Index: /tags/greenstone-3_02-distribution/gli/.java.policy
===================================================================
--- /tags/greenstone-3_02-distribution/gli/.java.policy	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/.java.policy	(revision 13928)
@@ -0,0 +1,12 @@
+
+grant {
+        permission java.io.FilePermission "<<ALL FILES>>", "read, write";
+        permission javax.sound.sampled.AudioPermission "record";
+        permission java.util.PropertyPermission "user.dir", "read";
+        permission java.util.PropertyPermission "user.home", "read";
+
+        permission java.lang.RuntimePermission "modifyThread";
+
+	permission java.util.prefs.syncInterval "write";
+	permission java.library.path "read, write";
+}
Index: /tags/greenstone-3_02-distribution/gli/CheckJavaVersion.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/CheckJavaVersion.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/CheckJavaVersion.java	(revision 13928)
@@ -0,0 +1,33 @@
+public class CheckJavaVersion
+{
+    static public void main(String[] args)
+    {
+	String java_version = System.getProperty("java.version");
+	System.out.println("Java version: " + java_version);
+
+	try {
+	    // Identify major version number
+	    int major_dot_position = java_version.indexOf(".");
+	    String java_version_major_string = java_version.substring(0, major_dot_position);
+	    int java_version_major = (new Integer(java_version_major_string)).intValue();
+
+	    // Identify minor version number
+	    int minor_dot_position = java_version.indexOf(".", major_dot_position + 1);
+	    String java_version_minor_string = java_version.substring(major_dot_position + 1, minor_dot_position);
+	    int java_version_minor = (new Integer(java_version_minor_string)).intValue();
+
+	    // Version of Java must be 1.4 or higher to run the GLI
+	    if (java_version_major > 1 || (java_version_major == 1 && java_version_minor >= 4)) {
+		// Valid
+		System.exit(2);
+	    }
+	    else {
+		// Invalid
+		System.exit(1);
+	    }
+	}
+	catch (Exception exception) {
+	    System.err.println("Exception: " + exception);
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/LICENSE.txt
===================================================================
--- /tags/greenstone-3_02-distribution/gli/LICENSE.txt	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/LICENSE.txt	(revision 13928)
@@ -0,0 +1,350 @@
+Copyright (c) 2003 Greenstone Digital Libraries, University of Waikato
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, and distribute copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the GPL and the following conditions (where not in conflict with the GPL):
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software, as will all other notices contained in the copyrights directory.
+
+THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDER (Greenstone Digital Libraries, University of Waikato), OR THEIR STAFF BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Greenstone Digital Libraries, University of Waikato shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the Greenstone Digital Libraries, University of Waikato. Distributed under GPL, as follows: 
+
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program 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 for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: /tags/greenstone-3_02-distribution/gli/READMEen.txt
===================================================================
--- /tags/greenstone-3_02-distribution/gli/READMEen.txt	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/READMEen.txt	(revision 13928)
@@ -0,0 +1,50 @@
+The Greenstone Librarian Interface
+----------------------------------
+
+This folder contains the Greenstone Librarian Interface (GLI), a tool to
+assist you with building digital libraries using Greenstone. The GLI gives
+you access to Greenstone's functionality from an easy-to-use, 'point and
+click' interface.
+
+To use the GLI, you need a suitable version of the Java Runtime Environment
+(version 1.4.0 or newer). If you don't already have one, you can download
+one from http://java.sun.com/j2se/downloads.html
+
+Note that the GLI is run in conjunction with Greenstone, and assumes that
+it is installed in a subdirectory of your Greenstone installation. If you
+have downloaded one of the Greenstone distributions, or installed from a 
+Greenstone CD-ROM, this will be the case.
+
+
+-- Running the GLI under Windows --
+
+To run the GLI under Windows, browse to the GLI folder in your Greenstone
+installation (using Windows Explorer), and double-click on the gli.bat
+file. This file will check that Greenstone, Perl, and the Java Runtime
+Environment are installed, then start the Greenstone Librarian Interface.
+
+
+-- Running the GLI under Unix --
+
+To run the GLI under Unix, change to the GLI directory in your Greenstone
+installation, then run the gli.sh script. This script will check that
+Greenstone, Perl, and the Java Runtime Environment are installed (make sure
+they are on your search path), then start the Greenstone Librarian
+Interface.
+
+
+Please report any problems you have running or using the Librarian
+Interface to greenstone@cs.waikato.ac.nz.
+
+
+-- Compiling the GLI --
+
+If you have downloaded the Greenstone source distribution, or you have
+obtained the GLI via CVS, you will have the source code (Java) of the
+Librarian Interface. Compiling it requires a suitable version of the Java
+Software Development Kit (version 1.4.0 or newer). You can download one
+from http://java.sun.com/j2se/downloads.html
+
+To compile this source code, run the makegli.bat (Windows) or makegli.sh
+(Unix) files. Once this has been done, you can run the GLI using the
+instructions above.
Index: /tags/greenstone-3_02-distribution/gli/READMEes.txt
===================================================================
--- /tags/greenstone-3_02-distribution/gli/READMEes.txt	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/READMEes.txt	(revision 13928)
@@ -0,0 +1,54 @@
+Interfaz de la Biblioteca Digital Greenstone
+--------------------------------------------
+
+Esta carpeta contiene la Interfaz de la Biblioteca Digital Greenstone (GLI
+por sus siglas en inglés), una herramienta que le ayudará a crear y 
+construir bibliotecas digitales por medio de Greenstone. La GLI le da 
+acceso a las funciones de Greenstone desde una interfaz fácil de usar con 
+la que solo tiene que apuntar y hacer click.
+
+Para poder usar la GLI usted necesita una versión adecuada del Ambiente 
+de Ejecución Java (versión 1.4.0 o posterior). Si aún no la tiene, podrá 
+bajarla desde http://java.sun.com/j2se/downloads.html.
+
+Recuerde que la GLI se ejecuta junto con los programas Greenstone, por 
+lo que se asume que estará instalada en un subdirectorio de Greenstone. 
+Si usted ya bajó de la Web una de las versiones de Greenstone o la instaló  
+desde un CD-ROM, entonces éste será el caso.
+
+
+-- Ejecución de la GLI bajo Windows --
+
+Para correr la GLI bajo Windows explore la carpeta GLI que se encuentra 
+en su instalación Greenstone (por medio de Windows Explorer) y haga 
+doble click en el archivo gli.bat. Este archivo verificará que Greenstone, 
+Perl y el Ambiente de Ejecución Java están instalados. A continuación 
+inicie la Interfaz de la Biblioteca Digital Greenstone.
+
+
+-- Ejecución de la GLI bajo UNIX --
+
+Para correr la GLI bajo UNIX cambie al directorio GLI que se encuentra en 
+su instalación Greenstone y ejecute el guión gli.sh. Este guión 
+verificará que Greenstone, Perl y el Ambiente de Ejecución Java están 
+instalados (asegúrese de que están en su ruta de búsqueda). A 
+continuación inicie la Interfaz de la Biblioteca Digital Greenstone.
+
+
+Por favor informe sobre cualquier problema que tenga al correr o usar la 
+Interfaz de la Biblioteca Digital a la siguiente dirección:
+greenstone@cs.waikato.ac.nz.
+
+
+-- Compilación de la GLI --
+
+Si usted ha bajado la versión con el código fuente de Greenstone o ha 
+obtenido la GLI por medio de CVS, entonces tendrá el código fuente 
+(Java) de la Interfaz de la Biblioteca Digital. Para compilarlo se necesita 
+una versión adecuada del Kit de Desarrollo de Software Java (versión 
+1.4.0 o posterior). Usted puede bajarlo desde 
+http://java.sun.com/j2se/downloads.html.
+
+Para compilar este código fuente ejecute los archivos makegli.bat 
+(Windows) o makegli.sh (UNIX). Una vez que haya hecho esto usted 
+podrá correr la GLI usando las instrucciones que aparecen arriba.
Index: /tags/greenstone-3_02-distribution/gli/READMEfr.txt
===================================================================
--- /tags/greenstone-3_02-distribution/gli/READMEfr.txt	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/READMEfr.txt	(revision 13928)
@@ -0,0 +1,49 @@
+L'Interface du Bibliothécaire de Greenstone (Greenstone Librarian Interface)
+----------------------------------------------------------------------------
+
+Ce dossier contient l'Interface du Bibliothécaire de Greenstone - Greenstone 
+Librarian Interface (GLI), un outil qui vous assiste pour la création de 
+bibliothèques numérique avec Greenstone. GLI vous donne accès aux fonctions 
+de Greenstone à partir d'une interce 'pointer et cliquer' facile à utiliser.
+
+Pour utiliser GLI, vous avez besoin d'une version adéquate de Java Runtime 
+Environment (version 1.4.0 ou supérieure). Si vous n'en disposez pas, vous 
+pouvez le télécharger de http://java.sun.com/j2se/downloads.html
+
+Notez que GLI est lancé avec Greenstone et suppose qu'il est installé dans 
+un sous-répertoire de votre installation Greenstone. Si vous avez téléchargé 
+une des distributions de Greenstone ou si vous avez installé à partir d'un 
+CD-ROM, ceci sera le cas.
+
+
+-- Exécuter GLI sous Windows --
+
+Pour exécuter GLI sous Windows, parcourez votre système de fichiers jusqu'au 
+répertoire GLI (en utilisant Windows Explorer), et double-cliquez sur le 
+fichier gli.bat. Ce fichier va vérifier que Greenstone, Perl et Java Runtime 
+Environment sont installés, puis démarre Greenstone Librarian Interface.
+
+
+-- Exécuter GLI sous Unix --
+
+Pour exécuter GLI sous Unix, aller au répertoire GLI de votre installation 
+Greenstone et lancer le script gli.sh. Ce script va vérifier que Greenstone, 
+Perl et Java Runtime Environment sont installés (assurez-vous qu'ils sont 
+dans le chemin de recherche), puis démarre Greenstone Librarian Interface.
+
+
+Prière de signaler tous problèmes rencontrés lors de l'exécution ou de 
+l'utilisation de Librarian Interface à greenstone@cs.waikato.ac.nz.
+
+
+-- Compiler GLI --
+
+Si vous avez téléchargé la distribution source de Greenstone, ou si vous 
+avez obtenu Greenstone à travers CVS, alors vous avez le code source (Java) 
+de Librarian Interface. Le compiler requière une version adéquate de Java 
+Software Development Kit (version 1.4.0 ou supérieure). Vous pouvez le 
+télécharger de http://java.sun.com/j2se/downloads.html
+
+Pour compiler ce code source, exécutez makegli.bat (Windows) ou makegli.sh 
+(Unix). Une fois ceci fait, vous pouvez exécuter GLI en suivant les 
+instructions ci-dessus.
Index: /tags/greenstone-3_02-distribution/gli/READMEru.txt-cp1251
===================================================================
--- /tags/greenstone-3_02-distribution/gli/READMEru.txt-cp1251	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/READMEru.txt-cp1251	(revision 13928)
@@ -0,0 +1,51 @@
+Èíòåðôåéñ áèáëèîòåêè Greenstone
+-------------------------------
+
+Ýòà ïàïêà ñîäåðæèò èíòåðôåéñ Áèáëèîòåêè Greenstone (GLI) - èíñòðóìåíò,
+êîòîðûé ïîìîæåò Âàì â ïîñòðîåíèè öèôðîâûõ áèáëèîòåê ñ èñïîëüçîâàíèåì
+Greenstone. GLI äàžò Âàì âîçìîæíîñòü ïîëó÷èòü äîñòóï ê ôóíêöèîíàëüíûì
+âîçìîæíîñòÿì Greenstone, óäîáíîìó â ðàáîòå èíòåðôåéñó - óêàæèòå è ùåëêíèòå.
+
+×òîáû èñïîëüçîâàòü GLI, Âàì íåîáõîäèìà ïîäõîäÿùàÿ âåðñèÿ Java Runtime
+Environment (JRE) (âåðñèÿ 1.4.0 èëè áîëåå íîâàÿ). Åñëè ó Âàñ îíà
+îòñóòñòâóåò, Âû ìîæåòå çàãðóçèòü åž ñ ñàéòà
+http://java.sun.com/j2se/downloads.html
+
+Îáðàòèòå âíèìàíèå, ÷òî GLI ñâÿçàíà ñ Greenstone. Ïðåäïîëàãàåòñÿ, ÷òî îíà
+óñòàíîâëåíà â ïîääèðåêòîðèè ïðè èíñòàëëÿöèè Greenstone. Åñëè Âû çàãðóçèëè
+îäèí èç äèñòðèáóòèâîâ Greenstone èëè óñòàíîâèëè åãî ñ CD-ROM, òî ýòî áóäåò
+èìåòü ìåñòî.
+
+
+-- Çàïóñê GLI ïîä Windows --
+
+×òîáû çàïóñòèòü GLI ïîä Windows, ðàññìîòðèòå ïàïêó GLI â èíñòàëëèðîâàííîì ó
+Âàñ Greenstone, èñïîëüçóÿ Windows Explorer, è ùåëêíèòå 2 ðàçà íà ôàéë
+gli.bat. Ýòîò ôàéë ïðîâåðèò, ÷òî Greenstone, Perl è JRE óñòàíîâëåíû, ïîñëå
+÷åãî çàïóñêàåòñÿ èíòåðôåéñ Greenstone.
+
+
+-- Çàïóñê GLI ïîä Unix --
+
+×òîáû çàïóñòèòü GLI ïîä Unix, èçìåíèòå äèðåêòîðèþ GLI â âàøåì
+èíñòàëëèðîâàííîì Greenstone, çàòåì îáðàòèòåñü ê ñêðèïòó gli.sh. Ýòîò ñêðèïò
+ïðîâåðèò, ÷òî Greenstone, Perl è JRE óñòàíîâëåíû (óäîñòîâåðüòåñü, ÷òî îíè
+íàõîäÿòñÿ íà óêàçàííîì âàìè ïóòè ïîèñêà), ïîñëå ÷åãî ñòàðòóåò èíòåðôåéñ
+Greenstone.
+
+
+Ïîæàëóéñòà, ñîîáùèòå î ëþáûõ ïðîáëåìàõ, êîòîðûå ó Âàñ èìåþòñÿ ïðè çàïóñêå
+èëè èñïîëüçîâàíèè èíòåðôåéñà GS, ê greenstone@cs.waikato.ac.nz.
+
+
+-- Êîìïèëèðîâàíèå GLI --
+
+Åñëè Âû çàãðóçèëè èñòî÷íèê äèñòðèáóòèâà Greenstone èëè æå ðàñïîëàãàåòå GLI
+îò CVS, òî Âû ðàñïîëàãàåòå èñõîäíîé ïðîãðàììîé Java èíòåðôåéñà áèáëèîòåêè.
+Êîìïèëÿöèÿ åž òðåáóåò ïîäõîäÿùåé âåðñèè ïðîãðàììíîãî îáåñïå÷åíèÿ Java
+Software Development Kit (âåðñèÿ 1.4.0 èëè áîëåå íîâàÿ). Âû ìîæåòå çàãðóçèòü
+åž ñ ñàéòà http://java.sun.com/j2se/downloads.html.
+
+×òîáû ñîáðàòü ýòó èñõîäíóþ ïðîãðàììó, âîéäèòå â ôàéëû makegli.bat (Windows)
+èëè makegli.sh (Unix). Êàê òîëüêî ýòî áóäåò ñäåëàíî, ìîæåòå çàïóñòèòü GLI,
+èñïîëüçóÿ äàííûå âûøå èíñòðóêöèè.
Index: /tags/greenstone-3_02-distribution/gli/READMEru.txt-koi8-r
===================================================================
--- /tags/greenstone-3_02-distribution/gli/READMEru.txt-koi8-r	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/READMEru.txt-koi8-r	(revision 13928)
@@ -0,0 +1,51 @@
+éÎÔÅÒÆÅÊÓ ÂÉÂÌÉÏÔÅËÉ Greenstone
+-------------------------------
+
+üÔÁ ÐÁÐËÁ ÓÏÄÅÒÖÉÔ ÉÎÔÅÒÆÅÊÓ âÉÂÌÉÏÔÅËÉ Greenstone (GLI) - ÉÎÓÔÒÕÍÅÎÔ,
+ËÏÔÏÒÙÊ ÐÏÍÏÖÅÔ ÷ÁÍ × ÐÏÓÔÒÏÅÎÉÉ ÃÉÆÒÏ×ÙÈ ÂÉÂÌÉÏÔÅË Ó ÉÓÐÏÌØÚÏ×ÁÎÉÅÍ
+Greenstone. GLI ÄÁ£Ô ÷ÁÍ ×ÏÚÍÏÖÎÏÓÔØ ÐÏÌÕÞÉÔØ ÄÏÓÔÕÐ Ë ÆÕÎËÃÉÏÎÁÌØÎÙÍ
+×ÏÚÍÏÖÎÏÓÔÑÍ Greenstone, ÕÄÏÂÎÏÍÕ × ÒÁÂÏÔÅ ÉÎÔÅÒÆÅÊÓÕ - ÕËÁÖÉÔÅ É ÝÅÌËÎÉÔÅ.
+
+þÔÏÂÙ ÉÓÐÏÌØÚÏ×ÁÔØ GLI, ÷ÁÍ ÎÅÏÂÈÏÄÉÍÁ ÐÏÄÈÏÄÑÝÁÑ ×ÅÒÓÉÑ Java Runtime
+Environment (JRE) (×ÅÒÓÉÑ 1.4.0 ÉÌÉ ÂÏÌÅÅ ÎÏ×ÁÑ). åÓÌÉ Õ ÷ÁÓ ÏÎÁ
+ÏÔÓÕÔÓÔ×ÕÅÔ, ÷Ù ÍÏÖÅÔÅ ÚÁÇÒÕÚÉÔØ Å£ Ó ÓÁÊÔÁ
+http://java.sun.com/j2se/downloads.html
+
+ïÂÒÁÔÉÔÅ ×ÎÉÍÁÎÉÅ, ÞÔÏ GLI Ó×ÑÚÁÎÁ Ó Greenstone. ðÒÅÄÐÏÌÁÇÁÅÔÓÑ, ÞÔÏ ÏÎÁ
+ÕÓÔÁÎÏ×ÌÅÎÁ × ÐÏÄÄÉÒÅËÔÏÒÉÉ ÐÒÉ ÉÎÓÔÁÌÌÑÃÉÉ Greenstone. åÓÌÉ ÷Ù ÚÁÇÒÕÚÉÌÉ
+ÏÄÉÎ ÉÚ ÄÉÓÔÒÉÂÕÔÉ×Ï× Greenstone ÉÌÉ ÕÓÔÁÎÏ×ÉÌÉ ÅÇÏ Ó CD-ROM, ÔÏ ÜÔÏ ÂÕÄÅÔ
+ÉÍÅÔØ ÍÅÓÔÏ.
+
+
+-- úÁÐÕÓË GLI ÐÏÄ Windows --
+
+þÔÏÂÙ ÚÁÐÕÓÔÉÔØ GLI ÐÏÄ Windows, ÒÁÓÓÍÏÔÒÉÔÅ ÐÁÐËÕ GLI × ÉÎÓÔÁÌÌÉÒÏ×ÁÎÎÏÍ Õ
+÷ÁÓ Greenstone, ÉÓÐÏÌØÚÕÑ Windows Explorer, É ÝÅÌËÎÉÔÅ 2 ÒÁÚÁ ÎÁ ÆÁÊÌ
+gli.bat. üÔÏÔ ÆÁÊÌ ÐÒÏ×ÅÒÉÔ, ÞÔÏ Greenstone, Perl É JRE ÕÓÔÁÎÏ×ÌÅÎÙ, ÐÏÓÌÅ
+ÞÅÇÏ ÚÁÐÕÓËÁÅÔÓÑ ÉÎÔÅÒÆÅÊÓ Greenstone.
+
+
+-- úÁÐÕÓË GLI ÐÏÄ Unix --
+
+þÔÏÂÙ ÚÁÐÕÓÔÉÔØ GLI ÐÏÄ Unix, ÉÚÍÅÎÉÔÅ ÄÉÒÅËÔÏÒÉÀ GLI × ×ÁÛÅÍ
+ÉÎÓÔÁÌÌÉÒÏ×ÁÎÎÏÍ Greenstone, ÚÁÔÅÍ ÏÂÒÁÔÉÔÅÓØ Ë ÓËÒÉÐÔÕ gli.sh. üÔÏÔ ÓËÒÉÐÔ
+ÐÒÏ×ÅÒÉÔ, ÞÔÏ Greenstone, Perl É JRE ÕÓÔÁÎÏ×ÌÅÎÙ (ÕÄÏÓÔÏ×ÅÒØÔÅÓØ, ÞÔÏ ÏÎÉ
+ÎÁÈÏÄÑÔÓÑ ÎÁ ÕËÁÚÁÎÎÏÍ ×ÁÍÉ ÐÕÔÉ ÐÏÉÓËÁ), ÐÏÓÌÅ ÞÅÇÏ ÓÔÁÒÔÕÅÔ ÉÎÔÅÒÆÅÊÓ
+Greenstone.
+
+
+ðÏÖÁÌÕÊÓÔÁ, ÓÏÏÂÝÉÔÅ Ï ÌÀÂÙÈ ÐÒÏÂÌÅÍÁÈ, ËÏÔÏÒÙÅ Õ ÷ÁÓ ÉÍÅÀÔÓÑ ÐÒÉ ÚÁÐÕÓËÅ
+ÉÌÉ ÉÓÐÏÌØÚÏ×ÁÎÉÉ ÉÎÔÅÒÆÅÊÓÁ GS, Ë greenstone@cs.waikato.ac.nz.
+
+
+-- ëÏÍÐÉÌÉÒÏ×ÁÎÉÅ GLI --
+
+åÓÌÉ ÷Ù ÚÁÇÒÕÚÉÌÉ ÉÓÔÏÞÎÉË ÄÉÓÔÒÉÂÕÔÉ×Á Greenstone ÉÌÉ ÖÅ ÒÁÓÐÏÌÁÇÁÅÔÅ GLI
+ÏÔ CVS, ÔÏ ÷Ù ÒÁÓÐÏÌÁÇÁÅÔÅ ÉÓÈÏÄÎÏÊ ÐÒÏÇÒÁÍÍÏÊ Java ÉÎÔÅÒÆÅÊÓÁ ÂÉÂÌÉÏÔÅËÉ.
+ëÏÍÐÉÌÑÃÉÑ Å£ ÔÒÅÂÕÅÔ ÐÏÄÈÏÄÑÝÅÊ ×ÅÒÓÉÉ ÐÒÏÇÒÁÍÍÎÏÇÏ ÏÂÅÓÐÅÞÅÎÉÑ Java
+Software Development Kit (×ÅÒÓÉÑ 1.4.0 ÉÌÉ ÂÏÌÅÅ ÎÏ×ÁÑ). ÷Ù ÍÏÖÅÔÅ ÚÁÇÒÕÚÉÔØ
+Å£ Ó ÓÁÊÔÁ http://java.sun.com/j2se/downloads.html.
+
+þÔÏÂÙ ÓÏÂÒÁÔØ ÜÔÕ ÉÓÈÏÄÎÕÀ ÐÒÏÇÒÁÍÍÕ, ×ÏÊÄÉÔÅ × ÆÁÊÌÙ makegli.bat (Windows)
+ÉÌÉ makegli.sh (Unix). ëÁË ÔÏÌØËÏ ÜÔÏ ÂÕÄÅÔ ÓÄÅÌÁÎÏ, ÍÏÖÅÔÅ ÚÁÐÕÓÔÉÔØ GLI,
+ÉÓÐÏÌØÚÕÑ ÄÁÎÎÙÅ ×ÙÛÅ ÉÎÓÔÒÕËÃÉÉ.
Index: /tags/greenstone-3_02-distribution/gli/classes/META-INF/MANIFEST.MF
===================================================================
--- /tags/greenstone-3_02-distribution/gli/classes/META-INF/MANIFEST.MF	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/classes/META-INF/MANIFEST.MF	(revision 13928)
@@ -0,0 +1,4 @@
+Manifest-Version: 1.0
+Created-By: 1.3.0 (Sun Microsystems Inc.)
+Main-Class: org.greenstone.gatherer.Gatherer
+Classpath: .\Gatherer.jar
Index: /tags/greenstone-3_02-distribution/gli/classes/dictionary.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gli/classes/dictionary.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/classes/dictionary.properties	(revision 13928)
@@ -0,0 +1,1038 @@
+#*******************
+#
+#***** AboutDialog *****
+AboutDialog.Acknowledgement:Acknowledgements for proprietary programs, packages or classes...
+AboutDialog.Date:(December 2006)
+AboutDialog.Item0:'Xerces Java 1' from The Apache Software Foundation (http://www.apache.org/)
+AboutDialog.Item2:'WGet' from Free Software Foundation, Inc. (http://www.gnu.org/software/wget/wget.html)
+AboutDialog.Item3:'qflib' from Quality First Software GmbH. (http://www.qfs.de/en/qflib/index.html)
+AboutDialog.Item4:'ExtensionFileFilter.class' by Bruno Dumon and contributors (http://pollo.sourceforge.net/)
+AboutDialog.Item5:'How to disable file renaming in file chooser' - vladi21 (http://www.experts-exchange.com/)
+AboutDialog.Item6:'Autoscrolling' - Java Swing by Robert Eckstein, Marc Loy & Dave Wood (http://www.oreilly.com/catalog/jswing/chapter/dnd.beta.pdf)
+AboutDialog.Item7:'Add ghosted drag images to your JTrees' - By Andrew J. Armstrong (http://www.javaworld.com/javaworld/javatips/jw-javatip114.html)
+AboutDialog.Item8:'Stop annoying java.prefs error when you don't have superuser access' - Thanks to Walter Schatz
+AboutDialog.Java_Req:Java is a trademark of Sun Microsystems Inc. The JRE is redistributed as per the Supplemental License Terms, found at http://java.sun.com/j2se/1.4.1/j2re-1_4_1_02-license.html
+AboutDialog.Java_Req_One:This product includes code licensed from RSA Security, Inc.
+AboutDialog.Java_Req_Two:Some portions licensed from IBM are available at http\://oss.software.ibm.com/icu4j/
+AboutDialog.Thanks:Also thanks to those who posted helpful java information on the web...
+AboutDialog.Title:About...
+AboutDialog.Title_One:Greenstone Librarian Interface
+AboutDialog.Title_Two:Greenstone Digital Library, University of Waikato
+AboutDialog.Copyright:Copyright (C) 2003 New Zealand Digital Library Project
+AboutDialog.Copyright_Two:Published under the GPL. See LICENSE.txt for details.
+#***********************
+#
+#***** Audit Table *****
+AuditTable.File:Filename
+#***********************
+#
+#***** Auto Filter *****
+Autofilter.AND:AND
+Autofilter.Ascending:Ascending
+Autofilter.Case_Sensitive:Match Case
+Autofilter.Custom_Filter:Advanced
+Autofilter.Descending:Descending
+Autofilter.Filter_By_Value:Simple
+Autofilter.Name:Column Name
+Autofilter.None:None
+Autofilter.Operator:Condition
+Autofilter.OR:OR
+Autofilter.Order:Ordering
+Autofilter.Order_Tooltip:Sort the matching items in this order
+Autofilter.Remove:Remove Filter
+Autofilter.Remove_Tooltip:Remove this filter from the table column
+Autofilter.Set:Set Filter
+Autofilter.Set_Tooltip:Add this filter to the table column
+Autofilter.Table_Header_Tooltip:Filter by {0}
+Autofilter.Title:Autofilter Metadata
+Autofilter.eqeq:equal to
+Autofilter.!eq:does not equal
+Autofilter.<:is less than
+Autofilter.<eq:is less than or equal to
+Autofilter.>:is greater than
+Autofilter.>eq:is greater than or equal to
+Autofilter.^:starts with
+Autofilter.!^:does not start with
+Autofilter.$:ends with
+Autofilter.!$:does not end with
+Autofilter.?:contains
+Autofilter.!?:does not contain
+#
+#     ********************************************************
+#     *************** Collection Design Module ***************
+#     ********************************************************
+#     * The dictionary  phrases  used in the creation of the *
+#     * Colection  Design  Module. Note that we  still  have *
+#     * access  to the format  arguments (argument  32+) for *
+#     * html formatting.                                     *
+#     ********************************************************
+CDM.ArgumentConfiguration.Bad_Integer:<html>The argument '{0}' requires an integer value,<br>but no integer can be parsed from {1}.</html>
+CDM.ArgumentConfiguration.Error_Title:Error In Arguments
+CDM.ArgumentConfiguration.Header:<HTML><STRONG><FONT FACE={FONT} COLOR=Black SIZE=5><CENTER>Please configure the arguments for {0}.</CENTER></FONT></STRONG></HTML>
+CDM.ArgumentConfiguration.No_Value:The argument '{0}' requires a value, but no value is specified.
+CDM.ArgumentConfiguration.Required_Argument:The argument '{0}' must be given a value.
+CDM.ArgumentConfiguration.Title:Configuring Arguments
+CDM.BuildTypeManager.Title:Select the Indexer
+CDM.BuildTypeManager.mg:MG
+CDM.BuildTypeManager.mg_Description:This is the original indexer used by Greenstone, developed mainly by Alistair Moffat and described in the classic book Managing Gigabytes. It does section level indexing, and searches can be boolean or ranked (not both at once). For each index specified in the collection, a separate physical index is created. For phrase searching, Greenstone does an "AND" search on all the terms, then scans the resulting hits to see if the phrase is present. It has been extensively tested on very large collections (many GB of text).
+CDM.BuildTypeManager.mgpp:MGPP
+CDM.BuildTypeManager.mgpp_Description:This new version of MG (MG plus plus) was developed by the New Zealand Digital Library Project. It does word level indexing, which allows fielded, phrase and proximity searching to be handled by the indexer. Boolean searches can be ranked. Only a single index is created for a Greenstone collection: document/section levels and text/metadata fields are all handled by the one index. For collections with many indexes, this results in a smaller collection size than using MG. For large collections, searching may be a bit slower due to the index being word level rather than section level.
+CDM.BuildTypeManager.lucene:Lucene
+CDM.BuildTypeManager.lucene_Description:Lucene was developed by the Apache Software Foundation. It handles field and proximity searching, but only at a single level (e.g. complete documents or individual sections, but not both). Therefore document and section indexes for a collection require two separate indexes. It provides a similar range of search functionality to MGPP with the addition of single-character wildcards, range searching and sorting of search results by metadata fields. It was added to Greenstone to facilitate incremental collection building, which MG and MGPP can't provide.
+CDM.BuildTypeManager.Current_Type:Indexer in use: {0}
+CDM.BuildTypeManager.Change:Change...
+CDM.BuildTypeManager.Change_Tooltip:Change the indexer used by this collection
+CDM.ClassifierManager.Add:Add Classifier...
+CDM.ClassifierManager.Add_Tooltip:Use the specified classifier with this collection
+CDM.ClassifierManager.Assigned:Assigned Classifiers
+CDM.ClassifierManager.Classifier:Select classifier to add:
+CDM.ClassifierManager.Classifier_Str:classifier
+CDM.ClassifierManager.Classifier_List_XML_Parse_Failed:Unable to get the list of classifiers using classinfo.pl -listall.
+CDM.ClassifierManager.Classifier_XML_Parse_Failed:Unable to determine the arguments for the {0}\nclassifier. Please ensure that the classifier in question\nprovides the -xml flag by running the classinfo.pl script\nsimilar to the description of the pluginfo.pl script in\nsection 2.1 of the Greenstone Developers Guide.
+CDM.ClassifierManager.Configure:Configure Classifier...
+CDM.ClassifierManager.Configure_Tooltip:Change the options of the selected classifier
+CDM.ClassifierManager.Remove:Remove Classifier
+CDM.ClassifierManager.Remove_Tooltip:Remove the selected classifier from the list
+CDM.FormatManager.Add:Add Format
+CDM.FormatManager.Add_Tooltip:Add the specified format command 
+CDM.FormatManager.AllFeatures:All Features
+CDM.FormatManager.AllParts:All Components
+CDM.FormatManager.Default:Reset to Default
+CDM.FormatManager.Default_Tooltip:Reset the selected format command to its default value 
+CDM.FormatManager.Editor:HTML Format String
+CDM.FormatManager.Editor_Tooltip:Enter or edit the format command
+CDM.FormatManager.Editor_Disabled_Tooltip:Click 'Add Format' to add this format command to your collection.
+CDM.FormatManager.Enabled:Enabled
+CDM.FormatManager.Feature:Choose Feature
+CDM.FormatManager.Feature_Tooltip:The feature to format
+CDM.FormatManager.Insert:Insert
+CDM.FormatManager.Insert_Tooltip:Insert the selected variable into the format command
+CDM.FormatManager.Default:Reset to Default
+CDM.FormatManager.Default_Tooltip:Reset the selected variable to its default
+CDM.FormatManager.Insert_Variable:Insert Variable...
+CDM.FormatManager.Part:Affected Component
+CDM.FormatManager.Part_Tooltip:The aspect of the selected feature to format
+CDM.FormatManager.Remove:Remove Format
+CDM.FormatManager.Remove_Tooltip:Remove the selected format command
+CDM.FormatManager.Variable_Tooltip:Insert one of the predefined variables into the selected format command
+CDM.General.Access:This collection should be publicly accessible
+CDM.General.Browser_Title:Select An Image
+CDM.General.Collection_Extra:Collection description:
+CDM.General.Collection_Extra_Tooltip:A description of the purpose and content of the collection
+CDM.General.Collection_Name:Collection title:
+CDM.General.Collection_Name_Tooltip:Name of the collection
+CDM.General.Email.Creator:Creator's email
+CDM.General.Email.Creator_Tooltip:E-mail address of the collection's creator
+CDM.General.Email.Maintainer:Maintainer's email
+CDM.General.Email.Maintainer_Tooltip:E-mail address of the collection's maintainer
+CDM.General.Icon_Collection:URL to 'about page' image:
+CDM.General.Icon_Collection_Tooltip:The URL of the image to display on the collection's about page
+CDM.General.Icon_Collection_Small:URL to 'home page' image:
+CDM.General.Icon_Collection_Small_Tooltip:The URL of the image to display on the library's home page for this collection
+CDM.General.Image_Copy_Failed:An error has occurred which prevents the image you selected being copied.\nPlease try manually copying the image:\n{0}\n to the images folder of your collection:\n{1}
+CDM.General.Image_Filter:Images (gifs, jpgs and pngs)
+CDM.GUI.Classifiers:Browsing Classifiers
+CDM.GUI.Formats:Format Features
+CDM.GUI.General:General
+CDM.GUI.Indexes:Search Indexes
+CDM.GUI.Macros:Collection Specific Macros
+CDM.GUI.Plugins:Document Plugins
+CDM.GUI.Root:CDM_ROOT
+CDM.GUI.SearchMetadata:Search
+CDM.GUI.Subcollections:Partition Indexes
+CDM.GUI.SuperCollection:Cross-Collection Search
+CDM.GUI.Translation:Translate Text
+CDM.HelpButton:Help for this screen
+CDM.HelpButton_Tooltip:Open up the GLI help for this screen
+CDM.IndexManager.Add_Index:Add Index
+CDM.IndexManager.Add_Index_Tooltip:Add the specified index
+CDM.IndexManager.Allfields_Index:Add combined searching over all assigned indexes (allfields)
+CDM.IndexManager.Default_Index_Indicator:[Default Index]
+CDM.IndexManager.Index_Exists:That index has already been assigned for this collection.
+CDM.IndexManager.Indexes:Assigned Indexes
+CDM.IndexManager.Level:Indexing level:
+CDM.IndexManager.Level_Tooltip:Textual unit on which index is based
+CDM.IndexManager.Add_All:Add All
+CDM.IndexManager.Add_All_Tooltip:Add a separate index for every source
+CDM.IndexManager.Edit_Index:Edit Index
+CDM.IndexManager.Edit_Index_Tooltip:Modify the selected index
+CDM.IndexManager.New_Index:New Index
+CDM.IndexManager.New_Index_Tooltip:Add a new index
+CDM.IndexManager.Remove_Index:Remove Index
+CDM.IndexManager.Remove_Index_Tooltip:Remove the selected index
+CDM.IndexManager.Replace_Index:Replace Index
+CDM.IndexManager.Replace_Index_Tooltip:Update the selected index
+CDM.IndexManager.Select_All:Select All
+CDM.IndexManager.Select_All_Tooltip:Select all index sources
+CDM.IndexManager.Select_None:Select None
+CDM.IndexManager.Select_None_Tooltip:Deselect all index sources
+CDM.IndexManager.Set_Default:Set Default Index
+CDM.IndexManager.Set_Default_Tooltip:Make the selected index the default index
+CDM.IndexManager.Source:Include in index:
+CDM.IndexManager.Source_Tooltip:The metadata elements to build the index on
+CDM.IndexManager.Text_Source:Full text
+CDM.IndexManager.Text_Source_Tooltip:Include the full text of the documents in the index
+CDM.IndexingManager.Accent_fold:Accent fold
+CDM.IndexingManager.Casefold:Casefold
+CDM.IndexingManager.Options:Indexing options:
+CDM.IndexingManager.Stem:Stem
+CDM.LanguageManager.Add_Tooltip:Add an index partition based on the specified languages
+CDM.LanguageManager.Assigned_Languages:Assigned Language Partitions
+CDM.LanguageManager.Default_Language:Default Language
+CDM.LanguageManager.LanguageMetadata:Language Metadata:
+CDM.LanguageManager.LanguageMetadata_Tooltip:The metadata element to use to determine a document's language
+CDM.LanguageManager.Remove_Tooltip:Remove the selected language partition from the list
+CDM.LanguageManager.Replace_Tooltip:Replace the selected partition with a new one based on the ticked languages
+CDM.LanguageManager.Selector:Languages to add: 
+CDM.LanguageManager.Selector_Tooltip:The languages to build an index partition on
+CDM.LanguageManager.Set_Default:Set Default
+CDM.LanguageManager.Set_Default_Tooltip:Make the selected language partition the default
+CDM.LevelManager.Document:document
+CDM.LevelManager.Section:section
+CDM.LevelManager.Paragraph:paragraph
+CDM.LevelManager.Level_Title:Indexing Levels
+CDM.LevelManager.Default:Default
+CDM.LevelManager.Default_Tooltip:Default level in reader's interface
+CDM.MacrosManager.Editor_Tooltip:Edit macros here
+CDM.Move.At_Bottom:Cannot move the {0} {1} lower as it is already at the bottom of the list.
+CDM.Move.At_Top:Cannot move the {0} {1} higher as it is already at the top of the list.
+CDM.Move.Cannot:Cannot move the plugin {0} any lower as RecPlug and ArcPlug must be at the bottom of the list.
+CDM.Move.Fixed:<html>RecPlug and ArcPlug are generally required to be last and so are fixed in place.<br>If you really must move them please hand edit the collect.cfg file.</html>
+CDM.Move.Move_Down:Move Down
+CDM.Move.Move_Down_Tooltip:Move the selected item down the list
+CDM.Move.Move_Up:Move Up
+CDM.Move.Move_Up_Tooltip:Move the selected item up the list
+CDM.Move.Title:Error - Cannot Move
+CDM.PlugInManager.Add:Add Plugin...
+CDM.PlugInManager.QuickAdd:Add Plugin
+CDM.PlugInManager.Add_Tooltip:Use the specified plugin with this collection
+CDM.PlugInManager.Assigned:Assigned Plugins
+CDM.PlugInManager.Configure:Configure Plugin...
+CDM.PlugInManager.Configure_Tooltip:Change the options of the selected plugin
+CDM.PlugInManager.Ignore:Don't Add Plugin
+CDM.PlugInManager.Ignore_Tooltip:Don't add any plugins to this collection.
+CDM.PlugInManager.PlugIn:Select plugin to add:
+CDM.PlugInManager.PlugIn_Tooltip:The plugins available for use in the collection
+CDM.PlugInManager.PlugIn_Str:plugin
+CDM.PlugInManager.PlugIn_XML_Parse_Failed:Unable to determine the arguments for the {0}\nplugin. Please ensure that the plugin in question provides\nthe -xml flag by running the pluginfo.pl script described\nin section 2.1 of the Greenstone Developers Guide.
+CDM.PluginManager.Plugin_List_XML_Parse_Failed:Unable to get the list of plugins using pluginfo.pl -listall.
+CDM.PluginManager.Plugin_Suggestion_Prompt:None of the plugins in this collection are expected to process the file "{0}". The following plugins can be used to process this file. You can add one to your collection now by selecting it and pressing the Add button. (Note that you can change the list of plugins at any time by going to "Document Plugins" on the Design Pane.)
+CDM.PlugInManager.Remove:Remove Plugin
+CDM.PlugInManager.Remove_Tooltip:Remove the selected plugin from the list
+CDM.PluginManager.SuggestedPluginListTitle:Suggested plugins for file
+CDM.SearchMetadataManager.Component:Item in search menu
+CDM.SearchMetadataManager.Component_Name:Display text
+CDM.SearchMetadataManager.Type_index:Index
+CDM.SearchMetadataManager.Type_level:Level
+CDM.SearchMetadataManager.Type_partition:Partition
+CDM.SearchMetadataManager.Type_language:Language Partition
+CDM.SubcollectionManager.Add:Add Filter
+CDM.SubcollectionManager.Add_Tooltip:Add the specified filter to the collection
+CDM.SubcollectionManager.Assigned:Defined Subcollection Filters
+CDM.SubcollectionManager.Exclude:Exclude
+CDM.SubcollectionManager.Flags:Flags to set when matching
+CDM.SubcollectionManager.Flags_Tooltip:Regular expression flags to use when matching (eg. "i" for case-insensitive matching)
+CDM.SubcollectionManager.Include:Include
+CDM.SubcollectionManager.Inclusive:What do we do with files that match?
+CDM.SubcollectionManager.Language_Controls:Assign Languages
+CDM.SubcollectionManager.Match:Regular expression to match with: 
+CDM.SubcollectionManager.Match_Tooltip:A regular expression defining the documents in the subcollection
+CDM.SubcollectionManager.Name:Subcollection filter name:
+CDM.SubcollectionManager.Name_Tooltip:The name of the new subcollection filter
+CDM.SubcollectionManager.Partitions_Disabled:This facility is currently disabled because you are operating in {0-Current Mode} mode. It can only be accessed in {1-Systems} and {2-Expert} modes. Use File->Preferences to alter the mode of operation.
+CDM.SubcollectionManager.Remove:Remove Filter
+CDM.SubcollectionManager.Remove_Tooltip:Remove the selected filter from the list
+CDM.SubcollectionManager.Replace:Replace Filter
+CDM.SubcollectionManager.Replace_Tooltip:Update the details of the selected filter
+CDM.SubcollectionManager.Source:Document attribute to match against:
+CDM.SubcollectionManager.Source_Tooltip:The document attribute to filter on
+CDM.SubcollectionManager.Subcollection_Controls:Define Filters
+CDM.SubcollectionManager.Subindex_Controls:Assign Partitions
+CDM.SubcollectionIndexManager.Add_Subindex:Add Partition
+CDM.SubcollectionIndexManager.Add_Subindex_Tooltip:Add the specified partition to this collection
+CDM.SubcollectionIndexManager.Default_Partition_Indicator:[Default Partition]
+CDM.SubcollectionIndexManager.Remove_Subindex:Remove Partition
+CDM.SubcollectionIndexManager.Remove_Subindex_Tooltip:Remove the selected partition from this collection
+CDM.SubcollectionIndexManager.Replace_Subindex:Replace Partition
+CDM.SubcollectionIndexManager.Replace_Subindex_Tooltip:Update the selected partition
+CDM.SubcollectionIndexManager.Set_Default_Subindex:Set Default
+CDM.SubcollectionIndexManager.Set_Default_Subindex_Tooltip:Make the selected partition the default
+CDM.SubcollectionIndexManager.Source:Build partition on:
+CDM.SubcollectionIndexManager.Source_Tooltip:The subcollection filters to build the partition on
+CDM.SubcollectionIndexManager.Subindexes:Assigned Subcollection Partitions
+CDM.TranslationManager.Add:Add Translation
+CDM.TranslationManager.Add_Tooltip:Add the specified translation to the collection
+CDM.TranslationManager.Affected_Features:Features
+CDM.TranslationManager.Assigned_Fragments:Assigned Translations
+CDM.TranslationManager.Default_Text:Initial Text Fragment
+CDM.TranslationManager.Fragment_Column:Text Fragment
+CDM.TranslationManager.Language:Language of translation:
+CDM.TranslationManager.Language_Column:Language
+CDM.TranslationManager.Language_Tooltip:The language being translated into
+CDM.TranslationManager.Remove:Remove Translation
+CDM.TranslationManager.Remove_Tooltip:Remove the selected translation from the collection
+CDM.TranslationManager.Replace:Replace Translation
+CDM.TranslationManager.Replace_Tooltip:Update the selected translation
+CDM.TranslationManager.Translation:Translated Text
+CDM.TranslationManager.Translation_Tooltip:Enter the translation of the string here
+#*******************
+#
+#***** Collection *****
+Collection.Collection:<HTML><STRONG><FONT FACE={FONT} COLOR=Black>Collection</FONT></STRONG></HTML>
+Collection.Delete_Tooltip:Delete selected files and folders
+Collection.Filter_Tooltip:Restrict the files shown in the file tree
+Collection.New_Folder_Tooltip:Create a new folder
+Collection.No_Collection:No Collection
+Collection.No_Collection_Loaded:No collection loaded
+Collection.Stop:Stop
+Collection.Stop_Tooltip:Stop copying files
+Collection.Workspace:<HTML><STRONG><FONT FACE={FONT} COLOR=Black>Workspace</FONT></STRONG></HTML>
+#**********************
+#
+#***** CollectionBuilt *****
+CollectionBuilt.Message:The collection has been built and is ready for previewing.
+CollectionBuilt.Title:Collection Creation Result
+#***************************
+#
+#***** CollectionManager *****
+CollectionManager.Build_Cancelled:Building the collection has been cancelled.
+CollectionManager.Cannot_Create_Collection:An error has occurred and the collection could not be created.
+CollectionManager.Cannot_Create_Collection_With_Reason:The collection could not be created because:\n{0-Error message}
+CollectionManager.Cannot_Delete_Index:This collection cannot be rebuilt because the old index files cannot be deleted.\nPlease make sure that Greenstone or some other program is not using these files,\n and try again.
+CollectionManager.Cannot_Delete_Index_Log:Old index files unable to be deleted so importing stopped.
+CollectionManager.Cannot_Open:The collection at:\n{0-Collection file path}\ncannot be opened.
+CollectionManager.Cannot_Open_With_Reason:The collection at:\n{0-Collection file path}\ncannot be opened because:\n{1-Error message}
+CollectionManager.Creating_Collection:Creating collection
+CollectionManager.Creating_Collection_Please_Wait:Creating collection, please wait...
+CollectionManager.Loading_Collection:Loading collection
+CollectionManager.Loading_Collection_Please_Wait:Loading collection, please wait...
+CollectionManager.Loading_Successful:Loaded collection {0}.
+CollectionManager.Missing_Config:This collection does not have a valid collect.cfg file 
+CollectionManager.Not_Col_File:'{0}' is not a Librarian Interface Collection File (.col)
+CollectionManager.No_Config_File:The collect.cfg file has not been created by mkcol.pl.
+CollectionManager.Preview_Ready_Failed:An error has occurred which will prevent the collection being previewed.
+CollectionManager.Preview_Ready_Title:Collection Preview State.
+CollectionManager.Build_Not_Moved:The building directory could not be moved.
+CollectionManager.Index_Not_Deleted:The index directory could not be deleted.
+CollectionManager.Install_Exception:Exception detected during collection install:\n{0}\nMost likely caused by Windows or Local Library holding locks on files.\nPlease make sure that none of the collection source files\nare opened in external applications, then rebuild.
+#*****************************
+#
+#***** CollectionPopupMenu *****
+CollectionPopupMenu.Delete:Delete
+CollectionPopupMenu.New_Dummy_Doc:New dummy document
+CollectionPopupMenu.New_Folder:New folder
+CollectionPopupMenu.Rename:Rename
+CollectionPopupMenu.Replace:Replace
+#*******************************
+#
+#***** CreatePane *****
+CreatePane.Build:Build Options
+CreatePane.Build_Tooltip:Options for the indexing and classification stage of collection formation
+CreatePane.Build_Collection:Build Collection
+CreatePane.Build_Collection_Tooltip:Start the collection formation process
+CreatePane.Build_Progress:Build Progress
+CreatePane.Cancel_Build:Cancel Build
+CreatePane.Cancel_Build_Tooltip:Stop the collection formation process
+CreatePane.Full_Build:Complete Rebuild
+CreatePane.Full_Build_Tooltip:Completely rebuild the collection from scratch
+CreatePane.Import:Import Options
+CreatePane.Import_Tooltip:Options for the file conversion and metadata assignment stage of collection formation
+CreatePane.Import_Progress:Import Progress
+CreatePane.Minimal_Build:Minimal Rebuild
+CreatePane.Minimal_Build_Tooltip:Faster, as only the parts of the collection building process that are necessary are performed
+CreatePane.Minimal_Build_Not_Required:Rebuilding is not required because you have not added any files to the collection,\nedited metadata, or changed options in the Design pane.\n(To force a rebuild, choose "Complete Rebuild" and press the "Build Collection" button.)
+CreatePane.Log:Message Log
+CreatePane.Log_Tooltip:View output from previous collection formation attempts
+CreatePane.Mode_All:all
+CreatePane.Options:Option Groups
+CreatePane.Options_Title:Collection Import & Build Options
+CreatePane.Preview_Collection:Preview Collection
+CreatePane.Preview_Collection_Tooltip:Preview the collection
+#**********************
+#
+#***** Dates *****
+Dates.Mon:Monday
+Dates.Tue:Tuesday
+Dates.Wed:Wednesday
+Dates.Thu:Thursday
+Dates.Fri:Friday
+Dates.Sat:Saturday
+Dates.Sun:Sunday
+Dates.Jan:January
+Dates.Feb:February
+Dates.Mar:March
+Dates.Apr:April
+Dates.May:May
+Dates.Jun:June
+Dates.Jul:July
+Dates.Aug:August
+Dates.Sep:September
+Dates.Oct:October
+Dates.Nov:November
+Dates.Dec:December
+#**********************
+#
+#***** Delete Collection Prompt *****
+DeleteCollectionPrompt.Collection_Details:Selected collection's details
+DeleteCollectionPrompt.Collection_List:Available collections
+DeleteCollectionPrompt.Confirm_Delete:Please tick the box to confirm collection deletion.
+DeleteCollectionPrompt.Delete:Delete
+DeleteCollectionPrompt.Delete_Tooltip:Delete the selected collection
+DeleteCollectionPrompt.Details:Creator - {0}\nMaintainer - {1}\nDescription\n{2}
+DeleteCollectionPrompt.Failed_Delete:Collection could not be completely deleted.
+DeleteCollectionPrompt.Failed_Title:Deletion Failed!
+DeleteCollectionPrompt.No_Collection:No collection selected.
+DeleteCollectionPrompt.Successful_Delete:Collection has been deleted.
+DeleteCollectionPrompt.Successful_Title:Deletion Complete!
+DeleteCollectionPrompt.Title:Collection Deletion
+#**********************
+#
+#***** DirectoryLevelMetadata *****
+DirectoryLevelMetadata.Message:You are about to assign 'folder level' metadata to the selected folder (or folders). Such metadata will be automatically inherited by all files and folders in this folder. Furthermore this metadata cannot be removed from specific children, only replaced. To continue with this action click 'OK'.
+DirectoryLevelMetadata.Title:About to add folder level metadata
+
+#*******************
+#
+#***** Download *****
+DOWNLOAD.MODE.Root:Download_Root
+DOWNLOAD.MODE.WebDownload:Web
+DOWNLOAD.MODE.OAIDownload:OAI
+DOWNLOAD.MODE.ZDownload:Z39.50
+DOWNLOAD.MODE.SRWDownload:SRW
+
+Download.ServerInformation:Server Information
+Download.ServerInformation_Tooltip:Download some information about the server, and check that a connection can be made
+
+#********************
+#
+#***** EnrichPane *****
+EnrichPane.AutoMessage:This element, {0}, belongs to the Greenstone metadata set. This set represents metadata that can usually be extracted automatically. To check what {0} metadata can be extracted create the collection using the 'Create' tab.
+EnrichPane.ExistingValues:Existing values for {0}
+EnrichPane.InheritedMetadataSelected:This piece of metadata is inherited from a folder above it, and cannot be edited. You can visit the actual folder containing the metadata by clicking on the folder icon at the start of the row.
+EnrichPane.InheritedMetadata_Tooltip:Click this icon to visit the folder where this inherited piece of metadata was assigned
+EnrichPane.ManageMetadataSets:Manage Metadata Sets...
+EnrichPane.ManageMetadataSets_Tooltip:Change the metadata sets used by the collection
+EnrichPane.No_File:No File Selected
+EnrichPane.No_Metadata:No Metadata Available
+EnrichPane.No_Metadata_Element:<HTML><STRONG><FONT FACE={FONT} COLOR=Black>No Metadata Element Selected</FONT></STRONG></HTML>
+EnrichPane.NotOneFileOnlyMetadataSelected:This piece of metadata does not apply only to this file, and cannot be edited.
+EnrichPane.Value_Field_Tooltip:Value to assign to the selected metadata element
+EnrichPane.Value_Field_Tooltip_Uneditable:Value assigned to the selected metadata element
+#***********************
+#
+#****** ExplodeMetadataPrompt *******
+ExplodeMetadataPrompt.Explode:Explode
+ExplodeMetadataPrompt.Explode_Tooltip:Explode the metadata file 
+ExplodeMetadataPrompt.Instructions:Exploding this metadata file will produce individual records with editable metadata. This is an irreversible process and the original metadata file will be removed from the collection.
+ExplodeMetadataPrompt.Failed_Title:Exploding Failed.
+ExplodeMetadataPrompt.Failed_Explode:The database {0} could not be exploded.
+ExplodeMetadataPrompt.NotExplodable:This file is not explodable.
+ExplodeMetadataPrompt.Successful_Explode:Database {0} successfully exploded.
+ExplodeMetadataPrompt.Successful_Title:Exploding Complete.
+ExplodeMetadataPrompt.Title:Explode Metadata Database
+ExplodeMetadataPrompt.Plugin:Plugin to use for exploding
+#***********************
+#
+#****** WriteCDImagePrompt *******
+WriteCDImagePrompt.CD_Name:CD/DVD name
+WriteCDImagePrompt.Export:Write CD/DVD image
+WriteCDImagePrompt.Export_Tooltip:Write the selected collections as a Windows CD/DVD Image
+WriteCDImagePrompt.Failed_Export:The collections ({0}) could not be exported.
+WriteCDImagePrompt.Failed_Title:Export Failed
+WriteCDImagePrompt.Install:CD/DVD will install some files when used (faster)
+WriteCDImagePrompt.Install_Tooltip:Produces a self-installing CD-ROM that installs the library server (and optionally all the collection files) onto the host machine. 
+WriteCDImagePrompt.NoInstall:CD/DVD will not install any files when used
+WriteCDImagePrompt.NoInstall_Tooltip:Produces a CD-ROM that runs the library directly from the CD-ROM without installing anything on the host machine.
+WriteCDImagePrompt.Instructions:Export one or more collections to a self-installing Windows CD/DVD image (although this works on any platform, the CD/DVD image that is created only runs under Windows).
+WriteCDImagePrompt.Progress_Label:Copying Files. This could take some time...
+WriteCDImagePrompt.Size_Label:Estimated size: 
+WriteCDImagePrompt.Successful_Export:The collections ({0}) have been exported.
+WriteCDImagePrompt.Successful_Title:Export Complete
+WriteCDImagePrompt.Title:Export Collection to CD/DVD
+#************************
+#
+#****** ExportAsPrompt *******
+ExportAsPrompt.Export_Name:Folder name
+ExportAsPrompt.Export_Name_Tooltip:The name of the folder in the Greenstone tmp directory where the exported collections will be saved.
+ExportAsPrompt.Export:Export collection(s)
+ExportAsPrompt.Export_Tooltip:Export the selected collections in the chosen file format into the designated directory
+ExportAsPrompt.Failed_ExportOne:The collection, {0}, could not be exported.
+ExportAsPrompt.Failed_ExportMany:The collections -- {0} -- could not be exported.
+ExportAsPrompt.Failed_Details:See {1} for details
+ExportAsPrompt.Failed_Title:Export Failed
+ExportAsPrompt.Instructions:Export one or more collections in the chosen format to into the stipulated directory
+ExportAsPrompt.Progress_Label:Exporting Files. This could take some time...
+ExportAsPrompt.Successful_ExportOne:The collection, {0}, has been exported.
+ExportAsPrompt.Successful_ExportMany:The collections -- {0} -- have been exported.
+ExportAsPrompt.Successful_Details:Files exported to: {1}
+ExportAsPrompt.Successful_Title:Export Complete
+ExportAsPrompt.Title:Export Collections
+ExportAsPrompt.SaveAs:Export to
+ExportAsPrompt.SaveAs_Tooltip:Select the format you want to export to
+ExportAsPrompt.Cancel:Cancel
+ExportAsPrompt.Cancel_Tooltip:Cancel the exporting process
+ExportAsPrompt.Browse:Browse
+ExportAsPrompt.Browse_Tooltip:Choose a xsl file
+ExportAsPrompt.ApplyXSL:Apply XSL file to {0}
+ExportAsPrompt.ApplyXSL_Tooltip:Use a xsl file to convert the exported files.
+ExportAsPrompt.MARCXMLGroup:Group marc records
+ExportAsPrompt.MARCXMLGroup_Tooltip:Export all marc records to a single file.
+ExportAsPrompt.MappingXML:Apply the mapping file
+ExportAsPrompt.MappingXML_Tooltip:Use a mapping file for converting the exported files.
+#
+#***** Inherited Metadata *****
+ExtractedMetadata.Message:The selected file or folder contains extracted metadata, but it is currently hidden. To view extracted metadata go to the "[F]ile" menu and select "[P]references". In the "General" properties sheet select "View Extracted Metadata", then click "[O]k".
+ExtractedMetadata.Title:This File/Folder Has Hidden Extracted Metadata
+#
+#***** FileActions *****
+FileActions.Calculating_Size:Calculating total size of selected files
+FileActions.Copying:Copying {0}
+FileActions.Could_Not_Delete:Could not delete {0}
+FileActions.Cyclic_Path:Cannot copy {0}: the destination folder is a subfolder of the source folder.
+FileActions.Deleting:Deleting {0}
+FileActions.Directories_Selected:{0} folders selected
+FileActions.Directory_Selected:1 folder selected
+FileActions.File_Already_Exists_No_Create:The file '{0}' already exists. 
+FileActions.File_And_Directories_Selected:1 file and {0} folders selected
+FileActions.File_And_Directory_Selected:1 file and 1 folder selected
+FileActions.File_Create_Error:The file {0} could not be created.
+FileActions.Folder_Create_Error:The folder {0} could not be created.
+FileActions.File_Exists:{0} already exists in the destination folder. Overwrite it?
+FileActions.File_Move_Error_Message:Could not move {0} to\n{1}.
+FileActions.File_Not_Deleted_Message:{0}\nThe file named above can not be deleted. \nPlease check that you don't have the file open\nin an external program, then try again. 
+FileActions.File_Not_Found_Message:{0}\nThe file named above can not be found. Once file view\nhas refreshed, please check the file still exists.
+FileActions.File_Selected:1 file selected
+FileActions.Files_And_Directory_Selected:{0} files and 1 folder selected
+FileActions.Files_Selected:{0} files selected
+FileActions.Folder_Already_Exists:The folder name '{0}' is already in use. Cannot create folder.
+FileActions.Insufficient_Space_Message:The file action has failed because of insufficient disk\nspace. For the file to copy successfully you require a\nfurther: {0}
+FileActions.Moving:Moving {0}
+FileActions.No_Activity:No action requested
+FileActions.Read_Not_Permitted_Message:Could not read {0}.
+FileActions.Read_Only:Files from the workspace are read only and cannot be deleted.
+FileActions.Replacing:Replacing {0}
+FileActions.Selected:{0} files and {1} folders selected
+FileActions.Unknown_File_Error_Message:Although no error message was reported during the file\naction, a final check has shown that the destination\ncopy is not the same as the source file. The reason\nfor this is unknown. Please check your media and update\nyour installed JVM.
+FileActions.Write_Not_Permitted_Message:The Librarian Interface does not have permission to write to\n{0}\nPlease check file permissions.
+FileActions.Write_Not_Permitted_Title:Error - Incorrect File Permissions
+FileActions.Yes_To_All:Yes to All
+#************************
+#
+#******* File Associations dialog **********
+FileAssociationDialog.Add:Add
+FileAssociationDialog.Add_Tooltip:Use this application to view files of this type
+FileAssociationDialog.Batch_File:Batch files
+FileAssociationDialog.Browse:Browse
+FileAssociationDialog.Browse_Tooltip:Choose the application to use from your filespace
+FileAssociationDialog.Browse_Tooltip_Mac:Browsing for your application is currently disabled for MacOS
+FileAssociationDialog.Browse_Title:Choose Application
+FileAssociationDialog.Close:Close
+FileAssociationDialog.Close_Tooltip:Close this dialog and return to the main window
+FileAssociationDialog.Command:Launch command:
+FileAssociationDialog.Command_File:Command files
+FileAssociationDialog.Command_Tooltip:Enter the command to launch the application to use
+FileAssociationDialog.Details:New File Association Details
+FileAssociationDialog.Executable_File:Executable files
+FileAssociationDialog.Extension:For files ending:
+FileAssociationDialog.Extension_Tooltip:The file extension of the files to view
+FileAssociationDialog.Instructions:Use this dialog to set what external programs are used to view a certain file-type, and what command is sent to launch this program.\nTo add a new file-type, type its extension in 'For files ending'. To add or modify a launch command, type the new command in 'Launch command' or click 'Browse' to search the file system for an appropriate program. Use the special string '%1' to indicate where the name of the file to be opened should be inserted, e.g. "C:\\Windows\\System\\MSPaint.exe %1". '%1' will be appended to the end of a command if not otherwise specified.\nMacOS users should always try the mac specific command "open [-a <application_name>] %1" first.
+FileAssociationDialog.Table.Command:Command
+FileAssociationDialog.Table.Extension:Extension
+FileAssociationDialog.Title:Edit File Associations
+FileAssociationDialog.Remove:Remove
+FileAssociationDialog.Remove_Tooltip:Remove the selected association from the existing associations
+FileAssociationDialog.Replace:Replace
+FileAssociationDialog.Replace_Tooltip:Replace the selected association with the new association details
+#*******************
+#
+#******Filter***************
+Filter.0:HTM & HTML
+Filter.1:XML
+Filter.2:Text Files
+Filter.3:Images
+Filter.All_Files:All Files
+Filter.Filter_Tree:Show Files
+Filter.Invalid_Pattern:<HTML><FONT FACE={FONT} COLOR=Black>The pattern you have entered for filtering files is invalid.<BR>Please try again using regular expression syntax and with<BR>* for the wildcard character.</FONT></HTML>
+#***********************
+#
+#***** GAuthenticator *****
+GAuthenticator.Password:Password:
+GAuthenticator.Password_Tooltip:Enter your password here
+GAuthenticator.Title:Password Required.
+GAuthenticator.Username:User Name:
+GAuthenticator.Username_Tooltip:Enter your username here
+#**************************
+#
+#***** General Messages *****
+# 0 - A String representing the name and method of the class in question.
+General.Apply:Apply
+General.Apply_Tooltip:Apply the current settings but do not exit the dialog
+General.Browse:Browse...
+General.Cancel:Cancel
+General.Cancel_Tooltip:Cancel the changes (will not undo any that have been applied already)
+General.Close:Close
+General.Close_Tooltip:Close this dialog box
+General.Edit:Edit Value
+General.Error:Error
+General.No:No
+General.NotSunJava:Java vendor: {0}\nNote that the Librarian Interface has been developed and tested with Java from Sun Microsystems. 
+General.OK:OK
+General.OK_Tooltip:Accept the current settings and exit the dialog
+General.Outstanding_Processes:<html>The Librarian Interface cannot close completely until all programs<br>started within The Librarian Interface have also exited.</html>
+General.Outstanding_Processes_Title:Waiting To Exit
+General.Pure_Cancel_Tooltip:Abort this action (no changes will be made)
+General.Review_Output:Please review output below:
+General.Redo:Redo
+General.Redo_Tooltip:Restore the last undo
+General.Undo:Undo
+General.Undo_Tooltip:Undo the last edit
+General.Usage:Usage: {0} <params>\nAll parameters are optional but the Librarian Interface may fail to work if -gsdl and -library aren't set.\n -gsdl <path>  : Force path to gsdl\n -library <path> : Path to cgi-bin\n -mozilla <path> : Enabled mozilla\n -mirror : Enable web-mirroring controls\n -laf [java|windows|motif|mac] : Look and feel\n -debug : Enable debug messages\n -no_load : Don't load previously open collection\n -load <path> : Load the specified collection
+General.View:View Value
+General.Warning:Warning
+General.Yes:Yes
+#****************************
+#
+#***** GShell *****
+GShell.BadArgument:Argument {0} is invalid.
+GShell.BadArgumentValue:Argument {0} has an invalid value.
+GShell.BadPluginOptions:The bad argument occurred in plugin {0}.
+GShell.BadClassifierOptions:The bad argument occurred in classifier {0}.
+GShell.Build.Auxilary:Creating auxiliary files and tidying up...
+GShell.Build.BuildBegun1:************** Build  Started **************
+GShell.Build.BuildCancelled:**************   Cancelled    **************
+GShell.Build.BuildComplete1:************** Build Finished **************
+GShell.Build.CompressText:Compressing text...
+GShell.Build.Index:Creating an index based on {0-index source and level}...
+GShell.Build.InfoDatabase:Creating information database...
+GShell.Build.Phind:Generating a Phind classifier. This may take some time...
+GShell.Command:Command
+GShell.Failure:Command failed.
+GShell.Import.FileNotProcessed:The file {0-target file path} was recognised but could not be processed by any plugin.
+GShell.Import.FileNotRecognised:The file {0-target file path} was not recognised by any plugin.
+GShell.Import.FileProcessing:The file {0-target file path} is being processed by {1-plugin name}.
+GShell.Import.FileProcessingError:The file {0-target file path} encountered an error during processing.
+GShell.Import.ImportBegun1:************** Import  Started **************
+GShell.Import.ImportComplete1:************** Import Finished **************
+GShell.Import.ImportComplete2:{0-number documents considered} documents were considered for processing:
+GShell.Import.ImportComplete2.1:1 document was considered for processing:
+GShell.Import.ImportComplete.Processed:{0-number processed} documents were processed and included in the collection. 
+GShell.Import.ImportComplete.Processed.1:1 document was processed and included in the collection. 
+GShell.Import.ImportComplete.Blocked:{0-number blocked} were prevented from being added by plugins (such as images in web pages).
+GShell.Import.ImportComplete.Blocked.1:1 was prevented from being added by plugins (such as images in web pages).
+GShell.Import.ImportComplete.Ignored:{0-number ignored} were unrecognised.
+GShell.Import.ImportComplete.Ignored.1:1 was unrecognised.
+GShell.Import.ImportComplete.Failed:{0-number failed} were rejected.
+GShell.Import.ImportComplete.Failed.1:1 was rejected.
+GShell.Import.ImportComplete3:\n
+GShell.Parsing_Metadata_Complete:Archived metadata extraction complete.
+GShell.Parsing_Metadata_Start:Extracting new metadata from archive files.
+GShell.Success:Command complete.
+#*********************
+#
+#***** GUI *****
+# Currently Enabled and Disabled display the same text but in different
+# colours. If necessary this can be changed.
+GUI.Create:Create
+GUI.Create_Tooltip:Build your collection using Greenstone
+GUI.Design:Design
+GUI.Design_Tooltip:Design the functionality of your collection
+GUI.Download:Download
+GUI.Download_Tooltip:Download resources from the internet for your collection
+GUI.Enrich:Enrich
+GUI.Enrich_Tooltip:Assign metadata to the files in your collection
+GUI.Format:Format
+GUI.Format_Tooltip:Design the appearance of your collection
+GUI.Gather:Gather
+GUI.Gather_Tooltip:Select the files to include in your collection
+#***************
+#
+#***** HELP *****
+Help.Contents:Contents
+Help.Title:Librarian Interface Help Pages
+#****************************
+#
+#***** Invalid Metadata ******
+InvalidMetadata.Message:This metadata element is restricted to the pre-defined set of values. Please choose one from the existing values.
+InvalidMetadata.Title:Invalid Metadata
+#***************************
+#
+#***** LegacyCollection
+LegacyCollection.Message:You are about to load a collection that has not been created by the GLI. Existing metadata will be imported into the Dublin Core metadata set. Original metadata files will be saved in a folder called import.bak.
+LegacyCollection.Title:Loading External Collection
+#***************************
+#
+#***** LockFileDialog *****
+LockFileDialog.Cancel_Tooltip:Do not steal control of the lock file (collection will not open)
+LockFileDialog.Date:Date
+LockFileDialog.Error:error
+LockFileDialog.Lockfile_Message_One:The presence of a lock file suggests this collection is already open.
+LockFileDialog.Lockfile_Message_Two:Do you wish to 'steal' control of this lock file?
+LockFileDialog.Machine:Where
+LockFileDialog.Name:Name
+LockFileDialog.OK_Tooltip:Steal control of the lock file
+LockFileDialog.Title:Lock File Detected
+LockFileDialog.User:Who
+#********************
+#
+#*****MappingPrompt **********
+MappingPrompt.File:Folder
+MappingPrompt.Map:Create Shortcut
+MappingPrompt.Name:Name
+MappingPrompt.Title:Set Folder Shortcut
+MappingPrompt.Unmap:Remove Shortcut
+#*******************
+#
+#***** Menu Options *****
+Menu.Collapse:Close Folder
+Menu.Edit:Edit
+Menu.Edit_Copy:Copy (ctrl-c)
+Menu.Edit_Cut:Cut (ctrl-x)
+Menu.Edit_Paste:Paste (ctrl-v)
+Menu.Expand:Open Folder
+Menu.Explode_Metadata_Database:Explode metadata database
+Menu.File:File
+Menu.File_Associations:File Associations...
+Menu.File_CDimage:Write CD/DVD image...
+Menu.File_Close:Close
+Menu.File_Delete:Delete...
+Menu.File_Exit:Exit
+Menu.File_ExportAs:Export...
+Menu.File_New:New...
+Menu.File_Open:Open...
+Menu.File_Options:Preferences...
+Menu.File_Save:Save
+Menu.Help:Help
+Menu.Help_About:About...
+Menu.Metadata_View:Assigned Metadata for the {0}
+Menu.Open_Externally:Open in external program
+#********************
+#
+#***** MetaAudit *****
+MetaAudit.Close:Close
+MetaAudit.Close_Tooltip:Close this dialog box
+MetaAudit.Title:All Metadata
+#*********************
+#
+#***** Metadata *****
+Metadata.Element:Element
+Metadata.Value:Value
+MetadataSet.Files:Metadata Set Files
+#**********************************
+#
+#***** MetadataSetDialog**********
+MetadataSetDialog.Title:Manage Metadata Sets
+MetadataSetDialog.Add_Title:Add Metadata Set
+MetadataSetDialog.Current_Sets:Assigned Metadata Sets
+MetadataSetDialog.Available_Sets:Available Metadata Sets
+MetadataSetDialog.Add:Add...
+MetadataSetDialog.Add_Tooltip:Add a new metadata set to the collection
+MetadataSetDialog.New_Set:New...
+MetadataSetDialog.New_Set_Tooltip:Create a new metadata set
+MetadataSetDialog.Add_Set:Add
+MetadataSetDialog.Add_Set_Tooltip:Add the selected metadata set to the collection
+MetadataSetDialog.Browse:Browse...
+MetadataSetDialog.Browse_Tooltip:Add a new metadata set to the collection
+MetadataSetDialog.Edit:Edit...
+MetadataSetDialog.Edit_Tooltip:Edit the selected metadata set
+MetadataSetDialog.Remove:Remove
+MetadataSetDialog.Remove_Tooltip:Remove the selected metadata set from the collection
+MetadataSetDialog.Elements:Elements in selected Metadata Set
+
+#****************************************
+#
+#***** MetadataSetNamespaceClash warning***
+MetadataSetNamespaceClash.Title:Metadata Set Namespace Clash
+MetadataSetNamespaceClash.Message:The metadata set you have chosen to add ({0}) has the same namespace as one already in the collection ({1}). If you add this new set, the old one will be deleted and the new one added in its place. Any assigned metadata values will be transferred to the new set if it contains the appropriate elements.
+#*********************************************
+#
+#******** MetadataImportMappingPrompt *********
+MIMP.Add:Add
+MIMP.Add_Tooltip:Add the metadata element to the selected set
+MIMP.Ignore:Ignore
+MIMP.Ignore_Tooltip:Ignore this metadata element
+MIMP.Instructions:The metadata element {0} cannot be automatically imported into the collection. Select a metadata set and either:\n(1) press 'Add' to add the metadata to that set (only if there is not already {0} metadata in the set), or\n(2) choose an element and press 'Merge' to import {0} metadata to this element, or\n(3) ignore this metadata element.
+MIMP.Merge:Merge
+MIMP.Merge_Tooltip:Map the metadata element to the specified element in the selected set
+MIMP.Source_Element:Source metadata element:
+MIMP.Target_Element:Target metadata element:
+MIMP.Target_Set:Target metadata set:
+MIMP.Title:Merging Action Required.
+#*****************************
+#
+#***** Mirroring *****
+Mirroring.ClearCache:Clear Cache
+Mirroring.ClearCache_Tooltip:Delete all downloaded files
+Mirroring.Download:Download
+Mirroring.Download_Tooltip:Start a new download job
+Mirroring.DownloadJob.Close:Close
+Mirroring.DownloadJob.Close_Tooltip:Remove this job from the list, stopping it if it is currently running
+Mirroring.DownloadJob.Downloading:Downloading {0}
+Mirroring.DownloadJob.Download_Complete:Download complete
+Mirroring.DownloadJob.Download_Stopped:Download halted
+Mirroring.DownloadJob.Download_Progress:Downloading in progress
+Mirroring.DownloadJob.Log:View Log
+Mirroring.DownloadJob.Log_Tooltip:View details about this download
+Mirroring.DownloadJob.Log_Title:Download Log
+Mirroring.DownloadJob.Pause:Pause
+Mirroring.DownloadJob.Pause_Tooltip:Pause this download
+Mirroring.DownloadJob.Resume:Resume
+Mirroring.DownloadJob.Resume_Tooltip:Resume this download
+Mirroring.DownloadJob.Status:Downloaded {0} of {1} files ({2} warnings, {3} errors)
+Mirroring.DownloadJob.Waiting:Waiting to start
+Mirroring.DownloadJob.Waiting_User:Waiting for user action
+Mirroring.Invalid_URL:The URL entered is not valid. Please correct.
+Mirroring.Invalid_URL_Title:Invalid URL
+Mirroring.Preferences:Preferences...
+Mirroring.Preferences_Tooltip:Enable proxy and/or edit proxy settings
+#*********************
+#
+#***** Missing EXEC *****
+MissingEXEC.Message:Warning! You will not be able to view your new collections within the Librarian Interface unless you specify the path to the Greenstone Library Webserver. You can enter this now in the text field below, or later by going to Preferences and choosing the Connection tab. Remember that a valid url must start with the protocol "http://", and will probably end with the executable name ("gsdl" for Greenstone local library server, "library" for other web servers).
+MissingEXEC.Title:Missing Greenstone Library Address
+#***** Missing EXEC_GS3 *****
+MissingEXEC_GS3.Message:Warning! You will not be able to view your new collections within the Librarian Interface unless you specify the path to the Greenstone context in the locally running Tomcat Webserver. You can enter this now in the text field below, or later by going to Preferences and choosing the Connection tab. Remember that a valid url must start with the protocol "http://". The default address is http://localhost:8080/greenstone3.
+MissingEXEC_GS3.Title:Missing Greenstone 3 Library Address
+#***** Missing GLIServer *****
+MissingGLIServer.Message:Warning! You will not be able to work with collections within the Librarian Interface unless you specify the address of the remote Greenstone "gliserver" script. You can enter this now in the text field below, or later by going to Preferences and choosing the Connection tab. Remember that a valid URL must start with the protocol "http://" and end with "gliserver".
+MissingGLIServer.Title:Missing GLIServer Address
+#***** Missing GSDL *****
+MissingGSDL.Message:Warning! You will not be able to access all of the Librarian Interface's features without a local copy of Greenstone Digital Library also installed. If you believe you are receiving this message in error please check your installation, and the paths specified in Librarian Interface batch or script file.
+MissingGSDL.Title:Missing Greenstone Path
+#***** Missing PERL *****
+MissingPERL.Message:Warning! You will not be able to create new collections, nor build existing ones, without PERL installed, and the Librarian Interface was unable to find PERL on your system. If you believe you are receiving this message in error please check your installation, and the paths specified in Librarian Interface batch or script file.
+MissingPERL.Title:Missing PERL Path
+#******* MissingImageMagick ********
+MissingImageMagick.Message:Warning! The Librarian Interface failed to locate an appropriate version of ImageMagick, and consequently ImagePlug will not work. Please install ImageMagick if you wish to build image collections.
+MissingImageMagick.Title:Missing ImageMagick
+#*****************************
+#
+#***** New Session *****
+NewCollectionPrompt.Base_Collection:Base this collection on:
+NewCollectionPrompt.Base_Collection_Tooltip:Select an existing collection to base the new collection on
+NewCollectionPrompt.Collection_Description:Description of content:
+NewCollectionPrompt.Collection_Name:Collection folder:
+NewCollectionPrompt.Collection_Scope_Personal:This is a personal collection
+NewCollectionPrompt.Collection_Scope_Shared:This is not a personal collection
+NewCollectionPrompt.Error:Error in new collection.
+NewCollectionPrompt.Instructions:To create a new collection fill out the fields below.
+NewCollectionPrompt.NewCollection:-- New Collection --
+NewCollectionPrompt.Title:Create a new Collection.
+NewCollectionPrompt.Title_Clash:The title you have chosen for your collection is already in use. Continue?
+NewCollectionPrompt.Title_Error:The title field must be filled out. Please correct.
+#***** New Folder OrFilePrompt *****
+NewFolderOrFilePrompt.Default_File_Name:dummy
+NewFolderOrFilePrompt.Default_Folder_Name:new folder
+NewFolderOrFilePrompt.Destination_Name:Destination Folder
+NewFolderOrFilePrompt.File_Name:File Name
+NewFolderOrFilePrompt.File_Name_Tooltip:Enter a name for the new file
+NewFolderOrFilePrompt.Folder_Name:Folder Name
+NewFolderOrFilePrompt.Folder_Name_Tooltip:Enter a name for the new folder
+NewFolderOrFilePrompt.Title_Folder:Create a new folder
+NewFolderOrFilePrompt.Title_File:Create a new dummy document
+#**********************
+#
+#******* OldWGET *******
+NoPluginExpectedToProcessFile.Message:None of Greenstone's plugins are expected to process the file "{0}". Check that the file has the correct extension. If it is correct then you may have to use UnknownPlug to process this file.
+NoPluginExpectedToProcessFile.Title:No plugin expected to process file
+#***********************
+#
+#***** OpenCollectionDialog *****
+OpenCollectionDialog.Available_Collections:Available Collections
+OpenCollectionDialog.Description:Collection Description
+OpenCollectionDialog.Open:Open
+OpenCollectionDialog.Open_Tooltip:Load the selected collection into the Librarian Interface
+OpenCollectionDialog.Title:Open Greenstone Collection
+#**********************
+#
+#***** Options Pane inside CreatePane *****
+OptionsPane.Cancelled: - cancelled
+OptionsPane.LogHistory:Log history
+OptionsPane.Successful: - successful
+OptionsPane.Unknown: - unknown
+OptionsPane.Unsuccessful: - unsuccessful
+#*******************
+#
+#***** Preferences *****
+Preferences:Preferences
+Preferences.Connection:Connection
+Preferences.Connection_Tooltip:Set the URL to the greenstone library and configure a proxy connection if appropriate
+Preferences.Connection.GLIServer_URL:Greenstone gliserver URL:
+Preferences.Connection.GLIServer_URL_Tooltip:The URL of the Greenstone "gliserver" CGI script
+Preferences.Connection.Library_Path:Library Path:
+Preferences.Connection.Library_Path_GS3:Greenstone Web Path:
+Preferences.Connection.Library_Path_Tooltip:The URL of the Greenstone web-server
+Preferences.Connection.Library_Path_Tooltip_GS3:The URL of the Greenstone web-server
+Preferences.Connection.ProgramCommand:Preview Command:
+Preferences.Connection.ProgramCommand_Tooltip:The launch command for the program used to view the collection preview. Remember to use %1 as the placeholder for the collection address, and to use speechmarks where necessary.
+Preferences.Connection.Proxy_Host:Proxy Host:
+Preferences.Connection.Proxy_Host_Tooltip:The address of your proxy server
+Preferences.Connection.Proxy_Port:Proxy Port:
+Preferences.Connection.Proxy_Port_Tooltip:The port number of your proxy server
+Preferences.Connection.Servlet:Servlet:
+Preferences.Connection.Servlet_Tooltip:The servlet to use to view your site
+Preferences.Connection.Servlet_Tooltip2:There is no servlet specified for this site, you can still build collections, but you wont be able to view them
+Preferences.Connection.Site:Site:
+Preferences.Connection.Site_Tooltip:The site you want to work in
+Preferences.Connection.Use_Proxy:Use proxy connection?
+Preferences.General:General
+Preferences.General_Tooltip:Set some general preferences
+Preferences.General.Email:User's Email:
+Preferences.General.Email_Tooltip:The email address automatically used for any collection created with the GLI
+Preferences.General.Font:Font:
+Preferences.General.Font_Tooltip:The font used for the GLI interface.
+Preferences.General.Interface_Language:Interface Language:
+Preferences.General.Interface_Language_Tooltip:Select the language you wish the interface and its controls to be displayed in. 
+Preferences.General.Restart_Required:GLI should now be restarted in order to complete loading a new interface language.
+Preferences.General.Show_File_Size:Show file sizes
+Preferences.General.Show_File_Size_Tooltip:Show file sizes next to entries in the Workspace and Collection file trees.
+Preferences.General.View_Extracted_Metadata:View Extracted Metadata
+Preferences.General.View_Extracted_Metadata_Tooltip:Display metadata extracted by the greenstone plugins in the metadata list in the Enrich view.
+Preferences.Mode:Mode
+Preferences.Mode_Tooltip:Click on an entry to select a suitable level of operation
+Preferences.Mode.Assistant:Library Assistant
+Preferences.Mode.Assistant_Description:Use this setting to gain access to the basic features of the Greenstone Librarian Interface: adding documents and metadata to collections, creating new collections whose structure mirrors existing ones, and building collections.
+Preferences.Mode.Librarian:Librarian
+Preferences.Mode.Librarian_Description:This setting gives normal use of the Greenstone Librarian Interface: creating and designing new collections, adding documents and metadata to collections, designing new collections, and building collections.
+Preferences.Mode.Systems:Library Systems Specialist
+Preferences.Mode.Systems_Description: This setting enables full use of the Greenstone Librarian Interface. To take advantage of all the features available, you will need to be able to formulate regular expressions.
+Preferences.Mode.Expert:Expert
+Preferences.Mode.Expert_Description:This setting enables expert use of the Greenstone Librarian Interface. It is recommended for users who are experienced with Greenstone, and are able to perform troubleshooting tasks that involve interpreting debugging output from PERL scripts. All features of the Greenstone Librarian Interface are enabled.
+Preferences.Warnings:Warnings
+Preferences.Warnings_Tooltip:Enable or disable various warning dialogs
+Preferences.Workflow:Workflow
+Preferences.Workflow_Tooltip:Design the interface workflow: set which views should be enabled
+Preferences.Workflow.Predefined.Label:Predefined Workflows
+Preferences.Workflow.Title:Check box to enable view
+#**********************
+#
+#**** PreviewCommandDialog *******
+PreviewCommandDialog.Instructions:Enter the command for opening the program to view collection preview. Remember to use %1 as the placeholder for the collection address, and to use speechmarks where necessary.
+PreviewCommandDialog.Title:Preview Command
+
+ShowPreviousCollection.Title:Preview the collection previously built
+ShowPreviousCollection.Message:An error has occurred and the collection could not be created.You are previewing the collection that was built previously. 
+#**********************
+#
+#***** Remote Greenstone Server *****
+RemoteGreenstoneServer.Authentication_Message:Please enter your Greenstone username and password:
+RemoteGreenstoneServer.Error:An error has occurred on the remote Greenstone server while performing this operation:\n{0-Error message}
+RemoteGreenstoneServer.Error_Title:Remote Greenstone Server Error
+RemoteGreenstoneServer.Progress:Remote Greenstone Server Progress: 
+RemoteGreenstoneServer.Steal_Lock_Message:This collection is currently locked by user '{0-User name}'.\nDo you want to steal control of this lock file (not recommended, as work may be lost)?
+#**********************
+#
+#***** Rename Prompt *****
+RenamePrompt.Name:Name:
+RenamePrompt.Title:Rename file/folder
+#**********************
+#
+#***** Replace Prompt *****
+ReplacePrompt.Title:Replace file with ...
+#**********************
+#
+#***** Save Collection Box *****
+SaveCollectionBox.File_Name:File Name:
+SaveCollectionBox.Files_Of_Type:Files of Type:
+SaveCollectionBox.Look_In:Look In:
+#**********************
+#
+#***** Save Progress Box *******
+SaveProgressDialog.Title:Saving Collection
+#*******************************
+#
+Server.QuitManual:The Librarian Interface was unable to close the local\nlibrary server automatically. Please exit the server\nmanually by clicking on the cross icon in its top\nright-hand corner, then click OK on this dialog.
+Server.QuitTimeOut:The greenstone local library has not responded to the\nautomatic close command for sixty seconds. Do you\nwish to wait for another minute?
+#
+#***** Sources *****
+Source.General:General
+#**********************
+#
+#***** Trees *****
+Tree.DownloadedFiles:Downloaded Files
+Tree.Files:files
+Tree.Home:Home Folder ({0})
+Tree.Root:Local Filespace
+Tree.World:Documents in Greenstone Collections
+#***********************
+#
+#***** Warning Dialog *****
+WarningDialog.Dont_Show_Again:Do not show this warning again
+WarningDialog.Dont_Show_Again_Message:Do not show this message again
+WarningDialog.Invalid_Value:The value you have entered in the value field\nis not valid for the specified property.
+WarningDialog.Value:Enter value:
+#
+#****** WGet *****
+WGet.Prompt:WGet Mirroring Client
+#
+#****** Workflows *****
+Workflow.AllPanels:All panels
+Workflow.LocalSourceCollectionBuilding:Local source collection building
+Workflow.DocumentEnriching:Document enriching
+
+
+#********GEMS******
+
+GEMS.Title:Greenstone Editor for Metadata Sets
+GEMS.OpenMetadataSetPrompt.Title:Open Metadata Set
+GEMS.OpenMetadataSetPrompt.Open_Tooltip:Open the selected metadata set
+GEMS.Set_Description:Metadata set description
+GEMS.OpenMetadataSetPrompt.Open:Open
+GEMS.OpenMetadataSetPrompt.Available_Sets:Available metadata sets
+GEMS.DeleteMetadataSetPrompt.Title:Delete Metadata Set
+GEMS.DeleteMetadataSetPrompt.Delete_Tooltip:Delete the selected metadata set
+GEMS.DeleteMetadataSetPrompt.Delete:Delete
+GEMS.DeleteMetadataSetPrompt.Available_Sets:Available metadata sets
+GEMS.DeleteMetadataSetPrompt.Confirm_Delete:Please tick the box to confirm metadata set deletion.
+GEMS.DeleteMetadataSetPrompt.No_Set:No metadata set selected
+GEMS.Confirm_Removal:Are you sure you wish to remove this {0}?
+GEMS.Confirm_Removal_Title:Confirm Removal
+GEMS.Attribute:Attribute
+GEMS.Popup.AddElement:Add Element
+GEMS.Popup.DeleteElement:Delete Element
+GEMS.Popup.AddSubElement:Add Subelement
+GEMS.Popup.DeleteSubElement:Delete Subelement
+GEMS.NewMetadataSetPrompt.Title:New Metadata Set
+GEMS.NewMetadataSetPrompt.Instructions:To create a new metadata set fill out the fields below:
+GEMS.NewMetadataSetPrompt.Base_MetadataSet:Base this metadata set on:
+GEMS.NewMetadataSetPrompt.Metadata_Title:Metadata set title:
+GEMS.NewMetadataSetPrompt.Metadata_Namespace:Metadata set namespace:
+GEMS.NewMetadataSetPrompt.New_Metadata:-- New Metadata Set --
+GEMS.NewMetadataSetPrompt.Title_Error_Message:A new metadata set must have a Title
+GEMS.NewMetadataSetPrompt.Title_Error:No Title Specified
+GEMS.NewMetadataSetPrompt.Namespace_Error_Message:A new metadata set must have a namespace
+GEMS.NewMetadataSetPrompt.Namespace_Error:No Namespace Specified
+GEMS.SelectedLanguage:Add attributes for language:
+GEMS.Language:--Choose Language--
+GEMS.LanguageDependent:Language dependent attributes
+GEMS.Attribute_Table:Attributes
+GEMS.Attribute_Deletion_Error:Attribute Deletion Error
+GEMS.Attribute_Deletion_Error_Message:This attribute is required and cannot be deleted
+GEMS.Add_Lang_Depend_Attr_Error:Attribute Addition Error
+GEMS.Add_Lang_Depend_Attr_Error_Message:No "language-dependent" attribute is provided, please add this attribute.
+GEMS.Attribute_Edition_Error:Attribute Edition Error
+GEMS.Attribute_Edition_Error_Message:This attribute is required and cannot be empty
+GEMS.Confirm_Save:This metadata set has been changed, would you like to save it?
+GEMS.Confirm_Save_Title:Save Metadata Set
+GEMS.Confirm_DeleteElement:Are you sure you wish to delete element {0}?
+GEMS.Confirm_DeleteElement_Title:Delete Element
+GEMS.File_Deletion_Error_Message:This file cannot be deleted
+GEMS.File_Deletion_Error:File Deletion Error
+GEMS.Namespace_Conflict_Message:Warning: this namespace has been used by another metadata set. Continue?
+GEMS.Namespace_Conflict:Namespace Conflict
+GEMS.Move_Up:Move Up
+GEMS.Move_Down:Move Down
+GEMS.Cannot_Undo:(this action cannot be undone)
+
+GEMS.AttributeTable.Name:Name
+GEMS.AttributeTable.Language:Language
+GEMS.AttributeTable.Value:Value
+GEMS.NewMetadataElementNamePrompt.Title:New Element
+GEMS.NewMetadataElementNamePrompt.Name:Please enter a name for the new element
+GEMS.NewMetadataElementNamePrompt.SubTitle:New Subelement
+GEMS.NewMetadataElementNamePrompt.SubName:Please enter a name for the new subelement
+GEMS.NewMetadataElementNamePrompt.Name_Error_Message:An element with this name already exists.
+GEMS.NewMetadataElementNamePrompt.Name_Error:Element Name Error
+GEMS.NewMetadataElementNamePrompt.EmptyName_Error_Message:A new element must have a name.
+
+
+GEMS.No_Set_Loaded:No metadata set is loaded. Please use File->New to create a new set, or File->Open to open an existing set.
Index: /tags/greenstone-3_02-distribution/gli/classes/dictionary_ar.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gli/classes/dictionary_ar.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/classes/dictionary_ar.properties	(revision 13928)
@@ -0,0 +1,3032 @@
+#*******************
+#
+#***** AboutDialog *****
+AboutDialog.Acknowledgement:ØŽÙØ± Ù Ø¹Ø±ÙØ§Ù...
+AboutDialog.Date:(Ø¯ÙØ³Ù
+ØšØ± 2006)
+AboutDialog.Item0:'Xerces Java 1' from The Apache Software Foundation (http://www.apache.org/)
+AboutDialog.Item2:'WGet' from Free Software Foundation, Inc. (http://www.gnu.org/software/wget/wget.html)
+AboutDialog.Item3:'qflib' from Quality First Software GmbH. (http://www.qfs.de/en/qflib/index.html)
+AboutDialog.Item4:'ExtensionFileFilter.class' by Bruno Dumon and contributors (http://pollo.sourceforge.net/)
+AboutDialog.Item5:'How to disable file renaming in file chooser' - vladi21 (http://www.experts-exchange.com/)
+AboutDialog.Item6:'Autoscrolling' - Java Swing by Robert Eckstein, Marc Loy & Dave Wood (http://www.oreilly.com/catalog/jswing/chapter/dnd.beta.pdf)
+AboutDialog.Item7:'Add ghosted drag images to your JTrees' - By Andrew J. Armstrong (http://www.javaworld.com/javaworld/javatips/jw-javatip114.html)
+AboutDialog.Item8:'Stop annoying java.prefs error when you don't have superuser access' - Thanks to Walter Schatz
+AboutDialog.Java_Req:Java Ø¹ÙØ§Ù
+Ø© ØªØ¬Ø§Ø±ÙØ© Ù
+Ø³Ø¬ÙØ© Ù
+Ù Sun Microsystems Inc. The JRE is redistributed as per the Supplemental License Terms, found at http://java.sun.com/j2se/1.4.1/j2re-1_4_1_02-license.html
+AboutDialog.Java_Req_One:ÙØ°Ø§ Ø§ÙÙ
+ÙØªØ¬ ÙØªØ¶Ù
+Ù ÙÙØ¯ Ø±Ø®ØµØª Ù
+Ù RSA Security, Inc.
+AboutDialog.Java_Req_Two:ØšØ¹Ø¶ Ø§ÙØ£Ø¬Ø²Ø§Ø¡ Ø±Ø®ØµØª Ù
+Ù  IBM Ù ÙÙ Ù
+ØªÙÙØ±Ø© ÙÙ http\://oss.software.ibm.com/icu4j/
+AboutDialog.Thanks:Ø§ÙØŽÙØ± Ø£ÙØ¶Ø§ Ù
+ÙØµÙÙ ÙÙ
+Ù Ø£ØŽØ§Ø± Ø¥ÙÙÙØ§ ØšÙ
+Ø¹ÙÙÙ
+Ø§Øª ÙÙ Ø§ÙØŽØšÙØ© Ø¹Ù  java ...
+AboutDialog.Title:Ø­ÙÙ...
+AboutDialog.Title_One:ÙØ§Ø¬ÙØ© Ù
+ÙØªØšÙ ÙØ±ÙÙØ³ØªÙÙ
+AboutDialog.Title_Two:ÙØ±ÙÙØ³ØªÙÙ ÙÙÙ
+ÙØªØšØ© Ø§ÙØ±ÙÙ
+ÙØ©, Ø¬Ø§Ù
+Ø¹Ø© ÙÙÙØ§ØªÙ
+AboutDialog.Copyright:Ø­Ù Ø§ÙÙØŽØ± (C) 2003 Ù
+ØŽØ±ÙØ¹ ÙÙÙØ²ÙÙÙØ¯Ø§ ÙÙÙ
+ÙØªØšØ© Ø§ÙØ±ÙÙ
+ÙØ©
+AboutDialog.Copyright_Two:ÙØŽØ± ØªØ­Øª Ø§ÙØ±Ø®ØµØ© Ø§ÙØ¹Ø§Ù
+Ø© GPL. Ø£ÙØžØ±  LICENSE.txt ÙÙØªÙØ§ØµÙÙ.
+#***********************
+#
+#***** Audit Table *****
+AuditTable.File:Filename
+#***********************
+#
+#***** Auto Filter *****
+Autofilter.AND:Ù
+Autofilter.Ascending:ØªØµØ§Ø¹Ø¯Ù
+Autofilter.Case_Sensitive:Ù
+Ø¶Ø§ÙØ§Ø© Ø­Ø§ÙØ©
+Autofilter.Custom_Filter:Ù
+ØªÙØ¯Ù
+
+Autofilter.Descending:ØªÙØ§Ø²ÙÙ
+Autofilter.Filter_By_Value:ØšØ³ÙØ·
+Autofilter.Name:Ø¥Ø³Ù
+ Ø§ÙØ¹Ù
+ÙØ¯
+Autofilter.None:ÙØ§ØŽÙ
+Autofilter.Operator:Ø­Ø§ÙØ©
+Autofilter.OR:Ø£Ù
+Autofilter.Order:ØªØ±ØªÙØš
+Autofilter.Order_Tooltip:ÙØ±Ø² Ø§ÙØ¹ÙØ§ØµØ± Ø§ÙÙ
+Ø¶Ø§ÙØ§Ø© ØšÙØ°Ø§ Ø§ÙØªØ±ØªÙØš
+Autofilter.Remove:Ø¥Ø²Ø§Ø­Ø© Ù
+Ø±ØŽØ­
+Autofilter.Remove_Tooltip:Ø­Ø°Ù ÙØ°Ø§ Ø§ÙÙ
+Ø±ØŽØ­ Ù
+Ù Ø¬Ø¯ÙÙ Ø§ÙØ£Ø¹Ù
+Ø¯Ø©
+Autofilter.Set:ØªØ¹ÙÙÙ Ù
+Ø±ØŽØ­
+Autofilter.Set_Tooltip:Ø¥Ø¶Ù ÙØ°Ø§ Ø§ÙÙ
+Ø±ØŽØ­ ÙØ¬Ø¯ÙÙ Ø§ÙØ£Ø¹Ù
+Ø¯Ø©
+Autofilter.Table_Header_Tooltip:Ø±ØŽØ­Øª Øš {0}
+Autofilter.Title:ØªØ±ØŽÙØ­ Ø¢ÙÙ ÙÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª
+Autofilter.eqeq:equal to
+Autofilter.!eq:does not equal
+Autofilter.<:is less than
+Autofilter.<eq:is less than or equal to
+Autofilter.>:is greater than
+Autofilter.>eq:is greater than or equal to
+Autofilter.^:starts with
+Autofilter.!^:does not start with
+Autofilter.$:ends with
+Autofilter.!$:does not end with
+Autofilter.?:contains
+Autofilter.!?:does not contain
+#
+#     ********************************************************
+#     *************** Collection Design Module ***************
+#     ********************************************************
+#     * The dictionary  phrases  used in the creation of the *
+#     * Colection  Design  Module. Note that we  still  have *
+#     * access  to the format  arguments (argument  32+) for *
+#     * html formatting.                                     *
+#     ********************************************************
+CDM.ArgumentConfiguration.Add:Ø¥Ø¶Ø§ÙØ©
+CDM.ArgumentConfiguration.Bad_Integer:<html>Ù
+Ø¶Ù
+ÙÙ  '{0}' ÙØ­ØªØ§Ø¬ ÙÙÙÙ
+Ø©  ØµØ­ÙØ­Ø©,<br>ÙÙÙ ÙØ§ ØªÙØ¬Ø¯ ÙÙÙ
+Ø© ÙÙ
+ÙÙ ØªØ­ÙÙÙÙØ§ Ù
+Ù {1}.</html>
+CDM.ArgumentConfiguration.Error_Title:Ø®Ø·Ø£ ÙÙ Ø§ÙÙ
+Ø¶Ù
+ÙÙ
+CDM.ArgumentConfiguration.Header:<HTML><STRONG><FONT FACE={FONT} COLOR=Black SIZE=5><CENTER>Ø§ÙØ±Ø¬Ø§Ø¡ ØªØ¬ÙÙØ² Ø§ÙÙ
+Ø¶Ù
+ÙÙ ÙÙ {0}.</CENTER></FONT></STRONG></HTML>
+CDM.ArgumentConfiguration.No_Value:Ù
+Ø¶Ù
+ÙÙ '{0}' ÙØªØ·ÙØš ÙÙÙ
+Ø© ØµØ­ÙØ­Ø©, ÙÙÙ ÙÙ
+ ØªØ­Ø¯Ø¯ ÙÙÙ
+Ø©.
+CDM.ArgumentConfiguration.Remove:Ø­Ø°Ù
+CDM.ArgumentConfiguration.Required_Argument:ÙØ¬Øš Ø¥Ø¹Ø·Ø§Ø¡ ÙÙÙ
+Ø© ÙÙ
+Ø¶Ù
+ÙÙ '{0}' .
+CDM.ArgumentConfiguration.Title:ØªØ¬ÙÙØ² Ù
+Ø¶Ø§Ù
+ÙÙ
+CDM.BuildTypeManager.Title:Ø¥Ø®ØªÙØ§Ø± Ù
+ÙØŽÙ
+CDM.BuildTypeManager.mg:mg
+CDM.BuildTypeManager.mg_Description:ÙØ°Ø§ ÙÙ Ø§ÙÙ
+ÙØŽÙ Ø§ÙØ£ØµÙÙ Ø§ÙØ°Ù ÙØ³ØªØ®Ø¯Ù
+Ù. ÙØ§Ù
+ ØšØªØ·ÙÙØ± ÙØ°Ø§ Ø§ÙØšØ±ÙØ§Ù
+Ø¬ ØšØµÙØ±Ø© Ø§Ø³Ø§Ø³ÙØ© Ø¥ÙÙØ³ØªÙØ± Ù
+ÙÙØ§Øª Ù ÙØ¯ ØªÙ
+ ÙØµÙÙ ÙÙ Ø§ÙÙØªØ§Øš Ø§ÙÙÙØ§Ø³ÙÙÙ  Managing Gigabytes. ÙØªÙØ­ Ø§ÙØªÙØŽÙÙ Ø¹ÙÙ Ù
+Ø³ØªÙÙ Ø§ÙÙØ³Ù
+ Ø Ù ÙÙÙÙ Ø§ÙØšØ­Ø« ÙÙÙ ØšÙÙÙØ§ÙÙ Ø£Ù ØªØ±Ø§ØªÙØšÙ(ÙÙØ³Ø§ Ù
+Ø¹Ø§ ÙÙ ÙØ­ØžØ© ÙØ§Ø­Ø¯Ø©) .ÙÙÙ Ù
+ÙØŽÙ Ù
+Ø®ØµØµ ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙØŽØ§Ù Ù
+Ø§Ø¯Ù Ù
+ÙÙØµÙ . ØšØ§ÙÙØ³ØšØ© ÙØšØ­Ø« Ø§ÙØ¬Ù
+ÙØ© ÙØ³ØªØ®Ø¯Ù
+ ÙØ±ÙÙØ³ØªÙÙ Ø§ÙÙ
+Ø¹Ø§Ù
+Ù "Ù" ÙÙÙ Ù
+ØµØ·ÙØ­Ø§Øª Ø§ÙØšØ­Ø« Ù Ø¹Ø±Ø¶ Ø§ÙØµÙØ§ØŠØš ÙÙ
+Ø¹Ø±ÙØ© Ù
+Ø§ Ø¥Ø°Ø§ ÙØ§ÙØª Ø§ÙØ¬Ù
+ÙØ© Ù
+ÙØ¬ÙØ¯Ø©. ØªÙ
+ ØªØ¬Ø±ÙØš ÙØ°Ø§ Ø§ÙØšØ±ÙØ§Ù
+Ø¬ ØšØµÙØ±Ø© Ù
+ÙØ«ÙØ© Ø¹ÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø§Øª ÙØšÙØ±Ø© Ø¬Ø¯Ø§  ections (ÙØµÙØµ ØšØ­Ø¬Ù
+ Ù
+ØªØ¹Ø¯Ø¯ Ø§Ù GB ).
+CDM.BuildTypeManager.mgpp:mgpp
+CDM.BuildTypeManager.mgpp_Description:ÙØ°Ù Ø¥ØµØ¯Ø§Ø±Ø© Ø¬Ø¯ÙØ¯Ø© Ù
+Ù MG (MG plus plus) ØªÙ
+ ØªØ·ÙÙØ±ÙØ§ ÙÙ Ù
+ØŽØ±ÙØ¹ Ù
+ÙØªØšØ© ÙÙÙØ²ÙÙÙØ¯Ø§ Ø§ÙØ±ÙÙ
+ÙØ©. ÙÙÙØ± Ø§ÙØªÙØŽÙÙ Ø¹ÙÙ Ù
+Ø³ØªÙÙ Ø§ÙÙÙÙ
+Ø© Ù ÙØªÙØ­ ÙØ°Ø§ Ø§ÙØ§Ø³ÙÙØš Ø§ÙØšØ­Ø« Ø§ÙØ­ÙÙÙ Ù Ø§ÙØšØ­Ø« Ø¹ÙÙ Ù
+Ø³ØªÙÙ Ø§ÙØªØ¬Ø§ÙØ± ÙÙÙ
+ÙØŽÙ. ÙÙ
+ÙÙ ÙÙØšØ­Ø« Ø§ÙØšÙÙÙØ§ÙÙ Ø£Ù ÙÙÙÙ ØªØ±Ø§ØªÙØšÙØ§. ÙØªÙ
+ Ø¥ÙØŽØ§Ø¡ ÙØŽØ§Ù ÙØ§Ø­Ø¯ ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙØ±ÙÙØ³ØªÙÙØ ØªØªØ§Ø­ ÙÙÙ ÙÙ Ù
+Ø³ØªÙÙØ§Øª ÙØ«ÙÙØ©/ÙØ³Ù
+ Ù ÙØµ / Ø­ÙÙÙ ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª.ØªÙÙØ± Ø£ÙØ«Ø± Ù
+Ù ÙØŽØ§Ù ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª ÙÙØªØ¬ Ø¹Ù Ø£ÙÙØ§ Ø§ØµØºØ± Ù
+Ù Ø£Ù ØªØ³ØªØ®Ø¯Ù
+  MG. ØšØ§ÙÙØ³ØšØ© ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙÙØšÙØ±Ø© ÙØµØšØ­ Ø¥Ø¬Ø±Ø§Ø¡ Ø§ÙØšØ­Ø« ØšØ·ÙØŠØ§ ÙØ³ØšØ© ÙÙ
+Ø³ØªÙÙ Ø§ÙÙÙÙ
+Ø© Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+ Ù ÙÙ Ø¯ÙÙ Ù
+Ø³ØªÙÙ Ø§ÙÙØ³Ù
+.
+CDM.BuildTypeManager.lucene:lucene
+CDM.BuildTypeManager.lucene_Description:ÙØ§Ù
+Øª Ù
+Ø€Ø³Ø³Ø© Ø¢ØšØ§ØªØŽÙ ÙÙØšØ±Ø§Ù
+Ø¬ ÙØªØ·ÙÙØ±  Lucene .ÙØªÙØ­ Ø§ÙØšØ­Ø« Ø§ÙØ­ÙÙÙ Ù ÙØšØ­Ø« Ø¹ÙÙ Ù
+Ø³ØªÙÙ Ø§ÙØªØ¬Ø§ÙØ± Ù ÙÙÙ ÙÙ Ù
+Ø³ØªÙÙ ÙØ§Ø­Ø¯ ÙÙØ·  (Ù
+Ø«Ø§Ù . ÙØ«Ø§ØŠÙ ÙØ§Ù
+ÙØ© Ø£Ù Ø£ÙØ³Ø§Ù
+ Ù ÙÙÙ ÙÙØ³Ø§ Ù
+Ø¹Ø§). ÙØ°ÙÙ ØªØµØšØ­ ÙÙØ§Ù Ø­ÙØ¬Ø© ÙÙØ¬ÙØ¯ ÙØŽØ§ÙÙÙ Ù
+ÙÙØµÙÙÙ ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙÙØ«Ø§ØŠÙ Ù Ø§ÙØ£ÙØ³Ø§Ù
+. ÙØªÙØ­ÙØžØ§ØŠÙ Ø§ÙØšØ­Ø« Ø§ÙÙ
+ØªÙÙØ±Ø© ÙÙ MGPP  Ø¥Ø¶Ø§ÙØ© Ø¥ÙÙ Ø¹ÙØ§Ù
+Ø§Øª Ø§ÙÙ
+Ø­Ø±Ù Ø§ÙÙØ§Ø­Ø¯Ø Ø³ÙØ§Ù ØšØ­Ø« Ù ÙØ±Ø² ÙÙØªØ§ØŠØ¬ Ø§ÙØšØ­Ø« ÙØ­ÙÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª. ØªÙ
+Øª Ø¥Ø¶Ø§ÙØªÙ ÙÙØ±ÙÙØ³ØªÙÙ ÙØªØ³ÙÙÙ ØªØ³Ø±ÙØ¹ ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ù Ø§ÙØªÙ ÙØ§ ØªØªÙÙØ± ÙÙ  MG Ù MGPP
+CDM.BuildTypeManager.Current_Type:Ø§ÙÙØŽØ§Ù Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+: {0}
+CDM.BuildTypeManager.Change:ØªØºÙÙØ±
+CDM.BuildTypeManager.Change_Tooltip:ØªØºÙÙØ± Ø§ÙÙ
+ÙØŽÙ Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+ ØšÙØ§Ø³Ø·Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+CDM.ClassifierManager.Add:Ø¥Ø¶Ø§ÙØ© Ù
+ØµÙÙ
+CDM.ClassifierManager.Add_Tooltip:Ø§Ø³ØªØ®Ø¯Ù
+ Ø§ÙÙ
+ØµÙÙ Ø§ÙÙ
+Ø®ØµØµ Ù
+Ø¹ ÙØ°Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+CDM.ClassifierManager.Assigned:Ø§ÙÙ
+ØµÙÙØ§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø©
+CDM.ClassifierManager.Classifier:Ø¥Ø®ØªÙØ§Ø± Ù
+ØµÙÙ ÙØ¥Ø¶Ø§ÙØªÙ
+CDM.ClassifierManager.Classifier_Exists:ÙÙØ¯ ØªÙ
+ ØªØ®ØµÙØµ ÙØ°Ø§ Ø§ÙÙ
+ØµÙÙ Ù
+Ù ÙØšÙ ÙÙØ°Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©.
+CDM.ClassifierManager.Classifier_Str:Ù
+ØµÙÙ
+CDM.ClassifierManager.Classifier_List_XML_Parse_Failed:ÙØ§ ÙÙ
+ÙÙ Ø§ÙØ¹Ø«ÙØ± Ø¹ÙÙ ÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ØµÙÙØ§Øª ØšØ¥Ø³ØªØ®Ø¯Ø§Ù
+ classinfo.pl -listall  # Updated 29-Nov-2006 by kkhalafala
+CDM.ClassifierManager.Classifier_XML_Parse_Failed:ÙØ§ ÙÙ
+ÙÙ ØªØ­Ø¯ÙØ¯ Ø§ÙÙ
+Ø¶Ù
+ÙÙ ÙÙ {0}\nØ§ÙÙ
+ØµÙÙ. Ø§ÙØ±Ø¬Ø§Ø¡ Ø§ÙØªØ£ÙØ¯ Ù
+Ù Ø§ÙÙ
+ØµÙÙ Ù
+ÙØ¶ÙØ¹ Ø§ÙØ³Ø€Ø§Ù\nØšØªÙÙÙØ± ØŽØ§Ø±Ø© -xml ØšØªÙÙÙØ° Ù
+ÙÙ
+CDM.ClassifierManager.Configure:ØªØ¬ÙÙØ² Ù
+ØµÙÙ
+CDM.ClassifierManager.Configure_Tooltip:ØªØºÙÙØ± Ø§ÙØ®ÙØ§Ø±Ø§Øª ÙÙÙ
+ØµÙÙ Ø§ÙÙ
+Ø®ØªØ§Ø±
+CDM.ClassifierManager.Remove:Ø­Ø°Ù Ù
+ØµÙÙ
+CDM.ClassifierManager.Remove_Tooltip:Ø­Ø°Ù Ø§ÙÙ
+ØµÙÙ Ø§ÙÙ
+Ø®ØªØ§Ø± Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©
+CDM.ClassifierManager.Parsing.Message:ÙØªÙ
+ ØªØ­Ù
+ÙÙ Ù
+Ø¹ÙÙÙ
+Ø§Øª Ø§ÙÙ
+ØµÙÙ
+CDM.ClassifierManager.Parsing.Title:ØªØ­Ù
+ÙÙ Ø§ÙÙ
+ØµÙÙØ§Øª
+CDM.FormatManager.Add:Ø¥Ø¶Ø§ÙØ© ÙØ³Ù Ø¹Ø±Ø¶
+CDM.FormatManager.Add_Tooltip:Ø¥Ø³ØªØ®Ø¯Ù
+ Ø£Ù
+Ø± ÙØ³Ù Ø§ÙØ¹Ø±Ø¶ Ù
+Ø¹ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+CDM.FormatManager.AllFeatures:ÙÙ Ø§ÙÙ
+ÙØ§Ù
+Ø­
+CDM.FormatManager.AllParts:ÙÙ Ø§ÙØ£Ø¬Ø²Ø§Ø¡
+CDM.FormatManager.Assigned_Formats:Ø£ÙØ§Ù
+Ø± ÙØ³Ù Ø§ÙØ¹Ø±Ø¶ Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø© Ø­Ø§ÙÙØ§
+CDM.FormatManager.Default:Reset to Default
+CDM.FormatManager.Default_Tooltip:Reset the selected format command to its default value 
+CDM.FormatManager.Editor:Ø³ÙØ§Ø³Ù Ù
+Ø­Ø§Ø±Ù Ø£Ù
+Ø± ÙØ³Ù Ø¹Ø±Ø¶ ØšÙØºØ© Ø§ÙÙØµÙØµ Ø§ÙØªØŽØ¹ØšÙØ©
+CDM.FormatManager.Editor_Tooltip:Ø¥Ø¯Ø®Ù Ø£ÙØ§Ù
+Ø± ÙØ³Ù Ø§ÙØ¹Ø±Ø¶ ÙÙØ§
+CDM.FormatManager.Editor_Disabled_Tooltip:Ø£ÙÙØ±  'Ø¥Ø¶Ø§ÙØ© ÙØ³Ù Ø¹Ø±Ø¶' ÙØ¥Ø¶Ø§ÙØ© Ø£Ù
+Ø± ÙØ³Ù Ø§ÙØ¹Ø±Ø¶ ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©.
+CDM.FormatManager.Enabled:ØªÙ
+ÙÙÙ
+CDM.FormatManager.Feature:Ø¥Ø®ØªÙØ§Ø± Ø³Ù
+Ø§Øª
+CDM.FormatManager.Feature_Tooltip:Ø³Ù
+Ø© ÙØ³Ù Ø§ÙØ¹Ø±Ø¶
+CDM.FormatManager.Insert:Ø­ØŽØ±
+CDM.FormatManager.Insert_Tooltip:Ø­ØŽØ± Ø§ÙÙ
+ØªØºÙØ±Ø§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±Ø© ÙÙ Ø£Ù
+Ø± ÙØ³Ù Ø§ÙØ¹Ø±Ø¶
+CDM.FormatManager.Default:Ø¥ÙØªØ±Ø§Ø¶Ù
+CDM.FormatManager.Default_Tooltip:Ø¥Ø¹Ø§Ø¯Ø© Ø§ÙÙ
+ØªØºÙØ±Ø§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±Ø© Ø¥ÙÙ Ø§ÙÙÙÙ
+Ø© Ø§ÙØ¥ÙØªØ±Ø§Ø¶ÙØ©
+CDM.FormatManager.Insert_Variable:Ø­ØŽØ± Ù
+ØªØºÙØ±
+CDM.FormatManager.Part:Ø§ÙÙ
+Ø­ØªÙÙ Ø§ÙÙ
+ØªÙØ§Ø¹Ù
+CDM.FormatManager.Part_Tooltip:Ø¬Ø§ÙØš Ø§ÙÙ
+ÙÙ
+Ø­ Ø§ÙÙ
+Ø®ØªØ§Ø± ÙÙØ³Ù Ø§ÙØ¹Ø±Ø¶
+CDM.FormatManager.Remove:Ø­Ø°Ù ÙØ³Ù Ø§ÙØ¹Ø±Ø¶
+CDM.FormatManager.Remove_Tooltip:Ø­Ø°Ù Ø£Ù
+Ø± ÙØ³Ù Ø§ÙØ¹Ø±Ø¶ Ø§ÙÙ
+Ø®ØªØ§Ø± Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©
+CDM.FormatManager.Variable_Tooltip:Ø§ÙÙ
+ØªØºÙØ±Ø§Øª Ø§ÙÙ
+ØªÙÙØ±Ø© Ù
+Ø¹ Ø£Ù
+Ø± ÙØ³Ù Ø§ÙØ¹Ø±Ø¶
+CDM.General.Access:ÙØ°Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ù
+ØªØ§Ø­Ø© ÙÙØ¬Ù
+ÙÙØ±
+CDM.General.Browser_Title:Ø¥Ø®ØªÙØ§Ø± ØµÙØ±Ø©
+CDM.General.Collection_Extra:ÙØµÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©:
+CDM.General.Collection_Extra_Tooltip:ÙØµÙ ØºØ±Ø¶ Ù Ù
+Ø­ØªÙÙØ§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+CDM.General.Collection_Name:Ø¹ÙÙØ§Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©:
+CDM.General.Collection_Name_Tooltip:Ø¥Ø³Ù
+ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+CDM.General.Email.Creator:Ø§ÙØšØ±ÙØ¯ Ø§ÙØ¥ÙÙØªØ±ÙÙÙ ÙÙÙ
+ÙØŽÙØ¡
+CDM.General.Email.Creator_Tooltip:Ø¹ÙÙØ§Ù Ø§ÙØšØ±ÙØ¯ Ø§ÙØ¥ÙÙØªØ±ÙÙÙ ÙÙ
+ÙØŽÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+CDM.General.Email.Maintainer:Ø§ÙØšØ±ÙØ¯ Ø§ÙØ¥ÙÙØªØ±ÙÙÙ ÙÙÙ
+Ø§ÙÙ
+CDM.General.Email.Maintainer_Tooltip:Ø¹ÙÙØ§Ù Ø§ÙØšØ±ÙØ¯ Ø§ÙØ¥ÙÙØªØ±ÙÙÙ ÙÙ
+Ø§ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+CDM.General.Icon_Collection:Ø¹ÙÙØ§Ù Ø§ÙÙ
+ÙØ§Ø±Ø¯ Ø§ÙÙ
+ÙØ­Ø¯ ÙØµÙØ±Ø©  'ØµÙØ­Ø© Ø­ÙÙ'
+CDM.General.Icon_Collection_Tooltip:Ø¹ÙÙØ§Ù Ø§ÙÙ
+ÙØ§Ø±Ø¯ Ø§ÙÙ
+ÙØ­Ø¯ ÙÙØµÙØ±Ø© Ø§ÙØªÙ ØªØ¹Ø±Ø¶ ÙÙ ØµÙØ­Ø© Ø­ÙÙ ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+CDM.General.Icon_Collection_Small:Ø¹ÙÙØ§Ù Ø§ÙÙ
+ÙØ§Ø±Ø¯ Ø§ÙÙ
+ÙØ­Ø¯ ÙØµÙØ±Ø©  'ØµÙØ­Ø© Ø§ÙÙ
+ÙÙØ¹' :
+CDM.General.Icon_Collection_Small_Tooltip:Ø¹ÙÙØ§Ù Ø§ÙÙ
+ÙØ§Ø±Ø¯ Ø§ÙÙ
+ÙØ­Ø¯ ÙÙØµÙØ±Ø© Ø§ÙØªÙ ØªØ¹Ø±Ø¶ ÙÙ ØµÙØ­Ø© Ù
+ÙÙØ¹ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+CDM.General.Image_Copy_Failed:Ø­Ø¯Ø« Ø®Ø·Ø£ ÙÙ
+ÙØ¹ Ø¹Ø±Ø¶ Ø§ÙØµÙØ±Ø©.\nØ§ÙØ±Ø¬Ø§Ø¡ Ù
+Ø­Ø§ÙÙØ© ÙØ³Ø® Ø§ÙØµÙØ±Ø© Ø§ÙÙ Ù
+Ø¬ÙØ¯ Ø§ÙØµÙØ± Ø§ÙØ®Ø§Øµ ØšØ§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙØ¯ÙÙØ§
+CDM.General.Image_Filter:ØµÙØ± (gifs, jpgs and pngs)
+CDM.GUI.Classifiers:Ù
+ØµÙÙØ§Øª Ø§ÙØªØµÙØ­
+CDM.GUI.Formats:Ù
+ÙØ§Ù
+Ø­ ÙØ³Ù Ø§ÙØ¹Ø±Ø¶
+CDM.GUI.General:Ø¹Ø§Ù
+
+CDM.GUI.Indexes:ÙØŽØ§ÙØ§Øª Ø§ÙØšØ­Ø«
+CDM.GUI.Macros:Ù
+Ø§ÙØ±Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙ
+Ø®ØµØµ
+CDM.GUI.Plugins:Ù
+ÙØ§ØšØ³ Ø§ÙÙØ«ÙÙØ©
+CDM.GUI.Root:CDM_ROOT:
+CDM.GUI.SearchMetadata:ØšØ­Ø«
+CDM.GUI.Subcollections:ÙØŽØ§ÙØ§Øª Ø§ÙÙØ·Ø§Ø¹Ø§Øª
+CDM.GUI.SuperCollection:ØšØ­Ø« ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª
+CDM.GUI.Translation:ØªØ±Ø¬Ù
+Ø© ÙØµ
+CDM.HelpButton:Ù
+Ø³Ø§Ø¹Ø¯Ø© ÙÙØ°Ù Ø§ÙØŽØ§ØŽØ©
+CDM.HelpButton_Tooltip:Ù
+Ø³Ø§Ø¹Ø¯Ø© ÙÙØ°Ù Ø§ÙØŽØ§ØŽØ©
+CDM.IndexManager.Add_Index:Ø¥Ø¶Ø§ÙØ© ÙØŽØ§Ù
+CDM.IndexManager.Add_Index_Tooltip:ØšÙØ§Ø¡ Ø§ÙÙØŽØ§Ù Ø§ÙÙ
+Ø®ØµØµ ÙÙØ°Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+CDM.IndexManager.Allfields_Index:ÙÙ Ø­ÙÙÙ Ø§ÙÙØŽØ§Ù
+CDM.IndexManager.Default_Index_Indicator:[Ø§ÙÙØŽØ§Ù Ø§ÙØ¥ÙØªØ±Ø§Ø¶Ù]
+CDM.IndexManager.Index_Exists:ÙÙØ¯ ØªÙ
+ ØªØ®ØµÙØµ ÙØ°Ø§ Ø§ÙÙØŽØ§Ù Ù
+Ù ÙØšÙ ÙÙØ°Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©.
+CDM.IndexManager.Indexes:Ø§ÙÙØŽØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø©
+CDM.IndexManager.Level:Ù
+Ø³ØªÙÙ Ø§ÙØªÙØŽÙÙ:
+CDM.IndexManager.Level_Tooltip:ØšÙØ§Ø¡ Ø§ÙÙØŽØ§Ù Ø¹ÙÙ Ù
+Ø³ØªÙÙ ÙØ«ÙÙØ©
+CDM.IndexManager.Add_All:Ø¥Ø¶Ø§ÙØ© Ø§ÙÙÙ
+CDM.IndexManager.Add_All_Tooltip:Ø¥Ø¶Ø§ÙØ© ÙØŽØ§Ù Ù
+ÙÙØµÙ ÙÙÙ Ù
+ØµØ¯Ø±
+CDM.IndexManager.Edit_Index:ØªØ­Ø¯ÙØ« ÙØŽØ§Ù
+CDM.IndexManager.Edit_Index_Tooltip:ØªØ­Ø¯ÙØ« Ø§ÙÙØŽØ§Ù Ø§ÙÙ
+Ø®ØªØ§Ø±
+CDM.IndexManager.New_Index:ÙØŽØ§Ù Ø¬Ø¯ÙØ¯
+CDM.IndexManager.New_Index_Tooltip:Ø¥Ø¶Ø§ÙØ© ÙØŽØ§Ù Ø¬Ø¯ÙØ¯
+CDM.IndexManager.Remove_Index:Ø­Ø°Ù ÙØŽØ§Ù
+CDM.IndexManager.Remove_Index_Tooltip:Ø­Ø°Ù Ø§ÙÙØŽØ§Ù Ø§ÙÙ
+Ø®ØªØ§Ø±
+CDM.IndexManager.Replace_Index:Ø¥Ø³ØªØšØ¯Ø§Ù ÙØŽØ§Ù
+CDM.IndexManager.Replace_Index_Tooltip:ØªØ­Ø¯ÙØ« Ø§ÙÙØŽØ§Ù Ø§ÙÙ
+Ø®ØªØ§Ø±
+CDM.IndexManager.Select_All:Ø¥Ø®ØªÙØ§Ø± Ø§ÙÙÙ
+CDM.IndexManager.Select_All_Tooltip:Ø¥Ø®ØªÙØ§Ø± ÙÙ ÙØŽØ§ÙØ§Øª Ø§ÙÙ
+ØµØ§Ø¯Ø±
+CDM.IndexManager.Select_None:ÙÙØ¶
+CDM.IndexManager.Select_None_Tooltip:ÙÙØ¶ Ø¥Ø®ØªÙØ§Ø± ÙÙ ÙØŽØ§ÙØ§Øª Ø§ÙÙ
+ØµØ§Ø¯Ø±
+CDM.IndexManager.Set_Default:ØªØ¹ÙÙÙ Ø§ÙÙØŽØ§Ù Ø§ÙØ¥ÙØªØ±Ø§Ø¶Ù
+CDM.IndexManager.Set_Default_Tooltip:Ø¬Ø¹Ù Ø§ÙÙØŽØ§Ù Ø§ÙÙ
+Ø®ØªØ§Ø± Ø§ÙÙØŽØ§Ù Ø§ÙØ¥ÙØªØ±Ø§Ø¶Ù
+CDM.IndexManager.Source:Ø¥ØšÙÙ ÙØŽØ§ÙØ§ Ø¹ÙÙ:
+CDM.IndexManager.Source_Tooltip:ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØªÙ ÙØšÙÙ Ø¹ÙÙÙØ§ Ø§ÙÙØŽØ§Ù
+CDM.IndexManager.Text_Source:ÙØµ ÙØ§Ù
+Ù
+CDM.IndexManager.Text_Source_Tooltip:ØªØ¶Ù
+ÙÙ Ø§ÙÙØµ Ø§ÙÙØ§Ù
+Ù ÙÙÙØ«ÙÙØ© ÙÙ Ø§ÙÙØŽØ§Ù
+CDM.IndexingManager.Accent_fold:Accent fold
+CDM.IndexingManager.Casefold:Casefold
+CDM.IndexingManager.Options:Ø®ÙØ§Ø±Ø§Øª Ø§ÙØªÙØŽÙÙ:
+CDM.IndexingManager.Stem:Stem
+CDM.LanguageManager.Add_Tooltip:Ø¥Ø¶Ø§ÙØ© Ø§ÙÙØºØ© Ø§ÙÙ
+Ø®ØµØµØ© ÙÙÙØ§ØŠÙ
+Ø©
+CDM.LanguageManager.Assigned_Languages:Ø§ÙÙØºØ§Øª Ø§ÙÙ
+Ø®ØµØµØ©
+CDM.LanguageManager.Default_Language:Ø§ÙÙØºØ© Ø§ÙØ¥ÙØªØ±Ø§Ø¶ÙØ©
+CDM.LanguageManager.LanguageMetadata:ÙØºØ© ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª
+CDM.LanguageManager.LanguageMetadata_Tooltip:Ø¹ÙØµØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+ ÙØªØ­Ø¯ÙØ¯ ÙØºØ© Ø§ÙÙØ«ÙÙØ©
+CDM.LanguageManager.Remove_Tooltip:Ø­Ø°Ù Ø§ÙÙØºØ© Ø§ÙÙ
+Ø®ØªØ§Ø±Ø© Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©
+CDM.LanguageManager.Replace_Tooltip:Ø¥Ø³ØªØšØ¯Ø§Ù
+CDM.LanguageManager.Selector:Ø¥Ø¶Ø§ÙØ© ÙØºØ©:
+CDM.LanguageManager.Selector_Tooltip:Ø§ÙÙØºØ© Ø§ÙØªÙ ÙØªÙ
+ ØšÙØ§Ø¡ ÙØ·Ø§Ø¹ Ø§ÙÙØŽØ§Ù ØšÙØ§
+CDM.LanguageManager.Set_Default:ØªØ¹ÙÙÙ Ø¥ÙØªØ±Ø§Ø¶Ù
+CDM.LanguageManager.Set_Default_Tooltip:ØªØ¹ÙÙÙ Ø§ÙÙØºØ© Ø§ÙÙ
+Ø®ØªØ§Ø±Ø© Ø¥ÙØªØ±Ø§Ø¶ÙØ©
+CDM.LevelManager.Document:ÙØ«ÙÙØ©
+CDM.LevelManager.Section:ÙØ³Ù
+
+CDM.LevelManager.Paragraph:ÙÙØ±Ø©
+CDM.LevelManager.Level:Ù
+Ø³ØªÙÙ
+CDM.LevelManager.Level_Title:Ù
+Ø³ØªÙÙØ§Øª Ø§ÙØªÙØŽÙÙ
+CDM.LevelManager.Level_Tooltip:Ø§ÙÙØ­Ø¯Ø§Øª Ø§ÙÙØµÙØ© Ø§ÙØªÙ Ø£Ø³Ø³Øª Ø¹ÙÙÙØ§ Ø§ÙÙØŽØ§ÙØ§Øª
+CDM.LevelManager.Default:Ø¥ÙØªØ±Ø§Ø¶Ù
+CDM.LevelManager.Default_Tooltip:Ø§ÙÙ
+Ø³ØªÙÙ Ø§ÙØ¥ÙØªØ±Ø§Ø¶Ù ÙÙ ÙØ§Ø¬ÙØ© Ø§ÙÙØ±Ø§Ø¡
+CDM.MacrosManager.Editor_Tooltip:ØªØ­Ø¯ÙØ« Ø§ÙÙ
+Ø§ÙØ±Ù ÙÙØ§
+CDM.Move.At_Bottom:Ø¥Ø³ØªØ­Ø§ÙØ© ØªØ­Ø±ÙÙ {0} {1} Ø¥ÙÙ Ø£Ø³ÙÙ ÙØ§ÙÙØ§ Ø§ÙØ£Ø®ÙØ±Ø© ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø©
+CDM.Move.At_Top:Ø¥Ø³ØªØ­Ø§ÙØ© ØªØ­Ø±ÙÙ {0} {1} Ø¥ÙÙ Ø£Ø¹ÙÙ ÙØ§ÙÙØ§ Ø§ÙØ£ÙÙÙ ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø©
+CDM.Move.Cannot:ÙØ§ ÙÙ
+ÙÙ ØªØ­Ø±ÙÙ Ø§ÙÙ
+ÙØ§ØšØ³ {0} Ø¥ÙÙ Ø£Ø¯ÙÙ Ø­ÙØ« ÙÙØšØºÙ ÙØ¬ÙØ¯  RecPlug Ù ArcPlug Ø£Ø³ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø©.
+CDM.Move.Fixed:<html>RecPlug Ù ArcPlug  ØšØµÙØ±Ø© Ø¹Ø§Ù
+Ø© Ù
+Ø·ÙÙØš ÙØ¬ÙØ¯ÙÙ
+Ø§ Ø£Ø³ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø©.<br>Ø¥Ø°Ø§ ÙÙØª ØªÙØ¯ Ø°ÙÙ Ø§ÙØ±Ø¬Ø§Ø¡ ÙØ¹Ù Ø°ÙÙ ÙØ¯ÙÙØ§ ÙÙ Ù
+ÙÙ Ø§ÙØªØ¬ÙÙØ² collect.cfg .</html>
+CDM.Move.Move_Down:Ø­Ø±Ù Ø§ÙÙ Ø£Ø³ÙÙ
+CDM.Move.Move_Down_Tooltip:ØªØ­Ø±ÙÙ Ø§ÙØ¹ÙØµØ± Ø§ÙÙ
+Ø®ØªØ§Ø± Ø¥ÙÙ Ø£Ø³ÙÙ
+CDM.Move.Move_Up:Ø­Ø±Ù Ø§ÙÙ Ø£Ø¹ÙÙ
+CDM.Move.Move_Up_Tooltip:ØªØ­Ø±ÙÙ Ø§ÙØ¹ÙØµØ± Ø§ÙÙ
+Ø®ØªØ§Ø± Ø¥ÙÙ Ø£Ø¹ÙÙ
+CDM.Move.Title:Ø®Ø·Ø£ - ÙØ§ ÙÙ
+ÙÙ Ø§ÙØªØ­Ø±ÙÙ
+CDM.PlugInManager.Add:Ø¥Ø¶Ø§ÙØ© Ù
+ÙØ§ØšØ³
+CDM.PlugInManager.QuickAdd:Ø¥Ø¶Ø§ÙØ© Ù
+ÙØ§ØšØ³
+CDM.PlugInManager.Add_Tooltip:Ø§Ø³ØªØ®Ø¯Ù
+ Ø§ÙÙ
+ÙØ§ØšØ³ Ø§ÙÙ
+Ø®ØµØµ ÙÙØ°Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+CDM.PlugInManager.Assigned:Ø§ÙÙ
+ÙØ§ØšØ³ Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø©
+CDM.PlugInManager.Configure:ØªØ¬ÙÙØ² Ù
+ÙØ§ØšØ³
+CDM.PlugInManager.Configure_Tooltip:ØªØºÙÙØ± Ø§ÙØ®ÙØ§Ø±Ø§Øª ÙÙÙ
+ÙØ§ØšØ³ Ø§ÙÙ
+Ø®ØªØ§Ø±
+CDM.PlugInManager.Ignore:ÙØ§ ØªØ¶Ù Ù
+ÙØ§ØšØ³
+CDM.PlugInManager.Ignore_Tooltip:ÙØ§ ØªØ¶Ù Ø£Ù Ù
+ÙØ§ØšØ³ ÙÙØ°Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©.
+CDM.PlugInManager.PlugIn:Ø¥Ø®ØªÙØ§Ø± Ù
+ÙØ§ØšØ³ ÙØ¥Ø¶Ø§ÙØªÙ:
+CDM.PlugInManager.PlugIn_Tooltip:Ø§ÙÙ
+ÙØ§ØšØ³ Ø§ÙÙ
+ØªÙÙØ±Ø© ÙÙØ¥Ø³ØªØ®Ø¯Ø§Ù
+ ÙÙ ÙØ°Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+CDM.PlugInManager.PlugIn_Exists:ØªÙ
+ Ø¥Ø¹ØªÙ
+Ø§Ø¯ ÙØ°Ø§ Ø§ÙÙ
+ÙØ§ØšØ³ ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ù
+Ù ÙØšÙ.
+CDM.PlugInManager.PlugIn_Str:Ù
+ÙØ§ØšØ³
+CDM.PlugInManager.PlugIn_XML_Parse_Failed:ÙØ§ ÙÙ
+ÙÙ ØªØ­Ø¯ÙØ¯ Ø§ÙÙ
+Ø¶Ù
+ÙÙ ÙÙ {0}\nÙ
+ÙØ§ØšØ³. . Ø§ÙØ±Ø¬Ø§Ø¡ Ø§ÙØªØ£ÙØ¯ Ù
+Ù Ø§ÙÙ
+ÙØ§ØšØ³ Ù
+ÙØ¶ÙØ¹ Ø§ÙØ³Ø€Ø§Ù\nØšØªÙÙÙØ± ØŽØ§Ø±Ø© -xml ØšØªÙÙÙØ° Ù
+ÙÙ
+CDM.PluginManager.Plugin_List_XML_Parse_Failed:ÙØ§ ÙÙ
+ÙÙ Ø§ÙØ¹Ø«ÙØ± Ø¹ÙÙ ÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ§ØšØ³ ØšØ¥Ø³ØªØ®Ø¯Ø§Ù
+pluginfo.pl -listall  # Updated 29-Nov-2006 by kkhalafala
+CDM.PluginManager.Plugin_Suggestion_Prompt:ÙØ§ ÙÙØ¬Ø¯ Ù
+ÙØ§ØšØ³ ÙÙ ÙØ°Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙØ³ØªØ·ÙØ¹ Ù
+Ø¹Ø§ÙØ¬Ø© Ø§ÙÙ
+ÙÙ "{0}". Ø§ÙÙ
+ÙØ§ØšØ³ Ø§ÙØªØ§ÙÙØ© ÙÙ
+ÙÙ Ø£Ù ØªØ¹Ø§ÙØ¬ ÙØ°Ø§ Ø§ÙÙ
+ÙÙ. ØªØ³ØªØ·ÙØ¹ Ø¥Ø¶Ø§ÙØ© ÙØ§Ø­Ø¯ ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØšØ¥Ø®ØªÙØ§Ø±Ù Ù Ø§ÙØ¶ØºØ· Ø¹ÙÙ Ø²Ø± Ø¥Ø¶Ø§ÙØ©. (ØªØ¬Øš Ù
+ÙØ§Ø­ØžØ© Ø§ÙÙ ØšØ§ÙØ¥Ù
+ÙØ§Ù ØªØ¹Ø¯ÙÙ ÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ§ØšØ³ ÙÙ Ø£Ù ÙÙØª Ù
+Ù Ø®ÙØ§Ù "Ù
+ÙØ§ØšØ³ Ø§ÙÙØ«ÙÙØ©" ÙÙ Ù
+ØŽÙØ¯ Ø§ÙØªØµÙ
+ÙÙ
+.)
+CDM.PlugInManager.Remove:Ø­Ø°Ù Ù
+ÙØ§ØšØ³
+CDM.PlugInManager.Remove_Tooltip:Ø­Ø°Ù Ø§ÙÙ
+ÙØ§ØšØ³ Ø§ÙÙ
+Ø®ØªØ§Ø± Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©
+CDM.PluginManager.SuggestedPluginListTitle:Ø§ÙÙ
+ÙØ§ØšØ³ Ø§ÙÙ
+ÙØªØ±Ø­Ø© ÙÙØ°Ø§ Ø§ÙÙ
+ÙÙ
+CDM.PlugInManager.Parsing.Message:ÙØªÙ
+ ØªØ­Ù
+ÙÙ Ù
+Ø¹ÙÙÙ
+Ø§Øª Ø§ÙÙ
+ÙØ§ØšØ³.
+CDM.PlugInManager.Parsing.Title:ØªØ­Ù
+ÙÙ Ù
+ÙØ§ØšØ³
+CDM.SearchMetadataManager.Component:Ø¹ÙØµØ± ÙÙ ÙØ§ØŠÙ
+Ø© Ø§ÙØšØ­Ø«
+CDM.SearchMetadataManager.Component_Name:Ø¹Ø±Ø¶ Ø§ÙØªØµ
+CDM.SearchMetadataManager.Type_index:ÙØŽØ§Ù
+CDM.SearchMetadataManager.Type_level:Ù
+Ø³ØªÙÙl
+CDM.SearchMetadataManager.Type_partition:ÙØ·Ø§Ø¹
+CDM.SearchMetadataManager.Type_language:ÙØºØ© Ø§ÙÙØ·Ø§Ø¹
+CDM.SubcollectionManager.Add:Ø¥Ø¶Ø§ÙØ© Ù
+Ø±ØŽØ­
+CDM.SubcollectionManager.Add_Tooltip:Ø¥Ø¶Ù Ø§ÙÙ
+Ø±ØŽØ­ Ø§ÙÙ
+Ø®ØµØµ ÙÙØ°Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+CDM.SubcollectionManager.Assigned:Ø¹Ø±Ù Ù
+Ø±ØŽØ­Ø§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙÙØ±Ø¹ÙØ©
+CDM.SubcollectionManager.Exclude:Ø¥Ø³ØªØšØ¹Ø§Ø¯
+CDM.SubcollectionManager.Flags:ØªØ¹ÙÙÙ Ø¹ÙØ§Ù
+Ø§Øª Ù
+Ù
+ÙØ²Ø© ÙÙÙ
+Ø¶Ø§ÙØ§Ø©
+CDM.SubcollectionManager.Flags_Tooltip:Ø§ÙØ¹ÙØ§Ù
+Ø§Øª Ø§ÙÙ
+Ù
+ÙØ²Ø© ÙÙØªØ¹ØšÙØ±Ø§Øª Ø§ÙÙ
+ÙØªØžÙ
+Ø© Ø§ÙØªÙ ØªØ³ØªØ®Ø¯Ù
+ ÙÙÙ
+Ø¶Ø§ÙØ§Ø© (Ù
+Ø«Ø§Ù. "i" ÙÙ
+Ø¶Ø§ÙØ§Ø© Ø­Ø§ÙØ© -ØºÙØ± Ø­Ø³Ø§Ø³Ø©)
+CDM.SubcollectionManager.Include:Ø¶Ù
+
+CDM.SubcollectionManager.Inclusive:Ù
+Ø§Ø°Ø§ ÙÙØ¹Ù ØšØ§ÙÙ
+ÙÙØ§Øª Ø§ÙØªÙ ØªÙ
+Øª Ù
+Ø¶Ø§ÙØ§ØªÙØ§Ø
+CDM.SubcollectionManager.Language_Controls:ØªØ­Ø¯ÙØ¯ ÙØºØ§Øª
+CDM.SubcollectionManager.Match:Ø§ÙØªØ¹ØšÙØ±Ø§Øª Ø§ÙÙ
+ÙØªØžÙ
+Ø© ÙÙÙ
+Ø¶Ø§ÙØ§Ø© Ù
+Ø¹:
+CDM.SubcollectionManager.Match_Tooltip:Ø§ÙØªØ¹ØšÙØ±Ø§Øª Ø§ÙÙ
+ÙØªØžÙ
+Ø© Ø§ÙØªÙ ØªØ¹Ø±Ù Ø§ÙÙØ«Ø§ØŠÙ ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙØ±Ø¹ÙØ©
+CDM.SubcollectionManager.Name:Ø¥Ø³Ù
+ Ù
+Ø±ØŽØ­ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙØ±Ø¹ÙØ©:
+CDM.SubcollectionManager.Name_Tooltip:Ø¥Ø³Ù
+ Ø§ÙÙ
+Ø±ØŽØ­ ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙØ±Ø¹ÙØ© Ø§ÙØ¬Ø¯ÙØ¯Ø©
+CDM.SubcollectionManager.Partitions_Disabled:ÙØ°Ù Ø§ÙØªØ³ÙÙÙØ© ØºÙØ± Ù
+ÙØ¹ÙØ© Ø­Ø§ÙÙØ§ ÙØ£ÙÙ ÙÙ Ø­Ø§ÙØ© {0-Current Mode} Ø­Ø§ÙØ©. ÙÙ
+ÙÙÙ Ø¥Ø³ØªØ®Ø¯Ø§Ù
+ÙØ§ ÙÙ Ø­Ø§ÙØ§Øª {1-Systems} Ù {2-Expert} . Ø§Ø³ØªØ®Ø¯Ù
+ Ù
+ÙÙ->Ø§ÙØªÙØ¶ÙÙØ§Øª ÙØªÙØ¹ÙÙ Ø­Ø§ÙØ© Ø§ÙØ¹Ù
+Ù.
+CDM.SubcollectionManager.Remove:Ø­Ø°Ù Ù
+Ø±ØŽØ­
+CDM.SubcollectionManager.Remove_Tooltip:Ø­Ø°Ù Ø§ÙÙ
+Ø±ØŽØ­ Ø§ÙÙ
+Ø®ØªØ§Ø± Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©
+CDM.SubcollectionManager.Replace:Ø¥Ø³ØªØšØ¯Ø§Ù Ù
+Ø±ØŽØ­
+CDM.SubcollectionManager.Replace_Tooltip:ØªØ­Ø¯ÙØ« ØªÙØ§ØµÙÙ Ø§ÙÙ
+Ø±ØŽØ­ Ø§ÙÙ
+Ø®ØªØ§Ø±
+CDM.SubcollectionManager.Source:Ù
+Ø€ØŽØ±Ø§Øª Ø§ÙÙØ«ÙÙØ© ÙÙÙ
+Ø¶Ø§ÙØ§Ø© Ø¶Ø¯ÙØ§:
+CDM.SubcollectionManager.Source_Tooltip:Ù
+Ø€ØŽØ±Ø§Øª Ø§ÙÙØ«ÙÙØ© ÙØ¥Ø¬Ø±Ø§Ø¡ Ø§ÙØªØ±ØŽÙØ­ Ø¹ÙÙÙØ§
+CDM.SubcollectionManager.Subcollection_Controls:ØªØ¹Ø±ÙÙ Ù
+Ø±ØŽØ­Ø§Øª
+CDM.SubcollectionManager.Subindex_Controls:ØªØ¹ÙÙÙ ÙØ·Ø§Ø¹Ø§Øª
+CDM.SubcollectionIndexManager.Add_Subindex:Ø¥Ø¶Ø§ÙØ© ÙØŽØ§Ù ÙØ·Ø§Ø¹
+CDM.SubcollectionIndexManager.Add_Subindex_Tooltip:Ø¥Ø¶Ø§ÙØ© ÙØŽØ§Ù Ø§ÙÙØ·Ø§Ø¹ Ø§ÙÙ
+Ø®ØµØµ ÙÙØ°Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+CDM.SubcollectionIndexManager.Default_Partition_Indicator:[ÙØŽØ§Ù Ø§ÙÙØ·Ø§Ø¹ Ø§ÙØ¥ÙØªØ±Ø§Ø¶Ù]
+CDM.SubcollectionIndexManager.Remove_Subindex:Ø­Ø°Ù ÙØŽØ§Ù Ø§ÙÙØ·Ø§Ø¹
+CDM.SubcollectionIndexManager.Remove_Subindex_Tooltip:Ø­Ø°Ù ÙØŽØ§Ù Ø§ÙÙØ·Ø§Ø¹ Ø§ÙÙ
+Ø®ØªØ§Ø± Ù
+Ù ÙØ°Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+CDM.SubcollectionIndexManager.Replace_Subindex:Ø¥Ø³ØªØšØ¯Ø§Ù ÙØŽØ§Ù ÙØ·Ø§Ø¹
+CDM.SubcollectionIndexManager.Replace_Subindex_Tooltip:ØªØ­Ø¯ÙØ« ÙØŽØ§Ù Ø§ÙÙØ·Ø§Ø¹ Ø§ÙÙ
+Ø®ØªØ§Ø±
+CDM.SubcollectionIndexManager.Set_Default_Subindex:ØªØ¹ÙÙÙ Ø¥ÙØªØ±Ø§Ø¶Ù
+CDM.SubcollectionIndexManager.Set_Default_Subindex_Tooltip:ØªØ¹ÙÙÙ ÙØŽØ§Ù Ø§ÙÙØ·Ø§Ø¹ Ø§ÙÙ
+Ø®ØªØ§Ø± Ø¥ÙØªØ±Ø§Ø¶ÙØ§
+CDM.SubcollectionIndexManager.Source:ØšÙØ§Ø¡ ÙØŽØ§Ù Ø§ÙÙØ·Ø§Ø¹ ÙÙÙØ§ Ù:
+CDM.SubcollectionIndexManager.Source_Tooltip:Ù
+Ø±ØŽØ­Ø§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙØ±Ø¹ÙØ© ÙØšÙØ§Ø¡ ÙØŽØ§Ù Ø§ÙÙØ·Ø§Ø¹ Ø¹ÙÙÙØ§
+CDM.SubcollectionIndexManager.Subindexes:ÙØ·Ø§Ø¹Ø§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙÙØ±Ø¹ÙØ© Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø©
+CDM.TranslationManager.Add:Ø¥Ø¶Ø§ÙØ© ØªØ±Ø¬Ù
+Ø©
+CDM.TranslationManager.Add_Tooltip:Ø¥Ø¶Ø§ÙØ© Ø§ÙØªØ±Ø¬Ù
+Ø© Ø§ÙÙ
+Ø­Ø¯Ø¯Ø© Ø§ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+CDM.TranslationManager.Affected_Features:Ø³Ù
+Ø§Øª
+CDM.TranslationManager.Assigned_Fragments:Ø§ÙØªØ±Ø¬Ù
+Ø§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø©
+CDM.TranslationManager.Default_Text:ØªØ¬Ø²ØŠØ© ÙØµ Ù
+ØšØ¯ØŠÙØ©
+CDM.TranslationManager.Fragment_Column:ØªØ¬Ø²ØŠØ© ÙØµ
+CDM.TranslationManager.Language:ÙØºØ© Ø§ÙØªØ±Ø¬Ù
+Ø©:
+CDM.TranslationManager.Language_Column:ÙØºØ©
+CDM.TranslationManager.Language_Tooltip:Ø§ÙÙØºØ© Ø§ÙØªÙ ØªÙ
+Øª Ø§ÙØªØ±Ø¬Ù
+Ø© Ø¥ÙÙÙØ§
+CDM.TranslationManager.Remove:Ø­Ø°Ù ØªØ±Ø¬Ù
+Ø©
+CDM.TranslationManager.Remove_Tooltip:Ø­Ø°Ù Ø§ÙØªØ±Ø¬Ù
+Ø© Ø§ÙÙ
+Ø®ØªØ§Ø±Ø© Ù
+Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+CDM.TranslationManager.Replace:Ø¥Ø³ØªØšØ¯Ø§Ù ØªØ±Ø¬Ù
+Ø©
+CDM.TranslationManager.Replace_Tooltip:ØªØ­Ø¯ÙØ« Ø§ÙØªØ±Ø¬Ù
+Ø© Ø§ÙÙ
+Ø®ØªØ§Ø±Ø©
+CDM.TranslationManager.Translation:Ø§ÙÙØµ Ø§ÙÙ
+ØªØ±Ø¬Ù
+
+CDM.TranslationManager.Translation_Tooltip:Ø¥Ø¯Ø®Ù Ø§ÙØªØ±Ø¬Ù
+Ø© ÙÙØ§
+#*******************
+#
+#***** Collection *****
+Collection.Collection:<HTML><STRONG><FONT FACE={FONT} COLOR=Black>Ù
+Ø¬Ù
+ÙØ¹Ø©</FONT></STRONG></HTML>
+Collection.Delete_Tooltip:Ø¥ÙØºØ§Ø¡ Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª Ù Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±Ø©
+Collection.Filter_Tooltip:ØªÙÙÙØ¯ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙØžØ§ÙØ±Ø© ÙÙ ØŽØ¬Ø±Ø© Ø§ÙÙ
+ÙÙ
+Collection.New_Folder_Tooltip:Ø¥ÙØŽØ§Ø¡ Ù
+Ø¬ÙØ¯ Ø¬Ø¯ÙØ¯
+Collection.No_Collection:ÙØ§ØªÙØ¬Ø¯ Ù
+Ø¬Ù
+ÙØ¹Ø©
+Collection.No_Collection_Loaded:ÙÙ
+ ÙØªÙ
+ ØªØ­Ù
+ÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø©
+Collection.Stop:Ø¥ÙÙØ§Ù
+Collection.Stop_Tooltip:Ø¥ÙÙØ§Ù ÙØ³Ø® Ø§ÙÙ
+ÙÙØ§Øª
+Collection.Workspace:<HTML><STRONG><FONT FACE={FONT} COLOR=Black>Ù
+Ø³Ø§Ø­Ø© Ø§ÙØ¹Ù
+Ù</FONT></STRONG></HTML>
+#**********************
+#
+#***** CollectionBuilt *****
+CollectionBuilt.Message:ØªÙ
+ ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ù ÙÙ
+ÙÙ Ø¹Ø±Ø¶ÙØ§
+CollectionBuilt.Title:ÙØªÙØ¬Ø© Ø¥ÙØŽØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+#***************************
+#
+#***** CollectionManager *****
+CollectionManager.Build_Cancelled:ØªÙ
+ Ø¥ÙØºØ§Ø¡ ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©.
+CollectionManager.Cannot_Create_Collection:Ø­Ø¯Ø« Ø®Ø·Ø£ Ù ÙÙ
+ ÙØªÙ
+ ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©.
+CollectionManager.Cannot_Create_Collection_With_Reason:ÙÙ
+ ÙØªÙ
+ ØšÙØ§Ø¡ ÙØ°Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØšØ³ØšØš:\n{0-Error message}
+CollectionManager.Cannot_Delete_Index:ÙØ§ ÙÙ
+ÙÙ Ø¥Ø¹Ø§Ø¯Ø© ØšÙØ§Ø¡ ÙØ°Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØšØ³ØšØš Ø§Ù Ø§ÙÙØŽØ§ÙØ§Øª Ø§ÙÙØ¯ÙÙ
+Ø© ÙØ§ ÙÙ
+ÙÙ Ø¥ÙØºØ§Ø€ÙØ§.\nØ§ÙØ±Ø¬Ø§Ø¡ Ø§ÙØªØ£ÙØ¯ Ù
+Ù Ø§Ù ÙØ±ÙÙØ³ØªÙÙ  Ø£Ù Ø§Ù ØšØ±ÙØ§Ù
+Ø¬ Ø¢Ø®Ø± ÙØ§ ÙØ³ØªØ®Ø¯Ù
+ ÙØ°Ù Ø§ÙÙ
+ÙÙØ§Øª,\n Ù Ø­Ø§ÙÙ Ù
+Ø±Ø© Ø£Ø®Ø±Ù.
+CollectionManager.Cannot_Delete_Index_Log:ÙÙ
+ ÙØªÙ
+ Ø¥ÙØºØ§Ø¡ Ù
+ÙÙØ§Øª Ø§ÙÙØŽØ§ÙØ§Øª Ø§ÙÙØ¯ÙÙ
+Ø© ÙØ°ÙÙ ØªÙÙÙ Ø§ÙØ¥Ø³ØªÙØ±Ø§Ø¯.
+CollectionManager.Cannot_Open:ÙØ§ ÙÙ
+ÙÙ ÙØªØ­ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©:\n{0-Collection file path}\n.
+CollectionManager.Cannot_Open_With_Reason:Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙ:\n{0-Collection file path}\nÙØ§ ÙÙ
+ÙÙ ÙØªØ­ÙØ§ ØšØ³ØšØš:\n{1-Error message}
+CollectionManager.Creating_Collection:Ø¥ÙØŽØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø©  # Updated 29-Nov-2006 by kkhalafala
+CollectionManager.Creating_Collection_Please_Wait:Ø¥ÙØŽØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø© ØØ§ÙØ±Ø¬Ø§Ø¡Ø§ÙØ¥ÙØªØžØ§Ø±....  # Updated 29-Nov-2006 by kkhalafala
+CollectionManager.Loading_Collection:ØªØ­Ù
+ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+CollectionManager.Loading_Collection_Please_Wait:ØªØ­Ù
+ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©Ø Ø§ÙØ±Ø¬Ø§Ø¡ Ø§ÙØ¥ÙØªØžØ§Ø±...
+CollectionManager.Loading_Successful:Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙ
+Ø­Ù
+ÙØ© {0}.
+CollectionManager.Missing_Config:ÙØ§ ØªÙ
+ÙÙ ÙØ°Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ù
+ÙÙ ØªØ¬ÙÙØ² ØµØ§ÙØ­ collect.cfg
+CollectionManager.Not_Col_File:'{0}' ÙÙØ³ Ù
+ÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø© ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ (.col)
+CollectionManager.No_Config_File:ÙÙ
+ ÙØªÙ
+ Ø¥ÙØŽØ§Ø¡ Ù
+ÙÙ Ø§ÙØªØ¬ÙÙØ² ØšÙØ§Ø³Ø·Ø©  mkcol.pl.
+CollectionManager.Preview_Ready_Failed:Ø­Ø¯Ø« Ø®Ø·Ø£ ÙÙ
+ÙØ¹ Ø¹Ø±Ø¶ ÙØ°Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©.
+CollectionManager.Preview_Ready_Title:Ø­Ø§ÙØ© Ø¹Ø±Ø¶ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©.
+CollectionManager.Build_Not_Moved:ÙØ§ ÙÙ
+ÙÙ ØªØ­ÙÙÙ Ø¯ÙÙÙ Ø§ÙØšÙØ§Ø¡.
+CollectionManager.Index_Not_Deleted:ÙØ§ ÙÙ
+ÙÙ Ø¥ÙØºØ§Ø¡ Ø¯ÙÙÙ Ø§ÙÙØŽØ§Ù.
+CollectionManager.Install_Exception:ØªÙ
+ Ø±ØµØ¯ ØªØ¬Ø§ÙØ² Ø®ÙØ§Ù ØªØ«ØšÙØª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©:\n{0}\nØºØ§ÙØšØ§ ØšØ³ØšØš Ø¥Ø³ØªØ®Ø¯Ø§Ù
+ ØšØ±Ø§Ù
+Ø¬ Ø£Ø®Ø±Ù ÙÙÙ
+ÙÙØ§Øª .\nØ§ÙØ±Ø¬Ø§Ø¡ Ø§ÙØªØ£ÙØ¯ Ù
+Ù Ø£Ù Ù
+ØµØ§Ø¯Ø± Ù
+ÙÙØ§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©\nØºÙØ± Ù
+Ø³ØªØ®Ø¯Ù
+Ø© ØšÙØ§Ø³Ø·Ø© ØšØ±ÙØ§Ù
+Ø¬ Ø®Ø§Ø±Ø¬Ù, Ø«Ù
+ Ø£Ø¹Ø¯ Ø§ÙØšÙØ§Ø¡.
+#*****************************
+#
+#***** CollectionPopupMenu *****
+CollectionPopupMenu.Delete:Ø¥ÙØºØ§Ø¡
+CollectionPopupMenu.New_Dummy_Doc:ÙØ«ÙÙØ© Ù
+Ø²ÙÙØ© Ø¬Ø¯ÙØ¯Ø©
+CollectionPopupMenu.New_Folder:Ù
+Ø¬ÙØ¯ Ø¬Ø¯ÙØ¯
+CollectionPopupMenu.Rename:Ø¥Ø¹Ø§Ø¯Ø© ØªØ³Ù
+ÙØ©
+CollectionPopupMenu.Replace:Ø¥Ø³ØªØšØ¯Ø§Ù
+#*******************************
+#
+#***** CreatePane *****
+CreatePane.Build:Ø®ÙØ§Ø±Ø§Øª Ø§ÙØšÙØ§Ø¡
+CreatePane.Build_Tooltip:Ø®ÙØ§Ø±Ø§Øª ÙÙ
+Ø±Ø­ÙØ© Ø§ÙØªÙØŽÙÙ Ù Ø§ÙØªØµÙÙÙ ÙÙ ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+CreatePane.Build_Collection:ØšÙØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø©
+CreatePane.Build_Collection_Tooltip:Ø¥ØšØ¯Ø£ Ø¥Ø¬Ø±Ø§Ø¡ ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+CreatePane.Build_Progress:ØªØ·ÙØ± Ø§ÙØšÙØ§Ø¡
+CreatePane.Cancel_Build:Ø¥ÙØºØ§Ø¡ Ø§ÙØšÙØ§Ø¡
+CreatePane.Cancel_Build_Tooltip:Ø£ÙÙÙ Ø¥Ø¬Ø±Ø§Ø¡ ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+CreatePane.Full_Build:Ø¥Ø¹Ø§Ø¯Ø© ØšÙØ§Ø¡
+CreatePane.Full_Build_Tooltip:Ø¥ØšØ¯Ø£ Ø¥Ø¹Ø§Ø¯Ø©  ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ù
+Ù Ø¬Ø¯ÙØ¯
+CreatePane.Import:Ø®ÙØ§Ø±Ø§Øª Ø§ÙØ¥Ø³ØªÙØ±Ø§Ø¯
+CreatePane.Import_Tooltip:Ø®ÙØ§Ø±Ø§Øª ÙÙ
+Ø±Ø­ÙØ© ØªØ­ÙÙÙ Ø§ÙÙ
+ÙÙ Ù ØªØ¹ÙÙÙ  ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª ÙÙ ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+CreatePane.Import_Progress:ØªØ·ÙØ± Ø§ÙØ¥Ø³ØªÙØ±Ø§Ø¯
+CreatePane.Minimal_Build:Ø¥Ø¹Ø§Ø¯Ø© ØšÙØ§Ø¡ Ø§ÙØ­Ø¯ Ø§ÙØ£Ø¯ÙÙ
+CreatePane.Minimal_Build_Tooltip:Ø§Ø³Ø±Ø¹ ØØšØªØ¶Ù
+ÙÙ Ø§ÙØ£Ø¬Ø²Ø§Ø¡ Ø§ÙØ¶Ø±ÙØ±ÙØ© ÙÙØ· ÙÙ Ø¥Ø¬Ø±Ø§Ø¡ ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©  # Updated 29-Nov-2006 by kkhalafala
+CreatePane.Minimal_Build_Not_Required:Ø¥Ø¹Ø§Ø¯Ø© Ø§ÙØšÙØ§Ø¡ ÙÙØ³Øª Ù
+Ø·ÙÙØšØ© ÙØ§ÙÙ ÙÙ
+ ØªÙÙ
+ ØšØ¥Ø¶Ø§ÙØ© Ø¢Ù Ù
+ÙÙ ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø©ØØªØ¹Ø¯ÙÙ ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§ØªØ Ø§Ù ØªØºÙÙØ± Ø®ÙØ§Ø±Ø§Øª ÙÙ Ø­ÙØ² Ø§ÙØªØµÙ
+ÙÙ
+\nÙØ¥Ø¬ØšØ§Ø± Ø¥Ø¹Ø§Ø¯Ø© ØšÙØ§Ø¡ Ø§ÙØ±Ø¬Ø§Ø¡ Ø¥Ø®ØªÙØ§Ø± "Ø¥Ø¹Ø§Ø¯Ø© ØšÙØ§Ø¡ ÙØ§Ù
+ÙØ©" Ù Ø¥Ø¶ØºØ· Ø²Ø± "ØšÙØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø©"  # Updated 29-Nov-2006 by kkhalafala
+CreatePane.Log:Ù
+ÙÙ Ø§ÙØ³Ø¬Ù
+CreatePane.Log_Tooltip:Ø¹Ø±Ø¶ Ù
+Ø®Ø±Ø¬Ø§Øª Ù
+Ø­Ø§ÙÙØ§Øª ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙØ³Ø§ØšÙØ©
+CreatePane.Mode_All:ÙÙ
+CreatePane.Options:Ø®ÙØ§Ø±Ø§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª
+CreatePane.Options_Title:Ø®ÙØ§Ø±Ø§Øª ØšÙØ§Ø¡ Ù Ø¥Ø³ØªÙØ±Ø§Ø¯ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+CreatePane.Preview_Collection:Ø¹Ø±Ø¶ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+CreatePane.Preview_Collection_Tooltip:Ø¹Ø±Ø¶ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+#**********************
+#
+#***** Dates *****
+Dates.Mon:Ø§ÙØ£Ø«ÙÙÙ
+Dates.Tue:Ø§ÙØ«ÙØ§Ø«Ø§Ø¡
+Dates.Wed:Ø§ÙØ£Ø±ØšØ¹Ø§Ø¡
+Dates.Thu:Ø§ÙØ®Ù
+ÙØ³
+Dates.Fri:Ø§ÙØ¬Ù
+Ø¹Ø©
+Dates.Sat:Ø§ÙØ³ØšØª
+Dates.Sun:Ø§ÙØ£Ø­Ø¯
+Dates.Jan:ÙÙØ§ÙØ±
+Dates.Feb:ÙØšØ±Ø§ÙØ±
+Dates.Mar:Ù
+Ø§Ø±Ø³
+Dates.Apr:Ø§ØšØ±ÙÙ
+Dates.May:Ù
+Ø§ÙÙ
+Dates.Jun:ÙÙÙÙÙ
+Dates.Jul:ÙÙÙÙÙ
+Dates.Aug:Ø£ØºØ³Ø·Ø³
+Dates.Sep:Ø³ØšØªÙ
+ØšØ±
+Dates.Oct:Ø§ÙØªÙØšØ±
+Dates.Nov:ÙÙÙÙ
+ØšØ±
+Dates.Dec:Ø¯ÙØ³Ù
+ØšØ±
+#**********************
+#
+#***** Delete Collection Prompt *****
+DeleteCollectionPrompt.Collection_Details:ØªÙØ§ØµÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙ
+Ø®ØªØ§Ø±Ø©
+DeleteCollectionPrompt.Collection_List:Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙÙ
+ØªÙÙØ±Ø©
+DeleteCollectionPrompt.Confirm_Delete:Ø§ÙØ±Ø¬Ø§Ø¡ ØªØ£ÙÙØ¯ Ø¥ÙØºØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+DeleteCollectionPrompt.Delete:Ø¥ÙØºØ§Ø¡
+DeleteCollectionPrompt.Delete_Tooltip:Ø¥ÙØºØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙ
+Ø®ØªØ§Ø±Ø©
+DeleteCollectionPrompt.Details:Ù
+ÙØŽÙ - {0}\nÙ
+Ø§ÙÙ - {1}\nÙØµÙ\n{2}
+DeleteCollectionPrompt.Failed_Delete:ÙØ§ ÙÙ
+ÙÙ Ø¥ÙØºØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØªÙ
+Ø§Ù
+Ø§.
+DeleteCollectionPrompt.Failed_Title:ÙØŽÙ Ø§ÙØ¥ÙØºØ§Ø¡
+DeleteCollectionPrompt.No_Collection:ÙØ§ ØªÙØ¬Ø¯ Ù
+Ø¬Ù
+ÙØ¹Ø© Ù
+Ø®ØªØ§Ø±Ø©.
+DeleteCollectionPrompt.Successful_Delete:ØªÙ
+ Ø¥ÙØºØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©.
+DeleteCollectionPrompt.Successful_Title:Ø¥ÙØªÙ
+ÙØª Ø¹Ù
+ÙÙØ© Ø§ÙØ¥ÙØºØ§Ø¡!
+DeleteCollectionPrompt.Title:Ø¥ÙØºØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+#**********************
+#
+#***** DirectoryLevelMetadata *****
+DirectoryLevelMetadata.Message:Ø£ÙØª ØšØµØ¯Ø¯ ØªØ¹ÙÙÙ ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª  'ÙÙ
+Ø³ØªÙÙ Ø§ÙÙ
+Ø¬ÙØ¯' ÙÙÙ
+Ø¬ÙØ¯ Ø§ÙÙ
+Ø®ØªØ§Ø±  (Ø£Ù Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±Ø©). Ø³ÙÙ ÙØªÙ
+ ØªÙØ±ÙØ« ÙØ°Ù Ø§ÙÙØ§ØµÙØ§Øª Ø¢ÙÙØ§ ÙÙÙ Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª Ø§ÙÙØ±Ø¹ÙØ© Ù Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙØªØ§ØšØ¹Ø© ÙÙØ°Ø§ Ø§ÙÙ
+Ø¬ÙØ¯. ÙÙØšØºÙ Ø£Ù ÙØ°ÙØ± ÙÙØ§ Ø§Ù ÙØ°Ù Ø§ÙÙØ§ØµÙØ§Øª ÙØ§ ÙÙ
+ÙÙ Ø¥ÙØºØ§Ø€ÙØ§ Ø£Ù ØªØºÙÙØ±ÙØ§ Ø¥ÙØ§ Ø¹ÙÙ Ù
+Ø³ØªÙÙ Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙØ£Øš. ÙØ¥ÙÙ
+Ø§Ù ÙØ°Ø§ Ø§ÙØ¥Ø¬Ø±Ø§Ø¡  Ø§ÙØ±Ø¬Ø§Ø¡ Ø§ÙÙÙØ± Ø¹ÙÙ 'OK'.
+DirectoryLevelMetadata.Title:Ø¥Ø¶Ø§ÙØ© ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+Ø³ØªÙÙ Ø§ÙÙ
+Ø¬ÙØ¯
+
+#*******************
+#
+#***** Download *****
+DOWNLOAD.MODE.Root:ØªÙØ²ÙÙ Ø£Ø³Ø§Ø³Ù
+DOWNLOAD.MODE.WebDownload:Ø§ÙÙØš
+DOWNLOAD.MODE.OAIDownload:OAI
+DOWNLOAD.MODE.ZDownload:Z39.50
+DOWNLOAD.MODE.SRWDownload:SRW
+
+Download.ServerInformation:Ù
+Ø¹ÙÙÙ
+Ø§Øª Ø§ÙÙ
+Ø²ÙØ¯
+Download.ServerInformation_Tooltip:ØªÙØ²ÙÙ ØšØ¹Ø¶ Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª Ø­ÙÙ Ø§ÙÙ
+Ø²ÙØ¯Ø Ù ÙØ­Øµ Ø§ÙØ¥ØªØµØ§Ù Ø§ÙØ°Ù ÙÙ
+ÙÙ Ø£Ù ÙÙÙÙ
+
+#********************
+#
+#***** EnrichPane *****
+EnrichPane.AutoMessage:ÙØ°Ø§ Ø§ÙØ¹ÙØµØ± , {0}, ÙÙØªÙ
+Ù ÙÙ
+Ø¹ÙØ§Ø± ÙØ±ÙÙØ³ØªÙÙ ÙÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª. ÙØ°Ø§ Ø§ÙÙ
+Ø¹ÙØ§Ø± ÙÙ
+Ø«Ù  ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø³ØªØ®Ø±Ø¬Ø© Ø¢ÙÙØ§. ÙÙØ­Øµ Ø£Ù  {0} ÙØ§ØµØ§ÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙ
+ÙÙ Ø¥Ø³ØªØ®Ø±Ø§Ø¬ÙØ§ Ø£ØšÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØšØ¥Ø³ØªØ®Ø¯Ø§Ù
+  'Ø¥ÙØŽØ§Ø¡' .
+EnrichPane.ExistingValues:Ø§ÙÙÙÙ
+ Ø§ÙÙ
+ÙØ¬ÙØ¯Ø©
+EnrichPane.InheritedMetadataSelected:Ø§ÙÙÙÙ
+ Ø§ÙÙ
+Ø¶Ù
+ÙØ© Ø§ÙÙ
+Ø®ØªØ§Ø±Ø©
+EnrichPane.InheritedMetadata_Tooltip:Ø§ÙÙÙÙ
+ Ø§ÙÙ
+Ø¶Ù
+ÙØ©
+EnrichPane.ManageMetadataSets:Ø¥Ø¯Ø§Ø±Ø© Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª
+EnrichPane.ManageMetadataSets_Tooltip:Ø¥Ø¯Ø§Ø±Ø© Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª
+EnrichPane.No_File:ÙÙ
+ ÙØªÙ
+ Ø¥Ø®ØªÙØ§Ø± Ù
+ÙÙ
+EnrichPane.No_Metadata:ÙØ§ ÙÙØ¬Ø¯ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+ØªÙÙØ±
+EnrichPane.No_Metadata_Element:<HTML><STRONG><FONT FACE={FONT} COLOR=Black>ÙÙ
+ ÙØªÙ
+ Ø¥Ø®ØªÙØ§Ø± Ø¹ÙØµØ± Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª</FONT></STRONG></HTML>
+EnrichPane.NotOneFileOnlyMetadataSelected:ÙØ§ ÙÙ
+ÙÙ ØªØ­Ø¯ÙØ« ÙØ§ØµÙØ© Ø§ÙØšÙØ§ÙØ§Øª ÙØ°Ù ÙØ§ÙÙØ§ ÙØ§ ØªÙØ·ØšÙ Ø¹ÙÙ ÙØ°Ø§ Ø§ÙÙ
+ÙÙ ÙØ­Ø¯Ù.
+EnrichPane.Value_Field_Tooltip:ÙÙÙ
+Ø© ÙØªØ¹ÙÙÙØ§ ÙØ¹ÙØµØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±
+EnrichPane.Value_Field_Tooltip_Uneditable:Ø§ÙÙÙÙ
+Ø© Ø§ÙØªÙ Ø¹ÙÙØª ÙØ¹ÙØµØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±
+#***********************
+#
+#****** ExplodeMetadataPrompt *******
+ExplodeMetadataPrompt.Explode:ØªØ¬Ø²ØŠØ©
+ExplodeMetadataPrompt.Explode_Tooltip:ØªØ¬Ø²ØŠØ© Ù
+ÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª
+ExplodeMetadataPrompt.Instructions:ØªØ¬Ø²ØŠØ© Ù
+ÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙØ°Ø§ Ø³ÙÙ ÙÙØªØ¬ ØªØ³Ø¬ÙÙØ§Øª ÙØ±Ø¹ÙØ© ØšÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª ÙØ§ØšÙØ© ÙÙØªØ¹Ø¯ÙÙ.ÙØ°Ø§ Ø¥Ø¬Ø±Ø§Ø¡ ØºÙØ± Ù
+Ø¹ÙÙØ³ Ù Ø³ÙÙ ÙØªÙ
+ Ø­Ø°Ù ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØ£ØµÙÙØ© Ù
+Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©.
+ExplodeMetadataPrompt.Failed_Title:ØªØ¬Ø²ØŠØ© .
+ExplodeMetadataPrompt.Failed_Explode:ÙÙ
+ ØªØªÙ
+ ØªØ¬Ø²ØŠØ© ÙØ§Ø¹Ø¯Ø© Ø§ÙØšÙØ§ÙØ§Øª {0} .
+ExplodeMetadataPrompt.NotExplodable:ÙØ°Ø§ Ø§ÙÙ
+ÙÙ ØºÙØ± ÙØ§ØšÙ ÙÙØªØ¬Ø²ØŠØ©.
+ExplodeMetadataPrompt.Successful_Explode:ØªÙ
+Øª Ø§ÙØªØ¬Ø²ØŠØ© ØšÙØ¬Ø§Ø­ ÙÙØ§Ø¹Ø¯Ø© Ø§ÙØšÙØ§ÙØ§Øª {0}
+ExplodeMetadataPrompt.Successful_Title:Ø¥ÙØªÙ
+ÙØª Ø§ÙØªØ¬Ø²ØŠØ©.
+ExplodeMetadataPrompt.Title:ØªØ¬Ø²ØŠØ© ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª ÙØ§Ø¹Ø¯Ø© ØšÙØ§ÙØ§Øª
+ExplodeMetadataPrompt.Plugin:Ø§ÙÙ
+ÙØ§ØšØ³ Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+ ÙÙØªØ¬Ø²ØŠØ©
+#***********************
+#
+#****** WriteCDImagePrompt *******
+WriteCDImagePrompt.CD_Name:CD/DVD Ø¥Ø³Ù
+
+WriteCDImagePrompt.Export:ØªØµØ¯ÙØ± CD/DVD
+WriteCDImagePrompt.Export_Tooltip:ØªØµØ¯ÙØ± Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±Ø© ÙÙØ±Øµ Ø¹ÙÙ Ù
+ÙØµØ©  ØšØ±Ø§Ù
+Ø¬ Ø§ÙÙÙØ§ÙØ°
+WriteCDImagePrompt.Failed_Export:ÙÙ
+ ÙØªÙ
+ ØªØµØ¯ÙØ± Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ({0}) .
+WriteCDImagePrompt.Failed_Title:ÙØŽÙ Ø§ÙØªØµØ¯ÙØ±
+WriteCDImagePrompt.Install:CD/DVD Ø³ÙÙ ÙØ«ØšØª ØšØ¹Ø¶ Ø§ÙÙ
+ÙÙØ§Øª Ø¹ÙØ¯ Ø§ÙØ¥Ø³ØªØ®Ø¯Ø§Ù
+ (Ø£Ø³Ø±Ø¹)
+WriteCDImagePrompt.Install_Tooltip:ÙÙØªØ¬  CD-ROM Ø°Ø§ØªÙ Ø§ÙØªØ«ØšÙØª ÙØ«ØšÙØª Ù
+Ø²ÙØ¯ Ø§ÙÙ
+ÙØªØšØ©  (Ù Ø¥Ø®ØªÙØ§Ø±ÙØ§ ÙÙ Ù
+ÙÙØ§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©) ÙÙ Ø§ÙØ¬ÙØ§Ø² Ø§ÙÙ
+Ø¶ÙÙ
+WriteCDImagePrompt.NoInstall:CD/DVD ÙÙ ÙØ«ØšØª Ø£Ù Ù
+ÙÙØ§Øª Ø¹ÙØ¯ Ø§ÙØ¥Ø³ØªØ®Ø¯Ø§Ù
+
+WriteCDImagePrompt.NoInstall_Tooltip:ÙØªÙ
+ ØªØŽØºÙÙ Ø§ÙÙ
+ÙØªØšØ© Ù
+ØšØ§ØŽØ±Ø© Ù
+Ù Ø§ÙÙØ±Øµ ØšØ¯ÙÙ ØªØ«ØšÙØª Ø§Ù ØŽÙÙ ÙÙ Ø§ÙØ¬ÙØ§Ø² Ø§ÙÙ
+Ø¶ÙÙ
+WriteCDImagePrompt.Instructions:ØªØµØ¯ÙØ± Ù
+Ø¬Ù
+ÙØ¹Ø© Ø£Ù Ø£ÙØ«Ø± ÙÙØ±Øµ ØªØŽØºÙÙ Ø°Ø§ØªÙ Ø¹ÙÙ Ù
+ÙØµØ© (ØšØ§ÙØ±ØºÙ
+ Ù
+Ù Ø¥ØªØ§Ø­Ø© Ø§ÙØªØµØ¯ÙØ± Ø¹ÙÙ Ø£ÙØ«Ø± Ù
+Ù Ù
+ÙØµØ©, Ø¥ÙØ§ Ø§Ù ÙØ°Ø§ Ø§ÙÙØ±Øµ ÙØªÙ
+ ØªØŽØºÙÙÙ ÙÙØ· Ù
+Ù Ù
+ÙØµØ© ØšØ±Ø§Ù
+Ø¬ Ø§ÙÙÙØ§ÙØ°).
+WriteCDImagePrompt.Progress_Label:ÙØ³Ø® Ù
+ÙÙØ§Øª. ÙØ¯ ÙØ³ØªØºØ±Ù ÙØ°Ø§ ÙÙØªØ§...
+WriteCDImagePrompt.Size_Label:Ø§ÙØ­Ø¬Ù
+ Ø§ÙÙ
+ØªÙÙØ¹:
+WriteCDImagePrompt.Successful_Export:ØªÙ
+ ØªØµØ¯ÙØ± Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª ({0})
+WriteCDImagePrompt.Successful_Title:Ø¥ÙØªÙ
+ÙØª Ø¥Ø¬Ø±Ø§Ø¡Ø§Øª Ø§ÙØªØµØ¯ÙØ±
+WriteCDImagePrompt.Title:ØªØµØ¯ÙØ± Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙ CD/DVD
+#************************
+#
+#****** ExportAsPrompt *******
+ExportAsPrompt.Export_Name:Ø¥Ø³Ù
+ Ø¯ÙÙÙ Ø§ÙØªØµØ¯ÙØ±
+ExportAsPrompt.Export_Name_Tooltip:Ø¥Ø³Ù
+ Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙØ°Ù ØªØ­ÙØž ÙÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙÙ
+ØµØ¯Ø±Ø© ÙÙ Ù
+Ø³Ø§Ø±Greenstone tmp  # Updated 29-Nov-2006 by kkhalafala
+ExportAsPrompt.Export:ØªØµØ¯ÙØ± Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª
+ExportAsPrompt.Export_Tooltip:ØªØµØ¯ÙØ± Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±Ø© ÙÙ ÙÙØŠØ© Ø§ÙÙ
+ÙÙ Ø§ÙÙ
+Ø®ØªØ§Ø± Ø§ÙÙ Ø§ÙÙ
+Ø³Ø§Ø±  Ø§ÙÙ
+Ø­Ø¯Ø¯
+ExportAsPrompt.Failed_ExportOne:ÙÙ
+ ÙØªÙ
+ ØªØµØ¯ÙØ± Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©, {0},
+ExportAsPrompt.Failed_ExportMany:ÙÙ
+ ÙØªÙ
+ ØªØµØ¯ÙØ± Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª -- {0} --
+ExportAsPrompt.Failed_Details:Ø§ÙØžØ± {1} ÙÙØªÙØ§ØµÙÙ
+ExportAsPrompt.Failed_Title:ÙØŽÙ Ø§ÙØªØµØ¯ÙØ±
+ExportAsPrompt.Instructions:ØªØµØ¯ÙØ± Ù
+Ø¬Ù
+ÙØ¹Ø© Ø£Ù Ø£ÙØ«Ø± ÙÙ ÙÙØŠØ© Ø§ÙÙ
+ÙÙ Ø§ÙÙ
+Ø®ØªØ§Ø±Ø© Ø¥ÙÙ Ø§ÙÙ
+Ø³Ø§Ø± Ø§ÙÙ
+ØŽØªØ±Ø·
+ExportAsPrompt.Progress_Label:ØªØµØ¯ÙØ± Ù
+ÙÙØ§Øª. ÙØ¯ ÙØ³ØªØºØ±Ù ÙØ°Ø§ ÙÙØªØ§...
+ExportAsPrompt.Successful_ExportOne:ØªÙ
+ ØªØµØ¯ÙØ± Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©, {0},
+ExportAsPrompt.Successful_ExportMany:ØªÙ
+ ØªØµØ¯ÙØ± Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª -- {0} --
+ExportAsPrompt.Successful_Details:Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+ØµØ¯Ø±Ø© Ø¥ÙÙ: {1}
+ExportAsPrompt.Successful_Title:Ø¥ÙØªÙ
+ÙØª Ø¥Ø¬Ø±Ø§Ø¡Ø§Øª Ø§ÙØªØµØ¯ÙØ±
+ExportAsPrompt.Title:ØªØµØ¯ÙØ± Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª
+ExportAsPrompt.SaveAs:ØªØµØ¯ÙØ± Ø¥ÙÙ
+ExportAsPrompt.SaveAs_Tooltip:Ø¥Ø®ØªØ± Ø§ÙÙØ³Ù Ø§ÙØ°Ù ØªÙØ¯ Ø§ÙØªØµØ¯ÙØ± Ø¥ÙÙÙ
+ExportAsPrompt.Cancel:Ø¥ÙØºØ§Ø¡
+ExportAsPrompt.Cancel_Tooltip:Ø¥ÙØºØ§Ø¡ Ø¥Ø¬Ø±Ø§Ø¡ Ø§ÙØªØµØ¯ÙØ±
+ExportAsPrompt.Browse:ØªØµÙØ­
+ExportAsPrompt.Browse_Tooltip:Ø¥Ø®ØªÙØ§Ø± Ù
+ÙÙ xsl
+ExportAsPrompt.ApplyXSL:ØªØ·ØšÙÙ Ù
+ÙÙ  XSL Ø¥ÙÙ {0}
+ExportAsPrompt.ApplyXSL_Tooltip:Ø¥Ø³ØªØ®Ø¯Ø§Ù
+ Ù
+ÙÙ  xsl ÙØªØ­ÙÙÙ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+ØµØ¯Ø±Ø©.
+ExportAsPrompt.MARCXMLGroup:Ù
+Ø¬Ù
+ÙØ¹Ø© ØªØ³Ø¬ÙÙØ§Øª Ù
+Ø§Ø±Ù
+ExportAsPrompt.MARCXMLGroup_Tooltip:ØªØµØ¯ÙØ± ØªØ³Ø¬ÙÙØ§Øª Ù
+Ø§Ø±Ù ÙÙ Ù
+ÙÙ ÙØ§Ø­Ø¯.
+ExportAsPrompt.MappingXML:ØªØ·ØšÙÙ Ø§ÙÙ
+ÙÙ Ø§ÙØªØ®Ø·ÙØ·Ù
+ExportAsPrompt.MappingXML_Tooltip:Ø¥Ø³ØªØ®Ø¯Ù
+ Ø§ÙÙ
+ÙÙ Ø§ÙØªØ®Ø·ÙØ·Ù ÙØªØ­ÙÙÙ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+ØµØ¯Ø±Ø©
+#************************
+#
+#*****ExternalCollectionPrompt********
+ExternalCollectionPrompt.NewMDS:Ø¥ÙØŽØ§Ø¡ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØ¬Ø¯ÙØ¯ Ù Ø§ÙÙØ§Ø±Øº.
+ExternalCollectionPrompt.ExistingMDS:Ø¥Ø®ØªÙØ§Ø± Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙØ§Ø­Ø¯ Ø§Ù Ø£ÙØ«Ø±
+ExternalCollectionPrompt.Title:ØªØ­Ù
+ÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø© Ø®Ø§Ø±Ø¬ÙØ©
+ExternalCollectionPrompt.Instructions_1:Ø£ÙØª ØšØµØ¯Ø¯ ØªØ­Ù
+ÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø© ÙÙ
+ ÙØªÙ
+ Ø¥ÙØŽØ§Ø€ÙØ§ ØšÙØ§Ø³Ø·Ø©GLI . Ø³ÙÙ  ÙØ·ÙØš Ù
+ÙÙ Ø¥Ø®ØªÙØ§Ø± Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø£Ù Ø£ÙØ«Ø± ÙØ¥Ø³ØªØ®Ø¯Ø§Ù
+ÙØ§ Ù
+Ø¹ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©. ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+ÙØ¬ÙØ¯Ø© Ø³ÙÙ ÙØªÙ
+ Ø¥Ø³ØªÙØ±Ø§Ø¯ÙØ§ ÙÙ
+Ø¹ÙØ§Ø± Ø£Ù Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±Ø©. Ù
+ÙÙØ§Øª  ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØ£ØµÙÙØ© Ø³ÙÙ ÙØªÙ
+ Ø­ÙØžÙØ§ ÙÙ Ù
+Ø¬ÙØ¯ ÙØ³Ù
+Ù import.bak.
+ExternalCollectionPrompt.Instructions_2:Ø£ÙØª ØšØµØ¯Ø¯ ØªØ­Ù
+ÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø© ÙÙ
+ ÙØªÙ
+ Ø¥ÙØŽØ§Ø€ÙØ§ ØšÙØ§Ø³Ø·Ø© GLI. Ø³ÙÙ ØªØ­ØªØ§Ø¬ ÙØ¥Ø¶Ø§ÙØ© Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙØ°Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©. ÙÙ
+ÙÙÙ Ø¥ÙØŽØ§Ø¡ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø¬Ø¯ÙØ¯Ø© Ù Ø§ÙØªÙ Ø³ÙÙ ÙØªÙ
+ Ø¥Ø³ØªÙØ±Ø§Ø¯ ÙÙ Ø¹ÙØ§ØµØ± Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+ÙØ¬ÙØ¯Ø© Ø¢ÙÙØ§. Ø£Ù ØšØ¯ÙØ§ ÙÙ
+ÙÙÙ Ø¥Ø®ØªÙØ§Ø± Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+ÙØ¬ÙØ¯Ø©, ÙØ³ÙÙ ÙØªÙ
+ Ø¥Ø¶Ø§ÙØ© Ø¹ÙØ§ØµØ± Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø£Ù Ø¯Ù
+Ø¬ÙØ§ Ù
+Ø¹ Ø§ÙØ¹ÙØ§ØµØ± Ø§ÙÙ
+ÙØ¬ÙØ¯Ø© ÙØšÙØ§ ÙÙ ÙØ°Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª. Ù
+ÙÙØ§Øª Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØ£ØµÙÙØ© Ø³ÙÙ ÙØªÙ
+ Ø­ÙØžÙØ§ ÙÙ Ù
+Ø¬ÙØ¯ ÙØ³Ù
+Ù import.bak.
+
+#****************************************
+#
+#***** Inherited Metadata *****
+ExtractedMetadata.Message:Ø§ÙÙ
+ÙÙ Ø£Ù Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙÙ
+Ø®ØªØ§Ø± ÙØªØ¶Ù
+Ù ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª ØÙÙÙÙÙØ§ Ù
+Ø®ÙÙØ© Ø­Ø§ÙÙØ§.ÙØ¹Ø±Ø¶ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙØªÙ
+ Ø¥Ø®ØªÙØ§Ø± ÙØ§ØŠÙ
+Ø© 'Ù
+ÙÙ' Ø«Ù
+ Ø¥Ø®ØªÙØ§Ø± 'ØªÙØ¶ÙÙØ§Øª' Ø«Ù
+ Ø¥Ø®ØªÙØ§Ø± 'Ø¹Ø§Ù
+' Ø«Ù
+ Ø¥Ø®ØªÙØ§Ø± 'Ø¹Ø±Ø¶ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø³ØªØ®Ø±Ø¬Ø©' Ù Ø§ÙÙÙØ± Ø¹ÙÙ "[O]k".
+ExtractedMetadata.Title:ÙØ°Ø§ Ø§ÙÙ
+ÙÙ/Ø§ÙÙ
+Ø¬ÙØ¯ ÙØªØ¶Ù
+Ù ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+Ø®ÙÙØ©
+#
+#***** FileActions *****
+FileActions.Calculating_Size:Ø­Ø³Ø§Øš Ø§ÙØ­Ø¬Ù
+ Ø§ÙÙÙÙ ÙÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±Ø©
+FileActions.Copying:ÙØ³Ø® {0}
+FileActions.Could_Not_Delete:ÙØ§ ÙÙ
+ÙÙ Ø¥ÙØºØ§Ø€Ù
+FileActions.Cyclic_Path:ÙØ§ ÙÙ
+ÙÙ ÙØ³Ø®{0}:Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙÙØ¯Ù ÙÙ Ù
+Ø¬ÙØ¯ ÙØ±Ø¹Ù ÙÙ Ù
+Ø¬ÙØ¯ Ø§ÙÙ
+ØµØ¯Ø±  # Updated 29-Nov-2006 by kkhalafala
+FileActions.Deleting:Ø¥ÙØºØ§Ø¡ {0}
+FileActions.Directories_Selected:{0} Ù
+Ø¬ÙØ¯Ø§Øª Ù
+Ø®ØªØ§Ø±Ø©
+FileActions.Directory_Selected:1 Ù
+Ø¬ÙØ¯ Ù
+Ø®ØªØ§Ø±
+FileActions.File_Already_Exists_No_Create:Ø§ÙÙ
+ÙÙ '{0}' Ù
+ÙØ¬ÙØ¯ Ù
+Ù ÙØšÙ.
+FileActions.File_Already_Exists_Message:{0}\nØ§ÙÙ
+ÙÙ ØšØ§ÙØ§Ø³Ù
+ Ø§ÙÙ
+ÙØ¶Ø­ Ø£Ø¹ÙØ§Ù Ù
+ÙØ¬ÙØ¯ Ù
+Ù ÙØšÙ ÙÙ Ø§ÙÙ
+Ø³Ø§Ø± Ø§ÙÙØ¯Ù Ø ØšØ§ÙØ±ØºÙ
+ Ù
+Ù Ø¥Ø®ØªÙØ§Ø±Ù Ø§ÙØ³Ø§ØšÙ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ \nØºÙØ± ÙØ§Ø¯Ø±Ø© Ø¹ÙÙ Ø§ÙÙØªØ§ØšØ© ÙÙÙÙ. Ø§ÙØ±Ø¬Ø§Ø¡ ÙØ­Øµ Ø£Ø°ÙÙØ§Øª Ø§ÙÙ
+ÙÙ.
+FileActions.File_Already_Exists_Title:Ø®Ø·Ø£ - Ø§ÙÙ
+ÙÙ Ù
+ÙØ¬ÙØ¯ Ù
+Ù ÙØšÙ.
+FileActions.File_And_Directories_Selected:1 Ù
+ÙÙ Ù {0} Ù
+Ø¬ÙØ¯Ø§Øª Ù
+Ø®ØªØ§Ø±Ø©
+FileActions.File_And_Directory_Selected:1 Ù
+ÙÙ Ù {0} Ù
+Ø¬ÙØ¯ Ù
+Ø®ØªØ§Ø±
+FileActions.File_Create_Error:ÙØ§ ÙÙ
+ÙÙ Ø¥ÙØŽØ§Ø¡ Ø§ÙÙ
+ÙÙ {0}
+FileActions.Folder_Create_Error:ÙØ§ ÙÙ
+ÙÙ Ø¥ÙØŽØ§Ø¡ Ø§ÙÙ
+Ø¬ÙØ¯ {0} .
+FileActions.File_Exists:<html>{0} Ù
+ÙØ¬ÙØ¯ Ù
+Ù ÙØšÙ ÙÙ Ø§ÙÙ
+ÙÙ Ø§ÙÙØ¯Ù. ÙÙ ØªÙØ¯ Ø§ÙÙØªØ§ØšØ© ÙÙÙÙ?</html>
+FileActions.File_Move_Error_Message:ÙØ§ ÙÙ
+ÙÙ ØªØ­Ø±ÙÙ {0} Ø¥ÙÙ\n{1}.
+FileActions.File_Not_Deleted_Message:{0}\nÙØ§ ÙÙ
+ÙÙ Ø¥ÙØºØ§Ø¡ Ø§ÙÙ
+ÙÙ ØšØ§ÙØ¥Ø³Ù
+ Ø£Ø¹ÙØ§Ù. \nØ§ÙØ±Ø¬Ø§Ø¡ ÙØ­Øµ Ø¥Ø°Ø§ Ù
+Ø§ ÙØ§Ù ÙØ°Ø§ Ø§ÙÙ
+ÙÙ Ù
+ÙØªÙØ­Ø§ Ù
+Ù ÙØšÙ\nØšØ±ÙØ§Ù
+Ø¬ Ø®Ø§Ø±Ø¬Ù. Ø«Ù
+ Ø­Ø§ÙÙ Ù
+Ø±Ø© Ø£Ø®Ø±Ù.
+FileActions.File_Not_Deleted_Title:Ø®Ø·Ø£ - ÙÙ
+ ÙØªÙ
+ Ø¥ÙØºØ§Ø¡ Ø§ÙÙ
+ÙÙ.
+FileActions.File_Not_Found_Message:{0}\nÙÙ
+ ÙØªÙ
+ Ø§ÙØ¹Ø«ÙØ± Ø¹ÙÙ Ø§ÙÙ
+ÙÙ ØšØ§ÙØ§Ø³Ù
+ Ø£Ø¹ÙØ§Ù. Ø¥Ø°Ø§ ØªÙ
+ Ø¥ÙØ¹Ø§ØŽ \nØ¹Ø±Ø¶ Ø§ÙÙ
+ÙÙ, Ø§ÙØ±Ø¬Ø§Ø¡ ÙØ­Øµ ÙØ¬ÙØ¯ Ø§ÙÙ
+ÙÙ.
+FileActions.File_Not_Found_Title:Ø®Ø·Ø£ - Ø§ÙÙ
+ÙÙ ØºÙØ± Ù
+ÙØ¬ÙØ¯.
+FileActions.File_Selected:1 Ù
+ÙÙ Ù
+Ø®ØªØ§Ø±
+FileActions.Files_And_Directory_Selected:{0} Ù
+ÙÙØ§Øª Ù 1 Ù
+Ø¬ÙØ¯ Ù
+Ø®ØªØ§Ø±
+FileActions.Files_Selected:{0} Ù
+ÙÙØ§Øª Ù
+Ø®ØªØ§Ø±Ø©
+FileActions.Folder_Already_Exists:Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙÙ
+Ø³Ù
+Ù  '{0}' ÙÙØ¯ Ø§ÙØ¥Ø³ØªØ®Ø¯Ø§Ù
+.ÙØ§ ÙÙ
+ÙÙ Ø¥ÙØŽØ§Ø¡ Ù
+Ø¬ÙØ¯.
+FileActions.Increase_Depth:Ø²ÙØ§Ø¯Ø© Ø§ÙØ¹Ù
+Ù Øš 1
+FileActions.Insufficient_Space_Message:ÙØŽÙ Ø§ÙØ¥Ø¬Ø±Ø§Ø¡ Ø§ÙÙ
+Ø·ÙÙØš ÙØ¹Ø¯Ù
+ ÙØ¬ÙØ¯ \nÙ
+Ø³Ø§Ø­Ø© ÙØ§ÙÙØ© ØšØ§ÙÙØ±Øµ. ÙÙØ³Ø® Ø§ÙÙ
+ÙÙ ØšÙØ¬Ø§Ø­ Ø³ÙÙ ØªØ­ØªØ§Ø¬ Ø§ÙÙ Ù
+Ø³Ø§Ø­Ø© \nØ¥Ø¶Ø§ÙÙØ©: {0}
+FileActions.Insufficient_Space_Title:Ø®Ø·Ø£ - Ù
+Ø³Ø§Ø­Ø© ØºÙØ± ÙØ§ÙÙØ©
+FileActions.Moving:ØªØ­Ø±ÙÙ {0}
+FileActions.No_Activity:ÙØ§ ÙÙØ¬Ø¯ Ø¥Ø¬Ø±Ø§Ø¡ Ù
+Ø·ÙÙØš
+FileActions.Possible_Cyclic_Path:{1} ÙÙ ØšØ¹Ù
+Ù {0} Ù
+Ø³Ø§Ø±Ø§Øª Ù Ø±ØšÙ
+Ø§ ÙÙÙÙ Ù
+Ø³Ø§Ø±Ø§ Ù
+ØªÙØ±Ø±Ø§ØÙÙ ÙØ³ØªÙ
+Ø± Ø¥Ø¬Ø±Ø§Ø¡ Ø§ÙÙ
+ÙÙØ
+FileActions.Read_Not_Permitted_Message:ÙØ§ ÙÙ
+ÙÙ ÙØ±Ø§Ø¡Ø© {0}.
+FileActions.Read_Only:Ø§ÙÙ
+ÙÙØ§Øª ÙÙ Ù
+Ø³Ø§Ø­Ø© Ø§ÙØ¹Ù
+Ù ØšØ®Ø§ØµÙØ© ÙØ±Ø§Ø¡Ø© ÙÙØ· Ù ÙØ§ ÙÙ
+ÙÙ Ø¥ÙØºØ§Ø€ÙØ§.
+FileActions.Replacing:Ø¥Ø³ØªØšØ¯Ø§Ù
+FileActions.Selected:{0} Ø§ÙÙ
+ÙÙØ§Øª Ù  {1} Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±Ø©
+FileActions.Unknown_File_Error_Message:ØšØ§ÙØ±ØºÙ
+ Ù
+Ù Ø¹Ø¯Ù
+ ÙØ¬ÙØ¯ ØªÙØ±ÙØ± Ø®ÙØ§Ù \nØ¥Ø¬Ø±Ø§Ø¡ Ø§ÙÙ
+ÙÙ. Ø¥ÙØ§ Ø§Ù Ø§ÙÙØ­Øµ Ø§ÙÙÙØ§ØŠÙ Ø£ØžÙØ± Ø§Ù Ø§ÙÙØ³Ø®Ø© Ø§ÙÙØ¯Ù \nØºÙØ± Ù
+ØªÙ
+Ø§Ø«ÙØ© Ù
+Ø¹ Ø§ÙÙØ³Ø®Ø© Ø§ÙÙ
+ØµØ¯Ø±. Ø§ÙØ³ØšØš\nÙÙ ÙØ°Ø§ Ø§ÙØ£Ù
+Ø± ØºÙØ± Ù
+Ø¹Ø±ÙÙ. Ø§ÙØ±Ø¬Ø§Ø¡ ÙØ­Øµ Ø§ÙÙ
+ÙÙ Ù ØªØ¹Ø¯ÙÙ\nØªÙØ¶ÙØš JVM.
+FileActions.Unknown_File_Error_Title:Ø®Ø·Ø£  -  Ù
+ÙÙ ØºÙØ± Ù
+Ø¹Ø±ÙÙ
+FileActions.Write_Not_Permitted_Message:ÙØ§ ÙÙ
+ÙÙ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ Ø§ÙØ£Ø°Ù ØšØ§ÙÙØªØ§ØšØ© Ø§ÙÙ\n{0}\nØ§ÙØ±Ø¬Ø§Ø¡ Ù
+Ø±Ø§Ø¬Ø¹Ø© Ø£Ø°ÙÙØ§Øª Ø§ÙÙ
+ÙÙ.
+FileActions.Write_Not_Permitted_Title:Ø®Ø·Ø£ - Ø£Ø°ÙÙØ§Øª Ù
+ÙÙ ØºÙØ± ØµØ­ÙØ­Ø©
+FileActions.Yes_To_All:ÙØ¹Ù
+ ÙÙÙÙ
+#************************
+#
+#******* File Associations dialog **********
+FileAssociationDialog.Add:Ø¥Ø¶Ø§ÙØ©
+FileAssociationDialog.Add_Tooltip:Ø§Ø³ØªØ®Ø¯Ù
+ ÙØ°Ø§ Ø§ÙØªØ·ØšÙÙ ÙØ¹Ø±Ø¶ Ù
+ÙÙØ§Øª Ù
+Ù ÙØ°Ø§ Ø§ÙÙÙØ¹
+FileAssociationDialog.Batch_File:Ù
+ÙÙØ§Øª ØªÙÙÙØ°
+FileAssociationDialog.Browse:ØªØµÙØ­
+FileAssociationDialog.Browse_Tooltip:Ø¥Ø®ØªÙØ§Ø± Ø§ÙØªØ·ØšÙÙ ÙÙØ¥Ø³ØªØ®Ø¯Ø§Ù
+ Ù
+Ù Ù
+Ø³Ø§Ø­Ø© Ø§ÙØ¹Ù
+Ù
+FileAssociationDialog.Browse_Tooltip_Mac:ØªØµÙØ­ ØªØ·ØšÙÙ Ø§ÙØ¹Ù
+Ù ØºÙØ± Ù
+ØªØ§Ø­ Ø­Ø§ÙÙØ§ Ù MacOS
+FileAssociationDialog.Browse_Title:Ø¥Ø®ØªÙØ§Ø± ØªØ·ØšÙÙ
+FileAssociationDialog.Close:ØºÙÙ
+FileAssociationDialog.Close_Tooltip:ØºÙÙ Ø§ÙØ­ÙØ§Ø± Ù Ø§ÙØ±Ø¬ÙØ¹ ÙÙÙØ§ØŠÙ
+Ø© Ø§ÙØ±ØŠÙØ³Ø©
+FileAssociationDialog.Command:Ø¥Ø·ÙØ§Ù Ø£Ù
+Ø±:
+FileAssociationDialog.Command_File:Ù
+ÙÙØ§Øª Ø£Ù
+Ø±
+FileAssociationDialog.Command_Tooltip:Ø¥Ø¯Ø®Ù Ø§ÙØ£Ù
+Ø± ÙØ¥Ø·ÙØ§Ù Ø§ÙØªØ·ØšÙÙ ÙÙØ¥Ø³ØªØ®Ø¯Ø§Ù
+
+FileAssociationDialog.Details:ØªÙØ§ØµÙÙ Ø¥Ù
+ØªØ¯Ø§Ø¯ Ø§ÙÙ
+ÙÙ Ø§ÙØ¬Ø¯ÙØ¯
+FileAssociationDialog.Executable_File:Ù
+ÙÙØ§Øª Ø§ÙØªÙÙÙØ°
+FileAssociationDialog.Extension:ÙÙÙØ§ÙØ© Ø§ÙÙ
+ÙÙ:
+FileAssociationDialog.Extension_Tooltip:Ø¹Ø±Ø¶ Ø¥Ù
+ØªØ¯Ø§Ø¯Ø§Øª Ø§ÙÙ
+ÙÙØ§Øª
+FileAssociationDialog.Instructions:Ø§Ø³ØªØ®Ø¯Ù
+ ÙØ°Ø§ Ø§ÙÙ
+Ø±ØšØ¹ ÙØªØ­Ø¯ÙØ¯ Ø§ÙØšØ±Ø§Ù
+Ø¬ Ø§ÙØ®Ø§Ø±Ø¬ÙØ© Ø§ÙØªÙ ØªØ¹Ø±Ø¶ Ø§ÙÙØ§Ø¹ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+Ø­Ø¯Ø¯Ø©, Ù ØªØ­Ø¯ÙØ¯ Ø§ÙØ§Ù
+Ø± Ø§ÙØ°Ù ÙØ±Ø³Ù ÙØ§Ø·ÙØ§Ù ÙØ°Ø§ Ø§ÙØšØ±ÙØ§Ù
+Ø¬.\nÙØ§Ø¶Ø§ÙØ© ÙÙØ¹ Ù
+ÙÙ Ø¬Ø¯ÙØ¯ , Ø¥Ø·ØšØ¹ Ø§Ù
+ØªØ¯Ø§Ø¯ Ø§ÙÙ
+ÙÙ ÙÙ  'Ø¥Ù
+ØªØ¯Ø§Ø¯ Ù
+ÙÙ'. ÙØ§Ø¶Ø§ÙØ© Ø§Ù ØªØ¹Ø¯ÙÙ Ø£Ù
+Ø± Ø§Ø·ÙØ§ÙØ Ø§Ø·ØšØ¹ Ø§ÙØ§Ù
+Ø± Ø§ÙØ¬Ø¯ÙØ¯ ÙÙ 'Ø£Ù
+Ø± Ø§Ø·ÙØ§Ù' Ø§Ù Ø§ÙÙÙØ± Ø¹ÙÙ  'ØªØµÙØ­' ÙÙØšØ­Ø« Ø¹Ù Ù
+ÙÙ Ø§ÙÙØžØ§Ù
+ Ø§ÙÙ
+ÙØ§Ø³Øš ÙÙØšØ±ÙØ§Ù
+Ø¬. Ø§Ø³ØªØ®Ø¯Ù
+ Ø§ÙØ³ÙØ³ÙØ© Ø§ÙØ®Ø§ØµØ© '%1' Ù
+ÙÙØ¹ Ø§ÙÙ
+ÙÙ Ø§ÙÙ
+Ø±Ø§Ø¯ ÙØªØ­Ù Ù Ø§ÙØ°Ù ÙØ¬Øš Ø§Ù ÙØ­ØŽØ± Ù
+Ø«Ù. "C:\\Windows\\System\\MSPaint.exe %1". '%1' ØªÙØ¶Ø¹ Ø¯Ø§ØŠÙ
+Ø§ ÙÙ ÙÙØ§ÙØ© Ø§ÙØ£Ù
+Ø± Ù
+Ø§ÙÙ
+ ÙØ­Ø¯Ø¯ ØºÙØ± Ø°ÙÙ.\nÙ
+Ø³ØªØ®Ø¯Ù
+Ù MacOS Ø¹ÙÙÙÙ
+ Ø¯Ø§ØŠÙ
+Ø§ Ø§Ø³ØªØ®Ø¯Ø§Ù
+ Ø§ÙØ§Ù
+Ø± mac Ø§ÙÙ
+Ø­Ø¯Ø¯Ø© "ÙØªØ­ [-a <application_name>] %1" Ø§ÙÙØ§.
+FileAssociationDialog.Table.Command:Ø£Ù
+Ø±
+FileAssociationDialog.Table.Extension:Ø¥Ù
+ØªØ¯Ø§Ø¯
+FileAssociationDialog.Title:ØªØ­Ø¯ÙØ« Ø¥Ù
+ØªØ¯Ø§Ø¯ Ù
+ÙÙ
+FileAssociationDialog.Remove:Ø­Ø°Ù
+FileAssociationDialog.Remove_Tooltip:Ø­Ø°Ù Ø¥Ù
+ØªØ¯Ø§Ø¯Ø§Øª Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±Ø© Ù
+Ù Ø¥Ù
+ØªØ¯Ø§Ø¯Ø§Øª Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙØ­Ø§ÙÙØ©
+FileAssociationDialog.Replace:Ø¥Ø³ØªØšØ¯Ø§Ù
+FileAssociationDialog.Replace_Tooltip:Ø¥Ø³ØªØšØ¯Ø§Ù Ø¥Ù
+ØªØ¯Ø§Ø¯Ø§Øª Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙØ­Ø§ÙÙØ© ØšØªÙØ§ØµÙÙ Ø¥Ù
+ØªØ¯Ø§Ø¯Ø§Øª Ø¬Ø¯ÙØ¯Ø©
+#*******************
+#
+#******Filter***************
+Filter.0:HTM & HTML
+Filter.1:XML
+Filter.2:Ù
+ÙÙØ§Øª ÙØµÙØ©
+Filter.3:ØµÙØ±
+Filter.All_Files:ÙÙ Ø§ÙÙ
+ÙÙØ§Øª
+Filter.Filter_Tree:Ø¹Ø±Ø¶ Ø§ÙÙ
+ÙÙØ§Øª
+Filter.Invalid_Pattern:<HTML><FONT FACE={FONT} COLOR=Black>Ø§ÙÙÙ
+Ø· Ø§ÙÙ
+Ø¯Ø®Ù ÙØªØ±ØŽÙØ­ Ø§ÙÙ
+ÙÙØ§Øª ØºÙØ± ØµØ§ÙØ­.<BR>Ø§ÙØ±Ø¬Ø§Ø¡ Ø§ÙÙ
+Ø­Ø§ÙÙØ© Ù
+Ø±Ø© Ø«Ø§ÙÙØ© ØšØ¥Ø³ØªØ®Ø¯Ø§Ù
+ ØµÙØºØ© Ø§ÙØªØ¹ØšÙØ±Ø§Øª Ø§ÙÙ
+ÙØªØžÙ
+Ø© Ù
+Ø¹ <BR>* for the wildcard character.</FONT></HTML>
+#***********************
+#
+#***** GAuthenticator *****
+GAuthenticator.Password:ÙÙÙ
+Ø© Ø§ÙÙ
+Ø±ÙØ±:
+GAuthenticator.Password_Tooltip:Ø¥Ø¯Ø®Ù ÙÙÙ
+Ø© Ø§ÙÙ
+Ø±ÙØ± ÙÙØ§
+GAuthenticator.Title:ÙÙÙ
+Ø© Ø§ÙÙ
+Ø±ÙØ±.
+GAuthenticator.Username:Ø¥Ø³Ù
+ Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+:
+GAuthenticator.Username_Tooltip:Ø¥Ø¯Ø®Ù Ø¥Ø³Ù
+ Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+ ÙÙØ§
+#**************************
+#
+#***** General Messages *****
+# 0 - A String representing the name and method of the class in question.
+General.Apply:ØªØ·ØšÙÙ
+General.Apply_Tooltip:ØªØ·ØšÙÙ Ø§ÙØ¥Ø¹Ø¯Ø§Ø¯Ø§Øª Ø§ÙØ­Ø§ÙÙØ© ØšØ¯ÙÙ Ø®Ø±ÙØ¬ Ù
+Ù Ù
+Ø±ØšØ¹ Ø§ÙØ­ÙØ§Ø±
+General.Browse:ØªØµÙØ­...
+General.Cancel:Ø¥ÙØºØ§Ø¡
+General.Cancel_Tooltip:Ø¥ÙØºØ§Ø¡ Ø§ÙØªØ¹Ø¯ÙÙØ§Øª (ÙÙ ÙØªÙ
+ ÙÙØ¶ Ø¢Ù Ø¥Ø¬Ø±Ø§Ø¡ ØªÙ
+ ØªØ·ØšÙÙÙ Ù
+Ù ÙØšÙ)
+General.Close:ØºÙÙ
+General.Close_Tooltip:ØºÙÙ Ù
+Ø±ØšØ¹ Ø§ÙØ­ÙØ§Ø±
+General.Edit:ØªØ¹Ø¯ÙÙ ÙÙÙ
+Ø©
+General.Error:Ø®Ø·Ø£
+General.No:ÙØ§
+General.NotSunJava:Java vendor: {0}\nÙØ¬Øš Ø§ÙØªÙØšÙ Ø¥ÙÙ Ø£Ù ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ÙØ¯ ØªÙ
+ ØªØ·ÙÙØ±ÙØ§ Ù Ø¥Ø®ØªØšØ§Ø±ÙØ§ ØšÙØ§Ø³Ø·Ø©  Ø¬Ø§ÙØ§ Ù
+Ù  Sun Microsystems.
+General.OK:OK
+General.OK_Tooltip:Ø®Ø±ÙØ¬ ÙØ­ÙØž Ø§ÙØªØ¬ÙÙØ² Ø§ÙØ­Ø§ÙÙ
+General.Open:ÙØªØ­
+General.Outstanding_Processes:<html>ÙÙ ÙØºÙÙ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ Ø­ØªÙ ÙØªÙ
+ ØºÙÙ ÙÙ Ø§ÙØšØ±Ø§Ù
+Ø¬ Ø§ÙØ£Ø®Ø±Ù<br>Ø§ÙØªÙ Ø¥ØšØªØ¯Ø£Øª Ù
+Ø¹ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ.</html>
+General.Outstanding_Processes_Title:Ø¥ÙØªØžØ§Ø± Ø§ÙØ®Ø±ÙØ¬
+General.Pure_Cancel_Tooltip:Ø£Ø¬ÙØ¶ ÙØ°Ø§ Ø§ÙØ¥Ø¬Ø±Ø§Ø¡ (Ø­Ø°Ù Ø§ÙØªØ¹Ø¯ÙÙØ§Øª)
+General.Review_Output:Ø§ÙØ±Ø¬Ø§Ø¡ Ø¹Ø±Ø¶ Ø§ÙÙ
+Ø®Ø±Ø¬Ø§Øª Ø£Ø¯ÙØ§Ù:
+General.Redo:Ø¥Ø¹Ø§Ø¯Ø©
+General.Redo_Tooltip:Ø¥Ø³ØªØ¹Ø§Ø¯Ø© Ø§ÙØ¥Ø¬Ø±Ø§Ø¡ Ø§ÙØ£Ø®ÙØ±
+General.Undo:ÙÙØ¶
+General.Undo_Tooltip:ÙÙØ¶ Ø§ÙØªØ­Ø¯ÙØ« Ø§ÙØ£Ø®ÙØ±
+General.Usage:Usage: {0} <params>\nÙÙ Ø§ÙÙ
+Ø€ØŽØ±Ø§Øª Ø¥Ø®ØªÙØ§Ø±ÙØ© ÙÙÙ Ø±ØšÙ
+Ø§ ÙÙØŽÙ ØªØŽØºÙÙ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ Ø§Ø°Ø§ ÙÙ
+ ÙØªÙ
+ ØªØ«ØšÙØª  -gsdl Ù Ø§ÙÙ
+ÙØªØšØ©.\n -gsdl <path>  : ØªØ­Ø¯ÙØ¯ Ù
+Ø³Ø§Ø± gsdl\n -Ø±Ø³Ø§ØŠÙ ØªØµØ­ÙØ­ Ø§ÙÙ
+ÙØªØšØ© <path> : Ù
+Ø³Ø§Ø± cgi-bin\n -mozilla <path> : ØªÙ
+ÙÙÙ mozilla\n -mirror : Ø¥ØªØ§Ø­Ø© ØªØ­ÙÙ
+ Ø§ÙÙØš Ø§ÙÙ
+ØªØ·Ø§ØšÙ\n -laf [java|windows|motif|mac] : ØªÙ
+ØžÙØ± Ù Ø¥Ø­Ø³Ø§Ø³\n -ØªØµØ­ÙØ­ : ØªÙ
+ÙÙÙ Ø±Ø³Ø§ØŠÙ Ø§ÙØªØµØ­ÙØ­\n -no_load : ÙØ§ ØªØ­Ù
+Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙ
+ÙØªÙØ­Ø© Ù
+Ù ÙØšÙ\n -load <path> : ØªØ­Ù
+ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙ
+Ø­Ø¯Ø¯Ø©
+General.View:Ø¹Ø±Ø¶ ÙÙÙ
+Ø©
+General.Warning:ØªØ­Ø°ÙØ±
+General.Yes:ÙØ¹Ù
+
+#****************************
+#
+#***** GShell *****
+GShell.BadArgument:Ù
+Ø¶Ù
+ÙÙ  {0} ÙÙØ³ ØµØ§ÙØ­Ø§.
+GShell.BadArgumentValue:Ù
+Ø¶Ù
+ÙÙ  {0} ÙÙØ³ ÙØ¯ÙÙ ÙÙÙ
+Ø© ØµØ§ÙØ­Ø©.
+GShell.BadPluginOptions:Ù
+Ø¶Ù
+ÙÙ ØºÙØ± ØµØ§ÙØ­ ÙÙ Ù
+ÙØ§ØšØ³ {0}.
+GShell.BadClassifierOptions:Ù
+Ø¶Ù
+ÙÙ ØºÙØ± ØµØ§ÙØ­ ÙÙ Ù
+ØµÙÙ {0}.
+GShell.Build.Auxilary:ØšÙØ§Ø¡ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙØ¥Ø¶Ø§ÙÙØ© Ù Ø§ÙØªØ±ØªÙØš...
+GShell.Build.BuildBegun1:************** ØšØ¯Ø§ÙØ© ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© **************
+GShell.Build.BuildCancelled:**************   Ø¥ÙØºØ§Ø¡    **************
+GShell.Build.BuildComplete1:************** ÙÙØ§ÙØ© ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© **************
+GShell.Build.CompressText:Ø¶ØºØ· Ø§ÙÙØµ...
+GShell.Build.Index:ØšÙØ§Ø¡ ÙØŽØ§Ù ÙÙÙØ§ ÙÙ {0-index source and level}...
+GShell.Build.InfoDatabase:ØšÙØ§Ø¡ Ù
+Ø¹ÙÙÙ
+Ø§Øª ÙØ§Ø¹Ø¯Ø© Ø§ÙØšÙØ§ÙØ§Øª...
+GShell.Build.Phind:ØªÙÙÙØ¯ Phind Ù
+ØµÙÙ. ÙØ¯ ÙØ³ØªØºØ±Ù ÙØ°Ø§ ÙÙØªØ§...
+GShell.Command:Ø£Ù
+Ø±
+GShell.Failure:ÙØŽÙØª Ø¥Ø¬Ø±Ø§Ø¡Ø§Øª ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©.
+GShell.Import.FileNotProcessed:ÙØ°Ø§ Ø§ÙÙ
+ÙÙ {0-target file path} ØªÙ
+ Ø§ÙØªØ¹Ø±Ù Ø¹ÙÙÙ Ù ÙÙÙ ÙÙ
+ ÙØ³ØªØ·Ø¹ Ø£Ù ÙØ§ØšØ³ Ù
+Ø¹Ø§ÙØ¬ØªÙ.
+GShell.Import.FileNotRecognised:ÙØ°Ø§ Ø§ÙÙ
+ÙÙ {0-target file path} ÙÙ
+ ÙØªÙ
+ Ø§ÙØªØ¹Ø±Ù Ø¹ÙÙÙ ØšÙØ§Ø³Ø·Ø© Ø£Ù Ù
+ÙØ§ØšØ³.
+GShell.Import.FileProcessing:ÙØ°Ø§ Ø§ÙÙ
+ÙÙ {0-target file path} ÙÙØ¯ Ø§ÙÙ
+Ø¹Ø§ÙØ¬Ø© ØšÙØ§Ø³Ø·Ø© {1-plugin name}.
+GShell.Import.FileProcessingError:Ø­Ø¯Ø«Øª Ø£Ø®Ø·Ø§ Ø®ÙØ§Ù Ù
+Ø¹Ø§ÙØ¬Ø© Ø§ÙÙ
+ÙÙ {0-target file path}
+GShell.Import.ImportBegun1:************** ØšØ¯Ø§ÙØ© Ø§ÙØ¥Ø³ØªÙØ±Ø§Ø¯ **************
+GShell.Import.ImportComplete1:************** ÙÙØ§ÙØ© Ø§ÙØ¥Ø³ØªÙØ±Ø§Ø¯ **************
+GShell.Import.ImportComplete2:{0-number documents considered}Ø§ÙÙØ«Ø§ØŠÙ Ø§ÙØªÙ Ø¶Ù
+ÙØª ÙÙØ¥Ø¬Ø±Ø§Ø¡:
+GShell.Import.ImportComplete2.1:1 Ø§ÙÙØ«Ø§ØŠÙ Ø§ÙØªÙ Ø¶Ù
+ÙØª ÙÙØ¥Ø¬Ø±Ø§Ø¡:
+GShell.Import.ImportComplete.Processed:{0-number processed} ÙØ«ÙÙØ© Ø¹ÙÙØ¬Øª ÙØ¶Ù
+ÙØª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©.
+GShell.Import.ImportComplete.Processed.1:1 ÙØ«ÙÙØ© Ø¹ÙÙØ¬Øª ÙØ¶Ù
+ÙØª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©.
+GShell.Import.ImportComplete.Blocked:{0-number blocked} ØªÙ
+ Ù
+ÙØ¹ÙØ§ ØšÙØ§Ø³Ø·Ø© Ù
+ÙØ§ØšØ³ (Ù
+Ø«Ù Ø§ÙØµÙØ± ÙÙ ØµÙØ­Ø§Øª Ø§ÙØŽØšÙØ©).
+GShell.Import.ImportComplete.Blocked.1:1 ØªÙ
+ Ù
+ÙØ¹ÙØ§ ØšÙØ§Ø³Ø·Ø© Ù
+ÙØ§ØšØ³ (Ù
+Ø«Ù Ø§ÙØµÙØ± ÙÙ ØµÙØ­Ø§Øª Ø§ÙØŽØšÙØ©).
+GShell.Import.ImportComplete.Ignored:{0-number ignored} ÙÙ
+ ÙØªÙ
+ Ø§ÙØªØ¹Ø±Ù Ø¹ÙÙÙØ§.
+GShell.Import.ImportComplete.Ignored.1:1 ÙÙ
+ ÙØªÙ
+ Ø¥Ø¹ØªØšØ§Ø±ÙØ§.
+GShell.Import.ImportComplete.Failed:{0-number failed} ØªÙ
+ Ø±ÙØ¶ÙØ§.
+GShell.Import.ImportComplete.Failed.1:1 ØªÙ
+ Ø±ÙØ¶ÙØ§.
+GShell.Import.ImportComplete3:\n
+GShell.Parsing_Metadata_Complete:Ø¥ÙØªÙ
+Ù Ø¥Ø±ØŽÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø³ØªØ®Ø±Ø¬Ø©.
+GShell.Parsing_Metadata_Start:Ø¥Ø³ØªØ®Ø±Ø§Ø¬ ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø¬Ø¯ÙØ¯Ø© Ù
+Ù Ù
+ÙØºØ§Øª Ø§ÙØ£Ø±ØŽÙÙ.
+GShell.Success:Ø¥ÙØªÙ
+ÙØª Ø¥Ø¬Ø±Ø§Ø¡Ø§Øª ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© .
+#*********************
+#
+#***** GUI *****
+# Currently Enabled and Disabled display the same text but in different
+# colours. If necessary this can be changed.
+GUI.Create:Ø¥ÙØŽØ§Ø¡
+GUI.Create_Tooltip:ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØšØ¥Ø³ØªØ®Ø¯Ø§Ù
+ ÙØ±ÙÙØ³ØªÙÙ
+GUI.Design:ØªØµÙ
+ÙÙ
+
+GUI.Design_Tooltip:ØšÙØ§Ø¡ ÙØžØ§ØŠÙ  Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+GUI.Download:ØªÙØ²ÙÙ
+GUI.Download_Tooltip:ØªÙØ²ÙÙ Ù
+ØµØ§Ø¯Ø± Ù
+Ù Ø§ÙØ¥ÙØªØ±ÙØª ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+GUI.Enrich:Ø¥Ø«Ø±Ø§Ø¡
+GUI.Enrich_Tooltip:ØªØ­Ø¯ÙØ¯  ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙÙ
+ÙÙØ§Øª ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+GUI.Format:ÙØ³Ù Ø¹Ø±Ø¶
+GUI.Format_Tooltip:ØšÙØ§Ø¡ ØªÙ
+ØžÙØ± Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+GUI.Gather:ØªØ¬Ù
+ÙØ¹
+GUI.Gather_Tooltip:Ø¥Ø®ØªÙØ§Ø± Ø§ÙÙ
+ÙÙØ§Øª ÙØªØ¶Ù
+ÙÙÙØ§ ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+#***************
+#
+#***** HELP *****
+Help.Contents:Ù
+Ø­ØªÙÙØ§Øª
+Help.Title:ØµÙØ­Ø§Øª Ø§ÙÙ
+Ø³Ø§Ø¹Ø¯Ø© ÙÙ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ
+#****************************
+#
+#***** Invalid Metadata ******
+InvalidMetadata.Message:Ø¹ÙØµØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ù
+Ø­Ø¬ÙØ² Ø¶Ù
+Ù ÙÙÙ
+ Ù
+Ø¹ÙØ§Ø± Ù
+Ø¹Ø±Ù Ù
+Ù ÙØšÙ .Ø§ÙØ±Ø¬Ø§Ø¡ Ø¥Ø®ØªÙØ§Ø± ÙØ§Ø­Ø¯Ø© Ù
+Ù Ø§ÙÙÙÙ
+ Ø§ÙÙ
+ÙØ¬ÙØ¯Ø©
+InvalidMetadata.Title:ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª ØºÙØ± ØµØ§ÙØ­Ø©
+#***************************
+#
+#***** LegacyCollection
+LegacyCollection.Message:Ø£ÙØª ØšØµØ¯Ø¯ ØªØ­Ù
+ÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø© ÙÙ
+ ÙØªÙ
+ ØšÙØ§Ø€ÙØ§ ØšÙØ§Ø³Ø·Ø©  GLI. Ø³ÙÙ ÙØªÙ
+ Ø¥Ø³ØªÙØ±Ø§Ø¯ ÙÙÙ
+ ÙØ§ÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+ÙØ¬ÙØ¯Ø© Ø¥ÙÙ Ù
+Ø¹ÙØ§Ø± Ø¯ØšÙÙ ÙÙØ± ÙÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª. Ù
+ÙÙØ§Øª ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØ£ØµÙÙØ© Ø³ÙÙ ÙØªÙ
+ Ø­ÙØžÙØ§ÙÙ Ù
+Ø¬ÙØ¯ ÙØ³Ù
+Ù  import.bak.
+LegacyCollection.Title:ØªØ­Ù
+ÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø© Ø®Ø§Ø±Ø¬ÙØ©
+#***************************
+#
+#***** LockFileDialog *****
+LockFileDialog.Cancel_Tooltip:ÙØ§ ØªÙ
+ÙÙ ØªØ­ÙÙ
+ Ø§ÙÙ
+ÙÙ Ø§ÙÙ
+ØºÙÙ (Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙ ØªÙØªØ­)
+LockFileDialog.Date:ØªØ£Ø±ÙØ®
+LockFileDialog.Error:Ø®Ø·Ø£
+LockFileDialog.Lockfile_Message_One:ÙØ¬ÙØ¯ Ù
+ÙØªØ§Ø­ Ø§ÙØºÙÙ ÙØŽÙØ± Ø§ÙÙ Ø§Ù ÙØ°Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙ ÙÙØ¯ Ø§ÙØ£Ø³ØªØ®Ø¯Ø§Ù
+ Ø§ÙØ¢Ù.
+LockFileDialog.Lockfile_Message_Two:ÙÙ ØªØ±ØºØš ÙÙ Ø¥Ù
+ØªÙØ§Ù ØªØ­ÙÙ
+ ÙØ°Ø§ Ø§ÙÙ
+ÙÙ Ø§ÙÙ
+ØºÙÙØ
+LockFileDialog.Machine:Ø£ÙÙ
+LockFileDialog.Name:Ø¥Ø³Ù
+
+LockFileDialog.OK_Tooltip:Ø¥Ù
+ØªÙØ§Ù ØªØ­ÙÙ
+ Ø§ÙÙ
+ÙÙ Ø§ÙÙ
+ØºÙÙ
+LockFileDialog.Title:ØªÙ
+ ØªØ­Ø³Ø³ Ù
+ÙÙ Ù
+ØºÙÙ
+LockFileDialog.User:Ù
+Ù
+#********************
+#
+#*****MappingPrompt **********
+MappingPrompt.File:Ù
+Ø¬ÙØ¯
+MappingPrompt.Map:Ø£ÙØŽØ§Ø¡ Ù
+Ø®ØªØµØ±
+MappingPrompt.Name:Ø¥Ø³Ù
+
+MappingPrompt.Title:ØªØ¹ÙÙÙ Ù
+Ø®ØªØµØ± Ù
+Ø¬ÙØ¯
+MappingPrompt.Unmap:Ø­Ø°Ù Ù
+Ø®ØªØµØ±
+#*******************
+#
+#***** Menu Options *****
+Menu.Collapse:ØºÙÙ Ù
+Ø¬ÙØ¯
+Menu.Edit:ØªØ­Ø¯ÙØ«
+Menu.Edit_Copy:ÙØ³Ø® (ctrl-c)
+Menu.Edit_Cut:ÙØ·Ø¹ (ctrl-x)
+Menu.Edit_Paste:ÙØµÙ (ctrl-v)
+Menu.Expand:ÙØªØ­ Ù
+Ø¬ÙØ¯
+Menu.Explode_Metadata_Database:ØªÙ
+Ø¯ÙØ¯ ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª ÙØ§Ø¹Ø¯Ø© Ø§ÙØšÙØ§ÙØ§Øª
+Menu.File:Ù
+ÙÙ
+Menu.File_Associations:Ù
+ØªØ¹ÙÙØ§Øª Ø§ÙÙ
+ÙÙ...
+Menu.File_CDimage:ØªØµØ¯ÙØ± CD/DVD ...
+Menu.File_Close:ØºÙÙ
+Menu.File_Delete:Ø¥ÙØºØ§Ø¡...
+Menu.File_Exit:Ø®Ø±ÙØ¬
+Menu.File_ExportAs:ØªØµØ¯ÙØ±...
+Menu.File_New:Ø¬Ø¯ÙØ¯..
+Menu.File_Open:ÙØªØ­...
+Menu.File_Options:ØªÙØ¶ÙÙØ§Øª...
+Menu.File_Save:Ø­ÙØž
+Menu.Help:Ù
+Ø³Ø§Ø¹Ø¯Ø©
+Menu.Help_About:Ø­ÙÙ...
+Menu.Metadata_View:ØªØ­Ø¯ÙØ¯ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ù {0}
+Menu.Open_Externally:ÙØªØ­ ØšØ±ÙØ§Ù
+Ø¬ Ø®Ø§Ø±Ø¬Ù
+#********************
+#
+#***** MetaAudit *****
+MetaAudit.Close:ØºÙÙ
+MetaAudit.Close_Tooltip:ØºÙÙ Ù
+Ø±ØšØ¹ Ø§ÙØ­ÙØ§Ø± ÙØ°Ø§
+MetaAudit.Title:ÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª
+#*********************
+#
+#***** Metadata *****
+Metadata.Element:Ø¹ÙØµØ±
+Metadata.Value:ÙÙÙ
+Ø©
+MetadataSet.Files:Ù
+ÙÙØ§Øª Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª
+#**********************************
+#
+#***** MetadataSetDialog**********
+MetadataSetDialog.Title:Ø¥Ø¯Ø§Ø±Ø© Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª
+MetadataSetDialog.Add_Title:Ø¥Ø¶Ø§ÙØ© Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª
+MetadataSetDialog.Current_Sets:Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø©
+MetadataSetDialog.Available_Sets:Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+ØªÙÙØ±Ø©
+MetadataSetDialog.Add:Ø¥Ø¶Ø§ÙØ©...
+MetadataSetDialog.Add_Tooltip:Ø¥Ø¶Ø§ÙØ© Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª  ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+MetadataSetDialog.New_Set:Ø¬Ø¯ÙØ¯...
+MetadataSetDialog.New_Set_Tooltip:Ø¥ÙØŽØ§Ø¡ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø¬Ø¯ÙØ¯
+MetadataSetDialog.Add_Set:Ø¥Ø¶Ø§ÙØ©
+MetadataSetDialog.Add_Set_Tooltip:Ø¥Ø¶Ø§ÙØ© Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø± ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+MetadataSetDialog.Browse:ØªØµÙØ­...
+MetadataSetDialog.Browse_Tooltip:Ø¥Ø¶Ø§ÙØ© Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø± ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+MetadataSetDialog.Edit:ØªØ­Ø¯ÙØ«...
+MetadataSetDialog.Edit_Tooltip:ØªØ­Ø¯ÙØ« Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±
+MetadataSetDialog.Remove:Ø­Ø°Ù
+MetadataSetDialog.Remove_Tooltip:Ø­Ø°Ù Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø± Ù
+Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+MetadataSetDialog.Elements:Ø§ÙØ¹ÙØ§ØµØ± ÙÙ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±
+MetadataSetDialog.Edit_Message:ÙÙ
+ÙÙ ØªØ­Ø¯ÙØ« Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ØšØ¥Ø³ØªØ®Ø¯Ø§Ù
+  GEMS (Ù
+Ø­Ø±Ø± ÙØ±ÙÙØ³ØªÙÙ ÙÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª).\nØ¥ØšØ¯Ø£ GEMS ÙÙ ÙÙÙØ¯ÙØ² ØšØªØŽØºÙÙ  \nØ¥ØšØ¯Ø£-->ØšØ±Ø§Ù
+Ø¬ ÙØ±ÙÙØ³ØªÙÙ ÙÙÙ
+ÙØªØšØ© Ø§ÙØ±ÙÙ
+ÙØ©-->Ù
+Ø­Ø±Ø± ÙØ±ÙÙØ³ØªÙÙ ÙÙ
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª.\nÙÙ Linux Ø£Ù Mac, ØŽØºÙ gems.sh Ù
+Ù Ù
+Ø¬ÙØ¯ gli ÙÙ ØªØ«ØšÙØª ÙØ±ÙÙØ³ØªÙÙ.
+MetadataSetDialog.Edit_Message_Title:ØªØ­Ø¯ÙØ« Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª
+
+#****************************************
+#
+#***** MetadataSetNamespaceClash warning***
+MetadataSetNamespaceClash.Title:ØªØ¶Ø§Ø±Øš Ø¥Ø³Ù
+ Ù
+Ø³Ø§Ø­Ø© Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª
+MetadataSetNamespaceClash.Message:Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØ°Ù Ø£Ø®ØªØ±ØªÙ ÙÙØ¥Ø¶Ø§ÙØ© ({0}) ÙÙÙ Ø¥Ø³Ù
+ Ù
+Ø³Ø§Ø­Ø© Ù
+ÙØ¬ÙØ¯ Ù
+Ù ÙØšÙ ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ({1}). Ø¥Ø°Ø§ Ø£Ø¶ÙØª ÙØ°Ø§ Ø§ÙÙ
+Ø¹ÙØ§Ø± Ø§ÙØ¬Ø¯ÙØ¯ØØ³ÙÙ ÙØªÙ
+ Ø¥ÙØºØ§Ø¡ Ø§ÙÙØ¯ÙÙ
+ Ù Ø¥Ø­ÙØ§Ù Ø§ÙØ¬Ø¯ÙØ¯ Ù
+Ø­ÙÙ. Ø¢Ù ÙÙÙ
+ ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+Ø¹ØªÙ
+Ø¯Ø© Ø³ÙÙ ÙØªÙ
+ ØªØ­ÙÙÙÙØ§ Ø¥ÙÙ Ø§ÙÙ
+Ø¹ÙØ§Ø± Ø§ÙØ¬Ø¯ÙØ¯ Ø·Ø§ÙÙ
+Ø§ ØªØ¶Ù
+ÙØª Ø§ÙØ¹ÙØ§ØµØ± Ø§ÙÙ
+ÙØ§Ø³ØšØ©.
+#*********************************************
+#
+#******** MetadataImportMappingPrompt *********
+MIMP.Add:Ø¥Ø¶Ø§ÙØ©
+MIMP.Add_Tooltip:Ø¥Ø¶Ø§ÙØ© ÙØ§ØµÙØ© ØšÙØ§ÙØ§Øª ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙ
+Ø®ØªØ§Ø±Ø©
+MIMP.Ignore:ØªØ¬Ø§ÙÙ
+MIMP.Ignore_Tooltip:ØªØ¬Ø§ÙÙ Ø¹ÙØµØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙØ°Ø§
+MIMP.Instructions:ÙØ§ ÙÙ
+ÙÙ Ø¥Ø³ØªÙØ±Ø§Ø¯ Ø¹ÙØµØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª {0} ØªÙÙØ§ØŠÙØ§ ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©. ÙÙ
+ ØšØ¥Ø®ØªÙØ§Ø± Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ù ÙÙÙØ§ ÙÙØ°Ù Ø§ÙØ®ÙØ§Ø±Ø§Øª:\n(1) Ø§Ø¶ØºØ·  'Ø¥Ø¶Ø§ÙØ©' ÙØ§Ø¶Ø§ÙØ© ÙØ§ØµÙØ© Ø§ÙØšÙØ§ÙØ§Øª Ø¥ÙÙ ÙØ°Ø§ Ø§ÙÙ
+Ø¹ÙØ§Ø± (ÙÙØ· ÙÙ Ø­Ø§ÙØ© Ø¹Ø¯Ù
+ ØªÙÙØ± {0} ÙØ§ØµÙØ© Ø§ÙØšÙØ§ÙØ§ØªÙÙ Ø§ÙÙ
+Ø¹ÙØ§Ø±), Ø£Ù\n(2) Ø¥Ø®ØªÙØ§Ø± Ø¹ÙØµØ± Ù Ø§ÙØ¶ØºØ· Ø¹ÙÙ  'Ø¯Ù
+Ø¬' ÙØ¥Ø³ØªÙØ±Ø§Ø¯ {0} ÙØ§ØµÙØ© Ø§ÙØšÙØ§ÙØ§Øª ÙÙØ°Ø§ Ø§ÙØ¹ÙØµØ±, Ø£Ù\n(3) ØªØ¬Ø§ÙÙ Ø¹ÙØµØ± ÙØ§ØµÙØ© Ø§ÙØšÙØ§ÙØ§Øª.
+MIMP.Merge:Ø¯Ù
+Ø¬
+MIMP.Merge_Tooltip:ØªØ®Ø·ÙØ· Ø¹ÙØµØ± ÙØ§ØµÙØ© Ø§ÙØšÙØ§ÙØ§Øª ÙÙØ¹ÙØµØ± Ø§ÙÙ
+Ø­Ø¯Ø¯ ÙÙ Ø§ÙÙ
+Ø¹ÙØ§Ø± Ø§ÙÙ
+Ø®ØªØ§Ø±.
+MIMP.Source_Element::Ù
+ØµØ¯Ø± Ø¹ÙØµØ± ÙØ§ØµÙØ© Ø§ÙØšÙØ§ÙØ§Øª
+MIMP.Target_Element::Ø¹ÙØµØ± ÙØ§ØµÙØ© Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙØ¯Ù
+MIMP.Target_Set::Ù
+Ø¹ØšØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙØ¯Ù
+MIMP.Title:Ø¯Ù
+Ø¬ Ø§ÙØ¥Ø¬Ø±Ø§Ø¡ Ø§ÙÙ
+Ø·ÙÙØš.
+#*****************************
+#
+#***** Mirroring *****
+Mirroring.ClearCache:Ù
+Ø­Ù Ø§ÙØ°Ø§ÙØ±Ø©
+Mirroring.ClearCache_Tooltip:Ø¥ÙØºØ§Ø¡ ÙÙ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+ÙØ²ÙØ©
+Mirroring.Download:ØªÙØ²ÙÙ
+Mirroring.Download_Tooltip:Ø¥ØšØ¯Ø£ Ù
+ÙÙ
+Ø© ØªÙØ²ÙÙ Ø¬Ø¯ÙØ¯Ø©
+Mirroring.DownloadJob.Close:ØºÙÙ
+Mirroring.DownloadJob.Close_Tooltip:Ø­Ø°Ù ÙØ°Ù Ø§ÙÙ
+ÙÙ
+Ø© Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©, Ø£ÙÙÙÙØ§ Ø¥Ø°Ø§ ÙØ§ÙØª ÙÙØ¯ Ø§ÙØªØŽØºÙÙ
+Mirroring.DownloadJob.Downloading:ØªÙØ²ÙÙ {0}
+Mirroring.DownloadJob.Download_Complete:Ø¥ÙØªÙØ§Ø¡ Ø§ÙØªÙØ²ÙÙ
+Mirroring.DownloadJob.Download_Stopped:Ø¹ÙÙ Ø¥Ø¬Ø±Ø§Ø¡ Ø§ÙØªÙØ²ÙÙ
+Mirroring.DownloadJob.Download_Progress:ØªØ·ÙØ± Ø¹Ù
+ÙÙØ© Ø§ÙØªÙØ²ÙÙ
+Mirroring.DownloadJob.Log:Ø¹Ø±Ø¶ Ø³Ø¬Ù
+Mirroring.DownloadJob.Log_Tooltip:Ø¹Ø±Ø¶ ØªÙØ§ØµÙÙ Ø­ÙÙ ÙØ°Ø§ Ø§ÙØªÙØ²ÙÙ
+Mirroring.DownloadJob.Log_Title:Ù
+Ø¯ÙÙØ© Ø§ÙØªÙØ²ÙÙ  # Updated 29-Nov-2006 by kkhalafala
+Mirroring.DownloadJob.Pause:Pause
+Mirroring.DownloadJob.Pause_Tooltip:ØªØ¹ÙÙÙ ÙØ°Ø§ Ø§ÙØªÙØ²ÙÙ
+Mirroring.DownloadJob.Resume:Ù
+ØªØ§ØšØ¹Ø©
+Mirroring.DownloadJob.Resume_Tooltip:Ù
+ØªØ§ØšØ¹Ø© ÙØ°Ø§ Ø§ÙØªÙØ²ÙÙ
+Mirroring.DownloadJob.Status:ØªÙØ²ÙÙ {0} of {1} Ù
+ÙÙØ§Øª ({2} ØªØ­Ø°ÙØ±Ø§Øª, {3} Ø£Ø®Ø·Ø§)
+Mirroring.DownloadJob.Waiting:Ø¥ÙØªØžØ§Ø± Ø§ÙØšØ¯Ø§ÙØ©
+Mirroring.DownloadJob.Waiting_User:Ø¥ÙØªØžØ§Ø± Ø¥Ø¬Ø±Ø§Ø¡ Ø§ÙÙ
+Ø³ØªÙÙØ¯
+Mirroring.Invalid_URL:Ø¹ÙÙØ§Ù Ù
+ÙØ§Ø±Ø¯ Ù
+ÙØ­Ø¯ ØºÙØ± ØµØ§ÙØ­. Ø±Ø¬Ø§Ø¡ Ø§ÙØªØµØ­ÙØ­.
+Mirroring.Invalid_URL_Title:Ø¹ÙÙØ§Ù Ù
+ÙØ§Ø±Ø¯ Ù
+ÙØ­Ø¯ ØºÙØ± ØµØ§ÙØ­
+Mirroring.Preferences:ØªÙØ¶ÙÙØ§Øª...
+Mirroring.Preferences_Tooltip:ØªÙØ¹ÙÙ ØšØ±ÙÙØ³Ù Ù / Ø£Ù ØªØ­Ø¯ÙØ« Ø¥Ø¹Ø¯Ø§Ø¯Ø§Øª Ø§ÙØšØ±ÙÙØ³Ù
+#*********************
+#
+#***** Missing EXEC *****
+MissingEXEC.Message:ØªØ­Ø°ÙØ±! ÙÙ ÙÙÙÙ Ù
+Ù
+ÙÙØ§ ÙÙ Ø¹Ø±Ø¶ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙØ¬Ø¯ÙØ¯Ø© Ù
+Ù Ø®ÙØ§Ù ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ Ø¥ÙØ§ Ø¥Ø°Ø§ ÙÙ
+Øª ØšØªØ­Ø¯ÙØ¯ Ù
+Ø³Ø§Ø± Ù
+Ø²ÙØ¯ ÙØ±ÙÙØ³ØªÙÙ. ÙÙ
+ÙÙÙ Ø§ÙÙÙØ§Ù
+ ØšÙØ°Ø§ Ø§ÙØ¥Ø¬Ø±Ø§Ø¡ Ø§ÙØ¢Ù ØšØ§ÙÙØªØ§ØšØ© ÙÙ Ù
+Ø±ØšØ¹ Ø§ÙÙØµ Ø£Ø¯ÙØ§Ù  Ø Ø£Ù ÙØ§Ø­ÙØ§ ØšØ¥Ø®ØªÙØ§Ø± Ù
+ØŽÙØ¯ ØªÙØ¶ÙÙØ§Øª Ø«Ù
+ Ø§ÙØ¥ØªØµØ§Ù, .ØªØ°ÙØ± Ø§Ù Ø¹ÙÙØ§Ù Ø§ÙÙ
+ÙØ§Ø±Ø¯ Ø§ÙÙ
+ÙØ­Ø¯ Ø§ÙØµØ§ÙØ­ ÙØ¬Øš Ø£Ù ÙØšØ¯Ø£ ØšØ§ÙØšØ±ÙØªÙÙÙ.  "http://", Ù Ø³ÙÙ ÙÙØªÙÙ ØšØ§Ø³Ù
+ Ø§ÙÙ
+ÙÙ Ø§ÙØªÙÙÙØ°Ù ("gsdl" ØªÙØ¶ÙØš Ù
+Ø²ÙØ¯ Ù
+ÙØªØšØ© Ù
+Ø­ÙÙ, "library" ÙÙ
+Ø²ÙØ¯ Ø§ÙÙØš).
+MissingEXEC.Title:Ø¹ÙÙØ§ÙGreenstone Library ØºÙØ± Ù
+ÙØ¬ÙØ¯
+#***** Missing EXEC_GS3 *****
+MissingEXEC_GS3.Message:ØªØ­Ø°ÙØ±! ÙÙ ØªØªÙ
+ÙÙ Ù
+Ù Ø¹Ø±Ø¶ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙØ¬Ø¯ÙØ¯Ø© Ù
+Ù Ø®ÙØ§Ù ÙØ§Ø¬ÙØ© Ù
+ÙØªØšÙ ÙØ±ÙÙØ³ØªÙÙ ØšØ¯ÙÙ ØªØ­Ø¯ÙØ¯ Ù
+Ø³Ø§Ø± ÙØ±ÙÙØ³ØªÙÙ ÙÙ
+Ø²ÙØ¯ Ø§ÙÙØš . ÙÙ
+ÙÙÙ Ø¥Ø¯Ø®Ø§Ù ÙØ°Ø§ ÙÙ Ù
+Ø±ØšØ¹ Ø§ÙÙØµ Ø§Ø¯ÙØ§Ù Ø§Ù ÙÙÙ
+Ø§ ØšØ¹Ø¯ ØšØ§ÙØªÙØ¬Ù Ø¥ÙÙ Ø§ÙØªÙØ¶ÙÙØ§Øª Ø«Ù
+ Ø§ÙØ¥ØªØµØ§Ù Ù ÙØªØ§ØšØ© ÙØ°Ø§ Ø§ÙÙØµ http://localhost:8080/gsdl3.ÙØ§ØšØ¯ ÙÙ Ù
+Ù ÙØªØ§ØšØ© Ø§ÙØšØ±ÙØªÙÙÙÙ "http:"
+MissingEXEC_GS3.Title:Ø¹ÙÙØ§ÙGreenstone Library ØºÙØ± Ù
+ÙØ¬ÙØ¯
+#***** Missing GLIServer *****
+MissingGLIServer.Message:ØªØ­Ø°ÙØ±! ÙÙ ØªØªÙ
+ÙÙ Ù
+Ù Ø§ÙØ¹Ù
+Ù Ù
+Ø¹ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ù
+Ø§ ÙÙ
+ ÙØªÙ
+ ØªØ­Ø¯ÙØ¯ Ø¹ÙÙØ§Ù ÙØ±ÙÙØ³ØªÙÙ "gliserver" . ÙÙ
+ÙÙÙ Ø¥Ø¯Ø®Ø§Ù ÙØ°Ø§ Ø§ÙØ¢Ù ØšØ§ÙÙØªØ§ØšØ© ÙÙ Ù
+Ø±ØšØ¹ Ø§ÙÙØµ Ø£Ø¯ÙØ§Ù  Ø£Ù ÙÙÙ
+Ø§ ØšØ¹Ø¯ ØšØ§ÙØªÙØ¬Ù Ø¥ÙÙ Ø§ÙØªÙØ¶ÙÙØ§Øª Ø«Ù
+ Ø§ÙØ¥ØªØµØ§Ù. ØªØ°ÙØ± Ø§Ù Ø¹ÙÙØ§Ù Ø§ÙÙ
+ÙØ§Ø±Ø¯ Ø§ÙØµØ§ÙØ­ ÙØšØ¯Ø£ ØšØ§ÙØšØ±ÙØªÙÙÙÙ "http://" ÙÙÙØªÙÙ Øš "gliserver".
+MissingGLIServer.Title:Ø¹ÙÙØ§Ù GLIServer ØºÙØ± Ù
+ÙØ¬ÙØ¯
+#***** Missing GSDL *****
+MissingGSDL.Message:ØªØ­Ø°ÙØ±! ÙÙ ØªØªÙ
+ÙÙ Ù
+Ù Ø¥Ø³ØªØ®Ø¯Ø§Ù
+ ÙÙ Ù
+ÙØ§Ù
+Ø­ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ØšØ¯ÙÙ ØªØ«ØšÙØª ÙØ³Ø®Ø© Ù
+Ø­ÙÙØ© Ù
+Ù ÙØ±ÙÙØ³ØªÙÙ. Ø§ÙØ±Ø¬Ø§Ø¡ ØªÙØ­Øµ ØªØ«ØšÙØª Ø§ÙÙØ³Ø®Ø© Ø§ÙÙ
+Ø­ÙÙØ© ÙÙØ±ÙÙØ³ØªÙÙ Ø§Ù Ù
+Ø³Ø§Ø± Ù
+ÙÙ Ø§ÙØªÙÙÙØ°.
+MissingGSDL.Title:Ù
+Ø³Ø§Ø± GreenstoneØºÙØ± Ù
+ÙØ¬ÙØ¯
+#***** Missing PERL *****
+MissingPERL.Message:ØªØ­Ø°ÙØ±! ÙÙ ØªØªÙ
+ÙÙ Ù
+Ù Ø¥ÙØŽØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø§Øª Ø¬Ø¯ÙØ¯Ø© Ø£Ù ØšÙØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø§Øª Ù
+ÙØ¬ÙØ¯Ø©Ø ØšØ¯ÙÙ ØªØ«ØšÙØª  ØšÙØ±Ù Ø Ø§Ù Ø§Ù ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ÙØ¯ ÙØŽÙ ÙÙ Ø§ÙÙØµÙÙ Ø¥ÙÙ ØšÙØ±Ù ÙÙ ÙØžØ§Ù
+Ù. Ø§ÙØ±Ø¬Ø§Ø¡ ØªÙØ­Øµ ØªØ«ØšÙØª ØšÙØ±Ù Ø£Ù Ù
+Ø³Ø§Ø± Ù
+ÙÙ Ø§ÙØªÙÙÙØ° ÙØšÙØ±Ù.
+MissingPERL.Title:Ù
+Ø³Ø§Ø± PERL ØºÙØ± Ù
+ÙØ¬ÙØ¯
+#******* MissingImageMagick ********
+MissingImageMagick.Message:ØªØ­Ø°ÙØ±! ÙØŽÙ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ÙÙ ØªØ­Ø¯ÙØ¯ Ø§ÙÙØ³Ø®Ø© Ø§ÙÙ
+ÙØ§Ø³ØšØ© Ù
+Ù ImageMagick, Ù ØšØ§ÙØªØ§ÙÙ ÙØ§Ù Ù
+ÙØ§ØšØ³ Ø§ÙØµÙØ± ÙÙ ÙØ¹Ù
+Ù.Ø§ÙØ±Ø¬Ø§Ø¡ Ø¥Ø¹Ø§Ø¯Ø© ØªØ«ØšÙØª Ø§ÙØšØ±ÙØ§Ù
+Ø¬ ÙÙÙ ØªØªÙ
+ÙÙ Ù
+Ù ØšÙØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙØµÙØ±.
+MissingImageMagick.Title:ImageMagick ØºÙØ± Ù
+ÙØ¬ÙØ¯
+#*****************************
+#
+#***** New Session *****
+NewCollectionPrompt.Base_Collection:ØªØ¹ØªÙ
+Ø¯ ÙØ°Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø¹ÙÙ:
+NewCollectionPrompt.Base_Collection_Tooltip:Ø¥Ø®ØªÙØ§Ø± Ù
+Ø¬Ù
+ÙØ¹Ø© Ù
+ÙØ¬ÙØ¯Ø© ÙØªØ¹ØªÙ
+Ø¯ Ø¹ÙÙÙØ§ ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙØ¬Ø¯ÙØ¯Ø©
+NewCollectionPrompt.Collection_Description:ÙØµÙ Ø§ÙÙ
+Ø­ØªÙÙØ§Øª:
+NewCollectionPrompt.Collection_Name:Ù
+Ø¬ÙØ¯ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©:
+NewCollectionPrompt.Collection_Scope_Personal:Ø³Ù
+Ø§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙØŽØ®ØµÙØ©
+NewCollectionPrompt.Collection_Scope_Shared:Ø³Ù
+Ø§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙØ¬Ù
+Ø§Ø¹ÙØ©
+NewCollectionPrompt.Error:Ø®Ø·Ø£ ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙØ¬Ø¯ÙØ¯Ø©.
+NewCollectionPrompt.Instructions:ÙØ¥ÙØŽØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø© Ø¬Ø¯ÙØ¯Ø© Ø¥Ø³ØªØ®Ø¯Ù
+ Ø§ÙØ­ÙÙÙ Ø£Ø¯ÙØ§Ù
+NewCollectionPrompt.NewCollection:-- Ù
+Ø¬Ù
+ÙØ¹Ø© Ø¬Ø¯ÙØ¯Ø© --
+NewCollectionPrompt.Title:Ø¥ÙØŽØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø© Ø¬Ø¯ÙØ¯Ø©.
+NewCollectionPrompt.Title_Clash:Ø§ÙØ¹ÙÙØ§Ù Ø§ÙØ°Ù Ø§Ø®ØªØ±ØªÙ ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙØ¯ Ø§ÙØ¥Ø³ØªØ®Ø¯Ø§Ù
+ Ù
+Ù ÙØšÙ . ÙÙ ØªÙØ¯ Ø§ÙØ¥Ø³ØªÙ
+Ø±Ø§Ø±Ø
+NewCollectionPrompt.Title_Error:Ø§ÙØ±Ø¬Ø§Ø¡ ÙØªØ§ØšØ© ØšÙØ§ÙØ§Øª Ø­ÙÙ Ø§ÙØ¹ÙÙØ§Ù.
+#***** New Folder OrFilePrompt *****
+NewFolderOrFilePrompt.Default_File_Name:Ø²Ø§ØŠÙ
+NewFolderOrFilePrompt.Default_Folder_Name:Ù
+Ø¬ÙØ¯ Ø¬Ø¯ÙØ¯
+NewFolderOrFilePrompt.Destination_Name:Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙÙØ¯Ù
+NewFolderOrFilePrompt.File_Name:Ø¥Ø³Ù
+ Ù
+ÙÙ
+NewFolderOrFilePrompt.File_Name_Tooltip:Ø¥Ø¯Ø®Ù Ø¥Ø³Ù
+Ø§ ÙÙÙ
+ÙÙ Ø§ÙØ¬Ø¯ÙØ¯
+NewFolderOrFilePrompt.Folder_Name:Ø¥Ø³Ù
+ Ø§ÙÙ
+Ø¬ÙØ¯
+NewFolderOrFilePrompt.Folder_Name_Tooltip:Ø¥Ø¯Ø®Ù Ø¥Ø³Ù
+Ø§ ÙÙÙ
+Ø¬ÙØ¯ Ø§ÙØ¬Ø¯ÙØ¯
+NewFolderOrFilePrompt.Title_Folder:Ø¥ÙØŽØ§Ø¡ Ù
+Ø¬ÙØ¯ Ø¬Ø¯ÙØ¯
+NewFolderOrFilePrompt.Title_File:Ø¥ÙØŽØ§Ø¡ ÙØ«ÙÙØ© Ù
+Ø²ÙÙØ© Ø¬Ø¯ÙØ¯Ø©
+#**********************
+#
+#******* OldWGET *******
+NoPluginExpectedToProcessFile.Message:ÙÙØ³ Ù
+Ù Ø§ÙÙ
+ØªÙÙØ¹ ÙØ£Ù Ù
+Ù Ù
+ÙØ§ØšØ³ ÙØ±ÙÙØ³ØªÙÙ Ø§Ù ÙÙÙÙ
+ ØšÙ
+Ø¹Ø§ÙØ¬Ø© Ø§ÙÙ
+ÙÙ "{0}". Ø¥ÙØ­Øµ ØµØ­Ø© Ø¥Ù
+ØªØ¯Ø§Ø¯ Ø§ÙÙ
+ÙÙ . Ø¥Ø°Ø§ ÙØ§Ù ØµØ­ÙØ­Ø§ Ø ÙÙ
+ÙÙÙ Ø¥Ø³ØªØ®Ø¯Ø§Ù
+ Ù
+ÙØ§ØšØ³ UnknownPlug ÙÙ
+Ø¹Ø§ÙØ¬Ø© Ø§ÙÙ
+ÙÙ.
+NoPluginExpectedToProcessFile.Title:ÙØ§ ÙÙØ¬Ø¯ Ù
+ÙØ§ØšØ³ ÙÙ
+Ø¹Ø§ÙØ¬Ø© ÙØ°Ø§ Ø§ÙÙ
+ÙÙ
+#***********************
+#
+#***** OpenCollectionDialog *****
+OpenCollectionDialog.Available_Collections:Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙÙ
+ØªÙÙØ±Ø©
+OpenCollectionDialog.Browse:ØªØµÙØ­
+OpenCollectionDialog.Browse_Tooltip:Ø¥Ø®ØªÙØ§Ø± Ù
+Ø¬Ù
+ÙØ¹Ø© Ù
+Ù Ù
+Ø³Ø§Ø­Ø© Ø§ÙÙ
+ÙÙØ§Øª
+OpenCollectionDialog.Collection:Ù
+Ø¬Ù
+ÙØ¹Ø© ÙØ±ÙÙØ³ØªÙÙ (".col")
+OpenCollectionDialog.Description:ÙØµÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+OpenCollectionDialog.Locked_Collection:Ù
+Ø¬Ù
+ÙØ¹Ø© ÙØ±ÙÙØ³ØªÙÙ ÙÙØ¯ Ø§ÙØ¥Ø³ØªØ®Ø¯Ø§Ù
+ Ù
+Ù ÙØšÙ
+OpenCollectionDialog.No_Description:Ø§ÙØ±Ø¬Ø§Ø¡ Ø¥Ø®ØªÙØ§Ø± Ù
+Ø¬Ù
+ÙØ¹Ø© ÙØ±ÙÙØ³ØªÙÙ (".col" file) ÙØ±Ø€ÙØ© Ø§ÙØªÙØ§ØµÙÙ.
+OpenCollectionDialog.Normal_Collection:Ù
+Ø¬Ù
+ÙØ¹Ø© ÙØ±ÙÙØ³ØªÙÙ
+OpenCollectionDialog.Open:ÙØªØ­
+OpenCollectionDialog.Open_Tooltip:ØªØ­Ù
+ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙ
+Ø®ØªØ§Ø±Ø© ÙÙ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ
+OpenCollectionDialog.Title:ÙØªØ­ Ù
+Ø¬Ù
+ÙØ¹Ø© ÙØ±ÙÙØ³ØªÙÙ
+#**********************
+#
+#***** Options Pane inside CreatePane *****
+OptionsPane.Cancelled:- Ù
+ÙØºÙØ©
+OptionsPane.LogHistory:Ù
+Ø¯ÙÙØ©
+OptionsPane.Successful:- ØšÙØ¬Ø§Ø­
+OptionsPane.Unknown:- Ù
+Ø¬ÙÙÙØ©
+OptionsPane.Unsuccessful:- ØºÙØ± ÙØ§Ø¬Ø­Ø©
+#*******************
+#
+#***** Preferences *****
+Preferences:Ø§ÙØªÙØ¶ÙÙØ§Øª
+Preferences.Connection:Ø§ÙØ¥ØªØµØ§Ù
+Preferences.Connection_Tooltip:Ø¥Ø¹Ø¯Ø§Ø¯ Ø¹ÙÙØ§Ù Ø§ÙÙ
+ÙØ§Ø±Ø¯ Ø§ÙÙ
+ÙØ­Ø¯ ÙÙ
+ÙØªØšØ© ÙØ±ÙÙØ³ØªÙÙ Ù ØªØ¬ÙÙØ² Ø¥ØªØµØ§Ù Ø§ÙØšØ±ÙÙØ³Ù ØšØ§ÙØµÙØ±Ø© Ø§ÙÙ
+ÙØ§Ø³ØšØ©
+Preferences.Connection.GLIServer_URL:Ø¹ÙÙØ§Ù Ø§ÙÙ
+ÙØ§Ø±Ø¯ Ø§ÙÙ
+ÙØ­Ø¯ ÙÙØ±ÙÙØ³ØªÙÙ gliserver :
+Preferences.Connection.GLIServer_URL_Tooltip:Ø¹ÙÙØ§Ù Ø§ÙÙ
+ÙØ§Ø±Ø¯ Ø§ÙÙ
+ÙØ­Ø¯ ÙÙØ±ÙÙØ³ØªÙÙ "gliserver" CGI Ù
+Ø®Ø·ÙØ·Ø©
+Preferences.Connection.Library_Path:Ù
+Ø³Ø§Ø± Ø§ÙÙ
+ÙØªØšØ©:
+Preferences.Connection.Library_Path_GS3:Ù
+Ø³Ø§Ø± ÙØš ÙØ±ÙÙØ³ØªÙÙ:
+Preferences.Connection.Library_Path_Tooltip:Ø¹ÙÙØ§Ù Ø§ÙÙ
+ÙØ§Ø±Ø¯ Ø§ÙÙ
+ÙØ­Ø¯ ÙÙØ±ÙÙØ³ØªÙÙ Ø¹ÙÙ Ù
+Ø²ÙØ¯ Ø§ÙÙØš
+Preferences.Connection.Library_Path_Tooltip_GS3:Ø¹ÙÙØ§Ù Ø§ÙÙ
+ÙØ§Ø±Ø¯ Ø§ÙÙ
+ÙØ­Ø¯ ÙÙØ±ÙÙØ³ØªÙÙ Ø¹ÙÙ Ù
+Ø²ÙØ¯ Ø§ÙÙØš
+Preferences.Connection.ProgramCommand:Ø£Ù
+Ø± Ø§ÙØ¹Ø±Ø¶:
+Preferences.Connection.ProgramCommand_Tooltip:Ø§Ù
+Ø± Ø¥Ø·ÙØ§Ù ØšØ±ÙØ§Ù
+Ø¬ Ø¹Ø±Ø¶ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©. ØªØ°ÙØ± Ø¥Ø³ØªØ®Ø¯Ø§Ù
+  %1 ÙØ­Ø¬Ø² Ù
+ÙØ§Ù Ø¹ÙÙØ§Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ù
+Ø¹ Ø¥Ø³ØªØ®Ø¯Ø§Ù
+ Ø§ÙØ¹ÙØ§Ù
+Ø§Øª Ø§ÙÙ
+Ø§ØŠÙØ© Ø§ÙÙ
+ÙØ§Ø³ØšØ©.
+Preferences.Connection.Proxy_Host:Ù
+Ø¶ÙÙ Ø§ÙØšØ±ÙÙØ³Ù:
+Preferences.Connection.Proxy_Host_Tooltip:Ø¹ÙÙØ§Ù Ù
+Ø²ÙØ¯ Ø§ÙØšØ±ÙÙØ³Ù
+Preferences.Connection.Proxy_Port:Ù
+ÙÙØ° Ø§ÙØšØ±ÙÙØ³Ù:
+Preferences.Connection.Proxy_Port_Tooltip:Ø±ÙÙ
+ Ù
+ÙÙØ° Ù
+Ø²ÙØ¯ Ø§ÙØšØ±ÙÙØ³Ù
+Preferences.Connection.Servlet:Ø³ÙØ±ÙÙÙØª:
+Preferences.Connection.Servlet_Tooltip:ØªØ­Ø¯ÙØ¯ Ø§ÙØ³ÙØ±ÙÙÙØª ÙØ¥Ø³ØªØ®Ø¯Ø§Ù
+Ø© ÙÙ Ø¹Ø±Ø¶ Ø§ÙÙ
+ÙÙØ¹
+Preferences.Connection.Servlet_Tooltip2:ÙØ§ ÙÙØ¬Ø¯ Ø³ÙØ±ÙÙÙØª Ù
+Ø­Ø¯Ø¯ ÙÙØ°Ø§ Ø§ÙÙ
+ÙÙØ¹. Ù
+Ø¹ Ø°ÙÙ ÙÙ
+ÙÙÙ ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ù ÙÙÙ ÙÙ ØªØªÙ
+ÙÙ Ù
+Ù Ø¹Ø±Ø¶ÙØ§
+Preferences.Connection.Site:Ù
+ÙÙØ¹:
+Preferences.Connection.Site_Tooltip:Ø§ÙÙ
+ÙÙØ¹ Ø§ÙØ°Ù ØªÙØ¯ Ø§ÙØ¹Ù
+Ù ÙÙÙ
+Preferences.Connection.Use_Proxy:Ø§Ø³ØªØ®Ø¯Ù
+ Ø¥ØªØµØ§Ù Ø§ÙØšØ±ÙÙØ³ÙØ
+Preferences.General:Ø¹Ø§Ù
+
+Preferences.General_Tooltip:Ø¥Ø¹Ø¯Ø§Ø¯ ØšØ¹Ø¶ Ø§ÙØªØ¬ÙÙØ²Ø§Øª Ø§ÙØ¹Ø§Ù
+Ø©
+Preferences.General.Email:Ø¹ÙÙØ§Ù Ø§ÙÙ
+Ø³ØªÙÙØ¯ Ø§ÙØ¥ÙÙØªØ±ÙÙÙ:
+Preferences.General.Email_Tooltip:Ø³ÙÙ ÙØªÙ
+ Ø¥Ø³ØªØ®Ø¯Ø§Ù
+ Ø¹ÙÙØ§Ù Ø§ÙØšØ±ÙØ¯ Ø§ÙØ¥ÙÙØªØ±ÙÙÙ ØªÙÙØ§ØŠÙØ§ Ù
+Ø¹ Ø¢Ù Ù
+Ø¬Ù
+ÙØ¹Ø© ÙØªÙ
+ Ø¥ÙØŽØ§Ø€ÙØ§ ØšÙØ§Ø³Ø·Ø©  GLI
+Preferences.General.Font:Ø§ÙØšÙØ·:
+Preferences.General.Font_Tooltip:Ø§ÙØšÙØ· Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+ ÙÙ ÙØ§Ø¬ÙØ©  GLI .
+Preferences.General.Interface_Language:ÙØºØ© Ø§ÙÙØ§Ø¬ÙØ©:
+Preferences.General.Interface_Language_Tooltip:Ø¥Ø®ØªÙØ§Ø± ÙØºØ© Ø§ÙØ¹Ø±Ø¶ ÙÙÙØ§Ø¬ÙØ©.
+Preferences.General.Restart_Required:ÙØ¬Øš Ø¥Ø¹Ø§Ø¯Ø© ØªØŽØºÙÙ GLI ÙØªÙØ¹ÙÙ Ø§ÙØªØ¹Ø¯ÙÙØ§Øª.
+Preferences.General.Show_File_Size:Ø¹Ø±Ø¶ Ø£Ø­Ø¬Ø§Ù
+ Ø§ÙÙ
+ÙÙØ§Øª
+Preferences.General.Show_File_Size_Tooltip:Ø¹Ø±Ø¶ Ø£Ø­Ø¬Ø§Ù
+ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙØªØ§ÙÙØ© ÙÙÙ
+Ø¯Ø§Ø®Ù ÙÙ Ù
+Ø­Ø·Ø© Ø§ÙØ¹Ù
+Ù Ù ØŽØ¬Ø±Ø© Ù
+ÙÙØ§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©.
+Preferences.General.View_Extracted_Metadata:Ø¹Ø±Ø¶ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø³ØªØ®Ø±Ø¬Ø©
+Preferences.General.View_Extracted_Metadata_Tooltip:Ø¹Ø±Ø¶ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø³ØªØ®Ø±Ø¬Ø© ØšÙØ§Ø³Ø·Ø© Ù
+ÙØ§ØšØ³ ÙØ±ÙÙØ³ØªÙÙ ÙÙ ÙØ§ØŠÙ
+Ø© ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙ Ù
+ØŽÙØ¯ Ø¥Ø«Ø±Ø§Ø¡.
+Preferences.Mode:Ø³ÙØ§Ù
+Preferences.Mode_Tooltip:Ø£ÙÙØ± Ø¹ÙÙ Ù
+Ø¯Ø®Ù ÙØ¥Ø®ØªÙØ§Ø± Ø§ÙÙ
+Ø³ØªÙÙ Ø§ÙÙ
+ÙØ§Ø³Øš ÙÙØ¹Ù
+Ù
+Preferences.Mode.Assistant:Ù
+Ø³Ø§Ø¹Ø¯ Ù
+ÙØªØšÙ
+Preferences.Mode.Assistant_Description:Ø§Ø³ØªØ®Ø¯Ø§Ù
+ ÙØ°Ø§ Ø§ÙØ¥Ø¹Ø¯Ø§Ø¯ ÙÙ
+ÙÙÙ Ù
+Ù Ø¥Ø³ØªØ®Ø¯Ø§Ù
+ Ø§ÙÙØžØ§ØŠÙ Ø§ÙØ£Ø³Ø§Ø³ÙØ© ÙÙØ§Ø¬ÙØ© Ù
+ÙØªØšÙ ÙØ±ÙÙØ³ØªÙÙ: Ø¥Ø¶Ø§ÙØ© Ø§ÙÙØ«Ø§ØŠÙ Ù ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø§ØªØ Ø¥ÙØŽØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø§Øª Ø¬Ø¯ÙØ¯Ø© ØªØ¹ÙØ³ ÙÙÙÙÙØ© Ù
+Ø¬Ù
+ÙØ¹Ø§Øª Ù
+ÙØ¬ÙØ¯Ø©, ÙØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª.
+Preferences.Mode.Librarian:Ù
+ÙØªØšÙ
+Preferences.Mode.Librarian_Description:ÙÙÙØ± ÙØ°Ø§ Ø§ÙØ¥Ø¹Ø¯Ø§Ø¯ Ø§ÙØ¥Ø³ØªØ®Ø¯Ø§Ù
+ Ø§ÙØ·ØšÙØ¹Ù ÙÙØ§Ø¬ÙØ© Ù
+ÙØªØšÙ ÙØ±ÙÙØ³ØªÙÙ: Ø¥ÙØŽØ§Ø¡ Ù ØªØµÙ
+ÙÙ
+ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙØ¬Ø¯ÙØ¯Ø© Ø Ø¥Ø¶Ø§ÙØ© Ø§ÙÙØ«Ø§ØŠÙ Ù ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø§ØªØ ØªØµÙ
+ÙÙ
+ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙØ¬Ø¯ÙØ¯Ø© Ù ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª.
+Preferences.Mode.Systems:Ø¥Ø®ØªØµØ§ØµÙ ÙØžÙ
+ Ù
+ÙØªØšØ§Øª
+Preferences.Mode.Systems_Description:ÙØªÙØ­ ÙÙ ÙØ°Ø§ Ø§ÙØ¥Ø¹Ø¯Ø§Ø¯ Ø§ÙØ¥Ø³ØªØ®Ø¯Ø§Ù
+ Ø§ÙÙØ§Ù
+Ù ÙÙØ§Ø¬ÙØ© Ù
+ÙØªØšÙ ÙØ±ÙÙØ³ØªÙÙ. ÙØ£Ø®Ø° Ø£ÙØ¶ÙÙØ© Ø¥Ø³ØªØ®Ø¯Ø§Ù
+ ÙÙ Ø§ÙÙ
+ÙØ§Ù
+Ø­ ÙÙØšØºÙ ÙÙ Ø§Ù ØªÙÙÙ Ù
+ÙÙ
+Ø§ ØšØªÙÙÙÙ Ø§ÙØªØ¹ØšÙØ±Ø§Øª Ø§ÙÙ
+ÙØªØžÙ
+Ø©.
+Preferences.Mode.Expert:Ø®ØšÙØ±
+Preferences.Mode.Expert_Description:ÙØªÙØ­ ÙÙ ÙØ°Ø§ Ø§ÙØ¥Ø¹Ø¯Ø§Ø¯ Ø§ÙØ¥Ø³ØªØ®Ø¯Ø§Ù
+ Ø§ÙØ®ØšÙØ± ÙÙØ§Ø¬ÙØ© Ù
+ÙØªØšÙ ÙØ±ÙÙØ³ØªÙÙ.. ÙÙØµÙ ØšÙ ÙÙÙ
+Ø³ØªØ®Ø¯ÙÙ Ø°ÙÙ Ø§ÙØ®ØšØ±Ø© ØšÙØ±ÙÙØ³ØªÙÙ Ù ÙØ¯ÙÙÙ
+ Ø§ÙÙØ¯Ø±Ø© Ø¹ÙÙ ØªÙØ¯ÙÙ
+ Ø§ÙØ­ÙÙÙ Ø§ÙÙ
+ØªØ¹ÙÙØ© ØšØªØµØ­ÙØ­ Ù
+Ø®Ø±Ø¬Ø§Øª Ù
+Ø®Ø·ÙØ·Ø§Øª ØšÙØ±Ù.ÙÙ Ù
+ÙØ§Ù
+Ø­ ÙØ§Ø¬ÙØ© Ù
+ÙØªØšÙ ÙØ±ÙÙØ³ØªÙÙ Ù
+ØªØ§Ø­Ø©.
+Preferences.Warnings:ØªØ­Ø°ÙØ±
+Preferences.Warnings_Tooltip:ØªÙ
+ÙÙÙ Ø£Ù Ø¥Ø®Ù
+Ø§Ø¯ Ø±Ø³Ø§ØŠÙ Ø§ÙØªØ­Ø°ÙØ±
+Preferences.Workflow:ØªØ¯ÙÙ Ø§ÙØ¹Ù
+Ù
+Preferences.Workflow_Tooltip:ØªØµÙ
+ÙÙ
+ ØªØ¯ÙÙ Ø¹Ù
+Ù Ø§ÙÙØ§Ø¬ÙØ©: ØªØ­Ø¯ÙØ¯ Ø§ÙÙ
+ØŽØ§ÙØ¯ Ø§ÙÙ
+ÙØ¹ÙØ©
+Preferences.Workflow.Predefined.Label:ØªØ¯ÙÙ Ø¹Ù
+Ù Ù
+Ø¹Ø±Ù Ù
+Ù ÙØšÙ
+Preferences.Workflow.Title:Ø¥Ø³ØªØ®Ø¯Ù
+ Ù
+Ø±ØšØ¹ Ø§ÙØ¥Ø®ØªÙØ§Ø± ÙØªÙØ¹ÙÙ Ù
+ØŽÙØ¯
+#**********************
+#
+#**** PreviewCommandDialog *******
+PreviewCommandDialog.Instructions:Ø§Ù
+Ø± Ø¥Ø·ÙØ§Ù ØšØ±ÙØ§Ù
+Ø¬ Ø¹Ø±Ø¶ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©. ØªØ°ÙØ± Ø¥Ø³ØªØ®Ø¯Ø§Ù
+  %1 ÙØ­Ø¬Ø² Ù
+ÙØ§Ù Ø¹ÙÙØ§Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ù
+Ø¹ Ø¥Ø³ØªØ®Ø¯Ø§Ù
+ Ø§ÙØ¹ÙØ§Ù
+Ø§Øª Ø§ÙÙ
+Ø§ØŠÙØ© Ø§ÙÙ
+ÙØ§Ø³ØšØ©.
+PreviewCommandDialog.Title:Ø£Ù
+Ø± Ø§ÙØ¹Ø±Ø¶
+
+ShowPreviousCollection.Title:Ø¹Ø±Ø¶ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙ
+ØšÙÙØ© Ø³Ø§ØšÙØ§
+ShowPreviousCollection.Message:ÙÙ
+ ÙØªÙ
+ ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙØ­Ø¯ÙØ« Ø®Ø·Ø£.Ø£ÙØª ØªØ¹Ø±Ø¶ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙØªÙ Ø³ØšÙ ØšÙØ§Ø€ÙØ§.
+#**********************
+#
+#***** Remote Greenstone Server *****
+RemoteGreenstoneServer.Authentication_Message:Ø§ÙØ±Ø¬Ø§Ø¡ Ø¥Ø¯Ø®Ø§Ù ÙÙÙ
+Ø© Ø¥Ø³Ù
+ Ù
+Ø³ØªØ®Ø¯Ù
+ ÙØ±ÙÙØ³ØªÙÙ Ù ÙÙÙ
+Ø© Ø§ÙØ³Ø±:
+RemoteGreenstoneServer.Error:Ø­Ø¯Ø« Ø®Ø·Ø£ ÙÙ Ù
+Ø²ÙØ¯ ÙØ±ÙÙØ³ØªÙÙ Ø®ÙØ§Ù ØªÙÙÙØ° Ø§ÙØ¹Ù
+ÙÙØ©:\n{0-Error message}
+RemoteGreenstoneServer.Error_Title:Ø®Ø·Ø£ Ù
+Ø²ÙØ¯ ÙØ±ÙÙØ³ØªÙÙ
+RemoteGreenstoneServer.Progress:ØªØ·ÙØ± Ù
+Ø²ÙØ¯ ÙØ±ÙÙØ³ØªÙÙ:
+RemoteGreenstoneServer.Steal_Lock_Message:ÙØ°Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ù
+ØºÙÙØ© ØšÙØ§Ø³Ø·Ø© Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+ '{0-User name}'.\nÙÙ ØªÙØ¯ Ø¥Ù
+ØªÙØ§Ù Ø§ÙÙ
+ÙÙ Ø§ÙÙ
+ØºÙÙ (ÙØ§ ÙÙØµØ­ ØšÙØ°Ø§, Ø±ØšÙ
+Ø§ ÙØ¶ÙØ¹ Ø§ÙØ¹Ù
+Ù)Ø
+#**********************
+#
+#***** Rename Prompt *****
+RenamePrompt.Name:Ø¥Ø³Ù
+:
+RenamePrompt.Title:Ø¥Ø¹Ø§Ø¯Ø© ØªØ³Ù
+ÙØ© Ù
+ÙÙ/Ù
+Ø¬ÙØ¯
+#**********************
+#
+#***** Replace Prompt *****
+ReplacePrompt.Title:Ø¥Ø³ØªØšØ¯Ø§Ù Ù
+ÙÙ Øš...
+#**********************
+#
+#***** Save Collection Box *****
+SaveCollectionBox.File_Name:Ø§Ø³Ù
+ Ø§ÙÙ
+ÙÙ:
+SaveCollectionBox.Files_Of_Type:Ù
+ÙÙØ§Øª Ù
+Ù ÙÙØ¹:
+SaveCollectionBox.Look_In:Ø§ÙÙØžØ± ÙÙ:
+#**********************
+#
+#***** Save Progress Box *******
+SaveProgressDialog.Title:Ø­ÙØž Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+#*******************************
+#
+Server.QuitManual:ÙÙ
+ ÙØ³ØªØ·Ø¹ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ØºÙÙ Ù
+Ø²ÙØ¯ Ø§ÙÙ
+ÙØªØšØ© Ø§ÙÙ
+Ø­ÙÙ ØªÙÙØ§ØŠÙØ§. Ø§ÙØ±Ø¬Ø§Ø¡ ØºÙÙ ÙØ°Ø§ Ø§ÙÙ
+Ø²ÙØ¯ ÙØ¯ÙÙØ§ ØšØ§ÙÙÙØ± Ø¹ÙÙ Ù
+Ø±ØšØ¹ Ø§ÙØºÙÙ ÙÙ Ø§ÙØ±ÙÙ Ø§ÙØ£Ø¹ÙÙ Ø§ÙØ£ÙÙ
+Ù Ø«Ù
+ Ø§ÙÙÙØ± Ø¹ÙÙ  OK ÙÙ Ù
+Ø±ØšØ¹ Ø§ÙØ­ÙØ§Ø± ÙØ°Ø§.
+Server.QuitTimeOut:ÙÙ
+ ØªØ³ØªØ¬Øš Ù
+ÙØªØšØ© ÙØ±ÙÙØ³ØªÙÙ Ø§ÙÙ
+Ø­ÙÙØ© ÙØ§Ù
+Ø± Ø§ÙØºÙÙ ÙÙØªØ±Ø© 60 Ø«Ø§ÙÙØ©. ÙÙ ØªÙØ¯ Ø§ÙØ¥ÙØªØžØ§Ø± ÙÙØªØ±Ø© Ø¯ÙÙÙØ© Ø£Ø®Ø±ÙØ
+#
+#***** Sources *****
+Source.General:Ø¹Ø§Ù
+
+#**********************
+#
+#***** Trees *****
+Tree.DownloadedFiles:Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+ÙØ²ÙØ©
+Tree.Files:Ù
+ÙÙØ§Øª
+Tree.Home:Ù
+Ø¬ÙØ¯ Ø§ÙÙ
+ÙÙØ¹ ({0})
+Tree.Root:Ù
+Ø³Ø§Ø­Ø© Ù
+ÙÙ Ù
+Ø­ÙÙØ©
+Tree.World:ÙØ«Ø§ØŠÙ  Ù
+Ø¬Ù
+ÙØ¹Ø§Øª ÙØ±ÙÙØ³ØªÙÙ
+#***********************
+#
+#***** Warning Dialog *****
+WarningDialog.Dont_Show_Again:ÙØ§ ØªØ¹Ø±Ø¶ ÙØ°Ù Ø§ÙØ±Ø³Ø§ÙØ© Ù
+Ø±Ø© Ø«Ø§ÙÙØ©
+WarningDialog.Dont_Show_Again_Message:ÙØ§ ØªØ¹Ø±Ø¶ ÙØ°Ù Ø§ÙØ±Ø³Ø§ÙØ© Ù
+Ø±Ø© Ø«Ø§ÙÙØ©
+WarningDialog.Invalid_Value:Ø§ÙÙÙÙ
+Ø© Ø§ÙÙ
+Ø¯Ø®ÙØ© ÙÙ ÙÙÙ
+Ø© Ø§ÙØ­ÙÙ ØºÙØ± ØµØ§ÙØ­Ø© Ù
+Ø¹ Ø§ÙØ®ØµØ§ØŠØµ Ø§ÙÙ
+Ø­Ø¯Ø¯Ø©.
+WarningDialog.Value:Ø¥Ø¯Ø®Ù ÙÙÙ
+Ø©:
+#
+#****** WGet *****
+WGet.Prompt:WGet Ù
+ØªØ·Ø§ØšÙØ§Øª Ù
+Ø²ÙØ¯
+#
+#****** Workflows *****
+Workflow.AllPanels:ÙÙ Ø§ÙÙØ§ÙØªØ§Øª
+Workflow.LocalSourceCollectionBuilding:Ø¹ÙØµØ± Ù
+Ø­ÙÙ ÙØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©
+Workflow.DocumentEnriching:Ø¥Ø«Ø±Ø§Ø¡ Ø§ÙÙØ«ÙÙØ©
+
+
+#********GEMS******
+
+GEMS.Title:Ù
+Ø­Ø±Ø± ÙØ±ÙÙØ³ØªÙÙ ÙÙ
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª
+GEMS.OpenMetadataSetPrompt.Title:ÙØªØ­ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª
+GEMS.OpenMetadataSetPrompt.Open_Tooltip:ÙØªØ­ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±
+GEMS.Set_Description:ÙØµÙ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª
+GEMS.OpenMetadataSetPrompt.Open:ÙØªØ­
+GEMS.OpenMetadataSetPrompt.Available_Sets:Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+ØªÙÙØ±Ø©
+GEMS.DeleteMetadataSetPrompt.Title:Ø¥ÙØºØ§Ø¡ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª
+GEMS.DeleteMetadataSetPrompt.Delete_Tooltip:Ø¥ÙØºØ§Ø¡ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±
+GEMS.DeleteMetadataSetPrompt.Delete:Ø¥ÙØºØ§Ø¡
+GEMS.DeleteMetadataSetPrompt.Available_Sets:Ø¥ÙØºØ§Ø¡ Ø§ÙÙ
+Ø¹Ø§ÙÙØ± Ø§ÙÙ
+ØªÙÙØ±Ø©
+GEMS.DeleteMetadataSetPrompt.Confirm_Delete:ØªØ£ÙÙØ¯ Ø§ÙØ¥ÙØºØ§Ø¡
+GEMS.DeleteMetadataSetPrompt.No_Set:ÙØ§ ÙÙØ¬Ø¯ Ù
+Ø¹ÙØ§Ø±
+GEMS.Confirm_Removal:ÙÙ Ø£ÙØª Ù
+ØªØ£ÙØ¯ Ù
+Ù Ø£ÙÙ ØªÙØ¯ Ø­Ø°Ù ÙØ°Ø§ {0}Ø
+GEMS.Confirm_Removal_Title:ØªØ£ÙÙØ¯ Ø§ÙØ­Ø°Ù
+GEMS.Attribute:ØµÙØ©
+GEMS.Popup.AddAttribute:Ø¥Ø¶Ø§ÙØ© ØµÙØ©
+GEMS.Popup.DeleteAttribute:Ø¥ÙØºØ§Ø¡ ØµÙØ©
+GEMS.Popup.AddElement:Ø¥Ø¶Ø§ÙØ© Ø¹ÙØµØ±
+GEMS.Popup.DeleteElement:Ø¥ÙØºØ§Ø¡ Ø¹ÙØµØ±
+GEMS.Popup.AddSubElement:Ø¥Ø¶Ø§ÙØ© Ø¹ÙØµØ± ÙØ±Ø¹Ù
+GEMS.Popup.DeleteSubElement:Ø¥ÙØºØ§Ø¡ Ø¹ÙØµØ± ÙØ±Ø¹Ù
+GEMS.NewMetadataSetPrompt.Title:Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø¬Ø¯ÙØ¯
+GEMS.NewMetadataSetPrompt.Instructions:ÙØ¥ÙØŽØ§Ø¡ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø¬Ø¯ÙØ¯ Ø¥Ø¯Ø®Ù ØšÙØ§ÙØ§Øª Ø§ÙØ­ÙÙÙ Ø£Ø¯ÙØ§Ù:
+GEMS.NewMetadataSetPrompt.Base_MetadataSet:ØªØ£Ø³ÙØ³ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙØ°Ø§ Ø¹ÙÙ:
+GEMS.NewMetadataSetPrompt.Metadata_Title:Ø¹ÙÙØ§Ù Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª:
+GEMS.NewMetadataSetPrompt.Metadata_Namespace:Ø¥Ø³Ù
+ Ù
+Ø³Ø§Ø­Ø© Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª:
+GEMS.NewMetadataSetPrompt.New_Metadata:-- Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø¬Ø¯ÙØ¯ --
+GEMS.NewMetadataSetPrompt.Title_Error_Message:ØªØ¬Øš ØªØ³Ù
+ÙØ© Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØ¬Ø¯ÙØ¯
+GEMS.NewMetadataSetPrompt.Title_Error:ÙÙ
+ ÙØªÙ
+ ØªØ­Ø¯ÙØ¯ Ø¹ÙÙØ§Ù
+GEMS.NewMetadataSetPrompt.Namespace_Error_Message:ÙØ¬Øš ØªÙÙÙØ± Ø¥Ø³Ù
+ Ù
+Ø³Ø§Ø­Ø© ÙÙ
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØ¬Ø¯ÙØ¯
+GEMS.NewMetadataSetPrompt.Namespace_Error:ÙÙ
+ ÙØªÙ
+ ØªØ­Ø¯ÙØ¯ Ø¥Ø³Ù
+ Ù
+Ø³Ø§Ø­Ø©
+GEMS.SelectedLanguage:Ø¥Ø¶Ø§ÙØ© ØµÙØ§Øª ÙÙØºØ©:
+GEMS.Language:--Ø¥Ø®ØªÙØ§Ø± ÙØºØ©--
+GEMS.LanguageDependent:Ø§ÙØµÙØ§Øª ØšØ§ÙÙØºØ©
+GEMS.Attribute_Table:ØµÙØ§Øª
+GEMS.Attribute_Deletion_Error:Ø®Ø·Ø£ Ø¥ÙØºØ§Ø¡ Ø§ÙØµÙØ©
+GEMS.Attribute_Deletion_Error_Message:ÙØ°Ù Ø§ÙØµÙØ© Ù
+Ø·ÙÙØšØ© ÙØ§ ÙÙ
+ÙÙ Ø¥ÙØºØ§Ø€ÙØ§
+GEMS.Attribute_Name_Error:Ø®Ø·Ø£ Ø¥Ø³Ù
+ ØµÙØ©
+GEMS.Attribute_Name_Error_Message:ÙØ¬Øš ØªÙÙÙØ± Ø¥Ø³Ù
+ Ø§ÙØµÙØ©
+GEMS.Add_Lang_Depend_Attr_Error:Ø®Ø·Ø£ Ø§ÙÙØºØ© Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø© ÙÙØµÙØ©
+GEMS.Add_Lang_Depend_Attr_Error_Message:ÙÙ
+ ØªÙÙØ± ØµÙØ©  "Ø§ÙÙØºØ© -Ø§ÙÙ
+Ø³ØªÙÙØ©" Ø Ø§ÙØ±Ø¬Ø§Ø¡ Ø¥Ø¶Ø§ÙØ© ÙØ°Ù Ø§ÙØµÙØ©
+GEMS.Attribute_Edition_Error:Ø®Ø·Ø£ Ø¥ØµØ¯Ø§Ø±Ø© Ø§ÙØµÙØ©
+GEMS.Attribute_Edition_Error_Message:ÙØ°Ù Ø§ÙØµÙØ© Ù
+Ø·ÙÙØšØ© Ù ÙØ§ ÙÙ
+ÙÙ Ø¥ÙØºØ§Ø€ÙØ§
+GEMS.Confirm_Save:Ø­Ø¯Ø« ØªØºÙÙØ± ÙÙ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙØ°Ø§Ø ÙÙ ØªØ±ØºØš ÙÙ Ø­ÙØžÙØ
+GEMS.Confirm_Save_Title:Ø­ÙØž Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª
+GEMS.Confirm_DeleteElement:ÙÙ Ø£ÙØª Ù
+ØªØ£ÙØ¯ Ù
+Ù Ø¥ÙØºØ§Ø¡ Ø§ÙØ¹ÙØµØ± {0}Ø
+GEMS.Confirm_DeleteElement_Title:Ø¥ÙØºØ§Ø¡  Ø¹ÙØµØ±
+GEMS.File_Deletion_Error_Message:ÙØ§ ÙÙ
+ÙÙ Ø¥ÙØºØ§Ø¡ ÙØ°Ø§ Ø§ÙÙ
+ÙÙ
+GEMS.File_Deletion_Error:Ø®Ø·Ø£ Ø¥ÙØºØ§Ø¡ Ù
+ÙÙ
+GEMS.Namespace_Conflict_Message:ØªØ­Ø°ÙØ±: Ø¥Ø³Ù
+ Ø§ÙÙ
+Ø³Ø§Ø­Ø© ÙØ°Ø§ Ù
+Ø³ØªØ®Ø¯Ù
+ Ù
+Ù ÙØšÙ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø¢Ø®Ø±. Ø£Ø³ØªÙ
+Ø± Ø
+GEMS.Namespace_Conflict:Ø¥Ø³Ù
+ Ù
+Ø³Ø§Ø­Ø© Ù
+ØªØ¶Ø§Ø±Øš
+GEMS.Move_Up:ØªØ­Ø±ÙÙ Ø¥ÙÙ Ø§Ø¹ÙÙ
+GEMS.Move_Down:ØªØ­Ø±ÙÙ Ø¥ÙÙ Ø£Ø³ÙÙ
+GEMS.Cannot_Undo:(ÙØ§ ÙÙ
+ÙÙ ÙÙØ¶ ÙØ°Ø§ Ø§ÙØ¥Ø¬Ø±Ø§Ø¡)
+
+GEMS.AttributeTable.Name:Ø¥Ø³Ù
+
+GEMS.AttributeTable.Language:ÙØºØ©
+GEMS.AttributeTable.Value:ÙÙÙ
+Ø©
+GEMS.NewMetadataElementNamePrompt.Title:Ø¹ÙØµØ± Ø¬Ø¯ÙØ¯
+GEMS.NewMetadataElementNamePrompt.Name:Ø§ÙØ±Ø¬Ø§Ø¡ Ø¥Ø¯Ø®Ø§Ù Ø¥Ø³Ù
+ Ø§ÙØ¹ÙØµØ± Ø§ÙØ¬Ø¯ÙØ¯
+GEMS.NewMetadataElementNamePrompt.SubTitle:Ø¹ÙØµØ± ÙØ±Ø¹Ù Ø¬Ø¯ÙØ¯
+GEMS.NewMetadataElementNamePrompt.SubName:Ø§ÙØ±Ø¬Ø§Ø¡ Ø¥Ø¯Ø®Ø§Ù Ø¥Ø³Ù
+ Ø§ÙØ¹ÙØµØ± Ø§ÙÙØ±Ø¹Ù
+GEMS.NewMetadataElementNamePrompt.Name_Error_Message:Ø¹ÙØµØ± ØšÙØ°Ø§ Ø§ÙØ¥Ø³Ù
+ Ù
+ÙØ¬ÙØ¯ Ù
+Ù ÙØšÙ
+GEMS.NewMetadataElementNamePrompt.Name_Error:Ø®Ø·Ø£ Ø¥Ø³Ù
+ Ø¹ÙØµØ±
+GEMS.NewMetadataElementNamePrompt.EmptyName_Error_Message:ÙØ¬Øš ØªÙÙÙØ± Ø¥Ø³Ù
+ ÙÙØ¹ÙØµØ± Ø§ÙØ¬Ø¯ÙØ¯.
+
+
+GEMS.No_Set_Loaded:ÙÙ
+ ÙØªÙ
+ ØªØ­Ù
+ÙÙ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª. Ø§ÙØ±Ø¬Ø§Ø¡ Ø¥Ø³ØªØ®Ø¯Ø§Ù
+  Ù
+ÙÙ->Ø¬Ø¯ÙØ¯ ÙØ¥ÙØŽØ§Ø¡ Ù
+Ø¹ÙØ§Ø± Ø¬Ø¯ÙØ¯, Ø£Ù Ù
+ÙÙ->ÙØªØ­ ÙÙØªØ­ Ù
+Ø¹ÙØ§Ø± Ù
+ÙØ¬ÙØ¯
Index: /tags/greenstone-3_02-distribution/gli/classes/dictionary_el.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gli/classes/dictionary_el.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/classes/dictionary_el.properties	(revision 13928)
@@ -0,0 +1,1804 @@
+#*******************
+#
+#***** AboutDialog *****
+AboutDialog.Acknowledgement:Î Î»Î·ÏÎ¿ÏÎ¿ÏÎ¯ÎµÏ Î³Î¹Î± Î¹ÎŽÎ¹ÏÎºÏÎ·ÏÎ± ÏÏÎ¿Î³ÏÎ¬ÎŒÎŒÎ±ÏÎ± ÏÎ±ÎºÎ­ÏÎ± Î® ÎºÎ»Î¬ÏÎµÎ¹Ï...  # Updated 1-Apr-2005
+AboutDialog.Date:(ÎÎµÎºÎ­ÎŒÎ²ÏÎ·Ï 2006)  # Updated 1-Apr-2005
+AboutDialog.Item0:'Xerces Java 1' Î±ÏÏ ÏÎ¿ Apache Software Foundation (http://www.apache.org/)  # Updated 1-Apr-2005
+AboutDialog.Item2:'WGet' Î±ÏÏ ÏÎ¿ Free Software Foundation, Inc. (http://www.gnu.org/software/wget/wget.html)  # Updated 1-Apr-2005
+AboutDialog.Item3:'qflib' Î±ÏÏ ÏÎ¿ Quality First Software GmbH. (http://www.qfs.de/en/qflib/index.html)  # Updated 1-Apr-2005
+AboutDialog.Item4:'ExtensionFileFilter.class' Î±ÏÏ ÏÎ¿Îœ Bruno Dumon ÎºÎ±Î¹ Î¬Î»Î»Î¿Ï
+Ï (http://pollo.sourceforge.net/)  # Updated 1-Apr-2005
+AboutDialog.Item5:'Î ÏÏ ÎœÎ± Î±ÏÎµÎœÎµÏÎ³Î¿ÏÎ¿Î¹Î®ÏÎµÏÎµ ÏÎ· ÎŒÎµÏÎ¿ÎœÎ¿ÎŒÎ±ÏÎ¯Î± ÏÎ±ÎºÎ­Î»ÏÎœ ÏÏÎ·Îœ ÎµÏÎ¹Î»Î¿Î³Î® ÏÎ±ÎºÎ­Î»ÏÎœ' - vladi21 (http://www.experts-exchange.com/)  # Updated 1-Apr-2005
+AboutDialog.Item6:'Autoscrolling' - Java Swing Î±ÏÏ ÏÎ¿Îœ Robert Eckstein, Marc Loy & Dave Wood (http://www.oreilly.com/catalog/jswing/chapter/dnd.beta.pdf)  # Updated 1-Apr-2005
+AboutDialog.Item7:'Î ÏÎ¿ÏÎžÎ®ÎºÎ· ghosted ÎµÎ¹ÎºÏÎœÏÎœ ÏÎµ JTrees' - By Andrew J. Armstrong (http://www.javaworld.com/javaworld/javatips/jw-javatip114.html)  # Updated 1-Apr-2005
+AboutDialog.Item8:'Î£ÏÎ±ÎŒÎ¬ÏÎ·ÎŒÎ± ÏÎ¿Ï
+ Î»Î¬ÎžÎ¿Ï
+Ï java.prefs Î»ÏÎ³Ï Î­Î»Î»ÎµÎ¹ÏÎ·Ï ÎŽÎ¹ÎºÎ±Î¹ÏÎŒÎ¬ÏÏÎœ' - Thanks to Walter Schatz  # Updated 1-Apr-2005
+AboutDialog.Java_Req:Î Java ÎµÎ¯ÎœÎ±Î¹ trademark ÏÎ·Ï Sun Microsystems Inc. Î€Î¿ JRE ÎŽÎ¹Î±ÎœÎ­ÎŒÎµÏÎ±Î¹ ÎŒÎµ ÏÎ·Îœ Î¬ÎŽÎµÎ¹Î± ÎºÎ±Î¹ ÏÎ¿Ï
+Ï ÏÏÎ¿Ï
+Ï ÏÏÎ¿ http://java.sun.com/j2se/1.4.1/j2re-1_4_1_02-license.html  # Updated 1-Apr-2005
+AboutDialog.Java_Req_One:Î ÎµÏÎ¹Î»Î±ÎŒÎ²Î¬ÎœÎµÎ¹ ÎºÏÎŽÎ¹ÎºÎµÏ ÎŒÎµ Î¬ÎŽÎµÎ¹Î± Î±ÏÏ ÏÎ¿ RSA Security, Inc.  # Updated 1-Apr-2005
+AboutDialog.Java_Req_Two:ÎÎµ Î¬ÎŽÎµÎ¹Î± Î±ÏÏ ÏÎ·Îœ IBM http://oss.software.ibm.com/icu4j/  # Updated 1-Apr-2005
+AboutDialog.Thanks:ÎÏ
+ÏÎ±ÏÎ¹ÏÏÎ¯ÎµÏ ÏÎµ ÏÏÎ¿Ï
+Ï ÎŸÎ­ÏÎ¿Ï
+Îœ java ÎºÎ±Î¹ Î²Î¿Î®ÎžÎ·ÏÎ±Îœ...  # Updated 1-Apr-2005
+AboutDialog.Title:Î£ÏÎµÏÎ¹ÎºÎ¬...  # Updated 1-Apr-2005
+AboutDialog.Title_One:ÎÎ¹ÎµÏÎ±ÏÎ® ÎÎ¹Î±ÏÎµÎ¯ÏÎ¹ÏÎ·Ï Greenstone  # Updated 1-Apr-2005
+AboutDialog.Title_Two:ÎÎ¹ÎµÏÎ±ÏÎ® ÎÎ¹Î±ÏÎµÎ¯ÏÎ¹ÏÎ·Ï Greenstone, Î Î±ÎœÎµÏÎ¹ÏÏÎ®ÎŒÎ¹Î¿ Waikato  # Updated 1-Apr-2005
+AboutDialog.Copyright:Copyright (C) 2006 New Zealand Digital Library Project  # Updated 1-Apr-2005
+AboutDialog.Copyright_Two:ÎÎ¬ÏÏ Î±ÏÏ ÏÎ·Îœ GPL Î¬ÎŽÎµÎ¹Î±. ÎÎ»Î­ÏÎµ LICENSE.txt Î³Î¹Î± Î»ÎµÏÏÎ¿ÎŒÎ­ÏÎµÎ¹ÎµÏ.  # Updated 1-Apr-2005
+#***********************
+#
+#***** Audit Table *****
+AuditTable.File:ÎÎœÎ¿ÎŒÎ± ÎÏÏÎµÎ¯Î¿Ï
+  # Updated 1-Apr-2005
+#***********************
+#
+#***** Auto Filter *****
+Autofilter.AND:ÎÎÎ  # Updated 1-Apr-2005
+Autofilter.Ascending:ÎÏÎŸÎ¿Ï
+ÏÎ±  # Updated 1-Apr-2005
+Autofilter.Case_Sensitive:ÎÎ¹Î±ÏÏÏÎ¹ÏÎŒÏÏ ÎÎµÏÎ±Î»Î±Î¯Î±-Î ÎµÎ¶Î¬  # Updated 1-Apr-2005
+Autofilter.Custom_Filter:ÎÎ¹Î± Î ÏÎ¿ÏÏÏÎ·ÎŒÎ­ÎœÎ¿Ï
+Ï  # Updated 1-Apr-2005
+Autofilter.Descending:ÎŠÎžÎ¯ÎœÎ¿Ï
+ÏÎ±  # Updated 1-Apr-2005
+Autofilter.Filter_By_Value:ÎÏÎ»Ï  # Updated 1-Apr-2005
+Autofilter.Name:ÎÎœÎ¿ÎŒÎ± Î£ÏÎ®Î»Î·Ï  # Updated 1-Apr-2005
+Autofilter.None:ÎÎ±ÎœÎ­ÎœÎ±  # Updated 1-Apr-2005
+Autofilter.Operator:ÎÎ±ÏÎ¬ÏÏÎ±ÏÎ·  # Updated 1-Apr-2005
+Autofilter.OR:Î  # Updated 1-Apr-2005
+Autofilter.Order:ÎÎ¹Î¬ÏÎ±ÎŸÎ·  # Updated 1-Apr-2005
+Autofilter.Order_Tooltip:Î€Î±ÎŸÎ¹ÎœÏÎŒÎ·ÏÎµ ÏÎ± Î±ÏÎ¿ÏÎµÎ»Î­ÏÎŒÎ±ÏÎ± ÎŒÎµ Î±Ï
+ÏÎ® ÏÎ· ÏÎµÎ¹ÏÎ¬  # Updated 1-Apr-2005
+Autofilter.Remove:ÎÏÎ±Î¯ÏÎµÏÎ· ÎŠÎ¯Î»ÏÏÎ¿Ï
+  # Updated 1-Apr-2005
+Autofilter.Remove_Tooltip:ÎÏÎ±Î¯ÏÎµÏÎ· ÏÎ¯Î»ÏÏÎ¿Ï
+ Î±ÏÏ Î±Ï
+ÏÎ® ÏÎ· ÏÏÎ®Î»Î·  # Updated 1-Apr-2005
+Autofilter.Set:ÎÎ­ÏÎµ ÎŠÎ¯Î»ÏÏÎ¿  # Updated 1-Apr-2005
+Autofilter.Set_Tooltip:Î ÏÏÏÎžÎµÏÎµ ÏÎ¿ ÏÎ¯Î»ÏÏÎ¿ ÏÎµ Î±Ï
+ÏÎ® ÏÎ· ÏÏÎ®Î»Î·  # Updated 1-Apr-2005
+Autofilter.Table_Header_Tooltip:Î€Î±ÎŸÎ¹ÎœÏÎŒÎ·ÏÎµ ÎºÎ±ÏÎ¬ {0}  # Updated 1-Apr-2005
+Autofilter.Title:ÎÏ
+ÏÏÎŒÎ±ÏÎ¿ ÏÎ¹Î»ÏÏÎ¬ÏÎ¹ÏÎŒÎ± ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ  # Updated 1-Apr-2005
+Autofilter.eqeq:Î¯ÏÎ¿ ÎŒÎµ  # Updated 1-Apr-2005
+Autofilter.!eq:ÏÏÎ¹ Î¯ÏÎ¿ ÎŒÎµ  # Updated 1-Apr-2005
+Autofilter.<:ÎŒÎ¹ÎºÏÏÏÎµÏÎ¿ Î±ÏÏ  # Updated 1-Apr-2005
+Autofilter.<eq:ÎŒÎ¹ÎºÏÏÏÎµÏÎ¿ Î® Î¯ÏÎ¿  # Updated 1-Apr-2005
+Autofilter.>:ÎŒÎµÎ³Î±Î»ÏÏÎµÏÎ¿ Î±ÏÏ  # Updated 1-Apr-2005
+Autofilter.>eq:ÎŒÎµÎ³Î±Î»ÏÏÎµÏÎ¿ Î® Î¯ÏÎ¿  # Updated 1-Apr-2005
+Autofilter.^:ÎŸÎµÎºÎ¹ÎœÎ¬ÎµÎ¹ ÎŒÎµ  # Updated 1-Apr-2005
+Autofilter.!^:ÎŽÎµÎœ ÎŸÎµÎºÎ¹ÎœÎ¬ÎµÎ¹ ÎŒÎµ  # Updated 1-Apr-2005
+Autofilter.$:ÏÎµÎ»ÎµÎ¹ÏÎœÎµÎ¹ ÎŒÎµ  # Updated 1-Apr-2005
+Autofilter.!$:ÎŽÎµÎœ ÏÎµÎ»ÎµÎ¹ÏÎœÎµÎ¹ ÎŒÎµ  # Updated 1-Apr-2005
+Autofilter.?:ÏÎµÏÎ¹Î­ÏÎµÎ¹  # Updated 1-Apr-2005
+Autofilter.!?:ÎŽÎµÎœ ÏÎµÏÎ¹Î­ÏÎµÎ¹  # Updated 1-Apr-2005
+#
+#     ********************************************************
+#     *************** Collection Design Module ***************
+#     ********************************************************
+#     * The dictionary  phrases  used in the creation of the *
+#     * Colection  Design  Module. Note that we  still  have *
+#     * access  to the format  arguments (argument  32+) for *
+#     * html formatting.                                     *
+#     ********************************************************
+CDM.ArgumentConfiguration.Add:Î ÏÏÏÎžÎµÏÎµ  # Updated 1-Apr-2005
+CDM.ArgumentConfiguration.Bad_Integer:<html>Î€Î¿ ÏÏÎ¹ÏÎŒÎ± '{0}' Î±ÏÎ±Î¹ÏÎµÎ¯ ÎŒÎ¹Î± Î±ÎºÎ­ÏÎ±Î¹Î± ÏÎ¹ÎŒÎ®,<br>Î±Î»Î»Î¬ ÎºÎ±ÎŒÎ¯Î± ÎŽÎµ ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± Î²ÏÎµÎžÎµÎ¯ Î±ÏÏ ÏÎ¿ {1}.</html>  # Updated 1-Apr-2005
+CDM.ArgumentConfiguration.Custom_Header:Î€ÏÎ¿ÏÎ¿ÏÎ¿Î¯ÏÎ·  # Updated 1-Apr-2005
+CDM.ArgumentConfiguration.Custom:ÎÏÎ¯ÏÎŒÎ±ÏÎ± Î€ÏÎ¿ÏÎ¿ÏÎ¿Î¯Î·ÏÎ·Ï  # Updated 1-Apr-2005
+CDM.ArgumentConfiguration.Error_Title:ÎÎ¬ÎžÎ¿Ï ÏÏÎ± Î¿ÏÎ¯ÏÎŒÎ±ÏÎ±  # Updated 1-Apr-2005
+CDM.ArgumentConfiguration.Header:{39}{46}Î¡Ï
+ÎžÎŒÎ¯ÏÏÎµ ÏÎ± Î¿ÏÎ¯ÏÎŒÎ±ÏÎ± Î³Î¹Î± {0}.{47}{34}  # Updated 1-Apr-2005
+CDM.ArgumentConfiguration.No_Value:ÏÎ¿ ÏÏÎ¹ÏÎŒÎ± '{0}' Î±ÏÎ±Î¹ÏÎµÎ¯ ÎŒÎ¹Î± ÏÎ¹ÎŒÎ® Î±Î»Î»Î¬ ÎºÎ±ÎŒÎ¯Î± ÎŽÎµÎœ Î­ÏÎµÎ¹ Î¿ÏÎ¹ÏÏÎµÎ¯.  # Updated 1-Apr-2005
+CDM.ArgumentConfiguration.Remove:ÎÏÎ±Î¯ÏÎµÏÎ·  # Updated 1-Apr-2005
+CDM.ArgumentConfiguration.Required_Argument:Î ÏÎ­ÏÎµÎ¹ ÎœÎ± ÎŽÏÎžÎµÎ¯ ÏÎ¹ÎŒÎ® ÏÏÎ¿ ÏÏÎ¹ÏÎŒÎ± '{0}'.  # Updated 1-Apr-2005
+CDM.ArgumentConfiguration.Title:Î¡ÏÎžÎŒÎ¹ÏÎ· Î¿ÏÎ¹ÏÎŒÎ¬ÏÏÎœ  # Updated 1-Apr-2005
+CDM.ClassifierManager.Add:Î ÏÎ¿ÏÎžÎ®ÎºÎ· Î€Î±ÎŸÎ¹ÎœÎ¿ÎŒÎ·ÏÎ®  # Updated 1-Apr-2005
+CDM.ClassifierManager.Add_Tooltip:Î§ÏÎ®ÏÎ· ÎºÎ±ÎžÎ¿ÏÎ¹ÏÎŒÎ­ÎœÎ¿Ï
+ ÏÎ±ÎŸÎ¹ÎœÎ¿ÎŒÎ·ÏÎ® Î³Î¹Î± ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î® Î±Ï
+ÏÎ®.  # Updated 1-Apr-2005
+CDM.ClassifierManager.Assigned:Î¥ÏÎ¬ÏÏÎ¿ÎœÏÎµÏ ÏÎ±ÎŸÎ¹ÎœÎ¿ÎŒÎ·ÏÎ­Ï  # Updated 1-Apr-2005
+CDM.ClassifierManager.Classifier:ÎÏÎ¹Î»Î¿Î³Î· ÏÎ±ÎŸÎ¹ÎœÎ¿ÎŒÎ·ÏÎ® Î³Î¹Î± ÏÏÎ¿ÏÎžÎ®ÎºÎ·:  # Updated 1-Apr-2005
+CDM.ClassifierManager.Classifier_Tooltip:ÎÎ¹ ÏÎ±ÎŸÎ¹ÎœÎ¿ÎŒÎ·ÏÎ­Ï ÎŽÎ¹Î±ÎžÎ­ÏÎ¹ÎŒÎ¿Î¹ Î³Î¹Î± ÏÏÎ®ÏÎ·  # Updated 1-Apr-2005
+CDM.ClassifierManager.Classifier_Exists:ÎÏ
+ÏÏÏ Î¿ ÏÎ±ÎŸÎ¹ÎœÎ¿ÎŒÎ·ÏÎ®Ï Î­ÏÎµÎ¹ Î®ÎŽÎ· ÎºÎ±ÏÎ±ÏÏÏÎ¹ÎžÎµÎ¯ Î³Î¹Î± ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î® Î±Ï
+ÏÎ®  # Updated 1-Apr-2005
+CDM.ClassifierManager.Classifier_Str:Î€Î±ÎŸÎ¹ÎœÎ¿ÎŒÎ·ÏÎ®Ï  # Updated 1-Apr-2005
+CDM.ClassifierManager.Classifier_XML_Parse_Failed:ÎÎŽÏÎœÎ±ÏÎ¿Îœ ÎœÎ± ÏÏÎ¿ÏÎŽÎ¹Î¿ÏÎ¹ÏÏÎ¿ÏÎœ ÏÎ± Î¿ÏÎ¯ÏÎŒÎ±ÏÎ± Î³Î¹Î± ÏÎ¿Îœ ÏÎ±ÎŸÎ¹ÎœÎ¿ÎŒÎ·ÏÎ® {0}\n. ÎÏÎ¹Î²ÎµÎ²Î±Î¹ÏÏÏÎµ ÏÏÎ¹ Î¿ ÏÎ±ÎŸÎ¹ÎœÎ¿ÎŒÎ·ÏÎ®Ï\nÏÎ±ÏÎ­ÏÎµÎ¹ ÏÎ¿ -xml flag ÏÏÎ­ÏÎ¿ÎœÏÎ±Ï ÏÎ¿ classinfo.pl script.  # Updated 1-Apr-2005
+CDM.ClassifierManager.Configure:Î¡ÏÎžÎŒÎ¹ÏÎ· ÏÎ±ÎŸÎ¹ÎœÎ¿ÎŒÎ·ÏÎ®  # Updated 1-Apr-2005
+CDM.ClassifierManager.Configure_Tooltip:ÎÎ»Î»Î±Î³Î® ÏÏ
+ÎžÎŒÎ¯ÏÎµÏÎœ ÏÎ¿Ï
+ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿Ï
+ ÏÎ±ÎŸÎ¹ÎœÎ¿ÎŒÎ·ÏÎ®  # Updated 1-Apr-2005
+CDM.ClassifierManager.Remove:ÎÏÎ±Î¯ÏÎµÏÎ· Î€Î±ÎŸÎ¹ÎœÎ¿ÎŒÎ·ÏÎ®  # Updated 1-Apr-2005
+CDM.ClassifierManager.Remove_Tooltip:ÎÏÎ±Î¯ÏÎµÏÎ· ÏÎ±ÎŸÎ¹ÎœÎ¿ÎŒÎ·ÏÎ® Î±ÏÏ ÏÎ· Î»Î¯ÏÏÎ±  # Updated 1-Apr-2005
+CDM.ClassifierManager.Parsing.Message:Î€Î¿ ÎµÏÎ³Î±Î»ÎµÎ¯Î¿ ÏÏÎµÎŽÎ¯Î±ÏÎ·Ï ÏÎ¿ÏÏÏÎœÎµÎ¹ ÏÎ»Î·ÏÎ¿ÏÎ¿ÏÎ¯ÎµÏ Î³Î¹Î± ÏÎ¿Îœ ÏÎ±ÎŸÎ¹ÎœÎ¿ÎŒÎ·ÏÎ®.  # Updated 1-Apr-2005
+CDM.ClassifierManager.Parsing.Title:ÎŠÏÏÏÏÏÎ· Î€Î±ÎŸÎ¹ÎœÎ¿ÎŒÎ·ÏÏÎœ  # Updated 1-Apr-2005
+CDM.FormatManager.Add:Î ÏÎ¿ÏÎžÎ®ÎºÎ· ÎÎ¿ÏÏÎ¿ÏÎ¿Î¯Î·ÏÎ·Ï  # Updated 1-Apr-2005
+CDM.FormatManager.Add_Tooltip:Î§ÏÎ·ÏÎ¹ÎŒÎ¿ÏÎ¿Î¯Î·ÏÎµ ÏÎ·Îœ ÎºÎ±ÎžÎ¿ÏÎ¹ÏÎŒÎ­ÎœÎ· ÎµÎœÏÎ¿Î»Î® ÎŒÎ¿ÏÏÎ¿ÏÎ¿Î¯Î·ÏÎ·Ï ÎŒÎµ ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+CDM.FormatManager.Assigned_Formats:ÎÎ±ÏÎ±ÏÏÏÎ·ÎŒÎ­ÎœÎµÏ ÎÎœÏÎ¿Î»Î­Ï ÎŒÎ¿ÏÏÎ¿ÏÎ¿Î¯Î·ÏÎ·Ï  # Updated 1-Apr-2005
+CDM.FormatManager.Editor:HTML Format String  # Updated 1-Apr-2005
+CDM.FormatManager.Editor_Tooltip:ÎÎ¹ÏÎ¬Î³ÎµÏÎµ ÏÎ·Îœ ÎµÎœÏÎ¿Î»Î® ÎŒÎ¿ÏÏÎ¿ÏÎ¿Î¯Î·ÏÎ·Ï ÎµÎŽÏ  # Updated 1-Apr-2005
+CDM.FormatManager.Enabled:ÎÎœÎµÏÎ³Î¿ÏÎ¿Î¹Î·ÎŒÎ­ÎœÎ¿  # Updated 1-Apr-2005
+CDM.FormatManager.Feature:ÎÏÎ¹Î»Î¿Î³Î® ÏÎ±ÏÎ±ÎºÏÎ·ÏÎ¹ÏÏÎ¹ÎºÎ¿Ï  # Updated 1-Apr-2005
+CDM.FormatManager.Feature_Tooltip:Î€Î¿ ÏÎ±ÏÎ±ÎºÏÎ·ÏÎ¹ÏÏÎ¹ÎºÏ ÏÏÎ¿Ï ÎŒÎ¿ÏÏÎ¿ÏÎ¿Î¯Î·ÏÎ·  # Updated 1-Apr-2005
+CDM.FormatManager.Insert:ÎÎ¹ÏÎ±Î³ÏÎ³Î®  # Updated 1-Apr-2005
+CDM.FormatManager.Insert_Tooltip:ÎÎ¹ÏÎ±Î³ÏÎ³Î® ÏÎ·Ï ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ·Ï ÎŒÎµÏÎ±Î²Î»Î·ÏÎ®Ï ÏÏÎ·Îœ ÎµÎœÏÎ¿Î»Î® ÎŒÎ¿ÏÏÎ¿ÏÎ¿Î¯Î·ÏÎ·Ï  # Updated 1-Apr-2005
+CDM.FormatManager.Part:ÎÏÎ·ÏÎµÎ±Î¶ÏÎŒÎµÎœÎ¿ Component  # Updated 1-Apr-2005
+CDM.FormatManager.Part_Tooltip:Î£ÏÎ¿Î¹ÏÎµÎ¯Î¿ ÏÏÎ¿Ï ÎŒÎ¿ÏÏÎ¿ÏÎ¿Î¯Î·ÏÎ· ÏÎ¿Ï
+ ÏÎ±ÏÎ±ÎºÏÎ·ÏÎ¹ÏÏÎ¹ÎºÎ¿Ï  # Updated 1-Apr-2005
+CDM.FormatManager.Remove:ÎÏÎ±Î¯ÏÎµÏÎ· ÎŒÎ¿ÏÏÎ¿ÏÎ¿Î¯Î·ÏÎ·Ï  # Updated 1-Apr-2005
+CDM.FormatManager.Remove_Tooltip:ÎÏÎ±Î¯ÏÎµÏÎ· ÎµÎœÏÎ¿Î»Î®Ï ÎŒÎ¿ÏÏÎ¿ÏÎ¿Î¯Î·ÏÎ·Ï Î±ÏÏ ÏÎ· Î»Î¯ÏÏÎ±  # Updated 1-Apr-2005
+CDM.FormatManager.Replace:ÎÎœÏÎ¹ÎºÎ±Ï=Î¬ÏÏÎ±ÏÎ· ÎŒÎ¿ÏÏÎ¿ÏÎ¿Î¯Î·ÏÎ·Ï  # Updated 1-Apr-2005
+CDM.FormatManager.Replace_Tooltip:ÎÎœÎ·ÎŒÎ­ÏÏÏÎ· ÏÎ·Ï ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ·Ï ÎµÎœÏÎ¿Î»Î®Ï ÎŒÎ¿ÏÏÎ¿ÏÎ¿Î¯Î·ÏÎ·Ï  # Updated 1-Apr-2005
+CDM.FormatManager.Variable:ÎÎµÏÎ±Î²Î»Î·ÏÎ­Ï  # Updated 1-Apr-2005
+CDM.FormatManager.Variable_Tooltip:ÎÎµÏÎ±Î²Î»Î·ÏÎ­Ï Î³Î¹Î± ÏÏÎ®ÏÎ· ÎŒÎµ ÏÎ·Îœ ÎµÎœÏÎ¿Î»Î® ÎŒÎ¿ÏÏÎ¿ÏÎ¿Î¯Î·ÏÎ·Ï  # Updated 1-Apr-2005
+CDM.General.Access:ÎÏ
+ÏÎ® Î· ÏÏ
+Î»Î»Î¿Î³Î® ÎœÎ± ÎµÎ¯ÎœÎ±Î¹ ÎŽÎ·ÎŒÏÏÎ¹Î± ÏÏÎ¿ÏÏÎµÎ»Î¬ÏÎ¹ÎŒÎ·  # Updated 1-Apr-2005
+CDM.General.Browser_Title:ÎÏÎ¹Î»Î¿Î³Î® ÎÎ¹ÎºÏÎœÎ±Ï  # Updated 1-Apr-2005
+CDM.General.Collection_Extra:Î ÎµÏÎ¹Î³ÏÎµÏÎ® Î£Ï
+Î»Î»Î¿Î³Î®Ï:  # Updated 1-Apr-2005
+CDM.General.Collection_Extra_Tooltip:Î ÎµÏÎ¹Î³ÏÎ±ÏÎ® ÏÎ¿Ï
+ ÏÎµÏÎ¹ÎµÏÎ¿ÎŒÎ­ÎœÎ¿Ï
+ ÎºÎ±Î¹ ÏÎ¿Ï
+ ÏÎºÎ¿ÏÎ¿Ï ÏÎ·Ï ÏÏ
+Î»Î»Î¿Î³Î®Ï  # Updated 1-Apr-2005
+CDM.General.Collection_Name:ÏÎ¯ÏÎ»Î¿Ï Î£Ï
+Î»Î»Î¿Î³Î®Ï:  # Updated 1-Apr-2005
+CDM.General.Collection_Name_Tooltip:ÎÎœÎ¿ÎŒÎ± Î£Ï
+Î»Î»Î¿Î³Î®Ï  # Updated 1-Apr-2005
+CDM.General.Email.Creator:Email ÎÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¿Ï  # Updated 1-Apr-2005
+CDM.General.Email.Creator_Tooltip:E-mail ÏÎ¿Ï
+ ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¿Ï ÏÎ·Ï ÏÏ
+Î»Î»Î¿Î³Î®Ï  # Updated 1-Apr-2005
+CDM.General.Email.Maintainer:E-mail ÏÏ
+ÎœÏÎ·ÏÎ·ÏÎ®  # Updated 1-Apr-2005
+CDM.General.Email.Maintainer_Tooltip:E-mail ÏÎ¿Ï
+ ÏÏ
+ÎœÏÎ·ÏÎ·ÏÎ® ÏÎ·Ï ÏÏ
+Î»Î»Î¿Î³Î®Ï  # Updated 1-Apr-2005
+CDM.General.Icon_Collection:URL ÏÏÎ¿Ï ÏÎ¿ 'about page' icon:  # Updated 1-Apr-2005
+CDM.General.Icon_Collection_Tooltip:Î€Î¿ URL ÏÎ·Ï ÎµÎ¹ÎºÏÎœÎ±Ï ÏÎ¿Ï
+ ÎžÎ± ÏÏÎ¿Î²Î»Î·ÎžÎµÎ¯ ÏÏÎ·Îœ about page  # Updated 1-Apr-2005
+CDM.General.Icon_Collection_Small:URL ÏÏÎ¿ 'home page' icon:  # Updated 1-Apr-2005
+CDM.General.Icon_Collection_Small_Tooltip:Î€Î¿ URL ÏÎ·Ï ÎµÎ¹ÎºÏÎœÎ±Ï ÏÎ·Ï ÎºÎµÎœÏÏÎ¹ÎºÎ®Ï ÏÎµÎ»Î¯ÎŽÎ±Ï ÏÎ·Ï ÏÏ
+Î»Î»Î¿Î³Î®Ï  # Updated 1-Apr-2005
+CDM.General.Image_Copy_Failed:Î£ÏÎ¬Î»ÎŒÎ±, ÎŽÎµ ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± Î±ÎœÏÎ¹Î³ÏÎ±ÏÎµÎ¯ ÏÎ¿ Î±ÏÏÎµÎ¯Î¿ ÎµÎ¹ÎºÏÎœÎ±Ï.\nÎ ÏÎ¿ÏÏÎ±ÎžÎµÎ¯ÏÏÎµ ÎœÎ± ÏÎ¿ Î±ÎœÏÎ¹Î³ÏÎ¬ÏÎµÏÎµ ÏÎµÎ¹ÏÎ¿ÎºÎ¯ÎœÎ·ÏÎ±  # Updated 1-Apr-2005
+CDM.General.Image_Filter:ÎÎ¹ÎºÏÎœÎµÏ (gifs, jpgs ÎºÎ±Î¹ pngs)  # Updated 1-Apr-2005
+CDM.GUI.Classifiers:Î€Î±ÎŸÎ¹ÎœÎ¿ÎŒÎ·ÏÎ­Ï Î Î»Î¿Î®Î³Î·ÏÎ·Ï  # Updated 1-Apr-2005
+CDM.GUI.Design_Topics:ÎÎœÏÏÎ·ÏÎµÏ Î£ÏÎµÎŽÎ¯Î±ÏÎ·Ï  # Updated 1-Apr-2005
+CDM.GUI.Formats:Î§Î±ÏÎ±ÎºÏÎ·ÏÎ¹ÏÏÎ¹ÎºÎ¬ ÎÎ¿ÏÏÎ¿ÏÎ¿Î¯Î·ÏÎ·Ï  # Updated 1-Apr-2005
+CDM.GUI.General:ÎÎµÎœÎ¹ÎºÎ¬  # Updated 1-Apr-2005
+CDM.GUI.Indexes:ÎÏ
+ÏÎµÏÎ®ÏÎ¹Î± ÎÎœÎ±Î¶Î®ÏÎ·ÏÎ·Ï  # Updated 1-Apr-2005
+CDM.GUI.MetadataSets:Î£ÏÎœÎ¿Î»Î± ÎÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ  # Updated 1-Apr-2005
+CDM.GUI.Plugins:Plugins ÎÏÏÎµÎ¯ÏÎœ  # Updated 1-Apr-2005
+CDM.GUI.Root:ÎÎ¡Î§Î  # Updated 1-Apr-2005
+CDM.GUI.SearchTypes:ÎÎ¯ÎŽÎ· ÎÎœÎ±Î¶Î®ÏÎ·ÏÎ·Ï  # Updated 1-Apr-2005
+CDM.GUI.Subcollections:ÎÎ¹Î±Î¯ÏÎµÏÎ· ÎÏ
+ÏÎµÏÎ·ÏÎ¯ÏÎœ  # Updated 1-Apr-2005
+CDM.GUI.SuperCollection:ÎÎ¹Î±Î£Ï
+Î»Î»Î¿Î³Î¹ÎºÎ® ÎÎœÎ±Î¶Î®ÏÎ·ÏÎ·  # Updated 1-Apr-2005
+CDM.GUI.Translation:ÎÎµÏÎ¬ÏÏÎ±ÏÎ· ÎºÎµÎ¹ÎŒÎ­ÎœÎ¿Ï
+  # Updated 1-Apr-2005
+CDM.HelpButton:ÎÎ¿Î®ÎžÎµÎ¹Î± Î³Î¹Î± Î±Ï
+ÏÎ® ÏÎ·Îœ Î¿ÎžÏÎœÎ·
+CDM.HelpButton_Tooltip:ÎÎœÎ¿Î¹ÎŸÏÎµ ÏÎ· Î²Î¿Î®ÎžÎµÎ¹Î± ÏÎ¿Ï
+ GLI Î³Î¹Î± Î±Ï
+ÏÎ® ÏÎ·Îœ Î¿ÎžÏÎœÎ·
+CDM.IndexManager.Add_Index:Î ÏÎ¿ÏÎžÎ®ÎºÎ· ÎÏ
+ÏÎµÏÎ·ÏÎ¯Î¿Ï
+  # Updated 1-Apr-2005
+CDM.IndexManager.Add_Index_Tooltip:ÎÎ±ÏÎ±ÏÎºÎµÏ
+Î® ÏÎ¿Ï
+ ÎºÎ±ÎžÎ¿ÏÎ¹ÏÎŒÎ­ÎœÎ¿Ï
+ ÎµÏ
+ÏÎµÏÎ·ÏÎ¯Î¿Ï
+ Î³Î¹' Î±Ï
+ÏÎ® ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+CDM.IndexManager.Allfields_Index:Î ÏÎ¿ÏÎžÎ­ÏÏÎµ ÏÏ
+ÎœÎŽÏ
+Î±ÏÏÎ¹ÎºÎ® Î±ÎœÎ±Î¶Î®ÏÎ·ÏÎ· ÏÎµ ÏÎ»Î± ÏÎ± ÎµÏ
+ÏÎµÏÎ®ÏÎ¹Î±
+CDM.IndexManager.Default_Index_Indicator:[Î ÏÎ¿ÎºÎ±ÎžÎ¿ÏÎ¹ÏÎŒÎ­ÎœÎ¿ ÎÏ
+ÏÎµÏÎ®ÏÎ¹Î¿]  # Updated 1-Apr-2005
+CDM.IndexManager.Document:Î­Î³Î³ÏÎ±ÏÎ¿  # Updated 1-Apr-2005
+CDM.IndexManager.Index_Exists:ÎÏ
+ÏÏ ÏÎ¿ ÎÏ
+ÏÎµÏÎ®ÏÎ¹Î¿ Î­ÏÎµÎ¹ Î®ÎŽÎ· ÎºÎ±ÏÎ±ÏÏÏÎ·ÎžÎµÎ¯ Î³Î¹Î± Î±Ï
+ÏÎ® ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+CDM.IndexManager.Index_Name:ÎÎœÎ¿ÎŒÎ± ÎÏ
+ÏÎµÏÎ·ÏÎ¯Î¿Ï
+:  # Updated 1-Apr-2005
+CDM.IndexManager.Index_Name_Tooltip:ÏÎ¿ ÎŒÎ¿ÎœÎ±ÎŽÎ¹ÎºÏ ÎÎœÎ¿ÎŒÎ± Î³Î¹Î± ÏÎ¿ ÎœÎ­Î¿ ÎÏ
+ÏÎµÏÎ®ÏÎ¹Î¿  # Updated 1-Apr-2005
+CDM.IndexManager.Indexes:ÎÎ±ÏÎ±ÏÏÏÎ·ÎŒÎ­ÎœÎ± ÎÏ
+ÏÎµÏÎ®ÏÎ¹Î±  # Updated 1-Apr-2005
+CDM.IndexManager.Level:Î£ÏÎ¿ ÎÏÎ¯ÏÎµÎŽÎ¿:  # Updated 1-Apr-2005
+CDM.IndexManager.Level_Exists:ÎÏ
+ÏÏ ÏÎ¿ ÎµÏÎ¯ÏÎµÎŽÎ¿ Î­ÏÎµÎ¹ Î®ÎŽÎ· ÎºÎ±ÏÎ±ÏÏÏÎ·ÎžÎµÎ¯ Î³Î¹Î± Î±Ï
+ÏÎ® ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+CDM.IndexManager.Level_Tooltip:Î€Î¿ ÎµÏÎ¯ÏÎµÎŽÎ¿ ÏÎ¿Ï
+ ÎµÎ³Î³ÏÎ¬ÏÎ¿Ï
+ ÏÏÎ¿ Î¿ÏÎ¿Î¯Î¿ ÎžÎ± ÏÏÎ¹ÏÏÎµÎ¯ ÏÎ¿ ÎÏ
+ÏÎµÏÎ®ÏÎ¹Î¿  # Updated 1-Apr-2005
+CDM.IndexManager.MGPP.Add_All_Metadata:Î ÏÎ¿ÏÎžÎ®ÎºÎ· ÏÎ»ÏÎœ  # Updated 1-Apr-2005
+CDM.IndexManager.MGPP.Add_All_Metadata_Tooltip:Î§ÏÎ¯Î¶ÎµÎ¹ Î­ÎœÎ± ÎŸÎµÏÏÏÎ¹ÏÏÏ ÎµÏ
+ÏÎµÏÎ®ÏÎ¹Î¿ Î³Î¹Î± ÎºÎ¬ÎžÎµ ÎŽÎ¹Î±ÎžÎ­ÏÎ¹ÎŒÎ¿ ÏÏÏÎ¿ ÏÏÎ·ÏÎ¹ÎŒÎ¿ÏÎ¿Î¯ÏÎœÏÎ±Ï ÏÎ¿ ÏÎœÎ¿ÎŒÎ± ÏÎ¿Ï
+ ÏÏÏÎ¿Ï
+ ÏÏ ÏÎ¿ ÏÎœÎ¿ÎŒÎ± ÏÎ¿Ï
+ ÎµÏ
+ÏÎµÏÎ·ÏÎ¯Î¿Ï
+  # Updated 1-Apr-2005
+CDM.IndexManager.MGPP.Add_Level:Î ÏÎ¿ÏÎžÎ®ÎºÎ· ÎÏÎ¹ÏÎ­ÎŽÎ¿Ï
+  # Updated 1-Apr-2005
+CDM.IndexManager.MGPP.Add_Level_Tooltip:Î§ÏÎ¯Î¶ÎµÎ¹ Î­ÎœÎ± ÎµÏ
+ÏÎµÏÎ®ÏÎ¹Î¿ ÏÏÎ¿ ÎºÎ±ÎžÎ¿ÏÎ¹ÏÎŒÎ­ÎœÎ¿ ÎµÏÎ¯ÏÎµÎŽÎ¿  # Updated 1-Apr-2005
+CDM.IndexManager.MGPP.Current_Levels:ÎÎ±ÏÎ±ÏÏÏÎ·ÎŒÎ­ÎœÎ± ÎµÏÎ¯ÏÎµÎŽÎ±  # Updated 1-Apr-2005
+CDM.IndexManager.MGPP.Indexes:ÎÎ¹Î±ÏÎµÎ¯ÏÎ¹ÏÎ· ÎÏ
+ÏÎµÏÎ·ÏÎ¯ÏÎœ  # Updated 1-Apr-2005
+CDM.IndexManager.MGPP.Level:ÎÏÎ¯ÏÎµÎŽÎ¿ Î ÏÏÎ¿Ï
+:  # Updated 1-Apr-2005
+CDM.IndexManager.MGPP.Level_Name:ÎÎœÎ¿ÎŒÎ± ÎÏÎ¹ÏÎ­ÎŽÎ¿Ï
+:  # Updated 1-Apr-2005
+CDM.IndexManager.MGPP.Level_Name_Tooltip:ÎÎœÎ± ÎŒÎ¿ÎœÎ±ÎŽÎ¹ÎºÏ ÏÎœÎ¿ÎŒÎ± Î³Î¹Î± ÏÎ¿ ÎœÎ­Î¿ ÎµÏÎ¯ÏÎµÎŽÎ¿ ÎÏ
+ÏÎµÏÎ·ÏÎ¹Î¿ÏÎ¿Î¯Î·ÏÎ·Ï  # Updated 1-Apr-2005
+CDM.IndexManager.MGPP.Levels:ÎÎ¹Î±ÏÎµÎ¯ÏÎ¹ÏÎ· ÎµÏÎ¹ÏÎ­ÎŽÏÎœ  # Updated 1-Apr-2005
+CDM.IndexManager.MGPP.Remove_Level:ÎÎ¹Î±Î³ÏÎ±ÏÎ® ÎÏÎ¹ÏÎ­ÎŽÎ¿Ï
+  # Updated 1-Apr-2005
+CDM.IndexManager.MGPP.Remove_Level_Tooltip:ÎÎ¹Î±Î³ÏÎ±ÏÎ® ÏÎ¿Ï
+ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿Ï
+ ÎµÏÎ¹ÏÎ­ÎŽÎ¿Ï
+ ÎµÏ
+ÏÎµÏÎ·ÏÎ¹Î¿ÏÎ¿Î¯Î·ÏÎ·Ï  # Updated 1-Apr-2005
+CDM.IndexManager.MGPP.Replace_Index:ÎÎœÏÎ¹ÎºÎ±ÏÎ¬ÏÏÎ±ÏÎ· ÎÏ
+ÏÎµÏÎ·ÏÎ¯Î¿Ï
+  # Updated 1-Apr-2005
+CDM.IndexManager.MGPP.Replace_Index_Tooltip:ÎÎœÎ·ÎŒÎ­ÏÏÏÎ· ÏÎ¿Ï
+ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿Ï
+ ÎµÏ
+ÏÎµÏÎ·ÏÎ¯Î¿Ï
+  # Updated 1-Apr-2005
+CDM.IndexManager.Paragraph:ÏÎ±ÏÎ¬Î³ÏÎ±ÏÎ¿Ï  # Updated 1-Apr-2005
+CDM.IndexManager.Remove_Index:ÎÏÎ±Î¯ÏÎµÏÎ· ÎÏ
+ÏÎµÏÎ·ÏÎ¯Î¿Ï
+  # Updated 1-Apr-2005
+CDM.IndexManager.Remove_Index_Tooltip:ÎÏÎ±Î¯ÏÎµÏÎ· ÏÎ¿Ï
+ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿Ï
+ ÎµÏ
+ÏÎµÏÎ·ÏÎ¯Î¿Ï
+ Î±ÏÏ ÏÎ· Î»Î¯ÏÏÎ±  # Updated 1-Apr-2005
+CDM.IndexManager.Section:ÎµÎœÏÏÎ·ÏÎ±  # Updated 1-Apr-2005
+CDM.IndexManager.Set_Default:ÎÎ­ÏÎµ ÏÏ ÏÏÎ¿ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿ ÎÏ
+ÏÎµÏÎ®ÏÎ¹Î¿  # Updated 1-Apr-2005
+CDM.IndexManager.Set_Default_Tooltip:ÎÏÎ¯Î¶ÎµÎ¹ ÏÎ¿ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿ ÎµÏ
+ÏÎµÏÎ®ÏÎ¹Î¿ ÏÏ ÏÏÎ¿ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿  # Updated 1-Apr-2005
+CDM.IndexManager.Source:Î§ÏÎ¯ÏÎµ ÏÎ¿ ÎÏ
+ÏÎµÏÎ®ÏÎ¹Î¿ ÏÎ¬ÎœÏ ÏÎµ:  # Updated 1-Apr-2005
+CDM.IndexManager.Source_Tooltip:Î€Î± ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ± ÏÎ¬ÎœÏ ÏÏÎ± Î¿ÏÎ¿Î¯Î± ÎžÎ± ÏÏÎ¹ÏÏÎµÎ¯ ÏÎ¿ ÎÏ
+ÏÎµÏÎ®ÏÎ¹Î¿  # Updated 1-Apr-2005
+CDM.LanguageManager.Add:Î ÏÎ¿ÏÎžÎ®ÎºÎ· ÎÎ»ÏÏÏÎ±Ï  # Updated 1-Apr-2005
+CDM.LanguageManager.Add_Tooltip:Î ÏÎ¿ÏÎžÎ®ÎºÎ· ÏÎ·Ï ÎºÎ±ÎžÎ¿ÏÎ¹ÏÎŒÎ­ÎœÎ·Ï Î³Î»ÏÏÏÎ±Ï ÏÏÎ· Î»Î¯ÏÏÎ±  # Updated 1-Apr-2005
+CDM.LanguageManager.Assigned_Languages:ÎÎ±ÏÎ±ÏÏÏÎ·ÎŒÎ­ÎœÎµÏ Î³Î»ÏÏÏÎµÏ  # Updated 1-Apr-2005
+CDM.LanguageManager.Default_Language:Î ÏÎ¿ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ· ÎÎ»ÏÏÏÎ±  # Updated 1-Apr-2005
+CDM.LanguageManager.Remove:ÎÎ¹Î±Î³ÏÎ±ÏÎ® ÎÎ»ÏÏÏÎ±Ï  # Updated 1-Apr-2005
+CDM.LanguageManager.Remove_Tooltip:ÎÎ¹Î±Î³ÏÎ±ÏÎ® ÏÎ·Ï ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ·Ï Î³Î»ÏÏÏÎ±Ï Î±ÏÏ ÏÎ· Î»Î¯ÏÏÎ±  # Updated 1-Apr-2005
+CDM.LanguageManager.Selector:ÎÎ»ÏÏÏÎ± Î³Î¹Î± Î ÏÎ¿ÏÎžÎ®ÎºÎ·:  # Updated 1-Apr-2005
+CDM.LanguageManager.Selector_Tooltip:Î Î³Î»ÏÏÏÎ± ÏÎ¬ÎœÏ ÏÏÎ·Îœ Î¿ÏÎ¿Î¯Î± ÎžÎ± ÏÏÎ¹ÏÏÎµÎ¯ ÏÎ¿ ÎµÏ
+ÏÎµÏÎ®ÏÎ¹Î¿  # Updated 1-Apr-2005
+CDM.LanguageManager.Set_Default:ÎÎ­ÏÎµ ÏÏ Î ÏÎ¿ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿  # Updated 1-Apr-2005
+CDM.LanguageManager.Set_Default_Tooltip:ÎÎ¬ÎœÎµ ÏÎ·Îœ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ· Î³Î»ÏÏÏÎ± Î ÏÎ¿ÎµÏÎ¹Î»Î¿Î³Î®  # Updated 1-Apr-2005
+CDM.MetadataSetManager.Add:Î ÏÎ¿ÏÎžÎ®ÎºÎ· ÏÏ
+ÎœÏÎ»Î¿Ï
+ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ  # Updated 1-Apr-2005
+CDM.MetadataSetManager.Add_Tooltip:Î ÏÎ¿ÏÎžÎ®ÎºÎ· ÎµÎœÏÏ ÎœÎµÏÏ
+ ÏÏ
+ÎœÏÎ»Î¿Ï
+ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ ÏÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+CDM.MetadataSetManager.Edit:ÎÏÎµÎŸÎµÏÎ³Î±ÏÎ¯Î± Î£Ï
+ÎœÏÎ»Î¿Ï
+ ÎÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ  # Updated 1-Apr-2005
+CDM.MetadataSetManager.Edit_Message:Î€Î± ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ± ÎŒÏÎ¿ÏÎ¿ÏÎœ ÎœÎ± ÎµÏÎµÎŸÎµÏÎ³Î±ÏÏÎ¿ÏÎœ ÎŒÎµ ÏÏÎ®ÏÎ· ÏÎ¿Ï
+ GEMS (Greenstone Editor for Metadata Sets).\nÎÎµÎºÎ¹ÎœÎ®ÏÏÎµ ÏÎ¿Îœ GEMS ÎŒÎµ ÏÎ·Îœ ÎµÎœÏÎ¿Î»Î® gems.bat (Windows) Î® gems.sh (Linux) Î±ÏÏ ÏÎ¿ ÏÎ¬ÎºÎµÎ»Î¿ gli.  # Updated 1-Apr-2005
+CDM.MetadataSetManager.Edit_Message_Title:ÎÏÎµÎŸÎµÏÎ³Î±ÏÎ¯Î± ÏÏ
+ÎœÏÎ»Î¿Ï
+ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ  # Updated 1-Apr-2005
+CDM.MetadataSetManager.Edit_Tooltip:ÎÏÎµÎŸÎµÏÎ³Î±ÏÎ¯Î± ÏÎ¿Ï
+ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿Ï
+ ÏÏ
+ÎœÏÎ»Î¿Ï
+.  # Updated 1-Apr-2005
+CDM.MetadataSetManager.Elements:Elements ÏÏÎ¿ ÏÏÎœÎ¿Î»Î¿ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ  # Updated 1-Apr-2005
+CDM.MetadataSetManager.Remove:ÎÏÎ±Î¯ÏÎµÏÎ· ÏÏ
+ÎœÏÎ»Î¿Ï
+ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ  # Updated 1-Apr-2005
+CDM.MetadataSetManager.Remove_Tooltip:ÎÏÎ±Î¯ÏÎµÏÎ· ÏÎ¿Ï
+ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿Ï
+ ÏÏ
+ÎœÏÎ»Î¿Ï
+ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ Î±ÏÏ ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+CDM.MetadataSetManager.Sets:ÎÎ¹Î±ÎžÎ­ÏÎ¹ÎŒÎ± ÏÏÎœÎ¿Î»Î± ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ  # Updated 1-Apr-2005
+CDM.MetadataSetManager.Chooser.Add:Î ÏÏÏÎžÎµÏÎµ
+CDM.Move.At_Bottom:ÎÎµ ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± ÎŒÎµÏÎ±ÎºÎ¹ÎœÎ·ÎžÎµÎ¯ ÏÎ¿ {0} {1} ÏÎ±ÎŒÎ·Î»ÏÏÎµÏÎ± Î³Î¹Î±ÏÎ¯ ÎµÎ¯ÎœÎ±Î¹ Î®ÎŽÎ· ÏÏÎ¿Îœ ÏÎ¬ÏÎ¿ ÏÎ·Ï Î»Î¯ÏÏÎ±Ï.  # Updated 1-Apr-2005
+CDM.Move.At_Top:ÎÎµ ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± ÎŒÎµÏÎ±ÎºÎ¹ÎœÎ·ÎžÎµÎ¯ ÏÎ¿ {0} {1} ÏÎ·Î»ÏÏÎµÏÎ± Î³Î¹Î±ÏÎ¯ ÎµÎ¯ÎœÎ±Î¹ Î®ÎŽÎ· ÏÏÎ·Îœ ÎºÎ¿ÏÏ
+ÏÎ® ÏÎ·Ï Î»Î¯ÏÏÎ±Ï  # Updated 1-Apr-2005
+CDM.Move.Cannot:ÎÎµ ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± ÎŒÎµÏÎ±ÎºÎ¹ÎœÎ·ÎžÎµÎ¯ ÏÎ¿ plugin {0} ÏÎ±ÎŒÎ·Î»ÏÏÎµÏÎ± Î±ÏÏ ÏÎ±  RecPlug and ArcPlug.  # Updated 1-Apr-2005
+CDM.Move.Fixed:<html>Î€Î¿ RecPlug ÎºÎ±Î¹ ÏÎ¿ ArcPlug ÏÏÎ­ÏÎµÎ¹ ÎœÎ± ÎµÎ¯ÎœÎ±Î¹ ÏÎµÎ»ÎµÏ
+ÏÎ±Î¯Î±.</html>  # Updated 1-Apr-2005
+CDM.Move.Move_Down:ÎÎµÏÎ±ÎºÎ¯ÎœÎ·ÏÎ· ÏÏÎ¿Ï ÏÎ± ÎºÎ¬ÏÏ  # Updated 1-Apr-2005
+CDM.Move.Move_Down_Tooltip:ÎÎµÏÎ±ÎºÎ¯ÎœÎ·ÏÎ· ÏÎ¿Ï
+ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿Ï
+ ÏÏÎ¿Ï
+ ÏÏÎ¿Ï ÏÎ± ÎºÎ¬ÏÏ  # Updated 1-Apr-2005
+CDM.Move.Move_Up:ÎÎµÏÎ±ÎºÎ¯ÎœÎ·ÏÎ· ÏÏÎ¿Ï ÏÎ± ÏÎ¬ÎœÏ  # Updated 1-Apr-2005
+CDM.Move.Move_Up_Tooltip:ÎÎµÏÎ±ÎºÎ¯ÎœÎ·ÏÎ· ÏÎ¿Ï
+ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿Ï
+ ÏÏÎ¿Ï
+ ÏÏÎ¿Ï ÏÎ± ÏÎ¬ÎœÏ  # Updated 1-Apr-2005
+CDM.Move.Title:Error - ÎÎµ ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± ÎŒÎµÏÎ±ÎºÎ¹ÎœÎ·ÎžÎµÎ¯  # Updated 1-Apr-2005
+CDM.PlugInManager.Add:Î ÏÎ¿ÏÎžÎ®ÎºÎ· Plugin  # Updated 1-Apr-2005
+CDM.PlugInManager.QuickAdd:Î ÏÎ¿ÏÎžÎ®ÎºÎ· Plugin
+CDM.PlugInManager.Add_Tooltip:Î§ÏÎ·ÏÎ¹ÎŒÎ¿ÏÎ¿Î¯Î·ÏÎµ ÏÎ¿ ÎºÎ±ÎžÎ¿ÏÎ¹ÏÎŒÎ­ÎœÎ¿ plugin ÎŒÎµ Î±Ï
+ÏÎ® ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+CDM.PlugInManager.Assigned:Î€ÏÎ­ÏÎ¿ÎœÏÎ± Plugins  # Updated 1-Apr-2005
+CDM.PlugInManager.Configure:ÎÎ¹Î±ÎŒÏÏÏÏÏÎ· Plugin  # Updated 1-Apr-2005
+CDM.PlugInManager.Configure_Tooltip:ÎÎ»Î»Î±Î³Î® ÏÏÎœ ÎµÏÎ¹Î»Î¿Î³ÏÎœ ÏÎ¿Ï
+ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿Ï
+ plugin  # Updated 1-Apr-2005
+CDM.PlugInManager.Ignore:ÎÎ· ÏÏÎ¿ÏÎžÎ­ÏÎµÎ¹Ï ÏÎ¿ Plugin  # Updated 1-Apr-2005
+CDM.PlugInManager.Ignore_Tooltip:ÎÎ·Îœ ÏÏÎ¿ÏÎžÎ­ÏÎµÎ¹Ï plugins ÏÎµ Î±Ï
+ÏÎ® ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®.  # Updated 1-Apr-2005
+CDM.PlugInManager.PlugIn:ÎÏÎ¹Î»Î¿Î³Î® plugin Î³Î¹Î± ÏÏÎ¿ÏÎžÎ®ÎºÎ·:  # Updated 1-Apr-2005
+CDM.PlugInManager.PlugIn_Tooltip:ÏÎ± plugins ÎŽÎ¹Î±ÎžÎ­ÏÎ¹ÎŒÎ± Î³Î¹Î± ÏÏÎ®ÏÎ· ÏÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®.  # Updated 1-Apr-2005
+CDM.PlugInManager.PlugIn_Exists:ÎÏ
+ÏÏ ÏÎ¿ plugin Î­ÏÎµÎ¹ Î®ÎŽÎ· ÎºÎ±ÏÎ±ÏÏÏÎ·ÎžÎµÎ¯ Î³Î¹Î± Î±Ï
+ÏÎ® ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®.  # Updated 1-Apr-2005
+CDM.PlugInManager.PlugIn_Str:plugin  # Updated 1-Apr-2005
+CDM.PlugInManager.PlugIn_XML_Parse_Failed:ÎÎµ ÎŒÏÎ¿ÏÎ¿ÏÎœ ÎœÎ± ÎºÎ±ÎžÎ¿ÏÎ¯ÏÏÎ¿ÏÎœ ÏÎ± Î¿ÏÎ¯ÏÎŒÎ±ÏÎ± Î³Î¹Î± ÏÎ¿ {0}\nplugin. ÎÎµÎ²Î±Î¹ÏÎžÎµÎ¯ÏÎµ ÏÏÎ¹ ÏÎ±ÏÎ­ÏÎµÏÎµ ÏÏÎ¿ plugin ÏÎ± ÎºÎ±ÏÎ¬Î»Î»Î·Î»Î± Î¿ÏÎ¯ÏÎŒÎ±ÏÎ± Î²Î»Î­ÏÎ¿ÎœÏÎ±Ï Î±ÏÏ ÏÎ·Îœ ÎµÎœÏÎ¿Î»Î® pluginfo.pl.  # Updated 1-Apr-2005
+CDM.PluginManager.Plugin_Suggestion_Prompt:ÎÎ±ÎœÎ­ÎœÎ± Î±ÏÏ ÏÎ± plugins ÏÎµ Î±Ï
+ÏÎ® ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î® ÎŽÎµ ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± ÎµÏÎµÎŸÎµÏÎ³Î±ÏÏÎµÎ¯ ÏÎ¿ Î±ÏÏÎµÎ¯Î¿ "{0}".  # Updated 1-Apr-2005
+CDM.PlugInManager.Remove:ÎÎ¹Î±Î³ÏÎ±ÏÎ® Plugin  # Updated 1-Apr-2005
+CDM.PlugInManager.Remove_Tooltip:ÎÏÎ±Î¯ÏÎµÏÎ· ÏÎ¿Ï
+ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿Ï
+ plugin Î±ÏÏ ÏÎ· Î»Î¯ÏÏÎ±  # Updated 1-Apr-2005
+CDM.PluginManager.SuggestedPluginListTitle:ÏÏÎ¿ÏÎµÎ¹ÎœÏÎŒÎµÎœÎ± plugins Î³Î¹Î± ÏÎ¿ Î±ÏÏÎµÎ¯Î¿  # Updated 1-Apr-2005
+CDM.PlugInManager.Parsing.Message:Î€Î¿ ÎµÏÎ³Î±Î»ÎµÎ¯Î¿ ÏÏÎµÎŽÎ¯Î±ÏÎ·Ï ÏÎ¿ÏÏÏÎœÎµÎ¹ ÏÎ»Î·ÏÎ¿ÏÎ¿ÏÎ¯ÎµÏ Î³Î¹Î± ÏÎ¿ plugin.  # Updated 1-Apr-2005
+CDM.PlugInManager.Parsing.Title:Î€Î± Plugins ÎŠÎ¿ÏÏÏÎœÎ¿ÎœÏÎ±Î¹  # Updated 1-Apr-2005
+CDM.SearchTypeManager.Add:Î ÏÎ¿ÏÎžÎ®ÎºÎ· ÏÏÏÎ¿Ï
+ ÎÎœÎ±Î¶Î®ÏÎ·ÏÎ·Ï  # Updated 1-Apr-2005
+CDM.SearchTypeManager.Add_Tooltip:ÎÏÎ¹ÏÏÎ­ÏÏÎµ ÏÎ¿Îœ ÎºÎ±ÎžÎ¿ÏÎ¹ÏÎŒÎ­ÎœÎ¿ ÏÏÏÎ¿ Î±ÎœÎ±Î¶Î®ÏÎ·ÏÎ·Ï ÎŒÎµ Î±Ï
+ÏÎ® ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+CDM.SearchTypeManager.Assigned:Î€ÏÎ­ÏÎ¿ÎœÏÎµÏ ÏÏÏÎ¿Î¹ ÏÎ±ÎŸÎ¯ÎŒÎ±ÏÎ¿Ï  # Updated 1-Apr-2005
+CDM.SearchTypeManager.BuildType_Selection:ÎÏ
+ÏÎµÏÎ·ÏÎ¹Î¿ÏÎ¿Î¯Î·ÏÎ·:
+CDM.SearchTypeManager.BuildType_Selection_Tooltip:ÎÏÎ¹Î»Î­ÎŸÏÎµ ÏÎ¿Îœ ÎµÏ
+ÏÎµÏÎ·ÏÎ¹Î¿ÏÎ¿Î¹Î·ÏÎ® ÏÎ¿Ï
+ ÎžÎ± ÏÏÎ·ÏÎ¹ÎŒÎ¿ÏÎ¿Î¹Î·ÎžÎµÎ¯ Î³Î¹Î± ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®
+CDM.SearchTypeManager.Enable:ÎÎœÎµÏÎ³Î¿ÏÎ¿Î¯Î·ÏÎ· Î ÏÎ¿ÏÏÏÎ·ÎŒÎ­ÎœÎ·Ï ÎÎœÎ±Î¶Î®ÏÎ·ÏÎ·Ï  # Updated 1-Apr-2005
+CDM.SearchTypeManager.Remove:ÎÏÎ±Î¯ÏÎµÏÎ· ÏÎ¿Ï
+ ÏÏÏÎ¿Ï
+ Î±ÎœÎ±Î¶Î®ÏÎ·ÏÎ·Ï  # Updated 1-Apr-2005
+CDM.SearchTypeManager.Remove_Tooltip:ÎÎ± ÎŒÎ· ÏÏÎ·ÏÎ¹ÎŒÎ¿ÏÎ¿Î¹ÎµÎ¯ÏÎ±Î¹ Î¿ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿Ï ÏÏÏÎ¿Ï Î±ÎœÎ±Î¶Î®ÏÎ·ÏÎ·Ï ÎŒÎµ Î±Ï
+ÏÎ® ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+CDM.SearchTypeManager.SearchType:Î€ÏÏÎ¿Ï ÎÎœÎ±Î¶Î®ÏÎ·ÏÎ·Ï  # Updated 1-Apr-2005
+CDM.SearchTypeManager.SearchType_Selection:Î€ÏÏÎ¿Î¹ ÎÎœÎ±Î¶Î®ÏÎ·ÏÎ·Ï:  # Updated 1-Apr-2005
+CDM.SearchTypeManager.SearchType_Selection_Tooltip:ÎÎ¹ ÏÏÏÎ¿Î¹ Î±ÎœÎ±Î¶Î®ÏÎ·ÏÎ·Ï Î³Î¹Î± Î±Ï
+ÏÎ® ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+CDM.SubcollectionManager.Add:Î ÏÎ¿ÏÎžÎ®ÎºÎ· ÏÎ¯Î»ÏÏÎ¿Ï
+  # Updated 1-Apr-2005
+CDM.SubcollectionManager.Add_Tooltip:Î ÏÎ¿ÏÎžÎ®ÎºÎ· ÏÎ¿Ï
+ ÎºÎ±ÎžÎ¿ÏÎ¹ÏÎŒÎ­ÎœÎ¿Ï
+ ÏÎ¯Î»ÏÏÎ¿Ï
+ ÏÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+CDM.SubcollectionManager.Assigned:ÎÎ±ÎžÎ¿ÏÎ¹ÏÎŒÎ­ÎœÎ± ÎŠÎ¯Î»ÏÏÎ± Î³Î¹Î± ÏÎ·Îœ Ï
+ÏÎ¿ÏÏ
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+CDM.SubcollectionManager.Exclude:ÎÏÎ­ÎºÎ»ÎµÎ¹ÏÎµ  # Updated 1-Apr-2005
+CDM.SubcollectionManager.Flags:Î£Î·ÎŒÎ±Î¯ÎµÏ ÏÎ¿Ï
+ ÎžÎ± ÏÎµÎžÎ¿ÏÎœ ÏÏÎ¿ ÏÎ±Î¯ÏÎ¹Î±ÏÎŒÎ±  # Updated 1-Apr-2005
+CDM.SubcollectionManager.Flags_Tooltip:Î€Î± Regular expression flags ÏÎ¿Ï
+ ÎžÎ± ÏÏÎ·ÏÎ¹ÎŒÎ¿ÏÎ¿Î¹Î·ÎžÎ¿ÏÎœ ÏÎµ ÏÎµÏÎ¯ÏÏÏÏÎ· ÏÎ±Î¹ÏÎ¹Î¬ÏÎŒÎ±ÏÎ¿Ï (ÏÏ. "i" Î³Î¹Î± ÎœÎ± ÎŒÎ· ÎŽÎ¹Î±ÏÏÏÎ¯Î¶Î¿ÎœÏÎ±Î¹ ÎºÎµÏÎ±Î»Î±Î¯Î± ÏÎµÎ¶Î¬)  # Updated 1-Apr-2005
+CDM.SubcollectionManager.Include:Î ÎµÏÎ¹Î­Î»Î±Î²Îµ  # Updated 1-Apr-2005
+CDM.SubcollectionManager.Inclusive:Î€Î¹ ÎœÎ± Î³Î¯ÎœÎµÎ¹ ÎŒÎµ Î±ÏÏÎµÎ¯Î± ÏÎ¿Ï
+ ÏÎ±Î¹ÏÎ¹Î¬Î¶Î¿Ï
+Îœ?  # Updated 1-Apr-2005
+CDM.SubcollectionManager.Language_Controls:ÎÎ±ÏÎ±ÏÏÏÎ·ÏÎ· ÎÎ»ÏÏÏÏÎœ  # Updated 1-Apr-2005
+CDM.SubcollectionManager.Match:ÎÎ±ÎœÎ¿ÎœÎ¹ÎºÎ® ÎÎºÏÏÎ±ÏÎ· Î³Î¹Î± ÏÎ±Î¯ÏÎ¹Î±ÏÎŒÎ±:  # Updated 1-Apr-2005
+CDM.SubcollectionManager.Match_Tooltip:ÎÎ¹Î± ÎºÎ±ÎœÎ¿ÎœÎ¹ÎºÎ® Î­ÎºÏÏÎ±ÏÎ· ÏÎ¿Ï
+ ÎºÎ±ÎžÎ¿ÏÎ¯Î¶ÎµÎ¹ ÏÎ± Î­Î³Î³ÏÎ±ÏÎ± ÏÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+CDM.SubcollectionManager.Name:ÎÎœÎ¿ÎŒÎ± ÏÎ¯Î»ÏÏÎ¿Ï
+ Ï
+ÏÎ¿ÏÏ
+Î»Î»Î¿Î³Î®Ï:  # Updated 1-Apr-2005
+CDM.SubcollectionManager.Name_Tooltip:Î€Î¿ ÏÎœÎ¿ÎŒÎ± ÏÎ¿Ï
+ ÎœÎ­Î¿Ï
+ ÏÎ¯Î»ÏÎ¿Ï
+ Ï
+ÏÎ¿ÏÏ
+Î»Î»Î¿Î³Î®Ï  # Updated 1-Apr-2005
+CDM.SubcollectionManager.Partitions_Disabled:ÎÏ
+ÏÎ® Î· Î¹ÎŽÎ¹ÏÏÎ·ÏÎ± Î­Î¹ÎœÎ±Î¹ Î±ÏÎµÎœÎµÏÎ³Î¿ÏÎ¿Î¹Î·ÎŒÎ­ÎœÎ· Î³Î¹Î±ÏÎ¯ ÎµÎ¯ÏÏÎµ ÏÎµ {0-Current Mode} ÏÏÏÏÎ¿ Î»ÎµÎ¹ÏÎ¿Ï
+ÏÎ³Î¯Î±Ï. ÎÏÎ¿ÏÎµÎ¯ ÎŒÏÎœÎ¿ ÎœÎ± ÏÏÎ¿ÏÏÎµÎ»Î±ÏÏÎµÎ¯ ÏÎµ {1-Systems} ÎºÎ±Î¹ {2-Expert} ÏÏÏÏÎ¿Ï
+Ï Î»ÎµÎ¹ÏÎ¿Ï
+ÏÎ³Î¯Î±Ï. Î§ÏÎ·ÏÎ¹ÎŒÎ¿ÏÎ¿Î¹ÎµÎ¯ÏÏÎµ ÎÏÏÎµÎ¯Î¿ -> Î ÏÎ¿ÏÎ¹ÎŒÎ®ÏÎµÎ¹Ï Î³Î¹Î± ÎœÎ± Î±Î»Î»Î¬ÎŸÎµÏÎµ ÏÎ¿Îœ ÏÏÏÏÎ¿ Î»ÎµÎ¹ÏÎ¿Ï
+ÏÎ³Î¯Î±Ï.  # Updated 1-Apr-2005
+CDM.SubcollectionManager.Remove:ÎÏÎ±Î¯ÏÎµÏÎ· ÎŠÎ¯Î»ÏÏÎ¿Ï
+  # Updated 1-Apr-2005
+CDM.SubcollectionManager.Remove_Tooltip:ÎÏÎ±Î¯ÏÎµÏÎ· ÏÎ¿Ï
+ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿Ï
+ ÏÎ¯Î»ÏÏÎ¿Ï
+ Î±ÏÏ ÏÎ· Î»Î¯ÏÏÎ±.  # Updated 1-Apr-2005
+CDM.SubcollectionManager.Replace:ÎÎœÏÎ¹ÎºÎ±ÏÎ¬ÏÏÎ±ÏÎ· ÎŠÎ¯Î»ÏÏÎ¿Ï
+  # Updated 1-Apr-2005
+CDM.SubcollectionManager.Replace_Tooltip:ÎÎœÎ·ÎŒÎ­ÏÏÏÎ· ÏÏÎœ Î»ÎµÏÏÎ¿ÎŒÎµÏÎµÎ¹ÏÎœ ÏÎ¿Ï
+ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿Ï
+ ÎŠÎ¯Î»ÏÏÎ¿Ï
+  # Updated 1-Apr-2005
+CDM.SubcollectionManager.Source:Î§Î±ÏÎ±ÎºÏÎ·ÏÎ¹ÏÏÎ¹ÎºÏ Î±ÏÏÎµÎ¯Î¿Ï
+ Î³Î¹Î± ÏÎ±Î¯ÏÎ¹Î±ÏÎŒÎ±:  # Updated 1-Apr-2005
+CDM.SubcollectionManager.Source_Tooltip:Î€Î¿ ÏÎ±ÏÎ±ÎºÏÎ·ÏÎ¹ÏÏÎ¹ÎºÏ ÏÎ¿Ï
+ Î±ÏÏÎµÎ¯Î¿Ï
+ Î³Î¹Î± ÏÎ±Î¯ÏÎ¹Î±ÏÎŒÎ±  # Updated 1-Apr-2005
+CDM.SubcollectionManager.Subcollection_Controls:ÎÎ±ÎžÎ¿ÏÎ¹ÏÎŒÏÏ ÎŠÎ¯Î»ÏÏÏÎœ  # Updated 1-Apr-2005
+CDM.SubcollectionManager.Subindex_Controls:ÎÎœÎ¬ÎžÎµÏÎ· Î¥ÏÎ¿ÎŽÎ¹Î±Î¹ÏÎ­ÏÎµÏÎœ  # Updated 1-Apr-2005
+CDM.SubcollectionIndexManager.Add_Subindex:Î ÏÎ¿ÏÎžÎ®ÎºÎ· ÎÏ
+ÏÎµÏÎ·ÏÎ¯Î¿Ï
+  # Updated 1-Apr-2005
+CDM.SubcollectionIndexManager.Add_Subindex_Tooltip:Î ÏÏÏÎžÎµÏÎµ ÏÎ·Îœ ÎºÎ±ÎžÎ¿ÏÎ¹ÏÎŒÎ­ÎœÎ· Ï
+ÏÎ¿ÎŽÎ¹Î±Î¯ÏÎµÏÎ· ÏÎµ Î±Ï
+ÏÎ® ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+CDM.SubcollectionIndexManager.Default_Partition_Indicator:[Î ÏÎ¿ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ· Î¥ÏÎ¿ÎŽÎ¹Î±Î¯ÏÎµÏÎ·]  # Updated 1-Apr-2005
+CDM.SubcollectionIndexManager.PartitionName:ÎÎœÎ¿ÎŒÎ± Î¥ÏÎ¿ÎŽÎ¹Î±Î¯ÏÎµÏÎ·Ï:  # Updated 1-Apr-2005
+CDM.SubcollectionIndexManager.PartitionName_Tooltip:Î€Î¿ ÏÎœÎ¿ÎŒÎ± ÏÎ·Ï ÎœÎ­Î±Ï Ï
+ÏÎ¿ÎŽÎ¹Î±Î¯ÏÎµÏÎ·Ï  # Updated 1-Apr-2005
+CDM.SubcollectionIndexManager.Remove_Subindex:ÎÏÎ±Î¯ÏÎµÏÎ· Î¥ÏÎ¿ÎŽÎ¹Î±Î¯ÏÎµÏÎ·Ï  # Updated 1-Apr-2005
+CDM.SubcollectionIndexManager.Remove_Subindex_Tooltip:ÎÏÎ±Î¯ÏÎµÏÏÎµ ÏÎ· ÏÏ
+Î³ÎºÎµÎºÏÎ¹ÎŒÎ­ÎœÎ· Ï
+ÏÎ¿ÎŽÎ¹Î±Î¯ÏÎµÏÎ· Î±ÏÏ Î±Ï
+ÏÎ® ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+CDM.SubcollectionIndexManager.Replace_Subindex:ÎÎœÏÎ¹ÎºÎ±ÏÎ¬ÏÏÎ±ÏÎ· Î¥ÏÎ¿ÎŽÎ¹Î±Î¯ÏÎµÏÎ·Ï  # Updated 1-Apr-2005
+CDM.SubcollectionIndexManager.Replace_Subindex_Tooltip:ÎÎœÎ±ÎœÎµÏÏÏÎµ ÏÎ·Îœ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ· Ï
+ÏÎ¿ÎŽÎ¹Î±Î¯ÏÎµÏÎ·  # Updated 1-Apr-2005
+CDM.SubcollectionIndexManager.Set_Default_Subindex:ÎÎ­ÏÎµ ÏÏ Î ÏÎ¿ÎµÏÎ¹Î»Î¿Î³Î®  # Updated 1-Apr-2005
+CDM.SubcollectionIndexManager.Set_Default_Subindex_Tooltip:ÎÎµÏÎ±ÏÏÎ­ÏÎµÎ¹ ÏÎ·Îœ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ· Ï
+ÏÎ¿ÎŽÎ¹Î±Î¯ÏÎµÏÎ· ÏÏ ÏÏÎ¿ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ·  # Updated 1-Apr-2005
+CDM.SubcollectionIndexManager.Source:Î§ÏÎ¯ÏÎµ ÏÎ·Îœ Ï
+ÏÎ¿ÎŽÎ¹Î±Î¯ÏÎµÏÎ· ÏÎ¬ÎœÏ ÏÏÎ¿:  # Updated 1-Apr-2005
+CDM.SubcollectionIndexManager.Source_Tooltip:Î€Î± ÏÎ¯Î»ÏÏÎ± ÏÎ·Ï Ï
+ÏÎ¿ÏÏ
+Î»Î»Î¿Î³Î®Ï ÏÎ¬ÎœÏ ÏÏÎ± Î¿ÏÎ¿Î¯Î± ÎžÎ± ÏÏÎ¹ÏÏÎµÎ¯ Î· Ï
+ÏÎ¿ÎŽÎ¹Î±Î¯ÏÎµÏÎ·  # Updated 1-Apr-2005
+CDM.SubcollectionIndexManager.Subindexes:ÎÎ±ÏÎ±ÏÏÏÎ·ÎŒÎ­ÎœÎµÏ Ï
+ÏÎ¿ÎŽÎ¹Î±ÏÎ­ÏÎ·Ï Ï
+ÏÎ¿ÏÏ
+Î»Î»Î¿Î³Î®Ï  # Updated 1-Apr-2005
+CDM.TranslationManager.Add:Î ÏÎ¿ÏÎžÎ®ÎºÎ· ÎÎµÏÎ¬ÏÏÎ±ÏÎ·Ï  # Updated 1-Apr-2005
+CDM.TranslationManager.Add_Tooltip:Î ÏÏÏÎžÎµÏÎµ ÏÎ·Îœ ÎºÎ±ÎžÎ¿ÏÎ¹ÏÎŒÎ­ÎœÎ· ÎŒÎµÏÎ¬ÏÏÎ±ÏÎ· ÏÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+CDM.TranslationManager.Affected_Features:Î§Î±ÏÎ±ÎºÏÎ·ÏÎ¹ÏÏÎ¹ÎºÎ¬  # Updated 1-Apr-2005
+CDM.TranslationManager.Assigned_Fragments:ÎÎ±ÏÎ±ÏÏÏÎ·ÎŒÎ­ÎœÎµÏ ÎÎµÏÎ±ÏÏÎ¬ÏÎµÎ¹Ï  # Updated 1-Apr-2005
+CDM.TranslationManager.Default_Text:ÎÏÏÎ¹ÎºÏ ÎÎµÎ¯ÎŒÎµÎœÎ¿  # Updated 1-Apr-2005
+CDM.TranslationManager.Fragment_Column:ÎÎµÎ¯ÎŒÎµÎœÎ¿  # Updated 1-Apr-2005
+CDM.TranslationManager.Language:ÎÎ»ÏÏÏÎ± ÎÎµÏÎ¬ÏÏÎ±ÏÎ·Ï:  # Updated 1-Apr-2005
+CDM.TranslationManager.Language_Column:ÎÎ»ÏÏÏÎ±  # Updated 1-Apr-2005
+CDM.TranslationManager.Language_Tooltip:Î Î³Î»ÏÏÏÎ± ÏÎ¿Ï
+ ÎžÎ± Î³Î¯ÎœÎµÎ¹ Î· ÎŒÎµÏÎ¬ÏÏÎ±ÏÎ·  # Updated 1-Apr-2005
+CDM.TranslationManager.Remove:ÎÏÎ±Î¯ÏÎµÏÎ· ÎŒÎµÏÎ¬ÏÏÎ±ÏÎ·Ï  # Updated 1-Apr-2005
+CDM.TranslationManager.Remove_Tooltip:ÎÏÎ±Î¹ÏÎ­Î¯ ÏÎ·Îœ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ· ÎŒÎµÏÎ¬ÏÏÎ±ÏÎ· Î±ÏÏ ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+CDM.TranslationManager.Replace:ÎÎœÏÎ¹ÎºÎ±ÏÎ¬ÏÏÎ±ÏÎ· ÎÎµÏÎ¬ÏÏÎ±ÏÎ·Ï  # Updated 1-Apr-2005
+CDM.TranslationManager.Replace_Tooltip:ÎÎœÎ·ÎŒÎµÏÏÎœÎµÎ¹ ÏÎ·Îœ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ· ÎŒÎµÏÎ¬ÏÏÎ±ÏÎ·  # Updated 1-Apr-2005
+CDM.TranslationManager.Translation:ÎÎµÏÎ±ÏÏÎ±ÏÎŒÎ­ÎœÎ¿ ÎÎµÎ¯ÎŒÎµÎœÎ¿  # Updated 1-Apr-2005
+CDM.TranslationManager.Translation_Tooltip:ÎÎ¹ÏÎ¬Î³ÎµÏÎµ ÏÎ· ÎŒÎµÏÎ¬ÏÏÎ±ÏÎ· ÏÎ¿Ï
+ ÎºÎµÎ¹ÎŒÎ­ÎœÎ¿Ï
+ ÎµÎŽÏ  # Updated 1-Apr-2005
+#*******************
+#
+#***** Collection *****
+Collection.Collection:{32}Î£Ï
+Î»Î»Î¿Î³Î®{34}  # Updated 1-Apr-2005
+Collection.Delete_Tooltip:ÎÎ¹Î±Î³ÏÎ¬ÏÏÎµ ÏÎ± ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ± ÎÏÏÎµÎ¯Î± ÎºÎ±Î¹ ÎŠÎ±ÎºÎ­Î»Î¿Ï
+Ï  # Updated 1-Apr-2005
+Collection.Filter_Tooltip:Î ÎµÏÎ¹Î¿ÏÎ¯ÏÏÎµ ÏÎ± Î±ÏÏÎµÎ¯Î± ÏÎ¿Ï
+ ÎµÎŒÏÎ±ÎœÎ¯Î¶Î¿ÎœÏÎ±Î¹ ÏÏÎ¿ ÎŽÎ­ÎœÏÏÎ¿  # Updated 1-Apr-2005
+Collection.New_Folder_Tooltip:ÎÎ·ÎŒÎ¹Î¿ÏÏÎ³Î®ÏÏÎµ Î­ÎœÎ± ÎœÎ­Î¿ ÏÎ¬ÎºÎµÎ»Î¿  # Updated 1-Apr-2005
+Collection.No_Collection:ÎÎµÎœ Ï
+ÏÎ¬ÏÏÎµÎ¹ Î£Ï
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+Collection.Stop_Tooltip:Î£ÏÎ±ÎŒÎ±ÏÎ¬ÎµÎ¹ ÏÎ·Îœ Î±ÎœÏÎ¹Î³ÏÎ±ÏÎµÎ¯ ÏÏÎœ Î±ÏÏÎµÎ¯ÏÎœ  # Updated 1-Apr-2005
+Collection.Workspace:{32}Î ÎµÏÎ¹Î²Î¬Î»Î»Î¿Îœ ÎÏÎ³Î±ÏÎ¯Î±Ï{34}  # Updated 1-Apr-2005
+#**********************
+#
+#***** CollectionBuilt *****
+CollectionBuilt.Message:Î ÏÏ
+Î»Î»Î¿Î³Î® Î­ÏÎµÎ¹ ÏÏÎ¹ÏÏÎµÎ¯ ÎºÎ±Î¹ ÎµÎ¯ÎœÎ±Î¹ Î­ÏÎ¿Î¹ÎŒÎ· Î³Î¹Î± ÏÏÎ¿ÎµÏÎ¹ÏÎºÏÏÎ·ÏÎ·  # Updated 1-Apr-2005
+CollectionBuilt.Title:ÎÏÎ¿ÏÎ­Î»ÎµÏÎŒÎ± ÎÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¯Î±Ï Î£Ï
+Î»Î»Î¿Î³Î®Ï  # Updated 1-Apr-2005
+#***************************
+#
+#***** CollectionManager *****
+CollectionManager.Build_Cancelled:Î ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¯Î± ÏÎ·Ï ÏÏ
+Î»Î»Î¿Î³Î®Ï Î­ÏÎµÎ¹ Î±ÎºÏ
+ÏÏÎžÎµÎ¯.  # Updated 1-Apr-2005
+CollectionManager.Cannot_Create_Collection:ÎÎœÎ± ÏÏÎ¬Î»ÎŒÎ± ÎµÎŒÏÏÎŽÎ¹ÏÎµ ÏÎ· ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¯Î± ÏÎ·Ï ÏÏ
+Î»Î»Î¿Î³Î®Ï  # Updated 1-Apr-2005
+CollectionManager.Cannot_Create_Collection_With_Reason:Î ÏÏ
+Î»Î»Î¿Î³Î® ÎŽÎµÎœ ÎŒÏÏÏÎµÏÎµ ÎœÎ± ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î·ÎžÎµÎ¯ ÎµÏÎµÎ¹ÎŽÎ® \n{0-Error message}
+CollectionManager.Cannot_Delete_Index:ÎÏ
+ÏÎ® Î· ÏÏ
+Î»Î»Î¿Î³Î® ÎŽÎµ ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± ÎŸÎ±ÎœÎ±ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î·ÎžÎµÎ¯ Î³Î¹Î±ÏÎ¯ ÏÎ± ÏÎ±Î»Î¹Î¬ ÎµÏ
+ÏÎµÏÎ®ÏÎ¹Î± ÎŽÎµ ÎŒÏÎ¿ÏÎ¿ÏÎœ ÎœÎ± ÎŽÎ¹Î±Î³ÏÎ±ÏÎ¿ÏÎœ.\nÎ£Î¹Î³Î¿Ï
+ÏÎµÏ
+ÏÎµÎ¯ÏÎµ ÏÏÎ¹ ÏÎ± Î±ÏÏÎµÎ¯Î± Î±Ï
+ÏÎ¬ ÎŽÎµ ÏÏÎ·ÏÎ¹ÎŒÎ¿ÏÎ¿Î¹Î¿ÏÎœÏÎ±Î¹ Î±ÏÏ ÎºÎ¬ÏÎ¿Î¹Î¿ Î¬Î»Î»Î¿ ÏÏÏÎ³ÏÎ±ÎŒÎŒÎ±.\n (Î® Î±ÏÏ ÏÎ¿ Greenstone) ÎºÎ±Î¹ ÏÏÎ¿ÏÏÎ±ÎžÎµÎ¯ÏÏÎµ ÎŸÎ±ÎœÎ¬.  # Updated 1-Apr-2005
+CollectionManager.Cannot_Delete_Index_Log:Î ÎµÎ¹ÏÎ±Î³ÏÎ³Î® ÏÏÎ±ÎŒÎ¬ÏÎ·ÏÎµ Î³Î¹Î±ÏÎ¯ ÏÎ± ÏÎ±Î»Î¹Î¬ ÎµÏ
+ÏÎµÏÎ®ÏÎ¹Î± ÎŽÎµ ÎŒÏÎ¿ÏÎ¿ÏÎœ ÎœÎ± ÎŽÎ¹Î±Î³ÏÎ±ÏÎ¿ÏÎœ.  # Updated 1-Apr-2005
+CollectionManager.Cannot_Open:Î ÏÏ
+Î»Î»Î¿Î³Î® ÏÏÎ¿:\n{0-Collection file path}\nÎÎµ ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± Î±ÎœÎ¿Î¹ÏÎžÎµÎ¯.  # Updated 1-Apr-2005
+CollectionManager.Cannot_Open_With_Reason:Î ÏÏ
+Î»Î»Î¿Î³Î® ÏÏÎ¿:\n{0-Collection file path}\nÎŽÎµ ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± Î±ÎœÎ¿Î¹ÏÎžÎµÎ¯ Î³Î¹Î±ÏÎ¯:\n{1-Error message}  # Updated 1-Apr-2005
+CollectionManager.Creating_New:ÎÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³ÎµÎ¯ÏÎ±Î¹ ÎŒÎ¹Î± ÎœÎ­Î± ÏÏ
+Î»Î»Î¿Î³Î®.  # Updated 1-Apr-2005
+CollectionManager.Log_Created:Î€Î¿ Î±ÏÏÎµÎ¯Î¿ ÎºÎ±ÏÎ±Î³ÏÎ±ÏÎ®Ï ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î®ÎžÎ·ÎºÎµ.  # Updated 1-Apr-2005
+CollectionManager.Loading_Collection:Î ÏÏ
+Î»Î»Î¿Î³Î® ÏÎ¿ÏÏÏÎœÎµÏÎ±Î¹  # Updated 1-Apr-2005
+CollectionManager.Loading_Collection_Please_Wait:Î ÏÏ
+Î»Î»Î¿Î³Î® ÏÎ¿ÏÏÏÎœÎµÏÎ±Î¹ ÏÎ±ÏÎ±ÎºÎ±Î»Î¿ÏÎŒÎµ ÏÎµÏÎ¹ÎŒÎ­ÎœÎµÏÎµ...  # Updated 1-Apr-2005
+CollectionManager.Loading_Successful:ÎŠÎ¿ÏÏÏÎŒÎ­ÎœÎ· Î£Ï
+Î»Î»Î¿Î³Î® {0}.  # Updated 1-Apr-2005
+CollectionManager.Missing_Config:ÎÏ
+ÏÎ® Î· ÏÏ
+Î»Î»Î¿Î³Î® ÎŽÎµÎœ Î­ÏÎµÎ¹ ÏÏÏÏÏ Î±ÏÏÎµÎ¯Î¿ ÎŽÎ¹Î±ÎŒÏÏÏÏÏÎ·Ï  # Updated 1-Apr-2005
+CollectionManager.Not_Col_File:'{0}' ÎŽÎµÎœ ÎµÎ¯ÎœÎ±Î¹ Î­ÎœÎ± Î­Î³ÎºÏ
+ÏÎ¿ Î±ÏÏÎµÎ¯Î¿ ÏÏ
+Î»Î»Î¿Î³Î®Ï (.col)  # Updated 1-Apr-2005
+CollectionManager.No_Config_File:Î€Î¿ collect.cfg ÎŽÎµÎœ Î­ÏÎµÎ¹ ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î·ÎžÎµÎ¯ Î±ÏÏ ÏÎ¿ mkcol.pl
+CollectionManager.Preview_Ready_Failed:ÎÎœÎ± ÏÏÎ¬Î»ÎŒÎ± ÎžÎ± ÎµÎŒÏÎ¿ÎŽÎ¯ÏÎµÎ¹ ÏÎ·Îœ ÏÏÎ¿ÎµÏÎ¹ÏÎºÏÏÎ·ÏÎ· ÏÎ·Ï ÏÏ
+Î»Î»Î¿Î³Î®Ï.  # Updated 1-Apr-2005
+CollectionManager.Preview_Ready_Title:ÎÎ±ÏÎ¬ÏÏÎ±ÏÎ· Î ÏÎ¿ÎµÏÎ¹ÏÎºÏÏÎ·ÏÎ·Ï Î£Ï
+Î»Î»Î¿Î³Î®Ï.  # Updated 1-Apr-2005
+CollectionManager.Session_Ready:Î ÏÏ
+Î»Î»Î¿Î³Î® {0} ÎµÎ¯ÎœÎ±Î¹ Î­ÏÎ¿Î¹ÎŒÎ· Î³Î¹Î± ÏÏÎ®ÏÎ·.  # Updated 1-Apr-2005
+CollectionManager.Build_Not_Moved:Î ÏÎ¬ÎºÎµÎ»Î¿Ï ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¯Î±Ï ÎŽÎµ ÎŒÏÎ¿ÏÎ¿ÏÏÎµ ÎœÎ± ÎŒÎµÏÎ±ÎºÎ¹ÎœÎ·ÎžÎµÎ¯
+CollectionManager.Index_Not_Deleted:Î ÏÎ¬ÎºÎµÎ»Î¿Ï ÎµÏ
+ÏÎµÏÎ·ÏÎ¹Î¿ÏÎ¿Î¯Î·ÏÎ·Ï ÎŽÎµÎœ ÎŒÏÎ¿ÏÎ¿ÏÏÎµ ÎœÎ± ÎŽÎ¹Î±Î³ÏÎ±ÏÎµÎ¯
+CollectionManager.Install_Exception:ÎÎœÎ± ÏÏÎ¬Î»ÎŒÎ± Î±ÎœÎ¹ÏÎœÎ­Ï
+ÎžÎ·ÎºÎµ ÎºÎ±ÏÎ¬ ÏÎ·Îœ ÎµÎ³ÎºÎ±ÏÎ¬ÏÏÎ±ÏÎ· ÏÎ·Ï ÏÏ
+Î»Î»Î¿Î³Î®Ï:\n{0}\nÎ Î¹ÎžÎ±ÎœÏÏÎ±ÏÎ± ÏÏÎ¿ÎºÎ»Î®ÎžÎ·ÎºÎµ Î±ÏÏ ÏÎ± Windows ÏÎ¿Ï
+ Î­ÏÎ¿Ï
+Îœ ÎºÎ»ÎµÎ¹ÎŽÏÏÎµÎ¹ ÏÎ± Î±ÏÏÎµÎ¯Î±.\nÎÎµÎ²Î±Î¹ÏÎžÎµÎ¯ÏÎµ ÏÏÎ¹ ÎºÎ±ÎœÎ­ÎœÎ± Î±ÏÏ ÏÎ± Î±ÏÏÎµÎ¯Î± ÏÎ·Ï ÏÏ
+Î»Î»Î¿Î³Î®Ï ÎŽÎµÎœ ÎµÎ¯ÎœÎ±Î¹ Î±ÎœÎ¿Î¹Î³ÎŒÎ­ÎœÎ¿ Î±ÏÏ ÎµÎŸÏÏÎµÏÎ¹ÎºÏ ÏÏÏÎ³ÏÎ±ÎŒÎŒÎ±.
+#*****************************
+#
+#***** CollectionPopupMenu *****
+CollectionPopupMenu.Delete:ÎÎ¹Î±Î³ÏÎ±ÏÎ®  # Updated 1-Apr-2005
+CollectionPopupMenu.New_Dummy_Doc:ÎÎ­Î¿ dummy Î­Î³Î³ÏÎ±ÏÎ¿  # Updated 1-Apr-2005
+CollectionPopupMenu.New_Folder:ÎÎ­Î¿Ï ÎŠÎ¬ÎºÎµÎ»Î¿Ï  # Updated 1-Apr-2005
+CollectionPopupMenu.Rename:ÎÎµÏÎ¿ÎœÎ¿ÎŒÎ±ÏÎ¯Î±
+CollectionPopupMenu.Replace:ÎÎœÏÎ¹ÎºÎ±ÏÎ¬ÏÏÎ±ÏÎ·
+#*******************************
+#
+#***** CreatePane *****
+CreatePane.Build:ÎÏÎ¹Î»Î¿Î³Î­Ï ÎÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¯Î±Ï  # Updated 1-Apr-2005
+CreatePane.Build_Tooltip:ÎÏÎ¹Î»Î¿Î³Î­Ï Î³Î¹Î± ÏÎ± ÎµÏ
+ÏÎµÏÎ®ÏÎ¹Î± ÎºÎ±Î¹ ÏÎ·Îœ ÎºÎ±ÏÎ·Î³Î¿ÏÎ¹Î¿ÏÎ¿Î¯Î·ÏÎ· ÏÎ·Ï ÏÏ
+Î»Î»Î¿Î³Î®Ï.  # Updated 1-Apr-2005
+CreatePane.Build_Collection:Î§ÏÎ¯ÏÎ¹ÎŒÎ¿ Î£Ï
+Î»Î»Î¿Î³Î®Ï  # Updated 1-Apr-2005
+CreatePane.Build_Collection_Tooltip:ÎÎµÎºÎ¹ÎœÎ¬ ÏÎ· ÎŽÎ¹Î±ÎŽÎ¹ÎºÎ±ÏÎ¯Î± ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¯Î±Ï ÏÎ·Ï ÏÏ
+Î»Î»Î¿Î³Î®Ï  # Updated 1-Apr-2005
+CreatePane.Build_Progress:Î ÏÏÎ¿ÎŽÎ¿Ï ÎÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¯Î±Ï  # Updated 1-Apr-2005
+CreatePane.Cancel_Build:ÎÎºÏÏÏÏÎ· ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¯Î±Ï  # Updated 1-Apr-2005
+CreatePane.Cancel_Build_Tooltip:Î Î±ÏÏÎ· ÏÎ·Ï ÎŽÎ¹Î±ÎŽÎ¹ÎºÎ±ÏÎ¯Î±Ï ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¯Î±Ï  # Updated 1-Apr-2005
+CreatePane.Full_Build:Î Î»Î®ÏÎ·Ï ÎµÏÎ±ÎœÎ±ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¯Î±
+CreatePane.Full_Build_Tooltip:Î Î»Î®ÏÎ·Ï ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¯Î± ÏÎ·Ï ÏÏ
+Î»Î»Î¿Î³Î®Ï Î±ÏÏ ÏÎ·Îœ Î±ÏÏÎ®
+CreatePane.Import:ÎÏÎ¹Î»Î¿Î³Î­Ï ÎÎ¹ÏÎ±Î³ÏÎ³Î®Ï  # Updated 1-Apr-2005
+CreatePane.Import_Tooltip:ÎÏÎ¹Î»Î¿Î³Î­Ï Î³Î¹Î± ÏÎ· ÎŒÎµÏÎ±ÏÏÎ¿ÏÎ® ÏÎ¿Ï
+ Î±ÏÏÎµÎ¯Î¿Ï
+ ÎºÎ±Î¹ ÎºÎ±Î¹ ÎºÎ±ÏÎ±ÏÏÏÎ·ÏÎ· ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ  # Updated 1-Apr-2005
+CreatePane.Import_Progress:Î ÏÏÎ¿ÎŽÎ¿Ï ÎÎ¹ÏÎ±Î³ÏÎ³Î®Ï  # Updated 1-Apr-2005
+CreatePane.Incremental_Build:ÎÎ±ÎžÎŒÎ¹Î±Î¯Î± ÎÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¯Î±
+CreatePane.Incremental_Build_Tooltip:ÎÏÎ·Î³Î¿ÏÏÏÎµÏÎ·, ÎºÎ±ÎžÏÏ ÎµÎºÏÎµÎ»Î¿ÏÎœÏÎ±Î¹ ÎŒÏÎœÎ¿ ÏÎ± ÏÎŒÎ®ÎŒÎ±ÏÎ± ÏÎ¿Ï
+ Î±ÏÎ±Î¹ÏÎ¿ÏÎœÏÎ±Î¹.
+CreatePane.Log:ÎÎ±ÏÎ±Î³ÏÎ±ÏÎ® ÎŒÎ·ÎœÏ
+ÎŒÎ¬ÏÏÎœ  # Updated 1-Apr-2005
+CreatePane.Log_Tooltip:Î Î±ÏÎ¿Ï
+ÏÎ¹Î¬Î¶ÎµÎ¹ ÏÎ± Î±ÏÎ¿ÏÎµÎ»Î­ÏÎŒÎ±ÏÎ± Î±ÏÏ ÏÏÎ¿Î·Î³Î¿ÏÎŒÎµÎœÎµÏ ÎµÎœÎ­ÏÎ³ÎµÎ¹ÎµÏ ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¯Î±Ï  # Updated 1-Apr-2005
+CreatePane.Mode_All:ÎÎ»Î±  # Updated 1-Apr-2005
+CreatePane.Options:ÎÏÎ¹Î»Î¿Î³Î­Ï ÏÎŒÎ·ÎŒÎ¬ÏÏÎœ  # Updated 1-Apr-2005
+CreatePane.Options_Title:ÎÏÎ¹Î»Î¿Î³Î­Ï ÎÎ¹ÏÎ±Î³ÏÎ³Î®Ï ÎºÎ±Î¹ ÎÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¯Î±Ï  # Updated 1-Apr-2005
+CreatePane.Preview_Collection:Î ÏÎ¿ÎµÏÎ¹ÏÎºÏÏÎ·ÏÎ· Î£Ï
+Î»Î»Î¿Î³Î®Ï  # Updated 1-Apr-2005
+CreatePane.Preview_Collection_Tooltip:Î ÏÎ¿ÎµÏÎ¹ÏÎºÏÏÎ·ÏÎ· ÏÎ·Ï ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î·ÎŒÎ­ÎœÎ·Ï ÏÏ
+Î»Î»Î¿Î³Î®Ï  # Updated 1-Apr-2005
+#**********************
+#
+#***** Dates *****
+Dates.Mon:ÎÎµÏ
+ÏÎ­ÏÎ±  # Updated 1-Apr-2005
+Dates.Tue:Î€ÏÎ¯ÏÎ·  # Updated 1-Apr-2005
+Dates.Wed:Î€ÎµÏÎ¬ÏÏÎ·  # Updated 1-Apr-2005
+Dates.Thu:Î Î­ÎŒÏÏÎ·  # Updated 1-Apr-2005
+Dates.Fri:Î Î±ÏÎ±ÏÎºÎµÏ
+Î®  # Updated 1-Apr-2005
+Dates.Sat:Î£Î¬Î²Î²Î±ÏÎ¿  # Updated 1-Apr-2005
+Dates.Sun:ÎÏ
+ÏÎ¹Î±ÎºÎ®  # Updated 1-Apr-2005
+Dates.Jan:ÎÎ±ÎœÎ¿Ï
+Î¬ÏÎ¹Î¿Ï  # Updated 1-Apr-2005
+Dates.Feb:ÎŠÎµÎ²ÏÎ¿Ï
+Î¬ÏÎ¹Î¿Ï  # Updated 1-Apr-2005
+Dates.Mar:ÎÎ¬ÏÏÎ¹Î¿Ï  # Updated 1-Apr-2005
+Dates.Apr:ÎÏÏÎ¯Î»Î¹Î¿Ï  # Updated 1-Apr-2005
+Dates.May:ÎÎ¬ÏÎ¿Ï  # Updated 1-Apr-2005
+Dates.Jun:ÎÎ¿ÏÎœÎ¹Î¿Ï  # Updated 1-Apr-2005
+Dates.Jul:ÎÎ¿ÏÎ»Î¹Î¿Ï  # Updated 1-Apr-2005
+Dates.Aug:ÎÏÎ³Î¿Ï
+ÏÏÎ¿Ï  # Updated 1-Apr-2005
+Dates.Sep:Î£ÎµÏÏÎ­ÎŒÎ²ÏÎ·Ï  # Updated 1-Apr-2005
+Dates.Oct:Î¿ÎºÏÏÎ²ÏÎ·Ï  # Updated 1-Apr-2005
+Dates.Nov:ÎÎ¿Î­ÎŒÎ²ÏÎ·Ï  # Updated 1-Apr-2005
+Dates.Dec:ÎÎµÎºÎ­ÎŒÎ²ÏÎ·Ï  # Updated 1-Apr-2005
+#**********************
+#
+#***** Delete Collection Prompt *****
+DeleteCollectionPrompt.Collection_Details:ÎÎµÏÏÎ¿ÎŒÎ­ÏÎµÎ¹ÎµÏ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ·Ï ÏÏ
+Î»Î»Î¿Î³Î®Ï  # Updated 1-Apr-2005
+DeleteCollectionPrompt.Collection_List:ÎÎ¹Î±ÎžÎ­ÏÎ¹ÎŒÎµÏ Î£Ï
+Î»Î»Î¿Î³Î­Ï  # Updated 1-Apr-2005
+DeleteCollectionPrompt.Confirm_Delete:Î Î±ÏÎ±ÎºÎ±Î»Î¿ÏÎŒÎµ ÎµÏÎ¹Î»Î­ÎŸÏÎµ ÏÎ¿ ÎºÎ¿Ï
+ÏÎ¬ÎºÎ¹ Î³Î¹Î± ÎµÏÎ¹Î²ÎµÎ²Î±Î¯ÏÏÎ·.  # Updated 1-Apr-2005
+DeleteCollectionPrompt.Delete:ÎÎ¹Î±Î³ÏÎ±ÏÏÎ®  # Updated 1-Apr-2005
+DeleteCollectionPrompt.Delete_Tooltip:ÎÎ¹Î±Î³ÏÎ¬ÏÎµÎ¹ ÏÎ·Îœ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ· Î£Ï
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+DeleteCollectionPrompt.Details:ÎÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³ÏÏ - {0}\nÎ£Ï
+ÎœÏÎ·ÏÎ·ÏÎ®Ï - {1}\nÎ ÎµÏÎ¹Î³ÏÎ±ÏÎ®\n{2}  # Updated 1-Apr-2005
+DeleteCollectionPrompt.Failed_Delete:Î ÏÏ
+Î»Î»Î¿Î³Î® ÎŽÎµ ÎŒÏÏÏÎµÏÎµ ÎœÎ± ÎŽÎ¹Î±Î³ÏÎ±ÏÎµÎ¯ ÏÎ»Î®ÏÏÏ  # Updated 1-Apr-2005
+DeleteCollectionPrompt.Failed_Title:Î ÎŽÎ¹Î±Î³ÏÎ±ÏÎ® Î±ÏÎ­ÏÏ
+ÏÎµ!  # Updated 1-Apr-2005
+DeleteCollectionPrompt.No_Collection:ÎÎµÎœ ÎµÏÎ¹Î»Î­ÏÎžÎ·ÎºÎµ ÏÏ
+Î»Î»Î¿Î³Î®.  # Updated 1-Apr-2005
+DeleteCollectionPrompt.Successful_Delete:Î ÏÏ
+Î»Î»Î¿Î³Î® Î­ÏÎµÎ¹ ÎŽÎ¹Î±Î³ÏÎ±ÏÎµÎ¯.  # Updated 1-Apr-2005
+DeleteCollectionPrompt.Successful_Title:Î ÎŽÎ¹Î±Î³ÏÎ±ÏÎ® Î¿Î»Î¿ÎºÎ»Î·ÏÏÎžÎ·ÎºÎµ!  # Updated 1-Apr-2005
+DeleteCollectionPrompt.Title:ÎÎ¹Î±Î³ÏÎ±ÏÎ® Î£Ï
+Î»Î»Î¿Î³Î®Ï  # Updated 1-Apr-2005
+#**********************
+#
+#***** DirectoryLevelMetadata *****
+DirectoryLevelMetadata.Message:ÎÎ± ÎºÎ±ÏÎ±ÏÏÏÎ®ÏÎµÏÎµ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ± ÎµÏÎ¹ÏÎ­ÎŽÎ¿Ï
+ ÏÎ±ÎºÎ­Î»Î¿Ï
+ ÏÎµ Î­ÎœÎ± ÏÎ¬ÎºÎµÎ»Î¿. ÎÏ
+ÏÎ¬ ÏÎ± ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ± ÎžÎ± ÎºÎ»Î·ÏÎ¿ÎŽÎ¿ÏÎ·ÎžÎ¿ÏÎœ Î±Ï
+ÏÏÎŒÎ±ÏÎ± ÎºÎ±Î¹ ÏÏÎ± ÎºÎ±ÏÏÏÎµÏÎ± ÏÏÎ·Îœ Î¹ÎµÏÎ±ÏÏÎ¯Î± Î±ÏÏÎµÎ¯Î± ÎºÎ±Î¹ ÎŽÎµ ÎŒÏÎ¿ÏÎ¿ÏÎœ ÎœÎ± ÎŽÎ¹Î±Î³ÏÎ±ÏÎ¿ÏÎœ ÏÎ±ÏÎ¬ ÎŒÏÎœÎ¿ ÎœÎ± Î±ÎœÏÎ¹ÎºÎ±ÏÎ±ÏÏÎ±ÎžÎ¿ÏÎœ. ÎÎ¹Î± ÎœÎ± ÏÏ
+ÎœÎµÏÎ¯ÏÎµÏÎµ ÏÎ±ÏÎ®ÏÏÎµ 'OK'.  # Updated 1-Apr-2005
+DirectoryLevelMetadata.Title:ÎÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ± ÎµÏÎ¹ÏÎ­ÎŽÎ¿Ï
+ ÏÎ±ÎºÎ­Î»Î¿Ï
+  # Updated 1-Apr-2005
+#********************
+#
+#***** EnrichPane *****
+EnrichPane.AutoMessage:ÎÏ
+ÏÏÏ Î¿ element, {0}, Î±ÎœÎ®ÎºÎµÎ¹ ÏÏÎ± Î±Ï
+ÏÏÎŒÎ±ÏÎ± ÎµÎŸÎ±Î³ÏÎŒÎµÎœÎ± ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ± ÏÎ¿Ï
+ Greenstone. ÎÎ¹Î± ÎœÎ± ÎµÎ»Î­Î³ÎŸÎµÏÎµ ÏÎ¿Î¹Î± {0} ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ± ÎŒÏÎ¿ÏÎ¿ÏÎœ ÎœÎ± ÎµÎŸÎ±ÏÎžÎ¿ÏÎœ ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î®ÏÏÎµ ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®.  # Updated 1-Apr-2005
+EnrichPane.ExistingValues:Î¥ÏÎ¬ÏÏÎ¿Ï
+ÏÎµÏ ÏÎ¹ÎŒÎ­Ï Î³Î¹Î± ÏÎ¿ {0}  # Updated 1-Apr-2005
+EnrichPane.InheritedMetadataSelected:ÎÏ
+ÏÏÏ Î¿ ÏÏÎ¿Ï ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ ÎºÎ»Î·ÏÎ¿ÎœÎ¿ÎŒÎµÎ¯ ÏÎ·Îœ ÏÎ¹ÎŒÎ® ÏÎ¿Ï
+ Î±ÏÏ Î­ÎœÎ± ÏÎ¬ÎºÎµÎ»Î¿ ÏÎ¬ÎœÏ Î±ÏÏ Î±Ï
+ÏÏÎœ ÎºÎ±Î¹ ÎŽÎµ ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± Î±Î»Î»Î¬ÎŸÎµÎ¹ Î±ÏÏ ÎµÎŽÏ. ÎÏÎ¿ÏÎµÎ¯ÏÎµ ÎœÎ± ÎµÏÎ¹ÏÎºÎµÏ
+ÎžÎµÎ¯ÏÎµ ÏÎ¿ ÏÎ¬ÎºÎµÎ»Î¿ ÎºÎ¬ÎœÎ¿ÎœÏÎ±Ï ÎºÎ»Î¹Îº ÏÏÎ¿ ÎµÎ¹ÎºÎ¿ÎœÎ¯ÎŽÎ¹Î¿ ÏÏÎ·Îœ Î±ÏÏÎ® ÏÎ·Ï Î³ÏÎ±ÎŒÎŒÎ®Ï.  # Updated 1-Apr-2005
+EnrichPane.No_File:ÎÎµ Î­ÏÎµÎ¹ ÎµÏÎ¹Î»ÎµÎ³ÎµÎ¯ Î±ÏÏÎµÎ¯Î¿  # Updated 1-Apr-2005
+EnrichPane.No_Metadata:ÎÎµ Ï
+ÏÎ¬ÏÏÎµÎ¹ ÎŽÎ¹Î±ÎžÎ­ÏÎ¹ÎŒÎ¿ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ¿  # Updated 1-Apr-2005
+EnrichPane.No_Metadata_Element:<HTML><STRONG><FONT FACE={FONT} COLOR=Black>ÎÎµÎœ Î­ÏÎµÎ¹ ÎµÏÎ¹Î»ÎµÎ³ÎµÎ¯ ÏÏÎ¿Ï ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ</FONT></STRONG></HTML>  # Updated 1-Apr-2005
+EnrichPane.NotOneFileOnlyMetadataSelected:ÎÏ
+ÏÏ ÏÎ¿ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ¿ ÎŽÎµÎœ ÎµÏÎ±ÏÎŒÏÎ¶ÎµÏÎ±Î¹ ÏÎµ Î±Ï
+ÏÏ ÏÎ¿ Î±ÏÏÎµÎ¯Î¿ ÎºÎ±Î¹ ÎŽÎµÎœ ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± ÏÏÎ¿ÏÎ¿ÏÎ¿Î¹Î·ÎžÎµÎ¯
+EnrichPane.Value_Field_Tooltip:Î€Î¹ÎŒÎ® ÏÏÎ¿Ï ÎºÎ±ÏÎ±ÏÏÏÎ·ÏÎ· ÏÏÎ¿Îœ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿ ÏÏÎ¿ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ  # Updated 1-Apr-2005
+EnrichPane.Value_Field_Tooltip_Uneditable:ÎÎ±ÏÎ±ÏÏÏÎ·ÎŒÎ­ÎœÎ· ÏÎ¹ÎŒÎ® ÏÏÎ¿Îœ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿ ÏÏÎ¿ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ  # Updated 1-Apr-2005
+#***********************
+#
+#****** ExplodeMetadataPrompt *******
+ExplodeMetadataPrompt.Explode:ÎÎºÏÏ
+ÎŸÎ·  # Updated 1-Apr-2005
+ExplodeMetadataPrompt.Explode_Tooltip:Explode the metadata file  # Updated 1-Apr-2005
+ExplodeMetadataPrompt.Instructions:Exploding this metadata file will produce individual records with editable metadata. This is an irreversible process and the original metadata file will be removed from the collection.  # Updated 1-Apr-2005
+ExplodeMetadataPrompt.Failed_Title:Exploding Failed.  # Updated 1-Apr-2005
+ExplodeMetadataPrompt.Failed_Explode:The database {0} could not be exploded.  # Updated 1-Apr-2005
+ExplodeMetadataPrompt.NotExplodable:This file is not explodable.  # Updated 1-Apr-2005
+ExplodeMetadataPrompt.Successful_Explode:Database {0} successfully exploded.  # Updated 1-Apr-2005
+ExplodeMetadataPrompt.Successful_Title:Exploding Complete.  # Updated 1-Apr-2005
+ExplodeMetadataPrompt.Title:Explode Metadata Database  # Updated 1-Apr-2005
+#***********************
+#
+#****** WriteCDImagePrompt *******
+WriteCDImagePrompt.CD_Name:ÎÎœÎ¿ÎŒÎ± CD/DVD  # Updated 1-Apr-2005
+WriteCDImagePrompt.Export:ÎÏÎ¬ÏÎµ Image CD/DVD  # Updated 1-Apr-2005
+WriteCDImagePrompt.Export_Tooltip:ÎÏÎ¬ÏÎµ ÏÎ·Îœ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ· ÏÏ
+Î»Î»Î¿Î³Î® ÏÏ Î­ÎœÎ± Windows CD/DVD Image  # Updated 1-Apr-2005
+WriteCDImagePrompt.Failed_Export:ÎÎ¹ ÏÏ
+Î»Î»Î¿Î³Î­Ï ({0}) ÎŽÎµ ÎŒÏÏÏÎµÏÎ±Îœ ÎœÎ± ÎµÎŸÎ±ÏÎžÎ¿ÏÎœ.  # Updated 1-Apr-2005
+WriteCDImagePrompt.Failed_Title:Î ÎµÎŸÎ±Î³ÏÎ³Î® Î±ÏÎ­ÏÏ
+ÏÎµ  # Updated 1-Apr-2005
+WriteCDImagePrompt.Instructions:ÎÎŸÎ±Î³ÏÎ³Î® ÎŒÎ¹Î±Ï Î® ÏÎµÏÎ¹ÏÏÏÏÎµÏÏÎœ ÏÏ
+Î»Î»Î¿Î³ÏÎœ ÏÎµ Î­ÎœÎ± self-installing Windows CD/DVD. Î€Î¿ CD ÎžÎ± ÎŽÎ¿Ï
+Î»ÎµÏÎµÎ¹ ÎŒÏÎœÎ¿ ÏÎµ Windows.  # Updated 1-Apr-2005
+WriteCDImagePrompt.Netscape_Compatibility:Bundle Netscape4 browser (and Netscape4 compatibility macros and images).
+WriteCDImagePrompt.Progress_Label:ÎÎœÏÎ¹Î³ÏÎ±ÏÎ® ÎÏÏÎµÎ¯ÏÎœ. ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± ÏÎ¬ÏÎµÎ¹ Î»Î¯Î³Î¿ ÏÏÏÎœÎ¿...  # Updated 1-Apr-2005
+WriteCDImagePrompt.Size_Label:ÎÎºÏÎ¹ÎŒÏÎŒÎµÎœÎ¿ ÎŒÎ­Î³ÎµÎžÎ¿Ï
+WriteCDImagePrompt.Successful_Export:ÎÎ¹ ÏÏ
+Î»Î»Î¿Î³Î­Ï ({0}) Î­ÏÎ¿Ï
+Îœ ÎµÎŸÎ±ÏÎžÎµÎ¯.  # Updated 1-Apr-2005
+WriteCDImagePrompt.Successful_Title:Î ÎµÎŸÎ±Î³ÏÎ³Î® Î¿Î»Î¿ÎºÎ»Î·ÏÏÎžÎ·ÎºÎµ  # Updated 1-Apr-2005
+WriteCDImagePrompt.Title:ÎÎŸÎ±Î³ÏÎ³Î® ÏÏ
+Î»Î»Î¿Î³Î®Ï ÏÎµ CD/DVD  # Updated 1-Apr-2005
+#************************
+#
+#****** ExportAsPrompt *******
+ExportAsPrompt.Export_Name:ÎÎŸÎ±Î³ÏÎ³Î® ÎÎœÏÎŒÎ±ÏÎ¿Ï ÎÎ±ÏÎ±Î»ÏÎ³Î¿Ï
+  # Updated 1-Apr-2005
+ExportAsPrompt.Export:ÎÎŸÎ±Î³ÏÎ³Î® Î£Ï
+Î»Î»Î¿Î³Î®Ï  # Updated 1-Apr-2005
+ExportAsPrompt.Export_Tooltip:ÎÎŸÎ¬Î³ÎµÎ¹ ÏÎ¹Ï ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎµÏ ÏÏ
+Î»Î»Î¿Î³Î­Ï ÏÏÎ¿Îœ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿ ÏÏÏÎ¿ Î±ÏÏÎµÎ¯Î¿Ï
+ ÎºÎ±Î¹ ÎºÎ±ÏÎ¬Î»Î¿Î³Î¿.  # Updated 1-Apr-2005
+ExportAsPrompt.Failed_ExportOne:Î ÏÏ
+Î»Î»Î¿Î³Î®, {0}, ÎŽÎµ ÎŒÏÏÏÎµÏÎµ ÎœÎ± ÎµÎŸÎ±ÏÎžÎµÎ¯.  # Updated 1-Apr-2005
+ExportAsPrompt.Failed_ExportMany:ÎÎ¹ ÏÏ
+Î»Î»Î¿Î³Î­Ï -- {0} -- ÎŽÎµ ÎŒÏÏÏÎµÏÎ±Îœ ÎœÎ± ÎµÎŸÎ±ÏÎžÎ¿ÏÎœ.  # Updated 1-Apr-2005
+ExportAsPrompt.Failed_Details:ÎÎµÎ¯ÏÎµ {1} Î³Î¹Î± Î»ÎµÏÏÎ¿ÎŒÎ­ÏÎµÎ¹ÎµÏ  # Updated 1-Apr-2005
+ExportAsPrompt.Failed_Title:Î ÎµÎŸÎ±Î³ÏÎ³Î® Î±ÏÎ­ÏÏ
+ÏÎµ  # Updated 1-Apr-2005
+ExportAsPrompt.Instructions:ÎÎŸÎ¬Î³ÎµÏÎµ ÎŒÎ¯Î± ÎÎÎ· ÏÎµÏÎ¹ÏÏÏÏÎµÏÎµÏ ÏÏ
+Î»Î»Î¿Î³Î­Ï ÏÏÎ¿Îœ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿ ÎŒÎ¿ÏÏÏÏÏ
+ÏÎ¿ ÎºÎ±Î¹ ÎºÎ±ÏÎ¬Î»Î¿Î³Î¿.  # Updated 1-Apr-2005
+ExportAsPrompt.Progress_Label:ÎÎŸÎ±Î³ÏÎ³Î® Î±ÏÏÎµÎ¯ÏÎœ. ÎÏÎ¿ÏÎµÎ¯ ÎœÎ± ÎŽÎ¹Î±ÏÎºÎ­ÏÎµÎ¹ Î»Î¯Î³Î¿ ÏÏÏÎœÎ¿...  # Updated 1-Apr-2005
+ExportAsPrompt.Successful_ExportOne:Î ÏÏ
+Î»Î»Î¿Î³Î®, {0}, Î­ÏÎµÎ¹ ÎµÎŸÎ±ÏÎžÎµÎ¯.  # Updated 1-Apr-2005
+ExportAsPrompt.Successful_ExportMany:ÎÎ¹ ÏÏ
+Î»Î»Î¿Î³Î­Ï -- {0} -- Î­ÏÎ¿Ï
+Îœ ÎµÎŸÎ±ÏÎžÎµÎ¯.  # Updated 1-Apr-2005
+ExportAsPrompt.Successful_Details:Î€Î± Î±ÏÏÎµÎ¯Î± ÎµÎŸÎ®ÏÎžÎ·ÏÎ±Îœ ÏÏÎ¿: {1}  # Updated 1-Apr-2005
+ExportAsPrompt.Successful_Title:Î ÎµÎŸÎ±Î³ÏÎ³Î® Î¿Î»Î¿ÎºÎ»Î·ÏÏÎžÎ·ÎºÎµ  # Updated 1-Apr-2005
+ExportAsPrompt.Title:ÎÎŸÎ±Î³ÏÎ³Î® Î£Ï
+Î»Î»Î¿Î³ÏÎœ  # Updated 1-Apr-2005
+ExportAsPrompt.SaveAs:ÎÎŸÎ±Î³ÏÎ³Î® ÏÎµ  # Updated 1-Apr-2005
+ExportAsPrompt.SaveAs_Tooltip:ÎÏÎ¹Î»Î­ÎŸÏÎµ ÏÎ¿Îœ ÏÏÏÎ¿ Î±ÏÏÎµÎ¯Î¿Ï
+ ÏÎ¿Ï
+ ÎžÎ­Î»ÎµÏÎµ ÎœÎ± Î³Î¯ÎœÎµÎ¹ Î· ÎµÎŸÎ±Î³ÏÎ³Î®  # Updated 1-Apr-2005
+#************************
+#
+#*****ExternalCollectionPrompt********
+ExternalCollectionPrompt.NewMDS:ÎÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î®ÏÏÎµ Î­ÎœÎ± ÎœÎ­Î¿ ÎºÎµÎœÏ ÏÏÎœÎ¿Î»Î¿ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ.  # Updated 1-Apr-2005
+ExternalCollectionPrompt.ExistingMDS:ÎÏÎ¹Î»Î­ÎŸÏÎµ Î­ÎœÎ± Î® ÏÎµÏÎ¹ÏÏÏÏÎµÏÎ± Î±ÏÏ ÏÎ± Ï
+ÏÎ¬ÏÏÎ¿ÎœÏÎ± ÏÏÎœÎ¿Î»Î± ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ  # Updated 1-Apr-2005
+ExternalCollectionPrompt.Title:ÎŠÏÏÏÏÏÎ· ÎÎŸÏÏÎµÏÎ¹ÎºÎ®Ï Î£Ï
+Î»Î»Î¿Î³Î®Ï  # Updated 1-Apr-2005
+ExternalCollectionPrompt.Instructions_1:Î ÏÎ¿ÏÎ¯ÎžÎµÏÏÎµ ÎœÎ± ÏÎ¿ÏÏÏÏÎµÏÎµ ÎŒÎ¹Î± ÏÏ
+Î»Î»Î¿Î³Î® ÏÎ¿Ï
+ ÎŽÎµÎœ Î­ÏÎµÎ¹ ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î·ÎžÎµÎ¯ Î±ÏÏ ÏÎ¿ Ï
+ÏÎ¬ÏÏÎ¿Îœ ÏÏÏÏÎ·ÎŒÎ±. ÎÎ± ÏÎ±Ï Î¶Î·ÏÎ·ÎžÎµÎ¯ ÎœÎ± ÎµÏÎ¹Î»Î­ÎŸÎµÏÎµ Î­ÎœÎ± Î® ÏÎµÏÎ¹ÏÏÏÏÎµÏÎ± ÏÏÎœÎ¿Î»Î± ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ Î³Î¹Î± ÏÏÎ®ÏÎ· ÎŒÎµ Î±Ï
+ÏÎ® ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®. Î¥ÏÎ¬ÏÏÎ¿ÎœÏÎ± ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ± ÎžÎ± ÎµÎ¹ÏÎ±ÏÎžÎ¿ÏÎœ ÎŒÎµ ÏÏÎ± ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ± ÏÏÎœÎ¿Î»Î±. Î€Î± Î±ÏÏÎ¹ÎºÎ¬ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ± ÎžÎ± ÎŽÎ¹Î±ÏÎ·ÏÎ·ÎžÎ¿ÏÎœ ÏÏÎ¿ Î±ÏÏÎµÎ¯Î¿ import.bak (just incase).  # Updated 1-Apr-2005
+ExternalCollectionPrompt.Instructions_2:Î ÏÎ¿ÏÎ¯ÎžÎµÏÏÎµ ÎœÎ± ÏÎ¿ÏÏÏÏÎµÏÎµ ÎŒÎ¹Î± ÏÏ
+Î»Î»Î¿Î³Î® ÏÎ¿Ï
+ ÎŽÎµÎœ Î­ÏÎµÎ¹ ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î·ÎžÎµÎ¯ Î±ÏÏ ÏÎ¿ Ï
+ÏÎ¬ÏÏÎ¿Îœ ÏÏÏÏÎ·ÎŒÎ±. ÎÎ± ÏÏÎ­ÏÎµÎ¹ ÎœÎ± ÏÏÎ¿ÏÎžÎ­ÏÎµÏÎµ Î­ÎœÎ± ÏÏÎœÎ¿Î»Î¿ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ ÏÎµ Î±Ï
+ÏÎ® ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®. ÎÏÎ¿ÏÎµÎ¯ÏÎµ ÎœÎ± ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î®ÏÎµÏÎµ Î­ÎœÎ± ÎœÎ­Î¿ Î¬ÎŽÎµÎ¹Î¿, ÏÏÎ¿ Î¿ÏÎ¿Î¯Î¿ ÎžÎ± ÏÏÎ¿ÏÏÎµÎžÎ¿ÏÎœ ÏÎ± Ï
+ÏÎ¬ÏÏÎ¿ÎœÏÎ± ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ± Î® ÎœÎ± ÏÏÎ·ÏÎ¹ÎŒÎ¿ÏÎ¿Î¹ÎµÎ¯ÏÎµÏÎµ Î­ÎœÎ± Î±ÏÏ ÏÎ± Ï
+ÏÎ¬ÏÏÎ¿ÎœÏÎ± ÏÏÎ¿ Î¿ÏÎ¿Î¯Î¿ Î­ÏÎµÏÎµ ÏÎ· ÎŽÏ
+ÎœÎ±ÏÏÏÎ·ÏÎ± ÎµÎ¯ÏÎµ ÎœÎ± ÏÏÎ¿ÏÎžÎ­ÏÎµÏÎµ ÎµÎ¯ÏÎµ ÎœÎ± ÏÏ
+ÎœÎµÎœÏÏÎµÏÎµ Ï
+ÏÎ¬ÏÏÎ¿ÎœÏÎ± ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ±. Î€Î± Î±ÏÏÎ¹ÎºÎ¬ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ± ÎžÎ± ÎŽÎ¹Î±ÏÎ·ÏÎ·ÎžÎ¿ÏÎœ ÏÏÎ¿ Î±ÏÏÎµÎ¯Î¿ import.bak (just incase).
+#****************************************
+#
+#***** Inherited Metadata *****
+ExtractedMetadata.Message:Î€Î¿ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿ Î±ÏÏÎµÎ¯Î¿ Î® ÏÎ¬ÎºÎµÎ»Î¿Ï ÏÎµÏÎ¹Î­ÏÎµÎ¹ ÎµÎŸÎ±Î³ÎŒÎ­ÎœÎ± ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ± ÏÎ± Î¿ÏÎ¿Î¯Î± ÎµÎ¯ÎœÎ±Î¹ ÎºÏÏ
+ÎŒÎŒÎ­ÎœÎ±. ÎÎ¹Î± ÎœÎ± ÏÎ± ÎŽÎµÎ¯ÏÎµ ÏÏÎ¿ÏÎ¿ÏÎ¿Î¹Î®ÏÏÎµ Î±ÎœÏÎ¯ÏÏÎ¿Î¹ÏÎ± Î±ÏÏ ÏÎ· Î³ÎµÎœÎ¹ÎºÎ® ÎºÎ±ÏÏÎ­Î»Î± ÏÏÎœ ÎµÏÎ¹Î»Î¿Î³ÏÎœ.  # Updated 1-Apr-2005
+ExtractedMetadata.Title:ÎÏ
+ÏÏ ÏÎ¿ Î±ÏÏÎµÎ¯Î¿/ÏÎ¬ÎºÎµÎ»Î¿Ï Î­ÏÎµÎ¹ ÎºÏÏ
+ÏÎ¬, ÎµÎŸÎ±Î³ÎŒÎ­ÎœÎ± ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ±.  # Updated 1-Apr-2005
+#
+#***** FileActions *****
+FileActions.Calculating_Size:Î¥ÏÎ¿Î»Î¿Î³Î¯Î¶ÎµÏÎ±Î¹ ÏÎ¿ ÏÏ
+ÎœÎ¿Î»Î¹ÎºÏ ÎŒÎ­Î³ÎµÎžÎ¿Ï ÏÏÎœ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÏÎœ Î±ÏÏÎµÎ¯ÏÎœ.  # Updated 1-Apr-2005
+FileActions.Copying:ÎÏÎ¹Î³ÏÎ¬ÏÎ¿ÎœÏÎ±Ï {0}  # Updated 1-Apr-2005
+FileActions.Could_Not_Delete:ÎÎµ Î³Î¯ÎœÎµÏÎµ ÎœÎ± ÎŽÎ¹Î±Î³ÏÎ±ÏÎµÎ¯ {0}
+FileActions.Cyclic_Path:ÎÎµÎœ ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± Î±ÎœÏÎ¹Î³ÏÎ±ÏÎµÎ¯ ÏÎ¿ {0}. Î€Î¿ ÎŒÎ¿ÎœÎ¿ÏÎ¬ÏÎ¹ ÏÏÎ¿Î¿ÏÎ¹ÏÎŒÎ¿Ï ÎµÎ¯ÎœÎ±Î¹ Ï
+ÏÎ¿ÏÎ¬ÎºÎµÎ»Î¿Ï ÏÎ¿Ï
+ Î±ÏÏÎ¹ÎºÎ¿Ï
+FileActions.Deleting:ÎÎ¹Î±Î³ÏÎ¬ÏÎ¿ÎœÏÎ±Ï {0}  # Updated 1-Apr-2005
+FileActions.Directories_Selected:{0} ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿Î¹ ÏÎ¬ÎºÎµÎ»Î¿Î¹  # Updated 1-Apr-2005
+FileActions.Directory_Selected:1 ÏÎ¬ÎºÎµÎ»Î¿Ï ÎµÏÎ¹Î»Î­Î³ÎµÎ¹  # Updated 1-Apr-2005
+FileActions.File_Already_Exists_No_Create:Î€Î¿ Î±ÏÏÎµÎ¯Î¿ '{0}' Ï
+ÏÎ¬ÏÏÎµÎ¹ Î®ÎŽÎ·.  # Updated 1-Apr-2005
+FileActions.File_Already_Exists_Message:{0}\nÎÎœÎ± Î±ÏÏÎµÎ¯Î¿ ÎŒÎµ ÏÎ¿ ÏÎ±ÏÎ±ÏÎ¬ÎœÏ ÏÎœÎ¿ÎŒÎ± Ï
+ÏÎ¬ÏÏÎµÎ¹ Î®ÎŽÎ· ÏÏÎ¿Îœ \nÎºÎ±Î¹ ÏÎ±ÏÎ¬ ÏÎ·Îœ ÏÏÎ¿Î·Î³Î¿ÏÎŒÎµÎœÎ® ÏÎ±Ï ÎµÏÎ¹Î»Î¿Î³Î® \n ÎµÎ¯ÎœÎ±Î¹ Î±ÎŽÏÎœÎ±ÏÎ¿ ÎœÎ± Î³ÏÎ±ÏÏÎµÎ¯. Î Î±ÏÎ±ÎºÎ±Î»Î¿ÏÎŒÎµ ÎµÏÎ¹Î»Î­ÎŸÏÎµ ÏÎ± ÎŽÎ¹ÎºÎ±Î¹ÏÎŒÎ±ÏÎ± Î±ÏÏÎµÎ¯ÏÎœ.  # Updated 1-Apr-2005
+FileActions.File_Already_Exists_Title:Î£ÏÎ¬Î»ÎŒÎ± - Î€Î¿ Î±ÏÏÎµÎ¯Î¿ Ï
+ÏÎ¬ÏÏÎµÎ¹ Î®ÎŽÎ·.  # Updated 1-Apr-2005
+FileActions.File_And_Directories_Selected:1 Î±ÏÏÎµÎ¯Î¿ ÎºÎ±Î¹ {0} ÏÎ¬ÎºÎµÎ»Î¿Î¹ Î­ÏÎ¿Ï
+Îœ ÎµÏÎ¹Î»ÎµÎ³ÎµÎ¯  # Updated 1-Apr-2005
+FileActions.File_And_Directory_Selected:1 Î±ÏÏÎµÎ¯Î¿ ÎºÎ±Î¹ 1 ÏÎ¬ÎºÎµÎ»Î¿Ï Î­ÏÎ¿Ï
+Îœ ÎµÏÎ¹Î»ÎµÎ³ÎµÎ¯  # Updated 1-Apr-2005
+FileActions.File_Create_Error:Î€Î¿ Î±ÏÏÎµÎ¯Î¿ {0} ÎŽÎµ ÎŒÏÏÏÎµÏÎµ ÎœÎ± ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î·ÎžÎµÎ¯.  # Updated 1-Apr-2005
+FileActions.Folder_Create_Error:Î ÏÎ¬ÎºÎµÎ»Î¿Ï {0} ÎŽÎµ ÎŒÏÏÏÎµÏÎµ ÎœÎ± ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î·ÎžÎµÎ¯.  # Updated 1-Apr-2005
+FileActions.File_Exists:<html>{0} Ï
+ÏÎ¬ÏÏÎµÎ¹ Î®ÎŽÎ· ÏÏÎ¿ ÏÎ¬ÎºÎµÎ»Î¿ ÏÏÎ¿Î¿ÏÎ¹ÏÎŒÎ¿Ï. ÎÎ± ÏÎ¿ ÎµÏÎ±ÎœÎµÎ³Î³ÏÎ¬ÏÏ?</html>  # Updated 1-Apr-2005
+FileActions.File_Move_Error_Message:ÎÎµÎœ ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± ÎŒÎµÏÎ±ÎºÎ¹ÎœÎ·ÎžÎµÎ¯ ÏÎ¿ {0} ÏÏÎ¿\n{1}.
+FileActions.File_Not_Deleted_Message:{0}\nÎ€Î¿ Î±ÎœÏÏÎ­ÏÏ Î±ÏÏÎµÎ¯Î¿ ÎŽÎµÎœ ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± ÎŽÎ¹Î±Î³ÏÎ±ÏÎµÎ¯. \nÎ Î±ÏÎ±ÎºÎ±Î»Î¿ÏÎŒÎµ ÎµÎ»Î­ÎœÎŸÏÎµ ÏÏÎ¹ ÎŽÎµÎœ Î­ÏÎµÏÎµ ÏÎ¿ Î±ÏÏÎµÎ¯Î¿ Î±ÎœÎ¿Î¹ÏÏÏ\n ÎŒÎµ Î­ÎœÎ± ÎµÎŸÏÏÎµÏÎ¹ÎºÏ ÏÏÏÎ³ÏÎ±ÎŒÎŒÎ± ÎºÎ±Î¹ ÏÏÎ¿ÏÏÎ±ÎžÎµÎ¯ÏÏÎµ ÎŸÎ±ÎœÎ¬.
+FileActions.File_Not_Deleted_Title:Î£ÏÎ¬Î»ÎŒÎ± - ÏÎ¿ Î±ÏÏÎµÎ¯Î¿ ÎŽÎµÎœ ÏÎ²Î®ÏÏÎ·ÎºÎµ.
+FileActions.File_Not_Found_Message:{0}\nÎ€Î¿ ÏÎ±ÏÎ±ÏÎ¬ÎœÏ Î±ÏÏÎµÎ¯Î¿ ÎŽÎµ ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± Î²ÏÎµÎžÎµÎ¯. ÎÏÎ»Î¹Ï Î³Î¯ÎœÎµÎ¹ Î· Î±ÎœÎ±ÎœÎ­ÏÏÎ·\nÎµÎ»Î­ÎŸÏÎµ ÏÏÎ¹ ÏÎ¿ Î±ÏÏÎµÎ¯Î¿ Ï
+ÏÎ¬ÏÏÎµÎ¹.  # Updated 1-Apr-2005
+FileActions.File_Not_Found_Title:Î£ÏÎ¬Î»ÎŒÎ± - ÏÎ¿ Î±ÏÏÎµÎ¯Î¿ ÎŽÎµ Î²ÏÎ­ÎžÎ·ÎºÎµ.  # Updated 1-Apr-2005
+FileActions.File_Selected:1 ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿ Î±ÏÏÎµÎ¯Î¿  # Updated 1-Apr-2005
+FileActions.Files_And_Directory_Selected:{0} Î±ÏÏÎµÎ¯Î± ÎºÎ±Î¹ 1 ÏÎ¬ÎºÎµÎ»Î¿Ï ÎµÏÎ¹Î»Î­ÏÎžÎ·ÎºÎ±Îœ  # Updated 1-Apr-2005
+FileActions.Files_Selected:{0} Î±ÏÏÎµÎ¯Î± ÎµÏÎ¹Î»Î­ÏÎžÎ·ÎºÎ±Îœ  # Updated 1-Apr-2005
+FileActions.Folder_Already_Exists:Î€Î¿ ÏÎœÎ¿ÎŒÎ± ÏÎ¿Ï
+ Î±ÏÏÎµÎ¯Î¿Ï
+ '{0}' ÎµÎ¯ÎœÎ±Î¹ ÏÎµ ÏÏÎ®ÏÎ·. ÎÎµ ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î·ÎžÎµÎ¯ Î¿ ÏÎ¬ÎºÎµÎ»Î¿Ï.  # Updated 1-Apr-2005
+FileActions.Increase_Depth:ÎÏÎŸÎ·ÏÎ· Î²Î¬ÎžÎ¿Ï
+Ï ÎºÎ±ÏÎ¬ 1  # Updated 1-Apr-2005
+FileActions.Insufficient_Space_Message:Î ÎµÎœÎ­ÏÎ³ÎµÎ¹Î± Î­ÏÎµÎ¹ Î±ÏÎ¿ÏÏÏÎµÎ¹ Î»ÏÎ³Ï Î±ÎœÎµÏÎ±ÏÎºÎ¿ÏÏ ÏÏÏÎ¿Ï
+ ÏÏÎ¿ ÎŽÎ¯ÏÎºÎ¿.\nÎÎ¹Î± ÎœÎ± Î±ÎœÏÎ¹Î³ÏÎ±ÏÎµÎ¯ ÎµÏÎ¹ÏÏ
+ÏÏÏ ÏÎ¿ Î±ÏÏÎµÎ¯Î¿ Î±ÏÎ±Î¹ÏÎ¿ÏÎœÏÎ±Î¹ \nÎµÏÎ¹ÏÎ»Î­Î¿Îœ: {0}  # Updated 1-Apr-2005
+FileActions.Insufficient_Space_Title:Î£ÏÎ¬Î»ÎŒÎ± - ÎÎœÎµÏÎ±ÏÎºÎ®Ï ÏÏÏÎ¿Ï  # Updated 1-Apr-2005
+FileActions.Moving:ÎÎµÏÎ±ÎºÎ¹ÎœÏÎœÏÎ±Ï {0}  # Updated 1-Apr-2005
+FileActions.No_Activity:ÎÎ±ÎŒÎ¯Î± Î±Î¯ÏÎ·ÏÎ· Î³Î¹Î± ÎµÎœÎ­ÏÎ³ÎµÎ¹Î±  # Updated 1-Apr-2005
+FileActions.Possible_Cyclic_Path:{1} ÎµÎ¯ÎœÎ±Î¹ {0} ÎºÎ±ÏÎ±Î»ÏÎ³Î¿Ï
+Ï Î²Î¬ÎžÎ¿Ï ÎºÎ±Î¹ ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± ÎµÎ¯ÎœÎ±Î¹ Î±ÎœÎ±ÎŽÏÎ¿ÎŒÎ¹ÎºÏ ÎŒÎ¿ÎœÎ¿ÏÎ¬ÏÎ¹? ÎÎ± ÏÏ
+ÎœÎµÏÎ¹ÏÏÎµÎ¯ Î· ÎµÎœÎ­ÏÎ³ÎµÎ¹Î±?  # Updated 1-Apr-2005
+FileActions.Read_Not_Permitted_Message:ÎÎµÎœ ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± ÎŽÎ¹Î±Î²Î±ÏÏÎµÎ¯ {0}
+FileActions.Read_Only:Î€Î± Î±ÏÏÎµÎ¯Î± ÏÏÎ¿ ÏÎµÏÎ¹Î²Î¬Î»Î»Î¿Îœ ÎµÏÎ³Î±ÏÎ¯Î±Ï ÎŽÎµ ÎŒÏÎ¿ÏÎ¿ÏÎœ ÎœÎ± ÎŽÎ¹Î±Î³ÏÎ±ÏÎ¿ÏÎœ.  # Updated 1-Apr-2005
+FileActions.Replacing:ÎÎœÏÎ¹ÎºÎ±ÎžÎ¹ÏÏÏÎœÏÎ±Ï {0}
+FileActions.Selected:{0} Î±ÏÏÎµÎ¯Î± ÎºÎ±Î¹ {1} ÏÎ±ÎºÎµÎ»Î¿Ï ÎµÏÎ¹Î»Î­Î³ÎµÎ¹.  # Updated 1-Apr-2005
+FileActions.Unknown_File_Error_Message:Î€Î¿ Î±ÎœÏÎ¯Î³ÏÎ±ÏÎ¿ ÏÏÎ¿Î¿ÏÎ¹ÏÎŒÎ¿Ï\nÎŽÎµÎœ ÎµÎ¯ÎœÎ±Î¹ Î¯ÎŽÎ¹Î¿ ÎŒÎµ ÏÎ¿ Î±ÏÏÎ¹ÎºÏ\nÎ±ÏÏÎµÎ¯Î¿. Î Î±Î¹ÏÎ¯Î± ÎµÎ¯ÎœÎ±Î¹ Î¬Î³ÎœÏÏÏÎ·.\nÎÎ»Î­ÎŸÏÎµ ÎºÎ±Î¹ Î±ÎœÎ±ÎœÎµÏÏÏÎµ ÏÎ·Îœ JVM.  # Updated 1-Apr-2005
+FileActions.Unknown_File_Error_Title:Î£ÏÎ¬Î»ÎŒÎ± - Î¬Î³ÎœÏÏÏÎ¿ ÏÏÎ¬Î»ÎŒÎ± Î±ÏÏÎµÎ¯Î¿Ï
+.  # Updated 1-Apr-2005
+FileActions.Write_Not_Permitted_Message:Î€Î¿ ÏÎµÏÎ¹Î²Î¬Î»Î»Î¿Îœ ÏÎµÎºÎŒÎ·ÏÎ¯ÏÏÎ·Ï ÎŽÎµÎœ Î­ÏÎµÎ¹ ÎŽÎ¹ÎºÎ±Î¯ÏÎŒÎ± ÎœÎ± Î³ÏÎ¬ÏÎµÎ¹ ÏÏÎ¿\n{0}\nÎÎ»Î­ÎŸÏÎµ ÏÎ± ÎŽÎ¹ÎºÎ±Î¹ÏÎŒÎ±ÏÎ± ÏÏÏÏÎ²Î±ÏÎ·Ï ÏÏÎ¿ Î±ÏÏÎµÎ¯Î¿.  # Updated 1-Apr-2005
+FileActions.Write_Not_Permitted_Title:Î£ÏÎ¬Î»ÎŒÎ± - Î»Î¬ÎžÎ¿Ï ÎŽÎ¹ÎºÎ±Î¹ÏÎŒÎ±ÏÎ± ÏÏÏÏÎ²Î±ÏÎ·Ï.  # Updated 1-Apr-2005
+FileActions.Yes_To_All:ÎÎ±Î¹ ÏÎµ ÏÎ»Î±  # Updated 1-Apr-2005
+#************************
+#
+#******* File Associations dialog **********
+FileAssociationDialog.Add:Î ÏÎ¿ÏÎžÎ®ÎºÎ·  # Updated 1-Apr-2005
+FileAssociationDialog.Add_Tooltip:Î§ÏÎ·ÏÎ¹ÎŒÎ¿ÏÎ¿Î¹Î®ÏÏÎµ Î±Ï
+ÏÎ® ÏÎ·Îœ ÎµÏÎ±ÏÎŒÎ¿Î³Î® Î³Î¹Î± ÎœÎ± ÎŽÎµÎ¯ÏÎµ Î±ÏÏÎµÎ¯Î± Î±Ï
+ÏÎ¿Ï ÏÎ¿Ï
+ ÏÏÏÎ¿Ï
+.  # Updated 1-Apr-2005
+FileAssociationDialog.Batch_File:Batch Î±ÏÏÎµÎ¯Î±  # Updated 1-Apr-2005
+FileAssociationDialog.Browse:Î Î»Î¿Î®Î³Î·ÏÎ·  # Updated 1-Apr-2005
+FileAssociationDialog.Browse_Tooltip:ÎÎ¹Î±Î»Î­ÎŸÏÎµ ÏÎ·Îœ ÎµÏÎ±ÏÎŒÎ¿Î³Î® ÏÎ¿Ï
+ ÎžÎ± ÏÏÎ·Î¹ÎŒÎ¿ÏÎ¿Î¹Î®ÏÎµÏÎµ Î±ÏÏ ÏÎ¿ ÏÏÏÏÎ·ÎŒÎ¬ ÏÎ±Ï  # Updated 1-Apr-2005
+FileAssociationDialog.Browse_Tooltip_Mac:Î ÏÎ»Î¿Î®Î³Î·ÏÎ· Î³Î¹Î± ÏÎ·Îœ ÎµÏÎ±ÏÎŒÎ¿Î³Î® ÏÎ±Ï ÎµÎ¯ÎœÎ±Î¹ Î±ÏÎµÎœÎµÏÎ³Î¿ÏÎ¿Î¹Î·ÎŒÎ­ÎœÎ· Î³Î¹Î± MacOS  # Updated 1-Apr-2005
+FileAssociationDialog.Browse_Title:ÎÏÎ¹Î»Î­ÎŸÏÎµ ÎÏÎ±ÏÎŒÎ¿Î³Î®  # Updated 1-Apr-2005
+FileAssociationDialog.Close:ÎÎ»ÎµÎ¯ÏÎ¹ÎŒÎ¿  # Updated 1-Apr-2005
+FileAssociationDialog.Close_Tooltip:ÎÎ»ÎµÎ¯ÏÎµ Î±Ï
+ÏÏ ÏÎ¿ ÎŽÎ¹Î¬Î»Î¿Î³Î¿ ÎºÎ±Î¹ ÎµÏÎ­ÏÏÏÎµÏÎµ ÏÏÎ¿ ÎºÎµÎœÏÏÎ¹ÎºÏ ÏÎ±ÏÎ¬ÎžÏ
+ÏÎ¿  # Updated 1-Apr-2005
+FileAssociationDialog.Command:ÎÎºÏÎ­Î»ÎµÏÎ· ÎµÎœÏÎ¿Î»Î®Ï:  # Updated 1-Apr-2005
+FileAssociationDialog.Command_File:ÎÏÏÎµÎ¯Î± ÎµÎœÏÎ¿Î»ÏÎœ  # Updated 1-Apr-2005
+FileAssociationDialog.Command_Tooltip:ÎÎ¹ÏÎ¬Î³ÎµÏÎµ ÏÎ·Îœ ÎµÎœÏÎ¿Î»Î® Î³Î¹Î± ÎœÎ± ÎŸÎµÎºÎ¹ÎœÎ®ÏÎµÏÎµ ÏÎ· ÏÏÎ®ÏÎ· ÏÎ·Ï ÎµÏÎ±ÏÎŒÎ¿Î³Î®Ï  # Updated 1-Apr-2005
+FileAssociationDialog.Details:Î»ÎµÏÏÎ¿ÎŒÎ­ÏÎµÎ¹ÎµÏ ÏÏ
+ÏÏÎµÏÎ¹ÏÎŒÎ¿Ï Î±ÏÏÎµÎ¯Î¿Ï
+  # Updated 1-Apr-2005
+FileAssociationDialog.Executable_File:ÎÎºÏÎµÎ»Î­ÏÎ¹ÎŒÎ± Î±ÏÏÎµÎ¯Î±  # Updated 1-Apr-2005
+FileAssociationDialog.Existing_Associations:Î€ÏÎ­ÏÎ¿ÎœÏÎµÏ ÏÏ
+ÏÏÎµÏÎ¹ÏÎŒÎ¿Î¯ Î±ÏÏÎµÎ¯ÏÎœ  # Updated 1-Apr-2005
+FileAssociationDialog.Extension:ÎÎ¹Î± Î±ÏÏÎµÎ¯Î± ÎŒÎµ ÎºÎ±ÏÎ¬Î»Î·ÎŸÎ·:  # Updated 1-Apr-2005
+FileAssociationDialog.Extension_Tooltip:Î ÎºÎ±ÏÎ¬Î»Î·ÎŸÎ· Î³Î¹Î± ÏÎ± Î±ÏÏÎµÎ¯Î±  # Updated 1-Apr-2005
+FileAssociationDialog.Instructions:Î§ÏÎ·ÏÎ¹ÎŒÎ¿ÏÎ¿Î¹ÎµÎ¯ÏÏÎµ Î±Ï
+ÏÏ ÏÎ¿ ÎŽÎ¹Î¬Î»Î¿Î³Î¿ Î³Î¹Î± ÎœÎ± ÎžÎ­ÏÎµÏÎµ ÏÎ¿Î¹Î± ÎµÎŸÏÏÎµÏÎ¹ÎºÎ¬ ÏÏÎ¿Î³ÏÎ¬ÎŒÎŒÎ±ÏÎ± ÏÏÎ·ÏÎ¹ÎŒÎ¿ÏÎ¿Î¹Î¿ÏÎœÏÎ±Î¹ Î³Î¹Î± ÎœÎ± Î±ÎœÎ¿ÏÎ¹ÏÎžÎµÎ¯ Î­ÎœÎ±Ï ÏÏ
+Î³ÎºÎµÎºÏÎ¹ÎŒÎ­ÎœÎ¿Ï ÏÏÏÎ¿Ï Î±ÏÏÎµÎ¯Î¿Ï
+ ÎºÎ±Î¹ ÏÎ¿Î¹Î± ÎµÎœÏÎ¿Î»Î® ÎŸÎµÎºÎ¹ÎœÎ¬ Î±Ï
+ÏÏ ÏÎ¿ ÎµÎŸÏÏÎµÏÎ¹ÎºÏ ÏÏÏÎ³ÏÎ±ÎŒÎŒÎ±.  # Updated 1-Apr-2005
+FileAssociationDialog.Table.Command:ÎÎœÏÎ¿Î»Î®  # Updated 1-Apr-2005
+FileAssociationDialog.Table.Extension:ÎÏÎ­ÎºÏÎ±ÏÎ·  # Updated 1-Apr-2005
+FileAssociationDialog.Title:ÎÏÎµÎŸÎµÏÎ³Î±ÏÏÎµÎ¯ÏÎµ ÏÎ¿Ï
+Ï ÏÏ
+ÏÏÎµÏÎ¹ÏÎŒÎ¿ÏÏ Î±ÏÏÎµÎ¯ÏÎœ  # Updated 1-Apr-2005
+FileAssociationDialog.Remove:ÎÎ¹Î±Î³ÏÎ±ÏÎ®  # Updated 1-Apr-2005
+FileAssociationDialog.Remove_Tooltip:ÎÎ¹Î±Î³ÏÎ¬ÏÎµÎ¹ ÏÎ¿Îœ ÏÏÎ­ÏÎ¿ÎœÏÎ± ÏÏ
+ÏÏÎµÏÎ¹ÏÎŒÏ.  # Updated 1-Apr-2005
+FileAssociationDialog.Replace:ÎÎœÏÎ¹ÎºÎ±ÏÎ¬ÏÏÎ±ÏÎ·  # Updated 1-Apr-2005
+FileAssociationDialog.Replace_Tooltip:ÎÎœÏÎ¹ÎºÎ±ÎžÎ¹ÏÏÎ¬ ÏÎ¿Îœ ÏÏÎ­ÏÎ¿ÎœÏÎ± ÎµÏÎ¹Î»Î­Î³ÎŒÎ­ÎœÎ¿ ÏÏ
+ÏÏÎµÏÎ¹ÏÎŒÏ.  # Updated 1-Apr-2005
+#*******************
+#
+#******Filter***************
+Filter.0:HTM & HTML  # Updated 1-Apr-2005
+Filter.1:XML  # Updated 1-Apr-2005
+Filter.2:ÎÏÏÎµÎ¯Î± ÎÎµÎ¹ÎŒÎ­ÎœÎ¿Ï
+  # Updated 1-Apr-2005
+Filter.3:ÎŠÏÏÎ¿Î³ÏÎ±ÏÎ¯ÎµÏ  # Updated 1-Apr-2005
+Filter.All_Files:ÎÎ»Î± ÏÎ± Î±ÏÏÎµÎ¯Î±  # Updated 1-Apr-2005
+Filter.Filter_Tree:ÎÎµÎ¯ÎŸÎµ ÏÎ± Î±ÏÏÎµÎ¯Î±  # Updated 1-Apr-2005
+Filter.Invalid_Pattern:{43}Î Î­ÎºÏÏÎ±ÏÎ· ÏÎ¿Ï
+ ÎµÎ¹ÏÎ¬Î³Î±ÏÎµ Î³Î¹Î± ÏÎ¹Î»ÏÏÎ¬ÏÎ¹ÏÎŒÎ± ÎŽÎµÎœ ÎµÎ¯ÎœÎ±Î¹ Î­Î³ÎºÏ
+ÏÎ·.{35}Î ÏÎ¿ÏÏÎ±ÎžÎµÎ¯ÏÏÎµ ÎŸÎ±ÎœÎ¬ ÏÏÎ·ÏÎ¹ÎŒÎ¿ÏÎ¿Î¹ÏÎœÏÎ±Ï ÎŒÎ¹Î± ÎºÎ±ÎœÎ¿ÎœÎ¹ÎºÎ® Î­ÎºÏÏÎ±ÏÎ· ÎŒÎµ {35}* Î³Î¹Î± ÎµÎ¹ÎŽÎ¹ÎºÏ ÏÎ±ÏÎ±ÎºÏÎ®ÏÎ±.{45}  # Updated 1-Apr-2005
+#***********************
+#
+#***** GAuthenticator *****
+GAuthenticator.Password:ÎÏÎŽÎ¹ÎºÏÏ:  # Updated 1-Apr-2005
+GAuthenticator.Password_Tooltip:ÎÎ¹ÏÎ¬Î³ÎµÏÎµ ÏÎ¿Îœ ÎºÏÎŽÎ¹ÎºÏ ÏÎ±Ï  # Updated 1-Apr-2005
+GAuthenticator.Title:ÎÏÎ±Î¹ÏÎµÎ¯ÏÎ±Î¹ ÎºÏÎŽÎ¹ÎºÏÏ.  # Updated 1-Apr-2005
+GAuthenticator.Username:ÎÎœÎ¿ÎŒÎ± ÏÏÎ®ÏÏÎ·:  # Updated 1-Apr-2005
+GAuthenticator.Username_Tooltip:ÎÎ¹ÏÎ¬Î³ÎµÏÎµ ÏÎ¿ ÏÎœÎ¿ÎŒÎ± ÏÏÎ®ÏÏÎ·  # Updated 1-Apr-2005
+#**************************
+#
+#***** General Messages *****
+# 0 - A String representing the name and method of the class in question.
+General.Apply:ÎÏÎ±ÏÎŒÎ¿Î³Î®  # Updated 1-Apr-2005
+General.Apply_Tooltip:ÎÏÎ¬ÏÎŒÎ¿ÏÎµ ÏÎ¹Ï ÏÏÎ­ÏÎ¿Ï
+ÏÎµÏ ÏÏ
+ÎžÎŒÎ¯ÏÎµÎ¹Ï Î±Î»Î»Î¬ ÎŒÎ·Îœ ÎºÎ»ÎµÎ¯ÏÎµÎ¹Ï ÏÎ¿ ÏÎ±ÏÎ¬ÎžÏ
+ÏÎ¿ ÎŽÎ¹Î±Î»ÏÎ³Î¿Ï
+.  # Updated 1-Apr-2005
+General.Browse:ÏÎ»Î¿Î®Î³Î·ÏÎ·...  # Updated 1-Apr-2005
+General.Cancel:ÎÎºÏÏÏÏÎ·  # Updated 1-Apr-2005
+General.Cancel_Tooltip:ÎÎºÏÏÏÏÎ· Î±Î»Î»Î±Î³ÏÎœ (ÎŽÎµÎœ Î±ÎºÏ
+ÏÏÎœÎµÎ¹ ÏÏÎ¹ Î­ÏÎµÎ¹ ÎµÏÎ±ÏÎŒÎ¿ÏÏÎµÎ¯ ÎŒÎ­ÏÏÎ¹ ÏÏÏÎ±)  # Updated 1-Apr-2005
+General.Close:ÎÎ»ÎµÎ¯ÏÎ¹ÎŒÎ¿  # Updated 1-Apr-2005
+General.Close_Tooltip:ÎÎ»ÎµÎ¯ÏÎµ Î±Ï
+ÏÏ ÏÎ¿ ÏÎ±ÏÎ¬ÎžÏ
+ÏÎ¿ ÎŽÎ¹Î±Î»ÏÎ³Î¿Ï
+  # Updated 1-Apr-2005
+General.Edit:ÎÏÎµÎŸÎµÏÎ³Î±ÏÎ¯Î± ÏÎ¹ÎŒÎ®Ï  # Updated 1-Apr-2005
+General.Error:Î£ÏÎ¬Î»ÎŒÎ±  # Updated 1-Apr-2005
+General.No:ÎÏÎ¹  # Updated 1-Apr-2005
+General.NotSunJava:Java vendor: {0}\nÎ€Î¿ ÎµÏÎ³Î±Î»ÎµÎ¯Î¿ Î­ÏÎµÎ¹ Î±ÎœÎ±ÏÏÏ
+ÏÎžÎµÎ¯ ÎºÎ±Î¹ ÎµÎ»ÎµÎ³ÏÎžÎµÎ¯ ÎŒÎµ Î­ÎºÎŽÎ¿ÏÎ· ÏÎ·Ï Java Î±ÏÏ ÏÎ· Sun Microsystems.  # Updated 1-Apr-2005
+General.OK:ÎÎœÏÎ¬ÎŸÎµÎ¹  # Updated 1-Apr-2005
+General.OK_Tooltip:ÎÎ­ÎŸÎ¿Ï
+ ÏÎ¹Ï ÏÏÎ­ÏÎ¿Ï
+ÏÎµÏ ÏÏ
+ÎžÎŒÎ¯ÏÎµÎ¹Ï ÎºÎ±Î¹ Î²Î³ÎµÏ Î±ÏÏ ÏÎ¿ ÏÎ±ÏÎ¬ÎžÏ
+ÏÎ¿ ÎŽÎ¹Î±Î»ÏÎ³Î¿Ï
+  # Updated 1-Apr-2005
+General.Open:ÎÎœÎ¿Î¹Î³ÎŒÎ±  # Updated 1-Apr-2005
+General.Outstanding_Processes:<html>Î€Î¿ ÏÎµÏÎ¹Î²Î¬Î»Î»Î¿Îœ ÏÎµÎºÎŒÎ·ÏÎ¯ÏÏÎ·Ï ÎŽÎµ ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± ÎºÎ»ÎµÎ¯ÏÎµÎ¹ ÏÎ»Î®ÏÏÏ ÎŒÎ­ÏÏÎ¹ ÎœÎ± ÎºÎ»ÎµÎ¯ÏÎ¿Ï
+Îœ ÏÎ»Î± ÏÎ± ÏÏÎ¿Î³ÏÎ¬ÎŒÎŒÎ±ÏÎ± <br>ÏÎ¿Ï
+ ÎŸÎµÎºÎ¯ÎœÎ·ÏÎ±Îœ Î±ÏÏ Î±Ï
+ÏÏ.</html>  # Updated 1-Apr-2005
+General.Outstanding_Processes_Title:Î ÎµÏÎ¹ÎŒÎ­ÎœÎ¿ÎœÏÎ±Ï Î³Î¹Î± ÎÎŸÎ¿ÎŽÎ¿...  # Updated 1-Apr-2005
+General.Pure_Cancel_Tooltip:ÎÎºÏÏÏÏÎ· Î±Ï
+ÏÎ®Ï ÏÎ·Ï ÎµÎœÎ­ÏÎ³ÎµÎ¹Î±Ï (ÎŽÎµ ÎžÎ± ÏÏÎ±Î³ÎŒÎ±ÏÎ¿ÏÎ¿Î¹Î·ÎžÎ¿ÏÎœ Î±Î»Î»Î±Î³Î­Ï)  # Updated 1-Apr-2005
+General.Review_Output:Î Î±ÏÎ±ÎºÎ±Î»Î¿ÏÎŒÎµ ÎµÎ»Î­ÎŸÏÎµ ÏÎ·Îœ ÏÎ±ÏÎ±ÎºÎ¬ÏÏ Î­ÎŸÎ¿ÎŽÎ¿:  # Updated 1-Apr-2005
+General.Usage:Usage: {0} <params>\nÎÎ»ÎµÏ Î¿Î¹ ÏÎ±ÏÎ¬ÎŒÎµÏÏÎ¿Î¹ ÎµÎ¯ÎœÎ±Î¹ ÏÏÎ¿Î±Î¹ÏÎµÏÎ¹ÎºÎ­Ï Î±Î»Î»Î¬ ÏÎ¿ ÏÎµÏÎ¹Î²Î¬Î»Î»Î¿Îœ ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± Î±ÏÎ¿ÏÏÏÎµÎ¹ Î±Îœ Î¿Î¹ -gsdl ÎºÎ±Î¹ -library ÎŽÎµÎœ Î­ÏÎ¿Ï
+Îœ ÏÎµÎžÎµÎ¯.\n -gsdl <path>  : Force path to gsdl\n -library <path> : Path to cgi-bin\n -mozilla <path> : Enabled mozilla\n -mirror : Enable web-mirroring controls\n -laf [java|windows|motif|mac] : Look and feel\n -debug : Enable debug messages\n -no_load : Don't load previously open collection\n -load <path> : Load the specified collection  # Updated 1-Apr-2005
+General.View:Î ÏÎ¿Î²Î¿Î»Î® Î€Î¹ÎŒÎ®Ï  # Updated 1-Apr-2005
+General.Warning:Î ÏÎ¿ÎµÎ¹ÎŽÎ¿ÏÎ¿Î¯Î·ÏÎ·  # Updated 1-Apr-2005
+General.Yes:ÎÎ±Î¹  # Updated 1-Apr-2005
+#****************************
+#
+#***** GShell *****
+GShell.BadArgument:Î€Î¿ ÏÏÎ¹ÏÎŒÎ± {0} ÎŽÎµÎœ ÎµÎ¯ÎœÎ±Î¹ Î­Î³ÎºÏ
+ÏÎ¿.
+GShell.BadArgumentValue:Î€Î¿ ÏÏÎ¹ÏÎŒÎ± {0} Î­ÏÎµÎ¹ ÎŒÎ¹Î± Î¬ÎºÏ
+ÏÎ· ÏÎ¹ÎŒÎ®.
+GShell.BadPluginOptions:Î€Î¿ ÎºÎ±ÎºÏ ÏÏÎ¹ÏÎŒÎ± ÏÏÎ¿Î­ÎºÏ
+ÏÎµ ÏÏÎ¿ plugin {0}.
+GShell.BadClassifierOptions:Î€Î¿ ÎºÎ±ÎºÏ ÏÏÎ¹ÏÎŒÎ± ÏÏÎ¿Î­ÎºÏ
+ÏÎµ ÏÏÎ¿Îœ ÏÎ±ÎŸÎ¹ÎœÎ¿ÎŒÎ·ÏÎ® {0}.
+GShell.Build.Auxilary:ÎÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¿ÏÎœÏÎ±Î¹ Î²Î¿Î·ÎžÎ·ÏÎ¹ÎºÎ¬ Î±ÏÏÎµÎ¯Î±...  # Updated 1-Apr-2005
+GShell.Build.BuildBegun1:************** Î ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¯Î± ÎŸÎµÎºÎ¯ÎœÎ·ÏÎµ **************  # Updated 1-Apr-2005
+GShell.Build.BuildCancelled:**************   ÎÎºÏ
+ÏÏÎžÎ·ÎºÎµ    **************  # Updated 1-Apr-2005
+GShell.Build.BuildComplete1:************** Î ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¯Î± ÏÎµÎ»ÎµÎ¯ÏÏÎµ **************  # Updated 1-Apr-2005
+GShell.Build.CompressText:Î€Î¿ ÎºÎµÎ¯ÎŒÎµÎœÎ¿ ÏÏ
+ÎŒÏÎ¹Î­Î¶ÎµÏÎ±Î¹...  # Updated 1-Apr-2005
+GShell.Build.Index:ÎÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³ÎµÎ¯ÏÎ±Î¹ Î­ÎœÎ± ÎµÏ
+ÏÎµÏÎ®ÏÎ¹Î¿ Î²Î±ÏÎ¹ÏÎŒÎ­ÎœÎ¿ ÏÏÎ¿ {0-index source and level}...  # Updated 1-Apr-2005
+GShell.Build.InfoDatabase:ÎÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¯Î± ÎÎ¬ÏÎ·Ï ÎÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ...  # Updated 1-Apr-2005
+GShell.Build.Phind:ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³ÎµÎ¯ÏÎ±Î¹ Î­ÎœÎ±Ï Phind ÏÎ±ÎŸÎ¹ÎœÎ¿ÎŒÎ·ÏÎ®Ï.......  # Updated 1-Apr-2005
+GShell.Command:ÎÎœÏÎ¿Î»Î®  # Updated 1-Apr-2005
+GShell.Failure:Î ÎµÎœÏÎ¿Î»Î® Î±ÏÎ­ÏÏ
+ÏÎµ.  # Updated 1-Apr-2005
+GShell.Import.FileNotProcessed:Î€Î¿ Î±ÏÏÎµÎ¯Î¿ {0-target file path} Î±ÎœÎ±Î³ÎœÏÏÎ¯ÏÎžÎ·ÎºÎµ Î±Î»Î»Î¬ ÎŽÎµ ÎŒÏÏÏÎµÏÎµ ÎœÎ± ÎµÏÎµÎŸÎµÏÎ³Î±ÏÏÎµÎ¯ Î±ÏÏ ÎºÎ±ÎœÎ­ÎœÎ± plugin.  # Updated 1-Apr-2005
+GShell.Import.FileNotRecognised:Î€Î¿ Î±ÏÏÎµÎ¯Î¿ {0-target file path} ÎŽÎµÎœ Î±ÎœÎ±Î³ÎœÏÏÎ¯ÏÎžÎ·ÎºÎµ Î±ÏÏ ÎºÎ±ÎœÎ­ÎœÎ± plugin.  # Updated 1-Apr-2005
+GShell.Import.FileProcessing:ÏÎ¿ Î±ÏÏÎµÎ¯Î¿ {0-target file path} ÎµÏÎµÎŸÎµÏÎ³Î¬Î¶ÎµÏÎ±Î¹ Î±ÏÏ {1-plugin name}.  # Updated 1-Apr-2005
+GShell.Import.FileProcessingError:Î€Î¿ Î±ÏÏÎµÎ¯Î¿ {0-target file path} Î±ÎœÏÎ¹ÎŒÎµÏÏÏÎ¹ÏÎµ Î­ÎœÎ± ÏÏÏÎ²Î»Î·ÎŒÎ± ÎºÎ±ÏÎ¬ ÏÎ·Îœ ÎµÏÎµÎŸÎµÏÎ³Î±ÏÎ¯Î± ÏÎ¿Ï
+.  # Updated 1-Apr-2005
+GShell.Import.ImportBegun1:************** Î ÎÎ¹ÏÎ±Î³ÏÎ³Î® ÎÎµÎºÎ¯ÎœÎ·ÏÎµ **************  # Updated 1-Apr-2005
+GShell.Import.ImportComplete1:************** Î ÎÎ¹ÏÎ±Î³ÏÎ³Î® Î£ÏÎ±ÎŒÎ¬ÏÎ·ÏÎµ **************  # Updated 1-Apr-2005
+GShell.Import.ImportComplete2:{0-number documents considered} Î­Î³Î³ÏÎ±ÏÎ± ÏÎ­ÎžÎ·ÎºÎ±Îœ ÏÎµ ÎµÏÎµÎŸÎµÏÎ³Î±ÏÎ¯Î±:  # Updated 1-Apr-2005
+GShell.Import.ImportComplete2.1:1 Î­Î³Î³ÏÎ±ÏÎ¿ ÎµÏÎµÎŸÎµÏÎ³Î¬ÏÏÎ·ÎºÎµ:  # Updated 1-Apr-2005
+GShell.Import.ImportComplete.Processed:{0-number processed} Î­Î³Î³ÏÎ±ÏÎ± ÎµÏÎµÎŸÎµÏÎ³Î¬ÏÏÎ·ÎºÎ±Îœ ÎºÎ±Î¹ ÏÎµÏÎ¹ÎµÎ»Î®ÏÎžÎ·ÏÎ±Îœ ÏÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®.  # Updated 1-Apr-2005
+GShell.Import.ImportComplete.Processed.1:1 Î­Î³Î³ÏÎ±ÏÎ¿ ÎµÏÎµÎŸÎµÏÎ³Î¬ÏÏÎ·ÎºÎµ ÎºÎ±Î¹ ÏÎµÏÎ¹ÎµÎ»Î®ÏÎžÎ· ÏÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®.  # Updated 1-Apr-2005
+GShell.Import.ImportComplete.Blocked:{0-number blocked} ÎŽÎµÎœ ÎµÎ¹ÏÎ®ÏÎžÎ·ÏÎ±Îœ Î±ÏÏ plugins ÏÏÎ· ÏÏ
+Î»Î»Î¿Î³Î® (ÏÏÏÏ ÎµÎ¹ÎºÏÎœÎµÏ ÏÎµ Î¹ÏÏÎ¿ÏÎµÎ»Î¯ÎŽÎµÏ).  # Updated 1-Apr-2005
+GShell.Import.ImportComplete.Blocked.1:1 ÎŽÎµÎœ ÎµÎ¹ÏÎ®ÏÎžÎµÎ¹ Î±ÏÏ plugins ÏÏÎ· ÏÏ
+Î»Î»Î¿Î³Î® (ÏÏÏÏ ÎµÎ¹ÎºÏÎœÎµÏ ÏÎµ Î¹ÏÏÎ¿ÏÎµÎ»Î¯ÎŽÎµÏ).  # Updated 1-Apr-2005
+GShell.Import.ImportComplete.Ignored:{0-number ignored} ÎŽÎµÎœ Î±ÎœÎ±Î³ÎœÏÏÎ¯ÏÏÎ·ÎºÎ±Îœ.  # Updated 1-Apr-2005
+GShell.Import.ImportComplete.Ignored.1:1 ÎŽÎµÎœ Î±ÎœÎ±Î³ÎœÏÏÎ¯ÏÏÎ·ÎºÎµ.  # Updated 1-Apr-2005
+GShell.Import.ImportComplete.Failed:{0-number failed} Î±ÏÎ¿ÏÏÎ¯ÏÎžÎ·ÎºÎ±Îœ.  # Updated 1-Apr-2005
+GShell.Import.ImportComplete.Failed.1:1 Î±ÏÎ¿ÏÏÎ¯ÏÎžÎ·ÎºÎµ.  # Updated 1-Apr-2005
+GShell.Import.ImportComplete3:\n  # Updated 1-Apr-2005
+GShell.Parsing_Metadata_Complete:Î ÎµÎŸÎ±Î³ÏÎ³Î® ÏÏÎœ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ Î¿Î»Î¿ÎºÎ»Î·ÏÏÎžÎ·ÎºÎµ.  # Updated 1-Apr-2005
+GShell.Parsing_Metadata_Start:ÎÎŸÎ¬Î³ÏÎœÏÎ±Î¹ ÎœÎ­Î± ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ± Î±ÏÏ Î±ÏÏÎµÎ¯Î±.  # Updated 1-Apr-2005
+GShell.Success:Î ÎµÎœÏÎ¿Î»Î® Î¿Î»Î¿ÎºÎ»Î·ÏÏÎžÎ·ÎºÎµ.  # Updated 1-Apr-2005
+#*********************
+#
+#***** GUI *****
+# Currently Enabled and Disabled display the same text but in different
+# colours. If necessary this can be changed.
+GUI.Create:ÎÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¯Î±  # Updated 1-Apr-2005
+GUI.Create_Tooltip:ÎÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¯Î± Î£Ï
+Î»Î»Î¿Î³Î®Ï  # Updated 1-Apr-2005
+GUI.Design:Î£ÏÎµÎŽÎ¹Î±ÏÎŒÏÏ  # Updated 1-Apr-2005
+GUI.Design_Tooltip:Î£ÏÎµÎŽÎ¹Î±ÏÎŒÏÏ ÏÎ·Ï Î»ÎµÎ¹ÏÎ¿Ï
+ÏÎ³Î¹ÎºÏÏÎ·ÏÎ± ÎºÎ±Î¹ ÏÎ·Ï ÎµÎŒÏÎ¬ÎœÎ¹ÏÎ·Ï ÏÎ·Ï ÏÏ
+Î»Î¿Î³Î®Ï  # Updated 1-Apr-2005
+GUI.Download:ÎÎ±ÏÎ­Î²Î±ÏÎŒÎ±/Mirroring  # Updated 1-Apr-2005
+GUI.Download_Tooltip:ÎÎ±ÏÎ­Î²Î±ÏÎŒÎ± ÏÏÏÏÎœ Î±ÏÏ ÏÎ¿ ÎÎ¹Î±ÎŽÎ¯ÎºÏÏ
+Î¿ Î³Î¹Î± ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+GUI.Enrich:ÎÎŒÏÎ»Î¿Ï
+ÏÎ¹ÏÎŒÏÏ  # Updated 1-Apr-2005
+GUI.Enrich_Tooltip:ÎÎ±ÏÎ±ÏÏÏÎ·ÏÎ· ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ Î³Î¹Î± ÏÎ± Î±ÏÏÎµÎ¯Î± ÏÎ·Ï ÏÏ
+Î»Î»Î¿Î³Î®Ï  # Updated 1-Apr-2005
+GUI.Gather:Î£Ï
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+GUI.Gather_Tooltip:ÎÏÎ¹Î»Î¿Î³Î® Î±ÏÏÎµÎ¯ÏÎœ ÏÎ¿Ï
+ ÎžÎ± ÏÎµÏÎ¹Î­ÏÎµÎ¹ Î· ÏÏ
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+#***************
+#
+#***** HELP *****
+Help.Contents:Î ÎµÏÎ¹ÎµÏÏÎŒÎµÎœÎ±  # Updated 1-Apr-2005
+Help.Title:ÎÎ¿Î·ÎžÎ·ÏÎ¹ÎºÎ­Ï Î£ÎµÎ»Î¯ÎŽÎµÏ Î§ÏÎ®ÏÏÎ·  # Updated 1-Apr-2005
+#****************************
+#
+#***** Invalid Metadata ******
+InvalidMetadata.Message:ÎÏ
+ÏÏÏ Î¿ ÏÏÎ¿Ï ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ ÎµÎ¯ÎœÎ±Î¹ ÏÎµÏÎ¹Î¿ÏÎ¹ÏÎŒÎ­ÎœÎ¿Ï ÏÎµ Î­ÎœÎ± ÏÏ
+Î³ÎºÎµÎºÏÎ¹ÎŒÎ­ÎœÎ¿ ÏÏÎœÎ¿Î»Î¿ ÏÎ¹ÎŒÏÎœ. ÎÎ¹Î±Î»Î­ÎŸÏÎµ ÎŒÎ¹Î± Î±ÏÏ Î±Ï
+ÏÎ­Ï.
+InvalidMetadata.Title:ÎÎºÏ
+ÏÎ¿ ÎÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ¿.
+#***************************
+#
+#***** LockFileDialog *****
+LockFileDialog.Cancel_Tooltip:ÎÎ± ÎŒÎ·Îœ ÎºÎ»Î±ÏÎµÎ¯ ÏÎ¿ ÎºÎ»ÎµÎ¯ÎŽÏÎŒÎ± (Î· ÏÏ
+Î»Î»Î¿Î³Î® ÎŽÎµ ÎžÎ± Î±ÎœÎ¿Î¯ÎŸÎµÎ¹)  # Updated 1-Apr-2005
+LockFileDialog.Date:ÎÎŒÎµÏÎ¿ÎŒÎ·ÎœÎ¯Î±  # Updated 1-Apr-2005
+LockFileDialog.Error:#Î£ÏÎ¬Î»ÎŒÎ±  # Updated 1-Apr-2005
+LockFileDialog.Lockfile_Message_One:Î ÏÎ±ÏÎ¿Ï
+ÏÎ¯Î± ÎºÎ»ÎµÎ¹ÎŽÏÎŒÎ±ÏÎ¿Ï Ï
+ÏÎ¿ÎŽÎµÎ¹ÎºÎœÏÎµÎ¹ ÏÏÎ¹ Î· ÏÏ
+Î»Î»Î¿Î³Î® ÎµÎ¯ÎœÎ±Î¹ Î®ÎŽÎ· Î±ÎœÎ¿Î¹Î³ÎŒÎ­ÎœÎ· (Î Î¹ÎžÎ±ÎœÏÏ ÏÎ¿ ÎÏÎ³Î±Î»ÎµÎ¯Î¿ ÎœÎ± ÎŒÎ·Îœ Î­ÎºÎ»ÎµÎ¹ÏÎµ ÏÏÏÏÎ¬)).  # Updated 1-Apr-2005
+LockFileDialog.Lockfile_Message_Two:ÎÏÎ¹ÎžÏ
+ÎŒÎµÎ¯ÏÎµ ÎœÎ± ÎºÎ»Î­ÏÎµÏÎµ ÏÎ¿Îœ Î­Î»ÎµÎ³ÏÎ¿ Î±Ï
+ÏÎ¿Ï ÏÎ¿Ï
+ ÎºÎ»ÎµÎ¹ÎŽÏÎŒÎ±ÏÎ¿Ï? ÎÏÎ¹Î»Î­ÎŸÏÎµ Î¿Îº  # Updated 1-Apr-2005
+LockFileDialog.Machine:Î Î¿Ï
+  # Updated 1-Apr-2005
+LockFileDialog.Name:ÎÎœÎ¿ÎŒÎ±  # Updated 1-Apr-2005
+LockFileDialog.OK_Tooltip:ÎÎ»Î­ÏÎµ ÏÎ¿Îœ Î­Î»ÎµÎ³ÏÎ¿ ÏÎ¿Ï
+ ÎºÎ»ÎµÎ¹ÎŽÏÎŒÎ±ÏÎ¿Ï  # Updated 1-Apr-2005
+LockFileDialog.Title:ÎÎœÎ¯ÏÎœÎµÏ
+ÏÎ·ÎºÎµ Î±ÏÏÎµÎ¯Î¿ ÎºÎ»ÎµÎ¹ÎŽÏÎŒÎ±ÏÎ¿Ï  # Updated 1-Apr-2005
+LockFileDialog.User:Î Î¿Î¹Î¿Ï  # Updated 1-Apr-2005
+#********************
+#
+#*****MappingPrompt **********
+MappingPrompt.File:ÎŠÎ¬ÎºÎµÎ»Î¿Ï  # Updated 1-Apr-2005
+MappingPrompt.Map:ÎÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¯Î± ÏÏ
+ÎœÏÏÎŒÎµÏ
+ÏÎ·Ï  # Updated 1-Apr-2005
+MappingPrompt.Name:ÎÎœÎ¿ÎŒÎ±  # Updated 1-Apr-2005
+MappingPrompt.Title:ÎžÎ­ÏÎµ ÏÏ
+ÎœÏÏÎŒÎµÏ
+ÏÎ· ÏÎ±ÎºÎ­Î»Î¿Ï
+  # Updated 1-Apr-2005
+MappingPrompt.Unmap:ÎÎ¹Î±Î³ÏÎ±ÏÎ® ÏÏ
+ÎœÏÏÎŒÎµÏ
+ÏÎ·Ï  # Updated 1-Apr-2005
+#*******************
+#
+#***** Menu Options *****
+Menu.Collapse:ÎÎ»ÎµÎ¯ÏÎµ ÏÎ¿ ÏÎ¬ÎºÎµÎ»Î¿  # Updated 1-Apr-2005
+Menu.Edit:ÎÏÎµÎŸÎµÏÎ³Î±ÏÎ¯Î±  # Updated 1-Apr-2005
+Menu.Edit_Copy:ÎÎœÏÎ¹Î³ÏÎ±ÏÎ® (ctrl-c)  # Updated 1-Apr-2005
+Menu.Edit_Cut:ÎÏÎ¿ÎºÎ¿ÏÎ® (ctrl-x)  # Updated 1-Apr-2005
+Menu.Edit_Paste:ÎÏÎ¹ÎºÏÎ»Î·ÏÎ· (ctrl-v)  # Updated 1-Apr-2005
+Menu.Expand:ÎÎœÎ¿Î¹Î³ÎŒÎ± ÎŠÎ±ÎºÎ­Î»Î¿Ï
+  # Updated 1-Apr-2005
+Menu.Explode_Metadata_Database:ÎÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ± ÎÎ¬ÏÎ·Ï  # Updated 1-Apr-2005
+Menu.File:ÎÏÏÎµÎ¯Î¿  # Updated 1-Apr-2005
+Menu.File_Associations:Î£Ï
+ÏÏÎµÏÎ¹ÏÎŒÎ¿Î¯ ÎÏÏÎµÎ¯ÏÎœ...  # Updated 1-Apr-2005
+Menu.File_CDimage:ÎÏÎ¬ÏÎµ ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î® ÏÎµ CD/DVD ...  # Updated 1-Apr-2005
+Menu.File_Close:ÎÎ»ÎµÎ¯ÏÎ¹ÎŒÎ¿  # Updated 1-Apr-2005
+Menu.File_Delete:ÎÎ¹Î±Î³ÏÎ±ÏÎ®...  # Updated 1-Apr-2005
+Menu.File_Exit:ÎÎŸÎ¿ÎŽÎ¿Ï  # Updated 1-Apr-2005
+Menu.File_ExportAs:ÎÎŸÎ±Î³ÏÎ³Î®...  # Updated 1-Apr-2005
+Menu.File_New:ÎÎ­Î¿...  # Updated 1-Apr-2005
+Menu.File_Open:ÎÎœÎ¿Î¹Î³ÎŒÎ±...  # Updated 1-Apr-2005
+Menu.File_Options:ÎÏÎ¹Î»Î¿Î³Î­Ï...  # Updated 1-Apr-2005
+Menu.File_Save:ÎÏÎ¿ÎžÎ®ÎºÎµÏ
+ÏÎ·  # Updated 1-Apr-2005
+Menu.Help:ÎÎ¿Î®ÎžÎµÎ¹Î±  # Updated 1-Apr-2005
+Menu.Help_About:Î£ÏÎµÏÎ¹ÎºÎ¬...  # Updated 1-Apr-2005
+Menu.Metadata_View:ÎÎ±ÏÎ±ÏÏÏÎ·ÎŒÎ­ÎœÎ± ÎÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ± Î³Î¹Î± ÏÎ¿ {0}  # Updated 1-Apr-2005
+Menu.Open_Externally:ÎÎœÎ¿Î¹Î³ÎŒÎ± ÎŒÎµ ÎµÎŸÏÏÎµÏÎ¹ÎºÏ ÏÏÏÎ³ÏÎ±ÎŒÎŒÎ±  # Updated 1-Apr-2005
+#********************
+#
+#***** MetaAudit *****
+MetaAudit.Close:ÎÎ»ÎµÎ¯ÏÎ¹ÎŒÎ¿  # Updated 1-Apr-2005
+MetaAudit.Close_Tooltip:ÎÎ»ÎµÎ¯ÎœÎµÎ¹ Î±Ï
+ÏÏ ÏÎ¿ ÏÎ±ÏÎ¬ÎžÏ
+ÏÎ¿ ÎŽÎ¹Î±Î»ÏÎ³Î¿Ï
+  # Updated 1-Apr-2005
+MetaAudit.Title:ÎÎ»Î± ÏÎ± ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ±  # Updated 1-Apr-2005
+#*********************
+#
+#***** Metadata *****
+Metadata.Element:ÎÏÎ¿Ï  # Updated 1-Apr-2005
+Metadata.Value:Î€Î¹ÎŒÎ®  # Updated 1-Apr-2005
+MetadataSet.Files:ÎÏÏÎµÎ¯Î± ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ  # Updated 1-Apr-2005
+#*********************************************
+#
+#******** MetadataImportMappingPrompt *********
+MIMP.Add:Î ÏÎ¿ÏÎžÎ®ÎºÎ·  # Updated 1-Apr-2005
+MIMP.Add_Tooltip:Î ÏÎ¿ÏÎžÎ®ÎºÎ· ÏÎ¿Ï
+ ÏÏÎ¿Ï
+ ÏÏÎ¿ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿ ÏÏÎœÎ¿Î»Î¿  # Updated 1-Apr-2005
+MIMP.Ignore:Î Î±ÏÎ¬Î²Î»ÎµÏÎµ  # Updated 1-Apr-2005
+MIMP.Ignore_Tooltip:ÎÎ³ÎœÏÎ·ÏÎµ Î±Ï
+ÏÏ ÏÎ¿ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ¿  # Updated 1-Apr-2005
+MIMP.Instructions:Î ÏÏÎ¿Ï {0} ÎŽÎµ ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± ÎµÎ¹ÏÎ±ÏÎžÎµÎ¯ ÏÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®. ÎÏÎ¹Î»Î­ÎŸÏÎµ Î­ÎœÎ± ÏÏÎœÎ¿Î»Î¿ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ ÎºÎ±Î¹ ÎµÎ¯ÏÎµ:\n(1) ÏÎ±ÏÎ®ÏÏÎµ 'Î ÏÎ¿ÏÎžÎ®ÎºÎ·' Î³Î¹Î± ÎœÎ± ÏÏÎ¿ÏÎžÎ­ÏÎµÏÎµ ÏÎ¿ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ¿ ÏÎµ Î±Ï
+ÏÏ ÏÎ¿ ÏÏÎœÎ¿Î»Î¿ (ÎŒÏÎœÎ¿ Î±Îœ ÎŽÎµÎœ Ï
+ÏÎ¬ÏÏÎµÎ¹ Î®ÎŽÎ· {0} ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ¿ ÏÏÎ¿ ÏÏÎœÎ¿Î»Î¿), Î®\n(2) ÎŽÎ¹Î±Î»Î­ÏÏÎµ Î­ÎœÎ±Îœ ÏÏÎ¿ ÎºÎ±Î¹ ÏÎ±ÏÎ®ÏÏÎµ 'Î£Ï
+Î³ÏÏÎœÎµÏ
+ÏÎ·' Î³Î¹Î± ÎœÎ± ÎµÎ¹ÏÎ¬Î³ÎµÏÎµ ÏÎ¿ {0} ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ¿ ÏÎµ Î±Ï
+ÏÏ ÏÎ¿Îœ ÏÏÎ¿, Î®\n(3) Î±Î³ÎœÎ¿ÎµÎ¯ÏÏÎµ Î±Ï
+ÏÏ ÏÎ¿Îœ ÏÏÎ¿.  # Updated 1-Apr-2005
+MIMP.Merge:Î£Ï
+Î³ÏÏÎœÎµÏ
+ÏÎ·  # Updated 1-Apr-2005
+MIMP.Merge_Tooltip:ÎÎœÏÎ¹ÏÏÎ¿Î¹ÏÎµÎ¯ ÏÎ¿Îœ ÏÏÎ¿ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ ÏÏÎ¿Îœ ÎºÎ±ÎžÎ¿ÏÎ¹ÏÎŒÎ­ÎœÎ¿ ÏÎ¿Ï
+ ÏÏ
+ÎœÏÎ»Î¿Ï
+.  # Updated 1-Apr-2005
+MIMP.Source_Element:ÎÏÏÎ¹ÎºÏÏ ÎÏÎ¿Ï ÎÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ¿Ï
+:  # Updated 1-Apr-2005
+MIMP.Target_Element:ÎÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ¿ ÏÏÏÏÎ¿Ï:  # Updated 1-Apr-2005
+MIMP.Target_Set:Î£ÏÎœÎ¿Î»Î¿ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ ÏÏÏÏÎ¿Ï:  # Updated 1-Apr-2005
+MIMP.Title:ÎÏÎ±Î¹ÏÎµÎ¯ÏÎ±Î¹ ÎµÎœÎ­ÏÎ³ÎµÎ¹Î± ÏÏ
+Î³ÏÏÎœÎµÏ
+ÏÎ·Ï.  # Updated 1-Apr-2005
+#*****************************
+#
+#***** Mirroring *****
+Mirroring.ClearCache:ÎÎ±ÎžÎ±ÏÎ¹ÏÎŒÏÏ ÎŒÎœÎ®ÎŒÎ·Ï  # Updated 1-Apr-2005
+Mirroring.ClearCache_Tooltip:ÎÎ¹Î±Î³ÏÎ±ÏÎ® ÏÎ»ÏÎœ ÏÏÎœ ÎºÎ±ÏÎµÎ²Î±ÏÎŒÎ­ÎœÏÎœ Î±ÏÏÎµÎ¯ÏÎœ  # Updated 1-Apr-2005
+Mirroring.Download:ÎÎ±ÏÎ­Î²Î±ÏÎŒÎ±  # Updated 1-Apr-2005
+Mirroring.Download_Tooltip:ÎÎµÎºÎ¹ÎœÎ¬ ÎŒÎ¹Î± ÎœÎ­Î± ÎŽÎ¹ÎµÏÎ³Î±ÏÎ¯Î± ÎºÎ±ÏÎµÎ²Î¬ÏÎŒÎ±ÏÎ¿Ï  # Updated 1-Apr-2005
+Mirroring.Download_Controls:Î¡Ï
+ÎžÎŒÎ¯ÏÎµÎ¹Ï ÎÎ±ÏÎµÎ²Î¬ÏÎŒÎ±ÏÎ¿Ï  # Updated 1-Apr-2005
+Mirroring.Download_Depth:ÎÎ¬ÎžÎ¿Ï ÎÎ±ÏÎµÎ²Î¬ÏÎŒÎ±ÏÎ¿Ï:  # Updated 1-Apr-2005
+Mirroring.Download_Depth.Zero:ÎÎ·ÎŽÎ­Îœ  # Updated 1-Apr-2005
+Mirroring.Download_Depth.Unlimited:ÎÏÎµÏÎ¹ÏÏÎ¹ÏÏÎ¿  # Updated 1-Apr-2005
+Mirroring.Download_Depth_Tooltip:ÎÎ±ÎžÎ¿ÏÎ¯Î¶ÎµÎ¹ ÏÎµ ÏÏÏÎ¿ Î²Î¬ÎžÎ¿Ï Ï
+ÏÎµÏÏÏ
+ÎœÎŽÎ­ÏÎŒÏÎœ ÎžÎ± ÏÏÎ¬ÏÎ¿Ï
+ÎŒÎµ  # Updated 1-Apr-2005
+# -- Missing translation: Mirroring.Download_OnlyHTML
+Mirroring.DownloadJob.Close:ÎÎ»ÎµÎ¯ÏÎ¹ÎŒÎ¿  # Updated 1-Apr-2005
+Mirroring.DownloadJob.Close_Tooltip:ÎÏÎ±Î¯ÏÎµÏÎµ Î±Ï
+ÏÎ® ÏÎ· ÎŽÎ¹ÎµÏÎ³ÏÎ¯Î± Î±ÏÏ ÏÎ· Î»Î¯ÏÏÎ± ÏÏÎ±ÎŒÎ±ÏÏÎœÏÎ±Ï ÏÎ·Îœ Î±Îœ Î®ÎŽÎ· ÏÏÎ­ÏÎµÎ¹  # Updated 1-Apr-2005
+Mirroring.DownloadJob.Downloading:ÎºÎ±ÏÎ­Î²Î¬Î¶Î¿ÎœÏÎ±Ï ÏÎ¿ {0}  # Updated 1-Apr-2005
+Mirroring.DownloadJob.Download_Complete:Î€Î¿ ÎÎ±ÏÎ­Î²Î±ÏÎŒÎ± Î¿Î»Î¿ÎºÎ»Î·ÏÏÎžÎ·ÎºÎµ  # Updated 1-Apr-2005
+Mirroring.DownloadJob.Download_Stopped:Î€Î¿ ÎºÎ±ÏÎ­Î²Î±ÏÎŒÎ± ÏÏÎ±ÎŒÎ¬ÏÎ·ÏÎµ  # Updated 1-Apr-2005
+Mirroring.DownloadJob.Download_Progress:Î€Î¿ ÎºÎ±ÏÎ­Î²Î±ÏÎŒÎ± Î²ÏÎ¯ÏÎºÎµÏÎ±Î¹ ÏÎµ ÎµÎŸÎ­Î»Î¹ÎŸÎ·  # Updated 1-Apr-2005
+Mirroring.DownloadJob.Log:ÎŽÎµÎ¯ÏÎµ ÏÎ¿ Log  # Updated 1-Apr-2005
+Mirroring.DownloadJob.Log_Tooltip:ÎÎµÎ¯ÏÎµ Î»ÎµÏÏÎ¿ÎŒÎ­ÏÎµÎ¹ÎµÏ ÏÏÎµÏÎ¹ÎºÎ¬ ÎŒÎµ Î±Ï
+ÏÏ ÏÎ¿ ÎºÎ±ÏÎ­Î²Î±ÏÎŒÎ±  # Updated 1-Apr-2005
+Mirroring.DownloadJob.Pause:Î Î±ÏÏÎ·  # Updated 1-Apr-2005
+Mirroring.DownloadJob.Pause_Tooltip:Î Î±ÏÏÎµ Î±Ï
+ÏÏ ÏÎ¿ ÎºÎ±ÏÎ­Î²Î±ÏÎŒÎ±  # Updated 1-Apr-2005
+Mirroring.DownloadJob.Resume:ÎÏÎ±ÎœÎ­ÎœÎ±ÏÎŸÎ·  # Updated 1-Apr-2005
+Mirroring.DownloadJob.Resume_Tooltip:ÎÏÎ±ÎœÎ­ÏÎŸÎ· ÏÎ¿Ï
+ ÎºÎ±ÏÎµÎ²Î¬ÏÎŒÎ±ÏÎ¿Ï  # Updated 1-Apr-2005
+Mirroring.DownloadJob.Status:ÎÎ±ÏÎ­Î²Î·ÎºÎ±Îœ {0} Î±ÏÏ {1} Î±ÏÏÎµÎ¯Î± ({2} ÏÏÎ¿ÎµÎ¹ÎŽÎ¿ÏÎ¿Î¹Î®ÏÎµÎ¹Ï, {3} Î»Î¬ÎžÎ·)  # Updated 1-Apr-2005
+Mirroring.DownloadJob.Waiting:Î ÎµÏÎ¹ÎŒÎ­ÎœÎµÏÎµ Î³Î¹Î± ÎœÎ± ÎŸÎµÎºÎ¹ÎœÎ®ÏÎµÎ¹  # Updated 1-Apr-2005
+Mirroring.DownloadJob.Waiting_User:Î ÎµÏÎ¹ÎŒÎ­ÎœÎ¿ÎœÏÎ±Ï ÎµÎœÎ­ÏÎ³ÎµÎ¹Î± ÏÏÎ®ÏÏÎ·  # Updated 1-Apr-2005
+Mirroring.Higher_Directories:ÎÎ±ÏÎ­Î²Î±ÏÎŒÎ± Î±ÏÏÎµÎ¯ÏÎœ ÎŒÏÎœÎ¿ ÎºÎ¬ÏÏ Î±ÏÏ Î±Ï
+ÏÏ ÏÎ¿ URL.  # Updated 1-Apr-2005
+Mirroring.Invalid_URL:Î€Î¿ URL ÎŽÎµÎœ ÎµÎ¯ÎœÎ±Î¹ Î­Î³ÎºÏ
+ÏÎ¿. Î Î±ÏÎ±ÎºÎ±Î»Ï ÎŽÎ¹Î¿ÏÎžÏÏÏÎµ.  # Updated 1-Apr-2005
+Mirroring.Invalid_URL_Title:ÎÎ· Î­Î³ÎºÏ
+ÏÎ¿ URL  # Updated 1-Apr-2005
+Mirroring.Preferences:ÎÏÎ¹Î»Î¿Î³Î­Ï...  # Updated 1-Apr-2005
+Mirroring.Preferences_Tooltip:ÎÎœÎµÏÎ³Î¿ÏÎ¿Î¹ÎµÎ¯ÏÏÎµ ÏÎ¿Îœ proxy ÎºÎ±Î¹/Î® ÎµÏÎµÎŸÎµÏÎ³Î±ÏÏÎµÎ¯ÏÎµ ÏÎ¹Ï ÏÏ
+ÎžÎŒÎ¯ÏÎµÎ¹Ï ÏÎ¿Ï
+  # Updated 1-Apr-2005
+Mirroring.Same_Host:ÎºÎ±ÏÎ­Î²Î±ÏÎŒÎ± Î±ÏÏÎµÎ¯ÏÎœ ÎŒÏÎœÎ¿ Î±ÏÏ ÏÎ¿ Î¯ÎŽÎ¹Î¿ site  # Updated 1-Apr-2005
+Mirroring.Source_URL:URL ÏÎ·Î³Î®Ï:  # Updated 1-Apr-2005
+Mirroring.Source_URL_Tooltip:URL Î³Î¹Î± ÎºÎ±ÏÎ­Î²Î±ÏÎŒÎ±  # Updated 1-Apr-2005
+#*********************
+#
+#***** Missing EXEC *****
+MissingEXEC.Message:Î ÏÎ¿ÎµÎ¹ÎŽÎ¿ÏÎ¿Î¯Î·ÏÎ·! ÎÎµ ÎžÎ± ÎŒÏÎ¿ÏÎµÎ¯ÏÎµ ÎœÎ± ÎŽÎµÎ¯ÏÎµ ÏÎ¹Ï ÏÏ
+Î»Î»Î¿Î³Î­Ï ÏÎ±Ï ÏÏÎ¿ ÏÎµÏÎ¹Î²Î¬Î»Î»Î¿Îœ Î±Ï
+ÏÏ Î±Îœ ÎŽÎµÎœ ÎºÎ±ÎžÎ¿ÏÎ¯ÏÎµÏÎµ ÏÎ¿ ÎŒÎ¿ÎœÎ¿ÏÎ¬ÏÎ¹ Î³Î¹Î± ÏÎ¿Îœ ÎµÎŸÏ
+ÏÎ·ÏÎµÏÎ·ÏÎ® ÏÏÎœ ÏÏ
+Î»Î»Î¿Î³ÏÎœ ÏÎ¿Ï
+ Greenstone. ÎÏÎ¿ÏÎµÎ¯ÏÎµ ÎœÎ± ÏÎ¿ ÎºÎ¬ÎœÎµÏÎµ ÎºÎ±Î¹ Î±ÏÎ³ÏÏÎµÏÎ± Î±ÏÏ ÏÎ·Îœ ÎºÎ±ÏÏÎ­Î»Î± ÏÏÎœ ÎµÏÎ¹Î»Î¿Î³ÏÎœ. ÎÎœÎ± Î­Î³ÎºÏ
+ÏÎ¿ URL ÏÏÎ­ÏÎµÎ¹ ÎœÎ± ÎŸÎµÎ¹ÎœÎ¬ÎµÎ¹ ÎŒÎµ "http://", ÎºÎ±Î¹ ÎœÎ± ÏÎµÎ»ÎµÎ¹ÏÎœÎµÎ¹ ÎŒÎµ "gsdl" Î³Î¹Î± ÏÎ¿ Greenstone local library server Î® "library" Î³Î¹Î± Î¬Î»Î»Î¿Ï
+Ï web servers).  # Updated 1-Apr-2005
+MissingEXEC.Title:ÎÎ»ÎµÎ¹ÏÎ®Ï ÎÎ¹ÎµÏÎžÏ
+ÎœÏÎ· ÎÎ¹Î²Î»Î¹Î¿ÎžÎ®ÎºÎ·Ï  # Updated 1-Apr-2005
+#***** Missing EXEC_GS3 *****
+MissingEXEC_GS3.Message:Î ÏÎ¿ÎµÎ¹ÎŽÎ¿ÏÎ¿Î¯Î·ÏÎ·! ÎÎµ ÎžÎ± ÎµÎ¯ÏÏÎµ Î¹ÎºÎ±ÎœÎ¿Î¯ ÎœÎ± ÎŽÎµÎ¯ÏÎµ ÏÎ¹Ï ÎœÎ­ÎµÏ ÏÎ±Ï ÏÏ
+Î»Î»Î¿Î³Î­Ï ÎµÎ¬Îœ ÎŽÎµÎœ ÎºÎ±ÎžÎ¿ÏÎ¯ÏÎµÏÎµ ÏÎ¿ ÎŒÎ¿ÎœÎ¿ÏÎ¬ÏÎ¹ Î³Î¹Î± ÏÎ¿Îœ ÎµÎŸÏ
+ÏÎ·ÏÎµÏÎ·ÏÎ® ÎÏÎ¿ÏÎµÎ¯ÏÎµ ÎœÎ± ÏÎ¿ ÎµÎ¹ÏÎ¬Î³ÎµÏÎµ ÏÏÏÎ± Î® Î±ÏÎ³ÏÏÎµÏÎ± Î±ÏÏ ÏÎ·Îœ ÎºÎ±ÏÏÎ­Î»Î± ÏÏÎœ ÎµÏÎ¹Î»Î¿Î³ÏÎœ. Î€Î¿ ÎŒÎ¿ÎœÎ¿ÏÎ¬ÏÎ¹ ÎžÎ± ÎŒÎ¿Î¹Î¬Î¶ÎµÎ¹ ÎŒÎµ (http://localhost:8080/gsdl3).  # Updated 1-Apr-2005
+MissingEXEC_GS3.Title:ÎÎ»ÎµÎ¹ÏÎ®Ï ÎÎ¹ÎµÏÎžÏ
+ÎœÏÎ· ÎÎ¹Î²Î»Î¹Î¿ÎžÎ®ÎºÎ·Ï ÏÎ¿Ï
+ GS3.  # Updated 1-Apr-2005
+#***** Missing GLIServer *****
+MissingGLIServer.Message:Î ÏÎ¿ÎµÎ¹ÎŽÎ¿ÏÎ¿Î¯Î·ÏÎ·! ÎÎµ ÎžÎ± ÎŒÏÎ¿ÏÎµÎ¯ÏÎµ ÎœÎ± ÎŽÎ¿Ï
+Î»Î­ÏÎµÏÎµ ÎŒÎµ ÏÎ¹Ï ÏÏ
+Î»Î»Î¿Î³Î­Ï ÏÎ¿Ï
+ Greenstone Î±Îœ ÎŽÎµÎœ Î¿ÏÎ¯ÏÎµÏÎµ ÏÎ· ÎŽÎ¹ÎµÏÎžÏ
+ÎœÏÎ· ÏÎ¿Ï
+ remote Greenstone "gliserver" script. Î ÏÎ­ÏÎµÎ¹ ÎœÎ± ÎŸÎµÎºÎ¹ÎœÎ¬ÎŒÎµ "http://" ÎºÎ±Î¹ ÎœÎ± ÏÎµÎ»ÎµÎ¯ÏÎœÎµÎ¹ ÎŒÎµ "gliserver".  # Updated 1-Apr-2005
+MissingGLIServer.Title:Î ÏÎ­ÏÎµÎ¹ ÎœÎ± ÏÏ
+ÎŒÏÎ»Î·ÏÏÎžÎµÎ¯ Î· ÎŽÎ¹ÎµÏÎžÏ
+ÎœÏÎ· ÏÎ¿Ï
+ GLIServer  # Updated 1-Apr-2005
+#***** Missing GSDL *****
+MissingGSDL.Message:ÏÏÎ¿ÎµÎ¹ÎŽÎ¿ÏÎ¿Î¯Î·ÏÎ·! Î ÎµÎ³ÎºÎ±ÏÎ¬ÏÏÎ±ÏÎ· ÎµÎ¯ÎœÎ±Î¹ ÎµÎ»ÎµÎ¹ÏÎ®Ï ÎºÎ±Î¹ ÎŽÎµ ÎžÎ± ÎŒÏÎ¿ÏÎµÎ¯ÏÎµ ÎœÎ± ÏÏÎ¿ÏÏÎµÎ»Î¬ÏÎµÏÎµ ÏÎ»Î± ÏÎ± ÏÎ±ÏÎ±ÎºÏÎ·ÏÎ¹ÏÏÎ¹ÎºÎ¬ ÏÎ¿Ï
+ ÎµÏÎ³Î±Î»ÎµÎ¯Î¿Ï
+. ÎÎ»Î­ÎŸÏÎµ ÏÎ± ÎŒÎ¿ÎœÎ¿ÏÎ¬ÏÎ¹Î± ÏÏÎ¿ .bat Î±ÏÏÎµÎ¯Î¿!  # Updated 1-Apr-2005
+MissingGSDL.Title:ÎÎ»ÎµÎ¹ÏÎ­Ï ÎŒÎ¿ÎœÎ¿ÏÎ¬ÏÎ¹  # Updated 1-Apr-2005
+#***** Missing PERL *****
+MissingPERL.Message:Î ÏÎ¿ÎµÎ¹ÎŽÎ¿ÏÎ¿Î¯Î·ÏÎ·! ÎÎµ ÎžÎ± ÎŒÏÎ¿ÏÎµÎ¯ÏÎµ ÎœÎ± ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î®ÏÎµÏÎµ ÎœÎ­ÎµÏ ÏÏ
+Î»Î»Î¿Î³Î­Ï Î® ÎœÎ± ÏÏÎ¯ÏÎµÏÎµ ÏÎ¹Ï Ï
+ÏÎ¬ÏÏÎ¿Ï
+ÏÎµÏ ÏÏÏÎ¯Ï ÏÎ·Îœ PERL. Î€Î¿ ÎµÏÎ³Î±Î»ÎµÎ¯Î¿ ÎŽÎµ ÎŒÏÏÏÎµÏÎµ ÎœÎ± Î²ÏÎµÎ¹ ÏÎ·Îœ ÎµÎ³ÎºÎ±ÏÎ¬ÏÏÎ±ÏÎ® ÏÎ·Ï ÏÏÎ¿ ÏÏÏÏÎ·ÎŒÎ±.ÎÎ»Î­ÎŸÏÎµ ÏÎ± ÎŒÎ¿ÎœÎ¿ÏÎ¬ÏÎ¹Î± ÏÎ¿Ï
+ ÎºÎ±ÎžÎ¿ÏÎ¯Î¶Î¿ÎœÏÎ±Î¹ ÏÏÎ¿ .bat Î±ÏÏÎµÎ¯Î¿.  # Updated 1-Apr-2005
+MissingPERL.Title:ÎÎ»ÎµÎ¹ÏÎ­Ï ÎŒÎ¿ÎœÎ¿ÏÎ¬ÏÎ¹ Î³Î¹Î± ÏÎ·Îœ PERL  # Updated 1-Apr-2005
+#******* MissingWGET ********
+MissingWGET.Message:Î ÏÎ¿ÎµÎ¹ÎŽÎ¿ÏÎ¿Î¯Î·ÏÎ·! ÎÎµ ÎžÎ± ÎŒÏÎ¿ÏÎµÎ¯ÏÎµ ÎœÎ± ÎºÎ±ÏÎµÎ²Î¬ÏÎµÏÎµ ÎœÎ­ÎµÏ ÏÏ
+Î»Î»Î¿Î³Î­Ï ÏÏÏÎ¯Ï ÏÎ¿ WGET. Î€Î¿ ÎµÏÎ³Î±Î»ÎµÎ¯Î¿ ÎŽÎµ ÎŒÏÏÏÎµÏÎµ ÎœÎ± Î²ÏÎµÎ¹ ÏÎ·Îœ ÎµÎ³ÎºÎ±ÏÎ¬ÏÏÎ±ÏÎ® ÏÎ¿Ï
+ ÏÏÎ¿ ÏÏÏÏÎ·ÎŒÎ±.ÎÎ»Î­ÎŸÏÎµ ÏÎ± ÎŒÎ¿ÎœÎ¿ÏÎ¬ÏÎ¹Î± ÏÎ¿Ï
+ ÎºÎ±ÎžÎ¿ÏÎ¯Î¶Î¿ÎœÏÎ±Î¹ ÏÏÎ¿ .bat Î±ÏÏÎµÎ¯Î¿.  # Updated 1-Apr-2005
+MissingWGET.Title:ÎÎ»ÎµÎ¹ÏÎ­Ï ÎŒÎ¿ÎœÎ¿ÏÎ¬ÏÎ¹ Î³Î¹Î± ÏÎ¿ WGet  # Updated 1-Apr-2005
+#******* MissingImageMagick ********
+MissingImageMagick.Message:Î€Î¿ ImageMagick ÎŽÎµÎœ ÎµÎ¯ÎœÎ±Î¹ ÎµÎ³ÎºÎ±ÏÎµÏÏÎ·ÎŒÎ­ÎœÎ¿, Î¿Î¹ ÏÏ
+Î»Î»Î¿Î³Î­Ï ÏÏÏÎ¿Î³ÏÎ±ÏÎ¹ÏÎœ ÎŽÎµ ÎžÎ± Î»ÎµÎ¹ÏÎ¿Ï
+ÏÎ³Î®ÏÎ¿Ï
+Îœ
+MissingImageMagick.Title:Î€Î¿ ImageMagick ÎŽÎµÎœ ÎµÎ¯ÎœÎ±Î¹ ÎµÎ³ÎºÎ±ÏÎµÏÏÎ·ÎŒÎ­ÎœÎ¿
+#*****************************
+#
+#***** New Session *****
+NewCollectionPrompt.Base_Collection:ÎÎ·ÎŒÎ¹Î¿ÏÏÎ³Î·ÏÎµ Î±Ï
+ÏÎ® ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î® ÎŒÎµ Î²Î¬ÏÎ·:  # Updated 1-Apr-2005
+NewCollectionPrompt.Base_Collection_Tooltip:ÎÏÎ¹Î»Î­ÎŸÏÎµ ÎŒÎ¹Î± Ï
+ÏÎ¬ÏÏÎ¿Ï
+ÏÎ± ÏÏ
+Î»Î»Î¿Î³Î® Î³Î¹Î± ÎœÎ± Î²Î±ÏÎ¹ÏÏÎµÎ¯ Î· ÎœÎ­Î±:  # Updated 1-Apr-2005
+NewCollectionPrompt.Collection_Description:Î ÎµÏÎ¹Î³ÏÎ±ÏÎ® Î ÎµÏÎ¹ÎµÏÎ¿ÎŒÎ­ÎœÎ¿Ï
+:  # Updated 1-Apr-2005
+#NewCollectionPrompt.Collection_Email:Email ÎÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¿Ï:  # Updated 1-Apr-2005
+NewCollectionPrompt.Collection_Name:ÎŠÎ¬ÎºÎµÎ»Î¿Ï Î£Ï
+Î»Î»Î¿Î³Î®Ï:  # Updated 1-Apr-2005
+#NewCollectionPrompt.Collection_Name_Tooltip:ÎÎ­ÏÏÎ¹ Î¿ÎºÏÏ ÏÎ±ÏÎ±ÎºÏÎ®ÏÎµÏ (ÏÏÎ·ÏÎ¹ÎŒÎ¿ÏÎ¿Î¹ÎµÎ¯ÏÎ±Î¹ ÎµÏÏÏÎµÏÎ¹ÎºÎ¬)  # Updated 1-Apr-2005
+NewCollectionPrompt.Error:Î£ÏÎ¬Î»ÎŒÎ± ÏÏÎ· ÎœÎ­Î± ÏÏ
+Î»Î»Î¿Î³Î®.  # Updated 1-Apr-2005
+NewCollectionPrompt.Instructions:ÎÎ¹Î± ÎœÎ± ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î®ÏÎµÏÎµ ÎŒÎ¹Î± ÎœÎ­Î± ÏÏ
+Î»Î»Î¿Î³Î® ÏÏ
+ÎŒÏÎ»Î·ÏÏÏÏÎµ ÏÎ± ÏÎ±ÏÎ±ÎºÎ¬ÏÏ ÏÎµÎŽÎ¯Î±.  # Updated 1-Apr-2005
+NewCollectionPrompt.Metadata_Elements:ÎÏÎ¿Î¹ ÎŒÎ­ÏÎ± ÏÏÎ¿ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿ ÏÏÎœÎ¿Î»Î¿:  # Updated 1-Apr-2005
+NewCollectionPrompt.Metadata_Instructions1:ÎÏÎ¹Î»Î­ÎŸÏÎµ ÏÎ¿ ÎºÎ¿Ï
+ÏÎ¬ÎºÎ¹ ÎŽÎ¯ÏÎ»Î± Î±ÏÏ ÎºÎ¬ÏÎ¿Î¹Î¿ ÏÏÎœÎ¿Î»Î¿ Î³Î¹Î± ÎœÎ± ÏÎµÏÎ¹Î»Î¬Î²ÎµÏÎµ ÏÎ¿ Î±ÎœÏÎ¯ÏÏÎ¿Î¹ÏÎ¿.  # Updated 1-Apr-2005
+NewCollectionPrompt.Metadata_Instructions2:(ÎÏÎ¿ÏÎµÎ¯ÏÎµ ÎœÎ± ÏÏÎ¿ÏÎžÎ­ÏÎµÏÎµ ÎµÏÎ¹ÏÎ»Î­Î¿Îœ ÏÏÎœÎ¿Î»Î± Î±ÏÎ³ÏÏÎµÏÎ±).  # Updated 1-Apr-2005
+NewCollectionPrompt.Metadata_Title_Existing:ÎÏÎ¹Î»Î­ÎŸÏÎµ ÏÏÎœÎ¿Î»Î± ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ.  # Updated 1-Apr-2005
+#NewCollectionPrompt.Name_Error:ÎÎµÎœ Î­ÏÎµÏÎµ ÎµÎ¹ÏÎ¬Î³ÎµÎ¹ ÏÎœÎ¿ÎŒÎ± Î³Î¹Î± ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î® Î® ÏÎ¿ ÏÎœÎ¿ÎŒÎ± ÏÎ¿Ï
+ ÎµÏÎ¹Î»Î­ÎŸÎ±ÏÎµ ÎµÎ¯ÎœÎ±Î¹ Î®ÎŽÎ· ÏÎµ ÏÏÎ®ÏÎ·.  # Updated 1-Apr-2005
+NewCollectionPrompt.NewCollection:-- ÎÎ­Î± Î£Ï
+Î»Î»Î¿Î³Î® --  # Updated 1-Apr-2005
+NewCollectionPrompt.Select_MDS:ÎÎ¹Î±ÎžÎ­ÏÎ¹ÎŒÎ± Î£ÏÎœÎ¿Î»Î± ÎÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ:  # Updated 1-Apr-2005
+NewCollectionPrompt.Title:ÎÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î®ÏÏÎµ ÎŒÎ¹Î± ÎœÎ­Î± ÏÏ
+Î»Î»Î¿Î³Î®.  # Updated 1-Apr-2005
+NewCollectionPrompt.Title_Clash:Î ÏÎ¯ÏÎ»Î¿Ï ÏÎ¿Ï
+ Î­ÏÎµÏÎµ ÎµÏÎ¹Î»Î­ÎŸÎµÎ¹ Î³Î¹Î± ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î® ÏÎ±Ï ÏÏÎ·ÏÎ¹ÎŒÎ¿ÏÎ¿Î¹ÎµÎ¯ÏÎ±Î¹ Î±ÏÏ Î¬Î»Î»Î·. ÎÎ± ÏÏ
+ÎœÎµÏÎ¯ÏÏ?  # Updated 1-Apr-2005
+NewCollectionPrompt.Title_Error:Î ÏÎ¯ÏÎ»Î¿Ï ÏÏÎ­ÏÎµÎ¹ ÎœÎ± ÏÏ
+ÎŒÏÎ»Î·ÏÏÎžÎµÎ¯. Î Î±ÏÎ±ÎºÎ±Î»Ï ÎŽÎ¹Î¿ÏÎžÏÏÏÎµ.  # Updated 1-Apr-2005
+#***** New Folder OrFilePrompt *****
+NewFolderOrFilePrompt.Default_File_Name:dummy  # Updated 1-Apr-2005
+NewFolderOrFilePrompt.Default_Folder_Name:ÎœÎ­Î¿Ï ÏÎ¬ÎºÎµÎ»Î¿Ï  # Updated 1-Apr-2005
+NewFolderOrFilePrompt.Destination_Name:ÎŠÎ¬ÎºÎµÎ»Î¿Ï Î ÏÎ¿Î¿ÏÎ¹ÏÎŒÎ¿Ï  # Updated 1-Apr-2005
+NewFolderOrFilePrompt.File_Name:ÎÎœÎ¿ÎŒÎ± Î±ÏÏÎµÎ¯Î¿Ï
+  # Updated 1-Apr-2005
+NewFolderOrFilePrompt.File_Name_Tooltip:ÎÎ¹ÏÎ¬Î³ÎµÏÎµ Î­ÎœÎ± ÏÎœÎ¿ÎŒÎ± Î³Î¹Î± ÏÎ¿ ÎœÎ­Î¿ Î±ÏÏÎµÎ¯Î¿  # Updated 1-Apr-2005
+NewFolderOrFilePrompt.Folder_Name:ÎÎœÎ¿ÎŒÎ± ÏÎ±ÎºÎ­Î»Î¿Ï
+  # Updated 1-Apr-2005
+NewFolderOrFilePrompt.Folder_Name_Tooltip:ÎÎ¹ÏÎ¬Î³ÎµÏÎ±Î¹ Î­ÎœÎ± ÏÎœÎ¿ÎŒÎ± Î³Î¹Î± ÏÎ¿ ÎœÎ­Î¿ ÏÎ¬ÎºÎµÎ»Î¿  # Updated 1-Apr-2005
+NewFolderOrFilePrompt.Title_Folder:ÎÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î®ÏÏÎµ Î­ÎœÎ± ÎœÎ­Î¿ ÏÎ¬ÎºÎµÎ»Î¿  # Updated 1-Apr-2005
+NewFolderOrFilePrompt.Title_File:ÎÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î®ÏÏÎµ Î­ÎœÎ± ÎœÎ­Î¿ dummy Î­Î³Î³ÏÎ±ÏÎ¿  # Updated 1-Apr-2005
+#***********************
+#
+NoMetadataSetsSelected.Message:ÎÎœ ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î®ÏÎµÏÎµ ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î® ÏÏÏÎ± ÎŽÎµ ÎžÎ± Î­ÏÎµÎ¹ Î±ÏÏÎ¹ÎºÎ¬ ÏÏÎœÎ¿Î»Î± ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ. ÎÎµ ÎžÎ± ÎŒÏÎ¿ÏÎµÎ¯ÏÎµ ÎœÎ± ÎºÎ±ÏÎ±ÏÏÏÎ®ÏÎµÏÎµ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ± ÎŒÎ­ÏÏÎ¹ ÎœÎ± ÎµÎ¹ÏÎ¬Î³ÎµÏÎµ Î­ÎœÎ± ÏÏÎœÎ¿Î»Î¿ ÏÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®. ÎÏÎ¹ÎžÏ
+ÎŒÎµÎ¯ÏÎµ ÎœÎ± ÏÏ
+ÎœÎµÏÎ¯ÏÎµÏÎµ?  # Updated 1-Apr-2005
+NoMetadataSetsSelected.Title:ÎÎµÎœ Î­ÏÎ¿Ï
+Îœ ÎµÏÎ¹Î»ÎµÎ³ÎµÎ¯ ÏÏÎœÎ¿Î»Î± ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ  # Updated 1-Apr-2005
+#**********************
+#
+#******* OldWGET *******
+NoPluginExpectedToProcessFile.Message:ÎÎµÎœÎ­ÎœÎ± Î±ÏÏ ÏÎ± plugins ÏÎ¿Ï
+ Greenstone ÎŽÎµ ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± ÎµÏÎµÎŸÎµÏÎ³Î±ÏÏÎµÎ¯ ÏÎ¿ Î±ÏÏÎµÎ¯Î¿ "{0}". ÎÎ»Î­ÎŸÏÎµ ÏÏÎ¹ ÏÎ¿ Î±ÏÏÎµÎ¯Î¿ Î­ÏÎµÎ¹ ÏÎ· ÏÏÏÏÎ® ÎºÎ±ÏÎ¬Î»Î·ÎŸÎ·. ÎÎœ Î­ÏÎµÎ¹ ÏÎœÏÏÏ ÏÏÏÏÎ® ÏÏÏÎµ ÏÏÎ·ÏÎ¹ÎŒÎ¿ÏÎ¿Î¹Î®ÏÏÎµ ÏÎ¿ UnknownPlug.  # Updated 1-Apr-2005
+NoPluginExpectedToProcessFile.Title:ÎÎµ Î²ÏÎ­ÎžÎ·ÎºÎµ plugin Î³Î¹Î± ÎœÎ± ÎµÏÎµÎŸÎµÏÎ³Î±ÏÏÎµÎ¯ ÏÎ¿ Î±ÏÏÎµÎ¯Î¿  # Updated 1-Apr-2005
+#**********************
+#
+#******* OldWGET *******
+OldWGET.Message:Î ÏÎ¿ÎµÎ¹ÎŽÎ¿ÏÎ¿Î¯Î·ÏÎ·! Î Î­ÎºÎŽÎ¿ÏÎ· ÏÎ¿Ï
+ WGet ÏÎ¿Ï
+ Î­ÏÎµÏ ÎµÎ³ÎºÎ±ÏÎµÏÏÎ·ÎŒÎ­Î· Î­ÏÎµÎ¹ Î­ÎœÎ± Î³ÎœÏÏÏÏ ÏÏÏÎ²Î»Î·ÎŒÎ± ÏÏÎ±Îœ mirror ÏÎ¿Ï
+ ÏÎµÏÎ¹Î­ÏÎ¿Ï
+Îœ ÎºÏÎŽÎ¹ÎºÎ¿ÏÎ¿Î¹Î·ÎŒÎ­ÎœÎ¿Ï
+Ï ÏÎ±ÏÎ±ÎºÏÎ®ÏÎµÏ ÏÏÏÏ space ÎºÎ±Î¹ tilde ÏÏÎ¿ URL. ÎÎ³ÎºÎ±ÏÎ±ÏÏÎ®ÏÏÎµ WGet 1.9.  # Updated 1-Apr-2005
+OldWGET.Title:Î Î±Î»Î¹Ï WGet  # Updated 1-Apr-2005
+#***********************
+#
+#***** OpenCollectionDialog *****
+OpenCollectionDialog.Available_Collections:ÎÎ¹Î±ÎžÎ­ÏÎ¹ÎŒÎµÏ ÏÏ
+Î»Î»Î¿Î³Î­Ï  # Updated 1-Apr-2005
+OpenCollectionDialog.Browse:Î Î»Î¿Î®Î³Î·ÏÎ·  # Updated 1-Apr-2005
+OpenCollectionDialog.Browse_Tooltip:ÎÏÎ¹Î»Î­ÎŸÏÎµ ÎŒÎ¹Î± ÏÏ
+Î»Î»Î¿Î³Î® Î±ÏÏ ÏÎ¿ ÏÏÏÏÎ·ÎŒÎ± Î±ÏÏÎµÎ¯ÏÎœ ÏÎ±Ï  # Updated 1-Apr-2005
+OpenCollectionDialog.Collection:Î£Ï
+Î»Î»Î¿Î³Î® ÏÎ¿Ï
+ Greenstone (".col")  # Updated 1-Apr-2005
+OpenCollectionDialog.Description:Î ÎµÏÎ¹Î³ÏÎ±ÏÎ® Î£Ï
+Î»Î»Î¿Î³Î®Ï  # Updated 1-Apr-2005
+OpenCollectionDialog.Locked_Collection:Î ÏÏ
+Î»Î»Î¿Î³Î® Î®ÎŽÎ· ÏÏÎ·ÏÎ¹ÎŒÎ¿ÏÎ¿Î¹ÎµÎ¯ÏÎ±Î¹  # Updated 1-Apr-2005
+OpenCollectionDialog.No_Description:ÎÏÎ¹Î»Î­ÎŸÏÎµ Î­ÎœÎ± ".col" Î±ÏÏÎµÎ¯Î¿ Î³Î¹Î± ÎœÎ± ÎŽÎµÎ¯ÏÎµ ÏÎ·Îœ ÏÎµÏÎ¹Î³ÏÎ±ÏÎ® ÏÎ·Ï ÏÏ
+Î»Î»Î¿Î³Î®Ï.  # Updated 1-Apr-2005
+OpenCollectionDialog.Normal_Collection:Î£Ï
+Î»Î»Î¿Î³Î® ÏÎ¿Ï
+ Greenstone  # Updated 1-Apr-2005
+OpenCollectionDialog.Open:ÎÎœÎ¿Î¹Î³ÎŒÎ±  # Updated 1-Apr-2005
+OpenCollectionDialog.Open_Tooltip:ÎŠÎ¿ÏÏÏÎœÎµÎ¹ ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î® ÏÎ¿Ï
+ ÎžÎ± ÎµÏÎ¹Î»ÎµÎ³ÎµÎ¯ ÏÏÎ¿ ÎµÏÎ³Î±Î»ÎµÎ¯Î¿  # Updated 1-Apr-2005
+OpenCollectionDialog.Title:ÎÎœÎ¿Î¹Î³ÎŒÎ± Î£Ï
+Î»Î»Î¿Î³Î®Ï ÏÎ¿Ï
+ Greenstone  # Updated 1-Apr-2005
+#**********************
+#
+#***** Options Pane inside CreatePane *****
+OptionsPane.Cancelled:- Î±ÎºÏ
+ÏÏÎžÎ·ÎºÎµ  # Updated 1-Apr-2005
+OptionsPane.LogHistory:ÎÏÏÎ¿ÏÎ¹ÎºÏ ÎºÎ±ÏÎ±Î³ÏÎ±ÏÎ®Ï  # Updated 1-Apr-2005
+OptionsPane.Successful:- ÎµÏÎ¹ÏÏ
+ÏÎ­Ï  # Updated 1-Apr-2005
+OptionsPane.Unknown:- Î¬Î³ÎœÏÏÏÎ¿  # Updated 1-Apr-2005
+OptionsPane.Unsuccessful:- Î±ÎœÎµÏÎ¹ÏÏ
+ÏÎ­Ï  # Updated 1-Apr-2005
+#*******************
+#
+#***** Preferences *****
+Preferences:Preferences  # Updated 1-Apr-2005
+Preferences.Connection:Î£ÏÎœÎŽÎµÏÎ·  # Updated 1-Apr-2005
+Preferences.Connection_Tooltip:ÎÎ­ÏÏÎµ ÏÎ¿ URL ÏÏÎ· Î²Î¹Î²Î»Î¹Î¿ÎžÎ®ÎºÎ· ÎºÎ±Î¹ ÎŽÎ¹Î±ÎŒÎ¿ÏÏÏÏÏÎµ ÎŒÎ¹Î± proxy ÏÏÎœÎŽÎµÏÎ· (Î±Îœ Ï
+ÏÎ¬ÏÏÎµÎ¹)  # Updated 1-Apr-2005
+Preferences.Connection.GLIServer_URL:Greenstone gliserver URL:  # Updated 1-Apr-2005
+Preferences.Connection.GLIServer_URL_Tooltip:Î€Î¿ URL ÏÎ¿Ï
+ "gliserver" ÏÎ¿Ï
+ Greenstone CGI script  # Updated 1-Apr-2005
+Preferences.Connection.Library_Path:ÎÎ¿ÎœÎ¿ÏÎ¬ÏÎ¹ Î²Î¹Î²Î»Î¹Î¿ÎžÎ®ÎºÎ·Ï:  # Updated 1-Apr-2005
+Preferences.Connection.Library_Path_GS3:ÎÎ¿ÎœÎ¿ÏÎ¬ÏÎ¹ Web:  # Updated 1-Apr-2005
+Preferences.Connection.Library_Path_Tooltip:Î€Î¿ URL ÏÎ¿Ï
+ web-server  # Updated 1-Apr-2005
+Preferences.Connection.Library_Path_Tooltip_GS3:Î€Î¿ URL ÏÎ¿Ï
+ web-server  # Updated 1-Apr-2005
+Preferences.Connection.ProgramCommand:Î ÏÎ¿ÎµÏÎ¹ÏÎºÏÏÎ·ÏÎ· ÎµÎœÏÎ¿Î»Î®Ï:  # Updated 1-Apr-2005
+Preferences.Connection.ProgramCommand_Tooltip:Î ÎµÎœÏÎ¿Î»Î® ÏÎ¿Ï
+ ÎŸÎµÎºÎ¹ÎœÎ¬ ÏÎ¿ ÏÏÏÎ³ÏÎ±ÎŒÎŒÎ± Î³Î¹Î± ÏÎ·Îœ ÏÏÎ¿ÎµÏÎ¹ÏÎºÏÏÎ·ÏÎ· ÏÎ·Ï ÏÏ
+Î»Î»Î¿Î³Î®Ï.  # Updated 1-Apr-2005
+Preferences.Connection.Proxy_Host:Proxy Host:  # Updated 1-Apr-2005
+Preferences.Connection.Proxy_Host_Tooltip:Î ÎŽÎ¹ÎµÏÎžÏ
+ÎœÏÎ· ÏÎ¿Ï
+ proxy server  # Updated 1-Apr-2005
+Preferences.Connection.Proxy_Port:Proxy Port:  # Updated 1-Apr-2005
+Preferences.Connection.Proxy_Port_Tooltip:Î€Î¿ port number ÏÎ¿Ï
+ proxy server  # Updated 1-Apr-2005
+Preferences.Connection.Servlet:Servlet:  # Updated 1-Apr-2005
+Preferences.Connection.Servlet_Tooltip:Î€Î¿ servlet ÏÎ¿Ï
+ ÎµÎŒÏÎ±ÎœÎ¯Î¶ÎµÎ¹ ÏÎ·Îœ Ï
+ÏÎµÏÏÏ
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+Preferences.Connection.Servlet_Tooltip2:ÎÎµÎœ Ï
+ÏÎ¬ÏÏÎµÎ¹ servlet Î³Î¹Î± Î±Ï
+ÏÎ® ÏÎ·Îœ Ï
+ÏÎµÏÏÏ
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+Preferences.Connection.Site:Site:  # Updated 1-Apr-2005
+Preferences.Connection.Site_Tooltip:Î€Î¿ site ÏÏÎ¿ Î¿ÏÎ¿Î¯Î¿ ÎžÎ± ÎµÏÎ³Î±ÏÏÎµÎ¯ÏÎµ  # Updated 1-Apr-2005
+Preferences.Connection.Use_Proxy:ÎÎ± ÏÏÎ·ÏÎ¹ÎŒÎ¿ÏÎ¿Î¹Î·ÎžÎµÎ¯ proxy ÏÏÎœÎŽÎµÏÎ·?  # Updated 1-Apr-2005
+Preferences.General:ÎÎµÎœÎ¹ÎºÎ¬  # Updated 1-Apr-2005
+Preferences.General_Tooltip:ÎÎ­ÏÎµÎ¹ ÎºÎ¬ÏÎ¿Î¹ÎµÏ Î³ÎµÎœÎ¹ÎºÎ­Ï ÎµÏÎ¹Î»Î¿Î³Î­Ï  # Updated 1-Apr-2005
+Preferences.General.Email:Email Î§ÏÎ®ÏÏÎ·:  # Updated 1-Apr-2005
+Preferences.General.Email_Tooltip:Î€Î¿ email ÏÎ¿Ï
+ ÎžÎ± ÏÏÎ·ÏÎ¹ÎŒÎ¿ÏÎ¿Î¹ÎµÎ¯ÏÎ±Î¹ Î±Ï
+ÏÏÎŒÎ±ÏÎ± Î³Î¹Î± ÎºÎ¬ÎžÎµ ÏÏ
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+Preferences.General.Font:Font:  # Updated 1-Apr-2005
+Preferences.General.Font_Tooltip:Î€Î¿ font Î³Î¹Î± ÏÎ¿ interface.  # Updated 1-Apr-2005
+Preferences.General.Interface_Language:ÎÎ»ÏÏÏÎ± ÎÎ¹ÎµÏÎ±ÏÎ®Ï:  # Updated 1-Apr-2005
+Preferences.General.Interface_Language_Tooltip:ÎÏÎ¹Î»Î­ÎŸÏÎµ ÏÎ· Î³Î»ÏÏÏÎ± ÏÏÎ·Îœ Î¿ÏÎ¿Î¯Î± ÎžÎ­Î»ÎµÏÎµ ÎœÎ± ÎµÎŒÏÎ±ÎœÎ¯Î¶ÎµÏÎ±Î¹ ÏÎ¿ ÏÎµÏÎ¹Î²Î¬Î»Î»Î¿Îœ.  # Updated 1-Apr-2005
+Preferences.General.Restart_Required:Î€Î¿ ÎµÏÎ³Î±Î»ÎµÎ¯Î¿ ÏÏÎ­ÏÎµÎ¹ ÎœÎ± ÎŸÎ±ÎœÎ±ÎŸÎµÎºÎ¹ÎœÎ®ÏÎµÎ¹ Î³Î¹Î± ÎœÎ± ÎŒÏÎ¿ÏÎ­ÏÎµÎ¹ ÎœÎ± ÎµÏÎ±ÏÎŒÏÏÎµÎ¹ ÏÎ¹Ï Î±Î»Î»Î±Î³Î­Ï. (ÎÎ»ÎµÎ¯ÏÏÎµ ÏÎ¿ ÎºÎ±Î¹ ÎŸÎµÎºÎ¹ÎœÎ®ÏÏÎµ ÏÎ¿ ÏÎ¬Î»Î¹)  # Updated 1-Apr-2005
+Preferences.General.Show_File_Size:ÎÎµÎ¯ÎŸÎµ ÏÎ± ÎŒÎµÎ³Î­ÎžÎ· ÏÏÎœ Î±ÏÏÎµÎ¯ÏÎœ  # Updated 1-Apr-2005
+Preferences.General.Show_File_Size_Tooltip:ÎÎµÎ¯ÏÎœÎµÎ¹ ÏÎ¿ ÎŒÎ­Î³ÎµÎžÎ¿Ï ÎºÎ¬ÎžÎµ Î±ÏÏÎµÎ¯Î¿Ï
+ ÎŽÎµÎŸÎ¹Î¬ Î±ÏÏ Î±Ï
+ÏÏ.  # Updated 1-Apr-2005
+Preferences.General.View_Extracted_Metadata:Î ÏÏÎ²Î±Î»Îµ ÏÎ± ÎµÎŸÎ±Î³ÎŒÎ­ÎœÎ± ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ±  # Updated 1-Apr-2005
+Preferences.General.View_Extracted_Metadata_Tooltip:Î Î±ÏÎ¿Ï
+ÏÎ¹Î¬Î¶ÎµÎ¹ ÏÎ± ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ± ÏÎ¿Ï
+ ÎµÎŸÎ¬Î³Î¿ÎœÏÎ±Î¹ Î±Ï
+ÏÏÎŒÎ±ÏÎ± Î±ÏÏ ÏÎ± plugins ÏÎ¿Ï
+ Greenstone ÏÏÎ· Î»Î¯ÏÏÎ± ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ ÏÏÎ·Îœ ÎºÎ±ÏÏÎ­Î»Î± ÎµÎŒÏÎ»Î¿Ï
+ÏÎ¹ÏÎŒÏÏ.  # Updated 1-Apr-2005
+Preferences.Mode:Mode  # Updated 1-Apr-2005
+Preferences.Mode_Tooltip:ÎÏÎ¹Î»Î­ÎŸÏÎµ ÎŒÎ¹Î± ÏÎ¹ÎŒÎ® ÏÎ¿Ï
+ Î±ÎœÏÎ¹ÏÏÎ¿ÏÏÏÎµÏÎµÎ¹ ÏÎ¿ ÎºÎ±ÏÎ¬Î»Î»Î·Î»Î¿ ÎµÏÎ¯ÏÎµÎŽÎ¿ Î»ÎµÎ¹ÏÎ¿Ï
+ÏÎ³Î¯Î±Ï  # Updated 1-Apr-2005
+Preferences.Mode.Assistant:ÎÎ¿Î·ÎžÏÏ ÎÎ¹Î²Î»Î¹Î¿ÎžÎ·ÎºÎ¿ÎœÏÎŒÎ¿Ï
+  # Updated 1-Apr-2005
+Preferences.Mode.Assistant_Description:Î ÏÏÏÎ²Î±ÏÎ· ÎŒÏÎœÎ¿ ÏÏÎ¹Ï Î²Î±ÏÎ¹ÎºÎ­Ï Ï
+ÏÎ·ÏÎµÏÎ¯ÎµÏ ÏÎ¿Ï
+ Greenstone: ÏÏÎ¿ÏÎžÎ®ÎºÎ· ÎµÎ³Î³ÏÎ¬ÏÏÎœ ÎºÎ±Î¹ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ ÏÏÎ¹Ï ÏÏ
+Î»Î»Î¿Î³Î­Ï, ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¯Î± ÎœÎ­ÏÎœ ÏÏ
+Î»Î»Î¿Î³ÏÎœ.  # Updated 1-Apr-2005
+Preferences.Mode.Librarian:ÎÎ¹Î²Î»Î¹Î¿ÎžÎ·ÎºÎ¿ÎœÏÎŒÎ¿Ï  # Updated 1-Apr-2005
+Preferences.Mode.Librarian_Description:ÎÎ±ÎœÎ¿ÎœÎ¹ÎºÏ ÎµÏÎ¯ÏÎµÎŽÎ¿ ÎŽÎ¹ÎºÎ±Î¹ÏÎŒÎ¬ÏÏÎœ: ÏÏÏÏ ÏÏÎ¿Î·Î³Î¿ÏÎŒÎµÎœÎ¿ + ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¯Î± ÎºÎ±Î¹ ÏÏÎµÎŽÎ¯Î±ÏÎ· ÏÏ
+Î»Î»Î¿Î³ÏÎœ.  # Updated 1-Apr-2005
+Preferences.Mode.Systems:ÎÎŸÎµÎ¹ÎŽÎ¹ÎºÎµÏ
+ÎŒÎ­ÎœÎ¿ Î ÏÎ¿ÏÏÏÎ¹ÎºÏ ÎÎ¹Î²Î»Î¹Î¿ÎžÎ®ÎºÎ·Ï  # Updated 1-Apr-2005
+Preferences.Mode.Systems_Description:Î Î»Î®ÏÎ·Ï ÏÏÎ®ÏÎ· ÏÎ¿Ï
+ ÎµÏÎ³Î±Î»ÎµÎ¯Î¿Ï
+ ÎŒÎµ Î±ÎŸÎ¹Î¿ÏÎ¿Î¯Î·ÏÎ· ÎºÎ±ÎœÎ¿ÎœÎ¹ÎºÏÎœ ÎµÎºÏÏÎ¬ÏÎµÏÎœ.  # Updated 1-Apr-2005
+Preferences.Mode.Expert:ÎÎ¹ÎŽÎ¹ÎºÎ¿Î¯  # Updated 1-Apr-2005
+Preferences.Mode.Expert_Description:ÎÎ»Î± ÏÎ± ÏÎ±ÏÎ±ÎºÏÎ·ÏÎ¹ÏÏÎ¹ÎºÎ¬ ÎµÎ¯ÎœÎ±Î¹ ÎµÎœÎµÏÎ³Î¿ÏÎ¿Î¹ÎŒÎ­ÎœÎ± ÎºÎ±ÎžÏÏ ÎµÏÎ¯ÏÎ·Ï ÎºÎ±Î¹ ÏÎ± ÎŒÎ·ÎœÏÎŒÎ±ÏÎ± Î±ÏÏ ÏÎ¿Îœ ÏÎ·Î³Î±Î¯Î¿ ÎºÏÎŽÎ¹ÎºÎ±. ÎÏÎœÎ¿ Î­ÎŒÏÎµÎ¹ÏÎ¿Î¹ ÏÏÎ®ÏÏÎµÏ ÏÏÎ­ÏÎµÎ¹ ÎœÎ± ÏÎ¿ ÏÏÎ·ÏÎ¹ÎŒÎ¿ÏÎ¿Î¹Î¿ÏÎœ  # Updated 1-Apr-2005
+Preferences.Warnings:Î ÏÎ¿ÎµÎ¹ÎŽÎ¿ÏÎ¿Î¹Î®ÏÎµÎ¹Ï  # Updated 1-Apr-2005
+Preferences.Warnings_Tooltip:ÎÎœÎµÏÎ³Î¿ÏÎ¿Î¯Î·ÏÏÎµ/ÎÏÎµÎœÎµÏÎ³Î¿ÏÎ¿Î¹Î®ÏÏÎµ ÏÎ± ÎŽÎ¹Î¬ÏÎ¿ÏÎ± ÎŒÎ·ÎœÏÎŒÎ±ÏÎ± ÏÏÎ¿ÎµÎ¹ÎŽÎ¿ÏÎ¿Î¯Î·ÏÎ·Ï  # Updated 1-Apr-2005
+Preferences.Workflow:Î¡Î¿Î® ÎÏÎ³Î±ÏÎ¹ÏÎœ  # Updated 1-Apr-2005
+Preferences.Workflow_Tooltip:Î£ÏÎµÎŽÎ¹Î¬ÏÏÎµ ÏÎ¿ ÏÎµÏÎ¹Î²Î¬Î»Î»Î¿Îœ Î±ÏÎµÎœÎµÏÎ³ ÎŽÎ¹Î±ÏÎ¿ÏÎµÏ ÎºÎ±ÏÏÎ­Î»ÎµÏ  # Updated 1-Apr-2005
+Preferences.Workflow.Create:ÎÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î®ÏÏÎµ ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î® ÎŒÎµ ÏÎ¿ Greenstone  # Updated 1-Apr-2005
+Preferences.Workflow.Design:Î£ÏÎµÎŽÎ¯Î±ÏÎ· - Î±Î»Î»Î±Î³Î® ÎµÎŒÏÎ¬ÎœÎ¹ÏÎ·Ï ÏÏ
+Î»Î»Î¿Î³Î®Ï  # Updated 1-Apr-2005
+Preferences.Workflow.Download:ÎÎ±ÏÎ­Î²Î±ÏÎŒÎ± - ÎºÎ±ÏÎ­Î²Î±ÏÎŒÎ± ÏÏÏÏÎœ Î±ÏÏ ÏÎ¿ web  # Updated 1-Apr-2005
+Preferences.Workflow.Enrich:ÎÎŒÏÎ»Î¿Ï
+ÏÎ¹ÏÎŒÏÏ - ÏÏÎ¿Î»Î¹Î±ÏÎŒÏÏ ÎŒÎµ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÎ±  # Updated 1-Apr-2005
+Preferences.Workflow.Gather:Î£Ï
+Î»Î»Î¿Î³Î® - ÎÏÎ¹Î»Î¿Î³Î® Î±ÏÏÎµÎ¯ÏÎœ Î³Î¹Î± ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®  # Updated 1-Apr-2005
+Preferences.Workflow.Predefined.Label:Î ÏÎ¿ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎµÏ Î¡Î¿Î­Ï  # Updated 1-Apr-2005
+Preferences.Workflow.Title:ÎÏÎ¹Î»Î­ÎŸÏÎµ ÎºÎ¿Ï
+ÏÎ¬ÎºÎ¹ Î³Î¹Î± ÎœÎ± ÎµÎœÎµÏÎ³Î¿ÏÎ¿Î¹Î®ÏÎµÏÎµ ÏÎ·Îœ ÏÏÎ¿Î²Î¿Î»Î®  # Updated 1-Apr-2005
+#**********************
+#
+#**** PreviewCommandDialog *******
+PreviewCommandDialog.Instructions:ÎÎ¹ÏÎ¬Î³ÎµÏÎµ ÏÎ·Îœ ÎµÎœÏÎ¿Î»Î® Î³Î¹Î± Î±ÎœÎ¿Î¯ÎŸÎµÎ¹ ÏÎ¿ ÏÏÏÎ³ÏÎ±ÎŒÎŒÎ± ÏÏÎ¿ÎµÏÎ¹ÏÎºÏÏÎ·ÏÎ·Ï ÏÎ·Ï ÏÏ
+Î»Î»Î¿Î³Î®Ï.  # Updated 1-Apr-2005
+PreviewCommandDialog.Title:ÎÎœÏÎ¿Î»Î® Î ÏÎ¿ÎµÏÎ¹ÏÎºÏÏÎ·ÏÎ·Ï  # Updated 1-Apr-2005
+#**********************
+#
+#***** Remote Greenstone Server *****
+RemoteGreenstoneServer.Authentication_Message:ÎÎ¹ÏÎ¬Î³ÎµÏÎµ ÏÎ¿ ÏÎœÎ¿ÎŒÎ± ÏÏÎ®ÏÏÎ· ÎºÎ±Î¹ ÏÎ¿Îœ ÎºÏÎŽÎ¹ÎºÏ ÏÎ±Ï:  # Updated 1-Apr-2005
+RemoteGreenstoneServer.Error:ÎÎœÎ± ÏÏÎ¬Î»ÎŒÎ± ÏÏÎ¿Î­ÎºÏ
+ÏÎµ ÏÏÎ¿Îœ Î±ÏÎ¿ÎŒÎ±ÎºÏÏ
+ÏÎŒÎ­ÎœÎ¿ Greenstone ÎµÎŸÏ
+ÏÎ·ÏÎµÏÎ·ÏÎ® ÎµÎœÏ ÎµÎºÏÎµÎ»Î¿ÏÏÎµ ÏÎ· ÎŽÎ¹Î±ÎŽÎ¹ÎºÎ±ÏÎ¯Î±:\n{0-Error message}  # Updated 1-Apr-2005
+RemoteGreenstoneServer.Error_Title:Î£ÏÎ¬Î»ÎŒÎ± Î±ÏÎ¿ÎŒÎ±ÎºÏÏ
+ÏÎŒÎ­ÎœÎ¿Ï
+ Greenstone Server  # Updated 1-Apr-2005
+RemoteGreenstoneServer.Progress:Î ÏÏÎ¿ÎŽÎ¿Ï ÎÏÎ¿ÎŒÎ±ÎºÏÏ
+ÏÎŒÎ­ÎœÎ¿Ï
+ Greenstone ÎÎŸÏ
+ÏÎ·ÏÎµÏÎ·ÏÎ®:  # Updated 1-Apr-2005
+RemoteGreenstoneServer.Steal_Lock_Message:ÎÏ
+ÏÎ® Î· ÏÏ
+Î»Î»Î¿Î³Î® ÎµÎ¯ÎœÎ±Î¹ ÏÏÎ¿ÏÏÏÎ¹ÎœÎ¬ ÎºÎ»ÎµÎ¹ÎŽÏÎŒÎ­ÎœÎ· Î±ÏÏ ÏÎ¿Îœ ÏÏÎ®ÏÏÎ· '{0-User name}'.\nÎÎ­Î»ÎµÏÎµ ÎœÎ± ÎºÎµÏÎŽÎ¯ÏÎµÏÎµ ÎµÏÎµÎ¯Ï ÏÎ¿Îœ Î­Î»ÎµÎ³ÏÎ¿? (ÎŽÎµ ÏÏ
+ÏÏÎ®ÎœÎµÏÎµ Î±ÏÎ¿Ï ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± ÏÎ±ÎžÎµÎ¯ ÎŽÎ¿Ï
+Î»ÎµÎ¹Î¬)?  # Updated 1-Apr-2005
+#**********************
+#
+#***** Rename Prompt *****
+RenamePrompt.Name:Name:  # Updated 1-Apr-2005
+RenamePrompt.Title:Rename file/folder  # Updated 1-Apr-2005
+#**********************
+#
+#***** Replace Prompt *****
+ReplacePrompt.Title:ÎÎœÏÎ¹ÎºÎ±ÏÎ±ÏÏÎ®ÏÏÎµ ÏÎ¿ Î±ÏÏÎµÎ¯Î¿ ÎŒÎµ ...
+#**********************
+#
+#***** Save Collection Box *****
+SaveCollectionBox.File_Name:ÎÎœÎ¿ÎŒÎ± ÎÏÏÎµÎ¯Î¿Ï
+:  # Updated 1-Apr-2005
+SaveCollectionBox.Files_Of_Type:ÎÏÏÎµÎ¯Î± ÏÏÏÎ¿Ï
+:  # Updated 1-Apr-2005
+SaveCollectionBox.Look_In:ÎšÎ¬ÎŸÎµ ÏÎµ:  # Updated 1-Apr-2005
+#**********************
+#
+#***** Save Progress Box *******
+SaveProgressDialog.Title:ÎÏÎ¿ÎžÎ®ÎºÎµÏ
+ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î®Ï  # Updated 1-Apr-2005
+#*******************************
+#
+Server.QuitManual:Î€Î¿ ÎµÏÎ³Î±Î»ÎµÎ¯Î¿ ÎŽÎµÎœ Î®ÏÎ±Îœ ÎŽÏ
+ÎœÎ±ÏÏ ÎœÎ± ÎºÎ»ÎµÎ¯ÏÎµÎ¹ ÏÎ¿Îœ ÏÎ¿ÏÎ¹ÎºÏ \nÎµÎŸÏ
+ÏÎ·ÏÎµÏÎ·ÏÎ® ÏÏ
+Î»Î»Î¿Î³Î®Ï Î±Ï
+ÏÏÎŒÎ±ÏÎ±. ÎÎ»ÎµÎ¯ÏÏÎµ ÏÎ¿Îœ \nÏÎµÎ¹ÏÎ¿ÎºÎ¯ÎœÎ·ÏÎ±.  # Updated 1-Apr-2005
+Server.QuitTimeOut:Î ÏÎ¿ÏÎ¹ÎºÎ® ÏÏ
+Î»Î»Î¿Î³Î® ÎŽÎµÎœ Î­ÏÎµÎ¹ Î±ÏÎ±ÎœÏÎ®ÏÎµÎ¹ \nÏÏÎ¿ Î±Ï
+ÏÏÎŒÎ±ÏÎ¿ ÎºÎ»ÎµÎ¯ÏÎ¹ÎŒÎ¿ Î³Î¹Î± ÎµÎŸÎ®ÎœÏÎ± ÎŽÎµÏ
+ÏÎµÏÏÎ»ÎµÏÏÎ±. ÎÏÎ¹ÎžÏ
+ÎŒÎµÎ¯ÏÎµ ÎœÎ± ÏÎµÏÎ¹ÎŒÎ­ÎœÎµÏÎµ Î³Î¹Î± Î¬Î»Î»Î¿ ÏÏÏÎ¿?  # Updated 1-Apr-2005
+#
+#***** Sources *****
+Source.General:ÎÎµÎœÎ¹ÎºÎ¬  # Updated 1-Apr-2005
+#*******************
+#
+#***** TitleClash *****
+TitleClashes.Message:Î ÏÎ¯ÏÎ»Î¿Ï ÏÎ¿Ï
+ Î­ÏÎµÏ ÎµÏÎ¹Î»Î­ÎŸÎµÎ¹ Î³Î¹Î± ÏÎ· ÏÏ
+Î»Î»Î¿Î³Î® ÏÏÎ·ÏÎ¹ÎŒÎ¿ÏÎ¿Î¹ÎµÎ¯ÏÎ±Î¹. ÎÎ± ÏÏ
+ÎœÎµÏÎ¯ÏÏ?  # Updated 1-Apr-2005
+TitleClashes.Title:Î ÏÎ¯ÏÎ»Î¿Ï ÏÏÎ·ÏÎ¹ÎŒÎ¿ÏÎ¿Î¹ÎµÎ¯ÏÎ±Î¹  # Updated 1-Apr-2005
+#**********************
+#
+#***** Trees *****
+Tree.DownloadedFiles:ÎÎ±ÏÎµÎ²Î±ÏÎŒÎ­ÎœÎ± ÎÏÏÎµÎ¯Î±  # Updated 1-Apr-2005
+Tree.Files:Î±ÏÏÎµÎ¯Î±  # Updated 1-Apr-2005
+Tree.Home:Home Folder ({0})  # Updated 1-Apr-2005
+Tree.Root:Î€Î¿ÏÎ¹ÎºÏÏ ÏÏÏÎ¿Ï Î±ÏÏÎµÎ¯ÏÎœ  # Updated 1-Apr-2005
+Tree.World:ÎÎ³Î³ÏÎ±ÏÎ± ÏÏÎ¹Ï ÏÏ
+Î»Î»Î¿Î³Î­Ï ÏÎ¿Ï
+ Greenstone  # Updated 1-Apr-2005
+#***********************
+#
+#***** Warning Dialog *****
+WarningDialog.Dont_Show_Again:ÎÎ± ÎŒÎ·Îœ ÎŸÎ±ÎœÎ±ÎµÎŒÏÎ±ÎœÎ¹ÏÏÎµÎ¯ Î±Ï
+ÏÏÏ Î¿ ÎŽÎ¹Î¬Î»Î¿Î³Î¿Ï  # Updated 1-Apr-2005
+WarningDialog.Dont_Show_Again_Message:ÎÎ± ÎŒÎ·Îœ ÎŸÎ±ÎœÎ±ÎµÎŒÏÎ±ÎœÎ¹ÏÏÎµÎ¯ Î±Ï
+ÏÏ ÏÎ¿ ÎŒÎ®ÎœÏ
+ÎŒÎ±  # Updated 1-Apr-2005
+WarningDialog.Invalid_Value:Î ÏÎ¹ÎŒÎ® ÏÎ¿Ï
+ Î­ÏÎµÏÎµ Î²Î¬Î»ÎµÎ¹ ÎŽÎµÎœ ÎµÎ¯ÎœÎ±Î¹\nÎ­Î³ÎºÏ
+ÏÎ· Î³Î¹Î± ÏÎ·Îœ ÎºÎ±ÎžÎ¿ÏÎ¹ÏÎŒÎ­ÎœÎ· Î¹ÎŽÎ¹ÏÏÎ·ÏÎ±.  # Updated 1-Apr-2005
+WarningDialog.Value:ÎÎ¹ÏÎ¬Î³ÎµÏÎµ ÏÎ¹ÎŒÎ®:  # Updated 1-Apr-2005
+#
+#****** WGet *****
+WGet.Prompt:WGet ÏÏÏÎ³ÏÎ±ÎŒÎŒÎ± Î³Î¹Î± Mirroring  # Updated 1-Apr-2005
+#
+#****** Workflows *****
+Workflow.AllPanels:ÎÎ»Î± ÏÎ± panels
+Workflow.LocalSourceCollectionBuilding:ÎÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³Î¯Î± ÏÎ¿ÏÎ¹ÎºÎ®Ï ÏÏ
+Î»Î»Î¿Î³Î®Ï
+Workflow.DocumentEnriching:ÎÎŒÏÎ»Î¿Ï
+ÏÎ¹ÏÎŒÏÏ Î±ÏÏÎµÎ¯ÏÎœ
+
+GEMS.Already_Loaded_Set_Error:Î€Î¿ ÏÏÎœÎ¿Î»Î¿ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ ÏÎ¿Ï
+ ÎµÏÎ¹Î»Î­ÎŸÎ±ÏÎµ ÎµÎ¯ÎœÎ±Î¹ Î±ÎœÎ¿Î¹ÏÏÏ.  # Updated 1-Apr-2005
+GEMS.Element_Already_Exists:ÎÎœÎ±Ï ÏÏÎ¿Ï ÎŒÎµ Î±Ï
+ÏÏ ÏÎ¿ ÏÎœÎ¿ÎŒÎ± Ï
+ÏÎ¬ÏÏÎµÎ¹ Î®ÎŽÎ·.  # Updated 1-Apr-2005
+GEMS.Set_Already_Exists:ÎÎœÎ± ÏÏÎœÎ¿Î»Î¿ ÎŒÎµ Î±Ï
+ÏÏ ÏÎ¿ ÏÎœÎ¿ÎŒÎ± Ï
+ÏÎ¬ÏÏÎµÎ¹ Î®ÎŽÎ·.  # Updated 1-Apr-2005
+GEMS.Cannot_Delete_Core_Sets_Error:ÎÎµ ÎŒÏÎ¿ÏÎµÎ¯ÏÎµ ÎœÎ± ÎŽÎ¹Î±Î³ÏÎ¬ÏÎµÏÎµ Î­ÎœÎ± ÏÏÎœÎ¿Î»Î¿ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ ÏÏ
+ÏÎ®ÎœÎ±.  # Updated 1-Apr-2005
+
+GEMS.Preferences.Selected_Languages_Tooltip:ÎÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎµÏ Î³Î»ÏÏÏÎµÏ Î³Î¹Î± ÏÏÎ¿Î²Î¿Î»Î®:  # Updated 1-Apr-2005
+
+GEMS.Add_Attribute:Î ÏÎ¿ÏÎžÎ®ÎºÎ· attribute  # Updated 1-Apr-2005
+GEMS.Add_Attribute_Tooltip:Î ÏÎ¿ÏÎžÎ­ÏÏÎµ Î­ÎœÎ± ÎœÎ­Î¿ attribute ÏÏÎ¿Îœ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿ ÏÏÎ¿  # Updated 1-Apr-2005
+GEMS.Add_Element:Î ÏÎ¿ÏÎžÎ®ÎºÎ· ÏÏÎ¿Ï
+  # Updated 1-Apr-2005
+GEMS.Add_Element_Tooltip:Î ÏÎ¿ÏÎžÎ­ÏÏÎµ Î­ÎœÎ± ÎœÎ­Î¿ ÏÏÎ¿ ÏÏÎ¿ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿ ÏÏÎœÎ¿Î»Î¿  # Updated 1-Apr-2005
+GEMS.Add_Subelement:Î ÏÎ¿ÏÎžÎ®ÎºÎ· Ï
+ÏÎ¿-ÏÏÎ¿Ï
+  # Updated 1-Apr-2005
+GEMS.Add_Subelement_Tooltip:Î ÏÎ¿ÏÎžÎ­ÏÏÎµ Î­ÎœÎ±Îœ Ï
+ÏÎ¿-ÏÏÎ¿ ÏÏÎ¿Îœ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿ ÏÏÎ¿  # Updated 1-Apr-2005
+GEMS.Add_Set:Î ÏÎ¿ÏÎžÎ®ÎºÎ· Î£Ï
+ÎœÏÎ»Î¿Ï
+  # Updated 1-Apr-2005
+GEMS.Attribute:Attribute  # Updated 1-Apr-2005
+GEMS.Attribute_Already_Exists:ÎÏ
+ÏÏ ÏÎ¿ attribute Ï
+ÏÎ¬ÏÏÎµÎ¹ Î®ÎŽÎ·.  # Updated 1-Apr-2005
+GEMS.Attribute_Name_Tooltip:Î€Î¿ ÏÎœÎ¿ÎŒÎ± ÏÎ¿Ï
+ ÎœÎ­Î¿Ï
+ attribute  # Updated 1-Apr-2005
+GEMS.Attribute_Language_Tooltip:Î Î³Î»ÏÏÏÎ± ÏÎ¿Ï
+ ÎœÎ­Î¿Ï
+ attribute  # Updated 1-Apr-2005
+GEMS.Attribute_Value_Tooltip:Î ÏÎ¹ÎŒÎ® ÏÎ¿Ï
+ ÎœÎ­Î¿Ï
+ attribute  # Updated 1-Apr-2005
+GEMS.Attributes:Attributes  # Updated 1-Apr-2005
+GEMS.Cannot_Undo:(Î±Ï
+ÏÎ® Î· ÎµÎœÎ­ÏÎ³ÎµÎ¹Î± ÎŽÎµ ÎŒÏÎ¿ÏÎµÎ¯ ÎœÎ± Î±ÎœÎ±Î¹ÏÎµÎžÎµÎ¯)  # Updated 1-Apr-2005
+GEMS.Cannot_Add_Elements_To_Greenstone_MDS:ÎÎµÎœ ÎŒÏÎ¿ÏÎµÎ¯ÏÎµ ÎœÎ± ÎµÎ¹ÏÎ¬Î³ÎµÏÎµ ÏÏÎ¿Ï
+Ï ÏÏÎ¿ ÏÏÎœÎ¿Î»Î¿ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ ÏÎ¿Ï
+ GS. ÎÎœ Î±ÏÎ±Î¹ÏÎµÎ¯ÏÎ±Î¹ ÎŽÎ·ÎŒÎ¹Î¿Ï
+ÏÎ³ÎµÎ¯ÏÏÎµ Î­ÎœÎ± ÎœÎ­Î¿ ÏÏÎœÎ¿Î»Î¿.
+GEMS.Confirm_Exit_Save:ÎÎ­Î»ÎµÏÎµ ÎœÎ± Î±ÏÎ¿ÎžÎ·ÎºÎµÏÏÎµÏÎµ ÏÏÎ¹Îœ ÏÎ·Îœ Î­ÎŸÎ¿ÎŽÎ¿?
+GEMS.Confirm_Exit_Save_Title:ÎÏÎ¿ÎžÎ®ÎºÎµÏ
+ÏÎ· ÏÏÎ¹Îœ ÏÎ·Îœ Î­ÎŸÎ¿ÎŽÎ¿?
+GEMS.Confirm_Removal:ÎÎ¯ÏÏÎµ ÏÎ¯Î³Î¿Ï
+ÏÎ¿Ï ÏÏÎ¹ ÎžÎ­Î»ÎµÏÎµ ÎœÎ± ÎŽÎ¹Î±Î³ÏÎ¬ÏÎµÏÎµ ÏÎ¿ {0}?
+GEMS.Confirm_Removal_Title:ÎÏÎ¹Î²ÎµÎ²Î±Î¯ÏÏÎ· ÎŽÎ¹Î±Î³ÏÎ±ÏÎ®Ï
+GEMS.Edit_Attribute:ÎÏÎµÎŸÎµÏÎ³Î±ÏÎ¯Î± ÏÎ±ÏÎ±ÎºÏÎ·ÏÎ¹ÏÏÎ¹ÎºÎ¿Ï
+GEMS.Edit_Value:ÎÏÎµÎŸÎµÏÎ³Î±ÏÎ¯Î± ÏÎ¹ÎŒÎ®Ï
+GEMS.Edit_Value_Tooltip:ÎÎ»Î»Î±Î³Î® ÏÎ·Ï ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ·Ï ÏÎ¹ÎŒÎ®Ï
+GEMS.Element:ÎÏÎ¿Ï
+GEMS.Element_Name_Tooltip:Î€Î¿ ÏÎœÎ¿ÎŒÎ± ÏÎ¿Ï
+ ÎœÎ­Î¿Ï
+ ÏÏÎ¿Ï
+
+GEMS.Element_Details:ÎÎµÏÏÎ¿ÎŒÎ­ÏÎµÎ¹ÎµÏ ÏÎ¿Ï
+ ÏÏÎ¿Ï
+ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ
+GEMS.Language:ÎÎ»ÏÏÏÎ±
+GEMS.Language_Code:ÎÎ»ÏÏÏÎ±
+GEMS.Name:ÎÎœÎ¿ÎŒÎ±
+GEMS.Namespace:Î§ÏÏÎ¿Ï ÎÎœÎ¿ÎŒÎ¬ÏÏÎœ
+GEMS.New_Name:ÎÎ­Î¿ ÏÎœÎ¿ÎŒÎ±
+GEMS.No_Description:ÎÎµÎœ Î²ÏÎ­ÎžÎ·ÎºÎµ ÏÎµÏÎ¹Î³ÏÎ±ÏÎ®.
+GEMS.No_Name:ÎÎµÎœ Î²ÏÎ­ÎžÎ·ÎºÎµ ÏÎœÎ¿ÎŒÎ±.
+GEMS.Open_Set:ÎÎœÎ¿Î¹Î³ÎŒÎ± Î£Ï
+ÎœÏÎ»Î¿Ï
+
+GEMS.Remove_Attribute:ÎÎ¹Î±Î³ÏÎ±ÏÎ® ÏÎ±ÏÎ±ÎºÏÎ·ÏÎ¹ÏÏÎ¹ÎºÎ¿Ï
+GEMS.Remove_Attribute_Tooltip:ÎÎ¹Î±Î³ÏÎ¬ÏÎµÎ¹ ÏÎ¿ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿ ÏÎ±ÏÎ±ÎºÏÎ·ÏÎ¹ÏÏÎ¹ÎºÏ.
+GEMS.Remove_Element:ÎÎ¹Î±Î³ÏÎ±ÏÎ® ÏÏÎ¿Ï
+
+GEMS.Remove_Element_Tooltip:ÎÎ¹Î±Î³ÏÎ¬ÏÎµÎ¹ ÏÎ¿Îœ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿ ÏÏÎ¿ Î±ÏÏ ÏÎ¿ ÏÏÎœÎ¿Î»Î¿
+GEMS.Remove_Set:ÎÎ¹Î±Î³ÏÎ±ÏÎ® ÏÏ
+ÎœÏÎ»Î¿Ï
+.
+GEMS.Remove_Set_Tooltip:ÎÎ¹Î±Î³ÏÎ¬ÏÎµÎ¹ ÏÎ¿ ÎµÏÎ¹Î»ÎµÎ³ÎŒÎ­ÎœÎ¿ ÏÏÎœÎ¿Î»Î¿
+GEMS.Rename_Element:ÎÎµÏÎ¿ÎœÎ¿ÎŒÎ±ÏÎ¯Î± ÏÏÎ¿Ï
+
+GEMS.Rename_Element_Tooltip:Î€Î¿ ÎœÎ­Î¿ ÏÎœÎ¿ÎŒÎ± ÏÎ¿Ï
+ ÏÏÎ¿Ï
+
+GEMS.Rename_Name_Tooltip:Î€Î¿ ÎœÎ­Î¿ ÏÎœÎ¿ÎŒÎ± ÏÎ¿Ï
+ ÏÏ
+ÎœÏÎ»Î¿Ï
+ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ
+GEMS.Rename_Namespace_Tooltip:Î ÎŒÎ¿ÎœÎ±ÎŽÎ¹ÎºÏÏ ÏÏÏÎ¿Ï Î¿ÎœÎ¿ÎŒÎ¬ÏÏÎœ ÏÎ¿Ï
+ ÏÏ
+ÎœÏÎ»Î¿Ï
+ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ
+GEMS.Rename_Set:ÎÎµÏÎ¿ÎœÎ¿ÎŒÎ±ÏÎ¯Î± ÏÏ
+ÎœÏÎ»Î¿Ï
+
+GEMS.Rename_Set_Tooltip:ÎÎµÏÎ¿ÎœÎ¿ÎŒÎ¬ÏÏÎµ ÏÎ¿ ÏÏÎœÎ¿Î»Î¿ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ
+GEMS.Set:Î£ÏÎœÎ¿Î»Î¿
+GEMS.Set_Details:ÎÎµÏÏÎ¿ÎŒÎ­ÏÎµÎ¹ÎµÏ ÏÏ
+ÎœÏÎ»Î¿Ï
+
+GEMS.Set_Name_Tooltip:Î€Î¿ ÏÎœÎ¿ÎŒÎ± ÏÎ¿Ï
+ ÎœÎ­Î¿Ï
+ ÏÏ
+ÎœÏÎ»Î¿Ï
+ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ
+GEMS.Set_Namespace_Tooltip:ÎÎœÎ±Ï ÎŒÎ¿ÎœÎ±ÎŽÎ¹ÎºÏÏ ÏÏÏÎ¿Ï Î¿ÎœÎ¿ÎŒÎ¬ÏÏÎœ Î³Î¹Î± ÏÎ¿ ÎœÎ­Î¿ ÏÏÎœÎ¿Î»Î¿
+GEMS.Subelement_Name_Tooltip:Î€Î¿ ÏÎœÎ¿ÎŒÎ± ÏÎ¿Ï
+ ÎœÎ­Î¿Ï
+ Ï
+ÏÎ¿ÏÏÎ¿Ï
+
+GEMS.Subelement_Already_Exists:Î¥ÏÎ¬ÏÏÎµÎ¹ Î®ÎŽÎ· Î­ÎœÎ±Ï Ï
+ÏÎ¿ÏÏÎ¿Ï ÎŒÎµ Î±Ï
+ÏÏ ÏÎ¿ ÏÎœÎ¿ÎŒÎ±.
+GEMS.Target:ÎÏÎ¿Ï
+GEMS.Title:ÎÏÎµÎŸÎµÏÎ³Î±ÏÏÎ®Ï Î³Î¹Î± ÏÏÎœÎ¿Î»Î± ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ
+GEMS.Value:Î€Î¹ÎŒÎ®
+GEMS.Values:Î€Î¹ÎŒÎ­Ï
+GEMS.inheritMetadataSet:ÎÎ»Î·ÏÎ¿ÎœÏÎŒÎ·ÏÎµ Î±ÏÏ ÏÎ¿ ÏÏÎœÎ¿Î»Î¿ ÎŒÎµÏÎ±ÎŽÎµÎŽÎ¿ÎŒÎ­ÎœÏÎœ:
+GEMS.Add_Set.No_Inherit:ÎÎ·Îœ ÎºÎ»Î·ÏÎ¿ÎœÎ¿ÎŒÎµÎ¯Ï
Index: /tags/greenstone-3_02-distribution/gli/classes/dictionary_es.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gli/classes/dictionary_es.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/classes/dictionary_es.properties	(revision 13928)
@@ -0,0 +1,1080 @@
+#*******************
+#
+#***** AboutDialog *****
+AboutDialog.Acknowledgement:Reconocimientos de marca de paquetes, clases y programas propietarios...
+AboutDialog.Date:(Diciembre 2006)
+AboutDialog.Item0:Xerces Java 1' de The Apache Software Foundation (http://www.apache.org/)
+AboutDialog.Item2:WGet' de Free Software Foundation, Inc. (http://www.gnu.org/software/wget/wget.html)
+AboutDialog.Item3:qflib' de Quality First Software GmbH. (http://www.qfs.de/en/qflib/index.html)
+AboutDialog.Item4:ExtensionFileFilter.class', por Bruno Dumon y asociados (http://pollo.sourceforge.net/)
+AboutDialog.Item5:How to disable file renaming in file chooser' - vladi21 (http://www.experts-exchange.com/)
+AboutDialog.Item6:Autoscrolling' - Java Swing, por Robert Eckstein, Marc Loy & Dave Wood (http://www.oreilly.com/catalog/jswing/chapter/dnd.beta.pdf)
+AboutDialog.Item7:Add ghosted drag images to your JTrees', por Andrew J. Armstrong (http://www.javaworld.com/javaworld/javatips/jw-javatip114.html)
+AboutDialog.Item8:Stop annoying java.prefs error when you don't have superuser access', cortesÃ­a de Walter Schatz
+AboutDialog.Java_Req:Java es una marca registrada de Sun Microsystems Inc. El Ambiente de EjecuciÃ³n Java (JRE por sus siglas en inglÃ©s) se distribuye de acuerdo a los tÃ©rminos de la licencia suplementaria que se encuentra en http://java.sun.com/j2se/1.4.1/j2re-1_4_1_02-license.html
+AboutDialog.Java_Req_One:Este producto incluye un cÃ³digo con licencia de uso de RSA Security, Inc.
+AboutDialog.Java_Req_Two:Algunas partes con licencia de IBM estÃ¡n disponibles en http\://oss.software.ibm.com/icu4j/
+AboutDialog.Thanks:TambiÃ©n queremos agradecer a todos aquellos que nos proporcionaron su valiosa informaciÃ³n sobre Java a travÃ©s de la Web...
+AboutDialog.Title:Acerca de...
+AboutDialog.Title_One:Interfaz de la Biblioteca Digital Greenstone
+AboutDialog.Title_Two:Biblioteca Digital Greenstone, Universidad de Waikato
+AboutDialog.Copyright:Copyright (C) 2006 New Zealand Digital Library Project
+AboutDialog.Copyright_Two:Publicado conforme a los tÃ©rminos y condiciones de la Licencia PÃºblica General. Para mayor informaciÃ³n vea LICENSE.txt
+#***********************
+#
+#***** Audit Table *****
+AuditTable.File:Nombre del archivo
+#***********************
+#
+#***** Auto Filter *****
+Autofilter.AND:Y
+Autofilter.Ascending:Ascendente
+Autofilter.Case_Sensitive:Concordancia de caso
+Autofilter.Custom_Filter:Avanzada
+Autofilter.Descending:Descendente
+Autofilter.Filter_By_Value:Sencilla
+Autofilter.Name:TÃ­tulo de la columna
+Autofilter.None:Ninguno
+Autofilter.Operator:CondiciÃ³n
+Autofilter.OR:O
+Autofilter.Order:Ordenar
+Autofilter.Order_Tooltip:Clasifica los elementos en este orden
+Autofilter.Remove:Eliminar filtro
+Autofilter.Remove_Tooltip:Quita este filtro de la columna
+Autofilter.Set:Filtrar
+Autofilter.Set_Tooltip:AÃ±ade este filtro a la columna
+Autofilter.Table_Header_Tooltip:Filtrar por {0}
+Autofilter.Title:Filtrar metadatos
+Autofilter.eqeq:igual a
+Autofilter.!eq:does not equal
+Autofilter.<:is less than
+Autofilter.<eq:is less than or equal to
+Autofilter.>:is greater than
+Autofilter.>eq:is greater than or equal to
+Autofilter.^:starts with
+Autofilter.!^:does not start with
+Autofilter.$:ends with
+Autofilter.!$:does not end with
+Autofilter.?:contains
+Autofilter.!?:does not contain
+#
+#     ********************************************************
+#     *************** Collection Design Module ***************
+#     ********************************************************
+#     * The dictionary  phrases  used in the creation of the *
+#     * Colection  Design  Module. Note that we  still  have *
+#     * access  to the format  arguments (argument  32+) for *
+#     * html formatting.                                     *
+#     ********************************************************
+CDM.ArgumentConfiguration.Add:AÃ±adir
+CDM.ArgumentConfiguration.Bad_Integer:<html>El argumento '{0}' requiere un nÃºmero entero,<br>pero no se puede obtener ningÃºn entero de {1}.</html>
+CDM.ArgumentConfiguration.Custom_Header:A la medida
+CDM.ArgumentConfiguration.Custom:Argumentos personalizados:
+CDM.ArgumentConfiguration.Error_Title:Error en los argumentos
+CDM.ArgumentConfiguration.Header:<HTML><STRONG><FONT FACE={FONT} COLOR=Black SIZE=5><CENTER>Por favor, configure los argumentos para {0}.</CENTER></FONT></STRONG></HTML>
+CDM.ArgumentConfiguration.No_Value:El argumento â{0}â requiere un valor, pero no se ha especificado ninguno.
+CDM.ArgumentConfiguration.Remove:Eliminar
+CDM.ArgumentConfiguration.Required_Argument:El argumento '{0}' deberÃ¡ ser un valor dado.
+CDM.ArgumentConfiguration.Title:Configurando argumentos
+CDM.BuildTypeManager.Title:Seleccionar el Indizador  # Updated 16-Aug-2006
+CDM.BuildTypeManager.mg:MG  # Updated 16-Aug-2006
+CDM.BuildTypeManager.mg_Description:Este es el indizador original utilizado por Greenstone, desarrollado por Alistair Moffat y descrito en el clÃ¡sico libro <i>Managing Gigabytes</i>. realzia indizaciÃ³n a nivel de secciÃ³n, y las bÃºsquedas pueden ser booleanas o por relevancia (no ambas a la vez). Para cada Ã­ndice especificado en la colecciÃ³n, se crea un Ã­ndice fÃ­sico separado. Para bÃºsqueda por frases, Greenstone aÃ±ade un "Y" para cada tÃ©rmino, y explora los resultados para ver si la frase estÃ¡ presente. Ha sido probado intensivamente en grandes colecciones (muchos GB de texto).  # Updated 16-Aug-2006
+CDM.BuildTypeManager.mgpp:MGPP  # Updated 16-Aug-2006
+CDM.BuildTypeManager.mgpp_Description:Esta nueva versiÃ³n de MP (MG plus plus) fuÃ© desarrollada por el New Zealand Digital Library Project. Hace la indizaciÃ³n a nivel de palabra, lo que permite bÃºsquedas por campo, frase y proximidad. Las bÃºsquedas booleanas pueden ser ordenadas por relevancia. SÃ³lo se crea un Ã­ndice para la colecciÃ³n: los niveles de documento/secciÃ³n y texto/campos de metadatos se gestionan en un Ãºnico Ã­ndice. Para colecciones con muchos Ã­ndices, esto ofrece una colecciÃ³n de tamaÃ±o menor que el obtenido usando MG. Para grandes colecciones, la bÃºsqueda puede ser un poco mÃ¡s lenta debido a la indizaciÃ³n a nivel de palabra.  # Updated 16-Aug-2006
+CDM.BuildTypeManager.lucene:Lucene  # Updated 16-Aug-2006
+CDM.BuildTypeManager.lucene_Description:Lucene fuÃ© desarrollado por la Apache Software Foundation. Ofrece bÃºsquedas por campo y de proximidad, pero sÃ³lo a nivel simple (por ej., documentos completos o secciones individuales, pero no ambos al mismo tiempo). Por lo tanto, una colecciÃ³n con Ã­ndices de documento y de secciÃ³n requiere dos Ã­ndices separados. Ofrece funcionalidades de bÃºsqueda similares a MGPP, aÃ±adiendo truncamiento de caracteres Ãºnicos y bÃºsqueda de rango. Se ha aÃ±adido a Greenstone para hacer posible la creaciÃ³n incremental de colecciones, que MG y MGPP no ofrecen.  # Updated 16-Aug-2006
+CDM.BuildTypeManager.Current_Type:Utilizando el indizador: {0}  # Updated 16-Aug-2006
+CDM.BuildTypeManager.Change:Cambiar...  # Updated 16-Aug-2006
+CDM.BuildTypeManager.Change_Tooltip:Cambiar el indizador utilizado en esta colecciÃ³n  # Updated 16-Aug-2006
+CDM.ClassifierManager.Add:AÃ±adir clasificador...
+CDM.ClassifierManager.Add_Tooltip:Utilice el clasificador especificado con esta colecciÃ³n
+CDM.ClassifierManager.Assigned:Clasificadores asignados actualmente
+CDM.ClassifierManager.Classifier:Seleccione el clasificador que se va a aÃ±adir:
+CDM.ClassifierManager.Classifier_Tooltip:Son los clasificadores disponibles para esta colecciÃ³n
+CDM.ClassifierManager.Classifier_Exists:Ese clasificador ya se le ha asignado a esta colecciÃ³n.
+CDM.ClassifierManager.Classifier_Str:clasificador
+CDM.ClassifierManager.Classifier_XML_Parse_Failed:Imnposible determinar los argumentos del clasificador {0}\n. Por favor, asegÃºrese que el clasificador\n contiene el indicador -xml ejecutando el guiÃ³n classinfo.pl\n, el cual es similar a la descripciÃ³n del guiÃ³n pluginfo.pl que se encuentra en\n la secciÃ³n 2.1 de la GuÃ­a del Programador de Greenstone.  # Updated 29-Jan-2006
+CDM.ClassifierManager.Configure:Configurar clasificador...
+CDM.ClassifierManager.Configure_Tooltip:Cambia las opciones del clasificador seleccionado
+CDM.ClassifierManager.Remove:Eliminar clasificador
+CDM.ClassifierManager.Remove_Tooltip:Elimina el clasificador seleccionado de la lista
+CDM.ClassifierManager.Parsing.Message:Cargando la informaciÃ³n sobre el clasificador...  # Updated 16-Aug-2006
+CDM.ClassifierManager.Parsing.Title:Cargando clasificadores
+CDM.FormatManager.Add:AÃ±adir formato
+CDM.FormatManager.Add_Tooltip:AÃ±ade la orden de formato especificada  # Updated 16-Aug-2006
+CDM.FormatManager.AllFeatures:Todas las CaraterÃ­sticas  # Updated 16-Aug-2006
+CDM.FormatManager.AllParts:Todos los Componentes  # Updated 16-Aug-2006
+CDM.FormatManager.Assigned_Formats:Ãrdenes de formato asignados actualmente.  # Updated 29-Jan-2006
+CDM.FormatManager.Default:Reset to Default
+CDM.FormatManager.Default_Tooltip:Reset the selected format command to its default value 
+CDM.FormatManager.Editor:Cadena de formato HTML
+CDM.FormatManager.Editor_Tooltip:Introduzca o edite la orden de formato  # Updated 16-Aug-2006
+CDM.FormatManager.Editor_Disabled_Tooltip:Pulse 'AÃ±adir Formato' para aÃ±adir esta orden de formato a su colecciÃ³n.  # Updated 16-Aug-2006
+CDM.FormatManager.Enabled:Activo
+CDM.FormatManager.Feature:Elegir funciÃ³n
+CDM.FormatManager.Feature_Tooltip:Es la funciÃ³n a la que se darÃ¡ formato
+CDM.FormatManager.Insert:Insertar
+CDM.FormatManager.Insert_Tooltip:Inserta la variable seleccionada en la orden de formato  # Updated 29-Jan-2006
+CDM.FormatManager.Default:Reset to Default
+CDM.FormatManager.Default_Tooltip:Reset the selected format command to its default value
+CDM.FormatManager.Part:Componente afectado
+CDM.FormatManager.Part_Tooltip:Es el aspecto del componente afectado al que se va a dar formato
+CDM.FormatManager.Remove:Eliminar formato
+CDM.FormatManager.Remove_Tooltip:Elimina la orden de formato seleccionada  # Updated 16-Aug-2006
+CDM.FormatManager.Replace:Reemplazar formato
+CDM.FormatManager.Replace_Tooltip:Actualiza la orden de formato seleccionado  # Updated 29-Jan-2006
+CDM.FormatManager.Variable:Variables
+CDM.FormatManager.Variable_Tooltip:Son las variables disponibles para la orden de formato  # Updated 29-Jan-2006
+CDM.General.Access:La colecciÃ³n serÃ¡ de acceso pÃºblico
+CDM.General.Browser_Title:Seleccione una imagen
+CDM.General.Collection_Extra:DescripciÃ³n de la colecciÃ³n:
+CDM.General.Collection_Extra_Tooltip:Es una descripciÃ³n del propÃ³sito y los contenidos de la colecciÃ³n
+CDM.General.Collection_Name:TÃ­tulo de la colecciÃ³n:
+CDM.General.Collection_Name_Tooltip:Es el nombre de la colecciÃ³n
+CDM.General.Email.Creator:E-mail del creador de la colecciÃ³n
+CDM.General.Email.Creator_Tooltip:es la direcciÃ³n de e-mail del creador de la colecciÃ³n
+CDM.General.Email.Maintainer:E-mail del administrador de la colecciÃ³n
+CDM.General.Email.Maintainer_Tooltip:Es la direcciÃ³n de e-mail del administrador de la colecciÃ³n
+CDM.General.Icon_Collection:URL del icono de la pÃ¡gina 'acerca de':  # Updated 16-Aug-2006
+CDM.General.Icon_Collection_Tooltip:Es el URL de la imagen que aparecerÃ¡ en la pÃ¡gina "Acerca de" de la biblioteca digital
+CDM.General.Icon_Collection_Small:URL del icono de la 'pÃ¡gina principal':  # Updated 16-Aug-2006
+CDM.General.Icon_Collection_Small_Tooltip:URL de la imagen para la colecciÃ³n, que aparecerÃ¡ en la pÃ¡gina principal de la biblioteca  # Updated 16-Aug-2006
+CDM.General.Image_Copy_Failed:Ha ocurrido un error que evita que la imagen que usted seleccionÃ³ sea copiada.\n Por favor trate de copiarla manualmente: :\n{0}\n en la carpeta de imÃ¡genes de su colecciÃ³n:\n{1}.  # Updated 27-Mar-2006
+CDM.General.Image_Filter:ImÃ¡genes (gifs, jpgs y pngs)
+CDM.GUI.Classifiers:Clasificadores de exploraciÃ³n
+CDM.GUI.Design_Topics:Secciones de diseÃ±o
+CDM.GUI.Formats:Formatos
+CDM.GUI.General:General
+CDM.GUI.Indexes:Ãndices de bÃºsqueda
+CDM.GUI.Macros:Macros EspecÃ­ficos de ColecciÃ³n  # Updated 16-Aug-2006
+CDM.GUI.MetadataSets:Conjuntos de metadatos
+CDM.GUI.Plugins:Plugins de documento
+CDM.GUI.Root:CDM_ROOT
+CDM.GUI.SearchMetadata:Buscar  # Updated 16-Aug-2006
+CDM.GUI.Subcollections:Particionar Ã­ndices
+CDM.GUI.SuperCollection:BÃºsqueda cruzada a travÃ©s de varias colecciones
+CDM.GUI.Translation:Traducir texto
+CDM.HelpButton:Ayuda para esta pantalla  # Updated 29-Jan-2006
+CDM.HelpButton_Tooltip:Abra la ayuda de GLI para esta pantalla  # Updated 29-Jan-2006
+CDM.IndexManager.Add_Index:AÃ±adir Ã­ndice
+CDM.IndexManager.Add_Index_Tooltip:AÃ±ade el Ã­ndice especificado  # Updated 16-Aug-2006
+CDM.IndexManager.Allfields_Index:AÃ±adir bÃºsqueda combinada sobre todos los Ã­ndices asignados (todos los campos)  # Updated 16-Aug-2006
+CDM.IndexManager.Default_Index_Indicator:[Ãndice por omisiÃ³n]
+CDM.IndexManager.Index_Exists:Ese Ã­ndice ya se le ha asignado a esta colecciÃ³n.
+CDM.IndexManager.Indexes:Ãndices asignados
+CDM.IndexManager.Level:Nivel de IndizaciÃ³n:  # Updated 16-Aug-2006
+CDM.IndexManager.Level_Tooltip:Unidad textual sobre la que se basarÃ¡ el Ã­ndice  # Updated 16-Aug-2006
+CDM.IndexManager.Add_All:AÃ±adir Todo  # Updated 16-Aug-2006
+CDM.IndexManager.Add_All_Tooltip:AÃ±adir un Ã­ndice independiente para cada fuente  # Updated 16-Aug-2006
+CDM.IndexManager.Edit_Index:Editar Ãndice  # Updated 16-Aug-2006
+CDM.IndexManager.Edit_Index_Tooltip:Modificar el Ã­ndice seleccionado  # Updated 16-Aug-2006
+CDM.IndexManager.New_Index:Nuevo Ãndice  # Updated 16-Aug-2006
+CDM.IndexManager.New_Index_Tooltip:AÃ±adir un nuevo Ã­ndice  # Updated 16-Aug-2006
+CDM.IndexManager.Remove_Index:Eliminar Ã­ndice
+CDM.IndexManager.Remove_Index_Tooltip:Elimina el Ã­ndice seleccionado  # Updated 16-Aug-2006
+CDM.IndexManager.Replace_Index:Reemplazar Ãndice  # Updated 16-Aug-2006
+CDM.IndexManager.Replace_Index_Tooltip:Actualizar el Ã­ndice seleccionado  # Updated 16-Aug-2006
+CDM.IndexManager.Select_All:Seleccionar Todo  # Updated 16-Aug-2006
+CDM.IndexManager.Select_All_Tooltip:Seleccionar todas las fuentes de los Ã­ndices  # Updated 16-Aug-2006
+CDM.IndexManager.Select_None:No seleccionar ninguno  # Updated 16-Aug-2006
+CDM.IndexManager.Select_None_Tooltip:Desmarcar todas las fuentes de Ã­ndices  # Updated 16-Aug-2006
+CDM.IndexManager.Set_Default:Establecer un Ã­ndice por omisiÃ³n
+CDM.IndexManager.Set_Default_Tooltip:Hace que el Ã­ndice seleccionado sea el Ã­ndice por omisiÃ³n
+CDM.IndexManager.Source:Incluir en el Ã­ndice:  # Updated 16-Aug-2006
+CDM.IndexManager.Source_Tooltip:Son los elementos de metadato sobre los que se crearÃ¡ el Ã­ndice
+CDM.IndexManager.Text_Source:Texto completo  # Updated 16-Aug-2006
+CDM.IndexManager.Text_Source_Tooltip:Incluir el texto completo de los documentos en el Ã­ndice  # Updated 16-Aug-2006
+CDM.LanguageManager.Add_Tooltip:AÃ±ade una particiÃ³n de Ã­ndice basada en los lenguajes especificados  # Updated 16-Aug-2006
+CDM.LanguageManager.Assigned_Languages:Particiones de lenguaje asignadas  # Updated 16-Aug-2006
+CDM.LanguageManager.Default_Language:Idioma predeterminado
+CDM.LanguageManager.LanguageMetadata:Metadatos de Lenguaje:  # Updated 16-Aug-2006
+CDM.LanguageManager.LanguageMetadata_Tooltip:Elemento de metadato usado para determinar el lenguaje de un documento  # Updated 16-Aug-2006
+CDM.LanguageManager.Remove_Tooltip:Elimina el idioma seleccionado de la lista  # Updated 16-Aug-2006
+CDM.LanguageManager.Replace_Tooltip:Reemplazar la particiÃ³n seleccionada con una nueva basada en los lenguajes marcados  # Updated 16-Aug-2006
+CDM.LanguageManager.Selector:Idiomas que se van a aÃ±adir:  # Updated 16-Aug-2006
+CDM.LanguageManager.Selector_Tooltip:Idiomas sobre los que se va a crear una particiÃ³n de Ã­ndice  # Updated 16-Aug-2006
+CDM.LanguageManager.Set_Default:Predeterminar
+CDM.LanguageManager.Set_Default_Tooltip:Hace que el idioma seleccionado sea el idioma predefinido  # Updated 16-Aug-2006
+CDM.LevelManager.Document:documento  # Updated 16-Aug-2006
+CDM.LevelManager.Section:secciÃ³n  # Updated 16-Aug-2006
+CDM.LevelManager.Paragraph:pÃ¡rrafo  # Updated 16-Aug-2006
+CDM.LevelManager.Level:Nivel  # Updated 16-Aug-2006
+CDM.LevelManager.Level_Title:Niveles de IndizaciÃ³n  # Updated 16-Aug-2006
+CDM.LevelManager.Level_Tooltip:Unidades textuales en las que se basan los Ã­ndices  # Updated 16-Aug-2006
+CDM.LevelManager.Default:Predefinido  # Updated 16-Aug-2006
+CDM.LevelManager.Default_Tooltip:Nivel predefinido en la interfaz de lector  # Updated 16-Aug-2006
+CDM.MacrosManager.Save:Guardar  # Updated 16-Aug-2006
+CDM.MacrosManager.Save_Tooltip:Guardar en el fichero extra.dm de la colecciÃ³n  # Updated 16-Aug-2006
+CDM.MacrosManager.Revert:Revertir  # Updated 16-Aug-2006
+CDM.MacrosManager.Revert_Tooltip:Volver a la Ãºltima versiÃ³n guardada  # Updated 16-Aug-2006
+CDM.MacrosManager.Editor_Tooltip:Editar macros aquÃ­  # Updated 16-Aug-2006
+CDM.Move.At_Bottom:{0} {1} no se puede mover mÃ¡s abajo puesto que ya se encuentra al final de la lista.
+CDM.Move.At_Top:{0} {1} no se puede mover mÃ¡s arriba puesto que ya se encuentra al principio de la lista.
+CDM.Move.Cannot:El plugin {0} no se puede mover mÃ¡s abajo ya que RecPlug y ArcPlug deben estar al final de la lista.
+CDM.Move.Fixed:<html>Por regla general RecPlug y ArcPlug siempre deben estar al final.<br>Si por alguna razÃ³n tiene que moverlos de lugar, por favor edite manualmente el archivo collect.cfg.</html>
+CDM.Move.Move_Down:Mover abajo
+CDM.Move.Move_Down_Tooltip:Mueve el elemento seleccionado hacia abajo en la lista
+CDM.Move.Move_Up:Mover arriba
+CDM.Move.Move_Up_Tooltip:Mueve el elemento seleccionado hacia arriba en la lista
+CDM.Move.Title:Error - no se puede mover
+CDM.PlugInManager.Add:AÃ±adir plugin...
+CDM.PlugInManager.QuickAdd:AÃ±adir plugin
+CDM.PlugInManager.Add_Tooltip:Utilice el plugin especificado con esta colecciÃ³n
+CDM.PlugInManager.Assigned:Plugins asignados actualmente
+CDM.PlugInManager.Configure:Configurar un plugin...
+CDM.PlugInManager.Configure_Tooltip:Cambia las opciones del plugin seleccionado
+CDM.PlugInManager.Ignore:No Agregar Plugin
+CDM.PlugInManager.Ignore_Tooltip:No agregar ningÃºn Plugin a esta colecciÃ³n.
+CDM.PlugInManager.PlugIn:Seleccione el plugin que se va a aÃ±adir
+CDM.PlugInManager.PlugIn_Tooltip:Son los plugins disponibles para esta colecciÃ³n
+CDM.PlugInManager.PlugIn_Exists:Ese plugin ya se le ha asignado a esta colecciÃ³n.
+CDM.PlugInManager.PlugIn_Str:plugin
+CDM.PlugInManager.PlugIn_XML_Parse_Failed:Imposible determinar los argumentos para el plugin {0}\n. Por favor, asegÃºrese que el plugin contiene\nel indicador -xml ejecutando el guiÃ³n pluginfo.pl descrito\nen la secciÃ³n 2.1 de la GuÃ­a del Programador de Greenstone.  # Updated 29-Jan-2006
+CDM.PluginManager.Plugin_Suggestion_Prompt:Ninguno de los plugins de esta colecciÃ³n puede procesar el archivo "{0}". Para procesar este archivo pueden utilizarse los siguientes plugins. En este momento usted puede agregar uno a su colecciÃ³n, seleccionÃ¡ndolo y oprimiendo el botÃ³n Agregar. (Tenga en cuenta que en cualquier momento puede cambiar la lista de plugins dirigiÃ©ndose a "Document Plugins" en el Panel de DiseÃ±o.)
+CDM.PlugInManager.Remove:Eliminar plugin
+CDM.PlugInManager.Remove_Tooltip:Elimina el plugin seleccionado de la lista
+CDM.PluginManager.SuggestedPluginListTitle:Plugins sugeridos para el archivo
+CDM.PlugInManager.Parsing.Message:Cargando la informaciÃ³n del plugin...  # Updated 16-Aug-2006
+CDM.PlugInManager.Parsing.Title:Cargando Plugins
+CDM.SearchMetadataManager.Component:Elemento en el menÃº de bÃºsqueda  # Updated 16-Aug-2006
+CDM.SearchMetadataManager.Component_Name:Mostrar texto  # Updated 16-Aug-2006
+CDM.SearchMetadataManager.Type_index:Ãndice  # Updated 16-Aug-2006
+CDM.SearchMetadataManager.Type_level:Nivel  # Updated 16-Aug-2006
+CDM.SearchMetadataManager.Type_partition:ParticiÃ³n  # Updated 16-Aug-2006
+CDM.SearchMetadataManager.Type_language:ParticiÃ³n de Lenguaje  # Updated 16-Aug-2006
+CDM.SubcollectionManager.Add:AÃ±adir filtro
+CDM.SubcollectionManager.Add_Tooltip:AÃ±ade el filtro especificado a la colecciÃ³n
+CDM.SubcollectionManager.Assigned:Filtros definidos para la subcolecciÃ³n
+CDM.SubcollectionManager.Exclude:Excluir
+CDM.SubcollectionManager.Flags:Indicadores que se usarÃ¡n al momento de contrastar
+CDM.SubcollectionManager.Flags_Tooltip:Indicadores de expresiones regulares que se utilizarÃ¡n al momento de cotejar (p. ej. âiâ para comparaciones que no toman en cuenta el caso)
+CDM.SubcollectionManager.Include:Incluir
+CDM.SubcollectionManager.Inclusive:Â¿QuÃ© hacemos con los ficheros que concuerdan?  # Updated 16-Aug-2006
+CDM.SubcollectionManager.Language_Controls:Asignar idiomas
+CDM.SubcollectionManager.Match:ExpresiÃ³n regular con la que se contrastarÃ¡:
+CDM.SubcollectionManager.Match_Tooltip:Es una expresiÃ³n regular que define los documentos de la subcolecciÃ³n
+CDM.SubcollectionManager.Name:Nombre del filtro de la subcolecciÃ³n:
+CDM.SubcollectionManager.Name_Tooltip:Es el nombre del nuevo filtro de la subcolecciÃ³n
+CDM.SubcollectionManager.Partitions_Disabled:Este programa no estÃ¡ activo en este momento ya que usted estÃ¡ operando en el modo {0-Modo Actual}. Ãnicamente se puede tener acceso a Ã©l en los modos {1-Sistemas} y {2-Avanzado}. Utilice la opciÃ³n de Preferencias que se encuentra en el menÃº de Archivo para cambiar el modo de operaciÃ³n.
+CDM.SubcollectionManager.Remove:Eliminar filtro
+CDM.SubcollectionManager.Remove_Tooltip:Quita el filtro seleccionado de la lista
+CDM.SubcollectionManager.Replace:Reemplazar filtro
+CDM.SubcollectionManager.Replace_Tooltip:Actualiza los detalles del filtro seleccionado
+CDM.SubcollectionManager.Source:Atributo del documento con el cual se va a contrastar:
+CDM.SubcollectionManager.Source_Tooltip:Es el atributo con base en el cual se filtrarÃ¡n los documentos
+CDM.SubcollectionManager.Subcollection_Controls:Definir filtros
+CDM.SubcollectionManager.Subindex_Controls:Asignar particiones
+CDM.SubcollectionIndexManager.Add_Subindex:AÃ±adir particiÃ³n
+CDM.SubcollectionIndexManager.Add_Subindex_Tooltip:AÃ±ade la particiÃ³n especificada a esta colecciÃ³n
+CDM.SubcollectionIndexManager.Default_Partition_Indicator:[ParticiÃ³n por Defecto]
+CDM.SubcollectionIndexManager.Remove_Subindex:Eliminar particiÃ³n
+CDM.SubcollectionIndexManager.Remove_Subindex_Tooltip:Elimina la particiÃ³n seleccionada de esta colecciÃ³n
+CDM.SubcollectionIndexManager.Replace_Subindex:Remplazar ParticiÃ³n
+CDM.SubcollectionIndexManager.Replace_Subindex_Tooltip:Actualizar la particiÃ³n seleccionada
+CDM.SubcollectionIndexManager.Set_Default_Subindex:Predeterminar
+CDM.SubcollectionIndexManager.Set_Default_Subindex_Tooltip:Hace que la particiÃ³n seleccionada sea la particiÃ³n por omisiÃ³n
+CDM.SubcollectionIndexManager.Source:Construir particiÃ³n en:
+CDM.SubcollectionIndexManager.Source_Tooltip:Los filtros de la subcolecciÃ³n para construir la particiÃ³n en
+CDM.SubcollectionIndexManager.Subindexes:Particiones asignadas a la subcolecciÃ³n
+CDM.TranslationManager.Add:AÃ±adir traducciÃ³n
+CDM.TranslationManager.Add_Tooltip:AÃ±ade la traducciÃ³n especificada a la colecciÃ³n
+CDM.TranslationManager.Affected_Features:Funciones
+CDM.TranslationManager.Assigned_Fragments:Traducciones asignadas
+CDM.TranslationManager.Default_Text:Fragmento de texto inicial
+CDM.TranslationManager.Fragment_Column:Fragmento de texto
+CDM.TranslationManager.Language:Idioma de la traducciÃ³n
+CDM.TranslationManager.Language_Column:Idioma
+CDM.TranslationManager.Language_Tooltip:Es el idioma al que se traducirÃ¡
+CDM.TranslationManager.Remove:Eliminar traducciÃ³n
+CDM.TranslationManager.Remove_Tooltip:Quita la traducciÃ³n seleccionada de la colecciÃ³n
+CDM.TranslationManager.Replace:Reemplazar traducciÃ³n
+CDM.TranslationManager.Replace_Tooltip:Actualiza la traducciÃ³n seleccionada
+CDM.TranslationManager.Translation:Texto traducido
+CDM.TranslationManager.Translation_Tooltip:Escriba aquÃ­ la traducciÃ³n de la cadena de texto
+#*******************
+#
+#***** Collection *****
+Collection.Collection:<HTML><STRONG><FONT FACE={FONT} COLOR=Black>ColecciÃ³n</FONT></STRONG></HTML>
+Collection.Delete_Tooltip:Elimina los ficheros y carpetas seleccionados  # Updated 29-Jan-2006
+Collection.Filter_Tooltip:Limita el nÃºmero de ficheros mostrados en este Ã¡rbol de ficheros  # Updated 29-Jan-2006
+Collection.New_Folder_Tooltip:Crea una nueva carpeta
+Collection.No_Collection:No hay colecciÃ³n
+Collection.No_Collection_Loaded:ColecciÃ³n no cargada  # Updated 16-Aug-2006
+Collection.Stop:Detener
+Collection.Stop_Tooltip:Detiene la copia de los ficheros  # Updated 29-Jan-2006
+Collection.Workspace:<HTML><STRONG><FONT FACE={FONT} COLOR=Black>Ãrea de trabajo</FONT></STRONG></HTML>
+#**********************
+#
+#***** CollectionBuilt *****
+CollectionBuilt.Message:Se ha construido la colecciÃ³n y estÃ¡ lista para verse.
+CollectionBuilt.Title:Resultado del proceso de creaciÃ³n de la colecciÃ³n
+#***************************
+#
+#***** CollectionManager *****
+CollectionManager.Build_Cancelled:Se ha cancelado la construcciÃ³n de la colecciÃ³n.
+CollectionManager.Cannot_Create_Collection:Ha ocurrido un error y no se ha podido crear la colecciÃ³n
+CollectionManager.Cannot_Create_Collection_With_Reason:La colecciÃ³n no pudo crearse debido a:\n{0-Error message}  # Updated 29-Jan-2006
+CollectionManager.Cannot_Delete_Index:Esta colecciÃ³n no se puede reconstruir debido a que los ficheross de Ã­ndices anteriores no se pueden suprimir.\n Por favor asegÃºrese que Greenstone o algÃºn otro programa no estÃ¡ usando estos ficheros\n e intÃ©ntelo de nuevo.  # Updated 29-Jan-2006
+CollectionManager.Cannot_Delete_Index_Log:Los ficheros de Ã­ndices anteriores no se pudieron suprimir, por lo cual la importaciÃ³n se detuvo.  # Updated 29-Jan-2006
+CollectionManager.Cannot_Open:La colecciÃ³n en:\n{0-ruta del archivo de la colecciÃ³n}\n no se pudo abrir.
+CollectionManager.Cannot_Open_With_Reason:La colecciÃ³n en:\n{0-ruta de acceso al archivo de la colecciÃ³n}\n no pudo abrirse debido a:\n{1-mensaje de error}
+CollectionManager.Creating_New:Creando una nueva colecciÃ³n.
+CollectionManager.Log_Created:Se ha creado la carpeta de registro.
+CollectionManager.Loading_Collection:Cargando colecciÃ³n
+CollectionManager.Loading_Collection_Please_Wait:Cargando colecciÃ³n, espere por favorâŠ
+CollectionManager.Loading_Successful:ColecciÃ³n cargada {0}.
+CollectionManager.Missing_Config:Esta colecciÃ³n no cuenta con un archivo collect.cfg vÃ¡lido
+CollectionManager.Not_Col_File:{0}' no es un archivo de colecciÃ³n de la Interfaz de la Biblioteca Digital (.col)
+CollectionManager.No_Config_File:El fichero collect.cfg no ha sido creado por mkcol.pl  # Updated 29-Jan-2006
+CollectionManager.Preview_Ready_Failed:Ha ocurrido un error que evitarÃ¡ que la colecciÃ³n se pueda ver de forma preliminar.
+CollectionManager.Preview_Ready_Title:Vista preliminar de la colecciÃ³n.
+CollectionManager.Session_Ready:La colecciÃ³n {0} estÃ¡ lista para usarse.
+CollectionManager.Build_Not_Moved:El directorio building no podrÃ­a moverse.  # Updated 29-Jan-2006
+CollectionManager.Index_Not_Deleted:El directorio index podrÃ­a no ser borrado.  # Updated 29-Jan-2006
+CollectionManager.Install_Exception:Detectada una excepciÃ³n durante la instalaciÃ³n de la colecciÃ³n:\n{0}\nSeguramente causada por Windows o por bloqueos de la Biblioteca Local Greenstone.\nPor favor, asegÃºrese de que ninguno de los ficheros fuente de la colecciÃ³n\nse encuentran abiertos en aplicaciones externas, y entonces reconstruya la colecciÃ³n.  # Updated 29-Jan-2006
+#*****************************
+#
+#***** CollectionPopupMenu *****
+CollectionPopupMenu.Delete:Suprimir
+CollectionPopupMenu.New_Dummy_Doc:Nuevo documento postizo
+CollectionPopupMenu.New_Folder:Nueva carpeta  # Updated 29-Jan-2006
+CollectionPopupMenu.Rename:Renombrar  # Updated 21-Mar-2006
+CollectionPopupMenu.Replace:Reemplazar
+#*******************************
+#
+#***** CreatePane *****
+CreatePane.Build:Opciones de construcciÃ³n de la colecciÃ³n
+CreatePane.Build_Tooltip:Opciones para las fases de indexaciÃ³n y clasificaciÃ³n en la formaciÃ³n de la colecciÃ³n
+CreatePane.Build_Collection:Crear colecciÃ³n
+CreatePane.Build_Collection_Tooltip:Inicia el proceso de formaciÃ³n de la colecciÃ³n
+CreatePane.Build_Progress:Grado de avance en el proceso de construcciÃ³n
+CreatePane.Cancel_Build:Cancelar la construcciÃ³n
+CreatePane.Cancel_Build_Tooltip:Detiene el proceso de formaciÃ³n de la colecciÃ³n
+CreatePane.Full_Build:ReconstrucciÃ³n completa  # Updated 29-Jan-2006
+CreatePane.Full_Build_Tooltip:ReconstrucciÃ³n completa de la colecciÃ³n desde el inicio.  # Updated 29-Jan-2006
+CreatePane.Import:Opciones de importaciÃ³n de la colecciÃ³n
+CreatePane.Import_Tooltip:Opciones para las fases de conversiÃ³n de ficheros y asignaciÃ³n de metadatos en la formaciÃ³n de la colecciÃ³n  # Updated 29-Jan-2006
+CreatePane.Import_Progress:Grado de avance del proceso de importaciÃ³n
+CreatePane.Incremental_Build:ReconstrucciÃ³n incremental  # Updated 29-Jan-2006
+CreatePane.Incremental_Build_Tooltip:RÃ¡pido, ya que sÃ³lo se ejecutan las tareas del proceso de construcciÃ³n de la colecciÃ³n que son necesarias  # Updated 29-Jan-2006
+CreatePane.Log:Registro de mensajes
+CreatePane.Log_Tooltip:Muestra los resultados de intentos anteriores de construcciÃ³n de la colecciÃ³n
+CreatePane.Mode_All:todos
+CreatePane.Options:Grupos opcionales
+CreatePane.Options_Title:Opciones de importaciÃ³n y construcciÃ³n de la colecciÃ³n
+CreatePane.Preview_Collection:Vista previa de la colecciÃ³n
+CreatePane.Preview_Collection_Tooltip:Vista previa de la colecciÃ³n  # Updated 16-Aug-2006
+#**********************
+#
+#***** Dates *****
+Dates.Mon:Lunes
+Dates.Tue:Martes
+Dates.Wed:MiÃ©rcoles
+Dates.Thu:Jueves
+Dates.Fri:Viernes
+Dates.Sat:SÃ¡bado
+Dates.Sun:Domingo
+Dates.Jan:Enero
+Dates.Feb:Febrero
+Dates.Mar:Marzo
+Dates.Apr:Abril
+Dates.May:Mayo
+Dates.Jun:Junio
+Dates.Jul:Julio
+Dates.Aug:Agosto
+Dates.Sep:Septiembre
+Dates.Oct:Octubre
+Dates.Nov:Noviembre
+Dates.Dec:Diciembre
+#**********************
+#
+#***** Delete Collection Prompt *****
+DeleteCollectionPrompt.Collection_Details:Detalles de la colecciÃ³n seleccionada
+DeleteCollectionPrompt.Collection_List:Colecciones disponibles
+DeleteCollectionPrompt.Confirm_Delete:Por favor marque el recuadro para confirmar que desea eliminar la colecciÃ³n.
+DeleteCollectionPrompt.Delete:Suprimir
+DeleteCollectionPrompt.Delete_Tooltip:Elimina la colecciÃ³n seleccionada
+DeleteCollectionPrompt.Details:Creador - {0}\nAdministrador - {1}\nDescripciÃ³n\n{2}
+DeleteCollectionPrompt.Failed_Delete:La colecciÃ³n no se pudo eliminar por completo.
+DeleteCollectionPrompt.Failed_Title:Â¡No se puede eliminar!
+DeleteCollectionPrompt.No_Collection:No se ha seleccionado ninguna colecciÃ³n.
+DeleteCollectionPrompt.Successful_Delete:La colecciÃ³n ha sido eliminada.
+DeleteCollectionPrompt.Successful_Title:Â¡Se ha eliminado por completo!
+DeleteCollectionPrompt.Title:EliminaciÃ³n de la colecciÃ³n
+#**********************
+#
+#***** DirectoryLevelMetadata *****
+DirectoryLevelMetadata.Message:EstÃ¡ a punto de asignar metadatos âa nivel de carpetaâ a la carpeta (o carpetas) seleccionadas. Estos metadatos serÃ¡n heredados automÃ¡ticamente por todos sus ficheros y subcarpetas, y  no podrÃ¡n eliminarse de ninguno de ellos de forma individual, sino sÃ³lo reemplazarse. Para continuar haga click en âAceptarâ.  # Updated 29-Jan-2006
+DirectoryLevelMetadata.Title:A punto de aÃ±adir metadatos a nivel de carpeta
+#********************
+#
+#***** EnrichPane *****
+EnrichPane.AutoMessage:Este elemento, {0}, pertenece al conjunto de metadatos de Greenstone, el cual representa metadatos que normalmente pueden extraerse automÃ¡ticamente. Para saber quÃ© metadatos {0} pueden extraerse, construya una colecciÃ³n por medio de la pantalla âCrearâ.
+EnrichPane.ExistingValues:Valores existentes para {0}  # Updated 29-Jan-2006
+EnrichPane.InheritedMetadataSelected:Este valor de metadato se hereda de una carpeta superior, y no puede editarse. Puede visitar la carpeta que contiene el metadato pulsando en el icono de carpeta situado al inicio de la fila.  # Updated 29-Jan-2006
+EnrichPane.InheritedMetadata_Tooltip:Pulsar este icono para ver la carpeta donde se ha heredado este elemento de metadato  # Updated 16-Aug-2006
+EnrichPane.ManageMetadataSets:Gestionar Conjuntos de Metadatos...  # Updated 16-Aug-2006
+EnrichPane.ManageMetadataSets_Tooltip:Cambiar los conjuntos de metadatos usados en la colecciÃ³n  # Updated 16-Aug-2006
+EnrichPane.No_File:No se ha seleccionado ningÃºn archivo
+EnrichPane.No_Metadata:No hay metadatos disponibles
+EnrichPane.No_Metadata_Element:<HTML><STRONG><FONT FACE={FONT} COLOR=Black>No se ha seleccionado ningÃºn elemento de metadato</FONT></STRONG></HTML>
+EnrichPane.NotOneFileOnlyMetadataSelected:Esta parte de metadatos no solo es aplicable para este archivo, y no puede ser editada.  # Updated 21-Mar-2006
+EnrichPane.Value_Field_Tooltip:Es el valor que se asignarÃ¡ al elemento de metadato seleccionado.
+EnrichPane.Value_Field_Tooltip_Uneditable:Valor asignado al metadato seleccionado  # Updated 29-Jan-2006
+#***********************
+#
+#****** ExplodeMetadataPrompt *******
+ExplodeMetadataPrompt.Explode:Explotar
+ExplodeMetadataPrompt.Explode_Tooltip:Explotar el archivo de metadatos
+ExplodeMetadataPrompt.Instructions:La explosiÃ³n de este archivo de metadatos producirÃ¡ registros individuales con metadatos editables. Este proceso es irreversible y el archivo original de metadatos serÃ¡ eliminado de la colecciÃ³n.
+ExplodeMetadataPrompt.Failed_Title:FallÃ³ la ExplosiÃ³n.
+ExplodeMetadataPrompt.Failed_Explode:No se pudo explotar la base de datos {0}
+ExplodeMetadataPrompt.NotExplodable:Este archivo no es explotable.
+ExplodeMetadataPrompt.Successful_Explode:La base de datos {0} ha sido explotada con Ã©xito
+ExplodeMetadataPrompt.Successful_Title:Se completÃ³ la ExplosiÃ³n.
+ExplodeMetadataPrompt.Title:Explotar la Base de Datos de Metadatos
+ExplodeMetadataPrompt.Plugin:Plugin usado para expandir  # Updated 16-Aug-2006
+#***********************
+#
+#****** WriteCDImagePrompt *******
+WriteCDImagePrompt.CD_Name:Nombre del CD-ROM
+WriteCDImagePrompt.Export:Exportar
+WriteCDImagePrompt.Export_Tooltip:Exportar las colecciones seleccionadas al CD-ROM para Windows
+WriteCDImagePrompt.Failed_Export:Las colecciones  ({0}) no se pudieron exportar al CD-ROM
+WriteCDImagePrompt.Failed_Title:No se pudo exportar
+WriteCDImagePrompt.Install:El CD/DVD instalarÃ¡ algunos ficheros cuando se use (mÃ¡s rÃ¡pido)  # Updated 16-Aug-2006
+WriteCDImagePrompt.Install_Tooltip:Crea un CD-ROM que auto instala el servidor de la Biblioteca (y opcionalmente todos los ficheros de la colecciÃ³n) en el servidor.  # Updated 16-Aug-2006
+WriteCDImagePrompt.NoInstall:El CD/DVD no instalarÃ¡ ningÃºn fichero cuando se use  # Updated 16-Aug-2006
+WriteCDImagePrompt.NoInstall_Tooltip:Produce un CD-ROM que ejecuta directamente la Biblioteca, sin instalar nada en el computador  # Updated 16-Aug-2006
+WriteCDImagePrompt.Instructions:Exportar una o mÃ¡s colecciones a una imÃ¡gen CD/DVD para Windows para que se instale automÃ¡ticamente (aunque esto funciona en cualquier plataforma, el CD/DVD que se crea Ãºnicamente correrÃ¡ bajo Windows).  # Updated 21-Mar-2006
+WriteCDImagePrompt.Progress_Label:Copiando ficheros. Esto podrÃ¡ tomar algÃºn tiempo...  # Updated 29-Jan-2006
+WriteCDImagePrompt.Size_Label:TamaÃ±o estimado:  # Updated 29-Jan-2006
+WriteCDImagePrompt.Successful_Export:Se han exportado las colecciones ({0}).
+WriteCDImagePrompt.Successful_Title:ExportaciÃ³n completa
+WriteCDImagePrompt.Title:Exportar la colecciÃ³n a un CD-ROM
+#************************
+#
+#****** ExportAsPrompt *******
+ExportAsPrompt.Export_Name:Nombre del directorio  # Updated 16-Aug-2006
+ExportAsPrompt.Export:Exportar la(s) colecciÃ³n(ciones)
+ExportAsPrompt.Export_Tooltip:Exportar las colecciones seleccionadas en el formato de archivo escogido al directorio designado
+ExportAsPrompt.Failed_ExportOne:La colecciÃ³n, {0}, no pudo exportarse.
+ExportAsPrompt.Failed_ExportMany:Las colecciones -- {0} -- no pudieron exportarse.
+ExportAsPrompt.Failed_Details:Ver detalles en {1}
+ExportAsPrompt.Failed_Title:FallÃ³ la ExportaciÃ³n
+ExportAsPrompt.Instructions:Exportar una o mÃ¡s colecciones en el formato escogido al directorio estipulado
+ExportAsPrompt.Progress_Label:Exportando Ficheros. Esto puede tomar algÃºn tiempoâŠ  # Updated 29-Jan-2006
+ExportAsPrompt.Successful_ExportOne:La colecciÃ³n -- {0} -- ha sido exportada
+ExportAsPrompt.Successful_ExportMany:Las colecciones -- {0} -- han sido exportadas
+ExportAsPrompt.Successful_Details:Ficheros exportados a: {1}  # Updated 29-Jan-2006
+ExportAsPrompt.Successful_Title:ExportaciÃ³n Completada
+ExportAsPrompt.Title:Exportar Colecciones
+ExportAsPrompt.SaveAs:Exportar a
+ExportAsPrompt.SaveAs_Tooltip:Seleccione el formato al cual desea exportar
+ExportAsPrompt.Cancel:Cancelar  # Updated 16-Aug-2006
+ExportAsPrompt.Cancel_Tooltip:Cancelar el proceso de exportaciÃ³n  # Updated 16-Aug-2006
+ExportAsPrompt.Browse:Mostrar  # Updated 16-Aug-2006
+ExportAsPrompt.Browse_Tooltip:Elegir un fichero XSL  # Updated 16-Aug-2006
+ExportAsPrompt.ApplyXSL:Aplicar fichero XSL a (0)  # Updated 16-Aug-2006
+ExportAsPrompt.ApplyXSL_Tooltip:Usar un fichero XSL para convertir los ficheros exportados  # Updated 16-Aug-2006
+ExportAsPrompt.MARCXMLGroup:Agrupar registros MARC  # Updated 16-Aug-2006
+ExportAsPrompt.MARCXMLGroup_Tooltip:Exportar todos los registros MARC a un fichero simple  # Updated 16-Aug-2006
+#************************
+#
+#*****ExternalCollectionPrompt********
+ExternalCollectionPrompt.NewMDS:Crear un conjunto nuevo y vacÃ­o de metadatos  # Updated 16-Aug-2006
+ExternalCollectionPrompt.ExistingMDS:Elija uno o mÃ¡s de los conjuntos de metadatos existentes  # Updated 16-Aug-2006
+ExternalCollectionPrompt.Title:Cargar una colecciÃ³n externa  # Updated 16-Aug-2006
+ExternalCollectionPrompt.Instructions_1:EstÃ¡ a punto de cargar una colecciÃ³n que no ha sido creada por medio de GLI. Se le pedirÃ¡ que seleccione uno o mÃ¡s conjuntos de metadatos para esta colecciÃ³n. Los metadatos existentes se importarÃ¡n al conjunto o conjuntos seleccionados. Los ficheros de metadatos originales se guardarÃ¡n en una carpeta llamada import.bak.  # Updated 16-Aug-2006
+ExternalCollectionPrompt.Instructions_2:EstÃ¡ a punto de cargar una colecciÃ³n que no ha sido creada por medio de GLI. Necesita aÃ±adir un conjunto de metadatos a esta colecciÃ³n. Usted puede crear un conjunto vacÃ­o de metadatos en el que se incluirÃ¡n automÃ¡ticamente todos los elementos encontrados en la colecciÃ³n. Otra opciÃ³n es seleccionar conjuntos existentes de metadatos, y los elementos de la colecciÃ³n se combinarÃ¡n o aÃ±adirÃ¡n a los elementos que ya se encuentran en dichos conjuntos. Los ficheros de metadatos originales se guardarÃ¡n en una carpeta llamada import.bak.  # Updated 16-Aug-2006
+
+#****************************************
+#
+#***** Inherited Metadata *****
+ExtractedMetadata.Message:El archivo o carpeta seleccionada contiene metadatos extraÃ­dos, los cuales estÃ¡n ocultos. Para verlos vaya al menÃº "[A]rchivo" y seleccione la opciÃ³n "[P]referencias". En la hoja de propiedades "Generales" seleccione "Ver metadatos extraÃ­dos" y haga click en "[A]ceptar".
+ExtractedMetadata.Title:Este archivo/carpeta tiene metadatos extraÃ­dos ocultos
+#
+#***** FileActions *****
+FileActions.Calculating_Size:Calculando el tamaÃ±o total de los ficheros seleccionados  # Updated 29-Jan-2006
+FileActions.Copying:Copiando {0}  # Updated 29-Jan-2006
+FileActions.Could_Not_Delete:No se podrÃ­a borrar {0}  # Updated 29-Jan-2006
+FileActions.Cyclic_Path:No se puede copiar {0}: la carpeta de destino es una subcarpeta de la carpeta de origen.  # Updated 29-Jan-2006
+FileActions.Deleting:Borrando {0}  # Updated 29-Jan-2006
+FileActions.Directories_Selected:{0} carpetas seleccionadas
+FileActions.Directory_Selected:1 carpeta seleccionada
+FileActions.File_Already_Exists_No_Create:El archivo '{0}' ya existe.
+FileActions.File_Already_Exists_Message:{0}\nYa existe un archivo con este nombre en la\n carpeta de destino y a pesar de que usted ha decidido reemplazarlo la Interfaz de la Biblioteca Digital\n no puede sobreescribirlo. Por favor verifique los permisos de acceso al archivo.
+FileActions.File_Already_Exists_Title:Error - El archivo ya existe.
+FileActions.File_And_Directories_Selected:1 archivo y {0} carpetas seleccionadas
+FileActions.File_And_Directory_Selected:1 archivo y 1 carpeta seleccionadas
+FileActions.File_Create_Error:El archivo {0} no pudo ser creado.
+FileActions.Folder_Create_Error:La carpeta {0} no pudo ser creada.
+FileActions.File_Exists:{0} ya existe en la carpeta de destino. Â¿Desea reemplazarlo?
+FileActions.File_Move_Error_Message:No se puede mover {0} a\n{1}.  # Updated 29-Jan-2006
+FileActions.File_Not_Deleted_Message:{0}\nEl fichero indicado arriba no puede borrarse. \nPor favor, compruebe que no tiene el fichero\nabierto con un programa externo, y pruebe de nuevo.  # Updated 29-Jan-2006
+FileActions.File_Not_Deleted_Title:Error - Fichero no borrado.  # Updated 29-Jan-2006
+FileActions.File_Not_Found_Message:{0}\nNo se encontrÃ³ el fichero mencionado. Una vez que la vista de los ficheros\n se haya refrescado, por favor verifique si el fichero aÃºn existe.  # Updated 29-Jan-2006
+FileActions.File_Not_Found_Title:Error - No se encontrÃ³ el archivo.
+FileActions.File_Selected:1 archivo seleccionado
+FileActions.Files_And_Directory_Selected:{0} ficheros y 1 carpeta seleccionados  # Updated 29-Jan-2006
+FileActions.Files_Selected:{0} ficheros seleccionados  # Updated 29-Jan-2006
+FileActions.Folder_Already_Exists:El nombre de la carpeta '{0}' ya se estÃ¡ usando. No se puede crear la carpeta.
+FileActions.Increase_Depth:Aumentar la profundidad 1 nivel
+FileActions.Insufficient_Space_Message:La acciÃ³n no se pudo realizar debido a que no hay suficiente espacio en el disco.\n Para que el archivo se pueda copiar se requiere de uno\n adicional: {0}
+FileActions.Insufficient_Space_Title:Error - Espacio insuficiente
+FileActions.Moving:Moviendo {0}
+FileActions.No_Activity:No se requiere ninguna acciÃ³n
+FileActions.Possible_Cyclic_Path:{1} tiene una profundidad de {0} directorios y puede ser una ruta recursiva. Â¿Desea continuar?
+FileActions.Read_Not_Permitted_Message:No se puede leer {0}.  # Updated 29-Jan-2006
+FileActions.Read_Only:Los ficheros del Ã¡rea de trabajo son de sÃ³lo lectura y no se pueden eliminar.  # Updated 29-Jan-2006
+FileActions.Replacing:Reemplazando {0}  # Updated 21-Mar-2006
+FileActions.Selected:{0} ficheros y {1} carpetas seleccionadas  # Updated 29-Jan-2006
+FileActions.Unknown_File_Error_Message:Aunque no se registrÃ³ ningÃºn mensaje de error durante la acciÃ³n\n, la revisiÃ³n final ha mostrado que la copia\n no es igual al archivo original. La razÃ³n\n de esto es desconocida. Por favor revise la media y actualice\n su JVM instalado.
+FileActions.Unknown_File_Error_Title:Error - Error de archivo desconocido
+FileActions.Write_Not_Permitted_Message:La Interfaz de la Biblioteca Digital no tiene permiso para escribir en\n{0}\n Por favor revise los permisos de acceso al archivo.
+FileActions.Write_Not_Permitted_Title:Error - Permisos de acceso al archivo incorrectos
+FileActions.Yes_To_All:Si a todo
+#************************
+#
+#******* File Associations dialog **********
+FileAssociationDialog.Add:AÃ±adir
+FileAssociationDialog.Add_Tooltip:Utilice este programa para ver ficheros de este tipo  # Updated 29-Jan-2006
+FileAssociationDialog.Batch_File:Ficheros de procesamiento por lotes  # Updated 29-Jan-2006
+FileAssociationDialog.Browse:Explorar
+FileAssociationDialog.Browse_Tooltip:Escoge el programa que se usarÃ¡ desde el espacio de ficheros de su computadora  # Updated 29-Jan-2006
+FileAssociationDialog.Browse_Tooltip_Mac:La bÃºsqueda de su aplicaciÃ³n no estÃ¡ activa en este momento para MacOS
+FileAssociationDialog.Browse_Title:Elegir aplicaciÃ³n
+FileAssociationDialog.Close:Cerrar
+FileAssociationDialog.Close_Tooltip:Cerrar este cuadro de diÃ¡logo y regresar a la ventana principal
+FileAssociationDialog.Command:Orden de inicio:  # Updated 29-Jan-2006
+FileAssociationDialog.Command_File:Archivo de Ã³rdenes  # Updated 29-Jan-2006
+FileAssociationDialog.Command_Tooltip:Introduzca la orden para iniciar el programa que se va a usar  # Updated 29-Jan-2006
+FileAssociationDialog.Details:Detalles de la nueva asociaciÃ³n
+FileAssociationDialog.Executable_File:Ficheros ejecutables  # Updated 29-Jan-2006
+FileAssociationDialog.Existing_Associations:Asociaciones actuales
+FileAssociationDialog.Extension:Para ficheros que terminan en:  # Updated 29-Jan-2006
+FileAssociationDialog.Extension_Tooltip:La extensiÃ³n de los ficheros que se van a ver  # Updated 29-Jan-2006
+FileAssociationDialog.Instructions:Utilice este cuadro de diÃ¡logo para establecer los programas externos que se usarÃ¡n para ver un cierto tipo de ficheroo y la orden que se enviarÃ¡ para iniciar este programa.\n Para aÃ±adir un nuevo tipo de fichero escriba su extensiÃ³n en âPara ficheros que terminan enâ. Para aÃ±adir o modificar una orden de inicio escriba la nueva orden en âOrden de inicioâ o haga click en âExplorarâ para buscar el sistema de ficheros un programa apropiado. Use la cadena de caracteres especiales â%1â para indicar el lugar en el que el nombre del fichero que se abrirÃ¡ deberÃ¡ insertarse, p. ej. "C:\\Windows\\System\\MSPaint.exe %1". '%1' se anexarÃ¡ al final de una orden si no se especifica de otra manera.\n Los usuarios de Mac OS siempre deberÃ¡n intentar primero la orden especÃ­fica para mac "open [-a <application_name>] %1".  # Updated 29-Jan-2006
+FileAssociationDialog.Table.Command:Orden  # Updated 29-Jan-2006
+FileAssociationDialog.Table.Extension:ExtensiÃ³n
+FileAssociationDialog.Title:Editar asociaciones de ficheros  # Updated 29-Jan-2006
+FileAssociationDialog.Remove:Eliminar
+FileAssociationDialog.Remove_Tooltip:Elimine la asociaciÃ³n seleccionada del conjunto de asociaciones existentes
+FileAssociationDialog.Replace:Reemplazar
+FileAssociationDialog.Replace_Tooltip:Reemplace la asociaciÃ³n seleccionada con los detalles de la nueva asociaciÃ³n
+#*******************
+#
+#******Filter***************
+Filter.0:HTM y HTML
+Filter.1:XML
+Filter.2:Ficheros de texto  # Updated 29-Jan-2006
+Filter.3:ImÃ¡genes
+Filter.All_Files:Todos los ficheros  # Updated 29-Jan-2006
+Filter.Filter_Tree:Mostrar ficheros  # Updated 29-Jan-2006
+Filter.Invalid_Pattern:<HTML><FONT FACE={FONT} COLOR=Black>El patrÃ³n que usted ha introducido para filtrar ficheros no es vÃ¡lido.<BR> Por favor intÃ©ntelo de nuevo usando la sintaxis de expresiones regulares con<BR>* como comodÃ­n.</FONT></HTML>  # Updated 29-Jan-2006
+#***********************
+#
+#***** GAuthenticator *****
+GAuthenticator.Password:ContraseÃ±a:
+GAuthenticator.Password_Tooltip:Escriba aquÃ­ su contraseÃ±a
+GAuthenticator.Title:Requiere contraseÃ±a.
+GAuthenticator.Username:Nombre de usuario:
+GAuthenticator.Username_Tooltip:Escriba aquÃ­ su nombre de usuario
+#**************************
+#
+#***** General Messages *****
+# 0 - A String representing the name and method of the class in question.
+General.Apply:Aplicar
+General.Apply_Tooltip:Aplica los ajustes, pero sin salir del cuadro de diÃ¡logo
+General.Browse:Explorar
+General.Cancel:Cancelar
+General.Cancel_Tooltip:Cancela los cambios (no desharÃ¡ ninguno de los cambios que ya se hayan aplicado)
+General.Close:Cerrar
+General.Close_Tooltip:Cierra este cuadro de diÃ¡logo
+General.Edit:Editar valor
+General.Error:Error
+General.No:No
+General.NotSunJava:Proveedor de Java: {0}\nTenga en cuenta que la Interfaz de Bibliotecario ha sido desarrollada y probada con Java de Sun Microsystems
+General.OK:Aceptar
+General.OK_Tooltip:Acepta los cambios actuales y sale del cuadro de diÃ¡logo
+General.Open:Abrir
+General.Outstanding_Processes:<html>La Interfaz de la Biblioteca Digital no se podrÃ¡ cerrar completamente hasta que se haya salido de todos los programas<br>.</html>
+General.Outstanding_Processes_Title:Esperando para salir
+General.Pure_Cancel_Tooltip:Aborta esta acciÃ³n (no se harÃ¡ ningÃºn cambio)
+General.Review_Output:Por favor revise los resultados que estÃ¡n a continuaciÃ³n:
+General.Redo:Rehacer  # Updated 16-Aug-2006
+General.Redo_Tooltip:Restaurar el Ãºltimo deshacer  # Updated 16-Aug-2006
+General.Undo:Deshacer  # Updated 16-Aug-2006
+General.Undo_Tooltip:Deshacer la Ãºltima ediciÃ³n  # Updated 16-Aug-2006
+General.Usage:Uso: {0} <params>\nTodos los parÃ¡metros son opcionales, pero es probable que la Interfaz de la Biblioteca Digital no funcione si -gsdl y -library no se han establecido.\n -gsdl <path>  : Forzar la ruta hacia gsdl\n -library <path> : Ruta hacia cgi-bin\n -mozilla <path> : Habilitada mozilla\n -mirror : Activar los controles para la descarga de ficheros de la web\n -laf [java|windows|motif|mac] : Imagen y apariencia\n -debug : Permite depurar mensajes\n -no_load : No carga una colecciÃ³n abierta previamente\n -load <path> : Carga la colecciÃ³n especificada  # Updated 29-Jan-2006
+General.View:Ver Valor
+General.Warning:Advertencia
+General.Yes:Si
+#****************************
+#
+#***** GShell *****
+GShell.BadArgument:El argumento {0} es invÃ¡lido.  # Updated 29-Jan-2006
+GShell.BadArgumentValue:El argumento {0} tiene un valor invÃ¡lido.  # Updated 29-Jan-2006
+GShell.BadPluginOptions:Argumento errÃ³neo en el plugin {0}.  # Updated 29-Jan-2006
+GShell.BadClassifierOptions:Argumento errÃ³neno en el clasificador {0}.  # Updated 29-Jan-2006
+GShell.Build.Auxilary:Creando los ficheros auxiliares y poniÃ©ndolos en orden...  # Updated 29-Jan-2006
+GShell.Build.BuildBegun1:************ Iniciando el proceso de construcciÃ³n de la colecciÃ³n ************
+GShell.Build.BuildCancelled:************** Cancelado **************
+GShell.Build.BuildComplete1:*********** El proceso de construcciÃ³n de la colecciÃ³n ha terminado ***********
+GShell.Build.CompressText:Comprimiendo el texto...
+GShell.Build.Index:Creando un Ã­ndice basado en {0-fuente y nivel del Ã­ndice}...
+GShell.Build.InfoDatabase:Creando una base de datos de informaciÃ³n...
+GShell.Build.Phind:Generando un clasificador Phind...
+GShell.Command:orden  # Updated 29-Jan-2006
+GShell.Failure:La orden no se pudo ejecutar.  # Updated 29-Jan-2006
+GShell.Import.FileNotProcessed:El archivo {0-target file path} fue reconocido pero no pudo ser procesado por ningÃºn plugin.
+GShell.Import.FileNotRecognised:El archivo que se encuentra en {0-ruta del archivo objetivo} no se puede aÃ±adir debido a que su tipo no es reconocible por ninguno de los plugins de Greenstone.
+GShell.Import.FileProcessing:El archivo {0-target file path} estÃ¡ siendo procesado por {1-plugin name}.
+GShell.Import.FileProcessingError:El archivo {0-target file path} generÃ³ un error al ser procesado.
+GShell.Import.ImportBegun1:************ Iniciando el proceso de importaciÃ³n de la colecciÃ³n ************
+GShell.Import.ImportComplete1:*********** El proceso de importaciÃ³n de la colecciÃ³n ha terminado ***********
+GShell.Import.ImportComplete2:{0-nÃºmero de documentos considerados} de los documentos fueron considerados a efecto de ser procesados:
+GShell.Import.ImportComplete2.1:1 documento fue considerado a efecto de ser procesado:
+GShell.Import.ImportComplete.Processed:{0-nÃºmero procesado} se procesaron e incluidos en la colecciÃ³n.
+GShell.Import.ImportComplete.Processed.1:1 fue procesado e incluido en la colecciÃ³n.
+GShell.Import.ImportComplete.Blocked:{0-nÃºmero bloqueado} eran ser aÃ±adidos por los plugins (como por ejemplo las imÃ¡genes de las pÃ¡ginas web).
+GShell.Import.ImportComplete.Blocked.1:1 era ser aÃ±adidos por los plugins (como por ejemplo las imÃ¡genes de las pÃ¡ginas web).
+GShell.Import.ImportComplete.Ignored:{0-nÃºmero ignorado} no eran ser reconocidos por los plugins y son disponibles en la colecciÃ³n.
+GShell.Import.ImportComplete.Ignored.1:1 no era ser reconocidos por los plugins y es disponibles en la colecciÃ³n.
+GShell.Import.ImportComplete.Failed:{0-number failed} rechazados.
+GShell.Import.ImportComplete.Failed.1:1 fue rechazado.
+GShell.Import.ImportComplete3:\n
+GShell.Parsing_Metadata_Complete:ExtracciÃ³n completa de metadatos archivados.
+GShell.Parsing_Metadata_Start:Extrayendo nuevos metadatos de los ficheros.  # Updated 29-Jan-2006
+GShell.Success:Orden completada.  # Updated 29-Jan-2006
+#*********************
+#
+#***** GUI *****
+# Currently Enabled and Disabled display the same text but in different
+# colours. If necessary this can be changed.
+GUI.Create:Crear
+GUI.Create_Tooltip:Le ayuda a crear su colecciÃ³n por medio del conjunto de programas Greenstone
+GUI.Design:DiseÃ±o
+GUI.Design_Tooltip:DiseÃ±a la funcionalidad de su colecciÃ³n  # Updated 16-Aug-2006
+GUI.Download:Descargar  # Updated 29-Jan-2006
+GUI.Download_Tooltip:Baja recursos de Internet para su colecciÃ³n
+GUI.Enrich:Enriquecer
+GUI.Enrich_Tooltip:Asigna metadatos a los ficheros de su colecciÃ³n  # Updated 29-Jan-2006
+GUI.Format:Formato  # Updated 16-Aug-2006
+GUI.Format_Tooltip:DiseÃ±ar la presentaciÃ³n de su colecciÃ³n  # Updated 16-Aug-2006
+GUI.Gather:Reunir
+GUI.Gather_Tooltip:Selecciona los ficheros que se incluirÃ¡n en su colecciÃ³n  # Updated 29-Jan-2006
+#***************
+#
+#***** HELP *****
+Help.Contents:Contenido
+Help.Title:PÃ¡ginas de ayuda de la Interfaz de la Biblioteca Digital
+#****************************
+#
+#***** Invalid Metadata ******
+InvalidMetadata.Message:Este elemento de metadato estÃ¡ restringido a un conjunto predefinido de valores. Por favor, elija uno de los valores existentes.  # Updated 29-Jan-2006
+InvalidMetadata.Title:Metadato invÃ¡lido  # Updated 29-Jan-2006
+#***************************
+#
+#***** LegacyCollection
+LegacyCollection.Message:EstÃ¡ a punto de cargar una colecciÃ³n no creada mediante GLI. Los metadatos existentes serÃ¡n importados en el conjunto de metadatos Dublin Core. Los ficheros de metadatos originales serÃ¡n guardados en una carpeta llamada import.bak  # Updated 16-Aug-2006
+LegacyCollection.Title:Cargando ColecciÃ³n Externa  # Updated 16-Aug-2006
+#***************************
+#
+#***** LockFileDialog *****
+LockFileDialog.Cancel_Tooltip:No tome el control del archivo de bloqueo (o la colecciÃ³n no se abrirÃ¡)
+LockFileDialog.Date:Fecha
+LockFileDialog.Error:error
+LockFileDialog.Lockfile_Message_One:La presencia de un archivo de bloqueo sugiere que esta colecciÃ³n estÃ¡ siendo usada por otra persona.
+LockFileDialog.Lockfile_Message_Two:Â¿Desea tomar el control de este archivo de bloqueo?
+LockFileDialog.Machine:Donde
+LockFileDialog.Name:Nombre
+LockFileDialog.OK_Tooltip:Toma el control del archivo de bloqueo
+LockFileDialog.Title:Se detectÃ³ un archivo de bloqueo
+LockFileDialog.User:Quien
+#********************
+#
+#*****MappingPrompt **********
+MappingPrompt.File:Carpeta
+MappingPrompt.Map:Crear un acceso directo
+MappingPrompt.Name:Nombre
+MappingPrompt.Title:Establecer un acceso directo a la carpeta
+MappingPrompt.Unmap:Eliminar acceso directo
+#*******************
+#
+#***** Menu Options *****
+Menu.Collapse:Cerrar carpeta
+Menu.Edit:Editar
+Menu.Edit_Copy:Copiar (ctrl-c)
+Menu.Edit_Cut:Cortar (ctrl-x)
+Menu.Edit_Paste:Pegar (ctrl-v)
+Menu.Expand:Abrir carpeta
+Menu.Explode_Metadata_Database:Explotar la base de datos de metadatos
+Menu.File:Archivo
+Menu.File_Associations:AsociaciÃ³n de ficheros...  # Updated 29-Jan-2006
+Menu.File_CDimage:Exportar a un CD-ROM/DVD...
+Menu.File_Close:Cerrar
+Menu.File_Delete:Suprimir...
+Menu.File_Exit:Salir
+Menu.File_ExportAs:Exportar...
+Menu.File_New:Nueva...
+Menu.File_Open:Abrir...
+Menu.File_Options:Preferencias...
+Menu.File_Save:Guardar
+Menu.Help:Ayuda
+Menu.Help_About:Acerca de...
+Menu.Metadata_View:Metadatos asignados para {0}
+Menu.Open_Externally:Abrir en un programa externo
+#********************
+#
+#***** MetaAudit *****
+MetaAudit.Close:Cerrar
+MetaAudit.Close_Tooltip:Cierra este cuadro de diÃ¡logo
+MetaAudit.Title:Todos los metadatos
+#*********************
+#
+#***** Metadata *****
+Metadata.Element:Elemento
+Metadata.Value:Valor
+MetadataSet.Files:Ficheros de conjunto de metadatos  # Updated 29-Jan-2006
+#**********************************
+#
+#***** MetadataSetDialog**********
+MetadataSetDialog.Title:Gestionar Conjuntos de Metadatos  # Updated 16-Aug-2006
+MetadataSetDialog.Add_Title:AÃ±adir Conjunto de Metadatos  # Updated 16-Aug-2006
+MetadataSetDialog.Current_Sets:Conjuntos de Metadatos Asignados  # Updated 16-Aug-2006
+MetadataSetDialog.Available_Sets:Conjuntos de Metadatos disponibles  # Updated 16-Aug-2006
+MetadataSetDialog.Add:AÃ±adir...  # Updated 16-Aug-2006
+MetadataSetDialog.Add_Tooltip:AÃ±adir un nuevo conjunto de metadatos a la colecciÃ³n  # Updated 16-Aug-2006
+MetadataSetDialog.Add_Set:AÃ±adir  # Updated 16-Aug-2006
+MetadataSetDialog.Add_Set_Tooltip:AÃ±adir el conjunto de metadatos seleccionado a la colecciÃ³n  # Updated 16-Aug-2006
+MetadataSetDialog.Browse:Mostrar...  # Updated 16-Aug-2006
+MetadataSetDialog.Browse_Tooltip:AÃ±adir un nuevo conjunto de metadatos a la colecciÃ³n  # Updated 16-Aug-2006
+MetadataSetDialog.Edit:Editar...  # Updated 16-Aug-2006
+MetadataSetDialog.Edit_Tooltip:Editar el conjunto de metadatos seleccionado  # Updated 16-Aug-2006
+MetadataSetDialog.Remove:Borrar  # Updated 16-Aug-2006
+MetadataSetDialog.Remove_Tooltip:Borrar de la colecciÃ³n el conjunto de metadatos seleccionado  # Updated 16-Aug-2006
+MetadataSetDialog.Elements:Elementos del Conjunto de Metadatos seleccionado  # Updated 16-Aug-2006
+MetadataSetDialog.Edit_Message:Los conjuntos de metadatos pueden editarse usando GEMS (Greenstone Editor for Metadata Sets).\nInicie GEMS en Windows ejecutando \nInicio-->Greenstone Digital Library Software-->Editor Greenstone para Conjuntos de Metadatos.\nEn Linux o Mac, ejecute gems.sh desde la carpeta gli folder existente en la instalaciÃ³n de Greenstone.  # Updated 16-Aug-2006
+MetadataSetDialog.Edit_Message_Title:Editando Conjuntos de Metadatos  # Updated 16-Aug-2006
+
+#****************************************
+#
+#***** MetadataSetNamespaceClash warning***
+MetadataSetNamespaceClash.Title:Conflicto de Espacio de Nombres del Conjunto de Metadatos  # Updated 16-Aug-2006
+MetadataSetNamespaceClash.Message:El conjunto de metadatos que ha elegido aÃ±adir ({0}) tiene el mismo espacio de nombres que otro existente ya en la colecciÃ³n ({1}). Si aÃ±ade este nuevo conjunto, el otro se borrarÃ¡ y el nuevo lo sustituirÃ¡. Cualquier valor asignado de metadatos se transferirÃ¡ al nuevo conjunto si Ã©ste contiene los elementos apropiados.  # Updated 16-Aug-2006
+#*********************************************
+#
+#******** MetadataImportMappingPrompt *********
+MIMP.Add::AÃ±adir
+MIMP.Add_Tooltip:AÃ±ade el elemento de metadato al conjunto seleccionado
+MIMP.Ignore:Ignorar
+MIMP.Ignore_Tooltip:Ignora este elemento de metadato
+MIMP.Instructions:El elemento de metadato {0} no se puede importar automÃ¡ticamente a la colecciÃ³n. Seleccione un conjunto de metadatos y:\n(1) haga click en âAÃ±adirâ para agregar el metadato a ese conjunto (sÃ³lo si el metadato {0} no se encuentra ya en el conjunto), o\n(2) elija un elemento y haga click en âCombinarâ para importar el metadato {0} a este elemento, o\n(3) ignore este elemento de metadato.
+MIMP.Merge:Combinar
+MIMP.Merge_Tooltip:Mapea el elemento de metadato hacia el elemento especificado en el conjunto seleccionado
+MIMP.Source_Element:Elemento de metadatos origen:
+MIMP.Target_Element:Elemento de metadatos destino:
+MIMP.Target_Set:Conjunto de metadatos destino:
+MIMP.Title:Es necesario combinar los elementos.
+#*****************************
+#
+#***** Mirroring *****
+Mirroring.ClearCache:Borrar CachÃ©
+Mirroring.ClearCache_Tooltip:Borrar todos los ficheros descargados  # Updated 29-Jan-2006
+Mirroring.Download:Descargar  # Updated 29-Jan-2006
+Mirroring.Download_Tooltip:Inicia una nueva descarga
+Mirroring.Download_Controls:Controles para descargar ficheros de Internet  # Updated 29-Jan-2006
+Mirroring.Download_Depth:Profundidad de la descarga:
+Mirroring.Download_Depth.Zero:Cero
+Mirroring.Download_Depth.Unlimited:Ilimitado
+Mirroring.Download_Depth_Tooltip:CuÃ¡ntos niveles de hipervÃ­nculos se seguirÃ¡n en al momento de descargar los ficheros de Internet  # Updated 29-Jan-2006
+Mirroring.Download_OnlyHTML:Baje de internet Ãºnicamente documentos en formato HTML (ignore los archivos asocioados e.j imÃ¡genes y hojasestilo)  # Updated 29-Mar-2006
+Mirroring.DownloadJob.Close:Cerrar
+Mirroring.DownloadJob.Close_Tooltip:Quitar este job de la lista, deteniÃ©ndolo si todavÃ­a estÃ¡ en ejecuciÃ³n
+Mirroring.DownloadJob.Downloading:Bajando {0}
+Mirroring.DownloadJob.Download_Complete:Descarga completa
+Mirroring.DownloadJob.Download_Stopped:Descarga detenida
+Mirroring.DownloadJob.Download_Progress:Descarga en ejecuciÃ³n
+Mirroring.DownloadJob.Log:Ver BitÃ¡cora
+Mirroring.DownloadJob.Log_Tooltip:Ver detalles acerca de esta descarga
+Mirroring.DownloadJob.Pause:Pausa
+Mirroring.DownloadJob.Pause_Tooltip:Pausa
+Mirroring.DownloadJob.Resume:Reiniciar
+Mirroring.DownloadJob.Resume_Tooltip:Reiniciar esta descarga
+Mirroring.DownloadJob.Status:{0} descarga de {1} ficheros ({2} mensajes de advertencia, {3} errores)  # Updated 29-Jan-2006
+Mirroring.DownloadJob.Waiting:Esperando para iniciar
+Mirroring.DownloadJob.Waiting_User:Esperando instrucciones
+Mirroring.Higher_Directories:Â¿Desea descargar ficheros de carpetas que estÃ©n a un nivel mÃ¡s arriba del url dado?  # Updated 29-Jan-2006
+Mirroring.Invalid_URL:El URL que se ingresÃ³ no es vÃ¡lido. Por favor corrÃ­jalo.
+Mirroring.Invalid_URL_Title:URL invÃ¡lida
+Mirroring.Preferences:Preferencias...
+Mirroring.Preferences_Tooltip:Habilitar proxy y/o editar la configuraciÃ³n del proxy
+Mirroring.Same_Host:SÃ³lo ficheros dentro del mismo sitio  # Updated 29-Jan-2006
+Mirroring.Source_URL:URL fuente:
+Mirroring.Source_URL_Tooltip:Es el URL que se va a descargar  # Updated 29-Jan-2006
+#*********************
+#
+#***** Missing EXEC *****
+MissingEXEC.Message:Â¡Cuidado! Usted no podrÃ¡ ver sus nuevas colecciones dentro de la Interfaz de Bibliotecario a menos que especifique la ruta hacia el servidor web de la Biblioteca Greenstone. Usted puede indicarla ahora en el campo de texto que se encuentra debajo, o mÃ¡s tarde en "Preferencias", pestaÃ±a "ConexiÃ³n". Recuerde que un url vÃ¡lido debe comenzar con el protocolo "http://" y terminar con el nombre del ejecutable ("gsdl" para el servidor de la biblioteca local Greenstone, "library" para otros servidores web).  # Updated 29-Jan-2006
+MissingEXEC.Title:Falta la direcciÃ³n de la Biblioteca Greenstone
+#***** Missing EXEC_GS3 *****
+MissingEXEC_GS3.Message:Â¡AtenciÃ³n! No podrÃ¡ ver las nuevas colecciones con la Interfaz de Bibliotecario a menos que especifique la ruta al entorno Greenstone en el servidor local Tomcat. Puede introducirla ahora en el campo de texto situado debajo, o mÃ¡s tarde en "Preferencias", pestaÃ±a "ConexiÃ³n". Recuerde que un URL vÃ¡lido debe comenzar con el protocolo "http://" La direcciÃ³n predefinida es http://localhost:8080/greenstone3  # Updated 29-Jan-2006
+MissingEXEC_GS3.Title:No se encuentra la direcciÃ³n de la Biblioteca Greenstone 3  # Updated 29-Jan-2006
+#***** Missing GLIServer *****
+MissingGLIServer.Message:Â¡AtenciÃ³n! No podrÃ¡ trabajar con colecciones desde la Interfaz de Bibliotecario a menos que especifique la direcciÃ³n del script "gliserver" del servidor Greenstone remoto. Puede hacerlo ahora introduciÃ©ndolo en el Ã¡rea de texto inferior, o mÃ¡s tarde en "Preferencias", pestaÃ±a "ConexiÃ³n". Recuede que un URL vÃ¡lido debe comenzar con el protocolo "http://" y terminar con "gliserver".  # Updated 29-Jan-2006
+MissingGLIServer.Title:DirecciÃ³n GLIServer perdida  # Updated 29-Jan-2006
+#***** Missing GSDL *****
+MissingGSDL.Message:Â¡Cuidado! Usted no podrÃ¡ tener acceso a todas las funciones de la Interfaz de Bibliotecario sin tener instalada una copia local de Biblioteca Digital Greenstone. Si usted cree que estÃ¡ recibiendo este mensaje por error, por favor revise su instalaciÃ³n y las rutas especificadas en los ficheros script y batch de la Interfaz de Bibliotecario.  # Updated 29-Jan-2006
+MissingGSDL.Title:Falta la ruta de conexiÃ³n con Greenstone
+#***** Missing PERL *****
+MissingPERL.Message:Â¡Cuidado! Usted no podrÃ¡ crear nuevas colecciones ni construir las que ya existen, si no ha instalado el lenguaje de programaciÃ³n PERL, o si la Interfaz de Bibliotecario no pudo encontrarlo en su sistema. Si usted cree que estÃ¡ recibiendo este mensaje por error, por favor revise su instalaciÃ³n y las rutas especificadas en los ficheros de script y batch de la Interfaz de Bibliotecario.  # Updated 29-Jan-2006
+MissingPERL.Title:Falta la ruta PERL
+#******* MissingWGET ********
+MissingWGET.Message:AtenciÃ³n! Se ha deshabilitado la capacidad de descargar de la Web porque la Interfaz de Bibliotecario no pudo localizar una versiÃ³n apropiada de Wget. Si usted cree que estÃ¡ recibiendo este mensaje debido a un error, por favor revise su instalaciÃ³n y las rutas especificadas en el archivo batch o script del 'Librarian'  # Updated 29-Jan-2006
+MissingWGET.Title:Falta Wget
+#******* MissingImageMagick ********
+MissingImageMagick.Message:AtenciÃ³n! La interfaz del bibliotecario fallÃ³ al ubicar un versiÃ³n apropiada de imageMagick y por lo tanto la imagePlug no funcionarÃ¡
+MissingImageMagick.Title:Falta ImageMagick
+#*****************************
+#
+#***** New Session *****
+NewCollectionPrompt.Base_Collection:Construir esta colecciÃ³n con base en:
+NewCollectionPrompt.Base_Collection_Tooltip:Seleccione una colecciÃ³n existente para basar en ella la nueva colecciÃ³n
+NewCollectionPrompt.Collection_Description:DescripciÃ³n de contenidos:
+NewCollectionPrompt.Collection_Name:Carpeta de la colecciÃ³n:
+NewCollectionPrompt.Collection_Scope_Personal:Esta es una colecciÃ³n personal  # Updated 16-Aug-2006
+NewCollectionPrompt.Collection_Scope_Shared:Esta no es una colecciÃ³n personal  # Updated 16-Aug-2006
+NewCollectionPrompt.Error:Error en la nueva colecciÃ³n
+NewCollectionPrompt.Instructions:Para crear una nueva colecciÃ³n llene los campos que estÃ¡n a continuaciÃ³n.
+NewCollectionPrompt.NewCollection:-- Nueva colecciÃ³n --
+NewCollectionPrompt.Title:Crear una nueva colecciÃ³n.
+NewCollectionPrompt.Title_Clash:El tÃ­tulo que usted ha elegido para su colecciÃ³n ya se estÃ¡ usando. Â¿Desea continuar?
+NewCollectionPrompt.Title_Error:El tÃ­tulo debe llenarse. Por favor corrija.
+#***** New Folder OrFilePrompt *****
+NewFolderOrFilePrompt.Default_File_Name:postizo
+NewFolderOrFilePrompt.Default_Folder_Name:nueva carpeta
+NewFolderOrFilePrompt.Destination_Name:Carpeta Destino
+NewFolderOrFilePrompt.File_Name:Nombre del Archivo
+NewFolderOrFilePrompt.File_Name_Tooltip:Dar un nombre para el nuevo archivo
+NewFolderOrFilePrompt.Folder_Name:Nombre de la Carpeta
+NewFolderOrFilePrompt.Folder_Name_Tooltip:Dar un nombre para la nueva carpeta
+NewFolderOrFilePrompt.Title_Folder:Crear una nueva carpeta
+NewFolderOrFilePrompt.Title_File:Crear un nuevo documento postizo
+#**********************
+#
+#******* OldWGET *******
+NoPluginExpectedToProcessFile.Message:No se encuentra ningÃºn plugin de Greenstone que pueda procesar el archivo "{0}". Compruebe que el archivo tiene la extensiÃ³n correcta. Si la extensiÃ³n es correcta entonces tendrÃ¡ que usar el plugin Unkowm para procesar este archivo.
+NoPluginExpectedToProcessFile.Title:No se encuentra un plugin que pueda procesar el archivo
+#**********************
+#
+#******* OldWGET *******
+OldWGET.Message:AtenciÃ³n! La versiÃ³n de Wget que ha instalado tiene un defecto conocido cuando se manejan ficheros que contienen caracteres codificados tales como espacio y tilde en su URL. Aunque este no debe ser un problema, recomendamos instalar Wget 1.9 o posterior  # Updated 29-Jan-2006
+OldWGET.Title:Wget viejo
+#***********************
+#
+#***** OpenCollectionDialog *****
+OpenCollectionDialog.Available_Collections:Colecciones disponibles
+OpenCollectionDialog.Browse:Explorar
+OpenCollectionDialog.Browse_Tooltip:Elija una colecciÃ³n del espacio de ficheros de su computadora  # Updated 29-Jan-2006
+OpenCollectionDialog.Collection:ColecciÃ³n Greenstone (".col")
+OpenCollectionDialog.Description:DescripciÃ³n de la colecciÃ³n
+OpenCollectionDialog.Locked_Collection:La colecciÃ³n Greenstone ya estÃ¡ en uso  # Updated 29-Jan-2006
+OpenCollectionDialog.No_Description:Por favor seleccione una colecciÃ³n Greenstone (archivo ".col") para ver su descripciÃ³n.
+OpenCollectionDialog.Normal_Collection:ColecciÃ³n Greenstone
+OpenCollectionDialog.Open:Abrir
+OpenCollectionDialog.Open_Tooltip:Carga la colecciÃ³n seleccionada en la Interfaz de la Biblioteca Digital
+OpenCollectionDialog.Title:Abrir la colecciÃ³n Greenstone
+#**********************
+#
+#***** Options Pane inside CreatePane *****
+OptionsPane.Cancelled:- cancelada
+OptionsPane.LogHistory:Historial de registro
+OptionsPane.Successful:- con Ã©xito
+OptionsPane.Unknown:- desconocido
+OptionsPane.Unsuccessful:- sin Ã©xito
+#*******************
+#
+#***** Preferences *****
+Preferences:Preferencias
+Preferences.Connection:ConexiÃ³n
+Preferences.Connection_Tooltip:Escriba el URL de la Biblioteca Greenstone y configure una conexiÃ³n proxy segÃºn sea necesario
+Preferences.Connection.GLIServer_URL:URL del gliserver de Greenstone:  # Updated 29-Jan-2006
+Preferences.Connection.GLIServer_URL_Tooltip:El URL del script CGI "gliserver" de Greenstone.  # Updated 29-Jan-2006
+Preferences.Connection.Library_Path:Ruta de la biblioteca
+Preferences.Connection.Library_Path_GS3:Ruta Web de Greenstone:
+Preferences.Connection.Library_Path_Tooltip:Es el URL del servidor Web Greenstone
+Preferences.Connection.Library_Path_Tooltip_GS3:URL del servidor web de Greenstone
+Preferences.Connection.ProgramCommand:Orden de vista previa:  # Updated 29-Jan-2006
+Preferences.Connection.ProgramCommand_Tooltip:Es la orden de inicio del programa usado para tener una vista previa de la colecciÃ³n. Recuerde usar %1 para indicar el lugar donde deberÃ¡ insertarse la direcciÃ³n de la colecciÃ³n y usar las marcas de habla donde sea necesario.  # Updated 29-Jan-2006
+Preferences.Connection.Proxy_Host:Servidor proxy
+Preferences.Connection.Proxy_Host_Tooltip:Es la direcciÃ³n del servidor proxy
+Preferences.Connection.Proxy_Port:Puerto para el servidor proxy
+Preferences.Connection.Proxy_Port_Tooltip:Es el nÃºmero de puerto del servidor proxy
+Preferences.Connection.Servlet:Servlet:
+Preferences.Connection.Servlet_Tooltip:Servlet a utilizar para ver su sitio
+Preferences.Connection.Servlet_Tooltip2:No se ha especificado 'servlet' para este sitio, es posible construir colecciones, pero no podrÃ¡ verlas
+Preferences.Connection.Site:Sitio:
+Preferences.Connection.Site_Tooltip:El sitio en el cual quiere trabajar
+Preferences.Connection.Use_Proxy:Â¿Desea usar la conexiÃ³n del servidor proxy?
+Preferences.General:General
+Preferences.General_Tooltip:Determine algunas preferencias generales
+Preferences.General.Email:E-mail del usuario:
+Preferences.General.Email_Tooltip:La direcciÃ³n de correo electrÃ³nico usada automÃ¡ticamente para cualquier colecciÃ³n creada por medio de GLI.
+Preferences.General.Font:Fuente:
+Preferences.General.Font_Tooltip:La fuente utilizada para el interfaz GLI.
+Preferences.General.Interface_Language:Idioma de la interfaz:
+Preferences.General.Interface_Language_Tooltip:Seleccione el idioma en el que usted desea que aparezcan los controles y la interfaz.
+Preferences.General.Restart_Required:DeberÃ¡ reiniciar GLI para completar la actualizaciÃ³n de su interfaz.  # Updated 16-Aug-2006
+Preferences.General.Show_File_Size:Mostrar el tamaÃ±o de los ficheros  # Updated 29-Jan-2006
+Preferences.General.Show_File_Size_Tooltip:Muestra el tamaÃ±o de los ficheros junto a cada una de las entradas de las estructuras de ficheros en el Ã¡rea de trabajo y en la colecciÃ³n.  # Updated 29-Jan-2006
+Preferences.General.View_Extracted_Metadata:Ver metadatos extraÃ­dos
+Preferences.General.View_Extracted_Metadata_Tooltip:Muestra los metadatos extraÃ­dos por los plugins de Greenstone en la lista de metadatos de la pantalla Enriquecer
+Preferences.Mode:Modo
+Preferences.Mode_Tooltip:Haga click en una entrada para seleccionar el nivel de operaciÃ³n
+Preferences.Mode.Assistant:Asistente de biblioteca
+Preferences.Mode.Assistant_Description:Utilice esta opciÃ³n para tener acceso a las funciones bÃ¡sicas de la Interfaz de Bibliotecario de Greenstone: aÃ±adir documentos y metadatos a las colecciones, crear nuevas colecciones cuya estructura refleje la de colecciones que ya existen y construir colecciones.  # Updated 29-Jan-2006
+Preferences.Mode.Librarian:Bibliotecario
+Preferences.Mode.Librarian_Description:Este control le da un uso normal de la Interfaz de Bibliotecario Greenstone: crear y diseÃ±ar nuevas colecciones, aÃ±adir documentos y metadatos a las colecciones, diseÃ±ar nuevas colecciones y construir colecciones.  # Updated 29-Jan-2006
+Preferences.Mode.Systems:Especialista en Sistemas de Bibliotecas
+Preferences.Mode.Systems_Description:Esta opciÃ³n permite el uso completo de la Interfaz de la Biblioteca Digital Greenstone. Para aprovechar todas las funciones disponibles usted deberÃ¡ ser capaz de formular expresiones regulares.
+Preferences.Mode.Expert:Avanzado
+Preferences.Mode.Expert_Description:Este control permite el uso avanzado de la Interfaz de la Biblioteca Digital Greenstone. Se recomienda para usuarios que tienen experiencia con Greenstone y son capaces de resolver problemas que impliquen interpretar la depuraciÃ³n de los resultados de los guiones PERL: Todas las funciones de la Biblioteca Digital estÃ¡n activas.
+Preferences.Warnings:Mensajes de advertencia
+Preferences.Warnings_Tooltip:Activa o desactiva los distintos mensajes de advertencia
+Preferences.Workflow:Flujo de trabajo
+Preferences.Workflow_Tooltip:DiseÃ±e el flujo de trabajo de la interfaz: determine las pantallas que estarÃ¡n activas
+Preferences.Workflow.Predefined.Label:Flujos de trabajo predeterminados
+Preferences.Workflow.Title:Marque el cuadro para activar la pantalla
+#**********************
+#
+#**** PreviewCommandDialog *******
+PreviewCommandDialog.Instructions:Introduzca la orden para abrir el programa a fin de tener una vista previa de la colecciÃ³n. Recuerde usar %1 para indicar el lugar donde deberÃ¡ insertarse la direcciÃ³n de la colecciÃ³n y usar las marcas de habla donde sea necesario.  # Updated 29-Jan-2006
+PreviewCommandDialog.Title:Orden de vista previa  # Updated 29-Jan-2006
+#**********************
+#
+#***** Remote Greenstone Server *****
+RemoteGreenstoneServer.Authentication_Message:Por favor, introduzca su nombre de usuario y su clave de acceso para Greenstone:  # Updated 29-Jan-2006
+RemoteGreenstoneServer.Error:Ha ocurrido un error en el servidor Greenstone remoto mientras se ejecutaba esta operaciÃ³n:\n{0-Error message}  # Updated 29-Jan-2006
+RemoteGreenstoneServer.Error_Title:Error del servidor Greenstone remoto  # Updated 29-Jan-2006
+RemoteGreenstoneServer.Progress:Progreso del servidor Greenstone remoto:  # Updated 29-Jan-2006
+RemoteGreenstoneServer.Steal_Lock_Message:Esta colecciÃ³n estÃ¡ acualmente bloqueada por el usuario '{0-User name}'.\nÂ¿Quiere tomar el control de este fichero de bloqueo? (no se recomienda, ya que el trabajo puede perderse)  # Updated 29-Jan-2006
+#**********************
+#
+#***** Rename Prompt *****
+RenamePrompt.Name:Nombre:  # Updated 21-Mar-2006
+RenamePrompt.Title:Renombrar el archivo/folder  # Updated 21-Mar-2006
+#**********************
+#
+#***** Replace Prompt *****
+ReplacePrompt.Title:Reemplazar archivo con ...  # Updated 21-Mar-2006
+#**********************
+#
+#***** Save Collection Box *****
+SaveCollectionBox.File_Name:Nombre del archivo:
+SaveCollectionBox.Files_Of_Type:Ficheros de tipo:  # Updated 29-Jan-2006
+SaveCollectionBox.Look_In:Visita rÃ¡pida:
+#**********************
+#
+#***** Save Progress Box *******
+SaveProgressDialog.Title:Guardando la colecciÃ³n
+#*******************************
+#
+Server.QuitManual:La Interfaz de la Biblioteca Digital no pudo cerrar el servidor local\n de forma automÃ¡tica. Por favor salga manualmente del servidor\n haciendo click en el icono en forma de tache o cruz que se encuentra en el Ã¡ngulo superior\n derecho de la pantalla y luego haga click en Aceptar.
+Server.QuitTimeOut:La biblioteca local Greenstone no ha respondido durante los Ãºltimos sesenta segundos a la\n instrucciÃ³n de cerrar. Â¿Desea\n esperar otro minuto?
+#
+#***** Sources *****
+Source.General:General
+#*******************
+#
+#***** TitleClash *****
+TitleClashes.Message:El tÃ­tulo que usted ha elegido para su colecciÃ³n ya se estÃ¡ usando. Â¿Desea continuar?
+TitleClashes.Title:Este tÃ­tulo ya existe
+#**********************
+#
+#***** Trees *****
+Tree.DownloadedFiles:Ficheros Descargados  # Updated 29-Jan-2006
+Tree.Files:ficheros  # Updated 29-Jan-2006
+Tree.Home:Carpeta principal ({0})
+Tree.Root:Espacio de ficheros local  # Updated 29-Jan-2006
+Tree.World:Documentos en las Colecciones Greenstone
+#***********************
+#
+#***** Warning Dialog *****
+WarningDialog.Dont_Show_Again:No mostrar este aviso otra vez.
+WarningDialog.Dont_Show_Again_Message:No mostrar este mensaje otra vez
+WarningDialog.Invalid_Value:El valor que usted ha ingresado en el campo de valores\n no es vÃ¡lido para esta propiedad.
+WarningDialog.Value:Introduzca el valor:  # Updated 29-Jan-2006
+#
+#****** WGet *****
+WGet.Prompt:Cliente de descarga Wget  # Updated 29-Jan-2006
+#
+#****** Workflows *****
+Workflow.AllPanels:Todos los paneles
+Workflow.LocalSourceCollectionBuilding:Construyendo la colecciÃ³n de fuente local
+Workflow.DocumentEnriching:Enriqueciendo el documento
+
+GEMS.Already_Loaded_Set_Error:El conjunto de metadatos seleccionado ya estÃ¡ abierto.
+GEMS.Element_Already_Exists:Ya existe un elemento con ese nombre
+GEMS.Set_Already_Exists:Un conjunto con este namespace ya existe
+GEMS.Cannot_Delete_Core_Sets_Error:No puede borrar un conjunto de metadatos fundamental de GLI.
+
+GEMS.Preferences.Selected_Languages_Tooltip:Seleccionar los lenguajes a mostrar:
+
+GEMS.Add_Attribute:AÃ±adir atributo
+GEMS.Add_Attribute_Tooltip:Le aÃ±ade un nuevo atributo al elemento seleccionado
+GEMS.Add_Element:AÃ±adir elemento
+GEMS.Add_Element_Tooltip:Le aÃ±ade un nuevo elemento al conjunto seleccionado
+GEMS.Add_Subelement:Agregar subelemento
+GEMS.Add_Subelement_Tooltip:Agregar un  nuevo subelemento al elemento seleccionado
+GEMS.Add_Set:AÃ±adir conjunto
+GEMS.Attribute:Atributo
+GEMS.Attribute_Already_Exists:Este atributo ya existe.
+GEMS.Attribute_Name_Tooltip:Es el nombre del nuevo atributo
+GEMS.Attribute_Language_Tooltip:Es el idioma del nuevo atributo
+GEMS.Attribute_Value_Tooltip:Es el valor del nuevo atributo
+GEMS.Attributes:Atributos
+GEMS.Cannot_Undo:(esta acciÃ³n no se puede deshacer)
+GEMS.Cannot_Add_Elements_To_Greenstone_MDS:No se pueden aÃ±adir manualmente elementos a los Conjuntos de Metadatos de Greenstone. En caso\n necesario, construya un nuevo conjunto y aÃ±Ã¡dale el nuevo elemento.  # Updated 29-Jan-2006
+GEMS.Confirm_Exit_Save:Â¿Deasea salvar antes de salir?
+GEMS.Confirm_Exit_Save_Title:Â¿Salvar Antes de Salir?
+GEMS.Confirm_Removal:Â¿EstÃ¡ seguro de que desea eliminar este {0}?
+GEMS.Confirm_Removal_Title:Â¿EstÃ¡ seguro de querer eliminarlo?
+GEMS.Edit_Attribute:Editar atributo
+GEMS.Edit_Value:Editar valor
+GEMS.Edit_Value_Tooltip:Cambia el valor seleccionado
+GEMS.Element:Elemento
+GEMS.Element_Name_Tooltip:Es el nombre del nuevo elemento
+GEMS.Element_Details:Detalles del elemento de metadato
+GEMS.Language:Idioma
+GEMS.Language_Code:Idioma
+GEMS.Name:Nombre
+GEMS.Namespace:Indicador del conjunto
+GEMS.New_Name:Nuevo Nombre
+GEMS.No_Description:No se encontrÃ³ la descripciÃ³n.
+GEMS.No_Name:No se encontrÃ³ el nombre.
+GEMS.Open_Set:Conjunto Abierto
+GEMS.Remove_Attribute:Remover atributo
+GEMS.Remove_Attribute_Tooltip:Elimina el atributo seleccionado
+GEMS.Remove_Element:Remover elemento
+GEMS.Remove_Element_Tooltip:Elimina el elemento seleccionado del conjunto
+GEMS.Remove_Set:Remover conjunto
+GEMS.Remove_Set_Tooltip:Elimina el conjunto seleccionado
+GEMS.Rename_Element:Renombrar elemento
+GEMS.Rename_Element_Tooltip:Nuevo nombre del elemento
+GEMS.Rename_Name_Tooltip:Nuevo nombre del conjunto de metadatos
+GEMS.Rename_Namespace_Tooltip:Espacio de nombres Ãºnico del conjunto de metadatos
+GEMS.Rename_Set:Renombrar conjunto
+GEMS.Rename_Set_Tooltip:Renombrar el conjunto de metadatos
+GEMS.Set:Conjunto
+GEMS.Set_Details:Detalles del conjunto de metadatos
+GEMS.Set_Name_Tooltip:Es el nombre del nuevo conjunto de metadatos
+GEMS.Set_Namespace_Tooltip:Es un indicador Ãºnico para el nuevo conjunto de metadatos
+GEMS.Subelement_Name_Tooltip:Nombre del nuevo subelemento
+GEMS.Subelement_Already_Exists:Ya existe un subelemento con este nombre.
+GEMS.Target:Elemento
+GEMS.Title:Editar conjuntos de metadatos
+GEMS.Value:Valor
+GEMS.Values:Valores
+GEMS.inheritMetadataSet:Heredar del conjunto de metadatos:
+GEMS.Add_Set.No_Inherit:No heredar
Index: /tags/greenstone-3_02-distribution/gli/classes/dictionary_lv.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gli/classes/dictionary_lv.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/classes/dictionary_lv.properties	(revision 13928)
@@ -0,0 +1,1033 @@
+#*******************
+#
+#***** AboutDialog *****
+AboutDialog.Acknowledgement:PateicÄ«bas par programmÄm, paketÄm vai klasÄm...
+AboutDialog.Date:(Decembris 2006)
+AboutDialog.Item0:Xerces Java 1' no The Apache Software Foundation (http://www.apache.org/)
+AboutDialog.Item2:WGet' no Free Software Foundation, Inc. (http://www.gnu.org/software/wget/wget.html)
+AboutDialog.Item3:qflib' no Quality First Software GmbH. (http://www.qfs.de/en/qflib/index.html)
+AboutDialog.Item4:ExtensionFileFilter.class'  Bruno Dumon un lÄ«dzstrÄdnieki (http://pollo.sourceforge.net/)
+AboutDialog.Item5:KÄ aizliegt datnes pÄrdÄvÄÅ¡anu datnes izvÄlnÄ' - vladi21 (http://www.experts-exchange.com/)
+AboutDialog.Item6:Autoscrolling' - Java Swing pateicoties Robert Eckstein, Marc Loy & Dave Wood (http://www.oreilly.com/catalog/jswing/chapter/dnd.beta.pdf)
+AboutDialog.Item7:Add ghosted drag images to your JTrees' - pateicoties Andrew J. Armstrong (http://www.javaworld.com/javaworld/javatips/jw-javatip114.html)
+AboutDialog.Item8:NovÄrsta nepatÄ«kama java.prefs kÄŒÅ«da, ja jums nav administrÄtora pieejas' - pateicoties Walter Schatz
+AboutDialog.Java_Req:Java ir Sun Microsystems Inc. firmas zÄ«me. JRE tiek distribÅ«tÄta pie Papildus Licences NosacÄ«jumiem (Supplemental License Terms), kura atrodama uz http://java.sun.com/j2se/1.4.1/j2re-1_4_1_02-license.html
+AboutDialog.Java_Req_One:Å is produkts iekÄŒauj kodus licencÄtas RSA Security, Inc.
+AboutDialog.Java_Req_Two:DaÅŸas programmatÅ«ras daÄŒas ir IBM licencÄtas un pieejamas uz http\://oss.software.ibm.com/icu4j/
+AboutDialog.Thanks:ArÄ« pateicamies tiem, kuri publicÄja noderÄ«gu informÄciju par java uz web...
+AboutDialog.Title:Par...
+AboutDialog.Title_One:Greenstone BibliotekÄra Interfeiss (GBI)
+AboutDialog.Title_Two:Greenstone DigitÄlÄ BibliotÄka, Waikato UniversitÄte
+AboutDialog.Copyright:Copyright (C) 2006 New Zealand Digital Library Project
+AboutDialog.Copyright_Two:PublicÄts zem GPL. VairÄk skatÄ«t LICENSE.txt.
+#***********************
+#
+#***** Audit Table *****
+AuditTable.File:Datne
+#***********************
+#
+#***** Auto Filter *****
+Autofilter.AND:UN
+Autofilter.Ascending:PieaugoÅ¡s
+Autofilter.Case_Sensitive:SakritÄ«bas GadÄ«jums
+Autofilter.Custom_Filter:Uzlabots
+Autofilter.Descending:DilstoÅ¡s
+Autofilter.Filter_By_Value:VienkÄrÅ¡s
+Autofilter.Name:Kolonnas VÄrds
+Autofilter.None:NekÄds
+Autofilter.Operator:NosacÄ«jums
+Autofilter.OR:VAI
+Autofilter.Order:SakÄrtoÅ¡ana
+Autofilter.Order_Tooltip:SakÄrtot sakrÄ«toÅ¡os elementus Å¡ÄdÄ secÄ«bÄ
+Autofilter.Remove:NoÅemt Filtru
+Autofilter.Remove_Tooltip:NoÅemt Å¡o filtru no tabulas kolonnas
+Autofilter.Set:Uzdot Filtru
+Autofilter.Set_Tooltip:Pievienot Å¡o filtru tabulas kolonnai
+Autofilter.Table_Header_Tooltip:FiltrÄt pÄc {0}
+Autofilter.Title:Metadatu Autofiltrs
+Autofilter.eqeq:vienlÄ«dzÄ«gs
+Autofilter.!eq:does not equal
+Autofilter.<:is less than
+Autofilter.<eq:is less than or equal to
+Autofilter.>:is greater than
+Autofilter.>eq:is greater than or equal to
+Autofilter.^:starts with
+Autofilter.!^:does not start with
+Autofilter.$:ends with
+Autofilter.!$:does not end with
+Autofilter.?:contains
+Autofilter.!?:does not contain
+#
+#     ********************************************************
+#     *************** Collection Design Module ***************
+#     ********************************************************
+#     * The dictionary  phrases  used in the creation of the *
+#     * Colection  Design  Module. Note that we  still  have *
+#     * access  to the format  arguments (argument  32+) for *
+#     * html formatting.                                     *
+#     ********************************************************
+CDM.ArgumentConfiguration.Add:Pievienot
+CDM.ArgumentConfiguration.Bad_Integer:<html>Arguments '{0}' prasa veselu skaitli,<br>bet ne vesels skaitlis var bÅ«t analizÄts no {1}.</html>
+CDM.ArgumentConfiguration.Custom_Header:IestatÄ«Å¡ana
+CDM.ArgumentConfiguration.Custom:IestatÄ«Å¡anas Argumenti:
+CDM.ArgumentConfiguration.Error_Title:KÄŒÅ«da Argumentos
+CDM.ArgumentConfiguration.Header:<HTML><STRONG><FONT FACE={FONT} COLOR=Black SIZE=5><CENTER>LÅ«dzu konfigurÄt argumentus priekÅ¡ {0}.</CENTER></FONT></STRONG></HTML>
+CDM.ArgumentConfiguration.No_Value:Arguments '{0}'  prasa vÄrtÄ«bu, bet tÄ nav norÄdÄ«ta.
+CDM.ArgumentConfiguration.Remove:NoÅemt
+CDM.ArgumentConfiguration.Required_Argument:Argumentam '{0}' jÄbÅ«t norÄdÄ«ta vÄrtÄ«ba.
+CDM.ArgumentConfiguration.Title:Argumentu KonfigurÄÅ¡ana
+CDM.ClassifierManager.Add:Pievienot Klasifikatoru...
+CDM.ClassifierManager.Add_Tooltip:Lietot norÄdÄ«to klasifikatoru ar Å¡o kolekciju
+CDM.ClassifierManager.Assigned:PaÅ¡laik PieÅ¡Ä·irtie Klasifikatori
+CDM.ClassifierManager.Classifier:IzvÄlieties klsifikatoru, ko pievienot:
+CDM.ClassifierManager.Classifier_Tooltip:Klasifikatori pieejami lietoÅ¡anai kolekcijÄ
+CDM.ClassifierManager.Classifier_Exists:Å is klasifikators ir jau nozÄ«mÄts Å¡ai kolekcijai.
+CDM.ClassifierManager.Classifier_Str:klasifikators
+CDM.ClassifierManager.Classifier_XML_Parse_Failed:NespÄju noteikt argumentus {0}\nklasifikatoram. LÅ«dzu pÄrliecinieties, ka klasifikators\nnodroÅ¡ina -xml karodziÅu, palaiÅŸot classinfo.pl skriptu\nlÄ«dzÄ«gi, ka skripta pluginfo.pl gadÄ«jumÄ,\nkÄ aprakstÄ«ts dokumentÄ Greenstone Developers Guide sekcijÄ 2.1.
+CDM.ClassifierManager.Configure:KonfigurÄt Klasifikatoru...
+CDM.ClassifierManager.Configure_Tooltip:IzvÄlÄtÄ klasifikÄtora opciju maiÅa
+CDM.ClassifierManager.Remove:NoÅemt Klasifikatoru
+CDM.ClassifierManager.Remove_Tooltip:NoÅemt izvÄlÄto klasifikatoru no saraksta
+CDM.ClassifierManager.Parsing.Message:Tiek ielÄdÄta klasifikatoru informÄcija...  # Updated 10-Jun-2006
+CDM.ClassifierManager.Parsing.Title:Klasifikatoru IelÄdÄÅ¡ana
+CDM.FormatManager.Add:Pievienot FormÄtu
+CDM.FormatManager.Add_Tooltip:Izmantot specificÄto formÄta komandu ar kolekciju
+CDM.FormatManager.Assigned_Formats:PaÅ¡laik NozÄ«mÄtÄs FormÄta Komandas
+CDM.FormatManager.Editor:HTML FormÄta Rinda
+CDM.FormatManager.Editor_Tooltip:Ievadiet formÄta komandu Å¡eit
+CDM.FormatManager.Enabled:AtÄŒauts
+CDM.FormatManager.Feature:IzvÄlÄties PazÄ«mi
+CDM.FormatManager.Feature_Tooltip:PazÄ«me kuru formatÄt
+CDM.FormatManager.Insert:Iespraust
+CDM.FormatManager.Insert_Tooltip:Iespraust izvÄlÄto mainÄ«go formÄta komandÄ
+CDM.FormatManager.Part:IetekmÄtÄ Komponente
+CDM.FormatManager.Part_Tooltip:IzvÄlÄtÄs pazÄ«mes aspekts, ko formatÄt
+CDM.FormatManager.Remove:NoÅemt FormÄtu
+CDM.FormatManager.Remove_Tooltip:NoÅemt izvÄlÄto formÄta komandu no saraksta
+CDM.FormatManager.Replace:NomainÄ«t FormÄtu
+CDM.FormatManager.Replace_Tooltip:AktualizÄt izvÄlÄto formÄta komandu
+CDM.FormatManager.Variable:MainÄ«gie
+CDM.FormatManager.Variable_Tooltip:MainÄ«gie pieejami izmantoÅ¡anai formÄta komandÄ
+CDM.General.Access:Å ai kolekcijai jÄbÅ«t publiski pieejamai
+CDM.General.Browser_Title:IzvÄlieties AttÄlu
+CDM.General.Collection_Extra:Kolekcijas apraksts:
+CDM.General.Collection_Extra_Tooltip:Kolekcijas satura un nodoma apraksts
+CDM.General.Collection_Name:Kolekcijas nosaukums:
+CDM.General.Collection_Name_Tooltip:Kolekcijas nosaukums
+CDM.General.Email.Creator:Autora epasts
+CDM.General.Email.Creator_Tooltip:Kolekcijas autora e-pasta adrese
+CDM.General.Email.Maintainer:AtbalstÄ«tÄja epasts
+CDM.General.Email.Maintainer_Tooltip:Kolekcijas atbalstÄ«tÄja (apkalpotÄja) e-patsta adrese
+CDM.General.Icon_Collection:URL uz 'Par' lapas ikonu:
+CDM.General.Icon_Collection_Tooltip:URL uz attÄlu (ikonu), ko attÄlot kolekcijas 'Par' lapÄ
+CDM.General.Icon_Collection_Small:URL uz 'mÄjas' lapas ikonu:
+CDM.General.Icon_Collection_Small_Tooltip:URL uz attÄlu (ikonu), ko attÄlot bibliotÄkas mÄjas lapÄ
+CDM.General.Image_Copy_Failed:AtgadÄ«jÄs kÄŒÅ«da, kura neÄŒauj jÅ«su izvÄlÄto attÄlu(s) nokopÄt.\nLÅ«dzu mÄÄ£iniet manuÄli nokopÄt attÄlu(s):\n{0}\n uz jÅ«su kolekcijas:\n{1}\n images mapi  # Updated 22-Apr-2006
+CDM.General.Image_Filter:AttÄli (gifs, jpgs un pngs)
+CDM.GUI.Classifiers:PÄrlÅ«koÅ¡anas Klasifikatori
+CDM.GUI.Design_Topics:Dezaina Sekcijas
+CDM.GUI.Formats:FormatizÄÅ¡ana
+CDM.GUI.General:VispÄrÄ«gi
+CDM.GUI.Indexes:MeklÄÅ¡anas Indeksi
+CDM.GUI.MetadataSets:Metadatu Kopas
+CDM.GUI.Plugins:Dokumentu SpraudÅi
+CDM.GUI.Root:CDM_ROOT
+CDM.GUI.SearchTypes:MeklÄÅ¡anas Tipi
+CDM.GUI.Subcollections:SadalÄ«jumu Indeksi
+CDM.GUI.SuperCollection:Starp-Kolekciju MeklÄÅ¡ana
+CDM.GUI.Translation:Teksta TulkoÅ¡ana
+CDM.HelpButton:DotÄ ekrÄna palÄ«gs  # Updated 22-Apr-2006
+CDM.HelpButton_Tooltip:AtvÄrt dotÄ ekrÄna GBI palÄ«gu  # Updated 22-Apr-2006
+CDM.IndexManager.Add_Index:Pievienot Indeksu
+CDM.IndexManager.Add_Index_Tooltip:Izveidot specifisku indeksu Å¡ai kolekcijai
+CDM.IndexManager.Allfields_Index:Pievienot kombinÄto meklÄÅ¡anu uz visiem indeksiem (visiem laukiem)  # Updated 22-Apr-2006
+CDM.IndexManager.Default_Index_Indicator:[NoklusÄjuma Indeks]
+CDM.IndexManager.Document:dokuments
+CDM.IndexManager.Index_Exists:Å is indeks esot jau bijis nozÄ«mÄts dotai kolekcijai.
+CDM.IndexManager.Index_Name:Indeksa VÄrds:
+CDM.IndexManager.Index_Name_Tooltip:UnikÄls nosaukums jaunam indeksam
+CDM.IndexManager.Indexes:NozÄ«mÄtie Indeksi
+CDM.IndexManager.Level:LÄ«menÄ«:
+CDM.IndexManager.Level_Exists:Å is lÄ«menis jau esot ticis nozÄ«mÄts dotai kolekcijai.
+CDM.IndexManager.Level_Tooltip:Dokumenta lÄ«menis uz kura veidot indeksu
+CDM.IndexManager.MGPP.Add_All_Metadata:Pievienot Visu
+CDM.IndexManager.MGPP.Add_All_Metadata_Tooltip:Izveidot atseviÅ¡Ä·u indeksu katram atseviÅ¡Ä·i pieejamam avotam, izmantojot avotu kÄ indeksa vÄrdu
+CDM.IndexManager.MGPP.Add_Level:Pievienot LÄ«meni
+CDM.IndexManager.MGPP.Add_Level_Tooltip:Izveidot indeksu uz norÄdÄ«to lÄ«meni
+CDM.IndexManager.MGPP.Current_Levels:Patreiz NozÄ«mÄtie LÄ«meÅi
+CDM.IndexManager.MGPP.Indexes:AdministrÄt Indeksus
+CDM.IndexManager.MGPP.Level:LÄ«meÅa Avots:
+CDM.IndexManager.MGPP.Level_Name:LÄ«meÅa VÄrds:
+CDM.IndexManager.MGPP.Level_Name_Tooltip:UnikÄls vÄrds jauna lÄ«meÅa indeksam
+CDM.IndexManager.MGPP.Levels:AdministrÄt LÄ«meÅus
+CDM.IndexManager.MGPP.Remove_Level:NoÅemt LÄ«meni
+CDM.IndexManager.MGPP.Remove_Level_Tooltip:NoÅemt izvÄlÄtÄ lÄ«meÅa indeksu
+CDM.IndexManager.MGPP.Replace_Index:NomainÄ«t Indeksu
+CDM.IndexManager.MGPP.Replace_Index_Tooltip:AktualizÄt izvÄlÄto indeksu
+CDM.IndexManager.Paragraph:paragrÄfs
+CDM.IndexManager.Remove_Index:NoÅemt Indeksu
+CDM.IndexManager.Remove_Index_Tooltip:NoÅemt izvÄlÄto indeksu no saraksta
+CDM.IndexManager.Section:sekcija
+CDM.IndexManager.Set_Default:Uzdot NoklusÄjuma Indeksu
+CDM.IndexManager.Set_Default_Tooltip:Uzdot izvÄlÄto indeksu, kÄ indeksu pÄc noklusÄjuma
+CDM.IndexManager.Source:Izveidot indeksu uz:
+CDM.IndexManager.Source_Tooltip:Metadatu elementi uz kuriem izveidot indeksus
+CDM.LanguageManager.Add:Pievienot Valodu
+CDM.LanguageManager.Add_Tooltip:Pievienot norÄdÄ«to valodu sarakstam
+CDM.LanguageManager.Assigned_Languages:NozÄ«mÄtÄs Valodas
+CDM.LanguageManager.Default_Language:NoklusÄjuma Valoda
+CDM.LanguageManager.Remove:NoÅemt Valodu
+CDM.LanguageManager.Remove_Tooltip:NoÅemt izvÄlÄto valodu no saraksta
+CDM.LanguageManager.Selector:Valoda ko pievienot:
+CDM.LanguageManager.Selector_Tooltip:Valoda uz kuras izveidot sadalÄ«juma indeksu
+CDM.LanguageManager.Set_Default:Uzdot NoklusÄjumu
+CDM.LanguageManager.Set_Default_Tooltip:Uzdot izvÄlÄto valodu kÄ noklusÄjumu
+CDM.MetadataSetManager.Add:Pievienot Metadatu Kopu...  # Updated 22-Apr-2006
+CDM.MetadataSetManager.Add_Tooltip:Pievienot kolekcijai jaunu metadatu kopu.
+CDM.MetadataSetManager.Edit:RediÄ£Ät Metadatu Kopu...  # Updated 22-Apr-2006
+CDM.MetadataSetManager.Edit_Message:Metadatu kopas var bÅ«t rediÄ£Ätas, izmantojot Greenstone Metadatu Kopu Redaktoru GEMS (Greenstone Editor for Metadata Sets).\nPalaidiet GEMS no Windows izmantojot \nStarts-->Greenstone DigitÄlÄs BibliotÄkas ProgrammatÅ«ra-->GEMS.\nNo Linux vai Mac palaist gems.sh no Greenstone instalÄcijas mapes ar nosaukumu gli.  # Updated 22-Apr-2006
+CDM.MetadataSetManager.Edit_Message_Title:Metadatu Kopu RediÄ£ÄÅ¡ana
+CDM.MetadataSetManager.Edit_Tooltip:RediÄ£Ät izvÄlÄto metadatu kopu.
+CDM.MetadataSetManager.Elements:Elementi izvÄlÄtÄ Metadatu KopÄ
+CDM.MetadataSetManager.Remove:DzÄst Metadatu Kopu
+CDM.MetadataSetManager.Remove_Tooltip:DzÄst izvÄlÄto metadatu kopu no kolekcijas.
+CDM.MetadataSetManager.Sets:PieejamÄs Metadatu Kopas
+CDM.MetadataSetManager.Chooser.Add:Pievienot
+CDM.Move.At_Bottom:Nevaru pÄrvietot {0} {1} zemÄk, jo tas jau ir paÅ¡Ä saraksta apakÅ¡Ä.
+CDM.Move.At_Top:Nevaru pÄrvietot {0} {1} augstÄk, jo tas jau ir paÅ¡Ä saraksta virsotnÄ.
+CDM.Move.Cannot:Nevaru pÄrvietot spraudni {0} zemÄk, jo RecPlug un ArcPlug jÄatrodas saraksta paÅ¡Ä apakÅ¡Ä.
+CDM.Move.Fixed:<html>RecPlug un ArcPlug parasti ir nepiecieÅ¡ams bÅ«t pÄdÄjiem un tÄdÄÄŒ ir fiksÄti savÄ vietÄ.<br>Ja jums patiesi vajag mainÄ«t viÅu pozÄ«cijas, tad lÅ«dzu rediÄ£Äjiet collect.cfg datni manuÄli.</html>
+CDM.Move.Move_Down:PÄrvietot ZemÄk
+CDM.Move.Move_Down_Tooltip:PÄrvietot izvÄlÄto elementu zemÄk sarakstÄ
+CDM.Move.Move_Up:PÄrvietot AugstÄk
+CDM.Move.Move_Up_Tooltip:PÄrvietot izvÄlÄto elementu augstÄk sarakstÄ
+CDM.Move.Title:KÄŒÅ«da - Nevaru PÄrvietot
+CDM.PlugInManager.Add:Pievienot Spraudni...
+CDM.PlugInManager.QuickAdd:Pievienot Spraudni
+CDM.PlugInManager.Add_Tooltip:Izmantot norÄdÄ«to spraudni Å¡ajÄ kolekcijÄ
+CDM.PlugInManager.Assigned:Patreiz NozÄ«mÄtie SpraudÅi
+CDM.PlugInManager.Configure:KonfigurÄt Spraudni...
+CDM.PlugInManager.Configure_Tooltip:IzmainÄ«t opcijas izvÄlÄtam spraudnim
+CDM.PlugInManager.Ignore:Nepievienot Spraudni
+CDM.PlugInManager.Ignore_Tooltip:Nepievienot nevienu spraudni Å¡ai kolekcijai.
+CDM.PlugInManager.PlugIn:IzvÄlieties spraudni ko pievienot:
+CDM.PlugInManager.PlugIn_Tooltip:Pieejamie spraudÅi izmantoÅ¡anai kolekcijÄ
+CDM.PlugInManager.PlugIn_Exists:Å is spraudnis jau esot pievienots Å¡ai kolekcijai.
+CDM.PlugInManager.PlugIn_Str:spraudnis
+CDM.PlugInManager.PlugIn_XML_Parse_Failed:Nevaru noteikt argumentus {0}\nspraudnim. LÅ«dzu pÄrliecinieties, ka spraudnis nodroÅ¡ina\n -xml karodziÅu, palaiÅŸot pluginfo.pl skriptu, kÄ aprakstÄ«ts\ndokumentÄ Greenstone Developers Guide sekcijÄ 2.1.
+CDM.PluginManager.Plugin_Suggestion_Prompt:Nav sagaidÄms, ka kÄds no spraudÅiem Å¡ajÄ kolekcijÄ varÄtu apstrÄdÄt datni â{0}â.SekojoÅ¡ie spraudÅi var bÅ«t izmantoti, lai apstrÄdÄtu Å¡o datni. JÅ«s varat pievienot vienu tagad, izvÄloties to, un nospieÅŸot Pievienot pogu. (JÄpiezÄ«mÄ, ka jÅ«s varat jebkurÄ laikÄ izmainÄ«t spraudÅu sarakstu izmantojot âDokumentu SpraudÅiâ no paneÄŒa Dizains.)
+CDM.PlugInManager.Remove:NoÅemt Spraudni
+CDM.PlugInManager.Remove_Tooltip:DzÄst izvÄlÄto spraudni no saraksta
+CDM.PluginManager.SuggestedPluginListTitle:Ieteicamie spraudÅi datnei
+CDM.PlugInManager.Parsing.Message:Tiek ielÄdÄta spraudÅu informÄcija...  # Updated 10-Jun-2006
+CDM.PlugInManager.Parsing.Title:IelÄdÄ SpraudÅus
+CDM.SearchTypeManager.Add:Pievienot MeklÄÅ¡nas Tipu
+CDM.SearchTypeManager.Add_Tooltip:AtÄŒaut noteiktu meklÄÅ¡anas tipu Å¡ajÄ kolekcijÄ
+CDM.SearchTypeManager.Assigned:Patreiz NozÄ«mÄtie MeklÄÅ¡anas Tipi
+CDM.SearchTypeManager.BuildType_Selection:IndeksÄtÄjs:  # Updated 19-Aug-2005
+CDM.SearchTypeManager.BuildType_Selection_Tooltip:IzvÄlieties indeksÄtÄju, ko lietot ar Å¡o kolekciju.  # Updated 19-Aug-2005
+CDM.SearchTypeManager.Enable:AtÄŒaut PaplaÅ¡inÄtÄs MeklÄÅ¡anas
+CDM.SearchTypeManager.Remove:DzÄst MeklÄÅ¡anas Tipu
+CDM.SearchTypeManager.Remove_Tooltip:NeatÄŒaut izvÄlÄto meklÄÅ¡anas tipu ar Å¡o kolekciju
+CDM.SearchTypeManager.SearchType:MeklÄÅ¡anas Tips
+CDM.SearchTypeManager.SearchType_Selection:MeklÄÅ¡anas Tipi:
+CDM.SearchTypeManager.SearchType_Selection_Tooltip:MeklÄÅ¡anas tipi pieejami izmantoÅ¡anai ar Å¡o kolekciju
+CDM.SubcollectionManager.Add:Pievienot Filtru
+CDM.SubcollectionManager.Add_Tooltip:Pievienot norÄdÄ«to filtru kolekcijai
+CDM.SubcollectionManager.Assigned:DefinÄtie ApkÅ¡kolekciju Filtri
+CDM.SubcollectionManager.Exclude:IzslÄgt
+CDM.SubcollectionManager.Flags:Uzdodamais karodziÅÅ¡ pie sakritÄ«bas
+CDM.SubcollectionManager.Flags_Tooltip:KarodziÅu regulÄrÄ izteiksme, kura izmantojama pie sakritÄ«bas (piem. "i" reÄ£istrnejÅ«tÄ«gai sakritÄ«bai)
+CDM.SubcollectionManager.Include:IekÄŒaut
+CDM.SubcollectionManager.Inclusive:Ko mÄs darÄm ar datnÄm, kuras sakrÄ«t?
+CDM.SubcollectionManager.Language_Controls:NozÄ«mÄt Valodas
+CDM.SubcollectionManager.Match:SakritÄ«bas regulÄrÄ izteiksme:
+CDM.SubcollectionManager.Match_Tooltip:RegulÄrÄ izteiksme, kura definÄ dokumentus apakÅ¡kolekcijÄ
+CDM.SubcollectionManager.Name:ApakÅ¡kolekcijas filtra vÄrds:
+CDM.SubcollectionManager.Name_Tooltip:JaunÄ apakÅ¡kolekcijas filtra nosaukums
+CDM.SubcollectionManager.Partitions_Disabled:Å Ä« iespÄja patreiz ir aizliegta, jo jÅ«s operÄjat {0-Current Mode} reÅŸÄ«mÄ. Tas ir tikai pieejams {1-Systems} un {2-Expert} reÅŸÄ«mos. Lietojiet Datne->IestatÄ«jumi, lai izmainÄ«tu operÄÅ¡anas reÅŸÄ«mus.
+CDM.SubcollectionManager.Remove:NoÅemt Filtru
+CDM.SubcollectionManager.Remove_Tooltip:DzÄst izvÄlÄto filtru no saraksta
+CDM.SubcollectionManager.Replace:Aizvietot Filtru
+CDM.SubcollectionManager.Replace_Tooltip:Aizvietot un aktualizÄt izvÄlÄtÄ filtra detaÄŒas
+CDM.SubcollectionManager.Source:Dokumenta atribÅ«ts pÄc kura jÄsakrÄ«t:
+CDM.SubcollectionManager.Source_Tooltip:Dokumenta atribÅ«ts pÄc kura filtrÄt
+CDM.SubcollectionManager.Subcollection_Controls:DefinÄt Filtrus
+CDM.SubcollectionManager.Subindex_Controls:NozÄ«mÄt SadalÄ«jumus
+CDM.SubcollectionIndexManager.Add_Subindex:Pieviento SadalÄ«jumu
+CDM.SubcollectionIndexManager.Add_Subindex_Tooltip:Pievienot norÄdÄ«to sadalÄ«jumu Å¡ai kolekcijai
+CDM.SubcollectionIndexManager.Default_Partition_Indicator:[NoklusÄjuma SadalÄ«jums]
+CDM.SubcollectionIndexManager.PartitionName:SadalÄ«juma VÄrds:
+CDM.SubcollectionIndexManager.PartitionName_Tooltip:JaunÄ sadalÄ«juma nosaukums
+CDM.SubcollectionIndexManager.Remove_Subindex:NoÅemt SadalÄ«jumu
+CDM.SubcollectionIndexManager.Remove_Subindex_Tooltip:IzdzÄst izvÄlÄto sadalÄ«jumu no Å¡Ä«s kolekcijas
+CDM.SubcollectionIndexManager.Replace_Subindex:Aizvietot SadalÄ«jumu
+CDM.SubcollectionIndexManager.Replace_Subindex_Tooltip:Azvietot izvÄlÄto sadalÄ«jumu
+CDM.SubcollectionIndexManager.Set_Default_Subindex:Uzdot NoklusÄjumu
+CDM.SubcollectionIndexManager.Set_Default_Subindex_Tooltip:Uzdot izvÄlÄto sadalÄ«jumu bÅ«t pÄc noklusÄjuma
+CDM.SubcollectionIndexManager.Source:Veidot sadalÄ«jumu uz:
+CDM.SubcollectionIndexManager.Source_Tooltip:ApakÅ¡kolekcijas filtri uz kuriem veidot sadalÄ«jumu
+CDM.SubcollectionIndexManager.Subindexes:NozÄ«mÄtie ApakÅ¡kolekcijas SadalÄ«jumi
+CDM.TranslationManager.Add:Pievienot Tulkojumu
+CDM.TranslationManager.Add_Tooltip:Pievienot specificÄto tulkojumu kolekcijai
+CDM.TranslationManager.Affected_Features:PazÄ«mes
+CDM.TranslationManager.Assigned_Fragments:NozÄ«mÄtie Tulkojumi
+CDM.TranslationManager.Default_Text:SÄkotnÄjs Teksta Fragments
+CDM.TranslationManager.Fragment_Column:Teksta Fragments
+CDM.TranslationManager.Language:Tulkojuma valoda:
+CDM.TranslationManager.Language_Column:Valoda
+CDM.TranslationManager.Language_Tooltip:Valoda uz kuru tiek tulkots
+CDM.TranslationManager.Remove:NoÅemt Tulkojumu
+CDM.TranslationManager.Remove_Tooltip:IzdzÄst izvÄlÄto tulkojumu no kolekcijas
+CDM.TranslationManager.Replace:Aizvietot Tulkojumu
+CDM.TranslationManager.Replace_Tooltip:AktualizÄt (aizvietot) izvÄlÄto tulkojumu
+CDM.TranslationManager.Translation:Iztulkotais Teksts
+CDM.TranslationManager.Translation_Tooltip:Iztulkota teksta rindu ievadiet Å¡eit
+#*******************
+#
+#***** Collection *****
+Collection.Collection:<HTML><STRONG><FONT FACE={FONT} COLOR=Black>Kolekcija</FONT></STRONG></HTML>
+Collection.Delete_Tooltip:IzdzÄst izvÄlÄtÄs datnes un mapes
+Collection.Filter_Tooltip:IerobeÅŸot datÅu atrÄdÄ«Å¡anu datÅu kokÄ
+Collection.New_Folder_Tooltip:Izveidot jaunu mapi
+Collection.No_Collection:Nav Kolekcijas
+Collection.No_Collection_Loaded:Nav ielÄdÄtas kolekcijas  # Updated 10-Jun-2006
+Collection.Stop:Stop
+Collection.Stop_Tooltip:PÄrtraukt datÅu kopÄÅ¡anu
+Collection.Workspace:<HTML><STRONG><FONT FACE={FONT} COLOR=Black>Darbatelpa</FONT></STRONG></HTML>
+#**********************
+#
+#***** CollectionBuilt *****
+CollectionBuilt.Message:Kolekcija esot izveidota un ir gatava priekÅ¡skatÄ«jumam.
+CollectionBuilt.Title:Kolekcijas IzveidoÅ¡anas RezultÄts
+#***************************
+#
+#***** CollectionManager *****
+CollectionManager.Build_Cancelled:Kolekcijas veidoÅ¡ana tikusi anulÄta.
+CollectionManager.Cannot_Create_Collection:AtgadÄ«jusies kÄŒÅ«da un kolekcija nevar bÅ«t izveidota.
+CollectionManager.Cannot_Create_Collection_With_Reason:Kolekcija nevar tikt radÄ«ta dÄÄŒ:\n{0-Error message}  # Updated 19-Aug-2005
+CollectionManager.Cannot_Delete_Index:Kolekcija nevar tikt veidota no jauna, jo nevaru izdzÄst vecÄs indeksa datnes.\n LÅ«dzu pÄrbaudiet, ka Greenstone vai cita programma neizmanto Å¡Ä«s datnes,\n un mÄÄ£iniet vÄlreiz.
+CollectionManager.Cannot_Delete_Index_Log:VecÄs indeksa datnes nevar tikt izdzÄstas, tÄpÄc importÄÅ¡ana pÄrtraukta.
+CollectionManager.Cannot_Open:Kolekcija:\n{0-Collection file path}\nnevar bÅ«t atvÄrta.
+CollectionManager.Cannot_Open_With_Reason:Kolekcija:\n{0-Collection file path}\nnevar bÅ«t atvÄrta jo:\n{1-Error message}
+CollectionManager.Creating_New:Jaunas kolekcijas radÄ«Å¡ana.
+CollectionManager.Log_Created:Log mape izveidota.
+CollectionManager.Loading_Collection:Kolekcijas ielÄdÄÅ¡ana
+CollectionManager.Loading_Collection_Please_Wait:Kolekcijas ielÄdÄÅ¡ana, lÅ«dzu uzgaidiet...
+CollectionManager.Loading_Successful:IelÄdÄtÄ kolekcija {0}.
+CollectionManager.Missing_Config:Å ai kolekcijai nav pareiza collect.cfg datne
+CollectionManager.Not_Col_File:{0}' neesot BibliotekÄra Interfeisa Kolekcijas Datne (.col)
+CollectionManager.No_Config_File:Datne collect.cfg netika radÄ«ta ar mkcol.pl.  # Updated 19-Aug-2005
+CollectionManager.Preview_Ready_Failed:AtgadÄ«jÄs kÄŒÅ«da, kura neÄŒauj, lai kolekcija tiktu priekÅ¡skatÄ«ta.
+CollectionManager.Preview_Ready_Title:Kolekcijas PriekÅ¡skatÄ«juma StÄvoklis.
+CollectionManager.Session_Ready:Kolekcija {0} gatava izmantoÅ¡anai.
+CollectionManager.Build_Not_Moved:VeidoÅ¡anas direktorijs (ar nosaukumu 'building') nevar tikt pÄrvietots.  # Updated 4-Nov-2005
+CollectionManager.Index_Not_Deleted:Index direktorijs nevar tikt izdzÄsts.  # Updated 4-Nov-2005
+CollectionManager.Install_Exception:Kolekcijas uzstÄdÄ«Å¡anas laikÄ konstatÄta problÄma:\n{0}\nIespÄjamais cÄlonis ir Windows
+#*****************************
+#
+#***** CollectionPopupMenu *****
+CollectionPopupMenu.Delete:IzdzÄst
+CollectionPopupMenu.New_Dummy_Doc:Jauns fiktÄ«vs dokuments
+CollectionPopupMenu.New_Folder:Jauna mape
+CollectionPopupMenu.Rename:PÄrdÄvÄt  # Updated 22-Apr-2006
+CollectionPopupMenu.Replace:Aizvietot
+#*******************************
+#
+#***** CreatePane *****
+CreatePane.Build:VeidoÅ¡anas Opcijas
+CreatePane.Build_Tooltip:Opcijas kolekcijas formÄÅ¡anas indeksÄcijas un klasifikÄcijas stadijÄ
+CreatePane.Build_Collection:Veidot Kolekciju
+CreatePane.Build_Collection_Tooltip:SÄkt kolekcijas formÄÅ¡anas procesu
+CreatePane.Build_Progress:VeidoÅ¡anas Progress
+CreatePane.Cancel_Build:Atcelt Veidot
+CreatePane.Cancel_Build_Tooltip:PÄrtraukt kolekcijas formÄÅ¡anas procesu
+CreatePane.Full_Build:PilnÄ«ga PÄrveidoÅ¡ana  # Updated 19-Aug-2005
+CreatePane.Full_Build_Tooltip:PilnÄ«gi pÄrveidot kolekciju no jauna  # Updated 19-Aug-2005
+CreatePane.Import:Importa Opcijas
+CreatePane.Import_Tooltip:Opcijas kolekcijas formÄÅ¡anas datÅu convertÄcijas un metadatu pieÅ¡Ä·irÅ¡anas stadijÄ
+CreatePane.Import_Progress:Importa Progress
+CreatePane.Incremental_Build:InkrementÄlÄ VeidoÅ¡ana  # Updated 19-Aug-2005
+CreatePane.Incremental_Build_Tooltip:ÄtrÄk, par cik, tikai daÄŒa no visa nepiecieÅ¡amÄ kolekcijas veidoÅ¡anas procesa tiek veikta.  # Updated 19-Aug-2005
+CreatePane.Log:PaziÅojumu Log
+CreatePane.Log_Tooltip:SkatÄ«t izvadu no iepriekÅ¡Äjiem kolekcijas formÄÅ¡anas mÄÄ£inÄjumiem
+CreatePane.Mode_All:all  # Updated 29-Apr-2006
+CreatePane.Options:Opciju Grupas
+CreatePane.Options_Title:Kolekcijas Importa & VeidoÅ¡anas Opcijas
+CreatePane.Preview_Collection:PriekÅ¡skatÄ«t Kolekciju
+CreatePane.Preview_Collection_Tooltip:PriekÅ¡skatÄ«t izveidotu kolekciju
+#**********************
+#
+#***** Dates *****
+Dates.Mon:Pirmdiena
+Dates.Tue:Otrdiena
+Dates.Wed:TreÅ¡diena
+Dates.Thu:Ceturtdiena
+Dates.Fri:Piektdiena
+Dates.Sat:Sestdiena
+Dates.Sun:SvÄtdiena
+Dates.Jan:JanvÄris
+Dates.Feb:FerbruÄris
+Dates.Mar:Marts
+Dates.Apr:AprÄ«lis
+Dates.May:Maijs
+Dates.Jun:JÅ«nijs
+Dates.Jul:JÅ«lijs
+Dates.Aug:Augusts
+Dates.Sep:Septembris
+Dates.Oct:Oktobris
+Dates.Nov:Novembris
+Dates.Dec:Decembris
+#**********************
+#
+#***** Delete Collection Prompt *****
+DeleteCollectionPrompt.Collection_Details:IzvÄlÄtÄs kolekcijas detaÄŒas
+DeleteCollectionPrompt.Collection_List:Pieejamas kolekcijas
+DeleteCollectionPrompt.Confirm_Delete:LÅ«dzu atzÄ«mÄjiet rÅ«tiÅu, lai apstiprinÄtu kolekcijas izdzÄÅ¡anu.
+DeleteCollectionPrompt.Delete:IzdzÄst
+DeleteCollectionPrompt.Delete_Tooltip:IzdzÄst izvÄlÄto kolekciju
+DeleteCollectionPrompt.Details:VeidotÄjs - {0}\nAtbalstÄ«tÄjs - {1}\nApraksts\n{2}
+DeleteCollectionPrompt.Failed_Delete:Kolekcija nevar bÅ«t pilnÄ«gi izdzÄsta.
+DeleteCollectionPrompt.Failed_Title:IzdzÄÅ¡ana NeizdevÄs!
+DeleteCollectionPrompt.No_Collection:Nav izvÄlÄta kolekcija.
+DeleteCollectionPrompt.Successful_Delete:Kolekcija tikusi izdzÄsta.
+DeleteCollectionPrompt.Successful_Title:IzdzÄÅ¡ana Pabeigta!
+DeleteCollectionPrompt.Title:Kolekcijas IzdzÄÅ¡ana
+#**********************
+#
+#***** DirectoryLevelMetadata *****
+DirectoryLevelMetadata.Message:JÅ«s taisÄties pieÅ¡Ä·irt 'mapes lÄ«meÅa' metadatus izvÄlÄtai mapei (vai mapÄm). Å os metadatus automÄtiski pÄrmantos visas datnes un mapes Å¡ajÄ mapÄ. TurklÄt Å¡ie metadata nevar bÅ«t vienkÄrÅ¡i noÅemti, bet tikai aizvietoti. Lai turpinÄtu Å¡o darbÄ«bu nospiediet 'OK'.
+DirectoryLevelMetadata.Title:Par mapes lÄ«meÅa metadatu pievienoÅ¡anu
+#********************
+#
+#***** EnrichPane *****
+EnrichPane.AutoMessage:Å is elements, {0}, pieder Greenstone metadatu kopai. Å Ä« kopa reprezentÄ metadatus, kuri parasti var bÅ«t izvilkti automÄtiski. Lai pÄrbaudÄ«tu, kÄdi  {0} metadati var tikt izvilkti, radiet kolekciju izmantojot 'RadÄ«t' paneli.  # Updated 29-Apr-2006
+EnrichPane.ExistingValues:EsoÅ¡Äs {0} vÄrtÄ«bas  # Updated 29-Apr-2006
+EnrichPane.InheritedMetadataSelected:Å ie metadati ir pÄrmantoti no mapes virs tÄs, un nevar bÅ«t rediÄ£Äti.
+EnrichPane.No_File:Nav IzvÄlÄtas Datnes
+EnrichPane.No_Metadata:Nav Pieejami Metadati
+EnrichPane.No_Metadata_Element:<HTML><STRONG><FONT FACE={FONT} COLOR=Black>Nav Metadatu Elements IzvÄlÄts</FONT></STRONG></HTML>
+EnrichPane.NotOneFileOnlyMetadataSelected:Å Ä« metadatu daÄŒa neattiecas tikai uz Å¡o datni, tÄpÄc nevar bÅ«t rediÄ£Äta.  # Updated 22-Apr-2006
+EnrichPane.Value_Field_Tooltip:VÄrtÄ«ba, ko pieÅ¡Ä·irt izvÄlÄtam metadatu elementam
+EnrichPane.Value_Field_Tooltip_Uneditable:VÄrtÄ«ba, kura pieÅ¡Ä·irta izvÄlÄtam metadatu elementam
+#***********************
+#
+#****** ExplodeMetadataPrompt *******
+ExplodeMetadataPrompt.Explode:SadalÄ«t
+ExplodeMetadataPrompt.Explode_Tooltip:SadalÄ«t metadatu datni
+ExplodeMetadataPrompt.Instructions:Sadalot Å¡o metadatu datni tiks producÄti individuÄli ieraksti ar rediÄ£Äjamiem metadatiem. Å is ir neatgrieÅŸams process un kolekcijas originÄlÄ metadatu datne tiks izdzÄsta.
+ExplodeMetadataPrompt.Failed_Title:SadalÄ«Å¡ana NeizdevÄs.
+ExplodeMetadataPrompt.Failed_Explode:DatubÄze {0} nevar bÅ«t sadalÄ«ta.
+ExplodeMetadataPrompt.NotExplodable:DotÄ datne nav sadalÄma.
+ExplodeMetadataPrompt.Successful_Explode:DatubÄze {0} sekmÄ«gi sadalÄ«ta.
+ExplodeMetadataPrompt.Successful_Title:SadalÄ«Å¡ana Pabeigta.
+ExplodeMetadataPrompt.Title:SadalÄ«t Metadatu DatubÄzi
+#***********************
+#
+#****** WriteCDImagePrompt *******
+WriteCDImagePrompt.CD_Name:CD/DVD vÄrds
+WriteCDImagePrompt.Export:RakstÄ«t CD/DVD attÄlu
+WriteCDImagePrompt.Export_Tooltip:RakstÄ«t izvÄlÄtÄs kolekcijas, kÄ Windows CD/DVD AttÄlus
+WriteCDImagePrompt.Failed_Export:Kolekcijas ({0}) nevarÄja bÅ«t eksportÄtas.
+WriteCDImagePrompt.Failed_Title:Eksports NeizdevÄs
+WriteCDImagePrompt.Instructions:Vienas vai vairÄku kolekciju eksports uz paÅ¡instalÄjoÅ¡os Windows CD/DVD (kaut arÄ« tas darbojas uz jebkuras platformas, CD/DVD, kas tiek radÄ«ts, palaiÅŸas tikai zem Windows).  # Updated 22-Apr-2006
+WriteCDImagePrompt.Progress_Label:DatÅu kopÄÅ¡ana. Tas var aizÅemt zinÄmu laiku...
+WriteCDImagePrompt.Size_Label:NovÄrtÄtais izmÄrs:  # Updated 4-Nov-2005
+WriteCDImagePrompt.Successful_Export:Kolekcijas ({0}) esot tikuÅ¡as eksportÄtas.
+WriteCDImagePrompt.Successful_Title:Eksports Pabeigts
+WriteCDImagePrompt.Title:Kolekcijas Eksports uz CD/DVD
+#************************
+#
+#****** ExportAsPrompt *******
+ExportAsPrompt.Export_Name:Eksporta mapes nosaukums
+ExportAsPrompt.Export:EksportÄt kolekciju(as)
+ExportAsPrompt.Export_Tooltip:EksportÄt izvÄlÄtÄs kolekcijas uz noteiktu mapi un izvÄlÄtÄ formÄtÄ
+ExportAsPrompt.Failed_ExportOne:Kolekcija, {0}, nevar bÅ«t eksportÄta.
+ExportAsPrompt.Failed_ExportMany:Kolekcijas -- {0} -- nevar bÅ«t eksportÄtas.
+ExportAsPrompt.Failed_Details:SkatÄ«t {1} sÄ«kÄk
+ExportAsPrompt.Failed_Title:Eksports NeizdevÄs
+ExportAsPrompt.Instructions:EksportÄt vienu vai vairÄkas kolekcijas izvÄlÄtÄ formÄtÄ uz noteiktu mapi
+ExportAsPrompt.Progress_Label:Datnes tiek eksportÄtas. Tas var aizÅemt zinÄmu laiku...
+ExportAsPrompt.Successful_ExportOne:Kolekcija, {0}, esot tikusi eksportÄta.
+ExportAsPrompt.Successful_ExportMany:Kolekcijas -- {0} -- esot tikuÅ¡as eksportÄtas.
+ExportAsPrompt.Successful_Details:Datnes eksportÄtas uz: {1}
+ExportAsPrompt.Successful_Title:Eksports Pabeigts
+ExportAsPrompt.Title:EksportÄt Kolekcijas
+ExportAsPrompt.SaveAs:EksportÄt uz
+ExportAsPrompt.SaveAs_Tooltip:IzvÄlieties formÄtu uz kuru jÅ«s vÄlaties eksportÄt
+#************************
+#
+#*****ExternalCollectionPrompt********
+ExternalCollectionPrompt.NewMDS:RadÄ«t jaunu, tukÅ¡u metadatu kopu.
+ExternalCollectionPrompt.ExistingMDS:IzvÄlieties vienu vai vairÄkas metadatu kopas
+ExternalCollectionPrompt.Title:IelÄdÄt Äreju kolekciju
+ExternalCollectionPrompt.Instructions_1:JÅ«s gribat ielÄdÄt kolekciju, kura netika izveidota ar GBI. JÅ«s tiksiet aicinÄti izvÄlÄties vienu vai vairÄkas metadatu kopas, kuras izmantot ar doto kolekciju. EksistÄjoÅ¡ie metadati tiks importÄti izvÄlÄtajÄ(s) metadatau kopÄ(s). OriginÄlÄs metadatu datnes tiks saglabÄtas mapÄ ar nosaukumu import.bak.
+ExternalCollectionPrompt.Instructions_2:JÅ«s gribat ielÄdÄt kolekciju, kura netika izveidota ar GBI. Jums nepiecieÅ¡ams pievienot metadatu kopu Å¡ai kolekcijai. JÅ«s varat radÄ«t jaunu tukÅ¡u metadatu kopu, kurai visi atrastie metadatu elementi kolekcijÄ tiks automÄtiski pievienoti. AlternatÄ«vi, jÅ«s varat izvÄlÄties eksistÄjoÅ¡as metadatu kopas, un elementi no kolekcijas tiks apvienoti vai pievienoti jau esoÅ¡iem elementiem Å¡ajÄs kopÄs. OriÄ£inÄlÄs metadatu datnes tiks saglabÄtas mapÄ ar nosaukumu import.bak.
+#****************************************
+#
+#***** Inherited Metadata *****
+ExtractedMetadata.Message:IzvÄletÄ datne vai mape satur izvilktus metadatus, bet patreiz tie ir neredzami. Lai redzÄtu izvilktus metadatus, dodieties uz "[D]atne" izvÄlni un izvÄlieties "[I]estatÄ«jumi". "VispÄrÄ«gi" rekvizÄ«tu lapÄ izvÄlieties "SkatÄ«t Izvilktus Metadatus", tad nospieÅŸiet "[O]k".
+ExtractedMetadata.Title:Å Ä« Datne/Mape satur Neredzamus Izvilktus Metadatus
+#
+#***** FileActions *****
+FileActions.Calculating_Size:Tiek kalkulÄts izvÄlÄto datÅu kopÄjais izmÄrs
+FileActions.Copying:KopÄju {0}
+FileActions.Could_Not_Delete:Nevaru izdzÄst {0}  # Updated 22-Apr-2006
+FileActions.Cyclic_Path:Nevaru kopÄt {0}: adresÄtÄ mape ir avota mapes apakÅ¡mape.  # Updated 22-Apr-2006
+FileActions.Deleting:IzdzÄÅ¡u {0}
+FileActions.Directories_Selected:{0} izvÄlÄtÄm mapÄm  # Updated 29-Apr-2006
+FileActions.Directory_Selected:1 izvÄlÄtai mapei  # Updated 29-Apr-2006
+FileActions.File_Already_Exists_No_Create:Datne '{0}' jau eksistÄ.
+FileActions.File_Already_Exists_Message:{0}\nDatne ar nosaukumu, kas parÄdÄ«ta augstÄk jau eksistÄ\nun par spÄ«ti jÅ«su iepriekÅ¡Äjai izvÄlei BibliotekÄra Interfeiss\nnevar to pÄrrakstÄ«t. LÅ«dzu pÄrbaudiet vai datne ir rakstÄ«t atÄŒauta.
+FileActions.File_Already_Exists_Title:KÄŒÅ«da - Datne Jau EksistÄ.
+FileActions.File_And_Directories_Selected:1 datnei un {0} izvÄlÄtÄm mapÄm  # Updated 29-Apr-2006
+FileActions.File_And_Directory_Selected:izvÄlÄtai 1 datnei un 1 mapei  # Updated 29-Apr-2006
+FileActions.File_Create_Error:Datne {0} nevar tikt radÄ«ta.
+FileActions.Folder_Create_Error:Mape {0} nevar tikt radÄ«ta.
+FileActions.File_Exists:{0} jau eksistÄ saÅÄmÄjmapÄ. PÄrrakstÄ« to?
+FileActions.File_Move_Error_Message:Nevaru pÄrvietot {0} uz\n{1}.  # Updated 22-Apr-2006
+FileActions.File_Not_Deleted_Message:{0}\nAugstÄk minÄtÄ datne nevar tikt izdzÄsta. \nLÅ«dzu pÄrbaudiet, ka jums Å¡Ä« datne nav
+FileActions.File_Not_Deleted_Title:KÄŒÅ«da - Datne nav IzdzÄsta.  # Updated 4-Nov-2005
+FileActions.File_Not_Found_Message:{0}\nAugstÄk minÄtÄ datne nevar tikt atrasta. LÄ«dz ar datÅu skata\natjaunoÅ¡anu, lÅ«dzu pÄrbaudiet, ka datne vÄl eksistÄ.
+FileActions.File_Not_Found_Title:KÄŒÅ«da - Datne nav atrasta.
+FileActions.File_Selected:1 izvÄlÄtai datnei  # Updated 29-Apr-2006
+FileActions.Files_And_Directory_Selected:izvÄlÄtÄm {0} datnÄm un 1 mapei  # Updated 29-Apr-2006
+FileActions.Files_Selected:{0} izvÄlÄtÄm datnÄm  # Updated 29-Apr-2006
+FileActions.Folder_Already_Exists:Mape ar nosaukumu '{0}' tiek jau lietota. Nevaru radÄ«t mapi.
+FileActions.Increase_Depth:PalielinÄt DziÄŒumu par 1
+FileActions.Insufficient_Space_Message:DarbÄ«ba ar datni neizdevÄs, jo nepietiek vietas\nuz diska. Lai sekmÄ«gi nokopÄtu datni jums turmÄk\nnepiecieÅ¡ams: {0}
+FileActions.Insufficient_Space_Title:KÄŒÅ«da - Nepietiek Vietas
+FileActions.Moving:PÄrvietoju {0}
+FileActions.No_Activity:Nav pieprasÄ«tas darbÄ«bas
+FileActions.Possible_Cyclic_Path:{1} ir {0} mapes dziÄŒumÄ un var bÅ«t rekursÄ«vs ceÄŒÅ¡? Vai datÅu darbÄ«bu turpinÄt?
+FileActions.Read_Not_Permitted_Message:Nevaru nolasÄ«t {0}.  # Updated 22-Apr-2006
+FileActions.Read_Only:Datnes no darbatelpas ir tikai lasÄmas un navar bÅ«t izdzÄstas.
+FileActions.Replacing:Aizvieto {0}  # Updated 22-Apr-2006
+FileActions.Selected:izvÄlÄtÄm {0} datnÄm un {1} mapÄm  # Updated 29-Apr-2006
+FileActions.Unknown_File_Error_Message:Lai gan nebija kÄŒÅ«da reportÄta datnes darbÄ«bas\nlaikÄ, gala pÄrbaude parÄda, ka\nkopijas datne nav tÄ pati kÄ avota datne. TÄ cÄlonis\nnav zinÄms. LÅ«dzu pÄrbaudiet jÅ«su disku un atjaunojiet\njÅ«su instalÄto JVM.
+FileActions.Unknown_File_Error_Title:KÄŒÅ«da - NezinÄma Datnes KÄŒÅ«da
+FileActions.Write_Not_Permitted_Message:BibliotekÄra Interfeisam nav atÄŒaujas rakstÄ«t\n{0}\nLÅ«dzu pÄrbaudiet datnes atÄŒaujas atribÅ«tus.
+FileActions.Write_Not_Permitted_Title:KÄŒÅ«da - Nepareizas Datnes AtÄŒaujas
+FileActions.Yes_To_All:JÄ uz Visiem
+#************************
+#
+#******* File Associations dialog **********
+FileAssociationDialog.Add:Pievienot
+FileAssociationDialog.Add_Tooltip:Izmantojiet Å¡o lietojumprogrammu, lai skatÄ«tu Å¡Ä tipa datni
+FileAssociationDialog.Batch_File:PakeÅ¡datnes
+FileAssociationDialog.Browse:PÄrlÅ«kot
+FileAssociationDialog.Browse_Tooltip:IzvÄlieties lietojumprogrammu, ko izmantot no jÅ«su datÅutelpas
+FileAssociationDialog.Browse_Tooltip_Mac:JÅ«su lietojumprogrammas pÄrlÅ«koÅ¡ana patreiz ir aizliegta priekÅ¡ MacOS
+FileAssociationDialog.Browse_Title:IzvÄlieties Lietojumprogrammu
+FileAssociationDialog.Close:AizvÄrt
+FileAssociationDialog.Close_Tooltip:Aizveriet Å¡o dialogu un atgriezieties uz galveno logu
+FileAssociationDialog.Command:PalaiÅ¡anas komanda:
+FileAssociationDialog.Command_File:Komanddatnes
+FileAssociationDialog.Command_Tooltip:Ievadiet komandu ar kuru palaist lietojumprogrammu
+FileAssociationDialog.Details:JaunÄs Datnes AsociÄcijas DetaÄŒas
+FileAssociationDialog.Executable_File:IzpildÄmÄs datnes
+FileAssociationDialog.Existing_Associations:AktuÄlÄs Datnes AsociÄcijas
+FileAssociationDialog.Extension:DatnÄm kas beidzas ar:
+FileAssociationDialog.Extension_Tooltip:SkatÄmo datÅu datnes paplaÅ¡inÄjums
+FileAssociationDialog.Instructions:Izmantojiet Å¡o dialogu, lai uzstÄdÄ«tu, kÄdas ÄrÄjÄs programmas tiks lietotas skatot noteiktu datnes-tipu, un kÄda komanda tiks nosÅ«tÄ«ta, lai  palaistu Å¡o programmu.\nLai pievienotu jaunu datnes-tipu, ievadiet tÄs paplaÅ¡inÄjumu lauciÅÄ 'DatnÄm kas beidzas ar'. Lai pievienotu vai modificÄtu palaiÅ¡anas komandu, ievadiet jaunu komandu lodziÅÄ 'PalaiÅ¡anas Komanda' vai noklikÅ¡Ä·iniet 'PÄrlÅ«kot', ja vÄlaties meklÄt datÅu sistÄmÄ attiecÄ«go programmu. Izmantojiet formÄtu '%1', lai indicÄtu vietu, kur vajadzÄtu tikt iespraustam datnes nosaukumam atveramai datnei, piemÄram, "C:\\Windows\\System\\MSPaint.exe %1". '%1' tiks pievienots komandas galÄ, ja netiks specificÄts citÄdi.\nMacOS lietotÄjiem vienmÄr vispirms jÄmÄÄ£ina specifisko mac komandu "open [-a <application_name>] %1".
+FileAssociationDialog.Table.Command:Komanda
+FileAssociationDialog.Table.Extension:PaplaÅ¡inÄjums
+FileAssociationDialog.Title:RediÄ£Ät Datnes AsociÄcijas
+FileAssociationDialog.Remove:NoÅemt
+FileAssociationDialog.Remove_Tooltip:IzdzÄst patreiz izvÄlÄto asociÄciju no eksistÄjoÅ¡o asociÄciju saraksta
+FileAssociationDialog.Replace:Aizvietot
+FileAssociationDialog.Replace_Tooltip:Aizvietot patreiz izvÄlÄto asociÄciju ar jaunÄm asociÄcijas detaÄŒÄm
+#*******************
+#
+#******Filter***************
+Filter.0:HTM & HTML
+Filter.1:XML
+Filter.2:Teksta Datnes
+Filter.3:AttÄli
+Filter.All_Files:Visas Datnes
+Filter.Filter_Tree:ParÄdÄ«t Datnes
+Filter.Invalid_Pattern:<HTML><FONT FACE={FONT} COLOR=Black>Å ablonu, ko jÅ«s esat ievadÄ«juÅ¡i datÅu filtrÄcijai, ir nederÄ«gs.<BR>LÅ«dzu mÄÄ£iniet vÄlreiz, izmantojot regulÄras izteiksmes sintaksi un ar<BR>* norÄdot aizstÄjÄjzÄ«mi.</FONT></HTML>
+#***********************
+#
+#***** GAuthenticator *****
+GAuthenticator.Password:Parole:
+GAuthenticator.Password_Tooltip:Ievadiet Å¡eit jÅ«su paroli
+GAuthenticator.Title:Parole ir NepiecieÅ¡ama.
+GAuthenticator.Username:LietotÄja VÄrds:
+GAuthenticator.Username_Tooltip:Ievadiet Å¡eit jÅ«su lietotÄjvÄrdu
+#**************************
+#
+#***** General Messages *****
+# 0 - A String representing the name and method of the class in question.
+General.Apply:Lietot
+General.Apply_Tooltip:Pielietot patreizÄjos uzstatÄ«jumus, bet neiziet no dialoga
+General.Browse:PÄrlÅ«kot...
+General.Cancel:Atcelt
+General.Cancel_Tooltip:Atcelt izmaiÅas (neatsauks jebkuru jau pielietotu izmaiÅu)
+General.Close:AizvÄrt
+General.Close_Tooltip:AizvÄrt Å¡o dialoglodziÅu
+General.Edit:RediÄ£Ät VÄrtÄ«bu
+General.Error:KÄŒÅ«da
+General.No:NÄ
+General.NotSunJava:Java vendor: {0}\nIevÄrojiet, ka BibliotekÄra Interfeiss ir ticis attÄ«stÄ«ts un testÄts ar Java no Sun Microsystems.
+General.OK:OK
+General.OK_Tooltip:AkceptÄt patreizÄjos iestatÄ«jumus un iziet no dialoga
+General.Open:AtvÄrt
+General.Outstanding_Processes:<html>BibliotekÄra Interfeiss nevar pilnÄ«gi beigt darbu, kamÄr visas programmas<br>startÄtas ar BibliotekÄra Interfeisu arÄ« nav pabeigtas.</html>
+General.Outstanding_Processes_Title:GaidoÅ¡s lai Izietu
+General.Pure_Cancel_Tooltip:PÄrtraukt Å¡o darbÄ«bu (izmaiÅas netiks veiktas)
+General.Review_Output:LÅ«dzu pÄrlÅ«kojiet izvadu zemÄk:
+General.Usage:LietoÅ¡ana: {0} <params>\nVisi parametri ir neobligÄti, bet BibliotekÄra Interfeiss var nojukt darbÄ, ja -gsdl un -library nav uzstÄdÄ«ti.\n -gsdl <path> : NorÄda ceÄŒu uz gsdl\n - library <path> : CeÄŒu uz cgi-bin\n -mozilla <path> : NorÄda ceÄŒu uz mozilla\n -mirror : AtÄŒauj web-mirroring kontroles\n -laf [java|windows|motif|mac] : Look and feel\n debug : AtÄŒauj kÄŒÅ«du paziÅojumus\n -no_load : NeielÄdÄt iepriekÅ¡ atvÄrtu kolekciju\n -load <path> : IelÄdÄt norÄdÄ«to kolekciju
+General.View:JaunÄ VÄrtÄ«ba
+General.Warning:BrÄ«dinÄjums
+General.Yes:JÄ
+#****************************
+#
+#***** GShell *****
+GShell.BadArgument:Arguments {0} ir nepareizs.  # Updated 4-Nov-2005
+GShell.BadArgumentValue:Argumeta {0} vÄrtÄ«ba ir nepareiza.  # Updated 4-Nov-2005
+GShell.BadPluginOptions:Nepareiz arguments nodots spraudnim {0}.  # Updated 4-Nov-2005
+GShell.BadClassifierOptions:Sastapts slikts arguments klasifikatorÄ {0}.  # Updated 4-Nov-2005
+GShell.Build.Auxilary:PalÄ«gdatÅu radÄ«Å¡ana un apstrÄde...
+GShell.Build.BuildBegun1:************** VeidoÅ¡ana  UzsÄkta **************
+GShell.Build.BuildCancelled:**************   AnulÄts    **************
+GShell.Build.BuildComplete1:************** VeidoÅ¡ana Pabeigta **************
+GShell.Build.CompressText:Teksta SaspieÅ¡ana...
+GShell.Build.Index:Indeksa radÄ«Å¡ana bÄzÄjoties uz {0-index source and level}...
+GShell.Build.InfoDatabase:InformÄcijas datu bÄzes radÄ«Å¡ana...
+GShell.Build.Phind:Klasifikatora Phind Ä£enerÄÅ¡ana. Tas var aizÅemt zinÄmu laiku...
+GShell.Command:Komanda
+GShell.Failure:Komanda izpildÄ«jÄs nesekmÄ«gi.
+GShell.Import.FileNotProcessed:Datne {0-target file path} bija atpazÄ«ta, bet nevarÄja tikt apstrÄdÄta ar kÄdu no spraudÅiem (plugin).
+GShell.Import.FileNotRecognised:Datne {0-target file path} nebija atpazÄ«ta ne ar vienu spraudni.
+GShell.Import.FileProcessing:Datne {0-target file path} tiek apstrÄdÄta ar {1-plugin name}.
+GShell.Import.FileProcessingError:Datnes {0-target file path} apstrÄdes process sadÅ«rÄs ar kÄŒÅ«du.
+GShell.Import.ImportBegun1:************** Imports  SÄcies **************
+GShell.Import.ImportComplete1:************** Imports Pabeigts **************
+GShell.Import.ImportComplete2:{0-number documents considered} dokumenti bija izskatÄ«ti apstrÄdei:
+GShell.Import.ImportComplete2.1:1 dokuments bija izskatÄ«ts apstrÄdei:
+GShell.Import.ImportComplete.Processed:{0-number processed} dokumenti bija apstrÄdÄti un iekÄŒauti kolekcijÄ.
+GShell.Import.ImportComplete.Processed.1:1 dokuments bija apstrÄdÄts un iekÄŒauts kolekcijÄ.
+GShell.Import.ImportComplete.Blocked:{0-number blocked} bija atturÄti no pievienoÅ¡anas ar spraudÅiem (tÄdi kÄ web lappuÅ¡u attÄli).
+GShell.Import.ImportComplete.Blocked.1:1 bija atturÄts no pievienoÅ¡anas ar spraudÅiem (tÄdi kÄ web lappuÅ¡u attÄli).
+GShell.Import.ImportComplete.Ignored:{0-number ignored} bija neatpazÄ«ti.
+GShell.Import.ImportComplete.Ignored.1:1 bija neatpazÄ«ts.
+GShell.Import.ImportComplete.Failed:{0-number failed} bija noraidÄ«ti.
+GShell.Import.ImportComplete.Failed.1:1 bija noraidÄ«ts.
+GShell.Import.ImportComplete3:\n
+GShell.Parsing_Metadata_Complete:ArhivÄtu metadatu izvilkÅ¡ana pabeigta.
+GShell.Parsing_Metadata_Start:Jaunu metadatu izvilkÅ¡ana no arhÄ«vu datnÄm.
+GShell.Success:Komanda pabeigta.
+#*********************
+#
+#***** GUI *****
+# Currently Enabled and Disabled display the same text but in different
+# colours. If necessary this can be changed.
+GUI.Create:RadÄ«t
+GUI.Create_Tooltip:Veidot jÅ«su kolekciju izmantojot Greenstone
+GUI.Design:Dizains
+GUI.Design_Tooltip:JÅ«su kolekcijas funkcionalitÄtes un izskata dizains
+GUI.Download:LejupielÄde
+GUI.Download_Tooltip:LejupielÄdÄt resursus no Interneta jÅ«su kolekcijai
+GUI.Enrich:PagÄtinÄt
+GUI.Enrich_Tooltip:NozÄ«mÄt metadatus datnÄm jÅ«su kolekcijÄ
+GUI.Gather:UzkrÄt
+GUI.Gather_Tooltip:IzvÄlÄties datnes, kuras iekÄŒaut jÅ«su kolekcijÄ
+#***************
+#
+#***** HELP *****
+Help.Contents:Saturs
+Help.Title:BibliotekÄra Interfeisa PalÄ«ga Lappuses
+#****************************
+#
+#***** Invalid Metadata ******
+InvalidMetadata.Message:Å is metadatu elements ir ierobeÅŸots ar iepriekÅ¡definÄtu vÄrtÄ«bu kopu. LÅ«dzu izvÄlÄties vienu no eksistÄjoÅ¡Äm vÄrtÄ«bÄm.  # Updated 22-Apr-2006
+InvalidMetadata.Title:Nepareizi Metadati  # Updated 22-Apr-2006
+#***************************
+#
+#***** LockFileDialog *****
+LockFileDialog.Cancel_Tooltip:NepÄrtvert slÄdzejdatnes kontroli (kolekcija netiks atvÄrta)
+LockFileDialog.Date:DatÄjums
+LockFileDialog.Error:error
+LockFileDialog.Lockfile_Message_One:SlÄdzÄjdatnes (lock file) klÄtbÅ«tne norÄda uz to, ka kolekcija ir jau atvÄrta.
+LockFileDialog.Lockfile_Message_Two:Vai jÅ«s gribat 'pÄrtvert' slÄdzÄjdatnes kontroli?
+LockFileDialog.Machine:Kur
+LockFileDialog.Name:Nosaukums
+LockFileDialog.OK_Tooltip:PÄrtvert slÄdzÄjdatnes kontroli
+LockFileDialog.Title:SlÄdzÄjdatne AtklÄta
+LockFileDialog.User:KurÅ¡
+#********************
+#
+#*****MappingPrompt **********
+MappingPrompt.File:Mape
+MappingPrompt.Map:RadÄ«t ÄªsinÄjumikonu
+MappingPrompt.Name:Nosaukums
+MappingPrompt.Title:Uzdot Mapes ÄªsinÄjumikonu
+MappingPrompt.Unmap:NoÅemt ÄªsinÄjumikonu
+#*******************
+#
+#***** Menu Options *****
+Menu.Collapse:AizvÄrt Mapi
+Menu.Edit:RediÄ£Ät
+Menu.Edit_Copy:KopÄt (ctrl-c)
+Menu.Edit_Cut:Izgriezt (ctrl-x)
+Menu.Edit_Paste:IelÄ«mÄt (ctrl-v)
+Menu.Expand:AtvÄrt Mapi
+Menu.Explode_Metadata_Database:SadalÄ«t metadatu datu bÄzi
+Menu.File:Datne
+Menu.File_Associations:Datnes AsociÄcijas...
+Menu.File_CDimage:IerakstÄ«t CD/DVD attÄlu...
+Menu.File_Close:AizvÄrt
+Menu.File_Delete:IzdzÄst...
+Menu.File_Exit:Iziet
+Menu.File_ExportAs:EksportÄt...
+Menu.File_New:Jauns...
+Menu.File_Open:AtvÄrt...
+Menu.File_Options:IestatÄ«jumi...
+Menu.File_Save:SaglabÄt
+Menu.Help:PalÄ«gs
+Menu.Help_About:Par...
+Menu.Metadata_View:NozÄ«mÄtie metadati {0}
+Menu.Open_Externally:AtvÄrt ar ÄrÄjo programmu
+#********************
+#
+#***** MetaAudit *****
+MetaAudit.Close:AizvÄrt
+MetaAudit.Close_Tooltip:AizvÄrt Å¡o dialoglodziÅu
+MetaAudit.Title:Visi Metadati
+#*********************
+#
+#***** Metadata *****
+Metadata.Element:Elements
+Metadata.Value:VÄrtÄ«ba
+MetadataSet.Files:Metadatu Kopas Datnes
+#*********************************************
+#
+#******** MetadataImportMappingPrompt *********
+MIMP.Add:Pievienot
+MIMP.Add_Tooltip:Pievienot metadatu elementu atlasÄ«tai kopai
+MIMP.Ignore:IgnorÄt
+MIMP.Ignore_Tooltip:IgnorÄt Å¡o metadatu elementu
+MIMP.Instructions:Metadatu elements {0} nevar bÅ«t automÄtiski importÄts kolekcijÄ. IzvÄlieties metadatu kopu un sekojoÅ¡i:\n(1) nospiediet  'Pievienot', lai pievienotu metadatus Å¡ai kopai (pie nosacÄ«juma, ja kopÄ jau nÄesot metadatu {0}), vai\n(2) izvÄlieties elementu un nospiediet  'IekÄŒaut', lai importÄtu {0} metadatus Å¡ajÄ elementÄ, vai\n(3) ignorÄjiet Å¡o metadatu elementu.
+MIMP.Merge:IekÄŒaut
+MIMP.Merge_Tooltip:IekÄŒaut metadatu elelementu specificÄtÄ elementÄ izvÄlÄtÄ kopÄ
+MIMP.Source_Element:Avota metadatu elements:
+MIMP.Target_Element:MÄrÄ·a metadatu elements:
+MIMP.Target_Set:MÄrÄ·a metadatu kopa:
+MIMP.Title:NepieceÅ¡ama IekÄŒauÅ¡anas DarbÄ«ba.
+#*****************************
+#
+#***** Mirroring *****
+Mirroring.ClearCache:IztÄ«rÄ«t KeÅ¡u
+Mirroring.ClearCache_Tooltip:IzdzÄst visas lejupielÄdÄtas datnes
+Mirroring.Download:LejupielÄde
+Mirroring.Download_Tooltip:SÄkt jaunu lejupielÄdes uzdevumu
+Mirroring.Download_Controls:LejupielÄdes UzstatÄ«jumi
+Mirroring.Download_Depth:LejupielÄdes DziÄŒums:
+Mirroring.Download_Depth.Zero:Nulle
+Mirroring.Download_Depth.Unlimited:NeierobeÅŸots
+Mirroring.Download_Depth_Tooltip:Cik daudz hipersaites dziÄŒumÄ iet lejupielÄdÄjot
+Mirroring.Download_OnlyHTML:LejupielÄdÄt tikai HTML datnes (ignorÄt asociÄtÄs datnes,piem., attÄlus un stila lapas)  # Updated 22-Apr-2006
+Mirroring.DownloadJob.Close:AizvÄrt
+Mirroring.DownloadJob.Close_Tooltip:NoÅemt Å¡o uzdevumu no saraksta, apstÄdinot to, ja tas patreiz izpildÄs
+Mirroring.DownloadJob.Downloading:{0} lejupielÄde
+Mirroring.DownloadJob.Download_Complete:LejupielÄde pabeigta
+Mirroring.DownloadJob.Download_Stopped:LejupielÄde apstÄdinÄta
+Mirroring.DownloadJob.Download_Progress:LejupielÄde ir progresÄ
+Mirroring.DownloadJob.Log:SkatÄ«t Log
+Mirroring.DownloadJob.Log_Tooltip:SkatÄ«t detalizÄtÄk par Å¡o lejupielÄdi
+Mirroring.DownloadJob.Pause:Pauze
+Mirroring.DownloadJob.Pause_Tooltip:PauzÄt Å¡o lejupielÄdi
+Mirroring.DownloadJob.Resume:AtsÄkt
+Mirroring.DownloadJob.Resume_Tooltip:AtsÄkt Å¡o lejupielÄdi
+Mirroring.DownloadJob.Status:LejupielÄdÄti {0} no {1} datnÄm ({2} brÄ«dinÄjumi, {3} kÄŒÅ«das)
+Mirroring.DownloadJob.Waiting:Gaida lai sÄktu
+Mirroring.DownloadJob.Waiting_User:Gaida uz lietotÄja darbÄ«bu
+Mirroring.Higher_Directories:Tikai atspoguÄŒot datnes zem Å¡Ä URL
+Mirroring.Invalid_URL:IevadÄ«tais URL nav pareizs. LÅ«dzu izlabojiet.
+Mirroring.Invalid_URL_Title:Nepareizs URL
+Mirroring.Preferences:IestatÄ«jumi...
+Mirroring.Preferences_Tooltip:AtÄŒaut starpnieku (proxy) un/vai rediÄ£Ät starpnieka iestatÄ«jumus
+Mirroring.Same_Host:Tikai atspoguÄŒot datnes Å¡ajÄ paÅ¡Ä vietnÄ
+Mirroring.Source_URL:Avota URL:
+Mirroring.Source_URL_Tooltip:LejupielÄdes URL
+#*********************
+#
+#***** Missing EXEC *****
+MissingEXEC.Message:BrÄ«dinÄjums! JÅ«s nevarÄsiet redzÄt jÅ«su jauno kolekciju no BibliotekÄra Interfeisa, ja jÅ«s nenorÄdÄ«siet ceÄŒu uz Greenstone BibliotekÄra Webserveri. JÅ«s to varat tagad ievadÄ«t teksta lauciÅÄ zemÄk, vai vÄlÄk aizejot uz IestatÄ«jumi un izvÄloties Savienojums tabulatoru. Atcerieties, ka pareizam url jÄsÄkas ar protokolu  "http://", un jÄbeidzas ar izpildÄmÄs programmas nosaukumu ("gsdl" Greenstone lokÄlas bibliotÄkas servera gadÄ«jumÄ, "library" visu pÄrejo web serveru gadÄ«jumos (piem., Apache)).  # Updated 4-Nov-2005
+MissingEXEC.Title:IztrÅ«kst Greenstone BibliotÄkas Adrese
+#***** Missing EXEC_GS3 *****
+MissingEXEC_GS3.Message:BrÄ«dinÄjums! JÅ«s nevarÄsiet redzÄt jÅ«su jauno kolekciju no BibliotekÄra Interfeisa, ja jÅ«s nenorÄdÄ«siet ceÄŒu uz Greenstone kontekstu lokÄli darbojoÅ¡os Tomcat WebserverÄ«. JÅ«s to varat tagad ievadÄ«t teksta lauciÅÄ zemÄk, vai vÄlÄk, aizejot uz IestatÄ«jumi un izvÄloties Savienojums tabulatoru. Atcerieties, ka pareizam url jÄsÄkas ar protokolu  http://. Adrese pÄc noklusÄjuma ir http://localhost:8080/greenstone3.  # Updated 4-Nov-2005
+MissingEXEC_GS3.Title:IztrÅ«kst Greenstone 3 BibliotÄkas Adrese  # Updated 4-Nov-2005
+#***** Missing GLIServer *****
+MissingGLIServer.Message:BrÄ«dinÄjums! JÅ«s nevarÄsiet strÄdÄt ar kolekcijÄm, izmantojot BibliotekÄra Interfeisu,
+MissingGLIServer.Title:IztrÅ«kst GLIServera Adrese  # Updated 4-Nov-2005
+#***** Missing GSDL *****
+MissingGSDL.Message:BrÄ«dinÄjums! JÅ«s nevarÄsiet izmantot visas BibliotekÄra Interfeisa iespÄjas bez instalÄtÄs Greenstone DigitÄlÄs BibliotÄkas lokÄlÄs kopijas. LÅ«dzu, pÄrbaudiet jÅ«su instalÄciju, un ceÄŒus BibliotekÄra Interfeisa pakeÅ¡datnÄ vai skripta datnÄ.
+MissingGSDL.Title:IztrÅ«kst Greenstone CeÄŒÅ¡
+#***** Missing PERL *****
+MissingPERL.Message:BrÄ«dinÄjums! JÅ«s nevarÄsiet radÄ«t jaunas kolekcijas, kÄ arÄ« veidot esoÅ¡as, bez uzinstalÄtÄ PERL. BibliotekÄra Interfeiss nevarÄja atrast PERL jÅ«su sistÄmÄ. LÅ«dzu, pÄrbaudiet jÅ«su sistÄmas instalÄciju un ceÄŒus, kuri specificÄti BibliotekÄra Interfeisa pakeÅ¡datnÄ vai skripta datnÄ.
+MissingPERL.Title:IztrÅ«kst PERL CeÄŒÅ¡
+#******* MissingWGET ********
+MissingWGET.Message:BrÄ«dinÄjums! Web atspoguÄŒoÅ¡ana ir liegta, jo BibliotekÄra Interfeiss nesekmÄ«gi mÄÄ£inÄja atrast atbilstoÅ¡as versijas Wget. LÅ«dzu, pÄrbaudiet jÅ«su sistÄmas instalÄciju un ceÄŒus, kuri specificÄti BibliotekÄra Interfeisa pakeÅ¡datnÄ vai skripta datnÄ.
+MissingWGET.Title:IztrÅ«kst WGet
+#******* MissingImageMagick ********
+MissingImageMagick.Message:BrÄ«dinÄjums! BibliotekÄra Interfeiss nevar atrast attiecÄ«go ImageMagick versiju, un tÄpÄc ImagePlug nedarbosies. LÅ«dzu, uzinstalÄjiet ImageMagick, ja jÅ«s vÄlÄties veidot attÄlu kolekcijas.
+MissingImageMagick.Title:IztrÅ«kst ImageMagick  # Updated 19-Aug-2005
+#*****************************
+#
+#***** New Session *****
+NewCollectionPrompt.Base_Collection:BÄzÄt Å¡o kolekciju uz:
+NewCollectionPrompt.Base_Collection_Tooltip:IzvÄlieties esoÅ¡o kolekciju uz kuras bÄzÄt jauno kolekciju
+NewCollectionPrompt.Collection_Description:Satura apraksts:
+#NewCollectionPrompt.Collection_Email:Author's Email:
+NewCollectionPrompt.Collection_Name:Kolekcijas mape:
+#NewCollectionPrompt.Collection_Name_Tooltip:Short collection name, used internally (must be 8 characters or less)
+NewCollectionPrompt.Error:KÄŒÅ«da jaunajÄ kolekcijÄ.
+NewCollectionPrompt.Instructions:Lai radÄ«tu jaunu kolekciju, aizpildiet lauciÅus zemÄk.
+NewCollectionPrompt.Metadata_Elements:Elementi izvÄlÄtajÄ kopÄ:
+NewCollectionPrompt.Metadata_Instructions1:IzvÄlieties rÅ«tiÅas blakus metadatu kopÄm, kuras iekÄŒaut jÅ«su kolekcijÄ.
+NewCollectionPrompt.Metadata_Instructions2:(PiezÄ«me: JÅ«s varat pievienot jaunas kopas vÄlÄk).
+NewCollectionPrompt.Metadata_Title_Existing:IzvÄlieties metadatu kopas.
+#NewCollectionPrompt.Name_Error:You have either failed to enter a name for the collection, or the name you have choosen is already in use. Please correct.
+NewCollectionPrompt.NewCollection:-- Jauna Kolekcija --
+NewCollectionPrompt.Select_MDS:Pieejamas metadatu kopas:
+NewCollectionPrompt.Title:RadÄ«t jaunu Kolekciju.
+NewCollectionPrompt.Title_Clash:Nosaukums, kuru jÅ«s izvÄlÄjaties jÅ«su kolekcijai, jau tiek izmantots. TurpinÄt?
+NewCollectionPrompt.Title_Error:Nosaukuma lauciÅam jÄbÅ«t aizpildÄ«tam. LÅ«dzu izlabojiet.
+#***** New Folder OrFilePrompt *****
+NewFolderOrFilePrompt.Default_File_Name:fiktÄ«vs
+NewFolderOrFilePrompt.Default_Folder_Name:jauna mape
+NewFolderOrFilePrompt.Destination_Name:SaÅÄmÄjMape
+NewFolderOrFilePrompt.File_Name:Datnes VÄrds
+NewFolderOrFilePrompt.File_Name_Tooltip:Ievadiet nosaukumu jaunai datnei
+NewFolderOrFilePrompt.Folder_Name:Mapes VÄrds
+NewFolderOrFilePrompt.Folder_Name_Tooltip:Ievadiet nosaukumu jaunai mapei
+NewFolderOrFilePrompt.Title_Folder:RadÄ«t jaunu mapi
+NewFolderOrFilePrompt.Title_File:RadÄ«t jaunu fiktÄ«vu dokumentu
+#***********************
+#
+NoMetadataSetsSelected.Message:Ja jÅ«s radÄ«siet tagad kolekciju, tad tai nebÅ«s sÄkotnÄjas metadatu kopas. JÅ«s nevarÄsiet importÄt vai pieÅ¡Ä·irt jebkÄdus metadatus, lÄ«dz nebÅ«s importÄta vai pievienota kopa jÅ«su kolekcijai. Vai jÅ«s vÄlaties turpinÄt?
+NoMetadataSetsSelected.Title:Nav Metadatu Kopa izvÄlÄta
+#**********************
+#
+#******* OldWGET *******
+NoPluginExpectedToProcessFile.Message:IzskatÄs, ka neviens no Greenstone spraudÅiem varÄtu apstrÄdÄt datni "{0}". PÄrbaudiet, ka datnei ir pareizs paplaÅ¡inÄjums. Ja tas ir pareizs, tad jums vajadzÄtu izmantot UnknownPlug spraudni, lai apstrÄdÄtu Å¡o datni.
+NoPluginExpectedToProcessFile.Title:Nav paredzamÄ spraudÅa datnes apstrÄdei
+#**********************
+#
+#******* OldWGET *******
+OldWGET.Message:BrÄ«dinÄjums! JÅ«su instalÄtai Wget versijai ir zinÄma kÄŒÅ«da, kad tiek atspoguÄŒotas datnes, kurÄs ir URL, kas satur kodÄtas zÄ«mes, tÄdas kÄ, atstarpi  un tildi. MÄs rekomendÄjam instalÄt Wget 1.9 un augstÄk.
+OldWGET.Title:Vecs Wget
+#***********************
+#
+#***** OpenCollectionDialog *****
+OpenCollectionDialog.Available_Collections:Pieejamas Kolekcijas
+OpenCollectionDialog.Browse:PÄrlÅ«kot
+OpenCollectionDialog.Browse_Tooltip:IzvÄlieties kolekciju no jÅ«su datÅu telpas
+OpenCollectionDialog.Collection:Greenstone Kolekcija (".col")
+OpenCollectionDialog.Description:Kolekcijas Apraksts
+OpenCollectionDialog.Locked_Collection:Greenstone kolekcija jau tiek lietota
+OpenCollectionDialog.No_Description:LÅ«dzu izvÄlieties greenstone kolekciju (".col" datne), lai redzÄtu aprakstu.
+OpenCollectionDialog.Normal_Collection:Greenstone kolekcija
+OpenCollectionDialog.Open:AtvÄrt
+OpenCollectionDialog.Open_Tooltip:IelÄdÄt izvÄlÄto kolekciju BibliotekÄra InterfeisÄ
+OpenCollectionDialog.Title:AtvÄrt Greenstone Kolekciju
+#**********************
+#
+#***** Options Pane inside CreatePane *****
+OptionsPane.Cancelled:- anulÄts
+OptionsPane.LogHistory:Log vÄsture
+OptionsPane.Successful:- sekmÄ«gi
+OptionsPane.Unknown:- nezinÄms
+OptionsPane.Unsuccessful:- nesekmÄ«gi
+#*******************
+#
+#***** Preferences *****
+Preferences:IestatÄ«jumi
+Preferences.Connection:Savienojums
+Preferences.Connection_Tooltip:UzstÄdiet URL uz greenstone bibliotÄku un nokonfigurÄjiet starpniekservera savienojumu, ja vajadzÄ«gs
+Preferences.Connection.GLIServer_URL:Greenstone gliserver URL:  # Updated 4-Nov-2005
+Preferences.Connection.GLIServer_URL_Tooltip:Greenstone "gliserver" CGI skripta URL  # Updated 4-Nov-2005
+Preferences.Connection.Library_Path:BibliotÄkas CeÄŒÅ¡:
+Preferences.Connection.Library_Path_GS3:Greenstone Web CeÄŒÅ¡:
+Preferences.Connection.Library_Path_Tooltip:Greenstone web-servera URL
+Preferences.Connection.Library_Path_Tooltip_GS3:Greenstone web-servera URL
+Preferences.Connection.ProgramCommand:PriekÅ¡skatÄ«juma Komanda:
+Preferences.Connection.ProgramCommand_Tooltip:Programmas palaiÅ¡anas komanda, lai skatÄ«tu kolekcijas priekÅ¡skatÄ«jumu. Atcerieties, ka jÄizmanto %1, kÄ kolekcijas adreses vietturi, un dubultpÄdiÅas, kur nepiecieÅ¡ams.
+Preferences.Connection.Proxy_Host:Starpniekserveris:
+Preferences.Connection.Proxy_Host_Tooltip:JÅ«su starpniekservera adrese
+Preferences.Connection.Proxy_Port:Starpniekservera pieslÄgvieta:
+Preferences.Connection.Proxy_Port_Tooltip:JÅ«su starpniekservera pieslÄgvietas numurs
+Preferences.Connection.Servlet:ServersÄ«klietotne:
+Preferences.Connection.Servlet_Tooltip:ServersÄ«klietotne izmantojama, lai skatÄ«tu jÅ«su vietni
+Preferences.Connection.Servlet_Tooltip2:ServersÄ«klietotne nav specificÄta Å¡ai vietnei. JÅ«s joprojÄm varat veidot kolekcijas, bet jÅ«s nevarÄsiet tÄs skatÄ«t.
+Preferences.Connection.Site:Vietne:
+Preferences.Connection.Site_Tooltip:Vietne kurÄ jÅ«s gribat strÄdÄt
+Preferences.Connection.Use_Proxy:Izmantot starpniekservera savienojumu?
+Preferences.General:VispÄrÄ«gs
+Preferences.General_Tooltip:Uzdot daÅŸus vispÄrigus iestatÄ«jumus
+Preferences.General.Email:LietotÄja Epasts:
+Preferences.General.Email_Tooltip:Epasta adrese automÄtiski izmantojama jebkurai kolekcijai radÄ«tai ar GBI
+Preferences.General.Font:Fonts:
+Preferences.General.Font_Tooltip:Fonts izmantojams GBI interfeisÄ.
+Preferences.General.Interface_Language:Interfeisa Valoda:
+Preferences.General.Interface_Language_Tooltip:IzvÄlieties valodu, kurÄ interfeiss un tÄ kontroles tiktu parÄdÄ«ti.
+Preferences.General.Restart_Required:GBI (Greenstone BibliotekÄra Interfeisam) tagad jÄrestartÄ, lai pabeigtu savu interfeisa izmaiÅu aktualizÄciju.
+Preferences.General.Show_File_Size:RÄdÄ«t datÅu izmÄrus
+Preferences.General.Show_File_Size_Tooltip:RÄdÄ«t datÅu izmÄrus pie katras ieejas DarbatelpÄ un Kolekcijas datÅu kokÄ.
+Preferences.General.View_Extracted_Metadata:SkatÄ«t Izvilktus Metadatus
+Preferences.General.View_Extracted_Metadata_Tooltip:ParÄdÄ«t greenstone spraudÅu izvilktos metadatus metadatu sarakstÄ BagÄtinÄÅ¡anas panelÄ«.
+Preferences.Mode:ReÅŸÄ«ms
+Preferences.Mode_Tooltip:NokliÅ¡Ä·iniet uz ieeju, lai izvÄletos piemÄrotu operÄÅ¡anas lÄ«meni
+Preferences.Mode.Assistant:BibliotekÄra Asistents
+Preferences.Mode.Assistant_Description:Izmantojiet Å¡o iestatÄ«jumu, lai iegÅ«tu piekÄŒuvi Greenstone BibliotekÄra Interfeisa pamata iespÄjÄm: pievienot dokumentus un metadatus kolekcijÄm, jauno kolekciju radÄ«Å¡ana, kuru struktÅ«ra atspoguÄŒo jau esoÅ¡as kolekcijas, un kolekciju veidoÅ¡ana.
+Preferences.Mode.Librarian:BibliotekÄrs
+Preferences.Mode.Librarian_Description:Å is iestatÄ«jums ÄŒauj normÄli izmantot Greenstone BibliotekÄra Interfeisu: radÄ«t un noformÄt jaunas kolekcijas, pievienot dokumentus un metadatus kolekcijÄm, jaunu kolekciju noformÄÅ¡anu (dizainu), un kolekciju veidoÅ¡anu (bÅ«vÄÅ¡anu).
+Preferences.Mode.Systems:BibliotÄku SistÄmu SpeciÄlists
+Preferences.Mode.Systems_Description:Å is iestatÄ«jums atÄŒauj pilnu Greenstone BibliotekÄra Interfeisa izmantoÅ¡anu. Lai izmantotu visu iespÄju priekÅ¡rocÄ«bas, jums bÅ«s nepiecieÅ¡ams mÄcÄt formulÄt regulÄrÄs izteiksmes.
+Preferences.Mode.Expert:Eksperts
+Preferences.Mode.Expert_Description:Å is iestatÄ«jums ÄŒauj ekspertam izmantot Greenstone BibliotekÄra Interfeisu. Tas tiek rekomendÄts lietotÄjiem, kuri ir pieredzÄjuÅ¡i darbam ar Greenstone, un ir spÄjÄ«gi veikt kÄŒÅ«du laboÅ¡anas uzdevumus, kas prasa interpretÄt atkÄŒÅ«doÅ¡anas izvadi no PERL skriptiem. Visas Greenstone BibliotekÄra Interfeisa iespÄjas ir atÄŒautas.
+Preferences.Warnings:BrÄ«dinÄjumi
+Preferences.Warnings_Tooltip:AtÄŒaut vai aizliegt daÅŸÄdus brÄ«dinÄjumu dialogus
+Preferences.Workflow:DarbplÅ«sma
+Preferences.Workflow_Tooltip:IestÄdÄ«t interfeisa darbplÅ«smu: noteikt, kurus skatus (tabulÄtorus) atÄŒaut
+Preferences.Workflow.Create:RadÄ«t - Veidot jÅ«su kolekciju izmantojot Greenstone
+Preferences.Workflow.Design:Dezains - IzmainÄ«t kolekcijas Ärieni
+Preferences.Workflow.Download:LejupielÄde - LejupielÄdÄt web-bÄzÄtos resursus
+Preferences.Workflow.Enrich:BagÄtinÄt - AprakstÄ«t ar metadatiem
+Preferences.Workflow.Gather:UzkrÄt - AtlasÄ«t datnes kolekcijai
+Preferences.Workflow.Predefined.Label:IepriekÅ¡noteiktas DarbplÅ«smas
+Preferences.Workflow.Title:IzvÄlieties rÅ«tiÅu, lai atÄŒautu skatu
+#**********************
+#
+#**** PreviewCommandDialog *******
+PreviewCommandDialog.Instructions:Ievadiet komandu, programmas palaiÅ¡anai, lai skatÄ«tu kolekcijas priekÅ¡skatÄ«jumu. Atcerieties izmantot %1, kÄ kolekcijas adreses vietturi, un dubultpÄdiÅas kur nepiecieÅ¡ams.
+PreviewCommandDialog.Title:PriekÅ¡skatÄ«juma Komanda
+#**********************
+#
+#***** Remote Greenstone Server *****
+RemoteGreenstoneServer.Authentication_Message:LÅ«dzu ievadiet jÅ«su Greenstone lietotÄjvÄrdu un paroli:  # Updated 4-Nov-2005
+RemoteGreenstoneServer.Error:AtgadÄ«jÄs kÄŒÅ«da uz attÄlÄ Greenstone servera veicot Å¡o operÄciju:\n{0-Error message}  # Updated 4-Nov-2005
+RemoteGreenstoneServer.Error_Title:AttÄlÄ Greenstone Servera KÄŒÅ«da  # Updated 4-Nov-2005
+RemoteGreenstoneServer.Progress:AttÄlÄ Greenstone Servera Progress:  # Updated 4-Nov-2005
+RemoteGreenstoneServer.Steal_Lock_Message:Kolekciju patreiz lieto lietotÄjs '{0-User name}'.\nVai jÅ«s vÄlaties pÄrtvert
+#**********************
+#
+#***** Rename Prompt *****
+RenamePrompt.Name:Nosaukums:  # Updated 22-Apr-2006
+RenamePrompt.Title:PÄrdÄvÄt datni/mapi  # Updated 22-Apr-2006
+#**********************
+#
+#***** Replace Prompt *****
+ReplacePrompt.Title:Aizvieto datni ar ...  # Updated 22-Apr-2006
+#**********************
+#
+#***** Save Collection Box *****
+SaveCollectionBox.File_Name:Datnes VÄrds:
+SaveCollectionBox.Files_Of_Type:DatÅu Tips:
+SaveCollectionBox.Look_In:IelÅ«koties:
+#**********************
+#
+#***** Save Progress Box *******
+SaveProgressDialog.Title:Kolekcijas SaglabÄÅ¡ana
+#*******************************
+#
+Server.QuitManual:BibliotekÄra Interfeiss nevarÄja aizvÄrt lokÄlo\n bibliotÄkas serveri automÄtiski. LÅ«dzu izejiet no servera\nmanuÄli, noklikÅ¡Ä·inot, uz tÄ augÅ¡ÄjÄ stÅ«rÄ« labÄs\npuses krusta ikonas.
+Server.QuitTimeOut:Greenstone lokÄlÄ bibliotÄka nav atbildÄjusi uz\nautomÄtisko aizvÄrt komandu 60 sekundes. Vai jÅ«s\nvÄlaties gaidÄ«t vÄl minÅ«ti?
+#
+#***** Sources *****
+Source.General:VispÄrÄ«gs
+#*******************
+#
+#***** TitleClash *****
+TitleClashes.Message:Nosaukums, kuru jÅ«s esat izvÄlÄjuÅ¡ies jÅ«su kolekcijai, tiek jau lietots. TurpinÄt?
+TitleClashes.Title:IevadÄ«tÄ Nosaukuma nesaskaÅas
+#**********************
+#
+#***** Trees *****
+Tree.DownloadedFiles:LejupielÄdÄtÄs Datnes
+Tree.Files:datnes
+Tree.Home:SÄkummape ({0})
+Tree.Root:LokÄlÄ DatÅutelpa
+Tree.World:Dokumenti Greenstone KolekcijÄs
+#***********************
+#
+#***** Warning Dialog *****
+WarningDialog.Dont_Show_Again:NerÄdÄ«t Å¡o brÄ«dinÄjumu vÄlreiz
+WarningDialog.Dont_Show_Again_Message:NerÄdÄ«t Å¡o paziÅojumu vÄlreiz
+WarningDialog.Invalid_Value:VÄrtÄ«ba, kuru jÅ«s esat ievadÄ«juÅ¡i vÄrtÄ«bas lauciÅÄ,\nnav pareiza specificÄtam rekvizÄ«tam.
+WarningDialog.Value:Ievadiet vÄrtÄ«bu:
+#
+#****** WGet *****
+WGet.Prompt:Wget AtspoguÄŒoÅ¡anas Klients
+#
+#****** Workflows *****
+Workflow.AllPanels:Visi paneÄŒi
+Workflow.LocalSourceCollectionBuilding:LokÄla avota kolekcijas veidoÅ¡ana
+Workflow.DocumentEnriching:Dokumenta bagÄtinÄÅ¡ana
+
+GEMS.Already_Loaded_Set_Error:JÅ«su izvÄletÄ metadatu kopa patreiz ir atvÄrta.
+GEMS.Element_Already_Exists:Elements ar Å¡o vÄrdu jau eksistÄ.
+GEMS.Set_Already_Exists:Kopa ar doto vÄrdutelpu jau eksistÄ.
+GEMS.Cannot_Delete_Core_Sets_Error:JÅ«s nevarat izdzÄst GBI kodola metadatu kopu.
+
+GEMS.Preferences.Selected_Languages_Tooltip:IzvÄlieties parÄdÄ«Å¡anas valodu:
+
+GEMS.Add_Attribute:Pievienot atribÅ«tu
+GEMS.Add_Attribute_Tooltip:Pievienot jaunu atribÅ«tu izvÄlÄtam vienumam
+GEMS.Add_Element:Pievienot elementu
+GEMS.Add_Element_Tooltip:Pievienot jaunu elementu izvÄlÄtai kopai
+GEMS.Add_Subelement:Pieviento apakÅ¡elementu
+GEMS.Add_Subelement_Tooltip:Pievienot jaunu apakÅ¡elementu izvÄlÄtam elementam
+GEMS.Add_Set:Pieviento Kopu
+GEMS.Attribute:AtribÅ«ts
+GEMS.Attribute_Already_Exists:Å is atribÅ«ts jau eksistÄ.
+GEMS.Attribute_Name_Tooltip:JaunÄ atribÅ«ta nosaukums
+GEMS.Attribute_Language_Tooltip:JaunÄ atribÅ«ta valoda
+GEMS.Attribute_Value_Tooltip:JaunÄ atribÅ«ta vÄrtÄ«ba
+GEMS.Attributes:AtribÅ«ti
+GEMS.Cannot_Undo:(Å¡Ä« darbÄ«ba nevar tikt atsaukta)
+GEMS.Cannot_Add_Elements_To_Greenstone_MDS:JÅ«s nevarat manuÄli pievienot elementus Greenstone Metadatiem. Ja\nnepiecieÅ¡ams radÄ«t jaunu kopu, tad ta vietÄ pievienojiet jÅ«su jauno elementu tam.
+GEMS.Confirm_Exit_Save:Vai jÅ«s nevÄlaties saglabÄt pirms izieÅ¡anas?
+GEMS.Confirm_Exit_Save_Title:SaglabÄt Pirms IzieÅ¡anas?
+GEMS.Confirm_Removal:Vai jÅ«s esat pÄrliecinÄti, ka gribat izdzÄst Å¡o {0}?
+GEMS.Confirm_Removal_Title:ApstiprinÄt IzdzÄÅ¡anu
+GEMS.Edit_Attribute:RediÄ£Ät AttribÅ«tu
+GEMS.Edit_Value:RediÄ£Ät VÄrtÄ«bu
+GEMS.Edit_Value_Tooltip:IzmainÄ«t izvÄlÄto vÄrtÄ«bu
+GEMS.Element:Elements
+GEMS.Element_Name_Tooltip:JaunÄ elementa nosaukums
+GEMS.Element_Details:Metadatu Elementa DetaÄŒas
+GEMS.Language:Valoda
+GEMS.Language_Code:Valoda
+GEMS.Name:Nosaukums
+GEMS.Namespace:VÄrdutelpa
+GEMS.New_Name:Jauns Nosaukums
+GEMS.No_Description:Apraksts nav atrasts.
+GEMS.No_Name:Nosaukums nav atrasts.
+GEMS.Open_Set:AtvÄrt Kopu
+GEMS.Remove_Attribute:NoÅemt attribÅ«tu
+GEMS.Remove_Attribute_Tooltip:IzdzÄst izvÄlÄto atribÅ«tu
+GEMS.Remove_Element:NoÅemt elementu
+GEMS.Remove_Element_Tooltip:IzdzÄst izvÄlÄto elementu no kopas
+GEMS.Remove_Set:NoÅemt kopu
+GEMS.Remove_Set_Tooltip:IzdzÄst izvÄlÄto kopu
+GEMS.Rename_Element:PÄrdÄvÄt elementu
+GEMS.Rename_Element_Tooltip:Elementa jauns nosaukums
+GEMS.Rename_Name_Tooltip:Metadatu kopas jaunais nosaukums
+GEMS.Rename_Namespace_Tooltip:Metadatu kopas unikÄlÄ vÄrdutelpa
+GEMS.Rename_Set:PÄrdÄvÄt kopu
+GEMS.Rename_Set_Tooltip:PÄrdÄvÄt metadatu kopu
+GEMS.Set:Kopa
+GEMS.Set_Details:Metadatu Kopas DetaÄŒas
+GEMS.Set_Name_Tooltip:JaunÄs metadatu kopas vÄrds (nosaukums)
+GEMS.Set_Namespace_Tooltip:UnikÄlÄ vÄrdutelpa jaunai metadatu kopai
+GEMS.Subelement_Name_Tooltip:JaunÄ apakÅ¡elementa nosaukums
+GEMS.Subelement_Already_Exists:ApakÅ¡elements ar Å¡o nosaukumu jau eksistÄ.
+GEMS.Target:Elements
+GEMS.Title:Greenstone Metadatu Kopu Redaktors
+GEMS.Value:VÄrtÄ«ba
+GEMS.Values:VÄrtÄ«bas
+GEMS.inheritMetadataSet:PÄrmantot no Metadatu kopas:
+GEMS.Add_Set.No_Inherit:NepÄrmantot
Index: /tags/greenstone-3_02-distribution/gli/classes/dictionary_zh.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gli/classes/dictionary_zh.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/classes/dictionary_zh.properties	(revision 13928)
@@ -0,0 +1,1366 @@
+#*******************
+#
+#***** AboutDialog *****
+AboutDialog.Acknowledgement:æ¥åçšåºïŒå
+æç±»çæææ
+AboutDialog.Date:(12æ 2006)
+AboutDialog.Item0:'Xerces Java 1' é¿åžå¥èœ¯ä»¶ç»ç» (http://www.apache.org/)
+AboutDialog.Item2:'WGet' å
+èŽ¹èœ¯ä»¶ç»ç» (http://www.gnu.org/software/wget/wget.html)
+AboutDialog.Item3:'qflib' èŽšéç¬¬äžèœ¯ä»¶ç»ç»(http://www.qfs.de/en/qflib/index.html)
+AboutDialog.Item4:'ExtensionFileFilter.class' by Bruno Dumon and contributors (http://pollo.sourceforge.net/)
+AboutDialog.Item5:'åšèœ¯ä»¶éæ©åšäž­ææ ·çŠæ­¢æä»¶éåœå' - vladi21 (http://www.experts-exchange.com/)
+AboutDialog.Item6:'èªåšæ»åš' - Java Swing by Robert Eckstein, Marc Loy & Dave Wood (http://www.oreilly.com/catalog/jswing/chapter/dnd.beta.pdf)
+AboutDialog.Item7:'æ·»å æ»åšåŸè±¡å° JTrees' - By Andrew J. Armstrong (http://www.javaworld.com/javaworld/javatips/jw-javatip114.html)
+AboutDialog.Item8:'åæ­¢java.prefs éè¯¯ïŒåœäœ æ²¡æè¶
+çº§çšæ·æéæ¶' - Thanks to Walter Schatz
+AboutDialog.Java_Req:Javaæ¯sunå
+¬åžçåæ . JREæ¯éæ°ååžçè®žå¯è¯æ¯è¯­, found at http://java.sun.com/j2se/1.4.1/j2re-1_4_1_02-license.html
+AboutDialog.Java_Req_One:è¿é¡¹äº§åå
+æ¬ç±RSAè®žå¯çä»£ç .
+AboutDialog.Java_Req_Two:äžéšåæ¥åšIBMçè®žå¯å¯ä»¥åš http\://oss.software.ibm.com/icu4j/æŸå°
+AboutDialog.Thanks:åæ ·æè°¢é£äºååžæçšçjavaä¿¡æ¯çäºº
+AboutDialog.Title:å
+³äº...
+AboutDialog.Title_One:ç»¿å®ç³ç®¡çåçé¢
+AboutDialog.Title_Two:ç»¿å®ç³æ°å­åŸä¹ŠéŠïŒ Waikatoå€§å­Š
+AboutDialog.Copyright:Copyright (C) 2006 æ°è¥¿å
+°æ°å­åŸä¹ŠéŠé¡¹ç®
+AboutDialog.Copyright_Two:åšGPLäžåè¡.è¯Šç»ä¿¡æ¯è¯·æ¥çlicense.txtæä»¶
+#***********************
+#
+#***** Audit Table *****
+AuditTable.File:æä»¶å
+#***********************
+#
+#***** Auto Filter *****
+Autofilter.AND:äž
+Autofilter.Ascending:åäž
+Autofilter.Case_Sensitive:åºåå€§å°å
+Autofilter.Custom_Filter:é«çº§
+Autofilter.Descending:åäž
+Autofilter.Filter_By_Value:ç®å
+Autofilter.Name:åå
+Autofilter.None:æ 
+Autofilter.Operator:æ¡ä»¶
+Autofilter.OR:æ
+Autofilter.Order:æåº
+Autofilter.Order_Tooltip:ææ­€é¡ºåºæåºå¹é
+å
+Autofilter.Remove:ç§»é€è¿æ»€åš
+Autofilter.Remove_Tooltip:ä»è¡šåäž­ç§»é€è¿æ»€åš
+Autofilter.Set:è®Ÿçœ®è¿æ»€åš
+Autofilter.Set_Tooltip:æ·»å æ­€è¿æ»€åšå°è¡šå
+Autofilter.Table_Header_Tooltip:Filter by {0}
+Autofilter.Title:èªåšè¿æ»€åæ°æ®
+Autofilter.eqeq:ç­äº
+Autofilter.!eq:äžç­
+Autofilter.<:is å°äº
+Autofilter.<eq:å°äºç­äº
+Autofilter.>:å€§äº
+Autofilter.>eq:å€§äºç­äº
+Autofilter.^:èµ·å§äº
+Autofilter.!^:éèµ·å§äº
+Autofilter.$:ç»æäº
+Autofilter.!$:éç»æäº
+Autofilter.?:å
+å«
+Autofilter.!?:äžå
+å«
+#
+#     ********************************************************
+#     *************** Collection Design Module ***************
+#     ********************************************************
+#     * The dictionary  phrases  used in the creation of the *
+#     * Colection  Design  Module. Note that we  still  have *
+#     * access  to the format  arguments (argument  32+) for *
+#     * html formatting.                                     *
+#     ********************************************************
+CDM.ArgumentConfiguration.Add:æ·»å 
+CDM.ArgumentConfiguration.Bad_Integer:<html>æ­€åæ° '{0}' éèŠäžäžªæŽåŒ,<br>äœæ¯æ æ³ä» {1}äž­è§£æåºæŽåŒ.</html>
+CDM.ArgumentConfiguration.Custom_Header:èªå®ä¹
+CDM.ArgumentConfiguration.Custom:èªå®ä¹åæ°:
+CDM.ArgumentConfiguration.Error_Title:éè¯¯åæ°
+CDM.ArgumentConfiguration.Header:<HTML><STRONG><FONT FACE={FONT} COLOR=Black SIZE=5><CENTER>è¯·äžº {0}é
+çœ®åæ°.</CENTER></FONT></STRONG></HTML>
+CDM.ArgumentConfiguration.No_Value:åæ° '{0}' éèŠäžäžªåŒ, äœæ¯æ­€åŒæ²¡æç¡®å®.
+CDM.ArgumentConfiguration.RemoveïŒç§»é€
+CDM.ArgumentConfiguration.Required_Argument:åæ°'{0}' å¿
+é¡»èµåŒ.
+CDM.ArgumentConfiguration.Title:é
+çœ®åæ°
+CDM.ClassifierManager.Add:æ·»å åç±»åš
+CDM.ClassifierManager.Add_Tooltip:å¯¹æ­€éååºçšç¹å®åç±»åš
+CDM.ClassifierManager.Assigned:ç®åæå®çåç±»åš
+CDM.ClassifierManager.Classifier:éæ©æ·»å çåç±»åš
+CDM.ClassifierManager.Classifier_Tooltip:éåäž­å¯çšçåç±»åš
+CDM.ClassifierManager.Classifier_Exists:æ­€åç±»åšå·²ç»è¢«æå®
+CDM.ClassifierManager.Classifier_Str:åç±»åš
+CDM.ClassifierManager.Classifier_XML_Parse_Failed:äžèœç¡®å®æ­€åç±»åšçåæ° {0}\n. è¯·ç¡®å®æé®é¢çåç±»åš\nè¯·éè¿è¿è¡ classinfo.pl èæ¬æ¥æäŸxmlæ å¿\n äžGreenStoneåŒåæå2.1éšåäž­çpluginfo.plèæ¬çžäŒŒã\n
+CDM.ClassifierManager.Configure:é
+çœ®åç±»åš
+CDM.ClassifierManager.Configure_Tooltip:äžºéæ©çåç±»åšæŽæ¹éé¡¹
+CDM.ClassifierManager.Controls:çŒèŸæ§å¶
+CDM.ClassifierManager.Instructions:çšæ­€è§åŸåšæ­€éåäž­æ·»å ïŒé
+çœ®æç§»é€åç±»åšã è¥èŠæ·»å äžäžªåç±»åšïŒä»äžææ¡äž­éæ©ïŒç¶åç¹å»æ·»å åç±»åšã\nè¥èŠç§»é€åç±»åšïŒä»åè¡šäž­éäž­ïŒç¶åç¹å»ç§»é€åç±»åšã\n è¥èŠé
+çœ®åç±»åšïŒä»åè¡šäž­éäž­ïŒç¶åç¹å»é
+çœ®åç±»åšã\n åœäœ é
+çœ®åç±»åšçæ¶åïŒå®çåæ°è¡šäŒæŸç€ºåºæ¥ãäœ¿åæ°ææå¹¶äžèŸå
+¥æè
+éæ©å¿
+é¡»çåŒã
+CDM.ClassifierManager.Remove:ç§»é€åç±»åš
+CDM.ClassifierManager.Remove_Tooltip:ä»åè¡šäž­ç§»é€éäž­çåç±»åšã
+CDM.ClassifierManager.Title:<HTML><STRONG><FONT FACE={FONT} COLOR=Black SIZE=5><CENTER>åç±»åšéæ©&é
+çœ®</CENTER></FONT></STRONG></HTML>
+CDM.ClassifierManager.Parsing.Message:è®Ÿè®¡å·¥å
+·æ­£åšå èœœåç±»åšä¿¡æ¯ã
+CDM.ClassifierManager.Parsing.Title:å èœœåç±»åš
+CDM.FormatManager.Add:æ·»å æ ŒåŒã
+CDM.FormatManager.Add_Tooltip:å¯¹éååºçšç¹å®çæ ŒåŒåœä»€ã
+CDM.FormatManager.Assigned_Formats:ç®åæå®çæ ŒåŒåœä»€
+CDM.FormatManager.Editor:HTML æ ŒåŒäž²
+CDM.FormatManager.Editor_Tooltip:åšæ­€èŸå
+¥æ ŒåŒåœä»€
+CDM.FormatManager.Editing_Controls:çŒèŸæ§ä»¶
+CDM.FormatManager.Enabled:æ¿æŽ»
+CDM.FormatManager.Feature:éæ©ç¹åŸ
+CDM.FormatManager.Feature_Tooltip:æ ŒåŒåç¹åŸ
+CDM.FormatManager.Insert:æå
+¥
+CDM.FormatManager.Insert_Tooltip: æå
+¥äžºæ ŒåŒåœä»€éæ©çåéã
+CDM.FormatManager.Instructions:äœ æçå°ççœé¡µå¹¶äžæ¯äºå
+å­å¥œçïŒèæ¯åšéèŠçæ¶åçæçã. æ ŒåŒåœä»€çšæ¥æ¹åè¿äºçæççœé¡µçå€è§. äžäºæ¯çšæ¥æ§å¶æä»¶æŸç€ºçåŒå
+³ïŒåŠå€çäžäºæ¯èŸå€æéèŠhtmlä»£ç äœäžºåæ°ïŒ\nèŠæ·»å æ ŒåŒåœä»€, ä»ç¹åŸåè¡šäž­éäž­å®. åŠæç/åé¢æ¿æŸç€ºåºæ¥, éè¿ç¹å»åéçæé®æ¥éäž­ç¶æ.åŠæé¢æ¿äž­å
+å«ååœ±åçç¹åŸå¹¶äžçŒèŸæ ŒåŒäž²æ§ä»¶åºç°çè¯äœ éèŠèŸå
+¥htmlææ¬ãäœ å¯ä»¥éè¿ä»åè¡šäž­éåæ¥å
+å«è¿é¢å
+è®Ÿçœ®çåé\näžæŠäœ å¯¹æŽæ¹æ»¡æ, ç¹å»"æ·»å æ ŒåŒ"å°å
+¶æ·»å å°é
+çœ®æä»¶äž­ã\nå¯ä»¥éè¿åšåè¡šäž­éäž­ç¶åç¹å»"ç§»é€æ ŒåŒ"æé®æ¥å é€æ ŒåŒã
+CDM.FormatManager.Part:ååœ±åçç»ä»¶
+CDM.FormatManager.Part_Tooltip:æ ŒåŒåéäž­çç¹åŸ
+CDM.FormatManager.Remove:ç§»é€æ ŒåŒ
+CDM.FormatManager.Remove_Tooltip:ç§»é€åè¡šäž­éäž­çæ ŒåŒåœä»€
+CDM.FormatManager.Replace:æ¿æ¢æ ŒåŒ
+CDM.FormatManager.Replace_Tooltip:æŽæ°éäž­çæ ŒåŒåœä»€
+CDM.FormatManager.Title:<HTML><STRONG><FONT FACE={FONT} COLOR=Black SIZE=5><CENTER>æ ŒåŒåœä»€/CENTER></FONT></STRONG></HTML>
+CDM.FormatManager.Variable:åé
+CDM.FormatManager.Variable_Tooltip:èœå€åºçšæ ŒåŒåœä»€çåé
+CDM.General.Access:æ­€éååºåœå¯ä»¥è¢«å
+¬å
+±è®¿é®
+CDM.General.Browser_Title:éæ©äžåŒ åŸç
+CDM.General.Collection_Extra:éåæè¿°
+CDM.General.Collection_Extra_Tooltip: å¯¹äºéåç®çåå
+å®¹çæè¿°ã
+CDM.General.Collection_Name:éå
+CDM.General.Collection_Name_Tooltip:éååå­
+CDM.General.Copy_Image:äžºäºèœå¯¹éåäœ¿çšè¿äºåŸç\næä»¶å¿
+é¡»è¢«æ·èŽè¿åŸçæä»¶å€¹. ç»§ç»­åïŒ
+CDM.General.Email.Creator:åå»ºè
+çemail
+CDM.General.Email.Creator_Tooltip:éååå»ºè
+çemailå°å
+CDM.General.Email.Maintainer:ç»Žæ€è
+çemail
+CDM.General.Email.Maintainer_Tooltip:éåç»Žæ€è
+çemailå°å
+CDM.General.Icon_Collection:æå"about page"åŸæ çURL:
+CDM.General.Icon_Collection_Tooltip:æŸç€º"about"é¡µé¢çåŸè±¡çURL
+CDM.General.Icon_Collection_Small:æå"äž»é¡µ"åŸæ çURL:
+CDM.General.Icon_Collection_Small_Tooltip:æŸç€ºäž»é¡µé¢çåŸè±¡çURL
+CDM.General.Image_Copy_Failed:äžäžªéè¯¯å¯ŒèŽäœ æéäž­çåŸè±¡äžèœå€è¢«å€å¶\nè¯·æåšå€å¶äœ çåŸè±¡å°åŸè±¡æä»¶å€¹ã
+CDM.General.Image_Filter:åŸå(gifs, jpgs and pngs)
+CDM.General.Instructions:åŸä¹Šç®¡çåçè®Ÿè®¡çé¢å
+è®žäœ èœè®Ÿè®¡æŸç€ºçåäžªæ¹é¢ãè®Ÿè®¡è¢«åæå äžªéšåïŒè¿äžéšåå
+æ¬æ®ééé¡¹äžè®Ÿè®¡ãç¹å»å·ŠèŸ¹åè¡šäž­çåå­æ¥éæ©äžåçéšåã
+CDM.General.Title:<HTML><STRONG><FONT FACE={FONT} COLOR=Black SIZE=5><CENTER>æ®ééé¡¹</CENTER></FONT></STRONG></HTML>
+CDM.GUI.Classifiers:æµè§åç±»åš
+CDM.GUI.Design_Topics:è®Ÿè®¡éšå
+CDM.GUI.Formats:æ ŒåŒç¹åŸ
+CDM.GUI.General:æ®é
+CDM.GUI.Indexes:æçŽ¢çŽ¢åŒ
+CDM.GUI.MetadataSets:åæ°æ®é
+CDM.GUI.Plugins:æä»¶æä»¶
+CDM.GUI.Root:CDM_ROOT
+CDM.GUI.SearchTypes:æçŽ¢ç±»å
+CDM.GUI.Subcollections:ååºçŽ¢åŒ
+CDM.GUI.SuperCollection:è·šéåæçŽ¢
+CDM.GUI.Translation:ç¿»è¯ææ¬
+CDM.IndexManager.Add_Index:æ·»å çŽ¢åŒ
+CDM.IndexManager.Add_Index_Tooltip:äžºéååå»ºç¹å®çŽ¢åŒ
+CDM.IndexManager.Default_Index_Indicator:[é»è®€çŽ¢åŒ]
+CDM.IndexManager.Document:æä»¶
+CDM.IndexManager.Index_Exists:æ­€çŽ¢åŒå·²ç»è¢«æå®ç»è¿äžªéå.
+CDM.IndexManager.Index_Name:çŽ¢åŒåç§°:
+CDM.IndexManager.Index_Name_Tooltip:å¯¹æ°çŽ¢åŒçå¯äžçåå­
+CDM.IndexManager.Indexes:æå®ççŽ¢åŒ
+CDM.IndexManager.Instructions:åšè¿ééæ©éåææçå¯æçŽ¢ççŽ¢åŒ\nèŠæ·»å çŽ¢åŒ, éæ©èŠè¢«çŽ¢åŒçèµæ, éæ©çŽ¢åŒçº§å«, ç¹å»"æ·»å çŽ¢åŒ".\nç§»é€çŽ¢åŒ, ä»æå®ççŽ¢åŒåè¡šäž­éäž­å®ç¶åç¹å»ç§»é€çŽ¢åŒ.\nè®Ÿçœ®é»è®€çŽ¢åŒ, ä»æå®ççŽ¢åŒåè¡šäž­éäž­å® ç¶åç¹å»"è®Ÿçœ®æé»è®€"
+CDM.IndexManager.Level:åšæ­€çº§å«:
+CDM.IndexManager.Level_Exists:æ­€çº§å«å·²ç»è¢«æå®ç»æ­€éå
+CDM.IndexManager.Level_Tooltip:å»ºç«çŽ¢åŒçæä»¶çº§å«
+CDM.IndexManager.MGPP.Add_All_Metadata:æ·»å ææ
+CDM.IndexManager.MGPP.Add_All_Metadata_Tooltip:äžºæ¯äžäžªå¯çšçæºå»ºç«æä»¶çŽ¢åŒïŒäœ¿çšæºäœäžºçŽ¢åŒåå­ã
+CDM.IndexManager.MGPP.Add_Level:æ·»å çº§å«
+CDM.IndexManager.MGPP.Add_Level_Tooltip:äžºç¹å®çº§å«å»ºç«çŽ¢åŒ
+CDM.IndexManager.MGPP.Current_Indexes:ç®åæå®ççº§å«
+CDM.IndexManager.MGPP.Current_Levels:ç®åæå®ççº§å«
+CDM.IndexManager.MGPP.Index:çŽ¢åŒæº:
+CDM.IndexManager.MGPP.Index_Tooltip:å»ºç«çŽ¢åŒçæºæ°æ®å
+çŽ 
+CDM.IndexManager.MGPP.Indexes:ç®¡ççŽ¢åŒ
+CDM.IndexManager.MGPP.Instructions:åšæ­€éæ©éåææçå¯æçŽ¢ççŽ¢åŒ\næ·»å æ°ççŽ¢åŒ, äžºçŽ¢åŒèŸå
+¥äžäžªå¯äžçåå­, éæ©å°è¢«çŽ¢åŒçå
+æ°æ®, ç¹å»æ·»å çŽ¢åŒ.\nåŠæäœ æ³äžºææçæåæ·»å çŽ¢åŒ, ç¹å»"æ·»å ææ" (çŽ¢åŒçåå­é»è®€æ¯æºçåå­). æ³šæè¿æ¯äžæ·»å 'AllFields' æºçç»åŸ®çäžå,çŽ¢åŒçé¡ºåºéåžžéèŠ.\nåŠæäœ åžæçŒèŸæäžçŽ¢åŒ, ä»çŽ¢åŒåè¡šäž­éäž­å®è¿è¡çŒèŸ, ç¶åéæ©æ¿æ¢çŽ¢åŒæ¥æ¿æ¢æ§ççŽ¢åŒ.\nç§»é€çŽ¢åŒ, ä»æå®åè¡šäž­éäž­ ç¶åç¹å»"ç§»é€çŽ¢åŒ".
+CDM.IndexManager.MGPP.Level:çº§å«æº:
+CDM.IndexManager.MGPP.Level_Name:çº§å«åç§°:
+CDM.IndexManager.MGPP.Level_Name_Tooltip:äžºæ°ççŽ¢åŒæå®å¯äžçåå­
+CDM.IndexManager.MGPP.Levels:ç®¡ççº§å«
+CDM.IndexManager.MGPP.Remove_Level:ç§»é€è§£å«
+CDM.IndexManager.MGPP.Remove_Level_Tooltip:ç§»é€éäž­ççº§å«çŽ¢åŒ
+CDM.IndexManager.MGPP.Replace_Index:æ¿æ¢çŽ¢åŒ
+CDM.IndexManager.MGPP.Replace_Index_Tooltip:æŽæ°éäž­ççŽ¢åŒ
+CDM.IndexManager.MGPP.Title:<HTML><STRONG><FONT FACE={FONT} COLOR=Black SIZE=5><CENTER>éäž­çŽ¢åŒåçº§å«</CENTER></FONT></STRONG></HTML>
+CDM.IndexManager.Paragraph:æ®µèœ
+CDM.IndexManager.Remove_Index:ç§»é€çŽ¢åŒ
+CDM.IndexManager.Remove_Index_TooltipïŒç§»é€éäž­ççŽ¢åŒ
+CDM.IndexManager.Section:éšå
+CDM.IndexManager.Set_Default:è®Ÿçœ®é»è®€ççŽ¢åŒ
+CDM.IndexManager.Set_Default_Tooltip:äœ¿éäž­ççŽ¢åŒæäžºé»è®€é»è®€çŽ¢åŒ
+CDM.IndexManager.Source:å»ºç«çŽ¢åŒåš:
+CDM.IndexManager.Source_Tooltip:å»ºç«çŽ¢åŒçå
+æ°æ®å
+çŽ 
+CDM.IndexManager.Title:<HTML><STRONG><FONT FACE={FONT} COLOR=Black SIZE=5><CENTER>çŽ¢åŒçéæ©</CENTER></FONT></STRONG></HTML>
+CDM.LanguageManager.Add:æ·»å è¯­èš
+CDM.LanguageManager.Add_Tooltip:äžºåè¡šæ·»å ç¹å®çè¯­èš
+CDM.LanguageManager.Assigned_Languages:æå®è¯­èš
+CDM.LanguageManager.Default_Language:é»è®€è¯­èš
+CDM.LanguageManager.Remove:ç§»é€è¯­èš
+CDM.LanguageManager.Remove_Tooltip:ç§»é€åè¡šäž­éäž­çè¯­èš
+CDM.LanguageManager.Selector:æ·»å è¯­èšå°: 
+CDM.LanguageManager.Selector_Tooltip:å»ºç«ååºçŽ¢åŒçè¯­èš
+CDM.LanguageManager.Set_Default:è®Ÿçœ®æé»è®€
+CDM.LanguageManager.Set_Default_Tooltip:äœ¿éäž­çè¯­èšæäžºé»è®€
+CDM.MetadataSetManager.Add:æ·»å å
+æ°æ®é
+CDM.MetadataSetManager.Add_Tooltip:äžºéåæ·»å æ°çå
+æ°æ®é
+CDM.MetadataSetManager.Edit:çŒèŸå
+æ°æ®é
+CDM.MetadataSetManager.Edit_Message:å
+æ°æ®éå¯ä»¥éè¿GEMSæ¥è¿è¡çŒèŸ(Greenstone å¯¹å
+æ°æ®ççŒèŸåš).\néè¿è¿è¡å®è£
+ç®åœgliæä»¶å€¹äžçgems.batæ¥å¯åšçŒèŸåš (Windows) æè
+ gems.sh (Linux) 
+CDM.MetadataSetManager.Edit_Message_Title:çŒèŸå
+æ°æ®é
+CDM.MetadataSetManager.Edit_Tooltip:çŒèŸéäž­çå
+æ°æ®é.
+CDM.MetadataSetManager.Elements:éäž­å
+æ°æ®éäž­çå
+çŽ 
+CDM.MetadataSetManager.Instructions:åšè®Ÿè®¡è§åŸäžäœ å¯ä»¥æ·»å é
+çœ®ç§»é€éåäž­çå
+æ°æ®éä»¥åå®ä»¬æå
+å«çå
+çŽ .
+CDM.MetadataSetManager.Remove:ç§»é€å
+æ°æ®é
+CDM.MetadataSetManager.Remove_Tooltip:ä»éåäžç§»é€éäž­çå
+æ°æ®é
+CDM.MetadataSetManager.Sets:å¯çšçå
+æ°æ®é
+CDM.MetadataSetManager.Title:<HTML><STRONG><FONT FACE={FONT} COLOR=Black SIZE=5><CENTER>å
+æ°æ®é</CENTER></FONT></STRONG></HTML>
+CDM.Move.At_Bottom:äžèœç§»åš{0} {1} æŽäœïŒå äžºå®å·²ç»åšåè¡šçæåºéš
+CDM.Move.At_Top:äžèœç§»åš {0} {1} æŽé«ïŒå äžºå®ä»¥åšåè¡šçæé¡¶éš
+CDM.Move.Cannot:äžèœç§»åšæä»¶{0}æŽäœïŒå äžº RecPlug and ArcPlug å¿
+é¡»åšåè¡šåºéš
+CDM.Move.Fixed:<html>RecPlug and ArcPlug éåžžéèŠåšæåïŒæä»¥å®ä»¬çäœçœ®æ¯åºå®ç<br>åŠæäœ å¿
+é¡»ç§»åšå®ïŒè¯·æåšçŒèŸ.cfg æä»¶.</html>
+CDM.Move.Move_Down:äžç§»
+CDM.Move.Move_Down_Tooltip:å°éæ©çæ¡ç®äžç§»
+CDM.Move.Move_Up:äžç§»
+CDM.Move.Move_Up_Tooltip:å°éæ©çæ¡ç®äžç§»
+CDM.Move.Title:éè¯¯ - äžèœç§»åš
+CDM.PlugInManager.Add:æ·»å æä»¶
+CDM.PlugInManager.Add_Tooltip:äœ¿çšè¿äžªéåç¹å®çæä»¶
+CDM.PlugInManager.Assigned:åœååé
+æä»¶
+CDM.PlugInManager.Configure:é
+çœ®æä»¶
+CDM.PlugInManager.Configure_Tooltip:æ¹åæéæä»¶çéé¡¹
+CDM.PlugInManager.Controls:çŒèŸæ§ä»¶
+CDM.PlugInManager.Ignore:äžèŠæ·»å æä»¶
+CDM.PlugInManager.Ignore_Tooltip:äžèŠåè¯¥éåäž­æ·»å ä»»äœæä»¶.
+CDM.PlugInManager.Instructions:äœ¿çšè¯¥è§åŸä»äœ çéåäž­å¢å ãé
+çœ®æè
+ç§»é€æä»¶. æ·»å ä»ç»åæ¡äž­éæ©ç¹å»âæ·»å æä»¶â.\né
+çœ®åç§»é€äžäžªæä»¶ïŒä»å·²åé
+çæä»¶æž
+åäž­éæ©ïŒç¶å\ni)éè¿ç®­å€Žæé®æ¹åæä»¶äœçœ®é¡ºåºïŒæ³šæïŒRecPlugåArcPlugçäœçœ®æ¯åºå®çïŒ.\nii)ç¹å»âç§»é€æä»¶âæé®ç§»é€.\n\næä»¶éé
+è¿äžäžªåŒ¹åºçåžŠæ»åšæ¡çåæ°æž
+åè®Ÿè®¡åºåïŒæ¿æŽ»åæ°åé®å
+¥æéæ©åŒ.
+CDM.PlugInManager.PlugIn:éæ©æ·»å çæä»¶:
+CDM.PlugInManager.PlugIn_Tooltip:è¯¥éåäž­å¯ä»¥äœ¿çšçæä»¶
+CDM.PlugInManager.PlugIn_Exists:è¯¥æä»¶å·²ç»åé
+ç»è¯¥éåäº.
+CDM.PlugInManager.PlugIn_Str:æä»¶
+CDM.PlugInManager.PlugIn_XML_Parse_Failed:äžèœäžº{0}\næä»¶ç¡®å®åæ°. è¯·ç¡®è®€å¯çæä»¶æäŸ\nè¿è¡pluginfo.plèæ¬çXMLæ å¿\næ­€èæ¬åšGreenstoneåŒååå¯Œ2.1èäž­æè¿°
+CDM.PluginManager.Plugin_Suggestion_Prompt:è¯¥éåäž­æ²¡æä»»äœäžäžªæä»¶å¯ä»¥å€çæä»¶ "{0}". äžåæä»¶å¯ä»¥çšæ¥å€çè¿äžªæä»¶.äœ ç°åšå¯ä»¥éè¿" æ·»å æä»¶" æé®å°å
+¶å å
+¥å°éåäž­.(æ³šæ: äœ å¯ä»¥éè¿è®Ÿè®¡é¢æ¿äžç"ææ¬æä»¶"éæ¶æ¹åæä»¶æž
+å)
+CDM.PlugInManager.Remove:ç§»é€æä»¶
+CDM.PlugInManager.Remove_Tooltip:ä»åè¡šäž­ç§»é€æéæ©çæä»¶
+CDM.PluginManager.SuggestedPluginListTitle:è¯¥æä»¶æšèçæä»¶
+CDM.PlugInManager.Title:<HTML><STRONG><FONT FACE={FONT} COLOR=Black SIZE=5><CENTER>æä»¶éæ© & é
+çœ®</CENTER></FONT></STRONG></HTML>
+CDM.PlugInManager.Parsing.Message:è®Ÿè®¡å·¥å
+·æ­£åšèœœå
+¥æä»¶ä¿¡æ¯.
+CDM.PlugInManager.Parsing.Title:èœœå
+¥æä»¶
+CDM.SearchTypeManager.Add:æ·»å æçŽ¢ç±»å
+CDM.SearchTypeManager.Add_Tooltip:å
+è®žåšè¯¥éåäž­æçŽ¢ç¹å®çç±»å
+CDM.SearchTypeManager.Assigned:åœååé
+æçŽ¢ç±»å
+CDM.SearchTypeManager.BuildType_Selection:çŽ¢åŒåš:
+CDM.SearchTypeManager.BuildType_Selection_Tooltip:éæ©è¯¥éåæçšççŽ¢åŒåš.
+CDM.SearchTypeManager.Enable:æ¯é«çº§æçŽ¢ææ
+CDM.SearchTypeManager.Instructions:å®ä¹æçŽ¢ç±»åæ¯äžäžªé«çº§ç¹åŸä»
+åšéæ©æ¯é«çº§æçŽ¢æææ¶å¯çš. (éè¿éæ©"æ¿æŽ»é«çº§æçŽ¢"å€éæ¡)äžæŠéæ©åæ¹åæçŽ¢ç±»åçé¡ºåºçæ§å¶è¢«æ¿æŽ».ä»ç»åæ¡éæ©äžäžªæçŽ¢ç±»åå"æ·»å ç±»å",æ¿æŽ»åæ·»å ç±»å.ä»åè¡šäž­éæ©äžäžªå·²å­åšæçŽ¢ç±»å,äœ¿çš"äžç§»"å"äžç§»"æ¥æ¹åé¡ºåº.æ"ç§»é€"æ¥å é€ç±»å.\n\næçŽ¢ç±»åæå®äºæçŽ¢æäŸçé¢:è¡šæ Œå¯¹åºfieldæçŽ¢ïŒææ¬å¯¹åºäžè¬æçŽ¢.é¡ºåºåŸéèŠïŒç¬¬äžäžªé»è®€åå§åæçŽ¢é¡µé¢.\n\næ³šæå°æ¿æŽ»æçŽ¢ç±»åä¹æ¹åäºçŽ¢åŒè§åŸä¹åŸéèŠ.FieldæçŽ¢æ¯Greenstoneçæ°ç¹è²ïŒå æ­€éèŠäžåççŽ¢åŒä¿¡æ¯.åœæçŽ¢ç±»åè¢«æ¿æŽ»ææåšè¿äžªæ°è®¡åäžè¢«æ¹åäžºææçåœåçŽ¢åŒïŒç¶èæ¯æçŽ¢ç±»åå€±æå°äŒåŒèµ·GLIæå€§èœåå°å°æ°çŽ¢åŒèœ¬æ¢äžºæ§çæ ŒåŒäœä¹äžäŒæ»æ¯æåïŒäžæåæ¶çŽ¢åŒå°äŒè¢«å é€.åšæ¯äžç§æ
+åµäžïŒå¯¹åçŽ¢åŒçå€ä»œäœäžºé
+çœ®æä»¶çæ³šééåžžææ.
+CDM.SearchTypeManager.Remove:ç§»é€æçŽ¢ç±»å
+CDM.SearchTypeManager.Remove_Tooltip:äžå
+è®žè¯¥éæ©ç±»åæçŽ¢è¯¥éå
+CDM.SearchTypeManager.SearchType:æçŽ¢ç±»å
+CDM.SearchTypeManager.SearchType_Selection:æçŽ¢ç±»å:
+CDM.SearchTypeManager.SearchType_Selection_Tooltip:è¯¥éåå¯çšççæçŽ¢ç±»å
+CDM.SearchTypeManager.Title:<HTML><STRONG><FONT FACE={FONT} COLOR=Black SIZE=5><CENTER>éæ©æçŽ¢ç±»å & æåº</CENTER></FONT></STRONG></HTML>
+CDM.SubcollectionManager.Add:å¢å è¿æ»€åš
+CDM.SubcollectionManager.Add_Tooltip:å¢å è¯¥éåçç¹å®è¿æ»€åš
+CDM.SubcollectionManager.Assigned:å®åœ±å­éåè¿æ»€åš
+CDM.SubcollectionManager.Exclude:äžå
+æ¬
+CDM.SubcollectionManager.Flags:å¹é
+æ¶çæ è®°
+CDM.SubcollectionManager.Flags_Tooltip:å¹é
+æ¶äœ¿çšçè§åè¡šèŸŸåŒæ è®°ïŒäŸåŠïŒ "i" æ¯å€§å°åå¹é
+ïŒ
+CDM.SubcollectionManager.Include:å
+æ¬
+CDM.SubcollectionManager.Inclusive:æä»¬å¯¹å¹é
+çæä»¶åä»ä¹?
+CDM.SubcollectionManager.Instructions:äœ¿çšè¯¥é¢æ¿æçŒçŽ¢åŒ.\ni) å®ä¹å­éåè¿æ»€åšïŒçè§åºäºç¹å®å
+æ°æ®åŒçéåææ¡£.äžæŠå®ä¹ïŒäœ å¯ä»¥åšåºäºäžäžªæè
+å€äžªè¿æ ·çè¿æ»€åšçä»¥åä»»æçç¹å®çŽ¢åŒäžäº§çåå.\nii)åºäºè¯­èšççŽ¢åŒååïŒåªæè¯¥è¯­èšçéåæä»¶æèœè¢«éæ©.\næ³šæå°äº§ççæ»çååæ°ç®æ¯ææçŽ¢åŒïŒå­éååè¯­èšéæ©ççç»å.äž€äžªçŽ¢åŒïŒäž€äžªå­éååäž€ç§è¯­èšå¯ä»¥äº§çå
+«ç§ååºåå.
+CDM.SubcollectionManager.Language_Controls:åé
+è¯­èš
+CDM.SubcollectionManager.Match:å¹é
+çè§åè¡šèŸŸåŒ: 
+CDM.SubcollectionManager.Match_Tooltip:å®ä¹å­éåæä»¶çè§åè¡šèŸŸåŒ
+CDM.SubcollectionManager.Name:å­éåè¿æ»€åšå:
+CDM.SubcollectionManager.Name_Tooltip:æ°çå­éåè¿æ»€åšå
+CDM.SubcollectionManager.Partitions_Disabled:è¿äžªå·¥å
+·åœåäžºdisableå äžºäœ åš{0-Current Mode}æš¡åŒäžæäœ.åœäžåªèœåš{1-Systems} å {2-Expert}æš¡åŒäžè®¿é®.éæ©æä»¶->éŠéé¡¹æ¥æ¹åæäœæš¡åŒ.
+CDM.SubcollectionManager.Remove:ç§»é€è¿æ»€åš
+CDM.SubcollectionManager.Remove_Tooltip:ä»åè¡šäž­ç§»é€æéçè¿æ»€åš
+CDM.SubcollectionManager.Replace:æ¿æ¢è¿æ»€åš
+CDM.SubcollectionManager.Replace_Tooltip:æŽæ°æéè¿æ»€åšçè¯Šç»èµæ
+CDM.SubcollectionManager.Source:Document attribute to match against:
+CDM.SubcollectionManager.Source_Tooltip:è¯¥è¿æ»€åšçæä»¶
+CDM.SubcollectionManager.Subcollection_Controls:å®ä¹è¿æ»€åš
+CDM.SubcollectionManager.Subindex_Controls:ååº
+CDM.SubcollectionManager.Title:<HTML><STRONG><FONT FACE={FONT} COLOR=Black SIZE=5><CENTER>ååºçŽ¢åŒ</CENTER></FONT></STRONG></HTML>
+CDM.SubcollectionIndexManager.Add_Subindex:æ·»å ååº
+CDM.SubcollectionIndexManager.Add_Subindex_Tooltip:åè¯¥éåæ·»å ç¹å®çååº
+CDM.SubcollectionIndexManager.Default_Partition_Indicator:[é»è®€ååº]
+CDM.SubcollectionIndexManager.PartitionName:ååºå:
+CDM.SubcollectionIndexManager.PartitionName_Tooltip:æ°ååºå
+CDM.SubcollectionIndexManager.Remove_Subindex:ç§»é€ååº
+CDM.SubcollectionIndexManager.Remove_Subindex_Tooltip:ä»éåäž­ç§»é€æéååº
+CDM.SubcollectionIndexManager.Replace_Subindex:æ¿æ¢ååº
+CDM.SubcollectionIndexManager.Replace_Subindex_Tooltip:æŽæ°æéååº
+CDM.SubcollectionIndexManager.Set_Default_Subindex:æå®äžºé»è®€
+CDM.SubcollectionIndexManager.Set_Default_Subindex_Tooltip:äœ¿åŸæéååºäžºé»è®€
+CDM.SubcollectionIndexManager.Source:åšå
+¶äžå»ºç«ååº:
+CDM.SubcollectionIndexManager.Source_Tooltip:åšè¯¥ååºäžå»ºç«å­éåè¿æ»€åš
+CDM.SubcollectionIndexManager.Subindexes:åé
+å­éåååº
+CDM.SuperCollectionManager.Instructions:äº€åéåæçŽ¢åšå äžªéåäž­è¿è¡ïŒå¥œååªæäžäžªéå.éè¿ç¹å»åè¡šäžé¢çåéçéååæ¥æå®äžäžªéåè¢«å
+å«äºäžäžªæçŽ¢.åœåéåäŒèªåšè¢«å
+å«.\nè­ŠåïŒåŠæäžªäººéåçžäºæ²¡æçžåççŽ¢åŒïŒå
+æ¬å­éååååè¯­èšååïŒïŒé£ä¹äº€åéåæçŽ¢å°äžäŒæ­£åžžå·¥äœ.çšæ·åªèœäœ¿çšææéåçäžè¬çŽ¢åŒæ¥æçŽ¢.
+CDM.SuperCollectionManager.Title:<HTML><STRONG><FONT FACE={FONT} COLOR=Black SIZE=5><CENTER>äº€åéåæçŽ¢é
+çœ®</CENTER></FONT></STRONG></HTML>
+CDM.TranslationManager.Add:æ·»å ç¿»è¯
+CDM.TranslationManager.Add_Tooltip:äžºè¯¥éåæ·»å ç¹å®ç¿»è¯
+CDM.TranslationManager.Affected_Features:ç¹ç¹
+CDM.TranslationManager.Assigned_Fragments:åé
+ç¿»è¯
+CDM.TranslationManager.Default_Text:åå§åææ¬ç¢ç
+CDM.TranslationManager.Fragment_Column:ææ¬ç¢ç
+CDM.TranslationManager.Instructions:äœ¿çšè¯¥è§åŸäžºäœ çéåè§å¯ååé
+ææ¬ç¢ççç¿»è¯.éŠå
+,ä»ç¹åŸåè¡šäž­éæ©äžäžªå®äœïŒäŸåŠïŒéåçº§å«å
+æ°æ®ååç±»åšåïŒ.äžäžæ­¥ïŒéæ©åçŒèŸäžæ®µææ¬,æè
+ä»ç»åæ¡äž­éæ©äžç§è¯­èšæ¥æ·»å äžæ®µæ°ææ¬.åšç©ºçœææ¬åºåé®å
+¥ææ¬,å°œå¯èœååå§ææ¬çžå
+³.ä»»äœæ¹ååšéåäž­ç«å³åºç°.
+CDM.TranslationManager.Language:ç¿»è¯çè¯­èš:
+CDM.TranslationManager.Language_Column:è¯­èš
+CDM.TranslationManager.Language_Tooltip:ç¿»è¯äžºçè¯­èš
+CDM.TranslationManager.Remove:ç§»é€ç¿»è¯
+CDM.TranslationManager.Remove_Tooltip:ä»è¯¥éåäž­ç§»é€ç¿»è¯
+CDM.TranslationManager.Replace:æ¿æ¢ç¿»è¯
+CDM.TranslationManager.Replace_Tooltip:æŽæ°æéæ©çç¿»è¯
+CDM.TranslationManager.Title:<HTML><STRONG><FONT FACE={FONT} COLOR=Black SIZE=5><CENTER>ææ¬ç¿»è¯</CENTER></FONT></STRONG></HTML>
+CDM.TranslationManager.Translation:ç¿»è¯ææ¬
+CDM.TranslationManager.Translation_Tooltip:åšæ­€å€é®å
+¥èŠç¿»è¯çå­ç¬Š
+#*******************
+#
+#***** Collection *****
+Collection.Collection:<HTML><STRONG><FONT FACE={FONT} COLOR=Black>éå</FONT></STRONG></HTML>
+Collection.Delete_Tooltip:å é€éæ©çæä»¶åæä»¶å€¹
+Collection.Filter_Tooltip:éå¶æä»¶æ äž­çæä»¶
+Collection.New_Folder_Tooltip:æ°å»ºæä»¶å€¹
+Collection.No_Collection:æ²¡æèä¹Š
+Collection.Stop:åæ­¢
+Collection.Stop_Tooltip:åæ­¢å€å¶æä»¶
+Collection.Workspace:<HTML><STRONG><FONT FACE={FONT} COLOR=Black>Workspace</FONT></STRONG></HTML>
+#**********************
+#
+#***** CollectionBuilt *****
+CollectionBuilt.Message:èä¹Šå·²ç»å­åšïŒå¯ä»¥é¢è§ã
+CollectionBuilt.Title:èä¹Šåå»ºç»æ
+#***************************
+#
+#***** CollectionManager *****
+CollectionManager.Build_Cancelled:èä¹Šåå»ºè¢«åæ¶
+CollectionManager.<input type="image" src="">Cannot_Create_Collection:åçéè¯¯ïŒèä¹Šäžèœè¢«åå»º
+CollectionManager.Cannot_Create_Collection_With_Reason:èä¹Šäžèœè¢«åå»ºå äžº:\n{0-Error message}
+CollectionManager.Cannot_Delete_Index:èä¹Šäžèœè¢«éå»ºå äžºäžèœå é€æ§ççŽ¢åŒæä»¶\nè¯·ç¡®ä¿Greenstoneæè
+å
+¶å®çšåºæ²¡æåšäœ¿çšè¿äºæä»¶\n ç¶åéè¯
+CollectionManager.Cannot_Delete_Index_Log:äžèœå é€æ§ççŽ¢åŒæä»¶æä»¥å¯Œå
+¥åæ­¢
+CollectionManager.Cannot_Open:{0-Collection file path}\näžçèä¹ŠäžèœæåŒ
+CollectionManager.Cannot_Open_With_Reason:{0-Collection file path}\näžçèä¹ŠäžèœæåŒå äžº:\n{1-Error message}
+CollectionManager.Creating_New:åå»ºäžæ¬æ°èä¹Š
+CollectionManager.Log_Created:æ¥å¿æä»¶å€¹åå»º
+CollectionManager.Loading_Collection:èœœå
+¥èä¹Š
+CollectionManager.Loading_Collection_Please_Wait:æ­£åšèœœå
+¥ïŒè¯·çšå...
+CollectionManager.Loading_Successful:å·²èœœå
+¥ {0}.
+CollectionManager.Missing_Config:èä¹ŠçŒºå°ææçcollect.cfgæä»¶ 
+CollectionManager.Not_Col_File:'{0}' äžæ¯äžäžªåŸä¹ŠéŠåçé¢èä¹Šæä»¶(.col)
+CollectionManager.No_Config_File:collect.cfgè¿æ²¡æè¢«mkcol.plåå»º.
+CollectionManager.Preview_Ready_Failed:åçéè¯¯ïŒèä¹Šäžèœé¢è§
+CollectionManager.Preview_Ready_Title:èä¹Šé¢è§ç¶æ
+CollectionManager.Session_Ready:èä¹Š {0} å¯ä»¥äœ¿çš
+CollectionManager.Build_Not_Moved:ç®åœäžèœç§»åš
+CollectionManager.Index_Not_Deleted:çŽ¢åŒç®åœäžèœå é€
+CollectionManager.Install_Exception:å®è£
+äž­åç°åŒåžž:\n{0}\nå¯èœç±äºWindowsææ¬å°åŸä¹ŠéŠéå®äºæä»¶\nè¯·ç¡®ä¿æææºæä»¶éœæ²¡æè¢«å€éšçšåºæåŒïŒç¶åéå»º
+#*****************************
+#
+#***** CollectionPopupMenu *****
+CollectionPopupMenu.Delete:å é€
+CollectionPopupMenu.New_Dummy_Doc:æ°çèææä»¶
+CollectionPopupMenu.New_Folder:æ°æä»¶å€¹
+#*******************************
+#
+#***** CreatePane *****
+CreatePane.Build:åå»ºéé¡¹
+CreatePane.Build_Tooltip:éé¡¹ïŒèä¹Šåœ¢æççŽ¢åŒååç±»é¶æ®µ
+CreatePane.Build_Collection:åå»ºèä¹Š
+CreatePane.Build_Collection_Tooltip:åŒå§åå»ºè¿çš
+CreatePane.Build_Progress:åå»ºè¿åºŠ
+CreatePane.Cancel_Build:åæ¶åå»º
+CreatePane.Cancel_Build_Tooltip:åæ­¢åå»ºè¿çš
+CreatePane.Full_Build:å®æéå»º
+CreatePane.Full_Build_Tooltip:å®æéå»ºèä¹Š
+CreatePane.Import:å¯Œå
+¥éé¡¹
+CreatePane.Import_Tooltip:Optionséé¡¹ïŒèä¹Šåœ¢æçæä»¶èœ¬æ¢åå
+æ°æ®åé
+é¶æ®µ
+CreatePane.Import_Progress:å¯Œå
+¥è¿åºŠ
+CreatePane.Incremental_Build:å¢ééå»º
+CreatePane.Incremental_Build_Tooltip:æŽå¿«ïŒåªæåå»ºè¿çšå¿
+éçæ­¥éª€è¢«è¿è¡
+CreatePane.Log:æ¶æ¯æ¥å¿
+CreatePane.Log_Tooltip:åšä»¥åçåå»ºå°è¯äž­æ¥çèŸåº
+CreatePane.Mode_All:ææ
+CreatePane.Options:éé¡¹ç»
+CreatePane.Options_Title:èä¹Šå¯Œå
+¥ååå»ºéé¡¹
+CreatePane.Preview_Collection:é¢è§èä¹Š
+CreatePane.Preview_Collection_Tooltip:é¢è§æ°åå»ºçèä¹Š
+#**********************
+#
+#***** Dates *****
+Dates.Mon:ææäž
+Dates.Tue:ææäº
+Dates.Wed:ææäž
+Dates.Thu:ææå
+Dates.Fri:ææäº
+Dates.Sat:ææå
+­
+Dates.Sun:æææ¥
+Dates.Jan:1æ
+Dates.Feb:2æ
+Dates.Mar:3æ
+Dates.Apr:4æ
+Dates.May:5æ
+Dates.Jun:6æ
+Dates.Jul:7æ
+Dates.Aug:8æ
+Dates.Sep:9æ
+Dates.Oct:10æ
+Dates.Nov:11æ
+Dates.Dec:12æ
+#**********************
+#
+#***** Delete Collection Prompt *****
+DeleteCollectionPrompt.Collection_Details:éæ©éåçè¯Šç»èµæ
+DeleteCollectionPrompt.Collection_List:å¯çšçéå
+DeleteCollectionPrompt.Confirm_Delete:è¯·éæ©æ è®°æ¡ç¡®è®€å é€éå.
+DeleteCollectionPrompt.Delete:å é€
+DeleteCollectionPrompt.Delete_Tooltip:å é€éæ©çéå
+DeleteCollectionPrompt.Details:åå»ºè
+ - {0}\nç»Žæ€è
+ - {1}\næè¿°\n{2}
+DeleteCollectionPrompt.Failed_Delete:éåäžèœå®å
+šå é€.
+DeleteCollectionPrompt.Failed_Title:å é€å€±èŽ¥!
+DeleteCollectionPrompt.No_Collection:æ²¡æéåè¢«éæ©.
+DeleteCollectionPrompt.Successful_Delete:éåå·²ç»è¢«å é€.
+DeleteCollectionPrompt.Successful_Title:å®å
+šå é€!
+DeleteCollectionPrompt.Title:éåå é€
+#**********************
+#
+#***** DirectoryLevelMetadata *****
+DirectoryLevelMetadata.Message:äœ æç®äžºéæ©çæä»¶å€¹åé
+'æä»¶å€¹çº§å«'.è¿äºå
+æ°æ®å°èªåšè¢«è¯¥æä»¶å€¹äžçæä»¶åæä»¶å€¹ç»§æ¿.è¿äžæ­¥è¯Žè¿äžªå
+æ°æ®äžèœä»æå®çå­ç±»ç§»é€,åªèœè¢«æ¿æ¢.ç»§ç»­è¿äžªè¡äžºè¯·æ'OK'.
+DirectoryLevelMetadata.Title:å
+³äºæ·»å æä»¶å€¹çº§å«å
+æ°æ®
+#********************
+#
+#***** EnrichPane *****
+EnrichPane.AutoMessage:è¿äžªæå, {0}, å±äºGreenstoneå
+æ°æ®é. 
+EnrichPane.ExistingValues:ç°æåŒ {0}
+EnrichPane.Expand:...
+EnrichPane.Expand_Tooltip:åšäžäžªå€§ææ¬æ¡äž­çŒèŸè¯¥åŒ
+EnrichPane.InheritedMetadataSelected:è¯¥å
+æ°æ®ç»§æ¿äžçº§æä»¶å€¹å¹¶äžäžèœçŒèŸ.
+EnrichPane.No_File:æ²¡ææä»¶è¢«éæ©
+EnrichPane.No_Metadata:æ²¡æå¯çšçå
+æ°æ®
+EnrichPane.No_Metadata_Element:<HTML><STRONG><FONT FACE={FONT} COLOR=Black>æ²¡æå
+æ°æ®æåè¢«éæ©</FONT></STRONG></HTML>
+EnrichPane.Value_Field_Tooltip:å°åé
+ç»éæ©çå
+æ°æ®æåçåŒ
+EnrichPane.Value_Field_Tooltip_Uneditable:å·²ç»åé
+ç»éæ©çå
+æ°æ®æåçåŒ
+#***********************
+#
+#****** ExplodeMetadataPrompt *******
+ExplodeMetadataPrompt.Explode:å±åŒ
+ExplodeMetadataPrompt.Explode_Tooltip:å±çå
+æ°æ®æä»¶
+ExplodeMetadataPrompt.Instructions:å±åŒè¯¥å
+æ°æ®æä»¶å°äº§çå¯çŒèŸçå
+æ°æ®çäžªå«è®°åœ. 
+ExplodeMetadataPrompt.Failed_Title:å±åŒå€±èŽ¥.
+ExplodeMetadataPrompt.Failed_Explode:æ°æ®åº {0} äžèœå±åŒ.
+ExplodeMetadataPrompt.NotExplodable:æä»¶äžèœå±åŒ.
+ExplodeMetadataPrompt.Successful_Explode:æ°æ®åº {0} æåå±åŒ.
+ExplodeMetadataPrompt.Successful_Title:å±åŒå®å
+š.
+ExplodeMetadataPrompt.Title:å±åŒå
+æ°æ®åº
+#***********************
+#
+#****** WriteCDImagePrompt *******
+WriteCDImagePrompt.CD_Name:CD/DVD å
+WriteCDImagePrompt.Export:å CD/DVD åŸå
+WriteCDImagePrompt.Export_Tooltip:äœäžºWindows CD/DVD åŸååæéæ©çéååå
+¥
+WriteCDImagePrompt.Failed_Export:éå ({0}) äžèœå¯Œåº.
+WriteCDImagePrompt.Failed_Title:å¯Œåºå€±èŽ¥
+WriteCDImagePrompt.Instructions:åèªå®è£
+çWindows CD/DVDå¯ŒåºäžäžªææŽå€éå.(å°œç®¡è¿åšä»»æå¹³å°äžéœèœè¿è¡,äœæ¯CD/DVDåå»ºäžºåªèœåšWindowsäžè¿è¡ïŒ.
+WriteCDImagePrompt.Progress_Label:å€å¶æä»¶ïŒè¿å¯èœéèŠäžå®æ¶éŽ...
+WriteCDImagePrompt.Size_Label:äŒ°è®¡å€§å°: 
+WriteCDImagePrompt.Successful_Export:éå ({0}) è¢«å¯Œåº.
+WriteCDImagePrompt.Successful_Title:å¯Œåºå®å
+š
+WriteCDImagePrompt.Title:å CD/DVD å¯Œåºéå
+#************************
+#
+#****** ExportAsPrompt *******
+ExportAsPrompt.Export_Name:å¯Œåºè·¯åŸåç§°
+ExportAsPrompt.Export:å¯Œåºéå
+ExportAsPrompt.Export_Tooltip:å¯Œåºåšéäž­çæ ŒåŒäž­çéå
+ExportAsPrompt.Failed_ExportOne:éå, {0}, äžèœå€è¢«å¯Œåº
+ExportAsPrompt.Failed_ExportMany:éå-- {0} -- äžèœå€è¢«å¯Œåº
+ExportAsPrompt.Failed_Details:æ¥ç{1} è¯Šç»ä¿¡æ¯
+ExportAsPrompt.Failed_Title:å¯Œåºå€±èŽ¥
+ExportAsPrompt.Instructions:å¯Œåºäžäžªæå€äžªéå
+ExportAsPrompt.Progress_Label:å¯Œåºæä»¶. è¿å¯èœèŠèèŽ¹äžäºæ¶éŽ
+ExportAsPrompt.Successful_ExportOne:éå, {0}, å·²ç»è¢«å¯Œåº
+ExportAsPrompt.Successful_ExportMany:éå -- {0} -- å·²ç»è¢«å¯Œåº.
+ExportAsPrompt.Successful_Details:æä»¶å¯Œåºå°: {1}
+ExportAsPrompt.Successful_Title:å¯Œåºå®æ¯
+ExportAsPrompt.Title:å¯Œåºéå
+ExportAsPrompt.SaveAs:å¯Œåºå°
+ExportAsPrompt.SaveAs_Tooltip:éæ©äœ æ³å¯Œåºçæ ŒåŒ
+#************************
+#
+#*****ExternalCollectionPrompt********
+ExternalCollectionPrompt.NewMDS:åå»ºäžäžªæ°çç©ºçå
+æ°æ®é
+ExternalCollectionPrompt.ExistingMDS:éæ©äžäžªæå€äžªå
+æ°æ®é
+ExternalCollectionPrompt.Title:å èœœå€éšéå
+ExternalCollectionPrompt.Instructions_1:äœ å°èŠå èœœäžäžªè¿æ²¡æè¢«GLIåå»ºçéå. äœ äŒè¢«èŠæ±éæ©äžäžªæå€äžªå
+æ°æ®éãå·²å­åšçå
+æ°æ®äŒè¢«å¯Œå
+¥å°éåäž­. åå§çå
+æ°æ®æä»¶äŒè¢«ä¿å­å°import.bak.
+ExternalCollectionPrompt.Instructions_2:äœ å°èŠå èœœäžäžªè¿æ²¡æè¢«GLIåå»ºçéå. äœ äŒè¢«èŠæ±éæ©äžäžªæå€äžªå
+æ°æ®é. äœ å¯ä»¥åå»ºäžäžªç©ºçæ°æ®ééé¢æ°çå
+æ°æ®å°äŒè¢«èªåšå¯Œå
+¥. æ­€å€,äœ ä¹å¯ä»¥éæ©å·²ç»å­åšçæ°æ®é,ç¶åäžå·²ç»å­åšçéååå¹¶.åå§çå
+æ°æ®æä»¶äŒè¢«ä¿å­åš import.bak.
+#****************************************
+#
+#***** Inherited Metadata *****
+ExtractedMetadata.Message:éäž­çæä»¶ææä»¶å€¹å
+å«äºæååºæ¥çå
+æ°æ®, äœæ¯ç®åå®æ¯éèç. èŠæ¥çæååºæ¥çæ°æ®ç¹å»"[F]ile" èå ç¶åéæ© "[P]references". åš "General" å±æ§äž­éæ© "View Extracted Metadata", ç¶åç¹å»"[O]k".
+ExtractedMetadata.Title:æ­€æä»¶æä»¶å€¹äž­æéèçå
+æ°æ®
+#
+#***** FileActions *****
+FileActions.Calculating_Size:è®¡ç®éäž­çæä»¶çå€§å°
+FileActions.Copying:å€å¶ {0}
+FileActions.Deleting:å é€ {0}
+FileActions.Directories_Selected:{0} æä»¶å€¹è¢«éæ©
+FileActions.Directory_Exists:<html>æä»¶å€¹<br>{0}<br>å·²ç»å­åš. æä»¶å°äŒè¢«å€å¶è¿å».</html>
+FileActions.Directory_Selected:1äžªæä»¶å€¹è¢«éäž­
+FileActions.File_Already_Exists_No_Create:æä»¶ '{0}' å·²ç»å­åš. 
+FileActions.File_Already_Exists_Message:{0}\nä»¥æ­€åœåçæä»¶å·²ç»å­åš, ç®¡çåæ¥å£æ²¡æåæ³èŠçå®.è¯·æ£æ¥æä»¶æé.
+FileActions.File_Already_Exists_Title:éè¯¯ - æä»¶å·²ç»å­åš.
+FileActions.File_And_Directories_Selected:1äžªæä»¶å{0} æä»¶å€¹è¢«éäž­
+FileActions.File_And_Directory_Selected:äžäžªæä»¶åäžäžªæä»¶å€¹è¢«éäž­
+FileActions.File_Create_Error:æä»¶ {0} äžèœè¢«åå»º
+FileActions.Folder_Create_Error:æä»¶{0}äžèœè¢«åå»º
+FileActions.File_Exists:<html>{0} å·²ç»å­åš. èŠèŠçå?</html>
+FileActions.File_Not_Deleted_Message:{0}\næä»¶çåå­äžèœè¢«å é€ \nè¯·æ£æ¥æ­€æä»¶æ¯åŠè¢«æåŒ, ç¶åéè¯. 
+FileActions.File_Not_Deleted_Title:éè¯¯ - æä»¶äžèœè¢«å é€.
+FileActions.File_Not_Found_Message:{0}\næŸäžå°æä»¶çåå­. äžæŠæä»¶è§åŸè¢«å·æ°, è¯·æ£æ¥æä»¶æ¯åŠè¿å­åš.
+FileActions.File_Not_Found_Title:éè¯¯ - æ²¡ææŸå°æä»¶.
+FileActions.File_Selected:éäž­äžäžªæä»¶
+FileActions.Files_And_Directory_Selected:{0} æä»¶åæä»¶å€¹è¢«éäž­
+FileActions.Files_Selected:{0} æä»¶è¢«éäž­
+FileActions.Folder_Already_Exists:æä»¶å€¹çåå­ '{0}' å·²ç»è¢«äœ¿çš æ æ³åå»º.
+FileActions.Increase_Depth:å¢å æ·±åºŠ1ã
+FileActions.Insufficient_Space_Message:æä»¶æäœå€±èŽ¥ïŒå äžºæ²¡æè¶³å€çç©ºéŽ.äžºäœ¿æäœæåïŒäœ è¿éèŠ: {0}
+FileActions.Insufficient_Space_Title:éè¯¯ - æ è¶³å€çç©ºéŽ
+FileActions.Moving:ç§»åš{0}
+FileActions.No_Activity:æ æäœ
+FileActions.Possible_Cyclic_Path:{1} æ¯{0} ç®åœæ·±åºŠå¹¶äžæ¯éåœè·¯åŸïŒèŠç»§ç»­åïŒ
+FileActions.Read_Only:æä»¶åªèœè¯»åäžèœå é€ã
+FileActions.Selected:{0} æä»¶å {1} æä»¶å€¹éäž­
+FileActions.Unknown_File_Error_Message:å°œç®¡æ²¡æéè¯¯ä¿¡æ¯ïŒæç»çæ£æ¥æŸç€ºæºæä»¶åç®çæä»¶äžå. åå æªç¥. è¯·æ£æ¥äœ çåªäœåæŽæ°JVM.
+FileActions.Unknown_File_Error_Title:éè¯¯ -æªç¥çæä»¶éè¯¯
+FileActions.Write_Not_Permitted_Message:Tç®¡çåæ²¡ææéåå
+¥\n{0}\nè¯·æ£æ¥æä»¶æéã
+FileActions.Write_Not_Permitted_Title:éè¯¯ - äžæ­£ç¡®çæä»¶æé
+FileActions.Yes_To_All:åºçšå°å
+šéš
+#************************
+#
+#******* File Associations dialog **********
+FileAssociationDialog.Add:æ·»å 
+FileAssociationDialog.Add_Tooltip:çšæ­€çšåºæ¥æµè§è¿ç§ç±»åçæä»¶
+FileAssociationDialog.Batch_File:æ¹å€çæä»¶
+FileAssociationDialog.Browse:æµè§
+FileAssociationDialog.Browse_Tooltip:ä»æä»¶ç©ºéŽäž­éæ©äœ¿çšççšåº
+FileAssociationDialog.Browse_Tooltip_Mac:æµè§ç®åéå¯¹MacOSè¢«çŠçšççšåº
+FileAssociationDialog.Browse_Title:éæ©åºçšçšåº
+FileAssociationDialog.Close:å
+³é­
+FileAssociationDialog.Close_Tooltip:å
+³é­å¯¹è¯æ¡å¹¶äžåå°äž»çªå£
+FileAssociationDialog.Command:è¿è¡åœä»€:
+FileAssociationDialog.Command_File:åœä»€æä»¶
+FileAssociationDialog.Command_Tooltip:èŸå
+¥å¯åšçšåºçåœä»€
+FileAssociationDialog.Details:æ°çæä»¶éåçç»è
+FileAssociationDialog.Executable_File:å¯æ§è¡æä»¶
+FileAssociationDialog.Existing_Associations:ç®åçæä»¶éå
+FileAssociationDialog.Extension:æä»¶ç»å°Ÿ:
+FileAssociationDialog.Extension_Tooltip:æ¥çæä»¶æ©å±å
+FileAssociationDialog.Instructions:çšè¿äžªå¯¹è¯æ¡æ¥è®Ÿçœ®å€éšçšåºçšä»ä¹æ¥æµè§ç¹å®æä»¶ç±»å, ä»ä¹åœä»€æ¥å¯åšçšåº.\næ·»å æ°çæä»¶ç±»åïŒåš 'For files ending'äž­èŸå
+¥æä»¶æ©å±å. æ·»å æä¿®æ¹å¯åšåœä»€, åš 'Launch command'äž­èŸå
+¥åœä»€ æè
+ç¹å»æµè§æ¥æ¥æŸåéçæä»¶ç³»ç»ã
+FileAssociationDialog.Table.Command:åœä»€
+FileAssociationDialog.Table.Extension:æ©å±
+FileAssociationDialog.Title:çŒèŸæä»¶éå
+FileAssociationDialog.Remove:ç§»é€
+FileAssociationDialog.Remove_Tooltip:ä»ç°æçæä»¶éåäž­ç§»é€éäž­çéå
+FileAssociationDialog.Replace:æ¿æ¢
+FileAssociationDialog.Replace_Tooltip:çšæ°çéåæ¿æ¢éäž­çéå
+#*******************
+#
+#******Filter***************
+Filter.0:HTM & HTML
+Filter.1:XML
+Filter.2:ææ¬æä»¶
+Filter.3:åŸå
+Filter.All_Files:æææä»¶
+Filter.Filter_Tree:å±ç€ºæä»¶
+Filter.Invalid_Pattern:<HTML><FONT FACE={FONT} COLOR=Black>äœ èŸå
+¥çè¿æ»€æä»¶æš¡åŒæ æ.<BR>Please try again using regular expression syntax and with<BR>* for the wildcard character.</FONT></HTML>
+#***********************
+#
+#***** GAuthenticator *****
+GAuthenticator.Password:å¯ç :
+GAuthenticator.Password_Tooltip:åšæ­€å€é®å
+¥äœ çå¯ç 
+GAuthenticator.Title:éèŠèŸå
+¥å¯ç .
+GAuthenticator.Username:çšæ·å:
+GAuthenticator.Username_Tooltip:åšæ­€å€é®å
+¥çšæ·å
+#**************************
+#
+#***** General Messages *****
+# 0 - A String representing the name and method of the class in question.
+General.Apply:åºçš
+General.Apply_Tooltip:åºçšåœåè®Ÿçœ®äœäžéåºå¯¹è¯æ¡
+General.Browse:æµè§...
+General.Cancel:åæ¶
+General.Cancel_Tooltip:åæ¶åå
+General.Close:å
+³é­
+General.Close_Tooltip:å
+³é­å¯¹è¯æ¡
+General.Edit:çŒèŸ
+General.Error:éè¯¯
+General.No:No
+General.NotSunJava:Java vendor: {0}\næ³šæå°æ°å­åŸä¹ŠéŠçé¢å·²ç»è¢«åŒååºæ¥å¹¶åšJavaç³»ç»äžåŸå°æµè¯. 
+General.OK:OK
+General.OK_Tooltip:æ¥ååœåè®Ÿçœ®å¹¶éåºå¯¹è¯æ¡
+General.Open:æåŒ
+General.Outstanding_Processes:<html>æ°å­åŸä¹ŠéŠçé¢äžäŒå®å
+šå
+³é­ç¥éææçšåº<br>äŒŽéæ°å­åŸä¹ŠéŠçé¢å¯åšççšåºéœéåº.</html>
+General.Outstanding_Processes_Title:ç­åŸ
+éåº
+General.Pure_Cancel_Tooltip:äž­æ­æäœ
+General.Review_Output:è¯·æ£æ¥äžé¢èŸåº:
+General.Usage:Usage: {0} <params>\nAll parameters are optional but the Librarian Interface may fail to work if -gsdl and -library aren't set.\n -gsdl <path>  : Force path to gsdl\n -library <path> : Path to cgi-bin\n -mozilla <path> : Enabled mozilla\n -mirror : Enable web-mirroring controls\n -laf [java|windows|motif|mac] : Look and feel\n -debug : Enable debug messages\n -no_load : Don't load previously open collection\n -load <path> : Load the specified collection
+General.View:å¯çåŒ
+General.Warning:è­Šå
+General.Yes:Yes
+#****************************
+#
+#***** GShell *****
+GShell.BadArgument:åæ° {0} ææ.
+GShell.BadArgumentValue:åæ° {0} æ æ.
+GShell.BadPluginOptions:æ æåæ°åšæä»¶ {0}.
+GShell.BadClassifierOptions:æ æåæ°åšåç±»åš {0}.
+GShell.Build.Auxilary:åå»ºèŸ
+å©æä»¶åæž
+ç...
+GShell.Build.BuildBegun1:************** åå»ºåŒå§ **************
+GShell.Build.BuildCancelled:**************   åæ¶    **************
+GShell.Build.BuildComplete1:************** åå»ºç»æ **************
+GShell.Build.CompressText:åçŒ©ææ¬...
+GShell.Build.Index:åå»ºåºäº {0-index source and level}ççŽ¢åŒ...
+GShell.Build.InfoDatabase:åå»ºä¿¡æ¯æ°æ®åº...
+GShell.Build.Phind:çæPhind åç±»åš. è¿éèŠäžäºæ¶éŽ...
+GShell.Command:åœä»€
+GShell.Failure:åœä»€å€±èŽ¥.
+GShell.Import.FileNotProcessed:æä»¶ {0-target file path} è¢«è®€å¯äœäžèœè¢«ä»»äœæä»¶å€ç.
+GShell.Import.FileNotRecognised:æä»¶ {0-target file path} äžèœè¢«ä»»äœæä»¶è®€å¯.
+GShell.Import.FileProcessing:æä»¶ {0-target file path} æ­£åšè¢«æä»¶ {1-plugin name}å€ç.
+GShell.Import.FileProcessingError:æä»¶ {0-target file path} åšå€çäž­éå°éè¯¯.
+GShell.Import.ImportBegun1:************** å¯Œå
+¥åŒå§ **************
+GShell.Import.ImportComplete1:************** å¯Œå
+¥ç»æ **************
+GShell.Import.ImportComplete2:{0-number documents considered} å¯ä»¥å€ççææ¡£:
+GShell.Import.ImportComplete2.1:äžäžªå¯ä»¥å€ççææ¡£:
+GShell.Import.ImportComplete.Processed:{0-number processed} å€çè¿çææ¡£å¹¶äžå
+å«åšéåäž­. 
+GShell.Import.ImportComplete.Processed.1:äžäžªå€çè¿çææ¡£å¹¶äžåšéåäž­. 
+GShell.Import.ImportComplete.Blocked:{0-number blocked} è¢«æä»¶é»æ­¢å å
+¥ 
+GShell.Import.ImportComplete.Blocked.1:äžäžªè¢«æä»¶é»æ­¢å å
+¥
+GShell.Import.ImportComplete.Ignored:{0-number ignored} äžè¢«è®€å¯
+GShell.Import.ImportComplete.Ignored.1:äžäžªäžè¢«è®€å¯.
+GShell.Import.ImportComplete.Failed:{0-number failed} è¢«åŠè®€.
+GShell.Import.ImportComplete.Failed.1:äžäžªè¢«åŠè®€.
+GShell.Import.ImportComplete3:\n
+GShell.Parsing_Metadata_Complete:æ¡£æ¡æä»¶å
+æ°æ®æœåå®æ.
+GShell.Parsing_Metadata_Start:ä»æ¡£æ¡æä»¶äž­æåå
+æ°æ®.
+GShell.Success:åœä»€å®æ.
+#*********************
+#
+#***** GUI *****
+# Currently Enabled and Disabled display the same text but in different
+# colours. If necessary this can be changed.
+GUI.Create:åå»º
+GUI.Create_Tooltip:çšGreenstoneåå»ºäœ çéå
+GUI.Design:è®Ÿè®¡
+GUI.Design_Tooltip:è®Ÿè®¡äœ çéåçåèœåå€è§
+GUI.Download:äžèœœ
+GUI.Download_Tooltip:äžºäœ çéåä»äºèçœäžé¢äžèœœèµæº
+GUI.Enrich:å å
+¥
+GUI.Enrich_Tooltip:äžºäœ çéåæä»¶åé
+å
+æ°æ®
+GUI.Gather:æ¶é
+GUI.Gather_Tooltip:éæ©æä»¶å
+å«å
+¥äœ çéå
+#***************
+#
+#***** HELP *****
+Help.Contents:å
+å®¹
+Help.Title:ç®¡çåçé¢åž®å©é¡µé¢
+#
+#***** LockFileDialog *****
+LockFileDialog.Cancel_Tooltip:äžèŠçªåéå®æä»¶çæ§å¶æ
+LockFileDialog.Date:æ¥æ
+LockFileDialog.Error:éè¯¯
+LockFileDialog.Lockfile_Message_One:éå®æä»¶çåºç°è¯Žæéåæ¯æåŒç.
+LockFileDialog.Lockfile_Message_Two:äœ æ³çªåéå®æä»¶çæ§å¶æå?
+LockFileDialog.Machine:åªé
+LockFileDialog.Name:åå­
+LockFileDialog.OK_Tooltip:çªåéå®æä»¶çæ§å¶æ
+LockFileDialog.Title:éå®æä»¶æ¢æµ
+LockFileDialog.User:è°
+#********************
+#
+#*****MappingPrompt **********
+MappingPrompt.File:æä»¶å€¹
+MappingPrompt.Map:åå»ºå¿«æ·æ¹åŒ
+MappingPrompt.Name:åå­
+MappingPrompt.Title:åå»ºæä»¶å€¹å¿«æ·æ¹åŒ
+MappingPrompt.Unmap:ç§»é€å¿«æ·æ¹åŒ
+#*******************
+#
+#***** Menu Options *****
+Menu.Collapse:å
+³é­æä»¶å€¹
+Menu.Edit:çŒèŸ
+Menu.Edit_Copy:å€å¶ (ctrl-c)
+Menu.Edit_Cut:åªå (ctrl-x)
+Menu.Edit_Paste:ç²èŽŽ (ctrl-v)
+Menu.Expand:æåŒæä»¶å€¹
+Menu.Explode_Metadata_Database:å±åŒå
+æ°æ®åº
+Menu.File:æä»¶
+Menu.File_Associations:æä»¶å
+³è...
+Menu.File_CDimage:åå
+¥ CD/DVD åŸå...
+Menu.File_Close:å
+³é­
+Menu.File_Delete:å é€...
+Menu.File_Exit:éåº
+Menu.File_ExportAs:å¯Œåº...
+Menu.File_New:æ°å»º...
+Menu.File_Open:æåŒ...
+Menu.File_Options:éŠéé¡¹...
+Menu.File_Save:ä¿å­
+Menu.Help:åž®å©
+Menu.Help_About:å
+³äº...
+Menu.Metadata_View:äžº {0} åé
+å
+æ°æ®
+Menu.Open_Externally:åšå€éšçšåºäž­æåŒ
+#********************
+#
+#***** MetaAudit *****
+MetaAudit.Close:å
+³é­
+MetaAudit.Close_Tooltip:å
+³é­è¯¥å¯¹è¯æ¡
+MetaAudit.Title:ææå
+æ°æ®
+#*********************
+#
+#***** Metadata *****
+Metadata.Element:å
+çŽ 
+Metadata.Value:åŒ
+MetadataSet.Files:å
+æ°æ®éæä»¶
+#*********************************************
+#
+#******** MetadataImportMappingPrompt *********
+MIMP.Add:æ·»å 
+MIMP.Add_Tooltip:åæééäž­æ·»å å
+æ°æ®æå
+MIMP.Ignore:å¿œç¥
+MIMP.Ignore_Tooltip:å¿œç¥è¯¥å
+æ°æ®æå
+MIMP.Instructions:å
+æ°æ®æå {0} äžèœèªåšå¯Œå
+¥è¯¥éå. 
+MIMP.Merge:åå¹¶
+MIMP.Merge_Tooltip:å°å
+æ°æ®æåæ å°å°æééçæå®æå
+MIMP.Source_Element:æºå
+æ°æ®æå:
+MIMP.Target_Element:ç®æ å
+æ°æ®æå:
+MIMP.Target_Set:ç®æ å
+æ°æ®é:
+MIMP.Title:åå¹¶éæ±.
+#*****************************
+#
+#***** Mirroring *****
+Mirroring.ClearCache:æž
+ç©ºçŒå­
+Mirroring.ClearCache_Tooltip:å é€ææäžèœœçæä»¶
+Mirroring.Download:äžèœœ
+Mirroring.Download_Tooltip:åŒå§äžäžªæ°çäžèœœä»»å¡
+Mirroring.Download_Controls:äžèœœè®Ÿçœ®
+Mirroring.Download_Depth:äžèœœæ·±åºŠ
+Mirroring.Download_Depth.Zero:é¶
+Mirroring.Download_Depth.Unlimited:æ çºŠæç
+Mirroring.Download_Depth_Tooltip:äžèœœæ¶çè¶
+éŸæ¥çæ·±åºŠ
+Mirroring.Download_Embedded:ä»
+äžèœœææ¬ïŒäžå
+æ¬åŸè±¡ïŒæ ·åŒè¡šç­ïŒ
+Mirroring.DownloadJob.Close:å
+³é­
+Mirroring.DownloadJob.Close_Tooltip:ä»åè¡šäž­å é€è¯¥ä»»å¡ïŒåŠæåœåæ­£åšæ§è¡ååæ­¢å®æ§è¡
+Mirroring.DownloadJob.Downloading:äžèœœ {0}
+Mirroring.DownloadJob.Download_Complete:äžèœœå®æ
+Mirroring.DownloadJob.Download_Stopped:äžèœœåæ­¢
+Mirroring.DownloadJob.Download_Progress:æè¿çšäžèœœ
+Mirroring.DownloadJob.Log:æ¥çæ¥å¿
+Mirroring.DownloadJob.Log_Tooltip:æ¥çè¯¥äžèœœçè¯Šç»å
+å®¹
+Mirroring.DownloadJob.Pause:æå
+Mirroring.DownloadJob.Pause_Tooltip:æåè¯¥äžèœœ
+Mirroring.DownloadJob.Resume:ç»§ç»­
+Mirroring.DownloadJob.Resume_Tooltip:ç»§ç»­è¯¥äžèœœ
+Mirroring.DownloadJob.Status:äžèœœç¶æ {0} of {1} æä»¶ ({2} è­Šå, {3} éè¯¯)
+Mirroring.DownloadJob.Waiting:ç­åŸ
+å¯åš
+Mirroring.DownloadJob.Waiting_User:ç­åŸ
+çšæ·çåšäœ
+Mirroring.Higher_Directories:åªå
+è®žURLäžçéåæä»¶
+Mirroring.Invalid_URL:èŸå
+¥çURLæ æïŒè¯·æŽæ­£
+Mirroring.Invalid_URL_Title:æ æçURL
+Mirroring.Preferences:åæ°éæ©...
+Mirroring.Preferences_Tooltip:å
+è®žä»£çïŒå¹¶äž/æè
+çŒèŸä»£çè®Ÿçœ®
+Mirroring.Same_Host:ä»
+å
+è®žåäžå°åçéåæä»¶
+Mirroring.Source_URL:æºURL
+Mirroring.Source_URL_Tooltip:äžèœœç®çå°åçURL
+#*********************
+#
+#***** Missing EXEC *****
+MissingEXEC.Message:è­Šå! äœ äžèœæ¥çåŸä¹ŠéŠæ¥å£çšåºéçæ°çå
+å®¹ãé€éäœ æå®å°GreenstoneåŸä¹ŠéŠwebæå¡åšçè·¯åŸ ïŒäœ æèœç°åšè®¿é®äžé¢çææ¬åæè
+éåè®Ÿå®åæ°åéæ©è¿æ¥è¡š.æ³šæäžäžªææçURLæ¯ä»¥åè®®âhttp;//âåŒå§ç,å¯èœä»¥å¯æ§è¡çåç§° ("gsdl" for Greenstone local library server, "library" for other web servers)ç»æ.
+MissingEXEC.Title:çŒºå°GreenstoneçåŸä¹ŠéŠå°å
+#***** Missing EXEC_GS3 *****
+MissingEXEC_GS3.Message:è­Šå! äœ äžèœæ¥çåŸä¹ŠéŠæ¥å£çšåºéçæ°çå
+å®¹ãé€éäœ åšæ¬å°è¿è¡Tomcatwebæå¡åšäž­æå®å°Greenstoneäžäžæçè·¯åŸ ïŒäœ æèœç°åšè®¿é®äžé¢çææ¬åæè
+éåè®Ÿå®åæ°åéæ©è¿æ¥è¡š.æ³šæäžäžªææçURLæ¯ä»¥åè®®âhttp;//âåŒå§ç,çŒºççå°åæ¯http://localhost:8080/greenstone3.
+MissingEXEC_GS3.Title:çŒºå°Greenstone 3 åŸä¹ŠéŠå°å
+#***** Missing GLIServer *****
+MissingGLIServer.Message:è­Šå!äœ äžèœå€çåŸä¹ŠéŠæ¥å£çšåºéçæ°çå
+å®¹ ïŒé€éäœ æå®å°è¿çš Greenstone "gliserver" èæ¬çå°åïŒäœ æèœç°åšè®¿é®äžé¢çææ¬åæè
+éåè®Ÿå®åæ°åéæ©è¿æ¥è¡š.æ³šæäžäžªææçURLæ¯ä»¥åè®®âhttp;//âåŒå§çïŒå¹¶äžä»¥ "gliserver"ç»æ.
+MissingGLIServer.Title:çŒºå° GLIServer å°å
+#***** Missing GSDL *****
+MissingGSDL.Message:è­Šå! äœ æ²¡æå®è£
+Greenstoneæ¬å°æ°å­åŸä¹ŠéŠçå€æ¬ïŒäžèœè®¿é®åŸä¹ŠéŠæ¥å£äžçææå
+å®¹.åŠæäœ è®€äžºè¯¯æ¥åäºè¿äžªæ¶æ¯ïŒè¯·æ£æ¥äœ çå®è£
+åæå®çè·¯åŸæèæ¬æä»¶
+MissingGSDL.Title:Missing Greenstone Path
+#***** Missing PERL *****
+MissingPERL.Message:è­Šå!äœ æ²¡æå®è£
+PERLïŒäžèœåå»ºæ°çå
+å®¹åå»ºç«å·²å­åšçå
+å®¹ïŒåŸä¹ŠéŠæ¥å£äžèœåç°äœ ç³»ç»æ²é
+å
+çRERL. åŠæäœ è®€äžºè¯¯æ¥åäºè¿äžªæ¶æ¯ïŒè¯·æ£æ¥äœ çå®è£
+åæå®çè·¯åŸæèæ¬æä»¶
+MissingPERL.Title:Missing PERL Path
+#******* MissingWGET ********
+MissingWGET.Message:è­Šå!ç±äºåŸä¹ŠéŠæ¥å£äžèœå®äœåéçWGetçæ¬ïŒæä»¥äžèœäœ¿çšWebéå åŠæäœ è®€äžºè¯¯æ¥åäºè¿äžªæ¶æ¯ïŒè¯·æ£æ¥äœ çå®è£
+åæå®çè·¯åŸæèæ¬æä»¶
+MissingWGET.Title:Missing WGet
+#******* MissingImageMagick ********
+MissingImageMagick.Message:è­Šå! åŸä¹ŠéŠæ¥å£äžèœåžåœéŸäžºåéçImageMagickçæ¬,å æ­€ImagePlugå°æ æ³å·¥äœãåŠæäœ æ³å»ºç«åŸè±¡å
+å®¹ïŒè¯·å®è£
+ ImageMagick 
+MissingImageMagick.Title:çŒºå° ImageMagick
+#*****************************
+#
+#***** New Session *****
+NewCollectionPrompt.Base_Collection:åºäºæ­€éŠèïŒ
+NewCollectionPrompt.Base_Collection_Tooltip:éæ©äžäžªå·²ç»å­åšçéŠèïŒæ°éŠèåºäºè¿äžªéŠè
+NewCollectionPrompt.Collection_Description:å
+å®¹æè¿°ïŒ
+#NewCollectionPrompt.Collection_Email:äœè
+Email:
+NewCollectionPrompt.Collection_Name:éŠèæä»¶å€¹ïŒ
+#NewCollectionPrompt.Collection_Name_Tooltip:éŠèç­åïŒå
+éšäœ¿çšïŒ8äžªä»¥äžå­ç¬ŠïŒ
+NewCollectionPrompt.Error:æ°éŠèéè¯¯
+NewCollectionPrompt.Instructions:åå»ºäžäžªæ°éŠèïŒå¡«åä»¥äžåºåã
+NewCollectionPrompt.Metadata_Elements:æééåäž­çå
+çŽ ã
+NewCollectionPrompt.Metadata_Instructions1:éäž­å
+æ°æ®éåæèŸ¹çæ¡ïŒå å
+¥æšçéŠèã
+NewCollectionPrompt.Metadata_Instructions2:ïŒæ³šæïŒçšåæšå¯æ·»å æ°éŠèïŒ
+NewCollectionPrompt.Metadata_Title_Existing:éæ©å
+æ°æ®éå
+#NewCollectionPrompt.Name_Error:æšæªèœäžºè¿äžªéŠèèŸå
+¥åç§°ïŒæè
+æšéæ©çåç§°å·²ç»è¢«äœ¿çšãè¯·æŽæ­£ã
+NewCollectionPrompt.NewCollection:-- æ°éŠè --
+NewCollectionPrompt.Select_MDS:å¯çšçå
+æ°æ®éåïŒ
+NewCollectionPrompt.Title:åå»ºäžäžªæ°éŠèã
+NewCollectionPrompt.Title_Clash:æšäžºéŠèéæ©çåç§°å·²ç»è¢«äœ¿çšãæ¯åŠç»§ç»­ïŒ
+NewCollectionPrompt.Title_Error:å¿
+é¡»å¡«ååç§°åãè¯·æŽæ­£ã
+#***** New Folder OrFilePrompt *****
+NewFolderOrFilePrompt.Default_File_Name:dummy
+NewFolderOrFilePrompt.Default_Folder_Name:æ°å»ºæä»¶å€¹
+NewFolderOrFilePrompt.Destination_Name:ç®æ æä»¶å€¹
+NewFolderOrFilePrompt.File_Name:æä»¶å
+NewFolderOrFilePrompt.File_Name_Tooltip:äžºæ°æä»¶èŸå
+¥æä»¶å
+NewFolderOrFilePrompt.Folder_Name:æä»¶å€¹å
+NewFolderOrFilePrompt.Folder_Name_Tooltip:äžºæ°æä»¶å€¹èŸå
+¥åç§°
+NewFolderOrFilePrompt.Title_Folder:æ°å»ºæä»¶å€¹
+NewFolderOrFilePrompt.Title_File:æ°å»ºäžäžªdummyæä»¶
+#***********************
+#
+NoMetadataSetsSelected.Message:åŠæäœ ç°åšåå»ºéŠèïŒå°æ²¡æåå§çå
+æ°æ®éãé€éåšäœ çéŠèäž­æå
+¥æå¢å äžäžªéåïŒåŠåäœ äžèœæå
+¥æåé
+ä»»äœå
+æ°æ®ãæ¯åŠèŠç»§ç»­ïŒ
+NoMetadataSetsSelected.Title:æ²¡æéäž­ä»»äœå
+æ°æ®éã
+#**********************
+#
+#******* OldWGET *******
+NoPluginExpectedToProcessFile.Message:Greenstoneçæä»¶éœäžçšæ¥å€çæä»¶ "{0}". ç¡®è®€æä»¶æ¯åŠææ­£ç¡®çæ©å±åãåŠææ¯æ­£ç¡®çïŒäœ å¯ä»¥äœ¿çšæªç¥æä»¶æ¥å€çè¿äžªæä»¶ã
+NoPluginExpectedToProcessFile.Title:æ²¡ææä»¶çšæ¥å€çæä»¶ã
+#**********************
+#
+#******* OldWGET *******
+OldWGET.Message:è­ŠåïŒåœæ å°å
+å«ç¹åŸçæä»¶ïŒäŸåŠURLäž­çç©ºéŽä¿¡æ¯ååé³ç¬Šå·ïŒæ¶ïŒäœ å®è£
+çWGetçæ¬æäžäžªå·²ç¥çéè¯¯ã è¿äžæ¯äžäžªéŸä»¥è§£å³çé®é¢ïŒæšèå®è£
+WGet 1.9ææŽé«çæ¬ã
+OldWGET.Title:èçWGet
+#***********************
+#
+#***** OpenCollectionDialog *****
+OpenCollectionDialog.Available_Collections:å¯çšçéŠè
+OpenCollectionDialog.Browse:æµè§
+OpenCollectionDialog.Browse_Tooltipä»äœ çæä»¶ç©ºéŽäž­éæ©äžäžªéŠè
+OpenCollectionDialog.Collection:GreenstoneçéŠè(".col")
+OpenCollectionDialog.Description:éŠèæè¿°
+OpenCollectionDialog.Locked_Collection:å·²ç»äœ¿çšçGreenstoneéŠè
+OpenCollectionDialog.No_Description:è¯·éæ©äžäžªgreenstoneçéŠè(".col" file)æ¥çæè¿°ä¿¡æ¯
+OpenCollectionDialog.Normal_Collection:GreenstoneçéŠè
+OpenCollectionDialog.Open:æåŒ
+OpenCollectionDialog.Open_Tooltip:æéäž­çéŠèè£
+èœœå°åŸä¹ŠéŠçæ¥å£äž­
+OpenCollectionDialog.Title:æåŒGreenstoneéŠè
+#**********************
+#
+#***** Options Pane inside CreatePane *****
+OptionsPane.Cancelled: - åæ¶
+OptionsPane.LogHistory:åå²æ¥å¿
+OptionsPane.Successful: - æå
+OptionsPane.Unknown: - æªç¥
+OptionsPane.Unsuccessful: - äžæå
+#*******************
+#
+#***** Preferences *****
+Preferences:éŠéé¡¹
+Preferences.Connection:è¿æ¥
+Preferences.Connection_Tooltip:è®Ÿçœ®greenstoneçURLïŒé
+çœ®ä»£çè¿æ¥
+Preferences.Connection.GLIServer_URL:Greenstone gliserverçURL:
+Preferences.Connection.GLIServer_URL_Tooltip:Greenstone "gliserver" CGI scriptçURL
+Preferences.Connection.Library_Path:åŸä¹ŠéŠè·¯åŸïŒ
+Preferences.Connection.Library_Path_GS3:Greenstone Webè·¯åŸïŒ
+Preferences.Connection.Library_Path_Tooltip:Greenstone webæå¡åšURL
+Preferences.Connection.Library_Path_Tooltip_GS3:Greenstone webæå¡åšURL
+Preferences.Connection.ProgramCommand:é¢è§åœä»€ïŒ
+Preferences.Connection.ProgramCommand_Tooltip:èä¹Šé¢è§åŒå§åœä»€ã
+Preferences.Connection.Proxy_Host:ä»£çäž»æºïŒ
+Preferences.Connection.Proxy_Host_Tooltip:ä»£çæå¡åšå°å
+Preferences.Connection.Proxy_Port:ä»£çç«¯å£ïŒ
+Preferences.Connection.Proxy_Port_Tooltip:ä»£çæå¡åšç«¯å£å·
+Preferences.Connection.Servlet:Servlet:
+Preferences.Connection.Servlet_Tooltip:æ¥çç«ç¹çservlet
+Preferences.Connection.Servlet_Tooltip2:è¿äžªç«ç¹æ²¡ææå®çservlet
+Preferences.Connection.Site:ç«ç¹
+Preferences.Connection.Site_Tooltip:æšèŠå·¥äœçç«ç¹
+Preferences.Connection.Use_Proxy:æ¯åŠäœ¿çšä»£çè¿æ¥
+Preferences.General:åžžè§
+Preferences.General_Tooltip:è®Ÿå®åžžè§éŠéé¡¹
+Preferences.General.Email:çšæ·Email:
+Preferences.General.Email_Tooltip:èªåšäœ¿çšemailå°å
+Preferences.General.Font:å­äœïŒ
+Preferences.General.Font_Tooltip:GLIçé¢äœ¿çšçå­äœ
+Preferences.General.Interface_Language:çé¢è¯­èšïŒ
+Preferences.General.Interface_Language_Tooltip:éæ©è¯­èš
+Preferences.General.Restart_Required:éå¯GLIïŒå®æçé¢æŽæ°
+Preferences.General.Show_File_Size:æŸç€ºæä»¶å€§å°
+Preferences.General.Show_File_Size_Tooltip:åšworkspaceåæä»¶æ åæŸç€ºæä»¶å€§å°S
+Preferences.General.View_Extracted_Metadata:æ¥çæåçå
+æ°æ®
+Preferences.General.View_Extracted_Metadata_Tooltip:åšå
+æ°æ®è¡šéæŸç€ºgreenstoneæä»¶æåçå
+æ°æ®
+Preferences.Mode:æš¡åŒ
+Preferences.Mode_Tooltip:ç¹å»å
+¥å£éæ©åéçæäœçº§å«
+Preferences.Mode.Assistant:åŸä¹ŠéŠå©æ
+Preferences.Mode.Assistant_Description:äœ¿çšGreenstoneåŸä¹ŠéŠåçé¢çåºæ¬åèœïŒæ·»å æä»¶åå
+æ°æ®ïŒåå»ºå·²æèä¹ŠéåïŒåå»ºèä¹Šã
+Preferences.Mode.Librarian:åŸä¹ŠéŠå
+Preferences.Mode.Librarian_Description:GreenstoneåŸä¹ŠéŠåçé¢åžžçšåèœïŒåèä¹Šæ·»å ææ¡£åå
+æ°æ®ïŒè®Ÿè®¡æ°èä¹ŠïŒåå»ºæ°èä¹Š
+Preferences.Mode.Systems:åŸä¹ŠéŠç³»ç»äžå®¶
+Preferences.Mode.Systems_Description:GreenstoneåŸä¹ŠéŠåçé¢ææåèœTo take advantage of all the features available, you will need to be able to formulate regular expressions.
+Preferences.Mode.Expert:äžå®¶
+Preferences.Mode.Expert_Description:GreenstoneåŸä¹ŠéŠåçé¢äžå®¶çº§åèœïŒ It is recommended for users who are experienced with Greenstone, and are able to perform troubleshooting tasks that involve interpreting debugging output from PERL scripts. All features of the Greenstone Librarian Interface are enabled.
+Preferences.Warnings:è­Šå
+Preferences.Warnings_Tooltip:å¯çšæè
+åçšåç§è­Šåå¯¹è¯æ¡ã
+Preferences.Workflow:å·¥åº
+Preferences.Workflow_Tooltip:è®Ÿè®¡çé¢å·¥åº
+Preferences.Workflow.Create:åå»º - äœ¿çšGreenstoneåå»ºèä¹Š
+Preferences.Workflow.Design:è®Ÿè®¡ - æŽæ¹èä¹Šå€è§
+Preferences.Workflow.Download:äžèœœ - äžèœœçœç»èµæº
+Preferences.Workflow.Enrich:æ·»å  - æ³šéåå
+æ°æ®
+Preferences.Workflow.Gather:éå - äžºèä¹Šéæ©æä»¶
+Preferences.Workflow.Predefined.Label:é¢ç¡®å®çå·¥åºã
+Preferences.Workflow.Title:å¯çšæ¥ççå€éæ¡
+#**********************
+#
+#**** PreviewCommandDialog *******
+PreviewCommandDialog.Instructions:é®å
+¥æåŒé¢è§éåçåœä»€. 
+PreviewCommandDialog.Title:é¢è§åœä»€
+#**********************
+#
+#***** Remote Greenstone Server *****
+RemoteGreenstoneServer.Authentication_Message:è¯·èŸå
+¥äœ çGreenstoneçšæ·ååå¯ç :
+RemoteGreenstoneServer.Error:åœè¿è¡è¿äžªæäœäžäžªéè¯¯åçåšè¿çšGreenstoneæå¡åšäžé¢
+RemoteGreenstoneServer.Error_Title:è¿çšGreenstoneæå¡åšéè¯¯
+RemoteGreenstoneServer.Progress:è¿çšGreenstoneæå¡åšè¿çš: 
+RemoteGreenstoneServer.Steal_Lock_Message:è¿äžªéåè¢«çšæ· '{0-User name}'éå®.
+#**********************
+#
+#***** Save Collection Box *****
+SaveCollectionBox.File_Name:æä»¶å:
+SaveCollectionBox.Files_Of_Type:æä»¶ç±»å:
+SaveCollectionBox.Look_In:Look In:
+#**********************
+#
+#***** Save Progress Box *******
+SaveProgressDialog.Title:ä¿å­éå
+#*******************************
+#
+Server.QuitManual:çé¢æ æ³èªåšå
+³é­æå¡
+Server.QuitTimeOut: greenstone æ¬å°åºäžåéå
+æ²¡æååº.äœ æ¿æåç­äžåéå?
+#
+#***** Sources *****
+Source.General:æŠèŠ
+#*******************
+#
+#***** TitleClash *****
+TitleClashes.Message:äœ äžºéåéæ©çäž»é¢å·²ç»åšäœ¿çšäž­.ç»§ç»­?
+TitleClashes.Title:é®å
+¥å²çªäž»é¢
+#**********************
+#
+#***** Trees *****
+Tree.DownloadedFiles:äžèœœæä»¶
+Tree.Files:æä»¶
+Tree.Home:äž»ç®åœ ({0})
+Tree.Root:æ¬å°æä»¶ç©ºéŽ
+Tree.World:Greenstoneéåææ¡£
+#***********************
+#
+#***** Warning Dialog *****
+WarningDialog.Dont_Show_Again:äœ æ³åæ¬¡æŸç€ºè¿äžªè­Šåå? 
+WarningDialog.Dont_Show_Again_Message:äžèŠæŸç€ºè¿äžªæ¶æ¯
+WarningDialog.Invalid_Value:äœ é®å
+¥çåŒæ æ.
+WarningDialog.Value:é®å
+¥åŒ:
+#
+#****** WGet *****
+WGet.Prompt:WGet éåå®¢æ·ç«¯
+#
+#****** Workflows *****
+Workflow.AllPanels:ææé¢æ¿
+Workflow.LocalSourceCollectionBuilding:æ¬å°æºéååå»º
+Workflow.DocumentEnriching:ææ¡£äž°å¯å
+
+GEMS.Already_Loaded_Set_Error: åœåäœ éæ©çå
+æ°æ®éæ¯æåŒç
+GEMS.Element_Already_Exists:äžäžªå
+·ææ­€åç§°çå
+çŽ å·²ç»å­åš
+GEMS.Set_Already_Exists:äžäžªå
+·ææ­€åœåç©ºéŽçéåå·²ç»å­åš
+GEMS.Cannot_Delete_Core_Sets_Error:äœ äžèœå é€äžäžªæ žå¿GLIå
+æ°æ®é
+
+GEMS.Preferences.Selected_Languages_Tooltip: éäž­çæŸç€ºè¯­èš:
+
+GEMS.Add_Attribute:å¢å å±æ§
+GEMS.Add_Attribute_Tooltip:å¢å äžäžªæ°çå±æ§å°éäž­çé¡¹ç®äž­
+GEMS.Add_Element:å¢å å
+çŽ 
+GEMS.Add_Element_Tooltip:å¢å äžäžªæ°çå
+çŽ å°éäž­çéåäž­
+GEMS.Add_Subelement:å¢å å­å
+çŽ 
+GEMS.Add_Subelement_Tooltip:å¢å äžäžªæ°çå­å
+çŽ å°éäž­çå
+çŽ äž­
+GEMS.Add_Set:å¢å éå
+GEMS.Attribute:å±æ§
+GEMS.Attribute_Already_Exists:æ­€å±æ§å·²ç»å­åš
+GEMS.Attribute_Name_Tooltip:æ°å±æ§çåç§°
+GEMS.Attribute_Language_Tooltip:æ°å±æ§çè¯­èš
+GEMS.Attribute_Value_Tooltip:æ°å±æ§çåŒ
+GEMS.Attributes:å±æ§
+GEMS.Cannot_Undo:(è¯¥è¡äžºäžèœæ€é)
+GEMS.Cannot_Add_Elements_To_Greenstone_MDS:äœ äžèœæå·¥åGreenStoneå
+æ°æ®æ·»å å
+çŽ . åŠæéèŠåå»ºäžäžªæ°çéåïŒé£ä¹å°äœ çæ°å
+çŽ æ·»å è¿å»
+GEMS.Confirm_Exit_Save: éåºä¹åäœ æ³ä¿å­å?
+GEMS.Confirm_Exit_Save_Title: éåºä¹åä¿å­?
+GEMS.Confirm_Removal:äœ ç¡®å®äœ æ³å é€è¿äžª{0}?
+GEMS.Confirm_Removal_Title:ç¡®è®€å é€
+GEMS.Edit_Attribute:çŒèŸå±æ§
+GEMS.Edit_Value:çŒèŸåŒ
+GEMS.Edit_Value_Tooltip:æ¹åéäž­çåŒ
+GEMS.Element:å
+çŽ 
+GEMS.Element_Name_Tooltip:æ°å
+çŽ çåç§°
+GEMS.Element_Details:å
+æ°æ®å
+çŽ è¯Šæ
+
+GEMS.Language:è¯­èš
+GEMS.Language_Code:è¯­èš
+GEMS.Name:åç§°
+GEMS.Namespace:åœåç©ºéŽ
+GEMS.New_Name:æ°åç§°
+GEMS.No_Description:æªåç°æè¿°ä¿¡æ¯.
+GEMS.No_Name:æªåç°åç§°.
+GEMS.Open_Set:æåŒçéå
+GEMS.Remove_Attribute:å é€å±æ§
+GEMS.Remove_Attribute_Tooltip:å é€éäž­çå±æ§
+GEMS.Remove_Element:å é€å
+çŽ 
+GEMS.Remove_Element_Tooltip:ä»éåäž­å é€éäž­çå
+çŽ 
+GEMS.Remove_Set:å é€éå
+GEMS.Remove_Set_Tooltip:å é€éäž­çéå
+GEMS.Rename_Element:éåœåå
+çŽ 
+GEMS.Rename_Element_Tooltip:å
+çŽ çæ°åç§°
+GEMS.Rename_Name_Tooltip:å
+æ°æ®éçæ°åç§°
+GEMS.Rename_Namespace_Tooltip:å
+æ°æ®éå¯äžçåœåç©ºéŽ
+GEMS.Rename_Set:éåœåéå
+GEMS.Rename_Set_Tooltip:éåœåå
+æ°æ®é
+GEMS.Set:éå
+GEMS.Set_Details:Metadata Set éåè¯Šæ
+
+GEMS.Set_Name_Tooltip:æ°çå
+æ°æ®éåç§°
+GEMS.Set_Namespace_Tooltip:æ°å
+æ°æ®éçäžäžªå¯äžçåœåç©ºéŽ
+GEMS.Subelement_Name_Tooltip:æ°å­å
+çŽ çåç§°
+GEMS.Subelement_Already_Exists:äžäžªå
+·ææ­€åç§°çå­å
+çŽ å·²ç»å­åš
+GEMS.Target:å
+çŽ 
+GEMS.Title:å
+æ°æ®éçGreenstone çŒèŸåš 
+GEMS.Value:åŒ
+GEMS.Values:åŒ
+GEMS.inheritMetadataSet:ä»å
+æ°æ®éç»§æ¿:
+GEMS.Add_Set.No_Inherit:äžç»§æ¿
Index: /tags/greenstone-3_02-distribution/gli/classes/feedback.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gli/classes/feedback.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/classes/feedback.properties	(revision 13928)
@@ -0,0 +1,264 @@
+TextComponent=Text Component
+true=True
+false=False
+Button=Button
+icon=icon
+NoImage=No Image
+ProgressBar=Progress Bar
+Slider=Slider
+Spinner=Spinner
+Label=Label
+ComboBox=Combo Box
+Selected=Selected
+NotSelected=Not Selected
+ToggleButton=Toggle Button
+MenuItem=Menu Item
+MenuBar=Menu Bar
+Window=Window
+Panel=Panel
+Scroller=Scroller
+OptionPane=Option Pane
+ViewPort=View Port
+Box=Box
+Splitters=Splitters
+List=List
+ColorChooser=Color Chooser
+PreviewPanel=Preview Panel
+ChooserPanels=Chooser Panels
+DesktopPane=Desktop Pane
+black=BLACK
+BLACK=BLACK
+blue=BLUE
+BLUE=BLUE
+cyan=CYAN
+CYAN=cyan
+gray=GRAY
+GRAY=GRAY
+green=GREEN
+GREEN=GREEN
+DARK_GRAY=DARK_GRAY
+darkGray=DARK_GRAY
+LIGHT_GRAY=LIGHT_GRAY
+lightGray=LIGHT_GRAY
+magenta=MAGENTA
+MAGENTA=MAGENTA
+orange=ORANGE
+ORANGE=ORANGE
+pink=PINK
+PINK=PINK
+red=RED
+RED=RED
+white=WHITE
+WHITE=WHITE
+YELLOW=YELLOW
+Table=Table
+row=Row
+ScrollerBar=Scroller Bar
+Tree=Tree
+Container=Container
+RootPane=Root Pane
+LayeredPane=Layered Pane
+InternalFrameTitlePane=Internal Frame Title Pane
+TableHeader=Table Header
+ToolBar=Tool Bar
+Conformation=Conformation
+ConformationText=Thank you for using this Send Feedback feature.\n\nDo you want to preview the report details you are about to send to us?\n
+Preview=Preview
+ConformationPreview=View information you about to send.
+Send=Send
+ConformationSend=Send all information inputted.
+Don'tSend=Don't Send
+NotSend=Not Send
+ConformationNotSend=Do not send all information inputted.
+content=content
+command=command
+feedback=feedback
+SendFeedback=Send Feedback
+SendFeedbackButton=Open Send feedback form
+SendFeedbackForm=Send Feedback Form
+FeedbackOpeningText=Feedback\n\nSending this report indicate that you have found the applications you were doing have some problems.You do not have to fill out the form -- any information will help.\n\nDescriptions:
+Whatkindofproblemisit=What kind of problem is it
+ContentError=Content Error
+ImageNotShow=Image Not Show
+StrangeBehaviour=Strange Behaviour
+SomethingUnexpectedHappen=Something Unexpected Happen
+HardToUse=Hard To Use
+Other=Other
+Howbadistheproblem=How bad is the problem
+Critical=Critical
+Serious=Serious
+Medium=Medium
+Minor=Minor
+Trivial=Trivial
+Doyouwanttosendthescreenshot=Do you want to send the screen shot
+Yes=Yes
+No=No
+FeedbackSendButton=Send all information inputted
+FeedbackNotSendButton=Do not send all information inputted
+FeedbackHelpText=How to report feedback\n\nYou do not have to fill in any of the form -- any information will help.\n\nClicking on thumbnail will allow you to draw scribble lines marking the problem and type more comments about it.\nIf you finish scribbling then you can click Finish Scribble which will take you back to Feedback form, or Send button which will send all the information you gave so far.\n\nYou can type your comment inside the comments text area.\n\nIf you go to any opened window and select screen shot then it will add the screen shot's thumbnail to problem details area.\n\nDetails... button will allow you to preview the xml files that are going to be send.\nSend button will send all the information away.
+FeedbackAboutText=About\n\nMany open source projects are under-utilised because normal users find the software they produce hard to use. The Send feedback button is an attempt by members of the Greenstone project to involve the users of Greenstone in making the software easier to use.\n\nEvery time you click a button in GLI, some information is collected about what you were doing in GLI at the time. This information can hopefully help the people working on the Greenstone project to figure out what caused the problems you had, and how to fix it.
+FeedbackPrivacyText=Privacy\n\nYour privacy is important to us. We assure you that we will take no information that can lead to your personal identification. Any information you provide will be used strictly for the research and for determining how to make Greenstone more usable, no other uses of the data will be allowed.\n\nNo information about anything other than GLI and the technology you use to view it (for example your screen size) will be taken.\n\nThe information we you provide will have a timestamp on it, and may be correlated with your activity within Greenstone around the time you made your complaint.
+Form=Form
+About=About
+Privacy=Privacy
+screen=screen
+ErrorLineAnd=ErrorLineAnd
+ErrorLineFor=ErrorLineFor
+Don'twanttosendscreenshot=Don't want to send the screenshot
+SendFeedback=Send Feedback
+CurrentlyOpenWindow=CurrentlyOpenWindow
+WindowActivated=Window Activated
+WindowOpened=Window Opened
+WindowClosed=Window Closed
+WindowDeactivated=Window Deactivated
+ChangeState=Change State
+Node=Node
+ValueChanged=ValueChanged
+Change=Change
+Inserted=Inserted
+Removed=Removed
+TreeStructuredChanged=Tree Structure Changed
+ItemStateChanged=Item State Changed
+ListChanged=List Changed
+ListContentsAdded=List Contents Added
+ListContentRemoved=List Content Removed
+ListValueChanged=List Value Changed
+MenuCanceled=Menu Canceled
+MenuDeselected=Menu Deselected
+MenuSelected=Menu Selected
+ColumnIndex=Column Index
+AddedToTable=Added to table
+ColumnIndexFrom=From column index
+MoveToColumnIndex=move to column index
+InTheTable=in the table
+RemovedFromTheTable= removed from the table
+ViewReport=View Report
+ViewFeedbackForm=View Feedback Form
+ViewHistoryState=View History State
+ViewCommandState=View Commands
+Close=Close
+ClosePreview=Close the preview window
+HISTORY=HISTORY
+BUGS=BUGS
+IDCode=IDCode
+LastViewedWindow=LastViewedWindow
+Optionals=Optionals
+Details=Details
+Type=Type
+Urgency=Urgency
+User=User
+Name=Name
+HomeDirectory=HomeDirectory
+WorkingDirectory=WorkingDirectory
+OpenFormTime=OpenFormTime
+SendFormTime=SendFormTime
+OperatingSystem=OperatingSystem
+JavaInformation=JavaInformation
+DefaultLocale=DefaultLocale
+Browser=Greenstone
+LocalHostName=LocalHostName
+LocalHostAddress=LocalHostAddress
+ScreenResolution=ScreenResolution
+ScreenShot=ScreenShot
+ErrorLineAndScreenShot=ErrorLineAndScreenShot
+ErrorLineForScreenShot=ErrorLineForScreenShot
+COMPONENT=COMPONENT
+Type=Type
+Title=Title
+Content=Content
+Visible=Visible
+Image=Image
+Date=Date
+Command=Command
+COMPONENTS=COMPONENTS
+LOG=LOG
+View=View
+Showwhereistheproblem=Show where is the problem
+ScreenShotLabel=Use the mouse to indicate where the problem occured. Click send once you finished.
+Rectangle=Rectangle
+RectangleToolTip=Tool to draw rectangle
+Arrow=Arrow
+ArrowToolTip=Tool to draw arrow line
+SendTheImage=Sending the image
+SMTPaddress=What is your SMTP address
+Emailaddress=What is your e-mail address
+SendAttachment=Hereby attached 2 jar files.Please download them at the same place and parser.jar is an executable jar file.\nPlease keep referencing to this ID Code\nID Code:
+Email=Email
+SMTP=SMTP
+HISTORYCOMMANDS=COMMANDS
+TotalMemory=TotalMemory
+MaxMemory=MaxMemory
+FreeMemory=FreeMemory
+ViewFileTitle=Viewing the XML file
+ViewFeedbackFile=View FeedbackInterface form file
+ViewFeedbackCommandFile=View feedback command's history file
+ViewFeedbackContentFile=View feedback's history file
+ViewContentFile=View History file
+ViewCommandFile=View Command's history file
+ParsingXMLText=Select the checkbox of the file you want to see
+View=View
+ViewToolTip=View the files selected from the check box
+CloseToolTip=Close this application
+ViewCode=Please enter the id code as written in your email
+COMMANDS=COMMANDS
+Pleasewait=Please wait this may take a while
+Java=Java
+InternalError=Sorry. There was an internal error while sending your message!Please make sure you connected to the internet.
+SendFailed=Send Failed.Please make sure you connected to the internet.Do you want to try again?
+Error=Error
+NotFoundProvider=Provider not Found!\n\nPlease enter your SMTP adress again
+NotFoundProvider2=Please enter the email address for that SMTP address.
+Emaillater=We will try to send this feedback documents next time you send another feedback document.
+ScreenShotDescription=ScreenShotDescription
+ProblemDetails=Problem Details :
+Size=Size
+Height=Height
+Width=Width
+Icon=Icon
+Viewfeedback=View Feedback
+Viewcontent=View Content
+Viewcommand=View Command
+Separator=Separator
+NoComponent=No Component (it's a null object)
+TitlePane=Metal Title Pane (Platform dependent)
+ToolTipText=ToolTipText
+Feedback=Feedback
+LookHistory=View History
+LookHistoryButton=View History of all the commands you've done
+RecreateEvent=Recreate the Event
+RecreateOpeningText=You can add your comments in the text area.Click the Screen Shot button to take the screenshot of this window.Click Send button once you finished recreating the event.
+SendRecreate=Send Recreate
+SaveRecreate=Save Recreate
+RecreateSaveButton=Save all the comments entered.
+Comment=Comment
+RecreateOption=Can you recreate the event that you want to report?
+RecreateTitle=Recreate Event
+Save=Save
+RecordReady=If you are ready to recreate the event click start.
+Start=Start
+StartRecreate=Start Recreate Event
+StartRecText=Start recording all the action you did.
+ViewFeedbackHistoryState=View Feedback History
+ViewFeedbackCommandState=View Feedback Command
+DLGmessage=We start recording every action you do now.
+Ok=Ok
+SnapShot=Screen Shot
+SnapShotText=SnapShotText
+SnapShotButton=Take screen shot of the window you are in now.
+ViewMovie=View Picture
+ViewMovieText=View all the sequence of action
+FramesPerSecond=Frames Per Second
+GenerateMovie=Frames sequences
+image=Image
+notfound=Not Found
+COMMENTS=COMMENTS
+Viewcomment=View comment
+ViewCommentFile=View Comment File
+SnapShotAppend=Screen Shot taken
+Start=Start
+Finish=Finish
+Sequences=Sequences
+Sequence=Sequence
+ImageDescription=ImageDescription
+
+
Index: /tags/greenstone-3_02-distribution/gli/classes/xml/CollectionConfig.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gli/classes/xml/CollectionConfig.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/classes/xml/CollectionConfig.xml	(revision 13928)
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<CollectionConfig>
+</CollectionConfig>
Index: /tags/greenstone-3_02-distribution/gli/classes/xml/collect_cfg.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gli/classes/xml/collect_cfg.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/classes/xml/collect_cfg.xml	(revision 13928)
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE Configuration [
+  <!ELEMENT Configuration (Gatherer)>
+  <!ELEMENT Gatherer      (Workflow)>
+  <!ELEMENT Workflow      (Browse, Mirror, Import, Gather, Enrich, Design, Export, Preview)>
+  <!ELEMENT Browse        (#PCDATA)>
+  <!ELEMENT Mirror        (#PCDATA)>  
+  <!ELEMENT Gather        (#PCDATA)>
+  <!ELEMENT Enrich        (#PCDATA)>
+  <!ELEMENT Design        (#PCDATA)>
+  <!ELEMENT Export        (#PCDATA)>
+  <!ELEMENT Preview       (#PCDATA)>
+]>
+
+<Configuration>
+  <Gatherer>
+    <Workflow>
+	   <Browse  enabled="true"/>
+		<Mirror  enabled="true"/>
+		<Import  enabled="true"/>
+		<Gather  enabled="true"/>
+		<Enrich  enabled="true"/>
+		<Design  enabled="true"/>
+		<Export  enabled="true"/>
+		<Preview enabled="true"/>
+	 </Workflow>
+  </Gatherer>
+</Configuration>
+
+
Index: /tags/greenstone-3_02-distribution/gli/classes/xml/config.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gli/classes/xml/config.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/classes/xml/config.xml	(revision 13928)
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE Configuration [
+  <!ELEMENT Configuration  (GathererConfig, Other, DirectoryMappings, Associations)>
+  <!ELEMENT GathererConfig (Argument*)>
+  <!ELEMENT Argument       (#PCDATA)>
+  <!ATTLIST Argument
+            name           CDATA #REQUIRED>
+  <!ELEMENT Other          (Info*)>
+  <!ELEMENT Info           (Name, Desc, Arguments)>
+  <!ELEMENT Arguments      (Option*)>
+  <!ELEMENT Option         (Name, Desc, Type, Required, Default?, List?)>
+  <!ELEMENT Type           (#PCDATA)>
+  <!ELEMENT Required       (#PCDATA)>
+  <!ELEMENT Default        (#PCDATA)>
+  <!ELEMENT List           (Value*)>
+  <!ELEMENT Value          (Name, Desc?)>
+  <!ELEMENT Name           (#PCDATA)>
+  <!ELEMENT Desc           (#PCDATA)>
+  <!ELEMENT DirectoryMappings (Mapping*)>
+  <!ELEMENT Mapping           (#PCDATA)>
+  <!ATTLIST Mapping 
+            name              CDATA #REQUIRED
+	    file              CDATA #REQUIRED>
+  <!ELEMENT Associations (Entry*)>
+  <!ELEMENT Entry (#PCDATA)>
+  <!ATTLIST Entry
+            extension CDATA #REQUIRED>
+]>
+
+<Configuration version="2.72">
+  <GathererConfig>
+    <!-- ***** General Options: apply globally to the GLI execution. ***** -->
+    <!-- The location and size of the main Gatherer window. -->
+    <Argument name="general.bounds">0, 0, 800, 600</Argument>
+    <!-- Are we expected to produce a debug file. Can be overidden at start up. default = [false] -->
+    <Argument name="general.debug">false</Argument>
+    <Argument name="general.email"/>
+    <!-- The standard font used in the Gatherer. [Verdana, BOLD, 12] -->
+    <Argument name="general.font">Verdana, BOLD, 12</Argument>
+    <Argument name="general.library_url"/>
+    <Argument name="general.locale">en_NZ</Argument>
+    <!-- How many folders deep should we recurse before suspecting a cyclic path? [40] -->
+    <Argument name="general.max_folder_depth">40</Argument>
+    <!-- The mode controls what level a detail is presented to the user - ranging from a basic, no regex, no perl experience up to complete details for all processes. The values, ranging from lowest to highest detail, are: 1 = Assistant, 2 = Librarian, 3 = Systems, 4 = Expert [default 2]-->
+    <Argument name="general.mode">2</Argument>
+    <Argument name="general.open_collection"></Argument>
+    <!-- The application launching command used when previewing the collection. [default -blank-] -->
+    <Argument name="general.preview_program"></Argument>
+    <Argument name="general.proxy_host"></Argument>
+    <Argument name="general.proxy_port">80</Argument>
+    <Argument name="general.show_file_size">false</Argument>
+    <!-- Do we expect to connect to the internet via a proxy server. [false] -->
+    <Argument name="general.use_proxy">false</Argument>
+    <Argument name="general.view_extracted_metadata">true</Argument>
+
+    <!-- Colouring -->
+    <Argument name="coloring.button_background">218, 237, 252</Argument>
+    <Argument name="coloring.button_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.button_selected_background">128, 180, 216</Argument>
+    <Argument name="coloring.button_selected_foreground">255, 255, 255</Argument>
+    <Argument name="coloring.collection_heading_background">176, 208, 176</Argument>  
+    <Argument name="coloring.collection_heading_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.collection_selection_background">128, 180, 216</Argument>
+    <Argument name="coloring.collection_selection_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.collection_tree_background">224, 240, 224</Argument>
+    <Argument name="coloring.collection_tree_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.collection_noneditable_background">192, 192, 192</Argument>
+    <Argument name="coloring.collection_noneditable_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.disabled">206, 206, 206</Argument>
+    <Argument name="coloring.editable_background">255, 255, 255</Argument>
+    <Argument name="coloring.editable_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.error_background">255, 0, 0</Argument>
+    <Argument name="coloring.error_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.scrollbar_background">192, 192, 192</Argument>
+    <Argument name="coloring.scrollbar_foreground">255, 255, 255</Argument>
+    <Argument name="coloring.workspace_heading_background">128, 180, 216</Argument>
+    <Argument name="coloring.workspace_heading_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.workspace_selection_background">176, 208, 176</Argument>
+    <Argument name="coloring.workspace_selection_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.workspace_tree_background">218, 237, 252</Argument>
+    <Argument name="coloring.workspace_tree_foreground">0, 0, 0</Argument>
+
+    <!-- Mirroring -->
+    <!-- Mirroring has many particular options. These show the default settings. -->
+    <Argument name="mirroring.depth">0</Argument>
+    <Argument name="mirroring.no_parents">true</Argument>
+    <Argument name="mirroring.other_hosts">false</Argument>
+    <Argument name="mirroring.overwrite">false</Argument>
+    <Argument name="mirroring.page_requisites">true</Argument>
+    <Argument name="mirroring.quiet">true</Argument>
+    <Argument name="mirroring.remove_failed">false</Argument>
+
+    <!-- Warnings -->
+    <!-- Warnings can be disabled by the user. -->
+    <Argument name="warning.CollectionBuilt">true</Argument>
+    <Argument name="warning.DirectoryLevelMetadata">true</Argument>
+    <Argument name="warning.ExtractedMetadata">true</Argument>
+    <Argument name="warning.MissingEXEC">true</Argument>
+    <Argument name="warning.MissingEXEC_GS3">true</Argument>
+    <Argument name="warning.MissingGSDL">true</Argument>
+    <Argument name="warning.MissingImageMagick">true</Argument>
+    <Argument name="warning.MissingPERL">true</Argument>
+    <Argument name="warning.NoPluginExpectedToProcessFile">true</Argument>
+    <Argument name="warning.LegacyCollection">true</Argument>
+    <Argument name="warning.MetadataSetNamespaceClash">true</Argument>
+    <Argument name="warning.ShowPreviousCollection">true</Argument>  
+
+    <!-- Workflow -->
+    <!-- Disabling a view here will cause it to be hidden from the Gatherer display. -->
+    <Argument name="workflow.download">true</Argument>
+    <Argument name="workflow.gather">true</Argument>
+    <Argument name="workflow.enrich">true</Argument>
+    <Argument name="workflow.design">true</Argument>
+    <Argument name="workflow.create">true</Argument>
+    <Argument name="workflow.format">true</Argument>
+
+    <Argument name="GEMS.Preferences.Selected_Languages">en</Argument>
+  </GathererConfig>
+
+  <Other/>
+  <DirectoryMappings/>
+  <Associations>
+    <Entry extension="doc"/>
+    <Entry extension="gif"/>
+    <Entry extension="htm"/>
+    <Entry extension="html"/>
+    <Entry extension="jpg"/>
+    <Entry extension="jpeg"/>
+    <Entry extension="pdf"/>
+    <Entry extension="png"/>
+    <Entry extension="ps"/>
+    <Entry extension="rtf"/>
+    <Entry extension="txt"/>
+    <Entry extension="text"/>
+  </Associations>
+</Configuration>
Index: /tags/greenstone-3_02-distribution/gli/classes/xml/configRemote.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gli/classes/xml/configRemote.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/classes/xml/configRemote.xml	(revision 13928)
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE Configuration [
+  <!ELEMENT Configuration  (GathererConfig, Other, DirectoryMappings, Associations)>
+  <!ELEMENT GathererConfig (Argument*)>
+  <!ELEMENT Argument       (#PCDATA)>
+  <!ATTLIST Argument
+            name           CDATA #REQUIRED>
+  <!ELEMENT Other          (Info*)>
+  <!ELEMENT Info           (Name, Desc, Arguments)>
+  <!ELEMENT Arguments      (Option*)>
+  <!ELEMENT Option         (Name, Desc, Type, Required, Default?, List?)>
+  <!ELEMENT Type           (#PCDATA)>
+  <!ELEMENT Required       (#PCDATA)>
+  <!ELEMENT Default        (#PCDATA)>
+  <!ELEMENT List           (Value*)>
+  <!ELEMENT Value          (Name, Desc?)>
+  <!ELEMENT Name           (#PCDATA)>
+  <!ELEMENT Desc           (#PCDATA)>
+  <!ELEMENT DirectoryMappings (Mapping*)>
+  <!ELEMENT Mapping           (#PCDATA)>
+  <!ATTLIST Mapping 
+            name              CDATA #REQUIRED
+	    file              CDATA #REQUIRED>
+  <!ELEMENT Associations (Entry*)>
+  <!ELEMENT Entry (#PCDATA)>
+  <!ATTLIST Entry
+            extension CDATA #REQUIRED>
+]>
+
+<Configuration version="2.72">
+  <GathererConfig>
+    <!-- ***** General Options: apply globally to the GLI execution. ***** -->
+    <!-- The location and size of the main Gatherer window. -->
+    <Argument name="general.bounds">0, 0, 800, 600</Argument>
+    <!-- Are we expected to produce a debug file. Can be overidden at start up. default = [false] -->
+    <Argument name="general.debug">false</Argument>
+    <!-- The standard font used in the Gatherer. [Verdana, BOLD, 12] -->
+    <Argument name="general.font">Verdana, BOLD, 12</Argument>
+    <Argument name="general.gliserver_url"/>
+    <Argument name="general.library_url"/>
+    <Argument name="general.locale">en_NZ</Argument>
+    <!-- How many folders deep should we recurse before suspecting a cyclic path? [40] -->
+    <Argument name="general.max_folder_depth">40</Argument>
+    <!-- The mode controls what level a detail is presented to the user - ranging from a basic, no regex, no perl experience up to complete details for all processes. The values, ranging from lowest to highest detail, are: 1 = Assistant, 2 = Librarian, 3 = Systems, 4 = Expert [default 2]-->
+    <Argument name="general.mode">2</Argument>
+    <Argument name="general.open_collection"></Argument>
+    <!-- The application launching command used when previewing the collection. [default -blank-] -->
+    <Argument name="general.preview_program"></Argument>
+    <Argument name="general.proxy_host"></Argument>
+    <Argument name="general.proxy_port">80</Argument>
+    <Argument name="general.show_file_size">false</Argument>
+    <!-- Do we expect to connect to the internet via a proxy server. [false] -->
+    <Argument name="general.use_proxy">false</Argument>
+    <Argument name="general.view_extracted_metadata">true</Argument>
+
+    <!-- Colouring -->
+    <Argument name="coloring.button_background">218, 237, 252</Argument>
+    <Argument name="coloring.button_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.button_selected_background">128, 180, 216</Argument>
+    <Argument name="coloring.button_selected_foreground">255, 255, 255</Argument>
+    <Argument name="coloring.collection_heading_background">176, 208, 176</Argument>  
+    <Argument name="coloring.collection_heading_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.collection_selection_background">128, 180, 216</Argument>
+    <Argument name="coloring.collection_selection_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.collection_tree_background">224, 240, 224</Argument>
+    <Argument name="coloring.collection_tree_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.collection_noneditable_background">192, 192, 192</Argument>
+    <Argument name="coloring.collection_noneditable_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.disabled">206, 206, 206</Argument>
+    <Argument name="coloring.editable_background">255, 255, 255</Argument>
+    <Argument name="coloring.editable_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.error_background">255, 0, 0</Argument>
+    <Argument name="coloring.error_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.scrollbar_background">192, 192, 192</Argument>
+    <Argument name="coloring.scrollbar_foreground">255, 255, 255</Argument>
+    <Argument name="coloring.workspace_heading_background">128, 180, 216</Argument>
+    <Argument name="coloring.workspace_heading_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.workspace_selection_background">176, 208, 176</Argument>
+    <Argument name="coloring.workspace_selection_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.workspace_tree_background">218, 237, 252</Argument>
+    <Argument name="coloring.workspace_tree_foreground">0, 0, 0</Argument>
+
+    <!-- Mirroring -->
+    <!-- Mirroring has many particular options. These show the default settings. -->
+    <Argument name="mirroring.depth">0</Argument>
+    <Argument name="mirroring.no_parents">true</Argument>
+    <Argument name="mirroring.other_hosts">false</Argument>
+    <Argument name="mirroring.overwrite">false</Argument>
+    <Argument name="mirroring.page_requisites">true</Argument>
+    <Argument name="mirroring.quiet">true</Argument>
+    <Argument name="mirroring.remove_failed">false</Argument>
+
+    <!-- Warnings -->
+    <!-- Warnings can be disabled by the user. -->
+    <Argument name="warning.CollectionBuilt">true</Argument>
+    <Argument name="warning.DirectoryLevelMetadata">true</Argument>
+    <Argument name="warning.ExtractedMetadata">true</Argument>
+    <Argument name="warning.InheritedMetadata">true</Argument>
+    <Argument name="warning.MissingEXEC">true</Argument>
+    <Argument name="warning.MissingGSDL">true</Argument>
+    <Argument name="warning.MissingGLIServer">true</Argument>
+    <Argument name="warning.MissingImageMagick">true</Argument>
+    <Argument name="warning.MissingPERL">true</Argument>
+    <Argument name="warning.NoMetadataSetsSelected">true</Argument>
+    <Argument name="warning.NoPluginExpectedToProcessFile">true</Argument>
+
+    <!-- Workflow -->
+    <!-- Disabling a view here will cause it to be hidden from the Gatherer display. -->
+    <Argument name="workflow.download">false</Argument>
+    <Argument name="workflow.gather">true</Argument>
+    <Argument name="workflow.enrich">true</Argument>
+    <Argument name="workflow.design">true</Argument>
+    <Argument name="workflow.create">true</Argument>
+    <Argument name="workflow.format">true</Argument>
+  </GathererConfig>
+
+  <Other/>
+  <DirectoryMappings/>
+  <Associations>
+    <Entry extension="doc"/>
+    <Entry extension="gif"/>
+    <Entry extension="htm"/>
+    <Entry extension="html"/>
+    <Entry extension="jpg"/>
+    <Entry extension="jpeg"/>
+    <Entry extension="pdf"/>
+    <Entry extension="png"/>
+    <Entry extension="ps"/>
+    <Entry extension="rtf"/>
+    <Entry extension="txt"/>
+    <Entry extension="text"/>
+  </Associations>
+</Configuration>
Index: /tags/greenstone-3_02-distribution/gli/classes/xml/gli.lck
===================================================================
--- /tags/greenstone-3_02-distribution/gli/classes/xml/gli.lck	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/classes/xml/gli.lck	(revision 13928)
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="ASCII" ?>
+
+<LockFile>
+  <User></User>
+  <Machine></Machine>
+  <Date></Date>
+</LockFile>
Index: /tags/greenstone-3_02-distribution/gli/classes/xml/languages.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gli/classes/xml/languages.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/classes/xml/languages.xml	(revision 13928)
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE Languages [
+   <!ELEMENT Languages     (Language*)>
+   <!ELEMENT Language      (#PCDATA)>
+   <!-- name: The name of the language -->
+   <!-- code: The two letter language code -->
+   <!-- gs:   Does greenstone include support for this language? -->
+   <!-- gli:  Does gli have a dictionary for this language? -->
+   <!-- mds:  Does any metadata set include support for this language? -->
+   <!ATTLIST Language
+             name          CDATA #REQUIRED
+	     code          CDATA #REQUIRED
+	     gs            CDATA "false"
+	     gli           CDATA "false"
+	     mds           CDATA "false">
+]>
+
+<Languages>
+   <Language name="ABKHAZIAN"           code="AB">IBERO-CAUCASIAN</Language>
+   <Language name="AFAN(OROMO)"         code="OM">HAMITIC</Language>
+   <Language name="AFAR"                code="AA">HAMITIC</Language>
+   <Language name="AFRIKAANS"           code="AF">GERMANIC</Language>
+   <Language name="ALBANIAN"            code="SQ">INDO-EUROPEAN (OTHER)</Language>
+   <Language name="AMHARIC"             code="AM">SEMITIC</Language>
+   <Language name="ARABIC"              code="AR" gli="true" gs="true" mds="true">SEMITIC</Language>
+   <Language name="ARMENIAN"            code="HY" gs="true">INDO-EUROPEAN (OTHER)</Language>
+   <Language name="ASSAMESE"            code="AS">INDIAN</Language>
+   <Language name="AYMARA"              code="AY">AMERINDIAN</Language>
+   <Language name="AZERBAIJANI"         code="AZ">TURKIC/ALTAIC</Language>
+   <Language name="BASHKIR"             code="BA">TURKIC/ALTAIC</Language>
+   <Language name="BASQUE"              code="EU">BASQUE</Language>
+   <Language name="BENGALI(BANGLA)"     code="BN">INDIAN</Language>
+   <Language name="BHUTANI"             code="DZ">ASIAN</Language>
+   <Language name="BIHARI"              code="BH">INDIAN</Language>
+   <Language name="BISLAMA"             code="BI">[not given]</Language>
+   <Language name="BRETON"              code="BR">CELTIC</Language>
+   <Language name="BULGARIAN"           code="BG">SLAVIC</Language>
+   <Language name="BURMESE"             code="MY">ASIAN</Language>
+   <Language name="BYELORUSSIAN"        code="BE">SLAVIC</Language>
+   <Language name="CAMBODIAN"           code="KM">ASIAN</Language>
+   <Language name="CATALAN"             code="CA">ROMANCE</Language>
+   <Language name="CHINESE-SIMPLIFIED"  code="ZH" gli="true" gs="true" mds="true">ASIAN</Language>
+   <Language name="CHINESE-TRADITIONAL" code="ZH-TR" gs="true">ASIAN</Language>
+   <Language name="CORSICAN"            code="CO">ROMANCE</Language>
+   <Language name="CROATIAN"            code="HR" gs="true">SLAVIC</Language>
+   <Language name="CZECH"               code="CS" gs="true" mds="true">SLAVIC</Language>
+   <Language name="DANISH"              code="DA">GERMANIC</Language>
+   <Language name="DUTCH"               code="NL" gs="true" mds="true">GERMANIC</Language>
+   <Language name="ENGLISH"             code="EN" gs="true" gli="true" mds="true">GERMANIC</Language>
+   <Language name="ESPERANTO"           code="EO">INTERNATIONAL AUX.</Language>
+   <Language name="ESTONIAN"            code="ET">FINNO-UGRIC</Language>
+   <Language name="FAROESE"             code="FO">GERMANIC</Language>
+   <Language name="FIJI"                code="FJ">OCEANIC/INDONESIAN</Language>
+   <Language name="FINNISH"             code="FI" gs="true" mds="true">FINNO-UGRIC</Language>
+   <Language name="FRENCH"              code="FR" gs="true" gli="true" mds="true">ROMANCE</Language>
+   <Language name="FRISIAN"             code="FY">GERMANIC</Language>
+   <Language name="GALICIAN"            code="GL" gs="true">ROMANCE</Language>
+   <Language name="GEORGIAN"            code="KA">IBERO-CAUCASIAN</Language>
+   <Language name="GERMAN"              code="DE" gs="true">GERMANIC</Language>
+   <Language name="GREEK"               code="EL" gs="true" gli="true">LATIN/GREEK</Language>
+   <Language name="GREENLANDIC"         code="KL">ESKIMO</Language>
+   <Language name="GUARANI"             code="GN">AMERINDIAN</Language>
+   <Language name="GUJARATI"            code="GU">INDIAN</Language>
+   <Language name="HAUSA"               code="HA">NEGRO-AFRICAN</Language>
+   <Language name="HEBREW"              code="HE" gs="true">SEMITIC</Language>
+   <Language name="HINDI"               code="HI" gs="true">INDIAN</Language>
+   <Language name="HUNGARIAN"           code="HU">FINNO-UGRIC</Language>
+   <Language name="ICELANDIC"           code="IS">GERMANIC</Language>
+   <Language name="INDONESIAN"          code="ID" gs="true">OCEANIC/INDONESIAN</Language>
+   <Language name="INTERLINGUA"         code="IA" mds="true">INTERNATIONAL AUX.</Language>
+   <Language name="INTERLINGUE"         code="IE">INTERNATIONAL AUX.</Language>
+   <Language name="INUKTITUT"           code="IU">[        ]</Language>
+   <Language name="INUPIAK"             code="IK">ESKIMO</Language>
+   <Language name="IRISH"               code="GA">CELTIC</Language>
+   <Language name="ITALIAN"             code="IT" gs="true">ROMANCE</Language>
+   <Language name="JAPANESE"            code="JA" gs="true">ASIAN</Language>
+   <Language name="JAVANESE"            code="JV">OCEANIC/INDONESIAN</Language>
+   <Language name="KANNADA"             code="KN" gs="true">DRAVIDIAN</Language>
+   <Language name="KASHMIRI"            code="KS">INDIAN</Language>
+   <Language name="KAZAKH"              code="KK" gs="true">TURKIC/ALTAIC</Language>
+   <Language name="KINYARWANDA"         code="RW">NEGRO-AFRICAN</Language>
+   <Language name="KIRGHIZ"             code="KY">TURKIC/ALTAIC</Language>
+   <Language name="KOREAN"              code="KO">ASIAN</Language>
+   <Language name="KURDISH"             code="KU">IRANIAN</Language>
+   <Language name="KURUNDI"             code="RN">NEGRO-AFRICAN</Language>
+   <Language name="LAOTHIAN"            code="LO">ASIAN</Language>
+   <Language name="LATIN"               code="LA">LATIN/GREEK</Language>
+   <Language name="LATVIAN (LETTISH)"   code="LV" gli="true">BALTIC</Language>
+   <Language name="LINGALA"             code="LN">NEGRO-AFRICAN</Language>
+   <Language name="LITHUANIAN"          code="LT">BALTIC</Language>
+   <Language name="MACEDONIAN"          code="MK">SLAVIC</Language>
+   <Language name="MALAGASY"            code="MG">OCEANIC/INDONESIAN</Language>
+   <Language name="MALAY"               code="MS">OCEANIC/INDONESIAN</Language>
+   <Language name="MALAYALAM"           code="ML">DRAVIDIAN</Language>
+   <Language name="MALTESE"             code="MT">SEMITIC</Language>
+   <Language name="MAORI"               code="MI" gs="true" mds="true">OCEANIC/INDONESIAN</Language>
+   <Language name="MARATHI"             code="MR" mds="true">INDIAN</Language>
+   <Language name="MOLDAVIAN"           code="MO">ROMANCE</Language>
+   <Language name="MONGOLIAN"           code="MN">[not given]</Language>
+   <Language name="NAURU"               code="NA">[not given]</Language>
+   <Language name="NEPALI"              code="NE">INDIAN</Language>
+   <Language name="NORWEGIAN"           code="NO">GERMANIC</Language>
+   <Language name="OCCITAN"             code="OC">ROMANCE</Language>
+   <Language name="ORIYA"               code="OR">INDIAN</Language>
+   <Language name="PASHTO(PUSHTO)"      code="PS">IRANIAN</Language>
+   <Language name="PERSIAN(FARSI)"      code="FA">IRANIAN</Language>
+   <Language name="POLISH"              code="PL">SLAVIC</Language>
+   <Language name="PORTUGUESE"          code="PT" gs="true">ROMANCE</Language>
+   <Language name="PUNJABI"             code="PA">INDIAN</Language>
+   <Language name="QUECHUA"             code="QU">AMERINDIAN</Language>
+   <Language name="RHAETO-ROMANCE"      code="RM">ROMANCE</Language>
+   <Language name="ROMANIAN"            code="RO">ROMANCE</Language>
+   <Language name="RUSSIAN"             code="RU" gs="true" gli="true" mds="true">SLAVIC</Language>
+   <Language name="SAMOAN"              code="SM">OCEANIC/INDONESIAN</Language>
+   <Language name="SANGHO"              code="SG">NEGRO-AFRICAN</Language>
+   <Language name="SANSKRIT"            code="SA">INDIAN</Language>
+   <Language name="SCOTS(GAELIC)"       code="GD">CELTIC</Language>
+   <Language name="SERBIAN"             code="SR">SLAVIC</Language>
+   <Language name="SERBO-CROATIAN"      code="SH">SLAVIC</Language>
+   <Language name="SESOTHO"             code="ST">NEGRO-AFRICAN</Language>
+   <Language name="SETSWANA"            code="TN">NEGRO-AFRICAN</Language>
+   <Language name="SHONA"               code="SN">NEGRO-AFRICAN</Language>
+   <Language name="SINDHI"              code="SD">INDIAN</Language>
+   <Language name="SINGHALESE"          code="SI">INDIAN</Language>
+   <Language name="SISWATI"             code="SS">NEGRO-AFRICAN</Language>
+   <Language name="SLOVAK"              code="SK">SLAVIC</Language>
+   <Language name="SLOVENIAN"           code="SL">SLAVIC</Language>
+   <Language name="SOMALI"              code="SO">HAMITIC</Language>
+   <Language name="SPANISH"             code="ES" gs="true" gli="true" mds="true">ROMANCE</Language>
+   <Language name="SUNDANESE"           code="SU">OCEANIC/INDONESIAN</Language>
+   <Language name="SWAHILI"             code="SW">NEGRO-AFRICAN</Language>
+   <Language name="SWEDISH"             code="SV">GERMANIC</Language>
+   <Language name="TAGALOG"             code="TL">OCEANIC/INDONESIAN</Language>
+   <Language name="TAJIK"               code="TG">IRANIAN</Language>
+   <Language name="TAMIL"               code="TA">DRAVIDIAN</Language>
+   <Language name="TATAR"               code="TT">TURKIC/ALTAIC</Language>
+   <Language name="TELUGU"              code="TE">DRAVIDIAN</Language>
+   <Language name="THAI"                code="TH" gs="true">ASIAN</Language>
+   <Language name="TIBETAN"             code="BO">ASIAN</Language>
+   <Language name="TIGRINYA"            code="TI">SEMITIC</Language>
+   <Language name="TONGA"               code="TO">OCEANIC/INDONESIAN</Language>
+   <Language name="TSONGA"              code="TS">NEGRO-AFRICAN</Language>
+   <Language name="TURKISH"             code="TR" gs="true">TURKIC/ALTAIC</Language>
+   <Language name="TURKMEN"             code="TK">TURKIC/ALTAIC</Language>
+   <Language name="TWI"                 code="TW">NEGRO-AFRICAN</Language>
+   <Language name="UIGUR"               code="UG">[       ]</Language>
+   <Language name="UKRAINIAN"           code="UK" gs="true">SLAVIC</Language>
+   <Language name="URDU"                code="UR">INDIAN</Language>
+   <Language name="UZBEK"               code="UZ">TURKIC/ALTAIC</Language>
+   <Language name="VIETNAMESE"          code="VI">ASIAN</Language>
+   <Language name="VOLAPUK"             code="VO">INTERNATIONAL AUX.</Language>
+   <Language name="WELSH"               code="CY">CELTIC</Language>
+   <Language name="WOLOF"               code="WO">NEGRO-AFRICAN</Language>
+   <Language name="XHOSA"               code="XH">NEGRO-AFRICAN</Language>
+   <Language name="YIDDISH"             code="YI">GERMANIC [*Changed 1989 from original ISO 639:1988, JI]</Language>
+   <Language name="YORUBA"              code="YO">NEGRO-AFRICAN</Language>
+   <Language name="ZHUANG"              code="ZA">[       ]</Language>
+   <Language name="ZULU"                code="ZU">NEGRO-AFRICAN</Language>
+</Languages>
Index: /tags/greenstone-3_02-distribution/gli/classes/xml/metadata.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gli/classes/xml/metadata.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/classes/xml/metadata.xml	(revision 13928)
@@ -0,0 +1,3 @@
+<?xml version="1.0"  encoding="UTF-8" standalone="no"?>
+<!DOCTYPE DirectoryMetadata SYSTEM "http://greenstone.org/dtd/DirectoryMetadata/1.0/DirectoryMetadata.dtd">
+<DirectoryMetadata/>
Index: /tags/greenstone-3_02-distribution/gli/classes/xml/profile.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gli/classes/xml/profile.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/classes/xml/profile.xml	(revision 13928)
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Profiles [
+<!ELEMENT Profiles (Action*)>
+<!ELEMENT Action (#PCDATA)>
+<!ATTLIST Action
+                source     CDATA #REQUIRED
+                target     CDATA "">
+]>
+<Profiles>
+</Profiles>
Index: /tags/greenstone-3_02-distribution/gli/classes/xml/template.col
===================================================================
--- /tags/greenstone-3_02-distribution/gli/classes/xml/template.col	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/classes/xml/template.col	(revision 13928)
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE GathererCollection [
+  <!ELEMENT GathererCollection (Argument*, GathererConfig, BuildConfig)>
+  <!ELEMENT GathererConfig    (Arguments*)>
+  <!ELEMENT BuildConfig       (Build, Import)>
+  <!ELEMENT Build             (Arguments*)>
+  <!ELEMENT Import            (Arguments*)>
+  <!ELEMENT Argument          (#PCDATA)>
+  <!ATTLIST Argument
+            name              CDATA #REQUIRED
+				enabled           CDATA "true">
+]>
+
+<GathererCollection>
+  <Argument name="built">false</Argument>
+  <Argument name="imported">false</Argument>
+  <Argument name="skimfile">true</Argument>
+  <GathererConfig/>
+  <BuildConfig>
+    <Build/>
+	 <Import/>
+  </BuildConfig>
+</GathererCollection>
+
+
+
Index: /tags/greenstone-3_02-distribution/gli/classes/xml/template.mds
===================================================================
--- /tags/greenstone-3_02-distribution/gli/classes/xml/template.mds	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/classes/xml/template.mds	(revision 13928)
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE MetadataSet SYSTEM "http://www.greenstone.org/dtd/MetadataSet/1.0/MetadataSet.dtd">
+<MetadataSet>
+</MetadataSet>
Index: /tags/greenstone-3_02-distribution/gli/classes/xml/workflows.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gli/classes/xml/workflows.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/classes/xml/workflows.xml	(revision 13928)
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE PredefinedWorkflows [
+  <!ELEMENT PredefinedWorkflows (Workflow*)>
+  <!ELEMENT Workflow            (#PCDATA)>
+  <!ATTLIST Workflow
+	download			  CDATA "true"
+	gather				  CDATA "true"
+	enrich				  CDATA "true"
+	design				  CDATA "true"
+	create				  CDATA "true"
+	export				  CDATA "true">
+]>
+
+<PredefinedWorkflows>
+  <Workflow>Workflow.AllPanels</Workflow>
+  <Workflow download="false">Workflow.LocalSourceCollectionBuilding</Workflow>
+  <Workflow design="false" create="false">Workflow.DocumentEnriching</Workflow>
+</PredefinedWorkflows>
Index: /tags/greenstone-3_02-distribution/gli/clean.bat
===================================================================
--- /tags/greenstone-3_02-distribution/gli/clean.bat	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/clean.bat	(revision 13928)
@@ -0,0 +1,47 @@
+@echo off
+set GLILANG=en
+
+
+::  -------- Clean up the Greenstone Librarian Interface directory --------
+
+:: This script must be run from within the directory in which it lives
+if exist clean.bat goto cleanGLI
+    if "%GLILANG%" == "en" echo This script must be run from the directory in which it resides.
+    if "%GLILANG%" == "es" echo Este gui¢n deber  ejecutarse desde el directorio en el que reside.
+    if "%GLILANG%" == "fr" echo Ce script doit tre excut 
+ partir du rpertoire dans lequel il se trouve.
+    if "%GLILANG%" == "ru" echo â®â áªàš¯â €®«Š¥­ ¡ëâì ¢§ïâ š§ €šà¥ªâ®àšš, ¢ ª®â®à®© ®­ à á¯®«®Š¥­
+    goto exit
+
+
+:cleanGLI
+:: ---- Remove class files ----
+echo.
+if "%GLILANG%" == "en" echo Removing the Greenstone Librarian Interface class files...
+if "%GLILANG%" == "es" echo Eliminando los archivos de clase de la Interfaz de la Biblioteca Digital Greenstone...
+if "%GLILANG%" == "fr" echo Suppression des fichiers de classe de Greenstone Librarian Interface
+if "%GLILANG%" == "ru" echo € «¥­š¥ ä ©«®¢ ª« áá  ¡š¡«š®â¥ç­®£® š­â¥àä¥©á  Greenstone
+
+if not exist classes\org\greenstone\gatherer goto done
+
+cd classes\org\greenstone\gatherer
+if exist "*.class" del "*.class"
+if exist "cdm\*.class" del "cdm\*.class"
+if exist "collection\*.class" del "collection\*.class"
+if exist "feedback\*.class" del "feedback\*.class"
+if exist "file\*.class" del "file\*.class"
+if exist "gems\*.class" del "gems\*.class"
+if exist "gui\*.class" del "gui\*.class"
+if exist "metadata\*.class" del "metadata\*.class"
+if exist "shell\*.class" del "shell\*.class"
+if exist "util\*.class" del "util\*.class"
+cd ..\..\..\..
+
+:done
+if "%GLILANG%" == "en" echo Done!
+if "%GLILANG%" == "es" echo ­Hecho!
+if "%GLILANG%" == "fr" echo Termin!
+if "%GLILANG%" == "ru" echo ë¯®«­¥­®!
+
+:exit
+echo.
Index: /tags/greenstone-3_02-distribution/gli/clean.sh
===================================================================
--- /tags/greenstone-3_02-distribution/gli/clean.sh	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/clean.sh	(revision 13928)
@@ -0,0 +1,31 @@
+#!/bin/sh
+glilang=en
+
+##  -------- Clean up the Greenstone Librarian Interface directory --------
+
+## ---- Remove class files ----
+echo
+if [ "$glilang" = "es" ]; then
+    echo "Eliminando los archivos de clase de la Interfaz de la Biblioteca "
+    echo "Digital Greenstone..."
+elif [ "$glilang" = "fr" ]; then
+    echo "Suppression des fichiers de classe de Greenstone Librarian Interface"
+elif [ "$glilang" = "ru" ]; then
+    echo "õÄÁÌÅÎÉÅ ÆÁÊÌÏ× ËÌÁÓÓÁ ÂÉÂÌÉÏÔÅÞÎÏÇÏ ÉÎÔÅÒÆÅÊÓÁ Greenstone"
+else
+    echo "Removing the Greenstone Librarian Interface class files..."
+fi
+
+rm -rf GLI.jar
+rm -rf classes/org/greenstone/gatherer/*
+
+if [ "$glilang" = "es" ]; then
+    echo "¡Hecho!"
+elif [ "$glilang" = "fr" ]; then
+    echo "Terminé!"
+elif [ "$glilang" = "ru" ]; then
+    echo "÷ÙÐÏÌÎÅÎÏ!"
+else
+    echo "Done!"
+fi
+echo
Index: /tags/greenstone-3_02-distribution/gli/client-gli.bat
===================================================================
--- /tags/greenstone-3_02-distribution/gli/client-gli.bat	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/client-gli.bat	(revision 13928)
@@ -0,0 +1,167 @@
+@echo off
+set GLILANG=en
+
+
+::  -------- Run the Greenstone Librarian Interface --------
+
+:: This script must be run from within the directory in which it lives
+if exist client-gli.bat goto start
+    if "%GLILANG%" == "en" echo This script must be run from the directory in which it resides.
+    if "%GLILANG%" == "es" echo Este gui¢n deber  ejecutarse desde el directorio en el que reside.
+    if "%GLILANG%" == "fr" echo Ce script doit tre excut 
+ partir du rpertoire dans lequel il se trouve.
+    if "%GLILANG%" == "ru" echo â®â áªàš¯â €®«Š¥­ ¡ëâì ¢§ïâ š§ €šà¥ªâ®àšš, ¢ ª®â®à®© ®­ à á¯®«®Š¥­
+    goto exit
+
+:start
+if "%OS%" == "Windows_NT" goto findGSDL
+    :: Invoke a new command processor to ensure there's enough environment space
+    if "%1" == "Second" goto findGSDL
+        command /E:2048 /C %0 Second %1 %2 %3 %4 %5 %6 %7 %8 %9
+        goto done
+
+:findGSDL
+echo.
+if "%GLILANG%" == "en" echo Greenstone Librarian Interface (GLI)
+if "%GLILANG%" == "en" echo Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato
+if "%GLILANG%" == "en" echo GLI comes with ABSOLUTELY NO WARRANTY; for details see LICENSE.txt
+if "%GLILANG%" == "en" echo This is free software, and you are welcome to redistribute it
+
+if "%GLILANG%" == "es" echo Interfaz de la Biblioteca Digital Greenstone (Greenstone Librarian Interface - GLI)
+if "%GLILANG%" == "es" echo Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato
+if "%GLILANG%" == "es" echo La Interfaz de la Biblioteca Digital Greenstone NO INCLUYE ABSOLUTAMENTE NINGUNA GARANTÖA.
+if "%GLILANG%" == "es" echo Para mayor informaci¢n vea los trminos de la licencia en LICENSE.txt
+if "%GLILANG%" == "es" echo Este es un software abierto, por lo que lo invitamos a que lo distribuya de forma gratuita
+
+if "%GLILANG%" == "fr" echo Interface du Bibliothcaire Greenstone (Greenstone Librarian Interface - GLI)
+if "%GLILANG%" == "fr" echo Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato
+if "%GLILANG%" == "fr" echo GLI est fourni sans AUCUNE GARANTIE; pour des dtails, voir LICENSE.txt
+if "%GLILANG%" == "fr" echo Ceci est un logiciel libre, et vous tes invit 
+ le redistribuer
+
+if "%GLILANG%" == "ru" echo š¡«š®â¥ç­ë© š­â¥àä¥©á Greenstone (Greenstone Librarian Interface - GLI)
+if "%GLILANG%" == "ru" echo Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato
+if "%GLILANG%" == "ru" echo  ­¥ € ¥â   ; €¥â «š á¬. ¢ â¥ªáâ¥ LICENSE.TXT
+if "%GLILANG%" == "ru" echo â® - á¢®¡®€­® à á¯à®áâà ­ï¥¬®¥ ¯à®£à ¬¬­®¥ ®¡¥á¯¥ç¥­š¥ š ë ¬®Š¥â¥ à á¯à®áâà ­ïâì ¥£®
+
+
+:findJava
+:: ---- Check Java exists ----
+set JAVAPATH=
+
+:: Some users may set the above line manually
+if not "%JAVAPATH%" == "" goto testJava
+
+    :: If it is set, use the JAVA_HOME environment variable
+    if not "%JAVA_HOME%" == "" goto javahome
+
+    :: Check if Java is on the search path
+    echo %PATH%| winutil\which.exe java.exe | winutil\setvar.exe JAVAPATH > setjava.bat
+    call setjava.bat
+    del setjava.bat
+    if not "%JAVAPATH%" == "" goto testJava
+
+    :: Still haven't found anything, so try looking in the registry (gulp!)
+    type nul > jdk.reg
+    regedit /E jdk.reg "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit"
+    type jdk.reg > jdk.txt
+    del jdk.reg
+    type nul > jre.reg
+    regedit /E jre.reg "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment"
+    type jre.reg > jre.txt
+    del jre.reg
+
+    winutil\findjava.exe jdk.txt jre.txt | winutil\setvar.exe JAVAPATH > setjava.bat
+    del jdk.txt
+    del jre.txt
+    call setjava.bat
+    del setjava.bat
+
+    :: If nothing was found in the registry, we're stuck
+    if "%JAVAPATH%" == "" goto noJava
+
+    set JAVAPATH=%JAVAPATH%\bin
+    goto testJava
+
+:javahome
+    set JAVAPATH=%JAVA_HOME%\bin
+
+:testJava
+:: Check that a Java executable has been found
+if "%GLILANG%" == "en" echo Checking Java: %JAVAPATH%
+if "%GLILANG%" == "es" echo Revisando Java: %JAVAPATH%
+if "%GLILANG%" == "fr" echo Vrification de Java: %JAVAPATH%
+if "%GLILANG%" == "ru" echo à®¢¥àª  Java: %JAVAPATH%
+if exist "%JAVAPATH%\java.exe" goto checkGLI
+
+:noJava
+    echo.
+    if "%GLILANG%" == "en" echo Failed to locate an appropriate version of Java. You must install a
+    if "%GLILANG%" == "en" echo Java Runtime Environment (version 1.4 or greater) before running the
+    if "%GLILANG%" == "en" echo Greenstone Librarian Interface.
+
+    if "%GLILANG%" == "es" echo No se pudo localizar una versi¢n apropiada de Java. Usted deber 
+    if "%GLILANG%" == "es" echo instalar un Ambiente de Ejecuci¢n Java (versi¢n 1.4 o superior)
+    if "%GLILANG%" == "es" echo antes de correr la Interfaz de la Biblioteca Digital Greenstone.
+
+    if "%GLILANG%" == "fr" echo Une version adquate de Java n'a pas pu tre localise. Vous devez
+    if "%GLILANG%" == "fr" echo installer un Java Runtime Environment (version 1.4 ou suprieur)
+    if "%GLILANG%" == "fr" echo avant de dmarrer Greenstone Librarian Interface.
+
+    if "%GLILANG%" == "ru" echo ¥ ã€ «®áì ®¯à¥€¥«šâì ¬¥áâ®­ å®Š€¥­š¥ á®®â¢¥âáâ¢ãîé¥© ¢¥àášš Java.
+    if "%GLILANG%" == "ru" echo ë €®«Š­ë ãáâ ­®¢šâì Java Runtime Environment (¢¥àášî 1.4 š«š ¢ëè¥) ¯¥à¥€ ¢¢®€®¬
+    if "%GLILANG%" == "ru" echo ¡š¡«š®â¥ç­®£® š­â¥àä¥©á  Greenstone.
+    goto exit
+
+
+:checkGLI
+:: ---- Check that the GLI has been compiled ----
+if exist "classes/org/greenstone/gatherer/Gatherer.class" goto runGLI
+if exist "GLI.jar" goto runGLI
+    echo.
+    if "%GLILANG%" == "en" echo You need to compile the Greenstone Librarian Interface (using makegli.bat)
+    if "%GLILANG%" == "en" echo before running this script.
+
+    if "%GLILANG%" == "es" echo Usted necesita compilar la Interfaz de la Biblioteca Digital Greenstone
+    if "%GLILANG%" == "es" echo (por medio de makegli.bat) antes de ejecutar este gui¢n.
+
+    if "%GLILANG%" == "fr" echo Vous devez compiler le Greenstone Interface (en utilisant makegil.bat)
+    if "%GLILANG%" == "fr" echo avant d'excuter ce script.
+
+    if "%GLILANG%" == "ru" echo ë €®«Š­ë ª®¬¯š«šà®¢ âì ¡š¡«š®â¥ç­ë© š­â¥àä¥©á Greenstone (šá¯®«ì§ãï makegli.bat)
+    if "%GLILANG%" == "ru" echo ¯¥à¥€ ¢¢®€®¬ íâ®£® áªàš¯â 
+    goto exit
+
+
+:runGLI
+:: ---- Finally, run the GLI ----
+echo.
+
+
+if "%GLILANG%" == "en" echo Running the Greenstone Librarian Interface...
+if "%GLILANG%" == "es" echo Ejecutando la Interfaz de la Biblioteca Digital Greenstone...
+if "%GLILANG%" == "fr" echo Excution de Greenstone Librarian Interface
+if "%GLILANG%" == "ru" echo ¥ªãéš© ¡š¡«š®â¥ç­ë© š­â¥àä¥©á Greenstone...
+
+:: -Xms32M          To set minimum memory
+:: -Xmx32M          To set maximum memory
+:: -verbose:gc      To set garbage collection messages
+:: -Xincgc          For incremental garbage collection
+:: -Xprof           Function call profiling
+:: -Xloggc:<file>   Write garbage collection log
+
+"%JAVAPATH%\java" -Xmx128M -cp classes/;GLI.jar;lib/apache.jar;lib/qfslib.jar org.greenstone.gatherer.GathererProg -use_remote_greenstone %1 %2 %3 %4 %5 %6 %7 %8 %9
+
+if "%GLILANG%" == "en" echo Done!
+if "%GLILANG%" == "es" echo ­Hecho!
+if "%GLILANG%" == "fr" echo Termin!
+if "%GLILANG%" == "ru" echo ë¯®«­¥­®!
+goto done
+
+:exit
+echo.
+pause
+
+:done
+:: ---- Clean up ----
+set JAVAPATH=
Index: /tags/greenstone-3_02-distribution/gli/client-gli.sh
===================================================================
--- /tags/greenstone-3_02-distribution/gli/client-gli.sh	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/client-gli.sh	(revision 13928)
@@ -0,0 +1,174 @@
+#!/bin/sh
+glilang=en
+
+echo
+if [ "$glilang" = "es" ]; then
+    echo "Interfaz de la Biblioteca Digital Greenstone (Greenstone Librarian Interface - GLI)"
+    echo "Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato"
+    echo "La Interfaz de la Biblioteca Digital Greenstone NO INCLUYE ABSOLUTAMENTE NINGUNA GARANTÍA."
+    echo "Para mayor información vea los términos de la licencia en LICENSE.txt"
+    echo "Este es un software abierto, por lo que lo invitamos a que lo distribuya de forma gratuita"
+elif [ "$glilang" = "fr" ]; then
+    echo "Interface du Bibliothécaire Greenstone (Greenstone Librarian Interface - GLI)"
+    echo "Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato"
+    echo "GLI est fourni sans AUCUNE GARANTIE; pour des détails, voir LICENSE.txt"
+    echo "Ceci est un logiciel libre, et vous êtes invité à le redistribuer"
+elif [ "$glilang" = "ru" ]; then
+    echo "âÉÂÌÉÏÔÅÞÎÙÊ ÉÎÔÅÒÆÅÊÓ Greenstone (Greenstone Librarian Interface - GLI)"
+    echo "Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato"
+    echo "âéç ÎÅ ÄÁÅÔ áâóïìàôîï îéëáëéè çáòáîôéê; ÄÅÔÁÌÉ ÓÍ. × ÔÅËÓÔÅ LICENSE.TXT"
+    echo "üÔÏ - Ó×ÏÂÏÄÎÏ ÒÁÓÐÒÏÓÔÒÁÎÑÅÍÏÅ ÐÒÏÇÒÁÍÍÎÏÅ ÏÂÅÓÐÅÞÅÎÉÅ É ÷Ù ÍÏÖÅÔÅ ÒÁÓÐÒÏÓÔÒÁÎÑÔØ ÅÇÏ"
+else
+    echo "Greenstone Librarian Interface (GLI)"
+    echo "Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato"
+    echo "GLI comes with ABSOLUTELY NO WARRANTY; for details see LICENSE.txt"
+    echo "This is free software, and you are welcome to redistribute it"
+fi
+echo
+
+##  -------- Run the Greenstone Librarian Interface --------
+
+# This script must be run from within the directory in which it lives
+thisdir=`pwd`
+if [ ! -f "${thisdir}/client-gli.sh" ]; then
+    if [ "$glilang" = "es" ]; then
+        echo "Este guión deberá ejecutarse desde el directorio en el que reside."
+    elif [ "$glilang" = "fr" ]; then
+	echo "Ce script doit être exécuté à partir du répertoire dans lequel il se trouve."
+    elif [ "$glilang" = "ru" ]; then
+	echo "üÔÏÔ ÓËÒÉÐÔ ÄÏÌÖÅÎ ÂÙÔØ ×ÚÑÔ ÉÚ ÄÉÒÅËÔÏÒÉÉ, × ËÏÔÏÒÏÊ ÏÎ ÒÁÓÐÏÌÏÖÅÎ"
+    else
+	echo "This script must be run from the directory in which it resides."
+    fi
+    exit 1
+fi
+
+
+## ---- Check Java exists ----
+javapath=
+
+# Some users may set the above line manually
+if [ "x$javapath" = "x" ]; then
+
+    # If it is set, use the JAVA_HOME environment variable
+    if [ "x$JAVA_HOME" != "x" ]; then
+	javapath="$JAVA_HOME/bin/java"
+
+    # Check if Java is on the search path
+    else
+	javapath=`which java 2> /dev/null`
+    fi
+fi
+
+# Check that a Java executable has been found
+if [ "$glilang" = "es" ]; then
+    echo "Revisando Java: $javapath"
+elif [ "$glilang" = "fr" ]; then
+    echo "Vérification de Java: $javapath"
+elif [ "$glilang" = "ru" ]; then
+    echo "ðÒÏ×ÅÒËÁ Java: $javapath"
+else
+    echo "Checking Java: $javapath"
+fi
+if [ ! -x "$javapath" ]; then
+    echo
+    if [ "$glilang" = "es" ]; then
+	echo "No se pudo localizar una versión apropiada de Java. Usted deberá "
+	echo "instalar un Ambiente de Ejecución Java (versión 1.4 o superior) "
+	echo "antes de correr la Interfaz de la Biblioteca Digital Greenstone."
+    elif [ "$glilang" = "fr" ]; then
+	echo "Une version adéquate de Java n'a pas pu être localisée."
+	echo "Vous devez installer un Java Runtime Environment (version 1.4 ou"
+	echo "supérieur) avant de démarrer Greenstone Librarian Interface."
+    elif [ "$glilang" = "ru" ]; then
+	echo "îÅ ÕÄÁÌÏÓØ ÏÐÒÅÄÅÌÉÔØ ÍÅÓÔÏÎÁÈÏÖÄÅÎÉÅ ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÅÊ ×ÅÒÓÉÉ Java."
+	echo "÷Ù ÄÏÌÖÎÙ ÕÓÔÁÎÏ×ÉÔØ Java Runtime Environment (×ÅÒÓÉÀ 1.4 ÉÌÉ ×ÙÛÅ)"
+	echo "ÐÅÒÅÄ ××ÏÄÏÍ ÂÉÂÌÉÏÔÅÞÎÏÇÏ ÉÎÔÅÒÆÅÊÓÁ Greenstone."
+    else
+	echo "Failed to locate an appropriate version of Java. You must install a"
+	echo "Java Runtime Environment (version 1.4 or greater) before running the"
+	echo "Greenstone Librarian Interface."
+    fi
+    exit 1
+fi
+
+
+## -- Check the version of Java is new enough (1.4.0 or higher) to run the GLI --
+`$javapath -classpath . CheckJavaVersion > /dev/null`
+if [ $? -ne 2 ] ; then
+    echo
+    if [ "$glilang" = "es" ]; then
+	echo "La versión del Ambiente de Ejecución Java (JRE por sus siglas en "
+	echo "inglés) que usted tiene instalada es demasiado vieja para ejecutar "
+	echo "la Interfaz de la Biblioteca Digital Greenstone. Por favor instale "
+	echo "una nueva versión del Ambiente de Ejecución Java (versión 1.4 o "
+	echo "posterior) y ejecute nuevamente este guión."
+    elif [ "$glilang" = "fr" ]; then
+	echo "La version de Java Runtime Environment que vous avez installée est"
+	echo "trop vielle pour faire fonctionner Greenstone Librarian Interface."
+	echo "Veuillez installer une nouvelle version du JRE (version 1.4 ou plus"
+	echo "récente) et redémarrez le script."
+    elif [ "$glilang" = "ru" ]; then
+	echo "÷ÅÒÓÉÑ Java Runtime Environment, ËÏÔÏÒÕÀ ÷Ù ÕÓÔÁÎÏ×ÉÌÉ, ÏÞÅÎØ ÓÔÁÒÁ,"
+	echo "ÞÔÏÂÙ ÕÐÒÁ×ÌÑÔØ ÂÉÂÌÉÏÔÅÞÎÙÍ ÉÎÔÅÒÆÅÊÓÏÍ Greenstone. ðÏÖÁÌÕÊÓÔÁ, "
+	echo "ÕÓÔÁÎÏ×ÉÔÅ ÎÏ×ÕÀ ×ÅÒÓÉÀ JRE (×ÅÒÓÉÀ 1.4 ÉÌÉ ÂÏÌÅÅ ÎÏ×ÕÀ) É"
+	echo "ÐÅÒÅÕÓÔÁÎÏ×ÉÔÅ ÜÔÏÔ ÓËÒÉÐÔ"
+    else
+	echo "The version of the Java Runtime Environment you have installed is too"
+	echo "old to run the Greenstone Librarian Interface. Please install a new"
+	echo "version of the JRE (version 1.4 or newer) and rerun this script."
+    fi
+    exit 1
+fi
+
+## ---- Check that the GLI has been compiled ----
+if [ ! -f "classes/org/greenstone/gatherer/GathererProg.class" ] && [ ! -f "GLI.jar" ]; then
+    echo
+    if [ "$glilang" = "es" ]; then
+	echo "Usted necesita compilar la Interfaz de la Biblioteca Digital Greenstone"
+	echo "(por medio de makegli.sh) antes de ejecutar este guión."
+    elif [ "$glilang" = "fr" ]; then
+	echo "Vous devez compiler le Greenstone Interface (en utilisant makegli.sh)"
+	echo "avant d'exécuter ce script."
+    elif [ "$glilang" = "ru" ]; then
+	echo "÷Ù ÄÏÌÖÎÙ ËÏÍÐÉÌÉÒÏ×ÁÔØ ÂÉÂÌÉÏÔÅÞÎÙÊ ÉÎÔÅÒÆÅÊÓ Greenstone"
+	echo "(ÉÓÐÏÌØÚÕÑ makegli.sh) ÐÅÒÅÄ ××ÏÄÏÍ ÜÔÏÇÏ ÓËÒÉÐÔÁ"
+    else
+	echo "You need to compile the Greenstone Librarian Interface (using makegli.sh)"
+	echo "before running this script."
+    fi
+    exit 1
+fi
+
+
+## ---- Finally, run the GLI ----
+echo
+if [ "$glilang" = "es" ]; then
+    echo "Ejecutando la Interfaz de la Biblioteca Digital Greenstone..."
+elif [ "$glilang" = "fr" ]; then
+    echo "Exécution de Greenstone Librarian Interface"
+elif [ "$glilang" = "ru" ]; then
+    echo "ôÅËÕÝÉÊ ÂÉÂÌÉÏÔÅÞÎÙÊ ÉÎÔÅÒÆÅÊÓ Greenstone..."
+else
+    echo "Running the Greenstone Librarian Interface..."
+fi
+
+# Other arguments you can provide to GLI to work around memory limitations, or debug
+# -Xms<number>M    To set minimum memory (by default 32MB)
+# -Xmx<number>M    To set maximum memory (by default the nearest 2^n to the total remaining physical memory)
+# -verbose:gc      To set garbage collection messages
+# -Xincgc          For incremental garbage collection (significantly slows performance)
+# -Xprof           Function call profiling
+# -Xloggc:<file>   Write garbage collection log
+
+$javapath -Xmx128M -classpath classes/:GLI.jar:lib/apache.jar:lib/qfslib.jar org.greenstone.gatherer.GathererProg -use_remote_greenstone $*
+
+if [ "$glilang" = "es" ]; then
+    echo "¡Hecho!"
+elif [ "$glilang" = "fr" ]; then
+    echo "Terminé!"
+elif [ "$glilang" = "ru" ]; then
+    echo "÷ÙÐÏÌÎÅÎÏ!"
+else
+    echo "Done!"
+fi
Index: /tags/greenstone-3_02-distribution/gli/copyright/apache_license.txt
===================================================================
--- /tags/greenstone-3_02-distribution/gli/copyright/apache_license.txt	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/copyright/apache_license.txt	(revision 13928)
@@ -0,0 +1,64 @@
+Pollo uses the following components from the Apache projects:
+
+ - Xerces: used to parse XML files. Pollo also depends heavely
+   on Xerces' DOM implementation (including the rarely found support
+   for mutation events).
+
+ - Commons Digester: used to parse the xml-based configuration file
+   of Pollo.
+
+ - log4j
+
+For more information about this projects, visit the following sites:
+http://xml.apache.org
+http://jakarta.apache.org
+
+The following license applies to all this software (substitute
+the word Xerces for all other mentioned projects):
+
+The Apache Software License, Version 1.1
+
+
+Copyright (c) 1999 The Apache Software Foundation.  All rights 
+reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer. 
+
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in
+   the documentation and/or other materials provided with the
+   distribution.
+
+3. The end-user documentation included with the redistribution,
+   if any, must include the following acknowledgment:  
+      "This product includes software developed by the
+       Apache Software Foundation (http://www.apache.org/)."
+   Alternately, this acknowledgment may appear in the software itself,
+   if and wherever such third-party acknowledgments normally appear.
+
+4. The names "Xerces" and "Apache Software Foundation" must
+   not be used to endorse or promote products derived from this
+   software without prior written permission. For written 
+   permission, please contact apache@apache.org.
+
+5. Products derived from this software may not be called "Apache",
+   nor may "Apache" appear in their name, without prior written
+   permission of the Apache Software Foundation.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
Index: /tags/greenstone-3_02-distribution/gli/copyright/mpl_1.1.txt
===================================================================
--- /tags/greenstone-3_02-distribution/gli/copyright/mpl_1.1.txt	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/copyright/mpl_1.1.txt	(revision 13928)
@@ -0,0 +1,171 @@
+MOZILLA PUBLIC LICENSE
+Version 1.1
+**********************
+
+1. Definitions.
+
+      1.0.1. "Commercial Use" means distribution or otherwise making the Covered Code available to a third party.
+
+      1.1. ''Contributor'' means each entity that creates or contributes to the creation of Modifications.
+
+      1.2. ''Contributor Version'' means the combination of the Original Code, prior Modifications used by a Contributor, and the Modifications made by that particular Contributor.
+
+      1.3. ''Covered Code'' means the Original Code or Modifications or the combination of the Original Code and Modifications, in each case including portions thereof.
+
+      1.4. ''Electronic Distribution Mechanism'' means a mechanism generally accepted in the software development community for the electronic transfer of data.
+
+      1.5. ''Executable'' means Covered Code in any form other than Source Code.
+
+      1.6. ''Initial Developer'' means the individual or entity identified as the Initial Developer in the Source Code notice required by Exhibit A.
+
+      1.7. ''Larger Work'' means a work which combines Covered Code or portions thereof with code not governed by the terms of this License.
+
+      1.8. ''License'' means this document.
+
+      1.8.1. "Licensable" means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently acquired, any and all of the rights conveyed herein.
+
+      1.9. ''Modifications'' means any addition to or deletion from the substance or structure of either the Original Code or any previous Modifications. When Covered Code is released as a series of files, a Modification is:
+            A. Any addition to or deletion from the contents of a file containing Original Code or previous Modifications.
+
+            B. Any new file that contains any part of the Original Code or previous Modifications.
+             
+      1.10. ''Original Code'' means Source Code of computer software code which is described in the Source Code notice required by Exhibit A as Original Code, and which, at the time of its release under this License is not already Covered Code governed by this License.
+
+      1.10.1. "Patent Claims" means any patent claim(s), now owned or hereafter acquired, including without limitation,  method, process, and apparatus claims, in any patent Licensable by grantor.
+
+      1.11. ''Source Code'' means the preferred form of the Covered Code for making modifications to it, including all modules it contains, plus any associated interface definition files, scripts used to control compilation and installation of an Executable, or source code differential comparisons against either the Original Code or another well known, available Covered Code of the Contributor's choice. The Source Code can be in a compressed or archival form, provided the appropriate decompression or de-archiving software is widely available for no charge.
+
+      1.12. "You'' (or "Your")  means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License or a future version of this License issued under Section 6.1. For legal entities, "You'' includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, "control'' means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity.
+
+2. Source Code License.
+
+      2.1. The Initial Developer Grant.
+      The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims:
+            (a)  under intellectual property rights (other than patent or trademark) Licensable by Initial Developer to use, reproduce, modify, display, perform, sublicense and distribute the Original Code (or portions thereof) with or without Modifications, and/or as part of a Larger Work; and
+
+            (b) under Patents Claims infringed by the making, using or selling of Original Code, to make, have made, use, practice, sell, and offer for sale, and/or otherwise dispose of the Original Code (or portions thereof).
+                          (c) the licenses granted in this Section 2.1(a) and (b) are effective on the date Initial Developer first distributes Original Code under the terms of this License.
+
+            (d) Notwithstanding Section 2.1(b) above, no patent license is granted: 1) for code that You delete from the Original Code; 2) separate from the Original Code;  or 3) for infringements caused by: i) the modification of the Original Code or ii) the combination of the Original Code with other software or devices.
+             
+      2.2. Contributor Grant.
+      Subject to third party intellectual property claims, each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license
+             
+            (a)  under intellectual property rights (other than patent or trademark) Licensable by Contributor, to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof) either on an unmodified basis, with other Modifications, as Covered Code and/or as part of a Larger Work; and
+
+            (b) under Patent Claims infringed by the making, using, or selling of  Modifications made by that Contributor either alone and/or in combination with its Contributor Version (or portions of such combination), to make, use, sell, offer for sale, have made, and/or otherwise dispose of: 1) Modifications made by that Contributor (or portions thereof); and 2) the combination of  Modifications made by that Contributor with its Contributor Version (or portions of such combination).
+
+            (c) the licenses granted in Sections 2.2(a) and 2.2(b) are effective on the date Contributor first makes Commercial Use of the Covered Code.
+
+            (d)    Notwithstanding Section 2.2(b) above, no patent license is granted: 1) for any code that Contributor has deleted from the Contributor Version; 2)  separate from the Contributor Version;  3)  for infringements caused by: i) third party modifications of Contributor Version or ii)  the combination of Modifications made by that Contributor with other software  (except as part of the Contributor Version) or other devices; or 4) under Patent Claims infringed by Covered Code in the absence of Modifications made by that Contributor.
+
+
+3. Distribution Obligations.
+
+      3.1. Application of License.
+      The Modifications which You create or to which You contribute are governed by the terms of this License, including without limitation Section 2.2. The Source Code version of Covered Code may be distributed only under the terms of this License or a future version of this License released under Section 6.1, and You must include a copy of this License with every copy of the Source Code You distribute. You may not offer or impose any terms on any Source Code version that alters or restricts the applicable version of this License or the recipients' rights hereunder. However, You may include an additional document offering the additional rights described in Section 3.5.
+
+      3.2. Availability of Source Code.
+      Any Modification which You create or to which You contribute must be made available in Source Code form under the terms of this License either on the same media as an Executable version or via an accepted Electronic Distribution Mechanism to anyone to whom you made an Executable version available; and if made available via Electronic Distribution Mechanism, must remain available for at least twelve (12) months after the date it initially became available, or at least six (6) months after a subsequent version of that particular Modification has been made available to such recipients. You are responsible for ensuring that the Source Code version remains available even if the Electronic Distribution Mechanism is maintained by a third party.
+
+      3.3. Description of Modifications.
+      You must cause all Covered Code to which You contribute to contain a file documenting the changes You made to create that Covered Code and the date of any change. You must include a prominent statement that the Modification is derived, directly or indirectly, from Original Code provided by the Initial Developer and including the name of the Initial Developer in (a) the Source Code, and (b) in any notice in an Executable version or related documentation in which You describe the origin or ownership of the Covered Code.
+
+      3.4. Intellectual Property Matters
+            (a) Third Party Claims.
+            If Contributor has knowledge that a license under a third party's intellectual property rights is required to exercise the rights granted by such Contributor under Sections 2.1 or 2.2, Contributor must include a text file with the Source Code distribution titled "LEGAL'' which describes the claim and the party making the claim in sufficient detail that a recipient will know whom to contact. If Contributor obtains such knowledge after the Modification is made available as described in Section 3.2, Contributor shall promptly modify the LEGAL file in all copies Contributor makes available thereafter and shall take other steps (such as notifying appropriate mailing lists or newsgroups) reasonably calculated to inform those who received the Covered Code that new knowledge has been obtained.
+
+            (b) Contributor APIs.
+            If Contributor's Modifications include an application programming interface and Contributor has knowledge of patent licenses which are reasonably necessary to implement that API, Contributor must also include this information in the LEGAL file.
+             
+                (c)    Representations.
+            Contributor represents that, except as disclosed pursuant to Section 3.4(a) above, Contributor believes that Contributor's Modifications are Contributor's original creation(s) and/or Contributor has sufficient rights to grant the rights conveyed by this License.
+
+
+      3.5. Required Notices.
+      You must duplicate the notice in Exhibit A in each file of the Source Code.  If it is not possible to put such notice in a particular Source Code file due to its structure, then You must include such notice in a location (such as a relevant directory) where a user would be likely to look for such a notice.  If You created one or more Modification(s) You may add your name as a Contributor to the notice described in Exhibit A.  You must also duplicate this License in any documentation for the Source Code where You describe recipients' rights or ownership rights relating to Covered Code.  You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Code. However, You may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear than any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability terms You offer.
+
+      3.6. Distribution of Executable Versions.
+      You may distribute Covered Code in Executable form only if the requirements of Section 3.1-3.5 have been met for that Covered Code, and if You include a notice stating that the Source Code version of the Covered Code is available under the terms of this License, including a description of how and where You have fulfilled the obligations of Section 3.2. The notice must be conspicuously included in any notice in an Executable version, related documentation or collateral in which You describe recipients' rights relating to the Covered Code. You may distribute the Executable version of Covered Code or ownership rights under a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License and that the license for the Executable version does not attempt to limit or alter the recipient's rights in the Source Code version from the rights set forth in this License. If You distribute the Executable version under a different license You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or any Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer.
+
+      3.7. Larger Works.
+      You may create a Larger Work by combining Covered Code with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Code.
+
+4. Inability to Comply Due to Statute or Regulation.
+
+      If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Code due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be included in the LEGAL file described in Section 3.4 and must be included with all distributions of the Source Code. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it.
+
+5. Application of this License.
+
+      This License applies to code to which the Initial Developer has attached the notice in Exhibit A and to related Covered Code.
+
+6. Versions of the License.
+
+      6.1. New Versions.
+      Netscape Communications Corporation (''Netscape'') may publish revised and/or new versions of the License from time to time. Each version will be given a distinguishing version number.
+
+      6.2. Effect of New Versions.
+      Once Covered Code has been published under a particular version of the License, You may always continue to use it under the terms of that version. You may also choose to use such Covered Code under the terms of any subsequent version of the License published by Netscape. No one other than Netscape has the right to modify the terms applicable to Covered Code created under this License.
+
+      6.3. Derivative Works.
+      If You create or use a modified version of this License (which you may only do in order to apply it to code which is not already Covered Code governed by this License), You must (a) rename Your license so that the phrases ''Mozilla'', ''MOZILLAPL'', ''MOZPL'', ''Netscape'', "MPL", ''NPL'' or any confusingly similar phrase do not appear in your license (except to note that your license differs from this License) and (b) otherwise make it clear that Your version of the license contains terms which differ from the Mozilla Public License and Netscape Public License. (Filling in the name of the Initial Developer, Original Code or Contributor in the notice described in Exhibit A shall not of themselves be deemed to be modifications of this License.)
+
+7. DISCLAIMER OF WARRANTY.
+
+      COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS'' BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+8. TERMINATION.
+
+      8.1.  This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. All sublicenses to the Covered Code which are properly granted shall survive any termination of this License. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive.
+
+      8.2.  If You initiate litigation by asserting a patent infringement claim (excluding declatory judgment actions) against Initial Developer or a Contributor (the Initial Developer or Contributor against whom You file such action is referred to as "Participant")  alleging that:
+
+      (a)  such Participant's Contributor Version directly or indirectly infringes any patent, then any and all rights granted by such Participant to You under Sections 2.1 and/or 2.2 of this License shall, upon 60 days notice from Participant terminate prospectively, unless if within 60 days after receipt of notice You either: (i)  agree in writing to pay Participant a mutually agreeable reasonable royalty for Your past and future use of Modifications made by such Participant, or (ii) withdraw Your litigation claim with respect to the Contributor Version against such Participant.  If within 60 days of notice, a reasonable royalty and payment arrangement are not mutually agreed upon in writing by the parties or the litigation claim is not withdrawn, the rights granted by Participant to You under Sections 2.1 and/or 2.2 automatically terminate at the expiration of the 60 day notice period specified above.
+
+      (b)  any software, hardware, or device, other than such Participant's Contributor Version, directly or indirectly infringes any patent, then any rights granted to You by such Participant under Sections 2.1(b) and 2.2(b) are revoked effective as of the date You first made, used, sold, distributed, or had made, Modifications made by that Participant.
+
+      8.3.  If You assert a patent infringement claim against Participant alleging that such Participant's Contributor Version directly or indirectly infringes any patent where such claim is resolved (such as by license or settlement) prior to the initiation of patent infringement litigation, then the reasonable value of the licenses granted by such Participant under Sections 2.1 or 2.2 shall be taken into account in determining the amount or value of any payment or license.
+
+      8.4.  In the event of termination under Sections 8.1 or 8.2 above,  all end user license agreements (excluding distributors and resellers) which have been validly granted by You or any distributor hereunder prior to termination shall survive termination.
+
+9. LIMITATION OF LIABILITY.
+
+      UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
+
+10. U.S. GOVERNMENT END USERS.
+
+      The Covered Code is a ''commercial item,'' as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of ''commercial computer software'' and ''commercial computer software documentation,'' as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Code with only those rights set forth herein.
+
+11. MISCELLANEOUS.
+
+      This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by California law provisions (except to the extent applicable law, if any, provides otherwise), excluding its conflict-of-law provisions. With respect to disputes in which at least one party is a citizen of, or an entity chartered or registered to do business in the United States of America, any litigation relating to this License shall be subject to the jurisdiction of the Federal Courts of the Northern District of California, with venue lying in Santa Clara County, California, with the losing party responsible for costs, including without limitation, court costs and reasonable attorneys' fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License.
+
+12. RESPONSIBILITY FOR CLAIMS.
+
+      As between Initial Developer and the Contributors, each party is responsible for claims and damages arising, directly or indirectly, out of its utilization of rights under this License and You agree to work with Initial Developer and Contributors to distribute such responsibility on an equitable basis. Nothing herein is intended or shall be deemed to constitute any admission of liability.
+
+13. MULTIPLE-LICENSED CODE.
+
+      Initial Developer may designate portions of the Covered Code as ?Multiple-Licensed?.  ?Multiple-Licensed? means that the Initial Developer permits you to utilize portions of the Covered Code under Your choice of the MPL or the alternative licenses, if any, specified by the Initial Developer in the file described in Exhibit A.
+
+
+EXHIBIT A -Mozilla Public License.
+
+      ``The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
+      http://www.mozilla.org/MPL/
+
+      Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
+      ANY KIND, either express or implied. See the License for the specific language governing rights and
+      limitations under the License.
+
+      The Original Code is ______________________________________.
+
+      The Initial Developer of the Original Code is ________________________. Portions created by
+       ______________________ are Copyright (C) ______ _______________________. All Rights
+      Reserved.
+
+      Contributor(s): ______________________________________.
+
+      Alternatively, the contents of this file may be used under the terms of the _____ license (the  ?[___] License?), in which case the provisions of [______] License are applicable  instead of those above.  If you wish to allow use of your version of this file only under the terms of the [____] License and not to allow others to use your version of this file under the MPL, indicate your decision by deleting  the provisions above and replace  them with the notice and other provisions required by the [___] License.  If you do not delete the provisions above, a recipient may use your version of this file under either the MPL or the [___] License."
+
+      [NOTE: The text of this Exhibit A may differ slightly from the text of the notices in the Source Code files of the Original Code. You should use the text of this Exhibit A rather than the text found in the Original Code Source Code for Your Modifications.] 
Index: /tags/greenstone-3_02-distribution/gli/copyright/qfs_license.txt
===================================================================
--- /tags/greenstone-3_02-distribution/gli/copyright/qfs_license.txt	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/copyright/qfs_license.txt	(revision 13928)
@@ -0,0 +1,11 @@
+Copyright (C) 2003 Quality First Software GmbH
+
+qflib - License
+
+qflib is distributed for free under the terms of the Mozilla Public License Version 1.1, MPL for short. It comes without warranty of any kind. The license grants you free use of qflib, access to the source and the right to modify and redistribute it.
+
+The only restrictions are that you cannot remove Quality First Software GmbH's copyright and that modifications of qflib are automatically covered by the MPL as well. Code that just uses the library through its published interface (referred to as "greater work" in the license) is free to use any license whatever.
+
+As long as these conditions are met there is nothing to inhibit commercial use or commercial distribution of qflib, e.g. together with other software on a CD-rom.
+
+We decided in favor of the MPL because it appears to be a good compromise between protecting openness and free use on the one hand and enabling interoperation with third party software under any license on the other. The text of the license is short and precise compared to others and is comprehensible for the layman. 
Index: /tags/greenstone-3_02-distribution/gli/copyright/wget_license.txt
===================================================================
--- /tags/greenstone-3_02-distribution/gli/copyright/wget_license.txt	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/copyright/wget_license.txt	(revision 13928)
@@ -0,0 +1,100 @@
+GNU GENERAL PUBLIC LICENSE
+
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+675 Mass Ave, Cambridge, MA 02139, USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too.
+
+When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.
+
+Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification follow.
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+   1. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.
+   2. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
+   3. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
+         1. You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
+         2. You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
+         3. If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) 
+      These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
+   4. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:
+         1. Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
+         2. Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
+         3. Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) 
+      The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.
+   5. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
+   6. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.
+   7. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
+   8. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
+   9. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
+  10. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.
+  11. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
+
+      NO WARRANTY
+  12. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+  13. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 
+
+END OF TERMS AND CONDITIONS
+How to Apply These Terms to Your New Programs
+
+If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
+
+To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.
+
+one line to give the program's name and an idea of what it does.
+Copyright (C) 19yy  name of author
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this when it starts in an interactive mode:
+
+Gnomovision version 69, Copyright (C) 19yy name of author
+Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
+type `show w'.  This is free software, and you are welcome
+to redistribute it under certain conditions; type `show c' 
+for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names:
+
+Yoyodyne, Inc., hereby disclaims all copyright
+interest in the program `Gnomovision'
+(which makes passes at compilers) written 
+by James Hacker.
+
+signature of Ty Coon, 1 April 1989
+Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. 
Index: /tags/greenstone-3_02-distribution/gli/gems4gs3.bat
===================================================================
--- /tags/greenstone-3_02-distribution/gli/gems4gs3.bat	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/gems4gs3.bat	(revision 13928)
@@ -0,0 +1,211 @@
+@echo off
+set GLILANG=en
+
+::  -------- Run the Greenstone Editor for Metadata Sets --------
+
+:: This script must be run from within the directory in which it lives
+if exist gems4gs3.bat goto start
+    if "%GLILANG%" == "en" echo This script must be run from the directory in which it resides.
+    if "%GLILANG%" == "es" echo Este gui¢n deber  ejecutarse desde el directorio en el que reside.
+    if "%GLILANG%" == "fr" echo Ce script doit tre excut 
+ partir du rpertoire dans lequel il se trouve.
+    if "%GLILANG%" == "ru" echo â®â áªàš¯â €®«Š¥­ ¡ëâì ¢§ïâ š§ €šà¥ªâ®àšš, ¢ ª®â®à®© ®­ à á¯®«®Š¥­
+    goto exit
+
+:start
+if "%OS%" == "Windows_NT" goto findGSDL3
+    :: Invoke a new command processor to ensure there's enough environment space
+    if "%1" == "Second" goto findGSDL3
+        command /E:2048 /C %0 Second %1 %2 %3 %4 %5 %6 %7 %8 %9
+        goto done
+
+:findGSDL3
+echo.
+if "%GLILANG%" == "en" echo Greenstone Editor for Metadata Sets (GEMS)
+if "%GLILANG%" == "en" echo Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato
+if "%GLILANG%" == "en" echo GEMS comes with ABSOLUTELY NO WARRANTY; for details see LICENSE.txt
+if "%GLILANG%" == "en" echo This is free software, and you are welcome to redistribute it
+
+if "%GLILANG%" == "es" echo Editar conjuntos de metadatos (Greenstone Editor for Metadata Sets - GEMS)
+if "%GLILANG%" == "es" echo Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato
+if "%GLILANG%" == "es" echo GEMS NO INCLUYE ABSOLUTAMENTE NINGUNA GARANTÖA.
+if "%GLILANG%" == "es" echo Para mayor informaci¢n vea los trminos de la licencia en LICENSE.txt
+if "%GLILANG%" == "es" echo Este es un software abierto, por lo que lo invitamos a que lo distribuya de forma gratuita
+
+if "%GLILANG%" == "fr" echo Editer les jeux de méta-données (Greenstone Editor for Metadata Sets - GEMS)
+if "%GLILANG%" == "fr" echo Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato
+if "%GLILANG%" == "fr" echo GEMS est fourni sans AUCUNE GARANTIE; pour des dtails, voir LICENSE.txt
+if "%GLILANG%" == "fr" echo Ceci est un logiciel libre, et vous tes invit 
+ le redistribuer
+
+if "%GLILANG%" == "ru" echo Ðåäàêòèðîâàòü íàáîðû ìåòàäàííûõ (Greenstone Editor for Metadata Sets - GEMS)
+if "%GLILANG%" == "ru" echo Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato
+if "%GLILANG%" == "ru" echo  ­¥ € ¥â   ; €¥â «š á¬. ¢ â¥ªáâ¥ LICENSE.TXT
+if "%GLILANG%" == "ru" echo â® - á¢®¡®€­® à á¯à®áâà ­ï¥¬®¥ ¯à®£à ¬¬­®¥ ®¡¥á¯¥ç¥­š¥ š ë ¬®Š¥â¥ à á¯à®áâà ­ïâì ¥£®
+
+echo.
+::  ---- Determine GSDL3HOME ----
+set GSDL3SRCPATH=
+
+:: Some users may set the above line manually
+if not "%GSDL3SRCPATH%" == "" goto testGSDL3
+    :: The default location for the GLI (and thus GEMS) is a subdirectory of Greenston
+    set GSDL3SRCPATH=..
+    :: If it is set, use the GSDLSRCHOME environment variable 
+    if "%GSDL3SRCHOME%" == "" goto testGSDL3
+	set GSDL3SRCPATH=%GSDL3SRCHOME%
+
+
+:testGSDL3
+:: Check that the Greenstone installation looks OK
+if "%GLILANG%" == "en" echo Checking GSDL3: %GSDL3SRCPATH%
+if "%GLILANG%" == "es" echo Revisando GSDL3: %GSDL3SRCPATH%
+if "%GLILANG%" == "fr" echo Vrification de GSDL3: %GSDLSRCPATH%
+if "%GLILANG%" == "ru" echo à®¢¥àª  GSDL3: %GSDLSRCPATH%
+:: Some users may set the above line manually
+if exist "%GSDL3SRCPATH%\gs3-setup.bat" goto prepGSDL3
+    echo.
+    if "%GLILANG%" == "en" echo The Greenstone installation could not be found, or is incomplete.
+    if "%GLILANG%" == "en" echo Try reinstalling Greenstone then running this script again.
+
+    if "%GLILANG%" == "es" echo No se pudo encontrar la instalaci¢n de Greenstone o est  incompleta.
+    if "%GLILANG%" == "es" echo Trate de reinstalar Greenstone y a continuaci¢n ejecute nuevamente este gui¢n.
+
+    if "%GLILANG%" == "fr" echo L'installation de Greenstone est introuvable ou incomplte. Essayez
+    if "%GLILANG%" == "fr" echo de rinstaller Greenstone et excutez ce script 
+ nouveau.
+
+    if "%GLILANG%" == "ru" echo ­áâ ««ïæšï Greenstone ­¥ ¡ë«  ­ ©€¥­  š«š ®­  ­¥¯®«­ . ®¯à®¡ã©â¥ ¯®¢â®à­®
+    if "%GLILANG%" == "ru" echo ãáâ ­®¢šâì Greenstone,   § â¥¬ ¢¢¥áâš íâ®â áªàš¯â á­®¢ .
+    goto exit
+
+:prepGSDL3
+:: Setup Greenstone, unless it has already been done
+if not "%GSDL3SRCHOME%" == "" goto doneGSDL3
+    cd %GSDL3SRCPATH% 
+    call gs3-setup.bat SetEnv > null 
+    cd %GSDL3SRCHOME%/gli
+
+:doneGSDL3
+:: GSDL3SRCPATH is no longer needed, since GSDL3HOME should now be set
+set GSDL3SRCPATH=
+
+:findJava
+:: ---- Check Java exists ----
+set JAVAPATH=
+
+:: Some users may set the above line manually
+if not "%JAVAPATH%" == "" goto testJava
+
+    :: If it is set, use the JAVA_HOME environment variable
+    if not "%JAVA_HOME%" == "" goto javahome
+
+    :: Check if Java is on the search path
+    echo %PATH%| winutil\which.exe java.exe | winutil\setvar.exe JAVAPATH > setjava.bat
+    call setjava.bat
+    del setjava.bat
+    if not "%JAVAPATH%" == "" goto testJava
+
+    :: Still haven't found anything, so try looking in the registry (gulp!)
+    type nul > jdk.reg
+    regedit /E jdk.reg "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit"
+    type jdk.reg > jdk.txt
+    del jdk.reg
+    type nul > jre.reg
+    regedit /E jre.reg "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment"
+    type jre.reg > jre.txt
+    del jre.reg
+
+    winutil\findjava.exe jdk.txt jre.txt | winutil\setvar.exe JAVAPATH > setjava.bat
+    del jdk.txt
+    del jre.txt
+    call setjava.bat
+    del setjava.bat
+
+    :: If nothing was found in the registry, we're stuck
+    if "%JAVAPATH%" == "" goto noJava
+
+    set JAVAPATH=%JAVAPATH%\bin
+    goto testJava
+
+:javahome
+    set JAVAPATH=%JAVA_HOME%\bin
+
+:testJava
+:: Check that a Java executable has been found
+if "%GLILANG%" == "en" echo Checking Java: %JAVAPATH%
+if "%GLILANG%" == "es" echo Revisando Java: %JAVAPATH%
+if "%GLILANG%" == "fr" echo Vrification de Java: %JAVAPATH%
+if "%GLILANG%" == "ru" echo à®¢¥àª  Java: %JAVAPATH%
+if exist "%JAVAPATH%\java.exe" goto checkGEMS
+
+:noJava
+    echo.
+    if "%GLILANG%" == "en" echo Failed to locate an appropriate version of Java. You must install a
+    if "%GLILANG%" == "en" echo Java Runtime Environment (version 1.4 or greater) before running the
+    if "%GLILANG%" == "en" echo Greenstone Editor for Metadata Sets.
+
+    if "%GLILANG%" == "es" echo No se pudo localizar una versi¢n apropiada de Java. Usted deber 
+    if "%GLILANG%" == "es" echo instalar un Ambiente de Ejecuci¢n Java (versi¢n 1.4 o superior)
+    if "%GLILANG%" == "es" echo antes de correr la Editar conjuntos de metadatos.
+
+    if "%GLILANG%" == "fr" echo Une version adquate de Java n'a pas pu tre localise. Vous devez
+    if "%GLILANG%" == "fr" echo installer un Java Runtime Environment (version 1.4 ou suprieur)
+    if "%GLILANG%" == "fr" echo avant de dmarrer Editer les jeux de méta-données.
+
+    if "%GLILANG%" == "ru" echo ¥ ã€ «®áì ®¯à¥€¥«šâì ¬¥áâ®­ å®Š€¥­š¥ á®®â¢¥âáâ¢ãîé¥© ¢¥àášš Java.
+    if "%GLILANG%" == "ru" echo ë €®«Š­ë ãáâ ­®¢šâì Java Runtime Environment (¢¥àášî 1.4 š«š ¢ëè¥) ¯¥à¥€ ¢¢®€®¬
+    if "%GLILANG%" == "ru" echo Ðåäàêòèðîâàòü íàáîðû ìåòàäàííûõ.
+    goto exit
+
+
+:checkGEMS
+:: ---- Check that the GEMS has been compiled ----
+if exist "classes/org/greenstone/gatherer/gems/GEMS.class" goto runGEMS
+if exist "GLI.jar" goto runGEMS
+    echo.
+    if "%GLILANG%" == "en" echo You need to compile the Greenstone Editor for Metadata Sets (using makegli.bat)
+    if "%GLILANG%" == "en" echo before running this script.
+
+    if "%GLILANG%" == "es" echo Usted necesita compilar la Editar conjuntos de metadatos
+    if "%GLILANG%" == "es" echo (por medio de makegli.bat) antes de ejecutar este gui¢n.
+
+    if "%GLILANG%" == "fr" echo Vous devez compiler le Editer les jeux de méta-données (en utilisant
+    if "%GLILANG%" == "fr" echo makegli.bat) avant d'excuter ce script.
+
+    if "%GLILANG%" == "ru" echo ë €®«Š­ë ª®¬¯š«šà®¢ âì Ðåäàêòèðîâàòü íàáîðû ìåòàäàííûõ (šá¯®«ì§ãï makegli.bat)
+    if "%GLILANG%" == "ru" echo ¯¥à¥€ ¢¢®€®¬ íâ®£® áªàš¯â 
+    goto exit
+
+
+:runGEMS
+:: ---- Finally, run the GEMS ----
+echo.
+
+if "%GLILANG%" == "en" echo Running the Greenstone Editor for Metadata Sets...
+if "%GLILANG%" == "es" echo Ejecutando la Editar conjuntos de metadatos...
+if "%GLILANG%" == "fr" echo Excution de Editer les jeux de méta-données
+if "%GLILANG%" == "ru" echo ¥ªãéš© Ðåäàêòèðîâàòü íàáîðû ìåòàäàííûõ...
+
+:: -Xms32M          To set minimum memory
+:: -Xmx32M          To set maximum memory
+:: -verbose:gc      To set garbage collection messages
+:: -Xincgc          For incremental garbage collection
+:: -Xprof           Function call profiling
+:: -Xloggc:<file>   Write garbage collection log
+
+"%JAVAPATH%\java" -cp classes/;GLI.jar;lib/apache.jar org.greenstone.gatherer.gems.GEMS -gsdl3 %GSDL3HOME% %1 %2 %3 %4 %5 %6 %7 %8 %9
+
+if "%GLILANG%" == "en" echo Done!
+if "%GLILANG%" == "es" echo ­Hecho!
+if "%GLILANG%" == "fr" echo Termin!
+if "%GLILANG%" == "ru" echo ë¯®«­¥­®!
+goto done
+
+:exit
+echo.
+pause
+
+:done
+:: ---- Clean up ----
+set JAVAPATH=
Index: /tags/greenstone-3_02-distribution/gli/gems4gs3.sh
===================================================================
--- /tags/greenstone-3_02-distribution/gli/gems4gs3.sh	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/gems4gs3.sh	(revision 13928)
@@ -0,0 +1,226 @@
+#!/bin/sh
+glilang=en
+
+echo
+if [ "$glilang" = "es" ]; then
+    echo "Editar conjuntos de metadatos (Greenstone Editor for Metadata Sets - GEMS)"
+    echo "Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato"
+    echo "GEMS NO INCLUYE ABSOLUTAMENTE NINGUNA GARANTÍA."
+    echo "Para mayor información vea los términos de la licencia en LICENSE.txt"
+    echo "Este es un software abierto, por lo que lo invitamos a que lo distribuya de forma gratuita"
+elif [ "$glilang" = "fr" ]; then
+    echo "Editer les jeux de méta-données (Greenstone Editor for Metadata Sets - GEMS)"
+    echo "Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato"
+    echo "GEMS est fourni sans AUCUNE GARANTIE; pour des détails, voir LICENSE.txt"
+    echo "Ceci est un logiciel libre, et vous êtes invité à le redistribuer"
+elif [ "$glilang" = "ru" ]; then
+    echo "òÅÄÁËÔÉÒÏ×ÁÔØ ÎÁÂÏÒÙ ÍÅÔÁÄÁÎÎÙÈ (Greenstone Editor for Metadata Sets - GEMS)"
+    echo "Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato"
+    echo "âéç ÎÅ ÄÁÅÔ áâóïìàôîï îéëáëéè çáòáîôéê; ÄÅÔÁÌÉ ÓÍ. × ÔÅËÓÔÅ LICENSE.TXT"
+    echo "üÔÏ - Ó×ÏÂÏÄÎÏ ÒÁÓÐÒÏÓÔÒÁÎÑÅÍÏÅ ÐÒÏÇÒÁÍÍÎÏÅ ÏÂÅÓÐÅÞÅÎÉÅ É ÷Ù ÍÏÖÅÔÅ ÒÁÓÐÒÏÓÔÒÁÎÑÔØ ÅÇÏ"
+else
+    echo "Greenstone Editor for Metadata Sets (GEMS)"
+    echo "Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato"
+    echo "GEMS comes with ABSOLUTELY NO WARRANTY; for details see LICENSE.txt"
+    echo "This is free software, and you are welcome to redistribute it"
+fi
+echo
+
+##  -------- Run the Greenstone Editor for Metadata Sets --------
+
+# This script must be run from within the directory in which it lives
+thisdir=`pwd`
+if [ ! -f "${thisdir}/gems4gs3.sh" ]; then
+    if [ "$glilang" = "es" ]; then
+        echo "Este guión deberá ejecutarse desde el directorio en el que reside."
+    elif [ "$glilang" = "fr" ]; then
+	echo "Ce script doit être exécuté à partir du répertoire dans lequel il se trouve."
+    elif [ "$glilang" = "ru" ]; then
+	echo "üÔÏÔ ÓËÒÉÐÔ ÄÏÌÖÅÎ ÂÙÔØ ×ÚÑÔ ÉÚ ÄÉÒÅËÔÏÒÉÉ, × ËÏÔÏÒÏÊ ÏÎ ÒÁÓÐÏÌÏÖÅÎ"
+    else
+	echo "This script must be run from the directory in which it resides."
+    fi
+    exit 1
+fi
+
+##  ---- Determine GSDL3SRCHOME ----
+gsdl3srcpath=
+# Some users may set the above line manually
+if [ "x$gsdl3srcpath" = "x" ]; then
+    # Check the environment variable first
+    if [ "x$GSDL3SRCHOME" != "x" ]; then
+	gsdl3srcpath=$GSDL3SRCHOME
+
+    # If it is not set, assume that the GLI (and thus GEMS) is installed as a subdirectory of Greenstone3
+    else
+	gsdl3srcpath=`(cd .. && pwd)` 
+    fi
+fi
+
+# Check that the Greenstone installation looks OK
+if [ "$glilang" = "es" ]; then
+    echo "Revisando GSDL3: $gsdl3srcpath"
+elif [ "$glilang" = "fr" ]; then
+    echo "Vérification de GSDL3: $gsdl3srcpath"
+elif [ "$glilang" = "ru" ]; then
+    echo "ðÒÏ×ÅÒËÁ GSDL3: $gsdl3srcpath"
+else
+    echo "Checking GSDL3: $gsdl3srcpath"
+fi
+if [ ! -f "${gsdl3srcpath}/gs3-setup.sh" ] ; then
+    echo
+    if [ "$glilang" = "es" ]; then
+	echo "No se pudo encontrar la instalación de Greenstone o está incompleta."
+        echo "Trate de reinstalar Greenstone y a continuación ejecute nuevamente"
+	echo "este guión."
+    elif [ "$glilang" = "fr" ]; then
+	echo "L'installation de Greenstone est introuvable ou incomplète."
+	echo "Essayez de réinstaller Greenstone et exécutez ce script à nouveau."
+    elif [ "$glilang" = "ru" ]; then
+	echo "éÎÓÔÁÌÌÑÃÉÑ Greenstone ÎÅ ÂÙÌÁ ÎÁÊÄÅÎÁ ÉÌÉ ÏÎÁ ÎÅÐÏÌÎÁ."
+	echo "ðÏÐÒÏÂÕÊÔÅ ÐÏ×ÔÏÒÎÏ ÕÓÔÁÎÏ×ÉÔØ Greenstone, Á ÚÁÔÅÍ ××ÅÓÔÉ ÜÔÏÔ ÓËÒÉÐÔ ÓÎÏ×Á."
+    else
+	echo "The Greenstone installation could not be found, or is incomplete."
+	echo "Try reinstalling Greenstone then running this script again."
+    fi
+    exit 1
+fi
+
+# Setup Greenstone3, unless it has already been done
+if [ "x$GSDL3SRCHOME" = "x" ]; then
+    cd "$gsdl3srcpath"
+    . gs3-setup.sh
+    cd "$thisdir"
+fi
+
+
+## ---- Check Java exists ----
+javapath=
+
+# Some users may set the above line manually
+if [ "x$javapath" = "x" ]; then
+
+    # If it is set, use the JAVA_HOME environment variable
+    if [ "x$JAVA_HOME" != "x" ]; then
+	javapath="$JAVA_HOME/bin/java"
+
+    # Check if Java is on the search path
+    else
+	javapath=`which java 2> /dev/null`
+    fi
+fi
+
+# Check that a Java executable has been found
+if [ "$glilang" = "es" ]; then
+    echo "Revisando Java: $javapath"
+elif [ "$glilang" = "fr" ]; then
+    echo "Vérification de Java: $javapath"
+elif [ "$glilang" = "ru" ]; then
+    echo "ðÒÏ×ÅÒËÁ Java: $javapath"
+else
+    echo "Checking Java: $javapath"
+fi
+if [ ! -x "$javapath" ]; then
+    echo
+    if [ "$glilang" = "es" ]; then
+	echo "No se pudo localizar una versión apropiada de Java. Usted deberá "
+	echo "instalar un Ambiente de Ejecución Java (versión 1.4 o superior) "
+	echo "antes de correr la Editar conjuntos de metadatos."
+    elif [ "$glilang" = "fr" ]; then
+	echo "Une version adéquate de Java n'a pas pu être localisée."
+	echo "Vous devez installer un Java Runtime Environment (version 1.4 ou"
+	echo "supérieur) avant de démarrer Editer les jeux de méta-données."
+    elif [ "$glilang" = "ru" ]; then
+	echo "îÅ ÕÄÁÌÏÓØ ÏÐÒÅÄÅÌÉÔØ ÍÅÓÔÏÎÁÈÏÖÄÅÎÉÅ ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÅÊ ×ÅÒÓÉÉ Java."
+	echo "÷Ù ÄÏÌÖÎÙ ÕÓÔÁÎÏ×ÉÔØ Java Runtime Environment (×ÅÒÓÉÀ 1.4 ÉÌÉ ×ÙÛÅ)"
+	echo "ÐÅÒÅÄ ××ÏÄÏÍ òÅÄÁËÔÉÒÏ×ÁÔØ ÎÁÂÏÒÙ ÍÅÔÁÄÁÎÎÙÈ."
+    else
+	echo "Failed to locate an appropriate version of Java. You must install a"
+	echo "Java Runtime Environment (version 1.4 or greater) before running the"
+	echo "Greenstone Editor for Metadata Sets."
+    fi
+    exit 1
+fi
+
+
+## -- Check the version of Java is new enough (1.4.0 or higher) to run the GEMS --
+`$javapath -classpath . CheckJavaVersion > /dev/null`
+if [ $? -ne 2 ] ; then
+    echo
+    if [ "$glilang" = "es" ]; then
+	echo "La versión del Ambiente de Ejecución Java (JRE por sus siglas en "
+	echo "inglés) que usted tiene instalada es demasiado vieja para ejecutar "
+	echo "la Editar conjuntos de metadatos. Por favor instale una nueva "
+	echo "versión del Ambiente de Ejecución Java (versión 1.4 o posterior)"
+	echo "y ejecute nuevamente este guión."
+    elif [ "$glilang" = "fr" ]; then
+	echo "La version de Java Runtime Environment que vous avez installée est"
+	echo "trop vielle pour faire fonctionner Editer les jeux de méta-données."
+	echo "Veuillez installer une nouvelle version du JRE (version 1.4 ou plus"
+	echo "récente) et redémarrez le script."
+    elif [ "$glilang" = "ru" ]; then
+	echo "÷ÅÒÓÉÑ Java Runtime Environment, ËÏÔÏÒÕÀ ÷Ù ÕÓÔÁÎÏ×ÉÌÉ, ÏÞÅÎØ ÓÔÁÒÁ,"
+	echo "ÞÔÏÂÙ ÕÐÒÁ×ÌÑÔØ òÅÄÁËÔÉÒÏ×ÁÔØ ÎÁÂÏÒÙ ÍÅÔÁÄÁÎÎÙÈ. ðÏÖÁÌÕÊÓÔÁ, "
+	echo "ÕÓÔÁÎÏ×ÉÔÅ ÎÏ×ÕÀ ×ÅÒÓÉÀ JRE (×ÅÒÓÉÀ 1.4 ÉÌÉ ÂÏÌÅÅ ÎÏ×ÕÀ) É"
+	echo "ÐÅÒÅÕÓÔÁÎÏ×ÉÔÅ ÜÔÏÔ ÓËÒÉÐÔ"
+    else
+	echo "The version of the Java Runtime Environment you have installed is too"
+	echo "old to run the Greenstone Editor for Metadata Sets. Please install a new"
+	echo "version of the JRE (version 1.4 or newer) and rerun this script."
+    fi
+    exit 1
+fi
+
+
+## ---- Check that the GEMS has been compiled ----
+if [ ! -f "classes/org/greenstone/gatherer/gems/GEMS.class" ] && [ ! -f "GLI.jar" ]; then
+    echo
+    if [ "$glilang" = "es" ]; then
+	echo "Usted necesita compilar la Editar conjuntos de metadatos"
+	echo "(por medio de makegli.sh) antes de ejecutar este guión."
+    elif [ "$glilang" = "fr" ]; then
+	echo "Vous devez compiler le Editer les jeux de méta-données (en utilisant makegli.sh)"
+	echo "avant d'exécuter ce script."
+    elif [ "$glilang" = "ru" ]; then
+	echo "÷Ù ÄÏÌÖÎÙ ËÏÍÐÉÌÉÒÏ×ÁÔØ òÅÄÁËÔÉÒÏ×ÁÔØ ÎÁÂÏÒÙ ÍÅÔÁÄÁÎÎÙÈ"
+	echo "(ÉÓÐÏÌØÚÕÑ makegli.sh) ÐÅÒÅÄ ××ÏÄÏÍ ÜÔÏÇÏ ÓËÒÉÐÔÁ"
+    else
+	echo "You need to compile the Greenstone Editor for Metadata Sets (using makegli.sh)"
+	echo "before running this script."
+    fi
+    exit 1
+fi
+
+
+## ---- Finally, run the GEMS ----
+echo
+if [ "$glilang" = "es" ]; then
+    echo "Ejecutando la Editar conjuntos de metadatos..."
+elif [ "$glilang" = "fr" ]; then
+    echo "Exécution de Editer les jeux de méta-données"
+elif [ "$glilang" = "ru" ]; then
+    echo "ôÅËÕÝÉÊ òÅÄÁËÔÉÒÏ×ÁÔØ ÎÁÂÏÒÙ ÍÅÔÁÄÁÎÎÙÈ..."
+else
+    echo "Running the Greenstone Editor for Metadata Sets..."
+fi
+
+# Other arguments you can provide to GEMS to work around memory limitations, or debug
+# -Xms<number>M    To set minimum memory (by default 32MB)
+# -Xmx<number>M    To set maximum memory (by default the nearest 2^n to the total remaining physical memory)
+# -verbose:gc      To set garbage collection messages
+# -Xincgc          For incremental garbage collection (significantly slows performance)
+# -Xprof           Function call profiling
+# -Xloggc:<file>   Write garbage collection log
+
+
+$javapath -classpath classes/:GLI.jar:lib/apache.jar org.greenstone.gatherer.gems.GEMS -gsdl3 $GSDL3HOME $*
+
+if [ "$glilang" = "es" ]; then
+    echo "¡Hecho!"
+elif [ "$glilang" = "fr" ]; then
+    echo "Terminé!"
+elif [ "$glilang" = "ru" ]; then
+    echo "÷ÙÐÏÌÎÅÎÏ!"
+else
+    echo "Done!"
+fi
Index: /tags/greenstone-3_02-distribution/gli/gli.bat
===================================================================
--- /tags/greenstone-3_02-distribution/gli/gli.bat	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/gli.bat	(revision 13928)
@@ -0,0 +1,294 @@
+@echo off
+set GLILANG=en
+
+
+::  -------- Run the Greenstone Librarian Interface --------
+
+:: This script must be run from within the directory in which it lives
+if exist gli.bat goto start
+    if "%GLILANG%" == "en" echo This script must be run from the directory in which it resides.
+    if "%GLILANG%" == "es" echo Este gui¢n deber  ejecutarse desde el directorio en el que reside.
+    if "%GLILANG%" == "fr" echo Ce script doit tre excut 
+ partir du rpertoire dans lequel il se trouve.
+    if "%GLILANG%" == "ru" echo â®â áªàš¯â €®«Š¥­ ¡ëâì ¢§ïâ š§ €šà¥ªâ®àšš, ¢ ª®â®à®© ®­ à á¯®«®Š¥­
+    goto exit
+
+:start
+if "%OS%" == "Windows_NT" goto findGSDL
+    :: Invoke a new command processor to ensure there's enough environment space
+    if "%1" == "Second" goto findGSDL
+        command /E:2048 /C %0 Second %1 %2 %3 %4 %5 %6 %7 %8 %9
+        goto done
+
+:findGSDL
+echo.
+if "%GLILANG%" == "en" echo Greenstone Librarian Interface (GLI)
+if "%GLILANG%" == "en" echo Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato
+if "%GLILANG%" == "en" echo GLI comes with ABSOLUTELY NO WARRANTY; for details see LICENSE.txt
+if "%GLILANG%" == "en" echo This is free software, and you are welcome to redistribute it
+
+if "%GLILANG%" == "es" echo Interfaz de la Biblioteca Digital Greenstone (Greenstone Librarian Interface - GLI)
+if "%GLILANG%" == "es" echo Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato
+if "%GLILANG%" == "es" echo La Interfaz de la Biblioteca Digital Greenstone NO INCLUYE ABSOLUTAMENTE NINGUNA GARANTÖA.
+if "%GLILANG%" == "es" echo Para mayor informaci¢n vea los trminos de la licencia en LICENSE.txt
+if "%GLILANG%" == "es" echo Este es un software abierto, por lo que lo invitamos a que lo distribuya de forma gratuita
+
+if "%GLILANG%" == "fr" echo Interface du Bibliothcaire Greenstone (Greenstone Librarian Interface - GLI)
+if "%GLILANG%" == "fr" echo Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato
+if "%GLILANG%" == "fr" echo GLI est fourni sans AUCUNE GARANTIE; pour des dtails, voir LICENSE.txt
+if "%GLILANG%" == "fr" echo Ceci est un logiciel libre, et vous tes invit 
+ le redistribuer
+
+if "%GLILANG%" == "ru" echo š¡«š®â¥ç­ë© š­â¥àä¥©á Greenstone (Greenstone Librarian Interface - GLI)
+if "%GLILANG%" == "ru" echo Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato
+if "%GLILANG%" == "ru" echo  ­¥ € ¥â   ; €¥â «š á¬. ¢ â¥ªáâ¥ LICENSE.TXT
+if "%GLILANG%" == "ru" echo â® - á¢®¡®€­® à á¯à®áâà ­ï¥¬®¥ ¯à®£à ¬¬­®¥ ®¡¥á¯¥ç¥­š¥ š ë ¬®Š¥â¥ à á¯à®áâà ­ïâì ¥£®
+
+echo.
+::  ---- Determine GSDLHOME ----
+set GSDLPATH=
+
+:: Some users may set the above line manually
+if not "%GSDLPATH%" == "" goto testGSDL
+
+    :: The default location for the GLI is a subdirectory of Greenstone
+    set GSDLPATH=..
+
+    :: If it is set, use the GSDLHOME environment variable 
+    if "%GSDLHOME%" == "" goto testGSDL
+	set GSDLPATH=%GSDLHOME%
+
+:testGSDL
+:: Check that the Greenstone installation looks OK
+if "%GLILANG%" == "en" echo Checking GSDL: %GSDLPATH%
+if "%GLILANG%" == "es" echo Revisando GSDL: %GSDLPATH%
+if "%GLILANG%" == "fr" echo Vrification de GSDL: %GSDLPATH%
+if "%GLILANG%" == "ru" echo à®¢¥àª  GSDL: %GSDLPATH%
+if exist "%GSDLPATH%\setup.bat" goto prepGSDL
+    echo.
+    if "%GLILANG%" == "en" echo The Greenstone installation could not be found, or is incomplete.
+    if "%GLILANG%" == "en" echo Try reinstalling Greenstone then running this script again.
+
+    if "%GLILANG%" == "es" echo No se pudo encontrar la instalaci¢n de Greenstone o est  incompleta.
+    if "%GLILANG%" == "es" echo Trate de reinstalar Greenstone y a continuaci¢n ejecute nuevamente este gui¢n.
+
+    if "%GLILANG%" == "fr" echo L'installation de Greenstone est introuvable ou incomplte. Essayez
+    if "%GLILANG%" == "fr" echo de rinstaller Greenstone et excutez ce script 
+ nouveau.
+
+    if "%GLILANG%" == "ru" echo ­áâ ««ïæšï Greenstone ­¥ ¡ë«  ­ ©€¥­  š«š ®­  ­¥¯®«­ . ®¯à®¡ã©â¥ ¯®¢â®à­®
+    if "%GLILANG%" == "ru" echo ãáâ ­®¢šâì Greenstone,   § â¥¬ ¢¢¥áâš íâ®â áªàš¯â á­®¢ .
+    goto exit
+
+:prepGSDL
+:: Setup Greenstone, unless it has already been done
+if not "%GSDLHOME%" == "" goto doneGSDL
+    call "%GSDLPATH%\setup.bat" SetEnv > nul
+
+:doneGSDL
+:: GSDLPATH is no longer needed, since GSDLHOME should now be set
+set GSDLPATH=
+
+
+:findPerl
+::  ---- Check Perl exists ----
+set PERLPATH=
+
+:: Some users may set the above line manually
+if not "%PERLPATH%" == "" goto testPerl
+
+    :: Check if Perl is on the search path
+    echo %PATH%| winutil\which.exe perl.exe | winutil\setvar.exe PERLPATH > setperl.bat
+    call setperl.bat
+    del setperl.bat
+    if not "%PERLPATH%" == "" goto testPerl
+
+    :: If not, try GSDLHOME\bin\windows\perl\bin
+    if exist "%GSDLHOME%\bin\windows\perl\bin\perl.exe" goto gsdlPerl
+
+    :: Still haven't found anything, so try looking in the registry (gulp!)
+    type nul > perl.reg
+    regedit /E perl.reg "HKEY_LOCAL_MACHINE\SOFTWARE\Perl"
+    type perl.reg > perl.txt
+    del perl.reg
+
+    winutil\findperl.exe perl.txt | winutil\setvar.exe PERLPATH > setperl.bat
+    del perl.txt
+    call setperl.bat
+    del setperl.bat
+
+    :: If nothing was found in the registry, we're stuck
+    if "%PERLPATH%" == "" goto noPerl
+
+    goto testPerl
+
+:gsdlPerl
+    set PERLPATH=%GSDLHOME%\bin\windows\perl\bin
+
+:testPerl
+:: Check that a Perl executable has been found
+if "%GLILANG%" == "en" echo Checking Perl: %PERLPATH%
+if "%GLILANG%" == "es" echo Revisando Perl: %PERLPATH%
+if "%GLILANG%" == "fr" echo Vrification de Perl: %PERLPATH%
+if "%GLILANG%" == "ru" echo à®¢¥àª  Perl: %PERLPATH%
+if exist "%PERLPATH%\perl.exe" goto findJava
+
+:noPerl
+    echo.
+    if "%GLILANG%" == "en" echo The Greenstone Librarian Interface requires perl in order to operate,
+    if "%GLILANG%" == "en" echo but perl could not be detected on your system. Please ensure that perl
+    if "%GLILANG%" == "en" echo is installed and is on your search path, then rerun this script.
+
+    if "%GLILANG%" == "es" echo La Interfaz de la Biblioteca Digital Greenstone requiere Perl para poder
+    if "%GLILANG%" == "es" echo operar, pero ste no aparece en su sistema. Por favor aseg£rese de
+    if "%GLILANG%" == "es" echo que Perl est  instalado y se encuentra en su ruta de b£squeda.
+    if "%GLILANG%" == "es" echo A continuaci¢n ejecute nuevamente este gui¢n.
+
+    if "%GLILANG%" == "fr" echo Greenstone Librarian Interface ncessite perl pour son fonctionnement,
+    if "%GLILANG%" == "fr" echo mais perl n'a pas pu tre dtect dans votre systme. Veuillez vous 
+    if "%GLILANG%" == "fr" echo assurer que perl est install et est spcifi dans votre chemin de 
+    if "%GLILANG%" == "fr" echo recherche, puis redmarrez ce script.
+
+    if "%GLILANG%" == "ru" echo š¡«š®â¥ç­ë© š­â¥àä¥©á Greenstone âà¥¡ã¥â Perl, çâ®¡ë š¬¥âì ¢®§¬®Š­®áâì
+    if "%GLILANG%" == "ru" echo à ¡®â âì, ­® Perl ­¥ ¡ë« ¢ ¢ è¥© ášáâ¥¬¥. ®Š «ã©áâ , ¯®€â¢¥à€šâ¥,
+    if "%GLILANG%" == "ru" echo çâ® Perl ãáâ ­®¢«¥­ š ­ å®€šâáï ­  ¢ è¥¬ ¯ãâš ¯®šáª , § â¥¬
+    if "%GLILANG%" == "ru" echo ¯®¢â®à­®¢¢¥€šâ¥ íâ®â áªàš¯â.
+    goto exit
+
+
+:findJava
+:: ---- Check Java exists ----
+set JAVAPATH=
+
+:: Some users may set the above line manually
+if not "%JAVAPATH%" == "" goto testJava
+
+    :: If it is set, use the JAVA_HOME environment variable
+    if not "%JAVA_HOME%" == "" goto javahome
+
+    :: Check if Java is on the search path
+    echo %PATH%| winutil\which.exe java.exe | winutil\setvar.exe JAVAPATH > setjava.bat
+    call setjava.bat
+    del setjava.bat
+    if not "%JAVAPATH%" == "" goto testJava
+
+    :: Still haven't found anything, so try looking in the registry (gulp!)
+    type nul > jdk.reg
+    regedit /E jdk.reg "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit"
+    type jdk.reg > jdk.txt
+    del jdk.reg
+    type nul > jre.reg
+    regedit /E jre.reg "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment"
+    type jre.reg > jre.txt
+    del jre.reg
+
+    winutil\findjava.exe jdk.txt jre.txt | winutil\setvar.exe JAVAPATH > setjava.bat
+    del jdk.txt
+    del jre.txt
+    call setjava.bat
+    del setjava.bat
+
+    :: If nothing was found in the registry, we're stuck
+    if "%JAVAPATH%" == "" goto noJava
+
+    set JAVAPATH=%JAVAPATH%\bin
+    goto testJava
+
+:javahome
+    set JAVAPATH=%JAVA_HOME%\bin
+
+:testJava
+:: Check that a Java executable has been found
+if "%GLILANG%" == "en" echo Checking Java: %JAVAPATH%
+if "%GLILANG%" == "es" echo Revisando Java: %JAVAPATH%
+if "%GLILANG%" == "fr" echo Vrification de Java: %JAVAPATH%
+if "%GLILANG%" == "ru" echo à®¢¥àª  Java: %JAVAPATH%
+if exist "%JAVAPATH%\java.exe" goto checkGLI
+
+:noJava
+    echo.
+    if "%GLILANG%" == "en" echo Failed to locate an appropriate version of Java. You must install a
+    if "%GLILANG%" == "en" echo Java Runtime Environment (version 1.4 or greater) before running the
+    if "%GLILANG%" == "en" echo Greenstone Librarian Interface.
+
+    if "%GLILANG%" == "es" echo No se pudo localizar una versi¢n apropiada de Java. Usted deber 
+    if "%GLILANG%" == "es" echo instalar un Ambiente de Ejecuci¢n Java (versi¢n 1.4 o superior)
+    if "%GLILANG%" == "es" echo antes de correr la Interfaz de la Biblioteca Digital Greenstone.
+
+    if "%GLILANG%" == "fr" echo Une version adquate de Java n'a pas pu tre localise. Vous devez
+    if "%GLILANG%" == "fr" echo installer un Java Runtime Environment (version 1.4 ou suprieur)
+    if "%GLILANG%" == "fr" echo avant de dmarrer Greenstone Librarian Interface.
+
+    if "%GLILANG%" == "ru" echo ¥ ã€ «®áì ®¯à¥€¥«šâì ¬¥áâ®­ å®Š€¥­š¥ á®®â¢¥âáâ¢ãîé¥© ¢¥àášš Java.
+    if "%GLILANG%" == "ru" echo ë €®«Š­ë ãáâ ­®¢šâì Java Runtime Environment (¢¥àášî 1.4 š«š ¢ëè¥) ¯¥à¥€ ¢¢®€®¬
+    if "%GLILANG%" == "ru" echo ¡š¡«š®â¥ç­®£® š­â¥àä¥©á  Greenstone.
+    goto exit
+
+
+:checkGLI
+:: ---- Check that the GLI has been compiled ----
+if exist "classes/org/greenstone/gatherer/Gatherer.class" goto runGLI
+if exist "GLI.jar" goto runGLI
+    echo.
+    if "%GLILANG%" == "en" echo You need to compile the Greenstone Librarian Interface (using makegli.bat)
+    if "%GLILANG%" == "en" echo before running this script.
+
+    if "%GLILANG%" == "es" echo Usted necesita compilar la Interfaz de la Biblioteca Digital Greenstone
+    if "%GLILANG%" == "es" echo (por medio de makegli.bat) antes de ejecutar este gui¢n.
+
+    if "%GLILANG%" == "fr" echo Vous devez compiler le Greenstone Interface (en utilisant makegli.bat)
+    if "%GLILANG%" == "fr" echo avant d'excuter ce script.
+
+    if "%GLILANG%" == "ru" echo ë €®«Š­ë ª®¬¯š«šà®¢ âì ¡š¡«š®â¥ç­ë© š­â¥àä¥©á Greenstone (šá¯®«ì§ãï makegli.bat)
+    if "%GLILANG%" == "ru" echo ¯¥à¥€ ¢¢®€®¬ íâ®£® áªàš¯â 
+    goto exit
+
+
+:runGLI
+:: ---- Finally, run the GLI ----
+echo.
+
+if "%GLILANG%" == "en" echo Running the Greenstone Librarian Interface...
+if "%GLILANG%" == "es" echo Ejecutando la Interfaz de la Biblioteca Digital Greenstone...
+if "%GLILANG%" == "fr" echo Excution de Greenstone Librarian Interface
+if "%GLILANG%" == "ru" echo ¥ªãéš© ¡š¡«š®â¥ç­ë© š­â¥àä¥©á Greenstone...
+
+:: -Xms32M          To set minimum memory
+:: -Xmx32M          To set maximum memory
+:: -verbose:gc      To set garbage collection messages
+:: -Xincgc          For incremental garbage collection
+:: -Xprof           Function call profiling
+:: -Xloggc:<file>   Write garbage collection log
+
+if exist "%GSDLHOME%\server.exe" goto localLib 
+
+:webLib
+    "%JAVAPATH%\java" -Xmx128M -cp classes/;GLI.jar;lib/apache.jar;lib/qfslib.jar org.greenstone.gatherer.GathererProg -gsdl %GSDLHOME% -gsdlos %GSDLOS% -perl %PERLPATH% %1 %2 %3 %4 %5 %6 %7 %8 %9
+
+    if ERRORLEVEL 2 goto webLib
+
+    if "%GLILANG%" == "en" echo Done!
+    if "%GLILANG%" == "es" echo ­Hecho!
+    if "%GLILANG%" == "fr" echo Termin!
+    if "%GLILANG%" == "ru" echo ë¯®«­¥­®!
+    goto done
+
+:localLib
+    "%JAVAPATH%\java" -Xmx128M -cp classes/;GLI.jar;lib/apache.jar;lib/qfslib.jar org.greenstone.gatherer.GathererProg -gsdl %GSDLHOME% -gsdlos %GSDLOS% -perl %PERLPATH% -local_library %GSDLHOME%\server.exe %1 %2 %3 %4 %5 %6 %7 %8 %9
+
+    if ERRORLEVEL 2 goto localLib
+
+    if "%GLILANG%" == "en" echo Done!
+    if "%GLILANG%" == "es" echo ­Hecho!
+    if "%GLILANG%" == "fr" echo Termin!
+    if "%GLILANG%" == "ru" echo ë¯®«­¥­®!
+    goto done
+
+:exit
+echo.
+pause
+
+:done
+:: ---- Clean up ----
+set PERLPATH=
+set JAVAPATH=
Index: /tags/greenstone-3_02-distribution/gli/gli.sh
===================================================================
--- /tags/greenstone-3_02-distribution/gli/gli.sh	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/gli.sh	(revision 13928)
@@ -0,0 +1,293 @@
+#!/bin/sh
+glilang=en
+
+echo
+if [ "$glilang" = "es" ]; then
+    echo "Interfaz de la Biblioteca Digital Greenstone (Greenstone Librarian Interface - GLI)"
+    echo "Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato"
+    echo "La Interfaz de la Biblioteca Digital Greenstone NO INCLUYE ABSOLUTAMENTE NINGUNA GARANTÍA."
+    echo "Para mayor información vea los términos de la licencia en LICENSE.txt"
+    echo "Este es un software abierto, por lo que lo invitamos a que lo distribuya de forma gratuita"
+elif [ "$glilang" = "fr" ]; then
+    echo "Interface du Bibliothécaire Greenstone (Greenstone Librarian Interface - GLI)"
+    echo "Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato"
+    echo "GLI est fourni sans AUCUNE GARANTIE; pour des détails, voir LICENSE.txt"
+    echo "Ceci est un logiciel libre, et vous êtes invité à le redistribuer"
+elif [ "$glilang" = "ru" ]; then
+    echo "âÉÂÌÉÏÔÅÞÎÙÊ ÉÎÔÅÒÆÅÊÓ Greenstone (Greenstone Librarian Interface - GLI)"
+    echo "Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato"
+    echo "âéç ÎÅ ÄÁÅÔ áâóïìàôîï îéëáëéè çáòáîôéê; ÄÅÔÁÌÉ ÓÍ. × ÔÅËÓÔÅ LICENSE.TXT"
+    echo "üÔÏ - Ó×ÏÂÏÄÎÏ ÒÁÓÐÒÏÓÔÒÁÎÑÅÍÏÅ ÐÒÏÇÒÁÍÍÎÏÅ ÏÂÅÓÐÅÞÅÎÉÅ É ÷Ù ÍÏÖÅÔÅ ÒÁÓÐÒÏÓÔÒÁÎÑÔØ ÅÇÏ"
+else
+    echo "Greenstone Librarian Interface (GLI)"
+    echo "Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato"
+    echo "GLI comes with ABSOLUTELY NO WARRANTY; for details see LICENSE.txt"
+    echo "This is free software, and you are welcome to redistribute it"
+fi
+echo
+
+##  -------- Run the Greenstone Librarian Interface --------
+
+# This script must be run from within the directory in which it lives
+thisdir=`pwd`
+if [ ! -f "${thisdir}/gli.sh" ]; then
+    if [ "$glilang" = "es" ]; then
+        echo "Este guión deberá ejecutarse desde el directorio en el que reside."
+    elif [ "$glilang" = "fr" ]; then
+	echo "Ce script doit être exécuté à partir du répertoire dans lequel il se trouve."
+    elif [ "$glilang" = "ru" ]; then
+	echo "üÔÏÔ ÓËÒÉÐÔ ÄÏÌÖÅÎ ÂÙÔØ ×ÚÑÔ ÉÚ ÄÉÒÅËÔÏÒÉÉ, × ËÏÔÏÒÏÊ ÏÎ ÒÁÓÐÏÌÏÖÅÎ"
+    else
+	echo "This script must be run from the directory in which it resides."
+    fi
+    exit 1
+fi
+
+
+##  ---- Determine GSDLHOME ----
+gsdlpath=
+
+# Some users may set the above line manually
+if [ "x$gsdlpath" = "x" ]; then
+    # Check the environment variable first
+    if [ "x$GSDLHOME" != "x" ]; then
+	gsdlpath=$GSDLHOME
+
+    # If it is not set, assume that the GLI is installed as a subdirectory of Greenstone
+    else
+	gsdlpath=`(cd .. && pwd)`
+    fi
+fi
+
+# Check that the Greenstone installation looks OK
+if [ "$glilang" = "es" ]; then
+    echo "Revisando GSDL: $gsdlpath"
+elif [ "$glilang" = "fr" ]; then
+    echo "Vérification de GSDL: $gsdlpath"
+elif [ "$glilang" = "ru" ]; then
+    echo "ðÒÏ×ÅÒËÁ GSDL: $gsdlpath"
+else
+    echo "Checking GSDL: $gsdlpath"
+fi
+if [ ! -f "${gsdlpath}/setup.bash" ] ; then
+    echo
+    if [ "$glilang" = "es" ]; then
+	echo "No se pudo encontrar la instalación de Greenstone o está incompleta."
+        echo "Trate de reinstalar Greenstone y a continuación ejecute nuevamente"
+	echo "este guión."
+    elif [ "$glilang" = "fr" ]; then
+	echo "L'installation de Greenstone est introuvable ou incomplète."
+	echo "Essayez de réinstaller Greenstone et exécutez ce script à nouveau."
+    elif [ "$glilang" = "ru" ]; then
+	echo "éÎÓÔÁÌÌÑÃÉÑ Greenstone ÎÅ ÂÙÌÁ ÎÁÊÄÅÎÁ ÉÌÉ ÏÎÁ ÎÅÐÏÌÎÁ."
+	echo "ðÏÐÒÏÂÕÊÔÅ ÐÏ×ÔÏÒÎÏ ÕÓÔÁÎÏ×ÉÔØ Greenstone, Á ÚÁÔÅÍ ××ÅÓÔÉ ÜÔÏÔ ÓËÒÉÐÔ ÓÎÏ×Á."
+    else
+	echo "The Greenstone installation could not be found, or is incomplete."
+	echo "Try reinstalling Greenstone then running this script again."
+    fi
+    exit 1
+fi
+
+# Setup Greenstone, unless it has already been done
+if [ "x$GSDLHOME" = "x" ]; then
+    cd "$gsdlpath"
+    . setup.bash
+    cd "$thisdir"
+fi
+
+
+##  ---- Check Perl exists ----
+perlpath=
+
+# Some users may set the above line manually
+if [ "x$perlpath" = "x" ]; then
+    # Check if Perl is on the search path
+    perlpath=`which perl 2> /dev/null`
+fi
+
+# Check that a Perl executable has been found
+if [ "$glilang" = "es" ]; then
+    echo "Revisando Perl: $perlpath"
+elif [ "$glilang" = "fr" ]; then
+    echo "Vérification de Perl: $perlpath"
+elif [ "$glilang" = "ru" ]; then
+    echo "ðÒÏ×ÅÒËÁ Perl: $perlpath"
+else
+    echo "Checking Perl: $perlpath"
+fi
+if [ ! -x "$perlpath" ] ; then
+    echo
+    if [ "$glilang" = "es" ]; then
+	echo "La Interfaz de la Biblioteca Digital Greenstone requiere Perl para "
+	echo "poder operar, pero éste no aparece en su sistema. Por favor asegúrese "
+	echo "de que Perl está instalado y se encuentra en su ruta de búsqueda. A "
+	echo "continuación ejecute nuevamente este guión."
+    elif [ "$glilang" = "fr" ]; then
+	echo "Greenstone Librarian Interface nécessite perl pour son fonctionnement,"
+	echo "mais perl n'a pas pu être détecté dans votre système. Veuillez vous "
+	echo "assurer que perl est installé et est spécifié dans votre chemin de "
+	echo "recherche, puis redémarrez ce script."
+    elif [ "$glilang" = "ru" ]; then
+	echo "âÉÂÌÉÏÔÅÞÎÙÊ ÉÎÔÅÒÆÅÊÓ Greenstone ÔÒÅÂÕÅÔ Perl, ÞÔÏÂÙ ÉÍÅÔØ ×ÏÚÍÏÖÎÏÓÔØ"
+	echo "ÒÁÂÏÔÁÔØ, ÎÏ Perl ÎÅ ÂÙÌ × ×ÁÛÅÊ ÓÉÓÔÅÍÅ. ðÏÖÁÌÕÊÓÔÁ, ÐÏÄÔ×ÅÒÄÉÔÅ, ÞÔÏ "
+	echo "Perl ÕÓÔÁÎÏ×ÌÅÎ É ÎÁÈÏÄÉÔÓÑ ÎÁ ×ÁÛÅÍ ÐÕÔÉ ÐÏÉÓËÁ, ÚÁÔÅÍ ÐÏ×ÔÏÒÎÏ××ÅÄÉÔÅ"
+	echo "ÜÔÏÔ ÓËÒÉÐÔ."
+    else
+	echo "The Greenstone Librarian Interface requires perl in order to operate,"
+	echo "but perl could not be detected on your system. Please ensure that perl"
+	echo "is installed and is on your search path, then rerun this script."
+    fi
+    exit 1
+fi
+
+
+## ---- Check Java exists ----
+javapath=
+
+# Some users may set the above line manually
+if [ "x$javapath" = "x" ]; then
+
+    # If it is set, use the JAVA_HOME environment variable
+    if [ "x$JAVA_HOME" != "x" ]; then
+	javapath="$JAVA_HOME/bin/java"
+
+    # Check if Java is on the search path
+    else
+	javapath=`which java 2> /dev/null`
+    fi
+fi
+
+# Check that a Java executable has been found
+if [ "$glilang" = "es" ]; then
+    echo "Revisando Java: $javapath"
+elif [ "$glilang" = "fr" ]; then
+    echo "Vérification de Java: $javapath"
+elif [ "$glilang" = "ru" ]; then
+    echo "ðÒÏ×ÅÒËÁ Java: $javapath"
+else
+    echo "Checking Java: $javapath"
+fi
+if [ ! -x "$javapath" ]; then
+    echo
+    if [ "$glilang" = "es" ]; then
+	echo "No se pudo localizar una versión apropiada de Java. Usted deberá "
+	echo "instalar un Ambiente de Ejecución Java (versión 1.4 o superior) "
+	echo "antes de correr la Interfaz de la Biblioteca Digital Greenstone."
+    elif [ "$glilang" = "fr" ]; then
+	echo "Une version adéquate de Java n'a pas pu être localisée."
+	echo "Vous devez installer un Java Runtime Environment (version 1.4 ou"
+	echo "supérieur) avant de démarrer Greenstone Librarian Interface."
+    elif [ "$glilang" = "ru" ]; then
+	echo "îÅ ÕÄÁÌÏÓØ ÏÐÒÅÄÅÌÉÔØ ÍÅÓÔÏÎÁÈÏÖÄÅÎÉÅ ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÅÊ ×ÅÒÓÉÉ Java."
+	echo "÷Ù ÄÏÌÖÎÙ ÕÓÔÁÎÏ×ÉÔØ Java Runtime Environment (×ÅÒÓÉÀ 1.4 ÉÌÉ ×ÙÛÅ)"
+	echo "ÐÅÒÅÄ ××ÏÄÏÍ ÂÉÂÌÉÏÔÅÞÎÏÇÏ ÉÎÔÅÒÆÅÊÓÁ Greenstone."
+    else
+	echo "Failed to locate an appropriate version of Java. You must install a"
+	echo "Java Runtime Environment (version 1.4 or greater) before running the"
+	echo "Greenstone Librarian Interface."
+    fi
+    exit 1
+fi
+
+
+## -- Check the version of Java is new enough (1.4.0 or higher) to run the GLI --
+`$javapath -classpath . CheckJavaVersion > /dev/null`
+if [ $? -ne 2 ] ; then
+    echo
+    if [ "$glilang" = "es" ]; then
+	echo "La versión del Ambiente de Ejecución Java (JRE por sus siglas en "
+	echo "inglés) que usted tiene instalada es demasiado vieja para ejecutar "
+	echo "la Interfaz de la Biblioteca Digital Greenstone. Por favor instale "
+	echo "una nueva versión del Ambiente de Ejecución Java (versión 1.4 o "
+	echo "posterior) y ejecute nuevamente este guión."
+    elif [ "$glilang" = "fr" ]; then
+	echo "La version de Java Runtime Environment que vous avez installée est"
+	echo "trop vielle pour faire fonctionner Greenstone Librarian Interface."
+	echo "Veuillez installer une nouvelle version du JRE (version 1.4 ou plus"
+	echo "récente) et redémarrez le script."
+    elif [ "$glilang" = "ru" ]; then
+	echo "÷ÅÒÓÉÑ Java Runtime Environment, ËÏÔÏÒÕÀ ÷Ù ÕÓÔÁÎÏ×ÉÌÉ, ÏÞÅÎØ ÓÔÁÒÁ,"
+	echo "ÞÔÏÂÙ ÕÐÒÁ×ÌÑÔØ ÂÉÂÌÉÏÔÅÞÎÙÍ ÉÎÔÅÒÆÅÊÓÏÍ Greenstone. ðÏÖÁÌÕÊÓÔÁ, "
+	echo "ÕÓÔÁÎÏ×ÉÔÅ ÎÏ×ÕÀ ×ÅÒÓÉÀ JRE (×ÅÒÓÉÀ 1.4 ÉÌÉ ÂÏÌÅÅ ÎÏ×ÕÀ) É"
+	echo "ÐÅÒÅÕÓÔÁÎÏ×ÉÔÅ ÜÔÏÔ ÓËÒÉÐÔ"
+    else
+	echo "The version of the Java Runtime Environment you have installed is too"
+	echo "old to run the Greenstone Librarian Interface. Please install a new"
+	echo "version of the JRE (version 1.4 or newer) and rerun this script."
+    fi
+    exit 1
+fi
+
+## ---- Check that the GLI has been compiled ----
+if [ ! -f "classes/org/greenstone/gatherer/GathererProg.class" ] && [ ! -f "GLI.jar" ]; then
+    echo
+    if [ "$glilang" = "es" ]; then
+	echo "Usted necesita compilar la Interfaz de la Biblioteca Digital Greenstone"
+	echo "(por medio de makegli.sh) antes de ejecutar este guión."
+    elif [ "$glilang" = "fr" ]; then
+	echo "Vous devez compiler le Greenstone Interface (en utilisant makegli.sh)"
+	echo "avant d'exécuter ce script."
+    elif [ "$glilang" = "ru" ]; then
+	echo "÷Ù ÄÏÌÖÎÙ ËÏÍÐÉÌÉÒÏ×ÁÔØ ÂÉÂÌÉÏÔÅÞÎÙÊ ÉÎÔÅÒÆÅÊÓ Greenstone"
+	echo "(ÉÓÐÏÌØÚÕÑ makegli.sh) ÐÅÒÅÄ ××ÏÄÏÍ ÜÔÏÇÏ ÓËÒÉÐÔÁ"
+    else
+	echo "You need to compile the Greenstone Librarian Interface (using makegli.sh)"
+	echo "before running this script."
+    fi
+    exit 1
+fi
+
+## ---- Finally, run the GLI ----
+echo
+if [ "$glilang" = "es" ]; then
+    echo "Ejecutando la Interfaz de la Biblioteca Digital Greenstone..."
+elif [ "$glilang" = "fr" ]; then
+    echo "Exécution de Greenstone Librarian Interface"
+elif [ "$glilang" = "ru" ]; then
+    echo "ôÅËÕÝÉÊ ÂÉÂÌÉÏÔÅÞÎÙÊ ÉÎÔÅÒÆÅÊÓ Greenstone..."
+else
+    echo "Running the Greenstone Librarian Interface..."
+fi
+
+stop_gli=0
+while [ "$stop_gli" = "0" ] ; do 
+
+# Other arguments you can provide to GLI to work around memory limitations, or debug
+# -Xms<number>M    To set minimum memory (by default 32MB)
+# -Xmx<number>M    To set maximum memory (by default the nearest 2^n to the total remaining physical memory)
+# -verbose:gc      To set garbage collection messages
+# -Xincgc          For incremental garbage collection (significantly slows performance)
+# -Xprof           Function call profiling
+# -Xloggc:<file>   Write garbage collection log
+
+
+
+  $javapath -Xmx128M -classpath classes/:GLI.jar:lib/apache.jar:lib/qfslib.jar org.greenstone.gatherer.GathererProg -gsdl $GSDLHOME -gsdlos $GSDLOS $*
+  exit_status=$?
+
+  if [ "$exit_status" != "2" ] ; then
+    stop_gli=1
+  else
+    echo
+    if [ "$glilang" = "es" ]; then
+        echo "Restarting/Ejecutando la Interfaz de la Biblioteca Digital Greenstone..."
+    elif [ "$glilang" = "fr" ]; then
+        echo "Restarting/Exécution de Greenstone Librarian Interface"
+    elif [ "$glilang" = "ru" ]; then
+        echo "Restarting/ôÅËÕÝÉÊ ÂÉÂÌÉÏÔÅÞÎÙÊ ÉÎÔÅÒÆÅÊÓ Greenstone..."
+    else
+        echo "Restarting the Greenstone Librarian Interface..."
+    fi
+
+  fi
+done 
+
+if [ "$glilang" = "es" ]; then
+    echo "¡Hecho!"
+elif [ "$glilang" = "fr" ]; then
+    echo "Terminé!"
+elif [ "$glilang" = "ru" ]; then
+    echo "÷ÙÐÏÌÎÅÎÏ!"
+else
+    echo "Done!"
+fi
Index: /tags/greenstone-3_02-distribution/gli/gli4gs3.bat
===================================================================
--- /tags/greenstone-3_02-distribution/gli/gli4gs3.bat	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/gli4gs3.bat	(revision 13928)
@@ -0,0 +1,328 @@
+@echo off
+set GLILANG=en
+
+
+::  -------- Run the Greenstone Librarian Interface --------
+
+:: This script must be run from within the directory in which it lives
+if exist gli4gs3.bat goto start
+    if "%GLILANG%" == "en" echo This script must be run from the directory in which it resides.
+    if "%GLILANG%" == "es" echo Este gui¢n deber  ejecutarse desde el directorio en el que reside.
+    if "%GLILANG%" == "fr" echo Ce script doit tre excut 
+ partir du rpertoire dans lequel il se trouve.
+    if "%GLILANG%" == "ru" echo â®â áªàš¯â €®«Š¥­ ¡ëâì ¢§ïâ š§ €šà¥ªâ®àšš, ¢ ª®â®à®© ®­ à á¯®«®Š¥­
+    goto exit
+
+:start
+if "%OS%" == "Windows_NT" goto findGSDL3
+    :: Invoke a new command processor to ensure there's enough environment space
+    if "%1" == "Second" goto findGSDL3
+        command /E:2048 /C %0 Second %1 %2 %3 %4 %5 %6 %7 %8 %9
+        goto done
+
+:findGSDL3
+echo.
+if "%GLILANG%" == "en" echo Greenstone Librarian Interface (GLI)
+if "%GLILANG%" == "en" echo Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato
+if "%GLILANG%" == "en" echo GLI comes with ABSOLUTELY NO WARRANTY; for details see LICENSE.txt
+if "%GLILANG%" == "en" echo This is free software, and you are welcome to redistribute it
+
+if "%GLILANG%" == "es" echo Interfaz de la Biblioteca Digital Greenstone (Greenstone Librarian Interface - GLI)
+if "%GLILANG%" == "es" echo Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato
+if "%GLILANG%" == "es" echo La Interfaz de la Biblioteca Digital Greenstone NO INCLUYE ABSOLUTAMENTE NINGUNA GARANTÖA.
+if "%GLILANG%" == "es" echo Para mayor informaci¢n vea los trminos de la licencia en LICENSE.txt
+if "%GLILANG%" == "es" echo Este es un software abierto, por lo que lo invitamos a que lo distribuya de forma gratuita
+
+if "%GLILANG%" == "fr" echo Interface du Bibliothcaire Greenstone (Greenstone Librarian Interface - GLI)
+if "%GLILANG%" == "fr" echo Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato
+if "%GLILANG%" == "fr" echo GLI est fourni sans AUCUNE GARANTIE; pour des dtails, voir LICENSE.txt
+if "%GLILANG%" == "fr" echo Ceci est un logiciel libre, et vous tes invit 
+ le redistribuer
+
+if "%GLILANG%" == "ru" echo š¡«š®â¥ç­ë© š­â¥àä¥©á Greenstone (Greenstone Librarian Interface - GLI)
+if "%GLILANG%" == "ru" echo Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato
+if "%GLILANG%" == "ru" echo  ­¥ € ¥â   ; €¥â «š á¬. ¢ â¥ªáâ¥ LICENSE.TXT
+if "%GLILANG%" == "ru" echo â® - á¢®¡®€­® à á¯à®áâà ­ï¥¬®¥ ¯à®£à ¬¬­®¥ ®¡¥á¯¥ç¥­š¥ š ë ¬®Š¥â¥ à á¯à®áâà ­ïâì ¥£®
+
+echo.
+::  ---- Determine GSDL3HOME ----
+set GSDL3PATH=%GSDL3PATH%
+
+:: Some users may set the above line manually, or it may be set as an argument
+if not "%GSDL3PATH%" == "" goto testGSDL3
+
+    :: The default location for the GLI is a subdirectory of Greenstone 3
+    set GSDL3PATH=..
+
+    :: If it is set, use the GSDL3HOME environment variable
+    if "%GSDL3SRCHOME%" == "" goto testGSDL3
+	set GSDL3PATH=%GSDL3SRCHOME%
+
+:testGSDL3
+:: Check that the Greenstone 3 installation looks OK
+if "%GLILANG%" == "en" echo Checking GSDL3: %GSDL3PATH%
+if "%GLILANG%" == "es" echo Revisando GSDL3: %GSDL3PATH%
+if "%GLILANG%" == "fr" echo Vrification de GSDL3: %GSDL3PATH%
+if "%GLILANG%" == "ru" echo à®¢¥àª  GSDL3: %GSDL3PATH%
+if exist "%GSDL3PATH%\gs3-setup.bat" goto prepGSDL3
+    echo.
+    if "%GLILANG%" == "en" echo The Greenstone 3 installation could not be found, or is incomplete.
+    if "%GLILANG%" == "en" echo Try reinstalling Greenstone 3 then running this script again.
+
+    if "%GLILANG%" == "es" echo No se pudo encontrar la instalaci¢n de Greenstone 3 o est  incompleta.
+    if "%GLILANG%" == "es" echo Trate de reinstalar Greenstone 3 y a continuaci¢n ejecute nuevamente este gui¢n.
+
+    if "%GLILANG%" == "fr" echo L'installation de Greenstone 3 est introuvable ou incomplte. Essayez
+    if "%GLILANG%" == "fr" echo de rinstaller Greenstone 3 et excutez ce script 
+ nouveau.
+
+    if "%GLILANG%" == "ru" echo ­áâ ««ïæšï Greenstone 3 ­¥ ¡ë«  ­ ©€¥­  š«š ®­  ­¥¯®«­ . ®¯à®¡ã©â¥ ¯®¢â®à­®
+    if "%GLILANG%" == "ru" echo ãáâ ­®¢šâì Greenstone, 3   § â¥¬ ¢¢¥áâš íâ®â áªàš¯â á­®¢ .
+    goto exit
+
+:prepGSDL3
+:: Setup Greenstone 3, unless it has already been done
+if not "%GSDL3SRCHOME%" == "" goto doneGSDL3
+    cd | winutil\setvar.exe GLIDIR > setgli.bat
+    call setgli.bat
+    del setgli.bat
+    cd "%GSDL3PATH%"
+    call gs3-setup.bat SetEnv > nul
+    cd %GLIDIR%
+
+:doneGSDL3
+:: GSDL3PATH is no longer needed, since GSDL3HOME should now be set
+set GSDL3PATH=
+
+
+::  ---- Determine GSDLHOME ----
+set GSDLPATH=%GSDLPATH%
+
+:: Some users may set the above line manually, or it may be set in the environment
+if not "%GSDLPATH%" == "" goto testGSDL
+
+    :: The default location for Greenstone is a gs2build subdirectory of Greenstone 3
+    set GSDLPATH=%GSDL3SRCHOME%\gs2build
+
+    :: If it is set, use the GSDLHOME environment variable
+    if "%GSDLHOME%" == "" goto testGSDL
+	set GSDLPATH=%GSDLHOME%
+
+:testGSDL
+:: Check that the Greenstone installation looks OK
+if "%GLILANG%" == "en" echo Checking GSDL: %GSDLPATH%
+if "%GLILANG%" == "es" echo Revisando GSDL: %GSDLPATH%
+if "%GLILANG%" == "fr" echo Vrification de GSDL: %GSDLPATH%
+if "%GLILANG%" == "ru" echo à®¢¥àª  GSDL: %GSDLPATH%
+if exist "%GSDLPATH%\setup.bat" goto prepGSDL
+    echo.
+    if "%GLILANG%" == "en" echo The Greenstone installation could not be found, or is incomplete.
+    if "%GLILANG%" == "en" echo Try reinstalling Greenstone then running this script again.
+
+    if "%GLILANG%" == "es" echo No se pudo encontrar la instalaci¢n de Greenstone o est  incompleta.
+    if "%GLILANG%" == "es" echo Trate de reinstalar Greenstone y a continuaci¢n ejecute nuevamente este gui¢n.
+
+    if "%GLILANG%" == "fr" echo L'installation de Greenstone est introuvable ou incomplte. Essayez
+    if "%GLILANG%" == "fr" echo de rinstaller Greenstone et excutez ce script 
+ nouveau.
+
+    if "%GLILANG%" == "ru" echo ­áâ ««ïæšï Greenstone ­¥ ¡ë«  ­ ©€¥­  š«š ®­  ­¥¯®«­ . ®¯à®¡ã©â¥ ¯®¢â®à­®
+    if "%GLILANG%" == "ru" echo ãáâ ­®¢šâì Greenstone,   § â¥¬ ¢¢¥áâš íâ®â áªàš¯â á­®¢ .
+    goto exit
+
+:prepGSDL
+:: Setup Greenstone, unless it has already been done
+if not "%GSDLHOME%" == "" goto doneGSDL
+    call "%GSDLPATH%\setup.bat" SetEnv > nul
+
+:doneGSDL
+:: GSDLPATH is no longer needed, since GSDLHOME should now be set
+set GSDLPATH=
+
+
+:findPerl
+::  ---- Check Perl exists ----
+set PERLPATH=
+
+:: Some users may set the above line manually
+if not "%PERLPATH%" == "" goto testPerl
+
+    :: Check if Perl is on the search path
+    echo %PATH%| winutil\which.exe perl.exe | winutil\setvar.exe PERLPATH > setperl.bat
+    call setperl.bat
+    del setperl.bat
+    if not "%PERLPATH%" == "" goto testPerl
+
+    :: If not, try GSDLHOME\bin\windows\perl\bin
+    if exist "%GSDLHOME%\bin\windows\perl\bin\perl.exe" goto gsdlPerl
+
+    :: Still haven't found anything, so try looking in the registry (gulp!)
+    type nul > perl.reg
+    regedit /E perl.reg "HKEY_LOCAL_MACHINE\SOFTWARE\Perl"
+    type perl.reg > perl.txt
+    del perl.reg
+
+    winutil\findperl.exe perl.txt | winutil\setvar.exe PERLPATH > setperl.bat
+    del perl.txt
+    call setperl.bat
+    del setperl.bat
+
+    :: If nothing was found in the registry, we're stuck
+    if "%PERLPATH%" == "" goto noPerl
+
+    goto testPerl
+
+:gsdlPerl
+    set PERLPATH=%GSDLHOME%\bin\windows\perl\bin
+
+:testPerl
+:: Check that a Perl executable has been found
+if "%GLILANG%" == "en" echo Checking Perl: %PERLPATH%
+if "%GLILANG%" == "es" echo Revisando Perl: %PERLPATH%
+if "%GLILANG%" == "fr" echo Vrification de Perl: %PERLPATH%
+if "%GLILANG%" == "ru" echo à®¢¥àª  Perl: %PERLPATH%
+if exist "%PERLPATH%\perl.exe" goto findJava
+
+:noPerl
+    echo.
+    if "%GLILANG%" == "en" echo The Greenstone Librarian Interface requires perl in order to operate,
+    if "%GLILANG%" == "en" echo but perl could not be detected on your system. Please ensure that perl
+    if "%GLILANG%" == "en" echo is installed and is on your search path, then rerun this script.
+
+    if "%GLILANG%" == "es" echo La Interfaz de la Biblioteca Digital Greenstone requiere Perl para poder
+    if "%GLILANG%" == "es" echo operar, pero ste no aparece en su sistema. Por favor aseg£rese de
+    if "%GLILANG%" == "es" echo que Perl est  instalado y se encuentra en su ruta de b£squeda.
+    if "%GLILANG%" == "es" echo A continuaci¢n ejecute nuevamente este gui¢n.
+
+    if "%GLILANG%" == "fr" echo Greenstone Librarian Interface ncessite perl pour son fonctionnement,
+    if "%GLILANG%" == "fr" echo mais perl n'a pas pu tre dtect dans votre systme. Veuillez vous 
+    if "%GLILANG%" == "fr" echo assurer que perl est install et est spcifi dans votre chemin de 
+    if "%GLILANG%" == "fr" echo recherche, puis redmarrez ce script.
+
+    if "%GLILANG%" == "ru" echo š¡«š®â¥ç­ë© š­â¥àä¥©á Greenstone âà¥¡ã¥â Perl, çâ®¡ë š¬¥âì ¢®§¬®Š­®áâì
+    if "%GLILANG%" == "ru" echo à ¡®â âì, ­® Perl ­¥ ¡ë« ¢ ¢ è¥© ášáâ¥¬¥. ®Š «ã©áâ , ¯®€â¢¥à€šâ¥,
+    if "%GLILANG%" == "ru" echo çâ® Perl ãáâ ­®¢«¥­ š ­ å®€šâáï ­  ¢ è¥¬ ¯ãâš ¯®šáª , § â¥¬
+    if "%GLILANG%" == "ru" echo ¯®¢â®à­®¢¢¥€šâ¥ íâ®â áªàš¯â.
+    goto exit
+
+
+:findJava
+:: ---- Check Java exists ----
+set JAVAPATH=
+
+:: Some users may set the above line manually
+if not "%JAVAPATH%" == "" goto testJava
+
+    :: If it is set, use the JAVA_HOME environment variable
+    if not "%JAVA_HOME%" == "" goto javahome
+
+    :: Check if Java is on the search path
+    echo %PATH%| winutil\which.exe java.exe | winutil\setvar.exe JAVAPATH > setjava.bat
+    call setjava.bat
+    del setjava.bat
+    if not "%JAVAPATH%" == "" goto testJava
+
+    :: Still haven't found anything, so try looking in the registry (gulp!)
+    type nul > jdk.reg
+    regedit /E jdk.reg "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit"
+    type jdk.reg > jdk.txt
+    del jdk.reg
+    type nul > jre.reg
+    regedit /E jre.reg "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment"
+    type jre.reg > jre.txt
+    del jre.reg
+
+    winutil\findjava.exe jdk.txt jre.txt | winutil\setvar.exe JAVAPATH > setjava.bat
+    del jdk.txt
+    del jre.txt
+    call setjava.bat
+    del setjava.bat
+
+    :: If nothing was found in the registry, we're stuck
+    if "%JAVAPATH%" == "" goto noJava
+
+    set JAVAPATH=%JAVAPATH%\bin
+    goto testJava
+
+:javahome
+    set JAVAPATH=%JAVA_HOME%\bin
+
+:testJava
+:: Check that a Java executable has been found
+if "%GLILANG%" == "en" echo Checking Java: %JAVAPATH%
+if "%GLILANG%" == "es" echo Revisando Java: %JAVAPATH%
+if "%GLILANG%" == "fr" echo Vrification de Java: %JAVAPATH%
+if "%GLILANG%" == "ru" echo à®¢¥àª  Java: %JAVAPATH%
+if exist "%JAVAPATH%\java.exe" goto checkGLI
+
+:noJava
+    echo.
+    if "%GLILANG%" == "en" echo Failed to locate an appropriate version of Java. You must install a
+    if "%GLILANG%" == "en" echo Java Runtime Environment (version 1.4 or greater) before running the
+    if "%GLILANG%" == "en" echo Greenstone Librarian Interface.
+
+    if "%GLILANG%" == "es" echo No se pudo localizar una versi¢n apropiada de Java. Usted deber 
+    if "%GLILANG%" == "es" echo instalar un Ambiente de Ejecuci¢n Java (versi¢n 1.4 o superior)
+    if "%GLILANG%" == "es" echo antes de correr la Interfaz de la Biblioteca Digital Greenstone.
+
+    if "%GLILANG%" == "fr" echo Une version adquate de Java n'a pas pu tre localise. Vous devez
+    if "%GLILANG%" == "fr" echo installer un Java Runtime Environment (version 1.4 ou suprieur)
+    if "%GLILANG%" == "fr" echo avant de dmarrer Greenstone Librarian Interface.
+
+    if "%GLILANG%" == "ru" echo ¥ ã€ «®áì ®¯à¥€¥«šâì ¬¥áâ®­ å®Š€¥­š¥ á®®â¢¥âáâ¢ãîé¥© ¢¥àášš Java.
+    if "%GLILANG%" == "ru" echo ë €®«Š­ë ãáâ ­®¢šâì Java Runtime Environment (¢¥àášî 1.4 š«š ¢ëè¥) ¯¥à¥€ ¢¢®€®¬
+    if "%GLILANG%" == "ru" echo ¡š¡«š®â¥ç­®£® š­â¥àä¥©á  Greenstone.
+    goto exit
+
+
+:checkGLI
+:: ---- Check that the GLI has been compiled ----
+if exist "classes/org/greenstone/gatherer/GathererProg.class" goto runGLI
+if exist "GLI.jar" goto runGLI
+    echo.
+    if "%GLILANG%" == "en" echo You need to compile the Greenstone Librarian Interface (using makegli.bat)
+    if "%GLILANG%" == "en" echo before running this script.
+
+    if "%GLILANG%" == "es" echo Usted necesita compilar la Interfaz de la Biblioteca Digital Greenstone
+    if "%GLILANG%" == "es" echo (por medio de makegli.bat) antes de ejecutar este gui¢n.
+
+    if "%GLILANG%" == "fr" echo Vous devez compiler le Greenstone Interface (en utilisant makegil.bat)
+    if "%GLILANG%" == "fr" echo avant d'excuter ce script.
+
+    if "%GLILANG%" == "ru" echo ë €®«Š­ë ª®¬¯š«šà®¢ âì ¡š¡«š®â¥ç­ë© š­â¥àä¥©á Greenstone (šá¯®«ì§ãï makegli.bat)
+    if "%GLILANG%" == "ru" echo ¯¥à¥€ ¢¢®€®¬ íâ®£® áªàš¯â 
+    goto exit
+
+
+:runGLI
+:: ---- Finally, run the GLI ----
+echo.
+
+if "%GLILANG%" == "en" echo Running the Greenstone Librarian Interface...
+if "%GLILANG%" == "es" echo Ejecutando la Interfaz de la Biblioteca Digital Greenstone...
+if "%GLILANG%" == "fr" echo Excution de Greenstone Librarian Interface
+if "%GLILANG%" == "ru" echo ¥ªãéš© ¡š¡«š®â¥ç­ë© š­â¥àä¥©á Greenstone...
+
+:: -Xms32M          To set minimum memory
+:: -Xmx32M          To set maximum memory
+:: -verbose:gc      To set garbage collection messages
+:: -Xincgc          For incremental garbage collection
+:: -Xprof           Function call profiling
+:: -Xloggc:<file>   Write garbage collection log
+
+"%JAVAPATH%\java" -cp classes/;GLI.jar;lib/apache.jar;lib/qfslib.jar org.greenstone.gatherer.GathererProg -gsdl %GSDLHOME% -gsdlos %GSDLOS% -gsdl3 %GSDL3HOME% -gsdl3src %GSDL3SRCHOME% -perl %PERLPATH% %1 %2 %3 %4 %5 %6 %7 %8 %9
+
+if "%GLILANG%" == "en" echo Done!
+if "%GLILANG%" == "es" echo ­Hecho!
+if "%GLILANG%" == "fr" echo Termin!
+if "%GLILANG%" == "ru" echo ë¯®«­¥­®!
+goto done
+
+:exit
+echo.
+pause
+
+:done
+:: ---- Clean up ----
+set PERLPATH=
+set JAVAPATH=
Index: /tags/greenstone-3_02-distribution/gli/gli4gs3.sh
===================================================================
--- /tags/greenstone-3_02-distribution/gli/gli4gs3.sh	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/gli4gs3.sh	(revision 13928)
@@ -0,0 +1,345 @@
+#!/bin/sh
+glilang=en
+
+echo
+if [ "$glilang" = "es" ]; then
+    echo "Interfaz de la Biblioteca Digital Greenstone (Greenstone Librarian Interface - GLI)"
+    echo "Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato"
+    echo "La Interfaz de la Biblioteca Digital Greenstone NO INCLUYE ABSOLUTAMENTE NINGUNA GARANTÍA."
+    echo "Para mayor información vea los términos de la licencia en LICENSE.txt"
+    echo "Este es un software abierto, por lo que lo invitamos a que lo distribuya de forma gratuita"
+elif [ "$glilang" = "fr" ]; then
+    echo "Interface du Bibliothécaire Greenstone (Greenstone Librarian Interface - GLI)"
+    echo "Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato"
+    echo "GLI est fourni sans AUCUNE GARANTIE; pour des détails, voir LICENSE.txt"
+    echo "Ceci est un logiciel libre, et vous êtes invité à le redistribuer"
+elif [ "$glilang" = "ru" ]; then
+    echo "âÉÂÌÉÏÔÅÞÎÙÊ ÉÎÔÅÒÆÅÊÓ Greenstone (Greenstone Librarian Interface - GLI)"
+    echo "Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato"
+    echo "âéç ÎÅ ÄÁÅÔ áâóïìàôîï îéëáëéè çáòáîôéê; ÄÅÔÁÌÉ ÓÍ. × ÔÅËÓÔÅ LICENSE.TXT"
+    echo "üÔÏ - Ó×ÏÂÏÄÎÏ ÒÁÓÐÒÏÓÔÒÁÎÑÅÍÏÅ ÐÒÏÇÒÁÍÍÎÏÅ ÏÂÅÓÐÅÞÅÎÉÅ É ÷Ù ÍÏÖÅÔÅ ÒÁÓÐÒÏÓÔÒÁÎÑÔØ ÅÇÏ"
+else
+    echo "Greenstone Librarian Interface (GLI)"
+    echo "Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato"
+    echo "GLI comes with ABSOLUTELY NO WARRANTY; for details see LICENSE.txt"
+    echo "This is free software, and you are welcome to redistribute it"
+fi
+echo
+
+##  -------- Run the Greenstone Librarian Interface --------
+
+# This script must be run from within the directory in which it lives
+thisdir=`pwd`
+if [ ! -f "${thisdir}/gli4gs3.sh" ]; then
+    if [ "$glilang" = "es" ]; then
+        echo "Este guión deberá ejecutarse desde el directorio en el que reside."
+    elif [ "$glilang" = "fr" ]; then
+	echo "Ce script doit être exécuté à partir du répertoire dans lequel il se trouve."
+    elif [ "$glilang" = "ru" ]; then
+	echo "üÔÏÔ ÓËÒÉÐÔ ÄÏÌÖÅÎ ÂÙÔØ ×ÚÑÔ ÉÚ ÄÉÒÅËÔÏÒÉÉ, × ËÏÔÏÒÏÊ ÏÎ ÒÁÓÐÏÌÏÖÅÎ"
+    else
+	echo "This script must be run from the directory in which it resides."
+    fi
+    exit 1
+fi
+
+
+##  ---- Determine GSDL3HOME ----
+## may be already set or manually entered here
+gsdl3path=$gsdl3path
+
+# Some users may set the above line manually
+if [ "x$gsdl3path" = "x" ]; then
+    # Check the environment variable first
+    if [ "x$GSDL3SRCHOME" != "x" ]; then
+	gsdl3path=$GSDL3SRCHOME
+
+    # If it is not set, assume that the GLI is installed as a subdirectory of Greenstone 3
+    else
+	gsdl3path=`(cd .. && pwd)`
+    fi
+fi
+
+# Check that the Greenstone 3 installation looks OK
+if [ "$glilang" = "es" ]; then
+    echo "Revisando GSDL3: $gsdl3path"
+elif [ "$glilang" = "fr" ]; then
+    echo "Vérification de GSDL3: $gsdl3path"
+elif [ "$glilang" = "ru" ]; then
+    echo "ðÒÏ×ÅÒËÁ GSDL3: $gsdl3path"
+else
+    echo "Checking GSDL3: $gsdl3path"
+fi
+if [ ! -f "${gsdl3path}/gs3-setup.sh" ] ; then
+    echo
+    if [ "$glilang" = "es" ]; then
+	echo "No se pudo encontrar la instalación de Greenstone 3 o está incompleta."
+        echo "Trate de reinstalar Greenstone 3 y a continuación ejecute nuevamente"
+	echo "este guión."
+    elif [ "$glilang" = "fr" ]; then
+	echo "L'installation de Greenstone 3 est introuvable ou incomplète."
+	echo "Essayez de réinstaller Greenstone 3 et exécutez ce script à nouveau."
+    elif [ "$glilang" = "ru" ]; then
+	echo "éÎÓÔÁÌÌÑÃÉÑ Greenstone 3 ÎÅ ÂÙÌÁ ÎÁÊÄÅÎÁ ÉÌÉ ÏÎÁ ÎÅÐÏÌÎÁ."
+	echo "ðÏÐÒÏÂÕÊÔÅ ÐÏ×ÔÏÒÎÏ ÕÓÔÁÎÏ×ÉÔØ Greenstone 3, Á ÚÁÔÅÍ ××ÅÓÔÉ ÜÔÏÔ ÓËÒÉÐÔ ÓÎÏ×Á."
+    else
+	echo "The Greenstone 3 installation could not be found, or is incomplete."
+	echo "Try reinstalling Greenstone 3 then running this script again."
+    fi
+    exit 1
+fi
+
+# Setup Greenstone 3, unless it has already been done
+if [ "x$GSDL3HOME" = "x" -o "x$GSDL3SRCHOME" = "x" ]; then
+    cd "$gsdl3path"
+    . gs3-setup.sh
+    cd "$thisdir"
+fi
+
+
+##  ---- Determine GSDLHOME ----
+## may be already set, or manually entered here.
+gsdlpath=$gsdlpath
+
+# Some users may set the above line manually
+if [ "x$gsdlpath" = "x" ]; then
+    # Check the environment variable first
+    if [ "x$GSDLHOME" != "x" ]; then
+	gsdlpath=$GSDLHOME
+
+    # If it is not set, assume that the gs2build subdirectory of Greenstone 3 exists
+    else
+	gsdlpath=$GSDL3SRCHOME/gs2build
+    fi
+fi
+
+# Check that the Greenstone installation looks OK
+if [ "$glilang" = "es" ]; then
+    echo "Revisando GSDL: $gsdlpath"
+elif [ "$glilang" = "fr" ]; then
+    echo "Vérification de GSDL: $gsdlpath"
+elif [ "$glilang" = "ru" ]; then
+    echo "ðÒÏ×ÅÒËÁ GSDL: $gsdlpath"
+else
+    echo "Checking GSDL: $gsdlpath"
+fi
+if [ ! -f "${gsdlpath}/setup.bash" ] ; then
+    echo
+    if [ "$glilang" = "es" ]; then
+	echo "No se pudo encontrar la instalación de Greenstone o está incompleta."
+        echo "Trate de reinstalar Greenstone y a continuación ejecute nuevamente"
+	echo "este guión."
+    elif [ "$glilang" = "fr" ]; then
+	echo "L'installation de Greenstone est introuvable ou incomplète."
+	echo "Essayez de réinstaller Greenstone et exécutez ce script à nouveau."
+    elif [ "$glilang" = "ru" ]; then
+	echo "éÎÓÔÁÌÌÑÃÉÑ Greenstone ÎÅ ÂÙÌÁ ÎÁÊÄÅÎÁ ÉÌÉ ÏÎÁ ÎÅÐÏÌÎÁ."
+	echo "ðÏÐÒÏÂÕÊÔÅ ÐÏ×ÔÏÒÎÏ ÕÓÔÁÎÏ×ÉÔØ Greenstone, Á ÚÁÔÅÍ ××ÅÓÔÉ ÜÔÏÔ ÓËÒÉÐÔ ÓÎÏ×Á."
+    else
+	echo "The Greenstone installation could not be found, or is incomplete."
+	echo "Try reinstalling Greenstone then running this script again."
+    fi
+    exit 1
+fi
+
+# Setup Greenstone, unless it has already been done
+if [ "x$GSDLHOME" = "x" ]; then
+    cd "$gsdlpath"
+    . setup.bash
+    cd "$thisdir"
+fi
+
+
+##  ---- Check Perl exists ----
+perlpath=
+
+# Some users may set the above line manually
+if [ "x$perlpath" = "x" ]; then
+    # Check if Perl is on the search path
+    perlpath=`which perl 2> /dev/null`
+fi
+
+# Check that a Perl executable has been found
+if [ "$glilang" = "es" ]; then
+    echo "Revisando Perl: $perlpath"
+elif [ "$glilang" = "fr" ]; then
+    echo "Vérification de Perl: $perlpath"
+elif [ "$glilang" = "ru" ]; then
+    echo "ðÒÏ×ÅÒËÁ Perl: $perlpath"
+else
+    echo "Checking Perl: $perlpath"
+fi
+if [ ! -x "$perlpath" ] ; then
+    echo
+    if [ "$glilang" = "es" ]; then
+	echo "La Interfaz de la Biblioteca Digital Greenstone requiere Perl para "
+	echo "poder operar, pero éste no aparece en su sistema. Por favor asegúrese "
+	echo "de que Perl está instalado y se encuentra en su ruta de búsqueda. A "
+	echo "continuación ejecute nuevamente este guión."
+    elif [ "$glilang" = "fr" ]; then
+	echo "Greenstone Librarian Interface nécessite perl pour son fonctionnement,"
+	echo "mais perl n'a pas pu être détecté dans votre système. Veuillez vous "
+	echo "assurer que perl est installé et est spécifié dans votre chemin de "
+	echo "recherche, puis redémarrez ce script."
+    elif [ "$glilang" = "ru" ]; then
+	echo "âÉÂÌÉÏÔÅÞÎÙÊ ÉÎÔÅÒÆÅÊÓ Greenstone ÔÒÅÂÕÅÔ Perl, ÞÔÏÂÙ ÉÍÅÔØ ×ÏÚÍÏÖÎÏÓÔØ"
+	echo "ÒÁÂÏÔÁÔØ, ÎÏ Perl ÎÅ ÂÙÌ × ×ÁÛÅÊ ÓÉÓÔÅÍÅ. ðÏÖÁÌÕÊÓÔÁ, ÐÏÄÔ×ÅÒÄÉÔÅ, ÞÔÏ "
+	echo "Perl ÕÓÔÁÎÏ×ÌÅÎ É ÎÁÈÏÄÉÔÓÑ ÎÁ ×ÁÛÅÍ ÐÕÔÉ ÐÏÉÓËÁ, ÚÁÔÅÍ ÐÏ×ÔÏÒÎÏ××ÅÄÉÔÅ"
+	echo "ÜÔÏÔ ÓËÒÉÐÔ."
+    else
+	echo "The Greenstone Librarian Interface requires perl in order to operate,"
+	echo "but perl could not be detected on your system. Please ensure that perl"
+	echo "is installed and is on your search path, then rerun this script."
+    fi
+    exit 1
+fi
+
+
+## ---- Check Java exists ----
+javapath=
+
+# Some users may set the above line manually
+if [ "x$javapath" = "x" ]; then
+
+    # If it is set, use the JAVA_HOME environment variable
+    if [ "x$JAVA_HOME" != "x" ]; then
+	javapath="$JAVA_HOME/bin/java"
+
+    # Check if Java is on the search path
+    else
+	javapath=`which java 2> /dev/null`
+    fi
+fi
+
+# Check that a Java executable has been found
+if [ "$glilang" = "es" ]; then
+    echo "Revisando Java: $javapath"
+elif [ "$glilang" = "fr" ]; then
+    echo "Vérification de Java: $javapath"
+elif [ "$glilang" = "ru" ]; then
+    echo "ðÒÏ×ÅÒËÁ Java: $javapath"
+else
+    echo "Checking Java: $javapath"
+fi
+if [ ! -x "$javapath" ]; then
+    echo
+    if [ "$glilang" = "es" ]; then
+	echo "No se pudo localizar una versión apropiada de Java. Usted deberá "
+	echo "instalar un Ambiente de Ejecución Java (versión 1.4 o superior) "
+	echo "antes de correr la Interfaz de la Biblioteca Digital Greenstone."
+    elif [ "$glilang" = "fr" ]; then
+	echo "Une version adéquate de Java n'a pas pu être localisée."
+	echo "Vous devez installer un Java Runtime Environment (version 1.4 ou"
+	echo "supérieur) avant de démarrer Greenstone Librarian Interface."
+    elif [ "$glilang" = "ru" ]; then
+	echo "îÅ ÕÄÁÌÏÓØ ÏÐÒÅÄÅÌÉÔØ ÍÅÓÔÏÎÁÈÏÖÄÅÎÉÅ ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÅÊ ×ÅÒÓÉÉ Java."
+	echo "÷Ù ÄÏÌÖÎÙ ÕÓÔÁÎÏ×ÉÔØ Java Runtime Environment (×ÅÒÓÉÀ 1.4 ÉÌÉ ×ÙÛÅ)"
+	echo "ÐÅÒÅÄ ××ÏÄÏÍ ÂÉÂÌÉÏÔÅÞÎÏÇÏ ÉÎÔÅÒÆÅÊÓÁ Greenstone."
+    else
+	echo "Failed to locate an appropriate version of Java. You must install a"
+	echo "Java Runtime Environment (version 1.4 or greater) before running the"
+	echo "Greenstone Librarian Interface."
+    fi
+    exit 1
+fi
+
+
+## -- Check the version of Java is new enough (1.4.0 or higher) to run the GLI --
+`$javapath -classpath . CheckJavaVersion > /dev/null`
+if [ $? -ne 2 ] ; then
+    echo
+    if [ "$glilang" = "es" ]; then
+	echo "La versión del Ambiente de Ejecución Java (JRE por sus siglas en "
+	echo "inglés) que usted tiene instalada es demasiado vieja para ejecutar "
+	echo "la Interfaz de la Biblioteca Digital Greenstone. Por favor instale "
+	echo "una nueva versión del Ambiente de Ejecución Java (versión 1.4 o "
+	echo "posterior) y ejecute nuevamente este guión."
+    elif [ "$glilang" = "fr" ]; then
+	echo "La version de Java Runtime Environment que vous avez installée est"
+	echo "trop vielle pour faire fonctionner Greenstone Librarian Interface."
+	echo "Veuillez installer une nouvelle version du JRE (version 1.4 ou plus"
+	echo "récente) et redémarrez le script."
+    elif [ "$glilang" = "ru" ]; then
+	echo "÷ÅÒÓÉÑ Java Runtime Environment, ËÏÔÏÒÕÀ ÷Ù ÕÓÔÁÎÏ×ÉÌÉ, ÏÞÅÎØ ÓÔÁÒÁ,"
+	echo "ÞÔÏÂÙ ÕÐÒÁ×ÌÑÔØ ÂÉÂÌÉÏÔÅÞÎÙÍ ÉÎÔÅÒÆÅÊÓÏÍ Greenstone. ðÏÖÁÌÕÊÓÔÁ, "
+	echo "ÕÓÔÁÎÏ×ÉÔÅ ÎÏ×ÕÀ ×ÅÒÓÉÀ JRE (×ÅÒÓÉÀ 1.4 ÉÌÉ ÂÏÌÅÅ ÎÏ×ÕÀ) É"
+	echo "ÐÅÒÅÕÓÔÁÎÏ×ÉÔÅ ÜÔÏÔ ÓËÒÉÐÔ"
+    else
+	echo "The version of the Java Runtime Environment you have installed is too"
+	echo "old to run the Greenstone Librarian Interface. Please install a new"
+	echo "version of the JRE (version 1.4 or newer) and rerun this script."
+    fi
+    exit 1
+fi
+
+## ---- Check that the GLI has been compiled ----
+if [ ! -f "classes/org/greenstone/gatherer/GathererProg.class" ] && [ ! -f "GLI.jar" ]; then
+    echo
+    if [ "$glilang" = "es" ]; then
+	echo "Usted necesita compilar la Interfaz de la Biblioteca Digital Greenstone"
+	echo "(por medio de makegli.sh) antes de ejecutar este guión."
+    elif [ "$glilang" = "fr" ]; then
+	echo "Vous devez compiler le Greenstone Interface (en utilisant makegli.sh)"
+	echo "avant d'exécuter ce script."
+    elif [ "$glilang" = "ru" ]; then
+	echo "÷Ù ÄÏÌÖÎÙ ËÏÍÐÉÌÉÒÏ×ÁÔØ ÂÉÂÌÉÏÔÅÞÎÙÊ ÉÎÔÅÒÆÅÊÓ Greenstone"
+	echo "(ÉÓÐÏÌØÚÕÑ makegli.sh) ÐÅÒÅÄ ××ÏÄÏÍ ÜÔÏÇÏ ÓËÒÉÐÔÁ"
+    else
+	echo "You need to compile the Greenstone Librarian Interface (using makegli.sh)"
+	echo "before running this script."
+    fi
+    exit 1
+fi
+
+## ---- Finally, run the GLI ----
+echo
+if [ "$glilang" = "es" ]; then
+    echo "Ejecutando la Interfaz de la Biblioteca Digital Greenstone..."
+elif [ "$glilang" = "fr" ]; then
+    echo "Exécution de Greenstone Librarian Interface"
+elif [ "$glilang" = "ru" ]; then
+    echo "ôÅËÕÝÉÊ ÂÉÂÌÉÏÔÅÞÎÙÊ ÉÎÔÅÒÆÅÊÓ Greenstone..."
+else
+    echo "Running the Greenstone Librarian Interface..."
+fi
+
+stop_gli=0
+while [ "$stop_gli" = "0" ] ; do 
+
+# Other arguments you can provide to GLI to work around memory limitations, or debug
+# -Xms<number>M    To set minimum memory (by default 32MB)
+# -Xmx<number>M    To set maximum memory (by default the nearest 2^n to the total remaining physical memory)
+# -verbose:gc      To set garbage collection messages
+# -Xincgc          For incremental garbage collection (significantly slows performance)
+# -Xprof           Function call profiling
+# -Xloggc:<file>   Write garbage collection log
+
+    $javapath -Xmx128M -classpath classes/:GLI.jar:lib/apache.jar:lib/qfslib.jar org.greenstone.gatherer.GathererProg -gsdl $GSDLHOME -gsdlos $GSDLOS -gsdl3 $GSDL3HOME -gsdl3src $GSDL3SRCHOME $*
+    exit_status=$?
+
+  if [ "$exit_status" != "2" ] ; then
+    stop_gli=1
+  else
+    echo
+    if [ "$glilang" = "es" ]; then
+        echo "Restarting/Ejecutando la Interfaz de la Biblioteca Digital Greenstone..."
+    elif [ "$glilang" = "fr" ]; then
+        echo "Restarting/Exécution de Greenstone Librarian Interface"
+    elif [ "$glilang" = "ru" ]; then
+        echo "Restarting/ôÅËÕÝÉÊ ÂÉÂÌÉÏÔÅÞÎÙÊ ÉÎÔÅÒÆÅÊÓ Greenstone..."
+    else
+        echo "Restarting the Greenstone Librarian Interface..."
+    fi
+
+  fi
+done 
+
+if [ "$glilang" = "es" ]; then
+    echo "¡Hecho!"
+elif [ "$glilang" = "fr" ]; then
+    echo "Terminé!"
+elif [ "$glilang" = "ru" ]; then
+    echo "÷ÙÐÏÌÎÅÎÏ!"
+else
+    echo "Done!"
+fi
Index: /tags/greenstone-3_02-distribution/gli/help/README.txt
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/README.txt	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/README.txt	(revision 13928)
@@ -0,0 +1,9 @@
+The following notes talk about the English version of the help. They can be adapted for the other languages by substituting the appropraite two-letter code for 'en'.
+
+en/help.xml is the main help file. This is the file that should be edited when modifying the help.
+
+After the XML file has been modified, the HTML versions and index need to be regenerated. This uses XSLT to transform the XML into HTML.
+
+The generate-html.sh script will do this for English. Just run this script in this directory (gli/help). This generates help_index.xml, and *.htm, one page per section of help.
+
+If you want to do it on Windows or for other languages, you'll need to modify the script.
Index: /tags/greenstone-3_02-distribution/gli/help/ar/addingfiles.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/addingfiles.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/addingfiles.htm	(revision 13928)
@@ -0,0 +1,134 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="addingfiles"><font size="5" face="Verdana"><strong>4.4: Ø¥Ø¶Ø§ÙØ© Ù
+ÙÙØ§Øª</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙÙ
+ÙÙ ÙØ³Ø® Ø§ÙÙ
+ÙÙØ§Øª Ø¥ÙÙ Ø§Ù Ù
+Ø¬Ù
+ÙØ¹Ø© ØšØ§ÙØ³Ø­Øš ÙØ§ÙØ§Ø³ÙØ§Ø·Ø ÙØµØšØ­ ØŽÙÙ Ø§ÙÙ
+Ø€ØŽØ± ØšØµÙØ±Ø© ØŽØšØ­ÙØ© ÙÙÙ
+ÙÙ Ø§ÙÙ
+Ø®ØªØ§Ø± (Ø£ÙØ Ù
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±Ø©)0 Ø§Ø³ÙØ· ÙØ°Ø§ Ø§ÙØ§Ø®ØªÙØ§Ø± ÙÙ ØŽØ¬Ø±Ø© Ù
+ÙÙØ§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙØ³Ø®ÙØ§ Ø¥ÙÙ ÙÙØ§ÙØ (Ø§Ø°Ø§ ÙØ§Ù Ø§ÙÙ
+ØµØ¯Ø± ÙÙ ØŽØ¬Ø±Ø© Ù
+Ø³Ø§Ø­Ø© Ø§ÙØ¹Ù
+Ù) Ø£Ù ØªØ­Ø±ÙÙÙØ§ Ø¬Ø§ÙØšÙØ§Ù (Ø§Ø°Ø§ ÙØ§Ù ÙØ°Ø§ Ø§ÙØ£Ù
+Ø± Ø¶Ù
+Ù ÙØ·Ø§Ù ØŽØ¬Ø±Ø© Ù
+ÙÙØ§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©)0</p>
+
+<p>Ø¹ÙØ¯ ÙØ³Ø® Ù
+Ø¬Ù
+ÙØ¹Ø© Ù
+ÙÙØ§ØªØ ØªÙØ¶Ø­ ÙÙÙØ§ ÙÙ Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙÙ
+Ø³ØªÙØ¯Ù ÙÙ ÙÙØ³ Ø§ÙÙ
+Ø³ØªÙÙ ØšØ¯ÙÙ Ø§Ø¹ØªØšØ§Ø± ÙÙØ¶Ø¹ÙØ§ Ø§ÙØ§ØµÙÙ ÙÙ Ø§ÙÙ
+ØµØ¯Ø±0 Ø¹ÙØ¯ ÙØ³Ø® Ù
+ÙÙ ØšÙÙØ³ Ø§ÙØ§Ø³Ù
+ ÙÙ
+ÙÙ ØšØ§ÙÙ
+Ø¬ÙØ¯ Ø§ÙÙ
+Ø³ØªÙØ¯ÙØ Ø³ÙÙ ÙØªÙ
+ Ø§Ø³ØªÙØ³Ø§Ø±Ù  Ø§Ø°Ø§ ÙÙØª ØªÙØ¯ ÙØ³Ø® ÙØ°Ø§ Ø§ÙÙ
+ÙÙ ÙÙÙ ÙÙØ³ Ø§ÙÙ
+ÙÙ Ø§ÙÙ
+ÙØ¬ÙØ¯0 Ø§ÙØ¥Ø¬Ø§ØšØ© ØšÙØ§ ØªØ¹ÙÙ Ø£Ù Ø§ÙÙ
+ÙÙ ÙØ§ ÙÙØ³Ø®Ø ÙÙÙ ÙØªÙ
+ ÙØ³Ø® ØšÙÙØ© Ø§ÙÙ
+ÙÙØ§Øª0 ÙØ§ÙØºØ§Ø¡ ØšÙÙØ© Ø§ÙØ§Ø¬Ø±Ø§Ø¡Ø Ø§ÙÙØ± Ø²Ø± "ØªÙÙÙ"0
+</p>
+
+<p>Ø§ÙØ¹ÙØ§ØµØ± "Ø§ÙØ¹ÙÙØ§ " ÙÙØ· ÙÙ Ø§ÙØ¹ÙØ§ØµØ± Ø§ÙÙ
+Ø®ØªØ§Ø±Ø© ÙÙ Ø§ÙØªÙ ØªÙ
+ ØªØ­ÙÙÙÙØ§ Ø ÙØ¹ØªØšØ± Ø§ÙÙ
+Ø¬ÙØ¯ Ø§Ø¹ÙÙ Ù
+Ù ØªØ¹Ø±ÙÙØ§ØªÙØ ÙØ§ ÙÙ
+ÙÙ Ø§Ø®ØªÙØ§Ø± Ø§ÙÙ
+ÙÙØ§Øª Ø¶Ù
+Ù Ø§ÙÙ
+Ø¬ÙØ¯ Ø£Ù Ø§ÙÙ
+Ø¬ÙØ¯ Ø°Ø§ØªÙ0</p>
+
+<p>ÙÙÙÙ
+ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ Ø¹ÙØ¯ Ø§Ø¶Ø§ÙØ© Ù
+ÙÙ ÙØšØ­Ø« Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª Ø¹Ù Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙØ§Ø¶Ø§ÙÙØ© Ø§ÙØªÙ ØªØªØ¶Ù
+Ù ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+Ø¹ÙÙØ© Ù
+Ù ÙØšÙ ÙÙ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙØ§Ø¶Ø§ÙÙØ©0 ÙØ§Ø°Ø§ ÙØ¬Ø¯ÙØ§ ÙÙÙÙ
+ ØšØ¹Ù
+ÙÙØ© Ø§Ø³ØªÙØ±Ø§Ø¯ ÙÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙØ°Ù Ø®ÙØ§Ù ÙØªØ±Ø© Ø³Ø±ÙØ§Ù Ø§ÙØ¹Ù
+ÙÙØ©Ø Ø³ÙÙ ÙØªÙ
+ Ø­Ø«Ù (Ø±ØšÙ
+Ø§ Ù
+Ø±Ø§Øª Ø¹Ø¯ÙØ¯Ø©) ÙÙ
+Ø²ÙØ¯ Ù
+Ù Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª ÙÙ
+ÙØ§Ø±ØšÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø³ØªÙØ±Ø¯Ø© ÙÙ
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+ØªÙÙØ±Ø© ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©Ø ÙÙØªØ¶Ù
+Ù ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø§Øª Ø­Ø« Ù
+Ø®ØªÙÙØ© Ù
+ÙØµÙÙØ© ÙÙ ÙØ³Ù
+ <a href="importingpreviouslyassignedmetadata.htm">Ø¥Ø³ØªÙØ±Ø§Ø¯ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø© Ø³Ø§ØšÙØ§</a>ÙÙ
+Ø²ÙØ¯ Ù
+Ù Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª Ø­ÙÙ ØªÙØ¶ÙØ­ Ø§Ø¬Ø±Ø§Ø¡Ø§Øª ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+ÙØ­ÙØ©Ø Ø§ÙØ±Ø£ Ø§ÙÙØµÙ Ø§ÙØ«Ø§ÙÙ Ù
+Ù Ø¯ÙÙÙ ÙØ±ÙÙØ³ØªÙÙ ÙÙÙ
+Ø·ÙØ±ÙÙ ØªØ­Øª Ø¹ÙÙØ§Ù Ø§ÙØ¬Ø§Ø¯ Ù
+Ø­ØªÙÙØ§Øª Ø§ÙÙØ«ÙÙØ©0</p>
+
+<p> ÙÙ
+ÙÙÙ Ø§Ø¶Ø§ÙØ© ÙØ«ÙÙØ© "Ù
+Ø²ÙÙØ©" Ø¥ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙÙØ± Ø§ÙØ²Ø± Ø§ÙØ§ÙÙ
+Ù ÙÙ ØŽØ¬Ø±Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø£Ù ÙÙ Ù
+Ø¬ÙØ¯Ø ÙØ§Ø®ØªÙØ§Ø± "ÙØ«ÙÙØ© Ù
+Ø²ÙÙØ© Ø¬Ø¯ÙØ¯Ø©" ÙØ³ÙÙ ÙÙØŽØŠ ÙØ°Ø§ Ù
+ÙÙ Ø¬Ø¯ÙØ¯ ÙØ§Ø±Øº ÙÙ
+ÙÙ ÙÙÙ Ø§Ø¹ØªÙ
+Ø§Ø¯ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§ØªØ ÙÙ
+ÙÙ Ø§Ø³ØªØšØ¯Ø§Ù ÙØ°Ø§ Ø§ÙÙ
+ÙÙ ØšÙ
+ÙÙ "Ø­ÙÙÙÙ" ÙÙÙ
+Ø§ ØšØ¹Ø¯0</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/addingpreviouslydefinedmetadata.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/addingpreviouslydefinedmetadata.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/addingpreviouslydefinedmetadata.htm	(revision 13928)
@@ -0,0 +1,47 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="addingpreviouslydefinedmetadata"><font size="5" face="Verdana"><strong>5.4: Ø¥Ø¶Ø§ÙØ© ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¹Ø±ÙØ© Ø³Ø§ØšÙØ§</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙØ§Ø¶Ø§ÙØ© ÙØ§ØµÙÙ ØšÙØ§ÙØ§Øª Ø¬Ø¯ÙØ¯Ø© ÙØ§Ø®Ø±Ù Ù
+ÙØ¬ÙØ¯Ù Ù
+Ù ÙÙÙ
+Ø© Ø§ÙØ­ÙÙØ Ø§ÙÙØ§Ù ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø§ÙÙ
+ÙÙØ  Ø«Ù
+ Ø§Ø®ØªÙØ§Ø± Ø§ÙÙÙÙ
+Ø© Ø§ÙÙ
+Ø·ÙÙØšØ© Ù
+Ù ØŽØ¬Ø±Ø© Ø§ÙÙÙÙ
+Ø ØªÙØ³ÙØ¹  Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª Ø§ÙÙØ±Ù
+ÙÙ ÙÙÙØ§Ù ÙÙ
+Ø§ ÙÙ Ù
+Ø·ÙÙØšØ Ø³ÙÙ ØªØžÙØ± ØªÙÙØ§ØŠÙØ§Ù ÙÙÙ
+Ø© Ø§ÙÙ
+Ø¯Ø®Ù Ø§ÙÙ
+Ø®ØªØ§Ø± ÙÙ ÙÙÙ
+Ø© Ø§ÙØ­ÙÙ (ØšØ¯ÙØ§ÙØ Ø§Ø³ØªØ®Ø¯Ù
+ Ø§Ø®ØªÙØ§Ø± Ø§ÙÙÙÙ
+ Ø§ÙØªÙÙØ§ØŠÙ ÙØ³Ù
+Ø§Øª Ø§ÙØ§ÙÙØ§Ø¡ Ø§ÙØªÙÙØ§ØŠÙ)0
+ </p>
+
+<p>Ø¥Ø¬Ø±Ø§Ø¡ Ø¥Ø¶Ø§ÙØ© ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+Ø¹ ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+ÙØ¬ÙØ¯Ø© Ù
+Ù ÙØšÙ Ø¥ÙÙ Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª Ø£Ù Ø§ÙÙ
+ÙÙØ§Øª ÙÙ ÙÙØ³ Ø§ÙØ§Ø¬Ø±Ø§Ø¡0</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/appendingmetadata.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/appendingmetadata.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/appendingmetadata.htm	(revision 13928)
@@ -0,0 +1,70 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="appendingmetadata"><font size="5" face="Verdana"><strong>5.3: ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø¬Ø¯ÙØ¯Ø© Ù
+Ø¹ÙÙØ©</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙØ­Ù Ø§ÙØ¢Ù ÙØ¶ÙÙ Ø¹ÙØµØ± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§ØªØ Ø§ÙØ¹ÙØµØ± ÙÙÙÙ
+Ø© Ø§ÙØ¹ÙØµØ± Ø§ÙÙ Ù
+ÙÙ0 Ø§ÙÙØ§Ù ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ù
+ÙÙ Ù
+Ù ØŽØ¬Ø±Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø¹ÙÙ Ø§ÙÙØ³Ø§Ø±Ø ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ ÙØ³ØšØš Ø§Ù Ø§Ù ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+Ø­Ø¯Ø¯Ø© Ù
+Ù ÙØšÙ Ø³ÙÙ ÙØªÙ
+ ØªØ¹ÙÙÙØ§ ÙÙØ°Ø§ Ø§ÙÙ
+ÙÙ ÙØ³ÙÙ ØªØžÙØ± ÙÙ Ø§ÙØ¬Ø¯ÙÙ ÙÙ Ø§ÙØ¬Ø§ÙØš Ø§ÙØ§ÙÙ
+Ù0
+</p>
+
+<p> ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø¹ÙØµØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØ°Ù ØªÙØ¯ Ø§Ø¶Ø§ÙØªÙ ØšÙØ§Ø³Ø·Ø© Ø§ÙÙÙØ± Ø¹ÙÙ Ù
+ÙØ§ÙÙ ÙÙ Ø§ÙØ¬Ø¯ÙÙ0</p>
+
+<p>Ø§Ø·ØšØ¹ Ø§ÙÙÙÙ
+Ø© Ø¯Ø§Ø®Ù Ø§ÙØ­ÙÙ0 Ø§Ø³Ø®Ø¯Ù
+ Ù
+Ø­Ø±Ù "|" ÙØ§Ø¶Ø§ÙØ© Ø§ÙØšÙØ§Ø¡ Ø§ÙÙØ±Ù
+ÙØ ÙÙ
+Ø§ ÙÙ Ù
+ÙØµÙÙ <a href="theenrichview.htm">Ù
+ØŽÙØ¯ Ø¥Ø«Ø±Ø§Ø¡</a>- Ø§ÙØ¶ØºØ· Ø¹ÙÙ Ù
+ÙØ§ØªÙØ­ Ø§Ø³ÙÙ
+ (Ø§Ø¹ÙÙ) Ù (Ø§Ø³ÙÙ) ÙØ­ÙØž ÙÙÙ
+Ø©  ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙØ­Ø±Ù  Ø§ÙØ§Ø®ØªÙØ§Ø± ØšØµÙØ±Ø© Ù
+ÙØ§Ø³ØšØ©0 Ø§ÙØ¶ØºØ· Ø¹ÙÙ Ù
+ÙØªØ§Ø­ [Enter] Ø³ÙÙ ÙØ­ÙØž  ÙÙÙ
+Ø© ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙÙØŽØŠ Ù
+Ø¯Ø®Ù ÙØ§Ø±Øº Ø¬Ø¯ÙØ¯ ÙØ¹ÙØµØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙÙ
+ÙÙÙ Ù
+Ù ØªØ¹ÙÙÙ ÙÙÙ
+ Ù
+ØªØ¹Ø¯Ø¯Ø© ÙØ¹ÙØµØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª0</p>
+
+<p>ÙÙ
+ÙÙÙ Ø£ÙØ¶Ø§Ù Ø§Ø¶Ø§ÙØ© ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø§ÙÙ Ù
+Ø¬ÙØ¯ Ø£Ù Ø§ÙÙ Ù
+ÙÙØ§Øª Ù
+ØªØ¹Ø¯Ø¯Ø© Ù
+Ø®ØªØ§Ø±Ø© ÙØ¥ÙÙ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙØ±Ø¹ÙØ©0 ÙØ¬Øš Ø£Ù ØªØªØ°ÙØ± Ø§Ù ØªØ¹ÙÙÙ ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø¥ÙÙ Ù
+Ø¬ÙØ¯Ø ÙØ¹ÙÙ Ø£Ù ÙØ°Ù Ø§ÙÙØ§ØµÙØ§Øª Ø³ÙÙ ÙØªÙ
+ ØªØ¶Ù
+ÙÙÙØ§ ØªÙÙØ§ØŠÙØ§Ù ÙØ§Ù Ù
+ÙÙØ§Øª Ø¬Ø¯ÙØ¯Ø© Ø¯Ø§Ø®Ù ÙÙÙ
+ ÙØ°Ù Ø§ÙÙ
+Ø¬ÙØ¯0
+</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/assignlanguages.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/assignlanguages.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/assignlanguages.htm	(revision 13928)
@@ -0,0 +1,67 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="assignlanguages"><font size="5" face="Verdana"><strong>6.4.3: ØªØ¹ÙÙÙ ÙØºØ©</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p> ÙÙØµÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ÙÙÙÙØ©  ØªÙÙÙØ¯ ÙØŽØ§ÙØ§Øª Ø§ÙØšØ­Ø« ÙÙØºØ§Øª Ù
+Ø¹ÙÙÙ0 ÙÙ
+ÙÙ Ø§ÙØ¬Ø§Ø²  ÙØ°Ø§ ØšØªÙÙÙØ¯ ÙØ·Ø§Ø¹ Ù
+Ø³ØªØ®Ø¯Ù
+Ø§Ù tab "ØªØ¹ÙÙÙ ÙØºØ§Øª" ÙÙ Ù
+ØŽÙØ¯ "ÙØŽØ§ÙØ§Øª Ø§ÙÙØ·Ø§Ø¹"0</p>
+
+<p>TÙØ§Ø¶Ø§ÙØ© ÙØ·Ø§Ø¹ ÙØºÙÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+ tab "ØªØ¹ÙÙÙ ÙØºØ§Øª" ÙØšÙØ§Ø¡ ÙØŽØ§Ù ÙÙØ§0ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± ÙØºØ© Ø£Ù Ø£ÙØ«Ø± Ù
+Ù ÙØ§ØŠÙ
+Ø© "ÙØºØ§Øª ÙÙØ§Ø¶Ø§ÙØ©" Ø Ø§ÙÙØ± "Ø§Ø¶Ø§ÙØ© ÙØ·Ø§Ø¹ "0</p>
+
+<p>ÙØªØºÙÙØ± ÙØ·Ø§Ø¹ Ù
+ÙØ¬ÙØ¯Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù Ù
+Ù ÙØ§ØŠÙ
+Ø© "ÙØ·Ø§Ø¹Ø§Øª Ø§ÙÙØºØ© Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø©" ÙØªØ¹Ø¯ÙÙ Ø§ÙÙØºØ© Ø§ÙÙ
+Ø®ØªØ§Ø±Ø© Ù
+Ù ÙØ§ØŠÙ
+Ø© "ÙØºØ§Øª ÙÙØ§Ø¶Ø§ÙØ©" ÙÙ Ø§ÙØ§Ø³ÙÙØ ÙØ§ÙÙØ± "Ø§Ø³ØªØšØ¯Ø§Ù ÙØ·Ø§Ø¹"0.</p>
+
+<p>ÙØ­Ø°Ù ÙØºØ© Ø  ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±ÙØ§ Ù
+Ù ÙØ§ØŠÙ
+Ø©  "Ø§Ø®ØªÙØ§Ø± ÙØºØ©"Ø ÙØ§ÙÙØ± "Ø­Ø°Ù ÙØºØ©"0</p>
+
+<p>ØªØ±ØªÙØš ÙØ·Ø§Ø¹Ø§Øª Ø§ÙÙØºØ© Ø§ÙÙ
+Ø­Ø¯Ø¯ ÙÙ ÙØ§ØŠÙ
+Ø© "ÙØ·Ø§Ø¹Ø§Øª Ø§ÙÙØºØ© Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø©" ÙÙ ÙÙØ³ Ø§ÙØªØ±ØªÙØš Ø§ÙØ°Ù ÙØžÙØ± ÙÙ ØªØ§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© ÙÙ ØµÙØ­Ø© Ø§ÙØšØ­Ø«0 Ø§Ø³ØªØ®Ø¯Ù
+ Ø§ÙØ§Ø²Ø±Ø§Ø± "Move Up" and "Move Up"  ÙØªØºÙÙØ± ÙØ°Ø§ Ø§ÙØªØ±ØªÙØš0</p>
+
+<p>ÙØªØ¹ÙÙÙ ÙØ·Ø§Ø¹ Ø§ÙÙØºØ© Ø§ÙØ§ÙØªØ±Ø§Ø¶ÙØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø© ÙØ§ÙÙØ± "ØªØ¹ÙÙÙ Ø§ÙØªØ±Ø§Ø¶Ù"</p>
+
+<p>ÙÙ
+ÙÙ Ø§Ø¹Ø¯Ø§Ø¯  Ø§Ø³Ù
+Ø§Ø¡ Ø§ÙÙØ·Ø§Ø¹Ø§Øª Ø§ÙÙØºÙÙØ©  Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© ÙÙ ØµÙØ­Ø© Ø§ÙØšØ­Ø« ÙÙ "Search" ÙÙÙ Ø¬Ø²Ø¡ Ù
+Ù ÙØ§ÙØªÙ "Format" panel (see <a href="searchmetadatasettings.htm">ØšØ­Ø«</a>).</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/assignpartitions.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/assignpartitions.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/assignpartitions.htm	(revision 13928)
@@ -0,0 +1,68 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="assignpartitions"><font size="5" face="Verdana"><strong>6.4.2: ØªØ¹ÙÙÙ ÙØ·Ø§Ø¹Ø§Øª</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Ø§Ø°Ø§ ÙÙ
+Øª  ØšØªØ¹Ø±ÙÙ Ù
+Ø±ØŽØ­Ø§Øª Ù
+Ø¬Ù
+ÙØ¹Ø© ÙØ±Ø¹ÙØ© ÙØ§Ø­Ø¯Ø© Ø£Ù Ø£ÙØ«Ø±Ø Ø§Ø³ØªØ®Ø¯Ù
+ tab "ØªØ¹ÙÙÙ ÙØ·Ø§Ø¹Ø§Øª" ÙØšÙØ§Ø¡ Ø§ÙÙØŽØ§ÙØ§Øª ÙÙØ§ Ø£Ù ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ù
+Ù Ø§ÙÙ
+Ø±ØŽØ­Ø§Øª)0 ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø§ÙÙ
+Ø±ØŽØ­ Ø£Ù Ø§ÙÙ
+Ø±ØŽØ­Ø§Øª Ø§ÙÙ
+Ø·ÙÙØšØ© Ù
+Ù ÙØ§ØŠÙ
+Ø© "Ù
+Ø±ØŽØ­Ø§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙØ±Ø¹ÙØ© Ø§ÙÙ
+Ø¹Ø±ÙØ©" ÙØ§ÙÙØ± "Ø§Ø¶Ø§ÙØ© ÙØ·Ø§Ø¹"Ø Ø³ÙÙ ÙÙØ¶Ù
+ Ø¥ÙÙ ÙØ·Ø§Ø¹ Ù
+Ø­Ø¯Ø¯ ÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø© ÙØ±Ø¹ÙØ© Ø§ÙÙØ«Ø§ØŠÙ Ø§ÙØªÙ ØªØ¶Ø§ÙÙ Ø§ÙÙ
+Ø±ØŽØ­ Ø§ÙÙ
+Ø¹ÙÙ ÙÙÙØ·Ø§Ø¹0</p>
+
+<p>To alter a partition, select it from the list, modify the filters, and click "Replace Partition".</p>
+
+<p>To remove a partition, select it from the list and click "Remove Partition".</p>
+
+<p>ØªØ±ØªÙØš Ø§ÙÙØ·Ø§Ø¹Ø§Øª Ø§ÙÙ
+Ø­Ø¯Ø¯ ÙÙ ÙØ§ØŠÙ
+Ø© Ø§ÙÙØ·Ø§Ø¹Ø§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø© ÙÙ ÙÙØ³ Ø§ÙØªØ±ØªÙØš Ø§ÙØ°Ù ØªØžÙØ± ØšÙ Ø§ÙÙØ·Ø§Ø¹Ø§Øª ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø©  Ø§ÙÙ
+ÙØ³Ø¯ÙØ© ÙÙ ØµÙØ­Ø© Ø§ÙØšØ­Ø«0 Ø§Ø³ØªØ®Ø¯Ù
+ Ø§ÙØ§Ø²Ø±Ø§Ø± "Move Up" and "Move Up" ÙØªØºÙÙØ± ÙØ°Ø§ Ø§ÙØªØ±ØªÙØš0</p>
+
+<p>ÙØªØ¹ÙÙÙ Ø§ÙÙØ·Ø§Ø¹ Ø§ÙØªØ±Ø§Ø¶ÙØ§ÙØ ÙÙ
+ ØšØ¥Ø®ØªÙØ§Ø± ÙØ§Ø­Ø¯ Ø§ÙÙØ§ØŠÙ
+Ø©Ø ÙØ§ÙÙØ± "ØªØ¹ÙÙÙ Ø§ÙØªØ±Ø§Ø¶Ù"0"Set Default".</p>
+
+<p>ÙÙ
+ÙÙ Ø¥Ø¹Ø¯Ø§Ø¯ Ø§Ø³Ù
+Ø§Ø¡ Ø§ÙÙØ·Ø§Ø¹Ø§Øª Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+Ø© ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© ÙÙ ØµÙØ­Ø© Ø§ÙØšØ­Ø« ÙÙ"Search" ÙÙÙ Ø¬Ø²Ø¡ Ù
+Ù ÙØ§ÙØªÙ "Format" panel (see <a href="searchmetadatasettings.htm">ØšØ­Ø«</a>).</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/builderrors.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/builderrors.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/builderrors.htm	(revision 13928)
@@ -0,0 +1,40 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="builderrors"><font size="5" face="Verdana"><strong>7.2:  Ø§Ø®Ø·Ø§Ø¡ ÙÙ ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Ø§Ø­ÙØ§ÙØ§Ù ÙØ§ ØªÙ
+Ø¶Ù Ø§ÙØ§Ù
+ÙØ± ØšØµÙØ±Ø© Ø³ÙØ³ÙØ© Ø®ÙØ§Ù ØšÙØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø©Ø ÙÙØ¯ ÙØ§ØªØªÙ
+ Ù
+Ø¹Ø§ÙØ¬Ø© ØšØ¹Ø¶ Ø§ÙÙ
+ÙÙØ§ØªØ ÙÙÙÙ ÙÙØªÙ
+Ù ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØšØµÙØ±Ø© Ø³ÙÙÙ
+Ø© ÙÙÙ
+ÙÙ Ø¹Ø±Ø¶ÙØ§ ÙÙÙÙ ØšØºÙØ§Øš ØšØ¹Ø¶ Ø§ÙÙØ«Ø§ØŠÙ 0 Ø£Ù Ø±ØšÙ
+Ø§ ÙØ§ ØªØšÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙÙØ§ ØšØµÙØ±Ø© Ø³ÙÙÙ
+Ø© ÙÙÙ ÙØ°Ù Ø§ÙØ­Ø§ÙØ© ØªØžÙØ± Ø±Ø³Ø§ÙØ© ÙØ­ÙØ§ÙØ§"An error has occurred and the collection could not be created." Ø¹ÙØ¯Ù
+Ø§ ÙØ­Ø¯Ø« ÙØ°Ø§Ø ÙÙÙÙ Ù
+Ù Ø§ÙÙ
+ÙÙØ¯ Ø§ÙØªØ­ÙÙ ÙÙ GLI Ø¥ÙÙ Ø³ÙØ§Ù "Ø®ØšÙØ±" (File-&gt;Preferences-&gt;Mode, see <a href="preferences.htm">Ø§ÙØªÙØ¶ÙÙØ§Øª</a>), ÙÙ
+ ØšØªØ­ÙÙÙ ÙÙÙ
+Ø© Ø®ÙØ§Ø± ÙØšÙØ§Ø¡ "Verbosity) Ø¥ÙÙ 5 ÙØ§Ø¹Ø¯ Ø§ÙØšÙØ§Ø¡ ÙØ±Ø€ÙØ© Ø§Ù Ø±Ø³Ø§ØŠÙ Ø®Ø·Ø£ ØªØžÙØ±0</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/classifiers.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/classifiers.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/classifiers.htm	(revision 13928)
@@ -0,0 +1,117 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="classifiers"><font size="5" face="Verdana"><strong>6.5: Ù
+ØµÙÙØ§Øª Ø§ÙØªØµÙØ­</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ØŽØ±Ø­ ÙÙ ÙØ°Ø§ Ø§ÙÙØµÙ ÙÙÙÙØ© ØªØ¹ÙÙÙ "Ø§ÙÙ
+ØµÙÙØ§Øª" ÙÙÙ Ø§ÙØªÙ ØªØ³ØªØ®Ø¯Ù
+ ÙÙ ØªØµÙØ­ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 ØªØ­Øª tab "ØªØµÙ
+ÙÙ
+" Ø Ø§ÙÙØ± "Ù
+ØµÙÙØ§Øª Ø§ÙØªØµÙØ­"0</p>
+
+<p>ÙØ§Ø¶Ø§ÙØ© Ù
+ØµÙÙØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù Ù
+Ø³ØªØ®Ø¯Ù
+Ø§Ù Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© "Ø§Ø®ØªÙØ§Ø± Ù
+ØµÙÙ ÙÙØ§Ø¶Ø§ÙØ©"  Ø§ÙØ§ÙØ±Øš Ø¥ÙÙ Ø§ÙØ£Ø³ÙÙ Ø«Ù
+ Ø§ÙÙØ± "Ø§Ø¶Ø§ÙØ© Ù
+ØµÙÙ" ØªØžÙØ± ÙÙ ÙØ§ÙØ°Ø© ØšØ¹ÙÙØ§Ù "ØªØ¬ÙÙØ² Ù
+Ø¶Ø§Ù
+ÙÙ" ØªØªÙ
+Ø§Ø«Ù ØªØ¹ÙÙÙ
+Ø§Øª ÙØ°Ù Ø§ÙÙØ§ÙØ°Ø© Ù
+Ø¹ ØªØ¹ÙÙÙ
+Ø§Øª Ø§ÙÙ
+ÙØ§ØšØ³ (see <a href="plugins.htm">Ù
+ÙØ§ØšØ³ Ø§ÙÙØ«ÙÙØ©</a>). ØªØªÙ
+ Ø§Ø¶Ø§ÙØ© Ø§ÙÙ
+ØµÙÙ Ø§ÙØ¬Ø¯ÙØ¯ ØšØ¹Ø¯ ØªØ¬ÙÙØ²Ù Ø£Ø³ÙÙ ÙØ§ØŠÙ
+Ø© &ndash; Ø§ÙÙ
+ØµÙÙØ§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø© Ø­Ø§ÙÙØ§Ù0</p>
+
+<p>ÙØ±Ø€ÙØ© ÙØµÙ ÙØµÙØ± ÙÙ
+ØµÙÙØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© "Ø§Ø®ØªÙØ§Ø± Ù
+ØµÙÙ ÙÙØ§Ø¶Ø§ÙØ©" Ø«Ù
+ Ø­ÙÙ ØšÙ
+Ø€ØŽØ± Ø§ÙÙØ£Ø±Ø© ÙÙÙÙ ÙØžÙØ± ÙÙ Ù
+Ø±ØšØ¹ Ø§ÙÙØµÙ0</p>
+
+<p>ÙÙÙ Ù
+ØµÙÙ Ù
+Ø¶Ø§Ù
+ÙÙ Ù
+ØªØ¹Ø¯Ø¯Ø© ÙÙ
+ÙÙ Ø§Ø¹Ø¯Ø§Ø¯ÙØ§ Ø ÙØªØªØ¶Ù
+Ù Ø§ÙÙ
+Ø¶Ø§Ù
+ÙÙ Ø§ÙÙ
+ÙÙ
+Ø© "ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª" Ø§ÙØªÙ ØªØ­Ø¯Ø¯ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØªÙ Ø¹ÙÙ Ø¶ÙØŠÙØ§ ØªØµÙÙ Ø§ÙÙØ«Ø§ØŠÙ Ù"Ø§Ø³Ù
+Ø§Ø¡ Ø§ÙØ§Ø²Ø±Ø§Ø±" ÙÙÙ Ø§ÙØ§Ø³Ù
+Ø§Ø¡ Ø§ÙØªÙ ØªØžÙØ± ÙÙ Ø¹Ù
+ÙØ¯ Ø§ÙØ§ØšØ­Ø§Ø±0</p>
+
+<p>ÙØ­Ø°Ù Ù
+ØµÙÙØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©Ø ÙØ§ÙÙØ± "Ø­Ø°Ù Ù
+ØµÙÙ"0</p>
+
+<p>ÙØªØºÙÙØ± Ù
+Ø¶Ø§Ù
+ÙÙ Ù
+ØµÙÙØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©Ø ÙØ§ÙÙØ± "ØªØ¬ÙÙØ² Ù
+ØµÙÙ" (Ø§Ù ÙÙØ±Ù Ù
+Ø²Ø¯ÙØ¬Ù Ø¹ÙÙØ§ÙÙ
+ØµÙÙ ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø©)0</p>
+
+<p>ØªØ±ØªÙØš Ø§ÙÙ
+ØµÙÙØ§Øª ÙÙ Ø¹Ù
+ÙØ¯ ØªØ¬ÙØ§Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØªØ¹ÙØ³ ØªØ±ØªÙØšÙØ§ ÙÙØ§Ø ÙØªØºÙÙØ± ÙØ°Ø§ Ø§ÙØªØ±ØªÙØšØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø§ÙÙ
+ØµÙÙ Ø§ÙÙ
+Ø·ÙÙØš ØªØ­Ø±ÙÙÙ ÙØ§ÙÙØ± Ø²Ø± "Ø­Ø±Ù Ø¥ÙÙ Ø£Ø¹ÙÙ" Ø£Ù "Ø­Ø±Ù Ø¥ÙÙ Ø§Ø³ÙÙ"0</p>
+
+<p>ÙÙ
+Ø²ÙØ¯ Ù
+Ù Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª Ø¹Ù Ø§ÙÙ
+ØµÙÙØ§Øª Ø§ÙØ±Ø£ Ø§ÙÙØµÙ 2 ÙÙ Ø¯ÙÙÙ ÙØ±ÙÙØ³ØªÙÙ Ù
+Ù
+Ø·ÙØ±ÙÙ &ndash; Ø§ÙØ¬Ø§Ø¯ ÙÙ Ù
+Ø§ ÙÙ Ù
+Ù
+ÙÙ Ø§Ø®Ø±Ø§Ø¬Ù Ù
+Ù Ø§ÙÙØ«Ø§ØŠÙ0</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/collectingfiles.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/collectingfiles.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/collectingfiles.htm	(revision 13928)
@@ -0,0 +1,44 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="collectingfiles"><font size="5" face="Verdana"><strong>4: ØªØ¬Ù
+ÙÙØ¹ Ø§ÙÙ
+ÙÙØ§Øª ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø©</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Ø¹ÙØ¯ Ø§ÙØŽØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø© Ø¬Ø¯ÙØ¯Ø© Ø³ÙÙ ØªØ­ØªØ§Ø¬ ÙØ¬ÙØš Ù
+ÙÙØ§Øª Ù
+Ø­Ø¯Ø¯Ø© Ø§ÙÙÙØ§Ø ÙÙÙ
+ÙÙ Ø§Ù ÙÙÙÙ ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ Ù
+Ù Ù
+Ø³Ø§Ø­Ø© Ø§ÙÙ
+ÙÙØ§Øª0 Ø§Ù Ù
+Ù Ù
+Ø¬Ù
+ÙØ¹Ø§Øª ÙØ±ØšÙØ³ØªÙÙ Ø§ÙØ£Ø®Ø±ÙØ ÙØ±ØšÙ
+Ø§ ÙØ­ØªÙÙ ØšØ¹Ø¶ÙØ§ Ø¹ÙÙ Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§ØªØ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ÙØµÙ ÙÙÙÙØ© Ø§Ø³ØªÙØ±Ø§Ø¯ Ø§ÙÙ
+ÙÙØ§Øª0</p>
+
+
+
+
+
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/collectionspecificmacros.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/collectionspecificmacros.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/collectionspecificmacros.htm	(revision 13928)
@@ -0,0 +1,43 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="collectionspecificmacros"><font size="5" face="Verdana"><strong>8.7: Ù
+Ø§ÙØ±Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙ
+Ø®ØµØµ</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ØªØ­Øª tab "ÙØ³Ù Ø¹Ø±Ø¶" Ø Ø§ÙÙØ± "Ù
+Ø§ÙØ±Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙ
+Ø®ØµØµ</p> 
+
+<p>ÙØ¹Ø±Ø¶ ÙÙ ÙØ°Ø§ Ø§ÙÙ
+ØŽÙØ¯ Ù
+Ø­ØªÙÙØ§Øª Ù
+ÙÙ Ù
+Ø§ÙØ±Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Extra-dm ÙÙÙØ§ ÙØªÙ
+ ØªØ¹Ø±ÙÙ Ø§ÙÙ
+Ø§ÙØ±Ù Ø§ÙÙ
+Ø®ØµØµ ÙÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø©0 ÙÙ
+Ø¹Ø±ÙØ© Ø§ÙÙ
+Ø²ÙØ¯ Ø­ÙÙ Ø§ÙÙ
+Ø§ÙØ±Ù Ø§ÙØžØ± Ø§ÙÙØµÙ 3 Ù
+Ù Ø¯ÙÙÙ ÙØ±ÙÙØ³ØªÙÙ ÙÙÙ
+Ø·ÙØ±ÙÙ0.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/creatingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/creatingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/creatingacollection.htm	(revision 13928)
@@ -0,0 +1,69 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="creatingacollection"><font size="5" face="Verdana"><strong>2.1: Ø¥ÙØŽØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø© Ø¬Ø¯ÙØ¯Ø©</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙØ§ÙØŽØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø© Ø¬Ø¯ÙØ¯Ø©Ø Ø§ÙØªØ­ ÙØ§ØŠÙ
+Ø© "Ù
+ÙÙ" ÙÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± "Ø¬Ø¯ÙØ¯" ØªØžÙØ± ÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø© Ù
+Ù Ø§ÙØ­ÙÙÙ Ø§ÙÙØµÙØ© Ø§ÙØªÙ ÙØ¬Øš ØªØ¹ØšØŠØªÙØ§0</p>
+
+<p>"Ø¹ÙÙØ§Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©" ÙÙ Ø§ÙÙØµ Ø§ÙØ°Ù ÙØ¹Ø±Ø¶ Ø£Ø¹ÙÙ ØµÙØ­Ø© Ø§ÙÙØš ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙÙ
+ÙÙ Ø£Ù ÙÙÙÙ ØšØ§Ù Ø·ÙÙ0</p>
+
+<p>"ÙØµÙ Ø§ÙÙ
+Ø­ØªÙÙØ§Øª" ÙØ¬Øš Ø£Ù ÙØµÙ ÙØ¯Ø± Ø§ÙÙ
+Ø³ØªØ·Ø§Ø¹ Ù
+Ø­ØªÙÙØ§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 ÙØ§Ø³ØªØ®Ø¯Ø§Ù
+  Ù
+ÙØªØ§Ø­ "Enter" ÙØ§ÙØŽØ§Ø¡ Ø§ÙÙÙØ±Ø§Øª0</p>
+
+<p>Ø§Ø®ÙØ±Ø§Ù ÙØ¬Øš ØªØ­Ø¯ÙØ¯  Ø§Ø°Ø§ Ù
+Ø§ ÙØ§Ù ØªÙ
+ØžÙØ± ÙÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ù
+ØšÙÙ Ø¹ÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø© Ø³Ø§ØšÙØ©0 Ø£Ù Ø§Ø³ØªØ®Ø¯Ø§Ù
+ Ø§ÙØšØ¯Ø§ÙØ© Ø§ÙØ§ÙØªØ±Ø§Ø¶ÙØ© "Ù
+Ø¬Ù
+ÙØ¹Ø© Ø¬Ø¯ÙØ¯Ø©"0 Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙØ¬Ø¯ÙØ¯Ø© Ø§ÙØ§ÙØªØ±Ø§Ø¶ÙØ© Ø§ÙØ¬Ø¯ÙØ¯Ø© ÙÙØ§ ØªÙÙÙÙ Ù
+Ø¹ÙØ§Ø±Ù ÙØªØ³ØªØ®Ø¯Ù
+ Ù
+Ø¹ÙØ§Ø± Ø¯ØšÙÙ ÙÙØ± ÙÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª0 ÙÙÙ
+ÙÙ ØªØºÙÙØ± ÙØ°Ø§ ÙÙÙ
+Ø§ ØšØ¹Ø¯0
+</p>
+
+<p>Ø§ÙÙØ± "OK" ÙØ§ÙØŽØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø©0 </p>
+
+<p>Ø§ÙÙØ± "Ø¥ÙØºØ§Ø¡" ÙÙØ±Ø¬ÙØ¹ Ø§ÙÙÙØ±Ù ÙÙØŽØ§ØŽØ© Ø§ÙØ±ØŠÙØ³ÙØ© 0.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/creatingfolders.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/creatingfolders.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/creatingfolders.htm	(revision 13928)
@@ -0,0 +1,61 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="creatingfolders"><font size="5" face="Verdana"><strong>4.3: Ø¥ÙØŽØ§Ø¡ Ù
+Ø¬ÙØ¯Ø§Øª</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Ø§Ø³ØªØ®Ø¯Ù
+ Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª ÙÙ ØŽØ¬Ø±Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙØªØ¬Ù
+ÙØ¹ Ø§ÙÙ
+ÙÙØ§Øª Ù
+Ø¹Ø§Ù ÙØªØ³ÙÙÙ Ø§ÙÙØµÙÙ Ø¥ÙÙÙØ§Ø ÙÙ
+ÙÙ Ù
+ÙØ¶Ø¹Ø©  Ù
+Ø¬ÙØ¯Ø§Øª Ø¯Ø§Ø®Ù Ù
+Ø¬ÙØ¯Ø§Øª ÙØ§ÙØªØ±Ø§Ø¶ÙØ§Ù ÙØ§ ÙÙØ¬Ø¯ Ø­Ø¯ ÙØ¹Ø¯Ø¯ Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª Ø£Ù Ø¹Ù
+Ù ØªÙØ±ÙØº Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª0</p>
+
+<p>ÙØ§ÙØŽØ§Ø¡ Ù
+Ø¬ÙØ¯ Ø¬Ø¯ÙØ¯Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ù
+Ø¬ÙØ¯ ÙÙ ØŽØ¬Ø±Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙØ§ÙÙØ± Ø¹ÙÙ Ø²Ø± "Ù
+Ø¬ÙØ¯ Ø¬Ø¯ÙØ¯"Ø ÙØžÙØ± Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙØ¬Ø¯ÙØ¯ Ø¶Ù
+Ù Ù
+Ø¬ÙØ¯ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙ
+Ø®ØªØ§Ø±Ø© Ø£Ù ÙÙ Ø§ÙÙ
+Ø³ØªÙÙ Ø§ÙØ£Ø¹ÙÙ Ø§Ø°Ø§ ÙÙ
+ ÙØªÙ
+ Ø§Ø®ØªÙØ§Ø± ÙØ§Ø­Ø¯Ø Ø³ÙÙ ÙØªÙ
+ Ø­Ø«Ù ØªØ³Ù
+ÙØ© Ø§ÙÙ
+Ø¬ÙØ¯ (Ø§ÙØ£Ø³Ù
+ Ø§ÙØ§ÙØªØ±Ø§Ø¶Ù ÙÙ "Ù
+Ø¬ÙØ¯ Ø¬Ø¯ÙØ¯"0
+</p>
+
+<p>ÙÙ
+ÙÙ Ø§ÙØŽØ§Ø¡ Ù
+Ø¬ÙØ¯ Ø¬Ø¯ÙØ¯ ÙÙÙØ± Ø§ÙØ²Ø± Ø§ÙØ§ÙÙ
+Ù ÙÙÙØ£Ø±Ø© ÙØ§Ø®ØªÙØ§Ø± "Ù
+Ø¬ÙØ¯ Ø¬Ø¯ÙØ¯" ÙØ§ØªØšØ§Ø¹ Ø§ÙØ§Ø¬Ø±Ø§Ø¡Ø§Øª Ø§Ø¹ÙØ§Ù0</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/creatingshortcuts.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/creatingshortcuts.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/creatingshortcuts.htm	(revision 13928)
@@ -0,0 +1,45 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="creatingshortcuts"><font size="5" face="Verdana"><strong>4.2:  Ø§ÙØŽØ§Ø¡ Ù
+Ø®ØªØµØ± Ù
+Ù ØŽØ¬Ø±Ø© Ù
+Ø³Ø§Ø­Ø© Ø§ÙØ¹Ù
+Ù0</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Ù
+Ø¬ÙØ¯Ø§Øª Ù
+Ø­Ø¯Ø¯Ø©00 Ù
+Ø«Ù Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙØ°Ù ÙØ­ØªÙÙ ØµÙØ­Ø§Øª Ø§ÙÙØš Ø®Ø§ØµØªÙ0 ÙØ¯ÙÙØ§ ÙÙ ØšØ¹Ø¶ Ø§ÙØ§Ø­ÙØ§Ù Ø¯ÙØ§ÙØ§Øª Ø®Ø§ØµØ©Ø ÙÙ
+ÙÙ ÙÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ Ù
+ÙØ¶Ø¹Ù ÙØ°Ù Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª ÙÙ Ø§ÙÙ
+Ø³ØªÙÙ Ø§ÙØ£ÙÙ Ù
+Ù ØŽØ¬Ø±Ø© Ø§ÙÙ
+ÙÙØ§Øª. ÙÙÙÙØ§Ù
+ ØšÙØ°Ø§ Ø§ÙØ¹Ù
+ÙØ Ø§ÙÙØ± Ø§ÙØ²Ø± Ø§ÙØ§ÙÙ
+Ù ÙÙÙ Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙÙ
+Ø·ÙÙØšØ ÙØžÙØ± "Ø§ÙØŽØ§Ø¡ Ù
+Ø®ØªØµØ±" Ø§Ø¯Ø®Ù Ø§Ø³Ù
+Ø§Ù ÙÙÙ
+Ø¬ÙØ¯0 ÙØ­Ø°Ù Ø¹ÙØµØ± Ø§ÙÙØ± Ø§ÙØ²Ø± Ø§ÙØ§ÙÙ
+Ù ÙÙÙ Ø§ÙÙ
+Ø¬ÙØ¯ ÙÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± "Ø­Ø°Ù Ù
+Ø®ØªØµØ±"0
+</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/definefilters.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/definefilters.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/definefilters.htm	(revision 13928)
@@ -0,0 +1,97 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="definefilters"><font size="5" face="Verdana"><strong>6.4.1: ØªØ¹Ø±ÙÙ Ù
+Ø±ØŽØ­Ø§Øª</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ØªØ³Ù
+Ø­ ÙÙ Ø§ÙÙ
+Ø±ØŽØ­Ø§Øª ØšØªØ¬Ù
+ÙØ¹ ÙÙ Ø§ÙÙØ«Ø§ØŠÙ ÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø© ÙØ±Ø¹ÙØ© ÙÙ ÙØŽØ§Ù ÙØªØ¶Ù
+Ù ÙÙÙ
+Ø©  ÙØ§ØµÙÙ ØšÙØ§ÙØ§Øª ØªØ¶Ø§ÙÙ  ÙÙ
+Ø· Ù
+Ø¹Ø·Ù0</p>
+
+<p>ÙØ§ÙØŽØ§Ø¡ Ù
+Ø±ØŽØ­Ø Ø§ÙÙØ± tab "ØªØ¹Ø±ÙÙ Ù
+Ø±ØŽØ­" ÙØ£Ø¯Ø®Ù Ø§Ø³Ù
+ Ø§ÙÙ
+Ø±ØŽØ­ Ø§ÙØ¬Ø¯ÙØ¯ ÙÙ Ø­ÙÙ "Ø§Ø³Ù
+ Ù
+Ø±ØŽØ­ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙØ±Ø¹ÙØ©" ØªÙ
+ Ø§Ø®ØªÙØ§Ø± ØµÙÙ ÙÙÙØ«ÙÙØ© ÙÙÙ
+Ø¶Ø§ÙØ§Ø© ÙÙÙ Ø§Ù
+Ø§ Ø£Ù ØªÙÙÙ ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø§ÙØ§Ø³Ù
+ Ù
+ÙÙ ÙÙ Ø³Ø€Ø§Ù0 Ø§Ø¯Ø®Ù Ø§ÙØªØ¹ØšÙØ± Ø§ÙÙ
+ÙØªØžÙ
+ ÙØ§Ø³ØªØ®Ø¯Ø§Ù
+Ù Ø®ÙØ§Ù Ø§ÙÙ
+Ø¶Ø§ÙØ§Ø© ÙÙ
+ÙÙÙ toggle ØšÙÙ "ØªØ¶Ù
+ÙÙ " ÙØ«Ø§ØŠÙ ØªØ¶Ø§ÙÙ Ø§ÙÙ
+Ø±ØŽØ­ Ø£Ù "Ø§Ø³ØªØšØ¹Ø§Ø¯" Ø§ÙÙØ«Ø§ØŠÙ0 ÙÙ
+ÙÙÙ ØªØ®ØµÙØµ Ø§Ù Ù
+Ù ØŽØ§Ø±Ø§Øª Ø§ÙØªÙ
+ÙØ² ÙÙØªØ¹ØšÙØ±Ø§Øª Ø§ÙÙ
+ÙØªØžÙ
+Ø© Ø§ÙÙ
+Ø¹ÙØ§Ø±ÙØ© ÙØšÙØ±Ù ÙØ§ Ø³ØªØ®Ø¯Ø§Ù
+ÙØ§ Ø¹ÙØ¯ Ø§ÙÙ
+Ø¶Ø§ÙØ§Ø© ("*" ÙÙ
+Ø¶Ø§ÙØ§Ø© Ø­Ø§ÙØ©  ØºÙØ± Ø­Ø³Ø§Ø³Ù) &ndash; Ø§Ø®ÙØ±Ø§Ù Ø§ÙÙØ± "Ø§Ø¶Ø§ÙØ© Ù
+Ø±ØŽØ­" ÙØ§Ø¶Ø§ÙØ© Ø§ÙÙ
+Ø±ØŽØ­ Ø¥ÙÙ ÙØ§ØŠÙ
+Ø© "Ù
+Ø±ØŽØ­Ø§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙØ±Ø¹ÙØ© Ø§ÙÙ
+Ø¹Ø±ÙØ©"</p>
+
+<p>ÙØ­Ø°Ù Ù
+Ø±ØŽØ­Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©Ø ÙØ§ÙÙØ± "Ø­Ø°Ù Ù
+Ø±ØŽØ­"0</p>
+
+<p> ÙÙ  alter Ù
+Ø±ØŽØ­ Ø  ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±  Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©Ø  ÙÙÙ
+ ØšØªØ¹Ø¯ÙÙ Ø§Ù Ù
+Ù Ø§ÙÙÙÙ
+ÙÙ Ø§ÙÙ
+ØªÙÙØ±Ø© Ù
+Ù Ø¹ÙØ§ØµØ± Ø§ÙØªØ­ÙÙ
+ ÙØ§ÙÙØ±  "Ø§Ø³ØªØšØ¯Ø§Ù Ù
+Ø±ØŽØ­" ÙØªØµØšØ­ Ø§ÙØªØºÙÙØ±Ø§Øª  Ù
+ÙØ²Ù
+Ù0</p>
+
+<p>ÙØ§ ÙØµÙØ¹ ØªØ¹Ø±ÙÙ ÙÙ
+Ø±ØŽØ­Ø§Øª Ù
+Ø¬Ù
+ÙØ¹Ø§Øª ÙØ±Ø¹ÙÙ0 ÙØªÙ
+ ØªØ­Ø¯ÙØ¯ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙÙØ±Ø¹ÙÙ ÙÙ "Assign Partitions", ØšÙØ§Ø¡Ø§Ù Ø¹ÙÙ Ø§ÙÙ
+Ø±ØŽØ­Ø§Øª Ø§ÙØªÙ ÙÙ
+Øª ØšØªØ¹Ø±ÙÙÙØ§0</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/deletingcollections.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/deletingcollections.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/deletingcollections.htm	(revision 13928)
@@ -0,0 +1,39 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="deletingcollections"><font size="5" face="Verdana"><strong>2.4: Ø¥ÙØºØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Ø¹ÙØ¯Ù
+Ø§ ØªØ±ÙØ¯ Ø¥ÙØºØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø§Øª Ù
+Ù ØªØ«ØšÙØª ÙØ±ÙÙØ³ØªÙÙ ØšØµÙØ© Ø¯Ø§ØŠÙ
+Ø©0 ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± "Ø¥ÙØºØ§Ø¡00" Ù
+Ù ÙØ§ØŠÙ
+Ø©  "Ù
+ÙÙ" - ØªØžÙØ± ÙØ§ØŠÙ
+Ø© ØšØ§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± ÙØ§Ø­Ø¯Ø© ÙÙ
+Ø¹Ø±ÙØ© ÙØµÙÙØ§ Ø«Ù
+ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ù
+Ø±ØšØ¹ Ø§ÙÙØ­Øµ Ø§Ø³ÙÙ Ù
+Ø±ØšØ¹ Ø§ÙØ­ÙØ§Ø± ÙØ§ÙÙØ± "Ø§ÙØºØ§Ø¡" ÙØ¬Øš ØªÙØ®Ù Ø§ÙØ­Ø°Ø± ÙØ§Ù ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ ØºÙØ± Ù
+Ø±Ø¯ÙØ¯0
+</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/designingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/designingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/designingacollection.htm	(revision 13928)
@@ -0,0 +1,40 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="designingacollection"><font size="5" face="Verdana"><strong>6: ØªÙÙÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Ø¹ÙØ¯ ØªÙ
+ÙÙØ² Ø§ÙÙ
+ÙÙØ§Øª ØšÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§ØªØ ÙØ¬Øš Ø£Ù ØªÙØ±Ø± ÙÙÙÙØ© ØªÙ
+ØžÙØ± Ù
+Ø¬Ù
+ÙØ¹Ø© ÙØ±ÙÙØ³ØªÙÙ ÙÙÙ
+Ø³ØªÙÙØ¯ÙÙØ Ù
+Ø§ÙÙ Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª Ø§ÙÙ
+ØªØ§Ø­Ø© ÙÙØšØ­Ø«Ø Ù
+Ø§ÙÙ  Ø·Ø±Ù ØªØµÙØ­ Ø§ÙÙØ«Ø§ØŠÙØ Ù
+Ø§ÙÙ Ø§ÙÙØºØ§Øª Ø§ÙÙ
+Ø¯Ø¹ÙÙ
+Ø©Ø Ø§ÙÙ ØªØ¶Ø¹ Ø§Ø²Ø±Ø§Ø± Ø§ÙØµÙØ­Ø©Ø ÙÙ ÙØ°Ù Ø§ÙØ§ØŽÙØ§Ø¡ ÙÙ
+ÙÙ ØªØŽÙÙÙÙØ§0 ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ÙØµÙ ÙÙ ÙÙÙ ØªÙØ¹Ù ÙØ°Ø§0</p>
+
+
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/downloadingfiles.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/downloadingfiles.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/downloadingfiles.htm	(revision 13928)
@@ -0,0 +1,32 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="downloadingfiles"><font size="5" face="Verdana"><strong>3: ØªÙØ²ÙÙ Ø§ÙÙ
+ÙÙØ§Øª Ù
+Ù Ø§ÙØ¥ÙØªØ±ÙØª</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙØµÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+"Download"  ÙÙÙÙØ© Ø¥Ø¹Ø¯Ø§Ø¯ Ù
+ÙÙ
+Ø© ØªÙØ²ÙÙ ÙØ§ÙØªØ­ÙÙ
+ ÙÙ Ø§Ø¬Ø±Ø§Ø¡ Ø§ÙØªÙØ²ÙÙØ ÙØ§ØªØ§Ø­Ø© Ø§ÙØªÙØ²ÙÙ Ø§ÙÙØ± Ø§ÙØ²Ø±0 ÙÙ Ù
+ÙØªØµÙ Ø§Ø¹ÙÙ Ø§ÙØŽØ§ØŽÙØ ØªØªÙÙØ± ÙÙ Ø¹ÙØ§ØµØ± Ø§ÙØªØ­ÙÙ
+ ÙÙ Ø§Ø¬Ø±Ø§Ø¡ Ø§ÙØªÙØ²ÙÙ0 ÙÙÙÙ ÙØµÙ Ø§ÙØŽØ§ØŽØ© Ø§ÙØ§Ø³ÙÙ ÙØ§Ø±Øº Ù
+ØšØ¯ØŠÙØ§Ù ÙØ°ÙÙ ÙØªÙÙÙØ± ÙÙØ§ØŠÙ
+ Ø§ÙÙ
+ÙÙ
+Ø§Øª Ø§ÙÙ
+ÙØ¬Ø²Ø© ÙØ§ÙÙ
+Ø¹ÙÙØ©0</p>
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/enrichingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/enrichingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/enrichingacollection.htm	(revision 13928)
@@ -0,0 +1,39 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="enrichingacollection"><font size="5" face="Verdana"><strong>5: Ø¥Ø«Ø±Ø§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø© ØšÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙØ¹Ø¯ ØªØ¬Ù
+ÙØ¹ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+ØªØ¹Ø¯Ø¯Ø© ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©Ø ÙÙ
+ÙÙÙ Ø§ÙØ£Ù  Ø¥Ø«Ø±Ø§Ø€ÙØ§ ØšÙ
+Ø¹ÙÙÙ
+Ø§Øª Ø§Ø¶Ø§ÙÙØ© ØªØ³Ù
+Ù "ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª"0 ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ÙÙØ¶Ø­ ÙÙÙÙØ© Ø§ÙØŽØ§Ø¡Ø ØªØ¹Ø¯ÙÙØ ØªØ¹ÙÙÙØ Ø§Ø³ØªØ±Ø¬Ø§Ø¹ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙÙÙÙØ© Ø§Ø³ØªØ®Ø¯Ø§Ù
+ ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+Ù Ù
+ØµØ§Ø¯Ø± Ø®Ø§Ø±Ø¬ÙØ© </p>
+
+
+
+
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/expertbuilding.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/expertbuilding.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/expertbuilding.htm	(revision 13928)
@@ -0,0 +1,63 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="expertbuilding"><font size="5" face="Verdana"><strong>7.3: Ù
+ØŽÙØ¯ Ø§ÙØŽØ§Ø¡ ÙÙ Ø³ÙØ§Ù Ø®ØšÙØ±</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙÙ Ø³ÙØ§Ù Ø®ØšÙØ±Ø ÙÙ
+ÙÙÙ  Ø§Ø³ØªØ®Ø¯Ø§Ù
+ "Ø§ÙÙ
+Ø¯ÙÙÙ" ÙÙ Ø§ÙØ¬Ø²Ø¡ Ø§ÙØ§ÙØ³Ø± ÙØ§Ø³ØªØ¹Ø±Ø§Ø¶ Ø§ÙÙ
+Ø­Ø§ÙÙØ§Øª Ø§ÙØ³Ø§ØšÙÙ ÙØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹ÙØ Ø§Ø°Ø§ ÙØ§ÙØª ÙØ§Ø¬Ø­Ù Ø§ÙÙØ§Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø§ÙÙ
+Ø¯ÙÙÙ ØšØ§ÙØªØ§Ø±ÙØ® ÙÙ ÙØ§ØŠÙ
+Ø© "Ø§ÙÙ
+Ø¯ÙÙÙ"0</p>
+
+<p>ÙÙ ÙØ°Ø§ Ø§ÙØ³ÙØ§ÙØ ØªØžÙØ± Ø§ÙØ®ÙØ§Ø±Ø§Øª Ø§ÙÙØ§Ù
+ÙØ© ÙÙØ§Ø³ØªÙØ±Ø§Ø¯ ÙØ§ÙØšÙØ§Ø¡ ÙÙ tab ØšÙØ§Ø¡ ÙØ§Ø³ØªÙØ±Ø§Ø¯ Ø¥ÙÙ Ø§ÙØ³ÙØ§Ø±0 ØªØªÙ
+Ø§Ø«Ù Ø§Ø¹Ø¯Ø§Ø¯Ø§Øª Ø§ÙØªØ­ÙÙ
+ Ø§ÙÙ
+Ø®ØªÙÙØ© ØªÙÙ Ø§ÙØªÙ ÙÙ ÙØ§ÙØ°Ø© "ØªØ¬ÙÙØ² Ù
+Ø¶Ø§Ù
+ÙÙ" Ø§ÙÙ
+ÙØµÙÙÙ ÙÙ ÙØ³Ù
+ <a href="plugins.htm">Ù
+ÙØ§ØšØ³ Ø§ÙÙØ«ÙÙØ©</a>  ØšØ¹Ø¶ Ø§ÙØ­ÙÙÙ ØªØ­ØªØ§Ø¬ Ù
+Ø¶Ø§Ù
+ÙÙ Ø¹Ø¯Ø¯ÙÙ ÙÙÙ
+ÙÙÙ Ø·ØšØ§Ø¹ØªÙØ§ Ø£Ù Ø§Ø³ØªØ®Ø¯Ø§Ù
+ Ø§ÙØ§Ø³ÙÙ
+ ÙØ²ÙØ§Ø¯Ø© Ø£Ù ØªÙÙÙÙ Ø§ÙÙÙÙ
+Ø© Ø§ÙØ­Ø§ÙÙØ© ( ÙÙ ØšØ¹Ø¶ Ø§ÙØ­Ø§ÙØ§ØªØ ØªÙÙØ¯ Ø§ÙÙØ§Ø¬ÙØ© Ø§ÙÙ
+Ø¯Ù)0 ÙØªÙ
+ ØªÙØŽÙØ·  Ø§Ø¬Ø±Ø§Ø¡Ø§Øª Ø§ÙØ£Ø®Ø±Ù ØšÙÙØ± Ù
+Ø±ØšØ¹ Ø§ÙÙØ­Øµ (Ø§ÙØžØ± Ù
+Ø±Ø© Ø«Ø§ÙÙØ© ÙÙØ§Ø®Ù
+Ø§Ø¯)0</p>
+
+<p>ÙÙ
+Ø²ÙØ¯ Ù
+Ù Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª Ø­ÙÙ Ø§Ø³ØªÙØ±Ø§Ø¯ ÙØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©Ø Ø§ÙØ±Ø£ Ø§ÙÙØµÙ 1 Ù
+Ù Ø¯ÙÙÙ ÙØ±ÙÙØ³ØªÙÙ ÙÙÙ
+Ø·ÙØ±ÙÙ- ÙÙÙ
+ Ø§Ø¬Ø±Ø§Ø¡ ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/explodingfiles.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/explodingfiles.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/explodingfiles.htm	(revision 13928)
@@ -0,0 +1,142 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="explodingfiles"><font size="5" face="Verdana"><strong>4.7:  ØªØ¬Ø²ØŠØ©  Ù
+ÙÙØ§Øª ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª0</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p> ÙÙ
+ÙÙ Ø§Ø³ØªÙØ±Ø§Ø¯ Ø£ÙÙØ§Ø¹ Ù
+ÙÙØ§Øª ÙÙØ§Ø¹Ø¯ ØšÙØ§ÙØ§Øª ÙÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+Ø«Ù MARC ÙCDS/ISIS	 Ù ProciteØ ÙÙ ØªØªÙ
+ÙÙ Ù
+Ù ØªØ­Ø¯ÙØ« ÙØ¹Ø±Ø¶ ÙØ§ØµÙØ§Øª  Ø§ÙØšÙØ§ÙØ§Øª ÙÙ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙØ ÙÙÙÙØ§Ù
+  ØšÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ ÙÙ
+ÙÙÙ Ø§ÙØ±Ø¬ÙØ¹ ÙÙØšØ±ÙØ§Ù
+Ø¬ Ø§ÙØ°Ù Ø£ÙØŽØ£ Ø§ÙÙ
+ÙÙ0
+</p>
+
+<p>"ØªØ¬Ø²ØŠØ©" Ù
+ÙÙ ÙØ§Ø¹Ø¯Ø© ØšÙØ§ÙØ§Øª ÙÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§ØªØ ÙÙØªØ¬ ØªØ³Ø¬ÙÙØ§Øª ÙØ±Ø¯ÙØ© ØšÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª ÙØ§ØšÙØ© ÙÙØ¹Ø±Ø¶ ÙØ§ÙØªØ­Ø¯ÙØ«0 ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ ØºÙØ± Ù
+Ø±Ø¯ÙØ¯ ÙØ³ÙÙ ÙØªÙ
+ Ù
+Ø³Ø­ Ù
+ÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØ£ØµÙÙ0</p>
+
+<p> Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+Ø¬Ø²Ø£Ø© ÙÙØ§ Ø§ÙÙÙÙØ© Ø®Ø¶Ø±Ø§Ø¡ ÙÙ ØŽØ¬Ø±Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 ÙØªØ¬Ø²ØŠØ© Ù
+ÙÙ Ø§ÙÙØ± Ø§ÙØ²Ø± Ø§ÙØ§ÙÙ
+Ù ÙÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± "ØªØ¬Ø²ØŠØ© ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª ÙØ§Ø¹Ø¯Ø© ØšÙØ§ÙØ§Øª" ØªØžÙØ±  ÙØ§ÙØ°Ø© ØªØ¹Ø±Ø¶ Ø®ÙØ§Ø±Ø§Øª Ø§Ø¬Ø±Ø§Ø¡ Ø§ÙØªØ¬Ø²ØŠØ©0 Ø§ÙØ®ÙØ§Ø± Ø§ÙØ£ÙÙ ("Ø§ÙÙ
+ÙØ§ØšØ³") ÙØ­Ø¯Ø¯ Ø§ÙÙ
+ÙØ§ØšØ³ ÙÙØªØ¬Ø²ØŠØ© ÙÙ Ù
+Ø¹ØžÙ
+  Ø§ÙØ­Ø§ÙØ§ØªØ ÙØ³ØªØ®Ø¯Ù
+ Ù
+ÙØ§ØšØ³ ÙØ§Ø­Ø¯ ÙÙ
+Ø¹Ø§ÙØ¬Ø©  ÙÙØ¹ Ù
+Ø¹ÙÙ Ù
+Ù Ø§ÙÙ
+ÙÙØ§ØªØ ÙÙÙ ÙÙ ØšØ¹Ø¶ Ø§ÙØ§Ø­ÙØ§ÙØ Ø­ÙØ« ØªÙØ¬Ø¯ Ù
+ÙÙØ§Øª Ù
+Ø®ØªÙÙØ© ÙÙÙØ§ Ø§Ù
+ØªØ¯Ø§Ø¯ Ù
+ØŽØªØ±Ù  ÙÙØ§ ÙÙ
+ÙÙ ÙÙ
+ÙØ§ØšØ³ÙÙ Ù
+Ø¹Ø§ÙØ¬Ø© Ø§ÙÙ
+ÙÙØ§Øª ØšÙÙØ³ Ø§ÙØ§Ù
+ØªØ¯Ø§Ø¯0ÙÙ
+ÙÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+ Ø®ÙØ§Ø± "input-encoding" ÙØªØ­Ø¯ÙØ¯ ØªØ±Ù
+ÙØ² ÙØ§Ø¹Ø¯Ø© Ø§ÙØšÙØ§ÙØ§Øª0 Ø®ÙØ§Ø± "Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª" "metadata-set"" ÙØ­Ø¯Ø¯ Ø£Ù Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª ÙÙ
+ÙÙ Ø§Ø¶Ø§ÙØ©  Ø§ÙØ­ÙÙ Ø§ÙØ¬Ø¯ÙØ¯ Ø¥ÙÙÙ0 Ø¥Ø°Ø§ ÙÙ
+ ÙØªÙ
+ ØªØ­Ø¯ÙØ¯ ÙØ§Ø­Ø¯Ø Ø³ÙÙ ÙØªÙ
+ Ø­Ø«Ù ÙÙ
+Ø¹Ø±ÙØ© Ù
+Ø§ ÙÙ
+ÙÙ ÙØ¹ÙÙ Ù
+Ø¹ Ø£Ù Ø­ÙÙ Ø¬Ø¯ÙØ¯ ÙÙ ÙØ§Ø¹Ø¯Ø© Ø§ÙØšÙØ§ÙØ§Øª0  ÙÙ
+ÙÙ Ø§Ø¶Ø§ÙØªÙ ÙØ¹ÙØµØ± Ø¬Ø¯ÙØ¯ ÙÙ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+ÙØ¬ÙØ¯Ø Ø¯Ù
+Ø¬Ù Ù
+Ø¹ Ø¹ÙØµØ± Ø¢Ø®Ø± Ø£Ù ØªØ¬Ø§ÙÙÙ0
+</p>
+
+<p>  ÙØªÙ
+ Ø§ÙØŽØ§Ø¡ ÙØ«ÙÙØ© ÙØ§Ø±ØºØ©  Ø¬Ø¯ÙØ¯Ø© ÙÙÙ ØªØ³Ø¬ÙÙØ© Ø¹ÙØ¯ ØªØ¬Ø²ØŠØ©  Ø§ÙÙ
+ÙÙ ÙÙØªÙ
+ Ø§Ø¹ØªÙ
+Ø§Ø¯ ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø§ÙØªØ³Ø¬ÙÙØ© ÙÙÙ ÙØ«ÙÙØ©Ø ØªØªÙ
+ ØªØ³Ù
+ÙØ© Ø§ÙÙØ«Ø§ØŠÙ ØšØ§Ø³ØªØ®Ø¯Ø§Ù
+ Ø§ÙØ§Ø±ÙØ§Ù
+ Ù
+Ø«Ù 00002,nul Ù000001-nul ÙÙÙØ°Ø§Ø Ø§Ø°Ø§ ØªÙ
+ ØªØ­Ø¯ÙØ¯ Ø§ÙØ®ÙØ§Ø± "Document-field" (Ø¥ÙÙ Ø§Ø³Ù
+ Ø­ÙÙ ÙØ§Ø¹Ø¯Ø© Ø§ÙØšÙØ§ÙØ§Øª) ØªØ³ØªØ®Ø¯Ù
+ ÙÙÙ
+Ø© ÙØ°Ø§ Ø§ÙØ­ÙÙØ Ø§Ø°Ø§ ØªÙÙØ±Øª ÙØ§Ø³Ù
+ Ø§ÙÙ
+ÙÙ. ÙÙÙÙ
+ Ø§Ø¬Ø±Ø§Ø¡ Ø§ÙØªØ¬Ø²ØŠØ© ØšÙ
+Ø­Ø§ÙÙØ© ØªÙØ²ÙÙ Ø§ÙÙ
+ÙÙ ÙØ§Ø³ØªØ®Ø¯Ø§Ù
+Ù ØšØ¯ÙØ§ Ù
+Ù Ù
+ÙÙ ÙØ§Ø±Øº0 ÙÙ
+ÙÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+  Ø®ÙØ§Ø±Ø§Øª0"Document- prefix"Ù "Document- sufix" ÙØ§ÙØŽØ§Ø¡ Ø¹ÙÙØ§Ù Ù
+ÙØ§Ø±Ø¯  Ù
+ÙØ­Ø¯ URL ØµØ§ÙØ­ Ø£Ù Ù
+Ø³Ø§Ø± Ù
+ÙÙ Ù
+Ù ÙÙÙ
+Ø© "Document-field" ÙÙ
+ÙÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+ Ø®ÙØ§Ø± "Records-per-folder" ÙØªØ¬Ù
+ÙØ¹ Ø§ÙØªØ³Ø¬ÙÙØ§Øª Ø§ÙÙ
+Ø¬Ø²ØŠØ© ÙÙ Ù
+Ø¬ÙØ¯Ø§Øª ÙØ±Ø¹ÙØ©Ø Ø§Ø°Ø§ ÙØ§ÙØª ÙØ§Ø¹Ø¯Ø© Ø§ÙØšÙØ§ÙØ§Øª ÙØšÙØ±Ø© Ø¬Ø¯Ø§ÙØ ÙÙ
+ÙÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+ ÙØ°Ø§ Ø§ÙØ®ÙØ§Ø± ÙØªØ³Ø±ÙØ¹ Ø§ÙØªØ¹Ø¯ÙÙ Ø§ÙÙ
+ØªØ³ÙØ³Ù  ÙÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª0
+</p>
+
+<p> ÙØªØ­Ø¯Ø¯ Ø¥Ø¬Ø±Ø§Ø¡ Ø§ÙØªØ¬Ø²ØŠØ© ØšØ§Ù
+ØªØ¯Ø§Ø¯  Ø§ÙÙ
+ÙÙ0 ÙÙ ØšØ¹Ø¶ Ø§ÙØ­Ø§ÙØ§ØªØ ØªÙØ¬Ø¯ Ù
+ÙÙØ§Øª ØªÙ
+ÙØ² ÙÙØªØ¬Ø²ØŠØ© ØšØµÙØ±Ø© ØºÙØ± ØµØ­ÙØ­Ø©Ø Ø¥Ø°Ø§ ÙØ§Ù ÙØ¯ÙÙØ§ ÙÙØ³ Ø§Ø³Ù
+ Ø§Ù
+ØªØ¯Ø§Ø¯  Ø§ÙÙ
+ÙÙ0 Ù
+Ø«Ø§Ù Ù
+ÙØ§ÙØ³Procite  ÙØ¹Ø§ÙØ¬  Ø§ÙÙ
+ÙÙØ§Øª ØšØ§ÙØ§Ù
+ØªØ¯Ø§Ø¯  TXT. ÙÙÙÙ Ù
+Ø¹ØžÙ
+ Ø§ÙÙ
+ÙÙØ§Øª ØšØ§ÙØ§Ù
+ØªØ¯Ø§Ø¯ TXT .ÙÙ Ù
+ÙÙØ§Øª ØšØ³ÙØ·Ø© ÙÙÙØ³Øª Ù
+ÙÙØ§Øª Procite</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/exporting.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/exporting.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/exporting.htm	(revision 13928)
@@ -0,0 +1,73 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="exporting"><font size="5" face="Verdana"><strong>9.3: ØªØµØ¯ÙØ± Ø§ÙÙ
+Ù
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙÙ ÙÙØŠØ§Øª Ø£Ø®Ø±Ù</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙØªÙØ­ ÙØ±ÙÙØ³ØªÙÙ ØªØµØ¯ÙØ± Ù
+Ø­ØªÙÙØ§Øª / Ø£Ù ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙØŠØ§Øª Ù
+Ø¹ÙØ§Ø±ÙØ© Ø¹Ø¯ÙØ¯Ù ÙØªØªØ¶Ù
+Ù METSÙ DSPACE Ù MABCXML</p>
+
+<p>ÙØªØµØ¯ÙØ± Ù
+Ø¬Ù
+ÙØ¹Ø© Ø£Ù Ø§ÙØ«Ø± Ø Ø§ÙØªØ­ "Ù
+ÙÙ" ÙÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± "ØªØµØ¯ÙØ±" ÙÙ
+ÙÙÙ Ø§Ø®ØªÙØ§Ø± Ø§Ù Ø§ÙÙÙØŠØ§Øª  Ø§ÙØªÙ ØªÙØ¯ Ø§ÙØªØµØ¯ÙØ± Ø¥ÙÙÙØ§ ØšØ§Ø®ØªÙØ§Ø±ÙØ§ ÙÙ (Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© "ØªØµØ¯ÙØ± Ø¥ÙÙ00 "0 ÙÙ
+ ØšØªØ­Ø¯ÙØ¯ Ø§Ø³Ù
+ Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙØ°Ù ØªÙØ¯ Ù
+ÙÙØ§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙ
+ØµØ¯Ø±Ø© ÙÙÙ&mdash;ØªÙØªÙÙ ÙØ°Ù Ø§ÙÙ
+ÙÙØ§Øª&lt;path to greenstone&gt;/tmp/exported_xxx, Ø­ÙØ« &times;&times;&times; ÙÙ Ø§ÙØ§Ø³Ù
+ Ø§ÙØ°Ù Ø­Ø¯Ø¯ØªÙ0 ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± ÙØ§Ø­Ø¯Ø© Ø£Ù Ø£ÙØ«Ø± Ù
+Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙÙ
+ØªÙÙØ±Ø© ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø© Ø«Ù
+ Ø§ÙÙØ± "ØªØµØ¯ÙØ± Ù
+Ø¬Ù
+ÙØ¹Ø© (Ø§Øª)"0</p>
+
+<p> ØªÙØ¬Ø¯ Ø®ÙØ§Ø±Ø§Øª  Ø£Ø®Ø±Ù Ù
+Ø®ØµØµØ© ÙÙÙÙØŠØ§Øª Ø§ÙÙ
+Ø®ØªÙÙØ©0 ÙÙ
+ÙÙÙ ØªØ­Ø¯ÙØ¯ Ù
+ÙÙØ§Øª XSLT Ø§ÙØªÙ ØªØ·ØšÙ Ø§ÙÙØ§ØªØ¬ Ù
+Ù ÙØ«Ø§ØŠÙ XML ØšÙØ§ ÙØªÙØ¶ÙØš ÙÙØŠØ© ÙØ³Ù Ø§ÙÙ
+Ø®Ø±Ø¬Ø§Øª &ndash; Ø§ÙØªØµØ¯ÙØ± Ø¥ÙÙ MARCXML ÙØ³ØªØ®Ø¯Ù
+ Ù
+ÙÙ ØªØ®Ø·ÙØ· ÙØªØ®Ø·ÙØ· ÙØ§ØµÙØ§Øª  ØšÙØ§ÙØ§Øª ÙØ±ÙÙØ³ØªÙÙ  Ø¥ÙÙ Ø­ÙÙÙ MARC. Ø§ÙÙ
+ÙÙ Ø§ÙØªØ®Ø·ÙØ·Ù Ø§ÙØ§ÙØªØ±Ø§Ø¶Ù  ÙÙÙÙ
+ ØšØªØ®Ø·ÙØ· Ù
+Ø¹ÙØ§Ø± Ø¯ØšÙÙ ÙÙØ± ÙÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙ
+ÙÙÙ  ØªØ®Ø·ÙØ· Ù
+ÙÙ ÙÙÙ ÙØªÙ
+ Ø§Ø³ØªØ®Ø¯Ø§Ù
+Ù ØšØ¯ÙØ§Ù Ù
+Ù Ø§ÙÙ
+ÙÙ Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+ Ø­Ø§ÙÙØ§Ù0</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/exportingcollections.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/exportingcollections.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/exportingcollections.htm	(revision 13928)
@@ -0,0 +1,66 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="exportingcollections"><font size="5" face="Verdana"><strong>9.4: ØªØµØ¯ÙØ± Ù
+Ø¬Ù
+ÙØ¹Ø§Øª  Ø¥ÙÙ  CD/DVD</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙÙ
+ÙÙ ÙÙØ±ÙÙØ³ØªÙÙ ØªØµØ¯ÙØ± Ù
+Ø¬Ù
+ÙØ¹Ø© Ø£Ù Ù
+Ø¬Ù
+ÙØ¹Ø§Øª Ø¥ÙÙ ÙØ±Øµ CD/DVD Ø°Ø§ØªÙ Ø§ÙØªØ«ØšÙØª ØªØ­Øª ØšØ±Ø§Ù
+Ø¬ Ø§ÙØªØŽØºÙÙ Windows </p>
+
+<p>ÙØªØµØ¯ÙØ± Ù
+Ø¬Ù
+ÙØ¹Ø©Ø Ø§ÙØªØ­ ÙØ§ØŠÙ
+Ø© "Ù
+ÙÙ" ÙÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± "ØªØµØ¯ÙØ± ÙØ±Øµ CD/DVD ØªØžÙØ± ÙÙ ÙØ§ØŠÙ
+ Ù
+Ø¬Ù
+ÙØ¹Ø§Øª ÙØ±ÙÙØ³ØªÙÙ &ndash; Ø§ÙÙØ± Ø¹ÙÙ Ø£Ù ÙØ§Ø­Ø¯Ø© ÙÙ
+Ø¹Ø±ÙØ© ÙØµÙÙØ§ ÙÙ
+ ØšØªØ£ØŽÙØ± Ù
+Ø±ØšØ¹ Ø§ÙÙØ­Øµ  ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙØªÙ ØªÙØ¯ ØªØµØ¯ÙØ±ÙØ§- ÙÙ
+ÙÙÙ  Ø§Ø¯Ø®Ø§Ù Ø§Ø³Ù
+  CD/DVD Ù
+Ù Ù
+Ø±ØšØ¹ "Ø§Ø³Ù
+  CD/DVD"0 ÙØžÙØ± ÙØ°Ø§ Ø§ÙØ§Ø³Ù
+ ÙÙ ÙØ§ØŠÙ
+Ø© Ø§ØšØ¯Ø§ Ø¹ÙØ¯Ù
+Ø§ ÙØªÙ
+ ØªØ«ØšÙØª Ø§ÙÙØ±Øµ CD/DVD- ÙÙ
+ÙÙÙ Ø§Ø®ØªÙØ§Ø±  ØªØŽØºÙÙ Ø§ÙÙØ±Øµ DVD Ø£Ù CD-ROM Ø§ÙÙØ§ØªØ¬ Ù
+ØšØ§ØŽØ±Ø© Ù
+Ù Ø§ÙÙØ±Øµ Ø§ÙÙ
+Ø¹ÙÙØ Ø£Ù ØªØ«ØšÙØª ØšØ¹Ø¶ Ø§ÙÙ
+ÙÙØ§Øª ÙÙ Ø§ÙØ­Ø§Ø³ÙØš0 Ø«Ù
+ Ø§ÙÙØ± "ØªØµØ¯ÙØ± ÙØ±Øµ CD/DVD0  ÙØªØ¶Ù
+Ù ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡  ÙØ³Ø® Ù
+ÙÙØ§Øª Ø¹Ø¯ÙØ¯Ù ÙÙØ¯ ÙØ³ØªØºØ±Ù Ø¯ÙØ§ØŠÙ ÙÙÙÙØ©0</p>
+
+<p> Ø¹ÙØ¯ Ø§ÙØ§ÙØªÙØ§Ø¡ Ø ÙØžÙØ± ÙÙ ÙØ±ÙÙØ³ØªÙÙ Ø§Ø³Ù
+ Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙØ°Ù ÙØ¶Ù
+ Ø§ÙØ¬Ù
+ÙØ¹Ø§Øª Ø§ÙÙ
+ØµØ¯Ø±Ù0 Ø§Ø³ØªØ®Ø¯Ù
+ Ø³ÙØ§ÙÙ CD/DVD ÙÙØ³Ø® Ø§ÙÙ
+Ø­ØªÙÙØ§Øª Ø§ÙÙ ÙØ±Øµ CD/DVD ÙØ§Ø±Øº0</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/fileassociations.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/fileassociations.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/fileassociations.htm	(revision 13928)
@@ -0,0 +1,94 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="fileassociations"><font size="5" face="Verdana"><strong>9.2: Ù
+ØªØ¹ÙÙØ§Øª Ø§ÙÙ
+ÙÙ</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙØ³ØªØ®Ø¯Ù
+ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ØšØ±Ø§Ù
+Ø¬ ØªØ·ØšÙÙÙØ© Ù
+Ø¹ÙÙØ© ÙÙØªØ­ Ø§ÙÙ
+Ø§Ø· Ù
+ÙÙØ§Øª Ù
+Ø¹ÙÙØ©Ø ÙØ­Ø« Ù
+ØªØ¹ÙÙØ§Øª Ø§ÙÙ
+ÙÙØ  Ø§ÙØªØ­ ÙØ§ØŠÙ
+Ø© "Ù
+ÙÙ" Ø«Ù
+ Ø£ÙÙØ± "Ù
+ØªØ¹ÙÙØ§Øª Ø§ÙÙ
+ÙÙ00"</p>
+
+<p>ÙØ§Ø¶Ø§ÙØ© Ù
+ØªØ¹ÙÙØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø§Ù
+ØªØ¯Ø§Ø¯ Ø§ÙÙ
+ÙÙ Ø§ÙÙ
+Ø·ÙÙØš ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© Ø Ø£Ù Ø£Ø·ØšØ¹ Ø§ÙØ§Ù
+ØªØ¯Ø§Ø¯ Ø§ÙØ¬Ø¯ÙØ¯ (ÙØ§ØªØ¶Ù
+Ù "0") &ndash; Ø«Ù
+ Ø¥Ù
+Ø§ Ø£Ù  ØšØ·ØšØ§Ø¹Ø© Ø§ÙØ£Ù
+Ø± ÙØ§Ø·ÙØ§Ù Ø§ÙØšØ±ÙØ§Ù
+Ø¬ Ø§ÙÙ
+Ø·ÙÙØš ÙÙ Ø§ÙØ­ÙÙ Ø§ÙÙ
+ÙØ§Ø³Øš Ø  Ø£Ù Ø§Ø®ØªÙØ§Ø± Ø§ÙØªØ·ØšÙÙ Ù
+Ù Ù
+Ø±ØšØ¹ Ø­ÙØ§Ø± "ØªØµÙØ­"0 ÙÙ
+ÙÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+ "1%" ÙØ§Ø·ÙØ§Ù Ø§ÙØ£Ù
+Ø± ÙØ­ØŽØ± Ø§Ø³Ù
+ Ø§ÙÙ
+ÙÙ Ø§ÙÙ
+Ø·ÙÙØš ÙØªØ­Ù0  Ø¹ÙØ¯Ù
+Ø§ ÙØªÙ
+ ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡Ø ÙØªÙ
+ ØªÙØŽÙØ· "Ø§Ø¶Ø§ÙØ©" ÙØšØ§ÙÙÙØ± Ø¹ÙÙÙØ§ ØªØªÙ
+ Ø§Ø¶Ø§ÙØ© Ø§ÙÙ
+ØªØ¹ÙÙ0</p>
+
+<p> ØªØ¹Ø¯ÙÙ Ø§ÙÙ
+ØªØ¹ÙÙØ§ØªØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø§Ù
+ØªØ¯Ø§Ø¯ Ù
+ÙÙ Ù
+ÙØ¬ÙØ¯ ÙØªØ¹Ø¯ÙÙ Ø§Ù Ø§Ù
+ØªØ¯Ø§Ø¯ Ù
+ØªØ¹ÙÙ ÙÙ Ø­ÙÙ Ø§Ø·ÙØ§Ù Ø§ÙØ£Ù
+Ø± Ø«Ù
+ Ø§ÙÙØ±  "Ø§Ø³ØªØšØ¯Ø§Ù"</p>
+
+<p>ÙØ­Ø°Ù Ù
+ØªØ¹ÙÙØ§ØªØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø§Ù
+ØªØ¯Ø§Ø¯ Ù
+ÙÙ Ù
+ÙØ¬ÙØ¯ ÙØ£ÙÙØ± "Ø­Ø°Ù" (ÙØšÙÙ Ø§Ù
+ØªØ¯Ø§Ø¯  Ø§ÙÙ
+ÙÙ ÙÙ ÙØ§ØŠÙ
+Ø© (ÙÙÙØ§ÙØ©  Ø§ÙÙ
+ÙÙ) Ø§ÙÙ
+ÙØ³Ø¯ÙØ©</p>
+
+<p>ÙØªÙ
+ Ø­ÙØž Ù
+ØªØ¹ÙÙØ§Øª Ø§ÙÙ
+ÙÙ ÙÙ Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙØ±ØŠÙØ³Ù ÙÙØ§Ø¬ÙÙÙØ© Ø§ÙÙ
+ÙØªØšÙ ÙÙ Ù
+ÙÙ "associations.xml".</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/filteringthetree.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/filteringthetree.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/filteringthetree.htm	(revision 13928)
@@ -0,0 +1,65 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="filteringthetree"><font size="5" face="Verdana"><strong>4.8: ØªØ±ØŽÙØ­ Ø§ÙØŽØ¬Ø±Ø©</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>"ØªØ±ØŽÙØ­"  ØŽØ¬Ø±Ø© Ù
+Ø³Ø§Ø­Ø© Ø§ÙØ¹Ù
+Ù ÙØ§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙØªÙØ­ ÙÙ ØªØ¶ÙÙ ÙØ·Ø§Ù Ø§ÙØšØ­Ø« Ø¹Ù Ù
+ÙÙØ§Øª Ù
+Ø­Ø¯Ø¯Ø©0</p>
+
+<p>ÙØ§ØŠÙ
+Ø© "Ø§ØžÙØ§Ø± Ù
+ÙÙØ§Øª" Ø§ÙÙ
+ÙØ³Ø¯ÙØ© ØªØ­Øª ÙÙ ØŽØ¬Ø±Ø© Ù
+ÙÙØ§Øª ØªØªÙØ­ ÙØ§ØŠÙ
+Ø© Ù
+Ø±ØŽØ­Ø§Øª Ù
+Ø¹Ø±ÙØ© Ù
+Ù ÙØšÙØ Ù
+Ø«Ù "ØµÙØ±" . Ø§Ø®ØªÙØ§Ø± Ù
+Ø±ØŽØ­ ØšØµÙØ±Ø© Ù
+Ø€ÙØªØ© ÙØ¹ÙÙ Ø§Ø®ØªÙØ§Ø¡ ØšÙÙØ© Ø£ÙÙØ¹ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+Ø®ØªÙÙØ©  ÙÙ ØŽØ¬Ø±Ø© Ø§ÙÙ
+ÙÙØ§Øª0 ÙØ§Ø³ØªØ¹Ø§Ø¯Ø© ØŽØ¬Ø±Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØªÙ
+ÙÙØ² Ø§ÙÙ
+Ø±ØŽØ­ Ø¥ÙÙ "ÙÙ Ø§ÙÙ
+ÙÙØ§Øª"0 ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ ÙØ§ ÙØ€Ø«Ø± ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø£Ù Ù
+Ø¬ÙØ¯Ø§Øª ØŽØ¬Ø±Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0</p>
+
+<p>ÙÙ
+ÙÙÙ ØªØ®ØµÙØµ Ù
+Ø±ØŽØ­ ØšØ·ØšØ§Ø¹Ø© Ø§ÙØ§Ù
+ØªØ¯Ø§Ø¯ Ø§ÙØ¹Ø§Ù
+ " *.*" Ø£Ù Ø§Ù
+ØªØ¯Ø§Ø¯ Ù
+Ø­Ø¯Ø¯ ".doc" ÙØ§ØžÙØ§Ø±  Ø§ÙÙ
+ÙÙØ§Øª ÙÙÙØ§ Ø£Ù Ø§ÙÙ
+Ø­Ø¯Ø¯Ø© (ÙØ°Ø§ Ø§ÙØ®ÙØ§Ø± Ù
+ØªÙÙØ± ÙÙØ· ÙÙ Ø³ÙØ§Ù Ø§Ø®ØªØµØ§ØµÙ ÙØžÙ
+ Ù
+ÙØªØšØ§Øª ÙØ³ÙØ§Ù Ø§ÙØ®ØšÙØ±) " *.*" Ù
+ÙØ§Ø±ÙØ© ØšØ§Ù Ù
+Ø­Ø§Ø±Ù0
+</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/formatstatements.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/formatstatements.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/formatstatements.htm	(revision 13928)
@@ -0,0 +1,119 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="formatstatements"><font size="5" face="Verdana"><strong>8.4: ÙØ³Ù Ø¹Ø±Ø¶</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ØµÙØ­Ø§Øª Ø§ÙÙØš Ø§ÙØªÙ ÙØ±Ø§ÙØ§ Ø¹ÙØ¯ Ø§Ø³ØªØ®Ø¯Ø§Ù
+ ÙØ±ÙÙØ³ØªÙÙ ÙÙØ³Øª Ø³Ø§ØšÙÙ Ø§ÙØªØ®Ø²ÙÙØ ÙÙÙÙ ÙØªÙ
+ ØªÙÙÙØ¯ÙØ§ "Ø¹ÙÙ Ø§ÙØ·Ø§ØŠØ±" Ø¹ÙØ¯ Ø§ÙØ§Ø­ØªÙØ§Ø¬ ÙÙØ§0 ØªØ³ØªØ®Ø¯Ù
+ Ø§ÙØ§Ù
+Ø± ÙØ³Ù Ø§ÙØ¹Ø±Ø¶ ÙØªØºÙÙØ± ØªÙ
+ØžÙØ± ÙØ°Ù Ø§ÙØµÙØ­Ø§Øª Ø§ÙÙ
+ÙÙØ¯Ø©Ø ÙØªØ€Ø«Ø± ÙÙ ØªÙ
+ØžÙØ± Ø§ÙØ§Ø²Ø±Ø§Ø± Ø¹ÙØ¯ Ø¹Ø±Ø¶ Ø§ÙÙØ«Ø§ØŠÙ Ø ÙØªØ­Ø¯ÙØ¯ Ø§ÙØ±ÙØ§ØšØ· Ø§ÙØªÙ ØªØ¹Ø±Ø¶ ØšÙØ§Ø³Ø·Ø© Ù
+ØµÙÙ "Datelist" &ndash; ÙÙØ³ Ù
+Ù Ø§ÙØ³ÙÙ ØªØ·ÙÙØ± Ø§ÙØ§Ù
+Ø± ÙØ³Ù Ø§ÙØ¹Ø±Ø¶Ø ÙØ°ÙÙ ØªØ¬Øš ÙØ±Ø§Ø¡Ø© Ø§ÙÙØµÙ 2  Ù
+Ù Ø¯ÙÙÙ ÙØ±ÙÙØ³ØªÙÙ ÙÙÙ
+Ø·ÙØ±ÙÙ0 ÙÙØ§ÙØŽ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ Ø¥Ø¹Ø¯Ø§Ø¯Ø§Øª ÙØ³Ù Ø§ÙØ¹Ø±Ø¶ ÙÙÙÙÙØ© Ø¥ØªØ§Ø­Ø© ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ÙÙØ§0 ØªØ­Øª tab "ÙØ³Ù Ø¹Ø±Ø¶" Ø Ø§ÙÙØ± "Ø³Ù
+Ø§Øª ÙØ³Ù Ø¹Ø±Ø¶"0</p>
+
+<p>ÙÙ
+ÙÙÙ ØªØ·ØšÙÙ Ø£Ù
+Ø± ÙØ³Ù Ø¹Ø±Ø¶ ÙØ§Ù ØŽØŠ ÙÙ ÙØ§ØŠÙ
+Ø© "Ø§Ø®ØªÙØ§Ø± Ø³Ù
+Ø©" Ø§ÙÙ
+ÙØ³Ø¯ÙØ© ÙØ§ÙØªÙ ØªØªØ¶Ù
+Ù ÙÙ Ù
+ØµÙÙ ÙÙØ§ØŠÙ
+Ø© ØšØ³Ù
+Ø§Øª Ù
+Ø¹Ø±ÙØ© Ù
+Ù ÙØšÙ0 ÙÙØ¬Ø¯ ÙÙ
+Ø·ÙÙ ÙÙØªØ­ÙÙ
+ ÙØ¯Ù
+Ø§ ØªÙÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø³Ù
+Ø©0 ØšØ¹Ø¶ Ø§ÙØ³Ù
+Ø§Øª Ù
+Ø¹Ø±ÙØ© ÙÙ
+ÙÙ ØªÙØŽÙØ·ÙØ§ Ø§Ù Ø§Ø®Ù
+Ø§Ø¯ÙØ§ ØšØšØ³Ø§Ø·Ø© Ù
+Ù Ø®ÙØ§Ù Ø¶ØšØ· ØªØ­ÙÙ
+ÙØ§ ØšÙ
+Ø±ØšØ¹Ø§Øª Ø§ÙÙØ­ØµØ ØªØªØ·ÙØš Ø§ÙØ£Ø®Ø±Ù ØªØ­Ø¯ÙØ¯ Ø³ÙØ§Ø³Ù ÙØµØšÙ ÙÙØ³Ù Ø§ÙØ¹Ø±Ø¶0 ÙÙÙÙ ÙØ°Ø§ ØªÙØ¬Ø¯ ÙØ§ØŠÙ
+Ø© Ù
+ØªØ³Ø¯ÙØ© ÙÙÙ "Ø§ÙÙ
+ÙÙÙØ§Øª Ø§ÙÙ
+ØªÙØ§Ø¹ÙØ©" ÙØ§Ø®ØªÙØ§Ø± Ø§Ù Ø§ÙØ£Ø¬Ø²Ø§Ø¡ Ø§ÙØªÙ ØªØ·ØšÙ Ø¹ÙÙÙØ§ Ø³ÙØ§Ø³Ù ÙØ³Ù Ø¹Ø±Ø¶ (Ø§Ø°Ø§ ÙØ§Ù Ø¶Ø±ÙØ±ÙØ§Ù)0 ÙØ³ØªØ®Ø¯Ù
+ Ù
+Ø±ØšØ¹ Ø§ÙÙØµ "Ø³ÙØ§Ø³Ù ÙØ³Ù Ø¹Ø±Ø¶ HTML" ÙØ§Ø¯Ø®Ø§Ù Ø§ÙØ³ÙØ§Ø³Ù ÙØ§Ø®ØªÙØ§Ø± "Ø§ÙÙ
+ØªØºÙØ±Ø§Øª" Ø§ÙÙ
+Ø¹Ø±ÙØ© Ù
+Ù ÙØšÙ0 ÙØ­ØŽØ± Ù
+ØªØºÙØ± ÙÙ Ø§ÙÙ
+ÙÙØ¹ Ø§ÙØ­Ø§ÙÙ Ù
+Ù Ø³ÙØ§Ø³Ù ÙØ³Ù Ø§ÙØ¹Ø±Ø¶Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±ÙØ§ Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ©Ø ÙØ§ÙÙØ± "Ø­ØŽØ±"0"Insert Variable..." combobox.</p>
+
+<p>ØªØ­Ø¯ÙØ¯ ÙØ³Ù Ø¹Ø±Ø¶ Ø§ÙØªØ±Ø§Ø¶Ù ÙÙ
+ÙÙÙ Ù
+Ø­Ø¯Ø¯ ØšØ§Ø®ØªÙØ§Ø± "ÙÙ Ø§ÙÙ
+ÙØ§Ù
+Ø­" Ø­ÙØ« ÙØªÙ
+ Ø§Ø¹ØªÙ
+Ø§Ø¯ ÙØ³Ù Ø§ÙØ¹Ø±Ø¶ ÙØ°Ø§ ÙÙÙ ØªØ·ØšÙÙØ§Øª Ù
+ÙØ§Ù
+Ø­ ÙØ³Ù Ø§ÙØ¹Ø±Ø¶ Ù
+Ø§ÙÙ
+ ÙØªÙ
+ ØªØ­Ø¯ÙØ¯ ØºÙØ±Ù0</p>
+
+<p>ÙØ§Ø¶Ø§ÙØ© Ø£Ù
+Ø± ÙØ³Ù Ø¹Ø±Ø¶ Ø¬Ø¯ÙØ¯0 ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø³Ù
+Ø© Ù
+ÙÙÙØ§Øª ÙØ§ØšÙØ© ÙÙØªØ·ØšÙÙ0 ØªØ¹Ø±Ø¶ Ø§ÙÙÙÙ
+Ø© Ø§ÙØ§ÙØªØ±Ø§Ø¶ÙØ© ÙÙØ°Ø§ Ø§ÙØ£Ù
+Ø± ØšØ§ÙÙÙÙ Ø§ÙØ±Ù
+Ø§Ø¯Ù0 Ø§ÙÙØ± "Add Format"ÙØªÙÙÙØ°ÙØ§ ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 Ø§Ù
+Ø± ÙØ³Ù Ø¹Ø±Ø¶ ÙØ§Ø­Ø¯ ÙÙØ· ÙØ§Ù Ù
+ØŽØªØ±Ù Ø³Ù
+Ø©/ Ù
+ÙÙÙØ§Øª0</p>
+
+<p>ÙØ­Ø°Ù Ø£Ù
+Ø± ÙØ³Ù Ø¹Ø±Ø¶Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©Ø ÙØ§ÙÙØ± "Ø­Ø°Ù Ø£Ù
+Ø± ÙØ³Ù Ø¹Ø±Ø¶"0</p>
+
+<p> ÙÙ
+Ø²ÙØ¯ Ù
+Ù Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª Ø­ÙÙ Ø§ÙÙ
+ØªØºÙØ±Ø§Øª ÙØ³Ù
+Ø§Øª Ø§ÙÙ
+ÙÙÙØ§Øª- Ø§ÙØ±Ø§ Ø§ÙÙØµÙ 2 Ù
+Ù Ø¯ÙÙÙ ÙØ±ÙÙØ³ØªÙÙ ÙÙÙ
+Ø·ÙØ±ÙÙ0</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/formattingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/formattingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/formattingacollection.htm	(revision 13928)
@@ -0,0 +1,45 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="formattingacollection"><font size="5" face="Verdana"><strong>8: ØªÙØ¶ÙØš ØªÙ
+ØžÙØ± Ù
+Ø¬Ù
+ÙØ¹ØªÙ</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Ø¹ÙØ¯ Ø§ÙØ§ÙØªÙØ§Ø¡ Ù
+Ù ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©Ø ÙÙ
+ÙÙÙ ÙÙÙ
+Ø§ ØšØ¹Ø¯ ÙØµÙ ØªÙ
+ØžÙØ±ÙØ§ ÙÙÙ
+Ø³ØªÙÙØ¯0 Ù
+Ø§ÙÙ Ø§Ø³Ù
+Ø§Ø¡ Ø§ÙÙØŽØ§ÙØ§Øª Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+Ø© ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© ÙÙ
+Ø±ØšØ¹ Ø§ÙØšØ­Ø«Ø ÙÙÙ ØªØ¹Ø±Ø¶ ÙØªØ§ØŠØ¬ Ø§ÙØšØ­Ø«Ø Ù
+Ø§ÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØªÙ ØªØžÙØ± Ø¹ÙØ¯ Ø¹Ø±Ø¶ Ø§ÙÙØ«Ø§ØŠÙØ ÙÙ
+ÙÙ ØªÙØ¶ÙØš ÙÙ ÙØ°Ù Ø§ÙØ§ØŽÙØ§Ø¡0 ÙÙØ°Ø§ Ø§ÙÙØ³Ù
+ ÙØŽØ±Ø­ ÙÙ ÙÙÙÙØ© Ø¹Ù
+Ù ÙØ°Ø§0</p>
+
+
+
+
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/generalsettings.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/generalsettings.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/generalsettings.htm	(revision 13928)
@@ -0,0 +1,70 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="generalsettings"><font size="5" face="Verdana"><strong>8.2: Ø¹Ø§Ù
+0</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙØŽØ±Ø­ ÙÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+  ÙÙÙÙØ© Ø§Ø³ØªØ¹Ø±Ø§Ø¶ Ù alter Ø§ÙØªÙØ¶ÙØš Ø§ÙØ¹Ø§Ù
+ ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 Ø§ÙÙØ§Ù ØªØ­Øª tab "ÙØ³Ù Ø¹Ø±Ø¶" Ø§ÙÙØ± "Ø¹Ø§Ù
+"0</p>
+
+<p>ÙÙÙØ§ ÙØªÙ
+ Ø¥Ø¹Ø¯Ø§Ø¯ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙØªÙØ³ÙØ±ÙØ§0 ÙÙÙ ØªØªØ¶Ù
+Ù Ø§ÙØ¹ÙÙØ§Ù ÙØ§ÙÙØµÙ ÙØ§ÙØªÙ ØªØ¯Ø®Ù ÙÙ ØšØ¯Ø§ÙØ© ÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø©0</p>
+
+<p>Ø§ÙÙØ§ÙØ Ø¹ÙØ§ÙÙÙ Ø§ÙØšØ±ÙØ¯ Ø§ÙØ§ÙÙØªØ±ÙÙÙ ÙÙ
+ÙØŽØŠ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙ
+Ø§ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙØªØªÙØ­ ÙÙ Ø§ÙØ­ÙÙÙ Ø§ÙØªÙ ØªÙÙ Ø£Ø¹ÙØ§Ù ØªØºÙÙÙØ± Ø¹ÙÙØ§Ù  Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©Ø Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙØ°Ù ØªØ®Ø²Ù ÙÙÙ Ù
+ÙÙØ§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙØ°Ø§ ÙØ§ ÙÙ
+ÙÙ ØªØ¹Ø¯ÙÙÙ0 Ø§ÙØªØ§ÙÙØ Ù
+Ø®ØµØµ (ÙÙ ØŽÙÙ URL) ÙØ±Ù
+Ø² Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙØ¹Ø±Ø¶Ù ÙÙ Ø§ÙØ¬Ø§ÙØš Ø§ÙØ£Ø¹ÙÙ ÙØ³Ø§Ø±Ø§Ù ÙÙ ØµÙØ­Ø© "Ø­ÙÙ" &ndash; ÙÙÙÙ Ø±Ù
+Ø² Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+ ÙÙ Ø§ÙØµÙØ­Ø© Ø§ÙØ¹Ø§Ù
+Ø© ÙÙ
+ÙØªØšÙ ÙØ±ÙØ³ØªÙÙ ÙØ±Ø§ØšØ· ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 Ø«Ù
+ Ù
+Ø±ØšØ¹ ÙØ­Øµ ÙØªØ­Ø¯ÙØ¯ Ø¹Ù
+Ø§ Ø§Ø°Ø§ ÙØ§ÙØª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø¹Ø§Ù
+Ø©0 Ø§Ø®ÙØ±Ø§Ù Ù
+Ø±ØšØ¹ "ÙØµÙ Ù
+Ø¬Ù
+ÙØ¹Ø©" Ø§ÙÙØµÙ ÙÙØµÙÙØ§0<a href="creatingacollection.htm">Ø¥ÙØŽØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø© Ø¬Ø¯ÙØ¯Ø©</a>.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/help.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/help.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/help.xml	(revision 13928)
@@ -0,0 +1,3307 @@
+<?xml version="1.0"?>
+<!DOCTYPE TutorialList [
+     <!ENTITY nbsp "&#160;">
+     <!ENTITY rarr "&#8594;">
+     <!ENTITY mdash "&#8212;">
+]>
+
+<Document>
+<Section name="introduction">
+<Title>
+<Text id="1">Ø§ÙØªØ¹Ø±ÙÙ</Text>
+</Title>
+<Text id="2">ÙØ§Ø¬ÙØ© ÙØ±ØšÙØ³ØªÙÙ ÙÙ Ø£Ø¯Ø§Ø© ÙØªØ­Ø¯ÙØ¯ ÙØªØ¬Ù
+ÙØ¹ Ø§ÙÙØ«Ø§ØŠÙ0 Ø«Ù
+ ØšÙØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙÙ
+ÙØªØšØ© Ø§ÙØ±ÙÙ
+ÙØ©0 ØªÙÙØ± Ø§ÙÙØµÙÙ ÙÙØžØ§ØŠÙ ØšØ±Ù
+Ø¬ÙØ§Øª ÙØ±ÙÙØ³ØªÙÙ ÙÙÙ
+ÙØªØšØ© Ø§ÙØ±ÙÙ
+ÙØ© Ù
+Ù Ø®ÙØ§Ù ÙØ§Ø¬ÙØ© Ø±Ø³ÙÙ
+ÙØ© ØšØ§ÙÙÙØ± Ø¹ÙÙ Ø§ÙÙÙÙØ©Ø§ÙÙØžÙÙØ© Ø§ÙÙ
+Ø·ÙÙØšØ©0.</Text>
+<Section name="ofmiceandmenus">
+<Title>
+<Text id="3">Ø§ÙÙØ£Ø±Ø© Ù Ø§ÙÙÙØ§ØŠÙ
+</Text>
+</Title>
+<Text id="4">ÙÙÙØ± ÙØ°Ø§ Ø§ÙÙØ³Ù
+ Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª Ø§ÙØ£Ø³Ø§Ø³ÙØ© ÙÙØªÙØ§Ø¹Ù Ù
+Ø¹ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ0 Ø§Ø°Ø§ ÙÙØª Ù
+Ø¹ØªØ§Ø¯Ø§ Ø¹ÙÙ Ø§ÙØªØ¹Ø§Ù
+Ù Ù
+Ø¹ ØšØ±Ø§Ù
+Ø¬  Ù
+ØªØµÙØ­ Ø§ÙØ§ÙØªØ±ÙØª Ù Microsoft Office ÙÙ
+Ø±ØªØ§Ø­Ø§Ù ÙÙØªØ¹Ø§Ù
+Ù Ù
+Ø¹ ÙÙØ± Ø§ÙÙØ£Ø±Ø©  ÙØ§ÙÙÙØ§ØŠÙ
+0 Ø§ÙØªÙÙ Ø¥ÙÙ <Reference target="howtoavoidthisdocument"/>.</Text>
+<Text id="5">ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ØªØªØšØ¹ ØªÙØ§ÙÙØ¯ ØšØ±Ø§Ù
+Ø¬ Windows ÙÙ
+ØšÙÙØ© Ø¹ÙÙ Ø§ÙÙ
+Ø¹Ø±ÙØ© ØšÙØ§0</Text>
+<Text id="6">ÙÙ Ø¬Ø²Ø¡ Ù
+Ù Ø§ÙØŽØ§ØŽØ© ØªØªÙØ§Ø¹Ù Ù
+Ø¹ÙØ Ù
+Ø«Ù Ø²Ø± Ø£Ù Ø­ÙÙ ÙØµ ÙØ³Ù
+Ù "ØªØ­ÙÙ
+" ÙØ³Ù
+Ù Ø§ÙØªØ­ÙÙ
+ ÙÙ Ø§Ù ÙØ­ØžØ© Ø§ÙØ²Ù
+ÙÙØ© "ØªØ±ÙÙØ²" ÙØ¶Ø§Ø¡ ÙÙØ³ØªØ¬ÙØš ÙÙÙØ­Ø© Ø§ÙÙ
+ÙØ§ØªÙØ­0 Ù
+Ø®ØªÙÙ ÙÙØ§Ø· Ø§ÙØªØ­ÙÙ
+ ØªØªÙØ­ ÙÙ Ø§Ø®ØªÙØ§Ø± Ø§ÙØ£Ø¬Ø²Ø§Ø¡ Ø§ÙÙ
+Ø¶Ø§Ø¡Ø© ÙÙ Ø§ÙØ£Ø²Ø±Ù Ø§ÙØºØ§Ù
+Ù0 ØšØ¹Ø¶ Ø§ÙØ£Ø¬Ø²Ø§Ø¡ ÙÙÙÙØ§ Ø±Ù
+Ø§Ø¯Ù ÙÙØ¯ÙØ§ÙØ© Ø¹ÙÙ Ø£ÙÙØ§ ØºÙØ± Ù
+ÙØŽØ·Ø©0</Text>
+<Text id="7">ÙÙ
+ÙÙÙ ØªØ­Ø±ÙÙ ÙÙÙØ± Ù
+ÙØ§ØªÙØ­ Ø§ÙÙØ£Ø±Ø© ÙÙ
+ÙÙØ§Ù ÙÙØ³Ø§Ø±Ø§Ù ØšØµÙØ±Ø© Ø§Ø¹ØªÙØ§Ø¯ÙØ©0 ÙÙ
+ÙÙÙ Ø³Ø­Øš ÙØ«ÙØ± Ù
+Ù Ø§ÙÙ
+ÙÙÙØ§Øª ØšØ§ÙÙÙØ± ÙØ§ÙØ§ØšÙØ§Ø¡ Ø¹ÙÙ Ø§ÙØ²Ø± Ø§ÙØ£ÙÙ
+Ù Ø«Ù
+ Ø§Ø³ÙØ§Ø·ÙØ§ ÙÙ Ø§Ù Ù
+ÙØ§Ù Ø¢Ø®Ø± ÙØªØ±Ù Ø§ÙØ²Ø±0 ÙÙ
+ÙÙ Ø­Ø« Ø§ÙØ£Ù
+Ø§ÙÙ Ø§ÙÙ
+Ø³ØªÙØ¯ÙØ© ØšØªÙ
+Ø±ÙØ± Ù
+Ø€ØŽØ± Ø§ÙÙØ£Ø±Ø© ÙÙÙÙØ§0</Text>
+<Text id="8">ÙÙ
+ÙÙÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+ ÙÙØ­Ø© Ø§ÙÙ
+ÙØ§ØªÙØ­ ÙØ·ØšØ§Ø¹Ø© Ø§ÙÙØµÙØµ ÙÙ Ø§ÙØ­ÙÙÙ0 Ù
+ÙØªØ§Ø­ [tab] ÙÙÙØ± Ø§ÙØªØ±ÙÙØ² ØšÙÙ Ù
+Ø®ØªÙÙ Ø§ÙØ­ÙÙÙ0</Text>
+<Text id="11">ÙØ§ÙÙØ§Ø¡ ØšØ±ÙØ§Ù
+Ø¬ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± "Ø®Ø±ÙØ¬" Ù
+Ù ÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙÙ0 Ø³ÙÙ ØªØ­ÙØž Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø£ÙÙØ§0</Text>
+</Section>
+<Section name="howtoavoidthisdocument">
+<Title>
+<Text id="12">ÙÙÙ ØªØªØ¬ÙØš ÙØ±Ø§Ø¡Ø© ÙØ°Ù Ø§ÙÙØ«ÙÙØ©</Text>
+</Title>
+<Text id="13"> ÙØ§  ØªÙØ±Ø£ ÙØµ Ø§ÙÙ
+Ø³Ø§Ø¹Ø¯Ø© Ù
+Ù Ø£ÙÙÙ Ø¥ÙÙ Ø£Ø®Ø±Ù0 ÙÙ
+ÙÙÙ ÙØ±Ø§Ø¡Ø© ÙØ¯Ø± Ù
+ÙÙ ÙÙ
+ÙÙÙ  Ù
+Ù Ù
+Ø¹Ø±ÙØ© ÙÙÙÙØ© Ø§ÙØ­ØµÙÙ Ø¹ÙÙ Ù
+Ø³Ø§Ø¹Ø¯Ø© ÙØ­Ù Ù
+ØŽÙÙØ© Ù
+Ø¹ÙÙØ©0</Text>
+<Text id="14">ÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+Ø³Ø§Ø¹Ø¯Ø© ØªØ­Ø¯Ø¯ ÙÙ Ù
+Ø§ÙÙ Ø§ÙØ¹ÙÙØ§Ù Ø§ÙÙ
+ÙØ§Ø³Øš Ù
+Ù ØšÙÙ Ø§ÙØ¹ÙØ§ÙÙÙ Ø§ÙØ¬Ø§ÙØšÙØ© Ø§ÙÙ
+Ø³ØšÙÙØ© Øš "Ø§ÙÙÙÙØ©"  Ø§ÙÙØªØ§Øš0</Text>
+<Text id="15">Ø¹ÙØ¯Ù
+Ø§ ØªÙ
+ÙØ¶Ø¹ Ù
+Ø€ØŽØ± Ø§ÙÙØ£Ø±Ø© Ø¹ÙÙ Ø¹ÙÙØ§Ù Ù
+Ø­Ø¯Ø¯ ÙØžÙØ± ÙÙ Ù
+Ø±ØšØ¹ ÙØµ ÙØŽØ±Ø­ ÙÙ ÙÙÙÙØ© Ø§ÙØ¬Ø§Ø² Ø§ÙÙ
+ÙÙ
+Ø©0</Text>
+<Text id="16">ÙØšÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+  ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙØ Ø¹ÙÙÙ Ø£ÙÙØ§ ÙØ±Ø§Ø¡Ø© Ø¯ÙÙÙ ÙØ±ÙÙØ³ØªÙÙ0</Text>
+</Section>
+</Section>
+<Section name="startingoff">
+<Title>
+<Text id="17">Ø§ÙØšØ¯Ø§ÙØ©</Text>
+</Title>
+<Text id="18">ÙØºØ·Ù ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ÙÙÙÙØ© Ø¥ÙØŽØ§Ø¡Ø ØªØ­Ù
+ÙÙ ØØ­ÙØž Ù Ø¥ÙØºØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª.</Text>
+<Section name="creatingacollection">
+<Title>
+<Text id="19">Ø¥ÙØŽØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø© Ø¬Ø¯ÙØ¯Ø©</Text>
+</Title>
+<Text id="20">ÙØ§ÙØŽØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø© Ø¬Ø¯ÙØ¯Ø©Ø Ø§ÙØªØ­ ÙØ§ØŠÙ
+Ø© "Ù
+ÙÙ" ÙÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± "Ø¬Ø¯ÙØ¯" ØªØžÙØ± ÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø© Ù
+Ù Ø§ÙØ­ÙÙÙ Ø§ÙÙØµÙØ© Ø§ÙØªÙ ÙØ¬Øš ØªØ¹ØšØŠØªÙØ§0</Text>
+<Text id="21">"Ø¹ÙÙØ§Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©" ÙÙ Ø§ÙÙØµ Ø§ÙØ°Ù ÙØ¹Ø±Ø¶ Ø£Ø¹ÙÙ ØµÙØ­Ø© Ø§ÙÙØš ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙÙ
+ÙÙ Ø£Ù ÙÙÙÙ ØšØ§Ù Ø·ÙÙ0</Text>
+<Text id="22">"ÙØµÙ Ø§ÙÙ
+Ø­ØªÙÙØ§Øª" ÙØ¬Øš Ø£Ù ÙØµÙ ÙØ¯Ø± Ø§ÙÙ
+Ø³ØªØ·Ø§Ø¹ Ù
+Ø­ØªÙÙØ§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 ÙØ§Ø³ØªØ®Ø¯Ø§Ù
+  Ù
+ÙØªØ§Ø­ "Enter" ÙØ§ÙØŽØ§Ø¡ Ø§ÙÙÙØ±Ø§Øª0</Text>
+<Text id="23">Ø§Ø®ÙØ±Ø§Ù ÙØ¬Øš ØªØ­Ø¯ÙØ¯  Ø§Ø°Ø§ Ù
+Ø§ ÙØ§Ù ØªÙ
+ØžÙØ± ÙÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ù
+ØšÙÙ Ø¹ÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø© Ø³Ø§ØšÙØ©0 Ø£Ù Ø§Ø³ØªØ®Ø¯Ø§Ù
+ Ø§ÙØšØ¯Ø§ÙØ© Ø§ÙØ§ÙØªØ±Ø§Ø¶ÙØ© "Ù
+Ø¬Ù
+ÙØ¹Ø© Ø¬Ø¯ÙØ¯Ø©"0 Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙØ¬Ø¯ÙØ¯Ø© Ø§ÙØ§ÙØªØ±Ø§Ø¶ÙØ© Ø§ÙØ¬Ø¯ÙØ¯Ø© ÙÙØ§ ØªÙÙÙÙ Ù
+Ø¹ÙØ§Ø±Ù ÙØªØ³ØªØ®Ø¯Ù
+ Ù
+Ø¹ÙØ§Ø± Ø¯ØšÙÙ ÙÙØ± ÙÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª0 ÙÙÙ
+ÙÙ ØªØºÙÙØ± ÙØ°Ø§ ÙÙÙ
+Ø§ ØšØ¹Ø¯0
+</Text>
+<Text id="24">Ø§ÙÙØ± "OK" ÙØ§ÙØŽØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø©0 </Text>
+<Text id="25">Ø§ÙÙØ± "Ø¥ÙØºØ§Ø¡" ÙÙØ±Ø¬ÙØ¹ Ø§ÙÙÙØ±Ù ÙÙØŽØ§ØŽØ© Ø§ÙØ±ØŠÙØ³ÙØ© 0.</Text>
+</Section>
+<Section name="savingacollection">
+<Title>
+<Text id="26">Ø­ÙØž Ù
+Ø¬Ù
+ÙØ¹Ø©</Text>
+</Title>
+<Text id="27">Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙØ³ Ù
+ØªÙ
+Ø§Ø«ÙØ§Ù Ù
+Ø¹ Ø§Ø¹Ø¯Ø§Ø¯ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙØ§Ø³ØªØ®Ø¯Ø§Ù
+ ÙÙ ÙØ±ÙÙØ³ØªÙÙ   (see <Reference target="producingthecollection"/>).</Text>
+<Text id="28">ÙØªÙÙÙ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ Ø­Ù
+Ø§ÙØ© Ø¹Ù
+ÙÙ ØšØ­ÙØžÙ Ø¹ÙØ¯ Ø§ÙØ®Ø±ÙØ¬ Ù
+Ù Ø§ÙØšØ±ÙØ§Ù
+Ø¬ Ø£Ù ØªØ­Ù
+ÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø© Ø£Ø®Ø±Ù0</Text>
+<Text id="29a"> ØªØ­ÙØž Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª ÙÙ Ù
+Ø¬ÙØ¯ "collect" Ø¶Ù
+Ù ØªØ«ØšÙØª ÙØ±ÙÙØ³ØªÙÙ ÙØªØ³Ù
+Ù ØšØ§Ø³Ù
+ ÙØµÙØ± Ù
+Ù Ø§Ø³Ù
+ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 ØªØ­ÙØž Ø§ÙÙØ«Ø§ØŠÙ ÙÙ Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙÙØ±Ø¹Ù "import"  ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª  ØªØ­ÙØž ÙÙØ§ Ø£ÙØ¶Ø§Ù  ÙÙ Ù
+ÙÙ "metadata.xml" Ù
+Ø¹ÙÙÙ
+Ø§Øª Ø§ÙØªÙÙÙÙ ØªØ­ÙØž ÙÙ Ù
+ÙÙ "collect. Cfq " ÙÙ Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙÙØ±Ø¹Ù etc." ØªØ­ÙØž ØšØ¹Ø¶ Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª ÙÙ Ù
+ÙÙ ØšØ§Ø³Ù
+ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØšØ§Ù
+ØªØ¯Ø§Ø¯ Ù
+ÙÙ "col"
+</Text>
+</Section>
+<Section name="openingacollection">
+<Title>
+<Text id="30">ÙØªØ­ Ù
+Ø¬Ù
+ÙØ¹Ø© Ù
+ÙØ¬ÙØ¯Ø©</Text>
+</Title>
+<Text id="31">0</Text>
+<Text id="32">ÙÙ Ø­Ø§ÙØ© ØªØŽØºÙÙ Ø£ÙØ«Ø± Ù
+Ù ØšØ±ÙØ§Ù
+Ø¬ ÙÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ Ù
+Ø¹Ø§ÙØ ÙØ§Ù Ø§ÙÙ
+ÙÙØ§Øª Ø°Ø§Øª Ø§ÙØµÙØ© ØªØºÙÙ ÙÙ
+ÙØ¹ Ø§ÙØªØ¯Ø§Ø®Ù0 Ø¹ÙØ¯ ÙØªØ­ Ù
+Ø¬Ù
+ÙØ¹Ø©  ÙÙØŽØ£ Ù
+ÙÙ ØºÙÙ ØµØºÙØ± ÙÙ Ù
+Ø³Ø§Ø±ÙØ§. ÙÙÙÙ
+ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ØšØ§ÙØªØ£ÙØ¯ Ù
+Ù ÙØ¬ÙØ¯ ÙØ°Ø§ Ø§ÙÙ
+ÙÙ ÙØšÙ ÙØªØ­ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© .Ø¹ÙÙ Ø¢Ù Ø­Ø§Ù Ø¹ÙØ¯Ù
+Ø§ ÙØªÙ
+ ØºÙÙ    ÙØ§Ø¬ÙØ©  Ø§ÙÙ
+ÙØªØšÙ ØšØµÙØ±Ø© Ø³ÙÙÙ
+Ù ÙØªÙÙØ± Ø§Ø­ÙØ§ÙØ§Ù Ù
+ÙÙ Ø§ÙØºÙÙ ÙÙ Ù
+ÙØ§ÙÙØ ÙÙÙÙ
+ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ØšØ§Ø³ØªÙØ³Ø§Ø±Ù  Ø§Ø°Ø§ Ù
+Ø§ ÙÙØª ØªÙØ¯ "Ø§Ù
+ØªÙØ§Ù" Ø§ÙØªØ­ÙÙ
+ ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø©.ØªØµØ±Ù Ø¹ÙÙ Ø§ÙÙØ­Ù Ø§ÙØ°Ù ÙØ±Ø¶ÙÙ Ø¥ÙØ§ Ø¥Ø°Ø§ ÙÙØª ØªØ¹ØªÙØ¯ Ø§Ù ØŽØ®ØµØ§ Ø¢Ø®Ø± ÙØ³ØªØ®Ø¯Ù
+ ÙÙØ³ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©</Text>
+<Text id="33">Ø¹ÙØ¯ ÙØªØ­ Ù
+Ø¬Ù
+ÙØ¹Ø© ÙÙ
+ ÙØªÙ
+ Ø§ÙØŽØ§Ø€ÙØ§ ØšÙØ§Ø³Ø·Ø© ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙØ Ø³ÙÙ ÙØªÙ
+ Ø§Ø¹ØªÙ
+Ø§Ø¯ Ù
+Ø¹ÙØ§Ø± Ø¯ØšÙÙ ÙÙØ± ÙÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙØ§0 ÙÙ
+Ø§ ÙØªÙ
+ Ø§Ø³ØªÙØ±Ø§Ø¯  Ø£Ù ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª ÙÙ
+Ø§ ÙÙ Ø¹ÙØ¯ Ø¬ÙØš Ù
+ÙÙØ§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØšÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª0 ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ Ù
+ÙØµÙÙ ÙÙ <Reference target="importingpreviouslyassignedmetadata"/> section. </Text>
+</Section>
+<Section name="deletingcollections">
+<Title>
+<Text id="34">Ø¥ÙØºØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª</Text>
+</Title>
+<Text id="35">Ø¹ÙØ¯Ù
+Ø§ ØªØ±ÙØ¯ Ø¥ÙØºØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø§Øª Ù
+Ù ØªØ«ØšÙØª ÙØ±ÙÙØ³ØªÙÙ ØšØµÙØ© Ø¯Ø§ØŠÙ
+Ø©0 ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± "Ø¥ÙØºØ§Ø¡00" Ù
+Ù ÙØ§ØŠÙ
+Ø©  "Ù
+ÙÙ" - ØªØžÙØ± ÙØ§ØŠÙ
+Ø© ØšØ§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± ÙØ§Ø­Ø¯Ø© ÙÙ
+Ø¹Ø±ÙØ© ÙØµÙÙØ§ Ø«Ù
+ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ù
+Ø±ØšØ¹ Ø§ÙÙØ­Øµ Ø§Ø³ÙÙ Ù
+Ø±ØšØ¹ Ø§ÙØ­ÙØ§Ø± ÙØ§ÙÙØ± "Ø§ÙØºØ§Ø¡" ÙØ¬Øš ØªÙØ®Ù Ø§ÙØ­Ø°Ø± ÙØ§Ù ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ ØºÙØ± Ù
+Ø±Ø¯ÙØ¯0
+</Text>
+</Section>
+</Section>
+<Section name="downloadingfiles">
+<Title>
+<Text id="36">ØªÙØ²ÙÙ Ø§ÙÙ
+ÙÙØ§Øª Ù
+Ù Ø§ÙØ¥ÙØªØ±ÙØª</Text>
+</Title>
+<Text id="37">ÙØµÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+<AutoText key="glidict::GUI.Download"/>  ÙÙÙÙØ© Ø¥Ø¹Ø¯Ø§Ø¯ Ù
+ÙÙ
+Ø© ØªÙØ²ÙÙ ÙØ§ÙØªØ­ÙÙ
+ ÙÙ Ø§Ø¬Ø±Ø§Ø¡ Ø§ÙØªÙØ²ÙÙØ ÙØ§ØªØ§Ø­Ø© Ø§ÙØªÙØ²ÙÙ Ø§ÙÙØ± Ø§ÙØ²Ø±0 ÙÙ Ù
+ÙØªØµÙ Ø§Ø¹ÙÙ Ø§ÙØŽØ§ØŽÙØ ØªØªÙÙØ± ÙÙ Ø¹ÙØ§ØµØ± Ø§ÙØªØ­ÙÙ
+ ÙÙ Ø§Ø¬Ø±Ø§Ø¡ Ø§ÙØªÙØ²ÙÙ0 ÙÙÙÙ ÙØµÙ Ø§ÙØŽØ§ØŽØ© Ø§ÙØ§Ø³ÙÙ ÙØ§Ø±Øº Ù
+ØšØ¯ØŠÙØ§Ù ÙØ°ÙÙ ÙØªÙÙÙØ± ÙÙØ§ØŠÙ
+ Ø§ÙÙ
+ÙÙ
+Ø§Øª Ø§ÙÙ
+ÙØ¬Ø²Ø© ÙØ§ÙÙ
+Ø¹ÙÙØ©0</Text>
+<Section name="themirrorview">
+<Title>
+<Text id="38">Ù
+ØŽÙØ¯ Ø§ÙØªÙØ²ÙÙ</Text>
+</Title>
+<Text id="39">ÙØµÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+<AutoText key="glidict::GUI.Download"/>  ÙÙÙÙØ© Ø¥Ø¹Ø¯Ø§Ø¯ Ù
+ÙÙ
+Ø© ØªÙØ²ÙÙ ÙØ§ÙØªØ­ÙÙ
+ ÙÙ Ø§Ø¬Ø±Ø§Ø¡ Ø§ÙØªÙØ²ÙÙØ ÙØ§ØªØ§Ø­Ø© Ø§ÙØªÙØ²ÙÙ Ø§ÙÙØ± Ø§ÙØ²Ø±0 ÙÙ Ù
+ÙØªØµÙ Ø§Ø¹ÙÙ Ø§ÙØŽØ§ØŽÙØ ØªØªÙÙØ± ÙÙ Ø¹ÙØ§ØµØ± Ø§ÙØªØ­ÙÙ
+ ÙÙ Ø§Ø¬Ø±Ø§Ø¡ Ø§ÙØªÙØ²ÙÙ0 ÙÙÙÙ ÙØµÙ Ø§ÙØŽØ§ØŽØ© Ø§ÙØ§Ø³ÙÙ ÙØ§Ø±Øº Ù
+ØšØ¯ØŠÙØ§Ù ÙØ°ÙÙ ÙØªÙÙÙØ± ÙÙØ§ØŠÙ
+ Ø§ÙÙ
+ÙÙ
+Ø§Øª Ø§ÙÙ
+ÙØ¬Ø²Ø© ÙØ§ÙÙ
+Ø¹ÙÙØ©0 </Text>
+<Text id="39a"> ØªÙØ¬Ø¯ ØšØ±ÙØªÙÙÙÙØ§Øª Ø¹Ø¯ÙØ¯Ø© ÙÙ
+ÙÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+ÙØ§ ÙØªÙØ²ÙÙ Ø§ÙØªØ³Ø¬ÙÙØ§Øª ÙÙØ§ØŠÙ
+Ø© Ø§ÙØšØ±ÙØªÙÙÙØ§Øª ØªÙØ¬Ø¯ Ø£Ø¹ÙÙ Ø¬ÙØ© Ø§ÙÙØ³Ø§Ø±0.</Text>
+<Text id="39b"><b>Web:</b>  ØªÙØ²ÙÙ ØµÙØ­Ø§Øª  Ø§ÙÙØš ÙØ§ÙÙ
+ÙÙØ§Øª Ø¹ØšØ± HTTP ÙFTP </Text>
+<Text id="39c"><b>OAI:</b> ØªÙØ²ÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙØªØ³Ø¬ÙÙØ§Øª Ù
+ØšØ§Ø¯Ø±Ø©  Ø§ÙØ§Ø±ØŽÙÙ Ø§ÙÙ
+ÙØªÙØ­  OAI
+</Text>
+<Text id="39d"><b>Z3950:</b>  ØªÙØ²ÙÙ ØªØ³Ø¬ÙÙØ§Øª MARC Ø§ÙØªÙ ØªØ¶Ø§ÙÙ Ø³Ù
+Ø§Øª ØšØ­Ø« Ù
+Ø¹ÙÙ ÙÙ ØšØ­Ø« Z3950
+</Text>
+<Text id="39e"><b>SRW:</b>  ØªÙØ²ÙÙ ØªØ³Ø¬ÙÙØ§Øª MARCXML Ø§ÙØªÙ ØªØ¶Ø§ÙÙ Ø³Ù
+Ø§Øª ØšØ­Ø« Ù
+Ø¹ÙÙ ÙÙ Ù
+Ø²ÙØ¯ SRW</Text>
+<Text id="39f"> ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø§ÙÙÙ
+Ø· Ø§ÙÙ
+ÙØ§Ø³Øš ØšØ§ÙÙÙØ± Ø¹ÙÙÙ Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ¬ÙØ¯Ø© ÙÙ Ø§ÙØ¬Ø²Ø¡ Ø§ÙØ§ÙØ³Ø± ÙØ§ÙØªÙ ØªØ¹Ø±Ø¶ Ø§ÙØ®ÙØ§Ø±Ø§Øª Ø§ÙÙ
+ÙØ¬ÙØ¯Ø© ÙÙÙ
+Ø· Ø§ÙØªÙØ²ÙÙ0 ÙÙ
+Ø¹Ø±ÙØ© ØªÙØ§ØµÙÙ ÙÙ ØªÙØ²ÙÙ Ø­ÙÙ ØšØ§ÙÙ
+Ø€ØŽØ± ÙÙÙ Ø§ÙØ®ÙØ§Ø± ØªØžÙØ± ÙÙ ØªÙØ§ØµÙÙ Ø§ÙÙÙ
+Ø· ÙÙ Ù
+Ø±ØšØ¹ Ù
+Ø³Ø§Ø¹Ø¯Ø©0 ØšØ¹Ø¶ Ø§ÙØ®ÙØ§Ø±Ø§Øª ÙÙ "Ø§Ø®ØªÙØ§Ø±ÙØ©" ÙØªØ¹Ø±Ø¶ ØšÙ
+Ø±ØšØ¹ ÙØ­Øµ ÙØªØ£ØŽÙØ±Ù Ø¹ÙØ¯ Ø§Ø³ØªØ®Ø¯Ø§Ù
+  Ø§ÙØ®ÙØ§Ø± . Ø§ÙØ§Ø®Ø±Ù "Ù
+Ø·ÙÙØšØ©" ÙÙØ§ ÙØªÙÙØ± ÙÙÙØ§ Ù
+Ø±ØšØ¹Ø§Øª ÙØ­Øµ  ÙÙØ¬Øš Ø§Ø¹Ø·Ø§Ø¡ Ø§ÙÙÙÙ
+Ø© ÙØšÙ Ù
+ØšØ§ØŽØ±Ø© Ø§ÙØªÙØ²ÙÙ0
+</Text>
+<Text id="39g"> Ø¹ÙØ¯Ù
+Ø§ ÙØªÙ
+ Ø¥Ø¹Ø¯Ø§Ø¯ Ø§ÙØªÙÙÙÙØ Ø§ÙÙØ± <AutoText key="glidict::Download.ServerInformation"/> ÙÙØ­Øµ Ù
+Ø¹ÙÙÙ
+Ø§Øª Ù
+Ø²ÙØ¯ Ø§ÙØ§ØªØµØ§Ù ÙØµÙØ­Ø© ÙØµÙØ­Ø© Ø§ÙÙØš Ø£Ù Ø£ÙÙØ±<AutoText key="glidict::Mirroring.Download"/> ÙØšØ¯Ø¡ Ø§ÙØªÙØ²ÙÙ0
+ </Text>
+<Text id="39g-1">ÙÙØ¬Ø¯ Ø²Ø±ÙÙ Ø¢Ø®Ø±ÙÙ ÙÙØªØ­ÙÙ
+ Ø²Ø± "Ø§ÙØªÙØµÙÙØ§Øª" ÙØ§ÙØ°Ù ÙØ±ØšØ· ØµÙØ­Ø© Ø§ÙØ§ØªØµØ§Ù Ø­ÙØ« ÙÙ
+ÙÙ ØªØ¹Ø¯ÙÙ Ø¥Ø¹Ø¯Ø§Ø¯Ø§Øª Ø§ÙØšØ±ÙÙØ³ÙØ Ø²Ø± "Ù
+Ø³Ø­ Ø§ÙØ°Ø§ÙØ±Ø©" Ø­ÙØ« ÙÙ
+ÙÙ Ø¥ÙØºØ§Ø¡ ÙÙ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+ÙØ²ÙØ© Ù
+Ù ÙØšÙ0 Ø³ÙÙ ØªØ­ØªØ§Ø¬  ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª  ÙØ§Ø¹Ø¯Ø§Ø¯ Ø§ÙØšØ±ÙÙØ³Ù Ø§Ø°Ø§ ÙÙØª ØªØ³ØªØ®Ø¯Ù
+  Ù
+Ø²ÙØ¯ ØšØ±ÙÙØ³Ù ÙÙØ§ØªØµØ§Ù ØšØ§ÙØ§ÙØªØ±ÙØª0 Ø§Ø°Ø§ ÙØ§ÙØª ÙÙØ§Ù Ø­ÙØ¬Ø© ÙØªØ£ÙÙØ¯ Ø§ÙØªØ¹Ø±ÙÙ ÙØ§Ù Ù
+Ø²ÙØ¯ Ø§ÙØšØ±ÙÙØ³Ù Ø³ÙÙ ÙØ­ØªÙ ÙØ§Ø³Ù
+ Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+ ÙÙÙÙ
+Ø© Ø§ÙÙ
+Ø±ÙØ±0 ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ÙØ§ ÙØ­ÙØž ÙÙÙ
+Ø§Øª Ø§ÙÙ
+Ø±ÙØ± ØšÙÙ "session"
+</Text>
+<Text id="40">Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙØªÙ ØªÙ
+ ØªÙØ²ÙÙÙØ§ ØªØ®Ø²Ù ÙÙ Ù
+Ø¬ÙØ¯ ÙØ³Ù
+Ù <AutoText key="glidict::Tree.DownloadedFiles"/> (ÙÙÙ Ù
+ØªÙÙØ±Ø© Ø¹ÙØ¯ ØªÙØ¹ÙÙ Ø§ÙØªÙØ²ÙÙ) ÙÙÙ
+ÙÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+ÙØ§ ÙÙ Ø£Ù Ù
+Ø¬Ù
+ÙØ¹Ø©. ØªØªÙ
+ ØªØ³Ù
+ÙØ© Ø§ÙÙ
+ÙÙØ§Øª ØšØ§ÙØ§Ø³Ù
+ Ø§ÙÙØ§Ù
+Ù ÙØ¹ÙÙØ§Ù  Ø§ÙÙ
+ÙØ§Ø±Ø¯ Ø§ÙÙ
+ÙØ­Ø¯ URL (ÙØªÙØ²ÙÙØ§Øª Ø§ÙÙØš Ø£Ù Ù
+Ø²ÙØ¬ Ù
+Ù Ø¹ÙÙØ§Ù Ø§ÙÙ
+ÙØ§Ø±Ø¯ Ø§ÙÙ
+ÙØ­Ø¯ URL ÙÙÙÙ
+ Ø§ÙØ®ÙØ§Ø± (ÙØ§ÙÙ
+Ø§Ø· Ø§ÙØªÙØ²ÙÙ Ø§ÙØ£Ø®Ø±Ù) ÙØªÙ
+ Ø§ÙØŽØ§Ø¡ Ù
+Ø¬ÙØ¯ Ø¬Ø¯ÙØ¯ ÙØ§Ù Ù
+Ø¶ÙÙ Ù
+ØªØšÙØ¹Ø§Ù ØšÙ
+Ø¬ÙØ¯Ø§Øª ÙØ±Ø¹ÙØ© ØªÙ
+Ø§Ø«Ù Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª Ø§ÙÙØ±Ø¹ÙØ© ÙÙÙ
+Ø¬ÙØ¯ Ø§ÙÙ
+ÙØ²Ù ÙØªÙÙÙØ± Ø§ÙØ¯ÙØ©0
+</Text>
+<Text id="42">ØªÙÙØ± ÙØ§ØŠÙ
+Ø© ØªÙØ²ÙÙ ÙÙÙ Ø§Ø¬Ø±Ø§Ø¡ ØªÙØ²ÙÙ0 ÙÙÙØ± ÙÙ Ù
+Ø¯Ø®Ù  Ù
+ÙØ§ÙØ§Ù ÙÙÙØµ Ø§ÙØ°Ù ÙØ¹Ø·Ù ØªÙØ§ØµÙÙ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ Ø§ÙØ­Ø§ÙÙ Ù
+Ø¹ Ø¹Ù
+ÙØ¯ ÙØ§ØžÙØ§Ø± ØªØ·ÙØ± Ø§ÙØ§Ø¬Ø±Ø§Ø¡0 ÙÙØ¬Ø¯ ÙÙ Ø§ÙØ¬Ø§ÙØš Ø§ÙØ§ÙØ³Ø± Ø«ÙØ§Ø« Ø§Ø²Ø±Ø§Ø± ÙÙÙ Ù
+Ø¯Ø®Ù "ØªØ¹ÙÙÙ" ÙØªØ¹ÙÙÙ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ Ø§ÙØ¬Ø§Ø±Ù0 "Ø¹Ø±Ø¶ Ø§ÙÙ
+Ø¯ÙÙÙ" ÙÙØªØ­ ÙØ§ÙØ°Ø© Ø§ÙÙ
+Ø¯ÙÙØ©0 "ØºÙÙ" ÙØ§ÙÙØ§Ø¡ Ø§Ø¬Ø±Ø§Ø¡ Ø§ÙØªÙØ²ÙÙ ÙØ­Ø°Ù Ø§ÙÙ
+ÙÙ
+Ø© Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©0  </Text>
+</Section>
+</Section>
+<Section name="collectingfiles">
+<Title>
+<Text id="44">ØªØ¬Ù
+ÙÙØ¹ Ø§ÙÙ
+ÙÙØ§Øª ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø©</Text>
+</Title>
+<Text id="45">Ø¹ÙØ¯ Ø§ÙØŽØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø© Ø¬Ø¯ÙØ¯Ø© Ø³ÙÙ ØªØ­ØªØ§Ø¬ ÙØ¬ÙØš Ù
+ÙÙØ§Øª Ù
+Ø­Ø¯Ø¯Ø© Ø§ÙÙÙØ§Ø ÙÙÙ
+ÙÙ Ø§Ù ÙÙÙÙ ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ Ù
+Ù Ù
+Ø³Ø§Ø­Ø© Ø§ÙÙ
+ÙÙØ§Øª0 Ø§Ù Ù
+Ù Ù
+Ø¬Ù
+ÙØ¹Ø§Øª ÙØ±ØšÙØ³ØªÙÙ Ø§ÙØ£Ø®Ø±ÙØ ÙØ±ØšÙ
+Ø§ ÙØ­ØªÙÙ ØšØ¹Ø¶ÙØ§ Ø¹ÙÙ Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§ØªØ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ÙØµÙ ÙÙÙÙØ© Ø§Ø³ØªÙØ±Ø§Ø¯ Ø§ÙÙ
+ÙÙØ§Øª0</Text>
+<Section name="thegatherview">
+<Title>
+<Text id="46">Ù
+ØŽÙØ¯ Ø§ÙØªØ¬Ù
+ÙÙØ¹</Text>
+</Title>
+<Text id="47">ÙØ¹Ø±Ù ÙØ°Ø§ Ø§ÙÙØ³Ù
+ Ù
+ÙØ·ÙØ© ØªØ¬Ù
+ÙØ¹ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+Ø·ÙÙØšÙ ÙØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 ÙØšØ¯Ø£ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ØšÙØ§ØŠÙ
+Ø© Ø§ÙØªØ¬Ù
+ÙØ¹ ÙÙØ±Ø¬ÙØ¹ ÙÙØ°Ù Ø§ÙÙØ§ØŠÙ
+Ø© ÙÙÙ
+Ø§ ØšØ¹Ø¯ Ø Ø§ÙÙØ± "<AutoText key="glidict::GUI.Gather"/>" Ù
+ØšØ§ØŽØ±Ø© Ø§Ø³ÙÙ Ø¹Ù
+ÙØ¯ Ø§ÙÙÙØ§ØŠÙ
+0 </Text>
+<Text id="49">-ÙØªÙ
+ Ø§Ø®ØªÙØ§Ø± Ø¹ÙØµØ± Ù
+Ù Ø§ÙØŽØ¬Ø±Ø© ØšØ§ÙÙÙØ± Ø¹ÙÙÙ (ØªÙØ¬Ø¯ Ø·Ø±Ù Ø£Ø®Ø±ÙØ Ø§ÙØžØ± Ø§Ø¯ÙØ§Ù) Ø§ÙÙØ± Ø§ÙÙ
+Ø¬ÙØ¯ ÙÙØ±Ø© Ù
+Ø²Ø¯ÙØ¬Ù Ø£Ù ÙÙØ±Ø© ÙØ§Ø­Ø¯Ø© ÙÙØªØ­ Ø§ÙØ±Ù
+Ø² ØšØ¬Ø§ÙØš Ø§ÙÙ
+Ø¬ÙØ¯ ÙÙØªÙ
+Ø¯ÙØ¯ (Ø£Ù Ø§ÙØªÙÙÙØµ)0 Ø§ÙÙØ± Ø§ÙÙ
+ÙÙ ÙÙØ±Ø© Ù
+Ø²Ø¯ÙØ¬Ø© ÙÙØªØ­ Ø§ÙÙ
+ÙÙ<AutoText key="glidict::Menu.Open_Externally"/> ØšÙØ§Ø³Ø·Ø© ØšÙØ§Ø³Ø·Ø© Ø§ÙØšØ±ÙØ§Ù
+Ø¬ Ø§ÙÙ
+ÙØ§Ø³Øš 0(see <Reference target="fileassociations"/>).</Text>
+<Text id="50"> ØªÙØ¶Ø­ ØŽØ¬Ø±Ø© Ø§ÙÙ
+ÙÙØ§Øª ÙÙ Ù
+Ø³Ø§Ø­Ø© Ø§ÙØ¹Ù
+Ù Ù
+ØµØ§Ø¯Ø± Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+ØªÙÙØ±Ø© ÙÙ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ- ÙØžØ§Ù
+ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+Ø­ÙÙ (Ø§ÙÙØ±Øµ Ø§ÙÙ
+Ø­ÙÙ ÙØ§ÙØ§ÙØ±Ø§Øµ Ø§ÙÙ
+Ø¯Ù
+Ø¬Ø©)0  Ù
+Ø­ØªÙÙØ§Øª Ù
+Ø¬Ù
+ÙØ¹Ø§Øª ÙØ±ÙÙØ³ØªÙÙ ÙØ°Ø§ÙØ±Ø© Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+ÙØ²ÙØ©.ÙÙ
+ÙÙÙ ÙØ³Ø® Ù Ø¹Ø±Ø¶ ÙØ°Ù Ø§ÙÙ
+ÙÙØ§Øª  ÙÙÙÙ ÙØ§ ÙÙ
+ÙÙÙ ØªØ­Ø±ÙÙ Ø£Ù Ø§ÙØºØ§Ø¡Ø§ Ø£Ù ØªØ¹Ø¯ÙÙ ÙØ°Ù Ø§ÙÙ
+ÙÙØ§ØªØ ØšØ§Ø³ØªØ«ÙØ§Ø¡ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+ÙØ²ÙØ©0 ÙØ§ÙØªÙ ÙÙ
+ÙÙ Ø¥ÙØºØ§Ø€ÙØ§0 ØªØ¬ÙÙ ÙÙ ÙØ°Ù Ø§ÙÙ
+Ø³Ø§Ø­Ø© ÙÙØ¹Ø«ÙØ± Ø¹ÙÙ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙØªÙ ØªÙØ¯ Ø¶Ù
+ÙØ§ ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø©</Text>
+<Text id="51">ØŽØ¬Ø±Ø© Ù
+ÙÙØ§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØªØ¹ØšØ± Ø¹Ù Ù
+Ø­ØªÙÙØ§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙÙ ØšØµÙØ±Ø© Ù
+ØšØ¯ØŠÙØ© ØªÙÙÙ ÙØ§Ø±ØºØ©0</Text>
+<Text id="52">ÙÙ
+ÙÙÙ ØªØ¹Ø¯ÙÙ Ø§Ø­Ø¬Ø§Ù
+ Ø§ÙÙ
+Ø³Ø§Ø­Ø§Øª ØšØªÙ
+Ø±ÙØ± Ù
+Ø€ØŽØ± Ø§ÙÙØ£Ø±Ø© ÙÙÙ Ø§ÙØ¹Ù
+ÙØ¯ Ø§ÙØ±Ù
+Ø§Ø¯Ù Ø§ÙØ°Ù ÙÙØµÙ ØŽØ¬Ø±Ø§Øª Ø§ÙÙ
+ÙÙØ§Øª (ØšØªØºÙØ± ØŽÙÙ Ù
+Ø€ØŽØ± Ø§ÙÙØ£Ø±Ø© ÙØ§Ø³ÙØ·0.</Text>
+<Text id="53">ÙÙØ¬Ø¯ Ø¹Ù
+ÙØ¯ Ø§ÙØ­Ø§ÙØ© Ø£Ø³ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø© ÙÙÙ ÙÙØ¶Ø­ 0 ØªØ·ÙØ± Ø§Ø¬Ø±Ø§Ø¡Ø§Øª Ø§ÙÙ
+ÙÙØ§Øª (ÙØ³Ø®Ø ØªØ­Ø±ÙÙØ Ø¥ÙØºØ§Ø¡) ÙÙØ°Ù Ø§ÙØ§Ø¬Ø±Ø§Ø¡Ø§Øª ÙØ¯ ØªØ³ØªØºØ±Ù Ø²Ù
+ÙØ§Ù ÙÙÙ ØªÙØªÙ
+Ù0</Text>
+<Text id="54">ÙÙØ¬Ø¯ Ø²Ø±ÙÙ ÙØšÙØ±ÙÙ ÙÙ Ø§ÙØ¬Ø§ÙØš Ø§ÙØ£ÙÙ
+Ù Ù
+Ù Ø§ÙØ¬Ø²Ø¡ Ø§ÙØ£Ø³ÙÙ  Ù
+Ù Ø§ÙØŽØ§ØŽØ©0 "Ù
+Ø¬ÙØ¯ Ø¬Ø¯ÙØ¯" ØšØµÙØ±Ø© Ù
+Ø¬ÙØ¯ ÙØ§ÙØŽØ§Ø¡ Ù
+ÙÙØ§Øª Ø¬Ø¯ÙØ¯Ø© (see  <Reference target="creatingfolders"/>). "Ø§ÙØºØ§Ø¡" ØšØµÙØ±Ø© Ø³ÙØ© ÙØžØ§ÙØ© ÙØ­Ø°Ù Ø§ÙÙ
+ÙÙØ§Øª0 ÙÙØ± Ø§ÙÙ
+ÙÙ Ø³ÙÙ ÙØ€Ø¯Ù  ÙØ­Ø°Ù Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±Ø© Ù
+Ù ØŽØ¬Ø±Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 ÙØ®ÙØ§Ø± Ø¢Ø®Ø± ÙÙ
+ÙÙ Ø­Ø°Ù Ø§ÙÙ
+ÙÙØ§Øª ØšØªØ­Ø±ÙÙÙØ§ Ø¥ÙÙ Ø²Ø± Ø§ÙØ§ÙØºØ§Ø¡0 </Text>
+<Text id="55">ÙØ§Ø®ØªÙØ§Ø± Ù
+Ø¬Ù
+ÙØ¹Ø©  Ø¹ÙØ§ØµØ± Ù
+ØªØ³ÙØ³ÙØ©Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø§ÙØ£ÙÙ Ù
+Ø¹ Ø­ÙØž ÙØ§Ù
+Ø³Ø§Ù Ù
+ÙØªØ§Ø­ [shift] ÙØ§ÙÙØ± Ø¹ÙÙ Ø¢Ø®Ø± Ø§Ø®ØªÙØ§Ø±Ø§ØªÙØ ÙØ³ÙÙ ÙØŽÙ
+Ù ÙØ°Ø§ Ø§ÙØ§Ø®ØªÙØ§Ø± Ù
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙØ¹ÙØ§ØµØ± Ø§ÙÙ
+Ø¶Ù
+ÙÙØ ÙØ§Ø®ØªØšØ§Ø± Ø§ÙØ¹ÙØ§ØµØ± ØºÙØ± Ø§ÙÙ
+ØªØ³ÙØ³ÙØ© Ø§Ø¶ØºØ· Ø¹ÙÙ Ù
+ÙØªØ§Ø­ [ctrl]  ØšÙÙÙ
+Ø§ ÙÙÙÙ
+ ØšØ§ÙÙÙØ±Ø Ø§Ø³ØªØ®Ø¯Ù
+ Ø§ÙØ§Ø³ÙÙØšÙÙ ÙØ§Ø®ØªÙØ§Ø± Ù
+Ø¬Ù
+ÙØ¹Ø© Ù
+ØªØ¬Ø§ÙØ±Ø© Ø£Ù Ù
+Ø¬Ù
+ÙØ¹Ø© ØºÙØ± Ù
+ØªØ¬Ø§ÙØ±Ø©0</Text>
+</Section>
+<Section name="creatingshortcuts">
+<Title>
+<Text id="55a"> Ø§ÙØŽØ§Ø¡ Ù
+Ø®ØªØµØ± Ù
+Ù ØŽØ¬Ø±Ø© Ù
+Ø³Ø§Ø­Ø© Ø§ÙØ¹Ù
+Ù0</Text>
+</Title>
+<Text id="56">Ù
+Ø¬ÙØ¯Ø§Øª Ù
+Ø­Ø¯Ø¯Ø©00 Ù
+Ø«Ù Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙØ°Ù ÙØ­ØªÙÙ ØµÙØ­Ø§Øª Ø§ÙÙØš Ø®Ø§ØµØªÙ0 ÙØ¯ÙÙØ§ ÙÙ ØšØ¹Ø¶ Ø§ÙØ§Ø­ÙØ§Ù Ø¯ÙØ§ÙØ§Øª Ø®Ø§ØµØ©Ø ÙÙ
+ÙÙ ÙÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ Ù
+ÙØ¶Ø¹Ù ÙØ°Ù Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª ÙÙ Ø§ÙÙ
+Ø³ØªÙÙ Ø§ÙØ£ÙÙ Ù
+Ù ØŽØ¬Ø±Ø© Ø§ÙÙ
+ÙÙØ§Øª. ÙÙÙÙØ§Ù
+ ØšÙØ°Ø§ Ø§ÙØ¹Ù
+ÙØ Ø§ÙÙØ± Ø§ÙØ²Ø± Ø§ÙØ§ÙÙ
+Ù ÙÙÙ Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙÙ
+Ø·ÙÙØšØ ÙØžÙØ± "Ø§ÙØŽØ§Ø¡ Ù
+Ø®ØªØµØ±" Ø§Ø¯Ø®Ù Ø§Ø³Ù
+Ø§Ù ÙÙÙ
+Ø¬ÙØ¯0 ÙØ­Ø°Ù Ø¹ÙØµØ± Ø§ÙÙØ± Ø§ÙØ²Ø± Ø§ÙØ§ÙÙ
+Ù ÙÙÙ Ø§ÙÙ
+Ø¬ÙØ¯ ÙÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± "Ø­Ø°Ù Ù
+Ø®ØªØµØ±"0
+</Text>
+</Section>
+<Section name="creatingfolders">
+<Title>
+<Text id="57">Ø¥ÙØŽØ§Ø¡ Ù
+Ø¬ÙØ¯Ø§Øª</Text>
+</Title>
+<Text id="58">Ø§Ø³ØªØ®Ø¯Ù
+ Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª ÙÙ ØŽØ¬Ø±Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙØªØ¬Ù
+ÙØ¹ Ø§ÙÙ
+ÙÙØ§Øª Ù
+Ø¹Ø§Ù ÙØªØ³ÙÙÙ Ø§ÙÙØµÙÙ Ø¥ÙÙÙØ§Ø ÙÙ
+ÙÙ Ù
+ÙØ¶Ø¹Ø©  Ù
+Ø¬ÙØ¯Ø§Øª Ø¯Ø§Ø®Ù Ù
+Ø¬ÙØ¯Ø§Øª ÙØ§ÙØªØ±Ø§Ø¶ÙØ§Ù ÙØ§ ÙÙØ¬Ø¯ Ø­Ø¯ ÙØ¹Ø¯Ø¯ Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª Ø£Ù Ø¹Ù
+Ù ØªÙØ±ÙØº Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª0</Text>
+<Text id="59">ÙØ§ÙØŽØ§Ø¡ Ù
+Ø¬ÙØ¯ Ø¬Ø¯ÙØ¯Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ù
+Ø¬ÙØ¯ ÙÙ ØŽØ¬Ø±Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙØ§ÙÙØ± Ø¹ÙÙ Ø²Ø± "Ù
+Ø¬ÙØ¯ Ø¬Ø¯ÙØ¯"Ø ÙØžÙØ± Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙØ¬Ø¯ÙØ¯ Ø¶Ù
+Ù Ù
+Ø¬ÙØ¯ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙ
+Ø®ØªØ§Ø±Ø© Ø£Ù ÙÙ Ø§ÙÙ
+Ø³ØªÙÙ Ø§ÙØ£Ø¹ÙÙ Ø§Ø°Ø§ ÙÙ
+ ÙØªÙ
+ Ø§Ø®ØªÙØ§Ø± ÙØ§Ø­Ø¯Ø Ø³ÙÙ ÙØªÙ
+ Ø­Ø«Ù ØªØ³Ù
+ÙØ© Ø§ÙÙ
+Ø¬ÙØ¯ (Ø§ÙØ£Ø³Ù
+ Ø§ÙØ§ÙØªØ±Ø§Ø¶Ù ÙÙ "Ù
+Ø¬ÙØ¯ Ø¬Ø¯ÙØ¯"0
+</Text>
+<Text id="60">ÙÙ
+ÙÙ Ø§ÙØŽØ§Ø¡ Ù
+Ø¬ÙØ¯ Ø¬Ø¯ÙØ¯ ÙÙÙØ± Ø§ÙØ²Ø± Ø§ÙØ§ÙÙ
+Ù ÙÙÙØ£Ø±Ø© ÙØ§Ø®ØªÙØ§Ø± "Ù
+Ø¬ÙØ¯ Ø¬Ø¯ÙØ¯" ÙØ§ØªØšØ§Ø¹ Ø§ÙØ§Ø¬Ø±Ø§Ø¡Ø§Øª Ø§Ø¹ÙØ§Ù0</Text>
+</Section>
+<Section name="addingfiles">
+<Title>
+<Text id="61">Ø¥Ø¶Ø§ÙØ© Ù
+ÙÙØ§Øª</Text>
+</Title>
+<Text id="62">ÙÙ
+ÙÙ ÙØ³Ø® Ø§ÙÙ
+ÙÙØ§Øª Ø¥ÙÙ Ø§Ù Ù
+Ø¬Ù
+ÙØ¹Ø© ØšØ§ÙØ³Ø­Øš ÙØ§ÙØ§Ø³ÙØ§Ø·Ø ÙØµØšØ­ ØŽÙÙ Ø§ÙÙ
+Ø€ØŽØ± ØšØµÙØ±Ø© ØŽØšØ­ÙØ© ÙÙÙ
+ÙÙ Ø§ÙÙ
+Ø®ØªØ§Ø± (Ø£ÙØ Ù
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±Ø©)0 Ø§Ø³ÙØ· ÙØ°Ø§ Ø§ÙØ§Ø®ØªÙØ§Ø± ÙÙ ØŽØ¬Ø±Ø© Ù
+ÙÙØ§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙØ³Ø®ÙØ§ Ø¥ÙÙ ÙÙØ§ÙØ (Ø§Ø°Ø§ ÙØ§Ù Ø§ÙÙ
+ØµØ¯Ø± ÙÙ ØŽØ¬Ø±Ø© Ù
+Ø³Ø§Ø­Ø© Ø§ÙØ¹Ù
+Ù) Ø£Ù ØªØ­Ø±ÙÙÙØ§ Ø¬Ø§ÙØšÙØ§Ù (Ø§Ø°Ø§ ÙØ§Ù ÙØ°Ø§ Ø§ÙØ£Ù
+Ø± Ø¶Ù
+Ù ÙØ·Ø§Ù ØŽØ¬Ø±Ø© Ù
+ÙÙØ§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©)0</Text>
+<Text id="63">Ø¹ÙØ¯ ÙØ³Ø® Ù
+Ø¬Ù
+ÙØ¹Ø© Ù
+ÙÙØ§ØªØ ØªÙØ¶Ø­ ÙÙÙØ§ ÙÙ Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙÙ
+Ø³ØªÙØ¯Ù ÙÙ ÙÙØ³ Ø§ÙÙ
+Ø³ØªÙÙ ØšØ¯ÙÙ Ø§Ø¹ØªØšØ§Ø± ÙÙØ¶Ø¹ÙØ§ Ø§ÙØ§ØµÙÙ ÙÙ Ø§ÙÙ
+ØµØ¯Ø±0 Ø¹ÙØ¯ ÙØ³Ø® Ù
+ÙÙ ØšÙÙØ³ Ø§ÙØ§Ø³Ù
+ ÙÙ
+ÙÙ ØšØ§ÙÙ
+Ø¬ÙØ¯ Ø§ÙÙ
+Ø³ØªÙØ¯ÙØ Ø³ÙÙ ÙØªÙ
+ Ø§Ø³ØªÙØ³Ø§Ø±Ù  Ø§Ø°Ø§ ÙÙØª ØªÙØ¯ ÙØ³Ø® ÙØ°Ø§ Ø§ÙÙ
+ÙÙ ÙÙÙ ÙÙØ³ Ø§ÙÙ
+ÙÙ Ø§ÙÙ
+ÙØ¬ÙØ¯0 Ø§ÙØ¥Ø¬Ø§ØšØ© ØšÙØ§ ØªØ¹ÙÙ Ø£Ù Ø§ÙÙ
+ÙÙ ÙØ§ ÙÙØ³Ø®Ø ÙÙÙ ÙØªÙ
+ ÙØ³Ø® ØšÙÙØ© Ø§ÙÙ
+ÙÙØ§Øª0 ÙØ§ÙØºØ§Ø¡ ØšÙÙØ© Ø§ÙØ§Ø¬Ø±Ø§Ø¡Ø Ø§ÙÙØ± Ø²Ø± "ØªÙÙÙ"0
+</Text>
+<Text id="64">Ø§ÙØ¹ÙØ§ØµØ± "Ø§ÙØ¹ÙÙØ§ " ÙÙØ· ÙÙ Ø§ÙØ¹ÙØ§ØµØ± Ø§ÙÙ
+Ø®ØªØ§Ø±Ø© ÙÙ Ø§ÙØªÙ ØªÙ
+ ØªØ­ÙÙÙÙØ§ Ø ÙØ¹ØªØšØ± Ø§ÙÙ
+Ø¬ÙØ¯ Ø§Ø¹ÙÙ Ù
+Ù ØªØ¹Ø±ÙÙØ§ØªÙØ ÙØ§ ÙÙ
+ÙÙ Ø§Ø®ØªÙØ§Ø± Ø§ÙÙ
+ÙÙØ§Øª Ø¶Ù
+Ù Ø§ÙÙ
+Ø¬ÙØ¯ Ø£Ù Ø§ÙÙ
+Ø¬ÙØ¯ Ø°Ø§ØªÙ0</Text>
+<Text id="65">ÙÙÙÙ
+ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ Ø¹ÙØ¯ Ø§Ø¶Ø§ÙØ© Ù
+ÙÙ ÙØšØ­Ø« Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª Ø¹Ù Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙØ§Ø¶Ø§ÙÙØ© Ø§ÙØªÙ ØªØªØ¶Ù
+Ù ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+Ø¹ÙÙØ© Ù
+Ù ÙØšÙ ÙÙ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙØ§Ø¶Ø§ÙÙØ©0 ÙØ§Ø°Ø§ ÙØ¬Ø¯ÙØ§ ÙÙÙÙ
+ ØšØ¹Ù
+ÙÙØ© Ø§Ø³ØªÙØ±Ø§Ø¯ ÙÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙØ°Ù Ø®ÙØ§Ù ÙØªØ±Ø© Ø³Ø±ÙØ§Ù Ø§ÙØ¹Ù
+ÙÙØ©Ø Ø³ÙÙ ÙØªÙ
+ Ø­Ø«Ù (Ø±ØšÙ
+Ø§ Ù
+Ø±Ø§Øª Ø¹Ø¯ÙØ¯Ø©) ÙÙ
+Ø²ÙØ¯ Ù
+Ù Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª ÙÙ
+ÙØ§Ø±ØšÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø³ØªÙØ±Ø¯Ø© ÙÙ
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+ØªÙÙØ±Ø© ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©Ø ÙÙØªØ¶Ù
+Ù ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø§Øª Ø­Ø« Ù
+Ø®ØªÙÙØ© Ù
+ÙØµÙÙØ© ÙÙ ÙØ³Ù
+ <Reference target="importingpreviouslyassignedmetadata"/>ÙÙ
+Ø²ÙØ¯ Ù
+Ù Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª Ø­ÙÙ ØªÙØ¶ÙØ­ Ø§Ø¬Ø±Ø§Ø¡Ø§Øª ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+ÙØ­ÙØ©Ø Ø§ÙØ±Ø£ Ø§ÙÙØµÙ Ø§ÙØ«Ø§ÙÙ Ù
+Ù Ø¯ÙÙÙ ÙØ±ÙÙØ³ØªÙÙ ÙÙÙ
+Ø·ÙØ±ÙÙ ØªØ­Øª Ø¹ÙÙØ§Ù Ø§ÙØ¬Ø§Ø¯ Ù
+Ø­ØªÙÙØ§Øª Ø§ÙÙØ«ÙÙØ©0</Text>
+<Text id="65a"> ÙÙ
+ÙÙÙ Ø§Ø¶Ø§ÙØ© ÙØ«ÙÙØ© "Ù
+Ø²ÙÙØ©" Ø¥ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙÙØ± Ø§ÙØ²Ø± Ø§ÙØ§ÙÙ
+Ù ÙÙ ØŽØ¬Ø±Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø£Ù ÙÙ Ù
+Ø¬ÙØ¯Ø ÙØ§Ø®ØªÙØ§Ø± "ÙØ«ÙÙØ© Ù
+Ø²ÙÙØ© Ø¬Ø¯ÙØ¯Ø©" ÙØ³ÙÙ ÙÙØŽØŠ ÙØ°Ø§ Ù
+ÙÙ Ø¬Ø¯ÙØ¯ ÙØ§Ø±Øº ÙÙ
+ÙÙ ÙÙÙ Ø§Ø¹ØªÙ
+Ø§Ø¯ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§ØªØ ÙÙ
+ÙÙ Ø§Ø³ØªØšØ¯Ø§Ù ÙØ°Ø§ Ø§ÙÙ
+ÙÙ ØšÙ
+ÙÙ "Ø­ÙÙÙÙ" ÙÙÙ
+Ø§ ØšØ¹Ø¯0</Text>
+</Section>
+<Section name="replacingfiles">
+<Title>
+<Text id="65b">Ø§Ø¹Ø§Ø¯Ø© ØªØ³Ù
+ÙØ© ÙØ§Ø³ØªØšØ¯Ø§Ù Ø§ÙÙ
+ÙÙØ§Øª0</Text>
+</Title>
+<Text id="65c"> ÙÙ
+ÙÙ Ø§Ø¹Ø§Ø¯Ø© ØªØ³Ù
+ÙØ© Ø§ÙÙ
+ÙÙØ§Øª ØšØ§ÙÙÙØ± Ø¹ÙÙ Ø§ÙØ²Ø± Ø§ÙØ£ÙÙ
+Ù Ø¹ÙÙÙØ§ ÙØ§Ø®ØªÙØ§Ø± "Ø§Ø¹Ø§Ø¯Ø© ØªØ³Ù
+ÙØ©" Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©Ø Ø¯Ø®Ù Ø§ÙØ§Ø³Ù
+ Ø§ÙØ¬Ø¯ÙØ¯ ÙØ§ÙÙØ± "OK"</Text>
+<Text id="65d"> ÙÙ
+ÙÙ Ø§Ø³ØªØšØ¯Ø§Ù Ø§ÙÙ
+ÙÙØ§Øª ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØšÙÙØ± Ø§ÙØ²Ø± Ø§ÙØ§ÙÙ
+Ù ÙÙÙ Ø§ÙÙ
+ÙÙ Ø§ÙÙ
+Ø±Ø§Ø¯ Ø§Ø³ØªØšØ¯Ø§ÙÙ ÙØ§Ø®ØªÙØ§Ø± "Ø§Ø³ØªØšØ¯Ø§Ù" ÙØªÙ
+ ÙØªØ­ Ù
+ØªØµÙØ­ Ø§ÙÙ
+ÙÙØ§ØªØ ØªØ¬ÙÙ Ø¥ÙÙ Ø§ÙÙØ«ÙÙØ© Ø§ÙØ¬Ø¯ÙØ¯Ø© ÙØ§ÙÙØ± "ÙØªØ­" ÙÙØ§ ÙØªÙ
+ Ø§Ø³ØªØšØ¯Ø§Ù Ø§ÙÙØ«ÙÙØ© Ø§ÙÙØ¯ÙÙ
+Ø© ØšØ§ÙØ¬Ø¯ÙØ¯Ø©  ÙØ³ÙÙ ÙØªÙ
+ ØªØ­ÙÙÙ Ø§Ù ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø¥ÙÙÙØ§ ÙÙÙÙÙ ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ Ù
+ÙÙØ¯Ø§Ù ÙÙ Ø­Ø§ÙØ© Ø§Ø³ØªØšØ¯Ø§Ù Ø§ÙÙØ«Ø§ØŠÙ Ø§ÙÙ
+Ø²ÙÙØ© ØšÙØ«Ø§ØŠÙ Ø­ÙÙÙÙØ©0</Text>
+</Section>
+<Section name="removingfiles">
+<Title>
+<Text id="66">Ø­Ø°Ù Ù
+ÙÙØ§Øª</Text>
+</Title>
+<Text id="67">ØªÙØ¬Ø¯ Ø§Ø³Ø§ÙÙØš Ø¹Ø¯ÙØ¯Ø© ÙØ­Ø°Ù Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª ÙØ§ÙÙ
+ÙÙØ§Øª0 ÙØ¬Øš Ø¹ÙÙÙ Ø§ÙÙØ§Ù ØªØ­Ø¯ÙØ¯ Ø§ÙØ¹ÙØ§ØµØ± Ø§ÙÙ
+Ø·ÙØš Ø­Ø°ÙÙ ØšØ§Ø®ØªÙØ§Ø± Ù
+Ø¬ÙØ¯ Ø£Ù Ù
+ÙÙ Ø§ÙØ£ÙØ«Ø± ÙÙ
+Ø§ ÙÙ Ù
+ÙØµÙÙ ÙÙ <Reference target="thegatherview"/>.</Text>
+<Text id="68">Ø¹ÙØ¯ Ø§Ø®ØªÙØ§Ø± Ø§ÙÙ
+ÙÙØ Ø§ÙÙØ± Ø²Ø± "Ø§ÙØºØ§Ø¡" ÙØ­Ø°ÙÙ Ø£Ù ØšØ§ÙØ¶ØºØ· Ø¹ÙÙ "Ø§ÙØºØ§Ø¡" ÙÙ ÙÙØ­Ø© Ø§ÙÙ
+ÙØ§ØªÙØ­ - Ø£Ù Ø³Ø­Øš Ø§ÙÙ
+ÙÙØ§Øª Ù
+Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø¥ÙÙ Ø²Ø± Ø§ÙØ§ÙØºØ§Ø¡ ÙØ§Ø³ÙØ§Ø·ÙØ§ ÙÙØ§Ù0</Text>
+</Section>
+<Section name="explodingfiles">
+<Title>
+<Text id="exm-1"> ØªØ¬Ø²ØŠØ©  Ù
+ÙÙØ§Øª ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª0</Text>
+</Title>
+<Text id="exm-2"> ÙÙ
+ÙÙ Ø§Ø³ØªÙØ±Ø§Ø¯ Ø£ÙÙØ§Ø¹ Ù
+ÙÙØ§Øª ÙÙØ§Ø¹Ø¯ ØšÙØ§ÙØ§Øª ÙÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+Ø«Ù MARC ÙCDS/ISIS	 Ù ProciteØ ÙÙ ØªØªÙ
+ÙÙ Ù
+Ù ØªØ­Ø¯ÙØ« ÙØ¹Ø±Ø¶ ÙØ§ØµÙØ§Øª  Ø§ÙØšÙØ§ÙØ§Øª ÙÙ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙØ ÙÙÙÙØ§Ù
+  ØšÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ ÙÙ
+ÙÙÙ Ø§ÙØ±Ø¬ÙØ¹ ÙÙØšØ±ÙØ§Ù
+Ø¬ Ø§ÙØ°Ù Ø£ÙØŽØ£ Ø§ÙÙ
+ÙÙ0
+</Text>
+<Text id="exm-3">"ØªØ¬Ø²ØŠØ©" Ù
+ÙÙ ÙØ§Ø¹Ø¯Ø© ØšÙØ§ÙØ§Øª ÙÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§ØªØ ÙÙØªØ¬ ØªØ³Ø¬ÙÙØ§Øª ÙØ±Ø¯ÙØ© ØšÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª ÙØ§ØšÙØ© ÙÙØ¹Ø±Ø¶ ÙØ§ÙØªØ­Ø¯ÙØ«0 ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ ØºÙØ± Ù
+Ø±Ø¯ÙØ¯ ÙØ³ÙÙ ÙØªÙ
+ Ù
+Ø³Ø­ Ù
+ÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØ£ØµÙÙ0</Text>
+<Text id="exm-4"> Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+Ø¬Ø²Ø£Ø© ÙÙØ§ Ø§ÙÙÙÙØ© Ø®Ø¶Ø±Ø§Ø¡ ÙÙ ØŽØ¬Ø±Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 ÙØªØ¬Ø²ØŠØ© Ù
+ÙÙ Ø§ÙÙØ± Ø§ÙØ²Ø± Ø§ÙØ§ÙÙ
+Ù ÙÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± "ØªØ¬Ø²ØŠØ© ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª ÙØ§Ø¹Ø¯Ø© ØšÙØ§ÙØ§Øª" ØªØžÙØ±  ÙØ§ÙØ°Ø© ØªØ¹Ø±Ø¶ Ø®ÙØ§Ø±Ø§Øª Ø§Ø¬Ø±Ø§Ø¡ Ø§ÙØªØ¬Ø²ØŠØ©0 Ø§ÙØ®ÙØ§Ø± Ø§ÙØ£ÙÙ ("Ø§ÙÙ
+ÙØ§ØšØ³") ÙØ­Ø¯Ø¯ Ø§ÙÙ
+ÙØ§ØšØ³ ÙÙØªØ¬Ø²ØŠØ© ÙÙ Ù
+Ø¹ØžÙ
+  Ø§ÙØ­Ø§ÙØ§ØªØ ÙØ³ØªØ®Ø¯Ù
+ Ù
+ÙØ§ØšØ³ ÙØ§Ø­Ø¯ ÙÙ
+Ø¹Ø§ÙØ¬Ø©  ÙÙØ¹ Ù
+Ø¹ÙÙ Ù
+Ù Ø§ÙÙ
+ÙÙØ§ØªØ ÙÙÙ ÙÙ ØšØ¹Ø¶ Ø§ÙØ§Ø­ÙØ§ÙØ Ø­ÙØ« ØªÙØ¬Ø¯ Ù
+ÙÙØ§Øª Ù
+Ø®ØªÙÙØ© ÙÙÙØ§ Ø§Ù
+ØªØ¯Ø§Ø¯ Ù
+ØŽØªØ±Ù  ÙÙØ§ ÙÙ
+ÙÙ ÙÙ
+ÙØ§ØšØ³ÙÙ Ù
+Ø¹Ø§ÙØ¬Ø© Ø§ÙÙ
+ÙÙØ§Øª ØšÙÙØ³ Ø§ÙØ§Ù
+ØªØ¯Ø§Ø¯0ÙÙ
+ÙÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+ Ø®ÙØ§Ø± "input-encoding" ÙØªØ­Ø¯ÙØ¯ ØªØ±Ù
+ÙØ² ÙØ§Ø¹Ø¯Ø© Ø§ÙØšÙØ§ÙØ§Øª0 Ø®ÙØ§Ø± "Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª" "metadata-set"" ÙØ­Ø¯Ø¯ Ø£Ù Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª ÙÙ
+ÙÙ Ø§Ø¶Ø§ÙØ©  Ø§ÙØ­ÙÙ Ø§ÙØ¬Ø¯ÙØ¯ Ø¥ÙÙÙ0 Ø¥Ø°Ø§ ÙÙ
+ ÙØªÙ
+ ØªØ­Ø¯ÙØ¯ ÙØ§Ø­Ø¯Ø Ø³ÙÙ ÙØªÙ
+ Ø­Ø«Ù ÙÙ
+Ø¹Ø±ÙØ© Ù
+Ø§ ÙÙ
+ÙÙ ÙØ¹ÙÙ Ù
+Ø¹ Ø£Ù Ø­ÙÙ Ø¬Ø¯ÙØ¯ ÙÙ ÙØ§Ø¹Ø¯Ø© Ø§ÙØšÙØ§ÙØ§Øª0  ÙÙ
+ÙÙ Ø§Ø¶Ø§ÙØªÙ ÙØ¹ÙØµØ± Ø¬Ø¯ÙØ¯ ÙÙ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+ÙØ¬ÙØ¯Ø Ø¯Ù
+Ø¬Ù Ù
+Ø¹ Ø¹ÙØµØ± Ø¢Ø®Ø± Ø£Ù ØªØ¬Ø§ÙÙÙ0
+</Text>
+<Text id="exm-5">  ÙØªÙ
+ Ø§ÙØŽØ§Ø¡ ÙØ«ÙÙØ© ÙØ§Ø±ØºØ©  Ø¬Ø¯ÙØ¯Ø© ÙÙÙ ØªØ³Ø¬ÙÙØ© Ø¹ÙØ¯ ØªØ¬Ø²ØŠØ©  Ø§ÙÙ
+ÙÙ ÙÙØªÙ
+ Ø§Ø¹ØªÙ
+Ø§Ø¯ ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø§ÙØªØ³Ø¬ÙÙØ© ÙÙÙ ÙØ«ÙÙØ©Ø ØªØªÙ
+ ØªØ³Ù
+ÙØ© Ø§ÙÙØ«Ø§ØŠÙ ØšØ§Ø³ØªØ®Ø¯Ø§Ù
+ Ø§ÙØ§Ø±ÙØ§Ù
+ Ù
+Ø«Ù 00002,nul Ù000001-nul ÙÙÙØ°Ø§Ø Ø§Ø°Ø§ ØªÙ
+ ØªØ­Ø¯ÙØ¯ Ø§ÙØ®ÙØ§Ø± "Document-field" (Ø¥ÙÙ Ø§Ø³Ù
+ Ø­ÙÙ ÙØ§Ø¹Ø¯Ø© Ø§ÙØšÙØ§ÙØ§Øª) ØªØ³ØªØ®Ø¯Ù
+ ÙÙÙ
+Ø© ÙØ°Ø§ Ø§ÙØ­ÙÙØ Ø§Ø°Ø§ ØªÙÙØ±Øª ÙØ§Ø³Ù
+ Ø§ÙÙ
+ÙÙ. ÙÙÙÙ
+ Ø§Ø¬Ø±Ø§Ø¡ Ø§ÙØªØ¬Ø²ØŠØ© ØšÙ
+Ø­Ø§ÙÙØ© ØªÙØ²ÙÙ Ø§ÙÙ
+ÙÙ ÙØ§Ø³ØªØ®Ø¯Ø§Ù
+Ù ØšØ¯ÙØ§ Ù
+Ù Ù
+ÙÙ ÙØ§Ø±Øº0 ÙÙ
+ÙÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+  Ø®ÙØ§Ø±Ø§Øª0"Document- prefix"Ù "Document- sufix" ÙØ§ÙØŽØ§Ø¡ Ø¹ÙÙØ§Ù Ù
+ÙØ§Ø±Ø¯  Ù
+ÙØ­Ø¯ URL ØµØ§ÙØ­ Ø£Ù Ù
+Ø³Ø§Ø± Ù
+ÙÙ Ù
+Ù ÙÙÙ
+Ø© "Document-field" ÙÙ
+ÙÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+ Ø®ÙØ§Ø± "Records-per-folder" ÙØªØ¬Ù
+ÙØ¹ Ø§ÙØªØ³Ø¬ÙÙØ§Øª Ø§ÙÙ
+Ø¬Ø²ØŠØ© ÙÙ Ù
+Ø¬ÙØ¯Ø§Øª ÙØ±Ø¹ÙØ©Ø Ø§Ø°Ø§ ÙØ§ÙØª ÙØ§Ø¹Ø¯Ø© Ø§ÙØšÙØ§ÙØ§Øª ÙØšÙØ±Ø© Ø¬Ø¯Ø§ÙØ ÙÙ
+ÙÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+ ÙØ°Ø§ Ø§ÙØ®ÙØ§Ø± ÙØªØ³Ø±ÙØ¹ Ø§ÙØªØ¹Ø¯ÙÙ Ø§ÙÙ
+ØªØ³ÙØ³Ù  ÙÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª0
+</Text>
+<Text id="exm-6"> ÙØªØ­Ø¯Ø¯ Ø¥Ø¬Ø±Ø§Ø¡ Ø§ÙØªØ¬Ø²ØŠØ© ØšØ§Ù
+ØªØ¯Ø§Ø¯  Ø§ÙÙ
+ÙÙ0 ÙÙ ØšØ¹Ø¶ Ø§ÙØ­Ø§ÙØ§ØªØ ØªÙØ¬Ø¯ Ù
+ÙÙØ§Øª ØªÙ
+ÙØ² ÙÙØªØ¬Ø²ØŠØ© ØšØµÙØ±Ø© ØºÙØ± ØµØ­ÙØ­Ø©Ø Ø¥Ø°Ø§ ÙØ§Ù ÙØ¯ÙÙØ§ ÙÙØ³ Ø§Ø³Ù
+ Ø§Ù
+ØªØ¯Ø§Ø¯  Ø§ÙÙ
+ÙÙ0 Ù
+Ø«Ø§Ù Ù
+ÙØ§ÙØ³Procite  ÙØ¹Ø§ÙØ¬  Ø§ÙÙ
+ÙÙØ§Øª ØšØ§ÙØ§Ù
+ØªØ¯Ø§Ø¯  TXT. ÙÙÙÙ Ù
+Ø¹ØžÙ
+ Ø§ÙÙ
+ÙÙØ§Øª ØšØ§ÙØ§Ù
+ØªØ¯Ø§Ø¯ TXT .ÙÙ Ù
+ÙÙØ§Øª ØšØ³ÙØ·Ø© ÙÙÙØ³Øª Ù
+ÙÙØ§Øª Procite</Text>
+</Section>
+<Section name="filteringthetree">
+<Title>
+<Text id="69">ØªØ±ØŽÙØ­ Ø§ÙØŽØ¬Ø±Ø©</Text>
+</Title>
+<Text id="70">"ØªØ±ØŽÙØ­"  ØŽØ¬Ø±Ø© Ù
+Ø³Ø§Ø­Ø© Ø§ÙØ¹Ù
+Ù ÙØ§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙØªÙØ­ ÙÙ ØªØ¶ÙÙ ÙØ·Ø§Ù Ø§ÙØšØ­Ø« Ø¹Ù Ù
+ÙÙØ§Øª Ù
+Ø­Ø¯Ø¯Ø©0</Text>
+<Text id="71">ÙØ§ØŠÙ
+Ø© "Ø§ØžÙØ§Ø± Ù
+ÙÙØ§Øª" Ø§ÙÙ
+ÙØ³Ø¯ÙØ© ØªØ­Øª ÙÙ ØŽØ¬Ø±Ø© Ù
+ÙÙØ§Øª ØªØªÙØ­ ÙØ§ØŠÙ
+Ø© Ù
+Ø±ØŽØ­Ø§Øª Ù
+Ø¹Ø±ÙØ© Ù
+Ù ÙØšÙØ Ù
+Ø«Ù "ØµÙØ±" . Ø§Ø®ØªÙØ§Ø± Ù
+Ø±ØŽØ­ ØšØµÙØ±Ø© Ù
+Ø€ÙØªØ© ÙØ¹ÙÙ Ø§Ø®ØªÙØ§Ø¡ ØšÙÙØ© Ø£ÙÙØ¹ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+Ø®ØªÙÙØ©  ÙÙ ØŽØ¬Ø±Ø© Ø§ÙÙ
+ÙÙØ§Øª0 ÙØ§Ø³ØªØ¹Ø§Ø¯Ø© ØŽØ¬Ø±Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØªÙ
+ÙÙØ² Ø§ÙÙ
+Ø±ØŽØ­ Ø¥ÙÙ "ÙÙ Ø§ÙÙ
+ÙÙØ§Øª"0 ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ ÙØ§ ÙØ€Ø«Ø± ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø£Ù Ù
+Ø¬ÙØ¯Ø§Øª ØŽØ¬Ø±Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0</Text>
+<Text id="72">ÙÙ
+ÙÙÙ ØªØ®ØµÙØµ Ù
+Ø±ØŽØ­ ØšØ·ØšØ§Ø¹Ø© Ø§ÙØ§Ù
+ØªØ¯Ø§Ø¯ Ø§ÙØ¹Ø§Ù
+ " *.*" Ø£Ù Ø§Ù
+ØªØ¯Ø§Ø¯ Ù
+Ø­Ø¯Ø¯ ".doc" ÙØ§ØžÙØ§Ø±  Ø§ÙÙ
+ÙÙØ§Øª ÙÙÙØ§ Ø£Ù Ø§ÙÙ
+Ø­Ø¯Ø¯Ø© (ÙØ°Ø§ Ø§ÙØ®ÙØ§Ø± Ù
+ØªÙÙØ± ÙÙØ· ÙÙ Ø³ÙØ§Ù Ø§Ø®ØªØµØ§ØµÙ ÙØžÙ
+ Ù
+ÙØªØšØ§Øª ÙØ³ÙØ§Ù Ø§ÙØ®ØšÙØ±) " *.*" Ù
+ÙØ§Ø±ÙØ© ØšØ§Ù Ù
+Ø­Ø§Ø±Ù0
+</Text>
+</Section>
+</Section>
+<Section name="enrichingacollection">
+<Title>
+<Text id="73">Ø¥Ø«Ø±Ø§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø© ØšÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª</Text>
+</Title>
+<Text id="74">ÙØ¹Ø¯ ØªØ¬Ù
+ÙØ¹ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+ØªØ¹Ø¯Ø¯Ø© ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©Ø ÙÙ
+ÙÙÙ Ø§ÙØ£Ù  Ø¥Ø«Ø±Ø§Ø€ÙØ§ ØšÙ
+Ø¹ÙÙÙ
+Ø§Øª Ø§Ø¶Ø§ÙÙØ© ØªØ³Ù
+Ù "ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª"0 ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ÙÙØ¶Ø­ ÙÙÙÙØ© Ø§ÙØŽØ§Ø¡Ø ØªØ¹Ø¯ÙÙØ ØªØ¹ÙÙÙØ Ø§Ø³ØªØ±Ø¬Ø§Ø¹ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙÙÙÙØ© Ø§Ø³ØªØ®Ø¯Ø§Ù
+ ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+Ù Ù
+ØµØ§Ø¯Ø± Ø®Ø§Ø±Ø¬ÙØ© </Text>
+<Section name="theenrichview">
+<Title>
+<Text id="75">Ù
+ØŽÙØ¯ Ø¥Ø«Ø±Ø§Ø¡</Text>
+</Title>
+<Text id="76">Ø§Ø³ØªØ®Ø¯Ù
+ Ù
+ØŽÙØ¯ Ø¥Ø«Ø±Ø§Ø¡<AutoText key="glidict::GUI.Enrich"/> ÙØªØ¹ÙÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙØ«Ø§ØŠÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙ ØšÙØ§ÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª - ØªØ­Ø¯ÙØ¯Ø§Ù Ø§ÙØ¹ÙÙØ§ÙØ Ø§ÙÙ
+Ø€ÙÙØ ØªØ§Ø±ÙØ® Ø§ÙØ¥ÙØŽØ§Ø¡ ÙÙÙØ°Ø§Ø Ø§Ù ÙØ§ØµÙØ© ØšÙØ§ÙØ§Øª ØªØªÙÙÙ Ù
+Ù Ø¬Ø²ØŠÙÙ "Ø§ÙØ¹ÙØµØ±"<AutoText key="glidict::Metadata.Element"/> ÙØªØ­Ø¯ÙØ¯ ØµÙØ© Ø§ÙØ¹ÙØµØ± (Ù
+Ø«ÙØ§Ù Ø§ÙÙ
+Ø€ÙÙ) Ù"Ø§ÙÙÙÙ
+Ø©"<AutoText key="glidict::Metadata.Value"/> ÙØšÙØ§Ù Ù
+Ø­ØªÙÙ Ø°ÙÙ Ø§ÙØ¹ÙØµØ± (Ø§Ø³Ù
+ Ø§ÙÙ
+Ø€ÙÙ)0</Text>
+<Text id="77"> ÙÙØ¬Ø¯ ÙØ³Ø§Ø± Ù
+ØŽÙØ¯ <AutoText key="glidict::GUI.Enrich"/>ØŽØ¬Ø±Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 ÙÙ ÙØžØ§ØŠÙ Ø§ÙØ²Ø± Ø§ÙØ§ÙÙ
+Ù Ù
+ØªØ§Ø­Ø© ÙØŽØ¬Ø±Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ù
+Ù Ù
+ØŽÙØ¯ <AutoText key="glidict::GUI.Gather"/>ÙÙÙ Ù
+ØªØ§Ø­Ø© ÙÙØ§ Ø£ÙØ¶Ø§Ù0 ÙÙ Ø§ÙØ¬Ø§ÙØš Ø§ÙØ§ÙÙ
+Ù Ø¬Ø¯ÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØªÙ ØªÙØ¶Ø­ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙÙ
+ÙÙØ§Øª Ø£Ù Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª ÙÙ ØŽØ¬Ø±Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 ØªÙ
+Øª ØªØ³Ù
+ÙØ© Ø§ÙØ§Ø¹Ù
+Ø¯Ø© ØšØ§ÙÙÙÙ Ø§ÙØ±Ù
+Ø§Ø¯Ù ÙÙ Ø§ÙØ§Ø¹ÙÙ0 ÙÙ
+ÙÙ Ø§ÙØªÙ
+Ø¯ÙØ¯ Ø£Ù Ø§ÙØªÙÙÙØµ ØšØ³Ø­Øš Ø§ÙØ®Ø· Ø§ÙÙØ§ØµÙ0 Ø§Ø°Ø§ Ø«Ù
+ Ø§Ø®ØªÙØ§Ø± Ù
+Ø¬Ù
+ÙØ¹Ø© Ù
+ÙÙØ§Øª ÙØŽÙØ± Ø§ÙÙØµ Ø§ÙØ£Ø³ÙØ¯ Ø¥ÙÙ ÙÙÙ
+Ø© Ù
+ØŽØªØ±ÙØ© ØšÙÙ Ø§ÙØ¹ÙØ§ØµØ± Ø§ÙÙ
+Ø®ØªØ§Ø±Ø© ØšÙÙÙ
+Ø§ ÙØŽÙØ±  Ø§ÙÙØµ Ø§ÙØ±Ù
+Ø§Ø¯Ù Ø¥ÙÙ Ø¹ÙØ³ Ø°ÙÙ0  ØªØ¹Ø¯ÙÙ Ø§ÙÙÙÙÙÙ
+ Ø§ÙØ±Ù
+Ø§Ø¯ÙØ© ÙØ€Ø«Ø± ÙÙØ· ÙÙ Ø§ÙÙØ«Ø§ØŠÙ Ø§ÙØªÙ ÙÙØ§ ÙØ°Ù Ø§ÙÙØ§ØµÙØ§ØªØ Ø£Ù ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø¬Ø¯ÙØ¯Ø© Ù
+Ø¯Ø®ÙØ© ØªØªÙ
+ Ø§Ø¶Ø§ÙØªÙØ§ Ø¥ÙÙ ÙÙ Ø§ÙÙÙÙ
+ Ø§ÙÙ
+Ø®ØªØ§Ø±Ø©0</Text>
+<Text id="78">ÙØžÙØ± ØšØ¬Ø§ÙØš Ø±Ù
+Ø² Ù
+Ø¬ÙØ¯ ØšØ¹Ø¶ Ù
+Ø¯Ø§Ø®Ù ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙØŽÙØ± ÙØ°Ø§ Ø¥ÙÙ Ø£Ù ÙØ°Ù Ø§ÙÙÙÙ
+ ÙØ¯ ØªÙ
+ ØªØ¶Ù
+ÙÙÙØ§ Ù
+Ù Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙØ£Ø¹ÙÙ (Ø§ÙØ³ÙÙ)Ø ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¶Ù
+ÙÙ ÙØ§ ÙÙ
+ÙÙ Ø­Ø°ÙÙØ§ Ø£Ù ØªØ¹Ø¯ÙÙÙØ§ ÙÙ Ø¥ÙØ§ ÙÙ Ù
+ÙØ·ÙØ© Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙØ§Ø¹ÙÙØ Ø­ÙØ« ØªÙ
+ ØªØ¹ÙÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª0
+</Text>
+<Text id="79">Ø§ÙÙÙØ± Ø¹ÙÙ Ø¹ÙØµØ± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª ÙÙ Ø§ÙØ¬Ø¯ÙÙØ ÙØ¹Ø±Ø¶ Ø§ÙÙÙÙÙÙ
+  Ø§ÙÙ
+ÙØ¬ÙØ¯Ø© ÙØ°ÙÙ Ø§ÙØ¹ÙØµØ± ÙÙ Ù
+Ø³Ø§Ø­Ø©  "ØŽØ¬Ø±Ø© Ø§ÙÙÙÙ
+00"<AutoText key="glidict::EnrichPane.ExistingValues" args="..."/> Ø§ÙÙ
+ÙØ¬ÙØ¯Ù Ø§Ø³ÙÙ Ø§ÙØ¬Ø¯ÙÙ0  ØªØªÙ
+Ø¯Ø¯ Ø£Ù ØªØªÙÙØµ ØªÙÙ Ø§ÙÙÙÙ
+ ÙÙÙØ§Ù ÙÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¯Ø®ÙØ© Ù
+Ù ÙØšÙ ÙØ¹ÙØµØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±0Ø§ÙÙÙØ± Ø¹ÙÙ Ù
+Ø¯Ø®Ù ÙØ¶Ø¹Ù ØªÙÙØ§ØŠÙØ§Ù ÙÙ ÙÙÙ
+Ø© Ø§ÙØ­ÙÙØ conversly Ø§ÙØ·ØšØ§Ø¹Ù ÙÙ Ø­ÙÙ Ø§ÙÙØµ ØªØ®ØªØ§Ø± Ø§ÙÙØµ Ø§ÙØ°Ù ÙØšØ¯Ø£ ØšÙÙØ³ Ø§ÙØ­Ø±Ù0 Ø§ÙØ¶ØºØ· Ø¹ÙÙ Ù
+ÙØªØ§Ø­ [Tab] ÙÙÙ
+Ù ØªÙÙØ§ØŠÙØ§Ù Ø·ØšØ§Ø¹Ù Ø§ÙÙÙÙ
+Ø© Ø§ÙÙ
+Ø®ØªØ§Ø±Ø©0
+</Text>
+<Text id="80">ÙÙ
+ÙÙ ØªÙØžÙÙ
+ ÙÙÙÙÙ
+ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙ ØªØ±ØªÙØš    - ÙÙ
+ÙÙ Ø§Ø¯Ø®Ø§Ù Ø§ÙÙÙÙÙÙ
+  Ø§ÙÙØ±Ù
+ÙÙ ØšØ§Ø³ØªØ®Ø¯Ø§Ù
+ Ø§ÙÙ
+Ø­Ø±Ù "|" ÙÙØµÙ Ø§ÙÙ
+Ø³ØªÙÙØ§Øª- Ù
+Ø«Ø§ÙØ "ÙØ±ÙØª Ø§ÙÙÙØªØŽÙÙÙ |Ø§ÙØ§Ø­Ù
+Ø±| Ø§ÙØ¬ÙÙØ±Ø©| Ø§ÙØ³ØšØ¹Ù" ÙÙØªÙ
+Ø«ÙÙ Ø§ÙÙØ±Ù
+Ù ÙÙØ±ÙØª Ø§ÙÙÙØªØŽÙÙÙØ ÙÙ
+ÙÙ  ÙØ°Ø§ Ù
+Ù ØªØ¬Ù
+ÙØ¹  Ø§ÙÙÙÙÙÙ
+ Ù
+Ø¹Ø§Ù0 ÙÙ
+ÙÙ ØªØ¹ÙÙÙ ÙØ°Ù Ø§ÙÙÙÙÙ
+Ù ÙÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª ÙÙÙ
+ÙÙØ§Øª0
+</Text>
+<Text id="81">ÙØ³ØªØ®Ø±Ø¬ ÙØ±ÙÙØ³ØªÙÙ ØªÙÙØ§ØŠÙØ§Ù ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ù
+Ù Ø§ÙÙØ«Ø§ØŠÙ ÙÙ
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+ØšØªØ¯ØŠØ© ØšÙ "ex." ÙÙØ°Ù Ø§ÙÙØ§ØµÙØ§Øª  ØºÙØ± Ù
+ÙØ¹ÙÙ ÙÙØ§ ÙÙ
+ÙÙ ØªØ¹Ø¯ÙÙÙØ§0     </Text>
+</Section>
+<Section name="selectingmetadatasets">
+<Title>
+<Text id="82">Ø¥Ø®ØªÙØ§Ø± Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª</Text>
+</Title>
+<Text id="83">Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¹Ø±ÙØ© Ù
+Ù ÙØšÙ ØªØ¹Ø±Ù ØšÙ "Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª"0 Ù
+Ø«Ø§ÙØ Ù
+Ø¹ÙØ§Ø± Ø¯ØšÙÙ ÙÙØ± ÙÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª0 Ø¹ÙØ¯ Ø¥Ø¶Ø§ÙØ© Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª ÙÙ
+Ø¬Ù
+ÙØ¹ØªÙ ØªØµØšØ­  Ø¹ÙØ§ØµØ±Ù Ù
+ØªØ§Ø­Ø© ÙÙØ§Ø®ØªÙØ§Ø±0 ÙÙ
+ÙÙÙ Ø§Ø®ØªÙØ§Ø± Ø£ÙØ«Ø± Ù
+Ù Ù
+Ø¹ÙØ§Ø± ÙÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§ØªØ ÙÙ
+ÙØ¹ ØªØ¶Ø§Ø±Øš Ø§ÙØ§Ø³Ù
+Ø§Ø¡Ø ÙÙØ­Ø¯ Ù
+Ø¹Ø±Ù ÙØµÙØ± ÙØšÙ Ø§Ø³Ù
+ Ø§ÙØ¹ÙØµØ± ÙÙ
+Ø«Ø§Ù Ù
+Ø¹Ø±ÙÙ Ø¹ÙØµØ± Ù
+Ø¹ÙØ§Ø± Ø¯ØšÙÙ ÙÙØ± ÙÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª  ÙØµØšØ­  "Ù
+Ø€ÙÙ .dc" ØªØ­ÙØž Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙ Ù
+Ø³Ø§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª"Metadata"ÙÙ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ÙÙØ­Ù
+Ù Ø§ÙØ§Ù
+ØªØ¯Ø§Ø¯ "mds."
+</Text> 
+<Text id="84">ØªØªÙ
+ Ø§Ø¶Ø§ÙØ© Ù
+Ø¹ÙØ§Ø± Ø¯ØšÙÙ ÙÙØ± ØšØµÙØ±Ø© Ø§ÙØªØ±Ø§Ø¶ÙØ© Ø¹ÙØ¯ Ø§ÙØŽØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø© Ø¬Ø¯ÙØ¯Ø©0 ÙÙ
+ÙÙÙ  ØªØºÙÙØ± Ø£Ù Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+Ø³ØªØ®Ø¯Ù
+ ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØšØ§ÙÙÙØ± Ø¹ÙÙ Ø²Ø± "Ø§Ø¯Ø§Ø±Ø© Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª" ØªØ­Øª ØŽØ¬Ø±Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙ Ù
+ØŽÙØ¯ Ø¥Ø«Ø±Ø§Ø¡0 ÙÙÙØ¯ ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ ÙØžÙÙØ± ÙØ§ÙØ°Ø© Ø¬Ø¯ÙØ¯Ø© ÙØ§Ø¯Ø§Ø±Ø© Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0
+</Text>
+<Text id="84a"> ÙØ§ØŠÙ
+Ø© "Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø©" ØªØ¹Ø±Ø¶ Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+Ø© ÙÙ Ø§ÙÙ
+Ø¬ÙØ¹Ø© Ø­Ø§ÙÙØ§Ù0</Text>
+<Text id="84b"> ÙØ§Ø³ØªØ®Ø¯Ø§Ù
+ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø¢Ø®Ø± Ù
+Ø¹ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©Ø Ø§ÙÙØ± "Ø§Ø¶Ø§ÙØ©00" ØªØžÙØ± ÙØ§ØŠÙ
+Ø© ØªÙØ¶Ø­ Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØ§ÙØªØ±Ø§Ø¶ÙØ© Ø§ÙØªÙ ÙØ¹Ø±ÙÙØ§ GLI ÙØ§Ø¶Ø§ÙØ©  ÙØ§Ø­Ø¯ Ù
+ÙÙØ§Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø© ÙØ§ÙÙØ± "Ø§Ø¶Ø§ÙØ©" Ø§Ø°Ø§ ÙÙ
+Øª ØšØªØ¹Ø±ÙÙ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø®Ø§ØµØªÙØ ÙÙ
+ÙÙÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+ Ø²Ø± "ØªØµÙØ­" ÙØªØ­Ø¯ÙØ¯ Ù
+ÙÙØ¹ Ø§ÙÙ
+ÙÙ ÙÙ ÙØžØ§Ù
+ Ø§ÙÙ
+ÙÙØ§Øª0
+</Text>
+<Text id="84c">ÙØ§ÙØŽØ§Ø¡ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø¬Ø¯ÙØ¯Ø Ø§ÙÙØ± "Ø¬Ø¯ÙØ¯"Ø ÙØ€Ø¯Ù ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ Ø¥ÙÙ Ø¥Ø·ÙØ§Ù Ù
+Ø­Ø±Ø± ÙØ±ÙÙØ³ØªÙÙ ÙÙ
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª GEMS ØªØžÙØ± ÙØ§ÙØ°Ø© ØªØ­Ø«Ù ÙØªØ­Ø¯ÙØ¯ Ø§ÙØ§Ø³Ù
+Ø Ø§Ø³Ù
+ Ù
+Ø³Ø§Ø­Ø© ÙØ§ÙÙØ­Ø¯Ø©0 ÙÙ
+ÙÙÙ Ø§ÙØ¶Ø§Ù Ø§Ø®ØªÙØ§Ø± Ù
+Ø¹ÙØ§Ø± ÙØªØ£Ø³ÙØ³ Ø§ÙÙ
+Ø¹ÙØ§Ø± Ø§ÙØ¬Ø¯ÙØ¯ Ø¹ÙÙÙ0 ÙÙ ÙØ°Ù Ø§ÙØ­Ø§ÙØ© Ø³ÙÙ ØªØ¶Ù
+Ù ÙÙ Ø§ÙØ¹ÙØ§ØµØ± Ù
+Ù Ø§ÙÙ
+Ø¹ÙØ§Ø± Ø§ÙÙ
+Ø­Ø¯Ø¯0 Ø§ÙÙØ± "OK" ØªØžÙØ± Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙØ±ØŠÙØ³Ù ÙÙ
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª  Ø§ÙØšÙØ§ÙØ§Øª Ø¥ÙÙ Ø§ÙÙØ³Ø§Ø± ÙØšØ¹Ø¶ Ø§ÙØµÙØ§Øª ÙÙÙ
+Ø¹ÙØ§Ø± ÙÙ
+ÙÙØ§ÙØ Ø§Ø°Ø§ ØªÙ
+ ØªØ£Ø³ÙØ³ Ø§ÙÙ
+Ø¹ÙØ§Ø± Ø¹ÙÙ Ù
+Ø¹ÙØ§Ø± Ù
+ÙØ¬ÙØ¯ ÙØ¹Ø±Ø¶ Ø¹ÙØµØ± Ø£Ù Ø¹ÙØ§ØµØ±0
+</Text>
+<Text id="84d">ÙØ§Ø¶Ø§ÙØ© Ø¹ÙØµØ± Ø¬Ø¯ÙØ¯Ø Ø§Ø¶ØºØ· Ø§ÙØ²Ø± Ø§ÙØ§ÙÙ
+Ù ÙÙ Ø§ÙÙ
+Ø¹ÙØ§Ø± ÙÙÙ
+ ØšØ¥Ø®ØªÙØ§Ø±  "Ø§Ø¶Ø§ÙØ© Ø¹ÙØµØ±" - ÙØ§Ø¶Ø§ÙØ© Ø¹ÙØµØ± ÙØ±Ø¹Ù Ø¬Ø¯ÙØ¯Ø Ø§Ø¶ØºØ· Ø§ÙØ²Ø± Ø§ÙØ§ÙÙ
+Ù  ÙÙÙ
+  ØšØ§Ø®ØªÙØ§Ø± "Ø§Ø¶Ø§ÙØ© Ø¹ÙØµØ± ÙØ±Ø¹Ù" ÙÙ
+ÙÙ Ø¥ÙØºØ§Ø¡ "Ø¹ÙØµØ± (ÙØ±Ø¹Ù)" Ù
+Ù ÙØ§ØŠÙ
+Ø© Ø§ÙØ²Ø± Ø§ÙØ§ÙÙ
+Ù. </Text>
+<Text id="84e"> ØªØ¬Øš Ù
+ÙØ§Ø­ØžØ© Ø§Ù Ù
+Ø­Ø±Ø± ÙØ±ÙÙØ³ØªÙÙ ÙÙ
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙ
+ÙÙ ØªØŽØºÙÙÙ Ù
+Ø³ØªÙÙØ§Ù Ø¹Ù GLIØ ØšØ§Ø®ØªÙØ§Ø±Ù Ù
+Ù ÙØ§ØŠÙ
+Ø© Ù
+Ù ÙØ§ØŠÙ
+Ø© Ø§ÙØšØ¯Ø§ÙØ© ÙÙØ±ÙÙØ³ØªÙÙ Ø£Ù ØšØªØŽØºÙÙ gens.sh Ø£Ù gems.bat ÙÙ Ù
+Ø¬ÙØ¯ GLI ÙÙ ØªØ«ØšÙØª  ÙØ±ÙÙØ³ØªÙÙ0 </Text>
+<Text id="84f">Ø£Ø­ÙØ§ÙØ§Ù ÙÙÙÙ Ø§Ø³Ù
+ Ø§ÙÙ
+Ø³Ø§Ø­Ø© Ù
+ØŽØªØ±ÙØ§Ù ØšÙÙ Ù
+ÙØ§Ø¯ÙÙ ÙÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª0 Ù
+Ø«Ø§Ù Dultin lore Ù Qualifiel Dubin lore ÙÙØ§Ø«ÙØ§Ù ÙØ³ØªØ®Ø¯Ù
+Ø§Ù Ø§Ø³Ù
+ Ø§ÙÙ
+Ø³Ø§Ø­Ø© "dc."  - ÙÙØ§ ÙÙ
+ÙÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+ Ù
+Ø«Ù ÙØ°Ù Ø§ÙÙ
+Ø¹Ø§ÙÙØ± ÙÙ ÙÙØª ÙØ§Ø­Ø¯ Ù
+Ù Ù
+Ø¬Ù
+ÙØ¹Ø© ÙØ§Ø­Ø¯Ø© ÙØ³ÙÙ ÙØžÙØ± ÙÙ  ØªØ­Ø°ÙØ±Ø Ø§Ø°Ø§ Ù
+Ø¶ÙØª ÙØ¯Ù
+Ø§Ù Ø³ÙÙ ÙØªÙ
+ Ø­Ø°Ù Ø§ÙÙ
+Ø¹ÙØ§Ø± Ø§ÙÙ
+ÙØ¬ÙØ¯ ÙØ§Ø¶Ø§ÙØ©  ØªØ§ÙØ¬Ø¯ÙØ¯0 ØªØªÙ
+ Ø§Ø¶Ø§ÙØ© ÙÙÙ
+ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø© Ø§ÙÙ Ø§ÙÙ
+Ø¹ÙØ§Ø± Ø§ÙØ¬Ø¯ÙØ¯ ÙØªÙÙÙØ± Ø§ÙØ¹ÙØ§ØµØ± Ø§ÙØªÙ  Ø²Ø§ÙØª Ù
+ÙØ¬ÙØ¯Ø©0</Text>
+<Text id="191"> ØšØ¥Ø³ØªØ®Ø¯Ø§Ù
+ GEMS ÙÙ
+ÙÙÙ ØªØ¹Ø¯ÙÙ Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+ÙØ¬ÙØ¯Ø© ÙÙ
+Ø§ ÙÙ
+ÙÙ Ø§ÙØŽØ§Ø¡ Ù
+Ø¹Ø§ÙÙØ± Ø¬Ø¯ÙØ¯Ø© - ÙÙØ± "ØªØ¹Ø¯ÙÙ" ÙØ€Ø¯Ù Ø¥ÙÙ Ø§Ø·ÙØ§Ù GEMS" ÙÙØªØ­ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø­Ø¯Ø¯0 Ø¹ÙØ¯ Ø§ÙØªÙØ§Ø¡ ØªØ¹Ø¯ÙÙ Ø§ÙÙ
+Ø¹ÙØ§Ø± (ÙÙ
+Ø§ ÙÙ Ù
+ÙØµÙÙ Ø£Ø¹ÙØ§Ù) ÙÙ
+ ØšØ­ÙØžÙ ÙÙ ÙØ§ØŠÙ
+Ø©-->Ù
+ÙÙ --> Ø­ÙØž ÙØ§ØºÙØ§Ù GEMS.
+</Text>
+<Text id="192">Ø§Ø°Ø§ ÙÙ
+ ÙØªÙ
+ ØªØ¹Ø¯ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ù
+Ø­ØªØ§Ø¬Ù ÙÙ
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§ØªØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù  ÙØ§Ø¶ØºØ· "Ø­Ø°Ù" - Ø§Ø°Ø§ ÙØ§Ù ÙØ¯ÙÙ Ø§Ù ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª ÙÙ Ø¹ÙØ§ØµØ±Ø ÙØ³ÙÙ ÙØªÙ
+ Ø§Ø³ØªÙØ³Ø§Ø±Ù Ø­ÙÙ ÙÙÙÙØ© Ø§ÙØªØµØ±Ù Ù
+Ø¹ ÙØ°Ù Ø§ÙÙØ§ØµÙØ§Øª Ø¹ÙØ¯ ÙØªØ­ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©  ÙÙ Ø§ÙÙ
+Ø±Ø© Ø§ÙØªØ§ÙÙØ©0</Text>
+</Section>
+<Section name="appendingmetadata">
+<Title>
+<Text id="85">ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø¬Ø¯ÙØ¯Ø© Ù
+Ø¹ÙÙØ©</Text>
+</Title>
+<Text id="86">ÙØ­Ù Ø§ÙØ¢Ù ÙØ¶ÙÙ Ø¹ÙØµØ± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§ØªØ Ø§ÙØ¹ÙØµØ± ÙÙÙÙ
+Ø© Ø§ÙØ¹ÙØµØ± Ø§ÙÙ Ù
+ÙÙ0 Ø§ÙÙØ§Ù ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ù
+ÙÙ Ù
+Ù ØŽØ¬Ø±Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø¹ÙÙ Ø§ÙÙØ³Ø§Ø±Ø ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ ÙØ³ØšØš Ø§Ù Ø§Ù ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+Ø­Ø¯Ø¯Ø© Ù
+Ù ÙØšÙ Ø³ÙÙ ÙØªÙ
+ ØªØ¹ÙÙÙØ§ ÙÙØ°Ø§ Ø§ÙÙ
+ÙÙ ÙØ³ÙÙ ØªØžÙØ± ÙÙ Ø§ÙØ¬Ø¯ÙÙ ÙÙ Ø§ÙØ¬Ø§ÙØš Ø§ÙØ§ÙÙ
+Ù0
+</Text>
+<Text id="87"> ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø¹ÙØµØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØ°Ù ØªÙØ¯ Ø§Ø¶Ø§ÙØªÙ ØšÙØ§Ø³Ø·Ø© Ø§ÙÙÙØ± Ø¹ÙÙ Ù
+ÙØ§ÙÙ ÙÙ Ø§ÙØ¬Ø¯ÙÙ0</Text>
+<Text id="88">Ø§Ø·ØšØ¹ Ø§ÙÙÙÙ
+Ø© Ø¯Ø§Ø®Ù Ø§ÙØ­ÙÙ0 Ø§Ø³Ø®Ø¯Ù
+ Ù
+Ø­Ø±Ù "|" ÙØ§Ø¶Ø§ÙØ© Ø§ÙØšÙØ§Ø¡ Ø§ÙÙØ±Ù
+ÙØ ÙÙ
+Ø§ ÙÙ Ù
+ÙØµÙÙ <Reference target="theenrichview"/>- Ø§ÙØ¶ØºØ· Ø¹ÙÙ Ù
+ÙØ§ØªÙØ­ Ø§Ø³ÙÙ
+ (Ø§Ø¹ÙÙ) Ù (Ø§Ø³ÙÙ) ÙØ­ÙØž ÙÙÙ
+Ø©  ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙØ­Ø±Ù  Ø§ÙØ§Ø®ØªÙØ§Ø± ØšØµÙØ±Ø© Ù
+ÙØ§Ø³ØšØ©0 Ø§ÙØ¶ØºØ· Ø¹ÙÙ Ù
+ÙØªØ§Ø­ [Enter] Ø³ÙÙ ÙØ­ÙØž  ÙÙÙ
+Ø© ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙÙØŽØŠ Ù
+Ø¯Ø®Ù ÙØ§Ø±Øº Ø¬Ø¯ÙØ¯ ÙØ¹ÙØµØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙÙ
+ÙÙÙ Ù
+Ù ØªØ¹ÙÙÙ ÙÙÙ
+ Ù
+ØªØ¹Ø¯Ø¯Ø© ÙØ¹ÙØµØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª0</Text>
+<Text id="89">ÙÙ
+ÙÙÙ Ø£ÙØ¶Ø§Ù Ø§Ø¶Ø§ÙØ© ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø§ÙÙ Ù
+Ø¬ÙØ¯ Ø£Ù Ø§ÙÙ Ù
+ÙÙØ§Øª Ù
+ØªØ¹Ø¯Ø¯Ø© Ù
+Ø®ØªØ§Ø±Ø© ÙØ¥ÙÙ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙØ±Ø¹ÙØ©0 ÙØ¬Øš Ø£Ù ØªØªØ°ÙØ± Ø§Ù ØªØ¹ÙÙÙ ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø¥ÙÙ Ù
+Ø¬ÙØ¯Ø ÙØ¹ÙÙ Ø£Ù ÙØ°Ù Ø§ÙÙØ§ØµÙØ§Øª Ø³ÙÙ ÙØªÙ
+ ØªØ¶Ù
+ÙÙÙØ§ ØªÙÙØ§ØŠÙØ§Ù ÙØ§Ù Ù
+ÙÙØ§Øª Ø¬Ø¯ÙØ¯Ø© Ø¯Ø§Ø®Ù ÙÙÙ
+ ÙØ°Ù Ø§ÙÙ
+Ø¬ÙØ¯0
+</Text>
+</Section>
+<Section name="addingpreviouslydefinedmetadata">
+<Title>
+<Text id="90">Ø¥Ø¶Ø§ÙØ© ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¹Ø±ÙØ© Ø³Ø§ØšÙØ§</Text>
+</Title>
+<Text id="91">ÙØ§Ø¶Ø§ÙØ© ÙØ§ØµÙÙ ØšÙØ§ÙØ§Øª Ø¬Ø¯ÙØ¯Ø© ÙØ§Ø®Ø±Ù Ù
+ÙØ¬ÙØ¯Ù Ù
+Ù ÙÙÙ
+Ø© Ø§ÙØ­ÙÙØ Ø§ÙÙØ§Ù ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø§ÙÙ
+ÙÙØ  Ø«Ù
+ Ø§Ø®ØªÙØ§Ø± Ø§ÙÙÙÙ
+Ø© Ø§ÙÙ
+Ø·ÙÙØšØ© Ù
+Ù ØŽØ¬Ø±Ø© Ø§ÙÙÙÙ
+Ø ØªÙØ³ÙØ¹  Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª Ø§ÙÙØ±Ù
+ÙÙ ÙÙÙØ§Ù ÙÙ
+Ø§ ÙÙ Ù
+Ø·ÙÙØšØ Ø³ÙÙ ØªØžÙØ± ØªÙÙØ§ØŠÙØ§Ù ÙÙÙ
+Ø© Ø§ÙÙ
+Ø¯Ø®Ù Ø§ÙÙ
+Ø®ØªØ§Ø± ÙÙ ÙÙÙ
+Ø© Ø§ÙØ­ÙÙ (ØšØ¯ÙØ§ÙØ Ø§Ø³ØªØ®Ø¯Ù
+ Ø§Ø®ØªÙØ§Ø± Ø§ÙÙÙÙ
+ Ø§ÙØªÙÙØ§ØŠÙ ÙØ³Ù
+Ø§Øª Ø§ÙØ§ÙÙØ§Ø¡ Ø§ÙØªÙÙØ§ØŠÙ)0
+ </Text>
+<Text id="92">Ø¥Ø¬Ø±Ø§Ø¡ Ø¥Ø¶Ø§ÙØ© ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+Ø¹ ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+ÙØ¬ÙØ¯Ø© Ù
+Ù ÙØšÙ Ø¥ÙÙ Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª Ø£Ù Ø§ÙÙ
+ÙÙØ§Øª ÙÙ ÙÙØ³ Ø§ÙØ§Ø¬Ø±Ø§Ø¡0</Text>
+</Section>
+<Section name="updatingmetadata">
+<Title>
+<Text id="93">ØªØ¹Ø¯ÙÙ Ø§Ù Ø­Ø°Ù ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª</Text>
+</Title>
+<Text id="94">ÙØªØ­Ø¯ÙØ« Ø£Ù Ø­Ø°Ù ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§ØªØ ÙÙ
+ Ø§ÙÙØ§Ù ØšØ§Ø®ØªÙØ§Ø± Ø§ÙÙ
+ÙÙ Ø§ÙÙ
+Ø·ÙÙØš Ø«Ù
+ ÙÙÙ
+Ø© ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ù
+Ù Ø§ÙØ¬Ø¯ÙÙ0 ÙÙ
+ ØšØªØ­Ø¯ÙØ« ÙÙÙ
+Ø© Ø§ÙØ­ÙÙ Ø£Ù Ø¥ÙØºØ§Ø¡ ÙÙ Ø§ÙÙØµ Ø§Ø°Ø§ Ø§Ø±Ø¯Øª Ø­Ø°Ù ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª0
+</Text>
+<Text id="95">ÙØªØšØ¹  ÙÙØ³  Ø§ÙØ§Ø¬Ø±Ø§Ø¡ Ø¹ÙØ¯ ØªØ­Ø¯ÙØ« Ù
+Ø¬ÙØ¯ ÙØ­ØªÙÙ  Ù
+Ø¬ÙØ¯Ø§Øª ÙØ±Ø¹ÙØ© Ø£Ù Ù
+ÙÙØ§Øª Ù
+ØªØ¹Ø¯Ø¯Ø©Ø  ÙÙ
+ÙÙÙ ØªØ­Ø¯ÙØ« ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+ØŽØªØ±ÙØ© ÙÙÙ Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª / Ø§ÙÙ
+ÙØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±Ø©0</Text>
+<Text id="96">ØªØžÙØ± ØŽØ¬Ø±Ø© Ø§ÙÙÙÙ
+ ÙÙ Ø§ÙÙÙÙ
+ Ø§ÙÙ
+Ø­Ø¯Ø¯Ø©  Ø§ÙØ­Ø§ÙÙØ© ÙØ§ÙØ³Ø§ØšÙØ© Ø¹ÙØ¯ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ Ø¹ÙØ¯ ØºÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø«Ù
+ ÙØªØ­ÙØ§  Ù
+Ø±Ø© Ø£Ø®Ø±Ù ØªØ®ØªÙÙ ÙÙ Ø§ÙÙÙÙ
+ Ø§ÙØªÙ ÙÙ
+ ÙØªÙ
+ ØªØµÙÙÙÙØ§0</Text>
+</Section>
+<Section name="reviewingmetadata">
+<Title>
+<Text id="97">
+Ø¥Ø³ØªØ¹Ø±Ø§Ø¶ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø©</Text>
+</Title>
+<Text id="98">ØªØ­ØªØ§Ø¬ Ø§Ø­ÙØ§ÙØ§Ù ÙØ±Ø€ÙØ© ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ÙÙØ© ÙØ¹Ø¯Ø¯ Ù
+Ù Ø§ÙÙ
+ÙÙØ§Øª Ù
+Ø±Ø© ÙØ§Ø­Ø¯Ø©00 Ù
+Ø«ÙØ§ ÙØªØ­Ø¯ÙØ¯ Ø­Ø¬Ù
+ Ø§ÙØ¹Ù
+Ù ÙÙ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+ØªØšÙÙØ© Ø§Ù ÙØ§Ø®Ø° ÙÙØ±Ø© Ø­ÙÙ Ø§ÙØªØºØ·ÙØ© Ø§ÙØ²Ù
+ÙÙØ©0
+</Text>
+<Text id="99">ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙØªÙ ØªÙØ¯ ÙØ­ØµÙØ§Ø Ø«Ù
+ Ø§ÙØ¶ØºØ· Ø¹ÙÙ Ø²Ø± Ø§ÙÙØ£Ø±Ø© Ø§ÙØ§ÙÙ
+Ù  ÙØ§Ø®ØªÙØ§Ø± "ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø© " ÙØžÙØ± ÙÙ Ø¬Ø¯ÙÙ ÙØšÙØ± ÙÙ ÙØ§ÙØ°Ø© Ø§Ø¹ÙÙØ§Ù  "ÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª" ÙØžÙØ± ÙÙ Ø§ÙØ¹Ù
+ÙØ¯ Ø§ÙØ£ÙÙ Ø§Ø³Ù
+Ø§Ø¡ Ø§ÙÙ
+ÙÙØ§Øª ÙØªØžÙØ± ÙÙ "rows" ÙÙ ÙÙÙ
+ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø­Ø¯Ø¯Ø© ÙÙØ°Ù Ø§ÙÙ
+ÙÙØ§Øª0
+</Text>
+<Text id="100">Ø±Ø³Ù
+ Ø§ÙØ¬Ø¯ÙÙ ÙØ¯ ÙØ³ØªØºØ±Ù Ø²Ù
+ÙØ§ÙØ Ø§Ø°Ø§ ØªÙ
+ Ø§Ø®ØªÙØ§Ø± Ù
+Ø¬Ù
+ÙØ¹Ø© Ù
+Ù Ø§ÙÙ
+ÙÙØ§Øª  ÙÙ
+ÙÙÙ Ø§ÙØ§Ø³ØªÙ
+Ø±Ø§Ø± ÙÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ØšÙÙÙ
+Ø§ ÙØ§ÙØ°Ø© "ÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª" Ù
+ÙØªÙØ­Ø©0</Text>
+<Text id="101">Ø¹ÙØ¯Ù
+Ø§ ÙØµØšØ­ Ø§ÙØ­Ø¬Ù
+ ÙØšÙØ±Ø§ÙØ ÙÙ
+ÙÙÙ ØªØ±ØŽÙØ­ Ø¬Ø¯ÙÙ "ÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª" ÙØªØ·ØšÙÙ Ø§ÙÙ
+Ø±ØŽØ­Ø§Øª Ø¹ÙÙ Ø§ÙØ£Ø¹Ù
+Ø¯Ø© - ØšØ§Ø¶Ø§ÙØ© Ø§ÙÙ
+Ø±ØŽØ­Ø§Øª Ø§ÙØ¬Ø¯ÙØ¯Ø© ØªØªØšÙÙ ÙÙØ· Ø§ÙØ§Ø¹Ù
+Ø¯Ø© Ø§ÙÙ
+ØªÙØ§ÙÙØ© Ù
+Ø¹ ÙØ°Ù Ø§ÙÙ
+Ø±ØŽØ­Ø§Øª ÙØ§Ø¶Ø­Ø©  ÙÙ Ø§ÙØŽØ§ØŽØ©0 ÙØ§Ø¹Ø¯Ø§Ø¯  Ø£Ù ØªØ¹Ø¯ÙÙ Ø£Ù Ù
+Ø³Ø­ Ù
+Ø±ØŽØ­Ø Ø§ÙÙØ± Ø¹ÙÙ Ø²Ø± "funnel" Ø§Ø¹ÙÙ Ø§ÙØ¹Ù
+ÙØ¯Ø Ø³ÙÙ ÙØªÙ
+ Ø­Ø«Ù ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª Ø­ÙÙ Ø§ÙÙ
+Ø±ØŽØ­Ø Ø¹ÙØ¯ Ø¥Ø¹Ø¯Ø§Ø¯ Ø§ÙÙ
+Ø±ØŽØ­ ÙØªØºÙØ± ÙÙÙ Ø±Ø§Ø³ Ø§ÙØ¹Ù
+ÙØ¯0
+</Text>
+<Text id="102"> ÙØªÙÙØ± Ø§ÙØ­Ø« ÙÙ Ø²Ø± "ØšØ³ÙØ·" ÙØ²Ø± "Ù
+ØªÙØ¯Ù
+"0 Ø²Ø± ØšØ³ÙØ· ÙØžÙØ± Ø§ÙÙ
+Ø±ØŽØ­Ø§Øª Ø§ÙØªÙ ØªØ­ØªÙÙ Ø¹ÙÙ ÙÙÙ
+ Ù
+Ø­Ø¯Ø¯Ø© ÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ( "*" ØªØ¶Ø§ÙÙ  ÙÙ Ø§ÙÙÙÙÙÙ
+) 0 ÙÙ
+ÙÙÙ  Ø§Ø®ØªÙØ§Ø± ÙÙÙ
+ ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©0 Ø²Ø± Ù
+ØªÙØ¯Ù
+  ÙØªÙØ­ ÙÙ  Ù
+Ø®ØªÙÙ  Ø¹Ù
+ÙÙØ§Øª Ø§ÙÙ
+Ø¶Ø§ÙØ§Ø© ÙØ§ÙØªÙ ÙØ¬Øš Ø£Ù ØªØšØ¯Ø£ Øš  ÙØ§ ÙØªØ¶Ù
+Ù         Ø Ø£ÙÙ Ù
+Ù  Ø£Ù Ù
+Ø³Ø§Ù0 Ø§ÙÙÙÙ
+ Ø§ÙÙ
+Ø¶Ø§ÙØ§Ø© ÙÙ
+ÙÙ ØªØ¹Ø¯ÙÙÙØ§ ÙØªÙÙÙ Ø§Ù Ø³ÙØ§Ø³Ù Ø£Ø®Ø±Ù  (Ù
+ØªØ¶Ù
+ÙÙ "*") Ø ÙÙÙ
+ÙÙÙ Ø§Ø®ØªÙØ§Ø± Ù
+Ø§ Ø§Ø°Ø§  ÙØ§ÙØª Ø§ÙÙ
+Ø¶Ø§ÙØ§Ø©  Ø­Ø§ÙØ© ØºÙØ±  Ø­Ø³Ø§Ø³Ø©Ø Ø§Ø®ÙØ±Ø§Ù ÙÙ
+ÙÙÙ ØªØ®ØµÙØµ ØŽØ±Ø· Ø«Ø§Ù ÙÙÙ
+Ø¶Ø§ÙØ§Ø© ÙØ§Ø³ØªØ®Ø¯Ø§Ù
+Ù  ØšØªØ­Ø¯ÙØ¯ Ù
+Ø¯Ù Ù
+Ù Ø§ÙÙÙÙ
+ (  ØšØ§Ø®ØªÙØ§Ø± AND) Ø§Ø³ÙÙ ÙØ°Ù Ø§ÙÙ
+Ø³Ø§Ø­Ø© ÙÙØ¬Ø¯ Ù
+Ø±ØšØ¹  ÙØªÙØ­  ØªØºÙØ± ØªØ±ØªÙØš  Ø§ÙÙØ±Ø² (ØªØµØ§Ø¹Ø¯Ù Ø£Ù ØªÙØ§Ø²ÙÙ)0 Ø§Ø¶ØºØ· Ø¹ÙÙ "ØªØ­Ø¯ÙØ¯ Ù
+Ø±ØŽØ­" Ø¹ÙØ¯ Ø§ÙØ§ÙØªÙØ§Ø¡ ÙØªØ·ØšÙÙ Ø§ÙÙ
+Ø±ØŽØ­ Ø§ÙØ¬Ø¯ÙØ¯ Ø¹ÙÙ Ø§ÙØ¹Ù
+ÙØ¯0 Ø§ÙÙØ± "Ø­Ø°Ù Ù
+Ø±ØŽØ­" ÙØ­Ø°Ù Ø§ÙÙ
+Ø±ØŽØ­ Ø§ÙØ­Ø§ÙÙ0 Ù
+Ø¹  Ù
+ÙØ§Ø­ØžØ© Ø§Ù ØªÙØ§ØµÙÙ Ø§ÙÙ
+Ø±ØŽØ­  ÙÙ
+ÙÙ Ø§Ø³ØªØ¹Ø§Ø¯ØªÙØ§ Ø­ØªÙ Ø¹ÙØ¯  Ù
+Ø³Ø­ Ø§ÙÙ
+Ø±ØŽØ­0
+</Text><Text id="103">Ù
+Ø«Ø§ÙØ ÙÙØ±Ø² Ø¬Ø¯ÙÙ "ÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª" ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø¹Ù
+ÙØ¯Ø Ø«Ù
+ Ø§Ø®ØªÙØ§Ø± Ø§Ø¹Ø¯Ø§Ø¯ Ø§ÙÙ
+Ø±ØŽØ­ Ø§ÙØ§ÙØªØ±Ø§Ø¶Ù (Ù
+Ø±ØŽØ­ ØšØ³ÙØ· "*") ÙØ§Ø®ØªÙØ§Ø±  Ø§ÙØªØ±ØªÙØš Ø§ÙØªØµØ§Ø¹Ø¯Ù</Text>
+</Section>
+<Section name="importingpreviouslyassignedmetadata">
+<Title>
+<Text id="104">Ø¥Ø³ØªÙØ±Ø§Ø¯ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø© Ø³Ø§ØšÙØ§</Text>
+</Title>
+<Text id="105">ÙØµÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ÙÙÙÙØ© Ø§Ø³ØªÙØ±Ø§Ø¯ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ÙÙÙ Ø³Ø§ØšÙØ§Ù ÙÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØªÙ ØªÙ
+  ØªØ¹ÙÙÙÙØ§ ÙÙÙØ«Ø§ØŠÙ ÙØšÙ Ø§Ø¶Ø§ÙØªÙØ§ ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø©0</Text>
+<Text id="106">Ø¥Ø°Ø§ ÙØ§ÙØª ÙØ§ØµÙØ§Øª  Ø§ÙØšÙØ§ÙØ§Øª ÙÙ ØŽÙÙ Ù
+Ø¹Ø±ÙÙ ÙÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ÙØªÙ
+ ØªØ¹ÙÙÙÙØ§ Ù
+Ù ÙØšÙ ÙÙ
+ÙÙ â Ù
+Ø«Ø§ÙØ Ø¹ÙØ¯Ù
+Ø§  ØªØ®ØªØ§Ø± ÙØ«ÙÙØ© Ù
+Ù Ù
+Ø¬Ù
+ÙØ¹Ø© Ù
+ÙØ¬ÙØ¯Ø© ÙÙ ÙØ±ÙÙØ³ØªÙÙ00 ÙØªÙ
+ Ø§Ø³ØªÙØ±Ø§Ø¯ÙØ§ ØªÙÙØ§ØŠÙØ§Ù Ø¹ÙØ¯ Ø§Ø¶Ø§ÙØ© Ø§ÙÙ
+ÙÙ ÙØ¹Ù
+Ù ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡Ø ÙØ¬Øš ØªØ®Ø·ÙØ·ÙØ§  ÙÙÙØ§Ù ÙÙ
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+ÙØ¬ÙØ¯Ø© ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0</Text>
+<Text id="107">ÙÙÙÙ
+ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ØšØ­Ø«Ù ÙØªÙÙÙØ± Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª Ø§ÙÙ
+Ø·ÙÙØšØ©Ø ÙØ¹Ø·ÙÙ Ø§ÙØ­Ø« ØªØ¹ÙÙÙ
+Ø§Øª Ù
+ÙØ¬Ø²Ø©Ø Ø«Ù
+ ÙØžÙØ± ÙÙ Ø§Ø³Ù
+ Ø¹ÙØµØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø³ØªÙØ±Ø¯ ÙÙ
+Ø§ ÙÙ ÙÙ Ø§ÙÙ
+ÙÙ Ø§ÙÙ
+ØµØ¯Ø±0 ÙÙØ°Ø§ Ø§ÙØ­ÙÙ ÙØ§ ÙÙ
+ÙÙ ØªØ­Ø¯ÙØ«Ù Ø£Ù ØªØºÙØ±Ù0  ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØ°Ù ØªÙØ¯ ØªØ®Ø·ÙØ· Ø§ÙØ¹ÙØµØ± Ø§ÙØ¬Ø¯ÙØ¯ ØšÙØ ÙÙÙÙ
+ Ø§ÙÙØžØ§Ù
+  ØªÙÙØ§ØŠÙØ§Ù ØšØ§Ø®ØªÙØ§Ø± Ø§ÙØ§ÙØ±Øš ÙÙÙ
+Ø¹ÙØ§Ø± ÙØ§ÙØ¹ÙØµØ± ÙÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØ¬Ø¯ÙØ¯Ø©0</Text>
+<Text id="108">ØšØ¹Ø¯ ÙØ­Øµ Ø§ÙØªØ®Ø·ÙØ·Ø ÙÙÙ
+ÙÙÙ Ø§Ø®ØªÙØ§Ø± "Ø§Ø¶Ø§ÙØ©" ÙØ§Ø¶Ø§ÙØ© Ø¹ÙØµØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙ
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø± (ÙØ°Ø§ Ø§ÙØ£Ù
+Ø± Ù
+ØªØ§Ø­ ÙÙØ· Ø¹ÙØ¯Ù
+Ø§ ÙØ§ ÙÙÙÙ ÙÙØ§Ù Ø¹ÙØµØ± ØšÙÙØ³ Ø§ÙØ§Ø³Ù
+ ÙÙ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±) "Ø¯Ù
+Ø¬" ÙØªÙØ­ ÙÙ Ø¯Ù
+Ø¬ Ø§ÙØ¹ÙØµØ± Ø§ÙØ¬Ø¯ÙØ¯ Ù
+Ø¹ ÙØ§Ø­Ø¯ Ù
+Ø®ØªØ§Ø± Ù
+Ù ÙØšÙ Ø§ÙÙ
+Ø³ØªÙÙØ¯0 Ø§Ø®ÙØ±Ø§Ù "ØªØ¬Ø§ÙÙ" ÙØ§ ØªØªÙØ­ ÙÙ Ø§Ø³ØªÙØ±Ø§Ø¯ Ø¹ÙØµØ± Ù
+Ù ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ù
+Ø¹ ÙØ°Ø§ Ø§ÙØ¹ÙØµØ±0 Ø¹ÙØ¯ ØªØ­Ø¯ÙØ¯ ÙÙÙÙØ© Ø§Ø³ØªÙØ±Ø§Ø¯ Ø¹ÙØµØ± ÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ù
+Ø¹ ÙØ°Ø§ Ø§ÙØ¹ÙØµØ±Ø Ø¹ÙØ¯ ØªØ­Ø¯ÙØ¯ ÙÙÙÙØ© Ø§Ø³ØªÙØ±Ø§Ø¯ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ØªÙÙÙ ÙØ¯ ÙØ±Ø±Øª ØŽÙÙ Ù
+Ø¹ÙÙÙ
+Ø§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0</Text>
+<Text id="109">ÙÙÙØ± ÙÙ Ø§ÙÙØµÙ Ø§ÙØ«Ø§ÙÙ Ù
+Ù Ø¯ÙÙÙ ÙØ±ÙÙØ³ØªÙÙ ÙÙÙ
+Ø·ÙØ±ÙÙ ÙÙÙ ØšØ¹ÙÙØ§Ù Ø§ÙØ¬Ø§Ø¯ ØºØ§ÙØš Ù
+Ø­ØªÙÙØ§Øª Ø§ÙÙØ«ÙÙØ© Ù
+Ø¹ÙÙÙ
+Ø§Øª Ø¹Ù Ù
+ÙÙØ§Øª Metadatz.xml0</Text>
+</Section>
+</Section>
+<Section name="designingacollection">
+<Title>
+<Text id="110">ØªÙÙÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©</Text>
+</Title>
+<Text id="111">Ø¹ÙØ¯ ØªÙ
+ÙÙØ² Ø§ÙÙ
+ÙÙØ§Øª ØšÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§ØªØ ÙØ¬Øš Ø£Ù ØªÙØ±Ø± ÙÙÙÙØ© ØªÙ
+ØžÙØ± Ù
+Ø¬Ù
+ÙØ¹Ø© ÙØ±ÙÙØ³ØªÙÙ ÙÙÙ
+Ø³ØªÙÙØ¯ÙÙØ Ù
+Ø§ÙÙ Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª Ø§ÙÙ
+ØªØ§Ø­Ø© ÙÙØšØ­Ø«Ø Ù
+Ø§ÙÙ  Ø·Ø±Ù ØªØµÙØ­ Ø§ÙÙØ«Ø§ØŠÙØ Ù
+Ø§ÙÙ Ø§ÙÙØºØ§Øª Ø§ÙÙ
+Ø¯Ø¹ÙÙ
+Ø©Ø Ø§ÙÙ ØªØ¶Ø¹ Ø§Ø²Ø±Ø§Ø± Ø§ÙØµÙØ­Ø©Ø ÙÙ ÙØ°Ù Ø§ÙØ§ØŽÙØ§Ø¡ ÙÙ
+ÙÙ ØªØŽÙÙÙÙØ§0 ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ÙØµÙ ÙÙ ÙÙÙ ØªÙØ¹Ù ÙØ°Ø§0</Text>
+<Section name="thedesignview">
+<Title>
+<Text id="112">Ù
+ØŽÙØ¯ Ø§ÙØªØµÙ
+ÙÙ
+</Text>
+</Title>
+<Text id="113"> ÙØ¹Ø±ÙÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ØšÙ
+ØŽÙØ¯ Ø§ÙØªØµÙ
+ÙÙ
+ ÙÙØŽØ±Ø­ ÙÙ ÙÙÙÙØ© Ø§ÙØªØ¬ÙØ§Ù ØšÙÙ Ù
+Ø®ØªÙÙ Ø§ÙÙ
+ØŽØ§ÙØ¯ Ø¶Ù
+Ù ÙØ°Ù Ø§ÙÙØ§ØŠÙ
+Ø©0</Text>
+<Text id="114">ØšÙØ§Ø³Ø·Ø© ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙØ ÙÙ
+ÙÙÙ  ØªÙÙÙÙ  ÙÙÙÙØ© Ù
+Ø¹Ø§ÙØ¬Ø© Ø§ÙÙØ«Ø§ØŠÙ ÙÙÙÙÙØ© Ø§ØªØ§Ø­Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙÙ
+Ø³ØªÙÙØ¯ Ø Ø®ÙØ§Ø±Ø§Øª Ø§ÙØªÙÙÙÙ Ù
+ÙØ³Ù
+Ø© Ø¥ÙÙ Ø£ÙØ³Ø§Ù
+ Ù
+Ø®ØªÙÙØ©  ÙÙ Ù
+ÙÙØ§ ÙØªØ¹ÙÙ ØšÙ
+Ø±Ø­ÙØ© Ù
+Ø¹ÙÙØ© Ù
+Ù ØªÙØ¶ÙØš Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0</Text>
+<Text id="115"> ÙØ³Ø§Ø±Ø§Ù ØªÙØ¬Ø¯ ÙØ§ØŠÙ
+Ø© ØšÙ
+Ø®ØªÙÙ Ø§ÙÙ
+ØŽØ§ÙØ¯0 ØªÙØ¬Ø¯ ÙÙ
+ÙÙØ§Ù Ø¶ÙØ§ØšØ· Ø§ÙØªØ­ÙÙ
+ Ø§ÙÙ
+ØªØ¹ÙÙØ© ØšØ§ÙÙ
+ØŽÙØ¯ Ø§ÙØ¬Ø§Ø±Ù0 ÙØªØºÙÙØ± ÙØ§Ø­Ø¯  Ø§ÙÙØ± Ø¹ÙÙ Ø§Ø³Ù
+ ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø©0</Text>
+<Text id="116">ÙÙÙÙ
+ Ù
+ØµØ·ÙØ­Ø§Øª ÙÙ
+Ø±Ø§Ø­Ù ØªØµÙ
+ÙÙ
+ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 Ø§ÙØ±Ø£ Ø§ÙÙØµÙÙÙ Ø§ÙØ£ÙÙ ÙØ§ÙØ«Ø§ÙÙ Ù
+Ù Ø¯ÙÙÙ ÙØ±ÙÙØ³ØªÙÙ ÙÙÙ
+Ø·ÙØ±ÙÙ0</Text>
+</Section>
+<Section name="plugins">
+<Title>
+<Text id="121">Ù
+ÙØ§ØšØ³ Ø§ÙÙØ«ÙÙØ©</Text>
+</Title>
+<Text id="122">ÙØµÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ÙÙÙÙØ© Ø¥Ø¹Ø¯Ø§Ø¯ Ù
+ÙØ§ØšØ³ Ø§ÙÙØ«ÙÙØ© Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+Ø© ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 ÙØŽØ±Ø­ ÙÙ ÙÙÙ ØªØ­Ø¯Ø¯ Ø§ÙÙ
+ÙØ§ØšØ³ ÙÙØ§Ø³ØªØ®Ø¯Ø§Ù
+Ø ÙÙ
+Ø§ÙÙ Ø§ÙÙ
+Ø€ØŽØ±Ø§Øª Ø§ÙØªÙ ØªÙ
+Ø±Ø± ÙÙØ§ ÙÙ
+Ø§ ÙÙ Ø§ÙØªØ±ØªÙØš Ø§ÙØ°Ù ØªØªØ®Ø°ÙØ ØªØ­Øª tab "ØªØµÙ
+ÙÙ
+"Ø Ø§ÙÙØ± "Ù
+ÙØ§ØšØ³ ÙØ«ÙÙØ©"0</Text>
+<Text id="123">ÙØ§Ø¶Ø§ÙØ© Ù
+ÙØ§ØšØ³ Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù ØšØ§Ø³ØªØ®Ø¯Ø§Ù
+ Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© "Ø§Ø®ØªÙØ§Ø± Ù
+ÙØ§ØšØ³ ÙÙØ§Ø¶Ø§ÙØ©" Ø§ÙÙØ±ÙØšØ© Ù
+Ù Ø§ÙØ£Ø³ÙÙØ Ø«Ù
+ Ø§ÙØžØ± "Ø§Ø¶Ø§ÙØ© Ù
+ÙØ§ØšØ³" ØªØžÙØ± ÙÙ ÙØ§ÙØ°Ø© ØšØ¹ÙÙØ§Ù "Ù
+Ø¶Ø§Ù
+ÙÙ Ø§ÙØªØ¬ÙÙØ²" ÙÙÙ Ù
+ÙØµÙÙÙ ÙÙÙ
+Ø§ ØšØ¹Ø¯0 Ø¹ÙØ¯ ØªØ¬ÙÙØ² Ø§ÙÙ
+ÙØ§ØšØ³ Ø§ÙØ¬Ø¯ÙØ¯Ø ØªØªÙ
+ Ø§Ø¶Ø§ÙØªÙ ÙÙ Ù
+Ø€Ø®Ø±Ø© ÙØ§ØŠÙ
+Ø© "Ø§ÙÙ
+ÙØ§ØšØ³ Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø© Ø­Ø§ÙÙØ§Ù0 ØªØ¬Øš Ù
+ÙØ§Ø­ØžØ©Ø Ø§ÙÙ ØšØ§Ø³ØªØ«ÙØ§Ø¡ Ù
+ÙØ§ØšØ³ UnknownPluq ÙØ¬Øš Ø£Ù ÙØŽØºÙ Ø£Ù Ù
+ÙØ§ØšØ³ Ø§Ø®Ø± Ø­ÙØ²Ø§Ù ÙØ§Ø­Ø¯Ø§Ù ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø©0</Text>
+<Text id="123aa">ÙØ±Ø€ÙØ© ÙØµÙ ÙØµÙØ± ÙÙ
+ÙØ§ØšØ³Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© "Ø§Ø®ØªÙØ§Ø± Ù
+ÙØ§ØšØ³ ÙÙØ§Ø¶Ø§ÙØ©" Ø«Ù
+ Ø­ÙÙ ØšÙ
+Ø€ØŽØ± Ø§ÙÙØ£Ø±Ø© ÙÙÙÙ0 ÙØžÙØ± ÙÙ Ù
+Ø±ØšØ¹ ÙØµ ÙØ¹Ø±Ø¶ Ø§ÙÙØµÙ0
+124- ÙØ§Ø²Ø§Ø­Ø© Ù
+ÙØ§ØšØ³Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù  Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©Ø ÙØ§ÙÙØ± "Ø­Ø°Ù Ù
+ÙØ§ØšØ³"0</Text>
+<Text id="124">ÙØ§Ø²Ø§Ø­Ø© Ù
+ÙØ§ØšØ³Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù  Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©Ø ÙØ§ÙÙØ± "Ø­Ø°Ù Ù
+ÙØ§ØšØ³"0</Text>
+<Text id="125"> ÙØªÙ
+ ØªØ¬ÙÙØ² Ø§ÙÙ
+ÙØ§ØšØ³ ØšØªÙÙÙØ± Ø§ÙÙ
+Ø¶Ø§Ù
+ÙÙ0 ÙØ­Ø« Ù
+ÙØ§ØšØ³Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ù
+ÙØ§ØšØ³ Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©Ø ÙØ§ÙÙØ± "ØªØ¬ÙÙØ² Ù
+ÙØ§ØšØ³" (Ø§Ù ÙÙØ±Ø© Ù
+Ø²Ø¯ÙØ¬Ø© ÙÙÙ
+ÙØ§ØšØ³" ÙØžÙØ± Ù
+Ø±ØšØ¹ Ø­ÙØ§Ø± "ØªØ¬ÙÙØ² Ù
+Ø¶Ø§Ù
+ÙÙ" ÙØ¶ØšØ· ØªØ­Ø¯ÙØ¯ Ø§ÙÙ
+Ø¶Ø§Ù
+ÙÙ0</Text>
+<Text id="126"> ØªÙØ¬Ø¯ Ø£ÙÙØ§Ø¹ Ù
+Ø®ØªÙÙØ© ÙÙØ¶ØšØ·Ø ØšØ¹Ø¶ÙØ§ Ù
+Ø±ØšØ¹Ø§Øª ÙØ­Øµ ÙØ§ÙÙÙØ± Ø¹ÙÙÙØ§ ÙØ¶ÙÙ Ø§ÙØ®ÙØ§Ø± Ø§ÙÙ
+ÙØ§ØŠÙ
+ ÙÙÙ
+ÙØ§ØšØ³0 Ø§ÙØ§ÙÙØ¹ Ø§ÙØ§Ø®Ø±Ù Ø³ÙØ§Ø³Ù ÙØµØšÙ ØšÙ
+Ø±ØšØ¹Ø§Øª ÙØ­Øµ Ø£Ù Ø­ÙÙ ÙØµÙ0 ÙÙ
+ ØšØªØ£ØŽÙØ± Ø§ÙÙ
+Ø±ØšØ¹ ÙØªÙØŽÙØ· Ø§ÙÙ
+Ø¶Ù
+ÙÙ Ø«Ù
+ Ø£Ø·ØšØ¹ Ø§ÙÙØµ Ø§ÙÙ
+ÙØ§ØŠÙ
+ (ØªØ¹ØšÙØ± Ù
+ÙØªØžÙ
+Ø Ù
+Ø³Ø§Ø± Ù
+ÙÙ00) ÙÙ Ø§ÙÙ
+Ø±ØšØ¹0 ØªØŽÙ
+Ù ØšÙÙØ© Ø§ÙØ§ÙÙØ§Ø¹ Ø§ÙØ¶Ø§Ù ÙÙØ§ØŠÙ
+ Ù
+ÙØ³Ø¯ÙØ© ØªØªÙØ­ ÙÙ Ø§ÙØ§Ø®ØªÙØ§Ø±Ø ÙÙ
+Ø¹Ø±ÙØ© Ù
+Ø§ ÙÙ
+ÙÙ Ø§Ù ÙÙØ¹ÙÙ Ø§ÙÙ
+Ø¶Ù
+ÙÙØ Ø§Ø¬Ø¹Ù Ù
+Ø€ØŽØ± Ø§ÙÙØ£Ø±Ø© ÙÙÙ Ø§ÙØ§Ø³Ù
+ ÙØšØ±ÙØ© ÙØžÙØ± ÙÙ Ø§ÙÙØµÙ0</Text>
+<Text id="127">Ø¥Ø°Ø§ ØºÙØ±Øª Ø§ÙØªØ¬ÙÙØ²Ø Ø§ÙÙØ± "OK" ÙØªØ£ÙÙØ¯ Ø§ÙØªØºÙÙØ±Ø§Øª ÙØ§ØºÙÙ Ù
+Ø±ØšØ¹ Ø§ÙØ­ÙØ§Ø± . Ø§Ù "Ø¥ÙØºØ§Ø¡" ÙØ§ØºÙØ§Ù Ù
+Ø±ØšØ¹ Ø§ÙØ­ÙØ§Ø± ØšØ¯ÙÙ ØªØºÙÙØ± Ù
+Ø¶Ø§Ù
+ÙÙ Ø§ÙÙ
+ÙØ§ØšØ³0</Text>
+<Text id="128">ÙØªÙ
+ ØªÙÙÙØ° Ø§ÙÙ
+ÙØ§ØšØ³ ØšØ§ÙØªØ±ØªÙØšØ ÙÙÙÙÙ Ø§ÙØªØ±ØªÙØš Ø§Ø­ÙØ§ÙØ§Ù Ù
+ÙÙ
+0 ÙÙ
+ÙÙ ØªØ±ØªÙØš Ø§ÙÙ
+ÙØ§ØšØ³ ÙÙ Ø³ÙØ§Ù Ø§Ø®ØªØµØ§ØµÙ ÙØžÙ
+ Ù
+ÙØªØšØ§Øª ÙØ³ÙØ§Ù Ø®ØšÙØ± (see <Reference target="preferences"/>).    </Text>
+</Section>
+<Section name="searchindexes">
+<Title>
+<Text id="134">ÙØŽØ§ÙØ§Øª Ø§ÙØšØ­Ø«</Text>
+</Title>
+<Text id="si-1"> ØªØ­Ø¯Ø¯ Ø§ÙÙØŽØ§ÙØ§Øª Ù
+Ø§ÙÙ Ø£Ø¬Ø²Ø§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙØ§ØšÙØ© ÙÙØšØ­Ø«0 ÙØŽØ±Ø­  ÙÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ÙÙÙÙØ© Ø§Ø¶Ø§ÙØ© ÙØ­Ø°Ù ÙØªØ¹ÙÙÙ ÙØŽØ§Ù Ø§ÙØªØ±Ø§Ø¶Ù ØªØ­Øª <AutoText key="glidict::GUI.Design"/> tab, click <AutoText key="glidict::CDM.GUI.Indexes"/>.</Text>
+<Text id="si-2">ÙÙ Ø§ÙØ¬Ø²Ø¡ Ø§ÙØ£ÙÙ
+Ù  Ø§Ø¹ÙÙ ÙØ§ÙØªÙ<AutoText key="glidict::CDM.GUI.Indexes"/> ØªØ¹Ø±Ø¶ Ù
+Ø¹ÙÙÙ
+Ø§Øª Ø­ÙÙ Ø§ÙÙ
+ÙØŽÙ Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+ Ø­Ø§ÙÙØ§Ù ØšÙØ§Ø³Ø·Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 ÙÙ
+ÙÙ ØªØºÙÙØ± ÙØ°Ø§ ØšÙÙØ±<AutoText key="glidict::CDM.BuildTypeManager.Change"/>. ØªØžÙØ± ÙÙ ÙØ§ÙØ°Ø© ØªØªØ¶Ù
+Ù ÙØ§ØŠÙ
+Ø© Ù
+Ù Ø§ÙØ®ÙØ§Ø±Ø§Øª Lucene, MGPP, MG Ø§ÙØªØºÙÙØ± ÙÙØ§ ÙØ€Ø«Ø± ÙÙ ÙÙÙÙØ© ØšÙØ§Ø¡ Ø§ÙÙØŽØ§ÙØ§Øª ÙÙØžÙÙÙØ© Ø§ÙØšØ­Ø«0</Text>
+<Text id="si-2a">ØªØžÙØ± ÙÙ ÙØ§ØŠÙ
+Ø© <AutoText key="glidict::CDM.IndexManager.Indexes"/> Ø§ÙÙØŽØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø© ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0</Text>
+<Text id="si-3">ÙØ§Ø¶Ø§ÙØ© ÙØŽØ§ÙØ Ø§ÙÙØ±<AutoText key="glidict::CDM.IndexManager.New_Index"/>.... ØªØžÙØ± ÙÙ ÙØ§ØŠÙ
+Ø© ØšØ§ÙÙ
+ØµØ§Ø¯Ø± Ø§ÙØªÙ ØªØªØ¶Ù
+Ù ÙØµ  ÙÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø§Ù Ø§ÙÙ
+ØµØ§Ø¯Ø± Ø§ÙØªÙ ØªÙØ¯ ØªÙØŽÙÙÙØ§0  Ø²Ø±<AutoText key="glidict::CDM.IndexManager.Select_All"/> and <AutoText key="glidict::CDM.IndexManager.Select_None"/> ÙÙÙÙ
+Ø§Ù ØšØªØ£ØŽÙØ± Ø£Ù ÙÙØµ ØªØ§ØŽÙØ± ÙÙ Ø§ÙØ¹ÙØ§ØµØ± ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø©0 Ø¹ÙØ¯  ØªØ¹Ø±ÙÙ  Ø§ÙÙØŽØ§ÙØ§ØªØ Ø£ÙÙØ±<AutoText key="glidict::CDM.IndexManager.Add_Index"/>ÙØ§Ø¶Ø§ÙØªÙØ§ Ø¥ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0  ØªØµØšØ­ <AutoText key="glidict::CDM.IndexManager.Add_Index"/> ÙØŽØ·Ø© ÙÙØ· ÙÙ Ø­Ø§ÙØ©  Ø§Ù Ø§ÙØ¥Ø¹Ø¯Ø§Ø¯ ÙØµÙ ÙØŽØ§Ù Ø¬Ø¯ÙØ¯ ÙÙ
+ ÙØ¹ÙÙ Ù
+Ù ÙØšÙ ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© </Text>
+<Text id="s1-3a">ØšØ§ÙÙØ³ØšÙ ÙÙØŽØ§ÙØ§Øª  MG ØªØ­ØªØ§Ø¬ Ø£ÙØ¶Ø§Ù ÙØ§Ø®ØªÙØ§Ø± qranularity Ø§ÙÙØŽØ§Ù Ù
+Ø³ØªØ®Ø¯Ù
+Ø§Ù ÙØ§ØŠÙ
+Ø©<AutoText key="glidict::CDM.IndexManager.Level"/> . </Text>
+<Text id="si-4">ØšØ§ÙÙØ³ØšØ© ÙÙØŽØ§ÙØ§Øª MGPP, Lucene
+Ø§ÙÙ
+Ø³ØªÙÙØ§Øª  Ø§ÙÙ
+Ø­ØªÙ
+ÙØ©  ØªØ¹Ø±Ø¶ ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙØ±ØŠÙØ³ÙØ©<AutoText key="glidict::CDM.GUI.Indexes"/> ÙÙÙ
+ÙÙ Ø§Ø¶Ø§ÙØªÙØ§ ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØšØªØ£ØŽÙØ± Ù
+Ø±ØšØ¹Ø§Øª Ø§ÙÙØ­Øµ0</Text>
+<Text id="si-5">ÙÙØ¬Ø¯  ÙØŽØ§Ù Ø®Ø§Øµ Øš Lucene, MGPP ÙÙÙ ÙØŽØ§Ù allhelds" ÙØªÙØ­ Ø§ÙØšØ­Ø« ÙÙ Ø§ÙÙØŽØ§ÙØ§Øª ØšØ¯ÙÙ Ø§ÙØ­ÙØ¬Ù ÙØªØ­Ø¯ÙØ¯ ÙØŽØ§Ù Ù
+ÙÙØµÙ ÙØ­ØªÙÙ ÙÙ Ø§ÙÙ
+ØµØ§Ø¯Ø±0 ÙØ§Ø¶Ø§ÙØ© ÙØ°Ø§ Ø§ÙÙØŽØ§Ù Ø Ø£ÙØ­Øµ <AutoText key="glidict::CDM.IndexManager.Allfields_Index"/>  ÙÙÙ
+  ØšØªØ£ØŽÙØ±Ù  Ø§ÙÙ
+Ø±ØšØ¹ ÙØ§ÙÙØ±<AutoText key="glidict::CDM.IndexManager.Add_Index"/>.</Text>
+<Text id="si-6">ØšØ§ÙÙØ³ØšØ© ÙÙØŽØ§ÙØ§Øª MGPP,Luane Ø ÙØªÙÙØ± Ø²Ø±<AutoText key="glidict::CDM.IndexManager.Add_All"/> ÙÙ
+Ø®ØªØµØ± ÙØ§Ø¶Ø§ÙØ© ÙÙ ÙØ§ØµÙØ§Øª  Ø§ÙØšÙØ§ÙØ§Øª ÙØ§ÙÙØµ ÙÙØŽØ§ÙØ§Øª ÙØ±Ø¯ÙØ©</Text>
+<Text id="si-7">ÙØªØ¹Ø¯ÙÙ  ÙØŽØ§ÙØ  ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù ÙØ§ÙÙØ± <AutoText key="glidict::CDM.IndexManager.Edit_Index"/>.  ÙØªÙÙØ± Ù
+Ø±ØšØ¹ Ø­ÙØ§Ø± ÙØ±Ø¯Ù Ø¥ÙÙ <AutoText key="glidict::CDM.IndexManager.New_Index"/> one is shown. </Text>
+<Text id="si-8">ÙØ­Ø°Ù  ÙØŽØ§ÙØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù Ù
+Ù ÙØ§ØŠÙ
+Ø© Ø§ÙÙØŽØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ù<AutoText key="glidict::CDM.IndexManager.Remove_Index"/>.</Text>
+<Text id="si-9">ØªØ±ØªÙØš Ø§ÙÙØŽØ§ÙØ§Øª ÙÙ ÙØ§ØŠÙ
+Ø© Ø§ÙÙØŽØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø©Ø ÙÙ ÙÙØ³ Ø§ÙØªØ±ØªÙØš Ø§ÙÙ
+ØªØšØ¹ ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© ÙÙ ØµÙØ­Ø© Ø§ÙØšØ­Ø«0 Ø§Ø³ØªØ®Ø¯Ù
+<AutoText key="glidict::CDM.Move.Move_Up"/> and <AutoText key="glidict::CDM.Move.Move_Up"/> ÙØªØºÙÙØ± ÙØ°Ø§ Ø§ÙØªØ±ØªÙØš0</Text>
+<Text id="si-10"> Ø§ÙÙØŽØ§Ù Ø§ÙØ°Ù ØªÙ
+ Ø§Ø®ØªÙØ§Ø±Ù ÙØ§ÙØªØ±Ø§Ø¶Ù ÙÙ ØµÙØ­Ø© Ø§ÙØšØ­Ø« ÙØ³Ù
+Ù "Ø§ÙÙØŽØ§Ù  Ø§ÙØ§ÙØªØ±Ø§Ø¶Ù" ÙØªÙ
+  ØªÙ
+ÙØ² Ø§ÙÙØŽØ§Ù  Ø§ÙØ§ÙØªØ±Ø§Ø¶Ù Øš "(ÙØŽØ§Ù Ø§ÙØªØ±Ø§Ø¶Ù" ÙÙ ÙØ§ØŠÙ
+Ø© "Ø§ÙÙØŽØ§ÙØ§Øª  Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø©"0 Ø§Ø°Ø§ ÙÙ
+ ÙØªÙ
+  ØªØ¹ÙÙÙ ÙØŽØ§Ù Ø§ÙØªØ±Ø§Ø¶Ù ÙØ§Ù Ø§ÙÙØŽØ§Ù Ø§ÙØ£ÙÙ ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø© ÙØªÙ
+ Ø§Ø³ØªØ®Ø¯Ø§Ù
+Ù ÙÙØŽØ§Ù Ø§ÙØªØ±Ø§Ø¶Ù0</Text>
+<Text id="si-11">Ø§ÙØ§Ø³Ù
+Ø§Ø¡ Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+Ø© ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© ÙÙ
+ÙÙ Ø§Ø¹Ø¯Ø§Ø¯ÙØ§ ÙÙ <AutoText key="glidict::CDM.GUI.SearchMetadata"/> Ø¬Ø²Ø¡Ø§Ù Ù
+Ù ÙØ§ÙØªÙ <AutoText key="glidict::GUI.Format"/>  (see <Reference target="searchmetadatasettings"/>).</Text>
+</Section>
+<Section name="partitionindexes">
+<Title>
+<Text id="143">ÙØŽØ§ÙØ§Øª Ø§ÙÙØ·Ø§Ø¹</Text>
+</Title>
+<Text id="144">ÙØªÙ
+ ØšÙØ§Ø¡ Ø§ÙÙØŽØ§ÙØ§Øª Ø¹ÙÙ ÙØµ Ù
+Ø¹ÙÙ Ø£Ù ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª0 ÙÙ
+ÙÙ Ø¶ØšØ· Ù
+Ø³Ø§Ø­Ø© Ø§ÙØšØ­Ø« ÙØªÙØ³ÙÙ
+ Ø§ÙÙØŽØ§ÙØ§Øª Ø¥ÙÙ ÙØ·Ø§Ø¹Ø§ØªØ Ø£Ù
+Ø§ ØšØ§ÙÙØºØ© Ø£Ù Ù
+Ø±ØŽØ­ Ù
+Ø­Ø¯Ø¯ Ù
+Ù ÙØšÙ0 ÙØµÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ÙÙÙÙØ© Ø¥ÙØ¬Ø§Ø² ÙØ°Ø§0 ØªØ­Ø« "ØªØµÙ
+ÙÙ
+" Ø§ÙÙØ± "ÙØŽØ§ÙØ§Øª Ø§ÙÙØ·Ø§Ø¹"0</Text>
+<Text id="145">ÙÙØ¬Ø¯ ÙÙ Ù
+ØŽÙØ¯ "ÙØŽØ§ÙØ§Øª Ø§ÙÙØ·Ø§Ø¹" Ø«ÙØ§Ø« tabs "ØªØ¹Ø±ÙÙ Ù
+Ø±ØŽØ­Ø§Øª"Ø Ù"ØªØ¹ÙÙ ÙØ·Ø§Ø¹Ø§Øª" Ù "ØªØ¹ÙÙÙ ÙØºØ§Øª" ÙÙ
+Ø¹Ø±ÙØ© Ø§ÙÙ
+Ø²ÙØ¯ Ø¹Ù Ø§ÙÙØ·Ø§Ø¹Ø§Øª Ø§ÙØ±Ø£  Ø­ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙÙØ±Ø¹ÙÙ ÙØ§ÙÙØŽØ§ÙØ§Øª Ø§ÙÙØ±Ø¹ÙØ© ÙÙ Ø§ÙÙØµÙ 2 Ù
+Ù Ø¯ÙÙÙ ÙØ±ÙØ³ØªÙÙ ÙÙÙ
+Ø·ÙØ±ÙÙ0</Text>
+<Text id="146">ÙØªÙ
+ ØªÙØŽÙØ· ØŽØ§ØŽØ© ÙØŽØ§ÙØ§Øª Ø§ÙØ·Ø§Ø¹ ÙÙ Ø³ÙØ§Ù Ø§Ø®ØªØµØ§ØµÙ ÙØžÙ
+ Ù
+ÙØªØšØ§Øª ÙØ³ÙØ§Ù Ø®ØšÙØ± (see <Reference target="preferences"/>). ÙØ§Ø­Øž Ø§ÙÙ ØšØ§ÙÙØ³ØšÙ  ÙÙ
+Ø¬Ù
+ÙØ¹Ù  MG ÙØ§Ù Ø§ÙØ¹Ø¯Ø¯ Ø§ÙÙÙÙ Ø§ÙØ°Ù ÙØªÙ
+ ØªÙÙÙØ¯Ù  Ù
+Ù Ù
+Ø²ÙØ¬  ÙÙ Ø§ÙÙØŽØ§ÙØ§ØªØ  Ù
+Ø±ØŽØ­Ø§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙØ±Ø¹ÙØ© ÙØ§ÙÙØºØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±Ø©0 ÙØŽØ§ÙÙÙ ØšÙ
+Ø±ØŽØ­Ø§Øª  Ù
+Ø¬Ù
+ÙØ¹ØªÙÙ ÙØ±Ø¹ÙØªÙÙ   ØšÙØºØªÙÙ ÙÙØªØ¬ ÙØŽØ§Ù ØšØ«Ù
+Ø§ÙÙØ© ÙØ·Ø§Ø¹Ø§Øª0 ØšØ§ÙÙØ³ØšØ© Ù MGPP Ø ØªÙØŽØŠ ÙÙ Ø§ÙÙØŽØ§ÙØ§Øª ÙÙ ÙØŽØ§Ù ÙØ§Ø­Ø¯ ÙÙØ· ÙÙØ°Ø§ ÙØ¹ÙÙ ÙØŽØ§Ù  ØšØ§Ø±ØšØ¹Ù ÙØ·Ø§Ø¹Ø§Øª- ØšØ§ÙÙØ³ØšØ© ÙÙ Lucene ÙØªØ­Ø¯Ø¯ Ø¹Ø¯Ø¯  Ø§ÙÙØŽØ§ÙØ§Øª Ø§ÙÙ
+Ø§Ø¯ÙÙ ØšØ¹Ø¯Ø¯ Ø§ÙÙ
+Ø³ØªÙÙØ§Øª Ø§ÙÙ
+Ø¹ÙÙÙ ÙÙÙ
+Ø¬Ù
+ÙØ¹ÙØ ÙÙÙ ÙØŽØ§Ù ÙØ§Ø­Ø¯ ÙÙÙ Ù
+Ø³ØªÙÙ0  ÙÙÙØ§Ù ÙÙÙØ¶Ø¹ Ø£Ø¹ÙØ§ÙØ ÙØ§Ù Ù
+Ø³ØªÙÙ ÙØ§Ø­Ø¯ ÙÙØªØ¬ Ø£Ø±ØšØ¹Ø© ÙØŽØ§ÙØ§Øª Ù
+Ø§Ø¯ÙÙ ØšÙÙÙ
+Ø§ Ù
+Ø³ØªÙÙÙ Ø³ÙÙ ÙÙØªØ¬Ø§Ù Ø«Ù
+Ø§ÙÙØ©0</Text>
+<Section name="definefilters">
+<Title>
+<Text id="147">ØªØ¹Ø±ÙÙ Ù
+Ø±ØŽØ­Ø§Øª</Text>
+</Title>
+<Text id="148">ØªØ³Ù
+Ø­ ÙÙ Ø§ÙÙ
+Ø±ØŽØ­Ø§Øª ØšØªØ¬Ù
+ÙØ¹ ÙÙ Ø§ÙÙØ«Ø§ØŠÙ ÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø© ÙØ±Ø¹ÙØ© ÙÙ ÙØŽØ§Ù ÙØªØ¶Ù
+Ù ÙÙÙ
+Ø©  ÙØ§ØµÙÙ ØšÙØ§ÙØ§Øª ØªØ¶Ø§ÙÙ  ÙÙ
+Ø· Ù
+Ø¹Ø·Ù0</Text>
+<Text id="149">ÙØ§ÙØŽØ§Ø¡ Ù
+Ø±ØŽØ­Ø Ø§ÙÙØ± tab "ØªØ¹Ø±ÙÙ Ù
+Ø±ØŽØ­" ÙØ£Ø¯Ø®Ù Ø§Ø³Ù
+ Ø§ÙÙ
+Ø±ØŽØ­ Ø§ÙØ¬Ø¯ÙØ¯ ÙÙ Ø­ÙÙ "Ø§Ø³Ù
+ Ù
+Ø±ØŽØ­ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙØ±Ø¹ÙØ©" ØªÙ
+ Ø§Ø®ØªÙØ§Ø± ØµÙÙ ÙÙÙØ«ÙÙØ© ÙÙÙ
+Ø¶Ø§ÙØ§Ø© ÙÙÙ Ø§Ù
+Ø§ Ø£Ù ØªÙÙÙ ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø§ÙØ§Ø³Ù
+ Ù
+ÙÙ ÙÙ Ø³Ø€Ø§Ù0 Ø§Ø¯Ø®Ù Ø§ÙØªØ¹ØšÙØ± Ø§ÙÙ
+ÙØªØžÙ
+ ÙØ§Ø³ØªØ®Ø¯Ø§Ù
+Ù Ø®ÙØ§Ù Ø§ÙÙ
+Ø¶Ø§ÙØ§Ø© ÙÙ
+ÙÙÙ toggle ØšÙÙ "ØªØ¶Ù
+ÙÙ " ÙØ«Ø§ØŠÙ ØªØ¶Ø§ÙÙ Ø§ÙÙ
+Ø±ØŽØ­ Ø£Ù "Ø§Ø³ØªØšØ¹Ø§Ø¯" Ø§ÙÙØ«Ø§ØŠÙ0 ÙÙ
+ÙÙÙ ØªØ®ØµÙØµ Ø§Ù Ù
+Ù ØŽØ§Ø±Ø§Øª Ø§ÙØªÙ
+ÙØ² ÙÙØªØ¹ØšÙØ±Ø§Øª Ø§ÙÙ
+ÙØªØžÙ
+Ø© Ø§ÙÙ
+Ø¹ÙØ§Ø±ÙØ© ÙØšÙØ±Ù ÙØ§ Ø³ØªØ®Ø¯Ø§Ù
+ÙØ§ Ø¹ÙØ¯ Ø§ÙÙ
+Ø¶Ø§ÙØ§Ø© ("*" ÙÙ
+Ø¶Ø§ÙØ§Ø© Ø­Ø§ÙØ©  ØºÙØ± Ø­Ø³Ø§Ø³Ù) â Ø§Ø®ÙØ±Ø§Ù Ø§ÙÙØ± "Ø§Ø¶Ø§ÙØ© Ù
+Ø±ØŽØ­" ÙØ§Ø¶Ø§ÙØ© Ø§ÙÙ
+Ø±ØŽØ­ Ø¥ÙÙ ÙØ§ØŠÙ
+Ø© "Ù
+Ø±ØŽØ­Ø§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙØ±Ø¹ÙØ© Ø§ÙÙ
+Ø¹Ø±ÙØ©"</Text>
+<Text id="150">ÙØ­Ø°Ù Ù
+Ø±ØŽØ­Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©Ø ÙØ§ÙÙØ± "Ø­Ø°Ù Ù
+Ø±ØŽØ­"0</Text>
+<Text id="151"> ÙÙ  alter Ù
+Ø±ØŽØ­ Ø  ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±  Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©Ø  ÙÙÙ
+ ØšØªØ¹Ø¯ÙÙ Ø§Ù Ù
+Ù Ø§ÙÙÙÙ
+ÙÙ Ø§ÙÙ
+ØªÙÙØ±Ø© Ù
+Ù Ø¹ÙØ§ØµØ± Ø§ÙØªØ­ÙÙ
+ ÙØ§ÙÙØ±  "Ø§Ø³ØªØšØ¯Ø§Ù Ù
+Ø±ØŽØ­" ÙØªØµØšØ­ Ø§ÙØªØºÙÙØ±Ø§Øª  Ù
+ÙØ²Ù
+Ù0</Text>
+<Text id="151a">ÙØ§ ÙØµÙØ¹ ØªØ¹Ø±ÙÙ ÙÙ
+Ø±ØŽØ­Ø§Øª Ù
+Ø¬Ù
+ÙØ¹Ø§Øª ÙØ±Ø¹ÙÙ0 ÙØªÙ
+ ØªØ­Ø¯ÙØ¯ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙÙØ±Ø¹ÙÙ ÙÙ <AutoText key="glidict::CDM.SubcollectionManager.Subindex_Controls"/>, ØšÙØ§Ø¡Ø§Ù Ø¹ÙÙ Ø§ÙÙ
+Ø±ØŽØ­Ø§Øª Ø§ÙØªÙ ÙÙ
+Øª ØšØªØ¹Ø±ÙÙÙØ§0</Text>
+</Section>
+<Section name="assignpartitions">
+<Title>
+<Text id="152">ØªØ¹ÙÙÙ ÙØ·Ø§Ø¹Ø§Øª</Text>
+</Title>
+<Text id="153">Ø§Ø°Ø§ ÙÙ
+Øª  ØšØªØ¹Ø±ÙÙ Ù
+Ø±ØŽØ­Ø§Øª Ù
+Ø¬Ù
+ÙØ¹Ø© ÙØ±Ø¹ÙØ© ÙØ§Ø­Ø¯Ø© Ø£Ù Ø£ÙØ«Ø±Ø Ø§Ø³ØªØ®Ø¯Ù
+ tab "ØªØ¹ÙÙÙ ÙØ·Ø§Ø¹Ø§Øª" ÙØšÙØ§Ø¡ Ø§ÙÙØŽØ§ÙØ§Øª ÙÙØ§ Ø£Ù ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ù
+Ù Ø§ÙÙ
+Ø±ØŽØ­Ø§Øª)0 ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø§ÙÙ
+Ø±ØŽØ­ Ø£Ù Ø§ÙÙ
+Ø±ØŽØ­Ø§Øª Ø§ÙÙ
+Ø·ÙÙØšØ© Ù
+Ù ÙØ§ØŠÙ
+Ø© "Ù
+Ø±ØŽØ­Ø§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙØ±Ø¹ÙØ© Ø§ÙÙ
+Ø¹Ø±ÙØ©" ÙØ§ÙÙØ± "Ø§Ø¶Ø§ÙØ© ÙØ·Ø§Ø¹"Ø Ø³ÙÙ ÙÙØ¶Ù
+ Ø¥ÙÙ ÙØ·Ø§Ø¹ Ù
+Ø­Ø¯Ø¯ ÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø© ÙØ±Ø¹ÙØ© Ø§ÙÙØ«Ø§ØŠÙ Ø§ÙØªÙ ØªØ¶Ø§ÙÙ Ø§ÙÙ
+Ø±ØŽØ­ Ø§ÙÙ
+Ø¹ÙÙ ÙÙÙØ·Ø§Ø¹0</Text>
+<Text id="154a">To alter a partition, select it from the list, modify the filters, and click <AutoText key="glidict::CDM.SubcollectionIndexManager.Replace_Subindex"/>.</Text>
+<Text id="154">To remove a partition, select it from the list and click "Remove Partition".</Text>
+<Text id="154b">ØªØ±ØªÙØš Ø§ÙÙØ·Ø§Ø¹Ø§Øª Ø§ÙÙ
+Ø­Ø¯Ø¯ ÙÙ ÙØ§ØŠÙ
+Ø© Ø§ÙÙØ·Ø§Ø¹Ø§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø© ÙÙ ÙÙØ³ Ø§ÙØªØ±ØªÙØš Ø§ÙØ°Ù ØªØžÙØ± ØšÙ Ø§ÙÙØ·Ø§Ø¹Ø§Øª ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø©  Ø§ÙÙ
+ÙØ³Ø¯ÙØ© ÙÙ ØµÙØ­Ø© Ø§ÙØšØ­Ø«0 Ø§Ø³ØªØ®Ø¯Ù
+ Ø§ÙØ§Ø²Ø±Ø§Ø± <AutoText key="glidict::CDM.Move.Move_Up"/> and <AutoText key="glidict::CDM.Move.Move_Up"/> ÙØªØºÙÙØ± ÙØ°Ø§ Ø§ÙØªØ±ØªÙØš0</Text>
+<Text id="155">ÙØªØ¹ÙÙÙ Ø§ÙÙØ·Ø§Ø¹ Ø§ÙØªØ±Ø§Ø¶ÙØ§ÙØ ÙÙ
+ ØšØ¥Ø®ØªÙØ§Ø± ÙØ§Ø­Ø¯ Ø§ÙÙØ§ØŠÙ
+Ø©Ø ÙØ§ÙÙØ± "ØªØ¹ÙÙÙ Ø§ÙØªØ±Ø§Ø¶Ù"0<AutoText key="glidict::CDM.SubcollectionIndexManager.Set_Default_Subindex"/>.</Text>
+<Text id="155a">ÙÙ
+ÙÙ Ø¥Ø¹Ø¯Ø§Ø¯ Ø§Ø³Ù
+Ø§Ø¡ Ø§ÙÙØ·Ø§Ø¹Ø§Øª Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+Ø© ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© ÙÙ ØµÙØ­Ø© Ø§ÙØšØ­Ø« ÙÙ<AutoText key="glidict::CDM.GUI.SearchMetadata"/> ÙÙÙ Ø¬Ø²Ø¡ Ù
+Ù ÙØ§ÙØªÙ <AutoText key="glidict::GUI.Format"/> panel (see <Reference target="searchmetadatasettings"/>).</Text>
+</Section>
+<Section name="assignlanguages">
+<Title>
+<Text id="156">ØªØ¹ÙÙÙ ÙØºØ©</Text>
+</Title>
+<Text id="157"> ÙÙØµÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ÙÙÙÙØ©  ØªÙÙÙØ¯ ÙØŽØ§ÙØ§Øª Ø§ÙØšØ­Ø« ÙÙØºØ§Øª Ù
+Ø¹ÙÙÙ0 ÙÙ
+ÙÙ Ø§ÙØ¬Ø§Ø²  ÙØ°Ø§ ØšØªÙÙÙØ¯ ÙØ·Ø§Ø¹ Ù
+Ø³ØªØ®Ø¯Ù
+Ø§Ù tab "ØªØ¹ÙÙÙ ÙØºØ§Øª" ÙÙ Ù
+ØŽÙØ¯ "ÙØŽØ§ÙØ§Øª Ø§ÙÙØ·Ø§Ø¹"0</Text>
+<Text id="158">TÙØ§Ø¶Ø§ÙØ© ÙØ·Ø§Ø¹ ÙØºÙÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+ tab "ØªØ¹ÙÙÙ ÙØºØ§Øª" ÙØšÙØ§Ø¡ ÙØŽØ§Ù ÙÙØ§0ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± ÙØºØ© Ø£Ù Ø£ÙØ«Ø± Ù
+Ù ÙØ§ØŠÙ
+Ø© "ÙØºØ§Øª ÙÙØ§Ø¶Ø§ÙØ©" Ø Ø§ÙÙØ± "Ø§Ø¶Ø§ÙØ© ÙØ·Ø§Ø¹ "0</Text>
+<Text id="158a">ÙØªØºÙÙØ± ÙØ·Ø§Ø¹ Ù
+ÙØ¬ÙØ¯Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù Ù
+Ù ÙØ§ØŠÙ
+Ø© "ÙØ·Ø§Ø¹Ø§Øª Ø§ÙÙØºØ© Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø©" ÙØªØ¹Ø¯ÙÙ Ø§ÙÙØºØ© Ø§ÙÙ
+Ø®ØªØ§Ø±Ø© Ù
+Ù ÙØ§ØŠÙ
+Ø© "ÙØºØ§Øª ÙÙØ§Ø¶Ø§ÙØ©" ÙÙ Ø§ÙØ§Ø³ÙÙØ ÙØ§ÙÙØ± "Ø§Ø³ØªØšØ¯Ø§Ù ÙØ·Ø§Ø¹"0.</Text>
+<Text id="159">ÙØ­Ø°Ù ÙØºØ© Ø  ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±ÙØ§ Ù
+Ù ÙØ§ØŠÙ
+Ø©  "Ø§Ø®ØªÙØ§Ø± ÙØºØ©"Ø ÙØ§ÙÙØ± "Ø­Ø°Ù ÙØºØ©"0</Text>
+<Text id="159a">ØªØ±ØªÙØš ÙØ·Ø§Ø¹Ø§Øª Ø§ÙÙØºØ© Ø§ÙÙ
+Ø­Ø¯Ø¯ ÙÙ ÙØ§ØŠÙ
+Ø© "ÙØ·Ø§Ø¹Ø§Øª Ø§ÙÙØºØ© Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø©" ÙÙ ÙÙØ³ Ø§ÙØªØ±ØªÙØš Ø§ÙØ°Ù ÙØžÙØ± ÙÙ ØªØ§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© ÙÙ ØµÙØ­Ø© Ø§ÙØšØ­Ø«0 Ø§Ø³ØªØ®Ø¯Ù
+ Ø§ÙØ§Ø²Ø±Ø§Ø± <AutoText key="glidict::CDM.Move.Move_Up"/> and <AutoText key="glidict::CDM.Move.Move_Up"/>  ÙØªØºÙÙØ± ÙØ°Ø§ Ø§ÙØªØ±ØªÙØš0</Text>
+<Text id="160">ÙØªØ¹ÙÙÙ ÙØ·Ø§Ø¹ Ø§ÙÙØºØ© Ø§ÙØ§ÙØªØ±Ø§Ø¶ÙØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø© ÙØ§ÙÙØ± "ØªØ¹ÙÙÙ Ø§ÙØªØ±Ø§Ø¶Ù"</Text>
+<Text id="160a">ÙÙ
+ÙÙ Ø§Ø¹Ø¯Ø§Ø¯  Ø§Ø³Ù
+Ø§Ø¡ Ø§ÙÙØ·Ø§Ø¹Ø§Øª Ø§ÙÙØºÙÙØ©  Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© ÙÙ ØµÙØ­Ø© Ø§ÙØšØ­Ø« ÙÙ <AutoText key="glidict::CDM.GUI.SearchMetadata"/> ÙÙÙ Ø¬Ø²Ø¡ Ù
+Ù ÙØ§ÙØªÙ <AutoText key="glidict::GUI.Format"/> panel (see <Reference target="searchmetadatasettings"/>).</Text>
+</Section>
+</Section>
+<Section name="classifiers">
+<Title>
+<Text id="166">Ù
+ØµÙÙØ§Øª Ø§ÙØªØµÙØ­</Text>
+</Title>
+<Text id="167">ØŽØ±Ø­ ÙÙ ÙØ°Ø§ Ø§ÙÙØµÙ ÙÙÙÙØ© ØªØ¹ÙÙÙ "Ø§ÙÙ
+ØµÙÙØ§Øª" ÙÙÙ Ø§ÙØªÙ ØªØ³ØªØ®Ø¯Ù
+ ÙÙ ØªØµÙØ­ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 ØªØ­Øª tab "ØªØµÙ
+ÙÙ
+" Ø Ø§ÙÙØ± "Ù
+ØµÙÙØ§Øª Ø§ÙØªØµÙØ­"0</Text>
+<Text id="168">ÙØ§Ø¶Ø§ÙØ© Ù
+ØµÙÙØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù Ù
+Ø³ØªØ®Ø¯Ù
+Ø§Ù Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© "Ø§Ø®ØªÙØ§Ø± Ù
+ØµÙÙ ÙÙØ§Ø¶Ø§ÙØ©"  Ø§ÙØ§ÙØ±Øš Ø¥ÙÙ Ø§ÙØ£Ø³ÙÙ Ø«Ù
+ Ø§ÙÙØ± "Ø§Ø¶Ø§ÙØ© Ù
+ØµÙÙ" ØªØžÙØ± ÙÙ ÙØ§ÙØ°Ø© ØšØ¹ÙÙØ§Ù "ØªØ¬ÙÙØ² Ù
+Ø¶Ø§Ù
+ÙÙ" ØªØªÙ
+Ø§Ø«Ù ØªØ¹ÙÙÙ
+Ø§Øª ÙØ°Ù Ø§ÙÙØ§ÙØ°Ø© Ù
+Ø¹ ØªØ¹ÙÙÙ
+Ø§Øª Ø§ÙÙ
+ÙØ§ØšØ³ (see <Reference target="plugins"/>). ØªØªÙ
+ Ø§Ø¶Ø§ÙØ© Ø§ÙÙ
+ØµÙÙ Ø§ÙØ¬Ø¯ÙØ¯ ØšØ¹Ø¯ ØªØ¬ÙÙØ²Ù Ø£Ø³ÙÙ ÙØ§ØŠÙ
+Ø© â Ø§ÙÙ
+ØµÙÙØ§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø© Ø­Ø§ÙÙØ§Ù0</Text>
+<Text id="168a">ÙØ±Ø€ÙØ© ÙØµÙ ÙØµÙØ± ÙÙ
+ØµÙÙØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© "Ø§Ø®ØªÙØ§Ø± Ù
+ØµÙÙ ÙÙØ§Ø¶Ø§ÙØ©" Ø«Ù
+ Ø­ÙÙ ØšÙ
+Ø€ØŽØ± Ø§ÙÙØ£Ø±Ø© ÙÙÙÙ ÙØžÙØ± ÙÙ Ù
+Ø±ØšØ¹ Ø§ÙÙØµÙ0</Text>
+<Text id="168b">ÙÙÙ Ù
+ØµÙÙ Ù
+Ø¶Ø§Ù
+ÙÙ Ù
+ØªØ¹Ø¯Ø¯Ø© ÙÙ
+ÙÙ Ø§Ø¹Ø¯Ø§Ø¯ÙØ§ Ø ÙØªØªØ¶Ù
+Ù Ø§ÙÙ
+Ø¶Ø§Ù
+ÙÙ Ø§ÙÙ
+ÙÙ
+Ø© "ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª" Ø§ÙØªÙ ØªØ­Ø¯Ø¯ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØªÙ Ø¹ÙÙ Ø¶ÙØŠÙØ§ ØªØµÙÙ Ø§ÙÙØ«Ø§ØŠÙ Ù"Ø§Ø³Ù
+Ø§Ø¡ Ø§ÙØ§Ø²Ø±Ø§Ø±" ÙÙÙ Ø§ÙØ§Ø³Ù
+Ø§Ø¡ Ø§ÙØªÙ ØªØžÙØ± ÙÙ Ø¹Ù
+ÙØ¯ Ø§ÙØ§ØšØ­Ø§Ø±0</Text>
+<Text id="169">ÙØ­Ø°Ù Ù
+ØµÙÙØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©Ø ÙØ§ÙÙØ± "Ø­Ø°Ù Ù
+ØµÙÙ"0</Text>
+<Text id="170">ÙØªØºÙÙØ± Ù
+Ø¶Ø§Ù
+ÙÙ Ù
+ØµÙÙØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©Ø ÙØ§ÙÙØ± "ØªØ¬ÙÙØ² Ù
+ØµÙÙ" (Ø§Ù ÙÙØ±Ù Ù
+Ø²Ø¯ÙØ¬Ù Ø¹ÙÙØ§ÙÙ
+ØµÙÙ ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø©)0</Text>
+<Text id="171">ØªØ±ØªÙØš Ø§ÙÙ
+ØµÙÙØ§Øª ÙÙ Ø¹Ù
+ÙØ¯ ØªØ¬ÙØ§Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØªØ¹ÙØ³ ØªØ±ØªÙØšÙØ§ ÙÙØ§Ø ÙØªØºÙÙØ± ÙØ°Ø§ Ø§ÙØªØ±ØªÙØšØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø§ÙÙ
+ØµÙÙ Ø§ÙÙ
+Ø·ÙÙØš ØªØ­Ø±ÙÙÙ ÙØ§ÙÙØ± Ø²Ø± "Ø­Ø±Ù Ø¥ÙÙ Ø£Ø¹ÙÙ" Ø£Ù "Ø­Ø±Ù Ø¥ÙÙ Ø§Ø³ÙÙ"0</Text>
+<Text id="172">ÙÙ
+Ø²ÙØ¯ Ù
+Ù Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª Ø¹Ù Ø§ÙÙ
+ØµÙÙØ§Øª Ø§ÙØ±Ø£ Ø§ÙÙØµÙ 2 ÙÙ Ø¯ÙÙÙ ÙØ±ÙÙØ³ØªÙÙ Ù
+Ù
+Ø·ÙØ±ÙÙ â Ø§ÙØ¬Ø§Ø¯ ÙÙ Ù
+Ø§ ÙÙ Ù
+Ù
+ÙÙ Ø§Ø®Ø±Ø§Ø¬Ù Ù
+Ù Ø§ÙÙØ«Ø§ØŠÙ0</Text>
+</Section>
+</Section>
+<Section name="producingthecollection">
+<Title>
+<Text id="193">Ø¥ÙØªØ§Ø¬ Ù
+Ø¬Ù
+ÙØ¹Ø©</Text>
+</Title>
+<Text id="194">Ø¥Ø°Ø§ ØªÙ
+ ØªØ¬Ù
+ÙÙØ¹ Ø§ÙÙØ«Ø§ØŠÙ ÙÙÙ
+Ø¬Ù
+ÙØ¹ÙØ Ù
+ØŽØ±ÙØ­Ø© ØšÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+Ø¹ ØªØµÙ
+ÙÙ
+ ÙÙÙÙØ© ØªÙ
+ØžÙØ± Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 ÙÙ
+ÙÙÙ ÙØ°Ø§ Ù
+Ù Ø§ÙØªØ§Ø¬ Ù
+Ø¬Ù
+ÙØ¹Ø© ØšÙØ§Ø³Ø·Ø© ÙØ±ÙÙØ³ØªÙÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ÙØŽØ±Ø­ ÙÙÙÙØ© Ø§ÙØ¬Ø§Ø² ÙØ°Ø§ Ø§ÙØ£Ù
+Ø±0</Text>
+<Section name="thecreateview">
+<Title>
+<Text id="195">Ù
+ØŽÙØ¯ Ø¥ÙØŽØ§Ø¡</Text>
+</Title>
+<Text id="196">ÙØ³ØªØ®Ø¯Ù
+ Ù
+ØŽÙØ¯ Ø§ÙØŽØ§Ø¡ ÙÙ Ø§ÙØŽØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØšØªØŽØºÙÙ Ù
+ÙÙØ§Øª ÙØ±ÙÙØ³ØªÙÙ ÙØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙÙØ§Ù ÙÙÙ
+Ø¹ÙÙÙ
+Ø§Øª Ø§ÙØªÙ ÙÙ
+Øª ØšØªÙÙÙØ±ÙØ§0 Ø§Ø¯Ø®Ù Ù
+ØŽÙØ¯ Ø§ÙØ§ÙØŽØ§Ø¡ ØšØ§ÙÙÙØ± Ø¹ÙÙ tab "Ø§ÙØŽØ§Ø¡"0</Text>
+<Text id="196a">ÙØšØ¯Ø£ Ø§Ø¬Ø±Ø§Ø¡ ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØšØ§ÙÙÙØ± Ø¹ÙÙ "ØšÙØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø©"- ØªØ­Ø¯ÙØ¯ Ø§ÙÙØªØ±Ø© Ø§ÙØ²Ù
+ÙÙØ© ÙØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙØ¹ØªÙ
+Ø¯ Ø¹ÙÙ Ø­Ø¬Ù
+ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙØ¹Ø¯Ø¯ Ø§ÙÙØŽØ§ÙØ§Øª Ø§ÙÙ
+ØšÙÙÙ (ÙØ¯ ØªÙÙÙ Ø³Ø§Ø¹Ø§Øª ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙØ¶Ø®Ù
+Ø©) ÙØŽÙØ± ØªØ·ÙØ± Ø¹Ù
+ÙØ¯ ØªØ·ÙØ± Ø§Ø¬Ø±Ø§Ø¡ Ø§ÙØšÙØ§Ø¡ Ø¥ÙÙ Ù
+Ø¯Ù Ø§ÙØ¬Ø²Ø¡ Ø§ÙØ°Ù Ø§ÙØªÙÙ .ÙØ¥ÙØºØ§Ø¡ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ ÙÙ Ø§Ù Ù
+Ø±Ø­ÙØ©Ø Ø§ÙÙØ± "Ø§ÙØºØ§Ø¡ Ø§ÙØšÙØ§Ø¡"0</Text>
+<Text id="197">Ø§Ø°Ø§ ØªÙ
+ ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØšÙØ¬Ø§Ø­ Ø ÙØ§Ù ÙÙØ± "Ø¹Ø±Ø¶ Ù
+Ø¬Ù
+ÙØ¹Ø©" Ø³ÙÙ ÙØ·ÙÙ Ù
+ØªØµÙØ­ ÙØš ÙØ¹Ø±Ø¶ ØµÙØ­Ø© Ù
+ÙÙØ¹ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0</Text>
+</Section>
+<Section name="builderrors">
+<Title>
+<Text id="199a"> Ø§Ø®Ø·Ø§Ø¡ ÙÙ ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©</Text>
+</Title>
+<Text id="199b">Ø§Ø­ÙØ§ÙØ§Ù ÙØ§ ØªÙ
+Ø¶Ù Ø§ÙØ§Ù
+ÙØ± ØšØµÙØ±Ø© Ø³ÙØ³ÙØ© Ø®ÙØ§Ù ØšÙØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø©Ø ÙÙØ¯ ÙØ§ØªØªÙ
+ Ù
+Ø¹Ø§ÙØ¬Ø© ØšØ¹Ø¶ Ø§ÙÙ
+ÙÙØ§ØªØ ÙÙÙÙ ÙÙØªÙ
+Ù ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØšØµÙØ±Ø© Ø³ÙÙÙ
+Ø© ÙÙÙ
+ÙÙ Ø¹Ø±Ø¶ÙØ§ ÙÙÙÙ ØšØºÙØ§Øš ØšØ¹Ø¶ Ø§ÙÙØ«Ø§ØŠÙ 0 Ø£Ù Ø±ØšÙ
+Ø§ ÙØ§ ØªØšÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙÙØ§ ØšØµÙØ±Ø© Ø³ÙÙÙ
+Ø© ÙÙÙ ÙØ°Ù Ø§ÙØ­Ø§ÙØ© ØªØžÙØ± Ø±Ø³Ø§ÙØ© ÙØ­ÙØ§ÙØ§<AutoText key="glidict::CollectionManager.Cannot_Create_Collection"/> Ø¹ÙØ¯Ù
+Ø§ ÙØ­Ø¯Ø« ÙØ°Ø§Ø ÙÙÙÙ Ù
+Ù Ø§ÙÙ
+ÙÙØ¯ Ø§ÙØªØ­ÙÙ ÙÙ GLI Ø¥ÙÙ Ø³ÙØ§Ù "Ø®ØšÙØ±" (File->Preferences->Mode, see <Reference target="preferences"/>), ÙÙ
+ ØšØªØ­ÙÙÙ ÙÙÙ
+Ø© Ø®ÙØ§Ø± ÙØšÙØ§Ø¡ "Verbosity) Ø¥ÙÙ 5 ÙØ§Ø¹Ø¯ Ø§ÙØšÙØ§Ø¡ ÙØ±Ø€ÙØ© Ø§Ù Ø±Ø³Ø§ØŠÙ Ø®Ø·Ø£ ØªØžÙØ±0</Text>
+</Section>
+<Section name="expertbuilding">
+<Title>
+<Text id="198a">Ù
+ØŽÙØ¯ Ø§ÙØŽØ§Ø¡ ÙÙ Ø³ÙØ§Ù Ø®ØšÙØ±</Text>
+</Title>
+<Text id="198">ÙÙ Ø³ÙØ§Ù Ø®ØšÙØ±Ø ÙÙ
+ÙÙÙ  Ø§Ø³ØªØ®Ø¯Ø§Ù
+ "Ø§ÙÙ
+Ø¯ÙÙÙ" ÙÙ Ø§ÙØ¬Ø²Ø¡ Ø§ÙØ§ÙØ³Ø± ÙØ§Ø³ØªØ¹Ø±Ø§Ø¶ Ø§ÙÙ
+Ø­Ø§ÙÙØ§Øª Ø§ÙØ³Ø§ØšÙÙ ÙØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹ÙØ Ø§Ø°Ø§ ÙØ§ÙØª ÙØ§Ø¬Ø­Ù Ø§ÙÙØ§Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø§ÙÙ
+Ø¯ÙÙÙ ØšØ§ÙØªØ§Ø±ÙØ® ÙÙ ÙØ§ØŠÙ
+Ø© "Ø§ÙÙ
+Ø¯ÙÙÙ"0</Text>
+<Text id="200a">ÙÙ ÙØ°Ø§ Ø§ÙØ³ÙØ§ÙØ ØªØžÙØ± Ø§ÙØ®ÙØ§Ø±Ø§Øª Ø§ÙÙØ§Ù
+ÙØ© ÙÙØ§Ø³ØªÙØ±Ø§Ø¯ ÙØ§ÙØšÙØ§Ø¡ ÙÙ tab ØšÙØ§Ø¡ ÙØ§Ø³ØªÙØ±Ø§Ø¯ Ø¥ÙÙ Ø§ÙØ³ÙØ§Ø±0 ØªØªÙ
+Ø§Ø«Ù Ø§Ø¹Ø¯Ø§Ø¯Ø§Øª Ø§ÙØªØ­ÙÙ
+ Ø§ÙÙ
+Ø®ØªÙÙØ© ØªÙÙ Ø§ÙØªÙ ÙÙ ÙØ§ÙØ°Ø© "ØªØ¬ÙÙØ² Ù
+Ø¶Ø§Ù
+ÙÙ" Ø§ÙÙ
+ÙØµÙÙÙ ÙÙ ÙØ³Ù
+ <Reference target="plugins"/>  ØšØ¹Ø¶ Ø§ÙØ­ÙÙÙ ØªØ­ØªØ§Ø¬ Ù
+Ø¶Ø§Ù
+ÙÙ Ø¹Ø¯Ø¯ÙÙ ÙÙÙ
+ÙÙÙ Ø·ØšØ§Ø¹ØªÙØ§ Ø£Ù Ø§Ø³ØªØ®Ø¯Ø§Ù
+ Ø§ÙØ§Ø³ÙÙ
+ ÙØ²ÙØ§Ø¯Ø© Ø£Ù ØªÙÙÙÙ Ø§ÙÙÙÙ
+Ø© Ø§ÙØ­Ø§ÙÙØ© ( ÙÙ ØšØ¹Ø¶ Ø§ÙØ­Ø§ÙØ§ØªØ ØªÙÙØ¯ Ø§ÙÙØ§Ø¬ÙØ© Ø§ÙÙ
+Ø¯Ù)0 ÙØªÙ
+ ØªÙØŽÙØ·  Ø§Ø¬Ø±Ø§Ø¡Ø§Øª Ø§ÙØ£Ø®Ø±Ù ØšÙÙØ± Ù
+Ø±ØšØ¹ Ø§ÙÙØ­Øµ (Ø§ÙØžØ± Ù
+Ø±Ø© Ø«Ø§ÙÙØ© ÙÙØ§Ø®Ù
+Ø§Ø¯)0</Text>
+<Text id="201a">ÙÙ
+Ø²ÙØ¯ Ù
+Ù Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª Ø­ÙÙ Ø§Ø³ØªÙØ±Ø§Ø¯ ÙØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©Ø Ø§ÙØ±Ø£ Ø§ÙÙØµÙ 1 Ù
+Ù Ø¯ÙÙÙ ÙØ±ÙÙØ³ØªÙÙ ÙÙÙ
+Ø·ÙØ±ÙÙ- ÙÙÙ
+ Ø§Ø¬Ø±Ø§Ø¡ ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0</Text>
+</Section>
+</Section>
+<Section name="formattingacollection">
+<Title>
+<Text id="fc-1">ØªÙØ¶ÙØš ØªÙ
+ØžÙØ± Ù
+Ø¬Ù
+ÙØ¹ØªÙ</Text>
+</Title>
+<Text id="fc-2">Ø¹ÙØ¯ Ø§ÙØ§ÙØªÙØ§Ø¡ Ù
+Ù ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©Ø ÙÙ
+ÙÙÙ ÙÙÙ
+Ø§ ØšØ¹Ø¯ ÙØµÙ ØªÙ
+ØžÙØ±ÙØ§ ÙÙÙ
+Ø³ØªÙÙØ¯0 Ù
+Ø§ÙÙ Ø§Ø³Ù
+Ø§Ø¡ Ø§ÙÙØŽØ§ÙØ§Øª Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+Ø© ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© ÙÙ
+Ø±ØšØ¹ Ø§ÙØšØ­Ø«Ø ÙÙÙ ØªØ¹Ø±Ø¶ ÙØªØ§ØŠØ¬ Ø§ÙØšØ­Ø«Ø Ù
+Ø§ÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØªÙ ØªØžÙØ± Ø¹ÙØ¯ Ø¹Ø±Ø¶ Ø§ÙÙØ«Ø§ØŠÙØ ÙÙ
+ÙÙ ØªÙØ¶ÙØš ÙÙ ÙØ°Ù Ø§ÙØ§ØŽÙØ§Ø¡0 ÙÙØ°Ø§ Ø§ÙÙØ³Ù
+ ÙØŽØ±Ø­ ÙÙ ÙÙÙÙØ© Ø¹Ù
+Ù ÙØ°Ø§0</Text>
+<Section name="theformatview">
+<Title>
+<Text id="fc-3">Ù
+ØŽÙØ¯ ÙØ³Ù Ø§ÙØ¹Ø±Ø¶0</Text>
+</Title>
+<Text id="fc-4">ÙØ¹Ø±ÙÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ØšÙ
+ØŽÙØ¯ ÙØ³Ù Ø§ÙØ¹Ø±Ø¶ ÙØŽØ±Ø­ ÙÙ ÙÙÙÙØ© Ø§ÙØªØ¬ÙØ§Ù ØšÙÙ Ø§ÙÙ
+ØŽØ§ÙØ¯ Ø§ÙØªÙ ÙØ­ØªÙÙÙØ§0</Text>
+<Text id="fc-5"> ÙÙÙØ± ÙÙ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ Ø¥Ø¹Ø¯Ø§Ø¯ ØªÙ
+ØžÙØ± Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙÙ
+Ø³ØªÙÙØ¯0 ØªÙÙØ³Ù
+ Ø®ÙØ§Ø±Ø§Øª Ø§ÙØ§Ø¹Ø¯Ø§Ø¯ Ø¥ÙÙ Ø£ÙØ³Ø§Ù
+ ÙÙ Ù
+ÙÙØ§ Ù
+ÙØ­Ù ØšÙ Ø§ÙÙØ§Ø¹ Ù
+Ø®ØªÙÙÙ Ù
+Ù Ø§ÙØªÙØµÙØš0</Text>
+<Text id="fc-6">ØªØ¬Ø¯ ÙØ³Ø§Ø±Ø§Ù ÙØ§ØŠÙ
+Ø© ØšØ§ÙÙ
+ØŽØ§ÙØ¯ ÙÙ
+Ù Ø¬ÙØ© Ø§ÙÙÙ
+ÙÙ Ø¹ÙØ§ØµØ± Ø§ÙØªØ­ÙÙ
+ Ø§ÙÙ
+ØªØ¹ÙÙØ© ØšØ§ÙÙ
+ØŽÙØ¯ Ø§ÙØ¬Ø§Ø±Ù0 ÙÙØªØºÙÙØ± Ø¥ÙÙ Ù
+ØŽÙØ¯ Ø¢Ø®Ø± Ø§ÙÙØ± Ø§Ø³Ù
+Ù Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©0</Text>
+<Text id="fc-7">ÙÙØ¬Ø¯ ØªØ­Øª ÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ØŽØ§ÙØ¯ Ø²Ø± "Ø¹Ø±Ø¶ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©" Ø§ÙØªØºÙÙØ± Ø§ÙØ°Ù ØªÙ
+ ÙÙ Ù
+ØŽÙØ¯ ÙØ³Ù Ø§ÙØ¹Ø±Ø¶ ÙÙ Ø§ÙÙ ÙÙ
+ ØªØ¹Ø¯  Ù
+Ø­ØªØ§Ø¬Ø§Ù ÙØ§Ø¹Ø§Ø¯Ø© ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙÙ
+ÙÙ Ø§ÙØ¹Ø±Ø¶ Ù
+ØšØ§ØŽØ±Ø©0 Ø¹ÙÙÙ ØšØ¯ Ù
+Ù ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ù
+Ø±Ø© ÙØ§Ø­Ø¯Ø© Ø¹ÙÙ Ø§ÙØ£ÙÙ0</Text>
+</Section>
+<Section name="generalsettings">
+<Title>
+<Text id="117">Ø¹Ø§Ù
+0</Text>
+</Title>
+<Text id="118">ÙØŽØ±Ø­ ÙÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+  ÙÙÙÙØ© Ø§Ø³ØªØ¹Ø±Ø§Ø¶ Ù alter Ø§ÙØªÙØ¶ÙØš Ø§ÙØ¹Ø§Ù
+ ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 Ø§ÙÙØ§Ù ØªØ­Øª tab "ÙØ³Ù Ø¹Ø±Ø¶" Ø§ÙÙØ± "Ø¹Ø§Ù
+"0</Text>
+<Text id="119">ÙÙÙØ§ ÙØªÙ
+ Ø¥Ø¹Ø¯Ø§Ø¯ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙØªÙØ³ÙØ±ÙØ§0 ÙÙÙ ØªØªØ¶Ù
+Ù Ø§ÙØ¹ÙÙØ§Ù ÙØ§ÙÙØµÙ ÙØ§ÙØªÙ ØªØ¯Ø®Ù ÙÙ ØšØ¯Ø§ÙØ© ÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø©0</Text>
+<Text id="120">Ø§ÙÙØ§ÙØ Ø¹ÙØ§ÙÙÙ Ø§ÙØšØ±ÙØ¯ Ø§ÙØ§ÙÙØªØ±ÙÙÙ ÙÙ
+ÙØŽØŠ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙ
+Ø§ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙØªØªÙØ­ ÙÙ Ø§ÙØ­ÙÙÙ Ø§ÙØªÙ ØªÙÙ Ø£Ø¹ÙØ§Ù ØªØºÙÙÙØ± Ø¹ÙÙØ§Ù  Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©Ø Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙØ°Ù ØªØ®Ø²Ù ÙÙÙ Ù
+ÙÙØ§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙØ°Ø§ ÙØ§ ÙÙ
+ÙÙ ØªØ¹Ø¯ÙÙÙ0 Ø§ÙØªØ§ÙÙØ Ù
+Ø®ØµØµ (ÙÙ ØŽÙÙ URL) ÙØ±Ù
+Ø² Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙØ¹Ø±Ø¶Ù ÙÙ Ø§ÙØ¬Ø§ÙØš Ø§ÙØ£Ø¹ÙÙ ÙØ³Ø§Ø±Ø§Ù ÙÙ ØµÙØ­Ø© "Ø­ÙÙ" â ÙÙÙÙ Ø±Ù
+Ø² Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+ ÙÙ Ø§ÙØµÙØ­Ø© Ø§ÙØ¹Ø§Ù
+Ø© ÙÙ
+ÙØªØšÙ ÙØ±ÙØ³ØªÙÙ ÙØ±Ø§ØšØ· ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 Ø«Ù
+ Ù
+Ø±ØšØ¹ ÙØ­Øµ ÙØªØ­Ø¯ÙØ¯ Ø¹Ù
+Ø§ Ø§Ø°Ø§ ÙØ§ÙØª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø¹Ø§Ù
+Ø©0 Ø§Ø®ÙØ±Ø§Ù Ù
+Ø±ØšØ¹ "ÙØµÙ Ù
+Ø¬Ù
+ÙØ¹Ø©" Ø§ÙÙØµÙ ÙÙØµÙÙØ§0<Reference target="creatingacollection"/>.</Text>
+</Section>
+<Section name="searchmetadatasettings">
+<Title>
+<Text id="fc-s1">ØšØ­Ø«</Text>
+</Title>
+<Text id="fc-s2">ÙØŽØ±Ø­ ÙÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ÙÙÙÙØ© Ø¹Ø±Ø¶ Ø§ÙÙØµ ÙÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© ÙÙ ØµÙØ­Ø© Ø§ÙØšØ­Ø« â ØªØ­Øª tab "ÙØ³Ù Ø¹Ø±Ø¶" Ø§ÙÙØ± "ØšØ­Ø«"0</Text>
+<Text id="fc-s3">ÙØªØ¶Ù
+Ù ÙØ°Ø§ Ø§ÙØ®ØšØ± Ø¬Ø¯ÙÙ ÙÙ ÙØŽØ§Ù ØšØ­Ø«Ø ÙÙ
+Ø³ØªÙÙ Ø§ÙØªÙØŽÙÙ (ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª MGPP Ø£Ù Lucene)  ÙÙØ§ ÙÙ
+ÙÙÙ Ø§Ø¯Ø®Ø§Ù Ø§ÙÙØµ Ø§ÙØ°Ù ÙØ³ØªØ®Ø¯Ù
+ ÙÙ
+ØµØ·ÙØ­ ØšØ­Ø« ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© ÙÙ ØµÙØ­Ø© Ø§ÙØšØ­Ø«- ÙØªÙØ­ ÙÙ ÙØ°Ø§ Ø§ÙØ­ÙØ² ØªØ­Ø¯ÙØ¯ Ø§ÙÙØµ ÙÙ ÙØºØ© ÙØ§Ø­Ø¯Ø© ÙØªØ±Ø¬Ù
+Ø© Ø§ÙÙØµ Ù
+Ù Ø§ÙÙØºØ© Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+Ø© Ø­Ø§ÙÙØ§Ù ÙÙ GLIØ¥ÙÙ Ø§ÙÙØºØ© Ø§ÙØ£Ø®Ø±Ù- Ø§Ø³ØªØ®Ø¯Ù
+ ØªØ±Ø¬Ù
+Ø© ÙØµ ÙÙÙ Ø¬Ø²Ø¡ Ù
+Ù Ù
+ØŽÙØ¯ ÙØ³Ù Ø¹Ø±Ø¶ (see <Reference target="translatetext"/>).</Text>
+</Section>
+<Section name="formatstatements">
+<Title>
+<Text id="173">ÙØ³Ù Ø¹Ø±Ø¶</Text>
+</Title>
+<Text id="174">ØµÙØ­Ø§Øª Ø§ÙÙØš Ø§ÙØªÙ ÙØ±Ø§ÙØ§ Ø¹ÙØ¯ Ø§Ø³ØªØ®Ø¯Ø§Ù
+ ÙØ±ÙÙØ³ØªÙÙ ÙÙØ³Øª Ø³Ø§ØšÙÙ Ø§ÙØªØ®Ø²ÙÙØ ÙÙÙÙ ÙØªÙ
+ ØªÙÙÙØ¯ÙØ§ "Ø¹ÙÙ Ø§ÙØ·Ø§ØŠØ±" Ø¹ÙØ¯ Ø§ÙØ§Ø­ØªÙØ§Ø¬ ÙÙØ§0 ØªØ³ØªØ®Ø¯Ù
+ Ø§ÙØ§Ù
+Ø± ÙØ³Ù Ø§ÙØ¹Ø±Ø¶ ÙØªØºÙÙØ± ØªÙ
+ØžÙØ± ÙØ°Ù Ø§ÙØµÙØ­Ø§Øª Ø§ÙÙ
+ÙÙØ¯Ø©Ø ÙØªØ€Ø«Ø± ÙÙ ØªÙ
+ØžÙØ± Ø§ÙØ§Ø²Ø±Ø§Ø± Ø¹ÙØ¯ Ø¹Ø±Ø¶ Ø§ÙÙØ«Ø§ØŠÙ Ø ÙØªØ­Ø¯ÙØ¯ Ø§ÙØ±ÙØ§ØšØ· Ø§ÙØªÙ ØªØ¹Ø±Ø¶ ØšÙØ§Ø³Ø·Ø© Ù
+ØµÙÙ "Datelist" â ÙÙØ³ Ù
+Ù Ø§ÙØ³ÙÙ ØªØ·ÙÙØ± Ø§ÙØ§Ù
+Ø± ÙØ³Ù Ø§ÙØ¹Ø±Ø¶Ø ÙØ°ÙÙ ØªØ¬Øš ÙØ±Ø§Ø¡Ø© Ø§ÙÙØµÙ 2  Ù
+Ù Ø¯ÙÙÙ ÙØ±ÙÙØ³ØªÙÙ ÙÙÙ
+Ø·ÙØ±ÙÙ0 ÙÙØ§ÙØŽ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ Ø¥Ø¹Ø¯Ø§Ø¯Ø§Øª ÙØ³Ù Ø§ÙØ¹Ø±Ø¶ ÙÙÙÙÙØ© Ø¥ØªØ§Ø­Ø© ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ÙÙØ§0 ØªØ­Øª tab "ÙØ³Ù Ø¹Ø±Ø¶" Ø Ø§ÙÙØ± "Ø³Ù
+Ø§Øª ÙØ³Ù Ø¹Ø±Ø¶"0</Text>
+<Text id="175">ÙÙ
+ÙÙÙ ØªØ·ØšÙÙ Ø£Ù
+Ø± ÙØ³Ù Ø¹Ø±Ø¶ ÙØ§Ù ØŽØŠ ÙÙ ÙØ§ØŠÙ
+Ø© "Ø§Ø®ØªÙØ§Ø± Ø³Ù
+Ø©" Ø§ÙÙ
+ÙØ³Ø¯ÙØ© ÙØ§ÙØªÙ ØªØªØ¶Ù
+Ù ÙÙ Ù
+ØµÙÙ ÙÙØ§ØŠÙ
+Ø© ØšØ³Ù
+Ø§Øª Ù
+Ø¹Ø±ÙØ© Ù
+Ù ÙØšÙ0 ÙÙØ¬Ø¯ ÙÙ
+Ø·ÙÙ ÙÙØªØ­ÙÙ
+ ÙØ¯Ù
+Ø§ ØªÙÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø³Ù
+Ø©0 ØšØ¹Ø¶ Ø§ÙØ³Ù
+Ø§Øª Ù
+Ø¹Ø±ÙØ© ÙÙ
+ÙÙ ØªÙØŽÙØ·ÙØ§ Ø§Ù Ø§Ø®Ù
+Ø§Ø¯ÙØ§ ØšØšØ³Ø§Ø·Ø© Ù
+Ù Ø®ÙØ§Ù Ø¶ØšØ· ØªØ­ÙÙ
+ÙØ§ ØšÙ
+Ø±ØšØ¹Ø§Øª Ø§ÙÙØ­ØµØ ØªØªØ·ÙØš Ø§ÙØ£Ø®Ø±Ù ØªØ­Ø¯ÙØ¯ Ø³ÙØ§Ø³Ù ÙØµØšÙ ÙÙØ³Ù Ø§ÙØ¹Ø±Ø¶0 ÙÙÙÙ ÙØ°Ø§ ØªÙØ¬Ø¯ ÙØ§ØŠÙ
+Ø© Ù
+ØªØ³Ø¯ÙØ© ÙÙÙ "Ø§ÙÙ
+ÙÙÙØ§Øª Ø§ÙÙ
+ØªÙØ§Ø¹ÙØ©" ÙØ§Ø®ØªÙØ§Ø± Ø§Ù Ø§ÙØ£Ø¬Ø²Ø§Ø¡ Ø§ÙØªÙ ØªØ·ØšÙ Ø¹ÙÙÙØ§ Ø³ÙØ§Ø³Ù ÙØ³Ù Ø¹Ø±Ø¶ (Ø§Ø°Ø§ ÙØ§Ù Ø¶Ø±ÙØ±ÙØ§Ù)0 ÙØ³ØªØ®Ø¯Ù
+ Ù
+Ø±ØšØ¹ Ø§ÙÙØµ "Ø³ÙØ§Ø³Ù ÙØ³Ù Ø¹Ø±Ø¶ HTML" ÙØ§Ø¯Ø®Ø§Ù Ø§ÙØ³ÙØ§Ø³Ù ÙØ§Ø®ØªÙØ§Ø± "Ø§ÙÙ
+ØªØºÙØ±Ø§Øª" Ø§ÙÙ
+Ø¹Ø±ÙØ© Ù
+Ù ÙØšÙ0 ÙØ­ØŽØ± Ù
+ØªØºÙØ± ÙÙ Ø§ÙÙ
+ÙÙØ¹ Ø§ÙØ­Ø§ÙÙ Ù
+Ù Ø³ÙØ§Ø³Ù ÙØ³Ù Ø§ÙØ¹Ø±Ø¶Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±ÙØ§ Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ©Ø ÙØ§ÙÙØ± "Ø­ØŽØ±"0<AutoText key="glidict::CDM.FormatManager.Insert_Variable"/> combobox.</Text>
+<Text id="176">ØªØ­Ø¯ÙØ¯ ÙØ³Ù Ø¹Ø±Ø¶ Ø§ÙØªØ±Ø§Ø¶Ù ÙÙ
+ÙÙÙ Ù
+Ø­Ø¯Ø¯ ØšØ§Ø®ØªÙØ§Ø± "ÙÙ Ø§ÙÙ
+ÙØ§Ù
+Ø­" Ø­ÙØ« ÙØªÙ
+ Ø§Ø¹ØªÙ
+Ø§Ø¯ ÙØ³Ù Ø§ÙØ¹Ø±Ø¶ ÙØ°Ø§ ÙÙÙ ØªØ·ØšÙÙØ§Øª Ù
+ÙØ§Ù
+Ø­ ÙØ³Ù Ø§ÙØ¹Ø±Ø¶ Ù
+Ø§ÙÙ
+ ÙØªÙ
+ ØªØ­Ø¯ÙØ¯ ØºÙØ±Ù0</Text>
+<Text id="177">ÙØ§Ø¶Ø§ÙØ© Ø£Ù
+Ø± ÙØ³Ù Ø¹Ø±Ø¶ Ø¬Ø¯ÙØ¯0 ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø³Ù
+Ø© Ù
+ÙÙÙØ§Øª ÙØ§ØšÙØ© ÙÙØªØ·ØšÙÙ0 ØªØ¹Ø±Ø¶ Ø§ÙÙÙÙ
+Ø© Ø§ÙØ§ÙØªØ±Ø§Ø¶ÙØ© ÙÙØ°Ø§ Ø§ÙØ£Ù
+Ø± ØšØ§ÙÙÙÙ Ø§ÙØ±Ù
+Ø§Ø¯Ù0 Ø§ÙÙØ± <AutoText key="glidict::CDM.FormatManager.Add"/>ÙØªÙÙÙØ°ÙØ§ ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 Ø§Ù
+Ø± ÙØ³Ù Ø¹Ø±Ø¶ ÙØ§Ø­Ø¯ ÙÙØ· ÙØ§Ù Ù
+ØŽØªØ±Ù Ø³Ù
+Ø©/ Ù
+ÙÙÙØ§Øª0</Text>
+<Text id="178">ÙØ­Ø°Ù Ø£Ù
+Ø± ÙØ³Ù Ø¹Ø±Ø¶Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©Ø ÙØ§ÙÙØ± "Ø­Ø°Ù Ø£Ù
+Ø± ÙØ³Ù Ø¹Ø±Ø¶"0</Text>
+<Text id="180"> ÙÙ
+Ø²ÙØ¯ Ù
+Ù Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª Ø­ÙÙ Ø§ÙÙ
+ØªØºÙØ±Ø§Øª ÙØ³Ù
+Ø§Øª Ø§ÙÙ
+ÙÙÙØ§Øª- Ø§ÙØ±Ø§ Ø§ÙÙØµÙ 2 Ù
+Ù Ø¯ÙÙÙ ÙØ±ÙÙØ³ØªÙÙ ÙÙÙ
+Ø·ÙØ±ÙÙ0</Text>
+</Section>
+<Section name="translatetext">
+<Title>
+<Text id="182">ØªØ±Ø¬Ù
+Ù ÙØµ</Text>
+</Title>
+<Text id="183">ÙØµÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ Ù
+ØŽÙØ¯ Ø§ÙØªØ±Ø¬Ù
+Ø©Ø Ø­ÙØ« ÙÙ
+ÙÙÙ ØªØ¬Ø²ØŠØ© ÙØµ Ù
+Ù ÙØºØ© Ù
+Ø®ØµØµØ© ÙØ§Ø¬Ø²Ø§Ø¡ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©Ø ØªØ­Øª tab "ÙØ³Ù Ø¹Ø±Ø¶" Ø§ÙÙØ± "ØªØ±Ø¬Ù
+Ø© ÙØµ"0</Text>
+<Text id="184">Ø§ÙÙØ§ÙØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ù
+Ø¯Ø®Ù Ù
+Ù ÙØ§ØŠÙ
+Ø© "Ø³Ù
+Ø§Øª"Ø ØªØžÙØ± Ø³ÙØ§Ø³Ù Ø§ÙÙØºØ© Ø§ÙÙ
+Ø®ØµØµØ© Ø§ÙÙ
+ØªØ¹ÙÙØ© ØšØ§ÙØ³Ù
+Ø© Ø§ÙØªÙ ØªØžÙØ± Ø§Ø¯ÙØ§Ù â Ø§Ø³ØªØ®Ø¯Ø§Ù
+ Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© "ÙØºØ© Ø§ÙØªØ±Ø¬Ù
+Ø©" ÙØ§Ø®ØªÙØ§Ø± Ø§ÙÙØºØ© Ø§ÙÙ
+Ø·ÙÙØšØ©- ÙØ§Ø·ØšØ¹ Ø§ÙÙØµ Ø§ÙÙ
+ØªØ±Ø¬Ù
+ Ù
+Ù Ù
+ÙØ·ÙØ© Ø§ÙÙØµ Ù
+Ø¹ Ø§ÙØ§Ø­Ø§ÙØ© Ø§ÙÙ "ØªØ¬Ø²ØŠØ© Ø§Ø°Ø§ ÙØ§Ù Ø¶Ø±ÙØ±ÙØ§ÙÙØµ Ù
+ØšØ¯ØŠÙØ©"0 Ø§Ø°Ø§ ÙØ§Ù Ø¶Ø±ÙØ±ÙØ§ÙØ Ø§ÙÙØ± "Ø§Ø¶Ø§ÙØ© ØªØ±Ø¬Ù
+Ø©"0</Text>
+<Text id="185"> ÙØ­Ø°Ù ØªØ±Ø¬Ù
+Ø© Ù
+ÙØ¬ÙØ¯Ø©Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±ÙØ§ Ù
+Ù Ø¬Ø¯ÙÙ "Ø§ÙØªØ±Ø¬Ù
+Ø§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø©" ÙØ§ÙÙØ± "Ø­Ø°Ù ØªØ±Ø¬Ù
+Ø©"0</Text>
+<Text id="186">ÙØªØ¹Ø¯ÙÙ ØªØ±Ø¬Ù
+Ø©Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±ÙØ§Ø ØªØ¹Ø¯ÙÙ Ù
+ÙØ·ÙØ© "Ø§ÙÙØµ Ø§ÙÙ
+ØªØ±Ø¬Ù
+" ÙØ§ÙÙØ± "Ø§Ø³ØªØšØ¯Ø§Ù ØªØ±Ø¬Ù
+Ø©"0</Text>
+</Section>
+<Section name="xcollectionsearching">
+<Title>
+<Text id="161">ØšØ­Ø« ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª</Text>
+</Title>
+<Text id="162">ÙØªÙØ­ ÙÙ ÙØ±ÙÙØ³ØªÙÙ ØšØ­Ø« Ù
+Ø®ØªÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª ÙØ£Ø£ÙÙØ§ Ù
+Ø¬Ù
+ÙØ¹Ø© ÙØ§Ø­Ø¯Ù .ÙÙ
+ÙÙ ÙØ¹Ù ÙØ°Ø§ ØšØªØ­Ø¯ÙØ¯ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙØ£Ø®Ø±Ù ÙÙØšØ­Ø« ÙØšØ¬Ø§ÙØš Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙØ­Ø§ÙÙÙ0 ØªØ­Øª "ÙØ³Ù Ø¹Ø±Ø¶" Ø Ø§ÙÙØ± "ØšØ­Ø« ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª"0</Text>
+<Text id="163">Ù
+ØŽÙØ¯ "ØšØ­Ø« ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª" ÙØžÙØ± ÙØ§ØŠÙ
+Ù
+Ø© ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙÙ
+ØªÙÙØ±Ø© ØšÙ
+Ø±ØšØ¹Ø§Øª ÙØ­Øµ0 ÙØªÙ
+ Ø§Ø¹ØªØšØ§Ø± Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙØ­Ø§ÙÙØ© Ù
+Ø®ØªØ§Ø±Ù ÙÙØ§ ÙÙ
+ÙÙ ÙÙØ¶ Ø§Ø®ØªÙØ§Ø±ÙØ§ 0 ÙØ§Ø¶Ø§ÙØ© Ù
+Ø¬Ù
+ÙØ¹Ø© Ø£Ø®Ø±Ù ÙÙØšØ­Ø« ØšØµÙØ±Ø© Ù
+ÙØ§Ø²ÙØ©Ø Ø§ÙÙØ± Ø¹ÙÙÙØ§ Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø© (Ø§ÙÙØ± Ø£Ø®Ø±Ù ÙØ­Ø°ÙÙØ§ )0 Ø§Ø°Ø§ ØªÙ
+ Ø§Ø®ØªÙØ§Ø± Ù
+Ø¬Ù
+ÙØ¹Ø© ÙØ§Ø­Ø¯Ø©   ÙÙÙÙ ÙÙØ§Ù ØšØ­Ø« Ø¹ØšØ± ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª0</Text>
+<Text id="164">Ø§Ø°Ø§ ÙÙ
+ ØªÙ
+ØªÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙÙØ±Ø¯ÙØ© ÙÙØ³ Ø§ÙÙØŽØ§ÙØ§Øª (Ù
+ØªØ¶Ù
+ÙÙ ÙØ·Ø§Ø¹Ø§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙØ±Ø¹ÙØ© ÙÙØ·Ø§Ø¹Ø§Øª Ø§ÙÙØºØ©) ØšØµÙØ±Ø© Ù
+ØªÙ
+Ø§Ø«ÙØ©Ø ÙØ§Ù Ø§ÙØšØ­Ø« Ø¹ØšØ± ÙØ°Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª ÙØ¹Ù
+Ù ØšØµÙØ±Ø© ØµØ­ÙØ­Ù0 ÙÙÙ ÙØªÙ
+ÙÙ Ø§ÙÙ
+Ø³ØªÙÙØ¯ Ø¥ÙØ§ Ù
+Ù ØšØ­Ø« Ø§ÙÙØŽØ§ÙØ§Øª ÙÙ ÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø©0</Text>
+<Text id="165">ÙÙ
+Ø²ÙØ¯ Ù
+Ù Ø§ÙØªÙØ§ØµÙÙØ Ø£ÙØžØ± Ø§ÙÙØµÙ Ø§ÙØ£ÙÙ Ù
+Ù Ø¯ÙÙÙ ÙØ±ÙÙØ³ØªÙÙ ÙÙÙ
+Ø·ÙØ±ÙÙ0</Text>
+</Section>
+<Section name="collectionspecificmacros">
+<Title>
+<Text id="fc-m1">Ù
+Ø§ÙØ±Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙ
+Ø®ØµØµ</Text>
+</Title>
+<Text id="fc-m2">ØªØ­Øª tab "ÙØ³Ù Ø¹Ø±Ø¶" Ø Ø§ÙÙØ± "Ù
+Ø§ÙØ±Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙ
+Ø®ØµØµ</Text> 
+<Text id="fc-m3">ÙØ¹Ø±Ø¶ ÙÙ ÙØ°Ø§ Ø§ÙÙ
+ØŽÙØ¯ Ù
+Ø­ØªÙÙØ§Øª Ù
+ÙÙ Ù
+Ø§ÙØ±Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Extra-dm ÙÙÙØ§ ÙØªÙ
+ ØªØ¹Ø±ÙÙ Ø§ÙÙ
+Ø§ÙØ±Ù Ø§ÙÙ
+Ø®ØµØµ ÙÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø©0 ÙÙ
+Ø¹Ø±ÙØ© Ø§ÙÙ
+Ø²ÙØ¯ Ø­ÙÙ Ø§ÙÙ
+Ø§ÙØ±Ù Ø§ÙØžØ± Ø§ÙÙØµÙ 3 Ù
+Ù Ø¯ÙÙÙ ÙØ±ÙÙØ³ØªÙÙ ÙÙÙ
+Ø·ÙØ±ÙÙ0.</Text>
+</Section>
+</Section>
+<Section name="miscellaneous">
+<Title>
+<Text id="202">Ù
+ØªÙÙØ¹Ø§Øª</Text>
+</Title>
+<Text id="203"> ÙØµÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ Ù
+ÙØ§Ù
+Ø­ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ØºÙØ± Ø§ÙÙ
+Ø±ØªØšØ·Ø© ØšØ§Ù Ù
+ØŽÙØ¯ Ù
+Ø¹ÙÙ0</Text>
+<Section name="preferences">
+<Title>
+<Text id="204">Ø§ÙØªÙØ¶ÙÙØ§Øª</Text>
+</Title>
+<Text id="205">ÙØŽØ±Ø­ ÙØ°Ø§  Ø§ÙÙØ³Ù
+ Ù
+Ø±ØšØ¹ Ø­ÙØ§Ø± Ø§ÙØªÙØ¶ÙÙØ§Øª ÙØ§ÙØ°Ù ÙØªØ§Ø­ ØšÙØªØ­ "Ù
+ÙÙ" 
+Ø§ÙØªÙØ¶ÙÙØ§Øª0</Text>
+<Text id="206">"ØªÙØªØ­ ÙØ§ÙØ°Ø© Ø§ÙØªÙØ¶ÙÙØ§Øª  ÙÙ  tab "Ø¹Ø§Ù
+"  Ø§ÙØ®ÙØ§Ø± Ø§ÙØ£ÙÙ ÙÙ Ø­ÙÙ ÙØµÙ ÙØ§Ø¯Ø®Ø§Ù Ø¹ÙÙØ§Ù  ØšØ±ÙØ¯Ù Ø§ÙØ§ÙÙØªØ±ÙÙÙ ÙØ³ÙÙ ÙØªÙ
+  Ø§Ø³ØªØ®Ø¯Ø§Ù
+Ù Ù "Ù
+ÙØŽØŠ" Ù"Ù
+Ø§ÙÙ" Ø¶Ù
+Ù Ø¹ÙØ§ØµØ±  ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø©  Ø§ÙØ¬Ø¯ÙØ¯Ø©0 Ø§ÙØ®ÙØ§Ø± Ø§ÙØ«Ø§ÙÙ  ÙÙ ÙØ§ØŠÙ
+Ø© Ù
+ÙØ³Ø¯ÙØ© ØšØ§ÙÙØºØ§Øª Ø§ÙØªÙ ØªØ³ØªØ·ÙØ¹ Ø¹Ø±Ø¶ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ØšÙØ§0 Ø§Ø°Ø§ ÙÙ
+Øª ØšØ§Ø®ØªÙØ§ Ø± ÙØºÙØ ÙÙØšØºÙ Ø§Ø¹Ø§Ø¯Ø© ØªØŽØºÙÙ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ÙØªØ­Ù
+ÙÙ Ø³ÙØ§Ø³Ù Ø§ÙÙØºØ© ÙÙ Ø§ÙÙØ§Ù
+ÙØ³0</Text>
+<Text id="207">Ø§Ø°Ø§ ØªÙ
+ ØªØ£ØŽÙØ± "Ø¹Ø±Ø¶ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø³ØªØ®ÙØµØ©" ÙØªÙ
+ Ø¹Ø±Ø¶ Ù
+Ø®ØªÙÙ Ø§ÙØ¶ÙØ§ØšØ· Ø§ÙØªÙ ØªØ¹Ø§Ù
+Ù ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø³ØªØ®ÙØµÙ Ø¢ÙÙØ§ Ù
+Ù Ø§ÙÙØ«Ø§ØŠÙ0 ØªÙØ¶  Ø§ÙØ§Ø®ØªÙØ§Ø±  ÙØ®ÙÙ ÙØ°Ù Ø§ÙÙØ§ØµÙØ§Øª (ØšØ§ÙØ±ØºÙ
+ Ù
+Ù Ø°ÙÙ  ØªØšÙ Ù
+ØªÙÙØ±Ù ÙÙ  ØªØµÙ
+ÙÙ
+ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0  ÙØ®ÙØ§Ù  Ù
+Ø¬Ù
+ÙØ¹Ø©  ÙØ±ÙÙØ³ØªÙÙ Ø§ÙÙÙØ§ØŠÙØ©)0 Ø§Ø°Ø§ ØªÙ
+ ØªØ£ØŽÙØ± "Ø¹Ø±Ø¶ Ø§Ø­Ø¬Ø§Ù
+ Ø§ÙÙ
+ÙÙ"  ÙØªÙ
+ Ø¹Ø±Ø¶ Ø§ÙØ­Ø¬Ù
+  ØšØ¹Ø¯ Ø§ÙÙ
+ÙÙ ÙÙ Ù
+Ø³Ø§Ø­Ø© Ø§ÙØ¹Ù
+Ù ÙØŽØ¬Ø±Ø©  Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙ Ù
+ØŽÙØ¯Ù  "ØªØ¬Ù
+ÙØ¹" Ù"Ø¥Ø«Ø±Ø§Ø¡"0</Text>
+<Text id="208">ÙØ³ØªØ®Ø¯Ù
+  tab "Ø³ÙØ§Ù" ÙØ¶ØšØ·  Ù
+Ø³ØªÙÙ Ø§ÙØªÙØµÙÙ ÙÙ Ø§ÙÙØ§Ø¬ÙØ©- ÙÙÙØ± "Ù
+Ø³Ø§Ø¹Ø¯ Ù
+ÙØªØšÙ" Ø£ÙÙ Ø§Ø¹Ø¯Ø§Ø¯ Ø­ÙØ« ÙØªÙ
+  Ø­Ø¬Øš Ù
+ØŽÙØ¯  Ø§ÙØªØµÙ
+ÙÙ
+ ÙØ§ÙÙ
+Ø¶Ø§Ù
+ÙÙ Ø§ÙØªÙ ØªØªØ·ÙØš Ø§ÙØªØºÙØ±Ø§Øª Ø§ÙÙ
+ÙØªØžÙ
+Ø©Ø ÙØªØªÙÙØ± Ù
+Ø¹ÙÙÙ
+Ø§Øª ÙÙÙÙØ© ÙÙ Ù
+Ø¯ÙÙÙ Ø§Ø­Ø¯Ø§Ø« ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0  ÙÙÙØ± Ø³ÙØ§Ù "Ø®ØšÙØ±" Ø§Ø¹ÙÙ Ø¥Ø¹Ø¯Ø§Ø¯ Ø­ÙØ« ÙØªØ§Ø­  Ø§ÙÙØµÙÙ ÙÙÙ Ù
+ÙØ§Ù
+Ø­ Ø§ÙØªØµÙ
+ÙÙ
+Ø Ù
+ØªØ¶Ù
+ÙÙ ØªÙ
+ÙØ¶Ø­ Ø§ÙÙ
+ÙØ§ØšØ³ ÙÙ
+Ø¶Ø§Ù
+ÙÙ Ø§ÙØªØ¹ØšÙØ±Ø§Øª Ø§ÙÙ
+ÙØªØžÙ
+Ø©Ø ÙØªØ³Ø¬ÙÙ Ø§ÙÙ
+Ø®Ø±Ø¬Ø§Øª Ø§ÙÙØ§Ù
+ÙØ© ÙØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙ Ø§ÙÙ
+Ø¯ÙÙÙ ÙØªØºÙÙØ± Ø£Ù Ø§Ø³ØªØ¹Ø±Ø§Ø¶ Ø§ÙØ³ÙØ§ÙØ§Øª Ø Ø§ÙÙØ± Ø²Ø± "Radio buttons" Ø§ÙØ«Ø§ÙÙ ÙÙØ³ÙØ§Ù Ø§ÙØ°Ù ØªÙØªÙ
+ ØšÙ0 ÙÙ
+ÙÙÙ Ù
+Ø¹Ø±ÙØ© Ø§ÙØ³ÙØ§Ù Ø§ÙØ°Ù Ø§ÙØª ÙÙÙ ØšØ§ÙÙØžØ± Ø¥ÙÙ Ø¹Ù
+ÙØ¯ Ø¹ÙÙØ§Ù ÙØ§Ø¬ÙÙ Ø§ÙÙ
+ÙØªØšÙ0</Text>
+<Text id="209">ÙØ³ØªØ·ÙØ¹ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ Ø¯Ø¹Ù
+ Ù
+Ø®ØªÙÙ ØªØ¯ÙÙØ§Øª Ø§ÙØ¹Ù
+Ù ÙØªØ¬Ø¯ÙØ¯  Ø§ÙÙ tab Ø§ÙÙ
+ØŽØ§ÙØ¯ ÙÙÙÙ Ù
+Ø±ØŠÙØ§Ù0  Ø¥Ø³ØªØ®Ø¯Ù
+ tab "ØªØ¯ÙÙ Ø§ÙØ¹Ù
+Ù" ÙØªØ£ØŽÙØ± Ø§ÙÙ
+Ø±ØšØ¹Ø§Øª Ø§ÙØªÙ ØªÙÙ Ø§ÙÙ
+ØŽØ§ÙØ¯ ÙØªÙØ¶ÙØš Ø§ÙÙ
+ØŽØ§ÙØ¯ Ø§ÙÙ
+ØªÙÙØ±Ø©0 Ø®ÙØ§Ø± Ø¢Ø®Ø± Ø§Ø³ØªØ®Ø¯Ù
+ Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© ÙÙØªØ­Ø¯ÙØ¯ Ø§ÙÙ
+Ø³ØšÙ ÙÙØªØ¬ÙÙØ²Ø§Øª0 ÙØªÙ
+ Ø§Ø¹ØªÙ
+Ø§Ø¯ Ø§Ø¹Ø¯Ø§Ø¯Ø§Øª ØªØ¯ÙÙ Ø§ÙØ¹Ù
+Ù Ø¹ÙØ¯ Ø§ØºÙØ§Ù Ù
+Ø±ØšØ¹ Ø­ÙØ§Ø± Ø§ÙØªÙØ¶ÙÙØ§ØªØ ÙÙØ°Ù  Ø§ÙØªÙØ¶ÙÙØ§Øª ÙÙØ· Ù
+Ø¹ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙÙØ³  ÙÙ ØªÙÙÙÙ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ0</Text>
+<Text id="210">ÙØªÙØ­ ÙÙ  tab "Ø§ÙØ§ØªØµØ§Ù" Ø­ÙØ« Ø§ÙÙ
+Ø³Ø§Ø± Ø¥ÙÙ Ù
+Ø²ÙØ¯ Ù
+ÙØªØšØ© ÙØ±ÙÙØ³ØªÙÙ Ø§ÙÙ
+Ø­ÙÙ Ø§ÙØ°Ù ÙØ³ØªØ®Ø¯Ù
+ Ø¹ÙØ¯ Ø¹Ø±Ø¶ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©Ø ÙÙ
+Ø§ ÙØªÙØ­  ÙÙ Ø¥Ø¹Ø¯Ø§Ø¯ Ù
+Ø¹ÙÙÙ
+Ø§Øª Ø§ÙØšØ±ÙÙØ³Ù ÙÙØ§ØªØµØ§Ù Ø¹ØšØ± Ø§ÙØ§ÙØªØ±ÙØª (Ù
+Ø«Ø§ÙØ ØªÙØ²ÙÙ Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª)<Reference target="downloadingfiles"/> ÙÙ
+Ø²ÙØ¯ Ù
+Ù Ø§ÙØªÙØ§ØµÙÙ). ÙÙÙ
+ ØšØªØ£ØŽÙØ± Ø§ÙÙ
+Ø±ØšØ¹ ÙØªÙØŽÙØ· Ø§ÙØšØ±ÙÙØ³Ù ÙØªÙÙÙØ± Ù
+Ø¹ÙÙÙ
+Ø§Øª Ø¹ÙÙØ§Ù Ù
+Ø¶ÙÙ Ø§ÙØšØ±ÙÙØ³Ù ÙØ±ÙÙ
+ Ø§ÙÙ
+ÙÙØ°0 ÙØªÙ
+ ØªØ¬ÙÙØ² Ø§ØªØµØ§Ù Ø§ÙØšØ±ÙÙØ³Ù Ø¹ÙØ¯Ù
+Ø§ ØªÙÙÙ
+  ØšØºÙÙ Ù
+Ø±ØšØ¹ Ø§ÙØªÙØ¶ÙÙØ§Øª0</Text>
+<Text id="211">Ø®ÙØ§Ù ÙØªØ±Ø© ØªØŽØºÙÙ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙØ Ø±ØšÙ
+Ø§ ØªØžÙØ± Ø±Ø³Ø§ØŠÙ ØªØ­Ø°ÙØ± ÙØ§Ø¹ÙØ§Ù
+Ù ØšØ¹ÙØ§ÙØš ØšØ¹Ø¶ Ø§ÙØ§Ø¬Ø±Ø§Ø¡Ø§Øª ØºÙØ± Ø§ÙÙ
+Ø±ØŠÙØ©0 ÙÙ
+ÙÙÙ Ø§Ø®Ù
+Ø§Ø¯ ÙØ°Ù Ø§ÙØ±Ø³Ø§ØŠÙ ÙØªØ£ØŽÙØ± Ù
+Ø±ØšØ¹ " ÙØ§ØªØ¹Ø±Ø¶ ÙØ°Ø§ Ø§ÙØªØ­Ø°ÙØ± Ù
+Ø±Ø© Ø«Ø§ÙÙØ©"0 ÙÙ
+ÙÙÙ ØªÙØŽÙØ· Ø±Ø³Ø§ØŠÙ  Ø§ÙØªØ­Ø°ÙØ± ØšØ§Ø³ØªØ®Ø¯Ø§Ù
+ tab  "ØªØ­Ø°ÙØ±Ø§Øª 0 ÙÙ
+ ØšØªØ£ØŽÙØ± Ø§ÙÙ
+Ø±ØšØ¹ Ø§ÙØªØ§ÙÙ ÙØ±Ø³Ø§ØŠÙ Ø§ÙØªØ­Ø°ÙØ± Ø§ÙØªÙ ØªØ±ØºØš ÙÙ Ø±Ø€ÙØªÙØ§ Ù
+Ø±Ø© Ø«Ø§ÙÙØ©0</Text>
+</Section>
+<Section name="fileassociations">
+<Title>
+<Text id="212">Ù
+ØªØ¹ÙÙØ§Øª Ø§ÙÙ
+ÙÙ</Text>
+</Title>
+<Text id="213">ÙØ³ØªØ®Ø¯Ù
+ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ØšØ±Ø§Ù
+Ø¬ ØªØ·ØšÙÙÙØ© Ù
+Ø¹ÙÙØ© ÙÙØªØ­ Ø§ÙÙ
+Ø§Ø· Ù
+ÙÙØ§Øª Ù
+Ø¹ÙÙØ©Ø ÙØ­Ø« Ù
+ØªØ¹ÙÙØ§Øª Ø§ÙÙ
+ÙÙØ  Ø§ÙØªØ­ ÙØ§ØŠÙ
+Ø© "Ù
+ÙÙ" Ø«Ù
+ Ø£ÙÙØ± "Ù
+ØªØ¹ÙÙØ§Øª Ø§ÙÙ
+ÙÙ00"</Text>
+<Text id="214">ÙØ§Ø¶Ø§ÙØ© Ù
+ØªØ¹ÙÙØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø§Ù
+ØªØ¯Ø§Ø¯ Ø§ÙÙ
+ÙÙ Ø§ÙÙ
+Ø·ÙÙØš ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© Ø Ø£Ù Ø£Ø·ØšØ¹ Ø§ÙØ§Ù
+ØªØ¯Ø§Ø¯ Ø§ÙØ¬Ø¯ÙØ¯ (ÙØ§ØªØ¶Ù
+Ù "0") â Ø«Ù
+ Ø¥Ù
+Ø§ Ø£Ù  ØšØ·ØšØ§Ø¹Ø© Ø§ÙØ£Ù
+Ø± ÙØ§Ø·ÙØ§Ù Ø§ÙØšØ±ÙØ§Ù
+Ø¬ Ø§ÙÙ
+Ø·ÙÙØš ÙÙ Ø§ÙØ­ÙÙ Ø§ÙÙ
+ÙØ§Ø³Øš Ø  Ø£Ù Ø§Ø®ØªÙØ§Ø± Ø§ÙØªØ·ØšÙÙ Ù
+Ù Ù
+Ø±ØšØ¹ Ø­ÙØ§Ø± "ØªØµÙØ­"0 ÙÙ
+ÙÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+ "1%" ÙØ§Ø·ÙØ§Ù Ø§ÙØ£Ù
+Ø± ÙØ­ØŽØ± Ø§Ø³Ù
+ Ø§ÙÙ
+ÙÙ Ø§ÙÙ
+Ø·ÙÙØš ÙØªØ­Ù0  Ø¹ÙØ¯Ù
+Ø§ ÙØªÙ
+ ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡Ø ÙØªÙ
+ ØªÙØŽÙØ· "Ø§Ø¶Ø§ÙØ©" ÙØšØ§ÙÙÙØ± Ø¹ÙÙÙØ§ ØªØªÙ
+ Ø§Ø¶Ø§ÙØ© Ø§ÙÙ
+ØªØ¹ÙÙ0</Text>
+<Text id="215"> ØªØ¹Ø¯ÙÙ Ø§ÙÙ
+ØªØ¹ÙÙØ§ØªØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø§Ù
+ØªØ¯Ø§Ø¯ Ù
+ÙÙ Ù
+ÙØ¬ÙØ¯ ÙØªØ¹Ø¯ÙÙ Ø§Ù Ø§Ù
+ØªØ¯Ø§Ø¯ Ù
+ØªØ¹ÙÙ ÙÙ Ø­ÙÙ Ø§Ø·ÙØ§Ù Ø§ÙØ£Ù
+Ø± Ø«Ù
+ Ø§ÙÙØ±  "Ø§Ø³ØªØšØ¯Ø§Ù"</Text>
+<Text id="216">ÙØ­Ø°Ù Ù
+ØªØ¹ÙÙØ§ØªØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø§Ù
+ØªØ¯Ø§Ø¯ Ù
+ÙÙ Ù
+ÙØ¬ÙØ¯ ÙØ£ÙÙØ± "Ø­Ø°Ù" (ÙØšÙÙ Ø§Ù
+ØªØ¯Ø§Ø¯  Ø§ÙÙ
+ÙÙ ÙÙ ÙØ§ØŠÙ
+Ø© (ÙÙÙØ§ÙØ©  Ø§ÙÙ
+ÙÙ) Ø§ÙÙ
+ÙØ³Ø¯ÙØ©</Text>
+<Text id="217">ÙØªÙ
+ Ø­ÙØž Ù
+ØªØ¹ÙÙØ§Øª Ø§ÙÙ
+ÙÙ ÙÙ Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙØ±ØŠÙØ³Ù ÙÙØ§Ø¬ÙÙÙØ© Ø§ÙÙ
+ÙØªØšÙ ÙÙ Ù
+ÙÙ "associations.xml".</Text>
+</Section>
+<Section name="exporting">
+<Title>
+<Text id="exp-1">ØªØµØ¯ÙØ± Ø§ÙÙ
+Ù
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙÙ ÙÙØŠØ§Øª Ø£Ø®Ø±Ù</Text>
+</Title>
+<Text id="exp-2">ÙØªÙØ­ ÙØ±ÙÙØ³ØªÙÙ ØªØµØ¯ÙØ± Ù
+Ø­ØªÙÙØ§Øª / Ø£Ù ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙØŠØ§Øª Ù
+Ø¹ÙØ§Ø±ÙØ© Ø¹Ø¯ÙØ¯Ù ÙØªØªØ¶Ù
+Ù METSÙ DSPACE Ù MABCXML</Text>
+<Text id="exp-3">ÙØªØµØ¯ÙØ± Ù
+Ø¬Ù
+ÙØ¹Ø© Ø£Ù Ø§ÙØ«Ø± Ø Ø§ÙØªØ­ "Ù
+ÙÙ" ÙÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± "ØªØµØ¯ÙØ±" ÙÙ
+ÙÙÙ Ø§Ø®ØªÙØ§Ø± Ø§Ù Ø§ÙÙÙØŠØ§Øª  Ø§ÙØªÙ ØªÙØ¯ Ø§ÙØªØµØ¯ÙØ± Ø¥ÙÙÙØ§ ØšØ§Ø®ØªÙØ§Ø±ÙØ§ ÙÙ (Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© "ØªØµØ¯ÙØ± Ø¥ÙÙ00 "0 ÙÙ
+ ØšØªØ­Ø¯ÙØ¯ Ø§Ø³Ù
+ Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙØ°Ù ØªÙØ¯ Ù
+ÙÙØ§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙ
+ØµØ¯Ø±Ø© ÙÙÙ&mdash;ØªÙØªÙÙ ÙØ°Ù Ø§ÙÙ
+ÙÙØ§Øª&lt;path to greenstone&gt;/tmp/exported_xxx, Ø­ÙØ« ÃÃÃ ÙÙ Ø§ÙØ§Ø³Ù
+ Ø§ÙØ°Ù Ø­Ø¯Ø¯ØªÙ0 ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± ÙØ§Ø­Ø¯Ø© Ø£Ù Ø£ÙØ«Ø± Ù
+Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙÙ
+ØªÙÙØ±Ø© ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø© Ø«Ù
+ Ø§ÙÙØ± "ØªØµØ¯ÙØ± Ù
+Ø¬Ù
+ÙØ¹Ø© (Ø§Øª)"0</Text>
+<Text id="exp-4"> ØªÙØ¬Ø¯ Ø®ÙØ§Ø±Ø§Øª  Ø£Ø®Ø±Ù Ù
+Ø®ØµØµØ© ÙÙÙÙØŠØ§Øª Ø§ÙÙ
+Ø®ØªÙÙØ©0 ÙÙ
+ÙÙÙ ØªØ­Ø¯ÙØ¯ Ù
+ÙÙØ§Øª XSLT Ø§ÙØªÙ ØªØ·ØšÙ Ø§ÙÙØ§ØªØ¬ Ù
+Ù ÙØ«Ø§ØŠÙ XML ØšÙØ§ ÙØªÙØ¶ÙØš ÙÙØŠØ© ÙØ³Ù Ø§ÙÙ
+Ø®Ø±Ø¬Ø§Øª â Ø§ÙØªØµØ¯ÙØ± Ø¥ÙÙ MARCXML ÙØ³ØªØ®Ø¯Ù
+ Ù
+ÙÙ ØªØ®Ø·ÙØ· ÙØªØ®Ø·ÙØ· ÙØ§ØµÙØ§Øª  ØšÙØ§ÙØ§Øª ÙØ±ÙÙØ³ØªÙÙ  Ø¥ÙÙ Ø­ÙÙÙ MARC. Ø§ÙÙ
+ÙÙ Ø§ÙØªØ®Ø·ÙØ·Ù Ø§ÙØ§ÙØªØ±Ø§Ø¶Ù  ÙÙÙÙ
+ ØšØªØ®Ø·ÙØ· Ù
+Ø¹ÙØ§Ø± Ø¯ØšÙÙ ÙÙØ± ÙÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙ
+ÙÙÙ  ØªØ®Ø·ÙØ· Ù
+ÙÙ ÙÙÙ ÙØªÙ
+ Ø§Ø³ØªØ®Ø¯Ø§Ù
+Ù ØšØ¯ÙØ§Ù Ù
+Ù Ø§ÙÙ
+ÙÙ Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+ Ø­Ø§ÙÙØ§Ù0</Text>
+</Section>
+<Section name="exportingcollections">
+<Title>
+<Text id="218">ØªØµØ¯ÙØ± Ù
+Ø¬Ù
+ÙØ¹Ø§Øª  Ø¥ÙÙ  CD/DVD</Text>
+</Title>
+<Text id="219">ÙÙ
+ÙÙ ÙÙØ±ÙÙØ³ØªÙÙ ØªØµØ¯ÙØ± Ù
+Ø¬Ù
+ÙØ¹Ø© Ø£Ù Ù
+Ø¬Ù
+ÙØ¹Ø§Øª Ø¥ÙÙ ÙØ±Øµ CD/DVD Ø°Ø§ØªÙ Ø§ÙØªØ«ØšÙØª ØªØ­Øª ØšØ±Ø§Ù
+Ø¬ Ø§ÙØªØŽØºÙÙ Windows </Text>
+<Text id="220">ÙØªØµØ¯ÙØ± Ù
+Ø¬Ù
+ÙØ¹Ø©Ø Ø§ÙØªØ­ ÙØ§ØŠÙ
+Ø© "Ù
+ÙÙ" ÙÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± "ØªØµØ¯ÙØ± ÙØ±Øµ CD/DVD ØªØžÙØ± ÙÙ ÙØ§ØŠÙ
+ Ù
+Ø¬Ù
+ÙØ¹Ø§Øª ÙØ±ÙÙØ³ØªÙÙ â Ø§ÙÙØ± Ø¹ÙÙ Ø£Ù ÙØ§Ø­Ø¯Ø© ÙÙ
+Ø¹Ø±ÙØ© ÙØµÙÙØ§ ÙÙ
+ ØšØªØ£ØŽÙØ± Ù
+Ø±ØšØ¹ Ø§ÙÙØ­Øµ  ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙØªÙ ØªÙØ¯ ØªØµØ¯ÙØ±ÙØ§- ÙÙ
+ÙÙÙ  Ø§Ø¯Ø®Ø§Ù Ø§Ø³Ù
+  CD/DVD Ù
+Ù Ù
+Ø±ØšØ¹ "Ø§Ø³Ù
+  CD/DVD"0 ÙØžÙØ± ÙØ°Ø§ Ø§ÙØ§Ø³Ù
+ ÙÙ ÙØ§ØŠÙ
+Ø© Ø§ØšØ¯Ø§ Ø¹ÙØ¯Ù
+Ø§ ÙØªÙ
+ ØªØ«ØšÙØª Ø§ÙÙØ±Øµ CD/DVD- ÙÙ
+ÙÙÙ Ø§Ø®ØªÙØ§Ø±  ØªØŽØºÙÙ Ø§ÙÙØ±Øµ DVD Ø£Ù CD-ROM Ø§ÙÙØ§ØªØ¬ Ù
+ØšØ§ØŽØ±Ø© Ù
+Ù Ø§ÙÙØ±Øµ Ø§ÙÙ
+Ø¹ÙÙØ Ø£Ù ØªØ«ØšÙØª ØšØ¹Ø¶ Ø§ÙÙ
+ÙÙØ§Øª ÙÙ Ø§ÙØ­Ø§Ø³ÙØš0 Ø«Ù
+ Ø§ÙÙØ± "ØªØµØ¯ÙØ± ÙØ±Øµ CD/DVD0  ÙØªØ¶Ù
+Ù ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡  ÙØ³Ø® Ù
+ÙÙØ§Øª Ø¹Ø¯ÙØ¯Ù ÙÙØ¯ ÙØ³ØªØºØ±Ù Ø¯ÙØ§ØŠÙ ÙÙÙÙØ©0</Text>
+<Text id="221"> Ø¹ÙØ¯ Ø§ÙØ§ÙØªÙØ§Ø¡ Ø ÙØžÙØ± ÙÙ ÙØ±ÙÙØ³ØªÙÙ Ø§Ø³Ù
+ Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙØ°Ù ÙØ¶Ù
+ Ø§ÙØ¬Ù
+ÙØ¹Ø§Øª Ø§ÙÙ
+ØµØ¯Ø±Ù0 Ø§Ø³ØªØ®Ø¯Ù
+ Ø³ÙØ§ÙÙ CD/DVD ÙÙØ³Ø® Ø§ÙÙ
+Ø­ØªÙÙØ§Øª Ø§ÙÙ ÙØ±Øµ CD/DVD ÙØ§Ø±Øº0</Text>
+</Section>
+</Section>
+</Document>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/help_index.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/help_index.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/help_index.xml	(revision 13928)
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Document><Section name="introduction"><Title>Ø§ÙØªØ¹Ø±ÙÙ</Title><Section name="ofmiceandmenus"><Title>Ø§ÙÙØ£Ø±Ø© Ù Ø§ÙÙÙØ§ØŠÙ
+</Title></Section><Section name="howtoavoidthisdocument"><Title>ÙÙÙ ØªØªØ¬ÙØš ÙØ±Ø§Ø¡Ø© ÙØ°Ù Ø§ÙÙØ«ÙÙØ©</Title></Section></Section><Section name="startingoff"><Title>Ø§ÙØšØ¯Ø§ÙØ©</Title><Section name="creatingacollection"><Title>Ø¥ÙØŽØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø© Ø¬Ø¯ÙØ¯Ø©</Title></Section><Section name="savingacollection"><Title>Ø­ÙØž Ù
+Ø¬Ù
+ÙØ¹Ø©</Title></Section><Section name="openingacollection"><Title>ÙØªØ­ Ù
+Ø¬Ù
+ÙØ¹Ø© Ù
+ÙØ¬ÙØ¯Ø©</Title></Section><Section name="deletingcollections"><Title>Ø¥ÙØºØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª</Title></Section></Section><Section name="downloadingfiles"><Title>ØªÙØ²ÙÙ Ø§ÙÙ
+ÙÙØ§Øª Ù
+Ù Ø§ÙØ¥ÙØªØ±ÙØª</Title><Section name="themirrorview"><Title>Ù
+ØŽÙØ¯ Ø§ÙØªÙØ²ÙÙ</Title></Section></Section><Section name="collectingfiles"><Title>ØªØ¬Ù
+ÙÙØ¹ Ø§ÙÙ
+ÙÙØ§Øª ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø©</Title><Section name="thegatherview"><Title>Ù
+ØŽÙØ¯ Ø§ÙØªØ¬Ù
+ÙÙØ¹</Title></Section><Section name="creatingshortcuts"><Title> Ø§ÙØŽØ§Ø¡ Ù
+Ø®ØªØµØ± Ù
+Ù ØŽØ¬Ø±Ø© Ù
+Ø³Ø§Ø­Ø© Ø§ÙØ¹Ù
+Ù0</Title></Section><Section name="creatingfolders"><Title>Ø¥ÙØŽØ§Ø¡ Ù
+Ø¬ÙØ¯Ø§Øª</Title></Section><Section name="addingfiles"><Title>Ø¥Ø¶Ø§ÙØ© Ù
+ÙÙØ§Øª</Title></Section><Section name="replacingfiles"><Title>Ø§Ø¹Ø§Ø¯Ø© ØªØ³Ù
+ÙØ© ÙØ§Ø³ØªØšØ¯Ø§Ù Ø§ÙÙ
+ÙÙØ§Øª0</Title></Section><Section name="removingfiles"><Title>Ø­Ø°Ù Ù
+ÙÙØ§Øª</Title></Section><Section name="explodingfiles"><Title> ØªØ¬Ø²ØŠØ©  Ù
+ÙÙØ§Øª ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª0</Title></Section><Section name="filteringthetree"><Title>ØªØ±ØŽÙØ­ Ø§ÙØŽØ¬Ø±Ø©</Title></Section></Section><Section name="enrichingacollection"><Title>Ø¥Ø«Ø±Ø§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø© ØšÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª</Title><Section name="theenrichview"><Title>Ù
+ØŽÙØ¯ Ø¥Ø«Ø±Ø§Ø¡</Title></Section><Section name="selectingmetadatasets"><Title>Ø¥Ø®ØªÙØ§Ø± Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª</Title></Section><Section name="appendingmetadata"><Title>ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø¬Ø¯ÙØ¯Ø© Ù
+Ø¹ÙÙØ©</Title></Section><Section name="addingpreviouslydefinedmetadata"><Title>Ø¥Ø¶Ø§ÙØ© ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¹Ø±ÙØ© Ø³Ø§ØšÙØ§</Title></Section><Section name="updatingmetadata"><Title>ØªØ¹Ø¯ÙÙ Ø§Ù Ø­Ø°Ù ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª</Title></Section><Section name="reviewingmetadata"><Title>
+Ø¥Ø³ØªØ¹Ø±Ø§Ø¶ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø©</Title></Section><Section name="importingpreviouslyassignedmetadata"><Title>Ø¥Ø³ØªÙØ±Ø§Ø¯ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø© Ø³Ø§ØšÙØ§</Title></Section></Section><Section name="designingacollection"><Title>ØªÙÙÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©</Title><Section name="thedesignview"><Title>Ù
+ØŽÙØ¯ Ø§ÙØªØµÙ
+ÙÙ
+</Title></Section><Section name="plugins"><Title>Ù
+ÙØ§ØšØ³ Ø§ÙÙØ«ÙÙØ©</Title></Section><Section name="searchindexes"><Title>ÙØŽØ§ÙØ§Øª Ø§ÙØšØ­Ø«</Title></Section><Section name="partitionindexes"><Title>ÙØŽØ§ÙØ§Øª Ø§ÙÙØ·Ø§Ø¹</Title><Section name="definefilters"><Title>ØªØ¹Ø±ÙÙ Ù
+Ø±ØŽØ­Ø§Øª</Title></Section><Section name="assignpartitions"><Title>ØªØ¹ÙÙÙ ÙØ·Ø§Ø¹Ø§Øª</Title></Section><Section name="assignlanguages"><Title>ØªØ¹ÙÙÙ ÙØºØ©</Title></Section></Section><Section name="classifiers"><Title>Ù
+ØµÙÙØ§Øª Ø§ÙØªØµÙØ­</Title></Section></Section><Section name="producingthecollection"><Title>Ø¥ÙØªØ§Ø¬ Ù
+Ø¬Ù
+ÙØ¹Ø©</Title><Section name="thecreateview"><Title>Ù
+ØŽÙØ¯ Ø¥ÙØŽØ§Ø¡</Title></Section><Section name="builderrors"><Title> Ø§Ø®Ø·Ø§Ø¡ ÙÙ ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©</Title></Section><Section name="expertbuilding"><Title>Ù
+ØŽÙØ¯ Ø§ÙØŽØ§Ø¡ ÙÙ Ø³ÙØ§Ù Ø®ØšÙØ±</Title></Section></Section><Section name="formattingacollection"><Title>ØªÙØ¶ÙØš ØªÙ
+ØžÙØ± Ù
+Ø¬Ù
+ÙØ¹ØªÙ</Title><Section name="theformatview"><Title>Ù
+ØŽÙØ¯ ÙØ³Ù Ø§ÙØ¹Ø±Ø¶0</Title></Section><Section name="generalsettings"><Title>Ø¹Ø§Ù
+0</Title></Section><Section name="searchmetadatasettings"><Title>ØšØ­Ø«</Title></Section><Section name="formatstatements"><Title>ÙØ³Ù Ø¹Ø±Ø¶</Title></Section><Section name="translatetext"><Title>ØªØ±Ø¬Ù
+Ù ÙØµ</Title></Section><Section name="xcollectionsearching"><Title>ØšØ­Ø« ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª</Title></Section><Section name="collectionspecificmacros"><Title>Ù
+Ø§ÙØ±Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙ
+Ø®ØµØµ</Title></Section></Section><Section name="miscellaneous"><Title>Ù
+ØªÙÙØ¹Ø§Øª</Title><Section name="preferences"><Title>Ø§ÙØªÙØ¶ÙÙØ§Øª</Title></Section><Section name="fileassociations"><Title>Ù
+ØªØ¹ÙÙØ§Øª Ø§ÙÙ
+ÙÙ</Title></Section><Section name="exporting"><Title>ØªØµØ¯ÙØ± Ø§ÙÙ
+Ù
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙÙ ÙÙØŠØ§Øª Ø£Ø®Ø±Ù</Title></Section><Section name="exportingcollections"><Title>ØªØµØ¯ÙØ± Ù
+Ø¬Ù
+ÙØ¹Ø§Øª  Ø¥ÙÙ  CD/DVD</Title></Section></Section></Document>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/howtoavoidthisdocument.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/howtoavoidthisdocument.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/howtoavoidthisdocument.htm	(revision 13928)
@@ -0,0 +1,48 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="howtoavoidthisdocument"><font size="5" face="Verdana"><strong>1.2: ÙÙÙ ØªØªØ¬ÙØš ÙØ±Ø§Ø¡Ø© ÙØ°Ù Ø§ÙÙØ«ÙÙØ©</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p> ÙØ§  ØªÙØ±Ø£ ÙØµ Ø§ÙÙ
+Ø³Ø§Ø¹Ø¯Ø© Ù
+Ù Ø£ÙÙÙ Ø¥ÙÙ Ø£Ø®Ø±Ù0 ÙÙ
+ÙÙÙ ÙØ±Ø§Ø¡Ø© ÙØ¯Ø± Ù
+ÙÙ ÙÙ
+ÙÙÙ  Ù
+Ù Ù
+Ø¹Ø±ÙØ© ÙÙÙÙØ© Ø§ÙØ­ØµÙÙ Ø¹ÙÙ Ù
+Ø³Ø§Ø¹Ø¯Ø© ÙØ­Ù Ù
+ØŽÙÙØ© Ù
+Ø¹ÙÙØ©0</p>
+
+<p>ÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+Ø³Ø§Ø¹Ø¯Ø© ØªØ­Ø¯Ø¯ ÙÙ Ù
+Ø§ÙÙ Ø§ÙØ¹ÙÙØ§Ù Ø§ÙÙ
+ÙØ§Ø³Øš Ù
+Ù ØšÙÙ Ø§ÙØ¹ÙØ§ÙÙÙ Ø§ÙØ¬Ø§ÙØšÙØ© Ø§ÙÙ
+Ø³ØšÙÙØ© Øš "Ø§ÙÙÙÙØ©"  Ø§ÙÙØªØ§Øš0</p>
+
+<p>Ø¹ÙØ¯Ù
+Ø§ ØªÙ
+ÙØ¶Ø¹ Ù
+Ø€ØŽØ± Ø§ÙÙØ£Ø±Ø© Ø¹ÙÙ Ø¹ÙÙØ§Ù Ù
+Ø­Ø¯Ø¯ ÙØžÙØ± ÙÙ Ù
+Ø±ØšØ¹ ÙØµ ÙØŽØ±Ø­ ÙÙ ÙÙÙÙØ© Ø§ÙØ¬Ø§Ø² Ø§ÙÙ
+ÙÙ
+Ø©0</p>
+
+<p>ÙØšÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+  ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙØ Ø¹ÙÙÙ Ø£ÙÙØ§ ÙØ±Ø§Ø¡Ø© Ø¯ÙÙÙ ÙØ±ÙÙØ³ØªÙÙ0</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/importingpreviouslyassignedmetadata.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/importingpreviouslyassignedmetadata.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/importingpreviouslyassignedmetadata.htm	(revision 13928)
@@ -0,0 +1,97 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="importingpreviouslyassignedmetadata"><font size="5" face="Verdana"><strong>5.7: Ø¥Ø³ØªÙØ±Ø§Ø¯ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø© Ø³Ø§ØšÙØ§</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙØµÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ÙÙÙÙØ© Ø§Ø³ØªÙØ±Ø§Ø¯ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ÙÙÙ Ø³Ø§ØšÙØ§Ù ÙÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØªÙ ØªÙ
+  ØªØ¹ÙÙÙÙØ§ ÙÙÙØ«Ø§ØŠÙ ÙØšÙ Ø§Ø¶Ø§ÙØªÙØ§ ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø©0</p>
+
+<p>Ø¥Ø°Ø§ ÙØ§ÙØª ÙØ§ØµÙØ§Øª  Ø§ÙØšÙØ§ÙØ§Øª ÙÙ ØŽÙÙ Ù
+Ø¹Ø±ÙÙ ÙÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ÙØªÙ
+ ØªØ¹ÙÙÙÙØ§ Ù
+Ù ÙØšÙ ÙÙ
+ÙÙ &ndash; Ù
+Ø«Ø§ÙØ Ø¹ÙØ¯Ù
+Ø§  ØªØ®ØªØ§Ø± ÙØ«ÙÙØ© Ù
+Ù Ù
+Ø¬Ù
+ÙØ¹Ø© Ù
+ÙØ¬ÙØ¯Ø© ÙÙ ÙØ±ÙÙØ³ØªÙÙ00 ÙØªÙ
+ Ø§Ø³ØªÙØ±Ø§Ø¯ÙØ§ ØªÙÙØ§ØŠÙØ§Ù Ø¹ÙØ¯ Ø§Ø¶Ø§ÙØ© Ø§ÙÙ
+ÙÙ ÙØ¹Ù
+Ù ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡Ø ÙØ¬Øš ØªØ®Ø·ÙØ·ÙØ§  ÙÙÙØ§Ù ÙÙ
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+ÙØ¬ÙØ¯Ø© ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0</p>
+
+<p>ÙÙÙÙ
+ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ØšØ­Ø«Ù ÙØªÙÙÙØ± Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª Ø§ÙÙ
+Ø·ÙÙØšØ©Ø ÙØ¹Ø·ÙÙ Ø§ÙØ­Ø« ØªØ¹ÙÙÙ
+Ø§Øª Ù
+ÙØ¬Ø²Ø©Ø Ø«Ù
+ ÙØžÙØ± ÙÙ Ø§Ø³Ù
+ Ø¹ÙØµØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø³ØªÙØ±Ø¯ ÙÙ
+Ø§ ÙÙ ÙÙ Ø§ÙÙ
+ÙÙ Ø§ÙÙ
+ØµØ¯Ø±0 ÙÙØ°Ø§ Ø§ÙØ­ÙÙ ÙØ§ ÙÙ
+ÙÙ ØªØ­Ø¯ÙØ«Ù Ø£Ù ØªØºÙØ±Ù0  ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØ°Ù ØªÙØ¯ ØªØ®Ø·ÙØ· Ø§ÙØ¹ÙØµØ± Ø§ÙØ¬Ø¯ÙØ¯ ØšÙØ ÙÙÙÙ
+ Ø§ÙÙØžØ§Ù
+  ØªÙÙØ§ØŠÙØ§Ù ØšØ§Ø®ØªÙØ§Ø± Ø§ÙØ§ÙØ±Øš ÙÙÙ
+Ø¹ÙØ§Ø± ÙØ§ÙØ¹ÙØµØ± ÙÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØ¬Ø¯ÙØ¯Ø©0</p>
+
+<p>ØšØ¹Ø¯ ÙØ­Øµ Ø§ÙØªØ®Ø·ÙØ·Ø ÙÙÙ
+ÙÙÙ Ø§Ø®ØªÙØ§Ø± "Ø§Ø¶Ø§ÙØ©" ÙØ§Ø¶Ø§ÙØ© Ø¹ÙØµØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙ
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø± (ÙØ°Ø§ Ø§ÙØ£Ù
+Ø± Ù
+ØªØ§Ø­ ÙÙØ· Ø¹ÙØ¯Ù
+Ø§ ÙØ§ ÙÙÙÙ ÙÙØ§Ù Ø¹ÙØµØ± ØšÙÙØ³ Ø§ÙØ§Ø³Ù
+ ÙÙ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±) "Ø¯Ù
+Ø¬" ÙØªÙØ­ ÙÙ Ø¯Ù
+Ø¬ Ø§ÙØ¹ÙØµØ± Ø§ÙØ¬Ø¯ÙØ¯ Ù
+Ø¹ ÙØ§Ø­Ø¯ Ù
+Ø®ØªØ§Ø± Ù
+Ù ÙØšÙ Ø§ÙÙ
+Ø³ØªÙÙØ¯0 Ø§Ø®ÙØ±Ø§Ù "ØªØ¬Ø§ÙÙ" ÙØ§ ØªØªÙØ­ ÙÙ Ø§Ø³ØªÙØ±Ø§Ø¯ Ø¹ÙØµØ± Ù
+Ù ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ù
+Ø¹ ÙØ°Ø§ Ø§ÙØ¹ÙØµØ±0 Ø¹ÙØ¯ ØªØ­Ø¯ÙØ¯ ÙÙÙÙØ© Ø§Ø³ØªÙØ±Ø§Ø¯ Ø¹ÙØµØ± ÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ù
+Ø¹ ÙØ°Ø§ Ø§ÙØ¹ÙØµØ±Ø Ø¹ÙØ¯ ØªØ­Ø¯ÙØ¯ ÙÙÙÙØ© Ø§Ø³ØªÙØ±Ø§Ø¯ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ØªÙÙÙ ÙØ¯ ÙØ±Ø±Øª ØŽÙÙ Ù
+Ø¹ÙÙÙ
+Ø§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0</p>
+
+<p>ÙÙÙØ± ÙÙ Ø§ÙÙØµÙ Ø§ÙØ«Ø§ÙÙ Ù
+Ù Ø¯ÙÙÙ ÙØ±ÙÙØ³ØªÙÙ ÙÙÙ
+Ø·ÙØ±ÙÙ ÙÙÙ ØšØ¹ÙÙØ§Ù Ø§ÙØ¬Ø§Ø¯ ØºØ§ÙØš Ù
+Ø­ØªÙÙØ§Øª Ø§ÙÙØ«ÙÙØ© Ù
+Ø¹ÙÙÙ
+Ø§Øª Ø¹Ù Ù
+ÙÙØ§Øª Metadatz.xml0</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/introduction.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/introduction.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/introduction.htm	(revision 13928)
@@ -0,0 +1,31 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="introduction"><font size="5" face="Verdana"><strong>1: Ø§ÙØªØ¹Ø±ÙÙ</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙØ§Ø¬ÙØ© ÙØ±ØšÙØ³ØªÙÙ ÙÙ Ø£Ø¯Ø§Ø© ÙØªØ­Ø¯ÙØ¯ ÙØªØ¬Ù
+ÙØ¹ Ø§ÙÙØ«Ø§ØŠÙ0 Ø«Ù
+ ØšÙØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙÙ
+ÙØªØšØ© Ø§ÙØ±ÙÙ
+ÙØ©0 ØªÙÙØ± Ø§ÙÙØµÙÙ ÙÙØžØ§ØŠÙ ØšØ±Ù
+Ø¬ÙØ§Øª ÙØ±ÙÙØ³ØªÙÙ ÙÙÙ
+ÙØªØšØ© Ø§ÙØ±ÙÙ
+ÙØ© Ù
+Ù Ø®ÙØ§Ù ÙØ§Ø¬ÙØ© Ø±Ø³ÙÙ
+ÙØ© ØšØ§ÙÙÙØ± Ø¹ÙÙ Ø§ÙÙÙÙØ©Ø§ÙÙØžÙÙØ© Ø§ÙÙ
+Ø·ÙÙØšØ©0.</p>
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/miscellaneous.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/miscellaneous.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/miscellaneous.htm	(revision 13928)
@@ -0,0 +1,29 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="miscellaneous"><font size="5" face="Verdana"><strong>9: Ù
+ØªÙÙØ¹Ø§Øª</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p> ÙØµÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ Ù
+ÙØ§Ù
+Ø­ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ØºÙØ± Ø§ÙÙ
+Ø±ØªØšØ·Ø© ØšØ§Ù Ù
+ØŽÙØ¯ Ù
+Ø¹ÙÙ0</p>
+
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/ofmiceandmenus.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/ofmiceandmenus.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/ofmiceandmenus.htm	(revision 13928)
@@ -0,0 +1,88 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="ofmiceandmenus"><font size="5" face="Verdana"><strong>1.1: Ø§ÙÙØ£Ø±Ø© Ù Ø§ÙÙÙØ§ØŠÙ
+</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙÙÙØ± ÙØ°Ø§ Ø§ÙÙØ³Ù
+ Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª Ø§ÙØ£Ø³Ø§Ø³ÙØ© ÙÙØªÙØ§Ø¹Ù Ù
+Ø¹ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ0 Ø§Ø°Ø§ ÙÙØª Ù
+Ø¹ØªØ§Ø¯Ø§ Ø¹ÙÙ Ø§ÙØªØ¹Ø§Ù
+Ù Ù
+Ø¹ ØšØ±Ø§Ù
+Ø¬  Ù
+ØªØµÙØ­ Ø§ÙØ§ÙØªØ±ÙØª Ù Microsoft Office ÙÙ
+Ø±ØªØ§Ø­Ø§Ù ÙÙØªØ¹Ø§Ù
+Ù Ù
+Ø¹ ÙÙØ± Ø§ÙÙØ£Ø±Ø©  ÙØ§ÙÙÙØ§ØŠÙ
+0 Ø§ÙØªÙÙ Ø¥ÙÙ <a href="howtoavoidthisdocument.htm">ÙÙÙ ØªØªØ¬ÙØš ÙØ±Ø§Ø¡Ø© ÙØ°Ù Ø§ÙÙØ«ÙÙØ©</a>.</p>
+
+<p>ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ØªØªØšØ¹ ØªÙØ§ÙÙØ¯ ØšØ±Ø§Ù
+Ø¬ Windows ÙÙ
+ØšÙÙØ© Ø¹ÙÙ Ø§ÙÙ
+Ø¹Ø±ÙØ© ØšÙØ§0</p>
+
+<p>ÙÙ Ø¬Ø²Ø¡ Ù
+Ù Ø§ÙØŽØ§ØŽØ© ØªØªÙØ§Ø¹Ù Ù
+Ø¹ÙØ Ù
+Ø«Ù Ø²Ø± Ø£Ù Ø­ÙÙ ÙØµ ÙØ³Ù
+Ù "ØªØ­ÙÙ
+" ÙØ³Ù
+Ù Ø§ÙØªØ­ÙÙ
+ ÙÙ Ø§Ù ÙØ­ØžØ© Ø§ÙØ²Ù
+ÙÙØ© "ØªØ±ÙÙØ²" ÙØ¶Ø§Ø¡ ÙÙØ³ØªØ¬ÙØš ÙÙÙØ­Ø© Ø§ÙÙ
+ÙØ§ØªÙØ­0 Ù
+Ø®ØªÙÙ ÙÙØ§Ø· Ø§ÙØªØ­ÙÙ
+ ØªØªÙØ­ ÙÙ Ø§Ø®ØªÙØ§Ø± Ø§ÙØ£Ø¬Ø²Ø§Ø¡ Ø§ÙÙ
+Ø¶Ø§Ø¡Ø© ÙÙ Ø§ÙØ£Ø²Ø±Ù Ø§ÙØºØ§Ù
+Ù0 ØšØ¹Ø¶ Ø§ÙØ£Ø¬Ø²Ø§Ø¡ ÙÙÙÙØ§ Ø±Ù
+Ø§Ø¯Ù ÙÙØ¯ÙØ§ÙØ© Ø¹ÙÙ Ø£ÙÙØ§ ØºÙØ± Ù
+ÙØŽØ·Ø©0</p>
+
+<p>ÙÙ
+ÙÙÙ ØªØ­Ø±ÙÙ ÙÙÙØ± Ù
+ÙØ§ØªÙØ­ Ø§ÙÙØ£Ø±Ø© ÙÙ
+ÙÙØ§Ù ÙÙØ³Ø§Ø±Ø§Ù ØšØµÙØ±Ø© Ø§Ø¹ØªÙØ§Ø¯ÙØ©0 ÙÙ
+ÙÙÙ Ø³Ø­Øš ÙØ«ÙØ± Ù
+Ù Ø§ÙÙ
+ÙÙÙØ§Øª ØšØ§ÙÙÙØ± ÙØ§ÙØ§ØšÙØ§Ø¡ Ø¹ÙÙ Ø§ÙØ²Ø± Ø§ÙØ£ÙÙ
+Ù Ø«Ù
+ Ø§Ø³ÙØ§Ø·ÙØ§ ÙÙ Ø§Ù Ù
+ÙØ§Ù Ø¢Ø®Ø± ÙØªØ±Ù Ø§ÙØ²Ø±0 ÙÙ
+ÙÙ Ø­Ø« Ø§ÙØ£Ù
+Ø§ÙÙ Ø§ÙÙ
+Ø³ØªÙØ¯ÙØ© ØšØªÙ
+Ø±ÙØ± Ù
+Ø€ØŽØ± Ø§ÙÙØ£Ø±Ø© ÙÙÙÙØ§0</p>
+
+<p>ÙÙ
+ÙÙÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+ ÙÙØ­Ø© Ø§ÙÙ
+ÙØ§ØªÙØ­ ÙØ·ØšØ§Ø¹Ø© Ø§ÙÙØµÙØµ ÙÙ Ø§ÙØ­ÙÙÙ0 Ù
+ÙØªØ§Ø­ [tab] ÙÙÙØ± Ø§ÙØªØ±ÙÙØ² ØšÙÙ Ù
+Ø®ØªÙÙ Ø§ÙØ­ÙÙÙ0</p>
+
+<p>ÙØ§ÙÙØ§Ø¡ ØšØ±ÙØ§Ù
+Ø¬ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± "Ø®Ø±ÙØ¬" Ù
+Ù ÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙÙ0 Ø³ÙÙ ØªØ­ÙØž Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø£ÙÙØ§0</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/openingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/openingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/openingacollection.htm	(revision 13928)
@@ -0,0 +1,73 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="openingacollection"><font size="5" face="Verdana"><strong>2.3: ÙØªØ­ Ù
+Ø¬Ù
+ÙØ¹Ø© Ù
+ÙØ¬ÙØ¯Ø©</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>0</p>
+
+<p>ÙÙ Ø­Ø§ÙØ© ØªØŽØºÙÙ Ø£ÙØ«Ø± Ù
+Ù ØšØ±ÙØ§Ù
+Ø¬ ÙÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ Ù
+Ø¹Ø§ÙØ ÙØ§Ù Ø§ÙÙ
+ÙÙØ§Øª Ø°Ø§Øª Ø§ÙØµÙØ© ØªØºÙÙ ÙÙ
+ÙØ¹ Ø§ÙØªØ¯Ø§Ø®Ù0 Ø¹ÙØ¯ ÙØªØ­ Ù
+Ø¬Ù
+ÙØ¹Ø©  ÙÙØŽØ£ Ù
+ÙÙ ØºÙÙ ØµØºÙØ± ÙÙ Ù
+Ø³Ø§Ø±ÙØ§. ÙÙÙÙ
+ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ØšØ§ÙØªØ£ÙØ¯ Ù
+Ù ÙØ¬ÙØ¯ ÙØ°Ø§ Ø§ÙÙ
+ÙÙ ÙØšÙ ÙØªØ­ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© .Ø¹ÙÙ Ø¢Ù Ø­Ø§Ù Ø¹ÙØ¯Ù
+Ø§ ÙØªÙ
+ ØºÙÙ    ÙØ§Ø¬ÙØ©  Ø§ÙÙ
+ÙØªØšÙ ØšØµÙØ±Ø© Ø³ÙÙÙ
+Ù ÙØªÙÙØ± Ø§Ø­ÙØ§ÙØ§Ù Ù
+ÙÙ Ø§ÙØºÙÙ ÙÙ Ù
+ÙØ§ÙÙØ ÙÙÙÙ
+ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ØšØ§Ø³ØªÙØ³Ø§Ø±Ù  Ø§Ø°Ø§ Ù
+Ø§ ÙÙØª ØªÙØ¯ "Ø§Ù
+ØªÙØ§Ù" Ø§ÙØªØ­ÙÙ
+ ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø©.ØªØµØ±Ù Ø¹ÙÙ Ø§ÙÙØ­Ù Ø§ÙØ°Ù ÙØ±Ø¶ÙÙ Ø¥ÙØ§ Ø¥Ø°Ø§ ÙÙØª ØªØ¹ØªÙØ¯ Ø§Ù ØŽØ®ØµØ§ Ø¢Ø®Ø± ÙØ³ØªØ®Ø¯Ù
+ ÙÙØ³ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©</p>
+
+<p>Ø¹ÙØ¯ ÙØªØ­ Ù
+Ø¬Ù
+ÙØ¹Ø© ÙÙ
+ ÙØªÙ
+ Ø§ÙØŽØ§Ø€ÙØ§ ØšÙØ§Ø³Ø·Ø© ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙØ Ø³ÙÙ ÙØªÙ
+ Ø§Ø¹ØªÙ
+Ø§Ø¯ Ù
+Ø¹ÙØ§Ø± Ø¯ØšÙÙ ÙÙØ± ÙÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙØ§0 ÙÙ
+Ø§ ÙØªÙ
+ Ø§Ø³ØªÙØ±Ø§Ø¯  Ø£Ù ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª ÙÙ
+Ø§ ÙÙ Ø¹ÙØ¯ Ø¬ÙØš Ù
+ÙÙØ§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØšÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª0 ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ Ù
+ÙØµÙÙ ÙÙ <a href="importingpreviouslyassignedmetadata.htm">Ø¥Ø³ØªÙØ±Ø§Ø¯ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø© Ø³Ø§ØšÙØ§</a> section. </p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/partitionindexes.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/partitionindexes.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/partitionindexes.htm	(revision 13928)
@@ -0,0 +1,71 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="partitionindexes"><font size="5" face="Verdana"><strong>6.4: ÙØŽØ§ÙØ§Øª Ø§ÙÙØ·Ø§Ø¹</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙØªÙ
+ ØšÙØ§Ø¡ Ø§ÙÙØŽØ§ÙØ§Øª Ø¹ÙÙ ÙØµ Ù
+Ø¹ÙÙ Ø£Ù ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª0 ÙÙ
+ÙÙ Ø¶ØšØ· Ù
+Ø³Ø§Ø­Ø© Ø§ÙØšØ­Ø« ÙØªÙØ³ÙÙ
+ Ø§ÙÙØŽØ§ÙØ§Øª Ø¥ÙÙ ÙØ·Ø§Ø¹Ø§ØªØ Ø£Ù
+Ø§ ØšØ§ÙÙØºØ© Ø£Ù Ù
+Ø±ØŽØ­ Ù
+Ø­Ø¯Ø¯ Ù
+Ù ÙØšÙ0 ÙØµÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ÙÙÙÙØ© Ø¥ÙØ¬Ø§Ø² ÙØ°Ø§0 ØªØ­Ø« "ØªØµÙ
+ÙÙ
+" Ø§ÙÙØ± "ÙØŽØ§ÙØ§Øª Ø§ÙÙØ·Ø§Ø¹"0</p>
+
+<p>ÙÙØ¬Ø¯ ÙÙ Ù
+ØŽÙØ¯ "ÙØŽØ§ÙØ§Øª Ø§ÙÙØ·Ø§Ø¹" Ø«ÙØ§Ø« tabs "ØªØ¹Ø±ÙÙ Ù
+Ø±ØŽØ­Ø§Øª"Ø Ù"ØªØ¹ÙÙ ÙØ·Ø§Ø¹Ø§Øª" Ù "ØªØ¹ÙÙÙ ÙØºØ§Øª" ÙÙ
+Ø¹Ø±ÙØ© Ø§ÙÙ
+Ø²ÙØ¯ Ø¹Ù Ø§ÙÙØ·Ø§Ø¹Ø§Øª Ø§ÙØ±Ø£  Ø­ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙÙØ±Ø¹ÙÙ ÙØ§ÙÙØŽØ§ÙØ§Øª Ø§ÙÙØ±Ø¹ÙØ© ÙÙ Ø§ÙÙØµÙ 2 Ù
+Ù Ø¯ÙÙÙ ÙØ±ÙØ³ØªÙÙ ÙÙÙ
+Ø·ÙØ±ÙÙ0</p>
+
+<p>ÙØªÙ
+ ØªÙØŽÙØ· ØŽØ§ØŽØ© ÙØŽØ§ÙØ§Øª Ø§ÙØ·Ø§Ø¹ ÙÙ Ø³ÙØ§Ù Ø§Ø®ØªØµØ§ØµÙ ÙØžÙ
+ Ù
+ÙØªØšØ§Øª ÙØ³ÙØ§Ù Ø®ØšÙØ± (see <a href="preferences.htm">Ø§ÙØªÙØ¶ÙÙØ§Øª</a>). ÙØ§Ø­Øž Ø§ÙÙ ØšØ§ÙÙØ³ØšÙ  ÙÙ
+Ø¬Ù
+ÙØ¹Ù  MG ÙØ§Ù Ø§ÙØ¹Ø¯Ø¯ Ø§ÙÙÙÙ Ø§ÙØ°Ù ÙØªÙ
+ ØªÙÙÙØ¯Ù  Ù
+Ù Ù
+Ø²ÙØ¬  ÙÙ Ø§ÙÙØŽØ§ÙØ§ØªØ  Ù
+Ø±ØŽØ­Ø§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙØ±Ø¹ÙØ© ÙØ§ÙÙØºØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±Ø©0 ÙØŽØ§ÙÙÙ ØšÙ
+Ø±ØŽØ­Ø§Øª  Ù
+Ø¬Ù
+ÙØ¹ØªÙÙ ÙØ±Ø¹ÙØªÙÙ   ØšÙØºØªÙÙ ÙÙØªØ¬ ÙØŽØ§Ù ØšØ«Ù
+Ø§ÙÙØ© ÙØ·Ø§Ø¹Ø§Øª0 ØšØ§ÙÙØ³ØšØ© Ù MGPP Ø ØªÙØŽØŠ ÙÙ Ø§ÙÙØŽØ§ÙØ§Øª ÙÙ ÙØŽØ§Ù ÙØ§Ø­Ø¯ ÙÙØ· ÙÙØ°Ø§ ÙØ¹ÙÙ ÙØŽØ§Ù  ØšØ§Ø±ØšØ¹Ù ÙØ·Ø§Ø¹Ø§Øª- ØšØ§ÙÙØ³ØšØ© ÙÙ Lucene ÙØªØ­Ø¯Ø¯ Ø¹Ø¯Ø¯  Ø§ÙÙØŽØ§ÙØ§Øª Ø§ÙÙ
+Ø§Ø¯ÙÙ ØšØ¹Ø¯Ø¯ Ø§ÙÙ
+Ø³ØªÙÙØ§Øª Ø§ÙÙ
+Ø¹ÙÙÙ ÙÙÙ
+Ø¬Ù
+ÙØ¹ÙØ ÙÙÙ ÙØŽØ§Ù ÙØ§Ø­Ø¯ ÙÙÙ Ù
+Ø³ØªÙÙ0  ÙÙÙØ§Ù ÙÙÙØ¶Ø¹ Ø£Ø¹ÙØ§ÙØ ÙØ§Ù Ù
+Ø³ØªÙÙ ÙØ§Ø­Ø¯ ÙÙØªØ¬ Ø£Ø±ØšØ¹Ø© ÙØŽØ§ÙØ§Øª Ù
+Ø§Ø¯ÙÙ ØšÙÙÙ
+Ø§ Ù
+Ø³ØªÙÙÙ Ø³ÙÙ ÙÙØªØ¬Ø§Ù Ø«Ù
+Ø§ÙÙØ©0</p>
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/plugins.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/plugins.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/plugins.htm	(revision 13928)
@@ -0,0 +1,149 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="plugins"><font size="5" face="Verdana"><strong>6.2: Ù
+ÙØ§ØšØ³ Ø§ÙÙØ«ÙÙØ©</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙØµÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ÙÙÙÙØ© Ø¥Ø¹Ø¯Ø§Ø¯ Ù
+ÙØ§ØšØ³ Ø§ÙÙØ«ÙÙØ© Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+Ø© ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 ÙØŽØ±Ø­ ÙÙ ÙÙÙ ØªØ­Ø¯Ø¯ Ø§ÙÙ
+ÙØ§ØšØ³ ÙÙØ§Ø³ØªØ®Ø¯Ø§Ù
+Ø ÙÙ
+Ø§ÙÙ Ø§ÙÙ
+Ø€ØŽØ±Ø§Øª Ø§ÙØªÙ ØªÙ
+Ø±Ø± ÙÙØ§ ÙÙ
+Ø§ ÙÙ Ø§ÙØªØ±ØªÙØš Ø§ÙØ°Ù ØªØªØ®Ø°ÙØ ØªØ­Øª tab "ØªØµÙ
+ÙÙ
+"Ø Ø§ÙÙØ± "Ù
+ÙØ§ØšØ³ ÙØ«ÙÙØ©"0</p>
+
+<p>ÙØ§Ø¶Ø§ÙØ© Ù
+ÙØ§ØšØ³ Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù ØšØ§Ø³ØªØ®Ø¯Ø§Ù
+ Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© "Ø§Ø®ØªÙØ§Ø± Ù
+ÙØ§ØšØ³ ÙÙØ§Ø¶Ø§ÙØ©" Ø§ÙÙØ±ÙØšØ© Ù
+Ù Ø§ÙØ£Ø³ÙÙØ Ø«Ù
+ Ø§ÙØžØ± "Ø§Ø¶Ø§ÙØ© Ù
+ÙØ§ØšØ³" ØªØžÙØ± ÙÙ ÙØ§ÙØ°Ø© ØšØ¹ÙÙØ§Ù "Ù
+Ø¶Ø§Ù
+ÙÙ Ø§ÙØªØ¬ÙÙØ²" ÙÙÙ Ù
+ÙØµÙÙÙ ÙÙÙ
+Ø§ ØšØ¹Ø¯0 Ø¹ÙØ¯ ØªØ¬ÙÙØ² Ø§ÙÙ
+ÙØ§ØšØ³ Ø§ÙØ¬Ø¯ÙØ¯Ø ØªØªÙ
+ Ø§Ø¶Ø§ÙØªÙ ÙÙ Ù
+Ø€Ø®Ø±Ø© ÙØ§ØŠÙ
+Ø© "Ø§ÙÙ
+ÙØ§ØšØ³ Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø© Ø­Ø§ÙÙØ§Ù0 ØªØ¬Øš Ù
+ÙØ§Ø­ØžØ©Ø Ø§ÙÙ ØšØ§Ø³ØªØ«ÙØ§Ø¡ Ù
+ÙØ§ØšØ³ UnknownPluq ÙØ¬Øš Ø£Ù ÙØŽØºÙ Ø£Ù Ù
+ÙØ§ØšØ³ Ø§Ø®Ø± Ø­ÙØ²Ø§Ù ÙØ§Ø­Ø¯Ø§Ù ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø©0</p>
+
+<p>ÙØ±Ø€ÙØ© ÙØµÙ ÙØµÙØ± ÙÙ
+ÙØ§ØšØ³Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© "Ø§Ø®ØªÙØ§Ø± Ù
+ÙØ§ØšØ³ ÙÙØ§Ø¶Ø§ÙØ©" Ø«Ù
+ Ø­ÙÙ ØšÙ
+Ø€ØŽØ± Ø§ÙÙØ£Ø±Ø© ÙÙÙÙ0 ÙØžÙØ± ÙÙ Ù
+Ø±ØšØ¹ ÙØµ ÙØ¹Ø±Ø¶ Ø§ÙÙØµÙ0
+124- ÙØ§Ø²Ø§Ø­Ø© Ù
+ÙØ§ØšØ³Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù  Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©Ø ÙØ§ÙÙØ± "Ø­Ø°Ù Ù
+ÙØ§ØšØ³"0</p>
+
+<p>ÙØ§Ø²Ø§Ø­Ø© Ù
+ÙØ§ØšØ³Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù  Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©Ø ÙØ§ÙÙØ± "Ø­Ø°Ù Ù
+ÙØ§ØšØ³"0</p>
+
+<p> ÙØªÙ
+ ØªØ¬ÙÙØ² Ø§ÙÙ
+ÙØ§ØšØ³ ØšØªÙÙÙØ± Ø§ÙÙ
+Ø¶Ø§Ù
+ÙÙ0 ÙØ­Ø« Ù
+ÙØ§ØšØ³Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ù
+ÙØ§ØšØ³ Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©Ø ÙØ§ÙÙØ± "ØªØ¬ÙÙØ² Ù
+ÙØ§ØšØ³" (Ø§Ù ÙÙØ±Ø© Ù
+Ø²Ø¯ÙØ¬Ø© ÙÙÙ
+ÙØ§ØšØ³" ÙØžÙØ± Ù
+Ø±ØšØ¹ Ø­ÙØ§Ø± "ØªØ¬ÙÙØ² Ù
+Ø¶Ø§Ù
+ÙÙ" ÙØ¶ØšØ· ØªØ­Ø¯ÙØ¯ Ø§ÙÙ
+Ø¶Ø§Ù
+ÙÙ0</p>
+
+<p> ØªÙØ¬Ø¯ Ø£ÙÙØ§Ø¹ Ù
+Ø®ØªÙÙØ© ÙÙØ¶ØšØ·Ø ØšØ¹Ø¶ÙØ§ Ù
+Ø±ØšØ¹Ø§Øª ÙØ­Øµ ÙØ§ÙÙÙØ± Ø¹ÙÙÙØ§ ÙØ¶ÙÙ Ø§ÙØ®ÙØ§Ø± Ø§ÙÙ
+ÙØ§ØŠÙ
+ ÙÙÙ
+ÙØ§ØšØ³0 Ø§ÙØ§ÙÙØ¹ Ø§ÙØ§Ø®Ø±Ù Ø³ÙØ§Ø³Ù ÙØµØšÙ ØšÙ
+Ø±ØšØ¹Ø§Øª ÙØ­Øµ Ø£Ù Ø­ÙÙ ÙØµÙ0 ÙÙ
+ ØšØªØ£ØŽÙØ± Ø§ÙÙ
+Ø±ØšØ¹ ÙØªÙØŽÙØ· Ø§ÙÙ
+Ø¶Ù
+ÙÙ Ø«Ù
+ Ø£Ø·ØšØ¹ Ø§ÙÙØµ Ø§ÙÙ
+ÙØ§ØŠÙ
+ (ØªØ¹ØšÙØ± Ù
+ÙØªØžÙ
+Ø Ù
+Ø³Ø§Ø± Ù
+ÙÙ00) ÙÙ Ø§ÙÙ
+Ø±ØšØ¹0 ØªØŽÙ
+Ù ØšÙÙØ© Ø§ÙØ§ÙÙØ§Ø¹ Ø§ÙØ¶Ø§Ù ÙÙØ§ØŠÙ
+ Ù
+ÙØ³Ø¯ÙØ© ØªØªÙØ­ ÙÙ Ø§ÙØ§Ø®ØªÙØ§Ø±Ø ÙÙ
+Ø¹Ø±ÙØ© Ù
+Ø§ ÙÙ
+ÙÙ Ø§Ù ÙÙØ¹ÙÙ Ø§ÙÙ
+Ø¶Ù
+ÙÙØ Ø§Ø¬Ø¹Ù Ù
+Ø€ØŽØ± Ø§ÙÙØ£Ø±Ø© ÙÙÙ Ø§ÙØ§Ø³Ù
+ ÙØšØ±ÙØ© ÙØžÙØ± ÙÙ Ø§ÙÙØµÙ0</p>
+
+<p>Ø¥Ø°Ø§ ØºÙØ±Øª Ø§ÙØªØ¬ÙÙØ²Ø Ø§ÙÙØ± "OK" ÙØªØ£ÙÙØ¯ Ø§ÙØªØºÙÙØ±Ø§Øª ÙØ§ØºÙÙ Ù
+Ø±ØšØ¹ Ø§ÙØ­ÙØ§Ø± . Ø§Ù "Ø¥ÙØºØ§Ø¡" ÙØ§ØºÙØ§Ù Ù
+Ø±ØšØ¹ Ø§ÙØ­ÙØ§Ø± ØšØ¯ÙÙ ØªØºÙÙØ± Ù
+Ø¶Ø§Ù
+ÙÙ Ø§ÙÙ
+ÙØ§ØšØ³0</p>
+
+<p>ÙØªÙ
+ ØªÙÙÙØ° Ø§ÙÙ
+ÙØ§ØšØ³ ØšØ§ÙØªØ±ØªÙØšØ ÙÙÙÙÙ Ø§ÙØªØ±ØªÙØš Ø§Ø­ÙØ§ÙØ§Ù Ù
+ÙÙ
+0 ÙÙ
+ÙÙ ØªØ±ØªÙØš Ø§ÙÙ
+ÙØ§ØšØ³ ÙÙ Ø³ÙØ§Ù Ø§Ø®ØªØµØ§ØµÙ ÙØžÙ
+ Ù
+ÙØªØšØ§Øª ÙØ³ÙØ§Ù Ø®ØšÙØ± (see <a href="preferences.htm">Ø§ÙØªÙØ¶ÙÙØ§Øª</a>).    </p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/preferences.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/preferences.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/preferences.htm	(revision 13928)
@@ -0,0 +1,180 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="preferences"><font size="5" face="Verdana"><strong>9.1: Ø§ÙØªÙØ¶ÙÙØ§Øª</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙØŽØ±Ø­ ÙØ°Ø§  Ø§ÙÙØ³Ù
+ Ù
+Ø±ØšØ¹ Ø­ÙØ§Ø± Ø§ÙØªÙØ¶ÙÙØ§Øª ÙØ§ÙØ°Ù ÙØªØ§Ø­ ØšÙØªØ­ "Ù
+ÙÙ" 
+Ø§ÙØªÙØ¶ÙÙØ§Øª0</p>
+
+<p>"ØªÙØªØ­ ÙØ§ÙØ°Ø© Ø§ÙØªÙØ¶ÙÙØ§Øª  ÙÙ  tab "Ø¹Ø§Ù
+"  Ø§ÙØ®ÙØ§Ø± Ø§ÙØ£ÙÙ ÙÙ Ø­ÙÙ ÙØµÙ ÙØ§Ø¯Ø®Ø§Ù Ø¹ÙÙØ§Ù  ØšØ±ÙØ¯Ù Ø§ÙØ§ÙÙØªØ±ÙÙÙ ÙØ³ÙÙ ÙØªÙ
+  Ø§Ø³ØªØ®Ø¯Ø§Ù
+Ù Ù "Ù
+ÙØŽØŠ" Ù"Ù
+Ø§ÙÙ" Ø¶Ù
+Ù Ø¹ÙØ§ØµØ±  ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø©  Ø§ÙØ¬Ø¯ÙØ¯Ø©0 Ø§ÙØ®ÙØ§Ø± Ø§ÙØ«Ø§ÙÙ  ÙÙ ÙØ§ØŠÙ
+Ø© Ù
+ÙØ³Ø¯ÙØ© ØšØ§ÙÙØºØ§Øª Ø§ÙØªÙ ØªØ³ØªØ·ÙØ¹ Ø¹Ø±Ø¶ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ØšÙØ§0 Ø§Ø°Ø§ ÙÙ
+Øª ØšØ§Ø®ØªÙØ§ Ø± ÙØºÙØ ÙÙØšØºÙ Ø§Ø¹Ø§Ø¯Ø© ØªØŽØºÙÙ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ÙØªØ­Ù
+ÙÙ Ø³ÙØ§Ø³Ù Ø§ÙÙØºØ© ÙÙ Ø§ÙÙØ§Ù
+ÙØ³0</p>
+
+<p>Ø§Ø°Ø§ ØªÙ
+ ØªØ£ØŽÙØ± "Ø¹Ø±Ø¶ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø³ØªØ®ÙØµØ©" ÙØªÙ
+ Ø¹Ø±Ø¶ Ù
+Ø®ØªÙÙ Ø§ÙØ¶ÙØ§ØšØ· Ø§ÙØªÙ ØªØ¹Ø§Ù
+Ù ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø³ØªØ®ÙØµÙ Ø¢ÙÙØ§ Ù
+Ù Ø§ÙÙØ«Ø§ØŠÙ0 ØªÙØ¶  Ø§ÙØ§Ø®ØªÙØ§Ø±  ÙØ®ÙÙ ÙØ°Ù Ø§ÙÙØ§ØµÙØ§Øª (ØšØ§ÙØ±ØºÙ
+ Ù
+Ù Ø°ÙÙ  ØªØšÙ Ù
+ØªÙÙØ±Ù ÙÙ  ØªØµÙ
+ÙÙ
+ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0  ÙØ®ÙØ§Ù  Ù
+Ø¬Ù
+ÙØ¹Ø©  ÙØ±ÙÙØ³ØªÙÙ Ø§ÙÙÙØ§ØŠÙØ©)0 Ø§Ø°Ø§ ØªÙ
+ ØªØ£ØŽÙØ± "Ø¹Ø±Ø¶ Ø§Ø­Ø¬Ø§Ù
+ Ø§ÙÙ
+ÙÙ"  ÙØªÙ
+ Ø¹Ø±Ø¶ Ø§ÙØ­Ø¬Ù
+  ØšØ¹Ø¯ Ø§ÙÙ
+ÙÙ ÙÙ Ù
+Ø³Ø§Ø­Ø© Ø§ÙØ¹Ù
+Ù ÙØŽØ¬Ø±Ø©  Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙ Ù
+ØŽÙØ¯Ù  "ØªØ¬Ù
+ÙØ¹" Ù"Ø¥Ø«Ø±Ø§Ø¡"0</p>
+
+<p>ÙØ³ØªØ®Ø¯Ù
+  tab "Ø³ÙØ§Ù" ÙØ¶ØšØ·  Ù
+Ø³ØªÙÙ Ø§ÙØªÙØµÙÙ ÙÙ Ø§ÙÙØ§Ø¬ÙØ©- ÙÙÙØ± "Ù
+Ø³Ø§Ø¹Ø¯ Ù
+ÙØªØšÙ" Ø£ÙÙ Ø§Ø¹Ø¯Ø§Ø¯ Ø­ÙØ« ÙØªÙ
+  Ø­Ø¬Øš Ù
+ØŽÙØ¯  Ø§ÙØªØµÙ
+ÙÙ
+ ÙØ§ÙÙ
+Ø¶Ø§Ù
+ÙÙ Ø§ÙØªÙ ØªØªØ·ÙØš Ø§ÙØªØºÙØ±Ø§Øª Ø§ÙÙ
+ÙØªØžÙ
+Ø©Ø ÙØªØªÙÙØ± Ù
+Ø¹ÙÙÙ
+Ø§Øª ÙÙÙÙØ© ÙÙ Ù
+Ø¯ÙÙÙ Ø§Ø­Ø¯Ø§Ø« ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0  ÙÙÙØ± Ø³ÙØ§Ù "Ø®ØšÙØ±" Ø§Ø¹ÙÙ Ø¥Ø¹Ø¯Ø§Ø¯ Ø­ÙØ« ÙØªØ§Ø­  Ø§ÙÙØµÙÙ ÙÙÙ Ù
+ÙØ§Ù
+Ø­ Ø§ÙØªØµÙ
+ÙÙ
+Ø Ù
+ØªØ¶Ù
+ÙÙ ØªÙ
+ÙØ¶Ø­ Ø§ÙÙ
+ÙØ§ØšØ³ ÙÙ
+Ø¶Ø§Ù
+ÙÙ Ø§ÙØªØ¹ØšÙØ±Ø§Øª Ø§ÙÙ
+ÙØªØžÙ
+Ø©Ø ÙØªØ³Ø¬ÙÙ Ø§ÙÙ
+Ø®Ø±Ø¬Ø§Øª Ø§ÙÙØ§Ù
+ÙØ© ÙØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙ Ø§ÙÙ
+Ø¯ÙÙÙ ÙØªØºÙÙØ± Ø£Ù Ø§Ø³ØªØ¹Ø±Ø§Ø¶ Ø§ÙØ³ÙØ§ÙØ§Øª Ø Ø§ÙÙØ± Ø²Ø± "Radio buttons" Ø§ÙØ«Ø§ÙÙ ÙÙØ³ÙØ§Ù Ø§ÙØ°Ù ØªÙØªÙ
+ ØšÙ0 ÙÙ
+ÙÙÙ Ù
+Ø¹Ø±ÙØ© Ø§ÙØ³ÙØ§Ù Ø§ÙØ°Ù Ø§ÙØª ÙÙÙ ØšØ§ÙÙØžØ± Ø¥ÙÙ Ø¹Ù
+ÙØ¯ Ø¹ÙÙØ§Ù ÙØ§Ø¬ÙÙ Ø§ÙÙ
+ÙØªØšÙ0</p>
+
+<p>ÙØ³ØªØ·ÙØ¹ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ Ø¯Ø¹Ù
+ Ù
+Ø®ØªÙÙ ØªØ¯ÙÙØ§Øª Ø§ÙØ¹Ù
+Ù ÙØªØ¬Ø¯ÙØ¯  Ø§ÙÙ tab Ø§ÙÙ
+ØŽØ§ÙØ¯ ÙÙÙÙ Ù
+Ø±ØŠÙØ§Ù0  Ø¥Ø³ØªØ®Ø¯Ù
+ tab "ØªØ¯ÙÙ Ø§ÙØ¹Ù
+Ù" ÙØªØ£ØŽÙØ± Ø§ÙÙ
+Ø±ØšØ¹Ø§Øª Ø§ÙØªÙ ØªÙÙ Ø§ÙÙ
+ØŽØ§ÙØ¯ ÙØªÙØ¶ÙØš Ø§ÙÙ
+ØŽØ§ÙØ¯ Ø§ÙÙ
+ØªÙÙØ±Ø©0 Ø®ÙØ§Ø± Ø¢Ø®Ø± Ø§Ø³ØªØ®Ø¯Ù
+ Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© ÙÙØªØ­Ø¯ÙØ¯ Ø§ÙÙ
+Ø³ØšÙ ÙÙØªØ¬ÙÙØ²Ø§Øª0 ÙØªÙ
+ Ø§Ø¹ØªÙ
+Ø§Ø¯ Ø§Ø¹Ø¯Ø§Ø¯Ø§Øª ØªØ¯ÙÙ Ø§ÙØ¹Ù
+Ù Ø¹ÙØ¯ Ø§ØºÙØ§Ù Ù
+Ø±ØšØ¹ Ø­ÙØ§Ø± Ø§ÙØªÙØ¶ÙÙØ§ØªØ ÙÙØ°Ù  Ø§ÙØªÙØ¶ÙÙØ§Øª ÙÙØ· Ù
+Ø¹ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙÙØ³  ÙÙ ØªÙÙÙÙ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ0</p>
+
+<p>ÙØªÙØ­ ÙÙ  tab "Ø§ÙØ§ØªØµØ§Ù" Ø­ÙØ« Ø§ÙÙ
+Ø³Ø§Ø± Ø¥ÙÙ Ù
+Ø²ÙØ¯ Ù
+ÙØªØšØ© ÙØ±ÙÙØ³ØªÙÙ Ø§ÙÙ
+Ø­ÙÙ Ø§ÙØ°Ù ÙØ³ØªØ®Ø¯Ù
+ Ø¹ÙØ¯ Ø¹Ø±Ø¶ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©Ø ÙÙ
+Ø§ ÙØªÙØ­  ÙÙ Ø¥Ø¹Ø¯Ø§Ø¯ Ù
+Ø¹ÙÙÙ
+Ø§Øª Ø§ÙØšØ±ÙÙØ³Ù ÙÙØ§ØªØµØ§Ù Ø¹ØšØ± Ø§ÙØ§ÙØªØ±ÙØª (Ù
+Ø«Ø§ÙØ ØªÙØ²ÙÙ Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª)<a href="downloadingfiles.htm">ØªÙØ²ÙÙ Ø§ÙÙ
+ÙÙØ§Øª Ù
+Ù Ø§ÙØ¥ÙØªØ±ÙØª</a> ÙÙ
+Ø²ÙØ¯ Ù
+Ù Ø§ÙØªÙØ§ØµÙÙ). ÙÙÙ
+ ØšØªØ£ØŽÙØ± Ø§ÙÙ
+Ø±ØšØ¹ ÙØªÙØŽÙØ· Ø§ÙØšØ±ÙÙØ³Ù ÙØªÙÙÙØ± Ù
+Ø¹ÙÙÙ
+Ø§Øª Ø¹ÙÙØ§Ù Ù
+Ø¶ÙÙ Ø§ÙØšØ±ÙÙØ³Ù ÙØ±ÙÙ
+ Ø§ÙÙ
+ÙÙØ°0 ÙØªÙ
+ ØªØ¬ÙÙØ² Ø§ØªØµØ§Ù Ø§ÙØšØ±ÙÙØ³Ù Ø¹ÙØ¯Ù
+Ø§ ØªÙÙÙ
+  ØšØºÙÙ Ù
+Ø±ØšØ¹ Ø§ÙØªÙØ¶ÙÙØ§Øª0</p>
+
+<p>Ø®ÙØ§Ù ÙØªØ±Ø© ØªØŽØºÙÙ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙØ Ø±ØšÙ
+Ø§ ØªØžÙØ± Ø±Ø³Ø§ØŠÙ ØªØ­Ø°ÙØ± ÙØ§Ø¹ÙØ§Ù
+Ù ØšØ¹ÙØ§ÙØš ØšØ¹Ø¶ Ø§ÙØ§Ø¬Ø±Ø§Ø¡Ø§Øª ØºÙØ± Ø§ÙÙ
+Ø±ØŠÙØ©0 ÙÙ
+ÙÙÙ Ø§Ø®Ù
+Ø§Ø¯ ÙØ°Ù Ø§ÙØ±Ø³Ø§ØŠÙ ÙØªØ£ØŽÙØ± Ù
+Ø±ØšØ¹ " ÙØ§ØªØ¹Ø±Ø¶ ÙØ°Ø§ Ø§ÙØªØ­Ø°ÙØ± Ù
+Ø±Ø© Ø«Ø§ÙÙØ©"0 ÙÙ
+ÙÙÙ ØªÙØŽÙØ· Ø±Ø³Ø§ØŠÙ  Ø§ÙØªØ­Ø°ÙØ± ØšØ§Ø³ØªØ®Ø¯Ø§Ù
+ tab  "ØªØ­Ø°ÙØ±Ø§Øª 0 ÙÙ
+ ØšØªØ£ØŽÙØ± Ø§ÙÙ
+Ø±ØšØ¹ Ø§ÙØªØ§ÙÙ ÙØ±Ø³Ø§ØŠÙ Ø§ÙØªØ­Ø°ÙØ± Ø§ÙØªÙ ØªØ±ØºØš ÙÙ Ø±Ø€ÙØªÙØ§ Ù
+Ø±Ø© Ø«Ø§ÙÙØ©0</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/producingthecollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/producingthecollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/producingthecollection.htm	(revision 13928)
@@ -0,0 +1,39 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="producingthecollection"><font size="5" face="Verdana"><strong>7: Ø¥ÙØªØ§Ø¬ Ù
+Ø¬Ù
+ÙØ¹Ø©</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Ø¥Ø°Ø§ ØªÙ
+ ØªØ¬Ù
+ÙÙØ¹ Ø§ÙÙØ«Ø§ØŠÙ ÙÙÙ
+Ø¬Ù
+ÙØ¹ÙØ Ù
+ØŽØ±ÙØ­Ø© ØšÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+Ø¹ ØªØµÙ
+ÙÙ
+ ÙÙÙÙØ© ØªÙ
+ØžÙØ± Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 ÙÙ
+ÙÙÙ ÙØ°Ø§ Ù
+Ù Ø§ÙØªØ§Ø¬ Ù
+Ø¬Ù
+ÙØ¹Ø© ØšÙØ§Ø³Ø·Ø© ÙØ±ÙÙØ³ØªÙÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ÙØŽØ±Ø­ ÙÙÙÙØ© Ø§ÙØ¬Ø§Ø² ÙØ°Ø§ Ø§ÙØ£Ù
+Ø±0</p>
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/removingfiles.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/removingfiles.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/removingfiles.htm	(revision 13928)
@@ -0,0 +1,35 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="removingfiles"><font size="5" face="Verdana"><strong>4.6: Ø­Ø°Ù Ù
+ÙÙØ§Øª</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ØªÙØ¬Ø¯ Ø§Ø³Ø§ÙÙØš Ø¹Ø¯ÙØ¯Ø© ÙØ­Ø°Ù Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª ÙØ§ÙÙ
+ÙÙØ§Øª0 ÙØ¬Øš Ø¹ÙÙÙ Ø§ÙÙØ§Ù ØªØ­Ø¯ÙØ¯ Ø§ÙØ¹ÙØ§ØµØ± Ø§ÙÙ
+Ø·ÙØš Ø­Ø°ÙÙ ØšØ§Ø®ØªÙØ§Ø± Ù
+Ø¬ÙØ¯ Ø£Ù Ù
+ÙÙ Ø§ÙØ£ÙØ«Ø± ÙÙ
+Ø§ ÙÙ Ù
+ÙØµÙÙ ÙÙ <a href="thegatherview.htm">Ù
+ØŽÙØ¯ Ø§ÙØªØ¬Ù
+ÙÙØ¹</a>.</p>
+
+<p>Ø¹ÙØ¯ Ø§Ø®ØªÙØ§Ø± Ø§ÙÙ
+ÙÙØ Ø§ÙÙØ± Ø²Ø± "Ø§ÙØºØ§Ø¡" ÙØ­Ø°ÙÙ Ø£Ù ØšØ§ÙØ¶ØºØ· Ø¹ÙÙ "Ø§ÙØºØ§Ø¡" ÙÙ ÙÙØ­Ø© Ø§ÙÙ
+ÙØ§ØªÙØ­ - Ø£Ù Ø³Ø­Øš Ø§ÙÙ
+ÙÙØ§Øª Ù
+Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø¥ÙÙ Ø²Ø± Ø§ÙØ§ÙØºØ§Ø¡ ÙØ§Ø³ÙØ§Ø·ÙØ§ ÙÙØ§Ù0</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/replacingfiles.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/replacingfiles.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/replacingfiles.htm	(revision 13928)
@@ -0,0 +1,44 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="replacingfiles"><font size="5" face="Verdana"><strong>4.5: Ø§Ø¹Ø§Ø¯Ø© ØªØ³Ù
+ÙØ© ÙØ§Ø³ØªØšØ¯Ø§Ù Ø§ÙÙ
+ÙÙØ§Øª0</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p> ÙÙ
+ÙÙ Ø§Ø¹Ø§Ø¯Ø© ØªØ³Ù
+ÙØ© Ø§ÙÙ
+ÙÙØ§Øª ØšØ§ÙÙÙØ± Ø¹ÙÙ Ø§ÙØ²Ø± Ø§ÙØ£ÙÙ
+Ù Ø¹ÙÙÙØ§ ÙØ§Ø®ØªÙØ§Ø± "Ø§Ø¹Ø§Ø¯Ø© ØªØ³Ù
+ÙØ©" Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©Ø Ø¯Ø®Ù Ø§ÙØ§Ø³Ù
+ Ø§ÙØ¬Ø¯ÙØ¯ ÙØ§ÙÙØ± "OK"</p>
+
+<p> ÙÙ
+ÙÙ Ø§Ø³ØªØšØ¯Ø§Ù Ø§ÙÙ
+ÙÙØ§Øª ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØšÙÙØ± Ø§ÙØ²Ø± Ø§ÙØ§ÙÙ
+Ù ÙÙÙ Ø§ÙÙ
+ÙÙ Ø§ÙÙ
+Ø±Ø§Ø¯ Ø§Ø³ØªØšØ¯Ø§ÙÙ ÙØ§Ø®ØªÙØ§Ø± "Ø§Ø³ØªØšØ¯Ø§Ù" ÙØªÙ
+ ÙØªØ­ Ù
+ØªØµÙØ­ Ø§ÙÙ
+ÙÙØ§ØªØ ØªØ¬ÙÙ Ø¥ÙÙ Ø§ÙÙØ«ÙÙØ© Ø§ÙØ¬Ø¯ÙØ¯Ø© ÙØ§ÙÙØ± "ÙØªØ­" ÙÙØ§ ÙØªÙ
+ Ø§Ø³ØªØšØ¯Ø§Ù Ø§ÙÙØ«ÙÙØ© Ø§ÙÙØ¯ÙÙ
+Ø© ØšØ§ÙØ¬Ø¯ÙØ¯Ø©  ÙØ³ÙÙ ÙØªÙ
+ ØªØ­ÙÙÙ Ø§Ù ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø¥ÙÙÙØ§ ÙÙÙÙÙ ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ Ù
+ÙÙØ¯Ø§Ù ÙÙ Ø­Ø§ÙØ© Ø§Ø³ØªØšØ¯Ø§Ù Ø§ÙÙØ«Ø§ØŠÙ Ø§ÙÙ
+Ø²ÙÙØ© ØšÙØ«Ø§ØŠÙ Ø­ÙÙÙÙØ©0</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/reviewingmetadata.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/reviewingmetadata.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/reviewingmetadata.htm	(revision 13928)
@@ -0,0 +1,138 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="reviewingmetadata"><font size="5" face="Verdana"><strong>5.6: 
+Ø¥Ø³ØªØ¹Ø±Ø§Ø¶ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø©</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ØªØ­ØªØ§Ø¬ Ø§Ø­ÙØ§ÙØ§Ù ÙØ±Ø€ÙØ© ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ÙÙØ© ÙØ¹Ø¯Ø¯ Ù
+Ù Ø§ÙÙ
+ÙÙØ§Øª Ù
+Ø±Ø© ÙØ§Ø­Ø¯Ø©00 Ù
+Ø«ÙØ§ ÙØªØ­Ø¯ÙØ¯ Ø­Ø¬Ù
+ Ø§ÙØ¹Ù
+Ù ÙÙ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+ØªØšÙÙØ© Ø§Ù ÙØ§Ø®Ø° ÙÙØ±Ø© Ø­ÙÙ Ø§ÙØªØºØ·ÙØ© Ø§ÙØ²Ù
+ÙÙØ©0
+</p>
+
+<p>ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙØªÙ ØªÙØ¯ ÙØ­ØµÙØ§Ø Ø«Ù
+ Ø§ÙØ¶ØºØ· Ø¹ÙÙ Ø²Ø± Ø§ÙÙØ£Ø±Ø© Ø§ÙØ§ÙÙ
+Ù  ÙØ§Ø®ØªÙØ§Ø± "ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø© " ÙØžÙØ± ÙÙ Ø¬Ø¯ÙÙ ÙØšÙØ± ÙÙ ÙØ§ÙØ°Ø© Ø§Ø¹ÙÙØ§Ù  "ÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª" ÙØžÙØ± ÙÙ Ø§ÙØ¹Ù
+ÙØ¯ Ø§ÙØ£ÙÙ Ø§Ø³Ù
+Ø§Ø¡ Ø§ÙÙ
+ÙÙØ§Øª ÙØªØžÙØ± ÙÙ "rows" ÙÙ ÙÙÙ
+ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø­Ø¯Ø¯Ø© ÙÙØ°Ù Ø§ÙÙ
+ÙÙØ§Øª0
+</p>
+
+<p>Ø±Ø³Ù
+ Ø§ÙØ¬Ø¯ÙÙ ÙØ¯ ÙØ³ØªØºØ±Ù Ø²Ù
+ÙØ§ÙØ Ø§Ø°Ø§ ØªÙ
+ Ø§Ø®ØªÙØ§Ø± Ù
+Ø¬Ù
+ÙØ¹Ø© Ù
+Ù Ø§ÙÙ
+ÙÙØ§Øª  ÙÙ
+ÙÙÙ Ø§ÙØ§Ø³ØªÙ
+Ø±Ø§Ø± ÙÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ØšÙÙÙ
+Ø§ ÙØ§ÙØ°Ø© "ÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª" Ù
+ÙØªÙØ­Ø©0</p>
+
+<p>Ø¹ÙØ¯Ù
+Ø§ ÙØµØšØ­ Ø§ÙØ­Ø¬Ù
+ ÙØšÙØ±Ø§ÙØ ÙÙ
+ÙÙÙ ØªØ±ØŽÙØ­ Ø¬Ø¯ÙÙ "ÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª" ÙØªØ·ØšÙÙ Ø§ÙÙ
+Ø±ØŽØ­Ø§Øª Ø¹ÙÙ Ø§ÙØ£Ø¹Ù
+Ø¯Ø© - ØšØ§Ø¶Ø§ÙØ© Ø§ÙÙ
+Ø±ØŽØ­Ø§Øª Ø§ÙØ¬Ø¯ÙØ¯Ø© ØªØªØšÙÙ ÙÙØ· Ø§ÙØ§Ø¹Ù
+Ø¯Ø© Ø§ÙÙ
+ØªÙØ§ÙÙØ© Ù
+Ø¹ ÙØ°Ù Ø§ÙÙ
+Ø±ØŽØ­Ø§Øª ÙØ§Ø¶Ø­Ø©  ÙÙ Ø§ÙØŽØ§ØŽØ©0 ÙØ§Ø¹Ø¯Ø§Ø¯  Ø£Ù ØªØ¹Ø¯ÙÙ Ø£Ù Ù
+Ø³Ø­ Ù
+Ø±ØŽØ­Ø Ø§ÙÙØ± Ø¹ÙÙ Ø²Ø± "funnel" Ø§Ø¹ÙÙ Ø§ÙØ¹Ù
+ÙØ¯Ø Ø³ÙÙ ÙØªÙ
+ Ø­Ø«Ù ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª Ø­ÙÙ Ø§ÙÙ
+Ø±ØŽØ­Ø Ø¹ÙØ¯ Ø¥Ø¹Ø¯Ø§Ø¯ Ø§ÙÙ
+Ø±ØŽØ­ ÙØªØºÙØ± ÙÙÙ Ø±Ø§Ø³ Ø§ÙØ¹Ù
+ÙØ¯0
+</p>
+
+<p> ÙØªÙÙØ± Ø§ÙØ­Ø« ÙÙ Ø²Ø± "ØšØ³ÙØ·" ÙØ²Ø± "Ù
+ØªÙØ¯Ù
+"0 Ø²Ø± ØšØ³ÙØ· ÙØžÙØ± Ø§ÙÙ
+Ø±ØŽØ­Ø§Øª Ø§ÙØªÙ ØªØ­ØªÙÙ Ø¹ÙÙ ÙÙÙ
+ Ù
+Ø­Ø¯Ø¯Ø© ÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ( "*" ØªØ¶Ø§ÙÙ  ÙÙ Ø§ÙÙÙÙÙÙ
+) 0 ÙÙ
+ÙÙÙ  Ø§Ø®ØªÙØ§Ø± ÙÙÙ
+ ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©0 Ø²Ø± Ù
+ØªÙØ¯Ù
+  ÙØªÙØ­ ÙÙ  Ù
+Ø®ØªÙÙ  Ø¹Ù
+ÙÙØ§Øª Ø§ÙÙ
+Ø¶Ø§ÙØ§Ø© ÙØ§ÙØªÙ ÙØ¬Øš Ø£Ù ØªØšØ¯Ø£ Øš  ÙØ§ ÙØªØ¶Ù
+Ù         Ø Ø£ÙÙ Ù
+Ù  Ø£Ù Ù
+Ø³Ø§Ù0 Ø§ÙÙÙÙ
+ Ø§ÙÙ
+Ø¶Ø§ÙØ§Ø© ÙÙ
+ÙÙ ØªØ¹Ø¯ÙÙÙØ§ ÙØªÙÙÙ Ø§Ù Ø³ÙØ§Ø³Ù Ø£Ø®Ø±Ù  (Ù
+ØªØ¶Ù
+ÙÙ "*") Ø ÙÙÙ
+ÙÙÙ Ø§Ø®ØªÙØ§Ø± Ù
+Ø§ Ø§Ø°Ø§  ÙØ§ÙØª Ø§ÙÙ
+Ø¶Ø§ÙØ§Ø©  Ø­Ø§ÙØ© ØºÙØ±  Ø­Ø³Ø§Ø³Ø©Ø Ø§Ø®ÙØ±Ø§Ù ÙÙ
+ÙÙÙ ØªØ®ØµÙØµ ØŽØ±Ø· Ø«Ø§Ù ÙÙÙ
+Ø¶Ø§ÙØ§Ø© ÙØ§Ø³ØªØ®Ø¯Ø§Ù
+Ù  ØšØªØ­Ø¯ÙØ¯ Ù
+Ø¯Ù Ù
+Ù Ø§ÙÙÙÙ
+ (  ØšØ§Ø®ØªÙØ§Ø± AND) Ø§Ø³ÙÙ ÙØ°Ù Ø§ÙÙ
+Ø³Ø§Ø­Ø© ÙÙØ¬Ø¯ Ù
+Ø±ØšØ¹  ÙØªÙØ­  ØªØºÙØ± ØªØ±ØªÙØš  Ø§ÙÙØ±Ø² (ØªØµØ§Ø¹Ø¯Ù Ø£Ù ØªÙØ§Ø²ÙÙ)0 Ø§Ø¶ØºØ· Ø¹ÙÙ "ØªØ­Ø¯ÙØ¯ Ù
+Ø±ØŽØ­" Ø¹ÙØ¯ Ø§ÙØ§ÙØªÙØ§Ø¡ ÙØªØ·ØšÙÙ Ø§ÙÙ
+Ø±ØŽØ­ Ø§ÙØ¬Ø¯ÙØ¯ Ø¹ÙÙ Ø§ÙØ¹Ù
+ÙØ¯0 Ø§ÙÙØ± "Ø­Ø°Ù Ù
+Ø±ØŽØ­" ÙØ­Ø°Ù Ø§ÙÙ
+Ø±ØŽØ­ Ø§ÙØ­Ø§ÙÙ0 Ù
+Ø¹  Ù
+ÙØ§Ø­ØžØ© Ø§Ù ØªÙØ§ØµÙÙ Ø§ÙÙ
+Ø±ØŽØ­  ÙÙ
+ÙÙ Ø§Ø³ØªØ¹Ø§Ø¯ØªÙØ§ Ø­ØªÙ Ø¹ÙØ¯  Ù
+Ø³Ø­ Ø§ÙÙ
+Ø±ØŽØ­0
+</p>
+<p>Ù
+Ø«Ø§ÙØ ÙÙØ±Ø² Ø¬Ø¯ÙÙ "ÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª" ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø¹Ù
+ÙØ¯Ø Ø«Ù
+ Ø§Ø®ØªÙØ§Ø± Ø§Ø¹Ø¯Ø§Ø¯ Ø§ÙÙ
+Ø±ØŽØ­ Ø§ÙØ§ÙØªØ±Ø§Ø¶Ù (Ù
+Ø±ØŽØ­ ØšØ³ÙØ· "*") ÙØ§Ø®ØªÙØ§Ø±  Ø§ÙØªØ±ØªÙØš Ø§ÙØªØµØ§Ø¹Ø¯Ù</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/savingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/savingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/savingacollection.htm	(revision 13928)
@@ -0,0 +1,66 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="savingacollection"><font size="5" face="Verdana"><strong>2.2: Ø­ÙØž Ù
+Ø¬Ù
+ÙØ¹Ø©</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙØ³ Ù
+ØªÙ
+Ø§Ø«ÙØ§Ù Ù
+Ø¹ Ø§Ø¹Ø¯Ø§Ø¯ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙØ§Ø³ØªØ®Ø¯Ø§Ù
+ ÙÙ ÙØ±ÙÙØ³ØªÙÙ   (see <a href="producingthecollection.htm">Ø¥ÙØªØ§Ø¬ Ù
+Ø¬Ù
+ÙØ¹Ø©</a>).</p>
+
+<p>ÙØªÙÙÙ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ Ø­Ù
+Ø§ÙØ© Ø¹Ù
+ÙÙ ØšØ­ÙØžÙ Ø¹ÙØ¯ Ø§ÙØ®Ø±ÙØ¬ Ù
+Ù Ø§ÙØšØ±ÙØ§Ù
+Ø¬ Ø£Ù ØªØ­Ù
+ÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø© Ø£Ø®Ø±Ù0</p>
+
+<p> ØªØ­ÙØž Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª ÙÙ Ù
+Ø¬ÙØ¯ "collect" Ø¶Ù
+Ù ØªØ«ØšÙØª ÙØ±ÙÙØ³ØªÙÙ ÙØªØ³Ù
+Ù ØšØ§Ø³Ù
+ ÙØµÙØ± Ù
+Ù Ø§Ø³Ù
+ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 ØªØ­ÙØž Ø§ÙÙØ«Ø§ØŠÙ ÙÙ Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙÙØ±Ø¹Ù "import"  ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª  ØªØ­ÙØž ÙÙØ§ Ø£ÙØ¶Ø§Ù  ÙÙ Ù
+ÙÙ "metadata.xml" Ù
+Ø¹ÙÙÙ
+Ø§Øª Ø§ÙØªÙÙÙÙ ØªØ­ÙØž ÙÙ Ù
+ÙÙ "collect. Cfq " ÙÙ Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙÙØ±Ø¹Ù etc." ØªØ­ÙØž ØšØ¹Ø¶ Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª ÙÙ Ù
+ÙÙ ØšØ§Ø³Ù
+ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØšØ§Ù
+ØªØ¯Ø§Ø¯ Ù
+ÙÙ "col"
+</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/searchindexes.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/searchindexes.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/searchindexes.htm	(revision 13928)
@@ -0,0 +1,125 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="searchindexes"><font size="5" face="Verdana"><strong>6.3: ÙØŽØ§ÙØ§Øª Ø§ÙØšØ­Ø«</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p> ØªØ­Ø¯Ø¯ Ø§ÙÙØŽØ§ÙØ§Øª Ù
+Ø§ÙÙ Ø£Ø¬Ø²Ø§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙØ§ØšÙØ© ÙÙØšØ­Ø«0 ÙØŽØ±Ø­  ÙÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ÙÙÙÙØ© Ø§Ø¶Ø§ÙØ© ÙØ­Ø°Ù ÙØªØ¹ÙÙÙ ÙØŽØ§Ù Ø§ÙØªØ±Ø§Ø¶Ù ØªØ­Øª "Design" tab, click "Search Indexes".</p>
+
+<p>ÙÙ Ø§ÙØ¬Ø²Ø¡ Ø§ÙØ£ÙÙ
+Ù  Ø§Ø¹ÙÙ ÙØ§ÙØªÙ"Search Indexes" ØªØ¹Ø±Ø¶ Ù
+Ø¹ÙÙÙ
+Ø§Øª Ø­ÙÙ Ø§ÙÙ
+ÙØŽÙ Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+ Ø­Ø§ÙÙØ§Ù ØšÙØ§Ø³Ø·Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 ÙÙ
+ÙÙ ØªØºÙÙØ± ÙØ°Ø§ ØšÙÙØ±"Change...". ØªØžÙØ± ÙÙ ÙØ§ÙØ°Ø© ØªØªØ¶Ù
+Ù ÙØ§ØŠÙ
+Ø© Ù
+Ù Ø§ÙØ®ÙØ§Ø±Ø§Øª Lucene, MGPP, MG Ø§ÙØªØºÙÙØ± ÙÙØ§ ÙØ€Ø«Ø± ÙÙ ÙÙÙÙØ© ØšÙØ§Ø¡ Ø§ÙÙØŽØ§ÙØ§Øª ÙÙØžÙÙÙØ© Ø§ÙØšØ­Ø«0</p>
+
+<p>ØªØžÙØ± ÙÙ ÙØ§ØŠÙ
+Ø© "Assigned Indexes" Ø§ÙÙØŽØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø© ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0</p>
+
+<p>ÙØ§Ø¶Ø§ÙØ© ÙØŽØ§ÙØ Ø§ÙÙØ±"New Index".... ØªØžÙØ± ÙÙ ÙØ§ØŠÙ
+Ø© ØšØ§ÙÙ
+ØµØ§Ø¯Ø± Ø§ÙØªÙ ØªØªØ¶Ù
+Ù ÙØµ  ÙÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø§Ù Ø§ÙÙ
+ØµØ§Ø¯Ø± Ø§ÙØªÙ ØªÙØ¯ ØªÙØŽÙÙÙØ§0  Ø²Ø±"Select All" and "Select None" ÙÙÙÙ
+Ø§Ù ØšØªØ£ØŽÙØ± Ø£Ù ÙÙØµ ØªØ§ØŽÙØ± ÙÙ Ø§ÙØ¹ÙØ§ØµØ± ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø©0 Ø¹ÙØ¯  ØªØ¹Ø±ÙÙ  Ø§ÙÙØŽØ§ÙØ§ØªØ Ø£ÙÙØ±"Add Index"ÙØ§Ø¶Ø§ÙØªÙØ§ Ø¥ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0  ØªØµØšØ­ "Add Index" ÙØŽØ·Ø© ÙÙØ· ÙÙ Ø­Ø§ÙØ©  Ø§Ù Ø§ÙØ¥Ø¹Ø¯Ø§Ø¯ ÙØµÙ ÙØŽØ§Ù Ø¬Ø¯ÙØ¯ ÙÙ
+ ÙØ¹ÙÙ Ù
+Ù ÙØšÙ ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© </p>
+
+<p>ØšØ§ÙÙØ³ØšÙ ÙÙØŽØ§ÙØ§Øª  MG ØªØ­ØªØ§Ø¬ Ø£ÙØ¶Ø§Ù ÙØ§Ø®ØªÙØ§Ø± qranularity Ø§ÙÙØŽØ§Ù Ù
+Ø³ØªØ®Ø¯Ù
+Ø§Ù ÙØ§ØŠÙ
+Ø©"Indexing level:" . </p>
+
+<p>ØšØ§ÙÙØ³ØšØ© ÙÙØŽØ§ÙØ§Øª MGPP, Lucene
+Ø§ÙÙ
+Ø³ØªÙÙØ§Øª  Ø§ÙÙ
+Ø­ØªÙ
+ÙØ©  ØªØ¹Ø±Ø¶ ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙØ±ØŠÙØ³ÙØ©"Search Indexes" ÙÙÙ
+ÙÙ Ø§Ø¶Ø§ÙØªÙØ§ ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØšØªØ£ØŽÙØ± Ù
+Ø±ØšØ¹Ø§Øª Ø§ÙÙØ­Øµ0</p>
+
+<p>ÙÙØ¬Ø¯  ÙØŽØ§Ù Ø®Ø§Øµ Øš Lucene, MGPP ÙÙÙ ÙØŽØ§Ù allhelds" ÙØªÙØ­ Ø§ÙØšØ­Ø« ÙÙ Ø§ÙÙØŽØ§ÙØ§Øª ØšØ¯ÙÙ Ø§ÙØ­ÙØ¬Ù ÙØªØ­Ø¯ÙØ¯ ÙØŽØ§Ù Ù
+ÙÙØµÙ ÙØ­ØªÙÙ ÙÙ Ø§ÙÙ
+ØµØ§Ø¯Ø±0 ÙØ§Ø¶Ø§ÙØ© ÙØ°Ø§ Ø§ÙÙØŽØ§Ù Ø Ø£ÙØ­Øµ "Add combined searching over all assigned indexes (allfields)"  ÙÙÙ
+  ØšØªØ£ØŽÙØ±Ù  Ø§ÙÙ
+Ø±ØšØ¹ ÙØ§ÙÙØ±"Add Index".</p>
+
+<p>ØšØ§ÙÙØ³ØšØ© ÙÙØŽØ§ÙØ§Øª MGPP,Luane Ø ÙØªÙÙØ± Ø²Ø±"Add All" ÙÙ
+Ø®ØªØµØ± ÙØ§Ø¶Ø§ÙØ© ÙÙ ÙØ§ØµÙØ§Øª  Ø§ÙØšÙØ§ÙØ§Øª ÙØ§ÙÙØµ ÙÙØŽØ§ÙØ§Øª ÙØ±Ø¯ÙØ©</p>
+
+<p>ÙØªØ¹Ø¯ÙÙ  ÙØŽØ§ÙØ  ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù ÙØ§ÙÙØ± "Edit Index".  ÙØªÙÙØ± Ù
+Ø±ØšØ¹ Ø­ÙØ§Ø± ÙØ±Ø¯Ù Ø¥ÙÙ "New Index" one is shown. </p>
+
+<p>ÙØ­Ø°Ù  ÙØŽØ§ÙØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù Ù
+Ù ÙØ§ØŠÙ
+Ø© Ø§ÙÙØŽØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ù"Remove Index".</p>
+
+<p>ØªØ±ØªÙØš Ø§ÙÙØŽØ§ÙØ§Øª ÙÙ ÙØ§ØŠÙ
+Ø© Ø§ÙÙØŽØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø©Ø ÙÙ ÙÙØ³ Ø§ÙØªØ±ØªÙØš Ø§ÙÙ
+ØªØšØ¹ ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© ÙÙ ØµÙØ­Ø© Ø§ÙØšØ­Ø«0 Ø§Ø³ØªØ®Ø¯Ù
+"Move Up" and "Move Up" ÙØªØºÙÙØ± ÙØ°Ø§ Ø§ÙØªØ±ØªÙØš0</p>
+
+<p> Ø§ÙÙØŽØ§Ù Ø§ÙØ°Ù ØªÙ
+ Ø§Ø®ØªÙØ§Ø±Ù ÙØ§ÙØªØ±Ø§Ø¶Ù ÙÙ ØµÙØ­Ø© Ø§ÙØšØ­Ø« ÙØ³Ù
+Ù "Ø§ÙÙØŽØ§Ù  Ø§ÙØ§ÙØªØ±Ø§Ø¶Ù" ÙØªÙ
+  ØªÙ
+ÙØ² Ø§ÙÙØŽØ§Ù  Ø§ÙØ§ÙØªØ±Ø§Ø¶Ù Øš "(ÙØŽØ§Ù Ø§ÙØªØ±Ø§Ø¶Ù" ÙÙ ÙØ§ØŠÙ
+Ø© "Ø§ÙÙØŽØ§ÙØ§Øª  Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø©"0 Ø§Ø°Ø§ ÙÙ
+ ÙØªÙ
+  ØªØ¹ÙÙÙ ÙØŽØ§Ù Ø§ÙØªØ±Ø§Ø¶Ù ÙØ§Ù Ø§ÙÙØŽØ§Ù Ø§ÙØ£ÙÙ ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø© ÙØªÙ
+ Ø§Ø³ØªØ®Ø¯Ø§Ù
+Ù ÙÙØŽØ§Ù Ø§ÙØªØ±Ø§Ø¶Ù0</p>
+
+<p>Ø§ÙØ§Ø³Ù
+Ø§Ø¡ Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+Ø© ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© ÙÙ
+ÙÙ Ø§Ø¹Ø¯Ø§Ø¯ÙØ§ ÙÙ "Search" Ø¬Ø²Ø¡Ø§Ù Ù
+Ù ÙØ§ÙØªÙ "Format"  (see <a href="searchmetadatasettings.htm">ØšØ­Ø«</a>).</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/searchmetadatasettings.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/searchmetadatasettings.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/searchmetadatasettings.htm	(revision 13928)
@@ -0,0 +1,40 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="searchmetadatasettings"><font size="5" face="Verdana"><strong>8.3: ØšØ­Ø«</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙØŽØ±Ø­ ÙÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ÙÙÙÙØ© Ø¹Ø±Ø¶ Ø§ÙÙØµ ÙÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© ÙÙ ØµÙØ­Ø© Ø§ÙØšØ­Ø« &ndash; ØªØ­Øª tab "ÙØ³Ù Ø¹Ø±Ø¶" Ø§ÙÙØ± "ØšØ­Ø«"0</p>
+
+<p>ÙØªØ¶Ù
+Ù ÙØ°Ø§ Ø§ÙØ®ØšØ± Ø¬Ø¯ÙÙ ÙÙ ÙØŽØ§Ù ØšØ­Ø«Ø ÙÙ
+Ø³ØªÙÙ Ø§ÙØªÙØŽÙÙ (ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª MGPP Ø£Ù Lucene)  ÙÙØ§ ÙÙ
+ÙÙÙ Ø§Ø¯Ø®Ø§Ù Ø§ÙÙØµ Ø§ÙØ°Ù ÙØ³ØªØ®Ø¯Ù
+ ÙÙ
+ØµØ·ÙØ­ ØšØ­Ø« ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© ÙÙ ØµÙØ­Ø© Ø§ÙØšØ­Ø«- ÙØªÙØ­ ÙÙ ÙØ°Ø§ Ø§ÙØ­ÙØ² ØªØ­Ø¯ÙØ¯ Ø§ÙÙØµ ÙÙ ÙØºØ© ÙØ§Ø­Ø¯Ø© ÙØªØ±Ø¬Ù
+Ø© Ø§ÙÙØµ Ù
+Ù Ø§ÙÙØºØ© Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+Ø© Ø­Ø§ÙÙØ§Ù ÙÙ GLIØ¥ÙÙ Ø§ÙÙØºØ© Ø§ÙØ£Ø®Ø±Ù- Ø§Ø³ØªØ®Ø¯Ù
+ ØªØ±Ø¬Ù
+Ø© ÙØµ ÙÙÙ Ø¬Ø²Ø¡ Ù
+Ù Ù
+ØŽÙØ¯ ÙØ³Ù Ø¹Ø±Ø¶ (see <a href="translatetext.htm">ØªØ±Ø¬Ù
+Ù ÙØµ</a>).</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/selectingmetadatasets.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/selectingmetadatasets.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/selectingmetadatasets.htm	(revision 13928)
@@ -0,0 +1,204 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="selectingmetadatasets"><font size="5" face="Verdana"><strong>5.2: Ø¥Ø®ØªÙØ§Ø± Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¹Ø±ÙØ© Ù
+Ù ÙØšÙ ØªØ¹Ø±Ù ØšÙ "Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª"0 Ù
+Ø«Ø§ÙØ Ù
+Ø¹ÙØ§Ø± Ø¯ØšÙÙ ÙÙØ± ÙÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª0 Ø¹ÙØ¯ Ø¥Ø¶Ø§ÙØ© Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª ÙÙ
+Ø¬Ù
+ÙØ¹ØªÙ ØªØµØšØ­  Ø¹ÙØ§ØµØ±Ù Ù
+ØªØ§Ø­Ø© ÙÙØ§Ø®ØªÙØ§Ø±0 ÙÙ
+ÙÙÙ Ø§Ø®ØªÙØ§Ø± Ø£ÙØ«Ø± Ù
+Ù Ù
+Ø¹ÙØ§Ø± ÙÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§ØªØ ÙÙ
+ÙØ¹ ØªØ¶Ø§Ø±Øš Ø§ÙØ§Ø³Ù
+Ø§Ø¡Ø ÙÙØ­Ø¯ Ù
+Ø¹Ø±Ù ÙØµÙØ± ÙØšÙ Ø§Ø³Ù
+ Ø§ÙØ¹ÙØµØ± ÙÙ
+Ø«Ø§Ù Ù
+Ø¹Ø±ÙÙ Ø¹ÙØµØ± Ù
+Ø¹ÙØ§Ø± Ø¯ØšÙÙ ÙÙØ± ÙÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª  ÙØµØšØ­  "Ù
+Ø€ÙÙ .dc" ØªØ­ÙØž Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙ Ù
+Ø³Ø§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª"Metadata"ÙÙ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ÙÙØ­Ù
+Ù Ø§ÙØ§Ù
+ØªØ¯Ø§Ø¯ "mds."
+</p> 
+
+<p>ØªØªÙ
+ Ø§Ø¶Ø§ÙØ© Ù
+Ø¹ÙØ§Ø± Ø¯ØšÙÙ ÙÙØ± ØšØµÙØ±Ø© Ø§ÙØªØ±Ø§Ø¶ÙØ© Ø¹ÙØ¯ Ø§ÙØŽØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø© Ø¬Ø¯ÙØ¯Ø©0 ÙÙ
+ÙÙÙ  ØªØºÙÙØ± Ø£Ù Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+Ø³ØªØ®Ø¯Ù
+ ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØšØ§ÙÙÙØ± Ø¹ÙÙ Ø²Ø± "Ø§Ø¯Ø§Ø±Ø© Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª" ØªØ­Øª ØŽØ¬Ø±Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙ Ù
+ØŽÙØ¯ Ø¥Ø«Ø±Ø§Ø¡0 ÙÙÙØ¯ ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ ÙØžÙÙØ± ÙØ§ÙØ°Ø© Ø¬Ø¯ÙØ¯Ø© ÙØ§Ø¯Ø§Ø±Ø© Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0
+</p>
+
+<p> ÙØ§ØŠÙ
+Ø© "Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø©" ØªØ¹Ø±Ø¶ Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+Ø© ÙÙ Ø§ÙÙ
+Ø¬ÙØ¹Ø© Ø­Ø§ÙÙØ§Ù0</p>
+
+<p> ÙØ§Ø³ØªØ®Ø¯Ø§Ù
+ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø¢Ø®Ø± Ù
+Ø¹ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©Ø Ø§ÙÙØ± "Ø§Ø¶Ø§ÙØ©00" ØªØžÙØ± ÙØ§ØŠÙ
+Ø© ØªÙØ¶Ø­ Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØ§ÙØªØ±Ø§Ø¶ÙØ© Ø§ÙØªÙ ÙØ¹Ø±ÙÙØ§ GLI ÙØ§Ø¶Ø§ÙØ©  ÙØ§Ø­Ø¯ Ù
+ÙÙØ§Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø© ÙØ§ÙÙØ± "Ø§Ø¶Ø§ÙØ©" Ø§Ø°Ø§ ÙÙ
+Øª ØšØªØ¹Ø±ÙÙ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø®Ø§ØµØªÙØ ÙÙ
+ÙÙÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+ Ø²Ø± "ØªØµÙØ­" ÙØªØ­Ø¯ÙØ¯ Ù
+ÙÙØ¹ Ø§ÙÙ
+ÙÙ ÙÙ ÙØžØ§Ù
+ Ø§ÙÙ
+ÙÙØ§Øª0
+</p>
+
+<p>ÙØ§ÙØŽØ§Ø¡ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø¬Ø¯ÙØ¯Ø Ø§ÙÙØ± "Ø¬Ø¯ÙØ¯"Ø ÙØ€Ø¯Ù ÙØ°Ø§ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ Ø¥ÙÙ Ø¥Ø·ÙØ§Ù Ù
+Ø­Ø±Ø± ÙØ±ÙÙØ³ØªÙÙ ÙÙ
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª GEMS ØªØžÙØ± ÙØ§ÙØ°Ø© ØªØ­Ø«Ù ÙØªØ­Ø¯ÙØ¯ Ø§ÙØ§Ø³Ù
+Ø Ø§Ø³Ù
+ Ù
+Ø³Ø§Ø­Ø© ÙØ§ÙÙØ­Ø¯Ø©0 ÙÙ
+ÙÙÙ Ø§ÙØ¶Ø§Ù Ø§Ø®ØªÙØ§Ø± Ù
+Ø¹ÙØ§Ø± ÙØªØ£Ø³ÙØ³ Ø§ÙÙ
+Ø¹ÙØ§Ø± Ø§ÙØ¬Ø¯ÙØ¯ Ø¹ÙÙÙ0 ÙÙ ÙØ°Ù Ø§ÙØ­Ø§ÙØ© Ø³ÙÙ ØªØ¶Ù
+Ù ÙÙ Ø§ÙØ¹ÙØ§ØµØ± Ù
+Ù Ø§ÙÙ
+Ø¹ÙØ§Ø± Ø§ÙÙ
+Ø­Ø¯Ø¯0 Ø§ÙÙØ± "OK" ØªØžÙØ± Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙØ±ØŠÙØ³Ù ÙÙ
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª  Ø§ÙØšÙØ§ÙØ§Øª Ø¥ÙÙ Ø§ÙÙØ³Ø§Ø± ÙØšØ¹Ø¶ Ø§ÙØµÙØ§Øª ÙÙÙ
+Ø¹ÙØ§Ø± ÙÙ
+ÙÙØ§ÙØ Ø§Ø°Ø§ ØªÙ
+ ØªØ£Ø³ÙØ³ Ø§ÙÙ
+Ø¹ÙØ§Ø± Ø¹ÙÙ Ù
+Ø¹ÙØ§Ø± Ù
+ÙØ¬ÙØ¯ ÙØ¹Ø±Ø¶ Ø¹ÙØµØ± Ø£Ù Ø¹ÙØ§ØµØ±0
+</p>
+
+<p>ÙØ§Ø¶Ø§ÙØ© Ø¹ÙØµØ± Ø¬Ø¯ÙØ¯Ø Ø§Ø¶ØºØ· Ø§ÙØ²Ø± Ø§ÙØ§ÙÙ
+Ù ÙÙ Ø§ÙÙ
+Ø¹ÙØ§Ø± ÙÙÙ
+ ØšØ¥Ø®ØªÙØ§Ø±  "Ø§Ø¶Ø§ÙØ© Ø¹ÙØµØ±" - ÙØ§Ø¶Ø§ÙØ© Ø¹ÙØµØ± ÙØ±Ø¹Ù Ø¬Ø¯ÙØ¯Ø Ø§Ø¶ØºØ· Ø§ÙØ²Ø± Ø§ÙØ§ÙÙ
+Ù  ÙÙÙ
+  ØšØ§Ø®ØªÙØ§Ø± "Ø§Ø¶Ø§ÙØ© Ø¹ÙØµØ± ÙØ±Ø¹Ù" ÙÙ
+ÙÙ Ø¥ÙØºØ§Ø¡ "Ø¹ÙØµØ± (ÙØ±Ø¹Ù)" Ù
+Ù ÙØ§ØŠÙ
+Ø© Ø§ÙØ²Ø± Ø§ÙØ§ÙÙ
+Ù. </p>
+
+<p> ØªØ¬Øš Ù
+ÙØ§Ø­ØžØ© Ø§Ù Ù
+Ø­Ø±Ø± ÙØ±ÙÙØ³ØªÙÙ ÙÙ
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙ
+ÙÙ ØªØŽØºÙÙÙ Ù
+Ø³ØªÙÙØ§Ù Ø¹Ù GLIØ ØšØ§Ø®ØªÙØ§Ø±Ù Ù
+Ù ÙØ§ØŠÙ
+Ø© Ù
+Ù ÙØ§ØŠÙ
+Ø© Ø§ÙØšØ¯Ø§ÙØ© ÙÙØ±ÙÙØ³ØªÙÙ Ø£Ù ØšØªØŽØºÙÙ gens.sh Ø£Ù gems.bat ÙÙ Ù
+Ø¬ÙØ¯ GLI ÙÙ ØªØ«ØšÙØª  ÙØ±ÙÙØ³ØªÙÙ0 </p>
+
+<p>Ø£Ø­ÙØ§ÙØ§Ù ÙÙÙÙ Ø§Ø³Ù
+ Ø§ÙÙ
+Ø³Ø§Ø­Ø© Ù
+ØŽØªØ±ÙØ§Ù ØšÙÙ Ù
+ÙØ§Ø¯ÙÙ ÙÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª0 Ù
+Ø«Ø§Ù Dultin lore Ù Qualifiel Dubin lore ÙÙØ§Ø«ÙØ§Ù ÙØ³ØªØ®Ø¯Ù
+Ø§Ù Ø§Ø³Ù
+ Ø§ÙÙ
+Ø³Ø§Ø­Ø© "dc."  - ÙÙØ§ ÙÙ
+ÙÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+ Ù
+Ø«Ù ÙØ°Ù Ø§ÙÙ
+Ø¹Ø§ÙÙØ± ÙÙ ÙÙØª ÙØ§Ø­Ø¯ Ù
+Ù Ù
+Ø¬Ù
+ÙØ¹Ø© ÙØ§Ø­Ø¯Ø© ÙØ³ÙÙ ÙØžÙØ± ÙÙ  ØªØ­Ø°ÙØ±Ø Ø§Ø°Ø§ Ù
+Ø¶ÙØª ÙØ¯Ù
+Ø§Ù Ø³ÙÙ ÙØªÙ
+ Ø­Ø°Ù Ø§ÙÙ
+Ø¹ÙØ§Ø± Ø§ÙÙ
+ÙØ¬ÙØ¯ ÙØ§Ø¶Ø§ÙØ©  ØªØ§ÙØ¬Ø¯ÙØ¯0 ØªØªÙ
+ Ø§Ø¶Ø§ÙØ© ÙÙÙ
+ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø© Ø§ÙÙ Ø§ÙÙ
+Ø¹ÙØ§Ø± Ø§ÙØ¬Ø¯ÙØ¯ ÙØªÙÙÙØ± Ø§ÙØ¹ÙØ§ØµØ± Ø§ÙØªÙ  Ø²Ø§ÙØª Ù
+ÙØ¬ÙØ¯Ø©0</p>
+
+<p> ØšØ¥Ø³ØªØ®Ø¯Ø§Ù
+ GEMS ÙÙ
+ÙÙÙ ØªØ¹Ø¯ÙÙ Ù
+Ø¹Ø§ÙÙØ± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+ÙØ¬ÙØ¯Ø© ÙÙ
+Ø§ ÙÙ
+ÙÙ Ø§ÙØŽØ§Ø¡ Ù
+Ø¹Ø§ÙÙØ± Ø¬Ø¯ÙØ¯Ø© - ÙÙØ± "ØªØ¹Ø¯ÙÙ" ÙØ€Ø¯Ù Ø¥ÙÙ Ø§Ø·ÙØ§Ù GEMS" ÙÙØªØ­ Ù
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø­Ø¯Ø¯0 Ø¹ÙØ¯ Ø§ÙØªÙØ§Ø¡ ØªØ¹Ø¯ÙÙ Ø§ÙÙ
+Ø¹ÙØ§Ø± (ÙÙ
+Ø§ ÙÙ Ù
+ÙØµÙÙ Ø£Ø¹ÙØ§Ù) ÙÙ
+ ØšØ­ÙØžÙ ÙÙ ÙØ§ØŠÙ
+Ø©--&gt;Ù
+ÙÙ --&gt; Ø­ÙØž ÙØ§ØºÙØ§Ù GEMS.
+</p>
+
+<p>Ø§Ø°Ø§ ÙÙ
+ ÙØªÙ
+ ØªØ¹Ø¯ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ù
+Ø­ØªØ§Ø¬Ù ÙÙ
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§ØªØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±Ù  ÙØ§Ø¶ØºØ· "Ø­Ø°Ù" - Ø§Ø°Ø§ ÙØ§Ù ÙØ¯ÙÙ Ø§Ù ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª ÙÙ Ø¹ÙØ§ØµØ±Ø ÙØ³ÙÙ ÙØªÙ
+ Ø§Ø³ØªÙØ³Ø§Ø±Ù Ø­ÙÙ ÙÙÙÙØ© Ø§ÙØªØµØ±Ù Ù
+Ø¹ ÙØ°Ù Ø§ÙÙØ§ØµÙØ§Øª Ø¹ÙØ¯ ÙØªØ­ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©  ÙÙ Ø§ÙÙ
+Ø±Ø© Ø§ÙØªØ§ÙÙØ©0</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/startingoff.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/startingoff.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/startingoff.htm	(revision 13928)
@@ -0,0 +1,25 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="startingoff"><font size="5" face="Verdana"><strong>2: Ø§ÙØšØ¯Ø§ÙØ©</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙØºØ·Ù ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ÙÙÙÙØ© Ø¥ÙØŽØ§Ø¡Ø ØªØ­Ù
+ÙÙ ØØ­ÙØž Ù Ø¥ÙØºØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª.</p>
+
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/thecreateview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/thecreateview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/thecreateview.htm	(revision 13928)
@@ -0,0 +1,60 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="thecreateview"><font size="5" face="Verdana"><strong>7.1: Ù
+ØŽÙØ¯ Ø¥ÙØŽØ§Ø¡</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙØ³ØªØ®Ø¯Ù
+ Ù
+ØŽÙØ¯ Ø§ÙØŽØ§Ø¡ ÙÙ Ø§ÙØŽØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØšØªØŽØºÙÙ Ù
+ÙÙØ§Øª ÙØ±ÙÙØ³ØªÙÙ ÙØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙÙØ§Ù ÙÙÙ
+Ø¹ÙÙÙ
+Ø§Øª Ø§ÙØªÙ ÙÙ
+Øª ØšØªÙÙÙØ±ÙØ§0 Ø§Ø¯Ø®Ù Ù
+ØŽÙØ¯ Ø§ÙØ§ÙØŽØ§Ø¡ ØšØ§ÙÙÙØ± Ø¹ÙÙ tab "Ø§ÙØŽØ§Ø¡"0</p>
+
+<p>ÙØšØ¯Ø£ Ø§Ø¬Ø±Ø§Ø¡ ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØšØ§ÙÙÙØ± Ø¹ÙÙ "ØšÙØ§Ø¡ Ù
+Ø¬Ù
+ÙØ¹Ø©"- ØªØ­Ø¯ÙØ¯ Ø§ÙÙØªØ±Ø© Ø§ÙØ²Ù
+ÙÙØ© ÙØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙØ¹ØªÙ
+Ø¯ Ø¹ÙÙ Ø­Ø¬Ù
+ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙØ¹Ø¯Ø¯ Ø§ÙÙØŽØ§ÙØ§Øª Ø§ÙÙ
+ØšÙÙÙ (ÙØ¯ ØªÙÙÙ Ø³Ø§Ø¹Ø§Øª ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙØ¶Ø®Ù
+Ø©) ÙØŽÙØ± ØªØ·ÙØ± Ø¹Ù
+ÙØ¯ ØªØ·ÙØ± Ø§Ø¬Ø±Ø§Ø¡ Ø§ÙØšÙØ§Ø¡ Ø¥ÙÙ Ù
+Ø¯Ù Ø§ÙØ¬Ø²Ø¡ Ø§ÙØ°Ù Ø§ÙØªÙÙ .ÙØ¥ÙØºØ§Ø¡ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ ÙÙ Ø§Ù Ù
+Ø±Ø­ÙØ©Ø Ø§ÙÙØ± "Ø§ÙØºØ§Ø¡ Ø§ÙØšÙØ§Ø¡"0</p>
+
+<p>Ø§Ø°Ø§ ØªÙ
+ ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØšÙØ¬Ø§Ø­ Ø ÙØ§Ù ÙÙØ± "Ø¹Ø±Ø¶ Ù
+Ø¬Ù
+ÙØ¹Ø©" Ø³ÙÙ ÙØ·ÙÙ Ù
+ØªØµÙØ­ ÙØš ÙØ¹Ø±Ø¶ ØµÙØ­Ø© Ù
+ÙÙØ¹ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/thedesignview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/thedesignview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/thedesignview.htm	(revision 13928)
@@ -0,0 +1,68 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="thedesignview"><font size="5" face="Verdana"><strong>6.1: Ù
+ØŽÙØ¯ Ø§ÙØªØµÙ
+ÙÙ
+</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p> ÙØ¹Ø±ÙÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ØšÙ
+ØŽÙØ¯ Ø§ÙØªØµÙ
+ÙÙ
+ ÙÙØŽØ±Ø­ ÙÙ ÙÙÙÙØ© Ø§ÙØªØ¬ÙØ§Ù ØšÙÙ Ù
+Ø®ØªÙÙ Ø§ÙÙ
+ØŽØ§ÙØ¯ Ø¶Ù
+Ù ÙØ°Ù Ø§ÙÙØ§ØŠÙ
+Ø©0</p>
+
+<p>ØšÙØ§Ø³Ø·Ø© ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙØ ÙÙ
+ÙÙÙ  ØªÙÙÙÙ  ÙÙÙÙØ© Ù
+Ø¹Ø§ÙØ¬Ø© Ø§ÙÙØ«Ø§ØŠÙ ÙÙÙÙÙØ© Ø§ØªØ§Ø­Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙÙ
+Ø³ØªÙÙØ¯ Ø Ø®ÙØ§Ø±Ø§Øª Ø§ÙØªÙÙÙÙ Ù
+ÙØ³Ù
+Ø© Ø¥ÙÙ Ø£ÙØ³Ø§Ù
+ Ù
+Ø®ØªÙÙØ©  ÙÙ Ù
+ÙÙØ§ ÙØªØ¹ÙÙ ØšÙ
+Ø±Ø­ÙØ© Ù
+Ø¹ÙÙØ© Ù
+Ù ØªÙØ¶ÙØš Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0</p>
+
+<p> ÙØ³Ø§Ø±Ø§Ù ØªÙØ¬Ø¯ ÙØ§ØŠÙ
+Ø© ØšÙ
+Ø®ØªÙÙ Ø§ÙÙ
+ØŽØ§ÙØ¯0 ØªÙØ¬Ø¯ ÙÙ
+ÙÙØ§Ù Ø¶ÙØ§ØšØ· Ø§ÙØªØ­ÙÙ
+ Ø§ÙÙ
+ØªØ¹ÙÙØ© ØšØ§ÙÙ
+ØŽÙØ¯ Ø§ÙØ¬Ø§Ø±Ù0 ÙØªØºÙÙØ± ÙØ§Ø­Ø¯  Ø§ÙÙØ± Ø¹ÙÙ Ø§Ø³Ù
+ ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø©0</p>
+
+<p>ÙÙÙÙ
+ Ù
+ØµØ·ÙØ­Ø§Øª ÙÙ
+Ø±Ø§Ø­Ù ØªØµÙ
+ÙÙ
+ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 Ø§ÙØ±Ø£ Ø§ÙÙØµÙÙÙ Ø§ÙØ£ÙÙ ÙØ§ÙØ«Ø§ÙÙ Ù
+Ù Ø¯ÙÙÙ ÙØ±ÙÙØ³ØªÙÙ ÙÙÙ
+Ø·ÙØ±ÙÙ0</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/theenrichview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/theenrichview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/theenrichview.htm	(revision 13928)
@@ -0,0 +1,135 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="theenrichview"><font size="5" face="Verdana"><strong>5.1: Ù
+ØŽÙØ¯ Ø¥Ø«Ø±Ø§Ø¡</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Ø§Ø³ØªØ®Ø¯Ù
+ Ù
+ØŽÙØ¯ Ø¥Ø«Ø±Ø§Ø¡"Enrich" ÙØªØ¹ÙÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙØ«Ø§ØŠÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙ ØšÙØ§ÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª - ØªØ­Ø¯ÙØ¯Ø§Ù Ø§ÙØ¹ÙÙØ§ÙØ Ø§ÙÙ
+Ø€ÙÙØ ØªØ§Ø±ÙØ® Ø§ÙØ¥ÙØŽØ§Ø¡ ÙÙÙØ°Ø§Ø Ø§Ù ÙØ§ØµÙØ© ØšÙØ§ÙØ§Øª ØªØªÙÙÙ Ù
+Ù Ø¬Ø²ØŠÙÙ "Ø§ÙØ¹ÙØµØ±""Element" ÙØªØ­Ø¯ÙØ¯ ØµÙØ© Ø§ÙØ¹ÙØµØ± (Ù
+Ø«ÙØ§Ù Ø§ÙÙ
+Ø€ÙÙ) Ù"Ø§ÙÙÙÙ
+Ø©""Value" ÙØšÙØ§Ù Ù
+Ø­ØªÙÙ Ø°ÙÙ Ø§ÙØ¹ÙØµØ± (Ø§Ø³Ù
+ Ø§ÙÙ
+Ø€ÙÙ)0</p>
+
+<p> ÙÙØ¬Ø¯ ÙØ³Ø§Ø± Ù
+ØŽÙØ¯ "Enrich"ØŽØ¬Ø±Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 ÙÙ ÙØžØ§ØŠÙ Ø§ÙØ²Ø± Ø§ÙØ§ÙÙ
+Ù Ù
+ØªØ§Ø­Ø© ÙØŽØ¬Ø±Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ù
+Ù Ù
+ØŽÙØ¯ "Gather"ÙÙÙ Ù
+ØªØ§Ø­Ø© ÙÙØ§ Ø£ÙØ¶Ø§Ù0 ÙÙ Ø§ÙØ¬Ø§ÙØš Ø§ÙØ§ÙÙ
+Ù Ø¬Ø¯ÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙØªÙ ØªÙØ¶Ø­ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙÙ
+ÙÙØ§Øª Ø£Ù Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª ÙÙ ØŽØ¬Ø±Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 ØªÙ
+Øª ØªØ³Ù
+ÙØ© Ø§ÙØ§Ø¹Ù
+Ø¯Ø© ØšØ§ÙÙÙÙ Ø§ÙØ±Ù
+Ø§Ø¯Ù ÙÙ Ø§ÙØ§Ø¹ÙÙ0 ÙÙ
+ÙÙ Ø§ÙØªÙ
+Ø¯ÙØ¯ Ø£Ù Ø§ÙØªÙÙÙØµ ØšØ³Ø­Øš Ø§ÙØ®Ø· Ø§ÙÙØ§ØµÙ0 Ø§Ø°Ø§ Ø«Ù
+ Ø§Ø®ØªÙØ§Ø± Ù
+Ø¬Ù
+ÙØ¹Ø© Ù
+ÙÙØ§Øª ÙØŽÙØ± Ø§ÙÙØµ Ø§ÙØ£Ø³ÙØ¯ Ø¥ÙÙ ÙÙÙ
+Ø© Ù
+ØŽØªØ±ÙØ© ØšÙÙ Ø§ÙØ¹ÙØ§ØµØ± Ø§ÙÙ
+Ø®ØªØ§Ø±Ø© ØšÙÙÙ
+Ø§ ÙØŽÙØ±  Ø§ÙÙØµ Ø§ÙØ±Ù
+Ø§Ø¯Ù Ø¥ÙÙ Ø¹ÙØ³ Ø°ÙÙ0  ØªØ¹Ø¯ÙÙ Ø§ÙÙÙÙÙÙ
+ Ø§ÙØ±Ù
+Ø§Ø¯ÙØ© ÙØ€Ø«Ø± ÙÙØ· ÙÙ Ø§ÙÙØ«Ø§ØŠÙ Ø§ÙØªÙ ÙÙØ§ ÙØ°Ù Ø§ÙÙØ§ØµÙØ§ØªØ Ø£Ù ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ø¬Ø¯ÙØ¯Ø© Ù
+Ø¯Ø®ÙØ© ØªØªÙ
+ Ø§Ø¶Ø§ÙØªÙØ§ Ø¥ÙÙ ÙÙ Ø§ÙÙÙÙ
+ Ø§ÙÙ
+Ø®ØªØ§Ø±Ø©0</p>
+
+<p>ÙØžÙØ± ØšØ¬Ø§ÙØš Ø±Ù
+Ø² Ù
+Ø¬ÙØ¯ ØšØ¹Ø¶ Ù
+Ø¯Ø§Ø®Ù ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙØŽÙØ± ÙØ°Ø§ Ø¥ÙÙ Ø£Ù ÙØ°Ù Ø§ÙÙÙÙ
+ ÙØ¯ ØªÙ
+ ØªØ¶Ù
+ÙÙÙØ§ Ù
+Ù Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙØ£Ø¹ÙÙ (Ø§ÙØ³ÙÙ)Ø ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¶Ù
+ÙÙ ÙØ§ ÙÙ
+ÙÙ Ø­Ø°ÙÙØ§ Ø£Ù ØªØ¹Ø¯ÙÙÙØ§ ÙÙ Ø¥ÙØ§ ÙÙ Ù
+ÙØ·ÙØ© Ø§ÙÙ
+Ø¬ÙØ¯ Ø§ÙØ§Ø¹ÙÙØ Ø­ÙØ« ØªÙ
+ ØªØ¹ÙÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª0
+</p>
+
+<p>Ø§ÙÙÙØ± Ø¹ÙÙ Ø¹ÙØµØ± ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª ÙÙ Ø§ÙØ¬Ø¯ÙÙØ ÙØ¹Ø±Ø¶ Ø§ÙÙÙÙÙÙ
+  Ø§ÙÙ
+ÙØ¬ÙØ¯Ø© ÙØ°ÙÙ Ø§ÙØ¹ÙØµØ± ÙÙ Ù
+Ø³Ø§Ø­Ø©  "ØŽØ¬Ø±Ø© Ø§ÙÙÙÙ
+00""Existing values for ..." Ø§ÙÙ
+ÙØ¬ÙØ¯Ù Ø§Ø³ÙÙ Ø§ÙØ¬Ø¯ÙÙ0  ØªØªÙ
+Ø¯Ø¯ Ø£Ù ØªØªÙÙØµ ØªÙÙ Ø§ÙÙÙÙ
+ ÙÙÙØ§Ù ÙÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø¯Ø®ÙØ© Ù
+Ù ÙØšÙ ÙØ¹ÙØµØ± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±0Ø§ÙÙÙØ± Ø¹ÙÙ Ù
+Ø¯Ø®Ù ÙØ¶Ø¹Ù ØªÙÙØ§ØŠÙØ§Ù ÙÙ ÙÙÙ
+Ø© Ø§ÙØ­ÙÙØ conversly Ø§ÙØ·ØšØ§Ø¹Ù ÙÙ Ø­ÙÙ Ø§ÙÙØµ ØªØ®ØªØ§Ø± Ø§ÙÙØµ Ø§ÙØ°Ù ÙØšØ¯Ø£ ØšÙÙØ³ Ø§ÙØ­Ø±Ù0 Ø§ÙØ¶ØºØ· Ø¹ÙÙ Ù
+ÙØªØ§Ø­ [Tab] ÙÙÙ
+Ù ØªÙÙØ§ØŠÙØ§Ù Ø·ØšØ§Ø¹Ù Ø§ÙÙÙÙ
+Ø© Ø§ÙÙ
+Ø®ØªØ§Ø±Ø©0
+</p>
+
+<p>ÙÙ
+ÙÙ ØªÙØžÙÙ
+ ÙÙÙÙÙ
+ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙÙ ØªØ±ØªÙØš    - ÙÙ
+ÙÙ Ø§Ø¯Ø®Ø§Ù Ø§ÙÙÙÙÙÙ
+  Ø§ÙÙØ±Ù
+ÙÙ ØšØ§Ø³ØªØ®Ø¯Ø§Ù
+ Ø§ÙÙ
+Ø­Ø±Ù "|" ÙÙØµÙ Ø§ÙÙ
+Ø³ØªÙÙØ§Øª- Ù
+Ø«Ø§ÙØ "ÙØ±ÙØª Ø§ÙÙÙØªØŽÙÙÙ |Ø§ÙØ§Ø­Ù
+Ø±| Ø§ÙØ¬ÙÙØ±Ø©| Ø§ÙØ³ØšØ¹Ù" ÙÙØªÙ
+Ø«ÙÙ Ø§ÙÙØ±Ù
+Ù ÙÙØ±ÙØª Ø§ÙÙÙØªØŽÙÙÙØ ÙÙ
+ÙÙ  ÙØ°Ø§ Ù
+Ù ØªØ¬Ù
+ÙØ¹  Ø§ÙÙÙÙÙÙ
+ Ù
+Ø¹Ø§Ù0 ÙÙ
+ÙÙ ØªØ¹ÙÙÙ ÙØ°Ù Ø§ÙÙÙÙÙ
+Ù ÙÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª ÙÙÙ
+ÙÙØ§Øª0
+</p>
+
+<p>ÙØ³ØªØ®Ø±Ø¬ ÙØ±ÙÙØ³ØªÙÙ ØªÙÙØ§ØŠÙØ§Ù ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ù
+Ù Ø§ÙÙØ«Ø§ØŠÙ ÙÙ
+Ø¹ÙØ§Ø± ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+ØšØªØ¯ØŠØ© ØšÙ "ex." ÙÙØ°Ù Ø§ÙÙØ§ØµÙØ§Øª  ØºÙØ± Ù
+ÙØ¹ÙÙ ÙÙØ§ ÙÙ
+ÙÙ ØªØ¹Ø¯ÙÙÙØ§0     </p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/theformatview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/theformatview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/theformatview.htm	(revision 13928)
@@ -0,0 +1,65 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="theformatview"><font size="5" face="Verdana"><strong>8.1: Ù
+ØŽÙØ¯ ÙØ³Ù Ø§ÙØ¹Ø±Ø¶0</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙØ¹Ø±ÙÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ ØšÙ
+ØŽÙØ¯ ÙØ³Ù Ø§ÙØ¹Ø±Ø¶ ÙØŽØ±Ø­ ÙÙ ÙÙÙÙØ© Ø§ÙØªØ¬ÙØ§Ù ØšÙÙ Ø§ÙÙ
+ØŽØ§ÙØ¯ Ø§ÙØªÙ ÙØ­ØªÙÙÙØ§0</p>
+
+<p> ÙÙÙØ± ÙÙ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ Ø¥Ø¹Ø¯Ø§Ø¯ ØªÙ
+ØžÙØ± Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙÙ
+Ø³ØªÙÙØ¯0 ØªÙÙØ³Ù
+ Ø®ÙØ§Ø±Ø§Øª Ø§ÙØ§Ø¹Ø¯Ø§Ø¯ Ø¥ÙÙ Ø£ÙØ³Ø§Ù
+ ÙÙ Ù
+ÙÙØ§ Ù
+ÙØ­Ù ØšÙ Ø§ÙÙØ§Ø¹ Ù
+Ø®ØªÙÙÙ Ù
+Ù Ø§ÙØªÙØµÙØš0</p>
+
+<p>ØªØ¬Ø¯ ÙØ³Ø§Ø±Ø§Ù ÙØ§ØŠÙ
+Ø© ØšØ§ÙÙ
+ØŽØ§ÙØ¯ ÙÙ
+Ù Ø¬ÙØ© Ø§ÙÙÙ
+ÙÙ Ø¹ÙØ§ØµØ± Ø§ÙØªØ­ÙÙ
+ Ø§ÙÙ
+ØªØ¹ÙÙØ© ØšØ§ÙÙ
+ØŽÙØ¯ Ø§ÙØ¬Ø§Ø±Ù0 ÙÙØªØºÙÙØ± Ø¥ÙÙ Ù
+ØŽÙØ¯ Ø¢Ø®Ø± Ø§ÙÙØ± Ø§Ø³Ù
+Ù Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©0</p>
+
+<p>ÙÙØ¬Ø¯ ØªØ­Øª ÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ØŽØ§ÙØ¯ Ø²Ø± "Ø¹Ø±Ø¶ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©" Ø§ÙØªØºÙÙØ± Ø§ÙØ°Ù ØªÙ
+ ÙÙ Ù
+ØŽÙØ¯ ÙØ³Ù Ø§ÙØ¹Ø±Ø¶ ÙÙ Ø§ÙÙ ÙÙ
+ ØªØ¹Ø¯  Ù
+Ø­ØªØ§Ø¬Ø§Ù ÙØ§Ø¹Ø§Ø¯Ø© ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙÙ
+ÙÙ Ø§ÙØ¹Ø±Ø¶ Ù
+ØšØ§ØŽØ±Ø©0 Ø¹ÙÙÙ ØšØ¯ Ù
+Ù ØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ù
+Ø±Ø© ÙØ§Ø­Ø¯Ø© Ø¹ÙÙ Ø§ÙØ£ÙÙ0</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/thegatherview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/thegatherview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/thegatherview.htm	(revision 13928)
@@ -0,0 +1,151 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="thegatherview"><font size="5" face="Verdana"><strong>4.1: Ù
+ØŽÙØ¯ Ø§ÙØªØ¬Ù
+ÙÙØ¹</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙØ¹Ø±Ù ÙØ°Ø§ Ø§ÙÙØ³Ù
+ Ù
+ÙØ·ÙØ© ØªØ¬Ù
+ÙØ¹ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+Ø·ÙÙØšÙ ÙØšÙØ§Ø¡ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 ÙØšØ¯Ø£ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ØšÙØ§ØŠÙ
+Ø© Ø§ÙØªØ¬Ù
+ÙØ¹ ÙÙØ±Ø¬ÙØ¹ ÙÙØ°Ù Ø§ÙÙØ§ØŠÙ
+Ø© ÙÙÙ
+Ø§ ØšØ¹Ø¯ Ø Ø§ÙÙØ± ""Gather"" Ù
+ØšØ§ØŽØ±Ø© Ø§Ø³ÙÙ Ø¹Ù
+ÙØ¯ Ø§ÙÙÙØ§ØŠÙ
+0 </p>
+
+<p>-ÙØªÙ
+ Ø§Ø®ØªÙØ§Ø± Ø¹ÙØµØ± Ù
+Ù Ø§ÙØŽØ¬Ø±Ø© ØšØ§ÙÙÙØ± Ø¹ÙÙÙ (ØªÙØ¬Ø¯ Ø·Ø±Ù Ø£Ø®Ø±ÙØ Ø§ÙØžØ± Ø§Ø¯ÙØ§Ù) Ø§ÙÙØ± Ø§ÙÙ
+Ø¬ÙØ¯ ÙÙØ±Ø© Ù
+Ø²Ø¯ÙØ¬Ù Ø£Ù ÙÙØ±Ø© ÙØ§Ø­Ø¯Ø© ÙÙØªØ­ Ø§ÙØ±Ù
+Ø² ØšØ¬Ø§ÙØš Ø§ÙÙ
+Ø¬ÙØ¯ ÙÙØªÙ
+Ø¯ÙØ¯ (Ø£Ù Ø§ÙØªÙÙÙØµ)0 Ø§ÙÙØ± Ø§ÙÙ
+ÙÙ ÙÙØ±Ø© Ù
+Ø²Ø¯ÙØ¬Ø© ÙÙØªØ­ Ø§ÙÙ
+ÙÙ"Open in external program" ØšÙØ§Ø³Ø·Ø© ØšÙØ§Ø³Ø·Ø© Ø§ÙØšØ±ÙØ§Ù
+Ø¬ Ø§ÙÙ
+ÙØ§Ø³Øš 0(see <a href="fileassociations.htm">Ù
+ØªØ¹ÙÙØ§Øª Ø§ÙÙ
+ÙÙ</a>).</p>
+
+<p> ØªÙØ¶Ø­ ØŽØ¬Ø±Ø© Ø§ÙÙ
+ÙÙØ§Øª ÙÙ Ù
+Ø³Ø§Ø­Ø© Ø§ÙØ¹Ù
+Ù Ù
+ØµØ§Ø¯Ø± Ø§ÙØšÙØ§ÙØ§Øª Ø§ÙÙ
+ØªÙÙØ±Ø© ÙÙ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ- ÙØžØ§Ù
+ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+Ø­ÙÙ (Ø§ÙÙØ±Øµ Ø§ÙÙ
+Ø­ÙÙ ÙØ§ÙØ§ÙØ±Ø§Øµ Ø§ÙÙ
+Ø¯Ù
+Ø¬Ø©)0  Ù
+Ø­ØªÙÙØ§Øª Ù
+Ø¬Ù
+ÙØ¹Ø§Øª ÙØ±ÙÙØ³ØªÙÙ ÙØ°Ø§ÙØ±Ø© Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+ÙØ²ÙØ©.ÙÙ
+ÙÙÙ ÙØ³Ø® Ù Ø¹Ø±Ø¶ ÙØ°Ù Ø§ÙÙ
+ÙÙØ§Øª  ÙÙÙÙ ÙØ§ ÙÙ
+ÙÙÙ ØªØ­Ø±ÙÙ Ø£Ù Ø§ÙØºØ§Ø¡Ø§ Ø£Ù ØªØ¹Ø¯ÙÙ ÙØ°Ù Ø§ÙÙ
+ÙÙØ§ØªØ ØšØ§Ø³ØªØ«ÙØ§Ø¡ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+ÙØ²ÙØ©0 ÙØ§ÙØªÙ ÙÙ
+ÙÙ Ø¥ÙØºØ§Ø€ÙØ§0 ØªØ¬ÙÙ ÙÙ ÙØ°Ù Ø§ÙÙ
+Ø³Ø§Ø­Ø© ÙÙØ¹Ø«ÙØ± Ø¹ÙÙ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙØªÙ ØªÙØ¯ Ø¶Ù
+ÙØ§ ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø©</p>
+
+<p>ØŽØ¬Ø±Ø© Ù
+ÙÙØ§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ØªØ¹ØšØ± Ø¹Ù Ù
+Ø­ØªÙÙØ§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© ÙÙÙ ØšØµÙØ±Ø© Ù
+ØšØ¯ØŠÙØ© ØªÙÙÙ ÙØ§Ø±ØºØ©0</p>
+
+<p>ÙÙ
+ÙÙÙ ØªØ¹Ø¯ÙÙ Ø§Ø­Ø¬Ø§Ù
+ Ø§ÙÙ
+Ø³Ø§Ø­Ø§Øª ØšØªÙ
+Ø±ÙØ± Ù
+Ø€ØŽØ± Ø§ÙÙØ£Ø±Ø© ÙÙÙ Ø§ÙØ¹Ù
+ÙØ¯ Ø§ÙØ±Ù
+Ø§Ø¯Ù Ø§ÙØ°Ù ÙÙØµÙ ØŽØ¬Ø±Ø§Øª Ø§ÙÙ
+ÙÙØ§Øª (ØšØªØºÙØ± ØŽÙÙ Ù
+Ø€ØŽØ± Ø§ÙÙØ£Ø±Ø© ÙØ§Ø³ÙØ·0.</p>
+
+<p>ÙÙØ¬Ø¯ Ø¹Ù
+ÙØ¯ Ø§ÙØ­Ø§ÙØ© Ø£Ø³ÙÙ Ø§ÙÙØ§ØŠÙ
+Ø© ÙÙÙ ÙÙØ¶Ø­ 0 ØªØ·ÙØ± Ø§Ø¬Ø±Ø§Ø¡Ø§Øª Ø§ÙÙ
+ÙÙØ§Øª (ÙØ³Ø®Ø ØªØ­Ø±ÙÙØ Ø¥ÙØºØ§Ø¡) ÙÙØ°Ù Ø§ÙØ§Ø¬Ø±Ø§Ø¡Ø§Øª ÙØ¯ ØªØ³ØªØºØ±Ù Ø²Ù
+ÙØ§Ù ÙÙÙ ØªÙØªÙ
+Ù0</p>
+
+<p>ÙÙØ¬Ø¯ Ø²Ø±ÙÙ ÙØšÙØ±ÙÙ ÙÙ Ø§ÙØ¬Ø§ÙØš Ø§ÙØ£ÙÙ
+Ù Ù
+Ù Ø§ÙØ¬Ø²Ø¡ Ø§ÙØ£Ø³ÙÙ  Ù
+Ù Ø§ÙØŽØ§ØŽØ©0 "Ù
+Ø¬ÙØ¯ Ø¬Ø¯ÙØ¯" ØšØµÙØ±Ø© Ù
+Ø¬ÙØ¯ ÙØ§ÙØŽØ§Ø¡ Ù
+ÙÙØ§Øª Ø¬Ø¯ÙØ¯Ø© (see  <a href="creatingfolders.htm">Ø¥ÙØŽØ§Ø¡ Ù
+Ø¬ÙØ¯Ø§Øª</a>). "Ø§ÙØºØ§Ø¡" ØšØµÙØ±Ø© Ø³ÙØ© ÙØžØ§ÙØ© ÙØ­Ø°Ù Ø§ÙÙ
+ÙÙØ§Øª0 ÙÙØ± Ø§ÙÙ
+ÙÙ Ø³ÙÙ ÙØ€Ø¯Ù  ÙØ­Ø°Ù Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±Ø© Ù
+Ù ØŽØ¬Ø±Ø© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©0 ÙØ®ÙØ§Ø± Ø¢Ø®Ø± ÙÙ
+ÙÙ Ø­Ø°Ù Ø§ÙÙ
+ÙÙØ§Øª ØšØªØ­Ø±ÙÙÙØ§ Ø¥ÙÙ Ø²Ø± Ø§ÙØ§ÙØºØ§Ø¡0 </p>
+
+<p>ÙØ§Ø®ØªÙØ§Ø± Ù
+Ø¬Ù
+ÙØ¹Ø©  Ø¹ÙØ§ØµØ± Ù
+ØªØ³ÙØ³ÙØ©Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø§ÙØ£ÙÙ Ù
+Ø¹ Ø­ÙØž ÙØ§Ù
+Ø³Ø§Ù Ù
+ÙØªØ§Ø­ [shift] ÙØ§ÙÙØ± Ø¹ÙÙ Ø¢Ø®Ø± Ø§Ø®ØªÙØ§Ø±Ø§ØªÙØ ÙØ³ÙÙ ÙØŽÙ
+Ù ÙØ°Ø§ Ø§ÙØ§Ø®ØªÙØ§Ø± Ù
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙØ¹ÙØ§ØµØ± Ø§ÙÙ
+Ø¶Ù
+ÙÙØ ÙØ§Ø®ØªØšØ§Ø± Ø§ÙØ¹ÙØ§ØµØ± ØºÙØ± Ø§ÙÙ
+ØªØ³ÙØ³ÙØ© Ø§Ø¶ØºØ· Ø¹ÙÙ Ù
+ÙØªØ§Ø­ [ctrl]  ØšÙÙÙ
+Ø§ ÙÙÙÙ
+ ØšØ§ÙÙÙØ±Ø Ø§Ø³ØªØ®Ø¯Ù
+ Ø§ÙØ§Ø³ÙÙØšÙÙ ÙØ§Ø®ØªÙØ§Ø± Ù
+Ø¬Ù
+ÙØ¹Ø© Ù
+ØªØ¬Ø§ÙØ±Ø© Ø£Ù Ù
+Ø¬Ù
+ÙØ¹Ø© ØºÙØ± Ù
+ØªØ¬Ø§ÙØ±Ø©0</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/themirrorview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/themirrorview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/themirrorview.htm	(revision 13928)
@@ -0,0 +1,158 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="themirrorview"><font size="5" face="Verdana"><strong>3.1: Ù
+ØŽÙØ¯ Ø§ÙØªÙØ²ÙÙ</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙØµÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+"Download"  ÙÙÙÙØ© Ø¥Ø¹Ø¯Ø§Ø¯ Ù
+ÙÙ
+Ø© ØªÙØ²ÙÙ ÙØ§ÙØªØ­ÙÙ
+ ÙÙ Ø§Ø¬Ø±Ø§Ø¡ Ø§ÙØªÙØ²ÙÙØ ÙØ§ØªØ§Ø­Ø© Ø§ÙØªÙØ²ÙÙ Ø§ÙÙØ± Ø§ÙØ²Ø±0 ÙÙ Ù
+ÙØªØµÙ Ø§Ø¹ÙÙ Ø§ÙØŽØ§ØŽÙØ ØªØªÙÙØ± ÙÙ Ø¹ÙØ§ØµØ± Ø§ÙØªØ­ÙÙ
+ ÙÙ Ø§Ø¬Ø±Ø§Ø¡ Ø§ÙØªÙØ²ÙÙ0 ÙÙÙÙ ÙØµÙ Ø§ÙØŽØ§ØŽØ© Ø§ÙØ§Ø³ÙÙ ÙØ§Ø±Øº Ù
+ØšØ¯ØŠÙØ§Ù ÙØ°ÙÙ ÙØªÙÙÙØ± ÙÙØ§ØŠÙ
+ Ø§ÙÙ
+ÙÙ
+Ø§Øª Ø§ÙÙ
+ÙØ¬Ø²Ø© ÙØ§ÙÙ
+Ø¹ÙÙØ©0 </p>
+
+<p> ØªÙØ¬Ø¯ ØšØ±ÙØªÙÙÙÙØ§Øª Ø¹Ø¯ÙØ¯Ø© ÙÙ
+ÙÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+ÙØ§ ÙØªÙØ²ÙÙ Ø§ÙØªØ³Ø¬ÙÙØ§Øª ÙÙØ§ØŠÙ
+Ø© Ø§ÙØšØ±ÙØªÙÙÙØ§Øª ØªÙØ¬Ø¯ Ø£Ø¹ÙÙ Ø¬ÙØ© Ø§ÙÙØ³Ø§Ø±0.</p>
+
+<p>
+<b>Web:</b>  ØªÙØ²ÙÙ ØµÙØ­Ø§Øª  Ø§ÙÙØš ÙØ§ÙÙ
+ÙÙØ§Øª Ø¹ØšØ± HTTP ÙFTP </p>
+
+<p>
+<b>OAI:</b> ØªÙØ²ÙÙ ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª ÙØªØ³Ø¬ÙÙØ§Øª Ù
+ØšØ§Ø¯Ø±Ø©  Ø§ÙØ§Ø±ØŽÙÙ Ø§ÙÙ
+ÙØªÙØ­  OAI
+</p>
+
+<p>
+<b>Z3950:</b>  ØªÙØ²ÙÙ ØªØ³Ø¬ÙÙØ§Øª MARC Ø§ÙØªÙ ØªØ¶Ø§ÙÙ Ø³Ù
+Ø§Øª ØšØ­Ø« Ù
+Ø¹ÙÙ ÙÙ ØšØ­Ø« Z3950
+</p>
+
+<p>
+<b>SRW:</b>  ØªÙØ²ÙÙ ØªØ³Ø¬ÙÙØ§Øª MARCXML Ø§ÙØªÙ ØªØ¶Ø§ÙÙ Ø³Ù
+Ø§Øª ØšØ­Ø« Ù
+Ø¹ÙÙ ÙÙ Ù
+Ø²ÙØ¯ SRW</p>
+
+<p> ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ø§ÙÙÙ
+Ø· Ø§ÙÙ
+ÙØ§Ø³Øš ØšØ§ÙÙÙØ± Ø¹ÙÙÙ Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ¬ÙØ¯Ø© ÙÙ Ø§ÙØ¬Ø²Ø¡ Ø§ÙØ§ÙØ³Ø± ÙØ§ÙØªÙ ØªØ¹Ø±Ø¶ Ø§ÙØ®ÙØ§Ø±Ø§Øª Ø§ÙÙ
+ÙØ¬ÙØ¯Ø© ÙÙÙ
+Ø· Ø§ÙØªÙØ²ÙÙ0 ÙÙ
+Ø¹Ø±ÙØ© ØªÙØ§ØµÙÙ ÙÙ ØªÙØ²ÙÙ Ø­ÙÙ ØšØ§ÙÙ
+Ø€ØŽØ± ÙÙÙ Ø§ÙØ®ÙØ§Ø± ØªØžÙØ± ÙÙ ØªÙØ§ØµÙÙ Ø§ÙÙÙ
+Ø· ÙÙ Ù
+Ø±ØšØ¹ Ù
+Ø³Ø§Ø¹Ø¯Ø©0 ØšØ¹Ø¶ Ø§ÙØ®ÙØ§Ø±Ø§Øª ÙÙ "Ø§Ø®ØªÙØ§Ø±ÙØ©" ÙØªØ¹Ø±Ø¶ ØšÙ
+Ø±ØšØ¹ ÙØ­Øµ ÙØªØ£ØŽÙØ±Ù Ø¹ÙØ¯ Ø§Ø³ØªØ®Ø¯Ø§Ù
+  Ø§ÙØ®ÙØ§Ø± . Ø§ÙØ§Ø®Ø±Ù "Ù
+Ø·ÙÙØšØ©" ÙÙØ§ ÙØªÙÙØ± ÙÙÙØ§ Ù
+Ø±ØšØ¹Ø§Øª ÙØ­Øµ  ÙÙØ¬Øš Ø§Ø¹Ø·Ø§Ø¡ Ø§ÙÙÙÙ
+Ø© ÙØšÙ Ù
+ØšØ§ØŽØ±Ø© Ø§ÙØªÙØ²ÙÙ0
+</p>
+
+<p> Ø¹ÙØ¯Ù
+Ø§ ÙØªÙ
+ Ø¥Ø¹Ø¯Ø§Ø¯ Ø§ÙØªÙÙÙÙØ Ø§ÙÙØ± "Server Information" ÙÙØ­Øµ Ù
+Ø¹ÙÙÙ
+Ø§Øª Ù
+Ø²ÙØ¯ Ø§ÙØ§ØªØµØ§Ù ÙØµÙØ­Ø© ÙØµÙØ­Ø© Ø§ÙÙØš Ø£Ù Ø£ÙÙØ±"Download" ÙØšØ¯Ø¡ Ø§ÙØªÙØ²ÙÙ0
+ </p>
+
+<p>ÙÙØ¬Ø¯ Ø²Ø±ÙÙ Ø¢Ø®Ø±ÙÙ ÙÙØªØ­ÙÙ
+ Ø²Ø± "Ø§ÙØªÙØµÙÙØ§Øª" ÙØ§ÙØ°Ù ÙØ±ØšØ· ØµÙØ­Ø© Ø§ÙØ§ØªØµØ§Ù Ø­ÙØ« ÙÙ
+ÙÙ ØªØ¹Ø¯ÙÙ Ø¥Ø¹Ø¯Ø§Ø¯Ø§Øª Ø§ÙØšØ±ÙÙØ³ÙØ Ø²Ø± "Ù
+Ø³Ø­ Ø§ÙØ°Ø§ÙØ±Ø©" Ø­ÙØ« ÙÙ
+ÙÙ Ø¥ÙØºØ§Ø¡ ÙÙ Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙÙ
+ÙØ²ÙØ© Ù
+Ù ÙØšÙ0 Ø³ÙÙ ØªØ­ØªØ§Ø¬  ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª  ÙØ§Ø¹Ø¯Ø§Ø¯ Ø§ÙØšØ±ÙÙØ³Ù Ø§Ø°Ø§ ÙÙØª ØªØ³ØªØ®Ø¯Ù
+  Ù
+Ø²ÙØ¯ ØšØ±ÙÙØ³Ù ÙÙØ§ØªØµØ§Ù ØšØ§ÙØ§ÙØªØ±ÙØª0 Ø§Ø°Ø§ ÙØ§ÙØª ÙÙØ§Ù Ø­ÙØ¬Ø© ÙØªØ£ÙÙØ¯ Ø§ÙØªØ¹Ø±ÙÙ ÙØ§Ù Ù
+Ø²ÙØ¯ Ø§ÙØšØ±ÙÙØ³Ù Ø³ÙÙ ÙØ­ØªÙ ÙØ§Ø³Ù
+ Ø§ÙÙ
+Ø³ØªØ®Ø¯Ù
+ ÙÙÙÙ
+Ø© Ø§ÙÙ
+Ø±ÙØ±0 ÙØ§Ø¬ÙØ© Ø§ÙÙ
+ÙØªØšÙ ÙØ§ ÙØ­ÙØž ÙÙÙ
+Ø§Øª Ø§ÙÙ
+Ø±ÙØ± ØšÙÙ "session"
+</p>
+
+<p>Ø§ÙÙ
+ÙÙØ§Øª Ø§ÙØªÙ ØªÙ
+ ØªÙØ²ÙÙÙØ§ ØªØ®Ø²Ù ÙÙ Ù
+Ø¬ÙØ¯ ÙØ³Ù
+Ù "Downloaded Files" (ÙÙÙ Ù
+ØªÙÙØ±Ø© Ø¹ÙØ¯ ØªÙØ¹ÙÙ Ø§ÙØªÙØ²ÙÙ) ÙÙÙ
+ÙÙ Ø§Ø³ØªØ®Ø¯Ø§Ù
+ÙØ§ ÙÙ Ø£Ù Ù
+Ø¬Ù
+ÙØ¹Ø©. ØªØªÙ
+ ØªØ³Ù
+ÙØ© Ø§ÙÙ
+ÙÙØ§Øª ØšØ§ÙØ§Ø³Ù
+ Ø§ÙÙØ§Ù
+Ù ÙØ¹ÙÙØ§Ù  Ø§ÙÙ
+ÙØ§Ø±Ø¯ Ø§ÙÙ
+ÙØ­Ø¯ URL (ÙØªÙØ²ÙÙØ§Øª Ø§ÙÙØš Ø£Ù Ù
+Ø²ÙØ¬ Ù
+Ù Ø¹ÙÙØ§Ù Ø§ÙÙ
+ÙØ§Ø±Ø¯ Ø§ÙÙ
+ÙØ­Ø¯ URL ÙÙÙÙ
+ Ø§ÙØ®ÙØ§Ø± (ÙØ§ÙÙ
+Ø§Ø· Ø§ÙØªÙØ²ÙÙ Ø§ÙØ£Ø®Ø±Ù) ÙØªÙ
+ Ø§ÙØŽØ§Ø¡ Ù
+Ø¬ÙØ¯ Ø¬Ø¯ÙØ¯ ÙØ§Ù Ù
+Ø¶ÙÙ Ù
+ØªØšÙØ¹Ø§Ù ØšÙ
+Ø¬ÙØ¯Ø§Øª ÙØ±Ø¹ÙØ© ØªÙ
+Ø§Ø«Ù Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª Ø§ÙÙØ±Ø¹ÙØ© ÙÙÙ
+Ø¬ÙØ¯ Ø§ÙÙ
+ÙØ²Ù ÙØªÙÙÙØ± Ø§ÙØ¯ÙØ©0
+</p>
+
+<p>ØªÙÙØ± ÙØ§ØŠÙ
+Ø© ØªÙØ²ÙÙ ÙÙÙ Ø§Ø¬Ø±Ø§Ø¡ ØªÙØ²ÙÙ0 ÙÙÙØ± ÙÙ Ù
+Ø¯Ø®Ù  Ù
+ÙØ§ÙØ§Ù ÙÙÙØµ Ø§ÙØ°Ù ÙØ¹Ø·Ù ØªÙØ§ØµÙÙ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ Ø§ÙØ­Ø§ÙÙ Ù
+Ø¹ Ø¹Ù
+ÙØ¯ ÙØ§ØžÙØ§Ø± ØªØ·ÙØ± Ø§ÙØ§Ø¬Ø±Ø§Ø¡0 ÙÙØ¬Ø¯ ÙÙ Ø§ÙØ¬Ø§ÙØš Ø§ÙØ§ÙØ³Ø± Ø«ÙØ§Ø« Ø§Ø²Ø±Ø§Ø± ÙÙÙ Ù
+Ø¯Ø®Ù "ØªØ¹ÙÙÙ" ÙØªØ¹ÙÙÙ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ Ø§ÙØ¬Ø§Ø±Ù0 "Ø¹Ø±Ø¶ Ø§ÙÙ
+Ø¯ÙÙÙ" ÙÙØªØ­ ÙØ§ÙØ°Ø© Ø§ÙÙ
+Ø¯ÙÙØ©0 "ØºÙÙ" ÙØ§ÙÙØ§Ø¡ Ø§Ø¬Ø±Ø§Ø¡ Ø§ÙØªÙØ²ÙÙ ÙØ­Ø°Ù Ø§ÙÙ
+ÙÙ
+Ø© Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø©0  </p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/translatetext.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/translatetext.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/translatetext.htm	(revision 13928)
@@ -0,0 +1,67 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="translatetext"><font size="5" face="Verdana"><strong>8.5: ØªØ±Ø¬Ù
+Ù ÙØµ</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙØµÙ ÙØ°Ø§ Ø§ÙÙØ³Ù
+ Ù
+ØŽÙØ¯ Ø§ÙØªØ±Ø¬Ù
+Ø©Ø Ø­ÙØ« ÙÙ
+ÙÙÙ ØªØ¬Ø²ØŠØ© ÙØµ Ù
+Ù ÙØºØ© Ù
+Ø®ØµØµØ© ÙØ§Ø¬Ø²Ø§Ø¡ ÙØ§Ø¬ÙØ© Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø©Ø ØªØ­Øª tab "ÙØ³Ù Ø¹Ø±Ø¶" Ø§ÙÙØ± "ØªØ±Ø¬Ù
+Ø© ÙØµ"0</p>
+
+<p>Ø§ÙÙØ§ÙØ ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø± Ù
+Ø¯Ø®Ù Ù
+Ù ÙØ§ØŠÙ
+Ø© "Ø³Ù
+Ø§Øª"Ø ØªØžÙØ± Ø³ÙØ§Ø³Ù Ø§ÙÙØºØ© Ø§ÙÙ
+Ø®ØµØµØ© Ø§ÙÙ
+ØªØ¹ÙÙØ© ØšØ§ÙØ³Ù
+Ø© Ø§ÙØªÙ ØªØžÙØ± Ø§Ø¯ÙØ§Ù &ndash; Ø§Ø³ØªØ®Ø¯Ø§Ù
+ Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+ÙØ³Ø¯ÙØ© "ÙØºØ© Ø§ÙØªØ±Ø¬Ù
+Ø©" ÙØ§Ø®ØªÙØ§Ø± Ø§ÙÙØºØ© Ø§ÙÙ
+Ø·ÙÙØšØ©- ÙØ§Ø·ØšØ¹ Ø§ÙÙØµ Ø§ÙÙ
+ØªØ±Ø¬Ù
+ Ù
+Ù Ù
+ÙØ·ÙØ© Ø§ÙÙØµ Ù
+Ø¹ Ø§ÙØ§Ø­Ø§ÙØ© Ø§ÙÙ "ØªØ¬Ø²ØŠØ© Ø§Ø°Ø§ ÙØ§Ù Ø¶Ø±ÙØ±ÙØ§ÙÙØµ Ù
+ØšØ¯ØŠÙØ©"0 Ø§Ø°Ø§ ÙØ§Ù Ø¶Ø±ÙØ±ÙØ§ÙØ Ø§ÙÙØ± "Ø§Ø¶Ø§ÙØ© ØªØ±Ø¬Ù
+Ø©"0</p>
+
+<p> ÙØ­Ø°Ù ØªØ±Ø¬Ù
+Ø© Ù
+ÙØ¬ÙØ¯Ø©Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±ÙØ§ Ù
+Ù Ø¬Ø¯ÙÙ "Ø§ÙØªØ±Ø¬Ù
+Ø§Øª Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø©" ÙØ§ÙÙØ± "Ø­Ø°Ù ØªØ±Ø¬Ù
+Ø©"0</p>
+
+<p>ÙØªØ¹Ø¯ÙÙ ØªØ±Ø¬Ù
+Ø©Ø ÙÙ
+ ØšØ§Ø®ØªÙØ§Ø±ÙØ§Ø ØªØ¹Ø¯ÙÙ Ù
+ÙØ·ÙØ© "Ø§ÙÙØµ Ø§ÙÙ
+ØªØ±Ø¬Ù
+" ÙØ§ÙÙØ± "Ø§Ø³ØªØšØ¯Ø§Ù ØªØ±Ø¬Ù
+Ø©"0</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/updatingmetadata.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/updatingmetadata.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/updatingmetadata.htm	(revision 13928)
@@ -0,0 +1,49 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="updatingmetadata"><font size="5" face="Verdana"><strong>5.5: ØªØ¹Ø¯ÙÙ Ø§Ù Ø­Ø°Ù ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙØªØ­Ø¯ÙØ« Ø£Ù Ø­Ø°Ù ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§ØªØ ÙÙ
+ Ø§ÙÙØ§Ù ØšØ§Ø®ØªÙØ§Ø± Ø§ÙÙ
+ÙÙ Ø§ÙÙ
+Ø·ÙÙØš Ø«Ù
+ ÙÙÙ
+Ø© ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª Ù
+Ù Ø§ÙØ¬Ø¯ÙÙ0 ÙÙ
+ ØšØªØ­Ø¯ÙØ« ÙÙÙ
+Ø© Ø§ÙØ­ÙÙ Ø£Ù Ø¥ÙØºØ§Ø¡ ÙÙ Ø§ÙÙØµ Ø§Ø°Ø§ Ø§Ø±Ø¯Øª Ø­Ø°Ù ÙØ§ØµÙØ§Øª Ø§ÙØšÙØ§ÙØ§Øª0
+</p>
+
+<p>ÙØªØšØ¹  ÙÙØ³  Ø§ÙØ§Ø¬Ø±Ø§Ø¡ Ø¹ÙØ¯ ØªØ­Ø¯ÙØ« Ù
+Ø¬ÙØ¯ ÙØ­ØªÙÙ  Ù
+Ø¬ÙØ¯Ø§Øª ÙØ±Ø¹ÙØ© Ø£Ù Ù
+ÙÙØ§Øª Ù
+ØªØ¹Ø¯Ø¯Ø©Ø  ÙÙ
+ÙÙÙ ØªØ­Ø¯ÙØ« ÙØ§ØµÙØ§Øª ØšÙØ§ÙØ§Øª Ù
+ØŽØªØ±ÙØ© ÙÙÙ Ø§ÙÙ
+Ø¬ÙØ¯Ø§Øª / Ø§ÙÙ
+ÙØ§Øª Ø§ÙÙ
+Ø®ØªØ§Ø±Ø©0</p>
+
+<p>ØªØžÙØ± ØŽØ¬Ø±Ø© Ø§ÙÙÙÙ
+ ÙÙ Ø§ÙÙÙÙ
+ Ø§ÙÙ
+Ø­Ø¯Ø¯Ø©  Ø§ÙØ­Ø§ÙÙØ© ÙØ§ÙØ³Ø§ØšÙØ© Ø¹ÙØ¯ Ø§ÙØ§Ø¬Ø±Ø§Ø¡ Ø¹ÙØ¯ ØºÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø«Ù
+ ÙØªØ­ÙØ§  Ù
+Ø±Ø© Ø£Ø®Ø±Ù ØªØ®ØªÙÙ ÙÙ Ø§ÙÙÙÙ
+ Ø§ÙØªÙ ÙÙ
+ ÙØªÙ
+ ØªØµÙÙÙÙØ§0</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ar/xcollectionsearching.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ar/xcollectionsearching.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ar/xcollectionsearching.htm	(revision 13928)
@@ -0,0 +1,83 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="xcollectionsearching"><font size="5" face="Verdana"><strong>8.6: ØšØ­Ø« ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>ÙØªÙØ­ ÙÙ ÙØ±ÙÙØ³ØªÙÙ ØšØ­Ø« Ù
+Ø®ØªÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª ÙØ£Ø£ÙÙØ§ Ù
+Ø¬Ù
+ÙØ¹Ø© ÙØ§Ø­Ø¯Ù .ÙÙ
+ÙÙ ÙØ¹Ù ÙØ°Ø§ ØšØªØ­Ø¯ÙØ¯ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙØ£Ø®Ø±Ù ÙÙØšØ­Ø« ÙØšØ¬Ø§ÙØš Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙØ­Ø§ÙÙÙ0 ØªØ­Øª "ÙØ³Ù Ø¹Ø±Ø¶" Ø Ø§ÙÙØ± "ØšØ­Ø« ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª"0</p>
+
+<p>Ù
+ØŽÙØ¯ "ØšØ­Ø« ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª" ÙØžÙØ± ÙØ§ØŠÙ
+Ù
+Ø© ÙÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙÙ
+ØªÙÙØ±Ø© ØšÙ
+Ø±ØšØ¹Ø§Øª ÙØ­Øµ0 ÙØªÙ
+ Ø§Ø¹ØªØšØ§Ø± Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙØ­Ø§ÙÙØ© Ù
+Ø®ØªØ§Ø±Ù ÙÙØ§ ÙÙ
+ÙÙ ÙÙØ¶ Ø§Ø®ØªÙØ§Ø±ÙØ§ 0 ÙØ§Ø¶Ø§ÙØ© Ù
+Ø¬Ù
+ÙØ¹Ø© Ø£Ø®Ø±Ù ÙÙØšØ­Ø« ØšØµÙØ±Ø© Ù
+ÙØ§Ø²ÙØ©Ø Ø§ÙÙØ± Ø¹ÙÙÙØ§ Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø© (Ø§ÙÙØ± Ø£Ø®Ø±Ù ÙØ­Ø°ÙÙØ§ )0 Ø§Ø°Ø§ ØªÙ
+ Ø§Ø®ØªÙØ§Ø± Ù
+Ø¬Ù
+ÙØ¹Ø© ÙØ§Ø­Ø¯Ø©   ÙÙÙÙ ÙÙØ§Ù ØšØ­Ø« Ø¹ØšØ± ÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª0</p>
+
+<p>Ø§Ø°Ø§ ÙÙ
+ ØªÙ
+ØªÙÙ Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª Ø§ÙÙØ±Ø¯ÙØ© ÙÙØ³ Ø§ÙÙØŽØ§ÙØ§Øª (Ù
+ØªØ¶Ù
+ÙÙ ÙØ·Ø§Ø¹Ø§Øª Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ø§ÙÙØ±Ø¹ÙØ© ÙÙØ·Ø§Ø¹Ø§Øª Ø§ÙÙØºØ©) ØšØµÙØ±Ø© Ù
+ØªÙ
+Ø§Ø«ÙØ©Ø ÙØ§Ù Ø§ÙØšØ­Ø« Ø¹ØšØ± ÙØ°Ù Ø§ÙÙ
+Ø¬Ù
+ÙØ¹Ø§Øª ÙØ¹Ù
+Ù ØšØµÙØ±Ø© ØµØ­ÙØ­Ù0 ÙÙÙ ÙØªÙ
+ÙÙ Ø§ÙÙ
+Ø³ØªÙÙØ¯ Ø¥ÙØ§ Ù
+Ù ØšØ­Ø« Ø§ÙÙØŽØ§ÙØ§Øª ÙÙ ÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø©0</p>
+
+<p>ÙÙ
+Ø²ÙØ¯ Ù
+Ù Ø§ÙØªÙØ§ØµÙÙØ Ø£ÙØžØ± Ø§ÙÙØµÙ Ø§ÙØ£ÙÙ Ù
+Ù Ø¯ÙÙÙ ÙØ±ÙÙØ³ØªÙÙ ÙÙÙ
+Ø·ÙØ±ÙÙ0</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/addingfiles.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/addingfiles.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/addingfiles.htm	(revision 13928)
@@ -0,0 +1,25 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="addingfiles"><font size="5" face="Verdana"><strong>4.4: Adding Files</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Files can be copied into the collection by dragging and dropping.  The mouse pointer becomes a ghost of the selected item (or, if more than one is selected, the number of them).  Drop the selection into the Collection Tree to copy the files there (if the source was the Workspace Tree) or move them around within the collection (if the source was the Collection Tree).</p>
+
+<p>When copying multiple files, they are all placed in the target folder at the same level, irrespective of the folder structure they occupied originally. When you copy a second file with the same name into the same folder, you are asked whether to overwrite the first one.  Respond "No" and the file will not be copied, but the others will be.  To cancel all remaining copy actions, click the "stop" button.</p>
+
+<p>Only the "highest" items in a selection are moved.  A folder is higher than its children.  You cannot select files within a folder and also the folder itself.</p>
+
+<p>When you add a file, the Librarian Interface searches through the source folders for auxiliary files containing metadata previously assigned to the added file and, if it finds one, begins to import this metadata.  As the operation proceeds, you may be prompted (perhaps several times) for extra information to match the imported metadata to the metadata sets in your collection.  This process involves many different prompts, described in the <a href="importingpreviouslyassignedmetadata.htm">Importing Previously Assigned Metadata</a> section.  For a more detailed explanation of associating metadata with files read Chapter 2 of the Greenstone Developer's Guide -- Getting the most out of your documents.</p>
+
+<p>You can also add a "dummy" document to the collection by right-clicking in the Collection Tree or on a folder, and selecting "New dummy document". This will create a new empty file to which metadata can be assigned. The file can be replaced with a "real" file later on.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/addingpreviouslydefinedmetadata.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/addingpreviouslydefinedmetadata.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/addingpreviouslydefinedmetadata.htm	(revision 13928)
@@ -0,0 +1,19 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="addingpreviouslydefinedmetadata"><font size="5" face="Verdana"><strong>5.4: Adding Previously Defined Metadata</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>To add metadata that has an existing value, first select the file, then select the metadata element that you are assigning to, then select the required value from the value tree, expanding hierarchy folders as necessary.  The value of the selected entry automatically appears in the metadata field (alternatively, use the value tree's auto-select and auto-complete features). </p>
+
+<p>The process of adding metadata with already-existing values to folders or multiple files is just the same.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/appendingmetadata.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/appendingmetadata.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/appendingmetadata.htm	(revision 13928)
@@ -0,0 +1,23 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="appendingmetadata"><font size="5" face="Verdana"><strong>5.3: Appending New Metadata</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>We now add a metadata item -- both element and value -- to a file.  First select the file from the Collection file tree on the left.  The action causes any metadata previously assigned to this file to appear in the table at the right.</p>
+
+<p>Next select the metadata element you want to add by clicking its row in the table.</p>
+
+<p>Type the value into the value field.  Use the "|" character to add structure, as described in <a href="theenrichview.htm">The Enrich View</a>. Pressing the [Up] or [Down] arrow keys will save the metadata value and move the selection appropriately. Pressing [Enter] will save the metadata value and create a new empty entry for the metadata element, allowing you to assign multiple values to a metadata element.</p>
+
+<p>You can also add metadata to a folder, or to several multiply selected files at once.  It is added to all files within the folder or selection, and to child folders.  Keep in mind that if you assign metadata to a folder, any new files in it automatically inherit the folder's values.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/assignlanguages.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/assignlanguages.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/assignlanguages.htm	(revision 13928)
@@ -0,0 +1,29 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="assignlanguages"><font size="5" face="Verdana"><strong>6.4.3: Assign Languages</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>This section details how to restrict search indexes to particular languages. You do this by generating a partition using the "Assign Languages" tab of the "Partition Indexes" view.</p>
+
+<p>To add a new language partition, use the "Assign Languages" tab to build an index for it.  Select one or more languages from the "Languages to add" list and click "Add Partition".</p>
+
+<p>To change an existing partition, select it from the "Assigned Language Partitions" list, modify the selected languages in the "Languages to add" list below, and click "Replace Partition".</p>
+
+<p>To remove a language partition, select it from the "Assigned Language Partitions" list and click "Remove Partition".</p>
+
+<p>The order that the language partitions are specified in the Assigned Language Partitions list is the order they appear in the drop down menu on the search page. Use the "Move Up" and "Move Up" buttons to change this ordering.</p>
+
+<p>To set the default language partition, select it from the list and click "Set Default".</p>
+
+<p>The names used for the drop-down list of language partitions on the search page can be set in the "Search" part of the "Format" panel (see <a href="searchmetadatasettings.htm">Search</a>).</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/assignpartitions.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/assignpartitions.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/assignpartitions.htm	(revision 13928)
@@ -0,0 +1,27 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="assignpartitions"><font size="5" face="Verdana"><strong>6.4.2: Assign Partitions</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Having defined one or more sub-collection filters, use the "Assign Partitions" tab to build indexes for it (or for a group of filters).  Select the desired filter or filters from the "Defined Subcollection Filters" list and click "Add Partition". Each specified partition will result in a sub-collection that contains documents that match any of the filters associated with that partition.</p>
+
+<p>To alter a partition, select it from the list, modify the filters, and click "Replace Partition".</p>
+
+<p>To remove a partition, select it from the list and click "Remove Partition".</p>
+
+<p>The order that the partitions are specified in the Assigned Partitions list is the order they appear in the drop down menu on the search page. Use the "Move Up" and "Move Up" buttons to change this ordering.</p>
+
+<p>To make a partition the default one, select it from the list and click "Set Default".</p>
+
+<p>The names used for the drop-down list of partitions on the search page can be set in the "Search" part of the "Format" panel (see <a href="searchmetadatasettings.htm">Search</a>).</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/builderrors.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/builderrors.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/builderrors.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="builderrors"><font size="5" face="Verdana"><strong>7.2: Errors in collection building</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Sometimes things go wrong during collection building. Maybe some files couldn't be processed: the rest of the collection builds fine, and can be previewed, but some documents are absent. Or the whole collection is not built properly, in which case a message says "An error has occurred and the collection could not be created." When this happens, it may be helpful to switch the GLI into expert mode (File-&gt;Preferences-&gt;Mode, see <a href="preferences.htm">Preferences</a>), set the build option "verbosity" to 5, and rebuild, to see if there are any error messages.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/classifiers.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/classifiers.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/classifiers.htm	(revision 13928)
@@ -0,0 +1,31 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="classifiers"><font size="5" face="Verdana"><strong>6.5: Browsing Classifiers</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>This section explains how to assign "classifiers", which are used for browsing, to the collection.  Under the "Design" tab, click "Browsing Classifiers".</p>
+
+<p>To add a classifier, select it using the "Select classifier to add" pull-down list near the bottom and then click "Add Classifier...".  A window appears entitled "Configuring Arguments"; instructions for this dialog are just the same as for plugins (see <a href="plugins.htm">Document Plugins</a>). Once you have configured the new classifier, it is added to the end of the "Assigned Classifiers" list.</p>
+
+<p>To see a short description of a classifier, select it in the "Select classifier to add" pull-down list, then hover the mouse over it. A tool-tip displaying the description will appear.</p>
+
+<p>Each classifier has several arguments that can be configured. Important arguments include "metadata", which specifies the metadata that documents will be classified on, and "buttonname", which is the name that will appear in the navigation bar.</p>
+
+<p>To remove a classifier, select it from the list and click "Remove Classifier".</p>
+
+<p>To change the arguments for a classifier, select it from the list and click "Configure Classifier" (or double-click on the classifier in the list).</p>
+
+<p>The ordering of classifiers in the collection's navigation bar is reflected in their order here.  To change it, select the classifier you want to move and click "Move Up" or "Move Down".</p>
+
+<p>For further information on classifiers read Chapter 2, Greenstone Developer's Guide -- Getting the most out of your documents.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/collectingfiles.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/collectingfiles.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/collectingfiles.htm	(revision 13928)
@@ -0,0 +1,25 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="collectingfiles"><font size="5" face="Verdana"><strong>4: Collecting Files for Your Collection</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Once you have a new collection you need to get some files into it.  These may come from your ordinary file space, from previously downloaded files, or from other Greenstone collections.  Some may already have attached metadata.  This section describes how to import files.</p>
+
+
+
+
+
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/collectionspecificmacros.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/collectionspecificmacros.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/collectionspecificmacros.htm	(revision 13928)
@@ -0,0 +1,19 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="collectionspecificmacros"><font size="5" face="Verdana"><strong>8.7: Collection Specific Macros</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Under the "Format" tab, click "Collection Specific Macros".</p> 
+
+<p>This view shows the contents of the collection's extra.dm macro file. This is where collection specific macros can be defined. To learn more about macros, see Chapter 3 of the Greenstone Developer's Guide.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/creatingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/creatingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/creatingacollection.htm	(revision 13928)
@@ -0,0 +1,27 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="creatingacollection"><font size="5" face="Verdana"><strong>2.1: Creating a New Collection</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>To create a new collection, open the "File" menu and choose "New".  Several fields need to be filled out -- but you can change their values later if you need to, in the Format view.</p>
+
+<p>"Collection title" is the text displayed at the top of your collection's home page.  It can be any length.</p>
+
+<p>"Description of content" should describe, in as much detail as possible, what the collection is about. Use the [Enter] key to break it into paragraphs.</p>
+
+<p>Finally you must specify whether the new collection will have the same appearance and metadata sets as an existing collection, or whether to start a default "New Collection". Default new collections have a standard configuration and use the Dublin Core metadata set. These can be changed later.</p>
+
+<p>Click "OK" to create the collection. </p>
+
+<p>Clicking "Cancel" returns you to the main screen immediately.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/creatingfolders.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/creatingfolders.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/creatingfolders.htm	(revision 13928)
@@ -0,0 +1,21 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="creatingfolders"><font size="5" face="Verdana"><strong>4.3: Creating Folders</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Use folders in the Collection file tree to group files together and make them easier to find.  Folders can be placed inside folders.  There is virtually no limit to how many folders you can have or how deeply they can be nested.</p>
+
+<p>To create a new folder, optionally select an existing folder in the Collection Tree and click the New Folder button.  The new folder appears within the selected one, or at the top level if none is selected.  You are prompted for the folder's name (default "New Folder").</p>
+
+<p>Folders can also be created by right-clicking in the Collection Tree, or over a folder, choosing "New Folder" and proceeding as above.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/creatingshortcuts.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/creatingshortcuts.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/creatingshortcuts.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="creatingshortcuts"><font size="5" face="Verdana"><strong>4.2: Creating A Shortcut in the Workspace Tree</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Certain folders -- such as the one containing your own web pages -- sometimes have special significance. If you like, the Librarian Interface can map them to the top level of the file tree.  To do this, right-click the desired folder.  Select "Create Shortcut", and enter a name for the folder.  To remove an item, right-click the mapped folder and select "Remove Shortcut".</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/definefilters.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/definefilters.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/definefilters.htm	(revision 13928)
@@ -0,0 +1,25 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="definefilters"><font size="5" face="Verdana"><strong>6.4.1: Define Filters</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Filters allow you to group together into a sub-collection all documents in an index for which a metadata value matches a given pattern.</p>
+
+<p>To create a filter, click the "Define Filters" tab and enter a name for the new filter into the "Subcollection filter name:" field.  Next choose a document attribute to match against, either a metadata element or the name of the file in question.  Enter a regular expression to use during the matching. You can toggle between "Including" documents that match the filter, or "Excluding" them.  Finally, you can specify any of the standard PERL regular expression flags to use when matching (e.g.  "i" for case-insensitive matching). Finally, click "Add Filter" to add the filter to the "Defined Subcollection Filters" list.</p>
+
+<p>To remove a filter, select it from the list and click "Remove Filter".</p>
+
+<p>To alter a filter, select it from the list, change any of the values that appear in the editing controls and click "Replace Filter" to commit the changes.</p>
+
+<p>Defining filters does not create sub-collections. Sub-collections are specified in the "Assign Partitions", based on the filters you have just defined.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/deletingcollections.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/deletingcollections.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/deletingcollections.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="deletingcollections"><font size="5" face="Verdana"><strong>2.4: Deleting Collections</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>To permanently delete collections from your Greenstone installation, choose "Delete..." from the "File" menu. A list of your collections appears. Select one to see its description, then tick the box at the bottom of the dialog and click "Delete". This action is irreversible, so be careful.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/designingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/designingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/designingacollection.htm	(revision 13928)
@@ -0,0 +1,22 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="designingacollection"><font size="5" face="Verdana"><strong>6: Configuring Your Collection</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Once your files are marked up with metadata, you next decide how the documents should be accessed by the end users. What kind of information is searchable?  What ways are provided to browse through the documents? These things can be customized; this section describes how to do it.</p>
+
+
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/downloadingfiles.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/downloadingfiles.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/downloadingfiles.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="downloadingfiles"><font size="5" face="Verdana"><strong>3: Downloading Files From the Internet</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>The "Download" view helps you download resources from the Internet. This section explains the Librarian Interface's downloading process.</p>
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/enrichingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/enrichingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/enrichingacollection.htm	(revision 13928)
@@ -0,0 +1,24 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="enrichingacollection"><font size="5" face="Verdana"><strong>5: Enriching Your Collection with Metadata</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Having gathered several files into the collection, now enrich them with additional information called "metadata".  This section explains how metadata is created, edited, assigned and retrieved, and how to use external metadata sources (also see Chapter 2 of the Greenstone Developer's Guide -- Getting the most out of your documents).</p>
+
+
+
+
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/expertbuilding.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/expertbuilding.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/expertbuilding.htm	(revision 13928)
@@ -0,0 +1,21 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="expertbuilding"><font size="5" face="Verdana"><strong>7.3: Create view in Expert mode</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>In Expert mode, you can use the "Message Log" entry at the left to review previous attempts to build the collection, whether successful or not. Select the log you want by clicking on the desired date in the "Log History" list.</p>
+
+<p>In this mode, a full list of import and build options are shown in the Import and Build tabs to the left. The various settings are controlled just like the "Configuring Arguments" window described in the <a href="plugins.htm">Document Plugins</a> section.  Some fields require numeric arguments, and you can type these in or use the arrows to increase or decrease the current value (in some cases, the interface restricts the range you can enter).  Others are enabled by clicking a checkbox (click again to disable).</p>
+
+<p>For more information about importing and building read Chapter 1 of the Greenstone Developer's Guide -- Understanding the collection-building process.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/explodingfiles.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/explodingfiles.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/explodingfiles.htm	(revision 13928)
@@ -0,0 +1,25 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="explodingfiles"><font size="5" face="Verdana"><strong>4.7: "Exploding" Metadata Files</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Metadata database file types, such as MARC, CDS/ISIS, BibTex, Refer and Procite can be imported into Greenstone but their metadata cannot be viewed or edited in the Librarian Interface. To see or edit any metadata, you need to go back to the program that created the file.</p>
+
+<p>"Exploding" a metadata database file splits it into individual records, with viewable and editable metadata. This process is irreversible: the original metadata file is deleted.</p>
+
+<p>Explodable files have a green icon in the Collection tree. To explode one, right click it and choose "Explode metadata database". A popup window shows options for the exploding process. The first option ("plugin") specifies the plugin to be used for exploding. In most cases, only one plugin will process a particular type of file, but in some cases, where different file types share the same filename extension, there may be two plugins that both process files with that extension. The "input_encoding" option can be used to specify the encoding of the database. The "metadata_set" option specifies which metadata set the new fields should be added to. If none is specified, you will be prompted for what to do with each new field in the database: add it as a new element to an existing metadata set, merge with another element, or ignore.</p>
+
+<p>When a file is exploded, a new empty document is created for each record, and the metadata from the record is assigned to the document. These are named using numbers such as 000001.nul, 000002.nul etc. If the "document_field" option is set (to a database field name), the value of this field, if present, will be used for the filename. The exploding process will also try to download the file and use it instead of an empty file. The "document_prefix" and "document_suffix" options can be used to make a valid URL or file path from the document_field value. The "records_per_folder" option can be used to group exploded records into sub-folders. If the database is very large, using this option will accelerate subsequent metadata editing.</p>
+
+<p>Explodability is determined by file extension. In some cases, files may be incorrectly labelled as explodable if they have the same file extension as an explodable file. For example, the ProCite plugin processes files with a .txt extension, but most .txt files are plain text files, not ProCite files.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/exporting.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/exporting.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/exporting.htm	(revision 13928)
@@ -0,0 +1,21 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="exporting"><font size="5" face="Verdana"><strong>9.3: Exporting collections to other formats</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Greenstone can export the contents and/or metadata of a collection to several standard formats, including METS, DSpace and MARCXML.</p>
+
+<p>To export one or more collections, open the "File" menu and choose "Export...". You can choose which format to export to by selecting it in the "Export to" drop-down list. Specify a name for the directory where you want to put the exported files&mdash;the files will end up in &lt;path to greenstone&gt;/tmp/exported_xxx, where xxx is the name you specified. Select one or more collections in the list of available collections, then click "Export collection(s)".</p>
+
+<p>There are other options specific to the various formats. You can specify XSLT files which will be applied to the resulting XML document(s) in order to customize the output format. Exporting to MARCXML uses a mapping file to map Greenstone metadata to MARC fields. The default mapping file maps only Dublin Core metadata. You can specify a custom mapping file to be used instead.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/exportingcollections.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/exportingcollections.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/exportingcollections.htm	(revision 13928)
@@ -0,0 +1,21 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="exportingcollections"><font size="5" face="Verdana"><strong>9.4: Exporting Collections to CD/DVD</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Greenstone can export one or more collections to a self-installing CD/DVD for Windows. </p>
+
+<p>To export a collection, open the "File" menu and choose "Write CD/DVD Image". A list of Greenstone collections appears; click on any one to see its description. Tick the check boxes of the collections to export. You can enter the CD/DVD's name in the "CD/DVD name" box: this is what will appear in the Start menu when the CD/DVD has been installed. You can choose whether the resulting CD-ROM or DVD runs directly from the disk drive, or installs some files onto the computer. Then click "Write CD/DVD image". The process involves copying many files and may take a few minutes.</p>
+
+<p>Upon completion, Greenstone will show the name of a folder containing the exported collections. Use a CD/DVD writer to copy its contents to a blank CD/DVD.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/fileassociations.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/fileassociations.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/fileassociations.htm	(revision 13928)
@@ -0,0 +1,25 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="fileassociations"><font size="5" face="Verdana"><strong>9.2: File Associations</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>The Librarian Interface uses particular application programs to open particular file types. To alter file associations open the "File" menu and click "File Associations...".</p>
+
+<p>To add an association, select the target file extension from the pull-down list, or type in a new extension (do not include the ".").  Next either type the command that launches the desired application in the appropriate field, or choose the application from the "Browse" dialog.  "%1" can be used in the launch command to insert the name of the file being opened.  Once these are filled out, "Add" is enabled and can be clicked to add the association.</p>
+
+<p>To edit an association, select an existing file extension.  Any existing associated command is shown in the "launch command" field.  Edit it, and then click "Replace".</p>
+
+<p>To remove an association, select an existing file extension and click "Remove". (The file extension remains in the "For Files Ending" pull-down list.)</p>
+
+<p>File associations are stored in the Librarian Interface's main folder, in a file called "associations.xml".</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/filteringthetree.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/filteringthetree.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/filteringthetree.htm	(revision 13928)
@@ -0,0 +1,21 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="filteringthetree"><font size="5" face="Verdana"><strong>4.8: Filtering the Trees</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>"Filtering" the collection and workspace trees allows you to narrow down the search for particular files.</p>
+
+<p>The "Show Files" pull-down menu underneath each tree shows a list of predefined filters, such as "Images".  Choosing this temporarily hides all other files in the tree.  To restore the tree, change the filter back to "All Files".  These operations do not alter the collection, nor do they affect the folders in the tree.</p>
+
+<p>You can specify a custom filter by typing in a pattern to match files against (Librarian Systems Specialist and Expert modes only). Use standard file system abbreviations such as "*.doc" ("*" matches any characters).</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/formatstatements.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/formatstatements.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/formatstatements.htm	(revision 13928)
@@ -0,0 +1,27 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="formatstatements"><font size="5" face="Verdana"><strong>8.4: Format Features</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>The web pages you see when using Greenstone are not pre-stored but are generated 'on the fly' as they are needed. Format commands are used to change the appearance of these generated pages. They affect such things as which buttons appear when a document is shown, and what links are displayed by the DateList classifier.  Format commands are not easy to develop, and you should read Chapter 2 of the Greenstone Developer's Guide. This section discusses the format settings, and how the Librarian Interface gives access to them.  Under the "Format" tab, click "Format Features".</p>
+
+<p>You can apply a format command to anything in the "Choose Feature" pull-down list, which includes each classifier and a predefined list of features.  When you select a feature, there are two types of control.  Some features are simply enabled or disabled, and this is controlled by a checkbox.  Others require a format string to be specified.  For these there is a pull-down list ("Affected Component") for selecting which part of the feature the string applies to (if necessary), a text area ("HTML Format String") for entering the string, and a selection of predefined "Variables".  To insert a variable into a format string, position the cursor at the place to insert, then select the desired variable from the "Insert Variable..." combobox.</p>
+
+<p>You can specify a default format for a particular component by selecting the "All Features" feature.  This format is then applied to all applicable features unless a more specific one is defined.</p>
+
+<p>To add a new format command, select the applicable feature and component. The default value for this command will be displayed in grey. Click "Add Format" to assign it to the collection. The "HTML Format String" will become editable and you can change it if you wish. Only one format command can be assigned to each feature/component combination.</p>
+
+<p>To remove a format command, select it from the list and click "Remove Format".</p>
+
+<p>For more information about variables and the feature components, read Chapter 2 of the Greenstone Developer's Guide.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/formattingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/formattingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/formattingacollection.htm	(revision 13928)
@@ -0,0 +1,24 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="formattingacollection"><font size="5" face="Verdana"><strong>8: Customizing Your Collection's Appearance</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Once you have built the collection, you next decide how it should appear to the user. What names should be used for the drop-down list of indexes in the search form? How should search results be displayed? What metadata should be displayed when a document is viewed? These can be customized; this section explains how to do it. </p>
+
+
+
+
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/generalsettings.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/generalsettings.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/generalsettings.htm	(revision 13928)
@@ -0,0 +1,21 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="generalsettings"><font size="5" face="Verdana"><strong>8.2: General</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>This section explains how to review and alter the general settings associated with your collection.  First, under the "Format" tab, click "General".</p>
+
+<p>Here some collection wide metadata can be set or modified, including the title and description entered when starting a new collection.</p>
+
+<p>First are the contact email addresses of the collection's creator and maintainer. The following field allows you to change the collection title. The folder that the collection is stored in is shown next, but this cannot be altered. Then comes the icon to show at the top left of the collection's "About" page (in the form of a URL), followed by the icon used in the Greenstone library page to link to the collection. Next is a checkbox that controls whether the collection should be publicly accessible. Finally comes the "Collection Description" text area as described in <a href="creatingacollection.htm">Creating a New Collection</a>.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/help.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/help.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/help.xml	(revision 13928)
@@ -0,0 +1,486 @@
+<?xml version="1.0"?>
+<!DOCTYPE TutorialList [
+     <!ENTITY nbsp "&#160;">
+     <!ENTITY rarr "&#8594;">
+     <!ENTITY mdash "&#8212;">
+]>
+<Document>
+<Section name="introduction">
+<Title>
+<Text id="1">Introduction</Text>
+</Title>
+<Text id="2">The Greenstone Librarian Interface is a tool for collecting documents, adding metadata, then building digital library collections. It provides access to the Greenstone Digital Library Software's functionality from a graphical point and click interface.</Text>
+<Section name="ofmiceandmenus">
+<Title>
+<Text id="3">Of Mice and Menus</Text>
+</Title>
+<Text id="4">This section provides basic information about interacting with the Librarian Interface. If you are familiar with programs such as Internet Explorer or Microsoft Office and are comfortable with mouse clicks and menus, skip to <Reference target="howtoavoidthisdocument"/>.</Text>
+<Text id="5">The Librarian Interface follows Microsoft Windows conventions and draws upon ordinary knowledge of Windows.</Text>
+<Text id="6">Any part of the screen that you interact with, such as a button or text field, is called a "control".  At any given time one control, called the "focus", is highlighted and responds to the keyboard.  Several controls allow you to select parts that are highlighted in dark blue.  Some controls are greyed out to indicate that they are disabled.</Text>
+<Text id="7">You can move and left- or right-click the mouse in the usual way.  Many components also allow you to "drag" them, by clicking and holding the left mouse button, move them with the mouse, and "drop" them elsewhere by releasing the button.  Potential drop targets alter their appearance when a component hovers over them.</Text>
+<Text id="8">You can use the keyboard to type into text fields. [Tab] alters the focus between multiple text fields.</Text>
+<Text id="11">Exit the Librarian Interface program by choosing "Exit" from the "File" menu.  Your collection will be saved first.</Text>
+</Section>
+<Section name="howtoavoidthisdocument">
+<Title>
+<Text id="12">How to Avoid Reading This Document</Text>
+</Title>
+<Text id="13">Don't read this help text all the way through!  Just read enough to learn how to get help when you need it.</Text>
+<Text id="14">The "Help" menu item marks what may be the most appropriate help item with a little book icon.</Text>
+<Text id="15">For many controls, if you station the mouse over them a "tool tip" appears that says what they do.</Text>
+<Text id="16">Before using the Librarian Interface, first read the Greenstone documentation.</Text>
+</Section>
+</Section>
+<Section name="startingoff">
+<Title>
+<Text id="17">Starting Off</Text>
+</Title>
+<Text id="18">This section covers how to create, load, save and delete collections.</Text>
+<Section name="creatingacollection">
+<Title>
+<Text id="19">Creating a New Collection</Text>
+</Title>
+<Text id="20">To create a new collection, open the "File" menu and choose "New".  Several fields need to be filled out -- but you can change their values later if you need to, in the Format view.</Text>
+<Text id="21">"Collection title" is the text displayed at the top of your collection's home page.  It can be any length.</Text>
+<Text id="22">"Description of content" should describe, in as much detail as possible, what the collection is about. Use the [Enter] key to break it into paragraphs.</Text>
+<Text id="23">Finally you must specify whether the new collection will have the same appearance and metadata sets as an existing collection, or whether to start a default "New Collection". Default new collections have a standard configuration and use the Dublin Core metadata set. These can be changed later.</Text>
+<Text id="24">Click "OK" to create the collection. </Text>
+<Text id="25">Clicking "Cancel" returns you to the main screen immediately.</Text>
+</Section>
+<Section name="savingacollection">
+<Title>
+<Text id="26">Saving the Collection</Text>
+</Title>
+<Text id="27">Save your work regularly by opening the "File" menu and choosing "Save". Saving a collection is not the same as making it ready for use in Greenstone (see <Reference target="producingthecollection"/>).</Text>
+<Text id="28">The Librarian Interface protects your work by saving it whenever you exit the program or load another collection.</Text>
+<Text id="29a">Collections are saved to a folder within your Greenstone installation's "collect" folder, named with a short version of the collection name. Documents are saved to the "import" sub-folder, and metadata is saved to "metadata.xml" files within this folder. Configuration information is saved to the "collect.cfg" file within the "etc" sub-folder. Some information is also saved in a file named for the collection and with file extension ".col".</Text>
+</Section>
+<Section name="openingacollection">
+<Title>
+<Text id="30">Opening an Existing Collection</Text>
+</Title>
+<Text id="31">To open an existing collection, choose "Open" from the "File" menu to get the Open Collection prompt.  A list of your Greenstone collections appears. Select one to see its description, and click "Open" to load it.  If you seek a collection that resides outside Greenstone's "collect" folder, click "Browse" for a file system browsing dialog.</Text>
+<Text id="32">In case more than one Greenstone Librarian Interface program is running concurrently, the relevant directories are "locked" to prevent interference. On opening a collection, a small temporary lock file is created in its folder.  Before opening a collection, the Librarian Interface checks to ensure that no lock file already exists.  However, when the Librarian Interface is exited prematurely the lock file is sometimes left in place.  When you open such a collection, the Librarian asks if you want to "steal" control of it. Feel free to do so unless you think that someone else is currently working on the same collection.</Text>
+<Text id="33">When you open a collection that the Greenstone Librarian Interface did not create, the Dublin Core metadata set will be assigned to it, and any existing metadata will be imported just as it is when you drag in files with existing metadata. The process is described in the <Reference target="importingpreviouslyassignedmetadata"/> section. </Text>
+</Section>
+<Section name="deletingcollections">
+<Title>
+<Text id="34">Deleting Collections</Text>
+</Title>
+<Text id="35">To permanently delete collections from your Greenstone installation, choose "Delete..." from the "File" menu. A list of your collections appears. Select one to see its description, then tick the box at the bottom of the dialog and click "Delete". This action is irreversible, so be careful.</Text>
+</Section>
+</Section>
+<Section name="downloadingfiles">
+<Title>
+<Text id="36">Downloading Files From the Internet</Text>
+</Title>
+<Text id="37">The <AutoText key="glidict::GUI.Download"/> view helps you download resources from the Internet. This section explains the Librarian Interface's downloading process.</Text>
+<Section name="themirrorview">
+<Title>
+<Text id="38">The Download view</Text>
+</Title>
+<Text id="39">This section describes how to configure a download task and control the downloading process. Access the <AutoText key="glidict::GUI.Download"/> view by clicking its tab. The top half of the screen shows the downloading controls. The bottom half is initially empty, but will show a list of pending and completed download jobs. </Text>
+<Text id="39a">There are several protocols that can be used for downloading records, and these are listed on the left hand side at the top.</Text>
+<Text id="39b"><b>Web:</b> downloads web pages and files via HTTP and FTP.</Text>
+<Text id="39c"><b>OAI:</b> downloads metadata records from an OAI (Open Archives Initiative) server.</Text>
+<Text id="39d"><b>Z3950:</b> downloads MARC records that match a particular search criterion from a Z3950 server.</Text>
+<Text id="39e"><b>SRW:</b> downloads MARCXML records that match a particular search criterion from an SRW server.</Text>
+<Text id="39f">Select the appropriate type by clicking it in the left hand list. The right-hand side displays the options available for the selected download type. To find out what an option does, hover the mouse over it: a tool-tip explaining the option will appear. Some options are 'optional': these are presented with a check box which must be ticked on for the option to be used. Others are 'required': these have no check box, and a value must be given before the download is carried out. </Text>
+<Text id="39g">Once the configuration is set up, click <AutoText key="glidict::Download.ServerInformation"/> to check the connection to the server and view some basic information about the web page or server, or click <AutoText key="glidict::Mirroring.Download"/> to start the download. </Text>
+<Text id="39g-1">There are two other buttons: "Preferences", which links to the connection section of the Preferences where proxy settings can be edited; and "Clear Cache", which deletes all previously downloaded files. You will need to set up proxy information if you use a proxy server to connect to the Internet. If authentication is needed when a download is being processed, the proxy server will prompt for username and password.  The Librarian Interface does not store passwords between sessions.</Text>
+<Text id="40">Files are downloaded into a folder called <AutoText key="glidict::Tree.DownloadedFiles"/> (only present when downloading is enabled), and can be used in any collections.  Files are named by their full web URL (for Web downloads) or a combination of URL and option values (for other download types). A new folder is created for each host, followed by others for each part of the path. This ensures that each file is distinct.</Text>
+<Text id="42">The download list has an entry for each download processed. Each entry has a text region that gives details of the task along with a progress bar showing current activity. Three buttons appear to the left of each entry. "Pause" is used to pause a task. "View Log" opens a window showing the download log file. "Close" terminates the download and removes the task from the list.  </Text>
+</Section>
+</Section>
+<Section name="collectingfiles">
+<Title>
+<Text id="44">Collecting Files for Your Collection</Text>
+</Title>
+<Text id="45">Once you have a new collection you need to get some files into it.  These may come from your ordinary file space, from previously downloaded files, or from other Greenstone collections.  Some may already have attached metadata.  This section describes how to import files.</Text>
+<Section name="thegatherview">
+<Title>
+<Text id="46">The Gather View</Text>
+</Title>
+<Text id="47">This section introduces the Gather area that you use to select what files to include in the collection you are building. The Librarian Interface starts with the Gather view.  To return to this view later, click the <AutoText key="glidict::GUI.Gather"/> tab directly below the menu bar.</Text>
+<Text id="48">The two large areas titled "Workspace" and "Collection" are used to move files into your collection.  They contain "file trees" that represent files and folders.</Text>
+<Text id="49">Select an item in the tree by clicking it.  (There are other ways; see below.) Double-click a folder, or single-click the switch symbol beside it, to expand (or collapse) its contents.  Double-click a file (or right-click and select <AutoText key="glidict::Menu.Open_Externally"/>) to open it using its associated application program (see <Reference target="fileassociations"/>).</Text>
+<Text id="50">The Workspace file tree shows the sources of data available to the Librarian Interface -- the local file system (including disk and CD-ROM drives), the contents of existing Greenstone collections, and the cache of downloaded files. You can copy and view these files but you cannot move, delete, or edit them, with the exception of the downloaded files, which can be deleted.  Navigate this space to find the files you want to include in the collection.</Text>
+<Text id="51">The Collection file tree represents the contents of the collection so far.  Initially, it is empty.</Text>
+<Text id="52">You can resize the spaces by mousing over the grey bar that separates the trees (the shape of the pointer changes) and dragging.</Text>
+<Text id="53">At the bottom of the window is a status area that shows the progress of actions involving files (copying, moving and deleting). These can take some time to complete. The "Stop" button stops any action that is currently in progress. </Text>
+<Text id="54">Two large buttons occupy the lower right corner of the screen. "New Folder", with a picture of a folder, creates new folders (see <Reference target="creatingfolders"/>). "Delete", with a garbage can, removes files. Clicking the Delete button will remove any selected files from the Collection file tree. Alternatively, files can be deleted by dragging them onto the Delete button. </Text>
+<Text id="55">To select several sequential items, select the first and then hold down [Shift] and click on the last -- the selection will encompass all intervening items.  Select non-sequential files by holding down [Ctrl] while clicking.  Use these two methods together to select groups of non-adjacent items.</Text>
+</Section>
+<Section name="creatingshortcuts">
+<Title>
+<Text id="55a">Creating A Shortcut in the Workspace Tree</Text>
+</Title>
+<Text id="56">Certain folders -- such as the one containing your own web pages -- sometimes have special significance. If you like, the Librarian Interface can map them to the top level of the file tree.  To do this, right-click the desired folder.  Select "Create Shortcut", and enter a name for the folder.  To remove an item, right-click the mapped folder and select "Remove Shortcut".</Text>
+</Section>
+<Section name="creatingfolders">
+<Title>
+<Text id="57">Creating Folders</Text>
+</Title>
+<Text id="58">Use folders in the Collection file tree to group files together and make them easier to find.  Folders can be placed inside folders.  There is virtually no limit to how many folders you can have or how deeply they can be nested.</Text>
+<Text id="59">To create a new folder, optionally select an existing folder in the Collection Tree and click the New Folder button.  The new folder appears within the selected one, or at the top level if none is selected.  You are prompted for the folder's name (default "New Folder").</Text>
+<Text id="60">Folders can also be created by right-clicking in the Collection Tree, or over a folder, choosing "New Folder" and proceeding as above.</Text>
+</Section>
+<Section name="addingfiles">
+<Title>
+<Text id="61">Adding Files</Text>
+</Title>
+<Text id="62">Files can be copied into the collection by dragging and dropping.  The mouse pointer becomes a ghost of the selected item (or, if more than one is selected, the number of them).  Drop the selection into the Collection Tree to copy the files there (if the source was the Workspace Tree) or move them around within the collection (if the source was the Collection Tree).</Text>
+<Text id="63">When copying multiple files, they are all placed in the target folder at the same level, irrespective of the folder structure they occupied originally. When you copy a second file with the same name into the same folder, you are asked whether to overwrite the first one.  Respond "No" and the file will not be copied, but the others will be.  To cancel all remaining copy actions, click the "stop" button.</Text>
+<Text id="64">Only the "highest" items in a selection are moved.  A folder is higher than its children.  You cannot select files within a folder and also the folder itself.</Text>
+<Text id="65">When you add a file, the Librarian Interface searches through the source folders for auxiliary files containing metadata previously assigned to the added file and, if it finds one, begins to import this metadata.  As the operation proceeds, you may be prompted (perhaps several times) for extra information to match the imported metadata to the metadata sets in your collection.  This process involves many different prompts, described in the <Reference target="importingpreviouslyassignedmetadata"/> section.  For a more detailed explanation of associating metadata with files read Chapter 2 of the Greenstone Developer's Guide -- Getting the most out of your documents.</Text>
+<Text id="65a">You can also add a "dummy" document to the collection by right-clicking in the Collection Tree or on a folder, and selecting "New dummy document". This will create a new empty file to which metadata can be assigned. The file can be replaced with a "real" file later on.</Text>
+</Section>
+<Section name="replacingfiles">
+<Title>
+<Text id="65b">Renaming and Replacing Files</Text>
+</Title>
+<Text id="65c">Files can be renamed by right-clicking them and selecting "Rename" from the list. Enter the new name at the prompt and click "OK".</Text>
+<Text id="65d">Files can be replaced in the collection by right-clicking the file to replace and choosing "Replace". A file browser will open up: navigate to the new document and click "Open". The new document will replace the old one in the collection, and any metadata will be transferred to it. This is particularly useful for replacing dummy documents by their real ones.</Text>
+</Section>
+<Section name="removingfiles">
+<Title>
+<Text id="66">Removing Files</Text>
+</Title>
+<Text id="67">There are several methods for removing files and folders.  You must first indicate what items to remove by selecting one or more files and folders as described in <Reference target="thegatherview"/>.</Text>
+<Text id="68">Once files have been selected, click the "delete" button to remove them, or press the [Delete] key on your keyboard, or drag them from the collection to the delete button and drop them there.</Text>
+</Section>
+<Section name="explodingfiles">
+<Title>
+<Text id="exm-1">"Exploding" Metadata Files</Text>
+</Title>
+<Text id="exm-2">Metadata database file types, such as MARC, CDS/ISIS, BibTex, Refer and Procite can be imported into Greenstone but their metadata cannot be viewed or edited in the Librarian Interface. To see or edit any metadata, you need to go back to the program that created the file.</Text>
+<Text id="exm-3">"Exploding" a metadata database file splits it into individual records, with viewable and editable metadata. This process is irreversible: the original metadata file is deleted.</Text>
+<Text id="exm-4">Explodable files have a green icon in the Collection tree. To explode one, right click it and choose "Explode metadata database". A popup window shows options for the exploding process. The first option ("plugin") specifies the plugin to be used for exploding. In most cases, only one plugin will process a particular type of file, but in some cases, where different file types share the same filename extension, there may be two plugins that both process files with that extension. The "input_encoding" option can be used to specify the encoding of the database. The "metadata_set" option specifies which metadata set the new fields should be added to. If none is specified, you will be prompted for what to do with each new field in the database: add it as a new element to an existing metadata set, merge with another element, or ignore.</Text>
+<Text id="exm-5">When a file is exploded, a new empty document is created for each record, and the metadata from the record is assigned to the document. These are named using numbers such as 000001.nul, 000002.nul etc. If the "document_field" option is set (to a database field name), the value of this field, if present, will be used for the filename. The exploding process will also try to download the file and use it instead of an empty file. The "document_prefix" and "document_suffix" options can be used to make a valid URL or file path from the document_field value. The "records_per_folder" option can be used to group exploded records into sub-folders. If the database is very large, using this option will accelerate subsequent metadata editing.</Text>
+<Text id="exm-6">Explodability is determined by file extension. In some cases, files may be incorrectly labelled as explodable if they have the same file extension as an explodable file. For example, the ProCite plugin processes files with a .txt extension, but most .txt files are plain text files, not ProCite files.</Text>
+</Section>
+<Section name="filteringthetree">
+<Title>
+<Text id="69">Filtering the Trees</Text>
+</Title>
+<Text id="70">"Filtering" the collection and workspace trees allows you to narrow down the search for particular files.</Text>
+<Text id="71">The "Show Files" pull-down menu underneath each tree shows a list of predefined filters, such as "Images".  Choosing this temporarily hides all other files in the tree.  To restore the tree, change the filter back to "All Files".  These operations do not alter the collection, nor do they affect the folders in the tree.</Text>
+<Text id="72">You can specify a custom filter by typing in a pattern to match files against (Librarian Systems Specialist and Expert modes only). Use standard file system abbreviations such as "*.doc" ("*" matches any characters).</Text>
+</Section>
+</Section>
+<Section name="enrichingacollection">
+<Title>
+<Text id="73">Enriching Your Collection with Metadata</Text>
+</Title>
+<Text id="74">Having gathered several files into the collection, now enrich them with additional information called "metadata".  This section explains how metadata is created, edited, assigned and retrieved, and how to use external metadata sources (also see Chapter 2 of the Greenstone Developer's Guide -- Getting the most out of your documents).</Text>
+<Section name="theenrichview">
+<Title>
+<Text id="75">The Enrich View</Text>
+</Title>
+<Text id="76">Use the <AutoText key="glidict::GUI.Enrich"/> view to assign metadata to the documents in the collection. Metadata is data about data -- typically title, author, creation date, and so on.  Each metadata item has two parts: <AutoText key="glidict::Metadata.Element"/> tells what kind of item it is (such as author), and <AutoText key="glidict::Metadata.Value"/> gives the value of that metadata element (such as the author's name).</Text>
+<Text id="77">On the left of the <AutoText key="glidict::GUI.Enrich"/> view is the Collection Tree. All the right-click functionality that was available for the Collection Tree in the <AutoText key="glidict::GUI.Gather"/> view is available here too. To the right is the Metadata Table, which shows metadata for any selected files or folders in the Collection Tree.  Columns are named in grey at the top, and can be resized by dragging the separating line. If several files or folders are selected, black text indicates that the value is common to all of the selected items, while grey text indicates that it is not. Editing grey values will only affect those documents with that metadata. Any new metadata values entered will be added to all selected values.</Text>
+<Text id="78">A folder icon may appear beside some metadata entries.  This indicates that the values are inherited from a parent (or ancestor) folder.  Inherited metadata cannot be edited or removed, only appended to or overwritten.  Click on the folder icon to go immediately to the folder where the metadata is assigned.</Text>
+<Text id="79">Clicking on a metadata element in the table will display the existing values for that element in the <AutoText key="glidict::EnrichPane.ExistingValues" args="..."/> area below the table. This "Value Tree" expands and collapses.  Usually it is a list that shows all values entered previously for the selected element.  Clicking an entry automatically places it into the value field.  Conversely, typing in the text field selects the Value Tree entry that starts with the characters you have typed.  Pressing [Tab] auto-completes the typing with the selected value.</Text>
+<Text id="80">Metadata values can be organized into a hierarchy. This is shown in the Value Tree using folders for internal levels. Hierarchical values can be entered using the character "|" to separate the levels.  For example, "Cards|Red|Diamonds|Seven" might be used in a hierarchy that represents a pack of playing cards. This enables values to be grouped together. Groups can also be assigned as metadata to files.</Text>
+<Text id="81">Greenstone extracts metadata automatically from documents into a metadata set whose elements are prefixed by "ex.".  This has no value tree and cannot be edited. </Text>
+</Section>
+<Section name="selectingmetadatasets">
+<Title>
+<Text id="82">Selecting Metadata Sets</Text>
+</Title>
+<Text id="83">Sets of predefined metadata elements are known as "metadata sets".  An example is the Dublin Core metadata set.  When you add a metadata set to your collection, its elements become available for selection.  You can have more than one set; to prevent name clashes a short identifier that identifies the metadata set is pre-pended to the element name.  For instance the Dublin Core element Creator becomes "dc.Creator".  Metadata sets are stored in the Librarian Interface's metadata folder and have the suffix ".mds".</Text> 
+<Text id="84">When you create a new collection, the Dublin Core metadata set is added by default. You can change which metadata sets are used in a collection by clicking the "Manage Metadata Sets..." button underneath the Collection Tree in the Enrich view. This brings up a new window for managing the collection's metadata sets.</Text>
+<Text id="84a">The "Assigned Metadata Sets" list shows you what sets are currently used by the collection.</Text>
+<Text id="84b">To use another metadata set with the loaded collection, click "Add...". A popup window shows you the default metadata sets that GLI knows about. To add one of these, select it from the list and click "Add". If you have defined your own metadata set, you can use the "Browse" button to locate the file on your file system.</Text>
+<Text id="84c">To create a new metadata set, click "New...". This will launch the Greenstone Editor for Metadata Sets, GEMS. An initial popup window prompts you for the set name, namespace and description. You can also choose to base the new set on an existing one, in which case it will inherit all the elements from the specified set. Click OK. The main window shows the metadata set on the left hand side, and some attributes for the set on the right hand side. If you have based the set on an existing one, one or more elements will be displayed. Clicking one displays attributes of the element in the right hand side.</Text>
+<Text id="84d">To add a new element, right click on the set and choose "Add Element". To add a new subelement, right click on the element and choose "Add Subelement". Elements and subelements can be deleted by choosing "Delete (Sub)element" from the right click menu. </Text>
+<Text id="84e">Note: the Greenstone Editor for Metadata Sets can be run independently of GLI by selecting it from the Greenstone Start menu, or by running gens.sh or gems.bat in the gli folder of your Greenstone installation.</Text>
+<Text id="84f">Sometimes two metadata sets may have the same namespace, for example, Dublin Core and Qualified Dublin Core both use the namespace "dc". Such sets cannot be used in the collection at the same time. If you try to add a set with a namespace already used by the collection, a warning will be shown. If you go ahead, the existing set will be removed and the new one added. Any assigned metadata values will be transferred to the new set providing those elements still exist.</Text>
+<Text id="191">With GEMS upi can edit existing metadata sets as well as create new ones. Clicking the "Edit" button launches GEMS with the specified metadata set open. Once you have finished editing the set (as described above), save it (File->Save) and close GEMS.</Text>
+<Text id="192">If a collection no longer needs a metadata set, select it and press "Remove". If you have assigned any metadata to its elements you will be asked how to deal with this metadata when you next open the collection.</Text>
+</Section>
+<Section name="appendingmetadata">
+<Title>
+<Text id="85">Appending New Metadata</Text>
+</Title>
+<Text id="86">We now add a metadata item -- both element and value -- to a file.  First select the file from the Collection file tree on the left.  The action causes any metadata previously assigned to this file to appear in the table at the right.</Text>
+<Text id="87">Next select the metadata element you want to add by clicking its row in the table.</Text>
+<Text id="88">Type the value into the value field.  Use the "|" character to add structure, as described in <Reference target="theenrichview"/>. Pressing the [Up] or [Down] arrow keys will save the metadata value and move the selection appropriately. Pressing [Enter] will save the metadata value and create a new empty entry for the metadata element, allowing you to assign multiple values to a metadata element.</Text>
+<Text id="89">You can also add metadata to a folder, or to several multiply selected files at once.  It is added to all files within the folder or selection, and to child folders.  Keep in mind that if you assign metadata to a folder, any new files in it automatically inherit the folder's values.</Text>
+</Section>
+<Section name="addingpreviouslydefinedmetadata">
+<Title>
+<Text id="90">Adding Previously Defined Metadata</Text>
+</Title>
+<Text id="91">To add metadata that has an existing value, first select the file, then select the metadata element that you are assigning to, then select the required value from the value tree, expanding hierarchy folders as necessary.  The value of the selected entry automatically appears in the metadata field (alternatively, use the value tree's auto-select and auto-complete features). </Text>
+<Text id="92">The process of adding metadata with already-existing values to folders or multiple files is just the same.</Text>
+</Section>
+<Section name="updatingmetadata">
+<Title>
+<Text id="93">Editing or Removing Metadata</Text>
+</Title>
+<Text id="94">To edit or remove a piece of metadata, first select the appropriate file, and then the metadata value from the table. Edit the value field, deleting all text if you wish to remove the metadata.</Text>
+<Text id="95">The process is the same when updating a folder with child folders or multiple files, but you can only update metadata that is common to all files/folders selected.</Text>
+<Text id="96">The value tree shows all currently assigned values as well as previous values for the current session, so changed or deleted values will remain in the tree. Closing the collection and then re-opening it will remove all values that are no longer assigned.</Text>
+</Section>
+<Section name="reviewingmetadata">
+<Title>
+<Text id="97">Reviewing Assigned Metadata</Text>
+</Title>
+<Text id="98">Sometimes you need to see the metadata assigned to many files at once -- for instance, to determine how many files are left to work on, or to get some idea of the spread of dates.</Text>
+<Text id="99">Select the files in the Collection Tree you wish to examine, then right-click and choose "Assigned Metadata...". A window called "All Metadata", dominated by a large table with many columns, appears.  The first column shows file names; the rows show all metadata values assigned to those files.</Text>
+<Text id="100">Drawing the table can take some time if many files are selected.  You can continue to use the Librarian Interface while the "All Metadata" window is open.</Text>
+<Text id="101">When it gets too large, you can filter the "All Metadata" table by applying filters to the columns.  As new filters are added, only those rows that match them remain visible.  To set, modify or clear a filter, click on the "funnel" icon at the top of a column.  You are prompted for information about the filter. Once a filter is set, the column header changes colour.</Text>
+<Text id="102">The filter prompt has a "Simple" and an "Advanced" tab.  The Simple version filters columns so that they only show rows that contain a certain metadata value ("*" matches all values).  You can select metadata values from the pull-down list. The Advanced version allows different matching operations: must start with, does not contain, alphabetically less than and is equal to.  The value to be matched can be edited to be any string (including "*"), and you can choose whether the matching should be case insensitive.  Finally, you can specify a second matching condition that you can use to specify a range of values (by selecting AND) or alternative values (by selecting OR).  Below this area is a box that allows you to change the sort order (ascending or descending).  Once you have finished, click "Set Filter" to apply the new filter to the column. Click "Clear Filter" to remove a current filter.  Note that the filter details are retained even when the filter is cleared.</Text>
+<Text id="103">For example, to sort the "All Metadata" table, choose a column, select the default filter setting (a Simple filter on "*"), and choose ascending or descending ordering.</Text>
+</Section>
+<Section name="importingpreviouslyassignedmetadata">
+<Title>
+<Text id="104">Importing Previously Assigned Metadata</Text>
+</Title>
+<Text id="105">This section describes how to import previously assigned metadata: metadata assigned to documents before they were added to the collection.</Text>
+<Text id="106">If metadata in a form recognized by the Librarian Interface has been previously assigned to a file -- for example, when you choose documents from an existing Greenstone collection -- it is imported automatically when you add the file. To do this, the metadata must be mapped to the metadata sets available in the collection.</Text>
+<Text id="107">The Librarian Interface prompts for the necessary information.  The prompt gives brief instructions and then shows the name of the metadata element that is being imported, just as it appears in the source file.  This field cannot be edited or changed.  Next you choose what metadata set the new element should map to, and then the appropriate metadata element in that set.  The system automatically selects the closest match, in terms of set and element, for the new metadata.</Text>
+<Text id="108">Having checked the mapping, you can choose "Add" to add the new metadata element to the chosen metadata set.  (This is only enabled if there is no element of the same name within the chosen set.) "Merge" maps the new element to the one chosen by the user.  Finally, "Ignore" does not import any metadata with this element name.  Once you have specified how to import a certain piece of metadata, the mapping information is retained for the collection's lifetime.</Text>
+<Text id="109">For details on the metadata.xml files which Greenstone uses to store the metadata, see Chapter 2 of the Greenstone Developer's Guide -- Getting the most out of your documents.</Text>
+</Section>
+</Section>
+<Section name="designingacollection">
+<Title>
+<Text id="110">Configuring Your Collection</Text>
+</Title>
+<Text id="111">Once your files are marked up with metadata, you next decide how the documents should be accessed by the end users. What kind of information is searchable?  What ways are provided to browse through the documents? These things can be customized; this section describes how to do it.</Text>
+<Section name="thedesignview">
+<Title>
+<Text id="112">The Design View</Text>
+</Title>
+<Text id="113">This section introduces you to the design view and explains how to navigate between the various views within this pane.</Text>
+<Text id="114">With the Librarian Interface, you can configure how the documents are processed, and how the collection is accessed by the user.  The configuration options are divided into different sections, each associated with a particular stage of collection customization.</Text>
+<Text id="115">On the left is a list of different views, and on the right are the controls associated with the current one.  To change to a different view, click its name in the list.</Text>
+<Text id="116">To understand the stages and terms involved in designing a collection, first read Chapters 1 and 2 of the Greenstone Developer's Guide.</Text>
+</Section>
+<Section name="plugins">
+<Title>
+<Text id="121">Document Plugins</Text>
+</Title>
+<Text id="122">This section describes how to configure the document plugins the collection uses.  It explains how you specify what plugins to use, what parameters to pass to them, and in what order they occur.  Under the "Design" tab, click "Document Plugins".</Text>
+<Text id="123">To add a plugin, select it using the "Select plugin to add" pull-down list near the bottom and then click "Add Plugin".  A window appears entitled "Configuring Arguments"; it is described later.  Once you have configured the new plugin, it is added to the end of the "Assigned Plugins" list. In Librarian mode, each plugin, except for UnknownPlug, may only occur once in the collection. In higher modes, plugins can appear multiple times. The process_exp argument will need to be set in order to make this useful.</Text>
+<Text id="123aa">To see a short description of a plugin, select it in the "Select plugin to add" pull-down list, then hover the mouse over it. A tool-tip displaying the description will appear.</Text>
+<Text id="124">To remove a plugin, select it in the list and click "Remove Plugin".</Text>
+<Text id="125">Plugins are configured by providing arguments.  To alter them, select the plugin from the list and click "Configure Plugin" (or double-click the plugin). A "Configuring Arguments" dialog appears with various controls for specifying arguments.</Text>
+<Text id="126">There are different kinds of controls.  Some are checkboxes, and clicking one adds the appropriate option to the plugin.  Others are text strings, with a checkbox and a text field.  Click the box to enable the argument, then type appropriate text (regular expression, file path etc) in the box.  Others are pull-down menus from which you can select from a given set of values.  To learn what an argument does, let the mouse hover over its name for a moment and a description will appear.</Text>
+<Text id="127">When you have changed the configuration, click "OK" to commit the changes and close the dialog, or "Cancel" to close the dialog without changing any plugin arguments.</Text>
+<Text id="128">The plugins in the list are executed in order, and the ordering is sometimes important. The order of the plugins can be changed in Library Systems Specialist and Expert modes only (see <Reference target="preferences"/>).    </Text>
+</Section>
+<Section name="searchindexes">
+<Title>
+<Text id="134">Search Indexes</Text>
+</Title>
+<Text id="si-1">Indexes specify what parts of the collection are searchable.  This section explains how to add and remove indexes, and set a default index.  Under the <AutoText key="glidict::GUI.Design"/> tab, click <AutoText key="glidict::CDM.GUI.Indexes"/>.</Text>
+<Text id="si-2">The top right of the <AutoText key="glidict::CDM.GUI.Indexes"/> panel displays information about which indexer is currently being used by the collection. This can be changed by clicking <AutoText key="glidict::CDM.BuildTypeManager.Change"/>. A popup window appears with the list of options: MG, MGPP, and Lucene. Changing this affects how the indexes are built, and may affect search functionality.</Text>
+<Text id="si-2a">The <AutoText key="glidict::CDM.IndexManager.Indexes"/> list shows what indexes are currently assigned to the collection. </Text>
+<Text id="si-3">To add an index, click <AutoText key="glidict::CDM.IndexManager.New_Index"/>... A popup window appears with a list of sources, which includes text and metadata. Select which sources you want to index. The <AutoText key="glidict::CDM.IndexManager.Select_All"/> and <AutoText key="glidict::CDM.IndexManager.Select_None"/> buttons will check or uncheck all of the items in the list, respectively. Once a new index has been defined, click <AutoText key="glidict::CDM.IndexManager.Add_Index"/> to add it to the collection. <AutoText key="glidict::CDM.IndexManager.Add_Index"/> will only become active once the settings describe a new index that is not already assigned to the collection. </Text>
+<Text id="s1-3a">For MG indexes, you also need to choose the granularity of the index, using the <AutoText key="glidict::CDM.IndexManager.Level"/> menu. </Text>
+<Text id="si-4">For MGPP and Lucene indexes, index granularity is determined globally, not per index. The possible levels are displayed on the main <AutoText key="glidict::CDM.GUI.Indexes"/> pane, and can be added to the collection by ticking the checkboxes.</Text>
+<Text id="si-5">A special index is available for MGPP and Lucene: an "allfields" index which merely provides combined searching over all specified indexes, without having to specify a separate index that contains all sources. To add this index, check the <AutoText key="glidict::CDM.IndexManager.Allfields_Index"/> check box and click <AutoText key="glidict::CDM.IndexManager.Add_Index"/>.</Text>
+<Text id="si-6">For MGPP and Lucene, an <AutoText key="glidict::CDM.IndexManager.Add_All"/> button is also provided, as a shortcut to adding all metadata and text sources as individual indexes.</Text>
+<Text id="si-7">To edit an index, select it and click <AutoText key="glidict::CDM.IndexManager.Edit_Index"/>. A similar dialog to the <AutoText key="glidict::CDM.IndexManager.New_Index"/> one is shown. </Text>
+<Text id="si-8">To remove an index, select it from the list of assigned indexes and click <AutoText key="glidict::CDM.IndexManager.Remove_Index"/>.</Text>
+<Text id="si-9">The order that the indexes are specified in the Assigned Indexes list is the order they appear in the drop down menu on the search page. Use the <AutoText key="glidict::CDM.Move.Move_Up"/> and <AutoText key="glidict::CDM.Move.Move_Up"/> buttons to change this ordering. </Text>
+<Text id="si-10">The one that is selected by default on the search page is called the "default index". This can be set by selecting an index from the list and clicking "Set Default". The default index is tagged with "[Default Index]" in the "Assigned Indexes" list. If no default index is set, the first one in the list will be used as the default.</Text>
+<Text id="si-11">The names used for the drop-down list of indexes on the search page can be set in the <AutoText key="glidict::CDM.GUI.SearchMetadata"/> part of the <AutoText key="glidict::GUI.Format"/> panel (see <Reference target="searchmetadatasettings"/>).</Text>
+<Text id="si-12">For MG and MGPP indexes, there are further options controlling how the indexes are built. Stemming and case-folding may be enabled or disabled in the indexes&mdash;if disabled, the options will not be displayed on the preferences page of the collection. Accent-folding is also available for MGPP indexes. This works in a similar way to case-folding, but instead of lower and upper case letters matching, letters with diacritics match those without.</Text>
+</Section>
+<Section name="partitionindexes">
+<Title>
+<Text id="143">Partition Indexes</Text>
+</Title>
+<Text id="144">Indexes are built on particular text or metadata sources.  The search space can be further controlled by partitioning the indexes, either by language or by a predetermined filter.  This section describes how to do this.  Under the "Design" tab, click "Partition Indexes".</Text>
+<Text id="145">The "Partition Indexes" view has three tabs; "Define Filters", "Assign Partitions" and "Assign Languages".  To learn more about partitions read about sub-collections and sub-indexes in Chapter 2 of the Greenstone Developer's Guide.</Text>
+<Text id="146">The Partition Indexes screen is only enabled in Library Systems Specialist and Expert modes (see <Reference target="preferences"/>). Note that for MG collections, the total number of partitions generated is a combination of all indexes, sub-collection filters and languages chosen. Two indexes with two sub-collection filters in two languages would yield eight index partitions. For MGPP, all indexes are created in one physical index, so there would only be four index partitions. For Lucene, the number of physical indexes is determined by the number of levels assigned to the collection, one index per level. So for the above situation, one level would result in four physical indexes, while two levels would result in eight.</Text>
+<Section name="definefilters">
+<Title>
+<Text id="147">Define Filters</Text>
+</Title>
+<Text id="148">Filters allow you to group together into a sub-collection all documents in an index for which a metadata value matches a given pattern.</Text>
+<Text id="149">To create a filter, click the "Define Filters" tab and enter a name for the new filter into the "Subcollection filter name:" field.  Next choose a document attribute to match against, either a metadata element or the name of the file in question.  Enter a regular expression to use during the matching. You can toggle between "Including" documents that match the filter, or "Excluding" them.  Finally, you can specify any of the standard PERL regular expression flags to use when matching (e.g.  "i" for case-insensitive matching). Finally, click "Add Filter" to add the filter to the "Defined Subcollection Filters" list.</Text>
+<Text id="150">To remove a filter, select it from the list and click "Remove Filter".</Text>
+<Text id="151">To alter a filter, select it from the list, change any of the values that appear in the editing controls and click "Replace Filter" to commit the changes.</Text>
+<Text id="151a">Defining filters does not create sub-collections. Sub-collections are specified in the <AutoText key="glidict::CDM.SubcollectionManager.Subindex_Controls"/>, based on the filters you have just defined.</Text>
+</Section>
+<Section name="assignpartitions">
+<Title>
+<Text id="152">Assign Partitions</Text>
+</Title>
+<Text id="153">Having defined one or more sub-collection filters, use the "Assign Partitions" tab to build indexes for it (or for a group of filters).  Select the desired filter or filters from the "Defined Subcollection Filters" list and click "Add Partition". Each specified partition will result in a sub-collection that contains documents that match any of the filters associated with that partition.</Text>
+<Text id="154a">To alter a partition, select it from the list, modify the filters, and click <AutoText key="glidict::CDM.SubcollectionIndexManager.Replace_Subindex"/>.</Text>
+<Text id="154">To remove a partition, select it from the list and click "Remove Partition".</Text>
+<Text id="154b">The order that the partitions are specified in the Assigned Partitions list is the order they appear in the drop down menu on the search page. Use the <AutoText key="glidict::CDM.Move.Move_Up"/> and <AutoText key="glidict::CDM.Move.Move_Up"/> buttons to change this ordering.</Text>
+<Text id="155">To make a partition the default one, select it from the list and click <AutoText key="glidict::CDM.SubcollectionIndexManager.Set_Default_Subindex"/>.</Text>
+<Text id="155a">The names used for the drop-down list of partitions on the search page can be set in the <AutoText key="glidict::CDM.GUI.SearchMetadata"/> part of the <AutoText key="glidict::GUI.Format"/> panel (see <Reference target="searchmetadatasettings"/>).</Text>
+</Section>
+<Section name="assignlanguages">
+<Title>
+<Text id="156">Assign Languages</Text>
+</Title>
+<Text id="157">This section details how to restrict search indexes to particular languages. You do this by generating a partition using the "Assign Languages" tab of the "Partition Indexes" view.</Text>
+<Text id="158">To add a new language partition, use the "Assign Languages" tab to build an index for it.  Select one or more languages from the "Languages to add" list and click "Add Partition".</Text>
+<Text id="158a">To change an existing partition, select it from the "Assigned Language Partitions" list, modify the selected languages in the "Languages to add" list below, and click "Replace Partition".</Text>
+<Text id="159">To remove a language partition, select it from the "Assigned Language Partitions" list and click "Remove Partition".</Text>
+<Text id="159a">The order that the language partitions are specified in the Assigned Language Partitions list is the order they appear in the drop down menu on the search page. Use the <AutoText key="glidict::CDM.Move.Move_Up"/> and <AutoText key="glidict::CDM.Move.Move_Up"/> buttons to change this ordering.</Text>
+<Text id="160">To set the default language partition, select it from the list and click "Set Default".</Text>
+<Text id="160a">The names used for the drop-down list of language partitions on the search page can be set in the <AutoText key="glidict::CDM.GUI.SearchMetadata"/> part of the <AutoText key="glidict::GUI.Format"/> panel (see <Reference target="searchmetadatasettings"/>).</Text>
+</Section>
+</Section>
+<Section name="classifiers">
+<Title>
+<Text id="166">Browsing Classifiers</Text>
+</Title>
+<Text id="167">This section explains how to assign "classifiers", which are used for browsing, to the collection.  Under the "Design" tab, click "Browsing Classifiers".</Text>
+<Text id="168">To add a classifier, select it using the "Select classifier to add" pull-down list near the bottom and then click "Add Classifier...".  A window appears entitled "Configuring Arguments"; instructions for this dialog are just the same as for plugins (see <Reference target="plugins"/>). Once you have configured the new classifier, it is added to the end of the "Assigned Classifiers" list.</Text>
+<Text id="168a">To see a short description of a classifier, select it in the "Select classifier to add" pull-down list, then hover the mouse over it. A tool-tip displaying the description will appear.</Text>
+<Text id="168b">Each classifier has several arguments that can be configured. Important arguments include "metadata", which specifies the metadata that documents will be classified on, and "buttonname", which is the name that will appear in the navigation bar.</Text>
+<Text id="169">To remove a classifier, select it from the list and click "Remove Classifier".</Text>
+<Text id="170">To change the arguments for a classifier, select it from the list and click "Configure Classifier" (or double-click on the classifier in the list).</Text>
+<Text id="171">The ordering of classifiers in the collection's navigation bar is reflected in their order here.  To change it, select the classifier you want to move and click "Move Up" or "Move Down".</Text>
+<Text id="172">For further information on classifiers read Chapter 2, Greenstone Developer's Guide -- Getting the most out of your documents.</Text>
+</Section>
+</Section>
+<Section name="producingthecollection">
+<Title>
+<Text id="193">Producing Your Collection</Text>
+</Title>
+<Text id="194">Having collected the documents for the collection, annotated them with metadata, and designed how the collection will appear, you can now produce the collection using Greenstone.  This section explains how.</Text>
+<Section name="thecreateview">
+<Title>
+<Text id="195">The Create View</Text>
+</Title>
+<Text id="196">The Create view is used to create the collection by running Greenstone collection-building scripts on the information you have provided. Access the Create view by clicking the Create tab.</Text>
+<Text id="196a">Clicking "Build Collection" initiates the collection building process.  The time this takes depends on the size of the collection and the number of indexes being created (for huge collections it can be hours). A progress bar indicates how much of the process has been completed. To cancel the process at any time, click "Cancel Build". The lower part of the panel shows some output from the build process. The upper part shows some options for controlling the build process.</Text>
+<Text id="197">Once the collection has successfully built, clicking "Preview Collection" will launch a web browser showing the home page of the collection.</Text>
+</Section>
+<Section name="builderrors">
+<Title>
+<Text id="199a">Errors in collection building</Text>
+</Title>
+<Text id="199b">Sometimes things go wrong during collection building. Maybe some files couldn't be processed: the rest of the collection builds fine, and can be previewed, but some documents are absent. Or the whole collection is not built properly, in which case a message says <AutoText key="glidict::CollectionManager.Cannot_Create_Collection"/> When this happens, it may be helpful to switch the GLI into expert mode (File->Preferences->Mode, see <Reference target="preferences"/>), set the build option "verbosity" to 5, and rebuild, to see if there are any error messages.</Text>
+</Section>
+<Section name="expertbuilding">
+<Title>
+<Text id="198a">Create view in Expert mode</Text>
+</Title>
+<Text id="198">In Expert mode, you can use the "Message Log" entry at the left to review previous attempts to build the collection, whether successful or not. Select the log you want by clicking on the desired date in the "Log History" list.</Text>
+<Text id="200a">In this mode, a full list of import and build options are shown in the Import and Build tabs to the left. The various settings are controlled just like the "Configuring Arguments" window described in the <Reference target="plugins"/> section.  Some fields require numeric arguments, and you can type these in or use the arrows to increase or decrease the current value (in some cases, the interface restricts the range you can enter).  Others are enabled by clicking a checkbox (click again to disable).</Text>
+<Text id="201a">For more information about importing and building read Chapter 1 of the Greenstone Developer's Guide -- Understanding the collection-building process.</Text>
+</Section>
+</Section>
+<Section name="formattingacollection">
+<Title>
+<Text id="fc-1">Customizing Your Collection's Appearance</Text>
+</Title>
+<Text id="fc-2">Once you have built the collection, you next decide how it should appear to the user. What names should be used for the drop-down list of indexes in the search form? How should search results be displayed? What metadata should be displayed when a document is viewed? These can be customized; this section explains how to do it. </Text>
+<Section name="theformatview">
+<Title>
+<Text id="fc-3">The Format View</Text>
+</Title>
+<Text id="fc-4">This section introduces you to the Format view and explains how to navigate between the various views within this pane.</Text>
+<Text id="fc-5">With the Librarian Interface you can configure how the collection appears to the user. The configuration options are divided into sections, each associated with a different type of customization.</Text>
+<Text id="fc-6">On the left is a list of views and on the right are the controls associated with the current one. To change to a different view, click its name in the list.</Text>
+<Text id="fc-7">Under the list of views is a "Preview Collection" button. Changes made in the Format view don't require a collection rebuild, so can be previewed straight away. However, the collection must have been built at least once to allow previewing.</Text>
+</Section>
+<Section name="generalsettings">
+<Title>
+<Text id="117">General</Text>
+</Title>
+<Text id="118">This section explains how to review and alter the general settings associated with your collection.  First, under the "Format" tab, click "General".</Text>
+<Text id="119">Here some collection wide metadata can be set or modified, including the title and description entered when starting a new collection.</Text>
+<Text id="120">First are the contact email addresses of the collection's creator and maintainer. The following field allows you to change the collection title. The folder that the collection is stored in is shown next, but this cannot be altered. Then comes the icon to show at the top left of the collection's "About" page (in the form of a URL), followed by the icon used in the Greenstone library page to link to the collection. Next is a checkbox that controls whether the collection should be publicly accessible. Finally comes the "Collection Description" text area as described in <Reference target="creatingacollection"/>.</Text>
+</Section>
+<Section name="searchmetadatasettings">
+<Title>
+<Text id="fc-s1">Search</Text>
+</Title>
+<Text id="fc-s2">This section explains how to set the display text for the drop down lists on the search page. Under the "Format" tab, click "Search".</Text>
+<Text id="fc-s3">This pane contains a table listing each search index, index level (for MGPP or Lucene collections), and index or language partition. Here you can enter the text to be used for each item in the various drop-down lists on the search page. This pane only allows you to set the text for one language, the current language used by GLI. To translate these names for other languages, use the Translate Text part of the Format view (see <Reference target="translatetext"/>).</Text>
+</Section>
+<Section name="formatstatements">
+<Title>
+<Text id="173">Format Features</Text>
+</Title>
+<Text id="174">The web pages you see when using Greenstone are not pre-stored but are generated 'on the fly' as they are needed. Format commands are used to change the appearance of these generated pages. They affect such things as which buttons appear when a document is shown, and what links are displayed by the DateList classifier.  Format commands are not easy to develop, and you should read Chapter 2 of the Greenstone Developer's Guide. This section discusses the format settings, and how the Librarian Interface gives access to them.  Under the "Format" tab, click "Format Features".</Text>
+<Text id="175">You can apply a format command to anything in the "Choose Feature" pull-down list, which includes each classifier and a predefined list of features.  When you select a feature, there are two types of control.  Some features are simply enabled or disabled, and this is controlled by a checkbox.  Others require a format string to be specified.  For these there is a pull-down list ("Affected Component") for selecting which part of the feature the string applies to (if necessary), a text area ("HTML Format String") for entering the string, and a selection of predefined "Variables".  To insert a variable into a format string, position the cursor at the place to insert, then select the desired variable from the <AutoText key="glidict::CDM.FormatManager.Insert_Variable"/> combobox.</Text>
+<Text id="176">You can specify a default format for a particular component by selecting the "All Features" feature.  This format is then applied to all applicable features unless a more specific one is defined.</Text>
+<Text id="177">To add a new format command, select the applicable feature and component. The default value for this command will be displayed in grey. Click <AutoText key="glidict::CDM.FormatManager.Add"/> to assign it to the collection. The "HTML Format String" will become editable and you can change it if you wish. Only one format command can be assigned to each feature/component combination.</Text>
+<Text id="178">To remove a format command, select it from the list and click "Remove Format".</Text>
+<Text id="180">For more information about variables and the feature components, read Chapter 2 of the Greenstone Developer's Guide.</Text>
+</Section>
+<Section name="translatetext">
+<Title>
+<Text id="182">Translate Text</Text>
+</Title>
+<Text id="183">This section describes the translation view, where you can translate text fragments for parts of the collection's interface into other languages. Under the "Format" tab, click "Translate Text".</Text>
+<Text id="184">First choose an entry from the "Features" list.  The language-specific strings associated with this feature appear below.  Use the "Language of translation" pull-down list to select the target language, and type the translated text into the text area, referring to the "Initial Text Fragment" if necessary.  Click "Add Translation" when finished.</Text>
+<Text id="185">To remove an existing translation, select it in the "Assigned Translations" table and click "Remove Translation".</Text>
+<Text id="186">To edit a translation, select it, edit the "Translated Text" area and click "Replace Translation".</Text>
+</Section>
+<Section name="xcollectionsearching">
+<Title>
+<Text id="161">Cross-Collection Search</Text>
+</Title>
+<Text id="162">Greenstone can search across several different collections as though they were one. This is done by specifying a list of other collections to be searched along with the current one.  Under the "Format" tab, click "Cross-Collection Search".</Text>
+<Text id="163">The Cross-Collection Search view shows a checklist of available collections.  The current collection is ticked and cannot be de-selected.  To add another collection to be searched in parallel, click it in the list (click again to remove it).  If only one collection is selected, there is no cross-collection searching.</Text>
+<Text id="164">If the individual collections do not have the same indexes (including sub-collection partitions and language partitions) as each other, cross-collection searching will not work properly. The user will only be able to search using indexes common to all collections.</Text>
+<Text id="165">For further details, see Chapter 1 of the Greenstone Developer's Guide.</Text>
+</Section>
+<Section name="collectionspecificmacros">
+<Title>
+<Text id="fc-m1">Collection Specific Macros</Text>
+</Title>
+<Text id="fc-m2">Under the "Format" tab, click "Collection Specific Macros".</Text> 
+<Text id="fc-m3">This view shows the contents of the collection's extra.dm macro file. This is where collection specific macros can be defined. To learn more about macros, see Chapter 3 of the Greenstone Developer's Guide.</Text>
+</Section>
+</Section>
+<Section name="miscellaneous">
+<Title>
+<Text id="202">Miscellaneous</Text>
+</Title>
+<Text id="203">This section describes features of the Librarian Interface that are not associated with any particular view.</Text>
+<Section name="preferences">
+<Title>
+<Text id="204">Preferences</Text>
+</Title>
+<Text id="205">This section explains the preferences dialog, accessed by opening "File" -> "Preferences".</Text>
+<Text id="206">The preferences window opens at the "General" tab. The first option is a text field for entering your e-mail address. This will be used for the "creator" and "maintainer" collection metadata items for new collections. The next option is a pull-down list of the languages in which the Librarian Interface can be presented. If you change the dictionary by choosing one from the list, the Librarian Interface must be restarted in order to load the new language strings from the dictionary.</Text>
+<Text id="207">If "View Extracted Metadata" is checked, the various controls dealing with metadata always show all metadata that has been extracted automatically from documents.  De-selecting it hides this metadata (although it is still available during collection design, and within the final Greenstone collection). If "Show file sizes" is checked, the file size is shown next to each file in the Workspace and Collection file trees in the Gather and Enrich views.</Text>
+<Text id="208">The "Mode" tab is used to control the level of detail within the interface. At its lowest setting, "Library Assistant", the design view is disabled, arguments requiring regular expressions are hidden and the collection building process produces a minimal log of events. In contrast the highest setting, "Expert", provides access to all of the features of design, including plugin positioning and regular expression arguments, and also allows the full output from the collection building to be recorded in the logs. To change or review modes, click the radio button next to the mode you are interested in. You can quickly review what mode you are in by looking at the Librarian Interface's title bar.</Text>
+<Text id="210">The "Connection" tab lets you alter the path to the locally-running Greenstone library server, which is used when Previewing collections. It also lets you set proxy information for connecting to the Internet (e.g. when downloading files; see the <Reference target="downloadingfiles"/> section for details). Check the box to enable proxy connection and supply details of the proxy host address and port number. The proxy connection is established when you close the Preferences dialog.</Text>
+<Text id="211">During the course of a session the Librarian Interface may give warning messages which inform you of possibly unforeseen consequences of an action.  You can disable the messages by checking the "Do not show this warning again" box. You can re-enable warning messages using the "Warnings" tab.  Check the boxes next to warning messages you want to see again.</Text>
+</Section>
+<Section name="fileassociations">
+<Title>
+<Text id="212">File Associations</Text>
+</Title>
+<Text id="213">The Librarian Interface uses particular application programs to open particular file types. To alter file associations open the "File" menu and click "File Associations...".</Text>
+<Text id="214">To add an association, select the target file extension from the pull-down list, or type in a new extension (do not include the ".").  Next either type the command that launches the desired application in the appropriate field, or choose the application from the "Browse" dialog.  "%1" can be used in the launch command to insert the name of the file being opened.  Once these are filled out, "Add" is enabled and can be clicked to add the association.</Text>
+<Text id="215">To edit an association, select an existing file extension.  Any existing associated command is shown in the "launch command" field.  Edit it, and then click "Replace".</Text>
+<Text id="216">To remove an association, select an existing file extension and click "Remove". (The file extension remains in the "For Files Ending" pull-down list.)</Text>
+<Text id="217">File associations are stored in the Librarian Interface's main folder, in a file called "associations.xml".</Text>
+</Section>
+<Section name="exporting">
+<Title>
+<Text id="exp-1">Exporting collections to other formats</Text>
+</Title>
+<Text id="exp-2">Greenstone can export the contents and/or metadata of a collection to several standard formats, including METS, DSpace and MARCXML.</Text>
+<Text id="exp-3">To export one or more collections, open the "File" menu and choose "Export...". You can choose which format to export to by selecting it in the "Export to" drop-down list. Specify a name for the directory where you want to put the exported files&mdash;the files will end up in &lt;path to greenstone&gt;/tmp/exported_xxx, where xxx is the name you specified. Select one or more collections in the list of available collections, then click "Export collection(s)".</Text>
+<Text id="exp-4">There are other options specific to the various formats. You can specify XSLT files which will be applied to the resulting XML document(s) in order to customize the output format. Exporting to MARCXML uses a mapping file to map Greenstone metadata to MARC fields. The default mapping file maps only Dublin Core metadata. You can specify a custom mapping file to be used instead.</Text>
+</Section>
+<Section name="exportingcollections">
+<Title>
+<Text id="218">Exporting Collections to CD/DVD</Text>
+</Title>
+<Text id="219">Greenstone can export one or more collections to a self-installing CD/DVD for Windows. </Text>
+<Text id="220">To export a collection, open the "File" menu and choose "Write CD/DVD Image". A list of Greenstone collections appears; click on any one to see its description. Tick the check boxes of the collections to export. You can enter the CD/DVD's name in the "CD/DVD name" box: this is what will appear in the Start menu when the CD/DVD has been installed. You can choose whether the resulting CD-ROM or DVD runs directly from the disk drive, or installs some files onto the computer. Then click "Write CD/DVD image". The process involves copying many files and may take a few minutes.</Text>
+<Text id="221">Upon completion, Greenstone will show the name of a folder containing the exported collections. Use a CD/DVD writer to copy its contents to a blank CD/DVD.</Text>
+</Section>
+</Section>
+</Document>
Index: /tags/greenstone-3_02-distribution/gli/help/en/help_index.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/help_index.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/help_index.xml	(revision 13928)
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Document><Section name="introduction"><Title>Introduction</Title><Section name="ofmiceandmenus"><Title>Of Mice and Menus</Title></Section><Section name="howtoavoidthisdocument"><Title>How to Avoid Reading This Document</Title></Section></Section><Section name="startingoff"><Title>Starting Off</Title><Section name="creatingacollection"><Title>Creating a New Collection</Title></Section><Section name="savingacollection"><Title>Saving the Collection</Title></Section><Section name="openingacollection"><Title>Opening an Existing Collection</Title></Section><Section name="deletingcollections"><Title>Deleting Collections</Title></Section></Section><Section name="downloadingfiles"><Title>Downloading Files From the Internet</Title><Section name="themirrorview"><Title>The Download view</Title></Section></Section><Section name="collectingfiles"><Title>Collecting Files for Your Collection</Title><Section name="thegatherview"><Title>The Gather View</Title></Section><Section name="creatingshortcuts"><Title>Creating A Shortcut in the Workspace Tree</Title></Section><Section name="creatingfolders"><Title>Creating Folders</Title></Section><Section name="addingfiles"><Title>Adding Files</Title></Section><Section name="replacingfiles"><Title>Renaming and Replacing Files</Title></Section><Section name="removingfiles"><Title>Removing Files</Title></Section><Section name="explodingfiles"><Title>"Exploding" Metadata Files</Title></Section><Section name="filteringthetree"><Title>Filtering the Trees</Title></Section></Section><Section name="enrichingacollection"><Title>Enriching Your Collection with Metadata</Title><Section name="theenrichview"><Title>The Enrich View</Title></Section><Section name="selectingmetadatasets"><Title>Selecting Metadata Sets</Title></Section><Section name="appendingmetadata"><Title>Appending New Metadata</Title></Section><Section name="addingpreviouslydefinedmetadata"><Title>Adding Previously Defined Metadata</Title></Section><Section name="updatingmetadata"><Title>Editing or Removing Metadata</Title></Section><Section name="reviewingmetadata"><Title>Reviewing Assigned Metadata</Title></Section><Section name="importingpreviouslyassignedmetadata"><Title>Importing Previously Assigned Metadata</Title></Section></Section><Section name="designingacollection"><Title>Configuring Your Collection</Title><Section name="thedesignview"><Title>The Design View</Title></Section><Section name="plugins"><Title>Document Plugins</Title></Section><Section name="searchindexes"><Title>Search Indexes</Title></Section><Section name="partitionindexes"><Title>Partition Indexes</Title><Section name="definefilters"><Title>Define Filters</Title></Section><Section name="assignpartitions"><Title>Assign Partitions</Title></Section><Section name="assignlanguages"><Title>Assign Languages</Title></Section></Section><Section name="classifiers"><Title>Browsing Classifiers</Title></Section></Section><Section name="producingthecollection"><Title>Producing Your Collection</Title><Section name="thecreateview"><Title>The Create View</Title></Section><Section name="builderrors"><Title>Errors in collection building</Title></Section><Section name="expertbuilding"><Title>Create view in Expert mode</Title></Section></Section><Section name="formattingacollection"><Title>Customizing Your Collection's Appearance</Title><Section name="theformatview"><Title>The Format View</Title></Section><Section name="generalsettings"><Title>General</Title></Section><Section name="searchmetadatasettings"><Title>Search</Title></Section><Section name="formatstatements"><Title>Format Features</Title></Section><Section name="translatetext"><Title>Translate Text</Title></Section><Section name="xcollectionsearching"><Title>Cross-Collection Search</Title></Section><Section name="collectionspecificmacros"><Title>Collection Specific Macros</Title></Section></Section><Section name="miscellaneous"><Title>Miscellaneous</Title><Section name="preferences"><Title>Preferences</Title></Section><Section name="fileassociations"><Title>File Associations</Title></Section><Section name="exporting"><Title>Exporting collections to other formats</Title></Section><Section name="exportingcollections"><Title>Exporting Collections to CD/DVD</Title></Section></Section></Document>
Index: /tags/greenstone-3_02-distribution/gli/help/en/howtoavoidthisdocument.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/howtoavoidthisdocument.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/howtoavoidthisdocument.htm	(revision 13928)
@@ -0,0 +1,23 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="howtoavoidthisdocument"><font size="5" face="Verdana"><strong>1.2: How to Avoid Reading This Document</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Don't read this help text all the way through!  Just read enough to learn how to get help when you need it.</p>
+
+<p>The "Help" menu item marks what may be the most appropriate help item with a little book icon.</p>
+
+<p>For many controls, if you station the mouse over them a "tool tip" appears that says what they do.</p>
+
+<p>Before using the Librarian Interface, first read the Greenstone documentation.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/importingpreviouslyassignedmetadata.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/importingpreviouslyassignedmetadata.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/importingpreviouslyassignedmetadata.htm	(revision 13928)
@@ -0,0 +1,25 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="importingpreviouslyassignedmetadata"><font size="5" face="Verdana"><strong>5.7: Importing Previously Assigned Metadata</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>This section describes how to import previously assigned metadata: metadata assigned to documents before they were added to the collection.</p>
+
+<p>If metadata in a form recognized by the Librarian Interface has been previously assigned to a file -- for example, when you choose documents from an existing Greenstone collection -- it is imported automatically when you add the file. To do this, the metadata must be mapped to the metadata sets available in the collection.</p>
+
+<p>The Librarian Interface prompts for the necessary information.  The prompt gives brief instructions and then shows the name of the metadata element that is being imported, just as it appears in the source file.  This field cannot be edited or changed.  Next you choose what metadata set the new element should map to, and then the appropriate metadata element in that set.  The system automatically selects the closest match, in terms of set and element, for the new metadata.</p>
+
+<p>Having checked the mapping, you can choose "Add" to add the new metadata element to the chosen metadata set.  (This is only enabled if there is no element of the same name within the chosen set.) "Merge" maps the new element to the one chosen by the user.  Finally, "Ignore" does not import any metadata with this element name.  Once you have specified how to import a certain piece of metadata, the mapping information is retained for the collection's lifetime.</p>
+
+<p>For details on the metadata.xml files which Greenstone uses to store the metadata, see Chapter 2 of the Greenstone Developer's Guide -- Getting the most out of your documents.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/introduction.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/introduction.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/introduction.htm	(revision 13928)
@@ -0,0 +1,19 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="introduction"><font size="5" face="Verdana"><strong>1: Introduction</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>The Greenstone Librarian Interface is a tool for collecting documents, adding metadata, then building digital library collections. It provides access to the Greenstone Digital Library Software's functionality from a graphical point and click interface.</p>
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/miscellaneous.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/miscellaneous.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/miscellaneous.htm	(revision 13928)
@@ -0,0 +1,21 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="miscellaneous"><font size="5" face="Verdana"><strong>9: Miscellaneous</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>This section describes features of the Librarian Interface that are not associated with any particular view.</p>
+
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/ofmiceandmenus.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/ofmiceandmenus.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/ofmiceandmenus.htm	(revision 13928)
@@ -0,0 +1,27 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="ofmiceandmenus"><font size="5" face="Verdana"><strong>1.1: Of Mice and Menus</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>This section provides basic information about interacting with the Librarian Interface. If you are familiar with programs such as Internet Explorer or Microsoft Office and are comfortable with mouse clicks and menus, skip to <a href="howtoavoidthisdocument.htm">How to Avoid Reading This Document</a>.</p>
+
+<p>The Librarian Interface follows Microsoft Windows conventions and draws upon ordinary knowledge of Windows.</p>
+
+<p>Any part of the screen that you interact with, such as a button or text field, is called a "control".  At any given time one control, called the "focus", is highlighted and responds to the keyboard.  Several controls allow you to select parts that are highlighted in dark blue.  Some controls are greyed out to indicate that they are disabled.</p>
+
+<p>You can move and left- or right-click the mouse in the usual way.  Many components also allow you to "drag" them, by clicking and holding the left mouse button, move them with the mouse, and "drop" them elsewhere by releasing the button.  Potential drop targets alter their appearance when a component hovers over them.</p>
+
+<p>You can use the keyboard to type into text fields. [Tab] alters the focus between multiple text fields.</p>
+
+<p>Exit the Librarian Interface program by choosing "Exit" from the "File" menu.  Your collection will be saved first.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/openingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/openingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/openingacollection.htm	(revision 13928)
@@ -0,0 +1,21 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="openingacollection"><font size="5" face="Verdana"><strong>2.3: Opening an Existing Collection</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>To open an existing collection, choose "Open" from the "File" menu to get the Open Collection prompt.  A list of your Greenstone collections appears. Select one to see its description, and click "Open" to load it.  If you seek a collection that resides outside Greenstone's "collect" folder, click "Browse" for a file system browsing dialog.</p>
+
+<p>In case more than one Greenstone Librarian Interface program is running concurrently, the relevant directories are "locked" to prevent interference. On opening a collection, a small temporary lock file is created in its folder.  Before opening a collection, the Librarian Interface checks to ensure that no lock file already exists.  However, when the Librarian Interface is exited prematurely the lock file is sometimes left in place.  When you open such a collection, the Librarian asks if you want to "steal" control of it. Feel free to do so unless you think that someone else is currently working on the same collection.</p>
+
+<p>When you open a collection that the Greenstone Librarian Interface did not create, the Dublin Core metadata set will be assigned to it, and any existing metadata will be imported just as it is when you drag in files with existing metadata. The process is described in the <a href="importingpreviouslyassignedmetadata.htm">Importing Previously Assigned Metadata</a> section. </p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/partitionindexes.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/partitionindexes.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/partitionindexes.htm	(revision 13928)
@@ -0,0 +1,24 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="partitionindexes"><font size="5" face="Verdana"><strong>6.4: Partition Indexes</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Indexes are built on particular text or metadata sources.  The search space can be further controlled by partitioning the indexes, either by language or by a predetermined filter.  This section describes how to do this.  Under the "Design" tab, click "Partition Indexes".</p>
+
+<p>The "Partition Indexes" view has three tabs; "Define Filters", "Assign Partitions" and "Assign Languages".  To learn more about partitions read about sub-collections and sub-indexes in Chapter 2 of the Greenstone Developer's Guide.</p>
+
+<p>The Partition Indexes screen is only enabled in Library Systems Specialist and Expert modes (see <a href="preferences.htm">Preferences</a>). Note that for MG collections, the total number of partitions generated is a combination of all indexes, sub-collection filters and languages chosen. Two indexes with two sub-collection filters in two languages would yield eight index partitions. For MGPP, all indexes are created in one physical index, so there would only be four index partitions. For Lucene, the number of physical indexes is determined by the number of levels assigned to the collection, one index per level. So for the above situation, one level would result in four physical indexes, while two levels would result in eight.</p>
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/plugins.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/plugins.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/plugins.htm	(revision 13928)
@@ -0,0 +1,31 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="plugins"><font size="5" face="Verdana"><strong>6.2: Document Plugins</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>This section describes how to configure the document plugins the collection uses.  It explains how you specify what plugins to use, what parameters to pass to them, and in what order they occur.  Under the "Design" tab, click "Document Plugins".</p>
+
+<p>To add a plugin, select it using the "Select plugin to add" pull-down list near the bottom and then click "Add Plugin".  A window appears entitled "Configuring Arguments"; it is described later.  Once you have configured the new plugin, it is added to the end of the "Assigned Plugins" list. In Librarian mode, each plugin, except for UnknownPlug, may only occur once in the collection. In higher modes, plugins can appear multiple times. The process_exp argument will need to be set in order to make this useful.</p>
+
+<p>To see a short description of a plugin, select it in the "Select plugin to add" pull-down list, then hover the mouse over it. A tool-tip displaying the description will appear.</p>
+
+<p>To remove a plugin, select it in the list and click "Remove Plugin".</p>
+
+<p>Plugins are configured by providing arguments.  To alter them, select the plugin from the list and click "Configure Plugin" (or double-click the plugin). A "Configuring Arguments" dialog appears with various controls for specifying arguments.</p>
+
+<p>There are different kinds of controls.  Some are checkboxes, and clicking one adds the appropriate option to the plugin.  Others are text strings, with a checkbox and a text field.  Click the box to enable the argument, then type appropriate text (regular expression, file path etc) in the box.  Others are pull-down menus from which you can select from a given set of values.  To learn what an argument does, let the mouse hover over its name for a moment and a description will appear.</p>
+
+<p>When you have changed the configuration, click "OK" to commit the changes and close the dialog, or "Cancel" to close the dialog without changing any plugin arguments.</p>
+
+<p>The plugins in the list are executed in order, and the ordering is sometimes important. The order of the plugins can be changed in Library Systems Specialist and Expert modes only (see <a href="preferences.htm">Preferences</a>).    </p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/preferences.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/preferences.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/preferences.htm	(revision 13928)
@@ -0,0 +1,27 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="preferences"><font size="5" face="Verdana"><strong>9.1: Preferences</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>This section explains the preferences dialog, accessed by opening "File" -&gt; "Preferences".</p>
+
+<p>The preferences window opens at the "General" tab. The first option is a text field for entering your e-mail address. This will be used for the "creator" and "maintainer" collection metadata items for new collections. The next option is a pull-down list of the languages in which the Librarian Interface can be presented. If you change the dictionary by choosing one from the list, the Librarian Interface must be restarted in order to load the new language strings from the dictionary.</p>
+
+<p>If "View Extracted Metadata" is checked, the various controls dealing with metadata always show all metadata that has been extracted automatically from documents.  De-selecting it hides this metadata (although it is still available during collection design, and within the final Greenstone collection). If "Show file sizes" is checked, the file size is shown next to each file in the Workspace and Collection file trees in the Gather and Enrich views.</p>
+
+<p>The "Mode" tab is used to control the level of detail within the interface. At its lowest setting, "Library Assistant", the design view is disabled, arguments requiring regular expressions are hidden and the collection building process produces a minimal log of events. In contrast the highest setting, "Expert", provides access to all of the features of design, including plugin positioning and regular expression arguments, and also allows the full output from the collection building to be recorded in the logs. To change or review modes, click the radio button next to the mode you are interested in. You can quickly review what mode you are in by looking at the Librarian Interface's title bar.</p>
+
+<p>The "Connection" tab lets you alter the path to the locally-running Greenstone library server, which is used when Previewing collections. It also lets you set proxy information for connecting to the Internet (e.g. when downloading files; see the <a href="downloadingfiles.htm">Downloading Files From the Internet</a> section for details). Check the box to enable proxy connection and supply details of the proxy host address and port number. The proxy connection is established when you close the Preferences dialog.</p>
+
+<p>During the course of a session the Librarian Interface may give warning messages which inform you of possibly unforeseen consequences of an action.  You can disable the messages by checking the "Do not show this warning again" box. You can re-enable warning messages using the "Warnings" tab.  Check the boxes next to warning messages you want to see again.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/producingthecollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/producingthecollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/producingthecollection.htm	(revision 13928)
@@ -0,0 +1,20 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="producingthecollection"><font size="5" face="Verdana"><strong>7: Producing Your Collection</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Having collected the documents for the collection, annotated them with metadata, and designed how the collection will appear, you can now produce the collection using Greenstone.  This section explains how.</p>
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/removingfiles.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/removingfiles.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/removingfiles.htm	(revision 13928)
@@ -0,0 +1,19 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="removingfiles"><font size="5" face="Verdana"><strong>4.6: Removing Files</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>There are several methods for removing files and folders.  You must first indicate what items to remove by selecting one or more files and folders as described in <a href="thegatherview.htm">The Gather View</a>.</p>
+
+<p>Once files have been selected, click the "delete" button to remove them, or press the [Delete] key on your keyboard, or drag them from the collection to the delete button and drop them there.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/replacingfiles.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/replacingfiles.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/replacingfiles.htm	(revision 13928)
@@ -0,0 +1,19 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="replacingfiles"><font size="5" face="Verdana"><strong>4.5: Renaming and Replacing Files</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Files can be renamed by right-clicking them and selecting "Rename" from the list. Enter the new name at the prompt and click "OK".</p>
+
+<p>Files can be replaced in the collection by right-clicking the file to replace and choosing "Replace". A file browser will open up: navigate to the new document and click "Open". The new document will replace the old one in the collection, and any metadata will be transferred to it. This is particularly useful for replacing dummy documents by their real ones.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/reviewingmetadata.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/reviewingmetadata.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/reviewingmetadata.htm	(revision 13928)
@@ -0,0 +1,27 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="reviewingmetadata"><font size="5" face="Verdana"><strong>5.6: Reviewing Assigned Metadata</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Sometimes you need to see the metadata assigned to many files at once -- for instance, to determine how many files are left to work on, or to get some idea of the spread of dates.</p>
+
+<p>Select the files in the Collection Tree you wish to examine, then right-click and choose "Assigned Metadata...". A window called "All Metadata", dominated by a large table with many columns, appears.  The first column shows file names; the rows show all metadata values assigned to those files.</p>
+
+<p>Drawing the table can take some time if many files are selected.  You can continue to use the Librarian Interface while the "All Metadata" window is open.</p>
+
+<p>When it gets too large, you can filter the "All Metadata" table by applying filters to the columns.  As new filters are added, only those rows that match them remain visible.  To set, modify or clear a filter, click on the "funnel" icon at the top of a column.  You are prompted for information about the filter. Once a filter is set, the column header changes colour.</p>
+
+<p>The filter prompt has a "Simple" and an "Advanced" tab.  The Simple version filters columns so that they only show rows that contain a certain metadata value ("*" matches all values).  You can select metadata values from the pull-down list. The Advanced version allows different matching operations: must start with, does not contain, alphabetically less than and is equal to.  The value to be matched can be edited to be any string (including "*"), and you can choose whether the matching should be case insensitive.  Finally, you can specify a second matching condition that you can use to specify a range of values (by selecting AND) or alternative values (by selecting OR).  Below this area is a box that allows you to change the sort order (ascending or descending).  Once you have finished, click "Set Filter" to apply the new filter to the column. Click "Clear Filter" to remove a current filter.  Note that the filter details are retained even when the filter is cleared.</p>
+
+<p>For example, to sort the "All Metadata" table, choose a column, select the default filter setting (a Simple filter on "*"), and choose ascending or descending ordering.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/savingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/savingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/savingacollection.htm	(revision 13928)
@@ -0,0 +1,21 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="savingacollection"><font size="5" face="Verdana"><strong>2.2: Saving the Collection</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Save your work regularly by opening the "File" menu and choosing "Save". Saving a collection is not the same as making it ready for use in Greenstone (see <a href="producingthecollection.htm">Producing Your Collection</a>).</p>
+
+<p>The Librarian Interface protects your work by saving it whenever you exit the program or load another collection.</p>
+
+<p>Collections are saved to a folder within your Greenstone installation's "collect" folder, named with a short version of the collection name. Documents are saved to the "import" sub-folder, and metadata is saved to "metadata.xml" files within this folder. Configuration information is saved to the "collect.cfg" file within the "etc" sub-folder. Some information is also saved in a file named for the collection and with file extension ".col".</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/searchindexes.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/searchindexes.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/searchindexes.htm	(revision 13928)
@@ -0,0 +1,43 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="searchindexes"><font size="5" face="Verdana"><strong>6.3: Search Indexes</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Indexes specify what parts of the collection are searchable.  This section explains how to add and remove indexes, and set a default index.  Under the "Design" tab, click "Search Indexes".</p>
+
+<p>The top right of the "Search Indexes" panel displays information about which indexer is currently being used by the collection. This can be changed by clicking "Change...". A popup window appears with the list of options: MG, MGPP, and Lucene. Changing this affects how the indexes are built, and may affect search functionality.</p>
+
+<p>The "Assigned Indexes" list shows what indexes are currently assigned to the collection. </p>
+
+<p>To add an index, click "New Index"... A popup window appears with a list of sources, which includes text and metadata. Select which sources you want to index. The "Select All" and "Select None" buttons will check or uncheck all of the items in the list, respectively. Once a new index has been defined, click "Add Index" to add it to the collection. "Add Index" will only become active once the settings describe a new index that is not already assigned to the collection. </p>
+
+<p>For MG indexes, you also need to choose the granularity of the index, using the "Indexing level:" menu. </p>
+
+<p>For MGPP and Lucene indexes, index granularity is determined globally, not per index. The possible levels are displayed on the main "Search Indexes" pane, and can be added to the collection by ticking the checkboxes.</p>
+
+<p>A special index is available for MGPP and Lucene: an "allfields" index which merely provides combined searching over all specified indexes, without having to specify a separate index that contains all sources. To add this index, check the "Add combined searching over all assigned indexes (allfields)" check box and click "Add Index".</p>
+
+<p>For MGPP and Lucene, an "Add All" button is also provided, as a shortcut to adding all metadata and text sources as individual indexes.</p>
+
+<p>To edit an index, select it and click "Edit Index". A similar dialog to the "New Index" one is shown. </p>
+
+<p>To remove an index, select it from the list of assigned indexes and click "Remove Index".</p>
+
+<p>The order that the indexes are specified in the Assigned Indexes list is the order they appear in the drop down menu on the search page. Use the "Move Up" and "Move Up" buttons to change this ordering. </p>
+
+<p>The one that is selected by default on the search page is called the "default index". This can be set by selecting an index from the list and clicking "Set Default". The default index is tagged with "[Default Index]" in the "Assigned Indexes" list. If no default index is set, the first one in the list will be used as the default.</p>
+
+<p>The names used for the drop-down list of indexes on the search page can be set in the "Search" part of the "Format" panel (see <a href="searchmetadatasettings.htm">Search</a>).</p>
+
+<p>For MG and MGPP indexes, there are further options controlling how the indexes are built. Stemming and case-folding may be enabled or disabled in the indexes&mdash;if disabled, the options will not be displayed on the preferences page of the collection. Accent-folding is also available for MGPP indexes. This works in a similar way to case-folding, but instead of lower and upper case letters matching, letters with diacritics match those without.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/searchmetadatasettings.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/searchmetadatasettings.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/searchmetadatasettings.htm	(revision 13928)
@@ -0,0 +1,19 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="searchmetadatasettings"><font size="5" face="Verdana"><strong>8.3: Search</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>This section explains how to set the display text for the drop down lists on the search page. Under the "Format" tab, click "Search".</p>
+
+<p>This pane contains a table listing each search index, index level (for MGPP or Lucene collections), and index or language partition. Here you can enter the text to be used for each item in the various drop-down lists on the search page. This pane only allows you to set the text for one language, the current language used by GLI. To translate these names for other languages, use the Translate Text part of the Format view (see <a href="translatetext.htm">Translate Text</a>).</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/selectingmetadatasets.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/selectingmetadatasets.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/selectingmetadatasets.htm	(revision 13928)
@@ -0,0 +1,35 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="selectingmetadatasets"><font size="5" face="Verdana"><strong>5.2: Selecting Metadata Sets</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Sets of predefined metadata elements are known as "metadata sets".  An example is the Dublin Core metadata set.  When you add a metadata set to your collection, its elements become available for selection.  You can have more than one set; to prevent name clashes a short identifier that identifies the metadata set is pre-pended to the element name.  For instance the Dublin Core element Creator becomes "dc.Creator".  Metadata sets are stored in the Librarian Interface's metadata folder and have the suffix ".mds".</p> 
+
+<p>When you create a new collection, the Dublin Core metadata set is added by default. You can change which metadata sets are used in a collection by clicking the "Manage Metadata Sets..." button underneath the Collection Tree in the Enrich view. This brings up a new window for managing the collection's metadata sets.</p>
+
+<p>The "Assigned Metadata Sets" list shows you what sets are currently used by the collection.</p>
+
+<p>To use another metadata set with the loaded collection, click "Add...". A popup window shows you the default metadata sets that GLI knows about. To add one of these, select it from the list and click "Add". If you have defined your own metadata set, you can use the "Browse" button to locate the file on your file system.</p>
+
+<p>To create a new metadata set, click "New...". This will launch the Greenstone Editor for Metadata Sets, GEMS. An initial popup window prompts you for the set name, namespace and description. You can also choose to base the new set on an existing one, in which case it will inherit all the elements from the specified set. Click OK. The main window shows the metadata set on the left hand side, and some attributes for the set on the right hand side. If you have based the set on an existing one, one or more elements will be displayed. Clicking one displays attributes of the element in the right hand side.</p>
+
+<p>To add a new element, right click on the set and choose "Add Element". To add a new subelement, right click on the element and choose "Add Subelement". Elements and subelements can be deleted by choosing "Delete (Sub)element" from the right click menu. </p>
+
+<p>Note: the Greenstone Editor for Metadata Sets can be run independently of GLI by selecting it from the Greenstone Start menu, or by running gens.sh or gems.bat in the gli folder of your Greenstone installation.</p>
+
+<p>Sometimes two metadata sets may have the same namespace, for example, Dublin Core and Qualified Dublin Core both use the namespace "dc". Such sets cannot be used in the collection at the same time. If you try to add a set with a namespace already used by the collection, a warning will be shown. If you go ahead, the existing set will be removed and the new one added. Any assigned metadata values will be transferred to the new set providing those elements still exist.</p>
+
+<p>With GEMS upi can edit existing metadata sets as well as create new ones. Clicking the "Edit" button launches GEMS with the specified metadata set open. Once you have finished editing the set (as described above), save it (File-&gt;Save) and close GEMS.</p>
+
+<p>If a collection no longer needs a metadata set, select it and press "Remove". If you have assigned any metadata to its elements you will be asked how to deal with this metadata when you next open the collection.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/startingoff.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/startingoff.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/startingoff.htm	(revision 13928)
@@ -0,0 +1,21 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="startingoff"><font size="5" face="Verdana"><strong>2: Starting Off</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>This section covers how to create, load, save and delete collections.</p>
+
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/thecreateview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/thecreateview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/thecreateview.htm	(revision 13928)
@@ -0,0 +1,21 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="thecreateview"><font size="5" face="Verdana"><strong>7.1: The Create View</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>The Create view is used to create the collection by running Greenstone collection-building scripts on the information you have provided. Access the Create view by clicking the Create tab.</p>
+
+<p>Clicking "Build Collection" initiates the collection building process.  The time this takes depends on the size of the collection and the number of indexes being created (for huge collections it can be hours). A progress bar indicates how much of the process has been completed. To cancel the process at any time, click "Cancel Build". The lower part of the panel shows some output from the build process. The upper part shows some options for controlling the build process.</p>
+
+<p>Once the collection has successfully built, clicking "Preview Collection" will launch a web browser showing the home page of the collection.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/thedesignview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/thedesignview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/thedesignview.htm	(revision 13928)
@@ -0,0 +1,23 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="thedesignview"><font size="5" face="Verdana"><strong>6.1: The Design View</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>This section introduces you to the design view and explains how to navigate between the various views within this pane.</p>
+
+<p>With the Librarian Interface, you can configure how the documents are processed, and how the collection is accessed by the user.  The configuration options are divided into different sections, each associated with a particular stage of collection customization.</p>
+
+<p>On the left is a list of different views, and on the right are the controls associated with the current one.  To change to a different view, click its name in the list.</p>
+
+<p>To understand the stages and terms involved in designing a collection, first read Chapters 1 and 2 of the Greenstone Developer's Guide.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/theenrichview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/theenrichview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/theenrichview.htm	(revision 13928)
@@ -0,0 +1,27 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="theenrichview"><font size="5" face="Verdana"><strong>5.1: The Enrich View</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Use the "Enrich" view to assign metadata to the documents in the collection. Metadata is data about data -- typically title, author, creation date, and so on.  Each metadata item has two parts: "Element" tells what kind of item it is (such as author), and "Value" gives the value of that metadata element (such as the author's name).</p>
+
+<p>On the left of the "Enrich" view is the Collection Tree. All the right-click functionality that was available for the Collection Tree in the "Gather" view is available here too. To the right is the Metadata Table, which shows metadata for any selected files or folders in the Collection Tree.  Columns are named in grey at the top, and can be resized by dragging the separating line. If several files or folders are selected, black text indicates that the value is common to all of the selected items, while grey text indicates that it is not. Editing grey values will only affect those documents with that metadata. Any new metadata values entered will be added to all selected values.</p>
+
+<p>A folder icon may appear beside some metadata entries.  This indicates that the values are inherited from a parent (or ancestor) folder.  Inherited metadata cannot be edited or removed, only appended to or overwritten.  Click on the folder icon to go immediately to the folder where the metadata is assigned.</p>
+
+<p>Clicking on a metadata element in the table will display the existing values for that element in the "Existing values for ..." area below the table. This "Value Tree" expands and collapses.  Usually it is a list that shows all values entered previously for the selected element.  Clicking an entry automatically places it into the value field.  Conversely, typing in the text field selects the Value Tree entry that starts with the characters you have typed.  Pressing [Tab] auto-completes the typing with the selected value.</p>
+
+<p>Metadata values can be organized into a hierarchy. This is shown in the Value Tree using folders for internal levels. Hierarchical values can be entered using the character "|" to separate the levels.  For example, "Cards|Red|Diamonds|Seven" might be used in a hierarchy that represents a pack of playing cards. This enables values to be grouped together. Groups can also be assigned as metadata to files.</p>
+
+<p>Greenstone extracts metadata automatically from documents into a metadata set whose elements are prefixed by "ex.".  This has no value tree and cannot be edited. </p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/theformatview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/theformatview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/theformatview.htm	(revision 13928)
@@ -0,0 +1,23 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="theformatview"><font size="5" face="Verdana"><strong>8.1: The Format View</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>This section introduces you to the Format view and explains how to navigate between the various views within this pane.</p>
+
+<p>With the Librarian Interface you can configure how the collection appears to the user. The configuration options are divided into sections, each associated with a different type of customization.</p>
+
+<p>On the left is a list of views and on the right are the controls associated with the current one. To change to a different view, click its name in the list.</p>
+
+<p>Under the list of views is a "Preview Collection" button. Changes made in the Format view don't require a collection rebuild, so can be previewed straight away. However, the collection must have been built at least once to allow previewing.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/thegatherview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/thegatherview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/thegatherview.htm	(revision 13928)
@@ -0,0 +1,33 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="thegatherview"><font size="5" face="Verdana"><strong>4.1: The Gather View</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>This section introduces the Gather area that you use to select what files to include in the collection you are building. The Librarian Interface starts with the Gather view.  To return to this view later, click the "Gather" tab directly below the menu bar.</p>
+
+<p>The two large areas titled "Workspace" and "Collection" are used to move files into your collection.  They contain "file trees" that represent files and folders.</p>
+
+<p>Select an item in the tree by clicking it.  (There are other ways; see below.) Double-click a folder, or single-click the switch symbol beside it, to expand (or collapse) its contents.  Double-click a file (or right-click and select "Open in external program") to open it using its associated application program (see <a href="fileassociations.htm">File Associations</a>).</p>
+
+<p>The Workspace file tree shows the sources of data available to the Librarian Interface -- the local file system (including disk and CD-ROM drives), the contents of existing Greenstone collections, and the cache of downloaded files. You can copy and view these files but you cannot move, delete, or edit them, with the exception of the downloaded files, which can be deleted.  Navigate this space to find the files you want to include in the collection.</p>
+
+<p>The Collection file tree represents the contents of the collection so far.  Initially, it is empty.</p>
+
+<p>You can resize the spaces by mousing over the grey bar that separates the trees (the shape of the pointer changes) and dragging.</p>
+
+<p>At the bottom of the window is a status area that shows the progress of actions involving files (copying, moving and deleting). These can take some time to complete. The "Stop" button stops any action that is currently in progress. </p>
+
+<p>Two large buttons occupy the lower right corner of the screen. "New Folder", with a picture of a folder, creates new folders (see <a href="creatingfolders.htm">Creating Folders</a>). "Delete", with a garbage can, removes files. Clicking the Delete button will remove any selected files from the Collection file tree. Alternatively, files can be deleted by dragging them onto the Delete button. </p>
+
+<p>To select several sequential items, select the first and then hold down [Shift] and click on the last -- the selection will encompass all intervening items.  Select non-sequential files by holding down [Ctrl] while clicking.  Use these two methods together to select groups of non-adjacent items.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/themirrorview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/themirrorview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/themirrorview.htm	(revision 13928)
@@ -0,0 +1,41 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="themirrorview"><font size="5" face="Verdana"><strong>3.1: The Download view</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>This section describes how to configure a download task and control the downloading process. Access the "Download" view by clicking its tab. The top half of the screen shows the downloading controls. The bottom half is initially empty, but will show a list of pending and completed download jobs. </p>
+
+<p>There are several protocols that can be used for downloading records, and these are listed on the left hand side at the top.</p>
+
+<p>
+<b>Web:</b> downloads web pages and files via HTTP and FTP.</p>
+
+<p>
+<b>OAI:</b> downloads metadata records from an OAI (Open Archives Initiative) server.</p>
+
+<p>
+<b>Z3950:</b> downloads MARC records that match a particular search criterion from a Z3950 server.</p>
+
+<p>
+<b>SRW:</b> downloads MARCXML records that match a particular search criterion from an SRW server.</p>
+
+<p>Select the appropriate type by clicking it in the left hand list. The right-hand side displays the options available for the selected download type. To find out what an option does, hover the mouse over it: a tool-tip explaining the option will appear. Some options are 'optional': these are presented with a check box which must be ticked on for the option to be used. Others are 'required': these have no check box, and a value must be given before the download is carried out. </p>
+
+<p>Once the configuration is set up, click "Server Information" to check the connection to the server and view some basic information about the web page or server, or click "Download" to start the download. </p>
+
+<p>There are two other buttons: "Preferences", which links to the connection section of the Preferences where proxy settings can be edited; and "Clear Cache", which deletes all previously downloaded files. You will need to set up proxy information if you use a proxy server to connect to the Internet. If authentication is needed when a download is being processed, the proxy server will prompt for username and password.  The Librarian Interface does not store passwords between sessions.</p>
+
+<p>Files are downloaded into a folder called "Downloaded Files" (only present when downloading is enabled), and can be used in any collections.  Files are named by their full web URL (for Web downloads) or a combination of URL and option values (for other download types). A new folder is created for each host, followed by others for each part of the path. This ensures that each file is distinct.</p>
+
+<p>The download list has an entry for each download processed. Each entry has a text region that gives details of the task along with a progress bar showing current activity. Three buttons appear to the left of each entry. "Pause" is used to pause a task. "View Log" opens a window showing the download log file. "Close" terminates the download and removes the task from the list.  </p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/translatetext.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/translatetext.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/translatetext.htm	(revision 13928)
@@ -0,0 +1,23 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="translatetext"><font size="5" face="Verdana"><strong>8.5: Translate Text</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>This section describes the translation view, where you can translate text fragments for parts of the collection's interface into other languages. Under the "Format" tab, click "Translate Text".</p>
+
+<p>First choose an entry from the "Features" list.  The language-specific strings associated with this feature appear below.  Use the "Language of translation" pull-down list to select the target language, and type the translated text into the text area, referring to the "Initial Text Fragment" if necessary.  Click "Add Translation" when finished.</p>
+
+<p>To remove an existing translation, select it in the "Assigned Translations" table and click "Remove Translation".</p>
+
+<p>To edit a translation, select it, edit the "Translated Text" area and click "Replace Translation".</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/updatingmetadata.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/updatingmetadata.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/updatingmetadata.htm	(revision 13928)
@@ -0,0 +1,21 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="updatingmetadata"><font size="5" face="Verdana"><strong>5.5: Editing or Removing Metadata</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>To edit or remove a piece of metadata, first select the appropriate file, and then the metadata value from the table. Edit the value field, deleting all text if you wish to remove the metadata.</p>
+
+<p>The process is the same when updating a folder with child folders or multiple files, but you can only update metadata that is common to all files/folders selected.</p>
+
+<p>The value tree shows all currently assigned values as well as previous values for the current session, so changed or deleted values will remain in the tree. Closing the collection and then re-opening it will remove all values that are no longer assigned.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/en/xcollectionsearching.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/en/xcollectionsearching.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/en/xcollectionsearching.htm	(revision 13928)
@@ -0,0 +1,23 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table width="100%" cellspacing="0" cellpadding="5" bgcolor="#B0D0B0" border="2">
+<tr>
+<td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td><td width="*" align="center"><a name="xcollectionsearching"><font size="5" face="Verdana"><strong>8.6: Cross-Collection Search</strong></font></a></td><td width="15%" align="center"><img width="45" src="../gatherer_medium.gif" height="45"></td>
+</tr>
+</table>
+
+
+<p>Greenstone can search across several different collections as though they were one. This is done by specifying a list of other collections to be searched along with the current one.  Under the "Format" tab, click "Cross-Collection Search".</p>
+
+<p>The Cross-Collection Search view shows a checklist of available collections.  The current collection is ticked and cannot be de-selected.  To add another collection to be searched in parallel, click it in the list (click again to remove it).  If only one collection is selected, there is no cross-collection searching.</p>
+
+<p>If the individual collections do not have the same indexes (including sub-collection partitions and language partitions) as each other, cross-collection searching will not work properly. The user will only be able to search using indexes common to all collections.</p>
+
+<p>For further details, see Chapter 1 of the Greenstone Developer's Guide.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/addingfiles.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/addingfiles.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/addingfiles.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="addingfiles"><font face="Verdana" size="5"><strong>4.3: A&ntilde;adiendo archivos</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Los archivos se pueden copiar arrastr&aacute;ndolos y coloc&aacute;ndolos en una colecci&oacute;n. El cursor se convierte en un fantasma del elemento seleccionado (o, si se ha seleccionado m&aacute;s de uno, del n&uacute;mero de ellos). Coloque la selecci&oacute;n en la estructura de directorios y subdirectorios de la colecci&oacute;n para copiar ah&iacute; los archivos (si la fuente son los archivos del &aacute;rea de trabajo) o mu&eacute;valos de lugar dentro de la misma colecci&oacute;n (si la fuente son los archivos de la colecci&oacute;n).</p>
+<p>Cuando se copien varios archivos en una carpeta todos estar&aacute;n al mismo nivel, sin importar la estructura de las carpetas en las que se encontraban originalmente. Cuando se copie un segundo archivo con el mismo nombre en la misma carpeta se le preguntar&aacute; si desea reemplazar el archivo existente. Si la respuesta es "No" entonces el archivo no se copiar&aacute;, pero los dem&aacute;s s&iacute;. Para cancelar las acciones restantes de copiado haga click en el bot&oacute;n "Detener".</p>
+<p>&Uacute;nicamente se mover&aacute;n los elementos "de m&aacute;s alto nivel" en una selecci&oacute;n. Una carpeta est&aacute; a un nivel m&aacute;s alto que los elementos que se encuentran en su interior, por lo que no se podr&aacute;n seleccionar los archivos de una carpeta y la carpeta al mismo tiempo.</p>
+<p>Cuando se a&ntilde;ada un archivo, la Interfaz de Bibliotecario buscar&aacute; a trav&eacute;s de las carpetas fuente los archivos auxiliares que contienen los metadatos asignados previamente a dicho archivo y, si encuentra alguno, empezar&aacute; a importar estos metadatos. Conforme la operaci&oacute;n siga adelante se le pedir&aacute; (quiz&aacute; varias veces) que proporcione informaci&oacute;n adicional para conciliar los metadatos importados con los conjuntos de metadatos de su colecci&oacute;n. Este proceso incluye muchos avisos diferentes, los cuales se describen en la secci&oacute;n <a href="importingpreviouslyassignedmetadata.htm">Importando metadatos previamente asignados</a>. Para obtener una explicaci&oacute;n m&aacute;s detallada sobre la forma de asociar metadatos a los archivos lea el Cap&iacute;tulo 2 de la Gu&iacute;a del Programador de Greenstone: Obteniendo el m&aacute;ximo beneficio de sus documentos.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/addingpreviouslydefinedmetadata.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/addingpreviouslydefinedmetadata.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/addingpreviouslydefinedmetadata.htm	(revision 13928)
@@ -0,0 +1,16 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="addingpreviouslydefinedmetadata"><font face="Verdana" size="5"><strong>5.4: A&ntilde;adiendo Metadatos Previamente Definidos</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Para a&ntilde;adir metadatos con un valor existente, seleccione primero el archivo y a continuaci&oacute;n el valor requerido de la estructura de valores, expandiendo las carpetas tanto como sea necesario. El valor de la entrada seleccionada aparecer&aacute; autom&aacute;ticamente en el campo de texto (otra alternativa es utilizar las funciones de selecci&oacute;n autom&aacute;tica y completamiento autom&aacute;tico de la estructura de valores). </p>
+<p>El proceso de a&ntilde;adir metadatos con valores existentes a carpetas o a varios archivos juntos es exactamente igual.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/appendingmetadata.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/appendingmetadata.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/appendingmetadata.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="appendingmetadata"><font face="Verdana" size="5"><strong>5.3: Agregando nuevos metadatos</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ahora a&ntilde;adiremos un &iacute;tem de metadato -- tanto un elemento como un valor -- a un archivo. Primero, seleccione el archivo en la estructura de directorios y subdirectorios de la colecci&oacute;n que se encuentra a la izquierda. Esto hace que cualquier metadato asignado previamente a este archivo aparezca en la tabla de la derecha.</p>
+<p>A continuaci&oacute;n, seleccione el elemento de metadato que desea a&ntilde;adir haciendo click en la fila correspondiente de la tabla.</p>
+<p>Escriba el valor en el campo de valores. Use el car&aacute;cter "|" para a&ntilde;adir estructura, tal y como se explica en <a href="theenrichview.htm">La pantalla de asignaci&oacute;n de metadatos</a>. Pulsando las teclas de flecha [Arriba] o [Abajo] se guardar&aacute;n los metadatos y se mover&aacute; la selecci&oacute;n adecuadamente. Pulsando [Retorno] se guardar&aacute;n los metadatos y se crear&aacute; una nueva entrada vac&iacute;a para un elemento de metadato, permitiendo asignar varios valores al mismo.</p>
+<p>Tambi&eacute;n se pueden a&ntilde;adir metadatos a una carpeta o a varios archivos seleccionados al mismo tiempo. Estos metadatos se a&ntilde;adir&aacute; a todos los archivos que forman parte de la carpeta o de la selecci&oacute;n, as&iacute; como a las subcarpetas. Recuerde que si usted asigna metadatos a una carpeta, todos los archivos nuevos que se encuentren en ella heredar&aacute;n autom&aacute;ticamente los valores de la carpeta.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/assignlanguages.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/assignlanguages.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/assignlanguages.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="assignlanguages"><font face="Verdana" size="5"><strong>6.6.3: Asignar idiomas</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Esta secci&oacute;n describe la forma de limitar los &iacute;ndices de b&uacute;squeda a ciertos idiomas. Esto se hace generando una partici&oacute;n por medio de la pesta&ntilde;a "Asignar idiomas" que se encuentra en la pantalla "Particionar &iacute;ndices".</p>
+<p>Para a&ntilde;adir un nuevo idioma use la pesta&ntilde;a "Asignar idiomas" a fin de construirle un &iacute;ndice. Seleccione el idioma en la lista descendente "Idioma que se va a a&ntilde;adir" y haga click en "A&ntilde;adir idioma".</p>
+<p>Para quitar un idioma, esc&oacute;jalo de la lista "Selecci&oacute;n de idiomas" y haga click en "Eliminar idioma".</p>
+<p>Para establecer un idioma por omisi&oacute;n, selecci&oacute;nelo de la lista y haga click en "Predeterminar".</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/assignpartitions.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/assignpartitions.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/assignpartitions.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="assignpartitions"><font face="Verdana" size="5"><strong>6.6.2: Asignar particiones</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Una vez que haya definido el filtro de una subcolecci&oacute;n, utilice la pesta&ntilde;a "Asignar particiones" para construir los &iacute;ndices del filtro (o de un grupo de filtros). Seleccione el filtro o los filtros que desee de la lista "Filtros definidos para la subcolecci&oacute;n", ingrese un nombre para la partici&oacute;n en el campo "Nombre de la partici&oacute;n" y haga click en "A&ntilde;adir partici&oacute;n".</p>
+<p>Para quitar una partici&oacute;n de la lista, selecci&oacute;nela y haga click en "Eliminar partici&oacute;n".</p>
+<p>Para hacer que una partici&oacute;n determinada sea el valor por omisi&oacute;n, selecci&oacute;nela de la lista y haga click en "Predeterminar".</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/buildsettings.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/buildsettings.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/buildsettings.htm	(revision 13928)
@@ -0,0 +1,16 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="buildsettings"><font face="Verdana" size="5"><strong>7.2: Controles de importaci&oacute;n y construcci&oacute;n</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Esta secci&oacute;n explica la forma de tener acceso a los diferentes controles de importaci&oacute;n y construcci&oacute;n. Para mayor informaci&oacute;n lea el Cap&iacute;tulo 1 de la Gu&iacute;a del Programador de Greenstone: Comprendiendo el proceso de creaci&oacute;n de una colecci&oacute;n.</p>
+<p>La forma de controlar los diferentes ajustes es similar a la de la ventana "Argumentos de configuraci&oacute;n" que se describe en la secci&oacute;n de <a href="plugins.htm">Plugins</a>. Algunos campos requerir&aacute;n argumentos num&eacute;ricos y usted puede escribirlos directamente en el campo o usar las flechas que se encuentran a un lado para aumentar o disminuir el n&uacute;mero (en algunos casos la interfaz limita el rango). Otros se activan (y desactivan) haciendo click en los recuadros correspondientes.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/classifiers.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/classifiers.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/classifiers.htm	(revision 13928)
@@ -0,0 +1,20 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="classifiers"><font face="Verdana" size="5"><strong>6.8: Clasificadores de exploraci&oacute;n</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Esta secci&oacute;n explica la forma de asignar "clasificadores" a una colecci&oacute;n, los cuales se usan para navegar y buscar en ella. En la parte de "Secciones de dise&ntilde;o" haga click en "Clasificadores de exploraci&oacute;n".</p>
+<p>Para a&ntilde;adir un clasificador, esc&oacute;jalo por medio de la lista descendente "Seleccione el clasificador que se va a a&ntilde;adir" en la parte inferior de la pantalla y haga click en "A&ntilde;adir clasificador". Con esto aparecer&aacute; una ventana titulada "Argumentos de configuraci&oacute;n". Las instrucciones para este cuadro de di&aacute;logo son exactamente las mismas que para los plugins (vea la secci&oacute;n <a href="plugins.htm">Plugins</a>). Una vez que haya configurado el nuevo clasificador, &eacute;ste se a&ntilde;adir&aacute; al final de la lista de "Clasificadores asignados actualmente".</p>
+<p>Para quitar un clasificador de la lista, selecci&oacute;nelo y haga click en "Eliminar clasificador".</p>
+<p>Para cambiar los argumentos de un clasificador, selecci&oacute;nelo de la lista y haga click en "Configurar clasificador" o doble click en el nombre del clasificador.</p>
+<p>El orden de los clasificadores en la barra de navegaci&oacute;n de la colecci&oacute;n se refleja aqu&iacute;. Para cambiarlo, seleccione el clasificador que desea mover y haga click en "Mover arriba" o "Mover abajo".</p>
+<p>Para mayor informaci&oacute;n sobre los clasificadores, lea el Cap&iacute;tulo 2 de la Gu&iacute;a del Programador de Greenstone: Obteniendo el m&aacute;ximo beneficio de sus documentos.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/collectingfiles.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/collectingfiles.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/collectingfiles.htm	(revision 13928)
@@ -0,0 +1,20 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="collectingfiles"><font face="Verdana" size="5"><strong>4: Reuniendo archivos para su colecci&oacute;n</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Una vez que usted tiene una nueva colecci&oacute;n necesita meter algunos archivos en ella. Estos pueden venir desde la estructura de archivos de su computadora o de otras colecciones Greenstone. Algunos incluso ya pueden tener metadatos. Esta secci&oacute;n describe la forma de importar archivos.</p>
+
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/creatingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/creatingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/creatingacollection.htm	(revision 13928)
@@ -0,0 +1,20 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="creatingacollection"><font face="Verdana" size="5"><strong>2.1: Creando una nueva colecci&oacute;n</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Para crear una nueva colecci&oacute;n abra el men&uacute; "Archivo" y elija la opci&oacute;n "Nueva". Deber&aacute;n llenarse varios campos, aunque en caso de que lo requiera usted podr&aacute; cambiar despu&eacute;s sus valores en la pantalla de dise&ntilde;o.</p>
+<p>El "T&iacute;tulo de la colecci&oacute;n" es el texto que aparece en la parte superior de la p&aacute;gina principal de su colecci&oacute;n. Puede tener la longitud  que usted quiera.</p>
+<p>La "Descripci&oacute;n del contenido" deber&aacute; describir tan detalladamente como sea posible de lo que se trata la colecci&oacute;n. Utilice la tecla [Enter] o [Intro] para dividirla en p&aacute;rrafos.</p>
+<p>Finalmente deber&aacute; especificar si desea que la nueva colecci&oacute;n tenga la misma apariencia y conjunto de metadatos que una colecci&oacute;n existente o si desea iniciar una "Nueva Colecci&oacute;n" por omisi&oacute;n.</p>
+<p>Haga click en "Aceptar" para crear la colecci&oacute;n. Si usted escogi&oacute; "Nueva Colecci&oacute;n" se le pedir&aacute; que elija el conjunto de metadatos que usar&aacute; en ella.  Puede elegir m&aacute;s de uno y tambi&eacute;n puede a&ntilde;adir otros m&aacute;s adelante.</p>
+<p>Si hace click en "Cancelar" regresar&aacute; inmediatamente a la pantalla principal.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/creatingfolders.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/creatingfolders.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/creatingfolders.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="creatingfolders"><font face="Verdana" size="5"><strong>4.2: Creando carpetas</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Utilice las carpetas que se encuentran en la estructura de directorios y subdirectorios de la colecci&oacute;n para agrupar archivos y hacer que sean m&aacute;s f&aacute;ciles de encontrar. Las carpetas pueden contener a su vez otras subcarpetas. No hay pr&aacute;cticamente ning&uacute;n l&iacute;mite en cuanto al n&uacute;mero de carpetas que se pueden tener o qu&eacute; tan profundamente anidadas puedan estar.</p>
+<p>Para crear una nueva carpeta, una opci&oacute;n es seleccionar una carpeta existente en la estructura de directorios y subdirectorios de la colecci&oacute;n y hacer click en el bot&oacute;n "Nueva carpeta". La nueva carpeta aparecer&aacute; dentro de la que se seleccion&oacute; primero o en el nivel superior si no se seleccion&oacute; ninguna. Se le pedir&aacute; que le d&eacute; un nombre a la carpeta (el valor por omisi&oacute;n es "Nueva carpeta").</p>
+<p>Tambi&eacute;n se pueden crear nuevas carpetas haciendo click sobre una carpeta con el bot&oacute;n derecho del mouse,  eligiendo la opci&oacute;n "Nueva carpeta" y continuando tal como se describe arriba.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/definefilters.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/definefilters.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/definefilters.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="definefilters"><font face="Verdana" size="5"><strong>6.6.1: Definir filtros</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Los filtros le permiten agrupar en una subcolecci&oacute;n todos los documentos de un &iacute;ndice para los cuales un valor de metadato sigue un patr&oacute;n definido.</p>
+<p>Para crear un filtro haga click en la pesta&ntilde;a "Definir filtros" y escriba el nombre del nuevo filtro en el campo titulado "Nombre del filtro de la subcolecci&oacute;n". A continuaci&oacute;n elija un atributo del documento con el cual se va a contrastar, ya sea un elemento de metadato o el nombre del archivo en cuesti&oacute;n. Ingrese una expresi&oacute;n regular que se utilizar&aacute; durante la contrastaci&oacute;n. Usted puede variar libremente entre "Incluir" documentos que concuerden con el filtro o "Excluirlos". Por &uacute;ltimo, usted tambi&eacute;n puede especificar cualquiera de los indicadores est&aacute;ndar de expresiones regulares PERL para usarlos al momento de contrastar (p. ej. "i" para concordancias que no tomen en cuenta el caso). Haga click en "A&ntilde;adir filtro" para a&ntilde;adir el filtro a la lista de "Filtros definidos para la subcolecci&oacute;n".</p>
+<p>Para quitar un filtro de la lista, selecci&oacute;nelo y haga click en "Eliminar filtro".</p>
+<p>Para modificar un filtro, selecci&oacute;nelo de la lista, cambie cualquiera de los valores que aparecen en los controles de edici&oacute;n y haga click en "Reemplazar filtro" para guardar los cambios.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/deletingcollections.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/deletingcollections.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/deletingcollections.htm	(revision 13928)
@@ -0,0 +1,15 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="deletingcollections"><font face="Verdana" size="5"><strong>2.4: Borrando colecciones</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Para borrar definitivamente colecciones de su instalaci&oacute;n de Greenstone, elija "Borrar&hellip;" del men&uacute; "Archivo". Aparece una lista de sus colecciones. Seleccione una para ver su descripci&oacute;n, marque la casilla situada en la parte inferior del di&aacute;logo, y pulse "Borrar" para borrar la colecci&oacute;n. Esta acci&oacute;n es irreversible, por lo que debe comprobar cuidadosamente que no necesita la colecci&oacute;n antes de proceder.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/designingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/designingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/designingacollection.htm	(revision 13928)
@@ -0,0 +1,26 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="designingacollection"><font face="Verdana" size="5"><strong>6: Dise&ntilde;ando la apariencia de su colecci&oacute;n</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Una vez que los archivos est&aacute;n marcados con metadatos, a continuaci&oacute;n se debe decidir la forma en que aparecer&aacute;n ante los usuarios como parte de una colecci&oacute;n Greenstone. &iquest;Qu&eacute; tipo de informaci&oacute;n se podr&aacute; buscar? &iquest;De qu&eacute; medios se dispone para navegar por los documentos? &iquest;En qu&eacute; idiomas? &iquest;D&oacute;nde aparecer&aacute;n los botones en la p&aacute;gina? Todas estas cosas se pueden personalizar. Esta secci&oacute;n describe la forma de hacerlo.</p>
+
+
+
+
+
+
+
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/downloadingfiles.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/downloadingfiles.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/downloadingfiles.htm	(revision 13928)
@@ -0,0 +1,16 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="downloadingfiles"><font face="Verdana" size="5"><strong>3: Descargando archivos de Internet</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>La vista "Bajar" le ayuda a descargar recursos de internet. Esta secci&oacute;n explica el interfaz del mecanismo de puesta en espejo del Bibliotecario.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/enrichingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/enrichingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/enrichingacollection.htm	(revision 13928)
@@ -0,0 +1,22 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="enrichingacollection"><font face="Verdana" size="5"><strong>5: Enriqueciendo la colecci&oacute;n con metadatos</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Despu&eacute;s de haber juntado varios archivos en una colecci&oacute;n, enriqu&eacute;zcalos con informaci&oacute;n adicional. Esta secci&oacute;n explica la forma en que se crean, editan, asignan y recuperan los metadatos, y la forma de usar fuentes externas de metadatos (v&eacute;ase tambi&eacute;n el Cap&iacute;tulo 2 de la Gu&iacute;a del Programador de Greenstone: Obteniendo el m&aacute;ximo beneficio de sus documentos).</p>
+
+
+
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/exportingcollections.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/exportingcollections.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/exportingcollections.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="exportingcollections"><font face="Verdana" size="5"><strong>8.3: Exportando colecciones a un CD/DVD</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Greenstone puede exportar una o m&aacute;s colecciones a un CD/DVD para Windows que se podr&aacute; instalar autom&aacute;ticamente. Para ello es indispensable que el paquete "Exportar a un CD-ROM" est&eacute; instalado. Esto no se incluye por omisi&oacute;n, por lo que ser&aacute; necesario modificar la instalaci&oacute;n para incluirlo.</p>
+<p>Para exportar una colecci&oacute;n abra el men&uacute; "Archivo" y seleccione la opci&oacute;n "Exportar a un CD-ROM/DVD...". Con esto aparecer&aacute; una lista de colecciones Greenstone. Haga click en una para ver su descripci&oacute;n. Marque los recuadros de las colecciones que desea exportar. Usted tambi&eacute;n puede ingresar el nombre de CD/DVD en el cuadro correspondiente, el cual aparecer&aacute; en el men&uacute; de Inicio una vez que el CD/DVD se haya instalado. A continuaci&oacute;n haga click en "Exportar". El proceso incluye la copia de varios archivos y requerir&aacute; de unos cuantos minutos.</p>
+<p>Una vez que haya terminado Greenstone mostrar&aacute; el nombre de una carpeta en la que se encontrar&aacute;n las colecciones que se han exportado. Utilice una quemadora de CD/DVDs para copiar sus contenidos en un CD/DVD en blanco.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/fileassociations.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/fileassociations.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/fileassociations.htm	(revision 13928)
@@ -0,0 +1,19 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="fileassociations"><font face="Verdana" size="5"><strong>8.2: Asociaci&oacute;n de archivos</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>La Interfaz de Bibliotecario utiliza diferentes programas de aplicaci&oacute;n para abrir tipos particulares de archivos. Para modificar la asociaci&oacute;n de archivos abra el men&uacute; "Archivo" y haga click en "Asociaci&oacute;n de archivos".</p>
+<p>Para establecer una asociaci&oacute;n seleccione la extensi&oacute;n del archivo de la lista descendente o escriba una nueva extensi&oacute;n (no incluya "."). A continuaci&oacute;n escriba en el campo correspondiente el comando que da inicio a la aplicaci&oacute;n deseada o elija la aplicaci&oacute;n en el cuadro "Explorar". "%1" se puede utilizar en el comando de inicio para insertar el nombre del archivo que se est&aacute; abriendo. Una vez que se han llenado estos campos, el bot&oacute;n "A&ntilde;adir" se activar&aacute;, con lo que ya se puede hacer click en &eacute;l para establecer la asociaci&oacute;n.</p>
+<p>Para editar una asociaci&oacute;n, seleccione una extensi&oacute;n de archivo existente. El comando asociado aparecer&aacute; en el campo correspondiente a comando de inicio. Ed&iacute;telo y a continuaci&oacute;n haga click en "Reemplazar".</p>
+<p>Para eliminar una asociaci&oacute;n, seleccione la extensi&oacute;n del archivo y haga click en "Eliminar". La extensi&oacute;n del archivo permanecer&aacute; en una lista llamada "Para archivos que terminan en...".</p>
+<p>Las asociaciones de archivos se guardan en la carpeta principal de la Interfaz de Bibliotecario en un archivo llamado "associations.xml".</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/filteringthetree.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/filteringthetree.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/filteringthetree.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="filteringthetree"><font face="Verdana" size="5"><strong>4.5: Filtrando la estructura de directorios y subdirectorios</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>"Filtrar" la estructura de directorios y subdirectorios de la colecci&oacute;n limita la b&uacute;squeda a determinados tipos de archivos.</p>
+<p>El men&uacute; "Mostrar archivos" debajo de cada estructura de directorios y subdirectorios muestra una lista de filtros definidos previamente, como por ejemplo el de "Im&aacute;genes". Al elegir uno se ocultan temporalmente todos los dem&aacute;s archivos. Para restaurarlos, cambie el filtro a "Todos los archivos". Estas operaciones no alteran la colecci&oacute;n ni afectan las carpetas en la estructura de archivos.</p>
+<p>Se puede especificar un filtro en particular escribiendo un patr&oacute;n que corresponda con los tipos de archivos que se desea filtrar (S&oacute;lo en los modos Especialista de Sistemas Bibliotecarios y Experto). Utilice las abreviaturas est&aacute;ndar del sistema como "*.*" o "*.doc" ("*" equivale a cualquier caracter).</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/formatstatements.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/formatstatements.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/formatstatements.htm	(revision 13928)
@@ -0,0 +1,22 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="formatstatements"><font face="Verdana" size="5"><strong>6.9: Formatos</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Las p&aacute;ginas Web que usted ve cuando utiliza Greenstone no han sido guardadas previamente sino que se generan &ldquo;al vuelo&rdquo; conforme se van necesitando. Los comandos de formato se utilizan para cambiar la apariencia de las p&aacute;ginas generadas. Afectan aspectos como el lugar donde aparecer&aacute;n los botones cuando se muestra un documento y qu&eacute; v&iacute;nculos despliega el clasificador DateList en pantalla. Los comandos de formato no son f&aacute;ciles de desarrollar, por lo que le recomendamos que lea el Cap&iacute;tulo 2 de la Gu&iacute;a del Programador de Greenstone. La presente secci&oacute;n describe los controles de los distintos formatos y la forma en que la Interfaz de Bibliotecario le da acceso a ellos. En la parte de "Secciones de dise&ntilde;o" haga click en "Formatos".</p>
+<p>Se puede aplicar un comando de formato a cualquier cosa que se encuentre en la lista llamada "Elegir funci&oacute;n", la cual incluye cada clasificador y una lista de funciones determinadas previamente. Cuando se selecciona una funci&oacute;n existen dos tipos de controles. Algunas funciones simplemente se activan o se desactivan por medio de un recuadro. Otras requieren que se especifique una cadena de formato, para las cuales hay una lista descendente (llamada "Componente afectado") que permite seleccionar la parte de la funci&oacute;n a la que se aplica la cadena (en caso necesario), un &aacute;rea de texto (llamada "cadena de formato HTML") para ingresar la cadena y una selecci&oacute;n de "variables" definidas previamente. Para insertar una variable en su posici&oacute;n actual dentro de la cadena de formato, selecci&oacute;nela de la lista descendente y haga click en "Insertar".</p>
+<p>Tambi&eacute;n se puede especificar un formato predeterminado para un componente en particular seleccionando la funci&oacute;n que est&aacute; en blanco. Este formato se aplicar&aacute; a todas las funciones aplicables a menos que se especifique lo contrario.</p>
+<p>Para a&ntilde;adir un nuevo formato de comando llene la informaci&oacute;n tal como se describe arriba y haga click en "A&ntilde;adir formato". El nuevo comando de formato aparecer&aacute; en la lista de "Comandos de formato asignados actualmente". Solamente se podr&aacute; asignar un comando de formato a cada combinaci&oacute;n de funci&oacute;n/componente.</p>
+<p>Para quitar un comando de formato de la lista, selecci&oacute;nelo y haga click en "Eliminar formato".</p>
+<p>Para cambiar un comando de formato, selecci&oacute;nelo de la lista, modifique sus par&aacute;metros y haga click en "Reemplazar formato".</p>
+<p>Para mayor informaci&oacute;n acerca de las variables y los componentes de las funciones lea el Cap&iacute;tulo 2 de la Gu&iacute;a del Programador de Greenstone.</p>
+<p>Si se marca el recuadro "Permitir opciones avanzadas" se activar&aacute;n algunas opciones de formateo avanzado. La lista de funciones que se pueden formatear cambia ligeramente y m&aacute;s variables est&aacute;n disponibles para usarlas en los comandos de formato, proporcionando as&iacute; un mayor control sobre el dise&ntilde;o de la p&aacute;gina.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/generalsettings.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/generalsettings.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/generalsettings.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="generalsettings"><font face="Verdana" size="5"><strong>6.2: General</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Esta secci&oacute;n explica la forma de revisar y modificar los ajustes generales asociados a una colecci&oacute;n. Primero que nada, en la parte de "Secciones de dise&ntilde;o" haga click en "General".</p>
+<p>Aqu&iacute; pueden modificarse los valores proporcionados durante la fase de creaci&oacute;n de la colecci&oacute;n.</p>
+<p>Primero se encuentran las direcciones de correo electr&oacute;nico del creador y del administrador de la colecci&oacute;n. El siguiente campo le permite cambiar el t&iacute;tulo de la colecci&oacute;n. El directorio en el que se almacena la colecci&oacute;n se muestra al lado, pero no puede editarse. El que sigue especifica (en forma de URL) el icono que aparecer&aacute; en el &aacute;ngulo superior izquierdo de la p&aacute;gina "Acerca de" y el siguiente es el icono usado en la p&aacute;gina de la biblioteca digital Greenstone para conectarse a la colecci&oacute;n. Entonces, una casilla controla que la colecci&oacute;n sea o no accesible p&uacute;blicamente. Finalmente viene el &aacute;rea de texto que permite dar una "Descripci&oacute;n de la Colecci&oacute;n", tal como se explica en la secci&oacute;n <a href="creatingacollection.htm">Creando una nueva colecci&oacute;n</a>.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/help.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/help.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/help.xml	(revision 13928)
@@ -0,0 +1,407 @@
+<Document>
+<Section name="introduction">
+<Title>
+<Text id="1">IntroducciÃ³n</Text>
+</Title>
+<Text id="2">La Interfaz de Bibliotecario de Greenstone es una herramienta que permite reunir y marcar documentos para luego crear colecciones digitales con ellos, dÃ¡ndole fÃ¡cil acceso a todas las funciones de los programas de software de la Biblioteca Digital Greenstone desde una interfaz grÃ¡fica de usuario con la que sÃ³lo tiene que apuntar y hacer click.</Text>
+<Section name="ofmiceandmenus">
+<Title>
+<Text id="3">De menÃºs y ratones</Text>
+</Title>
+<Text id="4">Esta secciÃ³n proporciona informaciÃ³n bÃ¡sica para poder trabajar con la Interfaz de Bibliotecario. Si estÃ¡ familiarizado con programas como Internet Explorer o Microsoft Office y estÃ¡ acostumbrado a usar el mouse, entonces pase a la secciÃ³n <Reference target="howtoavoidthisdocument"/>.</Text>
+<Text id="5">La Interfaz de Bibliotecario sigue las convenciones de Microsoft y se apoya en el conocimiento que comÃºnmente se tiene de Windows.</Text>
+<Text id="6">Cualquier parte de la pantalla con la que usted interactÃºe, como un botÃ³n o un campo de texto, se llama "control". En todo momento un botÃ³n o campo de texto llamado "control activo" aparecerÃ¡ resaltado y responderÃ¡ a las instrucciones del teclado. Asimismo, varios controles le permiten seleccionar las partes que estÃ©n resaltadas en azul marino. Algunos controles tambiÃ©n pueden aparecer sombreados para indicar que no estÃ¡n disponibles.</Text>
+<Text id="7">Usted puede mover y hacer click con el botÃ³n izquierdo o derecho del mouse de la forma acostumbrada. Muchos componentes tambiÃ©n se pueden "arrastrar" haciendo click en ellos y sosteniendo el botÃ³n izquierdo del mouse, para luego moverlos y "colocarlos" en algÃºn otro lugar soltando el botÃ³n. Normalmente el lugar de destino cambia de apariencia cuando un componente pasa sobre Ã©l.</Text>
+<Text id="8">Usted puede usar el teclado para escribir en los campos de texto. Muchos controles tambiÃ©n se pueden ejecutar por medio del teclado, lo que se indica por medio de corchetes -- por ejemplo la tecla de tabulaciÃ³n [Tab] cambia el control activo. El signo de mÃ¡s (+) indica que otras teclas deben oprimirse al mismo tiempo.</Text>
+<Text id="9">Para tener acceso a un menÃº, oprima el botÃ³n [ALT] y presione la letra correspondiente (la cual aparece subrayada). Por ejemplo, para desplegar el menÃº "Archivo" oprima [ALT] + [A]. Para elegir un comando presione la tecla correspondiente. Por ejemplo, en el menÃº "Archivo" presione [G] para "Guardar" la colecciÃ³n.</Text>
+<Text id="10">Los botones, al igual que los menÃºs, tienen una letra subrayada. Para seleccionar un botÃ³n oprima la tecla [ALT] y la letra que estÃ¡ subrayada al mismo tiempo.</Text>
+<Text id="11">Salga de la Interfaz de Bibliotecario eligiendo "Salir" en el menÃº "Archivo". Su colecciÃ³n se guardarÃ¡ primero.</Text>
+</Section>
+<Section name="howtoavoidthisdocument">
+<Title>
+<Text id="12">Temas de ayuda</Text>
+</Title>
+<Text id="13">Â¡Usted no necesita leer todo el texto de ayuda! SÃ³lo lea lo suficiente para saber cÃ³mo obtener ayuda cuando la necesite.</Text>
+<Text id="14">El comando del menÃº "Ayuda" indica los que serÃ­an los temas de ayuda mÃ¡s apropiados por medio de un pequeÃ±o icono en forma de libro.</Text>
+<Text id="15">Para muchos controles si se coloca el mouse encima de ellos aparecerÃ¡ un "cuadro de sugerencias" en el cual se explica su funciÃ³n.</Text>
+<Text id="16">Antes de usar la Interfaz de Bibliotecario lea primero la documentaciÃ³n de Greenstone.</Text>
+</Section>
+</Section>
+<Section name="startingoff">
+<Title>
+<Text id="17">Para empezar</Text>
+</Title>
+<Text id="18">Esta secciÃ³n explica cÃ³mo crear, cargar, guardar y borrar colecciones.</Text>
+<Section name="creatingacollection">
+<Title>
+<Text id="19">Creando una nueva colecciÃ³n</Text>
+</Title>
+<Text id="20">Para crear una nueva colecciÃ³n abra el menÃº "Archivo" y elija la opciÃ³n "Nueva". DeberÃ¡n llenarse varios campos, aunque en caso de que lo requiera usted podrÃ¡ cambiar despuÃ©s sus valores en la pantalla de diseÃ±o.</Text>
+<Text id="21">El "TÃ­tulo de la colecciÃ³n" es el texto que aparece en la parte superior de la pÃ¡gina principal de su colecciÃ³n. Puede tener la longitud  que usted quiera.</Text>
+<Text id="22">La "DescripciÃ³n del contenido" deberÃ¡ describir tan detalladamente como sea posible de lo que se trata la colecciÃ³n. Utilice la tecla [Enter] o [Intro] para dividirla en pÃ¡rrafos.</Text>
+<Text id="23">Finalmente deberÃ¡ especificar si desea que la nueva colecciÃ³n tenga la misma apariencia y conjunto de metadatos que una colecciÃ³n existente o si desea iniciar una "Nueva ColecciÃ³n" por omisiÃ³n.</Text>
+<Text id="24">Haga click en "Aceptar" para crear la colecciÃ³n. Si usted escogiÃ³ "Nueva ColecciÃ³n" se le pedirÃ¡ que elija el conjunto de metadatos que usarÃ¡ en ella.  Puede elegir mÃ¡s de uno y tambiÃ©n puede aÃ±adir otros mÃ¡s adelante.</Text>
+<Text id="25">Si hace click en "Cancelar" regresarÃ¡ inmediatamente a la pantalla principal.</Text>
+</Section>
+<Section name="savingacollection">
+<Title>
+<Text id="26">Guardar la colecciÃ³n</Text>
+</Title>
+<Text id="27">Guarde su trabajo regularmente abriendo el menÃº "Archivo" y seleccionando "Guardar". Tome en cuenta que guardar una colecciÃ³n no es lo mismo que prepararla para que se pueda usar en Greenstone (vea la secciÃ³n <Reference target="producingthecollection"/>).</Text>
+<Text id="28">La Interfaz de Bibliotecario protege su trabajo guardÃ¡ndolo cada vez que salga del programa o cargue otra colecciÃ³n.</Text>
+<Text id="29">Las colecciones se guardan en un archivo que lleva el nombre de la colecciÃ³n y la extensiÃ³n ".col", ubicado en una carpeta del mismo nombre dentro de la carpeta "colecciones" del programa Greenstone.</Text>
+</Section>
+<Section name="openingacollection">
+<Title>
+<Text id="30">Abriendo una colecciÃ³n existente</Text>
+</Title>
+<Text id="31">Para abrir una colecciÃ³n existente elija la opciÃ³n "Abrir" en el menÃº "Archivo". Con esto aparecerÃ¡ una lista de sus colecciones Greenstone. Seleccione una para ver su descripciÃ³n y haga click en "Abrir" para cargarla. Si busca una colecciÃ³n que resida fuera de la carpeta de "colecciones" de Greenstone, entonces haga click en "Explorar" para que aparezca un cuadro de diÃ¡logo que le permita buscar en el sistema de archivos.</Text>
+<Text id="32">En caso de que mÃ¡s de una Interfaz de Bibliotecario de Greenstone estÃ© corriendo al mismo tiempo, los directorios pertinentes se "bloquean" para evitar interferencias. Al abrir una colecciÃ³n se crea un pequeÃ±o archivo de bloqueo temporal en la carpeta. Antes de abrir una colecciÃ³n la Interfaz de Bibliotecario revisa que no haya un archivo de bloqueo en ella. Se puede saber si la colecciÃ³n estÃ¡ bloqueada por el color de su icono: verde para una colecciÃ³n normal, rojo para una colecciÃ³n bloqueada. Sin embargo, cuando se sale prematuramente de la Interfaz de Bibliotecario el archivo de bloqueo a veces permanece en la carpeta. Cuando posteriormente se abre esta colecciÃ³n, la Biblioteca Digital le pregunta si quiere tomar el control. Por favor, nunca le quite el control de una colecciÃ³n a alguien que este trabajando en ese momento con ella.</Text>
+<Text id="33">Cuando usted abra una colecciÃ³n que no haya sido creada por medio de la Interfaz de Bibliotecario de Greenstone se le pedirÃ¡ que seleccione uno o mÃ¡s conjuntos de metadatos. Si no selecciona ninguno, entonces los metadatos existentes se ignorarÃ¡n. De otra manera los metadatos se importarÃ¡n tal como son cuando usted arrastre los archivos. El proceso se describe en el documento llamado <Reference target="importingpreviouslyassignedmetadata"/>.</Text>
+</Section>
+<Section name="deletingcollections">
+<Title>
+<Text id="34">Borrando colecciones</Text>
+</Title>
+<Text id="35">Para borrar definitivamente colecciones de su instalaciÃ³n de Greenstone, elija "BorrarâŠ" del menÃº "Archivo". Aparece una lista de sus colecciones. Seleccione una para ver su descripciÃ³n, marque la casilla situada en la parte inferior del diÃ¡logo, y pulse "Borrar" para borrar la colecciÃ³n. Esta acciÃ³n es irreversible, por lo que debe comprobar cuidadosamente que no necesita la colecciÃ³n antes de proceder.</Text>
+</Section>
+</Section>
+<Section name="downloadingfiles">
+<Title>
+<Text id="36">Descargando archivos de Internet</Text>
+</Title>
+<Text id="37">La vista "Bajar" le ayuda a descargar recursos de internet. Esta secciÃ³n explica el interfaz del mecanismo de puesta en espejo del Bibliotecario.</Text>
+<Section name="themirrorview">
+<Title>
+<Text id="38">La vista en Bajar</Text>
+</Title>
+<Text id="39">Esta secciÃ³n describe como configurar una tarea de descarga y como controlar el proceso de descargue. Active la vista "Bajar" haciendo clic en su pestaÃ±a. La mitad superior de la pantalla contiene los controles para realizar descargas. La mitad inferior estÃ¡ vacÃ­a inicialmente, pero despuÃ©s va a mostrar una lista de tareas pendientes y terminadas.</Text>
+<Text id="40">Los archivos se descargan en una carpeta del espacio de trabajo denominada "Archivos Descargados", y pueden utilizarse en todas las colecciones construidas con el interfaz del Bibliotecario. En esta Ã¡rea los archivos se designan con su URL completo. Para cada "host" se crea una nueva carpeta, seguida por otras para cada parte del "path". De esta manera se asegura que todos los archivos son distintos.</Text>
+<Text id="41">Utilice el primero de los controles de configuraciÃ³n de la descarga, "URL OrÃ­gen", para capturar el URL de un recurso deseado. Utilice el control "Profundidad de la Descarga" para limitar el nÃºmero de hiper-vÃ­nculos que se deben seguir al descargar: PÃ³ngalo en 0 para descargar una sola pÃ¡gina; pÃ³ngalo en 1 para descargar una pÃ¡gina y todas las pÃ¡ginas a las que apunta. El lÃ­mite de profundidad se ignora al descargar medios diferentes de pÃ¡ginas html. AdemÃ¡s, hay varios controles de chequeo que se pueden prender para activar determinadas capacidades durante una descarga especÃ­fica. Una vez se ha establecido la configuraciÃ³n, haga clic en "Descargar" para iniciar un nuevo proceso de descargue. Hay otros dos controles en forma de botones: "Preferencias", que enlaza con la secciÃ³n de conexiÃ³n de las Preferencias, en la cual se pueden editar las caracterÃ­sticas del "proxy"; y "Borrar CachÃ©", que borra todos los archivos descargados previamente.</Text>
+<Text id="42">La lista de descargas tiene una entrada por cada pÃ¡gina web descargada. Cada entrada tiene un Ã¡rea de texto que da detalles acerca de la tarea, junto con una barra que indica el avance de la actividad en ejecuciÃ³n. A la izquierda de cada entrada aparecen tres botones. "Pausa" se utiliza para detener temporalmente la descarga que se estÃ¡ ejecutando. "Ver BitÃ¡cora" abre una ventana que muestra el archivo de bitÃ¡cora de las descargas. "Cerrar" termina la descarga y quita de la lista la tarea correspondiente.</Text>
+<Text id="43">La secciÃ³n <Reference target="preferences"/> describe como establecer una conexiÃ³n Internet por medio de un "proxy".  Si se necesita autenticaciÃ³n, el servidor "proxy" pide la identificaciÃ³n y la palabra clave. El interfaz del Bibliotecario no almacena palabras claves entre sesiones.</Text>
+</Section>
+</Section>
+<Section name="collectingfiles">
+<Title>
+<Text id="44">Reuniendo archivos para su colecciÃ³n</Text>
+</Title>
+<Text id="45">Una vez que usted tiene una nueva colecciÃ³n necesita meter algunos archivos en ella. Estos pueden venir desde la estructura de archivos de su computadora o de otras colecciones Greenstone. Algunos incluso ya pueden tener metadatos. Esta secciÃ³n describe la forma de importar archivos.</Text>
+<Section name="thegatherview">
+<Title>
+<Text id="46">La pantalla de selecciÃ³n de documentos</Text>
+</Title>
+<Text id="47">Esta secciÃ³n describe el funcionamiento de la pantalla "Reunir" que se utiliza para seleccionar los archivos que se van a incluir en la colecciÃ³n que se estÃ¡ construyendo. La Interfaz de Bibliotecario inicia con la pantalla "Reunir". Si despuÃ©s usted desea regresar a esta pantalla haga click en la pestaÃ±a del mismo nombre que se encuentra directamente debajo de la barra de menÃºs.</Text>
+<Text id="48">Dos grandes Ã¡reas tituladas "Area de trabajo" y "ColecciÃ³n" se utilizan para transferir los archivos a su colecciÃ³n. Cada una contiene "Ã¡rboles de archivos", los cuales son representaciones grÃ¡ficas de la estructura de directorios y subdirectorios de sus archivos y carpetas.</Text>
+<Text id="49">Seleccione un elemento del Ã¡rbol haciendo click en Ã©l. (TambiÃ©n existen otras formas; vÃ©ase mÃ¡s adelante.) Haga click en el signo que se encuentra junto a una carpeta o doble click en ella para expandir (o contraer) sus contenidos. Haga doble click en un archivo para abrirlo usando un programa de aplicaciÃ³n asociado (vea la secciÃ³n <Reference target="fileassociations"/>).</Text>
+<Text id="50">El Ã¡rbol de archivos del Ã¡rea de trabajo muestra los orÃ­genes de la informaciÃ³n disponible al interfaz del Bibliotecario -- el sistema local de archivos (incluyendo unidades de disco y CD-ROM), los contenidos de las colecciones existentes de Greenstone, y el cachÃ© de archivos descargados. Usted puede copiar y consultar estos archivos pero no puede moverlos, eliminarlos o editarlos, con la excepciÃ³n de los archivos descargados, los cuales pueden ser eliminados. Navegue por este espacio para buscar los archivos que desee incluir en la colecciÃ³n.</Text>
+<Text id="51">La estructura de directorios y subdirectorios de la colecciÃ³n muestra sus contenidos. Inicialmente estÃ¡ vacÃ­a.</Text>
+<Text id="52">Se puede cambiar el tamaÃ±o de las Ã¡reas oprimiendo el botÃ³n del mouse sobre la barra gris que separa las estructuras de directorios y subdirectorios (la forma del cursor cambia) y arrastrÃ¡ndola.</Text>
+<Text id="53">En la parte inferior de la ventana se muestra un Ã¡rea de estado que informa del progreso de las acciones sobre archivos (copiando, moviendo y borrando). Puede tardar un tiempo en terminar. El botÃ³n "Detener" interrumpe cualquier acciÃ³n que se estÃ© ejecutando en ese momento.</Text>
+<Text id="54">Dos grandes botones ocupan la esquina inferior derecha de la pantalla: "Nueva carpeta", con la imagen de una carpeta, crea nuevas carpetas (vea la secciÃ³n <Reference target="creatingfolders"/>), en tanto que "Eliminar", con la imagen de un bote de basura, descarta los archivos. Al hacer click en el botÃ³n "Eliminar" se suprimirÃ¡n los archivos seleccionados de la estructura de directorios y subdirectorios de la colecciÃ³n. Asimismo, los archivos pueden eliminarse arrastrÃ¡ndolos hacia este botÃ³n.</Text>
+<Text id="55">Para seleccionar varios elementos consecutivos, seleccione el primero y a continuaciÃ³n manteniendo oprimida la tecla de mayÃºsculas o [Shift] haga click en el Ãºltimo: la selecciÃ³n incluirÃ¡ todos los elementos que se encuentran en medio. Para seleccionar varios archivos que no sean consecutivos mantenga oprimida la tecla de control o [Ctrl] mientras hace click en ellos. Utilice alternativamente estos dos mÃ©todos para seleccionar grupos de elementos que no estÃ©n juntos.</Text>
+<Text id="56">En ocasiones algunas carpetas, como la que contiene sus propias pÃ¡ginas Web, tienen un significado especial. La Interfaz de Bibliotecario puede asignar dichas carpetas al primer nivel de la estructura de directorios y subdirectorios. Para hacerlo haga click con el botÃ³n derecho del mouse sobre la carpeta deseada. Seleccione "Crear un acceso directo" y dÃ©le un nombre a la carpeta. Para quitar un elemento haga click con el botÃ³n derecho del mouse sobre la carpeta mapeada y seleccione "Eliminar acceso directo".</Text>
+</Section>
+<Section name="creatingfolders">
+<Title>
+<Text id="57">Creando carpetas</Text>
+</Title>
+<Text id="58">Utilice las carpetas que se encuentran en la estructura de directorios y subdirectorios de la colecciÃ³n para agrupar archivos y hacer que sean mÃ¡s fÃ¡ciles de encontrar. Las carpetas pueden contener a su vez otras subcarpetas. No hay prÃ¡cticamente ningÃºn lÃ­mite en cuanto al nÃºmero de carpetas que se pueden tener o quÃ© tan profundamente anidadas puedan estar.</Text>
+<Text id="59">Para crear una nueva carpeta, una opciÃ³n es seleccionar una carpeta existente en la estructura de directorios y subdirectorios de la colecciÃ³n y hacer click en el botÃ³n "Nueva carpeta". La nueva carpeta aparecerÃ¡ dentro de la que se seleccionÃ³ primero o en el nivel superior si no se seleccionÃ³ ninguna. Se le pedirÃ¡ que le dÃ© un nombre a la carpeta (el valor por omisiÃ³n es "Nueva carpeta").</Text>
+<Text id="60">TambiÃ©n se pueden crear nuevas carpetas haciendo click sobre una carpeta con el botÃ³n derecho del mouse,  eligiendo la opciÃ³n "Nueva carpeta" y continuando tal como se describe arriba.</Text>
+</Section>
+<Section name="addingfiles">
+<Title>
+<Text id="61">AÃ±adiendo archivos</Text>
+</Title>
+<Text id="62">Los archivos se pueden copiar arrastrÃ¡ndolos y colocÃ¡ndolos en una colecciÃ³n. El cursor se convierte en un fantasma del elemento seleccionado (o, si se ha seleccionado mÃ¡s de uno, del nÃºmero de ellos). Coloque la selecciÃ³n en la estructura de directorios y subdirectorios de la colecciÃ³n para copiar ahÃ­ los archivos (si la fuente son los archivos del Ã¡rea de trabajo) o muÃ©valos de lugar dentro de la misma colecciÃ³n (si la fuente son los archivos de la colecciÃ³n).</Text>
+<Text id="63">Cuando se copien varios archivos en una carpeta todos estarÃ¡n al mismo nivel, sin importar la estructura de las carpetas en las que se encontraban originalmente. Cuando se copie un segundo archivo con el mismo nombre en la misma carpeta se le preguntarÃ¡ si desea reemplazar el archivo existente. Si la respuesta es "No" entonces el archivo no se copiarÃ¡, pero los demÃ¡s sÃ­. Para cancelar las acciones restantes de copiado haga click en el botÃ³n "Detener".</Text>
+<Text id="64">Ãnicamente se moverÃ¡n los elementos "de mÃ¡s alto nivel" en una selecciÃ³n. Una carpeta estÃ¡ a un nivel mÃ¡s alto que los elementos que se encuentran en su interior, por lo que no se podrÃ¡n seleccionar los archivos de una carpeta y la carpeta al mismo tiempo.</Text>
+<Text id="65">Cuando se aÃ±ada un archivo, la Interfaz de Bibliotecario buscarÃ¡ a travÃ©s de las carpetas fuente los archivos auxiliares que contienen los metadatos asignados previamente a dicho archivo y, si encuentra alguno, empezarÃ¡ a importar estos metadatos. Conforme la operaciÃ³n siga adelante se le pedirÃ¡ (quizÃ¡ varias veces) que proporcione informaciÃ³n adicional para conciliar los metadatos importados con los conjuntos de metadatos de su colecciÃ³n. Este proceso incluye muchos avisos diferentes, los cuales se describen en la secciÃ³n <Reference target="importingpreviouslyassignedmetadata"/>. Para obtener una explicaciÃ³n mÃ¡s detallada sobre la forma de asociar metadatos a los archivos lea el CapÃ­tulo 2 de la GuÃ­a del Programador de Greenstone: Obteniendo el mÃ¡ximo beneficio de sus documentos.</Text>
+</Section>
+<Section name="removingfiles">
+<Title>
+<Text id="66">Eliminando archivos</Text>
+</Title>
+<Text id="67">Existen varios mÃ©todos para eliminar archivos y carpetas. Primero se deben indicar los elementos que se desea eliminar seleccionando los archivos y carpetas tal como se describe en la secciÃ³n de <Reference target="thegatherview"/>.</Text>
+<Text id="68">Una vez que se han seleccionado los archivos, haga click en el botÃ³n "Eliminar" o presione la tecla [Del], [Supr] o [Suprimir], dependiendo del teclado de su computadora, o arrÃ¡strelos desde la colecciÃ³n hasta el botÃ³n "Eliminar" y suÃ©ltelos ahÃ­.</Text>
+</Section>
+<Section name="filteringthetree">
+<Title>
+<Text id="69">Filtrando la estructura de directorios y subdirectorios</Text>
+</Title>
+<Text id="70">"Filtrar" la estructura de directorios y subdirectorios de la colecciÃ³n limita la bÃºsqueda a determinados tipos de archivos.</Text>
+<Text id="71">El menÃº "Mostrar archivos" debajo de cada estructura de directorios y subdirectorios muestra una lista de filtros definidos previamente, como por ejemplo el de "ImÃ¡genes". Al elegir uno se ocultan temporalmente todos los demÃ¡s archivos. Para restaurarlos, cambie el filtro a "Todos los archivos". Estas operaciones no alteran la colecciÃ³n ni afectan las carpetas en la estructura de archivos.</Text>
+<Text id="72">Se puede especificar un filtro en particular escribiendo un patrÃ³n que corresponda con los tipos de archivos que se desea filtrar (SÃ³lo en los modos Especialista de Sistemas Bibliotecarios y Experto). Utilice las abreviaturas estÃ¡ndar del sistema como "*.*" o "*.doc" ("*" equivale a cualquier caracter).</Text>
+</Section>
+</Section>
+<Section name="enrichingacollection">
+<Title>
+<Text id="73">Enriqueciendo la colecciÃ³n con metadatos</Text>
+</Title>
+<Text id="74">DespuÃ©s de haber juntado varios archivos en una colecciÃ³n, enriquÃ©zcalos con informaciÃ³n adicional. Esta secciÃ³n explica la forma en que se crean, editan, asignan y recuperan los metadatos, y la forma de usar fuentes externas de metadatos (vÃ©ase tambiÃ©n el CapÃ­tulo 2 de la GuÃ­a del Programador de Greenstone: Obteniendo el mÃ¡ximo beneficio de sus documentos).</Text>
+<Section name="theenrichview">
+<Title>
+<Text id="75">La pantalla de asignaciÃ³n de metadatos</Text>
+</Title>
+<Text id="76">Utilice la pantalla "Enriquecer" para asignar metadatos a los documentos de la colecciÃ³n. Los metadatos son datos acerca de los datos: tÃ­tulo, autor, fecha de creaciÃ³n, etc. Cada metadato tiene dos partes: el "elemento" dice el tipo de metadato que es (como por ejemplo el autor) y el "valor" da la informaciÃ³n de ese elemento (como por ejemplo el nombre del autor).</Text>
+<Text id="77">En la parte izquierda de la pantalla "Enriquecer" se encuentra la estructura de directorios y subdirectorios de la colecciÃ³n. A la derecha estÃ¡ la Tabla de Metadatos, la cual muestra los metadatos de los archivos y carpetas seleccionados. Los nombres de las columnas estÃ¡n en gris en la parte superior y se pueden cambiar de tamaÃ±o arrastrando la lÃ­nea que las separa. Si se seleccionan varios archivos, el texto en negro indica que el valor es comÃºn a todos ellos, mientras que el texto sombreado indica que no. Los valores en negro se pueden actualizar o eliminar, mientras que los que estÃ¡n sombreados se pueden eliminar de los que los tienen o agregarse a los demÃ¡s.</Text>
+<Text id="78">Un icono en forma de carpeta puede aparecer junto a algunas entradas de metadatos. Esto indica que los valores se heredan de la carpeta en la que se encuentra el archivo. Los metadatos heredados no se pueden editar o eliminar, sino Ãºnicamente agregarse o sobreescribirse. Haga click en el icono de la carpeta para ir inmediatamente a la carpeta en la que se asignaron los metadatos.</Text>
+<Text id="79">Pulsando sobre el elemento de matadato en la tabla se mostrarÃ¡n los valores existentes  para ese elemento en el Ã¡rea "Valores existentes para..." situada debajo de la tabla. La estructura de valores se puede expandir y contraer. Normalmente es una lista que muestra todos los valores ingresados previamente para un elemento seleccionado. Al hacer click en una entrada Ã©sta aparece automÃ¡ticamente en el campo de valores. Y a la inversa, al escribir en el campo se selecciona la entrada de la estructura de valores que empieza con los caracteres ingresados. Al oprimir [Tab] se completa automÃ¡ticamente el valor seleccionado.</Text>
+<Text id="80">Los valores de los metadatos se pueden organizar jerÃ¡rquicamente. Esto se muestra en la estructura de valores por medio de carpetas para los niveles internos. Los valores jerÃ¡rquicos pueden ingresarse utilizando el carÃ¡cter "|" para separar los niveles. Por ejemplo, se puede usar "Cartas|Rojo|Diamantes|Siete" en una jerarquÃ­a que representa un mazo de cartas. Esto permite agrupar los valores, en tanto que los grupos tambiÃ©n pueden asignarse en forma de metadatos a los archivos.</Text>
+<Text id="81">Greenstone extrae automÃ¡ticamente los metadatos de los documentos para formar un conjunto de metadatos cuyos elementos llevan el prefijo "ex.". Ãste no tiene estructura de valores y no puede editarse.</Text>
+</Section>
+<Section name="selectingmetadatasets">
+<Title>
+<Text id="82">Seleccionando conjuntos de metadatos</Text>
+</Title>
+<Text id="83">Los grupos de elementos de metadatos definidos previamente son conocidos como "conjuntos de metadatos". Un ejemplo es el conjunto de metadatos de Dublin Core. Cuando se aÃ±ade un conjunto de metadatos a una colecciÃ³n, sus elementos se vuelven elegibles para que el usuario los pueda seleccionar. TambiÃ©n se puede tener mÃ¡s de un conjunto. Para evitar conflictos de nombre, un identificador que describe al conjunto de metadatos se agrega como prefijo al nombre del elemento. Por ejemplo, el elemento Creator de Dublin Core se convierte en "dc.Creator". Los conjuntos de metadatos se guardan en la carpeta de metadatos de la Interfaz de Bibliotecario y llevan el sufijo ".mds".</Text>
+<Text id="84">Para controlar los conjuntos de metadatos usados en una colecciÃ³n, utilice la opciÃ³n "Conjuntos de metadatos" en la vista DiseÃ±o.</Text>
+</Section>
+<Section name="appendingmetadata">
+<Title>
+<Text id="85">Agregando nuevos metadatos</Text>
+</Title>
+<Text id="86">Ahora aÃ±adiremos un Ã­tem de metadato -- tanto un elemento como un valor -- a un archivo. Primero, seleccione el archivo en la estructura de directorios y subdirectorios de la colecciÃ³n que se encuentra a la izquierda. Esto hace que cualquier metadato asignado previamente a este archivo aparezca en la tabla de la derecha.</Text>
+<Text id="87">A continuaciÃ³n, seleccione el elemento de metadato que desea aÃ±adir haciendo click en la fila correspondiente de la tabla.</Text>
+<Text id="88">Escriba el valor en el campo de valores. Use el carÃ¡cter "|" para aÃ±adir estructura, tal y como se explica en <Reference target="theenrichview"/>. Pulsando las teclas de flecha [Arriba] o [Abajo] se guardarÃ¡n los metadatos y se moverÃ¡ la selecciÃ³n adecuadamente. Pulsando [Retorno] se guardarÃ¡n los metadatos y se crearÃ¡ una nueva entrada vacÃ­a para un elemento de metadato, permitiendo asignar varios valores al mismo.</Text>
+<Text id="89">TambiÃ©n se pueden aÃ±adir metadatos a una carpeta o a varios archivos seleccionados al mismo tiempo. Estos metadatos se aÃ±adirÃ¡ a todos los archivos que forman parte de la carpeta o de la selecciÃ³n, asÃ­ como a las subcarpetas. Recuerde que si usted asigna metadatos a una carpeta, todos los archivos nuevos que se encuentren en ella heredarÃ¡n automÃ¡ticamente los valores de la carpeta.</Text>
+</Section>
+<Section name="addingpreviouslydefinedmetadata">
+<Title>
+<Text id="90">AÃ±adiendo Metadatos Previamente Definidos</Text>
+</Title>
+<Text id="91">Para aÃ±adir metadatos con un valor existente, seleccione primero el archivo y a continuaciÃ³n el valor requerido de la estructura de valores, expandiendo las carpetas tanto como sea necesario. El valor de la entrada seleccionada aparecerÃ¡ automÃ¡ticamente en el campo de texto (otra alternativa es utilizar las funciones de selecciÃ³n automÃ¡tica y completamiento automÃ¡tico de la estructura de valores). </Text>
+<Text id="92">El proceso de aÃ±adir metadatos con valores existentes a carpetas o a varios archivos juntos es exactamente igual.</Text>
+</Section>
+<Section name="updatingmetadata">
+<Title>
+<Text id="93">Editar o Borrar Metadatos</Text>
+</Title>
+<Text id="94">Para editar o borrar elementos de metadato, primero seleccione el campo apropiado, y luego el valor de metadato de la tabla. Edite el campo del valor, y borre todo el texto si quiere borrar el metadato.</Text>
+<Text id="95">El proceso es el mismo cuando se actualiza un directorio que contiene subdirectorios o mÃºltiples archivos, pero sÃ³lo se pueden actualizar metadatos que sean comunes a todos los archivos y carpetas seleccionados.</Text>
+<Text id="96">El arbol de valores muestra todos los valores asignados actualmente, asÃ­ como todos los valores previos de la sesiÃ³n activa, por lo que los valores modificados o borrados permanecerÃ¡n en el Ã¡rbol. Si cierra y vuelve a abrir la colecciÃ³n, se borrarÃ¡n los valores que ya no estÃ¡n asignados.</Text>
+</Section>
+<Section name="reviewingmetadata">
+<Title>
+<Text id="97">Revisando los metadatos asignados</Text>
+</Title>
+<Text id="98">En ocasiones es necesario ver los metadatos asignados a varios o a todos los archivos al mismo tiempo, por ejemplo, para determinar la forma en que quedan muchos archivos para trabajar en ellos o para tener una idea de la diferencia de tiempo entre las fechas.</Text>
+<Text id="99">Seleccione los archivos que desea examinar, pulse el botÃ³n derecho del ratÃ³n y elija "Metadatos AsignadosâŠ". Con lo que aparecerÃ¡ una ventana llamada "Todos los metadatos", ocupada en su mayor parte por una tabla de varias columnas. La primera columna muestra los nombres de los archivos, mientras que las filas muestran todos los valores asignados a dichos archivos.</Text>
+<Text id="100">Si se seleccionaron muchos archivos es posible que transcurra algÃºn tiempo antes de que se abra la ventana. Mientras tanto usted puede seguir usando la Interfaz de Bibliotecario.</Text>
+<Text id="101">Cuando la tabla sea demasiado grande se puede refinar aplicando los filtros a las columnas. Conforme se aÃ±adan nuevos filtros, Ãºnicamente aquellas filas que concuerden con ellos seguirÃ¡n siendo visibles. Para establecer, modificar o borrar un filtro haga click en el icono con forma de embudo que se encuentra en la parte superior de la columna. Se le indicarÃ¡ que proporcione informaciÃ³n sobre el filtro. Una vez que un filtro se ha aplicado, el encabezado de la columna cambia de color.</Text>
+<Text id="102">El aviso tiene una pestaÃ±a "Sencilla" y una "Avanzada". La versiÃ³n sencilla filtra las columnas de tal manera que sÃ³lo muestren las filas que contienen un determinado valor ("*" corresponde a todos los valores). Los valores de los metadatos se pueden seleccionar de la lista. La versiÃ³n avanzada permite diferentes operaciones de concordancia: "debe empezar con", "no contiene", "alfabÃ©ticamente menos que" y "es igual a". El valor se puede editar con cualquier cadena de caracteres (incluyendo "*") y se puede elegir que la concordancia no tome en cuenta el caso. Finalmente, se puede especificar una segunda condiciÃ³n de concordancia que se puede usar para especificar un rango de valores (seleccionando "Y") o valores alternativos (seleccionando "O"). Debajo de esta Ã¡rea hay un cuadro que le permite cambiar el orden de clasificaciÃ³n (ascendente o descendente). Una vez que haya terminado, haga click en "Filtrar" para aplicar el nuevo filtro a la columna. Para quitar el filtro haga click en "Borrar filtro". Recuerde que los detalles del filtro se conservan incluso cuando el filtro se borra.</Text>
+<Text id="103">Por ejemplo, para ordenar la tabla elija una columna, seleccione el filtro por omisiÃ³n (un filtro Sencillo en "*") y escoja el orden ascendente o descendente.</Text>
+</Section>
+<Section name="importingpreviouslyassignedmetadata">
+<Title>
+<Text id="104">Importando metadatos previamente asignados</Text>
+</Title>
+<Text id="105">Esta secciÃ³n describe cÃ³mo importar metadtos previamente asignados, es decir, metadatos asignados a los documentos antes de que fuesen aÃ±adidos a la colecciÃ³n.</Text>
+<Text id="106">Si se han asignado previamente metadatos en una forma reconocible por la Interfaz de Bibliotecario, por ejemplo, cuando se seleccionan documentos de una colecciÃ³n Greenstone existente, entonces Ã©stos se importarÃ¡n automÃ¡ticamente cuando usted aÃ±ada el archivo. Para poder hacer esto los metadatos deben mapearse hacia el conjunto de metadatos disponible en la colecciÃ³n.</Text>
+<Text id="107">La Interfaz de Bibliotecario enviarÃ¡ un mensaje solicitando la informaciÃ³n necesaria. El mensaje incluirÃ¡ breves instrucciones y a continuaciÃ³n mostrarÃ¡ el nombre del elemento de metadato que se estÃ¡ importando, tal como aparece en el archivo fuente. Este campo no se podrÃ¡ editar o cambiar. A continuaciÃ³n elija el conjunto de metadatos hacia el que el nuevo elemento deberÃ¡ mapearse y el correspondiente elemento de metadato en ese conjunto. El sistema selecciona automÃ¡ticamente la correspondencia mÃ¡s cercana en tÃ©rminos de conjunto y elemento para el nuevo metadato.</Text>
+<Text id="108">DespuÃ©s de revisar el mapeo, usted puede elegir "AÃ±adir" para aÃ±adir el nuevo elemento de metadato al conjunto de metadatos que se haya seleccionado. (Esto sÃ³lo es posible si no hay un elemento del mismo nombre dentro del conjunto seleccionado.) "Combinar" mapea el nuevo elemento hacia el que el usuario haya elegido. Finalmente, "Ignorar" no importa ningÃºn metadato con este nombre de elemento. Una vez que usted haya especificado la forma de importar una parte del metadato, la informaciÃ³n del proceso se conserva durante todo el tiempo de vida de la colecciÃ³n.</Text>
+<Text id="109">Para mayor informaciÃ³n sobre los archivos metadata.xml que Greenstone utiliza para guardar metadatos, vea el CapÃ­tulo 2 de la GuÃ­a del Programador de Greenstone: Obteniendo el mÃ¡ximo beneficio de sus documentos.</Text>
+</Section>
+</Section>
+<Section name="designingacollection">
+<Title>
+<Text id="110">DiseÃ±ando la apariencia de su colecciÃ³n</Text>
+</Title>
+<Text id="111">Una vez que los archivos estÃ¡n marcados con metadatos, a continuaciÃ³n se debe decidir la forma en que aparecerÃ¡n ante los usuarios como parte de una colecciÃ³n Greenstone. Â¿QuÃ© tipo de informaciÃ³n se podrÃ¡ buscar? Â¿De quÃ© medios se dispone para navegar por los documentos? Â¿En quÃ© idiomas? Â¿DÃ³nde aparecerÃ¡n los botones en la pÃ¡gina? Todas estas cosas se pueden personalizar. Esta secciÃ³n describe la forma de hacerlo.</Text>
+<Section name="thedesignview">
+<Title>
+<Text id="112">La pantalla de diseÃ±o</Text>
+</Title>
+<Text id="113">Esta secciÃ³n le presenta la pantalla de DiseÃ±o y le explica la forma de navegar entre las diferentes opciones de este conjunto.</Text>
+<Text id="114">Con la Interfaz de Bibliotecario usted puede configurar la forma en que la colecciÃ³n aparecerÃ¡ frente al usuario. Las opciones se dividen en diferentes secciones, cada una relacionada con una etapa particular de navegaciÃ³n o presentaciÃ³n.</Text>
+<Text id="115">A la izquierda se encuentra una lista de las diferentes pantallas, en tanto que a la derecha estÃ¡n los controles asociados a la pantalla que estÃ¡ activa en ese momento. Para cambiar a una pantalla diferente haga click en la lista.</Text>
+<Text id="116">Para entender las etapas y los tÃ©rminos usados en el diseÃ±o de una colecciÃ³n, lea primero los CapÃ­tulos 1 y 2 de la GuÃ­a del Programador de Greenstone.</Text>
+</Section>
+<Section name="generalsettings">
+<Title>
+<Text id="117">General</Text>
+</Title>
+<Text id="118">Esta secciÃ³n explica la forma de revisar y modificar los ajustes generales asociados a una colecciÃ³n. Primero que nada, en la parte de "Secciones de diseÃ±o" haga click en "General".</Text>
+<Text id="119">AquÃ­ pueden modificarse los valores proporcionados durante la fase de creaciÃ³n de la colecciÃ³n.</Text>
+<Text id="120">Primero se encuentran las direcciones de correo electrÃ³nico del creador y del administrador de la colecciÃ³n. El siguiente campo le permite cambiar el tÃ­tulo de la colecciÃ³n. El directorio en el que se almacena la colecciÃ³n se muestra al lado, pero no puede editarse. El que sigue especifica (en forma de URL) el icono que aparecerÃ¡ en el Ã¡ngulo superior izquierdo de la pÃ¡gina "Acerca de" y el siguiente es el icono usado en la pÃ¡gina de la biblioteca digital Greenstone para conectarse a la colecciÃ³n. Entonces, una casilla controla que la colecciÃ³n sea o no accesible pÃºblicamente. Finalmente viene el Ã¡rea de texto que permite dar una "DescripciÃ³n de la ColecciÃ³n", tal como se explica en la secciÃ³n <Reference target="creatingacollection"/>.</Text>
+</Section>
+<Section name="plugins">
+<Title>
+<Text id="121">Plugins</Text>
+</Title>
+<Text id="122">Esta secciÃ³n describe la forma de configurar los plugins que la colecciÃ³n utiliza. Explica el modo de especificar los plugins que se utilizarÃ¡n, los parÃ¡metros que emplearÃ¡n y el orden en el que se aplicarÃ¡n. En la parte de "Secciones de diseÃ±o" haga click en "Plugins de documento".</Text>
+<Text id="123">Para aÃ±adir un plugin, escÃ³jalo de la lista "Seleccione el plugin que se va a aÃ±adir" que se encuentra en la parte inferior de la pantalla y haga click en "AÃ±adir plugin". AparecerÃ¡ una ventana titulada "Argumentos de configuraciÃ³n", la cual se explica mÃ¡s adelante. Una vez que usted haya configurado el nuevo plugin, este se aÃ±adirÃ¡ al final de la lista de "Plugins asignados actualmente". Note que, excepto para UnknownPlug, cada plugin sÃ³lo puede aparecer una vez en la lista.</Text>
+<Text id="124">Para quitar un plugin de la lista, selecciÃ³nelo y haga click en "Eliminar plugin".</Text>
+<Text id="125">Los plugins se configuran por medio de argumentos. Para modificarlos, seleccione un plugin de la lista y haga click en "Configurar plugin" (o doble click en el plugin). Aparece un diÃ¡logo "Configurando Argumentos" con varios controles para especificar argumentos.</Text>
+<Text id="126">Existen diferentes tipos de controles. Algunos son recuadros y al hacer click en ellos se aÃ±ade la opciÃ³n correspondiente al plugin. Otros son cadenas de texto con un recuadro y un campo de texto. Haga click en el cuadro para habilitarlo y escriba el argumento (expresiÃ³n regular, ruta de archivo, etc.). Otros son menÃºs descendentes desde los que se puede seleccionar un conjunto dado de valores. Para saber lo que hace un argumento, coloque el cursor del mouse encima de su nombre y la descripciÃ³n aparecerÃ¡.</Text>
+<Text id="127">Una vez que usted haya cambiado la configuraciÃ³n, haga click en "Aceptar" para guardar los cambios y cerrar el cuadro de diÃ¡logo o en "Cancelar" para cerrar el cuadro de diÃ¡logo sin cambiar ningÃºn argumento.</Text>
+<Text id="128">Los plugins de la lista se ejecutan en orden y en ocasiones Ã©ste es importante. El orden de los plugins sÃ³lo se puede cambiar en los modos Especialista de Sistemas Bibliotecarios y Experto (vea la secciÃ³n <Reference target="preferences"/>).</Text>
+</Section>
+<Section name="searchtypes">
+<Title>
+<Text id="129">Tipos de bÃºsqueda</Text>
+</Title>
+<Text id="130">Esta secciÃ³n explica la forma de modificar una nueva funciÃ³n de diseÃ±o de Greenstone llamada "Tipos de bÃºsqueda", que permite la bÃºsqueda por campos. Los tipos de bÃºsqueda especifican el tipo de bÃºsqueda con el que contarÃ¡n las interfaces: formas, bÃºsqueda por campos y/o bÃºsqueda de sÃ³lo texto. En la parte de "Secciones de diseÃ±o" haga click en "Tipos de diseÃ±o".</Text>
+<Text id="131">Cuando ingrese a la pantalla de tipos de bÃºsqueda marque primero el recuadro "Permitir bÃºsquedas avanzadas", lo cual activa todos los demÃ¡s controles. Esto cambia la colecciÃ³n de forma que usa un mecanismo de indexado que permite la bÃºsqueda por campos. La especificaciÃ³n de Ã­ndices es ligeramente diferente en este modo. (Cuando se cambia entre bÃºsqueda estÃ¡ndar y avanzada, GLI intenta hacer correctamente el cambio de Ã­ndices, pero no lo hace de forma perfecta).</Text>
+<Text id="132">Para aÃ±adir un tipo de bÃºsqueda, selecciÃ³nelo de la lista "Tipos de bÃºsqueda" y haga click en "AÃ±adir tipo de bÃºsqueda". Cada tipo puede aparecer en la lista solamente una vez. El primer tipo de bÃºsqueda serÃ¡ el predefinido, y aparecerÃ¡ en la pÃ¡gina de bÃºsqueda de la colecciÃ³n construida. Los otros podrÃ¡n seleccionarse desde la pÃ¡gina de preferencias.</Text>
+<Text id="133">Para quitar un tipo de bÃºsqueda, selecciÃ³nelo de la lista "Tipos de bÃºsqueda asignados actualmente" y haga click en "Eliminar tipo de bÃºsqueda". La lista deberÃ¡ contener al menos uno.</Text>
+</Section>
+<Section name="searchindexes">
+<Title>
+<Text id="134">Ãndices de bÃºsqueda</Text>
+</Title>
+<Text id="135">Los Ã­ndices especifican las partes de la colecciÃ³n que se pueden buscar. Esta secciÃ³n explica la forma de aÃ±adir y eliminar Ã­ndices, asÃ­ como predeterminar un Ã­ndice por omisiÃ³n. En la parte correspondiente a "Secciones de diseÃ±o" haga click en "Ãndices de bÃºsqueda".</Text>
+<Text id="136">Para aÃ±adir un Ã­ndice escriba el nombre que le quiera dar en el campo "Nombre del Ã­ndice". Seleccione las fuentes de informaciÃ³n que se van a indexar haciendo click en los recuadros que se encuentran a un lado. La lista mostrarÃ¡ todos los elementos de metadatos asignados, asÃ­ como el texto completo. DespuÃ©s de seleccionar las fuentes de datos, elija la granularidad del Ã­ndice usando el menÃº de "Nivel". Una vez que se han completado estos detalles, la opciÃ³n "AÃ±adir Ã­ndice" se activa (a menos que haya un Ã­ndice con los mismos parÃ¡metros). Haga click en ella para aÃ±adir el nuevo Ã­ndice.</Text>
+<Text id="137">Para editar un Ã­ndice, selecciÃ³nelo, cambie los detalles del Ã­ndice, y pulse "Reemplazar Ãndice".</Text>
+<Text id="138">Para quitar un Ã­ndice de la lista de Ã­ndices asignados, selecciÃ³nelo y haga click en "Eliminar Ã­ndice".</Text>
+<Text id="139">Para crear un Ã­ndice que cubra todo el texto y todos los metadatos, pulse sobre "AÃ±adir todos".</Text>
+<Text id="140">El Ã­ndice predeterminado es el que se usa en la pÃ¡gina de bÃºsqueda de la colecciÃ³n y lleva la etiqueta "[Indice por omisiÃ³n]" en la lista de "Ãndices asignados". Para establecer un Ã­ndice por omisiÃ³n, selecciÃ³nelo de la lista y haga click en "Predeterminar".</Text>
+<Text id="141">Si la opciÃ³n de bÃºsqueda avanzada estÃ¡ activa (a travÃ©s de la pantalla de tipos de bÃºsqueda) los controles de indexaciÃ³n serÃ¡n diferentes. Hay una nueva fuente de pseudodatos llamada "allfields" (todos los campos) que permite buscar a travÃ©s de todos los Ã­ndices especificados al mismo tiempo. Los niveles no se asignan a un Ã­ndice en particular, sino que se aplican a todos los Ã­ndices. De esta manera los Ã­ndices y niveles se aÃ±aden por separado. "AÃ±adir todos" crea un Ã­ndice independiente para cada metadato en este modo.</Text>
+<Text id="142">El nombre de cada Ã­ndice serÃ¡ el de la fuente por omisiÃ³n. Para cambiar el nombre, seleccione un Ã­ndice, cambie sus detalles y haga click en "Reemplazar Ã­ndice".</Text>
+</Section>
+<Section name="partitionindexes">
+<Title>
+<Text id="143">Particiones</Text>
+</Title>
+<Text id="144">Los Ã­ndices se construyen sobre fuentes de metadatos o textos especÃ­ficos, por lo que el espacio de bÃºsqueda se puede controlar aÃºn mÃ¡s particionando el Ã­ndice, ya sea por idioma o por medio de un filtro determinado previamente. Esta secciÃ³n describe la forma de hacerlo. En la parte de "Secciones de diseÃ±o" haga click en "Particionar Ã­ndices".</Text>
+<Text id="145">La pantalla "Particionar Ã­ndices" tiene tres pestaÃ±as: "Definir filtros", "Asignar particiones" y "Asignar idiomas". Para saber mÃ¡s acerca de las particiones lea la secciÃ³n correspondiente a subcolecciones y subÃ­ndices en el CapÃ­tulo 2 de la GuÃ­a del Programador de Greenstone.</Text>
+<Text id="146">La pantalla de ParticiÃ³n de Ãndices sÃ³lo se activa en los modos Especialista de Sistemas Bibliotecarios y Experto (vea la secciÃ³n <Reference target="preferences"/>). Recuerde que el nÃºmero total de particiones generadas es una combinaciÃ³n de todos los Ã­ndices, filtros de subcolecciÃ³n e idiomas seleccionados. De esta manera, dos Ã­ndices con dos filtros de subcolecciÃ³n en dos idiomas producirÃ¡n ocho particiones.</Text>
+<Section name="definefilters">
+<Title>
+<Text id="147">Definir filtros</Text>
+</Title>
+<Text id="148">Los filtros le permiten agrupar en una subcolecciÃ³n todos los documentos de un Ã­ndice para los cuales un valor de metadato sigue un patrÃ³n definido.</Text>
+<Text id="149">Para crear un filtro haga click en la pestaÃ±a "Definir filtros" y escriba el nombre del nuevo filtro en el campo titulado "Nombre del filtro de la subcolecciÃ³n". A continuaciÃ³n elija un atributo del documento con el cual se va a contrastar, ya sea un elemento de metadato o el nombre del archivo en cuestiÃ³n. Ingrese una expresiÃ³n regular que se utilizarÃ¡ durante la contrastaciÃ³n. Usted puede variar libremente entre "Incluir" documentos que concuerden con el filtro o "Excluirlos". Por Ãºltimo, usted tambiÃ©n puede especificar cualquiera de los indicadores estÃ¡ndar de expresiones regulares PERL para usarlos al momento de contrastar (p. ej. "i" para concordancias que no tomen en cuenta el caso). Haga click en "AÃ±adir filtro" para aÃ±adir el filtro a la lista de "Filtros definidos para la subcolecciÃ³n".</Text>
+<Text id="150">Para quitar un filtro de la lista, selecciÃ³nelo y haga click en "Eliminar filtro".</Text>
+<Text id="151">Para modificar un filtro, selecciÃ³nelo de la lista, cambie cualquiera de los valores que aparecen en los controles de ediciÃ³n y haga click en "Reemplazar filtro" para guardar los cambios.</Text>
+</Section>
+<Section name="assignpartitions">
+<Title>
+<Text id="152">Asignar particiones</Text>
+</Title>
+<Text id="153">Una vez que haya definido el filtro de una subcolecciÃ³n, utilice la pestaÃ±a "Asignar particiones" para construir los Ã­ndices del filtro (o de un grupo de filtros). Seleccione el filtro o los filtros que desee de la lista "Filtros definidos para la subcolecciÃ³n", ingrese un nombre para la particiÃ³n en el campo "Nombre de la particiÃ³n" y haga click en "AÃ±adir particiÃ³n".</Text>
+<Text id="154">Para quitar una particiÃ³n de la lista, selecciÃ³nela y haga click en "Eliminar particiÃ³n".</Text>
+<Text id="155">Para hacer que una particiÃ³n determinada sea el valor por omisiÃ³n, selecciÃ³nela de la lista y haga click en "Predeterminar".</Text>
+</Section>
+<Section name="assignlanguages">
+<Title>
+<Text id="156">Asignar idiomas</Text>
+</Title>
+<Text id="157">Esta secciÃ³n describe la forma de limitar los Ã­ndices de bÃºsqueda a ciertos idiomas. Esto se hace generando una particiÃ³n por medio de la pestaÃ±a "Asignar idiomas" que se encuentra en la pantalla "Particionar Ã­ndices".</Text>
+<Text id="158">Para aÃ±adir un nuevo idioma use la pestaÃ±a "Asignar idiomas" a fin de construirle un Ã­ndice. Seleccione el idioma en la lista descendente "Idioma que se va a aÃ±adir" y haga click en "AÃ±adir idioma".</Text>
+<Text id="159">Para quitar un idioma, escÃ³jalo de la lista "SelecciÃ³n de idiomas" y haga click en "Eliminar idioma".</Text>
+<Text id="160">Para establecer un idioma por omisiÃ³n, selecciÃ³nelo de la lista y haga click en "Predeterminar".</Text>
+</Section>
+</Section>
+<Section name="xcollectionsearching">
+<Title>
+<Text id="161">BÃºsqueda cruzada a travÃ©s de varias colecciones</Text>
+</Title>
+<Text id="162">Greenstone puede buscar a travÃ©s de varias colecciones distintas como si fueran una sola. Esto se hace especificando una lista de otras colecciones que puedan ser buscadas junto con la actual. En la parte de "Secciones de diseÃ±o" haga click en "BÃºsqueda cruzada".</Text>
+<Text id="163">La pantalla de bÃºsqueda cruzada muestra una lista de las colecciones disponibles. La colecciÃ³n actual estÃ¡ marcada y no se puede quitar de la selecciÃ³n. Para aÃ±adir otra colecciÃ³n en la cual buscar de forma paralela, haga click en ella (o haga click en ella nuevamente para quitarla de la selecciÃ³n). Si sÃ³lo se seleccionÃ³ una colecciÃ³n, entonces no habrÃ¡ bÃºsqueda cruzada.</Text>
+<Text id="164">Si las colecciones no tienen los mismos Ã­ndices (incluyendo particiones en subcolecciones e idiomas) la bÃºsqueda cruzada no funcionarÃ¡ correctamente. El usuario Ãºnicamente serÃ¡ capaz de buscar usando Ã­ndices comunes a todas las colecciones.</Text>
+<Text id="165">Para mayor informaciÃ³n vea el CapÃ­tulo 1 de la GuÃ­a del Programador de Greenstone.</Text>
+</Section>
+<Section name="classifiers">
+<Title>
+<Text id="166">Clasificadores de exploraciÃ³n</Text>
+</Title>
+<Text id="167">Esta secciÃ³n explica la forma de asignar "clasificadores" a una colecciÃ³n, los cuales se usan para navegar y buscar en ella. En la parte de "Secciones de diseÃ±o" haga click en "Clasificadores de exploraciÃ³n".</Text>
+<Text id="168">Para aÃ±adir un clasificador, escÃ³jalo por medio de la lista descendente "Seleccione el clasificador que se va a aÃ±adir" en la parte inferior de la pantalla y haga click en "AÃ±adir clasificador". Con esto aparecerÃ¡ una ventana titulada "Argumentos de configuraciÃ³n". Las instrucciones para este cuadro de diÃ¡logo son exactamente las mismas que para los plugins (vea la secciÃ³n <Reference target="plugins"/>). Una vez que haya configurado el nuevo clasificador, Ã©ste se aÃ±adirÃ¡ al final de la lista de "Clasificadores asignados actualmente".</Text>
+<Text id="169">Para quitar un clasificador de la lista, selecciÃ³nelo y haga click en "Eliminar clasificador".</Text>
+<Text id="170">Para cambiar los argumentos de un clasificador, selecciÃ³nelo de la lista y haga click en "Configurar clasificador" o doble click en el nombre del clasificador.</Text>
+<Text id="171">El orden de los clasificadores en la barra de navegaciÃ³n de la colecciÃ³n se refleja aquÃ­. Para cambiarlo, seleccione el clasificador que desea mover y haga click en "Mover arriba" o "Mover abajo".</Text>
+<Text id="172">Para mayor informaciÃ³n sobre los clasificadores, lea el CapÃ­tulo 2 de la GuÃ­a del Programador de Greenstone: Obteniendo el mÃ¡ximo beneficio de sus documentos.</Text>
+</Section>
+<Section name="formatstatements">
+<Title>
+<Text id="173">Formatos</Text>
+</Title>
+<Text id="174">Las pÃ¡ginas Web que usted ve cuando utiliza Greenstone no han sido guardadas previamente sino que se generan âal vueloâ conforme se van necesitando. Los comandos de formato se utilizan para cambiar la apariencia de las pÃ¡ginas generadas. Afectan aspectos como el lugar donde aparecerÃ¡n los botones cuando se muestra un documento y quÃ© vÃ­nculos despliega el clasificador DateList en pantalla. Los comandos de formato no son fÃ¡ciles de desarrollar, por lo que le recomendamos que lea el CapÃ­tulo 2 de la GuÃ­a del Programador de Greenstone. La presente secciÃ³n describe los controles de los distintos formatos y la forma en que la Interfaz de Bibliotecario le da acceso a ellos. En la parte de "Secciones de diseÃ±o" haga click en "Formatos".</Text>
+<Text id="175">Se puede aplicar un comando de formato a cualquier cosa que se encuentre en la lista llamada "Elegir funciÃ³n", la cual incluye cada clasificador y una lista de funciones determinadas previamente. Cuando se selecciona una funciÃ³n existen dos tipos de controles. Algunas funciones simplemente se activan o se desactivan por medio de un recuadro. Otras requieren que se especifique una cadena de formato, para las cuales hay una lista descendente (llamada "Componente afectado") que permite seleccionar la parte de la funciÃ³n a la que se aplica la cadena (en caso necesario), un Ã¡rea de texto (llamada "cadena de formato HTML") para ingresar la cadena y una selecciÃ³n de "variables" definidas previamente. Para insertar una variable en su posiciÃ³n actual dentro de la cadena de formato, selecciÃ³nela de la lista descendente y haga click en "Insertar".</Text>
+<Text id="176">TambiÃ©n se puede especificar un formato predeterminado para un componente en particular seleccionando la funciÃ³n que estÃ¡ en blanco. Este formato se aplicarÃ¡ a todas las funciones aplicables a menos que se especifique lo contrario.</Text>
+<Text id="177">Para aÃ±adir un nuevo formato de comando llene la informaciÃ³n tal como se describe arriba y haga click en "AÃ±adir formato". El nuevo comando de formato aparecerÃ¡ en la lista de "Comandos de formato asignados actualmente". Solamente se podrÃ¡ asignar un comando de formato a cada combinaciÃ³n de funciÃ³n/componente.</Text>
+<Text id="178">Para quitar un comando de formato de la lista, selecciÃ³nelo y haga click en "Eliminar formato".</Text>
+<Text id="179">Para cambiar un comando de formato, selecciÃ³nelo de la lista, modifique sus parÃ¡metros y haga click en "Reemplazar formato".</Text>
+<Text id="180">Para mayor informaciÃ³n acerca de las variables y los componentes de las funciones lea el CapÃ­tulo 2 de la GuÃ­a del Programador de Greenstone.</Text>
+<Text id="181">Si se marca el recuadro "Permitir opciones avanzadas" se activarÃ¡n algunas opciones de formateo avanzado. La lista de funciones que se pueden formatear cambia ligeramente y mÃ¡s variables estÃ¡n disponibles para usarlas en los comandos de formato, proporcionando asÃ­ un mayor control sobre el diseÃ±o de la pÃ¡gina.</Text>
+</Section>
+<Section name="translatetext">
+<Title>
+<Text id="182">TraducciÃ³n de textos</Text>
+</Title>
+<Text id="183">Esta secciÃ³n describe la pantalla de traducciÃ³n, donde se pueden definir fragmentos de texto en un idioma especÃ­fico para partes de la interfaz de la colecciÃ³n. En la parte de "Secciones de diseÃ±o" haga click en "Traducir texto".</Text>
+<Text id="184">Primero elija una entrada de la lista de "funciones". Las cadenas de texto asociadas a esta funciÃ³n aparecerÃ¡n abajo. Utilice la lista "Idioma de la traducciÃ³n" para seleccionar el idioma al que se va a traducir y escriba el texto traducido en el Ã¡rea de texto, haciendo referencia al "fragmento de texto inicial" en caso necesario. Una vez que haya terminado haga click en "AÃ±adir traducciÃ³n".</Text>
+<Text id="185">Para quitar una traducciÃ³n existente, selecciÃ³nela de la tabla "Traducciones asignadas" y haga click en "Eliminar traducciÃ³n".</Text>
+<Text id="186">Para actualizar una traducciÃ³n, selecciÃ³nela, edÃ­tela en el Ã¡rea de texto titulada "Texto traducido" y haga click en "Reemplazar traducciÃ³n".</Text>
+</Section>
+<Section name="metadatasets">
+<Title>
+<Text id="187">Conjuntos de metadatos</Text>
+</Title>
+<Text id="188">Esta secciÃ³n describe la pantalla de revisiÃ³n del conjunto de metadatos. En la parte de "Secciones de diseÃ±o" haga click en "Conjuntos de metadatos".</Text>
+<Text id="189">Esta pantalla se usa para revisar los conjuntos de metadatos que utiliza la colecciÃ³n, asÃ­ como los elementos que estÃ¡n disponibles dentro de cada conjunto. Elija uno de la lista de "Conjuntos de Metadatos Disponibles" para ver los detalles de sus elementos.</Text>
+<Text id="190">Para usar otro conjunto de metadatos con la colecciÃ³n cargada, pulse "AÃ±adir Conjunto de Metadatos", y seleccione el archivo de conjunto de metadatos (.mds) para el nuevo conjunto de metadatos.</Text>
+<Text id="191">La edicion de conjuntos de metadatos se hace con el Editor Greenstone para Conjuntos de Metadatos (GEMS). Pulsando el botÃ³n "Editar Conjunto de metadatos" obtendrÃ¡ informaciÃ³n sobre cÃ³mo utilizar GEMS.</Text>
+<Text id="192">Si ya no necesita mÃ¡s un conjunto de metadatos, selecciÃ³nelo y pulse "Borrar Conjunto de Metadatos" para eliminarlo. Si habÃ­a asignado metadatos a cualquier elemento del conjunto borrado, se le preguntarÃ¡ cÃ³mo actuar con estos metadatos cuando vuelva a abrir la colecciÃ³n.</Text>
+</Section>
+</Section>
+<Section name="producingthecollection">
+<Title>
+<Text id="193"> Produciendo una colecciÃ³n </Text>
+</Title>
+<Text id="194">Una vez que se han reunido los documentos para la colecciÃ³n, que se han enriquecido con metadatos y que se ha diseÃ±ado la forma en que la colecciÃ³n aparecerÃ¡, usted ya puede empezar a producir la colecciÃ³n. Esta secciÃ³n le explica cÃ³mo.</Text>
+<Section name="thecreateview">
+<Title>
+<Text id="195">La pantalla de creaciÃ³n de la colecciÃ³n</Text>
+</Title>
+<Text id="196">La pantalla "Crear" se utiliza para producir la colecciÃ³n ejecutando los guiones de los programas Greenstone con base en la informaciÃ³n que usted ha proporcionado. Al hacer click en el botÃ³n "Crear colecciÃ³n" se inicia el proceso de construcciÃ³n de la colecciÃ³n. El tiempo que se lleve dependerÃ¡ del tamaÃ±o de la colecciÃ³n y del nÃºmero de Ã­ndices que se estÃ©n creando (para colecciones de gran tamaÃ±o pueden ser horas). Una barra de progreso indica cuÃ¡nto se ha completado del proceso. Para cancelar el proceso en cualquier momento haga click en el botÃ³n "Cancelar la construcciÃ³n".</Text>
+<Text id="197">Una vez que la colecciÃ³n se ha construido exitosamente, al seleccionar "Vista previa de la colecciÃ³n" se iniciarÃ¡ un navegador de web que mostrarÃ¡ la pÃ¡gina inicial de la colecciÃ³n.</Text>
+<Text id="198">En modo Experto, puede usar las entradas del "Registro de mensajes" a la izquierda, para revisar intentos previos de construcciÃ³n de la colecciÃ³n, hayan tenido Ã©xito o no. Seleccione el registro que desee haciendo click en la fecha correspondiente en la lista "Historial de registro".</Text>
+</Section>
+<Section name="buildsettings">
+<Title>
+<Text id="199">Controles de importaciÃ³n y construcciÃ³n</Text>
+</Title>
+<Text id="200">Esta secciÃ³n explica la forma de tener acceso a los diferentes controles de importaciÃ³n y construcciÃ³n. Para mayor informaciÃ³n lea el CapÃ­tulo 1 de la GuÃ­a del Programador de Greenstone: Comprendiendo el proceso de creaciÃ³n de una colecciÃ³n.</Text>
+<Text id="201">La forma de controlar los diferentes ajustes es similar a la de la ventana "Argumentos de configuraciÃ³n" que se describe en la secciÃ³n de <Reference target="plugins"/>. Algunos campos requerirÃ¡n argumentos numÃ©ricos y usted puede escribirlos directamente en el campo o usar las flechas que se encuentran a un lado para aumentar o disminuir el nÃºmero (en algunos casos la interfaz limita el rango). Otros se activan (y desactivan) haciendo click en los recuadros correspondientes.</Text>
+</Section>
+</Section>
+<Section name="miscellaneous">
+<Title>
+<Text id="202">MiscelÃ¡nea</Text>
+</Title>
+<Text id="203">Esta secciÃ³n describe funciones y caracterÃ­sticas de la Interfaz de Bibliotecario que no estÃ¡n asociadas a ninguna pantalla en particular.</Text>
+<Section name="preferences">
+<Title>
+<Text id="204">Preferencias</Text>
+</Title>
+<Text id="205">Esta secciÃ³n explica el cuadro de preferencias, al cual se tiene acceso por medio de la opciÃ³n "Preferencias" en el menÃº "Archivo".</Text>
+<Text id="206">La primera opciÃ³n "General" es un campo de texto para introducir su direcciÃ³n de correo electrÃ³nico. SerÃ¡ usada para los elementos de metadatos "creador" y "administrador" de la colecciÃ³n. La siguiente opciÃ³n es un menÃº desplegable de los lenguajes en los cuales se puede presentar la Interfaz de Bibliotecario. Si usted cambia el diccionario eligiendo un idioma de la lista, entonces deberÃ¡ reinicar la Interfaz de Bibliotecario para poder cargar las cadenas de texto en el nuevo idioma.</Text>
+<Text id="207">Si se marcÃ³ el recuadro "Ver metadatos extraÃ­dos", los diferentes controles que trabajan con metadatos siempre mostrarÃ¡n todos los metadatos que se han extraÃ­do automÃ¡ticamente de los documentos. Al quitar la marca del recuadro se ocultarÃ¡n estos metadatos (aunque la opciÃ³n seguirÃ¡ disponible durante el diseÃ±o de la colecciÃ³n y en la colecciÃ³n final). Si se marcÃ³ el recuadro "Mostrar el tamaÃ±o de los archivos" el tamaÃ±o del archivo aparecerÃ¡ junto a cada uno en las estructuras de archivos del Ã¡rea de trabajo y de la colecciÃ³n que se encuentran en las pantallas "Reunir" y "Enriquecer".</Text>
+<Text id="208">La pantalla de "Modo" se utiliza para controlar el nivel de detalle dentro de la interfaz. En su nivel mÃ¡s bÃ¡sico, "Asistente de Biblioteca", la pantalla de diseÃ±o estÃ¡ inhabilitada, los argumentos que requieren expresiones regulares estÃ¡n ocultos y el proceso de construcciÃ³n de la colecciÃ³n registra un mÃ­nimo de eventos. En comparaciÃ³n, el nivel mÃ¡s alto, "Avanzado", le da acceso a todas las funciones de diseÃ±o, incluyendo la posiciÃ³n de los plugins y argumentos con expresiones regulares, ademÃ¡s de permitir un registro completo del proceso de construcciÃ³n de la colecciÃ³n. Para cambiar o revisar los modos, haga click en el botÃ³n que se encuentra junto al modo en el que usted estÃ© interesado. De esta manera usted puede revisar rÃ¡pidamente el modo en el que estÃ¡ viendo la barra de tÃ­tulo de la Interfaz de Bibliotecario.</Text>
+<Text id="209">La Interfaz de Bibliotecario puede soportar diferentes flujos de trabajo determinando cuÃ¡les de las pestaÃ±as de las diferentes pantallas estarÃ¡n visibles. Utilice la pestaÃ±a "Flujo de trabajo" para determinar quÃ© pantallas estarÃ¡n disponibles marcando los recuadros que estÃ¡n junto al nombre de cada una de ellas. De forma alternativa utilice la lista descendente que se encuentra en la parte inferior para seleccionar las configuraciones predeterminadas. Al cerrar el cuadro de preferencias se aplicarÃ¡n los ajustes. Estos se guardan junto con la colecciÃ³n, no en el archivo de configuraciÃ³n de la Interfaz de Bibliotecario.</Text>
+<Text id="210">La pestaÃ±a de "ConexiÃ³n" le permite cambiar la ruta que lo conecta al servidor local de la biblioteca digital Greenstone, el cual se utiliza durante la presentaciÃ³n preliminar de la colecciÃ³n. TambiÃ©n le permite establecer la informaciÃ³n de proxy para conectarse a Internet (ejemplo: al descargar archivos; ver la secciÃ³n <Reference target="downloadingfiles"/> para mÃ¡s detalles). Marque la casilla para permitir la conexiÃ³n por proxy y suministre los detalles de la direcciÃ³n y el nÃºmero de puerto del host que sirve de proxy. La conexiÃ³n con el proxy se establece cuando cierre el diÃ¡logo de Preferencias.</Text>
+<Text id="211">En el curso de una sesiÃ³n la Interfaz de Bibliotecario podrÃ¡ enviarle mensajes de advertencia que le avisarÃ¡n sobre las posibles consecuencias no previstas de una acciÃ³n. Usted puede desactivar los mensajes marcando el recuadro "No mostrar este mensaje otra vez". Para reactivarlos utilice la pestaÃ±a "Mensajes de advertencia" y marque los recuadros de los mensajes que desea volver a ver.</Text>
+</Section>
+<Section name="fileassociations">
+<Title>
+<Text id="212">AsociaciÃ³n de archivos</Text>
+</Title>
+<Text id="213">La Interfaz de Bibliotecario utiliza diferentes programas de aplicaciÃ³n para abrir tipos particulares de archivos. Para modificar la asociaciÃ³n de archivos abra el menÃº "Archivo" y haga click en "AsociaciÃ³n de archivos".</Text>
+<Text id="214">Para establecer una asociaciÃ³n seleccione la extensiÃ³n del archivo de la lista descendente o escriba una nueva extensiÃ³n (no incluya "."). A continuaciÃ³n escriba en el campo correspondiente el comando que da inicio a la aplicaciÃ³n deseada o elija la aplicaciÃ³n en el cuadro "Explorar". "%1" se puede utilizar en el comando de inicio para insertar el nombre del archivo que se estÃ¡ abriendo. Una vez que se han llenado estos campos, el botÃ³n "AÃ±adir" se activarÃ¡, con lo que ya se puede hacer click en Ã©l para establecer la asociaciÃ³n.</Text>
+<Text id="215">Para editar una asociaciÃ³n, seleccione una extensiÃ³n de archivo existente. El comando asociado aparecerÃ¡ en el campo correspondiente a comando de inicio. EdÃ­telo y a continuaciÃ³n haga click en "Reemplazar".</Text>
+<Text id="216">Para eliminar una asociaciÃ³n, seleccione la extensiÃ³n del archivo y haga click en "Eliminar". La extensiÃ³n del archivo permanecerÃ¡ en una lista llamada "Para archivos que terminan en...".</Text>
+<Text id="217">Las asociaciones de archivos se guardan en la carpeta principal de la Interfaz de Bibliotecario en un archivo llamado "associations.xml".</Text>
+</Section>
+<Section name="exportingcollections">
+<Title>
+<Text id="218">Exportando colecciones a un CD/DVD</Text>
+</Title>
+<Text id="219">Greenstone puede exportar una o mÃ¡s colecciones a un CD/DVD para Windows que se podrÃ¡ instalar automÃ¡ticamente. Para ello es indispensable que el paquete "Exportar a un CD-ROM" estÃ© instalado. Esto no se incluye por omisiÃ³n, por lo que serÃ¡ necesario modificar la instalaciÃ³n para incluirlo.</Text>
+<Text id="220">Para exportar una colecciÃ³n abra el menÃº "Archivo" y seleccione la opciÃ³n "Exportar a un CD-ROM/DVD...". Con esto aparecerÃ¡ una lista de colecciones Greenstone. Haga click en una para ver su descripciÃ³n. Marque los recuadros de las colecciones que desea exportar. Usted tambiÃ©n puede ingresar el nombre de CD/DVD en el cuadro correspondiente, el cual aparecerÃ¡ en el menÃº de Inicio una vez que el CD/DVD se haya instalado. A continuaciÃ³n haga click en "Exportar". El proceso incluye la copia de varios archivos y requerirÃ¡ de unos cuantos minutos.</Text>
+<Text id="221">Una vez que haya terminado Greenstone mostrarÃ¡ el nombre de una carpeta en la que se encontrarÃ¡n las colecciones que se han exportado. Utilice una quemadora de CD/DVDs para copiar sus contenidos en un CD/DVD en blanco.</Text>
+</Section>
+</Section>
+</Document>
Index: /tags/greenstone-3_02-distribution/gli/help/es/help_index.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/help_index.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/help_index.xml	(revision 13928)
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Document><Section name="introduction"><Title>IntroducciÃ³n</Title><Section name="ofmiceandmenus"><Title>De menÃºs y ratones</Title></Section><Section name="howtoavoidthisdocument"><Title>Temas de ayuda</Title></Section></Section><Section name="startingoff"><Title>Para empezar</Title><Section name="creatingacollection"><Title>Creando una nueva colecciÃ³n</Title></Section><Section name="savingacollection"><Title>Guardar la colecciÃ³n</Title></Section><Section name="openingacollection"><Title>Abriendo una colecciÃ³n existente</Title></Section><Section name="deletingcollections"><Title>Borrando colecciones</Title></Section></Section><Section name="downloadingfiles"><Title>Descargando archivos de Internet</Title><Section name="themirrorview"><Title>La vista en Bajar</Title></Section></Section><Section name="collectingfiles"><Title>Reuniendo archivos para su colecciÃ³n</Title><Section name="thegatherview"><Title>La pantalla de selecciÃ³n de documentos</Title></Section><Section name="creatingfolders"><Title>Creando carpetas</Title></Section><Section name="addingfiles"><Title>AÃ±adiendo archivos</Title></Section><Section name="removingfiles"><Title>Eliminando archivos</Title></Section><Section name="filteringthetree"><Title>Filtrando la estructura de directorios y subdirectorios</Title></Section></Section><Section name="enrichingacollection"><Title>Enriqueciendo la colecciÃ³n con metadatos</Title><Section name="theenrichview"><Title>La pantalla de asignaciÃ³n de metadatos</Title></Section><Section name="selectingmetadatasets"><Title>Seleccionando conjuntos de metadatos</Title></Section><Section name="appendingmetadata"><Title>Agregando nuevos metadatos</Title></Section><Section name="addingpreviouslydefinedmetadata"><Title>AÃ±adiendo Metadatos Previamente Definidos</Title></Section><Section name="updatingmetadata"><Title>Editar o Borrar Metadatos</Title></Section><Section name="reviewingmetadata"><Title>Revisando los metadatos asignados</Title></Section><Section name="importingpreviouslyassignedmetadata"><Title>Importando metadatos previamente asignados</Title></Section></Section><Section name="designingacollection"><Title>DiseÃ±ando la apariencia de su colecciÃ³n</Title><Section name="thedesignview"><Title>La pantalla de diseÃ±o</Title></Section><Section name="generalsettings"><Title>General</Title></Section><Section name="plugins"><Title>Plugins</Title></Section><Section name="searchtypes"><Title>Tipos de bÃºsqueda</Title></Section><Section name="searchindexes"><Title>Ãndices de bÃºsqueda</Title></Section><Section name="partitionindexes"><Title>Particiones</Title><Section name="definefilters"><Title>Definir filtros</Title></Section><Section name="assignpartitions"><Title>Asignar particiones</Title></Section><Section name="assignlanguages"><Title>Asignar idiomas</Title></Section></Section><Section name="xcollectionsearching"><Title>BÃºsqueda cruzada a travÃ©s de varias colecciones</Title></Section><Section name="classifiers"><Title>Clasificadores de exploraciÃ³n</Title></Section><Section name="formatstatements"><Title>Formatos</Title></Section><Section name="translatetext"><Title>TraducciÃ³n de textos</Title></Section><Section name="metadatasets"><Title>Conjuntos de metadatos</Title></Section></Section><Section name="producingthecollection"><Title> Produciendo una colecciÃ³n </Title><Section name="thecreateview"><Title>La pantalla de creaciÃ³n de la colecciÃ³n</Title></Section><Section name="buildsettings"><Title>Controles de importaciÃ³n y construcciÃ³n</Title></Section></Section><Section name="miscellaneous"><Title>MiscelÃ¡nea</Title><Section name="preferences"><Title>Preferencias</Title></Section><Section name="fileassociations"><Title>AsociaciÃ³n de archivos</Title></Section><Section name="exportingcollections"><Title>Exportando colecciones a un CD/DVD</Title></Section></Section></Document>
Index: /tags/greenstone-3_02-distribution/gli/help/es/howtoavoidthisdocument.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/howtoavoidthisdocument.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/howtoavoidthisdocument.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="howtoavoidthisdocument"><font face="Verdana" size="5"><strong>1.2: Temas de ayuda</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>&iexcl;Usted no necesita leer todo el texto de ayuda! S&oacute;lo lea lo suficiente para saber c&oacute;mo obtener ayuda cuando la necesite.</p>
+<p>El comando del men&uacute; "Ayuda" indica los que ser&iacute;an los temas de ayuda m&aacute;s apropiados por medio de un peque&ntilde;o icono en forma de libro.</p>
+<p>Para muchos controles si se coloca el mouse encima de ellos aparecer&aacute; un "cuadro de sugerencias" en el cual se explica su funci&oacute;n.</p>
+<p>Antes de usar la Interfaz de Bibliotecario lea primero la documentaci&oacute;n de Greenstone.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/importingpreviouslyassignedmetadata.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/importingpreviouslyassignedmetadata.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/importingpreviouslyassignedmetadata.htm	(revision 13928)
@@ -0,0 +1,19 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="importingpreviouslyassignedmetadata"><font face="Verdana" size="5"><strong>5.7: Importando metadatos previamente asignados</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Esta secci&oacute;n describe c&oacute;mo importar metadtos previamente asignados, es decir, metadatos asignados a los documentos antes de que fuesen a&ntilde;adidos a la colecci&oacute;n.</p>
+<p>Si se han asignado previamente metadatos en una forma reconocible por la Interfaz de Bibliotecario, por ejemplo, cuando se seleccionan documentos de una colecci&oacute;n Greenstone existente, entonces &eacute;stos se importar&aacute;n autom&aacute;ticamente cuando usted a&ntilde;ada el archivo. Para poder hacer esto los metadatos deben mapearse hacia el conjunto de metadatos disponible en la colecci&oacute;n.</p>
+<p>La Interfaz de Bibliotecario enviar&aacute; un mensaje solicitando la informaci&oacute;n necesaria. El mensaje incluir&aacute; breves instrucciones y a continuaci&oacute;n mostrar&aacute; el nombre del elemento de metadato que se est&aacute; importando, tal como aparece en el archivo fuente. Este campo no se podr&aacute; editar o cambiar. A continuaci&oacute;n elija el conjunto de metadatos hacia el que el nuevo elemento deber&aacute; mapearse y el correspondiente elemento de metadato en ese conjunto. El sistema selecciona autom&aacute;ticamente la correspondencia m&aacute;s cercana en t&eacute;rminos de conjunto y elemento para el nuevo metadato.</p>
+<p>Despu&eacute;s de revisar el mapeo, usted puede elegir "A&ntilde;adir" para a&ntilde;adir el nuevo elemento de metadato al conjunto de metadatos que se haya seleccionado. (Esto s&oacute;lo es posible si no hay un elemento del mismo nombre dentro del conjunto seleccionado.) "Combinar" mapea el nuevo elemento hacia el que el usuario haya elegido. Finalmente, "Ignorar" no importa ning&uacute;n metadato con este nombre de elemento. Una vez que usted haya especificado la forma de importar una parte del metadato, la informaci&oacute;n del proceso se conserva durante todo el tiempo de vida de la colecci&oacute;n.</p>
+<p>Para mayor informaci&oacute;n sobre los archivos metadata.xml que Greenstone utiliza para guardar metadatos, vea el Cap&iacute;tulo 2 de la Gu&iacute;a del Programador de Greenstone: Obteniendo el m&aacute;ximo beneficio de sus documentos.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/introduction.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/introduction.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/introduction.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="introduction"><font face="Verdana" size="5"><strong>1: Introducci&oacute;n</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>La Interfaz de Bibliotecario de Greenstone es una herramienta que permite reunir y marcar documentos para luego crear colecciones digitales con ellos, d&aacute;ndole f&aacute;cil acceso a todas las funciones de los programas de software de la Biblioteca Digital Greenstone desde una interfaz gr&aacute;fica de usuario con la que s&oacute;lo tiene que apuntar y hacer click.</p>
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/metadatasets.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/metadatasets.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/metadatasets.htm	(revision 13928)
@@ -0,0 +1,19 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="metadatasets"><font face="Verdana" size="5"><strong>6.11: Conjuntos de metadatos</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Esta secci&oacute;n describe la pantalla de revisi&oacute;n del conjunto de metadatos. En la parte de "Secciones de dise&ntilde;o" haga click en "Conjuntos de metadatos".</p>
+<p>Esta pantalla se usa para revisar los conjuntos de metadatos que utiliza la colecci&oacute;n, as&iacute; como los elementos que est&aacute;n disponibles dentro de cada conjunto. Elija uno de la lista de "Conjuntos de Metadatos Disponibles" para ver los detalles de sus elementos.</p>
+<p>Para usar otro conjunto de metadatos con la colecci&oacute;n cargada, pulse "A&ntilde;adir Conjunto de Metadatos", y seleccione el archivo de conjunto de metadatos (.mds) para el nuevo conjunto de metadatos.</p>
+<p>La edicion de conjuntos de metadatos se hace con el Editor Greenstone para Conjuntos de Metadatos (GEMS). Pulsando el bot&oacute;n "Editar Conjunto de metadatos" obtendr&aacute; informaci&oacute;n sobre c&oacute;mo utilizar GEMS.</p>
+<p>Si ya no necesita m&aacute;s un conjunto de metadatos, selecci&oacute;nelo y pulse "Borrar Conjunto de Metadatos" para eliminarlo. Si hab&iacute;a asignado metadatos a cualquier elemento del conjunto borrado, se le preguntar&aacute; c&oacute;mo actuar con estos metadatos cuando vuelva a abrir la colecci&oacute;n.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/miscellaneous.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/miscellaneous.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/miscellaneous.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="miscellaneous"><font face="Verdana" size="5"><strong>8: Miscel&aacute;nea</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Esta secci&oacute;n describe funciones y caracter&iacute;sticas de la Interfaz de Bibliotecario que no est&aacute;n asociadas a ninguna pantalla en particular.</p>
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/ofmiceandmenus.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/ofmiceandmenus.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/ofmiceandmenus.htm	(revision 13928)
@@ -0,0 +1,22 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="ofmiceandmenus"><font face="Verdana" size="5"><strong>1.1: De men&uacute;s y ratones</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Esta secci&oacute;n proporciona informaci&oacute;n b&aacute;sica para poder trabajar con la Interfaz de Bibliotecario. Si est&aacute; familiarizado con programas como Internet Explorer o Microsoft Office y est&aacute; acostumbrado a usar el mouse, entonces pase a la secci&oacute;n <a href="howtoavoidthisdocument.htm">Temas de ayuda</a>.</p>
+<p>La Interfaz de Bibliotecario sigue las convenciones de Microsoft y se apoya en el conocimiento que com&uacute;nmente se tiene de Windows.</p>
+<p>Cualquier parte de la pantalla con la que usted interact&uacute;e, como un bot&oacute;n o un campo de texto, se llama "control". En todo momento un bot&oacute;n o campo de texto llamado "control activo" aparecer&aacute; resaltado y responder&aacute; a las instrucciones del teclado. Asimismo, varios controles le permiten seleccionar las partes que est&eacute;n resaltadas en azul marino. Algunos controles tambi&eacute;n pueden aparecer sombreados para indicar que no est&aacute;n disponibles.</p>
+<p>Usted puede mover y hacer click con el bot&oacute;n izquierdo o derecho del mouse de la forma acostumbrada. Muchos componentes tambi&eacute;n se pueden "arrastrar" haciendo click en ellos y sosteniendo el bot&oacute;n izquierdo del mouse, para luego moverlos y "colocarlos" en alg&uacute;n otro lugar soltando el bot&oacute;n. Normalmente el lugar de destino cambia de apariencia cuando un componente pasa sobre &eacute;l.</p>
+<p>Usted puede usar el teclado para escribir en los campos de texto. Muchos controles tambi&eacute;n se pueden ejecutar por medio del teclado, lo que se indica por medio de corchetes -- por ejemplo la tecla de tabulaci&oacute;n [Tab] cambia el control activo. El signo de m&aacute;s (+) indica que otras teclas deben oprimirse al mismo tiempo.</p>
+<p>Para tener acceso a un men&uacute;, oprima el bot&oacute;n [ALT] y presione la letra correspondiente (la cual aparece subrayada). Por ejemplo, para desplegar el men&uacute; "Archivo" oprima [ALT] + [A]. Para elegir un comando presione la tecla correspondiente. Por ejemplo, en el men&uacute; "Archivo" presione [G] para "Guardar" la colecci&oacute;n.</p>
+<p>Los botones, al igual que los men&uacute;s, tienen una letra subrayada. Para seleccionar un bot&oacute;n oprima la tecla [ALT] y la letra que est&aacute; subrayada al mismo tiempo.</p>
+<p>Salga de la Interfaz de Bibliotecario eligiendo "Salir" en el men&uacute; "Archivo". Su colecci&oacute;n se guardar&aacute; primero.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/openingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/openingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/openingacollection.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="openingacollection"><font face="Verdana" size="5"><strong>2.3: Abriendo una colecci&oacute;n existente</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Para abrir una colecci&oacute;n existente elija la opci&oacute;n "Abrir" en el men&uacute; "Archivo". Con esto aparecer&aacute; una lista de sus colecciones Greenstone. Seleccione una para ver su descripci&oacute;n y haga click en "Abrir" para cargarla. Si busca una colecci&oacute;n que resida fuera de la carpeta de "colecciones" de Greenstone, entonces haga click en "Explorar" para que aparezca un cuadro de di&aacute;logo que le permita buscar en el sistema de archivos.</p>
+<p>En caso de que m&aacute;s de una Interfaz de Bibliotecario de Greenstone est&eacute; corriendo al mismo tiempo, los directorios pertinentes se "bloquean" para evitar interferencias. Al abrir una colecci&oacute;n se crea un peque&ntilde;o archivo de bloqueo temporal en la carpeta. Antes de abrir una colecci&oacute;n la Interfaz de Bibliotecario revisa que no haya un archivo de bloqueo en ella. Se puede saber si la colecci&oacute;n est&aacute; bloqueada por el color de su icono: verde para una colecci&oacute;n normal, rojo para una colecci&oacute;n bloqueada. Sin embargo, cuando se sale prematuramente de la Interfaz de Bibliotecario el archivo de bloqueo a veces permanece en la carpeta. Cuando posteriormente se abre esta colecci&oacute;n, la Biblioteca Digital le pregunta si quiere tomar el control. Por favor, nunca le quite el control de una colecci&oacute;n a alguien que este trabajando en ese momento con ella.</p>
+<p>Cuando usted abra una colecci&oacute;n que no haya sido creada por medio de la Interfaz de Bibliotecario de Greenstone se le pedir&aacute; que seleccione uno o m&aacute;s conjuntos de metadatos. Si no selecciona ninguno, entonces los metadatos existentes se ignorar&aacute;n. De otra manera los metadatos se importar&aacute;n tal como son cuando usted arrastre los archivos. El proceso se describe en el documento llamado <a href="importingpreviouslyassignedmetadata.htm">Importando metadatos previamente asignados</a>.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/partitionindexes.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/partitionindexes.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/partitionindexes.htm	(revision 13928)
@@ -0,0 +1,20 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="partitionindexes"><font face="Verdana" size="5"><strong>6.6: Particiones</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Los &iacute;ndices se construyen sobre fuentes de metadatos o textos espec&iacute;ficos, por lo que el espacio de b&uacute;squeda se puede controlar a&uacute;n m&aacute;s particionando el &iacute;ndice, ya sea por idioma o por medio de un filtro determinado previamente. Esta secci&oacute;n describe la forma de hacerlo. En la parte de "Secciones de dise&ntilde;o" haga click en "Particionar &iacute;ndices".</p>
+<p>La pantalla "Particionar &iacute;ndices" tiene tres pesta&ntilde;as: "Definir filtros", "Asignar particiones" y "Asignar idiomas". Para saber m&aacute;s acerca de las particiones lea la secci&oacute;n correspondiente a subcolecciones y sub&iacute;ndices en el Cap&iacute;tulo 2 de la Gu&iacute;a del Programador de Greenstone.</p>
+<p>La pantalla de Partici&oacute;n de &Iacute;ndices s&oacute;lo se activa en los modos Especialista de Sistemas Bibliotecarios y Experto (vea la secci&oacute;n <a href="preferences.htm">Preferencias</a>). Recuerde que el n&uacute;mero total de particiones generadas es una combinaci&oacute;n de todos los &iacute;ndices, filtros de subcolecci&oacute;n e idiomas seleccionados. De esta manera, dos &iacute;ndices con dos filtros de subcolecci&oacute;n en dos idiomas producir&aacute;n ocho particiones.</p>
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/plugins.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/plugins.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/plugins.htm	(revision 13928)
@@ -0,0 +1,21 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="plugins"><font face="Verdana" size="5"><strong>6.3: Plugins</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Esta secci&oacute;n describe la forma de configurar los plugins que la colecci&oacute;n utiliza. Explica el modo de especificar los plugins que se utilizar&aacute;n, los par&aacute;metros que emplear&aacute;n y el orden en el que se aplicar&aacute;n. En la parte de "Secciones de dise&ntilde;o" haga click en "Plugins de documento".</p>
+<p>Para a&ntilde;adir un plugin, esc&oacute;jalo de la lista "Seleccione el plugin que se va a a&ntilde;adir" que se encuentra en la parte inferior de la pantalla y haga click en "A&ntilde;adir plugin". Aparecer&aacute; una ventana titulada "Argumentos de configuraci&oacute;n", la cual se explica m&aacute;s adelante. Una vez que usted haya configurado el nuevo plugin, este se a&ntilde;adir&aacute; al final de la lista de "Plugins asignados actualmente". Note que, excepto para UnknownPlug, cada plugin s&oacute;lo puede aparecer una vez en la lista.</p>
+<p>Para quitar un plugin de la lista, selecci&oacute;nelo y haga click en "Eliminar plugin".</p>
+<p>Los plugins se configuran por medio de argumentos. Para modificarlos, seleccione un plugin de la lista y haga click en "Configurar plugin" (o doble click en el plugin). Aparece un di&aacute;logo "Configurando Argumentos" con varios controles para especificar argumentos.</p>
+<p>Existen diferentes tipos de controles. Algunos son recuadros y al hacer click en ellos se a&ntilde;ade la opci&oacute;n correspondiente al plugin. Otros son cadenas de texto con un recuadro y un campo de texto. Haga click en el cuadro para habilitarlo y escriba el argumento (expresi&oacute;n regular, ruta de archivo, etc.). Otros son men&uacute;s descendentes desde los que se puede seleccionar un conjunto dado de valores. Para saber lo que hace un argumento, coloque el cursor del mouse encima de su nombre y la descripci&oacute;n aparecer&aacute;.</p>
+<p>Una vez que usted haya cambiado la configuraci&oacute;n, haga click en "Aceptar" para guardar los cambios y cerrar el cuadro de di&aacute;logo o en "Cancelar" para cerrar el cuadro de di&aacute;logo sin cambiar ning&uacute;n argumento.</p>
+<p>Los plugins de la lista se ejecutan en orden y en ocasiones &eacute;ste es importante. El orden de los plugins s&oacute;lo se puede cambiar en los modos Especialista de Sistemas Bibliotecarios y Experto (vea la secci&oacute;n <a href="preferences.htm">Preferencias</a>).</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/preferences.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/preferences.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/preferences.htm	(revision 13928)
@@ -0,0 +1,21 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="preferences"><font face="Verdana" size="5"><strong>8.1: Preferencias</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Esta secci&oacute;n explica el cuadro de preferencias, al cual se tiene acceso por medio de la opci&oacute;n "Preferencias" en el men&uacute; "Archivo".</p>
+<p>La primera opci&oacute;n "General" es un campo de texto para introducir su direcci&oacute;n de correo electr&oacute;nico. Ser&aacute; usada para los elementos de metadatos "creador" y "administrador" de la colecci&oacute;n. La siguiente opci&oacute;n es un men&uacute; desplegable de los lenguajes en los cuales se puede presentar la Interfaz de Bibliotecario. Si usted cambia el diccionario eligiendo un idioma de la lista, entonces deber&aacute; reinicar la Interfaz de Bibliotecario para poder cargar las cadenas de texto en el nuevo idioma.</p>
+<p>Si se marc&oacute; el recuadro "Ver metadatos extra&iacute;dos", los diferentes controles que trabajan con metadatos siempre mostrar&aacute;n todos los metadatos que se han extra&iacute;do autom&aacute;ticamente de los documentos. Al quitar la marca del recuadro se ocultar&aacute;n estos metadatos (aunque la opci&oacute;n seguir&aacute; disponible durante el dise&ntilde;o de la colecci&oacute;n y en la colecci&oacute;n final). Si se marc&oacute; el recuadro "Mostrar el tama&ntilde;o de los archivos" el tama&ntilde;o del archivo aparecer&aacute; junto a cada uno en las estructuras de archivos del &aacute;rea de trabajo y de la colecci&oacute;n que se encuentran en las pantallas "Reunir" y "Enriquecer".</p>
+<p>La pantalla de "Modo" se utiliza para controlar el nivel de detalle dentro de la interfaz. En su nivel m&aacute;s b&aacute;sico, "Asistente de Biblioteca", la pantalla de dise&ntilde;o est&aacute; inhabilitada, los argumentos que requieren expresiones regulares est&aacute;n ocultos y el proceso de construcci&oacute;n de la colecci&oacute;n registra un m&iacute;nimo de eventos. En comparaci&oacute;n, el nivel m&aacute;s alto, "Avanzado", le da acceso a todas las funciones de dise&ntilde;o, incluyendo la posici&oacute;n de los plugins y argumentos con expresiones regulares, adem&aacute;s de permitir un registro completo del proceso de construcci&oacute;n de la colecci&oacute;n. Para cambiar o revisar los modos, haga click en el bot&oacute;n que se encuentra junto al modo en el que usted est&eacute; interesado. De esta manera usted puede revisar r&aacute;pidamente el modo en el que est&aacute; viendo la barra de t&iacute;tulo de la Interfaz de Bibliotecario.</p>
+<p>La Interfaz de Bibliotecario puede soportar diferentes flujos de trabajo determinando cu&aacute;les de las pesta&ntilde;as de las diferentes pantallas estar&aacute;n visibles. Utilice la pesta&ntilde;a "Flujo de trabajo" para determinar qu&eacute; pantallas estar&aacute;n disponibles marcando los recuadros que est&aacute;n junto al nombre de cada una de ellas. De forma alternativa utilice la lista descendente que se encuentra en la parte inferior para seleccionar las configuraciones predeterminadas. Al cerrar el cuadro de preferencias se aplicar&aacute;n los ajustes. Estos se guardan junto con la colecci&oacute;n, no en el archivo de configuraci&oacute;n de la Interfaz de Bibliotecario.</p>
+<p>La pesta&ntilde;a de "Conexi&oacute;n" le permite cambiar la ruta que lo conecta al servidor local de la biblioteca digital Greenstone, el cual se utiliza durante la presentaci&oacute;n preliminar de la colecci&oacute;n. Tambi&eacute;n le permite establecer la informaci&oacute;n de proxy para conectarse a Internet (ejemplo: al descargar archivos; ver la secci&oacute;n <a href="downloadingfiles.htm">Descargando archivos de Internet</a> para m&aacute;s detalles). Marque la casilla para permitir la conexi&oacute;n por proxy y suministre los detalles de la direcci&oacute;n y el n&uacute;mero de puerto del host que sirve de proxy. La conexi&oacute;n con el proxy se establece cuando cierre el di&aacute;logo de Preferencias.</p>
+<p>En el curso de una sesi&oacute;n la Interfaz de Bibliotecario podr&aacute; enviarle mensajes de advertencia que le avisar&aacute;n sobre las posibles consecuencias no previstas de una acci&oacute;n. Usted puede desactivar los mensajes marcando el recuadro "No mostrar este mensaje otra vez". Para reactivarlos utilice la pesta&ntilde;a "Mensajes de advertencia" y marque los recuadros de los mensajes que desea volver a ver.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/producingthecollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/producingthecollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/producingthecollection.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="producingthecollection"><font face="Verdana" size="5"><strong>7:  Produciendo una colecci&oacute;n </strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Una vez que se han reunido los documentos para la colecci&oacute;n, que se han enriquecido con metadatos y que se ha dise&ntilde;ado la forma en que la colecci&oacute;n aparecer&aacute;, usted ya puede empezar a producir la colecci&oacute;n. Esta secci&oacute;n le explica c&oacute;mo.</p>
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/removingfiles.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/removingfiles.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/removingfiles.htm	(revision 13928)
@@ -0,0 +1,16 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="removingfiles"><font face="Verdana" size="5"><strong>4.4: Eliminando archivos</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Existen varios m&eacute;todos para eliminar archivos y carpetas. Primero se deben indicar los elementos que se desea eliminar seleccionando los archivos y carpetas tal como se describe en la secci&oacute;n de <a href="thegatherview.htm">La pantalla de selecci&oacute;n de documentos</a>.</p>
+<p>Una vez que se han seleccionado los archivos, haga click en el bot&oacute;n "Eliminar" o presione la tecla [Del], [Supr] o [Suprimir], dependiendo del teclado de su computadora, o arr&aacute;strelos desde la colecci&oacute;n hasta el bot&oacute;n "Eliminar" y su&eacute;ltelos ah&iacute;.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/reviewingmetadata.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/reviewingmetadata.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/reviewingmetadata.htm	(revision 13928)
@@ -0,0 +1,20 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="reviewingmetadata"><font face="Verdana" size="5"><strong>5.6: Revisando los metadatos asignados</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>En ocasiones es necesario ver los metadatos asignados a varios o a todos los archivos al mismo tiempo, por ejemplo, para determinar la forma en que quedan muchos archivos para trabajar en ellos o para tener una idea de la diferencia de tiempo entre las fechas.</p>
+<p>Seleccione los archivos que desea examinar, pulse el bot&oacute;n derecho del rat&oacute;n y elija "Metadatos Asignados&hellip;". Con lo que aparecer&aacute; una ventana llamada "Todos los metadatos", ocupada en su mayor parte por una tabla de varias columnas. La primera columna muestra los nombres de los archivos, mientras que las filas muestran todos los valores asignados a dichos archivos.</p>
+<p>Si se seleccionaron muchos archivos es posible que transcurra alg&uacute;n tiempo antes de que se abra la ventana. Mientras tanto usted puede seguir usando la Interfaz de Bibliotecario.</p>
+<p>Cuando la tabla sea demasiado grande se puede refinar aplicando los filtros a las columnas. Conforme se a&ntilde;adan nuevos filtros, &uacute;nicamente aquellas filas que concuerden con ellos seguir&aacute;n siendo visibles. Para establecer, modificar o borrar un filtro haga click en el icono con forma de embudo que se encuentra en la parte superior de la columna. Se le indicar&aacute; que proporcione informaci&oacute;n sobre el filtro. Una vez que un filtro se ha aplicado, el encabezado de la columna cambia de color.</p>
+<p>El aviso tiene una pesta&ntilde;a "Sencilla" y una "Avanzada". La versi&oacute;n sencilla filtra las columnas de tal manera que s&oacute;lo muestren las filas que contienen un determinado valor ("*" corresponde a todos los valores). Los valores de los metadatos se pueden seleccionar de la lista. La versi&oacute;n avanzada permite diferentes operaciones de concordancia: "debe empezar con", "no contiene", "alfab&eacute;ticamente menos que" y "es igual a". El valor se puede editar con cualquier cadena de caracteres (incluyendo "*") y se puede elegir que la concordancia no tome en cuenta el caso. Finalmente, se puede especificar una segunda condici&oacute;n de concordancia que se puede usar para especificar un rango de valores (seleccionando "Y") o valores alternativos (seleccionando "O"). Debajo de esta &aacute;rea hay un cuadro que le permite cambiar el orden de clasificaci&oacute;n (ascendente o descendente). Una vez que haya terminado, haga click en "Filtrar" para aplicar el nuevo filtro a la columna. Para quitar el filtro haga click en "Borrar filtro". Recuerde que los detalles del filtro se conservan incluso cuando el filtro se borra.</p>
+<p>Por ejemplo, para ordenar la tabla elija una columna, seleccione el filtro por omisi&oacute;n (un filtro Sencillo en "*") y escoja el orden ascendente o descendente.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/savingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/savingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/savingacollection.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="savingacollection"><font face="Verdana" size="5"><strong>2.2: Guardar la colecci&oacute;n</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Guarde su trabajo regularmente abriendo el men&uacute; "Archivo" y seleccionando "Guardar". Tome en cuenta que guardar una colecci&oacute;n no es lo mismo que prepararla para que se pueda usar en Greenstone (vea la secci&oacute;n <a href="producingthecollection.htm"> Produciendo una colecci&oacute;n </a>).</p>
+<p>La Interfaz de Bibliotecario protege su trabajo guard&aacute;ndolo cada vez que salga del programa o cargue otra colecci&oacute;n.</p>
+<p>Las colecciones se guardan en un archivo que lleva el nombre de la colecci&oacute;n y la extensi&oacute;n ".col", ubicado en una carpeta del mismo nombre dentro de la carpeta "colecciones" del programa Greenstone.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/searchindexes.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/searchindexes.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/searchindexes.htm	(revision 13928)
@@ -0,0 +1,22 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="searchindexes"><font face="Verdana" size="5"><strong>6.5: &Iacute;ndices de b&uacute;squeda</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Los &iacute;ndices especifican las partes de la colecci&oacute;n que se pueden buscar. Esta secci&oacute;n explica la forma de a&ntilde;adir y eliminar &iacute;ndices, as&iacute; como predeterminar un &iacute;ndice por omisi&oacute;n. En la parte correspondiente a "Secciones de dise&ntilde;o" haga click en "&Iacute;ndices de b&uacute;squeda".</p>
+<p>Para a&ntilde;adir un &iacute;ndice escriba el nombre que le quiera dar en el campo "Nombre del &iacute;ndice". Seleccione las fuentes de informaci&oacute;n que se van a indexar haciendo click en los recuadros que se encuentran a un lado. La lista mostrar&aacute; todos los elementos de metadatos asignados, as&iacute; como el texto completo. Despu&eacute;s de seleccionar las fuentes de datos, elija la granularidad del &iacute;ndice usando el men&uacute; de "Nivel". Una vez que se han completado estos detalles, la opci&oacute;n "A&ntilde;adir &iacute;ndice" se activa (a menos que haya un &iacute;ndice con los mismos par&aacute;metros). Haga click en ella para a&ntilde;adir el nuevo &iacute;ndice.</p>
+<p>Para editar un &iacute;ndice, selecci&oacute;nelo, cambie los detalles del &iacute;ndice, y pulse "Reemplazar &Iacute;ndice".</p>
+<p>Para quitar un &iacute;ndice de la lista de &iacute;ndices asignados, selecci&oacute;nelo y haga click en "Eliminar &iacute;ndice".</p>
+<p>Para crear un &iacute;ndice que cubra todo el texto y todos los metadatos, pulse sobre "A&ntilde;adir todos".</p>
+<p>El &iacute;ndice predeterminado es el que se usa en la p&aacute;gina de b&uacute;squeda de la colecci&oacute;n y lleva la etiqueta "[Indice por omisi&oacute;n]" en la lista de "&Iacute;ndices asignados". Para establecer un &iacute;ndice por omisi&oacute;n, selecci&oacute;nelo de la lista y haga click en "Predeterminar".</p>
+<p>Si la opci&oacute;n de b&uacute;squeda avanzada est&aacute; activa (a trav&eacute;s de la pantalla de tipos de b&uacute;squeda) los controles de indexaci&oacute;n ser&aacute;n diferentes. Hay una nueva fuente de pseudodatos llamada "allfields" (todos los campos) que permite buscar a trav&eacute;s de todos los &iacute;ndices especificados al mismo tiempo. Los niveles no se asignan a un &iacute;ndice en particular, sino que se aplican a todos los &iacute;ndices. De esta manera los &iacute;ndices y niveles se a&ntilde;aden por separado. "A&ntilde;adir todos" crea un &iacute;ndice independiente para cada metadato en este modo.</p>
+<p>El nombre de cada &iacute;ndice ser&aacute; el de la fuente por omisi&oacute;n. Para cambiar el nombre, seleccione un &iacute;ndice, cambie sus detalles y haga click en "Reemplazar &iacute;ndice".</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/searchtypes.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/searchtypes.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/searchtypes.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="searchtypes"><font face="Verdana" size="5"><strong>6.4: Tipos de b&uacute;squeda</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Esta secci&oacute;n explica la forma de modificar una nueva funci&oacute;n de dise&ntilde;o de Greenstone llamada "Tipos de b&uacute;squeda", que permite la b&uacute;squeda por campos. Los tipos de b&uacute;squeda especifican el tipo de b&uacute;squeda con el que contar&aacute;n las interfaces: formas, b&uacute;squeda por campos y/o b&uacute;squeda de s&oacute;lo texto. En la parte de "Secciones de dise&ntilde;o" haga click en "Tipos de dise&ntilde;o".</p>
+<p>Cuando ingrese a la pantalla de tipos de b&uacute;squeda marque primero el recuadro "Permitir b&uacute;squedas avanzadas", lo cual activa todos los dem&aacute;s controles. Esto cambia la colecci&oacute;n de forma que usa un mecanismo de indexado que permite la b&uacute;squeda por campos. La especificaci&oacute;n de &iacute;ndices es ligeramente diferente en este modo. (Cuando se cambia entre b&uacute;squeda est&aacute;ndar y avanzada, GLI intenta hacer correctamente el cambio de &iacute;ndices, pero no lo hace de forma perfecta).</p>
+<p>Para a&ntilde;adir un tipo de b&uacute;squeda, selecci&oacute;nelo de la lista "Tipos de b&uacute;squeda" y haga click en "A&ntilde;adir tipo de b&uacute;squeda". Cada tipo puede aparecer en la lista solamente una vez. El primer tipo de b&uacute;squeda ser&aacute; el predefinido, y aparecer&aacute; en la p&aacute;gina de b&uacute;squeda de la colecci&oacute;n construida. Los otros podr&aacute;n seleccionarse desde la p&aacute;gina de preferencias.</p>
+<p>Para quitar un tipo de b&uacute;squeda, selecci&oacute;nelo de la lista "Tipos de b&uacute;squeda asignados actualmente" y haga click en "Eliminar tipo de b&uacute;squeda". La lista deber&aacute; contener al menos uno.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/selectingmetadatasets.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/selectingmetadatasets.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/selectingmetadatasets.htm	(revision 13928)
@@ -0,0 +1,16 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="selectingmetadatasets"><font face="Verdana" size="5"><strong>5.2: Seleccionando conjuntos de metadatos</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Los grupos de elementos de metadatos definidos previamente son conocidos como "conjuntos de metadatos". Un ejemplo es el conjunto de metadatos de Dublin Core. Cuando se a&ntilde;ade un conjunto de metadatos a una colecci&oacute;n, sus elementos se vuelven elegibles para que el usuario los pueda seleccionar. Tambi&eacute;n se puede tener m&aacute;s de un conjunto. Para evitar conflictos de nombre, un identificador que describe al conjunto de metadatos se agrega como prefijo al nombre del elemento. Por ejemplo, el elemento Creator de Dublin Core se convierte en "dc.Creator". Los conjuntos de metadatos se guardan en la carpeta de metadatos de la Interfaz de Bibliotecario y llevan el sufijo ".mds".</p>
+<p>Para controlar los conjuntos de metadatos usados en una colecci&oacute;n, utilice la opci&oacute;n "Conjuntos de metadatos" en la vista Dise&ntilde;o.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/startingoff.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/startingoff.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/startingoff.htm	(revision 13928)
@@ -0,0 +1,19 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="startingoff"><font face="Verdana" size="5"><strong>2: Para empezar</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Esta secci&oacute;n explica c&oacute;mo crear, cargar, guardar y borrar colecciones.</p>
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/thecreateview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/thecreateview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/thecreateview.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="thecreateview"><font face="Verdana" size="5"><strong>7.1: La pantalla de creaci&oacute;n de la colecci&oacute;n</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>La pantalla "Crear" se utiliza para producir la colecci&oacute;n ejecutando los guiones de los programas Greenstone con base en la informaci&oacute;n que usted ha proporcionado. Al hacer click en el bot&oacute;n "Crear colecci&oacute;n" se inicia el proceso de construcci&oacute;n de la colecci&oacute;n. El tiempo que se lleve depender&aacute; del tama&ntilde;o de la colecci&oacute;n y del n&uacute;mero de &iacute;ndices que se est&eacute;n creando (para colecciones de gran tama&ntilde;o pueden ser horas). Una barra de progreso indica cu&aacute;nto se ha completado del proceso. Para cancelar el proceso en cualquier momento haga click en el bot&oacute;n "Cancelar la construcci&oacute;n".</p>
+<p>Una vez que la colecci&oacute;n se ha construido exitosamente, al seleccionar "Vista previa de la colecci&oacute;n" se iniciar&aacute; un navegador de web que mostrar&aacute; la p&aacute;gina inicial de la colecci&oacute;n.</p>
+<p>En modo Experto, puede usar las entradas del "Registro de mensajes" a la izquierda, para revisar intentos previos de construcci&oacute;n de la colecci&oacute;n, hayan tenido &eacute;xito o no. Seleccione el registro que desee haciendo click en la fecha correspondiente en la lista "Historial de registro".</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/thedesignview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/thedesignview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/thedesignview.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="thedesignview"><font face="Verdana" size="5"><strong>6.1: La pantalla de dise&ntilde;o</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Esta secci&oacute;n le presenta la pantalla de Dise&ntilde;o y le explica la forma de navegar entre las diferentes opciones de este conjunto.</p>
+<p>Con la Interfaz de Bibliotecario usted puede configurar la forma en que la colecci&oacute;n aparecer&aacute; frente al usuario. Las opciones se dividen en diferentes secciones, cada una relacionada con una etapa particular de navegaci&oacute;n o presentaci&oacute;n.</p>
+<p>A la izquierda se encuentra una lista de las diferentes pantallas, en tanto que a la derecha est&aacute;n los controles asociados a la pantalla que est&aacute; activa en ese momento. Para cambiar a una pantalla diferente haga click en la lista.</p>
+<p>Para entender las etapas y los t&eacute;rminos usados en el dise&ntilde;o de una colecci&oacute;n, lea primero los Cap&iacute;tulos 1 y 2 de la Gu&iacute;a del Programador de Greenstone.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/theenrichview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/theenrichview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/theenrichview.htm	(revision 13928)
@@ -0,0 +1,20 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="theenrichview"><font face="Verdana" size="5"><strong>5.1: La pantalla de asignaci&oacute;n de metadatos</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Utilice la pantalla "Enriquecer" para asignar metadatos a los documentos de la colecci&oacute;n. Los metadatos son datos acerca de los datos: t&iacute;tulo, autor, fecha de creaci&oacute;n, etc. Cada metadato tiene dos partes: el "elemento" dice el tipo de metadato que es (como por ejemplo el autor) y el "valor" da la informaci&oacute;n de ese elemento (como por ejemplo el nombre del autor).</p>
+<p>En la parte izquierda de la pantalla "Enriquecer" se encuentra la estructura de directorios y subdirectorios de la colecci&oacute;n. A la derecha est&aacute; la Tabla de Metadatos, la cual muestra los metadatos de los archivos y carpetas seleccionados. Los nombres de las columnas est&aacute;n en gris en la parte superior y se pueden cambiar de tama&ntilde;o arrastrando la l&iacute;nea que las separa. Si se seleccionan varios archivos, el texto en negro indica que el valor es com&uacute;n a todos ellos, mientras que el texto sombreado indica que no. Los valores en negro se pueden actualizar o eliminar, mientras que los que est&aacute;n sombreados se pueden eliminar de los que los tienen o agregarse a los dem&aacute;s.</p>
+<p>Un icono en forma de carpeta puede aparecer junto a algunas entradas de metadatos. Esto indica que los valores se heredan de la carpeta en la que se encuentra el archivo. Los metadatos heredados no se pueden editar o eliminar, sino &uacute;nicamente agregarse o sobreescribirse. Haga click en el icono de la carpeta para ir inmediatamente a la carpeta en la que se asignaron los metadatos.</p>
+<p>Pulsando sobre el elemento de matadato en la tabla se mostrar&aacute;n los valores existentes  para ese elemento en el &aacute;rea "Valores existentes para..." situada debajo de la tabla. La estructura de valores se puede expandir y contraer. Normalmente es una lista que muestra todos los valores ingresados previamente para un elemento seleccionado. Al hacer click en una entrada &eacute;sta aparece autom&aacute;ticamente en el campo de valores. Y a la inversa, al escribir en el campo se selecciona la entrada de la estructura de valores que empieza con los caracteres ingresados. Al oprimir [Tab] se completa autom&aacute;ticamente el valor seleccionado.</p>
+<p>Los valores de los metadatos se pueden organizar jer&aacute;rquicamente. Esto se muestra en la estructura de valores por medio de carpetas para los niveles internos. Los valores jer&aacute;rquicos pueden ingresarse utilizando el car&aacute;cter "|" para separar los niveles. Por ejemplo, se puede usar "Cartas|Rojo|Diamantes|Siete" en una jerarqu&iacute;a que representa un mazo de cartas. Esto permite agrupar los valores, en tanto que los grupos tambi&eacute;n pueden asignarse en forma de metadatos a los archivos.</p>
+<p>Greenstone extrae autom&aacute;ticamente los metadatos de los documentos para formar un conjunto de metadatos cuyos elementos llevan el prefijo "ex.". &Eacute;ste no tiene estructura de valores y no puede editarse.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/thegatherview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/thegatherview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/thegatherview.htm	(revision 13928)
@@ -0,0 +1,24 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="thegatherview"><font face="Verdana" size="5"><strong>4.1: La pantalla de selecci&oacute;n de documentos</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Esta secci&oacute;n describe el funcionamiento de la pantalla "Reunir" que se utiliza para seleccionar los archivos que se van a incluir en la colecci&oacute;n que se est&aacute; construyendo. La Interfaz de Bibliotecario inicia con la pantalla "Reunir". Si despu&eacute;s usted desea regresar a esta pantalla haga click en la pesta&ntilde;a del mismo nombre que se encuentra directamente debajo de la barra de men&uacute;s.</p>
+<p>Dos grandes &aacute;reas tituladas "Area de trabajo" y "Colecci&oacute;n" se utilizan para transferir los archivos a su colecci&oacute;n. Cada una contiene "&aacute;rboles de archivos", los cuales son representaciones gr&aacute;ficas de la estructura de directorios y subdirectorios de sus archivos y carpetas.</p>
+<p>Seleccione un elemento del &aacute;rbol haciendo click en &eacute;l. (Tambi&eacute;n existen otras formas; v&eacute;ase m&aacute;s adelante.) Haga click en el signo que se encuentra junto a una carpeta o doble click en ella para expandir (o contraer) sus contenidos. Haga doble click en un archivo para abrirlo usando un programa de aplicaci&oacute;n asociado (vea la secci&oacute;n <a href="fileassociations.htm">Asociaci&oacute;n de archivos</a>).</p>
+<p>El &aacute;rbol de archivos del &aacute;rea de trabajo muestra los or&iacute;genes de la informaci&oacute;n disponible al interfaz del Bibliotecario -- el sistema local de archivos (incluyendo unidades de disco y CD-ROM), los contenidos de las colecciones existentes de Greenstone, y el cach&eacute; de archivos descargados. Usted puede copiar y consultar estos archivos pero no puede moverlos, eliminarlos o editarlos, con la excepci&oacute;n de los archivos descargados, los cuales pueden ser eliminados. Navegue por este espacio para buscar los archivos que desee incluir en la colecci&oacute;n.</p>
+<p>La estructura de directorios y subdirectorios de la colecci&oacute;n muestra sus contenidos. Inicialmente est&aacute; vac&iacute;a.</p>
+<p>Se puede cambiar el tama&ntilde;o de las &aacute;reas oprimiendo el bot&oacute;n del mouse sobre la barra gris que separa las estructuras de directorios y subdirectorios (la forma del cursor cambia) y arrastr&aacute;ndola.</p>
+<p>En la parte inferior de la ventana se muestra un &aacute;rea de estado que informa del progreso de las acciones sobre archivos (copiando, moviendo y borrando). Puede tardar un tiempo en terminar. El bot&oacute;n "Detener" interrumpe cualquier acci&oacute;n que se est&eacute; ejecutando en ese momento.</p>
+<p>Dos grandes botones ocupan la esquina inferior derecha de la pantalla: "Nueva carpeta", con la imagen de una carpeta, crea nuevas carpetas (vea la secci&oacute;n <a href="creatingfolders.htm">Creando carpetas</a>), en tanto que "Eliminar", con la imagen de un bote de basura, descarta los archivos. Al hacer click en el bot&oacute;n "Eliminar" se suprimir&aacute;n los archivos seleccionados de la estructura de directorios y subdirectorios de la colecci&oacute;n. Asimismo, los archivos pueden eliminarse arrastr&aacute;ndolos hacia este bot&oacute;n.</p>
+<p>Para seleccionar varios elementos consecutivos, seleccione el primero y a continuaci&oacute;n manteniendo oprimida la tecla de may&uacute;sculas o [Shift] haga click en el &uacute;ltimo: la selecci&oacute;n incluir&aacute; todos los elementos que se encuentran en medio. Para seleccionar varios archivos que no sean consecutivos mantenga oprimida la tecla de control o [Ctrl] mientras hace click en ellos. Utilice alternativamente estos dos m&eacute;todos para seleccionar grupos de elementos que no est&eacute;n juntos.</p>
+<p>En ocasiones algunas carpetas, como la que contiene sus propias p&aacute;ginas Web, tienen un significado especial. La Interfaz de Bibliotecario puede asignar dichas carpetas al primer nivel de la estructura de directorios y subdirectorios. Para hacerlo haga click con el bot&oacute;n derecho del mouse sobre la carpeta deseada. Seleccione "Crear un acceso directo" y d&eacute;le un nombre a la carpeta. Para quitar un elemento haga click con el bot&oacute;n derecho del mouse sobre la carpeta mapeada y seleccione "Eliminar acceso directo".</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/themirrorview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/themirrorview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/themirrorview.htm	(revision 13928)
@@ -0,0 +1,19 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="themirrorview"><font face="Verdana" size="5"><strong>3.1: La vista en Bajar</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Esta secci&oacute;n describe como configurar una tarea de descarga y como controlar el proceso de descargue. Active la vista "Bajar" haciendo clic en su pesta&ntilde;a. La mitad superior de la pantalla contiene los controles para realizar descargas. La mitad inferior est&aacute; vac&iacute;a inicialmente, pero despu&eacute;s va a mostrar una lista de tareas pendientes y terminadas.</p>
+<p>Los archivos se descargan en una carpeta del espacio de trabajo denominada "Archivos Descargados", y pueden utilizarse en todas las colecciones construidas con el interfaz del Bibliotecario. En esta &aacute;rea los archivos se designan con su URL completo. Para cada "host" se crea una nueva carpeta, seguida por otras para cada parte del "path". De esta manera se asegura que todos los archivos son distintos.</p>
+<p>Utilice el primero de los controles de configuraci&oacute;n de la descarga, "URL Or&iacute;gen", para capturar el URL de un recurso deseado. Utilice el control "Profundidad de la Descarga" para limitar el n&uacute;mero de hiper-v&iacute;nculos que se deben seguir al descargar: P&oacute;ngalo en 0 para descargar una sola p&aacute;gina; p&oacute;ngalo en 1 para descargar una p&aacute;gina y todas las p&aacute;ginas a las que apunta. El l&iacute;mite de profundidad se ignora al descargar medios diferentes de p&aacute;ginas html. Adem&aacute;s, hay varios controles de chequeo que se pueden prender para activar determinadas capacidades durante una descarga espec&iacute;fica. Una vez se ha establecido la configuraci&oacute;n, haga clic en "Descargar" para iniciar un nuevo proceso de descargue. Hay otros dos controles en forma de botones: "Preferencias", que enlaza con la secci&oacute;n de conexi&oacute;n de las Preferencias, en la cual se pueden editar las caracter&iacute;sticas del "proxy"; y "Borrar Cach&eacute;", que borra todos los archivos descargados previamente.</p>
+<p>La lista de descargas tiene una entrada por cada p&aacute;gina web descargada. Cada entrada tiene un &aacute;rea de texto que da detalles acerca de la tarea, junto con una barra que indica el avance de la actividad en ejecuci&oacute;n. A la izquierda de cada entrada aparecen tres botones. "Pausa" se utiliza para detener temporalmente la descarga que se est&aacute; ejecutando. "Ver Bit&aacute;cora" abre una ventana que muestra el archivo de bit&aacute;cora de las descargas. "Cerrar" termina la descarga y quita de la lista la tarea correspondiente.</p>
+<p>La secci&oacute;n <a href="preferences.htm">Preferencias</a> describe como establecer una conexi&oacute;n Internet por medio de un "proxy".  Si se necesita autenticaci&oacute;n, el servidor "proxy" pide la identificaci&oacute;n y la palabra clave. El interfaz del Bibliotecario no almacena palabras claves entre sesiones.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/translatetext.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/translatetext.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/translatetext.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="translatetext"><font face="Verdana" size="5"><strong>6.10: Traducci&oacute;n de textos</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Esta secci&oacute;n describe la pantalla de traducci&oacute;n, donde se pueden definir fragmentos de texto en un idioma espec&iacute;fico para partes de la interfaz de la colecci&oacute;n. En la parte de "Secciones de dise&ntilde;o" haga click en "Traducir texto".</p>
+<p>Primero elija una entrada de la lista de "funciones". Las cadenas de texto asociadas a esta funci&oacute;n aparecer&aacute;n abajo. Utilice la lista "Idioma de la traducci&oacute;n" para seleccionar el idioma al que se va a traducir y escriba el texto traducido en el &aacute;rea de texto, haciendo referencia al "fragmento de texto inicial" en caso necesario. Una vez que haya terminado haga click en "A&ntilde;adir traducci&oacute;n".</p>
+<p>Para quitar una traducci&oacute;n existente, selecci&oacute;nela de la tabla "Traducciones asignadas" y haga click en "Eliminar traducci&oacute;n".</p>
+<p>Para actualizar una traducci&oacute;n, selecci&oacute;nela, ed&iacute;tela en el &aacute;rea de texto titulada "Texto traducido" y haga click en "Reemplazar traducci&oacute;n".</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/updatingmetadata.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/updatingmetadata.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/updatingmetadata.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="updatingmetadata"><font face="Verdana" size="5"><strong>5.5: Editar o Borrar Metadatos</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Para editar o borrar elementos de metadato, primero seleccione el campo apropiado, y luego el valor de metadato de la tabla. Edite el campo del valor, y borre todo el texto si quiere borrar el metadato.</p>
+<p>El proceso es el mismo cuando se actualiza un directorio que contiene subdirectorios o m&uacute;ltiples archivos, pero s&oacute;lo se pueden actualizar metadatos que sean comunes a todos los archivos y carpetas seleccionados.</p>
+<p>El arbol de valores muestra todos los valores asignados actualmente, as&iacute; como todos los valores previos de la sesi&oacute;n activa, por lo que los valores modificados o borrados permanecer&aacute;n en el &aacute;rbol. Si cierra y vuelve a abrir la colecci&oacute;n, se borrar&aacute;n los valores que ya no est&aacute;n asignados.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/es/xcollectionsearching.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/es/xcollectionsearching.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/es/xcollectionsearching.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="xcollectionsearching"><font face="Verdana" size="5"><strong>6.7: B&uacute;squeda cruzada a trav&eacute;s de varias colecciones</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Greenstone puede buscar a trav&eacute;s de varias colecciones distintas como si fueran una sola. Esto se hace especificando una lista de otras colecciones que puedan ser buscadas junto con la actual. En la parte de "Secciones de dise&ntilde;o" haga click en "B&uacute;squeda cruzada".</p>
+<p>La pantalla de b&uacute;squeda cruzada muestra una lista de las colecciones disponibles. La colecci&oacute;n actual est&aacute; marcada y no se puede quitar de la selecci&oacute;n. Para a&ntilde;adir otra colecci&oacute;n en la cual buscar de forma paralela, haga click en ella (o haga click en ella nuevamente para quitarla de la selecci&oacute;n). Si s&oacute;lo se seleccion&oacute; una colecci&oacute;n, entonces no habr&aacute; b&uacute;squeda cruzada.</p>
+<p>Si las colecciones no tienen los mismos &iacute;ndices (incluyendo particiones en subcolecciones e idiomas) la b&uacute;squeda cruzada no funcionar&aacute; correctamente. El usuario &uacute;nicamente ser&aacute; capaz de buscar usando &iacute;ndices comunes a todas las colecciones.</p>
+<p>Para mayor informaci&oacute;n vea el Cap&iacute;tulo 1 de la Gu&iacute;a del Programador de Greenstone.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/addingfiles.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/addingfiles.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/addingfiles.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="addingfiles"><font face="Verdana" size="5"><strong>4.3: Ajouter des fichiers</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Les fichiers peuvent &ecirc;tre copi&eacute;s dans la collection par glisser-d&eacute;placer. Le pointeur &eacute;pouse la forme de l'&eacute;l&eacute;ment s&eacute;lectionn&eacute; (ou, si la s&eacute;lection comprend plus d'un, leur nombre). D&eacute;poser la s&eacute;lection dans l'arborescence de la collection pour les y copier (si la source est l'arborescence de l'espace de travail) ou les d&eacute;placer &agrave; l'int&eacute;rieur de la collection (si la source est l'arborescence de la collection).</p>
+<p>Lorsque des fichiers multiples sont copi&eacute;s, ils sont tous plac&eacute; dans le dossier cible au m&ecirc;me niveau, quelle que soit la structure du dossier qui les contenait avant. Si vous copier un second fichier avec le m&ecirc;me nom dans le m&ecirc;me dossier, la question de savoir si le premier fichier doit &ecirc;tre &eacute;cras&eacute; est pos&eacute;e. Si la r&eacute;ponse est non, le fichier ne sera pas copi&eacute;, mais les autres le seront. Pour annuler toutes les autre t&acirc;ches de copie, cliquer sur le bouton "Stop".</p>
+<p>Seuls les &eacute;l&eacute;ments situ&eacute;s au-dessus dans la s&eacute;lection sont d&eacute;plac&eacute;s. Un dossier est plus &eacute;lev&eacute; que son contenu. On ne peut s&eacute;lectionner en m&ecirc;me temps l'int&eacute;rieur d'un dossier et le dossier lui-m&ecirc;me.</p>
+<p>Lorsqu'un fichier est ajout&eacute;, l'Interface Biblioth&eacute;caire cherche les dossiers sources de fichiers auxiliaires contenant une m&eacute;ta-donn&eacute;e qui lui originellement assign&eacute;es et, s'il en trouve, commence &agrave; les importer. Au fur et &agrave; mesure que l'op&eacute;ration se poursuit, une confirmation est faite (peut-&ecirc;tre plusieurs fois) de fournir des informations compl&eacute;mentaires pour ajuster la m&eacute;ta-donn&eacute;e aux jeux de m&eacute;ta-donn&eacute;es de la collection. Ces confirmations sont d&eacute;crites dans la section <a href="importingpreviouslyassignedmetadata.htm">Importer des M&eacute;ta-donn&eacute;es Pr&eacute;-assign&eacute;es</a>. Pour une explication plus d&eacute;taill&eacute;e de l'association de m&eacute;ta-donn&eacute;es avec les fichiers, lire le chapitre 2 du Guide de d&eacute;veloppement de Greenstone -- "Exploitez vos documents au maximum".</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/addingpreviouslydefinedmetadata.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/addingpreviouslydefinedmetadata.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/addingpreviouslydefinedmetadata.htm	(revision 13928)
@@ -0,0 +1,16 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="addingpreviouslydefinedmetadata"><font face="Verdana" size="5"><strong>5.4: Ajouter des M&eacute;ta-donn&eacute;es pr&eacute;d&eacute;finies</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Pour ajouter une m&eacute;ta-donn&eacute;e ayant une valeur existante, s&eacute;lectionner d'abord le fichier, et ensuite la valeur requise &agrave; partir de l'arborescence des valeurs, en d&eacute;veloppant si n&eacute;cessaire les dossiers de hi&eacute;rarchie. La valeur de l'entr&eacute;e s&eacute;lectionn&eacute;e appara&icirc;t automatiquement dans le champ texte Valeur. (Utiliser alternativement la valeur auto-select de l'arborescence et les caract&eacute;ristiques auto-compl&egrave;tes. </p>
+<p>La proc&eacute;dure d'ajouter m&eacute;ta-donn&eacute;es avec des valeurs d&eacute;j&agrave; existantes aux dossiers ou aux fichiers multiples est tout &agrave; fait identique.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/appendingmetadata.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/appendingmetadata.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/appendingmetadata.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="appendingmetadata"><font face="Verdana" size="5"><strong>5.3: Ajout de Nouvelles M&eacute;ta-donn&eacute;es</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>On ajoute un &eacute;l&eacute;ment m&eacute;ta-donn&eacute;e -- &eacute;l&eacute;ment et valeur &agrave; la fois -- &agrave; un fichier. S&eacute;lectionner d'abord le fichier &agrave; partir de l'arborescence de fichier de la collection situ&eacute;e &agrave; gauche. Cette action entra&icirc;ne l'apparition de toute m&eacute;ta-donn&eacute;e pr&eacute;-assign&eacute;e  dans le tableau de droite. </p>
+<p>S&eacute;lectionner ensuite l'&eacute;l&eacute;ment m&eacute;ta-donn&eacute;e &agrave; ajouter en cliquant sur sa rang&eacute;e dans le tableau.</p>
+<p>Taper la valeur dans le champ valeur. Utilisez le charact&egrave;re "|" pour rapporter une structure, comme d&eacute;crit dans <a href=".htm"></a>. Vous pouvez sauver l' information metadata en pressant les touches [Up] ou [Down] et bouger ainsi la s&eacute;lection convenablement. En pressant la touche [Enter] l'information metadata sera sauv&eacute;e et une nouvelle entr&eacute;e vide sera cr&eacute;&eacute;e pour l' &eacute;l&eacute;ment metadata, vous permettant d&eacute;signer multiples valeurs pour un &eacute;l&eacute;ment de metadata.</p>
+<p>Vous pouvez aussi ajouter des m&eacute;ta-donn&eacute;es &agrave; un dossier, ou &agrave; plusieurs fichiers s&eacute;lectionn&eacute;s &agrave; la fois. Elle est ajout&eacute;e &agrave; tous les fichiers ou &agrave; l'int&eacute;rieur du dossier ou de la s&eacute;l&eacute;ction, et aux sous-dossiers. Garder &agrave; l'esprit  que si des m&eacute;ta-donn&eacute;es sont ajout&eacute;es &agrave; un dossier tous les nouveaux fichiers en son sein h&eacute;rite automatiquement des valeurs du dossier.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/assignlanguages.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/assignlanguages.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/assignlanguages.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="assignlanguages"><font face="Verdana" size="5"><strong>6.6.3: Assigner Langages</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Cette section donne les d&eacute;tails de la mani&egrave;re de restreindre les index &agrave; des langages particuliers. On le fait en g&eacute;n&eacute;rant une partition par le biais de l'onglet "Assigner Langages" de l'Affichage "Index de Partition".</p>
+<p>Pour ajouter un nouveau langage, dont la partition par le biais de l'onglet "Assigner langues" conf&egrave;re un index, S&eacute;lectionner le langage souhait&eacute; &agrave; partir de la liste "Langage &agrave; ajouter" et cliquer sur "Ajouter langue".</p>
+<p>Pour supprimer une langue, s&eacute;lectionner-la &agrave; partir de la liste "S&eacute;lection de Langage" et cliquer sur "Enlever Langage". </p>
+<p>Pour installer un language par d&eacute;faut, s&eacute;lectionner-la dans la liste et cliquez sur "Par d&eacute;faut".</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/assignpartitions.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/assignpartitions.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/assignpartitions.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="assignpartitions"><font face="Verdana" size="5"><strong>6.6.2: Assigner des Partitions</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Apr&egrave;s avoir d&eacute;fini un filtre de sous-collection, utiliser l'onglet "Assigner des Partitions" pour construire ses indexes  (ou ceux pour un jeu de filtres.) S&eacute;lectionner le filtre (ou les filtres) de votre choix &agrave; partir de la liste "D&eacute;finir des Filtres de Sous-collection", entrer un nom pour la partition dans le champ "Nom de Partition Name", et cliquer sur "Ajouter Partition". </p>
+<p>Pour supprimer une partition, s&eacute;lectionner-la &agrave; partir de la liste et cliquer sur "Enlever Partition".</p>
+<p>Pour faire d'une partition celle par d&eacute;faut, s&eacute;lectionner-la &agrave; partir de la liste et cliquer sur "Par D&eacute;faut".</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/buildsettings.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/buildsettings.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/buildsettings.htm	(revision 13928)
@@ -0,0 +1,16 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="buildsettings"><font face="Verdana" size="5"><strong>7.2: Param&egrave;tres d'Importation et de Construction</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Cette section explique comment acc&eacute;der aux diff&eacute;rents param&egrave;tres de construction et d'importation. Pour plus d'informations sur l'importation et la construction lire le chapitre 1 du Guide du D&eacute;veloppeur de Greenstone -- Comprendre le processus de construction de la collection.</p>
+<p>Le contr&ocirc;le des diff&eacute;rents param&egrave;tres se fait de fa&ccedil;on identique &agrave; la fen&ecirc;tre "Configurer Arguments" d&eacute;crit dans la section <a href="plugins.htm">Plugiciels de Document</a>. Certains champs requi&egrave;rent des arguments num&eacute;riques, et on peut: soit les incorporer en les saisissant, soit utiliser les fl&egrave;ches Haut et Bas pour augmenter ou diminuer la valeur pr&eacute;sente (dans certains cas, l'interface limite la classe qu'on peut entrer.) D'autres sont activ&eacute;s en cliquant sur une case de v&eacute;rification (re-cliquer pour d&eacute;sactiver.)</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/classifiers.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/classifiers.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/classifiers.htm	(revision 13928)
@@ -0,0 +1,20 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="classifiers"><font face="Verdana" size="5"><strong>6.8: Classificateurs de navigation</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Cette section explique comment assigner &agrave; une collection des "classificateurs" qui sont utilis&eacute;s pour naviguer. Sous la section "Sections de conception", cliquer sur "Classificateurs de navigation".</p>
+<p>Pour ajouter un classificateur, s&eacute;lectionner-le en utilisant la liste d&eacute;roulante "Choisir classificateur &agrave; ajouter" et cliquer sur "Ajouter Classificateur". une fen&ecirc;tre qui s'intitule "Configurer Arguments" appara&icirc;t ; les instructions concernant ce dialogue sont les m&ecirc;mes que pour les plugiciels (voir <a href="plugins.htm">Plugiciels de Document</a>). Une fois le nouveau classificateur configur&eacute;, il s'ajoute &agrave; la fin de la liste des "Classificateurs couramment Assign&eacute;s". </p>
+<p>Pour supprimer un classificateur, s&eacute;lectionner-le dans la liste et cliquez sur "Supprimer Classificateur".</p>
+<p>Pour changer les arguments d'un classificateur, s&eacute;lectionner-le sur la liste et cliquer sur "Configurer Classificateur" (ou double-cliquer sur le classificateur sur la liste.) </p>
+<p>Le tri des classificateurs dans la barre de navigation de la collection est fourni ici dans l'ordre des classificateurs. Pour le changer, s&eacute;lectionner le classificateur &agrave; d&eacute;placer et cliquer sur "D&eacute;placer vers le haut" ou "D&eacute;placer vers le bas".</p>
+<p>Pour plus d'informations sur les classificateurs lisez le chapitre 2 du Guide du D&eacute;veloppeur Greenstone -- Exploitez vos documents au maximum.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/collectingfiles.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/collectingfiles.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/collectingfiles.htm	(revision 13928)
@@ -0,0 +1,20 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="collectingfiles"><font face="Verdana" size="5"><strong>4: Collecter les fichiers pour la Collection</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>D&egrave;s lors que l'on dispose d'une nouvelle collection, la n&eacute;cessit&eacute; se fait sentir de la doter de fichiers. Ils peuvent provenir de votre espace fichier ordinaire ou d'autres collections Greenstone. Quelques uns peuvent avoir des m&eacute;ta-donn&eacute;es attach&eacute;es.Cette section d&eacute;crit comment importer des fichiers.</p>
+
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/creatingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/creatingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/creatingacollection.htm	(revision 13928)
@@ -0,0 +1,20 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="creatingacollection"><font face="Verdana" size="5"><strong>2.1: Cr&eacute;er une nouvelle collection</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Pour cr&eacute;er la nouvelle collection, ouvrir le menu "Fichier" et choisir "Nouveau". Plusieurs champs doivent &ecirc;tre remplis -- mais leurs valeurs sont susceptibles d'&ecirc;tre modifi&eacute;es &agrave; souhait dans l'affichage de la conception.</p>
+<p>"Titre de la collection" est le texte affich&eacute; en haut de la page d'accueil de votre collection. Sa longueur peut &ecirc;tre quelconque.</p>
+<p>"Description du contenu" doit d&eacute;crire avec le plus de d&eacute;tails possibles ce que la collection est. Utiliser la touche [Entr&eacute;e] pour la diviser en paragraphes.</p>
+<p>On doit enfin sp&eacute;cifier soit que la nouvelle collection aura la m&ecirc;me forme et les m&ecirc;mes jeux de m&eacute;ta-donn&eacute;es que la collection existante, soit qu'elle est initi&eacute;e  "Nouvelle collection" par d&eacute;faut.</p>
+<p>Cliquer sur "OK" pour cr&eacute;er la collection. Si on choisit "Nouvelle collection", les jeux de m&eacute;ta-donn&eacute;es disponibles sont affich&eacute;es. On peut en choisir plus d'une et en ajouter d'autres ult&eacute;rieurement.</p>
+<p>Le clic sur "Annuler" ram&egrave;ne imm&eacute;diatement l'&eacute;cran principal.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/creatingfolders.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/creatingfolders.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/creatingfolders.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="creatingfolders"><font face="Verdana" size="5"><strong>4.2: Cr&eacute;er des dossiers</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Utiliser les dossiers de l'arborescence de fichiers de la collection pour rejeur les fichiers et les rendre ais&eacute;ment accessibles. Des dossiers peuvent &ecirc;tre plac&eacute;s &agrave; l'int&eacute;rieur d'autres dossiers. Aucune limite, virtuellement parlant, ni au nombre de dossiers dont on peut disposer ni &agrave; la complexit&eacute; de leur agencement.</p>
+<p>Pour cr&eacute;er un nouveau dossier, on peut opter pour un dossier existant et cliquer sur le bouton Nouveau Dossier. Le nouveau dossier appara&icirc;t &agrave; l'int&eacute;rieur de celui choisi, ou au niveau sup&eacute;rieur si aucun n'est choisi. Le nom de ce dossier est r&eacute;clam&eacute; ( &agrave; d&eacute;faut, il sera nomm&eacute; "Nouveau Dossier").</p>
+<p>Les dossiers peuvent aussi &ecirc;tre cr&eacute;&eacute;s en cliquant sur le dossier avec le bouton droit, et en choisissant "Nouveau Dossier" et proc&eacute;der comme ci-dessus.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/definefilters.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/definefilters.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/definefilters.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="definefilters"><font face="Verdana" size="5"><strong>6.6.1: D&eacute;finir les Filtres</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Les filtres permettent de jeur en sous-collection tous les documents dans un index pour laquelle une valeur m&eacute;ta-donn&eacute;e correspond &agrave; un type donn&eacute;.</p>
+<p>Pour cr&eacute;er un filtre, cliquer sur le bouton "D&eacute;finir les Filtres" et entrer un nom pour le nouveau filtre dans le champ "Nom du filtre de  sous collection". Ensuite choisir un attribut de document &agrave; faire correspondre  soit avec l'&eacute;l&eacute;ment de m&eacute;ta-donn&eacute;e soit avec le nom du fichier en question. Saisir une expression courante qu'il faut utiliser durant la correspondance. Vous pouvez choisir entre "Inclure" les documents qui correspondent au fichier ou les "Exclure". Enfin, on peut sp&eacute;cifier l'un quelconque des drapeaux standard PERL d'expression courante qu'il faut utiliser pour la correspondance (par exemple "i" pour les correspondances ne tenant pas compte des caract&egrave;res.) Pour finir, cliquez sur "Ajouter un Filtre" pour ajouter le filtre &agrave; la liste "Filtres de sous collection d&eacute;finis". </p>
+<p>Pour enlever un filtre, s&eacute;lectionner-le sur la liste et cliquer sur "Enlever Filtre".</p>
+<p>Pour changer un filtre, s&eacute;lectionner-le sur la liste, changer l'une quelconque des valeurs apparaissant dans les contr&ocirc;les d'&eacute;dition et cliquer sur "Remplacer Filtre" pour valider les modifications.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/deletingcollections.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/deletingcollections.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/deletingcollections.htm	(revision 13928)
@@ -0,0 +1,15 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="deletingcollections"><font face="Verdana" size="5"><strong>2.4: Suppression des collections</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Pour supprimer d&eacute;finitivement des collections de votre installation Greenstone, choisir "Supprimer..." dans le menu "Fichier". Une liste de vos collections Greenstone appara&icirc;t. Selectionner une collection pour vior sa description, puis cocher la case en bas du dialogue et clicquez "Supprimer" pour supprimer la collection. Cette operation est irr&eacute;versible, v&eacute;rifiez bien que vous n'avez plus besoin de cette collection avant de supprimer!</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/designingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/designingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/designingacollection.htm	(revision 13928)
@@ -0,0 +1,26 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="designingacollection"><font face="Verdana" size="5"><strong>6: D&eacute;coration de l'apparence de votre collection</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Une fois les fichiers marqu&eacute;s avec les m&eacute;ta-donn&eacute;es, on peut d&eacute;cider comment ils devraient appara&icirc;tre aux utilisateurs comme une collection Greenstone. Quel type d'information peut &ecirc;tre recherch&eacute;? Quels sont les moyens qui sont fournis pour naviguer &agrave; travers les documents? Quels sont les langages support&eacute;s? o&ugrave; apparaissent les boutons sur la page? ces choses peuvent &ecirc;tre adapt&eacute;es; cette section d&eacute;crit comment proc&eacute;der.</p>
+
+
+
+
+
+
+
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/downloadingfiles.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/downloadingfiles.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/downloadingfiles.htm	(revision 13928)
@@ -0,0 +1,16 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="downloadingfiles"><font face="Verdana" size="5"><strong>3: T&eacute;l&eacute;chargement de fichiers de lIinternet</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>La vue "T&eacute;l&eacute;chargement" vous permet de t&eacute;l&eacute;charger des resources de l'internet. Cette section explique le processus de miroir de l'interface biblioth&eacute;caire.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/enrichingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/enrichingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/enrichingacollection.htm	(revision 13928)
@@ -0,0 +1,22 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="enrichingacollection"><font face="Verdana" size="5"><strong>5: Enrichir la Collection avec des m&eacute;ta-donn&eacute;es</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Apr&egrave;s avoir rassembl&eacute; plusieurs fichiers dans la collection, on les enrichit d'une information compl&eacute;mentaire appel&eacute;e "m&eacute;ta-donn&eacute;e". Cette section explique comment une m&eacute;tadonn&eacute;e est cr&eacute;&eacute;e, &eacute;dit&eacute;e, assign&eacute;e ou retir&eacute;e, et comment utiliser les sources de m&eacute;ta-donn&eacute;es externes (voir aussi le chapitre 2 du Guide de d&eacute;veloppement de Greenstone -- "Exploitez vos documents au maximum").</p>
+
+
+
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/exportingcollections.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/exportingcollections.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/exportingcollections.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="exportingcollections"><font face="Verdana" size="5"><strong>8.3: Exportation de collections vers CD/DVD</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Greenstone peut exporter une ou plusieurs collections vers un CD/DVD d'auto-installation pour Windows. Pour ce faire, le paquetage Greenstone "Export to CD-ROM" doit &ecirc;tre install&eacute;. Il n'est pas inclut par d&eacute;faut, donc vous aurez peut &ecirc;tre &agrave; modifier votre installation pour l'inclure.</p>
+<p>Pour exporter une collection, ouvrir le menu "Fichier" et choisir "Exporter la Collection vers un CD-ROM". Une liste de collections Greenstone appara&icirc;t; cliquez sur n'importe laquelle pour obtenir une description. Cochez la case des collections &agrave; exporter. Vous pouvez entrer le nom du CD/DVD dans la case: c'est ce qui va appara&icirc;tre dans le menu de d&eacute;marrage lorsque le CD/DVD aura &eacute;t&eacute; install&eacute;. Puis cliquez sur "Exporter". Ce processus implique la copie de plusieurs fichiers et peut durer quelques minutes.</p>
+<p>A la fin de l'op&eacute;ration, Greenstone va afficher le nom d'un dossier contenant les collections export&eacute;es. Utilisez un graveur de CD/DVD pour copier le contenu dans un CD/DVD vierge.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/fileassociations.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/fileassociations.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/fileassociations.htm	(revision 13928)
@@ -0,0 +1,20 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="fileassociations"><font face="Verdana" size="5"><strong>8.2: Associations de fichiers</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>L'Interface Biblioth&eacute;caire utilise des programmes d'application particuli&egrave;res pour ouvrir des types de fichiers particuliers. 
+Pour modifier des associations ouvrez le menu "Fichier" et cliquer sur "Association de fichiers". </p>
+<p>Pour ajouter une association, s&eacute;lectionner l'extension du fichier cible dans la liste d&eacute;roulant, ou taper dans une nouvelle extension (n'y incluer pas le ".") Ensuite soit taper la commande qui lance l'application voulue dans la champ appropri&eacute;, soit choisir l'application dans le dialogue "Navigation". "%1" Peut &ecirc;tre utilis&eacute; dans la commande de lancement pour ins&eacute;rer le nom du fichier qu'on veut ouvrir. Une fois cela, "Ajouter" est activ&eacute;. Cliquer dessus pour ajouter l'association.</p>
+<p>Pour &eacute;diter une association, s&eacute;lectionner une extension de fichier existante. Toute commande existante associ&eacute;e est affich&eacute;e dans le champ de la commande de lancement. Corriger-la, et puis cliquer sur "Remplacer".</p>
+<p>Pour enlever une association, s&eacute;lectionner une extension de fichier existante et cliquer sur "Supprimer". (L'extension du fichier reste dans la liste d&eacute;roulante "For Files Ending").</p>
+<p>Les associations de fichiers sont stock&eacute;es dans le dossier principal du r&eacute;pertoire principal de l'Interface Biblioth&eacute;caire, dans un fichier appel&eacute; "associations.xml".</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/filteringthetree.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/filteringthetree.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/filteringthetree.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="filteringthetree"><font face="Verdana" size="5"><strong>4.5: Filtrer l'arborescence</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Le "Filtrage" de l'arborescence de la collection permet de r&eacute;duire la recherche de fichiers particuliers.</p>
+<p>Le menu d&eacute;roulant des "Montrer Fichiers" ("Show Files") au bas de chaque arborescence montre une liste de filtres pr&eacute;d&eacute;finis, tels "Images". Son choix cache temporairement tous les autres fichiers de l'arborescence. Pour restorer celle-ci, changer le filtre en "Tous Fichiers". Ces op&eacute;rations n'alt&egrave;rent ni la collection, ni n'affectent les dossiers dans l'arborescence.</p>
+<p>On peut sp&eacute;cifier un filtre usuel en saisissant un mod&egrave;le assorti aux fichiers vis&eacute;s (syst&egrave;mes Librairiens Sp&eacute;cialistes et modes Experts seulement). Utiliser un syst&egrave;me standard d'abr&eacute;viations de fichiers telles que "*.*" ou "*.doc" (*. concerne tous les caract&egrave;res).</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/formatstatements.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/formatstatements.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/formatstatements.htm	(revision 13928)
@@ -0,0 +1,22 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="formatstatements"><font face="Verdana" size="5"><strong>6.9: Caract&eacute;ristiques de Format</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Les pages web que vous voyez en utilisant Greenstone ne sont pas pr&eacute;-stock&eacute;s mais sont g&eacute;n&eacute;r&eacute;es '&agrave; la vol&eacute;e' au fur et &agrave; mesure qu'on en fait appel. Les commandes de format sont utilis&eacute;es pour changer l'apparence de ces pages g&eacute;n&eacute;r&eacute;es. Ils influencent le lieu d'apparition des boutons lorsqu'un document est affich&eacute;, et d&eacute;terminent les liens qui sont affich&eacute;s par le classificateur DateList. Les commandes de format ne sont pas faciles &agrave; concevoir, et la lecture du chapitre 2 de Greenstone Developer's Guide est recommand&eacute;e. Cette section concerne les cadres de format, et  indique comment l'Interface Biblioth&eacute;caire en fournit l'acc&egrave;s. Sous "Sections de conception", cliquer sur "Caract&eacute;ristiques de Format".</p>
+<p>On peut appliquer une commande de format &agrave; n'importe quoi dans la liste d&eacute;roulante "Choisir Caract&eacute;ristique" qui comprend tous les classificateurs de m&ecirc;me qu'une liste pr&eacute;d&eacute;finie de caract&eacute;ristiques. Deux types de contr&ocirc;les existent lorsqu'on s&eacute;lectionne une caract&eacute;ristique: Certaines caract&eacute;ristiques sont simplement activ&eacute;es ou d&eacute;sactiv&eacute;es, et le contr&ocirc;le se fait gr&acirc;ce &agrave; une liste de v&eacute;rification. D'autres requi&egrave;rent qu'on sp&eacute;cifie une cha&icirc;ne de format. Pour ces caract&eacute;ristiques, il existe une liste de retrait ("Composante Affect&eacute;e") pour la s&eacute;lection des parties de la caraxt&eacute;ristique o&ugrave; s'applique la cha&icirc;ne (si n&eacute;cessaire), une zone de texte ("Cha&icirc;ne de Format HTML") o&ugrave; on saisit la cha&icirc;ne, et une s&eacute;lection de "Variables" pr&eacute;d&eacute;finies. Pour ins&eacute;rer une variable dans la position courante dans la cha&icirc;ne de format, s&eacute;lectionner la &agrave; partir de la liste de retrait et cliquer sur "Ins&eacute;rer". </p>
+<p>Vous pouvez sp&eacute;cifier un format par d&eacute;faut pour une composante particuli&egrave;re en s&eacute;lectionnant la caract&eacute;ristique vierge.Ce format est alors appliqu&eacute; &agrave; toutes les caract&eacute;ristiques applicables sauf instruction contraire. </p>
+<p>Pour ajouter une nouvelle commande de format, remplir l'information comme indiqu&eacute;e plus haut et cliquer sur "Ajouter Format". La nouvelle commande de Format appara&icirc;t dans la liste des  "Commandes de Format fr&eacute;quemment Assign&eacute;es". Seule une commande de format peut &ecirc;tre assign&eacute;e pour chaque combinaison caract&eacute;ristique/composante.</p>
+<p>Pour enlever une commande de format, s&eacute;lectionner-la sur la liste et cliquer "Enlever Format".</p>
+<p>Pour modifier une commande de format, s&eacute;lectionner-la  sur la liste et cliquer sur "Remplacer Format". </p>
+<p>Pour de plus amples informations sur les variables et les composantes de caract&eacute;ristiques, lire le chapitre 2 du Guide du D&eacute;veloppeur de Greenstone. </p>
+<p>Si la bo&icirc;te de v&eacute;rification "Permettre options &eacute;tendues" est coch&eacute;e, certaines options avanc&eacute;es de formatage sont activ&eacute;es. La liste des caract&eacute;ristiques pouvant &ecirc;tre format&eacute;es est l&eacute;g&egrave;rement chang&eacute;e, et plusieurs variables sont disponibles dans la commande de format, offrant un contr&ocirc;le plus grand sur la mise en forme. </p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/generalsettings.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/generalsettings.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/generalsettings.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="generalsettings"><font face="Verdana" size="5"><strong>6.2: G&eacute;n&eacute;ral</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Cette section explique comment passer en revue et changer les r&eacute;glages g&eacute;neraux associ&eacute;s &agrave; la collection. D'abord, sous "Design section" cliquer "General".</p>
+<p>Les valeurs fournies ici peuvent &ecirc;tre modifi&eacute;es au cours de la cr&eacute;ation de la collection.</p>
+<p>D'abord, les contacts E-mail du cr&eacute;ateur et mainteneur de la collection. Le champ suivant permet le changement de titre de la collection. Le dossier dans lequel est enregistr&eacute; la collection est affich&eacute; ensuite, mais ne peut &ecirc;tre &eacute;dit&eacute;. Celui qui suit sp&eacute;cifie (sous forme d'URL) l'&icirc;cone &agrave; montrer &agrave; l'extr&eacute;mit&eacute; sup&eacute;rieure gauche de la page "About" de la collection et la suivante est l'&icirc;cone utilis&eacute;e dans la page de la biblioth&eacute;que Greenstone &agrave; lier &agrave; la collection. Puis, une case permet de contr&ocirc;ler si la collection est accessible au public. Enfin, la zone texte de "la description de la Collection" comme d&eacute;crit <a href="creatingacollection.htm">Cr&eacute;er une nouvelle collection</a>.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/help.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/help.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/help.xml	(revision 13928)
@@ -0,0 +1,408 @@
+<Document>
+<Section name="introduction">
+<Title>
+<Text id="1">Introduction</Text>
+</Title>
+<Text id="2">L'interface bibliothÃ©caire de Greenstone est un outil pour collecter et enrichir des documents et ensuite mettre sur pied des collections de bibliothÃšques numÃ©riques. Il fournit un accÃšs Ã  la fonctionnalitÃ© du logiciel de la BibliothÃšque numÃ©rique de Greenstone Ã  partir d'un point de vue graphique et d'une interface "clic".</Text>
+<Section name="ofmiceandmenus">
+<Title>
+<Text id="3">Dessouris et Menus</Text>
+</Title>
+<Text id="4">La section "Dessouris et Menus" fournit une information de base sur la maniÃšre de dialoguer avec l'interface bibliothÃ©caire. Si on est familier avec des programmes comme Internet Explorer ou Microsoft Office et aussi Ã  l'aise avec les menus et les clics de la souris, passer Ã  section <Reference target="howtoavoidthisdocument"/>.</Text>
+<Text id="5">L'interface bibliothÃ©caire suit les conventions de Microsoft Windows et requiert une connaissance de base de Windows.</Text>
+<Text id="6">Une position quelconque d'interaction sur l'Ã©cran, tel qu'un bouton ou un champ de texte, est appelÃ©e "contrÃŽle". A tout moment, un contrÃŽle appelÃ© "Foyer" est mis en relief et rÃ©pond au clavier. Plusieurs contrÃŽles vous permettent de sÃ©lectionner les parties qui sont mises en relief en bleu foncÃ©. Certains contrÃŽles virent au gris pour indiquer qu'ils sont Ã©teints.</Text>
+<Text id="7">On peut dÃ©placer la souris, cliquer sur son bouton gauche (cliquer-gauche) ou sur son bouton droit (cliquer-droite) de faÃ§on tout Ã  fait usuelle. Plusieurs Ã©lÃ©ments sont susceptibles d'Ãªtre entrainÃ©s par glissement de la souris son bouton gauche Ã©tant maintenu appuyÃ©, et d'Ãªtre ainsi dÃ©posÃ©s quelque part en relÃ¢chant le bouton. Des cibles de dÃ©pÃŽt potentielles changent d'apparence quand un composant les atteint.</Text>
+<Text id="8">On peut utiliser le clavier pour la saisie Ã  l'intÃ©rieur des champs de texte. Des alternatives au clavier sont disponibles pour plusieurs contrÃŽles indiquÃ©s par un nom clÃ© entre crochets --- par exemple [Tab] change le foyer. Le signe plus indique les autres touches susceptibles d'Ãªtre appuyÃ©es en mÃªme temps.</Text>
+<Text id="9">Pour accÃ©der au menu, appuyer sur le bouton [Alt] et sur la lettre correspondante (soulignÃ©e). Par exemple, pour le menu "Fichier" appuyer sur [Alt] + [F]. Pour choisir un Ã©lÃ©ment, appuyer sur la touche correspondante. Par exemple, lorsque le menu "Fichier" est dÃ©roulÃ©, appuyer sur "S" pour sauvegarder la collection.</Text>
+<Text id="10">Les boutons, tels les menus, ont un caractÃšre soulignÃ©. Pour cliquer sur le bouton, appuyer en mÃªme temps sur [Alt] et sur le caractÃšre soulignÃ©.</Text>
+<Text id="11">Pour quitter l'Interface BibliothÃ©caire, on utilise "Sortir" du menu "Fichier". Votre collection sera d'abord sauvegardÃ©e.</Text>
+</Section>
+<Section name="howtoavoidthisdocument">
+<Title>
+<Text id="12">Comment Ã©viter de lire ce document</Text>
+</Title>
+<Text id="13">Ne pas lire l'Aide en entier! Lire juste ce qui est nÃ©cessaire pour obtenir l'aide dont on a besoin.</Text>
+<Text id="14">L'Ã©lÃ©ment de menu Aide indique l'Ã©lÃ©ment d'aide le plus appropriÃ© par une icÃŽne sous forme de petit livre. </Text>
+<Text id="15">Le positionnement de la souris sur plusieurs contrÃŽles entraÃ®ne l'apparition d'un "Tool tip" qui dit ce qu'il faut faire.</Text>
+<Text id="16">Avant d'utiliser l'Interface BibliothÃ©caire, il faut lire la documentation Greenstone. La section "CrÃ©er une Nouvelle Collection" dÃ©crit comment crÃ©er une nouvelle collection. Avant d'utiliser l'Interface BiblithÃ©caire, lire d'abord la documentation de Greenstone.</Text>
+</Section>
+</Section>
+<Section name="startingoff">
+<Title>
+<Text id="17">DÃ©marrage</Text>
+</Title>
+<Text id="18">Cette section explique comment crÃ©er, charger, enregistrer et supprimer des collections.</Text>
+<Section name="creatingacollection">
+<Title>
+<Text id="19">CrÃ©er une nouvelle collection</Text>
+</Title>
+<Text id="20">Pour crÃ©er la nouvelle collection, ouvrir le menu "Fichier" et choisir "Nouveau". Plusieurs champs doivent Ãªtre remplis -- mais leurs valeurs sont susceptibles d'Ãªtre modifiÃ©es Ã  souhait dans l'affichage de la conception.</Text>
+<Text id="21">"Titre de la collection" est le texte affichÃ© en haut de la page d'accueil de votre collection. Sa longueur peut Ãªtre quelconque.</Text>
+<Text id="22">"Description du contenu" doit dÃ©crire avec le plus de dÃ©tails possibles ce que la collection est. Utiliser la touche [EntrÃ©e] pour la diviser en paragraphes.</Text>
+<Text id="23">On doit enfin spÃ©cifier soit que la nouvelle collection aura la mÃªme forme et les mÃªmes jeux de mÃ©ta-donnÃ©es que la collection existante, soit qu'elle est initiÃ©e  "Nouvelle collection" par dÃ©faut.</Text>
+<Text id="24">Cliquer sur "OK" pour crÃ©er la collection. Si on choisit "Nouvelle collection", les jeux de mÃ©ta-donnÃ©es disponibles sont affichÃ©es. On peut en choisir plus d'une et en ajouter d'autres ultÃ©rieurement.</Text>
+<Text id="25">Le clic sur "Annuler" ramÃšne immÃ©diatement l'Ã©cran principal.</Text>
+</Section>
+<Section name="savingacollection">
+<Title>
+<Text id="26">Enregistrer la Collection</Text>
+</Title>
+<Text id="27">Enregistrer rÃ©guliÃšrement votre travail en choisissant "Enregistrer" dans le fichier "Menu". Enregistrer une collection ne signifie pas la rendre prÃªte Ã  l'utilisation dans Greenstone (voir <Reference target="producingthecollection"/>).</Text>
+<Text id="28">L'Interface BiblithÃ©caire protÃšge votre travail en l'enregistrant Ã  la fermeture du programme ou Ã  l'ouverture d'une autre collection.</Text>
+<Text id="29">Les collections sont enregistrÃ©es en un fichier choisi pour la collection avec une extension ".col", localisÃ© dans un rÃ©pertoire de mÃªme nom Ã  l'intÃ©rieur du dossier "collect" de l'installation de Greenstone.</Text>
+</Section>
+<Section name="openingacollection">
+<Title>
+<Text id="30">Ouvrir une collection existante</Text>
+</Title>
+<Text id="31">Pour ouvrir une collection existante, choisir "ouvrir" Ã  partir du menu "Fichier" pour obtenir le "PrÃªt Ã  l'ouverture de la collection". Une liste de vos collections Greenstone apparaÃ®t. En sÃ©lectionner une pour voir sa description, et cliquer sur "Ouvrir" pour la charger. Si l'on cherche une collection qui est hors du dossier "Collect" de Greenstone, cliquer sur "Parcourir" pour un dialogue avec le systÃšme de fichiers concernÃ©.</Text>
+<Text id="32">Dans le cas oÃ¹ plusieurs programmes d'Interface BibliothÃ©caire de Greenstone sont exÃ©cutÃ©s simultanÃ©ment, les rÃ©pertoires concernÃ©s sont vÃ©rouillÃ©s pour prÃ©venir une interfÃ©rence. A l'ouverture d'une collection, un petit fichier de verrouillage temporaire est crÃ©Ã© dans son dossier. Avant d'ouvrir une collection, l'interface BibliothÃ©caire vÃ©rifie qu'aucun fichier de verrouillage n'existe dÃ©jÃ . Le verrouillage d'une collection est indiquÃ© par la couleur de son icÃŽne: verte pour une collection normale, rouge quand elle est vÃ©rouillÃ©e. Cependant, quand l'on quitte l'Interface BibliothÃ©caire prÃ©maturÃ©ment, le fichier de verrouillage est parfois laissÃ© en place. Quand une telle collection est ouverte, l'Interface BibliothÃ©caire demande si l'on veut se dÃ©faire de son contrÃŽle. Ne jamais sosutraire une collection en cours d'utilisation par un autre.</Text>
+<Text id="33">Lorsque vous ouvrez une collection qui n'a pas Ã©tÃ© crÃ©Ã©e par Greenstone Librarian Interface, on vous demande de sÃ©lectionner un ou plusieurs jeux de mÃ©ta-donnÃ©es. Si vous n'en sÃ©lectionnez aucun, les mÃ©ta-donnÃ©es existantes seront ignorÃ©es. Dans le cas contraire, les mÃ©ta-donnÃ©es seront importÃ©es comme lorsque vous cliquez et glisser dans des fichiers contenant des mÃ©ta-donnÃ©es. Ce processus est dÃ©crit dans la section <Reference target="importingpreviouslyassignedmetadata"/>.</Text>
+</Section>
+<Section name="deletingcollections">
+<Title>
+<Text id="34">Suppression des collections</Text>
+</Title>
+<Text id="35">Pour supprimer dÃ©finitivement des collections de votre installation Greenstone, choisir "Supprimer..." dans le menu "Fichier". Une liste de vos collections Greenstone apparaÃ®t. Selectionner une collection pour vior sa description, puis cocher la case en bas du dialogue et clicquez "Supprimer" pour supprimer la collection. Cette operation est irrÃ©versible, vÃ©rifiez bien que vous n'avez plus besoin de cette collection avant de supprimer!</Text>
+</Section>
+</Section>
+<Section name="downloadingfiles">
+<Title>
+<Text id="36">TÃ©lÃ©chargement de fichiers de lIinternet</Text>
+</Title>
+<Text id="37">La vue "TÃ©lÃ©chargement" vous permet de tÃ©lÃ©charger des resources de l'internet. Cette section explique le processus de miroir de l'interface bibliothÃ©caire.</Text>
+<Section name="themirrorview">
+<Title>
+<Text id="38">La vue TÃ©lÃ©chargement</Text>
+</Title>
+<Text id="39">Cette section dÃ©crit comment on configure une tache de tÃ©lÃ©chargement et comment on contrÃŽle le tÃ©lÃ©chargement. AccÃ©dez Ã  la vue "TÃ©lÃ©chargement" en cliquant son index. La moitiÃ© supÃ©rieure de l'Ã©cran montre le contrÃŽle des tÃ©lÃ©chargements. La moitiÃ© infÃ©rieure est initialement vide, mais montrera la liste des tÃ©lÃ©chargements en attente et rÃ©alisÃ©s.</Text>
+<Text id="40">Les fichiers sont tÃ©lÃ©chargÃ©s dans un dossier de l'espace de travail appelÃ© Â«Â Fichiers TÃ©lÃ©chargÃ©sÂ Â», et peut Ãªtre utilisÃ© pour toutes les collections construites avec l'interface bibliothÃ©caire. Les fichiers dans cette zone portent comme nom leur URL en entier. Un nouveau dossier est crÃ©Ã© pour chaque site hÃŽte, suivi par d'autres dossiers pour chaque Ã©lÃ©ment du chemin. Cela permet de s'assurer que chaque fichier a un nom distinct.</Text>
+<Text id="41">Utilisez le premier des contrÃŽles de la configuration de tÃ©lÃ©chargement, Â« Source URL Â», pour entrer l'URL de la ressource cible. Utilisez le contrÃŽle Â« Profondeur de TÃ©lÃ©chargement Â»  pour limiter le nombre de liens hypertextes Ã  suivre pour le tÃ©lÃ©chargement : utiliser 0 pour tÃ©lÃ©charger une seule page ; utiliser 1 pour tÃ©lÃ©charger la page et toutes les pages rÃ©fÃ©rencÃ©es par des liens hypertextes. La profondeur limite est ignorÃ©e lors du tÃ©lÃ©chargement de mÃ©dia autres que des pages html. Ensuite il y a plusieurs cases Ã  cocher qui peuvent Ãªtre cochÃ©es pour activer l'option spÃ©cifiÃ©e. Une fois la configuration prÃªte, cliquez Â« TÃ©lÃ©charger Â» pour dÃ©marrer l'opÃ©ration de tÃ©lÃ©chargement. Il y a deux autres boutons de contrÃŽle : Â« PrÃ©fÃ©rences Â», qui renvoie Ã  la section connexion de PrÃ©fÃ©rences ou les paramÃštre du proxy peuvent Ãªtre Ã©ditÃ©s ; et Â« Effacer la cache Â» qui supprimes tous les fichiers tÃ©lÃ©chargÃ©s prÃ©cÃ©demment.</Text>
+<Text id="42">La liste de tÃ©lÃ©chargement a une entrÃ©e pour chaque tÃ©lÃ©chargement de page Web.  Chaque entrÃ©e a une rÃ©gion de textes qui donne les dÃ©tails de la tÃ¢che avec une barre de progrÃšs montrant l'activitÃ© courante.  Trois boutons apparaissent Ã  la gauche de chaque entrÃ©e.  "Pause" est employÃ© pour pauser une tÃ¢che en cours de tÃ©lÃ©chargement.  "Voir le rÃ©sumÃ©" ouvre une fenÃªtre montrant l'historique du tÃ©lÃ©chargement.  "Fermer" termine le tÃ©lÃ©chargement et enlÃšve la tÃ¢che de la liste.</Text>
+<Text id="43">La section <Reference target="preferences"/> explique comment Ã©tablir une connection Internet Ã  travers un proxy.  Si l'authentification est nÃ©cessaire, le proxy server demande l'identification et le mot de passe.  L'interface bibliothÃ©caire n'enregistre pas les mots de passe entre les sessions.</Text>
+</Section>
+</Section>
+<Section name="collectingfiles">
+<Title>
+<Text id="44">Collecter les fichiers pour la Collection</Text>
+</Title>
+<Text id="45">DÃšs lors que l'on dispose d'une nouvelle collection, la nÃ©cessitÃ© se fait sentir de la doter de fichiers. Ils peuvent provenir de votre espace fichier ordinaire ou d'autres collections Greenstone. Quelques uns peuvent avoir des mÃ©ta-donnÃ©es attachÃ©es.Cette section dÃ©crit comment importer des fichiers.</Text>
+<Section name="thegatherview">
+<Title>
+<Text id="46">L'affichage Rassembler</Text>
+</Title>
+<Text id="47">cette section introduit la zone Rassembler utilisÃ©e pour selectionner les fichiers Ã  inclure dans la collection Ã  crÃ©er. L'Interface BibliothÃ©caire dÃ©marre avec l'affichage "Rassembler". Pour revenir ultÃ©rieurement Ã  celui-ci, cliquer directement sur l'onglet "Rassembler" au bas de la barre des menus.</Text>
+<Text id="48">Les deux vastes zones intitulÃ©es "Espace de travail" et "Collection" servent au transfert des fichiers vers la collection. Elles contiennent des arborescences de fichiers, des structures graphiques qui reprÃ©sentent des fichiers et des dossiers.</Text>
+<Text id="49">Choisir un Ã©lÃ©ment dans l'arborescence en cliquant dessus. (d'autres maniÃšres de le faire existent; voir ci-dessous). Double-cliquer sur un dossier, ou cliquer simplement sur le symbole de commutateur placÃ© Ã  cÃŽtÃ© de lui, pour dÃ©velopper (ou rÃ©duire) son contenu. Double-cliquer sur un fichier pour l'ouvrir en utilisant un programme d'application associÃ© (voir <Reference target="fileassociations"/>).</Text>
+<Text id="50">L'arbre des fichiers de l'espace de travail montre les sources de donnÃ©es disponibles pour l'interface bibliothÃ©caire -- le systÃšme de fichiers local (ainsi que les unitÃ©s de disques et Cd-rom), le contenu des collection Greenstone, et la cache des fichiers tÃ©lÃ©chargÃ©s. Vous pouvez copier et afficher ces fichiers mais vous ne pouvez pas les dÃ©placer, supprimer ou Ã©diter, Ã  l'exception des fichiers tÃ©lÃ©chargÃ©s qui peuvent Ãªtre supprimÃ©. Vous pouvez naviguer Ã  l'intÃ©rieur de cet espace pour trouver les documents que vous souhaitez ajouter Ã  la collection.</Text>
+<Text id="51">L'arborescence des fichiers de la Collection ne reprÃ©sente jusque-lÃ  que le contenu de la collection. Elle est initialement vide.</Text>
+<Text id="52">On peut redimensionner les espaces en positionnant la souris sur la barre grise qui sÃ©pare les arborescences (le pointeur change de forme) et en la faisant glisser.</Text>
+<Text id="53">En bas de la fenÃªtre, il y a une barre d'Ã©tat qui montre l'Ã©volution des opÃ©rations sur les fichiers (copie, dÃ©placement et suppression). Ces opÃ©rations peuvent Ãªtre longues. Le bouton "Stop" arrÃªte toute tÃ¢che en cours.</Text>
+<Text id="54">Deux grands boutons occupent le coin droit infÃ©rieur de l'Ã©cran. "Nouveau dossier", avec une image d'un dossier, crÃ©e de nouveaux dossiers (voir <Reference target="creatingfolders"/>). "Supprimer", avec une corbeille, supprime les fichiers. Cliquer sur le bouton "Supprimer" dÃ©truit tous les fichiers sÃ©lectionnÃ©s de l'arborescence de fichiers de la collection. On peut de mÃªme rÃ©aliser cette suppression de fichiers en les faisant glisser jusqu'au bouton "Supprimer". </Text>
+<Text id="55">Pour sÃ©lectionner plusieurs sÃ©quences d'Ã©lÃ©ments, sÃ©lectionner le premier, maintenir appuyÃ©e la touche [Maj] et cliquer sur le dernier Ã©lÃ©ment de la sÃ©quence -- la sÃ©lection comprendra tous les Ã©lÃ©ments compris entre les deux. Pour la sÃ©lection de fichiers qui ne se suivent pas, maintenir la touche [Ctrl] appuyÃ©e en cliquant sur chacun d'eux. Ces deux mÃ©thodes peuvent Ãªtre utilisÃ©es ensemble pour la sÃ©lection de jeux d'Ã©lÃ©ments non adjacents.</Text>
+<Text id="56">Certains dossiers -- tel que celui contenant vos propres pages Web -- ont parfois une signification spÃ©ciale. L'Interface BibliothÃ©caire peut appliquer de tels dossiers au premier niveau de l'arborescence de fichiers. Pour ce faire double-cliquer droite sur le dossier visÃ©. Choisir "CrÃ©er un Raccourci", saisir le nom du dossier. Pour enlever un Ã©lÃ©ment, cliquer-droite sur le fichier concernÃ© et sÃ©lectionner "Supprimer Raccourci".</Text>
+</Section>
+<Section name="creatingfolders">
+<Title>
+<Text id="57">CrÃ©er des dossiers</Text>
+</Title>
+<Text id="58">Utiliser les dossiers de l'arborescence de fichiers de la collection pour rejeur les fichiers et les rendre aisÃ©ment accessibles. Des dossiers peuvent Ãªtre placÃ©s Ã  l'intÃ©rieur d'autres dossiers. Aucune limite, virtuellement parlant, ni au nombre de dossiers dont on peut disposer ni Ã  la complexitÃ© de leur agencement.</Text>
+<Text id="59">Pour crÃ©er un nouveau dossier, on peut opter pour un dossier existant et cliquer sur le bouton Nouveau Dossier. Le nouveau dossier apparaÃ®t Ã  l'intÃ©rieur de celui choisi, ou au niveau supÃ©rieur si aucun n'est choisi. Le nom de ce dossier est rÃ©clamÃ© ( Ã  dÃ©faut, il sera nommÃ© "Nouveau Dossier").</Text>
+<Text id="60">Les dossiers peuvent aussi Ãªtre crÃ©Ã©s en cliquant sur le dossier avec le bouton droit, et en choisissant "Nouveau Dossier" et procÃ©der comme ci-dessus.</Text>
+</Section>
+<Section name="addingfiles">
+<Title>
+<Text id="61">Ajouter des fichiers</Text>
+</Title>
+<Text id="62">Les fichiers peuvent Ãªtre copiÃ©s dans la collection par glisser-dÃ©placer. Le pointeur Ã©pouse la forme de l'Ã©lÃ©ment sÃ©lectionnÃ© (ou, si la sÃ©lection comprend plus d'un, leur nombre). DÃ©poser la sÃ©lection dans l'arborescence de la collection pour les y copier (si la source est l'arborescence de l'espace de travail) ou les dÃ©placer Ã  l'intÃ©rieur de la collection (si la source est l'arborescence de la collection).</Text>
+<Text id="63">Lorsque des fichiers multiples sont copiÃ©s, ils sont tous placÃ© dans le dossier cible au mÃªme niveau, quelle que soit la structure du dossier qui les contenait avant. Si vous copier un second fichier avec le mÃªme nom dans le mÃªme dossier, la question de savoir si le premier fichier doit Ãªtre Ã©crasÃ© est posÃ©e. Si la rÃ©ponse est non, le fichier ne sera pas copiÃ©, mais les autres le seront. Pour annuler toutes les autre tÃ¢ches de copie, cliquer sur le bouton "Stop".</Text>
+<Text id="64">Seuls les Ã©lÃ©ments situÃ©s au-dessus dans la sÃ©lection sont dÃ©placÃ©s. Un dossier est plus Ã©levÃ© que son contenu. On ne peut sÃ©lectionner en mÃªme temps l'intÃ©rieur d'un dossier et le dossier lui-mÃªme.</Text>
+<Text id="65">Lorsqu'un fichier est ajoutÃ©, l'Interface BibliothÃ©caire cherche les dossiers sources de fichiers auxiliaires contenant une mÃ©ta-donnÃ©e qui lui originellement assignÃ©es et, s'il en trouve, commence Ã  les importer. Au fur et Ã  mesure que l'opÃ©ration se poursuit, une confirmation est faite (peut-Ãªtre plusieurs fois) de fournir des informations complÃ©mentaires pour ajuster la mÃ©ta-donnÃ©e aux jeux de mÃ©ta-donnÃ©es de la collection. Ces confirmations sont dÃ©crites dans la section <Reference target="importingpreviouslyassignedmetadata"/>. Pour une explication plus dÃ©taillÃ©e de l'association de mÃ©ta-donnÃ©es avec les fichiers, lire le chapitre 2 du Guide de dÃ©veloppement de Greenstone -- "Exploitez vos documents au maximum".</Text>
+</Section>
+<Section name="removingfiles">
+<Title>
+<Text id="66">Supprimer des Fichiers</Text>
+</Title>
+<Text id="67">Il existe plusieurs mÃ©thodes pour supprimer des fichiers et des dossiers. On doit d'abord indiquer les Ã©lÃ©ments Ã  supprimer en sÃ©lectionnant un ou plusieurs fichiers et dossiers comme dÃ©crit dans <Reference target="thegatherview"/>.</Text>
+<Text id="68">DÃšs lors que les fichiers sont sÃ©lectionnÃ©s, cliquer sur le bouton "Supprimer" pour les dÃ©truire, ou appuyer sur la touche [Delete] de votre clavier, ou les glisser-dÃ©placer de la collection vers le bouton "Supprimer" et les y dÃ©poser.</Text>
+</Section>
+<Section name="filteringthetree">
+<Title>
+<Text id="69">Filtrer l'arborescence</Text>
+</Title>
+<Text id="70">Le "Filtrage" de l'arborescence de la collection permet de rÃ©duire la recherche de fichiers particuliers.</Text>
+<Text id="71">Le menu dÃ©roulant des "Montrer Fichiers" ("Show Files") au bas de chaque arborescence montre une liste de filtres prÃ©dÃ©finis, tels "Images". Son choix cache temporairement tous les autres fichiers de l'arborescence. Pour restorer celle-ci, changer le filtre en "Tous Fichiers". Ces opÃ©rations n'altÃšrent ni la collection, ni n'affectent les dossiers dans l'arborescence.</Text>
+<Text id="72">On peut spÃ©cifier un filtre usuel en saisissant un modÃšle assorti aux fichiers visÃ©s (systÃšmes Librairiens SpÃ©cialistes et modes Experts seulement). Utiliser un systÃšme standard d'abrÃ©viations de fichiers telles que "*.*" ou "*.doc" (*. concerne tous les caractÃšres).</Text>
+</Section>
+</Section>
+<Section name="enrichingacollection">
+<Title>
+<Text id="73">Enrichir la Collection avec des mÃ©ta-donnÃ©es</Text>
+</Title>
+<Text id="74">AprÃšs avoir rassemblÃ© plusieurs fichiers dans la collection, on les enrichit d'une information complÃ©mentaire appelÃ©e "mÃ©ta-donnÃ©e". Cette section explique comment une mÃ©tadonnÃ©e est crÃ©Ã©e, Ã©ditÃ©e, assignÃ©e ou retirÃ©e, et comment utiliser les sources de mÃ©ta-donnÃ©es externes (voir aussi le chapitre 2 du Guide de dÃ©veloppement de Greenstone -- "Exploitez vos documents au maximum").</Text>
+<Section name="theenrichview">
+<Title>
+<Text id="75">L'affichage Enrichir</Text>
+</Title>
+<Text id="76">Utiliser l'affichage Enrichir pour assigner une mÃ©ta-donnÃ©e aux documents de la collection. Une mÃ©ta-donnÃ©e est une donnÃ©e sur une donnÃ©e -- de faÃ§on typique titre, auteur, date de crÃ©ation, et ainsi de suite. Chaque Ã©lÃ©ment de mÃ©ta-donnÃ©e a deux parties: "elÃ©ment" indique le type d'Ã©lÃ©ment (par exemple auteur), "valeur" qui donne la valeur de cette mÃ©ta-donnÃ©e Ã©lÃ©ment (par exemple le nom de l'auteur).</Text>
+<Text id="77">Sur la gauche de l'affichage "Enrichir" est l'arborescence de la collection. A sa droite, la Table de MÃ©ta-donnÃ©es, qui montre les mÃ©ta-donnÃ©es pour tous les fichiers et dossiers sÃ©lectionnÃ©es de l'arborescence de la collection. Les colonnes sont indiquÃ©es en gris en haut, et peuvent Ãªtre redimensionnÃ©es en faisant glisser la ligne de sÃ©paration. Si plusieurs fichiers sont sÃ©lectionnÃ©s, un texte en noir indique que la valeur est commune Ã  tous les fichiers sÃ©lectionnÃ©s, tandis qu'un texte en gris en indique le contraire. les valeurs en noir peuvent Ãªtre mises Ã  jour ou supprimÃ©es, tandis que celles en gris peuvent Ãªtre supprimÃ©es de ceux qui l'ont, ou ajoutÃ©es aux autres.</Text>
+<Text id="78">Une icÃŽne de dossier peut apparaÃ®tre Ã  cÃŽtÃ© de certaines entrÃ©es de mÃ©ta-donnÃ©es. Ceci indique que les valeurs ont Ã©tÃ© hÃ©ritÃ©es d'un dossier parent. Les mÃ©ta-donnÃ©es hÃ©ritÃ©es ne peuvent Ãªtre Ã©ditÃ©es ou supprimÃ©es, mais seulement ajoutÃ©es ou Ã©crasÃ©es. Cliquer sur l'icÃŽne du dossier pour aller immÃ©diatement au dossier oÃ¹ la mÃ©ta-donnÃ©e est assignÃ©e.</Text>
+<Text id="79">Si vous cliquez sur un l'Ã©lÃ©ment de metadata du tableau, celui-ci affichera les valeurs existantes pour l' Ã©lÃ©ment dans le domaine "Valeurs existantes pour..." en dessous du tableau. Celle-ci, dÃ©veloppe et comprime. C'est une liste qui, de faÃ§on usuelle, montre toutes les valeurs prÃ©cÃ©demment saisies pour un Ã©lÃ©ment sÃ©lectionnÃ©. Le clic sur une entrÃ©e la place automatiquement dans le champ valeur. Inversement, la saisie dans le champ texte sÃ©lectionne l'entrÃ©e de l'Arborescence Valeur qui dÃ©bute avec les caractÃšres saisis. Appuyer sur [Tab] complÃšte automatiquement la saisie de la valeur sÃ©lectionnÃ©e.</Text>
+<Text id="80">Les valeurs de mÃ©ta-donnÃ©e peuvent Ãªtre organisÃ©es en une hiÃ©rarchie.Ceci est montrÃ© dans l'Arborescence Valeur utilisant des dossiers de niveau interne. Les valeurs hiÃ©rarchiques peuvent Ãªtre saisies en utilisant le caractÃšre "|" pour sÃ©parer les niveaux. Par exemple, "Cards|Red|Diamonds|Seven" peut Ãªtre utilisÃ© dans une hiÃ©rarchie qui reprÃ©sente un jeu de cartes. Cela permet le rejeument des valeurs. Les jeux peuvent aussi Ãªtrre assignÃ©s comme mÃ©ta-donnÃ©e.</Text>
+<Text id="81">Greenstone extrait automatiquement des mÃ©ta-donnÃ©es Ã  partir des documents en un jeu de mÃ©ta-donnÃ©es dont les Ã©lÃ©ments sont prÃ©fixÃ©s "ex.". Ceci n'a aucune valeur et ne peut Ãªtre Ã©ditÃ©.</Text>
+</Section>
+<Section name="selectingmetadatasets">
+<Title>
+<Text id="82">SÃ©lectionner les jeux de mÃ©ta-donnÃ©es</Text>
+</Title>
+<Text id="83">Les sÃ©ries d'Ã©lÃ©ments de mÃ©ta-donnÃ©es prÃ©dÃ©finis sont connus comme "jeux de MÃ©ta-donnÃ©es". "Dublin Core" en est un exemple. Quand on ajoute un Groupe de MÃ©ta-donnÃ©es Ã  la collection, ses Ã©lÃ©ments peuvent Ãªtre sÃ©lectionnÃ©s. On peut avoir plus d'un jeu de mÃ©ta-donnÃ©es ; pour Ã©viter des tÃ©lescopages de nom, un identificateur abrÃ©gÃ© qui identifie le jeu de mÃ©ta-donnÃ©es est suspendu au nom de l'Ã©lÃ©ment. Par exemple l'Ã©lement crÃ©ateur de Dublin Core devient "dc.Creator". Les jeux de mÃ©ta-donnÃ©es sont sauvÃ©gardÃ©s dans le dossier de mÃ©ta-donnÃ©es de l'Interface BibliothÃ©caire et ont le sufixe ".mds".</Text>
+<Text id="84">Pour contrÃŽler les jeux de mÃ©ta-donnÃ©es utilisÃ©s dans une collection, utilisez l'entrÃ©e "Jeux MÃ©ta-DonnÃ©es" sur la vue "Conception".</Text>
+</Section>
+<Section name="appendingmetadata">
+<Title>
+<Text id="85">Ajout de Nouvelles MÃ©ta-donnÃ©es</Text>
+</Title>
+<Text id="86">On ajoute un Ã©lÃ©ment mÃ©ta-donnÃ©e -- Ã©lÃ©ment et valeur Ã  la fois -- Ã  un fichier. SÃ©lectionner d'abord le fichier Ã  partir de l'arborescence de fichier de la collection situÃ©e Ã  gauche. Cette action entraÃ®ne l'apparition de toute mÃ©ta-donnÃ©e prÃ©-assignÃ©e  dans le tableau de droite. </Text>
+<Text id="87">SÃ©lectionner ensuite l'Ã©lÃ©ment mÃ©ta-donnÃ©e Ã  ajouter en cliquant sur sa rangÃ©e dans le tableau.</Text>
+<Text id="88">Taper la valeur dans le champ valeur. Utilisez le charactÃšre "|" pour rapporter une structure, comme dÃ©crit dans <Reference reference="theenrichview">The Enrich View</Reference>. Vous pouvez sauver l' information metadata en pressant les touches [Up] ou [Down] et bouger ainsi la sÃ©lection convenablement. En pressant la touche [Enter] l'information metadata sera sauvÃ©e et une nouvelle entrÃ©e vide sera crÃ©Ã©e pour l' Ã©lÃ©ment metadata, vous permettant dÃ©signer multiples valeurs pour un Ã©lÃ©ment de metadata.</Text>
+<Text id="89">Vous pouvez aussi ajouter des mÃ©ta-donnÃ©es Ã  un dossier, ou Ã  plusieurs fichiers sÃ©lectionnÃ©s Ã  la fois. Elle est ajoutÃ©e Ã  tous les fichiers ou Ã  l'intÃ©rieur du dossier ou de la sÃ©lÃ©ction, et aux sous-dossiers. Garder Ã  l'esprit  que si des mÃ©ta-donnÃ©es sont ajoutÃ©es Ã  un dossier tous les nouveaux fichiers en son sein hÃ©rite automatiquement des valeurs du dossier.</Text>
+</Section>
+<Section name="addingpreviouslydefinedmetadata">
+<Title>
+<Text id="90">Ajouter des MÃ©ta-donnÃ©es prÃ©dÃ©finies</Text>
+</Title>
+<Text id="91">Pour ajouter une mÃ©ta-donnÃ©e ayant une valeur existante, sÃ©lectionner d'abord le fichier, et ensuite la valeur requise Ã  partir de l'arborescence des valeurs, en dÃ©veloppant si nÃ©cessaire les dossiers de hiÃ©rarchie. La valeur de l'entrÃ©e sÃ©lectionnÃ©e apparaÃ®t automatiquement dans le champ texte Valeur. (Utiliser alternativement la valeur auto-select de l'arborescence et les caractÃ©ristiques auto-complÃštes. </Text>
+<Text id="92">La procÃ©dure d'ajouter mÃ©ta-donnÃ©es avec des valeurs dÃ©jÃ  existantes aux dossiers ou aux fichiers multiples est tout Ã  fait identique.</Text>
+</Section>
+<Section name="updatingmetadata">
+<Title>
+<Text id="93">Editant ou Ãliminant MÃ©ta-donnÃ©es</Text>
+</Title>
+<Text id="94">Pour Ã©diter ou Ã©liminer une partie de metadata, premiÃšrement selectionnez un fichier convenable, en suite la valeur de la metadata du tableau. Editer la valeur de champ supprimant tout le texte si vous dÃ©sirez Ã©liminer la metadata.</Text>
+<Text id="95">Le processus est identique pour la mise Ã  jour d'un dossier avec des sous-dossiers ou plusieurs fichiers, mais vous pouvez seulement mettre Ã  jour les mÃ©ta-donnÃ©es qui sont communes Ã  tous les fichiers/dossiers sÃ©lectionnÃ©s.</Text>
+<Text id="96">L' arbre de valeurs montre toutes les valeurs actuellement assignÃ©es de mÃªme que les valeurs prÃ©cÃ©dentes pour la prÃ©sente session, toutes les valeurs Ã©ditÃ©s ou Ã©liminÃ©e seront donc prÃ©sentes dans l' arbre. Fermant la collection et la ouvrant encore une fois Ã©liminera les valeurs qui ne sont plus dÃ©signÃ©es.</Text>
+</Section>
+<Section name="reviewingmetadata">
+<Title>
+<Text id="97">Passer en revue les MÃ©ta-donnÃ©es assignÃ©es</Text>
+</Title>
+<Text id="98">On Ã©prouve parfois le besoin de voir, Ã  la fois, les mÃ©ta-donnÃ©es affectÃ©es Ã  plusieurs ou Ã  tous les fichiers -- par exemple, pour dÃ©terminer combien de fichiers sont en cours d'utilisation ou pour avoir une idÃ©e de la chronologie. </Text>
+<Text id="99">SÃ©lectionnez les fichiers que vous souhaitez examiner, puis clicquez sur le bouton droit et choisissez "MÃ©ta-donnÃ©es AssociÃ©es...". Une fenÃªtre appelÃ©e "Toutes les MÃ©ta-donnÃ©es", sous forme d'un grand tableau avec plusieurs colonnes, apparaÃ®t. La premiÃšre colonne montre les noms de fichiers; les lignes montrent toutes les valeurs de mÃ©ta-donnÃ©es assignÃ©es Ã  ces fichiers.</Text>
+<Text id="100">Dessiner le tableau peut prendre quelque temps si plusieurs fichiers sont sÃ©lectionnÃ©s. On peut continuer Ã  utiliser l'Interface BibliothÃ©caire pendant que la fenÃªtre "Toutes MÃ©ta-donnÃ©es" est ouverte.</Text>
+<Text id="101">Quand il devient trop large, on peut filtrer le tableau "Toutes MÃ©ta-donnÃ©es" en appliquant des filtres aux colonnes. Alors que de nouveaux filtres sont ajoutÃ©s, seules les lignes qui concernent restent visibles. Pour installer, modifier ou effacer un filtre, cliquez sur l'Ã®cone "Funnel" situÃ© en haut de la colonne. Une information sur le filtre est rÃ©clamÃ©e. Une fois le filtre installÃ©, l'en-tÃªte de la colonne change de couleur.</Text>
+<Text id="102">La confirmation possÃšde un onglet "simple" et " advancÃ©". La version simple filtre  les colonnes afin qu'elles ne montrent que des lignes qui contiennent une certaine valeur de mÃ©ta-donnÃ©e ("*" concerne toutes les valeurs). On peut sÃ©lectionner des valeurs de mÃ©ta-donnÃ©es Ã  partir d'une liste dÃ©roulante. La version advancÃ©e permet diffÃ©rentes opÃ©rations d'harmonisation: doit commencer avec, ne contient pas, alphabÃ©tiquement et est Ã©gal Ã . La valeur Ã  harmoniser peut Ãªtre Ã©ditÃ©e et prise sous forme d'une chaÃ®ne quelconque (y compris "*"), et on peut opter pour une harmonisation insensible aux caractÃšres. Enfin, on peut spÃ©cifier une deuxiÃšme condition d'harmonisation prÃ©cisant une gamme de valeurs (en sÃ©lectionnant AND) ou des valeurs alternatives (en selectionnant OR). En dessous de cette zone, une boÃ®te qui permet de changer l'ordre de tri (ascendant ou descendant) est placÃ©e. Enfin, cliquer sur "Installer Filtre" pour appliquer le nouveau filtre Ã  la colonne. Cliquer sur "Effacer Filtre" pour enlever le filtre courant. Notez que les dÃ©tails du filtre sont retenus mÃªme si le filtre est effacÃ©.</Text>
+<Text id="103">Par exemple, pour trier le tableau "Toutes MÃ©ta-donnÃ©es" , choisir une colonne, sÃ©lectionner le cadre du filtre par dÃ©faut (Un filtre simple sur "*") et choisir un ordre ascendant ou descendant.</Text>
+</Section>
+<Section name="importingpreviouslyassignedmetadata">
+<Title>
+<Text id="104">Importer des MÃ©ta-donnÃ©es PrÃ©-assignÃ©es</Text>
+</Title>
+<Text id="105">Cette section explique comment importer des mÃ©ta-donnÃ©es affectÃ©es prÃ©cÃ©demment; mÃ©ta-donnÃ©es affectÃ©es avant d'Ãªtre ajoutÃ©es Ã  la collection.</Text>
+<Text id="106">Si la mÃ©ta-donnÃ©e dans une forme reconnue par l'Interface BibliothÃ©caire a Ã©tÃ© prÃ©alablement assignÃ©e Ã  un fichier, -- par exemple, quand on choisit des documents dans une collection Greenstone existante -- elle est importÃ©e automatiquement quand on ajoute le fichier. Pour ce faire, la mÃ©ta-donnÃ©e doit Ãªtre ajustÃ©e au jeu de mÃ©ta-donnÃ©es disponibles dans la collection.</Text>
+<Text id="107">L'Interface BibliothÃ©caire confirme l'information nÃ©cessaire. confirmation sous forme d'instructions brÃšves et qui montre ensuite le nom de l'Ã©lÃ©ment mÃ©ta-donnÃ©e qui est importÃ©e, comme il apparaÃ®t dans le fichier source. Ce champ ne peut Ãªtre ni Ã©ditÃ© ni changÃ©. Ensuite on choisit sur quel jeu de mÃ©ta-donnÃ©e le nouveau Ã©lÃ©ment devrait Ãªtre calquÃ© et enfin l'Ã©lÃ©ment mÃ©ta-donnÃ©e appropriÃ©. Le sytÃšme selectionne automatiquement le meilleur ajustement, en terme de jeu et d'Ã©lÃ©ment pour la nouvelle mÃ©ta-donnÃ©e.</Text>
+<Text id="108">AprÃšs cela,on peut choisir "Ajouter" pour ajouter le nouvel Ã©lÃ©ment mÃ©ta-donnÃ©e au jeu de mÃ©ta-donnÃ©es choisi. (Ceci n'est possible que si aucun Ã©lement de mÃªme nom n'est prÃ©sent Ã  l'interieur du jeu choisi.) "Fusionner" applique le nouvel Ã©lement Ã  celui choisi par l'utilisateur. Enfin, "Ignorer" n'importe aucune mÃ©ta-donnÃ©e avec ce nom d'Ã©lement. Une fois prÃ©cisÃ©e la maniÃšre d'importer un certain Ã©lÃ©ment de mÃ©ta-donnÃ©e, l'information d'application est retenue pour la durÃ©e de vie de la collection.</Text>
+<Text id="109">Pour des dÃ©tails concenant les fichiers mÃ©ta-donnÃ©e.xml que Greenstone utilise pour sauvegarder les mÃ©ta-donnÃ©es, il faut vous refÃ©rer au chapitre 2 du guide du DÃ©veloppeur de Greenstone -- "Exploitez vos documents au maximum".</Text>
+</Section>
+</Section>
+<Section name="designingacollection">
+<Title>
+<Text id="110">DÃ©coration de l'apparence de votre collection</Text>
+</Title>
+<Text id="111">Une fois les fichiers marquÃ©s avec les mÃ©ta-donnÃ©es, on peut dÃ©cider comment ils devraient apparaÃ®tre aux utilisateurs comme une collection Greenstone. Quel type d'information peut Ãªtre recherchÃ©? Quels sont les moyens qui sont fournis pour naviguer Ã  travers les documents? Quels sont les langages supportÃ©s? oÃ¹ apparaissent les boutons sur la page? ces choses peuvent Ãªtre adaptÃ©es; cette section dÃ©crit comment procÃ©der.</Text>
+<Section name="thedesignview">
+<Title>
+<Text id="112">L'Affichage conception</Text>
+</Title>
+<Text id="113">Cette section prÃ©sente l'affichage de conception et explique comment on navigue entre les diffÃ©rents affichages Ã  l'intÃ©rieur de cette vitrine. </Text>
+<Text id="114">Avec l'Interface BibliothÃ©caire, on peut configurer la faÃ§on dont la collection va apparaÃ®tre Ã  l'utilisateur. Les options de configuration sont divisÃ©es en diffÃ©rentes sections, chacune associÃ©e Ã  une Ã©tape particuliÃšre de navigation ou de prÃ©sentation d'information.</Text>
+<Text id="115">Sur la gauche est placÃ©e une liste de diffÃ©rents affichages et Ã  droite les commandes associÃ©es Ã  celles en cours. Pour passer Ã  un  affichage diffÃ©rent, cliquer son nom dans la liste.</Text>
+<Text id="116">Pour comprendre les diffÃ©rentes Ã©tapes et les termes implmiquÃ©s dans la conception d'une collection, lire les chapitres 1 et 2 de Greenstone's Developer's Guide. </Text>
+</Section>
+<Section name="generalsettings">
+<Title>
+<Text id="117">GÃ©nÃ©ral</Text>
+</Title>
+<Text id="118">Cette section explique comment passer en revue et changer les rÃ©glages gÃ©neraux associÃ©s Ã  la collection. D'abord, sous "Design section" cliquer "General".</Text>
+<Text id="119">Les valeurs fournies ici peuvent Ãªtre modifiÃ©es au cours de la crÃ©ation de la collection.</Text>
+<Text id="120">D'abord, les contacts E-mail du crÃ©ateur et mainteneur de la collection. Le champ suivant permet le changement de titre de la collection. Le dossier dans lequel est enregistrÃ© la collection est affichÃ© ensuite, mais ne peut Ãªtre Ã©ditÃ©. Celui qui suit spÃ©cifie (sous forme d'URL) l'Ã®cone Ã  montrer Ã  l'extrÃ©mitÃ© supÃ©rieure gauche de la page "About" de la collection et la suivante est l'Ã®cone utilisÃ©e dans la page de la bibliothÃ©que Greenstone Ã  lier Ã  la collection. Puis, une case permet de contrÃŽler si la collection est accessible au public. Enfin, la zone texte de "la description de la Collection" comme dÃ©crit <Reference target="creatingacollection"/>.</Text>
+</Section>
+<Section name="plugins">
+<Title>
+<Text id="121">Plugiciels de Document</Text>
+</Title>
+<Text id="122">Cette section dÃ©crit comment faire la configuration des plugiciels des documents que la collection utilise. Elle explique comment spÃ©cifier les plugiciels utilisÃ©s, quels paramÃštres leur passer et dans quel ordre ils se dÃ©roulent. Sous "Sections de conception", cliquer "Plugiciels de document".</Text>
+<Text id="123">Pour ajouter un plugiciel, sÃ©lectionner-le sur la liste dÃ©roulante de "Choisir le plugiciel Ã  ajouter" situÃ©e Ã  cÃŽtÃ© du bouton et ensuite cliquer "Ajouter plugiciel". Une fenÃªtre dÃ©nommÃ©e "Configurer les arguments" apparaÃ®t; elle est dÃ©crite plus loin. Une fois la configuration du nouveau plugiciel achevÃ©e, il est ajoutÃ© Ã  la fin de la liste "Plugiciels couramment assignÃ©s". Veuillez noter que, Ã  l'exception de UnknownPlug, chaque plugin ne peut apparaÃ®tre qu'une seule fois dans la liste.</Text>
+<Text id="124">Pour enlever un plugiciel, sÃ©lectionner-le sur la liste et cliquer sur "Enlever plugiciel".</Text>
+<Text id="125">Les plugiciels sont configurÃ©s en fournissant des arguments. Pour les changer, il faut sÃ©lectionner le plugiciel Ã  partir de la liste et cliquer "Configurer plugiciel" (Ou double-cliquer sur le plugiciel). Un dialogue "Configuration des arguments" apparaÃ®t avec diffÃ©rent contÃŽles pour spÃ©cifier les arguments.</Text>
+<Text id="126">Il existe plusieurs types de contrÃŽles. Certains sont des boÃ®tes de dialogue et cliquer sur l'une ajoute l'option appropriÃ©e au plugiciel. Les autres sont des chaÃ®nes de textes avec une boÃ®te de dialogue et un champ texte. Cliquer sur la boÃ®te pour activer l'argument, ensuite saisir le texte appropriÃ© dans la boÃ®te (expression normale, chemin de fichier etc). Les autres sont des menus dÃ©roulants Ã  partir desquels on peut sÃ©lectionner Ã  partir d'une sÃ©rie de valeurs dÃ©terminÃ©es. Pour apprendre ce qu'un argument peut faire, promener la souris planer sur son nom pendant un instant une description apparaÃ®tra.</Text>
+<Text id="127">Pour changer la configuration, cliquer sur "OK" pour valider et fermer la boÃ®te de dialogue, ou "Annuler" pour fermer la boÃ®te de dialogue sans changer les arguments du plugiciel.</Text>
+<Text id="128">Les plugiciels dans la liste sont executÃ©s en ordre et l'ordre est parfois important. L' ordre des classificateurs ne peut Ãªtre changÃ© que dans la Librairie de SystÃšmes SpÃ©cialistes et modes Experts (voir <Reference target="preferences"/>).</Text>
+</Section>
+<Section name="searchtypes">
+<Title>
+<Text id="129">Types de recherche</Text>
+</Title>
+<Text id="130">cette section explique comment modifier une nouvelle caractÃ©ristique de conception dans Greenstone, Types de recherche, qui permet une recherche de champ. Les types de recherche spÃ©cifient le type d'interface de recherche Ã  fournir: formulaire, recherche par champs et/ou recherche simple. Sous "Sections de conception", cliquer sur "Types de recherche".</Text>
+<Text id="131">Lorsqu'on pÃ©nÃštre dans l'affichage Types de recherche, vÃ©rifier d'abord "Activer recherches avancÃ©es", qui active les autres contrÃŽles. Ceci change la collection Ã  utiliser un mÃ©chanisme d' indexage qui permet une recherche de champs. La spÃ©cification de l' indexe est lÃ©gÃšrement diffÃ©rente dans ce mode. (Quand Ã©changeant entre une recherche classique ou avancÃ©e, le GLI essaye de convertir la spÃ©cification de l' indexe, mais peut ne pas le faire correctement.)</Text>
+<Text id="132">pour ajouter un type de recherche, sÃ©lectionner-le Ã  partir de la liste "Types de recherche" et cliquer sur "Ajouter Type de recherche".  Chaque type n'apparaÃ®t qu'une fois sur la liste. La premiÃšre recherche sera de type dÃ©faut et apparÃªtra dans la page de recherche de la conection Ã©tablie. Tout les autres pourons Ãªtre sÃ©lectionÃ©s dans la page de prÃ©fÃ©rences.</Text>
+<Text id="133">Pour enlever un type de recherche, il faut le selectionner Ã  partir de la liste "Currently Assigned Search type" et cliquer sur "Enlever type de recheche". La liste doit contenir au moins un type de recherche.</Text>
+</Section>
+<Section name="searchindexes">
+<Title>
+<Text id="134">Index de recherche</Text>
+</Title>
+<Text id="135">Les index prÃ©cisent les parties de la collection qui doivent Ãªtre recherchÃ©es. Cette section explique comment ajouter et enlever des index et fixer un index par dÃ©faut. Sous "Sections de conception", cliquer sur "Rechercher Index".</Text>
+<Text id="136">Pour ajouter un index, taper un nom choisi dans le champ "Nom de l'Index". Selectionner les sources d'information Ã  indexer en cliquant les boÃ®tes de dialogue Ã  cÃŽtÃ© d'eux. La liste montre aussi bien tous les Ã©lÃ©ments de mÃ©ta-donnÃ©es assignÃ©s, que le texte entier. AprÃšs avoir sÃ©lectionnÃ© les sources de donnÃ©es, choisir la granularitÃ© de l'index en utilisant le menu "Au niveau". Une fois ces dÃ©tails completÃ©s, "Ajouter Index" devient actif  (Ã  moins qu'il n'ait un index existant avec les mÃªmes paramÃštres). Cliquez pour ajouter un nouvel index.</Text>
+<Text id="137">Pour Ã©diter un index, sÃ©lectionnez-le et changez les dÃ©tails de l'index, puis clicquez sur "Remplacer l'index".</Text>
+<Text id="138">Pour enlever un index, il faut le sÃ©lectionner sur la liste d'index assignÃ©s et cliquer "Enlever index". </Text>
+<Text id="139">Pour crÃ©er un indexe couvrant texte et toute metadata, cliquez sur "Ajouter Tout".</Text>
+<Text id="140">L'index par dÃ©faut, celui qui est utilisÃ© dans la page de recherche de la collection est labellÃ© parc "[Index par dÃ©faut]" dans la liste "Index assignÃ©s".</Text>
+<Text id="141">Si la recherche avancÃ©e est activÃ©e (voir Affichage des types de recherche), les contrÃŽles d'index sont diffÃ©rents. Il existe une nouvelle pseudo-source de donnÃ©es "Tous champs" qui fournit une recherche Ã  travers tous les index spÃ©cifiÃ©s Ã  la fois. Des niveaux ne sont pas assignÃ©s Ã  un index spÃ©cifique, mais s'applique Ã  tous les index: ainsi index et niveaux sont ajoutÃ©s sÃ©parement. "Ajouter Tout" crÃ©e un indexe sÃ©parÃ© pour chaque champ de metadata dans ce mode.</Text>
+<Text id="142">Le nom de chaque index sera en dÃ©faut pour le nom de source. Pour changer le nom, SÃ©lectionner un index, changer ses dÃ©tails et cliquez "Remplacer Index". </Text>
+</Section>
+<Section name="partitionindexes">
+<Title>
+<Text id="143">Index de Partition</Text>
+</Title>
+<Text id="144">Les index sont construits sur un texte particulier ou des sources MÃ©ta-donnÃ©es. L'espace de recherche peut Ãªtre plus tard contrÃŽlÃ© en morcelant l'index soit par langage ou par filtre choisi Ã  l'avance. Cette section en dÃ©crit la procÃ©dure. Sous "Sections de conception", cliquer "Index de Partition". </Text>
+<Text id="145">L'affichage "Index de Partition" possÃšde trois onglets: "DÃ©finir les Filtres", "Assigner une partition" et "Assigner des langages". Pour en savoir davantage sur les partitions, lire sur les sous collections et les sous index au chapitre 2 de Greenstone developer's guide.</Text>
+<Text id="146">La fenÃªtre des Indexes de Partition est seulement Ã©tablie dans la Librairie de SystÃšmes SpÃ©cialistes et modes Experts (voir <Reference target="preferences"/>). Notez que le nombre total de partitions gÃ©nÃ©rÃ©es est une combinaison de tous les indexes, des filtres de sous colection et des langues choisis. Deux indexes avec deux filtres de sous-collections dans deux langues donnent huit partitions d'index.</Text>
+<Section name="definefilters">
+<Title>
+<Text id="147">DÃ©finir les Filtres</Text>
+</Title>
+<Text id="148">Les filtres permettent de jeur en sous-collection tous les documents dans un index pour laquelle une valeur mÃ©ta-donnÃ©e correspond Ã  un type donnÃ©.</Text>
+<Text id="149">Pour crÃ©er un filtre, cliquer sur le bouton "DÃ©finir les Filtres" et entrer un nom pour le nouveau filtre dans le champ "Nom du filtre de  sous collection". Ensuite choisir un attribut de document Ã  faire correspondre  soit avec l'Ã©lÃ©ment de mÃ©ta-donnÃ©e soit avec le nom du fichier en question. Saisir une expression courante qu'il faut utiliser durant la correspondance. Vous pouvez choisir entre "Inclure" les documents qui correspondent au fichier ou les "Exclure". Enfin, on peut spÃ©cifier l'un quelconque des drapeaux standard PERL d'expression courante qu'il faut utiliser pour la correspondance (par exemple "i" pour les correspondances ne tenant pas compte des caractÃšres.) Pour finir, cliquez sur "Ajouter un Filtre" pour ajouter le filtre Ã  la liste "Filtres de sous collection dÃ©finis". </Text>
+<Text id="150">Pour enlever un filtre, sÃ©lectionner-le sur la liste et cliquer sur "Enlever Filtre".</Text>
+<Text id="151">Pour changer un filtre, sÃ©lectionner-le sur la liste, changer l'une quelconque des valeurs apparaissant dans les contrÃŽles d'Ã©dition et cliquer sur "Remplacer Filtre" pour valider les modifications.</Text>
+</Section>
+<Section name="assignpartitions">
+<Title>
+<Text id="152">Assigner des Partitions</Text>
+</Title>
+<Text id="153">AprÃšs avoir dÃ©fini un filtre de sous-collection, utiliser l'onglet "Assigner des Partitions" pour construire ses indexes  (ou ceux pour un jeu de filtres.) SÃ©lectionner le filtre (ou les filtres) de votre choix Ã  partir de la liste "DÃ©finir des Filtres de Sous-collection", entrer un nom pour la partition dans le champ "Nom de Partition Name", et cliquer sur "Ajouter Partition". </Text>
+<Text id="154">Pour supprimer une partition, sÃ©lectionner-la Ã  partir de la liste et cliquer sur "Enlever Partition".</Text>
+<Text id="155">Pour faire d'une partition celle par dÃ©faut, sÃ©lectionner-la Ã  partir de la liste et cliquer sur "Par DÃ©faut".</Text>
+</Section>
+<Section name="assignlanguages">
+<Title>
+<Text id="156">Assigner Langages</Text>
+</Title>
+<Text id="157">Cette section donne les dÃ©tails de la maniÃšre de restreindre les index Ã  des langages particuliers. On le fait en gÃ©nÃ©rant une partition par le biais de l'onglet "Assigner Langages" de l'Affichage "Index de Partition".</Text>
+<Text id="158">Pour ajouter un nouveau langage, dont la partition par le biais de l'onglet "Assigner langues" confÃšre un index, SÃ©lectionner le langage souhaitÃ© Ã  partir de la liste "Langage Ã  ajouter" et cliquer sur "Ajouter langue".</Text>
+<Text id="159">Pour supprimer une langue, sÃ©lectionner-la Ã  partir de la liste "SÃ©lection de Langage" et cliquer sur "Enlever Langage". </Text>
+<Text id="160">Pour installer un language par dÃ©faut, sÃ©lectionner-la dans la liste et cliquez sur "Par dÃ©faut".</Text>
+</Section>
+</Section>
+<Section name="xcollectionsearching">
+<Title>
+<Text id="161">Recherches Ã  travers collections</Text>
+</Title>
+<Text id="162">Greenstone peut rechercher dans plusieurs collections comme si elles n'en constituaient qu'une. Ceci est fait en spÃ©cifiant une liste d' une autre collection Ã  rechercher au mÃªme temps que celle en recherche. Sous "Sections de conception", cliquez sur "Recherche unique Ã  travers plusieurs collections".</Text>
+<Text id="163">L'Affichage de Recherche unique Ã  travers des collections montre une liste de collections disponibles. La collection courante est cochÃ©e et ne peut Ãªtre dÃ©-sÃ©lectionnÃ©e. Pour ajouter une autre collection qu'on peut rechercher parallÃšlement, cliquer sur une collection dans la liste (cliquer une deuxiÃšme fois pour l'enlever). Lorsqu'une seule collection est sÃ©lectionnÃ©e, aucune recherche Ã  travers collections n'est possible.</Text>
+<Text id="164">Si les collections individuelles n'ont pas les mÃªmes indexes (y compris les les partitions de sous-collection et les partitions de language), la recherche ne pourra pas fonctionner. L'utilisateur ne pourra alors qu'effectuer des recherches en utilisant les indexes communs Ã  toutes les collections.</Text>
+<Text id="165">Pour plus de dÃ©tails, voir Chapitre 1 du Guide du DÃ©veloppeur Greenstone.</Text>
+</Section>
+<Section name="classifiers">
+<Title>
+<Text id="166">Classificateurs de navigation</Text>
+</Title>
+<Text id="167">Cette section explique comment assigner Ã  une collection des "classificateurs" qui sont utilisÃ©s pour naviguer. Sous la section "Sections de conception", cliquer sur "Classificateurs de navigation".</Text>
+<Text id="168">Pour ajouter un classificateur, sÃ©lectionner-le en utilisant la liste dÃ©roulante "Choisir classificateur Ã  ajouter" et cliquer sur "Ajouter Classificateur". une fenÃªtre qui s'intitule "Configurer Arguments" apparaÃ®t ; les instructions concernant ce dialogue sont les mÃªmes que pour les plugiciels (voir <Reference target="plugins"/>). Une fois le nouveau classificateur configurÃ©, il s'ajoute Ã  la fin de la liste des "Classificateurs couramment AssignÃ©s". </Text>
+<Text id="169">Pour supprimer un classificateur, sÃ©lectionner-le dans la liste et cliquez sur "Supprimer Classificateur".</Text>
+<Text id="170">Pour changer les arguments d'un classificateur, sÃ©lectionner-le sur la liste et cliquer sur "Configurer Classificateur" (ou double-cliquer sur le classificateur sur la liste.) </Text>
+<Text id="171">Le tri des classificateurs dans la barre de navigation de la collection est fourni ici dans l'ordre des classificateurs. Pour le changer, sÃ©lectionner le classificateur Ã  dÃ©placer et cliquer sur "DÃ©placer vers le haut" ou "DÃ©placer vers le bas".</Text>
+<Text id="172">Pour plus d'informations sur les classificateurs lisez le chapitre 2 du Guide du DÃ©veloppeur Greenstone -- Exploitez vos documents au maximum.</Text>
+</Section>
+<Section name="formatstatements">
+<Title>
+<Text id="173">CaractÃ©ristiques de Format</Text>
+</Title>
+<Text id="174">Les pages web que vous voyez en utilisant Greenstone ne sont pas prÃ©-stockÃ©s mais sont gÃ©nÃ©rÃ©es 'Ã  la volÃ©e' au fur et Ã  mesure qu'on en fait appel. Les commandes de format sont utilisÃ©es pour changer l'apparence de ces pages gÃ©nÃ©rÃ©es. Ils influencent le lieu d'apparition des boutons lorsqu'un document est affichÃ©, et dÃ©terminent les liens qui sont affichÃ©s par le classificateur DateList. Les commandes de format ne sont pas faciles Ã  concevoir, et la lecture du chapitre 2 de Greenstone Developer's Guide est recommandÃ©e. Cette section concerne les cadres de format, et  indique comment l'Interface BibliothÃ©caire en fournit l'accÃšs. Sous "Sections de conception", cliquer sur "CaractÃ©ristiques de Format".</Text>
+<Text id="175">On peut appliquer une commande de format Ã  n'importe quoi dans la liste dÃ©roulante "Choisir CaractÃ©ristique" qui comprend tous les classificateurs de mÃªme qu'une liste prÃ©dÃ©finie de caractÃ©ristiques. Deux types de contrÃŽles existent lorsqu'on sÃ©lectionne une caractÃ©ristique: Certaines caractÃ©ristiques sont simplement activÃ©es ou dÃ©sactivÃ©es, et le contrÃŽle se fait grÃ¢ce Ã  une liste de vÃ©rification. D'autres requiÃšrent qu'on spÃ©cifie une chaÃ®ne de format. Pour ces caractÃ©ristiques, il existe une liste de retrait ("Composante AffectÃ©e") pour la sÃ©lection des parties de la caraxtÃ©ristique oÃ¹ s'applique la chaÃ®ne (si nÃ©cessaire), une zone de texte ("ChaÃ®ne de Format HTML") oÃ¹ on saisit la chaÃ®ne, et une sÃ©lection de "Variables" prÃ©dÃ©finies. Pour insÃ©rer une variable dans la position courante dans la chaÃ®ne de format, sÃ©lectionner la Ã  partir de la liste de retrait et cliquer sur "InsÃ©rer". </Text>
+<Text id="176">Vous pouvez spÃ©cifier un format par dÃ©faut pour une composante particuliÃšre en sÃ©lectionnant la caractÃ©ristique vierge.Ce format est alors appliquÃ© Ã  toutes les caractÃ©ristiques applicables sauf instruction contraire. </Text>
+<Text id="177">Pour ajouter une nouvelle commande de format, remplir l'information comme indiquÃ©e plus haut et cliquer sur "Ajouter Format". La nouvelle commande de Format apparaÃ®t dans la liste des  "Commandes de Format frÃ©quemment AssignÃ©es". Seule une commande de format peut Ãªtre assignÃ©e pour chaque combinaison caractÃ©ristique/composante.</Text>
+<Text id="178">Pour enlever une commande de format, sÃ©lectionner-la sur la liste et cliquer "Enlever Format".</Text>
+<Text id="179">Pour modifier une commande de format, sÃ©lectionner-la  sur la liste et cliquer sur "Remplacer Format". </Text>
+<Text id="180">Pour de plus amples informations sur les variables et les composantes de caractÃ©ristiques, lire le chapitre 2 du Guide du DÃ©veloppeur de Greenstone. </Text>
+<Text id="181">Si la boÃ®te de vÃ©rification "Permettre options Ã©tendues" est cochÃ©e, certaines options avancÃ©es de formatage sont activÃ©es. La liste des caractÃ©ristiques pouvant Ãªtre formatÃ©es est lÃ©gÃšrement changÃ©e, et plusieurs variables sont disponibles dans la commande de format, offrant un contrÃŽle plus grand sur la mise en forme. </Text>
+</Section>
+<Section name="translatetext">
+<Title>
+<Text id="182">Traduire Texte</Text>
+</Title>
+<Text id="183">Cette section dÃ©crit l'Affichage de traduction, oÃ¹ on peut dÃ©finir des fragments de texte spÃ©cifiques Ã  un langage pour des parties de l'interface de la collection. Sous "Sections de conception", cliquer sur "Traduire Texte".</Text>
+<Text id="184">Choisir d'abord une entrÃ©e dans la liste "CaractÃ©ristiques". Les chaÃ®nes spÃ©cifiques Ã  un langage associÃ©es Ã  la caractÃ©ristiques apparaissent en bas. Utiliser la liste dÃ©roulante de "Traduction de Langage" pour sÃ©lectionner le langage cible, et saisir le texte traduit dans la zone de texte, en se refÃ©rant Ã  "Fragment de Texte Initial" si nÃ©cessaire. Cliquez sur "Ajouter Traduction" Ã  la fin de l'opÃ©ration. </Text>
+<Text id="185">Pour supprimer une traduction existante, sÃ©lectionner-la Ã  partir du tableau "Traduction AssignÃ©e" et cliquer sur "Enlever Traduction". </Text>
+<Text id="186">Pour Ã©diter une traduction, sÃ©lectionner-la et Ã©diter-la dans la zone de texte "Texte Traduit", et cliquer sur "Remplacer Traduction". </Text>
+</Section>
+<Section name="metadatasets">
+<Title>
+<Text id="187">jeux de MÃ©ta-donnÃ©es</Text>
+</Title>
+<Text id="188">Cette section explique le panel de visualisation du jeu de mÃ©ta-donnÃ©es. Sous "Sections de conception", cliquer sur "jeux de MÃ©ta-donnÃ©es". </Text>
+<Text id="189">Cette fenÃªtre sert Ã  la revue des jeux de mÃ©ta-donnÃ©es utilisÃ©s dans la collection, et les Ã©lÃ©ments qui sont disponibles dans chaque jeu. Choisir dans la liste de "jeux de mÃ©ta-donnÃ©es disponibles" pour voir des informations dÃ©taillÃ©es Ã  ces Ã©lÃ©ments.</Text>
+<Text id="190">Pour utiliser un autre jeu de mÃ©ta-donnÃ©es avec la collection chargÃ©e, clicquez sur "Ajouter un jeu de mÃ©ta-donnÃ©es" et sÃ©lectionnez le fichier mÃ©ta-donnÃ©es (.mds) pour le nouveau jeu mÃ©ta-donnÃ©es.</Text>
+<Text id="191">L'Ã©dition de jeux mÃ©ta-donnÃ©es se fait avec l'Ã©diteur Greenstone de mÃ©ta-donnÃ©es (GEMS). En clicquant sur le bouton "Ãditer un jeux mÃ©ta-donnÃ©es" vous obtiendrez des informations sur l'utilisation de GEMS.</Text>
+<Text id="192">Si vous n'avez plus besoin d'un jeu mÃ©ta-donnÃ©es, sÃ©lectionnez le et clickez sur "Suppression du jeu mÃ©ta-donnÃ©es" pour l'enlever. Si vous avez affecttÃ© des mÃ©ta-donnÃ©es aux Ã©lÃ©ments du jeu supprimÃ©, on vous demandera ce que vous voulez en faire lorsque vous allez ouvrir Ã  nouveau cette collection.</Text>
+</Section>
+</Section>
+<Section name="producingthecollection">
+<Title>
+<Text id="193">Pour produire votre collection</Text>
+</Title>
+<Text id="194">AprÃšs avoir rassemblÃ© les documents de la collection, les avoir annotÃ©s avec les mÃ©ta-donnÃ©es, et dÃ©fini comment la collection va apparaÃ®tre, la production de la collection en utilisant Greenstone est alors possible. Cette section vous en explique la maniÃšre.</Text>
+<Section name="thecreateview">
+<Title>
+<Text id="195">L'Affichage CrÃ©er</Text>
+</Title>
+<Text id="196">L'Affichage CrÃ©er est utilisÃ© pour crÃ©er la collection en mettant en oeuvre les scripts Greenstone relatifs Ã  cette opÃ©ration. En cliquant sur "Construire Collection", on initie le processus de construction de la collection. Sa durÃ©e dÃ©pend de la taille de la collection  et du nombre d'index Ã  crÃ©er (pour les grandes collections cela peut prendre des heures). Une barre d'Ã©tat indique ou on en est dans le processus. Pour annuler le processus Ã  tout moment, cliquer sur "Annuler Construction".</Text>
+<Text id="197">Quand la collection est construite, appuyant "Preview Collection" initiera la page web hebergeant la collection.</Text>
+<Text id="198">En mode expert, vous pouvez utiliser l'entrÃ©e "Message Log" Ã  gauche pour revoir les tentatives prÃ©cÃ©dentes de construction de la collection avec ou san succÃ©s. SÃ©lectionnez le journal souhaitÃ© en cliquant sur la date correspondante dans la liste "Historique du Journal".</Text>
+</Section>
+<Section name="buildsettings">
+<Title>
+<Text id="199">ParamÃštres d'Importation et de Construction</Text>
+</Title>
+<Text id="200">Cette section explique comment accÃ©der aux diffÃ©rents paramÃštres de construction et d'importation. Pour plus d'informations sur l'importation et la construction lire le chapitre 1 du Guide du DÃ©veloppeur de Greenstone -- Comprendre le processus de construction de la collection.</Text>
+<Text id="201">Le contrÃŽle des diffÃ©rents paramÃštres se fait de faÃ§on identique Ã  la fenÃªtre "Configurer Arguments" dÃ©crit dans la section <Reference target="plugins"/>. Certains champs requiÃšrent des arguments numÃ©riques, et on peut: soit les incorporer en les saisissant, soit utiliser les flÃšches Haut et Bas pour augmenter ou diminuer la valeur prÃ©sente (dans certains cas, l'interface limite la classe qu'on peut entrer.) D'autres sont activÃ©s en cliquant sur une case de vÃ©rification (re-cliquer pour dÃ©sactiver.)</Text>
+</Section>
+</Section>
+<Section name="miscellaneous">
+<Title>
+<Text id="202">Miscellaneous</Text>
+</Title>
+<Text id="203">Cette section dÃ©crit les caractÃ©ristiques de l'Interface BibliothÃ©caire qui ne sont pas associÃ©es Ã  une fenÃªtre d'affichage particuliÃšre.</Text>
+<Section name="preferences">
+<Title>
+<Text id="204">PrÃ©fÃ©rences</Text>
+</Title>
+<Text id="205">Cette section explique le dialogue des prÃ©fÃ©rences, auquel on accÃšde en ouvrant "Fichier" -> "PrÃ©fÃ©rences". </Text>
+<Text id="206">La premiÃšre option "General" est un champ texte pour saisir votre adresse courriel. Ceci sera utilisÃ© pour les Ã©lÃ©ments mÃ©ta-donnÃ©es "crÃ©ateur" et "Mainteneur" de la collection. L'option suivante est un liste dÃ©roulante des langues dans lesquelles l'interface bibiothÃšquaire peut Ãªtre affichÃ©e. Si on change le dictionnaire par le choix d'un autre sur la liste, on doit redÃ©marrer l'Interface BibliothÃ©caire pour charger les chaÃ®nes du nouveau langage Ã  partir du dictionnaire.</Text>
+<Text id="207">Si on coche "Affichage MÃ©ta-donnÃ©es Ã©tendues", les diffÃ©rents contrÃŽles relatifs aux mÃ©ta-donnÃ©es affichent toujours toutes les mÃ©ta-donnÃ©es qui ont Ã©tÃ© extraites automatiquement des documents. Lorsqu'on le dÃ©sÃ©lectionne, ces mÃ©ta-donnÃ©es sont cachÃ©es (bien qu'elles restent disponibles pendant la conception de la collection, et dans la collection Greenstone finale.) Si on coche "Montrer les tailles des fichiers", la taille du fichier apparaÃ®t Ã  cÃŽtÃ© de chaque fichier dans l'espace de travail et dans les arborescences de fichiers de la collection dans les Affichages Rassembler et Enrichir.</Text>
+<Text id="208">Le panneau "Mode" est utilisÃ© pour contrÃŽler le niveau du dÃ©tail dans l'interface. Dans sa configuration la plus basse, "Librarian Assistant", la vue de dÃ©coration, est dÃ©sactivÃ©e, les arguments qui requiÃšrent des expressions ordinaires sont cachÃ©s, et la construction de la collection produit un enregistrement minimal d'Ã©vÃšnements. Par contre, la configuration la plus Ã©levÃ©e, "Expert", donne l'accÃšs Ã  toutes les fonctionnalitÃ©s de dÃ©coration, y compris le positionnement de plugin, et les arguments d'expressions ordinaires; elle permet aussi l'enregistrement de l'intÃ©gralitÃ© des messages lors de la construction de la collection. Pour changer ou revoir les modes, cliquez sur le bouton radio situÃ© Ã  cÃŽtÃ© du mode qui vous intÃ©resse. Vous pouvez contrÃŽler rapidement le mode dans lequel vous vous trouvez en regardant la barre de titre de Librarian Interface.</Text>
+<Text id="209">L'Interface BibliothÃ©caire est capable de supporter diffÃ©rents flux de travail en dÃ©terminant lesquels des diffÃ©rents onglets d'affichage sont visibles. Utiliser l'onglet "Workflow" pour adapter les fenÃªtres d'affichage disponibles en cochant les boÃ®tes qui sont Ã  cÃŽtÃ© des affichages souhaitÃ©s. On peut aussi utiliser la liste dÃ©roulante pour sÃ©lectionner des configurations prÃ©dÃ©terminÃ©es. La fermeture du dialogue des prÃ©fÃ©rences Ã©tablit ces paramÃštres de workflow (flux de travail). Ces paramÃštres sont emmagasinnÃ©s dans la collection, et non dans le fichier de configuration de l'Interface BibliothÃ©caire.</Text>
+<Text id="210">L'onglet "Connexion" permet changer le chemin vers le serveur de bibliothÃšque local basÃ© sur Greenstone et utilisÃ© dans l'aperÃ§u des collections. Vous pouvez aussi prÃ©ciser le proxy de connection internet (c.a.d. pour lÃ©lÃ©charger les fichiers; voir la <Reference target="downloadingfiles"/> section pour les details). Cochez la case pour une connection proxy et donnez l'addresse du proxy et son numÃ©ro de port. La connection proxy sera Ã©tablie aprÃšs fermeture du dialogue.</Text>
+<Text id="211">En cours de session, l'Interface BibliothÃ©ccaire peut dÃ©livrer des messages d'avertissement qui informent sur d'Ã©ventuelles consÃ©quences d'une action. On peut dÃ©sactiver le message  en cochant la case "Ne pas afficher cet avertissement de nouveau" ("Do not show this warning again"). On peut rÃ©activer les messages d'avertissement en utilisant l'onglet "Avertissement" ("Warning"). Cocher la boÃ®te situÃ©e Ã  cÃŽtÃ© des messages d'avertissement que l'on souhaite reconsulter. </Text>
+</Section>
+<Section name="fileassociations">
+<Title>
+<Text id="212">Associations de fichiers</Text>
+</Title>
+<Text id="213">L'Interface BibliothÃ©caire utilise des programmes d'application particuliÃšres pour ouvrir des types de fichiers particuliers. 
+Pour modifier des associations ouvrez le menu "Fichier" et cliquer sur "Association de fichiers". </Text>
+<Text id="214">Pour ajouter une association, sÃ©lectionner l'extension du fichier cible dans la liste dÃ©roulant, ou taper dans une nouvelle extension (n'y incluer pas le ".") Ensuite soit taper la commande qui lance l'application voulue dans la champ appropriÃ©, soit choisir l'application dans le dialogue "Navigation". "%1" Peut Ãªtre utilisÃ© dans la commande de lancement pour insÃ©rer le nom du fichier qu'on veut ouvrir. Une fois cela, "Ajouter" est activÃ©. Cliquer dessus pour ajouter l'association.</Text>
+<Text id="215">Pour Ã©diter une association, sÃ©lectionner une extension de fichier existante. Toute commande existante associÃ©e est affichÃ©e dans le champ de la commande de lancement. Corriger-la, et puis cliquer sur "Remplacer".</Text>
+<Text id="216">Pour enlever une association, sÃ©lectionner une extension de fichier existante et cliquer sur "Supprimer". (L'extension du fichier reste dans la liste dÃ©roulante "For Files Ending").</Text>
+<Text id="217">Les associations de fichiers sont stockÃ©es dans le dossier principal du rÃ©pertoire principal de l'Interface BibliothÃ©caire, dans un fichier appelÃ© "associations.xml".</Text>
+</Section>
+<Section name="exportingcollections">
+<Title>
+<Text id="218">Exportation de collections vers CD/DVD</Text>
+</Title>
+<Text id="219">Greenstone peut exporter une ou plusieurs collections vers un CD/DVD d'auto-installation pour Windows. Pour ce faire, le paquetage Greenstone "Export to CD-ROM" doit Ãªtre installÃ©. Il n'est pas inclut par dÃ©faut, donc vous aurez peut Ãªtre Ã  modifier votre installation pour l'inclure.</Text>
+<Text id="220">Pour exporter une collection, ouvrir le menu "Fichier" et choisir "Exporter la Collection vers un CD-ROM". Une liste de collections Greenstone apparaÃ®t; cliquez sur n'importe laquelle pour obtenir une description. Cochez la case des collections Ã  exporter. Vous pouvez entrer le nom du CD/DVD dans la case: c'est ce qui va apparaÃ®tre dans le menu de dÃ©marrage lorsque le CD/DVD aura Ã©tÃ© installÃ©. Puis cliquez sur "Exporter". Ce processus implique la copie de plusieurs fichiers et peut durer quelques minutes.</Text>
+<Text id="221">A la fin de l'opÃ©ration, Greenstone va afficher le nom d'un dossier contenant les collections exportÃ©es. Utilisez un graveur de CD/DVD pour copier le contenu dans un CD/DVD vierge.</Text>
+</Section>
+</Section>
+</Document>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/help_index.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/help_index.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/help_index.xml	(revision 13928)
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Document><Section name="introduction"><Title>Introduction</Title><Section name="ofmiceandmenus"><Title>Dessouris et Menus</Title></Section><Section name="howtoavoidthisdocument"><Title>Comment Ã©viter de lire ce document</Title></Section></Section><Section name="startingoff"><Title>DÃ©marrage</Title><Section name="creatingacollection"><Title>CrÃ©er une nouvelle collection</Title></Section><Section name="savingacollection"><Title>Enregistrer la Collection</Title></Section><Section name="openingacollection"><Title>Ouvrir une collection existante</Title></Section><Section name="deletingcollections"><Title>Suppression des collections</Title></Section></Section><Section name="downloadingfiles"><Title>TÃ©lÃ©chargement de fichiers de lIinternet</Title><Section name="themirrorview"><Title>La vue TÃ©lÃ©chargement</Title></Section></Section><Section name="collectingfiles"><Title>Collecter les fichiers pour la Collection</Title><Section name="thegatherview"><Title>L'affichage Rassembler</Title></Section><Section name="creatingfolders"><Title>CrÃ©er des dossiers</Title></Section><Section name="addingfiles"><Title>Ajouter des fichiers</Title></Section><Section name="removingfiles"><Title>Supprimer des Fichiers</Title></Section><Section name="filteringthetree"><Title>Filtrer l'arborescence</Title></Section></Section><Section name="enrichingacollection"><Title>Enrichir la Collection avec des mÃ©ta-donnÃ©es</Title><Section name="theenrichview"><Title>L'affichage Enrichir</Title></Section><Section name="selectingmetadatasets"><Title>SÃ©lectionner les jeux de mÃ©ta-donnÃ©es</Title></Section><Section name="appendingmetadata"><Title>Ajout de Nouvelles MÃ©ta-donnÃ©es</Title></Section><Section name="addingpreviouslydefinedmetadata"><Title>Ajouter des MÃ©ta-donnÃ©es prÃ©dÃ©finies</Title></Section><Section name="updatingmetadata"><Title>Editant ou Ãliminant MÃ©ta-donnÃ©es</Title></Section><Section name="reviewingmetadata"><Title>Passer en revue les MÃ©ta-donnÃ©es assignÃ©es</Title></Section><Section name="importingpreviouslyassignedmetadata"><Title>Importer des MÃ©ta-donnÃ©es PrÃ©-assignÃ©es</Title></Section></Section><Section name="designingacollection"><Title>DÃ©coration de l'apparence de votre collection</Title><Section name="thedesignview"><Title>L'Affichage conception</Title></Section><Section name="generalsettings"><Title>GÃ©nÃ©ral</Title></Section><Section name="plugins"><Title>Plugiciels de Document</Title></Section><Section name="searchtypes"><Title>Types de recherche</Title></Section><Section name="searchindexes"><Title>Index de recherche</Title></Section><Section name="partitionindexes"><Title>Index de Partition</Title><Section name="definefilters"><Title>DÃ©finir les Filtres</Title></Section><Section name="assignpartitions"><Title>Assigner des Partitions</Title></Section><Section name="assignlanguages"><Title>Assigner Langages</Title></Section></Section><Section name="xcollectionsearching"><Title>Recherches Ã  travers collections</Title></Section><Section name="classifiers"><Title>Classificateurs de navigation</Title></Section><Section name="formatstatements"><Title>CaractÃ©ristiques de Format</Title></Section><Section name="translatetext"><Title>Traduire Texte</Title></Section><Section name="metadatasets"><Title>jeux de MÃ©ta-donnÃ©es</Title></Section></Section><Section name="producingthecollection"><Title>Pour produire votre collection</Title><Section name="thecreateview"><Title>L'Affichage CrÃ©er</Title></Section><Section name="buildsettings"><Title>ParamÃštres d'Importation et de Construction</Title></Section></Section><Section name="miscellaneous"><Title>Miscellaneous</Title><Section name="preferences"><Title>PrÃ©fÃ©rences</Title></Section><Section name="fileassociations"><Title>Associations de fichiers</Title></Section><Section name="exportingcollections"><Title>Exportation de collections vers CD/DVD</Title></Section></Section></Document>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/howtoavoidthisdocument.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/howtoavoidthisdocument.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/howtoavoidthisdocument.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="howtoavoidthisdocument"><font face="Verdana" size="5"><strong>1.2: Comment &eacute;viter de lire ce document</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ne pas lire l'Aide en entier! Lire juste ce qui est n&eacute;cessaire pour obtenir l'aide dont on a besoin.</p>
+<p>L'&eacute;l&eacute;ment de menu Aide indique l'&eacute;l&eacute;ment d'aide le plus appropri&eacute; par une ic&ocirc;ne sous forme de petit livre. </p>
+<p>Le positionnement de la souris sur plusieurs contr&ocirc;les entra&icirc;ne l'apparition d'un "Tool tip" qui dit ce qu'il faut faire.</p>
+<p>Avant d'utiliser l'Interface Biblioth&eacute;caire, il faut lire la documentation Greenstone. La section "Cr&eacute;er une Nouvelle Collection" d&eacute;crit comment cr&eacute;er une nouvelle collection. Avant d'utiliser l'Interface Biblith&eacute;caire, lire d'abord la documentation de Greenstone.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/importingpreviouslyassignedmetadata.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/importingpreviouslyassignedmetadata.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/importingpreviouslyassignedmetadata.htm	(revision 13928)
@@ -0,0 +1,19 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="importingpreviouslyassignedmetadata"><font face="Verdana" size="5"><strong>5.7: Importer des M&eacute;ta-donn&eacute;es Pr&eacute;-assign&eacute;es</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Cette section explique comment importer des m&eacute;ta-donn&eacute;es affect&eacute;es pr&eacute;c&eacute;demment; m&eacute;ta-donn&eacute;es affect&eacute;es avant d'&ecirc;tre ajout&eacute;es &agrave; la collection.</p>
+<p>Si la m&eacute;ta-donn&eacute;e dans une forme reconnue par l'Interface Biblioth&eacute;caire a &eacute;t&eacute; pr&eacute;alablement assign&eacute;e &agrave; un fichier, -- par exemple, quand on choisit des documents dans une collection Greenstone existante -- elle est import&eacute;e automatiquement quand on ajoute le fichier. Pour ce faire, la m&eacute;ta-donn&eacute;e doit &ecirc;tre ajust&eacute;e au jeu de m&eacute;ta-donn&eacute;es disponibles dans la collection.</p>
+<p>L'Interface Biblioth&eacute;caire confirme l'information n&eacute;cessaire. confirmation sous forme d'instructions br&egrave;ves et qui montre ensuite le nom de l'&eacute;l&eacute;ment m&eacute;ta-donn&eacute;e qui est import&eacute;e, comme il appara&icirc;t dans le fichier source. Ce champ ne peut &ecirc;tre ni &eacute;dit&eacute; ni chang&eacute;. Ensuite on choisit sur quel jeu de m&eacute;ta-donn&eacute;e le nouveau &eacute;l&eacute;ment devrait &ecirc;tre calqu&eacute; et enfin l'&eacute;l&eacute;ment m&eacute;ta-donn&eacute;e appropri&eacute;. Le syt&egrave;me selectionne automatiquement le meilleur ajustement, en terme de jeu et d'&eacute;l&eacute;ment pour la nouvelle m&eacute;ta-donn&eacute;e.</p>
+<p>Apr&egrave;s cela,on peut choisir "Ajouter" pour ajouter le nouvel &eacute;l&eacute;ment m&eacute;ta-donn&eacute;e au jeu de m&eacute;ta-donn&eacute;es choisi. (Ceci n'est possible que si aucun &eacute;lement de m&ecirc;me nom n'est pr&eacute;sent &agrave; l'interieur du jeu choisi.) "Fusionner" applique le nouvel &eacute;lement &agrave; celui choisi par l'utilisateur. Enfin, "Ignorer" n'importe aucune m&eacute;ta-donn&eacute;e avec ce nom d'&eacute;lement. Une fois pr&eacute;cis&eacute;e la mani&egrave;re d'importer un certain &eacute;l&eacute;ment de m&eacute;ta-donn&eacute;e, l'information d'application est retenue pour la dur&eacute;e de vie de la collection.</p>
+<p>Pour des d&eacute;tails concenant les fichiers m&eacute;ta-donn&eacute;e.xml que Greenstone utilise pour sauvegarder les m&eacute;ta-donn&eacute;es, il faut vous ref&eacute;rer au chapitre 2 du guide du D&eacute;veloppeur de Greenstone -- "Exploitez vos documents au maximum".</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/introduction.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/introduction.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/introduction.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="introduction"><font face="Verdana" size="5"><strong>1: Introduction</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>L'interface biblioth&eacute;caire de Greenstone est un outil pour collecter et enrichir des documents et ensuite mettre sur pied des collections de biblioth&egrave;ques num&eacute;riques. Il fournit un acc&egrave;s &agrave; la fonctionnalit&eacute; du logiciel de la Biblioth&egrave;que num&eacute;rique de Greenstone &agrave; partir d'un point de vue graphique et d'une interface "clic".</p>
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/metadatasets.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/metadatasets.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/metadatasets.htm	(revision 13928)
@@ -0,0 +1,19 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="metadatasets"><font face="Verdana" size="5"><strong>6.11: jeux de M&eacute;ta-donn&eacute;es</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Cette section explique le panel de visualisation du jeu de m&eacute;ta-donn&eacute;es. Sous "Sections de conception", cliquer sur "jeux de M&eacute;ta-donn&eacute;es". </p>
+<p>Cette fen&ecirc;tre sert &agrave; la revue des jeux de m&eacute;ta-donn&eacute;es utilis&eacute;s dans la collection, et les &eacute;l&eacute;ments qui sont disponibles dans chaque jeu. Choisir dans la liste de "jeux de m&eacute;ta-donn&eacute;es disponibles" pour voir des informations d&eacute;taill&eacute;es &agrave; ces &eacute;l&eacute;ments.</p>
+<p>Pour utiliser un autre jeu de m&eacute;ta-donn&eacute;es avec la collection charg&eacute;e, clicquez sur "Ajouter un jeu de m&eacute;ta-donn&eacute;es" et s&eacute;lectionnez le fichier m&eacute;ta-donn&eacute;es (.mds) pour le nouveau jeu m&eacute;ta-donn&eacute;es.</p>
+<p>L'&eacute;dition de jeux m&eacute;ta-donn&eacute;es se fait avec l'&eacute;diteur Greenstone de m&eacute;ta-donn&eacute;es (GEMS). En clicquant sur le bouton "&Eacute;diter un jeux m&eacute;ta-donn&eacute;es" vous obtiendrez des informations sur l'utilisation de GEMS.</p>
+<p>Si vous n'avez plus besoin d'un jeu m&eacute;ta-donn&eacute;es, s&eacute;lectionnez le et clickez sur "Suppression du jeu m&eacute;ta-donn&eacute;es" pour l'enlever. Si vous avez affectt&eacute; des m&eacute;ta-donn&eacute;es aux &eacute;l&eacute;ments du jeu supprim&eacute;, on vous demandera ce que vous voulez en faire lorsque vous allez ouvrir &agrave; nouveau cette collection.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/miscellaneous.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/miscellaneous.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/miscellaneous.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="miscellaneous"><font face="Verdana" size="5"><strong>8: Miscellaneous</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Cette section d&eacute;crit les caract&eacute;ristiques de l'Interface Biblioth&eacute;caire qui ne sont pas associ&eacute;es &agrave; une fen&ecirc;tre d'affichage particuli&egrave;re.</p>
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/ofmiceandmenus.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/ofmiceandmenus.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/ofmiceandmenus.htm	(revision 13928)
@@ -0,0 +1,22 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="ofmiceandmenus"><font face="Verdana" size="5"><strong>1.1: Dessouris et Menus</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>La section "Dessouris et Menus" fournit une information de base sur la mani&egrave;re de dialoguer avec l'interface biblioth&eacute;caire. Si on est familier avec des programmes comme Internet Explorer ou Microsoft Office et aussi &agrave; l'aise avec les menus et les clics de la souris, passer &agrave; section <a href="howtoavoidthisdocument.htm">Comment &eacute;viter de lire ce document</a>.</p>
+<p>L'interface biblioth&eacute;caire suit les conventions de Microsoft Windows et requiert une connaissance de base de Windows.</p>
+<p>Une position quelconque d'interaction sur l'&eacute;cran, tel qu'un bouton ou un champ de texte, est appel&eacute;e "contr&ocirc;le". A tout moment, un contr&ocirc;le appel&eacute; "Foyer" est mis en relief et r&eacute;pond au clavier. Plusieurs contr&ocirc;les vous permettent de s&eacute;lectionner les parties qui sont mises en relief en bleu fonc&eacute;. Certains contr&ocirc;les virent au gris pour indiquer qu'ils sont &eacute;teints.</p>
+<p>On peut d&eacute;placer la souris, cliquer sur son bouton gauche (cliquer-gauche) ou sur son bouton droit (cliquer-droite) de fa&ccedil;on tout &agrave; fait usuelle. Plusieurs &eacute;l&eacute;ments sont susceptibles d'&ecirc;tre entrain&eacute;s par glissement de la souris son bouton gauche &eacute;tant maintenu appuy&eacute;, et d'&ecirc;tre ainsi d&eacute;pos&eacute;s quelque part en rel&acirc;chant le bouton. Des cibles de d&eacute;p&ocirc;t potentielles changent d'apparence quand un composant les atteint.</p>
+<p>On peut utiliser le clavier pour la saisie &agrave; l'int&eacute;rieur des champs de texte. Des alternatives au clavier sont disponibles pour plusieurs contr&ocirc;les indiqu&eacute;s par un nom cl&eacute; entre crochets --- par exemple [Tab] change le foyer. Le signe plus indique les autres touches susceptibles d'&ecirc;tre appuy&eacute;es en m&ecirc;me temps.</p>
+<p>Pour acc&eacute;der au menu, appuyer sur le bouton [Alt] et sur la lettre correspondante (soulign&eacute;e). Par exemple, pour le menu "Fichier" appuyer sur [Alt] + [F]. Pour choisir un &eacute;l&eacute;ment, appuyer sur la touche correspondante. Par exemple, lorsque le menu "Fichier" est d&eacute;roul&eacute;, appuyer sur "S" pour sauvegarder la collection.</p>
+<p>Les boutons, tels les menus, ont un caract&egrave;re soulign&eacute;. Pour cliquer sur le bouton, appuyer en m&ecirc;me temps sur [Alt] et sur le caract&egrave;re soulign&eacute;.</p>
+<p>Pour quitter l'Interface Biblioth&eacute;caire, on utilise "Sortir" du menu "Fichier". Votre collection sera d'abord sauvegard&eacute;e.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/openingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/openingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/openingacollection.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="openingacollection"><font face="Verdana" size="5"><strong>2.3: Ouvrir une collection existante</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Pour ouvrir une collection existante, choisir "ouvrir" &agrave; partir du menu "Fichier" pour obtenir le "Pr&ecirc;t &agrave; l'ouverture de la collection". Une liste de vos collections Greenstone appara&icirc;t. En s&eacute;lectionner une pour voir sa description, et cliquer sur "Ouvrir" pour la charger. Si l'on cherche une collection qui est hors du dossier "Collect" de Greenstone, cliquer sur "Parcourir" pour un dialogue avec le syst&egrave;me de fichiers concern&eacute;.</p>
+<p>Dans le cas o&ugrave; plusieurs programmes d'Interface Biblioth&eacute;caire de Greenstone sont ex&eacute;cut&eacute;s simultan&eacute;ment, les r&eacute;pertoires concern&eacute;s sont v&eacute;rouill&eacute;s pour pr&eacute;venir une interf&eacute;rence. A l'ouverture d'une collection, un petit fichier de verrouillage temporaire est cr&eacute;&eacute; dans son dossier. Avant d'ouvrir une collection, l'interface Biblioth&eacute;caire v&eacute;rifie qu'aucun fichier de verrouillage n'existe d&eacute;j&agrave;. Le verrouillage d'une collection est indiqu&eacute; par la couleur de son ic&ocirc;ne: verte pour une collection normale, rouge quand elle est v&eacute;rouill&eacute;e. Cependant, quand l'on quitte l'Interface Biblioth&eacute;caire pr&eacute;matur&eacute;ment, le fichier de verrouillage est parfois laiss&eacute; en place. Quand une telle collection est ouverte, l'Interface Biblioth&eacute;caire demande si l'on veut se d&eacute;faire de son contr&ocirc;le. Ne jamais sosutraire une collection en cours d'utilisation par un autre.</p>
+<p>Lorsque vous ouvrez une collection qui n'a pas &eacute;t&eacute; cr&eacute;&eacute;e par Greenstone Librarian Interface, on vous demande de s&eacute;lectionner un ou plusieurs jeux de m&eacute;ta-donn&eacute;es. Si vous n'en s&eacute;lectionnez aucun, les m&eacute;ta-donn&eacute;es existantes seront ignor&eacute;es. Dans le cas contraire, les m&eacute;ta-donn&eacute;es seront import&eacute;es comme lorsque vous cliquez et glisser dans des fichiers contenant des m&eacute;ta-donn&eacute;es. Ce processus est d&eacute;crit dans la section <a href="importingpreviouslyassignedmetadata.htm">Importer des M&eacute;ta-donn&eacute;es Pr&eacute;-assign&eacute;es</a>.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/partitionindexes.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/partitionindexes.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/partitionindexes.htm	(revision 13928)
@@ -0,0 +1,20 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="partitionindexes"><font face="Verdana" size="5"><strong>6.6: Index de Partition</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Les index sont construits sur un texte particulier ou des sources M&eacute;ta-donn&eacute;es. L'espace de recherche peut &ecirc;tre plus tard contr&ocirc;l&eacute; en morcelant l'index soit par langage ou par filtre choisi &agrave; l'avance. Cette section en d&eacute;crit la proc&eacute;dure. Sous "Sections de conception", cliquer "Index de Partition". </p>
+<p>L'affichage "Index de Partition" poss&egrave;de trois onglets: "D&eacute;finir les Filtres", "Assigner une partition" et "Assigner des langages". Pour en savoir davantage sur les partitions, lire sur les sous collections et les sous index au chapitre 2 de Greenstone developer's guide.</p>
+<p>La fen&ecirc;tre des Indexes de Partition est seulement &eacute;tablie dans la Librairie de Syst&egrave;mes Sp&eacute;cialistes et modes Experts (voir <a href="preferences.htm">Pr&eacute;f&eacute;rences</a>). Notez que le nombre total de partitions g&eacute;n&eacute;r&eacute;es est une combinaison de tous les indexes, des filtres de sous colection et des langues choisis. Deux indexes avec deux filtres de sous-collections dans deux langues donnent huit partitions d'index.</p>
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/plugins.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/plugins.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/plugins.htm	(revision 13928)
@@ -0,0 +1,21 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="plugins"><font face="Verdana" size="5"><strong>6.3: Plugiciels de Document</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Cette section d&eacute;crit comment faire la configuration des plugiciels des documents que la collection utilise. Elle explique comment sp&eacute;cifier les plugiciels utilis&eacute;s, quels param&egrave;tres leur passer et dans quel ordre ils se d&eacute;roulent. Sous "Sections de conception", cliquer "Plugiciels de document".</p>
+<p>Pour ajouter un plugiciel, s&eacute;lectionner-le sur la liste d&eacute;roulante de "Choisir le plugiciel &agrave; ajouter" situ&eacute;e &agrave; c&ocirc;t&eacute; du bouton et ensuite cliquer "Ajouter plugiciel". Une fen&ecirc;tre d&eacute;nomm&eacute;e "Configurer les arguments" appara&icirc;t; elle est d&eacute;crite plus loin. Une fois la configuration du nouveau plugiciel achev&eacute;e, il est ajout&eacute; &agrave; la fin de la liste "Plugiciels couramment assign&eacute;s". Veuillez noter que, &agrave; l'exception de UnknownPlug, chaque plugin ne peut appara&icirc;tre qu'une seule fois dans la liste.</p>
+<p>Pour enlever un plugiciel, s&eacute;lectionner-le sur la liste et cliquer sur "Enlever plugiciel".</p>
+<p>Les plugiciels sont configur&eacute;s en fournissant des arguments. Pour les changer, il faut s&eacute;lectionner le plugiciel &agrave; partir de la liste et cliquer "Configurer plugiciel" (Ou double-cliquer sur le plugiciel). Un dialogue "Configuration des arguments" appara&icirc;t avec diff&eacute;rent cont&ocirc;les pour sp&eacute;cifier les arguments.</p>
+<p>Il existe plusieurs types de contr&ocirc;les. Certains sont des bo&icirc;tes de dialogue et cliquer sur l'une ajoute l'option appropri&eacute;e au plugiciel. Les autres sont des cha&icirc;nes de textes avec une bo&icirc;te de dialogue et un champ texte. Cliquer sur la bo&icirc;te pour activer l'argument, ensuite saisir le texte appropri&eacute; dans la bo&icirc;te (expression normale, chemin de fichier etc). Les autres sont des menus d&eacute;roulants &agrave; partir desquels on peut s&eacute;lectionner &agrave; partir d'une s&eacute;rie de valeurs d&eacute;termin&eacute;es. Pour apprendre ce qu'un argument peut faire, promener la souris planer sur son nom pendant un instant une description appara&icirc;tra.</p>
+<p>Pour changer la configuration, cliquer sur "OK" pour valider et fermer la bo&icirc;te de dialogue, ou "Annuler" pour fermer la bo&icirc;te de dialogue sans changer les arguments du plugiciel.</p>
+<p>Les plugiciels dans la liste sont execut&eacute;s en ordre et l'ordre est parfois important. L' ordre des classificateurs ne peut &ecirc;tre chang&eacute; que dans la Librairie de Syst&egrave;mes Sp&eacute;cialistes et modes Experts (voir <a href="preferences.htm">Pr&eacute;f&eacute;rences</a>).</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/preferences.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/preferences.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/preferences.htm	(revision 13928)
@@ -0,0 +1,21 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="preferences"><font face="Verdana" size="5"><strong>8.1: Pr&eacute;f&eacute;rences</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Cette section explique le dialogue des pr&eacute;f&eacute;rences, auquel on acc&egrave;de en ouvrant "Fichier" -&gt; "Pr&eacute;f&eacute;rences". </p>
+<p>La premi&egrave;re option "General" est un champ texte pour saisir votre adresse courriel. Ceci sera utilis&eacute; pour les &eacute;l&eacute;ments m&eacute;ta-donn&eacute;es "cr&eacute;ateur" et "Mainteneur" de la collection. L'option suivante est un liste d&eacute;roulante des langues dans lesquelles l'interface bibioth&egrave;quaire peut &ecirc;tre affich&eacute;e. Si on change le dictionnaire par le choix d'un autre sur la liste, on doit red&eacute;marrer l'Interface Biblioth&eacute;caire pour charger les cha&icirc;nes du nouveau langage &agrave; partir du dictionnaire.</p>
+<p>Si on coche "Affichage M&eacute;ta-donn&eacute;es &eacute;tendues", les diff&eacute;rents contr&ocirc;les relatifs aux m&eacute;ta-donn&eacute;es affichent toujours toutes les m&eacute;ta-donn&eacute;es qui ont &eacute;t&eacute; extraites automatiquement des documents. Lorsqu'on le d&eacute;s&eacute;lectionne, ces m&eacute;ta-donn&eacute;es sont cach&eacute;es (bien qu'elles restent disponibles pendant la conception de la collection, et dans la collection Greenstone finale.) Si on coche "Montrer les tailles des fichiers", la taille du fichier appara&icirc;t &agrave; c&ocirc;t&eacute; de chaque fichier dans l'espace de travail et dans les arborescences de fichiers de la collection dans les Affichages Rassembler et Enrichir.</p>
+<p>Le panneau "Mode" est utilis&eacute; pour contr&ocirc;ler le niveau du d&eacute;tail dans l'interface. Dans sa configuration la plus basse, "Librarian Assistant", la vue de d&eacute;coration, est d&eacute;sactiv&eacute;e, les arguments qui requi&egrave;rent des expressions ordinaires sont cach&eacute;s, et la construction de la collection produit un enregistrement minimal d'&eacute;v&egrave;nements. Par contre, la configuration la plus &eacute;lev&eacute;e, "Expert", donne l'acc&egrave;s &agrave; toutes les fonctionnalit&eacute;s de d&eacute;coration, y compris le positionnement de plugin, et les arguments d'expressions ordinaires; elle permet aussi l'enregistrement de l'int&eacute;gralit&eacute; des messages lors de la construction de la collection. Pour changer ou revoir les modes, cliquez sur le bouton radio situ&eacute; &agrave; c&ocirc;t&eacute; du mode qui vous int&eacute;resse. Vous pouvez contr&ocirc;ler rapidement le mode dans lequel vous vous trouvez en regardant la barre de titre de Librarian Interface.</p>
+<p>L'Interface Biblioth&eacute;caire est capable de supporter diff&eacute;rents flux de travail en d&eacute;terminant lesquels des diff&eacute;rents onglets d'affichage sont visibles. Utiliser l'onglet "Workflow" pour adapter les fen&ecirc;tres d'affichage disponibles en cochant les bo&icirc;tes qui sont &agrave; c&ocirc;t&eacute; des affichages souhait&eacute;s. On peut aussi utiliser la liste d&eacute;roulante pour s&eacute;lectionner des configurations pr&eacute;d&eacute;termin&eacute;es. La fermeture du dialogue des pr&eacute;f&eacute;rences &eacute;tablit ces param&egrave;tres de workflow (flux de travail). Ces param&egrave;tres sont emmagasinn&eacute;s dans la collection, et non dans le fichier de configuration de l'Interface Biblioth&eacute;caire.</p>
+<p>L'onglet "Connexion" permet changer le chemin vers le serveur de biblioth&egrave;que local bas&eacute; sur Greenstone et utilis&eacute; dans l'aper&ccedil;u des collections. Vous pouvez aussi pr&eacute;ciser le proxy de connection internet (c.a.d. pour l&eacute;l&eacute;charger les fichiers; voir la <a href="downloadingfiles.htm">T&eacute;l&eacute;chargement de fichiers de lIinternet</a> section pour les details). Cochez la case pour une connection proxy et donnez l'addresse du proxy et son num&eacute;ro de port. La connection proxy sera &eacute;tablie apr&egrave;s fermeture du dialogue.</p>
+<p>En cours de session, l'Interface Biblioth&eacute;ccaire peut d&eacute;livrer des messages d'avertissement qui informent sur d'&eacute;ventuelles cons&eacute;quences d'une action. On peut d&eacute;sactiver le message  en cochant la case "Ne pas afficher cet avertissement de nouveau" ("Do not show this warning again"). On peut r&eacute;activer les messages d'avertissement en utilisant l'onglet "Avertissement" ("Warning"). Cocher la bo&icirc;te situ&eacute;e &agrave; c&ocirc;t&eacute; des messages d'avertissement que l'on souhaite reconsulter. </p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/producingthecollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/producingthecollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/producingthecollection.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="producingthecollection"><font face="Verdana" size="5"><strong>7: Pour produire votre collection</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Apr&egrave;s avoir rassembl&eacute; les documents de la collection, les avoir annot&eacute;s avec les m&eacute;ta-donn&eacute;es, et d&eacute;fini comment la collection va appara&icirc;tre, la production de la collection en utilisant Greenstone est alors possible. Cette section vous en explique la mani&egrave;re.</p>
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/removingfiles.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/removingfiles.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/removingfiles.htm	(revision 13928)
@@ -0,0 +1,16 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="removingfiles"><font face="Verdana" size="5"><strong>4.4: Supprimer des Fichiers</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Il existe plusieurs m&eacute;thodes pour supprimer des fichiers et des dossiers. On doit d'abord indiquer les &eacute;l&eacute;ments &agrave; supprimer en s&eacute;lectionnant un ou plusieurs fichiers et dossiers comme d&eacute;crit dans <a href="thegatherview.htm">L'affichage Rassembler</a>.</p>
+<p>D&egrave;s lors que les fichiers sont s&eacute;lectionn&eacute;s, cliquer sur le bouton "Supprimer" pour les d&eacute;truire, ou appuyer sur la touche [Delete] de votre clavier, ou les glisser-d&eacute;placer de la collection vers le bouton "Supprimer" et les y d&eacute;poser.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/reviewingmetadata.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/reviewingmetadata.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/reviewingmetadata.htm	(revision 13928)
@@ -0,0 +1,20 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="reviewingmetadata"><font face="Verdana" size="5"><strong>5.6: Passer en revue les M&eacute;ta-donn&eacute;es assign&eacute;es</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>On &eacute;prouve parfois le besoin de voir, &agrave; la fois, les m&eacute;ta-donn&eacute;es affect&eacute;es &agrave; plusieurs ou &agrave; tous les fichiers -- par exemple, pour d&eacute;terminer combien de fichiers sont en cours d'utilisation ou pour avoir une id&eacute;e de la chronologie. </p>
+<p>S&eacute;lectionnez les fichiers que vous souhaitez examiner, puis clicquez sur le bouton droit et choisissez "M&eacute;ta-donn&eacute;es Associ&eacute;es...". Une fen&ecirc;tre appel&eacute;e "Toutes les M&eacute;ta-donn&eacute;es", sous forme d'un grand tableau avec plusieurs colonnes, appara&icirc;t. La premi&egrave;re colonne montre les noms de fichiers; les lignes montrent toutes les valeurs de m&eacute;ta-donn&eacute;es assign&eacute;es &agrave; ces fichiers.</p>
+<p>Dessiner le tableau peut prendre quelque temps si plusieurs fichiers sont s&eacute;lectionn&eacute;s. On peut continuer &agrave; utiliser l'Interface Biblioth&eacute;caire pendant que la fen&ecirc;tre "Toutes M&eacute;ta-donn&eacute;es" est ouverte.</p>
+<p>Quand il devient trop large, on peut filtrer le tableau "Toutes M&eacute;ta-donn&eacute;es" en appliquant des filtres aux colonnes. Alors que de nouveaux filtres sont ajout&eacute;s, seules les lignes qui concernent restent visibles. Pour installer, modifier ou effacer un filtre, cliquez sur l'&icirc;cone "Funnel" situ&eacute; en haut de la colonne. Une information sur le filtre est r&eacute;clam&eacute;e. Une fois le filtre install&eacute;, l'en-t&ecirc;te de la colonne change de couleur.</p>
+<p>La confirmation poss&egrave;de un onglet "simple" et " advanc&eacute;". La version simple filtre  les colonnes afin qu'elles ne montrent que des lignes qui contiennent une certaine valeur de m&eacute;ta-donn&eacute;e ("*" concerne toutes les valeurs). On peut s&eacute;lectionner des valeurs de m&eacute;ta-donn&eacute;es &agrave; partir d'une liste d&eacute;roulante. La version advanc&eacute;e permet diff&eacute;rentes op&eacute;rations d'harmonisation: doit commencer avec, ne contient pas, alphab&eacute;tiquement et est &eacute;gal &agrave;. La valeur &agrave; harmoniser peut &ecirc;tre &eacute;dit&eacute;e et prise sous forme d'une cha&icirc;ne quelconque (y compris "*"), et on peut opter pour une harmonisation insensible aux caract&egrave;res. Enfin, on peut sp&eacute;cifier une deuxi&egrave;me condition d'harmonisation pr&eacute;cisant une gamme de valeurs (en s&eacute;lectionnant AND) ou des valeurs alternatives (en selectionnant OR). En dessous de cette zone, une bo&icirc;te qui permet de changer l'ordre de tri (ascendant ou descendant) est plac&eacute;e. Enfin, cliquer sur "Installer Filtre" pour appliquer le nouveau filtre &agrave; la colonne. Cliquer sur "Effacer Filtre" pour enlever le filtre courant. Notez que les d&eacute;tails du filtre sont retenus m&ecirc;me si le filtre est effac&eacute;.</p>
+<p>Par exemple, pour trier le tableau "Toutes M&eacute;ta-donn&eacute;es" , choisir une colonne, s&eacute;lectionner le cadre du filtre par d&eacute;faut (Un filtre simple sur "*") et choisir un ordre ascendant ou descendant.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/savingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/savingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/savingacollection.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="savingacollection"><font face="Verdana" size="5"><strong>2.2: Enregistrer la Collection</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Enregistrer r&eacute;guli&egrave;rement votre travail en choisissant "Enregistrer" dans le fichier "Menu". Enregistrer une collection ne signifie pas la rendre pr&ecirc;te &agrave; l'utilisation dans Greenstone (voir <a href="producingthecollection.htm">Pour produire votre collection</a>).</p>
+<p>L'Interface Biblith&eacute;caire prot&egrave;ge votre travail en l'enregistrant &agrave; la fermeture du programme ou &agrave; l'ouverture d'une autre collection.</p>
+<p>Les collections sont enregistr&eacute;es en un fichier choisi pour la collection avec une extension ".col", localis&eacute; dans un r&eacute;pertoire de m&ecirc;me nom &agrave; l'int&eacute;rieur du dossier "collect" de l'installation de Greenstone.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/searchindexes.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/searchindexes.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/searchindexes.htm	(revision 13928)
@@ -0,0 +1,22 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="searchindexes"><font face="Verdana" size="5"><strong>6.5: Index de recherche</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Les index pr&eacute;cisent les parties de la collection qui doivent &ecirc;tre recherch&eacute;es. Cette section explique comment ajouter et enlever des index et fixer un index par d&eacute;faut. Sous "Sections de conception", cliquer sur "Rechercher Index".</p>
+<p>Pour ajouter un index, taper un nom choisi dans le champ "Nom de l'Index". Selectionner les sources d'information &agrave; indexer en cliquant les bo&icirc;tes de dialogue &agrave; c&ocirc;t&eacute; d'eux. La liste montre aussi bien tous les &eacute;l&eacute;ments de m&eacute;ta-donn&eacute;es assign&eacute;s, que le texte entier. Apr&egrave;s avoir s&eacute;lectionn&eacute; les sources de donn&eacute;es, choisir la granularit&eacute; de l'index en utilisant le menu "Au niveau". Une fois ces d&eacute;tails complet&eacute;s, "Ajouter Index" devient actif  (&agrave; moins qu'il n'ait un index existant avec les m&ecirc;mes param&egrave;tres). Cliquez pour ajouter un nouvel index.</p>
+<p>Pour &eacute;diter un index, s&eacute;lectionnez-le et changez les d&eacute;tails de l'index, puis clicquez sur "Remplacer l'index".</p>
+<p>Pour enlever un index, il faut le s&eacute;lectionner sur la liste d'index assign&eacute;s et cliquer "Enlever index". </p>
+<p>Pour cr&eacute;er un indexe couvrant texte et toute metadata, cliquez sur "Ajouter Tout".</p>
+<p>L'index par d&eacute;faut, celui qui est utilis&eacute; dans la page de recherche de la collection est labell&eacute; parc "[Index par d&eacute;faut]" dans la liste "Index assign&eacute;s".</p>
+<p>Si la recherche avanc&eacute;e est activ&eacute;e (voir Affichage des types de recherche), les contr&ocirc;les d'index sont diff&eacute;rents. Il existe une nouvelle pseudo-source de donn&eacute;es "Tous champs" qui fournit une recherche &agrave; travers tous les index sp&eacute;cifi&eacute;s &agrave; la fois. Des niveaux ne sont pas assign&eacute;s &agrave; un index sp&eacute;cifique, mais s'applique &agrave; tous les index: ainsi index et niveaux sont ajout&eacute;s s&eacute;parement. "Ajouter Tout" cr&eacute;e un indexe s&eacute;par&eacute; pour chaque champ de metadata dans ce mode.</p>
+<p>Le nom de chaque index sera en d&eacute;faut pour le nom de source. Pour changer le nom, S&eacute;lectionner un index, changer ses d&eacute;tails et cliquez "Remplacer Index". </p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/searchtypes.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/searchtypes.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/searchtypes.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="searchtypes"><font face="Verdana" size="5"><strong>6.4: Types de recherche</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>cette section explique comment modifier une nouvelle caract&eacute;ristique de conception dans Greenstone, Types de recherche, qui permet une recherche de champ. Les types de recherche sp&eacute;cifient le type d'interface de recherche &agrave; fournir: formulaire, recherche par champs et/ou recherche simple. Sous "Sections de conception", cliquer sur "Types de recherche".</p>
+<p>Lorsqu'on p&eacute;n&egrave;tre dans l'affichage Types de recherche, v&eacute;rifier d'abord "Activer recherches avanc&eacute;es", qui active les autres contr&ocirc;les. Ceci change la collection &agrave; utiliser un m&eacute;chanisme d' indexage qui permet une recherche de champs. La sp&eacute;cification de l' indexe est l&eacute;g&egrave;rement diff&eacute;rente dans ce mode. (Quand &eacute;changeant entre une recherche classique ou avanc&eacute;e, le GLI essaye de convertir la sp&eacute;cification de l' indexe, mais peut ne pas le faire correctement.)</p>
+<p>pour ajouter un type de recherche, s&eacute;lectionner-le &agrave; partir de la liste "Types de recherche" et cliquer sur "Ajouter Type de recherche".  Chaque type n'appara&icirc;t qu'une fois sur la liste. La premi&egrave;re recherche sera de type d&eacute;faut et appar&ecirc;tra dans la page de recherche de la conection &eacute;tablie. Tout les autres pourons &ecirc;tre s&eacute;lection&eacute;s dans la page de pr&eacute;f&eacute;rences.</p>
+<p>Pour enlever un type de recherche, il faut le selectionner &agrave; partir de la liste "Currently Assigned Search type" et cliquer sur "Enlever type de recheche". La liste doit contenir au moins un type de recherche.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/selectingmetadatasets.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/selectingmetadatasets.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/selectingmetadatasets.htm	(revision 13928)
@@ -0,0 +1,16 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="selectingmetadatasets"><font face="Verdana" size="5"><strong>5.2: S&eacute;lectionner les jeux de m&eacute;ta-donn&eacute;es</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Les s&eacute;ries d'&eacute;l&eacute;ments de m&eacute;ta-donn&eacute;es pr&eacute;d&eacute;finis sont connus comme "jeux de M&eacute;ta-donn&eacute;es". "Dublin Core" en est un exemple. Quand on ajoute un Groupe de M&eacute;ta-donn&eacute;es &agrave; la collection, ses &eacute;l&eacute;ments peuvent &ecirc;tre s&eacute;lectionn&eacute;s. On peut avoir plus d'un jeu de m&eacute;ta-donn&eacute;es ; pour &eacute;viter des t&eacute;lescopages de nom, un identificateur abr&eacute;g&eacute; qui identifie le jeu de m&eacute;ta-donn&eacute;es est suspendu au nom de l'&eacute;l&eacute;ment. Par exemple l'&eacute;lement cr&eacute;ateur de Dublin Core devient "dc.Creator". Les jeux de m&eacute;ta-donn&eacute;es sont sauv&eacute;gard&eacute;s dans le dossier de m&eacute;ta-donn&eacute;es de l'Interface Biblioth&eacute;caire et ont le sufixe ".mds".</p>
+<p>Pour contr&ocirc;ler les jeux de m&eacute;ta-donn&eacute;es utilis&eacute;s dans une collection, utilisez l'entr&eacute;e "Jeux M&eacute;ta-Donn&eacute;es" sur la vue "Conception".</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/startingoff.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/startingoff.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/startingoff.htm	(revision 13928)
@@ -0,0 +1,19 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="startingoff"><font face="Verdana" size="5"><strong>2: D&eacute;marrage</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Cette section explique comment cr&eacute;er, charger, enregistrer et supprimer des collections.</p>
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/thecreateview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/thecreateview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/thecreateview.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="thecreateview"><font face="Verdana" size="5"><strong>7.1: L'Affichage Cr&eacute;er</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>L'Affichage Cr&eacute;er est utilis&eacute; pour cr&eacute;er la collection en mettant en oeuvre les scripts Greenstone relatifs &agrave; cette op&eacute;ration. En cliquant sur "Construire Collection", on initie le processus de construction de la collection. Sa dur&eacute;e d&eacute;pend de la taille de la collection  et du nombre d'index &agrave; cr&eacute;er (pour les grandes collections cela peut prendre des heures). Une barre d'&eacute;tat indique ou on en est dans le processus. Pour annuler le processus &agrave; tout moment, cliquer sur "Annuler Construction".</p>
+<p>Quand la collection est construite, appuyant "Preview Collection" initiera la page web hebergeant la collection.</p>
+<p>En mode expert, vous pouvez utiliser l'entr&eacute;e "Message Log" &agrave; gauche pour revoir les tentatives pr&eacute;c&eacute;dentes de construction de la collection avec ou san succ&eacute;s. S&eacute;lectionnez le journal souhait&eacute; en cliquant sur la date correspondante dans la liste "Historique du Journal".</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/thedesignview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/thedesignview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/thedesignview.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="thedesignview"><font face="Verdana" size="5"><strong>6.1: L'Affichage conception</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Cette section pr&eacute;sente l'affichage de conception et explique comment on navigue entre les diff&eacute;rents affichages &agrave; l'int&eacute;rieur de cette vitrine. </p>
+<p>Avec l'Interface Biblioth&eacute;caire, on peut configurer la fa&ccedil;on dont la collection va appara&icirc;tre &agrave; l'utilisateur. Les options de configuration sont divis&eacute;es en diff&eacute;rentes sections, chacune associ&eacute;e &agrave; une &eacute;tape particuli&egrave;re de navigation ou de pr&eacute;sentation d'information.</p>
+<p>Sur la gauche est plac&eacute;e une liste de diff&eacute;rents affichages et &agrave; droite les commandes associ&eacute;es &agrave; celles en cours. Pour passer &agrave; un  affichage diff&eacute;rent, cliquer son nom dans la liste.</p>
+<p>Pour comprendre les diff&eacute;rentes &eacute;tapes et les termes implmiqu&eacute;s dans la conception d'une collection, lire les chapitres 1 et 2 de Greenstone's Developer's Guide. </p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/theenrichview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/theenrichview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/theenrichview.htm	(revision 13928)
@@ -0,0 +1,20 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="theenrichview"><font face="Verdana" size="5"><strong>5.1: L'affichage Enrichir</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Utiliser l'affichage Enrichir pour assigner une m&eacute;ta-donn&eacute;e aux documents de la collection. Une m&eacute;ta-donn&eacute;e est une donn&eacute;e sur une donn&eacute;e -- de fa&ccedil;on typique titre, auteur, date de cr&eacute;ation, et ainsi de suite. Chaque &eacute;l&eacute;ment de m&eacute;ta-donn&eacute;e a deux parties: "el&eacute;ment" indique le type d'&eacute;l&eacute;ment (par exemple auteur), "valeur" qui donne la valeur de cette m&eacute;ta-donn&eacute;e &eacute;l&eacute;ment (par exemple le nom de l'auteur).</p>
+<p>Sur la gauche de l'affichage "Enrichir" est l'arborescence de la collection. A sa droite, la Table de M&eacute;ta-donn&eacute;es, qui montre les m&eacute;ta-donn&eacute;es pour tous les fichiers et dossiers s&eacute;lectionn&eacute;es de l'arborescence de la collection. Les colonnes sont indiqu&eacute;es en gris en haut, et peuvent &ecirc;tre redimensionn&eacute;es en faisant glisser la ligne de s&eacute;paration. Si plusieurs fichiers sont s&eacute;lectionn&eacute;s, un texte en noir indique que la valeur est commune &agrave; tous les fichiers s&eacute;lectionn&eacute;s, tandis qu'un texte en gris en indique le contraire. les valeurs en noir peuvent &ecirc;tre mises &agrave; jour ou supprim&eacute;es, tandis que celles en gris peuvent &ecirc;tre supprim&eacute;es de ceux qui l'ont, ou ajout&eacute;es aux autres.</p>
+<p>Une ic&ocirc;ne de dossier peut appara&icirc;tre &agrave; c&ocirc;t&eacute; de certaines entr&eacute;es de m&eacute;ta-donn&eacute;es. Ceci indique que les valeurs ont &eacute;t&eacute; h&eacute;rit&eacute;es d'un dossier parent. Les m&eacute;ta-donn&eacute;es h&eacute;rit&eacute;es ne peuvent &ecirc;tre &eacute;dit&eacute;es ou supprim&eacute;es, mais seulement ajout&eacute;es ou &eacute;cras&eacute;es. Cliquer sur l'ic&ocirc;ne du dossier pour aller imm&eacute;diatement au dossier o&ugrave; la m&eacute;ta-donn&eacute;e est assign&eacute;e.</p>
+<p>Si vous cliquez sur un l'&eacute;l&eacute;ment de metadata du tableau, celui-ci affichera les valeurs existantes pour l' &eacute;l&eacute;ment dans le domaine "Valeurs existantes pour..." en dessous du tableau. Celle-ci, d&eacute;veloppe et comprime. C'est une liste qui, de fa&ccedil;on usuelle, montre toutes les valeurs pr&eacute;c&eacute;demment saisies pour un &eacute;l&eacute;ment s&eacute;lectionn&eacute;. Le clic sur une entr&eacute;e la place automatiquement dans le champ valeur. Inversement, la saisie dans le champ texte s&eacute;lectionne l'entr&eacute;e de l'Arborescence Valeur qui d&eacute;bute avec les caract&egrave;res saisis. Appuyer sur [Tab] compl&egrave;te automatiquement la saisie de la valeur s&eacute;lectionn&eacute;e.</p>
+<p>Les valeurs de m&eacute;ta-donn&eacute;e peuvent &ecirc;tre organis&eacute;es en une hi&eacute;rarchie.Ceci est montr&eacute; dans l'Arborescence Valeur utilisant des dossiers de niveau interne. Les valeurs hi&eacute;rarchiques peuvent &ecirc;tre saisies en utilisant le caract&egrave;re "|" pour s&eacute;parer les niveaux. Par exemple, "Cards|Red|Diamonds|Seven" peut &ecirc;tre utilis&eacute; dans une hi&eacute;rarchie qui repr&eacute;sente un jeu de cartes. Cela permet le rejeument des valeurs. Les jeux peuvent aussi &ecirc;trre assign&eacute;s comme m&eacute;ta-donn&eacute;e.</p>
+<p>Greenstone extrait automatiquement des m&eacute;ta-donn&eacute;es &agrave; partir des documents en un jeu de m&eacute;ta-donn&eacute;es dont les &eacute;l&eacute;ments sont pr&eacute;fix&eacute;s "ex.". Ceci n'a aucune valeur et ne peut &ecirc;tre &eacute;dit&eacute;.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/thegatherview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/thegatherview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/thegatherview.htm	(revision 13928)
@@ -0,0 +1,24 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="thegatherview"><font face="Verdana" size="5"><strong>4.1: L'affichage Rassembler</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>cette section introduit la zone Rassembler utilis&eacute;e pour selectionner les fichiers &agrave; inclure dans la collection &agrave; cr&eacute;er. L'Interface Biblioth&eacute;caire d&eacute;marre avec l'affichage "Rassembler". Pour revenir ult&eacute;rieurement &agrave; celui-ci, cliquer directement sur l'onglet "Rassembler" au bas de la barre des menus.</p>
+<p>Les deux vastes zones intitul&eacute;es "Espace de travail" et "Collection" servent au transfert des fichiers vers la collection. Elles contiennent des arborescences de fichiers, des structures graphiques qui repr&eacute;sentent des fichiers et des dossiers.</p>
+<p>Choisir un &eacute;l&eacute;ment dans l'arborescence en cliquant dessus. (d'autres mani&egrave;res de le faire existent; voir ci-dessous). Double-cliquer sur un dossier, ou cliquer simplement sur le symbole de commutateur plac&eacute; &agrave; c&ocirc;t&eacute; de lui, pour d&eacute;velopper (ou r&eacute;duire) son contenu. Double-cliquer sur un fichier pour l'ouvrir en utilisant un programme d'application associ&eacute; (voir <a href="fileassociations.htm">Associations de fichiers</a>).</p>
+<p>L'arbre des fichiers de l'espace de travail montre les sources de donn&eacute;es disponibles pour l'interface biblioth&eacute;caire -- le syst&egrave;me de fichiers local (ainsi que les unit&eacute;s de disques et Cd-rom), le contenu des collection Greenstone, et la cache des fichiers t&eacute;l&eacute;charg&eacute;s. Vous pouvez copier et afficher ces fichiers mais vous ne pouvez pas les d&eacute;placer, supprimer ou &eacute;diter, &agrave; l'exception des fichiers t&eacute;l&eacute;charg&eacute;s qui peuvent &ecirc;tre supprim&eacute;. Vous pouvez naviguer &agrave; l'int&eacute;rieur de cet espace pour trouver les documents que vous souhaitez ajouter &agrave; la collection.</p>
+<p>L'arborescence des fichiers de la Collection ne repr&eacute;sente jusque-l&agrave; que le contenu de la collection. Elle est initialement vide.</p>
+<p>On peut redimensionner les espaces en positionnant la souris sur la barre grise qui s&eacute;pare les arborescences (le pointeur change de forme) et en la faisant glisser.</p>
+<p>En bas de la fen&ecirc;tre, il y a une barre d'&eacute;tat qui montre l'&eacute;volution des op&eacute;rations sur les fichiers (copie, d&eacute;placement et suppression). Ces op&eacute;rations peuvent &ecirc;tre longues. Le bouton "Stop" arr&ecirc;te toute t&acirc;che en cours.</p>
+<p>Deux grands boutons occupent le coin droit inf&eacute;rieur de l'&eacute;cran. "Nouveau dossier", avec une image d'un dossier, cr&eacute;e de nouveaux dossiers (voir <a href="creatingfolders.htm">Cr&eacute;er des dossiers</a>). "Supprimer", avec une corbeille, supprime les fichiers. Cliquer sur le bouton "Supprimer" d&eacute;truit tous les fichiers s&eacute;lectionn&eacute;s de l'arborescence de fichiers de la collection. On peut de m&ecirc;me r&eacute;aliser cette suppression de fichiers en les faisant glisser jusqu'au bouton "Supprimer". </p>
+<p>Pour s&eacute;lectionner plusieurs s&eacute;quences d'&eacute;l&eacute;ments, s&eacute;lectionner le premier, maintenir appuy&eacute;e la touche [Maj] et cliquer sur le dernier &eacute;l&eacute;ment de la s&eacute;quence -- la s&eacute;lection comprendra tous les &eacute;l&eacute;ments compris entre les deux. Pour la s&eacute;lection de fichiers qui ne se suivent pas, maintenir la touche [Ctrl] appuy&eacute;e en cliquant sur chacun d'eux. Ces deux m&eacute;thodes peuvent &ecirc;tre utilis&eacute;es ensemble pour la s&eacute;lection de jeux d'&eacute;l&eacute;ments non adjacents.</p>
+<p>Certains dossiers -- tel que celui contenant vos propres pages Web -- ont parfois une signification sp&eacute;ciale. L'Interface Biblioth&eacute;caire peut appliquer de tels dossiers au premier niveau de l'arborescence de fichiers. Pour ce faire double-cliquer droite sur le dossier vis&eacute;. Choisir "Cr&eacute;er un Raccourci", saisir le nom du dossier. Pour enlever un &eacute;l&eacute;ment, cliquer-droite sur le fichier concern&eacute; et s&eacute;lectionner "Supprimer Raccourci".</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/themirrorview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/themirrorview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/themirrorview.htm	(revision 13928)
@@ -0,0 +1,19 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="themirrorview"><font face="Verdana" size="5"><strong>3.1: La vue T&eacute;l&eacute;chargement</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Cette section d&eacute;crit comment on configure une tache de t&eacute;l&eacute;chargement et comment on contr&ocirc;le le t&eacute;l&eacute;chargement. Acc&eacute;dez &agrave; la vue "T&eacute;l&eacute;chargement" en cliquant son index. La moiti&eacute; sup&eacute;rieure de l'&eacute;cran montre le contr&ocirc;le des t&eacute;l&eacute;chargements. La moiti&eacute; inf&eacute;rieure est initialement vide, mais montrera la liste des t&eacute;l&eacute;chargements en attente et r&eacute;alis&eacute;s.</p>
+<p>Les fichiers sont t&eacute;l&eacute;charg&eacute;s dans un dossier de l'espace de travail appel&eacute; &laquo;&nbsp;Fichiers T&eacute;l&eacute;charg&eacute;s&nbsp;&raquo;, et peut &ecirc;tre utilis&eacute; pour toutes les collections construites avec l'interface biblioth&eacute;caire. Les fichiers dans cette zone portent comme nom leur URL en entier. Un nouveau dossier est cr&eacute;&eacute; pour chaque site h&ocirc;te, suivi par d'autres dossiers pour chaque &eacute;l&eacute;ment du chemin. Cela permet de s'assurer que chaque fichier a un nom distinct.</p>
+<p>Utilisez le premier des contr&ocirc;les de la configuration de t&eacute;l&eacute;chargement, &laquo; Source URL &raquo;, pour entrer l'URL de la ressource cible. Utilisez le contr&ocirc;le &laquo; Profondeur de T&eacute;l&eacute;chargement &raquo;  pour limiter le nombre de liens hypertextes &agrave; suivre pour le t&eacute;l&eacute;chargement : utiliser 0 pour t&eacute;l&eacute;charger une seule page ; utiliser 1 pour t&eacute;l&eacute;charger la page et toutes les pages r&eacute;f&eacute;renc&eacute;es par des liens hypertextes. La profondeur limite est ignor&eacute;e lors du t&eacute;l&eacute;chargement de m&eacute;dia autres que des pages html. Ensuite il y a plusieurs cases &agrave; cocher qui peuvent &ecirc;tre coch&eacute;es pour activer l'option sp&eacute;cifi&eacute;e. Une fois la configuration pr&ecirc;te, cliquez &laquo; T&eacute;l&eacute;charger &raquo; pour d&eacute;marrer l'op&eacute;ration de t&eacute;l&eacute;chargement. Il y a deux autres boutons de contr&ocirc;le : &laquo; Pr&eacute;f&eacute;rences &raquo;, qui renvoie &agrave; la section connexion de Pr&eacute;f&eacute;rences ou les param&egrave;tre du proxy peuvent &ecirc;tre &eacute;dit&eacute;s ; et &laquo; Effacer la cache &raquo; qui supprimes tous les fichiers t&eacute;l&eacute;charg&eacute;s pr&eacute;c&eacute;demment.</p>
+<p>La liste de t&eacute;l&eacute;chargement a une entr&eacute;e pour chaque t&eacute;l&eacute;chargement de page Web.  Chaque entr&eacute;e a une r&eacute;gion de textes qui donne les d&eacute;tails de la t&acirc;che avec une barre de progr&egrave;s montrant l'activit&eacute; courante.  Trois boutons apparaissent &agrave; la gauche de chaque entr&eacute;e.  "Pause" est employ&eacute; pour pauser une t&acirc;che en cours de t&eacute;l&eacute;chargement.  "Voir le r&eacute;sum&eacute;" ouvre une fen&ecirc;tre montrant l'historique du t&eacute;l&eacute;chargement.  "Fermer" termine le t&eacute;l&eacute;chargement et enl&egrave;ve la t&acirc;che de la liste.</p>
+<p>La section <a href="preferences.htm">Pr&eacute;f&eacute;rences</a> explique comment &eacute;tablir une connection Internet &agrave; travers un proxy.  Si l'authentification est n&eacute;cessaire, le proxy server demande l'identification et le mot de passe.  L'interface biblioth&eacute;caire n'enregistre pas les mots de passe entre les sessions.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/translatetext.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/translatetext.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/translatetext.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="translatetext"><font face="Verdana" size="5"><strong>6.10: Traduire Texte</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Cette section d&eacute;crit l'Affichage de traduction, o&ugrave; on peut d&eacute;finir des fragments de texte sp&eacute;cifiques &agrave; un langage pour des parties de l'interface de la collection. Sous "Sections de conception", cliquer sur "Traduire Texte".</p>
+<p>Choisir d'abord une entr&eacute;e dans la liste "Caract&eacute;ristiques". Les cha&icirc;nes sp&eacute;cifiques &agrave; un langage associ&eacute;es &agrave; la caract&eacute;ristiques apparaissent en bas. Utiliser la liste d&eacute;roulante de "Traduction de Langage" pour s&eacute;lectionner le langage cible, et saisir le texte traduit dans la zone de texte, en se ref&eacute;rant &agrave; "Fragment de Texte Initial" si n&eacute;cessaire. Cliquez sur "Ajouter Traduction" &agrave; la fin de l'op&eacute;ration. </p>
+<p>Pour supprimer une traduction existante, s&eacute;lectionner-la &agrave; partir du tableau "Traduction Assign&eacute;e" et cliquer sur "Enlever Traduction". </p>
+<p>Pour &eacute;diter une traduction, s&eacute;lectionner-la et &eacute;diter-la dans la zone de texte "Texte Traduit", et cliquer sur "Remplacer Traduction". </p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/updatingmetadata.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/updatingmetadata.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/updatingmetadata.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="updatingmetadata"><font face="Verdana" size="5"><strong>5.5: Editant ou &Eacute;liminant M&eacute;ta-donn&eacute;es</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Pour &eacute;diter ou &eacute;liminer une partie de metadata, premi&egrave;rement selectionnez un fichier convenable, en suite la valeur de la metadata du tableau. Editer la valeur de champ supprimant tout le texte si vous d&eacute;sirez &eacute;liminer la metadata.</p>
+<p>Le processus est identique pour la mise &agrave; jour d'un dossier avec des sous-dossiers ou plusieurs fichiers, mais vous pouvez seulement mettre &agrave; jour les m&eacute;ta-donn&eacute;es qui sont communes &agrave; tous les fichiers/dossiers s&eacute;lectionn&eacute;s.</p>
+<p>L' arbre de valeurs montre toutes les valeurs actuellement assign&eacute;es de m&ecirc;me que les valeurs pr&eacute;c&eacute;dentes pour la pr&eacute;sente session, toutes les valeurs &eacute;dit&eacute;s ou &eacute;limin&eacute;e seront donc pr&eacute;sentes dans l' arbre. Fermant la collection et la ouvrant encore une fois &eacute;liminera les valeurs qui ne sont plus d&eacute;sign&eacute;es.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/fr/xcollectionsearching.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/fr/xcollectionsearching.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/fr/xcollectionsearching.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="xcollectionsearching"><font face="Verdana" size="5"><strong>6.7: Recherches &agrave; travers collections</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Greenstone peut rechercher dans plusieurs collections comme si elles n'en constituaient qu'une. Ceci est fait en sp&eacute;cifiant une liste d' une autre collection &agrave; rechercher au m&ecirc;me temps que celle en recherche. Sous "Sections de conception", cliquez sur "Recherche unique &agrave; travers plusieurs collections".</p>
+<p>L'Affichage de Recherche unique &agrave; travers des collections montre une liste de collections disponibles. La collection courante est coch&eacute;e et ne peut &ecirc;tre d&eacute;-s&eacute;lectionn&eacute;e. Pour ajouter une autre collection qu'on peut rechercher parall&egrave;lement, cliquer sur une collection dans la liste (cliquer une deuxi&egrave;me fois pour l'enlever). Lorsqu'une seule collection est s&eacute;lectionn&eacute;e, aucune recherche &agrave; travers collections n'est possible.</p>
+<p>Si les collections individuelles n'ont pas les m&ecirc;mes indexes (y compris les les partitions de sous-collection et les partitions de language), la recherche ne pourra pas fonctionner. L'utilisateur ne pourra alors qu'effectuer des recherches en utilisant les indexes communs &agrave; toutes les collections.</p>
+<p>Pour plus de d&eacute;tails, voir Chapitre 1 du Guide du D&eacute;veloppeur Greenstone.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/gen-index-xml.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/gen-index-xml.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/gen-index-xml.xsl	(revision 13928)
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+  <xsl:output method="xml" encoding="UTF-8"/>
+
+  <xsl:template match="Document">
+    <Document>
+    <xsl:for-each select="Section">
+      <xsl:call-template name="processSection"/>
+    </xsl:for-each>
+    </Document>
+  </xsl:template>
+
+  <xsl:template name="processSection">
+    <Section name="{@name}">
+      <xsl:for-each select="Title">
+        <Title>
+          <xsl:apply-templates select="Text"/>
+        </Title>
+      </xsl:for-each>
+
+      <xsl:for-each select="Section">
+        <xsl:call-template name="processSection"/>
+      </xsl:for-each>
+    </Section>
+  </xsl:template>
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gli/help/gen-many-html.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/gen-many-html.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/gen-many-html.xsl	(revision 13928)
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0" 
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xalan/java"
+  extension-element-prefixes="java"
+  exclude-result-prefixes="java">
+
+  <xsl:output method="html" encoding="UTF-8"/>
+
+  <xsl:variable name="diction" select="java:Dictionary.new('en')"/>
+
+
+  <xsl:template match="Document">
+    <xsl:for-each select="Section">
+      <xsl:call-template name="processSection">
+	<xsl:with-param name="sectionHead" select="position()"/>
+      </xsl:call-template>
+    </xsl:for-each>
+  </xsl:template>
+
+
+  <xsl:template match="Reference">
+    <xsl:variable name="target" select="@target"/>
+    <a href="{@target}.htm"><xsl:value-of select="/Document//Section[@name=$target]/Title/Text"/></a>
+  </xsl:template>
+
+
+  <xsl:template match="Section"/>
+
+
+  <xsl:template match="Title"/>
+
+  <xsl:template match="Text">
+    <p><xsl:apply-templates/></p>
+  </xsl:template>
+
+  <xsl:template name="processSection">
+    <xsl:param name="sectionHead"/>
+
+    <html>
+      <head>
+        <title>The Greenstone Librarian Interface - Help Pages</title>
+      </head>
+      <body bgcolor="#E0F0E0">
+        <table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+          <tr>
+            <td align="center" width="15%">
+              <img height="45" src="../gatherer_medium.gif" width="45"/>
+            </td>
+            <td align="center" width="*">
+              <a name="{@name}">
+                <xsl:call-template name="processTitle">
+                  <xsl:with-param name="sectionNumber" select="$sectionHead"/>
+	          <xsl:with-param name="sectionTitle" select="Title"/>
+                </xsl:call-template>
+              </a>	    
+            </td>
+            <td align="center" width="15%">
+              <img height="45" src="../gatherer_medium.gif" width="45"/>
+            </td>
+          </tr>
+        </table>
+
+        <xsl:apply-templates/>
+      </body>
+    </html>
+
+    <xsl:for-each select="Section">
+      <xsl:call-template name="processSection">
+        <xsl:with-param name="sectionHead" select="concat($sectionHead, '.', position())"/>
+      </xsl:call-template>
+    </xsl:for-each>
+  </xsl:template>
+
+
+  <xsl:template name="processTitle">
+    <xsl:param name="sectionNumber"/>
+    <xsl:param name="sectionTitle"/>
+
+    <font face="Verdana" size="5">
+      <strong>
+        <xsl:value-of select="concat($sectionNumber, ': ', $sectionTitle/Text)"/>
+      </strong>
+    </font>
+  </xsl:template>
+
+   <xsl:template match="span|img|table|b|br|td|tr|u|i">
+    <xsl:copy><xsl:for-each select="@*"><xsl:copy/></xsl:for-each>
+        <xsl:apply-templates/>
+    </xsl:copy>
+  </xsl:template>
+
+  <xsl:template match="AutoText">
+    <xsl:variable name="value"><xsl:choose><xsl:when test="@key"><xsl:value-of select="java:get($diction, @key, @args)"/></xsl:when><xsl:otherwise><xsl:value-of select="@text"/></xsl:otherwise></xsl:choose></xsl:variable>
+    <xsl:choose>
+      <xsl:when test="@type='button'">
+	<b>&lt;<xsl:value-of select="$value"/>&gt;</b>
+      </xsl:when>
+      <xsl:when test="@type='quoted'">
+	<xsl:text>"</xsl:text><xsl:value-of select="$value"/><xsl:text>"</xsl:text>
+      </xsl:when>
+      <xsl:when test="@type='italics'">
+	<i><xsl:value-of select="$value"/></i>
+      </xsl:when>      
+      <xsl:when test="@type='plain'">
+	<xsl:value-of select="$value"/>
+      </xsl:when>      
+      <xsl:when test="@type='bold'">
+	<b><xsl:value-of select="$value"/></b>
+      </xsl:when>      
+      <xsl:otherwise>
+	<xsl:text>"</xsl:text><xsl:value-of select="$value"/><xsl:text>"</xsl:text>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gli/help/gen-one-html-for-doc.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/gen-one-html-for-doc.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/gen-one-html-for-doc.xsl	(revision 13928)
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+  <xsl:output method="html" encoding="UTF-8"/>
+
+  <xsl:template match="Document">
+    <html>
+      <head>
+        <title>The Greenstone Librarian Interface - Help Pages</title>
+      </head>
+      <body bgcolor="#E0F0E0">
+	<xsl:for-each select="Section">
+	  <!-- Skip the first section -->
+	  <xsl:if test="position() > 1">
+	    <xsl:call-template name="processSection">
+	      <xsl:with-param name="sectionHead" select="position()"/>
+	    </xsl:call-template>
+          </xsl:if>
+	</xsl:for-each>
+      </body>
+    </html>
+  </xsl:template>
+
+  <xsl:template match="Reference">
+    <xsl:variable name="target" select="@target"/>
+    <xsl:value-of select="/Document//Section[@name=$target]/Title/Text"/>
+  </xsl:template>
+
+  <xsl:template match="Section"/>
+
+  <xsl:template match="Title"/>
+
+
+  <xsl:template name="processSection">
+    <xsl:param name="sectionHead"/>
+
+    <xsl:if test="Title">
+        <xsl:call-template name="processTitle">
+          <xsl:with-param name="sectionNumber" select="$sectionHead"/>
+	  <xsl:with-param name="sectionTitle" select="Title"/>
+        </xsl:call-template>
+    </xsl:if>
+
+    <xsl:apply-templates/>
+
+    <xsl:for-each select="Section">
+      <xsl:call-template name="processSection">
+        <xsl:with-param name="sectionHead" select="concat($sectionHead, '.', position())"/>
+      </xsl:call-template>
+    </xsl:for-each>
+  </xsl:template>
+
+
+  <xsl:template name="processTitle">
+    <xsl:param name="sectionNumber"/>
+    <xsl:param name="sectionTitle"/>
+
+    <xsl:choose>
+      <xsl:when test="contains($sectionNumber, '.')">
+        <h4><xsl:value-of select="$sectionTitle/Text"/></h4>
+      </xsl:when>
+      <xsl:otherwise>
+        <h3><xsl:value-of select="$sectionTitle/Text"/></h3>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template match="Text">
+    <p><xsl:apply-templates/></p>
+  </xsl:template>
+
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gli/help/gen-one-html.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/gen-one-html.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/gen-one-html.xsl	(revision 13928)
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+  <xsl:output method="html" encoding="UTF-8"/>
+
+  <xsl:template match="Document">
+    <html>
+      <head>
+        <title>The Greenstone Librarian Interface - Help Pages</title>
+      </head>
+      <body bgcolor="#E0F0E0">
+	<xsl:for-each select="Section">
+	  <xsl:call-template name="processSection">
+	    <xsl:with-param name="sectionHead" select="position()"/>
+	  </xsl:call-template>
+	</xsl:for-each>
+      </body>
+    </html>
+  </xsl:template>
+
+  <xsl:template match="Reference">
+    <xsl:variable name="target" select="@target"/>
+    <a href="#{@target}"><xsl:value-of select="/Document//Section[@name=$target]/Title/Text"/></a>
+  </xsl:template>
+
+  <xsl:template match="Section"/>
+
+  <xsl:template match="Title"/>
+
+
+  <xsl:template name="processSection">
+    <xsl:param name="sectionHead"/>
+
+    <xsl:if test="Title">
+      <a name="{@name}">
+        <xsl:call-template name="processTitle">
+          <xsl:with-param name="sectionNumber" select="$sectionHead"/>
+	  <xsl:with-param name="sectionTitle" select="Title"/>
+        </xsl:call-template>
+      </a>
+    </xsl:if>
+
+    <xsl:apply-templates/>
+
+    <xsl:for-each select="Section">
+      <xsl:call-template name="processSection">
+        <xsl:with-param name="sectionHead" select="concat($sectionHead, '.', position())"/>
+      </xsl:call-template>
+    </xsl:for-each>
+  </xsl:template>
+
+
+  <xsl:template name="processTitle">
+    <xsl:param name="sectionNumber"/>
+    <xsl:param name="sectionTitle"/>
+
+    <xsl:choose>
+      <xsl:when test="contains($sectionNumber, '.')">
+        <h3>Section <xsl:value-of select="concat($sectionNumber, ': ', $sectionTitle/Text)"/></h3>
+      </xsl:when>
+      <xsl:otherwise>
+        <h1>Section <xsl:value-of select="concat($sectionNumber, ': ', $sectionTitle/Text)"/></h1>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template match="Text">
+    <p><xsl:apply-templates/></p>
+  </xsl:template>
+
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gli/help/gen-one-tex.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/gen-one-tex.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/gen-one-tex.xsl	(revision 13928)
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+  <xsl:output method="text" encoding="iso-8859-1"/>
+
+  <xsl:template match="Document-old">
+    <html>
+      <head>
+        <title>The Greenstone Librarian Interface - Help Pages</title>
+      </head>
+      <body bgcolor="#E0F0E0">
+	<xsl:for-each select="Section">
+	  <!-- Skip the first section -->
+	  <xsl:if test="position() > 1">
+	    <xsl:call-template name="processSection">
+	      <xsl:with-param name="sectionHead" select="position()"/>
+	    </xsl:call-template>
+          </xsl:if>
+	</xsl:for-each>
+      </body>
+    </html>
+  </xsl:template>
+
+  <xsl:template match="Document">
+    % START OF AUTO-GENERATED GLI USER GUIDE
+    <xsl:for-each select="Section">
+      <!-- Skip the first section -->
+      <xsl:if test="position() > 1">
+	<xsl:call-template name="processSection">
+	  <xsl:with-param name="sectionHead" select="position()"/>
+	</xsl:call-template>
+      </xsl:if>
+    </xsl:for-each>
+  </xsl:template>
+
+  <xsl:template match="Reference">
+    <xsl:variable name="target" select="@target"/>
+    <xsl:value-of select="/Document//Section[@name=$target]/Title/Text"/>
+  </xsl:template>
+
+  <xsl:template match="Section"/>
+
+  <xsl:template match="Title"/>
+
+
+  <xsl:template name="processSection">
+    <xsl:param name="sectionHead"/>
+
+    <xsl:if test="Title">
+        <xsl:call-template name="processTitle">
+          <xsl:with-param name="sectionNumber" select="$sectionHead"/>
+	  <xsl:with-param name="sectionTitle" select="Title"/>
+        </xsl:call-template>
+    </xsl:if>
+
+    <xsl:apply-templates/>
+
+    <xsl:for-each select="Section">
+      <xsl:call-template name="processSection">
+        <xsl:with-param name="sectionHead" select="concat($sectionHead, '.', position())"/>
+      </xsl:call-template>
+    </xsl:for-each>
+  </xsl:template>
+
+
+  <xsl:template name="processTitle">
+    <xsl:param name="sectionNumber"/>
+    <xsl:param name="sectionTitle"/>
+
+    <xsl:choose>
+      <xsl:when test="contains($sectionNumber, '.')">
+        <!--<h4><xsl:value-of select="$sectionTitle"/></h4>-->
+\paragraph{\emph{<xsl:value-of select="$sectionTitle/Text"/>}}<xsl:text>
+	</xsl:text>
+      </xsl:when>
+      <xsl:otherwise>
+        <!--<h3><xsl:value-of select="$sectionTitle"/></h3>-->
+\subsubsection{<xsl:value-of select="$sectionTitle/Text"/>}<xsl:text>
+	</xsl:text>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template match="Text">
+    <xsl:apply-templates/><xsl:text>
+</xsl:text>
+  </xsl:template>
+
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gli/help/gen-text.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/gen-text.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/gen-text.xsl	(revision 13928)
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xalan/java"
+  extension-element-prefixes="java"
+  exclude-result-prefixes="java">
+
+  <xsl:output method="text" encoding="UTF-8"/>
+
+  <xsl:variable name="diction" select="java:Dictionary.new('en')"/>
+
+  <xsl:template match="AutoText">
+    <xsl:text>"</xsl:text><xsl:choose><xsl:when test="@key"><xsl:value-of select="java:get($diction, @key, @args)"/></xsl:when><xsl:otherwise><xsl:value-of select="@text"/></xsl:otherwise></xsl:choose><xsl:text>"</xsl:text>
+  </xsl:template>
+
+  <xsl:template match="Reference">
+    <xsl:variable name="target" select="@target"/>
+    <xsl:text>"</xsl:text><xsl:value-of select="/Document//Section[@name=$target]/Title/Text"/><xsl:text>"</xsl:text>
+  </xsl:template>
+  
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gli/help/generate-html.sh
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/generate-html.sh	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/generate-html.sh	(revision 13928)
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+glihome=$GSDLHOME/gli
+
+if [ "$glihome" == "" ]; then
+    # assume glihelp in its usual place
+      pushd ../ > /dev/null
+      glihome=`pwd`
+      popd > /dev/null
+fi
+
+echo "processing english version"
+cd en
+java -cp $glihome -DGSDLHOME=$GSDLHOME ApplyXSLT ../gen-many-html.xsl help.xml | perl -S ../splithelpdocument.pl
+java -cp $glihome -DGSDLHOME=$GSDLHOME ApplyXSLT ../gen-index-xml.xsl help.xml > help_index.xml
+cd ..
+
+
+
Index: /tags/greenstone-3_02-distribution/gli/help/ru/addingfiles.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/addingfiles.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/addingfiles.htm	(revision 13928)
@@ -0,0 +1,37 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="addingfiles"><font face="Verdana" size="5"><strong>4.3: ÐÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÐµ ÑÐ°Ð¹Ð»ÐŸÐ²</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð€Ð°Ð¹Ð»Ñ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÐœÑ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐŒÑÑÑÑ Ð¿ÑÑÐµÐŒ ÐžÑ
+ Ð¿ÐµÑÐµÑÑÐ³ÐžÐ²Ð°ÐœÐžÑ Ðž ÐŸÑÐ¿ÑÑÐºÐ°ÐœÐžÑ. Ð£ÐºÐ°Ð·Ð°ÑÐµÐ»Ñ ÐŒÑÑÐž ÐŸÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑÑÑ ÐœÐ°ÐŽ ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÑÐŒ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐŒ ÐžÐ»Ðž, ÐµÑÐ»Ðž Ð²ÑÐ±ÐžÑÐ°ÐµÑÑÑ Ð±ÐŸÐ»ÑÑÐµ,ÑÐµÐŒ ÐŸÐŽÐžÐœ,ÐœÐ°ÐŽ ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÐŒÐž. ÐÑÐŸÐ¿ÑÑÑÐžÑÐµ Ð²ÑÐ±ÑÐ°ÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» Ð² ÐÐµÑÐµÐ²ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÑÐŸÐ±Ñ Ð·ÐŽÐµÑÑ ÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÑÑ ÑÐ°Ð¹Ð»Ñ (ÐµÑÐ»Ðž ÐžÑÑÐŸÑÐœÐžÐºÐŸÐŒ Ð±ÑÐ»ÐŸ ÐÐµÑÐµÐ²ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž).</p>
+<p>ÐÑÐž ÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÐœÐžÐž ÐŒÐœÐŸÐ¶ÐµÑÑÐ²ÐµÐœÐœÑÑ
+(ÑÐŸÑÑÐ°Ð²ÐœÑÑ
+) ÑÐ°Ð¹Ð»ÐŸÐ²,Ð²ÑÐµ ÐŸÐœÐž Ð¿ÐµÑÐµÐŒÐµÑÐ°ÑÑÑÑ Ð² ÑÐµÐ»ÐµÐ²ÑÑ Ð¿Ð°Ð¿ÐºÑ ÐœÐ° ÑÐŸÑ Ð¶Ðµ ÑÐ°ÐŒÑÐ¹ ÑÑÐŸÐ²ÐµÐœÑ,ÐœÐµÐ·Ð°Ð²ÐžÑÐžÐŒÐŸ ÐŸÑ ÑÑÑÑÐºÑÑÑÑ Ð¿Ð°Ð¿ÐºÐž,ÐºÐŸÑÐŸÑÑÑ ÐŸÐœÐž Ð·Ð°ÐœÐžÐŒÐ°Ð»Ðž Ð¿ÐµÑÐ²ÐŸÐœÐ°ÑÐ°Ð»ÑÐœÐŸ. ÐÐŸÐ³ÐŽÐ° ÐÑ ÐºÐŸÐ¿ÐžÑÑÐµÑÐµ Ð²ÑÐŸÑÐŸÐ¹ ÑÐ°Ð¹Ð» Ñ ÑÐµÐŒ Ð¶Ðµ ÑÐ°ÐŒÑÐŒ ÐžÐŒÐµÐœÐµÐŒ Ð² ÑÑ Ð¶Ðµ ÑÐ°ÐŒÑÑ Ð¿Ð°Ð¿ÐºÑ, ÐÐ°Ñ Ð·Ð°Ð¿ÑÐŸÑÑÑ, Ð·Ð°ÑÐµÑÐµÑÑ Ð»Ðž Ð¿ÐµÑÐ²ÑÐ¹. ÐÑÐ²ÐµÑÑÑÐµ "ÐÐµÑ" Ðž ÑÑÐŸÑ ÑÐ°Ð¹Ð» ÐœÐµ Ð±ÑÐŽÐµÑ ÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÑÑÑÑ,ÐœÐŸ ÐŽÑÑÐ³ÐžÐµ Ð±ÑÐŽÑÑ. Ð§ÑÐŸÐ±Ñ ÐŸÑÐŒÐµÐœÐžÑÑ Ð²ÑÐµ ÐŸÑÑÐ°ÑÑÐžÐµÑÑ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ Ð¿ÐŸ ÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÐœÐžÑ,ÑÐµÐ»ÐºÐœÐžÑÐµ ÐœÐ° ÐºÐœÐŸÐ¿ÐºÐµ "Ð¡ÑÐŸÐ¿".   </p>
+<p>Ð¢ÐŸÐ»ÑÐºÐŸ "ÑÐ°ÐŒÑÐµ Ð²ÑÑÐŸÐºÐžÐµ"ÐžÐ· ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÑÑ
+ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² Ð±ÑÐŽÑÑ Ð¿ÐµÑÐµÐŒÐµÑÐµÐœÑ. ÐÐ°Ð¿ÐºÐ° Ð²ÑÑÐµ, ÑÐµÐŒ ÐµÑ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐœÑÐµ. ÐÑ ÐœÐµ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐ±ÑÐ°ÑÑ ÑÐ°Ð¹Ð»Ñ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ Ð¿Ð°Ð¿ÐºÐž,Ð° ÑÐ°ÐºÐ¶Ðµ ÑÐ°ÐŒÑ Ð¿Ð°Ð¿ÐºÑ ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ. </p>
+<p>ÐÐŸÐ³ÐŽÐ° ÐÑ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑÐµ ÑÐ°Ð¹Ð», ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÑÐŸÐ²ÐŸÐŽÐžÑ Ð¿ÐŸÐžÑÐº Ð² ÐžÑÑ
+ÐŸÐŽÐœÑÑ
+ Ð¿Ð°Ð¿ÐºÐ°Ñ
+ Ð²ÑÐ¿ÐŸÐŒÐŸÐ³Ð°ÑÐµÐ»ÑÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ², ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐžÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ Ðº ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÐŒÐŸÐŒÑ ÑÐ°Ð¹Ð»Ñ,Ðž ÐµÑÐ»Ðž ÐŸÐœ ÐœÐ°Ñ
+ÐŸÐŽÐžÑ ÐµÐ³ÐŸ,ÑÐŸ ÐœÐ°ÑÐžÐœÐ°ÐµÑ ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÑÑÐž ÐŽÐ°ÐœÐœÑÐµ. ÐÑÐ»Ðž Ð¿ÑÐŸÑÐµÑÑ Ð¿ÑÐŸÐŽÐŸÐ»Ð¶Ð°ÐµÑÑÑ,ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð±ÑÑÑ Ð·Ð°Ð¿ÑÐŸÑÐµÐœÑ (Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÑÐ°Ð·) ÐŸ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž,ÑÑÐŸÐ±Ñ ÐŽÐŸÑÑÐžÑÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÑ ÐžÐŒÐ¿ÐŸÑÑÐžÑÑÐµÐŒÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ñ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒÐž,ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐœÑÐŒÐž Ð² ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð­ÑÐŸÑ Ð¿ÑÐŸÑÐµÑÑ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÐŒÐœÐŸÐ³ÐžÐµ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ Ð·Ð°Ð¿ÑÐŸÑÑ, ÐŸÐ¿ÐžÑÐ°ÐœÐœÑÐµ Ð² ÑÐ°Ð·ÐŽÐµÐ»Ðµ<a href="importingpreviouslyassignedmetadata.htm">ÐÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</a>.ÐÐ»Ñ Ð±ÐŸÐ»ÐµÐµ ÐŽÐµÑÐ°Ð»ÑÐœÐŸÐ³ÐŸ ÐŸÐ±ÑÑÑÐœÐµÐœÐžÑ Ð°ÑÑÐŸÑÐžÐžÑÐŸÐ²Ð°ÐœÐœÑÑ
+ Ñ ÑÐ°Ð¹Ð»Ð°ÐŒÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÑÐžÑÐ°Ð¹ÑÐµ ÐÐ»Ð°Ð²Ñ 2 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone - ÐÐ·Ð²Ð»ÐµÑÐµÐœÐžÐµ Ð±ÐŸÐ»ÑÑÐžÐœÑÑÐ²Ð° Ð²Ð°ÑÐžÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ².  </p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/addingpreviouslydefinedmetadata.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/addingpreviouslydefinedmetadata.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/addingpreviouslydefinedmetadata.htm	(revision 13928)
@@ -0,0 +1,21 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="addingpreviouslydefinedmetadata"><font face="Verdana" size="5"><strong>5.4: ÐÐŸÐ±Ð°Ð²Ð»ÐœÐžÐµ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐŽÐµÑÐ¶Ð°Ñ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ, ÑÐœÐ°ÑÐ°Ð»Ð° Ð²ÑÐ±ÐµÑÐžÑÐµ ÑÐ°Ð¹Ð», Ð·Ð°ÑÐµÐŒ ÑÑÐµÐ±ÑÐµÐŒÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐžÐ· ÐŽÐµÑÐµÐ²Ð° Ð·ÐœÐ°ÑÐµÐœÐžÐ¹, ÑÐ°ÑÑÐžÑÑÑ Ð¿Ð°Ð¿ÐºÐž ÐžÐµÑÐ°ÑÑ
+ÐžÐž Ð¿ÐŸ ÐŒÐµÑÐµ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÑÑÐž. ÐÑÐ±ÑÐ°ÐœÐœÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ Ð² Ð¿ÐŸÐ»Ðµ ÑÐµÐºÑÑÐ° (Ð°Ð»ÑÑÐµÑÐœÐ°ÑÐžÐ²ÐœÐŸ ÐŒÐŸÐ¶ÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð°Ð²ÑÐŸÐ²ÑÐ±ÐŸÑ Ð² ÐŽÐµÑÐµÐ²Ðµ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ Ðž ÑÑÐµÐŽÑÑÐ² Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐŸÐ³ÐŸ Ð·Ð°Ð²ÐµÑÑÐµÐœÐžÑ). </p>
+<p>ÐÑÐŸÑÐµÑÑ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ñ ÑÐ¶Ðµ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐŒÐž Ð·ÐœÐ°ÑÐµÐœÐžÑÐŒÐž Ðº Ð¿Ð°Ð¿ÐºÐ°ÐŒ ÐžÐ»Ðž ÐŒÐœÐŸÐ¶ÐµÑÑÐ²Ñ ÑÐ°Ð¹Ð»ÐŸÐ² ÑÐ°ÐºÐŸÐ¹ Ð¶Ðµ.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/appendingmetadata.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/appendingmetadata.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/appendingmetadata.htm	(revision 13928)
@@ -0,0 +1,30 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="appendingmetadata"><font face="Verdana" size="5"><strong>5.3: ÐÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð¢ÐµÐ¿ÐµÑÑ ÐŒÑ ÐŽÐŸÐ±Ð°Ð²ÐžÐŒ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ - Ðž ÑÐ°ÐŒ ÑÐ»ÐµÐŒÐµÐœÑ,Ðž ÐµÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÑ - Ðº ÑÐ°Ð¹Ð»Ñ. Ð¡ÐœÐ°ÑÐ°Ð»Ð° Ð²ÑÐ±ÐµÑÐµÐŒ ÑÐ°Ð¹Ð» ÐžÐ· ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ³ÐŸ ÐŽÐµÑÐµÐ²Ð° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.Ð¢Ð°ÐºÐŸÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ Ð²ÑÐ·ÑÐ²Ð°ÐµÑ Ð¿ÐŸÑÐ²Ð»ÐµÐœÐžÐµ Ð»ÑÐ±ÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+,Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ ÑÐ²ÑÐ·Ð°ÐœÐœÑÑ
+ Ñ ÑÑÐžÐŒ ÑÐ°Ð¹Ð»ÐŸÐŒ,Ð² ÑÐ°Ð±Ð»ÐžÑÐµ ÑÐ¿ÑÐ°Ð²Ð°. </p>
+<p>ÐÐ°ÑÐµÐŒ Ð²ÑÐ±ÐµÑÐµÐŒ ÑÐ»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+,ÐºÐŸÑÐŸÑÑÐ¹ Ñ
+ÐŸÑÐžÐŒ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ,Ð¿ÑÑÐµÐŒ ÑÐµÐ»ÑÐºÐ° ÑÑÐŽÐŸÐŒ Ñ ÐœÐžÐŒ Ð² ÑÐ°Ð±Ð»ÐžÑÐµ. </p>
+<p>ÐÐ¿ÐžÑÐžÑÐµ ÑÑÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ Ð² Ð¿ÐŸÐ»Ðµ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ Ð·ÐœÐ°Ðº "|", ÑÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÑÑÑÑÐºÑÑÑÑ, ÐºÐ°Ðº ÐŸÐ¿ÐžÑÐ°ÐœÐŸ Ð² ÑÐµÐºÑÐžÐž <a href="theenrichview.htm">ÐÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐŸÐ±ÐŸÐ³Ð°ÑÐµÐœÐžÑ</a>. ÐÐ°Ð¶Ð°Ð² ÐºÐ»Ð°Ð²ÐžÑÐž [ÐÐ²ÐµÑÑ
+] ÐžÐ»Ðž [ÐÐœÐžÐ·], ÐÑ ÑÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐ±ÑÐ°ÑÑ ÑÑÐµÐ±ÑÐµÐŒÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ. ÐÐ°Ð¶Ð°Ð² ÐºÐ»Ð°Ð²ÐžÑÑ [Enter], ÐÑ ÑÐŒÐŸÐ¶ÐµÑÐµ ÑÐŸÑ
+ÑÐ°ÐœÐžÑÑ Ð²ÑÐ±ÑÐ°ÐœÐœÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ðž ÑÐŸÐ·ÐŽÐ°ÑÑ ÐœÐŸÐ²ÐŸÐµ ÐœÐµÐ·Ð°Ð¿ÐŸÐ»ÐœÐµÐœÐœÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐŽÐ»Ñ ÑÐ»ÐµÐŒÐµÐœÑÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, Ð¿ÐŸÐ·Ð²ÐŸÐ»ÐžÐ² ÐÐ°ÐŒ ÐŸÐ¿ÑÐµÐŽÐžÐ»ÐžÑÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ ÐŽÐ»Ñ ÐŸÐŽÐœÐŸÐ³ÐŸ ÑÐ»ÐµÐŒÐµÐœÑÐ°.</p>
+<p>ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐ°ÐºÐ¶Ðµ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ðº Ð¿Ð°Ð¿ÐºÐµ ÐžÐ»Ðž ÑÑÐ°Ð·Ñ Ðº ÐœÐµÐºÐŸÑÐŸÑÐŸÐŒÑ ÐŒÐœÐŸÐ¶ÐµÑÑÐ²Ñ ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ². Ð­ÑÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑÑÑ ÐºÐŸ Ð²ÑÐµÐŒ ÑÐ°Ð¹Ð»Ð°ÐŒ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ Ð¿Ð°Ð¿ÐºÐž ÐžÐ»Ðž Ðº ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÑÐŒ Ðž Ðº Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐœÑÐŒ Ð¿Ð°Ð¿ÐºÐ°ÐŒ. ÐÐŒÐµÐ¹ÑÐµ Ð² Ð²ÐžÐŽÑ,ÑÑÐŸ ÐµÑÐ»Ðž ÐÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÐ»Ðž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ðº Ð¿Ð°Ð¿ÐºÐµ, ÑÐŸ Ð»ÑÐ±ÑÐµ ÐœÐŸÐ²ÑÐµ ÑÐ°Ð¹Ð»Ñ Ð² ÐœÐµÐ¹ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž ÑÐœÐ°ÑÐ»ÐµÐŽÑÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐžÐ· ÑÑÐŸÐ¹ Ð¿Ð°Ð¿ÐºÐž.  </p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/assignlanguages.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/assignlanguages.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/assignlanguages.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="assignlanguages"><font face="Verdana" size="5"><strong>6.6.3: ÐÐ°ÐŽÐ°ÐœÐœÑÐµ ÑÐ·ÑÐºÐž</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŽÐµÑÐ°Ð»ÐžÐ·ÐžÑÐŸÐ²Ð°ÐœÐŸ,ÐºÐ°Ðº ÐŸÐ³ÑÐ°ÐœÐžÑÐžÑÑ ÐžÐœÐŽÐµÐºÑÑ Ð¿ÐŸÐžÑÐºÐ° ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐžÐŒÐž ÑÐ·ÑÐºÐ°ÐŒÐž. ÐÑ ÑÐŸÐ²ÐµÑÑÐ°ÐµÑÐµ ÑÑÐŸ Ð¿ÑÐž ÑÐµÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÐžÐž ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ,ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐºÐ»Ð°Ð²ÐžÑÑ "ÐÐ°ÐŽÐ°ÐœÐœÑÐµ ÑÐ·ÑÐºÐž" Ð² Ð¿ÐµÑÐµÑÐœÐµ "ÐÐœÐŽÐµÐºÑÑ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ".</p>
+<p>Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐœÐŸÐ²ÑÐ¹ ÑÐ·ÑÐº ÐŽÐ»Ñ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐºÐ»Ð°Ð²ÐžÑÑ "ÐÐ°ÐŽÐ°ÐœÐœÑÐµ ÑÐ·ÑÐºÐž" ÐŽÐ»Ñ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐžÐœÐŽÐµÐºÑÐ° ÐŽÐ»Ñ ÑÑÐŸÐ³ÐŸ. ÐÑÐ±ÐµÑÐžÑÐµ Ð¶ÐµÐ»Ð°ÑÐµÐ»ÑÐœÑÐ¹ ÑÐ·ÑÐº ÐžÐ· ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐ³ÐŸ ÑÐ¿ÐžÑÐºÐ° "Ð¯Ð·ÑÐºÐž ÐŽÐ»Ñ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÑ" Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ ÑÐ·ÑÐº"</p>
+<p>Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÑÐ·ÑÐº,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° "ÐÑÐ±ÐŸÑÑ ÑÐ·ÑÐºÐ°" Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ ÑÐ·ÑÐº".</p>
+<p>Ð§ÑÐŸÐ±Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÑÐ·ÑÐº Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÑÑÐ°ÐœÐŸÐ²ÐºÐ° Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ".</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/assignpartitions.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/assignpartitions.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/assignpartitions.htm	(revision 13928)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="assignpartitions"><font face="Verdana" size="5"><strong>6.6.2: ÐÐ°Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>ÐÐŒÐµÑ Ð·Ð°ÐŽÐ°ÐœÐœÑÐ¹ ÑÐžÐ»ÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐºÐ»Ð°Ð²ÐžÑÑ "ÐÐ°Ð·ÐœÐ°ÑÐžÑÑ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ" ÐŽÐ»Ñ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐžÐœÐŽÐµÐºÑÐŸÐ² ÐŽÐ»Ñ ÑÑÐŸÐ³ÐŸ ÐžÐ»Ðž ÐŽÐ»Ñ Ð³ÑÑÐ¿Ð¿Ñ ÑÐžÐ»ÑÑÑÐŸÐ². ÐÑÐ±ÐµÑÐžÑÐµ Ð¶ÐµÐ»Ð°ÑÐµÐ»ÑÐœÑÐ¹ ÑÐžÐ»ÑÑÑ (ÐžÐ»Ðž ÑÐžÐ»ÑÑÑÑ) ÐžÐ· ÑÐ¿ÐžÑÐºÐ° "ÐÐ°ÐŽÐ°ÐœÐœÑÐµ ÑÐžÐ»ÑÑÑÑ ÑÑÐ±ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž", Ð²Ð²ÐµÐŽÐžÑÐµ ÐžÐŒÑ ÐŽÐ»Ñ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ Ð² Ð¿ÐŸÐ»Ðµ "ÐÐŒÑ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ" Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÐµ".</p>
+<p>Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÐµ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÐµ".</p>
+<p>Ð§ÑÐŸÐ±Ñ Ð¿ÑÐŸÐžÐ·Ð²ÐµÑÑÐž ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÐµ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÑÑÐ°ÐœÐŸÐ²ÐžÑÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ".</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/buildsettings.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/buildsettings.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/buildsettings.htm	(revision 13928)
@@ -0,0 +1,22 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="buildsettings"><font face="Verdana" size="5"><strong>7.2: ÐÐŒÐ¿ÐŸÑÑ Ðž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ, ÐºÐ°Ðº Ð¿ÐŸÐ»ÑÑÐžÑÑ ÐŽÐŸÑÑÑÐ¿ Ðº ÑÐ°Ð·Ð»ÐžÑÐœÑÐŒ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑÐŒ ÐžÐŒÐ¿ÐŸÑÑÐ° Ðž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐ°ÐŒ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ. ÐÐ° ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐµÐ¹ Ð¿ÐŸ ÐžÐŒÐ¿ÐŸÑÑÑ Ðž Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÑÐžÑÐ°Ð¹ÑÐµ Ð³Ð»Ð°Ð²Ñ 1 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone.  </p>
+<p>Ð£Ð¿ÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÑÐ°Ð·Ð»ÐžÑÐœÑÐŒÐž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐ°ÐŒÐž ÑÐŽÐµÐ»Ð°ÐœÐŸ Ð¿ÐŸÐŽÐŸÐ±ÐœÐŸ ÑÐŸÐŒÑ ÑÐ¿ÐŸÑÐŸÐ±Ñ, ÐºÐŸÑÐŸÑÑÐ¹ ÐŸÐ¿ÐžÑÐ°Ðœ Ð¿ÑÐž "ÐÐŸÐœÑÐžÐ³ÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐž Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ²" Ð² <a href="plugins.htm">ÐÐ»Ð°Ð³ÐžÐœÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°</a>. ÐÐµÐºÐŸÑÐŸÑÑÐµ Ð¿ÐŸÐ»Ñ ÑÑÐµÐ±ÑÑÑ ÑÐžÑÐ»ÐµÐœÐœÑÑ
+ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ². ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÑ
+ ÐžÐ»Ðž ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°ÑÑ ÐžÐ»Ðž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÑÑÑÐµÐ»ÐºÐž Ð²Ð²ÐµÑÑ
+ Ðž Ð²ÐœÐžÐ·, ÑÑÐŸÐ±Ñ ÑÐ²ÐµÐ»ÐžÑÐžÑÑ ÐžÐ»Ðž ÑÐŒÐµÐœÑÑÐžÑÑ ÑÐµÐºÑÑÐµÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ (Ð² ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ ÑÐ»ÑÑÐ°ÑÑ
+ ÐžÐœÑÐµÑÑÐµÐ¹Ñ ÐŸÐ³ÑÐ°ÐœÐžÑÐžÐ²Ð°ÐµÑ ÐŽÐžÐ°Ð¿Ð°Ð·ÐŸÐœ, Ð² ÐºÐŸÑÐŸÑÑÐ¹ ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÐŸÐ¹ÑÐž). ÐÑÑÐ³ÐžÐµ Ð¿ÐŸÐ»Ñ ÑÐ²Ð»ÑÑÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž Ð¿ÑÐž ÑÐµÐ»ÑÐºÐµ Ð¿ÐŸ ÐºÐœÐŸÐ¿ÐºÐµ (ÐÐŸÐ²ÑÐŸÑÐœÑÐ¹ ÑÐµÐ»ÑÐŸÐº ÐŽÐµÐ»Ð°ÐµÑ ÐžÑ
+ ÐœÐµÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž). </p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/classifiers.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/classifiers.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/classifiers.htm	(revision 13928)
@@ -0,0 +1,23 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="classifiers"><font face="Verdana" size="5"><strong>6.8: ÐÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ,ÐºÐ°Ðº ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ Ðº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐºÐŸÑÐŸÑÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÐŽÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°. Ð "Ð Ð°Ð·ÐŽÐµÐ»Ð°Ñ
+ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°" ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÑÐŸÑÐŒÐŸÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ²". </p>
+<p>Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ,ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐžÐ¹ ÑÐ¿ÐžÑÐŸÐº "ÐÑÐ±ÐŸÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐ° ÐŽÐ»Ñ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÑ" Ð²ÐœÐžÐ·Ñ ÐŸÐºÐœÐ°,Ðž Ð·Ð°ÑÐµÐŒ ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐ±Ð°Ð²ÑÑÐµ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ". ÐÐŸÑÐ²Ð»ÑÐµÑÑÑ ÐŸÐºÐœÐŸ, ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒÐŸÐµ "ÐÐŸÐœÑÐžÐ³ÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ²".ÐÐœÑÑÑÑÐºÑÐžÐž ÐŽÐ»Ñ ÑÑÐŸÐ³ÐŸ ÐŽÐžÐ°Ð»ÐŸÐ³Ð° ÑÐµ Ð¶Ðµ ÑÐ°ÐŒÑÐµ,ÑÑÐŸ ÐºÐ°ÑÐ°ÑÑÑÑ Ð¿Ð»Ð°Ð³ÐžÐœÐŸÐ² (<a href="plugins.htm">ÐÐ»Ð°Ð³ÐžÐœÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°</a>).ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐÑ ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°Ð»Ðž ÐœÐŸÐ²ÑÐ¹ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ, ÐŸÐœ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑÑÑ Ð² ÐºÐŸÐœÐµÑ ÑÐ¿ÐžÑÐºÐ° "Ð¢ÐµÐºÑÑÐžÐµ Ð·Ð°ÐŽÐ°ÐœÐœÑÐµ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ".  </p>
+<p>Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ".</p>
+<p>Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐ°, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐœÑÐžÐ³ÑÑÐžÑÑÐ¹ÑÐµ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ." (ÐžÐ»Ðž ÑÐµÐ»ÐºÐœÑÑÑ ÐŽÐ²Ð° ÑÐ°Ð·Ð° ÐœÐ° ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐµ Ð² ÑÐ¿ÐžÑÐºÐµ).</p>
+<p>ÐÐŸÑÑÐŽÐŸÐº ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ² Ð² ÐœÐ°Ð²ÐžÐ³Ð°ÑÐžÐŸÐœÐœÐŸÐ¹ Ð»ÐžÐœÐµÐ¹ÐºÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐž ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÐµÑ ÑÐŸÐŒÑ,ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÐŸÐºÐ°Ð·Ð°Ðœ Ð·ÐŽÐµÑÑ.Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ Ð¿ÐŸÑÑÐŽÐŸÐº,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ, ÐºÐŸÑÐŸÑÑÐ¹ ÐÑ Ñ
+ÐŸÑÐžÑÐµ Ð¿ÐµÑÐµÐŒÐµÑÑÐžÑÑ, Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐ²ÐžÐ³Ð°ÑÑÑÑ Ð²Ð²ÐµÑÑ
+" ÐžÐ»Ðž "ÐÐ²ÐžÐ³Ð°ÑÑÑÑ Ð²ÐœÐžÐ·".</p>
+<p>ÐÐ»Ñ ÐŽÐ°Ð»ÑÐœÐµÐ¹ÑÐµÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž ÐŸÑÐœÐŸÑÐžÑÐµÐ»ÑÐœÐŸ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ² ÑÐžÑÐ°Ð¹ÑÐµ Ð³Ð»Ð°Ð²Ñ 2 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/collectingfiles.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/collectingfiles.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/collectingfiles.htm	(revision 13928)
@@ -0,0 +1,23 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="collectingfiles"><font face="Verdana" size="5"><strong>4: Ð¡Ð±ÐŸÑ ÑÐ°Ð¹Ð»ÐŸÐ² ÐŽÐ»Ñ ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>ÐÑÐ»Ðž ÐÑ ÑÐŸÐ·ÐŽÐ°ÐµÑÐµ ÐœÐŸÐ²ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ,ÑÐŸ Ð²ÐŸÐ·ÐœÐžÐºÐ°ÐµÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÑÑÑ Ð²Ð²ÐŸÐŽÐ° Ð² ÐœÐµÐµ ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ².ÐÐœÐž ÐŒÐŸÐ³ÑÑ Ð¿ÐŸÑÑÑÐ¿ÐžÑÑ ÐžÐ· Ð²Ð°ÑÐµÐ³ÐŸ ÐŸÐ±ÑÑÐœÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ³ÐŸ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²Ð° ÐžÐ· ÐŽÑÑÐ³ÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Greenstone. ÐÐµÐºÐŸÑÐŸÑÑÐµ ÐŒÐŸÐ³ÑÑ ÑÐ¶Ðµ ÐžÐŒÐµÑÑ Ð¿ÑÐžÑÐŸÐµÐŽÐžÐœÐµÐœÐœÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ.Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑÑÑ,ÐºÐ°Ðº ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÑÐ°Ð¹Ð»Ñ.</p>
+
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/creatingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/creatingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/creatingacollection.htm	(revision 13928)
@@ -0,0 +1,25 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="creatingacollection"><font face="Verdana" size="5"><strong>2.1: Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð§ÑÐŸÐ±Ñ ÑÐŸÐ·ÐŽÐ°ÑÑ ÐœÐŸÐ²ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐŸÑÐºÑÐŸÐ¹ÑÐµ ÐŒÐµÐœÑ "Ð€Ð°Ð¹Ð»" Ðž Ð²ÑÐ±ÐµÑÐžÑÐµ Ð² ÐœÑÐŒ Ð¿ÑÐœÐºÑ "ÐÐŸÐ²ÑÐ¹...". ÐÐµÐºÐŸÑÐŸÑÑÐµ Ð¿ÐŸÐ»Ñ ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÐŸÐ±ÑÐ·Ð°ÑÐµÐ»ÑÐœÐŸ Ð·Ð°Ð¿ÐŸÐ»ÐœÐµÐœÑ, ÐœÐŸ ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð·Ð°ÐŒÐµÐœÐžÑÑ ÐžÑ
+ Ð·ÐœÐ°ÑÐµÐœÐžÑ Ð¿ÐŸÐ·Ð¶Ðµ, ÐµÑÐ»Ðž ÐÑ Ð² ÑÑÐŸÐŒ ÐœÑÐ¶ÐŽÐ°ÐµÑÐµÑÑ Ñ ÑÐŸÑÐºÐž Ð·ÑÐµÐœÐžÑ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°.</p>
+<p>ÐÐ°Ð³Ð»Ð°Ð²ÐžÐµ "ÐÐ°Ð·Ð²Ð°ÐœÐžÐµ/Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐŸÐº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž" - ÑÑÐŸ ÑÐµÐºÑÑ, ÑÐ°ÑÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐœÑÐ¹ ÐœÐ°Ð²ÐµÑÑ
+Ñ ÐŽÐŸÐŒÐ°ÑÐœÐµÐ¹ ÑÑÑÐ°ÐœÐžÑÑ ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐœÐŸ ÐŒÐŸÐ¶ÐµÑ ÐžÐŒÐµÑÑ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐ»ÑÐœÑÑ ÐŽÐ»ÐžÐœÑ.</p>
+<p>"ÐÐ¿ÐžÑÐ°ÐœÐžÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ" ÐŽÐŸÐ»Ð¶ÐœÐŸ Ð¿ÑÐµÐŽÑÑÐ°Ð²ÐžÑÑ ÐºÐ°Ðº ÐŒÐŸÐ¶ÐœÐŸ ÐŽÐµÑÐ°Ð»ÑÐœÐµÐµ ÑÐŸ,ÐŸ ÑÑÐŒ ÑÑÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐºÐ»Ð°Ð²ÐžÑÑ [Enter] ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ,ÑÑÐŸÐ±Ñ ÑÐ°Ð·Ð±ÐžÑÑ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ ÐœÐ° Ð¿Ð°ÑÐ°Ð³ÑÐ°ÑÑ.</p>
+<p>ÐÐ°ÐºÐŸÐœÐµÑ ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ, ÐŽÐŸÐ»Ð¶ÐœÐ° Ð»Ðž ÐœÐŸÐ²Ð°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐžÐŒÐµÑÑ ÑÐŸÑ Ð¶Ðµ ÑÐ°ÐŒÑÐ¹ Ð²ÐžÐŽ Ðž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÑÑÐŸ Ðž ÑÑÑÐµÑÑÐ²ÑÑÑÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐžÐ»Ðž Ð¶Ðµ ÐœÐ°ÑÐ°ÑÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ "ÐÐŸÐ²ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ".</p>
+<p>Ð©ÐµÐ»ÐºÐœÐžÑÐµ "OK", ÑÑÐŸÐ±Ñ ÑÐŸÐ·ÐŽÐ°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. ÐÑÐ»Ðž ÐÑ Ð²ÑÐ±ÑÐ°Ð»Ðž "ÐÐŸÐ²Ð°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ", ÑÐŸ ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ Ð²Ð²ÐµÑÑÐž ÐœÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÑÑÐŸÐ±Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐžÑ
+ Ð² ÑÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐ±ÑÐ°ÑÑ Ð±ÐŸÐ»ÑÑÐµ,ÑÐµÐŒ ÐŸÐŽÐœÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ, Ð° ÐŒÐŸÐ¶ÐµÑÐµ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐŽÑÑÐ³ÐžÐµ Ð¿ÐŸÐ·Ð¶Ðµ. </p>
+<p>ÐÐ°Ð¶Ð°ÑÐžÐµ ÐºÐ»Ð°Ð²ÐžÑÐž "ÐÑÐŒÐµÐœÐžÑÑ" ÐœÐµÐŒÐµÐŽÐ»ÐµÐœÐœÐŸ Ð²ÐŸÐ·Ð²ÑÐ°ÑÐ°ÐµÑ ÐÐ°Ñ Ðº Ð³Ð»Ð°Ð²ÐœÐŸÐŒÑ ÑÐºÑÐ°ÐœÑ. </p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/creatingfolders.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/creatingfolders.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/creatingfolders.htm	(revision 13928)
@@ -0,0 +1,20 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="creatingfolders"><font face="Verdana" size="5"><strong>4.2: Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ Ð¿Ð°Ð¿ÐŸÐº</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ "ÐÐ°Ð¿ÐºÐž" Ð² ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐŒ ÐŽÐµÑÐµÐ²Ðµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÑÐŸÐ±Ñ Ð³ÑÑÐ¿Ð¿ÐžÑÐŸÐ²Ð°ÑÑ Ð²ÐŒÐµÑÑÐµ Ðž Ð±ÐŸÐ»ÐµÐµ Ð»ÐµÐ³ÐºÐŸ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑ ÐžÑ
+. ÐÐ°Ð¿ÐºÐž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð¿ÐŸÐŒÐµÑÐµÐœÑ Ð²ÐœÑÑÑÐž Ð¿Ð°Ð¿ÐŸÐº. Ð€Ð°ÐºÑÐžÑÐµÑÐºÐž ÐœÐµÑ ÐŸÐ³ÑÐ°ÐœÐžÑÐµÐœÐžÑ ÐœÐ° ÑÐŸ,ÑÐºÐŸÐ»ÑÐºÐŸ Ð¿Ð°Ð¿ÐŸÐº ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÐŒÐµÑÑ ÐžÐ»Ðž ÐºÐ°Ðº Ð³Ð»ÑÐ±ÐŸÐºÐŸ ÐŸÐœÐž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð²Ð»ÐŸÐ¶ÐµÐœÑ.</p>
+<p>Ð§ÑÐŸÐ±Ñ ÑÐŸÐ·ÐŽÐ°ÑÑ ÐœÐŸÐ²ÑÑ Ð¿Ð°Ð¿ÐºÑ, Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐ»ÑÐœÐŸ Ð²ÑÐ±ÐµÑÐžÑÐµ ÑÑÑÐµÑÑÐ²ÑÑÑÑÑ Ð¿Ð°Ð¿ÐºÑ Ð² ÐÐµÑÐµÐ²Ðµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ ÐœÐ° ÐºÐœÐŸÐ¿ÐºÐµ "ÐÐŸÐ²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ°". ÐÐŸÐ²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ° Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÐŸÐ³ÐŸ ÐžÐ»Ðž ÐœÐ° Ð²ÑÑÑÐµÐŒ ÑÑÐŸÐ²ÐœÐµ,ÐµÑÐ»Ðž ÐœÐž ÐŸÐŽÐœÐ° ÐœÐµ ÐŸÑÐŸÐ±ÑÐ°ÐœÐ°.ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ Ð¿ÑÐŸÑÐ²ÐŸÐžÑÑ Ð¿Ð°Ð¿ÐºÐµ ÐžÐŒÑ (Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ "ÐÐŸÐ²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ°").</p>
+<p>ÐÐ°Ð¿ÐºÐž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐ°ÐºÐ¶Ðµ ÑÐŸÐ·ÐŽÐ°ÐœÑ ÑÐµÐ»ÑÐºÐŸÐŒ Ð¿ÑÐ°Ð²ÐŸÐ¹ ÐºÐœÐŸÐ¿ÐºÐž ÐŒÑÑÐž Ð¿ÐŸ Ð¿Ð°Ð¿ÐºÐµ,Ð²ÑÐ±ÐžÑÐ°Ñ "ÐÐŸÐ²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ°" Ðž ÐŽÐµÐ¹ÑÑÐ²ÑÑ,ÐºÐ°Ðº ÑÐºÐ°Ð·Ð·Ð°ÐœÐŸ Ð²ÑÑÐµ.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/definefilters.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/definefilters.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/definefilters.htm	(revision 13928)
@@ -0,0 +1,22 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="definefilters"><font face="Verdana" size="5"><strong>6.6.1: ÐÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÑÐžÐ»ÑÑÑÑ</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð€ÐžÐ»ÑÑÑÑ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑ ÐÐ°ÐŒ Ð³ÑÑÐ¿Ð¿ÐžÑÐŸÐ²Ð°ÑÑ Ð² Ð¿ÐŸÐŽÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð²ÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð¿ÐŸ  ÐžÐœÐŽÐµÐºÑÑ,ÐŽÐ»Ñ ÐºÐŸÑÐŸÑÐŸÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÐµÑ Ð·Ð°ÐŽÐ°ÐœÐœÐŸÐ¹ ÐŒÐŸÐŽÐµÐ»Ðž.</p>
+<p>Ð§ÑÐŸÐ±Ñ ÑÐŸÐ·ÐŽÐ°ÑÑ ÑÐžÐ»ÑÑÑ,ÑÐµÐ»ÐºÐœÐžÑÐµ ÐºÐ»Ð°Ð²ÐžÑÑ "ÐÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÑÐžÐ»ÑÑÑÑ" Ðž Ð²Ð²ÐµÐŽÐžÑÐµ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐŽÐ»Ñ ÐœÐŸÐ²ÐŸÐ³ÐŸ ÑÐžÐ»ÑÑÑÐ° Ð² Ð¿ÐŸÐ»Ðµ "ÐÐŒÑ ÑÐžÐ»ÑÑÑÐ° ÑÑÐ±ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž:".ÐÐ°ÑÐµÐŒ Ð²ÑÐ±ÐµÑÐžÑÐµ Ñ
+Ð°ÑÐ°ÐºÑÐµÑÐœÑÐµ Ð¿ÑÐžÐ·ÐœÐ°ÐºÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐµ ÐžÐ»Ðž ÑÐ»ÐµÐŒÐµÐœÑÐ°ÐŒ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+,ÐžÐ»Ðž ÐœÐ°Ð·Ð²Ð°ÐœÐžÑ ÑÐ°ÑÑÐŒÐ°ÑÑÐžÐ²Ð°ÐµÐŒÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»Ð°.ÐÐ²ÐµÐŽÐžÑÐµ Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÐŸÐµ Ð²ÑÑÐ°Ð¶ÐµÐœÐžÐµ,ÑÑÐŸÐ±Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð² ÑÐµÑÐµÐœÐžÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ ÑÑÐŸÐ³ÐŸ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÑ.ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÐµÑÐµÐºÐ»ÑÑÐ°ÑÑ "ÐÐºÐ»ÑÑÐµÐœÐžÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²", ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑ ÑÐžÐ»ÑÑÑÑ, ÐžÐ»Ðž "ÐÑÐºÐ»ÑÑÐµÐœÐžÐµ" ÐžÑ
+.ÐÐ°ÐºÐŸÐœÐµÑ,ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ Ð»ÑÐ±ÐŸÐ¹ ÑÑÐ°ÐœÐŽÐ°ÑÑ PERL, Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÑÐµ ÑÐ»Ð°Ð³Ðž Ð²ÑÑÐ°Ð¶ÐµÐœÐžÑ,ÑÑÐŸÐ±Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð¿ÑÐž ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐž (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ("i" ÐŽÐ»Ñ ÑÐ»ÑÑÐ°Ñ ÐœÐµÑÑÐ²ÑÑÐ²ÐžÑÐµÐ»ÑÐœÐŸÐ³ÐŸ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÑ),ÐÐ°ÐºÐŸÐœÐµÑ,ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ ÑÐžÐ»ÑÑÑ",ÑÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÑÐžÐ»ÑÑÑ Ðº ÑÐ¿ÐžÑÐºÑ "Ð€ÐžÐ»ÑÑÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ ÑÑÐ±ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹".</p>
+<p>Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÑÐžÐ»ÑÑÑ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ ÑÐžÐ»ÑÑÑ". </p>
+<p>Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÑÐžÐ»ÑÑÑ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ°,Ð·Ð°ÐŒÐµÐœÐžÑÐµ Ð»ÑÐ±ÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ, ÐºÐŸÑÐŸÑÐŸÐµ Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ Ð² ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÐž ÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐµÐŒ Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐ°ÐŒÐµÐœÐžÑÑ ÑÐžÐ»ÑÑÑ",ÑÑÐŸÐ±Ñ Ð·Ð°ÐºÑÐµÐ¿ÐžÑÑ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/deletingcollections.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/deletingcollections.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/deletingcollections.htm	(revision 13928)
@@ -0,0 +1,16 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="deletingcollections"><font face="Verdana" size="5"><strong>2.4: Ð£ÐŽÐ°Ð»ÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>ÐÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÐœÐµÐžÐ·ÐŒÐµÐœÐœÐŸ ÑÐŽÐ°Ð»ÐžÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐžÐ· ÐžÐœÑÑÐ°Ð»ÑÑÐžÐŸÐœÐœÐŸÐ¹ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž Greenstone, Ð²ÑÐ±ÐµÑÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ..." ÐžÐ· ÐŒÐµÐœÑ "Ð€Ð°Ð¹Ð»". ÐÑÐºÑÐŸÐµÑÑÑ ÑÐ¿ÐžÑÐŸÐº Ð²ÑÐµÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Greenstone. ÐÑÐ±ÐµÑÐžÑÐµ ÐœÑÐ¶ÐœÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐŽÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÐ° ÐµÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÑ, Ð¿ÐŸÑÐ»Ðµ ÑÑÐŸÐ³ÐŸ Ð¿ÐŸÑÑÐ°Ð²ÑÐµ Ð³Ð°Ð»ÐŸÑÐºÑ Ð² Ð¿ÑÐœÐºÑÐµ Ð²ÐœÐžÐ·Ñ ÐŽÐžÐ°Ð»ÐŸÐ³Ð° Ðž ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° "Ð£ÐŽÐ°Ð»ÐžÑÑ", ÑÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. Ð­ÑÐ° ÐŸÐ¿ÐµÑÐ°ÑÐžÑ Ð±ÐµÐ·Ð²ÐŸÐ·Ð²ÑÐ°ÑÐœÐ°, Ð¿ÐŸÑÑÐŸÐŒÑ Ð¿ÑÐŸÐ²ÐµÑÑÑÐµ Ð²ÐœÐžÐŒÐ°ÑÐµÐ»ÑÐœÐŸ, ÐŽÐµÐ¹ÑÑÐ²ÐžÑÐµÐ»ÑÐœÐŸ Ð»Ðž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐœÐµÐœÑÐ¶ÐœÐ°!</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/designingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/designingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/designingacollection.htm	(revision 13928)
@@ -0,0 +1,26 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="designingacollection"><font face="Verdana" size="5"><strong>6: ÐÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>ÐÐŸÐ³ÐŽÐ° ÐÐ°ÑÐž ÑÐ°Ð¹Ð»Ñ ÑÐœÐ°Ð±Ð¶ÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒÐž,ÐŽÐ°Ð»ÐµÐµ ÐÑ ÑÐµÑÐ°ÐµÑÐµ,Ð² ÐºÐ°ÐºÐŸÐŒ Ð²ÐžÐŽÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Greenstone ÐŽÐŸÐ»Ð¶ÐœÐ° Ð±ÑÑÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐ° Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÐŒ.ÐÐ°ÐºÐŸÐ³ÐŸ Ð²ÐžÐŽÐ° ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŽÐŸÑÑÑÐ¿ÐœÐ° ÐŽÐ»Ñ Ð¿ÐŸÐžÑÐºÐ°? ÐÐ°ÐºÐžÐµ Ð¿ÑÑÐž Ð¿ÑÐµÐŽÑÑÐŒÐŸÑÑÐµÐœÑ ÐŽÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°? ÐÐ°ÐºÐžÐµ ÑÐ·ÑÐºÐž Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÑÑÑÑ? ÐÐŽÐµ ÑÐ°Ð·ÐŒÐµÑÑÐžÑÑ ÐºÐœÐŸÐ¿ÐºÐž ÐœÐ° ÑÑÑÐ°ÐœÐžÑÐµ? Ð­ÑÐž Ð²ÐµÑÐž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐœÐ°ÑÑÑÐŸÐµÐœÑ;Ð² ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑÑÑ,ÐºÐ°Ðº ÑÑÐŸ ÑÐŽÐµÐ»Ð°ÑÑ.</p>
+
+
+
+
+
+
+
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/downloadingfiles.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/downloadingfiles.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/downloadingfiles.htm	(revision 13928)
@@ -0,0 +1,16 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="downloadingfiles"><font face="Verdana" size="5"><strong>3: ÐÐ°Ð³ÑÑÐ·ÐžÑÑ ÑÐ°Ð¹Ð»Ñ ÐžÐ· ÐžÐœÑÐµÑÐœÐµÑ</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>ÐÐžÐŽ "ÐÐµÑÐºÐ°Ð»ÐŸ" Ð¿ÐŸÐŒÐŸÐ¶ÐµÑ Ð²Ð°ÐŒ Ð·Ð°Ð³ÑÑÐ·ÐžÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐžÐ· ÐÐœÑÐµÑÐœÐµÑÐ°. ÐÐ°ÐœÐœÐ°Ñ ÑÐµÐºÑÐžÑ ÐŸÐ±ÑÑÑÐœÑÐµÑ Ð¿ÑÐŸÑÐµÑÑ Ð·ÐµÑÐºÐ°Ð»ÐžÑÐŸÐ²Ð°ÐœÐžÑ Ð² ÐÐœÑÐµÑÑÐµÐ¹ÑÐµ ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°ÑÑ.</p>
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/enrichingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/enrichingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/enrichingacollection.htm	(revision 13928)
@@ -0,0 +1,26 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="enrichingacollection"><font face="Verdana" size="5"><strong>5: ÐÐ±ÐŸÐ³Ð°ÑÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒÐž</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>ÐÐŒÐµÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐœÐ°ÐºÐŸÐ¿Ð»ÐµÐœÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž,ÐœÐ°Ð¿ÐŸÐ»ÐœÐžÑÐµ ÐžÑ
+ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐµÐ¹,ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒÐŸÐ¹ "ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ".Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ, ÐºÐ°Ðº ÑÐŸÐ·ÐŽÐ°ÑÑÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ,ÐºÐ°Ðº ÐŸÐœÐž ÑÐµÐŽÐ°ÐºÑÐžÑÑÑÑÑÑ, ÐœÐ°Ð·ÐœÐ°ÑÐ°ÑÑÑÑ Ðž Ð²ÐŸÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÑÑÑÑ,Ð° ÑÐ°ÐºÐ¶Ðµ ÐºÐ°Ðº ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ Ð²ÐœÐµÑÐœÐžÐµ ÐžÑÑÐŸÑÐœÐžÐºÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ (ÑÐ°ÐºÐ¶Ðµ ÑÐŒ.ÐÐ»Ð°Ð²Ñ 2 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone - ÐÐŸÐ»ÑÑÐµÐœÐžÐµ Ð±ÐŸÐ»ÑÑÐµÐ¹ ÑÐ°ÑÑÐž ÐžÐ· Ð²Ð°ÑÐžÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²). </p>
+
+
+
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/exportingcollections.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/exportingcollections.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/exportingcollections.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="exportingcollections"><font face="Verdana" size="5"><strong>8.3: Ð­ÐºÑÐ¿ÐŸÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐœÐ° CD/DVD</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Greenstone ÐŒÐŸÐ¶ÐµÑ ÑÐºÑÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÐŸÐŽÐœÑ ÐžÐ»Ðž Ð±ÐŸÐ»ÐµÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ð² ÑÐ°ÐŒÐŸÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÑÑÐžÐ¹ÑÑ CD/DVD Ð¿ÐŸÐŽ Windows. Ð§ÑÐŸÐ±Ñ ÑÑÐŸ ÑÐŽÐµÐ»Ð°ÑÑ, ÐŽÐŸÐ»Ð¶ÐµÐœ  Ð±ÑÑÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ Ð¿Ð°ÐºÐµÑ "Ð­ÐºÑÐ¿ÐŸÑÑ Ð² CD-ROM". ÐÐœ ÐœÐµ Ð²ÐºÐ»ÑÑÐµÐœ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ, Ð¿ÐŸÑÑÐŸÐŒÑ ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐÐ°ÑÑ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÑ, ÑÑÐŸÐ±Ñ ÐµÐ³ÐŸ Ð²ÐºÐ»ÑÑÐžÑÑ.</p>
+<p>Ð§ÑÐŸÐ±Ñ ÑÐºÑÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐŸÑÐºÑÐŸÐ¹ÑÐµ ÐŒÐµÐœÑ "Ð€Ð°Ð¹Ð»" Ðž Ð²ÑÐ±ÐµÑÐžÑÐµ "Ð­ÐºÑÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ Ð² CD-ROM/DVD...". ÐÐŸÑÐ²Ð»ÑÐµÑÑÑ ÑÐ¿ÐžÑÐŸÐº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÑÐŸÐ±ÑÐ°ÐœÐžÐ¹ Greenstone; ÑÐµÐ»ÐºÐœÐžÑÐµ ÐœÐ° Ð»ÑÐ±ÐŸÐ¹, ÑÑÐŸÐ±Ñ ÑÐ²ÐžÐŽÐµÑÑ ÐµÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ. ÐÐŸÐŒÐµÑÑÑÐµ Ð²ÑÐ±ÑÐ°ÐœÐœÑÐµ Ð¿ÐŸÐ»Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐŽÐ»Ñ ÑÐºÑÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²Ð²ÐµÑÑÐž ÐžÐŒÑ CD/DVD Ð² Ð¿ÐŸÐ»Ðµ: ÑÑÐŸ ÑÐŸ, ÑÑÐŸ Ð¿ÐŸÑÐ²ÐžÑÑÑ Ð² ÑÑÐ°ÑÑÐŸÐ²ÐŸÐŒ ÐŒÐµÐœÑ, ÐºÐŸÐ³ÐŽÐ° CD/DVD Ð±ÑÐŽÐµÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ. ÐÐ°ÑÐµÐŒ ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð­ÐºÑÐ¿ÐŸÑÑ". ÐÑÐŸÑÐµÑÑ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐŒÐœÐŸÐ³ÐžÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² Ðž ÐŒÐŸÐ¶ÐµÑ Ð·Ð°ÐœÑÑÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐŒÐžÐœÑÑ.</p>
+<p>ÐÐŸÑÐ»Ðµ ÐŸÐºÐŸÐœÑÐ°ÐœÐžÑ Greenstone Ð¿ÐŸÐºÐ°Ð¶ÐµÑ ÐžÐŒÑ Ð¿Ð°Ð¿ÐºÐž, ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐµÐ¹ ÑÐºÑÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÐœÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ Ð¿ÐžÑÑÑÐžÐ¹ ÐºÐŸÐŒÐ¿Ð°ÐºÑ-ÐŽÐžÑÐº ÐŽÐ»Ñ ÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐµÐ³ÐŸ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÐœÐ° ÑÐžÑÑÑÐ¹ CD/DVD.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/fileassociations.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/fileassociations.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/fileassociations.htm	(revision 13928)
@@ -0,0 +1,20 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="fileassociations"><font face="Verdana" size="5"><strong>8.2: ÐÑÑÐŸÑÐžÐ°ÑÐžÐž ÑÐ°Ð¹Ð»Ð°</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐÐœÑÐµÑÑÐµÐ¹Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐžÐµ Ð¿ÑÐžÐºÐ»Ð°ÐŽÐœÑÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ, ÑÑÐŸÐ±Ñ ÐŸÑÐºÑÑÐ²Ð°ÑÑ ÑÐ¿ÐµÑÐžÑÐžÑÐœÑÐµ ÑÐžÐ¿Ñ ÑÐ°Ð¹Ð»ÐŸÐ². Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ Ð°ÑÑÐŸÑÐžÐžÑÐŸÐ²Ð°ÐœÐœÑÐµ ÑÐ°Ð¹Ð»Ñ ÐŸÑÐºÑÑÐ²Ð°ÑÑ ÐŒÐµÐœÑ "Ð€Ð°Ð¹Ð»" Ðž ÑÐµÐ»ÐºÐ°ÑÑ "ÐÑÑÐŸÑÐžÐžÑÐŸÐ²Ð°ÐœÐœÑÐµ ÑÐ°Ð¹Ð»Ñ".</p>
+<p>Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ Ð°ÑÑÐŸÑÐžÐ°ÑÐžÐž, Ð²ÑÐ±ÐµÑÐžÑÐµ ÑÐµÐ»ÐµÐ²ÐŸÐµ ÑÐ°ÑÑÐžÑÐµÐœÐžÐµ ÑÐ°Ð¹Ð»Ð° ÐžÐ· ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐ³ÐŸ ÑÐ¿ÐžÑÐºÐ° ÐžÐ»Ðž ÐœÐ°Ð¿ÐžÑÐžÑÐµ ÐœÐŸÐ²ÐŸÐµ ÑÐ°ÑÑÐžÑÐµÐœÐžÐµ (ÐœÐµ Ð²ÐºÐ»ÑÑÐ°Ñ "."). ÐÐ°ÑÐµÐŒ ÐžÐ»Ðž ÐœÐ°Ð¿ÐžÑÐžÑÐµ Ð² ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐŒ Ð¿ÐŸÐ»Ðµ ÐºÐŸÐŒÐ°ÐœÐŽÑ,Ð·Ð°Ð¿ÑÑÐºÐ°ÑÑÑÑ Ð¶ÐµÐ»Ð°ÑÐµÐ»ÑÐœÐŸÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ,ÐžÐ»Ðž Ð²ÑÐ±ÐµÑÐžÑÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ ÐžÐ· ÐŽÐžÐ°Ð»ÐŸÐ³ÐŸÐ²ÐŸÐ³ÐŸ ÐŸÐºÐœÐ° "ÐÑÐŸÑÐŒÐŸÑÑ". ".%1" ÐŒÐŸÐ¶ÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ Ð² ÐºÐŸÐŒÐ°ÐœÐŽÐµ Ð·Ð°Ð¿ÑÑÐºÐ°, ÑÑÐŸÐ±Ñ Ð²ÑÑÐ°Ð²ÐžÑÑ ÐžÐŒÑ ÑÐ°Ð¹Ð»Ð°, ÐºÐŸÑÐŸÑÑÐ¹ ÐŽÐŸÐ»Ð¶ÐµÐœ ÐŸÑÐºÑÑÑÑÑÑ. ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐŸÐœÐž Ð·Ð°Ð¿ÐŸÐ»ÐœÐµÐœÑ,Ð¿ÑÐœÐºÑ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ" ÑÑÐ°ÐœÐŸÐ²ÐžÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒ Ðž ÐŒÐŸÐ¶ÐœÐŸ ÑÐµÐ»ÑÐºÐŸÐŒ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ Ð°ÑÑÐŸÑÐžÐ°ÑÐžÑ.  </p>
+<p>Ð§ÑÐŸÐ±Ñ ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ Ð°ÑÑÐŸÑÐžÐ°ÑÐžÑ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÑÑÑÐµÑÑÐ²ÑÑÑÐµÐµ ÑÐ°ÑÑÐžÑÐµÐœÐžÐµ ÑÐ°Ð¹Ð»Ð°. ÐÑÐ±Ð°Ñ ÑÑÑÐµÑÑÐ²ÑÑÑÐ°Ñ ÐºÐŸÐŒÐ°ÐœÐŽÐ° ÑÐ²ÑÐ·Ðž Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑÑÑ Ð² Ð¿ÐŸÐ»Ðµ Ð·Ð°Ð¿ÑÑÐºÐ° ÐºÐŸÐŒÐ°ÐœÐŽ. ÐÑÑÐµÐŽÐ°ÐºÑÐžÑÑÐ¹ÑÐµ ÐµÐµ Ðž Ð·Ð°ÑÐµÐŒ ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐ°ÐŒÐµÐœÐžÑÑ".</p>
+<p>Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ Ð°ÑÑÐŸÑÐžÐ°ÑÐžÑ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÑÑÑÐµÑÑÐ²ÑÑÑÐµÐµ ÑÐ°ÑÑÐžÑÐµÐœÐžÐµ ÑÐ°Ð¹Ð»Ð° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ".(Ð Ð°ÑÑÐžÑÐµÐœÐžÐµ ÑÐ°Ð¹Ð»Ð° ÐŸÑÑÐ°ÐµÑÑÑ Ð² ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐŒ ÑÐ¿ÐžÑÐºÐµ "ÐÐ»Ñ ÐŸÐºÐŸÐœÑÐ°ÐœÐžÑ ÑÐ°Ð¹Ð»ÐŸÐ²").</p>
+<p>ÐÑÐŸÑÐžÐ°ÑÐžÐ²ÐœÑÐµ ÑÐ°Ð¹Ð»Ñ Ñ
+ÑÐ°ÐœÑÑÑÑ Ð² Ð³Ð»Ð°Ð²ÐœÐŸÐ¹ Ð¿Ð°Ð¿ÐºÐµ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°, Ð² ÑÐ°Ð¹Ð»Ðµ, ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒÐŸÐŒ "associations.xml".</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/filteringthetree.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/filteringthetree.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/filteringthetree.htm	(revision 13928)
@@ -0,0 +1,21 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="filteringthetree"><font face="Verdana" size="5"><strong>4.5: Ð€ÐžÐ»ÑÑÑÐŸÐ²Ð°ÐœÐžÐµ ÐŽÐµÑÐµÐ²Ð°</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>"Ð€ÐžÐ»ÑÑÑÐŸÐ²Ð°ÐœÐžÐµ" ÐŽÐµÑÐµÐ²Ð° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐÐ°ÐŒ ÑÑÐ¶Ð°ÑÑ Ð¿ÐŸÐžÑÐº ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐžÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ².</p>
+<p>ÐÑÐœÐºÑ "ÐÐŸÐºÐ°Ð·Ð°ÑÑ ÑÐ°Ð¹Ð»Ñ" Ð² ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐŒ ÐŒÐµÐœÑ Ð¿ÐŸÐŽ ÐºÐ°Ð¶ÐŽÑÐŒ ÐŽÐµÑÐµÐ²ÐŸÐŒ Ð²ÑÐ²ÐŸÐŽÐžÑ ÑÐ¿ÐžÑÐŸÐº Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÑÑ
+ ÑÐžÐ»ÑÑÑÐŸÐ² ÑÐžÐ¿Ð° "Images".ÐÑÐ±ÐµÑÐžÑÐµ Ðž Ð²ÑÐµ Ð²ÑÐµÐŒÐµÐœÐœÐŸ ÑÐºÑÑÑÑÐµ ÑÐ°Ð¹Ð»Ñ Ð² ÐŽÐµÑÐµÐ²Ðµ.Ð§ÑÐŸÐ±Ñ Ð²ÐŸÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÐŽÐµÑÐµÐ²ÐŸ,Ð·Ð°ÐŒÐµÐœÐžÑÐµ ÑÐžÐ»ÑÑÑ ÑÐœÐŸÐ²Ð° ÐœÐ° "ÐÑÐµ ÑÐ°Ð¹Ð»Ñ".Ð­ÑÐž ÐŽÐµÐ¹ÑÑÐ²ÐžÑ ÐœÐµ ÐžÐ·ÐŒÐµÐœÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð¿ÑÐž ÑÑÐŸÐŒ ÐŸÐœÐž ÐœÐµ Ð·Ð°ÑÑÐ°Ð³ÐžÐ²Ð°ÑÑ Ð¿Ð°Ð¿ÐºÐž Ð² ÐŽÐµÑÐµÐ²Ðµ. </p>
+<p>ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð·Ð°ÐŽÐ°ÑÑ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÑ ÑÐžÐ»ÑÑÑÐ°,ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð² Ð² ÑÑ
+ÐµÐŒÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐµ ÑÐ°Ð¹Ð»ÐŸÐ² (Ð¢ÐŸÐ»ÑÐºÐŸ ÐŽÐ»Ñ ÑÐµÐ¶ÐžÐŒÐŸÐ² Ð¡Ð¿ÐµÑÐžÐ°Ð»ÐžÑÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÑ
+ Ð¡ÐžÑÑÐµÐŒ Ðž Ð­ÐºÑÐ¿ÐµÑÑ).ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÐµ Ð°Ð±Ð±ÑÐµÐ²ÐžÐ°ÑÑÑÑ ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ¹ ÑÐžÑÑÐµÐŒÑ ÑÐžÐ¿Ð° "*.*" ÐžÐ»Ðž "*.doc" ("*" ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÐµÑ Ð»ÑÐ±ÑÐŒ ÑÐžÐŒÐ²ÐŸÐ»Ð°ÐŒ). </p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/formatstatements.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/formatstatements.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/formatstatements.htm	(revision 13928)
@@ -0,0 +1,35 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="formatstatements"><font face="Verdana" size="5"><strong>6.9: ÐÑÐŸÐ±ÐµÐœÐœÐŸÑÑÐž ÑÐŸÑÐŒÐ°ÑÐ°</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>ÐÐµÐ±-ÑÑÑÐ°ÐœÐžÑÑ, ÐºÐŸÑÐŸÑÑÐµ ÐÑ Ð²ÐžÐŽÐžÑÐµ, ÐºÐŸÐ³ÐŽÐ° ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÐµ Greenstone, ÐœÐµ ÑÐ²Ð»ÑÑÑÑÑ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐœÑÐŒÐž, Ð° ÑÐŸÐ·ÐŽÐ°ÑÑÑÑ "ÐœÐ° Ð»ÐµÑÑ", ÐºÐŸÐ³ÐŽÐ° Ð² ÐœÐžÑ
+ ÐµÑÑÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÑÑÑ. ÐÐŸÐŒÐ°ÐœÐŽÑ ÑÐŸÑÐŒÐ°ÑÐ° ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÐŽÐ»Ñ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ð¿ÐŸÑÐ²Ð»ÐµÐœÐžÑ ÑÑÐžÑ
+ ÑÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÐœÑÑ
+ ÑÑÑÐ°ÐœÐžÑ. ÐÐœÐž Ð·Ð°ÑÑÐ°Ð³ÐžÐ²Ð°ÑÑ ÑÐ°ÐºÐžÐµ Ð²ÐµÑÐž,ÐºÐ°Ðº ÐŒÐµÑÑÐŸ Ð¿ÐŸÑÐ²Ð»ÐµÐœÐžÑ ÐºÐœÐŸÐ¿ÐºÐž,ÐºÐŸÐ³ÐŽÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑÑÑ,Ðž ÐºÐ°ÐºÐžÐµ ÑÐ²ÑÐ·Ðž ÐŸÑÐŸÐ±ÑÐ°Ð¶Ð°ÑÑÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐŒ DateList. ÐÐŸÐŒÐ°ÐœÐŽÑ ÑÐŸÑÐŒÐ°ÑÐ° ÐœÐµ Ð»ÐµÐ³ÐºÐŸ ÑÐ°Ð·ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÑÑ,Ðž ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ Ð¿ÑÐŸÑÐžÑÐ°ÑÑ Ð³Ð»Ð°Ð²Ñ 2 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone. Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÐ¶ÐŽÐ°ÑÑÑÑ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÑÐŸÑÐŒÐ°ÑÐ° Ðž ÑÐŸ, ÐºÐ°Ðº ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÑÐµÑ ÐŽÐŸÑÑÑÐ¿ Ðº ÐœÐžÐŒ. Ð "Ð Ð°Ð·ÐŽÐµÐ»Ð°Ñ
+ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°" ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÑÐŸÐ±ÐµÐœÐœÐŸÑÑÐž ÑÐŸÑÐŒÐ°ÑÐ°".</p>
+<p>ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÑÐžÐŒÐµÐœÐžÑÑ ÐºÐŸÐŒÐ°ÐœÐŽÑ ÑÐŸÑÐŒÐ°ÑÐ° Ðº ÑÐµÐŒÑ-ÐœÐžÐ±ÑÐŽÑ Ð² ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐŒ ÑÐ¿ÐžÑÐºÐµ "ÐÑÐ±ÐŸÑ ÑÑÐµÐŽÑÑÐ²",ÐºÐŸÑÐŸÑÑÐ¹ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÐºÐ°Ð¶ÐŽÑÐ¹ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ Ðž Ð²ÑÑÑÐŸÐµÐœÐœÑÐ¹ ÑÐ¿ÐžÑÐŸÐº ÑÑÐµÐŽÑÑÐ². ÐÐŸÐ³ÐŽÐ° ÐÑ Ð²ÑÐ±ÐžÑÐ°ÐµÑÐµ ÑÑÐµÐŽÑÑÐ²Ð°, ÐµÑÑÑ ÐŽÐ²Ð° ÑÐžÐ¿Ð° ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ. ÐÐµÐºÐŸÑÐŸÑÑÐµ ÑÑÐµÐŽÑÑÐ²Ð° ÑÐ²Ð»ÑÑÑÑÑ Ð¿ÑÐŸÑÑÐŸ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž ÐžÐ»Ðž ÐœÐµÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž,ÐŸÐœÐž ÑÐ¿ÑÐ°Ð²Ð»ÑÑÑÑÑ ÐºÐœÐŸÐ¿ÐºÐ°ÐŒÐž. ÐÑÑÐ³ÐžÐµ ÑÑÐµÐ±ÑÑÑ, ÑÑÐŸÐ±Ñ Ð±ÑÐ»Ð° ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐ° ÑÐŸÑÐŒÐ°ÑÐœÐ°Ñ ÑÑÑÐŸÐºÐ°. ÐÐ»Ñ ÐœÐžÑ
+ ÐžÐŒÐµÐµÑÑÑ ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐžÐ¹ ÑÐ¿ÐžÑÐŸÐº "ÐÐŸÐ·ÐŽÐµÐ¹ÑÑÐ²ÑÑÑÐžÐ¹ ÐºÐŸÐŒÐ¿ÐŸÐœÐµÐœÑ", ÑÑÐŸÐ±Ñ Ð²ÑÐ±ÑÐ°ÑÑ, Ðº ÐºÐ°ÐºÐŸÐ¹ ÑÐ°ÑÑÐž ÑÑÐµÐŽÑÑÐ² ÑÑÑÐŸÐºÐ° ÐŸÐ±ÑÐ°ÑÐ°ÐµÑÑÑ,ÐµÑÐ»Ðž ÑÑÐŸ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ, ÐŸÐ±Ð»Ð°ÑÑÑ ÑÐµÐºÑÑÐ°   ("Ð¡ÑÑÐŸÐºÐ° ÑÐŸÑÐŒÐ°ÑÐ° HTML") ÐŽÐ»Ñ Ð²Ð²ÐŸÐŽÐ° ÑÑÑÐŸÐºÐž, Ðž Ð²ÑÐ±ÐŸÑ Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ "ÐÐµÑÐµÐŒÐµÐœÐœÑÑ
+". Ð§ÑÐŸÐ±Ñ Ð²ÑÑÐ°Ð²ÐžÑÑ Ð¿ÐµÑÐµÐŒÐµÐœÐœÑÑ Ð² ÑÐµÐºÑÑÑÑ Ð¿ÐŸÐ·ÐžÑÐžÑ Ð² ÑÐŸÑÐŒÐ°ÑÐœÑÑ ÑÑÑÐŸÐºÑ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÑ ÐžÐ· ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐ³ÐŸ ÑÐ¿ÐžÑÐºÐ°  Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÑÑÐ°Ð²ÐžÑÑ". </p>
+<p>ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÑÐŸÑÐŒÐ°Ñ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ ÐŽÐ»Ñ ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐºÐŸÐŒÐ¿ÐŸÐœÐµÐœÑÐ°, Ð²ÑÐ±ÐžÑÐ°Ñ Ð±Ð»Ð°ÐœÐº ÑÐ²ÐŸÐ¹ÑÑÐ². Ð­ÑÐŸÑ ÑÐŸÑÐŒÐ°Ñ Ð·Ð°ÑÐµÐŒ Ð¿ÑÐžÐŒÐµÐœÑÐµÑÑÑ ÐºÐŸ Ð²ÑÐµÐŒ Ð¿ÑÐžÐŒÐµÐœÐžÐŒÑÐŒ ÑÐ²ÐŸÐ¹ÑÑÐ²Ð°ÐŒ, ÐµÑÐ»Ðž ÐŽÑÑÐ³ÐŸÐµ ÐœÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐŸ.</p>
+<p>Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐœÐŸÐ²ÑÑ ÐºÐŸÐŒÐ°ÐœÐŽÑ ÑÐŸÑÐŒÐ°ÑÐ°,Ð²ÐœÐµÑÐžÑÐµ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ,ÐºÐ°Ðº ÐŸÐ±ÑÑÑÐœÐµÐœÐŸ Ð²ÑÑÐµ, Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ ÑÐŸÑÐŒÐ°Ñ".ÐÐŸÐ²Ð°Ñ ÐºÐŸÐŒÐ°ÐœÐŽÐ° ÑÐŸÑÐŒÐ°ÑÐ° Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ Ð² ÑÐ¿ÐžÑÐºÐµ "Ð¢ÐµÐºÑÑÐžÐµ Ð·Ð°ÐŽÐ°ÐœÐœÑÐµ ÐºÐŸÐŒÐ°ÐœÐŽÑ ÑÐŸÑÐŒÐ°ÑÐ°".Ð¢ÐŸÐ»ÑÐºÐŸ ÐŸÐŽÐœÐ° ÐºÐŸÐŒÐ°ÐœÐŽÐ° ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÑÐ²ÑÐ·Ð°ÐœÐ° Ñ ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÐºÐŸÐŒÐ±ÐžÐœÐ°ÑÐžÐµÐ¹ ÑÐ²ÐŸÐ¹ÑÑÐ²ÐŸ/ÐºÐŸÐŒÐ¿ÐŸÐœÐµÐœÑ.</p>
+<p>Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÐºÐŸÐŒÐ°ÐœÐŽÑ ÑÐŸÑÐŒÐ°ÑÐ°, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÑ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ ÑÐŸÑÐŒÐ°Ñ".</p>
+<p>Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐºÐŸÐŒÐ°ÐœÐŽÑ ÑÐŸÑÐŒÐ°ÑÐ°, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÑ ÐŒÐ· ÑÐ¿ÐžÑÐºÐ°, ÐžÐ·ÐŒÐµÐœÐžÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐ°ÐŒÐµÐœÐžÑÑ ÑÐŸÑÐŒÐ°Ñ".</p>
+<p>ÐÐ° ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐµÐ¹ ÐŸ Ð¿ÐµÑÐµÐŒÐµÐœÐœÑÑ
+ Ðž ÐºÐŸÐŒÐ¿ÐŸÐœÐµÐœÑÐ°Ñ
+ ÑÑÐµÐŽÑÑÐ² ÐŸÐ±ÑÐ°ÑÐžÑÐµÑÑ Ðº Ð³Ð»Ð°Ð²Ðµ 2 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone.</p>
+<p>ÐÑÐ»Ðž ÐºÐœÐŸÐ¿ÐºÐ° "ÐÐŸÐ·Ð²ÐŸÐ»ÐµÐœÐœÑÐµ ÑÐ°ÑÑÐžÑÐµÐœÐœÑÐµ Ð²Ð°ÑÐžÐ°ÐœÑÑ" Ð¿ÐŸÐŒÐµÑÐµÐœÐ°,ÑÐŸ ÑÐ°Ð·ÑÐµÑÐµÐœÑ ÐœÐµÐºÐŸÑÐŸÑÑÐµ Ð¿ÑÐŸÐŽÐ²ÐžÐœÑÑÑÐµ Ð²Ð°ÑÐžÐ°ÐœÑÑ ÑÐŸÑÐŒÐ°ÑÐžÑÐŸÐ²Ð°ÐœÐžÑ . Ð¡Ð¿ÐžÑÐŸÐº ÑÑÐµÐŽÑÑÐ², ÐºÐŸÑÐŸÑÑÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐŸÑÐŒÐ°ÑÐžÑÐŸÐ²Ð°ÐœÑ, ÐœÐµÐŒÐœÐŸÐ³ÐŸ ÐžÐ·ÐŒÐµÐœÐµÐœ Ðž Ð±ÐŸÐ»ÑÑÐµÐµ ÑÐžÑÐ»ÐŸ Ð¿ÐµÑÐµÐŒÐµÐœÐœÑÑ
+ ÐŽÐŸÑÑÑÐ¿ÐœÐŸ ÐŽÐ»Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÐºÐŸÐŒÐ°ÐœÐŽÐŸÐ¹ ÑÐŸÑÐŒÐ°ÑÐ°, ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°Ñ Ð±ÐŸÐ»ÑÑÐµÐµ ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÑÑÑÐ°ÐœÐžÑÐµÐ¹ ÐŸÑÐžÐ³ÐžÐœÐ°Ð»-ÐŒÐ°ÐºÐµÑÐ°.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/generalsettings.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/generalsettings.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/generalsettings.htm	(revision 13928)
@@ -0,0 +1,20 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="generalsettings"><font face="Verdana" size="5"><strong>6.2: ÐÐ±ÑÐµÐµ</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ,ÐºÐ°Ðº Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ Ðž ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐŸÐ±ÑÐžÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž, ÐŸÑÐœÐŸÑÑÑÐžÐµÑÑ Ðº ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.Ð¡ÐœÐ°ÑÐ°Ð»Ð° Ð² "Ð Ð°Ð·ÐŽÐµÐ»Ð°Ñ
+ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°" ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐ±ÑÐžÐµ"</p>
+<p>ÐÐŽÐµÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÑ,Ð¿ÑÐµÐŽÑÑÐŒÐŸÑÑÐµÐœÐœÑÐµ Ð¿ÑÐž ÑÐŸÐ·ÐŽÐ°ÐœÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž,ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐžÐ·ÐŒÐµÐœÐµÐœÑ.</p>
+<p>Ð¡ÐœÐ°ÑÐ°Ð»Ð° ÐžÐŽÑÑ ÐºÐŸÐœÑÐ°ÐºÑÐœÑÐµ Ð°ÐŽÑÐµÑÐ° ÑÐ»ÐµÐºÑÑÐŸÐœÐœÐŸÐ¹ Ð¿ÐŸÑÑÑ ÑÐŸÐ·ÐŽÐ°ÑÐµÐ»Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÑÑÐµÐ³ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð»ÐžÑÐ°. Ð¡Ð»ÐµÐŽÑÑÑÐµÐµ Ð¿ÐŸÐ»Ðµ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐÐ°ÐŒ ÐžÐ·ÐŒÐµÐœÑÑÑ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð¡Ð»ÐµÐŽÑÑÐµÐµ ÑÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð¿Ð°Ð¿ÐºÑ, Ð² ÐºÐŸÑÐŸÑÐŸÐ¹ ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐœÐŸ ÐœÐµ Ð¿ÐŸÐŽÐ»ÐµÐ¶ÐžÑ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑÐŒ. Ð¡Ð»ÐµÐŽÑÑÑÐµÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ (Ð² ÑÐŸÑÐŒÐµ URL) ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ,ÑÑÐŸÐ±Ñ Ð¿ÐŸÐºÐ°Ð·Ð°ÑÑ ÐœÐ°Ð²ÐµÑÑ
+Ñ ÑÐ»ÐµÐ²Ð° ÐŸÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÑÑÐ°ÐœÐžÑÑ ÐŸ ÐœÐµÐ¹, Ðž ÑÐ»ÐµÐŽÑÑÑÐµÐµ - ÐžÐºÐŸÐœÐºÐ°, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐ°Ñ Ð² Greenstone ÑÑÑÐ°ÐœÐžÑÐ° ÐŽÐ»Ñ ÑÐ²ÑÐ·Ðž Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹. ÐÐŸÑÐ»Ðµ ÑÑÐŸÐ³ÐŸ, Ð²Ñ ÑÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐŽÐµÐ»ÐžÑÑ Ð¿ÑÐœÐºÑ Ð³Ð°Ð»ÐŸÑÐºÐŸÐ¹, ÑÐºÐ°Ð·Ð°Ð², ÐŽÐŸÑÑÑÐ¿ÐœÐ° Ð»Ðž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐŽÑÑÐ³ÐžÐŒ. ÐÐ°ÐºÐŸÐœÐµÑ, ÑÐ»ÐµÐŽÑÐµÑ ÐŸÐ±Ð»Ð°ÑÑÑ ÑÐµÐºÑÑÐ° "ÐÐ¿ÐžÑÐ°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž",Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐœÐ°Ñ ÑÐ°ÐœÐµÐµ Ð² <a href="creatingacollection.htm">Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</a>.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/help.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/help.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/help.xml	(revision 13928)
@@ -0,0 +1,733 @@
+<Document>
+<Section name="introduction">
+<Title>
+<Text id="1">ÐÐ²ÐµÐŽÐµÐœÐžÐµ</Text>
+</Title>
+<Text id="2">ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Greenstone - ÑÑÐŸ ÐžÐœÑÑÑÑÐŒÐµÐœÑ ÐŽÐ»Ñ ÑÐ±ÐŸÑÐ° Ðž ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ñ Ð¿ÐŸÑÐ»ÐµÐŽÑÑÑÐžÐŒ ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÑÐžÑÑÐŸÐ²ÑÑ
+ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐº.ÐÐœ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ ÐŽÐŸÑÑÑÐ¿ Ðº ÑÑÐœÐºÑÐžÐŸÐœÐ°Ð»ÑÐœÑÐŒ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑÐŒ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐ³ÐŸ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Greenstone Ð³ÑÐ°ÑÐžÑÐµÑÐºÐžÐŒ Ð¿ÑÑÐµÐŒ Ðž ÑÐ°Ð±ÐŸÑÐŸÐ¹ ÐŒÑÑÑÑ.</Text>
+<Section name="ofmiceandmenus">
+<Title>
+<Text id="3">ÐÑÑÑ Ðž ÐÐµÐœÑ</Text>
+</Title>
+<Text id="4">Ð­ÑÐŸÑ ÑÐ°Ð·ÐŽÐµÐ» ÐŽÐ°ÐµÑ Ð±Ð°Ð·ÐŸÐ²ÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ Ð²Ð·Ð°ÐžÐŒÐŸÐŽÐµÐ¹ÑÑÐ²ÐžÐž Ñ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐŸÐŒ  Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž. ÐÑÐ»Ðž ÐÑ Ð·ÐœÐ°ÐºÐŸÐŒÑ Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ°ÐŒÐž ÑÐžÐ¿Ð° Internet Explorer ÐžÐ»Ðž Microsoft office, Ð»ÐµÐ³ÐºÐŸ ÐŸÐ±ÑÐ°ÑÐ°ÐµÑÐµÑÑ Ñ ÐŒÑÑÑÑ Ðž ÐŒÐµÐœÑ, Ð¿ÑÐŸÐ¿ÑÑÑÐžÑÐµ <Reference target="howtoavoidthisdocument"/>.</Text><Updated date="2-Mar-2006"/>
+<Text id="5">ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÐµÑ ÑÐŸÐ³Ð»Ð°ÑÐµÐœÐžÑÐŒ Windows Microsoft Ðž ÑÑÐµÐ±ÑÐµÑ ÐŸÐ±ÑÑÐœÐŸÐ³ÐŸ Ð·ÐœÐ°ÐœÐžÑ Windows.   </Text>
+<Text id="6">ÐÑÐ±Ð°Ñ ÑÐ°ÑÑÑ ÑÐºÑÐ°ÐœÐ°, Ñ ÐºÐŸÑÐŸÑÐŸÐ¹ ÐÑ Ð²Ð·Ð°ÐžÐŒÐŸÐŽÐµÐ¹ÑÑÐ²ÑÐµÑÐµ, ÑÐžÐ¿Ð° ÐºÐœÐŸÐ¿ÐºÐž ÐžÐ»Ðž ÐŸÐ±Ð»Ð°ÑÑÐž ÑÐµÐºÑÑÐ°,ÐœÐ°Ð·ÑÐ²Ð°ÐµÑÑÑ ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÐµÐŒ. Ð Ð»ÑÐ±ÐŸÐµ Ð·Ð°ÐŽÐ°ÐœÐœÐŸÐµ Ð²ÑÐµÐŒÑ ÐŸÐŽÐžÐœ ÑÐ»ÐµÐŒÐµÐœÑ ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ, ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒÑÐ¹ "ÑÐŸÐºÑÑ",Ð²ÑÐŽÐµÐ»ÑÐµÑÑÑ Ð¿ÐŸÐŽÑÐ²ÐµÑÐºÐŸÐ¹ Ðž ÐŸÑÐºÐ»ÐžÐºÐ°ÐµÑÑÑ ÐœÐ° ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ ÐºÐ»Ð°Ð²ÐžÐ°ÑÑÑÑ. ÐÐµÑÐºÐŸÐ»ÑÐºÐŸ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑ ÐÐ°ÐŒ Ð²ÑÐ±ÐžÑÐ°ÑÑ ÑÑÐ°ÑÑÐºÐž, ÐºÐŸÑÐŸÑÑÐµ Ð²ÑÐŽÐµÐ»ÑÑÑÑÑ ÑÐµÐŒÐœÐŸÑÐžÐœÐžÐŒ ÑÐ²ÐµÑÐŸÐŒ. ÐÐµÐºÐŸÑÐŸÑÑÐµ ÑÐ»ÐµÐŒÐµÐœÑÑ ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ ÐŸÑÐŸÐ±ÑÐ°Ð¶Ð°ÑÑÑÑ Ñ Ð¿ÐŸÐœÐžÐ¶ÐµÐœÐœÐŸÐ¹ ÑÑÐºÐŸÑÑÑÑ, Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°Ñ ÑÐµÐŒ ÑÐ°ÐŒÑÐŒ, ÑÑÐŸ ÐŸÐœÐž Ð·Ð°Ð±Ð»ÐŸÐºÐžÑÐŸÐ²Ð°ÐœÑ.</Text>
+<Text id="7">ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÐµÑÐµÐŒÐµÑÐ°ÑÑÑÑ Ðž ÐŽÐµÐ¹ÑÑÐ²ÐŸÐ²Ð°ÑÑ  Ð»ÐµÐ²ÐŸÐ¹ ÐžÐ»Ðž Ð¿ÑÐ°Ð²ÐŸÐ¹ ÐºÐœÐŸÐ¿ÐºÐ°ÐŒÐž ÐŒÑÑÐž ÐŸÐ±ÑÑÐœÑÐŒ ÑÐ¿ÐŸÑÐŸÐ±ÐŸÐŒ. ÐÐœÐŸÐ³ÐžÐµ ÐºÐŸÐŒÐ¿ÐŸÐœÐµÐœÑÑ ÑÐ°ÐºÐ¶Ðµ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑ ÐÐ°ÐŒ "ÑÑÐœÑÑÑ" ÐžÑ
+, ÐœÐ°Ð¶ÐžÐŒÐ°Ñ Ðž ÑÐŽÐµÑÐ¶ÐžÐ²Ð°Ñ Ð»ÐµÐ²ÑÑ ÐºÐœÐŸÐ¿ÐºÑ ÐŒÑÑÐž, Ð¿ÐµÑÐµÐŒÐµÑÐ°ÑÑ ÐžÑ
+ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÐŒÑÑÐž Ðž ÐŸÑÑÐ°Ð²ÐžÑÑ ÐžÑ
+ Ð² ÐŽÑÑÐ³ÐŸÐŒ ÐŒÐµÑÑÐµ, ÐŸÑÐ¿ÑÑÐºÐ°Ñ ÐºÐœÐŸÐ¿ÐºÑ. ÐÐŸÑÐµÐœÑÐžÐ°Ð»ÑÐœÑÐµ ÐŸÐ±ÑÐµÐºÑÑ ÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐžÐ·ÐŒÐµÐœÑÑÑ ÑÐ²ÐŸÐ¹ Ð²ÐžÐŽ, ÐºÐŸÐ³ÐŽÐ° ÐºÐŸÐŒÐ¿ÐŸÐœÐµÐœÑ ÑÐºÐŸÐ»ÑÐ·ÐžÑ Ð¿ÐŸ ÐœÐžÐŒ.  </Text>
+<Text id="8">ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐºÐ»Ð°Ð²ÐžÐ°ÑÑÑÑ ÐŽÐ»Ñ Ð·Ð°Ð¿ÐžÑÐž Ð² ÐŸÐ±Ð»Ð°ÑÑÐž ÑÐµÐºÑÑÐ°. ÐÐ»ÑÑÐµÑÐœÐ°ÑÐžÐ²Ñ ÐºÐ»Ð°Ð²ÐžÐ°ÑÑÑÐµ ÐŽÐŸÑÑÑÐ¿ÐœÑ ÐŽÐ»Ñ ÐŒÐœÐŸÐ³ÐžÑ
+ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ, ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœÐœÑÑ
+ ÐºÐ»ÑÑÐµÐ²ÑÐŒ ÐžÐŒÐµÐœÐµÐŒ Ð² ÐºÐ²Ð°ÐŽÑÐ°ÑÐœÑÑ
+ ÑÐºÐŸÐ±ÐºÐ°Ñ
+. Ð Ð¿ÑÐžÐŒÐµÑÑ, [Tab] ÐžÐ·ÐŒÐµÐœÑÐµÑ ÑÐŸÐºÑÑ. ÐÐœÐ°Ðº Ð¿Ð»ÑÑ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ, ÑÑÐŸ ÐŽÑÑÐ³ÐžÐµ ÐºÐ»Ð°Ð²ÐžÑÐž ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÐœÐ°Ð¶Ð°ÑÑ ÐŸÐŽÐœÐŸÐ²ÑÐµÐŒÐµÐœÐœÐŸ. </Text>
+<Text id="9">Ð§ÑÐŸÐ±Ñ Ð¿ÐŸÐ»ÑÑÐžÑÑ ÐŽÐŸÑÑÑÐ¿ Ðº ÐŒÐµÐœÑ, ÑÐŽÐµÑÐ¶ÐžÐ²Ð°Ð¹ÑÐµ ÐºÐ»Ð°Ð²ÐžÑÑ [ALT] Ðž ÐœÐ°Ð¶ÐŒÐžÑÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÑÑ Ð±ÑÐºÐ²Ñ (Ð¿ÐŸÐŽÑÐµÑÐºÐœÑÑÑÑ).ÐÐ°Ð¿ÑÐžÐŒÐµÑ,ÐŽÐ»Ñ Ð²ÑÐ±ÐŸÑÐ° ÐŒÐµÐœÑ "Ð€Ð°Ð¹Ð»" ÐœÐ°Ð¶ÐŒÐžÑÐµ [ALT] + [F]. ÐÐ»Ñ Ð²ÑÐ±ÐŸÑÐ° ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÐŸÐ³ÐŸ Ð¿ÑÐœÐºÑÐ°, ÐœÐ°Ð¶ÐŒÐžÑÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÑÑ ÐºÐ»Ð°Ð²ÐžÑÑ. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÐµÑÐ»Ðž ÐÑ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÐµÑÑ Ð² ÐŒÐµÐœÑ Ð€Ð°Ð¹Ð» ÐœÐ°Ð¶ÐŒÐžÑÐµ [S], ÑÑÐŸÐ±Ñ "Ð¡ÐŸÑ
+ÑÐ°ÐœÐžÑÑ"ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ.</Text>
+<Text id="10">ÐÐœÐŸÐ¿ÐºÐž, ÑÐžÐ¿Ð° ÐŒÐµÐœÑ, ÐžÐŒÐµÑÑ ÐŸÐŽÐžÐœ Ð¿ÐŸÐŽÑÑÑÐºÐœÑÑÑÐ¹ ÑÐžÐŒÐ²ÐŸÐ». Ð§ÑÐŸÐ±Ñ Ð²ÑÐ·Ð²Ð°ÑÑ ÐºÐœÐŸÐ¿ÐºÑ ÐœÐ°Ð¶ÐŒÐžÑÐµ [ALT] Ðž ÐŸÐŽÐœÐŸÐ²ÑÐµÐŒÐµÐœÐœÐŸ Ð¿ÐŸÐŽÑÐµÑÐºÐœÑÑÑÐ¹ ÑÐžÐŒÐ²ÐŸÐ». </Text>
+<Text id="11">ÐÑÐ¹ÐŽÐžÑÐµ ÐžÐ· Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°, Ð²ÑÐ±ÐžÑÐ°Ñ Ð¿ÑÐœÐºÑ "ÐÑÑ
+ÐŸÐŽ" Ð² ÐŒÐµÐœÑ "Ð€Ð°Ð¹Ð»Ð°". ÐÐ°ÑÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð±ÑÐŽÐµÑ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ  ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐ°.</Text>
+</Section>
+<Section name="howtoavoidthisdocument">
+<Title>
+<Text id="12">ÐÐ°Ðº ÐžÐ·Ð±ÐµÐ¶Ð°ÑÑ ÑÑÐµÐœÐžÑ ÑÑÐŸÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°</Text>
+</Title>
+<Text id="13">ÐÐµ ÑÐžÑÐ°Ð¹ÑÐµ ÑÑÐŸÑ ÑÐµÐºÑÑ Ð¿ÐŸÐŒÐŸÑÐž Ð¿ÐŸÐ»ÐœÐŸÑÑÑÑ! ÐÐŸÑÑÐ°ÑÐŸÑÐœÐŸ Ð¿ÑÐŸÑÐµÑÑÑ, ÐºÐ°Ðº ÑÑÐŒÐµÑÑ Ð¿ÐŸÐ»ÑÑÐžÑÑ Ð¿ÐŸÐŒÐŸÑÑ, ÐºÐŸÐ³ÐŽÐ° ÐÑ ÐœÑÐ¶ÐŽÐ°ÐµÑÐµÑÑ Ð² ÑÑÐŸÐŒ.  </Text>
+<Text id="14">ÐÑÐœÐºÑÑ ÐŒÐµÐœÑ "ÐÐŸÐŒÐŸÑÑ" ÑÐºÐ°Ð·ÑÐ²Ð°ÑÑ ÑÐµ ÑÐ°Ð·ÐŽÐµÐ»Ñ,ÐºÐŸÑÐŸÑÑÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐœÐ°ÐžÐ±ÐŸÐ»ÐµÐµ Ð°ÐŽÐµÐºÐ²Ð°ÑÐœÑÐŒÐž ÐŽÐ»Ñ Ð¿ÐŸÐŒÐŸÑÐž, Ðž ÑÐŸÐ¿ÑÐŸÐ²ÐŸÐ¶ÐŽÐ°ÑÑÑÑ ÐœÐµÐ±ÐŸÐ»ÑÑÐžÐŒ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµÐŒ ÐºÐœÐžÐ³Ðž  </Text>
+<Text id="15">ÐÐ»Ñ ÐŒÐœÐŸÐ³ÐžÑ
+ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ, ÐµÑÐ»Ðž ÐÑ ÑÐ°Ð·ÐŒÐµÑÐ°ÐµÑÐµ ÐŒÑÑÑ ÐœÐ° ÐœÐžÑ
+,Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ  "Ð¿ÐŸÐŽÑÐºÐ°Ð·ÐºÐ°",ÐºÐŸÑÐŸÑÐ°Ñ ÐŸÐ±ÑÑÑÐœÑÐµÑ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ,ÐºÐŸÑÐŸÑÑÐµ ÐŸÐœÐž Ð²ÑÐ¿ÐŸÐ»ÐœÑÑÑ  </Text>
+<Text id="16">ÐÐµÑÐµÐŽ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐŒ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐŸÐŒ, ÑÐœÐ°ÑÐ°Ð»Ð° Ð¿ÑÐŸÑÑÐžÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÑÐžÑ Greenstone/</Text>
+</Section>
+</Section>
+<Section name="startingoff">
+<Title>
+<Text id="17">ÐÐŸ ÑÑÐ°ÑÑÐ°</Text>
+</Title>
+<Text id="18">Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÑÐ°ÑÑÐºÐ°Ð·Ð°ÐœÐŸ, ÐºÐ°Ðº ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ, Ð·Ð°Ð³ÑÑÐ¶Ð°ÑÑ Ðž ÑÐŽÐ°Ð»ÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Section name="creatingacollection">
+<Title>
+<Text id="19">Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<Text id="20">Ð§ÑÐŸÐ±Ñ ÑÐŸÐ·ÐŽÐ°ÑÑ ÐœÐŸÐ²ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐŸÑÐºÑÐŸÐ¹ÑÐµ ÐŒÐµÐœÑ "Ð€Ð°Ð¹Ð»" Ðž Ð²ÑÐ±ÐµÑÐžÑÐµ Ð² ÐœÑÐŒ Ð¿ÑÐœÐºÑ "ÐÐŸÐ²ÑÐ¹...". ÐÐµÐºÐŸÑÐŸÑÑÐµ Ð¿ÐŸÐ»Ñ ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÐŸÐ±ÑÐ·Ð°ÑÐµÐ»ÑÐœÐŸ Ð·Ð°Ð¿ÐŸÐ»ÐœÐµÐœÑ, ÐœÐŸ ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð·Ð°ÐŒÐµÐœÐžÑÑ ÐžÑ
+ Ð·ÐœÐ°ÑÐµÐœÐžÑ Ð¿ÐŸÐ·Ð¶Ðµ, ÐµÑÐ»Ðž ÐÑ Ð² ÑÑÐŸÐŒ ÐœÑÐ¶ÐŽÐ°ÐµÑÐµÑÑ Ñ ÑÐŸÑÐºÐž Ð·ÑÐµÐœÐžÑ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°.</Text>
+<Text id="21">ÐÐ°Ð³Ð»Ð°Ð²ÐžÐµ "ÐÐ°Ð·Ð²Ð°ÐœÐžÐµ/Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐŸÐº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž" - ÑÑÐŸ ÑÐµÐºÑÑ, ÑÐ°ÑÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐœÑÐ¹ ÐœÐ°Ð²ÐµÑÑ
+Ñ ÐŽÐŸÐŒÐ°ÑÐœÐµÐ¹ ÑÑÑÐ°ÐœÐžÑÑ ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐœÐŸ ÐŒÐŸÐ¶ÐµÑ ÐžÐŒÐµÑÑ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐ»ÑÐœÑÑ ÐŽÐ»ÐžÐœÑ.</Text>
+<Text id="22">"ÐÐ¿ÐžÑÐ°ÐœÐžÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ" ÐŽÐŸÐ»Ð¶ÐœÐŸ Ð¿ÑÐµÐŽÑÑÐ°Ð²ÐžÑÑ ÐºÐ°Ðº ÐŒÐŸÐ¶ÐœÐŸ ÐŽÐµÑÐ°Ð»ÑÐœÐµÐµ ÑÐŸ,ÐŸ ÑÑÐŒ ÑÑÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐºÐ»Ð°Ð²ÐžÑÑ [Enter] ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ,ÑÑÐŸÐ±Ñ ÑÐ°Ð·Ð±ÐžÑÑ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ ÐœÐ° Ð¿Ð°ÑÐ°Ð³ÑÐ°ÑÑ.</Text>
+<Text id="23">ÐÐ°ÐºÐŸÐœÐµÑ ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ, ÐŽÐŸÐ»Ð¶ÐœÐ° Ð»Ðž ÐœÐŸÐ²Ð°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐžÐŒÐµÑÑ ÑÐŸÑ Ð¶Ðµ ÑÐ°ÐŒÑÐ¹ Ð²ÐžÐŽ Ðž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÑÑÐŸ Ðž ÑÑÑÐµÑÑÐ²ÑÑÑÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐžÐ»Ðž Ð¶Ðµ ÐœÐ°ÑÐ°ÑÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ "ÐÐŸÐ²ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ".</Text>
+<Text id="24">Ð©ÐµÐ»ÐºÐœÐžÑÐµ "OK", ÑÑÐŸÐ±Ñ ÑÐŸÐ·ÐŽÐ°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. ÐÑÐ»Ðž ÐÑ Ð²ÑÐ±ÑÐ°Ð»Ðž "ÐÐŸÐ²Ð°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ", ÑÐŸ ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ Ð²Ð²ÐµÑÑÐž ÐœÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÑÑÐŸÐ±Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐžÑ
+ Ð² ÑÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐ±ÑÐ°ÑÑ Ð±ÐŸÐ»ÑÑÐµ,ÑÐµÐŒ ÐŸÐŽÐœÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ, Ð° ÐŒÐŸÐ¶ÐµÑÐµ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐŽÑÑÐ³ÐžÐµ Ð¿ÐŸÐ·Ð¶Ðµ. </Text>
+<Text id="25">ÐÐ°Ð¶Ð°ÑÐžÐµ ÐºÐ»Ð°Ð²ÐžÑÐž "ÐÑÐŒÐµÐœÐžÑÑ" ÐœÐµÐŒÐµÐŽÐ»ÐµÐœÐœÐŸ Ð²ÐŸÐ·Ð²ÑÐ°ÑÐ°ÐµÑ ÐÐ°Ñ Ðº Ð³Ð»Ð°Ð²ÐœÐŸÐŒÑ ÑÐºÑÐ°ÐœÑ. </Text>
+</Section>
+<Section name="savingacollection">
+<Title>
+<Text id="26">Ð¡ÐŸÑ
+ÑÐ°ÐœÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<Text id="27">Ð¡ÐŸÑ
+ÑÐ°ÐœÑÐ¹ÑÐµ ÐÐ°ÑÑ ÑÐ°Ð±ÐŸÑÑ ÑÐµÐ³ÑÐ»ÑÑÐœÐŸ, ÐŸÑÐºÑÑÐ²Ð°Ñ ÐŒÐµÐœÑ "Ð€Ð°Ð¹Ð»" Ðž Ð²ÑÐ±ÐžÑÐ°Ñ Ð² ÐœÑÐŒ Ð¿ÑÐœÐºÑ "Ð¡ÐŸÑ
+ÑÐ°ÐœÐžÑÑ". Ð¡ÐŸÑ
+ÑÐ°ÐœÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž - ÑÑÐŸ ÐœÐµ ÑÐŸ Ð¶Ðµ ÑÐ°ÐŒÐŸÐµ, ÐºÐ°Ðº  ÑÐŽÐµÐ»Ð°ÑÑ ÐµÑ Ð³ÐŸÑÐŸÐ²ÐŸÐ¹ Ðº ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ Ð² Greenstone.
+(see <Reference target="producingthecollection"/>).</Text>
+<Text id="28">ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð·Ð°ÑÐžÑÐ°ÐµÑ ÐÐ°ÑÑ ÑÐ°Ð±ÐŸÑÑ Ð¿ÑÑÑÐŒ ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐžÑ ÐµÑ Ð²ÑÑÐºÐžÐ¹ ÑÐ°Ð·, ÐºÐŸÐ³ÐŽÐ° ÐÑ Ð²ÑÑ
+ÐŸÐŽÐžÑÐµ ÐžÐ· Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐžÐ»Ðž Ð·Ð°Ð³ÑÑÐ¶Ð°ÐµÑÐµ ÐŽÑÑÐ³ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ.</Text>
+<Text id="29">Ð¡ÐŸÑ
+ÑÐ°ÐœÐµÐœÐœÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð·Ð°Ð¿ÐžÑÑÐ²Ð°ÑÑÑÑ  Ð² ÑÐ°Ð¹Ð», ÐžÐŒÐµÑÑÐžÐ¹ ÑÐŸ Ð¶Ðµ ÐžÐŒÑ, ÑÑÐŸ Ðž ÐžÐŒÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ñ ÑÐ°ÑÑÐžÑÐµÐœÐžÐµÐŒ ".col", Ðž ÑÐ°ÑÐ¿ÐŸÐ»Ð°Ð³Ð°ÐµÑÑÑ Ð² Ð¿Ð°Ð¿ÐºÐµ ÑÐŸÐ³ÐŸ Ð¶Ðµ ÐœÐ°ÐžÐŒÐµÐœÐŸÐ²Ð°ÐœÐžÑ, ÑÑÐŸ Ðž Ð¿Ð°Ð¿ÐºÐ° "collect" Ð¿ÑÐž ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž Greenstone.</Text>
+</Section>
+<Section name="openingacollection">
+<Title>
+<Text id="30">ÐÑÐºÑÑÑÐžÐµ ÑÑÑÐµÑÑÐ²ÑÑÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<Text id="31">ÐÐ»Ñ ÑÐŸÐ³ÐŸ ÑÑÐŸÐ±Ñ ÐŸÑÐºÑÑÑÑ ÑÑÑÐµÑÑÐ²ÑÑÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, Ð²ÑÐ±ÐµÑÐžÑÐµ "ÐÑÐºÑÑÑÑ" Ð² ÐŒÐµÐœÑ "Ð€Ð°Ð¹Ð»",ÑÑÐŸÐ±Ñ Ð±ÑÑÑÑÐŸ Ð¿ÐµÑÐµÐ¹ÑÐž Ðº ÐÑÐºÑÑÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐŸÑÐ²Ð»ÑÐµÑÑÑ ÑÐ¿ÐžÑÐŸÐº ÐÐ°ÑÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ð² Greenstone. ÐÑÐ±ÐµÑÐžÑÐµ ÐŸÐŽÐœÑ,ÑÑÐŸÐ±Ñ ÑÐ²ÐžÐŽÐµÑÑ ÐµÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ,Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ   "OÑÐºÑÑÑÑ", ÑÑÐŸÐ±Ñ Ð·Ð°Ð³ÑÑÐ·ÐžÑÑ ÐµÐµ. ÐÑÐ»Ðž ÐÑ ÐžÑÐžÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐºÐŸÑÐŸÑÐ°Ñ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð²ÐœÐµ Ð¿Ð°Ð¿ÐºÐž "Ð¡ollect Greenstone",ÑÐŸ ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð Ð°ÑÑÐŒÐŸÑÑÐµÑÑ" ÐŽÐ»Ñ Ð²ÑÐ·ÐŸÐ²Ð° ÐŽÐžÐ°Ð»ÐŸÐ³ÐŸÐ²ÐŸÐ¹ ÑÐžÑÑÐµÐŒÑ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÑÐ°Ð¹Ð»ÐŸÐ².</Text>
+<Text id="32">Ð ÑÐ»ÑÑÐ°Ðµ, ÐµÑÐ»Ðž Ð±ÐŸÐ»ÑÑÐµ ÑÐµÐŒ ÐŸÐŽÐœÐ° Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° Greenstone Ð²Ð²ÐŸÐŽÐžÑÑÑ ÐŸÐŽÐœÐŸÐ²ÑÐµÐŒÐµÐœÐœÐŸ, ÑÐµÐ»ÐµÐ²Ð°ÐœÑÐœÑÐµ ÐŽÐžÑÐµÐºÑÑÐžÐž "Ð·Ð°ÐºÑÑÑÑ",ÑÑÐŸÐ±Ñ Ð¿ÑÐµÐŽÐŸÑÐ²ÑÐ°ÑÐžÑÑ ÐœÐ°Ð»ÐŸÐ¶ÐµÐœÐžÐµ.ÐÑÐž ÐŸÑÐºÑÑÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐœÐµÐ±ÐŸÐ»ÑÑÐŸÐ¹ Ð²ÑÐµÐŒÐµÐœÐœÑÐ¹ Ð±Ð»ÐŸÐºÐžÑÑÑÑÐžÐ¹ ÑÐ°Ð¹Ð» ÑÐŸÐ·ÐŽÐ°ÐµÑÑÑ Ð² ÐµÑ Ð¿Ð°Ð¿ÐºÐµ.ÐÐµÑÐµÐŽ ÐŸÑÐºÑÑÑÐžÐµÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑ Ð¿ÑÐŸÐ²ÐµÑÐºÑ,ÑÑÐŸÐ±Ñ ÑÐ±ÐµÐŽÐžÑÑÑÑ,ÑÑÐŸ ÐœÐžÐºÐ°ÐºÐžÑ
+ Ð±Ð»ÐŸÐºÐžÑÑÑÑÐžÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² ÐœÐµ ÑÑÑÐµÑÑÐ²ÑÐµÑ. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐºÐ°Ð·Ð°ÑÑ,Ð·Ð°ÐºÑÑÑÐ° Ð»Ðž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, Ð¿ÐŸ ÑÐ²ÐµÑÑ ÐµÑ ÐžÐºÐŸÐœÐºÐž:Ð·ÐµÐ»ÑÐœÑÐ¹ - ÐŽÐ»Ñ ÐœÐŸÑÐŒÐ°Ð»ÑÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž,ÐºÑÐ°ÑÐœÑÐ¹ - ÐŽÐ»Ñ Ð·Ð°ÐºÑÑÑÐŸÐ¹. ÐÐŽÐœÐ°ÐºÐŸ,ÐºÐŸÐ³ÐŽÐ° ÐžÐ· ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° Ð²ÑÑ
+ÐŸÐŽÑÑ Ð¿ÑÐµÐ¶ÐŽÐµÐ²ÑÐµÐŒÐµÐœÐœÐŸ, Ð±Ð»ÐŸÐºÐžÑÑÑÑÐžÐ¹ ÑÐ°Ð¹Ð» ÐžÐœÐŸÐ³ÐŽÐ° ÐŸÑÑÐ°ÐµÑÑÑ ÐœÐ° ÐŒÐµÑÑÐµ. ÐÐŸÐ³ÐŽÐ° ÐÑ ÐŸÑÐºÑÑÐ²Ð°ÐµÑÐµ ÑÐ°ÐºÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Ð·Ð°Ð¿ÑÐ°ÑÐžÐ²Ð°ÐµÑ,Ñ
+ÐŸÑÐžÑÐµ Ð»Ðž ÐÑ "ÑÐºÑÐ°ÑÑÑ" ÐµÐ³ÐŸ ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÐµ. ÐÐžÐºÐŸÐ³ÐŽÐ° ÐœÐµ ÐŽÐµÐ»Ð°Ð¹ÑÐµ ÑÑÐŸÐ³ÐŸ,ÐµÑÐ»Ðž ÐºÑÐŸ-ÑÐŸ ÐµÑÐµ Ð² ÑÐŸ Ð¶Ðµ ÑÐ°ÐŒÐŸÐµ Ð²ÑÐµÐŒÑ ÑÐ°Ð±ÐŸÑÐ°ÐµÑ.   </Text>
+<Text id="33">ÐÐŸÐ³ÐŽÐ° ÐÑ ÐŸÑÐºÑÑÐ²Ð°ÐµÑÐµ ÐºÐŸÐ»ÐµÐºÑÐžÑ, ÐºÐŸÑÐŸÑÐ°Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐ° ÐœÐµ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°  Greenstone, ÐÐ°Ñ Ð¿ÐŸÐ¿ÑÐŸÑÑÑ Ð²ÑÐ±ÑÐ°ÑÑ ÐœÐ°Ð±ÐŸÑ (ÐžÐ»Ðž ÐœÐ°Ð±ÐŸÑÑ) ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. ÐÑÐ»Ðž ÐœÐž ÐŸÐŽÐžÐœ ÐœÐµ ÐŸÑÐŸÐ±ÑÐ°Ðœ, Ð»ÑÐ±ÑÐµ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ð±ÑÐŽÑÑ ÐžÐ³ÐœÐŸÑÐžÑÐŸÐ²Ð°ÑÑÑÑ. ÐÐœÐ°ÑÐµ, ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ð±ÑÐŽÑÑ ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÑ ÑÐ°Ðº Ð¶Ðµ, ÐºÐ°Ðº Ðž ÐºÐŸÐ³ÐŽÐ° ÐÑ Ð¿ÐµÑÐµÑÑÐ³ÐžÐ²Ð°ÐµÑÐµ Ð² ÑÐ°Ð¹Ð»Ñ Ñ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐŒÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒÐž. ÐÑÐŸÑÐµÑÑ ÐŸÐ¿ÐžÑÐ°Ðœ Ð² <Reference target="importingpreviouslyassignedmetadata"/>. </Text>
+</Section>
+<Section name="deletingcollections">
+<Title>
+<Text id="34">Ð£ÐŽÐ°Ð»ÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹</Text>
+</Title>
+<Text id="35">ÐÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÐœÐµÐžÐ·ÐŒÐµÐœÐœÐŸ ÑÐŽÐ°Ð»ÐžÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐžÐ· ÐžÐœÑÑÐ°Ð»ÑÑÐžÐŸÐœÐœÐŸÐ¹ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž Greenstone, Ð²ÑÐ±ÐµÑÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ..." ÐžÐ· ÐŒÐµÐœÑ "Ð€Ð°Ð¹Ð»". ÐÑÐºÑÐŸÐµÑÑÑ ÑÐ¿ÐžÑÐŸÐº Ð²ÑÐµÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Greenstone. ÐÑÐ±ÐµÑÐžÑÐµ ÐœÑÐ¶ÐœÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐŽÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÐ° ÐµÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÑ, Ð¿ÐŸÑÐ»Ðµ ÑÑÐŸÐ³ÐŸ Ð¿ÐŸÑÑÐ°Ð²ÑÐµ Ð³Ð°Ð»ÐŸÑÐºÑ Ð² Ð¿ÑÐœÐºÑÐµ Ð²ÐœÐžÐ·Ñ ÐŽÐžÐ°Ð»ÐŸÐ³Ð° Ðž ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° "Ð£ÐŽÐ°Ð»ÐžÑÑ", ÑÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. Ð­ÑÐ° ÐŸÐ¿ÐµÑÐ°ÑÐžÑ Ð±ÐµÐ·Ð²ÐŸÐ·Ð²ÑÐ°ÑÐœÐ°, Ð¿ÐŸÑÑÐŸÐŒÑ Ð¿ÑÐŸÐ²ÐµÑÑÑÐµ Ð²ÐœÐžÐŒÐ°ÑÐµÐ»ÑÐœÐŸ, ÐŽÐµÐ¹ÑÑÐ²ÐžÑÐµÐ»ÑÐœÐŸ Ð»Ðž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐœÐµÐœÑÐ¶ÐœÐ°!</Text>
+</Section>
+</Section>
+<Section name="downloadingfiles">
+<Title>
+<Text id="36">ÐÐ°Ð³ÑÑÐ·ÐžÑÑ ÑÐ°Ð¹Ð»Ñ ÐžÐ· ÐžÐœÑÐµÑÐœÐµÑ</Text>
+</Title>
+<Text id="37">ÐÐžÐŽ "ÐÐµÑÐºÐ°Ð»ÐŸ" Ð¿ÐŸÐŒÐŸÐ¶ÐµÑ Ð²Ð°ÐŒ Ð·Ð°Ð³ÑÑÐ·ÐžÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐžÐ· ÐÐœÑÐµÑÐœÐµÑÐ°. ÐÐ°ÐœÐœÐ°Ñ ÑÐµÐºÑÐžÑ ÐŸÐ±ÑÑÑÐœÑÐµÑ Ð¿ÑÐŸÑÐµÑÑ Ð·ÐµÑÐºÐ°Ð»ÐžÑÐŸÐ²Ð°ÐœÐžÑ Ð² ÐÐœÑÐµÑÑÐµÐ¹ÑÐµ ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°ÑÑ.</Text>
+<Section name="themirrorview">
+<Title>
+<Text id="38">ÐÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐÐ°Ð³ÑÑÐ·ÐžÑÑ</Text>
+</Title>
+<Text id="39">Ð­ÑÐ° ÑÐµÐºÑÐžÑ ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ ÐºÐ°Ðº ÐºÐŸÐœÑÐžÐ³ÑÑÐžÑÐŸÐ²Ð°ÑÑ Ð·Ð°ÐŽÐ°ÑÑ Ðž ÐºÐŸÐœÑÑÐŸÐ»Ñ Ð¿ÑÐŸÑÐµÑÑÐ° Ð·Ð°Ð³ÑÑÐ·ÐºÐž. ÐÐŸÑÑÑÐ¿ Ðº Ð¿ÑÐŸÑÐŒÐŸÑÑÑ "ÐÐ°Ð³ÑÑÐ·ÐžÑÑ" ÐœÐ°Ð¶Ð°ÑÐµÐŒ ÑÑÐŸÐ¹ Ð·Ð°ÐºÐ»Ð°ÐŽÐºÐž. ÐÐµÑÑ
+ÐœÑÑ Ð¿ÐŸÐ»ÐŸÐ²ÐžÐœÐ° ÑÐºÑÐ°ÐœÐ° Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐºÐŸÐœÑÑÐŸÐ»Ñ Ð·Ð°Ð³ÑÑÐ·ÐºÐž. ÐÐžÐ¶ÐœÑÑ Ð¿ÐŸÐ»ÐŸÐ²ÐžÐœÐ° Ð² ÐœÐ°ÑÐ°Ð»Ðµ Ð¿ÑÑÑÐ°, ÐŸÐŽÐœÐ°ÐºÐŸ Ð¿ÐŸÐºÐ°Ð¶ÐµÑ Ð¿ÐµÑÐµÑÐµÐœÑ ÐŸÐ¶ÐžÐŽÐ°ÐµÐŒÑÑ
+ Ðž Ð·Ð°ÐºÐŸÐœÑÐµÐœÐœÑÑ
+ Ð·Ð°Ð³ÑÑÐ·ÐŸÐº.</Text>
+<Text id="40">Ð€Ð°Ð¹Ð»Ñ Ð·Ð°Ð³ÑÑÐ¶ÐµÐœÐœÑÐµ Ð² Ð¿Ð°Ð¿ÐºÑ ÑÐ°Ð±ÐŸÑÐµÐ³ÐŸ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²Ð° ÐœÐ°Ð·ÑÐ²Ð°ÑÑÑÑ "ÐÐ°Ð³ÑÑÐ¶Ð°ÐµÐŒÑÐµ ÑÐ°Ð¹Ð»Ñ", Ðž ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐ° Ð²ÑÐµÐŒÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÐŒÐž Ð¿ÐŸÑÑÑÐŸÐµÐœÐœÑÐŒÐž Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÐÐœÑÐµÑÑÐµÐ¹ÑÐ° ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°ÑÑ. Ð€Ð°Ð¹Ð»Ñ Ð² ÑÑÐŸÐ¹ ÐŸÐ±Ð»Ð°ÑÑÐžÐžÐŒÐµÐœÑÑÑÑÑ Ð¿ÐŸ ÐžÑ
+ Ð¿ÐŸÐ»ÐœÐŸÐŒÑ URL Ð°ÐŽÑÐµÑÑ.  Ð¡ÐŸÐ·ÐŽÐ°ÐµÑÑÑ ÐœÐŸÐ²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ° ÐœÐ° ÐºÐ°Ð¶ÐŽÐŸÐŒ Ñ
+ÐŸÑÑÐµ, ÐœÐ°ÑÐ»ÐµÐŽÑÐµÐŒÐ°Ñ ÐŽÑÑÐ³ÐžÐŒÐž ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÑÑÐ°Ð³ÐŒÐµÐœÑÐ° Ð¿ÑÑÐž.  Ð­ÑÐŸ Ð³Ð°ÑÐ°ÐœÑÐžÑÑÐµÑ ÐŸÑÐ»ÐžÑÐžÐµ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»Ð°.</Text>
+<Text id="41">ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ Ð¿ÐµÑÐ²ÑÐ¹ ÐžÐ· ÐºÐŸÐœÑÑÐŸÐ»ÐžÑÑÐµÐŒÑÑ
+ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐ¹ Ð·Ð°Ð³ÑÑÐ·ÐŸÐº, "ÐÑÑ
+ÐŸÐŽÐœÑÐ¹ URL",  ÑÑÐŸÐ±Ñ Ð²Ð²ÐµÑÑÐž URL Ð°ÐŽÑÐµÑ Ð² ÑÐµÐ»ÐµÐ²ÐŸÐ¹ ÑÐµÑÑÑÑ. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐºÐŸÐœÑÑÐŸÐ»Ñ "ÐÐ»ÑÐ±ÐžÐœÑ ÐÐ°Ð³ÑÑÐ·ÐºÐž" ÐŽÐ»Ñ ÐŸÐ³ÑÐ°ÐœÐžÑÐµÐœÐžÑ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²Ð° Ð³ÐžÐ¿ÐµÑÑÑÑÐ»ÐŸÐº ÐŽÐ»Ñ Ð·Ð°Ð³ÑÑÐ·ÐºÐž: Ð£ÑÑÐ°ÐœÐŸÐ²ÐžÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ 0 ÐŽÐ»Ñ Ð·Ð°Ð³ÑÑÐ·ÐºÐž ÐŸÐŽÐœÐŸÐ¹ Ð²ÐµÐ± ÑÑÑÐ°ÐœÐžÑÑ; Ð·ÐœÐ°ÑÐµÐœÐžÐµ 1 ÑÑÐŸÐ±Ñ Ð·Ð°Ð³ÑÑÐ·ÐžÑÑ ÐŸÐŽÐœÑ ÑÑÑÐ°ÐœÐžÑÑ Ðž Ð²ÑÐµ ÑÑÑÐ°ÐœÐžÑÑ ÑÐ²ÑÐ·Ð°ÐœÐœÑÐµ Ñ ÐœÐµÐ¹ . Ð¿ÑÐµÐŽÐµÐ» Ð³Ð»ÑÐ±ÐžÐœÑ ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÑÐµÑÑÑ ÑÐŸÐ»ÑÐºÐŸ ÐœÐ° html ÑÑÑÐ°ÐœÐžÑÑ. Ð¡Ð»ÐµÐŽÑÐ¹ÑÐµÐµ, Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐ° ÑÑÑÐ°ÐœÐŸÐ²ÐºÐ° ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÑ
+ "Ð³Ð°Ð»ÐŸÑÐµÐº", ÐºÐŸÑÐŸÑÑÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÑ, ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ ÑÑÐŸÐ±Ñ ÑÑÐŸÐ±Ñ Ð²ÐºÐ»ÑÑÐžÑÑ ÑÐºÐ°Ð·Ð°ÐœÐœÑÑ ÐŸÑÐŸÐ±ÐµÐœÐœÐŸÑÑÑ ÐºÐŸÐœÐºÑÐµÑÐœÐŸÐ¹ Ð·Ð°Ð³ÑÑÐ·ÐºÐž. ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐ°, ÐœÐ°Ð¶ÐŒÐžÑÐµ "ÐÐ°Ð³ÑÑÐ·ÐºÐ°", ÑÑÐŸÐ±Ñ ÐœÐ°ÑÐ°ÑÑ ÐœÐŸÐ²ÑÑ Ð·Ð°Ð³ÑÑÐ·ÐºÑ. ÐÑÑÑ ÐŽÐ²Ðµ ÐŽÑÑÐ³ÐžÑ
+ ÐºÐœÐŸÐ¿ÐºÐž: Ð² ÑÐ°Ð·ÐŽÐµÐ»Ðµ "ÐÐ°ÑÑÑÐŸÐ¹ÐºÐž", ÐºÐŸÑÐŸÑÑÐµ ÑÐ²ÑÐ·Ð°ÐœÑ Ñ ÑÐ°Ð·ÐŽÐµÐ»ÐŸÐŒ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž ÑÐ²ÑÐ·Ðž, Ð³ÐŽÐµ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ Ð¿ÑÐŸÐºÑÐž ÑÐµÑÐ²ÐµÑÐ° ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐžÐ·ÐŒÐµÐœÐµÐœÑ; Ðž "ÐÑÐžÑÑÐºÐ° ÐÑÑ", ÐºÐŸÑÐŸÑÐ°Ñ ÑÐŽÐ°Ð»ÑÐµÑ Ð²ÑÐµ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°Ð³ÑÑÐ¶ÐµÐœÐœÑÐµ ÑÐ°Ð¹Ð»Ñ.</Text>
+<Text id="42">Ð¡Ð¿ÐžÑÐŸÐº Ð·Ð°Ð³ÑÑÐ·ÐºÐž ÐžÐŒÐµÐµÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ¹ Ð·Ð°Ð³ÑÑÐ¶Ð°ÐµÐŒÐŸÐ¹ Ð²ÐµÐ± ÑÑÑÐ°ÐœÐžÑÑ. ÐÐ°Ð¶ÐŽÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐžÐŒÐµÐµÑ ÑÐµÐºÑÑ Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÑÑÑÐžÐ¹ ÐŽÐµÑÐ°Ð»Ðž Ð·Ð°ÐŽÐ°ÑÐž Ð²ÐŒÐµÑÑÐµ Ñ ÐžÐœÐŽÐžÐºÐ°ÑÐŸÑÐŸÐŒ Ð¿ÑÐŸÐ³ÑÐµÑÑÐ° ÐŽÐµÐŒÐŸÐœÑÑÑÐžÑÑÑÑÐžÐŒ ÑÐµÐºÑÑÑÑ ÐŽÐµÑÑÐµÐ»ÑÐœÐŸÑÑÑ. Ð¢ÑÐž ÐºÐœÐŸÐ¿ÐºÐž Ð¿ÐŸÑÐ²Ð»ÑÑÑÑÑ ÑÐ»ÐµÐ²Ð° ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÑ. "ÐÐ°ÑÐ·Ð°" ÐŽÐ»Ñ Ð¿ÑÐžÐŸÑÑÐ°ÐœÐŸÐ²ÐºÐž Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ ÑÐµÐºÑÑÐµÐ³ÐŸ Ð¿ÑÐŸÑÐµÑÑÐ°. "Ð¡ÐŒÐŸÑÑÐµÑÑ ÐÐŸÐ³Ðž" ÐŸÑÐºÑÑÐ²Ð°ÐµÑ ÐŸÐºÐœÐŸ ÑÐ°Ð¹Ð»Ð° Ð·Ð°Ð³ÑÑÐ·ÐºÐž. "ÐÐ°ÐºÑÑÑÑ" Ð·Ð°Ð²ÐµÑÑÐ°ÐµÑ Ð·Ð°Ð³ÑÑÐ·ÐºÑ Ð·Ð°ÐŽÐ°ÑÐž ÐžÐ· ÑÐ¿ÐžÑÐºÐ°.</Text>
+<Text id="43"><Reference target="preferences"/> ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ ÐºÐ°Ðº ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÐžÐœÑÐµÑÐœÐµÑ ÑÐŸÐµÐŽÐžÐœÐµÐœÐžÐµ ÑÐµÑÐµÐ· Ð¿ÑÐŸÐºÑÐž ÑÐµÑÐ²ÐµÑ.  ÐÑÐ»Ðž ÐœÑÐ¶ÐœÐ° ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÐ°Ñ Ð°ÑÑÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÑ, Ð¿ÑÐŸÐºÑÐž ÑÐµÑÐ²ÐµÑ Ð·Ð°Ð¿ÑÐŸÑÐžÑ ÐžÐŒÑ Ðž Ð¿Ð°ÑÐŸÐ»Ñ.  ÐÐœÑÐµÑÑÐµÐ¹Ñ ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°ÑÑ ÐœÐµ ÑÐŸÐ·ÑÐ°ÐœÑÐµÑ Ð¿Ð°ÑÐŸÐ»Ðž ÐŒÐµÐ¶ÐŽÑ ÑÐµÑÑÐžÑÐŒÐž.</Text><Updated date="2-Mar-2006"/>
+</Section>
+</Section>
+<Section name="collectingfiles">
+<Title>
+<Text id="44">Ð¡Ð±ÐŸÑ ÑÐ°Ð¹Ð»ÐŸÐ² ÐŽÐ»Ñ ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<Text id="45">ÐÑÐ»Ðž ÐÑ ÑÐŸÐ·ÐŽÐ°ÐµÑÐµ ÐœÐŸÐ²ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ,ÑÐŸ Ð²ÐŸÐ·ÐœÐžÐºÐ°ÐµÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÑÑÑ Ð²Ð²ÐŸÐŽÐ° Ð² ÐœÐµÐµ ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ².ÐÐœÐž ÐŒÐŸÐ³ÑÑ Ð¿ÐŸÑÑÑÐ¿ÐžÑÑ ÐžÐ· Ð²Ð°ÑÐµÐ³ÐŸ ÐŸÐ±ÑÑÐœÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ³ÐŸ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²Ð° ÐžÐ· ÐŽÑÑÐ³ÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Greenstone. ÐÐµÐºÐŸÑÐŸÑÑÐµ ÐŒÐŸÐ³ÑÑ ÑÐ¶Ðµ ÐžÐŒÐµÑÑ Ð¿ÑÐžÑÐŸÐµÐŽÐžÐœÐµÐœÐœÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ.Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑÑÑ,ÐºÐ°Ðº ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÑÐ°Ð¹Ð»Ñ.</Text>
+<Section name="thegatherview">
+<Title>
+<Text id="46">ÐÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐœÐ°ÐºÐŸÐ¿ÐžÑÐµÐ»Ñ</Text>
+</Title>
+<Text id="47">Ð­ÑÐŸÑ ÑÐ°Ð·ÐŽÐµÐ» Ð²Ð²ÐŸÐŽÐžÑ Ð² ÐŸÐ±Ð»Ð°ÑÑÑ ÐœÐ°ÐºÐŸÐ¿Ð»ÐµÐœÐžÑ,ÐºÐŸÑÐŸÑÑÑ ÐÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÐµ,ÑÑÐŸÐ±Ñ Ð²ÑÐ±ÑÐ°ÑÑ,ÐºÐ°ÐºÐžÐµ ÑÐ°Ð¹Ð»Ñ Ð²ÐºÐ»ÑÑÐ°ÑÑ Ð² ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÐµÐŒÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ ÐœÐ°ÑÐžÐœÐ°ÐµÑÑÑ Ñ ÐŸÐ±Ð·ÐŸÑÐ° ÐœÐ°ÐºÐŸÐ¿Ð»ÐµÐœÐžÑ. Ð§ÑÐŸÐ±Ñ Ð²ÐµÑÐœÑÑÑÑÑ Ðº ÑÑÐŸÐŒÑ ÐŸÐ±Ð·ÐŸÑÑ Ð¿ÐŸÐ·Ð¶Ðµ,ÑÐµÐ»ÐºÐœÐžÑÐµ ÐœÐ° ÑÐžÐŒÐ²ÐŸÐ»Ðµ "Gather", ÑÐ°ÑÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐœÑÐŒ ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ ÐœÐžÐ¶Ðµ Ð»ÐžÐœÐµÐ¹ÐºÐž ÐŒÐµÐœÑ.  </Text>
+<Text id="48">ÐÐ²Ðµ Ð±ÐŸÐ»ÑÑÐžÐµ ÐŸÐ±Ð»Ð°ÑÑÐž,ÐœÐ°Ð·Ð²Ð°ÐœÐœÑÐµ "Ð Ð°Ð±ÐŸÑÐµÐµ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²ÐŸ" Ðž "ÐoÐ»Ð»ÐµÐºÑÐžÑ" ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ,ÑÑÐŸÐ±Ñ Ð¿ÐµÑÐµÐŒÐµÑÑÐžÑÑ ÑÐ°Ð¹Ð»Ñ Ð² ÐÐ°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. ÐÐœÐž Ð²ÐºÐ»ÑÑÐ°ÑÑ "ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐµ ÐŽÐµÑÐµÐ²ÐŸ",Ð³ÑÐ°ÑÐžÑÐµÑÐºÐžÐµ ÑÑÑÑÐºÑÑÑÑ,ÐºÐŸÑÐŸÑÑÐµ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶Ð°ÑÑ ÑÐ°Ð¹Ð»Ñ Ðž Ð¿Ð°Ð¿ÐºÐž. </Text>
+<Text id="49">ÐÑÐ±ÐµÑÐžÑÐµ ÑÐ»ÐµÐŒÐµÐœÑ ÐŽÐµÑÐµÐ²Ð°, ÐœÐ°Ð¶Ð°Ð² ÐœÐ° ÐœÐµÐ³ÐŸ Ð»ÐµÐ²ÐŸÐ¹ ÐºÐ»Ð°Ð²ÐžÑÐµÐ¹ ÐŒÑÑÐž. (Ð¢ÐŸ Ð¶Ðµ ÑÐ°ÐŒÐŸÐµ ÐŒÐŸÐ¶ÐœÐŸ ÑÐŽÐµÐ»Ð°ÑÑ ÐžÐœÐ°ÑÐµ, ÑÐŒ. ÐœÐžÐ¶Ðµ). ÐÐ²ÐŸÐ¹ÐœÑÐŒ ÑÐµÐ»ÑÐºÐŸÐŒ Ð²ÑÐ±ÐµÑÐžÑÐµ Ð¿Ð°Ð¿ÐºÑ, ÐžÐ»Ðž ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÑÐžÐŒÐ²ÐŸÐ» ÑÑÐŽÐŸÐŒ Ñ ÐœÐµÐ¹, ÑÑÐŸÐ±Ñ ÑÐ°Ð·Ð²ÐµÑÐœÑÑÑ (ÐžÐ»Ðž ÑÐ²ÐµÑÐœÑÑÑ) ÐµÐµ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐµ. ÐÐ²ÐŸÐ¹ÐœÑÐŒ ÑÐµÐ»ÑÐºÐŸÐŒ ÐœÐ° ÐœÑÐ¶ÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ ÐŸÑÐºÑÐŸÐ¹ÑÐµ ÐµÐ³ÐŸ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐœÐŸÐ¹ ÐŽÐ°ÐœÐœÐŸÐŒÑ ÑÐžÐ¿Ñ ÑÐ°Ð¹Ð»ÐŸÐ² Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ (ÑÐŒ.<Reference target="fileassociations"/>).</Text>
+<Text id="50">ÐÐµÑÐµÐ²ÐŸ ÑÐ°Ð±ÐŸÑÐµÐ³ÐŸ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²Ð° Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐžÑÑÐŸÑÐœÐžÐºÐž ÐŽÐ°ÐœÐœÑÑ
+ ÐŽÐŸÑÑÑÐ¿ÐœÑÑ
+ Ð² ÐÐœÑÐµÑÑÐµÐ¹ÑÐµ ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°ÑÑ -- ÑÐµÐºÑÑÑÑ ÑÐ°Ð¹Ð»ÐŸÐ²ÑÑ ÑÐžÑÑÐµÐŒÑ (Ð²ÐºÐ»ÑÑÐ°Ñ ÐŽÐžÑÐºÐŸÐ²ÐŸÐŽ Ðž CD-ROM), ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐÑÐžÐœÑÑÐŸÑÐœ, Ðž ÐºÑÑ Ð·Ð°Ð³ÑÑÐ¶ÐµÐœÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ². ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÐžÐŽÐµÑÑ Ðž ÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÑÑ ÑÑÐž ÑÐ°Ð¹Ð»Ñ, ÐŸÐŽÐœÐ°ÐºÐŸ ÐœÐµ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÐµÑÐµÐœÐŸÑÐžÑÑ, ÑÐŽÐ°Ð»ÑÑÑ, ÐžÐ»Ðž ÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ ÐžÑ
+, Ð·Ð° ÐžÑÐºÐ»ÑÑÐµÐœÐžÐµÐŒ ÑÐ¶Ðµ Ð·Ð°Ð³ÑÑÐ¶ÐµÐœÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐŽÐ°Ð»ÐµÐœÑ.  ÐÑÑÑÐµÑÑÐ²Ð»ÑÑÑ ÐœÐ°Ð²ÐžÐ³Ð°ÑÐžÑ Ð² ÑÑÐŸÐŒ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²Ðµ ÑÑÐŸÐ±Ñ ÐœÐ°Ð¹ÑÐž ÑÐ°Ð¹Ð»Ñ ÐºÐŸÑÐŸÑÑÐµ Ð²Ñ Ñ
+ÐŸÑÐžÑÐµ Ð²ÐºÐ»ÑÑÐžÑÑ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ.</Text>
+<Text id="51">Ð€Ð°Ð¹Ð»ÐŸÐ²ÐŸÐµ ÐŽÐµÑÐµÐ²ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÐµÑ Ð¿ÐŸÐ»ÐœÐŸÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐµÑÐ²ÐŸÐœÐ°ÑÐ°Ð»ÑÐœÐŸ ÐŸÐœÐŸ Ð¿ÑÑÑÐŸ.</Text>
+<Text id="52">ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÑÐ°Ð·ÐŒÐµÑÑ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²Ð°, Ð¿ÐµÑÐµÐŽÐ²ÐžÐ³Ð°Ñ ÐŒÑÑÑ Ð¿ÐŸ ÑÐµÑÐŸÐ¹ Ð»ÐžÐœÐµÐ¹ÐºÐµ, ÐºÐŸÑÐŸÑÐ°Ñ ÐŸÑÐŽÐµÐ»ÑÐµÑ ÐŽÐµÑÐµÐ²ÑÑ (ÑÐŸÑÐŒÐ° ÑÐºÐ°Ð·Ð°ÑÐµÐ»Ñ ÐžÐ·ÐŒÐµÐœÑÐµÑÑÑ),Ðž Ð±ÑÐºÑÐžÑÑÑ ÐžÑ
+.</Text>
+<Text id="53">ÐÐœÐžÐ·Ñ ÐŸÐºÐœÐ° ÑÐ°ÑÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐ° ÑÑÐ°ÑÑÑÐœÐ°Ñ ÐŸÐ±Ð»Ð°ÑÑÑ, ÐºÐŸÑÐŸÑÐ°Ñ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð¿ÑÐŸÐ³ÑÐµÑÑ ÐŸÐ¿ÐµÑÐ°ÑÐžÐ¹ ÐœÐ°ÐŽ ÑÐ°Ð¹Ð»Ð°ÐŒÐž (ÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÐœÐžÐµ, Ð¿ÐµÑÐµÐŒÐµÑÐµÐœÐžÐµ, ÑÐŽÐ°Ð»ÐµÐœÐžÐµ). ÐÐœÐž ÐŒÐŸÐ³ÑÑ Ð·Ð°ÐœÑÑÑ ÐºÐ°ÐºÐŸÐµ-ÑÐŸ Ð²ÑÐµÐŒÑ. ÐÐœÐŸÐ¿ÐºÐ° "Ð¡ÑÐŸÐ¿" ÐŸÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑ Ð»ÑÐ±ÐŸÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ, ÐºÐŸÑÐŸÑÐŸÐµ Ð² ÐœÐ°ÑÑÐŸÑÑÐµÐµ Ð²ÑÐµÐŒÑ Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÐžÑ. </Text>
+<Text id="54">ÐÐ²Ðµ Ð±ÐŸÐ»ÑÑÐžÐµ ÐºÐœÐŸÐ¿ÐºÐž Ð·Ð°ÐœÐžÐŒÐ°ÑÑ ÐœÐžÐ¶ÐœÐžÐ¹ Ð¿ÑÐ°Ð²ÑÐ¹ ÑÐ³ÐŸÐ» ÑÐºÑÐ°ÐœÐ°."ÐÐŸÐ²Ð°Ñ ÐÐ°Ð¿ÐºÐ°",Ñ ÐºÐ°ÑÑÐžÐœÐŸÐ¹ Ð¿Ð°Ð¿ÐºÐž, ÑÐŸÐ·ÐŽÐ°ÑÑ ÐœÐŸÐ²ÑÐµ Ð¿Ð°Ð¿ÐºÐž (ÑÐŒ. <Reference target="creatingfolders"/>). ÐÐœÐŸÐ¿ÐºÐ° "Ð£ÐŽÐ°Ð»ÐžÑÑ"ÑÐŽÐ°Ð»ÑÐµÑ ÑÐ°Ð¹Ð»Ñ Ñ ÐœÐµÐœÑÐ¶ÐœÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐµÐ¹.Ð©ÐµÐ»ÑÐŸÐº ÐœÐ° ÐºÐœÐŸÐ¿ÐºÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ" ÑÐŽÐ°Ð»ÐžÑ Ð»ÑÐ±ÑÐµ ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÑÐµ ÑÐ°Ð¹Ð»Ñ ÐžÐ· ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ³ÐŸ ÐŽÐµÑÐµÐ²Ð° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐ»ÑÑÐµÑÐœÐ°ÑÐžÐ²ÐœÐŸ, ÑÐ°Ð¹Ð»Ñ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐŽÐ°Ð»ÐµÐœÑ Ð¿ÑÑÐµÐŒ Ð¿ÐµÑÐµÑÑÐ³ÐžÐ²Ð°ÐœÐžÑ ÐžÑ
+ ÐœÐ° ÐºÐœÐŸÐ¿ÐºÑ "Ð£ÐŽÐ°Ð»ÐžÑÑ". </Text>
+<Text id="55">Ð§ÑÐŸÐ±Ñ ÐŸÑÐŸÐ±ÑÐ°ÑÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ Ð¿ÐŸÑÐ»ÐµÐŽÐŸÐ²Ð°ÑÐµÐ»ÑÐœÑÑ
+ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ²,Ð²ÑÐ±ÐµÑÐžÑÐµ Ð¿ÐµÑÐ²ÑÐ¹ Ðž Ð·Ð°ÑÐµÐŒ ÑÐŽÐµÑÐ¶ÐžÐ²Ð°Ñ [Shift],ÑÐµÐ»ÐºÐœÐžÑÐµ ÐœÐ° Ð¿ÐŸÑÐ»ÐµÐŽÐœÐµÐŒ - Ð¿ÑÐž ÑÑÐŸÐŒ Ð±ÑÐŽÑÑ ÐŸÑÐŸÐ±ÑÐ°ÐœÑ Ð²ÑÐµ ÐŸÑ
+Ð²Ð°ÑÐµÐœÐœÑÐµ ÑÐ»ÐµÐŒÐµÐœÑÑ.ÐÑÐ±ÐŸÑ ÐœÐµ ÑÐ»ÐµÐŽÑÑÑÐžÑ
+ ÐŸÐŽÐžÐœ Ð·Ð° ÐŽÑÑÐ³ÐžÐŒ ÑÐ°Ð¹Ð»ÐŸÐ² Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑÑ Ð¿ÑÐž ÐœÐ°Ð¶Ð°ÑÐŸÐ¹ ÐºÐ»Ð°Ð²ÐžÑÐµ [Ctrl] Ðž ÑÐµÐ»ÑÐºÐµ ÐœÐ° Ð²ÑÐ±ÐžÑÐ°ÐµÐŒÑÑ
+ ÑÐ°Ð¹Ð»Ð°Ñ
+. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÑÑÐž ÐŽÐ²Ð° ÐŒÐµÑÐŸÐŽÐ° Ð²ÐŒÐµÑÑÐµ ÐŽÐ»Ñ Ð³ÑÑÐ¿Ð¿Ñ ÐœÐµÑÐŒÐµÐ¶ÐœÑÑ
+ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ².  </Text>
+<Text id="56">ÐÐµÐºÐŸÑÐŸÑÑÐµ Ð¿Ð°Ð¿ÐºÐž - ÑÐžÐ¿Ð° ÑÐµÑ
+,ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐŽÐµÑÐ¶Ð°Ñ ÐÐ°ÑÐž ÑÐŸÐ±ÑÑÐ²ÐµÐœÐœÑÐµ Ð²ÐµÐ±-ÑÑÑÐ°ÐœÐžÑÑ - ÐžÐœÐŸÐ³ÐŽÐ° ÐžÐŒÐµÑÑ ÐŸÑÐŸÐ±ÑÑ Ð²Ð°Ð¶ÐœÐŸÑÑÑ.ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð¿ÐµÑÐµÐœÐµÑÑÐž ÑÐ°ÐºÐžÐµ Ð¿Ð°Ð¿ÐºÐž ÐœÐ° Ð¿ÐµÑÐ²ÑÐ¹ ÑÑÐŸÐ²ÐµÐœÑ ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ³ÐŸ ÐŽÐµÑÐµÐ²Ð°. Ð§ÑÐŸÐ±Ñ ÑÐŽÐµÐ»Ð°ÑÑ ÑÑÐŸ, ÑÐµÐ»ÐºÐœÐžÑÐµ Ð¿ÑÐ°Ð²ÐŸÐ¹ ÐºÐœÐŸÐ¿ÐºÐŸÐ¹ ÐŒÑÑÐž ÐœÐ° Ð¶ÐµÐ»Ð°ÑÐµÐ»ÑÐœÐŸÐ¹ Ð¿Ð°Ð¿ÐºÐµ. ÐÑÐ±ÐµÑÐžÑÐµ "Ð¡ÐŸÐ·ÐŽÐ°ÑÑ ÑÐŸÐºÑÐ°ÑÐµÐœÐžÐµ" Ðž Ð²Ð²ÐµÐŽÐžÑÐµ ÐžÐŒÑ ÐŽÐ»Ñ Ð¿Ð°Ð¿ÐºÐž. ÐÐ»Ñ ÑÐŽÐ°Ð»ÐµÐœÐžÑ ÑÐ»ÐµÐŒÐµÐœÑÐ° ÑÐµÐ»ÐºÐœÐžÑÐµ Ð¿ÑÐ°Ð²ÐŸÐ¹ ÐºÐœÐŸÐ¿ÐºÐŸÐ¹ ÐŒÑÑÐž ÐœÐ° Ð¿ÐŸÐŒÐµÑÐµÐœÐœÐŸÐ¹ Ð¿Ð°Ð¿ÐºÐµ Ðž Ð²ÑÐ±ÐµÑÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ ÑÐŸÐºÑÐ°ÑÐµÐœÐžÑ".</Text>
+</Section>
+<Section name="creatingfolders">
+<Title>
+<Text id="57">Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ Ð¿Ð°Ð¿ÐŸÐº</Text>
+</Title>
+<Text id="58">ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ "ÐÐ°Ð¿ÐºÐž" Ð² ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐŒ ÐŽÐµÑÐµÐ²Ðµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÑÐŸÐ±Ñ Ð³ÑÑÐ¿Ð¿ÐžÑÐŸÐ²Ð°ÑÑ Ð²ÐŒÐµÑÑÐµ Ðž Ð±ÐŸÐ»ÐµÐµ Ð»ÐµÐ³ÐºÐŸ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑ ÐžÑ
+. ÐÐ°Ð¿ÐºÐž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð¿ÐŸÐŒÐµÑÐµÐœÑ Ð²ÐœÑÑÑÐž Ð¿Ð°Ð¿ÐŸÐº. Ð€Ð°ÐºÑÐžÑÐµÑÐºÐž ÐœÐµÑ ÐŸÐ³ÑÐ°ÐœÐžÑÐµÐœÐžÑ ÐœÐ° ÑÐŸ,ÑÐºÐŸÐ»ÑÐºÐŸ Ð¿Ð°Ð¿ÐŸÐº ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÐŒÐµÑÑ ÐžÐ»Ðž ÐºÐ°Ðº Ð³Ð»ÑÐ±ÐŸÐºÐŸ ÐŸÐœÐž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð²Ð»ÐŸÐ¶ÐµÐœÑ.</Text>
+<Text id="59">Ð§ÑÐŸÐ±Ñ ÑÐŸÐ·ÐŽÐ°ÑÑ ÐœÐŸÐ²ÑÑ Ð¿Ð°Ð¿ÐºÑ, Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐ»ÑÐœÐŸ Ð²ÑÐ±ÐµÑÐžÑÐµ ÑÑÑÐµÑÑÐ²ÑÑÑÑÑ Ð¿Ð°Ð¿ÐºÑ Ð² ÐÐµÑÐµÐ²Ðµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ ÐœÐ° ÐºÐœÐŸÐ¿ÐºÐµ "ÐÐŸÐ²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ°". ÐÐŸÐ²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ° Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÐŸÐ³ÐŸ ÐžÐ»Ðž ÐœÐ° Ð²ÑÑÑÐµÐŒ ÑÑÐŸÐ²ÐœÐµ,ÐµÑÐ»Ðž ÐœÐž ÐŸÐŽÐœÐ° ÐœÐµ ÐŸÑÐŸÐ±ÑÐ°ÐœÐ°.ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ Ð¿ÑÐŸÑÐ²ÐŸÐžÑÑ Ð¿Ð°Ð¿ÐºÐµ ÐžÐŒÑ (Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ "ÐÐŸÐ²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ°").</Text>
+<Text id="60">ÐÐ°Ð¿ÐºÐž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐ°ÐºÐ¶Ðµ ÑÐŸÐ·ÐŽÐ°ÐœÑ ÑÐµÐ»ÑÐºÐŸÐŒ Ð¿ÑÐ°Ð²ÐŸÐ¹ ÐºÐœÐŸÐ¿ÐºÐž ÐŒÑÑÐž Ð¿ÐŸ Ð¿Ð°Ð¿ÐºÐµ,Ð²ÑÐ±ÐžÑÐ°Ñ "ÐÐŸÐ²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ°" Ðž ÐŽÐµÐ¹ÑÑÐ²ÑÑ,ÐºÐ°Ðº ÑÐºÐ°Ð·Ð·Ð°ÐœÐŸ Ð²ÑÑÐµ.</Text>
+</Section>
+<Section name="addingfiles">
+<Title>
+<Text id="61">ÐÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÐµ ÑÐ°Ð¹Ð»ÐŸÐ²</Text>
+</Title>
+<Text id="62">Ð€Ð°Ð¹Ð»Ñ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÐœÑ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐŒÑÑÑÑ Ð¿ÑÑÐµÐŒ ÐžÑ
+ Ð¿ÐµÑÐµÑÑÐ³ÐžÐ²Ð°ÐœÐžÑ Ðž ÐŸÑÐ¿ÑÑÐºÐ°ÐœÐžÑ. Ð£ÐºÐ°Ð·Ð°ÑÐµÐ»Ñ ÐŒÑÑÐž ÐŸÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑÑÑ ÐœÐ°ÐŽ ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÑÐŒ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐŒ ÐžÐ»Ðž, ÐµÑÐ»Ðž Ð²ÑÐ±ÐžÑÐ°ÐµÑÑÑ Ð±ÐŸÐ»ÑÑÐµ,ÑÐµÐŒ ÐŸÐŽÐžÐœ,ÐœÐ°ÐŽ ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÐŒÐž. ÐÑÐŸÐ¿ÑÑÑÐžÑÐµ Ð²ÑÐ±ÑÐ°ÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» Ð² ÐÐµÑÐµÐ²ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÑÐŸÐ±Ñ Ð·ÐŽÐµÑÑ ÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÑÑ ÑÐ°Ð¹Ð»Ñ (ÐµÑÐ»Ðž ÐžÑÑÐŸÑÐœÐžÐºÐŸÐŒ Ð±ÑÐ»ÐŸ ÐÐµÑÐµÐ²ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž).</Text>
+<Text id="63">ÐÑÐž ÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÐœÐžÐž ÐŒÐœÐŸÐ¶ÐµÑÑÐ²ÐµÐœÐœÑÑ
+(ÑÐŸÑÑÐ°Ð²ÐœÑÑ
+) ÑÐ°Ð¹Ð»ÐŸÐ²,Ð²ÑÐµ ÐŸÐœÐž Ð¿ÐµÑÐµÐŒÐµÑÐ°ÑÑÑÑ Ð² ÑÐµÐ»ÐµÐ²ÑÑ Ð¿Ð°Ð¿ÐºÑ ÐœÐ° ÑÐŸÑ Ð¶Ðµ ÑÐ°ÐŒÑÐ¹ ÑÑÐŸÐ²ÐµÐœÑ,ÐœÐµÐ·Ð°Ð²ÐžÑÐžÐŒÐŸ ÐŸÑ ÑÑÑÑÐºÑÑÑÑ Ð¿Ð°Ð¿ÐºÐž,ÐºÐŸÑÐŸÑÑÑ ÐŸÐœÐž Ð·Ð°ÐœÐžÐŒÐ°Ð»Ðž Ð¿ÐµÑÐ²ÐŸÐœÐ°ÑÐ°Ð»ÑÐœÐŸ. ÐÐŸÐ³ÐŽÐ° ÐÑ ÐºÐŸÐ¿ÐžÑÑÐµÑÐµ Ð²ÑÐŸÑÐŸÐ¹ ÑÐ°Ð¹Ð» Ñ ÑÐµÐŒ Ð¶Ðµ ÑÐ°ÐŒÑÐŒ ÐžÐŒÐµÐœÐµÐŒ Ð² ÑÑ Ð¶Ðµ ÑÐ°ÐŒÑÑ Ð¿Ð°Ð¿ÐºÑ, ÐÐ°Ñ Ð·Ð°Ð¿ÑÐŸÑÑÑ, Ð·Ð°ÑÐµÑÐµÑÑ Ð»Ðž Ð¿ÐµÑÐ²ÑÐ¹. ÐÑÐ²ÐµÑÑÑÐµ "ÐÐµÑ" Ðž ÑÑÐŸÑ ÑÐ°Ð¹Ð» ÐœÐµ Ð±ÑÐŽÐµÑ ÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÑÑÑÑ,ÐœÐŸ ÐŽÑÑÐ³ÐžÐµ Ð±ÑÐŽÑÑ. Ð§ÑÐŸÐ±Ñ ÐŸÑÐŒÐµÐœÐžÑÑ Ð²ÑÐµ ÐŸÑÑÐ°ÑÑÐžÐµÑÑ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ Ð¿ÐŸ ÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÐœÐžÑ,ÑÐµÐ»ÐºÐœÐžÑÐµ ÐœÐ° ÐºÐœÐŸÐ¿ÐºÐµ "Ð¡ÑÐŸÐ¿".   </Text>
+<Text id="64">Ð¢ÐŸÐ»ÑÐºÐŸ "ÑÐ°ÐŒÑÐµ Ð²ÑÑÐŸÐºÐžÐµ"ÐžÐ· ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÑÑ
+ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² Ð±ÑÐŽÑÑ Ð¿ÐµÑÐµÐŒÐµÑÐµÐœÑ. ÐÐ°Ð¿ÐºÐ° Ð²ÑÑÐµ, ÑÐµÐŒ ÐµÑ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐœÑÐµ. ÐÑ ÐœÐµ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐ±ÑÐ°ÑÑ ÑÐ°Ð¹Ð»Ñ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ Ð¿Ð°Ð¿ÐºÐž,Ð° ÑÐ°ÐºÐ¶Ðµ ÑÐ°ÐŒÑ Ð¿Ð°Ð¿ÐºÑ ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ. </Text>
+<Text id="65">ÐÐŸÐ³ÐŽÐ° ÐÑ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑÐµ ÑÐ°Ð¹Ð», ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÑÐŸÐ²ÐŸÐŽÐžÑ Ð¿ÐŸÐžÑÐº Ð² ÐžÑÑ
+ÐŸÐŽÐœÑÑ
+ Ð¿Ð°Ð¿ÐºÐ°Ñ
+ Ð²ÑÐ¿ÐŸÐŒÐŸÐ³Ð°ÑÐµÐ»ÑÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ², ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐžÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ Ðº ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÐŒÐŸÐŒÑ ÑÐ°Ð¹Ð»Ñ,Ðž ÐµÑÐ»Ðž ÐŸÐœ ÐœÐ°Ñ
+ÐŸÐŽÐžÑ ÐµÐ³ÐŸ,ÑÐŸ ÐœÐ°ÑÐžÐœÐ°ÐµÑ ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÑÑÐž ÐŽÐ°ÐœÐœÑÐµ. ÐÑÐ»Ðž Ð¿ÑÐŸÑÐµÑÑ Ð¿ÑÐŸÐŽÐŸÐ»Ð¶Ð°ÐµÑÑÑ,ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð±ÑÑÑ Ð·Ð°Ð¿ÑÐŸÑÐµÐœÑ (Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÑÐ°Ð·) ÐŸ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž,ÑÑÐŸÐ±Ñ ÐŽÐŸÑÑÐžÑÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÑ ÐžÐŒÐ¿ÐŸÑÑÐžÑÑÐµÐŒÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ñ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒÐž,ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐœÑÐŒÐž Ð² ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð­ÑÐŸÑ Ð¿ÑÐŸÑÐµÑÑ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÐŒÐœÐŸÐ³ÐžÐµ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ Ð·Ð°Ð¿ÑÐŸÑÑ, ÐŸÐ¿ÐžÑÐ°ÐœÐœÑÐµ Ð² ÑÐ°Ð·ÐŽÐµÐ»Ðµ<Reference target="importingpreviouslyassignedmetadata"/>.ÐÐ»Ñ Ð±ÐŸÐ»ÐµÐµ ÐŽÐµÑÐ°Ð»ÑÐœÐŸÐ³ÐŸ ÐŸÐ±ÑÑÑÐœÐµÐœÐžÑ Ð°ÑÑÐŸÑÐžÐžÑÐŸÐ²Ð°ÐœÐœÑÑ
+ Ñ ÑÐ°Ð¹Ð»Ð°ÐŒÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÑÐžÑÐ°Ð¹ÑÐµ ÐÐ»Ð°Ð²Ñ 2 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone - ÐÐ·Ð²Ð»ÐµÑÐµÐœÐžÐµ Ð±ÐŸÐ»ÑÑÐžÐœÑÑÐ²Ð° Ð²Ð°ÑÐžÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ².  </Text>
+</Section>
+<Section name="removingfiles">
+<Title>
+<Text id="66">Ð£ÐŽÐ°Ð»ÐµÐœÐžÐµ ÑÐ°Ð¹Ð»ÐŸÐ²</Text>
+</Title>
+<Text id="67">Ð¡ÑÑÐµÑÑÐ²ÑÐµÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐŒÐµÑÐŸÐŽÐŸÐ² ÑÐŽÐ°Ð»ÐµÐœÐžÑ ÑÐ°Ð¹Ð»ÐŸÐ² Ðž Ð¿Ð°Ð¿ÐŸÐº. ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ ÑÐœÐ°ÑÐ°Ð»Ð° ÑÐºÐ°Ð·Ð°ÑÑ,ÐºÐ°ÐºÐžÐµ ÐžÐ· ÐœÐžÑ
+ ÑÐŽÐ°Ð»ÑÑÑ, Ð²ÑÐ±ÐžÑÐ°Ñ ÐŸÐŽÐžÐœ ÐžÐ»Ðž Ð±ÐŸÐ»ÐµÐµ ÑÐ°Ð¹Ð»ÐŸÐ² Ðž Ð¿Ð°Ð¿ÐŸÐº, ÐºÐ°Ðº ÐŸÐ¿ÐžÑÐ°ÐœÐŸ Ð² <Reference target="thegatherview"/>.</Text>
+<Text id="68">ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÑÐ°Ð¹Ð»Ñ ÐŸÑÐŸÐ±ÑÐ°ÐœÑ, ÐŽÐ»Ñ ÐžÑ
+ ÑÐŽÐ°Ð»ÐµÐœÐžÑ ÑÐµÐ»ÐºÐ°ÑÑ ÐºÐœÐŸÐ¿ÐºÑ "Ð£ÐŽÐ°Ð»ÐžÑÑ"ÐžÐ»Ðž ÐœÐ°Ð¶ÐžÐŒÐ°ÑÑ ÐºÐºÐ»Ð°Ð²ÐžÑÑ [Ð£ÐŽÐ°Ð»ÐžÑÑ] ÐœÐ° ÐºÐ»Ð°Ð²ÐžÐ°ÑÑÑÐµ, ÐžÐ»Ðž Ð¶Ðµ ÑÑÐœÑÑ ÐžÑ
+ ÐžÐ· ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŽÐŸ ÐºÐœÐŸÐ¿ÐºÐž "Ð£ÐŽÐ°Ð»ÐžÑÑ" Ðž ÑÐ°ÐŒ ÐŸÑÐ¿ÑÑÐºÐ°ÑÑ.  </Text>
+</Section>
+<Section name ="filteringthetree">
+<Title>
+<Text id="69">Ð€ÐžÐ»ÑÑÑÐŸÐ²Ð°ÐœÐžÐµ ÐŽÐµÑÐµÐ²Ð°</Text>
+</Title>
+<Text id="70">"Ð€ÐžÐ»ÑÑÑÐŸÐ²Ð°ÐœÐžÐµ" ÐŽÐµÑÐµÐ²Ð° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐÐ°ÐŒ ÑÑÐ¶Ð°ÑÑ Ð¿ÐŸÐžÑÐº ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐžÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ².</Text>
+<Text id="71">ÐÑÐœÐºÑ "ÐÐŸÐºÐ°Ð·Ð°ÑÑ ÑÐ°Ð¹Ð»Ñ" Ð² ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐŒ ÐŒÐµÐœÑ Ð¿ÐŸÐŽ ÐºÐ°Ð¶ÐŽÑÐŒ ÐŽÐµÑÐµÐ²ÐŸÐŒ Ð²ÑÐ²ÐŸÐŽÐžÑ ÑÐ¿ÐžÑÐŸÐº Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÑÑ
+ ÑÐžÐ»ÑÑÑÐŸÐ² ÑÐžÐ¿Ð° "Images".ÐÑÐ±ÐµÑÐžÑÐµ Ðž Ð²ÑÐµ Ð²ÑÐµÐŒÐµÐœÐœÐŸ ÑÐºÑÑÑÑÐµ ÑÐ°Ð¹Ð»Ñ Ð² ÐŽÐµÑÐµÐ²Ðµ.Ð§ÑÐŸÐ±Ñ Ð²ÐŸÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÐŽÐµÑÐµÐ²ÐŸ,Ð·Ð°ÐŒÐµÐœÐžÑÐµ ÑÐžÐ»ÑÑÑ ÑÐœÐŸÐ²Ð° ÐœÐ° "ÐÑÐµ ÑÐ°Ð¹Ð»Ñ".Ð­ÑÐž ÐŽÐµÐ¹ÑÑÐ²ÐžÑ ÐœÐµ ÐžÐ·ÐŒÐµÐœÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð¿ÑÐž ÑÑÐŸÐŒ ÐŸÐœÐž ÐœÐµ Ð·Ð°ÑÑÐ°Ð³ÐžÐ²Ð°ÑÑ Ð¿Ð°Ð¿ÐºÐž Ð² ÐŽÐµÑÐµÐ²Ðµ. </Text>
+<Text id="72">ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð·Ð°ÐŽÐ°ÑÑ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÑ ÑÐžÐ»ÑÑÑÐ°,ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð² Ð² ÑÑ
+ÐµÐŒÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐµ ÑÐ°Ð¹Ð»ÐŸÐ² (Ð¢ÐŸÐ»ÑÐºÐŸ ÐŽÐ»Ñ ÑÐµÐ¶ÐžÐŒÐŸÐ² Ð¡Ð¿ÐµÑÐžÐ°Ð»ÐžÑÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÑ
+ Ð¡ÐžÑÑÐµÐŒ Ðž Ð­ÐºÑÐ¿ÐµÑÑ).ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÐµ Ð°Ð±Ð±ÑÐµÐ²ÐžÐ°ÑÑÑÑ ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ¹ ÑÐžÑÑÐµÐŒÑ ÑÐžÐ¿Ð° "*.*" ÐžÐ»Ðž "*.doc" ("*" ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÐµÑ Ð»ÑÐ±ÑÐŒ ÑÐžÐŒÐ²ÐŸÐ»Ð°ÐŒ). </Text>
+</Section>
+</Section>
+<Section name="enrichingacollection">
+<Title>
+<Text id="73">ÐÐ±ÐŸÐ³Ð°ÑÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒÐž</Text>
+</Title>
+<Text id="74">ÐÐŒÐµÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐœÐ°ÐºÐŸÐ¿Ð»ÐµÐœÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž,ÐœÐ°Ð¿ÐŸÐ»ÐœÐžÑÐµ ÐžÑ
+ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐµÐ¹,ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒÐŸÐ¹ "ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ".Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ, ÐºÐ°Ðº ÑÐŸÐ·ÐŽÐ°ÑÑÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ,ÐºÐ°Ðº ÐŸÐœÐž ÑÐµÐŽÐ°ÐºÑÐžÑÑÑÑÑÑ, ÐœÐ°Ð·ÐœÐ°ÑÐ°ÑÑÑÑ Ðž Ð²ÐŸÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÑÑÑÑ,Ð° ÑÐ°ÐºÐ¶Ðµ ÐºÐ°Ðº ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ Ð²ÐœÐµÑÐœÐžÐµ ÐžÑÑÐŸÑÐœÐžÐºÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ (ÑÐ°ÐºÐ¶Ðµ ÑÐŒ.ÐÐ»Ð°Ð²Ñ 2 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone - ÐÐŸÐ»ÑÑÐµÐœÐžÐµ Ð±ÐŸÐ»ÑÑÐµÐ¹ ÑÐ°ÑÑÐž ÐžÐ· Ð²Ð°ÑÐžÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²). </Text>
+<Section name="theenrichview">
+<Title>
+<Text id="75">ÐÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐŸÐ±ÐŸÐ³Ð°ÑÐµÐœÐžÑ</Text>
+</Title>
+<Text id="76">ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐŸÐ±ÐŸÐ³Ð°ÑÐµÐœÐžÑ ÐŽÐ»Ñ Ð·Ð°ÐŽÐ°ÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ - ÑÑÐŸ ÐŽÐ°ÐœÐœÑÐµ ÐŸ ÐŽÐ°ÐœÐœÑÑ
+ - ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÐÐ°Ð·Ð²Ð°ÐœÐžÐµ,ÐÐ²ÑÐŸÑ,ÐÐ°ÑÐ° ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ Ðž Ñ.ÐŽ. ÐÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ - ÑÑÐŸ ÐŽÐ°ÐœÐœÑÐµ ÐŸ ÐŽÐ°ÐœÐœÑÑ
+, ÐŸÐ±ÑÑÐœÐŸ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ, Ð°Ð²ÑÐŸÑ, ÐŽÐ°ÑÐ° ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° Ðž.Ñ.Ð¿. ÐÐ°Ð¶ÐŽÑÐ¹ Ð¿ÑÐµÐŽÐŒÐµÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÑÐŸÑÑÐŸÐžÑ ÐžÐ· ÐŽÐ²ÑÑ
+ ÑÐ°ÑÑÐµÐ¹: "ÑÐ»ÐµÐŒÐµÐœÑ" ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ, ÐºÐ°ÐºÐŸÐ¹ Ð¿ÑÐµÐŽÐŒÐµÑ ÐžÐŒÐµÐµÑÑÑ Ð²Ð²ÐžÐŽÑ (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, Ð°Ð²ÑÐŸÑ), Ð° "Ð·ÐœÐ°ÑÐµÐœÐžÐµ" Ð¿ÑÐžÑÐ²Ð°ÐžÐ²Ð°ÐµÑ ÑÑÐŸÐŒÑ ÑÐ»ÐµÐŒÐµÐœÑÑ ÐµÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÐžÐŒÑ Ð°Ð²ÑÐŸÑÐ°).</Text>
+<Text id="77">Ð "ÑÐ°ÑÑÐžÑÐµÐœÐœÐŸÐŒ" Ð²ÐžÐŽÐµ ÑÐ»ÐµÐ²Ð° ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ ÐÐµÑÐµÐ²ÐŸ ÐÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐ¿ÑÐ°Ð²Ð° Ð¢Ð°Ð±Ð»ÐžÑÐ° ÐÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÐºÐŸÑÐŸÑÐ°Ñ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ Ð²ÑÐ±ÑÐ°ÐœÐœÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»Ð° ÐžÐ»Ðž Ð¿Ð°Ð¿ÐºÐž ÐžÐ· ÐÐµÑÐµÐ²Ð° ÐÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð¡ÑÐŸÐ»Ð±ÑÑ ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœÑ ÑÐµÑÑÐŒ ÑÐ²ÐµÑÐŸÐŒ Ð²Ð²ÐµÑÑ
+Ñ Ðž ÐžÑ
+ ÑÐ°Ð·ÐŒÐµÑ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐžÐ·ÐŒÐµÐœÑÐœ Ð¿ÑÑÑÐŒ Ð¿ÐµÑÐµÐŽÐ²ÐžÐ¶ÐµÐœÐžÑ Ð»ÐžÐœÐžÐž ÑÐ°Ð·ÐŽÐµÐ»Ð°. ÐÐ°Ð¶Ð°Ð² ÐœÐ° Ð»ÑÐ±ÐŸÐ¹ ÑÑÐŽ Ð² ÑÐ°Ð±Ð»ÐžÑÐµ, Ð²Ñ ÑÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ Ðž ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ ÐŽÐµÑÐ°Ð»Ðž ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+ Ð² ÐœÐžÐ¶ÐœÐµÐ¹ ÑÐµÐºÑÐžÐž ÐŸÐºÐœÐ°. Ð§ÐµÑÐœÑÐ¹ ÑÐµÐºÑÑ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ, ÑÑÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÑÐ²Ð»ÑÐµÑÑÑ ÐŸÐ±ÑÐžÐŒ ÐŽÐ»Ñ Ð²ÑÐµÑ
+ ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ²,ÑÐŸÐ³ÐŽÐ° ÐºÐ°Ðº ÑÐµÑÑÐ¹ ÑÐµÐºÑÑ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ,ÑÑÐŸ ÑÑÐŸ - ÐœÐµ ÑÐ°Ðº.Ð§ÐµÑÐœÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐŸÐ±ÐœÐŸÐ²Ð»ÐµÐœÑ ÐžÐ»Ðž ÑÐŽÐ°Ð»ÐµÐœÑ, Ð² ÑÐŸ Ð²ÑÐµÐŒÑ ÐºÐ°Ðº ÑÐµÑÑÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐŽÐ°Ð»ÐµÐœÑ ÐžÐ· ÑÐµÑ
+,ÐºÐŸÑÐŸÑÑÐµ ÐžÐŒÐµÑÑ ÐžÑ
+,ÐžÐ»Ðž ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÑ Ðº ÐŽÑÑÐ³ÐžÐŒ.  </Text>
+<Text id="78">ÐÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ Ð¿Ð°Ð¿ÐºÐž ÐŒÐŸÐ¶ÐµÑ Ð¿ÐŸÑÐ²Ð»ÑÑÑÑÑ ÐŸÐºÐŸÐ»ÐŸ ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ Ð²Ñ
+ÐŸÐŽÐŸÐ² ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+.Ð­ÑÐŸ ÑÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐœÐ° ÑÐŸ,ÑÑÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÑÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÑ ÐŸÑ Ð¿Ð°Ð¿ÐŸÐº ÑÐŸÐŽÐžÑÐµÐ»ÐµÐ¹ (ÐžÐ»Ðž Ð¿ÑÐµÐŽÐºÐŸÐ²). Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐœÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÑ ÐžÐ»Ðž ÑÐŽÐ°Ð»ÐµÐœÑ, Ð° ÑÐŸÐ»ÑÐºÐŸ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÑ Ð² ÐºÐŸÐœÐµÑ ÑÐ¿ÐžÑÐºÐ° ÐžÐ»Ðž Ð¿ÐµÑÐµÐ¿ÐžÑÐ°ÐœÑ.Ð©ÐµÐ»ÐºÐœÐžÑÐµ ÐœÐ° ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐž Ð¿Ð°Ð¿ÐºÐž,ÑÑÐŸÐ±Ñ ÐœÐµÐŒÐµÐŽÐ»ÐµÐœÐœÐŸ Ð¿ÐµÑÐµÐ¹ÑÐž Ð² ÑÑ Ð¿Ð°Ð¿ÐºÑ, Ð³ÐŽÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ð·Ð°ÐŽÐ°ÐœÑ.  </Text>
+<Text id="79">ÐÑÐ±ÐµÑÐžÑÐµ ÑÐ»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ð² ÑÐ°Ð±Ð»ÐžÑÐµ, ÑÑÐŸÐ±Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŽÐ»Ñ ÑÑÐŸÐ³ÐŸ ÑÐ»ÐµÐŒÐµÐœÑÐ° Ð² ÐŸÐ±Ð»Ð°ÑÑÐž "Ð¡ÑÑÐµÑÑÐ²ÑÑÑÐžÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŽÐ»Ñ ...", ÐœÐ°Ñ
+ÐŸÐŽÑÑÐµÐ¹ÑÑ Ð²ÐœÐžÐ·Ñ ÑÐ°Ð±Ð»ÐžÑÑ. ÐÐµÑÐµÐ²ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ ÐŒÐŸÐ¶ÐµÑ ÑÐ°ÑÑÐžÑÑÑÑÑÑ Ðž ÑÐ°Ð·ÑÑÑÐ°ÑÑÑÑ. ÐÐ±ÑÑÐœÐŸ ÑÑÐŸ - ÑÐ¿ÐžÑÐŸÐº, ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð²ÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ, Ð²Ð²ÐµÐŽÐµÐœÐœÑÐµ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ ÐŽÐ»Ñ ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÐŸÐ³ÐŸ ÑÐ»ÐµÐŒÐµÐœÑÐ°. Ð©ÐµÐ»ÑÐŸÐº ÐœÐ° Ð²Ñ
+ÐŸÐŽÐµ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž ÑÐ°Ð·ÐŒÐµÑÐ°ÐµÑ ÐµÐ³ÐŸ Ð² Ð¿ÐŸÐ»Ðµ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹. Ð¡ ÐŽÑÑÐ³ÐŸÐ¹ ÑÑÐŸÑÐŸÐœÑ,Ð¿ÑÐž ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°ÐœÐœÐŸÐŒ Ð·ÐœÐ°ÑÐµÐœÐžÐž Ð² ÑÐµÐºÑÑÐŸÐ²ÐŸÐŒ Ð¿ÐŸÐ»Ðµ Ð²ÑÐ±ÐŸÑÐºÐž ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² ÐÐµÑÐµÐ²Ð° Ð·ÐœÐ°ÑÐµÐœÐžÐ¹, ÑÐžÑÑÐµÐŒÐ° ÐœÐ°ÑÐžÐœÐ°ÐµÑ ÑÐ°Ð±ÐŸÑÑ Ñ ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÐÑ Ð²Ð²ÐµÐ»Ðž. ÐÐ°Ð¶Ð°ÑÐžÐµ [Tab] Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž Ð·Ð°Ð²ÐµÑÑÐ°ÐµÑ Ð¿ÐµÑÐ°ÑÐ°ÐœÐžÐµ ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÐŸÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÑ.</Text>
+<Text id="80">ÐÐœÐ°ÑÐµÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐŸÑÐ³Ð°ÐœÐžÐ·ÐŸÐ²Ð°ÐœÑ Ð² ÐžÐµÑÐ°ÑÑ
+ÐžÑ. Ð­ÑÐŸ Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐŸ Ð² ÐÐµÑÐµÐ²Ðµ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ Ð¿Ð°Ð¿ÐºÐž ÐŽÐ»Ñ Ð²ÐœÑÑÑÐµÐœÐœÐžÑ
+ ÑÑÐŸÐ²ÐœÐµÐ¹. ÐÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐžÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð²Ð²ÐµÐŽÐµÐœÑ,ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ Ð·ÐœÐ°Ðº "|" ÐŽÐ»Ñ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ ÑÑÐŸÐ²ÐœÐµÐ¹. ÐÐ°Ð¿ÑÐžÐŒÐµÑ,"Cards|Red|Diamonds|Seven" ÐŒÐŸÐ³ Ð±Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ Ð² ÐžÐµÑÐ°ÑÑ
+ÐžÐž, Ð¿ÑÐžÐŒÐµÑÐŸÐŒ ÐºÐŸÑÐŸÑÐŸÐ¹ ÑÐ²Ð»ÑÐµÑÑÑ Ð¿Ð°ÐºÐµÑ ÐžÐ³ÑÑ Ð² ÐºÐ°ÑÑÑ.Ð­ÑÐŸ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð³ÑÑÐ¿Ð¿ÐžÑÐŸÐ²Ð°ÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÑ Ð²ÐŒÐµÑÑÐµ. ÐÑÑÐ¿Ð¿Ñ ÐŒÐŸÐ³ÑÑ ÑÐ°ÐºÐ¶Ðµ ÐœÐ°Ð·ÐœÐ°ÑÐ°ÑÑÑÑ ÐºÐ°Ðº ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ðº ÑÐ°Ð¹Ð»Ð°ÐŒ.  </Text>
+<Text id="81">Greenstone Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž ÐžÐ·Ð²Ð»ÐµÐºÐ°ÐµÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐžÐ· ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ð² ÐœÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÑÐ»ÐµÐŒÐµÐœÑÑ ÐºÐŸÑÐŸÑÐŸÐ³ÐŸ ÐžÐŒÐµÑÑ Ð¿ÑÐµÑÐžÐºÑ "ex.". Ð­ÑÐŸ ÐœÐµ ÐžÐŒÐµÐµÑ ÐœÐžÐºÐ°ÐºÐŸÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŽÐµÑÐµÐ²Ð° Ðž ÐœÐµ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐŸ.  </Text>
+</Section>
+<Section name="selectingmetadatasets">
+<Title>
+<Text id="82">ÐÑÐ±ÐŸÑ ÐœÐ°Ð±ÐŸÑÐŸÐ² ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</Text>
+</Title>
+<Text id="83">Ð£ÑÑÐ°ÐœÐŸÐ²ÐºÐ° ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐžÐ·Ð²ÐµÑÑÐœÐ° ÐºÐ°Ðº "ÐœÐ°Ð±ÐŸÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+". ÐÑÐžÐŒÐµÑÐŸÐŒ ÑÐ²Ð»ÑÐµÑÑÑ ÐœÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Dublin Core. ÐÐŸÐ³ÐŽÐ° ÐÑ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑÐµ ÐºÐŸÐŒÐ¿Ð»ÐµÐºÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ðº ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐŸ ÐµÐ³ÐŸ ÑÐ»ÐµÐŒÐµÐœÑÑ ÑÑÐ°ÐœÐŸÐ²ÑÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž ÐŽÐ»Ñ Ð²ÑÐ±ÐŸÑÐ°. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÐŒÐµÑÑ Ð±ÐŸÐ»ÑÑÐµ,ÑÐµÐŒ ÐŸÐŽÐžÐœ ÐœÐ°Ð±ÐŸÑ. ÐÐ»Ñ Ð¿ÑÐµÐŽÐŸÑÐ²ÑÐ°ÑÐµÐœÐžÑ ÑÑÐŸÐ»ÐºÐœÐŸÐ²ÐµÐœÐžÑ ÐŸÐŽÐžÐœÐ°ÐºÐŸÐ²ÑÑ
+ ÐžÐŒÑÐœ Ðº ÐœÐ°Ð·Ð²Ð°ÐœÐžÑ ÑÐ»ÐµÐŒÐµÐœÑÐ° Ð¿ÑÐžÑÐŸÐµÐŽÐžÐœÑÐµÑÑÑ ÐºÐŸÑÐŸÑÐºÐžÐ¹ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑ,ÐºÐŸÑÐŸÑÑÐ¹ Ð²ÑÐŽÐµÐ»ÑÐµÑ ÐœÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÑÐ»ÐµÐŒÐµÐœÑ Dublin Core "Creator" ÑÑÐ°ÐœÐµÑ "dc.Creator".ÐÐ°Ð±ÐŸÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ñ
+ÑÐ°ÐœÑÑÑÑ Ð² ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° Ðž ÐžÐŒÐµÑÑ ÑÑÑÑÐžÐºÑ ".mds".</Text>
+<Text id="84">Ð§ÑÐŸÐ±Ñ ÐºÐŸÐœÑÑÐŸÐ»ÐžÑÐŸÐ²Ð°ÑÑ ÐœÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÑ
+ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð²ÑÐ±ÐµÑÐžÑÐµ "ÐÐ°Ð±ÐŸÑ ÐÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+" Ð² Ð¿ÑÐŸÑÐŒÐŸÑÑÐµ "ÐÐžÐ·Ð°Ð¹Ðœ".</Text>
+</Section>
+<Section name="appendingmetadata">
+<Title>
+<Text id="85">ÐÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</Text>
+</Title>
+<Text id="86">Ð¢ÐµÐ¿ÐµÑÑ ÐŒÑ ÐŽÐŸÐ±Ð°Ð²ÐžÐŒ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ - Ðž ÑÐ°ÐŒ ÑÐ»ÐµÐŒÐµÐœÑ,Ðž ÐµÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÑ - Ðº ÑÐ°Ð¹Ð»Ñ. Ð¡ÐœÐ°ÑÐ°Ð»Ð° Ð²ÑÐ±ÐµÑÐµÐŒ ÑÐ°Ð¹Ð» ÐžÐ· ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ³ÐŸ ÐŽÐµÑÐµÐ²Ð° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.Ð¢Ð°ÐºÐŸÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ Ð²ÑÐ·ÑÐ²Ð°ÐµÑ Ð¿ÐŸÑÐ²Ð»ÐµÐœÐžÐµ Ð»ÑÐ±ÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+,Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ ÑÐ²ÑÐ·Ð°ÐœÐœÑÑ
+ Ñ ÑÑÐžÐŒ ÑÐ°Ð¹Ð»ÐŸÐŒ,Ð² ÑÐ°Ð±Ð»ÐžÑÐµ ÑÐ¿ÑÐ°Ð²Ð°. </Text>
+<Text id="87">ÐÐ°ÑÐµÐŒ Ð²ÑÐ±ÐµÑÐµÐŒ ÑÐ»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+,ÐºÐŸÑÐŸÑÑÐ¹ Ñ
+ÐŸÑÐžÐŒ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ,Ð¿ÑÑÐµÐŒ ÑÐµÐ»ÑÐºÐ° ÑÑÐŽÐŸÐŒ Ñ ÐœÐžÐŒ Ð² ÑÐ°Ð±Ð»ÐžÑÐµ. </Text>
+<Text id="88">ÐÐ¿ÐžÑÐžÑÐµ ÑÑÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ Ð² Ð¿ÐŸÐ»Ðµ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ Ð·ÐœÐ°Ðº "|", ÑÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÑÑÑÑÐºÑÑÑÑ, ÐºÐ°Ðº ÐŸÐ¿ÐžÑÐ°ÐœÐŸ Ð² ÑÐµÐºÑÐžÐž <Reference target="theenrichview"/>. ÐÐ°Ð¶Ð°Ð² ÐºÐ»Ð°Ð²ÐžÑÐž [ÐÐ²ÐµÑÑ
+] ÐžÐ»Ðž [ÐÐœÐžÐ·], ÐÑ ÑÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐ±ÑÐ°ÑÑ ÑÑÐµÐ±ÑÐµÐŒÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ. ÐÐ°Ð¶Ð°Ð² ÐºÐ»Ð°Ð²ÐžÑÑ [Enter], ÐÑ ÑÐŒÐŸÐ¶ÐµÑÐµ ÑÐŸÑ
+ÑÐ°ÐœÐžÑÑ Ð²ÑÐ±ÑÐ°ÐœÐœÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ðž ÑÐŸÐ·ÐŽÐ°ÑÑ ÐœÐŸÐ²ÐŸÐµ ÐœÐµÐ·Ð°Ð¿ÐŸÐ»ÐœÐµÐœÐœÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐŽÐ»Ñ ÑÐ»ÐµÐŒÐµÐœÑÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, Ð¿ÐŸÐ·Ð²ÐŸÐ»ÐžÐ² ÐÐ°ÐŒ ÐŸÐ¿ÑÐµÐŽÐžÐ»ÐžÑÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ ÐŽÐ»Ñ ÐŸÐŽÐœÐŸÐ³ÐŸ ÑÐ»ÐµÐŒÐµÐœÑÐ°.</Text>
+<Text id="89">ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐ°ÐºÐ¶Ðµ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ðº Ð¿Ð°Ð¿ÐºÐµ ÐžÐ»Ðž ÑÑÐ°Ð·Ñ Ðº ÐœÐµÐºÐŸÑÐŸÑÐŸÐŒÑ ÐŒÐœÐŸÐ¶ÐµÑÑÐ²Ñ ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ². Ð­ÑÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑÑÑ ÐºÐŸ Ð²ÑÐµÐŒ ÑÐ°Ð¹Ð»Ð°ÐŒ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ Ð¿Ð°Ð¿ÐºÐž ÐžÐ»Ðž Ðº ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÑÐŒ Ðž Ðº Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐœÑÐŒ Ð¿Ð°Ð¿ÐºÐ°ÐŒ. ÐÐŒÐµÐ¹ÑÐµ Ð² Ð²ÐžÐŽÑ,ÑÑÐŸ ÐµÑÐ»Ðž ÐÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÐ»Ðž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ðº Ð¿Ð°Ð¿ÐºÐµ, ÑÐŸ Ð»ÑÐ±ÑÐµ ÐœÐŸÐ²ÑÐµ ÑÐ°Ð¹Ð»Ñ Ð² ÐœÐµÐ¹ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž ÑÐœÐ°ÑÐ»ÐµÐŽÑÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐžÐ· ÑÑÐŸÐ¹ Ð¿Ð°Ð¿ÐºÐž.  </Text>
+</Section>
+<Section name="addingpreviouslydefinedmetadata">
+<Title>
+<Text id="90">ÐÐŸÐ±Ð°Ð²Ð»ÐœÐžÐµ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</Text>
+</Title>
+<Text id="91">Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐŽÐµÑÐ¶Ð°Ñ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ, ÑÐœÐ°ÑÐ°Ð»Ð° Ð²ÑÐ±ÐµÑÐžÑÐµ ÑÐ°Ð¹Ð», Ð·Ð°ÑÐµÐŒ ÑÑÐµÐ±ÑÐµÐŒÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐžÐ· ÐŽÐµÑÐµÐ²Ð° Ð·ÐœÐ°ÑÐµÐœÐžÐ¹, ÑÐ°ÑÑÐžÑÑÑ Ð¿Ð°Ð¿ÐºÐž ÐžÐµÑÐ°ÑÑ
+ÐžÐž Ð¿ÐŸ ÐŒÐµÑÐµ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÑÑÐž. ÐÑÐ±ÑÐ°ÐœÐœÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ Ð² Ð¿ÐŸÐ»Ðµ ÑÐµÐºÑÑÐ° (Ð°Ð»ÑÑÐµÑÐœÐ°ÑÐžÐ²ÐœÐŸ ÐŒÐŸÐ¶ÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð°Ð²ÑÐŸÐ²ÑÐ±ÐŸÑ Ð² ÐŽÐµÑÐµÐ²Ðµ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ Ðž ÑÑÐµÐŽÑÑÐ² Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐŸÐ³ÐŸ Ð·Ð°Ð²ÐµÑÑÐµÐœÐžÑ). </Text>
+<Text id="92">ÐÑÐŸÑÐµÑÑ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ñ ÑÐ¶Ðµ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐŒÐž Ð·ÐœÐ°ÑÐµÐœÐžÑÐŒÐž Ðº Ð¿Ð°Ð¿ÐºÐ°ÐŒ ÐžÐ»Ðž ÐŒÐœÐŸÐ¶ÐµÑÑÐ²Ñ ÑÐ°Ð¹Ð»ÐŸÐ² ÑÐ°ÐºÐŸÐ¹ Ð¶Ðµ.</Text>
+</Section>
+<Section name="updatingmetadata">
+<Title>
+<Text id="93">ÐÐ·ÐŒÐµÐœÐžÑÑ ÐžÐ»Ðž ÑÐŽÐ°Ð»ÐžÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ</Text>
+</Title>
+<Text id="94">Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐžÐ»Ðž ÑÐŽÐ°Ð»ÐžÑÑ ÑÐ°ÑÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÑÐœÐ°ÑÐ°Ð»Ð° Ð²ÑÐ±ÐµÑÐžÑÐµ Ð¿ÐŸÐŽÑ
+ÐŸÐŽÑÑÐžÐ¹ ÑÐ°Ð¹Ð», Ð° Ð¿ÐŸÑÐŸÐŒ ÑÐ»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ð² ÑÐ°Ð»Ð±ÐžÑÑ. Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÑÐ»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÑÐŽÐ°Ð»ÐžÑÐµ ÑÐµÐºÑÑ ÐµÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÑ.</Text>
+<Text id="95">ÐÑÐŸÑÐµÑÑ ÐŸÐ±ÐœÐŸÐ²Ð»ÐµÐœÐžÑ ÐŽÐ°ÐœÐœÑÑ
+ Ð¿Ð°Ð¿ÐºÐž Ñ Ð¿ÐŸÐŽÐ¿Ð°Ð¿ÐºÐ°ÐŒÐž ÐžÐ»Ðž ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² ÑÐŸÑ Ð¶Ðµ ÑÐ°ÐŒÑÐ¹, ÐœÐŸ Ð²Ñ ÑÐŒÐŸÐ¶ÐµÑÐµ ÐŸÐ±ÐœÐŸÐ²ÐžÑÑ ÑÐŸÐ»ÑÐºÐŸ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÐµ, ÐŸÐ±ÑÐžÐµ ÐŽÐ»Ñ Ð²ÑÐµÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ²/Ð¿Ð°Ð¿ÐŸÐº.</Text>
+<Text id="96">ÐÐµÑÐµÐ²ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð²ÑÐµ ÑÐµÐºÑÑÐžÐµ Ð¿ÑÐžÐ·ÐœÐ°ÑÐµÐœÐœÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ, Ð° ÑÐ°ÐºÐ¶Ðµ Ð²ÑÐµ Ð¿ÑÐµÐŽÑÐŽÑÑÐžÐµ ÐžÐ· ÑÐµÐºÑÑÐµÐ³ÐŸ ÑÐµÐ°ÐœÑÐ°, ÑÐ°Ðº ÑÑÐŸ ÐžÐ·ÐŒÐµÐœÐµÐœÐœÑÐµ ÐžÐ»Ðž ÑÐŽÐ°Ð»ÐµÐœÐœÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŸÑÑÐ°ÑÑÑÑ Ð² ÐŽÐµÑÐµÐ²Ðµ. ÐÐ°ÐºÑÑÐ² Ðž Ð²ÐœÐŸÐ²Ñ ÐŸÑÐºÑÑÐ² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐÑ ÑÐŽÐ°Ð»ÐžÑÐµ Ð²ÑÐµ ÑÐ°ÐœÐµÐµ Ð¿ÑÐžÐ·ÐœÐ°ÑÐµÐœÐœÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ. </Text>
+</Section>
+<Section name="reviewingmetadata">
+<Title>
+<Text id="97">ÐÑÐŸÑÐŒÐŸÑÑ Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</Text>
+</Title>
+<Text id="98">ÐÐœÐŸÐ³ÐŽÐ° ÐÐ°ÐŒ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ,Ð·Ð°ÐŽÐ°ÐœÐœÑÐµ ÐŽÐ»Ñ ÐŒÐœÐŸÐ³ÐžÑ
+ ÐžÐ»Ðž Ð²ÑÐµÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² ÑÑÐ°Ð·Ñ - ÐœÐ°Ð¿ÑÐžÐŒÐµÑ,ÑÑÐŸÐ±Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ,ÑÐºÐŸÐ»ÑÐºÐŸ ÑÐ°Ð¹Ð»ÐŸÐ² ÐŸÑÑÐ°ÑÑÑÑ ÐŽÐ»Ñ Ð²ÐŸÐ·ÐŽÐµÐ¹ÑÑÐ²ÐžÑ ÐžÐ»Ðž Ð¿ÐŸÐ»ÑÑÐžÑÑ ÐœÐµÐºÐŸÑÐŸÑÑÐµ ÐžÐŽÐµÐž ÐŸÑÐœÐŸÑÐžÑÐµÐ»ÑÐœÐŸ ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÐµÐœÐžÑ ÐŽÐ°ÐœÐœÑÑ
+.</Text>
+<Text id="99">ÐÑÐ±ÐµÑÐžÑÐµ ÑÐ°Ð¹Ð»Ñ, ÐºÐŸÑÐŸÑÑÐµ Ð²Ñ Ñ
+ÐŸÑÐžÑÐµ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ, Ð¿ÐŸÑÐŸÐŒ ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° Ð¿ÑÐ°Ð²ÑÑ ÐºÐœÐŸÐ¿ÐºÑ ÐŒÑÑÐž Ðž Ð²ÑÐ±ÐµÑÐžÑÐµ "ÐÐ°Ð·ÐœÐ°ÑÐµÐœÑÐµ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÐµ...". ÐÐŸÑÐ²Ð»ÑÐµÑÑÑ ÐŸÐºÐœÐŸ,ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒÐŸÐµ "ÐÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ", Ð·Ð°ÐœÑÑÐŸÐµ Ð±ÐŸÐ»ÑÑÐŸÐ¹ ÑÐ°Ð±Ð»ÐžÑÐµÐ¹,ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐµÐ¹ ÐŒÐœÐŸÐ³ÐŸ ÐºÐŸÐ»ÐŸÐœÐŸÐº.ÐÐµÑÐ²Ð°Ñ ÐºÐŸÐ»ÐŸÐœÐºÐž Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐžÐŒÐµÐœÐ° ÑÐ°Ð¹Ð»ÐŸÐ²;ÑÑÑÐŸÐºÐž Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÑÑ Ð²ÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+,Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ ÐŽÐ»Ñ ÑÑÐžÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ².  </Text>
+<Text id="100">Ð ÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÑÐ°Ð±Ð»ÐžÑÑ ÐŒÐŸÐ¶ÐµÑ Ð·Ð°ÐœÑÑÑ ÐœÐµÐºÐŸÑÐŸÑÐŸÐµ Ð²ÑÐµÐŒÑ,ÐµÑÐ»Ðž Ð²ÑÐ¿Ð°Ð»ÐŸ ÐŒÐœÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»ÐŸÐ².ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÑÐŸÐŽÐŸÐ»Ð¶Ð°ÑÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐŒ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐŸÐŒ Ð¿ÑÐž ÐŸÑÐºÑÑÑÐŸÐŒ ÐŸÐºÐœÐµ "ÐÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ". </Text>
+<Text id="101">ÐÐŸÐ³ÐŽÐ° ÐŸÐœÐ° ÑÑÐ°ÐœÐŸÐ²ÐžÑÑÑ ÑÐ»ÐžÑÐºÐŸÐŒ Ð±ÐŸÐ»ÑÑÐŸÐ¹,ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐŸÑÑÐžÐ»ÑÑÑÐŸÐ²Ð°ÑÑ ÑÐ°Ð±Ð»ÐžÑÑ "ÐÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ",Ð¿ÑÐžÐŒÐµÐœÑÑ ÑÐžÐ»ÑÑÑÑ Ðº ÐºÐŸÐ»ÐŸÐœÐºÐ°ÐŒ.ÐÐŸÑÐºÐŸÐ»ÑÐºÑ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÑ ÐœÐŸÐ²ÑÐµ ÑÐžÐ»ÑÑÑÑ, ÑÐŸÐ»ÑÐºÐŸ ÑÐµ ÑÑÑÐŸÐºÐž,ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑ ÐžÐŒ,ÐŸÑÑÐ°ÑÑÑÑ Ð²ÐžÐŽÐžÐŒÑÐŒÐž.Ð§ÑÐŸÐ±Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ,ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐžÐ»Ðž ÐŸÑÐžÑÑÐžÑÑ ÑÐžÐ»ÑÑÑ,ÑÐµÐ»ÐºÐœÐžÑÐµ Ð¿ÐŸ ÐžÐºÐŸÐœÐºÐµ "ÐÐŸÑÐŸÐœÐºÐ°" ÐœÐ°Ð²ÐµÑÑ
+Ñ ÐºÐŸÐ»ÐŸÐœÐºÐž. Ð£ Ð²Ð°Ñ Ð±ÑÐŽÐµÑ Ð·Ð°Ð¿ÑÐŸÑÐµÐœÐ° ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ ÑÐžÐ»ÑÑÑÐµ. ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÑÐžÐ»ÑÑÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ,ÐžÐ·ÐŒÐµÐœÑÐµÑÑÑ ÑÐ²ÐµÑ ÐºÐŸÐ»ÐŸÐœÐºÐž.</Text>
+<Text id="102">ÐÐ°Ð¿ÑÐŸÑ ÐžÐŒÐµÐµÑ ÑÐžÐŒÐ²ÐŸÐ»Ñ "ÐÑÐŸÑÑÐŸÐ¹" Ðž "ÐÑÐŸÐŽÐ²ÐžÐœÑÑÑÐ¹".ÐÑÐŸÑÑÐ°Ñ Ð²ÐµÑÑÐžÑ ÑÐžÐ»ÑÑÑÑÐµÑ ÐºÐŸÐ»ÐŸÐœÐºÐž ÑÐ°Ðº,ÑÑÐŸ ÐŸÐœÐž Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÑÑ ÑÐŸÐ»ÑÐºÐŸ ÑÑÑÐŸÐºÐž, ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐŽÐµÑÐ¶Ð°Ñ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ("*" ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÐµÑ Ð²ÑÐµÐŒ Ð·ÐœÐ°ÑÐµÐœÐžÑÐŒ).ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐ±ÑÐ°ÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐžÐ· ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐ³ÐŸ ÑÐ¿ÐžÑÐºÐ°.ÐÑÐŸÐŽÐ²ÐžÐœÑÑÐ°Ñ Ð²ÐµÑÑÐžÑ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð²ÑÐ¿ÐŸÐ»ÐœÑÑÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ:ÐÐŸÐ»Ð¶ÐµÐœ ÐœÐ°ÑÐ°ÑÑÑÑ Ñ,ÐÐµ ÑÐŸÐŽÐµÑÐ¶ÐžÑ,Ð Ð°Ð»ÑÐ°Ð²ÐžÑÐœÐŸÐŒ Ð¿ÐŸÑÑÐŽÐºÐµ,ÐÐµÐœÑÑÐµ ÑÐµÐŒ, Ð­ÐºÐ²ÐžÐ²Ð°Ð»ÐµÐœÑÐµÐœ. ÐÐœÐ°ÑÐµÐœÐžÐµ, ÐºÐŸÑÐŸÑÐŸÐµ Ð±ÑÐŽÐµÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐŸÐ²Ð°ÑÑ, ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐŸ ÑÐ°Ðº,ÑÑÐŸÐ±Ñ Ð±ÑÑÑ Ð»ÑÐ±ÐŸÐ¹ ÑÑÑÐŸÐºÐŸÐ¹,Ð²ÐºÐ»ÑÑÐ°Ñ "*". ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐ±ÑÐ°ÑÑ,ÐŽÐŸÐ»Ð¶ÐœÐŸ Ð»Ðž ÑÑÐŸ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐµ Ð±ÑÑÑ ÐœÐµ ÑÑÐ²ÑÑÐ²ÐžÑÐµÐ»ÑÐœÑÐŒ ÑÐ»ÑÑÐ°ÐµÐŒ. ÐÐ°ÐºÐŸÐœÐµÑ,ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ Ð²ÑÐŸÑÐŸÐµ ÑÑÐ»ÐŸÐ²ÐžÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÑ,ÐºÐŸÑÐŸÑÐŸÐµ ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐŽÐ»Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ ÑÐ°ÐœÐ³Ð° Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ (Ð²ÑÐ±ÐžÑÐ°Ñ Ð Ð±ÐŸÐ»ÑÑÐŸÐµ) ÐžÐ»Ðž Ð°Ð»ÑÑÐµÑÐœÐ°ÑÐžÐ²ÐœÑÑ
+ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ (Ð²ÑÐ±ÐžÑÐ°Ñ ÐÐÐ).ÐÐžÐ¶Ðµ ÑÑÐŸÐ¹ ÐŸÐ±Ð»Ð°ÑÑÐž ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð¿ÐŸÐ»Ðµ, ÐºÐŸÑÐŸÑÐŸÐµ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐÐ°ÐŒ ÐžÐ·ÐŒÐµÐœÑÑÑ Ð¿ÐŸÑÑÐŽÐŸÐº ÑÐŸÑÑÐžÑÐŸÐ²ÐºÐž (Ð²ÐŸÐ·ÑÐ°ÑÑÐ°ÑÑÐžÐ¹ ÐžÐ»Ðž Ð¿ÐŸÐœÐžÐ¶Ð°ÑÐžÐ¹ÑÑ).ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐÑ Ð·Ð°ÐºÐŸÐœÑÐžÑÐµ,ÐœÐ°Ð¶ÐŒÐžÑÐµ "Ð£ÑÑÐ°ÐœÐŸÐ²ÐºÐ° ÑÐžÐ»ÑÑÑÐ°",ÑÑÐŸÐ±Ñ Ð¿ÑÐžÐŒÐµÐœÐžÑÑ ÐœÐŸÐ²ÑÐ¹ ÑÐžÐ»ÑÑÑ Ðº ÐºÐŸÐ»ÐŸÐœÐºÐµ.ÐÐ°Ð¶ÐŒÐžÑÐµ "ÐÑÐžÑÑÐžÑÑ ÑÐžÐ»ÑÑÑ",ÑÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÑÐµÐºÑÑÐžÐ¹ ÑÐžÐ»ÑÑÑ.ÐÐ±ÑÐ°ÑÐžÑÐµ Ð²ÐœÐžÐŒÐ°ÐœÐžÐµ ÐœÐ° ÑÐŸ,ÑÑÐŸ ÐŽÐµÑÐ°Ð»Ðž ÑÐžÐ»ÑÑÑÐ° ÑÐŸÑ
+ÑÐ°ÐœÑÑÑÑÑ, ÐŽÐ°Ð¶Ðµ ÐºÐŸÐ³ÐŽÐ° ÑÐžÐ»ÑÑÑ ÐŸÑÐžÑÐµÐœ.</Text>
+<Text id="103">ÐÐ°Ð¿ÑÐžÐŒÐµÑ,ÑÑÐŸÐ±Ñ ÐŸÑÑÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÑÐ°Ð±Ð»ÐžÑÑ "ÐÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ",Ð²ÑÐ±ÐµÑÐžÑÐµ ÐºÐŸÐ»ÐŸÐœÐºÑ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÑ ÑÐžÐ»ÑÑÑÐ° Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ (Ð¿ÑÐŸÑÑÐŸÐ¹ ÑÐžÐ»ÑÑÑ ÐœÐ° "*") Ðž Ð²ÐŸÐ·ÑÐ°ÑÑÐ°ÑÑÐžÐ¹ ÐžÐ»Ðž Ð¿ÐŸÐœÐžÐ¶Ð°ÑÑÐžÐ¹ÑÑ Ð¿ÐŸÑÑÐŽÐŸÐº.   </Text>
+</Section>
+<Section name="importingpreviouslyassignedmetadata">
+<Title>
+<Text id="104">ÐÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</Text>
+</Title>
+<Text id="105">Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÑÐ°ÑÑÐºÐ°Ð·Ð°ÐœÐŸ, ÐºÐ°Ðº ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÐµ ÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐœÑÐµ ÑÐ°ÐœÑÑÐµ. Ð ÐµÑÑ ÐžÐŽÐµÑ ÐŸ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+, ÐºÐŸÑÐŸÑÑÐµ Ð±ÑÐ»Ðž ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÑ Ðº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÐ°ÐœÑÑÐµ.</Text>
+<Text id="106">ÐÑÐ»Ðž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ð² ÑÐŸÑÐŒÐµ,ÑÐ°ÑÐ¿ÐŸÐ·ÐœÐ°Ð²Ð°ÐµÐŒÐŸÐ¹ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐŒ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐŸÐŒ,Ð±ÑÐ»Ðž Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°ÐŽÐ°ÐœÑ ÑÐ°Ð¹Ð»Ñ - ÐœÐ°Ð¿ÑÐžÐŒÐµÑ,ÐºÐŸÐ³ÐŽÐ° ÐÑ Ð²ÑÐ±ÐžÑÐ°ÐµÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÐžÐ· ÑÑÑÐµÑÑÐ²ÑÑÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Greenstone - ÐŸÐœÐž ÐžÐŒÐ¿ÐŸÑÑÐžÑÑÑÑÑÑ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž,ÐºÐŸÐ³ÐŽÐ° ÐÑ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑÐµ ÑÐ°Ð¹Ð».Ð§ÑÐŸÐ±Ñ ÑÐŽÐµÐ»Ð°ÑÑ ÑÑÐŸ, ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœÑ Ð² ÑÑÑÐ°ÐœÐŸÐ²ÐºÐ°Ñ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+,ÐŽÐŸÑÑÑÐ¿ÐœÑÑ
+ Ð² ÑÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Text id="107">ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð·Ð°Ð¿ÑÐ°ÑÐžÐ²Ð°ÐµÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ.ÐÐ°Ð¿ÑÐŸÑ ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÐºÑÐ°ÑÐºÐžÐµ ÐžÐœÑÑÑÑÐºÑÐžÐž Ðž Ð·Ð°ÑÐµÐŒ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐžÐŒÑ ÑÐ»ÐµÐŒÐµÐœÑÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+,ÐºÐŸÑÐŸÑÑÐµ ÐžÐŒÐ¿ÐŸÑÑÐžÑÑÑÑÑÑ,ÐºÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐŸÐœ Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ Ð² ÐžÑÑ
+ÐŸÐŽÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ.Ð­ÑÐŸ Ð¿ÐŸÐ»Ðµ ÐœÐµ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐŸ ÐžÐ»Ðž ÐžÐ·ÐŒÐµÐœÐµÐœÐŸ.ÐÐ°ÑÐµÐŒ ÐÑ Ð²ÑÐ±ÐžÑÐ°ÐµÑÐµ,ÐºÐ°ÐºÐžÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐœÐŸÐ²ÐŸÐ³ÐŸ ÑÐ»ÐµÐŒÐµÐœÑÐ° ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœÑ,Ð° Ð·Ð°ÑÐµÐŒ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐ¹ ÑÐ»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ð² ÑÑÐžÑ
+ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐ°Ñ
+.Ð¡ÐžÑÑÐµÐŒÐ° Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž Ð²ÑÐ±ÐžÑÐ°ÐµÑ ÑÐ°ÐŒÐŸÐµ Ð±Ð»ÐžÐ·ÐºÐŸÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐµ Ð² ÑÐµÑÐŒÐžÐœÐ°Ñ
+ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž Ðž ÑÐ»ÐµÐŒÐµÐœÑÐ° ÐŽÐ»Ñ ÐœÐŸÐ²ÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. </Text>
+<Text id="108">ÐÑÐŸÐ²ÐµÑÐžÐ² ÑÑÐž ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœÐžÑ,ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐ±ÑÐ°ÑÑ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ",ÑÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐœÐŸÐ²ÑÐ¹ ÑÐ»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ðº Ð²ÑÐ±ÑÐ°ÐœÐœÑÐŒ ÐœÐ°Ð±ÐŸÑÐ°ÐŒ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+.Ð­ÑÐŸ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸ ÑÐŸÐ»ÑÐºÐŸ ÑÐŸÐ³ÐŽÐ°,ÐºÐŸÐ³ÐŽÐ° ÐŸÑÑÑÑÑÑÐ²ÑÐµÑ ÑÐ»ÐµÐŒÐµÐœÑ Ñ ÑÐµÐŒ Ð¶Ðµ ÑÐ°ÐŒÑÐŒ ÐžÐŒÐµÐœÐµÐŒ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ Ð²ÑÐ±ÑÐ°ÐœÐœÑÑ
+ ÑÑÑÐ°ÐœÐŸÐ²ÐŸÐº; "ÐÐ±ÑÐµÐŽÐžÐœÐžÑÑ" ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ Ð¿ÑÐžÑÐŸÐµÐŽÐžÐœÐµÐœÐžÐµ ÐœÐŸÐ²ÐŸÐ³ÐŸ ÑÐ»ÐµÐŒÐµÐœÑÐ° Ðº ÑÐ¶Ðµ ÑÐ°ÐœÐµÐµ Ð²ÑÐ±ÑÐ°ÐœÐœÐŸÐŒÑ  Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐŒ;ÐœÐ°ÐºÐŸÐœÐµÑ, "ÐÐµ ÑÑÐžÑÑÐ²Ð°ÑÑ", ÑÑÐŸÐ±Ñ ÐœÐµ ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÐœÐžÐºÐ°ÐºÐžÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ñ ÑÑÐžÐŒ ÐžÐŒÐµÐœÐµÐŒ ÑÐ»ÐµÐŒÐµÐœÑÐ°. ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÐ»Ðž,ÐºÐ°Ðº ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÐœÐµÐºÐŸÑÐŸÑÑÑ ÑÐ°ÑÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, Ð·Ð°Ð¿ÐžÑÐ°ÐœÐœÐ°Ñ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÑÐŸÑ
+ÑÐ°ÐœÑÐµÑÑÑ ÐœÐ° Ð²ÑÐµÐŒÑ ÑÑÑÐµÑÑÐ²ÐŸÐ²Ð°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Text id="109">ÐÐ»Ñ ÐŽÐµÑÐ°Ð»ÐµÐ¹ ÐŸÑÐœÐŸÑÐžÑÐµÐ»ÑÐœÐŸ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ð² metadata.xml, ÐºÐŸÑÐŸÑÑÐ¹ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð² Greenstone ÐŽÐ»Ñ Ñ
+ÑÐ°ÐœÐµÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÑÐŒ.Ð³Ð»Ð°Ð²Ñ 2 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone.</Text>
+</Section>
+</Section>
+<Section name="designingacollection">
+<Title>
+<Text id="110">ÐÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<Text id="111">ÐÐŸÐ³ÐŽÐ° ÐÐ°ÑÐž ÑÐ°Ð¹Ð»Ñ ÑÐœÐ°Ð±Ð¶ÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒÐž,ÐŽÐ°Ð»ÐµÐµ ÐÑ ÑÐµÑÐ°ÐµÑÐµ,Ð² ÐºÐ°ÐºÐŸÐŒ Ð²ÐžÐŽÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Greenstone ÐŽÐŸÐ»Ð¶ÐœÐ° Ð±ÑÑÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐ° Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÐŒ.ÐÐ°ÐºÐŸÐ³ÐŸ Ð²ÐžÐŽÐ° ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŽÐŸÑÑÑÐ¿ÐœÐ° ÐŽÐ»Ñ Ð¿ÐŸÐžÑÐºÐ°? ÐÐ°ÐºÐžÐµ Ð¿ÑÑÐž Ð¿ÑÐµÐŽÑÑÐŒÐŸÑÑÐµÐœÑ ÐŽÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°? ÐÐ°ÐºÐžÐµ ÑÐ·ÑÐºÐž Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÑÑÑÑ? ÐÐŽÐµ ÑÐ°Ð·ÐŒÐµÑÑÐžÑÑ ÐºÐœÐŸÐ¿ÐºÐž ÐœÐ° ÑÑÑÐ°ÐœÐžÑÐµ? Ð­ÑÐž Ð²ÐµÑÐž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐœÐ°ÑÑÑÐŸÐµÐœÑ;Ð² ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑÑÑ,ÐºÐ°Ðº ÑÑÐŸ ÑÐŽÐµÐ»Ð°ÑÑ.</Text>
+<Section name="thedesignview">
+<Title>
+<Text id="112">ÐÐžÐŽ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°</Text>
+</Title>
+<Text id="113">Ð­ÑÐŸÑ ÑÐ°Ð·ÐŽÐµÐ» Ð²Ð²ÐŸÐŽÐžÑ ÐÐ°Ñ Ð² ÑÐ°ÑÑÐŒÐ°ÑÑÐžÐ²Ð°ÐµÐŒÑÐ¹ Ð¿ÑÐŸÐµÐºÑ Ðž ÐŸÐ±ÑÑÑÐœÑÐµÑ,ÐºÐ°Ðº Ð²ÑÐ±ÑÐ°ÑÑ ÐŒÐµÐ¶ÐŽÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐŒÐž Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑÐŒÐž Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ Ð°ÐºÑÐžÐ²ÐœÐŸÐ¹ ÑÐ°ÑÑÐž ÐŸÐºÐœÐ°.</Text>
+<Text id="114">ÐÑÐž Ð¿ÐŸÐŒÐŸÑÐž ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÑÑ Ð²ÐžÐŽÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÐµÐŒÐŸÐ¹ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ.ÐÐ°ÑÐžÐ°ÐœÑÑ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÑ ÐœÐ° ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ ÑÐ°Ð·ÐŽÐµÐ»Ñ, ÐºÐ°Ð¶ÐŽÑÐ¹ ÐžÐ· ÐºÐŸÑÐŸÑÑÑ
+ ÑÐ²ÑÐ·Ð°Ðœ ÑÐŸ ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐŸÐ¹ ÑÑÐ°ÐŽÐžÐµÐ¹ ÐœÐ°Ð²ÐžÐ³Ð°ÑÐžÐž ÐžÐ»Ðž Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž.</Text>
+<Text id="115">Ð¡Ð»ÐµÐ²Ð° ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ ÑÐ¿ÐžÑÐŸÐº ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐ¹,Ð° ÑÐ¿ÑÐ°Ð²Ð° - ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÑÐµÐºÑÑÐžÐŒ ÑÐ¿ÐžÑÐºÐŸÐŒ.Ð§ÑÐŸÐ±Ñ Ð¿ÐµÑÐµÐ¹ÑÐž ÐœÐ° Ð²ÑÐ±ÑÐ°ÐœÐœÐŸÐµ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ,ÑÐµÐ»ÐºÐœÐžÑÐµ ÐµÐ³ÐŸ ÐžÐŒÑ Ð² ÑÐ¿ÐžÑÐºÐµ. </Text>
+<Text id="116">Ð§ÑÐŸÐ±Ñ Ð¿ÐŸÐœÐžÐŒÐ°ÑÑ ÑÑÐ°ÐŽÐžÐž Ðž ÑÐµÑÐŒÐžÐœÑ,ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐµ Ð¿ÑÐž Ð¿ÑÐŸÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐœÐ°ÑÐ°Ð»Ð° Ð¿ÑÐŸÑÑÐžÑÐµ Ð³Ð»Ð°Ð²Ñ 1 Ðž 2 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone. </Text>
+</Section>
+<Section name="generalsettings">
+<Title>
+<Text id="117">ÐÐ±ÑÐµÐµ</Text>
+</Title>
+<Text id="118">Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ,ÐºÐ°Ðº Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ Ðž ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐŸÐ±ÑÐžÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž, ÐŸÑÐœÐŸÑÑÑÐžÐµÑÑ Ðº ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.Ð¡ÐœÐ°ÑÐ°Ð»Ð° Ð² "Ð Ð°Ð·ÐŽÐµÐ»Ð°Ñ
+ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°" ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐ±ÑÐžÐµ"</Text>
+<Text id="119">ÐÐŽÐµÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÑ,Ð¿ÑÐµÐŽÑÑÐŒÐŸÑÑÐµÐœÐœÑÐµ Ð¿ÑÐž ÑÐŸÐ·ÐŽÐ°ÐœÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž,ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐžÐ·ÐŒÐµÐœÐµÐœÑ.</Text>
+<Text id="120">Ð¡ÐœÐ°ÑÐ°Ð»Ð° ÐžÐŽÑÑ ÐºÐŸÐœÑÐ°ÐºÑÐœÑÐµ Ð°ÐŽÑÐµÑÐ° ÑÐ»ÐµÐºÑÑÐŸÐœÐœÐŸÐ¹ Ð¿ÐŸÑÑÑ ÑÐŸÐ·ÐŽÐ°ÑÐµÐ»Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÑÑÐµÐ³ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð»ÐžÑÐ°. Ð¡Ð»ÐµÐŽÑÑÑÐµÐµ Ð¿ÐŸÐ»Ðµ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐÐ°ÐŒ ÐžÐ·ÐŒÐµÐœÑÑÑ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð¡Ð»ÐµÐŽÑÑÐµÐµ ÑÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð¿Ð°Ð¿ÐºÑ, Ð² ÐºÐŸÑÐŸÑÐŸÐ¹ ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐœÐŸ ÐœÐµ Ð¿ÐŸÐŽÐ»ÐµÐ¶ÐžÑ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑÐŒ. Ð¡Ð»ÐµÐŽÑÑÑÐµÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ (Ð² ÑÐŸÑÐŒÐµ URL) ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ,ÑÑÐŸÐ±Ñ Ð¿ÐŸÐºÐ°Ð·Ð°ÑÑ ÐœÐ°Ð²ÐµÑÑ
+Ñ ÑÐ»ÐµÐ²Ð° ÐŸÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÑÑÐ°ÐœÐžÑÑ ÐŸ ÐœÐµÐ¹, Ðž ÑÐ»ÐµÐŽÑÑÑÐµÐµ - ÐžÐºÐŸÐœÐºÐ°, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐ°Ñ Ð² Greenstone ÑÑÑÐ°ÐœÐžÑÐ° ÐŽÐ»Ñ ÑÐ²ÑÐ·Ðž Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹. ÐÐŸÑÐ»Ðµ ÑÑÐŸÐ³ÐŸ, Ð²Ñ ÑÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐŽÐµÐ»ÐžÑÑ Ð¿ÑÐœÐºÑ Ð³Ð°Ð»ÐŸÑÐºÐŸÐ¹, ÑÐºÐ°Ð·Ð°Ð², ÐŽÐŸÑÑÑÐ¿ÐœÐ° Ð»Ðž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐŽÑÑÐ³ÐžÐŒ. ÐÐ°ÐºÐŸÐœÐµÑ, ÑÐ»ÐµÐŽÑÐµÑ ÐŸÐ±Ð»Ð°ÑÑÑ ÑÐµÐºÑÑÐ° "ÐÐ¿ÐžÑÐ°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž",Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐœÐ°Ñ ÑÐ°ÐœÐµÐµ Ð² <Reference target="creatingacollection"/>.</Text>
+</Section>
+<Section name="plugins">
+<Title>
+<Text id="121">ÐÐ»Ð°Ð³ÐžÐœÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°</Text>
+</Title>
+<Text id="122">Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ¿ÐžÑÐ°ÐœÐŸ,ÐºÐ°Ðº ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÑÑ Ð¿Ð»Ð°Ð³ÐžÐœÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° ÐŽÐ»Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹.Ð ÐœÑÐŒ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ,ÐºÐ°Ðº ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ,ÐºÐ°ÐºÐžÐµ Ð¿Ð»Ð°Ð³ÐžÐœÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ, ÐºÐ°ÐºÐžÐµ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ Ð¿ÐµÑÐµÐŽÐ°Ð²Ð°ÑÑ Ðº ÐœÐžÐŒ Ðž Ð² ÐºÐ°ÐºÐŸÐŒ Ð¿ÐŸÑÑÐŽÐºÐµ ÐŸÐœÐž Ð²Ñ
+ÐŸÐŽÑÑ. Ð©ÐµÐ»ÐºÐœÐžÑÐµ "ÐÐ»Ð°Ð³ÐžÐœÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²" Ð² Ð¿ÑÐœÐºÑÐµ "Ð Ð°Ð·ÐŽÐµÐ»Ñ Ð¿ÑÐŸÐµÐºÑÐ°".</Text>
+<Text id="123">Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÑÑ Ð¿Ð»Ð°Ð³ÐžÐœ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ,ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ "ÐÑÐ±ÐŸÑ Ð¿Ð»Ð°Ð³ÐžÐœÐ° ÐŽÐ»Ñ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÑ" Ð² ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐŒ ÑÐ¿ÐžÑÐºÐµ ÐŸÐºÐŸÐ»ÐŸ ÐŸÑÐœÐŸÐ²Ð°ÐœÐžÑ,Ðž Ð·Ð°ÑÐµÐŒ ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ Ð¿Ð»Ð°Ð³ÐžÐœ". ÐÐŸÑÐ²Ð»ÑÐµÑÑÑ ÐŸÐºÐœÐŸ Ñ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµÐŒ "ÐÐŸÐœÑÐžÐ³ÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ²";ÐŸÐœÐŸ ÐŸÐ¿ÐžÑÐ°ÐœÐŸ ÐœÐžÐ¶Ðµ. ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐÑ ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°Ð»Ðž ÐœÐŸÐ²ÑÐ¹ Ð¿Ð»Ð°Ð³ÐžÐœ, ÐŸÐœ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑÑÑ Ð² ÐºÐŸÐœÐµÑ ÑÐ¿ÐžÑÐºÐ° "Ð£ÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐœÑÐµ ÑÐµÐºÑÑÐžÐµ Ð¿Ð»Ð°Ð³ÐžÐœÑ". ÐÐ°ÐŒÐµÑÑÑÐµ, ÑÑÐŸ, ÐºÑÐŸÐŒÐµ UnknownPlug, ÐºÐ°Ð¶ÐŽÑÐ¹ Ð¿Ð»Ð°Ð³ÐžÐœ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ Ð²ÑÐ²ÐµÐŽÐµÐœ ÑÐŸÐ»ÑÐºÐŸ ÐŸÐŽÐžÐœ ÑÐ°Ð· Ð² ÑÐ¿ÐžÑÐºÐµ.</Text>
+<Text id="124">Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ Ð¿Ð»Ð°Ð³ÐžÐœ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ Ð² ÑÐ¿ÐžÑÐºÐµ Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ Ð¿Ð»Ð°Ð³ÐžÐœ".</Text>
+<Text id="125">ÐÐ»Ð°Ð³ÐžÐœÑ ÑÐŸÑÐŒÐžÑÑÑÑÑÑ Ð¿ÑÑÐµÐŒ Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÐµÐœÐžÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ². Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐžÑ
+, Ð²ÑÐ±ÐµÑÐžÑÐµ Ð¿Ð»Ð°Ð³ÐžÐœ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð€ÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð¿Ð»Ð°Ð³ÐžÐœÐŸÐ²"(ÐžÐ»Ðž ÐŽÐ²ÐŸÐ¹ÐœÑÐŒ ÑÐµÐ»ÑÐºÐŸÐŒ ÐœÐ° Ð¿Ð»Ð°Ð³ÐžÐœÐµ). ÐÐžÐ°Ð»ÐŸÐ³ "ÐÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐµ ÐÑÐ³ÑÐŒÐµÐœÑÑ" Ð²ÐŸÐ·ÐœÐžÐºÐ°ÐµÑ Ñ ÑÐ°Ð·Ð»ÐžÑÐœÑÐŒÐž ÐŸÐ¿ÑÐžÑÐŒÐž ÐŽÐ»Ñ ÑÐºÐ°Ð·Ð°ÐœÐžÑ Ð°ÑÐ³ÑÐŒÐµÐœÑÐŸÐ².</Text>
+<Text id="126">Ð¡ÑÑÐµÑÑÐ²ÑÑÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ Ð²ÐžÐŽÑ ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ. ÐÐµÐºÐŸÑÐŸÑÑÐµ ÑÐ²Ð»ÑÑÑÑÑ ÐœÐµÐ·Ð°Ð²ÐžÑÐžÐŒÑÐŒÐž ÐºÐœÐŸÐ¿ÐºÐ°ÐŒÐž Ðž ÑÐµÐ»ÑÐŸÐº ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÑÑ ÐŸÐ¿ÑÐžÑ Ðº Ð¿Ð»Ð°Ð³ÐžÐœÑ. ÐÑÑÐ³ÐžÐµ Ð²ÑÑÑÑÐ¿Ð°ÑÑ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÑÑÑÐŸÐºÐž ÑÐµÐºÑÑÐ° Ñ ÐœÐµÐ·Ð°Ð²ÐžÑÐžÐŒÐŸÐ¹ ÐºÐœÐŸÐ¿ÐºÐŸÐ¹ Ðž ÐŸÐ±Ð»Ð°ÑÑÑÑ ÑÐµÐºÑÑÐ°. Ð©ÐµÐ»ÐºÐœÐžÑÐµ ÐœÐ° Ð¿ÐŸÐ»Ðµ,ÑÑÐŸÐ±Ñ Ð²ÑÐ·Ð²Ð°ÑÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑ,Ð·Ð°ÑÐµÐŒ ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð¹ÑÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐ¹ ÑÐµÐºÑÑ (Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÐŸÐµ Ð²ÑÑÐ°Ð¶ÐµÐœÐžÐµ,Ð¿ÑÑÑ ÑÐ°Ð¹Ð»Ð° Ðž Ñ.ÐŽ.) Ð² Ð¿ÐŸÐ»Ðµ. ÐÑÑÐ³ÐžÐµ - ÑÑÐŸ ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐžÐµ ÐŒÐµÐœÑ,Ð² ÐºÐŸÑÐŸÑÑÑ
+ ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐ±ÐžÑÐ°ÑÑ ÐœÑÐ¶ÐœÐŸÐµ ÐžÐ· Ð·Ð°ÐŽÐ°ÐœÐœÐŸÐ³ÐŸ ÐœÐ°Ð±ÐŸÑÐ° Ð·ÐœÐ°ÑÐµÐœÐžÐ¹. Ð§ÑÐŸÐ±Ñ Ð¿ÐŸÐœÑÑÑ,ÑÑÐŸ ÐŽÐµÐ»Ð°ÐµÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑ, ÐŽÐ°Ð¹ÑÐµ ÐŒÑÑÐž ÐœÐ° ÐŒÐ³ÐœÐŸÐ²ÐµÐœÐžÐµ Ð¿ÑÐŸÐ¹ÑÐž Ð¿ÐŸ ÐµÐ³ÐŸ ÐœÐ°Ð·Ð²Ð°ÐœÐžÑ Ðž ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ Ð¿ÐŸÑÐ²ÐžÑÑÑ. </Text>
+<Text id="127">ÐÐŸÐ³ÐŽÐ° ÐÑ ÐžÐ·ÐŒÐµÐœÐžÐ»Ðž ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÑ,ÐœÐ°Ð¶ÐŒÐžÑÐµ "ÐÐ", ÑÑÐŸÐ±Ñ Ð¿ÑÐžÐœÑÑÑ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ðž Ð·Ð°ÐºÑÑÑÑ ÐŽÐžÐ°Ð»ÐŸÐ³,ÐžÐ»Ðž "ÐÑÐŒÐµÐœÐžÑÑ",ÑÑÐŸÐ±Ñ Ð·Ð°ÐºÑÑÑÑ ÐŽÐžÐ°Ð»ÐŸÐ³ Ð±ÐµÐ· ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ð»ÑÐ±ÑÑ
+ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ² Ð¿Ð»Ð°Ð³ÐžÐœÐ°. </Text>
+<Text id="128">ÐÐ»Ð°Ð³ÐžÐœÑ Ð² ÑÐ¿ÐžÑÐºÐµ ÑÐ°ÑÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÑ Ð² ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÐŸÐŒ Ð¿ÐŸÑÑÐŽÐºÐµ,ÑÐ°Ðº ÐºÐ°Ðº ÑÐ¿ÐŸÑÑÐŽÐŸÑÐµÐœÐžÐµ ÐžÐœÐŸÐ³ÐŽÐ° Ð²Ð°Ð¶ÐœÐŸ. ÐÐŸÑÑÐŽÐŸÐº ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÑÑ
+ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÑÑ
+ ÐŒÐŸÐŽÑÐ»ÐµÐ¹ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐžÐ·ÐŒÐµÐœÐµÐœ ÑÐŸÐ»ÑÐºÐŸ Ð² ÑÐµÐ¶ÐžÐŒÐ°Ñ
+ Ð¡Ð¿ÐµÑÐžÐ°Ð»ÐžÑÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÑ
+ Ð¡ÐžÑÑÐµÐŒ Ðž Ð­ÐºÑÐ¿ÐµÑÑ (ÑÐŒ. <Reference target="preferences"/>).</Text>
+</Section>
+<Section name="searchtypes">
+<Title>
+<Text id="129">ÐÐžÐŽÑ Ð¿ÐŸÐžÑÐºÐ°</Text>
+</Title>
+<Text id="130">Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ,ÐºÐ°Ðº ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐŸÑÐŸÐ±ÐµÐœÐœÐŸÑÑÐž ÐœÐŸÐ²ÐŸÐ³ÐŸ ÐŽÐžÐ·Ð°Ð¹ÐœÐ° Ð² Greenstone; Ð²ÐžÐŽÑ Ð¿ÐŸÐžÑÐºÐ°,ÐºÐŸÑÐŸÑÑÐµ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑ Ð¿ÑÐŸÐ²ÐŸÐŽÐžÑÑ Ð¿ÐŸÐžÑÐº Ð¿ÐŸ Ð¿ÐŸÐ»ÑÐŒ. ÐÐžÐŽÑ Ð¿ÐŸÐžÑÐºÐ° ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑ, ÐºÐ°ÐºÐŸÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÐŸÐžÑÐºÐ° ÐŽÐŸÐ»Ð¶ÐµÐœ Ð±ÑÑÑ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœ: ÑÐŸÑÐŒÐ° ÐŽÐ»Ñ Ð¿ÐŸÐ»ÐµÐ¹ Ð¿ÐŸÐžÑÐºÐ° Ðž/ÐžÐ»Ðž Ð¿ÑÐŸÑÑÐŸÐ¹ ÐŽÐ»Ñ ÑÐµÐ³ÑÐ»ÑÑÐœÐŸÐ³ÐŸ Ð¿ÐŸÐžÑÐºÐ°. Ð©ÐµÐ»ÐºÐœÐžÑÐµ Ð²ÐžÐŽÑ Ð¿ÐŸÐžÑÐºÐ° Ð² "Ð Ð°Ð·ÐŽÐµÐ»Ð°Ñ
+ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°".</Text>
+<Text id="131">ÐÐŸÐ³ÐŽÐ° ÐÑ ÐœÐ°ÑÐžÐœÐ°ÐµÑÐµ Ð¿ÑÐŸÑÐŒÐŸÑÑ Ð²ÐžÐŽÐŸÐ² Ð¿ÐŸÐžÑÐºÐ°, ÑÐœÐ°ÑÐ°Ð»Ð° Ð²ÑÐ±ÐµÑÐžÑÐµ "ÐÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑ ÑÐ°ÑÑÐžÑÐµÐœÐœÐŸÐ³ÐŸ Ð¿ÐŸÐžÑÐºÐ°",ÐºÐŸÑÐŸÑÑÐ¹ Ð°ÐºÑÐžÐ²ÐžÐ·ÐžÑÑÐµÑ ÐŽÑÑÐ³ÐžÐµ ÑÑÐµÐŽÑÑÐ²Ð° ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ. ÐÑÐž ÑÑÐŸÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð±ÑÐŽÐµÑ ÐžÐ·ÐŒÐµÐœÐµÐœÐ°: ÐžÐœÐŽÐµÐºÑÐžÑÑÑÑÐžÐ¹ ÐŒÐµÑ
+Ð°ÐœÐžÐ·ÐŒ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÐžÑ Ð¿ÑÐŸÐ²ÐµÑÑÐž Ð¿ÐŸÐžÑÐº Ñ ÐžÑÐ¿ÐŸÐ»ÐžÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ Ð¿ÐŸÐžÑÐºÐŸÐ²ÑÑ
+ Ð¿ÐŸÐ»ÐµÐ¹. Ð¡Ð¿ÐµÑÐžÑÐžÐºÐ°ÑÐžÑ ÐžÐœÐŽÐµÐºÑÐ° Ð² ÑÑÐŸÐŒ ÑÐµÐ¶ÐžÐŒÐµ ÐœÐµÐŒÐœÐŸÐ³ÐŸ ÐžÐ·ÐŒÐµÐœÐµÐœÐ°. (ÐÑÐž Ð¿ÐµÑÐµÐºÐ»ÑÑÐµÐœÐžÐž ÐŒÐµÐ¶ÐŽÑ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÐŒ Ðž Ð¿ÑÐŸÐŽÐ²ÐžÐœÑÑÑÐŒ Ð¿ÑÐžÑÐºÐŸÐŒ ÐÐÐ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑ ÐºÐŸÐœÐ²ÐµÑÑÐžÐ²ÐŸÐ²Ð°ÐœÐžÐµ, ÐºÐŸÑÐŸÑÐŸÐµ ÐžÐœÐŸÐ³ÐŽÐ° ÐœÐµ ÐŽÐŸÑÑÐ°ÑÐŸÑÐœÐŸ ÑÐŸÑÐœÐŸ.)</Text>
+<Text id="132">Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ Ð²ÐžÐŽ Ð¿ÐŸÐžÑÐºÐ°,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° "ÐÐžÐŽÑ Ð¿ÐŸÐžÑÐºÐ°" Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ Ð²ÐžÐŽ Ð¿ÐŸÐžÑÐºÐ°".ÐÐ°Ð¶ÐŽÑÐ¹ Ð²ÐžÐŽ Ð¿ÐŸÐžÑÐºÐ° ÐŒÐŸÐ¶ÐµÑ Ð¿ÐŸÑÐ²ÐžÑÑÑÑ Ð² ÑÐ¿ÐžÑÐºÐµ ÑÐŸÐ»ÑÐºÐŸ ÐŸÐŽÐžÐœ ÑÐ°Ð·. ÐÐµÑÐ²ÑÐ¹ Ð²ÐžÐŽ Ð¿ÐŸÐžÑÐºÐ° Ð±ÑÐŽÐµÑ Ð¿ÐŸ-ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ Ðž ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑÑ ÐœÐ° ÑÑÑÐ°ÐœÐžÑÐµ Ð¿ÐŸÐžÑÐºÐ° ÑÐŸÐ·ÐŽÐ°ÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑÐµ ÐŸÑÑÐ°Ð»ÑÐœÑÐµ Ð²ÐžÐŽÑ ÐŒÐŸÐ¶ÐœÐŸ Ð±ÑÐŽÐµÑ Ð²ÑÐ±ÑÐ°ÑÑ ÐœÐ° ÑÑÑÐ°ÐœÐžÑÐµ ÐŸÐ¿ÑÐžÐ¹.</Text>
+<Text id="133">Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ Ð²ÐžÐŽ Ð¿ÐŸÐžÑÐºÐ°, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° "Ð¢ÐµÐºÑÑÐžÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ Ð²ÐžÐŽÐŸÐ² Ð¿ÐŸÐžÑÐºÐ°" Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ Ð²ÐžÐŽ Ð¿ÐŸÐžÑÐºÐ°".Ð¡Ð¿ÐžÑÐŸÐº ÐŽÐŸÐ»Ð¶ÐµÐœ ÑÐŸÐŽÐµÑÐ¶Ð°ÑÑ Ð¿ÐŸ ÐºÑÐ°Ð¹ÐœÐµÐ¹ ÐŒÐµÑÐµ ÐŸÐŽÐžÐœ Ð²ÐžÐŽ Ð¿ÐŸÐžÑÐºÐ°. </Text>
+</Section>
+<Section name="searchindexes">
+<Title>
+<Text id="134">ÐÐœÐŽÐµÐºÑÑ Ð¿ÐŸÐžÑÐºÐ°</Text>
+</Title>
+<Text id="135">ÐÐœÐŽÐµÐºÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑ,ÐºÐ°ÐºÐžÐµ ÑÐ°ÑÑÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÐ²Ð»ÑÑÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž ÐŽÐ»Ñ Ð¿ÐŸÐžÑÐºÐ°. Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ,ÐºÐ°Ðº ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ Ðž ÑÐŽÐ°Ð»ÐžÑÑ ÐžÐœÐŽÐµÐºÑÑ,Ð° ÑÐ°ÐºÐ¶Ðµ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÐžÐœÐŽÐµÐºÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ.ÐÐŸÐŽ "Ð Ð°Ð·ÐŽÐµÐ»Ð°ÐŒÐž ÐŽÐžÐ·Ð°Ð¹ÐœÐ°" ÑÐµÐ»ÐºÐœÐžÑÐµ ÐžÐœÐŽÐµÐºÑÑ Ð¿ÐŸÐžÑÐºÐ°.</Text>
+<Text id="136">Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐžÐœÐŽÐµÐºÑ,Ð²Ð²ÐµÐŽÐžÑÐµ ÐžÐŒÑ ÐŽÐ»Ñ ÐœÐµÐ³ÐŸ Ð² Ð¿ÐŸÐ»Ðµ "ÐÐŒÑ ÐžÐœÐŽÐµÐºÑÐ°".ÐÑÐ±ÐµÑÐžÑÐµ, ÐºÐ°ÐºÐžÐµ ÐžÐ· Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÑÑ
+ ÐžÑÑÐŸÑÐœÐžÐºÐŸÐ² ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž Ð¿ÑÐžÑÐŸÐµÐŽÐžÐœÐžÑÑ Ðº ÐžÐœÐŽÐµÐºÑÑ, ÑÐµÐ»ÐºÐ°Ñ ÐœÐ° Ð¿ÐŸÐ»Ðµ ÐŸÐºÐŸÐ»ÐŸ ÐœÐžÑ
+. Ð¡Ð¿ÐžÑÐŸÐº Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð²ÑÐµ Ð·Ð°ÐŽÐ°ÐœÐœÑÐµ ÑÐ»ÐµÐŒÐµÐœÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, Ð° ÑÐ°ÐºÐ¶Ðµ Ð¿ÐŸÐ»ÐœÑÐ¹ ÑÐµÐºÑÑ. Ð Ð°ÑÐ¿ÐŸÐ»Ð°Ð³Ð°Ñ Ð²ÑÐ±ÑÐ°ÐœÐœÑÐŒÐž ÐžÑÑÐŸÑÐœÐžÐºÐ°ÐŒÐž ÐŽÐ°ÐœÐœÑÑ
+, Ð²ÑÐ±ÐµÑÐžÑÐµ ÑÑÐµÐ¿ÐµÐœÑ ÐŽÐµÑÐ°Ð»ÐžÐ·Ð°ÑÐžÐž ÐžÐœÐŽÐµÐºÑÐ°, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐŒÐµÐœÑ "ÐÐ° ÑÑÐŸÐ²ÐœÐµ". ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÑÑÐž ÐŽÐµÑÐ°Ð»Ðž ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÑ,Ð¿ÑÐœÐºÑ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ ÐžÐœÐŽÐµÐºÑ" ÑÑÐ°ÐœÐŸÐ²ÐžÑÑÑ Ð°ÐºÑÐžÐ²ÐœÑÐŒ (ÐµÑÐ»Ðž ÐœÐµÑ ÑÑÑÐµÑÑÐ²ÑÑÑÐµÐ³ÐŸ ÐžÐœÐŽÐµÐºÑÐ° Ñ ÑÐµÐŒÐž Ð¶Ðµ ÑÐ°ÐŒÑÐŒÐž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐ°ÐŒÐž).Ð©ÐµÐºÐœÐžÑÐµ ÐœÐ° ÐœÑÐŒ, ÑÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐœÐŸÐ²ÑÐ¹ ÐžÐœÐŽÐµÐºÑ.</Text>
+<Text id="137">Ð§ÑÐŸÐ±Ñ ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ ÐžÐœÐŽÐµÐºÑ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ Ðž ÐžÐ·ÐŒÐµÐœÐžÑÐµ ÐŽÐµÑÐ°Ð»Ðž. ÐÐŸÐŽÑÐ²ÐµÑÐŽÐžÑÐµ, ÐœÐ°Ð¶Ð°Ð² ÐœÐ° "ÐÐ°ÐŒÐµÐœÐžÑÑ ÐžÐœÐŽÐµÐºÑ".</Text>
+<Text id="138">Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÐžÐœÐŽÐµÐºÑ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° ÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐœÑÑ
+ ÐžÐœÐŽÐµÐºÑÐŸÐ² Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ ÐžÐœÐŽÐµÐºÑ".</Text>
+<Text id="139">Ð§ÑÐŸÐ±Ñ ÑÐŸÐ·ÐŽÐ°ÑÑ ÐžÐœÐŽÐµÐºÑ ÐžÐ· ÑÐºÐŸÐœÐ²ÐµÑÑÐžÑÐŸÐ²Ð°ÐœÐœÐŸÐ³ÐŸ ÑÐµÐºÑÑÐ° Ðž Ð²ÑÐµÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÐœÐ°Ð¶ÐŒÐžÑÐµ "ÐÑÐ±ÑÐ°ÑÑ ÐÑÐµ".</Text>
+<Text id="140">ÐÐœÐŽÐµÐºÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ - ÑÐŸÑ, ÐºÐŸÑÐŸÑÑÐ¹ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐœÐ° Ð¿ÐŸÐžÑÐºÐŸÐ²ÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž,Ð¿ÐŸÐŒÐµÑÐµÐœ ÑÑÐ³Ð°ÐŒÐž "[ÐÐœÐŽÐµÐºÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ]" Ð² ÑÐ¿ÐžÑÐºÐµ "ÐÐ°ÐŽÐ°ÐœÐœÑÐµ ÐžÐœÐŽÐµÐºÑÑ".Ð§ÑÐŸÐ±Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÐµÐ³ÐŸ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐžÐœÐŽÐµÐºÑ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÑÑÐ°ÐœÐŸÐ²ÐžÑÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ".</Text>
+<Text id="141">ÐÑÐ»Ðž Ð¿ÐŸÐ·Ð²ÐŸÐ»ÐµÐœ ÑÐ°ÑÑÐžÑÐµÐœÐœÑÐ¹ Ð¿ÐŸÐžÑÐº (ÑÐµÑÐµÐ· Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ Ð²ÐžÐŽÐŸÐ² Ð¿ÐŸÐžÑÐºÐ°), ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐžÐœÐŽÐµÐºÑÐŸÐŒ ÐŸÑÐ»ÐžÑÐ°ÐµÑÑÑ. ÐÐŒÐµÐµÑÑÑ ÐœÐŸÐ²ÑÐ¹ ÐžÑÑÐŸÑÐœÐžÐº Ð¿ÑÐµÐ²ÐŽÐŸÐŽÐ°ÐœÐœÑÑ
+ "Ð²ÑÐµ Ð¿ÐŸÐ»Ñ",ÐºÐŸÑÐŸÑÑÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÑÑ Ð¿ÐŸÐžÑÐº Ð¿ÐŸ Ð²ÑÐµÐŒ ÑÐºÐ°Ð·Ð°ÐœÐœÑÐŒ ÐžÐœÐŽÐµÐºÑÐ°ÐŒ ÑÑÐ°Ð·Ñ.Ð£ÑÐŸÐ²ÐœÐž ÐœÐµ Ð¿ÑÐžÐ²ÑÐ·Ð°ÐœÑ Ðº ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐŸÐŒÑ ÐžÐœÐŽÐµÐºÑÑ,Ð° Ð¿ÑÐžÐŒÐµÐœÑÑÑÑÑ ÐºÐŸ Ð²ÑÐµÐŒ ÐžÐœÐŽÐµÐºÑÐ°ÐŒ.Ð¢Ð°ÐºÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ,ÐžÐœÐŽÐµÐºÑÑ Ðž ÑÑÐŸÐ²ÐœÐž ÐŽÐŸÐ±Ð°Ð²Ð»ÑÑÑÑÑ ÐŸÑÐŽÐµÐ»ÑÐœÐŸ. "ÐÐŸÐ±Ð°Ð²ÐžÑÑ ÐÑÐµ" ÑÐŸÐ·ÐŽÐ°ÐµÑ ÐŸÑÐŽÐµÐ»ÑÐœÑÐ¹ ÐžÐœÐŽÐµÐºÑ ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ Ð¿ÐŸÐ»Ñ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ð² ÑÑÐŸÐŒ ÑÐµÐ¶ÐžÐŒÐµ.</Text>
+<Text id="142">ÐÐŒÑ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÐžÐœÐŽÐµÐºÑÐ° Ð±ÑÐŽÐµÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ ÑÐ²ÑÐ·Ð°ÐœÐŸ Ñ ÐžÐŒÐµÐœÐµÐŒ ÐžÑÑÐŸÑÐœÐžÐºÐ°.Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐžÐŒÑ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐžÐœÐŽÐµÐºÑ,ÐžÐ·ÐŒÐµÐœÐžÑÐµ ÐµÐ³ÐŸ ÐŽÐµÑÐ°Ð»Ðž Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐ°ÐŒÐµÐœÐžÑÑ ÐžÐœÐŽÐµÐºÑ".   </Text>
+</Section>
+<Section name="partitionindexes">
+<Title>
+<Text id="143">ÐÐœÐŽÐµÐºÑÑ ÑÐ°Ð·Ð±ÐžÐµÐœÐžÑ</Text>
+</Title>
+<Text id="144">ÐÐœÐŽÐµÐºÑÑ Ð¿ÐŸÑÑÑÐŸÐµÐœÑ ÐœÐ° ÐŽÐµÑÐ°Ð»ÑÐœÐŸÐŒ ÑÐµÐºÑÑÐµ ÐžÐ»Ðž ÐžÑÑÐŸÑÐœÐžÐºÐ°Ñ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. ÐÐµÑÑÐŸ Ð¿ÐŸÐžÑÐºÐ° ÐŒÐŸÐ¶ÐµÑ Ð² ÐŽÐ°Ð»ÑÐœÐµÐ¹ÑÐµÐŒ ÑÐ¿ÑÐ°Ð²Ð»ÑÑÑÑÑ Ð¿ÑÑÑÐŒ ÑÐ°Ð·Ð±ÐžÐµÐœÐžÑ ÐžÐœÐŽÐµÐºÑÐŸÐ² Ð»ÐžÐ±ÐŸ Ð¿ÐŸ ÑÐ·ÑÐºÑ ÐžÐ»Ðž Ð¿ÐŸ ÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐœÑÐŒ ÑÐžÐ»ÑÑÑÐ°ÐŒ.Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑÑÑ,ÐºÐ°Ðº ÑÑÐŸ ÑÐŽÐµÐ»Ð°ÑÑ. ÐÐœÑÑÑÐž "Ð Ð°Ð·ÐŽÐµÐ»ÐŸÐ² ÐŽÐžÐ·Ð°Ð¹ÐœÐ°" ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐœÐŽÐµÐºÑÑ ÑÐ°Ð·Ð±ÐžÐµÐœÐžÑ".</Text>
+<Text id="145">ÐÐžÐŽ "ÐÐœÐŽÐµÐºÑÑ ÑÐ°Ð·Ð±ÐžÐµÐœÐžÑ" ÐžÐŒÐµÐµÑ ÑÑÐž Ð·ÐœÐ°ÑÐµÐœÐžÑ:"ÐÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÑÐžÐ»ÑÑÑÑ","ÐÐ°Ð·ÐœÐ°ÑÐžÑÑ ÑÐ°Ð·Ð±ÐžÐµÐœÐžÐµ" Ðž "ÐÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÑÐ·ÑÐºÐž". ÐÐ»Ñ ÑÐŸÐ³ÐŸ ÑÑÐŸÐ±Ñ Ð±ÐŸÐ»ÑÑÐµ ÑÐ·ÐœÐ°ÑÑ ÐŸ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÐž, ÑÐžÑÐ°Ð¹ÑÐµ  ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÑ
+ Ðž Ð¿ÐŸÐŽÐžÐœÐŽÐµÐºÑÐ°Ñ
+ Ð² Ð³Ð»Ð°Ð²Ðµ 2 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone.</Text>
+<Text id="146">Ð­ÐºÑÐ°Ðœ ÐÐœÐŽÐµÐºÑÐŸÐ² Ð Ð°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐµÐœ ÑÐŸÐ»ÑÐºÐŸ Ð² ÑÐµÐ¶ÐžÐŒÐ°Ñ
+ Ð¡Ð¿ÐµÑÐžÐ°Ð»ÐžÑÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÑ
+ Ð¡ÐžÑÑÐµÐŒ Ðž Ð­ÐºÑÐ¿ÐµÑÑ (ÑÐŒ. <Reference target="preferences"/>). ÐÐ°ÐŒÐµÑÑÑÐµ, ÑÑÐŸ ÐŸÐ±ÑÐµÐµ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸ Ð¿ÑÐŸÐžÐ·Ð²ÐµÐŽÐµÐœÐœÑÑ
+ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÐ¹ ÑÐ²Ð»ÑÐµÑÑÑ ÐºÐŸÐŒÐ±ÐžÐœÐ°ÑÐžÐµÐ¹ Ð²ÑÐµÑ
+ ÐžÐœÐŽÐµÐºÑÐŸÐ², ÑÐžÐ»ÑÑÑÐŸÐ² ÑÑÐ±ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð²ÑÐ±ÑÐ°ÐœÐœÑÑ
+ ÑÐ·ÑÐºÐŸÐ². ÐÐ²Ð° ÐžÐœÐŽÐµÐºÑÐ° Ñ ÐŽÐ²ÑÐŒÑ ÑÐžÐ»ÑÑÑÐ°ÐŒÐž ÑÑÐ±ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÐŸ ÐŽÐ²ÑÐŒ ÑÐ·ÑÐºÐ°ÐŒ Ð¿ÑÐžÐ²ÐµÐ»ÐŸ Ð±Ñ Ðº Ð²ÐŸÑÑÐŒÐž ÐžÐœÐŽÐµÐºÑÐ°ÐŒ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ.</Text>
+<Section name="definefilters">
+<Title>
+<Text id="147">ÐÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÑÐžÐ»ÑÑÑÑ</Text>
+</Title>
+<Text id="148">Ð€ÐžÐ»ÑÑÑÑ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑ ÐÐ°ÐŒ Ð³ÑÑÐ¿Ð¿ÐžÑÐŸÐ²Ð°ÑÑ Ð² Ð¿ÐŸÐŽÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð²ÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð¿ÐŸ  ÐžÐœÐŽÐµÐºÑÑ,ÐŽÐ»Ñ ÐºÐŸÑÐŸÑÐŸÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÐµÑ Ð·Ð°ÐŽÐ°ÐœÐœÐŸÐ¹ ÐŒÐŸÐŽÐµÐ»Ðž.</Text>
+<Text id="149">Ð§ÑÐŸÐ±Ñ ÑÐŸÐ·ÐŽÐ°ÑÑ ÑÐžÐ»ÑÑÑ,ÑÐµÐ»ÐºÐœÐžÑÐµ ÐºÐ»Ð°Ð²ÐžÑÑ "ÐÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÑÐžÐ»ÑÑÑÑ" Ðž Ð²Ð²ÐµÐŽÐžÑÐµ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐŽÐ»Ñ ÐœÐŸÐ²ÐŸÐ³ÐŸ ÑÐžÐ»ÑÑÑÐ° Ð² Ð¿ÐŸÐ»Ðµ "ÐÐŒÑ ÑÐžÐ»ÑÑÑÐ° ÑÑÐ±ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž:".ÐÐ°ÑÐµÐŒ Ð²ÑÐ±ÐµÑÐžÑÐµ Ñ
+Ð°ÑÐ°ÐºÑÐµÑÐœÑÐµ Ð¿ÑÐžÐ·ÐœÐ°ÐºÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐµ ÐžÐ»Ðž ÑÐ»ÐµÐŒÐµÐœÑÐ°ÐŒ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+,ÐžÐ»Ðž ÐœÐ°Ð·Ð²Ð°ÐœÐžÑ ÑÐ°ÑÑÐŒÐ°ÑÑÐžÐ²Ð°ÐµÐŒÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»Ð°.ÐÐ²ÐµÐŽÐžÑÐµ Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÐŸÐµ Ð²ÑÑÐ°Ð¶ÐµÐœÐžÐµ,ÑÑÐŸÐ±Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð² ÑÐµÑÐµÐœÐžÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ ÑÑÐŸÐ³ÐŸ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÑ.ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÐµÑÐµÐºÐ»ÑÑÐ°ÑÑ "ÐÐºÐ»ÑÑÐµÐœÐžÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²", ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑ ÑÐžÐ»ÑÑÑÑ, ÐžÐ»Ðž "ÐÑÐºÐ»ÑÑÐµÐœÐžÐµ" ÐžÑ
+.ÐÐ°ÐºÐŸÐœÐµÑ,ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ Ð»ÑÐ±ÐŸÐ¹ ÑÑÐ°ÐœÐŽÐ°ÑÑ PERL, Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÑÐµ ÑÐ»Ð°Ð³Ðž Ð²ÑÑÐ°Ð¶ÐµÐœÐžÑ,ÑÑÐŸÐ±Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð¿ÑÐž ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐž (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ("i" ÐŽÐ»Ñ ÑÐ»ÑÑÐ°Ñ ÐœÐµÑÑÐ²ÑÑÐ²ÐžÑÐµÐ»ÑÐœÐŸÐ³ÐŸ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÑ),ÐÐ°ÐºÐŸÐœÐµÑ,ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ ÑÐžÐ»ÑÑÑ",ÑÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÑÐžÐ»ÑÑÑ Ðº ÑÐ¿ÐžÑÐºÑ "Ð€ÐžÐ»ÑÑÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ ÑÑÐ±ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹".</Text>
+<Text id="150">Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÑÐžÐ»ÑÑÑ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ ÑÐžÐ»ÑÑÑ". </Text>
+<Text id="151">Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÑÐžÐ»ÑÑÑ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ°,Ð·Ð°ÐŒÐµÐœÐžÑÐµ Ð»ÑÐ±ÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ, ÐºÐŸÑÐŸÑÐŸÐµ Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ Ð² ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÐž ÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐµÐŒ Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐ°ÐŒÐµÐœÐžÑÑ ÑÐžÐ»ÑÑÑ",ÑÑÐŸÐ±Ñ Ð·Ð°ÐºÑÐµÐ¿ÐžÑÑ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ.</Text>
+</Section>
+<Section name="assignpartitions">
+<Title>
+<Text id="152">ÐÐ°Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ</Text>
+</Title>
+<Text id="153">ÐÐŒÐµÑ Ð·Ð°ÐŽÐ°ÐœÐœÑÐ¹ ÑÐžÐ»ÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐºÐ»Ð°Ð²ÐžÑÑ "ÐÐ°Ð·ÐœÐ°ÑÐžÑÑ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ" ÐŽÐ»Ñ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐžÐœÐŽÐµÐºÑÐŸÐ² ÐŽÐ»Ñ ÑÑÐŸÐ³ÐŸ ÐžÐ»Ðž ÐŽÐ»Ñ Ð³ÑÑÐ¿Ð¿Ñ ÑÐžÐ»ÑÑÑÐŸÐ². ÐÑÐ±ÐµÑÐžÑÐµ Ð¶ÐµÐ»Ð°ÑÐµÐ»ÑÐœÑÐ¹ ÑÐžÐ»ÑÑÑ (ÐžÐ»Ðž ÑÐžÐ»ÑÑÑÑ) ÐžÐ· ÑÐ¿ÐžÑÐºÐ° "ÐÐ°ÐŽÐ°ÐœÐœÑÐµ ÑÐžÐ»ÑÑÑÑ ÑÑÐ±ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž", Ð²Ð²ÐµÐŽÐžÑÐµ ÐžÐŒÑ ÐŽÐ»Ñ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ Ð² Ð¿ÐŸÐ»Ðµ "ÐÐŒÑ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ" Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÐµ".</Text>
+<Text id="154">Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÐµ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÐµ".</Text>
+<Text id="155">Ð§ÑÐŸÐ±Ñ Ð¿ÑÐŸÐžÐ·Ð²ÐµÑÑÐž ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÐµ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÑÑÐ°ÐœÐŸÐ²ÐžÑÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ".</Text>
+</Section>
+<Section name="assignlanguages">
+<Title>
+<Text id="156">ÐÐ°ÐŽÐ°ÐœÐœÑÐµ ÑÐ·ÑÐºÐž</Text>
+</Title>
+<Text id="157">Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŽÐµÑÐ°Ð»ÐžÐ·ÐžÑÐŸÐ²Ð°ÐœÐŸ,ÐºÐ°Ðº ÐŸÐ³ÑÐ°ÐœÐžÑÐžÑÑ ÐžÐœÐŽÐµÐºÑÑ Ð¿ÐŸÐžÑÐºÐ° ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐžÐŒÐž ÑÐ·ÑÐºÐ°ÐŒÐž. ÐÑ ÑÐŸÐ²ÐµÑÑÐ°ÐµÑÐµ ÑÑÐŸ Ð¿ÑÐž ÑÐµÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÐžÐž ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ,ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐºÐ»Ð°Ð²ÐžÑÑ "ÐÐ°ÐŽÐ°ÐœÐœÑÐµ ÑÐ·ÑÐºÐž" Ð² Ð¿ÐµÑÐµÑÐœÐµ "ÐÐœÐŽÐµÐºÑÑ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ".</Text>
+<Text id="158">Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐœÐŸÐ²ÑÐ¹ ÑÐ·ÑÐº ÐŽÐ»Ñ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐºÐ»Ð°Ð²ÐžÑÑ "ÐÐ°ÐŽÐ°ÐœÐœÑÐµ ÑÐ·ÑÐºÐž" ÐŽÐ»Ñ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐžÐœÐŽÐµÐºÑÐ° ÐŽÐ»Ñ ÑÑÐŸÐ³ÐŸ. ÐÑÐ±ÐµÑÐžÑÐµ Ð¶ÐµÐ»Ð°ÑÐµÐ»ÑÐœÑÐ¹ ÑÐ·ÑÐº ÐžÐ· ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐ³ÐŸ ÑÐ¿ÐžÑÐºÐ° "Ð¯Ð·ÑÐºÐž ÐŽÐ»Ñ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÑ" Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ ÑÐ·ÑÐº"</Text>
+<Text id="159">Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÑÐ·ÑÐº,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° "ÐÑÐ±ÐŸÑÑ ÑÐ·ÑÐºÐ°" Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ ÑÐ·ÑÐº".</Text>
+<Text id="160">Ð§ÑÐŸÐ±Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÑÐ·ÑÐº Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÑÑÐ°ÐœÐŸÐ²ÐºÐ° Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ".</Text>
+</Section>
+</Section>
+<Section name="xcollectionsearching">
+<Title>
+<Text id="161">ÐÐŸÐžÑÐº Ð² Ð¿ÐµÑÐµÑÐµÐºÐ°ÑÑÐžÑ
+ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÑ
+</Text>
+</Title>
+<Text id="162">Greenstone Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑ Ð¿ÐŸÐžÑÐº Ð² ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÑ
+ ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÑ
+, ÐºÐ°Ðº ÐµÑÐ»Ðž Ð±Ñ ÐŸÐœÐž Ð±ÑÐ»Ðž ÐŸÐ±ÑÐµÐŽÐžÐœÐµÐœÑ. Ð­ÑÐŸ ÑÐŽÐµÐ»Ð°ÐœÐŸ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÑÐºÐ°Ð·Ð°ÐœÐžÑ ÑÐ¿ÐžÑÐºÐ° ÐŽÑÑÐ³ÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹, Ð² ÐºÐŸÑÐŸÑÑÑ
+ ÐŽÐŸÐ»Ð¶ÐœÐ° Ð±ÑÑÑ Ð¿ÑÐŸÐ²ÐµÐŽÐµÐœ Ð¿ÐŸÐžÑÐº Ð²ÐŒÐµÑÑÐµ Ñ ÐœÐ°ÑÑÐŸÑÑÐµÐ¹. Ð "Ð Ð°Ð·ÐŽÐµÐ»Ð°Ñ
+ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°" ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐžÑÐº Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÑ
+".</Text>
+<Text id="163">ÐÐµÐ¶ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐŸÐœÐœÑÐ¹ Ð¿ÐŸÐžÑÐº Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÑ
+ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐºÐŸÐœÑÑÐŸÐ»ÑÐœÑÐ¹ ÑÐ¿ÐžÑÐŸÐº ÐŽÐŸÑÑÑÐ¿ÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹.Ð¢ÐµÐºÑÑÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð¿ÐŸÐŒÐµÑÐµÐœÑ Ðž ÐœÐµ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐŸÑÑÐµÑÐœÐ°. Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐŽÑÑÐ³ÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð² ÐºÐŸÑÐŸÑÑÑ
+ Ð¿ÐŸÐžÑÐº Ð±ÑÐŽÐµÑ Ð¿ÑÐŸÐ²ÐŸÐŽÐžÑÑÑÑ Ð¿Ð°ÑÐ°Ð»Ð»ÐµÐ»ÑÐœÐŸ, ÑÐµÐ»ÐºÐœÐžÑÐµ ÐœÐ° ÐœÐžÑ
+ Ð² ÑÐ¿ÐžÑÐºÐµ (ÑÐµÐ»ÐºÐœÐžÑÐµ ÑÐœÐŸÐ²Ð°, ÑÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÐžÑ
+). ÐÑÐ»Ðž ÐŸÑÐŸÐ±ÑÐ°ÐœÐ° ÑÐŸÐ»ÑÐºÐŸ ÐŸÐŽÐœÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÑÐŸ ÐŒÐµÐ¶ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐŸÐœÐœÑÐ¹ Ð¿ÐŸÐžÑÐº ÐœÐµÐ²ÐŸÐ·ÐŒÐŸÐ¶ÐµÐœ.</Text>
+<Text id="164">ÐÑÐ»Ðž ÐžÐœÐŽÐžÐ²ÐžÐŽÑÐ°Ð»ÑÐœÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐœÐµ ÐžÐŒÐµÑÑ ÐŸÐŽÐžÐœÐ°ÐºÐŸÐ²ÑÑ
+ ÐžÐœÐŽÐµÐºÑÐŸÐ² (Ð²ÐºÐ»ÑÑÐ°Ñ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ ÐœÐ° ÑÑÐ±ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÐµ Ð¿ÐŸ ÑÐ·ÑÐºÐ°ÐŒ) Ñ ÐŽÑÑÐ³ÐžÐŒÐž, ÑÐŸ Ð¿ÐµÑÐµÐºÑÐµÑÑÐœÑÐ¹ Ð¿ÐŸÐžÑÐº ÐœÐµ Ð±ÑÐŽÐµÑ ÑÐ°Ð±ÐŸÑÐ°ÑÑ ÐŽÐŸÐ»Ð¶ÐœÑÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ. ÐÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð±ÑÐŽÐµÑ ÑÐŸÐ»ÑÐºÐŸ ÑÐ¿ÐŸÑÐŸÐ±ÐµÐœ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑ Ð¿ÐŸÐžÑÐº,  ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐžÐœÐŽÐµÐºÑÑ, ÐŸÐ±ÑÐžÐµ ÐŽÐ»Ñ Ð²ÑÐµÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹.</Text>
+<Text id="165">ÐÐ»Ñ ÐŽÐ°Ð»ÑÐœÐµÐ¹ÑÐžÑ
+ ÐŽÐµÑÐ°Ð»ÐµÐ¹ ÑÐŒ.Ð³Ð»Ð°Ð²Ñ 1 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone.</Text>
+</Section>
+<Section name="classifiers">
+<Title>
+<Text id="166">ÐÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°</Text>
+</Title>
+<Text id="167">Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ,ÐºÐ°Ðº ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ Ðº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐºÐŸÑÐŸÑÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÐŽÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°. Ð "Ð Ð°Ð·ÐŽÐµÐ»Ð°Ñ
+ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°" ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÑÐŸÑÐŒÐŸÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ²". </Text>
+<Text id="168">Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ,ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐžÐ¹ ÑÐ¿ÐžÑÐŸÐº "ÐÑÐ±ÐŸÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐ° ÐŽÐ»Ñ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÑ" Ð²ÐœÐžÐ·Ñ ÐŸÐºÐœÐ°,Ðž Ð·Ð°ÑÐµÐŒ ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐ±Ð°Ð²ÑÑÐµ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ". ÐÐŸÑÐ²Ð»ÑÐµÑÑÑ ÐŸÐºÐœÐŸ, ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒÐŸÐµ "ÐÐŸÐœÑÐžÐ³ÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ²".ÐÐœÑÑÑÑÐºÑÐžÐž ÐŽÐ»Ñ ÑÑÐŸÐ³ÐŸ ÐŽÐžÐ°Ð»ÐŸÐ³Ð° ÑÐµ Ð¶Ðµ ÑÐ°ÐŒÑÐµ,ÑÑÐŸ ÐºÐ°ÑÐ°ÑÑÑÑ Ð¿Ð»Ð°Ð³ÐžÐœÐŸÐ² (<Reference target="plugins"/>).ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐÑ ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°Ð»Ðž ÐœÐŸÐ²ÑÐ¹ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ, ÐŸÐœ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑÑÑ Ð² ÐºÐŸÐœÐµÑ ÑÐ¿ÐžÑÐºÐ° "Ð¢ÐµÐºÑÑÐžÐµ Ð·Ð°ÐŽÐ°ÐœÐœÑÐµ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ".  </Text>
+<Text id="169">Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ".</Text>
+<Text id="170">Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐ°, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐœÑÐžÐ³ÑÑÐžÑÑÐ¹ÑÐµ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ." (ÐžÐ»Ðž ÑÐµÐ»ÐºÐœÑÑÑ ÐŽÐ²Ð° ÑÐ°Ð·Ð° ÐœÐ° ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐµ Ð² ÑÐ¿ÐžÑÐºÐµ).</Text>
+<Text id="171">ÐÐŸÑÑÐŽÐŸÐº ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ² Ð² ÐœÐ°Ð²ÐžÐ³Ð°ÑÐžÐŸÐœÐœÐŸÐ¹ Ð»ÐžÐœÐµÐ¹ÐºÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐž ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÐµÑ ÑÐŸÐŒÑ,ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÐŸÐºÐ°Ð·Ð°Ðœ Ð·ÐŽÐµÑÑ.Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ Ð¿ÐŸÑÑÐŽÐŸÐº,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ, ÐºÐŸÑÐŸÑÑÐ¹ ÐÑ Ñ
+ÐŸÑÐžÑÐµ Ð¿ÐµÑÐµÐŒÐµÑÑÐžÑÑ, Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐ²ÐžÐ³Ð°ÑÑÑÑ Ð²Ð²ÐµÑÑ
+" ÐžÐ»Ðž "ÐÐ²ÐžÐ³Ð°ÑÑÑÑ Ð²ÐœÐžÐ·".</Text>
+<Text id="172">ÐÐ»Ñ ÐŽÐ°Ð»ÑÐœÐµÐ¹ÑÐµÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž ÐŸÑÐœÐŸÑÐžÑÐµÐ»ÑÐœÐŸ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ² ÑÐžÑÐ°Ð¹ÑÐµ Ð³Ð»Ð°Ð²Ñ 2 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone.</Text>
+</Section>
+<Section name="formatstatements">
+<Title>
+<Text id="173">ÐÑÐŸÐ±ÐµÐœÐœÐŸÑÑÐž ÑÐŸÑÐŒÐ°ÑÐ°</Text>
+</Title>
+<Text id="174">ÐÐµÐ±-ÑÑÑÐ°ÐœÐžÑÑ, ÐºÐŸÑÐŸÑÑÐµ ÐÑ Ð²ÐžÐŽÐžÑÐµ, ÐºÐŸÐ³ÐŽÐ° ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÐµ Greenstone, ÐœÐµ ÑÐ²Ð»ÑÑÑÑÑ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐœÑÐŒÐž, Ð° ÑÐŸÐ·ÐŽÐ°ÑÑÑÑ "ÐœÐ° Ð»ÐµÑÑ", ÐºÐŸÐ³ÐŽÐ° Ð² ÐœÐžÑ
+ ÐµÑÑÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÑÑÑ. ÐÐŸÐŒÐ°ÐœÐŽÑ ÑÐŸÑÐŒÐ°ÑÐ° ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÐŽÐ»Ñ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ð¿ÐŸÑÐ²Ð»ÐµÐœÐžÑ ÑÑÐžÑ
+ ÑÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÐœÑÑ
+ ÑÑÑÐ°ÐœÐžÑ. ÐÐœÐž Ð·Ð°ÑÑÐ°Ð³ÐžÐ²Ð°ÑÑ ÑÐ°ÐºÐžÐµ Ð²ÐµÑÐž,ÐºÐ°Ðº ÐŒÐµÑÑÐŸ Ð¿ÐŸÑÐ²Ð»ÐµÐœÐžÑ ÐºÐœÐŸÐ¿ÐºÐž,ÐºÐŸÐ³ÐŽÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑÑÑ,Ðž ÐºÐ°ÐºÐžÐµ ÑÐ²ÑÐ·Ðž ÐŸÑÐŸÐ±ÑÐ°Ð¶Ð°ÑÑÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐŒ DateList. ÐÐŸÐŒÐ°ÐœÐŽÑ ÑÐŸÑÐŒÐ°ÑÐ° ÐœÐµ Ð»ÐµÐ³ÐºÐŸ ÑÐ°Ð·ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÑÑ,Ðž ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ Ð¿ÑÐŸÑÐžÑÐ°ÑÑ Ð³Ð»Ð°Ð²Ñ 2 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone. Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÐ¶ÐŽÐ°ÑÑÑÑ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÑÐŸÑÐŒÐ°ÑÐ° Ðž ÑÐŸ, ÐºÐ°Ðº ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÑÐµÑ ÐŽÐŸÑÑÑÐ¿ Ðº ÐœÐžÐŒ. Ð "Ð Ð°Ð·ÐŽÐµÐ»Ð°Ñ
+ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°" ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÑÐŸÐ±ÐµÐœÐœÐŸÑÑÐž ÑÐŸÑÐŒÐ°ÑÐ°".</Text>
+<Text id="175">ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÑÐžÐŒÐµÐœÐžÑÑ ÐºÐŸÐŒÐ°ÐœÐŽÑ ÑÐŸÑÐŒÐ°ÑÐ° Ðº ÑÐµÐŒÑ-ÐœÐžÐ±ÑÐŽÑ Ð² ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐŒ ÑÐ¿ÐžÑÐºÐµ "ÐÑÐ±ÐŸÑ ÑÑÐµÐŽÑÑÐ²",ÐºÐŸÑÐŸÑÑÐ¹ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÐºÐ°Ð¶ÐŽÑÐ¹ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ Ðž Ð²ÑÑÑÐŸÐµÐœÐœÑÐ¹ ÑÐ¿ÐžÑÐŸÐº ÑÑÐµÐŽÑÑÐ². ÐÐŸÐ³ÐŽÐ° ÐÑ Ð²ÑÐ±ÐžÑÐ°ÐµÑÐµ ÑÑÐµÐŽÑÑÐ²Ð°, ÐµÑÑÑ ÐŽÐ²Ð° ÑÐžÐ¿Ð° ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ. ÐÐµÐºÐŸÑÐŸÑÑÐµ ÑÑÐµÐŽÑÑÐ²Ð° ÑÐ²Ð»ÑÑÑÑÑ Ð¿ÑÐŸÑÑÐŸ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž ÐžÐ»Ðž ÐœÐµÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž,ÐŸÐœÐž ÑÐ¿ÑÐ°Ð²Ð»ÑÑÑÑÑ ÐºÐœÐŸÐ¿ÐºÐ°ÐŒÐž. ÐÑÑÐ³ÐžÐµ ÑÑÐµÐ±ÑÑÑ, ÑÑÐŸÐ±Ñ Ð±ÑÐ»Ð° ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐ° ÑÐŸÑÐŒÐ°ÑÐœÐ°Ñ ÑÑÑÐŸÐºÐ°. ÐÐ»Ñ ÐœÐžÑ
+ ÐžÐŒÐµÐµÑÑÑ ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐžÐ¹ ÑÐ¿ÐžÑÐŸÐº "ÐÐŸÐ·ÐŽÐµÐ¹ÑÑÐ²ÑÑÑÐžÐ¹ ÐºÐŸÐŒÐ¿ÐŸÐœÐµÐœÑ", ÑÑÐŸÐ±Ñ Ð²ÑÐ±ÑÐ°ÑÑ, Ðº ÐºÐ°ÐºÐŸÐ¹ ÑÐ°ÑÑÐž ÑÑÐµÐŽÑÑÐ² ÑÑÑÐŸÐºÐ° ÐŸÐ±ÑÐ°ÑÐ°ÐµÑÑÑ,ÐµÑÐ»Ðž ÑÑÐŸ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ, ÐŸÐ±Ð»Ð°ÑÑÑ ÑÐµÐºÑÑÐ°   ("Ð¡ÑÑÐŸÐºÐ° ÑÐŸÑÐŒÐ°ÑÐ° HTML") ÐŽÐ»Ñ Ð²Ð²ÐŸÐŽÐ° ÑÑÑÐŸÐºÐž, Ðž Ð²ÑÐ±ÐŸÑ Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ "ÐÐµÑÐµÐŒÐµÐœÐœÑÑ
+". Ð§ÑÐŸÐ±Ñ Ð²ÑÑÐ°Ð²ÐžÑÑ Ð¿ÐµÑÐµÐŒÐµÐœÐœÑÑ Ð² ÑÐµÐºÑÑÑÑ Ð¿ÐŸÐ·ÐžÑÐžÑ Ð² ÑÐŸÑÐŒÐ°ÑÐœÑÑ ÑÑÑÐŸÐºÑ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÑ ÐžÐ· ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐ³ÐŸ ÑÐ¿ÐžÑÐºÐ°  Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÑÑÐ°Ð²ÐžÑÑ". </Text>
+<Text id="176">ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÑÐŸÑÐŒÐ°Ñ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ ÐŽÐ»Ñ ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐºÐŸÐŒÐ¿ÐŸÐœÐµÐœÑÐ°, Ð²ÑÐ±ÐžÑÐ°Ñ Ð±Ð»Ð°ÐœÐº ÑÐ²ÐŸÐ¹ÑÑÐ². Ð­ÑÐŸÑ ÑÐŸÑÐŒÐ°Ñ Ð·Ð°ÑÐµÐŒ Ð¿ÑÐžÐŒÐµÐœÑÐµÑÑÑ ÐºÐŸ Ð²ÑÐµÐŒ Ð¿ÑÐžÐŒÐµÐœÐžÐŒÑÐŒ ÑÐ²ÐŸÐ¹ÑÑÐ²Ð°ÐŒ, ÐµÑÐ»Ðž ÐŽÑÑÐ³ÐŸÐµ ÐœÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐŸ.</Text>
+<Text id="177">Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐœÐŸÐ²ÑÑ ÐºÐŸÐŒÐ°ÐœÐŽÑ ÑÐŸÑÐŒÐ°ÑÐ°,Ð²ÐœÐµÑÐžÑÐµ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ,ÐºÐ°Ðº ÐŸÐ±ÑÑÑÐœÐµÐœÐŸ Ð²ÑÑÐµ, Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ ÑÐŸÑÐŒÐ°Ñ".ÐÐŸÐ²Ð°Ñ ÐºÐŸÐŒÐ°ÐœÐŽÐ° ÑÐŸÑÐŒÐ°ÑÐ° Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ Ð² ÑÐ¿ÐžÑÐºÐµ "Ð¢ÐµÐºÑÑÐžÐµ Ð·Ð°ÐŽÐ°ÐœÐœÑÐµ ÐºÐŸÐŒÐ°ÐœÐŽÑ ÑÐŸÑÐŒÐ°ÑÐ°".Ð¢ÐŸÐ»ÑÐºÐŸ ÐŸÐŽÐœÐ° ÐºÐŸÐŒÐ°ÐœÐŽÐ° ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÑÐ²ÑÐ·Ð°ÐœÐ° Ñ ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÐºÐŸÐŒÐ±ÐžÐœÐ°ÑÐžÐµÐ¹ ÑÐ²ÐŸÐ¹ÑÑÐ²ÐŸ/ÐºÐŸÐŒÐ¿ÐŸÐœÐµÐœÑ.</Text>
+<Text id="178">Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÐºÐŸÐŒÐ°ÐœÐŽÑ ÑÐŸÑÐŒÐ°ÑÐ°, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÑ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ ÑÐŸÑÐŒÐ°Ñ".</Text>
+<Text id="179">Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐºÐŸÐŒÐ°ÐœÐŽÑ ÑÐŸÑÐŒÐ°ÑÐ°, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÑ ÐŒÐ· ÑÐ¿ÐžÑÐºÐ°, ÐžÐ·ÐŒÐµÐœÐžÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐ°ÐŒÐµÐœÐžÑÑ ÑÐŸÑÐŒÐ°Ñ".</Text>
+<Text id="180">ÐÐ° ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐµÐ¹ ÐŸ Ð¿ÐµÑÐµÐŒÐµÐœÐœÑÑ
+ Ðž ÐºÐŸÐŒÐ¿ÐŸÐœÐµÐœÑÐ°Ñ
+ ÑÑÐµÐŽÑÑÐ² ÐŸÐ±ÑÐ°ÑÐžÑÐµÑÑ Ðº Ð³Ð»Ð°Ð²Ðµ 2 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone.</Text>
+<Text id="181">ÐÑÐ»Ðž ÐºÐœÐŸÐ¿ÐºÐ° "ÐÐŸÐ·Ð²ÐŸÐ»ÐµÐœÐœÑÐµ ÑÐ°ÑÑÐžÑÐµÐœÐœÑÐµ Ð²Ð°ÑÐžÐ°ÐœÑÑ" Ð¿ÐŸÐŒÐµÑÐµÐœÐ°,ÑÐŸ ÑÐ°Ð·ÑÐµÑÐµÐœÑ ÐœÐµÐºÐŸÑÐŸÑÑÐµ Ð¿ÑÐŸÐŽÐ²ÐžÐœÑÑÑÐµ Ð²Ð°ÑÐžÐ°ÐœÑÑ ÑÐŸÑÐŒÐ°ÑÐžÑÐŸÐ²Ð°ÐœÐžÑ . Ð¡Ð¿ÐžÑÐŸÐº ÑÑÐµÐŽÑÑÐ², ÐºÐŸÑÐŸÑÑÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐŸÑÐŒÐ°ÑÐžÑÐŸÐ²Ð°ÐœÑ, ÐœÐµÐŒÐœÐŸÐ³ÐŸ ÐžÐ·ÐŒÐµÐœÐµÐœ Ðž Ð±ÐŸÐ»ÑÑÐµÐµ ÑÐžÑÐ»ÐŸ Ð¿ÐµÑÐµÐŒÐµÐœÐœÑÑ
+ ÐŽÐŸÑÑÑÐ¿ÐœÐŸ ÐŽÐ»Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÐºÐŸÐŒÐ°ÐœÐŽÐŸÐ¹ ÑÐŸÑÐŒÐ°ÑÐ°, ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°Ñ Ð±ÐŸÐ»ÑÑÐµÐµ ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÑÑÑÐ°ÐœÐžÑÐµÐ¹ ÐŸÑÐžÐ³ÐžÐœÐ°Ð»-ÐŒÐ°ÐºÐµÑÐ°.</Text>
+</Section>
+<Section name="translatetext">
+<Title>
+<Text id="182">ÐÐµÑÐµÐ²ÐŸÐŽ ÑÐµÐºÑÑÐ°</Text>
+</Title>
+<Text id="183">Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑÑÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ Ð¿ÐµÑÐµÐ²ÐŸÐŽÐ°, Ð³ÐŽÐµ ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÑÐ·ÑÐº ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÑ
+ ÑÑÐ°Ð³ÐŒÐµÐœÑÐŸÐ² ÑÐµÐºÑÑÐ° ÐŽÐ»Ñ ÑÐ°ÑÑÐµÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð "Ð Ð°Ð·ÐŽÐµÐ»Ðµ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°" ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐµÑÐµÐ²ÐµÑÑÐž ÑÐµÐºÑÑ".</Text>
+<Text id="184">Ð¡ÐœÐ°ÑÐ°Ð»Ð° Ð²ÑÐ±ÐµÑÐžÑÐµ Ð²Ñ
+ÐŸÐŽ Ð² ÑÐ¿ÐžÑÐŸÐº "Ð¡Ð²ÐŸÐ¹ÑÑÐ²Ð°". ÐÐžÐ¶Ðµ Ð¿ÐŸÑÐ²ÑÑÑÑ ÑÑÑÐŸÐºÐž ÑÐ¿ÐµÑÐžÑÐžÑÐœÐŸÐ³ÐŸ ÑÐ·ÑÐºÐ°, ÑÐ²ÑÐ·Ð°ÐœÐœÑÐµ Ñ ÑÑÐžÐŒ ÑÐ²ÐŸÐ¹ÑÑÐ²ÐŸÐŒ. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐžÐ¹ ÑÐ¿ÐžÑÐŸÐº "Ð¯Ð·ÑÐº Ð¿ÐµÑÐµÐ²ÐŸÐŽÐ°",ÑÑÐŸÐ±Ñ Ð²ÑÐ±ÑÐ°ÑÑ ÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐœÑÐ¹ ÑÐ·ÑÐº Ðž Ð²Ð²ÐµÑÑÐž Ð¿ÐµÑÐµÐ²ÐµÐŽÐµÐœÐœÑÐ¹ ÑÐµÐºÑÑ Ð² ÐŸÐ±Ð»Ð°ÑÑÑ ÑÐµÐºÑÑÐ°, ÐŸÐ±ÑÐ°ÑÐ°ÑÑÑ Ðº "ÐÐ°ÑÐ°Ð»ÑÐœÐŸÐŒÑ ÑÑÐ°Ð³ÐŒÐµÐœÑÑ ÑÐµÐºÑÑÐ°",ÐµÑÐ»Ðž ÑÑÐŸ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ. ÐÐŸ ÐŸÐºÐŸÐœÑÐ°ÐœÐžÐž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ Ð¿ÐµÑÐµÐ²ÐŸÐŽ".</Text>
+<Text id="185">Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐ¹ Ð¿ÐµÑÐµÐ²ÐŸÐŽ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ Ð² ÑÐ°Ð±Ð»ÐžÑÐµ "ÐÐ°ÐŽÐ°ÐœÐœÑÐµ Ð¿ÐµÑÐµÐ²ÐŸÐŽÑ" Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ Ð¿ÐµÑÐµÐ²ÐŸÐŽ".</Text>
+<Text id="186">Ð§ÑÐŸÐ±Ñ ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ Ð¿ÐµÑÐµÐ²ÐŸÐŽ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ, ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÑÐ¹ÑÐµ Ð² ÑÐµÐºÑÑÐŸÐ²ÐŸÐ¹ ÐŸÐ±Ð»Ð°ÑÑÐž "ÐÐµÑÐµÐ²ÐµÐŽÐµÐœÐœÑÐ¹ ÑÐµÐºÑÑ" Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐ°ÐŒÐµÐœÐžÑÑ Ð¿ÐµÑÐµÐ²ÐŸÐŽ".</Text>
+</Section>
+<Section name="metadatasets">
+<Title>
+<Text id="187">Ð£ÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</Text>
+</Title>
+<Text id="188">Ð­ÑÐŸÑ ÑÐ°Ð·ÐŽÐµÐ» ÐŸÐ±ÑÑÑÐœÑÐµÑ ÐŸÐ±Ð·ÐŸÑÐœÑÑ Ð¿Ð°ÐœÐµÐ»Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. Ð "Ð Ð°Ð·ÐŽÐµÐ»Ðµ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°" ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+".</Text>
+<Text id="189">Ð­ÑÐŸ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ,ÑÑÐŸÐ±Ñ ÑÐ°ÑÑÐŒÐŸÑÑÐµÑÑ ÐœÐ°Ð±ÐŸÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+,ÐºÐŸÑÐŸÑÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹,Ðž ÑÐ»ÐµÐŒÐµÐœÑÑ,ÐºÐŸÑÐŸÑÑÐµ ÑÐ²Ð»ÑÑÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÐœÐ°Ð±ÐŸÑÐ°. ÐÑÐ±ÐµÑÐžÑÐµ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° "ÐÐŸÑÑÑÐ¿ÐœÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+",ÑÑÐŸÐ±Ñ Ð²ÐžÐŽÐµÑÑ ÐŽÐµÑÐ°Ð»Ðž ÐžÑ
+ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ².</Text>
+<Text id="190">Ð§ÑÐŸÐ±Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐŽÑÑÐ³ÐŸÐ¹ ÐœÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+ ÐŽÐ»Ñ Ð·Ð°Ð³ÑÑÐ¶ÐµÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° "ÐÐŸÐ±Ð°Ð²ÐžÑÑ ÐÐ°Ð±ÐŸÑ ÐÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+" Ðž Ð²ÑÐ±ÐµÑÐžÑÐµ ÑÐ°Ð¹Ð» Ñ ÐœÐ°Ð±ÐŸÑÐŸÐŒ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+ (.mds).</Text>
+<Text id="191">Ð ÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐœÐ°Ð±ÐŸÑÐ° ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐŸ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ Greenstone Editor for Metadata Sets (GEMS). ÐÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÐºÐœÐŸÐ¿ÐºÑ "Ð ÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ ÐÐ°Ð±ÐŸÑ ÐÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+", ÑÑÐŸÐ±Ñ Ð¿ÐŸÐ»ÑÑÐžÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ GEMS.</Text>
+<Text id="192">ÐÑÐ»Ðž ÐœÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+ Ð²Ð°ÐŒ Ð±ÐŸÐ»ÑÑÐµ ÐœÐµ ÐœÑÐ¶ÐµÐœ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ Ðž ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° "Ð£ÐŽÐ°Ð»ÐžÑÑ ÐÐ°Ð±ÐŸÑ ÐÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+". ÐÑÐ»Ðž Ð²Ñ ÐœÐ°Ð·ÐœÐ°ÑÐžÐ»Ðž ÐºÐ°ÐºÐžÐµ-Ð»ÐžÐ±ÐŸ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÐµ Ðº ÑÐ»ÐµÐŒÐµÐœÑÐ°ÐŒ Ð² ÑÐŽÐ°Ð»ÐµÐœÐœÐŸÐŒ ÐœÐ°Ð±ÐŸÑÐµ, Ñ Ð²Ð°Ñ ÑÐ¿ÑÐŸÑÑÑ ÐºÐ°Ðº Ñ ÐœÐžÐŒÐž Ð¿ÐŸÑÑÑÐ¿ÐžÑÑ Ð¿ÑÐž ÑÐ»ÐµÐŽÑÑÐµÐ¹ Ð·Ð°Ð³ÑÑÐ·ÐºÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+</Section>
+</Section>
+<Section name="producingthecollection">
+<Title>
+<Text id="193">ÐÐŸÑÑÑÐŸÐµÐœÐžÐµ ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<Text id="194">ÐÐŒÐµÑ ÑÐŸÐ±ÑÐ°ÐœÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÐŽÐ»Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð°ÐœÐœÐŸÑÐžÑÐŸÐ²Ð°Ð² ÐžÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒÐž Ðž ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÐ°Ð² ÐŽÐžÐ·Ð°Ð¹Ðœ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž,ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐµÐ¿ÐµÑÑ ÑÐŸÐ·ÐŽÐ°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ Greenstone. Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ,ÐºÐ°Ðº ÑÑÐŸ ÑÐŽÐµÐ»Ð°ÑÑ.</Text>
+<Section name="thecreateview">
+<Title>
+<Text id="195">Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ</Text>
+</Title>
+<Text id="196">Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ,ÑÑÐŸÐ±Ñ ÑÐŸÐ·ÐŽÐ°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ,Ð²ÑÐ¿ÐŸÐ»ÐœÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐµ ÑÑÐµÐœÐ°ÑÐžÐž Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Greenstone ÐžÐ· ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž, ÐºÐŸÑÐŸÑÑÑ ÐÑ Ð¿ÐŸÐŽÐ³ÐŸÑÐŸÐ²ÐžÐ»Ðž. Ð©ÐµÐ»ÑÐŸÐº ÐœÐ° "ÐÐŸÑÑÑÐŸÐµÐœÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž" ÐœÐ°ÑÐžÐœÐ°ÐµÑ Ð¿ÑÐŸÑÐµÑÑ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑÐµÐŒÑ, ÐºÐŸÑÐŸÑÐŸÐµ ÐŽÐ»Ñ ÑÑÐŸÐ³ÐŸ Ð¿ÐŸÑÑÐµÐ±ÑÐµÑÑÑ, Ð·Ð°Ð²ÐžÑÐžÑ ÐŸÑ ÑÐ°Ð·ÐŒÐµÑÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž ÑÐžÑÐ»Ð° ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÐµÐŒÑÑ
+ ÐžÐœÐŽÐµÐºÑÐŸÐ² (ÐŽÐ»Ñ ÐŸÐ³ÑÐŸÐŒÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÑÑÐŸ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐ°ÑÑ). ÐÐœÐŽÐžÐºÐ°ÑÐŸÑ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ ÑÐºÐ°Ð·ÑÐ²Ð°ÐµÑ, ÐœÐ°ÑÐºÐŸÐ»ÑÐºÐŸ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœ Ð¿ÑÐŸÑÐµÑÑ. Ð§ÑÐŸÐ±Ñ ÐŸÑÐŒÐµÐœÐžÑÑ Ð¿ÑÐŸÑÐµÑÑ Ð² Ð»ÑÐ±ÐŸÐµ Ð²ÑÐµÐŒÑ, ÐœÐ°Ð¶ÐŒÐžÑÐµ "ÐÑÐŒÐµÐœÐ° Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ".</Text>
+<Text id="197">ÐÐ°Ð¶Ð°Ð² ÐœÐ° "ÐÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÑÐ¹ Ð¿ÑÐŸÑÐŒÐŸÑÑ" Ð¿ÐŸÑÐ»Ðµ ÑÐŸÐ³ÐŸ, ÐºÐ°Ðº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð±ÑÐ»Ð° ÑÑÐ¿ÐµÑÐœÐŸ ÑÐŸÐ±ÑÐ°ÐœÐ°, ÐŒÐŸÐ¶ÐœÐŸ ÐŸÑÐºÑÑÑÑ Ð²ÐµÐ±-Ð±ÑÐ°ÑÐ·ÐµÑ Ñ Ð³Ð»Ð°Ð²ÐœÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Text id="198">Ð ÐŒÐŸÐŽÑÑÐµ Ð­ÐºÑÐ¿ÐµÑÑ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð·Ð°Ð¿ÐžÑÑ "ÐÐŸÐ³ Ð¡ÐŸÐŸÐ±ÑÐµÐœÐžÐ¹" ÑÐ»ÐµÐ²Ð°, ÑÑÐŸÐ±Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ, Ð±ÑÐ»Ðž Ð»Ðž Ð¿ÑÐµÐŽÑÐŽÑÑÐžÐµ Ð¿ÐŸÐ¿ÑÑÐºÐž ÑÐºÐŸÐœÑÑÑÑÐžÑÐŸÐ²Ð°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÑÑÐ¿ÐµÑÐœÑ ÐžÐ»Ðž ÐœÐµÑ. ÐÑÐ±ÐµÑÐžÑÐµ Ð¶ÐµÐ»Ð°ÐµÐŒÑÑ Ð·Ð°Ð¿ÐžÑÑ,ÑÐµÐ»ÐºÐ°Ñ Ð¿ÐŸ Ð²ÑÐ±ÑÐ°ÐœÐœÐŸÐ¹ ÐŽÐ°ÑÐµ Ð² ÑÐ¿ÐžÑÐºÐµ "ÐÑÑÐŸÑÐžÑ Ð·Ð°Ð¿ÐžÑÐž".</Text>
+</Section>
+<Section name="buildsettings">
+<Title>
+<Text id="199">ÐÐŒÐ¿ÐŸÑÑ Ðž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ</Text>
+</Title>
+<Text id="200">Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ, ÐºÐ°Ðº Ð¿ÐŸÐ»ÑÑÐžÑÑ ÐŽÐŸÑÑÑÐ¿ Ðº ÑÐ°Ð·Ð»ÐžÑÐœÑÐŒ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑÐŒ ÐžÐŒÐ¿ÐŸÑÑÐ° Ðž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐ°ÐŒ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ. ÐÐ° ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐµÐ¹ Ð¿ÐŸ ÐžÐŒÐ¿ÐŸÑÑÑ Ðž Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÑÐžÑÐ°Ð¹ÑÐµ Ð³Ð»Ð°Ð²Ñ 1 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone.  </Text>
+<Text id="201">Ð£Ð¿ÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÑÐ°Ð·Ð»ÐžÑÐœÑÐŒÐž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐ°ÐŒÐž ÑÐŽÐµÐ»Ð°ÐœÐŸ Ð¿ÐŸÐŽÐŸÐ±ÐœÐŸ ÑÐŸÐŒÑ ÑÐ¿ÐŸÑÐŸÐ±Ñ, ÐºÐŸÑÐŸÑÑÐ¹ ÐŸÐ¿ÐžÑÐ°Ðœ Ð¿ÑÐž "ÐÐŸÐœÑÐžÐ³ÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐž Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ²" Ð² <Reference target="plugins"/>. ÐÐµÐºÐŸÑÐŸÑÑÐµ Ð¿ÐŸÐ»Ñ ÑÑÐµÐ±ÑÑÑ ÑÐžÑÐ»ÐµÐœÐœÑÑ
+ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ². ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÑ
+ ÐžÐ»Ðž ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°ÑÑ ÐžÐ»Ðž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÑÑÑÐµÐ»ÐºÐž Ð²Ð²ÐµÑÑ
+ Ðž Ð²ÐœÐžÐ·, ÑÑÐŸÐ±Ñ ÑÐ²ÐµÐ»ÐžÑÐžÑÑ ÐžÐ»Ðž ÑÐŒÐµÐœÑÑÐžÑÑ ÑÐµÐºÑÑÐµÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ (Ð² ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ ÑÐ»ÑÑÐ°ÑÑ
+ ÐžÐœÑÐµÑÑÐµÐ¹Ñ ÐŸÐ³ÑÐ°ÐœÐžÑÐžÐ²Ð°ÐµÑ ÐŽÐžÐ°Ð¿Ð°Ð·ÐŸÐœ, Ð² ÐºÐŸÑÐŸÑÑÐ¹ ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÐŸÐ¹ÑÐž). ÐÑÑÐ³ÐžÐµ Ð¿ÐŸÐ»Ñ ÑÐ²Ð»ÑÑÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž Ð¿ÑÐž ÑÐµÐ»ÑÐºÐµ Ð¿ÐŸ ÐºÐœÐŸÐ¿ÐºÐµ (ÐÐŸÐ²ÑÐŸÑÐœÑÐ¹ ÑÐµÐ»ÑÐŸÐº ÐŽÐµÐ»Ð°ÐµÑ ÐžÑ
+ ÐœÐµÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž). </Text>
+</Section>
+</Section>
+<Section name="miscellaneous">
+<Title>
+<Text id="202">Ð Ð°Ð·ÐœÐŸÐµ</Text>
+</Title>
+<Text id="203">Ð­ÑÐŸÑ ÑÐ°Ð·ÐŽÐµÐ» ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ ÐŸÑÐŸÐ±ÐµÐœÐœÐŸÑÑÐž ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°,ÐºÐŸÑÐŸÑÑÐµ ÐœÐµ ÑÐ²ÑÐ·Ð°ÐœÑ ÐœÐž Ñ ÐºÐ°ÐºÐžÐŒ ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐžÐŒ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµÐŒ.</Text>
+<Section name="preferences">
+<Title>
+<Text id="204">ÐÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÑ</Text>
+</Title>
+<Text id="205">Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ ÐŽÐžÐ°Ð»ÐŸÐ³ Ð¿ÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÐ¹,ÐŽÐŸÑÑÑÐ¿ÐœÑÐ¹ Ð¿ÑÐž ÐŸÑÐºÑÑÑÐžÐž "Ð€Ð°Ð¹Ð»Ð°", Ð° Ð·Ð°ÑÐµÐŒ "ÐÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÐ¹".</Text>
+<Text id="206">ÐÐµÑÐ²Ð°Ñ ÐŸÐ¿ÑÐžÑ "ÐÐ±ÑÐµÐµ" - ÑÑÐŸ ÑÐµÐºÑÑÐŸÐ²ÐŸÐµ Ð¿ÐŸÐ»Ðµ ÐŽÐ»Ñ Ð²Ð²ÐµÐŽÐµÐœÐžÑ Ð°ÐŽÑÐµÑÐ° Ð²Ð°ÑÐµÐ¹ ÑÐ»ÐµÐºÑÑÐŸÐœÐœÐŸÐ¹ Ð¿ÐŸÑÑÑ. ÐÐœ Ð±ÑÐŽÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°Ðœ Ð² Ð·ÐœÐ°ÑÐµÐœÐžÐž ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+ "Ð¡ÐŸÐ·ÐŽÐ°ÑÐµÐ»Ñ" Ðž "ÐÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÑÐ¹". Ð¡Ð»ÐµÐŽÑÑÐ°Ñ ÐŸÐ¿ÑÐžÑ - ÑÑÐŸ Ð²ÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐµ ÐŒÐµÐœÑ Ñ ÑÐ·ÑÐºÐ°ÐŒÐž, Ð² ÐºÐŸÑÐŸÑÑÑ
+ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐÐœÑÐµÑÑÐµÐ¹Ñ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœ. ÐÑÐ»Ðž ÐÑ ÐžÐ·ÐŒÐµÐœÑÐµÑÐµ ÑÐ»ÐŸÐ²Ð°ÑÑ, Ð²ÑÐ±ÐžÑÐ°Ñ ÐºÐ°ÐºÐŸÐ¹-Ð»ÐžÐ±ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ°, ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ Ð¿ÐµÑÐµÐ·Ð°Ð³ÑÑÐ·ÐžÑÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ, ÑÑÐŸÐ±Ñ Ð·Ð°Ð³ÑÑÐ·ÐžÑÑ ÐœÐŸÐ²ÑÐµ ÑÑÑÐŸÐºÐž ÑÐ·ÑÐºÐ° ÐžÐ· ÑÑÐŸÐ³ÐŸ ÑÐ»ÐŸÐ²Ð°ÑÑ.</Text>
+<Text id="207">ÐÑÐ»Ðž Ð²ÑÐ±ÑÐ°ÐœÐ° "ÐÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐžÐ·Ð²Ð»ÐµÐºÐ°ÐµÐŒÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+", ÑÐ°Ð·Ð»ÐžÑÐœÐŸÐµ ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÐµ, ÑÐ²ÑÐ·Ð°ÐœÐœÐŸÐµ Ñ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒÐž, Ð²ÑÐµÐ³ÐŽÐ° Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð²ÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, ÐºÐŸÑÐŸÑÑÐµ Ð±ÑÐ»Ðž Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž ÐžÐ·Ð²Ð»ÐµÑÐµÐœÑ ÐžÐ· ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ². ÐÑÐŒÐµÐœÐ° ÑÑÐŸÐ³ÐŸ Ð²ÑÐ±ÐŸÑÐ° ÑÐºÑÑÐ²Ð°ÐµÑ ÑÑÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, Ñ
+ÐŸÑÑ ÐŸÐœÐž Ð²ÑÑ ÐµÑÑ  ÐŽÐŸÑÑÑÐ¿ÐœÑ Ð² ÑÐµÑÐµÐœÐžÐµ ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÐºÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð² ÑÐ°ÐŒÐºÐ°Ñ
+ ÐŸÐºÐŸÐœÑÐ°ÑÐµÐ»ÑÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Greenstone. ÐÑÐ»Ðž Ð²ÑÐ±ÑÐ°ÐœÐŸ "ÐÐŸÐºÐ°Ð·Ð°ÑÑ ÑÐ°Ð·ÐŒÐµÑÑ ÑÐ°Ð¹Ð»Ð°", ÑÐŸ ÑÐ°Ð·ÐŒÐµÑ ÑÐ°Ð¹Ð»Ð° Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑÑÑ ÑÑÐŽÐŸÐŒ Ñ ÐºÐ°Ð¶ÐŽÑÐŒ ÑÐ°Ð¹Ð»ÐŸÐŒ Ð² ÑÐ°Ð±ÐŸÑÐµÐŒ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²Ðµ, Ð° ÑÐ°ÐºÐ¶Ðµ Ð² ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐŒ ÐŽÐµÑÐµÐ²Ðµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð² Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑÑ
+ Gather Ðž Enrich.</Text>
+<Text id="208">ÐÐ°ÐœÐµÐ»Ñ "Ð¡Ð¿ÐŸÑÐŸÐ±" ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ ÑÑÐŸÐ²ÐœÐµÐŒ Ð¿ÐŸÐŽÑÐŸÐ±ÐœÐŸÑÑÐµÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°. ÐÐ° ÑÐ°ÐŒÐŸÐŒ ÐœÐžÐ¶ÐœÐµÐŒ ÑÑÐŸÐ²ÐœÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐŸÐº ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ "ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ Ð¿ÐŸÐŒÐŸÑÐœÐžÐº", Ð¿ÑÐž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐž ÐºÐŸÑÐŸÑÐŸÐ³ÐŸ Ð¿ÑÐŸÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð±Ð»ÐŸÐºÐžÑÐŸÐ²Ð°ÐœÐŸ, Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ, ÑÑÐµÐ±ÑÑÑÐžÐµ Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÐŸÐ³ÐŸ Ð²ÑÑÐ°Ð¶ÐµÐœÐžÑ, ÑÐºÑÑÑÑ Ðž Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑÑ ÐŒÐžÐœÐžÐŒÐ°Ð»ÑÐœÐŸ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÑÐŒ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸÐŒ Ð·Ð°Ð¿ÐžÑÐµÐ¹. ÐÐ°ÐŸÐ±ÐŸÑÐŸÑ, ÐœÐ°ÐžÐ²ÑÑÑÐ°Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐ° "Ð­ÐºÑÐ¿ÐµÑÑ" ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ ÐŽÐŸÑÑÑÐ¿ ÐºÐŸ Ð²ÑÐµÐŒ ÑÑÐµÐŽÑÑÐ²Ð°ÐŒ Ð¿ÑÐŸÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÑ, Ð²ÐºÐ»ÑÑÐ°Ñ Ð¿ÐŸÐ·ÐžÑÐžÐŸÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð¿Ð»Ð°Ð³ÐžÐœÐŸÐ² Ðž Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÐŸÐµ Ð²ÑÑÐ°Ð¶ÐµÐœÐžÐµ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ², Ð° ÑÐ°ÐºÐ¶Ðµ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð¿ÐŸÐ»ÐœÑÐ¹ Ð²ÑÑ
+ÐŸÐŽ ÐžÐ· Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÑÐŸÐ±Ñ Ð·Ð°ÑÐžÐºÑÐžÑÐŸÐ²Ð°ÑÑ Ð² Ð¶ÑÑÐœÐ°Ð»Ðµ Ð·Ð°Ð¿ÐžÑÐµÐ¹. Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐžÐ»Ðž Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ ÑÐ¿ÐŸÑÐŸÐ±Ñ, ÐºÐ»ÐžÐºÐœÐžÑÐµ ÑÐ°ÐŽÐžÐŸ-ÐºÐœÐŸÐ¿ÐºÑ, ÑÐ»ÐµÐŽÑÑÑÑÑ Ð·Ð° ÑÐ¿ÐŸÑÐŸÐ±ÐŸÐŒ, ÐºÐŸÑÐŸÑÑÐ¹ ÐžÐœÑÐµÑÐµÑÑÐµÑ ÐÐ°Ñ. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð±ÑÑÑÑÐŸ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ, ÐºÐ°ÐºÐŸÐ¹ ÑÐ¿ÐŸÑÐŸÐ± ÐÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÐµ, ÑÐ°ÑÑÐŒÐ°ÑÑÐžÐ²Ð°Ñ Ð»ÐžÐœÐµÐ¹ÐºÑ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐ¹ Ð² ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐŒ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐµ. </Text>
+<Text id="209">ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ ÐŒÐŸÐ¶ÐµÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÑÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ ÑÐµÑ
+ÐœÐŸÐ»ÐŸÐ³ÐžÑÐµÑÐºÐžÐµ Ð¿ÑÐŸÑÐµÑÑÑ Ð¿ÑÐž ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÐž, ÐºÐ°ÐºÐžÐµ ÐžÐ· ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐ¹ ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ² ÑÐ²Ð»ÑÑÑÑÑ Ð²ÐžÐŽÐžÐŒÑÐŒÐž. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐºÐ»Ð°Ð²ÐžÑÑ "Ð¢ÐµÑ
+ÐœÐŸÐ»ÐŸÐ³ÐžÑÐµÑÐºÐžÐµ Ð¿ÑÐŸÑÐµÑÑÑ", ÑÑÐŸÐ±Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ, ÐºÐ°ÐºÐžÐµ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ ÑÐ²Ð»ÑÑÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž, Ð¿ÑÐŸÐ²ÐµÑÑÑ Ð¿ÐŸÐ»Ñ ÑÑÐŽÐŸÐŒ Ñ ÑÐµÐŒÐž Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑÐŒÐž, ÐºÐŸÑÐŸÑÑÐµ ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž. ÐÐŒÐµÑÑÐŸ ÑÑÐŸÐ³ÐŸ ÐŒÐŸÐ¶ÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐžÐ¹ ÑÐ¿ÐžÑÐŸÐº Ð²ÐœÐžÐ·Ñ ÑÐºÑÐ°ÐœÐ°,ÑÑÐŸÐ±Ñ Ð²ÑÐ±ÑÐ°ÑÑ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°ÐŽÐ°ÐœÐœÑÐµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž. ÐÐ°ÐºÑÑÑÐžÐµ ÐŽÐžÐ°Ð»ÐŸÐ³Ð° Ð¿ÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÐ¹ Ð·Ð°ÐºÑÐµÐ¿Ð»ÑÐµÑ ÑÑÐž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÑÐµÑ
+ÐœÐŸÐ»ÐŸÐ³ÐžÑÐµÑÐºÐŸÐ³ÐŸ Ð¿ÑÐŸÑÐµÑÑÐ°. Ð­ÑÐž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž Ñ
+ÑÐ°ÐœÑÑÑÑ Ð²ÐŒÐµÑÑÐµ Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹,Ð° ÐœÐµ Ð² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°.</Text>
+<Text id="210">ÐÐ»Ð°Ð²ÐžÑÐ° "Ð¡ÐŸÐµÐŽÐžÐœÐµÐœÐžÐµ" Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐÐ°ÐŒ ÐžÐ·ÐŒÐµÐœÑÑÑ Ð¿ÑÑÑ Ðº Ð»ÐŸÐºÐ°Ð»ÑÐœÐŸÐŒÑ ÑÐµÑÐ²ÐµÑÑ Greenstone, ÐºÐŸÑÐŸÑÑÐ¹ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸÐ³ÐŸ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑÐŸÐŒÐµ ÑÐŸÐ³ÐŸ ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÐŒÐŸÐŽÑÐ»Ñ ÐŽÐŸÑÑÑÐ¿Ð° Ðº ÐÐœÑÐµÑÐœÐµÑÑ Ð¿ÑÐŸÐºÑÐž (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÐŽÐ»Ñ Ð·Ð°Ð³ÑÑÐ·ÐºÐž ÑÐ°Ð¹Ð»ÐŸÐ²; ÑÐŒÐŸÑÑÐž ÑÐ°Ð·ÐŽÐµÐ» <Reference target="downloadingfiles"/> ÐŽÐ»Ñ Ð¿ÐŸÐŽÑÐŸÐ±ÐœÐŸÑÑÐµÐ¹). ÐÐŸÐŒÐµÑÑÑÐµ ÑÐ»Ð°Ð³ÐŸÐ²ÑÑ ÐºÐœÐŸÐ¿ÐºÑ, ÑÑÐŸÐ±Ñ Ð²ÐºÐ»ÑÑÐžÑÑ ÐŒÐŸÐŽÑÐ»Ñ ÐŽÐŸÑÑÑÐ¿Ð°, Ðž ÑÐºÐ°Ð¶ÐžÑÐµ ÐŽÐµÑÐ°Ð»Ðž Ð°ÐŽÑÐµÑÐ° ÑÐµÑÐ²ÐµÑÐ° Ð¿ÑÐŸÐºÑÐž Ðž ÐœÐŸÐŒÐµÑ Ð¿ÐŸÑÑÐ°. ÐÐŸÐŽÑÐ»Ñ ÐŽÐŸÑÑÑÐ¿Ð° Ð±ÑÐŽÐµÑ Ð°ÐºÑÐžÐ²ÐžÑÐŸÐ²Ð°Ðœ Ð¿ÑÐž Ð·Ð°ÐºÑÑÑÐžÐž ÐŽÐžÐ°Ð»ÐŸÐ³ÐŸÐ²ÐŸÐ³ÐŸ ÐŸÐºÐœÐ° ÐÐ¿ÑÐžÐ¹.</Text>
+<Text id="211">Ð ÑÐµÑÐµÐœÐžÐµ ÑÐµÑÑÐžÐž ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ ÐŒÐŸÐ¶ÐµÑ ÐŽÐ°Ð²Ð°ÑÑ Ð¿ÑÐµÐŽÑÐ¿ÑÐµÐŽÐžÑÐµÐ»ÑÐœÑÐµ ÑÐŸÐŸÐ±ÑÐµÐœÐžÑ, ÐºÐŸÑÐŸÑÑÐµ ÐžÐœÑÐŸÑÐŒÐžÑÑÑÑ ÐÐ°Ñ ÐŸ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÑÑ
+ ÐœÐµÐ¿ÑÐµÐŽÐ²ÐžÐŽÐµÐœÐœÑÑ
+ Ð¿ÐŸÑÐ»ÐµÐŽÑÑÐ²ÐžÑÑ
+ ÐÐ°ÑÐžÑ
+ ÐŽÐµÐ¹ÑÑÐ²ÐžÐ¹. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð·Ð°Ð±Ð»ÐŸÐºÐžÑÐŸÐ²Ð°ÑÑ ÑÐŸÐŸÐ±ÑÐµÐœÐžÐµ, Ð²ÑÐ±ÐžÑÐ°Ñ Ð¿ÐŸÐ»Ðµ "ÐÐµ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÑÑ ÑÑÐŸ Ð¿ÑÐµÐŽÑÐ¿ÑÐµÐ¶ÐŽÐµÐœÐžÐµ ÑÐœÐŸÐ²Ð°". ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÐŸÐ·ÐŸÐ±ÐœÐŸÐ²ÐžÑÑ Ð¿ÐŸÑÐ²Ð»ÐµÐœÐžÐµ Ð¿ÑÐµÐŽÑÐ¿ÑÐµÐ¶ÐŽÐ°ÑÑÐžÑ
+ ÑÐŸÐŸÐ±ÑÐµÐœÐžÐ¹,ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐºÐ»Ð°Ð²ÐžÑÑ "ÐÑÐµÐŽÑÐ¿ÑÐµÐ¶ÐŽÐµÐœÐžÐµ". ÐÑÐ±ÐµÑÐžÑÐµ Ð¿ÐŸÐ»Ðµ ÑÑÐŽÐŸÐŒ Ñ Ð¿ÑÐµÐŽÑÐ¿ÑÐµÐ¶ÐŽÐ°ÑÑÐžÐŒÐž ÑÐŸÐŸÐ±ÑÐµÐœÐžÑÐŒÐž, ÐµÑÐ»Ðž ÐÑ Ñ
+ÐŸÑÐžÑÐµ ÑÐœÐŸÐ²Ð° Ð¿ÐŸÐ»ÑÑÐ°ÑÑ ÐžÑ
+.</Text>
+</Section>
+<Section name="fileassociations">
+<Title>
+<Text id="212">ÐÑÑÐŸÑÐžÐ°ÑÐžÐž ÑÐ°Ð¹Ð»Ð°</Text>
+</Title>
+<Text id="213">ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐÐœÑÐµÑÑÐµÐ¹Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐžÐµ Ð¿ÑÐžÐºÐ»Ð°ÐŽÐœÑÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ, ÑÑÐŸÐ±Ñ ÐŸÑÐºÑÑÐ²Ð°ÑÑ ÑÐ¿ÐµÑÐžÑÐžÑÐœÑÐµ ÑÐžÐ¿Ñ ÑÐ°Ð¹Ð»ÐŸÐ². Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ Ð°ÑÑÐŸÑÐžÐžÑÐŸÐ²Ð°ÐœÐœÑÐµ ÑÐ°Ð¹Ð»Ñ ÐŸÑÐºÑÑÐ²Ð°ÑÑ ÐŒÐµÐœÑ "Ð€Ð°Ð¹Ð»" Ðž ÑÐµÐ»ÐºÐ°ÑÑ "ÐÑÑÐŸÑÐžÐžÑÐŸÐ²Ð°ÐœÐœÑÐµ ÑÐ°Ð¹Ð»Ñ".</Text>
+<Text id="214">Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ Ð°ÑÑÐŸÑÐžÐ°ÑÐžÐž, Ð²ÑÐ±ÐµÑÐžÑÐµ ÑÐµÐ»ÐµÐ²ÐŸÐµ ÑÐ°ÑÑÐžÑÐµÐœÐžÐµ ÑÐ°Ð¹Ð»Ð° ÐžÐ· ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐ³ÐŸ ÑÐ¿ÐžÑÐºÐ° ÐžÐ»Ðž ÐœÐ°Ð¿ÐžÑÐžÑÐµ ÐœÐŸÐ²ÐŸÐµ ÑÐ°ÑÑÐžÑÐµÐœÐžÐµ (ÐœÐµ Ð²ÐºÐ»ÑÑÐ°Ñ "."). ÐÐ°ÑÐµÐŒ ÐžÐ»Ðž ÐœÐ°Ð¿ÐžÑÐžÑÐµ Ð² ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐŒ Ð¿ÐŸÐ»Ðµ ÐºÐŸÐŒÐ°ÐœÐŽÑ,Ð·Ð°Ð¿ÑÑÐºÐ°ÑÑÑÑ Ð¶ÐµÐ»Ð°ÑÐµÐ»ÑÐœÐŸÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ,ÐžÐ»Ðž Ð²ÑÐ±ÐµÑÐžÑÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ ÐžÐ· ÐŽÐžÐ°Ð»ÐŸÐ³ÐŸÐ²ÐŸÐ³ÐŸ ÐŸÐºÐœÐ° "ÐÑÐŸÑÐŒÐŸÑÑ". ".%1" ÐŒÐŸÐ¶ÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ Ð² ÐºÐŸÐŒÐ°ÐœÐŽÐµ Ð·Ð°Ð¿ÑÑÐºÐ°, ÑÑÐŸÐ±Ñ Ð²ÑÑÐ°Ð²ÐžÑÑ ÐžÐŒÑ ÑÐ°Ð¹Ð»Ð°, ÐºÐŸÑÐŸÑÑÐ¹ ÐŽÐŸÐ»Ð¶ÐµÐœ ÐŸÑÐºÑÑÑÑÑÑ. ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐŸÐœÐž Ð·Ð°Ð¿ÐŸÐ»ÐœÐµÐœÑ,Ð¿ÑÐœÐºÑ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ" ÑÑÐ°ÐœÐŸÐ²ÐžÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒ Ðž ÐŒÐŸÐ¶ÐœÐŸ ÑÐµÐ»ÑÐºÐŸÐŒ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ Ð°ÑÑÐŸÑÐžÐ°ÑÐžÑ.  </Text>
+<Text id="215">Ð§ÑÐŸÐ±Ñ ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ Ð°ÑÑÐŸÑÐžÐ°ÑÐžÑ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÑÑÑÐµÑÑÐ²ÑÑÑÐµÐµ ÑÐ°ÑÑÐžÑÐµÐœÐžÐµ ÑÐ°Ð¹Ð»Ð°. ÐÑÐ±Ð°Ñ ÑÑÑÐµÑÑÐ²ÑÑÑÐ°Ñ ÐºÐŸÐŒÐ°ÐœÐŽÐ° ÑÐ²ÑÐ·Ðž Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑÑÑ Ð² Ð¿ÐŸÐ»Ðµ Ð·Ð°Ð¿ÑÑÐºÐ° ÐºÐŸÐŒÐ°ÐœÐŽ. ÐÑÑÐµÐŽÐ°ÐºÑÐžÑÑÐ¹ÑÐµ ÐµÐµ Ðž Ð·Ð°ÑÐµÐŒ ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐ°ÐŒÐµÐœÐžÑÑ".</Text>
+<Text id="216">Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ Ð°ÑÑÐŸÑÐžÐ°ÑÐžÑ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÑÑÑÐµÑÑÐ²ÑÑÑÐµÐµ ÑÐ°ÑÑÐžÑÐµÐœÐžÐµ ÑÐ°Ð¹Ð»Ð° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ".(Ð Ð°ÑÑÐžÑÐµÐœÐžÐµ ÑÐ°Ð¹Ð»Ð° ÐŸÑÑÐ°ÐµÑÑÑ Ð² ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐŒ ÑÐ¿ÐžÑÐºÐµ "ÐÐ»Ñ ÐŸÐºÐŸÐœÑÐ°ÐœÐžÑ ÑÐ°Ð¹Ð»ÐŸÐ²").</Text>
+<Text id="217">ÐÑÐŸÑÐžÐ°ÑÐžÐ²ÐœÑÐµ ÑÐ°Ð¹Ð»Ñ Ñ
+ÑÐ°ÐœÑÑÑÑ Ð² Ð³Ð»Ð°Ð²ÐœÐŸÐ¹ Ð¿Ð°Ð¿ÐºÐµ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°, Ð² ÑÐ°Ð¹Ð»Ðµ, ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒÐŸÐŒ "associations.xml".</Text>
+</Section>
+<Section name="exportingcollections">
+<Title>
+<Text id="218">Ð­ÐºÑÐ¿ÐŸÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐœÐ° CD/DVD</Text>
+</Title>
+<Text id="219">Greenstone ÐŒÐŸÐ¶ÐµÑ ÑÐºÑÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÐŸÐŽÐœÑ ÐžÐ»Ðž Ð±ÐŸÐ»ÐµÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ð² ÑÐ°ÐŒÐŸÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÑÑÐžÐ¹ÑÑ CD/DVD Ð¿ÐŸÐŽ Windows. Ð§ÑÐŸÐ±Ñ ÑÑÐŸ ÑÐŽÐµÐ»Ð°ÑÑ, ÐŽÐŸÐ»Ð¶ÐµÐœ  Ð±ÑÑÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ Ð¿Ð°ÐºÐµÑ "Ð­ÐºÑÐ¿ÐŸÑÑ Ð² CD-ROM". ÐÐœ ÐœÐµ Ð²ÐºÐ»ÑÑÐµÐœ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ, Ð¿ÐŸÑÑÐŸÐŒÑ ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐÐ°ÑÑ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÑ, ÑÑÐŸÐ±Ñ ÐµÐ³ÐŸ Ð²ÐºÐ»ÑÑÐžÑÑ.</Text>
+<Text id="220">Ð§ÑÐŸÐ±Ñ ÑÐºÑÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐŸÑÐºÑÐŸÐ¹ÑÐµ ÐŒÐµÐœÑ "Ð€Ð°Ð¹Ð»" Ðž Ð²ÑÐ±ÐµÑÐžÑÐµ "Ð­ÐºÑÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ Ð² CD-ROM/DVD...". ÐÐŸÑÐ²Ð»ÑÐµÑÑÑ ÑÐ¿ÐžÑÐŸÐº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÑÐŸÐ±ÑÐ°ÐœÐžÐ¹ Greenstone; ÑÐµÐ»ÐºÐœÐžÑÐµ ÐœÐ° Ð»ÑÐ±ÐŸÐ¹, ÑÑÐŸÐ±Ñ ÑÐ²ÐžÐŽÐµÑÑ ÐµÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ. ÐÐŸÐŒÐµÑÑÑÐµ Ð²ÑÐ±ÑÐ°ÐœÐœÑÐµ Ð¿ÐŸÐ»Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐŽÐ»Ñ ÑÐºÑÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²Ð²ÐµÑÑÐž ÐžÐŒÑ CD/DVD Ð² Ð¿ÐŸÐ»Ðµ: ÑÑÐŸ ÑÐŸ, ÑÑÐŸ Ð¿ÐŸÑÐ²ÐžÑÑÑ Ð² ÑÑÐ°ÑÑÐŸÐ²ÐŸÐŒ ÐŒÐµÐœÑ, ÐºÐŸÐ³ÐŽÐ° CD/DVD Ð±ÑÐŽÐµÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ. ÐÐ°ÑÐµÐŒ ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð­ÐºÑÐ¿ÐŸÑÑ". ÐÑÐŸÑÐµÑÑ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐŒÐœÐŸÐ³ÐžÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² Ðž ÐŒÐŸÐ¶ÐµÑ Ð·Ð°ÐœÑÑÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐŒÐžÐœÑÑ.</Text>
+<Text id="221">ÐÐŸÑÐ»Ðµ ÐŸÐºÐŸÐœÑÐ°ÐœÐžÑ Greenstone Ð¿ÐŸÐºÐ°Ð¶ÐµÑ ÐžÐŒÑ Ð¿Ð°Ð¿ÐºÐž, ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐµÐ¹ ÑÐºÑÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÐœÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ Ð¿ÐžÑÑÑÐžÐ¹ ÐºÐŸÐŒÐ¿Ð°ÐºÑ-ÐŽÐžÑÐº ÐŽÐ»Ñ ÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐµÐ³ÐŸ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÐœÐ° ÑÐžÑÑÑÐ¹ CD/DVD.</Text>
+</Section>
+</Section>
+</Document>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/help_index.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/help_index.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/help_index.xml	(revision 13928)
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Document><Section name="introduction"><Title>ÐÐ²ÐµÐŽÐµÐœÐžÐµ</Title><Section name="ofmiceandmenus"><Title>ÐÑÑÑ Ðž ÐÐµÐœÑ</Title></Section><Section name="howtoavoidthisdocument"><Title>ÐÐ°Ðº ÐžÐ·Ð±ÐµÐ¶Ð°ÑÑ ÑÑÐµÐœÐžÑ ÑÑÐŸÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°</Title></Section></Section><Section name="startingoff"><Title>ÐÐŸ ÑÑÐ°ÑÑÐ°</Title><Section name="creatingacollection"><Title>Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Title></Section><Section name="savingacollection"><Title>Ð¡ÐŸÑ
+ÑÐ°ÐœÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Title></Section><Section name="openingacollection"><Title>ÐÑÐºÑÑÑÐžÐµ ÑÑÑÐµÑÑÐ²ÑÑÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Title></Section><Section name="deletingcollections"><Title>Ð£ÐŽÐ°Ð»ÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹</Title></Section></Section><Section name="downloadingfiles"><Title>ÐÐ°Ð³ÑÑÐ·ÐžÑÑ ÑÐ°Ð¹Ð»Ñ ÐžÐ· ÐžÐœÑÐµÑÐœÐµÑ</Title><Section name="themirrorview"><Title>ÐÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐÐ°Ð³ÑÑÐ·ÐžÑÑ</Title></Section></Section><Section name="collectingfiles"><Title>Ð¡Ð±ÐŸÑ ÑÐ°Ð¹Ð»ÐŸÐ² ÐŽÐ»Ñ ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Title><Section name="thegatherview"><Title>ÐÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐœÐ°ÐºÐŸÐ¿ÐžÑÐµÐ»Ñ</Title></Section><Section name="creatingfolders"><Title>Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ Ð¿Ð°Ð¿ÐŸÐº</Title></Section><Section name="addingfiles"><Title>ÐÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÐµ ÑÐ°Ð¹Ð»ÐŸÐ²</Title></Section><Section name="removingfiles"><Title>Ð£ÐŽÐ°Ð»ÐµÐœÐžÐµ ÑÐ°Ð¹Ð»ÐŸÐ²</Title></Section><Section name="filteringthetree"><Title>Ð€ÐžÐ»ÑÑÑÐŸÐ²Ð°ÐœÐžÐµ ÐŽÐµÑÐµÐ²Ð°</Title></Section></Section><Section name="enrichingacollection"><Title>ÐÐ±ÐŸÐ³Ð°ÑÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒÐž</Title><Section name="theenrichview"><Title>ÐÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐŸÐ±ÐŸÐ³Ð°ÑÐµÐœÐžÑ</Title></Section><Section name="selectingmetadatasets"><Title>ÐÑÐ±ÐŸÑ ÐœÐ°Ð±ÐŸÑÐŸÐ² ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</Title></Section><Section name="appendingmetadata"><Title>ÐÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</Title></Section><Section name="addingpreviouslydefinedmetadata"><Title>ÐÐŸÐ±Ð°Ð²Ð»ÐœÐžÐµ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</Title></Section><Section name="updatingmetadata"><Title>ÐÐ·ÐŒÐµÐœÐžÑÑ ÐžÐ»Ðž ÑÐŽÐ°Ð»ÐžÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ</Title></Section><Section name="reviewingmetadata"><Title>ÐÑÐŸÑÐŒÐŸÑÑ Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</Title></Section><Section name="importingpreviouslyassignedmetadata"><Title>ÐÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</Title></Section></Section><Section name="designingacollection"><Title>ÐÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Title><Section name="thedesignview"><Title>ÐÐžÐŽ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°</Title></Section><Section name="generalsettings"><Title>ÐÐ±ÑÐµÐµ</Title></Section><Section name="plugins"><Title>ÐÐ»Ð°Ð³ÐžÐœÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°</Title></Section><Section name="searchtypes"><Title>ÐÐžÐŽÑ Ð¿ÐŸÐžÑÐºÐ°</Title></Section><Section name="searchindexes"><Title>ÐÐœÐŽÐµÐºÑÑ Ð¿ÐŸÐžÑÐºÐ°</Title></Section><Section name="partitionindexes"><Title>ÐÐœÐŽÐµÐºÑÑ ÑÐ°Ð·Ð±ÐžÐµÐœÐžÑ</Title><Section name="definefilters"><Title>ÐÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÑÐžÐ»ÑÑÑÑ</Title></Section><Section name="assignpartitions"><Title>ÐÐ°Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ</Title></Section><Section name="assignlanguages"><Title>ÐÐ°ÐŽÐ°ÐœÐœÑÐµ ÑÐ·ÑÐºÐž</Title></Section></Section><Section name="xcollectionsearching"><Title>ÐÐŸÐžÑÐº Ð² Ð¿ÐµÑÐµÑÐµÐºÐ°ÑÑÐžÑ
+ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÑ
+</Title></Section><Section name="classifiers"><Title>ÐÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°</Title></Section><Section name="formatstatements"><Title>ÐÑÐŸÐ±ÐµÐœÐœÐŸÑÑÐž ÑÐŸÑÐŒÐ°ÑÐ°</Title></Section><Section name="translatetext"><Title>ÐÐµÑÐµÐ²ÐŸÐŽ ÑÐµÐºÑÑÐ°</Title></Section><Section name="metadatasets"><Title>Ð£ÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</Title></Section></Section><Section name="producingthecollection"><Title>ÐÐŸÑÑÑÐŸÐµÐœÐžÐµ ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Title><Section name="thecreateview"><Title>Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ</Title></Section><Section name="buildsettings"><Title>ÐÐŒÐ¿ÐŸÑÑ Ðž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ</Title></Section></Section><Section name="miscellaneous"><Title>Ð Ð°Ð·ÐœÐŸÐµ</Title><Section name="preferences"><Title>ÐÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÑ</Title></Section><Section name="fileassociations"><Title>ÐÑÑÐŸÑÐžÐ°ÑÐžÐž ÑÐ°Ð¹Ð»Ð°</Title></Section><Section name="exportingcollections"><Title>Ð­ÐºÑÐ¿ÐŸÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐœÐ° CD/DVD</Title></Section></Section></Document>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/howtoavoidthisdocument.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/howtoavoidthisdocument.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/howtoavoidthisdocument.htm	(revision 13928)
@@ -0,0 +1,20 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="howtoavoidthisdocument"><font face="Verdana" size="5"><strong>1.2: ÐÐ°Ðº ÐžÐ·Ð±ÐµÐ¶Ð°ÑÑ ÑÑÐµÐœÐžÑ ÑÑÐŸÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>ÐÐµ ÑÐžÑÐ°Ð¹ÑÐµ ÑÑÐŸÑ ÑÐµÐºÑÑ Ð¿ÐŸÐŒÐŸÑÐž Ð¿ÐŸÐ»ÐœÐŸÑÑÑÑ! ÐÐŸÑÑÐ°ÑÐŸÑÐœÐŸ Ð¿ÑÐŸÑÐµÑÑÑ, ÐºÐ°Ðº ÑÑÐŒÐµÑÑ Ð¿ÐŸÐ»ÑÑÐžÑÑ Ð¿ÐŸÐŒÐŸÑÑ, ÐºÐŸÐ³ÐŽÐ° ÐÑ ÐœÑÐ¶ÐŽÐ°ÐµÑÐµÑÑ Ð² ÑÑÐŸÐŒ.  </p>
+<p>ÐÑÐœÐºÑÑ ÐŒÐµÐœÑ "ÐÐŸÐŒÐŸÑÑ" ÑÐºÐ°Ð·ÑÐ²Ð°ÑÑ ÑÐµ ÑÐ°Ð·ÐŽÐµÐ»Ñ,ÐºÐŸÑÐŸÑÑÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐœÐ°ÐžÐ±ÐŸÐ»ÐµÐµ Ð°ÐŽÐµÐºÐ²Ð°ÑÐœÑÐŒÐž ÐŽÐ»Ñ Ð¿ÐŸÐŒÐŸÑÐž, Ðž ÑÐŸÐ¿ÑÐŸÐ²ÐŸÐ¶ÐŽÐ°ÑÑÑÑ ÐœÐµÐ±ÐŸÐ»ÑÑÐžÐŒ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµÐŒ ÐºÐœÐžÐ³Ðž  </p>
+<p>ÐÐ»Ñ ÐŒÐœÐŸÐ³ÐžÑ
+ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ, ÐµÑÐ»Ðž ÐÑ ÑÐ°Ð·ÐŒÐµÑÐ°ÐµÑÐµ ÐŒÑÑÑ ÐœÐ° ÐœÐžÑ
+,Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ  "Ð¿ÐŸÐŽÑÐºÐ°Ð·ÐºÐ°",ÐºÐŸÑÐŸÑÐ°Ñ ÐŸÐ±ÑÑÑÐœÑÐµÑ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ,ÐºÐŸÑÐŸÑÑÐµ ÐŸÐœÐž Ð²ÑÐ¿ÐŸÐ»ÐœÑÑÑ  </p>
+<p>ÐÐµÑÐµÐŽ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐŒ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐŸÐŒ, ÑÐœÐ°ÑÐ°Ð»Ð° Ð¿ÑÐŸÑÑÐžÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÑÐžÑ Greenstone/</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/importingpreviouslyassignedmetadata.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/importingpreviouslyassignedmetadata.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/importingpreviouslyassignedmetadata.htm	(revision 13928)
@@ -0,0 +1,46 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="importingpreviouslyassignedmetadata"><font face="Verdana" size="5"><strong>5.7: ÐÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÑÐ°ÑÑÐºÐ°Ð·Ð°ÐœÐŸ, ÐºÐ°Ðº ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÐµ ÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐœÑÐµ ÑÐ°ÐœÑÑÐµ. Ð ÐµÑÑ ÐžÐŽÐµÑ ÐŸ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+, ÐºÐŸÑÐŸÑÑÐµ Ð±ÑÐ»Ðž ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÑ Ðº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÐ°ÐœÑÑÐµ.</p>
+<p>ÐÑÐ»Ðž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ð² ÑÐŸÑÐŒÐµ,ÑÐ°ÑÐ¿ÐŸÐ·ÐœÐ°Ð²Ð°ÐµÐŒÐŸÐ¹ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐŒ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐŸÐŒ,Ð±ÑÐ»Ðž Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°ÐŽÐ°ÐœÑ ÑÐ°Ð¹Ð»Ñ - ÐœÐ°Ð¿ÑÐžÐŒÐµÑ,ÐºÐŸÐ³ÐŽÐ° ÐÑ Ð²ÑÐ±ÐžÑÐ°ÐµÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÐžÐ· ÑÑÑÐµÑÑÐ²ÑÑÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Greenstone - ÐŸÐœÐž ÐžÐŒÐ¿ÐŸÑÑÐžÑÑÑÑÑÑ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž,ÐºÐŸÐ³ÐŽÐ° ÐÑ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑÐµ ÑÐ°Ð¹Ð».Ð§ÑÐŸÐ±Ñ ÑÐŽÐµÐ»Ð°ÑÑ ÑÑÐŸ, ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœÑ Ð² ÑÑÑÐ°ÐœÐŸÐ²ÐºÐ°Ñ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+,ÐŽÐŸÑÑÑÐ¿ÐœÑÑ
+ Ð² ÑÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</p>
+<p>ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð·Ð°Ð¿ÑÐ°ÑÐžÐ²Ð°ÐµÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ.ÐÐ°Ð¿ÑÐŸÑ ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÐºÑÐ°ÑÐºÐžÐµ ÐžÐœÑÑÑÑÐºÑÐžÐž Ðž Ð·Ð°ÑÐµÐŒ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐžÐŒÑ ÑÐ»ÐµÐŒÐµÐœÑÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+,ÐºÐŸÑÐŸÑÑÐµ ÐžÐŒÐ¿ÐŸÑÑÐžÑÑÑÑÑÑ,ÐºÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐŸÐœ Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ Ð² ÐžÑÑ
+ÐŸÐŽÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ.Ð­ÑÐŸ Ð¿ÐŸÐ»Ðµ ÐœÐµ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐŸ ÐžÐ»Ðž ÐžÐ·ÐŒÐµÐœÐµÐœÐŸ.ÐÐ°ÑÐµÐŒ ÐÑ Ð²ÑÐ±ÐžÑÐ°ÐµÑÐµ,ÐºÐ°ÐºÐžÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐœÐŸÐ²ÐŸÐ³ÐŸ ÑÐ»ÐµÐŒÐµÐœÑÐ° ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœÑ,Ð° Ð·Ð°ÑÐµÐŒ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐ¹ ÑÐ»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ð² ÑÑÐžÑ
+ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐ°Ñ
+.Ð¡ÐžÑÑÐµÐŒÐ° Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž Ð²ÑÐ±ÐžÑÐ°ÐµÑ ÑÐ°ÐŒÐŸÐµ Ð±Ð»ÐžÐ·ÐºÐŸÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐµ Ð² ÑÐµÑÐŒÐžÐœÐ°Ñ
+ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž Ðž ÑÐ»ÐµÐŒÐµÐœÑÐ° ÐŽÐ»Ñ ÐœÐŸÐ²ÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. </p>
+<p>ÐÑÐŸÐ²ÐµÑÐžÐ² ÑÑÐž ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœÐžÑ,ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐ±ÑÐ°ÑÑ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ",ÑÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐœÐŸÐ²ÑÐ¹ ÑÐ»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ðº Ð²ÑÐ±ÑÐ°ÐœÐœÑÐŒ ÐœÐ°Ð±ÐŸÑÐ°ÐŒ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+.Ð­ÑÐŸ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸ ÑÐŸÐ»ÑÐºÐŸ ÑÐŸÐ³ÐŽÐ°,ÐºÐŸÐ³ÐŽÐ° ÐŸÑÑÑÑÑÑÐ²ÑÐµÑ ÑÐ»ÐµÐŒÐµÐœÑ Ñ ÑÐµÐŒ Ð¶Ðµ ÑÐ°ÐŒÑÐŒ ÐžÐŒÐµÐœÐµÐŒ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ Ð²ÑÐ±ÑÐ°ÐœÐœÑÑ
+ ÑÑÑÐ°ÐœÐŸÐ²ÐŸÐº; "ÐÐ±ÑÐµÐŽÐžÐœÐžÑÑ" ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ Ð¿ÑÐžÑÐŸÐµÐŽÐžÐœÐµÐœÐžÐµ ÐœÐŸÐ²ÐŸÐ³ÐŸ ÑÐ»ÐµÐŒÐµÐœÑÐ° Ðº ÑÐ¶Ðµ ÑÐ°ÐœÐµÐµ Ð²ÑÐ±ÑÐ°ÐœÐœÐŸÐŒÑ  Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐŒ;ÐœÐ°ÐºÐŸÐœÐµÑ, "ÐÐµ ÑÑÐžÑÑÐ²Ð°ÑÑ", ÑÑÐŸÐ±Ñ ÐœÐµ ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÐœÐžÐºÐ°ÐºÐžÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ñ ÑÑÐžÐŒ ÐžÐŒÐµÐœÐµÐŒ ÑÐ»ÐµÐŒÐµÐœÑÐ°. ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÐ»Ðž,ÐºÐ°Ðº ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÐœÐµÐºÐŸÑÐŸÑÑÑ ÑÐ°ÑÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, Ð·Ð°Ð¿ÐžÑÐ°ÐœÐœÐ°Ñ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÑÐŸÑ
+ÑÐ°ÐœÑÐµÑÑÑ ÐœÐ° Ð²ÑÐµÐŒÑ ÑÑÑÐµÑÑÐ²ÐŸÐ²Ð°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</p>
+<p>ÐÐ»Ñ ÐŽÐµÑÐ°Ð»ÐµÐ¹ ÐŸÑÐœÐŸÑÐžÑÐµÐ»ÑÐœÐŸ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ð² metadata.xml, ÐºÐŸÑÐŸÑÑÐ¹ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð² Greenstone ÐŽÐ»Ñ Ñ
+ÑÐ°ÐœÐµÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÑÐŒ.Ð³Ð»Ð°Ð²Ñ 2 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/introduction.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/introduction.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/introduction.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="introduction"><font face="Verdana" size="5"><strong>1: ÐÐ²ÐµÐŽÐµÐœÐžÐµ</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Greenstone - ÑÑÐŸ ÐžÐœÑÑÑÑÐŒÐµÐœÑ ÐŽÐ»Ñ ÑÐ±ÐŸÑÐ° Ðž ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ñ Ð¿ÐŸÑÐ»ÐµÐŽÑÑÑÐžÐŒ ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÑÐžÑÑÐŸÐ²ÑÑ
+ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐº.ÐÐœ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ ÐŽÐŸÑÑÑÐ¿ Ðº ÑÑÐœÐºÑÐžÐŸÐœÐ°Ð»ÑÐœÑÐŒ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑÐŒ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐ³ÐŸ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Greenstone Ð³ÑÐ°ÑÐžÑÐµÑÐºÐžÐŒ Ð¿ÑÑÐµÐŒ Ðž ÑÐ°Ð±ÐŸÑÐŸÐ¹ ÐŒÑÑÑÑ.</p>
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/metadatasets.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/metadatasets.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/metadatasets.htm	(revision 13928)
@@ -0,0 +1,33 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="metadatasets"><font face="Verdana" size="5"><strong>6.11: Ð£ÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð­ÑÐŸÑ ÑÐ°Ð·ÐŽÐµÐ» ÐŸÐ±ÑÑÑÐœÑÐµÑ ÐŸÐ±Ð·ÐŸÑÐœÑÑ Ð¿Ð°ÐœÐµÐ»Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. Ð "Ð Ð°Ð·ÐŽÐµÐ»Ðµ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°" ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+".</p>
+<p>Ð­ÑÐŸ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ,ÑÑÐŸÐ±Ñ ÑÐ°ÑÑÐŒÐŸÑÑÐµÑÑ ÐœÐ°Ð±ÐŸÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+,ÐºÐŸÑÐŸÑÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹,Ðž ÑÐ»ÐµÐŒÐµÐœÑÑ,ÐºÐŸÑÐŸÑÑÐµ ÑÐ²Ð»ÑÑÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÐœÐ°Ð±ÐŸÑÐ°. ÐÑÐ±ÐµÑÐžÑÐµ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° "ÐÐŸÑÑÑÐ¿ÐœÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+",ÑÑÐŸÐ±Ñ Ð²ÐžÐŽÐµÑÑ ÐŽÐµÑÐ°Ð»Ðž ÐžÑ
+ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ².</p>
+<p>Ð§ÑÐŸÐ±Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐŽÑÑÐ³ÐŸÐ¹ ÐœÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+ ÐŽÐ»Ñ Ð·Ð°Ð³ÑÑÐ¶ÐµÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° "ÐÐŸÐ±Ð°Ð²ÐžÑÑ ÐÐ°Ð±ÐŸÑ ÐÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+" Ðž Ð²ÑÐ±ÐµÑÐžÑÐµ ÑÐ°Ð¹Ð» Ñ ÐœÐ°Ð±ÐŸÑÐŸÐŒ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+ (.mds).</p>
+<p>Ð ÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐœÐ°Ð±ÐŸÑÐ° ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐŸ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ Greenstone Editor for Metadata Sets (GEMS). ÐÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÐºÐœÐŸÐ¿ÐºÑ "Ð ÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ ÐÐ°Ð±ÐŸÑ ÐÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+", ÑÑÐŸÐ±Ñ Ð¿ÐŸÐ»ÑÑÐžÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ GEMS.</p>
+<p>ÐÑÐ»Ðž ÐœÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+ Ð²Ð°ÐŒ Ð±ÐŸÐ»ÑÑÐµ ÐœÐµ ÐœÑÐ¶ÐµÐœ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ Ðž ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° "Ð£ÐŽÐ°Ð»ÐžÑÑ ÐÐ°Ð±ÐŸÑ ÐÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+". ÐÑÐ»Ðž Ð²Ñ ÐœÐ°Ð·ÐœÐ°ÑÐžÐ»Ðž ÐºÐ°ÐºÐžÐµ-Ð»ÐžÐ±ÐŸ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÐµ Ðº ÑÐ»ÐµÐŒÐµÐœÑÐ°ÐŒ Ð² ÑÐŽÐ°Ð»ÐµÐœÐœÐŸÐŒ ÐœÐ°Ð±ÐŸÑÐµ, Ñ Ð²Ð°Ñ ÑÐ¿ÑÐŸÑÑÑ ÐºÐ°Ðº Ñ ÐœÐžÐŒÐž Ð¿ÐŸÑÑÑÐ¿ÐžÑÑ Ð¿ÑÐž ÑÐ»ÐµÐŽÑÑÐµÐ¹ Ð·Ð°Ð³ÑÑÐ·ÐºÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/miscellaneous.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/miscellaneous.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/miscellaneous.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="miscellaneous"><font face="Verdana" size="5"><strong>8: Ð Ð°Ð·ÐœÐŸÐµ</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð­ÑÐŸÑ ÑÐ°Ð·ÐŽÐµÐ» ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ ÐŸÑÐŸÐ±ÐµÐœÐœÐŸÑÑÐž ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°,ÐºÐŸÑÐŸÑÑÐµ ÐœÐµ ÑÐ²ÑÐ·Ð°ÐœÑ ÐœÐž Ñ ÐºÐ°ÐºÐžÐŒ ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐžÐŒ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµÐŒ.</p>
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/ofmiceandmenus.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/ofmiceandmenus.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/ofmiceandmenus.htm	(revision 13928)
@@ -0,0 +1,33 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="ofmiceandmenus"><font face="Verdana" size="5"><strong>1.1: ÐÑÑÑ Ðž ÐÐµÐœÑ</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð­ÑÐŸÑ ÑÐ°Ð·ÐŽÐµÐ» ÐŽÐ°ÐµÑ Ð±Ð°Ð·ÐŸÐ²ÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ Ð²Ð·Ð°ÐžÐŒÐŸÐŽÐµÐ¹ÑÑÐ²ÐžÐž Ñ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐŸÐŒ  Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž. ÐÑÐ»Ðž ÐÑ Ð·ÐœÐ°ÐºÐŸÐŒÑ Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ°ÐŒÐž ÑÐžÐ¿Ð° Internet Explorer ÐžÐ»Ðž Microsoft office, Ð»ÐµÐ³ÐºÐŸ ÐŸÐ±ÑÐ°ÑÐ°ÐµÑÐµÑÑ Ñ ÐŒÑÑÑÑ Ðž ÐŒÐµÐœÑ, Ð¿ÑÐŸÐ¿ÑÑÑÐžÑÐµ <a href="howtoavoidthisdocument.htm">ÐÐ°Ðº ÐžÐ·Ð±ÐµÐ¶Ð°ÑÑ ÑÑÐµÐœÐžÑ ÑÑÐŸÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°</a>.</p>
+<p>ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÐµÑ ÑÐŸÐ³Ð»Ð°ÑÐµÐœÐžÑÐŒ Windows Microsoft Ðž ÑÑÐµÐ±ÑÐµÑ ÐŸÐ±ÑÑÐœÐŸÐ³ÐŸ Ð·ÐœÐ°ÐœÐžÑ Windows.   </p>
+<p>ÐÑÐ±Ð°Ñ ÑÐ°ÑÑÑ ÑÐºÑÐ°ÐœÐ°, Ñ ÐºÐŸÑÐŸÑÐŸÐ¹ ÐÑ Ð²Ð·Ð°ÐžÐŒÐŸÐŽÐµÐ¹ÑÑÐ²ÑÐµÑÐµ, ÑÐžÐ¿Ð° ÐºÐœÐŸÐ¿ÐºÐž ÐžÐ»Ðž ÐŸÐ±Ð»Ð°ÑÑÐž ÑÐµÐºÑÑÐ°,ÐœÐ°Ð·ÑÐ²Ð°ÐµÑÑÑ ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÐµÐŒ. Ð Ð»ÑÐ±ÐŸÐµ Ð·Ð°ÐŽÐ°ÐœÐœÐŸÐµ Ð²ÑÐµÐŒÑ ÐŸÐŽÐžÐœ ÑÐ»ÐµÐŒÐµÐœÑ ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ, ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒÑÐ¹ "ÑÐŸÐºÑÑ",Ð²ÑÐŽÐµÐ»ÑÐµÑÑÑ Ð¿ÐŸÐŽÑÐ²ÐµÑÐºÐŸÐ¹ Ðž ÐŸÑÐºÐ»ÐžÐºÐ°ÐµÑÑÑ ÐœÐ° ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ ÐºÐ»Ð°Ð²ÐžÐ°ÑÑÑÑ. ÐÐµÑÐºÐŸÐ»ÑÐºÐŸ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑ ÐÐ°ÐŒ Ð²ÑÐ±ÐžÑÐ°ÑÑ ÑÑÐ°ÑÑÐºÐž, ÐºÐŸÑÐŸÑÑÐµ Ð²ÑÐŽÐµÐ»ÑÑÑÑÑ ÑÐµÐŒÐœÐŸÑÐžÐœÐžÐŒ ÑÐ²ÐµÑÐŸÐŒ. ÐÐµÐºÐŸÑÐŸÑÑÐµ ÑÐ»ÐµÐŒÐµÐœÑÑ ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ ÐŸÑÐŸÐ±ÑÐ°Ð¶Ð°ÑÑÑÑ Ñ Ð¿ÐŸÐœÐžÐ¶ÐµÐœÐœÐŸÐ¹ ÑÑÐºÐŸÑÑÑÑ, Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°Ñ ÑÐµÐŒ ÑÐ°ÐŒÑÐŒ, ÑÑÐŸ ÐŸÐœÐž Ð·Ð°Ð±Ð»ÐŸÐºÐžÑÐŸÐ²Ð°ÐœÑ.</p>
+<p>ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÐµÑÐµÐŒÐµÑÐ°ÑÑÑÑ Ðž ÐŽÐµÐ¹ÑÑÐ²ÐŸÐ²Ð°ÑÑ  Ð»ÐµÐ²ÐŸÐ¹ ÐžÐ»Ðž Ð¿ÑÐ°Ð²ÐŸÐ¹ ÐºÐœÐŸÐ¿ÐºÐ°ÐŒÐž ÐŒÑÑÐž ÐŸÐ±ÑÑÐœÑÐŒ ÑÐ¿ÐŸÑÐŸÐ±ÐŸÐŒ. ÐÐœÐŸÐ³ÐžÐµ ÐºÐŸÐŒÐ¿ÐŸÐœÐµÐœÑÑ ÑÐ°ÐºÐ¶Ðµ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑ ÐÐ°ÐŒ "ÑÑÐœÑÑÑ" ÐžÑ
+, ÐœÐ°Ð¶ÐžÐŒÐ°Ñ Ðž ÑÐŽÐµÑÐ¶ÐžÐ²Ð°Ñ Ð»ÐµÐ²ÑÑ ÐºÐœÐŸÐ¿ÐºÑ ÐŒÑÑÐž, Ð¿ÐµÑÐµÐŒÐµÑÐ°ÑÑ ÐžÑ
+ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÐŒÑÑÐž Ðž ÐŸÑÑÐ°Ð²ÐžÑÑ ÐžÑ
+ Ð² ÐŽÑÑÐ³ÐŸÐŒ ÐŒÐµÑÑÐµ, ÐŸÑÐ¿ÑÑÐºÐ°Ñ ÐºÐœÐŸÐ¿ÐºÑ. ÐÐŸÑÐµÐœÑÐžÐ°Ð»ÑÐœÑÐµ ÐŸÐ±ÑÐµÐºÑÑ ÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐžÐ·ÐŒÐµÐœÑÑÑ ÑÐ²ÐŸÐ¹ Ð²ÐžÐŽ, ÐºÐŸÐ³ÐŽÐ° ÐºÐŸÐŒÐ¿ÐŸÐœÐµÐœÑ ÑÐºÐŸÐ»ÑÐ·ÐžÑ Ð¿ÐŸ ÐœÐžÐŒ.  </p>
+<p>ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐºÐ»Ð°Ð²ÐžÐ°ÑÑÑÑ ÐŽÐ»Ñ Ð·Ð°Ð¿ÐžÑÐž Ð² ÐŸÐ±Ð»Ð°ÑÑÐž ÑÐµÐºÑÑÐ°. ÐÐ»ÑÑÐµÑÐœÐ°ÑÐžÐ²Ñ ÐºÐ»Ð°Ð²ÐžÐ°ÑÑÑÐµ ÐŽÐŸÑÑÑÐ¿ÐœÑ ÐŽÐ»Ñ ÐŒÐœÐŸÐ³ÐžÑ
+ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ, ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœÐœÑÑ
+ ÐºÐ»ÑÑÐµÐ²ÑÐŒ ÐžÐŒÐµÐœÐµÐŒ Ð² ÐºÐ²Ð°ÐŽÑÐ°ÑÐœÑÑ
+ ÑÐºÐŸÐ±ÐºÐ°Ñ
+. Ð Ð¿ÑÐžÐŒÐµÑÑ, [Tab] ÐžÐ·ÐŒÐµÐœÑÐµÑ ÑÐŸÐºÑÑ. ÐÐœÐ°Ðº Ð¿Ð»ÑÑ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ, ÑÑÐŸ ÐŽÑÑÐ³ÐžÐµ ÐºÐ»Ð°Ð²ÐžÑÐž ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÐœÐ°Ð¶Ð°ÑÑ ÐŸÐŽÐœÐŸÐ²ÑÐµÐŒÐµÐœÐœÐŸ. </p>
+<p>Ð§ÑÐŸÐ±Ñ Ð¿ÐŸÐ»ÑÑÐžÑÑ ÐŽÐŸÑÑÑÐ¿ Ðº ÐŒÐµÐœÑ, ÑÐŽÐµÑÐ¶ÐžÐ²Ð°Ð¹ÑÐµ ÐºÐ»Ð°Ð²ÐžÑÑ [ALT] Ðž ÐœÐ°Ð¶ÐŒÐžÑÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÑÑ Ð±ÑÐºÐ²Ñ (Ð¿ÐŸÐŽÑÐµÑÐºÐœÑÑÑÑ).ÐÐ°Ð¿ÑÐžÐŒÐµÑ,ÐŽÐ»Ñ Ð²ÑÐ±ÐŸÑÐ° ÐŒÐµÐœÑ "Ð€Ð°Ð¹Ð»" ÐœÐ°Ð¶ÐŒÐžÑÐµ [ALT] + [F]. ÐÐ»Ñ Ð²ÑÐ±ÐŸÑÐ° ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÐŸÐ³ÐŸ Ð¿ÑÐœÐºÑÐ°, ÐœÐ°Ð¶ÐŒÐžÑÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÑÑ ÐºÐ»Ð°Ð²ÐžÑÑ. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÐµÑÐ»Ðž ÐÑ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÐµÑÑ Ð² ÐŒÐµÐœÑ Ð€Ð°Ð¹Ð» ÐœÐ°Ð¶ÐŒÐžÑÐµ [S], ÑÑÐŸÐ±Ñ "Ð¡ÐŸÑ
+ÑÐ°ÐœÐžÑÑ"ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ.</p>
+<p>ÐÐœÐŸÐ¿ÐºÐž, ÑÐžÐ¿Ð° ÐŒÐµÐœÑ, ÐžÐŒÐµÑÑ ÐŸÐŽÐžÐœ Ð¿ÐŸÐŽÑÑÑÐºÐœÑÑÑÐ¹ ÑÐžÐŒÐ²ÐŸÐ». Ð§ÑÐŸÐ±Ñ Ð²ÑÐ·Ð²Ð°ÑÑ ÐºÐœÐŸÐ¿ÐºÑ ÐœÐ°Ð¶ÐŒÐžÑÐµ [ALT] Ðž ÐŸÐŽÐœÐŸÐ²ÑÐµÐŒÐµÐœÐœÐŸ Ð¿ÐŸÐŽÑÐµÑÐºÐœÑÑÑÐ¹ ÑÐžÐŒÐ²ÐŸÐ». </p>
+<p>ÐÑÐ¹ÐŽÐžÑÐµ ÐžÐ· Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°, Ð²ÑÐ±ÐžÑÐ°Ñ Ð¿ÑÐœÐºÑ "ÐÑÑ
+ÐŸÐŽ" Ð² ÐŒÐµÐœÑ "Ð€Ð°Ð¹Ð»Ð°". ÐÐ°ÑÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð±ÑÐŽÐµÑ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ  ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐ°.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/openingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/openingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/openingacollection.htm	(revision 13928)
@@ -0,0 +1,26 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="openingacollection"><font face="Verdana" size="5"><strong>2.3: ÐÑÐºÑÑÑÐžÐµ ÑÑÑÐµÑÑÐ²ÑÑÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>ÐÐ»Ñ ÑÐŸÐ³ÐŸ ÑÑÐŸÐ±Ñ ÐŸÑÐºÑÑÑÑ ÑÑÑÐµÑÑÐ²ÑÑÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, Ð²ÑÐ±ÐµÑÐžÑÐµ "ÐÑÐºÑÑÑÑ" Ð² ÐŒÐµÐœÑ "Ð€Ð°Ð¹Ð»",ÑÑÐŸÐ±Ñ Ð±ÑÑÑÑÐŸ Ð¿ÐµÑÐµÐ¹ÑÐž Ðº ÐÑÐºÑÑÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐŸÑÐ²Ð»ÑÐµÑÑÑ ÑÐ¿ÐžÑÐŸÐº ÐÐ°ÑÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ð² Greenstone. ÐÑÐ±ÐµÑÐžÑÐµ ÐŸÐŽÐœÑ,ÑÑÐŸÐ±Ñ ÑÐ²ÐžÐŽÐµÑÑ ÐµÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ,Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ   "OÑÐºÑÑÑÑ", ÑÑÐŸÐ±Ñ Ð·Ð°Ð³ÑÑÐ·ÐžÑÑ ÐµÐµ. ÐÑÐ»Ðž ÐÑ ÐžÑÐžÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐºÐŸÑÐŸÑÐ°Ñ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð²ÐœÐµ Ð¿Ð°Ð¿ÐºÐž "Ð¡ollect Greenstone",ÑÐŸ ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð Ð°ÑÑÐŒÐŸÑÑÐµÑÑ" ÐŽÐ»Ñ Ð²ÑÐ·ÐŸÐ²Ð° ÐŽÐžÐ°Ð»ÐŸÐ³ÐŸÐ²ÐŸÐ¹ ÑÐžÑÑÐµÐŒÑ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÑÐ°Ð¹Ð»ÐŸÐ².</p>
+<p>Ð ÑÐ»ÑÑÐ°Ðµ, ÐµÑÐ»Ðž Ð±ÐŸÐ»ÑÑÐµ ÑÐµÐŒ ÐŸÐŽÐœÐ° Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° Greenstone Ð²Ð²ÐŸÐŽÐžÑÑÑ ÐŸÐŽÐœÐŸÐ²ÑÐµÐŒÐµÐœÐœÐŸ, ÑÐµÐ»ÐµÐ²Ð°ÐœÑÐœÑÐµ ÐŽÐžÑÐµÐºÑÑÐžÐž "Ð·Ð°ÐºÑÑÑÑ",ÑÑÐŸÐ±Ñ Ð¿ÑÐµÐŽÐŸÑÐ²ÑÐ°ÑÐžÑÑ ÐœÐ°Ð»ÐŸÐ¶ÐµÐœÐžÐµ.ÐÑÐž ÐŸÑÐºÑÑÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐœÐµÐ±ÐŸÐ»ÑÑÐŸÐ¹ Ð²ÑÐµÐŒÐµÐœÐœÑÐ¹ Ð±Ð»ÐŸÐºÐžÑÑÑÑÐžÐ¹ ÑÐ°Ð¹Ð» ÑÐŸÐ·ÐŽÐ°ÐµÑÑÑ Ð² ÐµÑ Ð¿Ð°Ð¿ÐºÐµ.ÐÐµÑÐµÐŽ ÐŸÑÐºÑÑÑÐžÐµÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑ Ð¿ÑÐŸÐ²ÐµÑÐºÑ,ÑÑÐŸÐ±Ñ ÑÐ±ÐµÐŽÐžÑÑÑÑ,ÑÑÐŸ ÐœÐžÐºÐ°ÐºÐžÑ
+ Ð±Ð»ÐŸÐºÐžÑÑÑÑÐžÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² ÐœÐµ ÑÑÑÐµÑÑÐ²ÑÐµÑ. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐºÐ°Ð·Ð°ÑÑ,Ð·Ð°ÐºÑÑÑÐ° Ð»Ðž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, Ð¿ÐŸ ÑÐ²ÐµÑÑ ÐµÑ ÐžÐºÐŸÐœÐºÐž:Ð·ÐµÐ»ÑÐœÑÐ¹ - ÐŽÐ»Ñ ÐœÐŸÑÐŒÐ°Ð»ÑÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž,ÐºÑÐ°ÑÐœÑÐ¹ - ÐŽÐ»Ñ Ð·Ð°ÐºÑÑÑÐŸÐ¹. ÐÐŽÐœÐ°ÐºÐŸ,ÐºÐŸÐ³ÐŽÐ° ÐžÐ· ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° Ð²ÑÑ
+ÐŸÐŽÑÑ Ð¿ÑÐµÐ¶ÐŽÐµÐ²ÑÐµÐŒÐµÐœÐœÐŸ, Ð±Ð»ÐŸÐºÐžÑÑÑÑÐžÐ¹ ÑÐ°Ð¹Ð» ÐžÐœÐŸÐ³ÐŽÐ° ÐŸÑÑÐ°ÐµÑÑÑ ÐœÐ° ÐŒÐµÑÑÐµ. ÐÐŸÐ³ÐŽÐ° ÐÑ ÐŸÑÐºÑÑÐ²Ð°ÐµÑÐµ ÑÐ°ÐºÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Ð·Ð°Ð¿ÑÐ°ÑÐžÐ²Ð°ÐµÑ,Ñ
+ÐŸÑÐžÑÐµ Ð»Ðž ÐÑ "ÑÐºÑÐ°ÑÑÑ" ÐµÐ³ÐŸ ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÐµ. ÐÐžÐºÐŸÐ³ÐŽÐ° ÐœÐµ ÐŽÐµÐ»Ð°Ð¹ÑÐµ ÑÑÐŸÐ³ÐŸ,ÐµÑÐ»Ðž ÐºÑÐŸ-ÑÐŸ ÐµÑÐµ Ð² ÑÐŸ Ð¶Ðµ ÑÐ°ÐŒÐŸÐµ Ð²ÑÐµÐŒÑ ÑÐ°Ð±ÐŸÑÐ°ÐµÑ.   </p>
+<p>ÐÐŸÐ³ÐŽÐ° ÐÑ ÐŸÑÐºÑÑÐ²Ð°ÐµÑÐµ ÐºÐŸÐ»ÐµÐºÑÐžÑ, ÐºÐŸÑÐŸÑÐ°Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐ° ÐœÐµ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°  Greenstone, ÐÐ°Ñ Ð¿ÐŸÐ¿ÑÐŸÑÑÑ Ð²ÑÐ±ÑÐ°ÑÑ ÐœÐ°Ð±ÐŸÑ (ÐžÐ»Ðž ÐœÐ°Ð±ÐŸÑÑ) ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. ÐÑÐ»Ðž ÐœÐž ÐŸÐŽÐžÐœ ÐœÐµ ÐŸÑÐŸÐ±ÑÐ°Ðœ, Ð»ÑÐ±ÑÐµ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ð±ÑÐŽÑÑ ÐžÐ³ÐœÐŸÑÐžÑÐŸÐ²Ð°ÑÑÑÑ. ÐÐœÐ°ÑÐµ, ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ð±ÑÐŽÑÑ ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÑ ÑÐ°Ðº Ð¶Ðµ, ÐºÐ°Ðº Ðž ÐºÐŸÐ³ÐŽÐ° ÐÑ Ð¿ÐµÑÐµÑÑÐ³ÐžÐ²Ð°ÐµÑÐµ Ð² ÑÐ°Ð¹Ð»Ñ Ñ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐŒÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒÐž. ÐÑÐŸÑÐµÑÑ ÐŸÐ¿ÐžÑÐ°Ðœ Ð² <a href="importingpreviouslyassignedmetadata.htm">ÐÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</a>. </p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/partitionindexes.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/partitionindexes.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/partitionindexes.htm	(revision 13928)
@@ -0,0 +1,29 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="partitionindexes"><font face="Verdana" size="5"><strong>6.6: ÐÐœÐŽÐµÐºÑÑ ÑÐ°Ð·Ð±ÐžÐµÐœÐžÑ</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>ÐÐœÐŽÐµÐºÑÑ Ð¿ÐŸÑÑÑÐŸÐµÐœÑ ÐœÐ° ÐŽÐµÑÐ°Ð»ÑÐœÐŸÐŒ ÑÐµÐºÑÑÐµ ÐžÐ»Ðž ÐžÑÑÐŸÑÐœÐžÐºÐ°Ñ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. ÐÐµÑÑÐŸ Ð¿ÐŸÐžÑÐºÐ° ÐŒÐŸÐ¶ÐµÑ Ð² ÐŽÐ°Ð»ÑÐœÐµÐ¹ÑÐµÐŒ ÑÐ¿ÑÐ°Ð²Ð»ÑÑÑÑÑ Ð¿ÑÑÑÐŒ ÑÐ°Ð·Ð±ÐžÐµÐœÐžÑ ÐžÐœÐŽÐµÐºÑÐŸÐ² Ð»ÐžÐ±ÐŸ Ð¿ÐŸ ÑÐ·ÑÐºÑ ÐžÐ»Ðž Ð¿ÐŸ ÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐœÑÐŒ ÑÐžÐ»ÑÑÑÐ°ÐŒ.Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑÑÑ,ÐºÐ°Ðº ÑÑÐŸ ÑÐŽÐµÐ»Ð°ÑÑ. ÐÐœÑÑÑÐž "Ð Ð°Ð·ÐŽÐµÐ»ÐŸÐ² ÐŽÐžÐ·Ð°Ð¹ÐœÐ°" ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐœÐŽÐµÐºÑÑ ÑÐ°Ð·Ð±ÐžÐµÐœÐžÑ".</p>
+<p>ÐÐžÐŽ "ÐÐœÐŽÐµÐºÑÑ ÑÐ°Ð·Ð±ÐžÐµÐœÐžÑ" ÐžÐŒÐµÐµÑ ÑÑÐž Ð·ÐœÐ°ÑÐµÐœÐžÑ:"ÐÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÑÐžÐ»ÑÑÑÑ","ÐÐ°Ð·ÐœÐ°ÑÐžÑÑ ÑÐ°Ð·Ð±ÐžÐµÐœÐžÐµ" Ðž "ÐÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÑÐ·ÑÐºÐž". ÐÐ»Ñ ÑÐŸÐ³ÐŸ ÑÑÐŸÐ±Ñ Ð±ÐŸÐ»ÑÑÐµ ÑÐ·ÐœÐ°ÑÑ ÐŸ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÐž, ÑÐžÑÐ°Ð¹ÑÐµ  ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÑ
+ Ðž Ð¿ÐŸÐŽÐžÐœÐŽÐµÐºÑÐ°Ñ
+ Ð² Ð³Ð»Ð°Ð²Ðµ 2 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone.</p>
+<p>Ð­ÐºÑÐ°Ðœ ÐÐœÐŽÐµÐºÑÐŸÐ² Ð Ð°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐµÐœ ÑÐŸÐ»ÑÐºÐŸ Ð² ÑÐµÐ¶ÐžÐŒÐ°Ñ
+ Ð¡Ð¿ÐµÑÐžÐ°Ð»ÐžÑÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÑ
+ Ð¡ÐžÑÑÐµÐŒ Ðž Ð­ÐºÑÐ¿ÐµÑÑ (ÑÐŒ. <a href="preferences.htm">ÐÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÑ</a>). ÐÐ°ÐŒÐµÑÑÑÐµ, ÑÑÐŸ ÐŸÐ±ÑÐµÐµ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸ Ð¿ÑÐŸÐžÐ·Ð²ÐµÐŽÐµÐœÐœÑÑ
+ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÐ¹ ÑÐ²Ð»ÑÐµÑÑÑ ÐºÐŸÐŒÐ±ÐžÐœÐ°ÑÐžÐµÐ¹ Ð²ÑÐµÑ
+ ÐžÐœÐŽÐµÐºÑÐŸÐ², ÑÐžÐ»ÑÑÑÐŸÐ² ÑÑÐ±ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð²ÑÐ±ÑÐ°ÐœÐœÑÑ
+ ÑÐ·ÑÐºÐŸÐ². ÐÐ²Ð° ÐžÐœÐŽÐµÐºÑÐ° Ñ ÐŽÐ²ÑÐŒÑ ÑÐžÐ»ÑÑÑÐ°ÐŒÐž ÑÑÐ±ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÐŸ ÐŽÐ²ÑÐŒ ÑÐ·ÑÐºÐ°ÐŒ Ð¿ÑÐžÐ²ÐµÐ»ÐŸ Ð±Ñ Ðº Ð²ÐŸÑÑÐŒÐž ÐžÐœÐŽÐµÐºÑÐ°ÐŒ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ.</p>
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/plugins.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/plugins.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/plugins.htm	(revision 13928)
@@ -0,0 +1,29 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="plugins"><font face="Verdana" size="5"><strong>6.3: ÐÐ»Ð°Ð³ÐžÐœÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ¿ÐžÑÐ°ÐœÐŸ,ÐºÐ°Ðº ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÑÑ Ð¿Ð»Ð°Ð³ÐžÐœÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° ÐŽÐ»Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹.Ð ÐœÑÐŒ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ,ÐºÐ°Ðº ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ,ÐºÐ°ÐºÐžÐµ Ð¿Ð»Ð°Ð³ÐžÐœÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ, ÐºÐ°ÐºÐžÐµ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ Ð¿ÐµÑÐµÐŽÐ°Ð²Ð°ÑÑ Ðº ÐœÐžÐŒ Ðž Ð² ÐºÐ°ÐºÐŸÐŒ Ð¿ÐŸÑÑÐŽÐºÐµ ÐŸÐœÐž Ð²Ñ
+ÐŸÐŽÑÑ. Ð©ÐµÐ»ÐºÐœÐžÑÐµ "ÐÐ»Ð°Ð³ÐžÐœÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²" Ð² Ð¿ÑÐœÐºÑÐµ "Ð Ð°Ð·ÐŽÐµÐ»Ñ Ð¿ÑÐŸÐµÐºÑÐ°".</p>
+<p>Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÑÑ Ð¿Ð»Ð°Ð³ÐžÐœ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ,ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ "ÐÑÐ±ÐŸÑ Ð¿Ð»Ð°Ð³ÐžÐœÐ° ÐŽÐ»Ñ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÑ" Ð² ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐŒ ÑÐ¿ÐžÑÐºÐµ ÐŸÐºÐŸÐ»ÐŸ ÐŸÑÐœÐŸÐ²Ð°ÐœÐžÑ,Ðž Ð·Ð°ÑÐµÐŒ ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ Ð¿Ð»Ð°Ð³ÐžÐœ". ÐÐŸÑÐ²Ð»ÑÐµÑÑÑ ÐŸÐºÐœÐŸ Ñ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµÐŒ "ÐÐŸÐœÑÐžÐ³ÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ²";ÐŸÐœÐŸ ÐŸÐ¿ÐžÑÐ°ÐœÐŸ ÐœÐžÐ¶Ðµ. ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐÑ ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°Ð»Ðž ÐœÐŸÐ²ÑÐ¹ Ð¿Ð»Ð°Ð³ÐžÐœ, ÐŸÐœ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑÑÑ Ð² ÐºÐŸÐœÐµÑ ÑÐ¿ÐžÑÐºÐ° "Ð£ÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐœÑÐµ ÑÐµÐºÑÑÐžÐµ Ð¿Ð»Ð°Ð³ÐžÐœÑ". ÐÐ°ÐŒÐµÑÑÑÐµ, ÑÑÐŸ, ÐºÑÐŸÐŒÐµ UnknownPlug, ÐºÐ°Ð¶ÐŽÑÐ¹ Ð¿Ð»Ð°Ð³ÐžÐœ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ Ð²ÑÐ²ÐµÐŽÐµÐœ ÑÐŸÐ»ÑÐºÐŸ ÐŸÐŽÐžÐœ ÑÐ°Ð· Ð² ÑÐ¿ÐžÑÐºÐµ.</p>
+<p>Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ Ð¿Ð»Ð°Ð³ÐžÐœ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ Ð² ÑÐ¿ÐžÑÐºÐµ Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ Ð¿Ð»Ð°Ð³ÐžÐœ".</p>
+<p>ÐÐ»Ð°Ð³ÐžÐœÑ ÑÐŸÑÐŒÐžÑÑÑÑÑÑ Ð¿ÑÑÐµÐŒ Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÐµÐœÐžÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ². Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐžÑ
+, Ð²ÑÐ±ÐµÑÐžÑÐµ Ð¿Ð»Ð°Ð³ÐžÐœ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð€ÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð¿Ð»Ð°Ð³ÐžÐœÐŸÐ²"(ÐžÐ»Ðž ÐŽÐ²ÐŸÐ¹ÐœÑÐŒ ÑÐµÐ»ÑÐºÐŸÐŒ ÐœÐ° Ð¿Ð»Ð°Ð³ÐžÐœÐµ). ÐÐžÐ°Ð»ÐŸÐ³ "ÐÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐµ ÐÑÐ³ÑÐŒÐµÐœÑÑ" Ð²ÐŸÐ·ÐœÐžÐºÐ°ÐµÑ Ñ ÑÐ°Ð·Ð»ÐžÑÐœÑÐŒÐž ÐŸÐ¿ÑÐžÑÐŒÐž ÐŽÐ»Ñ ÑÐºÐ°Ð·Ð°ÐœÐžÑ Ð°ÑÐ³ÑÐŒÐµÐœÑÐŸÐ².</p>
+<p>Ð¡ÑÑÐµÑÑÐ²ÑÑÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ Ð²ÐžÐŽÑ ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ. ÐÐµÐºÐŸÑÐŸÑÑÐµ ÑÐ²Ð»ÑÑÑÑÑ ÐœÐµÐ·Ð°Ð²ÐžÑÐžÐŒÑÐŒÐž ÐºÐœÐŸÐ¿ÐºÐ°ÐŒÐž Ðž ÑÐµÐ»ÑÐŸÐº ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÑÑ ÐŸÐ¿ÑÐžÑ Ðº Ð¿Ð»Ð°Ð³ÐžÐœÑ. ÐÑÑÐ³ÐžÐµ Ð²ÑÑÑÑÐ¿Ð°ÑÑ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÑÑÑÐŸÐºÐž ÑÐµÐºÑÑÐ° Ñ ÐœÐµÐ·Ð°Ð²ÐžÑÐžÐŒÐŸÐ¹ ÐºÐœÐŸÐ¿ÐºÐŸÐ¹ Ðž ÐŸÐ±Ð»Ð°ÑÑÑÑ ÑÐµÐºÑÑÐ°. Ð©ÐµÐ»ÐºÐœÐžÑÐµ ÐœÐ° Ð¿ÐŸÐ»Ðµ,ÑÑÐŸÐ±Ñ Ð²ÑÐ·Ð²Ð°ÑÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑ,Ð·Ð°ÑÐµÐŒ ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð¹ÑÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐ¹ ÑÐµÐºÑÑ (Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÐŸÐµ Ð²ÑÑÐ°Ð¶ÐµÐœÐžÐµ,Ð¿ÑÑÑ ÑÐ°Ð¹Ð»Ð° Ðž Ñ.ÐŽ.) Ð² Ð¿ÐŸÐ»Ðµ. ÐÑÑÐ³ÐžÐµ - ÑÑÐŸ ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐžÐµ ÐŒÐµÐœÑ,Ð² ÐºÐŸÑÐŸÑÑÑ
+ ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐ±ÐžÑÐ°ÑÑ ÐœÑÐ¶ÐœÐŸÐµ ÐžÐ· Ð·Ð°ÐŽÐ°ÐœÐœÐŸÐ³ÐŸ ÐœÐ°Ð±ÐŸÑÐ° Ð·ÐœÐ°ÑÐµÐœÐžÐ¹. Ð§ÑÐŸÐ±Ñ Ð¿ÐŸÐœÑÑÑ,ÑÑÐŸ ÐŽÐµÐ»Ð°ÐµÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑ, ÐŽÐ°Ð¹ÑÐµ ÐŒÑÑÐž ÐœÐ° ÐŒÐ³ÐœÐŸÐ²ÐµÐœÐžÐµ Ð¿ÑÐŸÐ¹ÑÐž Ð¿ÐŸ ÐµÐ³ÐŸ ÐœÐ°Ð·Ð²Ð°ÐœÐžÑ Ðž ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ Ð¿ÐŸÑÐ²ÐžÑÑÑ. </p>
+<p>ÐÐŸÐ³ÐŽÐ° ÐÑ ÐžÐ·ÐŒÐµÐœÐžÐ»Ðž ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÑ,ÐœÐ°Ð¶ÐŒÐžÑÐµ "ÐÐ", ÑÑÐŸÐ±Ñ Ð¿ÑÐžÐœÑÑÑ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ðž Ð·Ð°ÐºÑÑÑÑ ÐŽÐžÐ°Ð»ÐŸÐ³,ÐžÐ»Ðž "ÐÑÐŒÐµÐœÐžÑÑ",ÑÑÐŸÐ±Ñ Ð·Ð°ÐºÑÑÑÑ ÐŽÐžÐ°Ð»ÐŸÐ³ Ð±ÐµÐ· ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ð»ÑÐ±ÑÑ
+ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ² Ð¿Ð»Ð°Ð³ÐžÐœÐ°. </p>
+<p>ÐÐ»Ð°Ð³ÐžÐœÑ Ð² ÑÐ¿ÐžÑÐºÐµ ÑÐ°ÑÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÑ Ð² ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÐŸÐŒ Ð¿ÐŸÑÑÐŽÐºÐµ,ÑÐ°Ðº ÐºÐ°Ðº ÑÐ¿ÐŸÑÑÐŽÐŸÑÐµÐœÐžÐµ ÐžÐœÐŸÐ³ÐŽÐ° Ð²Ð°Ð¶ÐœÐŸ. ÐÐŸÑÑÐŽÐŸÐº ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÑÑ
+ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÑÑ
+ ÐŒÐŸÐŽÑÐ»ÐµÐ¹ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐžÐ·ÐŒÐµÐœÐµÐœ ÑÐŸÐ»ÑÐºÐŸ Ð² ÑÐµÐ¶ÐžÐŒÐ°Ñ
+ Ð¡Ð¿ÐµÑÐžÐ°Ð»ÐžÑÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÑ
+ Ð¡ÐžÑÑÐµÐŒ Ðž Ð­ÐºÑÐ¿ÐµÑÑ (ÑÐŒ. <a href="preferences.htm">ÐÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÑ</a>).</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/preferences.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/preferences.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/preferences.htm	(revision 13928)
@@ -0,0 +1,42 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="preferences"><font face="Verdana" size="5"><strong>8.1: ÐÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÑ</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ ÐŽÐžÐ°Ð»ÐŸÐ³ Ð¿ÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÐ¹,ÐŽÐŸÑÑÑÐ¿ÐœÑÐ¹ Ð¿ÑÐž ÐŸÑÐºÑÑÑÐžÐž "Ð€Ð°Ð¹Ð»Ð°", Ð° Ð·Ð°ÑÐµÐŒ "ÐÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÐ¹".</p>
+<p>ÐÐµÑÐ²Ð°Ñ ÐŸÐ¿ÑÐžÑ "ÐÐ±ÑÐµÐµ" - ÑÑÐŸ ÑÐµÐºÑÑÐŸÐ²ÐŸÐµ Ð¿ÐŸÐ»Ðµ ÐŽÐ»Ñ Ð²Ð²ÐµÐŽÐµÐœÐžÑ Ð°ÐŽÑÐµÑÐ° Ð²Ð°ÑÐµÐ¹ ÑÐ»ÐµÐºÑÑÐŸÐœÐœÐŸÐ¹ Ð¿ÐŸÑÑÑ. ÐÐœ Ð±ÑÐŽÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°Ðœ Ð² Ð·ÐœÐ°ÑÐµÐœÐžÐž ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+ "Ð¡ÐŸÐ·ÐŽÐ°ÑÐµÐ»Ñ" Ðž "ÐÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÑÐ¹". Ð¡Ð»ÐµÐŽÑÑÐ°Ñ ÐŸÐ¿ÑÐžÑ - ÑÑÐŸ Ð²ÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐµ ÐŒÐµÐœÑ Ñ ÑÐ·ÑÐºÐ°ÐŒÐž, Ð² ÐºÐŸÑÐŸÑÑÑ
+ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐÐœÑÐµÑÑÐµÐ¹Ñ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœ. ÐÑÐ»Ðž ÐÑ ÐžÐ·ÐŒÐµÐœÑÐµÑÐµ ÑÐ»ÐŸÐ²Ð°ÑÑ, Ð²ÑÐ±ÐžÑÐ°Ñ ÐºÐ°ÐºÐŸÐ¹-Ð»ÐžÐ±ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ°, ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ Ð¿ÐµÑÐµÐ·Ð°Ð³ÑÑÐ·ÐžÑÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ, ÑÑÐŸÐ±Ñ Ð·Ð°Ð³ÑÑÐ·ÐžÑÑ ÐœÐŸÐ²ÑÐµ ÑÑÑÐŸÐºÐž ÑÐ·ÑÐºÐ° ÐžÐ· ÑÑÐŸÐ³ÐŸ ÑÐ»ÐŸÐ²Ð°ÑÑ.</p>
+<p>ÐÑÐ»Ðž Ð²ÑÐ±ÑÐ°ÐœÐ° "ÐÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐžÐ·Ð²Ð»ÐµÐºÐ°ÐµÐŒÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+", ÑÐ°Ð·Ð»ÐžÑÐœÐŸÐµ ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÐµ, ÑÐ²ÑÐ·Ð°ÐœÐœÐŸÐµ Ñ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒÐž, Ð²ÑÐµÐ³ÐŽÐ° Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð²ÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, ÐºÐŸÑÐŸÑÑÐµ Ð±ÑÐ»Ðž Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž ÐžÐ·Ð²Ð»ÐµÑÐµÐœÑ ÐžÐ· ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ². ÐÑÐŒÐµÐœÐ° ÑÑÐŸÐ³ÐŸ Ð²ÑÐ±ÐŸÑÐ° ÑÐºÑÑÐ²Ð°ÐµÑ ÑÑÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, Ñ
+ÐŸÑÑ ÐŸÐœÐž Ð²ÑÑ ÐµÑÑ  ÐŽÐŸÑÑÑÐ¿ÐœÑ Ð² ÑÐµÑÐµÐœÐžÐµ ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÐºÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð² ÑÐ°ÐŒÐºÐ°Ñ
+ ÐŸÐºÐŸÐœÑÐ°ÑÐµÐ»ÑÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Greenstone. ÐÑÐ»Ðž Ð²ÑÐ±ÑÐ°ÐœÐŸ "ÐÐŸÐºÐ°Ð·Ð°ÑÑ ÑÐ°Ð·ÐŒÐµÑÑ ÑÐ°Ð¹Ð»Ð°", ÑÐŸ ÑÐ°Ð·ÐŒÐµÑ ÑÐ°Ð¹Ð»Ð° Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑÑÑ ÑÑÐŽÐŸÐŒ Ñ ÐºÐ°Ð¶ÐŽÑÐŒ ÑÐ°Ð¹Ð»ÐŸÐŒ Ð² ÑÐ°Ð±ÐŸÑÐµÐŒ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²Ðµ, Ð° ÑÐ°ÐºÐ¶Ðµ Ð² ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐŒ ÐŽÐµÑÐµÐ²Ðµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð² Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑÑ
+ Gather Ðž Enrich.</p>
+<p>ÐÐ°ÐœÐµÐ»Ñ "Ð¡Ð¿ÐŸÑÐŸÐ±" ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ ÑÑÐŸÐ²ÐœÐµÐŒ Ð¿ÐŸÐŽÑÐŸÐ±ÐœÐŸÑÑÐµÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°. ÐÐ° ÑÐ°ÐŒÐŸÐŒ ÐœÐžÐ¶ÐœÐµÐŒ ÑÑÐŸÐ²ÐœÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐŸÐº ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ "ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ Ð¿ÐŸÐŒÐŸÑÐœÐžÐº", Ð¿ÑÐž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐž ÐºÐŸÑÐŸÑÐŸÐ³ÐŸ Ð¿ÑÐŸÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð±Ð»ÐŸÐºÐžÑÐŸÐ²Ð°ÐœÐŸ, Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ, ÑÑÐµÐ±ÑÑÑÐžÐµ Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÐŸÐ³ÐŸ Ð²ÑÑÐ°Ð¶ÐµÐœÐžÑ, ÑÐºÑÑÑÑ Ðž Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑÑ ÐŒÐžÐœÐžÐŒÐ°Ð»ÑÐœÐŸ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÑÐŒ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸÐŒ Ð·Ð°Ð¿ÐžÑÐµÐ¹. ÐÐ°ÐŸÐ±ÐŸÑÐŸÑ, ÐœÐ°ÐžÐ²ÑÑÑÐ°Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐ° "Ð­ÐºÑÐ¿ÐµÑÑ" ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ ÐŽÐŸÑÑÑÐ¿ ÐºÐŸ Ð²ÑÐµÐŒ ÑÑÐµÐŽÑÑÐ²Ð°ÐŒ Ð¿ÑÐŸÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÑ, Ð²ÐºÐ»ÑÑÐ°Ñ Ð¿ÐŸÐ·ÐžÑÐžÐŸÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð¿Ð»Ð°Ð³ÐžÐœÐŸÐ² Ðž Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÐŸÐµ Ð²ÑÑÐ°Ð¶ÐµÐœÐžÐµ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ², Ð° ÑÐ°ÐºÐ¶Ðµ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð¿ÐŸÐ»ÐœÑÐ¹ Ð²ÑÑ
+ÐŸÐŽ ÐžÐ· Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÑÐŸÐ±Ñ Ð·Ð°ÑÐžÐºÑÐžÑÐŸÐ²Ð°ÑÑ Ð² Ð¶ÑÑÐœÐ°Ð»Ðµ Ð·Ð°Ð¿ÐžÑÐµÐ¹. Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐžÐ»Ðž Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ ÑÐ¿ÐŸÑÐŸÐ±Ñ, ÐºÐ»ÐžÐºÐœÐžÑÐµ ÑÐ°ÐŽÐžÐŸ-ÐºÐœÐŸÐ¿ÐºÑ, ÑÐ»ÐµÐŽÑÑÑÑÑ Ð·Ð° ÑÐ¿ÐŸÑÐŸÐ±ÐŸÐŒ, ÐºÐŸÑÐŸÑÑÐ¹ ÐžÐœÑÐµÑÐµÑÑÐµÑ ÐÐ°Ñ. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð±ÑÑÑÑÐŸ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ, ÐºÐ°ÐºÐŸÐ¹ ÑÐ¿ÐŸÑÐŸÐ± ÐÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÐµ, ÑÐ°ÑÑÐŒÐ°ÑÑÐžÐ²Ð°Ñ Ð»ÐžÐœÐµÐ¹ÐºÑ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐ¹ Ð² ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐŒ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐµ. </p>
+<p>ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ ÐŒÐŸÐ¶ÐµÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÑÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ ÑÐµÑ
+ÐœÐŸÐ»ÐŸÐ³ÐžÑÐµÑÐºÐžÐµ Ð¿ÑÐŸÑÐµÑÑÑ Ð¿ÑÐž ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÐž, ÐºÐ°ÐºÐžÐµ ÐžÐ· ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐ¹ ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ² ÑÐ²Ð»ÑÑÑÑÑ Ð²ÐžÐŽÐžÐŒÑÐŒÐž. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐºÐ»Ð°Ð²ÐžÑÑ "Ð¢ÐµÑ
+ÐœÐŸÐ»ÐŸÐ³ÐžÑÐµÑÐºÐžÐµ Ð¿ÑÐŸÑÐµÑÑÑ", ÑÑÐŸÐ±Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ, ÐºÐ°ÐºÐžÐµ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ ÑÐ²Ð»ÑÑÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž, Ð¿ÑÐŸÐ²ÐµÑÑÑ Ð¿ÐŸÐ»Ñ ÑÑÐŽÐŸÐŒ Ñ ÑÐµÐŒÐž Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑÐŒÐž, ÐºÐŸÑÐŸÑÑÐµ ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž. ÐÐŒÐµÑÑÐŸ ÑÑÐŸÐ³ÐŸ ÐŒÐŸÐ¶ÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐžÐ¹ ÑÐ¿ÐžÑÐŸÐº Ð²ÐœÐžÐ·Ñ ÑÐºÑÐ°ÐœÐ°,ÑÑÐŸÐ±Ñ Ð²ÑÐ±ÑÐ°ÑÑ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°ÐŽÐ°ÐœÐœÑÐµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž. ÐÐ°ÐºÑÑÑÐžÐµ ÐŽÐžÐ°Ð»ÐŸÐ³Ð° Ð¿ÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÐ¹ Ð·Ð°ÐºÑÐµÐ¿Ð»ÑÐµÑ ÑÑÐž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÑÐµÑ
+ÐœÐŸÐ»ÐŸÐ³ÐžÑÐµÑÐºÐŸÐ³ÐŸ Ð¿ÑÐŸÑÐµÑÑÐ°. Ð­ÑÐž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž Ñ
+ÑÐ°ÐœÑÑÑÑ Ð²ÐŒÐµÑÑÐµ Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹,Ð° ÐœÐµ Ð² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°.</p>
+<p>ÐÐ»Ð°Ð²ÐžÑÐ° "Ð¡ÐŸÐµÐŽÐžÐœÐµÐœÐžÐµ" Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐÐ°ÐŒ ÐžÐ·ÐŒÐµÐœÑÑÑ Ð¿ÑÑÑ Ðº Ð»ÐŸÐºÐ°Ð»ÑÐœÐŸÐŒÑ ÑÐµÑÐ²ÐµÑÑ Greenstone, ÐºÐŸÑÐŸÑÑÐ¹ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸÐ³ÐŸ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑÐŸÐŒÐµ ÑÐŸÐ³ÐŸ ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÐŒÐŸÐŽÑÐ»Ñ ÐŽÐŸÑÑÑÐ¿Ð° Ðº ÐÐœÑÐµÑÐœÐµÑÑ Ð¿ÑÐŸÐºÑÐž (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÐŽÐ»Ñ Ð·Ð°Ð³ÑÑÐ·ÐºÐž ÑÐ°Ð¹Ð»ÐŸÐ²; ÑÐŒÐŸÑÑÐž ÑÐ°Ð·ÐŽÐµÐ» <a href="downloadingfiles.htm">ÐÐ°Ð³ÑÑÐ·ÐžÑÑ ÑÐ°Ð¹Ð»Ñ ÐžÐ· ÐžÐœÑÐµÑÐœÐµÑ</a> ÐŽÐ»Ñ Ð¿ÐŸÐŽÑÐŸÐ±ÐœÐŸÑÑÐµÐ¹). ÐÐŸÐŒÐµÑÑÑÐµ ÑÐ»Ð°Ð³ÐŸÐ²ÑÑ ÐºÐœÐŸÐ¿ÐºÑ, ÑÑÐŸÐ±Ñ Ð²ÐºÐ»ÑÑÐžÑÑ ÐŒÐŸÐŽÑÐ»Ñ ÐŽÐŸÑÑÑÐ¿Ð°, Ðž ÑÐºÐ°Ð¶ÐžÑÐµ ÐŽÐµÑÐ°Ð»Ðž Ð°ÐŽÑÐµÑÐ° ÑÐµÑÐ²ÐµÑÐ° Ð¿ÑÐŸÐºÑÐž Ðž ÐœÐŸÐŒÐµÑ Ð¿ÐŸÑÑÐ°. ÐÐŸÐŽÑÐ»Ñ ÐŽÐŸÑÑÑÐ¿Ð° Ð±ÑÐŽÐµÑ Ð°ÐºÑÐžÐ²ÐžÑÐŸÐ²Ð°Ðœ Ð¿ÑÐž Ð·Ð°ÐºÑÑÑÐžÐž ÐŽÐžÐ°Ð»ÐŸÐ³ÐŸÐ²ÐŸÐ³ÐŸ ÐŸÐºÐœÐ° ÐÐ¿ÑÐžÐ¹.</p>
+<p>Ð ÑÐµÑÐµÐœÐžÐµ ÑÐµÑÑÐžÐž ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ ÐŒÐŸÐ¶ÐµÑ ÐŽÐ°Ð²Ð°ÑÑ Ð¿ÑÐµÐŽÑÐ¿ÑÐµÐŽÐžÑÐµÐ»ÑÐœÑÐµ ÑÐŸÐŸÐ±ÑÐµÐœÐžÑ, ÐºÐŸÑÐŸÑÑÐµ ÐžÐœÑÐŸÑÐŒÐžÑÑÑÑ ÐÐ°Ñ ÐŸ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÑÑ
+ ÐœÐµÐ¿ÑÐµÐŽÐ²ÐžÐŽÐµÐœÐœÑÑ
+ Ð¿ÐŸÑÐ»ÐµÐŽÑÑÐ²ÐžÑÑ
+ ÐÐ°ÑÐžÑ
+ ÐŽÐµÐ¹ÑÑÐ²ÐžÐ¹. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð·Ð°Ð±Ð»ÐŸÐºÐžÑÐŸÐ²Ð°ÑÑ ÑÐŸÐŸÐ±ÑÐµÐœÐžÐµ, Ð²ÑÐ±ÐžÑÐ°Ñ Ð¿ÐŸÐ»Ðµ "ÐÐµ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÑÑ ÑÑÐŸ Ð¿ÑÐµÐŽÑÐ¿ÑÐµÐ¶ÐŽÐµÐœÐžÐµ ÑÐœÐŸÐ²Ð°". ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÐŸÐ·ÐŸÐ±ÐœÐŸÐ²ÐžÑÑ Ð¿ÐŸÑÐ²Ð»ÐµÐœÐžÐµ Ð¿ÑÐµÐŽÑÐ¿ÑÐµÐ¶ÐŽÐ°ÑÑÐžÑ
+ ÑÐŸÐŸÐ±ÑÐµÐœÐžÐ¹,ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐºÐ»Ð°Ð²ÐžÑÑ "ÐÑÐµÐŽÑÐ¿ÑÐµÐ¶ÐŽÐµÐœÐžÐµ". ÐÑÐ±ÐµÑÐžÑÐµ Ð¿ÐŸÐ»Ðµ ÑÑÐŽÐŸÐŒ Ñ Ð¿ÑÐµÐŽÑÐ¿ÑÐµÐ¶ÐŽÐ°ÑÑÐžÐŒÐž ÑÐŸÐŸÐ±ÑÐµÐœÐžÑÐŒÐž, ÐµÑÐ»Ðž ÐÑ Ñ
+ÐŸÑÐžÑÐµ ÑÐœÐŸÐ²Ð° Ð¿ÐŸÐ»ÑÑÐ°ÑÑ ÐžÑ
+.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/producingthecollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/producingthecollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/producingthecollection.htm	(revision 13928)
@@ -0,0 +1,18 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="producingthecollection"><font face="Verdana" size="5"><strong>7: ÐÐŸÑÑÑÐŸÐµÐœÐžÐµ ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>ÐÐŒÐµÑ ÑÐŸÐ±ÑÐ°ÐœÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÐŽÐ»Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð°ÐœÐœÐŸÑÐžÑÐŸÐ²Ð°Ð² ÐžÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒÐž Ðž ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÐ°Ð² ÐŽÐžÐ·Ð°Ð¹Ðœ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž,ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐµÐ¿ÐµÑÑ ÑÐŸÐ·ÐŽÐ°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ Greenstone. Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ,ÐºÐ°Ðº ÑÑÐŸ ÑÐŽÐµÐ»Ð°ÑÑ.</p>
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/removingfiles.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/removingfiles.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/removingfiles.htm	(revision 13928)
@@ -0,0 +1,19 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="removingfiles"><font face="Verdana" size="5"><strong>4.4: Ð£ÐŽÐ°Ð»ÐµÐœÐžÐµ ÑÐ°Ð¹Ð»ÐŸÐ²</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð¡ÑÑÐµÑÑÐ²ÑÐµÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐŒÐµÑÐŸÐŽÐŸÐ² ÑÐŽÐ°Ð»ÐµÐœÐžÑ ÑÐ°Ð¹Ð»ÐŸÐ² Ðž Ð¿Ð°Ð¿ÐŸÐº. ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ ÑÐœÐ°ÑÐ°Ð»Ð° ÑÐºÐ°Ð·Ð°ÑÑ,ÐºÐ°ÐºÐžÐµ ÐžÐ· ÐœÐžÑ
+ ÑÐŽÐ°Ð»ÑÑÑ, Ð²ÑÐ±ÐžÑÐ°Ñ ÐŸÐŽÐžÐœ ÐžÐ»Ðž Ð±ÐŸÐ»ÐµÐµ ÑÐ°Ð¹Ð»ÐŸÐ² Ðž Ð¿Ð°Ð¿ÐŸÐº, ÐºÐ°Ðº ÐŸÐ¿ÐžÑÐ°ÐœÐŸ Ð² <a href="thegatherview.htm">ÐÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐœÐ°ÐºÐŸÐ¿ÐžÑÐµÐ»Ñ</a>.</p>
+<p>ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÑÐ°Ð¹Ð»Ñ ÐŸÑÐŸÐ±ÑÐ°ÐœÑ, ÐŽÐ»Ñ ÐžÑ
+ ÑÐŽÐ°Ð»ÐµÐœÐžÑ ÑÐµÐ»ÐºÐ°ÑÑ ÐºÐœÐŸÐ¿ÐºÑ "Ð£ÐŽÐ°Ð»ÐžÑÑ"ÐžÐ»Ðž ÐœÐ°Ð¶ÐžÐŒÐ°ÑÑ ÐºÐºÐ»Ð°Ð²ÐžÑÑ [Ð£ÐŽÐ°Ð»ÐžÑÑ] ÐœÐ° ÐºÐ»Ð°Ð²ÐžÐ°ÑÑÑÐµ, ÐžÐ»Ðž Ð¶Ðµ ÑÑÐœÑÑ ÐžÑ
+ ÐžÐ· ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŽÐŸ ÐºÐœÐŸÐ¿ÐºÐž "Ð£ÐŽÐ°Ð»ÐžÑÑ" Ðž ÑÐ°ÐŒ ÐŸÑÐ¿ÑÑÐºÐ°ÑÑ.  </p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/reviewingmetadata.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/reviewingmetadata.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/reviewingmetadata.htm	(revision 13928)
@@ -0,0 +1,37 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="reviewingmetadata"><font face="Verdana" size="5"><strong>5.6: ÐÑÐŸÑÐŒÐŸÑÑ Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>ÐÐœÐŸÐ³ÐŽÐ° ÐÐ°ÐŒ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ,Ð·Ð°ÐŽÐ°ÐœÐœÑÐµ ÐŽÐ»Ñ ÐŒÐœÐŸÐ³ÐžÑ
+ ÐžÐ»Ðž Ð²ÑÐµÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² ÑÑÐ°Ð·Ñ - ÐœÐ°Ð¿ÑÐžÐŒÐµÑ,ÑÑÐŸÐ±Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ,ÑÐºÐŸÐ»ÑÐºÐŸ ÑÐ°Ð¹Ð»ÐŸÐ² ÐŸÑÑÐ°ÑÑÑÑ ÐŽÐ»Ñ Ð²ÐŸÐ·ÐŽÐµÐ¹ÑÑÐ²ÐžÑ ÐžÐ»Ðž Ð¿ÐŸÐ»ÑÑÐžÑÑ ÐœÐµÐºÐŸÑÐŸÑÑÐµ ÐžÐŽÐµÐž ÐŸÑÐœÐŸÑÐžÑÐµÐ»ÑÐœÐŸ ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÐµÐœÐžÑ ÐŽÐ°ÐœÐœÑÑ
+.</p>
+<p>ÐÑÐ±ÐµÑÐžÑÐµ ÑÐ°Ð¹Ð»Ñ, ÐºÐŸÑÐŸÑÑÐµ Ð²Ñ Ñ
+ÐŸÑÐžÑÐµ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ, Ð¿ÐŸÑÐŸÐŒ ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° Ð¿ÑÐ°Ð²ÑÑ ÐºÐœÐŸÐ¿ÐºÑ ÐŒÑÑÐž Ðž Ð²ÑÐ±ÐµÑÐžÑÐµ "ÐÐ°Ð·ÐœÐ°ÑÐµÐœÑÐµ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÐµ...". ÐÐŸÑÐ²Ð»ÑÐµÑÑÑ ÐŸÐºÐœÐŸ,ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒÐŸÐµ "ÐÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ", Ð·Ð°ÐœÑÑÐŸÐµ Ð±ÐŸÐ»ÑÑÐŸÐ¹ ÑÐ°Ð±Ð»ÐžÑÐµÐ¹,ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐµÐ¹ ÐŒÐœÐŸÐ³ÐŸ ÐºÐŸÐ»ÐŸÐœÐŸÐº.ÐÐµÑÐ²Ð°Ñ ÐºÐŸÐ»ÐŸÐœÐºÐž Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐžÐŒÐµÐœÐ° ÑÐ°Ð¹Ð»ÐŸÐ²;ÑÑÑÐŸÐºÐž Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÑÑ Ð²ÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+,Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ ÐŽÐ»Ñ ÑÑÐžÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ².  </p>
+<p>Ð ÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÑÐ°Ð±Ð»ÐžÑÑ ÐŒÐŸÐ¶ÐµÑ Ð·Ð°ÐœÑÑÑ ÐœÐµÐºÐŸÑÐŸÑÐŸÐµ Ð²ÑÐµÐŒÑ,ÐµÑÐ»Ðž Ð²ÑÐ¿Ð°Ð»ÐŸ ÐŒÐœÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»ÐŸÐ².ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÑÐŸÐŽÐŸÐ»Ð¶Ð°ÑÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐŒ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐŸÐŒ Ð¿ÑÐž ÐŸÑÐºÑÑÑÐŸÐŒ ÐŸÐºÐœÐµ "ÐÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ". </p>
+<p>ÐÐŸÐ³ÐŽÐ° ÐŸÐœÐ° ÑÑÐ°ÐœÐŸÐ²ÐžÑÑÑ ÑÐ»ÐžÑÐºÐŸÐŒ Ð±ÐŸÐ»ÑÑÐŸÐ¹,ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐŸÑÑÐžÐ»ÑÑÑÐŸÐ²Ð°ÑÑ ÑÐ°Ð±Ð»ÐžÑÑ "ÐÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ",Ð¿ÑÐžÐŒÐµÐœÑÑ ÑÐžÐ»ÑÑÑÑ Ðº ÐºÐŸÐ»ÐŸÐœÐºÐ°ÐŒ.ÐÐŸÑÐºÐŸÐ»ÑÐºÑ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÑ ÐœÐŸÐ²ÑÐµ ÑÐžÐ»ÑÑÑÑ, ÑÐŸÐ»ÑÐºÐŸ ÑÐµ ÑÑÑÐŸÐºÐž,ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑ ÐžÐŒ,ÐŸÑÑÐ°ÑÑÑÑ Ð²ÐžÐŽÐžÐŒÑÐŒÐž.Ð§ÑÐŸÐ±Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ,ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐžÐ»Ðž ÐŸÑÐžÑÑÐžÑÑ ÑÐžÐ»ÑÑÑ,ÑÐµÐ»ÐºÐœÐžÑÐµ Ð¿ÐŸ ÐžÐºÐŸÐœÐºÐµ "ÐÐŸÑÐŸÐœÐºÐ°" ÐœÐ°Ð²ÐµÑÑ
+Ñ ÐºÐŸÐ»ÐŸÐœÐºÐž. Ð£ Ð²Ð°Ñ Ð±ÑÐŽÐµÑ Ð·Ð°Ð¿ÑÐŸÑÐµÐœÐ° ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ ÑÐžÐ»ÑÑÑÐµ. ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÑÐžÐ»ÑÑÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ,ÐžÐ·ÐŒÐµÐœÑÐµÑÑÑ ÑÐ²ÐµÑ ÐºÐŸÐ»ÐŸÐœÐºÐž.</p>
+<p>ÐÐ°Ð¿ÑÐŸÑ ÐžÐŒÐµÐµÑ ÑÐžÐŒÐ²ÐŸÐ»Ñ "ÐÑÐŸÑÑÐŸÐ¹" Ðž "ÐÑÐŸÐŽÐ²ÐžÐœÑÑÑÐ¹".ÐÑÐŸÑÑÐ°Ñ Ð²ÐµÑÑÐžÑ ÑÐžÐ»ÑÑÑÑÐµÑ ÐºÐŸÐ»ÐŸÐœÐºÐž ÑÐ°Ðº,ÑÑÐŸ ÐŸÐœÐž Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÑÑ ÑÐŸÐ»ÑÐºÐŸ ÑÑÑÐŸÐºÐž, ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐŽÐµÑÐ¶Ð°Ñ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ("*" ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÐµÑ Ð²ÑÐµÐŒ Ð·ÐœÐ°ÑÐµÐœÐžÑÐŒ).ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐ±ÑÐ°ÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐžÐ· ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐ³ÐŸ ÑÐ¿ÐžÑÐºÐ°.ÐÑÐŸÐŽÐ²ÐžÐœÑÑÐ°Ñ Ð²ÐµÑÑÐžÑ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð²ÑÐ¿ÐŸÐ»ÐœÑÑÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ:ÐÐŸÐ»Ð¶ÐµÐœ ÐœÐ°ÑÐ°ÑÑÑÑ Ñ,ÐÐµ ÑÐŸÐŽÐµÑÐ¶ÐžÑ,Ð Ð°Ð»ÑÐ°Ð²ÐžÑÐœÐŸÐŒ Ð¿ÐŸÑÑÐŽÐºÐµ,ÐÐµÐœÑÑÐµ ÑÐµÐŒ, Ð­ÐºÐ²ÐžÐ²Ð°Ð»ÐµÐœÑÐµÐœ. ÐÐœÐ°ÑÐµÐœÐžÐµ, ÐºÐŸÑÐŸÑÐŸÐµ Ð±ÑÐŽÐµÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐŸÐ²Ð°ÑÑ, ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐŸ ÑÐ°Ðº,ÑÑÐŸÐ±Ñ Ð±ÑÑÑ Ð»ÑÐ±ÐŸÐ¹ ÑÑÑÐŸÐºÐŸÐ¹,Ð²ÐºÐ»ÑÑÐ°Ñ "*". ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐ±ÑÐ°ÑÑ,ÐŽÐŸÐ»Ð¶ÐœÐŸ Ð»Ðž ÑÑÐŸ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐµ Ð±ÑÑÑ ÐœÐµ ÑÑÐ²ÑÑÐ²ÐžÑÐµÐ»ÑÐœÑÐŒ ÑÐ»ÑÑÐ°ÐµÐŒ. ÐÐ°ÐºÐŸÐœÐµÑ,ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ Ð²ÑÐŸÑÐŸÐµ ÑÑÐ»ÐŸÐ²ÐžÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÑ,ÐºÐŸÑÐŸÑÐŸÐµ ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐŽÐ»Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ ÑÐ°ÐœÐ³Ð° Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ (Ð²ÑÐ±ÐžÑÐ°Ñ Ð Ð±ÐŸÐ»ÑÑÐŸÐµ) ÐžÐ»Ðž Ð°Ð»ÑÑÐµÑÐœÐ°ÑÐžÐ²ÐœÑÑ
+ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ (Ð²ÑÐ±ÐžÑÐ°Ñ ÐÐÐ).ÐÐžÐ¶Ðµ ÑÑÐŸÐ¹ ÐŸÐ±Ð»Ð°ÑÑÐž ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð¿ÐŸÐ»Ðµ, ÐºÐŸÑÐŸÑÐŸÐµ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐÐ°ÐŒ ÐžÐ·ÐŒÐµÐœÑÑÑ Ð¿ÐŸÑÑÐŽÐŸÐº ÑÐŸÑÑÐžÑÐŸÐ²ÐºÐž (Ð²ÐŸÐ·ÑÐ°ÑÑÐ°ÑÑÐžÐ¹ ÐžÐ»Ðž Ð¿ÐŸÐœÐžÐ¶Ð°ÑÐžÐ¹ÑÑ).ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐÑ Ð·Ð°ÐºÐŸÐœÑÐžÑÐµ,ÐœÐ°Ð¶ÐŒÐžÑÐµ "Ð£ÑÑÐ°ÐœÐŸÐ²ÐºÐ° ÑÐžÐ»ÑÑÑÐ°",ÑÑÐŸÐ±Ñ Ð¿ÑÐžÐŒÐµÐœÐžÑÑ ÐœÐŸÐ²ÑÐ¹ ÑÐžÐ»ÑÑÑ Ðº ÐºÐŸÐ»ÐŸÐœÐºÐµ.ÐÐ°Ð¶ÐŒÐžÑÐµ "ÐÑÐžÑÑÐžÑÑ ÑÐžÐ»ÑÑÑ",ÑÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÑÐµÐºÑÑÐžÐ¹ ÑÐžÐ»ÑÑÑ.ÐÐ±ÑÐ°ÑÐžÑÐµ Ð²ÐœÐžÐŒÐ°ÐœÐžÐµ ÐœÐ° ÑÐŸ,ÑÑÐŸ ÐŽÐµÑÐ°Ð»Ðž ÑÐžÐ»ÑÑÑÐ° ÑÐŸÑ
+ÑÐ°ÐœÑÑÑÑÑ, ÐŽÐ°Ð¶Ðµ ÐºÐŸÐ³ÐŽÐ° ÑÐžÐ»ÑÑÑ ÐŸÑÐžÑÐµÐœ.</p>
+<p>ÐÐ°Ð¿ÑÐžÐŒÐµÑ,ÑÑÐŸÐ±Ñ ÐŸÑÑÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÑÐ°Ð±Ð»ÐžÑÑ "ÐÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ",Ð²ÑÐ±ÐµÑÐžÑÐµ ÐºÐŸÐ»ÐŸÐœÐºÑ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÑ ÑÐžÐ»ÑÑÑÐ° Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ (Ð¿ÑÐŸÑÑÐŸÐ¹ ÑÐžÐ»ÑÑÑ ÐœÐ° "*") Ðž Ð²ÐŸÐ·ÑÐ°ÑÑÐ°ÑÑÐžÐ¹ ÐžÐ»Ðž Ð¿ÐŸÐœÐžÐ¶Ð°ÑÑÐžÐ¹ÑÑ Ð¿ÐŸÑÑÐŽÐŸÐº.   </p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/savingacollection.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/savingacollection.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/savingacollection.htm	(revision 13928)
@@ -0,0 +1,25 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="savingacollection"><font face="Verdana" size="5"><strong>2.2: Ð¡ÐŸÑ
+ÑÐ°ÐœÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð¡ÐŸÑ
+ÑÐ°ÐœÑÐ¹ÑÐµ ÐÐ°ÑÑ ÑÐ°Ð±ÐŸÑÑ ÑÐµÐ³ÑÐ»ÑÑÐœÐŸ, ÐŸÑÐºÑÑÐ²Ð°Ñ ÐŒÐµÐœÑ "Ð€Ð°Ð¹Ð»" Ðž Ð²ÑÐ±ÐžÑÐ°Ñ Ð² ÐœÑÐŒ Ð¿ÑÐœÐºÑ "Ð¡ÐŸÑ
+ÑÐ°ÐœÐžÑÑ". Ð¡ÐŸÑ
+ÑÐ°ÐœÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž - ÑÑÐŸ ÐœÐµ ÑÐŸ Ð¶Ðµ ÑÐ°ÐŒÐŸÐµ, ÐºÐ°Ðº  ÑÐŽÐµÐ»Ð°ÑÑ ÐµÑ Ð³ÐŸÑÐŸÐ²ÐŸÐ¹ Ðº ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ Ð² Greenstone.
+(see <a href="producingthecollection.htm">ÐÐŸÑÑÑÐŸÐµÐœÐžÐµ ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</a>).</p>
+<p>ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð·Ð°ÑÐžÑÐ°ÐµÑ ÐÐ°ÑÑ ÑÐ°Ð±ÐŸÑÑ Ð¿ÑÑÑÐŒ ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐžÑ ÐµÑ Ð²ÑÑÐºÐžÐ¹ ÑÐ°Ð·, ÐºÐŸÐ³ÐŽÐ° ÐÑ Ð²ÑÑ
+ÐŸÐŽÐžÑÐµ ÐžÐ· Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐžÐ»Ðž Ð·Ð°Ð³ÑÑÐ¶Ð°ÐµÑÐµ ÐŽÑÑÐ³ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ.</p>
+<p>Ð¡ÐŸÑ
+ÑÐ°ÐœÐµÐœÐœÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð·Ð°Ð¿ÐžÑÑÐ²Ð°ÑÑÑÑ  Ð² ÑÐ°Ð¹Ð», ÐžÐŒÐµÑÑÐžÐ¹ ÑÐŸ Ð¶Ðµ ÐžÐŒÑ, ÑÑÐŸ Ðž ÐžÐŒÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ñ ÑÐ°ÑÑÐžÑÐµÐœÐžÐµÐŒ ".col", Ðž ÑÐ°ÑÐ¿ÐŸÐ»Ð°Ð³Ð°ÐµÑÑÑ Ð² Ð¿Ð°Ð¿ÐºÐµ ÑÐŸÐ³ÐŸ Ð¶Ðµ ÐœÐ°ÐžÐŒÐµÐœÐŸÐ²Ð°ÐœÐžÑ, ÑÑÐŸ Ðž Ð¿Ð°Ð¿ÐºÐ° "collect" Ð¿ÑÐž ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž Greenstone.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/searchindexes.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/searchindexes.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/searchindexes.htm	(revision 13928)
@@ -0,0 +1,31 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="searchindexes"><font face="Verdana" size="5"><strong>6.5: ÐÐœÐŽÐµÐºÑÑ Ð¿ÐŸÐžÑÐºÐ°</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>ÐÐœÐŽÐµÐºÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑ,ÐºÐ°ÐºÐžÐµ ÑÐ°ÑÑÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÐ²Ð»ÑÑÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž ÐŽÐ»Ñ Ð¿ÐŸÐžÑÐºÐ°. Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ,ÐºÐ°Ðº ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ Ðž ÑÐŽÐ°Ð»ÐžÑÑ ÐžÐœÐŽÐµÐºÑÑ,Ð° ÑÐ°ÐºÐ¶Ðµ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÐžÐœÐŽÐµÐºÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ.ÐÐŸÐŽ "Ð Ð°Ð·ÐŽÐµÐ»Ð°ÐŒÐž ÐŽÐžÐ·Ð°Ð¹ÐœÐ°" ÑÐµÐ»ÐºÐœÐžÑÐµ ÐžÐœÐŽÐµÐºÑÑ Ð¿ÐŸÐžÑÐºÐ°.</p>
+<p>Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐžÐœÐŽÐµÐºÑ,Ð²Ð²ÐµÐŽÐžÑÐµ ÐžÐŒÑ ÐŽÐ»Ñ ÐœÐµÐ³ÐŸ Ð² Ð¿ÐŸÐ»Ðµ "ÐÐŒÑ ÐžÐœÐŽÐµÐºÑÐ°".ÐÑÐ±ÐµÑÐžÑÐµ, ÐºÐ°ÐºÐžÐµ ÐžÐ· Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÑÑ
+ ÐžÑÑÐŸÑÐœÐžÐºÐŸÐ² ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž Ð¿ÑÐžÑÐŸÐµÐŽÐžÐœÐžÑÑ Ðº ÐžÐœÐŽÐµÐºÑÑ, ÑÐµÐ»ÐºÐ°Ñ ÐœÐ° Ð¿ÐŸÐ»Ðµ ÐŸÐºÐŸÐ»ÐŸ ÐœÐžÑ
+. Ð¡Ð¿ÐžÑÐŸÐº Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð²ÑÐµ Ð·Ð°ÐŽÐ°ÐœÐœÑÐµ ÑÐ»ÐµÐŒÐµÐœÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, Ð° ÑÐ°ÐºÐ¶Ðµ Ð¿ÐŸÐ»ÐœÑÐ¹ ÑÐµÐºÑÑ. Ð Ð°ÑÐ¿ÐŸÐ»Ð°Ð³Ð°Ñ Ð²ÑÐ±ÑÐ°ÐœÐœÑÐŒÐž ÐžÑÑÐŸÑÐœÐžÐºÐ°ÐŒÐž ÐŽÐ°ÐœÐœÑÑ
+, Ð²ÑÐ±ÐµÑÐžÑÐµ ÑÑÐµÐ¿ÐµÐœÑ ÐŽÐµÑÐ°Ð»ÐžÐ·Ð°ÑÐžÐž ÐžÐœÐŽÐµÐºÑÐ°, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐŒÐµÐœÑ "ÐÐ° ÑÑÐŸÐ²ÐœÐµ". ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÑÑÐž ÐŽÐµÑÐ°Ð»Ðž ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÑ,Ð¿ÑÐœÐºÑ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ ÐžÐœÐŽÐµÐºÑ" ÑÑÐ°ÐœÐŸÐ²ÐžÑÑÑ Ð°ÐºÑÐžÐ²ÐœÑÐŒ (ÐµÑÐ»Ðž ÐœÐµÑ ÑÑÑÐµÑÑÐ²ÑÑÑÐµÐ³ÐŸ ÐžÐœÐŽÐµÐºÑÐ° Ñ ÑÐµÐŒÐž Ð¶Ðµ ÑÐ°ÐŒÑÐŒÐž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐ°ÐŒÐž).Ð©ÐµÐºÐœÐžÑÐµ ÐœÐ° ÐœÑÐŒ, ÑÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐœÐŸÐ²ÑÐ¹ ÐžÐœÐŽÐµÐºÑ.</p>
+<p>Ð§ÑÐŸÐ±Ñ ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ ÐžÐœÐŽÐµÐºÑ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ Ðž ÐžÐ·ÐŒÐµÐœÐžÑÐµ ÐŽÐµÑÐ°Ð»Ðž. ÐÐŸÐŽÑÐ²ÐµÑÐŽÐžÑÐµ, ÐœÐ°Ð¶Ð°Ð² ÐœÐ° "ÐÐ°ÐŒÐµÐœÐžÑÑ ÐžÐœÐŽÐµÐºÑ".</p>
+<p>Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÐžÐœÐŽÐµÐºÑ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° ÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐœÑÑ
+ ÐžÐœÐŽÐµÐºÑÐŸÐ² Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ ÐžÐœÐŽÐµÐºÑ".</p>
+<p>Ð§ÑÐŸÐ±Ñ ÑÐŸÐ·ÐŽÐ°ÑÑ ÐžÐœÐŽÐµÐºÑ ÐžÐ· ÑÐºÐŸÐœÐ²ÐµÑÑÐžÑÐŸÐ²Ð°ÐœÐœÐŸÐ³ÐŸ ÑÐµÐºÑÑÐ° Ðž Ð²ÑÐµÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÐœÐ°Ð¶ÐŒÐžÑÐµ "ÐÑÐ±ÑÐ°ÑÑ ÐÑÐµ".</p>
+<p>ÐÐœÐŽÐµÐºÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ - ÑÐŸÑ, ÐºÐŸÑÐŸÑÑÐ¹ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐœÐ° Ð¿ÐŸÐžÑÐºÐŸÐ²ÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž,Ð¿ÐŸÐŒÐµÑÐµÐœ ÑÑÐ³Ð°ÐŒÐž "[ÐÐœÐŽÐµÐºÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ]" Ð² ÑÐ¿ÐžÑÐºÐµ "ÐÐ°ÐŽÐ°ÐœÐœÑÐµ ÐžÐœÐŽÐµÐºÑÑ".Ð§ÑÐŸÐ±Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÐµÐ³ÐŸ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐžÐœÐŽÐµÐºÑ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÑÑÐ°ÐœÐŸÐ²ÐžÑÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ".</p>
+<p>ÐÑÐ»Ðž Ð¿ÐŸÐ·Ð²ÐŸÐ»ÐµÐœ ÑÐ°ÑÑÐžÑÐµÐœÐœÑÐ¹ Ð¿ÐŸÐžÑÐº (ÑÐµÑÐµÐ· Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ Ð²ÐžÐŽÐŸÐ² Ð¿ÐŸÐžÑÐºÐ°), ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐžÐœÐŽÐµÐºÑÐŸÐŒ ÐŸÑÐ»ÐžÑÐ°ÐµÑÑÑ. ÐÐŒÐµÐµÑÑÑ ÐœÐŸÐ²ÑÐ¹ ÐžÑÑÐŸÑÐœÐžÐº Ð¿ÑÐµÐ²ÐŽÐŸÐŽÐ°ÐœÐœÑÑ
+ "Ð²ÑÐµ Ð¿ÐŸÐ»Ñ",ÐºÐŸÑÐŸÑÑÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÑÑ Ð¿ÐŸÐžÑÐº Ð¿ÐŸ Ð²ÑÐµÐŒ ÑÐºÐ°Ð·Ð°ÐœÐœÑÐŒ ÐžÐœÐŽÐµÐºÑÐ°ÐŒ ÑÑÐ°Ð·Ñ.Ð£ÑÐŸÐ²ÐœÐž ÐœÐµ Ð¿ÑÐžÐ²ÑÐ·Ð°ÐœÑ Ðº ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐŸÐŒÑ ÐžÐœÐŽÐµÐºÑÑ,Ð° Ð¿ÑÐžÐŒÐµÐœÑÑÑÑÑ ÐºÐŸ Ð²ÑÐµÐŒ ÐžÐœÐŽÐµÐºÑÐ°ÐŒ.Ð¢Ð°ÐºÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ,ÐžÐœÐŽÐµÐºÑÑ Ðž ÑÑÐŸÐ²ÐœÐž ÐŽÐŸÐ±Ð°Ð²Ð»ÑÑÑÑÑ ÐŸÑÐŽÐµÐ»ÑÐœÐŸ. "ÐÐŸÐ±Ð°Ð²ÐžÑÑ ÐÑÐµ" ÑÐŸÐ·ÐŽÐ°ÐµÑ ÐŸÑÐŽÐµÐ»ÑÐœÑÐ¹ ÐžÐœÐŽÐµÐºÑ ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ Ð¿ÐŸÐ»Ñ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ð² ÑÑÐŸÐŒ ÑÐµÐ¶ÐžÐŒÐµ.</p>
+<p>ÐÐŒÑ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÐžÐœÐŽÐµÐºÑÐ° Ð±ÑÐŽÐµÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ ÑÐ²ÑÐ·Ð°ÐœÐŸ Ñ ÐžÐŒÐµÐœÐµÐŒ ÐžÑÑÐŸÑÐœÐžÐºÐ°.Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐžÐŒÑ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐžÐœÐŽÐµÐºÑ,ÐžÐ·ÐŒÐµÐœÐžÑÐµ ÐµÐ³ÐŸ ÐŽÐµÑÐ°Ð»Ðž Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐ°ÐŒÐµÐœÐžÑÑ ÐžÐœÐŽÐµÐºÑ".   </p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/searchtypes.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/searchtypes.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/searchtypes.htm	(revision 13928)
@@ -0,0 +1,22 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="searchtypes"><font face="Verdana" size="5"><strong>6.4: ÐÐžÐŽÑ Ð¿ÐŸÐžÑÐºÐ°</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ,ÐºÐ°Ðº ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐŸÑÐŸÐ±ÐµÐœÐœÐŸÑÑÐž ÐœÐŸÐ²ÐŸÐ³ÐŸ ÐŽÐžÐ·Ð°Ð¹ÐœÐ° Ð² Greenstone; Ð²ÐžÐŽÑ Ð¿ÐŸÐžÑÐºÐ°,ÐºÐŸÑÐŸÑÑÐµ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑ Ð¿ÑÐŸÐ²ÐŸÐŽÐžÑÑ Ð¿ÐŸÐžÑÐº Ð¿ÐŸ Ð¿ÐŸÐ»ÑÐŒ. ÐÐžÐŽÑ Ð¿ÐŸÐžÑÐºÐ° ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑ, ÐºÐ°ÐºÐŸÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÐŸÐžÑÐºÐ° ÐŽÐŸÐ»Ð¶ÐµÐœ Ð±ÑÑÑ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœ: ÑÐŸÑÐŒÐ° ÐŽÐ»Ñ Ð¿ÐŸÐ»ÐµÐ¹ Ð¿ÐŸÐžÑÐºÐ° Ðž/ÐžÐ»Ðž Ð¿ÑÐŸÑÑÐŸÐ¹ ÐŽÐ»Ñ ÑÐµÐ³ÑÐ»ÑÑÐœÐŸÐ³ÐŸ Ð¿ÐŸÐžÑÐºÐ°. Ð©ÐµÐ»ÐºÐœÐžÑÐµ Ð²ÐžÐŽÑ Ð¿ÐŸÐžÑÐºÐ° Ð² "Ð Ð°Ð·ÐŽÐµÐ»Ð°Ñ
+ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°".</p>
+<p>ÐÐŸÐ³ÐŽÐ° ÐÑ ÐœÐ°ÑÐžÐœÐ°ÐµÑÐµ Ð¿ÑÐŸÑÐŒÐŸÑÑ Ð²ÐžÐŽÐŸÐ² Ð¿ÐŸÐžÑÐºÐ°, ÑÐœÐ°ÑÐ°Ð»Ð° Ð²ÑÐ±ÐµÑÐžÑÐµ "ÐÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑ ÑÐ°ÑÑÐžÑÐµÐœÐœÐŸÐ³ÐŸ Ð¿ÐŸÐžÑÐºÐ°",ÐºÐŸÑÐŸÑÑÐ¹ Ð°ÐºÑÐžÐ²ÐžÐ·ÐžÑÑÐµÑ ÐŽÑÑÐ³ÐžÐµ ÑÑÐµÐŽÑÑÐ²Ð° ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ. ÐÑÐž ÑÑÐŸÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð±ÑÐŽÐµÑ ÐžÐ·ÐŒÐµÐœÐµÐœÐ°: ÐžÐœÐŽÐµÐºÑÐžÑÑÑÑÐžÐ¹ ÐŒÐµÑ
+Ð°ÐœÐžÐ·ÐŒ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÐžÑ Ð¿ÑÐŸÐ²ÐµÑÑÐž Ð¿ÐŸÐžÑÐº Ñ ÐžÑÐ¿ÐŸÐ»ÐžÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ Ð¿ÐŸÐžÑÐºÐŸÐ²ÑÑ
+ Ð¿ÐŸÐ»ÐµÐ¹. Ð¡Ð¿ÐµÑÐžÑÐžÐºÐ°ÑÐžÑ ÐžÐœÐŽÐµÐºÑÐ° Ð² ÑÑÐŸÐŒ ÑÐµÐ¶ÐžÐŒÐµ ÐœÐµÐŒÐœÐŸÐ³ÐŸ ÐžÐ·ÐŒÐµÐœÐµÐœÐ°. (ÐÑÐž Ð¿ÐµÑÐµÐºÐ»ÑÑÐµÐœÐžÐž ÐŒÐµÐ¶ÐŽÑ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÐŒ Ðž Ð¿ÑÐŸÐŽÐ²ÐžÐœÑÑÑÐŒ Ð¿ÑÐžÑÐºÐŸÐŒ ÐÐÐ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑ ÐºÐŸÐœÐ²ÐµÑÑÐžÐ²ÐŸÐ²Ð°ÐœÐžÐµ, ÐºÐŸÑÐŸÑÐŸÐµ ÐžÐœÐŸÐ³ÐŽÐ° ÐœÐµ ÐŽÐŸÑÑÐ°ÑÐŸÑÐœÐŸ ÑÐŸÑÐœÐŸ.)</p>
+<p>Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ Ð²ÐžÐŽ Ð¿ÐŸÐžÑÐºÐ°,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° "ÐÐžÐŽÑ Ð¿ÐŸÐžÑÐºÐ°" Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ Ð²ÐžÐŽ Ð¿ÐŸÐžÑÐºÐ°".ÐÐ°Ð¶ÐŽÑÐ¹ Ð²ÐžÐŽ Ð¿ÐŸÐžÑÐºÐ° ÐŒÐŸÐ¶ÐµÑ Ð¿ÐŸÑÐ²ÐžÑÑÑÑ Ð² ÑÐ¿ÐžÑÐºÐµ ÑÐŸÐ»ÑÐºÐŸ ÐŸÐŽÐžÐœ ÑÐ°Ð·. ÐÐµÑÐ²ÑÐ¹ Ð²ÐžÐŽ Ð¿ÐŸÐžÑÐºÐ° Ð±ÑÐŽÐµÑ Ð¿ÐŸ-ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ Ðž ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑÑ ÐœÐ° ÑÑÑÐ°ÐœÐžÑÐµ Ð¿ÐŸÐžÑÐºÐ° ÑÐŸÐ·ÐŽÐ°ÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑÐµ ÐŸÑÑÐ°Ð»ÑÐœÑÐµ Ð²ÐžÐŽÑ ÐŒÐŸÐ¶ÐœÐŸ Ð±ÑÐŽÐµÑ Ð²ÑÐ±ÑÐ°ÑÑ ÐœÐ° ÑÑÑÐ°ÐœÐžÑÐµ ÐŸÐ¿ÑÐžÐ¹.</p>
+<p>Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ Ð²ÐžÐŽ Ð¿ÐŸÐžÑÐºÐ°, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° "Ð¢ÐµÐºÑÑÐžÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ Ð²ÐžÐŽÐŸÐ² Ð¿ÐŸÐžÑÐºÐ°" Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ Ð²ÐžÐŽ Ð¿ÐŸÐžÑÐºÐ°".Ð¡Ð¿ÐžÑÐŸÐº ÐŽÐŸÐ»Ð¶ÐµÐœ ÑÐŸÐŽÐµÑÐ¶Ð°ÑÑ Ð¿ÐŸ ÐºÑÐ°Ð¹ÐœÐµÐ¹ ÐŒÐµÑÐµ ÐŸÐŽÐžÐœ Ð²ÐžÐŽ Ð¿ÐŸÐžÑÐºÐ°. </p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/selectingmetadatasets.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/selectingmetadatasets.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/selectingmetadatasets.htm	(revision 13928)
@@ -0,0 +1,30 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="selectingmetadatasets"><font face="Verdana" size="5"><strong>5.2: ÐÑÐ±ÐŸÑ ÐœÐ°Ð±ÐŸÑÐŸÐ² ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð£ÑÑÐ°ÐœÐŸÐ²ÐºÐ° ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐžÐ·Ð²ÐµÑÑÐœÐ° ÐºÐ°Ðº "ÐœÐ°Ð±ÐŸÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+". ÐÑÐžÐŒÐµÑÐŸÐŒ ÑÐ²Ð»ÑÐµÑÑÑ ÐœÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Dublin Core. ÐÐŸÐ³ÐŽÐ° ÐÑ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑÐµ ÐºÐŸÐŒÐ¿Ð»ÐµÐºÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ðº ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐŸ ÐµÐ³ÐŸ ÑÐ»ÐµÐŒÐµÐœÑÑ ÑÑÐ°ÐœÐŸÐ²ÑÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž ÐŽÐ»Ñ Ð²ÑÐ±ÐŸÑÐ°. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÐŒÐµÑÑ Ð±ÐŸÐ»ÑÑÐµ,ÑÐµÐŒ ÐŸÐŽÐžÐœ ÐœÐ°Ð±ÐŸÑ. ÐÐ»Ñ Ð¿ÑÐµÐŽÐŸÑÐ²ÑÐ°ÑÐµÐœÐžÑ ÑÑÐŸÐ»ÐºÐœÐŸÐ²ÐµÐœÐžÑ ÐŸÐŽÐžÐœÐ°ÐºÐŸÐ²ÑÑ
+ ÐžÐŒÑÐœ Ðº ÐœÐ°Ð·Ð²Ð°ÐœÐžÑ ÑÐ»ÐµÐŒÐµÐœÑÐ° Ð¿ÑÐžÑÐŸÐµÐŽÐžÐœÑÐµÑÑÑ ÐºÐŸÑÐŸÑÐºÐžÐ¹ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑ,ÐºÐŸÑÐŸÑÑÐ¹ Ð²ÑÐŽÐµÐ»ÑÐµÑ ÐœÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÑÐ»ÐµÐŒÐµÐœÑ Dublin Core "Creator" ÑÑÐ°ÐœÐµÑ "dc.Creator".ÐÐ°Ð±ÐŸÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ñ
+ÑÐ°ÐœÑÑÑÑ Ð² ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° Ðž ÐžÐŒÐµÑÑ ÑÑÑÑÐžÐºÑ ".mds".</p>
+<p>Ð§ÑÐŸÐ±Ñ ÐºÐŸÐœÑÑÐŸÐ»ÐžÑÐŸÐ²Ð°ÑÑ ÐœÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÑ
+ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð²ÑÐ±ÐµÑÐžÑÐµ "ÐÐ°Ð±ÐŸÑ ÐÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+" Ð² Ð¿ÑÐŸÑÐŒÐŸÑÑÐµ "ÐÐžÐ·Ð°Ð¹Ðœ".</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/startingoff.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/startingoff.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/startingoff.htm	(revision 13928)
@@ -0,0 +1,19 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="startingoff"><font face="Verdana" size="5"><strong>2: ÐÐŸ ÑÑÐ°ÑÑÐ°</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÑÐ°ÑÑÐºÐ°Ð·Ð°ÐœÐŸ, ÐºÐ°Ðº ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ, Ð·Ð°Ð³ÑÑÐ¶Ð°ÑÑ Ðž ÑÐŽÐ°Ð»ÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</p>
+
+
+
+
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/thecreateview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/thecreateview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/thecreateview.htm	(revision 13928)
@@ -0,0 +1,19 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="thecreateview"><font face="Verdana" size="5"><strong>7.1: Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ,ÑÑÐŸÐ±Ñ ÑÐŸÐ·ÐŽÐ°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ,Ð²ÑÐ¿ÐŸÐ»ÐœÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐµ ÑÑÐµÐœÐ°ÑÐžÐž Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Greenstone ÐžÐ· ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž, ÐºÐŸÑÐŸÑÑÑ ÐÑ Ð¿ÐŸÐŽÐ³ÐŸÑÐŸÐ²ÐžÐ»Ðž. Ð©ÐµÐ»ÑÐŸÐº ÐœÐ° "ÐÐŸÑÑÑÐŸÐµÐœÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž" ÐœÐ°ÑÐžÐœÐ°ÐµÑ Ð¿ÑÐŸÑÐµÑÑ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑÐµÐŒÑ, ÐºÐŸÑÐŸÑÐŸÐµ ÐŽÐ»Ñ ÑÑÐŸÐ³ÐŸ Ð¿ÐŸÑÑÐµÐ±ÑÐµÑÑÑ, Ð·Ð°Ð²ÐžÑÐžÑ ÐŸÑ ÑÐ°Ð·ÐŒÐµÑÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž ÑÐžÑÐ»Ð° ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÐµÐŒÑÑ
+ ÐžÐœÐŽÐµÐºÑÐŸÐ² (ÐŽÐ»Ñ ÐŸÐ³ÑÐŸÐŒÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÑÑÐŸ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐ°ÑÑ). ÐÐœÐŽÐžÐºÐ°ÑÐŸÑ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ ÑÐºÐ°Ð·ÑÐ²Ð°ÐµÑ, ÐœÐ°ÑÐºÐŸÐ»ÑÐºÐŸ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœ Ð¿ÑÐŸÑÐµÑÑ. Ð§ÑÐŸÐ±Ñ ÐŸÑÐŒÐµÐœÐžÑÑ Ð¿ÑÐŸÑÐµÑÑ Ð² Ð»ÑÐ±ÐŸÐµ Ð²ÑÐµÐŒÑ, ÐœÐ°Ð¶ÐŒÐžÑÐµ "ÐÑÐŒÐµÐœÐ° Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ".</p>
+<p>ÐÐ°Ð¶Ð°Ð² ÐœÐ° "ÐÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÑÐ¹ Ð¿ÑÐŸÑÐŒÐŸÑÑ" Ð¿ÐŸÑÐ»Ðµ ÑÐŸÐ³ÐŸ, ÐºÐ°Ðº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð±ÑÐ»Ð° ÑÑÐ¿ÐµÑÐœÐŸ ÑÐŸÐ±ÑÐ°ÐœÐ°, ÐŒÐŸÐ¶ÐœÐŸ ÐŸÑÐºÑÑÑÑ Ð²ÐµÐ±-Ð±ÑÐ°ÑÐ·ÐµÑ Ñ Ð³Ð»Ð°Ð²ÐœÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</p>
+<p>Ð ÐŒÐŸÐŽÑÑÐµ Ð­ÐºÑÐ¿ÐµÑÑ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð·Ð°Ð¿ÐžÑÑ "ÐÐŸÐ³ Ð¡ÐŸÐŸÐ±ÑÐµÐœÐžÐ¹" ÑÐ»ÐµÐ²Ð°, ÑÑÐŸÐ±Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ, Ð±ÑÐ»Ðž Ð»Ðž Ð¿ÑÐµÐŽÑÐŽÑÑÐžÐµ Ð¿ÐŸÐ¿ÑÑÐºÐž ÑÐºÐŸÐœÑÑÑÑÐžÑÐŸÐ²Ð°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÑÑÐ¿ÐµÑÐœÑ ÐžÐ»Ðž ÐœÐµÑ. ÐÑÐ±ÐµÑÐžÑÐµ Ð¶ÐµÐ»Ð°ÐµÐŒÑÑ Ð·Ð°Ð¿ÐžÑÑ,ÑÐµÐ»ÐºÐ°Ñ Ð¿ÐŸ Ð²ÑÐ±ÑÐ°ÐœÐœÐŸÐ¹ ÐŽÐ°ÑÐµ Ð² ÑÐ¿ÐžÑÐºÐµ "ÐÑÑÐŸÑÐžÑ Ð·Ð°Ð¿ÐžÑÐž".</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/thedesignview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/thedesignview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/thedesignview.htm	(revision 13928)
@@ -0,0 +1,22 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="thedesignview"><font face="Verdana" size="5"><strong>6.1: ÐÐžÐŽ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð­ÑÐŸÑ ÑÐ°Ð·ÐŽÐµÐ» Ð²Ð²ÐŸÐŽÐžÑ ÐÐ°Ñ Ð² ÑÐ°ÑÑÐŒÐ°ÑÑÐžÐ²Ð°ÐµÐŒÑÐ¹ Ð¿ÑÐŸÐµÐºÑ Ðž ÐŸÐ±ÑÑÑÐœÑÐµÑ,ÐºÐ°Ðº Ð²ÑÐ±ÑÐ°ÑÑ ÐŒÐµÐ¶ÐŽÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐŒÐž Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑÐŒÐž Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ Ð°ÐºÑÐžÐ²ÐœÐŸÐ¹ ÑÐ°ÑÑÐž ÐŸÐºÐœÐ°.</p>
+<p>ÐÑÐž Ð¿ÐŸÐŒÐŸÑÐž ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÑÑ Ð²ÐžÐŽÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÐµÐŒÐŸÐ¹ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ.ÐÐ°ÑÐžÐ°ÐœÑÑ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÑ ÐœÐ° ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ ÑÐ°Ð·ÐŽÐµÐ»Ñ, ÐºÐ°Ð¶ÐŽÑÐ¹ ÐžÐ· ÐºÐŸÑÐŸÑÑÑ
+ ÑÐ²ÑÐ·Ð°Ðœ ÑÐŸ ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐŸÐ¹ ÑÑÐ°ÐŽÐžÐµÐ¹ ÐœÐ°Ð²ÐžÐ³Ð°ÑÐžÐž ÐžÐ»Ðž Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž.</p>
+<p>Ð¡Ð»ÐµÐ²Ð° ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ ÑÐ¿ÐžÑÐŸÐº ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐ¹,Ð° ÑÐ¿ÑÐ°Ð²Ð° - ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÑÐµÐºÑÑÐžÐŒ ÑÐ¿ÐžÑÐºÐŸÐŒ.Ð§ÑÐŸÐ±Ñ Ð¿ÐµÑÐµÐ¹ÑÐž ÐœÐ° Ð²ÑÐ±ÑÐ°ÐœÐœÐŸÐµ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ,ÑÐµÐ»ÐºÐœÐžÑÐµ ÐµÐ³ÐŸ ÐžÐŒÑ Ð² ÑÐ¿ÐžÑÐºÐµ. </p>
+<p>Ð§ÑÐŸÐ±Ñ Ð¿ÐŸÐœÐžÐŒÐ°ÑÑ ÑÑÐ°ÐŽÐžÐž Ðž ÑÐµÑÐŒÐžÐœÑ,ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐµ Ð¿ÑÐž Ð¿ÑÐŸÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐœÐ°ÑÐ°Ð»Ð° Ð¿ÑÐŸÑÑÐžÑÐµ Ð³Ð»Ð°Ð²Ñ 1 Ðž 2 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone. </p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/theenrichview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/theenrichview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/theenrichview.htm	(revision 13928)
@@ -0,0 +1,46 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="theenrichview"><font face="Verdana" size="5"><strong>5.1: ÐÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐŸÐ±ÐŸÐ³Ð°ÑÐµÐœÐžÑ</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐŸÐ±ÐŸÐ³Ð°ÑÐµÐœÐžÑ ÐŽÐ»Ñ Ð·Ð°ÐŽÐ°ÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ - ÑÑÐŸ ÐŽÐ°ÐœÐœÑÐµ ÐŸ ÐŽÐ°ÐœÐœÑÑ
+ - ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÐÐ°Ð·Ð²Ð°ÐœÐžÐµ,ÐÐ²ÑÐŸÑ,ÐÐ°ÑÐ° ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ Ðž Ñ.ÐŽ. ÐÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ - ÑÑÐŸ ÐŽÐ°ÐœÐœÑÐµ ÐŸ ÐŽÐ°ÐœÐœÑÑ
+, ÐŸÐ±ÑÑÐœÐŸ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ, Ð°Ð²ÑÐŸÑ, ÐŽÐ°ÑÐ° ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° Ðž.Ñ.Ð¿. ÐÐ°Ð¶ÐŽÑÐ¹ Ð¿ÑÐµÐŽÐŒÐµÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÑÐŸÑÑÐŸÐžÑ ÐžÐ· ÐŽÐ²ÑÑ
+ ÑÐ°ÑÑÐµÐ¹: "ÑÐ»ÐµÐŒÐµÐœÑ" ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ, ÐºÐ°ÐºÐŸÐ¹ Ð¿ÑÐµÐŽÐŒÐµÑ ÐžÐŒÐµÐµÑÑÑ Ð²Ð²ÐžÐŽÑ (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, Ð°Ð²ÑÐŸÑ), Ð° "Ð·ÐœÐ°ÑÐµÐœÐžÐµ" Ð¿ÑÐžÑÐ²Ð°ÐžÐ²Ð°ÐµÑ ÑÑÐŸÐŒÑ ÑÐ»ÐµÐŒÐµÐœÑÑ ÐµÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÐžÐŒÑ Ð°Ð²ÑÐŸÑÐ°).</p>
+<p>Ð "ÑÐ°ÑÑÐžÑÐµÐœÐœÐŸÐŒ" Ð²ÐžÐŽÐµ ÑÐ»ÐµÐ²Ð° ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ ÐÐµÑÐµÐ²ÐŸ ÐÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐ¿ÑÐ°Ð²Ð° Ð¢Ð°Ð±Ð»ÐžÑÐ° ÐÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÐºÐŸÑÐŸÑÐ°Ñ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ Ð²ÑÐ±ÑÐ°ÐœÐœÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»Ð° ÐžÐ»Ðž Ð¿Ð°Ð¿ÐºÐž ÐžÐ· ÐÐµÑÐµÐ²Ð° ÐÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð¡ÑÐŸÐ»Ð±ÑÑ ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœÑ ÑÐµÑÑÐŒ ÑÐ²ÐµÑÐŸÐŒ Ð²Ð²ÐµÑÑ
+Ñ Ðž ÐžÑ
+ ÑÐ°Ð·ÐŒÐµÑ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐžÐ·ÐŒÐµÐœÑÐœ Ð¿ÑÑÑÐŒ Ð¿ÐµÑÐµÐŽÐ²ÐžÐ¶ÐµÐœÐžÑ Ð»ÐžÐœÐžÐž ÑÐ°Ð·ÐŽÐµÐ»Ð°. ÐÐ°Ð¶Ð°Ð² ÐœÐ° Ð»ÑÐ±ÐŸÐ¹ ÑÑÐŽ Ð² ÑÐ°Ð±Ð»ÐžÑÐµ, Ð²Ñ ÑÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ Ðž ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ ÐŽÐµÑÐ°Ð»Ðž ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+ Ð² ÐœÐžÐ¶ÐœÐµÐ¹ ÑÐµÐºÑÐžÐž ÐŸÐºÐœÐ°. Ð§ÐµÑÐœÑÐ¹ ÑÐµÐºÑÑ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ, ÑÑÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÑÐ²Ð»ÑÐµÑÑÑ ÐŸÐ±ÑÐžÐŒ ÐŽÐ»Ñ Ð²ÑÐµÑ
+ ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ²,ÑÐŸÐ³ÐŽÐ° ÐºÐ°Ðº ÑÐµÑÑÐ¹ ÑÐµÐºÑÑ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ,ÑÑÐŸ ÑÑÐŸ - ÐœÐµ ÑÐ°Ðº.Ð§ÐµÑÐœÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐŸÐ±ÐœÐŸÐ²Ð»ÐµÐœÑ ÐžÐ»Ðž ÑÐŽÐ°Ð»ÐµÐœÑ, Ð² ÑÐŸ Ð²ÑÐµÐŒÑ ÐºÐ°Ðº ÑÐµÑÑÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐŽÐ°Ð»ÐµÐœÑ ÐžÐ· ÑÐµÑ
+,ÐºÐŸÑÐŸÑÑÐµ ÐžÐŒÐµÑÑ ÐžÑ
+,ÐžÐ»Ðž ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÑ Ðº ÐŽÑÑÐ³ÐžÐŒ.  </p>
+<p>ÐÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ Ð¿Ð°Ð¿ÐºÐž ÐŒÐŸÐ¶ÐµÑ Ð¿ÐŸÑÐ²Ð»ÑÑÑÑÑ ÐŸÐºÐŸÐ»ÐŸ ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ Ð²Ñ
+ÐŸÐŽÐŸÐ² ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+.Ð­ÑÐŸ ÑÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐœÐ° ÑÐŸ,ÑÑÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÑÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÑ ÐŸÑ Ð¿Ð°Ð¿ÐŸÐº ÑÐŸÐŽÐžÑÐµÐ»ÐµÐ¹ (ÐžÐ»Ðž Ð¿ÑÐµÐŽÐºÐŸÐ²). Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐœÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÑ ÐžÐ»Ðž ÑÐŽÐ°Ð»ÐµÐœÑ, Ð° ÑÐŸÐ»ÑÐºÐŸ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÑ Ð² ÐºÐŸÐœÐµÑ ÑÐ¿ÐžÑÐºÐ° ÐžÐ»Ðž Ð¿ÐµÑÐµÐ¿ÐžÑÐ°ÐœÑ.Ð©ÐµÐ»ÐºÐœÐžÑÐµ ÐœÐ° ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐž Ð¿Ð°Ð¿ÐºÐž,ÑÑÐŸÐ±Ñ ÐœÐµÐŒÐµÐŽÐ»ÐµÐœÐœÐŸ Ð¿ÐµÑÐµÐ¹ÑÐž Ð² ÑÑ Ð¿Ð°Ð¿ÐºÑ, Ð³ÐŽÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ð·Ð°ÐŽÐ°ÐœÑ.  </p>
+<p>ÐÑÐ±ÐµÑÐžÑÐµ ÑÐ»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ð² ÑÐ°Ð±Ð»ÐžÑÐµ, ÑÑÐŸÐ±Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŽÐ»Ñ ÑÑÐŸÐ³ÐŸ ÑÐ»ÐµÐŒÐµÐœÑÐ° Ð² ÐŸÐ±Ð»Ð°ÑÑÐž "Ð¡ÑÑÐµÑÑÐ²ÑÑÑÐžÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŽÐ»Ñ ...", ÐœÐ°Ñ
+ÐŸÐŽÑÑÐµÐ¹ÑÑ Ð²ÐœÐžÐ·Ñ ÑÐ°Ð±Ð»ÐžÑÑ. ÐÐµÑÐµÐ²ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ ÐŒÐŸÐ¶ÐµÑ ÑÐ°ÑÑÐžÑÑÑÑÑÑ Ðž ÑÐ°Ð·ÑÑÑÐ°ÑÑÑÑ. ÐÐ±ÑÑÐœÐŸ ÑÑÐŸ - ÑÐ¿ÐžÑÐŸÐº, ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð²ÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ, Ð²Ð²ÐµÐŽÐµÐœÐœÑÐµ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ ÐŽÐ»Ñ ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÐŸÐ³ÐŸ ÑÐ»ÐµÐŒÐµÐœÑÐ°. Ð©ÐµÐ»ÑÐŸÐº ÐœÐ° Ð²Ñ
+ÐŸÐŽÐµ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž ÑÐ°Ð·ÐŒÐµÑÐ°ÐµÑ ÐµÐ³ÐŸ Ð² Ð¿ÐŸÐ»Ðµ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹. Ð¡ ÐŽÑÑÐ³ÐŸÐ¹ ÑÑÐŸÑÐŸÐœÑ,Ð¿ÑÐž ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°ÐœÐœÐŸÐŒ Ð·ÐœÐ°ÑÐµÐœÐžÐž Ð² ÑÐµÐºÑÑÐŸÐ²ÐŸÐŒ Ð¿ÐŸÐ»Ðµ Ð²ÑÐ±ÐŸÑÐºÐž ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² ÐÐµÑÐµÐ²Ð° Ð·ÐœÐ°ÑÐµÐœÐžÐ¹, ÑÐžÑÑÐµÐŒÐ° ÐœÐ°ÑÐžÐœÐ°ÐµÑ ÑÐ°Ð±ÐŸÑÑ Ñ ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÐÑ Ð²Ð²ÐµÐ»Ðž. ÐÐ°Ð¶Ð°ÑÐžÐµ [Tab] Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž Ð·Ð°Ð²ÐµÑÑÐ°ÐµÑ Ð¿ÐµÑÐ°ÑÐ°ÐœÐžÐµ ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÐŸÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÑ.</p>
+<p>ÐÐœÐ°ÑÐµÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐŸÑÐ³Ð°ÐœÐžÐ·ÐŸÐ²Ð°ÐœÑ Ð² ÐžÐµÑÐ°ÑÑ
+ÐžÑ. Ð­ÑÐŸ Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐŸ Ð² ÐÐµÑÐµÐ²Ðµ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ Ð¿Ð°Ð¿ÐºÐž ÐŽÐ»Ñ Ð²ÐœÑÑÑÐµÐœÐœÐžÑ
+ ÑÑÐŸÐ²ÐœÐµÐ¹. ÐÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐžÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð²Ð²ÐµÐŽÐµÐœÑ,ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ Ð·ÐœÐ°Ðº "|" ÐŽÐ»Ñ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ ÑÑÐŸÐ²ÐœÐµÐ¹. ÐÐ°Ð¿ÑÐžÐŒÐµÑ,"Cards|Red|Diamonds|Seven" ÐŒÐŸÐ³ Ð±Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ Ð² ÐžÐµÑÐ°ÑÑ
+ÐžÐž, Ð¿ÑÐžÐŒÐµÑÐŸÐŒ ÐºÐŸÑÐŸÑÐŸÐ¹ ÑÐ²Ð»ÑÐµÑÑÑ Ð¿Ð°ÐºÐµÑ ÐžÐ³ÑÑ Ð² ÐºÐ°ÑÑÑ.Ð­ÑÐŸ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð³ÑÑÐ¿Ð¿ÐžÑÐŸÐ²Ð°ÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÑ Ð²ÐŒÐµÑÑÐµ. ÐÑÑÐ¿Ð¿Ñ ÐŒÐŸÐ³ÑÑ ÑÐ°ÐºÐ¶Ðµ ÐœÐ°Ð·ÐœÐ°ÑÐ°ÑÑÑÑ ÐºÐ°Ðº ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ðº ÑÐ°Ð¹Ð»Ð°ÐŒ.  </p>
+<p>Greenstone Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž ÐžÐ·Ð²Ð»ÐµÐºÐ°ÐµÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐžÐ· ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ð² ÐœÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÑÐ»ÐµÐŒÐµÐœÑÑ ÐºÐŸÑÐŸÑÐŸÐ³ÐŸ ÐžÐŒÐµÑÑ Ð¿ÑÐµÑÐžÐºÑ "ex.". Ð­ÑÐŸ ÐœÐµ ÐžÐŒÐµÐµÑ ÐœÐžÐºÐ°ÐºÐŸÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŽÐµÑÐµÐ²Ð° Ðž ÐœÐµ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐŸ.  </p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/thegatherview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/thegatherview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/thegatherview.htm	(revision 13928)
@@ -0,0 +1,41 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="thegatherview"><font face="Verdana" size="5"><strong>4.1: ÐÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐœÐ°ÐºÐŸÐ¿ÐžÑÐµÐ»Ñ</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð­ÑÐŸÑ ÑÐ°Ð·ÐŽÐµÐ» Ð²Ð²ÐŸÐŽÐžÑ Ð² ÐŸÐ±Ð»Ð°ÑÑÑ ÐœÐ°ÐºÐŸÐ¿Ð»ÐµÐœÐžÑ,ÐºÐŸÑÐŸÑÑÑ ÐÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÐµ,ÑÑÐŸÐ±Ñ Ð²ÑÐ±ÑÐ°ÑÑ,ÐºÐ°ÐºÐžÐµ ÑÐ°Ð¹Ð»Ñ Ð²ÐºÐ»ÑÑÐ°ÑÑ Ð² ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÐµÐŒÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ ÐœÐ°ÑÐžÐœÐ°ÐµÑÑÑ Ñ ÐŸÐ±Ð·ÐŸÑÐ° ÐœÐ°ÐºÐŸÐ¿Ð»ÐµÐœÐžÑ. Ð§ÑÐŸÐ±Ñ Ð²ÐµÑÐœÑÑÑÑÑ Ðº ÑÑÐŸÐŒÑ ÐŸÐ±Ð·ÐŸÑÑ Ð¿ÐŸÐ·Ð¶Ðµ,ÑÐµÐ»ÐºÐœÐžÑÐµ ÐœÐ° ÑÐžÐŒÐ²ÐŸÐ»Ðµ "Gather", ÑÐ°ÑÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐœÑÐŒ ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ ÐœÐžÐ¶Ðµ Ð»ÐžÐœÐµÐ¹ÐºÐž ÐŒÐµÐœÑ.  </p>
+<p>ÐÐ²Ðµ Ð±ÐŸÐ»ÑÑÐžÐµ ÐŸÐ±Ð»Ð°ÑÑÐž,ÐœÐ°Ð·Ð²Ð°ÐœÐœÑÐµ "Ð Ð°Ð±ÐŸÑÐµÐµ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²ÐŸ" Ðž "ÐoÐ»Ð»ÐµÐºÑÐžÑ" ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ,ÑÑÐŸÐ±Ñ Ð¿ÐµÑÐµÐŒÐµÑÑÐžÑÑ ÑÐ°Ð¹Ð»Ñ Ð² ÐÐ°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. ÐÐœÐž Ð²ÐºÐ»ÑÑÐ°ÑÑ "ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐµ ÐŽÐµÑÐµÐ²ÐŸ",Ð³ÑÐ°ÑÐžÑÐµÑÐºÐžÐµ ÑÑÑÑÐºÑÑÑÑ,ÐºÐŸÑÐŸÑÑÐµ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶Ð°ÑÑ ÑÐ°Ð¹Ð»Ñ Ðž Ð¿Ð°Ð¿ÐºÐž. </p>
+<p>ÐÑÐ±ÐµÑÐžÑÐµ ÑÐ»ÐµÐŒÐµÐœÑ ÐŽÐµÑÐµÐ²Ð°, ÐœÐ°Ð¶Ð°Ð² ÐœÐ° ÐœÐµÐ³ÐŸ Ð»ÐµÐ²ÐŸÐ¹ ÐºÐ»Ð°Ð²ÐžÑÐµÐ¹ ÐŒÑÑÐž. (Ð¢ÐŸ Ð¶Ðµ ÑÐ°ÐŒÐŸÐµ ÐŒÐŸÐ¶ÐœÐŸ ÑÐŽÐµÐ»Ð°ÑÑ ÐžÐœÐ°ÑÐµ, ÑÐŒ. ÐœÐžÐ¶Ðµ). ÐÐ²ÐŸÐ¹ÐœÑÐŒ ÑÐµÐ»ÑÐºÐŸÐŒ Ð²ÑÐ±ÐµÑÐžÑÐµ Ð¿Ð°Ð¿ÐºÑ, ÐžÐ»Ðž ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÑÐžÐŒÐ²ÐŸÐ» ÑÑÐŽÐŸÐŒ Ñ ÐœÐµÐ¹, ÑÑÐŸÐ±Ñ ÑÐ°Ð·Ð²ÐµÑÐœÑÑÑ (ÐžÐ»Ðž ÑÐ²ÐµÑÐœÑÑÑ) ÐµÐµ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐµ. ÐÐ²ÐŸÐ¹ÐœÑÐŒ ÑÐµÐ»ÑÐºÐŸÐŒ ÐœÐ° ÐœÑÐ¶ÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ ÐŸÑÐºÑÐŸÐ¹ÑÐµ ÐµÐ³ÐŸ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐœÐŸÐ¹ ÐŽÐ°ÐœÐœÐŸÐŒÑ ÑÐžÐ¿Ñ ÑÐ°Ð¹Ð»ÐŸÐ² Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ (ÑÐŒ.<a href="fileassociations.htm">ÐÑÑÐŸÑÐžÐ°ÑÐžÐž ÑÐ°Ð¹Ð»Ð°</a>).</p>
+<p>ÐÐµÑÐµÐ²ÐŸ ÑÐ°Ð±ÐŸÑÐµÐ³ÐŸ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²Ð° Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐžÑÑÐŸÑÐœÐžÐºÐž ÐŽÐ°ÐœÐœÑÑ
+ ÐŽÐŸÑÑÑÐ¿ÐœÑÑ
+ Ð² ÐÐœÑÐµÑÑÐµÐ¹ÑÐµ ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°ÑÑ -- ÑÐµÐºÑÑÑÑ ÑÐ°Ð¹Ð»ÐŸÐ²ÑÑ ÑÐžÑÑÐµÐŒÑ (Ð²ÐºÐ»ÑÑÐ°Ñ ÐŽÐžÑÐºÐŸÐ²ÐŸÐŽ Ðž CD-ROM), ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐÑÐžÐœÑÑÐŸÑÐœ, Ðž ÐºÑÑ Ð·Ð°Ð³ÑÑÐ¶ÐµÐœÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ². ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÐžÐŽÐµÑÑ Ðž ÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÑÑ ÑÑÐž ÑÐ°Ð¹Ð»Ñ, ÐŸÐŽÐœÐ°ÐºÐŸ ÐœÐµ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÐµÑÐµÐœÐŸÑÐžÑÑ, ÑÐŽÐ°Ð»ÑÑÑ, ÐžÐ»Ðž ÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ ÐžÑ
+, Ð·Ð° ÐžÑÐºÐ»ÑÑÐµÐœÐžÐµÐŒ ÑÐ¶Ðµ Ð·Ð°Ð³ÑÑÐ¶ÐµÐœÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐŽÐ°Ð»ÐµÐœÑ.  ÐÑÑÑÐµÑÑÐ²Ð»ÑÑÑ ÐœÐ°Ð²ÐžÐ³Ð°ÑÐžÑ Ð² ÑÑÐŸÐŒ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²Ðµ ÑÑÐŸÐ±Ñ ÐœÐ°Ð¹ÑÐž ÑÐ°Ð¹Ð»Ñ ÐºÐŸÑÐŸÑÑÐµ Ð²Ñ Ñ
+ÐŸÑÐžÑÐµ Ð²ÐºÐ»ÑÑÐžÑÑ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ.</p>
+<p>Ð€Ð°Ð¹Ð»ÐŸÐ²ÐŸÐµ ÐŽÐµÑÐµÐ²ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÐµÑ Ð¿ÐŸÐ»ÐœÐŸÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐµÑÐ²ÐŸÐœÐ°ÑÐ°Ð»ÑÐœÐŸ ÐŸÐœÐŸ Ð¿ÑÑÑÐŸ.</p>
+<p>ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÑÐ°Ð·ÐŒÐµÑÑ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²Ð°, Ð¿ÐµÑÐµÐŽÐ²ÐžÐ³Ð°Ñ ÐŒÑÑÑ Ð¿ÐŸ ÑÐµÑÐŸÐ¹ Ð»ÐžÐœÐµÐ¹ÐºÐµ, ÐºÐŸÑÐŸÑÐ°Ñ ÐŸÑÐŽÐµÐ»ÑÐµÑ ÐŽÐµÑÐµÐ²ÑÑ (ÑÐŸÑÐŒÐ° ÑÐºÐ°Ð·Ð°ÑÐµÐ»Ñ ÐžÐ·ÐŒÐµÐœÑÐµÑÑÑ),Ðž Ð±ÑÐºÑÐžÑÑÑ ÐžÑ
+.</p>
+<p>ÐÐœÐžÐ·Ñ ÐŸÐºÐœÐ° ÑÐ°ÑÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐ° ÑÑÐ°ÑÑÑÐœÐ°Ñ ÐŸÐ±Ð»Ð°ÑÑÑ, ÐºÐŸÑÐŸÑÐ°Ñ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð¿ÑÐŸÐ³ÑÐµÑÑ ÐŸÐ¿ÐµÑÐ°ÑÐžÐ¹ ÐœÐ°ÐŽ ÑÐ°Ð¹Ð»Ð°ÐŒÐž (ÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÐœÐžÐµ, Ð¿ÐµÑÐµÐŒÐµÑÐµÐœÐžÐµ, ÑÐŽÐ°Ð»ÐµÐœÐžÐµ). ÐÐœÐž ÐŒÐŸÐ³ÑÑ Ð·Ð°ÐœÑÑÑ ÐºÐ°ÐºÐŸÐµ-ÑÐŸ Ð²ÑÐµÐŒÑ. ÐÐœÐŸÐ¿ÐºÐ° "Ð¡ÑÐŸÐ¿" ÐŸÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑ Ð»ÑÐ±ÐŸÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ, ÐºÐŸÑÐŸÑÐŸÐµ Ð² ÐœÐ°ÑÑÐŸÑÑÐµÐµ Ð²ÑÐµÐŒÑ Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÐžÑ. </p>
+<p>ÐÐ²Ðµ Ð±ÐŸÐ»ÑÑÐžÐµ ÐºÐœÐŸÐ¿ÐºÐž Ð·Ð°ÐœÐžÐŒÐ°ÑÑ ÐœÐžÐ¶ÐœÐžÐ¹ Ð¿ÑÐ°Ð²ÑÐ¹ ÑÐ³ÐŸÐ» ÑÐºÑÐ°ÐœÐ°."ÐÐŸÐ²Ð°Ñ ÐÐ°Ð¿ÐºÐ°",Ñ ÐºÐ°ÑÑÐžÐœÐŸÐ¹ Ð¿Ð°Ð¿ÐºÐž, ÑÐŸÐ·ÐŽÐ°ÑÑ ÐœÐŸÐ²ÑÐµ Ð¿Ð°Ð¿ÐºÐž (ÑÐŒ. <a href="creatingfolders.htm">Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ Ð¿Ð°Ð¿ÐŸÐº</a>). ÐÐœÐŸÐ¿ÐºÐ° "Ð£ÐŽÐ°Ð»ÐžÑÑ"ÑÐŽÐ°Ð»ÑÐµÑ ÑÐ°Ð¹Ð»Ñ Ñ ÐœÐµÐœÑÐ¶ÐœÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐµÐ¹.Ð©ÐµÐ»ÑÐŸÐº ÐœÐ° ÐºÐœÐŸÐ¿ÐºÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ" ÑÐŽÐ°Ð»ÐžÑ Ð»ÑÐ±ÑÐµ ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÑÐµ ÑÐ°Ð¹Ð»Ñ ÐžÐ· ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ³ÐŸ ÐŽÐµÑÐµÐ²Ð° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐ»ÑÑÐµÑÐœÐ°ÑÐžÐ²ÐœÐŸ, ÑÐ°Ð¹Ð»Ñ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐŽÐ°Ð»ÐµÐœÑ Ð¿ÑÑÐµÐŒ Ð¿ÐµÑÐµÑÑÐ³ÐžÐ²Ð°ÐœÐžÑ ÐžÑ
+ ÐœÐ° ÐºÐœÐŸÐ¿ÐºÑ "Ð£ÐŽÐ°Ð»ÐžÑÑ". </p>
+<p>Ð§ÑÐŸÐ±Ñ ÐŸÑÐŸÐ±ÑÐ°ÑÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ Ð¿ÐŸÑÐ»ÐµÐŽÐŸÐ²Ð°ÑÐµÐ»ÑÐœÑÑ
+ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ²,Ð²ÑÐ±ÐµÑÐžÑÐµ Ð¿ÐµÑÐ²ÑÐ¹ Ðž Ð·Ð°ÑÐµÐŒ ÑÐŽÐµÑÐ¶ÐžÐ²Ð°Ñ [Shift],ÑÐµÐ»ÐºÐœÐžÑÐµ ÐœÐ° Ð¿ÐŸÑÐ»ÐµÐŽÐœÐµÐŒ - Ð¿ÑÐž ÑÑÐŸÐŒ Ð±ÑÐŽÑÑ ÐŸÑÐŸÐ±ÑÐ°ÐœÑ Ð²ÑÐµ ÐŸÑ
+Ð²Ð°ÑÐµÐœÐœÑÐµ ÑÐ»ÐµÐŒÐµÐœÑÑ.ÐÑÐ±ÐŸÑ ÐœÐµ ÑÐ»ÐµÐŽÑÑÑÐžÑ
+ ÐŸÐŽÐžÐœ Ð·Ð° ÐŽÑÑÐ³ÐžÐŒ ÑÐ°Ð¹Ð»ÐŸÐ² Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑÑ Ð¿ÑÐž ÐœÐ°Ð¶Ð°ÑÐŸÐ¹ ÐºÐ»Ð°Ð²ÐžÑÐµ [Ctrl] Ðž ÑÐµÐ»ÑÐºÐµ ÐœÐ° Ð²ÑÐ±ÐžÑÐ°ÐµÐŒÑÑ
+ ÑÐ°Ð¹Ð»Ð°Ñ
+. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÑÑÐž ÐŽÐ²Ð° ÐŒÐµÑÐŸÐŽÐ° Ð²ÐŒÐµÑÑÐµ ÐŽÐ»Ñ Ð³ÑÑÐ¿Ð¿Ñ ÐœÐµÑÐŒÐµÐ¶ÐœÑÑ
+ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ².  </p>
+<p>ÐÐµÐºÐŸÑÐŸÑÑÐµ Ð¿Ð°Ð¿ÐºÐž - ÑÐžÐ¿Ð° ÑÐµÑ
+,ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐŽÐµÑÐ¶Ð°Ñ ÐÐ°ÑÐž ÑÐŸÐ±ÑÑÐ²ÐµÐœÐœÑÐµ Ð²ÐµÐ±-ÑÑÑÐ°ÐœÐžÑÑ - ÐžÐœÐŸÐ³ÐŽÐ° ÐžÐŒÐµÑÑ ÐŸÑÐŸÐ±ÑÑ Ð²Ð°Ð¶ÐœÐŸÑÑÑ.ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð¿ÐµÑÐµÐœÐµÑÑÐž ÑÐ°ÐºÐžÐµ Ð¿Ð°Ð¿ÐºÐž ÐœÐ° Ð¿ÐµÑÐ²ÑÐ¹ ÑÑÐŸÐ²ÐµÐœÑ ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ³ÐŸ ÐŽÐµÑÐµÐ²Ð°. Ð§ÑÐŸÐ±Ñ ÑÐŽÐµÐ»Ð°ÑÑ ÑÑÐŸ, ÑÐµÐ»ÐºÐœÐžÑÐµ Ð¿ÑÐ°Ð²ÐŸÐ¹ ÐºÐœÐŸÐ¿ÐºÐŸÐ¹ ÐŒÑÑÐž ÐœÐ° Ð¶ÐµÐ»Ð°ÑÐµÐ»ÑÐœÐŸÐ¹ Ð¿Ð°Ð¿ÐºÐµ. ÐÑÐ±ÐµÑÐžÑÐµ "Ð¡ÐŸÐ·ÐŽÐ°ÑÑ ÑÐŸÐºÑÐ°ÑÐµÐœÐžÐµ" Ðž Ð²Ð²ÐµÐŽÐžÑÐµ ÐžÐŒÑ ÐŽÐ»Ñ Ð¿Ð°Ð¿ÐºÐž. ÐÐ»Ñ ÑÐŽÐ°Ð»ÐµÐœÐžÑ ÑÐ»ÐµÐŒÐµÐœÑÐ° ÑÐµÐ»ÐºÐœÐžÑÐµ Ð¿ÑÐ°Ð²ÐŸÐ¹ ÐºÐœÐŸÐ¿ÐºÐŸÐ¹ ÐŒÑÑÐž ÐœÐ° Ð¿ÐŸÐŒÐµÑÐµÐœÐœÐŸÐ¹ Ð¿Ð°Ð¿ÐºÐµ Ðž Ð²ÑÐ±ÐµÑÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ ÑÐŸÐºÑÐ°ÑÐµÐœÐžÑ".</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/themirrorview.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/themirrorview.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/themirrorview.htm	(revision 13928)
@@ -0,0 +1,29 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="themirrorview"><font face="Verdana" size="5"><strong>3.1: ÐÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐÐ°Ð³ÑÑÐ·ÐžÑÑ</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð­ÑÐ° ÑÐµÐºÑÐžÑ ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ ÐºÐ°Ðº ÐºÐŸÐœÑÐžÐ³ÑÑÐžÑÐŸÐ²Ð°ÑÑ Ð·Ð°ÐŽÐ°ÑÑ Ðž ÐºÐŸÐœÑÑÐŸÐ»Ñ Ð¿ÑÐŸÑÐµÑÑÐ° Ð·Ð°Ð³ÑÑÐ·ÐºÐž. ÐÐŸÑÑÑÐ¿ Ðº Ð¿ÑÐŸÑÐŒÐŸÑÑÑ "ÐÐ°Ð³ÑÑÐ·ÐžÑÑ" ÐœÐ°Ð¶Ð°ÑÐµÐŒ ÑÑÐŸÐ¹ Ð·Ð°ÐºÐ»Ð°ÐŽÐºÐž. ÐÐµÑÑ
+ÐœÑÑ Ð¿ÐŸÐ»ÐŸÐ²ÐžÐœÐ° ÑÐºÑÐ°ÐœÐ° Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐºÐŸÐœÑÑÐŸÐ»Ñ Ð·Ð°Ð³ÑÑÐ·ÐºÐž. ÐÐžÐ¶ÐœÑÑ Ð¿ÐŸÐ»ÐŸÐ²ÐžÐœÐ° Ð² ÐœÐ°ÑÐ°Ð»Ðµ Ð¿ÑÑÑÐ°, ÐŸÐŽÐœÐ°ÐºÐŸ Ð¿ÐŸÐºÐ°Ð¶ÐµÑ Ð¿ÐµÑÐµÑÐµÐœÑ ÐŸÐ¶ÐžÐŽÐ°ÐµÐŒÑÑ
+ Ðž Ð·Ð°ÐºÐŸÐœÑÐµÐœÐœÑÑ
+ Ð·Ð°Ð³ÑÑÐ·ÐŸÐº.</p>
+<p>Ð€Ð°Ð¹Ð»Ñ Ð·Ð°Ð³ÑÑÐ¶ÐµÐœÐœÑÐµ Ð² Ð¿Ð°Ð¿ÐºÑ ÑÐ°Ð±ÐŸÑÐµÐ³ÐŸ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²Ð° ÐœÐ°Ð·ÑÐ²Ð°ÑÑÑÑ "ÐÐ°Ð³ÑÑÐ¶Ð°ÐµÐŒÑÐµ ÑÐ°Ð¹Ð»Ñ", Ðž ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐ° Ð²ÑÐµÐŒÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÐŒÐž Ð¿ÐŸÑÑÑÐŸÐµÐœÐœÑÐŒÐž Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÐÐœÑÐµÑÑÐµÐ¹ÑÐ° ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°ÑÑ. Ð€Ð°Ð¹Ð»Ñ Ð² ÑÑÐŸÐ¹ ÐŸÐ±Ð»Ð°ÑÑÐžÐžÐŒÐµÐœÑÑÑÑÑ Ð¿ÐŸ ÐžÑ
+ Ð¿ÐŸÐ»ÐœÐŸÐŒÑ URL Ð°ÐŽÑÐµÑÑ.  Ð¡ÐŸÐ·ÐŽÐ°ÐµÑÑÑ ÐœÐŸÐ²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ° ÐœÐ° ÐºÐ°Ð¶ÐŽÐŸÐŒ Ñ
+ÐŸÑÑÐµ, ÐœÐ°ÑÐ»ÐµÐŽÑÐµÐŒÐ°Ñ ÐŽÑÑÐ³ÐžÐŒÐž ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÑÑÐ°Ð³ÐŒÐµÐœÑÐ° Ð¿ÑÑÐž.  Ð­ÑÐŸ Ð³Ð°ÑÐ°ÐœÑÐžÑÑÐµÑ ÐŸÑÐ»ÐžÑÐžÐµ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»Ð°.</p>
+<p>ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ Ð¿ÐµÑÐ²ÑÐ¹ ÐžÐ· ÐºÐŸÐœÑÑÐŸÐ»ÐžÑÑÐµÐŒÑÑ
+ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐ¹ Ð·Ð°Ð³ÑÑÐ·ÐŸÐº, "ÐÑÑ
+ÐŸÐŽÐœÑÐ¹ URL",  ÑÑÐŸÐ±Ñ Ð²Ð²ÐµÑÑÐž URL Ð°ÐŽÑÐµÑ Ð² ÑÐµÐ»ÐµÐ²ÐŸÐ¹ ÑÐµÑÑÑÑ. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐºÐŸÐœÑÑÐŸÐ»Ñ "ÐÐ»ÑÐ±ÐžÐœÑ ÐÐ°Ð³ÑÑÐ·ÐºÐž" ÐŽÐ»Ñ ÐŸÐ³ÑÐ°ÐœÐžÑÐµÐœÐžÑ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²Ð° Ð³ÐžÐ¿ÐµÑÑÑÑÐ»ÐŸÐº ÐŽÐ»Ñ Ð·Ð°Ð³ÑÑÐ·ÐºÐž: Ð£ÑÑÐ°ÐœÐŸÐ²ÐžÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ 0 ÐŽÐ»Ñ Ð·Ð°Ð³ÑÑÐ·ÐºÐž ÐŸÐŽÐœÐŸÐ¹ Ð²ÐµÐ± ÑÑÑÐ°ÐœÐžÑÑ; Ð·ÐœÐ°ÑÐµÐœÐžÐµ 1 ÑÑÐŸÐ±Ñ Ð·Ð°Ð³ÑÑÐ·ÐžÑÑ ÐŸÐŽÐœÑ ÑÑÑÐ°ÐœÐžÑÑ Ðž Ð²ÑÐµ ÑÑÑÐ°ÐœÐžÑÑ ÑÐ²ÑÐ·Ð°ÐœÐœÑÐµ Ñ ÐœÐµÐ¹ . Ð¿ÑÐµÐŽÐµÐ» Ð³Ð»ÑÐ±ÐžÐœÑ ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÑÐµÑÑÑ ÑÐŸÐ»ÑÐºÐŸ ÐœÐ° html ÑÑÑÐ°ÐœÐžÑÑ. Ð¡Ð»ÐµÐŽÑÐ¹ÑÐµÐµ, Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐ° ÑÑÑÐ°ÐœÐŸÐ²ÐºÐ° ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÑ
+ "Ð³Ð°Ð»ÐŸÑÐµÐº", ÐºÐŸÑÐŸÑÑÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÑ, ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ ÑÑÐŸÐ±Ñ ÑÑÐŸÐ±Ñ Ð²ÐºÐ»ÑÑÐžÑÑ ÑÐºÐ°Ð·Ð°ÐœÐœÑÑ ÐŸÑÐŸÐ±ÐµÐœÐœÐŸÑÑÑ ÐºÐŸÐœÐºÑÐµÑÐœÐŸÐ¹ Ð·Ð°Ð³ÑÑÐ·ÐºÐž. ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐ°, ÐœÐ°Ð¶ÐŒÐžÑÐµ "ÐÐ°Ð³ÑÑÐ·ÐºÐ°", ÑÑÐŸÐ±Ñ ÐœÐ°ÑÐ°ÑÑ ÐœÐŸÐ²ÑÑ Ð·Ð°Ð³ÑÑÐ·ÐºÑ. ÐÑÑÑ ÐŽÐ²Ðµ ÐŽÑÑÐ³ÐžÑ
+ ÐºÐœÐŸÐ¿ÐºÐž: Ð² ÑÐ°Ð·ÐŽÐµÐ»Ðµ "ÐÐ°ÑÑÑÐŸÐ¹ÐºÐž", ÐºÐŸÑÐŸÑÑÐµ ÑÐ²ÑÐ·Ð°ÐœÑ Ñ ÑÐ°Ð·ÐŽÐµÐ»ÐŸÐŒ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž ÑÐ²ÑÐ·Ðž, Ð³ÐŽÐµ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ Ð¿ÑÐŸÐºÑÐž ÑÐµÑÐ²ÐµÑÐ° ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐžÐ·ÐŒÐµÐœÐµÐœÑ; Ðž "ÐÑÐžÑÑÐºÐ° ÐÑÑ", ÐºÐŸÑÐŸÑÐ°Ñ ÑÐŽÐ°Ð»ÑÐµÑ Ð²ÑÐµ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°Ð³ÑÑÐ¶ÐµÐœÐœÑÐµ ÑÐ°Ð¹Ð»Ñ.</p>
+<p>Ð¡Ð¿ÐžÑÐŸÐº Ð·Ð°Ð³ÑÑÐ·ÐºÐž ÐžÐŒÐµÐµÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ¹ Ð·Ð°Ð³ÑÑÐ¶Ð°ÐµÐŒÐŸÐ¹ Ð²ÐµÐ± ÑÑÑÐ°ÐœÐžÑÑ. ÐÐ°Ð¶ÐŽÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐžÐŒÐµÐµÑ ÑÐµÐºÑÑ Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÑÑÑÐžÐ¹ ÐŽÐµÑÐ°Ð»Ðž Ð·Ð°ÐŽÐ°ÑÐž Ð²ÐŒÐµÑÑÐµ Ñ ÐžÐœÐŽÐžÐºÐ°ÑÐŸÑÐŸÐŒ Ð¿ÑÐŸÐ³ÑÐµÑÑÐ° ÐŽÐµÐŒÐŸÐœÑÑÑÐžÑÑÑÑÐžÐŒ ÑÐµÐºÑÑÑÑ ÐŽÐµÑÑÐµÐ»ÑÐœÐŸÑÑÑ. Ð¢ÑÐž ÐºÐœÐŸÐ¿ÐºÐž Ð¿ÐŸÑÐ²Ð»ÑÑÑÑÑ ÑÐ»ÐµÐ²Ð° ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÑ. "ÐÐ°ÑÐ·Ð°" ÐŽÐ»Ñ Ð¿ÑÐžÐŸÑÑÐ°ÐœÐŸÐ²ÐºÐž Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ ÑÐµÐºÑÑÐµÐ³ÐŸ Ð¿ÑÐŸÑÐµÑÑÐ°. "Ð¡ÐŒÐŸÑÑÐµÑÑ ÐÐŸÐ³Ðž" ÐŸÑÐºÑÑÐ²Ð°ÐµÑ ÐŸÐºÐœÐŸ ÑÐ°Ð¹Ð»Ð° Ð·Ð°Ð³ÑÑÐ·ÐºÐž. "ÐÐ°ÐºÑÑÑÑ" Ð·Ð°Ð²ÐµÑÑÐ°ÐµÑ Ð·Ð°Ð³ÑÑÐ·ÐºÑ Ð·Ð°ÐŽÐ°ÑÐž ÐžÐ· ÑÐ¿ÐžÑÐºÐ°.</p>
+<p>
+<a href="preferences.htm">ÐÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÑ</a> ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ ÐºÐ°Ðº ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÐžÐœÑÐµÑÐœÐµÑ ÑÐŸÐµÐŽÐžÐœÐµÐœÐžÐµ ÑÐµÑÐµÐ· Ð¿ÑÐŸÐºÑÐž ÑÐµÑÐ²ÐµÑ.  ÐÑÐ»Ðž ÐœÑÐ¶ÐœÐ° ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÐ°Ñ Ð°ÑÑÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÑ, Ð¿ÑÐŸÐºÑÐž ÑÐµÑÐ²ÐµÑ Ð·Ð°Ð¿ÑÐŸÑÐžÑ ÐžÐŒÑ Ðž Ð¿Ð°ÑÐŸÐ»Ñ.  ÐÐœÑÐµÑÑÐµÐ¹Ñ ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°ÑÑ ÐœÐµ ÑÐŸÐ·ÑÐ°ÐœÑÐµÑ Ð¿Ð°ÑÐŸÐ»Ðž ÐŒÐµÐ¶ÐŽÑ ÑÐµÑÑÐžÑÐŒÐž.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/translatetext.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/translatetext.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/translatetext.htm	(revision 13928)
@@ -0,0 +1,21 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="translatetext"><font face="Verdana" size="5"><strong>6.10: ÐÐµÑÐµÐ²ÐŸÐŽ ÑÐµÐºÑÑÐ°</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑÑÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ Ð¿ÐµÑÐµÐ²ÐŸÐŽÐ°, Ð³ÐŽÐµ ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÑÐ·ÑÐº ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÑ
+ ÑÑÐ°Ð³ÐŒÐµÐœÑÐŸÐ² ÑÐµÐºÑÑÐ° ÐŽÐ»Ñ ÑÐ°ÑÑÐµÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð "Ð Ð°Ð·ÐŽÐµÐ»Ðµ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°" ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐµÑÐµÐ²ÐµÑÑÐž ÑÐµÐºÑÑ".</p>
+<p>Ð¡ÐœÐ°ÑÐ°Ð»Ð° Ð²ÑÐ±ÐµÑÐžÑÐµ Ð²Ñ
+ÐŸÐŽ Ð² ÑÐ¿ÐžÑÐŸÐº "Ð¡Ð²ÐŸÐ¹ÑÑÐ²Ð°". ÐÐžÐ¶Ðµ Ð¿ÐŸÑÐ²ÑÑÑÑ ÑÑÑÐŸÐºÐž ÑÐ¿ÐµÑÐžÑÐžÑÐœÐŸÐ³ÐŸ ÑÐ·ÑÐºÐ°, ÑÐ²ÑÐ·Ð°ÐœÐœÑÐµ Ñ ÑÑÐžÐŒ ÑÐ²ÐŸÐ¹ÑÑÐ²ÐŸÐŒ. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐžÐ¹ ÑÐ¿ÐžÑÐŸÐº "Ð¯Ð·ÑÐº Ð¿ÐµÑÐµÐ²ÐŸÐŽÐ°",ÑÑÐŸÐ±Ñ Ð²ÑÐ±ÑÐ°ÑÑ ÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐœÑÐ¹ ÑÐ·ÑÐº Ðž Ð²Ð²ÐµÑÑÐž Ð¿ÐµÑÐµÐ²ÐµÐŽÐµÐœÐœÑÐ¹ ÑÐµÐºÑÑ Ð² ÐŸÐ±Ð»Ð°ÑÑÑ ÑÐµÐºÑÑÐ°, ÐŸÐ±ÑÐ°ÑÐ°ÑÑÑ Ðº "ÐÐ°ÑÐ°Ð»ÑÐœÐŸÐŒÑ ÑÑÐ°Ð³ÐŒÐµÐœÑÑ ÑÐµÐºÑÑÐ°",ÐµÑÐ»Ðž ÑÑÐŸ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ. ÐÐŸ ÐŸÐºÐŸÐœÑÐ°ÐœÐžÐž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ Ð¿ÐµÑÐµÐ²ÐŸÐŽ".</p>
+<p>Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐ¹ Ð¿ÐµÑÐµÐ²ÐŸÐŽ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ Ð² ÑÐ°Ð±Ð»ÐžÑÐµ "ÐÐ°ÐŽÐ°ÐœÐœÑÐµ Ð¿ÐµÑÐµÐ²ÐŸÐŽÑ" Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ Ð¿ÐµÑÐµÐ²ÐŸÐŽ".</p>
+<p>Ð§ÑÐŸÐ±Ñ ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ Ð¿ÐµÑÐµÐ²ÐŸÐŽ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ, ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÑÐ¹ÑÐµ Ð² ÑÐµÐºÑÑÐŸÐ²ÐŸÐ¹ ÐŸÐ±Ð»Ð°ÑÑÐž "ÐÐµÑÐµÐ²ÐµÐŽÐµÐœÐœÑÐ¹ ÑÐµÐºÑÑ" Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐ°ÐŒÐµÐœÐžÑÑ Ð¿ÐµÑÐµÐ²ÐŸÐŽ".</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/updatingmetadata.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/updatingmetadata.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/updatingmetadata.htm	(revision 13928)
@@ -0,0 +1,24 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="updatingmetadata"><font face="Verdana" size="5"><strong>5.5: ÐÐ·ÐŒÐµÐœÐžÑÑ ÐžÐ»Ðž ÑÐŽÐ°Ð»ÐžÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐžÐ»Ðž ÑÐŽÐ°Ð»ÐžÑÑ ÑÐ°ÑÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÑÐœÐ°ÑÐ°Ð»Ð° Ð²ÑÐ±ÐµÑÐžÑÐµ Ð¿ÐŸÐŽÑ
+ÐŸÐŽÑÑÐžÐ¹ ÑÐ°Ð¹Ð», Ð° Ð¿ÐŸÑÐŸÐŒ ÑÐ»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ð² ÑÐ°Ð»Ð±ÐžÑÑ. Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÑÐ»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÑÐŽÐ°Ð»ÐžÑÐµ ÑÐµÐºÑÑ ÐµÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÑ.</p>
+<p>ÐÑÐŸÑÐµÑÑ ÐŸÐ±ÐœÐŸÐ²Ð»ÐµÐœÐžÑ ÐŽÐ°ÐœÐœÑÑ
+ Ð¿Ð°Ð¿ÐºÐž Ñ Ð¿ÐŸÐŽÐ¿Ð°Ð¿ÐºÐ°ÐŒÐž ÐžÐ»Ðž ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² ÑÐŸÑ Ð¶Ðµ ÑÐ°ÐŒÑÐ¹, ÐœÐŸ Ð²Ñ ÑÐŒÐŸÐ¶ÐµÑÐµ ÐŸÐ±ÐœÐŸÐ²ÐžÑÑ ÑÐŸÐ»ÑÐºÐŸ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÐµ, ÐŸÐ±ÑÐžÐµ ÐŽÐ»Ñ Ð²ÑÐµÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ²/Ð¿Ð°Ð¿ÐŸÐº.</p>
+<p>ÐÐµÑÐµÐ²ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð²ÑÐµ ÑÐµÐºÑÑÐžÐµ Ð¿ÑÐžÐ·ÐœÐ°ÑÐµÐœÐœÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ, Ð° ÑÐ°ÐºÐ¶Ðµ Ð²ÑÐµ Ð¿ÑÐµÐŽÑÐŽÑÑÐžÐµ ÐžÐ· ÑÐµÐºÑÑÐµÐ³ÐŸ ÑÐµÐ°ÐœÑÐ°, ÑÐ°Ðº ÑÑÐŸ ÐžÐ·ÐŒÐµÐœÐµÐœÐœÑÐµ ÐžÐ»Ðž ÑÐŽÐ°Ð»ÐµÐœÐœÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŸÑÑÐ°ÑÑÑÑ Ð² ÐŽÐµÑÐµÐ²Ðµ. ÐÐ°ÐºÑÑÐ² Ðž Ð²ÐœÐŸÐ²Ñ ÐŸÑÐºÑÑÐ² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐÑ ÑÐŽÐ°Ð»ÐžÑÐµ Ð²ÑÐµ ÑÐ°ÐœÐµÐµ Ð¿ÑÐžÐ·ÐœÐ°ÑÐµÐœÐœÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ. </p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/ru/xcollectionsearching.htm
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/ru/xcollectionsearching.htm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/ru/xcollectionsearching.htm	(revision 13928)
@@ -0,0 +1,35 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>The Greenstone Librarian Interface - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0">
+<table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+<tr>
+<td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td><td align="center" width="*"><a name="xcollectionsearching"><font face="Verdana" size="5"><strong>6.7: ÐÐŸÐžÑÐº Ð² Ð¿ÐµÑÐµÑÐµÐºÐ°ÑÑÐžÑ
+ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÑ
+</strong></font></a></td><td align="center" width="15%"><img height="45" src="../gatherer_medium.gif" width="45"></td>
+</tr>
+</table>
+
+<p>Greenstone Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑ Ð¿ÐŸÐžÑÐº Ð² ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÑ
+ ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÑ
+, ÐºÐ°Ðº ÐµÑÐ»Ðž Ð±Ñ ÐŸÐœÐž Ð±ÑÐ»Ðž ÐŸÐ±ÑÐµÐŽÐžÐœÐµÐœÑ. Ð­ÑÐŸ ÑÐŽÐµÐ»Ð°ÐœÐŸ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÑÐºÐ°Ð·Ð°ÐœÐžÑ ÑÐ¿ÐžÑÐºÐ° ÐŽÑÑÐ³ÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹, Ð² ÐºÐŸÑÐŸÑÑÑ
+ ÐŽÐŸÐ»Ð¶ÐœÐ° Ð±ÑÑÑ Ð¿ÑÐŸÐ²ÐµÐŽÐµÐœ Ð¿ÐŸÐžÑÐº Ð²ÐŒÐµÑÑÐµ Ñ ÐœÐ°ÑÑÐŸÑÑÐµÐ¹. Ð "Ð Ð°Ð·ÐŽÐµÐ»Ð°Ñ
+ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°" ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐžÑÐº Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÑ
+".</p>
+<p>ÐÐµÐ¶ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐŸÐœÐœÑÐ¹ Ð¿ÐŸÐžÑÐº Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÑ
+ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐºÐŸÐœÑÑÐŸÐ»ÑÐœÑÐ¹ ÑÐ¿ÐžÑÐŸÐº ÐŽÐŸÑÑÑÐ¿ÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹.Ð¢ÐµÐºÑÑÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð¿ÐŸÐŒÐµÑÐµÐœÑ Ðž ÐœÐµ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐŸÑÑÐµÑÐœÐ°. Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐŽÑÑÐ³ÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð² ÐºÐŸÑÐŸÑÑÑ
+ Ð¿ÐŸÐžÑÐº Ð±ÑÐŽÐµÑ Ð¿ÑÐŸÐ²ÐŸÐŽÐžÑÑÑÑ Ð¿Ð°ÑÐ°Ð»Ð»ÐµÐ»ÑÐœÐŸ, ÑÐµÐ»ÐºÐœÐžÑÐµ ÐœÐ° ÐœÐžÑ
+ Ð² ÑÐ¿ÐžÑÐºÐµ (ÑÐµÐ»ÐºÐœÐžÑÐµ ÑÐœÐŸÐ²Ð°, ÑÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÐžÑ
+). ÐÑÐ»Ðž ÐŸÑÐŸÐ±ÑÐ°ÐœÐ° ÑÐŸÐ»ÑÐºÐŸ ÐŸÐŽÐœÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÑÐŸ ÐŒÐµÐ¶ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐŸÐœÐœÑÐ¹ Ð¿ÐŸÐžÑÐº ÐœÐµÐ²ÐŸÐ·ÐŒÐŸÐ¶ÐµÐœ.</p>
+<p>ÐÑÐ»Ðž ÐžÐœÐŽÐžÐ²ÐžÐŽÑÐ°Ð»ÑÐœÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐœÐµ ÐžÐŒÐµÑÑ ÐŸÐŽÐžÐœÐ°ÐºÐŸÐ²ÑÑ
+ ÐžÐœÐŽÐµÐºÑÐŸÐ² (Ð²ÐºÐ»ÑÑÐ°Ñ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ ÐœÐ° ÑÑÐ±ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÐµ Ð¿ÐŸ ÑÐ·ÑÐºÐ°ÐŒ) Ñ ÐŽÑÑÐ³ÐžÐŒÐž, ÑÐŸ Ð¿ÐµÑÐµÐºÑÐµÑÑÐœÑÐ¹ Ð¿ÐŸÐžÑÐº ÐœÐµ Ð±ÑÐŽÐµÑ ÑÐ°Ð±ÐŸÑÐ°ÑÑ ÐŽÐŸÐ»Ð¶ÐœÑÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ. ÐÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð±ÑÐŽÐµÑ ÑÐŸÐ»ÑÐºÐŸ ÑÐ¿ÐŸÑÐŸÐ±ÐµÐœ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑ Ð¿ÐŸÐžÑÐº,  ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐžÐœÐŽÐµÐºÑÑ, ÐŸÐ±ÑÐžÐµ ÐŽÐ»Ñ Ð²ÑÐµÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹.</p>
+<p>ÐÐ»Ñ ÐŽÐ°Ð»ÑÐœÐµÐ¹ÑÐžÑ
+ ÐŽÐµÑÐ°Ð»ÐµÐ¹ ÑÐŒ.Ð³Ð»Ð°Ð²Ñ 1 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone.</p>
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gli/help/splithelpdocument.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gli/help/splithelpdocument.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/help/splithelpdocument.pl	(revision 13928)
@@ -0,0 +1,66 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# splithelpdocument.pl
+#
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+sub main
+{
+    local @lines = <STDIN>;
+
+    local $filestart = 0;
+    local $filename = "";
+    for ($i = 0; $i < scalar(@lines); $i++) {
+	local $line = $lines[$i];
+
+	if ($line =~ /\<a name=\"([^\"]+)\"\>/ && $filename eq "") {
+	    $filename = $1;
+	}
+
+	if ($line =~ /^\<html\>/ && $i > $filestart) {
+	    open(FILE_OUT, ">$filename.htm") or die "Error: Could not write $filename.htm.\n";
+	    for ($j = $filestart; $j < $i; $j++) {
+		print FILE_OUT $lines[$j];
+	    }
+	    close(FILE_OUT);
+
+	    $filestart = $i;
+	    $filename = "";
+	}
+    }
+
+    # Deal with the last file
+    if ($filename ne "") {
+	open(FILE_OUT, ">$filename.htm") or die "Error: Could not write $filename.htm.\n";
+	for ($j = $filestart; $j < $i; $j++) {
+	    print FILE_OUT $lines[$j];
+	}
+	close(FILE_OUT);
+    }
+}
+
+
+&main(@ARGV);
Index: /tags/greenstone-3_02-distribution/gli/makegli.bat
===================================================================
--- /tags/greenstone-3_02-distribution/gli/makegli.bat	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/makegli.bat	(revision 13928)
@@ -0,0 +1,161 @@
+@echo off
+set GLILANG=en
+
+
+::  -------- Compile the Greenstone Librarian Interface --------
+
+echo.
+if "%GLILANG%" == "en" echo Greenstone Librarian Interface (GLI)
+if "%GLILANG%" == "en" echo Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato
+if "%GLILANG%" == "en" echo GLI comes with ABSOLUTELY NO WARRANTY; for details see LICENSE.txt
+if "%GLILANG%" == "en" echo This is free software, and you are welcome to redistribute it
+
+if "%GLILANG%" == "es" echo Interfaz de la Biblioteca Digital Greenstone (Greenstone Librarian Interface - GLI)
+if "%GLILANG%" == "es" echo Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato
+if "%GLILANG%" == "es" echo La Interfaz de la Biblioteca Digital Greenstone NO INCLUYE ABSOLUTAMENTE NINGUNA GARANTÖA.
+if "%GLILANG%" == "es" echo Para mayor informaci¢n vea los trminos de la licencia en LICENSE.txt
+if "%GLILANG%" == "es" echo Este es un software abierto, por lo que lo invitamos a que lo distribuya de forma gratuita
+
+if "%GLILANG%" == "fr" echo Interface du Bibliothcaire Greenstone (Greenstone Librarian Interface - GLI)
+if "%GLILANG%" == "fr" echo Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato
+if "%GLILANG%" == "fr" echo GLI est fourni sans AUCUNE GARANTIE; pour des dtails, voir LICENSE.txt
+if "%GLILANG%" == "fr" echo Ceci est un logiciel libre, et vous tes invit 
+ le redistribuer
+
+if "%GLILANG%" == "ru" echo š¡«š®â¥ç­ë© š­â¥àä¥©á Greenstone (Greenstone Librarian Interface - GLI)
+if "%GLILANG%" == "ru" echo Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato
+if "%GLILANG%" == "ru" echo  ­¥ € ¥â   ; €¥â «š á¬. ¢ â¥ªáâ¥ LICENSE.TXT
+if "%GLILANG%" == "ru" echo â® - á¢®¡®€­® à á¯à®áâà ­ï¥¬®¥ ¯à®£à ¬¬­®¥ ®¡¥á¯¥ç¥­š¥ š ë ¬®Š¥â¥ à á¯à®áâà ­ïâì ¥£®
+
+echo.
+
+:: This script must be run from within the directory in which it lives
+if exist makegli.bat goto findJavac
+    if "%GLILANG%" == "en" echo This script must be run from the directory in which it resides.
+    if "%GLILANG%" == "es" echo Este gui¢n deber  ejecutarse desde el directorio en el que reside.
+    if "%GLILANG%" == "fr" echo Ce script doit tre excut 
+ partir du rpertoire dans lequel il se trouve.
+    if "%GLILANG%" == "ru" echo â®â áªàš¯â €®«Š¥­ ¡ëâì ¢§ïâ š§ €šà¥ªâ®àšš, ¢ ª®â®à®© ®­ à á¯®«®Š¥­
+    goto exit
+
+
+:findJavac
+:: ---- Check Javac exists ----
+set JAVACPATH=
+
+:: Some users may set the above line manually
+if not "%JAVACPATH%" == "" goto testJavac
+
+    :: If it is set, use the JAVA_HOME environment variable
+    if not "%JAVA_HOME%" == "" goto javahome
+
+    :: Check if Javac is on the search path
+    echo %PATH%| winutil\which.exe javac.exe | winutil\setvar.exe JAVACPATH > setjavac.bat
+    call setjavac.bat
+    del setjavac.bat
+    if not "%JAVACPATH%" == "" goto testJavac
+
+    :: Still haven't found anything, so try looking in the registry (gulp!)
+    type nul > jdk.reg
+    regedit /E jdk.reg "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit"
+    type jdk.reg > jdk.txt
+    del jdk.reg
+
+    winutil\findjava.exe jdk.txt | winutil\setvar.exe JAVACPATH > setjavac.bat
+    del jdk.txt
+    call setjavac.bat
+    del setjavac.bat
+
+    :: If nothing was found in the registry, we're stuck
+    if "%JAVACPATH%" == "" goto noJavac
+
+    set JAVACPATH=%JAVACPATH%\bin
+    goto testJavac
+
+:javahome
+    set JAVACPATH=%JAVA_HOME%\bin
+
+:testJavac
+:: Check that a Javac executable has been found
+if "%GLILANG%" == "en" echo Checking Javac: %JAVACPATH%
+if "%GLILANG%" == "es" echo Revisando Javac: %JAVACPATH%
+if "%GLILANG%" == "fr" echo Vrification de Javac: %JAVACPATH%
+if "%GLILANG%" == "ru" echo à®¢¥àª  Javac: %JAVACPATH%
+if exist "%JAVACPATH%\javac.exe" goto makeGLI
+
+:noJavac
+    echo.
+    if "%GLILANG%" == "en" echo Failed to locate an appropriate version of Javac. You must install a
+    if "%GLILANG%" == "en" echo Java Development Kit (version 1.4 or greater) before compiling the
+    if "%GLILANG%" == "en" echo Greenstone Librarian Interface.
+
+    if "%GLILANG%" == "es" echo No se pudo localizar una versi¢n apropiada de Javac. Usted deber 
+    if "%GLILANG%" == "es" echo instalar un Kit de Desarrollo de Software Java (versi¢n 1.4 o superior)
+    if "%GLILANG%" == "es" echo antes de generar la documentaci¢n para la Interfaz de la Biblioteca
+    if "%GLILANG%" == "es" echo Digital Greenstone.
+
+    if "%GLILANG%" == "fr" echo Une version approprie de Javac n'a pas pu tre localise. Vous devez
+    if "%GLILANG%" == "fr" echo installer un Kit de Dveloppement Java (version 1.4 ou suprieure) 
+    if "%GLILANG%" == "fr" echo avant de produire la documentation de Greenstone Librarian Interface.
+
+    if "%GLILANG%" == "ru" echo ¥ ã€ «®áì ®¯à¥€¥«šâì ¬¥áâ®­ å®Š€¥­š¥ á®®â¢¥âáâ¢ãîé¥© ¢¥àášš Javac.
+    if "%GLILANG%" == "ru" echo ë €®«Š­ë š­áâ ««šà®¢ âì Java Development Kit (¢¥àášï 1.4 š«š ¢ëè¥)
+    if "%GLILANG%" == "ru" echo ¯à¥Š€¥, ç¥¬ £¥­¥àšà®¢ âì €®ªã¬¥­â æšî €«ï ¡š¡«š®â¥ç­®£®
+    if "%GLILANG%" == "ru" echo š­â¥àä¥©á  Greenstone.
+    goto exit
+
+
+:makeGLI
+:: ---- Compile the GLI ----
+
+if "%1" == "" goto makeAll
+    :: If a file has been specified as a command-line argument, just compile that file
+    echo.
+    if "%GLILANG%" == "en" echo Compiling %1 and dependent classes...
+    if "%GLILANG%" == "es" echo Compilando %1 y clases dependientes...
+    if "%GLILANG%" == "fr" echo Compilation de %1 et des classes dpendantes,,,
+    if "%GLILANG%" == "ru" echo ®¬¯š«šà®¢ ­š¥ %1 š § ¢šáš¬ë¥ ª« ááë...
+
+    "%JAVACPATH%\javac.exe" -d classes/ -sourcepath src/ -classpath classes/;lib/apache.jar;lib/qfslib.jar %1
+
+    if "%GLILANG%" == "en" echo Done!
+    if "%GLILANG%" == "es" echo ­Hecho!
+    if "%GLILANG%" == "fr" echo Termin!
+    if "%GLILANG%" == "ru" echo ë¯®«­¥­®!
+    goto done
+
+:makeAll
+:: Otherwise compile the lot...
+
+:: Remove any existing class files first
+call clean.bat
+
+if "%GLILANG%" == "en" echo Compiling the Greenstone Librarian Interface...
+if "%GLILANG%" == "es" echo Compilando la Interfaz de la Biblioteca Digital Greenstone...
+if "%GLILANG%" == "fr" echo Compilation de Greenstone Librarian Interface,,,
+if "%GLILANG%" == "ru" echo ®¬¯š«šà®¢ ­š¥ ¡š¡«š®â¥ç­®£® š­â¥àä¥©á  Greenstone...
+
+:: Compile the GLI
+"%JAVACPATH%\javac.exe" -d classes/ -sourcepath src/ -classpath classes/;lib/apache.jar;lib/qfslib.jar src/org/greenstone/gatherer/GathererProg.java src/org/greenstone/gatherer/util/DragTreeSelectionModel.java 
+"%JAVACPATH%\javac.exe" -d classes/ -sourcepath src/ -classpath classes/;lib/apache.jar;lib/qfslib.jar src/org/greenstone/gatherer/GathererApplet.java
+
+:: Compile the GEMS
+"%JAVACPATH%\javac.exe" -d classes/ -sourcepath src/ -classpath classes/;lib/apache.jar;lib/qfslib.jar src/org/greenstone/gatherer/gems/GEMS.java
+
+:: Compile the standalone programs needed on the server for remote building
+"%JAVACPATH%\javac.exe" -d classes/ -sourcepath src/ -classpath classes/ src/org/greenstone/gatherer/remote/Zip*.java
+"%JAVACPATH%\javac.exe" -d classes/ -sourcepath src/ -classpath classes/ src/org/greenstone/gatherer/remote/Unzip.java
+
+if "%GLILANG%" == "en" echo Done!
+if "%GLILANG%" == "es" echo ­Hecho!
+if "%GLILANG%" == "fr" echo Termin!
+if "%GLILANG%" == "ru" echo ë¯®«­¥­®!
+goto done
+
+:exit
+echo.
+pause
+
+:done
+:: ---- Clean up ----
+set JAVACPATH=
Index: /tags/greenstone-3_02-distribution/gli/makegli.sh
===================================================================
--- /tags/greenstone-3_02-distribution/gli/makegli.sh	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/makegli.sh	(revision 13928)
@@ -0,0 +1,143 @@
+#!/bin/sh
+glilang=en
+
+echo
+if [ "$glilang" = "es" ]; then
+    echo "Interfaz de la Biblioteca Digital Greenstone (Greenstone Librarian Interface - GLI)"
+    echo "Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato"
+    echo "La Interfaz de la Biblioteca Digital Greenstone NO INCLUYE ABSOLUTAMENTE NINGUNA GARANTÍA."
+    echo "Para mayor información vea los términos de la licencia en LICENSE.txt"
+    echo "Este es un software abierto, por lo que lo invitamos a que lo distribuya de forma gratuita"
+elif [ "$glilang" = "fr" ]; then
+    echo "Interface du Bibliothécaire Greenstone (Greenstone Librarian Interface - GLI)"
+    echo "Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato"
+    echo "GLI est fourni sans AUCUNE GARANTIE; pour des détails, voir LICENSE.txt"
+    echo "Ceci est un logiciel libre, et vous êtes invité à le redistribuer"
+elif [ "$glilang" = "ru" ]; then
+    echo "âÉÂÌÉÏÔÅÞÎÙÊ ÉÎÔÅÒÆÅÊÓ Greenstone (Greenstone Librarian Interface - GLI)"
+    echo "Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato"
+    echo "âéç ÎÅ ÄÁÅÔ áâóïìàôîï îéëáëéè çáòáîôéê; ÄÅÔÁÌÉ ÓÍ. × ÔÅËÓÔÅ LICENSE.TXT"
+    echo "üÔÏ - Ó×ÏÂÏÄÎÏ ÒÁÓÐÒÏÓÔÒÁÎÑÅÍÏÅ ÐÒÏÇÒÁÍÍÎÏÅ ÏÂÅÓÐÅÞÅÎÉÅ É ÷Ù ÍÏÖÅÔÅ ÒÁÓÐÒÏÓÔÒÁÎÑÔØ ÅÇÏ"
+else
+    echo "Greenstone Librarian Interface (GLI)"
+    echo "Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato"
+    echo "GLI comes with ABSOLUTELY NO WARRANTY; for details see LICENSE.txt"
+    echo "This is free software, and you are welcome to redistribute it"
+fi
+echo
+
+##  -------- Compile the Greenstone Librarian Interface --------
+
+## ---- Check Javac exists ----
+javacpath=
+
+# Some users may set the above line manually
+if [ "x$javacpath" = "x" ]; then
+
+    # If it is set, use the JAVA_HOME environment variable
+    if [ "x$JAVA_HOME" != "x" ]; then
+	javacpath="$JAVA_HOME/bin/javac"
+
+    # Check if Javac is on the search path
+    else
+	javacpath=`which javac 2> /dev/null`
+    fi
+fi
+
+# Check that a Javac executable has been found
+if [ "$glilang" = "es" ]; then
+    echo "Revisando Javac: $javacpath"
+elif [ "$glilang" = "fr" ]; then
+    echo "Vérification de Javac: $javacpath"
+elif [ "$glilang" = "ru" ]; then
+    echo "ðÒÏ×ÅÒËÁ Javac: $javacpath"
+else
+    echo "Checking Javac: $javacpath"
+fi
+if [ ! -x "$javacpath" ]; then
+    echo
+    if [ "$glilang" = "es" ]; then
+	echo "No se pudo localizar una versión apropiada de Javac."
+	echo "Por favor instale una nueva versión del Kit de Desarrollo de"
+	echo "Software Java (versión 1.4 o posterior) y ejecute nuevamente"
+	echo "este guión."
+    elif [ "$glilang" = "fr" ]; then
+	echo "Une version appropriée de Javac n'a pas pu être localisée."
+	echo "Veuillez installer une nouvelle version de Java SDK (version 1.4 ou"
+	echo "plus récente) et redémarrez ce script."
+    elif [ "$glilang" = "ru" ]; then
+	echo "îÅ ÕÄÁÌÏÓØ ÏÐÒÅÄÅÌÉÔØ ÍÅÓÔÏÎÁÈÏÖÄÅÎÉÅ ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÅÊ ×ÅÒÓÉÉ Javac."
+	echo "ðÏÖÁÌÕÊÓÔÁ, ÕÓÔÁÎÏ×ÉÔÅ ÎÏ×ÕÀ ×ÅÒÓÉÀ Java SDK (×ÅÒÓÉÀ 1.4 ÉÌÉ ÂÏÌÅÅ"
+	echo "ÎÏ×ÕÀ) É ÐÅÒÅÕÓÔÁÎÏ×ÉÔÅ ÜÔÏÔ ÓËÒÉÐÔ."
+    else
+	echo "Failed to locate an appropriate version of Javac. You must install a"
+	echo "Java Development Kit (version 1.4 or greater) before compiling the"
+	echo "Greenstone Librarian Interface."
+    fi
+    exit 1
+fi
+
+## ---- Compile the GLI ----
+
+# If a file has been specified at the command-line, just compile that file
+if [ ! "x$*" = "x" ] ; then
+    echo
+    if [ "$glilang" = "es" ]; then
+	echo "Compilando $* y clases dependientes..."
+    elif [ "$glilang" = "fr" ]; then
+	echo "Compilation de $* et des classes dépendantes,,,"
+    elif [ "$glilang" = "ru" ]; then
+	echo "ëÏÍÐÉÌÉÒÏ×ÁÎÉÅ $* É ÚÁ×ÉÓÉÍÙÅ ËÌÁÓÓÙ..."
+    else
+	echo "Compiling $* and dependent classes..."
+    fi
+
+    $javacpath -deprecation -d classes/ -sourcepath src/ -classpath classes/:lib/apache.jar:lib/qfslib.jar $*
+
+    if [ "$glilang" = "es" ]; then
+	echo "¡Hecho!"
+    elif [ "$glilang" = "fr" ]; then
+	echo "Terminé!"
+    elif [ "$glilang" = "ru" ]; then
+	echo "÷ÙÐÏÌÎÅÎÏ!"
+    else
+	echo "Done!"
+    fi
+    exit 0
+fi
+
+# Otherwise compile the lot...
+
+# Remove any existing class files first
+./clean.sh
+
+if [ "$glilang" = "es" ]; then
+    echo "Compilando la Interfaz de la Biblioteca Digital Greenstone..."
+elif [ "$glilang" = "fr" ]; then
+    echo "Compilation de Greenstone Librarian Interface,,,"
+elif [ "$glilang" = "ru" ]; then
+    echo "ëÏÍÐÉÌÉÒÏ×ÁÎÉÅ ÂÉÂÌÉÏÔÅÞÎÏÇÏ ÉÎÔÅÒÆÅÊÓÁ Greenstone..."
+else
+    echo "Compiling the Greenstone Librarian Interface..."
+fi
+
+# Compile the GLI
+$javacpath -deprecation -d classes/ -sourcepath src/ -classpath classes/:lib/apache.jar:lib/qfslib.jar src/org/greenstone/gatherer/GathererProg.java
+$javacpath -deprecation -d classes/ -sourcepath src/ -classpath classes/:lib/apache.jar:lib/qfslib.jar src/org/greenstone/gatherer/GathererApplet.java
+
+# Compile the GEMS
+$javacpath -deprecation -d classes/ -sourcepath src/ -classpath classes/:lib/apache.jar:lib/qfslib.jar src/org/greenstone/gatherer/gems/GEMS.java
+
+# Compile the standalone programs needed on the server for remote building
+$javacpath -deprecation -d classes/ -sourcepath src/ -classpath classes/ src/org/greenstone/gatherer/remote/Zip*.java
+$javacpath -deprecation -d classes/ -sourcepath src/ -classpath classes/ src/org/greenstone/gatherer/remote/Unzip.java
+
+if [ "$glilang" = "es" ]; then
+    echo "¡Hecho!"
+elif [ "$glilang" = "fr" ]; then
+    echo "Terminé!"
+elif [ "$glilang" = "ru" ]; then
+    echo "÷ÙÐÏÌÎÅÎÏ!"
+else
+    echo "Done!"
+fi
Index: /tags/greenstone-3_02-distribution/gli/makejar.bat
===================================================================
--- /tags/greenstone-3_02-distribution/gli/makejar.bat	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/makejar.bat	(revision 13928)
@@ -0,0 +1,170 @@
+echo off
+set GLILANG=en
+
+:: This script must be run from within the directory in which it lives
+if exist makejar.bat goto findJar
+    if "%GLILANG%" == "en" echo This script must be run from the directory in which it resides.
+    if "%GLILANG%" == "es" echo Este gui¢n deber  ejecutarse desde el directorio en el que reside.
+    if "%GLILANG%" == "fr" echo Ce script doit tre excut 
+ partir du rpertoire dans lequel il se trouve.
+    if "%GLILANG%" == "ru" echo â®â áªàš¯â €®«Š¥­ ¡ëâì ¢§ïâ š§ €šà¥ªâ®àšš, ¢ ª®â®à®© ®­ à á¯®«®Š¥­
+    goto exit
+
+
+
+
+:findJar
+:: ---- Check jar exists ----
+set JARPATH=
+
+:: Some users may set the above line manually
+if not "%JARPATH%" == "" goto testJar
+
+    :: If it is set, use the JAVA_HOME environment variable
+    if not "%JAVA_HOME%" == "" goto javahome
+
+    :: Check if jar is on the search path
+    echo %PATH%| winutil\which.exe jar.exe | winutil\setvar.exe JARPATH > setjar.bat
+    call setjar.bat
+    del setjar.bat
+    if not "%JARPATH%" == "" goto testJar
+
+    :: Still haven't found anything, so try looking in the registry (gulp!)
+    type nul > jdk.reg
+    regedit /E jdk.reg "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit"
+    type jdk.reg > jdk.txt
+    del jdk.reg
+
+    winutil\findjava.exe jdk.txt | winutil\setvar.exe JARPATH > setjar.bat
+    del jdk.txt
+    call setjar.bat
+    del setjar.bat
+
+    :: If nothing was found in the registry, we're stuck
+    if "%JARPATH%" == "" goto noJar
+
+    set JARPATH=%JARPATH%\bin
+    goto testJar
+
+:javahome
+    set JARPATH=%JAVA_HOME%\bin
+
+:testJar
+:: Check that a jar executable has been found
+if "%GLILANG%" == "en" echo Checking jar: %JARPATH%
+if "%GLILANG%" == "es" echo Revisando jar: %JARPATH%
+if "%GLILANG%" == "fr" echo Vrification de jar: %JARPATH%
+if "%GLILANG%" == "ru" echo à®¢¥àª  jar: %JARPATH%
+if exist "%JARPATH%\jar.exe" goto checkCompile
+
+:noJar
+    echo.
+    if "%GLILANG%" == "en" echo Failed to locate an appropriate version of jar. You must install a
+    if "%GLILANG%" == "en" echo Java Development Kit (version 1.4 or greater) before compiling the
+    if "%GLILANG%" == "en" echo Greenstone Librarian Interface.
+
+    if "%GLILANG%" == "es" echo No se pudo localizar una versi¢n apropiada de jar. Usted deber 
+    if "%GLILANG%" == "es" echo instalar un Kit de Desarrollo de Software Java (versi¢n 1.4 o superior)
+    if "%GLILANG%" == "es" echo antes de generar la documentaci¢n para la Interfaz de la Biblioteca
+    if "%GLILANG%" == "es" echo Digital Greenstone.
+
+    if "%GLILANG%" == "fr" echo Une version approprie de jar n'a pas pu tre localise. Vous devez
+    if "%GLILANG%" == "fr" echo installer un Kit de Dveloppement Java (version 1.4 ou suprieure) 
+    if "%GLILANG%" == "fr" echo avant de produire la documentation de Greenstone Librarian Interface.
+
+    if "%GLILANG%" == "ru" echo ¥ ã€ «®áì ®¯à¥€¥«šâì ¬¥áâ®­ å®Š€¥­š¥ á®®â¢¥âáâ¢ãîé¥© ¢¥àášš jar.
+    if "%GLILANG%" == "ru" echo ë €®«Š­ë š­áâ ««šà®¢ âì Java Development Kit (¢¥àášï 1.4 š«š ¢ëè¥)
+    if "%GLILANG%" == "ru" echo ¯à¥Š€¥, ç¥¬ £¥­¥àšà®¢ âì €®ªã¬¥­â æšî €«ï ¡š¡«š®â¥ç­®£®
+    if "%GLILANG%" == "ru" echo š­â¥àä¥©á  Greenstone.
+    goto exit
+
+
+
+:checkCompile
+:: Check that the GLI has been compiled 
+if exist classes\org\greenstone\gatherer\GathererProg.class goto makeJar
+    if "%GLILANG%" == "es"  (
+	echo Usted necesita compilar la Interfaz de la Biblioteca Digital Greenstone
+	echo (por medio de makegli.sh) antes de ejecutar este guión.
+    )
+    if "%GLILANG%" == "fr" (
+	echo Vous devez compiler le Greenstone Interface (en utilisant makegli.sh)
+	echo avant d'exécuter ce script.
+    )
+    if "%GLILANG%" == "ru" (
+	echo ÷Ù ÄÏÌÖÎÙ ËÏÍÐÉÌÉÒÏ×ÁÔØ ÂÉÂÌÉÏÔÅÞÎÙÊ ÉÎÔÅÒÆÅÊÓ Greenstone
+	echo (ÉÓÐÏÌØÚÕÑ makegli.sh) ÐÅÒÅÄ ××ÏÄÏÍ ÜÔÏÇÏ ÓËÒÉÐÔÁ
+    )
+    if "%GLILANG%" == "en" (
+	echo You need to compile the Greenstone Librarian Interface (using makegli.sh)
+	echo before running this script.
+    )
+    goto exit
+fi
+
+
+:makeJar
+:: All the GLI class files and supporting libraries are put into the "jar" directory
+
+echo Assuming that Java code is freshly compiled...
+
+if NOT exist jar (
+  mkdir jar
+
+  cd lib
+  "%JARPATH%\jar" xf apache.jar com org
+  "%JARPATH%\jar" xf qfslib.jar de
+
+  move com ..\jar\com     >NUL
+  move de ..\jar\de       >NUL
+  move org ..\jar\org     >NUL
+
+  cd ..
+)
+
+:: Copy the latest version of the GLI classes into the jar directory
+if exist jar\org\greenstone (
+  rmdir /q /s jar\org\greenstone
+)
+xcopy /i /e /q classes\org\greenstone jar\org\greenstone
+
+:: Some of the things to go into the JAR file are optional, and may not exist
+set optional=
+if exist collect.zip (
+    set optional=%optional% collect.zip
+)
+
+:: Recreate the metadata.zip file (contains the GLI metadata directory)
+if exist jar\org\greenstone (
+  del /f metadata.zip
+)
+winutil\zip.exe -r metadata.zip metadata >NUL
+
+:: Jar everything up
+"%JARPATH%\jar" cf GLI.jar .java.policy metadata.zip %optional% help -C classes dictionary.properties -C classes dictionary_es.properties -C classes dictionary_fr.properties -C classes dictionary_ru.properties -C classes feedback.properties -C classes images -C classes xml -C jar com -C jar de -C jar org
+
+:: Tidy up
+del /f metadata.zip
+
+:: Generate the GLIServer.jar file for remote building
+"%JARPATH%\jar" cf GLIServer.jar -C classes org/greenstone/gatherer/remote
+
+:: ---- Make signed JAR file for the applet, if desired ----
+if  (%1) == (-sign) (
+
+    if not exist appletstore (
+      "%JARPATH%\keytool" -genkey -alias privateKey -keystore appletstore -storepass greenstone
+    )
+
+    if exist SignedGatherer.jar del /f SignedGatherer.jar
+    if exist appletpasswd (
+      echo Using jarsigner to make signed jar file ...
+      "%JARPATH%\jarsigner" -keystore appletstore -signedjar SignedGatherer.jar GLI.jar privateKey < appletpasswd >NUL 2>NUL
+      echo ... done.
+    ) ELSE (
+      "%JARPATH%\jarsigner" -keystore appletstore -signedjar SignedGatherer.jar GLI.jar privateKey
+    )
+    echo Installing SignedGatherer in ..\bin\java
+    move SignedGatherer.jar ..\bin\java\SignedGatherer.jar
+)
+
Index: /tags/greenstone-3_02-distribution/gli/makejar.sh
===================================================================
--- /tags/greenstone-3_02-distribution/gli/makejar.sh	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/makejar.sh	(revision 13928)
@@ -0,0 +1,87 @@
+#!/bin/sh
+glilang=en
+
+
+# This script must be run from within the directory in which it lives
+thisdir=`pwd`
+if [ ! -f "${thisdir}/makejar.sh" ]; then
+    if [ "$glilang" = "es" ]; then
+        echo "Este guión deberá ejecutarse desde el directorio en el que reside."
+    elif [ "$glilang" = "fr" ]; then
+	echo "Ce script doit être exécuté à partir du répertoire dans lequel il se trouve."
+    elif [ "$glilang" = "ru" ]; then
+	echo "üÔÏÔ ÓËÒÉÐÔ ÄÏÌÖÅÎ ÂÙÔØ ×ÚÑÔ ÉÚ ÄÉÒÅËÔÏÒÉÉ, × ËÏÔÏÒÏÊ ÏÎ ÒÁÓÐÏÌÏÖÅÎ"
+    else
+	echo "This script must be run from the directory in which it resides."
+    fi
+    exit 1
+fi
+
+## ---- Check that the GLI has been compiled ----
+if [ ! -f "classes/org/greenstone/gatherer/GathererProg.class" ]; then
+    echo
+    if [ "$glilang" = "es" ]; then
+	echo "Usted necesita compilar la Interfaz de la Biblioteca Digital Greenstone"
+	echo "(por medio de makegli.sh) antes de ejecutar este guión."
+    elif [ "$glilang" = "fr" ]; then
+	echo "Vous devez compiler le Greenstone Interface (en utilisant makegli.sh)"
+	echo "avant d'exécuter ce script."
+    elif [ "$glilang" = "ru" ]; then
+	echo "÷Ù ÄÏÌÖÎÙ ËÏÍÐÉÌÉÒÏ×ÁÔØ ÂÉÂÌÉÏÔÅÞÎÙÊ ÉÎÔÅÒÆÅÊÓ Greenstone"
+	echo "(ÉÓÐÏÌØÚÕÑ makegli.sh) ÐÅÒÅÄ ××ÏÄÏÍ ÜÔÏÇÏ ÓËÒÉÐÔÁ"
+    else
+	echo "You need to compile the Greenstone Librarian Interface (using makegli.sh)"
+	echo "before running this script."
+    fi
+    exit 1
+fi
+
+echo "Assuming that Java code is freshly compiled..."
+
+# All the GLI class files and supporting libraries are put into the "jar" directory
+if [ ! -d jar ]; then
+  mkdir jar
+
+  cd lib
+  jar xf apache.jar com org
+  jar xf qfslib.jar de
+
+  mv com de org ../jar/.
+  cd ..
+fi
+
+# Copy the latest version of the GLI classes into the jar directory
+rm -rf jar/org/greenstone
+cp -r classes/org/greenstone jar/org
+
+# Some of the things to go into the JAR file are optional, and may not exist
+optional=
+if [ -f collect.zip ]; then
+    optional="$optional collect.zip"
+fi
+
+# Recreate the metadata.zip file (contains the GLI metadata directory)
+rm -f metadata.zip
+zip -r metadata.zip metadata >/dev/null
+
+# Jar everything up
+jar cf GLI.jar .java.policy metadata.zip $optional help \
+    -C classes dictionary.properties -C classes dictionary_es.properties \
+    -C classes dictionary_fr.properties -C classes dictionary_ru.properties \
+    -C classes feedback.properties -C classes images -C classes xml \
+    -C jar com -C jar de -C jar org
+
+# Tidy up
+rm -f metadata.zip
+
+# Generate the GLIServer.jar file for remote building
+jar cf GLIServer.jar -C classes org/greenstone/gatherer/remote
+
+# ---- Make signed JAR file for the applet, if desired ----
+if [ "$1" = "-sign" ]; then
+    rm -f SignedGatherer.jar
+    echo "greenstone" | jarsigner -keystore .greenstonestore -signedjar SignedGatherer.jar GLI.jar privateKey 2> /dev/null
+    echo
+    echo "Installing SignedGatherer in ../bin/java"
+    mv SignedGatherer.jar ../bin/java/.
+fi
Index: /tags/greenstone-3_02-distribution/gli/metadata/adding_translations.txt
===================================================================
--- /tags/greenstone-3_02-distribution/gli/metadata/adding_translations.txt	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/metadata/adding_translations.txt	(revision 13928)
@@ -0,0 +1,88 @@
+How to add a translation for a metadata set.
+
+Note: When using the word element, we are speaking of a document object model element. Whereas when we say Element we are talking about a particular document object model element used to describe an item from the current set.
+
+1. Prepare your source text in a UTF8 encoded document, or use a fully Unicode compliant text editor. Open the metadata set file that you want to edit.
+
+Example: To add a new language to the dublin.mds, open the file in a UTF8 editor.
+
+2. In MetadataSet DOM element edit, or add if necessary, an argument named "language_dependent". As its value add a list of comma separated attribute names. These are the names of the attributes which are taken to be language dependent (see 4). This is optional.
+
+Example: While editing the dublin.mds scroll down to the start of the MetadataSet xml block, which looks like:
+
+<MetadataSet 
+  contact     = "dcmi-feedback@dublincore.org"
+  creator     = "Dublin Core Metadata Initiative"
+  family      = "Dublin Core"
+  lastchanged = "Tue Jun 04 10:35:30 2002 - jmt12 on blackbird"
+  namespace   = "dc" 
+>
+
+and add the mentioned line so it reads something like:
+
+<MetadataSet 
+  contact     = "dcmi-feedback@dublincore.org"
+  creator     = "Dublin Core Metadata Initiative"
+  family      = "Dublin Core"
+  lastchanged = "Tue Jun 04 10:35:30 2002 - jmt12 on blackbird"
+  namespace   = "dc" 
+  language_dependent = "label, definition, comment"
+>
+
+where label, definition and command are the attributes that we wish to be language specific.
+
+3. Near the top of the document add a language specific set description block of the form
+
+  <SetLanguage code="**">
+    <Name>**</Name>
+    <Description>**</Description>
+  </SetLanguage>
+
+  Replace the ** with the relevant detail. Code is the two letter language code according to ISO 3166.
+
+Example: To add the French translation to the dublin.mds scroll down to just below the MetadataSet xml block, and add the SetLanguage xml block:
+
+  <SetLanguage code="fr">
+    <Name language="fr">El\303\251ments de m\303\251tadonn\303\251es du Dublin Core, Version 1.1: Description de R\303\251ference</Name>
+    <Description language="fr">Ce document r\303\251sume...</Description>
+  </SetLanguage>
+
+4. For each Element xml block defined in the metadata set, add a new Language xml block and within it add the language specfic Attributes. The block is of the form:
+
+    <Language code="**">
+       <Attribute name="**">**</Attribute>
+       ...
+    </Language>
+
+  Replace the ** with the relevant detail. Once again code is the two letter language code according to ISO 3166. Note that the names specified in the name argument of an Attribute must also be listed in the language_dependent argument of the MetadataSet (see 1) (OPTIONAL)
+
+Example: Thus to add a French translation for the Element "Title", scroll down to the Element xml block defining Title. This should start:
+
+  <Element name="Title" remember_values="true">
+  ...
+  ...
+  ...
+  </Element>
+
+Now add in a new Language block so it looks something like this:
+
+  <Element name="Title" remember_values="true">
+  ...
+     <!-- French -->
+     <Language code="fr">
+        <Attribute name="label">Titre</Attribute>
+        <Attribute name="definition">Le nom donn\303\251 \303\240  la ressource.</Attribute>
+        <Attribute name="comment">Typiquement, un titre sera le nom par lequel la ressource est officiellement connue.</Attribute>
+     </Language>
+  ...
+  </Element>    
+
+5. Finally edit the file <gli_install>/classes/xml/languages.xml. Locate the appropriate Language and add the argument mds="true" to enable this language. This controls what languages appear on the preferences page within the GLI.
+
+Example: Finally to enable the French translation, find the entry in the languages.xml file that reads:
+
+  <Language name="FRENCH"              code="FR" ... >ROMANCE</Language>
+
+And change it so it now says:
+
+  <Language name="FRENCH"              code="FR" ... mds="true">ROMANCE</Language> 
Index: /tags/greenstone-3_02-distribution/gli/metadata/agls.mds
===================================================================
--- /tags/greenstone-3_02-distribution/gli/metadata/agls.mds	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/metadata/agls.mds	(revision 13928)
@@ -0,0 +1,287 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE MetadataSet SYSTEM "http://www.greenstone.org/dtd/MetadataSet/1.0/MetadataSet.dtd">
+<MetadataSet contact="agls@naa.gov.au" creator="The National Archives of Australia" family="" lastchanged="Tue Sep 05 14:40:36 NZST 2006 - kjdon on kanuka" namespace="agls">
+    <Name language="en">Australian Government Locator Service Metadata Element Set, Version 1.3</Name>
+    <Element name="Creator">
+        <Attribute language="en" name="label">Creator</Attribute>
+        <Attribute language="en" name="obligation">Mandatory if known</Attribute>
+        <Attribute language="en" name="definition">An entity primarily responsible for making the content of the resource.</Attribute>
+        <Attribute language="en" name="comment">Examples of a Creator include a person, or an organisation.</Attribute>
+    </Element>
+    <Element name="Date">
+        <Attribute language="en" name="label">Date</Attribute>
+        <Attribute language="en" name="definition">A date of an event in the lifecycle of the resource.</Attribute>
+        <Attribute language="en" name="obligation">Mandatory</Attribute>
+        <Attribute language="en" name="comment">Typically, Date will be associated with the creator or availability of the resource. Recommended best practice for encoding the date value is defined in a profile of ISO 8601 [W3CDTF] and follows the YYYY-MM-DD format.</Attribute>
+        <Element name="created">
+            <Attribute language="en" name="label">Created</Attribute>
+            <Attribute language="en" name="definition">Creation date of the resource</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+        </Element>
+        <Element name="modified">
+            <Attribute language="en" name="label">Modified</Attribute>
+            <Attribute language="en" name="definition">Creation date of the resource</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+        </Element>
+        <Element name="valid">
+            <Attribute language="en" name="label">Valid</Attribute>
+            <Attribute language="en" name="comment">Typically, a date the resource becomes valid or ceases to be valid, or the date range for which the resource is valid.</Attribute>
+            <Attribute language="en" name="definition">A date (often a range) of validity of a resource.</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+        </Element>
+        <Element name="issued">
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Attribute language="en" name="definition">A date on which the rescource was made formally available in its current form.</Attribute>
+            <Attribute language="en" name="label">Issued</Attribute>
+        </Element>
+    </Element>
+    <Element name="Title">
+        <Attribute language="en" name="label">Title</Attribute>
+        <Attribute language="en" name="definition">A name given to the resource.</Attribute>
+        <Attribute language="en" name="obligation">Mandatory</Attribute>
+        <Attribute language="en" name="comment">This qualifier could include abbreviations and acronyms by which a resource may be known.</Attribute>
+        <Element name="alternative">
+            <Attribute language="en" name="label">Alternative</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Attribute language="en" name="definition">Any form of the title used as a substitute or alternative to the formal title or the resource</Attribute>
+            <Attribute language="en" name="comment">This qualifier could include abbreviations and acronyms by which a resource may be known.</Attribute>
+        </Element>
+    </Element>
+    <Element name="Availability">
+        <Attribute language="en" name="definition">How the resource can be obtained or contact information for obtaining the resource.</Attribute>
+        <Attribute language="en" name="obligation">Mandatory for offline resources.</Attribute>
+        <Attribute language="en" name="comment">The Availability element is primarily used for non-electronic resources to provide information on how to obtain physical access to the resource.</Attribute>
+        <Attribute language="en" name="label">Availability</Attribute>
+    </Element>
+    <Element name="Function">
+        <Attribute language="en" name="label">Function</Attribute>
+        <Attribute language="en" name="definition">The business function of the organisation to which the resource relates.</Attribute>
+        <Attribute language="en" name="obligation">Mandatory if no Subject element specified.</Attribute>
+        <Attribute language="en" name="comment">Used to indicate the business role of the resource in terms of business functions and activities. Functions are the major units of activity which organisations pursue in order to meet the mission and goals of the organisation. They are defined in the Australian Records Management Standard (AS 4390) as the largest unit of business activity in an organisation. Recommended best practice is to select a value from a controlled vocabulary or formal classification scheme.</Attribute>
+    </Element>
+    <Element name="Identifier">
+        <Attribute language="en" name="label">Resource Identifier</Attribute>
+        <Attribute language="en" name="definition">An unambiguous reference to the resource within a given context.</Attribute>
+        <Attribute language="en" name="obligation">Mandatory for online resources.</Attribute>
+        <Attribute language="en" name="comment">Recommended best practice is to identify the resource by means of a string or number conforming to a formal identification system. Example formal identification systems include the Uniform Resource Identifier (URI) (including the Uniform Resource Locator (URL)), the Digital Object Identifier (DOI) and the International Standard Book Number (ISBN).</Attribute>
+    </Element>
+    <Element name="Publisher">
+        <Attribute language="en" name="label">Publisher</Attribute>
+        <Attribute language="en" name="definition">An entity responsible for making the resource available.</Attribute>
+        <Attribute language="en" name="obligation">Mandatory for information resources.</Attribute>
+        <Attribute language="en" name="comment">This field is often the name of the organisation that owns or controls or publishes the resource. It is not recommended that this element be used for the name of the entity which merely acts as the host for a website.</Attribute>
+    </Element>
+    <Element name="Subject">
+        <Attribute language="en" name="label">Subject and Keywords</Attribute>
+        <Attribute language="en" name="definition">A subject and/or topic of the content of the resource.</Attribute>
+        <Attribute language="en" name="obligation">Mandatory if no Function element specified.</Attribute>
+        <Attribute language="en" name="comment">Typically, a Subject will be expressed as keywords, key phrases or classification codes that describe a topic of the resource content. Recommended best practice is to select a value from a controlled vocabulary or formal classification scheme.</Attribute>
+    </Element>
+    <Element name="Audience">
+        <Attribute language="en" name="label">Audience</Attribute>
+        <Attribute language="en" name="definition">A target audience of the resource.</Attribute>
+        <Attribute language="en" name="obligation">Optional</Attribute>
+        <Attribute language="en" name="comment">Types of audiences commonly used in this element include particular industry sectors, education levels, skill levels, occupations, and EEO categories. Recommended best practice is to select a value from a controlled vocabulary or formal classification scheme.</Attribute>
+    </Element>
+    <Element name="Contributor">
+        <Attribute language="en" name="label">Contributor</Attribute>
+        <Attribute language="en" name="definition">An entity responsible for making a contribution to the content of the resource.</Attribute>
+        <Attribute language="en" name="obligation">Optional</Attribute>
+        <Attribute language="en" name="comment">Typically, a contributor will be an entity that has played an important but secondary role in creating the content of the resource and is not specified in the creator element.</Attribute>
+    </Element>
+    <Element name="Coverage">
+        <Attribute language="en" name="label">Coverage</Attribute>
+        <Attribute language="en" name="definition">The extent or scope of the content of the resource.</Attribute>
+        <Attribute language="en" name="obligation">Optional</Attribute>
+        <Attribute language="en" name="comment">Coverage will typically include spatial location (a place name or geographic coordinates), temporal period (a period label, date, or date range) or jurisdiction (such as a named administrative entity). Recommended best practice is to select a value from a controlled vocabulary (for example, the Thesaurus of Geographic Names [TGN]) and that, where appropriate, named places or time periods be used in preference to numeric identifiers such as sets of coordinates or date ranges. </Attribute>
+        <Element name="jurisdiction">
+            <Attribute language="en" name="label">Jurisdiction</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Attribute language="en" name="definition">The name of the political/administrative entity covered by the content of the resource.</Attribute>
+            <Attribute language="en" name="comment">Jurisdiction is a description of the territory over which a particular government exercises its authority or a particualar business transacts its operations, to which the resource content is applicable.</Attribute>
+        </Element>
+        <Element name="spatial">
+            <Attribute language="en" name="label">Spatial</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Attribute language="en" name="definition">Spatial (geographic) characteristics of the intellectual content of the resource.</Attribute>
+        </Element>
+        <Element name="temporal">
+            <Attribute language="en" name="label">Temporal</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Attribute language="en" name="definition">Temporal characteristics of the intellectual content of the resource.</Attribute>
+        </Element>
+        <Element name="postcode">
+            <Attribute language="en" name="label">Postcode</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Attribute language="en" name="definition">Australian postcode(s) applicable to the spatial coverage of the resource content.</Attribute>
+            <Attribute language="en" name="comment">Postcode refers to the actual Australian postcode(s) which is relevant to the spatial coverage of the resource content. This qualifier will be of particular use in describing services.</Attribute>
+        </Element>
+    </Element>
+    <Element name="Description">
+        <Attribute language="en" name="label">Description</Attribute>
+        <Attribute language="en" name="definition">An account of the content of the resource.</Attribute>
+        <Attribute language="en" name="obligation">Optional</Attribute>
+        <Attribute language="en" name="comment">Description may include but is not limited to: an abstract, table of contents, reference to a graphical representation of content (eg a thumbnail of an image), or a free-text account of the content.</Attribute>
+    </Element>
+    <Element name="Format">
+        <Attribute language="en" name="label">Format</Attribute>
+        <Attribute language="en" name="definition">The physical or digital manifestation of the resource. </Attribute>
+        <Attribute language="en" name="obligation">Optional</Attribute>
+        <Attribute language="en" name="comment">Typically, Format may include the media-type or dimensions of the resource. Format may be used to determine the software, hardware or other equipment needed to display or operate the resource. Examples of dimensions include size and duration. Recommended best practice is to select a value from a controlled vocabulary (for example, the list of Internet Media Types [MIME] defining computer media formats).</Attribute>
+        <Element name="extent">
+            <Attribute language="en" name="label">Extent</Attribute>
+            <Attribute language="en" name="qualifier type">Element refinement</Attribute>
+            <Attribute language="en" name="definition">The size or duration of the resource.</Attribute>
+            <Attribute language="en" name="comment">The extent qualifier allows the description of the physical dimensions, file size or duration of the resource.</Attribute>
+        </Element>
+        <Element name="medium">
+            <Attribute language="en" name="label">Medium</Attribute>
+            <Attribute language="en" name="qualifier type">Element refinement</Attribute>
+            <Attribute language="en" name="definition">The material or physical carrier of the resource.</Attribute>
+        </Element>
+    </Element>
+    <Element name="Language">
+        <Attribute language="en" name="label">Language</Attribute>
+        <Attribute language="en" name="definition">A language of the intellectual content of the resource.</Attribute>
+        <Attribute language="en" name="obligation">Optional</Attribute>
+        <Attribute language="en" name="comment">Recommended best practice for the values of the Language element is defined by RFC 3066 [RFC 3066] which includes a two-letter Language Code (taken from the ISO 639 standard [ISO 639]), followed optionally, by a two-letter Country Code (taken from the ISO 3166 standard [ISO 3166]). For example, &apos;en&apos; for English, &apos;fr&apos; for French, or &apos;en-uk&apos; for English used in the United Kingdom.</Attribute>
+    </Element>
+    <Element name="Mandate">
+        <Attribute language="en" name="label">Mandate</Attribute>
+        <Attribute language="en" name="definition">A specific warrant which requires the resource to be created or provided.</Attribute>
+        <Attribute language="en" name="obligation">Optional </Attribute>
+        <Attribute language="en" name="comment">The element is useful to indicate the specific legal mandate which requires the resource being described to be created or provided to the public. The content of this element will usually be a reference to a specific Act, Regulation or Case, but may be a URI pointing to the legal instrument in question. </Attribute>
+        <Element name="act">
+            <Attribute language="en" name="label">Act</Attribute>
+            <Attribute language="en" name="definition">A reference to a specific State or Federal Act which requires the creation or provision of the resource</Attribute>
+            <Attribute language="en" name="qualifier type">Element refinement</Attribute>
+        </Element>
+        <Element name="regulation">
+            <Attribute language="en" name="label">Regulation</Attribute>
+            <Attribute language="en" name="definition">A reference to a specific regulation which requires the creation or provision of the resource.</Attribute>
+            <Attribute language="en" name="qualifier type">Element refinement</Attribute>
+        </Element>
+        <Element name="case">
+            <Attribute language="en" name="label">Case Law</Attribute>
+            <Attribute language="en" name="qualifier type">Element refinement</Attribute>
+            <Attribute language="en" name="definition">A reference to a specific case which requires the creation or provision of the resource</Attribute>
+        </Element>
+    </Element>
+    <Element name="Relation">
+        <Attribute language="en" name="label">Relation</Attribute>
+        <Attribute language="en" name="definition">A reference to a related resource.</Attribute>
+        <Attribute language="en" name="obligation">Optional</Attribute>
+        <Attribute language="en" name="comment">Recommended best practice is to reference the resource by means of a string or number conforming to a formal identification system.</Attribute>
+        <Element name="isVersionOf">
+            <Attribute language="en" name="label">Is Version Of</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Attribute language="en" name="definition">The described resource is a version, edition, or adaption of the referenced resource. Changes in version imply substative changes in content rather than differences in format.</Attribute>
+        </Element>
+        <Element name="hasVersion">
+            <Attribute language="en" name="label">Has Version</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Attribute language="en" name="definition">The described resource has a version, edition, or adaptation, namely, the referenced resource.</Attribute>
+        </Element>
+        <Element name="isReplacedBy">
+            <Attribute language="en" name="label">Is Replaced By</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Attribute language="en" name="definition">The described resource is supplanted, displaced, or superseded by the referenced resource.</Attribute>
+        </Element>
+        <Element name="replaces">
+            <Attribute language="en" name="label">Replaces</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Attribute language="en" name="definition">The described resources supplants, displaces, or supersedes the referenced reource.</Attribute>
+        </Element>
+        <Element name="isRequiredBy">
+            <Attribute language="en" name="label">Is Required By</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Attribute language="en" name="definition">The described resource is required by the referenced resource, either physically or logically. </Attribute>
+        </Element>
+        <Element name="requires">
+            <Attribute language="en" name="label">Requires</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Attribute language="en" name="definition">The described resource requires the referenced resource to support its function, delivery, or coherence of content. </Attribute>
+        </Element>
+        <Element name="isPartOf">
+            <Attribute language="en" name="label">Is Part Of</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Attribute language="en" name="definition">The described resource is a physical or logical part of the referenced resource. </Attribute>
+        </Element>
+        <Element name="hasPart">
+            <Attribute language="en" name="label">Has Part</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Attribute language="en" name="definition">The described resource includes the referenced resource either physically or logically. </Attribute>
+        </Element>
+        <Element name="isReferencedBy">
+            <Attribute language="en" name="label">Is Referenced By</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Attribute language="en" name="definition">The described resource is referenced, cited, or otherwise pointed to by the referenced resource. </Attribute>
+        </Element>
+        <Element name="references">
+            <Attribute language="en" name="label">References</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Attribute language="en" name="definition">The described resource references, cites, or otherwise points to the referenced resource. </Attribute>
+        </Element>
+        <Element name="isFormatOf">
+            <Attribute language="en" name="label">Is Format Of</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Attribute language="en" name="definition">The described resource is the same intellectual content of the referenced resource, but presented in another format. </Attribute>
+        </Element>
+        <Element name="hasFormat">
+            <Attribute language="en" name="label">Has Format</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Attribute language="en" name="definition">The described resource pre-existed the referenced resource, which is essentially the same intellectual content presented in another format. </Attribute>
+        </Element>
+        <Element name="isBasisFor">
+            <Attribute language="en" name="label">Is Basis For</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Attribute language="en" name="definition">The described resource pre-existed the referenced resource, which is a performance, production, derivation, translation, or interpretation of the described resource. </Attribute>
+        </Element>
+        <Element name="isBasedOn">
+            <Attribute language="en" name="label">Is Based On</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement </Attribute>
+            <Attribute language="en" name="definition">The described resource is a performance, production, derivation, translation, or interpretation of the referenced resource. </Attribute>
+        </Element>
+    </Element>
+    <Element name="Rights">
+        <Attribute language="en" name="label">Rights Management</Attribute>
+        <Attribute language="en" name="definition">Information about rights held in and over the resource.</Attribute>
+        <Attribute language="en" name="obligation">Optional</Attribute>
+        <Attribute language="en" name="comment">Typically, the Rights element will contain a rights management statement for the resource, or refer to a service providing such information. Rights information often encompasses Intellectual Property Rights (IPR), Copyright, and various Property Rights. If the Rights element is absent, no assumptions can be made about the status of these and other rights with respect to the resource.</Attribute>
+    </Element>
+    <Element name="Source">
+        <Attribute language="en" name="label">Source</Attribute>
+        <Attribute language="en" name="definition">A reference to a resource from which the present resource is derived.</Attribute>
+        <Attribute language="en" name="obligation">Optional</Attribute>
+        <Attribute language="en" name="comment">The present resource may be derived from the Source resource in whole or in part. Recommended best practice is to reference the source resource by means of a string or number conforming to a formal identification system.</Attribute>
+    </Element>
+    <Element name="Type">
+        <Attribute language="en" name="label">Type</Attribute>
+        <Attribute language="en" name="defintion">The nature or genre of the content of the resource.</Attribute>
+        <Attribute language="en" name="obligation">Optional</Attribute>
+        <Attribute language="en" name="comment">Type includes terms describing general categories, genres, or aggregation levels for content. Recommended best practice is to select a value from a controlled vocabulary (for example, the working draft list of Dublin Core Types [DCT1]). To describe the physical or digital manifestation of the resource, use the FORMAT element.</Attribute>
+        <Element name="category">
+            <Attribute language="en" name="label">Category</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement </Attribute>
+            <Attribute language="en" name="definition">The generic type of the resource being described. </Attribute>
+            <Attribute language="en" name="comment">The value for this qualifier must be one of either service, document, or agency. </Attribute>
+        </Element>
+        <Element name="aggregtionLevel">
+            <Attribute language="en" name="label">Aggregtion Level</Attribute>
+            <Attribute language="en" name="qualifier type">Element refinement</Attribute>
+            <Attribute language="en" name="definition">The level of aggregation of the resource being described.</Attribute>
+            <Attribute language="en" name="comment">There are only two values possible for this qualifier, either item or collection.</Attribute>
+        </Element>
+        <Element name="documentType">
+            <Attribute language="en" name="label">Document Type</Attribute>
+            <Attribute language="en" name="qualifier type">Element refinement</Attribute>
+            <Attribute language="en" name="definition">The form of the resource where category = document.</Attribute>
+            <Attribute language="en" name="comment">Document is used in its widest sense and includes such things as software sound files and images. </Attribute>
+        </Element>
+        <Element name="serviceType">
+            <Attribute language="en" name="label">Service Type</Attribute>
+            <Attribute language="en" name="qualifier type">Element refinement</Attribute>
+            <Attribute language="en" name="definition">The type of service being offered where category = service. </Attribute>
+        </Element>
+    </Element>
+</MetadataSet>
Index: /tags/greenstone-3_02-distribution/gli/metadata/dls.mds
===================================================================
--- /tags/greenstone-3_02-distribution/gli/metadata/dls.mds	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/metadata/dls.mds	(revision 13928)
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE MetadataSet SYSTEM "http://www.greenstone.org/dtd/MetadataSet/1.0/MetadataSet.dtd">
+<MetadataSet contact="nzdl.org" creator="New Zealand Digital Libraries Project: Greenstone" family="Development Library Subset" lastchanged="Tue Sep 05 14:40:36 NZST 2006 - kjdon on kanuka" namespace="dls">
+    <Name language="en">Development Library Subset Example Metadata</Name>
+    <Description language="en">A metadata set file for use in The Gatherer, created from original metadata found within the Development Library Subset.</Description>
+    <Element name="Title">
+        <Attribute language="en" name="comment"/>
+        <Attribute language="en" name="definition">The title of this resource.</Attribute>
+        <Attribute language="en" name="label">Title</Attribute>
+        <Attribute name="version">1.0</Attribute>
+    </Element>
+    <Element name="Organization">
+        <Attribute language="en" name="comment"/>
+        <Attribute language="en" name="definition">The organization responsible for producing this resource.</Attribute>
+        <Attribute language="en" name="label">Organization</Attribute>
+        <Attribute name="version">1.0</Attribute>
+    </Element>
+    <Element name="Subject">
+        <Attribute language="en" name="comment">Currently uses a hierarchy.</Attribute>
+        <Attribute language="en" name="definition">The subject of this resource.</Attribute>
+        <Attribute language="en" name="label">Subject And Keywords</Attribute>
+        <Attribute name="version">1.0</Attribute>
+    </Element>
+    <Element name="Keyword">
+        <Attribute language="en" name="comment">Informal.</Attribute>
+        <Attribute language="en" name="definition">A more specific indication of what the resource can be used for.</Attribute>
+        <Attribute language="en" name="label">Keyword</Attribute>
+        <Attribute name="version">1.0</Attribute>
+    </Element>
+    <Element name="Language">
+        <Attribute language="en" name="comment"/>
+        <Attribute language="en" name="definition">The language of this resource.</Attribute>
+        <Attribute language="en" name="label">Language</Attribute>
+        <Attribute name="version">1.0</Attribute>
+    </Element>
+    <Element name="AZList">
+        <Attribute language="en" name="comment">Not the same as an AZList classifier.</Attribute>
+        <Attribute language="en" name="definition">A customizable AZList based on document titles.</Attribute>
+        <Attribute language="en" name="label">AZList</Attribute>
+        <Attribute name="version">1.0</Attribute>
+    </Element>
+</MetadataSet>
Index: /tags/greenstone-3_02-distribution/gli/metadata/dublin.mds
===================================================================
--- /tags/greenstone-3_02-distribution/gli/metadata/dublin.mds	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/metadata/dublin.mds	(revision 13928)
@@ -0,0 +1,1617 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE MetadataSet SYSTEM "http://www.greenstone.org/dtd/MetadataSet/1.0/MetadataSet.dtd">
+<MetadataSet contact="dcmi-feedback@dublincore.org" creator="Dublin Core Metadata Initiative" family="Dublin Core" language_dependent="label, definition, comment" lastchanged="Tue Sep 05 14:40:36 NZST 2006 - kjdon on kanuka" namespace="dc">
+    <!-- English Version sourced from http://www.dublincore.org/documents/dces/ -->
+    <SetLanguage code="en">
+        <Name language="en">Dublin Core Metadata Element Set, Version 1.1: Reference Description</Name>
+        <Description language="en">This document is the reference description, version 1.1 of the Dublin Core Metadata Element Set. This document supersedes the Dublin Core Metadata Element Set, version 1.0. See the Dublin Core Home Page (http://dublincore.org) for further information about the workshops, reports, working group papers, projects, and new developments concerning the Dublin Core Metadata Element set</Description>
+    </SetLanguage>
+    <!-- Maori Version sourced from http://www.tki.org.nz/r/maori/pedagogy/dc_elements_m.php -->
+    <SetLanguage code="mi">
+        <Name>Dublin Core Huanga - Maori (He Tauira)</Name>
+    </SetLanguage>
+    <!-- French Version sourced from http://www-rocq.inria.fr/%7Evercoust/METADATA/DC-fr.1.1.html -->
+    <!--  by Anne-Marie Vercoustre, Inria -->
+    <SetLanguage code="fr">
+        <Name language="fr">ElÃ©ments de mÃ©tadonnÃ©es du Dublin Core, Version 1.1: Description de RÃ©ference</Name>
+        <Description language="fr">Ce document rÃ©sume les derniÃšres dÃ©finitions des Ã©lÃ©ments demÃ©tadonnÃ©es du Dublin Core originellement dÃ©finis dans le document[RFC2413]. Ces nouvelles dÃ©finitions seront officiellement connues comme la Version 1.1. Elles utilisent un standard dÃ©fini formellement pour la description d&apos;Ã©lÃ©ments de mÃ©tadonnÃ©es. Cette formalisation contribue Ã  amÃ©liorer la cohÃ©rence avec d&apos;autres communautÃ©s dÃ©crivant des mÃ©tadonnÃ©es et Ã  augmenter la prÃ©cision, la portÃ©e et la cohÃ©rence interne de la dÃ©finition des Ã©lÃ©ments du Dublin Core.</Description>
+    </SetLanguage>
+    <!-- Russian Version sourced from -->
+    <!-- by Olga Barysheva, National Library of Russia -->
+    <SetLanguage code="ru">
+        <Name language="ru">ÐÐ°Ð±ÐŸÑ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Dublin Core (ÐÑÐ±Ð»ÐžÐœÑÐºÐŸÐ³ÐŸ ÑÐŽÑÐ°) ÐÐµÑÑÐžÑ 1.1: Ð¡Ð¿ÑÐ°Ð²ÐŸÑÐœÐŸÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ</Name>
+        <Description language="ru">ÐÐ°ÑÑÐŸÑÑÐžÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑ ÐŸÐ±ÐŸÐ±ÑÐ°ÐµÑ ÐŸÐ±ÐœÐŸÐ²Ð»ÐµÐœÐœÑÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Dublin Core (ÐÑÐ±Ð»ÐžÐœÑÐºÐŸÐ³ÐŸ ÑÐŽÑÐ°), Ð¿ÐµÑÐ²ÐŸÐœÐ°ÑÐ°Ð»ÑÐœÐŸ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÑ
+ Ð² RFC2413 (ÐÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Dublin Core ÐŽÐ»Ñ ÐœÐ°Ñ
+ÐŸÐ¶ÐŽÐµÐœÐžÑ ÑÐµÑÑÑÑÐŸÐ²). Ð­ÑÐž ÐœÐŸÐ²ÑÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ ÐŸÑÐžÑÐžÐ°Ð»ÑÐœÐŸ ÐžÐ·Ð²ÐµÑÑÐœÑ ÐºÐ°Ðº ÐÐµÑÑÐžÑ 1.1.</Description>
+    </SetLanguage>
+    <!-- Spanish Version sourced from http://www.rediris.es/metadata/. Please note that this is a translation for Dublin Core v1.0 -->
+    <!-- by Javi Masa, RedIRIS -->
+    <SetLanguage code="es">
+        <Name language="es">Elementos del conjunto de metadatas de Dublin Core: DescripciÃ³n de Referencia</Name>
+        <Description language="es">Este documento corresponde a una traducciÃ³n del original en lengua inglesa, con fecha 02/11/1997 que se encuentra en http://purl.org/metadata/dublin_core_elements. Este documento es una descripciÃ³n de referencia de los elementos del conjunto de &quot;Dublin Core&quot;. Para mÃ¡s informaciÃ³n sobre reuniones de trabajo, documentos de trabajo, proyectos y nuevos desarrollos relacionados con el conjunto de elementos que aquÃ­ se describen consultar la &quot;Home Page&quot; de &quot;Dublin Core&quot; (http://purl.org/metadata/dublin_core). Los elementos poseen nombres descriptivos que pretenden transmitir un significado semÃ¡ntico a los mismos. Para promover una interoperabilidad global, una descripciÃ³n del valor de algunos elementos prodrÃ¡ ser asociada a vocabularios controlados. Se asume que otros vocabularios controlados serÃ¡n desarrollados para asegurar esta interoperabilidad en dominios especÃ­ficos. Cada elemento es opcional y puede repetirse. AdemÃ¡s, los elementos pueden aparecer en cualquier orden. Aunque algunos entornos, como HTML, no diferencian entre mayÃºsculas y minÃºsculas, es recomendable escribir correctamente cada metadata segÃºn su definiciÃ³n para evitar conflictos con otros entornos, como XML (Extensible Markup Language) http://www.w3.org/TR/PR-xml</Description>
+    </SetLanguage>
+    <!-- Arabic Version sourced from http://haddouti.de/DC_arabic.html -->
+    <!-- maintained by Hachim Haddouti. -->
+    <SetLanguage code="ar">
+        <Name>Ø¯ØšÙÙÙ ÙÙØ±</Name>
+        <Description>ÙØ±Ø­Øš ØšÙÙ
+ ÙÙ ØµÙØ­Ø©  Ø¯ ØšÙÙÙ ÙÙ  Ø± ØšØ§ÙØ¹Ø±ØšÙ    ÙÙ  ÙØ°Ù Ø§ÙØµÙØ­Ø©  Ù ØšØ§ÙØªØ¹Ø§ÙÙ Ù
+Ø¹ Ø§ÙØ§Ø®ÙØ§Ù Ø§ÙØ¹Ø±Øš Ù
+Ù Ø§ÙÙ
+ÙØªØšØ§ØªØ Ø¯Ø§Ø± Ø§ÙÙØŽØ±Ø Ø§ÙØšØ­ÙØ« Ø§ÙØ¹ÙÙ
+ÙØ© Ù    ÙØ±ØŽØ© Ø¹Ù
+ÙWorking Group On Multilingual Dublin Core (DC-International) Ø</Description>
+    </SetLanguage>
+    <!-- Chinese - Simplified Version from http://dc.library.sh.cn/DC/1-1.htm -->
+    <!-- by Liu Wei, Shanghai Library -->
+    <SetLanguage code="cn">
+        <Name>éœæææ žå¿å
+æ°æ®å
+çŽ é1.1çïŒåèæè¿°</Name>
+        <Description>æ¬ææ¡£å
+³äºéœæææ žå¿å
+æ°æ®å
+çŽ é1.1çæ¬çåèæè¿°ãæ­€æè¿°äžå·²ç»æäº€ç»ISOçšäºåœé
+æç¥šçNISOå®æ¹æ åä¿æäžèŽã    éœæææ žå¿å
+æ°æ®éæ¯äžç§è·šé¢åçä¿¡æ¯èµæºæè¿°æ åãè¿éçä¿¡æ¯èµæºè¢«å®ä¹äžºâä»»äœå
+·ææ è¯çäžè¥¿âãæ­€å®ä¹æ¥èªäºTim Berners-Leeç­äººæèçInternet RFC2396 &quot;Uniform Resource Identifiers (URI): Generic Syntax&quot;æä»¶ãéœæææ žå¿å
+æ°æ®çåºçšé¢åæ²¡ææ ¹æ¬çéå¶ã</Description>
+    </SetLanguage>
+    <!-- Czech Version from http://www.ics.muni.cz/dublin_core/DC-czech-1.1.html -->
+    <!-- Ustav vypocetni techniky Masarykovy univerzity v Brne -->
+    <SetLanguage code="cs">
+        <Name>Soubor metadatovÃœch prvkÅ¯ Dublin Core, verze 1.1: referenÄnÃ­ popis</Name>
+        <Description>Tento dokument je ÄeskÃœm pÅekladem anglickÃ© verze referenÄnÃ­ho popisu souboru metadatovÃœch prvkÅ¯  Dublin Core, verze 1.1 [DCEN1.1]. Tento dokument nahrazuje ÄeskÃœ pÅeklad souboru metadatovÃœch prvkÅ¯ Dublin Core, verze 1.0 [DCCS1.0]. DalÅ¡Ã­ informace o pracovnÃ­ch seminÃ¡ÅÃ­ch (workshopech), zprÃ¡vÃ¡ch, studiÃ­ch pracovnÃ­ch skupin, projektech a dalÅ¡Ã­m vÃœvoji souboru metadatovÃœch prvkÅ¯ Dublin Core najdete na domovskÃ© strÃ¡nce Dublin Core (http://purl.org/dc)</Description>
+    </SetLanguage>
+    <!-- Dutch Version from http://www.kb.nl/coop/donor/project-nl-index.html?/coop/donor/rapporten/DCsimpleformat.html -->
+    <!-- by ... -->
+    <SetLanguage code="nl">
+        <Name>Rapporten Dublin Core Simple Format</Name>
+        <Description>Dit document beschrijft welke Dublin Core metadata elementen er zijn en geeft een korte definitie van elk element. Voor uitgebreide uitleg en gebruik van de Dublin Core elementen wordt u verwezen naar de gebruikershandleiding. Deze vertaling geeft ook de keuzes aan voor standaarden (taalcodes, datum codes) die wij in DONOR verband gaan hanteren. In zoverre kan deze vertaling afwijken van het oorspronkelijke document &quot;Description of Dublin Core Elements&quot; http://purl.org/metadata/dublin_core_elements&quot;</Description>
+    </SetLanguage>
+    <!-- Finnish Version from http://www.lib.helsinki.fi/dublin_core/dcref-fin.html -->
+    <!-- by Jani Stenvall and Juha Hakala, Helsinki University Library -->
+    <SetLanguage code="fi">
+        <Name/>
+        <Description/>
+    </SetLanguage>
+    <!-- Interlingua Version sourced from http://www.nautilus.com.br/%7Eensjo/ia/purl.org/dc/documents/rec-dces-19990702.htm -->
+    <!-- by Emerson Jose` Silveira da Costa -->
+    <SetLanguage code="ia">
+        <Name>Collection de elementos de metadatos de Dublin Core, version 1.1: Description de referentia</Name>
+        <Description>Isto es un traduction de un Recommendation del Dublin Core Metadata Initiative. Le publication como un recommendation significa que le specificationes es stabile e su adoption es supportate per le communitate Dublin Core (http://purl.org/dc/).</Description>
+    </SetLanguage>
+    <!-- Marathi Version sourced from http://bioinfo.ernet.in/library/dc/ele.txt -->
+    <!-- by by Shubhada Nagarkar, Bioinformatics Centre, University of Pune -->
+    <SetLanguage code="mr">
+        <Name>à€¡à€¬à¥à€²à€¿à€š à€à¥à€° à€®à¥à€à€Ÿà€¡à¥à€à€Ÿ à€žà¥à€ à€à€µà¥à€€à¥à€€à¥ à¥§.à¥§ à€žà€à€Šà€°à¥à€­ à€žà¥à€ªà€·à¥à€à¥à€à€°à€£ à¥§.à¥§ à€¡à€¬à¥à€²à€¿à€š à€à¥à€° à€®à¥à€à€Ÿà€¡à¥à€à€Ÿà€à€µà¥à€€à¥à€€à¥ à¥§.à¥§.</Name>
+        <Description>à¥§.à¥§ à€¡à€¬à¥à€²à€¿à€š à€à¥à€° à€®à¥à€à€Ÿà€¡à¥à€à€Ÿ à€¹à¥ à€µà¥à€à€µà¥à€à€³à¥à€¯à€Ÿ à€µà€¿à€·à€¯à€Ÿà€€à¥à€² à€®à€Ÿà€¹à¥à€€à¥ à€žà€Ÿà€ à¥à€¯à€Ÿà€à€µà€Šà¥à€Šà€²à€à¥ à€®à€Ÿà€¹à¥à€€à¥ à€Šà¥à€£à¥à€¯à€Ÿà€à¥ à€®à€Ÿà€šà€ à€à€¹à¥.  à€¯à€Ÿà€€ à€®à€Ÿà€¹à¥à€€à¥à€žà€Ÿà€ à€Ÿ à€®à¥à€¹à€£à€à¥ à€à¥à€¯à€Ÿà€²à€Ÿ à€à€³à€ à€à€¹à¥ à€
+à€žà€Ÿ à€à€žà€€à¥.  à€
+à€¶à€Ÿ à€ªà¥à€°à€à€Ÿà€°à€à¥ à€µà¥à€¯à€Ÿà€à¥à€¯à€Ÿ à€®à€Ÿà€¹à¥à€€à¥ à€à€Ÿà€³à¥à€¯à€µà€°à¥à€² à€. à€à€«.à€žà¥. à¥šà¥©à¥¯à¥¬URI: Generic Syntax -- Tim Berners Lee et al. à€¡à€¬à¥à€²à€¿à€š à€à¥à€° à€®à€Ÿà€šà€ à€à¥à€£à€€à¥à€¯à€Ÿà€¹à¥ à€ªà¥à€°à€à€Ÿà€°à€à¥à€¯à€Ÿ à€®à€Ÿà€¹à¥à€€à¥ à€žà€Ÿà€ à¥à€¯à€Ÿà€à€žà€Ÿà€ à¥ à€µà€Ÿà€ªà€°à€€à€Ÿ à€¯à¥à€€à¥.  à€€à¥à€¯à€Ÿà€žà€Ÿà€ à¥ à€à¥à€£à€€à€Ÿà€¹à¥ à€®à€à¥à€à€Ÿà€µ à€šà€Ÿà€¹à¥.</Description>
+    </SetLanguage>
+    <Element name="Title">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Title</Attribute>
+            <Attribute name="definition">A name given to the resource.</Attribute>
+            <Attribute name="comment">Typically, a Title will be a name by which the resource is formally known.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Taitara</Attribute>
+            <Attribute name="definition">Te ingoa ka tapaina tetahi rauemi.</Attribute>
+            <Attribute name="comment">Ko te tikanga, ko te Taitara te ingoa ka mohio whanuitia te ingoa.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Titre</Attribute>
+            <Attribute name="definition">Le nom donnÃ© Ã  la ressource.</Attribute>
+            <Attribute name="comment">Typiquement, un titre sera le nom par lequel la ressource est officiellement connue.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÐ°Ð·Ð²Ð°ÐœÐžÐµ</Attribute>
+            <Attribute name="definition">ÐÐŒÑ, ÐŽÐ°ÐœÐœÐŸÐµ ÑÐµÑÑÑÑÑ.</Attribute>
+            <Attribute name="comment">ÐÐ±ÑÑÐœÐŸ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµÐŒ ÑÐ²Ð»ÑÐµÑÑÑ ÐžÐŒÑ, Ð¿ÐŸÐŽ ÐºÐŸÑÐŸÑÑÐŒ ÑÐµÑÑÑÑ ÐŸÑÐžÑÐžÐ°Ð»ÑÐœÐŸ ÐžÐ·Ð²ÐµÑÑÐµÐœ.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">TÃ­tulo</Attribute>
+            <Attribute name="definition">El nombre dado a un recurso, usualmente por el autor.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙØ¹ÙÙØ§Ù</Attribute>
+            <Attribute name="definition">ÙØ°Ø§ Ø§ÙØ§Ø³Ù
+ ÙØ¹Ø·Ù ÙÙÙ
+ØµØ¯Ø±, Ù
+Ù ÙØšÙ Ø§ÙÙ
+ØšØ¯Ø¹ Ø§Ù Ø§ÙÙØ§ØŽØ±</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">èµæºå</Attribute>
+            <Attribute name="definition">èµäºèµæºçåç§°ã</Attribute>
+            <Attribute name="comment">èµæºåäžè¬æèµæºå¯¹è±¡æ­£åŒå
+¬åŒçåç§°ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">NÃ¡zev</Attribute>
+            <Attribute name="definition">JmÃ©no danÃ© zdroji.</Attribute>
+            <Attribute name="comment">NÃ¡zev bude typicky jmÃ©no, pod nÃ­mÅŸ je zdroj oficiÃ¡lnÄ znÃ¡m.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Titel</Attribute>
+            <Attribute name="definition">De naam van de Internetbron. Meestal gegeven door de auteur, maker of uitgever</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Titulo</Attribute>
+            <Attribute name="definition">Un nomine date al ressource.</Attribute>
+            <Attribute name="comment">Typicamente se utiliza un nomine per le qual le ressource es formalmente cognite.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€¶à¥à€°à¥à€·à€</Attribute>
+            <Attribute name="definition">à€ªà€°à¥à€¯à€Ÿà€¯à¥ à€¶à¥à€°à¥à€·à€</Attribute>
+            <Attribute name="comment">à€žà€à€à¥à€·à€¿à€ªà¥à€€ ,  à€­à€Ÿà€·à€Ÿà€à€€à€°à¥à€€  à€¶à¥à€°à¥à€·à€</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Creator">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Creator</Attribute>
+            <Attribute name="definition">An entity primarily responsible for making the content of the resource.</Attribute>
+            <Attribute name="comment">Examples of a Creator include a person, an organisation, or a service. Typically, the name of a Creator should be used to indicate the entity.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Kaihanga</Attribute>
+            <Attribute name="definition">Te putahi, nana, na ratou ranei i matua oti ai te hanganga o te rauemi.</Attribute>
+            <Attribute name="comment">Ko te tangata, he putahitanga, he ratonga ranei etahi tauira Kaihanga. Ko te tikanga, ko te Kaihanga te ingoa ka whakamahia hei tohu i te putahi na ratou te hanganga.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">CrÃ©ateur</Attribute>
+            <Attribute name="definition">L&apos;entitÃ© principalement responsable de la crÃ©ation du contenu de la ressource.</Attribute>
+            <Attribute name="comment">Exemples de CrÃ©ateur incluent une personne, une organisation, ou un service. Typiquement, un nom du CrÃ©ateur devrait Ãªtre utilisÃ© pour dÃ©signer cette entitÃ©.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">Ð¡ÐŸÐ·ÐŽÐ°ÑÐµÐ»Ñ</Attribute>
+            <Attribute name="definition">ÐÐžÑÐŸ, ÐœÐµÑÑÑÐµÐµ Ð¿ÐµÑÐ²ÐžÑÐœÑÑ ÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÐŸÑÑÑ Ð·Ð° ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÑÐžÐŒÐµÑÑ Ð¡ÐŸÐ·ÐŽÐ°ÑÐµÐ»Ñ Ð²ÐºÐ»ÑÑÐ°ÑÑ Ð¿ÐµÑÑÐŸÐœÑ, ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÑ ÐžÐ»Ðž ÑÐ»ÑÐ¶Ð±Ñ. ÐÐ±ÑÑÐœÐŸ ÐžÐŒÑ Ð¡ÐŸÐ·ÐŽÐ°ÑÐµÐ»Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÐžÐœÐŽÐžÐºÐ°ÑÐžÐž ÐŸÐ±ÑÐµÐºÑÐ°.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Autor o Creador</Attribute>
+            <Attribute name="definition">La persona u organizaciÃ³n responsable de la creaciÃ³n del contenido intelectual del recurso. Por ejemplo, los autores en el caso de documentos escritos, artistas, fotografos e ilustradores en el caso de recursos visuales.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙÙØ§ØªØš Ø§Ù Ø§ÙÙ
+ØšØ¯Ø¹</Attribute>
+            <Attribute name="definition">ÙÙ Ø§ÙØŽØ®Øµ Ø§Ù Ø§ÙÙ
+Ø€Ø³Ø³Ø© Ø£ÙÙØ§  Ø¹Ù ÙØŽØŠ Ø§ÙÙ
+Ø­ØªÙÙ Ø§ÙÙÙØ± Ù ÙÙÙ
+ØµØ¯Ø± , Ø¹ÙÙ Ø³ØšÙÙ Ø§ÙÙ
+Ø«Ø§Ù , Ø§ÙÙ
+Ø€ÙÙÙÙ ÙÙ Ø­Ø§ÙØ© Ø§ÙØ«Ø§ØŠÙ Ø§ÙÙ
+ÙØªÙØšØ© , Ù Ø§ÙÙÙØ§ÙÙÙ , Ø§ÙÙ
+ØµÙØ±ÙÙ ÙÙ Ø­Ø§ÙØ© Ø§ÙÙ
+ØµØ§Ø¯Ø± Ø§ÙÙ
+Ø±ØŠÙØ©</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">åå»ºè
+</Attribute>
+            <Attribute name="definition">åå»ºèµæºå
+å®¹çäž»èŠèŽ£ä»»è
+ã</Attribute>
+            <Attribute name="comment">åå»ºè
+çå®äŸå
+æ¬äžªäººïŒç»ç»ææé¡¹æå¡ãäžè¬èèšïŒçšåå»ºè
+çåç§°æ¥æ è¯è¿äžæ¡ç®ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">TvÅ¯rce</Attribute>
+            <Attribute name="definition">Entita primÃ¡rnÄ odpovÄdnÃ¡ za vytvoÅenÃ­ obsahu zdroje.</Attribute>
+            <Attribute name="comment">PÅÃ­klady TvÅ¯rce zahrnujÃ­ osobu, organizaci nebo sluÅŸbu. K oznaÄenÃ­ entity se typicky pouÅŸÃ­vÃ¡ jmÃ©no tvÅ¯rce.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Auteur of maker</Attribute>
+            <Attribute name="definition">De auteur, maker of organisatie die primair verantwoordelijk is voor de intellectuele inhoud van het werk. Bijvoorbeeld auteurs in geval van geschreven documenten, artiesten, fotografen of illustrators in geval van visuele bronnen.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Creator</Attribute>
+            <Attribute name="definition">Le entitate primarimente responsabile pro producer le contento del ressource.</Attribute>
+            <Attribute name="comment">Exemplos de creator include un persona, un organization, o un servicio. Typicamente se utiliza un nomine de creator pro indicar iste entitate.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€šà€¿à€°à¥à€®à€Ÿà€€à€Ÿ, à€à€šà€</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à€Ÿ à€šà€¿à€°à¥à€®à€Ÿà€£  à€à€°à€£à€Ÿà€°à€Ÿ</Attribute>
+            <Attribute name="comment">à€à€Šà€Ÿ.  à€²à¥à€à€, à€²à¥à€à€¿à€à€Ÿ,  à€µà¥à€¯à€à¥à€€à¥, à€žà€à€žà¥à€¥à€Ÿ,  à€žà€à€ªà€Ÿà€Šà€, à€žà€à€ªà€Ÿà€Šà€¿à€à€Ÿ</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Subject">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Subject and Keywords</Attribute>
+            <Attribute name="definition">The topic of the content of the resource.</Attribute>
+            <Attribute name="comment">Typically, a Subject will be expressed as keywords, key phrases or classification codes that describe a topic of the resource. Recommended best practice is to select a value from a controlled vocabulary or formal classification scheme.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Kaupapa</Attribute>
+            <Attribute name="definition">Te take/ nga take o te kaupapa, o te rauemi.</Attribute>
+            <Attribute name="comment">Ko te tikanga, ka whakaaturia te kaupapa o te rauemi e nga kupu matua, nga kimahi matua, nga tohu wehewehenga whakaahua ranei.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Sujet</Attribute>
+            <Attribute name="definition">Le sujet du contenu de la ressource.</Attribute>
+            <Attribute name="comment">Typiquement, le sujet sera dÃ©crit par un ensemble de mots-clefs ou de phrases ou un code de classification qui prÃ©cisent le sujet de la ressource. L&apos;utilisation de vocabulaires contrÃŽlÃ©s et de schÃ©mas formels de classification est encouragÃ©e.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÑÐµÐŽÐŒÐµÑ Ðž ÐºÐ»ÑÑÐµÐ²ÑÐµ ÑÐ»ÐŸÐ²Ð°</Attribute>
+            <Attribute name="definition">Ð¢ÐµÐŒÐ° ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÐ±ÑÑÐœÐŸ ÐÑÐµÐŽÐŒÐµÑ Ð²ÑÑÐ°Ð¶Ð°ÐµÑÑÑ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÐºÐ»ÑÑÐµÐ²ÑÑ
+ ÑÐ»ÐŸÐ², ÐºÐ»ÑÑÐµÐ²ÑÑ
+ ÑÑÐ°Ð· ÐžÐ»Ðž  ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐŸÐœÐœÑÑ
+ ÐºÐŸÐŽÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÐŸÐ¿ÐžÑÑÐ²Ð°ÑÑ ÑÐµÐŒÑ ÑÐµÑÑÑÑÐ°. ÐÐ»Ñ Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ Ð²ÑÐ±ÐžÑÐ°ÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐžÐ· ÐºÐŸÐœÑÑÐŸÐ»ÐžÑÑÐµÐŒÐŸÐ³ÐŸ ÑÐ»ÐŸÐ²Ð°ÑÑ ÐžÐ»Ðž ÑÐŸÑÐŒÐ°Ð»ÑÐœÐŸÐ¹ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÑÑ
+ÐµÐŒÑ.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Claves</Attribute>
+            <Attribute name="definition">Los tÃ³picos del recurso. TÃ­picamente, Subject expresarÃ¡ las claves o frases que describen el tÃ­tulo o el contenido del recurso. Se fomentarÃ¡ el uso de vocabularios controlados y de sistemas de clasificaciÃ³n formales. Se pueden ver ejemplos de vocabularios controlados en: Controlled vocabularies, thesauri and classification systems available in the WWW. DC Subject</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙÙ
+ÙØ¶ÙØ¹ Ù Ø§ÙÙÙÙ
+Ø§Øª Ø§ÙØ±ØŠÙØ³ÙØ©</Attribute>
+            <Attribute name="definition">ÙÙ Ù
+ÙØ¶ÙØ¹ Ø§ÙÙ
+ØµØ¯Ø±. ÙÙ
+ÙØ°Ø¬ÙØ§  ÙØ¹ØšØ± Ø¹Ù Ø§ÙÙ
+ÙØ¶ÙØ¹ ØšØ§Ø³ØªØ®Ø¯Ø§Ù
+Ù
+ÙØªØ§Ø­  Ø§ÙÙÙÙ
+Ø§Øª  Ø§Ù Ø¬Ù
+Ù Ø§ÙØªÙ  ØªØµÙ Ù
+ÙØ¶ÙØ¹ Ø§Ù Ù
+Ø­ØªÙÙ Ø§ÙÙ
+ØµØ¯Ø± , Ù ÙØ³ØªØ­Ø³Ù Ø§Ø³ØªØ®Ø¯Ø§Ù
+ Ù
+ÙØ±Ø¯Ø§Øª Ù
+Ø®Ø·Ø·Ø©Ù Ù
+Ø­ÙÙ
+Ø©  ÙØ§Ø¯ÙØ© ØªØµÙÙÙ ØŽÙÙÙØ©</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">äž»é¢åå
+³é®è¯</Attribute>
+            <Attribute name="definition">èµæºå
+å®¹çäž»é¢æè¿°ã</Attribute>
+            <Attribute name="comment">åŠæèŠæè¿°ç¹å®èµæºçæäžäž»é¢ïŒäžè¬éçšå
+³é®è¯ãå
+³é®å­ç­è¯­æåç±»å·ïŒæå¥œäž»é¢åå
+³é®è¯ä»åæ§    è¯è¡šæè§èçåç±»äœç³»äž­ååŒã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">PÅedmÄt a klÃ­ÄovÃ¡ slova</Attribute>
+            <Attribute name="definition">TÃ©ma obsahu zdroje.</Attribute>
+            <Attribute name="comment">PÅedmÄt bude typicky vyjÃ¡dÅen pomocÃ­ klÃ­ÄovÃœch slov, klÃ­ÄovÃœch frÃ¡zÃ­ nebo klasifikaÄnÃ­ch znakÅ¯ popisujÃ­cÃ­ch tÃ©ma zdroje. DoporuÄuje se vybÃ­rat hodnotu prvku z ÅÃ­zenÃ©ho slovnÃ­ku nebo formÃ¡lnÃ­ho klasifikaÄnÃ­ho schÃ©matu.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Onderwerp en trefwoorden</Attribute>
+            <Attribute name="definition">Het onderwerp van de Internetbron. Het onderwerp wordt beschreven in korte zinnen of door het gebruik van trefwoorden. Het gebruik van gecontroleerde trefwoorden of classificatie schema&apos;s wordt aanbevolen.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Subjecto e parolas-clave</Attribute>
+            <Attribute name="definition">Le topico del contento del ressource.</Attribute>
+            <Attribute name="comment">Typicamente le subjecto es expresse per medio de parolas-clave, phrases-clave, o codices de classification que describe le topico del ressource. Le melior practica recommendate es selectionar un valor a partir de un vocabulario controlate o un schema formal de classification.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€µà€¿à€·à€¯</Attribute>
+            <Attribute name="definition">à€µà€¿à€·à€¯</Attribute>
+            <Attribute name="comment">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à€Ÿ, à€à¥à€à€Ÿà€šà€žà€Ÿà€§à€šà¥ à€¯à€Ÿà€€à¥à€² à€à€¶à€¯ à€žà¥à€ªà€·à¥à€ à€à€°à€£à€Ÿà€°à¥ à€¶à€¬à¥à€Š, à€µà€¿à€·à€¯à€Ÿà€à¥ à€µà€°à¥à€à¥à€à€°à€£ à€à€°à€€à€Ÿà€šà€Ÿ à€¶à€¬à¥à€Šà€žà€à€à¥à€°à€¹ à€
+à€¥à€µà€Ÿ à€¶à€¬à¥à€Š à€à¥à€·à€Ÿà€à€Ÿ à€µà€Ÿà€ªà€° à€à€°à€Ÿà€µà€Ÿ</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Description">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Description</Attribute>
+            <Attribute name="definition">An account of the content of the resource.</Attribute>
+            <Attribute name="comment">Description may include but is not limited to: an abstract, table of contents, reference to a graphical representation of content or a free-text account of the content.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Whakaaturanga</Attribute>
+            <Attribute name="definition">He whakaaturanga o nga kaupapa o te rauemi.</Attribute>
+            <Attribute name="comment">Ka uru atu, engari ehara noa ko: te whakarapopototanga korero, te ihirangi, te tohutanga o te kaupapa ma te whakaahua, te whakaaturanga kore kupu ranei, o te kauapapa.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Description</Attribute>
+            <Attribute name="definition">Une description du contenu de la ressource.</Attribute>
+            <Attribute name="comment">Une Description peut contenir, mais ce n&apos;est pas limitatif: un rÃ©sumÃ©, une table des matiÃšres, une rÃ©fÃ©rence Ã  une reprÃ©sentation graphique du contenu, ou un texte libre sur le contenu.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÐ¿ÐžÑÐ°ÐœÐžÐµ</Attribute>
+            <Attribute name="definition">Ð¡ÐŸÐŸÐ±ÑÐµÐœÐžÐµ ÐŸ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐž ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÐ¿ÐžÑÐ°ÐœÐžÐµ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐŸ (Ð¿ÐŸ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÑÑÐž) Ð² Ð²ÐžÐŽÐµ: ÑÐµÑÐµÑÐ°ÑÐ°, ÐŸÐ³Ð»Ð°Ð²Ð»ÐµÐœÐžÑ, ÑÑÑÐ»ÐºÐž ÐœÐ° Ð³ÑÐ°ÑÐžÑÐµÑÐºÐŸÐµ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÐžÐ»Ðž Ð¿ÑÐŸÑÑÐŸÐ³ÐŸ ÑÐµÐºÑÑÐŸÐ²ÐŸÐ³ÐŸ ÐžÐ·Ð»ÐŸÐ¶ÐµÐœÐžÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">DescripciÃ³n</Attribute>
+            <Attribute name="definition">Una descripciÃ³n textual del recurso, tal como un resumen en el caso de un documento o una descripciÃ³n del contenido en el caso de un documento visual.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙÙØµÙ</Attribute>
+            <Attribute name="definition">ÙÙ ÙØµÙ ÙØµÙ  ÙÙ
+Ø­ØªÙÙ Ø§ÙÙ
+ØµØ¯Ø±, ÙÙØ¶Ù
+ Ø§ÙÙ
+ÙØ®ØµØ§Øª ÙÙ Ø­Ø§ÙØ© Ø§ÙÙØ«Ø§ØŠÙ Ù
+Ø«Ù Ø§ÙØ§ØŽÙØ§Ø¡ Ø§ÙÙ
+ÙØªÙØšØ© Ø§Ù ØªÙØµÙÙ Ø§ÙÙ
+Ø­ØªÙÙ ÙÙ Ø­Ø§ÙØ© Ø§ÙÙ
+ØµØ§Ø¯Ø± Ø§ÙÙ
+Ø±ØŠÙØ©</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">è¯Žæ</Attribute>
+            <Attribute name="definition">èµæºå
+å®¹çè§£é</Attribute>
+            <Attribute name="comment">è¯Žæå¯ä»¥å
+æ¬äœäžéäºä»¥äžå
+å®¹ïŒææãç®åœãå¯¹ä»¥åŸåœ¢æ¥æ­ç€ºå
+å®¹çèµæºèèšçæå­è¯Žæãæè
+äž    äžªæå
+³èµæºå
+å®¹çèªç±ææ¬æè¿°ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">Popis</Attribute>
+            <Attribute name="definition">VysvÄtlenÃ­ obsahu zdroje.</Attribute>
+            <Attribute name="comment">Popis mÅ¯ÅŸe obsahovat (mimo jinÃ©): abstrakt, obsah, odkaz na grafickÃ© nebo volnÃ© textovÃ© vyjÃ¡dÅenÃ­ obsahu.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Omschrijving</Attribute>
+            <Attribute name="definition">Een omschrijving van de inhoud van de Internetbron. Abstracts of inhoudsomschrijvingen.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Description</Attribute>
+            <Attribute name="definition">Un description del contento del ressource.</Attribute>
+            <Attribute name="comment">Le description pote includer, ma non se limita a: summario, indice, referentia a un representation graphic del contento o un texto libere a proposito del contento.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€µà€°à¥à€£à€š</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à¥, à€à¥à€à€Ÿà€šà€žà€Ÿà€§à€šà€Ÿà€à¥à€µà€°à¥à€£à€š</Attribute>
+            <Attribute name="comment">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à¥ à€šà€¿à€µà¥à€Šà€š, à€à€²à¥à€, à€à€¿à€€à¥à€°à€°à¥à€ª</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Publisher">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Publisher</Attribute>
+            <Attribute name="definition">An entity responsible for making the resource available.</Attribute>
+            <Attribute name="comment">Examples of a Publisher include a person, an organisation, or a service. Typically, the name of a Publisher should be used to indicate the entity.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Kaiwhakaputa</Attribute>
+            <Attribute name="definition">Te putahi nana i whakaputa te rauemi.</Attribute>
+            <Attribute name="comment">Ko te tangata, he putahitanga, he ratonga ranei etahi tauira Kaiwhakaputa. Ko te tikanga, ka whakamahia te ingoa o te Kaiwhakaputa hei tohu i te putahi.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Editeur</Attribute>
+            <Attribute name="definition">L&apos;entitÃ© responsable de la diffusion de la ressource, dans sa forme actuelle, tels, un dÃ©partement universitaire, une entreprise.</Attribute>
+            <Attribute name="comment">Exemples d&apos;Editeurs incluent une personne, une organisation, ou un service. Typiquement, le nom d&apos;une maison d&apos;Ã©dition devrait Ãªtre utilisÃ© ici.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÐ·ÐŽÐ°ÑÐµÐ»Ñ</Attribute>
+            <Attribute name="definition">ÐÐžÑÐŸ, ÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÐŸÐµ Ð·Ð° Ð²Ð²ÐŸÐŽ ÑÐµÑÑÑÑÐ° Ð² ÐŸÐ±ÑÐ°ÑÐµÐœÐžÐµ.</Attribute>
+            <Attribute name="comment">ÐÑÐžÐŒÐµÑÑ ÐÐ·ÐŽÐ°ÑÐµÐ»Ñ Ð²ÐºÐ»ÑÑÐ°ÑÑ Ð¿ÐµÑÑÐŸÐœÑ, ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÑ ÐžÐ»Ðž ÑÐ»ÑÐ¶Ð±Ñ. ÐÐ±ÑÑÐœÐŸ ÐžÐŒÑ ÐÐ·ÐŽÐ°ÑÐµÐ»Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÐžÐœÐŽÐžÐºÐ°ÑÐžÐž ÐŸÐ±ÑÐµÐºÑÐ°.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Editor</Attribute>
+            <Attribute name="definition">&gt;La entidad responsable de hacer que el recurso se encuentre disponible en la red en su formato actual, por ejemplo la empresa editora, un departamento universitario u otro tipo de organizaciÃ³n.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙÙØ§ØŽØ±</Attribute>
+            <Attribute name="definition">ÙÙ Ø§ÙÙÙØŠØ© Ø§ÙÙ
+Ø³Ø€ÙÙØ© Ø¹Ù ØµÙØ§Ø¹Ø© Ø§ÙÙ
+ØµØ¯Ø± Ø§ÙÙ
+ØªÙÙØ± ÙÙ Ø­Ø§ÙØªÙ Ø§ÙØ­Ø§Ø¶Ø±Ø©, Ù
+Ø«Ù Ø¯Ø§Ø± Ø§ÙÙØŽØ±, ÙØ³Ù
+ Ø¬Ø§Ù
+Ø¹Ù Ø§Ù Ù
+Ø€Ø³Ø³Ø© Ø§Ø¹Ù
+Ø§Ù</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">åºçè
+</Attribute>
+            <Attribute name="definition">äœ¿èµæºæäžºå¯ä»¥è·åŸå¹¶å¯çšçèŽ£ä»»è
+ã</Attribute>
+            <Attribute name="comment">åºçè
+çå®äŸå
+æ¬äžªäœïŒç»ç»ïŒææå¡ãäžè¬èèšïŒåºè¯¥çšåºçè
+çåç§°æ¥æ è¯è¿äžæ¡ç®ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">Vydavatel</Attribute>
+            <Attribute name="definition">Entita odpovÄdnÃ¡ za zpÅÃ­stupnÄnÃ­ zdroje.</Attribute>
+            <Attribute name="comment">PÅÃ­klady Vydavatele zahrnujÃ­ osobu, organizaci nebo sluÅŸbu. K oznaÄenÃ­ entity se typicky pouÅŸÃ­vÃ¡ jmÃ©no vydavatele.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Uitgever</Attribute>
+            <Attribute name="definition">De entiteit die verantwoordelijk is voor het beschikbaarstellen van de Internetbron in de huidig vorm. Bijvoorbeeld een uitgeversbedrijf, een universiteitsafdeling.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Editor</Attribute>
+            <Attribute name="definition">Un entitate responsabile pro disponibilizar le ressource.</Attribute>
+            <Attribute name="comment">Exemplos de editor include un persona, un organization, o un servicio. Typicamente se utiliza un nomine de editor pro indicar le entitate.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€ªà¥à€°à€à€Ÿà€¶à€</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à€Ÿ  à€à€ªà€²à€¬à¥à€§ à€à€°à¥à€š à€Šà¥à€£à€Ÿà€°à€Ÿ</Attribute>
+            <Attribute name="comment">à€à€Šà€Ÿ.à€ à€ªà¥à€°à€à€Ÿà€¶à€ , à€ªà¥à€°à€à€Ÿà€¶à€š  à€žà€à€žà¥à€¥à€Ÿ, à€žà¥à€µà€Ÿ    à€®à€Ÿà€¹à€¿à€€à¥ à€à€Ÿà€ªà¥à€² à€°à¥à€ªà€Ÿà€€  à€
+à€¥à€µà€Ÿ à€à€à€à€°à€šà¥à€ à€µà€° à€à€ªà€²à€¬à¥à€§ à€à€°à¥à€š à€Šà¥à€£à€Ÿà€°à€Ÿ</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Contributor">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Contributor</Attribute>
+            <Attribute name="definition">An entity responsible for making contributions to the content of the resource.</Attribute>
+            <Attribute name="comment">Examples of a Contributor include a person, an organisation, or a service. Typically, the name of a Contributor should be used to indicate the entity.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Kaiwhakaaro</Attribute>
+            <Attribute name="definition">Te putahi nana, na ratou ranei nga whakakaupapatanga whakaaro o te rauemi.</Attribute>
+            <Attribute name="comment">Ko te tangata, he putahitanga, he ratonga ranei etahi tauira Kaiwhakaaro. Ko te tikanga ka whakamahia te ingoa o te Kaiwhakaaro hei tohu i te putahi.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Contributeur</Attribute>
+            <Attribute name="definition">Une entitÃ© qui a contribuÃ© Ã  la crÃ©ation du contenu de la ressource.</Attribute>
+            <Attribute name="comment">Exemples de Contributeur incluent une personne, une organisation, ou un service. Typiquement, le nom d&apos;un contributeur devrait Ãªtre utilisÃ© ici pour dÃ©signer l&apos;entitÃ©.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">Ð¡ÐŸÐžÑÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»Ñ</Attribute>
+            <Attribute name="definition">ÐÐžÑÐŸ, Ð²ÐœÐµÑÑÐµÐµ Ð²ÐºÐ»Ð°ÐŽ Ð² ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÑÐžÐŒÐµÑÑ Ð¡ÐŸÐžÑÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»Ñ Ð²ÐºÐ»ÑÑÐ°ÑÑ Ð¿ÐµÑÑÐŸÐœÑ, ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÑ ÐžÐ»Ðž ÑÐ»ÑÐ¶Ð±Ñ. ÐÐ±ÑÑÐœÐŸ ÐžÐŒÑ Ð¡ÐŸÐžÑÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÐžÐœÐŽÐžÐºÐ°ÑÐžÐž ÐŸÐ±ÑÐµÐºÑÐ°.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Otros Colaboradores</Attribute>
+            <Attribute name="definition">Una persona u organizacion que haya tenido una contribuciÃ³n intelectual significativa en la creaciÃ³n del recurso pero cuyas contribuciones son secundarias en comparaciÃ³n a las de las personas u organizaciones especificadas en el elementeo Creator (por ejemplo, editor, ilustrador y traductor).</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙÙ
+Ø³Ø§ÙÙ
+ Ø§ÙØ§Ø®Ø±</Attribute>
+            <Attribute name="definition">ÙÙ Ø§ÙØŽØ®Øµ Ø§Ù Ø§ÙÙ
+Ø€Ø³Ø³Ø© Ø§ÙØºÙØ± Ù
+Ø°ÙÙØ± ØµØ±Ø§Ø­Ø© ÙÙ Ø¹Ø§Ù
+Ù &quot; Ø§ÙÙ
+ØšØ¯Ø¹ &quot; Ù Ø§ÙØ°Ù ÙØ¯Ù
+ Ù
+Ø³Ø§ÙÙ
+Ø§Øª ÙÙØ±ÙØ© ÙØ§Ù
+Ø© ÙÙÙ
+ØµØ¯Ø±, ÙÙÙ Ù
+Ø³Ø§ÙÙ
+ØªÙØªØšÙÙ    Ø«Ø§ÙÙÙØ© Ù
+ÙØ§Ø±ÙØ© Ù
+Ø¹ Ø§ÙØŽØ®Øµ Ø£Ù Ø§ÙÙ
+Ø€Ø³Ø³Ø© Ø§ÙÙ
+Ø°ÙÙØ±Ø© ÙØµØ§ ÙÙ Ø¹Ø§Ù
+Ù &quot; Ø§ÙÙ
+ÙØŽØŠ &quot; Ù
+Ø«ÙØ§Ù Ù
+ØµØ­Ø­, Ø§ÙÙ
+ØªØ±Ø¬Ù
+, Ø§Ù Ø§ÙÙ
+ÙØ³Ø±</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">å
+¶ä»èŽ£ä»»è
+</Attribute>
+            <Attribute name="definition">å¯¹èµæºçå
+å®¹äœåºèŽ¡ç®çå
+¶ä»å®äœã</Attribute>
+            <Attribute name="comment">å
+¶ä»èŽ£ä»»è
+çå®äŸå¯å
+æ¬äžªäººãç»ç»ææé¡¹æå¡ãäžè¬èèšïŒçšå
+¶ä»èŽ£ä»»è
+çåå­æ¥æ è¯è¿äžæ¡ç®ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">PÅispÄvatel</Attribute>
+            <Attribute name="definition">Entita, kterÃ¡ pÅispÄla k vytvoÅenÃ­ obsahu zdroje.</Attribute>
+            <Attribute name="comment">PÅÃ­klady PÅispÄvatele zahrnujÃ­ osobu, organizaci nebo sluÅŸbu. K oznaÄenÃ­ entity se typicky pouÅŸÃ­vÃ¡ jmÃ©no pÅispÄvatele.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Andere medewerkers</Attribute>
+            <Attribute name="definition">Een persoon of organisatie die een belangrijke bijdrage heeft geleverd, maar die secondair is aan de persoon of organisatie die bij &quot;Creator&quot; genoemd wordt. Gedacht kan worden aan editors, vertalers en illustrators.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Contribuente</Attribute>
+            <Attribute name="definition">Un entitate responsabile pro facer contributiones al contento del ressource.</Attribute>
+            <Attribute name="comment">Exemplos de contribuente include un persona, un organization, o un servicio. Typicamente se utiliza un nomine de contribuente pro indicar le entitate.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label"> à€žà€¹à€¯à¥à€à€, à€žà€¹à€¯à¥à€à¥, à€žà€¹à€Ÿà€¯à¥à€¯à€</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à€Ÿ à€žà€à€à€²à¥à€€ à€à€°à€£à¥à¥à€Ÿà€ž  à€®à€Šà€€ à€à€°à€£à€Ÿà€°à¥ à€µà¥à€¯à€à¥à€€à¥</Attribute>
+            <Attribute name="comment">à€à€Šà€Ÿ.à€ à€µà¥à€¯à€à¥à€€à¥, à€žà¥à€µà€Ÿ, à€žà€à€žà¥à€¥à€Ÿ</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Date">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Date</Attribute>
+            <Attribute name="definition">A date associated with an event in the life cycle of the resource.</Attribute>
+            <Attribute name="comment">Typically, Date will be associated with the creation or availability of the resource.  Recommended best practice for encoding the date value is defined in a profile of ISO 8601 and follows the YYYY-MM-DD format.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Ra</Attribute>
+            <Attribute name="definition">He ra e whai panga ana ki te huringa ora o te rauemi.</Attribute>
+            <Attribute name="comment">Ko te tikanga, ka whai panga te ra ki te hanganga, te wateatanga ranei, o te rauemi. Ko te huarahi tino pai hei tohu i te uara o te ra (date value) kua whakaritea i roto i te whakaritenga IS0 8601 [W3CDTF], a, e whai atu ana ki te whakatakotoranga YYYY-MM-DD.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Date</Attribute>
+            <Attribute name="definition">Une date associÃ©e avec un Ã©vÃ©nement dans le cycle de vie de la ressource.</Attribute>
+            <Attribute name="comment">Typiquement, une date sera associÃ©e Ã  la crÃ©ation ou Ã  la publication d&apos;une ressource. Il est fortement recommandÃ© d&apos;encoder la valeur de la date en utilisant le format dÃ©fini par l&apos;ISO 8601 [W3CDTF] sous la forme AAAA-MM-JJ.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÐ°ÑÐ°</Attribute>
+            <Attribute name="definition">ÐÐ°ÑÐ°, ÑÐ²ÑÐ·Ð°ÐœÐœÐ°Ñ Ñ ÑÐŸÐ±ÑÑÐžÐµÐŒ Ð² Ð¶ÐžÐ·ÐœÐµÐœÐœÐŸÐŒ ÑÐžÐºÐ»Ðµ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÐ±ÑÑÐœÐŸ ÐÐ°ÑÐ° Ð°ÑÑÐŸÑÐžÐžÑÑÐµÑÑÑ Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµÐŒ ÐžÐ»Ðž ÐŽÐŸÑÑÑÐ¿ÐœÐŸÑÑÑÑ ÑÐµÑÑÑÑÐ°. ÐÐ° Ð¿ÑÐ°ÐºÑÐžÐºÐµ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ ÐŽÐ»Ñ ÐºÐŸÐŽÐžÑÐŸÐ²ÐºÐž Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŽÐ°ÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÐµ Ð¿ÑÐŸÑÐžÐ»Ñ ISO 8601 (Ð€ÐŸÑÐŒÐ°ÑÑ ÐŽÐ°ÑÑ Ðž Ð²ÑÐµÐŒÐµÐœÐž W3C), ÐºÐŸÑÐŸÑÐŸÐµ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÐµÑ ÑÐŸÑÐŒÐ°Ñ ÐÐÐÐ-ÐÐ-ÐÐ.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Fecha</Attribute>
+            <Attribute name="definition">Una fecha en la que el recurso se puso a disposiciÃ³n del usuario en su forma actual. Esta fecha no ha de confundirse con la que pertenece al elemento Coverage, que serÃ­a asociada con el recurso sÃ³lo en la medida en que el contenido intelectual estÃ¡ de algÃºn modo relacionado con esa fecha. Recomendamos la utiliazaciÃ³n de uno de los formatos definidos en el documento &quot;Date and Time Formats&quot;, http://www.w3.org/TR/NOTE-datetime basado en la norma ISO 8601 que incluye, entre otras, fechas en el formato AAAA y AAAA-MM-DD. De esta forma la fecha 1994-11-05 corresponderÃ­a al 5 de Noviembre de 1994.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙØªØ§Ø±Ø®</Attribute>
+            <Attribute name="definition">ÙÙ Ø§ÙØªØ§Ø±ÙØ® Ø§ÙÙ
+ØªØ¹ÙÙ ØšÙÙØª ÙØŽØŠ Ø£Ù ØªÙÙØ± Ø§ÙÙ
+ØµØ¯Ø± . Ù ÙØ¬Øš Ø£Ù ÙØ§ ÙØ®ÙØ· ÙØ°Ø§ Ø§ÙØªØ§Ø±ÙØ® Ø§ÙØ¹Ø§ØŠØ¯ ÙØ¹Ø§Ù
+Ù Ø§ÙØªØºØ·ÙØ© , Ù Ø§ÙØ° Ù ÙØ¬Øš Ø£Ù    ÙÙØ­Ù ØšØ§ÙÙ
+ØµØ¯Ø± ÙÙØ· Ù
+Ù ÙØ§Ø­ÙØ© Ø§ÙÙ
+Ø­ØªÙÙØ§ÙÙÙØ±Ù ÙÙÙÙÙ ÙÙØ¹Ø§ Ù
+Ø§ ÙÙ ÙØ°Ø§ Ø§ÙØªØ§Ø±ÙØ®. Ø§ÙØµÙØºØ© Ø§ÙÙ
+Ø³Ø«Ø­Ø³ÙØ© ÙÙØ§Ø­Ø³Ù Ø§ÙÙ
+ØªØ¹Ø§Ø±Ù Ø¹ÙÙÙ    Ø¹ÙØ¯ Ø§ÙØªØ·ØšÙÙ ÙÙ Ø§ÙØµÙØºØ© Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø© ÙÙ ØªØŽÙÙÙ (ISO 8601) ØµÙØºØ© ØªØ§Ø±ÙØ® Ø§ÙÙÙÙ
+ Ù Ø§ÙÙÙØª ) Ø§Ø¹ØªÙ
+Ø§Ø¯Ø§ Ø¹ÙÙ (ISO 8601) Ø§ÙÙ
+ÙØ§Ø­ØžØ© Ø§ÙÙÙÙØ© http://www.w3.org/TR/NOTE-datetime, W3C. ÙÙÙ    ÙØ°Ø§ Ø§ÙÙØ³Ù , Ù
+Ø«ÙØ§, ØªØ§Ø±ÙØ® Ø§ÙÙÙÙ
+ 1994-11-04 ÙÙØ§ØžØ± ÙÙÙ
+ 5 ÙÙÙÙ
+ØšØ± 1994</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">æ¥æ</Attribute>
+            <Attribute name="definition">äžèµæºçåœåšæäž­çäžäžªäºä»¶çžå
+³çæ¶éŽã</Attribute>
+            <Attribute name="comment">äžè¬èèšïŒæ¥æåºäžèµæºçåå»ºæåºçæ¥æçžå
+³ãå»ºè®®éçšçæ¥ææ ŒåŒåºç¬ŠåISO 8601 [W3CDTF]è§    èïŒå¹¶äœ¿çšYYYY-MM-DDçæ ŒåŒã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">Datum</Attribute>
+            <Attribute name="definition">Datum spojenÃ© s urÄitou udÃ¡lostÃ­ bÄhem existence zdroje.</Attribute>
+            <Attribute name="comment">Datum bude typicky spojeno s vytvoÅenÃ­m nebo zpÅÃ­stupnÄnÃ­m zdroje. DoporuÄenÃœ postup pro kÃ³dovÃ¡nÃ­ hodnoty data je definovÃ¡n v ISO 8601 [W3CDTF]: formÃ¡t RRRR-MM-DD.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Datum</Attribute>
+            <Attribute name="definition">De datum van de totstandkoming of beschikbaarstelling van een Internetbron. Deze datum moet niet verward worden met de datum in &quot;Coverage&quot;. De datum in &quot;Coverage&quot; geeft de tijdsperiode van de inhoud van de Internetbron aan. Voorgeschreven wordt de ISO 8601 standaard voor datum, zoals beschreven in W3C Technical Note http://www.w3.org/TR/NOTE-datetime. Hierin wordt het formaat YYYY-MM-DD beschreven. Het formaat YYYY-MM-DD wordt de voorgeschreven standaard. 3 September 1998 wordt in dit geval 1998-09-03.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Data</Attribute>
+            <Attribute name="definition">Un data associate a un evento in le cyclo vital del ressource.</Attribute>
+            <Attribute name="comment">Typicamente le data es associate al creation o disponibilization del ressource. Le practica recommendate pro codificar le valor del datas es definite in un profilo de ISO 8601 [W3CDTF] e seque le formato AAAA-MM-DD.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€€à€Ÿà€°à¥à€,  à€Šà€¿à€šà€Ÿà€à€</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à€Ÿ à€€à€¯à€Ÿà€° à€à¥à€²à¥à€¯à€Ÿà€à¥ à€€à€Ÿà€°à¥à€</Attribute>
+            <Attribute name="comment">à€€à€Ÿà€°à¥à€  à€²à€¿à€¹à¥à€£à¥à€¯à€Ÿà€à¥ à€žà¥à€µà€°à¥à€ª à€ à€µà€°à¥à€·. à€®à€¹à€¿à€šà€Ÿ. à€Šà€¿à€µà€ž à¥§à¥¯à¥«à¥Š. à¥Šà¥ª. à¥Šà¥ª</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Type">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Resource Type</Attribute>
+            <Attribute name="definition">The nature or genre of the content of the resource.</Attribute>
+            <Attribute name="comment">Type includes terms describing general categories, functions, genres, or aggregation levels for content. Recommended best practice is to select a value from a controlled vocabulary (for example, the working draft list of Dublin Core Types). To describe the physical or digital manifestation of the resource, use the FORMAT element.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Tumomo</Attribute>
+            <Attribute name="definition">Te ahua, te tu-ahuatanga ranei o nga kaupapa o te rauemi.</Attribute>
+            <Attribute name="comment">Kei roto i te Tumomo nga kupu whakaatu i nga wehewehenga whanui, nga aheinga, nga tu-ahuatanga, te whakaritenga ranei o nga taumata o te/ nga kaupapa. Ko te huarahi tino pai kua tohua, ko te tipako i tetahi uara mai i nga kupu kua whakaritea (hei tauira, ko te tauira rarangi e whakamahia ana o nga Dublin Core Types [DCT1]. Hei whakaatu i te whakatinanatanga o te rauemi, whakamahia ko te huanga WHAKATAKOTORANGA (FORMAT).</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Type</Attribute>
+            <Attribute name="definition">La nature ou le genre du contenu de la ressource.</Attribute>
+            <Attribute name="comment">Type inclut des termes dÃ©crivant des catÃ©gories, fonctions ou genres gÃ©nÃ©raux pour le contenu, ou des niveaux d&apos;agrÃ©gation. Il est recommandÃ© de choisir la valeur du type dans une liste de vocabulaire contrÃŽlÃ© (par exemple, la liste provisoire de Types du Dublin Core[DCT1]). Pour dÃ©crire la matÃ©rialisation physique ou digitale de la ressource, il faut utiliser l&apos;Ã©lÃ©ment Format.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">Ð¢ÐžÐ¿ ÑÐµÑÑÑÑÐ°</Attribute>
+            <Attribute name="definition">ÐÑÐžÑÐŸÐŽÐ° ÐžÐ»Ðž Ð¶Ð°ÐœÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">Ð¢ÐžÐ¿ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÑÐµÑÐŒÐžÐœÑ, ÐŸÐ¿ÐžÑÑÐ²Ð°ÑÑÐžÐµ ÐŸÐ±ÑÐžÐµ ÐºÐ°ÑÐµÐ³ÐŸÑÐžÐž, ÑÑÐœÐºÑÐžÐž, Ð¶Ð°ÐœÑÑ ÐžÐ»Ðž ÐŸÐ±ÑÐµÐŽÐžÐœÐµÐœÐœÑÐµ ÑÑÐŸÐ²ÐœÐž ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ. ÐÐ»Ñ Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ Ð²ÑÐ±ÐžÑÐ°ÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐžÐ· ÐºÐŸÐœÑÑÐŸÐ»ÐžÑÑÐµÐŒÐŸÐ³ÐŸ ÑÐ»ÐŸÐ²Ð°ÑÑ (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÑÐ°Ð±ÐŸÑÐµÐ³ÐŸ Ð¿ÑÐŸÐµÐºÑÐ° ÑÐ¿ÐžÑÐºÐ° Ð¢ÐžÐ¿ÐŸÐ² Dublin Core DCT1). ÐÐ»Ñ ÐŸÐ¿ÐžÑÐ°ÐœÐžÑ ÑÐžÐ·ÐžÑÐµÑ-ÐºÐŸÐ³ÐŸ ÐžÐ»Ðž ÑÐžÑÑÐŸÐ²ÐŸÐ³ÐŸ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ ÑÐµÑÑÑÑÐ° ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÑÐ»ÐµÐŒÐµÐœÑ Ð€ÐŸÑÐŒÐ°Ñ.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Tipo del Recurso</Attribute>
+            <Attribute name="definition">La categorÃ­a del recurso, por ejemplo pÃ¡gina personal, romance, poema, minuta, diccionario. Para asegurar la interoperabilidad, Type deberÃ­a ser seleccionado de entre una lista de valores que actualmente se encuentra bajo desarrollo en un grupo de trabajo. En http://sunsite.berkeley.edu/Metadata/types.html se puede consultar el estado actual de la discusiÃ³n en torno a este tema.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">ÙÙØ¹ Ø§ÙÙ
+ØµØ¯Ø±</Attribute>
+            <Attribute name="definition">ÙÙ ÙØŠØ© Ø§ÙÙ
+ØµØ¯Ø± , Ù
+Ø«ÙØ§ Ø§ÙØµÙØ­Ø© Ø§ÙØ§Ù
+, Ø±ÙØ§ÙØ© , ÙØ·Ø¹Ø© ØŽØ¹Ø±ÙØ© , ÙØ±ÙØ© Ø¹Ù
+Ù , ØªÙØ±ÙØ± ÙÙÙ , Ù
+ÙØ§Ù , ÙØ§Ù
+ÙØ³ . Ù Ù
+Ù Ø£Ø¬Ù Ø§ÙØªØ¹Ø§Ù
+Ù Ø§ÙÙ
+ØŽØªØ±Ù    ÙØ¬Øš Ø£Ù ÙØ®ØªØ§Ø± Ø§ÙÙÙØ¹ Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+Ø±ÙÙ
+Ø© ÙØ§ÙØªÙ ÙÙÙ
+ Ø§Ø¹Ø¯Ø§Ø¯ÙØ§ Ø­Ø§ÙÙØ§ Ø¶Ù
+Ù Ø­ÙÙØ§Øª ÙØ±ØŽØ© Ø¹Ù
+Ù</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">èµæºç±»å</Attribute>
+            <Attribute name="definition">èµæºå
+å®¹çç¹åŸæç±»åã</Attribute>
+            <Attribute name="comment">èµæºç±»åå
+æ¬æè¿°èµæºå
+å®¹çäžè¬èçŽïŒåèœïŒç§å±ïŒæèç±»å±æ¬¡çæ¯è¯­ãå»ºè®®éçšæ¥èªäºåæ§è¯è¡š    äž­çåŒïŒäŸåŠDCMIç±»åè¯æ±è¡š[DCMITYPE]ïŒãèŠæè¿°èµæºçç©çææ°å­åè¡šç°åœ¢åŒïŒè¯·äœ¿çšâæ ŒåŒïŒFORMATïŒâå
+çŽ ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">Typ zdroje</Attribute>
+            <Attribute name="definition">Povaha nebo druh obsahu zdroje.</Attribute>
+            <Attribute name="comment">Typ obsahuje termÃ­ny popisujÃ­cÃ­ obecnÃ© kategorie, funkce, druhy nebo agregaÄnÃ­ ÃºrovnÄ obsahu. DoporuÄuje se vybÃ­rat hodnotu z ÅÃ­zenÃ©ho slovnÃ­ku (napÅ. pracovnÃ­ nÃ¡vrh seznamu TypÅ¯ Dublin Core [DCT1]). K popisu fyzickÃ© nebo digitÃ¡lnÃ­ reprezentace zdroje uÅŸijte prvek FormÃ¡t.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Bestands type</Attribute>
+            <Attribute name="definition">Het soort Internetbron, bijvoorbeeld home page, gedicht, working paper, technical report, essay, woordenboek etc. De DC working groups zijn momenteel bezig met twee voorstellen; een minimalist draft: http://sunsite.berkeley.edu/Metadata/minimalist.html en een structuralist draft: http://sunsite.berkely.edu/Metadata/structuralist.html. Het wordt sterk aanbevolen om &quot;Type&quot; van deze lijsten te selecteren.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Typo del ressource</Attribute>
+            <Attribute name="definition">Le natura o genere del contento del ressource.</Attribute>
+            <Attribute name="comment">Le typo del ressource include terminos que describe categorias general, functiones, generes, o nivellos de aggregation pro le contento. Le practica recommendate es selectionar un valor a partir de un vocabulario controlate (per exemplo, le lista de schizzos de travalio de typos de Dublin Core [DCT1]). Pro describer le manifestation physic o digital del ressource, utiliza le elemento Formato.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€ªà¥à€°à€à€Ÿà€°</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à€Ÿà€ªà¥à€°à€à€Ÿà€°</Attribute>
+            <Attribute name="comment">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à¥ à€µà€°à¥à€à¥à€à€°à€£, à€µà€°à¥à€à€µà€Ÿà€°à¥à€®à€§à¥à€¯à¥ à€à€à€Ÿà€Šà¥à€¯à€Ÿ à€šà¥à€à€Šà¥à€à€Ÿ à€®à¥à€à¥à€¯ à€à€à€ªà¥à€°à€à€Ÿà€°</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Format">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Format</Attribute>
+            <Attribute name="definition">The physical or digital manifestation of the resource.</Attribute>
+            <Attribute name="comment">Typically, Format may include the media-type or dimensions of the resource. Format may be used to determine the software, hardware or other equipment needed to display or operate the resource. Examples of dimensions include size and duration. Recommended best practice is to select a value from a controlled vocabulary (for example, the list of Internet Media Types [MIME] defining computer media formats).</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Whakatakotoranga</Attribute>
+            <Attribute name="definition">Te whakatinanatanga, te whakaputanga a-mati o te rauemi.</Attribute>
+            <Attribute name="comment">Ko te tikanga, ka taea te Whakatakotoranga te whakamahi hei whakarite i te rawa-ngohe (software), te rawa-maro (hardware), ma etahi taputapu ranei me matua whiwhi, hei whakahaere i te rauemi. Ko te rahi me te roanga etahi tauira hanga. Ko te tino huarahi kua tohua ko te tipako uara mai i tetahi whakaritenga kupu (hei tauira, te rarangi o nga Tumomo Papaho Ipurangi (Internet Media Types [MIME]) e whakaatu ana i nga whakatakotoranga papaho rorohiko.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Format</Attribute>
+            <Attribute name="definition">La matÃ©rialisation physique ou digitale de la ressource.</Attribute>
+            <Attribute name="comment">Typiquement, Format peut inclure le media ou les dimensions de la ressource. Format peut Ãªtre utilisÃ© pour prÃ©ciser le logiciel, le matÃ©riel ou autre Ã©quipement nÃ©cessaire pour afficher ou faire fonctionner la ressource. Exemples de dimensions incluent la taille et la durÃ©e. Il est recommandÃ© de choisir la valeur du format dans une liste de vocabulaire contrÃŽlÃ©(par exemple, la liste des types de media dÃ©finis sur Internet [MIME]).</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">Ð€ÐŸÑÐŒÐ°Ñ</Attribute>
+            <Attribute name="definition">Ð€ÐžÐ·ÐžÑÐµÑÐºÐŸÐµ ÐžÐ»Ðž ÑÐžÑÑÐŸÐ²ÐŸÐµ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÐ±ÑÑÐœÐŸ Ð€ÐŸÑÐŒÐ°Ñ ÐŒÐŸÐ¶ÐµÑ Ð²ÐºÐ»ÑÑÐ°ÑÑ ÑÐžÐ¿ Ð°ÑÐŽÐžÐŸÐ²ÐžÐ·ÑÐ°Ð»ÑÐœÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž (ÐŒÐµÐŽÐžÐ°-ÑÐžÐ¿) ÐžÐ»Ðž Ð²ÐµÐ»ÐžÑÐžÐœÑ ÑÐµÑÑÑÑÐ°. Ð€ÐŸÑÐŒÐ°Ñ ÐŒÐŸÐ¶ÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ ÐŽÐ»Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ Ð°Ð¿Ð¿Ð°ÑÐ°ÑÐœÐŸÐ³ÐŸ, Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐ³ÐŸ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÑ ÐžÐ»Ðž ÐŽÑÑÐ³ÐŸÐ³ÐŸ ÐŸÐ±ÐŸÑÑÐŽÐŸÐ²Ð°ÐœÐžÑ, ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÐ³ÐŸ ÐŽÐ»Ñ Ð²ÐŸÑÐ¿ÑÐŸÐžÐ·Ð²ÐµÐŽÐµÐœÐžÑ ÐžÐ»Ðž ÑÐ°Ð±ÐŸÑÑ Ñ ÑÐµÑÑÑÑÐŸÐŒ. ÐÑÐžÐŒÐµÑÑ Ð²ÐµÐ»ÐžÑÐžÐœÑ Ð²ÐºÐ»ÑÑÐ°ÑÑ ÑÐ°Ð·ÐŒÐµÑ Ðž Ð¿ÑÐŸÐŽÐŸÐ»Ð¶ÐžÑÐµÐ»ÑÐœÐŸÑÑÑ. ÐÐ»Ñ Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ Ð²ÑÐ±ÐžÑÐ°ÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐžÐ· ÐºÐŸÐœÑÑÐŸÐ»ÐžÑÑÐµÐŒÐŸÐ³ÐŸ ÑÐ»ÐŸÐ²Ð°ÑÑ (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÑÐ¿ÐžÑÐºÐ° ÐÐµÐŽÐžÐ°-ÑÐžÐ¿ÐŸÐ² ÐÐœÑÐµÑÐœÐµÑ MIME, ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑÐµÐ³ÐŸ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐœÑÐµ ÑÐŸÑÐŒÐ°ÑÑ Ð°ÑÐŽÐžÐŸÐ²ÐžÐ·ÑÐ°Ð»ÑÐœÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž).</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Formato</Attribute>
+            <Attribute name="definition">El formato de datos de un recurso, usado para identificar el software y posiblemente, el hardware que se necesitarÃ­a para mostrar el recurso. Para asegurar la interoperabilidad, los valores de Format deberÃ­an ser seleccionados de entre una lista de valores que actualmente se encuentra bajo desarrollo en un grupo de trabajo.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙØµÙØºØ©</Attribute>
+            <Attribute name="definition">ÙØ°Ù ØµÙØºØ© Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø© Ø§ÙØ®Ø§ØµØ© ØšØ§ÙÙ
+ØµØ¯Ø± , Ù ØªØ³ØªØ®Ø¯Ù
+ ÙÙØªØ¹Ø±ÙÙ ØšØ§ÙØšØ±Ù
+Ø¬ÙØ§Øª ÙØ±ØšÙ
+Ø§ Ø§ÙØµÙØš ÙÙØ­Ø§Ø³ÙØš Ù Ø§ÙØªÙ ÙÙ
+ÙÙ Ø£Ù ÙØ­ØªØ§Ø¬    ÙÙØ§ ÙØ¹Ø±Ø¶ Ø£Ù ØªØŽØºÙÙ Ø§ÙÙ
+ØµØ¯Ø± . Ù
+Ù Ø£Ø¬Ù Ø§ÙØªØ¹Ø§Ù
+Ù Ø§ÙÙ
+ØŽØªØ±Ù, ÙØ¬Øš Ø£Ù ØªØ®ØªØ§Ø± Ø§ÙØµÙØºØ© Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+Ø±ÙÙ
+Ø© Ù Ø§ÙØªÙ ÙØªÙ
+ Ø§Ø¹Ø¯Ø§Ø¯ÙØ§    Ø­Ø§ÙÙØ§ Ø¶Ù
+Ù Ø­ÙÙØ§Øª ÙØ±ØŽØ© Ø¹Ù
+Ù</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">æ ŒåŒ</Attribute>
+            <Attribute name="definition">èµæºçç©çææ°å­è¡šç°åœ¢åŒã</Attribute>
+            <Attribute name="comment">äžè¬èèšïŒæ ŒåŒå¯èœå
+æ¬èµæºçåªäœç±»åæèµæºçå€§å°ïŒæ ŒåŒå
+çŽ å¯ä»¥çšæ¥å³å®å±ç€ºææäœèµæºæé    çèœ¯ç¡¬ä»¶æå
+¶ä»çžåºè®Ÿå€ïŒäŸåŠå€§å°å
+æ¬èµæºæå çå­åšç©ºéŽåæç»­æ¶éŽãå»ºè®®éçšæ¥èªäºåæ§è¯è¡š    äž­çåŒïŒïŒäŸåŠInternetåªäœç±»å[MIME]å®ä¹è®¡ç®æºåªäœæ ŒåŒïŒã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">FormÃ¡t</Attribute>
+            <Attribute name="definition">FyzickÃ¡ nebo digitÃ¡lnÃ­ reprezentace zdroje.</Attribute>
+            <Attribute name="comment">Typicky mÅ¯ÅŸe FormÃ¡t obsahovat typ mÃ©dia nebo rozmÄry zdroje. FormÃ¡t lze pouÅŸÃ­vat k urÄenÃ­ softwaru, hardwaru nebo dalÅ¡Ã­ho zaÅÃ­zenÃ­ potÅebnÃ©ho k zobrazenÃ­ nebo k manipulaci se zdrojem. PÅÃ­klady rozmÄrÅ¯ zahrnujÃ­ velikost a dobu trvÃ¡nÃ­. DoporuÄuje se vybÃ­rat hodnotu z ÅÃ­zenÃ©ho slovnÃ­ku (napÅ. seznam typÅ¯ internetovÃœch mÃ©diÃ­ [MIME] definujÃ­cÃ­ formÃ¡ty poÄÃ­taÄovÃœch mÃ©diÃ­).</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Format</Attribute>
+            <Attribute name="definition">Het data formaat van het Internetbestand. Dit gegeven kan gebruikt worden om systeemvereisten (hard- en software) te identificeren die nodig zijn voor raadpleging of bediening van de Internetbron. &quot;Format&quot; is nog in ontwikkeling bij de DC workshop. Uit compatibiliteitsoverwegingen wordt aanbevolen formaatgegevens te selecteren uit een gecontroleerde lijst. Formaten kunnen van de Internet Media Types (MIME types) lijst gekozen worden: http://www.isi.edu/in-notes/iana/assignments/media-types/media-types</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Formato</Attribute>
+            <Attribute name="definition">Le manifestation physic o digital del ressource.</Attribute>
+            <Attribute name="comment">Typicamente le formato pote includer le typo de medio o dimensiones del ressource. Le formato pote esser utilizate pro determinar le software o le equipamento necessari pro exhibir o operar le ressource. Exemplos de dimensiones include grandessa e duration. Le practica recommendate es selectionar un valor de un vocabulario controlate (per exemplo, le lista de typos de medios de Internet [MIME] que defini formatos de medios).</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€°à€à€šà€Ÿ</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à¥ à€°à€à€šà€Ÿ, à€šà€®à¥à€šà€Ÿà€¬à¥à€Š à€°à€à€šà€Ÿ</Attribute>
+            <Attribute name="comment">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à¥ à€žà¥à€µà€°à¥à€ª, à€°à€à€šà€Ÿà€à€Šà€Ÿ. à€€à¥à€¯à€Ÿà€à¥ à€°à¥à€ª à€à€žà¥ à€ªà¥à€žà¥à€€à€à€°à¥à€ª, à€žà€à€à€£à€à¥à€¯ à€°à¥à€ª, à€µà€¿à€Šà¥à€¯à¥à€€ à€ªà€°à€®à€Ÿà€£à¥à€à€à¥à€¯à€Ÿ à€žà€¹à€Ÿà€¯à¥à€¯à€Ÿà€šà¥ à€žà€à€à€£à€à¥à€à¥à€€ à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à€Ÿ</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Identifier">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Resource Identifier</Attribute>
+            <Attribute name="definition">An unambiguous reference to the resource within a given context.</Attribute>
+            <Attribute name="comment">Recommended best practice is to identify the resource by means of a string or number conforming to a formal identification system. Example formal identification systems include the Uniform Resource Identifier (URI) (including the Uniform Resource Locator (URL)), the Digital Object Identifier (DOI) and the International Standard Book Number (ISBN).</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Taututanga</Attribute>
+            <Attribute name="definition">He tohutoro e hangai ana ki te rauemi i roto i tetahi horopaki.</Attribute>
+            <Attribute name="comment">Ko te tino huarahi kua tohua, ko te tautu i te rauemi ma tetahi aho (string), tau ranei, e hangai ana ki tetahi punaha taututanga okawa. Ko etahi punaha taututanga okawa ko te Taututanga Rauemi Orite (Uniform Resource Identifier - URI), te Taututanga Rauemi Tohu-wahi (Uniform Resource Locator - URL), Te Mea A-mati (Digital Object Identifier - DOI) me te Tau Pukapuka Aro Whanui o te Ao (International Standard Book Number - ISBN).</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Identifiant</Attribute>
+            <Attribute name="definition">Une rÃ©fÃ©rence non ambiguÃ« Ã  la ressource dans un contexte donnÃ©</Attribute>
+            <Attribute name="comment">Il est recommandÃ© d&apos;identifier la ressource par une chaÃ®ne de caractÃšre ou un nombre conforme Ã  un sytÃšme formel d&apos;identification. Exemples de systemes formels d&apos;identification incluent le &quot;Uniform Resource Identifier&quot; (URI) (qui inclut le &quot;Uniform Resource Locator&quot; (URL)), le &quot;Digital Object Identifier&quot;(DOI) et le &quot;International Standard Book Number&quot;(ISBN).</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑ ÑÐµÑÑÑÑÐ°</Attribute>
+            <Attribute name="definition">ÐÐŽÐœÐŸÐ·ÐœÐ°ÑÐœÐ°Ñ ÑÑÑÐ»ÐºÐ° ÐœÐ° ÑÐµÑÑÑÑ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ ÐŽÐ°ÐœÐœÐŸÐ³ÐŸ ÐºÐŸÐœÑÐµÐºÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÐ»Ñ Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ ÐžÐŽÐµÐœÑÐžÑÐžÑÐžÑÐŸÐ²Ð°ÑÑ ÑÐµÑÑÑÑ Ð¿ÐŸÑÑÐµÐŽÑÑÐ²ÐŸÐŒ ÑÑÑÐŸÐºÐž ÐžÐ»Ðž ÑÐžÑÐ»Ð°, ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐ³ÐŸ ÑÐŸÑÐŒÐ°Ð»ÑÐœÐŸÐ¹ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÑÐžÑÑÐµÐŒÐµ. ÐÑÐžÐŒÐµÑÑ ÑÐŸÑÐŒÐ°Ð»ÑÐœÑÑ
+ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÐŸÐœÐœÑÑ
+ ÑÐžÑÑÐµÐŒ Ð²ÐºÐ»ÑÑÐ°ÑÑ Ð£ÐœÐžÑÐžÑÐžÑÐŸÐ²Ð°ÐœÐœÑÐ¹ ÐÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑ Ð ÐµÑÑÑÑÐ° (URI), (Ð²ÐºÐ»ÑÑÐ°Ñ Ð£ÐœÐžÑÐžÑÐžÑÐŸÐ²Ð°ÐœÐœÑÑÐ¹ ÐÐŸÐºÐ°ÑÐŸÑ Ð ÐµÑÑÑÑÐ° URL), ÐÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑ ÐŠÐžÑÑÐŸÐ²ÐŸÐ³ÐŸ ÐÐ±ÑÐµÐºÑÐ° (DOI) Ðž ÐÐµÐ¶ÐŽÑÐœÐ°ÑÐŸÐŽÐœÑÐ¹ Ð¡ÑÐ°ÐœÐŽÐ°ÑÑÐœÑÐ¹ ÐÐœÐžÐ¶ÐœÑÐ¹ ÐÐŸÐŒÐµÑ (ISBN).</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Identificador del Recurso</Attribute>
+            <Attribute name="definition">Secuencia de caracteres usados para identificar unÃ­vocamente un recurso. Ejemplos para recursos en lÃ­nea pueden ser URLs y URNs (cuando estÃ©n implementados). Para otros recursos pueden ser usados otros formatos de identificadores, como por ejemplo ISBN (&quot;International Standard Book Number&quot; - NÃºmero Internacional Normalizado para Libros)</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ù
+Ø¹Ø±Ù Ø§ÙÙ
+ØµØ¯Ø±</Attribute>
+            <Attribute name="definition">ÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø© Ø­Ø±ÙÙØ© Ø£Ù Ø±ÙÙ
+ ÙØ³ØªØ®Ø¯Ù
+ ÙØªØ¹Ø±ÙÙ Ø§ÙÙ
+ØµØ¯Ø± Ø§Ø­Ø¯ÙØ§ : Ø§ÙØ§Ù
+Ø«ÙØ© ÙØ°Ø§ÙÙ ÙÙ Ø§ÙÙ
+ØµØ§Ø¯Ø± Ø§ÙØŽØšÙÙØ©ØªØ¶Ù
+ ) URNs, URLs Ø¹ÙØ¯ ØšÙØ§ØŠÙØ§ (    ÙØ°ÙÙ ÙÙ
+ÙÙ Ø§Ø¹ØªØšØ§Ø± Ø§ÙÙ
+Ø¹Ø±ÙØ§Øª Ø§ÙØ¹Ø§ÙÙ
+ÙØ© Ø§ÙØ§Ø­Ø§Ø¯ÙØ© Ù
+Ø«Ù Ø§ÙØ±ÙÙ
+ Ø§ÙØ¯ÙÙÙ ÙØªØµÙÙÙ Ø§ÙÙØ§ØªØš (ISBN) Ù
+Ø±ØŽØ­Ø© ÙÙØ°Ø§ Ø§ÙØ¹Ø§Ù
+Ù</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">èµæºæ è¯ç¬Š</Attribute>
+            <Attribute name="definition">åšç¹å®çèåŽå
+ç»äºèµæºçäžäžªæç¡®çæ è¯ã</Attribute>
+            <Attribute name="comment">å»ºè®®å¯¹èµæºçæ è¯éçšç¬Šåæäžæ­£åŒæ è¯äœç³»çå­ç¬Šäž²åæ°å­ç»åãäŸåŠæ­£åŒçæ è¯äœç³»å
+æ¬ç»äžèµ    æºæ è¯ç¬Š(URI) (å
+æ¬åäžèµæºå®äœç¬ŠURL)ãæ°å­å¯¹è±¡æ è¯ç¬Š(DOI)ååœé
+æ åä¹Šå·(ISBN)ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">IdentifikÃ¡tor zdroje</Attribute>
+            <Attribute name="definition">JednoznaÄnÃœ odkaz na zdroj v rÃ¡mci danÃ©ho kontextu.</Attribute>
+            <Attribute name="comment">DoporuÄuje se identifikovat zdroj znakovÃœm ÅetÄzcem nebo ÄÃ­slem odpovÃ­dajÃ­cÃ­m nÄkterÃ©mu z formÃ¡lnÃ­ch identifikaÄnÃ­ch systÃ©mÅ¯. PÅÃ­klady formÃ¡lnÃ­ch identifikaÄnÃ­ch systÃ©mÅ¯ zahrnujÃ­ Uniform Resource Identifier (URI) (vÄetnÄ Uniform Resource Locator (URL)), Digital Object Identifier (DOI) a MezinÃ¡rodnÃ­ standardnÃ­ ÄÃ­slo knihy (ISBN).</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Bestandsidentificatie</Attribute>
+            <Attribute name="definition">Een unieke string of nummer ter identificatie van de Internetbron. Voorbeelden zijn URL&apos;s of URN&apos;s Andere voorbeelden zijn International Standard Book Number (ISBN) of International Standard Serial Number (ISSN)</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Identificator del ressource</Attribute>
+            <Attribute name="definition">Un referentia inambigue al ressource intra un date contexto.</Attribute>
+            <Attribute name="comment">Se recommenda identificar le ressource per medio de un catena de characteres o numero conforme a un systema formal de identification. Exemplos de systemas formal de identification include le Uniform Resource Identifier (URI) (includente le Uniform Resource Locator (URL)), le Digital Object Identifier (DOI) e le International Standard Book Number (ISBN).</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€à€³à€</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à€Ÿ à€à€ à€
+à€°à¥à€¥à¥ à€žà€à€Šà€°à¥à€­</Attribute>
+            <Attribute name="comment">à€à€Šà€Ÿ. à€®à€Ÿà€¹à€¿à€€à¥à€à€Ÿà€³à¥à€¯à€Ÿà€µà€°à¥à€² à€ªà€€à¥à€€à€Ÿ, à€µà€¿à€¶à€¿à€·à¥à€  à€žà¥à€¥à€³,  à€ªà¥à€žà¥à€€à€à€Ÿà€à€Ÿ à€à€à€€à€°à€°à€Ÿà€·à¥à€à¥à€°à¥à€¯  à€®à€Ÿà€šà€ à€à¥à€°à€®à€Ÿà€à€,  à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à¥ à€à€³à€ à€ªà€à€µà€¿à€£à€Ÿà€°à€Ÿ à€à€à€à€°à€šà¥à€ à€µà€°à¥à€² à€ªà€€à¥à€€à€Ÿ</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Source">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Source</Attribute>
+            <Attribute name="definition">A Reference to a resource from which the present resource is derived.</Attribute>
+            <Attribute name="comment">The present resource may be derived from the Source resource in whole or in part.  Recommended best practice is to reference the resource by means of a string or number conforming to a formal identification system.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Matapuna</Attribute>
+            <Attribute name="definition">He tohutoro ki tetahi rauemi koira te matapuna o te rauemi e tirohia ana.</Attribute>
+            <Attribute name="comment">Tera pea i puta te katoa, tetahi wahanga ranei o te rauemi, e tirohia ana, mai i te Matapuna rauemi. Ko te tino huarahi kua tohua ko te tohutoro ki te rauemi ma te aho, ma te tau ranei e hangai ana ki tetahi punaha taututanga okawa.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Source</Attribute>
+            <Attribute name="definition">Une rÃ©fÃ©rence Ã  une ressource Ã  partir de laquelle la ressource actuelle a Ã©tÃ© dÃ©rivÃ©e.</Attribute>
+            <Attribute name="comment">La ressource actuelle peut avoir Ã©tÃ© dÃ©rivÃ©e d&apos;une autre ressource source, en totalitÃ© ou en partie. Il est recommandÃ© de refÃ©rencer cette source par une chaÃ®ne de caractÃšre ou un nombre conforme Ã  un systÃšme formel d&apos;identification.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÑÑÐŸÑÐœÐžÐº</Attribute>
+            <Attribute name="definition">Ð¡ÑÑÐ»ÐºÐ° ÐœÐ° ÑÐµÑÑÑÑ, ÐžÐ· ÐºÐŸÑÐŸÑÐŸÐ³ÐŸ ÐžÐ·Ð²Ð»ÐµÑÐµÐœ ÐœÐ°ÑÑÐŸÑÑÐžÐ¹.</Attribute>
+            <Attribute name="comment">ÐÐ°ÑÑÐŸÑÑÐžÐ¹ ÑÐµÑÑÑÑ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐžÐ·Ð²Ð»ÐµÑÐµÐœ ÐžÐ· ÐÑÑÐŸÑÐœÐžÐºÐ° ÑÐµÐ»ÐžÐºÐŸÐŒ ÐžÐ»Ðž ÑÐ°ÑÑÐžÑÐœÐŸ. ÐÐ»Ñ Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ ÐžÐŽÐµÐœÑÐžÑÐžÑÐžÑÐŸÐ²Ð°ÑÑ ÑÐµÑÑÑÑ Ð¿ÐŸÑÑÐµÐŽÑÑÐ²ÐŸÐŒ ÑÑÑÐŸÐºÐž ÐžÐ»Ðž ÑÐžÑÐ»Ð°, ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐ³ÐŸ ÑÐŸÑÐŒÐ°Ð»ÑÐœÐŸÐ¹ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÑÐžÑÑÐµÐŒÐµ.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Fuente</Attribute>
+            <Attribute name="definition">Secuencia de caracteres utilizado para identificar unÃ­vocamente un trabajo a partir del cual proviene el recurso actual. Por ejemplo, es posible usar Source con la fecha de 1603 como descripciÃ³n de una pelÃ­cula basada en una obra de Shakespeare, pero es preferible, en ese caso, usar Relation &quot;IsBasedOn&quot; con una referencia a un recurso distinto cuya descripciÃ³n contenga el elemento Date con valor 1603.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙÙ
+ØµØ¯Ø±</Attribute>
+            <Attribute name="definition">Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª Ø§ÙØ®Ø§ØµØ© ØšÙ
+ØµØ¯Ø± Ø«Ø§ÙÙ Ù Ø§ÙØ°Ù Ø§Ø³ØªÙ
+Ø¯ Ù
+ÙÙ Ø§ÙÙ
+ØµØ¯Ø± Ø§ÙØ­Ø§ÙÙ. Ù
+Ø¹ Ø£ÙÙ Ù
+Ù Ø§ÙÙ
+ÙØµÙ ØšÙ Ø£Ù ØªÙØ¯Ù
+ Ø§ÙØ¹ÙØ§Ù
+Ù    Ù
+Ø¹ÙÙÙ
+Ø§Øª Ø¹Ù Ø§ÙÙ
+ØµØ¯Ø± Ø§ÙØ­Ø§ÙÙ ÙÙØ· , ÙÙÙ
+ÙÙ Ø£Ù ÙØ­ÙÙ ÙØ°Ø§ Ø§ÙØ¹Ø§Ù
+Ù Ø§ÙØªØ§Ø±ÙØ®, Ø§ÙÙ
+ÙØŽØŠ , Ø§ÙØµÙØºØ© , Ø§ÙÙ
+Ø¹Ø±Ù , Ø§Ù Ø§ÙØ© Ù
+ÙØ© - Ù
+Ø¹ÙÙÙ
+Ø§Øª Ø§Ø®Ø±Ù ÙÙÙ
+ØµØ¯Ø± Ø§ÙØ«Ø§ÙÙ Ø¹ÙØ¯Ù
+Ø§ ØªØ¹ØªØšØ± Ù
+ÙÙ
+Ø© ÙØ§ÙØªØŽØ§Ù Ø§ÙÙ
+ØµØ¯Ø± Ø§ÙØ­Ø§ÙÙ , Ù ÙØ°Ø§ÙÙ ÙÙØµÙ Ø¹ÙØ¯ Ø§ÙØªØ·ØšÙÙÙÙ Ø§Ø­Ø³Ù     Ø§ÙÙ
+ØªØ¹Ø§Ø±Ù Ø¹ÙÙÙ ØšØ§Ø³ØªØ®Ø¯Ø§Ù
+ Ø¹Ø§Ù
+Ù Ø§ÙØ¹ÙØ§ÙØ©</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">æ¥æº</Attribute>
+            <Attribute name="definition">ç°æèµæºæ¥æºçåç
+§ã</Attribute>
+            <Attribute name="comment">åœåèµæºå¯èœéšåæå
+šéšæºèªè¯¥å
+çŽ ææ è¯çèµæºïŒå»ºè®®å¯¹è¿äžèµæºçæ è¯éçšäžäžªç¬Šåæ­£åŒæ è¯ç³»    ç»çå­äž²åæ°å­ç»å ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">Zdroj</Attribute>
+            <Attribute name="definition">Odkaz na zdroj, z nÄhoÅŸ je popisovanÃœ zdroj odvozen.</Attribute>
+            <Attribute name="comment">PopisovanÃœ zdroj mÅ¯ÅŸe bÃœt zcela nebo zÄÃ¡sti odvozen ze zdroje uvedenÃ©ho v prvku Zdroj. DoporuÄuje se odkazovat zdroj znakovÃœm ÅetÄzcem nebo ÄÃ­slem odpovÃ­dajÃ­cÃ­m nÄkterÃ©mu z formÃ¡lnÃ­ch identifikaÄnÃ­ch systÃ©mÅ¯.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Bron</Attribute>
+            <Attribute name="definition">Informatie over een tweede bron waar de huidige Internetbron is van afgeleid. Bij &quot;Source&quot; mag een datum, auteur of maker, formaat, identificatie of andere metadata voor de tweede bron worden ingevuld. Voorbeeld: het is mogelijk om een &quot;Source&quot; datum 1603 in een omschrijving van een 1996 film bewerking van een Shakespeare stuk te gebruiken. &quot;Source&quot; is niet bruikbaar wanneer de huidige bron de orginele is.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Fonte</Attribute>
+            <Attribute name="definition">Un referentia a un ressource del qual se deriva le ressource presente.</Attribute>
+            <Attribute name="comment">Le ressource presente pote derivar se del ressource-fonte in toto o in parte. Le practica recommendate es facer referentia al ressource per medio de un catena de characteres o un numero conforme a un systema formal de identification.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€à€à€®</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€à€Ÿ à€à€à€® à€žà€Ÿà€à€à€£à€Ÿà€°à€Ÿ à€à€à€
+à€°à¥à€¥à¥ à€žà€à€Šà€°à¥à€­</Attribute>
+            <Attribute name="comment">à€à€Šà€Ÿ. à€ªà¥à€žà¥à€€à€, à€®à€Ÿà€žà€¿à€,  à€®à€Ÿà€¹à€¿à€€à¥à€à€Ÿà€³à¥à€¯à€Ÿà€µà€°à¥à€² à€ªà€€à¥à€€à€Ÿà€¯à€Ÿà€à€à€Ÿ à€žà€à€Šà€°à¥à€­</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Language">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Language</Attribute>
+            <Attribute name="definition">A language of the intellectual content of the resource.</Attribute>
+            <Attribute language="en" name="comment">Recommended best practice for the values of the Language element is defined by RFC 1766 which includes a two-letter Language Code (taken from the ISO 639 standard, followed optionally, by a two-letter Country Code (taken from the ISO 3166 standard). For example, &apos;en&apos; for English, &apos;fr&apos; for French, or &apos;en-uk&apos; for English used in the United Kingdom.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Reo</Attribute>
+            <Attribute name="definition">Te reo o te whakakaupapatanga o nga matauranga o te rauemi.</Attribute>
+            <Attribute name="comment">Ko te tino huarahi kua tohua mo nga uara o te huanga Reo kua whakaritea ki te RFC 1766 [RFC1766] kei roto te Tohu Reo kupu-rua (two-letter Language Code) (no te aro whanui ISO 639 [ISO639], ka taea e tetahi tohu kupu-rua te whai atu (no te aro whanui ISO 3166) [ISO366]). Hei tauira, te &apos;en&apos; mo te English, te &apos;fr&apos; mo te French, &apos;te en-uk&apos; mo te English e whakamahia ana i Ingarangi (UK).</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Langue</Attribute>
+            <Attribute name="definition">La langue du contenu intellectuel de la ressource.</Attribute>
+            <Attribute name="comment">Il est recommandÃ© d&apos;utiliser comme valeur de l&apos;Ã©lÃ©ment Langue celles definies par la RFC 1766 [RFC1766] qui comprend un code de langage Ã  deux caractÃšres(venant du standard ISO 639 [ISO639]), Ã©ventuellement suivi d&apos;un code Ã  deux lettres pour le pays (venant du standard ISO 3166 [ISO3166] ou en franÃ§ais [ISO3166]). Par exemple, &apos;en&apos; pour l&apos;anglais, &apos;fr&apos; pour le franÃ§ais, ou &apos;en-uk&apos; pour l&apos;anglais utilisÃ© au Royaume-Uni.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">Ð¯Ð·ÑÐº</Attribute>
+            <Attribute name="definition">Ð¯Ð·ÑÐº ÐžÐœÑÐµÐ»Ð»ÐµÐºÑÑÐ°Ð»ÑÐœÐŸÐ³ÐŸ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÐ»Ñ Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÑÐ»ÐµÐŒÐµÐœÑÐ° Ð¯Ð·ÑÐº, ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÐŒÐŸÐµ RFC 1766 (Ð¢ÑÐ³Ðž ÐŽÐ»Ñ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÐž ÑÐ·ÑÐºÐ°), Ð²ÐºÐ»ÑÑÐ°ÑÑÐžÐŒ ÐŽÐ²ÑÑ
+Ð±ÑÐºÐ²ÐµÐœÐœÑÐ¹ ÐºÐŸÐŽ ÑÐ·ÑÐºÐ° (Ð²Ð·ÑÑÑÐ¹ ÐžÐ· ÑÑÐ°ÐœÐŽÐ°ÑÑÐ° ISO 639 (ÐÐŸÐŽÑ ÐŽÐ»Ñ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐ¹ ÑÐ·ÑÐºÐŸÐ²)), Ð·Ð° ÐºÐŸÑÐŸÑÑÐŒ ÑÐ»ÐµÐŽÑÐµÑ (Ð¿ÑÐž ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÑÑÐž) ÐŽÐ²ÑÑ
+Ð±ÑÐºÐ²ÐµÐœÐœÑÐ¹ ÐºÐŸÐŽ ÑÑÑÐ°ÐœÑ (Ð²Ð·ÑÑÑÐŒÐž ÐžÐ· ÑÑÐ°ÐœÐŽÐ°ÑÑÐ° ISO 3166 (ÐÐŸÐŽÑ ÐŽÐ»Ñ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐ¹ ÑÑÑÐ°Ðœ)). ÐÐ°Ð¿ÑÐžÐŒÐµÑ, &quot;en&quot; - ÐŽÐ»Ñ Ð°ÐœÐ³Ð»ÐžÐ¹ÑÐºÐŸÐ³ÐŸ, &quot;fr&quot; - ÐŽÐ»Ñ ÑÑÐ°ÐœÑÑÐ·ÑÐºÐŸÐ³ÐŸ, &quot;en-uk&quot; - ÐŽÐ»Ñ Ð°ÐœÐ³Ð»ÐžÐ¹ÑÐºÐŸÐ³ÐŸ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐŸÐ³ÐŸ Ð² ÐÐµÐ»ÐžÐºÐŸÐ±ÑÐžÑÐ°ÐœÐžÐž.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Lengua</Attribute>
+            <Attribute name="definition">Lengua/s del contenido intelectual del recurso. Practicamente el contenido de este campo deberÃ­a coincidir con los de la RFC 1766 (Tags para la identificaciÃ³n de lenguas, http://ds.internic.net/rfc/rfc1766.txt); por ejemplo: en, es, de, fi, ja y zh.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙÙØºØ©</Attribute>
+            <Attribute name="definition">ÙØ°Ù ÙÙ ÙØºØ© Ø§ÙÙ
+Ø­ØªÙÙ Ø§ÙÙÙØ±Ù ÙÙÙ
+ØµØ¯Ø± . ÙÙÙ
+Ø§ ÙØ§Ù  Ø¹Ù
+ÙÙØ§ , Ù
+Ø­ØªÙÙ ÙØžØ§ Ø§ÙØ­ÙÙ ÙØ¬Øš Ø£Ù ÙØªØ·Ø§ØšÙ Ù
+Ø¹ RFC 1766    ] Ø§ÙØ§Ù
+Ø«ÙØ© ØªØ¶Ù
+ th, ja, fr, es, fi, de, en Ù zh ÙØ±Ù
+ÙØ² ÙÙØªØ¹Ø±ÙÙ ØšØ§ÙÙØºØ© [</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">è¯­ç§</Attribute>
+            <Attribute name="definition">æè¿°èµæºç¥è¯å
+å®¹çè¯­ç§ã</Attribute>
+            <Attribute name="comment">å»ºè®®æ¬å
+çŽ çåŒéçšRFC 3066[RFC3066]ïŒè¯¥æ åäžISO 639 [ISO639]äžèµ·å®ä¹äºç±äž€äžªåäžäžªè±    æå­æ¯ç»æçäž»è¯­èšæ ç­Ÿåå­æ ç­ŸäŸåŠå
+æ¬âenâæâengâæ¥è¡šç€ºEnglish, &quot;akk&quot; æ¥è¡šç€º    &quot;en-GB&quot;è¡šç€ºè±åœè±è¯­ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">Jazyk</Attribute>
+            <Attribute name="definition">Jazyk intelektuÃ¡lnÃ­ho obsahu zdroje.</Attribute>
+            <Attribute name="comment">DoporuÄenÃœ postup pro hodnoty prvku Jazyk je definovÃ¡n v RFC 1766 [RFC1766]: dvouznakovÃœ kÃ³d jazyka (pÅevzatÃœ z normy ISO 639 [ISO639]) volitelnÄ nÃ¡sledovanÃœ dvouznakovÃœm kÃ³dem zemÄ (pÅevzatÃœm z normy ISO 3166 [ISO3166]). NapÅÃ­klad &apos;en&apos; pro angliÄtinu, &apos;fr&apos; pro francouzÅ¡tinu, &apos;cs&apos; pro ÄeÅ¡tinu, nebo &apos;en-uk&apos; pro angliÄtinu uÅŸÃ­vanou ve SpojenÃ©m krÃ¡lovstvÃ­.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Taal</Attribute>
+            <Attribute name="definition">De taal waarin het document is beschreven. Voorgeschreven wordt de ISO639-1 norm, een twee karakter taalcode van de ISO 639(639-1 en 639-2) norm. Taalcodes kunnen van een lijst worden gekozen: http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt, Eventueel kan ISO3166 (landencodes) gebruikt worden om aan te geven in welk gebied de taal wordt gesproken. Deze kunnen ook van een lijst worden gekozen:  http://www.ics.uci.edu/pub/ietf/http/related/iso3166.txt.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Lingua</Attribute>
+            <Attribute name="definition">Le lingua del contento intellectual del ressource.</Attribute>
+            <Attribute name="comment">Le practica recommendate pro le valores del elemento lingua es definite per RFC 1766 [RFC1766], que include un codice de lingua de duo litteras (prendite del standard ISO 639 [ISO639]), sequite optionalmente per un codice de pais de duo litteras (prendite del standard ISO 3166 [ISO3166]). Per exemplo, &apos;ia&apos; pro interlingua, &apos;fr&apos; pro francese, o &apos;en-uk&apos; pro le anglese del Regno Unite.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€­à€Ÿà€·à€Ÿ</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à¥ à€­à€Ÿà€·à€Ÿ</Attribute>
+            <Attribute name="comment">à€à€Šà€Ÿ. à€®à€°à€Ÿà€ à¥ - à€­à€Ÿà€°à€€à¥à€¯ à€­à€Ÿà€·à€Ÿ</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Relation">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Relation</Attribute>
+            <Attribute name="definition">A reference to a related resource.</Attribute>
+            <Attribute name="comment">Recommended best practice is to reference the resource by means of a string or number conforming to a formal identification system.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Whai Panga</Attribute>
+            <Attribute name="definition">He tohutoro ki tetahi rauemi whai panga.</Attribute>
+            <Attribute name="comment">Ko te tino huarahi kua tohua, ko te tohutoro ki te rauemi ma te aho, te tau ranei, e hangai ana ki te punaha taututanga okawa.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Relation</Attribute>
+            <Attribute name="definition">Une rÃ©fÃ©rence Ã  une autre ressource qui a un rapport avec cette ressource.</Attribute>
+            <Attribute name="comment">Il est recommandÃ© de rÃ©fÃ©rencer cette ressource par une chaÃ®ne de caractÃšres ou un numÃ©ro conforme Ã  un systÃšme formel d&apos;identification.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÑÐœÐŸÑÐµÐœÐžÐµ</Attribute>
+            <Attribute name="definition">Ð²ÐµÐœÐœÑÐ¹ ÑÐµÑÑÑÑ.</Attribute>
+            <Attribute name="comment">ÐÐ»Ñ Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ ÐžÐŽÐµÐœÑÐžÑÐžÑÐžÑÐŸÐ²Ð°ÑÑ ÑÐµÑÑÑÑ Ð¿ÐŸÑÑÐµÐŽÑÑÐ²ÐŸÐŒ ÑÑÑÐŸÐºÐž ÐžÐ»Ðž ÑÐžÑÐ»Ð°, ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐ³ÐŸ ÑÐŸÑÐŒÐ°Ð»ÑÐœÐŸÐ¹ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÑÐžÑÑÐµÐŒÐµ.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">RelaciÃ³n</Attribute>
+            <Attribute name="definition">Un identificador de un segundo recurso y su relaciÃ³n con el recurso actual. Este elemento permite enlazar los recursos relacionados y las descripciones de los recursos. Por ejemplo: IsVersionOf - Incluye la ediciÃ³n de un trabajo, IsBasedOn - La traducciÃ³n de un trabajo, IsPartOf - Un capÃ­tulo de un libro, IsFormatOf - Un mecanismo de transformaciÃ³n de un conjunto de datos en una imagen. Para asegurar la interoperabilidad, las relaciones deberÃ­an ser seleccionadas de una lista de elementos que actualmente se encuentra bajo desarrollo en un grupo de trabajo.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙØ¹ÙØ§ÙØ©</Attribute>
+            <Attribute name="definition">ÙØ°Ø§ Ù
+Ø¹Ø±Ù ÙÙÙ
+ØµØ¯Ø± Ø§ÙØ«Ø§ÙÙ Ù Ø¹ÙØ§ÙØªÙ ØšØ§ÙÙ
+ØµØ¯Ø± Ø§ÙØ­Ø§ÙÙ . ÙØ³Ù
+Ø­ ÙØ°Ø§ Ø§ÙØ¹Ø§Ù
+Ù ØšØªÙØ¶ÙØ­ Ø§ÙØ±ÙØ§ØšØ· ØšÙÙ Ø§ÙÙ
+ØµØ§Ø¯Ø± Ø§ÙÙ
+ØªØ¹ÙÙØ©     ØšØšØ¹Ø¶ÙØ§ Ù ØªÙØµÙÙ Ø§ÙÙ
+ØµØ¯Ø± . Ø§ÙØ§Ù
+Ø«ÙØ© ØªØ¶Ù
+ Ø·ØšØ¹Ø© Ø§ÙØ¹Ù
+Ù ) ÙØ³Ø®Ø© Ù
+Ù ( ØªØ±Ø¬Ù
+Ø© Ø¹Ù
+Ù ) Ø§Ø¹ØªÙ
+Ø§Ø¯Ø§ Ø¹ÙÙ ( ÙØµÙ Ù
+Ù ÙØªØ§Øš ) Ø¬Ø²Ø¡ Ù
+Ù (    Ù ØªØ­ÙÙÙÙ Ù
+ÙÙØ§ÙÙÙÙØ© ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ù
+Ø¹ÙÙÙ
+Ø§ØªÙØ© Ø§ÙÙ ØµÙØ±Ø© ) ØµÙØºØ© Ù
+Ù ( Ù
+Ù Ø£Ø¬Ù Ø§ÙØªØ¹Ø§Ù
+Ù Ø§ÙÙ
+ØŽØªØ±Ù , ÙØ¬Øš Ø§Ø®ØªÙØ§Ø± Ø§ÙØ¹ÙØ§ÙØ§Øª Ù
+Ù    Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+Ø±ÙÙ
+Ø© Ù Ø§ÙØªÙ ÙØªÙ
+ Ø§Ø¹Ø¯Ø§Ø¯ÙØ§ Ø­Ø§ÙÙØ§ Ø¶Ù
+Ù Ø­ÙÙØ§Øª ÙØ±ØŽØ© Ø¹Ù
+Ù</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">å
+³è</Attribute>
+            <Attribute name="definition">æ¶åççžå
+³èµæºã</Attribute>
+            <Attribute name="comment">èåœçžå
+³èµæºæ¶ïŒå»ºè®®äœ¿çšç¬Šåæ­£åŒæ è¯ç³»ç»çå­ç¬Šäž²æè
+æ°å­ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">Vztah</Attribute>
+            <Attribute name="definition">Odkaz na pÅÃ­buznÃœ zdroj.</Attribute>
+            <Attribute name="comment">DoporuÄuje se odkazovat zdroj znakovÃœm ÅetÄzcem nebo ÄÃ­slem odpovÃ­dajÃ­cÃ­m nÄkterÃ©mu z formÃ¡lnÃ­ch identifikaÄnÃ­ch systÃ©mÅ¯.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Relatie</Attribute>
+            <Attribute name="definition">Een identificatie van een tweede bron en de relatie met de huide Internetbron. Voorbeelden zijn een editie van een werk (IsVersionOf), een vertaling van een werk (IsBasedOn), een hoofdstuk van een boek (IsPartOf) en een mechanische transformatie van een dataset in een plaatje (IsFormatOf). De DC Working Groups zijn bezig met een lijst met de meest verwachte relaties. Aanbevolen wordt om de relaties van deze lijst te gebruiken: http://purl.oclc.org/metadata/dublin_core/wrelationdraft.html.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="definition">Relation</Attribute>
+            <Attribute name="definition">Un referentia a un ressource correlate.</Attribute>
+            <Attribute name="comment">Le practica recommendate es facer referentia al ressource per medio de un catena de characteres o numero conforme a un systema de identification formal.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€šà€Ÿà€€à¥ , à€žà€à€¬à€à€§</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€¶à¥ à€žà€à€¬à€à€§ à€Šà€Ÿà€à€µà€£à€Ÿà€°à€Ÿ à€žà€à€Šà€°à¥à€­</Attribute>
+            <Attribute name="comment">à€à€Šà€Ÿ.  à€®à€Ÿà€¹à€¿à€€à¥ à€à€Ÿà€³à¥à€¯à€Ÿà€µà€°à¥à€² à€ªà€€à¥à€€à€Ÿ(URL)</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Coverage">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Coverage</Attribute>
+            <Attribute name="definition">The extent or scope of the content of the resource.</Attribute>
+            <Attribute name="comment">Coverage will typically include spatial location (a place name or geographic coordinates), temporal period (a period label, date, or date range) or jurisdiction (such as a named administrative entity). Recommended best practice is to select a value from a controlled vocabulary (for example, the Thesaurus of Geographic Names [TGN]) and that, where appropriate, named places or time periods be used in preference to numeric identifiers such as sets of coordinates or date ranges.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Kapitanga</Attribute>
+            <Attribute name="definition">Te roanga, te whanuitanga ranei o te whakakaupapatanga o te rauemi.</Attribute>
+            <Attribute name="comment">Ko te tikanga, ka uru atu te wahi mokowa (te ingoa o tetahi wahi, whakapiritanga matawhenua ranei), whakaritenga wa (he tapatanga wa (period label, ra, whakatakotoranga whanui o nga ra), te whakaritenga ture (penei i te putahi whakahaere). Ko te tino huarahi kua tohua, ko te tipako uara mai i tetahi whakaritenga kupu (hei tauira, i tetahi Puna Kupu Ingoa Matawhenua (Geographic Names [TGN] i nga wahi tika, ko nga wahi me nga whakaritenga wa ka whakamahia i mua i te whakamahitanga o nga taututanga tau penei i nga huinga whakapiritanga me nga whakatakotoranga whanui o nga ra.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Couverture</Attribute>
+            <Attribute name="definition">La portÃ©e ou la couverture spatio-temporelle de la ressource.</Attribute>
+            <Attribute name="comment">La couverture typiquement inclut une position gÃ©ographique (le nom d&apos;un lieu ou ses coordonnÃ©es), une pÃ©riode de temps (un nom de pÃ©riode, une date, ou un intervalle de temps) ou une juridiction (telle que le nom d&apos;une entitÃ© administrative). Il est recommandÃ© de choisir la  valeur de Couverture dans un vocabulaire contrÃŽlÃ© (par exemple, un thÃ©saurus de noms gÃ©ographiques, comme[TGN]) et, quand cela est appropriÃ©, des noms de lieux ou de pÃ©riodes plutÃŽt que des identifiants numÃ©riques tels que des coordonnÃ©es ou des intervalles de dates. </Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÑ
+Ð²Ð°Ñ</Attribute>
+            <Attribute name="definition">ÐÑÐŸÑÑÐ¶ÐµÐœÐœÐŸÑÑÑ Ðž Ð³ÑÐ°ÐœÐžÑÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÑ
+Ð²Ð°Ñ ÐŸÐ±ÑÐºÐœÐŸÐ²ÐµÐœÐœÐŸ Ð²ÐºÐ»ÑÑÐ°ÐµÑ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²ÐµÐœÐœÐŸÐµ ÐŒÐµÑÑÐŸÐœÐ°Ñ
+ÐŸÐ¶ÐŽÐµÐœÐžÐµ (ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐŒÐµÑÑÐœÐŸÑÑÐž ÐžÐ»Ðž Ð³ÐµÐŸÐ³ÑÐ°ÑÐžÑÐµÑÐºÐžÐµ ÐºÐŸÐŸÑÐŽÐžÐœÐ°ÑÑ), Ð²ÑÐµÐŒÐµÐœÐœÐŸÐ¹ Ð¿ÑÐŸÐŒÐµÐ¶ÑÑÐŸÐº (ÑÐºÐ°Ð·Ð°ÐœÐžÐµ Ð¿ÐµÑÐžÐŸÐŽÐ°, ÐŽÐ°ÑÐ° ÐžÐ»Ðž ÑÑÐŽ ÐŽÐ°Ñ) ÐžÐ»Ðž ÑÑÐžÑÐŽÐžÐºÑÐžÑ (ÑÐºÐ°Ð·Ð°ÐœÐžÐµ ÐµÐŽÐžÐœÐžÑÑ Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐ°ÑÐžÐ²ÐœÐŸÐ³ÐŸ ÐŽÐµÐ»ÐµÐœÐžÑ). ÐÐ° Ð¿ÑÐ°ÐºÑÐžÐºÐµ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ Ð²ÑÐ±ÐžÑÐ°ÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐžÐ· ÐºÐŸÐœÑÑÐŸÐ»ÐžÑÑÐµÐŒÐŸÐ³ÐŸ ÑÐ»ÐŸÐ²Ð°ÑÑ (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, Ð¢ÐµÐ·Ð°ÑÑÑÑÐ° Ð³ÐµÐŸÐ³ÑÐ°ÑÐžÑÐµÑÐºÐžÑ
+ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐ¹ TGN), Ðž, ÐµÑÐ»Ðž ÑÑÐŸ ÑÐŒÐµÑÑÐœÐŸ, Ð¿ÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÐµ ÐŸÑÐŽÐ°ÐµÑÑÑ ÑÐºÐ°Ð·Ð°ÐœÐžÑÐŒ ÐŒÐµÑÑÐœÐŸÑÑÐµÐ¹ ÐžÐ»Ðž Ð²ÑÐµÐŒÐµÐœÐœÑÑ
+ Ð¿ÑÐŸÐŒÐµÐ¶ÑÑÐºÐŸÐ² Ð²ÐŒÐµÑÑÐŸ ÑÐžÑÑÐŸÐ²ÑÑ
+ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ², ÐºÐ°Ðº, ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÑÐžÑÑÐµÐŒ ÐºÐŸÐŸÑÐŽÐžÐœÐ°Ñ ÐžÐ»Ðž Ð²ÑÐµÐŒÐµÐœÐœÑÑ
+ ÑÑÐŽÐŸÐ².</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Cobertura</Attribute>
+            <Attribute name="definition">La caracterÃ­stica de cobertura espacial y/o temporal del contenido intelectual del recurso. La cobertura espacial se refiere a una regiÃ³n fÃ­sica (por ejemplo, sector celestial); uso de coordenadas (por ejemplo, longitud y latitud) o nombres de lugares extraidos de una lista controlada. La cobertura temporal se refiere al contenido del recurso en vez de a cuando fue creado o puesto accesible ya que este Ãºltimo pertenece al elemento Date. Se usa el mismo formato basado en http://www.w3.org/TR/NOTE-datetime.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙØªØºØ·ÙØ©</Attribute>
+            <Attribute name="definition">ÙÙ Ø§ÙØ®ØµØ§ØŠØµ Ø§ÙÙ
+ÙØ§ÙÙØ© Ø§Ù Ø§ÙØ²Ù
+ÙÙØ© ÙÙÙ
+Ø­ØªÙÙ Ø§ÙÙÙØ±Ù ÙÙÙ
+ØµØ¯Ø± . Ø§ÙØªØºØ·ÙØ© Ø§ÙÙ
+ÙØ§ÙÙØ© ØªØŽÙØ± Ø§ÙÙ Ø¬ÙØ© Ø·ØšÙØ¹ÙØ© )Ù
+Ø«Ù , ÙØ·Ø§Ø¹ Ø³Ù
+Ø§ÙÙ (    Ø§Ø³ØªØ®Ø¯Ø§Ù
+ Ø§ÙØ§Ø­Ø¯Ø§Ø«ÙØ§Øª ) Ù
+Ø«Ù  Ø®Ø· Ø§ÙØ·ÙÙ Ù Ø®Ø· Ø§ÙØ¹Ø±Ø¶ ( ÙÙ Ø£Ø³Ù
+Ø§Ø¡ Ø§Ù
+ÙÙØ© Ù
+Ø³ØªØ­ÙÙ
+Ø© Ø§Ù Ù
+ØªØ¬ÙØ§Øª ØšØ§ÙÙØ§Ù
+Ù . Ø§ÙØªØºØ·ÙØ© Ø§ÙØ²Ù
+ÙÙØ©    Ø«Ø¹ÙØ¯ Ø§ÙÙ Ù
+Ø§ ÙØ±Ø¬Ø¹ Ø§ÙÙÙ Ø§ÙÙ
+ØµØ¯Ø± Ù ÙÙØ³ Ø§Ù Ù
+ØªÙ ØªÙ
+ ØªÙÙÙØ±Ù ) Ø§ÙØ§Ø®ÙØ± ÙØªØ¹ÙÙ ØšØ¹Ø§Ù
+Ù Ø§ÙØªØ§Ø±ÙØ® ( Ø§Ø³ØªØ®Ø¯Ø§Ù
+ ÙÙØ³ ØµÙØºØ© Ø§ÙØªØ§Ø±ÙØ®  Ø§Ù Ø§ÙÙÙØª    ) Ø¹Ø§Ø¯Ø© Ù
+Ø¯Ù ] ( ØµÙØ§ØºØ§Øª Ø§ÙÙÙÙ
+ Ù Ø§ÙÙÙØª ) Ø§Ø¹ØªÙ
+Ø§Ø¯Ø§ Ø¹ÙÙ (ISO 8601 Ø§ÙÙ
+ÙØ§Ø­ØžØ© Ø§ÙÙÙÙØ© [http://www.w3.org/TR/NOTE-datetime, W3C    ÙÙ
+Ø§ ÙÙ Ù
+ÙØµÙ ØšÙ ÙØ¹Ø§Ù
+Ù Ø§ÙØªØ§Ø±ÙØ® Ø§Ù ÙØªØ±Ø§Øª Ø²Ù
+ÙÙØ© Ù
+Ù ÙØ§ØŠÙ
+Ø© Ù
+Ø³ØªØ­ÙÙ
+Ø© Ø§Ù Ù
+ØªØ¬ÙØ§Øª ØšØ§ÙÙØ§Ù
+Ù</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">èŠçèåŽ</Attribute>
+            <Attribute name="definition">èµæºå
+å®¹ææ¶åçå€å»¶äžèŠçèåŽ</Attribute>
+            <Attribute name="comment">èŠçèåŽäžè¬å
+æ¬ç©ºéŽäœçœ®ïŒäžäžªå°åæå°çåæ ïŒãæ¶éŽåºéŽïŒäžäžªæ¶éŽæ è¯ïŒæ¥ææäžäžªæ¥æè    åŽïŒãæè
+æéïŒæ¯åŠåœåçææå®äœïŒæšèèŠçèåŽæå¥œæ¯åèªäºäžäžªåæ§è¯è¡šïŒäŸåŠå°åè¯åº    [TGN]ïŒïŒå¹¶åºå°œå¯èœå°äœ¿çšç±æ°å­è¡šç€ºçåæ ææ¥æåºéŽæ¥æè¿°å°åäžæ¶éŽæ®µã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">PokrytÃ­</Attribute>
+            <Attribute name="definition">Rozsah nebo zÃ¡bÄr obsahu zdroje.</Attribute>
+            <Attribute name="comment">PokrytÃ­ bude typicky obsahovat prostorovÃ© umÃ­stÄnÃ­ (jmÃ©no mÃ­sta nebo zemÄpisnÃ© souÅadnice), ÄasovÃ© obdobÃ­ (oznaÄenÃ­ obdobÃ­, datum nebo ÄasovÃœ interval) nebo jurisdikci (napÅ. jmÃ©no administrativnÃ­ jednotky). DoporuÄuje se vybÃ­rat hodnotu z ÅÃ­zenÃ©ho slovnÃ­ku (napÅ. Thesaurus of Geographic Names [TGN]) a tam, kde je to vhodnÃ©, uvÃ¡dÄt mÃ­sta nebo ÄasovÃ© Ãºseky spÃ­Å¡e jmÃ©nem neÅŸ ÄÃ­selnÃœmi identifikÃ¡tory jako jsou soubory souÅadnic nebo ÄasovÃ© intervaly.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Dekking</Attribute>
+            <Attribute name="definition">De ruimtelijke of tijdelijke karakteristieken van de intellectuele inhoud van de Internetbron. Ruimtelijke dekking verwijst naar een geografisch gebied. Gebruik coordinaten (longitude (lengtegraad) en latitude (breedtegraad)) of plaatsnamen die van een gecontroleerde lijst komen of volledig uitgeschreven zijn. Dekking in de tijd geeft de tijdsperiode aan waarop de inhoud van de Internetbron betrekking heeft en niet wanneer de Internetbron is gemaakt of beschikbaar is gesteld (dit laatste hoort ingevult te worden bij &quot;Date&quot;). Gebruik dezelfde datum/tijd formaat als bij &quot;Date&quot;; W3C Technical Note http://www.w3.org/TR/NOTE-datetime of tijdsperioden die van een gecontroleerde lijst komen of volledig uitgeschreven zijn. Coverage is in ontwikkeling bij de Dublin Core Working group http://www.alexandria.ucsb.edu/docs/metadata/dc_coverage.html.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Copertura</Attribute>
+            <Attribute name="definition">Le extension physic o abstracte del contento del ressource.</Attribute>
+            <Attribute name="comment">Le copertura typicamente include un location spatial (un nomine de localitate o coordinatas geographic), un periodo de tempore (un etiquetta de periodo, data, o gamma de datas), o un jurisdiction (tal como un entitate administrative nominate). Le practica recommendate es selectionar un valor a partir de un vocabulario controlate (per exemplo, le Thesaurus of Geographical Names [TGN]) e que, quando appropriate, localitates o periodos de tempore nominate sia utilizate in preferentia a identificatores numeric tales como collectiones de coordinatas o gammas de datas.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€µà¥à€¯à€Ÿà€ªà¥à€€à¥</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à¥ à€­à¥à€à¥à€²à€¿à€  à€®à€Ÿà€¹à€¿à€€à¥</Attribute>
+            <Attribute name="comment">à€à€Šà€Ÿ. à€­à¥à€à¥à€²à€¿à€ à€µà¥à€¯à€Ÿà€ªà¥à€€à¥</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Rights">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Rights Management</Attribute>
+            <Attribute name="definition">Information about rights held in and over the resource.</Attribute>
+            <Attribute name="comment">Typically, a Rights element will contain a rights management statement for the resource, or reference a service providing such information. Rights information often encompasses Intellectual Property Rights (IPR), Copyright, and various Property Rights. If the Rights element is absent, no assumptions can be made about the status of these and other rights with respect to the resource.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Motika</Attribute>
+            <Attribute name="definition">Ko nga mohiohio ki nga motika o tetahi rauemi.</Attribute>
+            <Attribute name="comment">Ko te tikanga, kei te huanga Motika e pupuri ana he korero mo te whakaritenga motika mo te rauemi, he ratonga tohutoro e whakarato ana ranei i enei tumomo mohiohio. He nui nga wa, puta ai i roto i te mohiohio Motika te Mana Whakairo Hinegaro (Intellectual Property Rights - (IPR)), te Manatarua me nga Tuahua Mana Taonga (Property Rights). Ki te kore te huanga Motika, kaore e taea te pohehe noa ki te mana o enei, nga motika ranei e pa ana ki te rauemi.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Droits</Attribute>
+            <Attribute name="definition">Information sur les droits sur et au sujet de la ressource.</Attribute>
+            <Attribute name="comment">Typiquement, un Ã©lÃ©ment Droits contiendra un Ã©tat du droit Ã  gÃ©rer une ressource, ou la refÃ©rence Ã  un service fournissant cette information. Ces droits souvent couvrent les droits de propriÃ©tÃ© intellectuelle (IPR), Copyright, et divers droits de propriÃ©tÃ©. Si l&apos;Ã©lÃ©ment Droits est absent, aucune hypothÃšse ne peut Ãªtre faite sur l&apos;Ã©tat de ces droits, ou de tout autre, par rapport Ã  la ressource.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÑÐ°Ð²ÐŸÐ²ÐŸÐµ ÑÐµÐ³ÑÐ»ÐžÑÐŸÐ²Ð°ÐœÐžÐµ</Attribute>
+            <Attribute name="definition">ÐÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ Ð¿ÑÐ°Ð²Ð°Ñ
+ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ, ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐ°ÑÑÑ Ð²ÐœÑÑÑÐž Ðž Ð²ÐœÐµ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÐ±ÑÑÐœÐŸ ÑÐ»ÐµÐŒÐµÐœÑ ÐÑÐ°Ð²Ð° ÑÐŸÐŽÐµÑÐ¶ÐžÑ Ð¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐžÐµ ÐŸ Ð¿ÑÐ°Ð²ÐŸÐ²ÑÑ
+ ÐœÐŸÑÐŒÐ°Ñ
+, ÑÐµÐ³ÑÐ»ÐžÑÑÑÑÐžÑ
+ ÑÑÐœÐºÑÐžÐŸÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÑÐµÑÑÑÑÐ° ÐžÐ»Ðž ÑÑÑÐ»ÐºÑ ÐœÐ° ÑÐ»ÑÐ¶Ð±Ñ, Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÑÑÑÑÑ ÑÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ. ÐÑÐ°Ð²ÐŸÐ²Ð°Ñ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸÐ±ÑÑÐœÐŸ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÑÐ²ÐµÐŽÐµÐœÐžÑ ÐŸ ÐÑÐ°Ð²Ð°Ñ
+ ÐžÐœÑÐµÐ»Ð»ÐµÐºÑÑÐ°Ð»ÑÐœÐŸÐ¹ ÑÐŸÐ±ÑÑÐ²ÐµÐœÐœÐŸÑÑÐž, ÐÐ²ÑÐŸÑÑÐºÐŸÐŒ Ð¿ÑÐ°Ð²Ðµ Ðž ÐŽÑÑÐ³ÐžÑ
+ ÐÐŒÑÑÐµÑÑÐ²ÐµÐœÐœÑÑ
+ Ð¿ÑÐ°Ð²Ð°Ñ
+. ÐÑÑÑÑÑÑÐ²ÐžÐµ ÑÐ»ÐµÐŒÐµÐœÑÐ° ÐÑÐ°Ð²Ð° ÐœÐµ ÐŒÐŸÐ¶ÐµÑ ÑÐ²Ð»ÑÑÑÑÑ ÐŸÑÐœÐŸÐ²Ð°ÐœÐžÐµÐŒ ÐŽÐ»Ñ ÐºÐ°ÐºÐžÑ
+-Ð»ÐžÐ±ÐŸ Ð¿ÑÐµÐŽÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐžÐ¹ ÐŸ Ð¿ÑÐ°Ð²ÐŸÐ²ÐŸÐŒ ÑÑÐ°ÑÑÑÐµ Ðž ÐŽÑÑÐ³ÐžÑ
+ Ð¿ÑÐ°Ð²Ð°Ñ
+, ÐºÐ°ÑÐ°ÑÑÐžÑ
+ÑÑ ÑÐµÑÑÑÑÐ°.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Derechos</Attribute>
+            <Attribute name="definition">Una referencia (URL, por ejemplo) para una nota sobre derechos de autor, para un servicio de gestiÃ³n de derechos o para un servicio que darÃ¡ informaciÃ³n sobre tÃ©rminos y condiciones de acceso a un recurso. Una especificaciÃ³n formal del elemento Rights se encuentra catualmente en discusiÃ³n y por lo tanto su uso se considera experimental.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø­ÙÙÙ Ø§ÙØ§Ø¯Ø§Ø±Ø©</Attribute>
+            <Attribute name="definition">ÙÙ Ø§ÙØ§Ø¯Ø© Ø­ÙÙÙ Ø§ÙØ§Ø¯Ø§Ø±Ø© , Ù
+Ø¹Ø±Ù Ù
+Ø±ØªØšØ· ØšØ§ÙØ§Ø¯Ø© Ø­ÙÙÙ Ø§ ÙØ§Ø¯Ø§Ø±Ø© , Ù
+Ø¹Ø±Ù Ù
+Ø±ØªØšØ· ØšØ®Ø¯Ù
+Ø© ØªÙØ¯Ù
+ Ù
+Ø¹ÙÙÙ
+Ø§Øª Ø¹Ù Ø­ÙÙÙ Ø§ÙØ§Ø¯Ø§Ø±Ø© Ø§ÙØ®Ø§ØµØ© ØšØ§ÙÙ
+ØµØ¯Ø±</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">æé</Attribute>
+            <Attribute name="definition">æå
+³èµæºæ¬èº«ææçæè¢«èµäºçæéä¿¡æ¯</Attribute>
+            <Attribute name="comment">äžè¬èèšïŒæéå
+çŽ åºå
+æ¬äžäžªå¯¹èµæºçæéå£°æïŒæè
+æ¯å¯¹æäŸè¿äžä¿¡æ¯çæå¡çåç
+§ãæéäžè¬    å
+æ¬ç¥è¯äº§æ(IPR)ïŒçææå
+¶ä»åç§åæ ·çäº§æãåŠææ²¡ææéå
+çŽ çæ æ³šïŒäžå¯ä»¥å¯¹äžèµæºçžå
+³    çäžè¿°æå
+¶ä»æå©çæ
+åµäœåºä»»äœåå®ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">PrÃ¡va</Attribute>
+            <Attribute name="definition">Informace o prÃ¡vech vztahujÃ­cÃ­ch se k popisovanÃ©mu zdroji.</Attribute>
+            <Attribute name="comment">Prvek PrÃ¡va bude typicky obsahovat ustanovenÃ­ o sprÃ¡vÄ autorskÃœch/vlastnickÃœch prÃ¡v ke zdroji nebo odkaz na sluÅŸbu poskytujÃ­cÃ­ takovÃ©to informace. Informace o prÃ¡vech Äasto zahrnujÃ­ prÃ¡va duÅ¡evnÃ­ho vlastnictvÃ­ (IPR), autorskÃ© prÃ¡vo a rÅ¯znÃ¡ vlastnickÃ¡ prÃ¡va. JestliÅŸe prvek PrÃ¡va chybÃ­, nelze odvozovat ÅŸÃ¡dnÃ© pÅedpoklady o stavu tÄchto a jinÃœch prÃ¡v vztahujÃ­cÃ­ch se k popisovanÃ©mu zdroji.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Copyright</Attribute>
+            <Attribute name="definition">Een copyright verklaring of een link naar een copyright verklaring of een link naar een service die informatie geeft over de copyright van de Internetbron.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Gestion de derectos</Attribute>
+            <Attribute name="definition">Information super derectos detenite super e a proposito del ressource.</Attribute>
+            <Attribute name="comment">Typicamente le elemento derectos continera un declaration de gestion de derectos pro le ressource, o un referentia a un servicio que provide tal information. Information de derectos frequentemente involve derectos de proprietate intellectual (IPR), copyright e varie derectos de proprietate. Si le elemento Derectos es absente, necun hypothese pote esser facite quanto al stato de iste e altere derectos concernente ressource.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€¹à€à¥à€</Attribute>
+            <Attribute name="definition">à€¬à¥à€§à¥à€Šà€¿à€ à€žà€à€ªà€Šà¥à€à€Ÿà€¹à€à¥à€</Attribute>
+            <Attribute name="comment">à€žà¥à€µà€€à€à€¹à€Ÿà€à¥ à€²à¥à€à€š à€à€Ÿà€ªà¥à€š à€
+à€¥à€µà€Ÿ à€®à€Ÿà€¹à€¿à€€à¥à€à€Ÿà€³à¥à€¯à€Ÿà€µà€° à€ªà¥à€°à€à€Ÿà€¶à€¿à€€ à€à€°à€£à¥à€¯à€Ÿà€à€Ÿ à€²à¥à€à€ à€
+à€¥à€µà€Ÿ à€²à¥à€à€¿à€à¥à€à€Ÿ à€¬à¥à€§à¥à€Šà€¿à€ à€žà€à€ªà€Šà¥à€à€Ÿà€¹à€à¥à€</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+</MetadataSet>
Index: /tags/greenstone-3_02-distribution/gli/metadata/ex.mds
===================================================================
--- /tags/greenstone-3_02-distribution/gli/metadata/ex.mds	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/metadata/ex.mds	(revision 13928)
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE MetadataSet SYSTEM "http://www.greenstone.org/dtd/MetadataSet/1.0/MetadataSet.dtd">
+<MetadataSet contact="nzdl.org" creator="New Zealand Digital Libraries Project: Greenstone" family="Extracted Greenstone" lastchanged="Tue Sep 05 14:40:36 NZST 2006 - kjdon on kanuka" namespace="ex">
+    <Name language="en">Extracted Greenstone Metadata 1.0</Name>
+    <Description language="en">This document is the reference description, version 1.0 of the automatically extracted Greenstone Metadata Element Set.</Description>
+    <Element name="Encoding">
+        <Attribute language="en" name="comment">Not always available.</Attribute>
+        <Attribute language="en" name="definition">The encoding of the imported document as extracted by Greenstone.</Attribute>
+        <Attribute language="en" name="label">Encoding</Attribute>
+    </Element>
+    <Element name="Language">
+        <Attribute language="en" name="comment">Not always available.</Attribute>
+        <Attribute language="en" name="definition">The language of the imported document as extracted by Greenstone.</Attribute>
+        <Attribute language="en" name="label">Language</Attribute>
+    </Element>
+    <Element name="Source">
+        <Attribute language="en" name="comment">Hidden in the Librarian Interface as it already shown by the various file trees.</Attribute>
+        <Attribute language="en" name="definition">The filename of the document imported by Greenstone.</Attribute>
+        <Attribute language="en" name="label">Source</Attribute>
+    </Element>
+    <Element name="Title">
+        <Attribute language="en" name="comment">Not always available.</Attribute>
+        <Attribute language="en" name="definition">The title of the imported document as extracted by Greenstone.</Attribute>
+        <Attribute language="en" name="label">Title</Attribute>
+    </Element>
+</MetadataSet>
Index: /tags/greenstone-3_02-distribution/gli/metadata/exp.mds
===================================================================
--- /tags/greenstone-3_02-distribution/gli/metadata/exp.mds	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/metadata/exp.mds	(revision 13928)
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE MetadataSet SYSTEM "http://www.greenstone.org/dtd/MetadataSet/1.0/MetadataSet.dtd">
+<MetadataSet contact="nzdl.org" creator="New Zealand Digital Libraries Project: Greenstone" family="Exploded Metadata" lastchanged="Mon Mar 13 10:30:32 2006 - mdewsnip on bedrock" namespace="exp">
+    <Name language="en">Exploded Metadata Set</Name>
+    <Description language="en">An empty metadata set that is a good place to put metadata exploded from a metadata database (eg. CDS/ISIS).</Description>
+</MetadataSet>
Index: /tags/greenstone-3_02-distribution/gli/metadata/greenstone.mds
===================================================================
--- /tags/greenstone-3_02-distribution/gli/metadata/greenstone.mds	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/metadata/greenstone.mds	(revision 13928)
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE MetadataSet SYSTEM "http://www.greenstone.org/dtd/MetadataSet/1.0/MetadataSet.dtd">
+<MetadataSet contact="" creator="" family="" lastchanged="Tue Sep 05 14:40:36 NZST 2006 - kjdon on kanuka" namespace="gs">
+    <SetLanguage code="en">
+        <Name>Greenstone metadata set</Name>
+        <Description>Some special elements particular to Greenstone.</Description>
+    </SetLanguage>
+    <Element name="DocumentHeader">
+        <Language code="en">
+            <Attribute name="label">Document Header</Attribute>
+            <Attribute name="definition">Headers that will be added to document display. For example, use this to include stylesheets in the document display. The content should be escaped HTML.</Attribute>
+            <Attribute name="comment">The _document:documentheader_ macro will be set to the value of this metadata.</Attribute>
+        </Language>
+    </Element>
+</MetadataSet>
Index: /tags/greenstone-3_02-distribution/gli/metadata/nzgls.mds
===================================================================
--- /tags/greenstone-3_02-distribution/gli/metadata/nzgls.mds	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/metadata/nzgls.mds	(revision 13928)
@@ -0,0 +1,1772 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE MetadataSet SYSTEM "http://www.greenstone.org/dtd/MetadataSet/1.0/MetadataSet.dtd">
+<MetadataSet contact="nzgls@ssc.govt.nz" creator="Archives New Zealand" family="" language_dependent="label, definition, comment" lastchanged="Tue Sep 05 14:40:36 NZST 2006 - kjdon on kanuka" namespace="nzgls">
+    <!-- English Version sourced from http://www.e-government.govt.nz/nzgls/standard/ -->
+    <SetLanguage code="en">
+        <Name language="en">New Zealand Government Locator Service Metadata Standard version 2.1</Name>
+        <Description language="en">The NZGLS metadata standard is the official New Zealand Government standard for creating discovery-level metadata (see Cabinet Circular CO (02) 3). The standard is based closely on two well established standards: the Dublin Core Metadata Element Set and the Australian Government Locator Service.</Description>
+    </SetLanguage>
+    <Element name="Title">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Title</Attribute>
+            <Attribute name="definition">A name given to the resource.</Attribute>
+            <Attribute name="comment">Typically, a Title will be a name by which the resource is formally known.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Taitara</Attribute>
+            <Attribute name="definition">Te ingoa ka tapaina tetahi rauemi.</Attribute>
+            <Attribute name="comment">Ko te tikanga, ko te Taitara te ingoa ka mohio whanuitia te ingoa.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Titre</Attribute>
+            <Attribute name="definition">Le nom donnÃ© Ã  la ressource.</Attribute>
+            <Attribute name="comment">Typiquement, un titre sera le nom par lequel la ressource est officiellement connue.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÐ°Ð·Ð²Ð°ÐœÐžÐµ</Attribute>
+            <Attribute name="definition">ÐÐŒÑ, ÐŽÐ°ÐœÐœÐŸÐµ ÑÐµÑÑÑÑÑ.</Attribute>
+            <Attribute name="comment">ÐÐ±ÑÑÐœÐŸ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµÐŒ ÑÐ²Ð»ÑÐµÑÑÑ ÐžÐŒÑ, Ð¿ÐŸÐŽ ÐºÐŸÑÐŸÑÑÐŒ ÑÐµÑÑÑÑ ÐŸÑÐžÑÐžÐ°Ð»ÑÐœÐŸ ÐžÐ·Ð²ÐµÑÑÐµÐœ.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">TÃ­tulo</Attribute>
+            <Attribute name="definition">El nombre dado a un recurso, usualmente por el autor.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙØ¹ÙÙØ§Ù</Attribute>
+            <Attribute name="definition">ÙØ°Ø§ Ø§ÙØ§Ø³Ù
+ ÙØ¹Ø·Ù ÙÙÙ
+ØµØ¯Ø±, Ù
+Ù ÙØšÙ Ø§ÙÙ
+ØšØ¯Ø¹ Ø§Ù Ø§ÙÙØ§ØŽØ±</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">èµæºå</Attribute>
+            <Attribute name="definition">èµäºèµæºçåç§°ã</Attribute>
+            <Attribute name="comment">èµæºåäžè¬æèµæºå¯¹è±¡æ­£åŒå
+¬åŒçåç§°ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">NÃ¡zev</Attribute>
+            <Attribute name="definition">JmÃ©no danÃ© zdroji.</Attribute>
+            <Attribute name="comment">NÃ¡zev bude typicky jmÃ©no, pod nÃ­mÅŸ je zdroj oficiÃ¡lnÄ znÃ¡m.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Titel</Attribute>
+            <Attribute name="definition">De naam van de Internetbron. Meestal gegeven door de auteur, maker of uitgever</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Titulo</Attribute>
+            <Attribute name="definition">Un nomine date al ressource.</Attribute>
+            <Attribute name="comment">Typicamente se utiliza un nomine per le qual le ressource es formalmente cognite.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€¶à¥à€°à¥à€·à€</Attribute>
+            <Attribute name="definition">à€ªà€°à¥à€¯à€Ÿà€¯à¥ à€¶à¥à€°à¥à€·à€</Attribute>
+            <Attribute name="comment">à€žà€à€à¥à€·à€¿à€ªà¥à€€ ,  à€­à€Ÿà€·à€Ÿà€à€€à€°à¥à€€  à€¶à¥à€°à¥à€·à€</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Creator">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Creator</Attribute>
+            <Attribute name="definition">An entity primarily responsible for making the content of the resource.</Attribute>
+            <Attribute name="comment">Examples of a Creator include a person, an organisation, or a service. Typically, the name of a Creator should be used to indicate the entity.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Kaihanga</Attribute>
+            <Attribute name="definition">Te putahi, nana, na ratou ranei i matua oti ai te hanganga o te rauemi.</Attribute>
+            <Attribute name="comment">Ko te tangata, he putahitanga, he ratonga ranei etahi tauira Kaihanga. Ko te tikanga, ko te Kaihanga te ingoa ka whakamahia hei tohu i te putahi na ratou te hanganga.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">CrÃ©ateur</Attribute>
+            <Attribute name="definition">L&apos;entitÃ© principalement responsable de la crÃ©ation du contenu de la ressource.</Attribute>
+            <Attribute name="comment">Exemples de CrÃ©ateur incluent une personne, une organisation, ou un service. Typiquement, un nom du CrÃ©ateur devrait Ãªtre utilisÃ© pour dÃ©signer cette entitÃ©.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">Ð¡ÐŸÐ·ÐŽÐ°ÑÐµÐ»Ñ</Attribute>
+            <Attribute name="definition">ÐÐžÑÐŸ, ÐœÐµÑÑÑÐµÐµ Ð¿ÐµÑÐ²ÐžÑÐœÑÑ ÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÐŸÑÑÑ Ð·Ð° ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÑÐžÐŒÐµÑÑ Ð¡ÐŸÐ·ÐŽÐ°ÑÐµÐ»Ñ Ð²ÐºÐ»ÑÑÐ°ÑÑ Ð¿ÐµÑÑÐŸÐœÑ, ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÑ ÐžÐ»Ðž ÑÐ»ÑÐ¶Ð±Ñ. ÐÐ±ÑÑÐœÐŸ ÐžÐŒÑ Ð¡ÐŸÐ·ÐŽÐ°ÑÐµÐ»Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÐžÐœÐŽÐžÐºÐ°ÑÐžÐž ÐŸÐ±ÑÐµÐºÑÐ°.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Autor o Creador</Attribute>
+            <Attribute name="definition">La persona u organizaciÃ³n responsable de la creaciÃ³n del contenido intelectual del recurso. Por ejemplo, los autores en el caso de documentos escritos, artistas, fotografos e ilustradores en el caso de recursos visuales.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙÙØ§ØªØš Ø§Ù Ø§ÙÙ
+ØšØ¯Ø¹</Attribute>
+            <Attribute name="definition">ÙÙ Ø§ÙØŽØ®Øµ Ø§Ù Ø§ÙÙ
+Ø€Ø³Ø³Ø© Ø£ÙÙØ§  Ø¹Ù ÙØŽØŠ Ø§ÙÙ
+Ø­ØªÙÙ Ø§ÙÙÙØ± Ù ÙÙÙ
+ØµØ¯Ø± , Ø¹ÙÙ Ø³ØšÙÙ Ø§ÙÙ
+Ø«Ø§Ù , Ø§ÙÙ
+Ø€ÙÙÙÙ ÙÙ Ø­Ø§ÙØ© Ø§ÙØ«Ø§ØŠÙ Ø§ÙÙ
+ÙØªÙØšØ© , Ù Ø§ÙÙÙØ§ÙÙÙ , Ø§ÙÙ
+ØµÙØ±ÙÙ ÙÙ Ø­Ø§ÙØ© Ø§ÙÙ
+ØµØ§Ø¯Ø± Ø§ÙÙ
+Ø±ØŠÙØ©</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">åå»ºè
+</Attribute>
+            <Attribute name="definition">åå»ºèµæºå
+å®¹çäž»èŠèŽ£ä»»è
+ã</Attribute>
+            <Attribute name="comment">åå»ºè
+çå®äŸå
+æ¬äžªäººïŒç»ç»ææé¡¹æå¡ãäžè¬èèšïŒçšåå»ºè
+çåç§°æ¥æ è¯è¿äžæ¡ç®ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">TvÅ¯rce</Attribute>
+            <Attribute name="definition">Entita primÃ¡rnÄ odpovÄdnÃ¡ za vytvoÅenÃ­ obsahu zdroje.</Attribute>
+            <Attribute name="comment">PÅÃ­klady TvÅ¯rce zahrnujÃ­ osobu, organizaci nebo sluÅŸbu. K oznaÄenÃ­ entity se typicky pouÅŸÃ­vÃ¡ jmÃ©no tvÅ¯rce.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Auteur of maker</Attribute>
+            <Attribute name="definition">De auteur, maker of organisatie die primair verantwoordelijk is voor de intellectuele inhoud van het werk. Bijvoorbeeld auteurs in geval van geschreven documenten, artiesten, fotografen of illustrators in geval van visuele bronnen.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Creator</Attribute>
+            <Attribute name="definition">Le entitate primarimente responsabile pro producer le contento del ressource.</Attribute>
+            <Attribute name="comment">Exemplos de creator include un persona, un organization, o un servicio. Typicamente se utiliza un nomine de creator pro indicar iste entitate.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€šà€¿à€°à¥à€®à€Ÿà€€à€Ÿ, à€à€šà€</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à€Ÿ à€šà€¿à€°à¥à€®à€Ÿà€£  à€à€°à€£à€Ÿà€°à€Ÿ</Attribute>
+            <Attribute name="comment">à€à€Šà€Ÿ.  à€²à¥à€à€, à€²à¥à€à€¿à€à€Ÿ,  à€µà¥à€¯à€à¥à€€à¥, à€žà€à€žà¥à€¥à€Ÿ,  à€žà€à€ªà€Ÿà€Šà€, à€žà€à€ªà€Ÿà€Šà€¿à€à€Ÿ</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Function">
+        <Attribute language="en" name="label">Function</Attribute>
+        <Attribute language="en" name="obligation">Mandatory</Attribute>
+        <Attribute language="en" name="definition">The business function of the organisation to which the resource relates</Attribute>
+        <Attribute language="en" name="comment">Used to indicate the business role of the resource in terms of business functions and activities. Functions are the major units of activity which organisations pursue in order to meet the mission and goals of the organisation. They are defined in the Australian Records Management Standard [AS4390] as the largest unit of business activity in an organisation. Recommended best practice is to select a value from a controlled vocabulary or formal classification scheme. Resources being described within the NZ Government should use the Functions of New Zealand (FONZ) thesaurus. Use of this encoding scheme is mandatory for metadata prepared for use by the NZ Government Portal.</Attribute>
+    </Element>
+    <Element name="Subject">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Subject and Keywords</Attribute>
+            <Attribute name="definition">The topic of the content of the resource.</Attribute>
+            <Attribute name="comment">Typically, a Subject will be expressed as keywords, key phrases or classification codes that describe a topic of the resource. Recommended best practice is to select a value from a controlled vocabulary or formal classification scheme.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Kaupapa</Attribute>
+            <Attribute name="definition">Te take/ nga take o te kaupapa, o te rauemi.</Attribute>
+            <Attribute name="comment">Ko te tikanga, ka whakaaturia te kaupapa o te rauemi e nga kupu matua, nga kimahi matua, nga tohu wehewehenga whakaahua ranei.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Sujet</Attribute>
+            <Attribute name="definition">Le sujet du contenu de la ressource.</Attribute>
+            <Attribute name="comment">Typiquement, le sujet sera dÃ©crit par un ensemble de mots-clefs ou de phrases ou un code de classification qui prÃ©cisent le sujet de la ressource. L&apos;utilisation de vocabulaires contrÃŽlÃ©s et de schÃ©mas formels de classification est encouragÃ©e.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÑÐµÐŽÐŒÐµÑ Ðž ÐºÐ»ÑÑÐµÐ²ÑÐµ ÑÐ»ÐŸÐ²Ð°</Attribute>
+            <Attribute name="definition">Ð¢ÐµÐŒÐ° ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÐ±ÑÑÐœÐŸ ÐÑÐµÐŽÐŒÐµÑ Ð²ÑÑÐ°Ð¶Ð°ÐµÑÑÑ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÐºÐ»ÑÑÐµÐ²ÑÑ
+ ÑÐ»ÐŸÐ², ÐºÐ»ÑÑÐµÐ²ÑÑ
+ ÑÑÐ°Ð· ÐžÐ»Ðž  ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐŸÐœÐœÑÑ
+ ÐºÐŸÐŽÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÐŸÐ¿ÐžÑÑÐ²Ð°ÑÑ ÑÐµÐŒÑ ÑÐµÑÑÑÑÐ°. ÐÐ»Ñ Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ Ð²ÑÐ±ÐžÑÐ°ÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐžÐ· ÐºÐŸÐœÑÑÐŸÐ»ÐžÑÑÐµÐŒÐŸÐ³ÐŸ ÑÐ»ÐŸÐ²Ð°ÑÑ ÐžÐ»Ðž ÑÐŸÑÐŒÐ°Ð»ÑÐœÐŸÐ¹ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÑÑ
+ÐµÐŒÑ.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Claves</Attribute>
+            <Attribute name="definition">Los tÃ³picos del recurso. TÃ­picamente, Subject expresarÃ¡ las claves o frases que describen el tÃ­tulo o el contenido del recurso. Se fomentarÃ¡ el uso de vocabularios controlados y de sistemas de clasificaciÃ³n formales. Se pueden ver ejemplos de vocabularios controlados en: Controlled vocabularies, thesauri and classification systems available in the WWW. DC Subject</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙÙ
+ÙØ¶ÙØ¹ Ù Ø§ÙÙÙÙ
+Ø§Øª Ø§ÙØ±ØŠÙØ³ÙØ©</Attribute>
+            <Attribute name="definition">ÙÙ Ù
+ÙØ¶ÙØ¹ Ø§ÙÙ
+ØµØ¯Ø±. ÙÙ
+ÙØ°Ø¬ÙØ§  ÙØ¹ØšØ± Ø¹Ù Ø§ÙÙ
+ÙØ¶ÙØ¹ ØšØ§Ø³ØªØ®Ø¯Ø§Ù
+Ù
+ÙØªØ§Ø­  Ø§ÙÙÙÙ
+Ø§Øª  Ø§Ù Ø¬Ù
+Ù Ø§ÙØªÙ  ØªØµÙ Ù
+ÙØ¶ÙØ¹ Ø§Ù Ù
+Ø­ØªÙÙ Ø§ÙÙ
+ØµØ¯Ø± , Ù ÙØ³ØªØ­Ø³Ù Ø§Ø³ØªØ®Ø¯Ø§Ù
+ Ù
+ÙØ±Ø¯Ø§Øª Ù
+Ø®Ø·Ø·Ø©Ù Ù
+Ø­ÙÙ
+Ø©  ÙØ§Ø¯ÙØ© ØªØµÙÙÙ ØŽÙÙÙØ©</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">äž»é¢åå
+³é®è¯</Attribute>
+            <Attribute name="definition">èµæºå
+å®¹çäž»é¢æè¿°ã</Attribute>
+            <Attribute name="comment">åŠæèŠæè¿°ç¹å®èµæºçæäžäž»é¢ïŒäžè¬éçšå
+³é®è¯ãå
+³é®å­ç­è¯­æåç±»å·ïŒæå¥œäž»é¢åå
+³é®è¯ä»åæ§    è¯è¡šæè§èçåç±»äœç³»äž­ååŒã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">PÅedmÄt a klÃ­ÄovÃ¡ slova</Attribute>
+            <Attribute name="definition">TÃ©ma obsahu zdroje.</Attribute>
+            <Attribute name="comment">PÅedmÄt bude typicky vyjÃ¡dÅen pomocÃ­ klÃ­ÄovÃœch slov, klÃ­ÄovÃœch frÃ¡zÃ­ nebo klasifikaÄnÃ­ch znakÅ¯ popisujÃ­cÃ­ch tÃ©ma zdroje. DoporuÄuje se vybÃ­rat hodnotu prvku z ÅÃ­zenÃ©ho slovnÃ­ku nebo formÃ¡lnÃ­ho klasifikaÄnÃ­ho schÃ©matu.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Onderwerp en trefwoorden</Attribute>
+            <Attribute name="definition">Het onderwerp van de Internetbron. Het onderwerp wordt beschreven in korte zinnen of door het gebruik van trefwoorden. Het gebruik van gecontroleerde trefwoorden of classificatie schema&apos;s wordt aanbevolen.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Subjecto e parolas-clave</Attribute>
+            <Attribute name="definition">Le topico del contento del ressource.</Attribute>
+            <Attribute name="comment">Typicamente le subjecto es expresse per medio de parolas-clave, phrases-clave, o codices de classification que describe le topico del ressource. Le melior practica recommendate es selectionar un valor a partir de un vocabulario controlate o un schema formal de classification.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€µà€¿à€·à€¯</Attribute>
+            <Attribute name="definition">à€µà€¿à€·à€¯</Attribute>
+            <Attribute name="comment">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à€Ÿ, à€à¥à€à€Ÿà€šà€žà€Ÿà€§à€šà¥ à€¯à€Ÿà€€à¥à€² à€à€¶à€¯ à€žà¥à€ªà€·à¥à€ à€à€°à€£à€Ÿà€°à¥ à€¶à€¬à¥à€Š, à€µà€¿à€·à€¯à€Ÿà€à¥ à€µà€°à¥à€à¥à€à€°à€£ à€à€°à€€à€Ÿà€šà€Ÿ à€¶à€¬à¥à€Šà€žà€à€à¥à€°à€¹ à€
+à€¥à€µà€Ÿ à€¶à€¬à¥à€Š à€à¥à€·à€Ÿà€à€Ÿ à€µà€Ÿà€ªà€° à€à€°à€Ÿà€µà€Ÿ</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Description">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Description</Attribute>
+            <Attribute name="definition">An account of the content of the resource.</Attribute>
+            <Attribute name="comment">Description may include but is not limited to: an abstract, table of contents, reference to a graphical representation of content or a free-text account of the content.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Whakaaturanga</Attribute>
+            <Attribute name="definition">He whakaaturanga o nga kaupapa o te rauemi.</Attribute>
+            <Attribute name="comment">Ka uru atu, engari ehara noa ko: te whakarapopototanga korero, te ihirangi, te tohutanga o te kaupapa ma te whakaahua, te whakaaturanga kore kupu ranei, o te kauapapa.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Description</Attribute>
+            <Attribute name="definition">Une description du contenu de la ressource.</Attribute>
+            <Attribute name="comment">Une Description peut contenir, mais ce n&apos;est pas limitatif: un rÃ©sumÃ©, une table des matiÃšres, une rÃ©fÃ©rence Ã  une reprÃ©sentation graphique du contenu, ou un texte libre sur le contenu.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÐ¿ÐžÑÐ°ÐœÐžÐµ</Attribute>
+            <Attribute name="definition">Ð¡ÐŸÐŸÐ±ÑÐµÐœÐžÐµ ÐŸ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐž ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÐ¿ÐžÑÐ°ÐœÐžÐµ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐŸ (Ð¿ÐŸ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÑÑÐž) Ð² Ð²ÐžÐŽÐµ: ÑÐµÑÐµÑÐ°ÑÐ°, ÐŸÐ³Ð»Ð°Ð²Ð»ÐµÐœÐžÑ, ÑÑÑÐ»ÐºÐž ÐœÐ° Ð³ÑÐ°ÑÐžÑÐµÑÐºÐŸÐµ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÐžÐ»Ðž Ð¿ÑÐŸÑÑÐŸÐ³ÐŸ ÑÐµÐºÑÑÐŸÐ²ÐŸÐ³ÐŸ ÐžÐ·Ð»ÐŸÐ¶ÐµÐœÐžÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">DescripciÃ³n</Attribute>
+            <Attribute name="definition">Una descripciÃ³n textual del recurso, tal como un resumen en el caso de un documento o una descripciÃ³n del contenido en el caso de un documento visual.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙÙØµÙ</Attribute>
+            <Attribute name="definition">ÙÙ ÙØµÙ ÙØµÙ  ÙÙ
+Ø­ØªÙÙ Ø§ÙÙ
+ØµØ¯Ø±, ÙÙØ¶Ù
+ Ø§ÙÙ
+ÙØ®ØµØ§Øª ÙÙ Ø­Ø§ÙØ© Ø§ÙÙØ«Ø§ØŠÙ Ù
+Ø«Ù Ø§ÙØ§ØŽÙØ§Ø¡ Ø§ÙÙ
+ÙØªÙØšØ© Ø§Ù ØªÙØµÙÙ Ø§ÙÙ
+Ø­ØªÙÙ ÙÙ Ø­Ø§ÙØ© Ø§ÙÙ
+ØµØ§Ø¯Ø± Ø§ÙÙ
+Ø±ØŠÙØ©</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">è¯Žæ</Attribute>
+            <Attribute name="definition">èµæºå
+å®¹çè§£é</Attribute>
+            <Attribute name="comment">è¯Žæå¯ä»¥å
+æ¬äœäžéäºä»¥äžå
+å®¹ïŒææãç®åœãå¯¹ä»¥åŸåœ¢æ¥æ­ç€ºå
+å®¹çèµæºèèšçæå­è¯Žæãæè
+äž    äžªæå
+³èµæºå
+å®¹çèªç±ææ¬æè¿°ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">Popis</Attribute>
+            <Attribute name="definition">VysvÄtlenÃ­ obsahu zdroje.</Attribute>
+            <Attribute name="comment">Popis mÅ¯ÅŸe obsahovat (mimo jinÃ©): abstrakt, obsah, odkaz na grafickÃ© nebo volnÃ© textovÃ© vyjÃ¡dÅenÃ­ obsahu.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Omschrijving</Attribute>
+            <Attribute name="definition">Een omschrijving van de inhoud van de Internetbron. Abstracts of inhoudsomschrijvingen.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Description</Attribute>
+            <Attribute name="definition">Un description del contento del ressource.</Attribute>
+            <Attribute name="comment">Le description pote includer, ma non se limita a: summario, indice, referentia a un representation graphic del contento o un texto libere a proposito del contento.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€µà€°à¥à€£à€š</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à¥, à€à¥à€à€Ÿà€šà€žà€Ÿà€§à€šà€Ÿà€à¥à€µà€°à¥à€£à€š</Attribute>
+            <Attribute name="comment">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à¥ à€šà€¿à€µà¥à€Šà€š, à€à€²à¥à€, à€à€¿à€€à¥à€°à€°à¥à€ª</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Publisher">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Publisher</Attribute>
+            <Attribute name="definition">An entity responsible for making the resource available.</Attribute>
+            <Attribute name="comment">Examples of a Publisher include a person, an organisation, or a service. Typically, the name of a Publisher should be used to indicate the entity.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Kaiwhakaputa</Attribute>
+            <Attribute name="definition">Te putahi nana i whakaputa te rauemi.</Attribute>
+            <Attribute name="comment">Ko te tangata, he putahitanga, he ratonga ranei etahi tauira Kaiwhakaputa. Ko te tikanga, ka whakamahia te ingoa o te Kaiwhakaputa hei tohu i te putahi.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Editeur</Attribute>
+            <Attribute name="definition">L&apos;entitÃ© responsable de la diffusion de la ressource, dans sa forme actuelle, tels, un dÃ©partement universitaire, une entreprise.</Attribute>
+            <Attribute name="comment">Exemples d&apos;Editeurs incluent une personne, une organisation, ou un service. Typiquement, le nom d&apos;une maison d&apos;Ã©dition devrait Ãªtre utilisÃ© ici.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÐ·ÐŽÐ°ÑÐµÐ»Ñ</Attribute>
+            <Attribute name="definition">ÐÐžÑÐŸ, ÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÐŸÐµ Ð·Ð° Ð²Ð²ÐŸÐŽ ÑÐµÑÑÑÑÐ° Ð² ÐŸÐ±ÑÐ°ÑÐµÐœÐžÐµ.</Attribute>
+            <Attribute name="comment">ÐÑÐžÐŒÐµÑÑ ÐÐ·ÐŽÐ°ÑÐµÐ»Ñ Ð²ÐºÐ»ÑÑÐ°ÑÑ Ð¿ÐµÑÑÐŸÐœÑ, ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÑ ÐžÐ»Ðž ÑÐ»ÑÐ¶Ð±Ñ. ÐÐ±ÑÑÐœÐŸ ÐžÐŒÑ ÐÐ·ÐŽÐ°ÑÐµÐ»Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÐžÐœÐŽÐžÐºÐ°ÑÐžÐž ÐŸÐ±ÑÐµÐºÑÐ°.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Editor</Attribute>
+            <Attribute name="definition">&gt;La entidad responsable de hacer que el recurso se encuentre disponible en la red en su formato actual, por ejemplo la empresa editora, un departamento universitario u otro tipo de organizaciÃ³n.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙÙØ§ØŽØ±</Attribute>
+            <Attribute name="definition">ÙÙ Ø§ÙÙÙØŠØ© Ø§ÙÙ
+Ø³Ø€ÙÙØ© Ø¹Ù ØµÙØ§Ø¹Ø© Ø§ÙÙ
+ØµØ¯Ø± Ø§ÙÙ
+ØªÙÙØ± ÙÙ Ø­Ø§ÙØªÙ Ø§ÙØ­Ø§Ø¶Ø±Ø©, Ù
+Ø«Ù Ø¯Ø§Ø± Ø§ÙÙØŽØ±, ÙØ³Ù
+ Ø¬Ø§Ù
+Ø¹Ù Ø§Ù Ù
+Ø€Ø³Ø³Ø© Ø§Ø¹Ù
+Ø§Ù</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">åºçè
+</Attribute>
+            <Attribute name="definition">äœ¿èµæºæäžºå¯ä»¥è·åŸå¹¶å¯çšçèŽ£ä»»è
+ã</Attribute>
+            <Attribute name="comment">åºçè
+çå®äŸå
+æ¬äžªäœïŒç»ç»ïŒææå¡ãäžè¬èèšïŒåºè¯¥çšåºçè
+çåç§°æ¥æ è¯è¿äžæ¡ç®ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">Vydavatel</Attribute>
+            <Attribute name="definition">Entita odpovÄdnÃ¡ za zpÅÃ­stupnÄnÃ­ zdroje.</Attribute>
+            <Attribute name="comment">PÅÃ­klady Vydavatele zahrnujÃ­ osobu, organizaci nebo sluÅŸbu. K oznaÄenÃ­ entity se typicky pouÅŸÃ­vÃ¡ jmÃ©no vydavatele.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Uitgever</Attribute>
+            <Attribute name="definition">De entiteit die verantwoordelijk is voor het beschikbaarstellen van de Internetbron in de huidig vorm. Bijvoorbeeld een uitgeversbedrijf, een universiteitsafdeling.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Editor</Attribute>
+            <Attribute name="definition">Un entitate responsabile pro disponibilizar le ressource.</Attribute>
+            <Attribute name="comment">Exemplos de editor include un persona, un organization, o un servicio. Typicamente se utiliza un nomine de editor pro indicar le entitate.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€ªà¥à€°à€à€Ÿà€¶à€</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à€Ÿ  à€à€ªà€²à€¬à¥à€§ à€à€°à¥à€š à€Šà¥à€£à€Ÿà€°à€Ÿ</Attribute>
+            <Attribute name="comment">à€à€Šà€Ÿ.à€ à€ªà¥à€°à€à€Ÿà€¶à€ , à€ªà¥à€°à€à€Ÿà€¶à€š  à€žà€à€žà¥à€¥à€Ÿ, à€žà¥à€µà€Ÿ    à€®à€Ÿà€¹à€¿à€€à¥ à€à€Ÿà€ªà¥à€² à€°à¥à€ªà€Ÿà€€  à€
+à€¥à€µà€Ÿ à€à€à€à€°à€šà¥à€ à€µà€° à€à€ªà€²à€¬à¥à€§ à€à€°à¥à€š à€Šà¥à€£à€Ÿà€°à€Ÿ</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Mandate">
+        <Attribute language="en" name="label">Mandate</Attribute>
+        <Attribute language="en" name="obligation">Recommended</Attribute>
+        <Attribute language="en" name="definition">A specific warrant which requires the resource to be created or provided.</Attribute>
+        <Attribute language="en" name="comment">The element is useful to indicate the specific legal mandate that requires the resource being described to be created or provided to the public. The content of this element will usually be a reference to a specific Act, Regulation or Case, but may be a URI pointing to the legal instrument in question.</Attribute>
+        <Element name="act">
+            <Attribute language="en" name="label">Act</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">A reference to a specific Act of Parliament which requires the creation or provision of the resource.</Attribute>
+            </Language>
+        </Element>
+        <Element name="regulation">
+            <Attribute language="en" name="label">Regulation</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">A reference to a specific regulation which requires the creation or provision of the resource.</Attribute>
+            </Language>
+        </Element>
+        <Element name="rules">
+            <Attribute language="en" name="label">Rules</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">The specific rule or bylaw which requires the creation or provision of the resource.</Attribute>
+            </Language>
+        </Element>
+        <Element name="case">
+            <Attribute language="en" name="label">Case Law</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">A reference to a specific case which requires the creation or provision of the resource.</Attribute>
+            </Language>
+        </Element>
+    </Element>
+    <Element name="Contributor">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Contributor</Attribute>
+            <Attribute name="definition">An entity responsible for making contributions to the content of the resource.</Attribute>
+            <Attribute name="comment">Examples of a Contributor include a person, an organisation, or a service. Typically, the name of a Contributor should be used to indicate the entity.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Kaiwhakaaro</Attribute>
+            <Attribute name="definition">Te putahi nana, na ratou ranei nga whakakaupapatanga whakaaro o te rauemi.</Attribute>
+            <Attribute name="comment">Ko te tangata, he putahitanga, he ratonga ranei etahi tauira Kaiwhakaaro. Ko te tikanga ka whakamahia te ingoa o te Kaiwhakaaro hei tohu i te putahi.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Contributeur</Attribute>
+            <Attribute name="definition">Une entitÃ© qui a contribuÃ© Ã  la crÃ©ation du contenu de la ressource.</Attribute>
+            <Attribute name="comment">Exemples de Contributeur incluent une personne, une organisation, ou un service. Typiquement, le nom d&apos;un contributeur devrait Ãªtre utilisÃ© ici pour dÃ©signer l&apos;entitÃ©.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">Ð¡ÐŸÐžÑÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»Ñ</Attribute>
+            <Attribute name="definition">ÐÐžÑÐŸ, Ð²ÐœÐµÑÑÐµÐµ Ð²ÐºÐ»Ð°ÐŽ Ð² ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÑÐžÐŒÐµÑÑ Ð¡ÐŸÐžÑÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»Ñ Ð²ÐºÐ»ÑÑÐ°ÑÑ Ð¿ÐµÑÑÐŸÐœÑ, ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÑ ÐžÐ»Ðž ÑÐ»ÑÐ¶Ð±Ñ. ÐÐ±ÑÑÐœÐŸ ÐžÐŒÑ Ð¡ÐŸÐžÑÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÐžÐœÐŽÐžÐºÐ°ÑÐžÐž ÐŸÐ±ÑÐµÐºÑÐ°.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Otros Colaboradores</Attribute>
+            <Attribute name="definition">Una persona u organizacion que haya tenido una contribuciÃ³n intelectual significativa en la creaciÃ³n del recurso pero cuyas contribuciones son secundarias en comparaciÃ³n a las de las personas u organizaciones especificadas en el elementeo Creator (por ejemplo, editor, ilustrador y traductor).</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙÙ
+Ø³Ø§ÙÙ
+ Ø§ÙØ§Ø®Ø±</Attribute>
+            <Attribute name="definition">ÙÙ Ø§ÙØŽØ®Øµ Ø§Ù Ø§ÙÙ
+Ø€Ø³Ø³Ø© Ø§ÙØºÙØ± Ù
+Ø°ÙÙØ± ØµØ±Ø§Ø­Ø© ÙÙ Ø¹Ø§Ù
+Ù &quot; Ø§ÙÙ
+ØšØ¯Ø¹ &quot; Ù Ø§ÙØ°Ù ÙØ¯Ù
+ Ù
+Ø³Ø§ÙÙ
+Ø§Øª ÙÙØ±ÙØ© ÙØ§Ù
+Ø© ÙÙÙ
+ØµØ¯Ø±, ÙÙÙ Ù
+Ø³Ø§ÙÙ
+ØªÙØªØšÙÙ    Ø«Ø§ÙÙÙØ© Ù
+ÙØ§Ø±ÙØ© Ù
+Ø¹ Ø§ÙØŽØ®Øµ Ø£Ù Ø§ÙÙ
+Ø€Ø³Ø³Ø© Ø§ÙÙ
+Ø°ÙÙØ±Ø© ÙØµØ§ ÙÙ Ø¹Ø§Ù
+Ù &quot; Ø§ÙÙ
+ÙØŽØŠ &quot; Ù
+Ø«ÙØ§Ù Ù
+ØµØ­Ø­, Ø§ÙÙ
+ØªØ±Ø¬Ù
+, Ø§Ù Ø§ÙÙ
+ÙØ³Ø±</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">å
+¶ä»èŽ£ä»»è
+</Attribute>
+            <Attribute name="definition">å¯¹èµæºçå
+å®¹äœåºèŽ¡ç®çå
+¶ä»å®äœã</Attribute>
+            <Attribute name="comment">å
+¶ä»èŽ£ä»»è
+çå®äŸå¯å
+æ¬äžªäººãç»ç»ææé¡¹æå¡ãäžè¬èèšïŒçšå
+¶ä»èŽ£ä»»è
+çåå­æ¥æ è¯è¿äžæ¡ç®ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">PÅispÄvatel</Attribute>
+            <Attribute name="definition">Entita, kterÃ¡ pÅispÄla k vytvoÅenÃ­ obsahu zdroje.</Attribute>
+            <Attribute name="comment">PÅÃ­klady PÅispÄvatele zahrnujÃ­ osobu, organizaci nebo sluÅŸbu. K oznaÄenÃ­ entity se typicky pouÅŸÃ­vÃ¡ jmÃ©no pÅispÄvatele.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Andere medewerkers</Attribute>
+            <Attribute name="definition">Een persoon of organisatie die een belangrijke bijdrage heeft geleverd, maar die secondair is aan de persoon of organisatie die bij &quot;Creator&quot; genoemd wordt. Gedacht kan worden aan editors, vertalers en illustrators.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Contribuente</Attribute>
+            <Attribute name="definition">Un entitate responsabile pro facer contributiones al contento del ressource.</Attribute>
+            <Attribute name="comment">Exemplos de contribuente include un persona, un organization, o un servicio. Typicamente se utiliza un nomine de contribuente pro indicar le entitate.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label"> à€žà€¹à€¯à¥à€à€, à€žà€¹à€¯à¥à€à¥, à€žà€¹à€Ÿà€¯à¥à€¯à€</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à€Ÿ à€žà€à€à€²à¥à€€ à€à€°à€£à¥à¥à€Ÿà€ž  à€®à€Šà€€ à€à€°à€£à€Ÿà€°à¥ à€µà¥à€¯à€à¥à€€à¥</Attribute>
+            <Attribute name="comment">à€à€Šà€Ÿ.à€ à€µà¥à€¯à€à¥à€€à¥, à€žà¥à€µà€Ÿ, à€žà€à€žà¥à€¥à€Ÿ</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Date">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Date</Attribute>
+            <Attribute name="definition">A date associated with an event in the life cycle of the resource.</Attribute>
+            <Attribute name="comment">Typically, Date will be associated with the creation or availability of the resource.  Recommended best practice for encoding the date value is defined in a profile of ISO 8601 and follows the YYYY-MM-DD format.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Ra</Attribute>
+            <Attribute name="definition">He ra e whai panga ana ki te huringa ora o te rauemi.</Attribute>
+            <Attribute name="comment">Ko te tikanga, ka whai panga te ra ki te hanganga, te wateatanga ranei, o te rauemi. Ko te huarahi tino pai hei tohu i te uara o te ra (date value) kua whakaritea i roto i te whakaritenga IS0 8601 [W3CDTF], a, e whai atu ana ki te whakatakotoranga YYYY-MM-DD.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Date</Attribute>
+            <Attribute name="definition">Une date associÃ©e avec un Ã©vÃ©nement dans le cycle de vie de la ressource.</Attribute>
+            <Attribute name="comment">Typiquement, une date sera associÃ©e Ã  la crÃ©ation ou Ã  la publication d&apos;une ressource. Il est fortement recommandÃ© d&apos;encoder la valeur de la date en utilisant le format dÃ©fini par l&apos;ISO 8601 [W3CDTF] sous la forme AAAA-MM-JJ.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÐ°ÑÐ°</Attribute>
+            <Attribute name="definition">ÐÐ°ÑÐ°, ÑÐ²ÑÐ·Ð°ÐœÐœÐ°Ñ Ñ ÑÐŸÐ±ÑÑÐžÐµÐŒ Ð² Ð¶ÐžÐ·ÐœÐµÐœÐœÐŸÐŒ ÑÐžÐºÐ»Ðµ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÐ±ÑÑÐœÐŸ ÐÐ°ÑÐ° Ð°ÑÑÐŸÑÐžÐžÑÑÐµÑÑÑ Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµÐŒ ÐžÐ»Ðž ÐŽÐŸÑÑÑÐ¿ÐœÐŸÑÑÑÑ ÑÐµÑÑÑÑÐ°. ÐÐ° Ð¿ÑÐ°ÐºÑÐžÐºÐµ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ ÐŽÐ»Ñ ÐºÐŸÐŽÐžÑÐŸÐ²ÐºÐž Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŽÐ°ÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÐµ Ð¿ÑÐŸÑÐžÐ»Ñ ISO 8601 (Ð€ÐŸÑÐŒÐ°ÑÑ ÐŽÐ°ÑÑ Ðž Ð²ÑÐµÐŒÐµÐœÐž W3C), ÐºÐŸÑÐŸÑÐŸÐµ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÐµÑ ÑÐŸÑÐŒÐ°Ñ ÐÐÐÐ-ÐÐ-ÐÐ.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Fecha</Attribute>
+            <Attribute name="definition">Una fecha en la que el recurso se puso a disposiciÃ³n del usuario en su forma actual. Esta fecha no ha de confundirse con la que pertenece al elemento Coverage, que serÃ­a asociada con el recurso sÃ³lo en la medida en que el contenido intelectual estÃ¡ de algÃºn modo relacionado con esa fecha. Recomendamos la utiliazaciÃ³n de uno de los formatos definidos en el documento &quot;Date and Time Formats&quot;, http://www.w3.org/TR/NOTE-datetime basado en la norma ISO 8601 que incluye, entre otras, fechas en el formato AAAA y AAAA-MM-DD. De esta forma la fecha 1994-11-05 corresponderÃ­a al 5 de Noviembre de 1994.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙØªØ§Ø±Ø®</Attribute>
+            <Attribute name="definition">ÙÙ Ø§ÙØªØ§Ø±ÙØ® Ø§ÙÙ
+ØªØ¹ÙÙ ØšÙÙØª ÙØŽØŠ Ø£Ù ØªÙÙØ± Ø§ÙÙ
+ØµØ¯Ø± . Ù ÙØ¬Øš Ø£Ù ÙØ§ ÙØ®ÙØ· ÙØ°Ø§ Ø§ÙØªØ§Ø±ÙØ® Ø§ÙØ¹Ø§ØŠØ¯ ÙØ¹Ø§Ù
+Ù Ø§ÙØªØºØ·ÙØ© , Ù Ø§ÙØ° Ù ÙØ¬Øš Ø£Ù    ÙÙØ­Ù ØšØ§ÙÙ
+ØµØ¯Ø± ÙÙØ· Ù
+Ù ÙØ§Ø­ÙØ© Ø§ÙÙ
+Ø­ØªÙÙØ§ÙÙÙØ±Ù ÙÙÙÙÙ ÙÙØ¹Ø§ Ù
+Ø§ ÙÙ ÙØ°Ø§ Ø§ÙØªØ§Ø±ÙØ®. Ø§ÙØµÙØºØ© Ø§ÙÙ
+Ø³Ø«Ø­Ø³ÙØ© ÙÙØ§Ø­Ø³Ù Ø§ÙÙ
+ØªØ¹Ø§Ø±Ù Ø¹ÙÙÙ    Ø¹ÙØ¯ Ø§ÙØªØ·ØšÙÙ ÙÙ Ø§ÙØµÙØºØ© Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø© ÙÙ ØªØŽÙÙÙ (ISO 8601) ØµÙØºØ© ØªØ§Ø±ÙØ® Ø§ÙÙÙÙ
+ Ù Ø§ÙÙÙØª ) Ø§Ø¹ØªÙ
+Ø§Ø¯Ø§ Ø¹ÙÙ (ISO 8601) Ø§ÙÙ
+ÙØ§Ø­ØžØ© Ø§ÙÙÙÙØ© http://www.w3.org/TR/NOTE-datetime, W3C. ÙÙÙ    ÙØ°Ø§ Ø§ÙÙØ³Ù , Ù
+Ø«ÙØ§, ØªØ§Ø±ÙØ® Ø§ÙÙÙÙ
+ 1994-11-04 ÙÙØ§ØžØ± ÙÙÙ
+ 5 ÙÙÙÙ
+ØšØ± 1994</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">æ¥æ</Attribute>
+            <Attribute name="definition">äžèµæºçåœåšæäž­çäžäžªäºä»¶çžå
+³çæ¶éŽã</Attribute>
+            <Attribute name="comment">äžè¬èèšïŒæ¥æåºäžèµæºçåå»ºæåºçæ¥æçžå
+³ãå»ºè®®éçšçæ¥ææ ŒåŒåºç¬ŠåISO 8601 [W3CDTF]è§    èïŒå¹¶äœ¿çšYYYY-MM-DDçæ ŒåŒã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">Datum</Attribute>
+            <Attribute name="definition">Datum spojenÃ© s urÄitou udÃ¡lostÃ­ bÄhem existence zdroje.</Attribute>
+            <Attribute name="comment">Datum bude typicky spojeno s vytvoÅenÃ­m nebo zpÅÃ­stupnÄnÃ­m zdroje. DoporuÄenÃœ postup pro kÃ³dovÃ¡nÃ­ hodnoty data je definovÃ¡n v ISO 8601 [W3CDTF]: formÃ¡t RRRR-MM-DD.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Datum</Attribute>
+            <Attribute name="definition">De datum van de totstandkoming of beschikbaarstelling van een Internetbron. Deze datum moet niet verward worden met de datum in &quot;Coverage&quot;. De datum in &quot;Coverage&quot; geeft de tijdsperiode van de inhoud van de Internetbron aan. Voorgeschreven wordt de ISO 8601 standaard voor datum, zoals beschreven in W3C Technical Note http://www.w3.org/TR/NOTE-datetime. Hierin wordt het formaat YYYY-MM-DD beschreven. Het formaat YYYY-MM-DD wordt de voorgeschreven standaard. 3 September 1998 wordt in dit geval 1998-09-03.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Data</Attribute>
+            <Attribute name="definition">Un data associate a un evento in le cyclo vital del ressource.</Attribute>
+            <Attribute name="comment">Typicamente le data es associate al creation o disponibilization del ressource. Le practica recommendate pro codificar le valor del datas es definite in un profilo de ISO 8601 [W3CDTF] e seque le formato AAAA-MM-DD.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€€à€Ÿà€°à¥à€,  à€Šà€¿à€šà€Ÿà€à€</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à€Ÿ à€€à€¯à€Ÿà€° à€à¥à€²à¥à€¯à€Ÿà€à¥ à€€à€Ÿà€°à¥à€</Attribute>
+            <Attribute name="comment">à€€à€Ÿà€°à¥à€  à€²à€¿à€¹à¥à€£à¥à€¯à€Ÿà€à¥ à€žà¥à€µà€°à¥à€ª à€ à€µà€°à¥à€·. à€®à€¹à€¿à€šà€Ÿ. à€Šà€¿à€µà€ž à¥§à¥¯à¥«à¥Š. à¥Šà¥ª. à¥Šà¥ª</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+        <Element name="created">
+            <Attribute language="en" name="label">Created</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">Date of creation of the resource.</Attribute>
+            </Language>
+        </Element>
+        <Element name="modified">
+            <Attribute language="en" name="label">Modified</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">Date on which the resource was changed.</Attribute>
+            </Language>
+        </Element>
+        <Element name="valid">
+            <Attribute language="en" name="label">Valid</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">Date (often a range) of validity of a resource.</Attribute>
+                <Attribute name="comment">Typically, a date the resource becomes valid or ceases to be valid, or the date range for which the resource is valid.</Attribute>
+            </Language>
+        </Element>
+        <Element name="issued">
+            <Attribute language="en" name="label">Issued</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">Date of formal issuance (e.g. publication) of the resource.</Attribute>
+            </Language>
+        </Element>
+        <Element name="available">
+            <Attribute language="en" name="label">Available</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">Date (often a range) that the resource will become or did become available.</Attribute>
+            </Language>
+        </Element>
+    </Element>
+    <Element name="Type">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Resource Type</Attribute>
+            <Attribute name="definition">The nature or genre of the content of the resource.</Attribute>
+            <Attribute name="comment">Type includes terms describing general categories, functions, genres, or aggregation levels for content. Recommended best practice is to select a value from a controlled vocabulary (for example, the working draft list of Dublin Core Types). To describe the physical or digital manifestation of the resource, use the FORMAT element.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Tumomo</Attribute>
+            <Attribute name="definition">Te ahua, te tu-ahuatanga ranei o nga kaupapa o te rauemi.</Attribute>
+            <Attribute name="comment">Kei roto i te Tumomo nga kupu whakaatu i nga wehewehenga whanui, nga aheinga, nga tu-ahuatanga, te whakaritenga ranei o nga taumata o te/ nga kaupapa. Ko te huarahi tino pai kua tohua, ko te tipako i tetahi uara mai i nga kupu kua whakaritea (hei tauira, ko te tauira rarangi e whakamahia ana o nga Dublin Core Types [DCT1]. Hei whakaatu i te whakatinanatanga o te rauemi, whakamahia ko te huanga WHAKATAKOTORANGA (FORMAT).</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Type</Attribute>
+            <Attribute name="definition">La nature ou le genre du contenu de la ressource.</Attribute>
+            <Attribute name="comment">Type inclut des termes dÃ©crivant des catÃ©gories, fonctions ou genres gÃ©nÃ©raux pour le contenu, ou des niveaux d&apos;agrÃ©gation. Il est recommandÃ© de choisir la valeur du type dans une liste de vocabulaire contrÃŽlÃ© (par exemple, la liste provisoire de Types du Dublin Core[DCT1]). Pour dÃ©crire la matÃ©rialisation physique ou digitale de la ressource, il faut utiliser l&apos;Ã©lÃ©ment Format.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">Ð¢ÐžÐ¿ ÑÐµÑÑÑÑÐ°</Attribute>
+            <Attribute name="definition">ÐÑÐžÑÐŸÐŽÐ° ÐžÐ»Ðž Ð¶Ð°ÐœÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">Ð¢ÐžÐ¿ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÑÐµÑÐŒÐžÐœÑ, ÐŸÐ¿ÐžÑÑÐ²Ð°ÑÑÐžÐµ ÐŸÐ±ÑÐžÐµ ÐºÐ°ÑÐµÐ³ÐŸÑÐžÐž, ÑÑÐœÐºÑÐžÐž, Ð¶Ð°ÐœÑÑ ÐžÐ»Ðž ÐŸÐ±ÑÐµÐŽÐžÐœÐµÐœÐœÑÐµ ÑÑÐŸÐ²ÐœÐž ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ. ÐÐ»Ñ Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ Ð²ÑÐ±ÐžÑÐ°ÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐžÐ· ÐºÐŸÐœÑÑÐŸÐ»ÐžÑÑÐµÐŒÐŸÐ³ÐŸ ÑÐ»ÐŸÐ²Ð°ÑÑ (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÑÐ°Ð±ÐŸÑÐµÐ³ÐŸ Ð¿ÑÐŸÐµÐºÑÐ° ÑÐ¿ÐžÑÐºÐ° Ð¢ÐžÐ¿ÐŸÐ² Dublin Core DCT1). ÐÐ»Ñ ÐŸÐ¿ÐžÑÐ°ÐœÐžÑ ÑÐžÐ·ÐžÑÐµÑ-ÐºÐŸÐ³ÐŸ ÐžÐ»Ðž ÑÐžÑÑÐŸÐ²ÐŸÐ³ÐŸ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ ÑÐµÑÑÑÑÐ° ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÑÐ»ÐµÐŒÐµÐœÑ Ð€ÐŸÑÐŒÐ°Ñ.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Tipo del Recurso</Attribute>
+            <Attribute name="definition">La categorÃ­a del recurso, por ejemplo pÃ¡gina personal, romance, poema, minuta, diccionario. Para asegurar la interoperabilidad, Type deberÃ­a ser seleccionado de entre una lista de valores que actualmente se encuentra bajo desarrollo en un grupo de trabajo. En http://sunsite.berkeley.edu/Metadata/types.html se puede consultar el estado actual de la discusiÃ³n en torno a este tema.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">ÙÙØ¹ Ø§ÙÙ
+ØµØ¯Ø±</Attribute>
+            <Attribute name="definition">ÙÙ ÙØŠØ© Ø§ÙÙ
+ØµØ¯Ø± , Ù
+Ø«ÙØ§ Ø§ÙØµÙØ­Ø© Ø§ÙØ§Ù
+, Ø±ÙØ§ÙØ© , ÙØ·Ø¹Ø© ØŽØ¹Ø±ÙØ© , ÙØ±ÙØ© Ø¹Ù
+Ù , ØªÙØ±ÙØ± ÙÙÙ , Ù
+ÙØ§Ù , ÙØ§Ù
+ÙØ³ . Ù Ù
+Ù Ø£Ø¬Ù Ø§ÙØªØ¹Ø§Ù
+Ù Ø§ÙÙ
+ØŽØªØ±Ù    ÙØ¬Øš Ø£Ù ÙØ®ØªØ§Ø± Ø§ÙÙÙØ¹ Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+Ø±ÙÙ
+Ø© ÙØ§ÙØªÙ ÙÙÙ
+ Ø§Ø¹Ø¯Ø§Ø¯ÙØ§ Ø­Ø§ÙÙØ§ Ø¶Ù
+Ù Ø­ÙÙØ§Øª ÙØ±ØŽØ© Ø¹Ù
+Ù</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">èµæºç±»å</Attribute>
+            <Attribute name="definition">èµæºå
+å®¹çç¹åŸæç±»åã</Attribute>
+            <Attribute name="comment">èµæºç±»åå
+æ¬æè¿°èµæºå
+å®¹çäžè¬èçŽïŒåèœïŒç§å±ïŒæèç±»å±æ¬¡çæ¯è¯­ãå»ºè®®éçšæ¥èªäºåæ§è¯è¡š    äž­çåŒïŒäŸåŠDCMIç±»åè¯æ±è¡š[DCMITYPE]ïŒãèŠæè¿°èµæºçç©çææ°å­åè¡šç°åœ¢åŒïŒè¯·äœ¿çšâæ ŒåŒïŒFORMATïŒâå
+çŽ ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">Typ zdroje</Attribute>
+            <Attribute name="definition">Povaha nebo druh obsahu zdroje.</Attribute>
+            <Attribute name="comment">Typ obsahuje termÃ­ny popisujÃ­cÃ­ obecnÃ© kategorie, funkce, druhy nebo agregaÄnÃ­ ÃºrovnÄ obsahu. DoporuÄuje se vybÃ­rat hodnotu z ÅÃ­zenÃ©ho slovnÃ­ku (napÅ. pracovnÃ­ nÃ¡vrh seznamu TypÅ¯ Dublin Core [DCT1]). K popisu fyzickÃ© nebo digitÃ¡lnÃ­ reprezentace zdroje uÅŸijte prvek FormÃ¡t.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Bestands type</Attribute>
+            <Attribute name="definition">Het soort Internetbron, bijvoorbeeld home page, gedicht, working paper, technical report, essay, woordenboek etc. De DC working groups zijn momenteel bezig met twee voorstellen; een minimalist draft: http://sunsite.berkeley.edu/Metadata/minimalist.html en een structuralist draft: http://sunsite.berkely.edu/Metadata/structuralist.html. Het wordt sterk aanbevolen om &quot;Type&quot; van deze lijsten te selecteren.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Typo del ressource</Attribute>
+            <Attribute name="definition">Le natura o genere del contento del ressource.</Attribute>
+            <Attribute name="comment">Le typo del ressource include terminos que describe categorias general, functiones, generes, o nivellos de aggregation pro le contento. Le practica recommendate es selectionar un valor a partir de un vocabulario controlate (per exemplo, le lista de schizzos de travalio de typos de Dublin Core [DCT1]). Pro describer le manifestation physic o digital del ressource, utiliza le elemento Formato.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€ªà¥à€°à€à€Ÿà€°</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à€Ÿà€ªà¥à€°à€à€Ÿà€°</Attribute>
+            <Attribute name="comment">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à¥ à€µà€°à¥à€à¥à€à€°à€£, à€µà€°à¥à€à€µà€Ÿà€°à¥à€®à€§à¥à€¯à¥ à€à€à€Ÿà€Šà¥à€¯à€Ÿ à€šà¥à€à€Šà¥à€à€Ÿ à€®à¥à€à¥à€¯ à€à€à€ªà¥à€°à€à€Ÿà€°</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+        <Element name="category">
+            <Attribute language="en" name="label">Category</Attribute>
+            <Attribute language="en" name="type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">The generic type of the resource being described.</Attribute>
+                <Attribute name="comment">The value for this qualifier must be one of service, document, or agency.</Attribute>
+            </Language>
+            <Attribute language="en" name="source">AGLS</Attribute>
+            <Attribute language="en" name="service">used when describing a service directly, not a document about a service.</Attribute>
+            <Attribute language="en" name="document">used for all resources which are not services or agencies, even if they are no traditional &amp;quot;documents&amp;quot; - for example, a sculpture;</Attribute>
+            <Attribute language="en" name="agency">used to describe an organisation</Attribute>
+        </Element>
+        <Element name="aggregationLevel">
+            <Attribute language="en" name="label">Aggregation Level</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">The level of aggregation of the resource being described.</Attribute>
+                <Attribute name="comment">There are only two values possible for this qualifier, either item or collection.</Attribute>
+            </Language>
+        </Element>
+    </Element>
+    <Element name="Format">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Format</Attribute>
+            <Attribute name="definition">The physical or digital manifestation of the resource.</Attribute>
+            <Attribute name="comment">Typically, Format may include the media-type or dimensions of the resource. Format may be used to determine the software, hardware or other equipment needed to display or operate the resource. Examples of dimensions include size and duration. Recommended best practice is to select a value from a controlled vocabulary (for example, the list of Internet Media Types [MIME] defining computer media formats).</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Whakatakotoranga</Attribute>
+            <Attribute name="definition">Te whakatinanatanga, te whakaputanga a-mati o te rauemi.</Attribute>
+            <Attribute name="comment">Ko te tikanga, ka taea te Whakatakotoranga te whakamahi hei whakarite i te rawa-ngohe (software), te rawa-maro (hardware), ma etahi taputapu ranei me matua whiwhi, hei whakahaere i te rauemi. Ko te rahi me te roanga etahi tauira hanga. Ko te tino huarahi kua tohua ko te tipako uara mai i tetahi whakaritenga kupu (hei tauira, te rarangi o nga Tumomo Papaho Ipurangi (Internet Media Types [MIME]) e whakaatu ana i nga whakatakotoranga papaho rorohiko.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Format</Attribute>
+            <Attribute name="definition">La matÃ©rialisation physique ou digitale de la ressource.</Attribute>
+            <Attribute name="comment">Typiquement, Format peut inclure le media ou les dimensions de la ressource. Format peut Ãªtre utilisÃ© pour prÃ©ciser le logiciel, le matÃ©riel ou autre Ã©quipement nÃ©cessaire pour afficher ou faire fonctionner la ressource. Exemples de dimensions incluent la taille et la durÃ©e. Il est recommandÃ© de choisir la valeur du format dans une liste de vocabulaire contrÃŽlÃ©(par exemple, la liste des types de media dÃ©finis sur Internet [MIME]).</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">Ð€ÐŸÑÐŒÐ°Ñ</Attribute>
+            <Attribute name="definition">Ð€ÐžÐ·ÐžÑÐµÑÐºÐŸÐµ ÐžÐ»Ðž ÑÐžÑÑÐŸÐ²ÐŸÐµ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÐ±ÑÑÐœÐŸ Ð€ÐŸÑÐŒÐ°Ñ ÐŒÐŸÐ¶ÐµÑ Ð²ÐºÐ»ÑÑÐ°ÑÑ ÑÐžÐ¿ Ð°ÑÐŽÐžÐŸÐ²ÐžÐ·ÑÐ°Ð»ÑÐœÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž (ÐŒÐµÐŽÐžÐ°-ÑÐžÐ¿) ÐžÐ»Ðž Ð²ÐµÐ»ÐžÑÐžÐœÑ ÑÐµÑÑÑÑÐ°. Ð€ÐŸÑÐŒÐ°Ñ ÐŒÐŸÐ¶ÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ ÐŽÐ»Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ Ð°Ð¿Ð¿Ð°ÑÐ°ÑÐœÐŸÐ³ÐŸ, Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐ³ÐŸ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÑ ÐžÐ»Ðž ÐŽÑÑÐ³ÐŸÐ³ÐŸ ÐŸÐ±ÐŸÑÑÐŽÐŸÐ²Ð°ÐœÐžÑ, ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÐ³ÐŸ ÐŽÐ»Ñ Ð²ÐŸÑÐ¿ÑÐŸÐžÐ·Ð²ÐµÐŽÐµÐœÐžÑ ÐžÐ»Ðž ÑÐ°Ð±ÐŸÑÑ Ñ ÑÐµÑÑÑÑÐŸÐŒ. ÐÑÐžÐŒÐµÑÑ Ð²ÐµÐ»ÐžÑÐžÐœÑ Ð²ÐºÐ»ÑÑÐ°ÑÑ ÑÐ°Ð·ÐŒÐµÑ Ðž Ð¿ÑÐŸÐŽÐŸÐ»Ð¶ÐžÑÐµÐ»ÑÐœÐŸÑÑÑ. ÐÐ»Ñ Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ Ð²ÑÐ±ÐžÑÐ°ÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐžÐ· ÐºÐŸÐœÑÑÐŸÐ»ÐžÑÑÐµÐŒÐŸÐ³ÐŸ ÑÐ»ÐŸÐ²Ð°ÑÑ (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÑÐ¿ÐžÑÐºÐ° ÐÐµÐŽÐžÐ°-ÑÐžÐ¿ÐŸÐ² ÐÐœÑÐµÑÐœÐµÑ MIME, ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑÐµÐ³ÐŸ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐœÑÐµ ÑÐŸÑÐŒÐ°ÑÑ Ð°ÑÐŽÐžÐŸÐ²ÐžÐ·ÑÐ°Ð»ÑÐœÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž).</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Formato</Attribute>
+            <Attribute name="definition">El formato de datos de un recurso, usado para identificar el software y posiblemente, el hardware que se necesitarÃ­a para mostrar el recurso. Para asegurar la interoperabilidad, los valores de Format deberÃ­an ser seleccionados de entre una lista de valores que actualmente se encuentra bajo desarrollo en un grupo de trabajo.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙØµÙØºØ©</Attribute>
+            <Attribute name="definition">ÙØ°Ù ØµÙØºØ© Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø© Ø§ÙØ®Ø§ØµØ© ØšØ§ÙÙ
+ØµØ¯Ø± , Ù ØªØ³ØªØ®Ø¯Ù
+ ÙÙØªØ¹Ø±ÙÙ ØšØ§ÙØšØ±Ù
+Ø¬ÙØ§Øª ÙØ±ØšÙ
+Ø§ Ø§ÙØµÙØš ÙÙØ­Ø§Ø³ÙØš Ù Ø§ÙØªÙ ÙÙ
+ÙÙ Ø£Ù ÙØ­ØªØ§Ø¬    ÙÙØ§ ÙØ¹Ø±Ø¶ Ø£Ù ØªØŽØºÙÙ Ø§ÙÙ
+ØµØ¯Ø± . Ù
+Ù Ø£Ø¬Ù Ø§ÙØªØ¹Ø§Ù
+Ù Ø§ÙÙ
+ØŽØªØ±Ù, ÙØ¬Øš Ø£Ù ØªØ®ØªØ§Ø± Ø§ÙØµÙØºØ© Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+Ø±ÙÙ
+Ø© Ù Ø§ÙØªÙ ÙØªÙ
+ Ø§Ø¹Ø¯Ø§Ø¯ÙØ§    Ø­Ø§ÙÙØ§ Ø¶Ù
+Ù Ø­ÙÙØ§Øª ÙØ±ØŽØ© Ø¹Ù
+Ù</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">æ ŒåŒ</Attribute>
+            <Attribute name="definition">èµæºçç©çææ°å­è¡šç°åœ¢åŒã</Attribute>
+            <Attribute name="comment">äžè¬èèšïŒæ ŒåŒå¯èœå
+æ¬èµæºçåªäœç±»åæèµæºçå€§å°ïŒæ ŒåŒå
+çŽ å¯ä»¥çšæ¥å³å®å±ç€ºææäœèµæºæé    çèœ¯ç¡¬ä»¶æå
+¶ä»çžåºè®Ÿå€ïŒäŸåŠå€§å°å
+æ¬èµæºæå çå­åšç©ºéŽåæç»­æ¶éŽãå»ºè®®éçšæ¥èªäºåæ§è¯è¡š    äž­çåŒïŒïŒäŸåŠInternetåªäœç±»å[MIME]å®ä¹è®¡ç®æºåªäœæ ŒåŒïŒã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">FormÃ¡t</Attribute>
+            <Attribute name="definition">FyzickÃ¡ nebo digitÃ¡lnÃ­ reprezentace zdroje.</Attribute>
+            <Attribute name="comment">Typicky mÅ¯ÅŸe FormÃ¡t obsahovat typ mÃ©dia nebo rozmÄry zdroje. FormÃ¡t lze pouÅŸÃ­vat k urÄenÃ­ softwaru, hardwaru nebo dalÅ¡Ã­ho zaÅÃ­zenÃ­ potÅebnÃ©ho k zobrazenÃ­ nebo k manipulaci se zdrojem. PÅÃ­klady rozmÄrÅ¯ zahrnujÃ­ velikost a dobu trvÃ¡nÃ­. DoporuÄuje se vybÃ­rat hodnotu z ÅÃ­zenÃ©ho slovnÃ­ku (napÅ. seznam typÅ¯ internetovÃœch mÃ©diÃ­ [MIME] definujÃ­cÃ­ formÃ¡ty poÄÃ­taÄovÃœch mÃ©diÃ­).</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Format</Attribute>
+            <Attribute name="definition">Het data formaat van het Internetbestand. Dit gegeven kan gebruikt worden om systeemvereisten (hard- en software) te identificeren die nodig zijn voor raadpleging of bediening van de Internetbron. &quot;Format&quot; is nog in ontwikkeling bij de DC workshop. Uit compatibiliteitsoverwegingen wordt aanbevolen formaatgegevens te selecteren uit een gecontroleerde lijst. Formaten kunnen van de Internet Media Types (MIME types) lijst gekozen worden: http://www.isi.edu/in-notes/iana/assignments/media-types/media-types</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Formato</Attribute>
+            <Attribute name="definition">Le manifestation physic o digital del ressource.</Attribute>
+            <Attribute name="comment">Typicamente le formato pote includer le typo de medio o dimensiones del ressource. Le formato pote esser utilizate pro determinar le software o le equipamento necessari pro exhibir o operar le ressource. Exemplos de dimensiones include grandessa e duration. Le practica recommendate es selectionar un valor de un vocabulario controlate (per exemplo, le lista de typos de medios de Internet [MIME] que defini formatos de medios).</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€°à€à€šà€Ÿ</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à¥ à€°à€à€šà€Ÿ, à€šà€®à¥à€šà€Ÿà€¬à¥à€Š à€°à€à€šà€Ÿ</Attribute>
+            <Attribute name="comment">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à¥ à€žà¥à€µà€°à¥à€ª, à€°à€à€šà€Ÿà€à€Šà€Ÿ. à€€à¥à€¯à€Ÿà€à¥ à€°à¥à€ª à€à€žà¥ à€ªà¥à€žà¥à€€à€à€°à¥à€ª, à€žà€à€à€£à€à¥à€¯ à€°à¥à€ª, à€µà€¿à€Šà¥à€¯à¥à€€ à€ªà€°à€®à€Ÿà€£à¥à€à€à¥à€¯à€Ÿ à€žà€¹à€Ÿà€¯à¥à€¯à€Ÿà€šà¥ à€žà€à€à€£à€à¥à€à¥à€€ à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à€Ÿ</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+        <Element name="extent">
+            <Attribute language="en" name="label">Extent</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">The size or duration of the resource.</Attribute>
+                <Attribute name="comment">The extent qualifier allows the description of the physical dimensions, file size or duration of the resource.</Attribute>
+            </Language>
+        </Element>
+        <Element name="medium">
+            <Attribute language="en" name="label">Medium</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">The material or physical carrier of the resource.</Attribute>
+            </Language>
+        </Element>
+    </Element>
+    <Element name="Availability">
+        <Attribute language="en" name="label">Availability</Attribute>
+        <Attribute language="en" name="obligation">Conditional - mandatory when adding an agency, service, or off-line document; optional when adding an on-line document.</Attribute>
+        <Attribute language="en" name="definition">How the resource can be obtained or contact information for obtaining the resource.</Attribute>
+        <Attribute language="en" name="comment">The Availability element is primarily used for non-electronic resources to provide information on how to obtain physical access to the resource. The Availability element should be repeated to show multiple access points - for example, a service where someone could pay a bill at two separate organisations. Generally, full details of how any service can be obtained, or contact information, should be provided. If a structured value is to be given (including for example name and address information) it is recommended that the NZGLS Agent Encoding scheme be used. Alternatively, a link to a directory, authority file or similar set of identity information may be provided.</Attribute>
+    </Element>
+    <Element name="Identifier">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Resource Identifier</Attribute>
+            <Attribute name="definition">An unambiguous reference to the resource within a given context.</Attribute>
+            <Attribute name="comment">Recommended best practice is to identify the resource by means of a string or number conforming to a formal identification system. Example formal identification systems include the Uniform Resource Identifier (URI) (including the Uniform Resource Locator (URL)), the Digital Object Identifier (DOI) and the International Standard Book Number (ISBN).</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Taututanga</Attribute>
+            <Attribute name="definition">He tohutoro e hangai ana ki te rauemi i roto i tetahi horopaki.</Attribute>
+            <Attribute name="comment">Ko te tino huarahi kua tohua, ko te tautu i te rauemi ma tetahi aho (string), tau ranei, e hangai ana ki tetahi punaha taututanga okawa. Ko etahi punaha taututanga okawa ko te Taututanga Rauemi Orite (Uniform Resource Identifier - URI), te Taututanga Rauemi Tohu-wahi (Uniform Resource Locator - URL), Te Mea A-mati (Digital Object Identifier - DOI) me te Tau Pukapuka Aro Whanui o te Ao (International Standard Book Number - ISBN).</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Identifiant</Attribute>
+            <Attribute name="definition">Une rÃ©fÃ©rence non ambiguÃ« Ã  la ressource dans un contexte donnÃ©</Attribute>
+            <Attribute name="comment">Il est recommandÃ© d&apos;identifier la ressource par une chaÃ®ne de caractÃšre ou un nombre conforme Ã  un sytÃšme formel d&apos;identification. Exemples de systemes formels d&apos;identification incluent le &quot;Uniform Resource Identifier&quot; (URI) (qui inclut le &quot;Uniform Resource Locator&quot; (URL)), le &quot;Digital Object Identifier&quot;(DOI) et le &quot;International Standard Book Number&quot;(ISBN).</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑ ÑÐµÑÑÑÑÐ°</Attribute>
+            <Attribute name="definition">ÐÐŽÐœÐŸÐ·ÐœÐ°ÑÐœÐ°Ñ ÑÑÑÐ»ÐºÐ° ÐœÐ° ÑÐµÑÑÑÑ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ ÐŽÐ°ÐœÐœÐŸÐ³ÐŸ ÐºÐŸÐœÑÐµÐºÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÐ»Ñ Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ ÐžÐŽÐµÐœÑÐžÑÐžÑÐžÑÐŸÐ²Ð°ÑÑ ÑÐµÑÑÑÑ Ð¿ÐŸÑÑÐµÐŽÑÑÐ²ÐŸÐŒ ÑÑÑÐŸÐºÐž ÐžÐ»Ðž ÑÐžÑÐ»Ð°, ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐ³ÐŸ ÑÐŸÑÐŒÐ°Ð»ÑÐœÐŸÐ¹ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÑÐžÑÑÐµÐŒÐµ. ÐÑÐžÐŒÐµÑÑ ÑÐŸÑÐŒÐ°Ð»ÑÐœÑÑ
+ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÐŸÐœÐœÑÑ
+ ÑÐžÑÑÐµÐŒ Ð²ÐºÐ»ÑÑÐ°ÑÑ Ð£ÐœÐžÑÐžÑÐžÑÐŸÐ²Ð°ÐœÐœÑÐ¹ ÐÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑ Ð ÐµÑÑÑÑÐ° (URI), (Ð²ÐºÐ»ÑÑÐ°Ñ Ð£ÐœÐžÑÐžÑÐžÑÐŸÐ²Ð°ÐœÐœÑÑÐ¹ ÐÐŸÐºÐ°ÑÐŸÑ Ð ÐµÑÑÑÑÐ° URL), ÐÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑ ÐŠÐžÑÑÐŸÐ²ÐŸÐ³ÐŸ ÐÐ±ÑÐµÐºÑÐ° (DOI) Ðž ÐÐµÐ¶ÐŽÑÐœÐ°ÑÐŸÐŽÐœÑÐ¹ Ð¡ÑÐ°ÐœÐŽÐ°ÑÑÐœÑÐ¹ ÐÐœÐžÐ¶ÐœÑÐ¹ ÐÐŸÐŒÐµÑ (ISBN).</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Identificador del Recurso</Attribute>
+            <Attribute name="definition">Secuencia de caracteres usados para identificar unÃ­vocamente un recurso. Ejemplos para recursos en lÃ­nea pueden ser URLs y URNs (cuando estÃ©n implementados). Para otros recursos pueden ser usados otros formatos de identificadores, como por ejemplo ISBN (&quot;International Standard Book Number&quot; - NÃºmero Internacional Normalizado para Libros)</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ù
+Ø¹Ø±Ù Ø§ÙÙ
+ØµØ¯Ø±</Attribute>
+            <Attribute name="definition">ÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø© Ø­Ø±ÙÙØ© Ø£Ù Ø±ÙÙ
+ ÙØ³ØªØ®Ø¯Ù
+ ÙØªØ¹Ø±ÙÙ Ø§ÙÙ
+ØµØ¯Ø± Ø§Ø­Ø¯ÙØ§ : Ø§ÙØ§Ù
+Ø«ÙØ© ÙØ°Ø§ÙÙ ÙÙ Ø§ÙÙ
+ØµØ§Ø¯Ø± Ø§ÙØŽØšÙÙØ©ØªØ¶Ù
+ ) URNs, URLs Ø¹ÙØ¯ ØšÙØ§ØŠÙØ§ (    ÙØ°ÙÙ ÙÙ
+ÙÙ Ø§Ø¹ØªØšØ§Ø± Ø§ÙÙ
+Ø¹Ø±ÙØ§Øª Ø§ÙØ¹Ø§ÙÙ
+ÙØ© Ø§ÙØ§Ø­Ø§Ø¯ÙØ© Ù
+Ø«Ù Ø§ÙØ±ÙÙ
+ Ø§ÙØ¯ÙÙÙ ÙØªØµÙÙÙ Ø§ÙÙØ§ØªØš (ISBN) Ù
+Ø±ØŽØ­Ø© ÙÙØ°Ø§ Ø§ÙØ¹Ø§Ù
+Ù</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">èµæºæ è¯ç¬Š</Attribute>
+            <Attribute name="definition">åšç¹å®çèåŽå
+ç»äºèµæºçäžäžªæç¡®çæ è¯ã</Attribute>
+            <Attribute name="comment">å»ºè®®å¯¹èµæºçæ è¯éçšç¬Šåæäžæ­£åŒæ è¯äœç³»çå­ç¬Šäž²åæ°å­ç»åãäŸåŠæ­£åŒçæ è¯äœç³»å
+æ¬ç»äžèµ    æºæ è¯ç¬Š(URI) (å
+æ¬åäžèµæºå®äœç¬ŠURL)ãæ°å­å¯¹è±¡æ è¯ç¬Š(DOI)ååœé
+æ åä¹Šå·(ISBN)ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">IdentifikÃ¡tor zdroje</Attribute>
+            <Attribute name="definition">JednoznaÄnÃœ odkaz na zdroj v rÃ¡mci danÃ©ho kontextu.</Attribute>
+            <Attribute name="comment">DoporuÄuje se identifikovat zdroj znakovÃœm ÅetÄzcem nebo ÄÃ­slem odpovÃ­dajÃ­cÃ­m nÄkterÃ©mu z formÃ¡lnÃ­ch identifikaÄnÃ­ch systÃ©mÅ¯. PÅÃ­klady formÃ¡lnÃ­ch identifikaÄnÃ­ch systÃ©mÅ¯ zahrnujÃ­ Uniform Resource Identifier (URI) (vÄetnÄ Uniform Resource Locator (URL)), Digital Object Identifier (DOI) a MezinÃ¡rodnÃ­ standardnÃ­ ÄÃ­slo knihy (ISBN).</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Bestandsidentificatie</Attribute>
+            <Attribute name="definition">Een unieke string of nummer ter identificatie van de Internetbron. Voorbeelden zijn URL&apos;s of URN&apos;s Andere voorbeelden zijn International Standard Book Number (ISBN) of International Standard Serial Number (ISSN)</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Identificator del ressource</Attribute>
+            <Attribute name="definition">Un referentia inambigue al ressource intra un date contexto.</Attribute>
+            <Attribute name="comment">Se recommenda identificar le ressource per medio de un catena de characteres o numero conforme a un systema formal de identification. Exemplos de systemas formal de identification include le Uniform Resource Identifier (URI) (includente le Uniform Resource Locator (URL)), le Digital Object Identifier (DOI) e le International Standard Book Number (ISBN).</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€à€³à€</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à€Ÿ à€à€ à€
+à€°à¥à€¥à¥ à€žà€à€Šà€°à¥à€­</Attribute>
+            <Attribute name="comment">à€à€Šà€Ÿ. à€®à€Ÿà€¹à€¿à€€à¥à€à€Ÿà€³à¥à€¯à€Ÿà€µà€°à¥à€² à€ªà€€à¥à€€à€Ÿ, à€µà€¿à€¶à€¿à€·à¥à€  à€žà¥à€¥à€³,  à€ªà¥à€žà¥à€€à€à€Ÿà€à€Ÿ à€à€à€€à€°à€°à€Ÿà€·à¥à€à¥à€°à¥à€¯  à€®à€Ÿà€šà€ à€à¥à€°à€®à€Ÿà€à€,  à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à¥ à€à€³à€ à€ªà€à€µà€¿à€£à€Ÿà€°à€Ÿ à€à€à€à€°à€šà¥à€ à€µà€°à¥à€² à€ªà€€à¥à€€à€Ÿ</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Source">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Source</Attribute>
+            <Attribute name="definition">A Reference to a resource from which the present resource is derived.</Attribute>
+            <Attribute name="comment">The present resource may be derived from the Source resource in whole or in part.  Recommended best practice is to reference the resource by means of a string or number conforming to a formal identification system.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Matapuna</Attribute>
+            <Attribute name="definition">He tohutoro ki tetahi rauemi koira te matapuna o te rauemi e tirohia ana.</Attribute>
+            <Attribute name="comment">Tera pea i puta te katoa, tetahi wahanga ranei o te rauemi, e tirohia ana, mai i te Matapuna rauemi. Ko te tino huarahi kua tohua ko te tohutoro ki te rauemi ma te aho, ma te tau ranei e hangai ana ki tetahi punaha taututanga okawa.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Source</Attribute>
+            <Attribute name="definition">Une rÃ©fÃ©rence Ã  une ressource Ã  partir de laquelle la ressource actuelle a Ã©tÃ© dÃ©rivÃ©e.</Attribute>
+            <Attribute name="comment">La ressource actuelle peut avoir Ã©tÃ© dÃ©rivÃ©e d&apos;une autre ressource source, en totalitÃ© ou en partie. Il est recommandÃ© de refÃ©rencer cette source par une chaÃ®ne de caractÃšre ou un nombre conforme Ã  un systÃšme formel d&apos;identification.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÑÑÐŸÑÐœÐžÐº</Attribute>
+            <Attribute name="definition">Ð¡ÑÑÐ»ÐºÐ° ÐœÐ° ÑÐµÑÑÑÑ, ÐžÐ· ÐºÐŸÑÐŸÑÐŸÐ³ÐŸ ÐžÐ·Ð²Ð»ÐµÑÐµÐœ ÐœÐ°ÑÑÐŸÑÑÐžÐ¹.</Attribute>
+            <Attribute name="comment">ÐÐ°ÑÑÐŸÑÑÐžÐ¹ ÑÐµÑÑÑÑ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐžÐ·Ð²Ð»ÐµÑÐµÐœ ÐžÐ· ÐÑÑÐŸÑÐœÐžÐºÐ° ÑÐµÐ»ÐžÐºÐŸÐŒ ÐžÐ»Ðž ÑÐ°ÑÑÐžÑÐœÐŸ. ÐÐ»Ñ Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ ÐžÐŽÐµÐœÑÐžÑÐžÑÐžÑÐŸÐ²Ð°ÑÑ ÑÐµÑÑÑÑ Ð¿ÐŸÑÑÐµÐŽÑÑÐ²ÐŸÐŒ ÑÑÑÐŸÐºÐž ÐžÐ»Ðž ÑÐžÑÐ»Ð°, ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐ³ÐŸ ÑÐŸÑÐŒÐ°Ð»ÑÐœÐŸÐ¹ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÑÐžÑÑÐµÐŒÐµ.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Fuente</Attribute>
+            <Attribute name="definition">Secuencia de caracteres utilizado para identificar unÃ­vocamente un trabajo a partir del cual proviene el recurso actual. Por ejemplo, es posible usar Source con la fecha de 1603 como descripciÃ³n de una pelÃ­cula basada en una obra de Shakespeare, pero es preferible, en ese caso, usar Relation &quot;IsBasedOn&quot; con una referencia a un recurso distinto cuya descripciÃ³n contenga el elemento Date con valor 1603.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙÙ
+ØµØ¯Ø±</Attribute>
+            <Attribute name="definition">Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª Ø§ÙØ®Ø§ØµØ© ØšÙ
+ØµØ¯Ø± Ø«Ø§ÙÙ Ù Ø§ÙØ°Ù Ø§Ø³ØªÙ
+Ø¯ Ù
+ÙÙ Ø§ÙÙ
+ØµØ¯Ø± Ø§ÙØ­Ø§ÙÙ. Ù
+Ø¹ Ø£ÙÙ Ù
+Ù Ø§ÙÙ
+ÙØµÙ ØšÙ Ø£Ù ØªÙØ¯Ù
+ Ø§ÙØ¹ÙØ§Ù
+Ù    Ù
+Ø¹ÙÙÙ
+Ø§Øª Ø¹Ù Ø§ÙÙ
+ØµØ¯Ø± Ø§ÙØ­Ø§ÙÙ ÙÙØ· , ÙÙÙ
+ÙÙ Ø£Ù ÙØ­ÙÙ ÙØ°Ø§ Ø§ÙØ¹Ø§Ù
+Ù Ø§ÙØªØ§Ø±ÙØ®, Ø§ÙÙ
+ÙØŽØŠ , Ø§ÙØµÙØºØ© , Ø§ÙÙ
+Ø¹Ø±Ù , Ø§Ù Ø§ÙØ© Ù
+ÙØ© - Ù
+Ø¹ÙÙÙ
+Ø§Øª Ø§Ø®Ø±Ù ÙÙÙ
+ØµØ¯Ø± Ø§ÙØ«Ø§ÙÙ Ø¹ÙØ¯Ù
+Ø§ ØªØ¹ØªØšØ± Ù
+ÙÙ
+Ø© ÙØ§ÙØªØŽØ§Ù Ø§ÙÙ
+ØµØ¯Ø± Ø§ÙØ­Ø§ÙÙ , Ù ÙØ°Ø§ÙÙ ÙÙØµÙ Ø¹ÙØ¯ Ø§ÙØªØ·ØšÙÙÙÙ Ø§Ø­Ø³Ù     Ø§ÙÙ
+ØªØ¹Ø§Ø±Ù Ø¹ÙÙÙ ØšØ§Ø³ØªØ®Ø¯Ø§Ù
+ Ø¹Ø§Ù
+Ù Ø§ÙØ¹ÙØ§ÙØ©</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">æ¥æº</Attribute>
+            <Attribute name="definition">ç°æèµæºæ¥æºçåç
+§ã</Attribute>
+            <Attribute name="comment">åœåèµæºå¯èœéšåæå
+šéšæºèªè¯¥å
+çŽ ææ è¯çèµæºïŒå»ºè®®å¯¹è¿äžèµæºçæ è¯éçšäžäžªç¬Šåæ­£åŒæ è¯ç³»    ç»çå­äž²åæ°å­ç»å ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">Zdroj</Attribute>
+            <Attribute name="definition">Odkaz na zdroj, z nÄhoÅŸ je popisovanÃœ zdroj odvozen.</Attribute>
+            <Attribute name="comment">PopisovanÃœ zdroj mÅ¯ÅŸe bÃœt zcela nebo zÄÃ¡sti odvozen ze zdroje uvedenÃ©ho v prvku Zdroj. DoporuÄuje se odkazovat zdroj znakovÃœm ÅetÄzcem nebo ÄÃ­slem odpovÃ­dajÃ­cÃ­m nÄkterÃ©mu z formÃ¡lnÃ­ch identifikaÄnÃ­ch systÃ©mÅ¯.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Bron</Attribute>
+            <Attribute name="definition">Informatie over een tweede bron waar de huidige Internetbron is van afgeleid. Bij &quot;Source&quot; mag een datum, auteur of maker, formaat, identificatie of andere metadata voor de tweede bron worden ingevuld. Voorbeeld: het is mogelijk om een &quot;Source&quot; datum 1603 in een omschrijving van een 1996 film bewerking van een Shakespeare stuk te gebruiken. &quot;Source&quot; is niet bruikbaar wanneer de huidige bron de orginele is.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Fonte</Attribute>
+            <Attribute name="definition">Un referentia a un ressource del qual se deriva le ressource presente.</Attribute>
+            <Attribute name="comment">Le ressource presente pote derivar se del ressource-fonte in toto o in parte. Le practica recommendate es facer referentia al ressource per medio de un catena de characteres o un numero conforme a un systema formal de identification.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€à€à€®</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€à€Ÿ à€à€à€® à€žà€Ÿà€à€à€£à€Ÿà€°à€Ÿ à€à€à€
+à€°à¥à€¥à¥ à€žà€à€Šà€°à¥à€­</Attribute>
+            <Attribute name="comment">à€à€Šà€Ÿ. à€ªà¥à€žà¥à€€à€, à€®à€Ÿà€žà€¿à€,  à€®à€Ÿà€¹à€¿à€€à¥à€à€Ÿà€³à¥à€¯à€Ÿà€µà€°à¥à€² à€ªà€€à¥à€€à€Ÿà€¯à€Ÿà€à€à€Ÿ à€žà€à€Šà€°à¥à€­</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Language">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Language</Attribute>
+            <Attribute name="definition">A language of the intellectual content of the resource.</Attribute>
+            <Attribute language="en" name="comment">Recommended best practice for the values of the Language element is defined by RFC 1766 which includes a two-letter Language Code (taken from the ISO 639 standard, followed optionally, by a two-letter Country Code (taken from the ISO 3166 standard). For example, &apos;en&apos; for English, &apos;fr&apos; for French, or &apos;en-uk&apos; for English used in the United Kingdom.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Reo</Attribute>
+            <Attribute name="definition">Te reo o te whakakaupapatanga o nga matauranga o te rauemi.</Attribute>
+            <Attribute name="comment">Ko te tino huarahi kua tohua mo nga uara o te huanga Reo kua whakaritea ki te RFC 1766 [RFC1766] kei roto te Tohu Reo kupu-rua (two-letter Language Code) (no te aro whanui ISO 639 [ISO639], ka taea e tetahi tohu kupu-rua te whai atu (no te aro whanui ISO 3166) [ISO366]). Hei tauira, te &apos;en&apos; mo te English, te &apos;fr&apos; mo te French, &apos;te en-uk&apos; mo te English e whakamahia ana i Ingarangi (UK).</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Langue</Attribute>
+            <Attribute name="definition">La langue du contenu intellectuel de la ressource.</Attribute>
+            <Attribute name="comment">Il est recommandÃ© d&apos;utiliser comme valeur de l&apos;Ã©lÃ©ment Langue celles definies par la RFC 1766 [RFC1766] qui comprend un code de langage Ã  deux caractÃšres(venant du standard ISO 639 [ISO639]), Ã©ventuellement suivi d&apos;un code Ã  deux lettres pour le pays (venant du standard ISO 3166 [ISO3166] ou en franÃ§ais [ISO3166]). Par exemple, &apos;en&apos; pour l&apos;anglais, &apos;fr&apos; pour le franÃ§ais, ou &apos;en-uk&apos; pour l&apos;anglais utilisÃ© au Royaume-Uni.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">Ð¯Ð·ÑÐº</Attribute>
+            <Attribute name="definition">Ð¯Ð·ÑÐº ÐžÐœÑÐµÐ»Ð»ÐµÐºÑÑÐ°Ð»ÑÐœÐŸÐ³ÐŸ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÐ»Ñ Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÑÐ»ÐµÐŒÐµÐœÑÐ° Ð¯Ð·ÑÐº, ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÐŒÐŸÐµ RFC 1766 (Ð¢ÑÐ³Ðž ÐŽÐ»Ñ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÐž ÑÐ·ÑÐºÐ°), Ð²ÐºÐ»ÑÑÐ°ÑÑÐžÐŒ ÐŽÐ²ÑÑ
+Ð±ÑÐºÐ²ÐµÐœÐœÑÐ¹ ÐºÐŸÐŽ ÑÐ·ÑÐºÐ° (Ð²Ð·ÑÑÑÐ¹ ÐžÐ· ÑÑÐ°ÐœÐŽÐ°ÑÑÐ° ISO 639 (ÐÐŸÐŽÑ ÐŽÐ»Ñ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐ¹ ÑÐ·ÑÐºÐŸÐ²)), Ð·Ð° ÐºÐŸÑÐŸÑÑÐŒ ÑÐ»ÐµÐŽÑÐµÑ (Ð¿ÑÐž ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÑÑÐž) ÐŽÐ²ÑÑ
+Ð±ÑÐºÐ²ÐµÐœÐœÑÐ¹ ÐºÐŸÐŽ ÑÑÑÐ°ÐœÑ (Ð²Ð·ÑÑÑÐŒÐž ÐžÐ· ÑÑÐ°ÐœÐŽÐ°ÑÑÐ° ISO 3166 (ÐÐŸÐŽÑ ÐŽÐ»Ñ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐ¹ ÑÑÑÐ°Ðœ)). ÐÐ°Ð¿ÑÐžÐŒÐµÑ, &quot;en&quot; - ÐŽÐ»Ñ Ð°ÐœÐ³Ð»ÐžÐ¹ÑÐºÐŸÐ³ÐŸ, &quot;fr&quot; - ÐŽÐ»Ñ ÑÑÐ°ÐœÑÑÐ·ÑÐºÐŸÐ³ÐŸ, &quot;en-uk&quot; - ÐŽÐ»Ñ Ð°ÐœÐ³Ð»ÐžÐ¹ÑÐºÐŸÐ³ÐŸ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐŸÐ³ÐŸ Ð² ÐÐµÐ»ÐžÐºÐŸÐ±ÑÐžÑÐ°ÐœÐžÐž.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Lengua</Attribute>
+            <Attribute name="definition">Lengua/s del contenido intelectual del recurso. Practicamente el contenido de este campo deberÃ­a coincidir con los de la RFC 1766 (Tags para la identificaciÃ³n de lenguas, http://ds.internic.net/rfc/rfc1766.txt); por ejemplo: en, es, de, fi, ja y zh.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙÙØºØ©</Attribute>
+            <Attribute name="definition">ÙØ°Ù ÙÙ ÙØºØ© Ø§ÙÙ
+Ø­ØªÙÙ Ø§ÙÙÙØ±Ù ÙÙÙ
+ØµØ¯Ø± . ÙÙÙ
+Ø§ ÙØ§Ù  Ø¹Ù
+ÙÙØ§ , Ù
+Ø­ØªÙÙ ÙØžØ§ Ø§ÙØ­ÙÙ ÙØ¬Øš Ø£Ù ÙØªØ·Ø§ØšÙ Ù
+Ø¹ RFC 1766    ] Ø§ÙØ§Ù
+Ø«ÙØ© ØªØ¶Ù
+ th, ja, fr, es, fi, de, en Ù zh ÙØ±Ù
+ÙØ² ÙÙØªØ¹Ø±ÙÙ ØšØ§ÙÙØºØ© [</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">è¯­ç§</Attribute>
+            <Attribute name="definition">æè¿°èµæºç¥è¯å
+å®¹çè¯­ç§ã</Attribute>
+            <Attribute name="comment">å»ºè®®æ¬å
+çŽ çåŒéçšRFC 3066[RFC3066]ïŒè¯¥æ åäžISO 639 [ISO639]äžèµ·å®ä¹äºç±äž€äžªåäžäžªè±    æå­æ¯ç»æçäž»è¯­èšæ ç­Ÿåå­æ ç­ŸäŸåŠå
+æ¬âenâæâengâæ¥è¡šç€ºEnglish, &quot;akk&quot; æ¥è¡šç€º    &quot;en-GB&quot;è¡šç€ºè±åœè±è¯­ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">Jazyk</Attribute>
+            <Attribute name="definition">Jazyk intelektuÃ¡lnÃ­ho obsahu zdroje.</Attribute>
+            <Attribute name="comment">DoporuÄenÃœ postup pro hodnoty prvku Jazyk je definovÃ¡n v RFC 1766 [RFC1766]: dvouznakovÃœ kÃ³d jazyka (pÅevzatÃœ z normy ISO 639 [ISO639]) volitelnÄ nÃ¡sledovanÃœ dvouznakovÃœm kÃ³dem zemÄ (pÅevzatÃœm z normy ISO 3166 [ISO3166]). NapÅÃ­klad &apos;en&apos; pro angliÄtinu, &apos;fr&apos; pro francouzÅ¡tinu, &apos;cs&apos; pro ÄeÅ¡tinu, nebo &apos;en-uk&apos; pro angliÄtinu uÅŸÃ­vanou ve SpojenÃ©m krÃ¡lovstvÃ­.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Taal</Attribute>
+            <Attribute name="definition">De taal waarin het document is beschreven. Voorgeschreven wordt de ISO639-1 norm, een twee karakter taalcode van de ISO 639(639-1 en 639-2) norm. Taalcodes kunnen van een lijst worden gekozen: http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt, Eventueel kan ISO3166 (landencodes) gebruikt worden om aan te geven in welk gebied de taal wordt gesproken. Deze kunnen ook van een lijst worden gekozen:  http://www.ics.uci.edu/pub/ietf/http/related/iso3166.txt.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Lingua</Attribute>
+            <Attribute name="definition">Le lingua del contento intellectual del ressource.</Attribute>
+            <Attribute name="comment">Le practica recommendate pro le valores del elemento lingua es definite per RFC 1766 [RFC1766], que include un codice de lingua de duo litteras (prendite del standard ISO 639 [ISO639]), sequite optionalmente per un codice de pais de duo litteras (prendite del standard ISO 3166 [ISO3166]). Per exemplo, &apos;ia&apos; pro interlingua, &apos;fr&apos; pro francese, o &apos;en-uk&apos; pro le anglese del Regno Unite.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€­à€Ÿà€·à€Ÿ</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à¥ à€­à€Ÿà€·à€Ÿ</Attribute>
+            <Attribute name="comment">à€à€Šà€Ÿ. à€®à€°à€Ÿà€ à¥ - à€­à€Ÿà€°à€€à¥à€¯ à€­à€Ÿà€·à€Ÿ</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Relation">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Relation</Attribute>
+            <Attribute name="definition">A reference to a related resource.</Attribute>
+            <Attribute name="comment">Recommended best practice is to reference the resource by means of a string or number conforming to a formal identification system.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Whai Panga</Attribute>
+            <Attribute name="definition">He tohutoro ki tetahi rauemi whai panga.</Attribute>
+            <Attribute name="comment">Ko te tino huarahi kua tohua, ko te tohutoro ki te rauemi ma te aho, te tau ranei, e hangai ana ki te punaha taututanga okawa.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Relation</Attribute>
+            <Attribute name="definition">Une rÃ©fÃ©rence Ã  une autre ressource qui a un rapport avec cette ressource.</Attribute>
+            <Attribute name="comment">Il est recommandÃ© de rÃ©fÃ©rencer cette ressource par une chaÃ®ne de caractÃšres ou un numÃ©ro conforme Ã  un systÃšme formel d&apos;identification.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÑÐœÐŸÑÐµÐœÐžÐµ</Attribute>
+            <Attribute name="definition">ï¿œÐµÐœÐœÑÐ¹ ÑÐµÑÑÑÑ.</Attribute>
+            <Attribute name="comment">ÐÐ»Ñ Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ ÐžÐŽÐµÐœÑÐžÑÐžÑÐžÑÐŸÐ²Ð°ÑÑ ÑÐµÑÑÑÑ Ð¿ÐŸÑÑÐµÐŽÑÑÐ²ÐŸÐŒ ÑÑÑÐŸÐºÐž ÐžÐ»Ðž ÑÐžÑÐ»Ð°, ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐ³ÐŸ ÑÐŸÑÐŒÐ°Ð»ÑÐœÐŸÐ¹ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÑÐžÑÑÐµÐŒÐµ.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">RelaciÃ³n</Attribute>
+            <Attribute name="definition">Un identificador de un segundo recurso y su relaciÃ³n con el recurso actual. Este elemento permite enlazar los recursos relacionados y las descripciones de los recursos. Por ejemplo: IsVersionOf - Incluye la ediciÃ³n de un trabajo, IsBasedOn - La traducciÃ³n de un trabajo, IsPartOf - Un capÃ­tulo de un libro, IsFormatOf - Un mecanismo de transformaciÃ³n de un conjunto de datos en una imagen. Para asegurar la interoperabilidad, las relaciones deberÃ­an ser seleccionadas de una lista de elementos que actualmente se encuentra bajo desarrollo en un grupo de trabajo.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙØ¹ÙØ§ÙØ©</Attribute>
+            <Attribute name="definition">ÙØ°Ø§ Ù
+Ø¹Ø±Ù ÙÙÙ
+ØµØ¯Ø± Ø§ÙØ«Ø§ÙÙ Ù Ø¹ÙØ§ÙØªÙ ØšØ§ÙÙ
+ØµØ¯Ø± Ø§ÙØ­Ø§ÙÙ . ÙØ³Ù
+Ø­ ÙØ°Ø§ Ø§ÙØ¹Ø§Ù
+Ù ØšØªÙØ¶ÙØ­ Ø§ÙØ±ÙØ§ØšØ· ØšÙÙ Ø§ÙÙ
+ØµØ§Ø¯Ø± Ø§ÙÙ
+ØªØ¹ÙÙØ©     ØšØšØ¹Ø¶ÙØ§ Ù ØªÙØµÙÙ Ø§ÙÙ
+ØµØ¯Ø± . Ø§ÙØ§Ù
+Ø«ÙØ© ØªØ¶Ù
+ Ø·ØšØ¹Ø© Ø§ÙØ¹Ù
+Ù ) ÙØ³Ø®Ø© Ù
+Ù ( ØªØ±Ø¬Ù
+Ø© Ø¹Ù
+Ù ) Ø§Ø¹ØªÙ
+Ø§Ø¯Ø§ Ø¹ÙÙ ( ÙØµÙ Ù
+Ù ÙØªØ§Øš ) Ø¬Ø²Ø¡ Ù
+Ù (    Ù ØªØ­ÙÙÙÙ Ù
+ÙÙØ§ÙÙÙÙØ© ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ù
+Ø¹ÙÙÙ
+Ø§ØªÙØ© Ø§ÙÙ ØµÙØ±Ø© ) ØµÙØºØ© Ù
+Ù ( Ù
+Ù Ø£Ø¬Ù Ø§ÙØªØ¹Ø§Ù
+Ù Ø§ÙÙ
+ØŽØªØ±Ù , ÙØ¬Øš Ø§Ø®ØªÙØ§Ø± Ø§ÙØ¹ÙØ§ÙØ§Øª Ù
+Ù    Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+Ø±ÙÙ
+Ø© Ù Ø§ÙØªÙ ÙØªÙ
+ Ø§Ø¹Ø¯Ø§Ø¯ÙØ§ Ø­Ø§ÙÙØ§ Ø¶Ù
+Ù Ø­ÙÙØ§Øª ÙØ±ØŽØ© Ø¹Ù
+Ù</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">å
+³è</Attribute>
+            <Attribute name="definition">æ¶åççžå
+³èµæºã</Attribute>
+            <Attribute name="comment">èåœçžå
+³èµæºæ¶ïŒå»ºè®®äœ¿çšç¬Šåæ­£åŒæ è¯ç³»ç»çå­ç¬Šäž²æè
+æ°å­ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">Vztah</Attribute>
+            <Attribute name="definition">Odkaz na pÅÃ­buznÃœ zdroj.</Attribute>
+            <Attribute name="comment">DoporuÄuje se odkazovat zdroj znakovÃœm ÅetÄzcem nebo ÄÃ­slem odpovÃ­dajÃ­cÃ­m nÄkterÃ©mu z formÃ¡lnÃ­ch identifikaÄnÃ­ch systÃ©mÅ¯.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Relatie</Attribute>
+            <Attribute name="definition">Een identificatie van een tweede bron en de relatie met de huide Internetbron. Voorbeelden zijn een editie van een werk (IsVersionOf), een vertaling van een werk (IsBasedOn), een hoofdstuk van een boek (IsPartOf) en een mechanische transformatie van een dataset in een plaatje (IsFormatOf). De DC Working Groups zijn bezig met een lijst met de meest verwachte relaties. Aanbevolen wordt om de relaties van deze lijst te gebruiken: http://purl.oclc.org/metadata/dublin_core/wrelationdraft.html.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="definition">Relation</Attribute>
+            <Attribute name="definition">Un referentia a un ressource correlate.</Attribute>
+            <Attribute name="comment">Le practica recommendate es facer referentia al ressource per medio de un catena de characteres o numero conforme a un systema de identification formal.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€šà€Ÿà€€à¥ , à€žà€à€¬à€à€§</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€¶à¥ à€žà€à€¬à€à€§ à€Šà€Ÿà€à€µà€£à€Ÿà€°à€Ÿ à€žà€à€Šà€°à¥à€­</Attribute>
+            <Attribute name="comment">à€à€Šà€Ÿ.  à€®à€Ÿà€¹à€¿à€€à¥ à€à€Ÿà€³à¥à€¯à€Ÿà€µà€°à¥à€² à€ªà€€à¥à€€à€Ÿ(URL)</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+        <Element name="isVersionOf">
+            <Attribute language="en" name="label">Is Version Of</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">The described resource is a version, edition, or adaptation of the referenced resource. Changes in version imply substantive changes in content rather than differences in format.</Attribute>
+            </Language>
+        </Element>
+        <Element name="hasVersion">
+            <Attribute language="en" name="label">Has Version</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">The described resource has a version, edition, or adaptation, namely, the referenced resource.</Attribute>
+            </Language>
+        </Element>
+        <Element name="isReplacedBy">
+            <Attribute language="en" name="label">Is Replaced By</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">The described resource is supplanted, displaced, or superseded by the referenced resource.</Attribute>
+            </Language>
+        </Element>
+        <Element name="replaces">
+            <Attribute language="en" name="label">Replaces</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">The described resource supplants, displaces, or supersedes the referenced resource.</Attribute>
+            </Language>
+        </Element>
+        <Element name="isRequiredBy">
+            <Attribute language="en" name="label">Is Required By</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">The described resource is required by the referenced resource, either physically or logically.</Attribute>
+            </Language>
+        </Element>
+        <Element name="requires">
+            <Attribute language="en" name="label">Requires</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">The described resource requires the referenced resource to support its function, delivery, or coherence of content.</Attribute>
+            </Language>
+        </Element>
+        <Element name="isPartOf">
+            <Attribute language="en" name="label">Is Part Of</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">The described resource is a physical or logical part of the referenced resource.</Attribute>
+                <Attribute name="comment">Used to describe the relationship between a service and relevant documents (e.g. web pages and forms)</Attribute>
+            </Language>
+        </Element>
+        <Element name="hasPart">
+            <Attribute language="en" name="label">Has Part</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">The described resource includes the referenced resource either physically or logically.</Attribute>
+            </Language>
+        </Element>
+        <Element name="isReferencedBy">
+            <Attribute language="en" name="label">Is Referenced By</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">The described resource is referenced, cited, or otherwise pointed to by the referenced resource.</Attribute>
+            </Language>
+        </Element>
+        <Element name="references">
+            <Attribute language="en" name="label">References</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">The described resource references, cites, or otherwise points to the referenced resource.</Attribute>
+            </Language>
+        </Element>
+        <Element name="isFormatOf">
+            <Attribute language="en" name="label">Is Format Of</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">The described resource is the same intellectual content of the referenced resource, but presented in another format.</Attribute>
+            </Language>
+        </Element>
+        <Element name="hasFormat">
+            <Attribute language="en" name="label">Has Format</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">The described resource pre-existed the referenced resource, which is essentially the same intellectual content presented in another format.</Attribute>
+            </Language>
+        </Element>
+        <Element name="isBasisFor">
+            <Attribute language="en" name="label">Is Basis For</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">The described resource pre-existed the referenced resource, which is a performance, production, derivation, translation, or interpretation of the described resource.</Attribute>
+            </Language>
+        </Element>
+        <Element name="isBasedOn">
+            <Attribute language="en" name="label">Is Based On</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">The described resource is a performance, production, derivation, translation, or interpretation of the referenced resource.</Attribute>
+            </Language>
+        </Element>
+    </Element>
+    <Element name="Coverage">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Coverage</Attribute>
+            <Attribute name="definition">The extent or scope of the content of the resource.</Attribute>
+            <Attribute name="comment">Coverage will typically include spatial location (a place name or geographic coordinates), temporal period (a period label, date, or date range) or jurisdiction (such as a named administrative entity). Recommended best practice is to select a value from a controlled vocabulary (for example, the Thesaurus of Geographic Names [TGN]) and that, where appropriate, named places or time periods be used in preference to numeric identifiers such as sets of coordinates or date ranges.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Kapitanga</Attribute>
+            <Attribute name="definition">Te roanga, te whanuitanga ranei o te whakakaupapatanga o te rauemi.</Attribute>
+            <Attribute name="comment">Ko te tikanga, ka uru atu te wahi mokowa (te ingoa o tetahi wahi, whakapiritanga matawhenua ranei), whakaritenga wa (he tapatanga wa (period label, ra, whakatakotoranga whanui o nga ra), te whakaritenga ture (penei i te putahi whakahaere). Ko te tino huarahi kua tohua, ko te tipako uara mai i tetahi whakaritenga kupu (hei tauira, i tetahi Puna Kupu Ingoa Matawhenua (Geographic Names [TGN] i nga wahi tika, ko nga wahi me nga whakaritenga wa ka whakamahia i mua i te whakamahitanga o nga taututanga tau penei i nga huinga whakapiritanga me nga whakatakotoranga whanui o nga ra.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Couverture</Attribute>
+            <Attribute name="definition">La portÃ©e ou la couverture spatio-temporelle de la ressource.</Attribute>
+            <Attribute name="comment">La couverture typiquement inclut une position gÃ©ographique (le nom d&apos;un lieu ou ses coordonnÃ©es), une pÃ©riode de temps (un nom de pÃ©riode, une date, ou un intervalle de temps) ou une juridiction (telle que le nom d&apos;une entitÃ© administrative). Il est recommandÃ© de choisir la  valeur de Couverture dans un vocabulaire contrÃŽlÃ© (par exemple, un thÃ©saurus de noms gÃ©ographiques, comme[TGN]) et, quand cela est appropriÃ©, des noms de lieux ou de pÃ©riodes plutÃŽt que des identifiants numÃ©riques tels que des coordonnÃ©es ou des intervalles de dates. </Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÑ
+Ð²Ð°Ñ</Attribute>
+            <Attribute name="definition">ÐÑÐŸÑÑÐ¶ÐµÐœÐœÐŸÑÑÑ Ðž Ð³ÑÐ°ÐœÐžÑÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÑ
+Ð²Ð°Ñ ÐŸÐ±ÑÐºÐœÐŸÐ²ÐµÐœÐœÐŸ Ð²ÐºÐ»ÑÑÐ°ÐµÑ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²ÐµÐœÐœÐŸÐµ ÐŒÐµÑÑÐŸÐœÐ°Ñ
+ÐŸÐ¶ÐŽÐµÐœÐžÐµ (ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐŒÐµÑÑÐœÐŸÑÑÐž ÐžÐ»Ðž Ð³ÐµÐŸÐ³ÑÐ°ÑÐžÑÐµÑÐºÐžÐµ ÐºÐŸÐŸÑÐŽÐžÐœÐ°ÑÑ), Ð²ÑÐµÐŒÐµÐœÐœÐŸÐ¹ Ð¿ÑÐŸÐŒÐµÐ¶ÑÑÐŸÐº (ÑÐºÐ°Ð·Ð°ÐœÐžÐµ Ð¿ÐµÑÐžÐŸÐŽÐ°, ÐŽÐ°ÑÐ° ÐžÐ»Ðž ÑÑÐŽ ÐŽÐ°Ñ) ÐžÐ»Ðž ÑÑÐžÑÐŽÐžÐºÑÐžÑ (ÑÐºÐ°Ð·Ð°ÐœÐžÐµ ÐµÐŽÐžÐœÐžÑÑ Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐ°ÑÐžÐ²ÐœÐŸÐ³ÐŸ ÐŽÐµÐ»ÐµÐœÐžÑ). ÐÐ° Ð¿ÑÐ°ÐºÑÐžÐºÐµ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ Ð²ÑÐ±ÐžÑÐ°ÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐžÐ· ÐºÐŸÐœÑÑÐŸÐ»ÐžÑÑÐµÐŒÐŸÐ³ÐŸ ÑÐ»ÐŸÐ²Ð°ÑÑ (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, Ð¢ÐµÐ·Ð°ÑÑÑÑÐ° Ð³ÐµÐŸÐ³ÑÐ°ÑÐžÑÐµÑÐºÐžÑ
+ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐ¹ TGN), Ðž, ÐµÑÐ»Ðž ÑÑÐŸ ÑÐŒÐµÑÑÐœÐŸ, Ð¿ÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÐµ ÐŸÑÐŽÐ°ÐµÑÑÑ ÑÐºÐ°Ð·Ð°ÐœÐžÑÐŒ ÐŒÐµÑÑÐœÐŸÑÑÐµÐ¹ ÐžÐ»Ðž Ð²ÑÐµÐŒÐµÐœÐœÑÑ
+ Ð¿ÑÐŸÐŒÐµÐ¶ÑÑÐºÐŸÐ² Ð²ÐŒÐµÑÑÐŸ ÑÐžÑÑÐŸÐ²ÑÑ
+ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ², ÐºÐ°Ðº, ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÑÐžÑÑÐµÐŒ ÐºÐŸÐŸÑÐŽÐžÐœÐ°Ñ ÐžÐ»Ðž Ð²ÑÐµÐŒÐµÐœÐœÑÑ
+ ÑÑÐŽÐŸÐ².</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Cobertura</Attribute>
+            <Attribute name="definition">La caracterÃ­stica de cobertura espacial y/o temporal del contenido intelectual del recurso. La cobertura espacial se refiere a una regiÃ³n fÃ­sica (por ejemplo, sector celestial); uso de coordenadas (por ejemplo, longitud y latitud) o nombres de lugares extraidos de una lista controlada. La cobertura temporal se refiere al contenido del recurso en vez de a cuando fue creado o puesto accesible ya que este Ãºltimo pertenece al elemento Date. Se usa el mismo formato basado en http://www.w3.org/TR/NOTE-datetime.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙØªØºØ·ÙØ©</Attribute>
+            <Attribute name="definition">ÙÙ Ø§ÙØ®ØµØ§ØŠØµ Ø§ÙÙ
+ÙØ§ÙÙØ© Ø§Ù Ø§ÙØ²Ù
+ÙÙØ© ÙÙÙ
+Ø­ØªÙÙ Ø§ÙÙÙØ±Ù ÙÙÙ
+ØµØ¯Ø± . Ø§ÙØªØºØ·ÙØ© Ø§ÙÙ
+ÙØ§ÙÙØ© ØªØŽÙØ± Ø§ÙÙ Ø¬ÙØ© Ø·ØšÙØ¹ÙØ© )Ù
+Ø«Ù , ÙØ·Ø§Ø¹ Ø³Ù
+Ø§ÙÙ (    Ø§Ø³ØªØ®Ø¯Ø§Ù
+ Ø§ÙØ§Ø­Ø¯Ø§Ø«ÙØ§Øª ) Ù
+Ø«Ù  Ø®Ø· Ø§ÙØ·ÙÙ Ù Ø®Ø· Ø§ÙØ¹Ø±Ø¶ ( ÙÙ Ø£Ø³Ù
+Ø§Ø¡ Ø§Ù
+ÙÙØ© Ù
+Ø³ØªØ­ÙÙ
+Ø© Ø§Ù Ù
+ØªØ¬ÙØ§Øª ØšØ§ÙÙØ§Ù
+Ù . Ø§ÙØªØºØ·ÙØ© Ø§ÙØ²Ù
+ÙÙØ©    Ø«Ø¹ÙØ¯ Ø§ÙÙ Ù
+Ø§ ÙØ±Ø¬Ø¹ Ø§ÙÙÙ Ø§ÙÙ
+ØµØ¯Ø± Ù ÙÙØ³ Ø§Ù Ù
+ØªÙ ØªÙ
+ ØªÙÙÙØ±Ù ) Ø§ÙØ§Ø®ÙØ± ÙØªØ¹ÙÙ ØšØ¹Ø§Ù
+Ù Ø§ÙØªØ§Ø±ÙØ® ( Ø§Ø³ØªØ®Ø¯Ø§Ù
+ ÙÙØ³ ØµÙØºØ© Ø§ÙØªØ§Ø±ÙØ®  Ø§Ù Ø§ÙÙÙØª    ) Ø¹Ø§Ø¯Ø© Ù
+Ø¯Ù ] ( ØµÙØ§ØºØ§Øª Ø§ÙÙÙÙ
+ Ù Ø§ÙÙÙØª ) Ø§Ø¹ØªÙ
+Ø§Ø¯Ø§ Ø¹ÙÙ (ISO 8601 Ø§ÙÙ
+ÙØ§Ø­ØžØ© Ø§ÙÙÙÙØ© [http://www.w3.org/TR/NOTE-datetime, W3C    ÙÙ
+Ø§ ÙÙ Ù
+ÙØµÙ ØšÙ ÙØ¹Ø§Ù
+Ù Ø§ÙØªØ§Ø±ÙØ® Ø§Ù ÙØªØ±Ø§Øª Ø²Ù
+ÙÙØ© Ù
+Ù ÙØ§ØŠÙ
+Ø© Ù
+Ø³ØªØ­ÙÙ
+Ø© Ø§Ù Ù
+ØªØ¬ÙØ§Øª ØšØ§ÙÙØ§Ù
+Ù</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">èŠçèåŽ</Attribute>
+            <Attribute name="definition">èµæºå
+å®¹ææ¶åçå€å»¶äžèŠçèåŽ</Attribute>
+            <Attribute name="comment">èŠçèåŽäžè¬å
+æ¬ç©ºéŽäœçœ®ïŒäžäžªå°åæå°çåæ ïŒãæ¶éŽåºéŽïŒäžäžªæ¶éŽæ è¯ïŒæ¥ææäžäžªæ¥æè    åŽïŒãæè
+æéïŒæ¯åŠåœåçææå®äœïŒæšèèŠçèåŽæå¥œæ¯åèªäºäžäžªåæ§è¯è¡šïŒäŸåŠå°åè¯åº    [TGN]ïŒïŒå¹¶åºå°œå¯èœå°äœ¿çšç±æ°å­è¡šç€ºçåæ ææ¥æåºéŽæ¥æè¿°å°åäžæ¶éŽæ®µã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">PokrytÃ­</Attribute>
+            <Attribute name="definition">Rozsah nebo zÃ¡bÄr obsahu zdroje.</Attribute>
+            <Attribute name="comment">PokrytÃ­ bude typicky obsahovat prostorovÃ© umÃ­stÄnÃ­ (jmÃ©no mÃ­sta nebo zemÄpisnÃ© souÅadnice), ÄasovÃ© obdobÃ­ (oznaÄenÃ­ obdobÃ­, datum nebo ÄasovÃœ interval) nebo jurisdikci (napÅ. jmÃ©no administrativnÃ­ jednotky). DoporuÄuje se vybÃ­rat hodnotu z ÅÃ­zenÃ©ho slovnÃ­ku (napÅ. Thesaurus of Geographic Names [TGN]) a tam, kde je to vhodnÃ©, uvÃ¡dÄt mÃ­sta nebo ÄasovÃ© Ãºseky spÃ­Å¡e jmÃ©nem neÅŸ ÄÃ­selnÃœmi identifikÃ¡tory jako jsou soubory souÅadnic nebo ÄasovÃ© intervaly.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Dekking</Attribute>
+            <Attribute name="definition">De ruimtelijke of tijdelijke karakteristieken van de intellectuele inhoud van de Internetbron. Ruimtelijke dekking verwijst naar een geografisch gebied. Gebruik coordinaten (longitude (lengtegraad) en latitude (breedtegraad)) of plaatsnamen die van een gecontroleerde lijst komen of volledig uitgeschreven zijn. Dekking in de tijd geeft de tijdsperiode aan waarop de inhoud van de Internetbron betrekking heeft en niet wanneer de Internetbron is gemaakt of beschikbaar is gesteld (dit laatste hoort ingevult te worden bij &quot;Date&quot;). Gebruik dezelfde datum/tijd formaat als bij &quot;Date&quot;; W3C Technical Note http://www.w3.org/TR/NOTE-datetime of tijdsperioden die van een gecontroleerde lijst komen of volledig uitgeschreven zijn. Coverage is in ontwikkeling bij de Dublin Core Working group http://www.alexandria.ucsb.edu/docs/metadata/dc_coverage.html.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Copertura</Attribute>
+            <Attribute name="definition">Le extension physic o abstracte del contento del ressource.</Attribute>
+            <Attribute name="comment">Le copertura typicamente include un location spatial (un nomine de localitate o coordinatas geographic), un periodo de tempore (un etiquetta de periodo, data, o gamma de datas), o un jurisdiction (tal como un entitate administrative nominate). Le practica recommendate es selectionar un valor a partir de un vocabulario controlate (per exemplo, le Thesaurus of Geographical Names [TGN]) e que, quando appropriate, localitates o periodos de tempore nominate sia utilizate in preferentia a identificatores numeric tales como collectiones de coordinatas o gammas de datas.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€µà¥à€¯à€Ÿà€ªà¥à€€à¥</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à¥ à€­à¥à€à¥à€²à€¿à€  à€®à€Ÿà€¹à€¿à€€à¥</Attribute>
+            <Attribute name="comment">à€à€Šà€Ÿ. à€­à¥à€à¥à€²à€¿à€ à€µà¥à€¯à€Ÿà€ªà¥à€€à¥</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+        <Element name="jurisdiction">
+            <Attribute language="en" name="label">Jurisdiction</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">The name of the political/administrative entity covered by the content of the resource.</Attribute>
+                <Attribute name="comment">Jurisdiction is a description of the territory over which a particular government exercises its authority or a particular business transacts its operations, to which the resource content is applicable.</Attribute>
+            </Language>
+        </Element>
+        <Element name="spatial">
+            <Attribute language="en" name="label">Spatial</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">Spatial characteristics of the intellectual content of the resource.</Attribute>
+                <Attribute name="comment">Spatial (geographic) coverage or locations or areas covered in the content of a resource. Use of the New Zealand Geographic Place Names Database (LINZ) may be appropriate. In some cases the DCMI Box Encoding Scheme may be suitable. Refer: http//dublincore.org.documents/2000/07/28/dcmi-box/</Attribute>
+            </Language>
+        </Element>
+        <Element name="temporal">
+            <Attribute language="en" name="label">Temporal</Attribute>
+            <Attribute language="en" name="qualifier type">element refinement</Attribute>
+            <Language code="en">
+                <Attribute name="definition">Temporal characteristics of the intellectual content of the resource.</Attribute>
+                <Attribute name="comment">The refinement &amp;quot;temporal&amp;quot; refers to time periods that are covered by or discussed in the content of resource. Time periods will generally be best expressed as date ranges, although named periods may be appropriate. The recommended encoding schemes for dates and date ranges are noted in the section on Date.</Attribute>
+            </Language>
+        </Element>
+    </Element>
+    <Element name="Rights">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Rights Management</Attribute>
+            <Attribute name="definition">Information about rights held in and over the resource.</Attribute>
+            <Attribute name="comment">Typically, a Rights element will contain a rights management statement for the resource, or reference a service providing such information. Rights information often encompasses Intellectual Property Rights (IPR), Copyright, and various Property Rights. If the Rights element is absent, no assumptions can be made about the status of these and other rights with respect to the resource.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Motika</Attribute>
+            <Attribute name="definition">Ko nga mohiohio ki nga motika o tetahi rauemi.</Attribute>
+            <Attribute name="comment">Ko te tikanga, kei te huanga Motika e pupuri ana he korero mo te whakaritenga motika mo te rauemi, he ratonga tohutoro e whakarato ana ranei i enei tumomo mohiohio. He nui nga wa, puta ai i roto i te mohiohio Motika te Mana Whakairo Hinegaro (Intellectual Property Rights - (IPR)), te Manatarua me nga Tuahua Mana Taonga (Property Rights). Ki te kore te huanga Motika, kaore e taea te pohehe noa ki te mana o enei, nga motika ranei e pa ana ki te rauemi.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Droits</Attribute>
+            <Attribute name="definition">Information sur les droits sur et au sujet de la ressource.</Attribute>
+            <Attribute name="comment">Typiquement, un Ã©lÃ©ment Droits contiendra un Ã©tat du droit Ã  gÃ©rer une ressource, ou la refÃ©rence Ã  un service fournissant cette information. Ces droits souvent couvrent les droits de propriÃ©tÃ© intellectuelle (IPR), Copyright, et divers droits de propriÃ©tÃ©. Si l&apos;Ã©lÃ©ment Droits est absent, aucune hypothÃšse ne peut Ãªtre faite sur l&apos;Ã©tat de ces droits, ou de tout autre, par rapport Ã  la ressource.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÑÐ°Ð²ÐŸÐ²ÐŸÐµ ÑÐµÐ³ÑÐ»ÐžÑÐŸÐ²Ð°ÐœÐžÐµ</Attribute>
+            <Attribute name="definition">ÐÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ Ð¿ÑÐ°Ð²Ð°Ñ
+ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ, ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐ°ÑÑÑ Ð²ÐœÑÑÑÐž Ðž Ð²ÐœÐµ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÐ±ÑÑÐœÐŸ ÑÐ»ÐµÐŒÐµÐœÑ ÐÑÐ°Ð²Ð° ÑÐŸÐŽÐµÑÐ¶ÐžÑ Ð¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐžÐµ ÐŸ Ð¿ÑÐ°Ð²ÐŸÐ²ÑÑ
+ ÐœÐŸÑÐŒÐ°Ñ
+, ÑÐµÐ³ÑÐ»ÐžÑÑÑÑÐžÑ
+ ÑÑÐœÐºÑÐžÐŸÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÑÐµÑÑÑÑÐ° ÐžÐ»Ðž ÑÑÑÐ»ÐºÑ ÐœÐ° ÑÐ»ÑÐ¶Ð±Ñ, Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÑÑÑÑÑ ÑÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ. ÐÑÐ°Ð²ÐŸÐ²Ð°Ñ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸÐ±ÑÑÐœÐŸ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÑÐ²ÐµÐŽÐµÐœÐžÑ ÐŸ ÐÑÐ°Ð²Ð°Ñ
+ ÐžÐœÑÐµÐ»Ð»ÐµÐºÑÑÐ°Ð»ÑÐœÐŸÐ¹ ÑÐŸÐ±ÑÑÐ²ÐµÐœÐœÐŸÑÑÐž, ÐÐ²ÑÐŸÑÑÐºÐŸÐŒ Ð¿ÑÐ°Ð²Ðµ Ðž ÐŽÑÑÐ³ÐžÑ
+ ÐÐŒÑÑÐµÑÑÐ²ÐµÐœÐœÑÑ
+ Ð¿ÑÐ°Ð²Ð°Ñ
+. ÐÑÑÑÑÑÑÐ²ÐžÐµ ÑÐ»ÐµÐŒÐµÐœÑÐ° ÐÑÐ°Ð²Ð° ÐœÐµ ÐŒÐŸÐ¶ÐµÑ ÑÐ²Ð»ÑÑÑÑÑ ÐŸÑÐœÐŸÐ²Ð°ÐœÐžÐµÐŒ ÐŽÐ»Ñ ÐºÐ°ÐºÐžÑ
+-Ð»ÐžÐ±ÐŸ Ð¿ÑÐµÐŽÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐžÐ¹ ÐŸ Ð¿ÑÐ°Ð²ÐŸÐ²ÐŸÐŒ ÑÑÐ°ÑÑÑÐµ Ðž ÐŽÑÑÐ³ÐžÑ
+ Ð¿ÑÐ°Ð²Ð°Ñ
+, ÐºÐ°ÑÐ°ÑÑÐžÑ
+ÑÑ ÑÐµÑÑÑÑÐ°.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Derechos</Attribute>
+            <Attribute name="definition">Una referencia (URL, por ejemplo) para una nota sobre derechos de autor, para un servicio de gestiÃ³n de derechos o para un servicio que darÃ¡ informaciÃ³n sobre tÃ©rminos y condiciones de acceso a un recurso. Una especificaciÃ³n formal del elemento Rights se encuentra catualmente en discusiÃ³n y por lo tanto su uso se considera experimental.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø­ÙÙÙ Ø§ÙØ§Ø¯Ø§Ø±Ø©</Attribute>
+            <Attribute name="definition">ÙÙ Ø§ÙØ§Ø¯Ø© Ø­ÙÙÙ Ø§ÙØ§Ø¯Ø§Ø±Ø© , Ù
+Ø¹Ø±Ù Ù
+Ø±ØªØšØ· ØšØ§ÙØ§Ø¯Ø© Ø­ÙÙÙ Ø§ ÙØ§Ø¯Ø§Ø±Ø© , Ù
+Ø¹Ø±Ù Ù
+Ø±ØªØšØ· ØšØ®Ø¯Ù
+Ø© ØªÙØ¯Ù
+ Ù
+Ø¹ÙÙÙ
+Ø§Øª Ø¹Ù Ø­ÙÙÙ Ø§ÙØ§Ø¯Ø§Ø±Ø© Ø§ÙØ®Ø§ØµØ© ØšØ§ÙÙ
+ØµØ¯Ø±</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">æé</Attribute>
+            <Attribute name="definition">æå
+³èµæºæ¬èº«ææçæè¢«èµäºçæéä¿¡æ¯</Attribute>
+            <Attribute name="comment">äžè¬èèšïŒæéå
+çŽ åºå
+æ¬äžäžªå¯¹èµæºçæéå£°æïŒæè
+æ¯å¯¹æäŸè¿äžä¿¡æ¯çæå¡çåç
+§ãæéäžè¬    å
+æ¬ç¥è¯äº§æ(IPR)ïŒçææå
+¶ä»åç§åæ ·çäº§æãåŠææ²¡ææéå
+çŽ çæ æ³šïŒäžå¯ä»¥å¯¹äžèµæºçžå
+³    çäžè¿°æå
+¶ä»æå©çæ
+åµäœåºä»»äœåå®ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">PrÃ¡va</Attribute>
+            <Attribute name="definition">Informace o prÃ¡vech vztahujÃ­cÃ­ch se k popisovanÃ©mu zdroji.</Attribute>
+            <Attribute name="comment">Prvek PrÃ¡va bude typicky obsahovat ustanovenÃ­ o sprÃ¡vÄ autorskÃœch/vlastnickÃœch prÃ¡v ke zdroji nebo odkaz na sluÅŸbu poskytujÃ­cÃ­ takovÃ©to informace. Informace o prÃ¡vech Äasto zahrnujÃ­ prÃ¡va duÅ¡evnÃ­ho vlastnictvÃ­ (IPR), autorskÃ© prÃ¡vo a rÅ¯znÃ¡ vlastnickÃ¡ prÃ¡va. JestliÅŸe prvek PrÃ¡va chybÃ­, nelze odvozovat ÅŸÃ¡dnÃ© pÅedpoklady o stavu tÄchto a jinÃœch prÃ¡v vztahujÃ­cÃ­ch se k popisovanÃ©mu zdroji.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Copyright</Attribute>
+            <Attribute name="definition">Een copyright verklaring of een link naar een copyright verklaring of een link naar een service die informatie geeft over de copyright van de Internetbron.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Gestion de derectos</Attribute>
+            <Attribute name="definition">Information super derectos detenite super e a proposito del ressource.</Attribute>
+            <Attribute name="comment">Typicamente le elemento derectos continera un declaration de gestion de derectos pro le ressource, o un referentia a un servicio que provide tal information. Information de derectos frequentemente involve derectos de proprietate intellectual (IPR), copyright e varie derectos de proprietate. Si le elemento Derectos es absente, necun hypothese pote esser facite quanto al stato de iste e altere derectos concernente ressource.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€¹à€à¥à€</Attribute>
+            <Attribute name="definition">à€¬à¥à€§à¥à€Šà€¿à€ à€žà€à€ªà€Šà¥à€à€Ÿà€¹à€à¥à€</Attribute>
+            <Attribute name="comment">à€žà¥à€µà€€à€à€¹à€Ÿà€à¥ à€²à¥à€à€š à€à€Ÿà€ªà¥à€š à€
+à€¥à€µà€Ÿ à€®à€Ÿà€¹à€¿à€€à¥à€à€Ÿà€³à¥à€¯à€Ÿà€µà€° à€ªà¥à€°à€à€Ÿà€¶à€¿à€€ à€à€°à€£à¥à€¯à€Ÿà€à€Ÿ à€²à¥à€à€ à€
+à€¥à€µà€Ÿ à€²à¥à€à€¿à€à¥à€à€Ÿ à€¬à¥à€§à¥à€Šà€¿à€ à€žà€à€ªà€Šà¥à€à€Ÿà€¹à€à¥à€</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+</MetadataSet>
Index: /tags/greenstone-3_02-distribution/gli/metadata/qdublin.mds
===================================================================
--- /tags/greenstone-3_02-distribution/gli/metadata/qdublin.mds	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/metadata/qdublin.mds	(revision 13928)
@@ -0,0 +1,1908 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE MetadataSet SYSTEM "http://www.greenstone.org/dtd/MetadataSet/1.0/MetadataSet.dtd">
+<MetadataSet contact="dcmi-feedback@dublincore.org" creator="Dublin Core Metadata Initiative" family="Dublin Core" language_dependent="label, definition, comment" lastchanged="Tue Sep 05 14:40:36 NZST 2006 - kjdon on kanuka" namespace="dc">
+    <!-- English Version sourced from http://www.dublincore.org/documents/dces/ -->
+    <SetLanguage code="en">
+        <Name language="en">Qualified Dublin Core Metadata Element Set, Version 1.1: Reference Description</Name>
+        <Description language="en">This document is the reference description, version 1.1 of the Dublin Core Metadata Element Set. This document supersedes the Dublin Core Metadata Element Set, version 1.0. See the Dublin Core Home Page (http://dublincore.org) for further information about the workshops, reports, working group papers, projects, and new developments concerning the Dublin Core Metadata Element set</Description>
+    </SetLanguage>
+    <!-- Maori Version sourced from http://www.tki.org.nz/r/maori/pedagogy/dc_elements_m.php -->
+    <SetLanguage code="mi">
+        <Name>Dublin Core Huanga - Maori (He Tauira)</Name>
+    </SetLanguage>
+    <!-- French Version sourced from http://www-rocq.inria.fr/%7Evercoust/METADATA/DC-fr.1.1.html -->
+    <!--  by Anne-Marie Vercoustre, Inria -->
+    <SetLanguage code="fr">
+        <Name language="fr">ElÃ©ments de mÃ©tadonnÃ©es du Dublin Core, Version 1.1: Description de RÃ©ference</Name>
+        <Description language="fr">Ce document rÃ©sume les derniÃšres dÃ©finitions des Ã©lÃ©ments demÃ©tadonnÃ©es du Dublin Core originellement dÃ©finis dans le document[RFC2413]. Ces nouvelles dÃ©finitions seront officiellement connues comme la Version 1.1. Elles utilisent un standard dÃ©fini formellement pour la description d&apos;Ã©lÃ©ments de mÃ©tadonnÃ©es. Cette formalisation contribue Ã  amÃ©liorer la cohÃ©rence avec d&apos;autres communautÃ©s dÃ©crivant des mÃ©tadonnÃ©es et Ã  augmenter la prÃ©cision, la portÃ©e et la cohÃ©rence interne de la dÃ©finition des Ã©lÃ©ments du Dublin Core.</Description>
+    </SetLanguage>
+    <!-- Russian Version sourced from -->
+    <!-- by Olga Barysheva, National Library of Russia -->
+    <SetLanguage code="ru">
+        <Name language="ru">ÐÐ°Ð±ÐŸÑ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Dublin Core (ÐÑÐ±Ð»ÐžÐœÑÐºÐŸÐ³ÐŸ ÑÐŽÑÐ°) ÐÐµÑÑÐžÑ 1.1: Ð¡Ð¿ÑÐ°Ð²ÐŸÑÐœÐŸÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ</Name>
+        <Description language="ru">ÐÐ°ÑÑÐŸÑÑÐžÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑ ÐŸÐ±ÐŸÐ±ÑÐ°ÐµÑ ÐŸÐ±ÐœÐŸÐ²Ð»ÐµÐœÐœÑÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Dublin Core (ÐÑÐ±Ð»ÐžÐœÑÐºÐŸÐ³ÐŸ ÑÐŽÑÐ°), Ð¿ÐµÑÐ²ÐŸÐœÐ°ÑÐ°Ð»ÑÐœÐŸ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÑ
+ Ð² RFC2413 (ÐÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Dublin Core ÐŽÐ»Ñ ÐœÐ°Ñ
+ÐŸÐ¶ÐŽÐµÐœÐžÑ ÑÐµÑÑÑÑÐŸÐ²). Ð­ÑÐž ÐœÐŸÐ²ÑÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ ÐŸÑÐžÑÐžÐ°Ð»ÑÐœÐŸ ÐžÐ·Ð²ÐµÑÑÐœÑ ÐºÐ°Ðº ÐÐµÑÑÐžÑ 1.1.</Description>
+    </SetLanguage>
+    <!-- Spanish Version sourced from http://www.rediris.es/metadata/. Please note that this is a translation for Dublin Core v1.0 -->
+    <!-- by Javi Masa, RedIRIS -->
+    <SetLanguage code="es">
+        <Name language="es">Elementos del conjunto de metadatas de Dublin Core: DescripciÃ³n de Referencia</Name>
+        <Description language="es">Este documento corresponde a una traducciÃ³n del original en lengua inglesa, con fecha 02/11/1997 que se encuentra en http://purl.org/metadata/dublin_core_elements. Este documento es una descripciÃ³n de referencia de los elementos del conjunto de &quot;Dublin Core&quot;. Para mÃ¡s informaciÃ³n sobre reuniones de trabajo, documentos de trabajo, proyectos y nuevos desarrollos relacionados con el conjunto de elementos que aquÃ­ se describen consultar la &quot;Home Page&quot; de &quot;Dublin Core&quot; (http://purl.org/metadata/dublin_core). Los elementos poseen nombres descriptivos que pretenden transmitir un significado semÃ¡ntico a los mismos. Para promover una interoperabilidad global, una descripciÃ³n del valor de algunos elementos prodrÃ¡ ser asociada a vocabularios controlados. Se asume que otros vocabularios controlados serÃ¡n desarrollados para asegurar esta interoperabilidad en dominios especÃ­ficos. Cada elemento es opcional y puede repetirse. AdemÃ¡s, los elementos pueden aparecer en cualquier orden. Aunque algunos entornos, como HTML, no diferencian entre mayÃºsculas y minÃºsculas, es recomendable escribir correctamente cada metadata segÃºn su definiciÃ³n para evitar conflictos con otros entornos, como XML (Extensible Markup Language) http://www.w3.org/TR/PR-xml</Description>
+    </SetLanguage>
+    <!-- Arabic Version sourced from http://haddouti.de/DC_arabic.html -->
+    <!-- maintained by Hachim Haddouti. -->
+    <SetLanguage code="ar">
+        <Name>Ø¯ØšÙÙÙ ÙÙØ±</Name>
+        <Description>ÙØ±Ø­Øš ØšÙÙ
+ ÙÙ ØµÙØ­Ø©  Ø¯ ØšÙÙÙ ÙÙ  Ø± ØšØ§ÙØ¹Ø±ØšÙ    ÙÙ  ÙØ°Ù Ø§ÙØµÙØ­Ø©  Ù ØšØ§ÙØªØ¹Ø§ÙÙ Ù
+Ø¹ Ø§ÙØ§Ø®ÙØ§Ù Ø§ÙØ¹Ø±Øš Ù
+Ù Ø§ÙÙ
+ÙØªØšØ§ØªØ Ø¯Ø§Ø± Ø§ÙÙØŽØ±Ø Ø§ÙØšØ­ÙØ« Ø§ÙØ¹ÙÙ
+ÙØ© Ù    ÙØ±ØŽØ© Ø¹Ù
+ÙWorking Group On Multilingual Dublin Core (DC-International) Ø</Description>
+    </SetLanguage>
+    <!-- Chinese - Simplified Version from http://dc.library.sh.cn/DC/1-1.htm -->
+    <!-- by Liu Wei, Shanghai Library -->
+    <SetLanguage code="cn">
+        <Name>éœæææ žå¿å
+æ°æ®å
+çŽ é1.1çïŒåèæè¿°</Name>
+        <Description>æ¬ææ¡£å
+³äºéœæææ žå¿å
+æ°æ®å
+çŽ é1.1çæ¬çåèæè¿°ãæ­€æè¿°äžå·²ç»æäº€ç»ISOçšäºåœé
+æç¥šçNISOå®æ¹æ åä¿æäžèŽã    éœæææ žå¿å
+æ°æ®éæ¯äžç§è·šé¢åçä¿¡æ¯èµæºæè¿°æ åãè¿éçä¿¡æ¯èµæºè¢«å®ä¹äžºâä»»äœå
+·ææ è¯çäžè¥¿âãæ­€å®ä¹æ¥èªäºTim Berners-Leeç­äººæèçInternet RFC2396 &quot;Uniform Resource Identifiers (URI): Generic Syntax&quot;æä»¶ãéœæææ žå¿å
+æ°æ®çåºçšé¢åæ²¡ææ ¹æ¬çéå¶ã</Description>
+    </SetLanguage>
+    <!-- Czech Version from http://www.ics.muni.cz/dublin_core/DC-czech-1.1.html -->
+    <!-- Ustav vypocetni techniky Masarykovy univerzity v Brne -->
+    <SetLanguage code="cs">
+        <Name>Soubor metadatovÃœch prvkÅ¯ Dublin Core, verze 1.1: referenÄnÃ­ popis</Name>
+        <Description>Tento dokument je ÄeskÃœm pÅekladem anglickÃ© verze referenÄnÃ­ho popisu souboru metadatovÃœch prvkÅ¯  Dublin Core, verze 1.1 [DCEN1.1]. Tento dokument nahrazuje ÄeskÃœ pÅeklad souboru metadatovÃœch prvkÅ¯ Dublin Core, verze 1.0 [DCCS1.0]. DalÅ¡Ã­ informace o pracovnÃ­ch seminÃ¡ÅÃ­ch (workshopech), zprÃ¡vÃ¡ch, studiÃ­ch pracovnÃ­ch skupin, projektech a dalÅ¡Ã­m vÃœvoji souboru metadatovÃœch prvkÅ¯ Dublin Core najdete na domovskÃ© strÃ¡nce Dublin Core (http://purl.org/dc)</Description>
+    </SetLanguage>
+    <!-- Dutch Version from http://www.kb.nl/coop/donor/project-nl-index.html?/coop/donor/rapporten/DCsimpleformat.html -->
+    <!-- by ... -->
+    <SetLanguage code="nl">
+        <Name>Rapporten Dublin Core Simple Format</Name>
+        <Description>Dit document beschrijft welke Dublin Core metadata elementen er zijn en geeft een korte definitie van elk element. Voor uitgebreide uitleg en gebruik van de Dublin Core elementen wordt u verwezen naar de gebruikershandleiding. Deze vertaling geeft ook de keuzes aan voor standaarden (taalcodes, datum codes) die wij in DONOR verband gaan hanteren. In zoverre kan deze vertaling afwijken van het oorspronkelijke document &quot;Description of Dublin Core Elements&quot; http://purl.org/metadata/dublin_core_elements&quot;</Description>
+    </SetLanguage>
+    <!-- Finnish Version from http://www.lib.helsinki.fi/dublin_core/dcref-fin.html -->
+    <!-- by Jani Stenvall and Juha Hakala, Helsinki University Library -->
+    <SetLanguage code="fi">
+        <Name/>
+        <Description/>
+    </SetLanguage>
+    <!-- Interlingua Version sourced from http://www.nautilus.com.br/%7Eensjo/ia/purl.org/dc/documents/rec-dces-19990702.htm -->
+    <!-- by Emerson Jose` Silveira da Costa -->
+    <SetLanguage code="ia">
+        <Name>Collection de elementos de metadatos de Dublin Core, version 1.1: Description de referentia</Name>
+        <Description>Isto es un traduction de un Recommendation del Dublin Core Metadata Initiative. Le publication como un recommendation significa que le specificationes es stabile e su adoption es supportate per le communitate Dublin Core (http://purl.org/dc/).</Description>
+    </SetLanguage>
+    <!-- Marathi Version sourced from http://bioinfo.ernet.in/library/dc/ele.txt -->
+    <!-- by by Shubhada Nagarkar, Bioinformatics Centre, University of Pune -->
+    <SetLanguage code="mr">
+        <Name>à€¡à€¬à¥à€²à€¿à€š à€à¥à€° à€®à¥à€à€Ÿà€¡à¥à€à€Ÿ à€žà¥à€ à€à€µà¥à€€à¥à€€à¥ à¥§.à¥§ à€žà€à€Šà€°à¥à€­ à€žà¥à€ªà€·à¥à€à¥à€à€°à€£ à¥§.à¥§ à€¡à€¬à¥à€²à€¿à€š à€à¥à€° à€®à¥à€à€Ÿà€¡à¥à€à€Ÿà€à€µà¥à€€à¥à€€à¥ à¥§.à¥§.</Name>
+        <Description>à¥§.à¥§ à€¡à€¬à¥à€²à€¿à€š à€à¥à€° à€®à¥à€à€Ÿà€¡à¥à€à€Ÿ à€¹à¥ à€µà¥à€à€µà¥à€à€³à¥à€¯à€Ÿ à€µà€¿à€·à€¯à€Ÿà€€à¥à€² à€®à€Ÿà€¹à¥à€€à¥ à€žà€Ÿà€ à¥à€¯à€Ÿà€à€µà€Šà¥à€Šà€²à€à¥ à€®à€Ÿà€¹à¥à€€à¥ à€Šà¥à€£à¥à€¯à€Ÿà€à¥ à€®à€Ÿà€šà€ à€à€¹à¥.  à€¯à€Ÿà€€ à€®à€Ÿà€¹à¥à€€à¥à€žà€Ÿà€ à€Ÿ à€®à¥à€¹à€£à€à¥ à€à¥à€¯à€Ÿà€²à€Ÿ à€à€³à€ à€à€¹à¥ à€
+à€žà€Ÿ à€à€žà€€à¥.  à€
+à€¶à€Ÿ à€ªà¥à€°à€à€Ÿà€°à€à¥ à€µà¥à€¯à€Ÿà€à¥à€¯à€Ÿ à€®à€Ÿà€¹à¥à€€à¥ à€à€Ÿà€³à¥à€¯à€µà€°à¥à€² à€. à€à€«.à€žà¥. à¥šà¥©à¥¯à¥¬URI: Generic Syntax -- Tim Berners Lee et al. à€¡à€¬à¥à€²à€¿à€š à€à¥à€° à€®à€Ÿà€šà€ à€à¥à€£à€€à¥à€¯à€Ÿà€¹à¥ à€ªà¥à€°à€à€Ÿà€°à€à¥à€¯à€Ÿ à€®à€Ÿà€¹à¥à€€à¥ à€žà€Ÿà€ à¥à€¯à€Ÿà€à€žà€Ÿà€ à¥ à€µà€Ÿà€ªà€°à€€à€Ÿ à€¯à¥à€€à¥.  à€€à¥à€¯à€Ÿà€žà€Ÿà€ à¥ à€à¥à€£à€€à€Ÿà€¹à¥ à€®à€à¥à€à€Ÿà€µ à€šà€Ÿà€¹à¥.</Description>
+    </SetLanguage>
+    <Element name="Title" >
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Title</Attribute>
+            <Attribute name="definition">A name given to the resource.</Attribute>
+            <Attribute name="comment">Typically, a Title will be a name by which the resource is formally known.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Taitara</Attribute>
+            <Attribute name="definition">Te ingoa ka tapaina tetahi rauemi.</Attribute>
+            <Attribute name="comment">Ko te tikanga, ko te Taitara te ingoa ka mohio whanuitia te ingoa.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Titre</Attribute>
+            <Attribute name="definition">Le nom donnÃ© Ã  la ressource.</Attribute>
+            <Attribute name="comment">Typiquement, un titre sera le nom par lequel la ressource est officiellement connue.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÐ°Ð·Ð²Ð°ÐœÐžÐµ</Attribute>
+            <Attribute name="definition">ÐÐŒÑ, ÐŽÐ°ÐœÐœÐŸÐµ ÑÐµÑÑÑÑÑ.</Attribute>
+            <Attribute name="comment">ÐÐ±ÑÑÐœÐŸ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµÐŒ ÑÐ²Ð»ÑÐµÑÑÑ ÐžÐŒÑ, Ð¿ÐŸÐŽ ÐºÐŸÑÐŸÑÑÐŒ ÑÐµÑÑÑÑ ÐŸÑÐžÑÐžÐ°Ð»ÑÐœÐŸ ÐžÐ·Ð²ÐµÑÑÐµÐœ.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">TÃ­tulo</Attribute>
+            <Attribute name="definition">El nombre dado a un recurso, usualmente por el autor.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙØ¹ÙÙØ§Ù</Attribute>
+            <Attribute name="definition">ÙØ°Ø§ Ø§ÙØ§Ø³Ù
+ ÙØ¹Ø·Ù ÙÙÙ
+ØµØ¯Ø±, Ù
+Ù ÙØšÙ Ø§ÙÙ
+ØšØ¯Ø¹ Ø§Ù Ø§ÙÙØ§ØŽØ±</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">èµæºå</Attribute>
+            <Attribute name="definition">èµäºèµæºçåç§°ã</Attribute>
+            <Attribute name="comment">èµæºåäžè¬æèµæºå¯¹è±¡æ­£åŒå
+¬åŒçåç§°ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">NÃ¡zev</Attribute>
+            <Attribute name="definition">JmÃ©no danÃ© zdroji.</Attribute>
+            <Attribute name="comment">NÃ¡zev bude typicky jmÃ©no, pod nÃ­mÅŸ je zdroj oficiÃ¡lnÄ znÃ¡m.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Titel</Attribute>
+            <Attribute name="definition">De naam van de Internetbron. Meestal gegeven door de auteur, maker of uitgever</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Titulo</Attribute>
+            <Attribute name="definition">Un nomine date al ressource.</Attribute>
+            <Attribute name="comment">Typicamente se utiliza un nomine per le qual le ressource es formalmente cognite.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€¶à¥à€°à¥à€·à€</Attribute>
+            <Attribute name="definition">à€ªà€°à¥à€¯à€Ÿà€¯à¥ à€¶à¥à€°à¥à€·à€</Attribute>
+            <Attribute name="comment">à€žà€à€à¥à€·à€¿à€ªà¥à€€ ,  à€­à€Ÿà€·à€Ÿà€à€€à€°à¥à€€  à€¶à¥à€°à¥à€·à€</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+        <Element name="alternative">
+            <Attribute language="en" name="status">recommended</Attribute>
+            <Language code="en">
+                <Attribute name="label">Alternative</Attribute>
+                <Attribute name="definition">Any form of the title used as a substitute or alternative to the formal title of the resource.</Attribute>
+                <Attribute name="comment">This qualifier can include Title abbreviations as well as translations.</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+        </Element>
+    </Element>
+    <Element name="Creator" >
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Creator</Attribute>
+            <Attribute name="definition">An entity primarily responsible for making the content of the resource.</Attribute>
+            <Attribute name="comment">Examples of a Creator include a person, an organisation, or a service. Typically, the name of a Creator should be used to indicate the entity.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Kaihanga</Attribute>
+            <Attribute name="definition">Te putahi, nana, na ratou ranei i matua oti ai te hanganga o te rauemi.</Attribute>
+            <Attribute name="comment">Ko te tangata, he putahitanga, he ratonga ranei etahi tauira Kaihanga. Ko te tikanga, ko te Kaihanga te ingoa ka whakamahia hei tohu i te putahi na ratou te hanganga.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">CrÃ©ateur</Attribute>
+            <Attribute name="definition">L&apos;entitÃ© principalement responsable de la crÃ©ation du contenu de la ressource.</Attribute>
+            <Attribute name="comment">Exemples de CrÃ©ateur incluent une personne, une organisation, ou un service. Typiquement, un nom du CrÃ©ateur devrait Ãªtre utilisÃ© pour dÃ©signer cette entitÃ©.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">Ð¡ÐŸÐ·ÐŽÐ°ÑÐµÐ»Ñ</Attribute>
+            <Attribute name="definition">ÐÐžÑÐŸ, ÐœÐµÑÑÑÐµÐµ Ð¿ÐµÑÐ²ÐžÑÐœÑÑ ÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÐŸÑÑÑ Ð·Ð° ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÑÐžÐŒÐµÑÑ Ð¡ÐŸÐ·ÐŽÐ°ÑÐµÐ»Ñ Ð²ÐºÐ»ÑÑÐ°ÑÑ Ð¿ÐµÑÑÐŸÐœÑ, ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÑ ÐžÐ»Ðž ÑÐ»ÑÐ¶Ð±Ñ. ÐÐ±ÑÑÐœÐŸ ÐžÐŒÑ Ð¡ÐŸÐ·ÐŽÐ°ÑÐµÐ»Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÐžÐœÐŽÐžÐºÐ°ÑÐžÐž ÐŸÐ±ÑÐµÐºÑÐ°.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Autor o Creador</Attribute>
+            <Attribute name="definition">La persona u organizaciÃ³n responsable de la creaciÃ³n del contenido intelectual del recurso. Por ejemplo, los autores en el caso de documentos escritos, artistas, fotografos e ilustradores en el caso de recursos visuales.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙÙØ§ØªØš Ø§Ù Ø§ÙÙ
+ØšØ¯Ø¹</Attribute>
+            <Attribute name="definition">ÙÙ Ø§ÙØŽØ®Øµ Ø§Ù Ø§ÙÙ
+Ø€Ø³Ø³Ø© Ø£ÙÙØ§  Ø¹Ù ÙØŽØŠ Ø§ÙÙ
+Ø­ØªÙÙ Ø§ÙÙÙØ± Ù ÙÙÙ
+ØµØ¯Ø± , Ø¹ÙÙ Ø³ØšÙÙ Ø§ÙÙ
+Ø«Ø§Ù , Ø§ÙÙ
+Ø€ÙÙÙÙ ÙÙ Ø­Ø§ÙØ© Ø§ÙØ«Ø§ØŠÙ Ø§ÙÙ
+ÙØªÙØšØ© , Ù Ø§ÙÙÙØ§ÙÙÙ , Ø§ÙÙ
+ØµÙØ±ÙÙ ÙÙ Ø­Ø§ÙØ© Ø§ÙÙ
+ØµØ§Ø¯Ø± Ø§ÙÙ
+Ø±ØŠÙØ©</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">åå»ºè
+</Attribute>
+            <Attribute name="definition">åå»ºèµæºå
+å®¹çäž»èŠèŽ£ä»»è
+ã</Attribute>
+            <Attribute name="comment">åå»ºè
+çå®äŸå
+æ¬äžªäººïŒç»ç»ææé¡¹æå¡ãäžè¬èèšïŒçšåå»ºè
+çåç§°æ¥æ è¯è¿äžæ¡ç®ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">TvÅ¯rce</Attribute>
+            <Attribute name="definition">Entita primÃ¡rnÄ odpovÄdnÃ¡ za vytvoÅenÃ­ obsahu zdroje.</Attribute>
+            <Attribute name="comment">PÅÃ­klady TvÅ¯rce zahrnujÃ­ osobu, organizaci nebo sluÅŸbu. K oznaÄenÃ­ entity se typicky pouÅŸÃ­vÃ¡ jmÃ©no tvÅ¯rce.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Auteur of maker</Attribute>
+            <Attribute name="definition">De auteur, maker of organisatie die primair verantwoordelijk is voor de intellectuele inhoud van het werk. Bijvoorbeeld auteurs in geval van geschreven documenten, artiesten, fotografen of illustrators in geval van visuele bronnen.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Creator</Attribute>
+            <Attribute name="definition">Le entitate primarimente responsabile pro producer le contento del ressource.</Attribute>
+            <Attribute name="comment">Exemplos de creator include un persona, un organization, o un servicio. Typicamente se utiliza un nomine de creator pro indicar iste entitate.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€šà€¿à€°à¥à€®à€Ÿà€€à€Ÿ, à€à€šà€</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à€Ÿ à€šà€¿à€°à¥à€®à€Ÿà€£  à€à€°à€£à€Ÿà€°à€Ÿ</Attribute>
+            <Attribute name="comment">à€à€Šà€Ÿ.  à€²à¥à€à€, à€²à¥à€à€¿à€à€Ÿ,  à€µà¥à€¯à€à¥à€€à¥, à€žà€à€žà¥à€¥à€Ÿ,  à€žà€à€ªà€Ÿà€Šà€, à€žà€à€ªà€Ÿà€Šà€¿à€à€Ÿ</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Subject" >
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Subject and Keywords</Attribute>
+            <Attribute name="definition">The topic of the content of the resource.</Attribute>
+            <Attribute name="comment">Typically, a Subject will be expressed as keywords, key phrases or classification codes that describe a topic of the resource. Recommended best practice is to select a value from a controlled vocabulary or formal classification scheme.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Kaupapa</Attribute>
+            <Attribute name="definition">Te take/ nga take o te kaupapa, o te rauemi.</Attribute>
+            <Attribute name="comment">Ko te tikanga, ka whakaaturia te kaupapa o te rauemi e nga kupu matua, nga kimahi matua, nga tohu wehewehenga whakaahua ranei.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Sujet</Attribute>
+            <Attribute name="definition">Le sujet du contenu de la ressource.</Attribute>
+            <Attribute name="comment">Typiquement, le sujet sera dÃ©crit par un ensemble de mots-clefs ou de phrases ou un code de classification qui prÃ©cisent le sujet de la ressource. L&apos;utilisation de vocabulaires contrÃŽlÃ©s et de schÃ©mas formels de classification est encouragÃ©e.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÑÐµÐŽÐŒÐµÑ Ðž ÐºÐ»ÑÑÐµÐ²ÑÐµ ÑÐ»ÐŸÐ²Ð°</Attribute>
+            <Attribute name="definition">Ð¢ÐµÐŒÐ° ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÐ±ÑÑÐœÐŸ ÐÑÐµÐŽÐŒÐµÑ Ð²ÑÑÐ°Ð¶Ð°ÐµÑÑÑ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÐºÐ»ÑÑÐµÐ²ÑÑ
+ ÑÐ»ÐŸÐ², ÐºÐ»ÑÑÐµÐ²ÑÑ
+ ÑÑÐ°Ð· ÐžÐ»Ðž  ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐŸÐœÐœÑÑ
+ ÐºÐŸÐŽÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÐŸÐ¿ÐžÑÑÐ²Ð°ÑÑ ÑÐµÐŒÑ ÑÐµÑÑÑÑÐ°. ÐÐ»Ñ Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ Ð²ÑÐ±ÐžÑÐ°ÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐžÐ· ÐºÐŸÐœÑÑÐŸÐ»ÐžÑÑÐµÐŒÐŸÐ³ÐŸ ÑÐ»ÐŸÐ²Ð°ÑÑ ÐžÐ»Ðž ÑÐŸÑÐŒÐ°Ð»ÑÐœÐŸÐ¹ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÑÑ
+ÐµÐŒÑ.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Claves</Attribute>
+            <Attribute name="definition">Los tÃ³picos del recurso. TÃ­picamente, Subject expresarÃ¡ las claves o frases que describen el tÃ­tulo o el contenido del recurso. Se fomentarÃ¡ el uso de vocabularios controlados y de sistemas de clasificaciÃ³n formales. Se pueden ver ejemplos de vocabularios controlados en: Controlled vocabularies, thesauri and classification systems available in the WWW. DC Subject</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙÙ
+ÙØ¶ÙØ¹ Ù Ø§ÙÙÙÙ
+Ø§Øª Ø§ÙØ±ØŠÙØ³ÙØ©</Attribute>
+            <Attribute name="definition">ÙÙ Ù
+ÙØ¶ÙØ¹ Ø§ÙÙ
+ØµØ¯Ø±. ÙÙ
+ÙØ°Ø¬ÙØ§  ÙØ¹ØšØ± Ø¹Ù Ø§ÙÙ
+ÙØ¶ÙØ¹ ØšØ§Ø³ØªØ®Ø¯Ø§Ù
+Ù
+ÙØªØ§Ø­  Ø§ÙÙÙÙ
+Ø§Øª  Ø§Ù Ø¬Ù
+Ù Ø§ÙØªÙ  ØªØµÙ Ù
+ÙØ¶ÙØ¹ Ø§Ù Ù
+Ø­ØªÙÙ Ø§ÙÙ
+ØµØ¯Ø± , Ù ÙØ³ØªØ­Ø³Ù Ø§Ø³ØªØ®Ø¯Ø§Ù
+ Ù
+ÙØ±Ø¯Ø§Øª Ù
+Ø®Ø·Ø·Ø©Ù Ù
+Ø­ÙÙ
+Ø©  ÙØ§Ø¯ÙØ© ØªØµÙÙÙ ØŽÙÙÙØ©</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">äž»é¢åå
+³é®è¯</Attribute>
+            <Attribute name="definition">èµæºå
+å®¹çäž»é¢æè¿°ã</Attribute>
+            <Attribute name="comment">åŠæèŠæè¿°ç¹å®èµæºçæäžäž»é¢ïŒäžè¬éçšå
+³é®è¯ãå
+³é®å­ç­è¯­æåç±»å·ïŒæå¥œäž»é¢åå
+³é®è¯ä»åæ§    è¯è¡šæè§èçåç±»äœç³»äž­ååŒã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">PÅedmÄt a klÃ­ÄovÃ¡ slova</Attribute>
+            <Attribute name="definition">TÃ©ma obsahu zdroje.</Attribute>
+            <Attribute name="comment">PÅedmÄt bude typicky vyjÃ¡dÅen pomocÃ­ klÃ­ÄovÃœch slov, klÃ­ÄovÃœch frÃ¡zÃ­ nebo klasifikaÄnÃ­ch znakÅ¯ popisujÃ­cÃ­ch tÃ©ma zdroje. DoporuÄuje se vybÃ­rat hodnotu prvku z ÅÃ­zenÃ©ho slovnÃ­ku nebo formÃ¡lnÃ­ho klasifikaÄnÃ­ho schÃ©matu.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Onderwerp en trefwoorden</Attribute>
+            <Attribute name="definition">Het onderwerp van de Internetbron. Het onderwerp wordt beschreven in korte zinnen of door het gebruik van trefwoorden. Het gebruik van gecontroleerde trefwoorden of classificatie schema&apos;s wordt aanbevolen.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Subjecto e parolas-clave</Attribute>
+            <Attribute name="definition">Le topico del contento del ressource.</Attribute>
+            <Attribute name="comment">Typicamente le subjecto es expresse per medio de parolas-clave, phrases-clave, o codices de classification que describe le topico del ressource. Le melior practica recommendate es selectionar un valor a partir de un vocabulario controlate o un schema formal de classification.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€µà€¿à€·à€¯</Attribute>
+            <Attribute name="definition">à€µà€¿à€·à€¯</Attribute>
+            <Attribute name="comment">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à€Ÿ, à€à¥à€à€Ÿà€šà€žà€Ÿà€§à€šà¥ à€¯à€Ÿà€€à¥à€² à€à€¶à€¯ à€žà¥à€ªà€·à¥à€ à€à€°à€£à€Ÿà€°à¥ à€¶à€¬à¥à€Š, à€µà€¿à€·à€¯à€Ÿà€à¥ à€µà€°à¥à€à¥à€à€°à€£ à€à€°à€€à€Ÿà€šà€Ÿ à€¶à€¬à¥à€Šà€žà€à€à¥à€°à€¹ à€
+à€¥à€µà€Ÿ à€¶à€¬à¥à€Š à€à¥à€·à€Ÿà€à€Ÿ à€µà€Ÿà€ªà€° à€à€°à€Ÿà€µà€Ÿ</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Description" >
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Description</Attribute>
+            <Attribute name="definition">An account of the content of the resource.</Attribute>
+            <Attribute name="comment">Description may include but is not limited to: an abstract, table of contents, reference to a graphical representation of content or a free-text account of the content.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Whakaaturanga</Attribute>
+            <Attribute name="definition">He whakaaturanga o nga kaupapa o te rauemi.</Attribute>
+            <Attribute name="comment">Ka uru atu, engari ehara noa ko: te whakarapopototanga korero, te ihirangi, te tohutanga o te kaupapa ma te whakaahua, te whakaaturanga kore kupu ranei, o te kauapapa.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Description</Attribute>
+            <Attribute name="definition">Une description du contenu de la ressource.</Attribute>
+            <Attribute name="comment">Une Description peut contenir, mais ce n&apos;est pas limitatif: un rÃ©sumÃ©, une table des matiÃšres, une rÃ©fÃ©rence Ã  une reprÃ©sentation graphique du contenu, ou un texte libre sur le contenu.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÐ¿ÐžÑÐ°ÐœÐžÐµ</Attribute>
+            <Attribute name="definition">Ð¡ÐŸÐŸÐ±ÑÐµÐœÐžÐµ ÐŸ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐž ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÐ¿ÐžÑÐ°ÐœÐžÐµ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐŸ (Ð¿ÐŸ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÑÑÐž) Ð² Ð²ÐžÐŽÐµ: ÑÐµÑÐµÑÐ°ÑÐ°, ÐŸÐ³Ð»Ð°Ð²Ð»ÐµÐœÐžÑ, ÑÑÑÐ»ÐºÐž ÐœÐ° Ð³ÑÐ°ÑÐžÑÐµÑÐºÐŸÐµ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÐžÐ»Ðž Ð¿ÑÐŸÑÑÐŸÐ³ÐŸ ÑÐµÐºÑÑÐŸÐ²ÐŸÐ³ÐŸ ÐžÐ·Ð»ÐŸÐ¶ÐµÐœÐžÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">DescripciÃ³n</Attribute>
+            <Attribute name="definition">Una descripciÃ³n textual del recurso, tal como un resumen en el caso de un documento o una descripciÃ³n del contenido en el caso de un documento visual.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙÙØµÙ</Attribute>
+            <Attribute name="definition">ÙÙ ÙØµÙ ÙØµÙ  ÙÙ
+Ø­ØªÙÙ Ø§ÙÙ
+ØµØ¯Ø±, ÙÙØ¶Ù
+ Ø§ÙÙ
+ÙØ®ØµØ§Øª ÙÙ Ø­Ø§ÙØ© Ø§ÙÙØ«Ø§ØŠÙ Ù
+Ø«Ù Ø§ÙØ§ØŽÙØ§Ø¡ Ø§ÙÙ
+ÙØªÙØšØ© Ø§Ù ØªÙØµÙÙ Ø§ÙÙ
+Ø­ØªÙÙ ÙÙ Ø­Ø§ÙØ© Ø§ÙÙ
+ØµØ§Ø¯Ø± Ø§ÙÙ
+Ø±ØŠÙØ©</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">è¯Žæ</Attribute>
+            <Attribute name="definition">èµæºå
+å®¹çè§£é</Attribute>
+            <Attribute name="comment">è¯Žæå¯ä»¥å
+æ¬äœäžéäºä»¥äžå
+å®¹ïŒææãç®åœãå¯¹ä»¥åŸåœ¢æ¥æ­ç€ºå
+å®¹çèµæºèèšçæå­è¯Žæãæè
+äž    äžªæå
+³èµæºå
+å®¹çèªç±ææ¬æè¿°ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">Popis</Attribute>
+            <Attribute name="definition">VysvÄtlenÃ­ obsahu zdroje.</Attribute>
+            <Attribute name="comment">Popis mÅ¯ÅŸe obsahovat (mimo jinÃ©): abstrakt, obsah, odkaz na grafickÃ© nebo volnÃ© textovÃ© vyjÃ¡dÅenÃ­ obsahu.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Omschrijving</Attribute>
+            <Attribute name="definition">Een omschrijving van de inhoud van de Internetbron. Abstracts of inhoudsomschrijvingen.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Description</Attribute>
+            <Attribute name="definition">Un description del contento del ressource.</Attribute>
+            <Attribute name="comment">Le description pote includer, ma non se limita a: summario, indice, referentia a un representation graphic del contento o un texto libere a proposito del contento.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€µà€°à¥à€£à€š</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à¥, à€à¥à€à€Ÿà€šà€žà€Ÿà€§à€šà€Ÿà€à¥à€µà€°à¥à€£à€š</Attribute>
+            <Attribute name="comment">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à¥ à€šà€¿à€µà¥à€Šà€š, à€à€²à¥à€, à€à€¿à€€à¥à€°à€°à¥à€ª</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+        <Element name="abstract">
+            <Language code="en">
+                <Attribute name="label">Abstract</Attribute>
+                <Attribute name="definition">A summary of the content of the resource.</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Attribute language="en" name="status">recommended</Attribute>
+        </Element>
+        <Element name="tableOfContents">
+            <Language code="en">
+                <Attribute name="label">Table Of Contents</Attribute>
+                <Attribute name="definition">A list of subunits of the content of the resource.</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Attribute language="en" name="status">recommended</Attribute>
+        </Element>
+    </Element>
+    <Element name="Publisher" >
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Publisher</Attribute>
+            <Attribute name="definition">An entity responsible for making the resource available.</Attribute>
+            <Attribute name="comment">Examples of a Publisher include a person, an organisation, or a service. Typically, the name of a Publisher should be used to indicate the entity.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Kaiwhakaputa</Attribute>
+            <Attribute name="definition">Te putahi nana i whakaputa te rauemi.</Attribute>
+            <Attribute name="comment">Ko te tangata, he putahitanga, he ratonga ranei etahi tauira Kaiwhakaputa. Ko te tikanga, ka whakamahia te ingoa o te Kaiwhakaputa hei tohu i te putahi.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Editeur</Attribute>
+            <Attribute name="definition">L&apos;entitÃ© responsable de la diffusion de la ressource, dans sa forme actuelle, tels, un dÃ©partement universitaire, une entreprise.</Attribute>
+            <Attribute name="comment">Exemples d&apos;Editeurs incluent une personne, une organisation, ou un service. Typiquement, le nom d&apos;une maison d&apos;Ã©dition devrait Ãªtre utilisÃ© ici.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÐ·ÐŽÐ°ÑÐµÐ»Ñ</Attribute>
+            <Attribute name="definition">ÐÐžÑÐŸ, ÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÐŸÐµ Ð·Ð° Ð²Ð²ÐŸÐŽ ÑÐµÑÑÑÑÐ° Ð² ÐŸÐ±ÑÐ°ÑÐµÐœÐžÐµ.</Attribute>
+            <Attribute name="comment">ÐÑÐžÐŒÐµÑÑ ÐÐ·ÐŽÐ°ÑÐµÐ»Ñ Ð²ÐºÐ»ÑÑÐ°ÑÑ Ð¿ÐµÑÑÐŸÐœÑ, ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÑ ÐžÐ»Ðž ÑÐ»ÑÐ¶Ð±Ñ. ÐÐ±ÑÑÐœÐŸ ÐžÐŒÑ ÐÐ·ÐŽÐ°ÑÐµÐ»Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÐžÐœÐŽÐžÐºÐ°ÑÐžÐž ÐŸÐ±ÑÐµÐºÑÐ°.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Editor</Attribute>
+            <Attribute name="definition">&gt;La entidad responsable de hacer que el recurso se encuentre disponible en la red en su formato actual, por ejemplo la empresa editora, un departamento universitario u otro tipo de organizaciÃ³n.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙÙØ§ØŽØ±</Attribute>
+            <Attribute name="definition">ÙÙ Ø§ÙÙÙØŠØ© Ø§ÙÙ
+Ø³Ø€ÙÙØ© Ø¹Ù ØµÙØ§Ø¹Ø© Ø§ÙÙ
+ØµØ¯Ø± Ø§ÙÙ
+ØªÙÙØ± ÙÙ Ø­Ø§ÙØªÙ Ø§ÙØ­Ø§Ø¶Ø±Ø©, Ù
+Ø«Ù Ø¯Ø§Ø± Ø§ÙÙØŽØ±, ÙØ³Ù
+ Ø¬Ø§Ù
+Ø¹Ù Ø§Ù Ù
+Ø€Ø³Ø³Ø© Ø§Ø¹Ù
+Ø§Ù</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">åºçè
+</Attribute>
+            <Attribute name="definition">äœ¿èµæºæäžºå¯ä»¥è·åŸå¹¶å¯çšçèŽ£ä»»è
+ã</Attribute>
+            <Attribute name="comment">åºçè
+çå®äŸå
+æ¬äžªäœïŒç»ç»ïŒææå¡ãäžè¬èèšïŒåºè¯¥çšåºçè
+çåç§°æ¥æ è¯è¿äžæ¡ç®ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">Vydavatel</Attribute>
+            <Attribute name="definition">Entita odpovÄdnÃ¡ za zpÅÃ­stupnÄnÃ­ zdroje.</Attribute>
+            <Attribute name="comment">PÅÃ­klady Vydavatele zahrnujÃ­ osobu, organizaci nebo sluÅŸbu. K oznaÄenÃ­ entity se typicky pouÅŸÃ­vÃ¡ jmÃ©no vydavatele.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Uitgever</Attribute>
+            <Attribute name="definition">De entiteit die verantwoordelijk is voor het beschikbaarstellen van de Internetbron in de huidig vorm. Bijvoorbeeld een uitgeversbedrijf, een universiteitsafdeling.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Editor</Attribute>
+            <Attribute name="definition">Un entitate responsabile pro disponibilizar le ressource.</Attribute>
+            <Attribute name="comment">Exemplos de editor include un persona, un organization, o un servicio. Typicamente se utiliza un nomine de editor pro indicar le entitate.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€ªà¥à€°à€à€Ÿà€¶à€</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à€Ÿ  à€à€ªà€²à€¬à¥à€§ à€à€°à¥à€š à€Šà¥à€£à€Ÿà€°à€Ÿ</Attribute>
+            <Attribute name="comment">à€à€Šà€Ÿ.à€ à€ªà¥à€°à€à€Ÿà€¶à€ , à€ªà¥à€°à€à€Ÿà€¶à€š  à€žà€à€žà¥à€¥à€Ÿ, à€žà¥à€µà€Ÿ    à€®à€Ÿà€¹à€¿à€€à¥ à€à€Ÿà€ªà¥à€² à€°à¥à€ªà€Ÿà€€  à€
+à€¥à€µà€Ÿ à€à€à€à€°à€šà¥à€ à€µà€° à€à€ªà€²à€¬à¥à€§ à€à€°à¥à€š à€Šà¥à€£à€Ÿà€°à€Ÿ</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Contributor" >
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Contributor</Attribute>
+            <Attribute name="definition">An entity responsible for making contributions to the content of the resource.</Attribute>
+            <Attribute name="comment">Examples of a Contributor include a person, an organisation, or a service. Typically, the name of a Contributor should be used to indicate the entity.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Kaiwhakaaro</Attribute>
+            <Attribute name="definition">Te putahi nana, na ratou ranei nga whakakaupapatanga whakaaro o te rauemi.</Attribute>
+            <Attribute name="comment">Ko te tangata, he putahitanga, he ratonga ranei etahi tauira Kaiwhakaaro. Ko te tikanga ka whakamahia te ingoa o te Kaiwhakaaro hei tohu i te putahi.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Contributeur</Attribute>
+            <Attribute name="definition">Une entitÃ© qui a contribuÃ© Ã  la crÃ©ation du contenu de la ressource.</Attribute>
+            <Attribute name="comment">Exemples de Contributeur incluent une personne, une organisation, ou un service. Typiquement, le nom d&apos;un contributeur devrait Ãªtre utilisÃ© ici pour dÃ©signer l&apos;entitÃ©.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">Ð¡ÐŸÐžÑÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»Ñ</Attribute>
+            <Attribute name="definition">ÐÐžÑÐŸ, Ð²ÐœÐµÑÑÐµÐµ Ð²ÐºÐ»Ð°ÐŽ Ð² ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÑÐžÐŒÐµÑÑ Ð¡ÐŸÐžÑÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»Ñ Ð²ÐºÐ»ÑÑÐ°ÑÑ Ð¿ÐµÑÑÐŸÐœÑ, ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÑ ÐžÐ»Ðž ÑÐ»ÑÐ¶Ð±Ñ. ÐÐ±ÑÑÐœÐŸ ÐžÐŒÑ Ð¡ÐŸÐžÑÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÐžÐœÐŽÐžÐºÐ°ÑÐžÐž ÐŸÐ±ÑÐµÐºÑÐ°.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Otros Colaboradores</Attribute>
+            <Attribute name="definition">Una persona u organizacion que haya tenido una contribuciÃ³n intelectual significativa en la creaciÃ³n del recurso pero cuyas contribuciones son secundarias en comparaciÃ³n a las de las personas u organizaciones especificadas en el elementeo Creator (por ejemplo, editor, ilustrador y traductor).</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙÙ
+Ø³Ø§ÙÙ
+ Ø§ÙØ§Ø®Ø±</Attribute>
+            <Attribute name="definition">ÙÙ Ø§ÙØŽØ®Øµ Ø§Ù Ø§ÙÙ
+Ø€Ø³Ø³Ø© Ø§ÙØºÙØ± Ù
+Ø°ÙÙØ± ØµØ±Ø§Ø­Ø© ÙÙ Ø¹Ø§Ù
+Ù &quot; Ø§ÙÙ
+ØšØ¯Ø¹ &quot; Ù Ø§ÙØ°Ù ÙØ¯Ù
+ Ù
+Ø³Ø§ÙÙ
+Ø§Øª ÙÙØ±ÙØ© ÙØ§Ù
+Ø© ÙÙÙ
+ØµØ¯Ø±, ÙÙÙ Ù
+Ø³Ø§ÙÙ
+ØªÙØªØšÙÙ    Ø«Ø§ÙÙÙØ© Ù
+ÙØ§Ø±ÙØ© Ù
+Ø¹ Ø§ÙØŽØ®Øµ Ø£Ù Ø§ÙÙ
+Ø€Ø³Ø³Ø© Ø§ÙÙ
+Ø°ÙÙØ±Ø© ÙØµØ§ ÙÙ Ø¹Ø§Ù
+Ù &quot; Ø§ÙÙ
+ÙØŽØŠ &quot; Ù
+Ø«ÙØ§Ù Ù
+ØµØ­Ø­, Ø§ÙÙ
+ØªØ±Ø¬Ù
+, Ø§Ù Ø§ÙÙ
+ÙØ³Ø±</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">å
+¶ä»èŽ£ä»»è
+</Attribute>
+            <Attribute name="definition">å¯¹èµæºçå
+å®¹äœåºèŽ¡ç®çå
+¶ä»å®äœã</Attribute>
+            <Attribute name="comment">å
+¶ä»èŽ£ä»»è
+çå®äŸå¯å
+æ¬äžªäººãç»ç»ææé¡¹æå¡ãäžè¬èèšïŒçšå
+¶ä»èŽ£ä»»è
+çåå­æ¥æ è¯è¿äžæ¡ç®ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">PÅispÄvatel</Attribute>
+            <Attribute name="definition">Entita, kterÃ¡ pÅispÄla k vytvoÅenÃ­ obsahu zdroje.</Attribute>
+            <Attribute name="comment">PÅÃ­klady PÅispÄvatele zahrnujÃ­ osobu, organizaci nebo sluÅŸbu. K oznaÄenÃ­ entity se typicky pouÅŸÃ­vÃ¡ jmÃ©no pÅispÄvatele.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Andere medewerkers</Attribute>
+            <Attribute name="definition">Een persoon of organisatie die een belangrijke bijdrage heeft geleverd, maar die secondair is aan de persoon of organisatie die bij &quot;Creator&quot; genoemd wordt. Gedacht kan worden aan editors, vertalers en illustrators.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Contribuente</Attribute>
+            <Attribute name="definition">Un entitate responsabile pro facer contributiones al contento del ressource.</Attribute>
+            <Attribute name="comment">Exemplos de contribuente include un persona, un organization, o un servicio. Typicamente se utiliza un nomine de contribuente pro indicar le entitate.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label"> à€žà€¹à€¯à¥à€à€, à€žà€¹à€¯à¥à€à¥, à€žà€¹à€Ÿà€¯à¥à€¯à€</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à€Ÿ à€žà€à€à€²à¥à€€ à€à€°à€£à¥à¥à€Ÿà€ž  à€®à€Šà€€ à€à€°à€£à€Ÿà€°à¥ à€µà¥à€¯à€à¥à€€à¥</Attribute>
+            <Attribute name="comment">à€à€Šà€Ÿ.à€ à€µà¥à€¯à€à¥à€€à¥, à€žà¥à€µà€Ÿ, à€žà€à€žà¥à€¥à€Ÿ</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Date" >
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Date</Attribute>
+            <Attribute name="definition">A date associated with an event in the life cycle of the resource.</Attribute>
+            <Attribute name="comment">Typically, Date will be associated with the creation or availability of the resource.  Recommended best practice for encoding the date value is defined in a profile of ISO 8601 and follows the YYYY-MM-DD format.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Ra</Attribute>
+            <Attribute name="definition">He ra e whai panga ana ki te huringa ora o te rauemi.</Attribute>
+            <Attribute name="comment">Ko te tikanga, ka whai panga te ra ki te hanganga, te wateatanga ranei, o te rauemi. Ko te huarahi tino pai hei tohu i te uara o te ra (date value) kua whakaritea i roto i te whakaritenga IS0 8601 [W3CDTF], a, e whai atu ana ki te whakatakotoranga YYYY-MM-DD.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Date</Attribute>
+            <Attribute name="definition">Une date associÃ©e avec un Ã©vÃ©nement dans le cycle de vie de la ressource.</Attribute>
+            <Attribute name="comment">Typiquement, une date sera associÃ©e Ã  la crÃ©ation ou Ã  la publication d&apos;une ressource. Il est fortement recommandÃ© d&apos;encoder la valeur de la date en utilisant le format dÃ©fini par l&apos;ISO 8601 [W3CDTF] sous la forme AAAA-MM-JJ.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÐ°ÑÐ°</Attribute>
+            <Attribute name="definition">ÐÐ°ÑÐ°, ÑÐ²ÑÐ·Ð°ÐœÐœÐ°Ñ Ñ ÑÐŸÐ±ÑÑÐžÐµÐŒ Ð² Ð¶ÐžÐ·ÐœÐµÐœÐœÐŸÐŒ ÑÐžÐºÐ»Ðµ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÐ±ÑÑÐœÐŸ ÐÐ°ÑÐ° Ð°ÑÑÐŸÑÐžÐžÑÑÐµÑÑÑ Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµÐŒ ÐžÐ»Ðž ÐŽÐŸÑÑÑÐ¿ÐœÐŸÑÑÑÑ ÑÐµÑÑÑÑÐ°. ÐÐ° Ð¿ÑÐ°ÐºÑÐžÐºÐµ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ ÐŽÐ»Ñ ÐºÐŸÐŽÐžÑÐŸÐ²ÐºÐž Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŽÐ°ÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÐµ Ð¿ÑÐŸÑÐžÐ»Ñ ISO 8601 (Ð€ÐŸÑÐŒÐ°ÑÑ ÐŽÐ°ÑÑ Ðž Ð²ÑÐµÐŒÐµÐœÐž W3C), ÐºÐŸÑÐŸÑÐŸÐµ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÐµÑ ÑÐŸÑÐŒÐ°Ñ ÐÐÐÐ-ÐÐ-ÐÐ.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Fecha</Attribute>
+            <Attribute name="definition">Una fecha en la que el recurso se puso a disposiciÃ³n del usuario en su forma actual. Esta fecha no ha de confundirse con la que pertenece al elemento Coverage, que serÃ­a asociada con el recurso sÃ³lo en la medida en que el contenido intelectual estÃ¡ de algÃºn modo relacionado con esa fecha. Recomendamos la utiliazaciÃ³n de uno de los formatos definidos en el documento &quot;Date and Time Formats&quot;, http://www.w3.org/TR/NOTE-datetime basado en la norma ISO 8601 que incluye, entre otras, fechas en el formato AAAA y AAAA-MM-DD. De esta forma la fecha 1994-11-05 corresponderÃ­a al 5 de Noviembre de 1994.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙØªØ§Ø±Ø®</Attribute>
+            <Attribute name="definition">ÙÙ Ø§ÙØªØ§Ø±ÙØ® Ø§ÙÙ
+ØªØ¹ÙÙ ØšÙÙØª ÙØŽØŠ Ø£Ù ØªÙÙØ± Ø§ÙÙ
+ØµØ¯Ø± . Ù ÙØ¬Øš Ø£Ù ÙØ§ ÙØ®ÙØ· ÙØ°Ø§ Ø§ÙØªØ§Ø±ÙØ® Ø§ÙØ¹Ø§ØŠØ¯ ÙØ¹Ø§Ù
+Ù Ø§ÙØªØºØ·ÙØ© , Ù Ø§ÙØ° Ù ÙØ¬Øš Ø£Ù    ÙÙØ­Ù ØšØ§ÙÙ
+ØµØ¯Ø± ÙÙØ· Ù
+Ù ÙØ§Ø­ÙØ© Ø§ÙÙ
+Ø­ØªÙÙØ§ÙÙÙØ±Ù ÙÙÙÙÙ ÙÙØ¹Ø§ Ù
+Ø§ ÙÙ ÙØ°Ø§ Ø§ÙØªØ§Ø±ÙØ®. Ø§ÙØµÙØºØ© Ø§ÙÙ
+Ø³Ø«Ø­Ø³ÙØ© ÙÙØ§Ø­Ø³Ù Ø§ÙÙ
+ØªØ¹Ø§Ø±Ù Ø¹ÙÙÙ    Ø¹ÙØ¯ Ø§ÙØªØ·ØšÙÙ ÙÙ Ø§ÙØµÙØºØ© Ø§ÙÙ
+Ø¹ØªÙ
+Ø¯Ø© ÙÙ ØªØŽÙÙÙ (ISO 8601) ØµÙØºØ© ØªØ§Ø±ÙØ® Ø§ÙÙÙÙ
+ Ù Ø§ÙÙÙØª ) Ø§Ø¹ØªÙ
+Ø§Ø¯Ø§ Ø¹ÙÙ (ISO 8601) Ø§ÙÙ
+ÙØ§Ø­ØžØ© Ø§ÙÙÙÙØ© http://www.w3.org/TR/NOTE-datetime, W3C. ÙÙÙ    ÙØ°Ø§ Ø§ÙÙØ³Ù , Ù
+Ø«ÙØ§, ØªØ§Ø±ÙØ® Ø§ÙÙÙÙ
+ 1994-11-04 ÙÙØ§ØžØ± ÙÙÙ
+ 5 ÙÙÙÙ
+ØšØ± 1994</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">æ¥æ</Attribute>
+            <Attribute name="definition">äžèµæºçåœåšæäž­çäžäžªäºä»¶çžå
+³çæ¶éŽã</Attribute>
+            <Attribute name="comment">äžè¬èèšïŒæ¥æåºäžèµæºçåå»ºæåºçæ¥æçžå
+³ãå»ºè®®éçšçæ¥ææ ŒåŒåºç¬ŠåISO 8601 [W3CDTF]è§    èïŒå¹¶äœ¿çšYYYY-MM-DDçæ ŒåŒã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">Datum</Attribute>
+            <Attribute name="definition">Datum spojenÃ© s urÄitou udÃ¡lostÃ­ bÄhem existence zdroje.</Attribute>
+            <Attribute name="comment">Datum bude typicky spojeno s vytvoÅenÃ­m nebo zpÅÃ­stupnÄnÃ­m zdroje. DoporuÄenÃœ postup pro kÃ³dovÃ¡nÃ­ hodnoty data je definovÃ¡n v ISO 8601 [W3CDTF]: formÃ¡t RRRR-MM-DD.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Datum</Attribute>
+            <Attribute name="definition">De datum van de totstandkoming of beschikbaarstelling van een Internetbron. Deze datum moet niet verward worden met de datum in &quot;Coverage&quot;. De datum in &quot;Coverage&quot; geeft de tijdsperiode van de inhoud van de Internetbron aan. Voorgeschreven wordt de ISO 8601 standaard voor datum, zoals beschreven in W3C Technical Note http://www.w3.org/TR/NOTE-datetime. Hierin wordt het formaat YYYY-MM-DD beschreven. Het formaat YYYY-MM-DD wordt de voorgeschreven standaard. 3 September 1998 wordt in dit geval 1998-09-03.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Data</Attribute>
+            <Attribute name="definition">Un data associate a un evento in le cyclo vital del ressource.</Attribute>
+            <Attribute name="comment">Typicamente le data es associate al creation o disponibilization del ressource. Le practica recommendate pro codificar le valor del datas es definite in un profilo de ISO 8601 [W3CDTF] e seque le formato AAAA-MM-DD.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€€à€Ÿà€°à¥à€,  à€Šà€¿à€šà€Ÿà€à€</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à€Ÿ à€€à€¯à€Ÿà€° à€à¥à€²à¥à€¯à€Ÿà€à¥ à€€à€Ÿà€°à¥à€</Attribute>
+            <Attribute name="comment">à€€à€Ÿà€°à¥à€  à€²à€¿à€¹à¥à€£à¥à€¯à€Ÿà€à¥ à€žà¥à€µà€°à¥à€ª à€ à€µà€°à¥à€·. à€®à€¹à€¿à€šà€Ÿ. à€Šà€¿à€µà€ž à¥§à¥¯à¥«à¥Š. à¥Šà¥ª. à¥Šà¥ª</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+        <Element name="available">
+            <Language code="en">
+                <Attribute name="label">Available</Attribute>
+                <Attribute name="definition">Date (often a range) that the resource will become or did become available.</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Attribute language="en" name="status">recommended</Attribute>
+        </Element>
+        <Element name="created">
+            <Language code="en">
+                <Attribute name="label">Created</Attribute>
+                <Attribute name="definition">Date of creation of the resource.</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Attribute language="en" name="status">recommended</Attribute>
+        </Element>
+        <Element name="dateAccepted">
+            <Language code="en">
+                <Attribute name="label">Date Accepted</Attribute>
+                <Attribute name="definition">Date of acceptance of the resource (e.g. of thesis by university department, of article by journal, etc.).</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Attribute language="en" name="status">conforming</Attribute>
+        </Element>
+        <Element name="dateCopyrighted">
+            <Language code="en">
+                <Attribute name="label">Date Copyrighted</Attribute>
+                <Attribute name="definition">Date of a statement of copyright.</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Attribute language="en" name="status">conforming</Attribute>
+        </Element>
+        <Element name="dateSubmitted">
+            <Language code="en">
+                <Attribute name="label">Date Submitted</Attribute>
+                <Attribute name="definition">Date of submission of the resource (e.g. thesis, articles, etc.).</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Attribute language="en" name="status">conforming</Attribute>
+        </Element>
+        <Element name="issued">
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Language code="en">
+                <Attribute name="label">Issued</Attribute>
+                <Attribute name="definition">Date of formal issuance (e.g., publication) of the resource.</Attribute>
+            </Language>
+            <Attribute language="en" name="status">recommended</Attribute>
+        </Element>
+        <Element name="modified">
+            <Language code="en">
+                <Attribute name="label">Modified</Attribute>
+                <Attribute name="definition">Date on which the resource was changed.</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Attribute language="en" name="status">recommended</Attribute>
+        </Element>
+        <Element name="valid">
+            <Attribute language="en" name="status">recommended</Attribute>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Language code="en">
+                <Attribute name="label">Valid</Attribute>
+                <Attribute name="definition">Date (often a range) of validity of a resource.</Attribute>
+            </Language>
+        </Element>
+    </Element>
+    <Element name="Type" >
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Resource Type</Attribute>
+            <Attribute name="definition">The nature or genre of the content of the resource.</Attribute>
+            <Attribute name="comment">Type includes terms describing general categories, functions, genres, or aggregation levels for content. Recommended best practice is to select a value from a controlled vocabulary (for example, the working draft list of Dublin Core Types). To describe the physical or digital manifestation of the resource, use the FORMAT element.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Tumomo</Attribute>
+            <Attribute name="definition">Te ahua, te tu-ahuatanga ranei o nga kaupapa o te rauemi.</Attribute>
+            <Attribute name="comment">Kei roto i te Tumomo nga kupu whakaatu i nga wehewehenga whanui, nga aheinga, nga tu-ahuatanga, te whakaritenga ranei o nga taumata o te/ nga kaupapa. Ko te huarahi tino pai kua tohua, ko te tipako i tetahi uara mai i nga kupu kua whakaritea (hei tauira, ko te tauira rarangi e whakamahia ana o nga Dublin Core Types [DCT1]. Hei whakaatu i te whakatinanatanga o te rauemi, whakamahia ko te huanga WHAKATAKOTORANGA (FORMAT).</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Type</Attribute>
+            <Attribute name="definition">La nature ou le genre du contenu de la ressource.</Attribute>
+            <Attribute name="comment">Type inclut des termes dÃ©crivant des catÃ©gories, fonctions ou genres gÃ©nÃ©raux pour le contenu, ou des niveaux d&apos;agrÃ©gation. Il est recommandÃ© de choisir la valeur du type dans une liste de vocabulaire contrÃŽlÃ© (par exemple, la liste provisoire de Types du Dublin Core[DCT1]). Pour dÃ©crire la matÃ©rialisation physique ou digitale de la ressource, il faut utiliser l&apos;Ã©lÃ©ment Format.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">Ð¢ÐžÐ¿ ÑÐµÑÑÑÑÐ°</Attribute>
+            <Attribute name="definition">ÐÑÐžÑÐŸÐŽÐ° ÐžÐ»Ðž Ð¶Ð°ÐœÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">Ð¢ÐžÐ¿ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÑÐµÑÐŒÐžÐœÑ, ÐŸÐ¿ÐžÑÑÐ²Ð°ÑÑÐžÐµ ÐŸÐ±ÑÐžÐµ ÐºÐ°ÑÐµÐ³ÐŸÑÐžÐž, ÑÑÐœÐºÑÐžÐž, Ð¶Ð°ÐœÑÑ ÐžÐ»Ðž ÐŸÐ±ÑÐµÐŽÐžÐœÐµÐœÐœÑÐµ ÑÑÐŸÐ²ÐœÐž ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ. ÐÐ»Ñ Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ Ð²ÑÐ±ÐžÑÐ°ÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐžÐ· ÐºÐŸÐœÑÑÐŸÐ»ÐžÑÑÐµÐŒÐŸÐ³ÐŸ ÑÐ»ÐŸÐ²Ð°ÑÑ (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÑÐ°Ð±ÐŸÑÐµÐ³ÐŸ Ð¿ÑÐŸÐµÐºÑÐ° ÑÐ¿ÐžÑÐºÐ° Ð¢ÐžÐ¿ÐŸÐ² Dublin Core DCT1). ÐÐ»Ñ ÐŸÐ¿ÐžÑÐ°ÐœÐžÑ ÑÐžÐ·ÐžÑÐµÑ-ÐºÐŸÐ³ÐŸ ÐžÐ»Ðž ÑÐžÑÑÐŸÐ²ÐŸÐ³ÐŸ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ ÑÐµÑÑÑÑÐ° ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÑÐ»ÐµÐŒÐµÐœÑ Ð€ÐŸÑÐŒÐ°Ñ.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Tipo del Recurso</Attribute>
+            <Attribute name="definition">La categorÃ­a del recurso, por ejemplo pÃ¡gina personal, romance, poema, minuta, diccionario. Para asegurar la interoperabilidad, Type deberÃ­a ser seleccionado de entre una lista de valores que actualmente se encuentra bajo desarrollo en un grupo de trabajo. En http://sunsite.berkeley.edu/Metadata/types.html se puede consultar el estado actual de la discusiÃ³n en torno a este tema.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">ÙÙØ¹ Ø§ÙÙ
+ØµØ¯Ø±</Attribute>
+            <Attribute name="definition">ÙÙ ÙØŠØ© Ø§ÙÙ
+ØµØ¯Ø± , Ù
+Ø«ÙØ§ Ø§ÙØµÙØ­Ø© Ø§ÙØ§Ù
+, Ø±ÙØ§ÙØ© , ÙØ·Ø¹Ø© ØŽØ¹Ø±ÙØ© , ÙØ±ÙØ© Ø¹Ù
+Ù , ØªÙØ±ÙØ± ÙÙÙ , Ù
+ÙØ§Ù , ÙØ§Ù
+ÙØ³ . Ù Ù
+Ù Ø£Ø¬Ù Ø§ÙØªØ¹Ø§Ù
+Ù Ø§ÙÙ
+ØŽØªØ±Ù    ÙØ¬Øš Ø£Ù ÙØ®ØªØ§Ø± Ø§ÙÙÙØ¹ Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+Ø±ÙÙ
+Ø© ÙØ§ÙØªÙ ÙÙÙ
+ Ø§Ø¹Ø¯Ø§Ø¯ÙØ§ Ø­Ø§ÙÙØ§ Ø¶Ù
+Ù Ø­ÙÙØ§Øª ÙØ±ØŽØ© Ø¹Ù
+Ù</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">èµæºç±»å</Attribute>
+            <Attribute name="definition">èµæºå
+å®¹çç¹åŸæç±»åã</Attribute>
+            <Attribute name="comment">èµæºç±»åå
+æ¬æè¿°èµæºå
+å®¹çäžè¬èçŽïŒåèœïŒç§å±ïŒæèç±»å±æ¬¡çæ¯è¯­ãå»ºè®®éçšæ¥èªäºåæ§è¯è¡š    äž­çåŒïŒäŸåŠDCMIç±»åè¯æ±è¡š[DCMITYPE]ïŒãèŠæè¿°èµæºçç©çææ°å­åè¡šç°åœ¢åŒïŒè¯·äœ¿çšâæ ŒåŒïŒFORMATïŒâå
+çŽ ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">Typ zdroje</Attribute>
+            <Attribute name="definition">Povaha nebo druh obsahu zdroje.</Attribute>
+            <Attribute name="comment">Typ obsahuje termÃ­ny popisujÃ­cÃ­ obecnÃ© kategorie, funkce, druhy nebo agregaÄnÃ­ ÃºrovnÄ obsahu. DoporuÄuje se vybÃ­rat hodnotu z ÅÃ­zenÃ©ho slovnÃ­ku (napÅ. pracovnÃ­ nÃ¡vrh seznamu TypÅ¯ Dublin Core [DCT1]). K popisu fyzickÃ© nebo digitÃ¡lnÃ­ reprezentace zdroje uÅŸijte prvek FormÃ¡t.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Bestands type</Attribute>
+            <Attribute name="definition">Het soort Internetbron, bijvoorbeeld home page, gedicht, working paper, technical report, essay, woordenboek etc. De DC working groups zijn momenteel bezig met twee voorstellen; een minimalist draft: http://sunsite.berkeley.edu/Metadata/minimalist.html en een structuralist draft: http://sunsite.berkely.edu/Metadata/structuralist.html. Het wordt sterk aanbevolen om &quot;Type&quot; van deze lijsten te selecteren.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Typo del ressource</Attribute>
+            <Attribute name="definition">Le natura o genere del contento del ressource.</Attribute>
+            <Attribute name="comment">Le typo del ressource include terminos que describe categorias general, functiones, generes, o nivellos de aggregation pro le contento. Le practica recommendate es selectionar un valor a partir de un vocabulario controlate (per exemplo, le lista de schizzos de travalio de typos de Dublin Core [DCT1]). Pro describer le manifestation physic o digital del ressource, utiliza le elemento Formato.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€ªà¥à€°à€à€Ÿà€°</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à€Ÿà€ªà¥à€°à€à€Ÿà€°</Attribute>
+            <Attribute name="comment">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à¥ à€µà€°à¥à€à¥à€à€°à€£, à€µà€°à¥à€à€µà€Ÿà€°à¥à€®à€§à¥à€¯à¥ à€à€à€Ÿà€Šà¥à€¯à€Ÿ à€šà¥à€à€Šà¥à€à€Ÿ à€®à¥à€à¥à€¯ à€à€à€ªà¥à€°à€à€Ÿà€°</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Format" >
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Format</Attribute>
+            <Attribute name="definition">The physical or digital manifestation of the resource.</Attribute>
+            <Attribute name="comment">Typically, Format may include the media-type or dimensions of the resource. Format may be used to determine the software, hardware or other equipment needed to display or operate the resource. Examples of dimensions include size and duration. Recommended best practice is to select a value from a controlled vocabulary (for example, the list of Internet Media Types [MIME] defining computer media formats).</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Whakatakotoranga</Attribute>
+            <Attribute name="definition">Te whakatinanatanga, te whakaputanga a-mati o te rauemi.</Attribute>
+            <Attribute name="comment">Ko te tikanga, ka taea te Whakatakotoranga te whakamahi hei whakarite i te rawa-ngohe (software), te rawa-maro (hardware), ma etahi taputapu ranei me matua whiwhi, hei whakahaere i te rauemi. Ko te rahi me te roanga etahi tauira hanga. Ko te tino huarahi kua tohua ko te tipako uara mai i tetahi whakaritenga kupu (hei tauira, te rarangi o nga Tumomo Papaho Ipurangi (Internet Media Types [MIME]) e whakaatu ana i nga whakatakotoranga papaho rorohiko.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Format</Attribute>
+            <Attribute name="definition">La matÃ©rialisation physique ou digitale de la ressource.</Attribute>
+            <Attribute name="comment">Typiquement, Format peut inclure le media ou les dimensions de la ressource. Format peut Ãªtre utilisÃ© pour prÃ©ciser le logiciel, le matÃ©riel ou autre Ã©quipement nÃ©cessaire pour afficher ou faire fonctionner la ressource. Exemples de dimensions incluent la taille et la durÃ©e. Il est recommandÃ© de choisir la valeur du format dans une liste de vocabulaire contrÃŽlÃ©(par exemple, la liste des types de media dÃ©finis sur Internet [MIME]).</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">Ð€ÐŸÑÐŒÐ°Ñ</Attribute>
+            <Attribute name="definition">Ð€ÐžÐ·ÐžÑÐµÑÐºÐŸÐµ ÐžÐ»Ðž ÑÐžÑÑÐŸÐ²ÐŸÐµ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÐ±ÑÑÐœÐŸ Ð€ÐŸÑÐŒÐ°Ñ ÐŒÐŸÐ¶ÐµÑ Ð²ÐºÐ»ÑÑÐ°ÑÑ ÑÐžÐ¿ Ð°ÑÐŽÐžÐŸÐ²ÐžÐ·ÑÐ°Ð»ÑÐœÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž (ÐŒÐµÐŽÐžÐ°-ÑÐžÐ¿) ÐžÐ»Ðž Ð²ÐµÐ»ÐžÑÐžÐœÑ ÑÐµÑÑÑÑÐ°. Ð€ÐŸÑÐŒÐ°Ñ ÐŒÐŸÐ¶ÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ ÐŽÐ»Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ Ð°Ð¿Ð¿Ð°ÑÐ°ÑÐœÐŸÐ³ÐŸ, Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐ³ÐŸ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÑ ÐžÐ»Ðž ÐŽÑÑÐ³ÐŸÐ³ÐŸ ÐŸÐ±ÐŸÑÑÐŽÐŸÐ²Ð°ÐœÐžÑ, ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÐ³ÐŸ ÐŽÐ»Ñ Ð²ÐŸÑÐ¿ÑÐŸÐžÐ·Ð²ÐµÐŽÐµÐœÐžÑ ÐžÐ»Ðž ÑÐ°Ð±ÐŸÑÑ Ñ ÑÐµÑÑÑÑÐŸÐŒ. ÐÑÐžÐŒÐµÑÑ Ð²ÐµÐ»ÐžÑÐžÐœÑ Ð²ÐºÐ»ÑÑÐ°ÑÑ ÑÐ°Ð·ÐŒÐµÑ Ðž Ð¿ÑÐŸÐŽÐŸÐ»Ð¶ÐžÑÐµÐ»ÑÐœÐŸÑÑÑ. ÐÐ»Ñ Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ Ð²ÑÐ±ÐžÑÐ°ÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐžÐ· ÐºÐŸÐœÑÑÐŸÐ»ÐžÑÑÐµÐŒÐŸÐ³ÐŸ ÑÐ»ÐŸÐ²Ð°ÑÑ (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÑÐ¿ÐžÑÐºÐ° ÐÐµÐŽÐžÐ°-ÑÐžÐ¿ÐŸÐ² ÐÐœÑÐµÑÐœÐµÑ MIME, ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑÐµÐ³ÐŸ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐœÑÐµ ÑÐŸÑÐŒÐ°ÑÑ Ð°ÑÐŽÐžÐŸÐ²ÐžÐ·ÑÐ°Ð»ÑÐœÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž).</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Formato</Attribute>
+            <Attribute name="definition">El formato de datos de un recurso, usado para identificar el software y posiblemente, el hardware que se necesitarÃ­a para mostrar el recurso. Para asegurar la interoperabilidad, los valores de Format deberÃ­an ser seleccionados de entre una lista de valores que actualmente se encuentra bajo desarrollo en un grupo de trabajo.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙØµÙØºØ©</Attribute>
+            <Attribute name="definition">ÙØ°Ù ØµÙØºØ© Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø© Ø§ÙØ®Ø§ØµØ© ØšØ§ÙÙ
+ØµØ¯Ø± , Ù ØªØ³ØªØ®Ø¯Ù
+ ÙÙØªØ¹Ø±ÙÙ ØšØ§ÙØšØ±Ù
+Ø¬ÙØ§Øª ÙØ±ØšÙ
+Ø§ Ø§ÙØµÙØš ÙÙØ­Ø§Ø³ÙØš Ù Ø§ÙØªÙ ÙÙ
+ÙÙ Ø£Ù ÙØ­ØªØ§Ø¬    ÙÙØ§ ÙØ¹Ø±Ø¶ Ø£Ù ØªØŽØºÙÙ Ø§ÙÙ
+ØµØ¯Ø± . Ù
+Ù Ø£Ø¬Ù Ø§ÙØªØ¹Ø§Ù
+Ù Ø§ÙÙ
+ØŽØªØ±Ù, ÙØ¬Øš Ø£Ù ØªØ®ØªØ§Ø± Ø§ÙØµÙØºØ© Ù
+Ù Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+Ø±ÙÙ
+Ø© Ù Ø§ÙØªÙ ÙØªÙ
+ Ø§Ø¹Ø¯Ø§Ø¯ÙØ§    Ø­Ø§ÙÙØ§ Ø¶Ù
+Ù Ø­ÙÙØ§Øª ÙØ±ØŽØ© Ø¹Ù
+Ù</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">æ ŒåŒ</Attribute>
+            <Attribute name="definition">èµæºçç©çææ°å­è¡šç°åœ¢åŒã</Attribute>
+            <Attribute name="comment">äžè¬èèšïŒæ ŒåŒå¯èœå
+æ¬èµæºçåªäœç±»åæèµæºçå€§å°ïŒæ ŒåŒå
+çŽ å¯ä»¥çšæ¥å³å®å±ç€ºææäœèµæºæé    çèœ¯ç¡¬ä»¶æå
+¶ä»çžåºè®Ÿå€ïŒäŸåŠå€§å°å
+æ¬èµæºæå çå­åšç©ºéŽåæç»­æ¶éŽãå»ºè®®éçšæ¥èªäºåæ§è¯è¡š    äž­çåŒïŒïŒäŸåŠInternetåªäœç±»å[MIME]å®ä¹è®¡ç®æºåªäœæ ŒåŒïŒã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">FormÃ¡t</Attribute>
+            <Attribute name="definition">FyzickÃ¡ nebo digitÃ¡lnÃ­ reprezentace zdroje.</Attribute>
+            <Attribute name="comment">Typicky mÅ¯ÅŸe FormÃ¡t obsahovat typ mÃ©dia nebo rozmÄry zdroje. FormÃ¡t lze pouÅŸÃ­vat k urÄenÃ­ softwaru, hardwaru nebo dalÅ¡Ã­ho zaÅÃ­zenÃ­ potÅebnÃ©ho k zobrazenÃ­ nebo k manipulaci se zdrojem. PÅÃ­klady rozmÄrÅ¯ zahrnujÃ­ velikost a dobu trvÃ¡nÃ­. DoporuÄuje se vybÃ­rat hodnotu z ÅÃ­zenÃ©ho slovnÃ­ku (napÅ. seznam typÅ¯ internetovÃœch mÃ©diÃ­ [MIME] definujÃ­cÃ­ formÃ¡ty poÄÃ­taÄovÃœch mÃ©diÃ­).</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Format</Attribute>
+            <Attribute name="definition">Het data formaat van het Internetbestand. Dit gegeven kan gebruikt worden om systeemvereisten (hard- en software) te identificeren die nodig zijn voor raadpleging of bediening van de Internetbron. &quot;Format&quot; is nog in ontwikkeling bij de DC workshop. Uit compatibiliteitsoverwegingen wordt aanbevolen formaatgegevens te selecteren uit een gecontroleerde lijst. Formaten kunnen van de Internet Media Types (MIME types) lijst gekozen worden: http://www.isi.edu/in-notes/iana/assignments/media-types/media-types</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Formato</Attribute>
+            <Attribute name="definition">Le manifestation physic o digital del ressource.</Attribute>
+            <Attribute name="comment">Typicamente le formato pote includer le typo de medio o dimensiones del ressource. Le formato pote esser utilizate pro determinar le software o le equipamento necessari pro exhibir o operar le ressource. Exemplos de dimensiones include grandessa e duration. Le practica recommendate es selectionar un valor de un vocabulario controlate (per exemplo, le lista de typos de medios de Internet [MIME] que defini formatos de medios).</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€°à€à€šà€Ÿ</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à¥ à€°à€à€šà€Ÿ, à€šà€®à¥à€šà€Ÿà€¬à¥à€Š à€°à€à€šà€Ÿ</Attribute>
+            <Attribute name="comment">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à¥ à€žà¥à€µà€°à¥à€ª, à€°à€à€šà€Ÿà€à€Šà€Ÿ. à€€à¥à€¯à€Ÿà€à¥ à€°à¥à€ª à€à€žà¥ à€ªà¥à€žà¥à€€à€à€°à¥à€ª, à€žà€à€à€£à€à¥à€¯ à€°à¥à€ª, à€µà€¿à€Šà¥à€¯à¥à€€ à€ªà€°à€®à€Ÿà€£à¥à€à€à¥à€¯à€Ÿ à€žà€¹à€Ÿà€¯à¥à€¯à€Ÿà€šà¥ à€žà€à€à€£à€à¥à€à¥à€€ à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à€Ÿ</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+        <Element name="extent">
+            <Language code="en">
+                <Attribute name="label">Extent</Attribute>
+                <Attribute name="definition">The size or duration of the resource.</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Attribute language="en" name="status">recommended</Attribute>
+        </Element>
+        <Element name="medium">
+            <Language code="en">
+                <Attribute name="label">Medium</Attribute>
+                <Attribute name="definition">The material or physical carrier of the resource.</Attribute>
+            </Language>
+            <Attribute language="en" name="status">recommended</Attribute>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+        </Element>
+    </Element>
+    <Element name="Identifier" >
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Resource Identifier</Attribute>
+            <Attribute name="definition">An unambiguous reference to the resource within a given context.</Attribute>
+            <Attribute name="comment">Recommended best practice is to identify the resource by means of a string or number conforming to a formal identification system. Example formal identification systems include the Uniform Resource Identifier (URI) (including the Uniform Resource Locator (URL)), the Digital Object Identifier (DOI) and the International Standard Book Number (ISBN).</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Taututanga</Attribute>
+            <Attribute name="definition">He tohutoro e hangai ana ki te rauemi i roto i tetahi horopaki.</Attribute>
+            <Attribute name="comment">Ko te tino huarahi kua tohua, ko te tautu i te rauemi ma tetahi aho (string), tau ranei, e hangai ana ki tetahi punaha taututanga okawa. Ko etahi punaha taututanga okawa ko te Taututanga Rauemi Orite (Uniform Resource Identifier - URI), te Taututanga Rauemi Tohu-wahi (Uniform Resource Locator - URL), Te Mea A-mati (Digital Object Identifier - DOI) me te Tau Pukapuka Aro Whanui o te Ao (International Standard Book Number - ISBN).</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Identifiant</Attribute>
+            <Attribute name="definition">Une rÃ©fÃ©rence non ambiguÃ« Ã  la ressource dans un contexte donnÃ©</Attribute>
+            <Attribute name="comment">Il est recommandÃ© d&apos;identifier la ressource par une chaÃ®ne de caractÃšre ou un nombre conforme Ã  un sytÃšme formel d&apos;identification. Exemples de systemes formels d&apos;identification incluent le &quot;Uniform Resource Identifier&quot; (URI) (qui inclut le &quot;Uniform Resource Locator&quot; (URL)), le &quot;Digital Object Identifier&quot;(DOI) et le &quot;International Standard Book Number&quot;(ISBN).</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑ ÑÐµÑÑÑÑÐ°</Attribute>
+            <Attribute name="definition">ÐÐŽÐœÐŸÐ·ÐœÐ°ÑÐœÐ°Ñ ÑÑÑÐ»ÐºÐ° ÐœÐ° ÑÐµÑÑÑÑ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ ÐŽÐ°ÐœÐœÐŸÐ³ÐŸ ÐºÐŸÐœÑÐµÐºÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÐ»Ñ Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ ÐžÐŽÐµÐœÑÐžÑÐžÑÐžÑÐŸÐ²Ð°ÑÑ ÑÐµÑÑÑÑ Ð¿ÐŸÑÑÐµÐŽÑÑÐ²ÐŸÐŒ ÑÑÑÐŸÐºÐž ÐžÐ»Ðž ÑÐžÑÐ»Ð°, ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐ³ÐŸ ÑÐŸÑÐŒÐ°Ð»ÑÐœÐŸÐ¹ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÑÐžÑÑÐµÐŒÐµ. ÐÑÐžÐŒÐµÑÑ ÑÐŸÑÐŒÐ°Ð»ÑÐœÑÑ
+ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÐŸÐœÐœÑÑ
+ ÑÐžÑÑÐµÐŒ Ð²ÐºÐ»ÑÑÐ°ÑÑ Ð£ÐœÐžÑÐžÑÐžÑÐŸÐ²Ð°ÐœÐœÑÐ¹ ÐÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑ Ð ÐµÑÑÑÑÐ° (URI), (Ð²ÐºÐ»ÑÑÐ°Ñ Ð£ÐœÐžÑÐžÑÐžÑÐŸÐ²Ð°ÐœÐœÑÑÐ¹ ÐÐŸÐºÐ°ÑÐŸÑ Ð ÐµÑÑÑÑÐ° URL), ÐÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑ ÐŠÐžÑÑÐŸÐ²ÐŸÐ³ÐŸ ÐÐ±ÑÐµÐºÑÐ° (DOI) Ðž ÐÐµÐ¶ÐŽÑÐœÐ°ÑÐŸÐŽÐœÑÐ¹ Ð¡ÑÐ°ÐœÐŽÐ°ÑÑÐœÑÐ¹ ÐÐœÐžÐ¶ÐœÑÐ¹ ÐÐŸÐŒÐµÑ (ISBN).</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Identificador del Recurso</Attribute>
+            <Attribute name="definition">Secuencia de caracteres usados para identificar unÃ­vocamente un recurso. Ejemplos para recursos en lÃ­nea pueden ser URLs y URNs (cuando estÃ©n implementados). Para otros recursos pueden ser usados otros formatos de identificadores, como por ejemplo ISBN (&quot;International Standard Book Number&quot; - NÃºmero Internacional Normalizado para Libros)</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ù
+Ø¹Ø±Ù Ø§ÙÙ
+ØµØ¯Ø±</Attribute>
+            <Attribute name="definition">ÙÙ Ù
+Ø¬Ù
+ÙØ¹Ø© Ø­Ø±ÙÙØ© Ø£Ù Ø±ÙÙ
+ ÙØ³ØªØ®Ø¯Ù
+ ÙØªØ¹Ø±ÙÙ Ø§ÙÙ
+ØµØ¯Ø± Ø§Ø­Ø¯ÙØ§ : Ø§ÙØ§Ù
+Ø«ÙØ© ÙØ°Ø§ÙÙ ÙÙ Ø§ÙÙ
+ØµØ§Ø¯Ø± Ø§ÙØŽØšÙÙØ©ØªØ¶Ù
+ ) URNs, URLs Ø¹ÙØ¯ ØšÙØ§ØŠÙØ§ (    ÙØ°ÙÙ ÙÙ
+ÙÙ Ø§Ø¹ØªØšØ§Ø± Ø§ÙÙ
+Ø¹Ø±ÙØ§Øª Ø§ÙØ¹Ø§ÙÙ
+ÙØ© Ø§ÙØ§Ø­Ø§Ø¯ÙØ© Ù
+Ø«Ù Ø§ÙØ±ÙÙ
+ Ø§ÙØ¯ÙÙÙ ÙØªØµÙÙÙ Ø§ÙÙØ§ØªØš (ISBN) Ù
+Ø±ØŽØ­Ø© ÙÙØ°Ø§ Ø§ÙØ¹Ø§Ù
+Ù</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">èµæºæ è¯ç¬Š</Attribute>
+            <Attribute name="definition">åšç¹å®çèåŽå
+ç»äºèµæºçäžäžªæç¡®çæ è¯ã</Attribute>
+            <Attribute name="comment">å»ºè®®å¯¹èµæºçæ è¯éçšç¬Šåæäžæ­£åŒæ è¯äœç³»çå­ç¬Šäž²åæ°å­ç»åãäŸåŠæ­£åŒçæ è¯äœç³»å
+æ¬ç»äžèµ    æºæ è¯ç¬Š(URI) (å
+æ¬åäžèµæºå®äœç¬ŠURL)ãæ°å­å¯¹è±¡æ è¯ç¬Š(DOI)ååœé
+æ åä¹Šå·(ISBN)ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">IdentifikÃ¡tor zdroje</Attribute>
+            <Attribute name="definition">JednoznaÄnÃœ odkaz na zdroj v rÃ¡mci danÃ©ho kontextu.</Attribute>
+            <Attribute name="comment">DoporuÄuje se identifikovat zdroj znakovÃœm ÅetÄzcem nebo ÄÃ­slem odpovÃ­dajÃ­cÃ­m nÄkterÃ©mu z formÃ¡lnÃ­ch identifikaÄnÃ­ch systÃ©mÅ¯. PÅÃ­klady formÃ¡lnÃ­ch identifikaÄnÃ­ch systÃ©mÅ¯ zahrnujÃ­ Uniform Resource Identifier (URI) (vÄetnÄ Uniform Resource Locator (URL)), Digital Object Identifier (DOI) a MezinÃ¡rodnÃ­ standardnÃ­ ÄÃ­slo knihy (ISBN).</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Bestandsidentificatie</Attribute>
+            <Attribute name="definition">Een unieke string of nummer ter identificatie van de Internetbron. Voorbeelden zijn URL&apos;s of URN&apos;s Andere voorbeelden zijn International Standard Book Number (ISBN) of International Standard Serial Number (ISSN)</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Identificator del ressource</Attribute>
+            <Attribute name="definition">Un referentia inambigue al ressource intra un date contexto.</Attribute>
+            <Attribute name="comment">Se recommenda identificar le ressource per medio de un catena de characteres o numero conforme a un systema formal de identification. Exemplos de systemas formal de identification include le Uniform Resource Identifier (URI) (includente le Uniform Resource Locator (URL)), le Digital Object Identifier (DOI) e le International Standard Book Number (ISBN).</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€à€³à€</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à€Ÿ à€à€ à€
+à€°à¥à€¥à¥ à€žà€à€Šà€°à¥à€­</Attribute>
+            <Attribute name="comment">à€à€Šà€Ÿ. à€®à€Ÿà€¹à€¿à€€à¥à€à€Ÿà€³à¥à€¯à€Ÿà€µà€°à¥à€² à€ªà€€à¥à€€à€Ÿ, à€µà€¿à€¶à€¿à€·à¥à€  à€žà¥à€¥à€³,  à€ªà¥à€žà¥à€€à€à€Ÿà€à€Ÿ à€à€à€€à€°à€°à€Ÿà€·à¥à€à¥à€°à¥à€¯  à€®à€Ÿà€šà€ à€à¥à€°à€®à€Ÿà€à€,  à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à¥ à€à€³à€ à€ªà€à€µà€¿à€£à€Ÿà€°à€Ÿ à€à€à€à€°à€šà¥à€ à€µà€°à¥à€² à€ªà€€à¥à€€à€Ÿ</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+        <Element name="bibliographicCitation">
+            <Attribute language="en" name="status">conforming</Attribute>
+            <Language code="en">
+                <Attribute name="label">Bibliographic Citation</Attribute>
+                <Attribute name="definition">A bibliographic reference for the resource. </Attribute>
+                <Attribute name="comment">Recommended practice is to include sufficient bibliographic detail to identify the resource as unambiguously as possible, whether or not the citation is in a standard form.</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+        </Element>
+    </Element>
+    <Element name="Source" >
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Source</Attribute>
+            <Attribute name="definition">A Reference to a resource from which the present resource is derived.</Attribute>
+            <Attribute name="comment">The present resource may be derived from the Source resource in whole or in part.  Recommended best practice is to reference the resource by means of a string or number conforming to a formal identification system.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Matapuna</Attribute>
+            <Attribute name="definition">He tohutoro ki tetahi rauemi koira te matapuna o te rauemi e tirohia ana.</Attribute>
+            <Attribute name="comment">Tera pea i puta te katoa, tetahi wahanga ranei o te rauemi, e tirohia ana, mai i te Matapuna rauemi. Ko te tino huarahi kua tohua ko te tohutoro ki te rauemi ma te aho, ma te tau ranei e hangai ana ki tetahi punaha taututanga okawa.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Source</Attribute>
+            <Attribute name="definition">Une rÃ©fÃ©rence Ã  une ressource Ã  partir de laquelle la ressource actuelle a Ã©tÃ© dÃ©rivÃ©e.</Attribute>
+            <Attribute name="comment">La ressource actuelle peut avoir Ã©tÃ© dÃ©rivÃ©e d&apos;une autre ressource source, en totalitÃ© ou en partie. Il est recommandÃ© de refÃ©rencer cette source par une chaÃ®ne de caractÃšre ou un nombre conforme Ã  un systÃšme formel d&apos;identification.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÑÑÐŸÑÐœÐžÐº</Attribute>
+            <Attribute name="definition">Ð¡ÑÑÐ»ÐºÐ° ÐœÐ° ÑÐµÑÑÑÑ, ÐžÐ· ÐºÐŸÑÐŸÑÐŸÐ³ÐŸ ÐžÐ·Ð²Ð»ÐµÑÐµÐœ ÐœÐ°ÑÑÐŸÑÑÐžÐ¹.</Attribute>
+            <Attribute name="comment">ÐÐ°ÑÑÐŸÑÑÐžÐ¹ ÑÐµÑÑÑÑ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐžÐ·Ð²Ð»ÐµÑÐµÐœ ÐžÐ· ÐÑÑÐŸÑÐœÐžÐºÐ° ÑÐµÐ»ÐžÐºÐŸÐŒ ÐžÐ»Ðž ÑÐ°ÑÑÐžÑÐœÐŸ. ÐÐ»Ñ Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ ÐžÐŽÐµÐœÑÐžÑÐžÑÐžÑÐŸÐ²Ð°ÑÑ ÑÐµÑÑÑÑ Ð¿ÐŸÑÑÐµÐŽÑÑÐ²ÐŸÐŒ ÑÑÑÐŸÐºÐž ÐžÐ»Ðž ÑÐžÑÐ»Ð°, ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐ³ÐŸ ÑÐŸÑÐŒÐ°Ð»ÑÐœÐŸÐ¹ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÑÐžÑÑÐµÐŒÐµ.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Fuente</Attribute>
+            <Attribute name="definition">Secuencia de caracteres utilizado para identificar unÃ­vocamente un trabajo a partir del cual proviene el recurso actual. Por ejemplo, es posible usar Source con la fecha de 1603 como descripciÃ³n de una pelÃ­cula basada en una obra de Shakespeare, pero es preferible, en ese caso, usar Relation &quot;IsBasedOn&quot; con una referencia a un recurso distinto cuya descripciÃ³n contenga el elemento Date con valor 1603.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙÙ
+ØµØ¯Ø±</Attribute>
+            <Attribute name="definition">Ø§ÙÙ
+Ø¹ÙÙÙ
+Ø§Øª Ø§ÙØ®Ø§ØµØ© ØšÙ
+ØµØ¯Ø± Ø«Ø§ÙÙ Ù Ø§ÙØ°Ù Ø§Ø³ØªÙ
+Ø¯ Ù
+ÙÙ Ø§ÙÙ
+ØµØ¯Ø± Ø§ÙØ­Ø§ÙÙ. Ù
+Ø¹ Ø£ÙÙ Ù
+Ù Ø§ÙÙ
+ÙØµÙ ØšÙ Ø£Ù ØªÙØ¯Ù
+ Ø§ÙØ¹ÙØ§Ù
+Ù    Ù
+Ø¹ÙÙÙ
+Ø§Øª Ø¹Ù Ø§ÙÙ
+ØµØ¯Ø± Ø§ÙØ­Ø§ÙÙ ÙÙØ· , ÙÙÙ
+ÙÙ Ø£Ù ÙØ­ÙÙ ÙØ°Ø§ Ø§ÙØ¹Ø§Ù
+Ù Ø§ÙØªØ§Ø±ÙØ®, Ø§ÙÙ
+ÙØŽØŠ , Ø§ÙØµÙØºØ© , Ø§ÙÙ
+Ø¹Ø±Ù , Ø§Ù Ø§ÙØ© Ù
+ÙØ© - Ù
+Ø¹ÙÙÙ
+Ø§Øª Ø§Ø®Ø±Ù ÙÙÙ
+ØµØ¯Ø± Ø§ÙØ«Ø§ÙÙ Ø¹ÙØ¯Ù
+Ø§ ØªØ¹ØªØšØ± Ù
+ÙÙ
+Ø© ÙØ§ÙØªØŽØ§Ù Ø§ÙÙ
+ØµØ¯Ø± Ø§ÙØ­Ø§ÙÙ , Ù ÙØ°Ø§ÙÙ ÙÙØµÙ Ø¹ÙØ¯ Ø§ÙØªØ·ØšÙÙÙÙ Ø§Ø­Ø³Ù     Ø§ÙÙ
+ØªØ¹Ø§Ø±Ù Ø¹ÙÙÙ ØšØ§Ø³ØªØ®Ø¯Ø§Ù
+ Ø¹Ø§Ù
+Ù Ø§ÙØ¹ÙØ§ÙØ©</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">æ¥æº</Attribute>
+            <Attribute name="definition">ç°æèµæºæ¥æºçåç
+§ã</Attribute>
+            <Attribute name="comment">åœåèµæºå¯èœéšåæå
+šéšæºèªè¯¥å
+çŽ ææ è¯çèµæºïŒå»ºè®®å¯¹è¿äžèµæºçæ è¯éçšäžäžªç¬Šåæ­£åŒæ è¯ç³»    ç»çå­äž²åæ°å­ç»å ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">Zdroj</Attribute>
+            <Attribute name="definition">Odkaz na zdroj, z nÄhoÅŸ je popisovanÃœ zdroj odvozen.</Attribute>
+            <Attribute name="comment">PopisovanÃœ zdroj mÅ¯ÅŸe bÃœt zcela nebo zÄÃ¡sti odvozen ze zdroje uvedenÃ©ho v prvku Zdroj. DoporuÄuje se odkazovat zdroj znakovÃœm ÅetÄzcem nebo ÄÃ­slem odpovÃ­dajÃ­cÃ­m nÄkterÃ©mu z formÃ¡lnÃ­ch identifikaÄnÃ­ch systÃ©mÅ¯.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Bron</Attribute>
+            <Attribute name="definition">Informatie over een tweede bron waar de huidige Internetbron is van afgeleid. Bij &quot;Source&quot; mag een datum, auteur of maker, formaat, identificatie of andere metadata voor de tweede bron worden ingevuld. Voorbeeld: het is mogelijk om een &quot;Source&quot; datum 1603 in een omschrijving van een 1996 film bewerking van een Shakespeare stuk te gebruiken. &quot;Source&quot; is niet bruikbaar wanneer de huidige bron de orginele is.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Fonte</Attribute>
+            <Attribute name="definition">Un referentia a un ressource del qual se deriva le ressource presente.</Attribute>
+            <Attribute name="comment">Le ressource presente pote derivar se del ressource-fonte in toto o in parte. Le practica recommendate es facer referentia al ressource per medio de un catena de characteres o un numero conforme a un systema formal de identification.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€à€à€®</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€à€Ÿ à€à€à€® à€žà€Ÿà€à€à€£à€Ÿà€°à€Ÿ à€à€à€
+à€°à¥à€¥à¥ à€žà€à€Šà€°à¥à€­</Attribute>
+            <Attribute name="comment">à€à€Šà€Ÿ. à€ªà¥à€žà¥à€€à€, à€®à€Ÿà€žà€¿à€,  à€®à€Ÿà€¹à€¿à€€à¥à€à€Ÿà€³à¥à€¯à€Ÿà€µà€°à¥à€² à€ªà€€à¥à€€à€Ÿà€¯à€Ÿà€à€à€Ÿ à€žà€à€Šà€°à¥à€­</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Language" >
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Language</Attribute>
+            <Attribute name="definition">A language of the intellectual content of the resource.</Attribute>
+            <Attribute language="en" name="comment">Recommended best practice for the values of the Language element is defined by RFC 1766 which includes a two-letter Language Code (taken from the ISO 639 standard, followed optionally, by a two-letter Country Code (taken from the ISO 3166 standard). For example, &apos;en&apos; for English, &apos;fr&apos; for French, or &apos;en-uk&apos; for English used in the United Kingdom.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Reo</Attribute>
+            <Attribute name="definition">Te reo o te whakakaupapatanga o nga matauranga o te rauemi.</Attribute>
+            <Attribute name="comment">Ko te tino huarahi kua tohua mo nga uara o te huanga Reo kua whakaritea ki te RFC 1766 [RFC1766] kei roto te Tohu Reo kupu-rua (two-letter Language Code) (no te aro whanui ISO 639 [ISO639], ka taea e tetahi tohu kupu-rua te whai atu (no te aro whanui ISO 3166) [ISO366]). Hei tauira, te &apos;en&apos; mo te English, te &apos;fr&apos; mo te French, &apos;te en-uk&apos; mo te English e whakamahia ana i Ingarangi (UK).</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Langue</Attribute>
+            <Attribute name="definition">La langue du contenu intellectuel de la ressource.</Attribute>
+            <Attribute name="comment">Il est recommandÃ© d&apos;utiliser comme valeur de l&apos;Ã©lÃ©ment Langue celles definies par la RFC 1766 [RFC1766] qui comprend un code de langage Ã  deux caractÃšres(venant du standard ISO 639 [ISO639]), Ã©ventuellement suivi d&apos;un code Ã  deux lettres pour le pays (venant du standard ISO 3166 [ISO3166] ou en franÃ§ais [ISO3166]). Par exemple, &apos;en&apos; pour l&apos;anglais, &apos;fr&apos; pour le franÃ§ais, ou &apos;en-uk&apos; pour l&apos;anglais utilisÃ© au Royaume-Uni.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">Ð¯Ð·ÑÐº</Attribute>
+            <Attribute name="definition">Ð¯Ð·ÑÐº ÐžÐœÑÐµÐ»Ð»ÐµÐºÑÑÐ°Ð»ÑÐœÐŸÐ³ÐŸ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÐ»Ñ Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÑÐ»ÐµÐŒÐµÐœÑÐ° Ð¯Ð·ÑÐº, ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÐŒÐŸÐµ RFC 1766 (Ð¢ÑÐ³Ðž ÐŽÐ»Ñ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÐž ÑÐ·ÑÐºÐ°), Ð²ÐºÐ»ÑÑÐ°ÑÑÐžÐŒ ÐŽÐ²ÑÑ
+Ð±ÑÐºÐ²ÐµÐœÐœÑÐ¹ ÐºÐŸÐŽ ÑÐ·ÑÐºÐ° (Ð²Ð·ÑÑÑÐ¹ ÐžÐ· ÑÑÐ°ÐœÐŽÐ°ÑÑÐ° ISO 639 (ÐÐŸÐŽÑ ÐŽÐ»Ñ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐ¹ ÑÐ·ÑÐºÐŸÐ²)), Ð·Ð° ÐºÐŸÑÐŸÑÑÐŒ ÑÐ»ÐµÐŽÑÐµÑ (Ð¿ÑÐž ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÑÑÐž) ÐŽÐ²ÑÑ
+Ð±ÑÐºÐ²ÐµÐœÐœÑÐ¹ ÐºÐŸÐŽ ÑÑÑÐ°ÐœÑ (Ð²Ð·ÑÑÑÐŒÐž ÐžÐ· ÑÑÐ°ÐœÐŽÐ°ÑÑÐ° ISO 3166 (ÐÐŸÐŽÑ ÐŽÐ»Ñ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐ¹ ÑÑÑÐ°Ðœ)). ÐÐ°Ð¿ÑÐžÐŒÐµÑ, &quot;en&quot; - ÐŽÐ»Ñ Ð°ÐœÐ³Ð»ÐžÐ¹ÑÐºÐŸÐ³ÐŸ, &quot;fr&quot; - ÐŽÐ»Ñ ÑÑÐ°ÐœÑÑÐ·ÑÐºÐŸÐ³ÐŸ, &quot;en-uk&quot; - ÐŽÐ»Ñ Ð°ÐœÐ³Ð»ÐžÐ¹ÑÐºÐŸÐ³ÐŸ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐŸÐ³ÐŸ Ð² ÐÐµÐ»ÐžÐºÐŸÐ±ÑÐžÑÐ°ÐœÐžÐž.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Lengua</Attribute>
+            <Attribute name="definition">Lengua/s del contenido intelectual del recurso. Practicamente el contenido de este campo deberÃ­a coincidir con los de la RFC 1766 (Tags para la identificaciÃ³n de lenguas, http://ds.internic.net/rfc/rfc1766.txt); por ejemplo: en, es, de, fi, ja y zh.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙÙØºØ©</Attribute>
+            <Attribute name="definition">ÙØ°Ù ÙÙ ÙØºØ© Ø§ÙÙ
+Ø­ØªÙÙ Ø§ÙÙÙØ±Ù ÙÙÙ
+ØµØ¯Ø± . ÙÙÙ
+Ø§ ÙØ§Ù  Ø¹Ù
+ÙÙØ§ , Ù
+Ø­ØªÙÙ ÙØžØ§ Ø§ÙØ­ÙÙ ÙØ¬Øš Ø£Ù ÙØªØ·Ø§ØšÙ Ù
+Ø¹ RFC 1766    ] Ø§ÙØ§Ù
+Ø«ÙØ© ØªØ¶Ù
+ th, ja, fr, es, fi, de, en Ù zh ÙØ±Ù
+ÙØ² ÙÙØªØ¹Ø±ÙÙ ØšØ§ÙÙØºØ© [</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">è¯­ç§</Attribute>
+            <Attribute name="definition">æè¿°èµæºç¥è¯å
+å®¹çè¯­ç§ã</Attribute>
+            <Attribute name="comment">å»ºè®®æ¬å
+çŽ çåŒéçšRFC 3066[RFC3066]ïŒè¯¥æ åäžISO 639 [ISO639]äžèµ·å®ä¹äºç±äž€äžªåäžäžªè±    æå­æ¯ç»æçäž»è¯­èšæ ç­Ÿåå­æ ç­ŸäŸåŠå
+æ¬âenâæâengâæ¥è¡šç€ºEnglish, &quot;akk&quot; æ¥è¡šç€º    &quot;en-GB&quot;è¡šç€ºè±åœè±è¯­ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">Jazyk</Attribute>
+            <Attribute name="definition">Jazyk intelektuÃ¡lnÃ­ho obsahu zdroje.</Attribute>
+            <Attribute name="comment">DoporuÄenÃœ postup pro hodnoty prvku Jazyk je definovÃ¡n v RFC 1766 [RFC1766]: dvouznakovÃœ kÃ³d jazyka (pÅevzatÃœ z normy ISO 639 [ISO639]) volitelnÄ nÃ¡sledovanÃœ dvouznakovÃœm kÃ³dem zemÄ (pÅevzatÃœm z normy ISO 3166 [ISO3166]). NapÅÃ­klad &apos;en&apos; pro angliÄtinu, &apos;fr&apos; pro francouzÅ¡tinu, &apos;cs&apos; pro ÄeÅ¡tinu, nebo &apos;en-uk&apos; pro angliÄtinu uÅŸÃ­vanou ve SpojenÃ©m krÃ¡lovstvÃ­.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Taal</Attribute>
+            <Attribute name="definition">De taal waarin het document is beschreven. Voorgeschreven wordt de ISO639-1 norm, een twee karakter taalcode van de ISO 639(639-1 en 639-2) norm. Taalcodes kunnen van een lijst worden gekozen: http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt, Eventueel kan ISO3166 (landencodes) gebruikt worden om aan te geven in welk gebied de taal wordt gesproken. Deze kunnen ook van een lijst worden gekozen:  http://www.ics.uci.edu/pub/ietf/http/related/iso3166.txt.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Lingua</Attribute>
+            <Attribute name="definition">Le lingua del contento intellectual del ressource.</Attribute>
+            <Attribute name="comment">Le practica recommendate pro le valores del elemento lingua es definite per RFC 1766 [RFC1766], que include un codice de lingua de duo litteras (prendite del standard ISO 639 [ISO639]), sequite optionalmente per un codice de pais de duo litteras (prendite del standard ISO 3166 [ISO3166]). Per exemplo, &apos;ia&apos; pro interlingua, &apos;fr&apos; pro francese, o &apos;en-uk&apos; pro le anglese del Regno Unite.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€­à€Ÿà€·à€Ÿ</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à¥ à€­à€Ÿà€·à€Ÿ</Attribute>
+            <Attribute name="comment">à€à€Šà€Ÿ. à€®à€°à€Ÿà€ à¥ - à€­à€Ÿà€°à€€à¥à€¯ à€­à€Ÿà€·à€Ÿ</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="Relation" >
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Relation</Attribute>
+            <Attribute name="definition">A reference to a related resource.</Attribute>
+            <Attribute name="comment">Recommended best practice is to reference the resource by means of a string or number conforming to a formal identification system.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Whai Panga</Attribute>
+            <Attribute name="definition">He tohutoro ki tetahi rauemi whai panga.</Attribute>
+            <Attribute name="comment">Ko te tino huarahi kua tohua, ko te tohutoro ki te rauemi ma te aho, te tau ranei, e hangai ana ki te punaha taututanga okawa.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Relation</Attribute>
+            <Attribute name="definition">Une rÃ©fÃ©rence Ã  une autre ressource qui a un rapport avec cette ressource.</Attribute>
+            <Attribute name="comment">Il est recommandÃ© de rÃ©fÃ©rencer cette ressource par une chaÃ®ne de caractÃšres ou un numÃ©ro conforme Ã  un systÃšme formel d&apos;identification.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÑÐœÐŸÑÐµÐœÐžÐµ</Attribute>
+            <Attribute name="definition">ï¿œÐµÐœÐœÑÐ¹ ÑÐµÑÑÑÑ.</Attribute>
+            <Attribute name="comment">ÐÐ»Ñ Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ ÐžÐŽÐµÐœÑÐžÑÐžÑÐžÑÐŸÐ²Ð°ÑÑ ÑÐµÑÑÑÑ Ð¿ÐŸÑÑÐµÐŽÑÑÐ²ÐŸÐŒ ÑÑÑÐŸÐºÐž ÐžÐ»Ðž ÑÐžÑÐ»Ð°, ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐ³ÐŸ ÑÐŸÑÐŒÐ°Ð»ÑÐœÐŸÐ¹ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÑÐžÑÑÐµÐŒÐµ.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">RelaciÃ³n</Attribute>
+            <Attribute name="definition">Un identificador de un segundo recurso y su relaciÃ³n con el recurso actual. Este elemento permite enlazar los recursos relacionados y las descripciones de los recursos. Por ejemplo: IsVersionOf - Incluye la ediciÃ³n de un trabajo, IsBasedOn - La traducciÃ³n de un trabajo, IsPartOf - Un capÃ­tulo de un libro, IsFormatOf - Un mecanismo de transformaciÃ³n de un conjunto de datos en una imagen. Para asegurar la interoperabilidad, las relaciones deberÃ­an ser seleccionadas de una lista de elementos que actualmente se encuentra bajo desarrollo en un grupo de trabajo.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙØ¹ÙØ§ÙØ©</Attribute>
+            <Attribute name="definition">ÙØ°Ø§ Ù
+Ø¹Ø±Ù ÙÙÙ
+ØµØ¯Ø± Ø§ÙØ«Ø§ÙÙ Ù Ø¹ÙØ§ÙØªÙ ØšØ§ÙÙ
+ØµØ¯Ø± Ø§ÙØ­Ø§ÙÙ . ÙØ³Ù
+Ø­ ÙØ°Ø§ Ø§ÙØ¹Ø§Ù
+Ù ØšØªÙØ¶ÙØ­ Ø§ÙØ±ÙØ§ØšØ· ØšÙÙ Ø§ÙÙ
+ØµØ§Ø¯Ø± Ø§ÙÙ
+ØªØ¹ÙÙØ©     ØšØšØ¹Ø¶ÙØ§ Ù ØªÙØµÙÙ Ø§ÙÙ
+ØµØ¯Ø± . Ø§ÙØ§Ù
+Ø«ÙØ© ØªØ¶Ù
+ Ø·ØšØ¹Ø© Ø§ÙØ¹Ù
+Ù ) ÙØ³Ø®Ø© Ù
+Ù ( ØªØ±Ø¬Ù
+Ø© Ø¹Ù
+Ù ) Ø§Ø¹ØªÙ
+Ø§Ø¯Ø§ Ø¹ÙÙ ( ÙØµÙ Ù
+Ù ÙØªØ§Øš ) Ø¬Ø²Ø¡ Ù
+Ù (    Ù ØªØ­ÙÙÙÙ Ù
+ÙÙØ§ÙÙÙÙØ© ÙÙ
+Ø¬Ù
+ÙØ¹Ø© Ù
+Ø¹ÙÙÙ
+Ø§ØªÙØ© Ø§ÙÙ ØµÙØ±Ø© ) ØµÙØºØ© Ù
+Ù ( Ù
+Ù Ø£Ø¬Ù Ø§ÙØªØ¹Ø§Ù
+Ù Ø§ÙÙ
+ØŽØªØ±Ù , ÙØ¬Øš Ø§Ø®ØªÙØ§Ø± Ø§ÙØ¹ÙØ§ÙØ§Øª Ù
+Ù    Ø§ÙÙØ§ØŠÙ
+Ø© Ø§ÙÙ
+Ø±ÙÙ
+Ø© Ù Ø§ÙØªÙ ÙØªÙ
+ Ø§Ø¹Ø¯Ø§Ø¯ÙØ§ Ø­Ø§ÙÙØ§ Ø¶Ù
+Ù Ø­ÙÙØ§Øª ÙØ±ØŽØ© Ø¹Ù
+Ù</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">å
+³è</Attribute>
+            <Attribute name="definition">æ¶åççžå
+³èµæºã</Attribute>
+            <Attribute name="comment">èåœçžå
+³èµæºæ¶ïŒå»ºè®®äœ¿çšç¬Šåæ­£åŒæ è¯ç³»ç»çå­ç¬Šäž²æè
+æ°å­ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">Vztah</Attribute>
+            <Attribute name="definition">Odkaz na pÅÃ­buznÃœ zdroj.</Attribute>
+            <Attribute name="comment">DoporuÄuje se odkazovat zdroj znakovÃœm ÅetÄzcem nebo ÄÃ­slem odpovÃ­dajÃ­cÃ­m nÄkterÃ©mu z formÃ¡lnÃ­ch identifikaÄnÃ­ch systÃ©mÅ¯.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Relatie</Attribute>
+            <Attribute name="definition">Een identificatie van een tweede bron en de relatie met de huide Internetbron. Voorbeelden zijn een editie van een werk (IsVersionOf), een vertaling van een werk (IsBasedOn), een hoofdstuk van een boek (IsPartOf) en een mechanische transformatie van een dataset in een plaatje (IsFormatOf). De DC Working Groups zijn bezig met een lijst met de meest verwachte relaties. Aanbevolen wordt om de relaties van deze lijst te gebruiken: http://purl.oclc.org/metadata/dublin_core/wrelationdraft.html.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="definition">Relation</Attribute>
+            <Attribute name="definition">Un referentia a un ressource correlate.</Attribute>
+            <Attribute name="comment">Le practica recommendate es facer referentia al ressource per medio de un catena de characteres o numero conforme a un systema de identification formal.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€šà€Ÿà€€à¥ , à€žà€à€¬à€à€§</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€¶à¥ à€žà€à€¬à€à€§ à€Šà€Ÿà€à€µà€£à€Ÿà€°à€Ÿ à€žà€à€Šà€°à¥à€­</Attribute>
+            <Attribute name="comment">à€à€Šà€Ÿ.  à€®à€Ÿà€¹à€¿à€€à¥ à€à€Ÿà€³à¥à€¯à€Ÿà€µà€°à¥à€² à€ªà€€à¥à€€à€Ÿ(URL)</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+        <Element name="conformsTo">
+            <Language code="en">
+                <Attribute name="label">Conforms To</Attribute>
+                <Attribute name="definition">A reference to an established standard to which the resource conforms.</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Attribute language="en" name="status">recommended</Attribute>
+        </Element>
+        <Element name="hasFormat">
+            <Language code="en">
+                <Attribute name="label">Has Format</Attribute>
+                <Attribute name="definition">The described resource pre-existed the referenced resource, which is essentially the same intellectual content presented in another format.</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Attribute language="en" name="status">recommended</Attribute>
+        </Element>
+        <Element name="hasPart">
+            <Language code="en">
+                <Attribute name="label">Has Part</Attribute>
+                <Attribute name="definition">The described resource includes the referenced resource either physically or logically.</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Attribute language="en" name="status">recommended</Attribute>
+        </Element>
+        <Element name="hasVersion">
+            <Language code="en">
+                <Attribute name="label">Has Version</Attribute>
+                <Attribute name="definition">The described resource has a version, edition, or adaptation, namely, the referenced resource.</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Attribute language="en" name="status">recommended</Attribute>
+        </Element>
+        <Element name="isFormatOf">
+            <Language code="en">
+                <Attribute name="label">Is Format Of</Attribute>
+                <Attribute name="definition">The described resource is the same intellectual content of the referenced resource, but presented in another format.</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Attribute language="en" name="status">recommended</Attribute>
+        </Element>
+        <Element name="isPartOf">
+            <Language code="en">
+                <Attribute name="label">Is Part Of</Attribute>
+                <Attribute name="definition">The described resource is a physical or logical part of the referenced resource.</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Attribute language="en" name="status">recommended</Attribute>
+        </Element>
+        <Element name="isReferencedBy">
+            <Language code="en">
+                <Attribute name="label">Is Referenced By</Attribute>
+                <Attribute name="definition">The described resource is referenced, cited, or otherwise pointed to by the referenced resource.</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Attribute language="en" name="status">recommended</Attribute>
+        </Element>
+        <Element name="isReplacedBy">
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Attribute language="en" name="status">recommended</Attribute>
+            <Language code="en">
+                <Attribute name="label">Is Replaced By</Attribute>
+                <Attribute name="definition">The described resource is supplanted, displaced, or superseded by the referenced resource.</Attribute>
+            </Language>
+        </Element>
+        <Element name="isRequiredBy">
+            <Attribute language="en" name="status">recommended</Attribute>
+            <Language code="en">
+                <Attribute name="label">Is Required By</Attribute>
+                <Attribute name="definition">The described resource is required by the referenced resource, either physically or logically.</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+        </Element>
+        <Element name="isVersionOf">
+            <Language code="en">
+                <Attribute name="label">Is Version Of</Attribute>
+                <Attribute name="definition">The described resource is a version, edition, or adaptation of the referenced resource. Changes in version imply substantive changes in content rather than differences in format.</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Attribute language="en" name="status">recommended</Attribute>
+        </Element>
+        <Element name="references">
+            <Language code="en">
+                <Attribute name="label">References</Attribute>
+                <Attribute name="definition">The described resource references, cites, or otherwise points to the referenced resource.</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Attribute language="en" name="status">recommended</Attribute>
+        </Element>
+        <Element name="replaces">
+            <Language code="en">
+                <Attribute name="status">recommended</Attribute>
+                <Attribute name="label">Replaces</Attribute>
+                <Attribute name="definition">The described resource supplants, displaces, or supersedes the referenced resource.</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+        </Element>
+        <Element name="requires">
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Language code="en">
+                <Attribute name="label">Requires</Attribute>
+                <Attribute name="definition">The described resource requires the referenced resource to support its function, delivery, or coherence of content.</Attribute>
+            </Language>
+            <Attribute language="en" name="status">recommended</Attribute>
+        </Element>
+    </Element>
+    <Element name="Coverage" >
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Coverage</Attribute>
+            <Attribute name="definition">The extent or scope of the content of the resource.</Attribute>
+            <Attribute name="comment">Coverage will typically include spatial location (a place name or geographic coordinates), temporal period (a period label, date, or date range) or jurisdiction (such as a named administrative entity). Recommended best practice is to select a value from a controlled vocabulary (for example, the Thesaurus of Geographic Names [TGN]) and that, where appropriate, named places or time periods be used in preference to numeric identifiers such as sets of coordinates or date ranges.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Kapitanga</Attribute>
+            <Attribute name="definition">Te roanga, te whanuitanga ranei o te whakakaupapatanga o te rauemi.</Attribute>
+            <Attribute name="comment">Ko te tikanga, ka uru atu te wahi mokowa (te ingoa o tetahi wahi, whakapiritanga matawhenua ranei), whakaritenga wa (he tapatanga wa (period label, ra, whakatakotoranga whanui o nga ra), te whakaritenga ture (penei i te putahi whakahaere). Ko te tino huarahi kua tohua, ko te tipako uara mai i tetahi whakaritenga kupu (hei tauira, i tetahi Puna Kupu Ingoa Matawhenua (Geographic Names [TGN] i nga wahi tika, ko nga wahi me nga whakaritenga wa ka whakamahia i mua i te whakamahitanga o nga taututanga tau penei i nga huinga whakapiritanga me nga whakatakotoranga whanui o nga ra.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Couverture</Attribute>
+            <Attribute name="definition">La portÃ©e ou la couverture spatio-temporelle de la ressource.</Attribute>
+            <Attribute name="comment">La couverture typiquement inclut une position gÃ©ographique (le nom d&apos;un lieu ou ses coordonnÃ©es), une pÃ©riode de temps (un nom de pÃ©riode, une date, ou un intervalle de temps) ou une juridiction (telle que le nom d&apos;une entitÃ© administrative). Il est recommandÃ© de choisir la  valeur de Couverture dans un vocabulaire contrÃŽlÃ© (par exemple, un thÃ©saurus de noms gÃ©ographiques, comme[TGN]) et, quand cela est appropriÃ©, des noms de lieux ou de pÃ©riodes plutÃŽt que des identifiants numÃ©riques tels que des coordonnÃ©es ou des intervalles de dates. </Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÑ
+Ð²Ð°Ñ</Attribute>
+            <Attribute name="definition">ÐÑÐŸÑÑÐ¶ÐµÐœÐœÐŸÑÑÑ Ðž Ð³ÑÐ°ÐœÐžÑÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÑ
+Ð²Ð°Ñ ÐŸÐ±ÑÐºÐœÐŸÐ²ÐµÐœÐœÐŸ Ð²ÐºÐ»ÑÑÐ°ÐµÑ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²ÐµÐœÐœÐŸÐµ ÐŒÐµÑÑÐŸÐœÐ°Ñ
+ÐŸÐ¶ÐŽÐµÐœÐžÐµ (ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐŒÐµÑÑÐœÐŸÑÑÐž ÐžÐ»Ðž Ð³ÐµÐŸÐ³ÑÐ°ÑÐžÑÐµÑÐºÐžÐµ ÐºÐŸÐŸÑÐŽÐžÐœÐ°ÑÑ), Ð²ÑÐµÐŒÐµÐœÐœÐŸÐ¹ Ð¿ÑÐŸÐŒÐµÐ¶ÑÑÐŸÐº (ÑÐºÐ°Ð·Ð°ÐœÐžÐµ Ð¿ÐµÑÐžÐŸÐŽÐ°, ÐŽÐ°ÑÐ° ÐžÐ»Ðž ÑÑÐŽ ÐŽÐ°Ñ) ÐžÐ»Ðž ÑÑÐžÑÐŽÐžÐºÑÐžÑ (ÑÐºÐ°Ð·Ð°ÐœÐžÐµ ÐµÐŽÐžÐœÐžÑÑ Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐ°ÑÐžÐ²ÐœÐŸÐ³ÐŸ ÐŽÐµÐ»ÐµÐœÐžÑ). ÐÐ° Ð¿ÑÐ°ÐºÑÐžÐºÐµ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ Ð²ÑÐ±ÐžÑÐ°ÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐžÐ· ÐºÐŸÐœÑÑÐŸÐ»ÐžÑÑÐµÐŒÐŸÐ³ÐŸ ÑÐ»ÐŸÐ²Ð°ÑÑ (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, Ð¢ÐµÐ·Ð°ÑÑÑÑÐ° Ð³ÐµÐŸÐ³ÑÐ°ÑÐžÑÐµÑÐºÐžÑ
+ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐ¹ TGN), Ðž, ÐµÑÐ»Ðž ÑÑÐŸ ÑÐŒÐµÑÑÐœÐŸ, Ð¿ÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÐµ ÐŸÑÐŽÐ°ÐµÑÑÑ ÑÐºÐ°Ð·Ð°ÐœÐžÑÐŒ ÐŒÐµÑÑÐœÐŸÑÑÐµÐ¹ ÐžÐ»Ðž Ð²ÑÐµÐŒÐµÐœÐœÑÑ
+ Ð¿ÑÐŸÐŒÐµÐ¶ÑÑÐºÐŸÐ² Ð²ÐŒÐµÑÑÐŸ ÑÐžÑÑÐŸÐ²ÑÑ
+ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ², ÐºÐ°Ðº, ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÑÐžÑÑÐµÐŒ ÐºÐŸÐŸÑÐŽÐžÐœÐ°Ñ ÐžÐ»Ðž Ð²ÑÐµÐŒÐµÐœÐœÑÑ
+ ÑÑÐŽÐŸÐ².</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Cobertura</Attribute>
+            <Attribute name="definition">La caracterÃ­stica de cobertura espacial y/o temporal del contenido intelectual del recurso. La cobertura espacial se refiere a una regiÃ³n fÃ­sica (por ejemplo, sector celestial); uso de coordenadas (por ejemplo, longitud y latitud) o nombres de lugares extraidos de una lista controlada. La cobertura temporal se refiere al contenido del recurso en vez de a cuando fue creado o puesto accesible ya que este Ãºltimo pertenece al elemento Date. Se usa el mismo formato basado en http://www.w3.org/TR/NOTE-datetime.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø§ÙØªØºØ·ÙØ©</Attribute>
+            <Attribute name="definition">ÙÙ Ø§ÙØ®ØµØ§ØŠØµ Ø§ÙÙ
+ÙØ§ÙÙØ© Ø§Ù Ø§ÙØ²Ù
+ÙÙØ© ÙÙÙ
+Ø­ØªÙÙ Ø§ÙÙÙØ±Ù ÙÙÙ
+ØµØ¯Ø± . Ø§ÙØªØºØ·ÙØ© Ø§ÙÙ
+ÙØ§ÙÙØ© ØªØŽÙØ± Ø§ÙÙ Ø¬ÙØ© Ø·ØšÙØ¹ÙØ© )Ù
+Ø«Ù , ÙØ·Ø§Ø¹ Ø³Ù
+Ø§ÙÙ (    Ø§Ø³ØªØ®Ø¯Ø§Ù
+ Ø§ÙØ§Ø­Ø¯Ø§Ø«ÙØ§Øª ) Ù
+Ø«Ù  Ø®Ø· Ø§ÙØ·ÙÙ Ù Ø®Ø· Ø§ÙØ¹Ø±Ø¶ ( ÙÙ Ø£Ø³Ù
+Ø§Ø¡ Ø§Ù
+ÙÙØ© Ù
+Ø³ØªØ­ÙÙ
+Ø© Ø§Ù Ù
+ØªØ¬ÙØ§Øª ØšØ§ÙÙØ§Ù
+Ù . Ø§ÙØªØºØ·ÙØ© Ø§ÙØ²Ù
+ÙÙØ©    Ø«Ø¹ÙØ¯ Ø§ÙÙ Ù
+Ø§ ÙØ±Ø¬Ø¹ Ø§ÙÙÙ Ø§ÙÙ
+ØµØ¯Ø± Ù ÙÙØ³ Ø§Ù Ù
+ØªÙ ØªÙ
+ ØªÙÙÙØ±Ù ) Ø§ÙØ§Ø®ÙØ± ÙØªØ¹ÙÙ ØšØ¹Ø§Ù
+Ù Ø§ÙØªØ§Ø±ÙØ® ( Ø§Ø³ØªØ®Ø¯Ø§Ù
+ ÙÙØ³ ØµÙØºØ© Ø§ÙØªØ§Ø±ÙØ®  Ø§Ù Ø§ÙÙÙØª    ) Ø¹Ø§Ø¯Ø© Ù
+Ø¯Ù ] ( ØµÙØ§ØºØ§Øª Ø§ÙÙÙÙ
+ Ù Ø§ÙÙÙØª ) Ø§Ø¹ØªÙ
+Ø§Ø¯Ø§ Ø¹ÙÙ (ISO 8601 Ø§ÙÙ
+ÙØ§Ø­ØžØ© Ø§ÙÙÙÙØ© [http://www.w3.org/TR/NOTE-datetime, W3C    ÙÙ
+Ø§ ÙÙ Ù
+ÙØµÙ ØšÙ ÙØ¹Ø§Ù
+Ù Ø§ÙØªØ§Ø±ÙØ® Ø§Ù ÙØªØ±Ø§Øª Ø²Ù
+ÙÙØ© Ù
+Ù ÙØ§ØŠÙ
+Ø© Ù
+Ø³ØªØ­ÙÙ
+Ø© Ø§Ù Ù
+ØªØ¬ÙØ§Øª ØšØ§ÙÙØ§Ù
+Ù</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">èŠçèåŽ</Attribute>
+            <Attribute name="definition">èµæºå
+å®¹ææ¶åçå€å»¶äžèŠçèåŽ</Attribute>
+            <Attribute name="comment">èŠçèåŽäžè¬å
+æ¬ç©ºéŽäœçœ®ïŒäžäžªå°åæå°çåæ ïŒãæ¶éŽåºéŽïŒäžäžªæ¶éŽæ è¯ïŒæ¥ææäžäžªæ¥æè    åŽïŒãæè
+æéïŒæ¯åŠåœåçææå®äœïŒæšèèŠçèåŽæå¥œæ¯åèªäºäžäžªåæ§è¯è¡šïŒäŸåŠå°åè¯åº    [TGN]ïŒïŒå¹¶åºå°œå¯èœå°äœ¿çšç±æ°å­è¡šç€ºçåæ ææ¥æåºéŽæ¥æè¿°å°åäžæ¶éŽæ®µã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">PokrytÃ­</Attribute>
+            <Attribute name="definition">Rozsah nebo zÃ¡bÄr obsahu zdroje.</Attribute>
+            <Attribute name="comment">PokrytÃ­ bude typicky obsahovat prostorovÃ© umÃ­stÄnÃ­ (jmÃ©no mÃ­sta nebo zemÄpisnÃ© souÅadnice), ÄasovÃ© obdobÃ­ (oznaÄenÃ­ obdobÃ­, datum nebo ÄasovÃœ interval) nebo jurisdikci (napÅ. jmÃ©no administrativnÃ­ jednotky). DoporuÄuje se vybÃ­rat hodnotu z ÅÃ­zenÃ©ho slovnÃ­ku (napÅ. Thesaurus of Geographic Names [TGN]) a tam, kde je to vhodnÃ©, uvÃ¡dÄt mÃ­sta nebo ÄasovÃ© Ãºseky spÃ­Å¡e jmÃ©nem neÅŸ ÄÃ­selnÃœmi identifikÃ¡tory jako jsou soubory souÅadnic nebo ÄasovÃ© intervaly.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Dekking</Attribute>
+            <Attribute name="definition">De ruimtelijke of tijdelijke karakteristieken van de intellectuele inhoud van de Internetbron. Ruimtelijke dekking verwijst naar een geografisch gebied. Gebruik coordinaten (longitude (lengtegraad) en latitude (breedtegraad)) of plaatsnamen die van een gecontroleerde lijst komen of volledig uitgeschreven zijn. Dekking in de tijd geeft de tijdsperiode aan waarop de inhoud van de Internetbron betrekking heeft en niet wanneer de Internetbron is gemaakt of beschikbaar is gesteld (dit laatste hoort ingevult te worden bij &quot;Date&quot;). Gebruik dezelfde datum/tijd formaat als bij &quot;Date&quot;; W3C Technical Note http://www.w3.org/TR/NOTE-datetime of tijdsperioden die van een gecontroleerde lijst komen of volledig uitgeschreven zijn. Coverage is in ontwikkeling bij de Dublin Core Working group http://www.alexandria.ucsb.edu/docs/metadata/dc_coverage.html.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Copertura</Attribute>
+            <Attribute name="definition">Le extension physic o abstracte del contento del ressource.</Attribute>
+            <Attribute name="comment">Le copertura typicamente include un location spatial (un nomine de localitate o coordinatas geographic), un periodo de tempore (un etiquetta de periodo, data, o gamma de datas), o un jurisdiction (tal como un entitate administrative nominate). Le practica recommendate es selectionar un valor a partir de un vocabulario controlate (per exemplo, le Thesaurus of Geographical Names [TGN]) e que, quando appropriate, localitates o periodos de tempore nominate sia utilizate in preferentia a identificatores numeric tales como collectiones de coordinatas o gammas de datas.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€µà¥à€¯à€Ÿà€ªà¥à€€à¥</Attribute>
+            <Attribute name="definition">à€®à€Ÿà€¹à€¿à€€à¥à€žà€Ÿà€ à¥à€¯à€Ÿà€à¥ à€­à¥à€à¥à€²à€¿à€  à€®à€Ÿà€¹à€¿à€€à¥</Attribute>
+            <Attribute name="comment">à€à€Šà€Ÿ. à€­à¥à€à¥à€²à€¿à€ à€µà¥à€¯à€Ÿà€ªà¥à€€à¥</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+        <Element name="spatial">
+            <Attribute language="en" name="status">recommended</Attribute>
+            <Language code="en">
+                <Attribute name="label">Spatial</Attribute>
+                <Attribute name="definition">Spatial characteristics of the intellectual content of the resource.</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+        </Element>
+        <Element name="temporal">
+            <Language code="en">
+                <Attribute name="label">Temporal</Attribute>
+                <Attribute name="definition">Temporal characteristics of the intellectual content of the resource.</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Attribute language="en" name="status">recommended</Attribute>
+        </Element>
+    </Element>
+    <Element name="Rights" >
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Rights Management</Attribute>
+            <Attribute name="definition">Information about rights held in and over the resource.</Attribute>
+            <Attribute name="comment">Typically, a Rights element will contain a rights management statement for the resource, or reference a service providing such information. Rights information often encompasses Intellectual Property Rights (IPR), Copyright, and various Property Rights. If the Rights element is absent, no assumptions can be made about the status of these and other rights with respect to the resource.</Attribute>
+        </Language>
+        <!-- Maori -->
+        <Language code="mi">
+            <Attribute name="label">Motika</Attribute>
+            <Attribute name="definition">Ko nga mohiohio ki nga motika o tetahi rauemi.</Attribute>
+            <Attribute name="comment">Ko te tikanga, kei te huanga Motika e pupuri ana he korero mo te whakaritenga motika mo te rauemi, he ratonga tohutoro e whakarato ana ranei i enei tumomo mohiohio. He nui nga wa, puta ai i roto i te mohiohio Motika te Mana Whakairo Hinegaro (Intellectual Property Rights - (IPR)), te Manatarua me nga Tuahua Mana Taonga (Property Rights). Ki te kore te huanga Motika, kaore e taea te pohehe noa ki te mana o enei, nga motika ranei e pa ana ki te rauemi.</Attribute>
+        </Language>
+        <!-- French -->
+        <Language code="fr">
+            <Attribute name="label">Droits</Attribute>
+            <Attribute name="definition">Information sur les droits sur et au sujet de la ressource.</Attribute>
+            <Attribute name="comment">Typiquement, un Ã©lÃ©ment Droits contiendra un Ã©tat du droit Ã  gÃ©rer une ressource, ou la refÃ©rence Ã  un service fournissant cette information. Ces droits souvent couvrent les droits de propriÃ©tÃ© intellectuelle (IPR), Copyright, et divers droits de propriÃ©tÃ©. Si l&apos;Ã©lÃ©ment Droits est absent, aucune hypothÃšse ne peut Ãªtre faite sur l&apos;Ã©tat de ces droits, ou de tout autre, par rapport Ã  la ressource.</Attribute>
+        </Language>
+        <!-- Russian -->
+        <Language code="ru">
+            <Attribute name="label">ÐÑÐ°Ð²ÐŸÐ²ÐŸÐµ ÑÐµÐ³ÑÐ»ÐžÑÐŸÐ²Ð°ÐœÐžÐµ</Attribute>
+            <Attribute name="definition">ÐÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ Ð¿ÑÐ°Ð²Ð°Ñ
+ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ, ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐ°ÑÑÑ Ð²ÐœÑÑÑÐž Ðž Ð²ÐœÐµ ÑÐµÑÑÑÑÐ°.</Attribute>
+            <Attribute name="comment">ÐÐ±ÑÑÐœÐŸ ÑÐ»ÐµÐŒÐµÐœÑ ÐÑÐ°Ð²Ð° ÑÐŸÐŽÐµÑÐ¶ÐžÑ Ð¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐžÐµ ÐŸ Ð¿ÑÐ°Ð²ÐŸÐ²ÑÑ
+ ÐœÐŸÑÐŒÐ°Ñ
+, ÑÐµÐ³ÑÐ»ÐžÑÑÑÑÐžÑ
+ ÑÑÐœÐºÑÐžÐŸÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÑÐµÑÑÑÑÐ° ÐžÐ»Ðž ÑÑÑÐ»ÐºÑ ÐœÐ° ÑÐ»ÑÐ¶Ð±Ñ, Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÑÑÑÑÑ ÑÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ. ÐÑÐ°Ð²ÐŸÐ²Ð°Ñ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸÐ±ÑÑÐœÐŸ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÑÐ²ÐµÐŽÐµÐœÐžÑ ÐŸ ÐÑÐ°Ð²Ð°Ñ
+ ÐžÐœÑÐµÐ»Ð»ÐµÐºÑÑÐ°Ð»ÑÐœÐŸÐ¹ ÑÐŸÐ±ÑÑÐ²ÐµÐœÐœÐŸÑÑÐž, ÐÐ²ÑÐŸÑÑÐºÐŸÐŒ Ð¿ÑÐ°Ð²Ðµ Ðž ÐŽÑÑÐ³ÐžÑ
+ ÐÐŒÑÑÐµÑÑÐ²ÐµÐœÐœÑÑ
+ Ð¿ÑÐ°Ð²Ð°Ñ
+. ÐÑÑÑÑÑÑÐ²ÐžÐµ ÑÐ»ÐµÐŒÐµÐœÑÐ° ÐÑÐ°Ð²Ð° ÐœÐµ ÐŒÐŸÐ¶ÐµÑ ÑÐ²Ð»ÑÑÑÑÑ ÐŸÑÐœÐŸÐ²Ð°ÐœÐžÐµÐŒ ÐŽÐ»Ñ ÐºÐ°ÐºÐžÑ
+-Ð»ÐžÐ±ÐŸ Ð¿ÑÐµÐŽÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐžÐ¹ ÐŸ Ð¿ÑÐ°Ð²ÐŸÐ²ÐŸÐŒ ÑÑÐ°ÑÑÑÐµ Ðž ÐŽÑÑÐ³ÐžÑ
+ Ð¿ÑÐ°Ð²Ð°Ñ
+, ÐºÐ°ÑÐ°ÑÑÐžÑ
+ÑÑ ÑÐµÑÑÑÑÐ°.</Attribute>
+        </Language>
+        <!-- Spanish -->
+        <Language code="es">
+            <Attribute name="label">Derechos</Attribute>
+            <Attribute name="definition">Una referencia (URL, por ejemplo) para una nota sobre derechos de autor, para un servicio de gestiÃ³n de derechos o para un servicio que darÃ¡ informaciÃ³n sobre tÃ©rminos y condiciones de acceso a un recurso. Una especificaciÃ³n formal del elemento Rights se encuentra catualmente en discusiÃ³n y por lo tanto su uso se considera experimental.</Attribute>
+        </Language>
+        <!-- Arabic -->
+        <Language code="ar">
+            <Attribute name="label">Ø­ÙÙÙ Ø§ÙØ§Ø¯Ø§Ø±Ø©</Attribute>
+            <Attribute name="definition">ÙÙ Ø§ÙØ§Ø¯Ø© Ø­ÙÙÙ Ø§ÙØ§Ø¯Ø§Ø±Ø© , Ù
+Ø¹Ø±Ù Ù
+Ø±ØªØšØ· ØšØ§ÙØ§Ø¯Ø© Ø­ÙÙÙ Ø§ ÙØ§Ø¯Ø§Ø±Ø© , Ù
+Ø¹Ø±Ù Ù
+Ø±ØªØšØ· ØšØ®Ø¯Ù
+Ø© ØªÙØ¯Ù
+ Ù
+Ø¹ÙÙÙ
+Ø§Øª Ø¹Ù Ø­ÙÙÙ Ø§ÙØ§Ø¯Ø§Ø±Ø© Ø§ÙØ®Ø§ØµØ© ØšØ§ÙÙ
+ØµØ¯Ø±</Attribute>
+        </Language>
+        <!-- Chinese - Simplified -->
+        <Language code="cn">
+            <Attribute name="label">æé</Attribute>
+            <Attribute name="definition">æå
+³èµæºæ¬èº«ææçæè¢«èµäºçæéä¿¡æ¯</Attribute>
+            <Attribute name="comment">äžè¬èèšïŒæéå
+çŽ åºå
+æ¬äžäžªå¯¹èµæºçæéå£°æïŒæè
+æ¯å¯¹æäŸè¿äžä¿¡æ¯çæå¡çåç
+§ãæéäžè¬    å
+æ¬ç¥è¯äº§æ(IPR)ïŒçææå
+¶ä»åç§åæ ·çäº§æãåŠææ²¡ææéå
+çŽ çæ æ³šïŒäžå¯ä»¥å¯¹äžèµæºçžå
+³    çäžè¿°æå
+¶ä»æå©çæ
+åµäœåºä»»äœåå®ã</Attribute>
+        </Language>
+        <!-- Czech -->
+        <Language code="cs">
+            <Attribute name="label">PrÃ¡va</Attribute>
+            <Attribute name="definition">Informace o prÃ¡vech vztahujÃ­cÃ­ch se k popisovanÃ©mu zdroji.</Attribute>
+            <Attribute name="comment">Prvek PrÃ¡va bude typicky obsahovat ustanovenÃ­ o sprÃ¡vÄ autorskÃœch/vlastnickÃœch prÃ¡v ke zdroji nebo odkaz na sluÅŸbu poskytujÃ­cÃ­ takovÃ©to informace. Informace o prÃ¡vech Äasto zahrnujÃ­ prÃ¡va duÅ¡evnÃ­ho vlastnictvÃ­ (IPR), autorskÃ© prÃ¡vo a rÅ¯znÃ¡ vlastnickÃ¡ prÃ¡va. JestliÅŸe prvek PrÃ¡va chybÃ­, nelze odvozovat ÅŸÃ¡dnÃ© pÅedpoklady o stavu tÄchto a jinÃœch prÃ¡v vztahujÃ­cÃ­ch se k popisovanÃ©mu zdroji.</Attribute>
+        </Language>
+        <!-- Dutch -->
+        <Language code="nl">
+            <Attribute name="label">Copyright</Attribute>
+            <Attribute name="definition">Een copyright verklaring of een link naar een copyright verklaring of een link naar een service die informatie geeft over de copyright van de Internetbron.</Attribute>
+        </Language>
+        <!-- Finnish -->
+        <Language code="fi">
+            <Attribute name="label"/>
+            <Attribute name="definition"/>
+            <Attribute name="comment"/>
+        </Language>
+        <!-- Interlingua -->
+        <Language code="ia">
+            <Attribute name="label">Gestion de derectos</Attribute>
+            <Attribute name="definition">Information super derectos detenite super e a proposito del ressource.</Attribute>
+            <Attribute name="comment">Typicamente le elemento derectos continera un declaration de gestion de derectos pro le ressource, o un referentia a un servicio que provide tal information. Information de derectos frequentemente involve derectos de proprietate intellectual (IPR), copyright e varie derectos de proprietate. Si le elemento Derectos es absente, necun hypothese pote esser facite quanto al stato de iste e altere derectos concernente ressource.</Attribute>
+        </Language>
+        <!-- Marathi -->
+        <Language code="mr">
+            <Attribute name="label">à€¹à€à¥à€</Attribute>
+            <Attribute name="definition">à€¬à¥à€§à¥à€Šà€¿à€ à€žà€à€ªà€Šà¥à€à€Ÿà€¹à€à¥à€</Attribute>
+            <Attribute name="comment">à€žà¥à€µà€€à€à€¹à€Ÿà€à¥ à€²à¥à€à€š à€à€Ÿà€ªà¥à€š à€
+à€¥à€µà€Ÿ à€®à€Ÿà€¹à€¿à€€à¥à€à€Ÿà€³à¥à€¯à€Ÿà€µà€° à€ªà¥à€°à€à€Ÿà€¶à€¿à€€ à€à€°à€£à¥à€¯à€Ÿà€à€Ÿ à€²à¥à€à€ à€
+à€¥à€µà€Ÿ à€²à¥à€à€¿à€à¥à€à€Ÿ à€¬à¥à€§à¥à€Šà€¿à€ à€žà€à€ªà€Šà¥à€à€Ÿà€¹à€à¥à€</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.1</Attribute>
+        <Attribute language="en" name="registration_authority">Dublin Core Metadata Initiative</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Charater String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+        <Element name="accessRights">
+            <Language code="en">
+                <Attribute name="label">Access Rights</Attribute>
+                <Attribute name="definition">Information about who can access the resource or an indication of its security status.</Attribute>
+                <Attribute name="comment">Access Rights may include information regarding access or restrictions based on privacy, security or other regulations.</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Attribute language="en" name="status">conforming</Attribute>
+        </Element>
+        <Element name="license">
+            <Language code="en">
+                <Attribute name="label">License</Attribute>
+                <Attribute name="definition">A legal document giving official permission to do something with the resource.</Attribute>
+                <Attribute name="comment">Recommended best practice is to identify the license using a URI. Examples of such licenses can be found at http://creativecommons.org/licenses/.</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Attribute language="en" name="status">conforming</Attribute>
+        </Element>
+    </Element>
+    <Element name="Audience">
+        <Language code="en">
+            <Attribute name="label">Audience</Attribute>
+            <Attribute name="definition">A class of entity for whom the resource is intended or useful.</Attribute>
+            <Attribute name="comment">A class of entity may be determined by the creator or the publisher or by a third party.</Attribute>
+        </Language>
+        <Element name="educationLevel">
+            <Language code="en">
+                <Attribute name="label">Audience Education Level</Attribute>
+                <Attribute name="definition">A general statement describing the education or training context. Alternatively, a more specific statement of the location of the audience in terms of its progression through an education or training context.</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Attribute language="en" name="status">conforming</Attribute>
+        </Element>
+        <Element name="mediator">
+            <Language code="en">
+                <Attribute name="definition">A class of entity that mediates access to the resource and for whom the resource is intended or useful.</Attribute>
+                <Attribute name="comment">The audiences for a resource are of two basic classes: (1) an ultimate beneficiary of the resource, and (2) frequently, an entity that mediates access to the resource. The mediator element refinement represents the second of these two classes.</Attribute>
+                <Attribute name="label">Mediator</Attribute>
+            </Language>
+            <Attribute language="en" name="type">element-refinement</Attribute>
+            <Attribute language="en" name="status">recommended</Attribute>
+        </Element>
+    </Element>
+    <Element name="Provenance">
+        <Language code="en">
+            <Attribute name="label">Provenance</Attribute>
+            <Attribute name="definition">A statement of any changes in ownership and custody of the resource since its creation that are significant for its authenticity, integrity and interpretation.</Attribute>
+            <Attribute name="comment">The statement may include a description of any changes successive custodians made to the resource.</Attribute>
+        </Language>
+    </Element>
+    <Element name="RightsHolder">
+        <Language code="en">
+            <Attribute name="definition">A person or organization owning or managing rights over the resource.</Attribute>
+            <Attribute name="comment">Recommended best practice is to use the URI or name of the Rights Holder to indicate the entity.</Attribute>
+            <Attribute name="label">Rights Holder</Attribute>
+        </Language>
+        <Attribute language="en" name="status">conforming</Attribute>
+    </Element>
+</MetadataSet>
Index: /tags/greenstone-3_02-distribution/gli/metadata/rfc1807.mds
===================================================================
--- /tags/greenstone-3_02-distribution/gli/metadata/rfc1807.mds	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/metadata/rfc1807.mds	(revision 13928)
@@ -0,0 +1,404 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE MetadataSet SYSTEM "http://www.greenstone.org/dtd/MetadataSet/1.0/MetadataSet.dtd">
+<MetadataSet contact="rlasher@forsythe.stanford.edu" creator="The Internet Engineering Task Force" family="RFC 1807" language_dependent="label, definition, comment" lastchanged="Tue Sep 05 14:40:36 NZST 2006 - kjdon on kanuka" namespace="rfc1807">
+    <SetLanguage code="en">
+        <Name language="en">RFC 1807 Metadata Element Set, Version TR-v2.1</Name>
+        <Description language="en">    This document is the reference description for Internet Engineering Task Force (IETF) Request for Comments (RFC) 1807 metadata standard for bibliographic records, expressed as a metadata set for Greenstone.  </Description>
+    </SetLanguage>
+    <Element name="bib-version">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Bib-version</Attribute>
+            <Attribute name="definition">The format version of RFC-1807 record.</Attribute>
+            <Attribute name="comment">This is the first field of any record. It is a mandatory field. It identifies the version of the format used to create this bibliographic record. This RFC defines BIB-Version TR-v2.1 BIB-VERSIONs that start with the letter X (case independent) are considered experimental. Bib-records sent with such a BIB-VERSION should NOT be incorporated in the permanent database of the recipient. Using this version of this format, this field is always: Format: BIB-VERSION:: CS-TR-v2.1  </Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Compulsory</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="minimum_occurance">1</Attribute>
+        <Attribute name="maximum_occurance">1</Attribute>
+    </Element>
+    <Element name="id">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Id</Attribute>
+            <Attribute name="definition">The identifier for the RFC-1807 record.</Attribute>
+            <Attribute name="comment">This is the second field of any record. It is also a mandatory field. The ID field identifies the bibliographic record and is used in management of these records. Its format is &quot;ID:: XXX//YYY&quot;, where XXX is the publisher-ID (the controlled symbol of the publisher) and YYY is the ID (e.g., report number) of the publication as assigned by the publisher. This ID is typically printed on the cover, and may contain slashes. The organization symbols &quot;DUMMY&quot; and &quot;TEST&quot; (case independent) are reserved for test records that should NOT be incorporated in the permanent database of the recipients. Format: ID:: &lt;publisher-ID&gt;//&lt;free-text&gt; Example: ID:: OUKS//CS-TR-91-123 </Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Compulsory</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="minimum_occurance">1</Attribute>
+        <Attribute name="maximum_occurance">1</Attribute>
+    </Element>
+    <Element name="entry">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Entry</Attribute>
+            <Attribute name="definition">The date RFC-1807 record was created.</Attribute>
+            <Attribute name="comment">This is a mandatory field. It is the date of creating this bibliographic record. The format for ENTRY date is &quot;Month Day, Year&quot;. The month must be alphabetic (spelled out). The &quot;Day&quot; is a 1- or 2-digit number. The &quot;Year&quot; is a 4-digit number. Format: ENTRY:: &lt;date&gt; Example: ENTRY:: January 15, 1992 </Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Compulsory</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="minimum_occurance">1</Attribute>
+        <Attribute name="maximum_occurance">1</Attribute>
+    </Element>
+    <Element name="organization">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Organization</Attribute>
+            <Attribute name="definition">The full name of the publishing organization</Attribute>
+            <Attribute name="comment">It is the full name spelled out (no acronyms, please) of the publishing organization. The use of this name is controlled together with the controlled symbol of the publisher (as discussed above for the ID field). Avoid acronyms because there are many common acronyms, such as ISI and USC. Please provide it in ascending order, such as &quot;X University, Y Department&quot; (not &quot;Y Department, X University&quot;) Format:  ORGANIZATION:: &lt;free-text&gt; Example:  ORGANIZATION:: Stanford University, Department of Computer Science  </Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="title">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Title</Attribute>
+            <Attribute name="definition">The title of the work</Attribute>
+            <Attribute name="comment">This is the title of the work as assigned by the author. This field should include the complete title with all the subtitles, if any. Format:  TITLE:: &lt;free-text&gt;  Example:  TITLE:: The Computerization of Oceanview with High Speed Fiber Optics Communication </Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="type">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Type</Attribute>
+            <Attribute name="definition">The type of publication</Attribute>
+            <Attribute name="comment">Indicates the type of publication (summary, final project report, etc.) as assigned by the issuing organization. Format:  TYPE:: &lt;free-text&gt; Example:  TYPE:: Technical Report  </Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="revision">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Revision</Attribute>
+            <Attribute name="definition">If the record is a revision of a previously issued record</Attribute>
+            <Attribute name="comment">Indicates that the current bibliographic record is a revision of a previously issued record and is intended to replace it. Revision information consists of a date and/or followed by a semicolon and by text in an open ended format. The revised bibliographic record should contain a complete record for the publication, not just a list of changes to the old record. If revision is omitted, the record is assumed to be a new record and not a revision.  If the revision date is specified as 0, this is assumed to be January 1, 1900 (the previous RFC, used revision data of 0, 1, 2, 3, etc. this specification is for programs that might process records from RFC1357). The text before the semicolon in this field is a date of the form month day, year. Any record with a more recent revision date replaces completely any record with an earlier revision date (supplied either explicitly or by default). Use the text to describe the revision. Reasons to send out a revised record include an error in the original, or change in the access information. Format:  REVISION:: January 1, 1995; &lt;free-text&gt; Example: REVISION:: January 1, 1995; FTP information added </Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="withdraw">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Withdraw</Attribute>
+            <Attribute name="definition">Withdraw means the document is no longer available.</Attribute>
+            <Attribute name="comment">Withdraw means the document is no longer available. Some Institutions choose to delete the record others remove some of the fields. It is up to each institution to decide how to process withdraw records. A withdraw record has all of the mandatory fields plus the withdraw field and a mandatory revision field. The Withdraw field should indicate the reason for the withdraw in free text. Example for withdrawing a bibliographic record:: BIB-VERSION::  CS-TR-v2.1 ID:: OUKS//CS-TR-91-123 ENTRY:: January 21, 1995 ORGANIZATION:: Oceanview University, Kansas, Computer Science TITLE:: The Computerization of Oceanview with High Speed Fiber Optics Communication REVISION:: January 21, 1995 WITHDRAW:: Withdrawn, found to be irrelevant END::  OUKS//CS-TR-91-123  </Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="author">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Author</Attribute>
+            <Attribute name="definition">The author</Attribute>
+            <Attribute name="comment">Personal names only. Normal last name first inversion. Editors should be listed here as well, identified with the usual &quot;(ed.)&quot; as shown below in the last example. If the report was not authored by a person (e.g., it was authored by a committee or a panel) use CORP-AUTHOR (see below) instead of AUTHOR. Multiple authors are entered by using multiple lines, each in the form of &quot;AUTHOR:: &lt;free-text&gt;&quot;. The system preserves the order of the authors. Format: AUTHOR:: &lt;free-text&gt; Example:  AUTHOR:: Finnegan, James A. AUTHOR:: Pooh, Winnie The AUTHOR:: Lastname, Firstname (ed.) </Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="corp-author">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Corp-author</Attribute>
+            <Attribute name="definition">The corporate author</Attribute>
+            <Attribute name="comment">The corporate author (e.g., a committee or a panel) that authored the report, which may be different from the ORGANIZATION issuing the report. In entering the corporate name please omit initial &quot;the&quot; or &quot;a&quot;.  If it is really part of the name, please invert it. Format: CORP-AUTHOR:: &lt;free-text&gt; Example: CORP-AUTHOR:: Committee on long-range computing </Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="contact">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Contact</Attribute>
+            <Attribute name="definition">The contact for the author(s)</Attribute>
+            <Attribute name="comment">The contact for the author(s). Open-ended, most likely E-mail and postal addresses. A CONTACT field for each author should be provided, separately, or for all the AUTHOR fields. E-mail addresses should always be in &quot;pointy brackets&quot; (as in the example below). Format: CONTACT:: &lt;free-text&gt; Example: CONTACT:: Prof. J. A. Finnegan, CS Dept, Oceanview Univ., Oceanview, Kansas, 54321 Tel: 913-456-7890 &lt;Finnegan@cs.ouks.edu&gt; </Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="date">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Date</Attribute>
+            <Attribute name="definition">The publication date</Attribute>
+            <Attribute name="comment">The publication date. The formats are &quot;Month Year&quot; and &quot;Month Day, Year&quot;. The month must be alphabetic (spelled out). The &quot;Day&quot; is a 1- or 2-digit number. The &quot;Year&quot; is a 4- digit number. Format:  DATE:: &lt;date&gt; Example: DATE:: January 1992 Example:  DATE:: January 15, 1992  </Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="pages">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Pages</Attribute>
+            <Attribute name="definition">Total number of pages</Attribute>
+            <Attribute name="comment">Total number of pages, without being too picky about it. Final numbered page is actually preferred, if it is a reasonable approximation to the total number of pages. Format: PAGES:: &lt;number&gt; Example:  PAGES:: 48 </Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="copyright">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Copyright</Attribute>
+            <Attribute name="definition">Copyright information</Attribute>
+            <Attribute name="comment">Copyright information. Open ended format. The COPYRIGHT field applies to the cited report, rather than to the current bibliographic record. Format:  COPYRIGHT:: &lt;free-text&gt; Example: COPYRIGHT:: Copyright for the report (c) 1991, by J. A. Finnegan. All rights reserved. Permission is granted for any academic use of the report. </Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="handle">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Handle</Attribute>
+            <Attribute name="definition">Handles are unique identifiers that are used to rerieve location data.</Attribute>
+            <Attribute name="comment">Handles are unique permanent identifiers that are  used in the Handle Management System to retrieve location data. A handle is a printable string which when given to a handle server returns the location of the data. Handles are used to identify digital objects stored within a digital library. If the technical report is available in electronic form, the Handle MUST be supplied in the bibliographic record. Format is &quot;HANDLE:: hdl:&lt;naming authority&gt;/string  of characters&quot;. The string of characters can be the report number of the technical report as assigned by the publisher. For more information on handles and handle servers see the CNRI WEB page at http://www.cnri.reston.va.us. NOTE: White space in HANDLE due to line wrap is ignored. Format: HANDLE:: hdl:&lt;naming authority&gt;/string of characters Example: HANDLE:: hdl:oceanview.electr/CS-TR-91-123</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="other_access">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Other_access</Attribute>
+            <Attribute name="definition">Other access information like URLs and URNs</Attribute>
+            <Attribute name="comment">For URLs, URNs, and other yet to be invented  formatted retrieval systems. Only one URL or URN per occurrence of the field. URL and URN information is available in the internet drafts from the IETF (Internet Engineering Task Force). The most recent drafts can be found on the CNRI WEB page at http://www.cnri.reston.va.us. NOTE: White space in a URL or URN due to line wrap is ignored. Format: OTHER_ACCESS:: URL:&lt;URL&gt; OTHER_ACCESS:: URN:&lt;URN&gt; Example: OTHER_ACCESS:: URL:http://elib.stanford.edu/Document/STANFORD.CS:CS-TN-94-1 Example: OTHER_ACCESS:: URL:ftp://JUPITER.CS.OUKS.EDU/PUBS/computerization.txt. When the URN standard is finalized naming authorities will be registered and URNs will be viable unique identifiers. Until then this is a place holder. For the latest URN drafts see CNRI WEB page at http://www.cnri.reston.va.us </Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="retrieval">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Retrieval</Attribute>
+            <Attribute name="definition">Describes how to get a copy of the full text</Attribute>
+            <Attribute name="comment">Open-ended format describing how to get a copy of the full text. This is an optional, repeatable field. No limitations are placed on the dissemination of the bibliographic records. If there are limitations on the dissemination of the publication, it should be protected by some means such as passwords. This format does not address this protection. Format:  RETRIEVAL:: &lt;free-text&gt; RETRIEVAL:: for full text with color pictures send a self-addressed stamped envelope to Prof. J.A. Finnegan, CS Dept, Oceanview University, Oceanview, KS 54321 </Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="keyword">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Keyword</Attribute>
+            <Attribute name="definition">Keywords</Attribute>
+            <Attribute name="comment">Specify any keywords, controlled or uncontrolled. This is an optional, repeatable field. Multiple keywords are entered using multiple lines in the form of  &quot;KEYWORD::  &lt;free-text&gt;.  Format: KEYWORD:: &lt;free-text&gt; Example: KEYWORD:: Scientific Communication KEYWORD:: Communication Theory </Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="cr-category">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Cr-category</Attribute>
+            <Attribute name="definition">The Computer Reviews Category index</Attribute>
+            <Attribute name="comment">Specify the CR-category.  The CR-category (the Computer Reviews Category) index (e.g., &quot;B.3&quot;) should always be included, optionally followed by the name of that category. If the name is specified it should be fully specified with parent levels as needed to clarify it, as in the second example below. Use multiple lines for multiple categories. Every year, the January issue of CR has the full list of these categories, with a detailed discussion of the CR Classification System, and a full index. Typically the full index appears in every January issue, and the top two levels in every issue. Format: CR-CATEGORY:: &lt;free-text&gt; Example: CR-CATEGORY:: D.1 Example: CR-CATEGORY:: B.3 Hardware, Memory Structures </Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="period">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Period</Attribute>
+            <Attribute name="definition">Time period covered</Attribute>
+            <Attribute name="comment">Time period covered (date range). Applicable primarily to progress reports, etc. Any format is acceptable, as long as the two dates are separated with &quot; to &quot; (the word &quot;to&quot; surrounded by spaces) and each date is in the format allowed for dates, as described above for the date field. Format: PERIOD:: &lt;date&gt; to &lt;date&gt;  Example:  PERIOD:: January 1990 to March 1990</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="series">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Series</Attribute>
+            <Attribute name="definition">Series title</Attribute>
+            <Attribute name="comment">Series title, including volume number within series. Open-ended format, with producing institution strongly  encouraged to be internally consistent. Format: SERIES:: &lt;free-text&gt;  Example: SERIES:: Communication </Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="monitoring">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Monitoring</Attribute>
+            <Attribute name="definition">The monitoring organization(s)</Attribute>
+            <Attribute name="comment">The name(s) of the monitoring organization(s). Format: MONITORING:: &lt;free-text&gt; Example: MONITORING:: ONR </Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="funding">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Funding</Attribute>
+            <Attribute name="definition">The funding organization(s)</Attribute>
+            <Attribute name="comment">The name(s) of the funding organization(s). Format: FUNDING:: &lt;free-text&gt; Example: FUNDING:: ARPA </Attribute>
+            <Attribute name="comment">The name(s) of the funding organization(s). Format: FUNDING:: &lt;free-text&gt; Example: FUNDING:: ARPA </Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="contract">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Contract</Attribute>
+            <Attribute name="definition">The contract number(s)</Attribute>
+            <Attribute name="comment">The contract number(s). Format: CONTRACT:: &lt; free-text&gt;  Example: CONTRACT:: MMA-90-23-456 </Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="grant">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Grant</Attribute>
+            <Attribute name="definition">The grant number(s)</Attribute>
+            <Attribute name="comment">The grant number(s). Format: GRANT:: &lt;free-text&gt; Example:  GRANT:: NASA-91-2345</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="language">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Language</Attribute>
+            <Attribute name="definition">The language in which the report is written</Attribute>
+            <Attribute name="comment">The language in which the report is written. Please use the full English name of that language. Please include the Abstract in English, if possible. If the language is not specified, English is assumed. Format: LANGUAGE:: &lt;free-text&gt; Example: LANGUAGE:: English  Example: LANGUAGE:: French</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="notes">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Notes</Attribute>
+            <Attribute name="definition">Miscellaneous free text</Attribute>
+            <Attribute name="comment">Miscellaneous free text. Format: NOTES:: &lt;free-text&gt; Example: NOTES:: This report is the full version of the paper with the same title in IEEE Trans ASSP Dec 1976 </Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+    <Element name="abstract">
+        <!-- English -->
+        <Language code="en">
+            <Attribute name="label">Abstract</Attribute>
+            <Attribute name="definition">The abstract of the report</Attribute>
+            <Attribute name="comment">Highly recommended, but not mandatory. Even though no limit is defined for its length, it is suggested not to expect applications to be able to handle more than 10,000 characters. The ABSTRACT is expected to be used for subject searching since titles are not enough. Even if the report is not in English, an English ABSTRACT is preferable. If no formal abstract appears on document, the producers of the bibliographic records are encouraged to use pieces of the introduction, first paragraph, etc. Format:  ABSTRACT:: xxxx .............. xxxxxxxx</Attribute>
+        </Language>
+        <!-- Non-language specific -->
+        <Attribute name="version">1.0</Attribute>
+        <Attribute language="en" name="registration_authority">The Internet Engineering Task Force</Attribute>
+        <Attribute name="obligation">Optional</Attribute>
+        <Attribute name="datatype">Character String</Attribute>
+        <Attribute name="maximum_occurance">Unlimited</Attribute>
+    </Element>
+</MetadataSet>
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/Configuration.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/Configuration.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/Configuration.java	(revision 13928)
@@ -0,0 +1,906 @@
+/**
+ *#########################################################################
+ * Configuration
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer;
+
+import java.awt.*;
+import java.io.*;
+import java.lang.ref.*;
+import java.net.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.plaf.*;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.XMLTools;
+import org.w3c.dom.*;
+
+/** This class stores the various configurable settings inside the Gatherer, both during a session, and between sessions in the form of XML. However not all data members are retained during xml serialization. To further improve efficiency, the property-name -> DOM Element pairs are stored in a SoftReferenced Hashtable.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class Configuration
+    extends Hashtable {
+
+    static final public boolean COLLECTION_SPECIFIC = true;
+    static final public boolean GENERAL_SETTING = true;
+
+    static final public int ASSISTANT_MODE = 1;
+    static final public int LIBRARIAN_MODE = 2;
+    static final public int SYSTEMS_MODE   = 3;
+    static final public int EXPERT_MODE    = 4; 
+
+    /** The string identifying an argument's name attribute. */
+    static final private String ARGUMENT_NAME = "name";
+    /** The name of the general Gatherer configuration file. */
+    static public String CONFIG_XML = "config.xml";
+    /** The name of the general Gatherer configuration file for running with GS3. */
+    static public String GS3_CONFIG_XML = "config3.xml";
+
+    /** The name of the root element of the subtree containing gatherer configuration options. This is required as the document itself may contain several other subtrees of settings (such as in the case of a '.col' file). */
+    static final private String GATHERER_CONFIG = "GathererConfig";
+    /** The string identifying an argument element. */
+    static final private String GATHERER_CONFIG_ARGUMENT = "Argument";
+
+    static final private String GENERAL_EMAIL_SETTING = "general.email";
+    /** the lang attribute of the other element */
+    static final private String LANGUAGE = "lang";
+    /** The name of a Name Element. */
+    static final private String NAME = "Name";
+    /** The name of the other arguments element. */
+    static final private String OTHER = "Other";
+    /** The name of the general Gatherer configuration template. */
+    static public String TEMPLATE_CONFIG_XML = "xml/config.xml";
+    /** The first of three patterns used during tokenization, this pattern handles a comma separated list. */
+    static final private String TOKENIZER_PATTERN1 = " ,\n\t";
+    /** The second of three patterns used during tokenization, this pattern handles an underscore separated list. */
+    static final private String TOKENIZER_PATTERN2 = "_\n\t";
+    /** The last of three patterns used during tokenization, this pattern handles an comma separated list containing spaces. */
+    static final private String TOKENIZER_PATTERN3 = ",\n\t";
+
+    static public Configuration self = null;
+    static private String gli_user_directory_path = null;
+
+    static public boolean just_updated_config_xml_file = false;
+    /** The path to the Greenstone Suite installation directory. */
+    static public String gsdl_path = "";
+    /** If we are using GLI in Greenstone 3, the path to gsdl3 home (== web dir) */
+    static public String gsdl3_path = "";
+    /** If we are using GLI in Greenstone 3, the path to gsdl3 src directory (== gsdl3 dir)*/
+    static public String gsdl3_src_path = "";
+    /** The path to the PERL executable, up to and including Perl.exe. */
+    static public String perl_path = "";
+    /** The password for the proxy server indicated above. */
+    static public String proxy_pass = null;
+    /** The username for the proxy server indicated above. */
+    static public String proxy_user = null;
+    /** The screen size of the desktop the Gatherer will be displayed on. */
+    static public Dimension screen_size = Toolkit.getDefaultToolkit().getScreenSize();
+    /** The site name if we are using GS3 */
+    static public String site_name = "";
+    /** The servlet path if we are using GS3 */
+    static public String servlet_path = "";
+    /** Collection level configuration (which in some cases overrides general configuration. */
+    static private Document collection_config;
+    /** The general configuration settings. */
+    static private Document general_config;
+
+    /** The element, from glis config file, that contains the various directory mappings. */
+    static private Element directory_mappings_element;
+
+    static private int cache_hit = 0;
+    static private int cache_miss = 0;
+
+    static public URL gliserver_url = null;
+    static public URL library_url = null;
+
+
+    /** Constructor.
+     * @param gsdl_path The path to the Greenstone directory as a <strong>String</strong>.
+     * @param gsdl3_path The path to the Greenstone 3 home (web) directory as a <strong>String</strong>.
+     * @param gsdl3_src_path The path to the Greenstone 3 src directory as a <strong>String</strong>.
+     * @param site_name The name of the Greenstone 3 site currently in use.
+     */
+    public Configuration(String gli_user_directory_path, String gsdl_path, String gsdl3_path, String gsdl3_src_path, String site_name)
+    {
+	super();
+	self = this;
+
+	this.gli_user_directory_path = gli_user_directory_path;
+	this.gsdl_path = gsdl_path;
+	this.gsdl3_path = gsdl3_path;
+	this.gsdl3_src_path = gsdl3_src_path;
+	this.site_name = site_name;
+
+	// Try to load the configuration file from the user specific location
+	String config_xml_file_name = CONFIG_XML;
+	if (gsdl3_path != null) {
+	    config_xml_file_name = GS3_CONFIG_XML;
+	}
+
+	// If the existing user config.xml file isn't recent enough, backup the old version and update it
+	File config_xml_file = new File(gli_user_directory_path + config_xml_file_name);
+	if (config_xml_file != null && config_xml_file.exists()) {
+	    just_updated_config_xml_file = updateUserConfigXMLFileIfNecessary(config_xml_file);
+	    general_config = XMLTools.parseXMLFile(config_xml_file);
+	}
+
+	// Create a new config from the default configuration file from our xml library
+	if (general_config == null) {
+	    general_config = XMLTools.parseXMLFile(TEMPLATE_CONFIG_XML, true);
+	    just_updated_config_xml_file = true;
+	}
+
+	// Determine the Directory Mappings element
+	directory_mappings_element = (Element) XMLTools.getNodeFromNamed(general_config.getDocumentElement(), StaticStrings.DIRECTORY_MAPPINGS_ELEMENT);
+
+	// Re-establish the color settings.
+	updateUI();
+
+	// Read the Greenstone library URL from the config file
+	String library_url_string = getString("general.library_url", true);
+	if (!library_url_string.equals("")) {
+	    try {
+		library_url = new URL(library_url_string);
+	    }
+	    catch (MalformedURLException exception) {
+		DebugStream.printStackTrace(exception);
+	    }
+	}
+
+	// Read the Greenstone gliserver URL from the config file, if using a remote Greenstone
+	if (Gatherer.isGsdlRemote) {
+	    String gliserver_url_string = getString("general.gliserver_url", true);
+	    if (!gliserver_url_string.equals("")) {
+		try {
+		    gliserver_url = new URL(gliserver_url_string);
+		}
+		catch (MalformedURLException exception) {
+		    DebugStream.printStackTrace(exception);
+		}
+	    }
+	}
+
+	if (gsdl3_path != null) {
+	    if (this.site_name == null || this.site_name.equals("")) {
+		this.site_name = getString("general.site_name", true);
+		this.servlet_path = getString("general.servlet_path", true);
+		if (this.site_name.equals("")) {
+		    this.site_name = "localsite"; // can we assume these??
+		    this.servlet_path = "/library";
+		    setString("general.site_name", true, this.site_name);
+		    setString("general.servlet_path", true, this.servlet_path);
+		}
+		
+	    } else {
+		// we set the current one in the config
+		setString("general.site_name", true, this.site_name);
+		if (this.servlet_path != null && !this.servlet_path.equals("")) {
+		    setString("general.servlet_path", true, this.servlet_path);
+		}
+	    }
+	}
+    }
+
+
+    static private boolean updateUserConfigXMLFileIfNecessary(File config_xml_file)
+    {
+	// Check if the configuration file actually needs updating by looking at the version numbers
+	Document new_document = XMLTools.parseXMLFile(TEMPLATE_CONFIG_XML, true);
+	Document old_document = XMLTools.parseXMLFile(config_xml_file);
+	if (new_document == null || old_document == null) {
+	    // Something has gone badly wrong, so we can't update the file
+	    return false;
+	}
+
+	String new_version = new_document.getDocumentElement().getAttribute(StaticStrings.VERSION_ATTRIBUTE);
+	String old_version = old_document.getDocumentElement().getAttribute(StaticStrings.VERSION_ATTRIBUTE);
+	if (new_version.compareTo(old_version) <= 0) {
+	    // Don't need to update file
+	    return false;
+	}
+
+	System.err.println("Updating user config.xml from version " + old_version + " to version " + new_version + "...");
+
+	// Build up the new user config.xml file from the template config.xml with the user's preferences added
+	// Make a backup of the old config.xml file first
+	config_xml_file.renameTo(new File(config_xml_file.getAbsolutePath() + ".old"));
+
+	// Check all of the Argument elements in the new config.xml file
+	NodeList new_argument_elements_nodelist = new_document.getElementsByTagName("Argument");
+	NodeList old_argument_elements_nodelist = old_document.getElementsByTagName("Argument");
+	for (int i = 0; i < new_argument_elements_nodelist.getLength(); i++) {
+	    Element new_argument_element = (Element) new_argument_elements_nodelist.item(i);
+	    String new_argument_element_name = new_argument_element.getAttribute("name");
+	    String new_argument_element_value = XMLTools.getElementTextValue(new_argument_element);
+
+	    // Did this Argument have a non-default value set?
+	    for (int j = old_argument_elements_nodelist.getLength() - 1; j >= 0; j--) {
+		Element old_argument_element = (Element) old_argument_elements_nodelist.item(j);
+		String old_argument_element_name = old_argument_element.getAttribute("name");
+
+		// Argument found
+		if (old_argument_element_name.equals(new_argument_element_name)) {
+		    if (!new_argument_element_name.equals("general.open_collection")) {
+			String old_argument_element_value = XMLTools.getElementTextValue(old_argument_element);
+			if (!old_argument_element_value.equals(new_argument_element_value)) {
+			    XMLTools.setElementTextValue(new_argument_element, old_argument_element_value);
+			}
+		    }
+
+		    // We don't care about this option any more
+		    old_argument_element.getParentNode().removeChild(old_argument_element);
+		    break;
+		}
+	    }
+	}
+
+	// Are there any old Argument elements left over? Keep these around for old time's sake
+	old_argument_elements_nodelist = old_document.getElementsByTagName("Argument");
+	if (old_argument_elements_nodelist.getLength() > 0) {
+	    NodeList new_gathererconfig_elements_nodelist = new_document.getElementsByTagName("GathererConfig");
+	    if (new_gathererconfig_elements_nodelist.getLength() > 0) {
+		Element new_gathererconfig_element = (Element) new_gathererconfig_elements_nodelist.item(0);
+		new_gathererconfig_element.appendChild(new_document.createComment(" Legacy options "));
+
+		// Add the legacy Arguments to the GathererConfig element
+		for (int i = 0; i < old_argument_elements_nodelist.getLength(); i++) {
+		    Element old_argument_element = (Element) old_argument_elements_nodelist.item(i);
+		    new_gathererconfig_element.appendChild(new_document.importNode(old_argument_element, true));
+		}
+	    }
+	}
+
+	// Keep all the Mapping elements
+	NodeList new_directorymappings_elements_nodelist = new_document.getElementsByTagName("DirectoryMappings");
+	if (new_directorymappings_elements_nodelist.getLength() > 0) {
+	    Element new_directorymappings_element = (Element) new_directorymappings_elements_nodelist.item(0);
+
+	    NodeList old_mapping_elements_nodelist = old_document.getElementsByTagName("Mapping");
+	    for (int i = 0; i < old_mapping_elements_nodelist.getLength(); i++) {
+		Element old_mapping_element = (Element) old_mapping_elements_nodelist.item(i);
+		new_directorymappings_element.appendChild(new_document.importNode(old_mapping_element, true));
+	    }
+	}
+
+	// Check all of the Associations elements in the new config.xml file
+	NodeList new_entry_elements_nodelist = new_document.getElementsByTagName("Entry");
+	NodeList old_entry_elements_nodelist = old_document.getElementsByTagName("Entry");
+	for (int i = 0; i < new_entry_elements_nodelist.getLength(); i++) {
+	    Element new_entry_element = (Element) new_entry_elements_nodelist.item(i);
+	    String new_entry_element_name = new_entry_element.getAttribute("extension");
+	    String new_entry_element_value = XMLTools.getElementTextValue(new_entry_element);
+
+	    // Did this Entry have a non-default value set?
+	    for (int j = old_entry_elements_nodelist.getLength() - 1; j >= 0; j--) {
+		Element old_entry_element = (Element) old_entry_elements_nodelist.item(j);
+		String old_entry_element_name = old_entry_element.getAttribute("extension");
+
+		// Entry found
+		if (old_entry_element_name.equals(new_entry_element_name)) {
+		    String old_entry_element_value = XMLTools.getElementTextValue(old_entry_element);
+		    if (!old_entry_element_value.equals(new_entry_element_value)) {
+			XMLTools.setElementTextValue(new_entry_element, old_entry_element_value);
+		    }
+
+		    // We don't care about this option any more
+		    old_entry_element.getParentNode().removeChild(old_entry_element);
+		    break;
+		}
+	    }
+	}
+
+	// Are there any old Entry elements left over? We want to keep these
+	old_entry_elements_nodelist = old_document.getElementsByTagName("Entry");
+	if (old_entry_elements_nodelist.getLength() > 0) {
+	    NodeList new_associations_elements_nodelist = new_document.getElementsByTagName("Associations");
+	    if (new_associations_elements_nodelist.getLength() > 0) {
+		Element new_associations_element = (Element) new_associations_elements_nodelist.item(0);
+
+		// Add the legacy Entries to the Associations element
+		for (int i = 0; i < old_entry_elements_nodelist.getLength(); i++) {
+		    Element old_entry_element = (Element) old_entry_elements_nodelist.item(i);
+		    new_associations_element.appendChild(new_document.importNode(old_entry_element, true));
+		}
+	    }
+	}
+
+	// Write out the updated config.xml file
+	XMLTools.writeXMLFile(config_xml_file, new_document);
+	return true;
+    }
+
+
+    /** Add a special directory mapping. */
+    static public boolean addDirectoryMapping(String name, File file) {
+	boolean result = false;
+	try {
+	    // Ensure the name isn't already in use.
+	    boolean found = false;
+	    NodeList mappings = directory_mappings_element.getElementsByTagName(StaticStrings.MAPPING_ELEMENT);
+	    for(int i = 0; !found && i < mappings.getLength(); i++) {
+		Element mapping_element = (Element) mappings.item(i);
+		if(mapping_element.getAttribute(StaticStrings.NAME_ATTRIBUTE).equalsIgnoreCase(name)) {
+		    found = true;
+		}
+		mapping_element = null;
+	    }
+	    // Otherwise add the mapping.
+	    if(!found) {
+		Element mapping_element = general_config.createElement(StaticStrings.MAPPING_ELEMENT);
+		mapping_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, name);
+		mapping_element.setAttribute(StaticStrings.FILE_ATTRIBUTE, file.toString());
+		directory_mappings_element.appendChild(mapping_element);
+		result = true;
+		mapping_element = null;
+	    }
+	    mappings = null;
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+	return result;
+    } /** addDirectoryMapping(String name, String file) **/
+
+    /** The default get action retrieves the named property from the desired configuration, and returns a true or false. */
+    static public boolean get(String property, boolean general) {
+	String raw = getString(property, general);
+	return (raw != null && raw.equalsIgnoreCase("true"));
+    }
+
+    /** Retrieve all of the configuration preferences which match a certain string. They are returned as a hash map of property names to String objects. */
+    static public HashMap getAll(String property_pattern, boolean general) {
+	HashMap properties = new HashMap();
+	try {
+	    // Locate the appropriate element
+	    Element document_element = null;
+	    if(general) {
+		document_element = general_config.getDocumentElement();
+	    }
+	    else if(collection_config != null) {
+		document_element = collection_config.getDocumentElement();
+	    }
+	    if(document_element != null) {
+		// Retrieve the Gatherer element
+		Element gatherer_element = (Element) XMLTools.getNodeFromNamed(document_element, GATHERER_CONFIG);
+		NodeList arguments = gatherer_element.getElementsByTagName(GATHERER_CONFIG_ARGUMENT);
+		for(int i = 0; i < arguments.getLength(); i++) {
+		    Element argument_element = (Element) arguments.item(i);
+		    if(argument_element.getAttribute(ARGUMENT_NAME).matches(property_pattern)) {
+			String result = XMLTools.getValue(argument_element);
+			// Store a mapping in the cache. Sometimes we will overwrite an existing value (say for collection and general level workflow options) but the processing overhead of detecting these clashes far exceeds any savings.
+			self.put(argument_element.getAttribute(ARGUMENT_NAME) + general, new SoftReference(argument_element));
+			// Add mapping to the properties we're going to return
+			properties.put(argument_element.getAttribute(ARGUMENT_NAME), result);
+		    }
+		}
+	    }
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+	return properties;
+    }
+
+    /** Retrieve the value of the named property as a Rectangle. */
+    static public Rectangle getBounds(String property, boolean general) {
+	Rectangle result = null;
+	try {
+	    String raw = getString(property, general);
+	    // Rectangle is (x, y, width, height)
+	    StringTokenizer tokenizer = new StringTokenizer(raw, TOKENIZER_PATTERN1);
+	    int x = Integer.parseInt(tokenizer.nextToken());
+	    int y = Integer.parseInt(tokenizer.nextToken());
+	    int width = Integer.parseInt(tokenizer.nextToken());
+	    int height = Integer.parseInt(tokenizer.nextToken());
+	    result = new Rectangle(x, y, width, height);
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+	return result;
+    }
+
+    /** Retrieve the value of the named property as a Color. */
+    static public Color getColor(String property, boolean general) {
+	Color result = Color.white; // Default
+	try {
+	    String raw = getString(property, general);
+	    // Color is a RGB triplet list, comma separated (also remove whitespace)
+	    StringTokenizer tokenizer = new StringTokenizer(raw, TOKENIZER_PATTERN1);
+	    int red = Integer.parseInt(tokenizer.nextToken());
+	    int green = Integer.parseInt(tokenizer.nextToken());
+	    int blue = Integer.parseInt(tokenizer.nextToken());
+	    result = new Color(red, green, blue);
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+	return result;
+    }
+
+
+    /** Retrieve the special directory mappings associated with this collection.
+     * @return A <strong>HashMap</strong> containing mappings from names to directories.
+     */
+    static public HashMap getDirectoryMappings() {
+	HashMap special_directories = new HashMap();
+	try {
+	    // Ensure the name isn't already in use.
+	    boolean found = false;
+	    NodeList mappings = directory_mappings_element.getElementsByTagName(StaticStrings.MAPPING_ELEMENT);
+	    for(int i = 0; !found && i < mappings.getLength(); i++) {
+		Element mapping_element = (Element) mappings.item(i);
+		String name = mapping_element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
+		File file = new File(mapping_element.getAttribute(StaticStrings.FILE_ATTRIBUTE));
+		special_directories.put(name, file);
+		file = null;
+		name = null;
+		mapping_element = null;
+	    }
+	    mappings = null;
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+	return special_directories;
+    } /** getDirectoryMappings() */
+
+    /** Retrieve the current users email. These are always stored in the general settings.
+     * @return the email address, if it is set, as a String
+     */
+    static public String getEmail() {
+	String email = getString(GENERAL_EMAIL_SETTING, true);
+	return (email.length() > 0 ? email : null);
+    }
+
+    static public Element getFileAssociations() {
+	NodeList file_association_elements = general_config.getDocumentElement().getElementsByTagName(StaticStrings.ASSOCIATIONS_ELEMENT);
+	return (Element) file_association_elements.item(0);
+    }
+
+    /** Retrieve the value of the named property as a FontUIResource. */
+    static public FontUIResource getFont(String property, boolean general) {
+	FontUIResource result = new FontUIResource("Times New Roman", Font.PLAIN, 10);
+	try {
+	    String raw = getString(property, general);
+	    // Font is a face, style, size triplet.
+	    StringTokenizer tokenizer = new StringTokenizer(raw, TOKENIZER_PATTERN3);
+	    String face = tokenizer.nextToken().trim();
+	    ///ystem.err.println("Face:  " + face);
+	    int style = Font.PLAIN;
+	    String temp = tokenizer.nextToken().toUpperCase().trim();
+	    ///ystem.err.println("Style: " + temp);
+	    if(temp.equals("BOLD")) {
+		style = Font.BOLD;
+	    }
+	    else if(temp.equals("ITALIC")) {
+		style = Font.ITALIC;
+	    }
+	    int size = Integer.parseInt(tokenizer.nextToken().trim());
+	    ///ystem.err.println("Size:  " + size);
+	    result = new FontUIResource(face, style, size);
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+	return result;
+    }
+
+    /** Retrieve the value of the named property as an integer. */
+    static public int getInt(String property, boolean general) {
+	int result = 0;
+	try {
+	    String raw = getString(property, general);
+	    result = Integer.parseInt(raw);
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+	return result;
+    }
+
+    /** Retrieves the current interface language two letter code. */
+    static public String getLanguage() {
+	Locale locale = getLocale("general.locale", GENERAL_SETTING);
+	String code = "en"; // Default
+	if(locale != null) {
+	    code = locale.getLanguage();
+	}
+	return code;
+    }
+
+    /** Retrieve the value of the named property as a Locale. */
+    static public Locale getLocale(String property, boolean general) {
+	Locale result = Locale.getDefault();
+	try {
+	    String raw = getString(property, general);
+	    // Locale is a underscore separated code.
+	    StringTokenizer tokenizer = new StringTokenizer(raw, TOKENIZER_PATTERN2);
+	    String language = tokenizer.nextToken();
+	    if(tokenizer.hasMoreTokens()) {
+		String country = tokenizer.nextToken();
+		result = new Locale(language, country);
+	    }
+	    else {
+		result = new Locale(language);
+	    }
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+	return result;
+    }
+
+    /** Because modes will soon be an integral part of GLI, they get their own easy to remember methods such as this one to get the mode.
+     * @return an int representing the mode
+     */
+    static public int getMode() {
+	return getInt("general.mode", GENERAL_SETTING);
+    }
+
+    /** Return the current mode as a string for use in title bar etc
+     * @return the mode as a String
+     */
+    static public String getModeAsString() {
+	String result;
+	switch(getInt("general.mode", GENERAL_SETTING)) {
+	case ASSISTANT_MODE:
+	    result = Dictionary.get("Preferences.Mode.Assistant");
+	    break;
+	case SYSTEMS_MODE:
+	    result = Dictionary.get("Preferences.Mode.Systems");
+	    break;
+	case EXPERT_MODE:
+	    result = Dictionary.get("Preferences.Mode.Expert");
+	    break;
+	default:
+	    result = Dictionary.get("Preferences.Mode.Librarian");
+	}
+	return result;
+    }
+
+    static public String getPreviewCommand() {
+	return getString("general.preview_program", GENERAL_SETTING);
+    }
+
+    static public String getServletPath() {
+	return servlet_path;
+    }
+
+    /** Retrieve the value of the named property, and noting whether we consult the general or collection specific configuration. */
+    static public String getString(String property, boolean general) {
+	// Its up to this method to find the appropriate node and retrieve the data itself.
+	String result = "";
+	try {
+	    // First of all we look in the cache to see if we have a match.
+	    SoftReference reference = (SoftReference) self.get(property + general);
+	    if(reference != null) {
+		Element argument_element = (Element) reference.get();
+		if(argument_element != null) {
+		    cache_hit++;
+		    result = XMLTools.getValue(argument_element);
+		}
+	    }
+	    // We may have missed in the cache, or the reference may have been consumed.
+	    if(result.length() == 0) {
+		cache_miss++;
+		// Locate the appropriate element
+		Element document_element = null;
+		if(general) {
+		    document_element = general_config.getDocumentElement();
+		}
+		else if(collection_config != null) {
+		    document_element = collection_config.getDocumentElement();
+		}
+		if(document_element != null) {
+		    // Retrieve the Gatherer element
+		    Element gatherer_element = (Element) XMLTools.getNodeFromNamed(document_element, GATHERER_CONFIG);
+		    NodeList arguments = gatherer_element.getElementsByTagName(GATHERER_CONFIG_ARGUMENT);
+		    for(int i = 0; result.length() == 0 && i < arguments.getLength(); i++) {
+			Element argument_element = (Element) arguments.item(i);
+			if(argument_element.getAttribute(ARGUMENT_NAME).equalsIgnoreCase(property)) {
+			    result = XMLTools.getValue(argument_element);
+			    // Store a mapping in the cache. Sometimes we will overwrite an existing value (say for collection and general level workflow options) but the processing overhead of detecting these clashes far exceeds any savings.
+			    self.put(property + general, new SoftReference(argument_element));
+			}
+		    }
+		}
+	    }
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+	// If we still have no result, and the search was made in the collection configuration, retrieve the general one instead.
+	if(result.length() == 0 && !general) {
+	    result = getString(property, true);
+	}
+	return result;
+    }
+
+    static public String getGS3ScriptPath() {
+	return gsdl3_src_path + "bin" + File.separator + "script" + File.separator;
+    }
+
+    /** Remove a previously defined special directory mapping.
+     * @param name The name of the mapping to remove as a <strong>String</strong>.
+     * @return The <strong>File</strong> of the mapping removed.
+     */
+    static public File removeDirectoryMapping(String name) {
+	File file = null;
+	try {
+	    // Ensure the name isn't already in use.
+	    boolean found = false;
+	    NodeList mappings = directory_mappings_element.getElementsByTagName(StaticStrings.MAPPING_ELEMENT);
+	    for(int i = 0; !found && i < mappings.getLength(); i++) {
+		Element mapping_element = (Element) mappings.item(i);
+		if(mapping_element.getAttribute(StaticStrings.NAME_ATTRIBUTE).equalsIgnoreCase(name)) {
+		    file = new File(XMLTools.getValue(mapping_element));
+		    directory_mappings_element.removeChild(mapping_element);
+		    found = true;
+		}
+		mapping_element = null;
+	    }
+	    mappings = null;
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+	return file;
+    } /** removeDirectoryMapping(String name) */
+
+    /** Export the general configuration to file. */
+    static public void save() {
+	///ystem.err.println("Hits " + cache_hit + " vs Misses " + cache_miss);
+	// We first try exporting to a user specific place
+	File user_config_xml = null;
+	String config_xml_name = CONFIG_XML;
+	if (gsdl3_path!=null) {
+	    config_xml_name = GS3_CONFIG_XML;
+	}
+	try {
+	    user_config_xml = new File(gli_user_directory_path + config_xml_name);
+	    ///ystem.err.println("Trying to save to: " + user_config_xml.getAbsolutePath());
+	    ///ystem.err.println("Writing.");
+	    user_config_xml.getParentFile().mkdirs();
+	    XMLTools.writeXMLFile(new File(user_config_xml.getAbsolutePath()), general_config);
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	    user_config_xml = null;
+	}
+    }
+
+    /** Set the named property, from the specified configuration, using the given boolean value. */
+    static public void set(String property, boolean general, boolean value) {
+	if(property.startsWith("workflow")) {
+	    DebugStream.println("Set property: " + property + ", general=" + general + ", value=" + value);
+	}
+	setString(property, general, (value ? "true" : "false"));
+    }
+
+    /** Set the collection configuration. */
+    static public void setCollectionConfiguration(Document collection_config_arg) {
+	// clear the cached values
+	self.clear();
+	collection_config = collection_config_arg;
+	updateUI();
+	///atherer.println("Collection configuration set.");
+    }
+
+    /** Set the named property, from the specified configuration, using the given Rectangle value. */
+    static public void setBounds(String property, boolean general, Rectangle value) {
+	StringBuffer text = new StringBuffer("");
+	text.append(value.x);
+	text.append(", ");
+	text.append(value.y);
+	text.append(", ");
+	text.append(value.width);
+	text.append(", ");
+	text.append(value.height);
+	setString(property, general, text.toString());
+    }
+
+    /** Set the named property, from the specified configuration, using the given Color value. */
+    static public void setColor(String property, boolean general, Color value) {
+	StringBuffer text = new StringBuffer("");
+	text.append(value.getRed());
+	text.append(", ");
+	text.append(value.getGreen());
+	text.append(", ");
+	text.append(value.getBlue());
+	setString(property, general, text.toString());
+    }
+
+    /** Establish the current users email.
+     * @param email the email as a String
+     */
+    static public void setEmail(String email) {
+	setString(GENERAL_EMAIL_SETTING, true, email);
+    }
+
+    /** Set the named property, from the specified configuration, using the given Font value. */
+    static public void setFont(String property, boolean general, Font value) {
+	StringBuffer text = new StringBuffer("");
+	text.append(value.getName());
+	text.append(", ");
+	switch(value.getStyle()) {
+	case Font.BOLD:
+	    text.append("BOLD");
+	    break;
+	case Font.ITALIC:
+	    text.append("ITALIC");
+	    break;
+	default:
+	    text.append("PLAIN");
+	}
+	text.append(", ");
+	text.append(value.getSize());
+	setString(property, general, text.toString());
+    }
+
+    /** Set the named property, from the specified configuration, using the given integer value. */
+    static public void setInt(String property, boolean general, int value) {
+        setString(property, general, String.valueOf(value));
+    } 
+
+    /** Set the named property, from the specified configuration, using the given Locale value. */
+    static public void setLocale(String property, boolean general, Locale value) {
+	StringBuffer text = new StringBuffer("");
+	text.append(value.getLanguage());
+	String country = value.getCountry();
+	if(country != null && country.length() > 0) {
+	    text.append("_");
+	    text.append(country);
+	}
+	country = null;
+	setString(property, general, text.toString());
+    }
+
+    /** Because modes will soon be an integral part of GLI, they get their own easy to remember methods such as this one to set the mode.
+     * @param value the new value for mode
+     */
+    static public void setMode(int value) {
+	setInt("general.mode", GENERAL_SETTING, value);
+    }
+
+    static public void setPreviewCommand(String value) {
+	setString("general.preview_program", GENERAL_SETTING, value);
+    }
+
+    static public void setSiteAndServlet(String site, String servlet) {
+	site_name = site;
+	servlet_path = servlet;
+	setString("general.site_name", GENERAL_SETTING, site);
+	setString("general.servlet_path", GENERAL_SETTING, servlet);
+	
+    }
+    /** Sets the value of the named property argument using the given string. */
+    static public void setString(String property, boolean general, String value) {
+	DebugStream.println("Set configuration property: " + property + " = " + value + (general ? "" : " [Collection]"));
+	try {
+	    Document document = general_config;
+	    if(!general && collection_config != null) {
+		document = collection_config;
+	    }
+	    if(document != null) {
+		Element argument_element = null;
+		// Try to retrieve from cache
+		SoftReference reference = (SoftReference) self.get(property + general);
+		if(reference != null) {
+		    argument_element = (Element) reference.get();
+		}
+		if(argument_element == null) {
+		    Element document_element = document.getDocumentElement();
+		    Element gatherer_element = (Element) XMLTools.getNodeFromNamed(document_element, GATHERER_CONFIG);
+		    NodeList arguments = document_element.getElementsByTagName(GATHERER_CONFIG_ARGUMENT);
+		    boolean found = false;
+		    for(int i = 0; argument_element == null && i < arguments.getLength(); i++) {
+			Element possible_element = (Element) arguments.item(i);
+			if(possible_element.getAttribute(ARGUMENT_NAME).equalsIgnoreCase(property)) {
+			    argument_element = possible_element;
+			}
+		    }
+		    // If argument element is still null, create it in the target document.
+		    if(argument_element == null) {
+			argument_element = document.createElement(GATHERER_CONFIG_ARGUMENT);
+			argument_element.setAttribute(ARGUMENT_NAME, property);
+			gatherer_element.appendChild(argument_element);
+		    }
+		    // Update cache
+		    self.put(property + general, new SoftReference(argument_element));
+
+		}
+		if(value == null) {
+		    value = "";
+		}
+		// Now remove any current text node children.
+		NodeList children = argument_element.getChildNodes();
+		for(int i = 0; i < children.getLength(); i++) {
+		    argument_element.removeChild(children.item(i));
+		}
+		// Add a new text node child with the new value
+		argument_element.appendChild(document.createTextNode(value));
+	    }
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+    }
+
+    static private void updateUI() {
+	// Buttons
+	UIManager.put("Button.select", new ColorUIResource(getColor("coloring.button_selected_background", false)));
+	UIManager.put("Button.background", new ColorUIResource(getColor("coloring.button_background", false)));
+	UIManager.put("Button.foreground", new ColorUIResource(getColor("coloring.button_foreground", false)));
+
+	UIManager.put("ToggleButton.background", new ColorUIResource(getColor("coloring.button_background", false)));
+	UIManager.put("ToggleButton.foreground", new ColorUIResource(getColor("coloring.button_foreground", false)));
+	UIManager.put("ToggleButton.select", new ColorUIResource(getColor("coloring.button_selected_background", false)));
+
+	// All the things with a lovely Collection green background
+	UIManager.put("OptionPane.background", new ColorUIResource(getColor("coloring.collection_heading_background", false)));
+	UIManager.put("Panel.background", new ColorUIResource(getColor("coloring.collection_heading_background", false)));
+	UIManager.put("Label.background", new ColorUIResource(getColor("coloring.collection_heading_background", false)));
+	UIManager.put("TabbedPane.background", new ColorUIResource(getColor("coloring.collection_heading_background", false)));
+	UIManager.put("SplitPane.background", new ColorUIResource(getColor("coloring.collection_heading_background", false)));
+	UIManager.put("CheckBox.background", new ColorUIResource(getColor("coloring.collection_heading_background", false)));
+
+
+	// Editable coloring
+	UIManager.put("ComboBox.background", new ColorUIResource(getColor("coloring.collection_tree_background", false))); // Indicate clickable
+	UIManager.put("Tree.background", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
+	UIManager.put("Tree.textBackground", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
+	UIManager.put("ProgressBar.background", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
+	UIManager.put("TextArea.background", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
+	UIManager.put("TextField.background", new ColorUIResource(getColor("coloring.editable_background", false)));
+	UIManager.put("Table.background", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
+	UIManager.put("List.background", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
+	UIManager.put("RadioButton.background", new ColorUIResource(getColor("coloring.collection_tree_background", false)));
+
+	// Selection color
+	UIManager.put("TabbedPane.selected", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
+	UIManager.put("Tree.selectionBackground", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
+	UIManager.put("ComboBox.selectionBackground", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
+	UIManager.put("ProgressBar.selectionBackground", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
+	UIManager.put("TextArea.selectionBackground", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
+	UIManager.put("TextField.selectionBackground", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
+	UIManager.put("List.selectionBackground", new ColorUIResource(getColor("coloring.collection_selection_background", false)));
+
+	// Scroll bar stuff
+	UIManager.put("ScrollBar.background", new ColorUIResource(getColor("coloring.scrollbar_background", false)));
+	UIManager.put("ScrollBar.thumb", new ColorUIResource(getColor("coloring.scrollbar_foreground", false)));
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/DebugStream.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/DebugStream.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/DebugStream.java	(revision 13928)
@@ -0,0 +1,120 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2004 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer;
+
+
+import java.io.*;
+import java.util.*;
+
+
+public class DebugStream
+{
+    static private boolean debugging_enabled = false;
+    static private PrintStream debug_stream = null;
+
+
+    static public void closeDebugStream()
+    {
+	if (debug_stream != null) {
+	    try {
+		debug_stream.flush();
+		debug_stream.close();
+	    }
+	    catch (Exception exception) {
+		exception.printStackTrace();
+	    }
+	}
+    }
+
+
+    static public void enableDebugging()
+    {
+	debugging_enabled = true;
+    }
+
+
+    static public boolean isDebuggingEnabled()
+    {
+	return debugging_enabled;
+    }
+
+
+    static synchronized public void print(Properties properties)
+    {
+	if (debugging_enabled) {
+	    if (debug_stream != null) {
+		properties.list(debug_stream);
+	    }
+	    properties.list(System.err);
+	}
+    }
+
+
+    /** Print a message to the debug stream. */
+    static synchronized public void print(String message)
+    {
+	if (debugging_enabled) {
+	    if (debug_stream != null) {
+		debug_stream.print(message);
+	    }
+	    System.err.print(message);
+	}
+    }
+
+
+    /** Print a message to the debug stream. */
+    static synchronized public void println(String message)
+    {
+	if (debugging_enabled) {
+	    if (debug_stream != null) {
+		debug_stream.println(message);
+	    }
+	    System.err.println(message);
+	}
+    }
+
+
+    /** Print a stack trace to the debug stream, and always to STDERR. */
+    static synchronized public void printStackTrace(Exception exception)
+    {
+	if (debugging_enabled && debug_stream != null) {
+	    exception.printStackTrace(debug_stream);
+	}
+	exception.printStackTrace();
+    }
+
+
+    static public void setDebugFile(String debug_file_path)
+    {
+	try {
+	    debug_stream = new PrintStream(new FileOutputStream(debug_file_path));
+	}
+	catch (Exception exception) {
+	    exception.printStackTrace();
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/Dictionary.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/Dictionary.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/Dictionary.java	(revision 13928)
@@ -0,0 +1,195 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer;
+
+import javax.swing.plaf.FontUIResource;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+
+/** Extends the ResourceBundle class to allow for the automatic insertion of arguments.<BR>
+ * <BR>
+ * Property files usable by this class have the Backus-Naur form: <BR>
+ * <BR>
+ * FileLine ::= Comment | Mapping <BR>
+ * Comment  ::= '#' SString <BR>
+ * Mapping  ::= NZString ':' SString ( Argument SString )* <BR>
+ * NZString ::= ( Char | Int ) SString <BR>
+ * Argument ::= '{' Int '}' <BR>
+ * SString  ::= String . ['"','#',...] -> ['\"','\#',...] <BR>
+ * <BR>
+ * In order to add a new dictionary Locale, simply copy the existing dictionary.properties files, replace the values (Strings after the ':') with the new language specific ones being careful to maintain formatting and Gatherer placed arguments, then save the new dictionary as: <br>
+ * <BR>
+ * dictionary_<I>locale</I>.properties<BR>
+ * <BR>
+ * where locale is made of two two-letter codes seperated by an underscore. The first code is in lower-case and defines the language. The second is in upper-case and defines the country. For example the default dictionary could also correctly be called:
+ * <BR>
+ * dictionary_en_NZ.properties<BR>
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class Dictionary
+    extends HashMap {
+
+    /** The font used when displaying various html text. */
+    static private FontUIResource font = null;
+    /** A reference to remind us of the current locale. */
+    static private Locale locale = null;
+    /** The ResourceBundle which contains the raw key-value mappings.
+	Loaded from a file named "dictionary<I>locale</I>.properties. */
+    static private ResourceBundle dictionary = null;
+
+
+    public Dictionary(Locale locale, FontUIResource font)
+    {
+	super();
+
+	// Initialize
+	this.font = font;
+	this.locale = ((locale == null) ? Locale.getDefault() : locale);
+	this.dictionary = ResourceBundle.getBundle("dictionary", this.locale);
+    }
+
+
+    /** Retrieve the two letter code of the current language we are using, according to the stored locale.
+     * @return A <strong>String</strong> containing the two letter ISO639 language code.
+     */
+    static public String getLanguage()
+    {
+	return locale.getLanguage();
+    }
+
+
+    static public String get(String key)
+    {
+	return get(key, (String[]) null);
+    }
+
+
+    static public String get(String key, String arg)
+    {
+	String[] args = new String[1];
+	args[0] = arg;
+	return get(key, args);
+    }
+
+
+    /** Used to retrieve a property value from the Locale specific ResourceBundle, based upon the key and arguments supplied. If the key cannot be found or if some other part of the call fails a default (English) error message is returned. <BR>
+     * Here the get recieves a second argument which is an array of Strings used to populate argument fields, denoted {<I>n</I>}, within the value String returned.
+     * @param key A <strong>String</strong> which is mapped to a initial String within the ResourceBundle.
+     * @param args A <strong>String[]</strong> used to populate argument fields within the complete String.
+     * @return A <strong>String</strong> which has been referenced by the key String and that either contains no argument fields, or has had the argument fields automatiically populated with formatting Strings of with argument String provided in the get call.
+     */
+    static public String get(String key, String[] args)
+    {
+	try {
+	    String initial_raw = dictionary.getString(key);
+
+	    // Convert into Unicode
+	    String initial = "";
+	    try {
+		// This "ISO-8859-1" looks out of place, but it is very important.
+		// It is essential to call getBytes with an 8-bit encoding, otherwise
+		// Java kindly deems some characters "undisplayable", and replaces
+		// them with question marks. This is NOT good.
+		initial = new String(initial_raw.getBytes("ISO-8859-1"), "UTF-8");
+	    }
+	    catch (Exception exception) {
+		DebugStream.printStackTrace(exception);
+		return initial_raw;
+	    }
+
+	    // Remove any comments from the string
+	    if (initial.indexOf("#") != -1) {
+		initial = initial.substring(0, initial.indexOf("#"));
+	    }
+
+	    // If the string contains arguments we have to insert them.
+	    StringBuffer complete = new StringBuffer();
+
+	    // While we still have initial string left.
+	    while (initial.length() > 0 && initial.indexOf('{') != -1 && initial.indexOf('}') != -1) {
+		// Remove preamble
+		int opening = initial.indexOf('{');
+		int closing = initial.indexOf('}');
+		int comment_mark = initial.indexOf('-', opening); // May not exist
+		if (comment_mark > closing) { // May also be detecting a later comment
+		    comment_mark = -1;
+		}
+		complete.append(initial.substring(0, opening));
+		
+		// Parse arg_num
+		String arg_str = null;
+		if (comment_mark != -1) {
+		    arg_str = initial.substring(opening + 1, comment_mark);
+		}
+		else {
+		    arg_str = initial.substring(opening + 1, closing);
+		}
+
+		if (closing + 1 < initial.length()) {
+		    initial = initial.substring(closing + 1);
+		}
+		else {
+		    initial = "";
+		}
+
+		// Insert argument
+		if (arg_str.equals("FONT")) {
+		    complete.append((font != null ? font.getFontName() : "Arial"));
+		}
+		else {
+		    int arg_num = Integer.parseInt(arg_str);
+		    if (args != null && 0 <= arg_num && arg_num < args.length) {
+			complete.append(args[arg_num]);
+		    }
+		}
+	    }
+	    complete.append(initial);
+	    
+	    return complete.toString();
+	}
+	catch (Exception exception) {
+	    System.err.println("Missing value for key: " + key);
+	    // DebugStream.printStackTrace(e);
+	    return key;
+	}
+    }
+
+}
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/GAuthenticator.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/GAuthenticator.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/GAuthenticator.java	(revision 13928)
@@ -0,0 +1,182 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */ 
+package org.greenstone.gatherer;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.net.*;
+import java.util.*;
+import javax.swing.*;
+import org.greenstone.gatherer.gui.GLIButton;
+
+/** Provides a graphic authenticator for network password requests.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class GAuthenticator
+    extends Authenticator
+{
+    static public Hashtable authentications = new Hashtable();
+
+    /** Indicates if this authentication prompt been cancelled, and if so rolls-back authentication. */
+    private boolean authentication_cancelled = false;
+    /** The button used to cancel a prompt. */
+    private JButton cancel_button = null;
+    /** The button used to submit the login/password. */
+    private JButton ok_button = null;
+    /** A reference to the dialog prompt created so inner classes can dispose of it. */
+    private JDialog dialog = null;
+    /** The password is a special starred out password field. */
+    private JPasswordField password = null;
+    /** The default size of this dialog. */
+    static final private Dimension SIZE = new Dimension(410,140);
+
+    /** Constructor. */
+    public GAuthenticator() {
+    }
+
+    /** Prompt the user for authentication using a pretty dialog box.
+     * @return A <strong>PasswordAuthentication</strong> object containing the login and password valuees the user has submitted.
+     * @see org.greenstone.gatherer.GAuthenticator.AuthenticationActionListener
+     * @see org.greenstone.gatherer.GAuthenticator.RequestFocusListener
+     */
+    protected PasswordAuthentication getPasswordAuthentication() {
+	// Component definition.
+	dialog = new JDialog (Gatherer.g_man, Dictionary.get("GAuthenticator.Title"), true);
+	dialog.setModal(true);
+	dialog.setSize(SIZE);
+	JPanel content_pane = (JPanel) dialog.getContentPane();
+	JLabel title_label = new JLabel(getMessageString());
+	JPanel user_panel = new JPanel();
+	JLabel username_label = new JLabel(Dictionary.get("GAuthenticator.Username"));
+	JTextField username = new JTextField();
+	username.setToolTipText(Dictionary.get("GAuthenticator.Username_Tooltip"));
+	JPanel password_panel = new JPanel();
+	JLabel password_label = new JLabel(Dictionary.get("GAuthenticator.Password"));
+	password = new JPasswordField();
+	password.setEchoChar('*');
+	password.setToolTipText(Dictionary.get("GAuthenticator.Password_Tooltip"));
+	JPanel button_panel = new JPanel();
+	ok_button = new GLIButton(Dictionary.get("General.OK"), Dictionary.get("General.OK_Tooltip"));
+	cancel_button = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("General.Cancel_Tooltip"));
+	
+	// Connection
+	cancel_button.addActionListener(new AuthenticationActionListener(true));
+	ok_button.addActionListener(new AuthenticationActionListener(false));
+	password.addActionListener(new AuthenticationActionListener(false));
+	username.addActionListener(new RequestFocusListener(password));
+
+	// Layout
+	user_panel.setLayout(new GridLayout(1,2));
+	user_panel.add(username_label);
+	user_panel.add(username);
+
+	password_panel.setLayout(new GridLayout(1,2));
+	password_panel.add(password_label);
+	password_panel.add(password);
+
+	button_panel.setLayout(new GridLayout(1,2));
+	button_panel.add(ok_button);
+	button_panel.add(cancel_button);
+
+	content_pane.setLayout(new GridLayout(4,1,0,2));
+	content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	content_pane.add(title_label);
+	content_pane.add(user_panel);
+	content_pane.add(password_panel);
+	content_pane.add(button_panel);
+
+	// Position the window
+	Dimension screen_size = Toolkit.getDefaultToolkit().getScreenSize();
+	dialog.setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+	dialog.setVisible(true);
+	if(!authentication_cancelled) {
+	    // Store the authentication
+	    authentications.put(getRequestingHost() + ":" + getRequestingPort(), username.getText() + "@" + new String(password.getPassword()));
+	    return new PasswordAuthentication(username.getText(), password.getPassword());
+	} else {
+	    return null;
+	}
+    }
+
+
+    /** This is defined so it can be overridden by subclasses (getRequestingPrompt is final). */
+    protected String getMessageString()
+    {
+	return getRequestingPrompt();
+    }
+
+
+    /** Detects actions upon any control that attempt to submit the current details for authentication. */
+    private class AuthenticationActionListener
+	implements ActionListener {
+	/** <i>true</i> if this authentication action cancels the authentication, <i>false</i> otherwise. */
+	private boolean cancel_action = false;
+	/** Constructor.
+	 * @param cancel_action <i>true</i> if this authentication action cancels the authentication, <i>false</i> otherwise.
+	 */
+	public AuthenticationActionListener(boolean cancel_action) {
+	    this.cancel_action = cancel_action;
+	}
+	/** Any implementation of an ActionListener must include this method so that we can be informed when an action has been performed on our registered controls, allowing us to dispose of the authentication dialog after determining if this is a submit action or a cancel one.
+	 * @param event An <strong>ActionEvent</strong> with information about the event that fired this method.
+	 */
+	public void actionPerformed(ActionEvent event) {
+	    authentication_cancelled = cancel_action;
+	    dialog.dispose();
+	}
+    }
+
+    /** This listener detects actions on registered controls, and when they occur ensures the focus is moved to some targetted component. */
+    private class RequestFocusListener
+	implements ActionListener {
+	/*The <strong>Component</strong> you wish to gain focus when an action is performed on a registered control. */
+	private Component target = null;
+	/** Constructor.
+	 * @param target The <strong>Component</strong> you wish to gain focus when an action is performed on a registered control.
+	 */
+	public RequestFocusListener(Component target) {
+	    this.target = target;
+	}
+	/** Any implementation of an ActionListener must include this method so that we can be informed when an action has been performed on our registered controls, allowing us to request focus in the target control.
+	 * @param event An <strong>ActionEvent</strong> with information about the event that fired this method.
+	 */
+	public void actionPerformed(ActionEvent event) {
+	    target.requestFocus();
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/Gatherer.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/Gatherer.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/Gatherer.java	(revision 13928)
@@ -0,0 +1,1012 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.lang.*;
+import java.net.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.plaf.*;
+import javax.swing.text.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.GAuthenticator;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.feedback.ActionRecorderDialog;
+import org.greenstone.gatherer.file.FileManager;
+import org.greenstone.gatherer.file.FileAssociationManager;
+import org.greenstone.gatherer.file.RecycleBin;
+import org.greenstone.gatherer.greenstone.Classifiers;
+import org.greenstone.gatherer.greenstone.LocalGreenstone;
+import org.greenstone.gatherer.greenstone.LocalLibraryServer;
+import org.greenstone.gatherer.greenstone.Plugins;
+import org.greenstone.gatherer.greenstone3.ServletConfiguration;
+import org.greenstone.gatherer.gui.GUIManager;
+import org.greenstone.gatherer.gui.URLField;
+import org.greenstone.gatherer.gui.WarningDialog;
+import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
+import org.greenstone.gatherer.util.JarTools;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+
+
+/** Containing the top-level "core" for the Gatherer, this class is the
+ * common core for the GLI application and applet. It first parses the
+ * command line arguments, preparing to update the configuration as
+ * required. Next it loads several important support classes such as the
+ * Configuration and Dictionary. Finally it creates the other important
+ * managers and sends them on their way.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class Gatherer
+{
+    /** The name of the GLI. */
+    static final public String PROGRAM_NAME = "Greenstone Librarian Interface";
+    /** The current version of the GLI. */
+    static final public String PROGRAM_VERSION = "v2.72";
+
+    static private Dimension size = new Dimension(800, 540);
+
+    /** Has the exit flag been set? */
+    static final public int EXIT_THEN_RESTART= 2;
+    static public boolean exit = false;
+    static public int exit_status = 0;
+
+    static private String gli_directory_path = null;
+    static private String gli_user_directory_path = null;
+
+    static public String client_operating_system = null;
+
+    /** All of the external applications that must exit before we close the Gatherer. */
+    static private Vector apps = new Vector();
+    static private String non_standard_collect_directory_path = null;
+    static public String open_collection_file_path = null;
+    /** A public reference to the FileAssociationManager. */
+    static public FileAssociationManager assoc_man;
+    /** A public reference to the CollectionManager. */
+    static public CollectionManager c_man;
+    /** A public reference to the RecycleBin. */
+    static public RecycleBin recycle_bin;
+    /** a reference to the Servlet Configuration is GS3 */
+    static public ServletConfiguration servlet_config;
+    /** A public reference to the FileManager. */
+    static public FileManager f_man;
+    /** A public reference to the GUIManager. */
+    static public GUIManager g_man = null;
+    static private boolean g_man_built = false;
+
+    /** We are using the GLI for GS3 */
+    static public boolean GS3 = false;
+
+    static public boolean isApplet = false;
+    static public boolean isGsdlRemote = false;
+
+    // feedback stuff
+    /** is the feedback feature enabled? */
+    static public boolean feedback_enabled = true;
+    /** the action recorder dialog */
+    static public ActionRecorderDialog feedback_dialog = null;
+
+    // Refresh reasons
+    static public final int COLLECTION_OPENED   = 0;
+    static public final int COLLECTION_CLOSED   = 1;
+    static public final int COLLECTION_REBUILT  = 2;
+    static public final int PREFERENCES_CHANGED = 3;
+
+   //////kk added////////  
+    static public String cgiBase="";
+    /////////////////
+
+    /** Magic to allow Enter to fire the default button. */
+    static {
+      KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
+      Keymap map = JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP);
+      map.removeKeyStrokeBinding(enter);
+    }
+
+
+    public Gatherer(String[] args) 
+    {
+	// Display the version to make error reports a lot more useful
+	System.err.println("Version: " + PROGRAM_VERSION + "\n");
+
+	JarTools.initialise(this); 
+
+	GetOpt go = new GetOpt(args);
+
+	// Remember the GSDLOS value
+	client_operating_system = go.client_operating_system;
+
+	// If feedback is enabled, set up the recorder dialog
+	if (go.feedback_enabled) {
+	    // Use the default locale for now - this will be changed by the Gatherer run method
+	    feedback_enabled = true;
+	    feedback_dialog = new ActionRecorderDialog(Locale.getDefault());
+	}
+
+	// Are we using a remote Greenstone?
+	if (go.use_remote_greenstone) {
+	    isGsdlRemote = true;
+
+	    // We don't have a local Greenstone!
+	    go.gsdl_path = null;
+
+	    // We have to use our own collect directory since we can't use the Greenstone one
+	    setCollectDirectoryPath(getGLIUserDirectoryPath() + "collect" + File.separator);
+	}
+	// No, we have a local Greenstone
+	else {
+	    LocalGreenstone.setDirectoryPath(go.gsdl_path);
+	}
+
+	// Users may specify a non-standard collect directory (eg. when running one GLI in a network environment)
+	if (go.collect_directory_path != null) {
+	    setCollectDirectoryPath(go.collect_directory_path);
+	}
+
+	// More special code for running with a remote Greenstone
+	if (isGsdlRemote) {
+	    Configuration.TEMPLATE_CONFIG_XML = "xml/configRemote.xml";
+	    Configuration.CONFIG_XML = "configRemote.xml";
+	    Configuration.GS3_CONFIG_XML = "config3Remote.xml";
+
+	    File collect_directory = new File(Gatherer.getCollectDirectoryPath());
+	    if (!collect_directory.exists() && !collect_directory.mkdir()) {
+		System.err.println("Warning: Unable to make directory: " + collect_directory);
+	    }
+	}
+
+	init(go.gsdl_path, go.gsdl3_path, go.gsdl3_src_path, go.local_library_path, go.library_url_string, 
+	     go.gliserver_url_string, go.debug, go.perl_path, go.no_load, go.filename, go.site_name,
+	     go.servlet_path);
+    }
+
+
+    public void init(String gsdl_path, String gsdl3_path, String gsdl3_src_path, String local_library_path,
+		     String library_url_string, String gliserver_url_string, boolean debug_enabled,
+		     String perl_path, boolean no_load, String open_collection, 
+		     String site_name, String servlet_path) 
+    {
+	if (gsdl3_path != null && !gsdl3_path.equals("")) {
+	    this.GS3 = true;
+	} else {
+	    gsdl3_path = null;
+	    gsdl3_src_path = null;
+	}
+
+	// Create the debug stream if required
+	if (debug_enabled) {
+	    DebugStream.enableDebugging();
+
+	    Calendar now = Calendar.getInstance();
+	    String debug_file_path = "debug" + now.get(Calendar.DATE) + "-" + now.get(Calendar.MONTH) + "-" + now.get(Calendar.YEAR) + ".txt";
+
+	    // Debug file is created in the user's GLI directory
+	    debug_file_path = getGLIUserDirectoryPath() + debug_file_path;
+	    DebugStream.println("Debug file path: " + debug_file_path);
+	    DebugStream.setDebugFile(debug_file_path);
+	    DebugStream.print(System.getProperties());
+	}
+
+	// Delete plugins.dat and classifiers.dat files from previous versions of the GLI (no longer used)
+	File plugins_dat_file = new File(Gatherer.getGLIUserDirectoryPath() + "plugins.dat");
+	if (plugins_dat_file.exists()) {
+	    System.err.println("Deleting plugins.dat file...");
+	    Utility.delete(plugins_dat_file);
+	}
+	File classifiers_dat_file = new File(Gatherer.getGLIUserDirectoryPath() + "classifiers.dat");
+	if (classifiers_dat_file.exists()) {
+	    System.err.println("Deleting classifiers.dat file...");
+	    Utility.delete(classifiers_dat_file);
+	}
+
+	try {
+	    // Load GLI config file
+	    new Configuration(getGLIUserDirectoryPath(), gsdl_path, gsdl3_path, gsdl3_src_path, site_name);
+
+	    if (GS3) {
+		// Load Greenstone 3 servlet configuration
+		servlet_config = new ServletConfiguration(gsdl3_path);
+	    }
+
+	    // Check we know where Perl is
+	    Configuration.perl_path = perl_path;
+	    if (isGsdlRemote && Utility.isWindows() && Configuration.perl_path != null) {
+		if (Configuration.perl_path.toLowerCase().endsWith("perl.exe")) {
+		    Configuration.perl_path = Configuration.perl_path.substring(0, Configuration.perl_path.length() - "perl.exe".length());
+		}
+		if (Configuration.perl_path.endsWith(File.separator)) {
+		    Configuration.perl_path = Configuration.perl_path.substring(0, Configuration.perl_path.length() - File.separator.length());
+		}
+	    }
+
+	    if (GS3 && Configuration.servlet_path == null) {
+		Configuration.servlet_path = servlet_config.getServletPath(Configuration.site_name);
+	    }
+
+	    // the feedback dialog has been loaded with a default locale, 
+	    // now set the user specified one
+	    if (feedback_enabled && feedback_dialog != null) {
+		feedback_dialog.setLocale(Configuration.getLocale("general.locale", true));
+	    }
+
+	    // Read Dictionary
+	    new Dictionary(Configuration.getLocale("general.locale", true), Configuration.getFont("general.font", true));
+
+	    // check that we are using Sun Java
+	    String java_vendor = System.getProperty("java.vendor");
+	    if (!java_vendor.equals("Sun Microsystems Inc.")) {
+		System.err.println(Dictionary.get("General.NotSunJava", java_vendor));
+	    }
+
+	    // Unless we're using remote building, we need to know where the local Greenstone is
+	    if (!isGsdlRemote && gsdl_path == null) {
+		missingGSDL();
+	    }
+
+	    // Start up the local library server, if that's what we want
+	    if (Utility.isWindows() && local_library_path != null && !isGsdlRemote && !GS3) {
+		LocalLibraryServer.start(gsdl_path, local_library_path);
+	    }
+
+	    // The "-library_url" option overwrites anything in the config files
+	    if (library_url_string != null && library_url_string.length() > 0) {
+		try {
+		    System.err.println("Setting library_url to " + library_url_string + "...");
+		    Configuration.library_url = new URL(library_url_string);
+		}
+		catch (MalformedURLException error) {
+		    DebugStream.printStackTrace(error);
+		}
+	    }
+
+	    // Check that we now know the Greenstone library URL, since we need this for previewing collections
+	    DebugStream.println("Configuration.library_url = " + Configuration.library_url);
+	    if (Configuration.library_url == null) {
+		missingEXEC();
+	    }
+
+	    // The "-gliserver_url" option overwrites anything in the config files
+	    if (gliserver_url_string != null && gliserver_url_string.length() > 0) {
+		try {
+		    System.err.println("Setting gliserver_url to " + gliserver_url_string + "...");
+		    Configuration.gliserver_url = new URL(gliserver_url_string);
+		}
+		catch (MalformedURLException error) {
+		    DebugStream.printStackTrace(error);
+		}
+	    }
+
+	    // If we're using a remote Greenstone we need to know where the gliserver script is
+	    DebugStream.println("Configuration.gliserver_url = " + Configuration.gliserver_url);
+	    if (isGsdlRemote) {
+		if (Configuration.gliserver_url == null) {
+		    missingGLIServer();
+		}
+		if (Configuration.gliserver_url != null) {
+		    gliserver_url_string = Configuration.gliserver_url.toString();
+		}
+	    }
+
+	    // Check for ImageMagick
+	    if (Gatherer.isGsdlRemote) {
+		DebugStream.println("Not checking for ImageMagick.");
+	    }
+	    else if (!(new ImageMagickTest()).found()) {
+		// Time for a warning message
+		missingImageMagick();
+	    }
+
+	    if (Gatherer.isGsdlRemote) {
+		DebugStream.println("Not checking for perl path/exe");
+	    }
+	    else {
+		// Perl path is a little different as it is perfectly ok to
+		// start the GLI without providing a perl path
+		boolean found_perl = false;
+		if (Configuration.perl_path != null) {
+		    // See if the file pointed to actually exists
+		    File perl_file = new File(Configuration.perl_path);
+		    found_perl = perl_file.exists();
+		    perl_file = null;
+		}
+		if (Configuration.perl_path == null || !found_perl) {
+		    // Run test to see if we can run perl as is.
+		    PerlTest perl_test = new PerlTest();
+		    if (perl_test.found()) {
+			// If so replace the perl path with the system
+			// default (or null for unix).
+			Configuration.perl_path = perl_test.toString();
+			found_perl = true;
+		    }
+		}
+		if (!found_perl) {
+		    // Time for an error message.
+		    missingPERL();
+		}
+	    }
+
+	    // Set the default font for all Swing components.
+	    FontUIResource default_font = Configuration.getFont("general.font", true);
+	    Enumeration keys = UIManager.getDefaults().keys();
+	    while (keys.hasMoreElements()) {
+		Object key = keys.nextElement();
+		Object value = UIManager.get(key);
+		if (value instanceof FontUIResource) {
+		    UIManager.put(key, default_font);
+		}
+	    }
+
+	    // Set up proxy
+	    setProxy();
+	    // Now we set up an Authenticator
+	    Authenticator.setDefault(new GAuthenticator());
+
+	    assoc_man = new FileAssociationManager();
+	    // Create File Manager
+	    f_man = new FileManager();
+	    // Create Collection Manager
+	    c_man = new CollectionManager();
+	    // Create Recycle Bin
+	    recycle_bin = new RecycleBin();
+
+	    if (GS3) {
+		if (site_name==null) {
+		    site_name = Configuration.site_name;
+		    servlet_path = null; // need to reset this
+		}
+		if (servlet_path == null) {
+		    servlet_path = Configuration.getServletPath();
+		}
+	    }
+
+	    open_collection_file_path = open_collection;
+	    if (open_collection_file_path == null) {
+		open_collection_file_path = Configuration.getString("general.open_collection", true);
+	    }
+	    if (no_load || open_collection_file_path.equals("")) {
+		open_collection_file_path = null;
+	    }
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+
+	// Create GUI Manager (last) or else suffer the death of a thousand NPE's
+	g_man = new GUIManager(size);
+    }
+
+
+    public void openGUI()
+    {
+	// Size and place the frame on the screen
+	Rectangle bounds = Configuration.getBounds("general.bounds", true);
+	if (bounds == null) {
+	    // Choose a sensible default value
+	    bounds = new Rectangle(0, 0, 640, 480);
+	}
+	
+	// Ensure width and height are reasonable
+	size = bounds.getSize();
+	if (size.width < 640) {
+	    size.width = 640;
+	}
+	else if (size.width > Configuration.screen_size.width && Configuration.screen_size.width > 0) {
+	    size.width = Configuration.screen_size.width;
+	}
+	if (size.height < 480) {
+	    size.height = 480;
+	}
+	else if (size.height > Configuration.screen_size.height && Configuration.screen_size.height > 0) {
+	    size.height = Configuration.screen_size.height;
+	}
+
+	if (!g_man_built) {
+
+	    g_man.display();
+
+	    // Place the window in the desired location on the screen, if this is do-able (not under most linux window managers apparently. In fact you're lucky if they listen to any of your screen size requests).
+	    g_man.setLocation(bounds.x, bounds.y);
+	    g_man.setVisible(true);
+
+	    // After the window has been made visible, check that it is in the correct place
+	    // sometimes java places a window not in the correct place, 
+	    // but with an offset. If so, we work out what the offset is
+	    // and change the desired location to take that into account 
+	    Point location = g_man.getLocation();
+	    int x_offset = bounds.x - location.x;
+	    int y_offset = bounds.y - location.y;
+	    // If not, offset the window to move it into the correct location
+	    if (x_offset > 0 || y_offset > 0) {
+		///ystem.err.println("changing the location to "+(bounds.x + x_offset)+" "+ (bounds.y + y_offset));
+		g_man.setLocation(bounds.x + x_offset, bounds.y + y_offset);
+	    }
+
+	    // The 'after-display' triggers several events which don't occur until after the visual components are actually available on screen. Examples of these would be the various html renderings, as they can't happen offscreen.
+	    g_man.afterDisplay();
+	    g_man_built = true;
+	}
+	else {
+	    g_man.setVisible(true);
+	}
+
+	// Get a list of the core Greenstone classifiers and plugins
+	Classifiers.loadClassifiersList(null);
+	Plugins.loadPluginsList(null);
+
+	// If using a remote Greenstone we need to download the collection configurations now
+	if (Gatherer.isGsdlRemote) {
+	    if (RemoteGreenstoneServer.downloadCollectionConfigurations().equals("")) {
+		// !! Something went wrong downloading the collection configurations
+		System.err.println("Error: Could not download collection configurations.");
+		System.exit(0);
+	    }
+	}
+
+	// If there was a collection left open last time, reopen it
+	c_man.openCollectionFromLastTime();
+    }
+
+
+    /** Exits the Gatherer after ensuring that things needing saving are saved.
+     * @see java.io.FileOutputStream
+     * @see java.io.PrintStream
+     * @see java.lang.Exception
+     * @see javax.swing.JOptionPane
+     * @see org.greenstone.gatherer.Configuration
+     * @see org.greenstone.gatherer.collection.CollectionManager
+     * @see org.greenstone.gatherer.gui.GUIManager
+     */
+    static public void exit(int new_exit_status)
+    {
+	DebugStream.println("In Gatherer.exit()...");
+	exit = true;
+	if (new_exit_status != 0) {
+	    // default exit_status is already 0 
+	    // only remember a new exit status if it is non-trivial
+	    exit_status = new_exit_status;
+	}
+
+	// Save the file associations
+	if (assoc_man != null) {
+	    assoc_man.save();
+	    assoc_man = null;
+	}
+
+	// Get the gui to deallocate
+	g_man.destroy();
+	g_man_built = false;
+
+	// Flush debug
+	DebugStream.closeDebugStream();
+
+	// If we started a server, we should try to stop it.
+	if (LocalLibraryServer.isRunning() == true) {
+	    LocalLibraryServer.stop();
+	}
+
+	// If we're using a remote Greenstone server we need to make sure that all jobs have completed first
+	if (isGsdlRemote) {
+	    RemoteGreenstoneServer.exit();
+	}
+
+	// Make sure we haven't started up any processes that are still running
+	if (apps.size() == 0) {
+	    // If we're running as an applet we don't actually quit (just hide the main GLI window)
+	    if (!Gatherer.isApplet) {
+		// This is the end...
+		System.exit(exit_status);
+	    }
+	}
+	else {
+	    JOptionPane.showMessageDialog(g_man, Dictionary.get("General.Outstanding_Processes"), Dictionary.get("General.Outstanding_Processes_Title"), JOptionPane.ERROR_MESSAGE);
+	    g_man.setVisible(false);
+	}
+    }
+
+    static public void exit()
+    {
+	exit(0);
+    }
+
+    /** Returns the path of the Greenstone "collect" directory. */
+    static public String getCollectDirectoryPath()
+    {
+	if (non_standard_collect_directory_path != null) {
+	    return non_standard_collect_directory_path;
+	}
+
+	if (!GS3) {
+	    return Configuration.gsdl_path + "collect" + File.separator;
+	}
+	else {
+	    return getSitesDirectoryPath() + Configuration.site_name + File.separator + "collect" + File.separator;
+	}
+    }
+
+
+    /** Returns the path of the GLI directory. */
+    static public String getGLIDirectoryPath()
+    {
+	return gli_directory_path;
+    }
+
+
+    /** Returns the path of the GLI "metadata" directory. */
+    static public String getGLIMetadataDirectoryPath()
+    {
+	return getGLIDirectoryPath() + "metadata" + File.separator;
+    }
+
+
+    /** Returns the path of the GLI user directory. */
+    static public String getGLIUserDirectoryPath()
+    {
+	return gli_user_directory_path;
+    }
+
+
+    /** Returns the path of the GLI user "cache" directory. */
+    static public String getGLIUserCacheDirectoryPath()
+    {
+	return getGLIUserDirectoryPath() + "cache" + File.separator;
+    }
+
+
+    /** Returns the path of the GLI user "log" directory. */
+    static public String getGLIUserLogDirectoryPath()
+    {
+	return getGLIUserDirectoryPath() + "log" + File.separator;
+    }
+
+
+    static public String getSitesDirectoryPath()
+    {
+	return Configuration.gsdl3_path + "sites" + File.separator;
+    }
+
+
+    static public void setCollectDirectoryPath(String collect_directory_path)
+    {
+	non_standard_collect_directory_path = collect_directory_path;
+	if (!non_standard_collect_directory_path.endsWith(File.separator)) {
+	    non_standard_collect_directory_path = non_standard_collect_directory_path + File.separator;
+	}
+    }
+
+
+    static public void setGLIDirectoryPath(String gli_directory_path_arg)
+    {
+	gli_directory_path = gli_directory_path_arg;
+    }
+
+
+    static public void setGLIUserDirectoryPath(String gli_user_directory_path_arg)
+    {
+	gli_user_directory_path = gli_user_directory_path_arg;
+
+	// Ensure the GLI user directory exists
+	File gli_user_directory = new File(gli_user_directory_path);
+	if (!gli_user_directory.exists() && !gli_user_directory.mkdirs()) {
+	    System.err.println("Error: Unable to make directory: " + gli_user_directory);
+	}
+    }
+
+
+    static public void refresh(int refresh_reason)
+    {
+	if (g_man != null) {
+	    g_man.refresh(refresh_reason, c_man.ready());
+	}
+
+	// Now is a good time to force a garbage collect
+	System.gc();
+    }
+
+
+    // used to send reload coll messages to the tomcat server
+    static public void configGS3Server(String site, String command) {
+	if (Configuration.library_url == null){
+	    System.out.println("Error: you have not provide the Greenstone Library address.");  
+           return;
+
+	} 
+          
+	try {
+	    // need to add the servlet name to the exec address
+	    String raw_url = Configuration.library_url.toString() + Configuration.getServletPath() + command;
+	    URL url = new URL(raw_url);
+	    DebugStream.println("Action: " + raw_url);
+	    HttpURLConnection library_connection = (HttpURLConnection) url.openConnection();
+	    int response_code = library_connection.getResponseCode();
+	    if(HttpURLConnection.HTTP_OK <= response_code && response_code < HttpURLConnection.HTTP_MULT_CHOICE) {
+		DebugStream.println("200 - Complete.");
+	    }
+	    else {
+		DebugStream.println("404 - Failed.");
+	    }
+	    url = null;
+	}
+	catch (Exception exception) {            
+	    DebugStream.printStackTrace(exception);
+	}
+    }
+
+
+    /** Used to 'spawn' a new child application when a file is double clicked.
+     * @param file The file to open 
+     * @see org.greenstone.gatherer.Gatherer.ExternalApplication
+     */
+    static public void spawnApplication(File file) {
+	String [] commands = assoc_man.getCommand(file);
+	if(commands != null) {
+	    ExternalApplication app = new ExternalApplication(commands);
+	    apps.add(app);
+	    app.start();
+	}
+	else {
+	    ///ystem.err.println("No open command available.");
+	}
+    }
+
+
+    static public void spawnApplication(String command)
+    {
+	ExternalApplication app = new ExternalApplication(command);
+	apps.add(app);
+	app.start();
+    }
+
+
+    /** Used to 'spawn' a new  browser application or reset an existing one when the preview button is clicked 
+     * @param url The url to open the browser at
+     * @see org.greenstone.gatherer.Gatherer.BrowserApplication
+     */    
+    static public void spawnBrowser(String url) {
+	String command = assoc_man.getBrowserCommand(url);
+	if (command != null) {
+	    BrowserApplication app = new BrowserApplication(command, url);
+	    apps.add(app);
+	    app.start();
+	}
+	else {
+	    ///ystem.err.println("No browser command available."); 
+	}
+    }
+
+
+    /** Prints a warning message about a missing library path, which means the final collection cannot be previewed in the Gatherer.
+     */
+    static private void missingEXEC() {
+	WarningDialog dialog;
+	if (GS3) {
+	    dialog = new WarningDialog("warning.MissingEXEC_GS3", Dictionary.get("MissingEXEC_GS3.Title"), Dictionary.get("MissingEXEC_GS3.Message"), "general.library_url", false);
+	}
+	else {
+	    dialog = new WarningDialog("warning.MissingEXEC", Dictionary.get("MissingEXEC.Title"), Dictionary.get("MissingEXEC.Message"), "general.library_url", false);
+	}
+	dialog.setValueField(new URLField(Configuration.getColor("coloring.editable_foreground", false), Configuration.getColor("coloring.editable_background", false)));
+	dialog.display();
+	dialog.dispose();
+	dialog = null;
+
+	String library_url_string = Configuration.getString("general.library_url", true);
+	if (!library_url_string.equals("")) {
+	    try {
+		Configuration.library_url = new URL(library_url_string);
+	    }
+	    catch (MalformedURLException exception) {
+		DebugStream.printStackTrace(exception);
+	    }
+	}
+    }
+
+
+    static private void missingGLIServer()
+    {
+	WarningDialog dialog = new WarningDialog("warning.MissingGLIServer", Dictionary.get("MissingGLIServer.Title"), Dictionary.get("MissingGLIServer.Message"), "general.gliserver_url", false);
+	dialog.setValueField(new URLField(Configuration.getColor("coloring.editable_foreground", false), Configuration.getColor("coloring.editable_background", false)));
+	dialog.display();
+	dialog.dispose();
+	dialog = null;
+
+	String gliserver_url_string = Configuration.getString("general.gliserver_url", true);
+	if (!gliserver_url_string.equals("")) {
+	    try {
+		Configuration.gliserver_url = new URL(gliserver_url_string);
+	    }
+	    catch (MalformedURLException exception) {
+		DebugStream.printStackTrace(exception);
+	    }
+	}
+    }
+
+
+    /** Prints a warning message about a missing GSDL path, which although not fatal pretty much ensures nothing will work properly in the GLI.
+     */
+    static private void missingGSDL() {
+	WarningDialog dialog = new WarningDialog("warning.MissingGSDL", Dictionary.get("MissingGSDL.Title"), Dictionary.get("MissingGSDL.Message"), null, false);
+	dialog.display();
+	dialog.dispose();
+	dialog = null;
+    }
+
+    /** Prints a warning message about missing a valid ImageMagick path, which although not fatal means building image collections won't work */
+    static private void missingImageMagick() {
+	WarningDialog dialog = new WarningDialog("warning.MissingImageMagick", Dictionary.get("MissingImageMagick.Title"), Dictionary.get("MissingImageMagick.Message"), null, false);
+	dialog.display();
+	dialog.dispose();
+	dialog = null;
+    }
+
+    /** Prints a warning message about missing a valid PERL path, which although not fatal pretty much ensures no collection creation/building will work properly in the GLI. */
+    static private void missingPERL() {
+	WarningDialog dialog = new WarningDialog("warning.MissingPERL", Dictionary.get("MissingPERL.Title"), Dictionary.get("MissingPERL.Message"), null, false);
+	dialog.display();
+	dialog.dispose();
+	dialog = null;
+    }
+
+
+    /** Sets up the proxy connection by setting JVM Environment flags and creating a new Authenticator.
+     * @see java.lang.Exception
+     * @see java.lang.System
+     * @see java.net.Authenticator
+     * @see org.greenstone.gatherer.Configuration
+     * @see org.greenstone.gatherer.GAuthenticator
+     */
+    static public void setProxy() {
+	try {// Can throw several exceptions
+	    if(Configuration.get("general.use_proxy", true)) {
+		System.setProperty("http.proxyType", "4");
+		System.setProperty("http.proxyHost", Configuration.getString("general.proxy_host", true));
+		System.setProperty("http.proxyPort", Configuration.getString("general.proxy_port", true));
+		System.setProperty("http.proxySet", "true");
+	    } else {
+		System.setProperty("http.proxyHost", "");
+		System.setProperty("http.proxyPort", "");
+		System.setProperty("http.proxySet", "false");
+	    }
+	} catch (Exception error) {
+	    DebugStream.println("Error in Gatherer.initProxy(): " + error);
+	    DebugStream.printStackTrace(error);
+	}
+    }
+
+    
+    /** This private class contains an instance of an external application running within a JVM shell. It is important that this process sits in its own thread, but its more important that when we exit the Gatherer we don't actually System.exit(0) the Gatherer object until the user has volunteerily ended all of these child processes. Otherwise when we quit the Gatherer any changes the users may have made in external programs will be lost and the child processes are automatically deallocated. */
+    static private class ExternalApplication
+	extends Thread {
+	private Process process = null;
+	/** The initial command string given to this sub-process. */
+	private String command = null;
+	private String[] commands = null;
+	/** Constructor.
+	 * @param command The initial command <strong>String</strong>.
+	 */
+	public ExternalApplication(String command) {
+	    this.command = command;
+	}
+
+	public ExternalApplication(String[] commands) {
+	    this.commands = commands;
+	}
+	/** We start the child process inside a new thread so it doesn't block the rest of Gatherer.
+	 * @see java.lang.Exception
+	 * @see java.lang.Process
+	 * @see java.lang.Runtime
+	 * @see java.lang.System
+	 * @see java.util.Vector
+	 */
+	public void run() {
+	    // Call an external process using the args.
+	    try {
+		if(commands != null) {
+		    StringBuffer whole_command = new StringBuffer();
+		    for(int i = 0; i < commands.length; i++) {
+			whole_command.append(commands[i]);
+			whole_command.append(" ");
+		    }
+		    DebugStream.println("Running " + whole_command.toString());
+		    Runtime rt = Runtime.getRuntime();
+		    process = rt.exec(commands);
+		    process.waitFor();
+		}
+		else {
+		    DebugStream.println("Running " + command);
+		    Runtime rt = Runtime.getRuntime();
+		    process = rt.exec(command);
+		    process.waitFor();
+		}
+	    }
+	    catch (Exception exception) {
+		DebugStream.printStackTrace(exception);
+	    }
+	    // Remove ourself from Gatherer list of threads.
+	    apps.remove(this);
+	    // Call exit if we were the last outstanding child process thread.
+	    if (apps.size() == 0 && exit == true) {
+		// In my opinion (DB) there is no need to exit here,
+		// the 'run' method ending naturally brings this
+		// thread to an end.  In fact it is potentially
+		// dangerous to exit here, as the main thread in the
+		// Gatherer class may be stopped prematurely.  As it so
+		// happens the point at which the ExternalApplication thread
+		// is asked to stop (Back in the main Gatherer thread) is after
+		// various configuration files have been saved.
+		// 
+		// A similar argument holds for BrowserApplication thread below.
+		System.exit(exit_status);
+	    }
+	}
+	public void stopExternalApplication() {
+	    if(process != null) {
+		process.destroy();
+	    }
+	}
+    }
+    /** This private class contains an instance of an external application running within a JVM shell. It is important that this process sits in its own thread, but its more important that when we exit the Gatherer we don't actually System.exit(0) the Gatherer object until the user has volunteerily ended all of these child processes. Otherwise when we quit the Gatherer any changes the users may have made in external programs will be lost and the child processes are automatically deallocated. */
+    static private class BrowserApplication
+	extends Thread {
+	private Process process = null;
+	/** The initial command string given to this sub-process. */
+	private String command = null;
+	private String url = null;
+	private String[] commands = null;
+
+	public BrowserApplication(String command, String url) {
+	    StringTokenizer st = new StringTokenizer(command);
+	    int num_tokens = st.countTokens();
+	    this.commands = new String [num_tokens];
+	    int i=0;
+	    while (st.hasMoreTokens()) {
+		commands[i] = st.nextToken();
+		i++;
+	    }
+	    //this.commands = commands;
+	    this.url = url;
+	}
+	/** We start the child process inside a new thread so it doesn't block the rest of Gatherer.
+	 * @see java.lang.Exception
+	 * @see java.lang.Process
+	 * @see java.lang.Runtime
+	 * @see java.lang.System
+	 * @see java.util.Vector
+	 */
+	public void run() {
+	    // Call an external process using the args.
+	    if(commands == null) {
+		apps.remove(this);
+		return;
+	    }
+	    try {
+		String prog_name = commands[0];
+		String lower_name = prog_name.toLowerCase();
+		if (lower_name.indexOf("mozilla") != -1 || lower_name.indexOf("netscape") != -1) { 
+		    DebugStream.println("found mozilla or netscape, trying remote it");
+		    // mozilla and netscape, try using a remote command to get things in the same window
+		    String [] new_commands = new String[] {prog_name, "-raise", "-remote", "openURL("+url+",new-tab)"};
+		    printArray(new_commands);
+
+		    Runtime rt = Runtime.getRuntime();
+		    process = rt.exec(new_commands);
+		    int exitCode = process.waitFor();
+		    if (exitCode != 0) { // if Netscape or mozilla was not open
+			DebugStream.println("couldn't do remote, trying original command");
+			printArray(commands);
+			process = rt.exec(commands); // try the original command
+		    }
+		} else {
+		    // just run what we have been given
+		    StringBuffer whole_command = new StringBuffer();
+		    for(int i = 0; i < commands.length; i++) {
+			whole_command.append(commands[i]);
+			whole_command.append(" ");
+		    }
+		    DebugStream.println("Running " + whole_command.toString());
+		    Runtime rt = Runtime.getRuntime();
+		    process = rt.exec(commands);
+		    process.waitFor();
+		}
+	    }
+	    
+	    catch (Exception exception) {
+		DebugStream.printStackTrace(exception);
+	    }
+	    // Remove ourself from Gatherer list of threads.
+	    apps.remove(this);
+	    // Call exit if we were the last outstanding child process thread.
+	    if (apps.size() == 0 && exit == true) {
+		System.exit(exit_status);
+	    }
+	}
+	public void printArray(String [] array) {
+	    for(int i = 0; i < array.length; i++) {
+		DebugStream.print(array[i]+" ");
+		System.err.println(array[i]+" ");
+	    }
+	}
+	public void stopBrowserApplication() {
+	    if(process != null) {
+		process.destroy();
+	    }
+	}
+    }
+
+
+    private class ImageMagickTest
+    {
+	public boolean found()
+	{
+	    try {
+		String[] command = new String[2];
+		command[0] = (Utility.isWindows() ? "identify.exe" : "identify");
+		command[1] = "-version";
+		Process image_magick_process = Runtime.getRuntime().exec(command);
+		image_magick_process.waitFor();
+		return (image_magick_process.exitValue() == 0);
+	    }
+	    catch (IOException exception) {
+		return false;
+	    }
+	    catch (InterruptedException exception) {
+		return false;
+	    }
+	}
+    }
+
+
+    private class PerlTest
+    {
+	private String[] command = new String[2];
+
+	public PerlTest()
+	{
+	    command[0] = (Utility.isWindows() ? Utility.PERL_EXECUTABLE_WINDOWS : Utility.PERL_EXECUTABLE_UNIX);
+	    command[1] = "-version";
+	}
+
+	public boolean found()
+	{
+	    try {
+		Process perl_process = Runtime.getRuntime().exec(command);
+		perl_process.waitFor();
+		return (perl_process.exitValue() == 0);
+	    }
+	    catch (Exception exception) {
+		return false;
+	    }
+	}
+
+	public String toString() {
+	    return command[0];
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/GathererApplet.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/GathererApplet.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/GathererApplet.java	(revision 13928)
@@ -0,0 +1,205 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+
+package org.greenstone.gatherer;
+
+import java.applet.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.net.*;
+import javax.swing.JApplet;
+
+import java.io.*;
+import javax.swing.*;
+import org.greenstone.gatherer.util.JarTools;
+import org.greenstone.gatherer.util.UnzipTools;
+import org.greenstone.gatherer.util.Utility;
+
+
+public class GathererApplet extends JApplet implements ActionListener
+{
+    private Gatherer gatherer = null;
+
+
+    protected String fullLibraryURL(String address) 
+    {
+	String full_address = "";
+
+        // make sure the URL has protocol, host, and file
+        if (address.startsWith("http:")) {
+            // the address has all the necessary components
+	    full_address = address;
+        } 
+	else if (address.startsWith("/")) {
+            // there is not protocol and host
+            URL document = getDocumentBase();
+	    int port_no = document.getPort();
+
+            String port = (port_no>0) ? ":" + port_no : "";
+            full_address = "http://" + document.getHost() + port  + address;
+	}
+
+	return full_address;
+    }
+
+
+    /* This is the entry point for the GLI applet */
+    public void init()
+    {
+	JarTools.initialise(this); 
+
+	// Check if the user has agreed to the requested security settings
+	try {
+	    // Work-around to reduce number of 
+	    // 'Could not lock user prefs' error messages.
+	    // Thanks to Walter Schatz from the java forums.
+	    System.setProperty("java.util.prefs.syncInterval","2000000");
+	}
+	catch (Exception exception) {
+	    getContentPane().add(new JLabel("Greenstone Librarian Interface Applet deactivated", JLabel.CENTER));
+	    return;
+	}
+
+	// Ensure platform specific LAF
+	try {
+	    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+	}
+	catch (Exception exception) {
+	    exception.printStackTrace();
+	}
+
+	// Determine the GLI user directory path
+	String gli_user_directory_path = System.getProperty("user.home") + File.separator;
+        if (Utility.isWindows()) {
+	    String windows_home_parameter = getParameter("windowsHome");
+	    if (windows_home_parameter != null && !windows_home_parameter.equals("")) {
+		gli_user_directory_path = windows_home_parameter + File.separator + "GLI" + File.separator;
+	    }
+	    else {
+		gli_user_directory_path += "Application Data" + File.separator + "Greenstone" + File.separator + "GLI" + File.separator;
+	    }
+	}
+        else {
+            gli_user_directory_path += ".gli" + File.separator;
+        }
+	Gatherer.setGLIUserDirectoryPath(gli_user_directory_path);
+
+	// If we're running as an applet we don't have a local GLI, so use the user directory path as the GLI path
+	Gatherer.setGLIDirectoryPath(gli_user_directory_path);
+
+	// Set some global variables so we know how we're running
+	Gatherer.isApplet = true;
+	String library_url_string = fullLibraryURL(getParameter("gwcgi"));
+	String gliserver_url_string = library_url_string.substring(0, library_url_string.lastIndexOf('/') + 1) + "gliserver.pl";
+
+        // String debug_param = getParameter("debug");
+        // if ((debug_param != null) && (debug_param.matches("true"))) {
+        //     go.debug = true;
+        // }
+
+	String[] args = { "-use_remote_greenstone",
+			  "-gliserver_url", gliserver_url_string,
+			  "-library_url", library_url_string,
+			  // "-debug",
+	                };
+
+	File collect_directory = new File(Gatherer.getCollectDirectoryPath());
+	if (!collect_directory.exists()) {
+	    if (JarTools.isInJar("collect.zip")) {
+		// Dig out collect.zip from JAR file and unzip it (thereby
+		// creating collect directory and descendants.
+		//   This is done to seed gsdl home folder with config files
+		//   for documented example collections so "base this on
+		//   existing collection" works
+		unzipFromJar("collect.zip", Gatherer.getGLIUserDirectoryPath());
+	    }
+	    else {
+		// Prepare an empty collect dir for use
+		if (!collect_directory.mkdir()) {
+		    System.err.println("Warning: Unable to make directory: " + collect_directory);
+		}
+	    }
+	}
+
+	File metadata_directory = new File(Gatherer.getGLIMetadataDirectoryPath());
+	if (!metadata_directory.exists()) {
+	    // dig out metadata.zip from JAR file and unzip it
+	    unzipFromJar("metadata.zip", Gatherer.getGLIDirectoryPath());
+	}
+
+	// Create an instance of the Gatherer class, which will parse the args and prepare the rest of the GLI
+	gatherer = new Gatherer(args);
+
+	// Create a button for the user to press to open the GLI GUI
+	JButton launch_GLI_button = new JButton("Launch Greenstone Librarian Interface ...");
+	launch_GLI_button.addActionListener(this);
+	getContentPane().add(launch_GLI_button);
+    }
+
+
+    public void start() 
+    {
+	System.err.println("Start called");
+    }
+
+
+    public void stop()
+    {
+	System.err.println("Stop called");
+    }
+
+
+    public void destroy()
+    {
+	System.err.println("Destroy called");
+	gatherer.exit();
+	System.err.println("Done gatherer exit.");
+    }
+
+
+    public void actionPerformed(ActionEvent e)
+    {
+	gatherer.openGUI();
+    }
+
+
+    /** 
+     * Method which unzips a given metadata resoure.
+     * @param jar_zip_fname The name of the jar file as a <strong>String</strong>.
+     * @param dst_dir The destination directory for unzipping, also as a <strong>String</strong>.
+     * @see JarTools.extractFromJar(String, String, boolean)
+     */
+    static public void unzipFromJar(String jar_zip_fname, String dst_dir)
+    {
+	if (!dst_dir.endsWith(File.separator)) {
+	    dst_dir += File.separator;
+	}
+
+	JarTools.extractFromJar(jar_zip_fname, dst_dir, true);
+	UnzipTools.unzipFile(dst_dir + jar_zip_fname, dst_dir);
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/GathererProg.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/GathererProg.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/GathererProg.java	(revision 13928)
@@ -0,0 +1,82 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, NZDL Project, University of Waikato
+ *
+ * Copyright (C) 2005 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer;
+
+
+import java.io.*;
+import javax.swing.*;
+import org.greenstone.gatherer.util.Utility;
+
+
+/**
+ * Containing the main() method, this class is the entry point for the
+ * stand-alone (non-Applet) GLI. The main point of this class is to set
+ * some stand-alone specific properties and then create an instance of the
+ * Gatherer class.
+ * @author John Thompson, NZDL Project, University of Waikato
+ */
+public class GathererProg
+{
+    /** The entry point into the stand-alone GLI.
+     * @param args A collection of arguments that may include: initial screen size, dictionary, path to the GSDL etc.
+     */
+    static public void main(String[] args)
+    {
+	// A serious hack, but its good enough to stop crappy 'Could not
+	// lock user prefs' error messages.  Thanks to Walter Schatz from
+	// the java forums.
+	System.setProperty("java.util.prefs.syncInterval","2000000"); 
+	// => results in one message every 600 hours!
+
+	// Ensure platform specific LAF
+	try {
+	    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+	}
+	catch (Exception exception) {
+	    exception.printStackTrace();
+	}
+
+	// Determine the GLI user directory path
+	String gli_user_directory_path = System.getProperty("user.home") + File.separator;
+        if (Utility.isWindows()) {
+	    gli_user_directory_path += "Application Data" + File.separator + "Greenstone" + File.separator + "GLI" + File.separator;
+        }
+        else {
+            gli_user_directory_path += ".gli" + File.separator;
+        }
+	Gatherer.setGLIUserDirectoryPath(gli_user_directory_path);
+
+	// We have a local GLI
+	Gatherer.setGLIDirectoryPath(System.getProperty("user.dir") + File.separator);
+
+	// Create an instance of the Gatherer class, which will parse the args and prepare the rest of the GLI
+	Gatherer gatherer = new Gatherer(args);
+
+	// Display the GUI immediately
+	gatherer.openGUI();
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/GetOpt.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/GetOpt.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/GetOpt.java	(revision 13928)
@@ -0,0 +1,247 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson and David Bainbridge, 
+ *         Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer;
+
+import java.io.*;
+import org.greenstone.gatherer.util.StaticStrings; 
+import org.greenstone.gatherer.util.Utility;
+
+public class GetOpt
+{
+    public boolean debug = false; 
+    public boolean feedback_enabled = false;
+    public boolean no_load = false;
+    public boolean use_remote_greenstone = false;
+    public boolean new_set = false;
+
+    public String client_operating_system = null;
+    public String collect_directory_path = null;
+    public String filename = null;
+    public String gliserver_url_string = null;
+    public String gsdl_path = null;
+    public String gsdl3_path = null;
+    public String gsdl3_src_path = null;
+    public String library_url_string = null;
+    public String local_library_path = null;
+    public String perl_path = null;
+    public String site_name = null; // for GS3
+    public String servlet_path = null;
+    public String metadata_path = null;
+
+    public GetOpt(String[] args)
+    {
+	// Default dictionary. Only used for starting error messages.
+	Dictionary dictionary = new Dictionary(null, null); 
+
+	// Parse arguments
+	int argument_index = 0;
+	String next_token = null;
+
+	while(argument_index < args.length || next_token != null) {
+	    // 1. We start by attempting to parse an argument name. An argument
+	    //    must start with a '-', and should not contain spaces. If
+	    //    anything else is encountered it is ignored.
+
+	    String argument_name = null;
+	    if(next_token == null) {
+		next_token = args[argument_index];
+		argument_index++;
+	    }
+
+	    if(next_token.startsWith(StaticStrings.MINUS_CHARACTER)) {
+		// Trim second '-' just to be kind to Unixy-type people
+		if(next_token.startsWith(StaticStrings.MINUS_CHARACTER + StaticStrings.MINUS_CHARACTER)) {
+		    argument_name = next_token.substring(1);
+		}
+		else {
+		    argument_name = next_token;
+		}
+	    }
+	    next_token = null;
+	    // 2. If we now have an argument name we continue by attempting
+	    //    to parse a value. A value is taken to be the sequence of
+	    //    space seperated Strings between the last argument name
+	    //    and up to but not including the next argument name. Of
+	    //    course an argument needn't have any value (ie -debug,
+	    //    -help), in which case value will be null.
+	    if(argument_name != null) {
+		String argument_value = null;
+		StringBuffer argument_value_buffer = new StringBuffer("");
+		while(argument_index < args.length && next_token == null) {
+		    next_token = args[argument_index];
+		    argument_index++;
+		    // If we just parsed an arbitary String then append it to value, followed by a single space
+		    if(!next_token.startsWith(StaticStrings.MINUS_CHARACTER)) {
+			argument_value_buffer.append(next_token);
+			argument_value_buffer.append(StaticStrings.SPACE_CHARACTER);
+			next_token = null;
+		    }
+		    // If the argument token retrieved is an argument name,
+		    // then leave it in next_token, which will cause the
+		    // argument parsing process to move onto the next step.
+		}
+		// If a value now exists in argument buffer, retrieve
+		// it. Remove the last character as it will be an erroneous
+		// space.
+		if(argument_value_buffer.length() > 0) {
+		    argument_value = argument_value_buffer.substring(0, argument_value_buffer.length() - 1);
+		}
+		
+		// 3. We now have the argument name, and any associated
+		//    value. We are ready to store the data in the
+		//    appropriate variables.
+		DebugStream.println("Parsed Argument: name=" + argument_name + (argument_value != null ? (", value=" + argument_value) : ", no value"));
+		// 3a. First those arguments that have no associated value
+		if(argument_value == null) {
+		    if(argument_name.equals(StaticStrings.HELP_ARGUMENT)) {
+			System.out.println(Dictionary.get("General.Usage"));
+			System.exit(0);
+		    }
+		    // Run GLI in debug mode. Produces debug log plus extra
+		    // messages.
+		    else if(argument_name.equals(StaticStrings.DEBUG_ARGUMENT)) {
+			debug = true;
+		    }
+		    // Run GLI with feedback enabled. 
+		    else if(argument_name.equals(StaticStrings.FEEDBACK_ARGUMENT)) {
+			feedback_enabled = true;
+		    }
+		    // Forces no loading on previous collection.
+		    else if(argument_name.equals(StaticStrings.NO_LOAD_ARGUMENT)) {
+			no_load = true;
+			filename = null;
+		    }
+		    // Use a remote Greenstone rather than a local one
+		    else if (argument_name.equals(StaticStrings.USE_REMOTE_GREENSTONE_ARGUMENT)) {
+			use_remote_greenstone = true;
+		    }
+		    else if (argument_name.equals(StaticStrings.NEW_METADATASET)) {
+			new_set = true;
+		    }
+		}
+		// 3b. Now for those that do
+		else {
+		    // Parse the path to the GSDL. Required argument.
+		    if(argument_name.equals(StaticStrings.GSDL_ARGUMENT)) {
+			if(argument_value.endsWith(File.separator)) {
+			    gsdl_path = argument_value;
+			}
+			else {
+			    gsdl_path = argument_value + File.separator;
+			}
+		    }
+		    // GSDL3 path
+		    if(argument_name.equals(StaticStrings.GSDL3_ARGUMENT)) {
+			if(argument_value.endsWith(File.separator)) {
+			    gsdl3_path = argument_value;
+			}
+			else {
+			    gsdl3_path = argument_value + File.separator;
+			}
+		    }
+		    // GSDL3 src path
+		    if(argument_name.equals(StaticStrings.GSDL3_SRC_ARGUMENT)) {
+			if(argument_value.endsWith(File.separator)) {
+			    gsdl3_src_path = argument_value;
+			}
+			else {
+			    gsdl3_src_path = argument_value + File.separator;
+			}
+		    }
+		    // Client operating system
+		    else if (argument_name.equals(StaticStrings.GSDLOS_ARGUMENT)) {
+			client_operating_system = argument_value;
+		    }
+		    
+		    else if (argument_name.equals(StaticStrings.SITE_ARGUMENT)) {
+			site_name = argument_value;
+		    }
+		    else if (argument_name.equals(StaticStrings.SERVLET_ARGUMENT)) {
+			servlet_path = argument_value;
+		    }
+		    // Specify a non-standard collect directory to use (for running one GLI in a network environment)
+		    else if (argument_name.equals(StaticStrings.COLLECTDIR_ARGUMENT)) {
+			collect_directory_path = argument_value;
+			System.err.println("Non standard collect directory specified: " + collect_directory_path);
+		    }
+		    // Specify a collection to load initially. Could be used for file associations.
+		    else if(argument_name.equals(StaticStrings.LOAD_ARGUMENT)) {
+			filename = argument_value;
+			no_load = false;
+		    }
+		    // Parse the file path of the local library server
+		    else if (argument_name.equals(StaticStrings.LOCAL_LIBRARY_ARGUMENT)) {
+			local_library_path = argument_value;
+		    }
+		    // Manually specify the Greenstone library URL
+		    else if (argument_name.equals(StaticStrings.LIBRARY_URL_ARGUMENT)) {
+			library_url_string = argument_value;
+		    }
+		    // Specify the URL to the gliserver CGI script for remote collection building
+		    else if (argument_name.equals(StaticStrings.GLISERVER_URL_ARGUMENT)) {
+			gliserver_url_string = argument_value;
+		    }
+		    // Parse the path to PERL. If not provided it assumes
+		    // perl should be availble on the PATH.
+		    else if(argument_name.equals(StaticStrings.PERL_ARGUMENT)) {
+			perl_path = argument_value;
+			// Test whether this points to the Perl bin
+			// directory or the Perl executable itself.
+			File perl_file = new File(perl_path);
+			if(perl_file.isDirectory()) {
+			    // If this is windows we create a child file
+			    // perl.exe, otherwise we create perl
+			    if(Utility.isWindows()) {
+				perl_file = new File(perl_file, Utility.PERL_EXECUTABLE_WINDOWS);
+			    }
+			    else {
+				perl_file = new File(perl_file, Utility.PERL_EXECUTABLE_UNIX);
+			    }
+			    // And store this new path.
+			    perl_path = perl_file.getAbsolutePath();
+			    perl_file = null;
+			}
+			// Otherwise it is fine as it is
+		    }
+                    else if(argument_name.equals(StaticStrings.METADATA_PATH)){
+			if (argument_value != null && !argument_value.equals("")) {
+			    File metadata_file = new File(argument_value);
+			    if (metadata_file.exists()) {
+				metadata_path = argument_value;
+			    } 
+			}
+		    }
+                  
+		}
+	    }
+	    // Argument name was null, nothing to be done.
+	}
+	next_token = null;
+	// Arguments all parsed.
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/Argument.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/Argument.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/Argument.java	(revision 13928)
@@ -0,0 +1,646 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Greenstone Librarian Interface (GLI) application, 
+ * part of the Greenstone digital library software suite from the New 
+ * Zealand Digital Library Project at the University of Waikato, 
+ * New Zealand.
+ *
+ * Author: John Thompson 
+ *         Greenstone Project, New Zealand Digital Library
+ *         University of Waikato
+ *         http://www.nzdl.org
+ *
+ * Copyright (C) 2004 New Zealand Digital Library, University of Waikato
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+
+package org.greenstone.gatherer.cdm;
+
+import java.io.*;
+import java.util.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.Collection;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.metadata.MetadataElement;
+import org.greenstone.gatherer.metadata.MetadataTools;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.util.XMLTools;
+import org.w3c.dom.*;
+
+/** This class contains all the details about a single argument that can be passed to this plugin, including option lists if the parameters are restricted.
+ * @author John Thompson, Greenstone Project, New Zealand Digital Library, University of Waikato
+ * @version 2.41 final
+ */
+public class Argument
+    implements Comparable, Serializable {
+    /** An element of the argument type enumeration specifying a combobox control. */
+    static final public byte ENUM = 0;
+    /** An element of the argument type enumeration specifying a checkbox control. */
+    static final public byte FLAG = 1;
+    /** An element of the argument type enumeration specifying a tree control. */
+    static final public byte HIERARCHY = 2;
+    /** An element of the argument type enumeration specifying a spinner control. */
+    static final public byte INTEGER = 3;
+    /** An element of the argument type enumeration specifying a language combobox control. */
+    static final public byte LANGUAGE = 4;
+    /** An element of the argument type enumeration specifying a list control. */
+    static final public byte METADATA = 5;
+    /** An element of the argument type enumeration specifying a metadata combobox control. */
+    static final public byte METADATUM = 6;
+    /** An element of the argument type enumeration specifying a text field. */
+    static final public byte STRING = 7;
+    /** An element of the argument type enumeration specifying a regular expression text field. */
+    static final public byte REGEXP = 8;
+    /** An element of the argument type enumeration specifying a metadata set combobox control. */
+    static final public byte METADATA_SET_NAMESPACE = 9;
+
+ ///////////kk added the number was 9, I changed it to 10//////////////
+  /** An element of the argument type enumeration specifying a text field. */
+    static final public byte URL = 10;
+    /////////////////////////////////////////////////////////////////
+
+    /** true if this argument should actually be hidden within the GLI. This is important for arguments such as import dir or other location critical arguments. */
+    private boolean hidden_gli = false;
+    /** <i>true</i> if this argument is required for the applicable script to work properly, <i>false</i> otherwise. */
+    private boolean required = false;
+    /** The type of this argument. Used to be an int, but bytes are cheaper. */
+    private byte type = STRING;
+    /** The maximum value an integer based control can have. */
+    private int maximum = Integer.MAX_VALUE;
+    /** The minimum value an integer based control can have. */
+    private int minimum = Integer.MIN_VALUE;
+    /** Every argument has a detail mode level at which it becomes available to the user to edit. 
+     * @see org.greenstone.gatherer.Configuration
+     */
+    private int mode_level = Configuration.LIBRARIAN_MODE;
+    /** The DOM element this argument is built around, if any. */
+    private Element element;
+    /** If the argument is of type ENUM then this map holds all the various options. Each entry is an &lt;option value&gt; -&gt; &lt;description&gt; mapping. */
+    private ArrayList option_list = null;
+    /** A default value for parameter-type arguments. May be a Perl pattern. */
+    private String default_value = null;
+    /** The text description of this argument parsed from the pluginfo output. */
+    private String description = null;
+    /** The argument flag as it appears in the command. Also used as the unique identifier of an argument. */
+    private String name = null;
+    /** The plugin that owns this argument, for the purposes of visualising inheritance. */
+    private String owner = null;
+
+    private String display_name = null;
+
+    /** Default Constructor. */
+    public Argument() {
+    }
+
+    /** Another constructor but this one is a little more interesting as it takes a DOM element.
+     * @param element the Element this argument is based around
+     */
+    public Argument(Element element) {
+	this.element = element;
+    }
+
+    /** Method to add an element to the option_list.
+     * @param name the name value of the option as a String
+     * @param desc the description of this options as a String
+     */
+    public void addOption(String name, String desc) {
+	if(type == ENUM && name != null) {
+	    if(desc == null) {
+		desc = "";
+	    }
+	    if(option_list == null) {
+		option_list = new ArrayList();
+	    }
+	    option_list.add(new ArgumentOption(name, desc));
+	}
+    }
+
+    /** Method to compare two arguments for ordering.
+     * @param object the argument we are comparing to, as an Object
+     * @return an int specifying the argument order, using values as set out in String
+     * @see org.greenstone.gatherer.cdm.Argument
+     */
+    public int compareTo(Object object) {
+	if(object instanceof Argument) {
+	    return getName().compareTo(((Argument)object).getName());
+	}
+	else {
+	    return toString().compareTo(object.toString());
+	}
+    }
+
+    /** Create a copy of this argument.
+     * @return a newly created Argument with the same details as this one
+     */
+    public Argument copy() {
+	Argument copy = new Argument();
+	copy.setDefaultValue(default_value);
+	copy.setDescription(description);
+	copy.setOptions(option_list);
+	copy.setOwner(owner);
+	copy.setName(name);
+	copy.setRequired(required);
+	copy.setType(type);
+	copy.setMinimum(minimum);
+	copy.setMaximum(maximum);
+	copy.setModeLevel(mode_level);
+	copy.setHiddenGLI(hidden_gli);
+	return copy;
+    }
+
+    /** Method to determine if two arguments are equal.
+     * @param object the argument to test against, as an Object
+     * @return true if the arguments names match, false otherwise
+     */
+    public boolean equals(Object object) {
+	return (compareTo(object) == 0);
+    }
+
+    /** Method to retrieve the value of default_value.
+     * @return a String containing the default value
+     */
+    public String getDefaultValue() {
+	return default_value;
+    }
+
+    /** Method to retrieve this arguments description.
+     * @return a String containing the description
+     */
+    public String getDescription() {
+	return description;
+    }
+
+    public Element getElement() {
+	return element;
+    }
+    /** Retrieve the upper bound of a range based argument.
+     * @return the maximum as an int
+     */
+    public int getMaximum() {
+	return maximum;
+    }
+
+    /** Retrieve the lower bound of a range based argument.
+     * @return the minimum as an int
+     */
+    public int getMinimum() {
+	return minimum;
+    }
+
+    /** Retrieves the mode level at which this argument should become available. Any higher levels should also see this argument.
+     * @return the mode level as an int
+     */
+    public int getModeLevel() {
+	return mode_level;
+    }
+
+    /** Method to retrieve the value of name.
+     * @return a String containing the argument name
+     * @see org.greenstone.gatherer.util.StaticStrings#NAME_ATTRIBUTE
+     */
+    public String getName() {
+	if(name == null && element != null) {
+	    name = element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
+	}
+	return name;
+    }
+
+    public String getDisplayName() {
+	return display_name;
+    }
+
+
+    /** Method to retrieve the option list for this argument.
+     * @return a HashMap containing &lt;option value&gt; -&gt; &lt;description&gt; entries
+     */
+    public ArrayList getOptions() {
+	return option_list;
+    }
+
+    /** Retrieve the name of the owner of this argument.
+     * @return the owners name as a String
+     */
+    public String getOwner() {
+	return owner;
+    }
+    
+    /** Method to determine the type of this argument.
+     * @return a byte specifying the type
+     */
+    public byte getType() {
+	return type;
+    }
+
+    /** Method to retrieve the value of value.
+     * @return the value of value as a String
+     * @see org.greenstone.gatherer.Gatherer#c_man
+     * @see org.greenstone.gatherer.collection.CollectionManager#getCollection
+     */
+    public String getValue()
+    {
+	// Only assigned arguments have values.
+	if (element == null) {
+	    return null;
+	}
+
+	return XMLTools.getValue(element);
+    }
+
+
+    /** Method to determine if this argument has been assigned.
+     * @return true if it has, false otherwise
+     * @see org.greenstone.gatherer.util.StaticStrings#ASSIGNED_ATTRIBUTE
+     * @see org.greenstone.gatherer.util.StaticStrings#TRUE_STR
+     */
+    public boolean isAssigned() {
+	return (element != null && element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.TRUE_STR));
+    }
+
+    /** Determine if this is a custom argument ie one that has been parsed from the config file but doesn't have a matching entry in the argument library.
+     * @return true if this argument is a custom, false otherwise
+     * @see org.greenstone.gatherer.util.StaticStrings#CUSTOM_ATTRIBUTE
+     * @see org.greenstone.gatherer.util.StaticStrings#TRUE_STR
+     */
+    public boolean isCustomArgument() {
+	return (element != null && element.getAttribute(StaticStrings.CUSTOM_ATTRIBUTE).equals(StaticStrings.TRUE_STR));
+    }
+
+    /** Determine if this argument is hidden in GLI
+     * @return true if the argument is hidden, false otherwise
+     */
+    public boolean isHiddenGLI() {
+	return hidden_gli;
+    }
+
+    /** Method to determine of this argument is required for the associated script to work.
+     * @return true if this argument is required, false otherwise
+     */
+    public boolean isRequired() {
+	return required;
+    }
+
+    /** Method to allow for the activation of arguments that might never have their setValue() method called.
+     * @param assigned the desired state as a boolean
+     * @see org.greenstone.gatherer.util.StaticStrings#ASSIGNED_ATTRIBUTE
+     * @see org.greenstone.gatherer.util.StaticStrings#FALSE_STR
+     * @see org.greenstone.gatherer.util.StaticStrings#TRUE_STR
+     */
+    public void setAssigned(boolean assigned) {
+	if(element != null) {
+	    element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, (assigned ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
+	}
+    }
+
+    /** Sets the value of default_value.
+     * @param default_value The new value for default_value as a <strong>String</strong>.
+     */
+    public void setDefaultValue(String default_value) {
+	this.default_value = default_value;
+    }
+
+    /** Set the value of desc.
+     * @param description the new value of desc as a String
+     */
+    public void setDescription(String description) {
+	this.description = description;
+    }
+
+    /** Set the element this argument should be based upon.
+     * @param element the Element
+     */
+    public void setElement(Element element) {
+	this.element = element;
+    }
+
+    /** Mark this argument as being hidden in GLI. */
+    public void setHiddenGLI(boolean hidden) {
+	this.hidden_gli = hidden;
+    }
+
+    /** Set the upper bound for a range type argument.
+     * @param maximum the maximum as an int
+     */
+    public void setMaximum(int maximum) {
+	this.maximum = maximum;
+    }
+
+    /** Set the lower bound for a range type argument.
+     * @param minimum the minimum as an int
+     */
+    public void setMinimum(int minimum) {
+	this.minimum = minimum;
+    }
+
+    /** Set the detail mode level where this argument will become available.
+     * @param mode_level the mode level as an int
+     */
+    public void setModeLevel(int mode_level) {
+	this.mode_level = mode_level;
+    }
+
+    /** Set the value of name.
+     * @param name the new value of name as a String
+     */
+    public void setName(String name) {
+	this.name = name;
+    }
+
+    /** Sets the value of the options list.
+     * @param list the new options list as a HashMap
+     */
+    public void setOptions(ArrayList list) {
+	this.option_list = list;
+    }
+
+    /** Set the owner of this argument.
+     * @param owner the name of the owner of this argument as a String
+     */
+    public void setOwner(String owner) {
+	this.owner = owner;
+    }
+
+    /** Set the value of required.
+     * @param required the new value of required as a boolean
+     */
+    public void setRequired(boolean required) {
+	this.required = required;
+    }
+
+    /** Set the value of type.
+     * @param type the new value of type as an byte
+     */
+    public void setType(byte type) {
+	this.type = type;
+    }
+
+    /** Set the value of type, by matching a type to the given string.
+     * @param new_type a String which contains the name of a certain argument type
+     * @see org.greenstone.gatherer.util.StaticStrings#ENUM_STR
+     * @see org.greenstone.gatherer.util.StaticStrings#FLAG_STR
+     * @see org.greenstone.gatherer.util.StaticStrings#HIERARCHY_STR
+     * @see org.greenstone.gatherer.util.StaticStrings#INT_STR
+     * @see org.greenstone.gatherer.util.StaticStrings#LANGUAGE_STR
+     * @see org.greenstone.gatherer.util.StaticStrings#METADATA_TYPE_STR
+     * @see org.greenstone.gatherer.util.StaticStrings#METADATUM_TYPE_STR
+     * @see org.greenstone.gatherer.util.StaticStrings#REGEXP_STR
+     */
+    public void setType(String new_type) {
+	if(new_type.equalsIgnoreCase(StaticStrings.ENUM_STR)) {
+	    this.type = ENUM;
+	    option_list = new ArrayList();
+	}
+	else if(new_type.equalsIgnoreCase(StaticStrings.FLAG_STR)) {
+	    this.type = FLAG;
+	}
+	else if(new_type.equalsIgnoreCase(StaticStrings.HIERARCHY_STR)) {
+	    this.type = HIERARCHY;
+	}
+	else if(new_type.equalsIgnoreCase(StaticStrings.INT_STR)) {
+	    this.type = INTEGER;
+	}
+	else if(new_type.equalsIgnoreCase(StaticStrings.LANGUAGE_STR)) {
+	    this.type = LANGUAGE;
+	}
+	else if(new_type.equalsIgnoreCase(StaticStrings.METADATA_TYPE_STR)) {
+	    this.type = METADATA;
+	}
+	else if(new_type.equalsIgnoreCase(StaticStrings.METADATUM_TYPE_STR)) {
+	    this.type = METADATUM;
+	}
+	else if(new_type.equalsIgnoreCase(StaticStrings.REGEXP_STR)) {
+	    this.type = REGEXP;
+	}
+	else {
+	    this.type = STRING;
+	}
+    }
+
+    /** Method to set the value of this argument.
+     * @param value the new value for the argument
+     * @see org.greenstone.gatherer.Gatherer#println
+     */
+    public void setValue(String value) {
+	if(element != null) {
+	    XMLTools.setValue(element, value);
+	}
+	else {
+	    DebugStream.println("Argument.setValue(" + value + ") called on a base Argument.");
+	}
+    }
+
+    /** Set the values vector to the given values. Currently I just assign the new values, whereas I may later want to implement a deep clone.
+     * @param values an ArrayList of values
+     * @see org.greenstone.gatherer.Gatherer#println
+     */
+    public void setValues(ArrayList values) {
+	if(element != null) {
+	    StringBuffer value = new StringBuffer();
+	    int value_length = values.size();
+	    for(int i = 0; i < value_length; i++) {
+		value.append(values.get(i));
+		value.append(StaticStrings.COMMA_CHARACTER);
+	    }
+	    value.deleteCharAt(value.length() - 1); // Remove last ','
+	    XMLTools.setValue(element, value.toString());
+	}
+	else {
+	    DebugStream.println("Argument.setValues([" + values.size() + " items]) called on a base Argument.");
+	}
+    }
+
+    /** Method for translating the data of this class into a string.
+     * @return a String containing a fragment of the total arguments string
+     * @see org.greenstone.gatherer.Gatherer#c_man
+     * @see org.greenstone.gatherer.collection.CollectionManager#getCollection
+     * @see org.greenstone.gatherer.util.StaticStrings#COMMA_CHARACTER
+     * @see org.greenstone.gatherer.util.StaticStrings#NAME_ATTRIBUTE
+     * @see org.greenstone.gatherer.util.StaticStrings#SPACE_CHARACTER
+     * @see org.greenstone.gatherer.util.StaticStrings#SPEECH_CHARACTER
+     */
+    public String toString()
+    {
+	StringBuffer text = new StringBuffer("-");
+
+	if (element == null) {
+	    return text.toString();
+	}
+
+	if (name == null) {
+	    name = element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
+	}
+	text.append(name);
+
+	String value = XMLTools.getValue(element);
+	if (value.length() == 0) {
+	    return text.toString();
+	}
+
+	text.append(StaticStrings.SPACE_CHARACTER);
+
+// 	// Handle metadata elements specially
+// 	if (type == METADATA || type == METADATUM) {
+// 	    // Tokenize the string
+// 	    StringTokenizer tokenizer = new StringTokenizer(value, ",");
+// 	    while (tokenizer.hasMoreTokens()) {
+// 		String token = tokenizer.nextToken();
+
+// 		MetadataElement metadata_element = MetadataTools.getMetadataElementWithDisplayName(token);
+// 		if (metadata_element != null) {
+// 		    text.append(metadata_element.getFullName());
+// 		}
+// 		else {
+// 		    text.append(token);
+// 		}
+
+// 		if (tokenizer.hasMoreTokens()) {
+// 		    text.append(StaticStrings.COMMA_CHARACTER);
+// 		}
+// 	    }
+// 	    return text.toString();
+// 	}
+
+	// If the value contains a space, add speech marks
+	//   (Except for metadata elements, which won't have spaces when written out to collect.cfg)
+	if (value.indexOf(StaticStrings.SPACE_CHARACTER) != -1 && !(type == METADATUM || type == METADATA)) {
+	    value = StaticStrings.SPEECH_CHARACTER + value + StaticStrings.SPEECH_CHARACTER;
+	}
+
+	text.append(value);
+	return text.toString();
+    } 
+
+    /** parse the <Option> XML from eg import.pl -xml or pluginfo.pl -xml */
+    public void parseXML(Element option) {
+
+	for(Node node = option.getFirstChild(); node != null; node = node.getNextSibling()) {
+	    String node_name = node.getNodeName();
+	    if(node_name.equals("Name")) {
+		setName(XMLTools.getValue(node));
+	    }
+	    else if(node_name.equals("Desc")) {
+		setDescription(XMLTools.getValue(node));
+	    }
+	    else if(node_name.equals("Type")) {
+		setType(XMLTools.getValue(node));
+	    }
+	    else if(node_name.equals("Default")) {
+		setDefaultValue(XMLTools.getValue(node));
+	    }
+	    else if(node_name.equals("Required")) {
+		String v = XMLTools.getValue(node);
+		if(v != null && v.equals("yes")) {
+		    setRequired(true);
+		}
+	    }
+	    else if(node_name.equals("List")) {
+		// Two final loops are required to parse lists.
+		for(Node value = node.getFirstChild(); value != null; value = value.getNextSibling()) {
+		    if(value.getNodeName().equals("Value")) {
+			String key = null;
+			String desc = "";
+			for(Node subvalue = value.getFirstChild(); subvalue != null; subvalue = subvalue.getNextSibling()) {
+			    node_name = subvalue.getNodeName();
+			    if(node_name.equals("Name")) {
+				key = XMLTools.getValue(subvalue);
+			    }
+			    else if(node_name.equals("Desc")) {
+				desc = XMLTools.getValue(subvalue);
+			    }
+			}
+			if(key != null) {
+			    addOption(key, desc);
+			}
+		    }
+		}
+	    }
+	    else if(node_name.equals("Range")) {
+		String range_raw = XMLTools.getValue(node);
+		int index = -1;
+		if((index = range_raw.indexOf(StaticStrings.COMMA_CHARACTER)) != -1) {
+		    if(index > 0) {
+			try {
+			    String first_number = range_raw.substring(0, index);
+			    setMinimum(Integer.parseInt(first_number));
+			    first_number = null;
+			}
+			catch(Exception exception) {
+			}
+		    }
+		    
+		    if(index + 1 < range_raw.length()) {
+			try {
+			    String second_number = range_raw.substring(index + 1);
+			    setMaximum(Integer.parseInt(second_number));
+			    second_number = null;    
+			}
+			catch(Exception exception) {
+			}
+		    }
+		}
+		// Else it wasn't a valid range anyway, so ignore it
+	    }
+	    else if(node_name.equals("HiddenGLI")) {
+		setHiddenGLI(true);
+	    }
+	    else if(node_name.equals("ModeGLI")) {
+		String mode_level_str = XMLTools.getValue(node);
+		try {
+		    int mode_level = Integer.parseInt(mode_level_str);
+		    setModeLevel(mode_level);
+		}
+		catch(Exception exception) {
+		    DebugStream.println("Exception in Argument.parseXML() - Unexpected but non-fatal");
+		    DebugStream.printStackTrace(exception);
+		}
+	    }
+	    
+	} // for each option
+	
+    } // parseXML
+
+    public class ArgumentOption 
+	implements Comparable {
+	public String name;
+	public String description;
+	private String text; // cached version
+
+	public ArgumentOption(String name, String desc) {
+	    this.name = name;
+	    this.description = desc;
+	}
+	
+	public int compareTo(Object obj) {
+	    return toString().compareTo(obj.toString());
+	}
+
+	public boolean equals(Object obj) {	    
+	    return (obj != null && compareTo(obj) == 0);
+	}
+	
+	public String toString() {
+	    return name + " "+ StaticStrings.MINUS_CHARACTER + " "+ description;
+	}
+	
+	public String getToolTip() {
+	    return Utility.formatHTMLWidth(name+": "+description, 80);
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/ArgumentConfiguration.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/ArgumentConfiguration.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/ArgumentConfiguration.java	(revision 13928)
@@ -0,0 +1,247 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.gui.GComboBox;
+import org.greenstone.gatherer.gui.GLIButton;
+import org.greenstone.gatherer.gui.ModalDialog;
+import org.greenstone.gatherer.gui.SimpleMenuBar;
+import org.greenstone.gatherer.metadata.MetadataElement;
+import org.greenstone.gatherer.metadata.MetadataSetManager;
+import org.greenstone.gatherer.metadata.MetadataTools;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+
+/** This class provides us with a dialog box which allows us to edit the arguments of either a Plugin or a Classifier.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ * @see org.greenstone.gatherer.cdm.Classifier
+ * @see org.greenstone.gatherer.cdm.Plugin
+ */
+public class ArgumentConfiguration
+    extends ModalDialog
+    implements ActionListener {
+    /** The data whose arguments we are editing. */
+    private ArgumentContainer data = null;
+    /** Whether we have successfully edited the arguments associated with the ArgumentContainer or if we have failed to enter required arguments and have instead cancelled (which would cause argument additions to roll back). */
+    private boolean success = false;
+    /** A button to cancel this dialog. */
+    private JButton cancel = null;
+    /** A button to accept the changes and close the dialog. */
+    private JButton ok = null;
+    /** A reference to the ourselves so our inner classes can dispose us like a dialog. */
+    private ArgumentConfiguration self = null;
+    /** The central pane where a list of known arguments is displayed. */
+    private JPanel central_pane = null;
+    /** The size used for an argument label. */
+    static final private Dimension LABEL_SIZE = new Dimension(225, 25);
+    /** Size of a list. */
+    static final private Dimension LIST_SIZE = new Dimension(380, 50);
+    /** The size used for the dialog. */
+    static final private Dimension SIZE = new Dimension(800, 425);
+
+    /** Constructor.
+     * @param data The plugin or classifier whose arguments we are configuring, in the form of its supported <strong>ArgumentContainer</strong> interface.
+     * @see org.greenstone.gatherer.Configuration
+     */
+    public ArgumentConfiguration(ArgumentContainer data) {
+	super(Gatherer.g_man);
+	this.data = data;
+	this.self = this;
+
+	// Create
+	setModal(true);
+	setSize(SIZE);
+	setJMenuBar(new SimpleMenuBar("designingacollection")); // can we tell whether we are doing a classifier or plugin, to make the help more specific??
+	setTitle(Dictionary.get("CDM.ArgumentConfiguration.Title"));
+
+	central_pane = new JPanel();
+	JPanel content_pane = (JPanel) getContentPane();
+
+	JLabel header = new JLabel(Dictionary.get("CDM.ArgumentConfiguration.Header", data.getName()));
+	header.setHorizontalAlignment(JLabel.CENTER);
+	header.setOpaque(true);
+	
+	JPanel button_pane = new JPanel();
+	cancel = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("General.Pure_Cancel_Tooltip"));
+		
+	ok = new GLIButton(Dictionary.get("General.OK"), Dictionary.get("General.OK_Tooltip"));
+	
+	// Listeners
+	cancel.addActionListener(this);
+	ok.addActionListener(this);
+
+	button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	button_pane.setLayout(new GridLayout(1,2));
+	button_pane.add(ok);
+	button_pane.add(cancel);
+
+	central_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	central_pane.setLayout(new BoxLayout(central_pane, BoxLayout.Y_AXIS));
+
+	content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(header, BorderLayout.NORTH);
+	content_pane.add(new JScrollPane(central_pane), BorderLayout.CENTER);
+	content_pane.add(button_pane, BorderLayout.SOUTH);
+
+	// Now generate a set of controls for each of the arguments.
+	generateControls();
+
+	// Display on screen.
+	Dimension screen_size = Configuration.screen_size;
+	setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+	screen_size = null;
+    }
+
+    /** Any implementation of ActionListener must include this method so that we can be informed when an action has occured on one of the controls we are listening to.
+     * @param event An <strong>ActionEvent</strong> containing pertinant information about the event that fired this call.
+     * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl
+     * @see org.greenstone.gatherer.cdm.ArgumentContainer
+     */
+    public void actionPerformed(ActionEvent event) {
+	boolean cont = true;
+	if (event.getSource() == ok) {
+	    // Clear the current focus to ensure components such as combobox have correctly updated
+	    // Loop through each of the controls in the central pane, updating the matching argument as necessary.
+	    for(int i = 0; i < central_pane.getComponentCount(); i++) {
+		Component component = central_pane.getComponent(i);
+		if(component instanceof ArgumentControl) {
+		   cont = cont && ((ArgumentControl)component).updateArgument();
+		}
+	    }
+	    if(cont) {
+		success = true;
+	    }
+	}
+	if(cont) {
+	    dispose();
+	}
+    }
+
+
+    public void addOKButtonActionListener(ActionListener action_listener)
+    {
+	ok.addActionListener(action_listener);
+    }
+
+
+    /** Destructor. */
+    public void destroy() {
+	cancel = null;
+	central_pane = null;
+	//custom_pane = null;
+	//custom = null;
+	data = null;
+	ok = null;
+	self = null;
+    }
+
+    /** Method which actually forces the dialog to be shown on screen.
+     * @return <i>true</i> if the user completed configuration and pressed ok, <i>false</i> otherwise.
+     */
+    public boolean display() {
+	setVisible(true);
+	return success;
+    }
+
+    private void addHeader(String name, Color color) {
+	JPanel header = new JPanel();
+	header.setBackground(color);
+	JPanel inner_pane = new JPanel();
+	inner_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,5,5,5), BorderFactory.createRaisedBevelBorder()));
+	inner_pane.setBackground(color);
+	JLabel header_label = new JLabel("<html><strong>" + name + "</strong></html>");
+	header_label.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
+	header_label.setHorizontalAlignment(JLabel.CENTER);
+	header_label.setOpaque(true);
+
+	// Layout
+	inner_pane.setLayout(new BorderLayout());
+	inner_pane.add(header_label, BorderLayout.CENTER);
+
+	header.setLayout(new BorderLayout());
+	header.add(inner_pane, BorderLayout.CENTER);
+	central_pane.add(header);
+    }
+
+    /** Method to iterate through the arguments associated with whatever argument container we are building an argument control view for, creating the appropriate controls for each.
+     * @see org.greenstone.gatherer.cdm.Argument
+     * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl
+     */
+    private void generateControls() {
+	// Alternating colours to show inheritance
+	Color colour_one = Configuration.getColor("coloring.collection_heading_background", false);
+	Color colour_two = Configuration.getColor("coloring.collection_tree_background", false);
+	boolean coloured = false;
+	ArrayList arguments = data.getArguments();
+	int total_height = 250;
+	int current_mode = Configuration.getMode();
+
+	String previous_owner = ((Argument) arguments.get(0)).getOwner();
+	addHeader(previous_owner, colour_two);
+
+	for(int i = 0; i < arguments.size(); i++) {
+	    Argument argument = (Argument) arguments.get(i);
+	    String owner = argument.getOwner();
+	    if(previous_owner != argument.getOwner()) {
+	    ///ystem.err.println("previous owner is different from current owner");
+		coloured = !coloured;
+		previous_owner = argument.getOwner();
+		addHeader(previous_owner, (coloured ? colour_one : colour_two));
+	    }
+	    if(!argument.isHiddenGLI() && (current_mode > Configuration.LIBRARIAN_MODE || !(argument.getType() == Argument.REGEXP))) {
+		ArgumentControl argument_control = new ArgumentControl(argument, false, null);
+		total_height = total_height - argument_control.getPreferredSize().height;
+		// Create
+		if(coloured) {
+		    argument_control.setBackground(colour_one);
+		}
+		else {
+		    argument_control.setBackground(colour_two);
+		}
+
+		central_pane.add(argument_control);
+	    }
+	}
+	if(total_height > 0) {
+	    JPanel filler = new JPanel();
+	    filler.setPreferredSize(new Dimension(100, total_height));
+	    filler.setSize(new Dimension(100, total_height));
+	    central_pane.add(filler);
+	}
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/ArgumentContainer.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/ArgumentContainer.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/ArgumentContainer.java	(revision 13928)
@@ -0,0 +1,288 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.w3c.dom.*;
+
+
+/** This class provides an interface to any class that contains a list of Arguments.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+abstract public class ArgumentContainer 
+    extends ArrayList 
+    implements Comparable, DOMProxyListEntry, Serializable  {
+
+    // The DOM Element this container is modelled on
+    protected Element element;
+    protected boolean is_abstract = false;
+    protected ArgumentContainer super_container;
+    protected String description;
+    protected String name;
+
+    /** Constructor used in DOMProxyListModel initializations
+     */
+    public ArgumentContainer() {
+    }
+
+    public ArgumentContainer(Element element, ArgumentContainer base_container) {
+
+	super();
+	this.element = element;
+	this.name = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE);
+
+	// Parse in any argument options for this container, keeping a list of the ones found
+	HashMap known_arguments = new HashMap();
+	NodeList option_elements = element.getElementsByTagName(StaticStrings.OPTION_ELEMENT);
+	int option_elements_length = option_elements.getLength();
+	for(int i = 0; i < option_elements_length; i++) {
+	    Element option_element = (Element) option_elements.item(i);
+	    Argument argument = new Argument(option_element);
+	    ///ystem.err.println("Rebuilding existing argument: " + argument.getName());
+	    known_arguments.put(argument.getName(), argument);
+	}
+	// If a base classifier was given
+	if(base_container != null) {
+	    // Copy the details, and add a reference to whatever the base container's super container is
+	    description = base_container.getDescription();
+	    // Now search through the 'dummy' arguments belonging to the base container. For each found, if it is already assigned, fill out further details such as type. If any are found that are not already assigned for this container, copy them and add them, but without a value.
+	    ArrayList all_arguments = base_container.getArguments();
+	    int argument_count = all_arguments.size();
+	    for(int j = 0; j < argument_count; j++) {
+		Argument base_argument = (Argument) all_arguments.get(j);
+		String base_argument_name = base_argument.getName();
+		///ystem.err.println("Library indicates this container should have an argument: " + base_argument_name);
+		Argument existing_argument = (Argument) known_arguments.get(base_argument_name);
+		// Found an existing argument. Complete its details
+		if(existing_argument != null) {
+		    ///ystem.err.println("Found existing argument. Filling out details.");
+		    known_arguments.remove(base_argument_name);
+		    existing_argument.setDefaultValue(base_argument.getDefaultValue());
+		    existing_argument.setDescription(base_argument.getDescription());
+		    existing_argument.setOptions(base_argument.getOptions());
+		    existing_argument.setRequired(base_argument.isRequired());
+		    existing_argument.setType(base_argument.getType());
+		    existing_argument.setMinimum(base_argument.getMinimum());
+		    existing_argument.setMaximum(base_argument.getMaximum());
+		    existing_argument.setOwner(base_argument.getOwner());
+		    existing_argument.setHiddenGLI(base_argument.isHiddenGLI());
+		    add(existing_argument);
+		}
+		// No existing argument. Copy base_argument and add it, but set its assigned flag to false 
+		else {
+		    ///atherer.println("No such argument. Adding new, unassigned, argument.");
+		    // The trick thing is that we have to create a new element in the DOM as well.
+		    Argument new_argument = base_argument.copy();
+		    Element argument_element = CollectionConfiguration.createElement(StaticStrings.OPTION_ELEMENT);
+		    argument_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, base_argument_name);
+		    argument_element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
+		    new_argument.setElement(argument_element);
+		    // All done. Add it.
+		    element.appendChild(argument_element);
+		    add(new_argument);
+		}
+	    }
+	}
+	
+	// The first time we do this, the args come from the config file and
+	// may contain invalid args. Here we remove them from the DOM.
+	if (!known_arguments.isEmpty()) {
+	    Set entry_set = known_arguments.entrySet();
+	    Iterator entry_iterator = entry_set.iterator();
+	    while (entry_iterator.hasNext()) {
+		Argument arg = (Argument)((Map.Entry)entry_iterator.next()).getValue();
+		Element e = arg.getElement();
+		element.removeChild(e);
+	    }
+	}
+    }
+
+
+    
+
+    /** Constructor used for the plugins that are in the DOMProxyList */
+    /** Method to add an argument to this container. Only adds the argument if it isn't already present.
+     * @param argument The <strong>Argument</strong> to add.
+     */
+    public void addArgument(Argument argument) {
+	if(element == null && !contains(argument)) {
+	    add(argument);
+	    argument.setOwner(name);
+	}
+    }
+
+    /** Method to compare two containers for ordering.
+     * @param object The container we are comparing to, as an <strong>Object</strong>.
+     * @return An <i>int</i> specifying the container order, using values as set out in String.
+     * @see java.lang.String#compareTo
+     */
+    public int compareTo(Object object) {
+	if(object == null ) {
+	    return -1;
+	}
+	return toString().compareTo(object.toString());
+    }
+
+    /** Method to determine if two containers are equal.
+     * @param object The container to test against, as an <strong>Object</strong>.
+     * @return <i>true</i> if they match (based on the equals method), <i>false</i> otherwise.
+     */
+
+    public boolean equals(Object object) {
+	return (compareTo(object) == 0);
+    }
+
+    abstract public DOMProxyListEntry create(Element element);
+    /** Method to retrieve an argument by its name.
+     * @param name The name of the argument as a <strong>String</strong>.
+     * @return The <strong>Argument</strong> requested, or <i>null</i> if no such argument.
+     */
+    public Argument getArgument(String name) {
+	// The name given may still include the '-'
+	if(name.startsWith("-")) {
+	    name = name.substring(1);
+	}
+	//ArrayList arguments = getArguments(true, true);
+	ArrayList arguments = getArguments();
+	for(int i = 0; i < arguments.size(); i++) {
+	    Argument argument = (Argument)arguments.get(i);
+	    if(argument.getName().equals(name)) {
+		return argument;
+	    }
+	}
+	return null;
+    }
+
+    /** Method to retrieve the list of arguments from this container. Note that this method returns both the containers arguments plus its 'supers' arguments if any, and alphabetically orders them.
+     * @return the arguments within a ArrayList
+     */
+    public ArrayList getArguments() {
+	ArrayList arguments = new ArrayList();
+	arguments.addAll(this);
+	if(super_container != null) {
+	    ArrayList remainder = super_container.getArguments();
+	    remainder.removeAll(arguments);
+	    arguments.addAll(remainder);
+	}
+	return arguments;
+
+    }
+
+    public String getDescription() {
+	return description;
+    }
+
+    public Element getElement() {
+	return element;
+    }
+    /** Method to retrieve the name associated with this argument container.
+     * @return the name as a String
+     */
+    public String getName() {
+	if(name == null && element != null) {
+	    name = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE);
+	}
+	return name;
+    }
+
+    public boolean isAbstract() {
+	return is_abstract;
+    }
+
+    public boolean isAssigned() {
+	return (element != null && !element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.FALSE_STR));
+    }
+
+    public void setAssigned(boolean assigned) {
+	if(element != null) {
+	    element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, (assigned ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
+	}
+    }
+
+    public void setDescription(String description) {
+	this.description = description;
+    }
+
+    public void setElement(Element element) {
+	this.element = element;
+    }
+
+    public void setIsAbstract(boolean is_abstract) {
+	this.is_abstract = is_abstract;
+    }
+
+    public void setName(String name) {
+	this.name = name;
+    }
+
+    /** Method to set the value of the super_container.
+     * @param super_container The new value of super_container as a <strong>ArgumentContainer</strong>, or <i>null</i> if this class has no inheritance.
+     */
+    public void setSuper(ArgumentContainer super_container) {
+	this.super_container = super_container;
+    }
+
+    public String toString()
+    {
+	if (element == null) {
+	    return name;
+	}
+
+	if (name == null) {
+	    name = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE);
+	}
+
+	StringBuffer text = new StringBuffer(" ");
+	if (!isAssigned()) {
+	    text.append("#");
+	}
+	text.append(name);
+
+	ArrayList arguments = getArguments();
+	for (int i = 0; i < arguments.size(); i++) {
+	    Argument argument = (Argument) arguments.get(i);
+	    if (argument.isAssigned()) {
+		text.append(" ");
+		text.append(argument.toString());
+	    }
+	}
+
+	return text.toString();
+    }
+
+    public ArrayList getArguments(boolean include_normal, boolean include_custom){
+	return this;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/ArgumentControl.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/ArgumentControl.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/ArgumentControl.java	(revision 13928)
@@ -0,0 +1,570 @@
+package org.greenstone.gatherer.cdm;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Iterator;
+
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.gui.GComboBox;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.metadata.MetadataElement;
+import org.greenstone.gatherer.metadata.MetadataSet;
+import org.greenstone.gatherer.metadata.MetadataSetManager;
+import org.greenstone.gatherer.metadata.MetadataTools;
+
+/** This class encapsulates all the technical difficulty of creating a specific control based on an Argument. */
+public class ArgumentControl
+    extends JPanel {
+
+    static protected Dimension LABEL_SIZE = new Dimension(175, 25);
+    static protected Dimension ROW_SIZE = new Dimension(400, 30);
+    /** The Argument this control will be based on. */
+    private Argument argument = null;
+
+    /** A checkbox to allow enabling or diabling of this Argument. */
+    private JCheckBox enabled = null;
+    /** Some form of editor component, such as a JComboBox or JTextField, used to set parameters to an Argument. */
+    private JComponent value_control = null;
+	
+    /** Constructor.
+     */
+    public ArgumentControl(Argument argument, boolean is_enabled, String preset_value) {
+	this.argument = argument;
+
+	String tip = "<html>" + argument.getName()+": "+argument.getDescription() + "</html>";
+	tip = Utility.formatHTMLWidth(tip, 80);
+
+	setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+	setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
+	setLayout(new BorderLayout());
+	setPreferredSize(ROW_SIZE);
+
+	if (argument.isRequired()) {
+	    JLabel label = new JLabel(argument.getName());
+	    label.setOpaque(false);
+	    label.setPreferredSize(LABEL_SIZE);
+	    label.setToolTipText(tip);
+	    add(label, BorderLayout.WEST);
+	} else {
+	    enabled = new JCheckBox(argument.getName());
+	    enabled.setOpaque(false);
+	    enabled.setPreferredSize(LABEL_SIZE);
+	    enabled.setToolTipText(tip);
+	    add(enabled, BorderLayout.WEST);
+	}
+	
+	String initial_value;
+	if (preset_value != null && !preset_value.equals("")) {
+	    initial_value = preset_value;
+	}
+	else {
+	    initial_value = argument.getValue();
+	}
+	if (initial_value == null || initial_value.equals("")) {
+	    initial_value = argument.getDefaultValue();
+	}
+	if (initial_value == null) {
+	    initial_value = "";
+	}
+	
+	switch(argument.getType()) {
+	case Argument.ENUM:
+	    ArrayList option_list = argument.getOptions();
+	    value_control = new GComboBox(option_list.toArray(), false, false);
+	    selectValue((JComboBox)value_control, initial_value); // also sets the tooltip
+	    ((JComboBox)value_control).addActionListener(new ToolTipUpdater());
+	    break;
+	    
+	case Argument.FLAG:
+	    // Only need the check box.
+	    break;
+
+	case Argument.INTEGER:
+	    // Build a spinner
+	    int initial_int=0;
+	    // If there was an original value, set it.
+	    try {
+		initial_int = Integer.parseInt(initial_value);
+	    } catch (Exception error) {
+		DebugStream.println("ArgumentControl Error: "+error);
+	    }
+	    if (initial_int < argument.getMinimum()) {
+		initial_int = argument.getMinimum();
+	    } else if (initial_int > argument.getMaximum()) {
+		initial_int = argument.getMaximum();
+	    }
+	    
+	    JSpinner spinner = new JSpinner(new SpinnerNumberModel(initial_int, argument.getMinimum(), argument.getMaximum(), 1));
+
+	    // And remember it
+	    value_control = spinner;
+	    break;
+
+	case Argument.REGEXP:
+	case Argument.STRING:
+	    value_control = new JTextField(initial_value);
+		break;
+		
+	case Argument.LANGUAGE:
+	    value_control = new GComboBox(CollectionDesignManager.language_manager.getLanguageCodes().toArray(), false);
+	    // we want to display the language name not the code
+	    ((JComboBox)value_control).setRenderer(new LanguageListCellRenderer());
+	    // Now ensure we have the existing value or default value selected if either exist in our known languages
+	    String lang_name = CollectionDesignManager.language_manager.getLanguageName(initial_value);
+	    if (lang_name != null) {
+		((JComboBox)value_control).setSelectedItem(initial_value);
+	    }
+	    break;
+
+	case Argument.METADATUM:
+	case Argument.METADATA:
+	    value_control = new GComboBox(MetadataSetManager.getEveryMetadataSetElement(), false);
+
+	    // Editable for advanced modes (allows things like dc.Title,ex.Title)
+	    if (Configuration.getMode() > Configuration.ASSISTANT_MODE) {
+		((JComboBox) value_control).setEditable(true);
+	    }
+	    // Now ensure we have the existing value or default value selected if either exist.
+	    String existing_value = preset_value;
+	    if (existing_value == null || existing_value.length() == 0) {
+		existing_value = argument.getValue();
+	    }
+	    if (existing_value != null && existing_value.length() > 0) {
+		boolean found = selectValue((JComboBox) value_control, existing_value);
+		// It's possible that this is a custom value and so doesn't exist in the combobox
+		if (!found) {
+		    // If so, add it then select it
+		    ((JComboBox) value_control).addItem(existing_value);
+		    ((JComboBox) value_control).setSelectedItem(existing_value);
+		}
+	    }
+	    else {
+		String default_value = argument.getDefaultValue();
+		if (default_value != null) {
+		    // if no namespace for default value, add ex.
+		    // won't work if we want to set a non-metadata value
+		    if (MetadataTools.getMetadataSetNamespace(default_value).equals("")) {
+			default_value = StaticStrings.EXTRACTED_NAMESPACE+default_value;
+		    }
+		    selectValue((JComboBox) value_control, default_value);
+		}
+	    }
+	    break;
+
+	case Argument.METADATA_SET_NAMESPACE:
+	    value_control = new JComboBox();
+	    // !! Hack for exploding metadata databases: add the (empty) exploded metadata set
+	    File exploded_metadata_set_file = new File(Gatherer.getGLIMetadataDirectoryPath() + "exp" + StaticStrings.METADATA_SET_EXTENSION);
+	    MetadataSet exploded_metadata_set = new MetadataSet(exploded_metadata_set_file);
+	    Gatherer.c_man.importMetadataSet(exploded_metadata_set);
+
+	    // All the loaded metadata sets except the extracted metadata set are applicable
+	    ArrayList metadata_sets = MetadataSetManager.getMetadataSets();
+	    for (int i = metadata_sets.size() - 1; i >= 0; i--) {
+		MetadataSet metadata_set = (MetadataSet) metadata_sets.get(i);
+		if (!(metadata_set.getNamespace().equals(MetadataSetManager.EXTRACTED_METADATA_NAMESPACE))) {
+		    ((JComboBox)value_control).addItem(metadata_set);
+		}
+	    }
+
+	    selectValue((JComboBox) value_control, initial_value);
+
+	} // end of switch
+
+	// Enable or disable as necessary.
+	if(argument.isRequired() || argument.isAssigned() || is_enabled) {
+	    if (enabled != null) {
+		enabled.setSelected(true);
+	    }
+	    if(value_control != null) {
+		value_control.setOpaque(true);
+		value_control.setBackground(Color.white);
+		value_control.setEnabled(true);
+		if(value_control instanceof JSpinner) {
+		    // Set enabled
+		    JComponent c = ((JSpinner)value_control).getEditor();
+		    if ( c instanceof JSpinner.DefaultEditor ) {
+			JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
+			JFormattedTextField field = editor.getTextField();
+			field.setEditable(true);
+			field.setBackground(Color.white);
+		    }
+		}
+	    }
+	}
+	else {
+	    if (enabled != null) {
+		enabled.setSelected(false);
+	    }
+	    if(value_control != null) {
+		value_control.setOpaque(true);
+		value_control.setBackground(Color.lightGray);
+		value_control.setEnabled(false);
+		if(value_control instanceof JSpinner) {
+		    // Set enabled
+		    JComponent c = ((JSpinner)value_control).getEditor();
+		    if ( c instanceof JSpinner.DefaultEditor ) {
+			JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
+			JFormattedTextField field = editor.getTextField();
+			field.setEditable(false);
+			field.setBackground(Color.lightGray);
+		    }
+		}
+	    }
+	}
+	
+	// Listener
+	if(value_control != null) {
+	    if (argument.getType() != Argument.ENUM) {
+		// enums have already set tooltips based on option value
+		value_control.setToolTipText(tip);
+	    }
+	    add(value_control, BorderLayout.CENTER);
+	    if (!argument.isRequired()) {
+		enabled.addActionListener(new EnabledListener(value_control));
+	    }
+	}
+    }
+    
+    public Argument getArgument() {
+	return argument;
+    }
+
+    public String getArgumentName() {
+	return argument.getName();
+    }
+
+    public String getValue() {
+	if(value_control == null) {
+	    return null;
+	}
+	if (value_control instanceof JSpinner) {
+	    return ((JSpinner)value_control).getValue().toString();
+	}
+	if(value_control instanceof JComboBox) {
+	    Object selected_item = ((JComboBox)value_control).getSelectedItem();
+	    if (selected_item != null) {
+		if (argument.getType() == Argument.METADATA_SET_NAMESPACE) {
+		    return ((MetadataSet) selected_item).getNamespace();
+		}
+		if (selected_item instanceof Argument.ArgumentOption) {
+		    return ((Argument.ArgumentOption)selected_item).name;
+		}
+		if (selected_item instanceof MetadataElement) {
+		    return ((MetadataElement) selected_item).getFullName();
+		}
+		return selected_item.toString();
+	    }    
+	    return null;
+	}
+	if(value_control instanceof JTextField) {
+	    return ((JTextField)value_control).getText();
+	}
+	return null;
+    }
+    /** Retrieve the control used for storing values.
+     * @return JComponent
+     */
+    public JComponent getValueControl() {
+	return value_control;
+    }
+
+    public boolean isEnabled() {
+	if (enabled == null) {
+	    return true; // always enabled
+	} 
+	return enabled.isSelected();
+    }
+
+
+    /** Identifies this control by returning the name of the Argument it is based on.
+     * @return The name of the Argument as a <strong>String</strong>.
+     * @see org.greenstone.gatherer.cdm.Argument
+     */
+    public String toString() {
+	return argument.getName();
+    }
+    /** Updates the enwrapped Argument using the values provided by the controls.
+     * @return <i>true</i> if the update was successful, <i>false</i> otherwise.
+     * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.Argument.ArgumentOption
+     * @see org.greenstone.gatherer.cdm.Language
+     */
+    public boolean updateArgument() {
+	if(argument.isRequired() || enabled.isSelected() ) {
+	    argument.setAssigned(false);
+	    String result = null;
+	    switch(argument.getType()) {
+	    case Argument.ENUM:
+		Argument.ArgumentOption option = (Argument.ArgumentOption)((JComboBox)value_control).getSelectedItem();
+		if(option != null && option.name.length() > 0) {
+		    argument.setValue(option.name);
+		}
+		else {
+		    String args[] = new String[1];
+		    args[0] = argument.getName();
+		    if(argument.isRequired()) {
+			JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
+		    }
+		    // They've left the field blank
+		    else {
+			JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
+			argument.setValue(null);
+		    }
+		    args = null;
+		    return false;
+		}
+		argument.setAssigned(true);
+		return true;
+	    case Argument.FLAG:
+		// Should have already been handled above.
+		argument.setAssigned(true);
+		return true;
+	    case Argument.INTEGER:
+		result = ((JSpinner)value_control).getValue().toString();
+		if(result.length() > 0) {
+		    // Test if the value entered is a valid int.
+		    try {
+			int x = Integer.parseInt(result);
+		    }
+		    catch(NumberFormatException nfe) {
+			String args[] = new String[2];
+			args[0] = argument.getName();
+			args[1] = result;
+			JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.Bad_Integer", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
+			args = null;
+			return false;
+		    }
+		    argument.setValue(result);
+		}
+		else {
+		    String args[] = new String[1];
+		    args[0] = argument.getName();
+		    if(argument.isRequired()) {
+			JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
+		    }
+		    // They've left the field blank
+		    else {
+			JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
+			argument.setValue(null);
+		    }
+		    args = null;
+		    return false;
+		}
+		argument.setAssigned(true);
+		return true;
+	    case Argument.LANGUAGE:
+		String language = (((JComboBox)value_control).getSelectedItem()).toString();
+		argument.setValue(language);
+		// Kinda lucked out here. Its impossible not to choose an entry from these comboboxes as they are restricted.
+		argument.setAssigned(true);
+		return true;
+	    case Argument.METADATUM:
+	    case Argument.METADATA:
+		Object new_value_raw = ((JComboBox) value_control).getSelectedItem();
+		if (new_value_raw instanceof MetadataElement) {
+		    argument.setValue(((MetadataElement) new_value_raw).getFullName());
+		}
+		else {
+		    // But we have to be careful as an arbitary string object could be zero length
+		    String new_value = new_value_raw.toString();
+		    ///ystem.err.println("The current value is: " + new_value);
+		    if(new_value.length() > 0) {
+			argument.setValue(new_value);
+		    }
+		    else {
+			String args[] = new String[1];
+			args[0] = argument.getName();
+			if(argument.isRequired()) {
+			    JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
+			}
+			// They've left the field blank
+			else {
+			    JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
+			    argument.setValue(null);
+			}
+			args = null;
+			return false;
+		    }
+		}
+		argument.setAssigned(true);
+		return true;
+	    case Argument.REGEXP:
+	    case Argument.STRING:
+		result = ((JTextField)value_control).getText();
+		if(result.length() > 0) {
+		    argument.setValue(result);
+		}
+		else {
+		    String args[] = new String[1];
+		    args[0] = argument.getName();
+		    if(argument.isRequired()) {
+			JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.Required_Argument", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
+		    }
+		    // They've left the field blank
+		    else {
+			JOptionPane.showMessageDialog(this, Dictionary.get("CDM.ArgumentConfiguration.No_Value", args), Dictionary.get("CDM.ArgumentConfiguration.Error_Title"), JOptionPane.ERROR_MESSAGE);
+			argument.setValue(null);
+		    }
+		    args = null;
+		    return false;
+		}
+		argument.setAssigned(true);
+		return true;
+	    }
+	    return false;
+	}
+	else {
+	    argument.setAssigned(false);
+	    return true;
+	}
+    }
+
+    
+    public boolean updateArgument(boolean checkRequired) {
+
+      
+	if (checkRequired){
+	    return updateArgument();
+	}
+	else{
+	    if (argument.getType() == Argument.STRING){
+		String result = ((JTextField)value_control).getText();
+               
+		if(result.length() > 0) {
+		    argument.setValue(result);
+                    argument.setAssigned(true);                    
+		}
+	    }	
+	}
+
+	return true;
+	
+    }
+      
+    
+
+    /** Method to ensure that a certain value is selected, if it exists within that combobox to begin with.
+     * @param combobox The <strong>JComboBox</strong> whose selection we are trying to preset.
+     * @param target The desired value of the selection as a <strong>String</strong>.
+     * @return true if the item was found and selected, false otherwise
+     * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.Argument.ArgumentOption
+     */
+    public static boolean selectValue(JComboBox combobox, String target)
+    {
+	for (int i = 0; i < combobox.getItemCount(); i++) {
+	    Object object = combobox.getItemAt(i);
+
+	    if (object instanceof Argument.ArgumentOption) {
+		Argument.ArgumentOption opt = (Argument.ArgumentOption) object;
+		if (opt.name.startsWith(target)) {
+		    combobox.setSelectedIndex(i);
+		    combobox.setToolTipText(opt.getToolTip());
+		    return true;
+		}
+	    }
+	    else if (object instanceof MetadataElement) {
+		if(((MetadataElement)object).getFullName().equals(target)) {
+		    combobox.setSelectedIndex(i);
+		    return true;
+		}
+	    }
+	    else if (object.toString().equals(target)) {
+		combobox.setSelectedIndex(i);
+		return true;
+	    }
+	}
+
+	return false;
+    }
+
+
+    /** Forces the control into an 'enabled' mode. */
+    public void setEnabled() {
+	enabled.setSelected(true);
+    }
+    /** Explicitly sets the value of a JTextField type control to the given String.
+     * @param value_str The new value of the control as a <strong>String</strong>.
+     */
+    public void setValue(String value_str) {
+	((JTextField)value_control).setText(value_str);
+    }
+
+    /** Listens for actions apon the enable checkbox, and if detected enables or diables control appropriately. */
+    private class EnabledListener
+	implements ActionListener {
+	/** An editor component, such as a JComboBox or JTextField, that might have its enabled state changed by this listener. */
+	private JComponent target = null;
+	
+	/** Constructor. */
+	public EnabledListener(JComponent target) {
+	    this.target = target;
+	}
+	
+	/** Any implementation of ActionListener must include this method so that we can be informed when an action has been performed on or registered check box, prompting us to change the state of the other controls as per the users request.
+	 * @param event An <strong>ActionEvent</strong> containing information about the click.
+	 */
+	public void actionPerformed(ActionEvent event) {
+	    if (this.target == null) {
+		return;
+	    }
+	    JCheckBox source = (JCheckBox)event.getSource();
+	    if(source.isSelected()) {
+		target.setBackground(Color.white);
+		target.setEnabled(true);
+	    }
+	    else {
+		target.setBackground(Color.lightGray);
+		target.setEnabled(false);
+	    }
+	    // Special case of stupid JSpinners who don't let their backgrounds change properly.
+	    if(target instanceof JSpinner) {
+		JSpinner spinner = (JSpinner) target;
+		JComponent c = spinner.getEditor();
+		if ( c instanceof JSpinner.DefaultEditor ) {
+		    JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
+		    JFormattedTextField field = editor.getTextField();
+		    field.setEditable(source.isSelected());
+		    if(source.isSelected()) {
+			field.setBackground(Color.white);
+		    }
+		    else {
+			field.setBackground(Color.lightGray);
+		    }
+		}
+	    }
+	}
+    }
+    
+
+    /** Listener that sets the tooltip associated to a combobox to the tooltip relevant to the selected item. */
+    private class ToolTipUpdater
+	implements ActionListener {
+	/** Any implementation of an ActionListener must include this method so that we can be informed when the selection in a combobox has changed and update the tooltip accordingly.
+	 * @param event An <strong>ActionEvent</strong> containing information about the action that fired this call.
+	 */
+	public void actionPerformed(ActionEvent event) {
+	    JComboBox source = (JComboBox)event.getSource();
+	    Object object = source.getSelectedItem();
+	    if(object instanceof Argument.ArgumentOption) {
+		Argument.ArgumentOption opt = (Argument.ArgumentOption)object;
+		if(opt != null) {
+		    source.setToolTipText(opt.getToolTip());
+		}
+		else {
+		    source.setToolTipText(StaticStrings.EMPTY_STR);
+		}
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/BuildTypeManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/BuildTypeManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/BuildTypeManager.java	(revision 13928)
@@ -0,0 +1,279 @@
+package org.greenstone.gatherer.cdm;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.util.EventListener;
+import javax.swing.event.EventListenerList;
+
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.gui.GLIButton;
+import org.greenstone.gatherer.gui.ModalDialog;
+
+public class BuildTypeManager {
+
+    /** The size of this new collection dialog box. */
+    static private Dimension DIALOG_SIZE = new Dimension(600, 280);
+
+    static final public String BUILD_TYPE_MG = "mg";
+    static final public String BUILD_TYPE_MGPP = "mgpp";
+    static final public String BUILD_TYPE_LUCENE = "lucene";
+
+    static final public String BUILD_TYPE_MG_STR = "MG";
+    static final public String BUILD_TYPE_MGPP_STR = "MGPP";
+    static final public String BUILD_TYPE_LUCENE_STR = "Lucene";
+    
+    static final public String[] BUILD_TYPES = {  BUILD_TYPE_MGPP, BUILD_TYPE_MG, BUILD_TYPE_LUCENE };
+
+    private EventListenerList listeners = null;
+    /** the buildtype element in the config file - uses CollectionMeta */
+    public CollectionMeta build_type_meta = null;
+    private Control controls = null;
+
+    protected BuildTypeManager manager = null;
+    public BuildTypeManager() {
+	build_type_meta = new CollectionMeta(CollectionDesignManager.collect_config.getBuildType());
+	if (getBuildType().equals("")) {
+	    build_type_meta.setValue(BUILD_TYPE_MG);
+	    // must have an old collection, assume MG
+	}
+	listeners = new EventListenerList();
+	manager = this;
+    }
+
+    public void addBuildTypeListener(BuildTypeListener listener) {
+	listeners.add(BuildTypeListener.class, listener);
+    }
+    
+    protected void notifyListeners(String new_build_type) {
+	Object[] concerned = listeners.getListenerList();
+	for(int i = 0; i < concerned.length ; i++) {
+	    if(concerned[i] == BuildTypeListener.class) {
+		((BuildTypeListener)concerned[i+1]).buildTypeChanged(new_build_type);
+	    }
+	}
+	concerned = null;
+    }
+    
+	
+    public void promptForNewBuildType() {
+
+	BuildTypePrompt btp = new BuildTypePrompt(build_type_meta.getValue(CollectionMeta.TEXT));	
+    }
+
+    public boolean isMGPP () {
+
+	return getBuildType().equals(BUILD_TYPE_MGPP);
+    }
+    public boolean isMG () {
+
+	return getBuildType().equals(BUILD_TYPE_MG);
+    }
+    public boolean isLucene () {
+
+	return getBuildType().equals(BUILD_TYPE_LUCENE);
+    }
+
+    
+    public String getBuildType() {
+	return build_type_meta.getValue(CollectionMeta.TEXT);
+    }
+
+    public Control getControls() {
+	if (controls == null) {
+	    controls = new BuildTypeControl();
+	}
+	return controls;
+    }
+
+    public interface BuildTypeListener
+	extends EventListener {
+	public void buildTypeChanged(String new_build_type);
+    }
+
+    private class BuildTypeControl 
+	extends JPanel
+	implements Control, BuildTypeListener {
+
+	JLabel label = null;
+	JButton change_button = null;
+	
+	public BuildTypeControl() {
+	    super();
+	    
+	    JPanel spacer_panel = new JPanel();
+	    
+	    JPanel main_panel = new JPanel();
+	    /* may be CDM.BuildTypeManager.mg, CDM.BuildTYpeManager.mgpp, CDM.BuildTypeManager.lucene */
+	    label = new JLabel(Dictionary.get("CDM.BuildTypeManager.Current_Type", getBuildTypeString(getBuildType())));
+	    change_button = new GLIButton(Dictionary.get("CDM.BuildTypeManager.Change"), Dictionary.get("CDM.BuildTypeManager.Change_Tooltip"));
+	    	    
+	    change_button.addActionListener(new ActionListener() {
+		    public void actionPerformed(ActionEvent event) {
+			promptForNewBuildType();
+		    }
+		});
+
+	    main_panel.setLayout(new BorderLayout(10,10));
+	    main_panel.add(label, BorderLayout.CENTER);
+	    main_panel.add(change_button, BorderLayout.EAST);
+
+	    setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
+	    setLayout(new BorderLayout());
+	    add(spacer_panel, BorderLayout.CENTER);
+	    add(main_panel, BorderLayout.EAST);
+
+	    manager.addBuildTypeListener(this);
+	}
+
+	public void loseFocus() {}
+	public void gainFocus() {}
+	public void destroy() {}
+
+	private String getBuildTypeString(String build_type) {
+	    if (build_type.equals(BUILD_TYPE_MG)) {
+		return BUILD_TYPE_MG_STR;
+	    }
+	    if (build_type.equals(BUILD_TYPE_MGPP)) {
+		return BUILD_TYPE_MGPP_STR;
+	    }
+	    if (build_type.equals(BUILD_TYPE_LUCENE)) {
+		return BUILD_TYPE_LUCENE_STR;
+	    }
+	    return "";
+	}
+
+		
+	public void buildTypeChanged(String new_build_type) {
+	    label.setText(Dictionary.get("CDM.BuildTypeManager.Current_Type", getBuildTypeString(new_build_type)));
+	}
+    }
+    
+    private class BuildTypePrompt 
+	extends ModalDialog {
+	
+	private JDialog self;
+	
+	private JRadioButton mg_button = null;
+	private JRadioButton mgpp_button = null;
+	private JRadioButton lucene_button = null;
+
+	private JTextArea description_textarea = null;
+	
+	JButton ok_button = null;
+	JButton cancel_button = null;
+	
+	public BuildTypePrompt(String current_build_type) {
+	    super(Gatherer.g_man, true);
+	    this.self = this;
+	    setSize(DIALOG_SIZE);
+	    setTitle(Dictionary.get("CDM.BuildTypeManager.Title"));
+	
+	    mg_button = new JRadioButton(BUILD_TYPE_MG_STR);
+	    mg_button.setActionCommand(BUILD_TYPE_MG);
+	    mgpp_button = new JRadioButton(BUILD_TYPE_MGPP_STR);
+	    mgpp_button.setActionCommand(BUILD_TYPE_MGPP);
+	    lucene_button = new JRadioButton(BUILD_TYPE_LUCENE_STR);
+	    lucene_button.setActionCommand(BUILD_TYPE_LUCENE);
+	    
+	    BuildTypeButtonListener btbl = new BuildTypeButtonListener();
+	    mg_button.addActionListener(btbl);
+	    mgpp_button.addActionListener(btbl);
+	    lucene_button.addActionListener(btbl);
+
+	    ButtonGroup build_type_group = new ButtonGroup();
+	    build_type_group.add(mgpp_button);
+	    build_type_group.add(mg_button);
+	    build_type_group.add(lucene_button);
+
+	    if (current_build_type != null) {
+		if (current_build_type.equals(BUILD_TYPE_MGPP)) {
+		    mgpp_button.setSelected(true);
+		} else if (current_build_type.equals(BUILD_TYPE_MG)) {
+		    mg_button.setSelected(true);
+		} else if (current_build_type.equals(BUILD_TYPE_LUCENE)) {
+		    lucene_button.setSelected(true);
+		} 
+	    }
+	    
+	    JPanel radio_pane = new JPanel();
+	    radio_pane.setLayout(new GridLayout(3,1));
+	    radio_pane.add(mgpp_button);
+	    radio_pane.add(mg_button);
+	    radio_pane.add(lucene_button);
+
+	    description_textarea = new JTextArea();
+	    description_textarea.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	    /* may be CDM.BuildTypeManager.mg_Description, CDM.BuildTYpeManager.mgpp_Description, CDM.BuildTypeManager.lucene_Description */
+	    description_textarea.setText(Dictionary.get("CDM.BuildTypeManager."+current_build_type+"_Description"));
+	    description_textarea.setLineWrap(true);
+	    description_textarea.setWrapStyleWord(true);
+	    cancel_button = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("General.Cancel_Tooltip"));
+	    
+	    cancel_button.addActionListener(new ActionListener() {
+		    public void actionPerformed(ActionEvent event) {
+			self.dispose();
+		    }
+		});
+	    
+	    ok_button = new GLIButton(Dictionary.get("General.OK"), Dictionary.get("General.OK_Tooltip"));
+	    
+	    ok_button.addActionListener(new ActionListener() {
+		    public void actionPerformed(ActionEvent event) {
+			String new_build_type = BUILD_TYPE_MGPP;
+			if (mgpp_button.isSelected()) {
+			    new_build_type = BUILD_TYPE_MGPP;
+			} else if (mg_button.isSelected()) {
+			    new_build_type = BUILD_TYPE_MG;
+			} else if (lucene_button.isSelected()) {
+			    new_build_type = BUILD_TYPE_LUCENE;
+			}
+			if (!build_type_meta.getValue(CollectionMeta.TEXT).equals(new_build_type)) {
+			    build_type_meta.setValue(new_build_type);
+			    manager.notifyListeners(new_build_type);
+			}
+			self.dispose();
+		    }
+		});
+	    // tell the CDM that we have (possibly) changed
+	    ok_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
+	    JPanel button_pane = new JPanel();
+	    button_pane.setLayout(new GridLayout(1,2));
+	    button_pane.add(ok_button);
+	    button_pane.add(cancel_button);
+
+	    JPanel content_pane = (JPanel) getContentPane();
+	    content_pane.setOpaque(true);
+	    content_pane.setLayout(new BorderLayout());
+	    content_pane.add(radio_pane, BorderLayout.NORTH);
+	    content_pane.add(new JScrollPane(description_textarea), BorderLayout.CENTER);
+	    content_pane.add(button_pane, BorderLayout.SOUTH);
+
+	    // Center and display.
+	    Dimension screen_size = Configuration.screen_size;
+	    this.setLocation((screen_size.width - DIALOG_SIZE.width) / 2, (screen_size.height - DIALOG_SIZE.height) / 2);
+	    this.setVisible(true); // blocks until the dialog is killed
+	       
+	}
+
+	public void loseFocus() {
+
+	}
+	public void gainFocus() {
+
+	}
+	public void destroy() {
+
+	}
+	
+	private class BuildTypeButtonListener
+	    implements ActionListener {
+
+	    public void actionPerformed(ActionEvent event) {
+		description_textarea.setText(Dictionary.get("CDM.BuildTypeManager."+event.getActionCommand()+"_Description"));
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/Classifier.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/Classifier.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/Classifier.java	(revision 13928)
@@ -0,0 +1,102 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import java.io.*;
+import java.util.*;
+import org.greenstone.gatherer.greenstone.Classifiers;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+import org.w3c.dom.*;
+
+
+/** This class is responsible for storing information from a parsed classinfo.pl call in such a way that it allows easy access to parsed details for the purposes of user design and specification of classifiers.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class Classifier
+    extends ArgumentContainer
+{
+    static final public String CLASSIFIER_PREFIX = "CL";
+
+    private boolean loading_options_failed = false;
+
+
+    /** Constructor used only in DOMProxyListModel initializations.
+     */
+    public Classifier() {
+    }
+
+    
+    public Classifier(Element element, Classifier base_classifier) {
+	super(element, base_classifier);
+    }
+
+
+    /** The assigned classifier constructor.
+     * @param element the DOM Element this classifier is based upon
+     */
+    public DOMProxyListEntry create(Element element) {
+	String classifier_name = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE);
+	// Determine the base classifier from the classifier name
+	Classifier base_classifier = Classifiers.getClassifier(classifier_name, true);
+	Classifier classifier = new Classifier(element, base_classifier);
+	if (base_classifier == null) {
+	    // this is kind of a place holder classifier for one which is invalid. It won't get written out to the config file when its next saved.
+	    classifier.setAssigned(false);
+	}
+	base_classifier = null;
+	classifier_name = null;
+	return classifier;
+    }
+
+
+    public boolean didLoadingOptionsFail()
+    {
+	return loading_options_failed;
+    }
+
+
+    /** Generate the string showing this classifiers position. */
+    public String getPositionString() {
+	String position_string = CLASSIFIER_PREFIX;
+	if(element != null) {
+	    // Determine our place in the collect.cfg file
+	    int position_int = CollectionDesignManager.classifier_manager.indexOf(this) + 1;
+	    if(position_int != -1) {
+		position_string = position_string + position_int;
+	    }
+	}
+	return position_string;
+    }
+
+
+    public void setLoadingOptionsFailed()
+    {
+	this.loading_options_failed = true;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/ClassifierManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/ClassifierManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/ClassifierManager.java	(revision 13928)
@@ -0,0 +1,586 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.util.jar.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import org.apache.xerces.parsers.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.greenstone.Classifiers;
+import org.greenstone.gatherer.gui.DesignPaneHeader;
+import org.greenstone.gatherer.gui.GComboBox;
+import org.greenstone.gatherer.gui.GLIButton;
+import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
+import org.greenstone.gatherer.util.JarTools;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.util.XMLTools;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+
+/** This class is responsible for keeping track of all the classifiers assigned to this collection, and providing methods for adding and removing them.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class ClassifierManager
+    extends DOMProxyListModel
+{
+    /** The controls for editing the contents of this manager. */
+    private Control controls = null;
+
+    private DOMProxyListModel model;
+
+    /** Constructor.
+     * @see org.greenstone.gatherer.cdm.DynamicListModel
+     * @see org.greenstone.gatherer.collection.CollectionManager
+     */
+    public ClassifierManager() {
+	super(CollectionDesignManager.collect_config.getDocumentElement(), StaticStrings.CLASSIFY_ELEMENT, new Classifier());
+	this.model = this;
+	DebugStream.println("ClassifierManager: " + getSize() + " classifiers parsed.");
+
+	// Force the assigned classifiers to be loaded and cached now
+	for (int i = 0; i < getSize(); i++) {
+	    getElementAt(i);
+	}
+    }
+
+
+    /** Retrieve a list of the classifiers that are available to be added to the collection. */
+    private Object[] getAvailableClassifiers()
+    {
+	ArrayList available = new ArrayList();
+
+	// Add all the non-abstract core Greenstone classifiers
+	ArrayList classifiers_list = Classifiers.getClassifiersList();
+	for (int i = 0; i < classifiers_list.size(); i++) {
+	    Classifier classifier = (Classifier) classifiers_list.get(i);
+	    if (!classifier.isAbstract()) {
+		available.add(classifier);
+	    }
+	}
+
+	// Sort the available classifiers into alphabetical order
+	Collections.sort(available);
+
+	return available.toArray();
+    }
+
+
+    /** Method to assign a classifier.
+     * @param classifier The base <strong>Classifier</strong> to assign.
+     * @see org.greenstone.gatherer.cdm.DynamicListModel
+     */
+    private void assignClassifier(Classifier classifier) {
+	if(!contains(classifier)) {
+	    Element element = classifier.getElement();
+	    // Locate where we should insert this new classifier.
+	    Node target_node = CollectionConfiguration.findInsertionPoint(element);
+	    add(root, classifier, target_node);
+	}
+    }
+
+
+    /** Destructor. */
+    public void destroy()
+    {
+	if (controls != null) {
+	    controls.destroy();
+	    controls = null;
+	}
+    }
+
+
+    /** Method to retrieve the classifier with the given index.
+     * @param index The index of the desired classifier as an <i>int</i>.
+     * @return The requested Classifier or <i>null</i> if no such classifier exists.
+     */
+    public Classifier getClassifier(int index) {
+	if(0 <= index && index < getSize()) {
+	    return (Classifier) getElementAt(index);
+	}
+	return null;
+    }
+
+    /** Method to retrieve the control for this manager.
+     * @return the Control for editing classifiers
+     */
+    public Control getControls() {
+	if(controls == null) {
+	    // Build controls
+	    this.controls = new ClassifierControl();
+	}
+	return controls;
+    }
+
+    /** Called when the detail mode has changed which in turn may cause several design elements to be available/hidden
+     * @param mode the new mode as an int
+     */
+    public void modeChanged(int mode) {
+
+    }
+
+
+
+    /** Determine if the Phind classifier has been assigned.
+     * @return true if it has, false otherwise
+     */
+    public boolean isPhindClassifierAssigned() {
+	for(int i = 0; i < getSize(); i++) {
+	    Classifier classifier = (Classifier) getElementAt(i);
+	    if(classifier.getName().equalsIgnoreCase(StaticStrings.PHIND_CLASSIFIER)) {
+		return true;
+	    }
+	    classifier = null;
+	}
+	return false;
+    }
+
+    /** Determine if a DateList classifier has been assigned
+     * @return true if it has, false otherwise
+     */
+    public boolean isDateListClassifierAssigned() {
+	for(int i = 0; i < getSize(); i++) {
+	    Classifier classifier = (Classifier) getElementAt(i);
+	    if(classifier.getName().equalsIgnoreCase(StaticStrings.DATELIST_CLASSIFIER)) {
+		return true;
+	    }
+	    classifier = null;
+	}
+	return false;
+	
+    }
+    /** Method to move a classifier in the list order.
+     * @param classifier the Classifier you want to move.
+     * @param direction true to move the classifier up, false to move it down.
+     * @param all true to move to move all the way, false for a single step.
+     */
+    private void moveClassifier(Classifier classifier, boolean direction, boolean all) {
+	if(getSize() < 2) {
+	    DebugStream.println("Not enough classifiers to allow moving.");
+	    return;
+	}
+	if(all) {
+	    // Move to top
+	    if(direction) {
+		// Remove the moving classifier
+		remove(classifier);
+		// Retrieve the first classifier
+		Classifier first_classifier = (Classifier) getElementAt(0);
+		// Add the moving classifier before the first classifier
+		addBefore(classifier, first_classifier);
+		first_classifier = null;
+	    }
+	    else {
+		// Remove the moving classifier
+		remove(classifier);
+		// And add after last classifier
+		add(getSize(), classifier);
+	    }
+	}
+	else {
+	    // Try to move the classifier one step in the desired direction.
+	    int index = indexOf(classifier);
+	    ///ystem.err.println("Index of " + classifier + " = " + index);
+	    if(direction) {
+		index--;
+		if(index < 0) {
+		    String args[] = new String[2];
+		    args[0] = Dictionary.get("CDM.ClassifierManager.Classifier");
+		    args[1] = classifier.getName();
+		    JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.Move.At_Top", args), Dictionary.get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
+		    return;
+		}
+		remove(classifier);
+		add(index, classifier);
+	    }
+	    else {
+		index++;
+		if(index >= getSize()) {
+		    String args[] = new String[2];
+		    args[0] = Dictionary.get("CDM.ClassifierManager.Classifier_Str");
+		    args[1] = classifier.getName();
+		    JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.Move.At_Bottom", args), Dictionary.get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
+		    return;
+		}
+		remove(classifier);
+		add(index, classifier);
+	    }
+	}
+	
+	// tell the format manager to update the names of its format statements
+	Gatherer.c_man.getCollection().cdm.format_manager.refresh();
+    }
+    
+    /** This method removes an assigned classifier. I was tempted to call it unassign, but remove is more consistant. Note that there is no way to remove a classifier from the library.
+     * @param classifier The Classifier to remove
+     * @see org.greenstone.gatherer.cdm.DynamicListModel
+     */
+    private void removeClassifier(Classifier classifier) {
+	remove(classifier);
+    }
+
+
+    /** A class which provides controls for assigned and editing classifiers. */
+    private class ClassifierControl
+	extends JPanel
+	implements Control {
+	/** A combobox containing all of the known classifiers, including those that may have already been assigned. */
+	private JComboBox classifier_combobox = null;
+	/** Button for adding classifiers. */
+	private JButton add = null;
+	/** Button for configuring the selected classifier. */
+	private JButton configure = null;
+	private JButton move_down_button;
+	private JButton move_up_button;
+
+	/** Button to remove the selected classifier. */
+	private JButton remove = null;
+
+	/** A list of assigned classifiers. */
+	private JList classifier_list = null;
+
+	/** Constructor.
+	 * @see org.greenstone.gatherer.cdm.ClassifierManager.ClassifierControl.AddListener
+	 * @see org.greenstone.gatherer.cdm.ClassifierManager.ClassifierControl.ConfigureListener
+	 * @see org.greenstone.gatherer.cdm.ClassifierManager.ClassifierControl.RemoveListener
+	 */
+	public ClassifierControl()
+	{
+	    // Create
+	    add = new GLIButton(Dictionary.get("CDM.ClassifierManager.Add"), Dictionary.get("CDM.ClassifierManager.Add_Tooltip"));
+	    
+	    JPanel button_pane = new JPanel();
+	    JPanel central_pane = new JPanel();
+	    
+configure = new GLIButton(Dictionary.get("CDM.ClassifierManager.Configure"), Dictionary.get("CDM.ClassifierManager.Configure_Tooltip"));
+	    configure.setEnabled(false);
+	    
+	    JPanel header_pane = new DesignPaneHeader("CDM.GUI.Classifiers", "classifiers");
+
+	    ClassifierComboboxListener ccl = new ClassifierComboboxListener();
+	    classifier_combobox = new JComboBox(getAvailableClassifiers());
+	    classifier_combobox.setOpaque(!Utility.isMac());
+	    classifier_combobox.setEditable(false);
+	    if(classifier_combobox.getItemCount() > 0) {
+		classifier_combobox.setSelectedIndex(0);
+		ccl.itemStateChanged(new ItemEvent(classifier_combobox, 0, null, ItemEvent.SELECTED));
+	    }
+
+	    JLabel classifier_label = new JLabel(Dictionary.get("CDM.ClassifierManager.Classifier"));
+	    
+	    classifier_list = new JList(model);
+	    classifier_list.setOpaque(true);
+	    classifier_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+	    JLabel classifier_list_label = new JLabel(Dictionary.get("CDM.ClassifierManager.Assigned"));
+	    
+	    classifier_list_label.setOpaque(true);
+	    
+	    JPanel classifier_list_pane = new JPanel();
+	    JPanel classifier_pane = new JPanel();
+	    remove = new GLIButton(Dictionary.get("CDM.ClassifierManager.Remove"), Dictionary.get("CDM.ClassifierManager.Remove_Tooltip"));
+	    remove.setEnabled(false);
+	    
+	    JPanel temp = new JPanel(new BorderLayout());
+
+	    JPanel move_button_pane = new JPanel();
+
+	    move_up_button = new GLIButton(Dictionary.get("CDM.Move.Move_Up"), JarTools.getImage("arrow-up.gif"), Dictionary.get("CDM.Move.Move_Up_Tooltip"));
+	    move_up_button.setEnabled(false);
+	    
+	    move_down_button = new GLIButton(Dictionary.get("CDM.Move.Move_Down"), JarTools.getImage("arrow-down.gif"), Dictionary.get("CDM.Move.Move_Down_Tooltip"));
+	    move_down_button.setEnabled(false);
+	    
+	    // Listeners
+	    add.addActionListener(new AddListener());
+	    classifier_combobox.addItemListener(ccl);
+	    configure.addActionListener(new ConfigureListener());
+	    remove.addActionListener(new RemoveListener());
+	    remove.addActionListener(CollectionDesignManager.buildcol_change_listener);
+	    classifier_list.addMouseListener(new ClickListener());
+	    classifier_list.addListSelectionListener(new ListListener());
+	    ccl = null;
+
+	    MoveListener ml = new MoveListener();
+	    move_down_button.addActionListener(ml);
+	    move_down_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
+	    move_up_button.addActionListener(ml);
+	    move_up_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
+
+	    // Layout
+	    move_button_pane.setLayout(new GridLayout(4,1));
+	    move_button_pane.add(move_up_button);
+	    move_button_pane.add(new JPanel());
+	    move_button_pane.add(new JPanel());
+	    move_button_pane.add(move_down_button);
+
+	    classifier_list_label.setBorder(BorderFactory.createEmptyBorder(0,2,0,2));
+
+	    classifier_list_pane.setLayout(new BorderLayout());
+	    classifier_list_pane.add(classifier_list_label, BorderLayout.NORTH);
+	    classifier_list_pane.add(new JScrollPane(classifier_list), BorderLayout.CENTER);
+	    classifier_list_pane.add(move_button_pane, BorderLayout.EAST);
+
+	    classifier_label.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
+
+	    classifier_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
+	    classifier_pane.setLayout(new BorderLayout(5,0));
+	    classifier_pane.add(classifier_label, BorderLayout.WEST);
+	    classifier_pane.add(classifier_combobox, BorderLayout.CENTER);
+
+	    button_pane.setLayout(new GridLayout(1, 3));
+	    button_pane.add(add);
+	    button_pane.add(configure);
+	    button_pane.add(remove);
+
+	    temp.add(classifier_pane, BorderLayout.NORTH);
+	    temp.add(button_pane, BorderLayout.SOUTH);
+
+	    central_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	    central_pane.setLayout(new BorderLayout());
+	    central_pane.add(classifier_list_pane, BorderLayout.CENTER);
+	    central_pane.add(temp, BorderLayout.SOUTH);
+
+	    setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
+	    setLayout(new BorderLayout());
+	    add(header_pane, BorderLayout.NORTH);
+	    add(central_pane, BorderLayout.CENTER);
+	}
+
+	/** Method which acts like a destructor, tidying up references to persistant objects.
+	 */
+	public void destroy() {
+	    add = null;
+	    classifier_combobox = null;
+	    classifier_list = null;
+	    configure = null;
+	    //instructions = null;
+	    remove = null;
+	}
+
+	public void gainFocus() {
+	}
+
+	public void loseFocus() {
+	}
+
+
+	private class AddListener
+	    implements ActionListener
+	{
+	    public void actionPerformed(ActionEvent event)
+	    {
+		if (classifier_combobox.getSelectedItem() != null) {
+		    // This must be done on a new thread for the remote building code
+		    new AddClassifierTask(classifier_combobox.getSelectedItem().toString()).start();
+		}
+	    }
+	}
+
+
+	private class AddClassifierTask
+	    extends Thread
+	{
+	    private String classifier_name;
+
+	    public AddClassifierTask(String classifier_name)
+	    {
+		this.classifier_name = classifier_name;
+	    }
+
+	    public void run()
+	    {
+		// Retrieve the classifier
+		Classifier classifier = Classifiers.getClassifier(classifier_name, true);
+		if (classifier == null) {
+		    System.err.println("Error: getClassifier() returned null.");
+		    return;
+		}
+
+		// Create a new element in the DOM
+		Element new_classifier_element = CollectionConfiguration.createElement(StaticStrings.CLASSIFY_ELEMENT);
+		new_classifier_element.setAttribute(StaticStrings.TYPE_ATTRIBUTE, classifier.getName());
+		Classifier new_classifier = new Classifier(new_classifier_element, classifier);
+
+		ArgumentConfiguration ac = new ArgumentConfiguration(new_classifier);
+		ac.addOKButtonActionListener(CollectionDesignManager.buildcol_change_listener);
+		if (ac.display()) {
+		    assignClassifier(new_classifier);
+		    classifier_list.setSelectedValue(new_classifier, true);
+		}
+	    }
+	}
+
+
+	/** This listener reacts to changes in the current selection of the classifier combobox. */
+	private class ClassifierComboboxListener
+	    implements ItemListener {
+	    /** When a user selects a certain classifier, update the tooltip to show the classifier description. */
+	    public void itemStateChanged(ItemEvent event) {
+		if(event.getStateChange() == ItemEvent.SELECTED) {
+		    // Retrieve the selected classifier
+		    Classifier current_selection = (Classifier) classifier_combobox.getSelectedItem();
+		    // And reset the tooltip. 
+		    classifier_combobox.setToolTipText(Utility.formatHTMLWidth(current_selection.getDescription(), 40));
+		    current_selection = null;
+		}
+	    }
+	}
+
+
+	/** Listens for double clicks apon the list and react as if the configure button was pushed. */
+	private class ClickListener
+	    extends MouseAdapter {
+	    /** Called whenever the mouse is clicked over a registered component, we use this to chain through to the configure prompt.
+	     * @param event A <strong>MouseEvent</strong> containing information about the mouse click.
+	     */
+	    public void mouseClicked(MouseEvent event) {
+		if(event.getClickCount() == 2 ) {
+		    if(!classifier_list.isSelectionEmpty()) {
+			Classifier classifier = (Classifier) classifier_list.getSelectedValue();
+			ArgumentConfiguration ac = new ArgumentConfiguration(classifier);
+			ac.addOKButtonActionListener(CollectionDesignManager.buildcol_change_listener);
+			if (ac.display()) {
+			    refresh(classifier);
+			}
+			ac.destroy();
+			ac = null;
+		    }
+		}
+	    }
+	}
+
+	/** This class listens for actions upon the configure button in the controls, and if detected creates a new ArgumentConfiguration dialog box to allow for configuration.
+	 */
+	private class ConfigureListener
+	    implements ActionListener {
+	    /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls.
+	     * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
+	     * @see org.greenstone.gatherer.cdm.ArgumentConfiguration
+	     * @see org.greenstone.gatherer.cdm.Classifier
+	     */
+	    public void actionPerformed(ActionEvent event) {
+		if(!classifier_list.isSelectionEmpty()) {
+		   Classifier classifier = (Classifier) classifier_list.getSelectedValue();
+		   ArgumentConfiguration ac = new ArgumentConfiguration(classifier);
+		   ac.addOKButtonActionListener(CollectionDesignManager.buildcol_change_listener);
+		   if (ac.display()) {
+		       refresh(classifier);
+		   }
+		   ac.destroy();
+		   ac = null;
+		}
+	    }
+	}
+
+	/** listens for changes in the list selection and enables the configure and remove buttons if there is a selection, disables them if there is no selection */
+	private class ListListener
+	    implements ListSelectionListener {
+
+	    public void valueChanged(ListSelectionEvent e) {
+		if (!e.getValueIsAdjusting()) { // we get two events for one change in list selection - use the false one ( the second one)
+		    if (classifier_list.isSelectionEmpty()) {
+			move_up_button.setEnabled(false);
+			move_down_button.setEnabled(false);
+			configure.setEnabled(false);
+			remove.setEnabled(false);
+		    }
+		    else {
+			configure.setEnabled(true);
+			remove.setEnabled(true);
+			int selected_index = classifier_list.getSelectedIndex();
+			move_up_button.setEnabled(selected_index !=0);
+			move_down_button.setEnabled(selected_index != model.getSize()-1);
+		    }
+		}
+	    }
+	}
+
+	/** Listens for actions apon the move buttons in the manager controls, and if detected calls the <i>moveClassifier()</i> method of the manager with the appropriate details. */
+	private class MoveListener
+	    implements ActionListener {
+	    /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls.
+	     * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
+	     */
+	    public void actionPerformed(ActionEvent event) {
+		if(!classifier_list.isSelectionEmpty()) {
+		    Object object = classifier_list.getSelectedValue();
+		    if(object instanceof Classifier) {
+			Classifier classifier = (Classifier) object;
+			if(event.getSource() == move_up_button) {
+			    moveClassifier(classifier, true, false);
+			}
+			else if(event.getSource() == move_down_button) {
+			    moveClassifier(classifier, false, false);
+			}
+			classifier_list.setSelectedValue(classifier, true);
+		    }
+		}
+	    }
+	}
+
+	/** This class listens for actions upon the remove button in the controls, and if detected calls the <i>removeClassifier()</i> method.
+	 */
+	private class RemoveListener
+	    implements ActionListener {
+	    /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls.
+	     * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
+	     */
+	    public void actionPerformed(ActionEvent event) {
+		if(classifier_list.isSelectionEmpty()) {
+		    remove.setEnabled(false);
+		    return;
+		}
+		int selected_index = classifier_list.getSelectedIndex();
+		Object selected_classifier = classifier_list.getSelectedValue();
+		if (!(selected_classifier instanceof Classifier)) {
+		    return; // what else could we have here???
+		}
+		removeClassifier((Classifier)selected_classifier);
+
+		if (selected_index >= classifier_list.getModel().getSize()) {
+		    selected_index--;
+		}
+		if (selected_index >=0) {
+		    classifier_list.setSelectedIndex(selected_index);
+		} else {
+		    // no more classifiers in the list
+		    remove.setEnabled(false);
+		}
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/CollectionConfiguration.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/CollectionConfiguration.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/CollectionConfiguration.java	(revision 13928)
@@ -0,0 +1,1784 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.greenstone.LocalLibraryServer;
+import org.greenstone.gatherer.gui.GLIButton;
+import org.greenstone.gatherer.metadata.MetadataElement;
+import org.greenstone.gatherer.metadata.MetadataSetManager;
+import org.greenstone.gatherer.metadata.MetadataTools;
+import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
+import org.greenstone.gatherer.util.DOMTree;
+import org.greenstone.gatherer.util.Codec;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.XMLTools;
+import org.w3c.dom.*;
+
+/** This class provides access to an xml-type view of the collect.cfg file. This is useful as it allows the manipulation and free form editing of a collect.cfg file while still allowing the various CDM data managers to base themselves directly on this model (whereas they used to be independant ListModels which clobbered the ordering of unparsed commands).
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3d
+ */
+public class CollectionConfiguration
+{
+    static final private String ENCODING = "UTF-8";
+    static final private String NEWLINE_ELEMENT = "NewLine";
+
+    static private Document document;
+    static private StringBuffer saved_collect_cfg_string_buffer = null;
+
+
+    static public Element createElement(String element_name)
+    {
+	return document.createElement(element_name);
+    }
+
+
+    /** Find the best insertion position for the given DOM Element. This should try to match command tag, and if found should then try to group by name or type (eg CollectionMeta), or append to end is no such grouping exists (eg Plugins). Failing a command match it will check against the command order for the best insertion location.
+     * @param target_element the command Element to be inserted
+     * @return the Element which the given command should be inserted before, or null to append to end of list
+     */
+    static public Node findInsertionPoint(Element target_element) {
+	///ystem.err.println("Find insertion point: " + target_element.getNodeName());
+	String target_element_name = target_element.getNodeName();
+	Element document_element = document.getDocumentElement();
+	// Try to find commands with the same tag.
+	NodeList matching_elements = document_element.getElementsByTagName(target_element_name);
+	// If we found matching elements, then we have our most likely insertion location, so check within for groupings
+	if(matching_elements.getLength() != 0) {
+	    ///ystem.err.println("Found matching elements.");
+	    // Only CollectionMeta are grouped.
+	    if(target_element_name.equals(StaticStrings.COLLECTIONMETADATA_ELEMENT)) {
+		///ystem.err.println("Dealing with collection metadata");
+		// Special case: CollectionMeta can be added at either the start or end of a collection configuration file. However the start position is reserved for special metadata, so if no non-special metadata can be found we must append to the end.
+		// So if the command to be added is special add it immediately after any other special command
+		if(target_element.getAttribute(StaticStrings.SPECIAL_ATTRIBUTE).equals(StaticStrings.TRUE_STR)) {
+		    int index = 0;
+		    Element matched_element = (Element) matching_elements.item(index);
+		    Element sibling_element = (Element) matched_element.getNextSibling();
+		    while(sibling_element.getAttribute(StaticStrings.SPECIAL_ATTRIBUTE).equals(StaticStrings.TRUE_STR)) {
+			index++;
+			matched_element = (Element) matching_elements.item(index);
+			sibling_element = (Element) matched_element.getNextSibling();
+		    }
+		    if(sibling_element.getNodeName().equals(NEWLINE_ELEMENT)) {
+			Element newline_element = document.createElement(NEWLINE_ELEMENT);
+			document_element.insertBefore(newline_element, sibling_element);
+		    }
+		    return sibling_element;
+		}
+		// Otherwise try to find a matching 'name' and add after the last one in that group.
+		else {
+		    int index = 0;
+		    target_element_name = target_element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
+		    boolean found = false;
+		    // Skip all of the special metadata
+		    Element matched_element = (Element) matching_elements.item(index);
+		    while(matched_element.getAttribute(StaticStrings.SPECIAL_ATTRIBUTE).equals(StaticStrings.TRUE_STR)) {
+			index++;
+			matched_element = (Element) matching_elements.item(index);
+		    }
+		    // Begin search
+		    while(!found && matched_element != null) {
+			if(matched_element.getAttribute(StaticStrings.NAME_ATTRIBUTE).equals(target_element_name)) {
+			    found = true;
+			}
+			else {
+			    index++;
+			    matched_element = (Element) matching_elements.item(index);
+			}
+		    }
+		    // If we found a match, we need to continue checking until we find the last name match.
+		    if(found) {
+			index++;
+			Element previous_sibling = matched_element;
+			Element sibling_element = (Element) matching_elements.item(index);
+			while(sibling_element != null && sibling_element.getAttribute(StaticStrings.NAME_ATTRIBUTE).equals(target_element_name)) {
+			    previous_sibling = sibling_element;
+			    index++;
+			    sibling_element = (Element) matching_elements.item(index);
+			}
+			// Previous sibling now holds the command immediately before where we want to add, so find its next sibling and add to that. In this one case we can ignore new lines!
+			return previous_sibling.getNextSibling();
+		    }
+		    // If not found we just add after last metadata element
+		    else {
+			Element last_element = (Element) matching_elements.item(matching_elements.getLength() - 1);
+			return last_element.getNextSibling();
+		    }
+		}
+
+	    }
+	    else {
+		///ystem.err.println("Not dealing with collection meta.");
+		Element matched_element = (Element) matching_elements.item(matching_elements.getLength() - 1);
+		// One final quick test. If the matched element is immediately followed by a NewLine command, then we insert another NewLine after the matched command, then return the NewLine instead (thus the about to be inserted command will be placed between the two NewLines)
+		Node sibling_element = matched_element.getNextSibling();
+		if(sibling_element != null && sibling_element.getNodeName().equals(NEWLINE_ELEMENT)) {
+		    Element newline_element = document.createElement(NEWLINE_ELEMENT);
+		    document_element.insertBefore(newline_element, sibling_element);
+		}
+		return sibling_element; // Note that this may be null
+	    }
+	}
+	///ystem.err.println("No matching elements found.");
+	// Locate where this command is in the ordering
+	int command_index = -1;
+	for(int i = 0; command_index == -1 && i < COMMAND_ORDER.length; i++) {
+	    if(COMMAND_ORDER[i].equals(target_element_name)) {
+		command_index = i;
+	    }
+	}
+	///ystem.err.println("Command index is: " + command_index);
+	// Now move forward, checking for existing elements in each of the preceeding command orders.
+	int preceeding_index = command_index - 1;
+	///ystem.err.println("Searching before the target command.");
+	while(preceeding_index >= 0) {
+	    matching_elements = document_element.getElementsByTagName(COMMAND_ORDER[preceeding_index]);
+	    // If we've found a match
+	    if(matching_elements.getLength() > 0) {
+		// We add after the last element
+		Element matched_element = (Element) matching_elements.item(matching_elements.getLength() - 1);
+		// One final quick test. If the matched element is immediately followed by a NewLine command, then we insert another NewLine after the matched command, then return the NewLine instead (thus the about to be inserted command will be placed between the two NewLines)
+		Node sibling_element = matched_element.getNextSibling();
+		if(sibling_element != null && sibling_element.getNodeName().equals(NEWLINE_ELEMENT)) {
+		    Element newline_element = document.createElement(NEWLINE_ELEMENT);
+		    document_element.insertBefore(newline_element, sibling_element);
+		}
+		return sibling_element; // Note that this may be null
+	    }
+	    preceeding_index--;
+	}
+	// If all that fails, we now move backwards through the commands
+	int susceeding_index = command_index + 1;
+	///ystem.err.println("Searching after the target command.");
+	while(susceeding_index < COMMAND_ORDER.length) {
+	    matching_elements = document_element.getElementsByTagName(COMMAND_ORDER[susceeding_index]);
+	    // If we've found a match
+	    if(matching_elements.getLength() > 0) {
+		// We add before the first element
+		Element matched_element = (Element) matching_elements.item(0);
+		// One final quick test. If the matched element is immediately preceeded by a NewLine command, then we insert another NewLine before the matched command, then return this new NewLine instead (thus the about to be inserted command will be placed between the two NewLines)
+		Node sibling_element = matched_element.getPreviousSibling();
+		if(sibling_element != null && sibling_element.getNodeName().equals(NEWLINE_ELEMENT)) {
+		    Element newline_element = document.createElement(NEWLINE_ELEMENT);
+		    document_element.insertBefore(newline_element, sibling_element);
+		}
+		return sibling_element; // Note that this may be null
+	    }
+	    susceeding_index++;
+	}
+	// Well. Apparently there are no other commands in this collection configuration. So append away...
+	return null;
+    }
+
+
+    static public NodeList getElementsByTagName(String element_name)
+    {
+	return document.getDocumentElement().getElementsByTagName(element_name);
+    }
+
+
+    static public String toString(Element command_element, boolean show_extracted_namespace) {
+	String command_element_name = command_element.getNodeName();
+	if(command_element_name.equals(StaticStrings.CLASSIFY_ELEMENT)) {
+	    return classifyToString(command_element, show_extracted_namespace);
+	}
+	else if(command_element_name.equals(StaticStrings.FORMAT_ELEMENT)) {
+	    return formatToString(command_element, show_extracted_namespace);
+	}
+	else if(command_element_name.equals(StaticStrings.INDEXES_ELEMENT)) {
+	    return indexesToString(command_element, show_extracted_namespace);
+	}
+	else if(command_element_name.equals(StaticStrings.INDEX_DEFAULT_ELEMENT)) {
+	    return indexDefaultToString(command_element, show_extracted_namespace);
+	}
+	else if(command_element_name.equals(StaticStrings.LANGUAGES_ELEMENT)) {
+	    return languagesToString(command_element);
+	}
+	else if(command_element_name.equals(StaticStrings.LANGUAGE_DEFAULT_ELEMENT)) {
+	    return languageDefaultToString(command_element);
+	}
+	else if (command_element_name.equals(StaticStrings.LANGUAGE_METADATA_ELEMENT)) {
+	    return languageMetadataToString(command_element, show_extracted_namespace);
+	}
+	else if(command_element_name.equals(StaticStrings.INDEXOPTIONS_ELEMENT)) {
+	    return indexOptionsToString(command_element);
+	}
+	else if(command_element_name.equals(StaticStrings.INDEXOPTION_DEFAULT_ELEMENT)) {
+	    return indexOptionDefaultToString(command_element);
+	}
+	else if(command_element_name.equals(StaticStrings.COLLECTIONMETADATA_ELEMENT)) {
+	    return metadataToString(command_element, show_extracted_namespace);
+	}
+	else if(command_element_name.equals(StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT)) {
+	    return metadataToString(command_element, show_extracted_namespace);
+	}
+	else if(command_element_name.equals(StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT)) {
+	    return metadataToString(command_element, show_extracted_namespace);
+	}
+	else if(command_element_name.equals(StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT)) {
+	    return metadataToString(command_element, show_extracted_namespace);
+	}
+	else if (command_element_name.equals(StaticStrings.BUILDTYPE_ELEMENT)) {
+	    return metadataToString(command_element, show_extracted_namespace);
+	}
+	else if(command_element_name.equals(StaticStrings.PLUGIN_ELEMENT)) {
+	    return pluginToString(command_element, show_extracted_namespace);
+	}
+	else if(command_element_name.equals(StaticStrings.SUBCOLLECTION_ELEMENT)) {
+	    return subcollectionToString(command_element, show_extracted_namespace);
+	}
+	else if(command_element_name.equals(StaticStrings.SUBCOLLECTION_DEFAULT_INDEX_ELEMENT)) {
+	    return subcollectionDefaultIndexToString(command_element);
+	}
+	else if(command_element_name.equals(StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT)) {
+	    return subcollectionIndexesToString(command_element);
+	}
+	else if(command_element_name.equals(StaticStrings.SUPERCOLLECTION_ELEMENT)) {
+	    return supercollectionToString(command_element);
+	}
+	else if(command_element_name.equals(StaticStrings.UNKNOWN_ELEMENT)) {
+	    return unknownToString(command_element);
+	}
+	return "";
+    }
+
+    /** Parses arguments from a tokenizer and returns a HashMap of mappings. The tricky bit here is that not all entries in the HashMap are name->value pairs, as some arguments are boolean and are turned on by their presence. Arguments are denoted by a '-' prefix.
+     * @param tokenizer a CommandTokenizer based on the unconsumed portion of a command string
+     * @return a HashMap containing the arguments parsed
+     */
+    static public HashMap parseArguments(CommandTokenizer tokenizer) {
+	HashMap arguments = new HashMap();
+	String name = null;
+	String value = null;
+	while(tokenizer.hasMoreTokens() || name != null) {
+	    // First we retrieve a name if we need one.
+	    if(name == null) {
+		name = tokenizer.nextToken();
+	    }
+	    // Now we attempt to retrieve a value
+	    if(tokenizer.hasMoreTokens()) {
+		value = tokenizer.nextToken();
+		// Test if the value is actually a name, and if so add the name by itself, then put value into name so that it is parsed correctly during the next loop.
+		if(value.startsWith(StaticStrings.MINUS_CHARACTER)) {
+		    arguments.put(name, null);
+		    name = value;
+		}
+		// Otherwise we have a typical name->value pair ready to go
+		else {
+		    arguments.put(name, value);
+		    name = null;
+		}
+	    }
+	    // Otherwise its a binary flag
+	    else {
+		arguments.put(name, null);
+		name = null;
+	    }
+	}
+	return arguments;
+    }
+
+    /** Gives the preferred ordering of commands */
+    static final private String[] COMMAND_ORDER = {StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT, StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT, StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT, StaticStrings.BUILDTYPE_ELEMENT, StaticStrings.PLUGIN_ELEMENT, StaticStrings.INDEXES_ELEMENT, StaticStrings.INDEX_DEFAULT_ELEMENT, StaticStrings.INDEXOPTIONS_ELEMENT, StaticStrings.INDEXOPTION_DEFAULT_ELEMENT, StaticStrings.LANGUAGES_ELEMENT, StaticStrings.LANGUAGE_DEFAULT_ELEMENT, StaticStrings.LANGUAGE_METADATA_ELEMENT, StaticStrings.SUBCOLLECTION_ELEMENT, StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT, StaticStrings.SUBCOLLECTION_DEFAULT_INDEX_ELEMENT, StaticStrings.SUPERCOLLECTION_ELEMENT, StaticStrings.CLASSIFY_ELEMENT, StaticStrings.FORMAT_ELEMENT, StaticStrings.COLLECTIONMETADATA_ELEMENT};
+
+    /** ************************** Public Data Members ***************************/
+
+    /** ************************** Private Data Members ***************************/
+    
+    private File collect_cfg_file;
+
+    /** ************************** Public Methods ***************************/
+
+    public CollectionConfiguration(File collect_cfg_file)
+    {
+	this.collect_cfg_file = collect_cfg_file;
+	// parse the XML template
+	document = XMLTools.parseXMLFile("xml/CollectionConfig.xml", true);
+	parse(collect_cfg_file);
+	
+    }
+
+    /** This debug facility shows the currently loaded collect.cfg or CollectConfig.xml file as a DOM tree. */
+    public void display() {
+	JDialog dialog = new JDialog(Gatherer.g_man, "Collection Configuration", false);
+	dialog.setSize(400,400);
+	JPanel content_pane = (JPanel) dialog.getContentPane();
+	final DOMTree tree = new DOMTree(document);
+	JButton refresh_button = new GLIButton("Refresh Tree");
+	refresh_button.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent event) {
+		    tree.setDocument(document);
+		}
+	    });
+	content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(new JScrollPane(tree), BorderLayout.CENTER);
+	content_pane.add(refresh_button, BorderLayout.SOUTH);
+	dialog.setVisible(true);
+    }
+
+
+    public Element getCreator() {
+	Element element = getOrCreateElementByTagName(StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT, null, null);
+	element.setAttribute(StaticStrings.NAME_ATTRIBUTE, StaticStrings.COLLECTIONMETADATA_CREATOR_STR);
+	element.setAttribute(StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
+	return element;
+    }
+
+    public Element getDocumentElement() {
+	return document.getDocumentElement();
+    }
+
+    public File getFile() {
+	return collect_cfg_file;
+    }
+
+    /** Retrieve or create the languages Element. */
+    public Element getLanguages() {
+	return getOrCreateElementByTagName(StaticStrings.LANGUAGES_ELEMENT, null, null);
+    }
+
+    public Element getLanguageMetadata() {
+	return getOrCreateElementByTagName(StaticStrings.LANGUAGE_METADATA_ELEMENT, null, null);
+    }
+    
+    public Element getLevels() {
+ 	return getOrCreateElementByTagName(StaticStrings.INDEXOPTIONS_ELEMENT, StaticStrings.NAME_ATTRIBUTE, StaticStrings.LEVELS_STR);
+     }
+
+    public Element getLevelDefault() {
+ 	return getOrCreateElementByTagName(StaticStrings.INDEXOPTION_DEFAULT_ELEMENT, StaticStrings.NAME_ATTRIBUTE, StaticStrings.LEVEL_DEFAULT_STR);
+     }
+	
+    public Element getStemOptions() {
+ 	return getOrCreateElementByTagName(StaticStrings.INDEXOPTIONS_ELEMENT, StaticStrings.NAME_ATTRIBUTE, StaticStrings.STEMOPTIONS_STR);
+     }
+	
+    
+    public Element getMaintainer() {
+	Element element = getOrCreateElementByTagName(StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT, null, null);
+	element.setAttribute(StaticStrings.NAME_ATTRIBUTE, StaticStrings.COLLECTIONMETADATA_MAINTAINER_STR);
+	element.setAttribute(StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
+	return element;
+    }
+
+    /** Retrieve or create the indexes Element. Note that this method behaves differently from the other getBlah methods, in that it also has to keep in mind that indexes come in two flavours, MG and MGPP. */
+    public Element getMGIndexes() {
+	return getOrCreateElementByTagName(StaticStrings.INDEXES_ELEMENT, StaticStrings.MGPP_ATTRIBUTE, StaticStrings.FALSE_STR);
+    }
+
+    public Element getMGPPIndexes() {
+	return getOrCreateElementByTagName(StaticStrings.INDEXES_ELEMENT, StaticStrings.MGPP_ATTRIBUTE, StaticStrings.TRUE_STR);
+    }
+
+    public Element getPublic() {
+	Element element = getOrCreateElementByTagName(StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT, null, null);
+	element.setAttribute(StaticStrings.NAME_ATTRIBUTE, StaticStrings.COLLECTIONMETADATA_PUBLIC_STR);
+	element.setAttribute(StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
+	return element;
+    }
+
+    public Element getBuildType() {
+	Element element = getOrCreateElementByTagName(StaticStrings.BUILDTYPE_ELEMENT, null, null);
+	element.setAttribute(StaticStrings.NAME_ATTRIBUTE, StaticStrings.BUILDTYPE_STR);
+	element.setAttribute(StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
+	return element;
+
+    }
+
+    /** Retrieve or create the subindexes Element. */
+    public Element getSubIndexes() {
+	return getOrCreateElementByTagName(StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT, null, null);
+    }
+
+    /** Retrieve or create the supercollections Element. */
+    public Element getSuperCollection() {
+	return getOrCreateElementByTagName(StaticStrings.SUPERCOLLECTION_ELEMENT, null, null);
+    }
+
+    public boolean ready() {
+	return document != null;
+    }
+
+
+    public void saveIfNecessary()
+    {
+	// Convert the collection configuration XML tree to the collect.cfg version
+	StringBuffer collect_cfg_string_buffer = new StringBuffer();
+	NodeList command_elements = document.getDocumentElement().getChildNodes();
+	boolean just_wrote_blank_line = false;  // Prevent two or more blank lines in a row
+	for (int i = 0; i < command_elements.getLength(); i++) {
+	    Node command_node = command_elements.item(i);
+	    if (!(command_node instanceof Element)) {
+		// We're only interested in Elements
+		continue;
+	    }
+	    Element command_element = (Element) command_node;
+
+	    // Handle NewLine elements (blank lines)
+	    if (command_element.getNodeName().equals(NEWLINE_ELEMENT) && !just_wrote_blank_line) {
+		collect_cfg_string_buffer.append("\n");
+		just_wrote_blank_line = true;
+	    }
+
+	    // Anything else we write to file, but only if it has been assigned, except for index and level commands
+	    // (which just get commented out if unassigned -- a side effect of MG & MGPP compatibility)
+	    else if (!command_element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.FALSE_STR) || command_element.getNodeName().equals(StaticStrings.INDEXES_ELEMENT) || command_element.getNodeName().equals(StaticStrings.INDEX_DEFAULT_ELEMENT) || command_element.getNodeName().equals(StaticStrings.INDEXOPTIONS_ELEMENT) || command_element.getNodeName().equals(StaticStrings.INDEXOPTION_DEFAULT_ELEMENT)) {
+		String command;
+		if (command_element.getNodeName().equals(StaticStrings.FORMAT_ELEMENT)) {
+		    // Format statements we write out with ex. still present
+		    command = toString(command_element, true);
+		}
+		else {
+		    command = toString(command_element, false);
+		}
+
+		if (command != null && command.length()> 0 ) {
+		    collect_cfg_string_buffer.append(command + "\n");
+		    just_wrote_blank_line = false;
+		}
+	    }
+	}
+
+	String collect_cfg_string = collect_cfg_string_buffer.toString();
+	String saved_collect_cfg_string = saved_collect_cfg_string_buffer.toString();
+	if (collect_cfg_string.equals(saved_collect_cfg_string)) {
+	    DebugStream.println("Collect.cfg file hasn't changed so no save necessary...");
+	    return;
+	}
+
+	DebugStream.println("Collect.cfg file has changed, saving now...");
+
+	// If we're using the Local Library we must release the collection before writing to the collect.cfg file
+	String collection_name = CollectionManager.getLoadedCollectionName();
+	boolean collection_released = false;
+	if (Gatherer.c_man.built() && LocalLibraryServer.isRunning() == true) {
+	    // Release the collection
+	    LocalLibraryServer.releaseCollection(collection_name);
+	    collection_released = true;
+	}
+
+	// Make a backup of the collect.cfg file
+ 	if (collect_cfg_file.exists()) {
+ 	    File original_file = new File(collect_cfg_file.getParentFile(), StaticStrings.COLLECT_CFG);
+ 	    File backup_file = new File(collect_cfg_file.getParentFile(), "collect.bak");
+ 	    if (backup_file.exists()) {
+ 		backup_file.delete();
+ 	    }
+ 	    if (!original_file.renameTo(backup_file)) {
+ 		System.err.println("Warning: can't rename collect.cfg to collect.bak.");
+ 	    }
+ 	}
+
+ 	try {		
+ 	    OutputStream ostream = new FileOutputStream(collect_cfg_file);
+ 	    Writer file_writer = new OutputStreamWriter(ostream, ENCODING);
+ 	    BufferedWriter buffered_writer = new BufferedWriter(file_writer);
+	    buffered_writer.write(collect_cfg_string);
+ 	    buffered_writer.close();
+
+	    saved_collect_cfg_string_buffer = collect_cfg_string_buffer;
+
+ 	    // If we're using a remote Greenstone server, upload the new collect.cfg file
+ 	    if (Gatherer.isGsdlRemote) {
+ 		RemoteGreenstoneServer.uploadCollectionFile(collection_name, collect_cfg_file);
+ 	    }
+ 	}
+ 	catch (Exception exception) {
+ 	    DebugStream.println("Error in CollectionConfiguration.save(): " + exception);
+ 	    DebugStream.printStackTrace(exception);
+ 	}
+
+	// Now re-add the collection to the Local Library server
+	if (collection_released) {
+	    LocalLibraryServer.addCollection(collection_name);
+	}    
+    }
+
+
+    /** ************************** Private Methods ***************************/
+
+    static private String classifyToString(Element command_element, boolean show_extracted_namespace)
+    {
+	StringBuffer text = new StringBuffer(StaticStrings.CLASSIFY_STR);
+	text.append(StaticStrings.TAB_CHARACTER);
+	text.append(command_element.getAttribute(StaticStrings.TYPE_ATTRIBUTE));
+	NodeList option_elements = command_element.getElementsByTagName(StaticStrings.OPTION_ELEMENT);
+	int option_elements_length = option_elements.getLength();
+	for(int j = 0; j < option_elements_length; j++) {
+	    Element option_element = (Element) option_elements.item(j);
+	    if(option_element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.TRUE_STR)) {
+		text.append(StaticStrings.SPACE_CHARACTER);
+		text.append(StaticStrings.MINUS_CHARACTER);
+		text.append(option_element.getAttribute(StaticStrings.NAME_ATTRIBUTE));
+		String value_str = XMLTools.getValue(option_element);
+
+		// Convert metadata element names to internal names, and remove extracted metadata namespaces
+		if (value_str.length() > 0) {
+		    StringTokenizer string_tokenizer = new StringTokenizer(value_str, ",");
+		    StringBuffer value_buffer = new StringBuffer();
+		    while (string_tokenizer.hasMoreElements()) {
+			String raw_token = (String) string_tokenizer.nextElement();
+			String token = raw_token.trim();
+			MetadataElement metadata_element = MetadataTools.getMetadataElementWithDisplayName(token);
+			if (metadata_element != null) {
+			    token = metadata_element.getFullName();
+			}
+
+			if (token.startsWith(StaticStrings.EXTRACTED_NAMESPACE)) {
+			    token = token.substring(StaticStrings.EXTRACTED_NAMESPACE.length());
+			}
+			value_buffer.append(token);
+			if (string_tokenizer.hasMoreElements()) {
+			    value_buffer.append(",");
+			}
+		    }
+		    value_str = value_buffer.toString();
+		}
+
+		text.append(StaticStrings.SPACE_CHARACTER);
+		if (value_str.indexOf(StaticStrings.SPACE_CHARACTER) == -1) {
+		    text.append(value_str);
+		}
+		else {
+		    text.append(StaticStrings.SPEECH_CHARACTER);
+		    text.append(value_str);
+		    text.append(StaticStrings.SPEECH_CHARACTER);
+		}
+		value_str = null;
+	    }
+	    option_element = null;
+	}
+	option_elements = null;
+	return text.toString();
+    }
+
+    static private String formatToString(Element command_element, boolean show_extracted_namespace) {
+	StringBuffer text = new StringBuffer(StaticStrings.FORMAT_STR);
+	text.append(StaticStrings.SPACE_CHARACTER);
+	text.append(command_element.getAttribute(StaticStrings.NAME_ATTRIBUTE));
+	text.append(StaticStrings.SPACE_CHARACTER);
+	String value_str = command_element.getAttribute(StaticStrings.VALUE_ATTRIBUTE);
+	if(value_str.length() != 0) {
+	    text.append(value_str);
+	}
+	else {
+	    // Remember to encode format string to Greenstone specification
+	    value_str = Codec.transform(XMLTools.getValue(command_element), Codec.DOM_TO_GREENSTONE);
+	    // Remove any references to a namespace for extracted metadata
+	    if (!show_extracted_namespace) {
+		String match_string = "\\[" + MetadataSetManager.EXTRACTED_METADATA_NAMESPACE + "\\.";
+		value_str = value_str.replaceAll(match_string, "[");
+	    }
+
+	    text.append(StaticStrings.SPEECH_CHARACTER);
+	    text.append(value_str);
+	    text.append(StaticStrings.SPEECH_CHARACTER);
+	}
+	value_str = null;
+	return text.toString();
+    }
+
+    /** Retrieve or create the indexes Element. */
+    static private Element getOrCreateElementByTagName(String name, String conditional_attribute, String required_value) {
+	Element document_element = document.getDocumentElement();
+	NodeList elements = document_element.getElementsByTagName(name);
+	int elements_length = elements.getLength();
+	if(elements_length > 0) {
+	    if(conditional_attribute == null) {
+		document_element = null;
+		return (Element) elements.item(0);
+	    }
+	    else {
+		for(int i = 0; i < elements_length; i++) {
+		    Element element = (Element) elements.item(i);
+		    if(element.getAttribute(conditional_attribute).equals(required_value)) {
+			document_element = null;
+			return element;
+		    }
+		    element = null;
+		}
+	    }
+	}
+	// Create the element
+	Element element = document.createElement(name);
+	// If there was a property set it
+	if(conditional_attribute != null) {
+	    element.setAttribute(conditional_attribute, required_value);
+	}
+	Node target_node = findInsertionPoint(element);
+	if(target_node != null) {
+	    document_element.insertBefore(element, target_node);
+	}
+	else {
+	    document_element.appendChild(element);
+	}
+	document_element = null;
+	return element;
+    }
+
+    static private String indexesToString(Element command_element, boolean show_extracted_namespace) {
+	boolean comment_only = false;
+	StringBuffer text = new StringBuffer("");
+	if(command_element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.FALSE_STR)) {
+	    text.append("#");
+	    comment_only = true;
+	}
+	text.append(StaticStrings.INDEX_STR);
+	text.append(StaticStrings.TAB_CHARACTER);
+	if(!comment_only) {
+	    text.append(StaticStrings.TAB_CHARACTER);
+	}
+	NodeList index_elements = command_element.getElementsByTagName(StaticStrings.INDEX_ELEMENT);
+	if (index_elements.getLength() == 0) { // no indexes
+	    return "";
+	}
+	// For each index, write its level, a colon, then concatenate its child content elements into a single comma separated list
+	int index_elements_length = index_elements.getLength();
+	for(int j = 0; j < index_elements_length; j++) {
+	    Element index_element = (Element) index_elements.item(j);
+	    String level_str = index_element.getAttribute(StaticStrings.LEVEL_ATTRIBUTE);
+	    if(level_str.length() > 0) {
+		text.append(level_str);
+		text.append(StaticStrings.COLON_CHARACTER);
+	    }
+	    NodeList content_elements = index_element.getElementsByTagName(StaticStrings.CONTENT_ELEMENT);
+	    int content_elements_length = content_elements.getLength();
+	    // Don't output anything if no indexes are set
+	    if(content_elements_length == 0) {
+		return null;
+	    }
+	    for(int k = 0; k < content_elements_length; k++) {
+		Element content_element = (Element) content_elements.item(k);
+		String name_str = content_element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
+		if(!show_extracted_namespace && name_str.startsWith(StaticStrings.EXTRACTED_NAMESPACE)) {
+		    name_str = name_str.substring(StaticStrings.EXTRACTED_NAMESPACE.length());
+		}
+		text.append(name_str);
+		name_str = null;
+		if(k < content_elements_length - 1) {
+		    text.append(StaticStrings.COMMA_CHARACTER);
+		}
+		content_element = null;
+	    }
+	    if(j < index_elements_length - 1) {
+		text.append(StaticStrings.SPACE_CHARACTER);
+	    }
+	    content_elements = null;
+	    index_element = null;
+	}
+	index_elements = null;
+	return text.toString();
+    }
+
+    static private String indexDefaultToString(Element command_element, boolean show_extracted_namespace) {
+	StringBuffer text = new StringBuffer("");
+	if(command_element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.FALSE_STR)) {
+	    text.append("#");
+	}
+	text.append(StaticStrings.INDEX_DEFAULT_STR);
+	text.append(StaticStrings.TAB_CHARACTER);
+	if (!command_element.getAttribute(StaticStrings.LEVEL_ATTRIBUTE).equals("")) {
+	    text.append(command_element.getAttribute(StaticStrings.LEVEL_ATTRIBUTE));
+	    text.append(StaticStrings.COLON_CHARACTER);
+	}
+	NodeList content_elements = command_element.getElementsByTagName(StaticStrings.CONTENT_ELEMENT);
+	int content_elements_length = content_elements.getLength();
+	for(int j = 0; j < content_elements_length; j++) {
+	    Element content_element = (Element) content_elements.item(j);
+	    String name_str = content_element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
+	    if(!show_extracted_namespace && name_str.startsWith(StaticStrings.EXTRACTED_NAMESPACE)) {
+		name_str = name_str.substring(StaticStrings.EXTRACTED_NAMESPACE.length());
+	    }
+	    text.append(name_str);
+	    name_str = null;
+	    if(j < content_elements_length - 1) {
+		text.append(StaticStrings.COMMA_CHARACTER);
+	    }
+	    content_element = null;
+	}
+	content_elements = null;
+	return text.toString();
+    }
+
+    static private String languagesToString(Element command_element) {
+	StringBuffer text = new StringBuffer(StaticStrings.LANGUAGES_STR);
+	text.append(StaticStrings.TAB_CHARACTER);
+	// Retrieve all the languages and write them out in a space separated list
+	NodeList language_elements = command_element.getElementsByTagName(StaticStrings.LANGUAGE_ELEMENT);
+	int language_elements_length = language_elements.getLength();
+	if(language_elements_length == 0) {
+	    return null;
+	}
+	for(int j = 0; j < language_elements_length; j++) {
+	    Element language_element = (Element) language_elements.item(j);
+	    text.append(language_element.getAttribute(StaticStrings.NAME_ATTRIBUTE));
+	    if(j < language_elements_length - 1) {
+		text.append(StaticStrings.SPACE_CHARACTER);
+	    }
+	}
+	return text.toString();
+    }
+
+    static private String languageDefaultToString(Element command_element) {
+	StringBuffer text = new StringBuffer(StaticStrings.LANGUAGE_DEFAULT_STR);
+	text.append(StaticStrings.TAB_CHARACTER);
+	text.append(command_element.getAttribute(StaticStrings.NAME_ATTRIBUTE));
+	return text.toString();
+    }
+
+    static private String languageMetadataToString(Element command_element, boolean show_extracted_namespace) {
+	if (!command_element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.TRUE_STR)) {
+	    return "";
+	}
+	StringBuffer text = new StringBuffer(StaticStrings.LANGUAGE_METADATA_STR);
+	text.append(StaticStrings.TAB_CHARACTER);
+	String name_str = command_element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
+	if(!show_extracted_namespace && name_str.startsWith(StaticStrings.EXTRACTED_NAMESPACE)) {
+	    name_str = name_str.substring(StaticStrings.EXTRACTED_NAMESPACE.length());
+	}
+	text.append(name_str);
+	return text.toString();
+    }
+    
+    static private String indexOptionsToString(Element command_element) {
+	StringBuffer text = new StringBuffer("");
+	if(command_element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.FALSE_STR)) {
+	    text.append("#");
+	}
+	text.append(command_element.getAttribute(StaticStrings.NAME_ATTRIBUTE));
+	text.append(StaticStrings.TAB_CHARACTER);
+	NodeList content_elements = command_element.getElementsByTagName(StaticStrings.INDEXOPTION_ELEMENT);
+	int content_elements_length = content_elements.getLength();
+	// Don't output anything if no options are set.
+	if(content_elements_length == 0) {
+	    return null;
+	}
+	for(int i = 0; i < content_elements_length; i++) {
+	    Element content_element = (Element) content_elements.item(i);
+	    text.append(content_element.getAttribute(StaticStrings.NAME_ATTRIBUTE));
+	    text.append(StaticStrings.SPACE_CHARACTER);
+	}
+	return text.substring(0, text.length() - 1);
+    }
+
+    static private String indexOptionDefaultToString(Element command_element) {
+	// Don't bother if there is no value
+	if (command_element.getAttribute(StaticStrings.VALUE_ATTRIBUTE).equals("")) {
+	    return "";
+	}
+	StringBuffer text = new StringBuffer("");
+	if(command_element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.FALSE_STR)) {
+	    text.append("#");
+	}
+	text.append(command_element.getAttribute(StaticStrings.NAME_ATTRIBUTE));
+	text.append(StaticStrings.TAB_CHARACTER);
+	text.append(command_element.getAttribute(StaticStrings.VALUE_ATTRIBUTE));
+	return text.toString();
+    }
+    
+    static private String metadataToString(Element command_element, boolean text_value) {
+	// lets first check the value - if its empty, don't bother sticking it in the config file
+	String value_str = XMLTools.getValue(command_element);
+	if (value_str.equals("")) {
+	    return "";
+	}
+	boolean special = false;
+	
+	StringBuffer text = new StringBuffer("");
+	String name_str = command_element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
+	// If the name is one of the special four, we don't write the collectionmeta first. Note maintainer and buildtype are singled out for 'prittying' reasons.
+	if(name_str.equals(StaticStrings.COLLECTIONMETADATA_MAINTAINER_STR)|| name_str.equals(StaticStrings.BUILDTYPE_STR) ) {
+	    text.append(name_str);
+	    text.append(StaticStrings.TAB_CHARACTER);
+	    special = true;
+	}
+	else if (name_str.equals(StaticStrings.COLLECTIONMETADATA_CREATOR_STR) || name_str.equals(StaticStrings.COLLECTIONMETADATA_PUBLIC_STR) ) {
+	    text.append(name_str);
+	    text.append(StaticStrings.TAB_CHARACTER);
+	    text.append(StaticStrings.TAB_CHARACTER);
+	    special = true;
+	}
+	else {
+	    text.append(StaticStrings.COLLECTIONMETADATA_STR);
+	    text.append(StaticStrings.TAB_CHARACTER);
+	    text.append(name_str);
+	    text.append(StaticStrings.SPACE_CHARACTER);
+	    String language_str = command_element.getAttribute(StaticStrings.LANGUAGE_ATTRIBUTE);
+	    text.append(StaticStrings.LBRACKET_CHARACTER);
+	    text.append(StaticStrings.LANGUAGE_ARGUMENT);
+	    text.append(language_str);
+	    text.append(StaticStrings.RBRACKET_CHARACTER);
+	    text.append(StaticStrings.SPACE_CHARACTER);
+	}
+	name_str = null;
+
+	// The value string we retrieved will be encoded for xml, so we now decode it - to text if text_value set. This parameter was originally show_extracted_namespace, but sincethis is only true for 'toString()' commands from within the CDM, its good enough to determine if this toString() will be used to display on screen, or write to collect.cfg
+	if(text_value == CollectionMeta.TEXT) {
+	    value_str = Codec.transform(value_str, Codec.DOM_TO_TEXT);
+	}
+	else {
+	    value_str = Codec.transform(value_str, Codec.DOM_TO_GREENSTONE);
+	}
+
+	// We don't wrap the email addresses in quotes, nor the other special metadata
+	if(special) {
+	    text.append(value_str);
+	}
+	else {
+	    text.append(StaticStrings.SPEECH_CHARACTER);
+	    text.append(value_str);
+	    text.append(StaticStrings.SPEECH_CHARACTER);
+	}
+	value_str = null;
+	return text.toString();
+    }
+
+    /** Parse a collect.cfg into a DOM model representation. 
+     * note we are ignoring 2.39 compatibility now. */
+    private void parse(File collect_cfg_file) {
+	// hack for pre 2.71 compatibility - we need to add in a 
+	// build type if there is not one there
+	boolean search_types_parsed = false;
+	boolean build_types_parsed = false;
+	try {
+	    saved_collect_cfg_string_buffer = new StringBuffer();
+
+	    Element collect_cfg_element = document.getDocumentElement();
+	    // Read in the file one command at a time.
+	    InputStream istream = new FileInputStream(collect_cfg_file);
+	    Reader in_reader = new InputStreamReader(istream, ENCODING);
+	    BufferedReader in = new BufferedReader(in_reader);
+	    String command_str = null;
+	    while((command_str = in.readLine()) != null) {
+		saved_collect_cfg_string_buffer.append(command_str + "\n");
+
+		boolean append_element = true;
+		Element command_element = null;
+		// A command may be broken over several lines.
+		command_str = command_str.trim();
+		boolean eof = false;
+		while(!eof && command_str.endsWith(StaticStrings.NEWLINE_CHARACTER)) {
+		    String next_line = in.readLine();
+		    if(next_line != null) {
+			next_line = next_line.trim();
+			if(next_line.length() > 0) {
+			    // Remove the new line character
+			    command_str = command_str.substring(0, command_str.lastIndexOf(StaticStrings.NEWLINE_CHARACTER));
+			    // And append the next line, which due to the test above must be non-zero length
+			    command_str = command_str + next_line;
+			}
+			next_line = null;
+		    }
+		    // If we've reached the end of the file theres nothing more we can do
+		    else {
+			eof = true;
+		    }
+		}
+		// If there is still a new line character, then we remove it and hope for the best
+		if(command_str.endsWith(StaticStrings.NEWLINE_CHARACTER)) {
+		    command_str = command_str.substring(0, command_str.lastIndexOf(StaticStrings.NEWLINE_CHARACTER));
+		}
+		// Now we've either got a command to parse...
+		if(command_str.length() != 0) {
+		    // Start trying to figure out what it is
+		    //StringTokenizer tokenizer = new StringTokenizer(command_str);
+		    // Instead of a standard string tokenizer I'm going to use the new version of CommandTokenizer, which is not only smart enough to correctly notice speech marks and correctly parse them out, but now also takes the input stream so it can rebuild tokens that stretch over several lines.
+		    CommandTokenizer tokenizer = new CommandTokenizer(command_str, in);
+		    String command_type = tokenizer.nextToken().toLowerCase();
+		    // Why can't you switch on strings eh? We pass it to the various subparsers who each have a bash at parsing the command. If none can parse the command, an unknown element is created
+		    if(command_element == null && command_type.equals(StaticStrings.CLASSIFY_STR)) {
+			command_element = parseClassify(command_str);
+		    }
+		    if(command_element == null && command_type.equals(StaticStrings.FORMAT_STR)) {
+			command_element = parseFormat(tokenizer); // Revised to handle multiple lines
+		    }
+		    if(command_element == null && (command_type.equals(StaticStrings.INDEX_STR)  || command_type.equals(StaticStrings.COMMENTED_INDEXES_STR))) {
+			command_element = parseIndex(command_str);
+		    }
+		    if(command_element == null && (command_type.equals(StaticStrings.INDEX_DEFAULT_STR) || command_type.equals(StaticStrings.COMMENTED_INDEX_DEFAULT_STR))) {
+			
+			command_element = parseIndexDefault(command_str);
+		    }
+		    if(command_element == null && command_type.equals(StaticStrings.LANGUAGES_STR)) {
+			command_element = parseLanguage(command_str);
+		    }
+		    if(command_element == null && command_type.equals(StaticStrings.LANGUAGE_DEFAULT_STR)) {
+			command_element = parseLanguageDefault(command_str);
+		    }
+		    if (command_element == null && command_type.equals(StaticStrings.LANGUAGE_METADATA_STR)) {
+			command_element = parseLanguageMetadata(command_str);
+		    }
+		    if(command_element == null && command_type.equals(StaticStrings.LEVELS_STR)) {
+			command_element = parseIndexOptions(command_str, StaticStrings.LEVELS_STR, true);
+		    }
+		    if (command_element == null && command_type.equals(StaticStrings.COMMENTED_LEVELS_STR)) {
+			command_element = parseIndexOptions(command_str, StaticStrings.LEVELS_STR, false);
+		    }
+		    if(command_element == null && command_type.equals(StaticStrings.LEVEL_DEFAULT_STR)) {
+			command_element = parseIndexOptionDefault(command_str, StaticStrings.LEVEL_DEFAULT_STR, true);
+		    }
+		    if(command_element == null && command_type.equals(StaticStrings.COMMENTED_LEVEL_DEFAULT_STR)) {
+			command_element = parseIndexOptionDefault(command_str, StaticStrings.LEVEL_DEFAULT_STR, false);
+		    }
+		    if (command_element == null && command_type.equals(StaticStrings.STEMOPTIONS_STR)) {
+			command_element = parseIndexOptions(command_str, StaticStrings.STEMOPTIONS_STR, true);
+		    }
+		    if (command_element == null && command_type.equals(StaticStrings.COMMENTED_STEMOPTIONS_STR)) {
+			command_element = parseIndexOptions(command_str, StaticStrings.STEMOPTIONS_STR, false);
+		    }
+		    if(command_element == null && command_type.equals(StaticStrings.COLLECTIONMETADATA_STR)) {
+			command_element = parseMetadata(tokenizer); // Revised to handle multiple lines
+		    }
+		    if(command_element == null && (command_type.equals(StaticStrings.COLLECTIONMETADATA_PUBLIC_STR) || command_type.equals(StaticStrings.COLLECTIONMETADATA_CREATOR_STR) || command_type.equals(StaticStrings.COLLECTIONMETADATA_MAINTAINER_STR) || command_type.equals(StaticStrings.BUILDTYPE_STR))) {
+			command_element = parseMetadataSpecial(command_str);
+			// pre 2.71 hack
+			if (command_type.equals(StaticStrings.BUILDTYPE_STR)) {
+			    build_types_parsed = true;
+			}
+		    }
+		    if(command_element == null && command_type.equals(StaticStrings.PLUGIN_STR)) {
+			command_element = parsePlugin(command_str);
+		    }
+		    // leave here for backwards compatibility
+		    if(command_element == null && command_type.equals(StaticStrings.SEARCHTYPE_STR)) {
+			command_element = parseSearchType(command_str);
+			// pre 2.71 hack
+			search_types_parsed = true;
+			
+		    }
+		    if(command_element == null && command_type.equals(StaticStrings.SUBCOLLECTION_STR)) {
+			command_element = parseSubCollection(command_str);
+		    }
+		    if(command_element == null && command_type.equals(StaticStrings.SUBCOLLECTION_DEFAULT_INDEX_STR)) {
+			command_element = parseSubCollectionDefaultIndex(command_str);
+		    }
+		    if(command_element == null && command_type.equals(StaticStrings.SUBCOLLECTION_INDEX_STR)) {
+			command_element = parseSubCollectionIndex(command_str);
+		    }
+		    if(command_element == null && (command_type.equals(StaticStrings.SUPERCOLLECTION_STR) || command_type.equals(StaticStrings.CCS_STR))) {
+			command_element = parseSuperCollection(command_str);
+		    }
+		    // Doesn't match any known type
+		    command_type = null;
+		    if(command_element == null) {
+			// No-one knows what to do with this command, so we create an Unknown command element
+			command_element = document.createElement(StaticStrings.UNKNOWN_ELEMENT);
+			XMLTools.setValue(command_element, command_str);
+		    }
+		}
+		// Or an empty line to remember for later
+		else {
+		    command_element = document.createElement(NEWLINE_ELEMENT);
+		}
+		// Now command element shouldn't be null so we append it to the collection config DOM, but only if we haven't been told not to add it
+		//if(append_element) {
+		    collect_cfg_element.appendChild(command_element);
+		    //}
+	    }
+	    if (!build_types_parsed) {
+		String buildtype_type = BuildTypeManager.BUILD_TYPE_MG;
+		if (search_types_parsed) {
+		    buildtype_type = BuildTypeManager.BUILD_TYPE_MGPP;
+		}
+		Element command_element = parseMetadataSpecial(StaticStrings.BUILDTYPE_STR+"  "+buildtype_type);
+		Node target_node = findInsertionPoint(command_element);
+		if(target_node != null) {
+		    collect_cfg_element.insertBefore(command_element, target_node);
+		}
+		else {
+		    collect_cfg_element.appendChild(command_element);
+		}
+
+	    }
+	}
+	catch(Exception exception) {
+	    DebugStream.println("Error in CollectionConfiguration.parse(java.io.File): " + exception);
+	    DebugStream.printStackTrace(exception);
+	}
+    }
+    
+ 
+    private Element parseClassify(String command_str) {
+	Element command_element = null;
+	try {
+	    CommandTokenizer tokenizer = new CommandTokenizer(command_str);
+	    // Check the token count. The token count from a command tokenizer isn't guarenteed to be correct, but it does give the maximum number of available tokens according to the underlying StringTokenizer (some of which may actually be append together by the CommandTokenizer as being a single argument).
+	    if(tokenizer.countTokens() >= 2) {  // Must support "classify Phind" (no args)
+		command_element = document.createElement(StaticStrings.CLASSIFY_ELEMENT);
+		// First token is classify
+		tokenizer.nextToken();
+		// The next token is the classifier type
+		command_element.setAttribute(StaticStrings.TYPE_ATTRIBUTE, tokenizer.nextToken());
+		// Now we parse out the remaining arguments into a hashmapping from name to value
+		HashMap arguments = parseArguments(tokenizer);
+		// Assign the arguments as Option elements, but watch out for the metadata argument as we treat that differently
+		Iterator names = arguments.keySet().iterator();
+		while(names.hasNext()) {
+		    String name = (String) names.next();
+		    String value = (String) arguments.get(name); // Can be null
+		    // The metadata argument gets added as the content attribute
+		    if (name.equals(StaticStrings.METADATA_ARGUMENT) && value != null) {
+			// Add the extracted namespace onto un-namespaced metadata names
+			StringTokenizer string_tokenizer = new StringTokenizer(value, ",");
+			value = "";
+			while (string_tokenizer.hasMoreElements()) {
+			    String token = (String) string_tokenizer.nextElement();
+
+			    if (token.indexOf(StaticStrings.NS_SEP) == -1) {
+				token = StaticStrings.EXTRACTED_NAMESPACE + token;
+			    }
+			    else {
+				MetadataElement metadata_element = MetadataTools.getMetadataElementWithName(token);
+				if (metadata_element != null) {
+				    token = metadata_element.getDisplayName();
+				}
+			    }
+
+			    if (!value.equals("")) {
+				value = value + ",";
+			    }
+			    value = value + token;
+			}
+		    }
+		    // Everything else is an Option Element
+		    Element option_element = document.createElement(StaticStrings.OPTION_ELEMENT);
+		    option_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, name.substring(1));
+		    if(value != null) {
+			// Remove any speech marks appended in strings containing whitespace
+			if(value.startsWith(StaticStrings.SPEECH_CHARACTER) && value.endsWith(StaticStrings.SPEECH_CHARACTER)) {
+			    value = value.substring(1, value.length() - 1);
+			}
+			XMLTools.setValue(option_element, value);
+		    }
+		    option_element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+		    command_element.appendChild(option_element);
+		    option_element = null;
+		    name = null;
+		    value = null;
+		}
+		names = null;
+		arguments = null;
+	    }
+	    tokenizer = null;
+	}
+	catch(Exception error) {
+	}
+	return command_element;
+    }
+
+    private Element parseFormat(CommandTokenizer tokenizer) {
+	Element command_element = null;
+	try {
+	    command_element = document.createElement(StaticStrings.FORMAT_ELEMENT);
+	    String name_str = tokenizer.nextToken();
+	    String value_str = tokenizer.nextToken();
+	    if(name_str != null && value_str != null) {
+		command_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, name_str);
+		// If the value is true or false we add it as an attribute
+		if(value_str.equalsIgnoreCase(StaticStrings.TRUE_STR) || value_str.equalsIgnoreCase(StaticStrings.FALSE_STR)) {
+		    command_element.setAttribute(StaticStrings.VALUE_ATTRIBUTE, value_str.toLowerCase());
+		}
+		// Otherwise it gets added as a text node
+		else {
+		    // Ready the value str (which can contain all sorts of funky characters) for writing as a DOM value
+		    value_str = Codec.transform(value_str, Codec.GREENSTONE_TO_DOM);
+		    XMLTools.setValue(command_element, value_str);
+		}
+	    }
+	    else {
+		command_element = null;
+	    }
+	    name_str = null;
+	    value_str = null;
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	    command_element = null;
+	}
+	return command_element;
+    }
+
+    private Element parseIndex(String command_str) {
+	Element command_element = null;
+	try {
+	    StringTokenizer tokenizer = new StringTokenizer(command_str);
+	    String command = tokenizer.nextToken();
+	    command_element = document.createElement(StaticStrings.INDEXES_ELEMENT);
+	    command_element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, (command.equals(StaticStrings.INDEX_STR) ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
+	    command = null;
+	    if(!tokenizer.hasMoreTokens()) {
+
+		// there are no indexes
+		command_element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
+		command_element.setAttribute(StaticStrings.MGPP_ATTRIBUTE, StaticStrings.FALSE_STR); // for now
+		tokenizer = null;
+		return command_element;
+	    }
+
+	    while(tokenizer.hasMoreTokens()) {
+		Element index_element = document.createElement(StaticStrings.INDEX_ELEMENT);
+		String index_str = tokenizer.nextToken();
+		// There are two types of index we have to consider. Old G2.38 and earlier use level:source tuplets while G2.39+ have just a single, non-comma separated list where order is important.
+		boolean old_index;
+		if(index_str.indexOf(StaticStrings.COLON_CHARACTER) != -1) {
+		    old_index = true;
+		    index_element.setAttribute(StaticStrings.LEVEL_ATTRIBUTE, index_str.substring(0, index_str.indexOf(StaticStrings.COLON_CHARACTER)));
+		    index_str = index_str.substring(index_str.indexOf(StaticStrings.COLON_CHARACTER) + 1);
+		    command_element.setAttribute(StaticStrings.MGPP_ATTRIBUTE, StaticStrings.FALSE_STR);
+		}
+		else {
+		    command_element.setAttribute(StaticStrings.MGPP_ATTRIBUTE, StaticStrings.TRUE_STR);
+		    old_index = false;
+		}
+		StringTokenizer content_tokenizer = new StringTokenizer(index_str, StaticStrings.COMMA_CHARACTER);
+		while(content_tokenizer.hasMoreTokens()) {
+		    Element content_element = document.createElement(StaticStrings.CONTENT_ELEMENT);
+		    String content_str = content_tokenizer.nextToken();
+		    // Since the contents of indexes have to be certain keywords, or metadata elements, if the content isn't a keyword and doesn't yet have a namespace, append the extracted metadata namespace.
+		    if(content_str.indexOf(StaticStrings.NS_SEP) == -1) {
+			if(content_str.equals(StaticStrings.TEXT_STR) || (!old_index && content_str.equals(StaticStrings.ALLFIELDS_STR))) {
+				// Our special strings are OK.
+			}
+			else {
+			    content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
+			}
+		    }
+		    content_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, content_str);
+		    index_element.appendChild(content_element);
+		    content_element = null;
+		}
+		content_tokenizer = null;
+		index_str = null;
+		command_element.appendChild(index_element);
+		index_element = null;
+	    }
+	    tokenizer = null;
+	}
+	catch (Exception exception) {
+	    exception.printStackTrace();
+	}
+	return command_element;
+    }
+
+    private Element parseIndexDefault(String command_str) {
+	Element command_element = null;
+       	try {
+	    StringTokenizer tokenizer = new StringTokenizer(command_str);
+	    if(tokenizer.countTokens() >= 2) {
+		command_element = document.createElement(StaticStrings.INDEX_DEFAULT_ELEMENT);                 
+		command_element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, ((tokenizer.nextToken()).equals(StaticStrings.INDEX_DEFAULT_STR) ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
+		String index_str = tokenizer.nextToken();
+                String level="";
+                if (index_str.indexOf(StaticStrings.COLON_CHARACTER) !=-1){
+		    level =  index_str.substring(0, index_str.indexOf(StaticStrings.COLON_CHARACTER));
+		}
+   
+		command_element.setAttribute(StaticStrings.LEVEL_ATTRIBUTE,level);
+                 
+		String content_str = index_str;
+                
+		if (index_str.indexOf(StaticStrings.COLON_CHARACTER) !=-1){
+		    content_str = index_str.substring(index_str.indexOf(StaticStrings.COLON_CHARACTER) + 1);
+		}
+		
+		StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER);
+		while(content_tokenizer.hasMoreTokens()) {
+		    Element content_element = document.createElement(StaticStrings.CONTENT_ELEMENT);
+		    content_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, content_tokenizer.nextToken());
+		    command_element.appendChild(content_element);
+		    content_element = null;
+		}
+		content_tokenizer = null;
+		content_str = null;
+		content_str = null;
+		index_str = null;
+	    }
+	    tokenizer = null;
+	}
+	catch (Exception exception) {
+	}
+	return command_element;
+    }
+
+    private Element parseLanguage(String command_str) {
+	Element command_element = null;
+	try {
+	    StringTokenizer tokenizer = new StringTokenizer(command_str);
+	    tokenizer.nextToken();
+	    if(tokenizer.hasMoreTokens()) {
+		command_element = document.createElement(StaticStrings.LANGUAGES_ELEMENT);
+		while(tokenizer.hasMoreTokens()) {
+		    Element language_element = document.createElement(StaticStrings.LANGUAGE_ELEMENT);
+		    language_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, tokenizer.nextToken());
+		    command_element.appendChild(language_element);
+		    language_element = null;
+		}
+	    }
+	    tokenizer = null;
+	}
+	catch (Exception exception) {
+	}
+	return command_element;
+    }
+
+    private Element parseLanguageDefault(String command_str) {
+	Element command_element = null;
+	try {
+	    StringTokenizer tokenizer = new StringTokenizer(command_str);
+	    if(tokenizer.countTokens() >= 2) {
+		command_element = document.createElement(StaticStrings.LANGUAGE_DEFAULT_ELEMENT);
+		tokenizer.nextToken();
+		String default_language_str = tokenizer.nextToken();
+		command_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, default_language_str);
+		command_element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+		default_language_str = null;
+	    }
+	    tokenizer = null;
+	}
+	catch (Exception exception) {
+	}
+	return command_element;
+    }
+
+    private Element parseLanguageMetadata(String command_str) {
+	Element command_element = null;
+	try {
+	    StringTokenizer tokenizer = new StringTokenizer(command_str);
+	    if(tokenizer.countTokens() >= 2) {
+		command_element = document.createElement(StaticStrings.LANGUAGE_METADATA_ELEMENT);
+		tokenizer.nextToken();
+		String language_metadata_str = tokenizer.nextToken();
+		if (language_metadata_str.indexOf(StaticStrings.NS_SEP) == -1) {
+		    language_metadata_str = StaticStrings.EXTRACTED_NAMESPACE + language_metadata_str;
+		}
+		command_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, language_metadata_str);
+		command_element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+		language_metadata_str = null;
+	    }
+	    tokenizer = null;
+	    
+	}
+	catch (Exception exception) {
+	}
+	return command_element;
+    }
+	
+    private Element parseIndexOptions(String command_str, String type, boolean assigned) {
+	Element command_element = null;
+	try {
+	    StringTokenizer tokenizer = new StringTokenizer(command_str);
+	    // First token is command type 
+	    String command = tokenizer.nextToken();
+	    if(tokenizer.hasMoreTokens()) {
+		command_element = document.createElement(StaticStrings.INDEXOPTIONS_ELEMENT);
+		command_element.setAttribute(StaticStrings.NAME_ATTRIBUTE,type);
+		command_element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, (assigned ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
+		while(tokenizer.hasMoreTokens()) {
+		    Element option_element = document.createElement(StaticStrings.INDEXOPTION_ELEMENT);
+		    option_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, tokenizer.nextToken());
+		    command_element.appendChild(option_element);
+		    option_element = null;
+		}
+	    }
+	    command = null;
+	}
+	catch(Exception exception) {
+	}
+	return command_element;
+    }
+
+    private Element parseIndexOptionDefault(String command_str, String type, boolean assigned) {
+	Element command_element = null;
+	try {
+	    StringTokenizer tokenizer = new StringTokenizer(command_str);
+	    // First token is command type 
+	    String command = tokenizer.nextToken();
+	    if(tokenizer.hasMoreTokens()) {
+		command_element = document.createElement(StaticStrings.INDEXOPTION_DEFAULT_ELEMENT);
+		command_element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, (assigned ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR)); // is it commented out or not?
+		command_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, type);
+		command_element.setAttribute(StaticStrings.VALUE_ATTRIBUTE, tokenizer.nextToken());
+	    }
+	    
+	    tokenizer = null;
+	}
+	catch (Exception exception) {
+	}
+	return command_element;
+    }
+
+    private Element parseMetadata(CommandTokenizer tokenizer) {
+	Element command_element = null;
+	try {
+	    command_element = document.createElement(StaticStrings.COLLECTIONMETADATA_ELEMENT);
+	    String name_str = tokenizer.nextToken();
+	    String value_str = tokenizer.nextToken();
+	    if(name_str != null && value_str != null) {
+		String language_str = Configuration.getLanguage();
+		// Check if the value string is actually a language string
+		if(value_str.startsWith(StaticStrings.LBRACKET_CHARACTER) && value_str.endsWith(StaticStrings.RBRACKET_CHARACTER)) {
+		    language_str = value_str.substring(value_str.indexOf(StaticStrings.LANGUAGE_ARGUMENT) + 2, value_str.length() - 1);
+		    value_str = tokenizer.nextToken();
+		}
+		if(value_str != null) {
+		    // Ready the value str (which can contain all sorts of funky characters) for writing as a DOM value
+		    value_str = Codec.transform(value_str, Codec.GREENSTONE_TO_DOM);
+		    command_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, name_str);
+		    command_element.setAttribute(StaticStrings.LANGUAGE_ATTRIBUTE, language_str);
+		    command_element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+		    XMLTools.setValue(command_element, value_str);
+		}
+		else {
+		    command_element = null;
+		}
+		language_str = null;
+	    }
+	    else {
+		command_element = null;
+	    }
+	    name_str = null;
+	    value_str = null;
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	    command_element = null;
+	}
+	return command_element;
+    }
+
+    private Element parseMetadataSpecial(String command_str) {
+	Element command_element = null;
+	try {
+	    StringTokenizer tokenizer = new StringTokenizer(command_str);
+	    if(tokenizer.countTokens() >= 2) {
+		String name_str = tokenizer.nextToken();
+		String value_str = tokenizer.nextToken();
+		if (name_str.equals(StaticStrings.COLLECTIONMETADATA_CREATOR_STR)) {
+		    command_element = document.createElement(StaticStrings.COLLECTIONMETADATA_CREATOR_ELEMENT);
+		}
+		else if(name_str.equals(StaticStrings.COLLECTIONMETADATA_MAINTAINER_STR)) {
+		    command_element = document.createElement(StaticStrings.COLLECTIONMETADATA_MAINTAINER_ELEMENT);
+		}
+		else if(name_str.equals(StaticStrings.COLLECTIONMETADATA_PUBLIC_STR)) {
+		    command_element = document.createElement(StaticStrings.COLLECTIONMETADATA_PUBLIC_ELEMENT);
+		}
+		else if (name_str.equals(StaticStrings.BUILDTYPE_STR)) {
+		    command_element = document.createElement(StaticStrings.BUILDTYPE_ELEMENT);
+		}
+		if(command_element != null) {
+		    command_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, name_str);
+		    command_element.setAttribute(StaticStrings.LANGUAGE_ATTRIBUTE, StaticStrings.ENGLISH_LANGUAGE_STR);
+		    command_element.setAttribute(StaticStrings.SPECIAL_ATTRIBUTE, StaticStrings.TRUE_STR);
+		    command_element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+		    if(value_str.startsWith(StaticStrings.SPEECH_CHARACTER) && value_str.endsWith(StaticStrings.SPEECH_CHARACTER)) {
+			value_str = value_str.substring(1, value_str.length() - 1);
+		    }
+		    XMLTools.setValue(command_element, value_str);
+		}
+		value_str = null;
+		name_str = null;
+	    }
+	    tokenizer = null;
+	}
+	catch (Exception exception) {
+	}
+	return command_element;
+    }
+
+    private Element parsePlugin(String command_str) {
+	Element command_element = null;
+	try {
+	    CommandTokenizer tokenizer = new CommandTokenizer(command_str);
+	    // Check the token count. The token count from a command tokenizer isn't guarenteed to be correct, but it does give the maximum number of available tokens according to the underlying StringTokenizer (some of which may actually be append together by the CommandTokenizer as being a single argument).
+	    if(tokenizer.countTokens() >= 2) {
+		command_element = document.createElement(StaticStrings.PLUGIN_ELEMENT);
+		// First token is plugin
+		tokenizer.nextToken();
+		// The next token is the type
+		String type = tokenizer.nextToken();
+		command_element.setAttribute(StaticStrings.TYPE_ATTRIBUTE, type);
+		// Now we parse out the remaining arguments into a hashmapping from name to value
+		HashMap arguments = parseArguments(tokenizer);
+		// Assign the arguments as Option elements, but watch out for the metadata argument as we treat that differently
+		// also watch out for the deprecated -use_metadata_files option to RecPlug and remove it
+		Iterator names = arguments.keySet().iterator();
+		while(names.hasNext()) {
+		    String name = (String) names.next();
+		    String value = (String) arguments.get(name); // Can be null
+		    
+		    if(type.equals(StaticStrings.RECPLUG_STR) && name.substring(1).equals(StaticStrings.USE_METADATA_FILES_ARGUMENT)) {
+			continue; // ignore this option
+		    }
+		    Element option_element = document.createElement(StaticStrings.OPTION_ELEMENT);
+		    option_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, name.substring(1));
+		    option_element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+		    if(value != null) {
+			// Remove any speech marks appended in strings containing whitespace
+			if(value.startsWith(StaticStrings.SPEECH_CHARACTER) && value.endsWith(StaticStrings.SPEECH_CHARACTER)) {
+			    value = value.substring(1, value.length() - 1);
+			}
+			if(name.equals(StaticStrings.METADATA_ARGUMENT)) {
+			    // The metadata argument must be the fully qualified name of a metadata element, so if it doesn't yet have a namespace, append the extracted metadata namespace.
+			    if(value.indexOf(StaticStrings.NS_SEP) == -1) {
+				value = StaticStrings.EXTRACTED_NAMESPACE + value;
+      		    }
+			}
+			XMLTools.setValue(option_element, value);
+		    }
+		    command_element.appendChild(option_element);
+		    option_element = null;
+		    name = null;
+		    value = null;
+		}
+
+		type = null;
+		names = null;
+		arguments = null;
+	    }
+	    tokenizer = null;
+	}
+	catch(Exception exception) {
+	}
+	return command_element;
+    }
+
+    /* search types are now handled as formats - leave this here to convert in case we have an old config file */
+    private Element parseSearchType(String command_str) {
+	Element command_element = null;
+	try {
+	    StringTokenizer tokenizer = new StringTokenizer(command_str);
+	    // First token is command type (searchtype)
+	    tokenizer.nextToken();
+	    if(tokenizer.hasMoreTokens()) {
+		command_element = document.createElement(StaticStrings.FORMAT_ELEMENT);
+		command_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, "SearchTypes");
+		String value = tokenizer.nextToken();
+		while(tokenizer.hasMoreTokens()) {
+		    value += ","+tokenizer.nextToken();
+		}
+		value = Codec.transform(value, Codec.GREENSTONE_TO_DOM);
+		XMLTools.setValue(command_element, value);		
+	    }
+	}
+	catch(Exception exception) {
+	}
+	return command_element;
+    }
+
+    private Element parseSubCollection(String command_str) {
+	Element command_element = null;
+	try {
+	    CommandTokenizer tokenizer = new CommandTokenizer(command_str);
+	    if(tokenizer.countTokens() >= 3) {
+		command_element = document.createElement(StaticStrings.SUBCOLLECTION_ELEMENT);
+		// First token is command type
+		tokenizer.nextToken();
+		// Then subcollection identifier
+		command_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, tokenizer.nextToken());
+		// Then finally the pattern used to build the subcollection partition
+		String full_pattern_str = tokenizer.nextToken();
+		// Set inclusion/exclusion flag and remove any exclamation mark
+		boolean exclusion = full_pattern_str.startsWith(StaticStrings.EXCLAMATION_CHARACTER);
+		if (exclusion) {
+		    full_pattern_str = full_pattern_str.substring(1, full_pattern_str.length());
+		    command_element.setAttribute(StaticStrings.TYPE_ATTRIBUTE, StaticStrings.EXCLUDE_STR);
+		}
+		else {
+		    command_element.setAttribute(StaticStrings.TYPE_ATTRIBUTE, StaticStrings.INCLUDE_STR);
+		}
+		StringTokenizer pattern_tokenizer = new StringTokenizer(full_pattern_str, StaticStrings.SEPARATOR_CHARACTER);
+		if(pattern_tokenizer.countTokens() >= 2) {
+		    String content_str = pattern_tokenizer.nextToken();
+		    // Since the contents of indexes have to be certain keywords, or metadata elements, if the content isn't a keyword and doesn't yet have a namespace, append the extracted metadata namespace.
+		    if(!content_str.equals(StaticStrings.FILENAME_STR) && content_str.indexOf(StaticStrings.NS_SEP) == -1) {
+			content_str = StaticStrings.EXTRACTED_NAMESPACE + content_str;
+		    }
+		    command_element.setAttribute(StaticStrings.CONTENT_ATTRIBUTE, content_str);
+		    XMLTools.setValue(command_element, pattern_tokenizer.nextToken());
+		    if(pattern_tokenizer.hasMoreTokens()) {
+			command_element.setAttribute(StaticStrings.OPTIONS_ATTRIBUTE, pattern_tokenizer.nextToken());
+		    }
+		}
+		pattern_tokenizer = null;
+	    }
+	}
+	catch(Exception exception) {
+	    exception.printStackTrace();
+	}
+	return command_element;
+    }
+
+    private Element parseSubCollectionDefaultIndex(String command_str) {
+	Element command_element = null;
+	try {
+	    StringTokenizer tokenizer = new StringTokenizer(command_str);
+	    if(tokenizer.countTokens() == 2) {
+		command_element = document.createElement(StaticStrings.SUBCOLLECTION_DEFAULT_INDEX_ELEMENT);
+		tokenizer.nextToken();
+		//command_element.setAttribute(CONTENT_ATTRIBUTE, tokenizer.nextToken());
+		String content_str = tokenizer.nextToken();
+		StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER);
+		while(content_tokenizer.hasMoreTokens()) {
+		    Element content_element = document.createElement(StaticStrings.CONTENT_ELEMENT);
+		    content_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, content_tokenizer.nextToken());
+		    command_element.appendChild(content_element);
+		    content_element = null;
+		}
+		content_tokenizer = null;
+		content_str = null;
+	    }
+	    tokenizer = null;
+	}
+	catch(Exception exception) {
+	}
+	return command_element;
+    }
+
+    private Element parseSubCollectionIndex(String command_str) {
+	Element command_element = null;
+	try {
+	    StringTokenizer tokenizer = new StringTokenizer(command_str);
+	    tokenizer.nextToken();
+	    if(tokenizer.hasMoreTokens()) {
+		command_element = document.createElement(StaticStrings.SUBCOLLECTION_INDEXES_ELEMENT);
+	    }
+	    while(tokenizer.hasMoreTokens()) {
+		Element subcollectionindex_element = document.createElement(StaticStrings.INDEX_ELEMENT);
+		//command_element.setAttribute(CONTENT_ATTRIBUTE, tokenizer.nextToken());
+		String content_str = tokenizer.nextToken();
+		StringTokenizer content_tokenizer = new StringTokenizer(content_str, StaticStrings.COMMA_CHARACTER);
+		while(content_tokenizer.hasMoreTokens()) {
+		    Element content_element = document.createElement(StaticStrings.CONTENT_ELEMENT);
+		    content_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, content_tokenizer.nextToken());
+		    subcollectionindex_element.appendChild(content_element);
+		    content_element = null;
+		}
+		content_tokenizer = null;
+		content_str = null;
+		command_element.appendChild(subcollectionindex_element);
+		subcollectionindex_element = null;
+	    }
+	    tokenizer = null;
+	}
+	catch (Exception exception) {
+	}
+	return command_element;
+    }
+
+    private Element parseSuperCollection(String command_str) {
+	Element command_element = null;
+	try {
+	    StringTokenizer tokenizer = new StringTokenizer(command_str);
+	    if(tokenizer.countTokens() >= 3) {
+		command_element = document.createElement(StaticStrings.SUPERCOLLECTION_ELEMENT);
+		tokenizer.nextToken();
+		while(tokenizer.hasMoreTokens()) {
+		    Element collection_element = document.createElement(StaticStrings.COLLECTION_ELEMENT);
+		    collection_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, tokenizer.nextToken());
+		    command_element.appendChild(collection_element);
+		    collection_element = null;
+		}
+	    }
+	    tokenizer = null;
+	}
+	catch(Exception exception) {
+	}
+	return command_element;
+    }
+
+    static private String pluginToString(Element command_element, boolean show_extracted_namespace) {
+	StringBuffer text = new StringBuffer();
+	if(!command_element.getAttribute(StaticStrings.SEPARATOR_ATTRIBUTE).equals(StaticStrings.TRUE_STR)) {
+	    text.append(StaticStrings.PLUGIN_STR);
+	    text.append(StaticStrings.TAB_CHARACTER);
+	    text.append(StaticStrings.TAB_CHARACTER);
+	    text.append(command_element.getAttribute(StaticStrings.TYPE_ATTRIBUTE));
+	    // Retrieve, and output, the arguments
+	    NodeList option_elements = command_element.getElementsByTagName(StaticStrings.OPTION_ELEMENT);
+	    int option_elements_length = option_elements.getLength();
+	    if(option_elements_length > 0) {
+		for(int j = 0; j < option_elements_length; j++) {
+		    Element option_element = (Element) option_elements.item(j);
+		    if(option_element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.TRUE_STR)) {
+			text.append(StaticStrings.SPACE_CHARACTER);
+			text.append(StaticStrings.MINUS_CHARACTER);
+			text.append(option_element.getAttribute(StaticStrings.NAME_ATTRIBUTE));
+			String value_str = XMLTools.getValue(option_element);
+			if(!show_extracted_namespace && value_str.startsWith(StaticStrings.EXTRACTED_NAMESPACE)) {
+			    value_str = value_str.substring(StaticStrings.EXTRACTED_NAMESPACE.length());
+			}
+			if(value_str.length() > 0) {
+			    text.append(StaticStrings.SPACE_CHARACTER);
+			    if(value_str.indexOf(StaticStrings.SPACE_CHARACTER) == -1) {
+				text.append(value_str);
+			    }
+			    else {
+				text.append(StaticStrings.SPEECH_CHARACTER);
+				text.append(value_str);
+				text.append(StaticStrings.SPEECH_CHARACTER);
+			    }
+			}
+			value_str = null;
+		    }
+		    option_element = null;
+		}
+	    }
+	    option_elements = null;
+	}
+	return text.toString();
+    }
+
+    static private String searchtypeToString(Element command_element) {
+	if(command_element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.TRUE_STR)) {
+	    StringBuffer text = new StringBuffer(StaticStrings.SEARCHTYPE_STR);
+	    text.append(StaticStrings.TAB_CHARACTER);
+	    NodeList search_elements = command_element.getElementsByTagName(StaticStrings.CONTENT_ELEMENT);
+	    int search_elements_length = search_elements.getLength();
+	    for(int i = 0; i < search_elements_length; i++) {
+		Element search_element = (Element) search_elements.item(i);
+		text.append(search_element.getAttribute(StaticStrings.NAME_ATTRIBUTE));
+		text.append(StaticStrings.SPACE_CHARACTER);
+	    }
+	    return text.substring(0, text.length() - 1);
+	}
+	else {
+	    return null;
+	}
+    }
+
+    static private String subcollectionToString(Element command_element, boolean show_extracted_namespace) {
+	StringBuffer text = new StringBuffer(StaticStrings.SUBCOLLECTION_STR);
+	text.append(StaticStrings.SPACE_CHARACTER);
+	text.append(command_element.getAttribute(StaticStrings.NAME_ATTRIBUTE));
+	text.append(StaticStrings.SPACE_CHARACTER);
+	text.append(StaticStrings.TAB_CHARACTER);
+	text.append(StaticStrings.SPEECH_CHARACTER);
+	if(command_element.getAttribute(StaticStrings.TYPE_ATTRIBUTE).equals(StaticStrings.EXCLUDE_STR)) {
+	    text.append(StaticStrings.EXCLAMATION_CHARACTER);
+	}
+	String content_str = command_element.getAttribute(StaticStrings.CONTENT_ATTRIBUTE);
+	if(!show_extracted_namespace && content_str.startsWith(StaticStrings.EXTRACTED_NAMESPACE)) {
+	    content_str = content_str.substring(StaticStrings.EXTRACTED_NAMESPACE.length());
+	}
+	text.append(content_str);
+	content_str = null;
+	text.append(StaticStrings.SEPARATOR_CHARACTER);
+	text.append(XMLTools.getValue(command_element));
+	text.append(StaticStrings.SEPARATOR_CHARACTER);
+	String options_str = command_element.getAttribute(StaticStrings.OPTIONS_ATTRIBUTE);
+	if(options_str.length() > 0) {
+	    text.append(options_str);
+	}
+	options_str = null;
+	text.append(StaticStrings.SPEECH_CHARACTER);
+	return text.toString();
+    }
+
+    static private String subcollectionDefaultIndexToString(Element command_element) {
+	StringBuffer text = new StringBuffer(StaticStrings.SUBCOLLECTION_DEFAULT_INDEX_STR);
+	text.append(StaticStrings.TAB_CHARACTER);
+	NodeList content_elements = command_element.getElementsByTagName(StaticStrings.CONTENT_ELEMENT);
+	int content_elements_length = content_elements.getLength();
+	for(int j = 0; j < content_elements_length; j++) {
+	    Element content_element = (Element) content_elements.item(j);
+	    text.append(content_element.getAttribute(StaticStrings.NAME_ATTRIBUTE));
+	    if(j < content_elements_length - 1) {
+		text.append(StaticStrings.COMMA_CHARACTER);
+	    }
+	}
+	return text.toString();
+    }
+
+    static private String subcollectionIndexesToString(Element command_element) {
+	StringBuffer text = new StringBuffer(StaticStrings.SUBCOLLECTION_INDEX_STR);
+	text.append(StaticStrings.TAB_CHARACTER);
+	// Retrieve all of the subcollection index partitions
+	NodeList subcollectionindex_elements = command_element.getElementsByTagName(StaticStrings.INDEX_ELEMENT);
+	int subcollectionindex_elements_length = subcollectionindex_elements.getLength();
+	if(subcollectionindex_elements_length == 0) {
+	    return null;
+	}
+	for(int j = 0; j < subcollectionindex_elements_length; j++) {
+	    Element subcollectionindex_element = (Element) subcollectionindex_elements.item(j);
+	    NodeList content_elements = subcollectionindex_element.getElementsByTagName(StaticStrings.CONTENT_ELEMENT);
+	    int content_elements_length = content_elements.getLength();
+	    for(int k = 0; k < content_elements_length; k++) {
+		Element content_element = (Element) content_elements.item(k);
+		text.append(content_element.getAttribute(StaticStrings.NAME_ATTRIBUTE));
+		if(k < content_elements_length - 1) {
+		    text.append(StaticStrings.COMMA_CHARACTER);
+		}
+	    }
+	    if(j < subcollectionindex_elements_length - 1) {
+		text.append(StaticStrings.SPACE_CHARACTER);
+	    }
+	}
+	return text.toString();
+    }
+
+    static private String supercollectionToString(Element command_element) {
+	NodeList content_elements = command_element.getElementsByTagName(StaticStrings.COLLECTION_ELEMENT);
+	int content_elements_length = content_elements.getLength();
+	if(content_elements_length > 1) {
+	    StringBuffer text = new StringBuffer(StaticStrings.SUPERCOLLECTION_STR);
+	    text.append(StaticStrings.TAB_CHARACTER);
+	    for(int j = 0; j < content_elements_length; j++) {
+		Element content_element = (Element) content_elements.item(j);
+		text.append(content_element.getAttribute(StaticStrings.NAME_ATTRIBUTE));
+		if(j < content_elements_length - 1) {
+		    text.append(StaticStrings.SPACE_CHARACTER);
+		}
+	    }
+	    return text.toString();
+	}
+	return null;
+    }
+
+    static private String unknownToString(Element command_element) {
+	return XMLTools.getValue(command_element);
+    }
+
+    /** Write the text to the buffer. This is used so we don't have to worry about storing intermediate String values just so we can calaulate length and offset.
+     * @param writer the BufferedWriter to which the str will be written
+     * @param str the String to be written
+     */
+    private void write(BufferedWriter writer, String str)
+	throws IOException {
+	writer.write(str, 0, str.length());
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/CollectionDesignManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/CollectionDesignManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/CollectionDesignManager.java	(revision 13928)
@@ -0,0 +1,223 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import java.awt.event.*;
+import java.io.*;
+import javax.swing.event.*;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Gatherer;
+
+
+/** This manager provides access to submanagers, which in turn provide tools for the designing of Greenstone collections via the information stored in etc/collect.cfg. This class acts as a hub for the managers that handle specific parts of the configuration such as classifiers, format strings and language settings.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3d
+ */
+public class CollectionDesignManager {
+    /** This listener listens for any event on any of the components in any of the sub-views, and marks the collection as needing saving if any change occurs. */
+    static public CDMChangeListener change_listener;
+    /** These listeners listen to changes in the Design mode so as to allow minimal rebuilding */
+    static public DesignChangeListener all_change_listener;
+    static public DesignChangeListener buildcol_change_listener;
+    /** A list of classifiers to use at build time. */
+    static public ClassifierManager classifier_manager;
+    /** The CollectionConfiguration object on which this CDM will be based. */
+    static public CollectionConfiguration collect_config;
+    /** A manager of collection level metadata. */
+    static public CollectionMetaManager collectionmeta_manager;
+    /** A list of formating strings to use at build time. */
+    static public FormatManager format_manager;
+    /** A manager of general options */
+    static public GeneralManager general_manager;
+    /** List of indexes to be built, and the default index. 
+     also handles build type and levels */
+    static public IndexingManager index_manager;
+    /** Contains instructions dealing with the collection language. */
+    static public LanguageManager language_manager;
+    /** Handling writing extra.dm file */
+    static public MacrosManager macros_manager;
+    /** A list of plugins to use at build time. */
+    static public PluginManager plugin_manager;
+    /** a manager of searching metadata such as index names*/ 
+    static public SearchMetadataManager searchmetadata_manager;
+    /** Contains: A list of subcollections, (defined on metadatadata), a list of which subcollection indexes to build and the default subcollection index. */
+    static public SubcollectionManager subcollection_manager;
+
+    static public SubcollectionIndexManager subcollectionindex_manager;
+    /** A supercollection command allows a single search to be conducted across several collections. It is a very basic command and so avoids all the crazy model stuff that exists in most of the design managers. */
+    static public SuperCollectionManager supercollection_manager; // Just cause I could ;p
+    /** The text translation manager. */
+    static public TranslationView translation_manager;
+    /** These mark what needs to happen when building a collection where ONLY design options have been changed.
+        The build requirements of the higher numbers must include doing everything from the lower numbers. */
+    static final public int ALL = 3;
+    static final public int BUILDCOL = 2;
+    static final public int NOTHING = 0;
+    static private int rebuildTypeRequired = NOTHING; //Rebuild type required if only design options have changed
+
+    /** Constructor. Loads a certain collection configuration file, which is parsed into a DOM. This model is then registered with the command information managers, each of whom knows how to, and provides controls to, alter certain commands.
+     * @param collect_config_file the File representing a collection configuration file either in its text (G2) or xml (G3) form
+     */
+    public CollectionDesignManager(File collect_config_file) {
+	DebugStream.println("Initializaing CollectionDesignModule.");
+	change_listener = new CDMChangeListener();
+	all_change_listener = new DesignChangeListener(ALL);
+	buildcol_change_listener = new DesignChangeListener(BUILDCOL);
+	// Parse the collection configuration
+	collect_config = new CollectionConfiguration(collect_config_file);
+	if (DebugStream.isDebuggingEnabled()) {
+	    collect_config.display();
+	}
+	loadDesignDetails();
+	DebugStream.println("CollectionDesignModule loaded.");
+    }
+
+    /** Reloads the various managers to ensure they have built themselves from the latest details available in the collection configuration class
+     * @see org.greenstone.gatherer.cdm.ClassifierManager
+     * @see org.greenstone.gatherer.cdm.CollectionMetaManager
+     * @see org.greenstone.gatherer.cdm.FormatManager
+     * @see org.greenstone.gatherer.cdm.GeneralManager
+     * @see org.greenstone.gatherer.cdm.IndexManager
+     * @see org.greenstone.gatherer.cdm.LanguageManager
+     * @see org.greenstone.gatherer.cdm.PluginManager
+     * @see org.greenstone.gatherer.cdm.SubcollectionIndexManager
+     * @see org.greenstone.gatherer.cdm.SubcollectionManager
+     * @see org.greenstone.gatherer.cdm.SuperCollectionManager
+     * @see org.greenstone.gatherer.cdm.TranslationView
+     */
+    private void loadDesignDetails() {
+	// Create the command information managers, registering the config file with each as necessary
+	language_manager = new LanguageManager(collect_config.getLanguages());
+	collectionmeta_manager = new CollectionMetaManager();
+	classifier_manager = new ClassifierManager();
+	general_manager = new GeneralManager();
+	macros_manager = new MacrosManager();
+	index_manager = new IndexingManager();
+	plugin_manager = new PluginManager();
+	subcollection_manager = new SubcollectionManager();
+	subcollectionindex_manager = new SubcollectionIndexManager(collect_config.getSubIndexes());
+	supercollection_manager = new SuperCollectionManager(collect_config.getSuperCollection());
+	searchmetadata_manager = new SearchMetadataManager();
+	translation_manager = new TranslationView();
+	format_manager = new FormatManager(); // Parse formats at the very end, given that they depend upon several other managers to appear properly.
+    }
+
+    /** This method deconstructs each of the managers, causing them to dispose of their controls.
+     */
+    public void destroy() {
+	// Remove references from persistant listeners.
+	classifier_manager.destroy();
+	classifier_manager = null;
+	searchmetadata_manager.destroy();
+	searchmetadata_manager = null;
+	format_manager.destroy();
+	format_manager = null;
+	general_manager.destroy();
+	general_manager = null;
+	index_manager.destroy();
+	index_manager = null;
+	language_manager.destroy();
+	language_manager = null;
+	plugin_manager.destroy();
+	plugin_manager = null;
+	subcollection_manager.destroy();
+	subcollection_manager = null;
+	supercollection_manager.destroy();
+	supercollection_manager = null;
+	translation_manager.destroy();
+	translation_manager = null;
+    }
+
+    /** Called when the detail mode has changed which in turn may cause several design elements to be available/hidden
+     * @param mode the new mode as an int
+     */
+    public void modeChanged(int mode) {
+	plugin_manager.modeChanged(mode);
+	classifier_manager.modeChanged(mode);
+	subcollection_manager.modeChanged(mode);
+	supercollection_manager.modeChanged(mode);
+	format_manager.modeChanged(mode);
+	index_manager.modeChanged(mode);
+	translation_manager.modeChanged(mode);
+	general_manager.modeChanged(mode);
+	language_manager.modeChanged(mode);
+	searchmetadata_manager.modeChanged(mode);
+    }
+
+    /** The cdm is considered to be ready if the collect.cfg file was found and parsed and the collection title is not error.
+     * @return true if the collection is ready, false otherwise
+     */
+    public boolean ready() {
+	return collect_config.ready();
+    }
+
+
+    /** Cause the current collection configuration to be written out to disk.
+     */
+    public void save()
+    {
+	collect_config.saveIfNecessary();
+    }
+
+
+    public static int getRebuildTypeRequired() {
+	return rebuildTypeRequired;
+    }
+    public static void resetRebuildTypeRequired() {
+	setRebuildTypeRequired(NOTHING);
+    }
+    public static void setRebuildTypeRequired(int number) {
+	rebuildTypeRequired = number;
+    }
+
+    /**
+     * What exactly does this do?
+     */
+    private class CDMChangeListener
+	implements ActionListener, DocumentListener {
+
+	/** Gives notification that an event has happened */
+	public void actionPerformed(ActionEvent event) {
+	    Gatherer.c_man.getCollection().setSaved(false);
+	}
+
+	/** Gives notification that an attribute or set of attributes changed. */
+	public void changedUpdate(DocumentEvent e) {
+	    Gatherer.c_man.getCollection().setSaved(false);
+	}
+
+	/** Gives notification that there was an insert into the document. */
+	public void insertUpdate(DocumentEvent e) {
+	    Gatherer.c_man.getCollection().setSaved(false);
+	}
+
+	/** Gives notification that a portion of the document has been removed. */
+	public void removeUpdate(DocumentEvent e) {
+	    Gatherer.c_man.getCollection().setSaved(false);
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/CollectionMeta.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/CollectionMeta.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/CollectionMeta.java	(revision 13928)
@@ -0,0 +1,188 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.util.Codec;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.XMLTools;
+import org.w3c.dom.*;
+
+
+/** This class encapsulates a single collection level metadata assignment, which constitutes a name, language and value.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.4
+ */
+public class CollectionMeta
+    implements DOMProxyListEntry {
+
+    static final public boolean TEXT = true;
+    static final public boolean GREENSTONE = false;
+
+    private boolean dummy = false;
+    private Element element = null;
+    private String text = null;
+
+    /** Constructor.
+     * @param element the Element from which we will determine metadata details
+     */
+    public CollectionMeta(Element element) {
+	this.element = element;
+    }
+
+    /** Constructor to create a new piece of metadata given its name. */
+    public CollectionMeta(String name) {
+	element = CollectionConfiguration.createElement(StaticStrings.COLLECTIONMETADATA_ELEMENT);
+	element.setAttribute(StaticStrings.NAME_ATTRIBUTE, name);
+	element.setAttribute(StaticStrings.LANGUAGE_ATTRIBUTE, Configuration.getLanguage());
+	element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
+    }
+
+    /** Constructor to create a new piece of metadata given its name. */
+    public CollectionMeta(String name, String language) {
+	element = CollectionConfiguration.createElement(StaticStrings.COLLECTIONMETADATA_ELEMENT);
+	element.setAttribute(StaticStrings.NAME_ATTRIBUTE, name);
+	element.setAttribute(StaticStrings.LANGUAGE_ATTRIBUTE, language);
+	element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
+    }
+
+    /** Constructor to create a new piece of metadata given its name. */
+    public CollectionMeta(String name, String language, boolean dummy) {
+	this(name, language);
+	this.dummy = dummy;
+    }
+
+    /** Method to compare two collection metadata objects to calculate their respective ordering.
+     * @param object the other metadata to compare to, as an Object
+     * @return an int which is less than 0 if this object proceeds the given object, 0 if they are equal and greater than 0 otherwise.
+     * @see org.greenstone.gatherer.cdm.Language
+     */
+    public int compareTo(Object object) {
+	return toString().compareTo(object.toString());
+    }
+
+    /** Factory constructor. */
+    public DOMProxyListEntry create(Element element) {
+	return new CollectionMeta(element);
+    }
+
+    /** Method to compare two collection metadata objects for equality.
+     * @param object The other metadata to compare to, as an <strong>Object</strong>.
+     * @return A <i>boolean</i> value of <i>true</i> if the object are equal, <i>false</i> otherwise.
+     */
+    public boolean equals(Object object) {
+	return (compareTo(object) == 0);
+    }
+
+    public Element getElement() {
+	return element;
+    }
+
+    /** Method to retrieve the value of language.
+     * @return the value of language as a <strong>String</strong>.
+     */
+    public String getLanguage() {
+	// Retrieve the language string
+	return element.getAttribute(StaticStrings.LANGUAGE_ATTRIBUTE);
+    }
+
+    /** Method to retrieve the value of name.
+     * @return the name attribute of the collection meta as a String 
+     */
+    public String getName() {
+	return element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
+    }
+    /** Method to retrieve the value of value (well great choice of name there).
+     * @return The value of value as a <strong>String</strong>.
+     */
+    public String getValue(boolean text_value) {
+	String raw_value = XMLTools.getValue(element);
+	// Decode the raw value depending on whether the user asked for the TEXT or GREENSTONE version
+	if(text_value == TEXT) {
+	    return Codec.transform(raw_value, Codec.DOM_TO_TEXT);
+	}
+	else {
+	    return Codec.transform(raw_value, Codec.DOM_TO_GREENSTONE);
+	}
+    }
+
+    public boolean isAssigned() {
+	return (element != null && !element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.FALSE_STR));
+    }
+
+    public boolean isDummy() {
+	return dummy;
+    }
+
+    /** Determine if this metadata is one of the four special pieces of metadata.
+     * @return true if this metadata is special, false otherwise.
+     */
+    public boolean isSpecial() {
+	return (element != null && element.getAttribute(StaticStrings.SPECIAL_ATTRIBUTE).equals(StaticStrings.TRUE_STR));
+    }
+
+    public void setAssigned(boolean assigned) {
+	if(element != null) {
+	    element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, (assigned ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
+	}
+    }
+
+    public void setElement(Element element) {
+	this.element = element;
+	text = null;
+    }
+
+    /** Change the value of value. 
+     * @param raw_value the new value as a String.
+     */
+    public void setValue(String raw_value) {
+	// we need to check if the value has changed
+	String current_value = XMLTools.getValue(element);
+	String new_value = Codec.transform(raw_value, Codec.TEXT_TO_DOM);
+	if (!current_value.equals(new_value)) {
+	// Only raw html text can be given to setValue so we need to encode it
+	    XMLTools.setValue(element, new_value);
+	    text = null; // Reset text
+	    // And determine if this makes the metadata assigned
+	    setAssigned(raw_value != null && raw_value.length() > 0);
+	}
+    }
+
+    /** Method to print out this class as it would appear within the collection configuration file.
+     * @return A <strong>String</strong> containing the text value of this class.
+     */
+    public String toString() {
+	if(text == null) {
+            text = CollectionConfiguration.toString(element, true);
+	    if (text.equals("")){
+		text = getName();
+	    }
+	}
+	return text;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/CollectionMetaManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/CollectionMetaManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/CollectionMetaManager.java	(revision 13928)
@@ -0,0 +1,200 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.w3c.dom.*;
+
+/** This class is responsible for maintaining a list of assigned collection level metadata, and for allows manipulations on the aforementioned data.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3d
+ */
+public class CollectionMetaManager 
+    extends DOMProxyListModel {
+    
+    /** Constructor. */
+    public CollectionMetaManager() {
+	super(CollectionDesignManager.collect_config.getDocumentElement(), StaticStrings.COLLECTIONMETADATA_ELEMENT, new CollectionMeta(""));
+	DebugStream.println("CollectionMetaManager: " + getSize() + " metadata parsed.");
+    }
+    /** Method to add a new piece of metadata.
+     * @param metadata the new CollectionMeta
+     */
+    public void addMetadatum(CollectionMeta metadata) {
+	if(!contains(metadata)) {
+	    Element element = metadata.getElement();
+	    // Locate where we should insert this new metadata. 
+	    Node target_node = CollectionConfiguration.findInsertionPoint(element);
+	    add(root, metadata, target_node);
+	}
+    }
+
+    public CollectionMeta get(int i) {
+	return (CollectionMeta) getElementAt(i);
+    }
+
+    /** Retrieve the languages in use for the metadata assigned to this collection
+     * @return an TreeSet containing the languages used
+     */
+    public TreeSet getLanguages() {
+	TreeSet result = new TreeSet();
+	int size = getSize();
+	for(int i = 0; i < size; i++) {
+	    CollectionMeta metadata = (CollectionMeta) getElementAt(i);
+	    String language = metadata.getLanguage();
+	    result.add(language);
+	}
+	return result;
+    }
+
+    /** Retrieve all of the general metadata. */
+    public ArrayList getMetadata() {
+	ArrayList result = new ArrayList();
+	int size = getSize();
+	for(int i = 0; i < size; i++) {
+	    CollectionMeta metadata = (CollectionMeta) getElementAt(i);
+	    if(!metadata.getName().startsWith(StaticStrings.STOP_CHARACTER)) {
+		result.add(metadata);
+	    }
+	}
+	return result;
+    }
+	 
+    /** Retrieve all of the metadata for the given feature, regardless of language. */
+    public ArrayList getMetadata(String name) {
+	ArrayList result = new ArrayList();
+	int size = getSize(); // Refresh DOM Model
+	for(int i = 0; i < size; i++) {
+	    CollectionMeta metadata = (CollectionMeta) getElementAt(i);
+	    if(metadata.getName().equals(name)) {
+		result.add(metadata);
+	    }
+	}
+	return result;
+    }
+
+    /** Retrieve the named piece of metadata, in the default language, if available. If no such metadata is available then it is created.
+     * @param name the name of the metadatum to retrieve as a String
+     * @return the dom Element containing the specified metadatum
+     */
+    public CollectionMeta getMetadatum(String name) {
+	return getMetadatum(name, true);
+    }
+
+    public CollectionMeta getMetadatum(String name, boolean add_if_not_found) {
+	//DebugStream.println("Get the metadata for " + name + " in the default language.");
+	int size = getSize();
+	for(int i = 0; i < size; i++) {
+	    CollectionMeta metadatum = (CollectionMeta) getElementAt(i);
+	    if(metadatum.getName().equals(name) && metadatum.getLanguage().equals(Configuration.getLanguage())) {
+		DebugStream.println("Found '" + metadatum + "'");
+		return metadatum;
+	    }
+	    else {
+		//DebugStream.println("No match with: " + metadatum.getName() + " [l=" + metadatum.getLanguage() + "] \"" + metadatum.getValue() + "\"");
+	    }
+	    metadatum = null;
+	}
+	if(add_if_not_found) {
+	    CollectionMeta result = new CollectionMeta(name);
+	    addMetadatum(result);
+	    DebugStream.println("Added new metadata: " + name);
+	    return result;
+	}
+	else {
+	    return null;
+	}
+    }
+
+    /** Method to retrieve a certain piece of metadata based on its name and language.
+     * @param name the name of the metadata as an Object (as it may actually be a refernce to an Index or SubIndex)
+     * @param language the language of the metadata.
+     * @param partial <i>true</i> to return the first partial match (ie matches name but not language).
+     * @return The <strong>CollectionMeta</strong> requested, or <i>null</i> if no such metadata.
+     */
+    public CollectionMeta getMetadata(String name, String language, boolean partial) { 
+	CollectionMeta partial_match = null;
+	for(int i = 0; i < getSize(); i++) {
+	    CollectionMeta metadata = (CollectionMeta) getElementAt(i);
+	    Object metadata_name = metadata.getName();
+	    // We test the case of an object match (ie Index to Index)...
+	    if(metadata_name.equals(name)) {
+		if (metadata.getLanguage().equals(language)) {
+		    return metadata;
+		}
+		partial_match = metadata;
+	    }
+	}
+	if(partial) {
+	    return partial_match;
+	}
+	return null;
+    }
+
+    /** Method to remove a piece of metadata.
+     * @param metadata metadata
+     */
+    public void removeMetadata(CollectionMeta metadata) {
+	if(metadata != null) {
+	    String name = metadata.getName();
+	    String language = metadata.getLanguage();
+	    for(int i = 0; i < getSize(); i++) {
+		CollectionMeta other = (CollectionMeta) getElementAt(i);
+		if(name.equals(other.getName()) && language.equals(other.getLanguage())) {
+		    remove(i);
+		    return;
+		}
+		other = null;
+	    }	
+	    language = null;
+	    name = null;
+	}
+    }
+
+    /** Removes all of the metadata with a certain name, regardless of language or value. */
+    public void removeMetadata(String name) {
+	for(int i = getSize(); i != 0; i--) {
+	    CollectionMeta other = (CollectionMeta) getElementAt(i - 1);
+	    if(name.equals(other.getName())) {
+		remove(i - 1);
+	    }
+	    other = null;
+	}	
+    }
+
+    public int size() {
+	return getSize();
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/CommandTokenizer.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/CommandTokenizer.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/CommandTokenizer.java	(revision 13928)
@@ -0,0 +1,225 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+/**************************************************************************************
+ * Title:		Gatherer
+ * Description:  The Gatherer: a tool for gathering and enriching a digital collection.
+ * Company:	  The University of Waikato
+ * Written:	  07/05/02
+ * Revised:	  03/10/02 - Commented
+ **************************************************************************************/
+import java.io.BufferedReader;
+import java.util.StringTokenizer;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.util.StaticStrings;
+
+/** This class provides an extension to the standard StringTokenizer in that it recognizes quotes (or some form of bracketting) enclose a single token so in something like: <br>format Search '&lt;table&gt;&lt;img src=... &lt;/table&gt;'<br> the formatting string is parsed as a single token. Unfortunately this makes countTokens() unreliable for exact measurement of tokens remaining, and only useful for determining if there are tokens left to be processed (includes any that have already been read into command buffer).
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class CommandTokenizer {
+    
+    static final public int BRACKET_ENCLOSED		= 0;
+    static final public int DOUBLE_QUOTE_ENCLOSED	= 1;
+    static final public int NORMAL			= 2;
+    static final public int QUOTE_ENCLOSED		= 3;
+    
+    private BufferedReader in_stream;
+    private int count = -1;
+    private StringTokenizer internal_tokenizer;
+    private boolean strip_quotes = true;
+    /** Basic Constructor. Used to parse tokens from a string keeping tokens surrounded by speechmarks or square brackets intact. Thus something like:<br>
+     * collectionmeta collectionextra [l = en] "Hello World"<br>
+     * is tokenized thus<br>
+     * {'collectionmeta', 'collectionextra', 'l = en', 'Hello World'}
+     * @param command the command String you wish to tokenize
+     */
+    public CommandTokenizer(String command) {
+	this.internal_tokenizer = new StringTokenizer(command);
+	this.in_stream = null;
+    }
+    
+    /** Advanced Constructor. As above but with one major difference. Since it is provided an input stream (presumably where the command string originated from), it is able to parse a quote enclosed command token that stretches over several lines. Each newline is preserved in the resulting token. There is an extra bitchslap here as comething like a collection extra might have html code in them that contain escaped speechmarks, so extra care must be taken not to break at them. Thus something like:<br>
+     * collectionmeta collectionextra [l = en] "<br>
+     *     an example of the crazy as description we sometimes get which includes of all things something like <a href=\"this.html\"<br>
+     *     >this</a> which you could easily see might be a problem if I parse this niavely."<br>
+     * is tokenized thus<br>
+     * {'collectionmeta', 'collectionextra', 'l = en', '\nan example of the crazy as description we sometimes get which includes of all things something like <a href=\"this.html\"\n>this</a> which you could easily see might be a problem if I parse this niavely.'}
+     * @param command the command String you wish to tokenize
+     * @param in_stream a BufferedReader from which the tokenizer can draw further lines as necessary
+     */
+    public CommandTokenizer(String command, BufferedReader in_stream) {
+	///atherer.println("***** CommandTokenizer *****\nparse:\t" + command + "\n****************************");
+	this.internal_tokenizer = new StringTokenizer(command);
+	this.in_stream = in_stream;
+    }
+    
+    public CommandTokenizer(String command, BufferedReader in_stream, boolean strip_quotes) {
+	this.internal_tokenizer = new StringTokenizer(command);
+	this.in_stream = in_stream;
+	this.strip_quotes = strip_quotes;
+    }
+	
+    /** Returns the minumum number of remaining tokens before the tokenizer runs out of string. There may be more tokens than this count, but never less. The discrepancy is due to internal functionality and the fact we can't read ahead in the string or associated stream without risking the need for unpredictable push-back
+     * @return the minumum number of tokens available as an int
+     */
+    public int countTokens() {
+	if(count == 0 && internal_tokenizer.countTokens() > 1) {
+	    return 1;
+	}
+	if(count == -1) {
+	    count = internal_tokenizer.countTokens();
+	}
+	return count;
+    }
+    
+    /** Determine if there are still tokens available.
+     * @return true if there are more tokens, false otherwise
+     */
+    public boolean hasMoreTokens() {
+	return internal_tokenizer.hasMoreTokens();
+    }
+    
+    /** Method to retrieve the next token from the command, taking care to group tokens enclosed in speech marks.
+     * @return a String containing the next token from the command
+     */
+    public String nextToken() {
+	String result = null;
+	if(internal_tokenizer.hasMoreTokens()) {
+	    StringBuffer buffer = new StringBuffer(internal_tokenizer.nextToken());
+	    switch(buffer.charAt(0)) {
+	    case StaticStrings.DOUBLEQUOTE_CHAR:
+		///ystem.err.println("Building token wrapped by double quotes.");
+		result = buildToken(buffer, StaticStrings.DOUBLEQUOTE_CHAR, this.strip_quotes);
+		break;
+	    case StaticStrings.SINGLEQUOTE_CHAR:
+		///ystem.err.println("Building token wrapped by single quotes.");
+		result = buildToken(buffer, StaticStrings.SINGLEQUOTE_CHAR, this.strip_quotes);
+		break;
+	    case StaticStrings.OPENBRACKET_CHAR:
+		///ystem.err.println("Building token wrapped by brackets.");
+		result = buildToken(buffer, StaticStrings.CLOSEBRACKET_CHAR, false);
+		break;
+	    default:
+		///ystem.err.println("Returning plain string.");
+		result = buffer.toString();
+	    }
+	    buffer = null;
+	}
+	// Because of our tricky counting system we never want to have negative tokens remaining. In fact, unless the internal string buffer is empty, we will return a count of 1 anyway
+	if(count > 0) {
+	    count = count - 1;
+	}
+	///ystem.err.println("----- CommandTokenizer -----\ntoken:\t" + result + "\n----------------------------");
+	return result;
+    }
+    
+    /** Parse in the next token. paying heed to enclosing characters demands, escaped characters, newlines and empty buffers and consequential unexpected end of tokens
+     * @param buffer the StringBuffer in which the partial token is stored (at the first bit that caused this method to be called)
+     * @param end_char the sentinel char we are watching for as it encloses a token
+     * @param strip_characters a boolean denoting whether the enclosing characters should be stripped off
+     * @return the token, either in its entirity less the enclosing characters if required or, if an unexpected end occured, whatever we parsed without its starting enclosing character, again only if required. In fact if we weren't asked to strip characters then we add the enclosing character back in
+     */
+    private String buildToken(StringBuffer buffer, char end_char, boolean strip_characters) {
+	while(buffer.length() == 1 || buffer.charAt(buffer.length() - 1) != end_char || (buffer.length() > 3 && buffer.charAt(buffer.length() - 2) == StaticStrings.BACKSLASH_CHAR)) {
+	    try {
+		// The first version is for the basic tokenizer which has no idea of an input stream, so runs out tokens at the same time as the internal tokenizer does
+		if(internal_tokenizer.hasMoreTokens()) {
+		    buffer.append(StaticStrings.SPACE_CHAR);
+		    buffer.append(internal_tokenizer.nextToken());
+		}
+		// While the second version can draw more lines from the stream until eof occurs
+		else if(in_stream != null) {
+		    String line_str = null;
+		    while(!internal_tokenizer.hasMoreTokens() && (line_str = in_stream.readLine()) != null) {
+			///atherer.println("+++++ CommandTokenizer +++++\nappend:\t" + line_str + "\n+++++++++++++++++++++++++++++");
+			// Its at this stage the our token count becomes completely putu
+			internal_tokenizer = new StringTokenizer(line_str);
+			buffer.append(StaticStrings.NEW_LINE_CHAR); // A new line in the final token
+		    }
+		    line_str = null;
+		    if(internal_tokenizer.hasMoreTokens()) {
+			// Don't add a space if we just added a newline
+			if(buffer.charAt(buffer.length() - 1) != StaticStrings.NEW_LINE_CHAR) {
+			    buffer.append(StaticStrings.SPACE_CHAR);
+			}
+			buffer.append(internal_tokenizer.nextToken());
+		    }
+		    // We've prematurely run out of content, so throw the dummy, or at least return whatever we managed to parse sans its opening character
+		    else {
+			if(strip_characters) {
+			    return buffer.substring(1);
+			}
+			else {
+			    buffer.append(end_char);
+			    return buffer.toString();
+			}
+		    }
+		}
+		// We've prematurely run out of content, so throw the dummy, or at least return whatever we managed to parse sans its opening character
+		else {
+		    if(strip_characters) {
+			return buffer.substring(1);
+		    }
+		    else {
+			buffer.append(end_char);
+			return buffer.toString();
+		    }
+		}
+	    }
+	    // Exception thrown when we attempted reading from the input stream, so throw the dummy, or at least return whatever we managed to parse sans its opening character
+	    catch(Exception exception) {
+		DebugStream.printStackTrace(exception);
+		if(strip_characters) {
+		    return buffer.substring(1);
+		}
+		else {
+		    buffer.append(end_char);
+		    return buffer.toString();
+		}
+	    }
+	}
+	// Return the string sans enclosing characters
+	if(buffer.length() >= 2 && strip_characters) {
+	    return buffer.substring(1, buffer.length() - 1);
+	}
+	else {
+	    return buffer.toString();
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/Control.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/Control.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/Control.java	(revision 13928)
@@ -0,0 +1,36 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+/**
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3d
+ */
+public interface Control {
+    public void destroy();
+    public void gainFocus();
+    public void loseFocus();
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/DOMProxyListEntry.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/DOMProxyListEntry.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/DOMProxyListEntry.java	(revision 13928)
@@ -0,0 +1,38 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import org.w3c.dom.*;
+
+public interface DOMProxyListEntry 
+    extends Comparable {
+    public DOMProxyListEntry create(Element element);
+    public Element getElement();
+    public boolean isAssigned();
+    public void setAssigned(boolean assigned);
+    public void setElement(Element element);
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/DOMProxyListModel.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/DOMProxyListModel.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/DOMProxyListModel.java	(revision 13928)
@@ -0,0 +1,286 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import java.util.*;
+import javax.swing.*;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.w3c.dom.*;
+
+/** This class provides ListModel like access to a list of nodes within a DOM model.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3d
+ */
+public class DOMProxyListModel
+    extends AbstractListModel {
+    protected Element root;
+    private DOMProxyListEntry class_type;
+    private HashMap cache = new HashMap();
+    private NodeList children = null;
+    private String tag_name;
+
+    /** Constructor.
+     * @param root the Element at the root of the subtree to be searched for appropriate child elements
+     * @param tag_name the name of appropriate elements as a String
+     * @param class_type the type of object to wrap the elements returned in, as a DOMProxyListEntry
+     */
+    public DOMProxyListModel(Element root, String tag_name, DOMProxyListEntry class_type) {
+	this.class_type = class_type;
+	this.root = root;
+	this.tag_name = tag_name;
+	this.children = this.root.getElementsByTagName(this.tag_name);
+    }
+
+    /** Used to add an element into the underlying dom, and fire the appropriate repaint events. This version always adds the new element at the very head of the DOM. */
+    public synchronized void add(DOMProxyListEntry entry) {
+	Element element = entry.getElement();
+	if(root.hasChildNodes()) {
+	    Node sibling = root.getFirstChild();
+	    root.insertBefore(element, sibling);
+	    sibling = null;
+	}
+	else {
+	    root.appendChild(element);
+	}
+	element = null;
+	// Regardless fire update event
+	cache.clear();
+	fireIntervalAdded(this, 0, 0);
+    }
+
+    /** Used to add an element into the underlying dom, and fire the appropriate repaint events.
+     * @param index the index where the element should be inserted (relative of the other elements in this proxy list)
+     * @param entry the <strong>DOMProxyListEntry</strong> to be inserted
+     */
+    public synchronized void add(int index, DOMProxyListEntry entry) {
+	///atherer.println("Add entry at " + index + " where size = " + getSize());
+	Element element = entry.getElement();
+	// retrieve the node where we want to insert
+	if(index < children.getLength()) {
+	    Node sibling = children.item(index);
+	    // Find the parent node
+	    Node parent_node = sibling.getParentNode();
+	    parent_node.insertBefore(element, sibling);
+	    sibling = null;
+	}
+	// If the index is too large, we are adding to the end of our list of entries. However you have to remember that this list is only a viewport on the entire DOM so there might be entries following this group that we actually want to insert before (not append at the very end!)
+	else {
+	    // Retrieve the currently last entry
+	    index = children.getLength() - 1;
+	    Node sibling = null;
+	    Node parent_node = null;
+	    if(index >= 0) {
+		sibling = children.item(index);
+		parent_node = sibling.getParentNode();
+		sibling = sibling.getNextSibling();
+	    }
+	    if(sibling != null && parent_node != null) {
+		parent_node.insertBefore(element, sibling);
+	    }
+	    // Add to the root node
+	    else {
+		index = 0;
+		root.appendChild(element);
+	    }
+	}
+	// Regardless fire update event
+	cache.clear();
+	fireIntervalAdded(this, index, index);
+    }
+
+    /** Used to add an element into the underlying dom, and fire the appropriate repaint events. This version inserts the new entry immediately -after- the given entry in the DOM.
+     * @param entry the DOMProxyListEntry to be inserted
+     * @param preceeding_entry the DOMProxyListEntry immediately before where we want the new entry
+     */
+    public synchronized void addAfter(DOMProxyListEntry entry, DOMProxyListEntry preceeding_entry) {
+	Element element = entry.getElement();
+	Element preceeding_sibling = preceeding_entry.getElement();
+	Node parent_node = preceeding_sibling.getParentNode();
+	Node following_sibling = preceeding_sibling.getNextSibling();
+	if(following_sibling != null) {
+	    parent_node.insertBefore(element, following_sibling);
+	}
+	else {
+	    parent_node.appendChild(element);
+	}
+	// Regardless fire update event
+	cache.clear();
+	int index = indexOf(entry);
+	fireIntervalAdded(this, index, index);
+    }
+
+    /** Used to add an element into the underlying dom, and fire the appropriate repaint events. This version inserts the new entry immediately -before- the given entry in the DOM.
+     * @param entry the DOMProxyListEntry to be inserted
+     * @param following_entry the DOMProxyListEntry immediately after where we want the new entry
+     */
+    public synchronized void addBefore(DOMProxyListEntry entry, DOMProxyListEntry following_entry) {
+	Element element = entry.getElement();
+	Element following_sibling = following_entry.getElement();
+	Node parent_node = following_sibling.getParentNode();
+	parent_node.insertBefore(element, following_sibling);
+	// Regardless fire update event
+	cache.clear();
+	int index = indexOf(entry);
+	fireIntervalAdded(this, index, index);
+    }
+
+    public synchronized void add(Node parent, DOMProxyListEntry entry, Node sibling) {
+	Element child = entry.getElement();
+	if(sibling != null) {
+	    parent.insertBefore(child, sibling);
+	}
+	else {
+	    parent.appendChild(child);
+	}
+	cache.clear();
+	int index = indexOf(entry);
+      
+         
+	fireIntervalAdded(this, index, index);
+    }
+
+    /** Used to add an element into the underlying dom, and fire the appropriate repaint events. This version always adds the new element at the end of the children. */
+    public synchronized void append(DOMProxyListEntry entry) {
+	Element element = entry.getElement();
+	root.appendChild(element);
+	element = null;
+	// Regardless fire update event
+	cache.clear();
+	fireIntervalAdded(this, 0, 0);
+    }
+   
+    public synchronized ArrayList children() {
+	ArrayList child_list = new ArrayList();
+	int child_count = children.getLength();
+	for(int i = 0; i < child_count; i++) {
+	    child_list.add(getElementAt(i));
+	}
+	return child_list;
+    }
+
+    public synchronized boolean contains(Object entry) {
+	boolean found = false;
+	int size = getSize();
+      
+	for(int i = 0; !found && i < size; i++) {
+	    DOMProxyListEntry sibling = (DOMProxyListEntry) getElementAt(i);
+            if(sibling.equals(entry)) {
+               
+		found = true;
+	    }
+	}
+	return found;
+    }
+
+    
+    public synchronized Object getElementAt(int index)
+    {
+	Object object = cache.get(new Integer(index));
+	if (object != null) {
+	    return object;
+	}
+
+	// Retrieve the required element
+	Element element = (Element) children.item(index);
+	DebugStream.println("Element at index " + index + " not in cache: " + element);
+
+	// Now wrap it in the object of the users choice
+	object = class_type.create(element);
+	cache.put(new Integer(index), object);
+	return object;
+    }
+
+    public synchronized int indexOf(DOMProxyListEntry entry) {
+	Element element = entry.getElement();
+	int children_length = children.getLength();
+	for(int i = 0; i < children_length; i++) {
+	    Node node = children.item(i);
+	    if(element == node) {
+		return i;
+	    }
+	}
+	return -1;
+    }
+
+    public synchronized int getSize() {
+	if(children == null) {
+	    children = root.getElementsByTagName(tag_name);
+	}
+	return children.getLength();
+    }
+
+    public synchronized void refresh() {
+	fireContentsChanged(this, 0, getSize());
+    }
+
+    public synchronized void refresh(DOMProxyListEntry entry) {
+	int index = indexOf(entry);
+	fireContentsChanged(this, index, index);
+    }
+
+    public synchronized void remove(DOMProxyListEntry entry) {
+	remove(indexOf(entry));
+    } 
+
+    public synchronized void remove(int index) {
+	// Retrieve the required element
+	Node node = children.item(index);
+	// Find its parent
+	Node parent_node = node.getParentNode();
+	// Now remove it
+	parent_node.removeChild(node);
+	// Refresh model
+	cache.clear();
+	fireIntervalRemoved(this, index, index);
+    }
+
+ 
+    /** Changes the 'root' element that this list sources its information from. 
+     * @param  root the new root Element
+     */
+    public synchronized void setRoot(Element root) {
+	this.children = null;
+	cache.clear();
+	this.root = root;
+	this.children = this.root.getElementsByTagName(this.tag_name);
+	fireContentsChanged(this, 0, getSize());     
+    }
+
+    public synchronized void setAssigned(boolean assigned) {
+	if (assigned) {
+	    root.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+	}
+	else {
+	    root.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
+	}
+    }
+
+    public boolean isAssigned() {
+	return (root.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals("") || root.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.TRUE_STR));
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/DesignChangeListener.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/DesignChangeListener.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/DesignChangeListener.java	(revision 13928)
@@ -0,0 +1,81 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Matthew Whyte, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+
+package org.greenstone.gatherer.cdm;
+
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.DebugStream;
+import javax.swing.event.*;
+import java.awt.event.*;
+
+/**
+ * This handles events generated by changing design options.
+ * The rebuildTypeRequired is updated if the rebuild type associated with this
+ * listener requires more 'work' than what is currently set in the {@link CollectionDesignManager}.
+ * @author Matthew Whyte
+ */
+public class DesignChangeListener implements ActionListener, DocumentListener {
+    
+    /** The rebuild type required associated with this listener */
+    private final int rebuildType;
+    
+    /** Constructor. Sets the build type required. */
+    public DesignChangeListener(int type) {
+	rebuildType = type;
+    }
+
+    public void maybeSetRebuildRequired() {
+	if (rebuildType > CollectionDesignManager.getRebuildTypeRequired()) {
+	    CollectionDesignManager.setRebuildTypeRequired(rebuildType);
+	}
+    }
+    
+    /** Gives notification that an event has happened */
+    public void actionPerformed(ActionEvent event) {
+	//DebugStream.println("ActionEvent in Design from: " + event.getSource());
+	maybeSetRebuildRequired();
+    }
+
+    /** Gives notification that an attribute or set of attributes changed. */
+    public void changedUpdate(DocumentEvent e) {
+	maybeSetRebuildRequired();
+	//DebugStream.println("changedUpdate in Design.");
+    }
+    
+    /** Gives notification that there was an insert into the document. */
+    public void insertUpdate(DocumentEvent e) {
+	maybeSetRebuildRequired();
+	//DebugStream.println("insertUpdate in Design."); //debug
+    }
+    
+    /** Gives notification that a portion of the document has been removed. */
+    public void removeUpdate(DocumentEvent e) {
+	maybeSetRebuildRequired();
+	//DebugStream.println("removeUpdate in Design."); //debug
+    }
+    
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/DynamicListModel.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/DynamicListModel.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/DynamicListModel.java	(revision 13928)
@@ -0,0 +1,119 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+/**************************************************************************************
+ * Title:        Gatherer
+ * Description:  The Gatherer: a tool for gathering and enriching a digital collection.
+ * Company:      The University of Waikato
+ * Written:      20/05/02
+ * Revised:      03/10/02 - Commented
+ **************************************************************************************/
+import javax.swing.ComboBoxModel;
+import javax.swing.DefaultListModel;
+
+/** This class extends the functionality of the DefaultListModel to include simple methods for refreshing the contents of this model if one of its elements changes.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class DynamicListModel
+    extends DefaultListModel
+    implements ComboBoxModel {
+
+    private boolean auto_order = false;
+
+    private Object object = null;
+
+    public void addElement(Object element) {
+	if(auto_order) {
+	    // Insert the object in its alphabetically correct place.
+	    int position = 0;
+	    boolean found = false;
+	    while(!found && position < size()) {
+		///ystem.err.print("Compare " + element.toString() + " to " + get(position).toString() + ": ");
+		int order = element.toString().compareTo(get(position).toString());
+		if(order < 0) {
+		    add(position, element);
+		    found = true;
+		    ///ystem.err.println("Greater than. Insert");
+		}
+		else if(order == 0) {
+		    found = true;
+		    ///ystem.err.println("Equal. End.");
+		}
+		else {
+		    position++;
+		    ///ystem.err.println("Less than. Carry on.");
+		}
+	    }
+	    if(!found) {
+		super.addElement(element);
+		///ystem.err.println("Out of elements. Insert");
+	    }
+	}
+	else {
+	    super.addElement(element);
+	}
+    }
+
+    /* private DynamicListModel shallowCopy() {
+	DynamicListModel copy = new DynamicListModel();
+	copy.setAutoOrder(auto_order);
+	for(int i = 0; i < size(); i++) {
+	    copy.addElement(get(i));
+	}
+	return copy;
+	} */
+
+    public Object getSelectedItem() {
+	///ystem.err.println("Get item: " + object);
+	return object;
+    }
+    /** Notify all controls that are based on this list model that its contents have changed, and they should repaint themselves. */
+    public void refresh() {
+	fireContentsChanged(this, 0, size());
+    }
+
+    public void setAutoOrder(boolean auto_order) {
+	this.auto_order = auto_order;
+    }
+
+    public void setSelectedItem(Object object) {
+	///ystem.err.println("Set item: " + object);
+	this.object = object;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/Format.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/Format.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/Format.java	(revision 13928)
@@ -0,0 +1,381 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.util.Codec;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.XMLTools;
+import org.w3c.dom.*;
+
+
+/** This class encapsulates all the information about a format command from the collection configuration. This includes both the 'general' formatting commands, and the commands targetted at specific classifiers or classification component types. This class is, unfortunately, the most complex in terms of DOM model support, since we have to maintain a live reference to any classifier this format applies to. We temporarily use the feature name as the format name attribute but since the order of classifiers can change, this of course gets horribly out of date. Before the CollectionDesignManager saves the CollectionConfiguration it calls a method in the FormatManager to force all of the Formats to update their name attributes.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class Format 
+    implements DOMProxyListEntry {
+
+    /** The default features (not all of these are in the Greenstone Developer's Guide). */
+    static final public String DEFAULT_FEATURES[] = { "", "AllowExtendedOptions", "Document", "DocumentArrowsBottom", "DocumentArrowsTop","DocumentSearchResultLinks", "DocumentButtons", "DocumentContents", "DocumentHeading", "DocumentImages", "DocumentText", "DocumentTitles", "DocumentUseHTML", "RelatedDocuments", "Search", "SearchTypes" };
+    /** The list of known feature parts. */
+    static final public String DEFAULT_PARTS[] = { "", "DateList", "HList", "VList" };
+
+      
+    /** Only "" and "Search" can have parts */
+    static public boolean canHavePart(String name) {
+	return (name.startsWith("<html>") || name.equalsIgnoreCase("") || name.equalsIgnoreCase("Search") || name.equalsIgnoreCase("Document"));
+    }
+	
+    static public String generateName(Object feature, String part) {
+	if(feature instanceof Classifier) {
+	    return ((Classifier)feature).getPositionString() + part;
+	}
+	else {
+	    return feature.toString() + part;
+	}
+    }
+
+
+    /** Returns true if the parameter is a boolean type, false otherwise. */
+    static public boolean isParamType(String name)
+    {
+	if (name.equalsIgnoreCase("AllowExtendedOptions") || name.equalsIgnoreCase("DocumentArrowsBottom") || name.equalsIgnoreCase("DocumentArrowsTop") || name.equalsIgnoreCase("DocumentSearchResultLinks") || name.equalsIgnoreCase("DocumentContents") || name.equalsIgnoreCase("DocumentImages") || name.equalsIgnoreCase("DocumentTitles") || name.equalsIgnoreCase("DocumentUseHTML")) {
+	    return true;
+	}
+	else {
+	    return false;
+	}
+    }
+
+   
+    /** If this format is altering a Classifier then this is the classifier in question. */
+    private Classifier classifier = null;
+    /** The element this format is based on. */
+    private Element element = null;
+    /** We keep a copy of the part because its slightly more computationally tricky to calculate. */
+    private String part = null;
+    /** We keep a copy of the feature name */
+    private String feature_name = null;
+    /** Cached result of toString. */
+    private String text = null;
+
+    /** Constructor only to be used during DOMProxyListModel initialization. */
+    public Format() {
+	   
+    }
+
+    public Format(Element element) {
+
+	this.element = element;
+	// Immediately check if we are dealing with a classifier, by retrieving the feature name. If it is a classifier, then restore the live reference immediately before anything changes it.
+	Object object = getFeature();
+
+	// There may be format statements for no-longer-existing classifiers
+	if (object == null) {
+	    DebugStream.println("No matching classifier for format statement!");
+	    return;
+	}
+
+	if(object instanceof Classifier) {
+	    classifier = (Classifier) object;
+	}
+	else {
+	    String feature = (String) object;
+	    if(feature.toUpperCase().startsWith(Classifier.CLASSIFIER_PREFIX)) {
+		// Extract the integer index
+		int index = Integer.parseInt(feature.substring(Classifier.CLASSIFIER_PREFIX.length()));
+		// Subtract one (as java is 0-2 where G2 is 1-3)
+		index = index - 1;
+		// Retrieve the appropriate classifier
+		classifier = CollectionDesignManager.classifier_manager.getClassifier(index);
+	    }
+	}
+
+      	 
+    }
+
+    /** Constructor for a flag format command.
+     * @param feature The <Strong>Object</strong> this format affects.
+     * @param part The specific part of the control to format as a <strong>String</strong>.
+     * @param state A <i>boolean</i> indicating this formats state.
+     */
+    public Format(Object feature, String part, boolean state) {
+
+	element = CollectionConfiguration.createElement(StaticStrings.FORMAT_ELEMENT);
+	setName(feature, part);
+	setState(state);
+	 
+    }
+
+    /** Constructor for a format-string format command.
+     * @param feature The <Strong>Object</strong> this format affects.
+     * @param part The specific part of the control to format as a <strong>String</strong>.
+     * @param value The format <strong>String</strong> which may be a label name, or a piece of HTML formatting.
+     */
+    public Format(Object feature, String part, String value) {
+
+	element = CollectionConfiguration.createElement(StaticStrings.FORMAT_ELEMENT);       
+	setName(feature, part);
+	setValue(value);
+	 
+    }
+
+     
+ 
+    public boolean canHavePart() {
+	return canHavePart(getFeatureName());
+    }
+
+    public int compareTo(Object object) {
+	if(object == null) { // It seems that occasionally compareTo is called and somehow null ends up in comparison.
+	    return -1;
+	}
+	if(object instanceof Format && element != null) {
+	    return element.getAttribute(StaticStrings.NAME_ATTRIBUTE).compareTo(((Format)object).getName());
+	}
+	return toString().compareTo(object.toString());
+    }
+
+    public DOMProxyListEntry create(Element element) {
+	return new Format(element);
+    }
+
+    public boolean equals(Object object) {
+	return (compareTo(object) == 0);
+    }
+
+    public Element getElement() {
+	return element;
+    }
+
+    /** Method to retrieve the value of feature, which may either be a String or a Classifier.
+     * @return The value of feature as an <strong>Object</strong>.
+     */
+    public Object getFeature() {
+	if(classifier != null) {
+	    return classifier;
+	}
+	else if(element != null) {
+	    String feature = getFeatureName();
+	    // If the feature now refers to a classifier, retrieve it.
+	    if(feature.toUpperCase().startsWith(Classifier.CLASSIFIER_PREFIX)) {
+		// Extract the integer index
+		int index = Integer.parseInt(feature.substring(Classifier.CLASSIFIER_PREFIX.length()));
+		// Subtract one (as java is 0-2 where G2 is 1-3)
+		index = index - 1;
+		// Retrieve the appropriate classifier
+		classifier = CollectionDesignManager.classifier_manager.getClassifier(index);
+		return classifier;
+	    }
+	    else {
+		return feature;
+	    }
+	}
+	else {
+	    return "Error";
+	}
+    }
+
+    public String getFeatureName() {
+	if (feature_name == null) {
+	    String name  = element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
+	    // Remove part
+	    String part = getPart();
+	    if(part != null) {
+		feature_name = name.substring(0, name.length() - part.length());
+	    }
+	    else {
+		feature_name = name;
+	    }
+	    part = null;
+	    name = null;
+	}
+
+	return feature_name;
+	    
+    }
+    public String getName() {
+	if(element != null) {
+	    String name  = element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
+           return element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
+	}
+	return "Error";
+    }
+
+    /** Method to retrieve the value of part. Of course there may not be one, in which case return ""
+     * @return The value of part as a <Strong>String</strong>.
+     */
+    public String getPart() {
+	if(part == null && element != null) {
+	    // To determine a part, we retrieve the Format name, then look for one of our recognized parts
+	    String name = element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
+	    // DEFAULT_PARTS[0] is an empty string to correctly enable comboboxes.
+	    name = name.toLowerCase();
+	    for(int i = 1; part == null && i < DEFAULT_PARTS.length; i++) {
+		if(name.endsWith(DEFAULT_PARTS[i].toLowerCase())) {
+		    part = DEFAULT_PARTS[i];
+		}
+	    }
+	    if(part == null) {
+		part = DEFAULT_PARTS[0];
+	    }
+	}
+	return part;
+    }
+
+    /** Method to retrieve the value of state.
+     * @return value of state as a <i>boolean</i>.
+     */
+    public boolean getState() {
+	return (element != null && element.getAttribute(StaticStrings.VALUE_ATTRIBUTE).equals(StaticStrings.TRUE_STR));
+    }
+
+    /** Retrieve the value of value.
+     * @return A <strong>String</strong> which is the value of value.
+     */
+    public String getValue() {
+	String value = "Error";
+	if(element != null) {
+	   value = XMLTools.getValue(element);
+	   // Decode into text
+	   value = Codec.transform(value, Codec.DOM_TO_TEXT);
+	}
+	return value;
+    }
+
+    public boolean isAssigned() {
+	return (element != null && !element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.FALSE_STR));
+    }
+
+    public boolean isParamType() {
+	return (element != null && element.getAttribute(StaticStrings.VALUE_ATTRIBUTE).length() > 0);
+    }
+
+    public void setAssigned(boolean assigned) {
+	if(element != null) {
+	    element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, (assigned ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
+	}
+    }
+
+    public void setElement(Element element) {
+	this.element = element;
+	part = null;
+	text = null;
+	// Establish the classifier reference, if necessary
+	getFeature();
+    }
+
+    public void setName(Object feature, String part) {
+	// Can't do anything unless an element exists.
+        
+	if(element != null) {
+	    this.part = part; // Easier for later on.
+	    if(feature instanceof Classifier) {
+		classifier = (Classifier) feature;
+		feature_name = classifier.getPositionString(); 
+		element.setAttribute(StaticStrings.NAME_ATTRIBUTE, classifier.getPositionString() + part);
+	    }
+	    else {
+                if  (feature.toString().startsWith("<html>")){
+		    feature_name = "";
+		}
+		else{
+		    feature_name = feature.toString();
+		}
+		element.setAttribute(StaticStrings.NAME_ATTRIBUTE, feature_name + part);
+	    }
+	    text = null;
+	}
+    }
+
+    /** Set the value of state.
+     * @param state The new value for state as a <i>boolean</i>.
+     */
+    public void setState(boolean state) {
+	if(element != null) {
+	    element.setAttribute(StaticStrings.VALUE_ATTRIBUTE, (state ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
+	    text = null;
+	}
+    }
+
+    /** Set the value of value. Hmmm.
+     * @param value The new value from value as a <strong>String</strong>.
+     */
+    public void setValue(String value) {
+	if(element != null) {
+	    // Strip off any enclosing speech marks
+	    if(value.startsWith(StaticStrings.SPEECH_CHARACTER) && value.startsWith(StaticStrings.SPEECH_CHARACTER)) {
+		value = value.substring(1, value.length() - 1);
+	    }
+	    // Encode
+	    value = Codec.transform(value, Codec.TEXT_TO_DOM);
+	    // Store in DOM
+	    XMLTools.setValue(element, value);
+	    text = null;
+	}
+    }
+
+    /** Method to translate this classes information into a line of text as you would expect in the collection configuration file.
+     * @return A <strong>String</strong> containing the format command.
+     */
+    public String toString() {
+	if(text == null && element != null) {
+	    StringBuffer temp = new StringBuffer(" ");
+	    temp.append(element.getAttribute(StaticStrings.NAME_ATTRIBUTE));
+	    temp.append(" ");
+	    String value = element.getAttribute(StaticStrings.VALUE_ATTRIBUTE);
+	    if(value.length() > 0) {
+		temp.append(value);
+	    }
+	    else {
+		value = XMLTools.getValue(element);
+		if(value.equalsIgnoreCase(StaticStrings.TRUE_STR) || value.equalsIgnoreCase(StaticStrings.FALSE_STR)) {
+		    temp.append(value);
+		}
+		else {
+		    temp.append("\"");
+		    // Retrieve the DOM encoded value, decode and then append
+		    value = Codec.transform(value, Codec.DOM_TO_TEXT);
+		    temp.append(value);
+		    temp.append("\"");
+		}
+	    }
+	    text = temp.toString();
+	    temp = null;
+	}
+	return text;
+    }
+
+    public void update() {
+	if(classifier != null) {
+	    element.setAttribute(StaticStrings.NAME_ATTRIBUTE, classifier.getPositionString() + getPart());
+	    feature_name = classifier.getPositionString(); 
+	    text = null;
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/FormatManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/FormatManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/FormatManager.java	(revision 13928)
@@ -0,0 +1,1214 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.undo.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.gui.DesignPaneHeader;
+import org.greenstone.gatherer.gui.GLIButton;
+import org.greenstone.gatherer.metadata.MetadataElement;
+import org.greenstone.gatherer.metadata.MetadataSetManager;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+import org.w3c.dom.*;
+
+/** This class maintains a list of format statements, and allows the addition and removal of these statements.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class FormatManager
+    extends DOMProxyListModel {
+
+    static final private String BLANK = "blank";
+    static final private String FLAG  = "flag";
+    static final private String VALUE = "value";
+
+    static final private String DATELIST = "DateList";
+    static final private String DATELIST_DEFAULT_FORMAT = "<td>[link][icon][/link]</td>\n<td>[highlight]{Or}{[dc.Title],[exp.Title],[ex.Title],Untitled}[/highlight]</td>\n<td>{Or}{[dc.Date],[exp.Date],[ex.Date]}</td>";
+    static final private String HLIST = "HList";
+    static final private String HLIST_DEFAULT_FORMAT = "[link][highlight][ex.Title][/highlight][/link]";
+    static final private String VLIST = "VList";
+    static final private String VLIST_DEFAULT_FORMAT = "<td valign=\"top\">[link][icon][/link]</td>\n<td valign=\"top\">[ex.srclink]{Or}{[ex.thumbicon],[ex.srcicon]}[ex./srclink]</td>\n<td valign=\"top\">[highlight]\n{Or}{[dc.Title],[exp.Title],[ex.Title],Untitled}\n[/highlight]{If}{[ex.Source],<br><i>([ex.Source])</i>}</td>";
+    //    static final private String INVISIBLE = "Invisible";
+    //static final private String INVISIBLE_DEFAULT_FORMAT = "";
+
+    static final private String DOCUMENTHEADING = "DocumentHeading";
+    static final private String DOCUMENTHEADING_DEFAULT_FORMAT = "{Or}{[parent(Top):Title],[Title],untitled}<br>";
+
+    static final private String DOCUMENTTEXT = "DocumentText";
+    static final private String DOCUMENTTEXT_DEFAULT_FORMAT = "[Text]";
+
+    static final private String DOCUMENTBUTTONS = "DocumentButtons";
+    static final private String DOCUMENTBUTTONS_DEFAULT_FORMAT = "Detach|Highlight";
+    static final private String SEARCHTYPES = "SearchTypes";
+    static final private String SEARCHTYPES_DEFAULT_FORMAT = "plain,form";
+
+    static private HashMap default_format_map = null;
+
+    /** The controls used to edit the format commands. */
+    private Control controls = null;
+    /** A reference to ourselves so inner classes can get at the model. */
+    private DOMProxyListModel model = null;
+   
+   
+    /** Constructor. */
+    public FormatManager() {
+	super(CollectionDesignManager.collect_config.getDocumentElement(), StaticStrings.FORMAT_ELEMENT, new Format());
+	this.model = this;
+
+        default_format_map = new HashMap();
+	default_format_map.put(DATELIST, DATELIST_DEFAULT_FORMAT);
+	default_format_map.put(HLIST, HLIST_DEFAULT_FORMAT);
+	default_format_map.put(VLIST, VLIST_DEFAULT_FORMAT);
+	default_format_map.put(DOCUMENTHEADING, DOCUMENTHEADING_DEFAULT_FORMAT);
+	default_format_map.put(DOCUMENTTEXT, DOCUMENTTEXT_DEFAULT_FORMAT);
+	default_format_map.put(DOCUMENTBUTTONS, DOCUMENTBUTTONS_DEFAULT_FORMAT);
+	default_format_map.put(SEARCHTYPES, SEARCHTYPES_DEFAULT_FORMAT);
+       	default_format_map.put("", "");
+
+	DebugStream.println("FormatManager: parsed " + getSize() + " format statements.");
+	// Establish all of the format objects, so that classifier indexes are initially correct (subsequent refreshes of the model will be sufficient to keep these up to date, as long as we start with a live reference to a classifier.
+	int size = getSize();
+    	for(int i = 0; i < size; i++) {
+	    getElementAt(i);
+	}
+         
+	// Ensure the default formats for important format statements are assigned
+ 	if (getFormat(VLIST) == null) {
+ 	    addFormat(new Format("",VLIST,VLIST_DEFAULT_FORMAT));            
+ 	}
+	if (getFormat(HLIST) == null) {
+	    addFormat(new Format("",HLIST,HLIST_DEFAULT_FORMAT)); 
+	}
+	// only if DateList is used
+	if (getFormat(DATELIST) == null && CollectionDesignManager.classifier_manager.isDateListClassifierAssigned()) {
+	    addFormat(new Format("",DATELIST,DATELIST_DEFAULT_FORMAT));        
+ 	}
+	if (getFormat(DOCUMENTHEADING) == null) {
+	    addFormat(new Format(DOCUMENTHEADING, "", DOCUMENTHEADING_DEFAULT_FORMAT));
+     	} 
+	if (getFormat(DOCUMENTTEXT)== null) {
+	    addFormat(new Format(DOCUMENTTEXT,"",DOCUMENTTEXT_DEFAULT_FORMAT));
+   	}
+	if (getFormat(DOCUMENTBUTTONS) == null) {
+	    addFormat(new Format(DOCUMENTBUTTONS,"",DOCUMENTBUTTONS_DEFAULT_FORMAT));
+	}
+	// only for mgpp and lucene colls 
+	if (getFormat(SEARCHTYPES)==null && (CollectionDesignManager.index_manager.isMGPP()) || CollectionDesignManager.index_manager.isLucene()) {
+	    addFormat(new Format(SEARCHTYPES, "", SEARCHTYPES_DEFAULT_FORMAT));
+	}
+
+
+    }
+
+    /** Method to add a new format to this manager.
+     * @param format The <strong>Format</strong> to add.
+     */
+    private void addFormat(Format format) {
+       	if(!contains(format)) {
+	    Element element = format.getElement();
+	    // Locate where we should insert this new classifier. 
+	    Node target_node = CollectionConfiguration.findInsertionPoint(element);
+	    add(root, format, target_node);
+	}
+    }
+
+
+    public void destroy() {
+	if(controls != null) {
+	    controls.destroy();
+	    controls = null;
+	}
+    }
+
+
+    private Format getFormat(String name) {
+	int model_size = getSize();
+	for(int index = 0; index < model_size; index++) {
+	    Format format = (Format) getElementAt(index);
+	    if(format.getName().equals(name)) {
+		return format;
+	    }
+	}
+	return null;
+    }
+    
+    /** Method to retrieve this managers controls.
+     * @return the Control for this collection.
+     */
+    public Control getControls() {
+	if(controls == null) {
+	    controls = new FormatControl();
+	}
+	return controls;
+    }
+
+    /** Called when the detail mode has changed which in turn may cause several design elements to be available/hidden
+     * @param mode the new mode as an int
+     */
+    public void modeChanged(int mode) {
+
+    }
+
+
+    /** updates the format model */
+    public synchronized void refresh() {
+	for(int i = 0; i < getSize(); i++) {
+	    Format format = (Format) getElementAt(i);
+	    format.update();
+	    format = null;
+	}
+	super.refresh();
+    }
+    /** Method to remove a format.
+     * @param format The <strong>Format</strong> to remove.
+     */
+    private void removeFormat(Format format) {
+	remove(format);
+    }
+
+    private ArrayList buildFeatureModel() {
+	// Rebuild feature model.
+	ArrayList feature_model = new ArrayList();
+	// Add the set options
+	for(int i = 0; i < Format.DEFAULT_FEATURES.length; i++) {
+	    feature_model.add(new Entry(Format.DEFAULT_FEATURES[i]));
+	}
+	// Now the classifiers.
+	for(int j = 0; j < CollectionDesignManager.classifier_manager.getSize(); j++) {
+	    feature_model.add(new Entry(CollectionDesignManager.classifier_manager.getClassifier(j)));
+	}
+	Collections.sort(feature_model);
+	return feature_model;
+    }
+
+    private ArrayList buildPartModel() {
+	DebugStream.println("buildPartModel(): replace me with something that reads in a data xml file.");
+	ArrayList part_model = new ArrayList();
+	part_model.add(new Part("", ""));
+	part_model.add(new Part(DATELIST, DATELIST_DEFAULT_FORMAT));
+	part_model.add(new Part(HLIST, HLIST_DEFAULT_FORMAT));
+	//part_model.add(new Part(INVISIBLE, INVISIBLE_DEFAULT_FORMAT));
+	part_model.add(new Part(VLIST, VLIST_DEFAULT_FORMAT));
+	return part_model;
+    }
+
+    private ArrayList buildVariableModel()
+    {
+	ArrayList variable_model = new ArrayList();
+       	variable_model.add(Dictionary.get("CDM.FormatManager.Insert_Variable")); 
+	variable_model.add("[Text]");
+	ArrayList every_metadata_set_element = MetadataSetManager.getEveryMetadataSetElement();
+	for (int i = 0; i < every_metadata_set_element.size(); i++) {
+	    variable_model.add("[" + ((MetadataElement) every_metadata_set_element.get(i)).getFullName() + "]");
+	}
+	variable_model.add("[link]");
+	variable_model.add("[/link]");
+	variable_model.add("[icon]");
+	variable_model.add("[numleafdocs]");
+	variable_model.add("[num]");
+	variable_model.add("[parent():_]");
+	variable_model.add("[parent(Top):_]");
+	variable_model.add("[parent(All'_'):_]");
+	variable_model.add("[child():_]");
+	variable_model.add("[child(All'_'):_]");
+	variable_model.add("[sibling():_]");
+	variable_model.add("[sibling(All'_'):_]");
+	
+	return variable_model;
+    }
+
+    public class FormatControl
+	extends JPanel 
+	implements Control{
+	
+	private ArrayList feature_model;
+	private ArrayList part_model;
+	private ArrayList variable_model;
+	private boolean ignore_event = false;
+	private boolean ready = false; // Are these controls available to be refreshed
+	private CardLayout card_layout;
+	private JButton add_button;
+	private JButton insert_button;
+	private JButton remove_button;
+	private JButton default_button;
+        private JButton undo_button;    
+	private JButton redo_button; 
+   	private JCheckBox enabled_checkbox;
+	private JComboBox feature_combobox;
+	private JComboBox part_combobox;
+	private JComboBox variable_combobox;
+	private JList format_list;
+	private JTextArea editor_textarea;
+	private JPanel blank_pane;
+	private JPanel control_pane;
+	private JPanel part_pane;
+	private JPanel selection_pane;
+	private String view_type;
+  	private final Dimension FIELD_SIZE = new Dimension(200, 30);
+        private final UndoManager undo = new UndoManager();
+        private boolean newtext = true;
+        private Format previousFormat = null;
+        private Format currentFormat = null;        
+        private boolean fresh = true;
+       
+        public FormatControl() {
+	    feature_model = buildFeatureModel();
+	    part_model = buildPartModel();
+	    variable_model = buildVariableModel();
+	 
+	    // Create
+	    JPanel header_pane = new DesignPaneHeader("CDM.GUI.Formats", "formatstatements");
+
+	    format_list = new JList(model);
+
+	    selection_pane = new JPanel();
+	    JPanel feature_pane = new JPanel();
+	    JLabel feature_label = new JLabel(Dictionary.get("CDM.FormatManager.Feature"));
+
+	    feature_combobox = new JComboBox(feature_model.toArray());
+	    feature_combobox.setOpaque(!Utility.isMac());
+	    feature_combobox.setPreferredSize(FIELD_SIZE);
+	    feature_combobox.setEditable(false);
+	    feature_combobox.setToolTipText(Dictionary.get("CDM.FormatManager.Feature_Tooltip"));
+	    
+	    part_pane = new JPanel();
+	    JLabel part_label = new JLabel(Dictionary.get("CDM.FormatManager.Part"));
+	    part_combobox = new JComboBox(part_model.toArray());
+	    part_combobox.setOpaque(!Utility.isMac());
+	    part_combobox.setPreferredSize(FIELD_SIZE);
+	    part_combobox.setEditable(false);
+	    part_combobox.setToolTipText(Dictionary.get("CDM.FormatManager.Part_Tooltip"));
+	    
+	    blank_pane = new JPanel();
+	    
+	    JPanel center_pane = new JPanel();
+
+	    card_layout = new CardLayout();
+	    control_pane = new JPanel();
+
+	    JPanel blank_pane = new JPanel();
+
+	    JPanel editor_pane = new JPanel();
+	    JPanel editor_header_pane = new JPanel();
+	    JLabel editor_label = new JLabel(Dictionary.get("CDM.FormatManager.Editor"));
+	    
+	    editor_textarea = new JTextArea();
+	    editor_textarea.setBackground(Configuration.getColor("coloring.editable_background", false));
+	    editor_textarea.setCaretPosition(0);
+	    editor_textarea.setLineWrap(true);
+	    editor_textarea.setRows(6);
+	    editor_textarea.setWrapStyleWord(false);
+	    editor_textarea.setToolTipText(Dictionary.get("CDM.FormatManager.Add_Tooltip"));
+	    
+	    JPanel variable_pane = new JPanel();
+	    	    
+	    variable_combobox = new JComboBox(variable_model.toArray());
+	    variable_combobox.setOpaque(!Utility.isMac());
+	    variable_combobox.setToolTipText(Dictionary.get("CDM.FormatManager.Variable_Tooltip"));
+	    
+	    insert_button = new GLIButton(Dictionary.get("CDM.FormatManager.Insert"), Dictionary.get("CDM.FormatManager.Insert_Tooltip"));
+	          
+            default_button = new GLIButton(Dictionary.get("CDM.FormatManager.Default"), Dictionary.get("CDM.FormatManager.Default_Tooltip"));
+	          
+	    JPanel flag_pane = new JPanel();
+	    enabled_checkbox = new JCheckBox(Dictionary.get("CDM.FormatManager.Enabled"));
+	   
+	    JPanel button_pane = new JPanel();
+	    add_button = new GLIButton(Dictionary.get("CDM.FormatManager.Add"), Dictionary.get("CDM.FormatManager.Add_Tooltip"));
+	    add_button.setEnabled(false);
+	    	   
+	    remove_button = new GLIButton(Dictionary.get("CDM.FormatManager.Remove"), Dictionary.get("CDM.FormatManager.Remove_Tooltip"));
+	    remove_button.setEnabled(false);
+	    
+            undo_button = new GLIButton(Dictionary.get("General.Undo"), Dictionary.get("General.Undo_Tooltip"));
+	    undo_button.setEnabled(false);
+	    
+            redo_button = new GLIButton(Dictionary.get("General.Redo"), Dictionary.get("General.Redo_Tooltip"));
+	    redo_button.setEnabled(false);
+	    
+	    // Connect
+	    add_button.addActionListener(new AddListener());
+	    remove_button.addActionListener(new RemoveListener());
+            default_button.addActionListener(new DefaultListener());
+            undo_button.addActionListener(new UndoListener());
+            redo_button.addActionListener(new RedoListener());
+	    enabled_checkbox.addActionListener(new EnabledListener());
+	    feature_combobox.addActionListener(new FeatureListener());
+	    part_combobox.addActionListener(new PartListener());
+	    
+            editor_textarea.getDocument().addDocumentListener(new EditorListener());
+	    // Listen for undo and redo events
+	    editor_textarea.getDocument().addUndoableEditListener(new UndoableEditListener() {
+		    public void undoableEditHappened(UndoableEditEvent evt) {
+			undo.addEdit(evt.getEdit());
+		    }
+		});
+
+
+            format_list.addListSelectionListener(new FormatListListener());
+            variable_combobox.addActionListener(new VariableListener());
+
+	    // Layout
+	    JPanel format_list_pane = new JPanel();
+	    format_list_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	    format_list_pane.setLayout(new BorderLayout());
+	    format_list_pane.add(new JScrollPane(format_list), BorderLayout.CENTER);
+            
+
+	    feature_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	    feature_pane.setLayout(new BorderLayout(5,0));
+	    feature_pane.add(feature_label, BorderLayout.WEST);
+	    feature_pane.add(feature_combobox, BorderLayout.CENTER);
+
+	    part_pane.setBorder(BorderFactory.createEmptyBorder(2,0,0,0));
+	    part_pane.setLayout(new BorderLayout(5, 0));
+	    part_pane.add(part_label, BorderLayout.WEST);
+	    part_pane.add(part_combobox, BorderLayout.CENTER);
+
+
+	    flag_pane.add(enabled_checkbox);
+
+	    editor_header_pane.setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
+	    editor_header_pane.setLayout(new GridLayout(1,3));
+	    editor_header_pane.add(editor_label);
+	    
+	    JPanel rupanel = new JPanel();
+            rupanel.setLayout(new GridLayout(1,2));
+	    rupanel.add(undo_button);      
+	    rupanel.add(redo_button);
+     
+	    variable_pane.setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
+	    variable_pane.setLayout(new GridLayout(1,3));
+	    variable_pane.add(new JPanel());
+	    variable_pane.add(variable_combobox);
+	    variable_pane.add(rupanel);
+
+	    editor_pane.setLayout(new BorderLayout());
+	    editor_pane.add(editor_header_pane, BorderLayout.NORTH);
+            editor_pane.add(new JScrollPane(editor_textarea), BorderLayout.CENTER);
+
+	    selection_pane.setLayout(new BorderLayout());
+	    selection_pane.add(part_pane, BorderLayout.NORTH);
+	    selection_pane.add(editor_pane, BorderLayout.CENTER);
+	    selection_pane.add(variable_pane, BorderLayout.SOUTH);
+
+	    control_pane.setLayout(card_layout);
+	    control_pane.add(flag_pane, FLAG);
+	    control_pane.add(selection_pane, VALUE);
+	    control_pane.add(blank_pane, BLANK);
+           
+           
+	    button_pane.setLayout(new GridLayout(1,3));
+	    button_pane.add(add_button);
+	    button_pane.add(remove_button);
+            button_pane.add(default_button);      
+            
+
+	    center_pane.setLayout(new BorderLayout());
+	    center_pane.add(feature_pane, BorderLayout.NORTH);
+	    center_pane.add(control_pane, BorderLayout.CENTER);
+	    center_pane.add(button_pane, BorderLayout.SOUTH);
+
+	    setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
+	    setLayout(new BorderLayout());
+	    add(header_pane, BorderLayout.NORTH);
+	    add(format_list_pane, BorderLayout.CENTER);
+	    add(center_pane, BorderLayout.SOUTH);
+	    ready = true;
+	}
+
+	public void destroy() {
+	}
+       
+
+
+	/** Overriden to ensure that the instructions pane is scrolled to the top.
+	 */
+	public void gainFocus() {
+	    // This is only necessary if the components have been realized
+	    if(ready) {
+		model.refresh();
+
+		// Update the feature model, trying to maintain the same selected object
+		Object selected_feature = feature_combobox.getSelectedItem();
+		feature_model = buildFeatureModel();
+		feature_combobox.setModel(new DefaultComboBoxModel(feature_model.toArray()));
+		feature_combobox.setSelectedItem(selected_feature);
+
+		// Update the variable model,
+		variable_model = buildVariableModel();
+		variable_combobox.setModel(new DefaultComboBoxModel(variable_model.toArray()));
+	    }   
+	}
+
+	public void loseFocus() {
+	    // Force all of the Formats to update their names with the correct values.
+	    // do we need to do this on loseFocus???
+	    model.refresh();
+	}
+
+	public Format getCurrentFormat() {
+	    return (Format)format_list.getSelectedValue();
+	    
+	}
+
+	/** Listens for clicks on the add button, and if the relevant details are provided adds a new format. Note that formats are responsible for codecing the values into something that can be a) stored in a DOM and b) written to file */
+	private class AddListener
+	    implements ActionListener {
+
+	    public void actionPerformed(ActionEvent event)
+	    {
+	
+		ignore_event = true; // Prevent format_list excetera propagating events
+
+		Entry entry = (Entry) feature_combobox.getSelectedItem();
+		Object f = entry.getFeature();
+		String p = "";
+		if (entry.canHavePart()) {
+		    p = ((Part)part_combobox.getSelectedItem()).getName();
+		}
+
+		// Add a new format string of the appropriate type
+		Format format = null;
+		if (view_type.equals(FLAG)) {
+		    format = new Format(f, p, enabled_checkbox.isSelected());
+           	}
+		else {
+		    format = new Format(f, p, editor_textarea.getText());
+		   
+		}
+
+	
+		addFormat(format);
+		existingFormat();
+
+       		// Update list selection
+		format_list.setSelectedValue(format, true);
+		format = null;
+		p = null;
+		f = null;
+		entry = null;
+		ignore_event = false;
+	    }
+	}
+    
+	private class EditorListener
+	    implements DocumentListener {
+ 
+	    public void changedUpdate(DocumentEvent e) {
+             
+		update();
+	    }
+          
+	    public void insertUpdate(DocumentEvent e) {
+		update();	
+		updateUndo("insert");                   
+	    
+	    }
+          
+	    public void removeUpdate(DocumentEvent e) {
+		update();
+		updateUndo("remove");         
+	   
+	    }
+
+            private void updateUndo(String from){
+
+	  	if (!newtext){
+		    undo_button.setEnabled(true);
+		}                   
+
+		if (editor_textarea.getText().length()!=0 && newtext){
+		    newtext = false;                                                               		
+   		}               
+	    }
+
+	    public void update() {
+	                              
+		// Determine if replace should be enabled
+		if(!format_list.isSelectionEmpty()) {
+		    Format format = (Format)format_list.getSelectedValue();
+		    boolean shouldSave = !format.isParamType();
+		    
+                    if (shouldSave){
+			format.setValue(editor_textarea.getText());
+                        model.refresh((DOMProxyListEntry)format);
+		    }
+                                                                         
+		}
+		else {
+		    add_button.setEnabled(false);
+		   
+		}
+        	
+	    }
+	}
+
+	private class EnabledListener
+	    implements ActionListener {
+	    
+	    public void actionPerformed(ActionEvent event) {
+		// If there is a current format selected, and the value of enable_checkbox is now different than to value in it, then enable to replace button.
+		if(!format_list.isSelectionEmpty()) {
+		    Format format = (Format)format_list.getSelectedValue();
+		    boolean shouldSave = format.isParamType();
+		    if (shouldSave){
+			format.setState(enabled_checkbox.isSelected());
+                        model.refresh((DOMProxyListEntry)format);
+		    } 
+		}
+
+		// Thats it. Add would have been enabled upon feature/part selection depending if no existing format, um, existed.
+	    }
+	}
+
+	private class FeatureListener
+	    implements ActionListener {
+	    public void actionPerformed(ActionEvent event) {
+                undo_button.setEnabled(false);
+                redo_button.setEnabled(false);
+                default_button.setEnabled(true);
+		newtext = true; 
+	
+		if(!ignore_event) {
+		    ignore_event = true;
+		    Entry entry = (Entry) feature_combobox.getSelectedItem();
+		    
+                    // Step one: reset part
+		    if (entry.canHavePart()) {
+			part_combobox.setEnabled(true);
+			part_combobox.setSelectedIndex(part_combobox.getModel().getSize()-1);
+
+		    } else {
+			part_combobox.setEnabled(false);
+			part_combobox.setSelectedIndex(0);
+		    }
+		    // Step two: the rest
+		   
+		    String name = entry.toString();
+		    // Add is only enabled if there isn't already a format for the choosen feature and part. Create a dummy format and test if itsa already in the model
+		    Object f = entry.getFeature();
+		    Part part = (Part)part_combobox.getSelectedItem();
+		    String pname = part.getName();
+		    // You can never add anything to blank-blank
+		    if(f.toString().length() == 0 && pname.length() == 0) {
+                        add_button.setEnabled(false);
+			remove_button.setEnabled(false);
+		    }
+		    else {
+                    
+		       Format format = getFormat(Format.generateName(f, pname));
+		       // If there is an existing feature, select it, and use it to determine what controls are visible
+		      
+		       if(format != null) {
+			  ///ystem.err.println("There is an existing format!");
+			    format_list.setSelectedValue(format, true);
+			    // Now use type to determine what controls are visible, and what have initial values.
+			    if(format.isParamType()) {
+			       ///ystem.err.println("Flag type");
+				// Flags first.
+				///election_pane.remove(part_pane);
+				card_layout.show(control_pane, FLAG);
+				view_type = FLAG;
+				// Initial value
+				enabled_checkbox.setSelected(format.getState());
+			    }
+			    else {
+				///ystem.err.println("Value type");
+				///election_pane.add(part_pane);
+				card_layout.show(control_pane, VALUE);
+				view_type = VALUE;
+				// Initial value
+
+                                editor_textarea.setText(format.getValue());
+                                editor_textarea.setCaretPosition(0);
+                                			                              
+			    }
+                            existingFormat(); 
+			    control_pane.updateUI();
+		       }
+		       // Otherwise there is no existing format, so we proceed by checking against the feature name
+			else {
+			     ///ystem.err.println("No existing format");
+                            format_list.clearSelection();
+			    if(Format.isParamType(name)) {
+			       ///ystem.err.println("Flag type");
+				// Flags first.
+				///election_pane.remove(part_pane);
+				card_layout.show(control_pane, FLAG);
+				view_type = FLAG;
+				// Initial value
+				enabled_checkbox.setSelected(false);
+				enabled_checkbox.setEnabled(false);
+			    }
+			    else {
+				///ystem.err.println("Value type");
+				///election_pane.add(part_pane);
+				card_layout.show(control_pane, VALUE);
+				view_type = VALUE;
+				// Initial value
+
+				String feature_default_format = (String) default_format_map.get(f.toString());
+				if (feature_default_format != null) {
+				    
+				    editor_textarea.setText(feature_default_format);
+				}
+				else {
+				    editor_textarea.setText(part.getDefaultFormat());
+				}
+                                editor_textarea.setCaretPosition(0);
+	                   
+			    }
+			    newFormat();
+			}
+			format = null;
+			name = null;
+		    }
+		    part = null;
+		    pname = null;
+		    f = null;
+		    name = null;
+		    entry = null;
+		    ignore_event = false;
+		}
+                undo.discardAllEdits();	
+	    }
+	}
+
+	private class FormatListListener
+	    implements ListSelectionListener {
+	    public void valueChanged(ListSelectionEvent event) {
+                undo_button.setEnabled(false);
+                redo_button.setEnabled(false);
+                default_button.setEnabled(true);
+		newtext = true;
+		
+		if(!ignore_event && !event.getValueIsAdjusting()) {
+		
+		    if(!format_list.isSelectionEmpty()) {
+                        existingFormat();
+                    	ignore_event = true;
+			Format format = (Format)format_list.getSelectedValue();
+			// Try to match the target, remembering the entries within are Entry's
+			Entry an_entry = new Entry(format.getFeature());
+			feature_combobox.setSelectedItem(an_entry);
+			// If we didn't match anything, add it and select it again
+			Entry result_entry = (Entry) feature_combobox.getSelectedItem();
+			if(!an_entry.equals(result_entry)) {
+			    feature_combobox.insertItemAt(an_entry, feature_combobox.getItemCount());
+			    feature_combobox.setSelectedItem(an_entry);
+			}
+
+			// Now use type to determine what controls are visible, and what have initial values.
+			///ystem.err.println("Determine the correct type.");
+			if(format.isParamType()) {
+			    ///ystem.err.println("Flag type - remove part");
+			    // Flags first.
+			    ///SwingUtilities.invokeLater(new GUIChangeTask(/election_pane, part_pane, blank_pane, false));
+			   card_layout.show(control_pane, FLAG);
+			   view_type = FLAG;
+			   // Initial value
+			   enabled_checkbox.setSelected(format.getState());
+			}
+			else {
+			   ///ystem.err.println("Value type - show part");
+			    ///SwingUtilities.invokeLater(new GUIChangeTask(/election_pane, part_pane, blank_pane, true));
+			   card_layout.show(control_pane, VALUE);
+			   view_type = VALUE;
+			   // Initial values
+			   // do we have a part?
+			   if (format.canHavePart()) {
+			       part_combobox.setEnabled(true);
+			       // Try to match the part.
+			       String part_entry = format.getPart();
+			       // Set Selected Item doesn't work so I'll do this manually
+			       boolean found = false;
+			       for(int i=0; i < part_combobox.getItemCount(); i++) {
+				   Part a_part = (Part) part_combobox.getItemAt(i);
+				   if(a_part.equals(part_entry)) {
+				       part_combobox.setSelectedItem(a_part);
+				       found = true;
+				   }
+				   a_part = null;
+			       }
+			       // If we didn't match anything, add it and select it again
+			       if(!found) {
+				   Part a_part = new Part(part_entry, "");
+				   part_combobox.insertItemAt(a_part, part_combobox.getItemCount());
+				   part_combobox.setSelectedItem(a_part);
+				   
+			       }
+			   } else {
+			       part_combobox.setEnabled(false);
+			       part_combobox.setSelectedIndex(0);
+			   }
+			   editor_textarea.setText(format.getValue());
+			   editor_textarea.setCaretPosition(0);
+                          			  
+                        }
+                            
+			//control_pane.updateUI();
+			ignore_event = false;
+		    }
+		  
+		}
+		undo.discardAllEdits();
+    	    }
+         
+	}
+
+        private void newFormat(){
+	    editor_textarea.setEditable(false);
+	    editor_textarea.setBackground(Color.lightGray); 
+	    editor_textarea.setToolTipText(Dictionary.get("CDM.FormatManager.Editor_Disabled_Tooltip"));
+	    
+	    enabled_checkbox.setEnabled(false);
+            undo_button.setEnabled(false);
+	    redo_button.setEnabled(false);
+            variable_combobox.setEnabled(false);  
+	    add_button.setEnabled(true);
+	    remove_button.setEnabled(false);
+            default_button.setEnabled(false);
+                  
+	}
+
+          private void existingFormat(){
+	    editor_textarea.setEditable(true);
+	    editor_textarea.setBackground(Color.white);
+	    editor_textarea.setToolTipText(Dictionary.get("CDM.FormatManager.Editor_Tooltip"));
+	    enabled_checkbox.setEnabled(true);
+            variable_combobox.setEnabled(true);  
+	    add_button.setEnabled(false);
+	    remove_button.setEnabled(true);
+            default_button.setEnabled(true);
+                  
+	}
+             
+	private class VariableListener
+	    implements ActionListener {
+	    public void actionPerformed(ActionEvent event) {
+		int selected_index = variable_combobox.getSelectedIndex();
+		if (selected_index == 0) return;
+                String selected_value = (String)variable_combobox.getSelectedItem();
+		editor_textarea.insert(selected_value, editor_textarea.getCaretPosition());   
+		undo_button.setEnabled(true);
+		variable_combobox.setSelectedIndex(0);
+	    }
+	    	    
+	}
+
+	private class PartListener
+	    implements ActionListener {
+	    public void actionPerformed(ActionEvent event) {
+		undo_button.setEnabled(false);
+                redo_button.setEnabled(false);
+                default_button.setEnabled(true);
+	     	newtext = true;
+          	if(!ignore_event) {
+		    // Add is only enabled if there isn't already a format for the choosen feature and part. Create a dummy format and test if its already in the model
+		    Entry entry = (Entry) feature_combobox.getSelectedItem();
+		    Object f = entry.getFeature();
+		    Part part = (Part) part_combobox.getSelectedItem();
+		    String pname = part.getName();
+		    // You can never add anything to blank-blank
+		    if(f.toString().length() == 0 && pname.length() == 0) {
+			add_button.setEnabled(false);
+			remove_button.setEnabled(false);
+		    }
+		    else {
+			String name = Format.generateName(f, pname);
+			Format format = getFormat(name);
+			// If there is an existing feature, select it.
+			if(format != null) {
+			    format_list.setSelectedValue(format, true);
+			    // Now use type to determine what controls are visible, and what have initial values.
+			    if(format.isParamType()) {
+				// Flags first.
+				///election_pane.remove(part_pane);
+				card_layout.show(control_pane, FLAG);
+				view_type = FLAG;
+				// Initial value
+				enabled_checkbox.setSelected(format.getState());
+			    }
+			    else {
+				///election_pane.add(part_pane);
+				card_layout.show(control_pane, VALUE);
+				view_type = VALUE;
+				// Initial value
+                              
+				editor_textarea.setText(format.getValue());
+			        editor_textarea.setCaretPosition(0);
+                                
+			    }
+			    control_pane.updateUI();
+			    existingFormat(); 
+			}
+			else {
+			    format_list.clearSelection();
+			    if(Format.isParamType(name)) {
+				// Flags first.
+				///election_pane.remove(part_pane);
+				card_layout.show(control_pane, FLAG);
+				view_type = FLAG;
+				// Initial value
+				enabled_checkbox.setSelected(false);
+				enabled_checkbox.setEnabled(false);
+			    }
+			    else {
+				///election_pane.add(part_pane);
+				card_layout.show(control_pane, VALUE);
+				view_type = VALUE;
+				// Initial value
+                               
+                                editor_textarea.setText(part.getDefaultFormat());
+				editor_textarea.setCaretPosition(0);
+			       
+			    }
+                            newFormat();
+			}
+			format = null;
+			name = null;
+		    }
+		    
+		    pname = null;
+		    part = null;
+		    f = null;
+		    entry = null;
+		}
+		undo.discardAllEdits();
+	    }
+	}
+
+	private class RemoveListener
+	    implements ActionListener {
+
+	    public void actionPerformed(ActionEvent event)
+	    {
+		if (!format_list.isSelectionEmpty()) {
+		    // Remove the current format
+		    removeFormat((Format)format_list.getSelectedValue());
+
+		    // Change buttons
+		    add_button.setEnabled(true);
+		    newFormat();
+		}
+	    }
+	}
+
+
+
+	private class DefaultListener
+	    implements ActionListener {
+
+	    public void actionPerformed(ActionEvent event)
+	    {
+		newtext = false;
+		if(!ignore_event) {	 
+		    Entry entry = (Entry) feature_combobox.getSelectedItem();
+		    Object f = entry.getFeature();
+		    String name ="";
+		    String pname="";
+                    Part part = null;
+
+		    if (entry.canHavePart()){
+			part = (Part) part_combobox.getSelectedItem();
+			pname = part.getName();
+			name = Format.generateName(f, pname);		
+		    }
+		    else{
+			name = entry.toString();
+		    }
+
+		    Format format = getFormat(name);
+		    // If there is an existing feature, select it.
+		    if(format != null) {
+			remove_button.setEnabled(true);
+		    }
+		    else {
+						
+			add_button.setEnabled(true);
+		    }//endif (format !=null)
+	
+		    if(Format.isParamType(name)) {
+			// Flags first.
+			card_layout.show(control_pane, FLAG);
+			view_type = FLAG;
+			    // Initial value
+			enabled_checkbox.setSelected(false);
+		    }
+		    else {
+			card_layout.show(control_pane, VALUE);
+			view_type = VALUE;
+			// Initial value
+			if (pname !=null && pname.length()!=0 ){
+			    editor_textarea.setText((String) default_format_map.get(pname));
+			    editor_textarea.setCaretPosition(0);
+			}
+			else{
+			    editor_textarea.setText((String) default_format_map.get(name));
+			    editor_textarea.setCaretPosition(0);
+			}
+		    }
+		    
+		}
+	    }
+
+ }
+
+        private class UndoListener
+	    implements ActionListener {
+
+	    public void actionPerformed(ActionEvent event)
+	    {	
+                try {
+                    if (undo.canUndo()) {
+		       int pos = editor_textarea.getCaretPosition();
+		        redo_button.setEnabled(true); 
+                        undo.undo();
+			if (pos > 0)
+			    editor_textarea.setCaretPosition(pos-1);
+			else
+			    editor_textarea.setCaretPosition(pos);
+		    }
+                    if (!undo.canUndo()){
+			undo_button.setEnabled(false);
+		    }
+		    else{
+                      	undo_button.setEnabled(true); 
+		    }   
+
+                } catch (Exception e) {
+		   
+		}           
+	    }
+	}
+    
+       private class RedoListener
+	    implements ActionListener {
+         public void actionPerformed(ActionEvent evt) {
+                try {
+                    if (undo.canRedo()) {
+			int pos = editor_textarea.getCaretPosition();
+                        undo.redo();
+                        editor_textarea.setCaretPosition(pos); 
+                    }
+                    if (!undo.canRedo()){
+			redo_button.setEnabled(false);
+		    }
+		    else{
+                      	redo_button.setEnabled(true); 
+		    }                     
+
+                } catch (Exception e) {}
+	 }
+       }
+
+    }
+
+    /** This object provides a wrapping around an entry in the format target control, which is tranparent as to whether it is backed by a String or a Classifier. */
+    private class Entry
+	implements Comparable {
+	private Classifier classifier = null;
+	private String text = null;
+	
+	public Entry(Object object) {
+	    if(object instanceof Classifier) {
+		classifier = (Classifier)object;
+	    }
+	    else if(object instanceof String) {
+		text = (String)object;
+	    }
+	    else {
+		text = "";
+	    }
+	}
+	
+	public Entry(String text) {
+	    this.text = text;
+	}
+	
+	public boolean canHavePart() {
+	    if (classifier !=null) return true;
+	    return Format.canHavePart(text);
+	}
+
+	public int compareTo(Object object) {
+	    if(object == null) {
+		return 1;
+	    }
+	    if(toString() == null) {
+		return -1;
+	    }
+	    else {
+		String object_str = object.toString();
+		if(object_str == null) {
+		    return 1;
+		}
+		return toString().compareTo(object_str);
+	    }
+	}
+	
+	public boolean equals(Object object) {
+	    if(compareTo(object) == 0) {
+		return true;
+	    }
+	    return false;
+	}
+	
+	public Classifier getClassifier() {
+	    return classifier;
+	}
+	
+	public Object getFeature() {
+	    if(classifier != null) {
+		return classifier;
+	    }
+
+	    if (text.startsWith("<html>")){
+		return  "";
+	    }
+	    return text;
+	}
+	
+	public String toString() {
+	    if(classifier != null) {
+		// Return the classifier - with its CL index shown
+		return classifier.getPositionString() + StaticStrings.COLON_CHARACTER + StaticStrings.SPACE_CHARACTER + classifier.toString();
+	    }
+	    if (text.equals("")) {
+		return "<html><body><i>"+Dictionary.get("CDM.FormatManager.AllFeatures")+"</i></body></html>";
+	    }
+	    return text;
+	}
+    }
+
+    /*
+      private class GUIChangeTask
+      implements Runnable {
+      private boolean to_add;
+      private JPanel child;
+      private JPanel parent;
+      private JPanel replacement;
+      
+      public GUIChangeTask(JPanel parent, JPanel child, JPanel replacement, boolean to_add) {
+      this.child = child;
+      this.parent = parent;
+      this.replacement = replacement;
+      this.to_add = to_add;
+      }
+      
+      public void run() {
+      if(to_add) {
+      parent.remove(replacement);
+      parent.add(child);
+      parent.updateUI();
+      }
+      else {
+      parent.remove(child);
+      parent.add(replacement);
+      parent.updateUI();
+      }
+      }
+      }
+    */
+
+   /** This class encapsulates all of the information associated with a certain component part of a feature within a html page returned from the receptioninst. */
+   private class Part
+      implements Comparable {
+      /** The default format string for this part */
+      private String default_format = null;
+      /** The name of this part */
+      private String name = null;
+      /** Constructor - must be provided with all of the details of a part as there are no other setter methods.
+       * @param name the name of this part
+       * @param default_format the default format string for this part
+       */
+      public Part(String name, String default_format) {
+	 this.default_format = default_format;
+	 this.name = name;
+      }
+      /** Compare this part to another object in terms of ordering
+       * @param obj the other Object
+       * @return <0 if the object is before, 0 if equal to, and >0 if the object is after this part
+       */
+      public int compareTo(Object obj) {
+	  if (obj instanceof Part) {
+	      return name.compareTo(((Part)obj).getName());
+	  }
+	  return name.compareTo(obj.toString());
+      }
+      
+      /** Determine if the part is equivelent to some other object
+       * @param obj the other Object
+       * @return true is the two objects are equal
+       */
+      public boolean equals(Object obj) {
+	  if (obj instanceof Part) {
+	      return name.equals(((Part)obj).getName());
+	  }
+	  return name.equals(obj.toString());
+      }
+      
+      /** Retrieve the default format string for this part
+       * @return the default format String
+       */
+      public String getDefaultFormat() {
+	 // Retrieve the format for the super format - either VList or HList
+	 Format default_format_object = getFormat(name);
+	 if(default_format_object != null) {
+	    return default_format_object.getValue();
+	 }
+	 else {
+	    return this.default_format;
+	 }
+      }
+      /** Retrieve the name of this part
+       * @return the name as a String
+       */
+      public String getName() {
+	 return name;
+      }
+      /** Produce a string representation of this part, which in this case is simply the name again
+       * @return the name as a String
+       */
+      public String toString() {
+ 	  if (name.equals("")) {
+ 	      return "<html><body><i>"+Dictionary.get("CDM.FormatManager.AllParts")+"</i></body></html>";
+ 	  }
+	  return name;
+      }
+   }  
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/GeneralManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/GeneralManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/GeneralManager.java	(revision 13928)
@@ -0,0 +1,426 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.regex.*;
+import javax.swing.*;
+import javax.swing.filechooser.*;
+import javax.swing.event.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.gui.DesignPaneHeader;
+import org.greenstone.gatherer.gui.EmailField;
+import org.greenstone.gatherer.gui.GLIButton;
+import org.greenstone.gatherer.gui.GUIUtils;
+import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
+import org.greenstone.gatherer.util.StaticStrings;
+
+/** This class provides a graphical interface for editing general metadata for the collection, such as name, description, icons etc. 
+*/
+public class GeneralManager {
+
+    /** The controls used to modify the general options. */
+    private Control controls;
+    /** Constructor. */
+    public GeneralManager() {
+    }
+
+    /** Destructor. */
+    public void destroy() {
+	if (controls != null) {
+	    controls.destroy();
+	    controls = null;
+	}
+    }
+
+    public void loseFocus() {
+    }
+
+    public void gainFocus() {
+
+    }
+    /** This class is resposible for generating the controls for the editing of general options.
+     * @return the Control for editing the general options
+     */
+    public Control getControls() {
+	if (controls == null) {
+	    controls = new GeneralControl();
+	}
+	return controls;
+    }
+    
+
+    /** Called when the detail mode has changed which in turn may cause several design elements to be available/hidden
+     * @param mode the new mode as an int
+     */
+    public void modeChanged(int mode) {
+
+    }
+    
+    /** This class represents the visual component of the general options stored in the CollectionDesignManager. */
+    private class GeneralControl
+	extends JPanel
+	implements Control {
+
+        private boolean ready = false;
+	private CollectionMeta collection_extra_collectionmeta;
+	private CollectionMeta collection_name_collectionmeta;
+	private CollectionMeta creator_collectionmeta;
+	private CollectionMeta icon_collection_collectionmeta;
+	private CollectionMeta icon_collection_small_collectionmeta;
+	private CollectionMeta maintainer_collectionmeta;
+	private CollectionMeta public_collectionmeta;
+	/** The creators email. */
+	private EmailField creator_emailfield;
+	/** The maintainers email. */
+	private EmailField maintainer_emailfield;
+	/** Button to browse for the collection about page icon. */
+	private JButton browse_about_icon_button;
+	/** Button to browse for the collection home page icon. */
+	private JButton browse_home_icon_button;
+	/** The checkbox controlling public access to the collection. */
+	private JCheckBox public_checkbox;
+	private JLabel creator_label;
+	private JLabel description_label;
+	private JLabel icon_label;
+	private JLabel maintainer_label;
+	private JLabel name_label;
+	private JLabel small_icon_label;
+	/** The text field used to edit the file name of the collections icon. */
+	private JTextField icon_textfield;
+	/** The text field used to edit the collections title. */
+	private JTextField name_textfield;
+	/** The text field used to edit the file name of the collections small icon. */
+	private JTextField small_icon_textfield;
+	/** A text area used to modify the collection description. */
+	private JTextArea description_textarea;
+	/** Constructor. */
+	public GeneralControl() {
+	    super();
+	    // Retrieve some of the model elements, those we know aren't language dependant
+	    public_collectionmeta = new CollectionMeta(CollectionDesignManager.collect_config.getPublic());
+
+	    // Creation
+	    JPanel header_panel = new DesignPaneHeader("CDM.GUI.General", "generalsettings");
+
+	    JPanel all_details_panel = new JPanel();
+	    JPanel details_panel = new JPanel();
+	    JPanel fields_panel = new JPanel();
+
+	    creator_label = new JLabel(Dictionary.get("CDM.General.Email.Creator"));
+	    
+	    creator_emailfield = new EmailField(Configuration.getColor("coloring.error_background", false));
+	    creator_emailfield.setToolTipText(Dictionary.get("CDM.General.Email.Creator_Tooltip"));
+	    
+	    maintainer_label = new JLabel(Dictionary.get("CDM.General.Email.Maintainer"));
+	    
+	    maintainer_emailfield = new EmailField(Configuration.getColor("coloring.error_background", false));
+	    maintainer_emailfield.setToolTipText(Dictionary.get("CDM.General.Email.Maintainer_Tooltip"));
+	    
+	    name_label = new JLabel(Dictionary.get("CDM.General.Collection_Name"));
+	    name_textfield = new JTextField();
+	    name_textfield.setToolTipText(Dictionary.get("CDM.General.Collection_Name_Tooltip"));
+	    
+	    JLabel short_name_label = new JLabel(Dictionary.get("NewCollectionPrompt.Collection_Name"));
+	    JTextField short_name_textfield = new JTextField(CollectionManager.getLoadedCollectionName());
+	    short_name_textfield.setEditable(false);
+	    short_name_textfield.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+	    JPanel icon_panel = new JPanel();
+	    icon_label = new JLabel(Dictionary.get("CDM.General.Icon_Collection"));
+	    icon_textfield = new JTextField();
+	    icon_textfield.setToolTipText(Dictionary.get("CDM.General.Icon_Collection_Tooltip")); 
+	    browse_about_icon_button = new GLIButton(Dictionary.get("General.Browse"));
+	    JPanel small_icon_panel = new JPanel();
+	    small_icon_label = new JLabel(Dictionary.get("CDM.General.Icon_Collection_Small"));
+	    small_icon_textfield = new JTextField();
+	    small_icon_textfield.setToolTipText(Dictionary.get("CDM.General.Icon_Collection_Small_Tooltip"));
+	    browse_home_icon_button = new GLIButton(Dictionary.get("General.Browse"));
+
+	    // public
+	    JPanel box_panel = new JPanel();
+	    public_checkbox = new JCheckBox(Dictionary.get("CDM.General.Access"), public_collectionmeta.getValue(CollectionMeta.TEXT).equals(StaticStrings.TRUE_STR));
+	    
+	    JPanel description_panel = new JPanel();
+	    description_label = new JLabel(Dictionary.get("CDM.General.Collection_Extra"));
+	    
+	    description_textarea = new JTextArea();
+	    description_textarea.setBackground(Configuration.getColor("coloring.editable_background", false));
+	    description_textarea.setToolTipText(Dictionary.get("CDM.General.Collection_Extra_Tooltip"));
+	    
+	    // Connection
+	    BrowseListener browse_listener = new BrowseListener(StaticStrings.IMAGES_PATH_RELATIVE_TO_GSDL_PREFIX);
+	    browse_about_icon_button.addActionListener(browse_listener);
+	    browse_home_icon_button.addActionListener(browse_listener);
+	    browse_listener = null;
+	    public_checkbox.addActionListener(CollectionDesignManager.change_listener);
+	    creator_emailfield.getDocument().addDocumentListener(CollectionDesignManager.change_listener);
+	    description_textarea.getDocument().addDocumentListener(CollectionDesignManager.change_listener);
+	    icon_textfield.getDocument().addDocumentListener(CollectionDesignManager.change_listener);
+	    maintainer_emailfield.getDocument().addDocumentListener(CollectionDesignManager.change_listener);
+	    name_textfield.getDocument().addDocumentListener(CollectionDesignManager.change_listener);
+	    name_textfield.getDocument().addDocumentListener(new CollectionTitleUpdater());
+	    small_icon_textfield.getDocument().addDocumentListener(CollectionDesignManager.change_listener);
+
+	    // Layout
+	    fields_panel.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	    fields_panel.setLayout(new BorderLayout(5,2));
+	    
+	    JPanel fields_label_panel = new JPanel();
+	    fields_label_panel.setLayout(new GridLayout(6,1));
+
+	    JPanel fields_box_panel = new JPanel();
+	    fields_box_panel.setLayout(new GridLayout(6,1));
+    
+	    // creator
+	    fields_label_panel.add(creator_label);
+	    fields_box_panel.add(creator_emailfield);
+
+	    // maintainer
+	    fields_label_panel.add(maintainer_label);
+	    fields_box_panel.add(maintainer_emailfield);
+
+	    // title
+	    fields_label_panel.add(name_label);
+	    fields_box_panel.add(name_textfield);
+
+	    // collection short name
+	    fields_label_panel.add(short_name_label);
+	    fields_box_panel.add(short_name_textfield);
+
+	    // icon
+	    fields_label_panel.add(icon_label);
+	    fields_box_panel.add(icon_panel);
+
+	    // small icon
+	    fields_label_panel.add(small_icon_label);
+	    fields_box_panel.add(small_icon_panel);
+
+	    fields_panel.add(fields_label_panel, BorderLayout.WEST);
+	    fields_panel.add(fields_box_panel, BorderLayout.CENTER);
+
+	    icon_panel.setLayout(new BorderLayout());
+	    icon_panel.add(icon_textfield, BorderLayout.CENTER);
+	    icon_panel.add(browse_about_icon_button, BorderLayout.EAST);
+
+	    small_icon_panel.setLayout(new BorderLayout());
+	    small_icon_panel.add(small_icon_textfield, BorderLayout.CENTER);
+	    small_icon_panel.add(browse_home_icon_button, BorderLayout.EAST);
+
+	    box_panel.setLayout(new GridLayout(1,1,5,2));
+	    box_panel.add(public_checkbox);
+
+	    description_panel.setLayout(new BorderLayout());
+	    description_panel.add(description_label, BorderLayout.NORTH);
+	    description_panel.add(new JScrollPane(description_textarea), BorderLayout.CENTER);
+	    
+	    details_panel.setLayout(new BorderLayout());
+	    details_panel.add(fields_panel, BorderLayout.NORTH);
+	    details_panel.add(box_panel, BorderLayout.CENTER);
+
+	    all_details_panel.setLayout(new BorderLayout());
+	    all_details_panel.add(details_panel, BorderLayout.NORTH);
+	    all_details_panel.add(description_panel, BorderLayout.CENTER);
+
+	    setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
+	    setLayout(new BorderLayout());
+	    add(header_panel, BorderLayout.NORTH);
+	    add(all_details_panel, BorderLayout.CENTER);
+	}
+
+	/** Destructor. */
+	public void destroy() {
+	}
+
+	/** Called to refresh the components. */
+	public void gainFocus() {
+             // Retrieve all of the elements that are dependant on default language.
+	    collection_extra_collectionmeta = CollectionDesignManager.collectionmeta_manager.getMetadatum(StaticStrings.COLLECTIONMETADATA_COLLECTIONEXTRA_STR);
+	    collection_name_collectionmeta = CollectionDesignManager.collectionmeta_manager.getMetadatum(StaticStrings.COLLECTIONMETADATA_COLLECTIONNAME_STR);
+	    
+	    creator_collectionmeta = new CollectionMeta(CollectionDesignManager.collect_config.getCreator());
+	    icon_collection_collectionmeta = CollectionDesignManager.collectionmeta_manager.getMetadatum(StaticStrings.COLLECTIONMETADATA_ICONCOLLECTION_STR);
+	    icon_collection_small_collectionmeta = CollectionDesignManager.collectionmeta_manager.getMetadatum(StaticStrings.COLLECTIONMETADATA_ICONCOLLECTIONSMALL_STR);
+	    maintainer_collectionmeta = new CollectionMeta(CollectionDesignManager.collect_config.getMaintainer());
+	    // Make sure the components are up to date
+	    creator_emailfield.setText(creator_collectionmeta.getValue(CollectionMeta.TEXT));
+	    creator_emailfield.setCaretPosition(0);
+	    description_textarea.setText(collection_extra_collectionmeta.getValue(CollectionMeta.TEXT));
+	    description_textarea.setCaretPosition(0);
+	    icon_textfield.setText(icon_collection_collectionmeta.getValue(CollectionMeta.TEXT));
+	    icon_textfield.setCaretPosition(0);
+	    maintainer_emailfield.setText(maintainer_collectionmeta.getValue(CollectionMeta.TEXT));
+	    maintainer_emailfield.setCaretPosition(0);
+	    name_textfield.setText(collection_name_collectionmeta.getValue(CollectionMeta.TEXT));
+	    name_textfield.setCaretPosition(0);
+	    small_icon_textfield.setText(icon_collection_small_collectionmeta.getValue(CollectionMeta.TEXT));
+	    small_icon_textfield.setCaretPosition(0);
+	    public_checkbox.setSelected(public_collectionmeta.getValue(CollectionMeta.TEXT).equals(StaticStrings.TRUE_STR));
+            ready = true;
+	}
+
+	/** Called to store the current value of the components. */
+	public void loseFocus() {
+	    // String values. Have to test if this component has actually ever recieved focus anyway.
+	    
+            if (!ready) return;
+
+	    public_collectionmeta.setValue((public_checkbox.isSelected() ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
+	    String creator_email_str = creator_emailfield.getText();
+	    creator_collectionmeta.setValue(creator_email_str);
+		// If the email is currently empty, store this email
+	    if(Configuration.getEmail() == null) {
+		Configuration.setEmail(creator_email_str); // Store the email address in the configuration
+	    }
+	    collection_extra_collectionmeta.setValue(description_textarea.getText());
+	    icon_collection_collectionmeta.setValue(icon_textfield.getText());
+	    maintainer_collectionmeta.setValue(maintainer_emailfield.getText());
+	    icon_collection_small_collectionmeta.setValue(small_icon_textfield.getText());
+	    collection_name_collectionmeta.setValue(name_textfield.getText());
+	 
+	
+    }
+
+	/** Listens for a click on either browse button, and when detected opens a file browser window initially pointed at the images folder of the collection. Once a user has selected a path, does it's best to construct the best address to the resource, such as _httpcollection_/images/about.gif */
+	private class BrowseListener
+	    implements ActionListener {
+
+	    private String prefix;
+
+	    public BrowseListener(String prefix_raw) {
+		this.prefix = prefix_raw.replaceAll(StaticStrings.COLNAME_PATTERN, CollectionManager.getLoadedCollectionName());
+	    }
+
+	    public void actionPerformed(ActionEvent event) {
+		// Open an almost standard file browser to the images folder of the current collection
+		File images_folder = new File(CollectionManager.getLoadedCollectionImagesDirectoryPath());
+		// If images isn't already there, create it
+		if(!images_folder.exists()) {
+		    images_folder.mkdirs();
+		}
+		JFileChooser file_chooser = new JFileChooser(images_folder);
+		file_chooser.setAcceptAllFileFilterUsed(false);
+		file_chooser.setDialogTitle(Dictionary.get("CDM.General.Browser_Title"));
+		file_chooser.setFileFilter(new ImageFilter());
+		file_chooser.setSize(400,300);
+		GUIUtils.disableRename(file_chooser);
+		int value = file_chooser.showOpenDialog(Gatherer.g_man);
+		// If the user hasn't cancelled, retrieve the file path selected
+		if(value == JFileChooser.APPROVE_OPTION) {
+		    // If the file isn't in the images folder, then ask the user if they want to copy it there
+		    File file = file_chooser.getSelectedFile();
+		    if (!file.getParentFile().equals(images_folder)) {
+			// Copy the file
+			try {
+			    File collection_image_file = new File(images_folder, file.getName());
+			    Gatherer.f_man.getQueue().copyFile(file, collection_image_file, true);
+
+			    // If we're using a remote Greenstone server, upload the image
+			    if (Gatherer.isGsdlRemote) {
+				RemoteGreenstoneServer.uploadCollectionFile(CollectionManager.getLoadedCollectionName(), collection_image_file);
+			    }
+			}
+			catch(Exception exception) {
+			    DebugStream.printStackTrace(exception);
+			    // Show warning
+			    String[] args = new String[] {file.getAbsolutePath(), images_folder.getAbsolutePath()};
+			    JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.General.Image_Copy_Failed", args), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
+			    // Nothing else we can do.
+			    return;
+			}
+		    }
+
+		    // Create the path starting _httpcollection_/images/<filename>
+		    String path = prefix + file.getName();
+		    if(event.getSource() == browse_about_icon_button) {
+			icon_textfield.setText(path);
+                        icon_collection_collectionmeta.setValue(icon_textfield.getText());
+		    }
+		    else {
+			small_icon_textfield.setText(path);
+                        icon_collection_small_collectionmeta.setValue(small_icon_textfield.getText());
+		    }
+		    path = null;
+		}
+	    }
+
+	    /** ImageFilter.java is a 1.4 example used by FileChooserDemo2.java. */
+	    private class ImageFilter
+		extends javax.swing.filechooser.FileFilter {
+
+		private Pattern pattern = null;
+
+		public ImageFilter() {
+		    pattern = Pattern.compile(".*\\.(gif|png|jpe?g)");
+		}
+
+		// Accept all directories and all .col files
+		public boolean accept(File f) {
+		    String filename = f.getName().toLowerCase();
+		    Matcher matcher = pattern.matcher(filename);
+		    return f.isDirectory() || matcher.matches();
+		}
+
+		// The description of this filter
+		public String getDescription() {
+		    return Dictionary.get("CDM.General.Image_Filter");
+		}
+	    }
+	}
+
+	private class CollectionTitleUpdater
+	    implements DocumentListener {
+	    /** Gives notification that an attribute or set of attributes changed. */
+	    public void changedUpdate(DocumentEvent e) {
+		setTitle();
+	    }
+	    /** Gives notification that there was an insert into the document. */
+	    public void insertUpdate(DocumentEvent e) {
+		setTitle();
+	    }
+	    /** Gives notification that a portion of the document has been removed. */
+	    public void removeUpdate(DocumentEvent e) {
+		setTitle();
+	    }
+	    
+	    private void setTitle() {
+		// Set the title
+		String collection_title = name_textfield.getText();
+		String collection_name = CollectionManager.getLoadedCollectionName();
+		Gatherer.g_man.setTitle(collection_title, collection_name);
+                collection_name_collectionmeta.setValue(name_textfield.getText());
+		collection_title = null;
+		collection_name = null;
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/Index.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/Index.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/Index.java	(revision 13928)
@@ -0,0 +1,309 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import java.util.*;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.metadata.MetadataElement;
+import org.greenstone.gatherer.metadata.MetadataTools;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.XMLTools;
+import org.w3c.dom.*;
+
+/** This class encapsulates a single indexing pair.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3d
+ */
+public class Index
+    implements Comparable, DOMProxyListEntry {
+    /** An values of items in the index level enumeration. */
+    static protected final String LEVEL[] = {StaticStrings.DOCUMENT_STR,  StaticStrings.SECTION_STR, StaticStrings.PARAGRAPH_STR};
+
+    private ArrayList sources = null;
+    /** The level of this index (if old sckool MG). */
+    private int level = -1;
+    /** The element this index is based upon. */
+    private Element element = null;
+    /** The unique, if cryptic, identifier of an index. */
+    private String id = null;
+
+    /** Default constructor, which should only be used during DOMProxyListModel creation. */
+    public Index() {
+    }
+
+    /** Constructor. */
+    public Index(Element element) {
+	this.element = element;
+    }
+
+    /** Constructor for a newly assigned index. */
+    public Index(ArrayList sources) {
+	this.sources = sources;
+	// Create a new element
+	this.element = CollectionConfiguration.createElement(StaticStrings.INDEX_ELEMENT);
+	// For each source add a content element
+	int size = sources.size();
+	for(int i = 0; i < size; i++) {
+	    Element content_element = CollectionConfiguration.createElement(StaticStrings.CONTENT_ELEMENT);
+	    Object source_object = sources.get(i);
+	    if (source_object instanceof MetadataElement) {
+		// System.err.println("Constructing new Index with MetadataElement source...");
+		content_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, ((MetadataElement) source_object).getFullName());
+	    }
+	    else {
+		// System.err.println("Constructing new Index with String source...");
+		content_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, source_object.toString());
+	    }
+	    element.appendChild(content_element);
+	    content_element = null;
+	}
+    }
+
+    /** Constructor for a newly assigned index with specified level (old skool). */
+    public Index(int level, ArrayList sources) {
+	this(sources);
+	this.level = level;
+	element.setAttribute(StaticStrings.LEVEL_ATTRIBUTE, LEVEL[level]);
+    }
+
+    public Index(String level, ArrayList sources) {
+	this(sources);
+	for(int i = 0; i < LEVEL.length; i++) {
+	    if(LEVEL[i].equalsIgnoreCase(level)) {
+		this.level = i;
+	    }
+	}
+	element.setAttribute(StaticStrings.LEVEL_ATTRIBUTE, LEVEL[this.level]);
+    }
+
+    /** Method to compare two indexes.
+     * @param object The other index as an <strong>Object</strong>.
+     * @return An <i>int</i> which indicates how the indexes compare.
+     * @see java.lang.String
+     */
+    public int compareTo(Object object) {
+	if(object == null) {
+	    return -1;
+	}
+	String id = getID();
+	return id.compareTo(((Index)object).getID());
+    }
+    
+    public DOMProxyListEntry create(Element element) {
+	return new Index(element);
+    }
+
+    /** Method to test for the equality of two indexes.
+     * @param object The other index as an <strong>Object</strong>.
+     * @return A <i>boolean</i> which is <i>true</i> if the two indexes are equal, <i>false</i> otherwise.
+     */
+    public boolean equals(Object object) {
+	return (compareTo(object) == 0);
+    }
+    
+    public Element getElement() {
+	return element;
+    }
+    
+    /** Method to get the value of level.
+     * @return the level as a int
+     */
+    public int getLevel() {
+	if(level == -1 && element != null) {
+	    String level_str = element.getAttribute(StaticStrings.LEVEL_ATTRIBUTE);
+	    for(int i = 0; level == -1 && i < LEVEL.length; i++) {
+		if(level_str.equals(LEVEL[i])) {
+		    level = i;
+		}
+	    }
+	    level_str = null;
+	}
+	return level;
+    }
+
+    public String getID() {
+	if(element == null) {
+	    id="";
+	}
+	else if(id == null) {
+	    StringBuffer id_buffer = new StringBuffer();
+	    // Write level information, if any.
+	    int level = getLevel();
+	    if(0 <= level && level < 3) {
+		id_buffer.append(LEVEL[level]);
+		id_buffer.append(StaticStrings.COLON_CHARACTER);
+	    }
+	    // Write data information. Retrieve each of the content sources and add them in a comma separated list.
+	    ArrayList sources = getSources();
+	    int sources_size = sources.size();
+	    for(int i = 0; i < sources_size; i++) {
+		Object source_object = sources.get(i);
+		if (source_object instanceof MetadataElement) {
+		    String full_element_name = ((MetadataElement)source_object).getFullName();
+		    if(full_element_name.startsWith(StaticStrings.EXTRACTED_NAMESPACE)) {
+		       id_buffer.append(full_element_name.substring(StaticStrings.EXTRACTED_NAMESPACE.length()));
+		    }
+		    else {
+			id_buffer.append(full_element_name);
+		    }
+		}
+		else {
+		    id_buffer.append(source_object.toString());
+		}
+		id_buffer.append(StaticStrings.COMMA_CHARACTER);
+	    }
+	    sources = null;
+	    if (id_buffer.length()==0) {
+		id = "";
+	    } else {
+		id = id_buffer.substring(0, id_buffer.length() - 1);
+	    }
+	}
+	return id;
+    }
+
+
+    /** Retrieve the sources of this index.
+     * @return the sources as an ArrayList
+     */
+    public ArrayList getSources() {
+	if(sources == null) {
+	    sources = new ArrayList();
+	    NodeList content_elements = element.getElementsByTagName(StaticStrings.CONTENT_ELEMENT);
+	    int content_elements_length = content_elements.getLength();
+	    for(int i = 0; i < content_elements_length; i++) {
+		Element content_element = (Element) content_elements.item(i);
+		String metadata_element_name_full = (String) content_element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
+		MetadataElement metadata_element = MetadataTools.getMetadataElementWithName(metadata_element_name_full);
+		if (metadata_element != null) {
+		    sources.add(metadata_element);
+		}
+		else {
+		    sources.add(metadata_element_name_full);
+		}
+	    }
+	    content_elements = null;
+	}
+	return sources;
+    }
+
+    public boolean isAssigned() {
+	return (element != null && !element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.FALSE_STR));
+    }
+
+    public void setAssigned(boolean assigned) {
+	if(element != null) {
+	    element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, (assigned ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
+	}
+    }
+
+    public void setElement(Element element) {
+	this.element = element;
+	this.level = -1;
+	this.id = null;
+	this.sources = null;
+    }
+
+    /** Method to set the level of this index which can only be used for the default index. 
+     * @param new_level the new level as an int
+     */
+    public void setLevel(int new_level) {
+	// System.err.println("SetLevel(" + new_level + ")");
+	if(element != null && element.getNodeName().equals(StaticStrings.INDEX_DEFAULT_ELEMENT)) {
+	    if (0 <= new_level && new_level < 3) {
+		element.setAttribute(StaticStrings.LEVEL_ATTRIBUTE, LEVEL[new_level]);
+	    } else {
+		element.setAttribute(StaticStrings.LEVEL_ATTRIBUTE, "");
+	    }
+	    this.id = null; // Regenerate ID.
+	    this.level = new_level;
+	}
+	else {
+	    DebugStream.println("Error! Called setLevel() of index other than the default.");
+	}
+    }
+
+    /** Method to set the sources for this index which can only be used for the default index.
+     * @param sources an ArrayList of source names
+     */
+    public void setSources(ArrayList sources) {
+	if(element != null && element.getNodeName().equals(StaticStrings.INDEX_DEFAULT_ELEMENT)) {
+	    // Erase old sources
+	    XMLTools.clear(element);
+	    // For each entry in the sources array add a new content element.
+	    int size = sources.size();
+	    for(int i = 0; i < size; i++) {
+		Element content_element = element.getOwnerDocument().createElement(StaticStrings.CONTENT_ELEMENT);
+		Object source_object = sources.get(i);
+		if (source_object instanceof MetadataElement) {
+		    String name = ((MetadataElement) source_object).getFullName();
+		    content_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, name);
+		    name = null;
+		}
+		else {
+		    //DebugStream.println("Found String as source: " + source_object.toString());
+		    content_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, source_object.toString());
+		}
+		source_object = null;
+		element.appendChild(content_element);
+		content_element = null;
+	    }
+	    this.id = null; // Regenerate ID.
+	    this.sources = sources;
+	}
+	else {
+	    DebugStream.println("Error! Called setSource() of index other than the default.");
+	}
+    }
+
+    /** Method to turn this object into a string representation ready to be placed in the collection configuration file.
+     * @return A <strong>String</strong> containing the information of this class.
+     */
+    public String toString() {
+	StringBuffer text_buffer = new StringBuffer("");
+	// Generate language dependant id (include extracted metadata namespace)
+	// Write level information, if any.
+	int level = getLevel();
+	if(0 <= level && level < 3) {
+	    text_buffer.append(LEVEL[level]);
+	    text_buffer.append(StaticStrings.COLON_CHARACTER);
+	}
+	// Write data information. Retrieve each of the content sources and add them in a comma separated list.
+	ArrayList sources = getSources();
+	int sources_size = sources.size();
+	for(int i = 0; i < sources_size; i++) {
+	    String source_name = (sources.get(i)).toString();
+	    text_buffer.append(source_name);
+	    if(i < sources_size - 1) {
+		text_buffer.append(StaticStrings.COMMA_CHARACTER);
+	    }
+	}
+	sources = null;
+	return text_buffer.toString();
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/IndexManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/IndexManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/IndexManager.java	(revision 13928)
@@ -0,0 +1,1005 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.gui.DesignPaneHeader;
+import org.greenstone.gatherer.gui.GComboBox;
+import org.greenstone.gatherer.gui.GLIButton;
+import org.greenstone.gatherer.gui.ModalDialog;
+import org.greenstone.gatherer.gui.SimpleMenuBar;
+import org.greenstone.gatherer.metadata.MetadataElement;
+import org.greenstone.gatherer.metadata.MetadataSetManager;
+import org.greenstone.gatherer.util.CheckList;
+import org.greenstone.gatherer.util.JarTools;
+import org.greenstone.gatherer.util.XMLTools;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.w3c.dom.*;
+/** This class is resposible for storing the indexes which have been assigned to this collection and the default index, and providing methods for interacting with both these data pools. It also knows how to turn itself into a String as it would be displayed in the collection configuration file.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class IndexManager
+    extends DOMProxyListModel 
+    implements BuildTypeManager.BuildTypeListener {
+
+    /** A reference to ourselves so our inner methods have access. */
+    private DOMProxyListModel index_model = null;
+    /** The default index. */
+    private Index default_index = null;
+
+    private Control controls = null;
+    private String build_type = null;
+    
+    static final private Dimension FIELD_SIZE = new Dimension(200,30);
+    static final private String ALLFIELDS = "allfields";
+
+    static final private Dimension PROMPT_SIZE = new Dimension(400,400);
+    public IndexManager(Element indexes, String current_build_type) {
+
+	super(indexes, StaticStrings.INDEX_ELEMENT, new Index());
+	DebugStream.println("IndexManager: " + getSize() + " indexes parsed.");
+	index_model = this;
+      
+       
+	// Parse and retrieve the default index
+	NodeList default_index_elements = CollectionConfiguration.getElementsByTagName(StaticStrings.INDEX_DEFAULT_ELEMENT);
+	if(default_index_elements.getLength() > 0) {
+	             
+	    default_index = new Index((Element)default_index_elements.item(0));
+	}
+	build_type = current_build_type;
+    }
+
+    /** Method to add a new index.
+     * @param index The <strong>Index</strong> to add.
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.collection.CollectionManager
+     */
+    private void addIndex(Index index, CollectionMeta metadatum) {
+	///ystem.err.println("Adding an index: " + index.toString());
+	if(!contains(index)) {
+	    CollectionDesignManager.collectionmeta_manager.addMetadatum(metadatum);
+	    // Retrieve the currently last index
+	    if(getSize() > 0) {
+		Index last_index = (Index)getElementAt(getSize() - 1);
+		addAfter(index, last_index);
+		
+	    }
+	    else {
+		add(index);
+		// Also set this index as the default one, 
+		setDefault(index);
+	    }
+	}
+	else {
+	    JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.IndexManager.Index_Exists"), Dictionary.get("General.Warning"), JOptionPane.WARNING_MESSAGE);
+	}
+    }
+
+    public void buildTypeChanged(String new_build_type) {
+	if (build_type.equals(new_build_type)) {
+	    return;
+	}
+	// we don;t care about this if old or new is not MG as MGPP and 
+	// Lucene have the same index specification
+	if (!build_type.equals(BuildTypeManager.BUILD_TYPE_MG) && !new_build_type.equals(BuildTypeManager.BUILD_TYPE_MG)) {
+	    return;
+	}
+	boolean mg_to_mgpp = true;
+	if (new_build_type.equals(BuildTypeManager.BUILD_TYPE_MG)) {
+	    mg_to_mgpp = false;
+	}
+	build_type  = new_build_type;
+	if (mg_to_mgpp) {
+	    changeToMGPPIndexes();
+	} else {
+	    changeToMGIndexes();
+	}
+	// its really hard to transfer defaults between mgpp/lucene and mg indexes, so we'll just set the first one to be the default
+	Index first_index = (Index) getElementAt(0);
+	setDefault(first_index);
+	first_index = null;
+    }
+    
+    private void changeToMGIndexes() {
+	Element mgpp_element = root;
+	// Retrieve and assign MG element and default index element
+	Element mg_element = CollectionDesignManager.collect_config.getMGIndexes();
+	mg_element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+	NodeList indexes = mg_element.getElementsByTagName(StaticStrings.INDEX_ELEMENT);
+	if(indexes.getLength() != 0) {
+	    //just reinstate what we had previously
+	    setRoot(mg_element);
+	} else {
+	    // If mg element has no indexes, and the current mgpp index includes a text one, then generate text indexes for each of the registered levels.
+	    Index index = getIndex(StaticStrings.TEXT_STR);
+	    if(index != null) {
+		// Replace mgpp element with mg element
+		setRoot(mg_element);
+		ArrayList levels = CollectionDesignManager.index_manager.getLevels();
+		int level_size = levels.size();
+		for(int i = 0; i < level_size; i++) {
+		    IndexOption level = (IndexOption) levels.get(i);
+		    Index new_index = new Index(level.getName(), index.getSources());
+		    // Try to retrieve existing metadatum
+		    String source_str = new_index.getID();
+		    CollectionMeta metadatum = CollectionDesignManager.collectionmeta_manager.getMetadatum(StaticStrings.STOP_CHARACTER + source_str, false);
+		    // If no metadata was found, add new pseudo metadata using the id
+		    if(metadatum == null) {
+			metadatum = new CollectionMeta(StaticStrings.STOP_CHARACTER + source_str);
+			metadatum.setAssigned(true);
+			metadatum.setValue(source_str);
+		    }
+		    // If it was found, ensure it is assigned
+		    else {
+			metadatum.setAssigned(true);
+		    }
+		    source_str = null;
+		    addIndex(new_index, metadatum);
+		    new_index = null;
+		    level = null;
+		}
+	    }
+	}
+	
+	// Unassign mgpp element 
+	mgpp_element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
+	mgpp_element = null;
+	
+    }
+
+    private void changeToMGPPIndexes() {
+	Element mg_element = root;
+	// Retrieve and assign the MGPP indexes element.
+	Element mgpp_element = CollectionDesignManager.collect_config.getMGPPIndexes();
+	mgpp_element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+	NodeList indexes = mgpp_element.getElementsByTagName(StaticStrings.INDEX_ELEMENT);
+	if(indexes.getLength() != 0) {
+	    // we just reinstate the indexes we had before the change
+	    setRoot(mgpp_element);
+	} else {
+	    // If the MGPP indexes element is empty (ie was created by CollectionConfiguration), generate new MGPP index from the existing index
+	    
+	    ArrayList sources_list = new ArrayList();
+	    // We first use details from the default index if any
+	    if(default_index != null) {
+		ArrayList sources = default_index.getSources();
+		sources_list.addAll(sources);
+	    }
+	    int size = getSize();
+	    for(int i = 0; i < size; i++) {
+		Index index = (Index) getElementAt(i);
+		ArrayList sources = index.getSources();
+		sources.removeAll(sources_list);
+		sources_list.addAll(sources);
+		index = null;
+	    }
+	    // Replace mg element with mgpp element
+	    setRoot(mgpp_element);
+	    
+	    // We now have a list of sources, so create new indexes based on these
+	    int sources_list_size = sources_list.size();
+	    for(int j = 0; j < sources_list_size; j++) {
+		Object source_object = sources_list.get(j);
+		String source_str = null;
+		if(source_object instanceof MetadataElement) {
+		    source_str = ((MetadataElement) source_object).getFullName();
+		}
+		else {
+		    source_str = source_object.toString();
+		}
+		ArrayList new_sources = new ArrayList();
+		new_sources.add(source_object);
+		source_object = null;
+		Index new_index = new Index(new_sources);
+		// Try to retrieve existing metadatum
+		source_str = new_index.getID();
+		CollectionMeta metadatum = CollectionDesignManager.collectionmeta_manager.getMetadatum(StaticStrings.STOP_CHARACTER + source_str, false);
+		// If no metadata was found, add new pseudo metadata using the id
+		if(metadatum == null) {
+		    metadatum = new CollectionMeta(StaticStrings.STOP_CHARACTER + source_str);
+		    metadatum.setAssigned(true);
+		    metadatum.setValue(source_str);
+		}
+		// If it was found, ensure it is assigned
+		else {
+		    metadatum.setAssigned(true);
+		}
+		source_str = null;
+		addIndex(new_index, metadatum);
+		metadatum = null;
+		new_index = null;
+		new_sources = null;
+		source_str = null;
+	    }
+	    
+	}
+
+	// Unassign MG element
+	mg_element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
+	mg_element = null;
+	
+    }
+    
+    public Control getControls() {
+	if (controls == null) {
+	    controls = new IndexControl();
+	}
+	return controls;
+    }
+
+    /** Method to retrieve a certain index, as referenced by an index number.
+     * @param index An <i>int</i> which indicates the position of the desired index.
+     * @return The <strong>Index</strong> at the given index, or <i>null</i> if no such index exists.
+     */
+    public Index getIndex(int index) {
+	if(0 <= index && index < getSize()) {
+	    return (Index)getElementAt(index);
+	}
+	return null;
+    }
+
+    /** Method to retrieve a certain index, given its id.
+     * @param id the id of the index as a String
+     * @return the Index that matches id, or null if no such index exists
+     */
+    public Index getIndex(String id) {
+	int size = getSize();
+	for(int i = 0; i < size; i++) {
+	    Index index = (Index) getElementAt(i);
+	    if(index.getID().equals(id)) {
+		return index;
+	    }
+	}
+	return null;
+    }
+
+    public ArrayList getIndexes() {
+	return children();
+    }
+
+
+
+    /** Called when the detail mode has changed which in turn may cause several design elements to be available/hidden
+     * @param mode the new mode as an int
+     */
+    public void modeChanged(int mode) {
+
+    }
+
+    private void moveIndex(Index index, boolean move_up)
+    {
+	// Determine the current position of the index
+	int position = indexOf(index);
+	// Determine if it can be moved, ie if its not already at the top trying to move up, or at the bottom trying to move down.
+	if(position == -1) {
+	    return;
+	}
+	if(position == 0 && move_up) {
+	    return;
+	}
+	if(position == (getSize()) - 1 && !move_up) {
+	    return;
+	}
+	
+	// Ok, move up
+	if (move_up) {
+	    position--;
+	    remove(index);
+	    add(position, index);
+	}
+
+	// Or move down
+	else {
+	    position++;
+	    remove(index);
+	    add(position, index);
+	}
+    }
+
+
+
+    /** Method to remove a certain index.
+     * @param index the Index to remove.
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.cdm.CollectionDesignManager
+     * @see org.greenstone.gatherer.cdm.CollectionMetaManager
+     * @see org.greenstone.gatherer.collection.CollectionManager
+     */
+    private void removeIndex(Index index) {
+	if(index != null) {
+	    // Remove any current metadata from this index
+	    CollectionDesignManager.collectionmeta_manager.removeMetadata(StaticStrings.STOP_CHARACTER + index.getID());
+	    // Remove the index
+	    remove(index);
+	    // Check if the index removed happens to be the default index
+	    if(default_index != null && default_index.equals(index)) {
+		// If so our first solution is to set the first index to be default
+		if(getSize() > 0) {
+		    Index another_index = (Index) getElementAt(0);
+		    setDefault(another_index);
+		    another_index = null;
+		}
+		else {
+		    default_index.setAssigned(false);
+		}
+	    }
+	}
+    }
+
+
+    /* replace an index in the list. new index may have the same sources but a
+       different name, or may be a new index altogether */
+    private void replaceIndex(Index old_index, Index new_index,
+			      CollectionMeta coll_meta) {
+	if (old_index == null || new_index == null || coll_meta == null) {
+	    return;
+	}
+	if (!old_index.getID().equals(new_index.getID()) && contains(new_index)) {
+	    // shoudl we output an error??
+	    return;
+	}
+	// Remove the old index coll meta
+	CollectionDesignManager.collectionmeta_manager.removeMetadata(StaticStrings.STOP_CHARACTER + old_index.getID());
+	// Add the new coll meta
+	CollectionDesignManager.collectionmeta_manager.addMetadatum(coll_meta);
+
+	// get the position of the old one
+	int position = indexOf(old_index);
+	// remove it
+	remove(old_index);
+	// add the new one at that position
+	add(position, new_index);
+    }
+
+
+    /** Method to set the default index.
+     * @param index the new default Index
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.collection.CollectionManager
+     */
+    public void setDefault(Index index) {
+	if(index != null) {
+	    if(default_index == null) {
+		// Create the default index element, and place immediately after indexes element.
+		Element default_index_element = root.getOwnerDocument().createElement(StaticStrings.INDEX_DEFAULT_ELEMENT);               
+		default_index = new Index(default_index_element);
+		Node target_node = CollectionConfiguration.findInsertionPoint(default_index_element);
+		if(target_node != null) {
+		    root.getOwnerDocument().getDocumentElement().insertBefore(default_index_element, target_node);
+		}
+		else {
+		    root.getOwnerDocument().getDocumentElement().appendChild(default_index_element);
+		}
+	    }
+	    default_index.setAssigned(true);
+	    default_index.setLevel(index.getLevel());
+	    default_index.setSources(index.getSources());
+	    
+	}
+	else {
+	    if(default_index != null) {
+		default_index.setAssigned(false);
+	    }
+	}
+    }
+
+
+    private class IndexControl
+	extends JPanel
+	implements Control {
+
+	private JList index_list;
+	private JButton move_down_button;
+	private JButton move_up_button;
+	private JButton set_default_button;
+
+	private JButton new_button;
+	private JButton edit_button;
+	private JButton remove_button;
+
+	public IndexControl() {
+	    super();
+
+	    // Creation
+	    JPanel assigned_indexes_pane = new JPanel();
+	    
+	    JLabel index_label = new JLabel(Dictionary.get("CDM.IndexManager.Indexes"));
+	    index_list = new JList(index_model);
+	    index_list.setCellRenderer(new IndexListRenderer());
+	    index_list.setVisibleRowCount(6);
+	    index_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+
+	    JPanel movement_pane = new JPanel();
+	    move_up_button = new GLIButton(Dictionary.get("CDM.Move.Move_Up"), JarTools.getImage("arrow-up.gif"), Dictionary.get("CDM.Move.Move_Up_Tooltip"));
+	    move_up_button.setEnabled(false);
+	    
+	    move_down_button = new GLIButton(Dictionary.get("CDM.Move.Move_Down"), JarTools.getImage("arrow-down.gif"), Dictionary.get("CDM.Move.Move_Down_Tooltip"));
+	    move_down_button.setEnabled(false);
+	    	    
+	    set_default_button = new GLIButton(Dictionary.get("CDM.IndexManager.Set_Default"), Dictionary.get("CDM.IndexManager.Set_Default_Tooltip"));
+	    set_default_button.setEnabled(false);
+	    
+	    JPanel button_pane = new JPanel();
+	    new_button = new GLIButton(Dictionary.get("CDM.IndexManager.New_Index")+StaticStrings.FURTHER_DIALOG_INDICATOR, Dictionary.get("CDM.IndexManager.New_Index_Tooltip"));
+	    new_button.setEnabled(true);
+	    
+	    edit_button = new GLIButton(Dictionary.get("CDM.IndexManager.Edit_Index")+StaticStrings.FURTHER_DIALOG_INDICATOR, Dictionary.get("CDM.IndexManager.Edit_Index_Tooltip"));
+	    edit_button.setEnabled(false);
+	    
+	    remove_button = new GLIButton(Dictionary.get("CDM.IndexManager.Remove_Index"), Dictionary.get("CDM.IndexManager.Remove_Index_Tooltip"));
+	    remove_button.setEnabled(false);
+	    	  
+	    // Listeners
+	    new_button.addActionListener(new NewIndexListener());
+	    edit_button.addActionListener(new EditIndexListener());
+	    remove_button.addActionListener(new RemoveIndexListener());
+	    remove_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
+
+	    index_list.addListSelectionListener(new IndexListListener());
+
+	    move_down_button.addActionListener(new MoveListener(false));
+	    move_down_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
+	    move_up_button.addActionListener(new MoveListener(true));
+	    move_up_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
+
+	    set_default_button.addActionListener(new SetDefaultListener());
+	    // Layout
+	    movement_pane.setBorder(BorderFactory.createEmptyBorder(0,2,0,0));
+	    movement_pane.setLayout(new GridLayout(3,1));
+	    movement_pane.add(move_up_button);
+	    movement_pane.add(move_down_button);
+	    movement_pane.add(set_default_button);
+
+	    assigned_indexes_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
+	    assigned_indexes_pane.setLayout(new BorderLayout());
+	    assigned_indexes_pane.add(index_label, BorderLayout.NORTH);
+	    assigned_indexes_pane.add(new JScrollPane(index_list), BorderLayout.CENTER);
+	    assigned_indexes_pane.add(movement_pane, BorderLayout.EAST);
+
+	    button_pane.setLayout(new GridLayout(1,3,5,0));
+	    button_pane.add(new_button);
+	    button_pane.add(edit_button);
+	    button_pane.add(remove_button);
+
+	    setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
+	    setLayout(new BorderLayout());
+	    add(assigned_indexes_pane, BorderLayout.CENTER);
+	    add(button_pane, BorderLayout.SOUTH);
+	    
+	}
+	public void loseFocus() {}
+	public void gainFocus() {}
+	public void destroy() {}
+	
+	private class IndexListListener
+	    implements ListSelectionListener {
+	    
+	    /** This method is called whenever the source list selection changes. When it does we need to fill in the various parts of the list description panel
+	     * @param event A <strong>ListSelectionEvent</strong> containing further information about the list selection.
+	     */
+	    public void valueChanged(ListSelectionEvent event)
+	    {
+		if (event.getValueIsAdjusting()) {
+		    return;
+		}
+		
+                set_default_button.setEnabled(true);
+		Object value = index_list.getSelectedValue();
+		if (value == null) {
+		    move_down_button.setEnabled(false);
+		    move_up_button.setEnabled(false);
+		    remove_button.setEnabled(false);
+		    edit_button.setEnabled(false);
+		    set_default_button.setEnabled(false);
+		    return;
+		}
+
+		// Enable the buttons appropriately
+		remove_button.setEnabled(true);
+		edit_button.setEnabled(true);
+		set_default_button.setEnabled(default_index == null || !default_index.equals(value));
+		int i = index_list.getSelectedIndex();
+		int size = index_list.getModel().getSize();
+		move_up_button.setEnabled((i>0));
+		move_down_button.setEnabled((i<size-1));
+	    }
+	}
+
+	private class IndexListRenderer
+	    extends DefaultListCellRenderer {
+
+	    /** Return a component that has been configured to display the specified value. */
+	    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+		JLabel component = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+		if(default_index != null && default_index.equals(value)) {
+		    component.setText(component.getText() + " " + Dictionary.get("CDM.IndexManager.Default_Index_Indicator"));
+		}
+		return component;
+	    }
+
+	}
+
+	private class NewIndexListener
+	    implements ActionListener {
+
+	    public void actionPerformed(ActionEvent event) {
+		NewIndexPrompt nip = new NewIndexPrompt(build_type, null);
+		nip.destroy();
+	    }
+	}
+	
+	private class EditIndexListener
+	    implements ActionListener {
+
+	    public void actionPerformed(ActionEvent event) {
+		Index index = (Index) index_list.getSelectedValue();
+		NewIndexPrompt nip = new NewIndexPrompt(build_type, index);
+		nip.destroy();
+	    }
+	}
+
+	private class RemoveIndexListener
+	    implements ActionListener {
+	    
+	    public void actionPerformed(ActionEvent event) {
+		
+		int i = index_list.getSelectedIndex();
+		if (i != -1) {
+		    removeIndex((Index) index_list.getSelectedValue());
+		}
+		int size = index_list.getModel().getSize();
+		if (i == size) {
+		    i--;
+		}
+		index_list.setSelectedIndex(i);
+		// This will produce an event on the list, updating the other buttons
+	    }
+	}
+
+	private class MoveListener
+	    implements ActionListener {
+
+	    private boolean move_up;
+
+	    public MoveListener(boolean move_up) {
+		this.move_up = move_up;
+	    }
+
+	    public void actionPerformed(ActionEvent event) {
+		// Retrieve the selected index
+		Index index = (Index) index_list.getSelectedValue();
+		if(index != null) {
+		    moveIndex(index, move_up);
+		    // Ensure the index that moved is still selected
+		    index_list.setSelectedValue(index, true);
+		    index = null;
+		}
+	    }
+	}
+
+	private class SetDefaultListener
+	    implements ActionListener {
+
+	    public void actionPerformed(ActionEvent event) {
+		Index index = (Index) index_list.getSelectedValue();
+		if(index != null) {
+		    setDefault(index);
+		    // This should cause a repaint of just the desired row
+		    index_list.setSelectedValue(index, true);
+		}
+		set_default_button.setEnabled(false);
+	    }
+	}
+
+	
+
+	private class NewIndexPrompt 
+	    extends ModalDialog {
+
+	    NewIndexPrompt new_index_prompt = null;
+	
+	    private JCheckBox text_checkbox;
+	    private CheckList source_list;
+	    // mg uses a level box
+	    private JComboBox level_combobox;
+	    // mgpp has a allfields selector
+	    private JCheckBox allfields_box;
+
+	    private JButton add_or_replace_button;
+	    private JButton select_all_button;
+	    private JButton select_none_button;
+	    private JButton add_all_button;
+	    //private JButton select_all_button;
+	    //private JButton replace_button;
+	    private JButton cancel_button;
+
+	    private boolean mgpp_enabled = false;
+	    private boolean editing = false;
+	
+	    public NewIndexPrompt(String build_type, Index existing_index) {
+		super(Gatherer.g_man, true);
+		new_index_prompt = this;
+
+		setModal(true);
+		setSize(PROMPT_SIZE);
+		if (existing_index != null) {
+		    setTitle (Dictionary.get("CDM.IndexManager.Edit_Index"));
+		    editing = true;
+		} else {
+		    setTitle(Dictionary.get("CDM.IndexManager.New_Index"));
+		}
+		
+		setJMenuBar(new SimpleMenuBar("searchindexes"));
+		if (build_type.equals(BuildTypeManager.BUILD_TYPE_MGPP) || build_type.equals(BuildTypeManager.BUILD_TYPE_LUCENE)) {
+		    mgpp_enabled = true;
+		}
+		JPanel content_pane = (JPanel)this.getContentPane();
+		ArrayList new_data = new ArrayList();
+		new_data.addAll(MetadataSetManager.getEveryMetadataSetElement());
+
+		JPanel details_pane = new JPanel();
+		
+		text_checkbox = new JCheckBox(Dictionary.get("CDM.IndexManager.Text_Source"));
+		text_checkbox.setToolTipText(Dictionary.get("CDM.IndexManager.Text_Source_Tooltip"));
+		text_checkbox.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent event) {
+			    validateAddOrReplaceButton();
+			}
+		    });
+		JLabel source_label = new JLabel(Dictionary.get("CDM.IndexManager.Source"));
+		source_list = new CheckList(false);
+		source_list.setListData(new_data);
+		source_list.setToolTipText(Dictionary.get("CDM.IndexManager.Source_Tooltip"));
+		source_list.addListSelectionListener(new SourceListListener());
+
+		JPanel button_pane = new JPanel();
+		button_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+		
+		if (existing_index == null && mgpp_enabled) {
+		    button_pane.setLayout(new GridLayout(2,3,5,0));
+		    button_pane.add(new JPanel());
+		} else {
+		    button_pane.setLayout(new GridLayout(2,2,5,0));
+		}
+		
+		select_all_button = new GLIButton(Dictionary.get("CDM.IndexManager.Select_All"), Dictionary.get("CDM.IndexManager.Select_All_Tooltip"));
+		select_all_button.addActionListener(new ActionListener() {
+			
+			public void actionPerformed(ActionEvent event) {
+			    text_checkbox.setSelected(true);
+			    source_list.setAllTicked();
+			    validateAddOrReplaceButton();
+			}
+		    });
+		
+		select_none_button = new GLIButton(Dictionary.get("CDM.IndexManager.Select_None"), Dictionary.get("CDM.IndexManager.Select_None_Tooltip"));
+		select_none_button.addActionListener(new ActionListener() {
+			
+			public void actionPerformed(ActionEvent event) {
+			    text_checkbox.setSelected(false);
+			    source_list.clearTicked();
+			    validateAddOrReplaceButton();
+			}
+		    });
+		
+		
+		button_pane.add(select_all_button);
+		button_pane.add(select_none_button);
+		
+		if (existing_index != null) {
+		    add_or_replace_button = new GLIButton(Dictionary.get("CDM.IndexManager.Replace_Index"), Dictionary.get("CDM.IndexManager.Replace_Index_Tooltip"));
+		    add_or_replace_button.addActionListener(new ReplaceIndexListener());
+		} else {
+		    add_or_replace_button = new GLIButton(Dictionary.get("CDM.IndexManager.Add_Index"), Dictionary.get("CDM.IndexManager.Add_Index_Tooltip"));
+		    add_or_replace_button.addActionListener(new AddIndexListener());
+		}
+
+		add_or_replace_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
+		add_or_replace_button.setEnabled(false);
+		button_pane.add(add_or_replace_button);
+		
+		if (existing_index == null && mgpp_enabled) {
+		    add_all_button = new GLIButton(Dictionary.get("CDM.IndexManager.Add_All"), Dictionary.get("CDM.IndexManager.Add_All_Tooltip"));
+		    add_all_button.setEnabled(true);
+		    add_all_button.addActionListener(new AddAllIndexActionListener());
+		    button_pane.add(add_all_button);
+		} 
+		
+		// always have a cancel button
+		cancel_button = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("General.Cancel"));
+		cancel_button.setEnabled(true);
+		cancel_button.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent event) {
+			    new_index_prompt.dispose();
+			}
+		    });
+		button_pane.add(cancel_button);
+
+		//Layout
+		details_pane.setLayout(new BorderLayout(10,10));
+		details_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+		details_pane.add(text_checkbox, BorderLayout.NORTH);
+		details_pane.add(new JScrollPane(source_list), BorderLayout.CENTER);
+
+
+		// do type specific stuff
+		if (mgpp_enabled) {
+		    // allfields
+		    allfields_box = new JCheckBox(Dictionary.get("CDM.IndexManager.Allfields_Index"));
+		    allfields_box.addItemListener(new AllFieldsBoxListener());
+		    //JLabel allfields_label = new JLabel(Dictionary.get("CDM.IndexManager.Allfields_Index"));
+		    details_pane.add(allfields_box, BorderLayout.SOUTH);
+		    
+		    
+		} else {
+		    // index level
+		    JLabel level_label = new JLabel(Dictionary.get("CDM.IndexManager.Level"));
+		    level_combobox = new JComboBox();
+		    level_combobox.setOpaque(false);
+		    level_combobox.setPreferredSize(FIELD_SIZE);
+		    // Note the order of these must be the same as the
+		    // level order in Index
+		    level_combobox.addItem(StaticStrings.DOCUMENT_STR);//Dictionary.get("CDM.LevelManager.Document"));
+		    level_combobox.addItem(StaticStrings.SECTION_STR);//Dictionary.get("CDM.LevelManager.Section"));
+		    level_combobox.addItem(StaticStrings.PARAGRAPH_STR);//Dictionary.get("CDM.LevelManager.Paragraph"));
+		    level_combobox.setEditable(false);
+		    level_combobox.setToolTipText(Dictionary.get("CDM.IndexManager.Level_Tooltip"));
+		    level_combobox.addActionListener(new ActionListener() {
+			    public void actionPerformed(ActionEvent event) {
+				validateAddOrReplaceButton();
+			    }
+			});
+		    JPanel level_pane = new JPanel();
+		    level_pane.setLayout(new BorderLayout());
+		    level_pane.add(level_label, BorderLayout.WEST);
+		    level_pane.add(level_combobox, BorderLayout.CENTER);
+		    details_pane.add(level_pane, BorderLayout.SOUTH);
+
+		}
+		// if we are editing, fill in the controls
+		if (existing_index !=null) {
+		    ArrayList sources = existing_index.getSources();
+		    if (mgpp_enabled && sources.get(0).equals(ALLFIELDS)) {
+			allfields_box.setSelected(true);
+			source_list.setEnabled(false);
+		    } else {
+			source_list.setTickedObjects(sources.toArray());
+			source_list.setEnabled(true);
+			if (sources.contains(StaticStrings.TEXT_STR)) {
+			    text_checkbox.setSelected(true);
+			}
+		    } 
+		    if (!mgpp_enabled) {
+			level_combobox.setSelectedIndex(existing_index.getLevel());
+		    }
+		    
+		}
+		content_pane.setLayout(new BorderLayout());
+		content_pane.add(source_label, BorderLayout.NORTH);
+		content_pane.add(details_pane, BorderLayout.CENTER);
+		content_pane.add(button_pane, BorderLayout.SOUTH);
+	    
+		// Display on screen.
+		Dimension screen_size = Configuration.screen_size;
+		setLocation((screen_size.width - PROMPT_SIZE.width) / 2, (screen_size.height - PROMPT_SIZE.height) / 2);
+		screen_size = null;
+		setVisible(true);
+	    
+	    }
+
+	    /** Method which actually forces the dialog to be shown on screen.
+	     * @return <i>true</i> if the user completed configuration and pressed ok, <i>false</i> otherwise.
+	     */
+	    public boolean display() {
+		setVisible(true);
+		return true;
+		//    return success;
+	    }
+	
+	    public void destroy() {
+	    }
+
+	    // Checks that specified index not already in the collection
+	    private void validateAddOrReplaceButton() {
+		Index index;
+		ArrayList sources;
+		if (mgpp_enabled && allfields_box.isSelected()) {
+		    sources = new ArrayList();
+		    sources.add(ALLFIELDS);
+		    index = new Index(sources);
+		    
+		} else if (text_checkbox.isSelected() || 
+			   !source_list.isNothingTicked()) {
+		    sources = source_list.getTicked();
+		    if (text_checkbox.isSelected()) {
+			sources.add(0, StaticStrings.TEXT_STR);
+		    }		    
+		    if (mgpp_enabled) {
+			index = new Index(sources);
+		    } else {
+			index = new Index(level_combobox.getSelectedIndex(), sources);
+		    }
+		} else {
+		    // nothing selected
+		    add_or_replace_button.setEnabled(false);
+		    return;
+		}
+		
+		sources = null;
+		if (index_model.contains(index)) {
+		    add_or_replace_button.setEnabled(false);
+		}
+		else {
+		    add_or_replace_button.setEnabled(true);
+		}
+		
+	    }
+	    private class AddIndexListener
+		implements ActionListener
+	    {
+		public void actionPerformed(ActionEvent event)
+		{
+		    Index index;
+		    if (mgpp_enabled && allfields_box.isSelected()) {
+			ArrayList sources = new ArrayList();
+			sources.add(ALLFIELDS);
+			index = new Index(sources);
+		    }
+		    else if (text_checkbox.isSelected() || 
+			     !source_list.isNothingTicked()) {
+			ArrayList sources = source_list.getTicked();
+			if (text_checkbox.isSelected()) {
+			    sources.add(0, StaticStrings.TEXT_STR);
+			}
+			if(mgpp_enabled) {
+			    index = new Index(sources);
+			} else {
+			    index = new Index(level_combobox.getSelectedIndex(), sources);
+			}
+		    } else {
+			return;
+		    }
+		 
+		    // Before we add the index to the model, we have to add a default collection metadata for this
+		    CollectionMeta metadatum = new CollectionMeta(StaticStrings.STOP_CHARACTER + index.getID());
+		    metadatum.setValue(index.getID());
+		
+		    // Finally, add the index
+		    addIndex(index, metadatum);
+		    index_list.setSelectedValue(index, true);
+		    new_index_prompt.dispose();
+		}
+	    }
+
+	    /** add all sources as separate indexes (fields).  */
+	    private class AddAllIndexActionListener
+		implements ActionListener {
+
+		public void actionPerformed(ActionEvent event) {
+		    ArrayList all_sources = source_list.getAll();
+		    all_sources.add(0, StaticStrings.TEXT_STR);
+		    ArrayList new_sources = new ArrayList();
+		    for(int i = 0; i < all_sources.size(); i++) {
+			Object source = all_sources.get(i);
+
+			// Create new index
+			new_sources.clear();
+			new_sources.add(source);
+			Index index = new Index(new_sources);
+			if(!index_model.contains(index)) {
+			    // Determine the metadatum value
+			    String name = source.toString();
+			    if(name.startsWith(StaticStrings.EXTRACTED_NAMESPACE)) {
+				name = name.substring(StaticStrings.EXTRACTED_NAMESPACE.length());
+			    }
+			    // Create new metadatum
+			    CollectionMeta metadatum = new CollectionMeta(StaticStrings.STOP_CHARACTER + index.getID());
+			    metadatum.setValue(name);
+			    name = null;
+			    // Assign new index
+			    addIndex(index, metadatum);
+			}
+			source = null;
+			index = null;
+		    }
+		    new_sources = null;
+		    new_index_prompt.dispose();
+		
+		}
+	    }
+    
+	    private class AllFieldsBoxListener
+		implements ItemListener {
+		
+		public void itemStateChanged(ItemEvent event) {
+		    if (event.getStateChange() == ItemEvent.SELECTED) {
+			source_list.setEnabled(false);
+		    } else if (event.getStateChange() == ItemEvent.DESELECTED) {
+			source_list.setEnabled(true);
+		    }
+		    validateAddOrReplaceButton();
+		}
+		
+	    }
+
+	    private class SourceListListener
+		implements ListSelectionListener {
+	    
+		public void valueChanged(ListSelectionEvent event) {
+		    if (event.getValueIsAdjusting()) {
+			return;
+		    }
+		    validateAddOrReplaceButton();
+		}
+	    }
+	
+
+	    private class ReplaceIndexListener
+		implements ActionListener {
+	    
+		public void actionPerformed(ActionEvent event) {
+		
+		    ArrayList sources;
+		    Index index = null;
+		    if (text_checkbox.isSelected() || !source_list.isNothingTicked()) {
+			sources = source_list.getTicked();
+			if (text_checkbox.isSelected()) {
+			    sources.add(0, StaticStrings.TEXT_STR);
+			}
+			if (mgpp_enabled) {
+			    index = new Index(sources);
+			} else {
+			    index = new Index(level_combobox.getSelectedIndex(), sources);
+			}
+		    }
+		    if (index != null) {
+			// Create the new collection meta
+			CollectionMeta metadatum = new CollectionMeta(StaticStrings.STOP_CHARACTER + index.getID());
+			metadatum.setValue(index.getID());
+		    
+			// replace the index
+			replaceIndex((Index) index_list.getSelectedValue(), index, metadatum);
+			index_list.setSelectedValue(index, true);
+		    
+		    }
+		    new_index_prompt.dispose();
+		
+		}
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/IndexOption.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/IndexOption.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/IndexOption.java	(revision 13928)
@@ -0,0 +1,153 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Katherine Don, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import org.greenstone.gatherer.util.StaticStrings;
+import org.w3c.dom.*;
+
+
+/** This class represents an index option. currently, might be a level or a stem option. 
+ */
+public class IndexOption
+    implements DOMProxyListEntry {
+
+    /** The Element this object will source its information from. */
+    private Element element;
+
+    /** Constructor used only during DOMProxyListModel initialization. */
+    public IndexOption() {
+    }
+
+    /** Normal constructor.
+     * @param  element the Element this object will find its data from
+     */
+    public IndexOption(Element element) {
+	this.element = element;
+    }
+
+    /** Creation of a brand new IndexOption 
+     * @param  name the name of this type as a String
+     */
+    public IndexOption(String name) {
+	this.element = CollectionConfiguration.createElement(StaticStrings.INDEXOPTION_ELEMENT);
+	this.element.setAttribute(StaticStrings.NAME_ATTRIBUTE, name);
+    }
+
+    /** Compare two objects for ordering. 
+     * @param  object the other Object to compare to
+     * @return <0 if this option should be before the given object, 0 if they are equal, and >0 if it should be after
+     */
+    public int compareTo(Object object) {
+	if(object == null) {
+	    return -1;
+	}
+	// hope we never compare a IndexOption with something that is not a IndexOption!
+	return getName().compareTo(((IndexOption)object).getName());
+    }
+
+    /** Factory-like method to allow DOMProxyListModel to generate new entries.
+     * @param  element the Element the new option should be based on
+     * @return a newly created DOMProxyListEntry for the given element
+     */
+    public DOMProxyListEntry create(Element element) {
+	return new IndexOption(element);
+    }
+
+    /** Determine if this option is equivalent to another object.
+     * @param  object the other Object to match against
+     * @return true if the two are equal, false otherwise
+     */
+    public boolean equals(Object object) {
+	return (compareTo(object) == 0);
+    }
+
+    /** Retrieve the element this DOMProxyListEntry is based upon. Specified by the interface.
+     * @return the Element in question
+     */
+    public Element getElement() {
+	return element;
+    }
+
+    /** Retrieve the option name
+     * @return the name as a String
+     */
+    public String getName() {
+	return element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
+    }
+    /** Retrieve the option value
+     * @return the value as a string
+     */
+    public String getValue() {
+	return element.getAttribute(StaticStrings.VALUE_ATTRIBUTE);
+    }
+
+   /** Determine is this command has been assigned, either because it already existed in the collection configuration, or because it has been explicitly set by the user. Non-assigned entries imply they have been added by the GLI to ensure consistancy (and avoid NPE's!)
+     * @return true if this command has been assigned, false otherwise
+     */
+    public boolean isAssigned() {
+	return (element != null && !element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.FALSE_STR));
+    }
+    
+    /** Set the assigned state.
+     * @param  assigned the desired state of assigned as a boolean
+     */
+    public void setAssigned(boolean assigned) {
+	if(element != null) {
+	    element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, (assigned ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
+	}
+    }
+
+    /** Set the element that this DOMProxyListEntry is base on.
+     * @param  element the new Element that this entry should source informatin from
+     */
+    public void setElement(Element element) {
+	this.element = element;
+    }
+
+    /** Set the name of this option.
+     * @param  name the new name for this option, as a String
+     */
+    public void setName(String name) {
+	if(element != null) {
+	    element.setAttribute(StaticStrings.NAME_ATTRIBUTE, name);
+	}
+    }
+
+    /** Set the value of this option  - sometimes value is used as well as name*/
+    public void setValue(String value) {
+	if (element != null) {
+	    element.setAttribute(StaticStrings.VALUE_ATTRIBUTE, value);
+	}
+    }
+
+    /** Produce a text representation of this option
+     * @return a String showing this option's name
+     */
+    public String toString() {
+	return getName();
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/IndexOptionList.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/IndexOptionList.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/IndexOptionList.java	(revision 13928)
@@ -0,0 +1,72 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Katherine Don, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import org.w3c.dom.Element;
+import org.greenstone.gatherer.util.StaticStrings;
+
+/** A DOMProxyListModel thatholds options for indexoptions. For example, levels and stem options */
+public class IndexOptionList
+    extends DOMProxyListModel {
+
+    /** A reference to ourselves so our inner methods have access. */
+    private DOMProxyListModel options_model = null;
+
+    public IndexOptionList(Element options) {
+	super(options, StaticStrings.INDEXOPTION_ELEMENT, new IndexOption());
+
+	options_model = this;
+    }
+
+    public void addOption(String name) {
+	if (getOption(name) == null) {
+	    add(new IndexOption(name));
+	}
+    }
+
+
+    public IndexOption getOption(String name) {
+	int options_model_size = options_model.getSize();
+	for(int i = 0; i < options_model_size; i++) {
+	    IndexOption option = (IndexOption) options_model.getElementAt(i);
+	    if(option.getName().equals(name)) {
+		return option;
+	    }
+	}
+	return null;
+    }
+
+    public void removeOption(String name) {
+	IndexOption option_elem = null;
+	if ((option_elem = getOption(name)) != null) {
+	    options_model.remove(option_elem);
+	}
+    }
+
+
+}
+	    
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/IndexOptionManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/IndexOptionManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/IndexOptionManager.java	(revision 13928)
@@ -0,0 +1,475 @@
+package org.greenstone.gatherer.cdm;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.util.JarTools;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.w3c.dom.*;
+
+
+public class IndexOptionManager 
+    implements BuildTypeManager.BuildTypeListener {
+
+    // we have an IndexOptionList (DOMProxyListModel) for each option type
+    private IndexOptionList level_model = null;
+    private IndexOptionList stem_model = null;
+    
+    /** the default level option  - for mgpp and lucene */
+    private IndexOption default_level = null;
+    
+    private String build_type = null;
+    private Control controls = null;
+    
+    public IndexOptionManager(String current_build_type) {
+	level_model = new IndexOptionList(CollectionDesignManager.collect_config.getLevels());
+	stem_model = new IndexOptionList(CollectionDesignManager.collect_config.getStemOptions());
+	
+	DebugStream.println("IndexOptionManager: " + level_model.getSize() + " levels parsed.");
+	DebugStream.println("IndexOptionManager: " + stem_model.getSize() + " stem options parsed.");
+	
+	build_type = current_build_type;
+	if (build_type.equals(BuildTypeManager.BUILD_TYPE_MG)) {
+	    level_model.setAssigned(false);
+	}
+	else if (build_type.equals(BuildTypeManager.BUILD_TYPE_LUCENE)) {
+	    stem_model.setAssigned(false);
+	}
+	// Parse and retrieve the default level 
+	Element default_level_element = CollectionDesignManager.collect_config.getLevelDefault();
+	default_level = new IndexOption(default_level_element);
+	if (build_type.equals(BuildTypeManager.BUILD_TYPE_MG)) {
+	    default_level.setAssigned(false);
+	}
+	
+    }
+	
+    
+    public void buildTypeChanged(String new_build_type) {
+	boolean levels_enabled = true;
+	boolean stem_enabled = true;
+	if (new_build_type.equals(BuildTypeManager.BUILD_TYPE_MG)) {
+	    levels_enabled = false;
+	} else if (new_build_type.equals(BuildTypeManager.BUILD_TYPE_LUCENE)) {
+	    stem_enabled = false;
+	}
+	level_model.setAssigned(levels_enabled);
+	default_level.setAssigned(levels_enabled);
+	stem_model.setAssigned(stem_enabled);
+	((IndexOptionControl)controls).buildTypeChanged(new_build_type);
+	build_type = new_build_type;
+    }
+
+    /** Method to acquire the controls for editing the indexes.
+     * @return the Control
+     */
+    public Control getControls() {
+	if(controls == null) {
+	    // Build controls
+	    controls = new IndexOptionControl();
+	}
+	return controls;
+    }
+    
+    public int getNumLevels() {
+	return level_model.getSize();
+    }
+    public ArrayList getLevels() {
+	return level_model.children();
+    }
+    
+    private void addLevel(String level) {
+	if (level_model.getOption(level) == null) {
+	    int position = 0;
+	    
+	    if (level.equals(StaticStrings.SECTION_STR) && level_model.getSize()==1) {
+		position = 1;
+	    }
+	    level_model.add(position, new IndexOption(level));
+	    // add in a default collection meta
+	    CollectionMeta meta = new CollectionMeta(StaticStrings.STOP_CHARACTER + level);
+	    meta.setAssigned(true);
+	    meta.setValue(level);
+	    CollectionDesignManager.collectionmeta_manager.addMetadatum(meta);
+	}
+    }
+
+    private IndexOption getLevel(String level) {
+	return level_model.getOption(level);
+    }
+
+    private void removeLevel(String level_name) {
+	// Remove any current metadata from this level
+	CollectionDesignManager.collectionmeta_manager.removeMetadata(StaticStrings.STOP_CHARACTER + level_name);
+	// Remove the level
+	level_model.removeOption(level_name);
+    }
+
+   /** Method to set the default level
+     * @param level the new default level
+     */
+    private void setDefaultLevel(String level) {
+ 	if(level != null) {
+	    default_level.setValue(level);
+	    if (!build_type.equals(BuildTypeManager.BUILD_TYPE_MG)) {
+		default_level.setAssigned(true);
+	    } 
+	} else {
+	    default_level.setAssigned(false);
+	}
+    }
+
+    private class IndexOptionControl
+	extends JPanel
+	implements Control {
+
+	public StemmingControl stem_control = null;
+	public LevelControl level_control = null;
+	
+	public IndexOptionControl() {
+
+	    stem_control = new StemmingControl();
+	    level_control = new LevelControl();
+
+	    setLayout(new BorderLayout());
+	    if (!build_type.equals(BuildTypeManager.BUILD_TYPE_LUCENE)) {
+		add(stem_control, BorderLayout.NORTH);
+	    }
+	    if (!build_type.equals(BuildTypeManager.BUILD_TYPE_MG)) {
+		add(level_control, BorderLayout.CENTER);
+	    }
+	}
+
+	public void destroy() {}
+	public void gainFocus() {}
+	public void loseFocus() {}
+
+	public void buildTypeChanged(String new_build_type)
+	{
+	    if (build_type.equals(new_build_type)) {
+		// shouldn't happen
+		return;
+	    }
+	    // tell our sub parts about the change in build type
+	    stem_control.buildTypeChanged(new_build_type);
+	    level_control.buildTypeChanged(new_build_type);
+	    
+	    // then display/hide as appropriate
+	    if (build_type.equals(BuildTypeManager.BUILD_TYPE_LUCENE)) {
+		// Changing to MG/MGPP
+		add(stem_control, BorderLayout.NORTH);
+	    }
+	    else if (new_build_type.equals(BuildTypeManager.BUILD_TYPE_LUCENE)) {
+		// Changing to Lucene
+		remove(stem_control);
+	    }
+	    if (build_type.equals(BuildTypeManager.BUILD_TYPE_MG)) {
+		// changing from MG
+		add(level_control, BorderLayout.CENTER);
+	    }
+	    else if (new_build_type.equals(BuildTypeManager.BUILD_TYPE_MG)) {
+		// changing to MG
+		remove(level_control);
+	    }
+	    
+	}
+	    
+    }
+    
+    private class StemmingControl
+	extends JPanel
+	implements BuildTypeManager.BuildTypeListener
+    {
+	private JCheckBox stem_checkbox = new JCheckBox();
+	private JCheckBox casefold_checkbox = new JCheckBox();
+	private JCheckBox accentfold_checkbox = new JCheckBox();
+
+	public StemmingControl()
+	{
+	    setLayout(new BorderLayout(10,10));
+	    setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	    
+	    stem_checkbox.setText(Dictionary.get("CDM.IndexingManager.Stem"));
+	    stem_checkbox.setActionCommand(StaticStrings.STEM_OPTION_STR);
+	    
+	    casefold_checkbox.setText(Dictionary.get("CDM.IndexingManager.Casefold"));
+	    casefold_checkbox.setActionCommand(StaticStrings.CASEFOLD_OPTION_STR);
+	    
+	    accentfold_checkbox.setText(Dictionary.get("CDM.IndexingManager.Accent_fold"));
+	    accentfold_checkbox.setActionCommand(StaticStrings.ACCENTFOLD_OPTION_STR);
+	    // Accent-folding is currently not available for MG
+	    accentfold_checkbox.setEnabled(!build_type.equals(BuildTypeManager.BUILD_TYPE_MG));
+	    
+	    JPanel checkbox_panel = new JPanel();
+	    checkbox_panel.setLayout(new GridLayout(1, 3));
+	    checkbox_panel.add(stem_checkbox);
+	    checkbox_panel.add(casefold_checkbox);
+	    checkbox_panel.add(accentfold_checkbox);
+	    
+	    add(new JLabel(Dictionary.get("CDM.IndexingManager.Options")), BorderLayout.WEST);
+	    add(checkbox_panel, BorderLayout.CENTER);
+
+	    // set up the checked/unchecked boxes
+	    if (stem_model.getSize()==0) {
+		// select all
+		stem_checkbox.setSelected(true);
+		stem_model.addOption(StaticStrings.STEM_OPTION_STR);
+		casefold_checkbox.setSelected(true);
+		stem_model.addOption(StaticStrings.CASEFOLD_OPTION_STR);
+		if (accentfold_checkbox.isEnabled()) {
+		    accentfold_checkbox.setSelected(true);
+		    stem_model.addOption(StaticStrings.ACCENTFOLD_OPTION_STR);
+		}
+	    } 
+	    else {
+		if (stem_model.getOption(StaticStrings.STEM_OPTION_STR)!=null) {
+		    stem_checkbox.setSelected(true);
+		}
+		if (stem_model.getOption(StaticStrings.CASEFOLD_OPTION_STR)!=null) {
+		    casefold_checkbox.setSelected(true);
+		}
+		if (stem_model.getOption(StaticStrings.ACCENTFOLD_OPTION_STR)!=null) {
+		    accentfold_checkbox.setSelected(true);
+		}
+		
+	    }
+	
+	    CheckBoxListener cbl = new CheckBoxListener();
+	    stem_checkbox.addActionListener(cbl);
+	    casefold_checkbox.addActionListener(cbl);
+ 	    accentfold_checkbox.addActionListener(cbl);
+
+	    // changing stem indexes changes build settings
+	    stem_checkbox.addActionListener(CollectionDesignManager.buildcol_change_listener);
+	    casefold_checkbox.addActionListener(CollectionDesignManager.buildcol_change_listener);
+ 	    accentfold_checkbox.addActionListener(CollectionDesignManager.buildcol_change_listener);
+
+	    
+	}
+	
+	public void buildTypeChanged(String new_build_type) {
+	    // Accent-folding is currently not available for MG
+	    if (new_build_type.equals(BuildTypeManager.BUILD_TYPE_MG)) {
+		//changing to MG
+		accentfold_checkbox.setEnabled(false);
+		if (accentfold_checkbox.isSelected()) {
+		    stem_model.removeOption(StaticStrings.ACCENTFOLD_OPTION_STR);
+		} 
+	    }
+	    else if (build_type.equals(BuildTypeManager.BUILD_TYPE_MG)) {
+		//Changing from MG
+		accentfold_checkbox.setEnabled(true);
+		if (accentfold_checkbox.isSelected()) {
+		    stem_model.addOption(StaticStrings.ACCENTFOLD_OPTION_STR);
+		}
+	    }
+	    
+	}
+
+	private class CheckBoxListener
+	    implements ActionListener {
+	    public void actionPerformed(ActionEvent event) {
+		if (!((JCheckBox)event.getSource()).isSelected()) {
+		    // deselecting
+		    stem_model.removeOption(event.getActionCommand());
+		}
+		else {
+		    // selecting a new one
+		    stem_model.addOption(event.getActionCommand());
+		}
+	    }
+	}
+    }
+
+
+
+    /** This class creates a set of controls for editing the levels. */
+    private class LevelControl
+	extends JPanel 
+	implements BuildTypeManager.BuildTypeListener
+    {
+	
+	JCheckBox document_checkbox = null;
+	JCheckBox section_checkbox = null;
+	JRadioButton document_default_radio = null;
+	JRadioButton section_default_radio = null;
+	
+	public LevelControl() {
+	    
+	    JPanel checkbox_panel = new JPanel();
+	    JPanel default_panel = new JPanel();
+	    document_checkbox = new JCheckBox();
+	    document_checkbox.setText(Dictionary.get("CDM.LevelManager.Document"));
+	    document_default_radio = new JRadioButton();
+	    document_default_radio.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+	    document_default_radio.setOpaque(false);
+	    document_default_radio.setActionCommand(StaticStrings.DOCUMENT_STR);
+	    document_default_radio.setIcon(JarTools.getImage("radio_unselected.gif"));
+	    document_default_radio.setSelectedIcon(JarTools.getImage("radio_selected.gif"));
+
+	    section_checkbox = new JCheckBox();
+	    section_checkbox.setText(Dictionary.get("CDM.LevelManager.Section"));
+	    section_default_radio = new JRadioButton();
+	    section_default_radio.setOpaque(true);
+	    section_default_radio.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+	    section_default_radio.setOpaque(false);
+	    section_default_radio.setIcon(JarTools.getImage("radio_unselected.gif"));
+	    section_default_radio.setSelectedIcon(JarTools.getImage("radio_selected.gif"));
+
+	    section_default_radio.setActionCommand(StaticStrings.SECTION_STR);
+	    ButtonGroup default_group = new ButtonGroup();
+	    default_group.add(document_default_radio);
+	    default_group.add(section_default_radio);
+
+	 
+
+	    if (level_model.getSize()==0) {
+		// no levels yet, set document
+		document_checkbox.setSelected(true);
+		addLevel(StaticStrings.DOCUMENT_STR);
+	    } else {
+		if (getLevel(StaticStrings.DOCUMENT_STR)!= null) {
+		    document_checkbox.setSelected(true);
+		}
+		if (getLevel(StaticStrings.SECTION_STR) != null) {
+		    section_checkbox.setSelected(true);
+		}
+	    }
+
+	    if (default_level.isAssigned()) {
+		// set the default based on specified default
+		if (default_level.getValue().equals(StaticStrings.DOCUMENT_STR) && document_checkbox.isSelected()) {
+		    document_default_radio.setSelected(true);
+		}
+		else if (default_level.getValue().equals(StaticStrings.SECTION_STR) && section_checkbox.isSelected()) {
+		    section_default_radio.setSelected(true);
+		} else {
+    		    default_level.setAssigned(false);
+		}
+	    }
+	    // if have no valid specified default
+	    if (!default_level.isAssigned()) {
+		String default_l = StaticStrings.DOCUMENT_STR;
+		if (document_checkbox.isSelected()) {
+		    document_default_radio.setSelected(true);
+		    default_l = StaticStrings.DOCUMENT_STR;
+		} else if (section_checkbox.isSelected()) {
+		    section_default_radio.setSelected(true);
+		    default_l = StaticStrings.SECTION_STR;
+		}
+		setDefaultLevel(default_l);
+	    }
+	    
+	    validateControls();
+	    JLabel checkbox_label = new JLabel(Dictionary.get("CDM.LevelManager.Level_Title"));
+	    checkbox_panel.setLayout(new GridLayout(3,1));
+	    checkbox_panel.setToolTipText(Dictionary.get("CDM.IndexManager.Level_Tooltip"));
+	    checkbox_panel.add(checkbox_label);
+	    checkbox_panel.add(document_checkbox);
+	    checkbox_panel.add(section_checkbox);
+
+	    JLabel default_label = new JLabel(Dictionary.get("CDM.LevelManager.Default"));
+	    default_panel.setLayout(new GridLayout(3,1));
+	    default_panel.setToolTipText(Dictionary.get("CDM.LevelManager.Default_Tooltip"));
+	    default_panel.add(default_label);
+	    default_panel.add(document_default_radio);
+	    default_panel.add(section_default_radio);
+
+        
+	    CheckBoxListener cbl = new CheckBoxListener();
+	    document_checkbox.addActionListener(cbl);
+	    section_checkbox.addActionListener(cbl);
+
+	    // changing selected levels changes build settings
+	    document_checkbox.addActionListener(CollectionDesignManager.buildcol_change_listener);
+	    section_checkbox.addActionListener(CollectionDesignManager.buildcol_change_listener);
+	    
+	    RadioListener rl = new RadioListener();
+	    document_default_radio.addActionListener(rl);
+	    section_default_radio.addActionListener(rl);
+	    // changing the default doesn't need a rebuild
+
+	    setLayout(new BorderLayout(10,10));
+	    setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	    add(checkbox_panel, BorderLayout.WEST);
+	    add(default_panel, BorderLayout.CENTER);
+	} // LevelControl
+	
+	public void buildTypeChanged(String new_build_type) {};
+	public void gainFocus() {
+
+	}
+
+	public void loseFocus() {
+
+	}
+
+	public void destroy() {
+	}
+
+	private class RadioListener
+	    implements ActionListener {
+	    public void actionPerformed(ActionEvent event) {
+		String new_level = event.getActionCommand();
+		setDefaultLevel(new_level);
+	    }
+	}
+	private class CheckBoxListener
+	    implements ActionListener {
+	    
+	    public void actionPerformed(ActionEvent event) {
+		if (!((JCheckBox)event.getSource()).isSelected()) {
+		    // deselecting
+		    if (noLevelsSelected()) {
+			// can't do this
+			((JCheckBox)event.getSource()).setSelected(true);
+		    } else {
+			// remove the level
+			removeLevel(event.getActionCommand());
+		    }
+		} else {
+		    // selecting a new one
+		    addLevel(event.getActionCommand());
+		}
+		validateControls();
+	    }
+	}
+	    
+	private boolean noLevelsSelected() {
+	    if (!document_checkbox.isSelected() && !section_checkbox.isSelected()) {
+		return true;
+
+	    }
+	    return false;
+	}
+
+	private void validateControls() {
+            
+	    boolean document_enabled = document_checkbox.isSelected();
+	    document_default_radio.setEnabled(document_enabled);
+	    
+	    boolean section_enabled = section_checkbox.isSelected();
+	    section_default_radio.setEnabled(section_enabled);
+
+	    // have we disabled our default??
+	    if (!document_enabled && document_default_radio.isSelected()) {
+		section_default_radio.setSelected(true);
+		setDefaultLevel(StaticStrings.SECTION_STR);
+               
+	    } else if (!section_enabled && section_default_radio.isSelected()) {
+		document_default_radio.setSelected(true);
+		setDefaultLevel(StaticStrings.DOCUMENT_STR);
+	    }
+
+           
+	}
+
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/IndexingManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/IndexingManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/IndexingManager.java	(revision 13928)
@@ -0,0 +1,173 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.gui.DesignPaneHeader;
+import org.greenstone.gatherer.gui.GComboBox;
+import org.greenstone.gatherer.gui.GLIButton;
+import org.greenstone.gatherer.metadata.MetadataElement;
+import org.greenstone.gatherer.metadata.MetadataSetManager;
+import org.greenstone.gatherer.util.CheckList;
+import org.greenstone.gatherer.util.JarTools;
+import org.greenstone.gatherer.util.StaticStrings;
+
+
+/** This class is responsible for coordinating the IndexManager and IndexOptionManager (controls levels, stem options etc) and BuildTypeManager into one panel  
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class IndexingManager {
+
+    private IndexOptionManager option_manager = null;
+    private IndexManager index_manager = null;
+    private BuildTypeManager build_type_manager = null;
+
+
+    private String build_type = null;
+
+    private Control controls = null;
+
+
+    public IndexingManager()
+    {
+	build_type_manager = new BuildTypeManager();
+	build_type = build_type_manager.getBuildType();
+	option_manager = new IndexOptionManager(build_type);
+	if (build_type.equals(BuildTypeManager.BUILD_TYPE_MG)) {
+	    index_manager = new IndexManager(CollectionDesignManager.collect_config.getMGIndexes(), build_type);
+	} else {
+	    index_manager = new IndexManager(CollectionDesignManager.collect_config.getMGPPIndexes(), build_type);
+	}
+    }
+
+    public boolean isMGPP() {
+	return build_type_manager.isMGPP();
+    }
+
+    public boolean isLucene() {
+	return build_type_manager.isLucene();
+    }
+
+    public boolean isMG() {
+	return build_type_manager.isMG();
+    }
+
+    public int getNumLevels() {
+	return option_manager.getNumLevels();
+    }
+
+    public int getNumIndexes() {
+	return index_manager.getSize();
+    }
+
+    public ArrayList getIndexes() {
+	return index_manager.getIndexes();
+    }
+
+    public ArrayList getLevels() {
+	if (!build_type.equals(BuildTypeManager.BUILD_TYPE_MG)) {
+	    return option_manager.getLevels();
+	}
+	return null;
+    }
+
+    public Control getControls() {
+	if (controls == null) {
+	    controls = new IndexingControl();
+	}
+	return controls;
+    }
+
+    public void destroy() {
+
+    }
+
+    /** Called when the detail mode has changed which in turn may cause several design elements to be available/hidden
+     * @param mode the new mode as an int
+     */
+    public void modeChanged(int mode) {
+
+    }
+
+
+    private class IndexingControl
+	extends JPanel
+	implements Control, BuildTypeManager.BuildTypeListener
+    {
+	JPanel main_index_pane = null;
+	JPanel index_options_panel = null;
+
+	public IndexingControl() {
+	    super();
+
+	    // Creation
+	    JPanel header_pane = new DesignPaneHeader("CDM.GUI.Indexes", "searchindexes");	   
+	    
+	    JPanel build_type_panel = (JPanel)build_type_manager.getControls();
+	    JPanel index_panel = (JPanel)index_manager.getControls();
+	    index_options_panel = (JPanel)option_manager.getControls();
+
+	    main_index_pane = new JPanel();
+	    main_index_pane.setLayout(new BorderLayout());
+	    main_index_pane.add(build_type_panel, BorderLayout.NORTH);
+	    main_index_pane.add(index_panel, BorderLayout.CENTER);
+	    main_index_pane.add(index_options_panel, BorderLayout.SOUTH);
+	    
+	    setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
+	    setLayout(new BorderLayout());
+	    add(header_pane, BorderLayout.NORTH);
+	    add(main_index_pane, BorderLayout.CENTER);
+
+	    build_type_manager.addBuildTypeListener(this);
+	    build_type_manager.addBuildTypeListener(index_manager);
+	    build_type_manager.addBuildTypeListener(option_manager);
+	}
+
+	public void loseFocus() {}
+	public void gainFocus() {}
+	public void destroy() {}
+
+	public void buildTypeChanged(String new_build_type)
+	{
+	    if (build_type.equals(new_build_type)) {
+		// shouldn't happen
+		return;
+	    }
+ 	    build_type = new_build_type;
+	}
+
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/Language.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/Language.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/Language.java	(revision 13928)
@@ -0,0 +1,173 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import java.util.ArrayList;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.w3c.dom.*;
+
+
+/** A pretty unexciting extension of a two character string, in that it has a field which details if its the default language.
+* @author John Thompson, Greenstone Digital Library, University of Waikato
+* @version 2.1
+*/
+public class Language
+    implements Comparable, DOMProxyListEntry {
+    /** The Element this language entry is based upon. */
+    private Element element = null;
+    /** A comma separated list of two character codes */
+    private String code = null;
+    /** A comma separated list of language names */
+    private String name = null;
+ 
+    public Language() {
+    }
+
+    public Language(Element element) {
+	this.element = element;
+    }
+
+    /** Constructor for a brand new language. */
+    public Language(String code) {
+	this.code = code;
+	// Create the new element
+	element = CollectionConfiguration.createElement(StaticStrings.LANGUAGE_ELEMENT);
+	element.setAttribute(StaticStrings.NAME_ATTRIBUTE, code);
+	element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+    }
+
+    /** Constructor which takes an ArrayList of codes */
+    public Language(ArrayList codes) {
+	StringBuffer code_str = new StringBuffer();
+	boolean first = true;
+	for (int i=0; i<codes.size(); i++) {
+	    if (!first) {
+		code_str.append(",");
+	    } else {
+		first = false;
+	    }
+	    code_str.append(codes.get(i));
+	}
+	this.code = code_str.toString();
+	element = CollectionConfiguration.createElement(StaticStrings.LANGUAGE_ELEMENT);
+	element.setAttribute(StaticStrings.NAME_ATTRIBUTE, code);
+	element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+	
+    }
+
+    /** Method to compare two languages for ordering purposes.
+     * @param object the other language as an Object
+     * @return an int which indicates the order between this language and the given one: < 0, 0 or > 0 for before, equal to or after respectively
+     */
+    public int compareTo(Object object) {
+	return toString().compareTo(object.toString());
+    }
+
+    public DOMProxyListEntry create(Element element) {
+	return new Language(element);
+    }
+
+    /** Method to test for the equality of two languages.
+     * @param object The other language as an <strong>Object</strong>.
+     * @return <i>true</i> if the languages are equal, <i>false</i> otherwise.
+     */
+    public boolean equals(Object object) {
+	// two langs are equal if their codes are equal
+	if (object instanceof Language) {
+	    return getCode().equals(((Language)object).getCode());
+	} else if (object instanceof String) {
+	    return getCode().equals((String)object);
+	}
+	return false;
+    }
+
+    /** Method to retrieve the code of this language.
+     * @return A <strong>String</strong> representing the two letter code.
+     */
+    public String getCode() {
+	if(code == null && element != null) {
+	    code = element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
+	}
+	return code;
+    }
+
+    public Element getElement() {
+	return element;
+    }
+
+    public String getName() {
+	if(name == null) {
+	    String code_str = getCode();
+	    String [] codes = code_str.split(",");
+	    StringBuffer name_str = new StringBuffer();
+	    boolean first = true;
+	    for (int i=0; i<codes.length; i++) {
+		if (!first) {
+		    name_str.append(",");
+		} else {
+		    first = false;
+		}
+		name_str.append(CollectionDesignManager.language_manager.getLanguageName(codes[i]));
+	    }
+	    name = name_str.toString();
+	}
+	return name;
+    }
+
+    public boolean isAssigned() {
+	return (element != null && element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.TRUE_STR));
+    }
+
+    public void setAssigned(boolean value) {
+	if(element != null) {
+	    element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, (value ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
+	}
+    }
+
+    public void setCode(String new_code) {
+	code = new_code;
+	// Set element
+	if(element != null) {
+	    element.setAttribute(StaticStrings.NAME_ATTRIBUTE, new_code);
+	}
+	// Reset name
+	name = null;
+    }
+
+    public void setElement(Element new_element) {
+	element = new_element;
+	code = null;
+	name = null;
+    }
+
+    /** Method to display the language code.
+     * @return A <strong>String</strong> representing the language code.
+     */
+    public String toString() {
+	return getName();
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/LanguageListCellRenderer.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/LanguageListCellRenderer.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/LanguageListCellRenderer.java	(revision 13928)
@@ -0,0 +1,43 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+/**************************************************************************************
+ * Written:      11/07/03
+ * Revised:      
+ **************************************************************************************/
+import java.awt.*;
+import javax.swing.*;
+
+/** Provides a renderer which transforms a language code (such as en or fr) into its appropriate name (English and French respectively) before generating the rubberstamping component. */
+public class LanguageListCellRenderer
+    extends DefaultListCellRenderer {
+    
+    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+	return super.getListCellRendererComponent(list, CollectionDesignManager.language_manager.getLanguageName((String)value), index, isSelected, cellHasFocus);
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/LanguageManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/LanguageManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/LanguageManager.java	(revision 13928)
@@ -0,0 +1,665 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.border.*;
+import javax.swing.event.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.gui.GLIButton;
+import org.greenstone.gatherer.metadata.MetadataElement;
+import org.greenstone.gatherer.metadata.MetadataSetManager;
+import org.greenstone.gatherer.util.CheckList;
+import org.greenstone.gatherer.util.CheckListEntry;
+import org.greenstone.gatherer.util.JarTools;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.XMLTools;
+import org.w3c.dom.*;
+
+/** This class manages the language commands, remembering both a list of languages to build indexes in, plus the default language.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class LanguageManager
+    extends DOMProxyListModel {
+
+    static public Document LANGUAGES_DOCUMENT = XMLTools.parseXMLFile("xml/languages.xml", true);
+
+    static final private Dimension COMPONENT_SIZE = new Dimension(125,25);
+
+    /** The visual controls for this manager. */
+    private Control controls = null;
+    /** A reference to this class as a model, for the inner controls class. */
+    private DOMProxyListModel model = null;
+    /** A hashtable of code->name mappings of known languages. */
+    private LinkedHashMap known_languages = null;
+    /** The default language object. */
+    private Language default_language = null;
+    /** The language metadata element - specifies which metadata the 
+	language should be read from to determine the partitons */
+    private Element language_metadata = null;
+   /** Constructor. */
+    public LanguageManager(Element languages_element) {
+	super(languages_element, StaticStrings.LANGUAGE_ELEMENT, new Language());
+	
+	DebugStream.println("LanguageManager: " + getSize() + " languages parsed.");
+
+	this.model = this;
+	// Retrieve the default language
+	NodeList default_language_elements = CollectionConfiguration.getElementsByTagName(StaticStrings.LANGUAGE_DEFAULT_ELEMENT);
+	if(default_language_elements.getLength() > 0) {
+	    default_language = new Language((Element)default_language_elements.item(0));
+	}
+
+	// Retrieve the language metadata
+	language_metadata = CollectionDesignManager.collect_config.getLanguageMetadata();
+	// Load a series of code->language mappings into known_languages, by reading from the 'languages.xml' file, which is essentially a subset of the ISO 639 Standard.
+	known_languages = new LinkedHashMap();
+	NodeList language_elements = LANGUAGES_DOCUMENT.getDocumentElement().getElementsByTagName(StaticStrings.LANGUAGE_ELEMENT);
+	for(int i = 0; i < language_elements.getLength(); i++) {
+	    Element language_element = (Element) language_elements.item(i);
+	    String code = language_element.getAttribute(StaticStrings.CODE_ATTRIBUTE);
+	    String name = language_element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
+	    known_languages.put(code.toLowerCase(), name);
+	    name = null;
+	    code = null;
+	    language_element = null;
+	}
+    }
+
+    /** Method to add a new language.
+     * @param language The <strong>Language</strong> to add.
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.collection.CollectionManager
+     */
+    private void addLanguage(Language language) {
+	if(!contains(language)) {
+	    // need to add a pseudo metadata
+	    CollectionMeta metadatum = new CollectionMeta(StaticStrings.STOP_CHARACTER + language.getCode());
+	    metadatum.setValue(language.getName());
+	    CollectionDesignManager.collectionmeta_manager.addMetadatum(metadatum);
+	    add(getSize(), language);
+	}
+    }
+
+    public void destroy() {
+	if(controls != null) {
+	    controls.destroy();
+	    controls = null;
+	}
+	known_languages.clear();
+	known_languages = null;
+	default_language = null;
+    }
+
+    /** Method to retrieve the control for this manager.
+     * @return the Control for editing the language partitions
+     */
+    public Control getControls() {
+	if(controls == null) {
+	    // Build controls
+	    controls = new LanguageControl();
+	}
+	return controls;
+    }
+    
+    /** Method to retrieve a certain language object by its code.
+     * @param code The two letter code of a language, as a <strong>String</strong>.
+     * @return The <strong>Language</strong> that matches the given code, or <i>null</i> if no such language exists.
+     */
+    public Language getLanguage(String code) {
+	int size = getSize();
+	for(int i = 0; i < size; i++) {
+	    Language language = (Language) getElementAt(i);
+	    if(language.getCode().equals(code)) {
+		return language;
+	    }
+	}
+	return null;
+    }
+
+    public ArrayList getLanguages() {
+	return children();
+    }
+
+    /** Method to return a list of the known language codes.
+     * @return an ArrayList containing the series of known language codes as per the languages.dat file
+     */
+    public ArrayList getLanguageCodes() {
+	return new ArrayList(known_languages.keySet());
+    }
+
+    public String getLanguageName(String code) {
+	return (String) known_languages.get(code);
+    }
+    
+    /** Called when the detail mode has changed which in turn may cause several design elements to be available/hidden
+     * @param mode the new mode as an int
+     */
+    public void modeChanged(int mode) {
+	
+    }
+
+   private int moveLanguage(Language lang, boolean move_up)
+    {
+	// Determine the current position of the language
+	int position = indexOf(lang);
+	int new_position;
+
+	// Attempt to move the language up
+	if (move_up) {
+	    // Check it's not already at the top
+	    if (position == 0) {
+		return position;
+	    }
+
+	    // This automatically removes the language first, as an Element can only exist once in a particular document
+	    new_position = position - 1;
+	    addBefore(lang, (Language) getElementAt(new_position));
+	}
+
+	// Attempt to move the language down
+	else {
+	    // Check it's not already at the bottom
+	    if (position == (getSize()) - 1) {
+		return position;
+	    }
+
+	    // This automatically removes the language first, as an Element can only exist once in a particular document
+	    new_position = position + 1;
+	    addAfter(lang, (Language) getElementAt(new_position));
+	}
+
+	return new_position;
+    }
+
+    /** Method to remove a certain language.
+     * @param language The <strong>Language</strong> to remove.
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.collection.CollectionManager
+     */
+    private void removeLanguage(Language language) {
+	remove(language);
+	// Remove any collection metadata for this language
+	CollectionDesignManager.collectionmeta_manager.removeMetadata(StaticStrings.STOP_CHARACTER + language.getCode());
+	if(default_language != null && default_language.equals(language)) {
+	    setDefault(null);
+	}
+    }
+
+    private void replaceLanguage(Language old_language, Language new_language) {
+	// Remove old lang collection meta
+	CollectionDesignManager.collectionmeta_manager.removeMetadata(StaticStrings.STOP_CHARACTER + old_language.getCode());
+	// Add new one
+	CollectionMeta metadatum = new CollectionMeta(StaticStrings.STOP_CHARACTER + new_language.getCode());
+	metadatum.setValue(new_language.getName());
+	CollectionDesignManager.collectionmeta_manager.addMetadatum(metadatum);
+	if(default_language != null && default_language.equals(old_language)) {
+	    setDefault(new_language);
+	}
+
+	// get the position of the old one
+	int position = indexOf(old_language);
+	remove(old_language);
+	add(position, new_language);
+    }
+
+
+    /** Method to set the default language.
+     * @param language The <strong>Language</strong> to use as a default, or <i>null</i> for no default.
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.collection.CollectionManager
+     */
+    public void setDefault(Language language) {
+	if(language != null) {
+	    if(default_language == null) {
+		// Create the default index element, and place immediately after indexes element.
+		Element default_language_element = root.getOwnerDocument().createElement(StaticStrings.LANGUAGE_DEFAULT_ELEMENT);
+		default_language = new Language(default_language_element);
+		Node target_node = CollectionConfiguration.findInsertionPoint(default_language_element);
+		if(target_node != null) {
+		    root.getOwnerDocument().getDocumentElement().insertBefore(default_language_element, target_node);
+		}
+		else {
+		    root.getOwnerDocument().getDocumentElement().appendChild(default_language_element);
+		}
+	    }
+	    default_language.setAssigned(true);
+	    default_language.setCode(language.getCode());
+	}
+	else {
+	    if(default_language != null) {
+		default_language.setAssigned(false);
+	    }
+	}
+    }
+
+
+    /** This class represents the visual component of the Language Manager. */
+    private class LanguageControl
+	extends JPanel 
+	implements Control {
+	/** The list of available languages */
+	private CheckList language_list = null;
+	/** The button to add a new language support. */
+	private JButton add_button = null;
+	/** The button to replace a language support. */
+	private JButton replace_button = null;
+	/** The button to remove a supported language. */
+	private JButton remove_button = null;
+	/** button to move a language up in the list */
+	private JButton move_down_button;
+	/** button to move a language down in the list */
+	private JButton move_up_button;
+	/** The button to set the current language as the default one. */
+	private JButton set_default_button = null;
+	/** A list of currently supported languages. */
+	private JList selected_languages_list = null;
+	/** A list of metadata elements that may hold the language metadata */
+	private JComboBox language_metadata_combo = null;
+	
+	/** Constructor.
+	 * @see org.greenstone.gatherer.cdm.LanguageManager.LanguageControl.AddListener
+	 * @see org.greenstone.gatherer.cdm.LanguageManager.LanguageControl.ClearDefaultListener
+	 * @see org.greenstone.gatherer.cdm.LanguageManager.LanguageControl.ListListener
+	 * @see org.greenstone.gatherer.cdm.LanguageManager.LanguageControl.RemoveListener
+	 * @see org.greenstone.gatherer.cdm.LanguageManager.LanguageControl.SelectorListener
+	 * @see org.greenstone.gatherer.cdm.LanguageManager.LanguageControl.SetDefaultListener
+	 */
+	public LanguageControl() {
+	    super();
+	    // Creation.
+	    JPanel center_panel = new JPanel();
+
+	    JLabel selected_languages_list_label = new JLabel(Dictionary.get("CDM.LanguageManager.Assigned_Languages"));
+	    selected_languages_list = new JList(model);
+	    selected_languages_list.setCellRenderer(new MyLanguageListCellRenderer());
+	    selected_languages_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+	    selected_languages_list.setVisibleRowCount(5);
+	    
+	    JPanel control_panel = new JPanel();
+	    JLabel selector_label = new JLabel(Dictionary.get("CDM.LanguageManager.Selector"));
+	    
+	    language_metadata_combo = new JComboBox(MetadataSetManager.getEveryMetadataSetElement().toArray());
+	    language_metadata_combo.setOpaque(false);
+	    language_metadata_combo.setToolTipText(Dictionary.get("CDM.LanguageManager.LanguageMetadata_Tooltip"));
+	    JLabel language_metadata_label = new JLabel(Dictionary.get("CDM.LanguageManager.LanguageMetadata"));
+	    String current_value = "ex.Language";
+	    if (language_metadata.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.TRUE_STR) && !language_metadata.getAttribute(StaticStrings.NAME_ATTRIBUTE).equals("")) {
+		current_value = language_metadata.getAttribute(StaticStrings.NAME_ATTRIBUTE);
+	    }
+	    ArgumentControl.selectValue(language_metadata_combo, current_value);
+	    language_list = new CheckList(false);
+	    language_list.setListData(getLanguageCodes());
+	    language_list.setToolTipText(Dictionary.get("CDM.LanguageManager.Selector_Tooltip"));
+	    language_list.setCellRenderer(new LanguageCheckListCellRenderer());
+	    	    
+	    JPanel movement_pane = new JPanel();
+	    move_up_button = new GLIButton(Dictionary.get("CDM.Move.Move_Up"), JarTools.getImage("arrow-up.gif"), Dictionary.get("CDM.Move.Move_Up_Tooltip"));
+	    move_up_button.setEnabled(false);
+	    
+	    move_down_button = new GLIButton(Dictionary.get("CDM.Move.Move_Down"), JarTools.getImage("arrow-down.gif"), Dictionary.get("CDM.Move.Move_Down_Tooltip"));
+	    move_down_button.setEnabled(false);
+	    
+	    set_default_button = new GLIButton(Dictionary.get("CDM.LanguageManager.Set_Default"), Dictionary.get("CDM.LanguageManager.Set_Default_Tooltip"));
+	    set_default_button.setEnabled(false);
+	    
+	    JPanel button_panel = new JPanel();
+
+	    add_button = new GLIButton(Dictionary.get("CDM.SubcollectionIndexManager.Add_Subindex"), Dictionary.get("CDM.LanguageManager.Add_Tooltip"));
+	    add_button.setEnabled(false);
+
+	    replace_button = new GLIButton(Dictionary.get("CDM.SubcollectionIndexManager.Replace_Subindex"), Dictionary.get("CDM.LanguageManager.Replace_Tooltip"));
+	    replace_button.setEnabled(false);
+	    
+	    remove_button = new GLIButton(Dictionary.get("CDM.SubcollectionIndexManager.Remove_Subindex"), Dictionary.get("CDM.LanguageManager.Remove_Tooltip"));
+	    remove_button.setEnabled(false);
+	    
+	    // Set up and connect listeners.
+	    add_button.addActionListener(new AddListener());
+	    add_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
+	    move_down_button.addActionListener(new MoveListener(false));
+	    move_down_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
+	    move_up_button.addActionListener(new MoveListener(true));
+	    move_up_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
+	    remove_button.addActionListener(new RemoveListener());
+	    remove_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
+	    replace_button.addActionListener(new ReplaceListener());
+	    replace_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
+
+	    language_list.addListSelectionListener(new LanguageListListener());
+	    language_metadata_combo.addActionListener(new ActionListener() {
+		    public void actionPerformed(ActionEvent event) {
+			String value = ((MetadataElement)language_metadata_combo.getSelectedItem()).getFullName();
+			language_metadata.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+			language_metadata.setAttribute(StaticStrings.NAME_ATTRIBUTE, value);
+		    }
+		});
+	    set_default_button.addActionListener(new SetDefaultListener());
+	    set_default_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
+	    selected_languages_list.addListSelectionListener(new AssignedListListener());
+
+	    // Layout components
+	    button_panel.setLayout(new GridLayout(1,3));
+	    button_panel.add(add_button);
+	    button_panel.add(replace_button);
+	    button_panel.add(remove_button);
+
+	    JPanel metadata_panel = new JPanel();
+	    metadata_panel.setLayout(new BorderLayout());
+	    JPanel inner_panel = new JPanel();
+	    inner_panel.setLayout(new BorderLayout(10,10));
+	    inner_panel.add(language_metadata_label, BorderLayout.WEST);
+	    inner_panel.add(language_metadata_combo, BorderLayout.CENTER);
+	    metadata_panel.add(new JPanel(), BorderLayout.CENTER);
+	    metadata_panel.add(inner_panel, BorderLayout.EAST);
+
+	    movement_pane.setBorder(BorderFactory.createEmptyBorder(0,2,0,0));
+	    movement_pane.setLayout(new GridLayout(3,1));
+	    movement_pane.add(move_up_button);
+	    movement_pane.add(move_down_button);
+	    movement_pane.add(set_default_button);
+
+	    control_panel.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	    control_panel.setLayout(new BorderLayout());
+	    control_panel.add(selector_label, BorderLayout.WEST);
+	    control_panel.add(new JScrollPane(language_list), BorderLayout.CENTER);
+	    control_panel.add(button_panel, BorderLayout.SOUTH);
+
+	    center_panel.setLayout(new BorderLayout());
+	    center_panel.add(selected_languages_list_label, BorderLayout.NORTH);
+	    center_panel.add(new JScrollPane(selected_languages_list), BorderLayout.CENTER);
+	    center_panel.add(movement_pane, BorderLayout.EAST);
+
+	    JPanel top_panel = new JPanel();
+	    top_panel.setLayout(new BorderLayout());
+	    top_panel.add(metadata_panel, BorderLayout.NORTH);
+	    top_panel.add(center_panel, BorderLayout.SOUTH);
+	    
+	    setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	    setLayout(new BorderLayout());
+	    add(top_panel, BorderLayout.NORTH);
+	    add(control_panel, BorderLayout.CENTER);
+	}
+	
+	/** Destructor.	*/
+	public void destroy() {
+	}
+
+	public void gainFocus() {
+	}
+
+	public void loseFocus() {
+	}
+
+	
+	private void clearControls() {
+	    selected_languages_list.clearSelection();
+	    language_list.clearTicked();
+	    add_button.setEnabled(false);
+	    remove_button.setEnabled(false);
+	    replace_button.setEnabled(false);
+	    set_default_button.setEnabled(false);
+	    move_down_button.setEnabled(false);
+	    move_up_button.setEnabled(false);
+
+	}
+	
+	private void updateControlsWithSelectedLanguage()
+	{
+	    Language selected_lang = (Language) selected_languages_list.getSelectedValue();
+	    if (selected_lang == null) {
+		clearControls();
+		return;
+	    }
+	    
+	    // Display the selected subcollection index's sources
+	    language_list.clearTicked();
+	    language_list.setTickedObjects(selected_lang.getCode().split(","));
+	    
+	}
+
+	private void validateButtons() {
+	    boolean add_enabled = false;
+	    boolean replace_enabled = false;
+
+	    if (!language_list.isNothingTicked()) {
+		// Create a dummy Langauge and see if its in the collection
+		ArrayList langs = language_list.getTicked();
+		StringBuffer code_str = new StringBuffer();
+		boolean first = true;
+		for (int i=0; i<langs.size(); i++) {
+		    if (!first) {
+			code_str.append(",");
+		    } else {
+			first = false;
+		    }
+		    code_str.append(langs.get(i));
+		}
+		String lang_str = code_str.toString();
+		
+		if (!model.contains(lang_str)) {
+		    add_enabled = true;
+		    if (!selected_languages_list.isSelectionEmpty()) {
+			replace_enabled = true;
+		    }
+		}
+
+	    }
+	    add_button.setEnabled(add_enabled);
+	    replace_button.setEnabled(replace_enabled);
+	}
+	
+	/** Listens for actions apon the 'add' button in the LanguageManager controls, and if detected calls the add method of the manager with a newly created language. */
+	private class AddListener
+	    implements ActionListener {
+	    /** Add a new language support.
+	     * @param event an ActionEvent
+	     * @see org.greenstone.gatherer.cdm.Language
+	     */
+	    public void actionPerformed(ActionEvent event) {
+		if (!language_list.isNothingTicked()) {
+		    addLanguage(new Language(language_list.getTicked()));
+		    clearControls();
+		}
+	    }
+	}
+
+	/** Listens for actions apon the 'remove' button in the LanguageManager controls, and if detected calls the remove method of the manager with the language selected for removal. */
+	private class RemoveListener
+	    implements ActionListener {
+	    /** Remove the currently selected language, if any.
+	     * @param event An <strong>ActionEvent</strong>.
+	     * @see org.greenstone.gatherer.cdm.Language
+	     */
+	    public void actionPerformed(ActionEvent event) {
+		Language delete_me = (Language)selected_languages_list.getSelectedValue();
+		if(delete_me != null) {
+		    removeLanguage(delete_me);
+		}
+	    }
+	}
+
+	private class ReplaceListener
+	    implements ActionListener {
+	    
+	    public void actionPerformed(ActionEvent event) {
+		if (selected_languages_list.isSelectionEmpty() || language_list.isNothingTicked()) {
+		    // This should never happen, but just in case...
+		    replace_button.setEnabled(false);
+		    return;
+		}
+		Language old_language = (Language) selected_languages_list.getSelectedValue();
+		Language new_language = new Language(language_list.getTicked());
+		replaceLanguage(old_language, new_language);
+		
+	    }
+	}
+	
+	private class LanguageListListener
+	    implements ListSelectionListener {
+
+	    public void valueChanged(ListSelectionEvent event) {
+		if (event.getValueIsAdjusting()) {
+		    return;
+		}
+		validateButtons();
+	    }
+	}
+	
+	/** Listens for actions apon the 'set default' button in the LanguageManager controls, and if detected calls the <i>setDefault()</i> method of the manager with the language selected for default. */
+	private class SetDefaultListener
+	    implements ActionListener {
+	    /** Set the default index to the one currently selected, if any.
+	     * @param event An <strong>ActionEvent</strong>.
+	     * @see org.greenstone.gatherer.cdm.Language
+	     */
+	    public void actionPerformed(ActionEvent event) {
+		Language selected_language = (Language) selected_languages_list.getSelectedValue();
+		if(selected_language != null) {
+		    setDefault(selected_language);
+		    // This should cause a repaint of just the desired row
+		    selected_languages_list.setSelectedValue(selected_language, true);
+		}
+		set_default_button.setEnabled(false);
+	    }
+	}
+
+	private class MoveListener
+	    implements ActionListener
+	{
+	    private boolean move_up;
+
+	    public MoveListener(boolean move_up)
+	    {
+		this.move_up = move_up;
+	    }
+
+	    public void actionPerformed(ActionEvent event)
+	    {
+		// Retrieve the selected language
+		Language language = (Language) selected_languages_list.getSelectedValue();
+		if (language != null) {
+		    int new_position = moveLanguage(language, move_up);
+		    // Ensure the language that moved is still selected
+		    selected_languages_list.setSelectedIndex(new_position);
+		}
+	    }
+	}
+
+
+	/** Listens for selections within the list on the LanguageManager controls, and if a change is detected enables, or disables, controls appropriately. */
+	private class AssignedListListener
+	    implements ListSelectionListener {
+	    /** Enable or disable controls depending on the current list selection.
+	     * @param event A <strong>ListSelectionEvent</strong>.
+	     */
+	    public void valueChanged(ListSelectionEvent event) {
+		if (event.getValueIsAdjusting()) {
+		    return;
+		}
+		if(selected_languages_list.isSelectionEmpty()) {
+		    clearControls();
+		    return;
+		}
+		
+		int i = selected_languages_list.getSelectedIndex();
+ 		int size = selected_languages_list.getModel().getSize();
+		Language selected_lang = (Language)selected_languages_list.getSelectedValue();
+		remove_button.setEnabled(true);
+		replace_button.setEnabled(false);
+		add_button.setEnabled(false);
+		set_default_button.setEnabled(default_language == null || !default_language.equals(selected_lang));
+		
+		if (i > 0) {
+ 		    move_up_button.setEnabled(true);
+ 		}
+ 		else {
+ 		    move_up_button.setEnabled(false);
+ 		}
+ 		if (i < size-1){
+ 		    move_down_button.setEnabled(true);
+ 		}
+ 		else {
+ 		    move_down_button.setEnabled(false);
+ 		}
+		updateControlsWithSelectedLanguage();
+	    }
+	}
+
+	private class MyLanguageListCellRenderer
+	    extends DefaultListCellRenderer
+	{
+	    /** Return a component that has been configured to display the specified value. */
+	    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+		JLabel component = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+		if (default_language != null && default_language.equals(value)) {
+		    component.setText(component.getText() + " [" + Dictionary.get("CDM.LanguageManager.Default_Language")+"]");
+		}
+		return component;
+	    }
+	}
+    }
+    
+    /** A custom list cell renderer for producing rows which contain clickable check boxes. */
+    private class LanguageCheckListCellRenderer 
+	implements ListCellRenderer
+    {
+	/** Return a component that has been configured to display the specified value. That component's paint method is then called to "render" the cell. If it is necessary to compute the dimensions of a list because the list cells do not have a fixed size, this method is called to generate a component on which getPreferredSize  can be invoked.
+	 * @param list The </strong>JList</strong> we're painting.
+	 * @param value The value returned by list.getModel().getElementAt(index), as an <strong>Object</strong>.
+	 * @param index The cells index as an <i>int</i>.
+	 * @param is_selected <i>true</i> if the specified cell was selected, <i>false</i> otherwise.
+	 * @param cell_has_focus <i>true</i> if and only if the specified cell has the focus.
+	 * @return A <strong>Component</strong> whose paint() method will render the specified value.
+	 */
+	public Component getListCellRendererComponent(JList list, Object value, int index, boolean is_selected, boolean cell_has_focus) {
+	    JCheckBox checkbox = (JCheckBox) value;
+	    checkbox.setBackground(list.getBackground());
+	    checkbox.setForeground(list.getForeground());
+	    checkbox.setBorderPainted(false);
+	    checkbox.setEnabled(list.isEnabled());
+	    checkbox.setFont(list.getFont());
+	    checkbox.setFocusPainted(false);
+	    checkbox.setBorder((is_selected) ? UIManager.getBorder("List.focusCellHighlightBorder") : new EmptyBorder(1, 1, 1, 1));
+	    
+	    String code = (String)((CheckListEntry)list.getModel().getElementAt(index)).getObject();
+	    checkbox.setText((String)known_languages.get(code));
+
+	    return checkbox;
+	}
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/MacrosManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/MacrosManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/MacrosManager.java	(revision 13928)
@@ -0,0 +1,297 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Katherine Don, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.undo.*;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.gui.DesignPaneHeader;
+import org.greenstone.gatherer.gui.GLIButton;
+import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
+
+
+public class MacrosManager {
+
+    /** The controls used to modify the general options. */
+    private Control controls;
+    /** Constructor. */
+    public MacrosManager() {
+    }
+
+
+    /** Destructor. */
+    public void destroy() {
+	if (controls != null) {
+	    controls.destroy();
+	    controls = null;
+	}
+    }
+
+    public void loseFocus() {
+    }
+
+    public void gainFocus() {
+
+    }
+    /** This class is resposible for generating the controls for the editing of general options.
+     * @return the Control for editing the general options
+     */
+    public Control getControls() {
+	if (controls == null) {
+	    controls = new MacrosControl();
+	}
+	return controls;
+    }
+    
+
+    /** Called when the detail mode has changed which in turn may cause several design elements to be available/hidden
+     * @param mode the new mode as an int
+     */
+    public void modeChanged(int mode) {
+
+    }
+
+
+    private class MacrosControl
+	extends JPanel
+	implements Control, WindowFocusListener {
+
+	JTextArea macros_textarea = null;
+	JButton undo_button = null;
+	JButton redo_button = null;
+	private final UndoManager undo = new UndoManager();
+	private boolean macros_changed = false;
+	public MacrosControl() {
+	    super();
+
+	    JPanel header_pane = new DesignPaneHeader("CDM.GUI.Macros", "collectionspecificmacros");
+	    
+	    JPanel main_pane = new JPanel();
+	    main_pane.setLayout(new BorderLayout());
+	    macros_textarea = new JTextArea();
+	    macros_textarea.setBackground(Configuration.getColor("coloring.editable_background", false));
+	    macros_textarea.setLineWrap(false);
+	    macros_textarea.setWrapStyleWord(false);
+	    macros_textarea.setToolTipText(Dictionary.get("CDM.MacrosManager.Editor_Tooltip"));
+	    readMacroFile(); // load in the original contents
+	    macros_textarea.getDocument().addDocumentListener(new EditorListener());
+
+	    // Listen for undo and redo events
+	    macros_textarea.getDocument().addUndoableEditListener(new UndoableEditListener() {
+		    public void undoableEditHappened(UndoableEditEvent evt) {
+			undo.addEdit(evt.getEdit());
+		    }
+		});
+	    macros_textarea.setCaretPosition(0);
+	    
+	    JPanel macros_pane = new JPanel();
+	    macros_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
+	    macros_pane.setLayout(new BorderLayout());
+	    macros_pane.add(new JScrollPane(macros_textarea), BorderLayout.CENTER);
+	    undo_button = new GLIButton(Dictionary.get("General.Undo"), Dictionary.get("General.Undo_Tooltip"));
+	    undo_button.setEnabled(false);
+	    undo_button.addActionListener(new UndoListener());
+
+	    redo_button = new GLIButton(Dictionary.get("General.Redo"), Dictionary.get("General.Redo_Tooltip"));
+	    redo_button.setEnabled(false);
+	    redo_button.addActionListener(new RedoListener());
+	    
+	    JPanel button_pane = new JPanel();
+	    button_pane.setLayout(new GridLayout(1,2));
+	    button_pane.add(undo_button);
+	    button_pane.add(redo_button);
+
+	    main_pane.add(macros_pane, BorderLayout.CENTER);
+	    main_pane.add(button_pane, BorderLayout.SOUTH);
+
+	    setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
+	    setLayout(new BorderLayout());
+	    add(header_pane, BorderLayout.NORTH);
+	    add(main_pane, BorderLayout.CENTER);
+	    Gatherer.g_man.addWindowFocusListener(this);
+	}
+
+	public void destroy() {
+	}
+
+	public void loseFocus() {
+	    if (macros_changed) {
+		writeMacroFile();
+		macros_changed = false;
+	    }
+	}
+
+	public void gainFocus() {
+	    macros_textarea.grabFocus();
+	}
+	
+	public void windowGainedFocus(WindowEvent e) {
+	}
+	
+	public void windowLostFocus(WindowEvent e) {
+	    if (macros_changed) {
+		writeMacroFile();
+		macros_changed = false;
+	    }	    
+	}
+
+	private void readMacroFile() {
+	    macros_textarea.setText("");
+	    File extra_dm = new File(CollectionManager.getLoadedCollectionMacrosDirectoryPath() + "extra.dm");
+	    
+	    if (extra_dm.exists()) {
+		try {
+		    BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(extra_dm), "UTF-8"));
+		
+		    String line;
+		    while ((line = br.readLine()) != null) {
+			macros_textarea.append(line+"\n");
+		    }
+
+		    br.close();
+		}
+		catch (Exception exception) {
+		    DebugStream.printStackTrace(exception);
+		}
+	    }
+	}
+	
+	private void writeMacroFile() {
+	    File extra_dm_file = new File(CollectionManager.getLoadedCollectionMacrosDirectoryPath() + "extra.dm");
+	    try {
+		if (!extra_dm_file.exists()) {
+		    File parent_dir = extra_dm_file.getParentFile();
+		    parent_dir.mkdirs();
+		    extra_dm_file.createNewFile();
+		}
+		
+		BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(extra_dm_file), "UTF-8"));
+		String text = macros_textarea.getText();
+		out.write(text, 0, text.length());
+		out.newLine();
+		out.flush();
+		out.close();
+
+		// If we're using a remote Greenstone server, upload the new extra.dm file
+		// This will return immediately, since we're on the event dispatch thread
+		// Users need to wait until the upload has finished before pressing Preview Collection!
+		if (Gatherer.isGsdlRemote) {
+		    RemoteGreenstoneServer.uploadCollectionFile(CollectionManager.getLoadedCollectionName(), extra_dm_file);
+		}
+	    }
+	    catch (Exception exception) {
+		DebugStream.printStackTrace(exception);
+	    }
+	}
+
+	private class EditorListener
+	    implements DocumentListener {
+	    public void changedUpdate(DocumentEvent e) {
+		macros_changed = true;
+		undo_button.setEnabled(true);
+	    }
+          
+	    public void insertUpdate(DocumentEvent e) {
+		macros_changed = true;
+		undo_button.setEnabled(true);
+	    }
+          
+	    public void removeUpdate(DocumentEvent e) {
+		macros_changed = true;
+		undo_button.setEnabled(true);
+	    }
+
+	}
+
+	private class UndoListener
+	    implements ActionListener {
+	    
+	    public void actionPerformed(ActionEvent event) {
+		try {
+                    if (undo.canUndo()) {
+                        int pos = macros_textarea.getCaretPosition();
+                        undo.undo();
+			macros_textarea.setCaretPosition(pos-1);
+			macros_textarea.grabFocus();
+			redo_button.setEnabled(true); 
+			
+                    }
+                    if (!undo.canUndo()){
+			undo_button.setEnabled(false);
+		    }
+		    else{
+                      	undo_button.setEnabled(true); 
+		    }   
+                }
+		catch (Exception exception) {
+		    DebugStream.printStackTrace(exception);
+                }           
+	    }
+	}
+    
+
+	private class RedoListener
+	    implements ActionListener {
+	   
+	    public void actionPerformed(ActionEvent evt) {
+		try {
+		    if (undo.canRedo()) {
+			int pos = macros_textarea.getCaretPosition();
+			undo.redo();
+			macros_textarea.setCaretPosition(pos+1); 
+			macros_textarea.grabFocus();
+		    }
+		    if (!undo.canRedo()){
+			redo_button.setEnabled(false);
+		    }
+		    else{
+			redo_button.setEnabled(true); 
+		    }
+		}
+		catch (Exception exception) {
+		    DebugStream.printStackTrace(exception);
+		}
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/ParsingProgress.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/ParsingProgress.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/ParsingProgress.java	(revision 13928)
@@ -0,0 +1,101 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+/**************************************************************************************
+ * Title:        Gatherer
+ * Description:  The Gatherer: a tool for gathering and enriching a digital collection.
+ * Copyright:    Copyright (c) 2001
+ * Company:      The University of Waikato
+ * Written:      03/05/02
+ * Revised:      20/05/02
+ *               17/11/02 - Commented
+ **************************************************************************************/
+import java.awt.*;
+import javax.swing.*;
+
+/** This class provides a progress bar to be displayed whenever the module must reload the plugin and classifier information, either automatically or if the user indicates a reload is needed.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class ParsingProgress
+    extends JDialog {
+    /** The content pane within the dialog box. */
+    private JPanel content_pane = null;
+    /** The progress bar itself. */
+    private JProgressBar progress = null;
+    /** The default size of the progress dialog. */
+    static final Dimension SIZE = new Dimension(600,75);
+
+    /** Constructor.
+     * @param title The title to show on the dialog, as a <strong>String</strong>.
+     * @param message The message to show on the dialog, as a <strong>String</strong>.
+     * @param max The total number of plugins/classifiers that have to be parsed before the progress bar can be disposed of, as an <i>int</i>.
+     */
+    public ParsingProgress(String title, String message, int max) {
+	super();
+	this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
+	this.setSize(SIZE);
+	this.setTitle(title);
+
+	// Creation
+	this.content_pane = (JPanel) getContentPane();
+	this.progress = new JProgressBar();
+	this.progress.setMaximum(max);
+
+	// Layout
+	this.content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	this.content_pane.setLayout(new BorderLayout());
+	this.content_pane.add(new JLabel(message), BorderLayout.NORTH);
+	this.content_pane.add(progress, BorderLayout.CENTER);
+
+	// Center and display
+	Dimension screen_size = Toolkit.getDefaultToolkit().getScreenSize();
+	setLocation((screen_size.width - SIZE.width) / 2,
+		    (screen_size.height - SIZE.height) / 2);
+	setVisible(true);
+    }
+
+    public void destroy() {
+    }
+
+    /** Method which increments the progress count by one, which should be called after every successful parsing of a classifier or plugin.
+     */
+    public void inc() {
+	progress.setValue(progress.getValue() + 1);
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/Plugin.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/Plugin.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/Plugin.java	(revision 13928)
@@ -0,0 +1,218 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import java.io.*;
+import java.util.*;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.greenstone.Plugins;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.w3c.dom.*;
+
+
+/** This class is responsible for storing information from a parsed pluginfo call in such a way that it allows easy access to parsed details for the purposes of user design and specification of plugins. */
+public class Plugin
+    extends ArgumentContainer
+{
+    private String default_block_expression = "";
+    private String default_process_expression = "";
+    private boolean does_explode_metadata_databases = false; 
+    private boolean loading_options_failed = false;
+
+    
+    /** Constructor used in DOMProxyListModel initializations, and Library Level. Used for Base plugins (those in the list of available plugins, not ones that are in the DOMProxyList)
+     */
+    public Plugin() {
+    }
+
+    
+    public Plugin(Element element, Plugin base_plugin) {
+	super(element, base_plugin);
+    }
+
+
+    /** Method to compare two plugins for ordering.
+     * We override the base method cos we compare by plugin name rather than toString()
+     */
+    public int compareTo(Object object) {
+	if(object instanceof Plugin) {
+	    return name.compareTo(((Plugin)object).getName());
+	}
+	return -1;
+    }
+
+    
+    /** The assigned plugin constructor.
+     * @param element the DOM Element this plugin is based upon
+     */
+    public DOMProxyListEntry create(Element element) {
+	String plugin_name = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE);
+	// Determine the base plugin from the plugin name
+	Plugin base_plugin = Plugins.getPlugin(plugin_name, true);
+	Plugin plugin = new Plugin(element, base_plugin);
+	if (base_plugin == null) {
+	    plugin.setAssigned(false);
+	}
+	base_plugin = null;
+	plugin_name = null;
+	return plugin;
+    }
+
+
+    public boolean didLoadingOptionsFail()
+    {
+	return loading_options_failed;
+    }
+
+
+    /** Checks whether the plugin this instance is based on processes metadata databases that can be exploded. */
+    public boolean doesExplodeMetadataDatabases()
+    {
+	Plugin base_plugin = Plugins.getPlugin(getName(), false);
+	if (base_plugin == null) {
+	    return false;
+	}
+	return base_plugin.does_explode_metadata_databases;
+    }
+
+
+    /** Checks whether this plugin instance will process the specified file (given its block_exp). */
+    public boolean doesBlockFile(File file)
+    {
+	// Check the filename against the plugin's block_exp value
+	ArrayList arguments = getArguments();
+	for (int i = 0; i < arguments.size(); i++) {
+	    Argument argument = (Argument) arguments.get(i);
+	    if (argument.getName().equals("block_exp")) {
+		// Try the assigned value first, for when the user has manually set the value
+		String regular_expression = argument.getValue();
+		if (regular_expression == null || regular_expression.equals("")) {
+		    // Not set, so use the default value
+		    regular_expression = argument.getDefaultValue();
+		    if (regular_expression.equals("")) {
+			continue;
+		    }
+		}
+
+		if (doesFileMatchRegularExpression(file, regular_expression)) {
+		    return true;
+		}
+	    }
+	}
+
+	// Try the plugin's default block expression
+	if (!default_block_expression.equals("") && doesFileMatchRegularExpression(file, default_block_expression)) {
+	    return true;
+	}
+
+	// This plugin will (probably) not deal with the specified file
+	return false;
+    }
+
+
+    /** Checks whether this plugin instance will process the specified file (given its process_exp). */
+    public boolean doesProcessFile(File file)
+    {
+	// Check the filename against the plugin's process_exp value
+	ArrayList arguments = getArguments();
+	for (int i = 0; i < arguments.size(); i++) {
+	    Argument argument = (Argument) arguments.get(i);
+	    if (argument.getName().equals("process_exp")) {
+		// Try the assigned value first, for when the user has manually set the value
+		String regular_expression = argument.getValue();
+		if (regular_expression == null || regular_expression.equals("")) {
+		    // Not set, so use the default value
+		    regular_expression = argument.getDefaultValue();
+		    if (regular_expression.equals("")) {
+			continue;
+		    }
+		}
+
+		if (doesFileMatchRegularExpression(file, regular_expression)) {
+		    return true;
+		}
+	    }
+	}
+
+	// Try the plugin's default process expression
+	if (!default_process_expression.equals("") && doesFileMatchRegularExpression(file, default_process_expression)) {
+	    return true;
+	}
+
+	// This plugin will (probably) not deal with the specified file
+	return false;
+    }
+
+
+    private boolean doesFileMatchRegularExpression(File file, String regular_expression)
+    {
+	// The $ at the end doesn't seem to work in Java, so need to add ".*" at the start
+	if (regular_expression.startsWith("(?i)")) {
+	    // Don't mess up case-insensitive matching though
+	    regular_expression = "(?i)" + ".*" + regular_expression.substring("(?i)".length());
+	}
+	else {
+	    regular_expression = ".*" + regular_expression;
+	}
+
+	// If the filename matches the regular expression, this plugin will deal with the file in some way
+	if (file.getName().matches(regular_expression)) {
+	    return true;
+	}
+
+	return false;
+    }
+
+
+    public boolean isSeparator() {
+	return (element != null && element.getAttribute(StaticStrings.SEPARATOR_ATTRIBUTE).equals(StaticStrings.TRUE_STR));
+    }
+
+
+    public void setDefaultBlockExpression(String default_block_expression)
+    {
+	this.default_block_expression = default_block_expression;
+    }
+
+
+    public void setDefaultProcessExpression(String default_process_expression)
+    {
+	this.default_process_expression = default_process_expression;
+    }
+
+
+    public void setDoesExplodeMetadataDatabases(boolean does_explode_metadata_databases)
+    {
+	this.does_explode_metadata_databases = does_explode_metadata_databases;
+    }
+
+
+    public void setLoadingOptionsFailed()
+    {
+	this.loading_options_failed = true;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/PluginManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/PluginManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/PluginManager.java	(revision 13928)
@@ -0,0 +1,1030 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.plaf.*;
+import javax.swing.plaf.basic.*;
+import org.apache.xerces.parsers.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.CollectionContentsChangedListener;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.greenstone.Plugins;
+import org.greenstone.gatherer.gui.DesignPaneHeader;
+import org.greenstone.gatherer.gui.GComboBox;
+import org.greenstone.gatherer.gui.GLIButton;
+import org.greenstone.gatherer.gui.ModalDialog;
+import org.greenstone.gatherer.gui.WarningDialog;
+import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
+import org.greenstone.gatherer.util.JarTools;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.util.XMLTools;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+
+
+/** This class is for maintaining a list of known plug-ins, and importing new plugins using the parser. */
+public class PluginManager
+    extends DOMProxyListModel
+    implements CollectionContentsChangedListener
+{
+    /** When asking how many rows are in the model, and if this variables value is true, then this modifier alters the number returned. This funtionality is used to hide the last three rows of the list in low detail modes. */
+    private boolean modify_row_count = false;
+    /** The controls for editing the contents of this manager. */
+    private Control controls = null;
+    private DOMProxyListModel model;
+    private JPanel separator;
+    private Plugin separator_plugin;
+    /** Constructor.
+     */
+    public PluginManager() {	super(CollectionDesignManager.collect_config.getDocumentElement(), StaticStrings.PLUGIN_ELEMENT, new Plugin());
+	DebugStream.println("PluginManager: " + super.getSize() + " plugins parsed.");
+	model = this;
+
+	// Force the assigned plugins to be loaded and cached now
+	for (int i = 0; i < getSize(); i++) {
+	    getElementAt(i);
+	}
+	
+	// Create the separator, cause we can reuse it.
+	separator = getSeparator();
+	placeSeparator();
+	// check for MetadataXMLPlug
+	ensureMetadataXMLPlugIsLoaded();
+	// Listen for CollectionContentsChanged events, so we can give plugin hints when new files are added
+	CollectionManager.addCollectionContentsChangedListener(this);
+	
+    }
+
+    private void ensureMetadataXMLPlugIsLoaded() {
+
+	Plugin metaxmlplug = Plugins.getPlugin("MetadataXMLPlug", false);
+	if (metaxmlplug!= null) {
+	    if (!contains(metaxmlplug)) {
+		// Create a new element in the DOM
+		Element new_plugin_element = CollectionConfiguration.createElement(StaticStrings.PLUGIN_ELEMENT);
+		new_plugin_element.setAttribute(StaticStrings.TYPE_ATTRIBUTE, metaxmlplug.getName());
+		Plugin new_plugin = new Plugin(new_plugin_element, metaxmlplug);
+		assignPlugin(new_plugin);
+	    }
+	}
+    }
+
+
+    /** Retrieve a list of the plugins that are available to be added to the collection. */
+    private Object[] getAvailablePlugins()
+    {
+	ArrayList available = new ArrayList();
+
+	// Add all the non-abstract core Greenstone plugins, except for ArcPlug and RecPlug
+	ArrayList plugins_list = Plugins.getPluginsList();
+	for (int i = 0; i < plugins_list.size(); i++) {
+	    Plugin plugin = (Plugin) plugins_list.get(i);
+	    if (!plugin.isAbstract()) {
+		String plugin_name = plugin.getName();
+		if (!plugin_name.equals(StaticStrings.ARCPLUG_STR) && !plugin_name.equals(StaticStrings.RECPLUG_STR)) {
+		    available.add(plugin);
+		}
+	    }
+	}
+
+	// Now remove any assigned plugins
+	if (Configuration.getMode() < Configuration.SYSTEMS_MODE) {
+	    available.removeAll(children());
+	}
+        
+	// Sort the available plugins into alphabetical order
+	Collections.sort(available);
+
+	return available.toArray();
+    }
+
+
+    public ArrayList getExploderPlugins(File file)
+    {
+	ArrayList exploder_plugins = new ArrayList();
+	ArrayList plugins_list = Plugins.getPluginsList();
+	for (int i = 0; i < plugins_list.size(); i++) {
+	    Plugin plugin = (Plugin) plugins_list.get(i);
+	    if (plugin.doesExplodeMetadataDatabases() == true && plugin.doesProcessFile(file)) {
+		exploder_plugins.add(plugin);
+	    }
+	}
+
+	return exploder_plugins;	
+    }
+
+    
+    public boolean isFileExplodable(File file)
+    {
+	ArrayList plugins_list = Plugins.getPluginsList();
+	for (int i = 0; i < plugins_list.size(); i++) {
+	    Plugin plugin = (Plugin) plugins_list.get(i);
+	    if (plugin.doesExplodeMetadataDatabases() == true && plugin.doesProcessFile(file) == true) { 
+		return true;
+	    }
+	}
+
+	return false;
+    }
+
+
+    /** Method to assign a plugin
+     * @param plugin the Plugin to assign
+     */
+    private void assignPlugin(Plugin plugin) {
+	if(plugin.getName().equals(StaticStrings.RECPLUG_STR) || plugin.getName().equals(StaticStrings.ARCPLUG_STR)) {
+	    addAfter(plugin, separator_plugin); // Adds after separator
+	} else {
+	    addBefore(plugin, separator_plugin);
+	}
+    }
+
+
+    /** Destructor. */
+    public void destroy()
+    {
+	CollectionManager.removeCollectionContentsChangedListener(this);
+
+	if (controls != null) {
+	    controls.destroy();
+	    controls = null;
+	}
+    }
+
+
+    /** This function listens for new files being added to the collection and hints about suitable plugins. */
+    public void fileAddedToCollection(File file)
+    {
+	// First check the plugins already assigned in the collection
+	for (int i = 0; i < super.getSize(); i++) {
+	    Plugin assigned_plugin = (Plugin) getElementAt(i);
+	    if (assigned_plugin.isSeparator() == false && (assigned_plugin.doesProcessFile(file) == true || assigned_plugin.doesBlockFile(file) == true)) {
+		// This file will be processed by an assigned plugin, so no suggestion is necessary
+		DebugStream.println("Processed by assigned plugin: " + assigned_plugin);
+		return;
+	    }
+	}
+
+	// Next try the plugins NOT already assigned in the collection
+	ArrayList suitable_plugins = new ArrayList();
+	Object[] unassigned_plugins = getAvailablePlugins();
+	for (int i = 0; i < unassigned_plugins.length; i++) {
+	    Plugin unassigned_plugin = (Plugin) unassigned_plugins[i];
+	    if (unassigned_plugin.doesProcessFile(file) == true) {
+		DebugStream.println("Processed by unassigned plugin: " + unassigned_plugin);
+		suitable_plugins.add(unassigned_plugin);
+	    }
+	}
+
+	// If there appear to be no suitable plugins, warn the user about this and be done
+	if (suitable_plugins.size() == 0) {
+	    String[] args = new String[1];
+	    args[0] = file.getName();
+	    WarningDialog warning_dialog = new WarningDialog("warning.NoPluginExpectedToProcessFile", Dictionary.get("NoPluginExpectedToProcessFile.Title"), Dictionary.get("NoPluginExpectedToProcessFile.Message", args), null, false);
+	    warning_dialog.display();
+	    warning_dialog.dispose();
+	    return;
+	}
+
+	// Generate a dialog 
+	new PluginSuggestionPrompt(file.getName(), suitable_plugins);
+    }
+
+
+    /** Method to retrieve the control for this manager.
+     * @return the Control
+     */
+    public Control getControls() {
+	if(controls == null) {
+	    // Build controls
+	    controls = new PluginControl();
+	}
+	return controls;
+    }
+
+
+    /** Overrides getSize in DOMProxyListModel to take into account the row count modifier used to hide the last three rows in lower detail modes
+     * @return an int indicating the number of rows in the model, or more correctly the desired number of rows to display
+     */
+    public int getSize() {
+	int result = super.getSize();
+	if(modify_row_count) {
+	    result = result-3;
+	}
+	return result;
+    }
+
+    /** Called when the detail mode has changed which in turn may cause several design elements to be available/hidden
+     * @param mode the new mode as an int
+     */
+    public void modeChanged(int mode) {
+	if(controls != null) {
+	    ((PluginControl)controls).modeChanged(mode);
+	}
+    }    
+
+    /** Method to move a plugin in the list order.
+     * @param plugin the Plugin you want to move.
+     * @param direction true to move the plugin up, false to move it down.
+     * @param all true to move to move all the way, false for a single step.
+     */
+    // why are all the error notices there when the buttons are disabled is you cant move???
+    private void movePlugin(Plugin plugin, boolean direction, boolean all) {
+	// Can't ever move RecPlug or ArcPlug
+	if(super.getSize() < 4) {
+	    //DebugStream.println("Not enough plugins to allow moving.");
+	    return;
+	}
+	if(plugin.getName().equals(StaticStrings.ARCPLUG_STR) || plugin.getName().equals(StaticStrings.RECPLUG_STR)) {
+	    JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.Move.Fixed"), Dictionary.get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
+	    return;
+	}
+	if(all) {
+	    // Move to top
+	    if(direction) {
+		// Remove the moving plugin
+		remove(plugin);
+		// Retrieve the first plugin
+		Plugin first_plugin = (Plugin) getElementAt(0);
+		// Add the moving plugin before the first plugin
+		addBefore(plugin, first_plugin);
+		first_plugin = null;
+	    }
+	    else {
+		// Remove the moving plugin
+		remove(plugin);
+		// Add the moving plugin before the separator
+		addBefore(plugin, separator_plugin);
+	    }
+	}
+	else {
+	    // Try to move the plugin one step in the desired direction.
+	    int index = indexOf(plugin);
+	    ///ystem.err.println("Index of " + plugin + " = " + index);
+	    if(direction) {
+		index--;
+		if(index < 0) {
+		    String args[] = new String[2];
+		    args[0] = Dictionary.get("CDM.PlugInManager.PlugIn_Str");
+		    args[1] = plugin.getName();
+		    JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.Move.At_Top", args), Dictionary.get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
+		    return;
+		}
+		remove(plugin);
+		add(index, plugin);
+	    }
+	    else {
+		index++;
+		Plugin next_plugin = (Plugin) getElementAt(index);
+		if(next_plugin.isSeparator()) {
+		    String args[] = new String[1];
+		    args[0] = plugin.getName();
+		    JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.Move.Cannot", args), Dictionary.get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
+		    // Still not going to move RecPlug or ArcPlug.
+		    return;
+		}
+		remove(plugin);
+		add(index, plugin);
+	    }
+	}
+    }
+
+    /** We attempt to place the separator between the unfixed and the fixed plugins. Since we only know of two fixed plugins, we search for either of them, and place the separator before them.
+     */
+    private void placeSeparator() {
+	///ystem.err.println("Placing separator.");
+	int separator_index = super.getSize();
+	if(separator_index > 0) { 
+	    boolean found_fixed = false;
+	    int index = separator_index - 1;
+	    while(index > 0) {
+		Plugin plugin = (Plugin) getElementAt(index);
+		String name = plugin.getName();
+		if(name.equals(StaticStrings.RECPLUG_STR) || name.equals(StaticStrings.ARCPLUG_STR)) {
+		    found_fixed = true;
+		    index--;
+		}
+		else {
+		    if(found_fixed) {
+			separator_index = index + 1;
+			index = -1;
+		    }
+		    else {
+			index--;
+		    }
+		}
+		name = null;
+		plugin = null;
+	    }
+	}
+	Element element = CollectionConfiguration.createElement(StaticStrings.PLUGIN_ELEMENT);
+	element.setAttribute(StaticStrings.TYPE_ATTRIBUTE, StaticStrings.SEPARATOR_ATTRIBUTE);
+	element.setAttribute(StaticStrings.SEPARATOR_ATTRIBUTE, StaticStrings.TRUE_STR);
+	separator_plugin = new Plugin(element, null);
+	///atherer.println("Adding plugin separator at: " + separator_index);
+	add(separator_index, separator_plugin);
+    }
+
+    /** This method removes an assigned plugin. I was tempted to call it unassign, but remove is more consistant. Note that there is no way to remove a plugin from the library.
+     * @param plugin The <strong>Plugin</strong> to remove.
+     */
+    private void removePlugin(Plugin plugin) {
+	remove(plugin);
+    }
+
+
+    /** Inform the model to hide/show the last three lines on the list.
+     * @param modify_row_count true to hide the last three lines, false otherwise
+     */
+    private void setHideLines(boolean modify_row_count) {
+	this.modify_row_count = modify_row_count;
+	int original_size = super.getSize();
+	if(modify_row_count) {
+	    fireIntervalRemoved(this, original_size - 4, original_size - 1);
+	}
+	else {
+	    fireIntervalAdded(this, original_size - 4, original_size - 1);
+	}
+    }
+
+    /** Determine the current separator index. */
+    private int findSeparatorIndex() {
+	int separator_index = super.getSize() - 1;
+	while(separator_index >= 0) {
+	    Plugin search = (Plugin) getElementAt(separator_index);
+	    if(search.isSeparator()) {
+		return separator_index;
+	    }
+	    separator_index--;
+	}
+	return separator_index;
+    }
+
+
+    /** A class which provodes controls for assigned and editing plugins. */
+    private class PluginControl
+	extends JPanel
+	implements Control {
+	/** Button for adding plugins. */
+	private JButton add = null;
+	/** Button for configuring the selected plugin. */
+	private JButton configure = null;
+	/** Button to move an assigned plugin one position lower in the order. */
+	private JButton move_down_button = null;
+	/** Button to move an assigned plugin one position higher in the order. */
+	private JButton move_up_button = null;
+	/** Button to remove the selected plugin. */
+	private JButton remove = null;
+	/** A combobox containing all of the known plugins, including those that may have already been assigned. */
+	private JComboBox plugin_combobox = null;
+	/** The label next to the plugin combobox. */
+	private JLabel plugin_label = null;
+	/** The label above the assigned plugin list. */
+	private JLabel plugin_list_label = null;
+	/** A list of assigned plugins. */
+	private JList plugin_list = null;
+	/** The area where the add, configure and remove buttons are placed. */
+	private JPanel button_pane = null;
+	/** The region which divides the central portion of the view into list and controls */
+	private JPanel central_pane = null;
+	/** The area where movement buttons are placed. */
+	private JPanel movement_pane = null;
+	/** The small region containing the plugin combobox and its label. */
+	private JPanel plugin_pane = null;
+	/** The pane containing the assigned plugin list and its label. */
+	private JPanel plugin_list_pane = null;
+
+	/** Constructor.
+	 */
+	public PluginControl()
+	{
+	    // Create
+	    add = new GLIButton(Dictionary.get("CDM.PlugInManager.Add"), Dictionary.get("CDM.PlugInManager.Add_Tooltip"));
+	    
+	    button_pane = new JPanel();
+	    central_pane = new JPanel();
+
+	    configure = new GLIButton(Dictionary.get("CDM.PlugInManager.Configure"), Dictionary.get("CDM.PlugInManager.Configure_Tooltip"));
+	    configure.setEnabled(false);
+	    
+	    JPanel header_pane = new DesignPaneHeader("CDM.GUI.Plugins", "plugins");
+	    move_up_button = new GLIButton(Dictionary.get("CDM.Move.Move_Up"), JarTools.getImage("arrow-up.gif"), Dictionary.get("CDM.Move.Move_Up_Tooltip"));
+	    move_up_button.setEnabled(false);
+	    
+	    move_down_button = new GLIButton(Dictionary.get("CDM.Move.Move_Down"), JarTools.getImage("arrow-down.gif"), Dictionary.get("CDM.Move.Move_Down_Tooltip"));
+	    move_down_button.setEnabled(false);
+	    
+	    movement_pane = new JPanel();
+
+	    PluginComboboxListener picl = new PluginComboboxListener();
+	    plugin_combobox = new JComboBox(getAvailablePlugins());
+	    plugin_combobox.setOpaque(!Utility.isMac());
+	    plugin_combobox.setEditable(false);
+	    picl.itemStateChanged(new ItemEvent(plugin_combobox, 0, null, ItemEvent.SELECTED));
+
+	    plugin_label = new JLabel(Dictionary.get("CDM.PlugInManager.PlugIn"));
+	    
+	    plugin_list = new JList(model);
+	    plugin_list.setOpaque(true);
+	    plugin_list.setCellRenderer(new ListRenderer());
+	    plugin_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+	    plugin_list_label = new JLabel(Dictionary.get("CDM.PlugInManager.Assigned"));
+	    //plugin_list_label.setHorizontalAlignment(JLabel.CENTER);
+	    plugin_list_label.setOpaque(true);
+	    
+	    plugin_list_pane = new JPanel();
+	    plugin_pane = new JPanel();
+	    plugin_pane.setOpaque(true);
+
+	    remove = new GLIButton(Dictionary.get("CDM.PlugInManager.Remove"), Dictionary.get("CDM.PlugInManager.Remove_Tooltip"));
+	    remove.setEnabled(false);
+	    
+	    // Listeners
+	    add.addActionListener(new AddListener());
+	    configure.addActionListener(new ConfigureListener());
+	    MoveListener ml = new MoveListener();
+	    move_down_button.addActionListener(ml);
+	    move_down_button.addActionListener(CollectionDesignManager.all_change_listener);
+	    move_up_button.addActionListener(ml);
+	    move_up_button.addActionListener(CollectionDesignManager.all_change_listener);
+	    plugin_combobox.addItemListener(picl);
+	    remove.addActionListener(new RemoveListener());
+	    remove.addActionListener(CollectionDesignManager.all_change_listener);
+	    plugin_list.addMouseListener(new ClickListener());
+	    plugin_list.addListSelectionListener(new ListListener());
+	    picl = null;
+
+	    // Layout
+	    movement_pane.setBorder(BorderFactory.createEmptyBorder(0,2,0,0));
+	    movement_pane.setLayout(new GridLayout(4,1));
+	    movement_pane.add(move_up_button);
+	    movement_pane.add(new JPanel());
+	    movement_pane.add(new JPanel());
+	    movement_pane.add(move_down_button);
+
+	    plugin_list_pane.setLayout(new BorderLayout());
+	    plugin_list_pane.add(plugin_list_label, BorderLayout.NORTH);
+	    plugin_list_pane.add(new JScrollPane(plugin_list), BorderLayout.CENTER);
+	    modeChanged(Configuration.getMode()); // Whether the movement buttons are visible is mode dependant
+
+	    plugin_label.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
+
+	    plugin_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
+	    plugin_pane.setLayout(new BorderLayout(5,0));
+	    plugin_pane.add(plugin_label, BorderLayout.WEST);
+	    plugin_pane.add(plugin_combobox, BorderLayout.CENTER);
+
+	    button_pane.setLayout(new GridLayout(1,3));
+	    button_pane.add(add);
+	    button_pane.add(configure);
+	    button_pane.add(remove);
+
+	    // Scope these mad bordering skillz.
+	    JPanel temp = new JPanel(new BorderLayout());
+	    temp.add(plugin_pane, BorderLayout.NORTH);
+	    temp.add(button_pane, BorderLayout.SOUTH);
+
+	    central_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	    central_pane.setLayout(new BorderLayout());
+	    central_pane.add(plugin_list_pane, BorderLayout.CENTER);
+	    central_pane.add(temp, BorderLayout.SOUTH);
+
+	    setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
+	    setLayout(new BorderLayout());
+	    add(header_pane, BorderLayout.NORTH);
+	    add(central_pane, BorderLayout.CENTER);
+	}
+
+	/** Method which acts like a destructor, tidying up references to persistant objects.
+	 */
+	public void destroy() {
+	}
+
+	/** This method is overridden to ensure the instructions are scrolled to top, before the super classes updateUI() is called.
+	    no longer have instructions, do we still need updateUI???
+	 */
+	public void gainFocus() {
+	    super.updateUI();
+	}
+
+	public void loseFocus() {
+	}
+
+	/** The current detail mode controls two aspects of plugin manager: whether the movement buttons are visible and whether the fixed position plugins Arc and RecPlug are in the list
+	 * @param mode the current mode as an int, which can be matched against static ints in the Configuration class
+	 */
+	public void modeChanged(int mode) {
+	    // First of all we clear the current selection, as there can be some serious problems if the user selects the plugins we're hiding, or had the last plugin selected before we unhid the last three
+	    plugin_list.clearSelection();
+	    // The first change is dependant on whether the user is systems mode or higher
+	 
+	    plugin_combobox.setModel(new DefaultComboBoxModel(getAvailablePlugins()));
+	 
+	    if(mode >= Configuration.SYSTEMS_MODE) {
+		// Show movement buttons
+             
+		plugin_list_pane.add(movement_pane, BorderLayout.EAST);
+		// Do we show Arc and RecPlugs or hide them and the separator line
+		setHideLines(!(mode >= Configuration.EXPERT_MODE));
+	    }
+	    // Otherwise hide the movement buttons and fixed plugins
+	    else {
+		plugin_list_pane.remove(movement_pane);
+		setHideLines(true);
+	    }
+	    plugin_list_pane.updateUI();
+	}
+
+
+	private class AddListener
+	    implements ActionListener
+	{
+	    public void actionPerformed(ActionEvent event)
+	    {
+		if (plugin_combobox.getSelectedItem() != null) {
+		    // This must be done on a new thread for the remote building code
+		    new AddPluginTask(plugin_combobox.getSelectedItem().toString()).start();
+		}
+	    }
+	}
+
+
+	private class AddPluginTask
+	    extends Thread
+	{
+	    private String plugin_name;
+
+	    public AddPluginTask(String plugin_name)
+	    {
+		this.plugin_name = plugin_name;
+	    }
+
+	    public void run()
+	    {
+		// Retrieve the plugin
+		Plugin plugin = Plugins.getPlugin(plugin_name, true);
+		if (plugin == null) {
+		    System.err.println("Error: getPlugin() returned null.");
+		    return;
+		}
+
+		// Create a new element in the DOM
+		Element new_plugin_element = CollectionConfiguration.createElement(StaticStrings.PLUGIN_ELEMENT);
+		new_plugin_element.setAttribute(StaticStrings.TYPE_ATTRIBUTE, plugin.getName());
+		Plugin new_plugin = new Plugin(new_plugin_element, plugin);
+
+		ArgumentConfiguration ac = new ArgumentConfiguration(new_plugin);
+		ac.addOKButtonActionListener(CollectionDesignManager.all_change_listener);
+		if (ac.display()) {
+		    assignPlugin(new_plugin);
+		    plugin_list.setSelectedValue(new_plugin, true);
+
+		    // Remove the plugin from the available list (unless we're in a high mode, or it's UnknownPlug)
+		    if (Configuration.getMode() < Configuration.SYSTEMS_MODE && !plugin_name.equals(StaticStrings.UNKNOWNPLUG_STR)) {
+			plugin_combobox.removeItem(plugin);
+			plugin_combobox.setSelectedIndex(0);
+		    }
+		}
+	    }
+	}
+
+
+	/** Listens for double clicks apon the list and react as if the configure button was pushed. */
+	private class ClickListener
+	    extends MouseAdapter {
+	    /** Called whenever the mouse is clicked over a registered component, we use this to chain through to the configure prompt.
+	     * @param event A <strong>MouseEvent</strong> containing information about the mouse click.
+	    */
+	    public void mouseClicked(MouseEvent event) {
+		if(event.getClickCount() == 2 ) {
+		    if(!plugin_list.isSelectionEmpty()) {
+			Plugin plugin = (Plugin) plugin_list.getSelectedValue();
+			if(!plugin.isSeparator()) {
+			    ArgumentConfiguration ac = new ArgumentConfiguration(plugin);
+			    ac.addOKButtonActionListener(CollectionDesignManager.all_change_listener);
+			    if (ac.display()) {
+				refresh(plugin);
+			    }
+			    ac.destroy();
+			    ac = null;
+			}
+		    }
+		}
+	    }
+	}
+
+	/** This class listens for actions upon the configure button in the controls, and if detected creates a new <strong>ArgumentConfiguration</strong> dialog box to allow for configuration.
+	 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration
+	 */
+	private class ConfigureListener
+	    implements ActionListener {
+	    /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls.
+	     * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
+	     */
+	    public void actionPerformed(ActionEvent event) {
+		if(!plugin_list.isSelectionEmpty()) {
+		    Plugin plugin = (Plugin) plugin_list.getSelectedValue();
+		    if(!plugin.isSeparator()) {
+			ArgumentConfiguration ac = new ArgumentConfiguration(plugin);
+			ac.addOKButtonActionListener(CollectionDesignManager.all_change_listener);
+			if (ac.display()) {
+			    refresh(plugin);
+			}
+			ac.destroy();
+			ac = null;
+		    }
+		}
+	    }
+	}
+
+	/** listens for changes in the list selection and enables the configure and remove buttons if there is a selection, disables them if there is no selection */
+	private class ListListener
+	    implements ListSelectionListener {
+
+	    public void valueChanged(ListSelectionEvent e) {
+		if (!e.getValueIsAdjusting()) { // we get two events for one change in list selection - use the false one (the second one)
+		    if (plugin_list.isSelectionEmpty()) {
+			move_up_button.setEnabled(false);
+			move_down_button.setEnabled(false);
+			configure.setEnabled(false);
+			remove.setEnabled(false);
+		    }
+		    else {
+			Plugin selected_plugin = (Plugin) plugin_list.getSelectedValue();
+			if(selected_plugin.isSeparator()) {
+			    move_up_button.setEnabled(false);
+			    move_down_button.setEnabled(false);
+			    configure.setEnabled(false);
+			    remove.setEnabled(false);
+			}
+			else {
+			    configure.setEnabled(true);
+			    String plugin_name = selected_plugin.getName();
+			    // Some buttons are only available for plugins other than ArcPlug and RecPlug 
+			    if(plugin_name.equals(StaticStrings.ARCPLUG_STR) || plugin_name.equals(StaticStrings.RECPLUG_STR) ) {
+				move_up_button.setEnabled(false);
+				move_down_button.setEnabled(false);
+				remove.setEnabled(false);
+			    }
+			    else if (plugin_name.equals(StaticStrings.METADATAXMLPLUG_STR)) {
+				remove.setEnabled(false);
+			    }
+				
+			    else {
+				// don't let people remove special plugins such GAPlug an METSPlug,
+				// unless they are in systems mode or above
+				int mode = Configuration.getMode();
+				for (int i=0; i<StaticStrings.KEEP_PLUG.length; i++) {
+				    if ((plugin_name.equals(StaticStrings.KEEP_PLUG[i])) &&
+					(mode < Configuration.SYSTEMS_MODE)) {
+					remove.setEnabled(false); 
+					break;
+				    } else {
+					remove.setEnabled(true);
+				    }
+				}
+				    
+				// Move ups are only enabled if the selected plugin isn't already at the top 
+				Plugin first_plugin = (Plugin) getElementAt(0);
+				if(!first_plugin.equals(selected_plugin)) {
+				    move_up_button.setEnabled(true);
+				}
+				else {
+				    move_up_button.setEnabled(false);
+				}
+				// And move downs are only allowed when the selected plugin isn't at an index one less than the separator line.
+				int separator_index = findSeparatorIndex();
+				int selected_index = plugin_list.getSelectedIndex();
+				if(selected_index < separator_index - 1) {
+				    move_down_button.setEnabled(true);
+				}
+				else {
+				    move_down_button.setEnabled(false);
+				}
+			    }
+			    selected_plugin = null;
+			    plugin_name = null;
+			}
+		    }
+		}
+	    }
+	}
+
+	/** A special list renderer which is able to render separating lines as well. */
+	private class ListRenderer
+	    extends DefaultListCellRenderer {
+	    /** Return a component that has been configured to display the specified value. That component's paint method is then called to "render" the cell. If it is necessary to compute the dimensions of a list because the list cells do not have a fixed size, this method is called to generate a component on which getPreferredSize  can be invoked.
+	     * @param list - The <strong>JList</strong> we're painting.
+	     * @param value - The value returned by list.getModel().getElementAt(index) as an <strong>Object</strong>.
+	     * @param index - The cells index as an <i>int</i>.
+	     * @param isSelected - <i>true</i> if the specified cell was selected.
+	     * @param cellHasFocus - <i>true</i> if the specified cell has the focus.
+	     * @return A <strong>Component</strong> whose paint() method will render the specified value.
+	     * @see javax.swing.JList
+	     * @see javax.swing.JSeparator
+	     * @see javax.swing.ListModel
+	     * @see javax.swing.ListSelectionModel
+	     */
+	    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+		Plugin plugin = (Plugin) value;
+		if(plugin.isSeparator()) {
+		    return separator;
+		}
+		else {
+		    return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+		}
+	    }
+	}
+
+
+	/** Listens for actions apon the move buttons in the manager controls, and if detected calls the <i>movePlugin()</i> method of the manager with the appropriate details. */
+	private class MoveListener
+	    implements ActionListener {
+	    /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls.
+	     * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
+	     */
+	    public void actionPerformed(ActionEvent event) {
+		if (!plugin_list.isSelectionEmpty()) {
+		    Object object = plugin_list.getSelectedValue();
+		    if (object instanceof Plugin) {
+			Plugin plugin = (Plugin) object;
+			if (event.getSource() == move_up_button) {
+			    movePlugin(plugin, true, false);
+			}
+			else if (event.getSource() == move_down_button) {
+			    movePlugin(plugin, false, false);
+			}
+			plugin_list.setSelectedValue(plugin, true);
+		    }
+		}
+	    }
+	}
+
+	/** This listener reacts to changes in the current selection of the plugin combobox. */
+	private class PluginComboboxListener
+        implements ItemListener {
+        /** When a user selects a certain plugin, update the tooltip to show the plugin description. */
+        public void itemStateChanged(ItemEvent event) {
+            if(event.getStateChange() == ItemEvent.SELECTED) {
+                // Retrieve the selected plugin
+                Object current_selection = plugin_combobox.getSelectedItem();
+                // And reset the tooltip. If the plugin is null or is a string, then go back to the default message
+                if(current_selection == null || current_selection instanceof String) {
+		    plugin_combobox.setToolTipText(Dictionary.get("CDM.PlugInManager.PlugIn_Tooltip"));
+                }
+                else {
+                    Plugin current_plugin = (Plugin) current_selection;
+		    plugin_combobox.setToolTipText(Utility.formatHTMLWidth(current_plugin.getDescription(), 40));
+                    current_plugin = null;
+                }
+                current_selection = null;
+            }
+        }
+    }
+	
+	/** This class listens for actions upon the remove button in the controls, and if detected calls the <i>removePlugin()</i> method.
+	 */
+	private class RemoveListener
+	    implements ActionListener {
+	    /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls.
+	     * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
+	     */
+	    public void actionPerformed(ActionEvent event) {
+		int selected_index = plugin_list.getSelectedIndex();
+		if(selected_index != -1) {
+		    Plugin selected_plugin = (Plugin) plugin_list.getSelectedValue();
+		    removePlugin(selected_plugin);
+		    selected_plugin = null;
+		    // Select the next plugin if available
+		    if(selected_index < plugin_list.getModel().getSize()) {
+			// If the new selection is above the separator we can remove it
+			if(selected_index < findSeparatorIndex()) {
+			    plugin_list.setSelectedIndex(selected_index);
+			    
+			    // don't let people remove special plugins such GAPlug an METSPlug,
+			    // unless they are in systems mode or above
+			    int mode = Configuration.getMode();
+			    for (int i=0; i<StaticStrings.KEEP_PLUG.length; i++) {
+				String selected_plugin_name
+				    = ((Plugin)plugin_list.getSelectedValue()).getName();
+				if ((selected_plugin_name.equals(StaticStrings.KEEP_PLUG[i])) &&
+				    (mode < Configuration.SYSTEMS_MODE)) {
+				    remove.setEnabled(false); 
+				    break;
+				} else {
+				    remove.setEnabled(true);
+				}
+			    }					
+			}
+			// Otherwise select the first non-removable plugin
+			else {
+			    plugin_list.setSelectedIndex(selected_index + 1);
+			    remove.setEnabled(false);
+			}
+		    }
+		    else {
+			remove.setEnabled(false);
+		    }
+		    // Refresh the available plugins
+		    plugin_combobox.setModel(new DefaultComboBoxModel(getAvailablePlugins()));
+		}
+		else {
+		    remove.setEnabled(false);
+		}
+	    }
+	}
+    }
+    
+
+    private class PluginSuggestionPrompt
+	extends ModalDialog
+	implements ActionListener
+    {
+	private Dimension size = new Dimension(480, 240);
+	private GComboBox suitable_plugins_combobox = null;
+	private GLIButton add_button = null;
+	private GLIButton ignore_button = null;
+
+	public PluginSuggestionPrompt(String filename, ArrayList suitable_plugins)
+	{
+	    super(Gatherer.g_man, true);
+	    setModal(true);
+	    setSize(size);
+	    setTitle(Dictionary.get("CDM.PluginManager.SuggestedPluginListTitle"));
+
+	    String[] args = new String[1];
+	    args[0] = filename;
+
+	    JTextArea instructions_textarea = new JTextArea(Dictionary.get("CDM.PluginManager.Plugin_Suggestion_Prompt", args));
+	    instructions_textarea.setCaretPosition(0);
+	    instructions_textarea.setEditable(false);
+	    instructions_textarea.setLineWrap(true);
+	    instructions_textarea.setRows(5);
+	    instructions_textarea.setWrapStyleWord(true);
+
+	    JLabel suitable_plugins_label = new JLabel(Dictionary.get("CDM.PlugInManager.PlugIn"));
+	    suitable_plugins_label.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
+
+	    suitable_plugins_combobox = new GComboBox(suitable_plugins);
+	    suitable_plugins_combobox.setBackgroundNonSelectionColor(Configuration.getColor("coloring.editable_background", false));
+	    suitable_plugins_combobox.setBackgroundSelectionColor(Configuration.getColor("coloring.collection_selection_background", false));
+	    suitable_plugins_combobox.setTextNonSelectionColor(Configuration.getColor("coloring.workspace_tree_foreground", false));
+	    suitable_plugins_combobox.setTextSelectionColor(Configuration.getColor("coloring.collection_selection_foreground", false));
+
+	    JPanel suitable_plugins_pane = new JPanel();
+	    //suitable_plugins_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
+	    suitable_plugins_pane.setLayout(new BorderLayout(5,0));
+	    suitable_plugins_pane.add(suitable_plugins_label, BorderLayout.WEST);
+	    suitable_plugins_pane.add(suitable_plugins_combobox, BorderLayout.CENTER);
+
+	    add_button = new GLIButton(Dictionary.get("CDM.PlugInManager.QuickAdd"), Dictionary.get("CDM.PlugInManager.Add_Tooltip"));
+	    ignore_button = new GLIButton(Dictionary.get("CDM.PlugInManager.Ignore"), Dictionary.get("CDM.PlugInManager.Ignore_Tooltip"));
+	    
+	    add_button.addActionListener(this);
+	    ignore_button.addActionListener(this);
+
+	    JPanel button_pane = new JPanel();
+	    button_pane.setLayout(new GridLayout(1,2,5,0));
+	    button_pane.add(add_button);
+	    button_pane.add(ignore_button);
+
+	    JPanel controls_pane = new JPanel();
+	    controls_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	    controls_pane.setLayout(new GridLayout(2,1,0,5));
+	    controls_pane.add(suitable_plugins_pane);
+	    controls_pane.add(button_pane);
+
+	    JPanel content_pane = (JPanel) getContentPane();
+	    content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	    content_pane.setLayout(new BorderLayout());
+	    content_pane.add(instructions_textarea, BorderLayout.CENTER);
+	    content_pane.add(controls_pane, BorderLayout.SOUTH);
+
+	    // Show
+	    Dimension screen_size = Configuration.screen_size;
+	    setLocation((screen_size.width - size.width) / 2, (screen_size.height - size.height) / 2);
+	    setVisible(true);
+	}
+
+
+	public void actionPerformed(ActionEvent event)
+	{
+	    // Close the dialog
+	    setVisible(false);
+
+	    if (event.getSource() == add_button) {
+		AddPluginWithoutConfigurationTask add_plugin_task = new AddPluginWithoutConfigurationTask(suitable_plugins_combobox.getSelectedItem().toString());
+		add_plugin_task.start();
+
+		// We have to wait for this task to complete before continuing, otherwise
+		// we might offer to add the same plugin again before the task has completed
+		try {
+		    add_plugin_task.join();
+		}
+		catch (Exception exception) {
+		    DebugStream.printStackTrace(exception);
+		}
+	    }
+	}
+
+
+	private class AddPluginWithoutConfigurationTask
+	    extends Thread
+	{
+	    private String plugin_name;
+
+	    public AddPluginWithoutConfigurationTask(String plugin_name)
+	    {
+		this.plugin_name = plugin_name;
+	    }
+
+	    public void run()
+	    {
+		// Retrieve the plugin
+		Plugin plugin = Plugins.getPlugin(plugin_name, true);
+		if (plugin == null) {
+		    System.err.println("Error: getPlugin() returned null.");
+		    return;
+		}
+
+		// Create a new element in the DOM
+		Element new_plugin_element = CollectionConfiguration.createElement(StaticStrings.PLUGIN_ELEMENT);
+		new_plugin_element.setAttribute(StaticStrings.TYPE_ATTRIBUTE, plugin.getName());
+		Plugin new_plugin = new Plugin(new_plugin_element, plugin);
+
+		// Just assign the plugin with no argument configuration
+		assignPlugin(new_plugin);
+	    }
+	}
+    }
+
+
+    /** Creates a list separator.
+     * Found on Google Groups. Code courtesy of Paul Farwell.
+     */
+    private JPanel getSeparator() {
+	// We put the separator inside a panel to control its appearance
+	JPanel _sepPanel = new JPanel();
+	_sepPanel.setOpaque(false);
+	_sepPanel.setBorder(BorderFactory.createEmptyBorder(1, 3, 1, 3));
+	_sepPanel.setLayout(new BoxLayout(_sepPanel, BoxLayout.Y_AXIS));
+	_sepPanel.add(Box.createRigidArea(new Dimension(0, 4)));
+	// We have to be a little careful here, as the default UI for separators under MacOS is a blank box. Instead we force a BasicUI look
+	_sepPanel.add(new BasicSeparator());
+	_sepPanel.add(Box.createRigidArea(new Dimension(0, 4)));
+	return _sepPanel;
+    }
+
+    /** This class behaves just like a normal JSeparator except that, no matter what the current settings in the UIManager are, it always paints itself with BasicSeparatorUI. */
+    private static class BasicSeparator
+	extends JSeparator {
+
+	private ComponentUI basic_ui;
+
+	public BasicSeparator() {
+	    super();
+	    basic_ui = new BasicSeparatorUI();
+	}
+
+	public void paintComponent(Graphics g) {
+	    if (basic_ui != null) {
+		basic_ui.update(g, this);
+	    }   
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/SearchMetadataManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/SearchMetadataManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/SearchMetadataManager.java	(revision 13928)
@@ -0,0 +1,354 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.table.*;
+import java.util.ArrayList;
+
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.gui.DesignPaneHeader;
+import org.greenstone.gatherer.util.StaticStrings;
+
+
+public class SearchMetadataManager
+{
+    private Control controls;
+
+    public static final String TYPE_INDEX = "index";
+    public static final String TYPE_LEVEL = "level";
+    public static final String TYPE_PARTITION = "partition";
+    public static final String TYPE_LANGUAGE = "language";
+    
+    CollectionMetaManager collmeta_manager = CollectionDesignManager.collectionmeta_manager;
+
+    public SearchMetadataManager() {
+    }
+
+    /** Destructor. */
+    public void destroy() {
+	if (controls != null) {
+	    controls.destroy();
+	    controls = null;
+	}
+    }
+
+    public void loseFocus() {
+    }
+
+    public void gainFocus() {
+    }
+    
+    public Control getControls() {
+	if (controls == null) {
+	    controls = new DisplayControl();
+	}
+	return controls;
+    }
+    
+
+    /** Called when the detail mode has changed which in turn may cause several design elements to be available/hidden
+     * @param mode the new mode as an int
+     */
+    public void modeChanged(int mode) {
+    }
+
+    private class DisplayControl
+	extends JPanel
+	implements Control {
+
+	private SearchMetadataTable metadata_table = null;
+	
+	public DisplayControl() {
+	    super();
+
+	    JPanel header_panel = new DesignPaneHeader("CDM.GUI.SearchMetadata", "searchmetadatasettings");
+
+	    metadata_table = new SearchMetadataTable();
+
+	    JScrollPane scroll_panel = new JScrollPane(metadata_table);
+	    scroll_panel.getViewport().setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+	    scroll_panel.setOpaque(true);
+
+	    JPanel metadata_table_pane = new JPanel();
+	    metadata_table_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	    metadata_table_pane.setLayout(new BorderLayout());
+	    metadata_table_pane.add(scroll_panel, BorderLayout.CENTER);
+
+	    setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
+	    setLayout(new BorderLayout());
+	    add(header_panel, BorderLayout.NORTH);
+	    add(metadata_table_pane, BorderLayout.CENTER);
+	}
+
+	public void loseFocus(){
+	    // save the last metadata in case its still editing
+	    metadata_table.stopEditing();
+	}
+	
+	
+	public void gainFocus(){
+	    // refresh the model as we may have changed indexes in the meantime
+	    metadata_table.refreshModel();
+	}
+
+	public void destroy() {}
+    }
+    
+    private ArrayList getEntries() {
+	ArrayList entries = new ArrayList();
+	
+	ArrayList indexes = CollectionDesignManager.index_manager.getIndexes();
+	if (indexes != null) {
+	    int indexes_size = indexes.size();
+	    for (int i=0; i<indexes_size; i++) {
+		SearchMetadataEntry sme = new SearchMetadataEntry(((Index)indexes.get(i)).getID(), TYPE_INDEX);
+		entries.add(sme);
+	    }
+	}
+	
+	ArrayList levels = CollectionDesignManager.index_manager.getLevels();
+	if (levels != null) {
+	    int levels_size = levels.size();
+	    for (int i=0; i<levels_size; i++) {
+		SearchMetadataEntry sme = new SearchMetadataEntry(((IndexOption)levels.get(i)).getName(), TYPE_LEVEL);
+		entries.add(sme);
+	    }
+	}
+	
+	ArrayList partitions = CollectionDesignManager.subcollectionindex_manager.getSubcollectionIndexes();
+	if (partitions != null) {
+	    int partitions_size = partitions.size();
+	    for(int i=0; i<partitions_size; i++) {
+		SearchMetadataEntry sme = new SearchMetadataEntry(((SubcollectionIndex)partitions.get(i)).getID(), TYPE_PARTITION);
+		entries.add(sme);
+	    }
+	}
+	
+	ArrayList languages = CollectionDesignManager.language_manager.getLanguages();
+	if (languages != null) {
+	    int languages_size = languages.size();
+	    for (int i=0; i<languages_size; i++) {
+		SearchMetadataEntry sme = new SearchMetadataEntry(((Language)languages.get(i)).getCode(), TYPE_LANGUAGE);
+		entries.add(sme);
+	    }
+	}
+	return entries;
+    }
+    
+    
+    private class SearchMetadataEntry {
+		
+	String id;
+	String type;
+	CollectionMeta coll_meta = null;
+	String value;
+
+	public SearchMetadataEntry(String id, String type) {
+	    this.id = id;
+	    this.type = type;
+	    coll_meta = collmeta_manager.getMetadatum(getMetaID());
+	    value = coll_meta.getValue(false);
+	}
+	
+	public String toString() {
+	    return Dictionary.get("CDM.SearchMetadataManager.Type_"+type)+": "+id;
+	}
+	
+	public String getMetaID() {
+	    return StaticStrings.STOP_CHARACTER+id;
+	}
+	public String getValue() {
+	    return value;
+	}
+	public void setValue(String val) {
+	    coll_meta.setValue(val);
+	    value = val;
+	}
+    }
+
+    private class SearchMetadataTable
+	extends JTable {
+
+	private SearchMetadataTableModel model = null;
+	
+	public SearchMetadataTable() {
+	    // create the model
+	    model = new SearchMetadataTableModel();
+	    setModel(model);
+
+	    setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+
+	    // set our own cell renderer
+	    TableColumnModel column_model = getColumnModel();
+	    TableColumn name_column = column_model.getColumn(0);
+	    TableColumn value_column = column_model.getColumn(1);
+
+	    SearchMetadataTableCellRenderer cell_renderer = new SearchMetadataTableCellRenderer();
+	    name_column.setCellRenderer(cell_renderer);
+	    value_column.setCellRenderer(cell_renderer);
+	}
+	
+	public void refreshModel() {
+	    model.refresh();
+	}
+
+	public void stopEditing() {
+	    // Save the current value in the text field, then remove the editor so it doesn't get saved again
+	    TableCellEditor table_cell_editor = getCellEditor();
+	    if (table_cell_editor != null) {
+		table_cell_editor.stopCellEditing();
+	    }
+	}
+    }
+    
+    private class SearchMetadataTableModel
+	extends AbstractTableModel {
+	
+	// the list of items in the table
+	private ArrayList search_metadata_entries = null;
+	
+	final private String[] COLUMN_NAMES = {Dictionary.get("CDM.SearchMetadataManager.Component"), Dictionary.get("CDM.SearchMetadataManager.Component_Name")};
+	
+	public SearchMetadataTableModel() {
+	    refresh(); 
+	}
+	
+	/** Returns the number of columns in this table. */
+	public int getColumnCount() {
+	    
+	    return COLUMN_NAMES.length;
+	}
+	
+	/** Retrieves the name of the specified column. */
+	public String getColumnName(int col) {
+	    
+	    return COLUMN_NAMES[col];
+	}
+	
+	/** Returns the number of rows in this table. */
+	public int getRowCount() {
+	    
+	    return search_metadata_entries.size();
+	}
+	
+	/** Returns the cell value at a given row and column as an Object. */
+	public Object getValueAt(int row, int col) {
+	    // Check values are reasonable
+	    if (row < 0 || row >= search_metadata_entries.size() || col < 0 || col >= COLUMN_NAMES.length) {
+		return null;
+	    }
+	    
+	    SearchMetadataEntry sme = (SearchMetadataEntry) search_metadata_entries.get(row);
+	    if (col == 0) {
+		return sme.toString();
+	    }
+	    if (col == 1) {
+		return sme.getValue();
+	    }
+	    return null;
+	}
+	
+	public boolean isCellEditable(int row, int col) {
+	    if (col == 1) {
+		return true;
+	    }
+	    return false;
+	}
+
+	public void refresh() {
+	    search_metadata_entries = getEntries();
+	    
+	}
+	
+	public void setValueAt(Object new_value, int row, int col) {
+	    SearchMetadataEntry sme = (SearchMetadataEntry) search_metadata_entries.get(row);
+	    String old_value = sme.getValue();
+	    if (!new_value.equals(old_value)) {
+		sme.setValue((String)new_value);
+		
+	    }
+
+	}
+
+    }
+    private static class SearchMetadataTableCellRenderer
+	extends DefaultTableCellRenderer {
+
+	public void setValue(Object value) {
+	    
+	    setText((String)value);
+	}
+	/** Returns the default table cell renderer.
+	 * @param table The <strong>JTable</strong>.
+	 * @param value The value to assign to the cell at [row, column] as an <strong>Object</strong>.
+	 * @param isSelected <i>true</i> if cell is selected.
+	 * @param hasFocus <i>true</i> if cell has focus.
+	 * @param row The row of the cell to render as an <i>int</i>.
+	 * @param column The column of the cell to render as an <i>int</i>.
+	 * @return The default table cell renderer <strong>Component</strong>.
+	 */
+	public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
+	    JComponent component = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+
+	    // real_column is the column in the model, column is the column in the table - may be different if the user has moved the columns around
+	    int real_column =  table.convertColumnIndexToModel(column);
+	    if (real_column == 1 && isSelected) {
+		table.editCellAt(row, column);
+		if (table.isEditing()) {
+		    table.getEditorComponent().requestFocus();
+		}
+	    }
+	    
+	    // so we can see the background colour
+	    component.setOpaque(true);
+
+	    // Background
+	    if (isSelected) {
+		component.setBackground(Configuration.getColor("coloring.workspace_heading_background", true));
+	    }
+	    else {
+		if (real_column == 0) {
+		    component.setBackground(Configuration.getColor("coloring.collection_heading_background", true));
+		}
+		else {
+		    component.setBackground(Configuration.getColor("coloring.collection_tree_background", true));
+		}
+	    }
+	    
+	    // The value column of cells never paints focus
+	    if (real_column == 1) {
+		component.setBorder(BorderFactory.createEmptyBorder(0,2,0,0));
+	    }
+	 
+	    return component;
+	}
+
+    }
+    
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/Subcollection.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/Subcollection.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/Subcollection.java	(revision 13928)
@@ -0,0 +1,270 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.XMLTools;
+import org.w3c.dom.*;
+
+
+/** This class encapsulates one subcollection entry in the collection configuration file.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.4
+ */
+public class Subcollection
+    implements Comparable, DOMProxyListEntry {
+    /** A <i>boolean</i> which is <i>true</i> if the condition is an include one, <i>false</i> otherwise. */
+    private boolean include = true;
+    /** The DOM Element this Subcollection is based upon. */
+    private Element element = null;
+    /** A String containing a Perl expression which is used as the pattern by which to filter this subcollection. */
+    private String pattern = null;
+    /** A series of flags to be used when matching the expression. */
+    private String flags = null;
+    /** A String which is a unique identifier of a subcollection. */
+    private String name = null;
+    /** Either the fully qualified name of the metadata whose value should be matched against the given expression, or <i>null</i> if you wish to match against the file name. */
+    private String source = null;
+    private String text = null;
+
+    /** Default constructor which should only be used during DOMProxyListModel initialization. */
+    public Subcollection() {
+    }
+
+    /** Constructor for representing an existing assigned Subcollection.
+     * @param element the Element this subcollection is based upon
+     */
+    public Subcollection(Element element) {
+	this.element = element;
+    }
+
+    /** Constructor for assigning a brand new Subcollection.
+     * @param name a unique identifier for this collection as a String
+     * @param include true if this the pattern should be an inclusion filter, false for exclusion
+     * @param source either the fully qualified name of an element as a String, or null to filter filenames
+     * @param pattern the matching pattern as a String
+     * @param flags any flags to use while matching, as a String
+     */
+    public Subcollection(String name, boolean include, String source, String pattern, String flags) {
+	// Cache the details
+	this.flags = flags;
+	this.include = include;
+	this.name = name;
+	this.pattern = pattern;
+	if(source != null) {
+	    this.source = source;
+	}
+	else {
+	    this.source = StaticStrings.FILENAME_STR;
+	}
+	// Create a new DOM Element with the appropriate attributes and text value
+	element = CollectionConfiguration.createElement(StaticStrings.SUBCOLLECTION_ELEMENT);
+	element.setAttribute(StaticStrings.CONTENT_ATTRIBUTE, source);
+	element.setAttribute(StaticStrings.NAME_ATTRIBUTE, name);
+	element.setAttribute(StaticStrings.OPTIONS_ATTRIBUTE, flags);
+	element.setAttribute(StaticStrings.TYPE_ATTRIBUTE, (include ? StaticStrings.INCLUDE_STR : StaticStrings.EXCLUDE_STR));
+	XMLTools.setValue(element, pattern);
+    }
+
+    /** Method to compare two subcollections.
+     * @param object he other subcollection to compare to, as an Object
+     * @return an int which is &gt;0, 0, or &lt;0 if this subcollection is before, equal to, or after the target object respectively.
+     */
+    public int compareTo(Object object)
+    {
+	if (object == null) {
+	    return -1;
+	}
+
+	// Object may be a String
+	if (object instanceof String) {
+	    return getName().compareTo((String) object);
+	}
+
+	// Otherwise assume it is a Subcollection object
+	return getName().compareTo(((Subcollection) object).getName());
+    }
+
+
+    public DOMProxyListEntry create(Element element) {
+	return new Subcollection(element);
+    }
+
+    /** Method to check two subcollections for equality.
+     * @param object the other subcollection to compare to, as an Object
+     * @return true if the subcollections are equal, false otherwise.
+     */
+    public boolean equals(Object object) {
+	return (compareTo(object) == 0);
+    }
+
+    /** Retrieve the DOM Element this Subcollection is based upon.
+     * @return an Element
+     */
+    public Element getElement() {
+	return element;
+    }
+
+    /** Method to get the value of flags.
+     * @return the value of flags as a String
+     */
+    public String getFlags() {
+	if(flags == null && element != null) {
+	    flags = element.getAttribute(StaticStrings.OPTIONS_ATTRIBUTE);
+	}
+	return flags;
+    }
+
+    /** Method to get the value of name.
+     * @return String The value of name as a <strong>String</string>.
+     */
+    public String getName() {
+	if(name == null && element != null) {
+	    name = element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
+	}
+	return name;
+    }
+
+    public String getPattern() {
+	if(pattern == null && element != null) {
+	    pattern = XMLTools.getValue(element);
+	}
+	return pattern;
+    }
+
+    /** Method to get the name of the source of the strings used in pattern matching.
+     * @return a String which is either the fully qualified name of a metadata element, or filename
+     */
+    public String getSource()
+    {
+	if (source == null && element != null) {
+	    source = element.getAttribute(StaticStrings.CONTENT_ATTRIBUTE);
+	}
+
+	return source;
+    }
+
+    public boolean isAssigned() {
+	return (element != null && !element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.FALSE_STR));
+    }
+
+    /** Method to get the value of include.
+     * @return boolean true if this is an inclusion filter, false otherwise
+     */
+    public boolean isInclusive() {
+	if (element != null) {
+	    include = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE).equals(StaticStrings.INCLUDE_STR);
+	}
+
+	return include;
+    }
+
+    public void setAssigned(boolean assigned) {
+	if(element != null) {
+	    element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, (assigned ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
+	}
+    }
+
+    public void setElement(Element element) {
+	this.element = element;
+	include = true;
+	flags = null;
+	name = null;
+	pattern = null;
+	source = null;
+	text = null;
+    }
+
+    public void setFlags(String new_flags) {
+	if(element != null) {
+	    // Change element
+	    element.setAttribute(StaticStrings.OPTIONS_ATTRIBUTE, new_flags);
+	    flags = new_flags;
+	    text = null;
+	}
+    }
+
+    public void setInclusive(boolean new_include) {
+	if(element != null) {
+	    // Change element
+	    include = new_include;
+	    element.setAttribute(StaticStrings.TYPE_ATTRIBUTE, (include ? StaticStrings.INCLUDE_STR : StaticStrings.EXCLUDE_STR));
+	    text = null;
+	}
+    }
+
+    public void setName(String new_name) {
+	if(element != null) {
+	    // Change element
+	    element.setAttribute(StaticStrings.NAME_ATTRIBUTE, new_name);
+	    name = new_name;
+	    text = null;
+	}
+    }
+
+    public void setPattern(String new_pattern) {
+	if(element != null) {
+	    // Change element
+	    XMLTools.setValue(element, new_pattern);
+	    pattern = new_pattern;
+	    text = null;
+	}
+    }
+
+    public void setSource(String new_source) {
+	if(element != null) {
+	    // Change element
+	    element.setAttribute(StaticStrings.CONTENT_ATTRIBUTE, new_source);
+	    source = new_source;
+	    text = null;
+	}
+    }
+
+    /** Method to display the contents of this class as it would appear in the collection configuration file.
+     * @return a String representing this subcollection
+     */
+    public String toString() {
+	if(text == null) {// && element != null) {
+
+	    StringBuffer new_text = new StringBuffer(getName());
+	    new_text.append(StaticStrings.SPACE_CHARACTER);
+	    new_text.append(StaticStrings.SPEECH_CHARACTER);
+	    if (!isInclusive()) {
+		new_text.append(StaticStrings.EXCLAMATION_CHARACTER);
+	    }
+	    new_text.append(getSource());
+	    new_text.append(StaticStrings.SEPARATOR_CHARACTER);
+	    new_text.append(getPattern());
+	    new_text.append(StaticStrings.SEPARATOR_CHARACTER);
+	    new_text.append(getFlags());
+	    new_text.append(StaticStrings.SPEECH_CHARACTER);
+	    text =  new_text.toString();
+	}
+	
+	return text;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/SubcollectionIndex.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/SubcollectionIndex.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/SubcollectionIndex.java	(revision 13928)
@@ -0,0 +1,175 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import java.util.*;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.XMLTools;
+import org.w3c.dom.*;
+
+/** This class encapsulates a single indexing pair.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.4
+ */
+public class SubcollectionIndex
+    implements Comparable, DOMProxyListEntry {
+
+    private ArrayList sources = null;
+    /** The element this index is based upon. */
+    private Element element = null;
+    /** The unique, if cryptic, identifier of an index. */
+    private String id = null;
+
+    /** Default constructor, which should only be used during DOMProxyListModel creation. */
+    public SubcollectionIndex() {
+    }
+
+    /** Constructor. */
+    public SubcollectionIndex(Element element) {
+	this.element = element;
+    }
+
+    public SubcollectionIndex(Object[] raw_sources) {
+	this.sources = new ArrayList();
+	// Create a new element
+	element = CollectionConfiguration.createElement(StaticStrings.INDEX_ELEMENT);
+	// For each source add a content element
+	int size = raw_sources.length;
+	for(int i = 0; i < size; i++) {
+	    Subcollection subcollection = (Subcollection) raw_sources[i];
+	    String subcollection_name = subcollection.getName();
+	    sources.add(subcollection_name);
+	    Element content_element = CollectionConfiguration.createElement(StaticStrings.CONTENT_ELEMENT);
+	    content_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, subcollection_name);
+	    element.appendChild(content_element);
+	    content_element = null;
+	}
+    }
+
+    /** Method to compare two indexes.
+     * @param object The other index as an <strong>Object</strong>.
+     * @return An <i>int</i> which indicates how the indexes compare.
+     * @see java.lang.String
+     */
+    public int compareTo(Object object) {
+	return getID().compareTo(((SubcollectionIndex)object).getID());
+    }
+    
+    public DOMProxyListEntry create(Element element) {
+	return new SubcollectionIndex(element);
+    }
+
+    /** Method to test for the equality of two indexes.
+     * @param object The other index as an <strong>Object</strong>.
+     * @return A <i>boolean</i> which is <i>true</i> if the two indexes are equal, <i>false</i> otherwise.
+     */
+    public boolean equals(Object object) {
+	return (compareTo(object) == 0);
+    }
+    
+    public Element getElement() {
+	return element;
+    }
+
+    public String getID() {
+	if(id == null) {
+	    StringBuffer id_buffer = new StringBuffer();
+	    // Write data information. Retrieve each of the content sources and add them in a comma separated list.
+	    ArrayList sources = getSources();
+	    int sources_size = sources.size();
+	    for(int i = 0; i < sources_size; i++) {
+		id_buffer.append((String)sources.get(i));
+		id_buffer.append(StaticStrings.COMMA_CHARACTER);
+	    }
+	    sources = null;
+	    id = id_buffer.substring(0, id_buffer.length() - 1);
+	}
+	return id;
+    }
+
+    /** Retrieve the sources of this index.
+     * @return the sources as an ArrayList
+     */
+    public ArrayList getSources() {
+	if(sources == null) {
+	    sources = new ArrayList();
+	    NodeList content_elements = element.getElementsByTagName(StaticStrings.CONTENT_ELEMENT);
+	    int content_elements_length = content_elements.getLength();
+	    for(int i = 0; i < content_elements_length; i++) {
+		Element content_element = (Element) content_elements.item(i);
+		sources.add(content_element.getAttribute(StaticStrings.NAME_ATTRIBUTE));
+	    }
+	    content_elements = null;
+	    Collections.sort(sources);
+	}
+	return sources;
+    }
+
+    public boolean isAssigned() {
+	return (element != null && !element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.FALSE_STR));
+    }
+
+    public void setAssigned(boolean assigned) {
+	if(element != null) {
+	    element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, (assigned ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
+	}
+    }
+
+    public void setElement(Element element) {
+	this.element = element;
+	this.id = null;
+	this.sources = null;
+    }
+
+    /** Method to set the sources for this index which can only be used for the default index.
+     * @param sources an ArrayList of source names
+     */
+    public void setSources(ArrayList sources) {
+	if(element != null) {
+	    // Erase old sources
+	    XMLTools.clear(element);
+	    // For each entry in the sources array add a new content element.
+	    int size = sources.size();
+	    for(int i = 0; i < size; i++) {
+		Element content_element = element.getOwnerDocument().createElement(StaticStrings.CONTENT_ELEMENT);
+		content_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, (String) sources.get(i));
+		element.appendChild(content_element);
+		content_element = null;
+	    }
+	    this.id = null; // Regenerate ID.
+	    this.sources = sources;
+	}
+    }
+
+    /** Method to turn this object into a string representation ready to be placed in the collection configuration file.
+     * @return A <strong>String</strong> containing the information of this class.
+     */
+
+    public String toString() {
+	return getID();
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/SubcollectionIndexManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/SubcollectionIndexManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/SubcollectionIndexManager.java	(revision 13928)
@@ -0,0 +1,599 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.gui.GLIButton;
+import org.greenstone.gatherer.util.CheckList;
+import org.greenstone.gatherer.util.JarTools;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.w3c.dom.*;
+
+
+/** This class maintains a list of indexes partitions for the purpose of defining subcollections.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.4
+ */
+public class SubcollectionIndexManager
+    extends DOMProxyListModel
+{
+    static final private Dimension FIELD_SIZE = new Dimension(200, 30);
+
+    private Control controls;
+    private DOMProxyListModel model;
+    private SubcollectionIndex default_index;
+
+
+    /** Constructor. */
+    public SubcollectionIndexManager(Element subindexes)
+    {
+	super(subindexes, StaticStrings.INDEX_ELEMENT, new SubcollectionIndex());
+	DebugStream.println("SubcollectionIndexManager: " + getSize() + " subcollection indexes parsed.");
+	this.model = this;
+
+	// Parse and retrieve the default index
+	NodeList default_index_elements = CollectionConfiguration.getElementsByTagName(StaticStrings.SUBCOLLECTION_DEFAULT_INDEX_ELEMENT);
+	if (default_index_elements.getLength() > 0) {
+	    default_index = new SubcollectionIndex((Element) default_index_elements.item(0));
+	}
+    }
+
+
+    /** Method to add a subindex.
+     * @param subindex a SubcollectionIndex
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.collection.CollectionManager
+     */
+    private void addSubcollectionIndex(SubcollectionIndex subcollection_index)
+    {
+	if (!contains(subcollection_index)) {
+	    // add a pseudo metadata
+	    CollectionMeta metadatum = new CollectionMeta(StaticStrings.STOP_CHARACTER + subcollection_index.getID());
+	    metadatum.setValue(subcollection_index.getID());
+	    CollectionDesignManager.collectionmeta_manager.addMetadatum(metadatum);
+	    add(getSize(), subcollection_index);
+	}
+    }
+
+
+    public void destroy()
+    {
+	if (controls != null) {
+	    controls.destroy();
+	    controls = null;
+	}
+	default_index = null;
+	model = null;
+    }
+
+
+    public Control getControls()
+    {
+	if (controls == null) {
+	    controls = new SubcollectionIndexControls();
+	}
+	return controls;
+    }
+
+
+    /** Method to get all of the subindexes set.
+     * @return an ArrayList containing all the defined indexes
+     */
+    public ArrayList getSubcollectionIndexes()
+    {
+	return children();
+    }
+
+    /** Called when the detail mode has changed which in turn may cause several design elements to be available/hidden
+     * @param mode the new mode as an int
+     */
+    public void modeChanged(int mode) {
+	
+    }
+
+    private int moveSubcollectionIndex(SubcollectionIndex subcollection_index, boolean move_up)
+    {
+	// Determine the current position of the subcollection index
+	int position = indexOf(subcollection_index);
+	int new_position;
+
+	// Attempt to move the subcollection index up
+	if (move_up) {
+	    // Check it's not already at the top
+	    if (position == 0) {
+		return position;
+	    }
+
+	    // This automatically removes the index first, as an Element can only exist once in a particular document
+	    new_position = position - 1;
+	    addBefore(subcollection_index, (SubcollectionIndex) getElementAt(new_position));
+	}
+
+	// Attempt to move the subcollection index down
+	else {
+	    // Check it's not already at the bottom
+	    if (position == (getSize()) - 1) {
+		return position;
+	    }
+
+	    // This automatically removes the index first, as an Element can only exist once in a particular document
+	    new_position = position + 1;
+	    addAfter(subcollection_index, (SubcollectionIndex) getElementAt(new_position));
+	}
+
+	return new_position;
+    }
+
+
+    /** Method to remove a certain subcollection index. */
+    private void removeSubcollectionIndex(SubcollectionIndex subcollection_index)
+    {
+	if (subcollection_index != null) {
+	    // Remove any current metadata from this index
+	    CollectionDesignManager.collectionmeta_manager.removeMetadata(StaticStrings.STOP_CHARACTER + subcollection_index.getID());
+
+	    // Check if the index removed happens to be the default index
+	    if (default_index != null && default_index.equals(subcollection_index)) {
+		setDefault(null);
+	    }
+	    
+	    // Remove the index
+	    remove(subcollection_index);
+	}
+    }
+
+
+    /** Method to remove all of the subindexes that contain a certain subcollection.
+     * @param subcollection the Subcollection that has been removed
+     * @see org.greenstone.gatherer.cdm.Subcollection
+     * @see org.greenstone.gatherer.cdm.SubcollectionIndex
+     */
+    public void removeSubcollectionIndexes(Subcollection subcollection)
+    {
+	String subcollection_name = subcollection.getName();
+	int size = getSize();
+	for(int i = size - 1; i >= 0; i--) {
+	    SubcollectionIndex subcollection_index = (SubcollectionIndex) getElementAt(i);
+	    if (subcollection_index.getSources().contains(subcollection_name)) {
+		removeSubcollectionIndex(subcollection_index);
+	    }
+	}
+    }
+
+    private void replaceSubcollectionIndex(SubcollectionIndex old_subcollection, SubcollectionIndex new_subcollection) {
+	// Remove old collection meta
+	CollectionDesignManager.collectionmeta_manager.removeMetadata(StaticStrings.STOP_CHARACTER + old_subcollection.getID());
+	// Add new one
+	CollectionMeta metadatum = new CollectionMeta(StaticStrings.STOP_CHARACTER + new_subcollection.getID());
+	metadatum.setValue(new_subcollection.getID());
+	CollectionDesignManager.collectionmeta_manager.addMetadatum(metadatum);
+	if(default_index != null && default_index.equals(old_subcollection)) {
+	    setDefault(new_subcollection);
+	}
+
+	// get the position of the old one
+	int position = indexOf(old_subcollection);
+	remove(old_subcollection);
+	add(position, new_subcollection);
+    }
+
+    /** Method to set the default subcollection index.
+     * @param index The <strong>SubcollectionIndex</strong> to use as the default index.
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.collection.CollectionManager
+     * @see org.greenstone.gatherer.cdm.SubcollectionIndex
+     */
+    private void setDefault(SubcollectionIndex subcollection_index)
+    {
+ 	if (subcollection_index != null) {
+ 	    if (default_index == null) {
+		// Create the default index element, and place immediately after indexes element.
+		Element default_index_element = root.getOwnerDocument().createElement(StaticStrings.SUBCOLLECTION_DEFAULT_INDEX_ELEMENT);
+		default_index = new SubcollectionIndex(default_index_element);
+		Node target_node = CollectionConfiguration.findInsertionPoint(default_index_element);
+		if (target_node != null) {
+		    root.getOwnerDocument().getDocumentElement().insertBefore(default_index_element, target_node);
+		}
+		else {
+		    root.getOwnerDocument().getDocumentElement().appendChild(default_index_element);
+		}
+ 	    }
+ 	    default_index.setAssigned(true);
+ 	    default_index.setSources(subcollection_index.getSources());
+ 	}
+ 	else {
+ 	    if (default_index != null) {
+ 		default_index.setAssigned(false);
+ 	    }
+ 	}
+    }
+
+
+    /** This class creates a set of controls for editing the indexes. */
+    private class SubcollectionIndexControls
+	extends JPanel
+	implements Control
+    {
+	private CheckList source_list;
+	private JButton add_button;
+	private JButton move_down_button;
+	private JButton move_up_button;
+	private JButton remove_button;
+	private JButton replace_button;
+	private JButton set_default_button;
+	private JList subcollection_index_list;
+	private JTextField subcollection_index_name_textfield;
+
+
+	/** Constructor.
+	 */
+	public SubcollectionIndexControls()
+	{
+	    super();
+
+	    ArrayList sources = new ArrayList();
+	    ListModel source_model = CollectionDesignManager.subcollection_manager;
+	    for (int i = 0; i < source_model.getSize(); i++) {
+		sources.add(source_model.getElementAt(i));
+	    }
+
+	    // Creation
+	    JPanel assigned_indexes_pane = new JPanel();
+	    JLabel index_label = new JLabel(Dictionary.get("CDM.SubcollectionIndexManager.Subindexes"));
+	    subcollection_index_list = new JList(model);
+	    subcollection_index_list.setCellRenderer(new SubcollectionIndexListCellRenderer());
+ 	    subcollection_index_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+	    subcollection_index_list.setVisibleRowCount(2);
+
+	    JPanel movement_pane = new JPanel();
+	    move_up_button = new GLIButton(Dictionary.get("CDM.Move.Move_Up"), JarTools.getImage("arrow-up.gif"), Dictionary.get("CDM.Move.Move_Up_Tooltip"));
+	    move_up_button.setEnabled(false);
+	    
+	    move_down_button = new GLIButton(Dictionary.get("CDM.Move.Move_Down"), JarTools.getImage("arrow-down.gif"), Dictionary.get("CDM.Move.Move_Down_Tooltip"));
+	    move_down_button.setEnabled(false);
+	    
+	    set_default_button = new GLIButton(Dictionary.get("CDM.SubcollectionIndexManager.Set_Default_Subindex"), Dictionary.get("CDM.SubcollectionIndexManager.Set_Default_Subindex_Tooltip"));
+	    set_default_button.setEnabled(false);
+	    
+	    JPanel index_pane = new JPanel();
+	    JPanel details_pane = new JPanel();
+	    JPanel labels_pane = new JPanel();
+	    JPanel boxes_pane = new JPanel();
+	    JPanel content_pane = new JPanel();
+
+	    JLabel source_label = new JLabel(Dictionary.get("CDM.SubcollectionIndexManager.Source"));
+	    
+	    source_list = new CheckList(false);
+	    source_list.setListData(sources);
+	    source_list.setToolTipText(Dictionary.get("CDM.SubcollectionIndexManager.Source_Tooltip"));
+	    
+	    JPanel button_pane = new JPanel();
+	    add_button = new GLIButton(Dictionary.get("CDM.SubcollectionIndexManager.Add_Subindex"), Dictionary.get("CDM.SubcollectionIndexManager.Add_Subindex_Tooltip"));
+	    add_button.setEnabled(false);
+	    
+	    remove_button = new GLIButton(Dictionary.get("CDM.SubcollectionIndexManager.Remove_Subindex"), Dictionary.get("CDM.SubcollectionIndexManager.Remove_Subindex_Tooltip"));
+	    remove_button.setEnabled(false);
+	   
+	    replace_button = new GLIButton(Dictionary.get("CDM.SubcollectionIndexManager.Replace_Subindex"), Dictionary.get("CDM.SubcollectionIndexManager.Replace_Subindex_Tooltip"));
+	    replace_button.setEnabled(false);
+	    
+	    // Listeners
+	    add_button.addActionListener(new AddListener());
+	    add_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
+	    move_down_button.addActionListener(new MoveListener(false));
+	    move_down_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
+	    move_up_button.addActionListener(new MoveListener(true));
+	    move_up_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
+	    remove_button.addActionListener(new RemoveListener());
+	    remove_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
+	    replace_button.addActionListener(new ReplaceListener());
+	    replace_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
+	    set_default_button.addActionListener(new SetDefaultListener());
+	    set_default_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
+	    subcollection_index_list.addListSelectionListener(new AssignedListListener());
+	    source_list.addListSelectionListener(new SourceListListener());
+
+	    // Layout
+	    movement_pane.setBorder(BorderFactory.createEmptyBorder(0,2,0,0));
+	    movement_pane.setLayout(new GridLayout(3,1));
+	    movement_pane.add(move_up_button);
+	    movement_pane.add(move_down_button);
+	    movement_pane.add(set_default_button);
+
+	    assigned_indexes_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
+	    assigned_indexes_pane.setLayout(new BorderLayout());
+	    assigned_indexes_pane.add(index_label, BorderLayout.NORTH);
+	    assigned_indexes_pane.add(new JScrollPane(subcollection_index_list), BorderLayout.CENTER);
+	    assigned_indexes_pane.add(movement_pane, BorderLayout.EAST);
+
+	    labels_pane.setLayout(new BorderLayout());
+	    labels_pane.setBorder(BorderFactory.createEmptyBorder(5, 5, 10, 5));
+	    labels_pane.add(source_label, BorderLayout.CENTER);
+	    
+	    boxes_pane.setLayout(new BorderLayout());
+	    boxes_pane.add(new JScrollPane(source_list), BorderLayout.CENTER);
+	    
+	    details_pane.setLayout(new BorderLayout());
+	    details_pane.add(labels_pane, BorderLayout.WEST);
+	    details_pane.add(boxes_pane, BorderLayout.CENTER);
+
+	    button_pane.setLayout(new GridLayout(1,3));
+	    button_pane.add(add_button);
+	    button_pane.add(replace_button);
+	    button_pane.add(remove_button);
+
+	    index_pane.setLayout(new BorderLayout());
+	    index_pane.add(details_pane, BorderLayout.CENTER);
+	    index_pane.add(button_pane, BorderLayout.SOUTH);
+
+	    content_pane.setLayout(new BorderLayout());
+	    content_pane.add(assigned_indexes_pane, BorderLayout.NORTH);
+	    content_pane.add(index_pane, BorderLayout.CENTER);
+
+	    setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	    setLayout(new BorderLayout());
+	    add(content_pane, BorderLayout.CENTER);
+	}
+
+
+	public void destroy()
+	{
+	}
+
+
+	public void gainFocus()
+	{
+ 	    // Reload the source list
+ 	    ArrayList sources = new ArrayList();
+ 	    ListModel source_model = CollectionDesignManager.subcollection_manager;
+ 	    for (int i = 0; i < source_model.getSize(); i++) {
+ 		sources.add(source_model.getElementAt(i));
+ 	    }
+ 	    source_list.setListData(sources);
+
+ 	    // Refresh the subcollection index list
+ 	    subcollection_index_list.updateUI();
+
+ 	    clearControls();
+ 	    
+	}
+
+
+	public void loseFocus() {
+	}
+
+	private void clearControls() {
+	    subcollection_index_list.clearSelection();
+	    source_list.clearTicked();
+	    add_button.setEnabled(false);
+	    remove_button.setEnabled(false);
+	    replace_button.setEnabled(false);
+	    set_default_button.setEnabled(false);
+	    move_down_button.setEnabled(false);
+	    move_up_button.setEnabled(false);
+
+	}
+
+	private void updateControlsWithSelectedIndex()
+	{
+	    SubcollectionIndex selected_index = (SubcollectionIndex) subcollection_index_list.getSelectedValue();
+	    if (selected_index == null) {
+		source_list.clearTicked();
+		return;
+	    }
+
+	    // Display the selected subcollection index's sources
+	    source_list.clearTicked();
+	    source_list.setTickedObjects(selected_index.getSources().toArray());
+	}
+
+
+	private void validateButtons() {
+	    
+	    boolean add_enabled = false;
+	    boolean replace_enabled = false;
+
+	    // Can't add a new index if no sources are selected
+	    if (!source_list.isNothingTicked()) {
+		ArrayList sources = source_list.getTicked();
+ 		SubcollectionIndex subcollection_index = new SubcollectionIndex(sources.toArray());
+
+		// Subcollection index already exists: can't add, but can replace if the name has changed
+ 		if (!model.contains(subcollection_index)) {
+ 		    add_enabled = true;
+ 		    if (!subcollection_index_list.isSelectionEmpty()) {
+ 			replace_enabled = true;
+ 		    }
+ 		}
+	    }
+
+	    // We should now know the add_button state
+	    add_button.setEnabled(add_enabled);
+	    replace_button.setEnabled(replace_enabled);
+	}
+
+
+	private class AddListener
+	    implements ActionListener {
+	    
+	    public void actionPerformed(ActionEvent event)
+	    {
+		if (!source_list.isNothingTicked()) {
+		    ArrayList sources = source_list.getTicked();
+		    SubcollectionIndex subcollection_index = new SubcollectionIndex(sources.toArray());
+		    addSubcollectionIndex(subcollection_index);
+		    clearControls();
+		}
+	    }
+	}
+
+
+	private class MoveListener
+	    implements ActionListener
+	{
+	    private boolean move_up;
+
+	    public MoveListener(boolean move_up)
+	    {
+		this.move_up = move_up;
+	    }
+
+	    public void actionPerformed(ActionEvent event)
+	    {
+		// Retrieve the selected subcollection index
+		SubcollectionIndex subcollection_index = (SubcollectionIndex) subcollection_index_list.getSelectedValue();
+		if (subcollection_index != null) {
+		    int new_position = moveSubcollectionIndex(subcollection_index, move_up);
+		    // Ensure the subcollection index that moved is still selected
+		    subcollection_index_list.setSelectedIndex(new_position);
+		}
+	    }
+	}
+
+	private class RemoveListener
+	    implements ActionListener
+	{
+	    public void actionPerformed(ActionEvent event) {
+		
+		SubcollectionIndex delete_me = (SubcollectionIndex) subcollection_index_list.getSelectedValue();
+		if (delete_me != null) {
+		    removeSubcollectionIndex(delete_me);
+		}
+	    }
+	}
+
+
+	private class ReplaceListener
+	    implements ActionListener {
+	    
+	    public void actionPerformed(ActionEvent event) {
+	    
+		if (subcollection_index_list.isSelectionEmpty()|| source_list.isNothingTicked()) {
+		    // This should never happen, but just in case...
+		    replace_button.setEnabled(false);
+		    return;
+		}
+		SubcollectionIndex old_index = (SubcollectionIndex) subcollection_index_list.getSelectedValue();
+		ArrayList sources = source_list.getTicked();
+ 		SubcollectionIndex new_index = new SubcollectionIndex(sources.toArray());
+		replaceSubcollectionIndex(old_index, new_index);
+	    }
+	}
+
+
+	private class SetDefaultListener
+	    implements ActionListener {
+	    
+	    public void actionPerformed(ActionEvent event)
+	    {
+		SubcollectionIndex subcollection_index = (SubcollectionIndex) subcollection_index_list.getSelectedValue();
+		if (subcollection_index != null) {
+		    setDefault(subcollection_index);
+		    // This should cause a repaint of just the desired row
+		    subcollection_index_list.setSelectedValue(subcollection_index, true);
+		}
+		set_default_button.setEnabled(false);
+	    }
+	}
+
+
+	private class SourceListListener
+	    implements ListSelectionListener {
+	
+	    public void valueChanged(ListSelectionEvent event) {
+		if (event.getValueIsAdjusting()) {
+		    return;
+		}
+		validateButtons();
+	    }
+	}
+
+
+	/** Listens for selections within the assigned subcollection indexes list  */
+	private class AssignedListListener
+	    implements ListSelectionListener {
+	    
+	    public void valueChanged(ListSelectionEvent event) {
+		
+		if (event.getValueIsAdjusting()) {
+		    return;
+		}
+
+		if (subcollection_index_list.isSelectionEmpty()) {
+		    clearControls();
+		    return;
+		}
+		
+ 		int i = subcollection_index_list.getSelectedIndex();
+ 		int size = subcollection_index_list.getModel().getSize();
+		
+ 		// Enable the buttons appropriately
+ 		remove_button.setEnabled(true);
+		replace_button.setEnabled(false);
+		add_button.setEnabled(false);
+ 		SubcollectionIndex selected_index = (SubcollectionIndex) subcollection_index_list.getSelectedValue();
+ 		set_default_button.setEnabled(default_index == null || !default_index.equals(selected_index));
+ 		if (i > 0) {
+ 		    move_up_button.setEnabled(true);
+ 		}
+ 		else {
+ 		    move_up_button.setEnabled(false);
+ 		}
+ 		if (i < size-1){
+ 		    move_down_button.setEnabled(true);
+ 		}
+ 		else {
+ 		    move_down_button.setEnabled(false);
+ 		}
+
+ 		// Need to fill in the rest of the bits
+		updateControlsWithSelectedIndex();
+	    }
+	}
+
+
+	private class SubcollectionIndexListCellRenderer
+	    extends DefaultListCellRenderer
+	{
+	    /** Return a component that has been configured to display the specified value. */
+	    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+		JLabel component = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+		if (default_index != null && default_index.equals(value)) {
+		    component.setText(component.getText() + " " + Dictionary.get("CDM.SubcollectionIndexManager.Default_Partition_Indicator"));
+		}
+		return component;
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/SubcollectionManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/SubcollectionManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/SubcollectionManager.java	(revision 13928)
@@ -0,0 +1,547 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.gui.DesignPaneHeader;
+import org.greenstone.gatherer.gui.GLIButton;
+import org.greenstone.gatherer.gui.NonWhitespaceField;
+import org.greenstone.gatherer.metadata.MetadataElement;
+import org.greenstone.gatherer.metadata.MetadataSetManager;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.w3c.dom.*;
+
+/** This class maintains a list of subcollections within our collection.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.4
+ */
+public class SubcollectionManager
+    extends DOMProxyListModel {
+
+    static final private String DISABLED_CONTROLS = "Disabled";
+    static final private String ENABLED_CONTROLS  = "Normal";
+    static final private String CLASS_DICTIONARY_NAME = "CDM.SubcollectionManager.";
+
+    /** The controls used to edit the settings of this manager. */
+    private Control controls = null;
+
+    private DOMProxyListModel model;
+
+    /** Constructor. 
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.cdm.CollectionConfiguration
+     * @see org.greenstone.gatherer.cdm.CollectionDesignManager
+     * @see org.greenstone.gatherer.cdm.DOMProxyListModel
+     * @see org.greenstone.gatherer.cdm.Subcollection
+     */
+    public SubcollectionManager() {
+	super(CollectionDesignManager.collect_config.getDocumentElement(), StaticStrings.SUBCOLLECTION_ELEMENT, new Subcollection());
+	DebugStream.println("SubcollectionManager: " + getSize() + " subcollections parsed.");
+	this.model = this;
+    }
+
+    /** Method to add a new subcollection.
+     * @param subcollection the Subcollection to add
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.cdm.CollectionConfiguration
+     * @see org.greenstone.gatherer.cdm.DOMProxyListModel
+     * @see org.greenstone.gatherer.collection.CollectionManager
+     */
+    private void addSubcollection(Subcollection subcollection) {
+	if(!contains(subcollection)) {
+	    Element element = subcollection.getElement();
+	    // Locate where we should insert this new subcollection. 
+	    Node target_node = CollectionConfiguration.findInsertionPoint(element);
+	    // Failing that we insert immediately after a language string
+	    add(root, subcollection, target_node);
+	}
+    }
+
+    public void destroy() {
+	if(controls != null) {
+	    controls.destroy();
+	    controls = null;
+	}
+    }
+
+    /** Method to retrieve the controls for this manager.
+     * @return the Control used to edit the subcollection data
+     */
+    public Control getControls() {
+	if(controls == null) {
+	    controls = new SubcollectionControl();
+	}
+	return controls;
+    }
+
+    /** Method to retrieve a certain subcollection by its name.
+     * @param name a String which is used as the key for finding the matching subcollection
+     * @return the requested Subcollection or null if no such subcollection exists.
+     */
+    private Subcollection getSubcollection(String name) {
+	Subcollection result = null;
+	int size = getSize();
+	for(int i = 0; i < size; i++) {
+	    Subcollection subcollection = (Subcollection) getElementAt(i);
+	    if(subcollection.getName().equals(name)) {
+		result = subcollection;
+	    }
+	}
+	return result;
+    }
+
+
+    /** Called when the detail mode has changed which in turn may cause several design elements to be available/hidden
+     * @param mode the new mode as an int
+     */
+    public void modeChanged(int mode) {
+	if(controls != null) {
+	    ((SubcollectionControl)controls).modeChanged(mode);
+	}
+    }    
+
+    /** Method to remove the given subcollection.
+     * @param subcollection the Subcollection you want to remove
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.collection.CollectionManager
+     */
+    private void removeSubcollection(Subcollection subcollection) {
+	remove(subcollection);
+    }
+
+    private void updateSubcollection(Subcollection subcollection, String name, boolean include, String source, String pattern, String flags) {
+	subcollection.setFlags(flags);
+	subcollection.setInclusive(include);
+	subcollection.setName(name);
+	subcollection.setPattern(pattern);
+	subcollection.setSource(source);
+	refresh(subcollection);
+    }
+
+    /** This class creates a JPanel containing serveral more controls used for editing subcollection information. */
+    private class SubcollectionControl
+	extends JPanel 
+	implements Control, ChangeListener
+    {
+	private CardLayout card_layout;
+	private JButton add_button;
+	private JButton remove_button;
+	private JButton update_button;
+	private JComboBox source_combobox;
+	private JList subcollection_list;
+	private JPanel border_pane;
+	private JTabbedPane tabbed_pane;
+	private JTextField flags_field;
+	private JTextField match_field;
+	private JTextField name_field;
+	private JRadioButton exclude_button;
+	private JRadioButton include_button;
+
+	/** Constructor */
+	public SubcollectionControl() {
+	    // Create
+	    JPanel header_pane = new DesignPaneHeader("CDM.GUI.Subcollections", "partitionindexes");
+
+	    border_pane = new JPanel();
+	    card_layout = new CardLayout();
+
+	    tabbed_pane = new JTabbedPane();
+	    tabbed_pane.addChangeListener(this);
+
+	    JPanel button_pane_3 = new JPanel();
+	    add_button = new GLIButton(Dictionary.get("CDM.SubcollectionManager.Add"), Dictionary.get("CDM.SubcollectionManager.Add_Tooltip"));
+	    add_button.setEnabled(false);
+	    
+	    remove_button = new GLIButton(Dictionary.get("CDM.SubcollectionManager.Remove"), Dictionary.get("CDM.SubcollectionManager.Remove_Tooltip"));
+	    remove_button.setEnabled(false);
+	    
+	    update_button = new GLIButton(Dictionary.get("CDM.SubcollectionManager.Replace"), Dictionary.get("CDM.SubcollectionManager.Replace_Tooltip"));
+	    update_button.setEnabled(false);
+	    
+	    JPanel button_pane = new JPanel();
+	    JPanel button_pane_1 = new JPanel();
+	    include_button = new JRadioButton(Dictionary.get("CDM.SubcollectionManager.Include"));
+	    include_button.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+	    include_button.setOpaque(false);
+	    
+	    exclude_button = new JRadioButton(Dictionary.get("CDM.SubcollectionManager.Exclude"));
+	    exclude_button.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+	    exclude_button.setOpaque(false);
+	    
+	    JLabel flags_label = new JLabel(Dictionary.get("CDM.SubcollectionManager.Flags"));
+	    
+	    flags_field = new NonWhitespaceField();
+	    flags_field.setToolTipText(Dictionary.get("CDM.SubcollectionManager.Flags_Tooltip"));
+
+	    JPanel inclusive_pane = new JPanel();
+	    JLabel inclusive_label = new JLabel(Dictionary.get("CDM.SubcollectionManager.Inclusive"));
+	    
+	    JLabel match_label = new JLabel(Dictionary.get("CDM.SubcollectionManager.Match"));
+	    
+	    match_field = new JTextField();
+	    match_field.setToolTipText(Dictionary.get("CDM.SubcollectionManager.Match_Tooltip"));
+	    
+	    JLabel name_label = new JLabel(Dictionary.get("CDM.SubcollectionManager.Name"));
+	    
+	    name_field = new NonWhitespaceField();
+	    name_field.setToolTipText(Dictionary.get("CDM.SubcollectionManager.Name_Tooltip"));
+	    
+	    JLabel source_label = new JLabel(Dictionary.get("CDM.SubcollectionManager.Source"));
+	    
+	    ArrayList every_metadata_set_element = MetadataSetManager.getEveryMetadataSetElement();
+	    Vector source_model = new Vector(every_metadata_set_element);
+	    source_model.add(0, StaticStrings.FILENAME_STR);
+	    source_combobox = new JComboBox(source_model);
+	    source_combobox.setOpaque(false);
+	    source_combobox.setToolTipText(Dictionary.get("CDM.SubcollectionManager.Source_Tooltip"));
+	    
+	    subcollection_list = new JList(model);
+	    subcollection_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+	    JPanel subcollection_pane = new JPanel();
+	    ButtonGroup bg = new ButtonGroup();
+	    bg.add(include_button);
+	    bg.add(exclude_button);
+	    include_button.setSelected(true);
+	    JPanel subcollection_list_pane = new JPanel();
+	    JLabel subcollection_list_label = new JLabel(Dictionary.get("CDM.SubcollectionManager.Assigned"));
+	    
+	    // Create a message pane which explains why these controls are not currently active
+	    JPanel message_pane = new JPanel();
+	    String args[] = new String[3];
+	    args[0] = Configuration.getModeAsString();
+	    args[1] = Dictionary.get("Preferences.Mode.Systems");
+	    args[2] = Dictionary.get("Preferences.Mode.Expert");
+	    JTextArea message_textarea = new JTextArea(Dictionary.get("CDM.SubcollectionManager.Partitions_Disabled", args));
+	    
+	    message_textarea.setEditable(false);
+	    message_textarea.setHighlighter(null); // Prevent highlighting
+	    message_textarea.setLineWrap(true);
+	    message_textarea.setOpaque(false); // Make it transparent
+	    message_textarea.setWrapStyleWord(true);
+
+	    // Add listeners
+	    SubCollectionChangeListener cl = new SubCollectionChangeListener();
+	    add_button.addActionListener(new AddSubCollectionListener());
+	    add_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
+	    remove_button.addActionListener(new RemoveSubCollectionListener());
+	    remove_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
+	    update_button.addActionListener(new UpdateSubCollectionListener());
+	    update_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
+	    exclude_button.addActionListener(cl);
+	    include_button.addActionListener(cl);
+	    source_combobox.addActionListener(cl);
+	    flags_field.getDocument().addDocumentListener(cl);
+	    match_field.getDocument().addDocumentListener(cl);
+	    name_field.getDocument().addDocumentListener(cl);
+	    subcollection_list.addListSelectionListener(new SubCollectionListListener());
+
+	    inclusive_pane.setLayout(new GridLayout());
+	    inclusive_pane.add(include_button);
+	    inclusive_pane.add(exclude_button);
+
+	    button_pane_1.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	    button_pane_1.setLayout(new GridLayout(5, 2));
+	    button_pane_1.add(name_label);
+	    button_pane_1.add(name_field);
+	    button_pane_1.add(source_label);
+	    button_pane_1.add(source_combobox);
+	    button_pane_1.add(match_label);
+	    button_pane_1.add(match_field);
+	    button_pane_1.add(inclusive_label);
+	    button_pane_1.add(inclusive_pane);
+	    button_pane_1.add(flags_label);
+	    button_pane_1.add(flags_field);
+
+	    button_pane_3.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	    button_pane_3.setLayout(new GridLayout(1,3));
+	    button_pane_3.add(add_button);
+	    button_pane_3.add(update_button);
+	    button_pane_3.add(remove_button);
+
+	    button_pane.setLayout(new BorderLayout());
+	    button_pane.add(button_pane_1, BorderLayout.CENTER);
+	    button_pane.add(button_pane_3, BorderLayout.SOUTH);
+
+	    subcollection_list_pane.setLayout(new BorderLayout());
+	    subcollection_list_pane.add(subcollection_list_label, BorderLayout.NORTH);
+	    subcollection_list_pane.add(new JScrollPane(subcollection_list), BorderLayout.CENTER);
+	    subcollection_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	    subcollection_pane.setLayout(new BorderLayout());
+	    subcollection_pane.add(subcollection_list_pane, BorderLayout.CENTER);
+	    subcollection_pane.add(button_pane, BorderLayout.SOUTH);
+
+	    tabbed_pane.addTab(Dictionary.get("CDM.SubcollectionManager.Subcollection_Controls"), subcollection_pane);
+	    tabbed_pane.addTab(Dictionary.get("CDM.SubcollectionManager.Subindex_Controls"), (JPanel) CollectionDesignManager.subcollectionindex_manager.getControls());
+	    tabbed_pane.addTab(Dictionary.get("CDM.SubcollectionManager.Language_Controls"), (JPanel) CollectionDesignManager.language_manager.getControls());
+
+	    message_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
+	    message_pane.setLayout(new GridLayout(3,1,0,0));
+	    message_pane.add(new JPanel());
+	    message_pane.add(message_textarea);
+	    message_pane.add(new JPanel());
+
+	    border_pane.setLayout(card_layout);
+	    if(Configuration.getMode() > Configuration.LIBRARIAN_MODE) {
+		border_pane.add(tabbed_pane, ENABLED_CONTROLS);
+		border_pane.add(message_pane, DISABLED_CONTROLS);
+	    }
+	    else {
+		border_pane.add(message_pane, DISABLED_CONTROLS);
+		border_pane.add(tabbed_pane, ENABLED_CONTROLS);
+	    }
+
+	    setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
+	    setLayout(new BorderLayout());
+	    add(header_pane, BorderLayout.NORTH);
+	    add(border_pane, BorderLayout.CENTER);
+	}
+       	
+	/** Method to unregister any listeners to avoid memory leaks.
+	 */
+	public void destroy() {
+	}
+
+	public void gainFocus() {
+	    // Rebuild the sources combobox
+	    ArrayList every_metadata_set_element = MetadataSetManager.getEveryMetadataSetElement();
+	    Vector source_model = new Vector(every_metadata_set_element);
+	    source_model.add(0, "Filename"); // Add filename as a possible source.
+	    source_combobox.setModel(new DefaultComboBoxModel(source_model));
+	}
+
+	public void loseFocus() {
+	}
+	
+	/** Called when the detail mode has changed which in turn controls if any of the partition controls are visible, or if they are instead replaced with a message explaining why they are not.
+	 * @param mode the new mode as an int
+	 */
+	public void modeChanged(int mode) {
+	    if(mode > Configuration.LIBRARIAN_MODE) {
+		card_layout.show(border_pane, ENABLED_CONTROLS);
+	    }
+	    else {
+		card_layout.show(border_pane, DISABLED_CONTROLS);
+	    }
+	}
+
+	public void stateChanged(ChangeEvent event)
+	{
+	    if (tabbed_pane.getSelectedIndex() == 1) {
+		CollectionDesignManager.subcollectionindex_manager.getControls().gainFocus();
+	    }
+	    if (tabbed_pane.getSelectedIndex() == 2) {
+		CollectionDesignManager.language_manager.getControls().gainFocus();
+	    }
+	}
+
+	/** Listens for actions apon the 'add' button in the SubcollectionManager controls, and if detected calls the addSubcollection method of the manager with a newly created subcollection. */
+	private class AddSubCollectionListener
+	    implements ActionListener {
+	    /** Any implementation of ActionListener must include this method so we can be informed when an action has been performed on one of our target controls. In this case we wish to retrieve information from the various edit controls, and if we have sufficient data to build a new subcollection do so.
+	     * @param event An <strong>ActionEvent</strong> containing information about the event.
+	     * @see org.greenstone.gatherer.cdm.Subcollection
+	     */
+	    public void actionPerformed(ActionEvent event) {
+		String name = name_field.getText();
+		String source = null;
+		Object object = source_combobox.getSelectedItem();
+		if (object instanceof MetadataElement) {
+		    MetadataElement metadata_element = (MetadataElement) object;
+		    source = metadata_element.getFullName();
+		}
+		else {
+		    source = object.toString();
+		}
+		String pattern = match_field.getText();
+		String flags = flags_field.getText();
+		if(name.length() > 0 && (source == null || source.length() > 0) && pattern.length() > 0) {
+		    Subcollection subcollection = new Subcollection(name, include_button.isSelected(), source, pattern, flags);
+		    addSubcollection(subcollection);
+		    // Change the selection to the new subcollection
+		    subcollection_list.setSelectedValue(subcollection, true);
+		}
+		add_button.setEnabled(false);
+	    }
+	}
+
+	/** This class listens for any key entry in a text field, selection change in a combobox or button click, and updates a subcollection as appropriate. Its also convenient to use this class to test if the add button should be active yet. */
+	private class SubCollectionChangeListener
+	    implements DocumentListener, ActionListener {
+	    /** Any implementation of ActionListener must include this method so we can be informed when an action has been performed on one of our target controls. In this case we want to record that somethings changed, then validate the controls.
+	     * @param event An <strong>ActionEvent</strong> containing information about the event.
+	     */
+	    public void actionPerformed(ActionEvent event) {
+		validateAdd();
+	    }
+
+	    public void changedUpdate(DocumentEvent event) {
+		validateAdd();
+	    }
+
+	    public void insertUpdate(DocumentEvent event) {
+		validateAdd();
+
+	    }
+
+	    public void removeUpdate(DocumentEvent event) {
+		validateAdd();
+	    }
+
+	    /** Method to validate the current subcollection editor values, and enable or disable controls (add button) based on said values. */
+	    private void validateAdd() {
+		if(name_field.getText().length() > 0 && match_field.getText().length() > 0) {
+		    if (getSubcollection(name_field.getText()) == null) {
+			add_button.setEnabled(true);
+		    } else {
+			add_button.setEnabled(false);
+		    }
+		}
+		else {
+		    add_button.setEnabled(false);
+		}
+	    }
+	}
+
+	/** Listens for actions apon the 'remove' button in the SubcollectionManager controls, and if detected calls the remove method of the manager with the SubIndex selected for removal. */
+	private class RemoveSubCollectionListener
+	    implements ActionListener {
+	    /** Any implementation of ActionListener must include this method so we can be informed when an action has been performed on one of our target controls. In this case we want to check if they have a subcolleciton selected, and if so remove both it and any subindexes based on it.
+	     * @param event An <strong>ActionEvent</strong> containing information about the event.
+	     * @see org.greenstone.gatherer.cdm.Subcollection
+	     */
+	    public void actionPerformed(ActionEvent event) {
+		if(!subcollection_list.isSelectionEmpty()) {
+		    Subcollection subcollection = (Subcollection)subcollection_list.getSelectedValue();
+		    removeSubcollection(subcollection);
+		    // And remove subcollection indexes dependant on this subcollection
+		    CollectionDesignManager.subcollectionindex_manager.removeSubcollectionIndexes(subcollection);
+		}
+		remove_button.setEnabled(false);
+	    }
+	}
+
+	private class UpdateSubCollectionListener
+	    implements ActionListener {
+	    public void actionPerformed(ActionEvent event) {
+		if(!subcollection_list.isSelectionEmpty()) {
+		    Subcollection subcollection = (Subcollection)subcollection_list.getSelectedValue();
+		    String name = name_field.getText();
+		    String source = null;
+		    Object object = source_combobox.getSelectedItem();
+		    if (object instanceof MetadataElement) {
+			MetadataElement metadata_element = (MetadataElement) object;
+			source = metadata_element.getFullName();
+		    }
+		    else {
+			source = object.toString();
+		    }
+		    String pattern = match_field.getText();
+		    String flags = flags_field.getText();
+		    if(name.length() > 0 && (source == null || source.length() > 0) && pattern.length() > 0) {
+			updateSubcollection(subcollection, name, include_button.isSelected(), source, pattern, flags);
+		    }
+		}
+	    }
+	}
+
+	/** This class listens for selections in the list on the subcollections pane of the SubcollectionManager, and updates the controls as necessary to reflect selection. */
+	private class SubCollectionListListener
+	    implements ListSelectionListener {
+	    /** Any implementation of ListSelectionListener must include this method so we can be informed when the selection changes. In this case we want to execute any changes the users made to the entry, then update the controls with details of the new selection.
+	     * @param event A <strong>ListSelectionEvent</strong> containing information related to this event.
+	     * @see org.greenstone.gatherer.cdm.Subcollection
+	     */
+	    public void valueChanged(ListSelectionEvent event) {
+		// Wait until the event stabilises to avoid processing it multiple times
+		if (event.getValueIsAdjusting() == true) {
+		    return;
+		}
+		// Now the entry
+		if(!subcollection_list.isSelectionEmpty()) {
+		    Subcollection subcollection = (Subcollection) subcollection_list.getSelectedValue();
+		    flags_field.setText(subcollection.getFlags());
+		    include_button.setSelected(subcollection.isInclusive());
+		    exclude_button.setSelected(!subcollection.isInclusive());
+		    match_field.setText(subcollection.getPattern());
+		    name_field.setText(subcollection.getName());
+		    String s = subcollection.getSource();
+		    int pos = 0;
+		    Object value = source_combobox.getItemAt(pos);
+		    //ystem.err.println("Search for: " + s);
+		    while (value != null) {
+			if (value instanceof MetadataElement) {
+			    MetadataElement metadata_element = (MetadataElement) value;
+			    String metadata_element_name = metadata_element.getFullName();
+			    //ystem.err.print("Compare to: " + e_name);
+			    if (metadata_element_name.equals(s)) {
+				source_combobox.setSelectedIndex(pos);
+				value = null;
+				//ystem.err.println(" - Match");
+			    }
+			    else {
+				pos++;
+				value = source_combobox.getItemAt(pos);
+				//ystem.err.println(" - Fail");
+			    }
+			}
+			else if(value.toString().equals(s)) {
+			    source_combobox.setSelectedIndex(pos);
+			    value = null;
+			}
+			else {
+			    pos++;
+			    value = source_combobox.getItemAt(pos);
+			}
+		    }
+		    // Can't add one thats already there.
+		    add_button.setEnabled(false);
+		    // You can update or remove it though...
+		    remove_button.setEnabled(true);
+		    update_button.setEnabled(true);
+		}
+		else {
+		    flags_field.setText("");
+		    include_button.setSelected(true);
+		    match_field.setText("");
+		    name_field.setText("");
+		    source_combobox.setSelectedIndex(0);
+		    remove_button.setEnabled(false);
+		    update_button.setEnabled(false);
+		}
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/SuperCollection.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/SuperCollection.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/SuperCollection.java	(revision 13928)
@@ -0,0 +1,97 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+* This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import org.greenstone.gatherer.util.StaticStrings;
+import org.w3c.dom.Element;
+
+
+public class SuperCollection
+    implements DOMProxyListEntry {
+
+    private Element element;
+    private String name;
+
+    public SuperCollection() {
+	element = null;
+	name = null;
+    }
+
+    public SuperCollection(Element element) {
+	this.element = element;
+	name = null;
+    }
+
+    public int compareTo(Object other) {
+	return this.getName().compareTo(other.toString());
+    }
+
+    public DOMProxyListEntry create(Element element) {
+	return new SuperCollection(element);
+    } 
+
+    public boolean equals(Object other) {
+	return (compareTo(other) == 0);
+    }
+
+    public Element getElement() {
+	return element;
+    }
+
+    public String getName() {
+	if(name == null && element != null) {
+	    name = element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
+	}
+	return name;
+    }
+
+    public boolean isAssigned() {
+	return (element != null && element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.TRUE_STR));
+    }
+
+    public void setAssigned(boolean assigned) {
+	if(element != null) {
+	    element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, (assigned ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
+	}
+    }
+
+    public void setElement(Element element) {
+	this.element = element;
+	name = null;
+    }
+
+    public void setName(String name) {
+	this.name = name;
+	if(element != null) {
+	    element.setAttribute(StaticStrings.NAME_ATTRIBUTE, name);
+	}
+    }
+
+    public String toString() {
+	return getName();
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/SuperCollectionManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/SuperCollectionManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/SuperCollectionManager.java	(revision 13928)
@@ -0,0 +1,242 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+* This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import java.awt.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.BasicCollectionConfiguration;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.util.CheckList;
+import org.greenstone.gatherer.util.CheckListEntry;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.gui.DesignPaneHeader;
+import org.w3c.dom.*;
+
+/** This class contains the information about what supercollection has been specified (if any) and methods for changing this information. Note that there is a major difference between this manager and the others in that its DOM model is never used directly in any list component. It is only used to decide whether a certain entry in the actual checklist is checked. */
+public class SuperCollectionManager
+    extends DOMProxyListModel {
+
+    static final public String SUPERCOLLECTION_COMMAND = "supercollection";
+    static final public String CCS_COMMAND = "ccs";
+    private ArrayList collection_checklist_model = null; // Model used to actually populate list
+    private Control controls = null;
+    private DOMProxyListModel model = null;
+    private String current_coll_name = null;
+    private boolean superCollectionChanged = false;
+
+    public SuperCollectionManager(Element supercollections_element) {
+	super(supercollections_element, StaticStrings.COLLECTION_ELEMENT, new SuperCollection());
+	DebugStream.println("SuperCollectionManager: " + getSize() + " supercollection members parsed.");
+	this.model = this;
+    }
+
+    public void destroy() {
+	if(controls != null) {
+	    controls.destroy();
+	    controls = null;
+	}
+	if(collection_checklist_model != null) {
+	    collection_checklist_model.clear();
+	    collection_checklist_model = null;
+	}
+    }
+
+    private void addSuperCollection(SuperCollection supercollection) {
+	if(!contains(supercollection)) {
+	    add(getSize(), supercollection);
+	}
+    }
+
+    /** Method to retrieve the control for this manager.
+     * @return the Control for editing supercollection settings
+     */
+    public Control getControls() {
+	if(controls == null) {
+	    // Build controls
+	    this.controls = new SuperCollectionControl();
+	}
+	return controls;
+    }
+
+    public SuperCollection getSuperCollection(String collection_name) {
+	SuperCollection result = null;
+	int size = getSize();
+	for(int i = 0; result == null && i < size; i++) {
+	    SuperCollection supercollection = (SuperCollection) getElementAt(i);
+	    if(supercollection.getName().equals(collection_name)) {
+		result = supercollection;
+	    }
+	    supercollection = null;
+	}
+	return result;
+    }
+    /** Called when the detail mode has changed which in turn may cause several design elements to be available/hidden
+     * @param mode the new mode as an int
+     */
+    public void modeChanged(int mode) {
+
+    }
+
+    private void removeSuperCollection(SuperCollection supercollection) {
+	if(contains(supercollection)) {
+	    remove(supercollection);
+	}
+    }
+
+    /** Provides controls for altering the SuperCollection settings. */
+    private class SuperCollectionControl
+	extends JPanel
+	implements Control {
+
+	private boolean init = true;
+	private CheckList collection_checklist = null;
+
+	SuperCollectionControl() {
+	    super();
+
+	    // Creation
+	    JPanel header_panel = new DesignPaneHeader("CDM.GUI.SuperCollection", "xcollectionsearching");
+
+	    collection_checklist = new CheckList(false);
+	    buildModel();
+	    collection_checklist.setListData(collection_checklist_model);
+
+	    JPanel collection_checklist_pane = new JPanel();
+	    collection_checklist_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	    collection_checklist_pane.setLayout(new BorderLayout());
+	    collection_checklist_pane.add(new JScrollPane(collection_checklist), BorderLayout.CENTER);
+
+	    setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
+	    setLayout(new BorderLayout());
+	    add(header_panel, BorderLayout.NORTH);
+	    add(collection_checklist_pane, BorderLayout.CENTER);
+	}
+
+	public void destroy() {
+	}
+
+	public void gainFocus() {
+	}
+
+	public void loseFocus() {
+	    int super_collections_count = 0;
+	    // Retrieve the current supercollections
+	    ArrayList supercollections = children();
+	    // Now iterate through the checklist, and for each checked box found ensure the Supercollection exists, and ensure its assigned. Remove any supercollections altered in this way from the temporary array list
+	    // we ignore the current coll at the moment
+	    int size = collection_checklist_model.size();
+	    for(int i = 0; i < size; i++) {
+		CheckListEntry entry = (CheckListEntry) collection_checklist_model.get(i);
+		if(entry.isSelected()) {
+		    String collection_name = (String) entry.getProperty();
+		    if (!collection_name.equals(current_coll_name)) {
+			SuperCollection supercollection = getSuperCollection(collection_name);
+			// Create the supercollection element if necessary
+			if(supercollection == null) {
+			    Element supercollection_element = root.getOwnerDocument().createElement(StaticStrings.COLLECTION_ELEMENT);
+			    supercollection = new SuperCollection(supercollection_element);
+			    supercollection.setName(collection_name);
+			    addSuperCollection(supercollection);
+			}
+			else {
+			    supercollections.remove(supercollection);
+			}
+			supercollection.setAssigned(true);
+			super_collections_count++;
+		    }
+		}
+	    }
+	    if (super_collections_count > 0) {
+		// we have some super colls, add in the current collection
+		SuperCollection supercollection = getSuperCollection(current_coll_name);
+		// Create the supercollection element if necessary
+		if(supercollection == null) {
+		    Element supercollection_element = root.getOwnerDocument().createElement(StaticStrings.COLLECTION_ELEMENT);
+		    supercollection = new SuperCollection(supercollection_element);
+		    supercollection.setName(current_coll_name);
+		    addSuperCollection(supercollection);
+		}
+		else {
+		    supercollections.remove(supercollection);
+		}
+		model.root.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
+	    } else {
+		// current collection is the only one - don't bother adding it, because assigned is false, and we don't want to update the config file for an unassigned item.
+		model.root.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
+	    }
+	    
+	    // Any collections left in the temporary list have been unselected, so delete them
+	    for(int j = supercollections.size(); j > 0; j--) {
+		SuperCollection supercollection = (SuperCollection) supercollections.get(j - 1);
+		removeSuperCollection(supercollection);
+	    }
+	}
+
+	
+	private void buildModel()
+	{
+	    collection_checklist_model = new ArrayList();
+	    current_coll_name = CollectionManager.getLoadedCollectionName();
+
+	    File collect_directory = new File(Gatherer.getCollectDirectoryPath());
+	    File[] possible_collections = collect_directory.listFiles();
+	    for(int i = 0; possible_collections != null && i < possible_collections.length; i++) {
+		File collect_cfg_file = new File(possible_collections[i], Utility.CONFIG_FILE);
+		if (collect_cfg_file.exists()) {
+		    BasicCollectionConfiguration collect_cfg = new BasicCollectionConfiguration(collect_cfg_file);
+		    StringBuffer title_buffer = new StringBuffer(collect_cfg.getName());
+		    title_buffer.append(StaticStrings.SPACE_CHARACTER);
+		    title_buffer.append(StaticStrings.OPEN_PARENTHESIS_CHARACTER);
+		    title_buffer.append(possible_collections[i].getName());
+		    title_buffer.append(StaticStrings.CLOSE_PARENTHESIS_CHARACTER);
+		    String collection_title = title_buffer.toString();
+		    title_buffer = null;
+		    String collection_name = possible_collections[i].getName();
+
+		    // We have to block the model collection.
+		    if (collect_cfg.getName().equals("**title**")) {
+			continue;
+		    }
+
+		    // The current collection is always selected.
+		    CheckListEntry entry = new CheckListEntry(collection_title);
+		    entry.setProperty(collection_name);
+		    entry.setSelected(getSuperCollection(collection_name) != null || collection_name.equals(current_coll_name));
+		    entry.setFixed(collection_name.equals(current_coll_name));
+		    collection_checklist_model.add(entry);
+		}
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/TranslationView.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/TranslationView.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/cdm/TranslationView.java	(revision 13928)
@@ -0,0 +1,718 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.cdm;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.table.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.gui.DesignPaneHeader;
+import org.greenstone.gatherer.gui.GLIButton;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+
+/** This class provides a graphical interface to allow a user to quickly and conviently (ie all in one place) translate the text fragments associated with general metadata and indexes into each of the assigned languages in the collection. It should provide clear controls for the editing of these text fragments, plus clear indicate what languages still need further translation, which it will do through a combination of coloring and other visual indicators.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class TranslationView {
+
+    private Control controls;
+
+    static final private Dimension COMPONENT_SIZE = new Dimension(225,25);
+    static final private int LANGUAGE_WIDTH = 75;
+    static final private String GENERAL_STR = "General:";
+    static final private String INDEX_STR = "Index:";
+    static final private String PARTITION_STR = "Partitions:";
+
+    public TranslationView() {
+	DebugStream.println("TranslationView: Initialized.");
+    }
+
+    public void destroy() {
+	if(controls != null) {
+	    controls.destroy();
+	    controls = null;
+	}
+    }
+
+    public Control getControls() {
+	if(controls == null) {
+	    controls = new TranslationControl();
+	}
+	return controls;
+    }
+
+    /** Called when the detail mode has changed which in turn may cause several design elements to be available/hidden
+     * @param mode the new mode as an int
+     */
+    public void modeChanged(int mode) {
+
+    }
+
+    private Object[] getFeaturesList() {
+	ArrayList features_model = new ArrayList();
+
+	// Add the indexes
+	ArrayList indexes = CollectionDesignManager.index_manager.getIndexes();
+	int indexes_size = indexes.size();
+	for(int j = 0; j < indexes_size; j++) {
+	    Object bob = new BobTheMagicalComparableWrapper(indexes.get(j));
+	    if(!features_model.contains(bob)) {
+		features_model.add(bob);
+	    }
+	}
+
+	// We also add subindexes.
+	ArrayList subindexes = CollectionDesignManager.subcollectionindex_manager.getSubcollectionIndexes();
+	int subindexes_size = subindexes.size();
+	for(int j = 0; j < subindexes_size; j++) {
+	    Object bob = new BobTheMagicalComparableWrapper(subindexes.get(j));
+	    if(!features_model.contains(bob)) {
+		features_model.add(bob);
+	    }
+	}
+
+	// Finally we add any remaining metadata as general
+	ArrayList general_metadata = CollectionDesignManager.collectionmeta_manager.getMetadata();
+	for(int i = 0; i < general_metadata.size(); i++) {
+	    CollectionMeta metadata = (CollectionMeta) general_metadata.get(i);
+	    if(!metadata.isSpecial()) {
+		Object bob = new BobTheMagicalComparableWrapper(metadata.getName());
+		if(!features_model.contains(bob)) {
+		    features_model.add(bob);
+		}
+	    }
+	}
+
+	Collections.sort(features_model);
+
+	return features_model.toArray();
+    }
+
+    private class BobTheMagicalComparableWrapper
+	implements Comparable {
+	private Object content;
+	private String text;
+	BobTheMagicalComparableWrapper(Object content) {
+	    this.content = content;
+	}
+	public int compareTo(Object object) {
+	    if(object == null) {
+		object = "";
+	    }
+	    if(text == null) {
+		toString();
+	    }
+	    return text.compareTo(object.toString());
+	}
+
+	/** Equals is used by contains and since we want to prevent double up of metadata we compare differently than in compareTo. */
+	public boolean equals(Object object) {
+	    return (object != null && content.toString().equals(((BobTheMagicalComparableWrapper)object).getContent().toString()));
+	}
+
+	public Object getContent() {
+	    return content;
+	}
+
+	public String getName() {
+	    if(content instanceof Index) {
+		return StaticStrings.STOP_CHARACTER + ((Index)content).getID();
+	    }
+	    else if (content instanceof SubcollectionIndex) {
+	    	return StaticStrings.STOP_CHARACTER + ((SubcollectionIndex)content).getID();
+	    }
+	    else {
+		return content.toString();
+	    }
+	}
+
+	public String toString() {
+	    if(text == null) {
+		String temp = content.toString();
+		if(temp.indexOf(StaticStrings.SPACE_CHARACTER) != -1) {
+		    temp = temp.substring(0, temp.indexOf(StaticStrings.SPACE_CHARACTER));
+		}
+		if(content instanceof Index) {
+		    text = INDEX_STR + temp;
+		}
+		else if(content instanceof SubcollectionIndex) {
+		    text = PARTITION_STR + temp;
+		}
+		else {
+		    text = GENERAL_STR + temp;
+		}
+	    }
+	    return text;
+	}
+    }
+
+    private class TranslationControl
+	extends JPanel 
+	implements Control {
+
+	private boolean ignore_event = false;
+	private FragmentTableModel fragment_table_model;
+	private JButton add_button;
+	private JButton remove_button;
+	private JButton replace_button;
+	private JComboBox language_combobox;
+	private JList features_list;
+	private JTable fragment_table;
+	private JTextArea default_area;
+	private JTextArea translation_area;
+
+	TranslationControl() {
+	    fragment_table_model = new FragmentTableModel("", new TreeSet(), new ArrayList());
+	    // Creation
+	    JPanel header_panel = new DesignPaneHeader("CDM.GUI.Translation", "translatetext");
+
+	    JPanel center_panel = new JPanel();
+
+	    JPanel selection_panel = new JPanel();
+
+	    JPanel component_selection_panel = new JPanel();
+	    JLabel component_label = new JLabel(Dictionary.get("CDM.TranslationManager.Affected_Features"));
+
+
+	    Object[] features = getFeaturesList();
+	    features_list = new JList(features);
+	    features_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+            if (features != null && features.length >0){
+		features_list.setSelectedIndex(0);
+	    }
+
+	    JPanel fragment_selection_panel = new JPanel();
+	    JLabel fragment_label = new JLabel(Dictionary.get("CDM.TranslationManager.Assigned_Fragments"));
+	    
+	    fragment_table = new JTable(fragment_table_model);
+	    fragment_table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
+	    fragment_table.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+	    fragment_table.setColumnSelectionAllowed(false);
+	    fragment_table.setDefaultRenderer(Object.class, new FragmentTableRenderer());
+	    fragment_table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+
+	    JScrollPane table_scroll = new JScrollPane(fragment_table);
+	    table_scroll.getViewport().setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+	    table_scroll.setOpaque(true);
+
+	    JPanel south_panel = new JPanel();
+
+	    JPanel text_panel = new JPanel();
+
+	    JPanel language_panel = new JPanel();
+	    JLabel language_label = new JLabel(Dictionary.get("CDM.TranslationManager.Language"));
+	    
+	    language_combobox = new JComboBox(CollectionDesignManager.language_manager.getLanguageCodes().toArray());
+	    language_combobox.setOpaque(!Utility.isMac());
+	    language_combobox.setPreferredSize(COMPONENT_SIZE);
+	    language_combobox.setRenderer(new LanguageListCellRenderer());
+	    language_combobox.setToolTipText(Dictionary.get("CDM.TranslationManager.Language_Tooltip"));
+	    
+	    JPanel default_text_panel = new JPanel();
+	    JLabel default_label = new JLabel(Dictionary.get("CDM.TranslationManager.Default_Text"));
+	    
+	    default_area = new JTextArea();
+	    default_area.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+	    default_area.setEditable(false);
+	    default_area.setLineWrap(true);
+	    default_area.setWrapStyleWord(true);
+
+	    JPanel translated_text_panel = new JPanel();
+	    JLabel translation_label = new JLabel(Dictionary.get("CDM.TranslationManager.Translation"));
+	 
+	    translation_area = new JTextArea();
+	    translation_area.setBackground(Configuration.getColor("coloring.disabled", false));
+	    translation_area.setEnabled(false);
+	    translation_area.setLineWrap(true);
+	    translation_area.setWrapStyleWord(true);
+	    translation_area.setToolTipText(Dictionary.get("CDM.TranslationManager.Translation_Tooltip"));
+
+	    JPanel button_pane = new JPanel();
+	    add_button = new GLIButton(Dictionary.get("CDM.TranslationManager.Add"), Dictionary.get("CDM.TranslationManager.Add_Tooltip"));
+	    add_button.setEnabled(false);
+
+	    replace_button = new GLIButton(Dictionary.get("CDM.TranslationManager.Replace"), Dictionary.get("CDM.TranslationManager.Replace_Tooltip"));
+	    replace_button.setEnabled(false);
+
+	    remove_button = new GLIButton(Dictionary.get("CDM.TranslationManager.Remove"), Dictionary.get("CDM.TranslationManager.Remove_Tooltip"));
+	    remove_button.setEnabled(false);
+
+
+	    // Connection
+	    add_button.addActionListener(new AddListener());
+	    remove_button.addActionListener(new RemoveListener());
+	    replace_button.addActionListener(new ReplaceListener());
+	    language_combobox.addActionListener(new LanguageActionListener());
+	    translation_area.getDocument().addDocumentListener(new TranslationDocumentListener());
+	    features_list.addListSelectionListener(new FeaturesListSelectionListener());
+	    fragment_table.getSelectionModel().addListSelectionListener(new FragmentListSelectionListener());
+
+	    // Layout
+	    component_selection_panel.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	    component_selection_panel.setLayout(new BorderLayout());
+	    component_selection_panel.add(component_label, BorderLayout.NORTH);
+	    component_selection_panel.add(new JScrollPane(features_list), BorderLayout.CENTER);
+
+	    fragment_selection_panel.setLayout(new BorderLayout());
+	    fragment_selection_panel.add(fragment_label, BorderLayout.NORTH);
+	    fragment_selection_panel.add(table_scroll, BorderLayout.CENTER);
+
+	    selection_panel.setLayout(new GridLayout(2,1,0,5));
+	    selection_panel.add(component_selection_panel);
+	    selection_panel.add(fragment_selection_panel);
+
+	    default_text_panel.setLayout(new BorderLayout());
+	    default_text_panel.add(default_label, BorderLayout.NORTH);
+	    default_text_panel.add(new JScrollPane(default_area), BorderLayout.CENTER);
+
+	    translated_text_panel.setLayout(new BorderLayout());
+	    translated_text_panel.add(translation_label, BorderLayout.NORTH);
+	    translated_text_panel.add(new JScrollPane(translation_area), BorderLayout.CENTER);
+
+	    text_panel.setLayout(new GridLayout(1,2,5,0));
+	    text_panel.add(default_text_panel);
+	    text_panel.add(translated_text_panel);
+
+	    language_panel.setLayout(new BorderLayout(5,0));
+	    language_panel.add(language_label, BorderLayout.WEST);
+	    language_panel.add(language_combobox, BorderLayout.CENTER);
+
+	    south_panel.setLayout(new BorderLayout());
+	    south_panel.add(language_panel, BorderLayout.NORTH);
+	    south_panel.add(text_panel, BorderLayout.CENTER);
+
+	    center_panel.setLayout(new GridLayout(2,1,0,5));
+	    center_panel.add(selection_panel);
+	    center_panel.add(south_panel);
+
+	    button_pane.setBorder(BorderFactory.createEmptyBorder(2,0,0,0));
+	    button_pane.setLayout(new GridLayout(1,3));
+	    button_pane.add(add_button);
+	    button_pane.add(replace_button);
+	    button_pane.add(remove_button);
+
+	    setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
+	    setLayout(new BorderLayout());
+	    add(header_panel, BorderLayout.NORTH);
+	    add(center_panel, BorderLayout.CENTER);
+	    add(button_pane, BorderLayout.SOUTH);
+	}
+
+	public void destroy() {
+	}
+
+	public void gainFocus() {
+	    // Rebuild the features model, just incase features have been added or removed.
+	    if(features_list != null) {
+		Object selected_feature = features_list.getSelectedValue();
+		features_list.setListData(getFeaturesList());
+		if(selected_feature != null) {
+		    features_list.setSelectedValue(selected_feature, true);
+		}
+	    }
+	}
+
+	public void loseFocus() {
+	}
+
+
+	private class AddListener
+	    implements ActionListener {
+	    
+	    public void actionPerformed(ActionEvent event) {
+		ignore_event = true;
+		String translation_text = translation_area.getText();
+		if(translation_text.length() > 0) {
+		    // If there is no current fragment table selection, but translation text is not an empty string, then this is a new fragment. Create new collection metadata, refresh the fragment table, then ensure that the new metadata is selected. Remember that it is the selected metadata to which changes will be applied.
+		    BobTheMagicalComparableWrapper selected_feature = (BobTheMagicalComparableWrapper)features_list.getSelectedValue();
+		    String language = (String) language_combobox.getSelectedItem();
+		    CollectionMeta metadatum = new CollectionMeta(selected_feature.getName(), language);
+		    metadatum.setValue(translation_text);
+		    CollectionDesignManager.collectionmeta_manager.addMetadatum(metadatum);
+		    fragment_table.clearSelection();
+		    ArrayList metadata = CollectionDesignManager.collectionmeta_manager.getMetadata(selected_feature.getName());
+		    fragment_table_model.setData(selected_feature.getName(), CollectionDesignManager.collectionmeta_manager.getLanguages(), metadata);
+		    int index = fragment_table_model.getMetadataIndexByLanguage(language);
+		    ///ystem.err.println("I want to select the row " + index + " out of " + metadata.size());
+		    fragment_table.setRowSelectionInterval(index, index);
+		    metadatum = null;
+		    language = null;
+		    selected_feature = null;
+		    translation_text = null;
+		    remove_button.setEnabled(true);
+		}
+		add_button.setEnabled(false);
+		replace_button.setEnabled(false);
+		ignore_event = false;
+	    }
+	}
+
+	private class RemoveListener
+	    implements ActionListener {
+	    
+	    public void actionPerformed(ActionEvent event) {
+		ignore_event = true;
+		int index = -1;
+		if((index = fragment_table.getSelectedRow()) != -1) {
+		    CollectionMeta metadata = fragment_table_model.getMetadata(index);
+		    CollectionDesignManager.collectionmeta_manager.removeMetadata(metadata);
+		    fragment_table_model.remove(index);
+		    // If a remove occured then enable add
+		    add_button.setEnabled(true);
+		}
+		// Either way disable replace and remove
+		replace_button.setEnabled(false);
+		remove_button.setEnabled(false);
+		ignore_event = false;
+	    }
+	}
+
+	private class ReplaceListener 
+	    implements ActionListener {
+
+	    public void actionPerformed(ActionEvent event) {
+		ignore_event = true;
+		int index = -1;
+		if((index = fragment_table.getSelectedRow()) != -1) {
+		    String translation_text = translation_area.getText();
+		    // Get the selected collection metadata
+		    CollectionMeta metadata = fragment_table_model.getMetadata(index);
+		    // Update the fragment metadata and ask the table to repaint the appropriate row
+		    metadata.setValue(translation_text);
+		    fragment_table_model.fireTableRowsUpdated(index, index);
+		    metadata = null;
+		    remove_button.setEnabled(true);
+		}
+		// Either way disable replace
+		add_button.setEnabled(false);
+		replace_button.setEnabled(false);
+		ignore_event = false;
+	    }
+	}
+
+	private class FeaturesListSelectionListener
+	    implements ListSelectionListener {
+	    public void valueChanged(ListSelectionEvent event) {
+		if(!event.getValueIsAdjusting() && !ignore_event) {
+		    ///ystem.err.println("FeaturesListSelectionListener");
+		    if(!features_list.isSelectionEmpty()) {
+			// Determine the features name. Remember to remove our helpful source prefix (delimited by ':').
+			BobTheMagicalComparableWrapper selected_feature = (BobTheMagicalComparableWrapper)features_list.getSelectedValue();
+			// Retrieve the default language translation, or otherwise the first match, to be default text.
+			CollectionMeta default_metadata = CollectionDesignManager.collectionmeta_manager.getMetadatum(selected_feature.getName());
+			if(default_metadata != null) {
+			    default_area.setText(default_metadata.getValue(CollectionMeta.TEXT));
+			}
+			// Update the text fragment table.
+			fragment_table.clearSelection();
+			fragment_table_model.setData(selected_feature.getName(), CollectionDesignManager.collectionmeta_manager.getLanguages(), CollectionDesignManager.collectionmeta_manager.getMetadata(selected_feature.getName()));
+			selected_feature = null;
+			// Now we check whatever value is currently selected in the combobox to see if it is valid to add.
+			String language_name = (String) language_combobox.getSelectedItem();
+			int index = fragment_table_model.getMetadataIndexByLanguage(language_name);
+			if(index != -1) {
+			    CollectionMeta metadata = fragment_table_model.getMetadata(index);
+			    fragment_table.setRowSelectionInterval(index, index);
+			    if(metadata != null) {
+				translation_area.setText(metadata.getValue(CollectionMeta.TEXT));
+			    }
+			    else {
+				translation_area.setText("");
+			    }
+			    metadata = null;
+			}
+			else {
+			    translation_area.setText("");
+			}
+			// Update and enable the text area
+			translation_area.setEnabled(true);
+			translation_area.setBackground(Configuration.getColor("coloring.editable_background", false));
+		    }
+		    else {
+			default_area.setText("");
+			fragment_table.clearSelection();
+			fragment_table_model.setData("", new TreeSet(), new ArrayList());
+			translation_area.setText("");
+			// Update and disable the text area
+			translation_area.setText("");
+			translation_area.setEnabled(false);
+			translation_area.setBackground(Configuration.getColor("coloring.disabled", false));
+		    }
+		}
+	    }
+	}
+
+	private class FragmentListSelectionListener
+	    implements ListSelectionListener {
+	    public void valueChanged(ListSelectionEvent event) {
+		if(!event.getValueIsAdjusting() && !ignore_event) {
+		    ignore_event = true;
+		    ///ystem.err.println("FragmentListSelectionListener");
+		    int index = -1;
+		    if((index = fragment_table.getSelectedRow()) != -1) {
+			// A row has been selected. Retrieve the collection metadata.
+			CollectionMeta metadatum = fragment_table_model.getMetadata(index);
+			if(metadatum != null) {
+			    // Update the combobox to show the current language.
+			    String language = metadatum.getLanguage();
+			    ///ystem.err.println("Searching for the language: " + language_name);
+			    for(int i = 0; i < language_combobox.getItemCount(); i++) {
+				if(language_combobox.getItemAt(i).toString().equals(language)) {
+				    language_combobox.setSelectedIndex(i);
+				}
+			    }
+			    translation_area.setText(metadatum.getValue(CollectionMeta.TEXT));
+			    remove_button.setEnabled(!metadatum.isDummy());
+			}
+			else {
+			    remove_button.setEnabled(false);
+			}
+		    }
+		    else {
+			translation_area.setText("");
+			remove_button.setEnabled(false);
+		    }
+		    ignore_event = false;
+		}
+	    }
+	}
+
+	private class FragmentTableModel
+	    extends AbstractTableModel {
+
+	    private ArrayList metadata;
+	    private String feature_name;
+	    private TreeSet languages;
+
+	    FragmentTableModel(String feature_name, TreeSet languages, ArrayList metadata) {
+		this.feature_name = feature_name;
+		this.languages = languages;
+		this.metadata = metadata;
+	    }
+	    public int getRowCount() {
+	       // The row count is equal to the maximum number of languages currently assigned in the collection.
+		return languages.size();
+	    }
+	    public int getColumnCount() {
+		return 2;
+	    }
+
+	    public String getColumnName(int column) {
+		if (column == 0) {
+		    return Dictionary.get("CDM.TranslationManager.Language_Column");
+		}
+		if (column == 1) {
+		    return Dictionary.get("CDM.TranslationManager.Fragment_Column");
+		}
+		return "";
+	    }
+
+	    /** Attempt to retrieve the metadata associated with a certain row - however not all rows actually have metadata with them (say the French row where no metadata has been set).
+	     * @param row the row number as an int
+	     * @return the CollectionMeta requested, which may be a dummy metadata pair
+	     */
+	    public CollectionMeta getMetadata(int row) {
+		// Determine what language we are talking about
+		String language = null;
+		Iterator language_iterator = languages.iterator();
+		int current_row = 0;
+		while(current_row != row && language_iterator.hasNext()) {
+		    language_iterator.next();
+		    current_row++;
+		}
+		if(current_row == row) {
+		    language = (String) language_iterator.next();
+		    return getMetadata(language);
+		}
+		language_iterator = null;
+		return null;
+	    }
+
+	    public CollectionMeta getMetadata(String language) {
+		// Attempt to retrieve metadata with that language
+		for(int i = 0; i < metadata.size(); i++) {
+		    CollectionMeta metadatum = (CollectionMeta) metadata.get(i);
+		    if(metadatum.getLanguage().equals(language)) {
+			return metadatum;
+		    }
+		}
+		return new CollectionMeta(feature_name, language, true);
+	    }
+
+	    public int getMetadataIndexByLanguage(String language) {
+		///ystem.err.println("Find the index for the language " + language + " (out of " + languages.size() + ")");
+		// First we have to iterate to the correct place
+		Iterator language_iterator = languages.iterator();
+		int current_row = 0;
+		while(language_iterator.hasNext()) {
+		    String target = (String)language_iterator.next();
+		    if(language.equals(target)) {
+			///ystem.err.println("Matches " + target);
+			return current_row;
+		    }
+		    else {
+			///ystem.err.println("Doesn't match " + target);
+			current_row++;
+		    }
+		}
+		///ystem.err.println("No such language in model: -1");
+		return -1;
+	    }
+
+	    public Object getValueAt(int row, int column) {
+		if(0 <= row && row < languages.size()) {
+		    // First we have to iterate to the correct place
+		    Iterator language_iterator = languages.iterator();
+		    int current_row = 0;
+		    while(current_row != row && language_iterator.hasNext()) {
+			language_iterator.next();
+			current_row++;
+		    }
+		    if(current_row == row) {
+			String language = (String)language_iterator.next();
+			if(column == 0) {
+			    return CollectionDesignManager.language_manager.getLanguageName(language);
+			}
+			else {
+			    CollectionMeta metadatum = getMetadata(language);
+			    return metadatum.getValue(CollectionMeta.TEXT);
+			}
+		    }
+		    language_iterator = null;
+		}
+		return "#Error";
+	    }
+
+	    public void remove(int index) {
+		metadata.remove(index);
+		fireTableRowsDeleted(index, index);
+	    }
+
+	    public void setData(String feature_name, TreeSet languages, ArrayList metadata) {
+		this.feature_name = feature_name;
+		this.languages = languages;
+		this.metadata = metadata;
+		fireTableDataChanged();
+	    }
+
+	    public int size() {
+		return metadata.size();
+	    }
+	}
+
+	private class FragmentTableRenderer
+	    extends DefaultTableCellRenderer {
+	    /** Retrieve the component used to rubberstamp the table based on the given parameters.
+	     * @param table The <strong>JTable</strong> to rendered.
+	     * @param value The <strong>Object</strong> whose representation will be shown in the table row.
+	     * @param isSelected <i>true</i> iff the column/row is selected.
+	     * @param hasFocus <i>true</i> iff the column/row is in focus.
+	     * @param row An <i>int</i> specifying the target row.
+	     * @param column An <i>int</i> specifying the target column.
+	     * @see org.greenstone.gatherer.cdm.Language
+	     */
+	    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
+		JComponent component = (JComponent) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+		if(isSelected) {
+		    component.setBackground(Configuration.getColor("coloring.workspace_heading_background", false));
+		}
+		else {
+		    component.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+		}
+		return component;
+	    }
+	}
+
+	private class LanguageActionListener
+	    implements ActionListener {
+	    public void actionPerformed(ActionEvent event) {
+		if(!ignore_event && features_list.getSelectedIndex()>-1) {
+		    ignore_event = true;
+		    ///ystem.err.println("LanguageActionListener");
+		    // If the newly selected language value already exists in the fragment table, and that row isn't the one selected, then select that row the text area.
+		    String language_name = language_combobox.getSelectedItem().toString();
+		    int index = fragment_table_model.getMetadataIndexByLanguage(language_name);
+		    if(index != -1) {
+			CollectionMeta metadata = fragment_table_model.getMetadata(index);
+			fragment_table.setRowSelectionInterval(index, index);
+			translation_area.setText(metadata.getValue(CollectionMeta.TEXT));
+		    }
+		    else {
+			fragment_table.clearSelection();
+			translation_area.setText("");
+		    }
+		    // Ready the text area
+		    translation_area.setEnabled(true);
+		    translation_area.setBackground(Configuration.getColor("coloring.editable_background", false));
+		    ignore_event = false;
+		}
+	    }
+	}
+
+	private class TranslationDocumentListener
+	    implements DocumentListener {
+	    /** Gives notification that an attribute or set of attributes changed. */
+	    public void changedUpdate(DocumentEvent e) {
+		update();
+	    }
+	    /** Gives notification that there was an insert into the document. */
+	    public void insertUpdate(DocumentEvent e) {
+		update();
+	    }
+	    /** Gives notification that a portion of the document has been removed. */
+	    public void removeUpdate(DocumentEvent e) {
+		update();
+	    }
+	    /** The text area has changed in some way. Given that this can only happed when we are editing or adding a text fragment we better respond appropriately. */
+	    private void update() {
+		String translation_text = translation_area.getText();
+		// Determine if add should be enabled. You can only add if the current text fragment doesn't already exist in the fragment table for the given language
+		String language = (String) language_combobox.getSelectedItem();
+		CollectionMeta metadatum = fragment_table_model.getMetadata(language);
+		add_button.setEnabled(translation_text.length() > 0 && (metadatum.isDummy() || fragment_table_model.getMetadataIndexByLanguage(language) == -1));
+		language = null;
+		// Determine if replace should be enabled. Replace is only enabled it the text fragment is different from the one in the current fragment table selection.
+		if(fragment_table.getSelectedRowCount() > 0) {
+		    replace_button.setEnabled(!metadatum.isDummy() && !translation_text.equals(fragment_table.getValueAt(fragment_table.getSelectedRow(), 1)));
+		}
+		// Nothing selected, nothing to replace
+		else {
+		    replace_button.setEnabled(false);
+		}
+		translation_text = null;
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/BasicCollectionConfiguration.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/BasicCollectionConfiguration.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/BasicCollectionConfiguration.java	(revision 13928)
@@ -0,0 +1,213 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.collection;
+
+import java.io.*;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.cdm.CommandTokenizer;
+import org.greenstone.gatherer.util.Codec;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.w3c.dom.*;
+
+/** This class provides access to a collection configuration file. This version accepts either a valid xml document or a historical collect.cfg file. */
+public class BasicCollectionConfiguration
+    implements Comparable {
+    
+    private File file;
+    private String creator = "";
+    private String description = "";
+    private String maintainer = "";
+    private String name = "";
+    
+    private String site = null; // used for gs3 colls
+    
+    public BasicCollectionConfiguration(File file) {
+	this.file = file;
+	try {
+	    String filename = file.getName().toLowerCase();
+	    if(!file.exists()) {
+		return;
+	    }
+	    if(filename.endsWith(".cfg")) {
+		FileInputStream fis = new FileInputStream(file);
+		InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
+		BufferedReader br = new BufferedReader(isr);
+		String command = null;
+		while((command = br.readLine()) != null) {
+		    if(command.length() > 0) {
+			// We have to test the end of command for the special character '\'. If found, remove it and append the next line, then repeat.
+			while(command.trim().endsWith("\\")) {
+			    command = command.substring(0, command.lastIndexOf("\\"));
+			    String next_line = br.readLine();
+			    if (next_line != null) {
+				command = command + "\n" + next_line;
+			    }
+			    next_line = null;
+			}
+			CommandTokenizer tokenizer = new CommandTokenizer(command, br);
+			String command_type_str = tokenizer.nextToken();
+			if (command_type_str == null) {
+			    // Bad command. Do nothing
+			    continue;
+			}
+
+			command_type_str = command_type_str.toLowerCase();
+			if(command_type_str.equals(StaticStrings.COLLECTIONMETADATA_CREATOR_STR)) {
+			    creator = tokenizer.nextToken();
+			}
+			else if(command_type_str.equals(StaticStrings.COLLECTIONMETADATA_MAINTAINER_STR)) {
+			    maintainer = tokenizer.nextToken();
+			}
+			else if(command_type_str.equalsIgnoreCase(StaticStrings.COLLECTIONMETADATA_STR)) {
+			    String meta_type_str = tokenizer.nextToken();
+			    String value_str = tokenizer.nextToken();
+			    // check for language
+			    String language_str = StaticStrings.ENGLISH_LANGUAGE_STR; // assume the no-lang ones are english, but we shouldn't really do this.
+			    if(meta_type_str != null && value_str != null) {
+				meta_type_str = meta_type_str.toLowerCase();
+				if(value_str.startsWith(StaticStrings.LBRACKET_CHARACTER) && value_str.endsWith(StaticStrings.RBRACKET_CHARACTER)) {
+				    language_str = value_str.substring(value_str.indexOf(StaticStrings.EQUALS_CHARACTER) + 1, value_str.length() - 1);
+				    language_str = language_str.toLowerCase();
+				    value_str = tokenizer.nextToken();
+				}
+				// now we can work out which coll meta we are dealing with
+				if (meta_type_str.equals(StaticStrings.COLLECTIONMETADATA_COLLECTIONNAME_STR)) {
+				    // If this is the first collection title found, then use it, otherwise search for one that more closely matches our choosen interface language
+				    if (name == null || language_str.equals(Dictionary.getLanguage())) {
+					name = Codec.transform(value_str, Codec.GREENSTONE_TO_TEXT);
+				    }
+				}
+				else if (meta_type_str.equals(StaticStrings.COLLECTIONMETADATA_COLLECTIONEXTRA_STR)) {
+				    // Again we are either looking for the first description, then after that a language specific one
+				    if (description == null || language_str.equals(Dictionary.getLanguage())) {
+					description = Codec.transform(value_str, Codec.GREENSTONE_TO_TEXT);
+				    }
+				}
+			    }
+			    language_str = null;
+			    value_str = null;
+			    meta_type_str = null;
+			} else {
+			    // we want to process all the tokens to make sure we get rid of multi line commands before trying to find the next one
+			    while (tokenizer.hasMoreTokens()) {
+			    	tokenizer.nextToken();
+			    }
+
+			} // end of coll meta bit
+			command_type_str = null;
+			tokenizer = null;
+		    } // if command.length > 0
+		} // while
+		command = null;
+		br.close();
+		isr.close();
+		br = null;
+		isr = null;
+	    } // cfg file
+	    ///ystem.err.println("Parsed collect.cfg");
+	    ///ystem.err.println("name		= " + name);
+	    ///ystem.err.println("creator	 = " + creator);
+	    ///ystem.err.println("maintainer  = " + maintainer);
+	    ///ystem.err.println("description = " + description);
+	}
+	catch(Exception error) {
+	    DebugStream.println("Error in CollectionConfiguration.<init>(): " + error);
+	    DebugStream.printStackTrace(error);
+	}
+    }
+
+    /** Compare this configuration to another for ordering, which essentially compares two strings for ordering.
+     * @param other the other Object which is presumably another basic collection configuration
+     * @return an integer which is either <0, 0 or >0 if this configuration is naturally less than, equal to or greater than the target object
+     */
+    public int compareTo(Object other) {
+	if(other == null) {
+	    return -1;
+	}
+	return toString().compareTo(other.toString());
+    }
+
+    public boolean equals(Object other) {
+	return (compareTo(other) == 0);
+    }
+
+    /** Retrieve the creators email for this collection.
+     * @return a String
+     */
+    public String getCreator() {
+	return creator;
+    }
+
+    public String getDescription() {
+	return description;
+    }
+
+    public File getFile() {
+	return file;
+    }
+    
+    public String getMaintainer() {
+	return maintainer;
+    }
+
+    public String getName() {
+	return name;
+    }
+    
+    /** Retrieve the short name for this collection which, given this current file is in <col_name>/etc/collect.cfg, is the name of this file's parent file's parent.
+     * @return the short name of this collection as a String
+     */
+    public String getShortName() {
+	return file.getParentFile().getParentFile().getName();
+    }
+    
+    /** set the site for this coll */
+    public void setSite(String site) {
+	this.site = site;
+    }
+	
+    
+    /** Display the title for this collection. */
+    public String toString() {
+	if (this.site == null) {
+	    return getName() + StaticStrings.SPACE_CHARACTER + StaticStrings.OPEN_PARENTHESIS_CHARACTER + getShortName() + StaticStrings.CLOSE_PARENTHESIS_CHARACTER;
+	} else {
+	    return getName() + StaticStrings.SPACE_CHARACTER + StaticStrings.OPEN_PARENTHESIS_CHARACTER + getShortName()+", "+this.site + StaticStrings.CLOSE_PARENTHESIS_CHARACTER;
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/Collection.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/Collection.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/Collection.java	(revision 13928)
@@ -0,0 +1,425 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.collection;
+
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.CollectionDesignManager;
+import org.greenstone.gatherer.cdm.CollectionMeta;
+import org.greenstone.gatherer.cdm.CollectionMetaManager;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.XMLTools;
+import org.w3c.dom.*;
+
+/** Collection provides a common collection point for all the information about a certain collection build session. It keeps a record of several other managers that actually handle the content of the collection, such as metadata sets and metadata itself.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3c
+ */
+public class Collection {
+    /** A reference to the Collection Design Manager. */
+    public CollectionDesignManager cdm;
+    /** A reference to the build ScriptOptions. */
+    public ScriptOptions build_options;
+    /** A reference to the import ScriptOptions. */
+    public ScriptOptions import_options;
+    /** true if an error has occurred during construction */
+    public boolean error = false;
+    /** <i>true</i> if the currently loaded collection has been saved since the last significant change, <i>false</i> otherwise. */
+    private boolean saved = false;
+    /*<i>true</i> if the currently loaded collection has had files added since its last build */
+    private boolean filesChanged = false;
+    /*<i>true</i> if the currently loaded collection has had metadata added since its last build */
+    private boolean metadataChanged = false;
+    /** The document around which this collection class is based. */
+    private Document document;
+
+     /** The file the collection is in (the file may not actually exist, such in the case of a legacy collection)! */
+     private File file;
+    /** The name of the argument element. */
+    static final private String ARGUMENT = "Argument";
+    static final private String BASE_COLLECTION = "base_collection";
+    /** The name of the build element. */
+    static final private String BUILD = "Build";
+    /** The name of the build config element. */
+    static final private String BUILD_CONFIG = "BuildConfig";
+    /** The name of the collection xml template. */
+    static final private String COLLECTION_XML_TEMPLATE = "xml/template.col";
+    /** The name of the import element. */
+    static final private String IMPORT = "Import";
+    /** The name of the imported attribute. */
+    static final private String IMPORTED = "imported";
+      /** The name of the imported attribute. */
+    static final private String SKIM_FILE = "skimfile"; 
+     
+
+    /** Constructor. */
+    public Collection(File collection_xml) {
+	this.file = collection_xml;
+	// Try to load this collections details.
+       	document = XMLTools.parseXMLFile(collection_xml);
+	// If that fails load the default settings for a collection.
+	if(document == null) {
+	    document = XMLTools.parseXMLFile(COLLECTION_XML_TEMPLATE, true);
+	}
+	if (document == null) {
+	    error = true;
+	    return;
+	}
+	// Point the Configuration class at our gatherer config arguments.
+	Configuration.setCollectionConfiguration(document);
+	if (Gatherer.g_man != null) {
+	    Gatherer.g_man.updateUI();
+	}
+	// Finally create all of the child managers that are directly dependant on a collection
+	build_options = new ScriptOptions(getBuildValues(), "buildcol.pl");
+	import_options = new ScriptOptions(getImportValues(), "import.pl");
+    }
+    
+    /** Destructor.
+     * @see org.greenstone.gatherer.Configuration
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.cdm.CollectionDesignManager
+     */
+    public void destroy() {
+	cdm.destroy();
+	Configuration.setCollectionConfiguration(null);
+	// this is called after calling collection.destroy, so we shouldn't need it here too.
+// 	if (Gatherer.g_man != null) {
+// 	    Gatherer.g_man.updateUI();
+// 	}
+	cdm = null;
+	document = null;
+    }
+    
+    /** Determine the number of documents and folders in this collection. */
+    public int getCount() {
+	return getCount((TreeNode)Gatherer.c_man.getCollectionTreeModel().getRoot(), true, true);
+    }
+    
+    /** Calculates the number of documents in this collection. */
+    public int getDocumentCount() {
+	return getCount((TreeNode)Gatherer.c_man.getCollectionTreeModel().getRoot(), false, true);
+    }
+    
+    /** Retrieve the description of this collection.
+     * @return a String
+     */
+    public String getDescription() {
+	if(cdm == null) {
+	    return StaticStrings.EMPTY_STR;
+	}
+	CollectionMeta collection_extra_collectionmeta = cdm.collectionmeta_manager.getMetadatum(StaticStrings.COLLECTIONMETADATA_COLLECTIONEXTRA_STR);
+	return collection_extra_collectionmeta.getValue(CollectionMeta.TEXT);
+    }
+    
+    /** Retrieve the authors email for this collection.
+     * @return The email as a <strong>String</strong>.
+     */
+    public String getEmail() {
+	if(cdm == null) {
+	    return StaticStrings.EMPTY_STR;
+	}
+	CollectionMeta creator_collectionmeta = new CollectionMeta(CollectionDesignManager.collect_config.getCreator());
+	return creator_collectionmeta.getValue(CollectionMeta.TEXT);
+    }
+
+    /** Retrieve the short name for this collection.
+     * @return The name as a <strong>String</strong>.
+     */
+    public String getName() {
+	return file.getParentFile().getName();
+    }
+    
+    /** Determine if this collection has been saved since the last major change.
+     * @return <i>true</i> if it has been saved recently, <i>false</i> otherwise.
+     */
+    public boolean getSaved() {
+	return saved;
+    }
+
+    /** Determine if this collection has had its collection files changed since the last build.
+     * @return <i>true</i> if they have been saved, <i>false</i> otherwise.
+     */
+    public boolean getFilesChanged() {
+	return filesChanged;
+    }
+    
+    /** Set the flag that marks weather or not the files has been changed since the last build.
+	@param changed if files has been added/removed, as a <strong>boolean</strong>
+    */
+    public void setFilesChanged(boolean changed) {
+	filesChanged = changed;
+    }
+
+    /** Determine if this collection has had metadata changed since the last build.
+     * @return <i>true</i> if it has been changed, <i>false</i> otherwise.
+     */
+    public boolean getMetadataChanged() {
+	return metadataChanged;
+    }
+    
+    /** Set the flag that marks weather or not the metadata has been changed since the last build.
+	@param changed if metadata has been added/changed/removed, as a <strong>boolean</strong>
+    */
+    public void setMetadataChanged(boolean changed) {
+	metadataChanged = changed;
+    }
+
+    /** Retrieve the title of this collection.
+     * @return The title as a <strong>String</strong>.
+     */
+    public String getTitle() {
+	if(cdm == null) {
+	    return StaticStrings.EMPTY_STR;
+	}
+	CollectionMeta collection_name_collectionmeta = cdm.collectionmeta_manager.getMetadatum(StaticStrings.COLLECTIONMETADATA_COLLECTIONNAME_STR);
+	return collection_name_collectionmeta.getValue(CollectionMeta.TEXT);
+    }
+
+    /** Save this xml document to the given file. */
+    public void save() {
+	XMLTools.writeXMLFile(file, document);
+	saved = true;
+    }
+
+    public void setBaseCollection(String base_collection) {
+	set(BASE_COLLECTION, base_collection);
+    }
+    
+    /** Set the value of imported to the given value.
+     * @param value The new value for imported, <i>true</i> if the collection has been imported successfully, <i>false</i> otherwise.
+     */
+    public void setImported(boolean value) {
+	set(IMPORTED, value);
+	saved = false;
+    }
+
+    /** Set the value of saved to the given value.
+     * @param value The new value for saved, <i>true</i> if the collection has been saved recently, <i>false</i> otherwise.
+     */
+    public void setSaved(boolean value) {
+	saved = value;
+    }
+
+    /** Set the value of title to the given value.
+     * @param title The new <strong>String</strong> title.
+     */
+    public void setTitle(String title) {
+	if(cdm != null) {
+	    CollectionMeta collection_name_collectionmeta = cdm.collectionmeta_manager.getMetadatum(StaticStrings.COLLECTIONMETADATA_COLLECTIONNAME_STR);
+	    collection_name_collectionmeta.setValue(title);
+	}
+    }
+
+    /** Method called to return a textual representation of a class, which in this case is the collections title.
+     * @return A <strong>String</strong> containing the collections title.
+     */
+    public String toString() {
+	return getTitle();
+    }
+ 
+    public boolean toSkimFile(){
+	 Element document_element = document.getDocumentElement();
+	 NodeList arguments = document_element.getElementsByTagName(ARGUMENT);
+          for(int i = 0;  i < arguments.getLength(); i++) {
+	      Element argument_element = (Element) arguments.item(i);
+              if(argument_element.getAttribute(StaticStrings.NAME_ATTRIBUTE).equalsIgnoreCase(SKIM_FILE)) {
+		  String skimfile = XMLTools.getValue(argument_element); 
+		  if (skimfile !=null && skimfile.trim().toLowerCase().equals("false")){
+		      return false;
+		  } 
+	      }
+	     
+	  }
+	  
+	  return true;
+    }
+
+    
+    /** Get the value of a collection argument. */
+    private boolean get(String name) {
+	boolean result = false;
+	try {
+	    Element document_element = document.getDocumentElement();
+	    NodeList arguments = document_element.getElementsByTagName(ARGUMENT);
+	    boolean found = false;
+	    for(int i = 0; !found && i < arguments.getLength(); i++) {
+		Element argument_element = (Element) arguments.item(i);
+		if(argument_element.getParentNode() == document_element) {
+		    if(argument_element.getAttribute(StaticStrings.NAME_ATTRIBUTE).equalsIgnoreCase(name)) {
+			String value = XMLTools.getValue(argument_element);
+			if(value.equalsIgnoreCase(StaticStrings.TRUE_STR)) {
+			    result = true;
+			}
+			found = true;
+			value = null;
+		    }
+		}
+		argument_element = null;
+	    }
+	    arguments = null;
+	    document_element = null;
+	}
+	catch (Exception error) {
+	    DebugStream.printStackTrace(error);
+	}
+	return result;
+    }
+    
+    /** Get the value of a collection argument. */
+    private String getString(String name) {
+	String result = "";
+	try {
+	    Element document_element = document.getDocumentElement();
+	    NodeList arguments = document_element.getElementsByTagName(ARGUMENT);
+	    boolean found = false;
+	    for(int i = 0; !found && i < arguments.getLength(); i++) {
+		Element argument_element = (Element) arguments.item(i);
+		if(argument_element.getParentNode() == document_element) {
+		    if(argument_element.getAttribute(StaticStrings.NAME_ATTRIBUTE).equalsIgnoreCase(name)) {
+			result = XMLTools.getValue(argument_element);
+			found = true;
+		    }
+		}
+		argument_element = null;
+	    }
+	    arguments = null;
+	    document_element = null;
+	}
+	catch (Exception error) {
+	    DebugStream.printStackTrace(error);
+	}
+	return result;
+    }
+
+    
+
+    
+    /** Method to retrieve the current build options associated with this Collection. */
+    private Element getBuildValues() {
+	Element build_values_element = null;
+	try {
+	    Element document_element = document.getDocumentElement();
+	    Element build_config_element = (Element) XMLTools.getNodeFromNamed(document_element, BUILD_CONFIG);
+	    build_values_element = (Element) XMLTools.getNodeFromNamed(build_config_element, BUILD);
+	    build_config_element = null;
+	    document_element = null;
+	}
+	catch (Exception error) {
+	    DebugStream.printStackTrace(error);
+	}
+	return build_values_element;
+    }
+    
+    /** Count either documents or folders, depending on the state of the given boolean. */
+    private int getCount(TreeNode node, boolean count_folders, boolean count_files) {
+	int count = 0;
+	File file = ((CollectionTreeNode)node).getFile();
+	if(file.isFile() && count_files) {
+	    count++;
+	}
+	else if(file.isDirectory() && count_folders) {
+	    count++;
+	}
+	for(int i = 0; !file.getName().equals("CVS") && i < node.getChildCount(); i++) {
+	    count = count + getCount(node.getChildAt(i), count_folders, count_files);
+	}
+	return count;
+    }
+    
+    /** Method to retrieve the current import options associated with this Collection. */
+    public Element getImportValues() {
+	Element import_values_element = null;
+	try {
+	    Element document_element = document.getDocumentElement();
+	    Element build_config_element = (Element) XMLTools.getNodeFromNamed(document_element, BUILD_CONFIG);
+	    import_values_element = (Element) XMLTools.getNodeFromNamed(build_config_element, IMPORT);
+	    build_config_element = null;
+	    document_element = null;
+	}
+	catch (Exception error) {
+	    DebugStream.printStackTrace(error);
+	}
+	return import_values_element;
+    }
+    
+    /** Set the value of a collection argument. */
+    private void set(String name, boolean value) {
+	set(name, (value ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
+    }
+    
+    private void set(String name, String value) {
+	try {
+	    Element document_element = document.getDocumentElement();
+	    NodeList arguments = document_element.getElementsByTagName(ARGUMENT);
+	    boolean found = false;
+	    for(int i = 0; !found && i < arguments.getLength(); i++) {
+		Element argument_element = (Element) arguments.item(i);
+		if(argument_element.getParentNode() == document_element) {
+		    if(argument_element.getAttribute(StaticStrings.NAME_ATTRIBUTE).equalsIgnoreCase(name)) {
+			// Strip any current value nodes.
+			while(argument_element.hasChildNodes()) {
+			    argument_element.removeChild(argument_element.getFirstChild());
+			}
+			// Append new value
+			argument_element.appendChild(document.createTextNode(value));
+			found = true;
+		    }
+		}
+		argument_element = null;
+	    }
+	    // Append it
+	    if(!found) {
+		Element argument_element = document.createElement(ARGUMENT);
+		argument_element.setAttribute(StaticStrings.NAME_ATTRIBUTE, name);
+		argument_element.appendChild(document.createTextNode(value));
+		document_element.appendChild(argument_element);
+		argument_element = null;
+	    }
+	    arguments = null;
+	    document_element = null;
+	}
+	catch (Exception error) {
+	    DebugStream.printStackTrace(error);
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/CollectionContentsChangedListener.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/CollectionContentsChangedListener.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/CollectionContentsChangedListener.java	(revision 13928)
@@ -0,0 +1,37 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2004 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.collection;
+
+
+import java.io.File;
+
+
+public interface CollectionContentsChangedListener
+{
+    /** Notification that a new file has been added to the collection. */
+    public void fileAddedToCollection(File file);
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/CollectionManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/CollectionManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/CollectionManager.java	(revision 13928)
@@ -0,0 +1,1600 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.collection;
+
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.filechooser.FileSystemView;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.CollectionDesignManager;
+import org.greenstone.gatherer.cdm.CollectionMeta;
+import org.greenstone.gatherer.cdm.CollectionMetaManager;
+import org.greenstone.gatherer.cdm.CommandTokenizer;
+import org.greenstone.gatherer.greenstone.Classifiers;
+import org.greenstone.gatherer.greenstone.LocalGreenstone;
+import org.greenstone.gatherer.greenstone.LocalLibraryServer;
+import org.greenstone.gatherer.greenstone.Plugins;
+import org.greenstone.gatherer.greenstone3.ServletConfiguration;
+import org.greenstone.gatherer.gui.LockFileDialog;
+import org.greenstone.gatherer.gui.ModalProgressPopup;
+import org.greenstone.gatherer.gui.WarningDialog;
+import org.greenstone.gatherer.metadata.DocXMLFileManager;
+import org.greenstone.gatherer.metadata.MetadataChangedListener;
+import org.greenstone.gatherer.metadata.MetadataSet;
+import org.greenstone.gatherer.metadata.MetadataSetManager;
+import org.greenstone.gatherer.metadata.MetadataXMLFileManager;
+import org.greenstone.gatherer.metadata.ProfileXMLFileManager;
+import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
+import org.greenstone.gatherer.shell.GShell;
+import org.greenstone.gatherer.shell.GShellEvent;
+import org.greenstone.gatherer.shell.GShellListener;
+import org.greenstone.gatherer.shell.GShellProgressMonitor;
+import org.greenstone.gatherer.util.Codec;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.util.XMLTools;
+import org.w3c.dom.*;
+
+/** This class manages many aspects of the collection, from its creation via scripts, data access via methods and its importing and building into the final collection. It is also resposible for firing appropriate event when significant changes have occured within the collection, and for creating a new metadata set manager as necessary.
+ * @author John Thompson
+ * @version 2.3
+ */
+public class CollectionManager
+    implements GShellListener, MetadataChangedListener
+{
+    /** Are we currently in the process of building? */
+    static private boolean building = false;
+    /** Are we currently in the process of importing? */
+    static private boolean importing = false;
+    /** The objects listening for CollectionContentsChanged events. */
+    static private ArrayList collection_contents_changed_listeners = new ArrayList();
+    /** The collection this manager is managing! */
+    static private Collection collection = null;
+    /** The collection tree (used in both Gather and Enrich panes). */
+    static private CollectionTree collection_tree = null;
+    /** The collection tree model. */
+    static private CollectionTreeModel collection_tree_model = null;
+    /** An inner class listener responsible for noting tree changes and resetting saved when they occur. */
+    static private FMTreeModelListener fm_tree_model_listener = null;
+    /** The monitor resposible for parsing the build process. */
+    static private GShellProgressMonitor build_monitor = null;
+    /** The monitor resposible for parsing the import process. */
+    static private GShellProgressMonitor import_monitor = null;
+
+    /** The name of the standard lock file. */
+    static final public String LOCK_FILE = "gli.lck";
+
+    /** Used to indicate the source of the message is the file collection methods. */
+    static final public int COLLECT   = 3;
+    /** Used to indicate the source of the message is the building methods. */
+    static final public int BUILDING  = 5;
+
+  
+    /** Constructor. */
+    public CollectionManager() {
+	// Initialisation.
+	this.building = false;
+	this.importing = false;
+	this.collection = null;
+
+	MetadataXMLFileManager.addMetadataChangedListener(this);
+
+	// If using a remote Greenstone server, delete the local collect directory because it will be out of date
+	if (Gatherer.isGsdlRemote) {
+	    System.err.println("Deleting user's local collect directory...");
+	    Utility.delete(new File(Gatherer.getCollectDirectoryPath()));
+	    System.err.println("Done.");
+	    new File(Gatherer.getCollectDirectoryPath()).mkdirs();
+	}
+    }
+
+
+    static public void addCollectionContentsChangedListener(CollectionContentsChangedListener listener)
+    {
+	collection_contents_changed_listeners.add(listener);
+    }
+
+
+    /** This method calls the builcol.pl scripts via a GShell so as to not lock up the processor.
+     * @see org.greenstone.gatherer.Configuration
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.collection.Collection
+     * @see org.greenstone.gatherer.gui.BuildOptions
+     * @see org.greenstone.gatherer.shell.GShell
+     * @see org.greenstone.gatherer.shell.GShellListener
+     * @see org.greenstone.gatherer.shell.GShellProgressMonitor
+     * @see org.greenstone.gatherer.util.Utility
+     */
+    public void buildCollection(boolean incremental_build)
+    {
+          
+	DebugStream.println("In CollectionManager.buildCollection(), incremental_build: " + incremental_build);
+	DebugStream.println("Is event dispatch thread: " + SwingUtilities.isEventDispatchThread());
+	building = true;
+
+	// Generate the buildcol.pl command
+	ArrayList command_parts_list = new ArrayList();
+	if ((Utility.isWindows()) && (!Gatherer.isGsdlRemote)) {
+	    command_parts_list.add(Configuration.perl_path);
+	    command_parts_list.add("-S");
+	}
+	command_parts_list.add(LocalGreenstone.getBinScriptDirectoryPath() + "buildcol.pl");
+	command_parts_list.add("-gli");
+	command_parts_list.add("-language");
+	command_parts_list.add(Configuration.getLanguage());
+	command_parts_list.add("-collectdir");
+	command_parts_list.add(getCollectDirectory());
+
+	// If the user hasn't manually specified "-keepold" or "-removeold" then pick one based on incremental_build
+	if (!collection.build_options.getValueEnabled("keepold") && !collection.build_options.getValueEnabled("removeold")) {
+	    command_parts_list.add(incremental_build ? "-keepold" : "-removeold");
+	}
+
+	String[] build_options = collection.build_options.getValues();
+	for (int i = 0; i < build_options.length; i++) {
+	    command_parts_list.add(build_options[i]);
+	}
+
+	command_parts_list.add(collection.getName());
+
+	// Run the buildcol.pl command
+	String[] command_parts = (String[]) command_parts_list.toArray(new String[0]);
+	GShell shell = new GShell(command_parts, GShell.BUILD, BUILDING, this, build_monitor, GShell.GSHELL_BUILD);
+	shell.addGShellListener(Gatherer.g_man.create_pane);
+	shell.addGShellListener(Gatherer.g_man.format_pane);
+	shell.start();
+	
+    }
+
+
+    /** Used to determine whether the currently active collection has been built.
+     * @return A boolean indicating the built status of the collection.
+     */
+    public boolean built() {
+	if(collection != null) {
+	    // Determine if the collection has been built by looking for the build.cfg file
+	    File build_cfg_file = new File(getLoadedCollectionIndexDirectoryPath() + "build.cfg");
+	    return build_cfg_file.exists();
+	}
+	return false;
+    }
+
+
+    /** a test method to see if we can delete a directory/file - returns false is the file or any of the contents of a directory cannot be deleted */
+    static private boolean canDelete(File file)
+    {
+	if (!file.isDirectory()) {
+	    return file.canWrite();
+	}
+	File [] file_list = file.listFiles();
+	for (int i=0; i<file_list.length; i++) {
+	    if (!canDelete(file_list[i])) {
+		return false;
+	    }
+	}
+	return true;
+    }
+
+
+    /** Called to close the current collection and remove its lock file.
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.collection.Collection
+     * @see org.greenstone.gatherer.util.Utility
+     */
+    public void closeCollection() {
+	DebugStream.println("Close collection: " + collection.getName());
+
+	// Remove the lock on this file, then remove the collection.
+	File lock_file = new File(getLoadedCollectionDirectoryPath() + LOCK_FILE);
+	lock_file.delete();
+	if (lock_file.exists()) {
+	    System.err.println("Warning: Lockfile was not successfully deleted.");
+	}
+
+	// Remove the lock file on the server
+	if (Gatherer.isGsdlRemote) {
+	    RemoteGreenstoneServer.deleteCollectionFile(collection.getName(), lock_file);
+	}
+
+	MetadataSetManager.clearMetadataSets();
+	MetadataXMLFileManager.clearMetadataXMLFiles();
+	DocXMLFileManager.clearDocXMLFiles();
+	ProfileXMLFileManager.clearProfileXMLFile();
+
+	collection.destroy();
+	collection = null;
+	collection_tree_model = null;
+	//Configuration.setCollectionConfiguration(null);
+	Gatherer.refresh(Gatherer.COLLECTION_CLOSED);
+	if (Gatherer.g_man != null) {
+	    Gatherer.g_man.updateUI();  // !!! Necessary?
+	}
+    }
+
+
+    public void convertToGS3Collection() {
+	// Generate the convert_coll_from_gs2.pl command
+	ArrayList command_parts_list = new ArrayList();
+	if ((Utility.isWindows()) && (!Gatherer.isGsdlRemote)) {
+	    command_parts_list.add(Configuration.perl_path);
+	    command_parts_list.add("-S");
+	}
+	command_parts_list.add(Configuration.getGS3ScriptPath() + "convert_coll_from_gs2.pl");
+	command_parts_list.add("-collectdir");
+	command_parts_list.add(getCollectDirectory());
+    	command_parts_list.add(collection.getName());
+
+	// Run the convert_coll_from_gs2.pl command
+	String[] command_parts = (String[]) command_parts_list.toArray(new String[0]);
+	GShell process = new GShell(command_parts, GShell.CONVERT, COLLECT, this, null, GShell.GSHELL_CONVERT);
+	process.addGShellListener(this);
+	process.run(); // Don't bother threading this... yet
+       
+    }
+
+    /** When basing a new collection on an existing one, we need to copy 
+     *	over some extra directories: images and macros  
+     */
+    private boolean copyExtraBaseCollStuff(File new_coll_dir, File base_coll_dir) {
+	if (!new_coll_dir.isDirectory() || !base_coll_dir.isDirectory()) {
+	    return false;
+	}
+	DebugStream.println("Copying images and macros dirs from the base collection");
+	try {
+	    // do the images dir
+	    File base_coll_images = new File(base_coll_dir, "images");
+	    if (base_coll_images.isDirectory()) {
+		// copy all the images over
+		File new_coll_images = new File(new_coll_dir, "images");
+		new_coll_images.mkdirs();
+		
+		// copy the contents over
+		Gatherer.f_man.getQueue().copyDirectoryContents(base_coll_images, new_coll_images);
+	    }
+	}
+	catch (Exception e) {
+	    DebugStream.println("Couldn't copy over the images dir from the base collection: "+e.toString());
+	}
+	try {
+	    // do the macros dir
+	    File base_coll_macros = new File(base_coll_dir, "macros");
+	    if (base_coll_macros.isDirectory()) {
+		// copy all the macros over
+		File new_coll_macros = new File(new_coll_dir, "macros");
+		new_coll_macros.mkdirs();
+		
+		// copy the contents over
+		Gatherer.f_man.getQueue().copyDirectoryContents(base_coll_macros, new_coll_macros);
+	    } 
+	}
+	catch (Exception e) {
+	    DebugStream.println("Couldn't copy over the macros dir from the base collection: "+e.toString());
+	}
+	return true;
+    }
+
+    /** Used to set the current collection to the given collection. Note that this call should -always- be proceeded by a ready call, and if the collection is ready and the saved flag is unset then the user should be prompted to save. Also note that this method creates yet another GShell to run buildcol.pl.
+     * @param description a description of the collection as a String
+     * @param email the email address of the author/maintainer as a String
+     * @param name the short name of the collection, which will subsequently be used to refer to this particular collection, as a String
+     * @param title the longer title of the collection as a String
+     * @param base_collection_directory if the user has chosen to base their new collection on an existing one, this is the directory where this base collection can be found, as a File, otherwise its null
+     * @param metadata_sets if the user has decided to select several metadata sets with which to initially populate the GLI then this is an ArrayList of metadata set file names, otherwise its null
+     */
+    public void createCollection(String description, String email, String name, String title, File base_collection_directory, ArrayList metadata_sets)
+    {
+	// Display a modal progress popup to indicate that the collection is being loaded
+	ModalProgressPopup create_collection_progress_popup = new ModalProgressPopup(Dictionary.get("CollectionManager.Creating_Collection"), Dictionary.get("CollectionManager.Creating_Collection_Please_Wait"));
+	create_collection_progress_popup.display();
+
+	// Create the collection on a separate thread so the progress bar updates correctly
+	(new CreateCollectionTask(description, email, name, title, base_collection_directory, metadata_sets, create_collection_progress_popup)).start();
+    }
+
+
+    private class CreateCollectionTask
+	extends Thread
+    {
+	private String description = null;
+	private String email = null;
+	private String name = null;
+	private String title = null;
+	private File base_collection_directory = null;
+	private ArrayList metadata_sets = null;
+	private ModalProgressPopup create_collection_progress_popup = null;
+
+	public CreateCollectionTask(String description, String email, String name, String title, File base_collection_directory, ArrayList metadata_sets, ModalProgressPopup create_collection_progress_popup)
+	{
+	    this.description = description;
+	    this.email = email;
+	    this.name = name;
+	    this.title = title;
+	    this.base_collection_directory = base_collection_directory;
+	    this.metadata_sets = metadata_sets;
+	    this.create_collection_progress_popup = create_collection_progress_popup;
+	}
+
+	public void run()
+	{
+	    createCollectionInternal(description, email, name, title, base_collection_directory, metadata_sets);
+	    create_collection_progress_popup.close();
+	}
+    }
+
+
+    private void createCollectionInternal(String description, String email, String name, String title, File base_collection_directory, ArrayList metadata_sets)
+    {
+	try {
+	    // first make sure that the collect directory exists
+	    File collect_dir = new File(getCollectDirectory());
+	    if (!collect_dir.exists()) {
+		collect_dir.mkdirs();
+	    }
+
+	    // Create the new collection
+	    makeCollection(name, email);
+
+	    // Check that the collection has been created successfully
+	    String collection_directory_path = getCollectionDirectoryPath(name);
+	    if (!new File(collection_directory_path).exists()) {
+		// If there is no collection directory then the creation was unsuccessful, or cancelled
+		System.err.println("No collection directory...");
+		return;
+	    }
+
+	    // Check for the existence of the collect.cfg file
+	    File collect_cfg_file = new File(collection_directory_path + "etc" + File.separator + "collect.cfg");
+	    if (!collect_cfg_file.exists()) {
+		System.err.println("Error: no collect.cfg file has been created!");
+		JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CollectionManager.Cannot_Create_Collection_With_Reason", Dictionary.get("CollectionManager.No_Config_File")), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE); 
+		return;
+	    }
+ 	    
+	    // ACTIVE_DIR/log/
+	    File log_dir = new File(collection_directory_path + "log");
+	    log_dir.mkdirs();
+
+	    // Make sure an import folder exists
+	    File collection_import_directory = new File(collection_directory_path + "import");
+	    if (!collection_import_directory.exists()) {
+		collection_import_directory.mkdirs();
+		if (Gatherer.isGsdlRemote) {
+		    RemoteGreenstoneServer.newCollectionDirectory(name, collection_import_directory);
+		}
+	    }
+
+	    // Now create the collection object around the directory.
+	    collection = new Collection(new File(collection_directory_path, name + ".col"));
+
+	    // "-removeold" is on by default for import.pl
+	    collection.import_options.setValue("removeold", true, null);
+
+	    MetadataSetManager.clearMetadataSets();
+	    MetadataXMLFileManager.clearMetadataXMLFiles();
+	    DocXMLFileManager.clearDocXMLFiles();
+
+	    // Import default metadata sets, if any
+	    // for (int i = 0; metadata_sets != null && i < metadata_sets.size(); i++) {
+	    // importMetadataSet((MetadataSet) metadata_sets.get(i));
+	    // }
+
+	    ProfileXMLFileManager.loadProfileXMLFile(new File(collection_directory_path + "metadata"));
+
+	    // Before creating the CollectionDesignManager check if we are basing it upon some other collection
+	    if (base_collection_directory != null) {
+		DebugStream.println("Basing new collection on existing one: " + base_collection_directory);
+
+		// If we're using a remote Greenstone server, download the collection shell to get the files needed
+		if (Gatherer.isGsdlRemote) {
+		    String base_collection_name = base_collection_directory.getName();
+		    RemoteGreenstoneServer.downloadCollection(base_collection_name);
+		}
+
+		collection.setBaseCollection(base_collection_directory.getAbsolutePath());
+		// copy over other needed directories
+		copyExtraBaseCollStuff(new File(collection_directory_path), base_collection_directory);
+
+		// Try to import any existing metadata sets for this collection
+		// Look in base_collection_directory/metadata and import any metadata sets found.
+		File base_metadata_directory = new File(base_collection_directory, "metadata");
+		ArrayList base_metadata_sets = MetadataSetManager.listMetadataSets(base_metadata_directory);
+		if (base_metadata_sets != null) {
+		    for (int i = 0; i < base_metadata_sets.size(); i++) {
+			importMetadataSet((MetadataSet) base_metadata_sets.get(i));
+		    }
+		}
+		else {
+		    DebugStream.println("This base collection has no metadata directory.");
+		}
+
+		// Now we update our collect.cfg
+		DebugStream.println("Copy and update collect.cfg from base collection.");
+		updateCollectionCFG(new File(base_collection_directory, Utility.CONFIG_FILE), new File(collection_directory_path, Utility.CONFIG_FILE), description, email, title);
+	    }
+
+	    // Load the default metadata sets
+	    addDefaultMetadataSets();
+
+	    // Make sure we always have the extracted metadata set
+	    addRequiredMetadataSets();
+
+	    collection.cdm = new CollectionDesignManager(new File(getLoadedCollectionCfgFilePath()));
+
+	    // We always set title and description here rather than calling mkcol.pl with Unicode arguments
+	    CollectionMeta collection_name_collectionmeta = collection.cdm.collectionmeta_manager.getMetadatum(StaticStrings.COLLECTIONMETADATA_COLLECTIONNAME_STR);
+	    collection_name_collectionmeta.setValue(title);
+	    CollectionMeta collection_extra_collectionmeta = collection.cdm.collectionmeta_manager.getMetadatum(StaticStrings.COLLECTIONMETADATA_COLLECTIONEXTRA_STR);
+	    collection_extra_collectionmeta.setValue(description);
+
+	    // Now that we have a CDM, update several settings, such as if we created this collection by basing it on another, set it as public automatically
+	    if (base_collection_directory != null) {
+		// Update the creator and maintainer
+		CollectionMeta creator_collectionmeta = new CollectionMeta(collection.cdm.collect_config.getCreator());
+		creator_collectionmeta.setValue(email);
+		creator_collectionmeta = null;
+		CollectionMeta maintainer_collectionmeta = new CollectionMeta(collection.cdm.collect_config.getMaintainer());
+		maintainer_collectionmeta.setValue(email);
+		maintainer_collectionmeta = null;
+
+		// All collections based on others are automatically public
+		CollectionMeta public_collectionmeta = new CollectionMeta(collection.cdm.collect_config.getPublic());
+		public_collectionmeta.setValue(StaticStrings.TRUE_STR);
+		public_collectionmeta = null;
+
+		// Finally reset the icons
+		CollectionMeta icon_collection_collectionmeta = collection.cdm.collectionmeta_manager.getMetadatum(StaticStrings.COLLECTIONMETADATA_ICONCOLLECTION_STR);
+		icon_collection_collectionmeta.setValue(StaticStrings.EMPTY_STR);
+		icon_collection_collectionmeta = null;
+		CollectionMeta icon_collection_small_collectionmeta = collection.cdm.collectionmeta_manager.getMetadatum(StaticStrings.COLLECTIONMETADATA_ICONCOLLECTIONSMALL_STR);
+		icon_collection_small_collectionmeta.setValue(StaticStrings.EMPTY_STR);
+		icon_collection_small_collectionmeta = null;
+	    }
+
+	    saveCollection();
+
+	    // Create a lock file
+	    createLockFile(new File(collection_directory_path, LOCK_FILE));
+
+	    // We're done. Let everyone know.
+	    Gatherer.refresh(Gatherer.COLLECTION_OPENED);
+	}
+	catch (Exception error) {
+	    DebugStream.printStackTrace(error);
+	}
+    }
+
+
+    private void createLockFile(File lock_file)
+    {
+	try {
+	    Document default_lockfile = XMLTools.parseXMLFile("xml/" + LOCK_FILE, true);
+	    String user_name = System.getProperty("user.name");
+	    Element person_element = (Element) XMLTools.getNodeFromNamed(default_lockfile.getDocumentElement(), "User");
+	    person_element.appendChild(default_lockfile.createTextNode(user_name));
+	    person_element = null;
+	    user_name = null;
+	    String machine_name = Utility.getMachineName();
+	    Element machine_element = (Element) XMLTools.getNodeFromNamed(default_lockfile.getDocumentElement(), "Machine");
+	    machine_element.appendChild(default_lockfile.createTextNode(machine_name));
+	    machine_element = null;
+	    machine_name = null;
+	    String date_time = Utility.getDateString();
+	    Element date_element = (Element) XMLTools.getNodeFromNamed(default_lockfile.getDocumentElement(), "Date");
+	    date_element.appendChild(default_lockfile.createTextNode(date_time));
+	    date_element = null;
+	    date_time = null;
+	    XMLTools.writeXMLFile(lock_file, default_lockfile);
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+    }
+
+
+    public boolean deleteCollection(String collection_name)
+    {
+	// First we must release the collection from the local library, if it's running
+	if (LocalLibraryServer.isRunning() == true) {
+	    LocalLibraryServer.releaseCollection(collection_name);
+	}
+
+	// Delete the collection on the server if we're using a remote Greenstone
+	if (Gatherer.isGsdlRemote) {
+	    RemoteGreenstoneServer.deleteCollection(collection_name);
+	}
+
+	// Now delete the collection directory
+	return Utility.delete(new File(getCollectionDirectoryPath(collection_name)));
+    }
+
+
+    public void fireFileAddedToCollection(File file)
+    {
+	// Send the event off to all the CollectionContentsChangedListeners
+	for (int i = 0; i < collection_contents_changed_listeners.size(); i++) {
+	    ((CollectionContentsChangedListener) collection_contents_changed_listeners.get(i)).fileAddedToCollection(file);
+	}
+    }
+
+
+    /** Retrieve the current collection.
+     * @return The <strong>Collection</strong> itself.
+     */
+    public Collection getCollection() {
+	return collection;
+    }
+
+
+    /** Returns the absolute filename of the specified collection's directory.
+     */
+    static public String getCollectionDirectoryPath(String collection_name)
+    {
+	return Gatherer.getCollectDirectoryPath() + collection_name + File.separator;
+    }
+
+
+    /** Returns the absolute filename of the loaded collection's archives directory.
+     */
+    static public String getLoadedCollectionArchivesDirectoryPath()
+    {
+	return getLoadedCollectionDirectoryPath() + "archives" + File.separator;
+    }
+
+
+    /** Returns the absolute filename of the loaded collection's building directory.
+     */
+    static public String getLoadedCollectionBuildingDirectoryPath()
+    {
+	return getLoadedCollectionDirectoryPath() + "building" + File.separator;
+    }
+
+
+    /** Returns the absolute filename of the loaded collection's collect.cfg file.
+     */
+    static public String getLoadedCollectionCfgFilePath()
+    {
+	return getLoadedCollectionEtcDirectoryPath() + "collect.cfg";
+    }
+
+
+    /** Returns the absolute filename of the loaded collection's directory.
+     */
+    static public String getLoadedCollectionDirectoryPath()
+    {
+	return Gatherer.getCollectDirectoryPath() + collection.getName() + File.separator;
+    }
+
+
+    /** Returns the absolute filename of the loaded collection's etc directory.
+     */
+    static public String getLoadedCollectionEtcDirectoryPath()
+    {
+	return getLoadedCollectionDirectoryPath() + "etc" + File.separator;
+    }
+
+
+    /** Returns the absolute filename of the loaded collection's .col file.
+     */
+    static public String getLoadedCollectionColFilePath()
+    {
+	return getLoadedCollectionDirectoryPath() + collection.getName() + ".col";
+    }
+
+
+    /** Returns the absolute filename of the loaded collection's images directory.
+     */
+    static public String getLoadedCollectionImagesDirectoryPath()
+    {
+	return getLoadedCollectionDirectoryPath() + "images" + File.separator;
+    }
+
+
+    /** Returns the absolute filename of the loaded collection's import directory.
+     */
+    static public String getLoadedCollectionImportDirectoryPath()
+    {
+	return getLoadedCollectionDirectoryPath() + "import" + File.separator;
+    }
+
+
+    /** Returns the absolute filename of the loaded collection's index directory.
+     */
+    static public String getLoadedCollectionIndexDirectoryPath()
+    {
+	return getLoadedCollectionDirectoryPath() + "index" + File.separator;
+    }
+
+
+    /** Returns the absolute filename of the loaded collection's log directory.
+     */
+    static public String getLoadedCollectionLogDirectoryPath()
+    {
+	return getLoadedCollectionDirectoryPath() + "log" + File.separator;
+    }
+
+
+    /** Returns the absolute filename of the loaded collection's macros directory.
+     */
+    static public String getLoadedCollectionMacrosDirectoryPath()
+    {
+	return getLoadedCollectionDirectoryPath() + "macros" + File.separator;
+    }
+
+
+    /** Returns the absolute filename of the loaded collection's metadata directory.
+     */
+    static public String getLoadedCollectionMetadataDirectoryPath()
+    {
+	return getLoadedCollectionDirectoryPath() + "metadata" + File.separator;
+    }
+
+
+    /** Returns the name of the loaded collection.
+     */
+    static public String getLoadedCollectionName()
+    {
+	if (collection != null) {
+	    return collection.getName();
+	}
+
+	return null;
+    }
+
+
+    public CollectionTree getCollectionTree()
+    {
+	if (collection_tree == null) {
+	    collection_tree = new CollectionTree(collection_tree_model, true);
+	}
+
+	return collection_tree;
+    }
+
+
+    /** Retrieve the tree model associated with the current collection. */
+    public CollectionTreeModel getCollectionTreeModel()
+    {
+	if (collection_tree_model == null && collection != null) {
+	    // Use the import directory to generate a new CollectionTreeModel
+	    collection_tree_model = new CollectionTreeModel(new CollectionTreeNode(new File(getLoadedCollectionImportDirectoryPath())));
+	    // Ensure that the manager is a change listener for the tree.
+	    if (fm_tree_model_listener == null) {
+		fm_tree_model_listener = new FMTreeModelListener();
+	    }
+	    collection_tree_model.addTreeModelListener(fm_tree_model_listener);
+	}
+	return collection_tree_model;
+    }
+
+
+    /** This method when called, creates a new GShell in order to run the import.pl script.
+     * @see org.greenstone.gatherer.Configuration
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.gui.BuildOptions
+     * @see org.greenstone.gatherer.shell.GShell
+     * @see org.greenstone.gatherer.shell.GShellListener
+     * @see org.greenstone.gatherer.shell.GShellProgressMonitor
+     * @see org.greenstone.gatherer.util.Utility
+     */
+    public void importCollection() {
+	importing = true;
+
+	if (!saved()) {
+	    DebugStream.println("CollectionManager.importCollection().forcesave");
+	    import_monitor.saving();
+	    saveCollection();
+	}
+
+	DebugStream.println("CollectionManager.importCollection()");
+	DebugStream.println("Is event dispatch thread: " + SwingUtilities.isEventDispatchThread());
+	//check that we can remove the old index before starting import
+	File index_dir = new File(getLoadedCollectionIndexDirectoryPath());
+	if (index_dir.exists()) {
+	    DebugStream.println("Old Index = " + index_dir.getAbsolutePath()+", testing for deletability");
+	    if (!canDelete(index_dir)) {
+		// tell the user
+		JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CollectionManager.Cannot_Delete_Index"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE); 
+		// tell the gui manager
+		// a message for the building log 
+		GShellEvent event = new GShellEvent(this, 0, GShell.IMPORT, Dictionary.get("CollectionManager.Cannot_Delete_Index_Log"), GShell.ERROR);
+		Gatherer.g_man.create_pane.message(event);
+		event = new GShellEvent(this, 0, GShell.IMPORT, "", GShell.ERROR);
+		Gatherer.g_man.create_pane.processComplete(event);
+		importing = false;
+		return;
+	    }
+	}
+
+	// Generate the import.pl command
+	ArrayList command_parts_list = new ArrayList();
+	if ((Utility.isWindows()) && (!Gatherer.isGsdlRemote)) {
+	    command_parts_list.add(Configuration.perl_path);
+	    command_parts_list.add("-S");
+	}
+	command_parts_list.add(LocalGreenstone.getBinScriptDirectoryPath() + "import.pl");
+	command_parts_list.add("-gli");
+	command_parts_list.add("-language");
+	command_parts_list.add(Configuration.getLanguage());
+	command_parts_list.add("-collectdir");
+	command_parts_list.add(getCollectDirectory());
+
+	String[] import_options = collection.import_options.getValues();
+	for (int i = 0; i < import_options.length; i++) {
+	    command_parts_list.add(import_options[i]);
+	}
+
+	command_parts_list.add(collection.getName());
+
+	// Run the import.pl command
+	String[] command_parts = (String[]) command_parts_list.toArray(new String[0]);
+	GShell shell = new GShell(command_parts, GShell.IMPORT, BUILDING, this, import_monitor, GShell.GSHELL_IMPORT);
+	shell.addGShellListener(Gatherer.g_man.create_pane);
+        shell.addGShellListener(Gatherer.g_man.format_pane);
+	shell.start();
+	DebugStream.println("CollectionManager.importCollection().return");
+
+	importing = false;
+    }
+
+
+    public void importMetadataSet(MetadataSet external_metadata_set)
+    {
+	// Copy the .mds file into the collection's "metadata" folder...
+	File external_metadata_set_file = external_metadata_set.getMetadataSetFile();
+
+	// ...but not if it is the redundant "hidden.mds" file
+	if (external_metadata_set_file.getName().equals("hidden.mds")) {
+	    return;
+	}
+
+	// ...and only if it doesn't already exist
+	File metadata_set_file = new File(getLoadedCollectionMetadataDirectoryPath(), external_metadata_set_file.getName());
+	if (!metadata_set_file.exists()) {
+	    try {
+		Gatherer.f_man.getQueue().copyFile(external_metadata_set_file, metadata_set_file, false);
+
+		// If we're using a remote Greenstone server, upload the metadata file
+		if (Gatherer.isGsdlRemote) {
+		    RemoteGreenstoneServer.uploadCollectionFile(collection.getName(), metadata_set_file);
+		}
+	    }
+	    catch (Exception exception) {
+		DebugStream.printStackTrace(exception);
+	    }
+
+	    // Load it into the MetadataSetManager
+	    MetadataSetManager.loadMetadataSet(metadata_set_file);
+	}
+    }
+
+
+    /** Determine if we are currently in the middle of importing (and thus, in this case, we can't allow the log writer to exit). Boy was this a mission to track down. The cascade of crap rolls out something like this: Joe Schmo clicks 'Build Collection', which calls the importCollection() method above, which in turn saves the collection with a saveTask, which fires a collectionChanged message once its finished, which drives the list of logs shown on the create pane to update, which fires a itemChanged() event to the OptionsPane who dutifully tells the current log writer thread to finish up writing (all zero lines its been asked to write) and then die. Wereapon Joe Schmo gets a pretty log to look at, but it isn't actually being written to file so the next time he tries to view it faeces hits the air motion cooling device. Joy.
+     * @return true if the gli is currently importing
+     */
+    public boolean isImporting() {
+	return importing;
+    }
+
+
+    public void loadCollection(String collection_file_path)
+    {
+	// Display a modal progress popup to indicate that the collection is being loaded
+	ModalProgressPopup load_collection_progress_popup = new ModalProgressPopup(Dictionary.get("CollectionManager.Loading_Collection"), Dictionary.get("CollectionManager.Loading_Collection_Please_Wait"));
+	load_collection_progress_popup.display();
+
+	// Load the collection on a separate thread so the progress bar updates correctly
+	(new LoadCollectionTask(collection_file_path, load_collection_progress_popup)).start();
+    }
+
+
+    private class LoadCollectionTask
+	extends Thread
+    {
+	private String collection_file_path = null;
+	private ModalProgressPopup load_collection_progress_popup = null;
+
+	public LoadCollectionTask(String collection_file_path, ModalProgressPopup load_collection_progress_popup)
+	{
+	    this.collection_file_path = collection_file_path;
+	    this.load_collection_progress_popup = load_collection_progress_popup;
+	}
+
+	public void run()
+	{
+	    loadCollectionInternal(collection_file_path);
+	    load_collection_progress_popup.close();
+	}
+    }
+
+
+    /** Attempts to load the given collection. Currently uses simple serialization of the collection class.
+     * @param location The path to the collection as a <strong>String</strong>.
+     * @see org.greenstone.gatherer.Configuration
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.collection.Collection
+     * @see org.greenstone.gatherer.util.Utility
+     */
+    private void loadCollectionInternal(String location)
+    {
+	DebugStream.println("Loading collection " + location + "...");
+
+	if (Gatherer.isGsdlRemote) {
+	    String collection_name = location.substring(location.lastIndexOf(File.separator) + 1, location.length() - ".col".length());
+	    if (RemoteGreenstoneServer.downloadCollection(collection_name).equals("")) {
+		return;
+	    }
+	}
+
+	// Check we have actually been given a .col file.
+	if (!location.endsWith(".col")) {
+	    JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CollectionManager.Not_Col_File", location), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
+	    DebugStream.println("CollectionManager.loadCollection: Haven't been given a .col file.");
+	    return;
+	}
+
+	// Check that the collection configuration file is available
+	File collection_file = new File(location);
+
+	// Ensure that the directory exists
+	File collection_directory = collection_file.getParentFile();
+	if (collection_directory == null || !collection_directory.exists()) {
+	    // We can't open this
+	    System.err.println("CollectionManager.loadCollection: No collection directory.");
+	    return;
+	}
+
+	File collection_config_file = new File(collection_directory, Utility.CONFIG_FILE);
+	if (!collection_config_file.exists()) {
+	    System.err.println("CollectionManager.loadCollection: No config file.");
+	    collection_directory = null;
+	    collection_config_file = null;
+	    return;
+	}
+
+	// Ensure that an import directory exists for this collection
+	File collection_import_directory = new File(collection_directory, "import");
+	if (!collection_import_directory.exists()) {
+	    collection_import_directory.mkdir();
+	}
+
+	// Special case of a user trying to open an old greenstone collection.
+	boolean non_gli_collection = false;
+	File collection_metadata_directory = new File(collection_directory, "metadata");
+	if (!collection_metadata_directory.exists()) {
+	    DebugStream.println("Loading non-gatherer collection...");
+	    // Show a warning message in case user wants to quit now
+	    non_gli_collection = true;
+	    WarningDialog legacy_dialog = new WarningDialog("warning.LegacyCollection", Dictionary.get("LegacyCollection.Title"), Dictionary.get("LegacyCollection.Message"), null, true);
+	    if (legacy_dialog.display()==JOptionPane.CANCEL_OPTION) {
+		legacy_dialog.dispose();
+		collection_directory = null;
+		collection_config_file = null;
+		return;
+	    }
+	    legacy_dialog.dispose();
+
+	}
+
+	// Now determine if a lock already exists on this collection.
+	String collection_name = collection_directory.getName();
+	File lock_file = new File(collection_file.getParentFile(), LOCK_FILE);
+	if (lock_file.exists()) {
+	    LockFileDialog dialog = new LockFileDialog(Gatherer.g_man, collection_name, lock_file);
+	    int choice = dialog.getChoice();
+	    dialog.dispose();
+	    dialog = null;
+
+	    if (choice != LockFileDialog.YES_OPTION) {
+		// user has cancelled
+		lock_file = null;
+		collection_directory = null;
+		collection_config_file = null;
+		return;
+	    }
+
+	    lock_file.delete();
+	}
+
+	try {
+	    // Create a lock file.
+	    createLockFile(lock_file);
+	    // This lock file may not have been created so check
+	    if(!lock_file.canWrite()) {
+		// The lock file cannot be written to. Most likely cause incorrect file permissions.
+		System.err.println("Cannot write lock file!");
+		String args[] = new String[2];
+		args[0] = location;
+		args[1] = Dictionary.get("FileActions.Write_Not_Permitted_Title");
+		JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CollectionManager.Cannot_Open_With_Reason", args), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
+		args = null;
+		return;
+	    }
+
+	    // Open the collection file
+	    this.collection = new Collection(collection_file);
+	    if (collection.error) {
+		collection = null;
+		// Remove lock file
+		if (lock_file.exists()) {
+		    lock_file.delete();
+		}
+		throw(new Exception(Dictionary.get("CollectionManager.Missing_Config"))); // this error message does not agree with the error
+	    }
+
+            MetadataSetManager.clearMetadataSets();
+	    MetadataSetManager.loadMetadataSets(collection_metadata_directory);
+
+	    // Make sure we always have the extracted metadata set
+	    addRequiredMetadataSets();
+
+	    ProfileXMLFileManager.loadProfileXMLFile(collection_metadata_directory);
+ 
+	    // If this is a non-GLI (legacy) collection, load the default metadata sets
+	    if (non_gli_collection) {
+		addDefaultMetadataSets();
+
+		// Recurse the import folder tree, backing up the metadata.xml files before they are edited
+		LegacyCollectionImporter.backupMetadataXMLFiles(collection_directory);
+	    }
+
+	    // Read through the metadata.xml files in the import directory, building up the metadata value trees
+	    MetadataXMLFileManager.clearMetadataXMLFiles();
+	    MetadataXMLFileManager.loadMetadataXMLFiles(collection_import_directory,collection.toSkimFile());
+
+	    // Read through the doc.xml files in the archives directory
+	    File collection_archives_directory = new File(getLoadedCollectionArchivesDirectoryPath());
+	    DocXMLFileManager.clearDocXMLFiles();
+	    DocXMLFileManager.loadDocXMLFiles(collection_archives_directory);
+
+	    // Get a list of the collection specific classifiers and plugins
+	    Classifiers.loadClassifiersList(collection_name);
+	    Plugins.loadPluginsList(collection_name);
+
+	    collection.cdm = new CollectionDesignManager(collection_config_file);
+	    if (non_gli_collection) {
+		// Change the classifiers to use the namespaced element names
+		LegacyCollectionImporter.updateClassifiers(collection.cdm);
+	    }
+
+	    // We're done. Let everyone know.
+	    DebugStream.println(Dictionary.get("CollectionManager.Loading_Successful", collection_name));
+	    Gatherer.refresh(Gatherer.COLLECTION_OPENED);
+	}
+	catch (Exception error) {
+	    // There is obviously no existing collection present.
+	    DebugStream.printStackTrace(error);
+	    if(error.getMessage() != null) {
+		String[] args = new String[2];
+		args[0] = location;
+		args[1] = error.getMessage();
+		JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CollectionManager.Cannot_Open_With_Reason", args), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
+	    }
+	    else {
+		JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CollectionManager.Cannot_Open", location), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
+	    }
+	}
+
+	lock_file = null;
+	collection_directory = null;
+	collection_config_file = null;
+    }
+
+
+    private void makeCollection(String name, String email)
+    {
+	// Generate the mkcol.pl command
+	ArrayList command_parts_list = new ArrayList();
+	if (Utility.isWindows() && (!Gatherer.isGsdlRemote)) {
+	    command_parts_list.add(Configuration.perl_path);
+	    command_parts_list.add("-S");
+	}
+	command_parts_list.add(LocalGreenstone.getBinScriptDirectoryPath() + "mkcol.pl");
+
+	command_parts_list.add("-collectdir");
+	command_parts_list.add(getCollectDirectory());
+	command_parts_list.add("-win31compat");
+	command_parts_list.add((Gatherer.isGsdlRemote) ? "false" : "true");
+
+	if (email != null && !email.equals("")) {
+	    command_parts_list.add("-creator");
+	    command_parts_list.add(email);
+	}
+
+	command_parts_list.add(name);
+
+	// Run the mkcol.pl command
+	String[] command_parts = (String[]) command_parts_list.toArray(new String[0]);
+	GShell process = new GShell(command_parts, GShell.NEW, COLLECT, this, null, GShell.GSHELL_NEW);
+	process.run(); // Don't bother threading this... yet
+    }
+
+
+    /** Any implementation of GShellListener must include this method to allow the GShell to send messages to listeners. However in this case the CollectionManager is in no way interested in what the messages are, just the import events which have a specific type and are handled elsewhere. Thus we can safely ignore this event.
+     * @param event A <strong>GShellEvent</strong> which contains a the message.
+     */
+    public synchronized void message(GShellEvent event) {
+    }
+
+
+    public void metadataChanged(CollectionTreeNode[] file_nodes)
+    {
+	if (collection != null) {
+	    collection.setMetadataChanged(true);
+	}
+    }
+
+
+    public void openCollectionFromLastTime()
+    {
+	// If there was an open collection last session, reopen it
+	if (Gatherer.open_collection_file_path != null) {
+	    // Load the collection now
+	    loadCollection(Gatherer.open_collection_file_path);
+	}
+    }
+
+
+    /** This call is fired whenever a process within a GShell created by this class begins.
+     * @param event A <strong>GShellEvent</strong> containing information about the GShell process.
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.gui.GUIManager
+     * @see org.greenstone.gatherer.shell.GShell
+     */
+    public synchronized void processBegun(GShellEvent event) {
+	DebugStream.println("CollectionManager.processBegun(" + event.getType() + ")");
+	///ystem.err.println("ProcessBegun " + event.getType());
+	// If this is one of the types where we wish to lock user control
+	Gatherer.g_man.lockCollection((event.getType() == GShell.IMPORT), true);
+    }
+    /** This call is fired whenever a process within a GShell created by this class ends.
+     * @param event A <strong>GShellEvent</strong> containing information about the GShell process.
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.gui.GUIManager
+     * @see org.greenstone.gatherer.shell.GShell
+     */
+    public synchronized void processComplete(GShellEvent event) {
+	//ystem.err.println("CollectionManager.processComplete(" + event.getType() + ")");
+	Gatherer.g_man.lockCollection((event.getType() == GShell.IMPORT), false);
+	///ystem.err.println("Recieved process complete event - " + event);
+	// If we were running an import, now run a build.
+	if(event.getType() == GShell.IMPORT && event.getStatus() == GShell.OK) {
+	    // Finish import.
+	    collection.setImported(true);
+	    collection.setFilesChanged(false);
+	    collection.setMetadataChanged(false);
+	    buildCollection(false);
+	}
+	// If we were running a build, now is when we move files across.
+	else if(event.getType() == GShell.BUILD && event.getStatus() == GShell.OK) {
+            
+	    if(installCollection()) {
+		// If we have a local library running then ask it to add our newly create collection
+		if (LocalLibraryServer.isRunning() == true) {
+		    LocalLibraryServer.addCollection(collection.getName());
+		}
+		else if (Gatherer.GS3) {
+		    convertToGS3Collection();
+		    Gatherer.configGS3Server(Configuration.site_name, ServletConfiguration.ADD_COMMAND + collection.getName());
+		}  
+
+		// Fire a collection changed first to update the preview etc buttons
+		Gatherer.refresh(Gatherer.COLLECTION_REBUILT);
+
+  		// Now display a message dialog saying its all built
+  		WarningDialog collection_built_warning_dialog = new WarningDialog("warning.CollectionBuilt", Dictionary.get("CollectionBuilt.Title"), Dictionary.get("CollectionBuilt.Message"), null, false);
+  		collection_built_warning_dialog.setMessageOnly(true); // Not a warning
+  		collection_built_warning_dialog.display();
+  		collection_built_warning_dialog.dispose();
+  		collection_built_warning_dialog = null;
+
+		//Set nothing as needing rebuilding, as a build has just finished :-)
+		CollectionDesignManager.resetRebuildTypeRequired();
+	    }
+	    else {
+		JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CollectionManager.Preview_Ready_Failed"), Dictionary.get("CollectionManager.Preview_Ready_Title"), JOptionPane.ERROR_MESSAGE);
+		Gatherer.refresh(Gatherer.COLLECTION_REBUILT);
+		DebugStream.println("Status is ok but !installCollection()");
+	    }
+	}
+	else if (event.getStatus() == GShell.CANCELLED) {
+	    JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CollectionManager.Build_Cancelled"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
+	    Gatherer.g_man.repaint();
+	}
+	else if (event.getStatus() == GShell.ERROR) {
+	    DebugStream.println("There was an error in the gshell:"+ event.getMessage());
+	    if (event.getType() == GShell.NEW) {
+		JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CollectionManager.Cannot_Create_Collection"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
+	    } else {
+		JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CollectionManager.Preview_Ready_Failed"), Dictionary.get("CollectionManager.Preview_Ready_Title"), JOptionPane.ERROR_MESSAGE);
+		Gatherer.refresh(Gatherer.COLLECTION_REBUILT);
+	    }
+	    
+	    Gatherer.g_man.repaint(); // It appears Java's own dialogs have the same not always painting correct area bug that I suffer from. Well I don't suffer from it personally, but my ModalDialog components do.
+	}
+    }
+
+
+    /** Determine if the manager is ready for actions apon its collection.
+     * @return A <i>boolean</i> which is <i>true</i> to indicate a collection has been loaded and thus the collection is ready for editing, <i>false</i> otherwise.
+     */
+    static public synchronized boolean ready() {
+	if(collection != null) {
+	    return true;
+	}
+	else {
+	    return false;
+	}
+    }
+
+
+    /** This method associates the collection build monitor with the build monitor created in CreatePane.
+     * @param monitor A <strong>GShellProgressMonitor</strong> which we will use as the build monitor.
+     */
+    public void registerBuildMonitor(GShellProgressMonitor monitor) {
+	build_monitor = monitor;
+    }
+    /** This method associates the collection import monitor with the import monitor created in CreatePane.
+     * @param monitor A <strong>GShellProgressMonitor</strong> which we will use as the import monitor.
+     */
+    public void registerImportMonitor(GShellProgressMonitor monitor) {
+	import_monitor = monitor;
+    }
+
+
+    static public void removeCollectionContentsChangedListener(CollectionContentsChangedListener listener)
+    {
+	collection_contents_changed_listeners.remove(listener);
+    }
+
+
+    public void removeMetadataSet(MetadataSet metadata_set)
+    {
+	DebugStream.println("Removing metadata set...");
+
+	// Delete the .mds file from the collection's "metadata" folder...
+	File metadata_set_file = metadata_set.getMetadataSetFile();
+
+	// ...but not if it is the "ex.mds" file
+	if (metadata_set_file.getName().equals("ex.mds")) {
+	    return;
+	}
+
+	// ...and only if it exists
+	if (metadata_set_file.exists()) {
+	    metadata_set_file.delete();
+
+	    // Unload it from the MetadataSetManager
+	    MetadataSetManager.unloadMetadataSet(metadata_set);
+
+	    // If we're using a remote Greenstone server, delete the metadata file on the server
+	    if (Gatherer.isGsdlRemote) {
+		RemoteGreenstoneServer.deleteCollectionFile(collection.getName(), metadata_set_file);
+	    }
+	}
+    }
+
+
+    /** Used to check whether all open collections have a 'saved' state.
+     * @return A <i>boolean</i> which is <i>true</i> if the collection has been saved.
+     * @see org.greenstone.gatherer.collection.Collection
+     */
+    public boolean saved() {
+	boolean result = true;
+	if(collection != null) {
+	    result = collection.getSaved();
+	}
+	return result;
+    }
+
+
+    /** Saves the currently loaded collection. */
+    public void saveCollection()
+    {
+
+        if (collection == null) return;
+
+	DebugStream.println("Saving collection " + collection.getName() + "...");
+
+	// Change cursor to hourglass
+	Gatherer.g_man.wait(true);
+
+	// Create a backup of the collection file, just in case anything goes wrong
+	File collection_file = new File(getLoadedCollectionColFilePath());
+	if (collection_file.exists()) {
+	    File collection_file_backup = new File(collection_file.getAbsolutePath() + "~");
+	    if (!collection_file.renameTo(collection_file_backup)) {
+		DebugStream.println("Error in CollectionManager.saveCollection(): could not create backup file.");
+	    }
+	    collection_file_backup.deleteOnExit();
+	}
+
+	// Write out the collection file
+	collection.save();
+
+	// Write out the collection configuration file
+	collection.cdm.save();
+
+	// Change cursor back to normal
+	Gatherer.g_man.wait(false);
+    }
+
+
+    /** I started giving the user the choice of using an existing meta set or creating a new one. The second option being so that they didn't have to add/merge/ignore each element, they could all be added automatically. However, I am not sure where the merge prompt gets called from, and it is not essential, so I am leaving it for now - it should be added back in and finished. [kjdon] */
+    private void addDefaultMetadataSets()
+    {
+	// Add dublin core which is the default metadata set. The user
+	// can change this later
+	File dc_file = new File(Gatherer.getGLIMetadataDirectoryPath()+"dublin.mds");
+	if (dc_file.exists()) {
+	    importMetadataSet(new MetadataSet(dc_file));
+	}
+    }
+
+
+    private void addRequiredMetadataSets()
+    {
+	// Always import the extracted metadata set
+	File extracted_metadata_set_file = new File(Gatherer.getGLIMetadataDirectoryPath() + MetadataSetManager.EXTRACTED_METADATA_NAMESPACE + StaticStrings.METADATA_SET_EXTENSION);
+	importMetadataSet(new MetadataSet(extracted_metadata_set_file));
+    }
+
+
+    // used as arg in the perl scripts
+    private String getCollectDirectory() {
+	String collect_dir = Gatherer.getCollectDirectoryPath();
+
+	// Remove erroneous file windows file separator as it causes problems when running import.pl
+	if(collect_dir.length() > 2 && collect_dir.endsWith("\\")) {
+	    collect_dir = collect_dir.substring(0, collect_dir.length() - 1);
+	}
+
+	return collect_dir;
+    }
+
+
+    /** Install collection by moving its files from building to index after a successful build.
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.util.Utility
+     */
+    private boolean installCollection()
+    {
+	DebugStream.println("Build complete. Moving files.");
+
+	try {
+	    // Ensure that the local library has released this collection so we can delete the index directory
+	    if (LocalLibraryServer.isRunning() == true) {
+		LocalLibraryServer.releaseCollection(collection.getName());
+	    }
+	    // deactivate it in tomcat so that windows will release the index files
+	    if (Gatherer.GS3) {
+		Gatherer.configGS3Server(Configuration.site_name, ServletConfiguration.DEACTIVATE_COMMAND + collection.getName());
+	    }
+	    File index_dir = new File(getLoadedCollectionIndexDirectoryPath());
+	    DebugStream.println("Index = " + index_dir.getAbsolutePath());
+
+	    File building_dir = new File(getLoadedCollectionBuildingDirectoryPath());
+	    DebugStream.println("Building = " + building_dir.getAbsolutePath());
+
+	    // Get the build mode from the build options
+	    String build_mode = collection.build_options.getValue("mode");
+
+	    // Special case for build mode "all": replace index dir with building dir
+	    if (build_mode == null || build_mode.equals(Dictionary.get("CreatePane.Mode_All"))) {
+		// Remove the old index directory
+		if (index_dir.exists()) {
+		    Utility.delete(index_dir);
+
+		    // Wait for a couple of seconds, just for luck
+		    wait(2000);
+
+		    // Check the delete worked
+		    if (index_dir.exists()) {
+			throw new Exception(Dictionary.get("CollectionManager.Index_Not_Deleted"));
+		    }
+		}
+
+		if (Gatherer.isGsdlRemote) {
+		    RemoteGreenstoneServer.deleteCollectionFile(collection.getName(), new File(getLoadedCollectionIndexDirectoryPath()));
+		    RemoteGreenstoneServer.moveCollectionFile(collection.getName(), new File(getLoadedCollectionBuildingDirectoryPath()), new File(getLoadedCollectionIndexDirectoryPath()));
+		}
+
+		// Move the building directory to become the new index directory
+		if (building_dir.renameTo(index_dir) == false) {
+		    throw new Exception(Dictionary.get("CollectionManager.Build_Not_Moved"));
+		}
+	    }
+
+	    // Otherwise copy everything in the building dir into the index dir
+	    else {
+		moveContentsInto(building_dir, index_dir);
+	    }
+	}
+	catch (Exception exception) {
+	    JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CollectionManager.Install_Exception", exception.getMessage()), "Error", JOptionPane.ERROR_MESSAGE);
+	    return false;
+	}
+	return true;
+    }
+
+
+    /** Moves all the files in one directory into another, overwriting existing files */
+    private void moveContentsInto(File source_directory, File target_directory)
+    {
+	File[] source_files = source_directory.listFiles();
+	for (int i = 0; i < source_files.length; i++) {
+	    File source_file = source_files[i];
+	    File target_file = new File(target_directory, source_file.getName());
+
+	    if (source_file.isDirectory()) {
+		moveContentsInto(source_file, target_file);
+		source_file.delete();
+	    }
+	    else {
+		if (target_file.exists()) {
+		    target_file.delete();
+		}
+
+		source_file.renameTo(target_file);
+	    }
+	}
+    }
+
+
+    private void updateCollectionCFG(File base_cfg, File new_cfg, String description, String email, String title)
+    {
+	boolean first_name = true;
+	boolean first_extra = true;
+	
+	// Now read in base_cfg line by line, parsing important onces and/or replacing them with information pertinent to our collection. Each line is then written back out to the new collect.cfg file.
+	try {
+	    BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(base_cfg), "UTF-8"));
+	    BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new_cfg), "UTF-8"));
+	    String command = null;
+	    while((command = in.readLine()) != null) {
+		if (command.length()==0) {
+		    // output a new line
+		    out.newLine();
+		    continue;
+		}
+		// We have to test the end of command for the special character '\'. If found, remove it and append the next line, then repeat.
+		while(command.trim().endsWith("\\")) {
+		    command = command.substring(0, command.lastIndexOf("\\"));
+		    String next_line = in.readLine();
+		    if(next_line != null) {
+			command = command + next_line;
+		    }
+		}
+		// commands can extend over more than one line so use the CommandTokenizer which takes care of that
+		CommandTokenizer tokenizer = new CommandTokenizer(command, in, false);
+		String command_type_str = tokenizer.nextToken().toLowerCase();
+
+		if (command_type_str.equals(StaticStrings.COLLECTIONMETADATA_STR)) {
+		    // read the whole thing in, but for collectionname, collectionextra, iconcollection, iconcollectionsmall we will ignore them
+		    StringBuffer new_command = new StringBuffer(command_type_str);
+		    String meta_name = tokenizer.nextToken();
+		    new_command.append(' ');
+		    new_command.append(meta_name);
+		    while (tokenizer.hasMoreTokens()) {
+			new_command.append(' ');
+			new_command.append(tokenizer.nextToken());
+		    }
+		    if (meta_name.equals(StaticStrings.COLLECTIONMETADATA_COLLECTIONNAME_STR) || meta_name.equals(StaticStrings.COLLECTIONMETADATA_COLLECTIONEXTRA_STR) || meta_name.equals(StaticStrings.COLLECTIONMETADATA_ICONCOLLECTION_STR) || meta_name.equals(StaticStrings.COLLECTIONMETADATA_ICONCOLLECTIONSMALL_STR)) {
+			// dont save
+		    } else {
+			write(out, new_command.toString());
+		    }
+		    new_command = null;
+		    continue;
+		} // if collectionmeta
+
+		if (command_type_str.equals("classify")) {
+		    StringBuffer text = new StringBuffer(command_type_str);
+		    // Read in the classifier command watching for hfile, metadata and sort arguments.
+		    String buttonname = null;
+		    String hfile = null;
+		    String new_metadata = null;
+		    String old_metadata = null;
+		
+		    while(tokenizer.hasMoreTokens()) {
+			String token = tokenizer.nextToken();
+			if (token.equals("-hfile")) {
+			    if(tokenizer.hasMoreTokens()) {
+				text.append(" ");
+				text.append(token);
+				token = tokenizer.nextToken();
+				hfile = token;
+			    }
+			}
+			else if (token.equals("-metadata")) {
+			    if(tokenizer.hasMoreTokens()) {
+				text.append(" ");
+				text.append(token);
+				String temp_metadata = tokenizer.nextToken();
+				String replacement = ProfileXMLFileManager.getMetadataElementFor(temp_metadata);
+				if (replacement != null && !replacement.equals("")) {
+				    token = replacement;
+				    old_metadata = temp_metadata;
+				    new_metadata = replacement;
+				}
+				else {
+				    token = temp_metadata;
+				}
+				temp_metadata = null;
+				replacement = null;
+			    }
+			}
+			else if (token.equals("-sort")) {
+			    if(tokenizer.hasMoreTokens()) {
+				text.append(" ");
+				text.append(token);
+				String temp_metadata = tokenizer.nextToken();
+				String replacement = ProfileXMLFileManager.getMetadataElementFor(temp_metadata);
+				if (replacement != null && !replacement.equals("")) {
+				    token = replacement;
+				}
+				else {
+				    token = temp_metadata;
+				}
+				temp_metadata = null;
+				replacement = null;
+			    }
+			}
+			else if(token.equals("-buttonname")) {
+			    buttonname = token;
+			}
+			text.append(' ');
+			text.append(token);
+			token = null;
+		    }
+		   
+		    // If we replaced the metadata argument and didn't encounter a buttonname, then add one now pointing back to the old metadata name in order to accomodate macro files which required such names (buttonname is metadata name by default)!
+		    if(old_metadata != null && new_metadata != null && buttonname == null) {
+			text.append(' ');
+			text.append("-buttonname");
+			text.append(' ');
+			text.append(old_metadata);
+		    }
+		    command = text.toString();
+		    // Replace the hfile if we found it
+		    if(hfile != null && new_metadata != null) {
+			command = command.replaceAll(hfile, new_metadata + ".txt");
+		    }
+		
+		    buttonname = null;
+		    hfile = null;
+		    new_metadata = null;
+		    old_metadata = null;
+		    write(out, command);
+		} else {
+		    // the rest of the commands just want a string - we read in all the tokens from the tokeniser and get rid of it.
+		    StringBuffer new_command = new StringBuffer(command_type_str);
+		    while (tokenizer.hasMoreTokens()) {
+			new_command.append(' ');
+			new_command.append(tokenizer.nextToken());
+		    }
+
+		    command = new_command.toString();
+		    
+		    // There is still one special case, that of the format command. In such a command we have to search for [<target>] to ensure we don't change parts of the format which have nothing to do with the metadata elements.
+		    // we really want to build up the whole command here
+		    boolean format_command = command_type_str.equals("format");
+		    HashMap metadata_mapping = ProfileXMLFileManager.getMetadataMapping();
+		    if (metadata_mapping != null) {
+			Iterator keys = metadata_mapping.keySet().iterator();
+			while (keys.hasNext()) {
+			    String target = (String) keys.next();
+			    String replacement = (String) metadata_mapping.get(target);
+			    if (replacement != null && !replacement.equals("")) {
+				if (format_command) {
+				    target = "\\[" + target + "\\]";
+				    replacement = "{Or}{[" + replacement + "]," + target + "}";
+				}
+				command = command.replaceAll(target, replacement);
+			    }
+			}
+		    }
+
+		    write(out, command);
+		}
+		tokenizer = null;
+	    }
+	    in.close();
+	    in = null;
+	    out.flush();
+	    out.close();
+	    out = null;
+	}
+	catch(Exception error) {
+	    DebugStream.printStackTrace(error);
+	}
+	// All done, I hope.
+    }
+    
+    private void write(BufferedWriter out, String message)
+	throws Exception {
+	out.write(message, 0, message.length());
+	out.newLine();
+    }
+
+
+    /** The CollectionManager class is getting too confusing by half so I'll implement this TreeModelListener in a private class to make responsibility clear. */
+    private class FMTreeModelListener
+	implements TreeModelListener {
+	/** Any action that changes one of the tree models within a collection, which are the only models we listen to, mean the collections contents have changed and so saved should be set to false.
+	 * @param event A <strong>TreeModelEvent</strong> encompassing all the information about the event which has changed the tree.
+	 */
+	public void treeNodesChanged(TreeModelEvent event) {
+	    if(collection != null) {
+		collection.setSaved(false);
+		collection.setFilesChanged(true);
+	    }
+	}
+	/** Any action that changes one of the tree models within a collection, which are the only models we listen to, mean the collections contents have changed and so saved should be set to false.
+	 * @param event A <strong>TreeModelEvent</strong> encompassing all the information about the event which has changed the tree.
+	 */
+	public void treeNodesInserted(TreeModelEvent event) {
+	    if(collection != null) {
+		collection.setSaved(false);
+		collection.setFilesChanged(true);
+	    }
+	}
+	/** Any action that changes one of the tree models within a collection, which are the only models we listen to, mean the collections contents have changed and so saved should be set to false.
+	 * @param event A <strong>TreeModelEvent</strong> encompassing all the information about the event which has changed the tree.
+	 */
+	public void treeNodesRemoved(TreeModelEvent event) {
+	    if(collection != null) {
+		collection.setSaved(false);
+		collection.setFilesChanged(true);
+
+	    }
+	}
+	/** Any action that changes one of the tree models within a collection, which are the only models we listen to, mean the collections contents have changed and so saved should be set to false.
+	 * @param event A <strong>TreeModelEvent</strong> encompassing all the information about the event which has changed the tree.
+	 */
+	public void treeStructureChanged(TreeModelEvent event) {
+	    if(collection != null) {
+		collection.setSaved(false);
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/CollectionTree.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/CollectionTree.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/CollectionTree.java	(revision 13928)
@@ -0,0 +1,356 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.collection;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.gui.tree.DragTree;
+import org.greenstone.gatherer.gui.tree.DragTreeCellRenderer;
+
+
+public class CollectionTree
+    extends DragTree
+    implements MouseListener
+{
+    public CollectionTree(CollectionTreeModel collection_tree_model, boolean mixed_selection)
+    {
+	super(collection_tree_model, mixed_selection);
+	addMouseListener(this);
+
+	setCellRenderer(new CollectionTreeCellRenderer());
+	setBackgroundNonSelectionColor(Configuration.getColor("coloring.collection_tree_background", false));
+	setBackgroundSelectionColor(Configuration.getColor("coloring.collection_selection_background", false));
+	setTextNonSelectionColor(Configuration.getColor("coloring.collection_tree_foreground", false));
+	setTextSelectionColor(Configuration.getColor("coloring.collection_selection_foreground", false));
+
+	filter.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
+	filter.setEditable(Configuration.getMode() > Configuration.LIBRARIAN_MODE);
+    }
+
+
+    public boolean isDraggable()
+    {
+	return true;
+    }
+
+
+    public boolean isDroppable()
+    {
+	return true;
+    }
+
+
+    public void mouseClicked(MouseEvent event)
+    {
+	if (SwingUtilities.isRightMouseButton(event)) {
+	    new CollectionTreeRightClickMenu(this, event);
+	}
+    }
+
+    public void mouseEntered(MouseEvent event) { }
+
+    public void mouseExited(MouseEvent event) { }
+
+    public void mousePressed(MouseEvent event) { }
+
+    public void mouseReleased(MouseEvent event) { }
+
+
+    public String toString()
+    {
+	return "Collection";
+    }
+
+
+    private class CollectionTreeCellRenderer
+	extends DragTreeCellRenderer
+    {
+	public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus)
+	{
+	    JLabel tree_cell = (JLabel) super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
+
+	    // Mark explodable files with a different icon
+	    if (value instanceof CollectionTreeNode && ((CollectionTreeNode) value).isExplodable()) {
+		tree_cell.setIcon(CollectionTreeNode.GREEN_FILE_ICON);
+	    }
+
+	    return tree_cell;
+	}
+    }
+
+
+    /** When a user right-clicks within the workspace and collection trees they are presented with a small popup menu of context based options. This class provides such functionality.
+     */
+    private class CollectionTreeRightClickMenu
+	extends JPopupMenu
+	implements ActionListener
+    {
+	/** The tree over which the right click action occurred. */
+	private CollectionTree collection_tree = null;
+	/** The tree nodes selected when the right click action occurred. */
+	private TreePath[] selection_paths = null;
+	/** The file record over which the right click action occurred. */
+	private CollectionTreeNode node = null;
+
+	private JMenuItem collapse_folder = null;
+	private JMenuItem expand_folder = null;
+	private JMenuItem explode_metadata_database = null;
+	private JMenuItem delete = null;
+	private JMenuItem metaaudit = null;
+	private JMenuItem new_folder = null;
+	private JMenuItem new_dummy_doc = null;
+	private JMenuItem open_externally = null;
+	private JMenuItem rename = null;
+	private JMenuItem replace = null;
+
+
+	private CollectionTreeRightClickMenu(CollectionTree collection_tree, MouseEvent event)
+	{
+	    super();
+	    this.collection_tree = collection_tree;
+
+	    // Note we have to use setImmediate() with the set selction paths
+	    // otherwise the selection doesn't get updated until after the 
+	    // popup comes up.
+
+	    // the right click position
+	    TreePath right_click_path = collection_tree.getPathForLocation(event.getX(), event.getY());
+	    if (right_click_path == null) {
+		// user has clicked outside of the tree, clear the selection
+		selection_paths = null;
+		collection_tree.setImmediate(true);
+		collection_tree.clearSelection();
+		collection_tree.setImmediate(false);
+	    }
+	    else {
+		// Get the paths currently selected in the tree
+		selection_paths = collection_tree.getSelectionPaths();
+		if (selection_paths == null) {
+		    // nothing currently selected - we shift the selection to 
+		    // the node that was right clicked on
+		    selection_paths = new TreePath[1];
+		    selection_paths[0] = right_click_path;
+		    collection_tree.setImmediate(true);
+		    collection_tree.setSelectionPath(right_click_path);
+		    collection_tree.setImmediate(false);
+		}
+		else if (selection_paths.length == 1 && ! selection_paths[0].equals( right_click_path)) {
+		    collection_tree.setImmediate(true);
+		    collection_tree.clearSelection();
+		    collection_tree.setSelectionPath(right_click_path);
+		    collection_tree.setImmediate(false);
+		    selection_paths[0] = right_click_path;
+		}
+		else {
+		    // we had multiply selected paths in the tree.
+		    // if we clicked on one of those paths, then use all the 
+		    // current selection, otherwise clear the selection and 
+		    // select the one we right clicked on
+		    boolean clicked_in_selection = false;
+		    for (int i = 0; i < selection_paths.length; i++) {
+			if (selection_paths[i].equals(right_click_path)) {
+			    clicked_in_selection = true;
+			    break;
+			}
+		    }
+		    if (!clicked_in_selection) {
+			// want the tree to update right away
+			collection_tree.setImmediate(true);
+			collection_tree.clearSelection();
+			collection_tree.setSelectionPath(right_click_path);
+			collection_tree.setImmediate(false);
+			selection_paths = new TreePath[1];
+			selection_paths[0] = right_click_path;
+		    }
+		}
+	    }
+	    
+	    // Create an appropriate context menu, based on what is selected
+	    buildContextMenu(selection_paths);
+
+	    // Show the popup menu on screen
+	    show(collection_tree, event.getX(), event.getY());
+	}
+
+
+	private void buildContextMenu(TreePath[] selection_paths)
+	{
+	    // If nothing is selected, only the new folder/dummy doc options are available...
+	    if (selection_paths == null) {
+		new_folder = new JMenuItem(Dictionary.get("CollectionPopupMenu.New_Folder"), KeyEvent.VK_N);
+		new_folder.addActionListener(this);
+		add(new_folder);
+
+		new_dummy_doc = new JMenuItem(Dictionary.get("CollectionPopupMenu.New_Dummy_Doc"));
+		new_dummy_doc.addActionListener(this);
+		add(new_dummy_doc);
+
+		node = (CollectionTreeNode) collection_tree.getModel().getRoot();
+		return;
+	    }
+
+	    // Meta-audit and delete options
+	    metaaudit = new JMenuItem(Dictionary.get("Menu.Metadata_View", collection_tree.getSelectionDetails()), KeyEvent.VK_A);
+	    metaaudit.addActionListener(this);
+	    add(metaaudit);
+
+	    delete = new JMenuItem(Dictionary.get("CollectionPopupMenu.Delete"), KeyEvent.VK_D);
+	    delete.addActionListener(this);
+	    add(delete);
+
+	    // Only meta-audit and delete are available if multiple items are selected...
+	    if (selection_paths.length > 1) {
+		return;
+	    }
+
+	    // Rename option
+	    rename = new JMenuItem(Dictionary.get("CollectionPopupMenu.Rename"), KeyEvent.VK_R);
+	    rename.addActionListener(this);
+	    add(rename);
+
+	    TreePath path = selection_paths[0];
+	    node = (CollectionTreeNode) path.getLastPathComponent();
+
+	    // ---- Options for file nodes ----
+	    if (node.isLeaf()) {
+		// Explode metadata databases, for explodable files only
+		if (node.isExplodable()) {
+		    explode_metadata_database = new JMenuItem(Dictionary.get("Menu.Explode_Metadata_Database"), KeyEvent.VK_E);
+		    explode_metadata_database.addActionListener(this);
+		    add(explode_metadata_database);
+		}
+
+		// Replace file
+		// !! TO DO: Remote building
+		if (!Gatherer.isGsdlRemote) {
+		    replace = new JMenuItem(Dictionary.get("CollectionPopupMenu.Replace"), KeyEvent.VK_P);
+		    replace.addActionListener(this);
+		    add(replace);
+		}
+		
+		// Open the file in an external program
+		open_externally = new JMenuItem(Dictionary.get("Menu.Open_Externally"), KeyEvent.VK_O);
+		open_externally.addActionListener(this);
+		add(open_externally);
+
+		return;
+	    }
+
+	    // ---- Options for folder nodes ----
+	    // Collapse or expand, depending on current status
+	    if (collection_tree.isExpanded(path)) {
+		collapse_folder = new JMenuItem(Dictionary.get("Menu.Collapse"), KeyEvent.VK_C);
+		collapse_folder.addActionListener(this);
+		add(collapse_folder);
+	    }
+	    else {
+		expand_folder = new JMenuItem(Dictionary.get("Menu.Expand"), KeyEvent.VK_O);
+		expand_folder.addActionListener(this);
+		add(expand_folder);
+	    }
+
+	    // New folder/dummy doc options
+	    if (!node.isReadOnly()) {
+		new_folder = new JMenuItem(Dictionary.get("CollectionPopupMenu.New_Folder"), KeyEvent.VK_N);
+		new_folder.addActionListener(this);
+		add(new_folder);
+
+		new_dummy_doc = new JMenuItem(Dictionary.get("CollectionPopupMenu.New_Dummy_Doc"));
+		new_dummy_doc.addActionListener(this);
+		add(new_dummy_doc);
+	    }
+	}
+
+
+	/** Called whenever one of the menu items is clicked, this method then causes the appropriate effect. */
+	public void actionPerformed(ActionEvent event)
+	{
+  	    Object source = event.getSource();
+
+	    // Collapse folder
+	    if (source == collapse_folder) {
+		collection_tree.collapsePath(selection_paths[0]);
+	    }
+
+	    // Expand folder
+	    else if (source == expand_folder) {
+		collection_tree.expandPath(selection_paths[0]);
+	    }
+
+	    // Explode metadata database
+	    else if (source == explode_metadata_database) {
+ 		Gatherer.f_man.explodeMetadataDatabase(node.getFile());
+	    }
+
+	    // Delete
+	    else if (source == delete) {
+		CollectionTreeNode[] source_nodes = new CollectionTreeNode[selection_paths.length];
+		for (int i = 0; i < selection_paths.length; i++) {
+		    source_nodes[i] = (CollectionTreeNode) selection_paths[i].getLastPathComponent();
+		}
+
+		// Fire a delete action
+		Gatherer.f_man.action(collection_tree, source_nodes, Gatherer.recycle_bin, null);
+	    }
+
+	    // Meta-audit
+	    else if (source == metaaudit) {
+ 		Gatherer.g_man.showMetaAuditBox();
+ 	    }
+
+	    // New folder
+  	    else if (source == new_folder) {
+ 		Gatherer.f_man.newFolder(collection_tree, node);
+ 	    }
+
+	    // New dummy doc
+	    else if (source == new_dummy_doc) {
+		Gatherer.f_man.newDummyDoc(collection_tree, node);
+	    }
+
+	    // Open in external program
+	    else if (source == open_externally) {
+		Gatherer.f_man.openFileInExternalApplication(node.getFile());
+	    }
+
+	    // Rename
+	    else if (source == rename) {
+		Gatherer.f_man.renameCollectionFile(collection_tree, node);
+	    }
+
+	    // Replace
+	    else if (source == replace) {
+		Gatherer.f_man.replaceCollectionFile(collection_tree, node);
+	    }
+  	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/CollectionTreeModel.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/CollectionTreeModel.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/CollectionTreeModel.java	(revision 13928)
@@ -0,0 +1,41 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2004 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.collection;
+
+
+import org.greenstone.gatherer.file.FileSystemModel;
+
+
+/** This class represents ... */
+public class CollectionTreeModel
+    extends FileSystemModel
+{
+    public CollectionTreeModel(CollectionTreeNode root_node)
+    {
+	super(root_node);
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/CollectionTreeNode.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/CollectionTreeNode.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/CollectionTreeNode.java	(revision 13928)
@@ -0,0 +1,68 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2004 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.collection;
+
+
+import java.io.*;
+import javax.swing.*;
+import org.greenstone.gatherer.cdm.CollectionDesignManager;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.util.JarTools;
+
+
+/** This class represents one node in the collection tree. */
+public class CollectionTreeNode
+    extends FileNode
+{
+    static final public ImageIcon GREEN_FILE_ICON = JarTools.getImage("greenfile.gif", true);
+
+    /** Is this file a metadata database that is explodable with the explode_metadata_databases.pl script? */
+    private boolean is_explodable = false;
+
+
+    public CollectionTreeNode(File file)
+    {
+	super(file);
+
+	this.is_explodable = CollectionDesignManager.plugin_manager.isFileExplodable(file);
+    }
+
+
+    public FileNode addChildNode(File file)
+    {
+	CollectionTreeNode child_node = new CollectionTreeNode(file);
+	child_node.setModel(model);
+	child_node.setParent(this);
+	return child_node;
+    }
+
+
+    public boolean isExplodable()
+    {
+	return is_explodable;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/LegacyCollectionImporter.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/LegacyCollectionImporter.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/LegacyCollectionImporter.java	(revision 13928)
@@ -0,0 +1,142 @@
+package org.greenstone.gatherer.collection;
+
+
+import java.io.*;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.Argument;
+import org.greenstone.gatherer.cdm.Classifier;
+import org.greenstone.gatherer.cdm.CollectionDesignManager;
+import org.greenstone.gatherer.metadata.MetadataElement;
+import org.greenstone.gatherer.metadata.MetadataTools;
+import org.greenstone.gatherer.metadata.ProfileXMLFileManager;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+
+
+/**
+ * Importing legacy collections involves two main steps:
+ *
+ * 1. Read the existing metadata.xml files and namespace them, usually by prompting the user
+ *    to specify the mapping between old metadata elements and new elements.
+ *
+ * 2. Fix up the classify commands in the collect.cfg file to specify the new element names.
+ *
+ * @author Michael Dewsnip
+ */
+public class LegacyCollectionImporter 
+{
+    /** Definition of an important directory name, in this case the backup import directory for the collection. */
+    static final public String IMPORT_BAK_DIR = "import.bak" + File.separator;
+
+
+    // This copies all the existing metadata.xml files into a backup directory
+    static public void backupMetadataXMLFiles(File collection_dir)
+    {
+	File import_dir = new File(collection_dir, "import");
+	File import_bak_dir = new File(collection_dir, IMPORT_BAK_DIR);
+	import_bak_dir.mkdir();
+	copyMetadataXMLFiles(import_dir, import_bak_dir);
+    }
+
+
+    static private void copyMetadataXMLFiles(File source_dir, File backup_dir)
+    {
+	if (source_dir == null || !source_dir.exists()) {
+	    return;
+	}
+
+	// Find the metadata file in this dir
+	File metadata_xml_file_file = new File(source_dir, "metadata.xml");
+	if (metadata_xml_file_file.exists()) {
+	    File new_metadata_xml_file_file = new File(backup_dir, "metadata.xml");
+	    try {
+		backup_dir.mkdirs();
+		Gatherer.f_man.getQueue().copyFile(metadata_xml_file_file, new_metadata_xml_file_file, false);
+		if (!new_metadata_xml_file_file.exists()) {
+		    throw new Exception("");
+		}
+	    }
+	    catch (Exception e) {
+		DebugStream.println("Exception: couldn't copy the file " + metadata_xml_file_file.getPath() + e.getMessage());
+	    }
+	}
+
+	// Now go through child directories
+	File [] children = source_dir.listFiles();
+	for (int i = 0; i < children.length; i++) {
+	    File child = children[i];
+	    if (child.isDirectory()) {
+		copyMetadataXMLFiles(child, new File(backup_dir, child.getName()));
+	    }
+	}
+    }
+
+
+    static public void updateClassifiers(CollectionDesignManager cdm)
+    {
+	// Update the metadata elements in each of the classifiers
+	for (int i = 0; i < cdm.classifier_manager.getSize(); i++) {
+	    Classifier classifier = cdm.classifier_manager.getClassifier(i);
+	    // System.err.println("Classifier: " + classifier);
+
+	    // Update the "-metadata" value
+	    Argument metadata_argument = classifier.getArgument("-metadata");
+	    String metadata_argument_value = metadata_argument.getValue();
+	    String metadata_element_name_full = mapLegacyMetadataElementName(metadata_argument_value);
+	    if (metadata_element_name_full != null && !metadata_element_name_full.equals("")) {
+		String metadata_element_display_name_full = MetadataTools.getDisplayNameForMetadataElementWithName(metadata_element_name_full);
+		if (metadata_element_display_name_full != null) {
+		    metadata_argument_value = metadata_element_display_name_full;
+		    metadata_argument.setValue(metadata_argument_value);
+		}
+	    }
+
+  	    // Update the "-sort" value
+	    Argument sort_argument = classifier.getArgument("-sort");
+	    if (sort_argument != null) {
+		String sort_element_name_full = mapLegacyMetadataElementName(sort_argument.getValue());
+		if (sort_element_name_full != null && !sort_element_name_full.equals("")) {
+		    String sort_element_display_name_full = MetadataTools.getDisplayNameForMetadataElementWithName(sort_element_name_full);
+		    if (sort_element_display_name_full != null) {
+			sort_argument.setValue(sort_element_display_name_full);
+		    }
+		}
+	    }
+
+	    // Set the "-buttonname" value if it isn't already set
+	    Argument buttonname_argument = classifier.getArgument("-buttonname");
+	    if (buttonname_argument != null && buttonname_argument.getValue().equals("")) {
+		int namespace_index = metadata_argument_value.indexOf(".");
+		if (namespace_index != -1) {
+		    buttonname_argument.setValue(metadata_argument_value.substring(namespace_index + 1));
+		}
+		else {
+		    buttonname_argument.setValue(metadata_argument_value);
+		}
+		buttonname_argument.setAssigned(true);
+	    }
+
+	    // With Hierarchy classifiers, update the hfile arguments
+  	    if (classifier.getName().equalsIgnoreCase(StaticStrings.HIERARCHY_CLASSIFIER)) {
+		// Update the "-hfile" value
+		Argument hfile_argument = classifier.getArgument(StaticStrings.HFILE_ARGUMENT);
+		hfile_argument.setValue(metadata_element_name_full + ".txt");
+  	    }
+
+	    // System.err.println("Classifier (after): " + classifier);
+	}
+    }
+
+
+    static private String mapLegacyMetadataElementName(String metadata_element_name)
+    {
+ 	// Remove the extracted namespace if it has been added
+ 	if (metadata_element_name.startsWith(StaticStrings.EXTRACTED_NAMESPACE)) {
+ 	    metadata_element_name = metadata_element_name.substring(StaticStrings.EXTRACTED_NAMESPACE.length());
+ 	}
+
+ 	// Update the metadata value to the new (namespaced) one
+	return ProfileXMLFileManager.getMetadataElementFor(metadata_element_name);
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/ScriptOptions.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/ScriptOptions.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/collection/ScriptOptions.java	(revision 13928)
@@ -0,0 +1,264 @@
+package org.greenstone.gatherer.collection;
+
+import java.io.*;
+import java.util.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.Argument;
+import org.greenstone.gatherer.greenstone.LocalGreenstone;
+import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
+import org.greenstone.gatherer.util.ArrayTools;
+import org.greenstone.gatherer.util.Codec;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.util.XMLTools;
+import org.w3c.dom.*;
+
+
+/** This class parses options from Perl scripts: import.pl, buildcol.pl and explode_metadata_database.pl in particular. */
+public class ScriptOptions
+{
+    /** The root element of the argument tree. */
+    private Element arguments_element;
+    /** The root element of the values tree. */
+    private Element values_element;
+    /** The name of an argument element. */
+    static final private String ARGUMENT = "Argument";
+    /** The name of the enabled attribute. */
+    static final private String ENABLED = "enabled";
+    /** The name of the 'false' value. */
+    static final private String FALSE = "false";
+    /** The name of a name attribute. */
+    static final private String NAME = "name";
+    /** The name of an option element. */
+    static final private String OPTION = "Option";
+    /** The name of the 'true' value. */
+    static final private String TRUE = "true";
+
+
+    /** Parse the arguments from running "script_name -xml" */
+    public ScriptOptions(Element values_element, String script_name)
+    {
+	this.values_element = values_element;
+	this.arguments_element = loadArguments(script_name, Configuration.getLanguage());
+    }
+
+
+    /** Retrieve the indexth argument */
+    public Argument getArgument(int index)
+    {
+	Argument argument = null;
+
+	NodeList option_list = arguments_element.getElementsByTagName(OPTION);
+	if (index >= 0 && index < option_list.getLength()) {
+	    argument = new Argument();
+	    argument.parseXML((Element) option_list.item(index));
+	}
+
+	return argument;
+    }
+
+
+    /** Retrieve the number of arguments.
+     */
+    public int getArgumentCount() {
+	// Determining the total count is easy.
+	NodeList argument_elements = arguments_element.getElementsByTagName(OPTION);
+	return argument_elements.getLength();
+    }
+
+
+    /** Retrieve the value of a certain argument. */
+    public String getValue(String name) {
+	return getValue(name, false);
+    }
+
+    /** Determine if the named argument value is enabled or disabled. */
+    public boolean getValueEnabled(String name) {
+	boolean result = false;
+	String value = getValue(name, true);
+	if(value != null && value.length() > 0) {
+	    result = (value.equalsIgnoreCase(TRUE));
+	}
+	return result;
+    }
+
+    /** Retrieve all of the values as a String array ready to added to the script call. */
+    public String[] getValues() {
+	ArrayList values = new ArrayList();
+	try {
+	    NodeList arguments = values_element.getElementsByTagName(ARGUMENT);
+	    for(int i = 0; i < arguments.getLength(); i++) {
+		Element argument_element = (Element) arguments.item(i);
+		// Determine if this argument is enabled.
+		if(argument_element.getAttribute(ENABLED).equalsIgnoreCase(TRUE)) {
+		    // First store the name of the argument prefixed with a '-'
+		    values.add("-" + argument_element.getAttribute(NAME));
+		    // Now retrieve the value.
+		    String argument_value = Codec.transform(XMLTools.getValue(argument_element), Codec.DOM_TO_TEXT);
+		    // If there is a value, tokenize it by commas only.
+		    if(argument_value != null && argument_value.length() > 0) {
+			values.add(argument_value);
+		    }
+		    argument_value = null;
+		}
+		argument_element = null;
+	    }
+	    arguments = null;
+	}
+	catch (Exception error) {
+	    DebugStream.printStackTrace(error);
+	}
+	return ArrayTools.arrayListToStringArray(values);
+    }
+
+   /** Remove the named value from the arguments */
+    public void removeValue(String name) {
+	try {
+	    NodeList arguments = values_element.getElementsByTagName(ARGUMENT);
+	    boolean found = false;
+	    for(int i = 0; !found && i < arguments.getLength(); i++) {
+		Element argument_element = (Element) arguments.item(i);
+		// Is this the argument we want.
+		if(argument_element.getAttribute(NAME).equalsIgnoreCase(name)) {
+		    values_element.removeChild(argument_element);
+		    found = true;
+		}
+		argument_element = null;
+	    }
+	    arguments = null;
+	}
+	catch (Exception error) {
+	    DebugStream.printStackTrace(error);
+	}
+    }
+
+    /** Set the state of some argument. Note that value may be either a single String, an ArrayList of Strings or null. If enable is false then any existing argument for the named argument is disabled. */
+    public void setValue(String name, boolean enable, String value) {
+	///ystem.err.println("Set value: " + (arguments_element == build_values_element ? "Build" : "Import") + ", " + name + ", " + enable + ", " + value);
+	try {
+	    Document document = values_element.getOwnerDocument();
+	    NodeList arguments = values_element.getElementsByTagName(ARGUMENT);
+	    boolean found = false;
+	    for(int i = 0; i < arguments.getLength(); i++) {
+		Element argument_element = (Element) arguments.item(i);
+		// If this the argument named.
+		if(argument_element.getAttribute(NAME).equalsIgnoreCase(name)) {
+		    found = true;
+		    // Set whether this argument is enabled
+		    argument_element.setAttribute(ENABLED, (enable ? TRUE : FALSE));
+		    // Now we set the value, depending or what it is.
+		    if(value == null) {
+			// Nothing to do.
+		    }
+		    else {
+			// Remove existing text nodes.
+			while(argument_element.hasChildNodes()) {
+			    argument_element.removeChild(argument_element.getFirstChild());
+			}
+			argument_element.appendChild(document.createTextNode((String)value));
+		    }
+		}
+		argument_element = null;
+	    }
+	    // If we haven't found an instance of this argument, but should have, then add it.
+	    if(!found && (enable || value != null)) {
+		Element argument_element = document.createElement(ARGUMENT);
+		argument_element.setAttribute(NAME, name);
+		argument_element.setAttribute(ENABLED, (enable ? TRUE : FALSE));
+		// Now we set the value, depending or what it is.
+		if(value == null) {
+		    // Nothing to do.
+		}
+		else {
+		    argument_element.appendChild(document.createTextNode((String)value));
+		}
+		values_element.appendChild(argument_element);
+	    }
+	    arguments = null;
+	    document = null;
+	    // Make sure the collection knows to save.
+	    Gatherer.c_man.getCollection().setSaved(false);
+	}
+	catch (Exception error) {
+	    DebugStream.printStackTrace(error);
+	}
+    }
+
+ 
+    private String getValue(String name, boolean is_enabled) {
+	String result = null;
+	try {
+	    NodeList arguments = values_element.getElementsByTagName(ARGUMENT);
+	    for(int i = 0; result == null && i < arguments.getLength(); i++) {
+		Element argument_element = (Element) arguments.item(i);
+		// Is this the argument we want.
+		if(argument_element.getAttribute(NAME).equalsIgnoreCase(name)) {
+		    // Are we simply determining if this argument is enabled
+		    if(is_enabled) {
+			result = argument_element.getAttribute(ENABLED);
+		    }
+		    else {
+			String argument_value = XMLTools.getValue(argument_element);
+			if(argument_value != null) {
+			    result = argument_value;
+			}
+			argument_value = null;
+		    }
+		}
+		argument_element = null;
+	    }
+	    arguments = null;
+	}
+	catch (Exception error) {
+	    DebugStream.printStackTrace(error);
+	}
+	return result;
+    }
+
+
+    private Element loadArguments(String filename, String lang)
+    {
+	// Run the required program.
+	try {
+	    Document document;
+
+	    if (Gatherer.isGsdlRemote) {
+		String script_output = RemoteGreenstoneServer.getScriptOptions(filename, "");
+		document = XMLTools.parseXML(new StringReader(script_output));
+	    }
+	    else {
+		String args[];
+		if(Utility.isWindows()) {
+		    args = new String[6];
+		    args[0] = Configuration.perl_path;
+		    args[1] = "-S";
+		    args[2] = LocalGreenstone.getBinScriptDirectoryPath() + filename;
+		    args[3] = "-xml";
+		    args[4] = "-language";
+		    args[5] = lang;
+		}
+		else {
+		    args = new String[4];
+		    args[0] = LocalGreenstone.getBinScriptDirectoryPath() + filename;
+		    args[1] = "-xml";
+		    args[2] = "-language";
+		    args[3] = lang;
+		}
+
+		// Create the process.
+		Runtime runtime = Runtime.getRuntime();
+		Process process = runtime.exec(args);
+		document = XMLTools.parseXML(process.getErrorStream());
+	    }
+
+	    return document.getDocumentElement();
+	}
+	catch (Exception error) {
+	    DebugStream.println("Error in ScriptOptions.loadArguments(): " + error);
+	    DebugStream.printStackTrace(error);
+	}
+
+	return null;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/download/Download.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/download/Download.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/download/Download.java	(revision 13928)
@@ -0,0 +1,207 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.download;
+
+import java.io.*;
+import java.util.*;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+import org.w3c.dom.*;
+import org.greenstone.gatherer.cdm.*;
+
+
+/** This class is responsible for storing information from a parsed downloadinfo.pl call in such a way that it allows easy access to parsed details for the purposes of user design and specification of downloads.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class Download
+    extends ArgumentContainer
+{
+    private boolean is_abstract = false;
+
+    /** A reference to the download that this one inherits from. */
+    private Download super_download = null;
+    /** The element this download is based upon. */
+    private Element element;
+    /** A description of this download. */
+    private String description = null;
+    private String name = null;
+
+
+    public Download() {
+    }
+
+    /** Method to add an argument to this download. Only adds the argument if it isn't already present.
+     * @param argument The <strong>Argument</strong> to add.
+     */
+    public void addArgument(Argument argument) {
+	if(element == null && !contains(argument)) {
+	    add(argument);
+	    argument.setOwner(name);
+	}
+    }
+
+    /** Method to compare two downloads for ordering.
+     * @param object The download we are comparing to, as an <strong>Object</strong>.
+     * @return An <i>int</i> specifying the download order, using values as set out in String.
+     * @see java.lang.String#compareTo
+     */
+    public int compareTo(Object object) {
+	if(object == null) {
+	    return -1;
+	}
+	return toString().compareTo(object.toString());
+    }
+
+    /** Probably not used.
+     */
+    public DOMProxyListEntry create(Element element) {
+	return null;
+    }
+
+    /** Method to determine if two downloads are equal.
+     * @param object The download to test against, as an <strong>Object</strong>.
+     * @return <i>true</i> if the download names match, <i>false</i> otherwise.
+     */
+    public boolean equals(Object object) {
+	return (compareTo(object) == 0);
+    }
+
+    /** Method to retrieve an argument by its name.
+     * @param name The name of the argument as a <strong>String</strong>.
+     * @return The <strong>Argument</strong> requested, or <i>null</i> if no such argument.
+     */
+    public Argument getArgument(String name) {
+	// The name given may still include the '-'
+	if(name.startsWith("-")) {
+	    name = name.substring(1);
+	}
+	ArrayList arguments = getArguments(true, true);
+	for(int i = 0; i < arguments.size(); i++) {
+	    Argument argument = (Argument)arguments.get(i);
+	    if(argument.getName().equals(name)) {
+		return argument;
+	    }
+	}
+	return null;
+    }
+
+     /** Retrieve all of the arguments available to this base download, including its super downloads arguments. Some complexity is added by allowing the caller to choose whether they want normal arguments, custom arguments, or both.
+      * @return an ArrayList of all of the arguments, starting with those for this download and ending with the arguments for basplug or similiar root download
+      */
+    public ArrayList getArguments(boolean include_normal, boolean include_custom) {
+	ArrayList arguments = new ArrayList();
+	if(include_normal && include_custom) {
+	    arguments.addAll(this);
+	}
+	else {
+	    int size = size();
+	    for(int i = 0; i < size; i++) {
+		Argument argument = (Argument) get(i);
+		if(argument.isCustomArgument()) {
+		    if(include_custom && !arguments.contains(argument)) {
+			arguments.add(argument);
+		    }
+		}
+		else {
+		    if(include_normal && !arguments.contains(argument)) {
+			arguments.add(argument);
+		    }
+		}
+		argument = null;
+	    }
+	}
+	if(super_download != null) {
+	    ArrayList remainder = super_download.getArguments(include_normal, include_custom);
+	    remainder.removeAll(arguments);
+	    arguments.addAll(remainder);
+	}
+	return arguments;
+    }
+
+    public String getDescription() {
+	return description;
+    }
+
+    public Element getElement() {
+	return element;
+    }
+
+    /** Method to retrieve a download name.
+     * @return A <strong>String</strong> containing the downloads name.
+     */
+    public String getName() {
+	if(name == null && element != null) {
+	    name = element.getAttribute(StaticStrings.TYPE_ATTRIBUTE);
+	}
+	return name;
+    }
+
+    public boolean isAbstract() {
+	return is_abstract;
+    }
+
+    public boolean isAssigned() {	
+	return (element != null && !element.getAttribute(StaticStrings.ASSIGNED_ATTRIBUTE).equals(StaticStrings.FALSE_STR));
+    }
+
+    public void setAssigned(boolean assigned) {
+	if(element != null) {
+	    element.setAttribute(StaticStrings.ASSIGNED_ATTRIBUTE, (assigned ? StaticStrings.TRUE_STR : StaticStrings.FALSE_STR));
+	}
+    }
+
+
+    /** Method to set the value of desc.
+     * @param description The new value of desc as a <strong>String</strong>.
+     */
+    public void setDescription(String description) {
+	this.description = description;
+    }
+
+    public void setElement(Element element) {
+	this.element = element;
+    }
+
+    public void setIsAbstract(boolean is_abstract) {
+	this.is_abstract = is_abstract;
+    }
+
+    /** Method to set the value of name.
+     * @param name The new value of name as a <strong>String</strong>.
+     */
+    public void setName(String name) {
+	this.name = name;
+    }
+
+    /** Method to set the value of the super_download.
+     * @param super_download The new value of super_download as a <strong>Download</strong>, or <i>null</i> if this class has no inheritance.
+     */
+    public void setSuper(Download super_download) {
+	this.super_download = super_download;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/download/DownloadJob.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/download/DownloadJob.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/download/DownloadJob.java	(revision 13928)
@@ -0,0 +1,466 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.download;
+
+import java.awt.event.*;
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.GAuthenticator;
+import org.greenstone.gatherer.greenstone.LocalGreenstone;
+import org.greenstone.gatherer.file.WorkspaceTree;
+import org.greenstone.gatherer.util.AppendLineOnlyFileDocument;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.cdm.Argument;
+import org.greenstone.gatherer.collection.*;
+/**
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.0
+ */
+public class DownloadJob
+    implements ActionListener {
+	 
+    private boolean debug;
+    private boolean higher_directories;
+    private boolean no_parents;
+    private boolean other_hosts; 
+    private boolean page_requisites; 
+    private boolean quiet;
+
+    private AppendLineOnlyFileDocument download_log;
+
+    private DownloadProgressBar progress;
+
+    private int depth;
+    private int previous_state;
+    private int state;
+
+    private String download_url = "";
+
+    //    private String current_url;
+    //    private String destination;
+    private String proxy_pass;
+    private String proxy_user;
+
+    private Vector encountered_urls;
+    private Vector failed_urls;
+    private Download download;
+    private DownloadScrollPane mummy;
+    private HashMap download_option;
+
+    public static int COMPLETE = 0;
+    public static int PAUSED   = 1;
+    public static int RUNNING  = 2;
+    public static int STOPPED  = 3;
+
+    public static int UNKNOWN_MAX  = 0;
+    public static int DEFINED_MAX  = 1;
+    public static int UNDEFINED_MAX  = 2;
+
+    private String mode = null;
+   
+    private String proxy_url;
+
+    /**
+     */
+    public DownloadJob(Download download, String proxy_pass, String proxy_user, DownloadScrollPane mummy, String mode, String proxy_url) {
+	URL url = null;
+	int folder_hash;
+
+        this.proxy_url =  proxy_url;
+	
+       	download_option = downloadToHashMap(download);
+	if (!mode.equals("Z3950") && !mode.equals("SRW")) {
+	    Argument url_arg = (Argument)download_option.get((String)"url");
+	    download_url =  url_arg.getValue();
+	    
+	}
+	else {
+	    Argument host_arg = (Argument)download_option.get((String)"host");
+	    Argument port_arg = (Argument)download_option.get((String)"port");
+	    download_url = host_arg.getValue() + ":" +port_arg.getValue();
+	}
+       
+	folder_hash = download_url.hashCode();
+	String log_filename = Utility.getLogDir(null) + "download-"+ mode + folder_hash + ".log";
+	File log_file = new File(log_filename);
+	if(log_file.exists()) {
+	    log_file.delete();
+	}
+
+	File parent_log_file = log_file.getParentFile();
+	parent_log_file.mkdirs();
+	parent_log_file = null;
+	log_file = null;
+
+	this.download_log = new AppendLineOnlyFileDocument(log_filename, false);
+   
+	this.proxy_pass = proxy_pass;
+	this.proxy_user = proxy_user;
+	this.mummy = mummy;
+	this.mode = mode;
+	this.download = download;
+
+	progress = new DownloadProgressBar(this,download_url, true);
+	encountered_urls = new Vector();
+	failed_urls = new Vector();
+
+	previous_state = STOPPED;
+	state = STOPPED;
+    }
+
+    private HashMap downloadToHashMap(Download download)
+    {
+	HashMap download_option = new HashMap();
+	ArrayList arguments = download.getArguments(true, false);
+	for(int i = 0; i < arguments.size(); i++) {
+	    Argument argument = (Argument) arguments.get(i);
+	    download_option.put(argument.getName(), argument);
+	}
+	return download_option;
+    }
+
+    /** Depending on which button on the progress bar was pushed,
+     * this method will affect the state of the DownloadJob and perhaps make
+     * calls to wget.class if necessary.
+     * @param event The ActionEvent fired from within the DownloadProgressBar
+     * which we must respond to.
+     */
+    public void actionPerformed(ActionEvent event) {
+	// The stop_start_button is used to alternately start or stop the
+	// job. If the current state of the job is paused then this
+	// restart is logically equivelent to a resume.
+	if(event.getSource() == progress.stop_start_button) {
+	    previous_state = state;
+	    if (state == RUNNING) {
+		state = STOPPED;
+	    } else {
+		//previous_state = state;
+		state = RUNNING;
+		mummy.resumeThread();
+	    }
+	}
+	else if (event.getSource() == progress.close_button) {
+	    if(state == RUNNING) {
+		previous_state = state;
+		state = STOPPED; // do we need to do anything else to stop this?
+	    } 
+	    mummy.deleteDownloadJob(this);
+	}
+    }
+
+
+    public void callDownload() {
+	
+	ArrayList command_list = new ArrayList();
+        if (Utility.isWindows()) {
+	    command_list.add(Configuration.perl_path);
+	    command_list.add("-S");
+	}
+	command_list.add(LocalGreenstone.getBinScriptDirectoryPath()+"downloadfrom.pl");
+	command_list.add("-download_mode");
+	command_list.add(mode);
+	command_list.add("-cache_dir");
+	command_list.add(Gatherer.getGLIUserCacheDirectoryPath());
+	
+	ArrayList all_arg = download.getArguments(true,false);
+	for(int i = 0; i < all_arg.size(); i++) {
+	    Argument argument = (Argument) all_arg.get(i);
+	    if(argument.isAssigned()) {
+		command_list.add("-" + argument.getName());
+		if(argument.getType() != Argument.FLAG) {
+		    command_list.add(argument.getValue());
+		}
+	    }   
+	}
+
+	String [] cmd = (String []) command_list.toArray(new String[0]);
+	DebugStream.println("Download job, "+command_list);
+
+	if (previous_state == DownloadJob.COMPLETE) {
+	    progress.mirrorBegun(true, true);
+	}
+	else {
+	    progress.mirrorBegun(false, true);
+	}
+
+	try {
+	    Runtime rt = Runtime.getRuntime();
+
+	    String [] env = null;
+	 
+	    Process prcs = null; 
+
+         
+	    if (Utility.isWindows()) {
+              	prcs = rt.exec(cmd);   
+	    }
+	    else {
+		if (proxy_url != null && !proxy_url.equals("")) {          	
+		    // Specify proxies as environment variables
+		    // Need to manually specify GSDLHOME and GSDLOS also
+		    env = new String[4];
+                    proxy_url = proxy_url.replaceAll("http://","");
+		    env[0] = "http_proxy=http://"+proxy_url;
+		    env[1] = "ftp_proxy=ftp://"+proxy_url;
+		    env[2] = "GSDLHOME=" + Configuration.gsdl_path;
+		    env[3] = "GSDLOS=" + Gatherer.client_operating_system;
+		    prcs = rt.exec(cmd, env); 
+		} 
+		else {
+		    // Will inherit the GLI's environment, with GSDLHOME and GSDLOS set
+		    prcs = rt.exec(cmd);
+		}
+	    }
+ 
+	    //System.out.println(newcmd);	    
+
+	    InputStreamReader isr = new InputStreamReader(prcs.getErrorStream());
+	    BufferedReader br = new BufferedReader(isr);
+	    // Capture the standard error stream and seach for two particular occurances.
+	    String line="";
+	    boolean ignore_for_robots = false;
+	    int max_download = DownloadJob.UNKNOWN_MAX;
+
+
+	    while ((line = br.readLine()) != null && !line.trim().equals("<<Finished>>") && state != STOPPED) {
+
+		if ( max_download == DownloadJob.UNKNOWN_MAX) {
+		    if(line.lastIndexOf("<<Defined Maximum>>") != -1) {
+			max_download = DownloadJob.DEFINED_MAX;
+		    }
+		    else if (line.lastIndexOf("<<Undefined Maximum>>") != -1) {
+			max_download = DownloadJob.UNDEFINED_MAX;
+		    }
+		}
+		else if(max_download == DownloadJob.UNDEFINED_MAX) {
+		    DebugStream.println(line);
+		    download_log.appendLine(line);
+		    // The first magic special test is to see if we've just
+		    // asked for the robots.txt file. If so we ignore
+		    // the next add and then the next complete/error.
+		    if(line.lastIndexOf("robots.txt;") != -1) {
+			DebugStream.println("***** Requesting robot.txt");
+			ignore_for_robots = true;
+		    }
+		    // If line contains "=> `" display text as the 
+		    // currently downloading url. Unique to add download.
+		    else if(line.lastIndexOf("=> `") != -1) {
+			if(!ignore_for_robots) {
+			    // Add download
+			    String new_url = line.substring(line.indexOf("`") + 1, line.lastIndexOf("'"));
+			    //addDownload("http:/" + new_url);
+			}
+		    }
+		    // If line contains "/s) - `" set currently 
+		    // downloading url to "Download Complete".
+		    else if(line.lastIndexOf("/s) - `") != -1) {
+			String current_file_downloading = line.substring(line.indexOf("`") + 1, line.lastIndexOf("'"));
+			if(!ignore_for_robots) {
+			    DebugStream.println("Not ignore for robots");
+			    // Download complete
+			    downloadComplete(current_file_downloading);
+			}
+			else {
+			    DebugStream.println("Ignore for robots");
+			    ignore_for_robots = false;
+			}
+		    }
+		    // The already there line begins "File `..." However this
+		    // is only true in english, so instead I looked and there
+		    // are few (if any at all) other messages than those above
+		    // and not overwriting messages that use " `" so we'll 
+		    // look for that. Note this method is not guarenteed to be
+		    // unique like the previous two.
+		    else if(line.lastIndexOf(" `") != -1) {
+			// Not Overwriting
+			DebugStream.println("Already there.");
+			String new_url = 
+			    line.substring(line.indexOf("`") + 1, line.lastIndexOf("'"));
+			//addDownload("http:/" + new_url);
+			downloadWarning();
+		    }
+		    // Any other important message starts with the time in the form hh:mm:ss
+		    else if(line.length() > 7) {
+			if(line.charAt(2) == ':' && line.charAt(5) == ':') {
+			    if(!ignore_for_robots) {
+				DebugStream.println("Error.");
+				downloadFailed();
+			    }
+			    else {
+				ignore_for_robots = false;
+			    }
+			}
+		    }
+		}
+		else if (max_download == DownloadJob.DEFINED_MAX) {
+		    if (line.lastIndexOf("<<Total number of record(s):") != -1) {
+			String total_ID = line.substring(line.indexOf(":") + 1, line.indexOf(">"));
+			progress.setTotalDownload((Integer.valueOf(total_ID)).intValue());
+			progress.resetFileCount();
+		    }
+		    else if (line.lastIndexOf("<<Done>>") != -1) {
+			progress.increaseFileCount();
+		    }
+		    else if(line.lastIndexOf("<<Done:") != -1) {
+			String completed_amount = line.substring(line.indexOf(":") + 1, line.indexOf(">"));
+			progress.increaseFileCount((Integer.valueOf(completed_amount)).intValue());
+		    }
+		    
+		    DebugStream.println(line);
+		    download_log.appendLine(line);
+		}
+		else {
+		    System.out.println("Error!!");
+		    System.exit(-1);
+		}
+	    }
+	    if(state == STOPPED) {
+		isr.close();
+		prcs.destroy(); // This doesn't always work, but it's worth a try
+	    }
+	   
+	}
+	catch (Exception ioe) {
+	    //message(Utility.ERROR, ioe.toString());
+	    //JTest
+	    DebugStream.printStackTrace(ioe);
+	}
+	// If we've got to here and the state isn't STOPPED then the
+	// job is complete.
+	if(state == DownloadJob.RUNNING) {
+	    progress.mirrorComplete();
+	    previous_state = state;
+	    state = DownloadJob.COMPLETE;
+	    
+	}
+	// refresh the workspace tree
+ 	Gatherer.g_man.refreshWorkspaceTree(WorkspaceTree.DOWNLOADED_FILES_CHANGED);
+       
+    }
+
+
+    /** Called by the WGet native code when the current download is 
+     * completed. In turn all download listeners are informed.
+     */
+    public void downloadComplete() {
+	progress.downloadComplete();
+    }
+
+
+    public void downloadComplete(String current_file_downloading)
+    {
+	progress.downloadComplete();
+	DebugStream.println("Download complete: " + current_file_downloading);
+    }
+
+
+    /** Called by the WGet native code when the requested download returns
+     * a status code other than 200.
+     */
+    public void downloadFailed() {
+	// TODO!!
+	//failed_urls.add(current_url); // It is the current url that failed
+	progress.downloadFailed();
+	//DebugStream.println("Download failed: " + current_url);
+    } 
+	 
+    /**
+     */
+    public void downloadWarning() {
+	progress.downloadWarning();
+    }
+
+    public AppendLineOnlyFileDocument getLogDocument() {
+	return download_log;
+    }
+
+    /**
+     * @return Returns the progress bar associated with this job.
+     */
+    public DownloadProgressBar getProgressBar() {
+	return progress;
+    }
+
+    /** Called to discover if the user wanted this thread to run or if
+     * it is paused.
+     * @return An int representing the current DownloadJob state.
+     */
+    public int getState() {
+	return state;
+    }
+
+    /** Returns the current state of the stop flag for this job.
+     * @return A boolean representing whether the user has requested to
+     * stop.
+     */
+    public boolean hasSignalledStop() {
+	if(state == DownloadJob.STOPPED || state == DownloadJob.PAUSED || 
+	   state == DownloadJob.COMPLETE) {
+	    return true;
+	}
+	return false;
+    }
+
+    public void setState(int state) {
+	previous_state = this.state;
+	this.state = state;
+    }
+
+    /** A convenience call.
+     * @return A String representing the url of the initial url (root node of the mirrored tree).
+     */
+    public String toString() {
+	return download_url;
+    }
+
+    /** Called by the WGet native code to signal the current progress of 
+     * downloading.
+     * @param current A long representing the number of bytes that have 
+     * been downloaded since the last update. 
+     * @param expected A long representing the total number of bytes
+     * expected for this download.
+     */
+    public void updateProgress(long current, long expected) {
+	progress.updateProgress(current, expected);
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/download/DownloadProgressBar.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/download/DownloadProgressBar.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/download/DownloadProgressBar.java	(revision 13928)
@@ -0,0 +1,421 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.download;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.border.*;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+//import org.greenstone.gatherer.collection.DownloadJob;
+import org.greenstone.gatherer.util.AppendLineOnlyFileDocument;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.gui.*;
+
+public class DownloadProgressBar
+    extends JPanel 
+    implements ActionListener {
+
+    private boolean simple = false;
+
+    private Dimension bar_size = new Dimension(520, 25);
+
+    private Dimension MINIMUM_BUTTON_SIZE = new Dimension(100, 25);
+    private  Dimension PROGRESS_BAR_SIZE = new Dimension(580,75);
+    
+    private int current_action;
+    private int err_count;
+    private int file_count;
+    private int total_count;
+    private int warning_count;
+
+    private JLabel current_status;
+    private JLabel main_status;
+    private JLabel results_status;
+	 
+    private JPanel center_pane;
+    private JPanel inner_pane;
+
+    private JProgressBar progress;
+
+    private long file_size;
+    private long total_size;
+
+    private String current_url;
+    private String initial_url;
+
+    private DownloadJob owner;
+
+    public JButton stop_start_button;
+    public JButton log_button;
+    public JButton close_button;
+
+    public DownloadProgressBar(DownloadJob owner, String initial_url, boolean simple) {
+	this.owner = owner;
+	this.current_url = null;
+	this.err_count = 0;
+	this.initial_url = initial_url;
+	this.file_count = 0;
+	this.file_size = 0;
+	this.simple = simple;
+	this.total_count = 0;
+	this.total_size = 0;
+	this.warning_count = 0;
+
+	this.setLayout(new BorderLayout());
+	this.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
+
+	this.current_action = DownloadJob.STOPPED;
+
+	inner_pane = new JPanel(new BorderLayout());
+	inner_pane.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
+
+	center_pane = new JPanel(new GridLayout(3,1));
+
+	main_status = new JLabel();
+
+	current_status = new JLabel();
+		  
+	results_status = new JLabel();
+
+	progress = new JProgressBar();
+	progress.setStringPainted(true);
+	progress.setMinimum(0);
+	progress.setMaximum(0);
+	progress.setEnabled(false);
+	progress.setString(Dictionary.get("Mirroring.DownloadJob.Waiting"));
+	inner_pane.add(progress, BorderLayout.CENTER);
+
+	center_pane.add(main_status);
+	center_pane.add(current_status);
+	center_pane.add(results_status);
+
+	JPanel button_pane = new JPanel();
+
+	stop_start_button = new GLIButton(Dictionary.get("Mirroring.DownloadJob.Pause"),Dictionary.get("Mirroring.DownloadJob.Pause_Tooltip"));
+	stop_start_button.addActionListener(this);
+	stop_start_button.addActionListener(owner);
+	stop_start_button.setMinimumSize(MINIMUM_BUTTON_SIZE);
+	stop_start_button.setMnemonic(KeyEvent.VK_P);
+	stop_start_button.setEnabled(true);
+	
+
+	log_button = new GLIButton(Dictionary.get("Mirroring.DownloadJob.Log"),Dictionary.get("Mirroring.DownloadJob.Log_Tooltip"));
+	log_button.addActionListener(owner);
+	log_button.addActionListener(this);
+	log_button.setEnabled(false);
+	log_button.setMinimumSize(MINIMUM_BUTTON_SIZE);
+	log_button.setMnemonic(KeyEvent.VK_L);
+
+
+	close_button =  new GLIButton(Dictionary.get("Mirroring.DownloadJob.Close"),Dictionary.get("Mirroring.DownloadJob.Close_Tooltip"));
+	close_button.addActionListener(owner);
+	close_button.addActionListener(this);
+	close_button.setMinimumSize(MINIMUM_BUTTON_SIZE);
+	close_button.setMnemonic(KeyEvent.VK_C);
+	close_button.setEnabled(true);
+
+
+	// Layout - or at least some of it
+
+	inner_pane.add(center_pane, BorderLayout.NORTH);
+
+	button_pane.setLayout(new GridLayout(3,1));
+	button_pane.add(stop_start_button);
+	button_pane.add(log_button);
+	button_pane.add(close_button);
+
+	this.add(inner_pane, BorderLayout.CENTER);
+	this.add(button_pane, BorderLayout.EAST);
+
+	// Make the labels, etc update.
+	refresh();
+    }
+
+    public void actionPerformed(ActionEvent event) {
+	Object source = event.getSource();
+	if(source == stop_start_button) {
+	    // If we are running, stop.
+	    if (current_action == DownloadJob.RUNNING) {
+		current_action = DownloadJob.STOPPED;
+                stop_start_button.setText(Dictionary.get("Mirroring.DownloadJob.Resume"));
+                stop_start_button.setToolTipText(Dictionary.get("Mirroring.DownloadJob.Resume_Tooltip"));
+	        
+		progress.setString(Dictionary.get("Mirroring.DownloadJob.Download_Stopped"));
+		progress.setIndeterminate(false);
+	    } else {
+		current_action = DownloadJob.RUNNING;
+		// we are stopped, so restart
+                stop_start_button.setText(Dictionary.get("Mirroring.DownloadJob.Pause"));
+                stop_start_button.setToolTipText(Dictionary.get("Mirroring.DownloadJob.Pause_Tooltip"));
+		progress.setString(Dictionary.get("Mirroring.DownloadJob.Download_Progress"));
+		progress.setIndeterminate(true);
+	    }
+	}
+	else if(source == close_button) {
+	    // If we are running, stop.
+	    if (current_action == DownloadJob.RUNNING) {
+		current_action = DownloadJob.STOPPED;
+             	progress.setString(Dictionary.get("Mirroring.DownloadJob.Download_Stopped"));
+	
+		progress.setIndeterminate(false);
+	    }
+	}
+	else if(source == log_button) {
+           
+	    LogDialog dialog = new LogDialog(owner.getLogDocument());
+	    dialog.setVisible(true);
+	    dialog = null;
+	}
+
+	refresh();
+    }
+
+    /** This method is called when a new download is begun. The
+     * details of the download are updated and a new JProgressBar
+     * assigned to track the download.
+     * @param url The url String of the file that is being downloaded.
+     */
+    public void addDownload(String url) {
+	current_url = url;
+	file_size = 0;
+	refresh();
+    }
+
+    /** When the download of the current url is completed, this method
+     * is called to enlighten the DownloadProgressBar of this fact.
+     */
+    public void downloadComplete() {
+	current_url = null;
+	file_count++;
+	if(total_count < (file_count + err_count + warning_count)) {
+	    total_count = (file_count + err_count + warning_count);
+	}
+	progress.setValue(progress.getMaximum());
+	//Dictionary.setText(progress, "Mirroring.DownloadJob.Download_Complete");
+	refresh();
+    }
+
+    public void downloadFailed() {
+	err_count++;
+	if(total_count < (file_count + err_count + warning_count)) {
+	    total_count = (file_count + err_count + warning_count);
+	}
+	refresh();
+    }
+
+    public void downloadWarning() {
+	warning_count++;
+	if(total_count < (file_count + err_count + warning_count)) {
+	    total_count = (file_count + err_count + warning_count);
+	}
+	refresh();
+    }
+
+    public void setTotalDownload(int total_download) {
+	total_count = total_download;
+	refresh();
+    }
+
+    public Dimension getPreferredSize() {
+	return PROGRESS_BAR_SIZE;
+    }
+
+    public void increaseFileCount() {
+	file_count++;
+	refresh();
+    }
+
+    public void increaseFileCount(int amount) {
+	file_count += amount;
+	refresh();
+    }
+
+    public void resetFileCount() {
+	file_count = 0;
+	refresh();
+    }
+
+    /** When a mirroring task is first initiated this function is called
+     * to set initial values for the variables if necessary and to 
+     * fiddle visual components such as the tool tip etc.
+     * @param reset A Boolean specifying whether the variables should be
+     * reset to zero.
+     */
+    public void mirrorBegun(boolean reset, boolean simple) {
+	if(reset) {
+	    this.file_count = 0;
+	    this.file_size = 0;
+	    this.total_count = 0;
+	    this.total_size = 0;
+	    this.err_count = 0;
+	    this.warning_count = 0;
+	}
+	current_action = DownloadJob.RUNNING;
+	stop_start_button.setEnabled(true);
+	log_button.setEnabled(true);
+	if(simple) {
+	    progress.setIndeterminate(true);
+	    progress.setString(Dictionary.get("Mirroring.DownloadJob.Download_Progress"));
+	}
+    }	
+
+    /** Once a mirroring task is complete, is the DownloadJob returns from the
+     * native call but the status is still running, then this method
+     * is called to once again tinker with the pritty visual 
+     * components.
+     */
+    public void mirrorComplete() {
+	current_action = DownloadJob.COMPLETE;
+	current_url = null;
+	if(simple) {
+	    progress.setIndeterminate(false);
+	}
+	progress.setValue(progress.getMaximum());
+	progress.setString(Dictionary.get("Mirroring.DownloadJob.Download_Complete"));
+
+	stop_start_button.setEnabled(false);
+	this.updateUI();
+    }
+
+    /** When called this method updates the DownloadProgressBar to reflect
+     * the ammount of the current file downloaded.
+     */
+    public void updateProgress(long current, long expected) {
+	file_size = file_size + current;
+	if(!progress.isIndeterminate()) {
+	    // If current is zero, then this is the 'precall' before the
+	    // downloading actually starts.
+	    if(current == 0) {
+		// Remove the old progress bar, then deallocate it.
+		inner_pane.remove(progress);
+		progress = null;
+		if(expected == 0) {
+		    // We don't have a content length. This bar will go from 0 to 100 only!
+		    progress = new JProgressBar(0, 100);
+		}
+		else {
+		    // Assign a new progress bar of length expected content length.
+		    progress = new JProgressBar(0, (new Long(expected)).intValue());
+		}
+		progress.setEnabled(true);
+		// Add the new progress bar.
+		inner_pane.add(progress, BorderLayout.CENTER);
+		inner_pane.updateUI();
+	    }
+	    // Otherwise if expected is not zero move the progress bar and
+	    // update percent complete.
+	    else if (expected != 0) {
+		progress.setValue((new Long(file_size)).intValue());
+		int p_c = (new Double(progress.getPercentComplete() * 100)).intValue();
+		progress.setString(p_c + "%");
+		progress.setStringPainted(true);
+	    }
+	    // Finally, in the case we have no content length, we'll instead
+	    // write the current number of bytes downloaded again.
+	    else {
+		progress.setString(file_size + " b");
+		progress.setStringPainted(true);
+	    }
+	}
+	refresh();
+    }
+
+    /** Causes the two labels associated with this DownloadProgressBar object to
+     * update, thus reflecting the progression of the download. This 
+     * method is called by any of the other public setter methods in this 
+     * class.
+     */
+    private void refresh() {
+	// Refresh the contents of main label.
+	String args1[] = new String[1];
+	args1[0] = initial_url.toString();
+	main_status.setText(Dictionary.get("Mirroring.DownloadJob.Downloading", args1));
+
+	if (current_url != null) {
+	    // Refresh the current label contents.
+	    String args2[] = new String[1];
+	    args2[0] = current_url;
+	    current_status.setText(Dictionary.get("Mirroring.DownloadJob.Downloading", args2));
+	}
+	else if (current_action == DownloadJob.STOPPED || current_action == DownloadJob.PAUSED) {
+	    current_status.setText(Dictionary.get("Mirroring.DownloadJob.Waiting_User"));
+	}
+	else {
+	    current_status.setText(Dictionary.get("Mirroring.DownloadJob.Download_Complete"));
+	}
+
+	// Refresh the contents of results label
+	String args3[] = new String[4]; 
+	args3[0] = file_count + "";
+	args3[1] = total_count + "";
+	args3[2] = warning_count + "";
+	args3[3] = err_count + "";
+	results_status.setText(Dictionary.get("Mirroring.DownloadJob.Status", args3));
+
+	this.updateUI();
+    }
+
+    static final private Dimension DIALOG_SIZE = new Dimension(640,480);
+
+    private class LogDialog
+	extends JDialog {
+	
+	public LogDialog(AppendLineOnlyFileDocument document) {
+	    super(Gatherer.g_man, Dictionary.get("Mirroring.DownloadJob.Log_Title"));
+	    setSize(DIALOG_SIZE);
+	    JPanel content_pane = (JPanel) getContentPane();
+	    JTextArea text_area = new JTextArea(document);
+	    JButton button = new GLIButton(Dictionary.get("General.Close"));
+	    // Connection
+	    button.addActionListener(new CloseActionListener());
+	    // Layout
+	    content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	    content_pane.setLayout(new BorderLayout());
+	    content_pane.add(new JScrollPane(text_area), BorderLayout.CENTER);
+	    content_pane.add(button, BorderLayout.SOUTH);
+	}
+
+	private class CloseActionListener
+	    implements ActionListener {
+	    public void actionPerformed(ActionEvent event) {
+		LogDialog.this.dispose();
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/download/DownloadScrollPane.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/download/DownloadScrollPane.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/download/DownloadScrollPane.java	(revision 13928)
@@ -0,0 +1,225 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.download;
+
+import java.awt.*;
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.*;
+
+/** This class provides access to the functionality of the WGet program, either by calling it via a shell script or by the JNI. It maintains a queue of pending jobs, and the component for showing these tasks to the user.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class DownloadScrollPane
+    extends Thread {
+    
+    /** <i>true</i> if there is a task currently being carried out, <i>false</i> otherwise. */
+    private boolean busy = false;
+    /** <i>true</i> if verbose debug messages should be displayed, <i>false</i> otherwise. */
+    private boolean debug = false;
+    /** <i>true</i> if successfully completed tasks should be automatically removed from the job queue. */
+    private boolean remove_complete_jobs = true;
+
+    private JPanel filler_pane = null;
+    /** The panel that the task list will be shown in. */
+    private JPanel list_pane;
+    /** The job currently underway. */
+    private DownloadJob job;
+    /** A scroll pane which will be used to display the list of pending tasks. */
+    private JScrollPane list_scroll;
+    /** A queue of download tasks. */
+    private Vector job_queue;
+    static final private boolean simple = true;
+    
+    public DownloadScrollPane() {
+	job = null;
+	job_queue = new Vector();
+	filler_pane = new JPanel();
+	list_pane = new JPanel();
+	list_pane.setLayout(new BoxLayout(list_pane, BoxLayout.Y_AXIS));
+	list_scroll = new JScrollPane(list_pane);
+    }
+
+    public void deleteDownloadJob(DownloadJob delete_me) {
+	if (delete_me == job) {
+	    while(busy) {
+	    }
+	    job = null;
+	}
+	if (delete_me.hasSignalledStop()) {
+	    list_pane.remove(delete_me.getProgressBar());
+	    job_queue.remove(delete_me);
+	    list_pane.remove(filler_pane);
+	    if(job_queue.size() > 0) {
+		Dimension progress_bar_size = delete_me.getProgressBar().getPreferredSize();
+		Dimension list_pane_size = list_pane.getSize();
+		int height = list_pane_size.height - (job_queue.size() * progress_bar_size.height);
+		progress_bar_size = null;
+		if(height > 0) {
+		    filler_pane.setPreferredSize(new Dimension(list_pane_size.width, height));
+		    list_pane.add(filler_pane);
+		}
+		list_pane_size = null;
+	    }
+	    list_pane.updateUI();
+	}
+	else {
+	    DebugStream.println("Somehow we're trying to delete a job that is still running.");
+	}
+    }
+
+    public synchronized void downloadComplete() {
+	job.downloadComplete();
+    }
+
+    public synchronized void downloadFailed() {
+	job.downloadFailed();
+    }
+
+    public synchronized void downloadWarning() {
+	job.downloadWarning();
+    }
+
+    public JScrollPane getDownloadJobList() {
+	return list_scroll;
+    }
+
+    public synchronized boolean hasSignalledStop() {
+	return job.hasSignalledStop();
+    }
+
+    public void newDownloadJob(Download download, String mode, String proxy_url) {
+	// Create the job and fill in the details from gatherer.config.
+
+	DebugStream.println("About to create a new job");
+
+
+        DownloadJob new_job = new DownloadJob(download, Configuration.proxy_pass, Configuration.proxy_user, this, mode, proxy_url);
+	// Tell it to run as soon as possible
+
+      
+
+	new_job.setState(DownloadJob.RUNNING);
+	
+	// Add to job_queue job list.
+	job_queue.add(new_job);
+
+	// Now add it to the visual component, job list.
+
+	list_pane.remove(filler_pane);
+
+	Dimension progress_bar_size = new_job.getProgressBar().getPreferredSize();
+
+	Dimension list_pane_size = list_pane.getSize();
+
+	int height = list_pane_size.height - (job_queue.size() * progress_bar_size.height);
+
+	progress_bar_size = null;
+
+	list_pane.add(new_job.getProgressBar());
+
+	if(height > 0) {
+	    filler_pane.setPreferredSize(new Dimension(list_pane_size.width, height));
+	    list_pane.add(filler_pane);
+	}
+
+	list_pane_size = null;
+	//list_pane.setAlignmentX(Component.LEFT_ALIGNMENT);
+	list_pane.updateUI();
+	new_job = null;
+	synchronized(this) {
+	    notify(); // Just incase its sleeping.
+	}
+    }
+    
+    public synchronized void updateProgress(long current, long expected) {
+	job.updateProgress(current, expected);
+    }
+    
+    /* There may be times when the download thread is sleeping, but the
+     * user has indicated that a previously paused job should now begin
+     * again. The flag within the job will change, so we tell the thread
+     * to start again.
+     */
+    public void resumeThread() {
+	synchronized(this) {
+	    notify(); // Just incase its sleeping.
+	}
+    }
+    
+    public void run() {
+	while(true) {
+	    if(job_queue.size() > 0) {
+		int index = 0;
+		while(job_queue.size() > 0 && index < job_queue.size()) {
+		    job = (DownloadJob) job_queue.get(index);
+		    if(job.getState() == DownloadJob.RUNNING) {
+			DebugStream.println("DownloadJob " + job.toString() + " Begun.");
+			busy = true;
+			job.callDownload();
+			busy = false;
+			DebugStream.println("DownloadJob " + job.toString() + " complete.");
+			job = null;
+		    }
+		    index++;
+		}
+		try {
+		    synchronized(this) {
+			DebugStream.println("WGet thread is waiting for DownloadJobs.");
+			wait();
+		    }
+		} catch (InterruptedException e) {
+		    // Time to get going again.
+		}
+	    }
+	    else {
+		try {
+		    synchronized(this) {
+			DebugStream.println("WGet thread is waiting for DownloadJobs.");
+			wait();
+		    }
+		} catch (InterruptedException e) {
+		    // Time to get going again.
+		}
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/download/ServerInfoDialog.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/download/ServerInfoDialog.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/download/ServerInfoDialog.java	(revision 13928)
@@ -0,0 +1,150 @@
+package org.greenstone.gatherer.download;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.border.*;
+import javax.swing.event.*;
+import java.io.*;
+import java.util.ArrayList;
+import org.greenstone.gatherer.cdm.Argument;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.greenstone.LocalGreenstone;
+import org.greenstone.gatherer.gui.*;
+import org.greenstone.gatherer.util.Utility;
+
+public class ServerInfoDialog extends JDialog
+{    
+    static private Dimension SIZE = new Dimension(500, 300);
+    private String url;
+    private String mode;
+    private JPanel info_list_pane;
+    private JScrollPane info_scroll_pane;
+    private JDialog info_dialog;
+    private Download download;
+    private String proxy_url;
+    
+    public ServerInfoDialog(String url, String proxy_url, String mode, Download download) {
+	super();
+	this.url = url;
+	this.mode = mode;
+        this.download = download;
+        this.proxy_url = proxy_url;
+	this.info_dialog = this;
+	
+	this.setSize(SIZE);
+
+ 	JButton close_button = new GLIButton(Dictionary.get("General.Close"),Dictionary.get("General.Close_Tooltip"));
+ 	close_button.setEnabled(true); 
+	close_button.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent event) {
+		    info_dialog.dispose();
+		}
+	    });
+	
+	JPanel button_pane = new JPanel();
+	button_pane.setLayout(new FlowLayout());
+	button_pane.setBorder(BorderFactory.createEtchedBorder());
+	button_pane.add(close_button);
+	
+	info_list_pane = new JPanel();
+	info_list_pane.setLayout(new BoxLayout(info_list_pane, BoxLayout.Y_AXIS));
+	info_list_pane.setBorder(BorderFactory.createEtchedBorder());
+	getServerInfo();
+
+	info_scroll_pane = new JScrollPane(info_list_pane);
+	
+	JPanel information_pane = new JPanel();
+	information_pane.setLayout(new BorderLayout());
+	information_pane.setBorder(BorderFactory.createEtchedBorder());
+	information_pane.add(info_scroll_pane,BorderLayout.CENTER);
+	
+	JPanel main_pane = new JPanel();
+	main_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	main_pane.setLayout(new BorderLayout());
+	main_pane.add(information_pane,BorderLayout.CENTER);
+	main_pane.add(button_pane,BorderLayout.SOUTH);
+
+	Container main_container = this.getContentPane();
+	main_container.add(main_pane);
+	
+	// Show
+	Dimension screen_size = Configuration.screen_size;
+	setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+	setVisible(true);
+
+    }
+
+    private void getServerInfo()
+    {
+	ArrayList commands = new ArrayList();
+	if (Utility.isWindows()) {
+	    commands.add(Configuration.perl_path);
+	    commands.add("-S");
+	}
+	commands.add(LocalGreenstone.getBinScriptDirectoryPath()+"downloadfrom.pl");
+	commands.add("-info");
+	commands.add("-download_mode");
+	commands.add(mode);
+	
+       	ArrayList all_arg = download.getArguments(true,false);
+	for (int i = 0; i < all_arg.size(); i++) {
+	    Argument argument = (Argument) all_arg.get(i);
+	    
+	    if(argument.isAssigned()) {
+		commands.add("-" + argument.getName());
+		if(argument.getType() != Argument.FLAG) {
+		    commands.add(argument.getValue());
+		}
+	    }   
+	}
+	
+	String[] command = (String[]) commands.toArray(new String[0]);
+	DebugStream.println("Getting server info: "+commands);
+	try {
+	    String [] env = null;
+	    Process prcs = null; 
+	    Runtime rt = Runtime.getRuntime();
+	  
+	    if (Utility.isWindows()) {
+              	prcs = rt.exec(command);   
+	    }
+	    else {
+		if (proxy_url != null && !proxy_url.equals("")) {          	
+		    // Specify proxies as environment variables
+		    // Need to manually specify GSDLHOME and GSDLOS also
+		    env = new String[4];
+                    proxy_url = proxy_url.replaceAll("http://","");
+		    env[0] = "http_proxy=http://"+proxy_url;
+		    env[1] = "ftp_proxy=ftp://"+proxy_url;
+		    env[2] = "GSDLHOME=" + Configuration.gsdl_path;
+		    env[3] = "GSDLOS=" + Gatherer.client_operating_system;
+		    prcs = rt.exec(command, env); 
+		} 
+		else {
+		    // Will inherit the GLI's environment, with GSDLHOME and GSDLOS set
+		    prcs = rt.exec(command);
+		}
+	    }
+
+	    InputStreamReader isr = new InputStreamReader(prcs.getErrorStream());
+	    BufferedReader br = new BufferedReader(isr);
+	    String line;
+	    // Capture the standard error stream and seach for two particular occurances.
+	    while ((line = br.readLine()) != null && !line.trim().equals("<<Finished>>")) {
+	      
+		JLabel a_label = new JLabel(line);
+		a_label.setAlignmentX(Component.LEFT_ALIGNMENT);
+		info_list_pane.add(a_label);
+	    }
+	    
+	} catch (Exception ioe) {
+	  
+	}
+	
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/ActionRecorderDialog.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/ActionRecorderDialog.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/ActionRecorderDialog.java	(revision 13928)
@@ -0,0 +1,2135 @@
+package org.greenstone.gatherer.feedback;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import javax.swing.tree.*;
+import javax.swing.event.*;
+import javax.swing.text.*;
+import java.io.*;
+import java.awt.image.*;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.text.MessageFormat;
+import javax.swing.border.*;
+import java.text.*;
+
+import org.greenstone.gatherer.util.JarTools;
+
+/**
+ * This is the special class listener. 
+ * <p>This class will record all the action did to any of the
+ * component inside the window that were open by the application. 
+ * <br> This listener will start listening since the beginning of the application 
+ * until the user quits from the application. It will record :
+ * <br>1. All the information about the window and its components where the action occured.
+ * <br>2. All the information about all windows and its components that were open when the action occured.
+ * <br>Note : point 1 and 2 only start when user wants to send feedback.
+ * <br>3. The action's command the user did.
+ * <br>4. The date of when the action occured.
+ * <br><br>The history of the action will be stored in history.log file, which then will be compressed
+ * to a zip file called MyZipFile.zip.</p>
+ * <p>The listener this class implements are only the listener interface that a javax.swing.* component
+ * could have as stated in API.Some of the listener however is not implemented here as it is considered the event
+ * listened by those listener are not essential to be recorded as they not making any major changes
+ * to the application.</p> 
+ * <p>This listener will only record maximum last 60 instructions user did to the application.</p>
+ * <p>In this class also we can add some stuff globally through out all the window open by
+ * the application.
+ * <br>This is the class will add a menu called Feedback through out all the window of type JFrame or JDialog
+ * open by the application.This menu will allow user to either sending feedback or viewing the history
+ * of all the action user did so far.
+ * @author Veronica Liesaputra
+ */
+public class ActionRecorderDialog
+    implements ActionListener,TreeModelListener,ItemListener,ListDataListener,ChangeListener,
+	       ListSelectionListener,MenuListener,TableColumnModelListener,TreeSelectionListener
+{
+    /**
+     * This hold the title of the window where the action occured.
+     */
+    private String myframe;
+
+    /**
+     * This hold the title of the window where user called send feedback.
+     */
+    private String feedbackframe;
+
+    /**
+     * This hold the instance of ComponentInformation to get all the information inside a window.
+     */
+    private ComponentInformation compInfo;
+    
+    /**
+     * This will hold a record of the action that user just did at the moment.
+     */
+    private History log;
+
+    /**
+     * This will reference to the window where the action occured.
+     */
+    private Window point;
+   
+    /**
+     * This hold the vector of all the History instances of all the record of action user did
+     * so far.
+     * This vector will hold the history of all the 30 actions user just did.
+     * There are 2 situation for this vector :
+     * <br>1. Before user choose to send feedback.
+     * <br>Here, If we want to add another record to the vector when the vector size already 30 then,
+     * all the 30 records inside the vector will be saved in the temp_history.log file. The vector will
+     * be cleared and then added with the new record.
+     * <br>If the user quits the application, then whats in the vector will be saved to history.log file.
+     * <br>2. After user choose to send feedback.
+     * <br>When user choose to send feedback,then what happen is what ever inside the vector at the moment
+     * will be saved to history.log file and then vector will be cleared and it will add the new instruction.
+     * <br> If we want to add another record to the vector when the vector size already 30 then,
+     * all the 30 records inside the vector will be saved in the temp_feedbackhist.log file. The vector will
+     * be cleared and then added with the new record.
+     * <br> If the user finished with the feedback then it will cleared all the vector and load the vector
+     * inside the history.log to it and add the new record to the vector.
+     * <br> If the user quits the application, then whats in the vector will not be saved.
+     */
+    private static Vector vector;
+
+    /**
+     * This is the flag to tell whether or not the image for the window where the action occured is
+     * finished being added properly to the appropriate record.
+     * If savefinish = true then it means that the thread of adding image to the record stop, otherwise
+     * it means its not yet finished so don't stop the thread.
+     */
+    private static boolean savefinish = true;
+
+    /**
+     * This is the thread that contains all the code that the application should be when the user exiting
+     * the application.
+     */
+    private Thread writeThread;
+
+    /**
+     * This is the thread that contains all the code to add the image of the window where the action
+     * occured to the proper record.
+     * This thread will stop if savefinish = true.
+     */
+    private Thread saveThread;
+
+    /**
+     * This is the runtime of this application.
+     */
+    private Runtime run;
+
+    /**
+     * This variable will hold the resource of the words that is stored in feedback.properties file.
+     * The calling using messages.getString(someString) will caused someString to be translated
+     * into some other string that is hold in that file.usually it will caused it to be translated
+     * to the language that the user use or choose to have as stated in Locale.
+     */
+    private static ResourceBundle messages;
+
+    /**
+     * This is an instance of ScreenShot that will allow this application to take screen shot of the whole
+     * screen or just the screen shot of the window where the actions occured.
+     */
+    private ScreenShot sh;
+
+    /**
+     * This HashMap stored the pair of model and its component.
+     * This will allow this listener to know which component the model where the actions occured belongs to.
+     */
+    private HashMap modelHash;
+
+    /**
+     * This is the flag variable to sign that the user start the Reporting Feedback sequence.
+     * If start_rec = false means that the user did not start reporting feedback sequence.
+     * Otherwise, it means the user start reporting feedback sequence, here there will be changes in the
+     * content of the vector used to save all the records.This also will change the appearance of the
+     * window that are currently open by the application. it will make toolbar value = true, rec = true and
+     * stop_rec = false.
+     */
+    private boolean start_rec = false;
+
+    /**
+     * This is the flag variable to sign that the user are now recording the Reporting Feedback sequence.
+     * If rec = true, it means its recording, otherwise its false.It also will decide
+     * the GUI appearance of the window that are currently open by the application.
+     */
+    private boolean rec = false;
+
+    /**
+     * This is the flag variable to sign that user are finished the Reporting Feedback sequence.
+     * If stop_rec = false, then it means user stop the Reporting Feedback sequence.So here, there will
+     * be changes in the vector's content. If rec = true then it will also delete the added toolbar on the currently open
+     * window by the application and its also will delete all the history and file taken when user doing the
+     * Reporting Feedback sequence.
+     */
+    private boolean stop_rec = true;
+
+    /**
+     * This is the thread do task to take history of the actions.
+     */
+    private Thread saveallThread;
+
+    /**
+     * This is the flag to say whether or not the send feedback button been pushed by user.
+     */
+    private boolean start_fd = false;
+
+    /**
+     * This is a blocker to say that user cannot do anything while we taking history.
+     */
+    private MouseListener mouse_blocker_listener = new MouseAdapter() {};
+
+    /**
+     * This is the feedback interface window.
+     */
+    private FeedbackInterface frame;
+
+    /**
+     * This is an instance of CompListener that will add listener to all the components inside it.
+     */
+    private CompListener compList;
+
+    /**
+     * This is the accelerator key (shortcuts key) for taking screenshot.
+     */
+    private KeyStroke shKey;
+
+    /**
+     * This is the accelerator key (shortcuts key) for reporting feedback.
+     */
+    private KeyStroke fdKey;
+
+    /**
+     * This is the accelerator key (shortcuts key) for viewing history.
+     */
+    private KeyStroke histKey;
+
+    /**
+     * This is the accelerator key (shortcuts key) for sending feedback straight away.
+     */
+    private KeyStroke sndfdKey;
+
+    /**
+     * This is the window that is active at the moment.
+     */
+    private Window activeWindow;
+
+    /**
+     * This is the modal window where user wants to take the screeshot or sending feedback.
+     */
+    private Window modalWindow;
+
+    /**
+     * This constructor will seeting up the data member to its appropriate value.
+     * It will get the vector that are stored in the history.log file and also it will
+     * setup the writeThread.
+     * @param currentLocale is the locale user choose all the text to be displayed as.
+     */
+    public ActionRecorderDialog (Locale currentLocale)
+    {
+	messages = ResourceBundle.getBundle("feedback",currentLocale);
+	setup_UIManager();
+
+	fdKey = KeyStroke.getKeyStroke("F2");
+	histKey = KeyStroke.getKeyStroke("F3");
+	shKey = KeyStroke.getKeyStroke("F5");
+	sndfdKey = KeyStroke.getKeyStroke("F12");
+	/*shKey = KeyStroke.getKeyStroke(KeyEvent.VK_SLASH,InputEvent.CTRL_MASK|
+	  InputEvent.SHIFT_MASK);*/
+
+	final ZipFile zip;
+	zip = new ZipFile();
+	zip.unZipFile();
+	vector = getPrev_log("history.log");
+	sh = new ScreenShot();
+	modelHash = new HashMap();
+	compInfo = new ComponentInformation(this,currentLocale,modelHash);
+        compList = new CompListener(this,modelHash);
+	EventQueue eq;
+	eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
+	eq.push(new MyEventQueue());
+	run = Runtime.getRuntime();
+	Runnable writeRun;
+	writeRun = new Runnable()
+	    {
+		public void run()
+		{
+		    try
+			{
+			    if (stop_rec == true)
+				{
+				    File f;
+				    f = new File("history.log");
+				    FileOutputStream fos;
+				    fos = new FileOutputStream("history.log");
+				    ObjectOutputStream oos;
+				    oos = new ObjectOutputStream(fos);
+				    oos.writeObject(vector);
+				    vector.removeAllElements();
+				    vector = getPrev_log("temp_history.log");
+				    oos.writeObject(vector);
+				    oos.close();
+				    f = new File("temp_history.log");
+				    f.delete();
+				}
+
+			    File f2;
+			    f2 = new File("feedbackhist.log");
+			    f2.delete();
+			    f2 = new File("temp_feedbackhist.log");
+			    f2.delete();
+
+			    zip.sendZipFile();
+			    writeThread = null;
+			}
+		    catch (IOException exp) {}
+		}
+	    };
+
+	writeThread = new Thread(writeRun);
+	run.addShutdownHook(writeThread);
+    }
+
+    /** change the locale for the resource bundle*/
+    public void setLocale(Locale loc) {
+	messages = ResourceBundle.getBundle("feedback",loc);
+    }
+    /**
+     * This method will setup some of the GUI appearance that window should have when the user
+     * choose to start the Reporting Feedback sequence.
+     */
+    public void setup_UIManager ()
+    {
+	// why do you do all this???
+	//UIManager.put("TabbedPane.selected",(new Color(224,240,224)));
+	//UIManager.put("Button.select",(new Color(224,240,224)));
+	//UIManager.put("ScrollBar.background",(new Color(176,208,176)));
+	//UIManager.put("ScrollBar.highlight",(new Color(224,240,224)));
+	//UIManager.put("ScrollBar.thumb",(new Color(224,240,224)));
+	//UIManager.put("ScrollBar.track",(new Color(224,240,224)));
+	//UIManager.put("Tree.textBackground",new Color(224,240,224));
+	//UIManager.put("Label.font",new Font("Dialog",Font.PLAIN,12));
+	//UIManager.put("ComboBox.font",new Font("Dialog",Font.PLAIN,12));
+	//UIManager.put("TextArea.font",new Font("Dialog",Font.PLAIN,12));
+    }
+
+    /**
+     * This method will get the information about all the components inside the window that are
+     * open by the application when the action occured and save it to vector.
+     * @param comp its the component where the user did the action.
+     * @param command its the action's command the user did.
+     */
+    private void saving (final Component comp,final String command)
+    {
+	if ((command.equals(messages.getString("SendFeedback"))) ||
+	    ((command.equals("FastSend")) && (stop_rec == false)))
+	    {
+		start_fd = true;
+	    }
+
+	Runnable saveall;
+	saveall = new Runnable ()
+	    {
+		public void run ()
+		{
+		    try
+			{
+			    Runnable savework;
+			    savework = new Runnable ()
+				{
+				    public void run ()
+				    {
+					Date curr_date;
+					curr_date = new Date();
+					log = new History(curr_date,command);
+
+					if ((start_fd == true)&&(command.equals(messages.getString("WindowOpened"))))
+					    {
+						start_rec = true;
+						rec = true;
+						start_fd = false;
+					    }
+
+					getFrame(comp,command);
+					saveState(command);
+					saveLog();
+
+					if ((point != null) && (rec == true))
+					    {
+						if (command.equals(messages.getString("WindowClosed")))
+						    {
+							if (point instanceof JDialog)
+							    if (((JDialog)point).isModal() == true)
+								if (point == modalWindow)
+								    frame.setComment(false);
+						    }
+					    }
+				    }
+				};
+
+			    SwingUtilities.invokeAndWait(savework);
+			}
+		    catch (Exception ex) {ex.printStackTrace();}
+		}
+	    };
+
+	saveallThread = new Thread(saveall);
+	saveallThread.start();
+    }
+
+    /**
+     * This method will get the screen shot of the window where the actions occured and
+     * add the image also its dimension to the passed record.
+     * It will caused the saveThread to start so it can allows other stuff to be run concurrently
+     * and this thread will be stopped when the screen shot of the window alreadyfinished taken.
+     * @param hst is the record where the image and its dimension should be stored to.
+     */
+    public void saveImage (final History hst)
+    {
+	Runnable saveRun;
+	saveRun = new Runnable()
+	    {
+		History hist = hst;
+		public void run()
+		{
+		    String img,width,height;
+		    Rectangle rect;
+		    int w, h,dimwidth,dimheight;
+		 
+		    if (point != null)
+			{
+			    dimwidth = sh.getWidth();
+			    dimheight = sh.getHeight();
+
+			    w = point.getWidth();
+			    h = point.getHeight();
+
+			    try
+				{
+				    rect = new Rectangle(point.getLocationOnScreen(),
+							 new Dimension(w,h));
+			    
+				    if (w >= dimwidth)
+					w = dimwidth - 50;
+				    
+				    width = "" +  w;
+				    
+				    if (h >= dimheight)
+					h = dimheight - 50;
+				    
+				    height = "" + h;
+				}
+			    catch (IllegalComponentStateException exp)
+				{
+				    rect = null;
+				    width = null;
+				    height = null;
+				}
+			}
+		    else
+			{
+			    rect = null;
+			    width = null;
+			    height = null;
+			}
+		    
+		    if (rect != null)
+			{
+			    img = sh.getImage(rect);
+			    if (savefinish == true)
+				{
+				    hist.setImage(img,height,width);
+				}
+			}
+		}
+	    };
+	
+	Thread saveThread;
+	saveThread = new Thread(saveRun);
+	saveThread.start();
+    }
+
+    /**
+     * This method will setup the savefinish value.
+     * (Precondition: (save != null))
+     * @param save the value savefinish should have.
+     */
+    public static void setSavefinish (boolean save)
+    {
+	savefinish = save;
+    }
+
+
+    /**
+     * This method will make the JMenu that is should be added to all the
+     * window opened by the application.
+     * <br>If rec = false then the JMenu will give user option to start the Reporting Feedback sequence
+     * or Sending feedback or to view the history of actions they have done so far.
+     * <br>If rec = true then the JMenu will only give user option to view the history of actions
+     * they have done so far or sending feedback or taking screenshot.
+     * @return JMenu that should be added to all window open.
+     */
+    public JMenu makeMenu ()
+    {
+	JMenu menu;
+	JMenuItem item,item2,item3;
+	ImageIcon icon,icon2,icon3;
+
+	icon3 = JarTools.getImage("fastsend.gif");
+	item3 = new JMenuItem(messages.getString("SendFeedback"), 
+			      new ImageIcon(icon3.getImage().getScaledInstance
+					    (20,20,Image.SCALE_SMOOTH)));
+	item3.setActionCommand("FastSend");
+	item3.addActionListener(this);
+	item3.setMnemonic(KeyEvent.VK_N);
+	item3.setAccelerator(sndfdKey);
+	item3.setToolTipText("Send feedback now");
+
+	item = null;
+
+	if (rec == false)
+	    {
+		icon = JarTools.getImage("feedback.gif");
+		item = new JMenuItem("Report Feedback",
+				     new ImageIcon(icon.getImage().getScaledInstance
+						   (20,20,Image.SCALE_SMOOTH)));
+		item.setActionCommand(messages.getString("SendFeedback"));
+		item.addActionListener(this);
+		item.setMnemonic(KeyEvent.VK_F);
+		item.setAccelerator(fdKey);
+		item.setToolTipText("Report feedback");
+	    }
+	else
+	    {
+		icon = JarTools.getImage("camera.gif");
+		item = new JMenuItem(messages.getString("ScreenShot"),
+				     new ImageIcon(icon.getImage().getScaledInstance
+						   (20,20,Image.SCALE_SMOOTH)));
+		item.setActionCommand("ScreenShot");
+		item.setMnemonic(KeyEvent.VK_S);
+		item.addActionListener(this);
+		item.setAccelerator(shKey);
+		item.setToolTipText("Take screenshot of the whole screen.");
+	    }
+
+	icon2 = JarTools.getImage("history.gif");
+	item2 = new JMenuItem(messages.getString("LookHistory"),
+			      new ImageIcon(icon2.getImage().getScaledInstance
+					    (20,20,Image.SCALE_SMOOTH)));
+	item2.setActionCommand(messages.getString("LookHistory"));
+	item2.addActionListener(this);
+	item2.setMnemonic(KeyEvent.VK_H);
+	item2.setAccelerator(histKey);
+	item2.setToolTipText(messages.getString("LookHistoryButton"));
+
+	menu = new JMenu (messages.getString("Feedback"));
+	menu.setMnemonic(KeyEvent.VK_D);
+
+
+	if (item != null)
+	    menu.add(item);
+
+	menu.add(item3);
+
+	menu.add(item2);
+
+	if (rec == true)
+	    menu.setBackground(new Color(176,209,217));
+	else
+	    menu.setBackground(new Color(204,204,204));
+
+	return menu;
+    }
+
+    public void refreshLocationAndSize(Window window) {
+
+	window.setLocation(window.getX(),window.getY());
+	
+	Toolkit kit;
+	kit = Toolkit.getDefaultToolkit();
+	Dimension screenSize;
+	screenSize = kit.getScreenSize();
+	int screenHeight;
+	screenHeight = screenSize.height;
+	int screenWidth;
+	screenWidth = screenSize.width;
+	
+	if ((window.getSize().width > screenWidth) &&
+	    (window.getSize().height > screenHeight)) {
+	    window.setSize(window.getPreferredSize());
+	}
+    }
+
+
+    /**
+     * This method will setup the GUI that this window should have at the moment.
+     * If start_rec is true then JMenu don't have the option to start Reporting Feedback sequence in it.
+     * If stop_rec is true and rec is true then JMenu there should be an option to start Reporting Feedback sequence in it.
+     * The JMenu will only be affected window of type JDialog and JFrame only.
+     * (Precondition: (window != null))
+     * @param window its the window that we want to set the GUI
+     */
+    public void setUI (Window window)
+    {	
+	if (start_rec == true) {
+	    if (window instanceof JFrame) {
+		JFrame a;
+		a = (JFrame) window;
+		
+		JMenuBar menuBar;
+		menuBar = a.getJMenuBar();
+		
+		if (menuBar != null) {
+		    
+		    JMenu temp_menu;
+		    temp_menu = menuBar.getMenu(menuBar.getMenuCount() - 1);
+		    temp_menu.setBackground(new Color(176,209,217));
+		    temp_menu.remove(0);
+		    
+		    JMenuItem item;
+		    ImageIcon icon;
+		    icon = JarTools.getImage("camera.gif");
+		    item = new JMenuItem(messages.getString("ScreenShot"),
+					 new ImageIcon(icon.getImage().getScaledInstance
+						       (20,20,Image.SCALE_SMOOTH)));
+		    item.setActionCommand("ScreenShot");
+		    item.setMnemonic(KeyEvent.VK_S);
+		    item.addActionListener(this);
+		    item.setAccelerator(shKey);
+		    item.setToolTipText("Take screenshot of this window");
+		    
+		    temp_menu.insert(item,0);
+		}
+		
+		refreshLocationAndSize(a);
+		a.validate();
+		a.repaint();
+	    }
+	    else if (window instanceof JDialog) {
+		
+		JDialog a;
+		a = (JDialog) window;
+		JMenuBar menuBar;
+		menuBar = a.getJMenuBar();
+		
+		if (menuBar != null) {
+		    
+		    JMenu temp_menu;
+		    temp_menu = menuBar.getMenu(menuBar.getMenuCount() - 1);
+		    temp_menu.setBackground(new Color(176,209,217));
+		    temp_menu.remove(0);
+		    
+		    JMenuItem item;
+		    ImageIcon icon;
+		    icon = JarTools.getImage("camera.gif");
+		    item = new JMenuItem(messages.getString("ScreenShot"),
+					 new ImageIcon(icon.getImage().getScaledInstance
+						       (20,20,Image.SCALE_SMOOTH)));
+		    item.setActionCommand("ScreenShot");
+		    item.setMnemonic(KeyEvent.VK_S);
+		    item.addActionListener(this);
+		    item.setAccelerator(shKey);
+		    item.setToolTipText("Take screenshot of this window");
+		    
+		    temp_menu.insert(item,0);
+		}
+		refreshLocationAndSize(a);
+		a.validate();
+		a.repaint();	
+	    }
+	    else if (window instanceof JWindow) {
+		JWindow a;
+		a = (JWindow) window;
+		
+		((JComponent) a.getContentPane()).unregisterKeyboardAction(fdKey);
+		
+		((JComponent) a.getContentPane()).registerKeyboardAction(this, "ScreenShot", shKey,JComponent.WHEN_IN_FOCUSED_WINDOW);
+	    }
+	    else
+		return;
+	}
+	else {
+	    
+	    if ((stop_rec == true) && (rec == true)) {
+		
+		if (window instanceof JFrame) {
+		    JFrame a;
+		    a = (JFrame) window;
+		    
+		    JMenuBar menuBar;
+		    menuBar = a.getJMenuBar();
+		    
+		    if (menuBar != null) {
+			
+			JMenu temp_menu;
+			temp_menu = menuBar.getMenu(menuBar.getMenuCount() - 1);
+			temp_menu.setBackground(new Color(204,204,204));
+			temp_menu.remove(0);
+			
+			ImageIcon icon;
+			JMenuItem item;
+			
+			icon = JarTools.getImage("feedback.gif");
+			item = new JMenuItem("Report Feedback", new ImageIcon(icon.getImage().getScaledInstance(20,20,Image.SCALE_SMOOTH)));
+			item.setActionCommand(messages.getString("SendFeedback"));
+			item.addActionListener(this);
+			item.setMnemonic(KeyEvent.VK_F);
+			item.setAccelerator(fdKey);
+			item.setToolTipText(messages.getString("SendFeedbackButton"));
+			
+			temp_menu.insert(item,0);
+		    }
+		    a.setSize(a.getPreferredSize());
+		    a.validate();
+		    a.repaint();
+		}
+		else if (window instanceof JDialog) {
+		    JDialog a;
+		    a = (JDialog) window;
+		    
+		    JMenuBar menuBar;
+		    menuBar = a.getJMenuBar();
+		    
+		    if (menuBar != null) {
+			
+			JMenu temp_menu;
+			temp_menu = menuBar.getMenu(menuBar.getMenuCount() - 1);
+			temp_menu.setBackground(new Color(204,204,204));
+			temp_menu.remove(0);
+			
+			ImageIcon icon;
+			JMenuItem item;
+			
+			icon = JarTools.getImage("feedback.gif");
+			item = new JMenuItem("Report Feedback", new ImageIcon(icon.getImage().getScaledInstance(20,20,Image.SCALE_SMOOTH)));
+			item.setActionCommand(messages.getString("SendFeedback"));
+			item.addActionListener(this);
+			item.setMnemonic(KeyEvent.VK_F);
+			item.setAccelerator(fdKey);
+			item.setToolTipText(messages.getString("SendFeedbackButton"));
+			
+			temp_menu.insert(item,0);
+		    }
+		    a.setSize(a.getPreferredSize());
+		    a.validate();
+		    a.repaint();
+		}
+		else if (window instanceof JWindow) {
+		    JWindow a;
+		    a = (JWindow) window;
+		    
+		    ((JComponent) a.getContentPane()).registerKeyboardAction(this, messages.getString("SendFeedback"), fdKey, JComponent.WHEN_IN_FOCUSED_WINDOW);
+		    
+		    ((JComponent) a.getContentPane()).unregisterKeyboardAction(shKey);
+		    
+		}
+		else
+		    return;
+	    }
+	    else
+		return;
+	}
+    }
+    
+    /**
+     * This will make an Window[] convert to ArrayList that contain list of Window.
+     * (Precondition: (windows != null))
+     * @param windows the array that we want to convert to ArrayList
+     * @return        the array list that contains all object in array windows.
+     */
+    public ArrayList addToArrayList (Window[] windows,ArrayList arr)
+    {
+	int i;
+
+	for (i = 0 ; i < windows.length ; i++)
+	    {
+		arr.add(windows[i]);
+	    }
+	
+	return arr;
+    }
+
+    /**
+     * This method will get all the information of the window that are currently open when the action
+     * occured and these windows are not the window where the action occured.
+     * It will add these windows information to the current record and it will also setting up the 
+     * GUI for each of these windows.
+     * @param command the action's command user did.
+     */
+    public void saveState(String command)
+    {
+	Window[] frame_windows;
+	ArrayList windows;
+	Frame[] frames;
+	int i,j;
+
+	if (log == null)
+	    return;
+	
+	windows = new ArrayList();
+
+	frames = Frame.getFrames();
+	for (i = 0 ; i<frames.length;i++) 
+	    {
+		frame_windows = frames[i].getOwnedWindows();
+		windows = addToArrayList(frame_windows,windows);
+		
+		for (j = 0;j < frame_windows.length ; j++)
+		    {
+			Window window;
+			window = frame_windows[j];
+
+			if (window == point)
+			    {
+				Container cont;
+				cont = window.getParent();
+
+				if ((cont != null) && (cont instanceof Window) &&
+				    (windows.contains(cont) == false)&&(cont != point))
+				    {
+					if (cont instanceof ReportDetails.View) {}
+					else if (cont instanceof Movie) {}
+					else
+					    {
+						setUI((Window) cont);
+						
+						/*if (rec == true)
+						    {
+							log.addComponent(compInfo.getInside((Window) cont),
+									 messages.getString("CurrentlyOpenWindow"));
+						    }
+						    else*/
+						    compList.getInside((Window) cont);
+						
+						windows.add(cont);
+					    }
+				    }	
+				else
+				    {}
+			    }
+			else
+			    {
+				if (window instanceof ReportDetails.View) {}
+				else if (window instanceof Movie) {}
+				else
+				    {
+					if ((window != null) && (window != point))
+					    {
+						setUI(window);
+						
+						if (rec == true)
+						    {
+							log.addComponent(compInfo.getInside((Window) window),
+									 messages.getString("CurrentlyOpenWindow"));
+						    }
+						else
+						    compList.getInside((Window) window);
+						
+						Container cont;
+						cont = window.getParent();
+						
+						if ((cont != null) && (cont instanceof Window) &&
+						    (cont != point) && (windows.contains(cont) == false))
+						    {
+							if (cont instanceof ReportDetails.View) {}
+							else if (cont instanceof Movie) {}
+							else
+							    {
+								setUI((Window)cont);
+								
+								/*if (rec == true)
+								    {
+									log.addComponent(compInfo.getInside((Window) cont),
+											 messages.getString("CurrentlyOpenWindow"));
+								    }
+								    else*/
+								    compList.getInside((Window) cont);
+
+								windows.add(cont);
+							    }
+						    }
+						else {}
+					    }
+				    }
+			    }
+		    }
+	    }
+    }
+
+    /**
+     * This method will get all the information about the window where the actions occured and it also will setting up
+     * how hthe GUI should look like in this window and it will also take the image of this window.
+     * @param comp is the component where the actions happened.
+     * @param command is the command of user's action
+     */
+    public void getFrame (Component comp,String command)
+    {
+	boolean cls;
+	
+	cls = false;
+	point = null;
+	
+	Container frame; 
+	myframe = null;
+	
+	if (comp == null)
+	    return;
+	else if (comp instanceof Window)
+	    frame = (Container) comp;
+	else
+	    frame = SwingUtilities.getWindowAncestor(comp);
+	
+	if (frame instanceof Window)
+	    {
+		JMenu menu;
+		point = (Window) frame;
+
+		point.addMouseListener(mouse_blocker_listener);
+		point.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+
+		
+		if ((frame instanceof ReportDetails.View)||
+		    (frame instanceof Movie))
+		    {
+			log = null;
+			return;
+		    }
+		
+		if (command.equals(messages.getString("WindowClosed")))
+		    {
+			cls = true;
+			if (frame instanceof FeedbackInterface)
+			    {
+				stop_rec = true;
+			    }
+			else
+			    {}
+		    }
+		
+		if  (command.equals(messages.getString("WindowOpened")))
+		    {
+			menu = makeMenu();
+		    }
+		else
+		    {
+			menu = null;
+		    }
+		
+		if (frame instanceof JFrame)
+		    {
+			JFrame a;
+			a = (JFrame) frame;
+			
+			myframe = a.getTitle();
+			
+			if (menu != null)
+			    {
+				JMenuBar menuBar;
+				menuBar = a.getJMenuBar();
+				
+				if (menuBar == null)
+				    {
+					menuBar = new JMenuBar();
+					menuBar.add(menu);
+					a.setJMenuBar(menuBar);
+				    }
+				else
+				    menuBar.add(menu);
+			    }
+			
+			if ((menu != null))
+			    {
+				refreshLocationAndSize(a);
+				a.validate();
+				a.repaint();
+			    }
+		    }
+		else if (frame instanceof JDialog)
+		    {   
+			JDialog a;
+			a = (JDialog) frame;
+			
+			myframe = a.getTitle();
+			
+			if (menu != null)
+			    {
+				JMenuBar menuBar;
+				menuBar = a.getJMenuBar();
+				
+				if (menuBar == null)
+				    {
+					menuBar = new JMenuBar();
+					menuBar.add(menu);
+					a.setJMenuBar(menuBar);
+				    }
+				else
+				    menuBar.add(menu);
+			    }
+		    
+			if ((menu != null))
+			    {
+				refreshLocationAndSize(a);
+				a.validate();
+				a.repaint();
+			    }
+		    }
+		else if (frame instanceof JWindow)
+		    {
+			JWindow a;
+			a = (JWindow) frame;
+			
+			if (menu != null)
+			    {
+				((JComponent) a.getContentPane()).registerKeyboardAction(this,
+											 messages.getString("LookHistory"),
+											 histKey,
+											 JComponent.WHEN_IN_FOCUSED_WINDOW);
+				
+				if (rec == false)
+				    {
+					((JComponent) a.getContentPane()).registerKeyboardAction(this,
+												 messages.getString("SendFeedback"),
+												 fdKey,
+												 JComponent.WHEN_IN_FOCUSED_WINDOW);
+					
+					((JComponent) a.getContentPane()).unregisterKeyboardAction(shKey);
+				    }
+				else
+				    {
+					((JComponent) a.getContentPane()).unregisterKeyboardAction(fdKey);
+					
+					((JComponent) a.getContentPane()).registerKeyboardAction(this,
+												 "ScreenShot",
+												shKey,
+												 JComponent.WHEN_IN_FOCUSED_WINDOW);
+				    }
+			    }
+
+			if (cls == true)
+			    {
+				((JComponent) a.getContentPane()).unregisterKeyboardAction(fdKey);
+				
+				((JComponent) a.getContentPane()).unregisterKeyboardAction(shKey);
+			    }
+		    }
+		
+		/*if ((command.equals(messages.getString("WindowClosed")))||
+		  (log == null))
+		  {}
+		  else
+		  saveImage(log);*/
+
+		/*if (rec == true)
+		    log.addComponent(compInfo.getInside(point),command);
+		    else*/
+		    compList.getInside(point);
+
+		if (myframe == null)
+		    myframe = " ";
+		
+		log.setTitle(myframe);
+		
+		return;
+	    }
+	else
+	    return;
+    }
+
+    /**
+     * This method will add the current record to the vector.
+     */
+    public void saveLog()
+    {
+	if (start_rec == true)
+	    {
+		save_HistLog("history.log");
+		vector.removeAllElements();
+		System.gc();
+		start_rec = false;
+		stop_rec = false;
+		rec = true;
+	    }
+	
+	if (log != null)
+	    vector.add(0,log);
+
+	if (vector.size() > 30)
+	    {
+		if (rec == false)
+		    {
+			save_tempHistLog("history.log");
+		    }
+		else
+		    save_tempHistLog("feedbackhist.log");
+		vector.removeAllElements();
+		//vector.removeElementAt(vector.size() - 1);
+		System.gc();
+	    }
+
+	if ((rec == true) && (stop_rec == true))
+	    {
+		save_HistLog("feedbackhist.log");
+		vector.removeAllElements();
+		System.gc();
+		vector = getPrev_log("history.log");
+		File f2;
+		f2 = new File("feedbackhist.log");
+		f2.delete();
+		f2 = new File("temp_feedbackhist.log");
+		f2.delete();
+		start_rec = false;
+		stop_rec = true;
+		rec = false;
+	    }
+
+	if (point != null)
+	    {
+		point.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+		point.removeMouseListener(mouse_blocker_listener);
+	    }
+    }
+
+    /**
+     * This method will save whatever in the vector at the moment to a file
+     * with the specified filename.
+     * Then it will also save the vector inside the file with the name "temp_"
+     * concatenated with the specified filename into it.
+     * (Precondition : (filename != null))
+     * @param filename its the name of the file where the vector should be saved.
+     */
+    public void save_HistLog(String filename)
+    {
+	 try 
+	     {
+		 File f;
+		 f = new File(filename);
+		 FileOutputStream fos;
+		 fos = new FileOutputStream(f);
+		 ObjectOutputStream oos;
+		 oos = new ObjectOutputStream(fos);
+		 oos.writeObject(vector);
+		 vector.removeAllElements();
+		 System.gc();
+		 vector = getPrev_log("temp_"+ filename);
+		 oos.writeObject(vector);
+		 oos.close();
+		 f = new File("temp_" + filename);
+		 f.delete();
+		 writeThread = null;
+	     }
+	 catch (IOException exp) {}
+    }
+   
+    /**
+     * This method will save whatever in the vector at the moment to a file with a 
+     * name "temp_" concatenated with the specified filename into it.
+     * (Precondition : (filename != null))
+     * @param filename its part of the name of the file where the vector should be saved.
+     */
+    public void save_tempHistLog(String filename)
+    {
+	try
+	    {
+		File f;
+		f = new File("temp_"+ filename);
+		FileOutputStream fos;
+		fos = new FileOutputStream(f);
+		ObjectOutputStream oos;
+		oos = new ObjectOutputStream(fos);
+		oos.writeObject(vector);
+		oos.close();
+	    }
+	catch (IOException exp) {}
+    }
+
+    /**
+     * This method will get vector that is stored in a file with the specified filename and
+     * it will also save the second vector in that file to a file with a name
+     * temp_history.log.
+     * If file with the specified filename does not exist then it will return a new vector.
+     * (Precondition : (filename != null))
+     * @param filename is the name of the file where we want to get the vector.
+     * @return         the first vector saved in the file with the specified filename.
+     */
+    public Vector getPrev_log(String filename)
+    {
+	Vector stack;
+	ObjectInputStream ois;
+	stack = null;
+	try
+	    {
+		File f;
+		f = new File(filename);
+		if (f.exists() == true)
+		    {
+			FileInputStream fis;
+			fis = new FileInputStream(f);
+			ois = new ObjectInputStream(fis);
+			stack = (Vector) ois.readObject();
+
+			Vector stack2;
+			stack2 = null;
+
+			try
+			    {
+				stack2 = (Vector) ois.readObject();
+			    }
+			catch (EOFException e) {stack2 = null;}
+			
+			if (stack2 != null)
+			    {
+				File f2;
+				f2 = new File("temp_history.log");
+				FileOutputStream fos;
+				fos = new FileOutputStream(f2);
+				ObjectOutputStream oos;
+				oos = new ObjectOutputStream(fos);
+				oos.writeObject(stack2);
+				oos.close();
+				stack2.removeAllElements();
+				stack2 = null;
+				System.gc();
+			    }
+
+			ois.close();
+			return stack;
+		    }
+		else
+		    stack = new Vector(); 
+	    }
+	catch (IOException exp) {exp.printStackTrace();}
+	catch (ClassNotFoundException exp2) {System.out.println("class exp");}
+	
+	return stack;
+    }
+ 
+    /**
+     * This method will make sure that there is something running at the moment.
+     */
+    private static void ensureEventThread()
+    {
+	if (SwingUtilities.isEventDispatchThread())
+	    {
+		return;
+	    }
+	throw new RuntimeException("something running");
+    }
+    
+    /**
+     * This method will called the Conformation window to show up.
+     * @param err_array this is the array containing all the information taken when user doing the Feedback form.
+     * @param imgFile this is the array conataining the String representation of the images taken when user doing the 
+     *                Feedback form.
+     */
+    /*public void getVector(String[] err_array,String[] imgFile)
+    {
+	Conformation rd;
+	rd = new Conformation(vector,err_array,imgFile,messages);
+	return;
+	}*/
+
+    /**
+     * This method will get the vector that hold the history.
+     * @return the vector that hold the history stored so far.
+     */
+    public Vector getVector()
+    {
+	return vector;
+    }
+
+    /**
+     * This class will catch the window opened and window closed event.
+     * If an application open or close a window it will be listened by this class so the information
+     * about that window and all the other open window can be took.
+     */
+    class MyEventQueue extends EventQueue
+    { 
+	/**
+	 * This method  will catch the window opened and window closed event.
+	 * If an application open or close a window it will be listened by this class so the information
+	 * about that window and all the other open window can be took.
+	 * @param evt its the event.
+	 */
+	protected void dispatchEvent(AWTEvent evt) 
+	{
+	    super.dispatchEvent(evt);
+	    int id;
+	    id = evt.getID();
+	
+	    if ((id == WindowEvent.WINDOW_OPENED)||(id == WindowEvent.WINDOW_CLOSED))
+		{   
+		    String command;
+		    command = " ";
+		    
+		    if (id == WindowEvent.WINDOW_OPENED) command = messages.getString("WindowOpened");
+		    else if (id == WindowEvent.WINDOW_CLOSED) command = messages.getString("WindowClosed");
+		   
+		    WindowEvent e;
+		    e = (WindowEvent) evt;
+		    Window comp;
+		    comp =  e.getWindow();
+		 
+		    if ((comp instanceof ReportDetails.View)||
+			(comp instanceof Movie))
+			return;
+
+		    saving(comp,command);
+		}
+	}
+    }
+
+    /**
+     * This method will take the screenshot of the whole screen.
+     * @param p the window where user select to take screenshot.
+     * @return  the screenshot image.
+     */
+    //public byte[] recreateEvent (final Window p)
+    public BufferedImage recreateEvent (final Window p)
+    {
+	setup_UIManager();
+	Rectangle rect;
+	int w, h;
+	
+	if (p != null)
+	    {
+		w = p.getWidth();
+		h = p.getHeight();
+		
+		try
+		    {
+			rect = new Rectangle(p.getLocationOnScreen(),
+				 	     new Dimension(w,h));
+		    }
+		catch (IllegalComponentStateException exp)
+		    {
+			rect = null;
+		    }
+	    }
+	else
+	    {
+		rect = null;
+	    }
+	
+	if (rect != null)
+	    {
+		//byte[] img;
+		BufferedImage img;
+		img = sh.captureScreen();
+		
+		return img;
+	    }
+	else
+	    return null;
+    }
+
+    /**
+     * This method will listen to any action event that occured.
+     * It will allow this special listener class to record all the information inside all the
+     * window open when the action occured.
+     * @param e the ActionEvent.
+     */
+    public void actionPerformed(ActionEvent e)
+    {
+	String command;
+	command = e.getActionCommand();
+	Component comp;
+	comp = (Component)e.getSource();
+	
+	saving(comp,command);
+
+	if (myframe == null)
+	    myframe = " ";
+	
+	if("FastSend".equals(e.getActionCommand()))
+	    {
+		point.addMouseListener(mouse_blocker_listener);
+		point.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+
+		BufferedImage img;
+		boolean modal;
+			
+		modal = false;
+
+		img = recreateEvent(point);
+		
+		if (stop_rec == true)
+		    {
+			feedbackframe = myframe;
+			
+			JDialog.setDefaultLookAndFeelDecorated(true);
+			stop_rec = false;
+			frame = null;
+			frame = new FeedbackInterface(sh,feedbackframe,messages,this);
+			if ((img != null) && (savefinish == true))
+			    {
+				int x,y,w,h,iw,ih;
+				double wrat,hrat;
+				Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
+				
+				iw = (int) (dim.getWidth() - 60);
+				ih = (int) (dim.getHeight() * 0.75) - 50;
+				
+				wrat = iw/((double)dim.getWidth());
+				hrat = ih/((double)dim.getHeight());
+				
+				w = (int) (point.getWidth() * wrat);
+				h = (int) (point.getHeight() * hrat);
+				x = (int) (point.getLocationOnScreen().x * wrat);
+				y = (int) (point.getLocationOnScreen().y * hrat);
+
+				//frame.addScreenPanel(feedbackframe,sh.getBuffImage(),img);
+				frame.addScreenPanel(feedbackframe,img,x,y,w,h);
+			    }
+			frame.setVisible(false);
+		    }
+		else
+		    {
+			if ((img != null) &&(savefinish == true))
+			    {
+				int x,y,w,h,iw,ih;
+				double wrat,hrat;
+				Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
+				
+				iw = (int) (dim.getWidth() - 60);
+				ih = (int) (dim.getHeight() * 0.75) - 50;
+				
+				wrat = iw/((double)dim.getWidth());
+				hrat = ih/((double)dim.getHeight());
+				
+				w = (int) (point.getWidth() * wrat);
+				h = (int) (point.getHeight() * hrat);
+				x = (int) (point.getLocationOnScreen().x * wrat);
+				y = (int) (point.getLocationOnScreen().y * hrat);
+				
+				//frame.addScreenPanel(feedbackframe,sh.getBuffImage(),img);
+				if (point instanceof JDialog)
+				    modal = ((JDialog) point).isModal();
+				
+				feedbackframe = myframe;
+				frame.addScreenPanel(feedbackframe,img,x,y,w,h);
+			    }
+		    }
+		
+		ActionEvent evt;
+		evt = new ActionEvent(frame.send_button,ActionEvent.ACTION_PERFORMED,messages.getString("Send"));
+		
+		frame.actionPerformed(evt);
+
+		point.removeMouseListener(mouse_blocker_listener);
+		point.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));		 
+	    }
+
+	if(messages.getString("SendFeedback").equals(e.getActionCommand()))
+	    {
+		setup_UIManager();
+		//byte[] img;
+		BufferedImage img;
+		boolean modal;
+
+		point.addMouseListener(mouse_blocker_listener);
+		point.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+
+		modal = false;
+		
+		img = recreateEvent(point);
+		feedbackframe = myframe;
+		if (point instanceof JDialog)
+		    modal = ((JDialog)point).isModal();
+			
+		JDialog.setDefaultLookAndFeelDecorated(true);
+		stop_rec = false;
+		frame = null;
+		frame = new FeedbackInterface(sh,feedbackframe,messages,this);
+		if ((img != null) && (savefinish == true))
+		    {
+			int x,y,w,h,iw,ih;
+			double wrat,hrat;
+			Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
+
+			iw = (int) (dim.getWidth() - 60);
+			ih = (int) (dim.getHeight() * 0.75) - 50;
+			
+			wrat = iw/((double)dim.getWidth());
+			hrat = ih/((double)dim.getHeight());
+			
+			w = (int) (point.getWidth() * wrat);
+			h = (int) (point.getHeight() * hrat);
+			x = (int) (point.getLocationOnScreen().x * wrat);
+			y = (int) (point.getLocationOnScreen().y * hrat);
+		
+			//frame.addScreenPanel(feedbackframe,sh.getBuffImage(),img);
+			frame.addScreenPanel(feedbackframe,img,x,y,w,h);
+			frame.setComment(modal);
+			
+			if (modal == true)
+			    {
+				modalWindow = point;
+			    }
+		    }
+
+		point.removeMouseListener(mouse_blocker_listener);
+		point.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));	
+	    }
+	
+	if ("ScreenShot".equals(e.getActionCommand()))
+	    {
+		point.addMouseListener(mouse_blocker_listener);
+		point.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+
+		//byte[] img;
+		BufferedImage img;
+		boolean modal;
+		modal = false;
+		img = recreateEvent(point);
+		
+		if ((img != null) &&(savefinish == true))
+		    {
+			int x,y,w,h,iw,ih;
+			double wrat,hrat;
+			Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
+
+			iw = (int) (dim.getWidth() - 60);
+			ih = (int) (dim.getHeight() * 0.75) - 50;
+			
+			wrat = iw/((double)dim.getWidth());
+			hrat = ih/((double)dim.getHeight());
+			
+			w = (int) (point.getWidth() * wrat);
+			h = (int) (point.getHeight() * hrat);
+			x = (int) (point.getLocationOnScreen().x * wrat);
+			y = (int) (point.getLocationOnScreen().y * hrat);
+
+			//frame.addScreenPanel(feedbackframe,sh.getBuffImage(),img);
+			if (point instanceof JDialog)
+			    modal = ((JDialog) point).isModal();
+
+			feedbackframe = myframe;
+			frame.addScreenPanel(feedbackframe,img,x,y,w,h);
+			frame.setComment(modal);
+
+			if (modal == true)
+			    modalWindow = point;
+		    }
+
+		point.removeMouseListener(mouse_blocker_listener);
+		point.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));	
+	    }
+
+	if (messages.getString("LookHistory").equals(e.getActionCommand()))
+	    {
+		point.addMouseListener(mouse_blocker_listener);
+		point.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+
+		setup_UIManager();
+		ReportDetails rd;
+		rd = new ReportDetails(vector,null,null,messages,rec);
+
+		point.removeMouseListener(mouse_blocker_listener);
+		point.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));	
+	    }
+    }
+   
+
+    /**
+     * This method will listen to any Change event that occured.
+     * It will allow this special listener class to record all the information inside all the
+     * window open when the action occured.
+     * @param e the ChangeEvent.
+     */
+    public void stateChanged(ChangeEvent e)
+    {
+	String command;
+	command = messages.getString("ChangeState");
+	Object obj;
+	obj = e.getSource();
+	
+	Component comp;
+
+	if (obj instanceof Component)
+	    {
+		comp = (Component)e.getSource();
+	    }
+	else
+	    {
+		if (modelHash.containsKey(obj) == true)
+		    {
+			comp = (Component) modelHash.get(obj);
+		    }
+		else
+		    {
+			comp = null;
+			System.out.println("weird" + obj.toString());
+		    }
+	    }
+	
+	saving(comp,command);
+    }
+
+    /**
+     * This method will listen to any tree selection event that occured.
+     * It will allow this special listener class to record all the information inside all the
+     * window open when the action occured.
+     * @param e the TreeSelectionEvent.
+     */
+    public void valueChanged(TreeSelectionEvent e)
+    {
+	MutableTreeNode node;
+        node = (MutableTreeNode)
+	    (e.getPath().getLastPathComponent());
+	
+	if (node == null) return;
+
+	Object obj;
+	obj = e.getSource();
+	
+	Component comp;
+
+	if (obj instanceof Component)
+	    {
+		comp = (Component)e.getSource();
+	    }
+	else
+	    {
+		if (modelHash.containsKey(obj) == true)
+		    {
+			comp = (Component) modelHash.get(obj);
+		    }
+		else
+		    {
+			comp = null;
+			System.out.println("weird" + obj.toString());
+		    }
+	    }
+	
+	String command;
+	command = messages.getString("Node") + " ";
+	if (node instanceof DefaultMutableTreeNode)
+	    command = command + ((DefaultMutableTreeNode)node).getUserObject() + " ";
+	command = command + messages.getString("ValueChanged");
+	
+	saving(comp,command);
+    }
+
+    /**
+     * This method will listen to any tree nodes change in the tree model event that occured.
+     * It will allow this special listener class to record all the information inside all the
+     * window open when the action occured.
+     * @param e the TreeModelEvent.
+     */
+    public void treeNodesChanged(TreeModelEvent e)
+    {
+	MutableTreeNode node;
+        node = (MutableTreeNode)
+                 (e.getTreePath().getLastPathComponent());
+
+	try {
+            int index;
+	    index = e.getChildIndices()[0];
+            node = (MutableTreeNode)(node.getChildAt(index));
+        } catch (NullPointerException exc) {}
+
+	Object obj;
+	obj = e.getSource();
+	
+	Component comp;
+
+	if (obj instanceof Component)
+	    {
+		comp = (Component)e.getSource();
+	    }
+	else
+	    {
+		if (modelHash.containsKey(obj) == true)
+		    {
+			comp = (Component) modelHash.get(obj);
+		    }
+		else
+		    {
+			comp = null;
+			System.out.println("weird" + obj.toString());
+		    }
+	    }
+
+	String command;
+	command = messages.getString("Node");
+
+	if (node instanceof DefaultMutableTreeNode)
+	    command = command + " "  + ((DefaultMutableTreeNode)node).getUserObject();
+
+	command = command + " " + messages.getString("Change");
+	
+	saving(comp,command);
+    }
+
+    /**
+     * This method will listen to any tree nodes inserted in the tree model event that occured.
+     * It will allow this special listener class to record all the information inside all the
+     * window open when the action occured.
+     * @param e the TreeModelEvent.
+     */
+    public void treeNodesInserted(TreeModelEvent e)
+    {
+	MutableTreeNode node;
+        node = (MutableTreeNode)
+                 (e.getTreePath().getLastPathComponent());
+
+	try {
+            int index;
+	    index = e.getChildIndices()[0];
+            node = (MutableTreeNode)(node.getChildAt(index));
+        } catch (NullPointerException exc) {}
+	
+	Object obj;
+	obj = e.getSource();
+	
+	Component comp;
+
+	if (obj instanceof Component)
+	    {
+		comp = (Component)e.getSource();
+	    }
+	else
+	    {
+		if (modelHash.containsKey(obj) == true)
+		    {
+			comp = (Component) modelHash.get(obj);
+		    }
+		else
+		    {
+			comp = null;
+			System.out.println("weird" + obj.toString());
+		    }
+	    }
+	
+	String command;
+	command = messages.getString("Node");
+	if (node instanceof DefaultMutableTreeNode)
+	    command = command + " "  + ((DefaultMutableTreeNode)node).getUserObject();
+
+	command = command + " " + messages.getString("Inserted");
+	
+	saving(comp,command);
+    }
+    
+    /**
+     * This method will listen to any tree nodes removed in the tree model event that occured.
+     * It will allow this special listener class to record all the information inside all the
+     * window open when the action occured.
+     * @param e the TreeModelEvent.
+     */
+    public void treeNodesRemoved(TreeModelEvent e)
+    {
+	MutableTreeNode node;
+        node = (MutableTreeNode)
+                 (e.getTreePath().getLastPathComponent());
+
+	try {
+            int index;
+	    index = e.getChildIndices()[0];
+            node = (MutableTreeNode)(node.getChildAt(index));
+        } catch (NullPointerException exc) {}
+
+	Object obj;
+	obj = e.getSource();
+	
+	Component comp;
+
+	if (obj instanceof Component)
+	    {
+		comp = (Component)e.getSource();
+	    }
+	else
+	    {
+		if (modelHash.containsKey(obj) == true)
+		    {
+			comp = (Component) modelHash.get(obj);
+		    }
+		else
+		    {
+			comp = null;
+			System.out.println("weird" + obj.toString());
+		    }
+	    }
+
+	String command;
+	command = messages.getString("Node");
+	if (node instanceof DefaultMutableTreeNode)
+	    command = command + " "  + ((DefaultMutableTreeNode)node).getUserObject();
+	command = command + " " + messages.getString("Removed");
+	
+	saving(comp,command);
+    }
+ 
+    /**
+     * This method will listen to any tree structure change in the tree model event that occured.
+     * It will allow this special listener class to record all the information inside all the
+     * window open when the action occured.
+     * @param e the TreeModelEvent.
+     */
+    public void treeStructureChanged(TreeModelEvent e)
+    {
+	Object obj;
+	obj = e.getSource();
+	
+	Component comp;
+
+	if (obj instanceof Component)
+	    {
+		comp = (Component)e.getSource();
+	    }
+	else
+	    {
+		if (modelHash.containsKey(obj) == true)
+		    {
+			comp = (Component) modelHash.get(obj);
+		    }
+		else
+		    {
+			comp = null;
+			System.out.println("weird" + obj.toString());
+		    }
+	    }
+	
+	String command;
+	command = messages.getString("TreeStructuredChanged");
+	
+	saving(comp,command);
+    }
+
+    /**
+     * This method will listen to any item state change in the item  event that occured.
+     * It will allow this special listener class to record all the information inside all the
+     * window open when the action occured.
+     * @param e the ItemEvent.
+     */
+    public void itemStateChanged(ItemEvent e)
+    {
+	Component comp;
+	comp = (Component) e.getSource();
+	String command;
+	command = ((String) e.getItem()) + " " + 
+	    messages.getString("ItemStateChanged");
+
+	saving(comp,command);
+    } 
+
+    /**
+     * This method will listen to any contents change in the list data event that occured.
+     * It will allow this special listener class to record all the information inside all the
+     * window open when the action occured.
+     * @param e the ListDataEvent.
+     */
+    public void contentsChanged (ListDataEvent e)
+    {
+	Object obj;
+	obj = e.getSource();
+	
+	Component comp;
+
+	if (obj instanceof Component)
+	    {
+		comp = (Component)e.getSource();
+	    }
+	else
+	    {
+		if (modelHash.containsKey(obj) == true)
+		    {
+			comp = (Component) modelHash.get(obj);
+		    }
+		else
+		    {
+			comp = null;
+			System.out.println("weird" + obj.toString());
+		    }
+	    }
+	
+	String command;
+	command = messages.getString("ListChanged");
+
+	saving(comp,command);
+    } 
+
+    /**
+     * This method will listen to any interval added in the list data event that occured.
+     * It will allow this special listener class to record all the information inside all the
+     * window open when the action occured.
+     * @param e the ListDataEvent.
+     */
+    public void intervalAdded (ListDataEvent e)
+    {
+	Object obj;
+	obj = e.getSource();
+	
+	Component comp;
+
+	if (obj instanceof Component)
+	    {
+		comp = (Component)e.getSource();
+	    }
+	else
+	    {
+		if (modelHash.containsKey(obj) == true)
+		    {
+			comp = (Component) modelHash.get(obj);
+		    }
+		else
+		    {
+			comp = null;
+			System.out.println("weird" + obj.toString());
+		    }
+	    }
+	
+	String command;
+	command = messages.getString("ListContentsAdded");
+
+	saving(comp,command);
+    } 
+
+    /**
+     * This method will listen to any interval removed in the list data event that occured.
+     * It will allow this special listener class to record all the information inside all the
+     * window open when the action occured.
+     * @param e the ListDataEvent.
+     */
+    public void intervalRemoved (ListDataEvent e)
+    {
+	Object obj;
+	obj = e.getSource();
+	
+	Component comp;
+
+	if (obj instanceof Component)
+	    {
+		comp = (Component)e.getSource();
+	    }
+	else
+	    {
+		if (modelHash.containsKey(obj) == true)
+		    {
+			comp = (Component) modelHash.get(obj);
+		    }
+		else
+		    {
+			comp = null;
+			System.out.println("weird" + obj.toString());
+		    }
+	    }
+
+	String command;
+	command = messages.getString("ListContentRemoved");
+
+	saving(comp,command);
+    }
+
+    /**
+     * This method will listen to any value changed in the list data event that occured.
+     * It will allow this special listener class to record all the information inside all the
+     * window open when the action occured.
+     * @param e the ListDataEvent.
+     */
+    public void valueChanged (ListSelectionEvent e)
+    {
+	Object obj;
+	obj = e.getSource();
+	
+	Component comp;
+
+	if (obj instanceof Component)
+	    {
+		comp = (Component)e.getSource();
+	    }
+	else
+	    {
+		if (modelHash.containsKey(obj) == true)
+		    {
+			comp = (Component) modelHash.get(obj);
+		    }
+		else
+		    {
+			comp = null;
+			System.out.println("weird" + obj.toString());
+		    }
+	    }
+
+	String command;
+	command = messages.getString("ListValueChanged");
+
+	saving(comp,command);
+    }
+
+    /**
+     * This method will listen to any menu canceled in the menu event that occured.
+     * It will allow this special listener class to record all the information inside all the
+     * window open when the action occured.
+     * @param e the MenuEvent.
+     */
+    public void menuCanceled (MenuEvent e)
+    {
+	Component comp;
+	comp = (Component) e.getSource();
+	String command;
+	command = messages.getString("MenuCanceled");
+
+	saving(comp,command);
+    }
+
+    /**
+     * This method will listen to any menu deselected in the menu event that occured.
+     * It will allow this special listener class to record all the information inside all the
+     * window open when the action occured.
+     * @param e the MenuEvent.
+     */
+    public void menuDeselected (MenuEvent e)
+     {
+	Component comp;
+	comp = (Component) e.getSource();
+	String command;
+	command = messages.getString("MenuDeselected");
+
+	saving(comp,command);
+    }
+
+    /**
+     * This method will listen to any menu selected in the menu event that occured.
+     * It will allow this special listener class to record all the information inside all the
+     * window open when the action occured.
+     * @param e the MenuEvent.
+     */
+    public void menuSelected(MenuEvent e)
+    {
+	Component comp;
+	comp = (Component) e.getSource();
+	String command;
+	command = messages.getString("MenuSelected");
+
+	saving(comp,command);
+    }
+
+    /**
+     * This method will listen to any column added in the table column model event that occured.
+     * It will allow this special listener class to record all the information inside all the
+     * window open when the action occured.
+     * @param e the TableColumnModelEvent.
+     */
+    public void columnAdded (TableColumnModelEvent e)
+    {
+	Object obj;
+	obj = e.getSource();
+	
+	Component comp;
+
+	if (obj instanceof Component)
+	    {
+		comp = (Component)e.getSource();
+	    }
+	else
+	    {
+		if (modelHash.containsKey(obj) == true)
+		    {
+			comp = (Component) modelHash.get(obj);
+		    }
+		else
+		    {
+			comp = null;
+			System.out.println("weird" + obj.toString());
+		    }
+	    }
+
+	String command;
+	command = messages.getString("ColumnIndex") + " "  + e.getToIndex() 
+	    + messages.getString("AddedToTable");
+
+	saving(comp,command);
+    }
+
+    public void columnMarginChanged(ChangeEvent e) {}
+
+    /**
+     * This method will listen to any column moved in the table column model event that occured.
+     * It will allow this special listener class to record all the information inside all the
+     * window open when the action occured.
+     * @param e the TableColumnModelEvent.
+     */
+    public void columnMoved(TableColumnModelEvent e)
+    {
+	Object obj;
+	obj = e.getSource();
+	
+	Component comp;
+
+	if (obj instanceof Component)
+	    {
+		comp = (Component)e.getSource();
+	    }
+	else
+	    {
+		if (modelHash.containsKey(obj) == true)
+		    {
+			comp = (Component) modelHash.get(obj);
+		    }
+		else
+		    {
+			comp = null;
+			System.out.println("weird" + obj.toString());
+		    }
+	    }
+
+	String command;
+	command = messages.getString("ColumnIndexFrom") + " " + 
+	    e.getFromIndex() + " " + 
+	    messages.getString("MovedToColumnIndex") + " "  + e.getToIndex() +
+	    " " + messages.getString("InTheTable");
+
+	saving(comp,command);
+    }
+
+    /**
+     * This method will listen to any column removed in the table column model event that occured.
+     * It will allow this special listener class to record all the information inside all the
+     * window open when the action occured.
+     * @param e the TableColumnModelEvent.
+     */
+    public void columnRemoved(TableColumnModelEvent e)
+    {
+	Object obj;
+	obj = e.getSource();
+	
+	Component comp;
+
+	if (obj instanceof Component)
+	    {
+		comp = (Component)e.getSource();
+	    }
+	else
+	    {
+		if (modelHash.containsKey(obj) == true)
+		    {
+			comp = (Component) modelHash.get(obj);
+		    }
+		else
+		    {
+			comp = null;
+			System.out.println("weird" + obj.toString());
+		    }
+	    }
+
+	String command;
+	command = messages.getString("ColumnIndex") + " "  + e.getFromIndex() +
+	    " " + messages.getString("RemovedFromTheTable");
+
+	saving(comp,command);
+    }
+
+    public void columnSelectionChanged(ListSelectionEvent e) {}
+}
+
+
+
+
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/Base64.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/Base64.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/Base64.java	(revision 13928)
@@ -0,0 +1,1279 @@
+package org.greenstone.gatherer.feedback;
+
+import java.io.*;
+/**
+ * Encodes and decodes to and from Base64 notation.
+ *
+ * <p>
+ * Change Log:
+ * </p>
+ * <ul>
+ *  <li>v2.0.1 - Fixed an error when decoding a single byte, that is, when the
+ *   encoded data was a single byte.</li>
+ *  <li>v2.0 - I got rid of methods that used booleans to set options. 
+ *   Now everything is more consolidated and cleaner. The code now detects
+ *   when data that's being decoded is gzip-compressed and will decompress it
+ *   automatically. Generally things are cleaner. You'll probably have to
+ *   change some method calls that you were making to support the new
+ *   options format (<tt>int</tt>s that you "OR" together).</li>
+ *  <li>v1.5.1 - Fixed bug when decompressing and decoding to a             
+ *   byte[] using <tt>decode( String s, boolean gzipCompressed )</tt>.      
+ *   Added the ability to "suspend" encoding in the Output Stream so        
+ *   you can turn on and off the encoding if you need to embed base64       
+ *   data in an otherwise "normal" stream (like an XML file).</li>  
+ *  <li>v1.5 - Output stream pases on flush() command but doesn't do anything itself.
+ *      This helps when using GZIP streams.
+ *      Added the ability to GZip-compress objects before encoding them.</li>
+ *  <li>v1.4 - Added helper methods to read/write files.</li>
+ *  <li>v1.3.6 - Fixed OutputStream.flush() so that 'position' is reset.</li>
+ *  <li>v1.3.5 - Added flag to turn on and off line breaks. Fixed bug in input stream
+ *      where last buffer being read, if not completely full, was not returned.</li>
+ *  <li>v1.3.4 - Fixed when "improperly padded stream" error was thrown at the wrong time.</li>
+ *  <li>v1.3.3 - Fixed I/O streams which were totally messed up.</li>
+ * </ul>
+ *
+ * <p>
+ * I am placing this code in the Public Domain. Do with it as you will.
+ * This software comes with no guarantees or warranties but with
+ * plenty of well-wishing instead!
+ * Please visit <a href="http://iharder.net/xmlizable">http://iharder.net/base64</a>
+ * periodically to check for updates or to contribute improvements.
+ * </p>
+ *
+ * @author Robert Harder
+ * @author rob@iharder.net
+ * @version 2.0
+ */
+public class Base64
+{
+    
+/* ********  P U B L I C   F I E L D S  ******** */   
+    
+    
+    /** No options specified. Value is zero. */
+    public final static int NO_OPTIONS = 0;
+    
+    /** Specify encoding. */
+    public final static int ENCODE = 1;
+    
+    
+    /** Specify decoding. */
+    public final static int DECODE = 0;
+    
+    
+    /** Specify that data should be gzip-compressed. */
+    public final static int GZIP = 2;
+    
+    
+    /** Don't break lines when encoding (violates strict Base64 specification) */
+    public final static int DONT_BREAK_LINES = 8;
+    
+    
+/* ********  P R I V A T E   F I E L D S  ******** */  
+    
+    
+    /** Maximum line length (76) of Base64 output. */
+    private final static int MAX_LINE_LENGTH = 76;
+    
+    
+    /** The equals sign (=) as a byte. */
+    private final static byte EQUALS_SIGN = (byte)'=';
+    
+    
+    /** The new line character (\n) as a byte. */
+    private final static byte NEW_LINE = (byte)'\n';
+    
+    
+    /** The 64 valid Base64 values. */
+    private final static byte[] ALPHABET =
+    {
+        (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
+        (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
+        (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', 
+        (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
+        (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
+        (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
+        (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', 
+        (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z',
+        (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', 
+        (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'+', (byte)'/'
+    };
+    
+    /** 
+     * Translates a Base64 value to either its 6-bit reconstruction value
+     * or a negative number indicating some other meaning.
+     **/
+    private final static byte[] DECODABET =
+    {   
+        -9,-9,-9,-9,-9,-9,-9,-9,-9,                 // Decimal  0 -  8
+        -5,-5,                                      // Whitespace: Tab and Linefeed
+        -9,-9,                                      // Decimal 11 - 12
+        -5,                                         // Whitespace: Carriage Return
+        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 14 - 26
+        -9,-9,-9,-9,-9,                             // Decimal 27 - 31
+        -5,                                         // Whitespace: Space
+        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,              // Decimal 33 - 42
+        62,                                         // Plus sign at decimal 43
+        -9,-9,-9,                                   // Decimal 44 - 46
+        63,                                         // Slash at decimal 47
+        52,53,54,55,56,57,58,59,60,61,              // Numbers zero through nine
+        -9,-9,-9,                                   // Decimal 58 - 60
+        -1,                                         // Equals sign at decimal 61
+        -9,-9,-9,                                      // Decimal 62 - 64
+        0,1,2,3,4,5,6,7,8,9,10,11,12,13,            // Letters 'A' through 'N'
+        14,15,16,17,18,19,20,21,22,23,24,25,        // Letters 'O' through 'Z'
+        -9,-9,-9,-9,-9,-9,                          // Decimal 91 - 96
+        26,27,28,29,30,31,32,33,34,35,36,37,38,     // Letters 'a' through 'm'
+        39,40,41,42,43,44,45,46,47,48,49,50,51,     // Letters 'n' through 'z'
+        -9,-9,-9,-9                                 // Decimal 123 - 126
+        /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 127 - 139
+        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 140 - 152
+        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 153 - 165
+        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 166 - 178
+        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 179 - 191
+        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 192 - 204
+        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 205 - 217
+        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 218 - 230
+        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 231 - 243
+        -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9         // Decimal 244 - 255 */
+    };
+    
+    private final static byte BAD_ENCODING    = -9; // Indicates error in encoding
+    private final static byte WHITE_SPACE_ENC = -5; // Indicates white space in encoding
+    private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in encoding
+
+    
+    /** Defeats instantiation. */
+    private Base64(){}
+    
+    
+    
+/* ********  E N C O D I N G   M E T H O D S  ******** */    
+    
+    
+    /**
+     * Encodes the first three bytes of array <var>threeBytes</var>
+     * and returns a four-byte array in Base64 notation.
+     *
+     * @param threeBytes the array to convert
+     * @return four byte array in Base64 notation.
+     * @since 1.3
+     */
+    private static byte[] encode3to4( byte[] threeBytes )
+    {   
+        return encode3to4( threeBytes, 3 );
+    }   // end encodeToBytes
+    
+    
+    
+    /**
+     * Encodes up to the first three bytes of array <var>threeBytes</var>
+     * and returns a four-byte array in Base64 notation.
+     * The actual number of significant bytes in your array is
+     * given by <var>numSigBytes</var>.
+     * The array <var>threeBytes</var> needs only be as big as
+     * <var>numSigBytes</var>.
+     *
+     * @param threeBytes the array to convert
+     * @param numSigBytes the number of significant bytes in your array
+     * @return four byte array in Base64 notation.
+     * @since 1.3
+     */
+    private static byte[] encode3to4( byte[] threeBytes, int numSigBytes )
+    {  
+        byte[] dest = new byte[4];
+        encode3to4( threeBytes, 0, numSigBytes, dest, 0 );
+        return dest;
+    }
+    
+     /**
+     * Encodes up to the first three bytes of array <var>threeBytes</var>
+     * and returns a four-byte array in Base64 notation.
+     * The actual number of significant bytes in your array is
+     * given by <var>numSigBytes</var>.
+     * The array <var>threeBytes</var> needs only be as big as
+     * <var>numSigBytes</var>.
+     * Code can reuse a byte array by passing a four-byte array as <var>b4</var>.
+     *
+     * @param b4 A reusable byte array to reduce array instantiation
+     * @param threeBytes the array to convert
+     * @param numSigBytes the number of significant bytes in your array
+     * @return four byte array in Base64 notation.
+     * @since 1.5.1
+     */
+    private static byte[] encode3to4( byte[] b4, byte[] threeBytes, int numSigBytes )
+    {
+        encode3to4( threeBytes, 0, numSigBytes, b4, 0 );
+        return b4;
+    }   // end encode3to4
+
+    
+    /**
+     * Encodes up to three bytes of the array <var>source</var>
+     * and writes the resulting four Base64 bytes to <var>destination</var>.
+     * The source and destination arrays can be manipulated
+     * anywhere along their length by specifying 
+     * <var>srcOffset</var> and <var>destOffset</var>.
+     * This method does not check to make sure your arrays
+     * are large enough to accomodate <var>srcOffset</var> + 3 for
+     * the <var>source</var> array or <var>destOffset</var> + 4 for
+     * the <var>destination</var> array.
+     * The actual number of significant bytes in your array is
+     * given by <var>numSigBytes</var>.
+     *
+     * @param source the array to convert
+     * @param srcOffset the index where conversion begins
+     * @param numSigBytes the number of significant bytes in your array
+     * @param destination the array to hold the conversion
+     * @param destOffset the index where output will be put
+     * @return the <var>destination</var> array
+     * @since 1.3
+     */
+    private static byte[] encode3to4( 
+     byte[] source, int srcOffset, int numSigBytes,
+     byte[] destination, int destOffset )
+    {
+        //           1         2         3  
+        // 01234567890123456789012345678901 Bit position
+        // --------000000001111111122222222 Array position from threeBytes
+        // --------|    ||    ||    ||    | Six bit groups to index ALPHABET
+        //          >>18  >>12  >> 6  >> 0  Right shift necessary
+        //                0x3f  0x3f  0x3f  Additional AND
+        
+        // Create buffer with zero-padding if there are only one or two
+        // significant bytes passed in the array.
+        // We have to shift left 24 in order to flush out the 1's that appear
+        // when Java treats a value as negative that is cast from a byte to an int.
+        int inBuff =   ( numSigBytes > 0 ? ((source[ srcOffset     ] << 24) >>>  8) : 0 )
+                     | ( numSigBytes > 1 ? ((source[ srcOffset + 1 ] << 24) >>> 16) : 0 )
+                     | ( numSigBytes > 2 ? ((source[ srcOffset + 2 ] << 24) >>> 24) : 0 );
+
+        switch( numSigBytes )
+        {
+            case 3:
+                destination[ destOffset     ] = ALPHABET[ (inBuff >>> 18)        ];
+                destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ];
+                destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>>  6) & 0x3f ];
+                destination[ destOffset + 3 ] = ALPHABET[ (inBuff       ) & 0x3f ];
+                return destination;
+                
+            case 2:
+                destination[ destOffset     ] = ALPHABET[ (inBuff >>> 18)        ];
+                destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ];
+                destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>>  6) & 0x3f ];
+                destination[ destOffset + 3 ] = EQUALS_SIGN;
+                return destination;
+                
+            case 1:
+                destination[ destOffset     ] = ALPHABET[ (inBuff >>> 18)        ];
+                destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ];
+                destination[ destOffset + 2 ] = EQUALS_SIGN;
+                destination[ destOffset + 3 ] = EQUALS_SIGN;
+                return destination;
+                
+            default:
+                return destination;
+        }   // end switch
+    }   // end encode3to4
+    
+    
+    
+    /**
+     * Serializes an object and returns the Base64-encoded
+     * version of that serialized object. If the object
+     * cannot be serialized or there is another error,
+     * the method will return <tt>null</tt>.
+     * The object is not GZip-compressed before being encoded.
+     *
+     * @param serializableObject The object to encode
+     * @return The Base64-encoded object
+     * @since 1.4
+     */
+    public static String encodeObject( java.io.Serializable serializableObject )
+    {
+        return encodeObject( serializableObject, NO_OPTIONS );
+    }   // end encodeObject
+    
+
+
+    /**
+     * Serializes an object and returns the Base64-encoded
+     * version of that serialized object. If the object
+     * cannot be serialized or there is another error,
+     * the method will return <tt>null</tt>.
+     * <p>
+     * Valid options:<pre>
+     *   GZIP: gzip-compresses object before encoding it.
+     *   DONT_BREAK_LINES: don't break lines at 76 characters
+     *     <i>Note: Technically, this makes your encoding non-compliant.</i>
+     * </pre>
+     * <p>
+     * Example: <code>encodeObject( myObj, Base64.GZIP )</code> or
+     * <p>
+     * Example: <code>encodeObject( myObj, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>
+     *
+     * @param serializableObject The object to encode
+     * @param options Specified options
+     * @return The Base64-encoded object
+     * @see Base64#GZIP
+     * @see Base64#DONT_BREAK_LINES
+     * @since 2.0
+     */
+    public static String encodeObject( java.io.Serializable serializableObject, int options )
+    {
+        // Streams
+        java.io.ByteArrayOutputStream  baos  = null; 
+        java.io.OutputStream           b64os = null; 
+        java.io.ObjectOutputStream     oos   = null; 
+        java.util.zip.GZIPOutputStream gzos  = null;
+        
+        // Isolate options
+        int gzip           = (options & GZIP);
+        int dontBreakLines = (options & DONT_BREAK_LINES);
+        
+        try
+        {
+            // ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream
+            baos  = new java.io.ByteArrayOutputStream();
+            b64os = new Base64.OutputStream( baos, ENCODE | dontBreakLines );
+    
+            // GZip?
+            if( gzip == GZIP )
+            {
+                gzos = new java.util.zip.GZIPOutputStream( b64os );
+                oos  = new java.io.ObjectOutputStream( gzos );
+            }   // end if: gzip
+            else
+                oos   = new java.io.ObjectOutputStream( b64os );
+            
+            oos.writeObject( serializableObject );
+        }   // end try
+        catch( java.io.IOException e )
+        {
+            e.printStackTrace();
+            return null;
+        }   // end catch
+        finally
+        {
+            try{ oos.close();   } catch( Exception e ){}
+            try{ gzos.close();  } catch( Exception e ){}
+            try{ b64os.close(); } catch( Exception e ){}
+            try{ baos.close();  } catch( Exception e ){}
+        }   // end finally
+        
+        return new String( baos.toByteArray() );
+    }   // end encode
+    
+    
+
+    /**
+     * Encodes a byte array into Base64 notation.
+     * Does not GZip-compress data.
+     *
+     * @param source The data to convert
+     * @since 1.4
+     */
+    public static String encodeBytes( byte[] source )
+    {
+        return encodeBytes( source, 0, source.length, NO_OPTIONS );
+    }   // end encodeBytes
+    
+
+
+    /**
+     * Encodes a byte array into Base64 notation.
+     * <p>
+     * Valid options:<pre>
+     *   GZIP: gzip-compresses object before encoding it.
+     *   DONT_BREAK_LINES: don't break lines at 76 characters
+     *     <i>Note: Technically, this makes your encoding non-compliant.</i>
+     * </pre>
+     * <p>
+     * Example: <code>encodeBytes( myData, Base64.GZIP )</code> or
+     * <p>
+     * Example: <code>encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>
+     *
+     *
+     * @param source The data to convert
+     * @param options Specified options
+     * @see Base64#GZIP
+     * @see Base64#DONT_BREAK_LINES
+     * @since 2.0
+     */
+    public static String encodeBytes( byte[] source, int options )
+    {   
+        return encodeBytes( source, 0, source.length, options );
+    }   // end encodeBytes
+    
+    
+    /**
+     * Encodes a byte array into Base64 notation.
+     * Does not GZip-compress data.
+     *
+     * @param source The data to convert
+     * @param off Offset in array where conversion should begin
+     * @param len Length of data to convert
+     * @since 1.4
+     */
+    public static String encodeBytes( byte[] source, int off, int len )
+    {
+        return encodeBytes( source, off, len, NO_OPTIONS );
+    }   // end encodeBytes
+    
+    
+
+    /**
+     * Encodes a byte array into Base64 notation.
+     * <p>
+     * Valid options:<pre>
+     *   GZIP: gzip-compresses object before encoding it.
+     *   DONT_BREAK_LINES: don't break lines at 76 characters
+     *     <i>Note: Technically, this makes your encoding non-compliant.</i>
+     * </pre>
+     * <p>
+     * Example: <code>encodeBytes( myData, Base64.GZIP )</code> or
+     * <p>
+     * Example: <code>encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>
+     *
+     *
+     * @param source The data to convert
+     * @param off Offset in array where conversion should begin
+     * @param len Length of data to convert
+     * @param options Specified options
+     * @see Base64#GZIP
+     * @see Base64#DONT_BREAK_LINES
+     * @since 2.0
+     */
+    public static String encodeBytes( byte[] source, int off, int len, int options )
+    {
+        // Isolate options
+        int dontBreakLines = ( options & DONT_BREAK_LINES );
+        int gzip           = ( options & GZIP   );
+        
+        // Compress?
+        if( gzip == GZIP )
+        {
+            java.io.ByteArrayOutputStream  baos  = null;
+            java.util.zip.GZIPOutputStream gzos  = null;
+            Base64.OutputStream            b64os = null;
+            
+    
+            try
+            {
+                // GZip -> Base64 -> ByteArray
+                baos = new java.io.ByteArrayOutputStream();
+                b64os = new Base64.OutputStream( baos, ENCODE | dontBreakLines );
+                gzos  = new java.util.zip.GZIPOutputStream( b64os ); 
+            
+                gzos.write( source, off, len );
+                gzos.close();
+            }   // end try
+            catch( java.io.IOException e )
+            {
+                e.printStackTrace();
+                return null;
+            }   // end catch
+            finally
+            {
+                try{ gzos.close();  } catch( Exception e ){}
+                try{ b64os.close(); } catch( Exception e ){}
+                try{ baos.close();  } catch( Exception e ){}
+            }   // end finally
+
+            return new String( baos.toByteArray() );
+        }   // end if: compress
+        
+        // Else, don't compress. Better not to use streams at all then.
+        else
+        {
+            // Convert option to boolean in way that code likes it.
+            boolean breakLines = dontBreakLines == 0;
+            
+            int    len43   = len * 4 / 3;
+            byte[] outBuff = new byte[   ( len43 )                      // Main 4:3
+                                       + ( (len % 3) > 0 ? 4 : 0 )      // Account for padding
+                                       + (breakLines ? ( len43 / MAX_LINE_LENGTH ) : 0) ]; // New lines      
+            int d = 0;
+            int e = 0;
+            int len2 = len - 2;
+            int lineLength = 0;
+            for( ; d < len2; d+=3, e+=4 )
+            {
+                encode3to4( source, d+off, 3, outBuff, e );
+
+                lineLength += 4;
+                if( breakLines && lineLength == MAX_LINE_LENGTH )
+                {   
+                    outBuff[e+4] = NEW_LINE;
+                    e++;
+                    lineLength = 0;
+                }   // end if: end of line
+            }   // en dfor: each piece of array
+
+            if( d < len )
+            {
+                encode3to4( source, d+off, len - d, outBuff, e );
+                e += 4;
+            }   // end if: some padding needed
+
+            return new String( outBuff, 0, e );
+        }   // end else: don't compress
+        
+    }   // end encodeBytes
+    
+
+    
+    
+    
+/* ********  D E C O D I N G   M E T H O D S  ******** */
+    
+    
+    /**
+     * Decodes the first four bytes of array <var>fourBytes</var>
+     * and returns an array up to three bytes long with the
+     * decoded values.
+     *
+     * @param fourBytes the array with Base64 content
+     * @return array with decoded values
+     * @since 1.3
+     */
+    private static byte[] decode4to3( byte[] fourBytes )
+    {
+        byte[] outBuff1 = new byte[3];
+        int    count    = decode4to3( fourBytes, 0, outBuff1, 0 );
+        byte[] outBuff2 = new byte[ count ];
+        
+        for( int i = 0; i < count; i++ )
+            outBuff2[i] = outBuff1[i];
+        
+        return outBuff2;
+    }
+    
+    
+    
+    
+    /**
+     * Decodes four bytes from array <var>source</var>
+     * and writes the resulting bytes (up to three of them)
+     * to <var>destination</var>.
+     * The source and destination arrays can be manipulated
+     * anywhere along their length by specifying 
+     * <var>srcOffset</var> and <var>destOffset</var>.
+     * This method does not check to make sure your arrays
+     * are large enough to accomodate <var>srcOffset</var> + 4 for
+     * the <var>source</var> array or <var>destOffset</var> + 3 for
+     * the <var>destination</var> array.
+     * This method returns the actual number of bytes that 
+     * were converted from the Base64 encoding.
+     * 
+     *
+     * @param source the array to convert
+     * @param srcOffset the index where conversion begins
+     * @param destination the array to hold the conversion
+     * @param destOffset the index where output will be put
+     * @return the number of decoded bytes converted
+     * @since 1.3
+     */
+    private static int decode4to3( byte[] source, int srcOffset, byte[] destination, int destOffset )
+    {
+        // Example: Dk==
+        if( source[ srcOffset + 2] == EQUALS_SIGN )
+        {
+            // Two ways to do the same thing. Don't know which way I like best.
+            //int outBuff =   ( ( DECODABET[ source[ srcOffset    ] ] << 24 ) >>>  6 )
+            //              | ( ( DECODABET[ source[ srcOffset + 1] ] << 24 ) >>> 12 );
+            int outBuff =   ( ( DECODABET[ source[ srcOffset    ] ] & 0xFF ) << 18 )
+                          | ( ( DECODABET[ source[ srcOffset + 1] ] & 0xFF ) << 12 );
+            
+            destination[ destOffset ] = (byte)( outBuff >>> 16 );
+            return 1;
+        }
+        
+        // Example: DkL=
+        else if( source[ srcOffset + 3 ] == EQUALS_SIGN )
+        {
+            // Two ways to do the same thing. Don't know which way I like best.
+            //int outBuff =   ( ( DECODABET[ source[ srcOffset     ] ] << 24 ) >>>  6 )
+            //              | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 )
+            //              | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 );
+            int outBuff =   ( ( DECODABET[ source[ srcOffset     ] ] & 0xFF ) << 18 )
+                          | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF ) << 12 )
+                          | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF ) <<  6 );
+            
+            destination[ destOffset     ] = (byte)( outBuff >>> 16 );
+            destination[ destOffset + 1 ] = (byte)( outBuff >>>  8 );
+            return 2;
+        }
+        
+        // Example: DkLE
+        else
+        {
+            try{
+            // Two ways to do the same thing. Don't know which way I like best.
+            //int outBuff =   ( ( DECODABET[ source[ srcOffset     ] ] << 24 ) >>>  6 )
+            //              | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 )
+            //              | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 )
+            //              | ( ( DECODABET[ source[ srcOffset + 3 ] ] << 24 ) >>> 24 );
+            int outBuff =   ( ( DECODABET[ source[ srcOffset     ] ] & 0xFF ) << 18 )
+                          | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF ) << 12 )
+                          | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF ) <<  6)
+                          | ( ( DECODABET[ source[ srcOffset + 3 ] ] & 0xFF )      );
+
+            
+            destination[ destOffset     ] = (byte)( outBuff >> 16 );
+            destination[ destOffset + 1 ] = (byte)( outBuff >>  8 );
+            destination[ destOffset + 2 ] = (byte)( outBuff       );
+
+            return 3;
+            }catch( Exception e){
+                System.out.println(""+source[srcOffset]+ ": " + ( DECODABET[ source[ srcOffset     ] ]  ) );
+                System.out.println(""+source[srcOffset+1]+  ": " + ( DECODABET[ source[ srcOffset + 1 ] ]  ) );
+                System.out.println(""+source[srcOffset+2]+  ": " + ( DECODABET[ source[ srcOffset + 2 ] ]  ) );
+                System.out.println(""+source[srcOffset+3]+  ": " + ( DECODABET[ source[ srcOffset + 3 ] ]  ) );
+                return -1;
+            }   //e nd catch
+        }
+    }   // end decodeToBytes
+    
+    
+    
+    
+    /**
+     * Very low-level access to decoding ASCII characters in
+     * the form of a byte array. Does not support automatically
+     * gunzipping or any other "fancy" features.
+     *
+     * @param source The Base64 encoded data
+     * @param off    The offset of where to begin decoding
+     * @param len    The length of characters to decode
+     * @return decoded data
+     * @since 1.3
+     */
+    public static byte[] decode( byte[] source, int off, int len )
+    {
+        int    len34   = len * 3 / 4;
+        byte[] outBuff = new byte[ len34 ]; // Upper limit on size of output
+        int    outBuffPosn = 0;
+        
+        byte[] b4        = new byte[4];
+        int    b4Posn    = 0;
+        int    i         = 0;
+        byte   sbiCrop   = 0;
+        byte   sbiDecode = 0;
+        for( i = off; i < off+len; i++ )
+        {
+            sbiCrop = (byte)(source[i] & 0x7f); // Only the low seven bits
+            sbiDecode = DECODABET[ sbiCrop ];
+            
+            if( sbiDecode >= WHITE_SPACE_ENC ) // White space, Equals sign or better
+            {
+                if( sbiDecode >= EQUALS_SIGN_ENC )
+                {
+                    b4[ b4Posn++ ] = sbiCrop;
+                    if( b4Posn > 3 )
+                    {
+                        outBuffPosn += decode4to3( b4, 0, outBuff, outBuffPosn );
+                        b4Posn = 0;
+                        
+                        // If that was the equals sign, break out of 'for' loop
+                        if( sbiCrop == EQUALS_SIGN )
+                            break;
+                    }   // end if: quartet built
+                    
+                }   // end if: equals sign or better
+                
+            }   // end if: white space, equals sign or better
+            else
+            {
+                System.err.println( "Bad Base64 input character at " + i + ": " + source[i] + "(decimal)" );
+                return null;
+            }   // end else: 
+        }   // each input character
+                                   
+        byte[] out = new byte[ outBuffPosn ];
+        System.arraycopy( outBuff, 0, out, 0, outBuffPosn ); 
+        return out;
+    }   // end decode
+    
+    
+    
+    
+    /**
+     * Decodes data from Base64 notation, automatically
+     * detecting gzip-compressed data and decompressing it.
+     *
+     * @param s the string to decode
+     * @return the decoded data
+     * @since 1.4
+     */
+    public static byte[] decode( String s )
+    {   
+        byte[] bytes = s.getBytes();
+        bytes = decode( bytes, 0, bytes.length );
+        
+        // Check to see if it's gzip-compressed
+        // GZIP Magic Two-Byte Number: 0x8b1f (35615)
+        if( bytes.length >= 2 )
+        {
+            
+            int head = ((int)bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00);       
+            if(
+            bytes != null &&      // In case decoding returned null
+            bytes.length >= 4  && // Don't want to get ArrayIndexOutOfBounds exception
+            java.util.zip.GZIPInputStream.GZIP_MAGIC == head ) 
+            {
+                java.io.ByteArrayInputStream  bais = null;
+                java.util.zip.GZIPInputStream gzis = null;
+                java.io.ByteArrayOutputStream baos = null;
+                byte[] buffer = new byte[2048];
+                int    length = 0;
+
+                try
+                {
+                    baos = new java.io.ByteArrayOutputStream();
+                    bais = new java.io.ByteArrayInputStream( bytes );
+                    gzis = new java.util.zip.GZIPInputStream( bais );
+
+                    while( ( length = gzis.read( buffer ) ) >= 0 )
+                    {
+                        baos.write(buffer,0,length);
+                    }   // end while: reading input
+
+                    // No error? Get new bytes.
+                    bytes = baos.toByteArray();
+
+                }   // end try
+                catch( java.io.IOException e )
+                {
+                    // Just return originally-decoded bytes
+                }   // end catch
+                finally
+                {
+                    try{ baos.close(); } catch( Exception e ){}
+                    try{ gzis.close(); } catch( Exception e ){}
+                    try{ bais.close(); } catch( Exception e ){}
+                }   // end finally
+
+            }   // end if: gzipped
+        }   // end if: bytes.length >= 2
+        
+        return bytes;
+    }   // end decode
+
+
+    
+
+    /**
+     * Attempts to decode Base64 data and deserialize a Java
+     * Object within. Returns <tt>null</tt> if there was an error.
+     *
+     * @param encodedObject The Base64 data to decode
+     * @return The decoded and deserialized object
+     * @since 1.5
+     */
+    public static Object decodeToObject( String encodedObject )
+    {
+        // Decode and gunzip if necessary
+        byte[] objBytes = decode( encodedObject );
+        
+        java.io.ByteArrayInputStream  bais = null;
+        java.io.ObjectInputStream     ois  = null;
+        Object obj = null;
+        
+        try
+        {
+            bais = new java.io.ByteArrayInputStream( objBytes );
+            ois  = new java.io.ObjectInputStream( bais );
+        
+            obj = ois.readObject();
+        }   // end try
+        catch( java.io.IOException e )
+        {
+            e.printStackTrace();
+            obj = null;
+        }   // end catch
+        catch( java.lang.ClassNotFoundException e )
+        {
+            e.printStackTrace();
+            obj = null;
+        }   // end catch
+        finally
+        {
+            try{ bais.close(); } catch( Exception e ){}
+            try{ ois.close();  } catch( Exception e ){}
+        }   // end finally
+        
+        return obj;
+    }   // end decodeObject
+    
+    
+    /* ********  I N N E R   C L A S S   I N P U T S T R E A M  ******** */
+    
+    
+    
+    /**
+     * It will read data from another
+     * {@link java.io.InputStream}, given in the constructor,
+     * and encode/decode to/from Base64 notation on the fly.
+     *
+     * @see Base64
+     * @see java.io.FilterInputStream
+     * @since 1.3
+     */
+    public static class InputStream extends java.io.FilterInputStream
+    {
+        private int     options;        // Options specified
+        private boolean encode;         // Encoding or decoding
+        private int     position;       // Current position in the buffer
+        private byte[]  buffer;         // Small buffer holding converted data
+        private int     bufferLength;   // Length of buffer (3 or 4)
+        private int     numSigBytes;    // Number of meaningful bytes in the buffer
+        private int     lineLength;
+        private boolean breakLines;     // Break lines at less than 80 characters
+        
+        
+        /**
+         * Constructs a InputStream in DECODE mode.
+         *
+         * @param in the {@link java.io.InputStream} from which to read data.
+         * @since 1.3
+         */
+        public InputStream( java.io.InputStream in )
+        {   
+            this( in, DECODE );
+        }   // end constructor
+        
+        
+        /**
+         * Constructs a InputStream in
+         * either ENCODE or DECODE mode.
+         * <p>
+         * Valid options:<pre>
+         *   ENCODE or DECODE: Encode or Decode as data is read.
+         *   DONT_BREAK_LINES: don't break lines at 76 characters
+         *     (only meaningful when encoding)
+         *     <i>Note: Technically, this makes your encoding non-compliant.</i>
+         * </pre>
+         * <p>
+         * Example: <code>new Base64.InputStream( in, Base64.DECODE )</code>
+         *
+         *
+         * @param in the {@link java.io.InputStream} from which to read data.
+         * @param options Specified options
+         * @see Base64#ENCODE
+         * @see Base64#DECODE
+         * @see Base64#DONT_BREAK_LINES
+         * @since 2.0
+         */
+        public InputStream( java.io.InputStream in, int options )
+        {   
+            super( in );
+            this.options      = options;
+            this.breakLines   = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES;
+            this.encode       = (options & ENCODE) == ENCODE;
+            this.bufferLength = encode ? 4 : 3;
+            this.buffer   = new byte[ bufferLength ];
+            this.position = -1;
+            this.lineLength = 0;
+        }   // end constructor
+        
+        /**
+         * Reads enough of the input stream to convert
+         * to/from Base64 and returns the next byte.
+         *
+         * @return next byte
+         * @since 1.3
+         */
+        public int read() throws java.io.IOException 
+        { 
+            // Do we need to get data?
+            if( position < 0 )
+            {
+                if( encode )
+                {
+                    byte[] b3 = new byte[3];
+                    int numBinaryBytes = 0;
+                    for( int i = 0; i < 3; i++ )
+                    {
+                        try
+                        { 
+                            int b = in.read();
+                            
+                            // If end of stream, b is -1.
+                            if( b >= 0 )
+                            {
+                                b3[i] = (byte)b;
+                                numBinaryBytes++;
+                            }   // end if: not end of stream
+                            
+                        }   // end try: read
+                        catch( java.io.IOException e )
+                        {   
+                            // Only a problem if we got no data at all.
+                            if( i == 0 )
+                                throw e;
+                            
+                        }   // end catch
+                    }   // end for: each needed input byte
+                    
+                    if( numBinaryBytes > 0 )
+                    {
+                        encode3to4( b3, 0, numBinaryBytes, buffer, 0 );
+                        position = 0;
+                        numSigBytes = 4;
+                    }   // end if: got data
+                    else
+                    {
+                        return -1;
+                    }   // end else
+                }   // end if: encoding
+                
+                // Else decoding
+                else
+                {
+                    byte[] b4 = new byte[4];
+                    int i = 0;
+                    for( i = 0; i < 4; i++ )
+                    {
+                        // Read four "meaningful" bytes:
+                        int b = 0;
+                        do{ b = in.read(); }
+                        while( b >= 0 && DECODABET[ b & 0x7f ] <= WHITE_SPACE_ENC );
+                        
+                        if( b < 0 )
+                            break; // Reads a -1 if end of stream
+                        
+                        b4[i] = (byte)b;
+                    }   // end for: each needed input byte
+                    
+                    if( i == 4 )
+                    {
+                        numSigBytes = decode4to3( b4, 0, buffer, 0 );
+                        position = 0;
+                    }   // end if: got four characters
+                    else if( i == 0 ){
+                        return -1;
+                    }   // end else if: also padded correctly
+                    else
+                    {
+                        // Must have broken out from above.
+                        throw new java.io.IOException( "Improperly padded Base64 input." );
+                    }   // end 
+                    
+                }   // end else: decode
+            }   // end else: get data
+            
+            // Got data?
+            if( position >= 0 )
+            {
+                // End of relevant data?
+                if( /*!encode &&*/ position >= numSigBytes )
+                    return -1;
+                
+                if( encode && breakLines && lineLength >= MAX_LINE_LENGTH )
+                {
+                    lineLength = 0;
+                    return '\n';
+                }   // end if
+                else
+                {
+                    lineLength++;   // This isn't important when decoding
+                                    // but throwing an extra "if" seems
+                                    // just as wasteful.
+                    
+                    int b = buffer[ position++ ];
+
+                    if( position >= bufferLength )
+                        position = -1;
+
+                    return b & 0xFF; // This is how you "cast" a byte that's
+                                     // intended to be unsigned.
+                }   // end else
+            }   // end if: position >= 0
+            
+            // Else error
+            else
+            {   
+                // When JDK1.4 is more accepted, use an assertion here.
+                throw new java.io.IOException( "Error in Base64 code reading stream." );
+            }   // end else
+        }   // end read
+        
+        
+        /**
+         * Calls {@link #read} repeatedly until the end of stream
+         * is reached or <var>len</var> bytes are read.
+         * Returns number of bytes read into array or -1 if
+         * end of stream is encountered.
+         *
+         * @param dest array to hold values
+         * @param off offset for array
+         * @param len max number of bytes to read into array
+         * @return bytes read into array or -1 if end of stream is encountered.
+         * @since 1.3
+         */
+        public int read( byte[] dest, int off, int len ) throws java.io.IOException
+        {
+            int i;
+            int b;
+            for( i = 0; i < len; i++ )
+            {
+                b = read();
+                
+                //if( b < 0 && i == 0 )
+                //    return -1;
+                
+                if( b >= 0 )
+                    dest[off + i] = (byte)b;
+                else if( i == 0 )
+                    return -1;
+                else
+                    break; // Out of 'for' loop
+            }   // end for: each byte read
+            return i;
+        }   // end read
+        
+    }   // end inner class InputStream
+    
+    
+    
+    
+    
+    
+    /* ********  I N N E R   C L A S S   O U T P U T S T R E A M  ******** */
+    
+    
+    
+    /**
+     * A OutputStream will write data to another
+     * {@link java.io.OutputStream}, given in the constructor,
+     * and encode/decode to/from Base64 notation on the fly.
+     *
+     * @see Base64
+     * @see java.io.FilterOutputStream
+     * @since 1.3
+     */
+    public static class OutputStream extends java.io.FilterOutputStream
+    {
+        private int     options;
+        private boolean encode;
+        private int     position;
+        private byte[]  buffer;
+        private int     bufferLength;
+        private int     lineLength;
+        private boolean breakLines;
+        private byte[]  b4; // Scratch used in a few places
+        private boolean suspendEncoding;
+        
+        /**
+         * Constructs a OutputStream in ENCODE mode.
+         *
+         * @param out the {@link java.io.OutputStream} to which data will be written.
+         * @since 1.3
+         */
+        public OutputStream( java.io.OutputStream out )
+        {   
+            this( out, ENCODE );
+        }   // end constructor
+        
+        
+        /**
+         * Constructs a OutputStream in
+         * either ENCODE or DECODE mode.
+         * <p>
+         * Valid options:<pre>
+         *   ENCODE or DECODE: Encode or Decode as data is read.
+         *   DONT_BREAK_LINES: don't break lines at 76 characters
+         *     (only meaningful when encoding)
+         *     <i>Note: Technically, this makes your encoding non-compliant.</i>
+         * </pre>
+         * <p>
+         * Example: <code>new Base64.OutputStream( out, Base64.ENCODE )</code>
+         *
+         * @param out the {@link java.io.OutputStream} to which data will be written.
+         * @param options Specified options.
+         * @see Base64#ENCODE
+         * @see Base64#DECODE
+         * @see Base64#DONT_BREAK_LINES
+         * @since 1.3
+         */
+        public OutputStream( java.io.OutputStream out, int options )
+        {   
+            super( out );
+            this.options      = options;
+            this.breakLines   = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES;
+            this.encode       = (options & ENCODE) == ENCODE;
+            this.bufferLength = encode ? 3 : 4;
+            this.buffer       = new byte[ bufferLength ];
+            this.position     = 0;
+            this.lineLength   = 0;
+            this.suspendEncoding = false;
+            this.b4           = new byte[4];
+        }   // end constructor
+        
+        
+        /**
+         * Writes the byte to the output stream after
+         * converting to/from Base64 notation.
+         * When encoding, bytes are buffered three
+         * at a time before the output stream actually
+         * gets a write() call.
+         * When decoding, bytes are buffered four
+         * at a time.
+         *
+         * @param theByte the byte to write
+         * @since 1.3
+         */
+        public void write(int theByte) throws java.io.IOException
+        {
+            // Encoding suspended?
+            if( suspendEncoding )
+            {
+                super.out.write( theByte );
+                return;
+            }   // end if: supsended
+            
+            // Encode?
+            if( encode )
+            {
+                buffer[ position++ ] = (byte)theByte;
+                if( position >= bufferLength )  // Enough to encode.
+                {
+                    out.write( encode3to4( b4, buffer, bufferLength ) );
+
+                    lineLength += 4;
+                    if( breakLines && lineLength >= MAX_LINE_LENGTH )
+                    {
+                        out.write( NEW_LINE );
+                        lineLength = 0;
+                    }   // end if: end of line
+
+                    position = 0;
+                }   // end if: enough to output
+            }   // end if: encoding
+
+            // Else, Decoding
+            else
+            {
+                // Meaningful Base64 character?
+                if( DECODABET[ theByte & 0x7f ] > WHITE_SPACE_ENC )
+                {
+                    buffer[ position++ ] = (byte)theByte;
+                    if( position >= bufferLength )  // Enough to output.
+                    {
+                        int len = Base64.decode4to3( buffer, 0, b4, 0 );
+                        out.write( b4, 0, len );
+                        //out.write( Base64.decode4to3( buffer ) );
+                        position = 0;
+                    }   // end if: enough to output
+                }   // end if: meaningful base64 character
+                else if( DECODABET[ theByte & 0x7f ] != WHITE_SPACE_ENC )
+                {
+                    throw new java.io.IOException( "Invalid character in Base64 data." );
+                }   // end else: not white space either
+            }   // end else: decoding
+        }   // end write
+        
+        
+        
+        /**
+         * Calls {@link #write} repeatedly until <var>len</var> 
+         * bytes are written.
+         *
+         * @param theBytes array from which to read bytes
+         * @param off offset for array
+         * @param len max number of bytes to read into array
+         * @since 1.3
+         */
+        public void write( byte[] theBytes, int off, int len ) throws java.io.IOException
+        {
+            // Encoding suspended?
+            if( suspendEncoding )
+            {
+                super.out.write( theBytes, off, len );
+                return;
+            }   // end if: supsended
+            
+            for( int i = 0; i < len; i++ )
+            {
+                write( theBytes[ off + i ] );
+            }   // end for: each byte written
+            
+        }   // end write
+        
+        
+        
+        /**
+         * Method added by PHIL. [Thanks, PHIL. -Rob]
+         * This pads the buffer without closing the stream.
+         */
+        public void flushBase64() throws java.io.IOException 
+        {
+            if( position > 0 )
+            {
+                if( encode )
+                {
+                    out.write( encode3to4( b4, buffer, position ) );
+                    position = 0;
+                }   // end if: encoding
+                else
+                {
+                    throw new java.io.IOException( "Base64 input not properly padded." );
+                }   // end else: decoding
+            }   // end if: buffer partially full
+
+        }   // end flush
+
+        
+        /** 
+         * Flushes and closes (I think, in the superclass) the stream. 
+         *
+         * @since 1.3
+         */
+        public void close() throws java.io.IOException
+        {
+            // 1. Ensure that pending characters are written
+            flushBase64();
+
+            // 2. Actually close the stream
+            // Base class both flushes and closes.
+            super.close();
+            
+            buffer = null;
+            out    = null;
+        }   // end close
+        
+        
+        
+        /**
+         * Suspends encoding of the stream.
+         * May be helpful if you need to embed a piece of
+         * base640-encoded data in a stream.
+         *
+         * @since 1.5.1
+         */
+        public void suspendEncoding() throws java.io.IOException 
+        {
+            flushBase64();
+            this.suspendEncoding = true;
+        }   // end suspendEncoding
+        
+        
+        /**
+         * Resumes encoding of the stream.
+         * May be helpful if you need to embed a piece of
+         * base640-encoded data in a stream.
+         *
+         * @since 1.5.1
+         */
+        public void resumeEncoding()
+        {
+            this.suspendEncoding = false;
+        }   // end resumeEncoding
+        
+        
+        
+    }   // end inner class OutputStream
+    
+    
+}   // end class Base64
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/CombineGraphs.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/CombineGraphs.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/CombineGraphs.java	(revision 13928)
@@ -0,0 +1,138 @@
+/** This class is not currently used and therefore will not be compiled by makegli. */
+
+package org.greenstone.gatherer.feedback;
+
+import java.io.*;
+import javax.imageio.*;
+import java.awt.*;
+import java.awt.image.*;
+import com.sun.image.codec.jpeg.*;
+import javax.swing.*;
+
+/**
+ *  CombineGraphs class is a class to combine 2 images file into 1 jpeg file
+ *  called test.jpg using point by point comparison.
+ *  <p>User need to supplied the valid exist filenames of the 2 images that 
+ *  they want to combine.If in any one point in 2nd image file is not transparent
+ *  then that point will be drawn to the 1st image file.</p>  
+ *  <p>To run this class properly the format is :
+ *  <br><i>java CombineGraphs filename1 filename2</i>
+ *  <br>where filename1 is the names of the first image file.
+ *  <br>and filename2 is the names of the second image file. This file must
+ *  contains transparent.</p>
+ *  <p>For example: If user wants to combine the screenshot image file with the
+ *  image file of the scribble lines, then
+ *  <br>filename1 will be the filename of the screenshot image file, and
+ *  <br>filename2 will be the filename of the scribble lines image file.</p>
+ *
+ *  @author Veronica Liesaputra
+ */
+
+public class CombineGraphs extends JPanel
+{
+    /**
+     * This is a variable to stored the image that is stored inside f1.
+     * After the combine method called this variable will store the resulted image of
+     * combining 2 images together.
+     */
+    private BufferedImage bi1;
+
+    /**
+     * This is a variable to stored the image that is stored inside f2.
+     */
+    private BufferedImage bi2;
+
+    /**
+     * This is a variable to stored the first image file that the user supplied.
+     */
+    private File f1;
+
+    /**
+     * This is a variable to stored the second image file that the user supplied.
+     */
+    private File f2;
+    
+    /**
+     * It will read the image files user supplied and stored the image
+     * to the appropriate bufferedimage variable.
+     * (Precondition: (file1 != null) && (file2 != null))
+     * @param file1   the name of the first image file.
+     * @param file2   the name of the second image file.
+     */
+    public CombineGraphs(String file1,String file2)
+    {
+	try
+	    {
+		f1 = new File(file1);
+		f2 = new File(file2);
+		bi1 = ImageIO.read(f1);
+		bi2 = ImageIO.read(f2);	
+	    }
+	catch(IOException exp) {}
+    }   
+
+    /**
+     * This method will combine the 2 buffered images into 1 buffered image and 
+     * saved it to an output file in jpeg format.
+     * (Precondition: (filename != null))
+     * @param filename the name of the output file.
+     * (Postcondition: the combined image is stored in a jpeg file with the name
+     *                 as specified in filename.)
+     */
+    public void combine(String filename)
+    {
+
+	/*using bi1 as the base layer that we use to compare point by point with bi2. 
+	  if in one point in bi2 its not transparent then we draw that point to bi1.*/ 
+	Graphics2D G1;
+	
+	G1 = bi1.createGraphics();
+	
+	int width = bi2.getWidth();
+	int height = bi2.getHeight();
+
+	for (int y = 0 ; y < height ; y++) 
+	    {
+		for (int x = 0 ; x < width ; x++)
+		    {
+			int rgb = bi2.getRGB(x,y);
+			if (rgb != 0)
+			    {
+				G1.setColor(new Color(rgb,true));
+				G1.drawLine(x,y,x,y);
+			    }
+		    }
+	    }
+	
+	// Save the combined bufferedimage into a jpeg output file.
+	try {
+	    File file = new File(filename);
+	    FileOutputStream out = new FileOutputStream(file);
+	    
+	    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
+	    JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bi1);
+	    param.setQuality(1.0f, false);
+	    encoder.setJPEGEncodeParam(param);
+	    encoder.encode(bi1);
+	    
+	} catch (Exception ex) {}
+    }
+
+    /**
+     * This the main method that need 2 inputs from the user for it to
+     * work properly. 
+     * The inputs are the 2 image filenames that user want to combine.
+     */
+    public static void main (String[] args)
+    {
+	CombineGraphs cb = new CombineGraphs(args[0],args[1]);
+	cb.combine("test.jpg");
+    }
+}
+
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/CompGroup.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/CompGroup.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/CompGroup.java	(revision 13928)
@@ -0,0 +1,60 @@
+package org.greenstone.gatherer.feedback;
+
+import java.io.*;
+
+/**
+ * The instance of this class will hold a UserComponent and the status of the UserComponent.
+ * For each of the CompGroup instance will contains all the information and the status of
+ * a window that is opened by the application the user used.
+ * @author Veronica Liesaputra
+ */
+public class CompGroup implements Serializable
+{
+    /**
+     *  This variable will hold the status of the window that is opened by the application.
+     */
+    private String comp_status;
+
+    /**
+     *  This variable will hold the information about the window that is opened by the
+     *  application.
+     */
+    private UserComponent comp;
+
+    public CompGroup ()
+    {
+
+    }
+    
+    /**
+     *  It will make CompGroup instance that hold the information and status of the window
+     *  thats is opened by the application.
+     *  @param curr_comp  information about the window opened by the application.
+     *  @param curr_status status of the window opened by the application.
+     */
+    public CompGroup (UserComponent curr_comp,String curr_status)
+    {
+	comp_status = curr_status;
+	comp = curr_comp;
+    }
+    
+    /**
+     * This method will return the status of the window opened by the application.
+     * @return the status of the window.
+     */
+    public String getStatus ()
+    {
+	return comp_status;
+    }
+    
+    /**
+     * This method will return the information about the window opened by the application.
+     * @return the information about the window.
+     */
+    public UserComponent getComponent()
+    {
+	return comp;
+    }
+}
+
+  
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/CompListener.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/CompListener.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/CompListener.java	(revision 13928)
@@ -0,0 +1,944 @@
+package org.greenstone.gatherer.feedback;
+
+import org.omg.IOP.ComponentIdHelper;
+import java.awt.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.tree.*;
+import javax.swing.table.*;
+import javax.swing.text.*;
+import java.awt.image.*;
+import javax.imageio.ImageIO;
+import javax.swing.plaf.*;
+import javax.swing.plaf.basic.*;
+import javax.swing.colorchooser.*;
+import java.awt.event.*;
+import javax.swing.event.*;
+import java.text.MessageFormat;
+import javax.swing.plaf.metal.MetalIconFactory.*;
+import javax.swing.plaf.metal.MetalIconFactory;
+import javax.swing.plaf.basic.BasicInternalFrameTitlePane;
+import javax.swing.plaf.metal.MetalInternalFrameTitlePane;
+
+/**
+ *  In general, this class will get add special listener 
+ *  to a Container and of all the components inside it.
+ *  <p>This class will also add special listener to the Container and each of the components inside 
+ *  the Container. So, it will allows special listener  to record and listen each of the actions 
+ *  the user do to the Container or any of the components inside it. The special listener
+ *  is an instance of ActionRecorderDialog.</p>
+ *  <p>This class will only recognized all the components that is belongs to the javax.swing package
+ *  which are all the implementing classes of RootPaneContainer interface and all the direct known
+ *  subclasses of JComponent. All the other components will be stated simply as Container 
+ *  and user cannot really get much information out of it.</p>
+ *  <p>The added special listener to this component is as what its allowed in API, if the component
+ *  have some modified listener added to it then that action will not be known and recorded by
+ *  the special listener.</p>
+ *  
+ *  @author Veronica Liesaputra
+ */
+public class CompListener
+{
+    /**
+     *  This variable will hold the special listener that will listen and record any of the 
+     *  actions user do to the Container and any of the components inside it.
+     */
+    private ActionRecorderDialog m;
+   
+    /**
+     *  This variable will hold the pair of the component and the model of the component.
+     *  With this variable allows ActionRecorderDialog listener to know which component the model that fires an action
+     *  belongs to. In this HashMap the model is the key and the component where the model belongs to is
+     *  the value. 
+     */
+    private HashMap hash;
+    
+    /**
+     *  This constructor will set the special listener, the locale and the hashmap to be used in
+     *  this Container.
+     *  (Precondition: dialog != null)
+     *  @param dialog  its the special listener that will listen and record all the action
+     *                 user do to any of the component inside the Container.
+     *  @param h       its the HashMap that will hold the pair of model with the component it belongs.
+     */
+    public CompListener 
+	(ActionRecorderDialog dialog,HashMap h)
+    {
+	m = dialog;
+	hash = h;
+    }
+	
+    /**
+     *  If the JTextComponent is a JTextField then it will add the special action listener to it.
+     *  (Precondition: txt != null)
+     *  @param txt its the JTextComponent we want to get all the information from.
+     */
+    public void getTextAreaInfo(JTextComponent txt)
+    {
+	if (txt instanceof JTextField)
+	    {
+		((JTextField)txt).removeActionListener(m);
+		((JTextField)txt).addActionListener(m);
+	    }
+    }
+
+    /**
+     *  This method will add the special action listener to the JButton.
+     *  (Precondition: button != null)
+     *  @param button its the JButton we want to get the information from.
+     */
+    public void getButtonInfo (JButton button)
+    {
+	button.removeActionListener(m);
+	button.addActionListener(m);
+    }
+
+     /**
+     *  This method will get add the special change listener to the JProgressBar.
+     *  (Precondition: bar != null)
+     *  @param  bar   its the JProgressBar we want to get information from.
+     */
+    public void getProgressBarInfo (JProgressBar bar)
+    {
+	bar.removeChangeListener(m);
+	bar.addChangeListener(m);
+    }
+    
+    /**
+     *  This method will add the special change listener to the JSlider.
+     *  (Precondition: slider != null)
+     *  @param  slider its the JSlider we want to get information from.
+     */
+    public void getSliderInfo (JSlider slider)
+    {
+	slider.removeChangeListener(m);
+	slider.addChangeListener(m);
+    }
+
+    /**
+     *  This method will add the special change listener to the JSpinner.
+     *  (Precondition: spinner != null)
+     *  @param spinner its the JSpinner we want to the information from.
+     */
+    public void getSpinnerInfo (JSpinner spinner)
+    {
+	spinner.removeChangeListener(m);
+	spinner.addChangeListener(m);
+    }
+    
+    /**
+     * Dummy method to get JLabel.
+     */
+    public void getLabelInfo(JLabel lbl)
+    {}
+    
+    /**
+     *  This method will add the special action listener to the JComboBox.
+     *  (Precondition: box != null)
+     *  @param box    its the JComboBox we want to get information from.
+     */
+    public void getComboBoxInfo(JComboBox box)
+    {
+	ComboBoxModel cm;
+	cm = box.getModel();
+
+	box.removeActionListener(m);
+	box.addActionListener(m);
+    }
+
+    /**
+     *  This method will add the special action listener to the JToggleButton.
+     *  (Precondition: button != null)
+     *  @param button its a JToggleButton inside the window.
+     */
+    public void getToggleButtonInfo (JToggleButton button)
+    {
+	button.removeActionListener(m);
+	button.addActionListener(m);
+    }
+
+    /**
+     *  This method will add the special action listener to the JMenuItem.
+     *  (Precondition: menuitem != null)
+     *  @param menuitem its the JMenuItem we want to get the information from.
+     */
+    public void getMenuItemInfo (JMenuItem menuitem)
+    {
+	menuitem.removeActionListener(m);
+	menuitem.addActionListener(m);
+    }
+
+    /**
+     *  This method will get all the components inside JMenuBar.
+     *  (Precondition: menubar != null)
+     *  @param menubar its the JMenuBar we want to get the information from.
+     */
+    public void getMenuBarInfo (JMenuBar menubar)
+    {
+	int i;
+	for (i= 0 ; i < menubar.getMenuCount() ; i++)
+	    {
+		getInside(menubar.getMenu(i));
+	    }
+    }
+
+    /**
+     *  This method will add the special action and menu listener to the JMenu and
+     *  get the components inside JMenu.
+     *  (Precondition: menu != null)
+     *  @param menu   its the JMenu we want to the the information from.
+     */
+    public void getMenuInfo (JMenu menu)
+    {
+	menu.removeActionListener(m);
+	menu.removeMenuListener(m);
+	menu.addActionListener(m);
+	menu.addMenuListener(m);
+
+	int i;
+	for (i= 0 ; i < menu.getMenuComponentCount() ; i++)
+	    {
+		getInside((Container)menu.getMenuComponent(i));
+	    }
+    }
+    
+    /**
+     *  This method will get all the components inside the JApplet.
+     *  (Precondition: applet != null)
+     *  @param applet its the JApplet we want to get the information from.
+     */
+    public void getAppletInfo (JApplet applet)
+    {
+	Component[] group;
+	group = applet.getComponents();
+	int i;
+
+	if (group != null)
+	    {
+		for (i = 0; i < group.length ; i++)
+		    {
+			getInside((Container)applet.getComponent(i));
+		    }
+	    }
+    }
+
+    /**
+     *  This method will get all the components inside the JWindow.
+     *  (Precondition: window != null)
+     *  @param window its the JWindow we want to get the information from.
+     */
+    public void getWindowInfo (JWindow window)
+    {
+	Component[] group;
+	group = window.getComponents();
+	int i;
+
+	if (group != null)
+	    {
+		for (i = 0; i < group.length ; i++)
+		    {
+			getInside((Container)window.getComponent(i));
+		    }
+	    }
+    }
+
+    /**
+     *  This method will get all the components inside the JDialog.
+     *  (Precondition: dialog != null)
+     *  @param dialog its the JDialog we want to get the information from.
+     */
+    public void getDialogInfo (JDialog dialog)
+    {
+	Component[] group;
+	group = dialog.getComponents();
+	int i;
+
+	if (group != null)
+	    {
+		for (i = 0; i < group.length ; i++)
+		    {
+			getInside((Container)dialog.getComponent(i));
+		    }
+	    }
+    }
+
+    /**
+     *  This method will get all the components inside the JInternalFrame.
+     *  (Precondition: frame != null)
+     *  @param frame  its the JInternalFrame we want to get the information from.
+     */
+    public void getInternalFrameInfo (JInternalFrame frame)
+    {
+	Component[] group;
+	group = frame.getComponents();
+	int i;
+
+	if (group != null)
+	    {
+		for (i = 0; i < group.length ; i++)
+		    {
+			getInside((Container)frame.getComponent(i));
+		    }
+	    }
+    }
+
+    /**
+     *  This method will get all the components inside the JFrame.
+     *  (Precondition: frame != null)
+     *  @param frame  its the JFrame we want to get the information from.
+     */
+    public void getFrameInfo (JFrame frame)
+    {
+	Component[] group;
+	group = frame.getComponents();
+	int i;
+	
+	if (group != null)
+	    {
+		for (i = 0; i < group.length ; i++)
+		    {
+			getInside((Container)frame.getComponent(i));
+		    }
+	    }
+    }
+
+    /**
+     *  This method will get all the components inside the JPanel.
+     *  (Precondition: pane != null)
+     *  @param pane   its the JPanel we want to get the information from.
+     */
+    public void getPanelInfo (JPanel pane)
+    {
+	Component[] group;
+	group = pane.getComponents();
+	int i;
+
+	if (group != null)
+	    {
+		for (i = 0; i < group.length ; i++)
+		    {
+			getInside((Container)pane.getComponent(i));
+		    }
+	    }
+    }
+    
+    /**
+     *  This method will get all the components inside the JScrollPane.
+     *  (Precondition: scroll != null)
+     *  @param scroll its the JScrollPane we want to get the information from.
+     */
+    public void getScrollInfo (JScrollPane scroll)
+    {
+	Component[] group;
+	group = scroll.getComponents();
+	int i;
+	
+	if (group != null)
+	    {
+		for (i = 0; i < group.length ; i++)
+		    {
+			getInside((Container)group[i]);
+		    }
+	    }
+    }
+
+    /**
+     *  This method will add special change listener to the JTabbedPane and get all
+     *  the components inside it.
+     *  (Precondition: tab != null)
+     *  @param tab   its the JTabbedPane we want to get the information from.
+     */
+    public void getTabbedPaneInfo (JTabbedPane tab)
+    {
+	int j;
+	
+	tab.removeChangeListener(m);
+	tab.addChangeListener(m);
+
+	for (j = 0 ; j < tab.getTabCount(); j++)
+	    {	
+		
+		Component group = tab.getComponentAt(j);
+		getInside((Container)group);
+		
+	    }
+    }
+    
+    /**
+     *  This is the dummy method to ge the option pane info.
+     */
+    public void getOptionPaneInfo (JOptionPane op)
+    {}
+
+    /**
+     *  This method will get components inside the JViewPort.
+     *  (Precondition: vp != null)
+     *  @param vp   its the JViewPort we want to get the information from.
+     */
+    public void getViewPortInfo (JViewport vp)
+    {
+	Component[] group;
+	group = vp.getComponents();
+	int i;
+
+	if (group != null)
+	    {
+		for (i = 0; i < group.length ; i++)
+		    {
+			getInside((Container)group[i]);
+		    }
+	    }
+    }
+
+    /**
+     *  This method will get components inside the Box.
+     *  (Precondition: box != null)
+     *  @param box  its the Box we want to get the information from.
+     */
+    public void getBoxInfo (Box box)
+    {
+	Component[] group;
+	group = box.getComponents();
+	int i;
+
+	if (group != null)
+	    {
+		for (i = 0; i < group.length ; i++)
+		    {
+			getInside((Container)group[i]);
+		    }
+	    }
+    }
+
+    /**
+     *  This method will get components inside the JSplitPane.
+     *  (Precondition: split != null)
+     *  @param split  its the JSplitPane we want to get the information from.
+     */
+    public void getSplitPaneInfo (JSplitPane split)
+    {
+	Component[] group;
+	group = split.getComponents();
+	int i;
+
+	if (group != null)
+	    {
+		for (i = 0; i < group.length ; i++)
+		    {
+			getInside((Container)group[i]);
+		    }
+	    }
+    }
+
+    /**
+     *  This method will get add special list selection listener to the JList.
+     *  (Precondition: list != null)
+     *  @param list  its the JList we want to get the information from.
+     */
+    public void getListInfo (JList list)
+    {
+	ListModel ls;
+	ls = list.getModel();
+	
+	list.removeListSelectionListener(m);
+	list.addListSelectionListener(m);
+	
+	if (ls != null)
+	    {
+		if (hash.containsKey(ls) == false)
+		    hash.put(ls,list);
+		ls.removeListDataListener(m);
+		ls.addListDataListener(m);
+	    }
+    }
+
+    /**
+     *  This method will add special change listener to the JColorChooser.
+     *  (Precondition: color != null)
+     *  @param color  its the JColorChooser we want to get the information from.
+     */
+    public void getColorInfo (JColorChooser color)
+    {
+	ColorSelectionModel cm;
+	cm = color.getSelectionModel();
+	
+	if (cm != null)
+	    {
+		if (hash.containsKey(cm) == false)
+		    hash.put(cm,color);
+		cm.removeChangeListener(m);
+		cm.addChangeListener(m);
+	    }
+
+	getInside((Container) color.getPreviewPanel());
+    }
+
+    /**
+     *  This method will add special action listener to the JFileChooser.
+     *  (Precondition: fc != null)
+     *  @param fc  its the JFileChooser we want to get the information from.
+     */
+    public void getFileChooserInfo (JFileChooser fc)
+    {
+	fc.removeActionListener(m);
+	fc.addActionListener(m);
+    }		
+
+    /**
+     *  This method will add special list selection and column model listener 
+     *  to the JTable.
+     *  (Precondition: table != null)
+     *  @param table  its the JTable we want to get the information from.
+     */
+    public void getTableInfo (JTable table)
+    {
+	TableModel tm;
+	tm = table.getModel();
+	
+	TableColumnModel tcm;
+	tcm = table.getColumnModel();
+	ListSelectionModel lm;
+	lm = table.getSelectionModel(); 
+
+	if (lm != null)
+	    {
+		if (hash.containsKey(lm) == false)
+		    hash.put(lm,table);
+		lm.removeListSelectionListener(m);
+		lm.addListSelectionListener(m);
+	    }
+	
+	if (tcm != null)
+	    {
+		if (hash.containsKey(tcm) == false)
+		    hash.put(tcm,table);
+		tcm.removeColumnModelListener(m);
+		tcm.addColumnModelListener(m);
+	    }
+    }
+
+    /**
+     *  This is a dummy method to get the JScrollBar.
+     */
+    public void getScrollBarInfo (JScrollBar scroll)
+    {
+    }
+
+    /**
+     *  This method will add special tree selection listener to the JTree.
+     *  (Precondition: tree != null)
+     *  @param tree  its the JTree we want to get the information from.
+     */
+    public void getTreeInfo (JTree tree)
+    {
+	TreeModel tm;
+	tm = tree.getModel();
+	
+	tree.removeTreeSelectionListener(m);
+	tree.addTreeSelectionListener(m);
+	
+	if (tm != null)
+	    {
+		if (hash.containsKey(tm) == false)
+		    hash.put(tm,tree);
+		tm.removeTreeModelListener(m);
+		tm.addTreeModelListener(m);
+	    }
+    }
+       
+    /**
+     *  This method is a dummy method to get Container.
+     */
+    public void getCompInfo (Container pane)
+    {
+    }
+
+    /**
+     *  This method will get all components inside the JPopupMenu.
+     *  (Precondition: popup != null)
+     *  @param popup  its the JPopUpMenu we want to get the information from.
+     */
+    public void getPopUpMenuInfo (JPopupMenu popup)
+    {
+	Component[] group;
+	group = popup.getComponents();
+	SingleSelectionModel sm;
+	sm = popup.getSelectionModel();
+	int i;
+
+	if (group != null)
+	    {
+		for (i = 0; i < group.length ; i++)
+		    {
+			getInside((Container)popup.getComponent(i));
+		    }
+	    }
+    }
+
+    /**
+     *  This method will get all the components inside the JRootPane.
+     *  (Precondition: pane != null)
+     *  @param pane  its the JRootPane we want to get the information from.
+     */
+    public void getRootPaneInfo (JRootPane pane)
+    {
+	Component[] group;
+	group = pane.getComponents();
+	int i;
+	
+	if (group != null)
+	    {
+		for (i = 0; i < group.length ; i++)
+		    {
+			
+			getInside((Container)pane.getComponent(i));
+		    }
+	    }
+    }
+
+    /**
+     *  This method will get all the components inside the JLayeredPane.
+     *  (Precondition: pane != null)
+     *  @param pane  its the JLayeredPane we want to get the information from.
+     */
+    public void getLayeredPaneInfo (JLayeredPane pane)
+    {
+	Component[] group;
+	group = pane.getComponents();
+	int i;
+	
+	if (group != null)
+	    {
+		for (i = 0; i < group.length ; i++)
+		    {
+			getInside((Container)pane.getComponent(i));
+		    }
+	    }
+    }
+
+    /**
+     * This is a dummy method to get BasicInternalFrameTitlePane.
+     */
+    public void getInternalFrameTitleInfo (BasicInternalFrameTitlePane pane)
+    {
+    }
+
+    /**
+     *  This method will add special column model and list selection
+     *  listener to JTableHeader.
+     *  (Precondition: header != null)
+     *  @param header  its the JTableHeader we want to get the information from.
+     */
+    public void getTableHeaderInfo (JTableHeader header)
+    {
+	TableColumnModel tcm;
+	tcm = header.getColumnModel();
+	ListSelectionModel lm;
+	lm = tcm.getSelectionModel();
+
+	if (tcm != null)
+	    {
+		if (hash.containsKey(tcm) == false)
+		    hash.put(tcm,header);
+		tcm.removeColumnModelListener(m);
+		tcm.addColumnModelListener(m);
+	    }
+
+	if (lm != null)
+	    {
+		if (hash.containsKey(lm) == false)
+		    hash.put(lm,header);
+		lm.removeListSelectionListener(m);
+		lm.addListSelectionListener(m);
+	    }
+    }
+
+    /**
+     *  This method will get all components inside the JToolBar.
+     *  (Precondition: tool != null)
+     *  @param tool  its the JToolBar we want to get the information from.
+     */
+    public void getToolBarInfo (JToolBar tool)
+    {
+	Component[] group;
+	group = tool.getComponents();
+	int i;
+	
+	if (group != null)
+	    {
+		for (i = 0; i < group.length ; i++)
+		    {
+			getInside((Container)tool.getComponent(i));
+		    }
+	    }
+    }
+
+    /**
+     *  This method will get all the components inside the JToolTip.
+     *  (Precondition: tip != null)
+     *  @param tip  its the JToolTip we want to get the information from.
+     */
+    public void getToolTipInfo (JToolTip tip)
+    {
+	Component group;
+	group = tip.getComponent();
+	int i;
+	
+	if (group != null)
+	    {
+		getInside((Container) group);
+	    }
+    }
+
+    /**
+     *  This is the dummy method to get JSeparator.
+     */
+    public void getSeparatorInfo (JSeparator sept)
+    {
+    }
+
+    /**
+     *  This method will get all the components inside the JDesktopPane.
+     *  (Precondition: pane != null)
+     *  @param pane  its the JDesktopPane we want to get the information from.
+     */
+    public void getDesktopPaneInfo (JDesktopPane pane)
+    {
+	JInternalFrame[]  group;
+	group = pane.getAllFrames();
+
+	if (group != null)
+	    {
+		int i;
+		
+		for ( i = 0 ; i < group.length ; i++ )
+		    {
+			getInside((Container) group[i]);
+		    }
+	    }
+    }
+
+    /**
+     *  This is a dummy method to catch null components.
+     */
+    public void getNullInfo ()
+    {
+    }
+
+    /**
+     *  This method will add a special listener to a container and components inside it.
+     *  This method is the gateway to all other methods in this class.
+     *  @param comp its the Container we want to get the information from.
+     */
+    public void getInside(Container comp)
+    {
+	if (comp == null)
+	    {
+		getNullInfo();
+		return;
+	    }
+	else if (comp instanceof JApplet)
+	    {
+		getAppletInfo ((JApplet) comp);
+		return;
+	    }
+	else if (comp instanceof JSeparator)
+	    {
+		getSeparatorInfo ((JSeparator) comp);
+		return;
+	    }
+	else if (comp instanceof JWindow)
+	    {
+		getWindowInfo((JWindow) comp);
+		return;
+	    }
+	else if (comp instanceof JDialog)
+	    {
+		getDialogInfo((JDialog) comp);
+		return;
+	    }
+	else if (comp instanceof JComboBox)
+	    {
+		getComboBoxInfo((JComboBox) comp);
+		return;
+	    }
+	else if (comp instanceof JLabel)
+	    {
+		getLabelInfo((JLabel) comp);
+		return;
+	    }
+	else if (comp instanceof JTextComponent)
+	    {
+		getTextAreaInfo((JTextComponent) comp);
+		return;
+	    }
+	else if (comp instanceof JFrame)
+	    {
+		getFrameInfo((JFrame) comp);
+		return;
+	    }
+	else if (comp instanceof JPanel)
+	    {
+		getPanelInfo((JPanel) comp);
+		return;
+	    }
+	else if (comp instanceof JScrollPane)
+	    {
+		getScrollInfo((JScrollPane) comp);
+		return;
+	    }
+	else if (comp instanceof JScrollBar)
+	    {
+		getScrollBarInfo ((JScrollBar) comp);
+		return;
+	    }
+	else if (comp instanceof JViewport)
+	    {
+		getViewPortInfo((JViewport) comp);
+		return;
+	    }
+	else if (comp instanceof JTabbedPane)
+	    {
+		getTabbedPaneInfo((JTabbedPane) comp);
+		return;
+	    }
+	else if (comp instanceof Box)
+	    {
+		getBoxInfo((Box) comp);
+		return;
+	    }
+	else if (comp instanceof JToggleButton)
+	    {
+		getToggleButtonInfo((JToggleButton) comp);
+		return;
+	    }
+	else if (comp instanceof JSplitPane)
+	    {
+		getSplitPaneInfo ((JSplitPane) comp);
+		return;
+	    }
+	else if (comp instanceof JList)
+	    {
+		getListInfo ((JList) comp);
+		return;
+	    }
+	else if (comp instanceof JTree)
+	    {
+		getTreeInfo ((JTree) comp);
+		return;
+	    }
+	else if (comp instanceof JTable)
+	    {
+		getTableInfo ((JTable) comp);
+		return;
+	    }
+	else if (comp instanceof JSlider)
+	    {
+		getSliderInfo ((JSlider) comp);
+		return;
+	    }
+	else if (comp instanceof JSpinner)
+	    {
+		getSpinnerInfo ((JSpinner) comp);
+		return;
+	    }
+	else if (comp instanceof JProgressBar)
+	    {
+		getProgressBarInfo ((JProgressBar) comp);
+		return;
+	    }
+	else if (comp instanceof JButton)
+	    {
+		getButtonInfo ((JButton) comp);
+		return;
+	    }
+	else if (comp instanceof JMenu)
+	    {
+		getMenuInfo ((JMenu) comp);
+		return;
+	    }
+	else if (comp instanceof JMenuBar)
+	    {
+		getMenuBarInfo ((JMenuBar) comp);
+		return;
+	    }
+	else if (comp instanceof JMenuItem)
+	    {
+		getMenuItemInfo ((JMenuItem) comp);
+		return;
+	    }
+	else if (comp instanceof JOptionPane)
+	    {
+		getOptionPaneInfo ((JOptionPane) comp);
+		return;
+	    }
+	else if (comp instanceof BasicInternalFrameTitlePane)
+	    {
+		getInternalFrameTitleInfo ((BasicInternalFrameTitlePane) comp);
+		return;
+	    }
+	else if (comp instanceof JColorChooser)
+	    {
+		getColorInfo ((JColorChooser) comp);
+		return;
+	    }
+	else if (comp instanceof JFileChooser)
+	    {
+		getFileChooserInfo ((JFileChooser) comp);
+		return;
+	    }
+	else if (comp instanceof JDesktopPane)
+	    {
+		getDesktopPaneInfo ((JDesktopPane) comp);
+		return;
+	    }
+	else if (comp instanceof JInternalFrame)
+	    {
+		getInternalFrameInfo ((JInternalFrame) comp);
+		return;
+	    }
+	else if (comp instanceof JLayeredPane)
+	    {
+		getLayeredPaneInfo ((JLayeredPane) comp);
+		return;
+	    }
+	else if (comp instanceof JPopupMenu)
+	    {
+		getPopUpMenuInfo ((JPopupMenu) comp);
+		return;
+	    }
+	else if (comp instanceof JRootPane)
+	    {
+		getRootPaneInfo ((JRootPane) comp);
+		return;
+	    }
+	else if (comp instanceof JTableHeader)
+	    {
+		getTableHeaderInfo ((JTableHeader) comp);
+		return;
+	    }
+	else if (comp instanceof JToolBar)
+	    {
+		getToolBarInfo ((JToolBar) comp);
+		return;
+	    }
+	else if (comp instanceof JToolTip)
+	    {
+		getToolTipInfo ((JToolTip) comp);
+		return;
+	    }
+	else
+	    {
+		getCompInfo (comp);
+		return;
+	    }
+    }
+}
+
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/ComponentInformation.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/ComponentInformation.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/ComponentInformation.java	(revision 13928)
@@ -0,0 +1,2261 @@
+package org.greenstone.gatherer.feedback;
+
+import org.omg.IOP.ComponentIdHelper;
+import java.awt.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.tree.*;
+import javax.swing.table.*;
+import javax.swing.text.*;
+import java.awt.image.*;
+import javax.imageio.ImageIO;
+import javax.swing.plaf.*;
+import javax.swing.plaf.basic.*;
+import javax.swing.colorchooser.*;
+import java.awt.event.*;
+import javax.swing.event.*;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.text.MessageFormat;
+import javax.swing.plaf.metal.MetalIconFactory.*;
+import javax.swing.plaf.metal.MetalIconFactory;
+import javax.swing.plaf.basic.BasicInternalFrameTitlePane;
+import javax.swing.plaf.metal.MetalInternalFrameTitlePane;
+
+/**
+ *  In general, this class will get all information and add special listener 
+ *  to a Container and of all the components inside it.
+ *  <p>This class will get the information about the Container and all the components inside it.
+ *  The information we get is like whether or not the component is visible and the contents of it.
+ *  This class will also add special listener to the Container and each of the components inside 
+ *  the Container. So, it will allows special listener  to record and listen each of the actions 
+ *  the user do to the Container or any of the components inside it. The special listener
+ *  is an instance of ActionRecorderDialog.</p>
+ *  <p>This class will only recognized all the components that is belongs to the javax.swing package
+ *  which are all the implementing classes of RootPaneContainer interface and all the direct known
+ *  subclasses of JComponent. All the other components will be stated simply as Container 
+ *  and user cannot really get much information out of it.</p>
+ *  <p>The added special listener to this component is as what its allowed in API, if the component
+ *  have some modified listener added to it then that action will not be known and recorded by
+ *  the special listener.</p>
+ *  
+ *  @author Veronica Liesaputra
+ */
+public class ComponentInformation
+{
+    /**
+     *  This variable will hold the special listener that will listen and record any of the 
+     *  actions user do to the Container and any of the components inside it.
+     */
+    private ActionRecorderDialog m;
+    
+    /**
+     *  This variable will hold the resource of the words that is stored in Messages.properties file. 
+     *  The calling using messages.getString(someString) will caused someString to be translated
+     *  into some other string that is hold in that file.usually it will caused it to be translated
+     *  to the language that the user use or choose to have as stated in Locale.
+     */
+    private static ResourceBundle messages;
+
+    /**
+     *  This variable will hold the pair of the component and the model of the component.
+     *  With this variable allows ActionRecorderDialog listener to know which component the model that fires an action
+     *  belongs to. In this HashMap the model is the key and the component where the model belongs to is
+     *  the value. 
+     */
+    private HashMap hash;
+    
+    /**
+     *  This constructor will set the special listener, the locale and the hashmap to be used in
+     *  this Container.
+     *  (Precondition: dialog != null)
+     *  @param dialog  its the special listener that will listen and record all the action
+     *                 user do to any of the component inside the Container.
+     *  @param currentLocale its the locale that the user choose all the information to be displayed as.
+     *  @param h       its the HashMap that will hold the pair of model with the component it belongs.
+     */
+    public ComponentInformation 
+	(ActionRecorderDialog dialog,Locale currentLocale,HashMap h)
+    {
+	m = dialog;
+	hash = h;
+	messages = ResourceBundle.getBundle("feedback", currentLocale);
+    }
+	
+    /**
+     *  This method will get all information about the JTextComponent.
+     *  If the JTextComponent is a JTextField then it will add the special action listener to it.
+     *  (Precondition: txt != null)
+     *  @param txt its the JTextComponent we want to get all the information from.
+     *  @return    a UserComponent that hold the information about this
+     *             JTextComponent.
+     */
+    public  UserComponent getTextAreaInfo(JTextComponent txt)
+    {
+	UserComponent file;
+	file = new UserComponent(); 
+	String text;
+	text = txt.getText();
+
+	file.startContent(1);
+	if (txt instanceof JTextArea)
+	    file.saveContent("JTextArea");
+	else if (txt instanceof JTextPane)
+	    file.saveContent("JTextPane");
+	else if (txt instanceof JEditorPane)
+	    file.saveContent("JEditorPane");
+	else if (txt instanceof JTextField)
+	    {
+		((JTextField)txt).removeActionListener(m);
+		((JTextField)txt).addActionListener(m);
+		
+		if (txt instanceof JFormattedTextField)
+		    {
+			file.saveContent("JFormattedTextField");
+		    }
+		else if (txt instanceof JPasswordField)
+		    {
+			file.saveContent("JPasswordField");
+		    }
+		else
+		    {
+			file.saveContent("JTextField");
+		    }
+	    }
+
+	file.startContent(2);
+	file.saveContent(messages.getString("TextComponent"));
+	
+	file.startContent(3);
+	if (text != null)
+	    file.saveContent(text);
+	else
+	    file.saveContent(" ");
+	
+	file.startContent(4);
+	file.saveContent(txt.getSelectedText());
+
+	file.startContent(5);
+	file.saveContent(messages.getString("" + txt.isVisible()));
+
+	file.startContent(7);
+	file.saveContent(txt.getToolTipText());
+	
+	return file;
+    }
+
+    /**
+     *  This method will get all the information and add the special action listener to the JButton.
+     *  (Precondition: button != null)
+     *  @param button its the JButton we want to get the information from.
+     *  @return       a UserComponent that will hold the information about this JButton.
+     */
+    public UserComponent getButtonInfo (JButton button)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	String text;
+	text = button.getText();
+
+	button.removeActionListener(m);
+	button.addActionListener(m);
+
+	file.startContent(1);
+	file.saveContent("JButton");
+
+	file.startContent(2);
+	file.saveContent(messages.getString("Button"));
+	
+	file.startContent(3);
+	if (text != null)
+	    file.saveContent(text);
+	else
+	    file.saveContent(" ");
+
+	file.startContent(4);
+	file.saveContent(messages.getString("" + button.isSelected()));
+
+	file.startContent(5);
+	file.saveContent(messages.getString("" + button.isVisible()));
+	
+	file.startContent(6);
+	Icon img = button.getIcon();
+	if (img != null)
+	    {
+		file.saveImage(img,messages.getString("icon")+img.hashCode()+".jpg");
+	    }
+	else
+	    {
+		file.saveContent(messages.getString("NoImage"));
+	    }
+
+	file.startContent(7);
+	file.saveContent(button.getToolTipText());
+
+	return file;
+    }
+
+     /**
+     *  This method will get all the information and add the special change listener to the JProgressBar.
+     *  (Precondition: bar != null)
+     *  @param  bar   its the JProgressBar we want to get information from.
+     *  @return       a UserComponent that will hold the information about this JProgressBar.
+     */
+    public UserComponent getProgressBarInfo (JProgressBar bar)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	String text;
+	text = bar.getString();
+
+	bar.removeChangeListener(m);
+	bar.addChangeListener(m);
+	
+	file.startContent(1);
+	file.saveContent("JProgressBar");
+
+	file.startContent(2);
+	file.saveContent(messages.getString("ProgressBar"));
+	
+	file.startContent(3);
+	if (text != null)
+	    file.saveContent(text);
+	else
+	    file.saveContent(" ");
+
+	file.startContent(5);
+	file.saveContent(messages.getString("" + bar.isVisible()));
+	
+	file.startContent(7);
+	file.saveContent(bar.getToolTipText());
+
+	return file;
+    }
+    
+    /**
+     *  This method will get all the information and add the special change listener to the JSlider.
+     *  (Precondition: slider != null)
+     *  @param  slider its the JSlider we want to get information from.
+     *  @return        a UserComponent that will hold the information about this JSlider.
+     */
+    public UserComponent getSliderInfo (JSlider slider)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	String text;
+	text = "" + slider.getValue();
+	
+	slider.removeChangeListener(m);
+	slider.addChangeListener(m);
+
+	file.startContent(1);
+	file.saveContent("JSlider");
+	
+	file.startContent(2);
+	file.saveContent(messages.getString("Slider"));
+	
+	file.startContent(3);
+	if (text != null)
+	    file.saveContent(text);
+	else
+	    file.saveContent(" ");
+
+	file.startContent(5);
+	file.saveContent(messages.getString("" + slider.isVisible()));
+	
+	file.startContent(7);
+	file.saveContent(slider.getToolTipText());
+
+	return file;
+    }
+
+    /**
+     *  This method will get all the information and add the special change listener to the JSpinner.
+     *  (Precondition: spinner != null)
+     *  @param spinner its the JSpinner we want to the information from.
+     *  @return        a UserComponent that will hold the information about this JSpinner.
+     */
+    public UserComponent getSpinnerInfo (JSpinner spinner)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	String text;
+	text = "" + spinner.getValue();
+	
+	spinner.removeChangeListener(m);
+	spinner.addChangeListener(m);
+
+	file.startContent(1);
+	file.saveContent("JSpinner");
+	
+	file.startContent(2);
+	file.saveContent(messages.getString("Spinner"));
+	
+	file.startContent(3);
+	if (text != null)
+	    file.saveContent(text);
+	else
+	    file.saveContent(" ");
+
+	file.startContent(5);
+	file.saveContent(messages.getString("" + spinner.isVisible()));
+	
+	file.startContent(7);
+	file.saveContent(spinner.getToolTipText());
+
+	return file;
+    }
+    
+    /**
+     *  This method will get all the information of  the JLabel.
+     *  (Precondition: lbl != null)
+     *  @param lbl    its the JLabel we want to get information from.
+     *  @return       a UserComponent that will hold the information about this JLabel.
+     */
+    public UserComponent getLabelInfo(JLabel lbl)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	String text;
+	text = lbl.getText();
+
+	file.startContent(1);
+	file.saveContent("JLabel");
+	
+	file.startContent(2);
+	file.saveContent(messages.getString("Label"));
+	
+	file.startContent(3);
+	if (text != null)
+	    file.saveContent(text);
+	else
+	    file.saveContent(" ");
+	
+	file.startContent(5);
+	file.saveContent(messages.getString("" + lbl.isVisible()));
+
+	file.startContent(6);
+	Icon img = lbl.getIcon();
+	if (img != null)
+	    {
+		file.saveImage(img,messages.getString("icon")+img.hashCode()+".jpg");
+	    }
+	else
+	    {
+		file.saveContent(messages.getString("NoImage"));
+	    }
+	
+	file.startContent(7);
+	file.saveContent(lbl.getToolTipText());
+
+	return file;
+    }
+    
+    /**
+     *  This method will get all the information and add the special action listener to the JComboBox.
+     *  (Precondition: box != null)
+     *  @param box    its the JComboBox we want to get information from.
+     *  @return       a UserComponent that will hold the information about this JComboBox.
+     */
+    public  UserComponent getComboBoxInfo(JComboBox box)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	ComboBoxModel cm;
+	cm = box.getModel();
+
+	box.removeActionListener(m);
+	box.addActionListener(m);
+	
+	file.startContent(1);
+	file.saveContent("JComboBox");
+	
+	file.startContent(2);
+	file.saveContent(messages.getString("ComboBox"));
+	
+	file.startContent(3);
+	int i;
+	for (i = 0; i < box.getItemCount() ; i++)
+	    {
+		UserComponent file2;
+		file2 = new UserComponent();
+		//Assuming that they don't put any picture or images
+		String text;
+		Object objmsg;
+
+		objmsg = box.getItemAt(i);
+
+		if (objmsg instanceof String)
+		    text = (String) objmsg + "\n";
+		else
+		    text = objmsg.toString() + "\n" ;
+		
+		file2.startContent(3);
+		if (text != null)
+		    file2.saveContent(text);
+		else
+		    file2.saveContent(" ");
+		
+		file2.startContent(4);
+		if (i == box.getSelectedIndex())
+		    file2.saveContent(messages.getString("Selected"));
+		else
+		    file2.saveContent(messages.getString("NotSelected"));
+		
+		file.saveContent(file2);
+	    }
+
+	file.startContent(5);
+	file.saveContent(messages.getString("" + box.isVisible()));
+
+	file.startContent(7);
+	file.saveContent(box.getToolTipText());
+
+	return file;
+    }
+
+    /**
+     *  This method will get all the information and add the special action listener to the JToggleButton.
+     *  (Precondition: button != null)
+     *  @param button its a JToggleButton inside the window
+     *  @return       a UserComponent that will hold the information about this JToggleButton.
+     */
+    public UserComponent getToggleButtonInfo (JToggleButton button)
+    {
+	UserComponent file;
+	file = new UserComponent();
+
+	button.removeActionListener(m);
+	button.addActionListener(m);
+
+	file.startContent(1);
+	if (button instanceof JCheckBox)
+	    file.saveContent("JCheckBox");
+	else
+	    file.saveContent("JRadioButton");
+	
+	file.startContent(2);
+	file.saveContent(messages.getString("ToggleButton"));
+	
+	file.startContent(3);
+	String text;
+	text = button.getText();
+	if (text != null)
+	    file.saveContent(text);
+	else
+	    file.saveContent(" ");
+	
+	file.startContent(4);
+	if (button.isSelected() == true)
+	    {
+		file.saveContent(messages.getString("Selected"));
+	    }
+	else
+	    file.saveContent(messages.getString("NotSelected"));
+	
+	file.startContent(5);
+	file.saveContent(messages.getString("" + button.isVisible()));
+	
+	file.startContent(6);
+	Icon img = button.getIcon();
+	if (img != null)
+	    {
+		file.saveImage(img,messages.getString("icon")+img.hashCode()+".jpg");
+	    }
+	else
+	    {
+		file.saveContent(messages.getString("NoImage"));
+	    }
+	
+	file.startContent(7);
+	file.saveContent(button.getToolTipText());
+
+	return file;
+    }
+
+    /**
+     *  This method will get all the information and add the special action listener to the JMenuItem.
+     *  (Precondition: menuitem != null)
+     *  @param menuitem its the JMenuItem we want to get the information from.
+     *  @return         a UserComponent that will hold the information about this JMenuItem.
+     */
+    public UserComponent getMenuItemInfo (JMenuItem menuitem)
+    {
+	UserComponent file;
+	file = new UserComponent();
+
+	menuitem.removeActionListener(m);
+	menuitem.addActionListener(m);
+	
+	file.startContent(1);
+	file.saveContent("JMenuItem");
+	
+	file.startContent(2);
+	file.saveContent(messages.getString("MenuItem"));
+	
+	file.startContent(3);
+	String text;
+	text = menuitem.getText();
+	if (text != null)
+	    file.saveContent(text);
+	else
+	    file.saveContent(" ");
+	
+	file.startContent(4);
+	if (menuitem.isSelected() == true)
+	    {
+		file.saveContent(messages.getString("Selected"));
+	    }
+	else
+	    file.saveContent(messages.getString("NotSelected"));
+	
+	file.startContent(5);
+	file.saveContent(messages.getString("" +  menuitem.isVisible()));
+	
+	file.startContent(6);
+	Icon img = menuitem.getIcon();
+	if (img  != null)
+	    {
+		file.saveImage(img,messages.getString("icon")+img.hashCode()+".jpg");
+	    }
+	else
+	    {
+		file.saveContent(messages.getString("NoImage"));
+	    }
+	
+	file.startContent(7);
+	file.saveContent(menuitem.getToolTipText());
+
+	return file;
+    }
+
+    /**
+     *  This method will get all the information of the JMenuBar.
+     *  (Precondition: menubar != null)
+     *  @param menubar its the JMenuBar we want to get the information from.
+     *  @return        a UserComponent that will hold the information about this JMenuBar.
+     */
+    public  UserComponent getMenuBarInfo (JMenuBar menubar)
+    {
+	UserComponent file;
+	file = new UserComponent();
+
+	file.startContent(1);
+	file.saveContent("JMenuBar");
+	
+	file.startContent(2);
+	file.saveContent(messages.getString("MenuBar"));
+	
+	file.startContent(3);
+	int i;
+	for (i= 0 ; i < menubar.getMenuCount() ; i++)
+	    {
+		file.saveContent(getInside(menubar.getMenu(i)));
+	    }
+	
+	file.startContent(4);
+	if (menubar.isSelected() == true)
+	    {
+		file.saveContent(messages.getString("Selected"));
+	    }
+	else
+	    file.saveContent(messages.getString("NotSelected"));
+	
+	file.startContent(5);
+	file.saveContent(messages.getString("" +  menubar.isVisible()));
+	
+	file.startContent(7);
+	file.saveContent(menubar.getToolTipText());
+
+	return file;
+    }
+
+    /**
+     *  This method will get all the information and add the special action and menu listener to the JMenu.
+     *  (Precondition: menu != null)
+     *  @param menu   its the JMenu we want to the the information from.
+     *  @return       a UserComponent that will hold the information about this JMenu.
+     */
+    public  UserComponent getMenuInfo (JMenu menu)
+    {
+	UserComponent file;
+	file = new UserComponent();
+
+	menu.removeActionListener(m);
+	menu.removeMenuListener(m);
+	menu.addActionListener(m);
+	menu.addMenuListener(m);
+
+	file.startContent(1);
+	file.saveContent("JMenu");
+	
+	file.startContent(2);
+	String text;
+	text = menu.getText();
+	if (text != null)
+	    file.saveContent(text);
+	else
+	    file.saveContent(" ");
+	
+	file.startContent(3);
+	int i;
+	for (i= 0 ; i < menu.getMenuComponentCount() ; i++)
+	    {
+		file.saveContent(getInside((Container)menu.getMenuComponent(i)));
+	    }
+	
+	file.startContent(4);
+	if (menu.isSelected() == true)
+	    {
+		file.saveContent(messages.getString("Selected"));
+	    }
+	else
+	    file.saveContent(messages.getString("NotSelected"));
+	
+	file.startContent(5);
+	file.saveContent(messages.getString("" +  menu.isVisible()));
+	
+	file.startContent(6);
+	Icon img = menu.getIcon();
+	if (img  != null)
+	    {
+		file.saveImage(img,messages.getString("icon")+img.hashCode()+".jpg");
+	    }
+	else
+	    {
+		file.saveContent(messages.getString("NoImage"));
+	    }
+	
+	file.startContent(7);
+	file.saveContent(menu.getToolTipText());
+
+	return file;
+    }
+    
+    /**
+     *  This method will get all the information of the JApplet.
+     *  (Precondition: applet != null)
+     *  @param applet its the JApplet we want to get the information from.
+     *  @return       a UserComponent that will hold the information about this JApplet.
+     */
+    public  UserComponent getAppletInfo (JApplet applet)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	Component[] group;
+	group = applet.getComponents();
+	int i;
+
+	file.startContent(1);
+	file.saveContent("JApplet");
+	
+	file.startContent(2);
+	String text;
+	text = applet.getAppletInfo();
+	if (text != null)
+	    file.saveContent(text);
+	else
+	    file.saveContent(" ");
+	
+	if (group != null)
+	    {
+		file.startContent(3);
+		for (i = 0; i < group.length ; i++)
+		    {
+			file.saveContent(getInside((Container)applet.getComponent(i)));
+		    }
+	    }
+	
+	file.startContent(4);
+	file.saveContent(messages.getString("" + applet.isActive()));
+	
+	file.startContent(5);
+	file.saveContent(messages.getString("" + applet.isVisible()));
+	
+	return file;
+    }
+
+    /**
+     *  This method will get all the information of the JWindow.
+     *  (Precondition: window != null)
+     *  @param window its the JWindow we want to get the information from.
+     *  @return       a UserComponent that will hold the information about this JWindow.
+     */
+    public  UserComponent getWindowInfo (JWindow window)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	Component[] group;
+	group = window.getComponents();
+	int i;
+
+	file.startContent(1);
+	file.saveContent("JWindow");
+	
+	file.startContent(2);
+	file.saveContent(messages.getString("Window"));
+	
+	if (group != null)
+	    {
+		file.startContent(3);
+		for (i = 0; i < group.length ; i++)
+		    {
+			file.saveContent(getInside((Container)window.getComponent(i)));
+		    }
+	    }
+	
+	file.startContent(4);
+	file.saveContent(messages.getString("" + window.isActive()));
+	
+	file.startContent(5);
+	file.saveContent(messages.getString("" + window.isVisible()));
+
+	return file;
+    }
+
+    /**
+     *  This method will get all the information of the JDialog.
+     *  (Precondition: dialog != null)
+     *  @param dialog its the JDialog we want to get the information from.
+     *  @return       a UserComponent that will hold the information about this JDialog.
+     */
+    public UserComponent getDialogInfo (JDialog dialog)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	Component[] group;
+	group = dialog.getComponents();
+	int i;
+
+	file.startContent(1);
+	file.saveContent("JDialog");
+	
+	file.startContent(2);
+	String text = dialog.getTitle();
+	if (text != null)
+	    file.saveContent(text);
+	else
+	    file.saveContent(" ");
+	
+	if (group != null)
+	    {
+		file.startContent(3);
+		for (i = 0; i < group.length ; i++)
+		    {
+			file.saveContent(getInside((Container)dialog.getComponent(i)));
+		    }
+	    }
+	
+	file.startContent(4);
+	file.saveContent(messages.getString("" + dialog.isActive()));
+
+	file.startContent(5);
+	file.saveContent(messages.getString("" + dialog.isVisible()));
+	
+	return file;
+    }
+
+    /**
+     *  This method will get all the information of the JInternalFrame.
+     *  (Precondition: frame != null)
+     *  @param frame  its the JInternalFrame we want to get the information from.
+     *  @return       a UserComponent that will hold the information about this JInternalFrame.
+     */
+    public UserComponent getInternalFrameInfo (JInternalFrame frame)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	Component[] group;
+	group = frame.getComponents();
+	int i;
+
+	file.startContent(1);
+	file.saveContent("JInternalFrame");
+	
+	file.startContent(2);
+	String text;
+	text = frame.getTitle();
+	if (text != null)
+	    file.saveContent(text);
+	else
+	    file.saveContent(" ");
+	
+	if (group != null)
+	    {
+		file.startContent(3);
+		for (i = 0; i < group.length ; i++)
+		    {
+			file.saveContent(getInside((Container)frame.getComponent(i)));
+		    }
+	    }
+	
+	file.startContent(4);
+	file.saveContent(messages.getString("" + frame.isSelected()));
+
+	file.startContent(5);
+	file.saveContent(messages.getString("" + frame.isVisible()));
+	
+	file.startContent(6);
+	Icon img = frame.getFrameIcon();
+	if (img != null)
+	    {
+		file.saveImage(img,messages.getString("icon")+img.hashCode()+".jpg");
+	    }
+	else
+	    {
+		file.saveContent(messages.getString("NoImage"));
+	    }
+	
+	file.startContent(7);
+	file.saveContent(frame.getToolTipText());
+
+	return file;
+    }
+
+    /**
+     *  This method will get all the information of the JFrame.
+     *  (Precondition: frame != null)
+     *  @param frame  its the JFrame we want to get the information from.
+     *  @return       a UserComponent that will hold the information about this JFrame.
+     */
+    public UserComponent getFrameInfo (JFrame frame)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	Component[] group;
+	group = frame.getComponents();
+	int i;
+	
+	file.startContent(1);
+	file.saveContent("JFrame");
+	
+	file.startContent(2);
+	String text;
+	text = frame.getTitle();
+	if (text != null)
+	    file.saveContent(text);
+	else
+	    file.saveContent(" ");
+	
+	if (group != null)
+	    {
+		file.startContent(3);
+		for (i = 0; i < group.length ; i++)
+		    {
+			file.saveContent(getInside((Container)frame.getComponent(i)));
+		    }
+	    }
+	
+	file.startContent(4);
+	file.saveContent(messages.getString("" + frame.isActive()));
+
+	file.startContent(5);
+	file.saveContent(messages.getString("" + frame.isVisible()));
+	
+	file.startContent(6);
+	Image image;
+	image = frame.getIconImage();
+	if (image != null)
+	    {
+		ImageIcon img;
+		img = new ImageIcon(image);
+		file.saveImage(img,messages.getString("icon")+img.hashCode()+".jpg");
+	    }
+	else
+	    {
+		file.saveContent(messages.getString("NoImage"));
+	    }
+	
+	return file;
+    }
+
+    /**
+     *  This method will get all the information of the JPanel.
+     *  (Precondition: pane != null)
+     *  @param pane   its the JPanel we want to get the information from.
+     *  @return       a UserComponent that will hold the information about this JPanel.
+     */
+    public UserComponent getPanelInfo (JPanel pane)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	Component[] group;
+	group = pane.getComponents();
+	int i;
+
+	file.startContent(1);
+	file.saveContent("JPanel");
+	
+	file.startContent(2);
+	file.saveContent(messages.getString("Panel"));
+
+	if (group != null)
+	    {
+		file.startContent(3);
+		for (i = 0; i < group.length ; i++)
+		    {
+			file.saveContent(getInside((Container)pane.getComponent(i)));
+		    }
+	    }
+
+	file.startContent(5);
+	file.saveContent(messages.getString("" + pane.isVisible()));
+	
+	file.startContent(7);
+	file.saveContent(pane.getToolTipText());
+
+	return file;
+    }
+    
+    /**
+     *  This method will get all the information of the JScrollPane.
+     *  (Precondition: scroll != null)
+     *  @param scroll its the JScrollPane we want to get the information from.
+     *  @return       a UserComponent that will hold the information about this JScrollPane.
+     */
+    public UserComponent getScrollInfo (JScrollPane scroll)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	Component[] group;
+	group = scroll.getComponents();
+	int i;
+	
+	file.startContent(1);
+	file.saveContent("JScrollPane");
+	
+	file.startContent(2);
+	file.saveContent(messages.getString("Scroller"));
+	
+	if (group != null)
+	    {
+		file.startContent(3);
+		for (i = 0; i < group.length ; i++)
+		    {
+			file.saveContent(getInside((Container)group[i]));
+		    }
+	    }
+	
+	file.startContent(5);
+	file.saveContent(messages.getString("" + scroll.isVisible()));
+	
+	file.startContent(7);
+	file.saveContent(scroll.getToolTipText());
+
+	return file;
+    }
+
+    /**
+     *  This method will get all the information and add special change listener to the JTabbedPane.
+     *  (Precondition: tab != null)
+     *  @param tab   its the JTabbedPane we want to get the information from.
+     *  @return      a UserComponent that will hold the information about this JTabbedPane.
+     */
+    public UserComponent getTabbedPaneInfo (JTabbedPane tab)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	int j;
+	
+	tab.removeChangeListener(m);
+	tab.addChangeListener(m);
+
+	file.startContent(1);
+	file.saveContent("JTabbedPane");
+	
+	file.startContent(3);
+	for (j = 0 ; j < tab.getTabCount(); j++)
+	    {	
+		UserComponent file2;
+		file2 = new UserComponent();
+
+		file2.startContent(2);
+		String title;
+		title = tab.getTitleAt(j);
+		if (title != null)
+		    file2.saveContent(title);
+		else
+		    file2.saveContent(" ");
+		
+		file2.startContent(6);
+		Icon img;
+		img = tab.getIconAt(j);
+		if (img != null)
+		    {
+			file2.saveImage(img,messages.getString("icon")+img.hashCode()+".jpg");
+		    }
+		else
+		    {
+			file2.saveContent(messages.getString("NoImage"));
+		    }
+		
+		file2.startContent(3);
+		Component group = tab.getComponentAt(j);
+		file2.saveContent(getInside((Container)group));
+		
+		file2.startContent(4);
+		if (j == tab.getSelectedIndex())
+		    file2.saveContent(messages.getString("Selected"));
+		else
+		    file2.saveContent(messages.getString("NotSelected"));
+		
+		file.saveContent(file2);
+	    }
+	
+	file.startContent(5);
+	file.saveContent(messages.getString("" + tab.isVisible()));
+	
+	file.startContent(7);
+	file.saveContent(tab.getToolTipText());
+
+	return file;
+    }
+    
+    /**
+     *  This method will get all the information of the JOptionPane.
+     *  (Precondition: op != null)
+     *  @param op   its the JOptionPane we want to get the information from.
+     *  @return      a UserComponent that will hold the information about this JOptionPane.
+     */
+    public UserComponent getOptionPaneInfo (JOptionPane op)
+    {
+	UserComponent file;
+	file = new UserComponent();
+
+	file.startContent(1);
+	file.saveContent("JOptionPane");
+	
+	file.startContent(2);
+	file.saveContent(messages.getString("OptionPane"));
+	
+	file.startContent(3);
+	Object objmsg;
+	objmsg = op.getMessage();
+
+	if (objmsg != null)
+	    {
+		String text;
+		if (objmsg instanceof String)
+		    text = (String) objmsg + "\n";
+		else
+		    text = objmsg.toString() + "\n" ;
+		file.saveContent(text);
+	    }
+	else
+	    file.saveContent(" ");
+	
+	Object[] obj;
+	int i;
+	obj = op.getOptions();
+	if (obj != null)
+	    {
+		for (i = 0; i < obj.length ; i++)
+		    {
+			if (obj[i] instanceof String)
+			    file.saveContent((String) obj[i]);
+			else
+			    file.saveContent(obj[i].toString());
+		    }
+	    }
+
+	file.startContent(5);
+	file.saveContent(messages.getString("" + op.isVisible()));
+	
+	file.startContent(6);
+	Icon img = op.getIcon();
+	if (img != null)
+	    {
+		file.saveImage(img,messages.getString("icon")+img.hashCode()+".jpg");
+	    }
+	else
+	    {
+		file.saveContent(messages.getString("NoImage"));
+	    }
+	
+	file.startContent(7);
+	file.saveContent(op.getToolTipText());
+
+	return file;
+	
+    }
+
+    /**
+     *  This method will get all the information of the JViewPort.
+     *  (Precondition: vp != null)
+     *  @param vp   its the JViewPort we want to get the information from.
+     *  @return     a UserComponent that will hold the information about this JViewPort.
+     */
+    public  UserComponent getViewPortInfo (JViewport vp)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	Component[] group;
+	group = vp.getComponents();
+	int i;
+
+	file.startContent(1);
+	file.saveContent("JViewPort");
+	
+	file.startContent(2);
+	file.saveContent(messages.getString("ViewPort"));
+	
+	if (group != null)
+	    {
+		file.startContent(3);
+		for (i = 0; i < group.length ; i++)
+		    {
+			file.saveContent(getInside((Container)group[i]));
+		    }
+	    }
+	
+	file.startContent(5);
+	file.saveContent(messages.getString("" + vp.isVisible()));
+	
+	file.startContent(7);
+	file.saveContent(vp.getToolTipText());
+
+	return file;
+    }
+
+    /**
+     *  This method will get all the information of the Box.
+     *  (Precondition: box != null)
+     *  @param box  its the Box we want to get the information from.
+     *  @return     a UserComponent that will hold the information about this Box.
+     */
+    public UserComponent getBoxInfo (Box box)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	Component[] group;
+	group = box.getComponents();
+	int i;
+
+	file.startContent(1);
+	file.saveContent("Box");
+	
+	file.startContent(2);
+	file.saveContent(messages.getString("Box"));
+	
+	if (group != null)
+	    {
+		file.startContent(3);
+		for (i = 0; i < group.length ; i++)
+		    {
+			file.saveContent(getInside((Container)group[i]));
+		    }
+	    }
+	
+	file.startContent(5);
+	file.saveContent(messages.getString("" + box.isVisible()));
+	
+	file.startContent(7);
+	file.saveContent(box.getToolTipText());
+
+	return file;
+    }
+
+    /**
+     *  This method will get all the information of the JSplitPane.
+     *  (Precondition: split != null)
+     *  @param split  its the JSplitPane we want to get the information from.
+     *  @return       a UserComponent that will hold the information about this JSplitPane.
+     */
+    public  UserComponent getSplitPaneInfo (JSplitPane split)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	Component[] group;
+	group = split.getComponents();
+	int i;
+
+	file.startContent(1);
+	file.saveContent("JSplitPane");
+	
+	file.startContent(2);
+	file.saveContent(messages.getString("Splitters"));
+	
+	if (group != null)
+	    {
+		file.startContent(3);
+		for (i = 0; i < group.length ; i++)
+		    {
+			file.saveContent(getInside((Container)group[i]));
+		    }
+	    }
+	
+	file.startContent(5);
+	file.saveContent(messages.getString("" + split.isVisible()));
+	
+	file.startContent(7);
+	file.saveContent(split.getToolTipText());
+
+	return file;
+    }
+
+    /**
+     *  This method will get all the information and add special list selection listener to the JList.
+     *  (Precondition: list != null)
+     *  @param list  its the JList we want to get the information from.
+     *  @return      a UserComponent that will hold the information about this JList.
+     */
+    public UserComponent getListInfo (JList list)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	ListModel ls;
+	ls = list.getModel();
+	int i;
+	
+	list.removeListSelectionListener(m);
+	list.addListSelectionListener(m);
+	
+	if (ls != null)
+	    {
+		if (hash.containsKey(ls) == false)
+		    hash.put(ls,list);
+		ls.removeListDataListener(m);
+		ls.addListDataListener(m);
+	    }
+
+	file.startContent(1);
+	file.saveContent("JList");
+	
+	file.startContent(2);
+	file.saveContent(messages.getString("List"));
+	
+	if (ls != null)
+	    {
+		file.startContent(3);
+		for ( i = 0 ; i < ls.getSize() ; i++)
+		    {
+			UserComponent file2;
+			file2 = new UserComponent();
+			//Assume that its all a text
+			file2.startContent(3);
+			String text;
+			Object obj;
+			obj = ls.getElementAt(i);
+			
+			if (obj instanceof String)
+			    text = (String) obj;
+			else
+			    text = obj.toString();
+			
+			if (text != null)
+			    file2.saveContent(text);
+			else
+			    file2.saveContent(" ");
+			
+			file2.startContent(4);
+			if ( i == list.getSelectedIndex())
+			    {
+				file2.saveContent(messages.getString("Selected"));
+			    }
+			else
+			    file2.saveContent(messages.getString("NotSelected"));
+			
+			file.saveContent(file2);
+		    }
+	    }
+	
+	file.startContent(5);
+	file.saveContent(messages.getString("" + list.isVisible()));
+	
+	file.startContent(7);
+	file.saveContent(list.getToolTipText());
+
+	return file;
+    }
+
+    /**
+     *  This method will get all the information and add special change listener to the JColorChooser.
+     *  (Precondition: color != null)
+     *  @param color  its the JColorChooser we want to get the information from.
+     *  @return       a UserComponent that will hold the information about this JColorChooser.
+     */
+    public UserComponent getColorInfo (JColorChooser color)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	ColorSelectionModel cm;
+	cm = color.getSelectionModel();
+	int i;
+	
+	if (cm != null)
+	    {
+		if (hash.containsKey(cm) == false)
+		    hash.put(cm,color);
+		cm.removeChangeListener(m);
+		cm.addChangeListener(m);
+	    }
+	
+	file.startContent(1);
+	file.saveContent("JColorChooser");
+
+	file.startContent(2);
+	file.saveContent(messages.getString("ColorChooser"));
+
+	file.startContent(3);
+	UserComponent file2;
+	file2 = new UserComponent();
+	file2.startContent(2);
+	file2.saveContent(messages.getString("PreviewPanel"));
+
+	file2.startContent(3);
+	file2.saveContent(getInside((Container) color.getPreviewPanel()));
+	
+	file.saveContent(file2);
+
+	file2 = new UserComponent();
+	file2.startContent(2);
+	file2.saveContent(messages.getString("ChooserPanels"));
+
+	AbstractColorChooserPanel[] cp;
+	cp = color.getChooserPanels();
+	if ((cp != null) && (cp.length != 0))
+	    {
+		file2.startContent(3);
+		for (i = 0 ; i < cp.length ; i++)
+		    {
+			UserComponent file3;
+			file3 = new UserComponent();
+			file3.startContent(2);
+			file3.saveContent(cp[i].getDisplayName());
+			
+			ColorSelectionModel cpsm;
+			cpsm = cp[i].getColorSelectionModel();
+
+			if (cpsm != null)
+			    {
+				file3.startContent(3);
+				file3.saveContent("" + 
+						  cpsm.getSelectedColor());
+			    }
+
+			file3.startContent(6);
+			Icon img = cp[i].getSmallDisplayIcon();
+			if (img  != null)
+			    {
+				file3.saveImage(img,messages.getString("icon")+img.hashCode()+".jpg");
+			    }
+			else
+			    {
+				file3.saveContent(messages.getString("NoImage"));
+			    }
+			
+			file3.startContent(6);
+			img = cp[i].getLargeDisplayIcon();
+			if (img  != null)
+			    {
+				file3.saveImage(img,messages.getString("icon")+img.hashCode()+".jpg");
+			    }
+			else
+			    {
+				file3.saveContent(messages.getString("NoImage"));
+			    }
+			file2.saveContent(file3);
+		    }
+	    }
+		
+	file.saveContent(file2);    
+	
+	file.startContent(4);
+	file.saveContent("" + cm.getSelectedColor().toString());
+
+	file.startContent(5);
+	file.saveContent(messages.getString("" +  color.isVisible()));
+	
+	file.startContent(7);
+	file.saveContent(color.getToolTipText());
+
+	return file;
+    }
+
+    /**
+     *  This method will get all the information and add special action listener to the JFileChooser.
+     *  (Precondition: fc != null)
+     *  @param fc  its the JFileChooser we want to get the information from.
+     *  @return    a UserComponent that will hold the information about this JFileChooser.
+     */
+    public UserComponent getFileChooserInfo (JFileChooser fc)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	int i;
+
+	fc.removeActionListener(m);
+	fc.addActionListener(m);
+
+	file.startContent(1);
+	file.saveContent("JFileChooser");
+	
+	file.startContent(2);
+	file.saveContent(fc.getDialogTitle());
+
+	File[] f;
+	f = fc.getSelectedFiles();
+	
+	if (f != null)
+	    {
+		file.startContent(3);
+		
+		for ( i = 0 ; i < f.length ; i++)
+		    {
+			UserComponent file2;
+			file2 = new UserComponent();
+			file2.startContent(1);
+			file2.saveContent(fc.getTypeDescription(f[i]));
+			
+			file2.startContent(2);
+			file2.saveContent(fc.getName(f[i]));
+			
+			file2.startContent(6);
+			Icon img = fc.getIcon(f[i]);
+			if (img  != null)
+			    {
+				file2.saveImage(img,messages.getString("icon")+img.hashCode()+".jpg");
+			    }
+			else
+			    {
+				file2.saveContent(messages.getString("NoImage"));
+			    }
+			file.saveContent(file2);
+		    }
+	    }
+
+	file.startContent(5);
+	file.saveContent(messages.getString("" +  fc.isVisible()));
+	
+	file.startContent(7);
+	file.saveContent(fc.getToolTipText());
+
+	return file;
+    }		
+
+    /**
+     *  This method will get all the information and add special list selection and column model listener 
+     *  to the JTable.
+     *  (Precondition: table != null)
+     *  @param table  its the JTable we want to get the information from.
+     *  @return       a UserComponent that will hold the information about this JTable.
+     */
+    public UserComponent getTableInfo (JTable table)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	TableModel tm;
+	tm = table.getModel();
+	int i,j;
+	String text;
+
+	TableColumnModel tcm;
+	tcm = table.getColumnModel();
+	ListSelectionModel lm;
+	lm = table.getSelectionModel(); 
+
+	if (lm != null)
+	    {
+		if (hash.containsKey(lm) == false)
+		    hash.put(lm,table);
+		lm.removeListSelectionListener(m);
+		lm.addListSelectionListener(m);
+	    }
+	
+	if (tcm != null)
+	    {
+		if (hash.containsKey(tcm) == false)
+		    hash.put(tcm,table);
+		tcm.removeColumnModelListener(m);
+		tcm.addColumnModelListener(m);
+	    }
+
+	file.startContent(1);
+	file.saveContent("JTable");
+	
+	file.startContent(2);
+	file.saveContent(messages.getString("Table"));
+	
+	if (tm != null)
+	    {
+		file.startContent(3);
+		for ( i = 0 ; i < tm.getRowCount() ; i++)
+		    {
+			UserComponent file2;
+			file2 = new UserComponent();
+			
+			file2.startContent(2);
+			text = messages.getString("row") +" " + (i + 1);
+			file2.saveContent(text);
+			
+			file2.startContent(3);
+			for ( j = 0 ; j < tm.getColumnCount() ; j++)
+			    {
+				UserComponent file3;
+				file3 = new UserComponent();
+				
+				file3.startContent(2);
+				file3.saveContent(tm.getColumnName(j));
+				
+				file3.startContent(3);
+				
+				Object obj;
+				obj = tm.getValueAt(i,j);
+				
+				if (obj instanceof String)
+				    file3.saveContent((String)obj);
+				else
+				    file3.saveContent(obj.toString());
+				
+				file3.startContent(4);
+				if (table.isCellSelected(i,j) == true)
+				    {
+					file3.saveContent(messages.getString("Selected"));
+				    }
+				else
+				    file3.saveContent(messages.getString("NotSelected"));
+				
+				file2.saveContent(file3);
+			    }
+			
+			file.saveContent(file2);
+		    }
+	    }
+
+	file.startContent(5);
+	file.saveContent(messages.getString("" +  table.isVisible()));
+	
+	file.startContent(7);
+	file.saveContent(table.getToolTipText());
+
+	return file;
+    }
+
+    /**
+     *  This method will get all the information of the JScrollBar.
+     *  (Precondition: scroll != null)
+     *  @param scroll  its the JScrollBar we want to get the information from.
+     *  @return         a UserComponent that will hold the information about this JScrollBar.
+     */
+    public  UserComponent getScrollBarInfo (JScrollBar scroll)
+    {
+	UserComponent file;
+	file = new UserComponent();
+
+	file.startContent(1);
+	file.saveContent("JScrollBar");
+	
+	file.startContent(2);
+	file.saveContent(messages.getString("ScrollerBar"));
+	
+	file.startContent(3);
+	file.saveContent(""+ scroll.getOrientation()+ " :"+ scroll.getValue());
+	
+	file.startContent(5);
+	file.saveContent(messages.getString("" + scroll.isVisible()));
+	
+	file.startContent(7);
+	file.saveContent(scroll.getToolTipText());
+
+	return file;
+    }
+
+    /**
+     *  This method will get all the information and add special tree selection listener to the JTree.
+     *  (Precondition: tree != null)
+     *  @param tree  its the JTree we want to get the information from.
+     *  @return      a UserComponent that will hold the information about this JTree.
+     */
+    public UserComponent getTreeInfo (JTree tree)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	TreeModel tm;
+	tm = tree.getModel();
+	int i;
+	
+	tree.removeTreeSelectionListener(m);
+	tree.addTreeSelectionListener(m);
+	
+	if (tm != null)
+	    {
+		if (hash.containsKey(tm) == false)
+		    hash.put(tm,tree);
+		tm.removeTreeModelListener(m);
+		tm.addTreeModelListener(m);
+	    }
+	
+	file.startContent(1);
+	file.saveContent("JTree");
+	
+	file.startContent(2);
+	file.saveContent(messages.getString("Tree"));
+	
+	file.startContent(3);
+	Object root;
+	root = tm.getRoot();
+	file.saveContent(getChildInfo(tm,root,tree));
+	
+	file.startContent(5);
+	file.saveContent(messages.getString("" +  tree.isVisible()));
+	
+	file.startContent(7);
+	file.saveContent(tree.getToolTipText());
+
+	return file;
+    }
+       
+    /**
+     *  This method will get all the information about the parent node and all the childs of it inside the JTree.
+     *  (Precondition: (tree != null) && (tm != null) && (parent != null))
+     *  @param tm      its the tree model of the JTree.
+     *  @param parent  its the parent node that we want to get all the child information from.
+     *  @param tree    its the JTree where the parent node belongs to.
+     *  @return        a UserComponent that will hold the information about this parent node.  
+     */
+    private UserComponent getChildInfo (TreeModel tm,Object parent,JTree tree)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	if (tm.isLeaf(parent) == false)
+	    {
+		file.startContent(2);
+		String text;
+		text = parent.toString();
+		if (text != null)
+		    file.saveContent(text);
+		else
+		    file.saveContent(" ");
+		
+		int j;
+		for (j = 0 ; j < tm.getChildCount(parent) ; j++)
+		    {
+			file.startContent(3);
+			Object child;
+			child = tm.getChild(parent,j);
+			file.saveContent(getChildInfo(tm,child,tree));
+		    }
+	    }
+	else
+	    {
+		file.startContent(2);
+		String text;
+		text = parent.toString();
+		if (text != null)
+		    file.saveContent(text);
+		else
+		    file.saveContent(" ");
+	    }
+	return file;
+    }
+
+    /**
+     *  This method will get all the information of a Container that is not belongs to any of the more specified
+     *  method stated in this class.
+     *  (Precondition: pane != null)
+     *  @param pane  its the Container component we want to get the information from.
+     *  @return      a UserComponent that will hold the information about this Container.
+     */
+    public UserComponent getCompInfo (Container pane)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	Component[] group;
+	group = pane.getComponents();
+	int i;
+
+	file.startContent(1);
+	file.saveContent("Container");
+	
+	file.startContent(2);
+	file.saveContent(messages.getString("Container"));
+	
+	if (group != null)
+	    {
+		file.startContent(3);
+		file.saveContent(messages.getString("TitlePane"));
+		file.saveContent(getInside(null));
+		/*for (i = 0; i < group.length ; i++)
+		    {
+			file.saveContent(getInside((Container)pane.getComponent(i)));
+			}*/
+	    }
+	
+	file.startContent(5);
+	file.saveContent(messages.getString("" + pane.isVisible()));
+	
+	return file;
+    }
+
+    /**
+     *  This method will get all the information of the JPopupMenu.
+     *  (Precondition: popup != null)
+     *  @param popup  its the JPopUpMenu we want to get the information from.
+     *  @return       a UserComponent that will hold the information about this JPopupMenu.
+     */
+    public UserComponent getPopUpMenuInfo (JPopupMenu popup)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	Component[] group;
+	group = popup.getComponents();
+	SingleSelectionModel sm;
+	sm = popup.getSelectionModel();
+	int i;
+
+	file.startContent(1);
+	file.saveContent("JPopUpMenu");
+
+	file.startContent(2);
+	String text;
+	text = popup.getLabel();
+	if (text != null)
+	    file.saveContent(popup.getLabel());
+	else
+	    file.saveContent(" ");
+
+	if (group != null)
+	    {
+		file.startContent(3);
+		for (i = 0; i < group.length ; i++)
+		    {
+			file.saveContent(getInside((Container)popup.getComponent(i)));
+		    }
+	    }
+
+	if (sm != null)
+	    {
+		file.startContent(4);
+		file.saveContent("" + sm.getSelectedIndex());
+	    }
+
+	file.startContent(5);
+	file.saveContent(messages.getString("" + popup.isVisible()));
+	
+	file.startContent(7);
+	file.saveContent(popup.getToolTipText());
+
+	return file;
+    }
+
+    /**
+     *  This method will get all the information of the JRootPane.
+     *  (Precondition: pane != null)
+     *  @param pane  its the JRootPane we want to get the information from.
+     *  @return      a UserComponent that will hold the information about this JRootPane.
+     */
+    public UserComponent getRootPaneInfo (JRootPane pane)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	Component[] group;
+	group = pane.getComponents();
+	int i;
+	
+	file.startContent(1);
+	file.saveContent("JRootPane");
+	
+	file.startContent(2);
+	file.saveContent(messages.getString("RootPane"));
+
+	if (group != null)
+	    {
+		file.startContent(3);
+		for (i = 0; i < group.length ; i++)
+		    {
+			
+			file.saveContent(getInside((Container)pane.getComponent(i)));
+		    }
+	    }
+
+	file.startContent(5);
+	file.saveContent(messages.getString("" + pane.isVisible()));
+	
+	file.startContent(7);
+	file.saveContent(pane.getToolTipText());
+
+	return file;
+    }
+
+    /**
+     *  This method will get all the information of the JLayeredPane.
+     *  (Precondition: pane != null)
+     *  @param pane  its the JLayeredPane we want to get the information from.
+     *  @return      a UserComponent that will hold the information about this JLayeredPane.
+     */
+    public UserComponent getLayeredPaneInfo (JLayeredPane pane)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	Component[] group;
+	group = pane.getComponents();
+	int i;
+	
+	file.startContent(1);
+	file.saveContent("JLayeredPane");
+	
+	file.startContent(2);
+	file.saveContent(messages.getString("LayeredPane"));
+	
+	if (group != null)
+	    {
+		file.startContent(3);
+		for (i = 0; i < group.length ; i++)
+		    {
+			file.saveContent(getInside((Container)pane.getComponent(i)));
+		    }
+	    }
+
+	file.startContent(5);
+	file.saveContent(messages.getString("" + pane.isVisible()));
+	
+	file.startContent(7);
+	file.saveContent(pane.getToolTipText());
+
+	return file;
+    }
+
+    /**
+     *  This method will get all the information of the BasicInternalFrameTitlePane.
+     *  (Precondition: pane != null)
+     *  @param pane  its the BasicInternalFrameTitlePane we want to get the information from.
+     *  @return      a UserComponent that will hold the information about this BasicInternalFrameTitlePane.
+     */
+    public UserComponent getInternalFrameTitleInfo (BasicInternalFrameTitlePane pane)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	Component[] group;
+	group = pane.getComponents();
+	int i;
+
+	file.startContent(1);
+	file.saveContent("BasicInternalFrameTitlePane");
+	
+	file.startContent(2);
+	file.saveContent(messages.getString("InternalFrameTitlePane"));
+	
+	/*if (group != null)
+	    {
+		file.startContent(3);
+		for (i = 0; i < group.length ; i++)
+		    {
+			Component c;
+			c = pane.getComponent(i);
+			
+			else
+			    file.saveContent(getInside((Container)pane.getComponent(i)));
+		    }
+		    }*/
+	
+	file.startContent(5);
+	file.saveContent(messages.getString("" + pane.isVisible()));
+	
+	file.startContent(7);
+	file.saveContent(pane.getToolTipText());
+
+	return file;
+    }
+
+    /**
+     *  This method will get all the information and add special column model and list selection
+     *  listener to JTableHeader.
+     *  (Precondition: header != null)
+     *  @param header  its the JTableHeader we want to get the information from.
+     *  @return        a UserComponent that will hold the information about this JTableHeader.
+     */
+    public UserComponent getTableHeaderInfo (JTableHeader header)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	TableColumnModel tcm;
+	tcm = header.getColumnModel();
+	ListSelectionModel lm;
+	lm = tcm.getSelectionModel();
+
+	if (tcm != null)
+	    {
+		if (hash.containsKey(tcm) == false)
+		    hash.put(tcm,header);
+		tcm.removeColumnModelListener(m);
+		tcm.addColumnModelListener(m);
+	    }
+
+	if (lm != null)
+	    {
+		if (hash.containsKey(lm) == false)
+		    hash.put(lm,header);
+		lm.removeListSelectionListener(m);
+		lm.addListSelectionListener(m);
+	    }
+
+	file.startContent(1);
+	file.saveContent("JTableHeader");
+	
+	file.startContent(2);
+	file.saveContent(messages.getString("TableHeader"));
+
+	if (tcm != null)
+	    {
+		int[] select = tcm.getSelectedColumns();
+
+		if (select != null)
+		    {
+			file.startContent(3);
+			for (int i = 0 ; i < select.length ; i++)
+			    {
+				UserComponent file2;
+				file2 = new UserComponent();
+				file2.startContent(4);
+				file2.saveContent("" + select[i]);
+				
+				file.saveContent(file2);
+			    }
+		    }
+	    }
+
+	file.startContent(5);
+	file.saveContent(messages.getString("" + header.isVisible()));
+	
+	file.startContent(7);
+	file.saveContent(header.getToolTipText());
+
+	return file;
+    }
+
+    /**
+     *  This method will get all the information of the JToolBar.
+     *  (Precondition: tool != null)
+     *  @param tool  its the JToolBar we want to get the information from.
+     *  @return      a UserComponent that will hold the information about this JToolBar.
+     */
+    public UserComponent getToolBarInfo (JToolBar tool)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	Component[] group;
+	group = tool.getComponents();
+	int i;
+	
+	file.startContent(1);
+	file.saveContent("JToolBar");
+	
+	file.startContent(2);
+	file.saveContent(messages.getString("ToolBar"));
+	
+	if (group != null)
+	    {
+		file.startContent(3);
+		for (i = 0; i < group.length ; i++)
+		    {
+			file.saveContent(getInside((Container)tool.getComponent(i)));
+		    }
+	    }
+
+	file.startContent(5);
+	file.saveContent(messages.getString("" + tool.isVisible()));
+	
+	file.startContent(7);
+	file.saveContent(tool.getToolTipText());
+
+	return file;
+    }
+
+    /**
+     *  This method will get all the information of the JToolTip.
+     *  (Precondition: tip != null)
+     *  @param tip  its the JToolTip we want to get the information from.
+     *  @return     a UserComponent that will hold the information about this JToolTip.
+     */
+    public UserComponent getToolTipInfo (JToolTip tip)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	Component group;
+	group = tip.getComponent();
+	int i;
+	
+	file.startContent(1);
+	file.saveContent("JToolTip");
+	
+	file.startContent(2);
+	String text;
+	text = tip.getTipText();
+	if (text != null)
+	    file.saveContent(tip.getTipText());
+	else
+	    file.saveContent(" ");
+	
+	if (group != null)
+	    {
+		file.startContent(3);
+		file.saveContent(getInside((Container) group));
+	    }
+	
+	file.startContent(5);
+	file.saveContent(messages.getString("" + tip.isVisible()));
+	
+	return file;
+    }
+
+    /**
+     *  This method will get all the information of the JSeparator.
+     *  (Precondition: sept != null)
+     *  @param sept  its the JSeparator we want to get the information from.
+     *  @return      a UserComponent that will hold the information about this JSeparator.
+     */
+    public UserComponent getSeparatorInfo (JSeparator sept)
+    {
+	UserComponent file;
+	file = new UserComponent();
+
+	file.startContent(1);
+	file.saveContent("JSeparator");
+	
+	file.startContent(2);
+	file.saveContent(messages.getString("Separator"));
+
+	file.startContent(5);
+	file.saveContent(messages.getString("" + sept.isVisible()));
+	
+	file.startContent(7);
+	file.saveContent(sept.getToolTipText());
+
+	return file;
+    }
+
+    /**
+     *  This method will get all the information of the JDesktopPane.
+     *  (Precondition: pane != null)
+     *  @param pane  its the JDesktopPane we want to get the information from.
+     *  @return      a UserComponent that will hold the information about this JDesktopPane.
+     */
+    public UserComponent getDesktopPaneInfo (JDesktopPane pane)
+    {
+	UserComponent file;
+	file = new UserComponent();
+	JInternalFrame[]  group;
+	group = pane.getAllFrames();
+
+	file.startContent(1);
+	file.saveContent("JDesktopPane");
+
+	file.startContent(2);
+	file.saveContent(messages.getString("DesktopPane"));
+
+	if (group != null)
+	    {
+		int i;
+		file.startContent(3);
+		for ( i = 0 ; i < group.length ; i++ )
+		    {
+			file.saveContent (getInside((Container) group[i]));
+		    }
+	    }
+
+	file.startContent(5);
+	file.saveContent(messages.getString("" + pane.isVisible()));
+	
+	file.startContent(7);
+	file.saveContent(pane.getToolTipText());
+
+	return file;
+    }
+
+    /**
+     *  This method will give you a UserComponent that hold the information saying
+     *  the component is null (no component).
+     *  @return  a UserComponent that will hold the information saying its a null component.
+     */
+    public UserComponent getNullInfo ()
+    {
+	UserComponent file;
+	file = new UserComponent();
+
+	file.startContent(1);
+	file.saveContent(messages.getString("NoComponent"));
+
+	return file;
+    }
+
+    /**
+     *  This method will get all information about any kind of Container.
+     *  This method is the gateway to all other methods in this class and will give you all
+     *  information about the Container and whats inside it.If you dont know what the specific class
+     *  of your container then you go here and it will sort which appropriate method 
+     *  this container should go to in this class.
+     *  @param comp its the Container we want to get the information from.
+     *  @return     a UserComponent that hold the information about this Container.
+     */
+    public  UserComponent getInside(Container comp)
+    {
+	if (comp == null)
+	    {
+		return getNullInfo();
+	    }
+	else if (comp instanceof JApplet)
+	    {
+		return getAppletInfo ((JApplet) comp);
+	    }
+	else if (comp instanceof JSeparator)
+	    {
+		return getSeparatorInfo ((JSeparator) comp);
+	    }
+	else if (comp instanceof JWindow)
+	    {
+		return getWindowInfo((JWindow) comp);
+	    }
+	else if (comp instanceof JDialog)
+	    {
+		return getDialogInfo((JDialog) comp);
+	    }
+	else if (comp instanceof JComboBox)
+	    {
+		return getComboBoxInfo((JComboBox) comp);
+	    }
+	else if (comp instanceof JLabel)
+	    {
+		return getLabelInfo((JLabel) comp);
+	    }
+	else if (comp instanceof JTextComponent)
+	    {
+		return getTextAreaInfo((JTextComponent) comp);
+	    }
+	else if (comp instanceof JFrame)
+	    {
+		return getFrameInfo((JFrame) comp);
+	    }
+	else if (comp instanceof JPanel)
+	    {
+		return getPanelInfo((JPanel) comp);
+	    }
+	else if (comp instanceof JScrollPane)
+	    {
+		return getScrollInfo((JScrollPane) comp);
+	    }
+	else if (comp instanceof JScrollBar)
+	    {
+		return getScrollBarInfo ((JScrollBar) comp);
+	    }
+	else if (comp instanceof JViewport)
+	    {
+		return getViewPortInfo((JViewport) comp);
+	    }
+	else if (comp instanceof JTabbedPane)
+	    {
+		return getTabbedPaneInfo((JTabbedPane) comp);
+	    }
+	else if (comp instanceof Box)
+	    {
+		return getBoxInfo((Box) comp);
+	    }
+	else if (comp instanceof JToggleButton)
+	    {
+		return getToggleButtonInfo((JToggleButton) comp);
+	    }
+	else if (comp instanceof JSplitPane)
+	    {
+		return getSplitPaneInfo ((JSplitPane) comp);
+	    }
+	else if (comp instanceof JList)
+	    {
+		return getListInfo ((JList) comp);
+	    }
+	else if (comp instanceof JTree)
+	    {
+		return getTreeInfo ((JTree) comp);
+	    }
+	else if (comp instanceof JTable)
+	    {
+		return getTableInfo ((JTable) comp);
+	    }
+	else if (comp instanceof JSlider)
+	    {
+		return getSliderInfo ((JSlider) comp);
+	    }
+	else if (comp instanceof JSpinner)
+	    {
+		return getSpinnerInfo ((JSpinner) comp);
+	    }
+	else if (comp instanceof JProgressBar)
+	    {
+		return getProgressBarInfo ((JProgressBar) comp);
+	    }
+	else if (comp instanceof JButton)
+	    {
+		return getButtonInfo ((JButton) comp);
+	    }
+	else if (comp instanceof JMenu)
+	    {
+		return getMenuInfo ((JMenu) comp);
+	    }
+	else if (comp instanceof JMenuBar)
+	    {
+		return getMenuBarInfo ((JMenuBar) comp);
+	    }
+	else if (comp instanceof JMenuItem)
+	    {
+		return getMenuItemInfo ((JMenuItem) comp);
+	    }
+	else if (comp instanceof JOptionPane)
+	    {
+		return getOptionPaneInfo ((JOptionPane) comp);
+	    }
+	else if (comp instanceof BasicInternalFrameTitlePane)
+	    {
+		return getInternalFrameTitleInfo ((BasicInternalFrameTitlePane) comp);
+	    }
+	else if (comp instanceof JColorChooser)
+	    {
+		return getColorInfo ((JColorChooser) comp);
+	    }
+	else if (comp instanceof JFileChooser)
+	    {
+		return getFileChooserInfo ((JFileChooser) comp);
+	    }
+	else if (comp instanceof JDesktopPane)
+	    {
+		return getDesktopPaneInfo ((JDesktopPane) comp);
+	    }
+	else if (comp instanceof JInternalFrame)
+	    {
+		return getInternalFrameInfo ((JInternalFrame) comp);
+	    }
+	else if (comp instanceof JLayeredPane)
+	    {
+		return getLayeredPaneInfo ((JLayeredPane) comp);
+	    }
+	else if (comp instanceof JPopupMenu)
+	    {
+		return getPopUpMenuInfo ((JPopupMenu) comp);
+	    }
+	else if (comp instanceof JRootPane)
+	    {
+		return getRootPaneInfo ((JRootPane) comp);
+	    }
+	else if (comp instanceof JTableHeader)
+	    {
+		return getTableHeaderInfo ((JTableHeader) comp);
+	    }
+	else if (comp instanceof JToolBar)
+	    {
+		return getToolBarInfo ((JToolBar) comp);
+	    }
+	else if (comp instanceof JToolTip)
+	    {
+		return getToolTipInfo ((JToolTip) comp);
+	    }
+	else
+	    {
+		return getCompInfo (comp);
+	    }
+    }
+}
+
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/FeedbackInterface.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/FeedbackInterface.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/FeedbackInterface.java	(revision 13928)
@@ -0,0 +1,1656 @@
+package org.greenstone.gatherer.feedback;
+
+import java.io.*;
+import java.awt.*;
+import java.awt.image.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.border.*;
+import java.util.*;
+import java.net.*;
+import java.rmi.server.*;
+import javax.imageio.*;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.text.MessageFormat;
+import com.sun.image.codec.jpeg.*;
+import javax.swing.Timer;
+import org.greenstone.gatherer.Gatherer;
+
+/**
+ * This class will show the FeedbackInterface form.
+ * It will allow user to described about the problem better.Here we will also take some more information available
+ * in the system such as the size of the memory available and the screen size.User also could take more screenshot
+ * so they will be able to say the sequence of events that lead up to the problem.
+ * <br>If the user don't want to send this form, then all the information taken from this form will be deleted 
+ * and user will be quitted from the Reporting Feedback sequence.
+ *
+ * @author Veronica Liesaputra
+ */
+public class FeedbackInterface extends JDialog
+    implements ActionListener
+{
+    /**
+     * This is the button user need to pressed if they want to view the files.
+     * This button will be disabled when the timer is running and finish = false.
+     */
+    private JButton view_button;
+    
+    /**
+     * This button means that the user finished give the information and
+     * want to send it.
+     */
+    public JButton send_button;
+
+    /**
+     * This button means that the user don't want to send information and
+     * back to normal application.
+     * All the data taken start from user choose to start doing the Feedback sequence 
+     * up to this point will be delete.
+     */
+    private JButton notsend_button; 
+
+    /**
+     * This is the text area where user can explain more about the problem.
+     */
+    private JTextArea problem_details;
+
+    /**
+     * This is the combo box that allow user to specify the poblem type.
+     */
+    private JComboBox problem_type;
+
+    /**
+     * This is the combo box that allow user to specify the urgency of the problem.
+     */
+    private JComboBox problem_urgency;
+
+    /**
+     * This combo box will ask whether or not user want to send the screenshot.
+     */
+    private JComboBox problem_screenshot;
+
+    /**
+     * This text field allow user to type the smtp address of their email that
+     * they want this application to use to send all the data.
+     * If they don't fill this field then it will set to the same
+     * smtp adress of where the data will be send to.
+     */
+    private JTextField smtp_address;
+
+    /**
+     * This text field allow user to type the email adress that they want this
+     * application to use to send all the data.
+     * If they don't fill this field then it will set to the same email
+     * adress of where the data will be send to.
+     */
+    private JTextField email_address;
+
+    /**
+     * This is the name of the window the user lastly used.
+     * This is the name of the window where the user called to start the Feedback
+     * sequence.
+     */
+    private String frameName;
+
+    /**
+     * This is the unique code generated for each time user start doing the Feedback
+     * sequence.
+     * This code will be used as reference to which feedback that the user send.
+     */
+    private static String code;
+
+    /**
+     * This is the date when the user start open this FeedbackInterface form.
+     */
+    private Date curr_date;
+    
+    /**
+     * This is the special listener class that record all the action user did in application.
+     */
+    private static ActionRecorderDialog dialog;
+
+    /**
+     * This variable will hold the resource of the words that is stored in Messages.properties file.
+     * The calling using messages.getString(someString) will caused someString to be translated
+     * into some other string that is hold in that file.usually it will caused it to be translated
+     * to the language that the user use or choose to have as stated in Locale.
+     */
+    private static ResourceBundle messages;
+
+    /**
+     * This is the screen shot instance that will allow the application to take screen shot of the whole
+     * screen or only the window that the user currently doing their action.
+     */
+    private ScreenShot screen;
+
+    /**
+     * This is the thread that allows the encoding of the image file to String and the saving of image to
+     * a jpeg file happens concurrently.
+     */
+    private Thread save;
+
+    /**
+     * This is the hashmap that hold the screen shot and the panel where the screenshot is held.
+     */
+    private HashMap picAndPane;
+
+    /**
+     * This is the panel that hold all the panels containing the screenshots taken.
+     */
+    private JPanel picture_scroll;
+
+    /**
+     * This is how many rows of screenshots panel displayed at the moment.
+     */
+    private int row;
+
+    /**
+     * This is the array list that hold all the screenshots panel displayed.
+     */
+    private ArrayList paneArray;
+
+    /**
+     * This button will remove the last screenshot panels.
+     */
+    private JButton remove;
+
+    /**
+     * This is a reference to feedback interface displayed at the moment.
+     */
+    private FeedbackInterface frame;
+
+    /**
+     * This is the thread to send all the xml files back to the developer.
+     */
+    private Thread sendThread;
+
+    /**
+     * This is the flag to tell whether or not the sending files finished or not.
+     * It is also flag to tell whether or not the viewing files finished or not.
+     */
+    private static boolean finish;
+
+    /**
+     * This is the timer to displayed the progress bar to tell user to wait while
+     * we sending the files or while we generate the xml files to be viewed.
+     * If finish = false then wait cursor,progress bar and wait label will be displayed.
+     * If finish = true then default cursor will be displayed.
+     */
+    private Timer timer;
+
+    /**
+     * Progress bar displayed when user sending or want to view details.
+     */
+    private JProgressBar progressBar;
+
+    /**
+     * Label displayed to tell user to wait for a while.
+     */
+    private JLabel wait_lbl;
+
+    /**
+     * This is the background colour for the window.
+     */
+    private Color bckcolor;
+    
+    /**
+     * This is the panel to displayed all descriptions panel.
+     */
+    private JPanel tempPane;
+
+    /**
+     * This is the thread that will be running when user pressed the preview button.
+     * This thread will show the 6 xml files that are going to be send. It will run concurrently
+     * with the timer, if value of finish = true, this thread will be null-ed.
+     */
+    private Thread prevThread;
+    
+    /**
+     * This is the flag to say whether or not this window should be dispose when timer is stop
+     * and finish = true.
+     * If selected = true then this window should be dispose, otherwise don't dispose it.
+     */
+    private boolean selected = false;
+    
+    /**
+     * This is a blocker to say that user cannot do anything while waiting.
+     */
+    private MouseListener mouse_blocker_listener = new MouseAdapter() {};
+ 
+    /**
+     * Will make a dialog window that allows people to write more about the problem that want
+     * to send.
+     * This is the GUI for user to write on Feedback form. It is also setting the up the appropriate 
+     * data member with the value passed on to this constructor.
+     * (Precondition: (sh != null) && (dlg != null) && (msg != null))
+     * @param sh  an instance of ScreenShot that will allow application to take screenshot.
+     * @param frame_name name of the window where user called Feedback form from.
+     * @param msg holding the resource of the words that is stored in Messages.properties file.
+     * @param dlg holding the special listener.
+     */
+    public FeedbackInterface(ScreenShot sh,String frame_name,
+			     ResourceBundle msg,ActionRecorderDialog dlg)
+    {
+	super();
+
+	frame = this;
+
+	bckcolor = new Color(176,209,217);
+
+	picAndPane = new HashMap();
+
+	messages = msg;
+	frameName = frame_name;
+	dialog = dlg;
+
+	FeedbackInterface.setDefaultLookAndFeelDecorated(true);
+	setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
+	setTitle(messages.getString("SendFeedbackForm"));
+	
+	screen = sh;
+	Container container;
+	container = getContentPane();
+	createUI(container);
+	curr_date = new Date();
+	
+	Toolkit kit;
+	kit = Toolkit.getDefaultToolkit();
+	Dimension screenSize;
+	screenSize = kit.getScreenSize();
+	int screenHeight;
+	screenHeight = screenSize.height;
+	int screenWidth;
+	screenWidth = screenSize.width;
+	Dimension size;
+	size = this.getSize();
+	setLocation((screenWidth - size.width - 500) , 
+		    (screenHeight - size.height - 700));
+	
+	setBackground(bckcolor);
+	pack();
+	setModal(false);
+	setVisible(true);
+    }
+
+    /**
+     * This method is setting up the content pane for the Feedback form window.
+     * (Precondition: (window != null))
+     * @param window the content pane of Feedback form window. 
+     */
+    public void createUI(Container window)
+    {
+	JPanel container;
+	container = new JPanel();
+	container.setBackground(bckcolor);
+	container.setLayout(new BoxLayout(container,BoxLayout.PAGE_AXIS));
+	
+	String opening_text;
+	opening_text = messages.getString("FeedbackOpeningText");
+	JTextArea textArea;
+	textArea = new JTextArea(opening_text);
+	textArea.setMinimumSize(new Dimension(100,100));
+	textArea.setOpaque(false);
+	textArea.setEditable(false);
+	textArea.setLineWrap(true);
+	textArea.setWrapStyleWord(true);
+	textArea.setBorder(new EmptyBorder(10,10,0,10));
+	textArea.setBackground(bckcolor);
+	container.add(textArea);
+
+	tempPane = new JPanel();
+	tempPane.setLayout(new BorderLayout());
+	tempPane.setBackground(new Color(176,208,176));
+
+	paneArray = new ArrayList();
+	picture_scroll = new JPanel();
+	row = 1;
+	picture_scroll.setLayout(new GridLayout(0,1));
+	picture_scroll.setBackground(new Color(176,208,176));
+	tempPane.add(picture_scroll,BorderLayout.PAGE_START);
+
+	JPanel btnPanel;
+	btnPanel = new JPanel();
+	btnPanel.setBackground(new Color(176,208,176));
+	remove = new JButton("Remove");
+	remove.setActionCommand("Remove");
+	remove.addActionListener(new ActionListener ()
+	    {
+		public void actionPerformed(ActionEvent e)
+		{
+		    Object obj;
+		    JPanel pane;
+
+		    if (paneArray.size() == 0)
+			System.out.println("There is no panel here!");
+		    else
+			{
+			    pane = (JPanel) paneArray.get((row - 2));
+			    obj = picAndPane.get(pane);
+			    obj = null;
+			    picAndPane.remove(pane);
+			    paneArray.remove((row - 2));
+			    
+			    if (paneArray.size() == 0)
+				remove.setVisible(false);
+
+			    picture_scroll.remove(pane);
+			
+			    row--;
+			    
+			    picture_scroll.setSize(picture_scroll.getPreferredSize());
+			    picture_scroll.revalidate();
+			    picture_scroll.repaint();
+			    tempPane.setSize(tempPane.getPreferredSize());
+			    tempPane.revalidate();
+			    tempPane.repaint();
+			}
+		}
+	    });
+	remove.setToolTipText("Remove last thumbnail");
+	remove.setBackground(new Color(176,208,176));
+	remove.setVisible(false);
+	btnPanel.add(remove);
+	tempPane.add(btnPanel,BorderLayout.PAGE_END);
+   
+	JScrollPane pict_scroll;
+	pict_scroll = new JScrollPane(tempPane);
+	pict_scroll.setBackground(bckcolor);
+	pict_scroll.setPreferredSize(new Dimension(300,300));
+	pict_scroll.setBorder(new EmptyBorder(0,10,10,10));
+	container.add(pict_scroll);
+
+	JPanel pane;
+	pane = new JPanel();
+	pane.setBackground(bckcolor);
+	pane.setLayout(new GridLayout(0,2));
+	pane.setBorder(new EmptyBorder(10,10,10,10));
+		
+	JLabel txt_type;
+	txt_type = new JLabel(messages.getString("Whatkindofproblemisit") + "?    ");
+	txt_type.setBackground(bckcolor);
+	pane.add(txt_type);
+	
+	String [] type = {" ",messages.getString("ContentError"),
+			  messages.getString("ImageNotShow"),
+			  messages.getString("StrangeBehaviour"),
+			  messages.getString("SomethingUnexpectedHappen"),
+			  messages.getString("HardToUse"),
+			  messages.getString("Other")};
+	problem_type = new JComboBox(type);
+	problem_type.setOpaque(false);
+	problem_type.addActionListener(this);
+	problem_type.setBackground(bckcolor);
+	pane.add(problem_type);
+
+	JLabel txt_urgent;
+	txt_urgent = new JLabel(messages.getString("Howbadistheproblem")+"?  ");
+	txt_urgent.setBackground(bckcolor);
+	pane.add(txt_urgent);
+
+	String[] urgent = {" ",messages.getString("Critical"),
+		  messages.getString("Serious"),
+		  messages.getString("Medium"),messages.getString("Minor"),
+		  messages.getString("Trivial")};
+	problem_urgency = new JComboBox(urgent);
+	problem_urgency.setOpaque(false);
+	problem_urgency.addActionListener(this);
+	problem_urgency.setBackground(bckcolor);
+	pane.add(problem_urgency);
+
+	/*JLabel txt_screenshot;
+	txt_screenshot= new JLabel(messages.getString("Doyouwanttosendthescreenshot") + "?  ");
+	txt_screenshot.setBackground(new Color(108,168,108));
+	pane.add(txt_screenshot);
+
+	String[] screenshot = {messages.getString("Yes"),
+			       messages.getString("No")};
+	problem_screenshot = new JComboBox(screenshot);
+	problem_screenshot.addActionListener(this);
+	problem_screenshot.setBackground(new Color(108,168,108));
+	pane.add(problem_screenshot);*/
+	
+	
+	/*JLabel txt_smtp;
+	txt_smtp = new JLabel(messages.getString("SMTPaddress") + "?  ");
+	txt_smtp.setBackground(new Color(176,208,176));
+	pane.add(txt_smtp);
+
+	smtp_address = new JTextField();
+	smtp_address.setBackground(new Color(224,240,224));
+	pane.add(smtp_address);*/
+	
+
+	/*JLabel txt_email;
+	txt_email = new JLabel(messages.getString("Emailaddress") + "?  ");
+	txt_email.setBackground(new Color(176,208,176));
+	pane.add(txt_email);
+
+	email_address = new JTextField();
+	email_address.setBackground(new Color(224,240,224));
+	pane.add(email_address);*/
+	
+	JLabel empty;
+	empty = new JLabel ("   ");
+	empty.setBackground(bckcolor);
+	pane.add(empty);
+	JLabel empty2;
+	empty2 = new JLabel ("   ");
+	empty2.setBackground(bckcolor);
+	pane.add(empty2);
+	container.add(pane);
+
+	JPanel panely;
+	panely = new JPanel();
+	panely.setLayout(new GridLayout(0,3));
+	panely.setBackground(bckcolor);
+	panely.setBorder(new EmptyBorder(new Insets(10,10,10,10)));
+	
+	view_button = new JButton("Details . . .");
+	view_button.setActionCommand(messages.getString("Preview"));
+	view_button.addActionListener(this);
+	view_button.setToolTipText(messages.getString("ConformationPreview"));
+	view_button.setBackground(bckcolor);
+	panely.add(view_button); 
+
+	send_button = new JButton(messages.getString("Send"));
+	send_button.setActionCommand(messages.getString("Send"));
+	send_button.addActionListener(this);
+	send_button.setDefaultCapable(true);
+	send_button.setToolTipText(messages.getString("FeedbackSendButton"));
+	send_button.setBackground(bckcolor);
+	panely.add(send_button);
+	
+	notsend_button = new JButton("Cancel");
+	notsend_button.setActionCommand(messages.getString("NotSend"));
+	notsend_button.addActionListener(this);
+	notsend_button.setToolTipText(messages.getString("FeedbackNotSendButton"));
+	notsend_button.setBackground(bckcolor);
+	panely.add(notsend_button);
+	container.add(panely);
+
+	//Align the left edges of the components.
+	textArea.setAlignmentX(Component.LEFT_ALIGNMENT);
+	pict_scroll.setAlignmentX(Component.LEFT_ALIGNMENT);
+	pane.setAlignmentX(Component.LEFT_ALIGNMENT);
+	panely.setAlignmentX(Component.LEFT_ALIGNMENT);
+
+	String about;
+	about = messages.getString("FeedbackAboutText");
+	JTextArea about_txt;
+	about_txt = new JTextArea(about);
+	about_txt.setEditable(false);
+	about_txt.setLineWrap(true);
+	about_txt.setWrapStyleWord(true);
+	about_txt.setBackground(bckcolor);
+	about_txt.setBorder(new EmptyBorder(10,10,10,10));
+
+	String privacy;
+	privacy = messages.getString("FeedbackPrivacyText");
+	JTextArea privacy_txt;
+	privacy_txt = new JTextArea(privacy);
+	privacy_txt.setEditable(false);
+	privacy_txt.setLineWrap(true);
+	privacy_txt.setWrapStyleWord(true);
+	privacy_txt.setBackground(bckcolor);
+	privacy_txt.setBorder(new EmptyBorder(10,10,10,10));
+ 
+	JTabbedPane tab;
+	tab = new JTabbedPane();
+	tab.setBackground(bckcolor);
+	tab.addTab(messages.getString("Form"),container);
+	tab.addTab(messages.getString("About"),about_txt);
+	tab.addTab(messages.getString("Privacy"),privacy_txt);
+	tab.setBorder(new EmptyBorder(5,5,5,5));
+	
+	JPanel panelx;
+	panelx = new JPanel();
+	panelx.setLayout(new BoxLayout(panelx,BoxLayout.PAGE_AXIS));
+	panelx.setBackground(bckcolor);
+	panelx.setBorder(new EmptyBorder(new Insets(10,10,10,10)));
+	
+	wait_lbl = new JLabel(messages.getString("Pleasewait"));
+	wait_lbl.setBackground(bckcolor);
+	wait_lbl.setVisible(false);
+	panelx.add(wait_lbl);
+	
+	progressBar = new JProgressBar ();
+	progressBar.setBackground(bckcolor);
+	progressBar.setVisible(false);
+	panelx.add(progressBar);
+
+	JLabel emp2;
+	emp2 = new JLabel ("   ");
+	emp2.setBackground(bckcolor);
+	panelx.add(emp2);
+
+	wait_lbl.setAlignmentX(Component.CENTER_ALIGNMENT);
+	progressBar.setAlignmentX(Component.CENTER_ALIGNMENT);
+	emp2.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+	final String p1;
+	final String p2;
+	p1 = "Tab";
+	p2 = "ProgressBar";
+
+	final JPanel cards;
+	cards = new JPanel(new CardLayout());
+	cards.setBackground(bckcolor);
+	cards.add(tab,p1);
+	cards.add(panelx,p2);
+
+	window.add(cards);
+
+	
+	timer = new Timer(1000, new ActionListener()
+	    {
+		public void actionPerformed(ActionEvent evt)
+		{
+		    if (finish == true)
+			{
+			    if (sendThread != null)
+				{
+				    sendThread.interrupt();
+				    sendThread = null;
+				}
+
+			    if (prevThread != null)
+				{
+				    prevThread.interrupt();
+				    prevThread = null;
+				}
+			    
+			    Component glass_pane;
+			    glass_pane = frame.getGlassPane();
+			    
+			    glass_pane.setVisible(false);
+			    glass_pane.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+			    glass_pane.removeMouseListener(mouse_blocker_listener);
+			    
+			    wait_lbl.setVisible(false);
+			    progressBar.setIndeterminate(false);
+			    progressBar.setVisible(false);
+			    
+			    frame.setTitle(messages.getString("SendFeedbackForm"));
+			    
+			    CardLayout cl = (CardLayout)(cards.getLayout());
+			    cl.show(cards,p1);
+			    
+			    if (selected == true)
+				frame.dispose();
+
+			    timer.stop();
+			}
+		    else
+			{
+			    Component glass_pane;
+			    glass_pane = frame.getGlassPane();
+			    
+			    glass_pane.addMouseListener(mouse_blocker_listener);
+			    glass_pane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+			    glass_pane.setVisible(true);
+
+			    frame.setTitle("Please wait...");
+
+			    CardLayout cl = (CardLayout)(cards.getLayout());
+			    cl.show(cards,p2);
+
+			    wait_lbl.setVisible(true);
+			    progressBar.setIndeterminate(true);
+			    progressBar.setVisible(true);
+			}
+		}
+	    });
+    }
+
+    /**
+     * This method will set the finish variable values.
+     * When the sending files is finished, the sending application  will set the finish value to true.
+     * @param fin whether or not the send files is finished.
+     */
+    public static void setFinish (boolean fin)
+    {
+	finish = fin;
+    }
+
+    /**
+     * This is the class to represent the whole panel that hold the screenshot and the comments
+     * about the screenshot.
+     */
+    private class ThumbnailPic implements Serializable
+    {
+	/**
+	 * This is the panel that hold a thumbnail for a screenshot and a comments text area.
+	 */
+	private JPanel picpane;
+
+	/**
+	 * This hold the BufferedImages for the whole screen version of screenshot.
+	 */
+	private BufferedImage[] screenimages;
+
+	/**
+	 * This hold the BufferedImages for the window version only.
+	 */
+	private BufferedImage[] windowimages;
+
+	/**
+	 * This is the text area where user can enter their comments.
+	 */
+	private JTextArea problem_details;
+
+	/**
+	 * This is a flag to tell us which image user wants to send.Its defaults value is false.
+	 * If iswindow = true then it means user wants to send the window version only.
+	 * If iswindow = false then it means user wants to send the whole screen version.
+	 */
+	private boolean iswindow;
+
+	/**
+	 * This is the titles for the panel.
+	 * Usually this is the title of the window where user wants to do the screenshot.
+	 * If the title is more than 40 characters then we will trim it and add ... at the back of it.
+	 */
+	private String titles;
+
+	/**
+	 * This is the width of the image user wants to send.
+	 */
+	private String iw;
+
+	/**
+	 * This is the height of the image user wants to send.
+	 */
+	private String ih;
+
+	/**
+	 * This is the x-coordinate where the window located inside the whole screen image.
+	 */
+	private int xcoord;
+
+	/**
+	 * This is the y-coordinate where the window located inside the whole screen image.
+	 */
+	private int ycoord;
+
+	/**
+	 * This is the width of the window inside the whole screen image.
+	 */
+	private int width;
+
+	/**
+	 * This is the height of the window inside the whole screen image.
+	 */
+	private int height;
+
+	/**
+	 * This is the constructor that will setup the panel that contains
+	 * a thumbnail screenshot and a comments text area.
+	 * @param image the whole screen screenshot image.
+	 * @param text  the title for this pane.
+	 * @param x     the x-coordinate of the window inside the whole screen image.
+	 * @param y     the y-coordinate of the window inside the whole screen image.
+	 * @param w     the width of the window inside the whole screen image.
+	 * @param h     the height of the window inside the whole screen  image. 
+	 */
+	//public ThumbnailPic (BufferedImage screen,byte[] image,String text)
+	public ThumbnailPic (BufferedImage image,String text,int x,int y,int w,int h)
+	{
+	    xcoord = x;
+	    ycoord = y;
+	    width = w;
+	    height = h;
+	    iswindow = false;
+	    titles = text;
+	    screenimages = new BufferedImage[3];
+	    windowimages = new BufferedImage[3];
+	    //screenimages[0] = screen;
+	    screenimages[0] = image;
+	    screenimages[1] = null;
+	    screenimages[2] = null;
+	    windowimages[0] = null;
+	    windowimages[1] = null;
+	    windowimages[2] = null;
+	    addPanel(image);
+	}
+
+	/**
+	 * This method will setup the components inside the panel properly.
+	 * @param image the whole screen screenshot image.
+	 */
+	//public void addPanel (byte[] image)
+	public void addPanel (BufferedImage image)
+	{
+	    picpane = new JPanel();
+	    picpane.setLayout(new BorderLayout());
+	    
+	    final JButton picture;
+	    picture = new JButton();
+
+	    int w;
+	    int h;
+
+	    w = (int) (150/2);
+	    h = (int) (150/2);
+	    
+	    iw = "" + image.getWidth();
+	    ih = "" + image.getHeight();
+
+	    ImageIcon thumbnail;
+	    thumbnail = new ImageIcon(image.getScaledInstance(w,h,Image.SCALE_SMOOTH));
+
+	    picture.setIcon(thumbnail);
+	    picture.setText("Draw . . .");
+	    picture.setActionCommand("Scribble");
+	    picture.addActionListener(new ActionListener()
+		{
+		    public void actionPerformed (ActionEvent e)
+		    {
+			frame.addMouseListener(mouse_blocker_listener);
+			frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+			SelectPicture select;
+			select = new SelectPicture(screenimages,windowimages,iswindow,problem_details.getText(),messages);
+			frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+			frame.removeMouseListener(mouse_blocker_listener);	
+			select.setWindowBounds(xcoord,ycoord,width,height);
+			
+			iswindow = select.getIsWindow();
+
+			screenimages[0] = select.getImage3();
+			screenimages[1] = select.getImage();
+			screenimages[2] = select.getImage2();
+
+			if (iswindow == true)
+			    {
+				windowimages[0] = select.getWindowImage3();
+				windowimages[1] = select.getWindowImage();
+				windowimages[2] = select.getWindowImage2();
+			    }
+			else
+			    {
+				windowimages[0] = null;
+				windowimages[1] = null;
+				windowimages[2] = null;
+			    }
+			
+			problem_details.setText(select.getDetails());
+
+			int w,h;
+			w = (int) (150/2);
+			h = (int) (150/2);
+			
+			ImageIcon thumbnail;
+
+			if (iswindow == false)
+			    thumbnail = new ImageIcon(screenimages[1].getScaledInstance(w,h,Image.SCALE_SMOOTH));
+			else
+			    thumbnail = new ImageIcon(windowimages[1].getScaledInstance(w,h,Image.SCALE_SMOOTH));
+
+			picture.setIcon(thumbnail);
+			
+			if (select.getSendNow() == true)
+			    {
+				ActionEvent evt;
+				evt = new ActionEvent(send_button,ActionEvent.ACTION_PERFORMED,messages.getString("Send"));
+
+				frame.actionPerformed(evt);
+			    }
+		    }
+		});
+	    picture.setToolTipText("Click if you want to draw on it");
+	    picture.setMargin(new Insets(5,5,5,5));
+	    picture.setVerticalTextPosition(AbstractButton.BOTTOM);
+	    picture.setHorizontalTextPosition(AbstractButton.CENTER);
+	    picture.setBackground(new Color(176,208,176));
+	    picpane.add(picture,BorderLayout.LINE_START);
+	    
+	    JPanel txtPane;
+	    txtPane = new JPanel(new BorderLayout());
+	    txtPane.setBackground(new Color(176,208,176));
+	    txtPane.setBorder(new EmptyBorder(5,5,5,5));
+
+	    JLabel lbldesc = new JLabel("Comments :");
+	    lbldesc.setBackground(new Color(176,208,176));
+	    txtPane.add(lbldesc,BorderLayout.PAGE_START);
+
+	    problem_details = new JTextArea();
+	    problem_details.setWrapStyleWord(true);
+	    problem_details.setEditable(true);
+	    problem_details.setBackground(new Color(224,240,224));
+	   
+	    JScrollPane scroll;
+	    scroll = new JScrollPane(problem_details);
+	    scroll.setBackground(new Color(176,208,176));
+	    scroll.setPreferredSize(new Dimension(300,150));
+	    txtPane.add(scroll,BorderLayout.LINE_START);
+	   
+	    picpane.setSize(new Dimension(150,150));
+	    picpane.add(txtPane,BorderLayout.CENTER);
+	}
+
+	/**
+	 * This method will get the width of the image user wants to send.
+	 * @return the width of the image.
+	 */
+	public String getWidth()
+	{
+	    if (iswindow == false)
+		return "" + screenimages[0].getWidth();
+	    else
+		{
+		    return "" + windowimages[0].getWidth();
+		}
+	}
+
+	/**
+	 * This method will get the height of the image user wants to send.
+	 * @return the height of the image.
+	 */
+	public String getHeight()
+	{
+	    if (iswindow == false)
+		return "" + screenimages[0].getHeight();
+	    else
+		{
+		    return "" + windowimages[0].getHeight();
+		}  
+	}
+
+	/**
+	 * This method will get the titles of this panel.
+	 * @return the panel's title.
+	 */
+	public String getTitles()
+	{
+	    return titles;
+	}
+
+	/**
+	 * This method will get user comments inside the text area.
+	 * @return the user's comments.
+	 */
+	public String getProblemDetails ()
+	{
+	    String txt;
+	    txt = problem_details.getText();
+	    
+	    if (txt == null)
+		return " ";
+	    else
+		return txt;
+	}
+
+	/**
+	 * This method will setting up the text inside the text area.
+	 * @param comments the text set to the text area.
+	 */
+	public void setComments (String comments)
+	{
+	    problem_details.setText(comments);
+	}
+
+	/**
+	 * This method will get the image that user wants to send.
+	 * @return image going to be send.
+	 */
+	public BufferedImage[] getImages ()
+	{
+	    if (iswindow == false)
+		return screenimages;
+	    else
+		return windowimages;
+	}
+
+	/**
+	 * This method will get the non-scribble lines image that user wants to send.
+	 * @return the string representation of the non-scribble lines image.
+	 */
+	public String getScreenImage ()
+	{
+	    if (iswindow == false)
+		return convert(screenimages[0]);
+	    else
+		return convert(windowimages[1]);
+	}
+
+	/**
+	 * This method will get the scribble lines image that user wants to send.
+	 * @return the string representation of the scribble lines image.
+	 */
+	public String getScreenAndLineImage ()
+	{
+	    if (iswindow == false)
+		{
+		    if (screenimages[1]!= null)
+			return convert(screenimages[1]);
+		    else
+			return convert(screenimages[0]);
+		}
+	    else
+		{
+		    if (windowimages[1]!= null)
+			return convert(windowimages[1]);
+		    else
+			return convert(windowimages[0]);
+		}
+	}
+
+	/**
+	 * This method will get only scribble lines image that user wants to send.
+	 * @return the string representation of the only scribble lines image.
+	 */
+	public String getLineForScreenImage ()
+	{
+	    if (iswindow == false)
+		{
+		    if (screenimages[2] != null)
+			return convert(screenimages[2]);
+		    else
+			return "";
+		}
+	    else
+		{
+		    if (windowimages[2] != null)
+			return convert(windowimages[2]);
+		    else
+			return "";
+		}
+	}
+
+	/**
+	 * This method will get the panel that hold a thumbnail and a text area.
+	 * @return panel that represent the thumbnail and the text area.
+	 */
+	public JPanel getPanel()
+	{
+	    return picpane;
+	}
+    }
+
+    /**
+     * This method will setting up the comments to be displayed inside the latest added panel.
+     * So if the window where user wants to take the screenshot at the moment is a modal window
+     * then it will setting the comments to ask user to close the window before they can enter
+     * their comments there.
+     * @param modal the modality of the window where user wants to take the screenshot.
+     */
+    public void setComment (boolean modal)
+    {
+	if (paneArray.size() == 0)
+	    System.out.println("There is no panel here!");
+	else
+	    {
+		JPanel pane;
+		pane = (JPanel) paneArray.get((row - 2));
+		ThumbnailPic obj;
+		obj = (ThumbnailPic) picAndPane.get(pane);
+		String text;
+		if (modal == true)
+		    text = "Please close '" + obj.getTitles() + "' window \nbefore you can enter comments here.";
+		else
+		    text = " ";
+		obj.setComments(text);
+	    }
+    }
+
+    /**
+     * This method will add a panel that contains the thumbnail button and the text area.
+     * @param title the window's title.
+     * @param image the whole screen image.
+     * @param x     the window's x-coordinate in the image.
+     * @param y     the window's y-coordinate in the image.
+     * @param width the window's width in the image.
+     * @param height the window's height in the image.
+     */
+    //public void addScreenPanel (String title,BufferedImage screen,byte[] image)
+    public void addScreenPanel (String title,BufferedImage image,int x,int y,int width,int height)
+    {
+	final JPanel pane;
+	pane = new JPanel();
+	pane.setLayout(new BorderLayout());
+	pane.setBackground(new Color(176,208,176));
+
+	Border loweredetched;
+	loweredetched = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
+
+	String ttl;
+	if (title.length() > 41)
+	    ttl = title.substring(0,40) + "  . . . ";
+	else
+	    ttl = title;
+
+	TitledBorder border;
+	border = BorderFactory.createTitledBorder(loweredetched, title);
+	border.setTitleJustification(TitledBorder.LEFT);
+	
+	pane.setBorder(BorderFactory.createCompoundBorder(new EmptyBorder(5,5,5,5),border));
+	
+	ThumbnailPic pic;
+	//pic = new ThumbnailPic(screen,image,title);
+	pic = new ThumbnailPic(image,title,x,y,width,height);
+	picAndPane.put(pane,pic);
+	pane.add(pic.getPanel(),BorderLayout.LINE_START);
+
+	remove.setVisible(true);
+	picture_scroll.add(pane);
+	paneArray.add(pane);
+	row++;
+	picture_scroll.setSize(picture_scroll.getPreferredSize());
+	picture_scroll.revalidate();
+	picture_scroll.repaint();
+	tempPane.setSize(tempPane.getPreferredSize());
+	tempPane.revalidate();
+	tempPane.repaint();
+    }
+
+    /**
+     * This method will generate the unique code that will be used as the 
+     * reference number of the feedback that user are about to send.
+     * @return the unique code.
+     */
+    public String getPrevData ()
+    {
+	try
+	    {
+		UID id = new UID();
+		code =  "" + InetAddress.getLocalHost().hashCode() + id.hashCode();
+	    }
+	catch (UnknownHostException exp) {}
+	return code;
+    }
+
+    /**
+     * This method allows another class to get the unique code that can be used as 
+     * the reference number of the feedback that user are about to send.
+     * This method should be called only if 
+     * getPrevData() method already been called before.Otherwise it will return null. 
+     * @return the unique code
+     */
+    public static String getCode()
+    {
+	return code;
+    }
+
+    /**
+     * This method will encode BufferedImage into their String representation using
+     * Base64 encoder.
+     * (Precondition: (image != null))
+     * @param image is the image that we want to encode to String.
+     */
+    public String convert (BufferedImage image)
+    {
+	String txt;
+	txt = null;
+
+	try
+	    {
+		ByteArrayOutputStream stream = new ByteArrayOutputStream();
+		ImageIO.write(image,"jpeg",stream);
+		byte[] bytes = stream.toByteArray();
+
+		txt = Base64.encodeBytes(bytes);
+		
+	    }
+	catch(IOException ex) {}
+
+	return txt;
+    }
+
+    /**
+     * This method is to make sure that there is no thread running at the moment.
+     */
+    private void ensureEventThread()
+    {
+	if(SwingUtilities.isEventDispatchThread())
+	    {
+		return;
+	    }
+	throw new RuntimeException(messages.getString("file"));
+    }
+
+    /**
+     * This method will create all 6 xml files, jarred them into one file, deletes all xml files and
+     * sending it.
+     * The xml files for:
+     * <br> 1.The history & information of all the actions done and windows opened by the application
+     *        after user choose to start the sequence of sending feedback.
+     * <br> 2.The history of all the commands (actions) done by the user before choosing
+     *        after start the sequence of sending feedback.
+     * <br> 3.The informations we get from the feedback interface form period.
+     * <br> will be getting from vector and the temp_feedbackhist.log file.
+     * (Precondition: (sx != null) && (vector != null) && (err_array != null))
+     * @param sx the xml parser.
+     * @param vector the vector that hold the history and information.
+     * @param err_array the arrays of information we take from the feedback interface period.
+     * @param imgFile   the arrays of information we take from the panels inside feedback interface form.
+     */
+    private void sendState (SaveToXML sx,Vector vector,String[] err_array,String[] imgFile)
+    {
+	String dirname;
+	dirname = "xmlfeedback/";
+	
+	File dir = new File("xmlfeedback");
+	if (dir.isDirectory() == false)
+	    dir.mkdir();
+
+	sx.saveFeedback(err_array,imgFile);
+	
+	sx.open(dirname + "feedbackcontent" + FeedbackInterface.getCode() + ".xml",
+		"HISTORY");
+	SaveToXML sx2;
+	sx2 = new SaveToXML(messages);
+	sx2.open(dirname + "feedbackcommand" + FeedbackInterface.getCode() + ".xml",
+		 "COMMANDS");
+	
+	for (int i = 0 ; i < vector.size() ; i++)
+	    {
+		History log;
+		log = (History) vector.get(i);
+		log.sendXML(sx);
+		log.sendXMLComm(sx2);
+	    }
+	
+	Vector stack;
+	stack = getPrev_log();
+	if (stack != null)
+	    {
+		for (int i = 0 ; i < stack.size() ; i++)
+		    {
+			History log;
+			log = (History) stack.get(i);
+			log.sendXML(sx);
+			log.sendXMLComm(sx2);
+		    }
+		stack.removeAllElements();
+		System.gc();
+		stack = null;
+	    }
+	
+	sx2.close("COMMANDS");
+	sx.close("HISTORY");
+	
+	getHistPrev_log(sx,sx2);
+	
+	ZipFile zip;
+	zip = new ZipFile();
+	zip.sendZipXMLFile();
+
+	File f;
+	f = new File (dirname + "feedback" + FeedbackInterface.getCode() + ".xml");
+	f.delete();
+	f = new File (dirname + "feedbackcontent" + FeedbackInterface.getCode() + ".xml");
+	f.delete();
+	f = new File (dirname + "feedbackcommand" + FeedbackInterface.getCode() + ".xml");
+	f.delete();
+	/*f = new File (dirname + "content" + FeedbackInterface.getCode() + ".xml");
+	  f.delete();*/
+	f = new File (dirname + "command" + FeedbackInterface.getCode() + ".xml");
+	f.delete();
+	
+	String[] args = new String[5];
+	args[0] = "vl6@cs.waikato.ac.nz";
+	args[1] = dirname + "Jar" + FeedbackInterface.getCode() + "File.jar";
+	args[4] = "lib/parser.jar";
+	args[2] = err_array[19];
+	args[3] = err_array[20];
+	SendHTTP sm = new SendHTTP();
+	//SendMail sm = new SendMail();
+	sm.sendMail(args,messages,FeedbackInterface.getCode());
+    }
+	
+    /**
+     * This method will create the 2 xml files.
+     * The xml files are:
+     * <br> 1.The history & information of all the actions done and windows opened by the application
+     *         before user choose to start the sequence of sending feedback.
+     * <br> 2.The history of all the commands (actions) done by the user before choosing
+     *         to start the sequence of sending feedback.
+     * <br> The information will be getting from history.log file and the temp_history.log file.
+     * (Precondition: (sx != null) && (sx2 != null))
+     * @param sx the xml parser for the history xml file.
+     * @param sx2 the xml parser for the command xml file.
+     */
+    private void getHistPrev_log(SaveToXML sx,SaveToXML sx2)
+    {
+	Vector stack = null;
+	try
+	    {
+		File f = new File("history.log");
+		if (f.exists() == true)
+		    {
+			FileInputStream fis = new FileInputStream(f);
+			ObjectInputStream ois = new ObjectInputStream(fis);
+			
+			stack = (Vector) ois.readObject();
+			
+			String dirname;
+			dirname = "xmlfeedback/";
+
+			/*sx.open(dirname + "content" + FeedbackInterface.getCode() + ".xml",
+			  "HISTORY");*/
+			sx2.open(dirname + "command" + FeedbackInterface.getCode() + ".xml",
+				 "COMMANDS");
+			
+			if (stack != null)
+			    {
+				for (int i = 0 ; i < stack.size() ; i++)
+				    {
+					History log;
+					log = (History) stack.get(i);
+				        //log.sendXML(sx);
+					log.sendXMLComm(sx2);
+				    }
+				stack.removeAllElements();
+				System.gc();
+				stack = null;
+			    }
+			
+			stack = (Vector) ois.readObject();
+			
+			if (stack != null)
+			    {
+				for (int i = 0 ; i < stack.size() ; i++)
+				    {
+					History log;
+					log = (History) stack.get(i);
+				        //log.sendXML(sx);
+					log.sendXMLComm(sx2);
+				    }
+				stack.removeAllElements();
+				System.gc();
+				stack = null;
+			    }
+			
+			sx2.close("COMMANDS");
+			//sx.close("HISTORY");
+			
+			ois.close();
+		    }
+	    }
+	catch (IOException exp) {exp.printStackTrace();}
+	catch (ClassNotFoundException exp2)
+	    {
+		System.out.println("class exp");}
+    }
+
+    /**
+     * This method will get the Vector stored in temp_feedbackhist.log file.
+     * @return the vector stored in temp_feedbackhist.log file.
+     */
+    public Vector getPrev_log()
+    {
+	Vector stack = null;
+	try
+	    {
+		File f = new File("temp_feedbackhist.log");
+		if (f.exists() == true)
+		    {
+			FileInputStream fis = new FileInputStream(f);
+			ObjectInputStream ois = new ObjectInputStream(fis);
+			stack = (Vector) ois.readObject();
+			ois.close();
+			return stack;
+		    }
+		else
+		    stack = null;
+	    }
+	catch (IOException exp) {exp.printStackTrace();}
+	catch (ClassNotFoundException exp2)
+	    {
+		System.out.println("class exp");}
+	
+	return stack;
+    }
+
+    /**
+     * This is the thread that will start when user click send button and it will
+     * make 6 xml files,jarred them together into 1 jar file, deletes the 6 xml files and send it.
+     * @param vector the vector stored the current actions history.
+     * @param err_array the array that stored all the information took during feedback interface period.
+     * @param imgFile the array of that stored all the information from all the panels inside feedback interface form.
+     */
+    public void sendMethod (final Vector vector,final String err_array[], final String imgFile[])
+    {
+	ensureEventThread();
+	Runnable sendRun;
+	sendRun = new Runnable()
+	    {
+		public void run ()
+		{
+		    finish = false;
+		    selected = true;
+		    SaveToXML sx;
+		    sx = new SaveToXML(messages);
+		    sendState(sx,vector,err_array,imgFile);
+		    finish = true;
+		}
+	    };
+	sendThread = new Thread(sendRun);
+	sendThread.start();
+    }
+
+    /**
+     * This method will called the window that will display the preview of all
+     * the file going to be send.
+     * @param vector the vector stored the current actions history.
+     * @param err_array the array that stored all the information took during feedback interface period.
+     * @param imgFile the array of that stored all the information from all the panels inside feedback interface form.
+     */
+    public void viewMethod (final Vector vector,final String err_array[], final String imgFile[])
+    {
+	ensureEventThread();
+	Runnable prevRun;
+	prevRun = new Runnable()
+	    {
+		public void run ()
+		{
+		    finish = false;
+		    selected = false;
+		    ReportDetails rd;
+		    rd = new ReportDetails(vector,err_array,imgFile,messages,true);
+		    finish = true;
+		}
+	    };
+	
+	prevThread = new Thread(prevRun);
+	prevThread.start();
+    }
+
+    /**
+     * This method will save a BufferedImage to a jpeg file with the specified filename.
+     * This method is a thread that will caused the thread save to be started and stop
+     * if the saving process is finished.
+     * (Precondition: (I != null))
+     * @param I is the BufferedImage that we want to save.
+     * @param picScreen name of the jpeg file where we want to store the BufferedImage
+     */
+    public void saveGraph(final BufferedImage I,final String picScreen)
+    {
+	ensureEventThread();
+	Runnable saveRun;
+	saveRun = new Runnable ()
+	    {
+		public void run()
+		{
+		    try 
+			{
+			    File file;
+			    file = new File(picScreen);
+			    FileOutputStream out;
+			    out = new FileOutputStream(file);
+			    
+			    JPEGImageEncoder encoder;
+			    encoder = JPEGCodec.createJPEGEncoder(out);
+			    JPEGEncodeParam param;
+			    param = encoder.getDefaultJPEGEncodeParam(I);
+			    param.setQuality(1.0f, false);
+			    encoder.setJPEGEncodeParam(param);
+			    encoder.encode(I);
+			    out.close();
+			    save = null;
+			} 
+		    catch (Exception ex) {}
+		}
+	    };
+	
+	save = new Thread(saveRun);
+	save.start();
+    }
+
+    /**
+     * This method will get all the informations from the all the panels inside the feedback interface form.
+     * @return the arrays of information from all the panels.
+     */
+    public String[] getimgFile()
+    {
+	String[] imgFile;	
+	imgFile = null;
+
+	/*String answer;
+	  answer = (String) problem_screenshot.getSelectedItem();
+	  if(answer == messages.getString("Yes"))
+	  {*/
+	
+	if (paneArray.size() > 0)
+	    {
+		imgFile = new String[(paneArray.size() * 10)];
+		
+		int step;
+		for (step = 0 ; step < (paneArray.size()*10) ; step=step+10)
+		    {
+			JPanel pane;
+			ThumbnailPic obj;
+			pane = (JPanel) paneArray.get((step/10));
+			obj = (ThumbnailPic) picAndPane.get(pane);
+			
+			//obj.setSize();
+			
+			String title;
+			title = obj.getTitles();
+			
+			imgFile[step+0] = title;
+			imgFile[step+1] = obj.getScreenImage();
+			title = "Window" + pane.hashCode() + "File";
+			imgFile[step+2] = messages.getString("screen")+title+step+".jpg";
+			imgFile[step+3] = obj.getScreenAndLineImage();
+			imgFile[step+4] = messages.getString("ErrorLineAnd")+imgFile[step+2];
+			imgFile[step+5] = obj.getLineForScreenImage();
+			imgFile[step+6] = messages.getString("ErrorLineFor")+imgFile[step+2];
+			imgFile[step+7] = obj.getWidth();
+			imgFile[step+8] = obj.getHeight();
+			imgFile[step+9] = obj.getProblemDetails();
+		    }
+	    }
+		
+	return imgFile;
+    }
+
+    /**
+     * This method will get all the informations taken during feedback interface period, such as os version.
+     * @return then arrays of informations.
+     */
+    public String[] geterr_array()
+    {
+	String[] err_array;
+	err_array = null;
+
+	String os_name;
+	os_name = System.getProperty("os.name") + " " + System.getProperty("os.version") 
+	    + " " + System.getProperty("os.arch");
+	
+	Date problem_date;
+	String err_date,java_info,screen_res;
+	problem_date = new Date();
+	err_date = problem_date.toString();
+	java_info = System.getProperty("java.vendor")+ " " + System.getProperty("java.class.version");
+	Dimension dim;
+	dim = Toolkit.getDefaultToolkit().getScreenSize();
+	screen_res = "" + dim.width + "x" + dim.height;
+	
+	try
+	    {
+		err_array = new String[24];
+
+		err_array[0] = code;
+		err_array[1] = frameName;
+		err_array[2] = "";
+		err_array[3] = (String) problem_type.getSelectedItem();
+		err_array[4] = (String) problem_urgency.getSelectedItem();
+		err_array[5] = System.getProperty("user.name");
+		err_array[6] = System.getProperty("user.home");
+		err_array[7] = System.getProperty("user.dir");
+		err_array[8] = curr_date.toString();
+		err_array[9] = err_date;
+		err_array[10] = os_name;
+		err_array[11] = java_info;
+		err_array[12] = "" + Locale.getDefault();
+		err_array[13] = Gatherer.PROGRAM_NAME + " " + Gatherer.PROGRAM_VERSION; 
+		err_array[14] = InetAddress.getLocalHost().getHostName();
+		err_array[15] = InetAddress.getLocalHost().getHostAddress();
+		err_array[16] = screen_res;
+		err_array[17] = "";
+		
+		/*String test_txt;
+		  test_txt = smtp_address.getText();
+		  if ((test_txt == null)||(test_txt.length() < 5))*/
+		err_array[19] = "mail.waikato.ac.nz";
+		/*else
+		  err_array[19] = test_txt;
+		  
+		  test_txt = email_address.getText();
+		  if ((test_txt == null)||(test_txt.length() < 5))*/
+		err_array[20] = "vl6@cs.waikato.ac.nz";
+		//else
+		//err_array[20] = test_txt;
+		
+		Runtime run;
+		run = Runtime.getRuntime();
+		err_array[21] = formatFileSize(run.totalMemory());
+		err_array[22] = formatFileSize(run.maxMemory());
+		err_array[23] = formatFileSize(run.freeMemory());
+	    }
+	catch(UnknownHostException exp) {}
+
+	return err_array;
+    }
+
+    /**
+     * This method will format the file size given into more elegant form,e.g. 2KB
+     * @param length the file size.
+     * @return the more elegant string representations of the file size.
+     */
+    public String formatFileSize(long length) 
+    {
+	String BYTE_SUFFIX;
+	BYTE_SUFFIX = " B";
+	long GIGABYTE;
+	GIGABYTE = 1024000000l;
+	String GIGABYTE_SUFFIX;
+	GIGABYTE_SUFFIX = " GB";
+	long KILOBYTE;
+	KILOBYTE = 1024l;
+	String KILOBYTE_SUFFIX;
+	KILOBYTE_SUFFIX = " KB";
+	long MEGABYTE;
+	MEGABYTE = 1024000l;
+	String MEGABYTE_SUFFIX;
+	MEGABYTE_SUFFIX = " MB";
+
+	StringBuffer result;
+	result = new StringBuffer("");
+	float number;
+	number = 0f;
+	String suffix;
+	suffix = null;
+	
+	if(length >= GIGABYTE) 
+	    {
+		number = (float) length / (float) GIGABYTE;
+		suffix = GIGABYTE_SUFFIX;
+	    }
+	else if(length >= MEGABYTE) 
+	    {
+		number = (float) length / (float) MEGABYTE;
+		suffix = MEGABYTE_SUFFIX;
+	    }
+	else if(length >= KILOBYTE) 
+	    {
+		number = (float) length / (float) KILOBYTE;
+		suffix = KILOBYTE_SUFFIX;
+	    }
+	else 
+	    {
+		return length + BYTE_SUFFIX;
+	    }
+	
+	String number_str;
+	number_str = Float.toString(number);
+	char number_char[] = number_str.toCharArray();
+	int pos,i;
+	pos = 0;
+	
+	while(number_char != null && pos < number_char.length && number_char[pos] != '.')
+	    {
+		result.append(number_char[pos]);
+		pos++;
+	    }
+
+	if(pos < number_char.length) 
+	    {
+		result.append(number_char[pos]);
+		pos++;
+		
+		for(i = 0; i < 2 && pos < number_char.length; i++, pos++)
+		    result.append(number_char[pos]);
+	   
+		while(pos < number_char.length && number_char[pos] != 'E') 
+		    pos++;
+	   
+		while(pos < number_char.length) 
+		    {
+			result.append(number_char[pos]);
+			pos++;
+		    }
+	    }
+	
+	result.append(suffix);
+	
+	return result.toString();
+    }
+
+    /**
+     * This method will decide what action should be done if the user entered a button in
+     * the Feedback form.
+     * <br>If user click cancel button then all the information taken in this form will be deleted
+     * and user will be quitted from the Reporting Feedback sequence.
+     * <br>If user click the send button then all the information taken will be stored in array which
+     * then will be saved into xml files and sent when user confirm to send all the files.
+     * <br>If user click the details button then they can view all the xml files that are going to be send.
+     * @param e the button that user clicked
+     */
+    public void actionPerformed (ActionEvent e)
+    {
+	getPrevData();
+
+	if(messages.getString("Send").equals(e.getActionCommand()))
+	    {
+		String[] imgFile;
+		String[] err_array;
+
+		imgFile = getimgFile();
+		err_array = geterr_array();
+
+		timer.start();
+		
+		sendMethod(dialog.getVector(),err_array,imgFile);
+	    }
+
+	if(messages.getString("Preview").equals(e.getActionCommand()))
+	    {
+		String[] imgFile;
+		String[] err_array;
+
+		imgFile = getimgFile();
+		err_array = geterr_array();
+
+		timer.start();
+		
+		viewMethod(dialog.getVector(),err_array,imgFile); 
+	    }
+
+	if(messages.getString("NotSend").equals(e.getActionCommand()))
+	    {
+		dispose();
+	    }
+    }
+}
+	
+	
+
+	
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/Graphs.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/Graphs.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/Graphs.java	(revision 13928)
@@ -0,0 +1,360 @@
+package org.greenstone.gatherer.feedback;
+
+import java.awt.image.*;
+import java.awt.geom.*;
+import java.awt.geom.Line2D.*;
+import java.awt.geom.Line2D.Double;
+import java.io.*;
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * This is the class that will allow user to draw a same line to 2 different BufferedImage
+ * at the same time.
+ * The first BufferedImage is BufferedImage with some Image as the based and then
+ * we draw a line on it, and the second BufferedImage is just a transparent Image and then we 
+ * draw a line on it. The line drawn in first BufferedImage is exactly the same with the line
+ * drawn in second BufferedImage.The Image drawn in the first bufferedimage is the
+ * screen shot image of the whole screen.
+ * @author Veronica Liesaputra
+ */
+public class Graphs
+{ 
+    /**
+     * This is the first buffered image.
+     * It will drawn with an image first to be its based, and a line  
+     * that are identical to line drawn the second BufferedImage, will be drawn on it.
+     */
+    private BufferedImage I = null;
+
+    /**
+     * This is the second buffered image.
+     * Its a transaparent buffered image and a line that are indetical to line
+     * drawn in the first BufferedImage, will be drawn on it. 
+     */
+    private BufferedImage I2;
+
+    /**
+     * This is the Graphics for the first BufferedImage.
+     * This will allow user to draw a line and an image on the first buffered image.
+     */
+    private Graphics2D G;
+    
+    /**
+     * This is the Graphics for the second BufferedImage.
+     * This will allow user to draw a line on the second buffered image.
+     */
+    private Graphics2D G2;
+
+    /**
+     * This is the arrays of the 3 BufferedImage.
+     */
+    private BufferedImage[] screen;
+
+    /**
+     * This is the graphics for screen[0] BufferedImage.
+     * This will allow user to draw something on the screen[0] image.
+     */
+    private Graphics2D G3;
+  
+    /**
+     * This is the width of the image.
+     */
+    private double imwidth;
+
+    /**
+     * This is the height of the image.
+     */
+    private double imheight;
+
+    /**
+     * This is the constructor that will initialised the BufferedImage and
+     * its Graphics.
+     * (Precondition: (sh != null))
+     * @param sh is the images.
+     */
+    public Graphs (BufferedImage[] sh)
+    {
+	screen = sh;
+
+	if (screen[0] != null)
+	    { 
+		imwidth = screen[0].getWidth();
+		imheight = screen[0].getHeight();
+
+
+		if((screen[1] == null)&& (screen[2] == null))
+		    {
+			I = new BufferedImage(screen[0].getWidth(),screen[0].getHeight(),
+					      BufferedImage.TYPE_INT_RGB);
+			I2 = new BufferedImage(I.getWidth(),I.getHeight(),
+					       BufferedImage.TYPE_INT_ARGB);
+		    }
+		else
+		    {
+			I = screen[1];
+			I2 = screen[2];
+		    }
+		start();
+	    }
+	else
+	    System.out.println("weird");
+    }
+
+    /**
+     * This method will make sure that everything is null-ed and dispose properly.
+     */
+    public void flush()
+    {
+	G.dispose();
+	G = null;
+	G3.dispose();
+	G3 = null;
+	G2.dispose();
+	G2 = null;
+
+	int i;
+	for ( i = 0 ; i < 3; i++)
+	    {
+		if (screen[i] != null)
+		    {
+			screen[i].flush();
+			screen[i] = null;
+		    }
+	    }
+
+	I.flush();
+	I = null;
+	I2.flush();
+	I2 = null;
+	System.gc();
+    }
+
+    /**
+     * This method will cleared the scribble lines in the images.
+     */
+    public void reset()
+    {
+	I.flush();
+	I = null;
+	System.gc();
+	I2.flush();
+	I2 = null;
+	G.dispose();
+	System.gc();
+	G2.dispose();
+	G = null;
+	G2 = null;
+	System.gc();
+
+	I = new BufferedImage(screen[0].getWidth(),
+			      screen[0].getHeight(),
+			      BufferedImage.TYPE_INT_RGB);
+	I2 = new BufferedImage(I.getWidth(),I.getHeight(),
+			       BufferedImage.TYPE_INT_ARGB);
+
+	screen[1] = null;
+	screen[2] = null;
+
+	start();
+    }
+    /**
+     * This method will setup the 3 Graphics for the 3 BufferedImage.
+     * Here the graphics for the bufferedimage will be created and the appropriate image
+     * will be drawn to the first bufferedimage.  
+     */
+    public void start ()
+    {
+	G3 = screen[0].createGraphics();
+	G3.drawImage((Image) screen[0],0,0,new JLabel());
+
+	G = I.createGraphics();
+	if (screen[1] == null)
+	    G.drawImage((Image) screen[0],0,0,new JLabel());
+	else
+	    G.drawImage ((Image) screen[1],0,0,new JLabel());
+	G2 = I2.createGraphics();
+    }
+ 
+    /**
+     * This method will draw a red line on both BufferedImage from the source point
+     * to the destination point.
+     * @param x1 is the x-coordinate of the source point.
+     * @param y1 is the y-coordinate of the source point.
+     * @param x2 is the x-coordinate of the destination point.
+     * @param y2 is the y-coordinate of the destination point. 
+     */
+    public void drawLines(int x1,int y1,int x2,int y2)
+    {
+	G2.setColor(Color.red);
+	G.setColor(Color.red);
+
+	G.setStroke(new BasicStroke(2.5f));
+	G2.setStroke(new BasicStroke(2.5f));
+
+	G2.drawLine(x1,y1,x2,y2);
+	G.drawLine(x1,y1,x2,y2);
+    }
+
+    
+    /**
+     * This method will draw a white line on all 3 BufferedImage from the source point
+     * to the destination point.
+     * @param x1 is the x-coordinate of the source point.
+     * @param y1 is the y-coordinate of the source point.
+     * @param x2 is the x-coordinate of the destination point.
+     * @param y2 is the y-coordinate of the destination point. 
+     */
+    public void eraseLines(int x1,int y1,int x2,int y2)
+    {
+	G3.setColor(Color.white);
+	G2.setColor(Color.white);
+	G.setColor(Color.white);
+
+	G.setStroke(new BasicStroke(25.5f));
+	G2.setStroke(new BasicStroke(25.5f));
+	G3.setStroke(new BasicStroke(25.5f));
+	
+	G3.drawLine(x1,y1,x2,y2);
+	G2.drawLine(x1,y1,x2,y2);
+	G.drawLine(x1,y1,x2,y2);
+    }
+
+    /**
+     * This method will get the first BufferedImage.
+     * This is the BufferedImage where it will already be drawn with the
+     * screen shot image and the lines.
+     * @return the first BufferedImage.
+     */
+    public BufferedImage getImage ()
+    {
+	return I;
+    }
+
+    /**
+     * This method will get the second BufferedImage.
+     * This is the BufferedImage where its base is transparent and it will
+     * already be drawn with the lines.
+     * @return the second BufferedImage.
+     */
+    public BufferedImage getImage2()
+    {
+	return I2;
+    }
+
+    /**
+     * This method will get the image without scribble lines only the white lines.
+     * @return the image without scribble lines.
+     */
+    public BufferedImage getScreenImage()
+    {
+	return screen[0];
+    }
+
+    /**
+     * This method will get the window out of the whole screen image.
+     * @param xcoord the xcoordinate of the window in the image.
+     * @param ycoord the ycoordinate of the window in the image.
+     * @param width  the width of the window in the image.
+     * @param height the height of the window in the image.
+     * @return the BufferedImage of the window only from the 3 buffered image.
+     */
+    public BufferedImage[] getWindowVersion(int xcoord,int ycoord,int width,int height)
+    {
+	BufferedImage[] window;
+	window = new BufferedImage[3];
+
+	Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
+	
+	if (xcoord < 0 ) 
+	    xcoord = 0;
+	if (ycoord < 0)
+	    ycoord = 0;
+
+	if (xcoord >= imwidth)
+	    xcoord = (int)(imwidth - 1);
+	if (ycoord >= imheight)
+	    ycoord = (int)(imheight - 1);
+	if ((xcoord + width) > imwidth)
+	    width = (int)(imwidth - xcoord);
+	if ((ycoord + height) > imheight)
+	    height = (int)(imheight - ycoord);
+
+	if (width <= 0)
+	    width = 1;
+	if (height <= 0)
+	    height = 1;
+
+	window[0] = getClipVersion(screen[0],xcoord,ycoord,width,height);
+	
+	window[1] = getClipVersion(I,xcoord,ycoord,width,height);
+	
+	window[2] = getClipVersion(I2,xcoord,ycoord,width,height);
+	
+	return window;
+    }
+    
+    /**
+     * This method will return the subimage of the big buffered image.
+     * @param tag the original buffered image.
+     * @param x   the x location of subimage.
+     * @param y   the y location of subimage.
+     * @param w   the width of the subimage.
+     * @param h   the height of the subimage.
+     * @return    the subimage.
+     */
+    public BufferedImage getClipVersion (BufferedImage tag,int x, int y, int w, int h) 
+    {
+	BufferedImage sub;
+	sub = tag.getSubimage(x,y,w,h);
+	
+	return sub;
+    }
+
+    /**
+     * This method will return the screen image version of the give buffered image.
+     * @param sh the buffered image that we going to draw in the screen image version.
+     * @param xcoord   the x location of subimage.
+     * @param ycoord   the y location of subimage.
+     * @param w   the width of the subimage.
+     * @param h   the height of the subimage.
+     */
+    public void setScreenVersion(BufferedImage[] sh,int xcoord,int ycoord,int w, int h)
+    {
+	if (xcoord < 0 ) 
+	    xcoord = 0;
+	if (ycoord < 0)
+	    ycoord = 0;
+
+	if (xcoord >= imwidth)
+	    xcoord = (int) (imwidth - 1);
+	if (ycoord >= imheight)
+	    ycoord = (int) (imheight - 1);
+	if ((xcoord + w) > imwidth)
+	    w = (int) (imwidth - xcoord);
+	if ((ycoord + h) > imheight)
+	    h = (int) (imheight - ycoord);
+
+	if (w <= 0)
+	    w = 1;
+	if (h <= 0)
+	    h = 1;
+       
+	G3.drawImage(sh[0], xcoord,ycoord,new JLabel());
+
+        
+        G.drawImage(sh[1], xcoord,ycoord,new JLabel());
+	
+	
+	G2.drawImage(sh[2], xcoord,ycoord,new JLabel());
+    }
+}
+    
+
+
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/History.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/History.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/History.java	(revision 13928)
@@ -0,0 +1,284 @@
+package org.greenstone.gatherer.feedback;
+
+import java.util.*;
+import java.awt.image.*;
+import java.io.*;
+import javax.imageio.*;
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * This class is one record of the action user did to any of the component
+ * inside the window that the application open that is recorded by the 
+ * special listener class.
+ * An instance of this class will hold all the information about the action
+ * user did at that moment,all information about all the components inside the
+ * window where the action occured and all information about all the components
+ * inside all the windows that were opened when the action occured.
+ * @author Veronica Liesaputra
+ */
+public class History implements Serializable
+{
+    /**
+     * This is the date of when the action is done by the user.
+     */
+    private String date;
+    
+    /**
+     * This is the command that user did.
+     */
+    private String command;
+    
+    /**
+     * This is the title of the window where the action occured.
+     */
+    private String title;
+
+    /**
+     * This hold all information about all the components inside the
+     * window where the action occured and all information about all the components
+     * inside all the windows that were open when the action occured.
+     */
+    private ArrayList component;
+
+    /**
+     * This hold the image of the window where the action occured.
+     */
+    private String image = null;
+
+    /**
+     * This is the image file name, if then user decide to save the image to a jpeg file.
+     */
+    private String imageName = "";
+
+    /**
+     * This is the height of image of the window where the action occured. 
+     */
+    private String height;
+
+    /**
+     * This is the width of image of the window where the action occured.
+     */
+    private String width;
+
+    /**
+     * This constructor will be initializing the date,command and component value.
+     * (Precondition: (curr_date != null))
+     * @param curr_date is the date when the action occured.
+     * @param curr_command is the command the user did.
+     */
+    public History (Date curr_date,String curr_command)
+    {
+	date = curr_date.toString();
+	command = curr_command;
+	component = new ArrayList();
+    }
+
+    /**
+     * This method will be setting up the image attributes to the passed values.
+     * It will setting the image of the window where the action occured and its height 
+     * and width.It will also generate the supposed file name for this image.
+     * (Precondition: (imag != null) && (h != null) && (w != null))
+     * @param img the image of the window where the action occured.
+     * @param h   image's height.
+     * @param w   image's width.
+     */
+    public void setImage(String img,String h,String w)
+    {
+	image = img;
+	height = h;
+	width = w;
+	StringTokenizer st;
+	st = new StringTokenizer(date,": ");
+	while (st.hasMoreTokens()) 
+	    {
+		imageName += st.nextToken();
+	    }
+	imageName += ".jpg";
+    }
+
+    /**
+     * This method will add a new CompGroup instance that hold information and
+     * the status of a window that were open when the action occured.
+     * @param comp UserComponent instance that hold information about all
+     *             components inside the window.
+     * @param curr_status The current status of the window.
+     */
+    public void addComponent (UserComponent comp,String curr_status)
+    {
+	component.add(new CompGroup(comp,curr_status));
+    }
+
+    /**
+     * This method will get the image's height of the window where the action
+     * occured.
+     * @return image's height.
+     */
+    public String getHeight ()
+    {
+	return height;
+    }
+
+    /**
+     * This method will get the image's width of the window where the action
+     * occured.
+     * @return image's width.
+     */
+    public String getWidth ()
+    {
+	return width;
+    }
+
+    /**
+     * This method will set the title of the window where the action occured.
+     * @param name window's title.
+     */
+    public void setTitle (String name)
+    {
+	title = name;
+    }
+
+    /**
+     * This method will get the title of the window where the action occured.
+     * @return the window's title.
+     */
+    public String getTitle ()
+    {
+	return title;
+    }
+
+    /**
+     * This method will get the date when the action occured.
+     * @return the date when the action occured.
+     */
+    public String getDate()
+    {
+	return date;
+    }
+
+    /**
+     * This method will get the command that user did.
+     * @return the command user did.
+     */
+    public String getCommand()
+    {
+	return command;
+    }
+
+    /**
+     * This method will get the array of CompGroup instances that hold
+     * all the information and status of all the window that were open when 
+     * the action occured.
+     * @return the array list of the CompGroup instances.
+     */
+    public ArrayList getArray()
+    {
+	return component;
+    }
+
+    /**
+     * This method will get the image of the window where the action occured.
+     * @return image the window's image.
+     */
+    public String getImage()
+    {
+	return image;
+    }
+    
+    /**
+     * This method will get the supposed image's file name.
+     * @return image's file name.
+     */
+    public String getImageName()
+    {
+	return imageName;
+    }
+ 
+    /**
+     * This method will stored this instance to an xml file.
+     * It will only store the date,title,command,image and all
+     * image attributes of this instance to the xml file.
+     * @param sx is the xml file where we want to store.
+     */
+    public void sendXMLComm (SaveToXML sx)
+    {
+	sx.startContent(10);
+	
+	sx.startContent(7);
+	sx.saveContent(date);
+	sx.closeContent(7);
+	
+	sx.startContent(2);
+	sx.saveContent(title);
+	sx.closeContent(2);
+	
+	sx.startContent(8);
+	sx.saveContent(command);
+	sx.closeContent(8);
+
+	if (image != null)
+	    {
+		sx.startContent(6);
+		sx.saveImage(image,imageName,width,height);
+		sx.closeContent(6);
+	    }
+	
+	sx.closeContent(10);
+    }
+
+    /**
+     * This method will stored this instance to an xml file.
+     * It will store all the data members of this instance to
+     * the xml file.
+     * @param sx is the xml file where we want to store.
+     */
+    public void sendXML (SaveToXML sx)
+    {
+	sx.startContent(10);
+
+	sx.startContent(7);
+	sx.saveContent(date);
+	sx.closeContent(7);
+
+	sx.startContent(2);
+	sx.saveContent(title);
+	sx.closeContent(2);
+
+	sx.startContent(8);
+	sx.saveContent(command);
+	sx.closeContent(8);
+
+	if (image != null)
+	    {
+		sx.startContent(6);
+		sx.saveImage(image,imageName,width,height);
+		sx.closeContent(6);
+	    }
+	
+	int j;
+	for (j = 0 ; j < component.size() ; j++)
+	    {
+		sx.startContent(9);
+		CompGroup comp;
+		comp = (CompGroup) component.get(j);
+		
+		sx.startContent(8);
+		sx.saveContent(comp.getStatus());
+		sx.closeContent(8);
+
+		sx.startContent(0);
+		comp.getComponent().sendingXML(sx);
+		sx.closeContent(0);
+		
+		sx.closeContent(9);
+	    }
+	sx.closeContent(10);
+    }
+}
+
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/Movie.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/Movie.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/Movie.java	(revision 13928)
@@ -0,0 +1,376 @@
+package org.greenstone.gatherer.feedback;
+
+import java.awt.image.*;
+import com.sun.image.codec.jpeg.*;
+import javax.swing.*;
+import java.awt.event.*;
+import java.awt.*;
+import javax.swing.event.*;
+import java.io.*;
+import java.util.ResourceBundle;
+import java.text.MessageFormat;
+import javax.swing.text.NumberFormatter;
+import java.text.NumberFormat;
+import java.beans.*;
+import java.util.ArrayList;
+
+/**
+ * This is the class to generate a animation type from a list of ImageIcon.
+ * It will display a JDialog window and then user can specify the frames
+ * per second rate that the user want to use to view the list of the ImageIcon.
+ * @author Veronica Liesaputra
+ */
+public class Movie extends JDialog
+    implements ActionListener,ChangeListener,PropertyChangeListener
+{
+    /**
+     * This variable will hold the resource of the words that is stored in Messages.properties file.
+     * The calling using messages.getString(someString) will caused someString to be translated
+     * into some other string that is hold in that file.usually it will caused it to be translated
+     * to the language that the user use or choose to have as stated in Locale.
+     */
+    private static ResourceBundle messages;
+
+    /**
+     * This is the label that we use to display the ImageIcon.
+     */
+    private JLabel picture;
+
+    /**
+     * This is a textField where user can set how many frames per second they want to view the
+     * ImageIcon.If user enter value that is bigger than the FPS_MAX then it will beep and user
+     * will need to enter new valid value or it will stay as the previous valid value.
+     * If user enter 0 then it will stop the animation.
+     */
+    private JFormattedTextField textField;
+
+    /**
+     * This is a slider where user can set how many frames per second they want to view the
+     * ImageIcon.If user slide to 0 then animation stop.
+     */
+    private JSlider framesPerSecond;
+    
+    /**
+     * This is the minimum frame per second value.
+     */
+    private int FPS_MIN = 0;
+
+    /**
+     * This is the maximum frame per second value. The value is the twice the amount of 
+     * ImageIcon in the list.
+     */
+    private int FPS_MAX;
+
+    /**
+     * This is the initial frame per second value to view the ImageIcon.
+     */
+    private int FPS_INIT = 1;
+
+    /**
+     * This is the ImageIcon index that are currently showing in the label.
+     */
+    private int frameNumber;
+
+    /**
+     * This is the total number of ImageIcon in the list.
+     */
+    private int NUM_FRAMES;
+
+    /**
+     * This hold the list of the ImageIcon that are to be displayed.
+     */
+    private ArrayList images;
+
+    /**
+     * This is telling how long is the delay for each frame to be refreshed.
+     */
+    private int delay;
+
+    /**
+     * This is the timer that generate the animation of the list of ImageIcon.
+     * The animation will be paused twice per cycle by restarting the timer.
+     * If the the prame per second chosen by the user is 0 then the timer
+     * will be stop.
+     */
+    private Timer timer;
+
+    /**
+     * This the flag to say when the animation should stop.
+     * If frozen = true then the animation should stop otherwise the animation
+     * should keep running.
+     */
+    private boolean frozen = false;
+
+    /**
+     * This will sho a modal-dialog and set up the value for the animation to run properly 
+     * according to the list of ImageIcon passed in.
+     * @param msg  hold the resource of the words that is stored in Messages.properties file.
+     * @param img  hold the list of ImageIcon to be displayed.
+     */
+    public Movie (ResourceBundle msg,ArrayList img)
+    {
+	super();
+
+	images = img;
+	NUM_FRAMES = img.size(); 
+	FPS_MAX = img.size() * 2;
+
+	messages = msg; 
+	setTitle(messages.getString("GenerateMovie"));
+	setModal(true);
+	setBackground(new Color (176,208,176));
+    }
+
+    /**
+     * This method will seeting up the content pane of the dialog window.
+     * It also setting up the timer and the delay.
+     * @return the content pane of the window.
+     */
+    public JPanel create_UI()
+    {
+	JPanel cont;
+	cont = new JPanel();
+	cont.setOpaque(true);
+	cont.setBackground(new Color (176,208,176));
+
+	JButton cls;
+	cls = new JButton(messages.getString("Close"));
+	cls.addActionListener(new ActionListener ()
+	    {
+		public void actionPerformed (ActionEvent e)
+		{
+		    dispose();
+		    if (timer != null)
+			timer.stop();
+		}
+	    });
+	cls.setDefaultCapable(true);
+	cls.setActionCommand(messages.getString("Close"));
+	cls.setBackground(new Color(176,208,176));
+
+
+	if (images.size() <= 0)
+	    {
+		JLabel empty_lbl;
+		empty_lbl = new JLabel ("No Image to be displayed   ");
+		cont.add(empty_lbl);
+		cont.add(cls);
+		return cont;
+	    }
+
+	cont.setLayout(new BoxLayout(cont, BoxLayout.PAGE_AXIS));
+
+	delay = 1000 / FPS_INIT;
+
+	JLabel sliderLabel;
+	sliderLabel = new JLabel(messages.getString("FramesPerSecond") + ": ", JLabel.CENTER);
+	sliderLabel.setBackground(new Color(176,208,176));
+        sliderLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+        NumberFormat numberFormat;
+	numberFormat = NumberFormat.getIntegerInstance();
+        NumberFormatter formatter;
+	formatter = new NumberFormatter(numberFormat);
+        formatter.setMinimum(new Integer(FPS_MIN));
+        formatter.setMaximum(new Integer(FPS_MAX));
+
+        textField = new JFormattedTextField(formatter);
+	textField.setBackground(new Color(224,240,224));
+        textField.setValue(new Integer(FPS_INIT));
+        textField.setColumns(5);
+        textField.addPropertyChangeListener(this);
+
+        textField.getInputMap().put(KeyStroke.getKeyStroke(
+                                        KeyEvent.VK_ENTER, 0),
+                                        "check");
+        textField.getActionMap().put("check", new AbstractAction() 
+	    {
+		public void actionPerformed(ActionEvent e) 
+		{
+		    if (!textField.isEditValid()) 
+			{ 
+			    Toolkit.getDefaultToolkit().beep();
+			    textField.selectAll();
+			} 
+		    else
+			{ 
+			    try 
+				{                  
+				    textField.commitEdit();
+				} 
+			    catch (java.text.ParseException exc) { }
+			}
+		}
+	    });
+
+        framesPerSecond = new JSlider(JSlider.HORIZONTAL,
+                                      FPS_MIN, FPS_MAX, FPS_INIT);
+        framesPerSecond.addChangeListener(this);
+	framesPerSecond.setBackground(new Color(176,208,176));
+	framesPerSecond.setMajorTickSpacing(10);
+        framesPerSecond.setMinorTickSpacing(1);
+        framesPerSecond.setPaintTicks(true);
+        framesPerSecond.setPaintLabels(true);
+        framesPerSecond.setBorder(BorderFactory.createEmptyBorder(0,0,10,0));
+	
+        picture = new JLabel();
+	Dimension dim;
+	int iw,ih;
+	dim = Toolkit.getDefaultToolkit().getScreenSize();
+	iw = (int) (dim.width - 30);
+	ih = (int) (dim.height * 0.75);
+	picture.setPreferredSize(new Dimension(iw,ih));
+        picture.setHorizontalAlignment(JLabel.CENTER);
+        picture.setAlignmentX(Component.CENTER_ALIGNMENT);
+        picture.setBorder(BorderFactory.createCompoundBorder(
+                BorderFactory.createLoweredBevelBorder(),
+                BorderFactory.createEmptyBorder(10,10,10,10)));
+	picture.setBackground(new Color(176,208,176));
+        updatePicture(0);
+
+	
+        JPanel labelAndTextField;
+	labelAndTextField = new JPanel();
+        labelAndTextField.add(sliderLabel);
+        labelAndTextField.add(textField);
+	labelAndTextField.add(cls);
+	labelAndTextField.setBackground(new Color(176,208,176));
+
+	cont.add(picture);
+	cont.add(framesPerSecond);
+        cont.add(labelAndTextField);
+       
+        cont.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
+
+        timer = new Timer(delay, this);
+        timer.setInitialDelay(delay * 7); 
+        timer.setCoalesce(true);
+	timer.start();
+	
+	return cont;
+    }
+
+    /**
+     * This method will tell what should happen when the slider's arrow
+     * change its position.
+     * <br>If user adjusting the frame per second value using the slider
+     * then it will set the Textfield to have the value that slider point 
+     * to at the moment.If the value is 0 then it will stop the animation
+     * otherwise it will keep animate with the new frame per second value.
+     * @param e is the slider when the slider's arrow change its position.
+     */
+    public void stateChanged(ChangeEvent e) 
+    {
+        JSlider source;
+	source = (JSlider)e.getSource();
+        int fps;
+	fps = (int)source.getValue();
+        if (!source.getValueIsAdjusting()) 
+	    { 
+		textField.setValue(new Integer(fps));
+		if (fps == 0) 
+		    {
+			if (!frozen) 
+			    stopAnimation();
+		    } 
+		else 
+		    {
+			delay = 1000 / fps;
+			timer.setDelay(delay);
+			timer.setInitialDelay(delay * 10);
+			if (frozen) 
+			    startAnimation();
+		    }
+	    } 
+	else 
+	    { 
+		textField.setText(String.valueOf(fps));
+	    }
+    }
+   
+    /**
+     * This method will set the slider value when the user adjusting
+     * the frame per second value using the textfield.
+     * <br>If user adjusting the frame per second value using text field, the
+     * slider's arrow position will be changed into that value.
+     * @param e the text field
+     */
+    public void propertyChange(PropertyChangeEvent e) 
+    {
+        if ("value".equals(e.getPropertyName())) 
+	    {
+		Number value;
+		value = (Number)e.getNewValue();
+		if (framesPerSecond != null && value != null) 
+		    {
+			framesPerSecond.setValue(value.intValue());
+		    }
+	    }
+    }
+
+    /**
+     * This method will start the timer.
+     */
+    public void startAnimation() 
+    {
+        timer.start();
+        frozen = false;
+    }
+
+    /**
+     * This method will stop the timer.
+     */
+    public void stopAnimation() 
+    {
+        timer.stop();
+        frozen = true;
+    }
+
+    /**
+     * This method will tell what should happen when the timer is start.
+     * When the timer start it will increase the framenumber and will
+     * update the label with the new image icon.
+     * If the timer already display all the image icon in the list, it 
+     * will restart the timer and reanimate the image icon again.
+     * @param e fires when the timer start.
+     */
+    public void actionPerformed(ActionEvent e) 
+    {
+        if (frameNumber == (NUM_FRAMES - 1))
+            frameNumber = 0;
+        else 
+            frameNumber++;
+        
+        updatePicture(frameNumber);
+
+        if ((frameNumber == (NUM_FRAMES - 1)) ||
+	    (frameNumber==(NUM_FRAMES/2 - 1)))
+            timer.restart();
+    }
+
+    /**
+     * This will update the label with the new ImageIcon.
+     * If the ImageIcon is null then the label will display an error message
+     * instead of the picture.
+     * @param frameNum this is the index of the ImageIcon to be displayed. 
+     */
+    protected void updatePicture(int frameNum) 
+    {
+        if (images.get(frameNumber) != null) 
+	    {
+		picture.setIcon((ImageIcon) images.get(frameNumber));
+	    } 
+	else 
+	    {
+		picture.setText(messages.getString("image")+" #"
+				+ frameNumber + " " +
+				messages.getString("notfound"));
+	    }
+    }
+}
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/MyTextArea.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/MyTextArea.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/MyTextArea.java	(revision 13928)
@@ -0,0 +1,85 @@
+/** This class is not currently used and therefore will not be compiled by makegli. */
+
+package org.greenstone.gatherer.feedback;
+
+import javax.swing.*;
+import javax.swing.text.*;
+import java.util.Date;
+import java.awt.Color;
+
+/**
+ * This class will allow us to changed what should be inputted to the 
+ * text area as the user inputted the text to the text area.
+ * @author Veronica Liesaputra
+ */
+public class MyTextArea extends JTextArea 
+{
+    /**
+     * Creating an empty JTextArea.
+     */
+    public MyTextArea ()
+    {
+	super();
+    }
+
+    /**
+     * Creating a JTextArea already appended with cols.
+     * (Precondition: (cols != null))
+     * @param cols the text to be appended.
+     */
+    public MyTextArea(String cols) 
+    {
+	super(cols);
+    }
+ 
+    /**
+     * It will give the default model this text area should use.
+     * @return the default model this text area used.
+     */
+    protected Document createDefaultModel() 
+    {
+	return new UpperCaseDocument();
+    }
+ 
+    /**
+     * This class will be used as the default model of MyTextArea.
+     * Here we can control and modified the string that is going to be inserted to 
+     * the document.
+     */
+    static class UpperCaseDocument extends PlainDocument 
+    {
+	/**
+	 * This method will caused the document to be appended with the date followed by newline
+	 * everytime user trying to insert a new line to the document.
+	 * (Precondition : (offs >= 0) && (str != null))
+	 * @param offs is the offset placted to insert the string.
+	 * @param str is the string to be inserted.
+	 * @param a is the attribute set to be used.
+	 */
+	public void insertString(int offs, String str, AttributeSet a) 
+	    throws BadLocationException 
+	{
+	    if (str == null) 
+		{
+		    return;
+		}
+	    
+	    char[] upper;
+	    upper = str.toCharArray();
+
+	    if (str.endsWith("\n") == true)
+		{
+		    String str2;
+		    str2 = str + ((new Date()).toString()) + "\n\n>";
+		    upper = str2.toCharArray();
+		}
+	   
+	    super.insertString(offs, new String(upper), a);
+	}
+    }
+}
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/ReportDetails.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/ReportDetails.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/ReportDetails.java	(revision 13928)
@@ -0,0 +1,1304 @@
+package org.greenstone.gatherer.feedback;
+
+import java.io.*;
+import java.awt.image.*;
+import javax.swing.*;
+import java.awt.*;
+import java.util.*;
+import javax.swing.event.MouseInputAdapter;
+import java.awt.event.*;
+import javax.swing.border.*;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.text.MessageFormat;
+import javax.swing.tree.*;
+
+/**
+ * This class can give preview of all the history of actions user did or give preview of all the
+ * xml files that are ready to be send and it also can give preview of all the screen shot of
+ * all window taken when user did the actions.
+ * If user select Details button then they will view all xml files that are going to be send.
+ * If user select View History then they will see the history record that we took so far.
+ * @author Veronica Liesaputra
+ */
+public class ReportDetails extends WindowAdapter 
+{
+    /**
+     * This is the tree that will be used to hold the feedback form,the history stored inside the vector 
+     * at the moment, and hold the comment user did when they recreating the event.
+     * This tree's data partly will be supplied from whats inside vector. 
+     */
+    private JTree tree;
+    /**
+     * This is the root node for tree.
+     */
+    private DefaultMutableTreeNode rootNode;
+    /**
+     * This hold the parent node of the current node that is currently just being added to tree.
+     */
+    private DefaultMutableTreeNode parentNode;
+    /**
+     * This hold the current node that is currently just being added to tree.
+     */
+    private DefaultMutableTreeNode currNode;
+    /**
+     * This is the tree model for tree.
+     */
+    private DefaultTreeModel treeModel;
+
+    /**
+     * This is the tree that will be used to hold the commands (actions) done by the user inside the vector
+     * at the moment.This tree builds from partial data of tree and which data entered to this tree
+     * is signed by the value of comm_bool and comm_start. 
+     */
+    private JTree tree2;
+    /**
+     * This is the root node for tree2.
+     */
+    private DefaultMutableTreeNode rootNode2;
+    /**
+     * This is the parent node of the current node that is currently just being added to tree2.
+     */
+    private DefaultMutableTreeNode parentNode2;
+    /**
+     * This is the current node that is currently just being added to tree2.
+     */
+    private DefaultMutableTreeNode currNode2;
+    /**
+     * This is the tree model for tree2.
+     */
+    private DefaultTreeModel treeModel2;
+
+    /**
+     * This is the tree that will be used to hold the history of all the actions
+     * done by the user before they choose to do the Reporting Feedback sequence.
+     */
+    private JTree tree3;
+    /**
+     * This is the root node for tree3.
+     */
+    private DefaultMutableTreeNode rootNode3;
+    /**
+     * This is the parent node for the current node that is currently just being added to tree3.
+     */
+    private DefaultMutableTreeNode parentNode3;
+    /**
+     * This is the current node that is currently just being added to tree3.
+     */
+    private DefaultMutableTreeNode currNode3;
+    /**
+     * This is the tree model for tree3.
+     */
+    private DefaultTreeModel treeModel3;
+
+    /**
+     * This is the tree that will be used to hold the commands (actions) done by the user 
+     * before they choose to do the Reporting Feedback sequence.This tree builds from partial data of tree3 
+     * and which data entered to this tree2 is signed by the value of comm_bool and comm_start. 
+     */
+    private JTree tree4;
+    /**
+     * This is the root node for tree4.
+     */
+    private DefaultMutableTreeNode rootNode4;
+    /**
+     * This is the parent node for the current node that is currently just being added to tree4.
+     */
+    private DefaultMutableTreeNode parentNode4;
+    /**
+     * This is the current node that is currently just being added to tree4.
+     */
+    private DefaultMutableTreeNode currNode4;
+    /**
+     * This is the tree model for tree4.
+     */
+    private DefaultTreeModel treeModel4;
+
+    /**
+     * This is the panel to display tree4.
+     */
+    private JPanel pane4;
+    /**
+     * This is the scroll pane for displaying tree3, so it is scrollable.
+     */
+    private JScrollPane scroll3;
+    /**
+     * This is the scroll pane for displaying tree4, so it is scrollable.
+     */
+    private JScrollPane scroll4;
+
+    /**
+     * This is the panel to display tree2.
+     */
+    private JPanel pane2;
+    /**
+     * This is the scroll pane for displaying tree2, so it is scrollable.
+     */
+    private JScrollPane scroll2;
+    /**
+     * This is the scroll pane for displaying tree, so it is scrollable.
+     */
+    private JScrollPane scroll;
+   
+    /**
+     * This is all the information taken from the Feedback form and information that
+     * was taken from the system.
+     */
+    private String[] err_details;
+    
+    /**
+     * This is the vector that hold all information about the history of all
+     * the actions user did.
+     * If rec = true, it means it hold the history of all the actions and information
+     * of all the windows were open when user did the actions during reporting feedback
+     * sequence.
+     * If rec = false, it means it hold the history of all the actions and information
+     * of all the windows were open when user did the actions before and after
+     * reporting feedback sequence.
+     */
+    private Vector vector;
+    
+    /**
+     * This is a variable to know which tag xml data that wants to be added to the JTree. 
+     */
+    private int count;
+    
+    /**
+     * This is a flag variable to sign whether or not the next data is to be added to
+     * the command JTree. 
+     */
+    private boolean comm_bool = false;
+    /**
+     * This is a flag variable to sign whether or not the next history is to be added to
+     * the command JTree.
+     */
+    private boolean comm_start = false;
+    /**
+     * This is a flag variable to sign whether or not at the moment we building a new tree
+     * or build from the existing tree.
+     */
+    private boolean new_tree = false;
+    
+    /**
+     * This is a flag variable to sign which type of preview that user wants at the moment.
+     * If its true, then its means user will view all the 6 xml files that will be send.
+     * If its false, then its means user only wants to view the history and command user just did
+     * before and after the reporting feedback sequence.
+     */
+    private boolean rec = false;
+   
+    /**
+     * This is array list of all the image icons that are inside all the command JTree.
+     */
+    private ArrayList movie;
+
+    /**
+     * This variable will hold the resource of the words that is stored in Messages.properties file.
+     * The calling using messages.getString(someString) will caused someString to be translated
+     * into some other string that is hold in that file.usually it will caused it to be translated
+     * to the language that the user use or choose to have as stated in Locale.
+     */
+    private static ResourceBundle messages;
+
+    private String[] img;
+   
+    /**
+     * This constructor will be seeting up the data member to its appropriate value.
+     * (Precondition : (msg != null) && (bool != null))
+     * @param stack this is all vector to be supplied to tree.
+     * @param err_array holding all the information taken when user doing the FeedbackInterface form.
+     * @param imgFile holding all the information inside all the panels in the FeedbackInterface form.
+     * @param msg hold the resource of the words that is stored in Messages.properties file.
+     * @param bool hold the falg value of rec.
+     */
+    public ReportDetails(Vector stack,String[] err_array,String[] imgFile,ResourceBundle msg,boolean bool)
+    {
+	img = imgFile;
+	vector = stack;
+	err_details = err_array;
+	messages = msg;
+	rec = bool;
+	movie = new ArrayList();
+	makeNewWindow();
+    }
+
+    /**
+     * This method will make a modal-dialog window that will display all the preview.
+     */
+    public void makeNewWindow()
+    {
+	JDialog frame;
+	frame = new View (this);
+	frame.setModal(true);
+	frame.setVisible(true);
+    }
+
+    /**
+     * This class is the dialog window that will give the preview.
+     */
+    class View extends JDialog implements ActionListener
+    {
+	/**
+	 * This variable is holding the current window that display the preview.
+	 */
+	private JDialog frame;
+	/**
+	 * This variable holding the owner of this window.
+	 */
+	private ReportDetails framework = null;
+
+	/**
+	 * This constructor will make the dialog window for previewing and setting up the
+	 * content pane of this window.
+	 * @param controller is the owner of this window.
+	 */
+	public View (ReportDetails controller)
+	{
+	    super();
+	    framework = controller;
+	    frame = this;
+
+	    setTitle(messages.getString("ViewReport"));  
+	    setBackground(new Color(176,208,176));
+	    setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+	    setDefaultLookAndFeelDecorated(true);
+	 
+	    JPanel cont;
+	    cont = new JPanel();
+	    cont.setLayout(new BoxLayout(cont,BoxLayout.PAGE_AXIS));
+	    cont.setBackground(new Color(176,208,176));
+	
+	    JTabbedPane tab;
+	    tab = new JTabbedPane();
+	    tab.setBackground(new Color(176,208,176));
+
+	    new_tree = false;
+
+	    if (err_details != null)
+		{
+		    tab.addTab(messages.getString("ViewFeedbackForm"), 
+			       createFeedback_UI(err_details,img));
+		}
+	    
+	    if (rec == true)
+		{
+		    tab.addTab(messages.getString("ViewFeedbackHistoryState"),
+			       createFeedbackHistory_UI(vector));
+		    tab.addTab(messages.getString("ViewFeedbackCommandState"),pane2);
+		    /*tab.addTab(messages.getString("ViewHistoryState"),
+		      createHistory_UI());*/
+		    createHistory_UI();
+		    tab.addTab(messages.getString("ViewCommandState"),pane4);
+		}
+	    else
+		{
+		    /*tab.addTab(messages.getString("ViewHistoryState"),
+		      createFeedbackHistory_UI(vector));*/
+		    createFeedbackHistory_UI(vector);
+		    tab.addTab(messages.getString("ViewCommandState"),pane2);
+		}
+
+	    cont.add(tab);
+
+	    JLabel lbl;
+	    lbl = new JLabel("   ");
+	    lbl.setBackground(new Color(176,208,176));
+
+	    cont.add(lbl);
+
+	    JPanel pane3;
+	    pane3 = new JPanel();
+	    pane3.setBackground(new Color(176,208,176));
+	    JButton button;
+	    button = new JButton(messages.getString("Close"));
+	    button.setActionCommand(messages.getString("Close"));
+	    button.addActionListener(this);
+	    button.setDefaultCapable(true);
+	    button.setToolTipText(messages.getString("ClosePreview"));
+	    button.setBackground(new Color(176,208,176));
+	   
+	    /*JButton button2;
+	    button2 = new JButton(messages.getString("ViewMovie"));
+	    button2.setActionCommand(messages.getString("ViewMovie"));
+	    button2.addActionListener(new ActionListener()
+		{
+		    public void actionPerformed (ActionEvent e)
+		    {
+			JDialog.setDefaultLookAndFeelDecorated(true);
+			JDialog frame;
+			frame = new Movie(messages,movie);
+
+			frame.setContentPane(((Movie)frame).create_UI());
+			frame.pack();
+			frame.setVisible(true);
+		    }
+		});
+	    button2.setToolTipText(messages.getString("ViewMovieText"));
+	    button2.setBackground(new Color(176,208,176));
+	    pane3.add(button2);*/
+	    pane3.add(button);
+	    pane3.setBorder(new EmptyBorder(new Insets(0,10,10,10)));
+
+	    cont.add(pane3);
+
+	    cont.setBorder(new EmptyBorder(new Insets(5,5,5,5)));
+	    getContentPane().add(cont);
+
+	    tab.setAlignmentX(Component.LEFT_ALIGNMENT);
+	    lbl.setAlignmentX(Component.LEFT_ALIGNMENT);
+	    pane3.setAlignmentX(Component.LEFT_ALIGNMENT);
+	    
+	    addWindowListener(framework);
+	    Toolkit kit;
+	    kit = Toolkit.getDefaultToolkit();
+	    Dimension screenSize;
+	    screenSize = kit.getScreenSize();
+	    int screenHeight;
+	    screenHeight = screenSize.height;
+	    int screenWidth;
+	    screenWidth = screenSize.width;
+	    Dimension size;
+	    size = this.getSize();
+	    setLocation((screenWidth -size.width)/ 4, 
+			(screenHeight - size.height)/ 4);
+
+	    pack();
+	    setResizable(false);
+	}
+	
+	/**
+	 * This method will get the vector that is stored inside temp_feedbackhist.log
+	 * if rec is true, and will get the vector that is stored inside temp_history.log
+	 * if rec is false. If file is not exist then it will return null. 
+	 * @return vector that is stored in the file.
+	 */
+	public Vector getPrev_log()
+	{
+	    Vector stack = null;
+	    try
+		{
+		    File f;
+		    if (rec == true)
+			{
+			    f = new File("temp_feedbackhist.log");
+			}
+		    else
+			{
+			    f = new File("temp_history.log");
+			}
+
+		    if (f.exists() == true)
+		    {
+			FileInputStream fis = new FileInputStream(f);
+			ObjectInputStream ois = new ObjectInputStream(fis);
+			stack = (Vector) ois.readObject();
+			ois.close();
+			return stack;
+		    }
+		    else
+			stack = null; 
+		}
+	    catch (IOException exp) {exp.printStackTrace();}
+	    catch (ClassNotFoundException exp2) 
+		{
+		    System.out.println("class exp");}
+	    
+	    return stack;
+	}
+
+	/**
+	 * This method will update the graphics of this window and it will
+	 * set variable finish in Conformation to true.
+	 * @param g is the graphics for this window.
+	 */
+	public void paint (Graphics g)
+	{
+	    super.paint(g); 
+	    FeedbackInterface.setFinish(true);
+	}
+
+	/**
+	 * This method will close the preview window if user select close button.
+	 * @param e action event user did.
+	 */
+	public void actionPerformed (ActionEvent e)
+	{   
+	    if(messages.getString("Close").equals(e.getActionCommand()))
+		{ 
+		    dispose();
+		}
+	}
+
+	/**
+	 * This method will add a record to history tree and the command tree.
+	 * @param log is the record to be added.
+	 */
+	public void getHist(History log)
+	{
+	    comm_bool = true;
+	    startContent(10);
+
+	    startContent(7);
+	    saveContent(log.getDate());
+	    closeContent(7);
+	    
+	    startContent(2);
+	    saveContent(log.getTitle());
+	    closeContent(2);
+	    
+	    startContent(8);
+	    saveContent(log.getCommand());
+	    closeContent(8);
+	  
+	    String image;
+	    image = log.getImage();
+
+	    if (image != null)
+		{
+		    byte[] img;
+		    img = Base64.decode(image);
+		    
+		    String width,height;
+		    width = log.getWidth();
+		    height = log.getHeight();
+		    
+		    int w,h;
+		    w = Integer.parseInt(width);
+		    h = Integer.parseInt(height);
+
+		    ImageIcon icon,small_icon;
+		    small_icon = new ImageIcon(img);
+		    icon = new ImageIcon
+			(small_icon.getImage().getScaledInstance(w,h,Image.SCALE_SMOOTH));
+
+		    movie.add(0,icon);
+
+		    startContent(6);
+		    saveImage(log.getImageName(),width,height);
+		    closeContent(6);
+		}
+	    comm_bool = false;
+	    
+	    ArrayList component;
+	    component = log.getArray();
+	    int j;
+	    for (j = 0 ; j < component.size() ; j++)
+		{
+		    startContent(9);
+		    CompGroup comp;
+		    comp = (CompGroup) component.get(j);
+		    
+		    startContent(8);
+		    saveContent(comp.getStatus());
+		    closeContent(8);
+		    
+		    startContent(0);
+		    UserComponent cmp;
+		    cmp = comp.getComponent();
+		    showReport(cmp);
+		    closeContent(0);
+		    
+		    closeContent(9);
+		}
+	    
+	    comm_bool = true;
+	    closeContent(10);
+	    comm_bool = false;
+	}
+    
+	/**
+	 * This method will make the tree that contains the history and the commands of all the actions and window 
+	 * open when user did the action that stored in vector.
+	 * @param vector the vector that contains the information need to be display in tree.
+	 * @return       the panel that display tree and tree2.
+	 */
+	public JPanel createFeedbackHistory_UI(Vector vector)
+	{
+	    scroll = null;
+	    int k;
+
+	    tree = null;
+	    rootNode = null;
+	    currNode = null;
+	    parentNode =  null; 
+	    treeModel = null;
+
+	    tree2 = null;
+	    rootNode2 = null;
+	    currNode2 = null;
+	    parentNode2 =  null; 
+	    treeModel2 = null;
+	    
+	    comm_bool = true;
+	    comm_start = true;
+	    new_tree = false;
+
+	    startElement(messages.getString("HISTORY"));
+ 
+	    for (k = 0 ; k < vector.size() ; k++)
+		{
+		    History log;
+		    log = (History) vector.get(k);
+		    getHist(log);
+		}
+
+	    Vector stack;
+	    stack = getPrev_log();
+	    if (stack != null)
+		{
+		    for (k = 0 ; k < stack.size() ; k++)
+			{
+			    History log;
+			    log = (History) stack.get(k);
+			    getHist(log);
+			}
+		    stack.removeAllElements();
+		    System.gc();
+		    stack = null;
+		}
+
+	    comm_bool = true;
+	    endElement(messages.getString("HISTORY"));
+	    comm_bool = false;
+	    
+	    comm_start = false;
+	
+	    pane2 = new JPanel();
+	    pane2.add(scroll2);
+	    pane2.setBackground(new Color(176,208,176));
+	    pane2.setBorder(new EmptyBorder(new Insets(10,10,10,10)));
+
+	    JPanel pane;
+	    pane = new JPanel();
+	    pane.add(scroll);
+	    pane.setBackground(new Color(176,208,176));
+	    pane.setBorder(new EmptyBorder(new Insets(10,10,10,10)));
+	    
+	    return pane;
+	}
+
+	/**
+	 * This method will make the tree that contains the history and the commands of all the actions and window 
+	 * open when user did the action before user choose the reporting feedback sequence.
+	 * @return the panel contains the preview of this history and commands before user choose to start
+	 *         the reporting feedback sequence.
+	 */
+	public JPanel createHistory_UI()
+	{
+	    scroll3 = null;
+	    int k;
+
+	    tree3 = null;
+	    rootNode3 = null;
+	    currNode3 = null;
+	    parentNode3 =  null; 
+	    treeModel3 = null;
+
+	    tree4 = null;
+	    rootNode4 = null;
+	    currNode4 = null;
+	    parentNode4 =  null; 
+	    treeModel4 = null;
+	    
+	    comm_bool = true;
+	    comm_start = true;
+	    new_tree = true;
+
+	    startElement(messages.getString("HISTORY"));
+ 
+	    try
+		{
+		    File f = new File("history.log");
+		    FileInputStream fis = new FileInputStream(f);
+		    ObjectInputStream ois = new ObjectInputStream(fis);
+		    
+		    Vector stack;
+		    stack = (Vector) ois.readObject();
+
+		    if (stack != null)
+			{
+			    for (k = 0 ; k < stack.size() ; k++)
+				{
+				    History log;
+				    log = (History) stack.get(k);
+				    getHist(log);
+				}
+			    stack.removeAllElements();
+			    System.gc();
+			    stack = null;
+			}
+		    
+		    stack = (Vector) ois.readObject();
+		    
+		    if (stack != null)
+			{
+			    for (k = 0 ; k < stack.size() ; k++)
+				{
+				    History log;
+				    log = (History) stack.get(k);
+				    getHist(log);
+				}
+			    stack.removeAllElements();
+			    System.gc();
+			    stack = null;
+			}
+		
+		    ois.close();
+		}
+	    catch (IOException exp) {exp.printStackTrace();}
+	    catch (ClassNotFoundException exp2) 
+		{
+		    System.out.println("class exp");}
+	    
+	    comm_bool = true;
+	    endElement(messages.getString("HISTORY"));
+	    comm_bool = false;
+	    
+	    comm_start = false;
+	
+	    pane4 = new JPanel();
+	    pane4.add(scroll4);
+	    pane4.setBackground(new Color(176,208,176));
+	    pane4.setBorder(new EmptyBorder(new Insets(10,10,10,10)));
+
+	    JPanel pane;
+	    pane = new JPanel();
+	    pane.add(scroll3);
+	    pane.setBackground(new Color(176,208,176));
+	    pane.setBorder(new EmptyBorder(new Insets(10,10,10,10)));
+	    
+	    return pane;
+	}
+
+	/**
+	 * This method display all the information taken when user did the Feedback form.
+	 * @param err_details is the information taken when user did the Feedback form.
+	 * @param img         is the information from all the panels inside the Feedback form.
+	 * @return            panel displaying the information.
+	 */
+	public JPanel createFeedback_UI(String[] err_details,String[] img)
+	{
+	    scroll = null;
+	 
+	    tree = null;
+	    rootNode = null;
+	    currNode = null;
+	    parentNode =  null; 
+	    treeModel = null;
+
+	    tree2 = null;
+	    rootNode2 = null;
+	    currNode2 = null;
+	    parentNode2 =  null; 
+	    treeModel2 = null;
+
+	    startElement(messages.getString("BUGS"));
+	    
+	    startElement(messages.getString("IDCode"));
+	    characters(err_details[0].toCharArray(),0,err_details[0].length());
+	    endElement(messages.getString("IDCode"));
+	
+	    startElement(messages.getString("LastViewedWindow"));
+	    characters(err_details[1].toCharArray(),0,err_details[1].length());
+	    endElement(messages.getString("LastViewedWindow"));
+	    
+	    startElement(messages.getString("Optionals"));
+	   
+	    startElement(messages.getString("Type"));
+	    characters(err_details[3].toCharArray(),0,err_details[3].length());
+	    endElement(messages.getString("Type"));
+		
+	    startElement(messages.getString("Urgency"));
+	    characters(err_details[4].toCharArray(),0,err_details[4].length());
+	    endElement(messages.getString("Urgency"));
+	    
+	    endElement(messages.getString("Optionals"));
+	
+	    startElement(messages.getString("User"));
+	    
+	    startElement(messages.getString("Name"));
+	    characters(err_details[5].toCharArray(),0,err_details[5].length());
+	    endElement(messages.getString("Name"));
+	    
+	    startElement(messages.getString("HomeDirectory"));
+	    characters(err_details[6].toCharArray(),0,err_details[6].length());
+	    endElement(messages.getString("HomeDirectory"));
+	    
+	    startElement(messages.getString("WorkingDirectory"));
+	    characters(err_details[7].toCharArray(),0,err_details[7].length());
+	    endElement(messages.getString("WorkingDirectory"));
+	    
+	    startElement(messages.getString("SMTP"));
+	    characters(err_details[19].toCharArray(),0,err_details[19].length());
+	    endElement(messages.getString("SMTP"));
+	    
+	    startElement(messages.getString("Email"));
+	    characters(err_details[20].toCharArray(),0,err_details[20].length());
+	    endElement(messages.getString("Email"));
+
+	    endElement(messages.getString("User"));
+	    
+	    startElement(messages.getString("OpenFormTime"));
+	    characters(err_details[8].toCharArray(),0,err_details[8].length());
+	    endElement(messages.getString("OpenFormTime"));
+
+	    startElement(messages.getString("SendFormTime"));
+	    characters(err_details[9].toCharArray(),0,err_details[9].length());
+	    endElement(messages.getString("SendFormTime"));
+	    
+	    startElement(messages.getString("OperatingSystem"));
+	    characters(err_details[10].toCharArray(),0,err_details[10].length());
+	    endElement(messages.getString("OperatingSystem"));
+
+	    startElement(messages.getString("Java"));
+	    
+	    startElement(messages.getString("JavaInformation"));
+	    characters(err_details[11].toCharArray(),0,err_details[11].length());
+	    endElement(messages.getString("JavaInformation"));
+	    
+	    startElement(messages.getString("TotalMemory"));
+	    characters(err_details[21].toCharArray(),0,err_details[21].length());
+	    endElement(messages.getString("TotalMemory"));
+
+	    startElement(messages.getString("MaxMemory"));
+	    characters(err_details[22].toCharArray(),0,err_details[22].length());
+	    endElement(messages.getString("MaxMemory"));
+
+	    startElement(messages.getString("FreeMemory"));
+	    characters(err_details[23].toCharArray(),0,err_details[23].length());
+	    endElement(messages.getString("FreeMemory"));
+
+	    startElement(messages.getString("DefaultLocale"));
+	    characters(err_details[12].toCharArray(),0,err_details[12].length());
+	    endElement(messages.getString("DefaultLocale"));
+	
+
+	    endElement(messages.getString("Java"));
+	    
+	    startElement(messages.getString("Browser"));
+	    characters(err_details[13].toCharArray(),0,err_details[13].length());
+	    endElement(messages.getString("Browser"));
+	
+	    startElement(messages.getString("LocalHostName"));
+	    characters(err_details[14].toCharArray(),0,err_details[14].length());
+	    endElement(messages.getString("LocalHostName"));
+	
+	    startElement(messages.getString("LocalHostAddress"));
+	    characters(err_details[15].toCharArray(),0,err_details[15].length());
+	    endElement(messages.getString("LocalHostAddress"));
+	    
+	    startElement(messages.getString("ScreenResolution"));
+	    characters(err_details[16].toCharArray(),0,err_details[16].length());
+	    endElement(messages.getString("ScreenResolution"));
+
+	    if (img!=null)
+		{
+		    startElement("Sequences");
+		    int i;
+		    for ( i = 0 ; i < img.length ; i= i + 10)
+			{
+			    startElement("Sequence");
+			    
+			    startElement("Title");
+			    characters(img[i].toCharArray(),0,img[i].length());
+			    endElement("Title");
+			    
+			    startElement("Details");
+			    characters(img[i+9].toCharArray(),0,img[i+9].length());
+			    endElement("Details");
+			    
+			    startElement("ImageDescription");
+			    
+			    startElement("ScreenShot");
+			    startElement("Image");
+			    saveImage(img[i+2],img[i+7],img[i+8]);
+			    endElement("Image");
+			    endElement("ScreenShot");
+			    
+			    startElement("ErrorLineAndScreenShot");
+			    startElement("Image");
+			    saveImage(img[i+4],img[i+7],img[i+8]);
+			    endElement("Image");
+			    endElement("ErrorLineAndScreenShot");
+			    
+			    startElement("ErrorLineForScreenShot");
+			    startElement("Image");
+			    saveImage(img[i+6],img[i+7],img[i+8]); 
+			    endElement("Image");
+			    endElement("ErrorLineForScreenShot");
+			  
+			    endElement("ImageDescription");
+			    
+			    endElement("Sequence");
+			}
+		    endElement("Sequences");
+		}
+
+	    endElement(messages.getString("BUGS"));
+	    
+	    JPanel pane;
+	    pane = new JPanel();
+	    pane.add(scroll);
+	    pane.setBackground(new Color(176,208,176));
+	    pane.setBorder(new EmptyBorder(new Insets(10,10,10,10)));
+
+	    return pane;
+	}
+	
+	/**
+	 * This will add the UserComponent to the tree.
+	 * @param sx is the UserComponent to be added. 
+	 */
+	public void showReport (UserComponent sx)
+	{
+	    String type;
+	    type = sx.getType();
+	    String title;
+	    title = sx.getTitle();
+	    ArrayList content;
+	    content = sx.getContent();
+	    String selected;
+	    selected = sx.getSelected();
+	    String visible;
+	    visible = sx.getVisible();
+	    String image;
+	    image = sx.getImage();
+	    String img;
+	    img = sx.getImageFileName();
+	    String width;
+	    width = sx.getWidth();
+	    String height;
+	    height = sx.getHeight();
+	    String tooltip;
+	    tooltip = sx.getToolTip();
+	    
+	    if (type != null)
+		{
+		    startContent(1);
+		    saveContent(type);
+		    closeContent(1);
+		}
+	    
+	    if (title != null)
+		{
+		    startContent(2);
+		    saveContent(title);
+		    closeContent(2);
+		}
+	    
+	    if (content != null)
+		{
+		    startContent(3);
+		    int j;
+		    for ( j = 0 ; j < content.size() ; j++)
+			{
+			    if (content.get(j) instanceof String)
+				saveContent((String) content.get(j));
+			    else if (content.get(j) instanceof UserComponent)
+				{
+				    startContent(0);
+				    UserComponent cmp;
+				    cmp = (UserComponent) content.get(j);
+				    showReport(cmp);
+				    closeContent(0);
+				}
+			}
+		    closeContent(3);
+		}
+	    
+	    if (selected != null)
+		{
+		    startContent(4);
+		    saveContent(selected);
+		    closeContent(4);
+		}
+	    
+	    if (visible != null)
+		{
+		    startContent(5);
+		    saveContent(visible);
+		    closeContent(5);
+		}
+	
+	    if (img != null)
+		{
+		    startContent(6);
+		    saveImage(img,width,height);
+		    closeContent(6);
+		}
+	    else
+		{
+		    if (image != null)
+			{ 
+			    startContent(11);
+			    saveContent(image);
+			    closeContent(11);
+			} 
+		}
+
+	    if (tooltip != null)
+		{
+		    startContent(12);
+		    saveContent(tooltip);
+		    closeContent(12);
+		}
+	}
+	
+	/**
+	 * This method will give what type of information this node hold according the number
+	 * @param num the number that describe what type of information it hold.
+	 */
+	public void startContent (int num)
+	{
+	    switch(num)
+		{
+		case 0: startElement(messages.getString("COMPONENT"));
+		    break;
+		case 1: startElement(messages.getString("Type"));
+		    break;
+		case 2: startElement(messages.getString("Title"));
+		    break;
+		case 3: startElement(messages.getString("Content"));
+		    break;
+		case 4: startElement(messages.getString("Selected"));
+		    break;
+		case 5: startElement(messages.getString("Visible"));  
+		    break;
+		case 6: startElement(messages.getString("Image"));
+		    break;
+		case 7: startElement(messages.getString("Date"));
+		    break;
+		case 8: startElement(messages.getString("Command"));
+		    break;
+		case 9: startElement(messages.getString("COMPONENTS"));
+		    break;
+		case 10:startElement(messages.getString("LOG"));
+		    break;
+		case 11:startElement(messages.getString("Icon"));
+		    break;
+		case 12:startElement(messages.getString("ToolTipText"));
+		    break;
+		case 13:startElement(messages.getString("Comment"));
+		    break;
+		}
+	}
+	
+	/**
+	 * This will add the text content to the current node.
+	 * @param text is the text content of the current node.
+	 */
+	public void saveContent (String text)
+	{
+	    if (text == null)
+		text = "\t";
+	    characters(text.toCharArray(),0,text.length());
+	}
+	
+	/**
+	 * This will say that what type of information that has been finished added
+	 * accroding its number.
+	 * @param num  the number that describe what type of information it hold.
+	 */
+	public void closeContent (int num)
+	{
+	    switch(num)
+		{
+		case 0: endElement(messages.getString("COMPONENT"));
+		    break;
+		case 1: endElement(messages.getString("Type"));
+		    break;
+		case 2: endElement(messages.getString("Title"));
+		    break;
+		case 3: endElement(messages.getString("Content"));
+		    break;
+		case 4: endElement(messages.getString("Selected"));
+		    break;
+		case 5: endElement(messages.getString("Visible"));
+		    break;
+		case 6: endElement(messages.getString("Image"));
+		    break;
+		case 7: endElement(messages.getString("Date"));
+		    break;
+		case 8: endElement(messages.getString("Command"));
+		    break;
+		case 9: endElement(messages.getString("COMPONENTS"));
+		    break;
+		case 10:endElement(messages.getString("LOG"));
+		    break;
+		case 11:endElement(messages.getString("Icon"));
+		    break;
+		case 12:endElement(messages.getString("ToolTipText"));
+		    break;
+		case 13:endElement(messages.getString("Comment"));
+		    break;
+		}
+	}
+	
+	/**
+	 * This method will add the this string to the appropriate place in the tree.
+	 * @param type its the type to be added to the tree.
+	 */
+	public void startElement (String type)
+	{
+	   
+	    if ((comm_bool == true)&&(comm_start == true))
+		{
+		    if (new_tree == true)
+			{
+			    if (type == messages.getString("HISTORY"))
+				{
+				    rootNode4 = new DefaultMutableTreeNode(messages.getString("HISTORYCOMMANDS"));
+				    treeModel4 = new DefaultTreeModel(rootNode4);
+				    
+				    parentNode4 = rootNode4;
+				    tree4 = new JTree(treeModel4);
+				    tree4.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+				    tree4.setBackground(new Color(224,240,224));
+				    tree4.setEditable(false);
+				    tree4.setShowsRootHandles(true);
+				}  
+			    else
+				{
+				    currNode4 = new DefaultMutableTreeNode(type + " : ");
+				    treeModel4.insertNodeInto(currNode4,parentNode4,parentNode4.getChildCount());
+				    parentNode4 = currNode4;
+				} 
+			}
+		    else
+			{
+			    if (type == messages.getString("HISTORY"))
+				{
+				    rootNode2 = new DefaultMutableTreeNode(messages.getString("HISTORYCOMMANDS"));
+				    treeModel2 = new DefaultTreeModel(rootNode2);
+				    
+				    parentNode2 = rootNode2;
+				    tree2 = new JTree(treeModel2);
+				    tree2.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+				    tree2.setBackground(new Color(224,240,224));
+				    tree2.setEditable(false);
+				    tree2.setShowsRootHandles(true);
+				}  
+			    else
+				{
+				    currNode2 = new DefaultMutableTreeNode(type + " : ");
+				    treeModel2.insertNodeInto(currNode2,parentNode2,parentNode2.getChildCount());
+				    parentNode2 = currNode2;
+				} 
+			}
+		}
+		
+	    if ((type == messages.getString("COMMENTS"))||(type == messages.getString("BUGS"))||
+		(type == messages.getString("HISTORY")))
+		{
+		    if (new_tree == true)
+			{
+			    rootNode3 = new DefaultMutableTreeNode(type);
+			    treeModel3 = new DefaultTreeModel(rootNode3);
+			    
+			    parentNode3 = rootNode3;
+			    tree3 = new JTree(treeModel3);
+			    tree3.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+			    
+			    tree3.setBackground(new Color(224,240,224));
+			    tree3.setEditable(false);
+			    tree3.setShowsRootHandles(true);
+			}
+		    else
+			{
+			    rootNode = new DefaultMutableTreeNode(type);
+			    treeModel = new DefaultTreeModel(rootNode);
+			    
+			    parentNode = rootNode;
+			    tree = new JTree(treeModel);
+			    tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+			    
+			    tree.setBackground(new Color(224,240,224));
+			    tree.setEditable(false);
+			    tree.setShowsRootHandles(true);
+			}
+		}
+	    else
+		 {
+		     if (new_tree == true)
+			 {
+			     currNode3 = new DefaultMutableTreeNode(type + " : ");
+			     treeModel3.insertNodeInto(currNode3,parentNode3,parentNode3.getChildCount());
+			     parentNode3 = currNode3;
+			 }
+		     else
+			 {
+			     currNode = new DefaultMutableTreeNode(type + " : ");
+			     treeModel.insertNodeInto(currNode,parentNode,parentNode.getChildCount());
+			     parentNode = currNode;
+			 }
+		 }
+	}
+	
+	/**
+	 * This method is to mark that we finished adding the type to the tree.
+	 * @param type type that finished added to the tree.
+	 */
+	public void endElement (String type)
+	{
+	    if ((type == messages.getString("HISTORY"))||(type == messages.getString("BUGS"))||
+		(type == messages.getString("COMMENTS")))
+		{
+		    if (new_tree == true)
+			{
+			    scroll3 = new JScrollPane(tree3);
+			    scroll3.setPreferredSize(new Dimension(600,600));
+			    if (comm_bool == true)
+				{
+				    scroll4 = new JScrollPane(tree4);
+				    scroll4.setPreferredSize(new Dimension(600,600));
+				}
+			}
+		    else
+			{
+			    scroll = new JScrollPane(tree);
+			    scroll.setPreferredSize(new Dimension(600,600));
+			    if (comm_bool == true)
+				{
+				    scroll2 = new JScrollPane(tree2);
+				    scroll2.setPreferredSize(new Dimension(600,600));
+				}
+			}
+		}
+	    else
+		{
+		    if (new_tree == true)
+			{
+			    parentNode3 = (DefaultMutableTreeNode) parentNode3.getParent();
+			    
+			    if ((comm_bool == true)&&(comm_start == true))
+				{
+				    if (parentNode4 == null)  return;
+				    parentNode4 = (DefaultMutableTreeNode) parentNode4.getParent();
+				}  
+			}
+		    else
+			{
+			    parentNode = (DefaultMutableTreeNode) parentNode.getParent();
+			    
+			    if ((comm_bool == true)&&(comm_start == true))
+				{
+				    if (parentNode2 == null)  return;
+				    parentNode2 = (DefaultMutableTreeNode) parentNode2.getParent();
+				}  
+			}
+		}
+	}
+	
+	/*public BufferedImage iconToImage(Icon icon, Component targetComponent) 
+	{
+	    int w = icon.getIconWidth();
+	    int h = icon.getIconHeight();
+	    GraphicsConfiguration gc = targetComponent.getGraphicsConfiguration();
+	    BufferedImage image = gc.createCompatibleImage(w, h);
+	    Graphics2D g = image.createGraphics();
+	    icon.paintIcon(targetComponent,g,0,0);
+	    g.dispose();
+	    return image;
+	}
+	
+	public BufferedImage savingImage (ImageIcon img)
+	{
+	    JFrame f = new JFrame();
+	    f.setVisible(false);
+	    BufferedImage image = iconToImage(img,f);
+	    f.dispose();
+	    return image;
+	    }*/
+	
+	/**
+	 * This will add the image filename,width and height to the tree.
+	 * @param filename image's filename
+	 * @param width    image's width
+	 * @param height   image's height
+	 */
+	public void saveImage (String filename,String width,String height)
+	{
+	    startElement(messages.getString("Title"));
+	    characters(filename.toCharArray(),0,filename.length());
+	    endElement(messages.getString("Title"));
+	
+	    startElement(messages.getString("Size"));
+	    
+	    startElement(messages.getString("Width"));
+	    characters(width.toCharArray(),0,width.length());
+	    endElement(messages.getString("Width"));
+	    
+	    startElement(messages.getString("Height"));
+	    characters(height.toCharArray(),0,height.length());
+	    endElement(messages.getString("Height"));
+
+	    endElement(messages.getString("Size"));
+
+	    /*JFrame f = new JFrame();
+	    f.setVisible(false);
+	    BufferedImage image = savingImage(img);
+	    BufferedImage bi = new BufferedImage(400, 400, BufferedImage.TYPE_INT_RGB);
+	    Graphics2D big = bi.createGraphics();
+	    big.drawImage(image.getScaledInstance(400,400,Image.SCALE_SMOOTH),0,0,f);
+	    f.dispose();
+	    
+	
+	    JLabel label = new JLabel(new ImageIcon(bi));
+	    label.setPreferredSize(new Dimension(400,400));
+	    currNode = new DefaultMutableTreeNode(label);
+	    treeModel.insertNodeInto(currNode,parentNode,parentNode.getChildCount());*/
+	}
+	
+	/**
+	 * This method will add the characters to the current node's type.
+	 * @param ch is the char[] that is need to be added to the current node's type.
+	 * @param start is where we should start taking from ch.
+	 * @param len is the length of charcacters we should take from ch
+	 */
+	public void characters (char[] ch, int start, int len)
+	{
+	    String text;
+	    text = new String(ch,start,len);
+	    String text1;
+	    text1 = text.trim();
+	    if (text1.length() > 0)
+		{
+		    if ((comm_bool == true)&&(comm_start == true))
+			{
+			    if (new_tree == true)
+				{
+				    String txt2;
+				    txt2 = (String) currNode4.getUserObject();
+				    currNode4.setUserObject(txt2 + text1);
+				}
+			    else 
+				{
+				    String txt2;
+				    txt2 = (String) currNode2.getUserObject();
+				    currNode2.setUserObject(txt2 + text1);
+				}
+			}
+
+		    if (new_tree == true)
+			{
+			    String txt;
+			    txt = (String) currNode3.getUserObject();
+			    currNode3.setUserObject(txt + text1);
+			}
+		    else
+			{
+			    String txt;
+			    txt = (String) currNode.getUserObject();
+			    currNode.setUserObject(txt + text1);
+			}
+		}
+	}
+    }
+ 
+}
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/SaveToXML.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/SaveToXML.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/SaveToXML.java	(revision 13928)
@@ -0,0 +1,482 @@
+package org.greenstone.gatherer.feedback;
+
+import java.awt.image.*;
+import java.io.*;// SAX classes.
+import javax.imageio.*;
+import org.xml.sax.*;
+import org.xml.sax.helpers.*;//JAXP 1.1
+import javax.xml.parsers.*;
+import javax.xml.transform.*;
+import javax.xml.transform.stream.*;
+import javax.xml.transform.sax.*; 
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.text.MessageFormat;
+import java.util.*;
+
+/**
+ * This class will make xml files from the information given.
+ * @author Veronica Liesaputra
+ */
+public class SaveToXML
+{
+    /**
+     * This is the file where the xml file will be saved.
+     */
+    private FileOutputStream fos;
+    /**
+     * This is the transformer handler for the xml file.
+     */
+    private TransformerHandler hd;
+    /**
+     * This is the attribute implementation for the xml file.
+     */
+    private AttributesImpl atts;
+     /**
+     * This variable will hold the resource of the words that is stored in Messages.properties file.
+     * The calling using messages.getString(someString) will caused someString to be translated
+     * into some other string that is hold in that file.usually it will caused it to be translated
+     * to the language that the user use or choose to have as stated in Locale.
+     */
+    private static ResourceBundle messages;
+
+    /**
+     * This constructor will setup what languange should be use.
+     * @param msg will hold the resource of the words that is stored in Messages.properties file.
+     */
+    public SaveToXML(ResourceBundle msg)
+    {
+	messages = msg;
+    }
+
+    /**
+     * This will save the image, image filename,width and height to the xml file.
+     * @param image    image
+     * @param filename image's filename
+     * @param width    image's width
+     * @param height   image's height
+     */
+    public void saveImage (String image,String filename,String width,String height)
+    {
+	try
+	    {
+		hd.startElement("","","Title",atts);
+		hd.characters(filename.toCharArray(),0,filename.length());
+		hd.endElement("","","Title");
+		hd.startElement("","","Size",atts);
+		hd.startElement("","","Width",atts);
+		hd.characters(width.toCharArray(),0,width.length());
+		hd.endElement("","","Width");
+		hd.startElement("","","Height",atts);
+		hd.characters(height.toCharArray(),0,height.length());
+		hd.endElement("","","Height");
+		hd.endElement("","","Size");
+		hd.startElement("","","View",atts);
+		hd.characters(image.toCharArray(),0,image.length());
+		hd.endElement("","","View");
+	    }
+	catch(SAXException sax) {}
+    }
+
+    /**
+     * This method will create and setup the xml file.
+     * @param xmlname this is the file name for the xml file.
+     * @param type    this is the first tag that open the xml file.
+     */
+    public void open (String xmlname,String type)
+    {
+	try
+	    {
+		File f;
+		f = new File(xmlname);
+		fos = new FileOutputStream(f);
+		PrintWriter out;
+		out = new PrintWriter(fos);
+		StreamResult streamResult;
+		streamResult = new StreamResult(out);
+		SAXTransformerFactory tf;
+		tf = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
+		hd = tf.newTransformerHandler();
+		Transformer serializer;
+		serializer = hd.getTransformer();
+		
+		serializer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");
+		//serializer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM,dtdname);
+		serializer.setOutputProperty(OutputKeys.INDENT,"yes");
+			
+		hd.setResult(streamResult);
+		atts = new AttributesImpl();
+		
+		hd.startDocument();
+		
+		hd.startElement("","",type,atts);   
+	    }
+	catch (IOException e){
+	    System.err.println ("Unable to write to file");
+	    System.exit(-1);
+	}catch (TransformerConfigurationException tce){
+	    System.err.println("Error in: TransformerConfigurationException");
+	}catch (SAXException spe) {
+	    // Error generated by the parser
+	    System.err.println("Error in: (SAXException");
+	    // Use the contained exception, if any
+	    Exception  x = spe;
+	    if (spe.getException() != null)
+		x = spe.getException();
+	    x.printStackTrace();
+	}
+    }
+
+    /**
+     * This method will setup to close the xml file.
+     * @param type    this is the last tag that close the xml file.
+     */
+    public void close(String type)
+    {
+	try
+	    {
+		hd.endElement("","",type);
+		hd.endDocument();
+		fos.close(); 
+	    }
+	catch (IOException e){
+	    System.err.println ("Unable to write to file");
+	    System.exit(-1);
+	}catch (SAXException spe) {
+	    // Error generated by the parser
+	    System.err.println("Error in: (SAXException");
+	    // Use the contained exception, if any
+	    Exception  x = spe;
+	    if (spe.getException() != null)
+		x = spe.getException();
+	    x.printStackTrace();
+	}
+    }
+
+    /**
+     * This method will add the open tag according to the number.
+     * @param num the number to say which type of tag it is.
+     */
+    public void startContent (int num)
+    {
+	try
+	    {
+		switch(num)
+		    {
+		    case 0: hd.startElement("","","COMPONENT",atts);
+			break;
+		    case 1: hd.startElement("","","Type",atts);
+			break;
+		    case 2: hd.startElement("","","Title",atts);
+			break;
+		    case 3: hd.startElement("","","Content",atts);
+			break;
+		    case 4: hd.startElement("","","Selected",atts);
+			break;
+		    case 5: hd.startElement("","","Visible",atts);  
+			break;
+		    case 6: hd.startElement("","","Image",atts);
+			break;
+		    case 7: hd.startElement("","","Date",atts);
+			break;
+		    case 8: hd.startElement("","","Command",atts);
+			break;
+		    case 9: hd.startElement("","","COMPONENTS",atts);
+			break;
+		    case 10:hd.startElement("","","LOG",atts);
+			break;
+		    case 11:hd.startElement("","","Icon",atts);
+			break;
+		    case 12:hd.startElement("","","ToolTipText",atts);
+			break;
+		    case 13:hd.startElement("","","Comment",atts);
+			break;
+		    }
+	    }
+	catch (SAXException spe) {
+	    // Error generated by the parser
+	    System.err.println("Error in: (SAXException");
+	    // Use the contained exception, if any
+	    Exception  x;
+	    x = spe;
+	    if (spe.getException() != null)
+		x = spe.getException();
+	    x.printStackTrace();
+	}
+    }
+
+    /**
+     * This method will add the text to the tag.
+     * @param text is the text to be saved in xml files.
+     */
+    public void saveContent (String text)
+    {
+	try
+	    {
+		if (text == null)
+		    text = "\t";
+		hd.characters(text.toCharArray(),0,text.length());
+	    }
+	catch (SAXException spe) {
+	    // Error generated by the parser
+	    System.err.println("Error in: (SAXException");
+	    // Use the contained exception, if any
+	    Exception  x;
+	    x = spe;
+	    if (spe.getException() != null)
+		x = spe.getException();
+	    x.printStackTrace();
+	}
+    }
+
+    /**
+     * This method will add the close tag according to the number.
+     * @param num the number to say which type of tag it is.
+     */
+    public void closeContent (int num)
+    {
+	try
+	    {
+		switch(num)
+		    {
+		    case 0: hd.endElement("","","COMPONENT");
+			break;
+		    case 1: hd.endElement("","","Type");
+			break;
+		    case 2: hd.endElement("","","Title");
+			break;
+		    case 3: hd.endElement("","","Content");
+			break;
+		    case 4: hd.endElement("","","Selected");
+			break;
+		    case 5: hd.endElement("","","Visible");
+			break;
+		    case 6: hd.endElement("","","Image");
+			break;
+		    case 7: hd.endElement("","","Date");
+			break;
+		    case 8: hd.endElement("","","Command");
+			break;
+		    case 9: hd.endElement("","","COMPONENTS");
+			break;
+		    case 10:hd.endElement("","","LOG");
+			break;
+		    case 11:hd.endElement("","","Icon");
+			break;
+		    case 12:hd.endElement("","","ToolTipText");
+			break;
+		    case 13:hd.endElement("","","Comment");
+			break;
+		    }
+	    }
+	catch (SAXException spe) {
+	    // Error generated by the parser
+	    System.err.println("Error in: (SAXException");
+	    // Use the contained exception, if any
+	    Exception  x;
+	    x = spe;
+	    if (spe.getException() != null)
+		x = spe.getException();
+	    x.printStackTrace();
+	}
+    }
+
+    /**
+     * This method save to xml all the information taken when user did the Feedback form.
+     * @param err_details is the information taken when user did the Feedback form.
+     * @param img         is the images taken when user did the Feedback form
+     */ 
+    public void saveFeedback (String[] err_details,String[] img)
+    {
+	try
+	    {
+		String dirname;
+		dirname = "xmlfeedback/";
+		FileOutputStream fos;
+		fos = new FileOutputStream(dirname + "feedback" + err_details[0] + 
+					   ".xml");
+		PrintWriter out;
+		out = new PrintWriter(fos);
+		StreamResult streamResult;
+		streamResult = new StreamResult(out);
+		SAXTransformerFactory tf;
+		tf = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
+		hd = tf.newTransformerHandler();
+		Transformer serializer;
+		serializer = hd.getTransformer();
+		serializer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");
+		serializer.setOutputProperty(OutputKeys.INDENT,"yes");
+		hd.setResult(streamResult);
+		
+		
+		hd.startDocument();
+		atts = new AttributesImpl();
+		hd.startElement("","","BUGS",atts);
+		
+		hd.startElement("","","IDCode",atts);
+		hd.characters(err_details[0].toCharArray(),0,err_details[0].length());
+		hd.endElement("","","IDCode");
+		
+		hd.startElement("","","LastViewedWindow",atts);
+		hd.characters(err_details[1].toCharArray(),0,err_details[1].length());
+		hd.endElement("","","LastViewedWindow");
+
+		hd.startElement("","","Optionals",atts);
+		
+		hd.startElement("","","Type",atts);
+		hd.characters(err_details[3].toCharArray(),0,err_details[3].length());
+		hd.endElement("","","Type");
+		
+		hd.startElement("","","Urgency",atts);
+		hd.characters(err_details[4].toCharArray(),0,err_details[4].length());
+		hd.endElement("","","Urgency");
+		hd.endElement("","","Optionals");
+
+		hd.startElement("","","User",atts);
+		hd.startElement("","","Name",atts);
+		hd.characters(err_details[5].toCharArray(),0,err_details[5].length());
+		hd.endElement("","","Name");
+
+		hd.startElement("","","HomeDirectory",atts);
+		hd.characters(err_details[6].toCharArray(),0,err_details[6].length());
+		hd.endElement("","","HomeDirectory");
+
+		hd.startElement("","","WorkingDirectory",atts);
+		hd.characters(err_details[7].toCharArray(),0,err_details[7].length());
+		hd.endElement("","","WorkingDirectory");
+
+		hd.startElement("","","SMTP",atts);
+		hd.characters(err_details[19].toCharArray(),0,err_details[19].length());
+		hd.endElement("","","SMTP");
+
+		hd.startElement("","","Email",atts);
+		hd.characters(err_details[20].toCharArray(),0,err_details[20].length());
+		hd.endElement("","","Email");
+
+		hd.endElement("","","User");
+
+		hd.startElement("","","OpenFormTime",atts);
+		hd.characters(err_details[8].toCharArray(),0,err_details[8].length());
+		hd.endElement("","","OpenFormTime");
+
+		hd.startElement("","","SendFormTime",atts);
+		hd.characters(err_details[9].toCharArray(),0,err_details[9].length());
+		hd.endElement("","","SendFormTime");
+
+		hd.startElement("","","OperatingSystem",atts);
+		hd.characters(err_details[10].toCharArray(),0,err_details[10].length());
+		hd.endElement("","","OperatingSystem");
+
+		hd.startElement("","","Java",atts);
+
+		hd.startElement("","","JavaInformation",atts);
+		hd.characters(err_details[11].toCharArray(),0,err_details[11].length());
+		hd.endElement("","","JavaInformation");
+
+		hd.startElement("","","TotalMemory",atts);
+		hd.characters(err_details[21].toCharArray(),0,err_details[21].length());
+		hd.endElement("","","TotalMemory");
+
+		hd.startElement("","","MaxMemory",atts);
+		hd.characters(err_details[22].toCharArray(),0,err_details[22].length());
+		hd.endElement("","","MaxMemory");
+
+		hd.startElement("","","FreeMemory",atts);
+		hd.characters(err_details[23].toCharArray(),0,err_details[23].length());
+		hd.endElement("","","FreeMemory");
+
+		hd.startElement("","","DefaultLocale",atts);
+		hd.characters(err_details[12].toCharArray(),0,err_details[12].length());
+		hd.endElement("","","DefaultLocale");
+		
+		hd.endElement("","","Java");
+
+		hd.startElement("","","Browser",atts);
+		hd.characters(err_details[13].toCharArray(),0,err_details[13].length());
+		hd.endElement("","","Browser");
+
+		hd.startElement("","","LocalHostName",atts);
+		hd.characters(err_details[14].toCharArray(),0,err_details[14].length());
+		hd.endElement("","","LocalHostName");
+
+		hd.startElement("","","LocalHostAddress",atts);
+		hd.characters(err_details[15].toCharArray(),0,err_details[15].length());
+		hd.endElement("","","LocalHostAddress");
+
+		hd.startElement("","","ScreenResolution",atts);
+		hd.characters(err_details[16].toCharArray(),0,err_details[16].length());
+		hd.endElement("","","ScreenResolution");
+
+		if (img!= null)
+		    {
+			hd.startElement("","","Sequences",atts);
+			int i;
+			for ( i = 0 ; i < img.length ; i= i + 10)
+			    {
+				hd.startElement("","","Sequence",atts);
+				
+				hd.startElement("","","Title",atts);
+				hd.characters(img[i].toCharArray(),0,img[i].length());
+				hd.endElement("","","Title");
+				
+				hd.startElement("","","Details",atts);
+				hd.characters(img[i+9].toCharArray(),0,img[i+9].length());
+				hd.endElement("","","Details");
+				
+				hd.startElement("","","ImageDescription",atts);
+				
+				hd.startElement("","","ScreenShot",atts);
+				hd.startElement("","","Image",atts);
+				saveImage(img[i+1],img[i+2],img[i+7],img[i+8]);
+				hd.endElement("","","Image");
+				hd.endElement("","","ScreenShot");
+				
+				hd.startElement("","","ErrorLineAndScreenShot",atts);
+				hd.startElement("","","Image",atts);
+				saveImage(img[i+3],img[i+4],img[i+7],img[i+8]);
+				hd.endElement("","","Image");
+				hd.endElement("","","ErrorLineAndScreenShot");
+				
+				hd.startElement("","","ErrorLineForScreenShot",atts);
+				hd.startElement("","","Image",atts);
+				saveImage(img[i+5],img[i+6],img[i+7],img[i+8]); 
+				hd.endElement("","","Image");
+				hd.endElement("","","ErrorLineForScreenShot");
+				
+				hd.endElement("","","ImageDescription");
+				
+				hd.endElement("","","Sequence");
+			    }
+			hd.endElement("","","Sequences");
+		    }
+
+		hd.endElement("","","BUGS");
+		hd.endDocument();
+		fos.close();
+	    }
+	catch (IOException e){
+	    System.err.println ("Unable to write to file");
+	    System.exit(-1);
+	}catch (TransformerConfigurationException tce){
+	    System.err.println("Error in: TransformerConfigurationException");
+	}catch (SAXException spe) {
+	    // Error generated by the parser
+	    System.err.println("Error in: (SAXException");
+	    // Use the contained exception, if any
+	    Exception  x;
+	    x = spe;
+	    if (spe.getException() != null)
+		x = spe.getException();
+	    x.printStackTrace();
+	}
+    }
+}
+
+
+
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/ScreenShot.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/ScreenShot.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/ScreenShot.java	(revision 13928)
@@ -0,0 +1,273 @@
+package org.greenstone.gatherer.feedback;
+
+import java.awt.*;
+import java.applet.Applet;
+import java.awt.image.*;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.*;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBuffer;
+import java.awt.geom.GeneralPath;
+import java.io.*;
+import javax.imageio.*;
+import javax.swing.*; 
+import com.sun.image.codec.jpeg.*;
+import java.awt.geom.*;
+
+/**
+ * This class can take screen shot of the whole screen size or screen shot of a specified
+ * rectangle only.
+ * @author Veronica Liesaputra
+ */
+public class ScreenShot
+{
+    /**
+     * This is the buffered image that hold the screen shot.
+     */
+    private BufferedImage img;
+    
+    /**
+     * The dimension of the whole screen size.
+     */
+    private final static Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
+    
+    /**
+     * Rectangle with a dimension of a whole screen size.
+     */
+    private Rectangle mRect = new Rectangle(dim);
+    
+    /**
+     * The desired width of the image.
+     */
+    private int iw;
+
+    /**
+     * The desired height of the image.
+     */
+    private int ih;
+
+    /**
+     * BufferedImage that hold the screen shot image with the desired height and width.
+     */
+    private BufferedImage bi;
+    
+    /**
+     * This is the robot that allows to take screen shot.
+     */
+    private Robot mRobot;
+  
+    /**
+     * This constructor will setup the robot to alow taking a screen shot.
+     */
+    public ScreenShot () 
+    {
+	try
+	    {
+		mRobot = new Robot();
+		iw = (int) (dim.getWidth() - 60);
+		ih = (int) (dim.getHeight() * 0.75) - 50;
+	    }
+	catch (AWTException exp) {}
+    }
+
+    /**
+     * This method will only take screen shot of the particular rectangle.
+     * @param rect is the specified rectangle that we want to take the screen shot of.
+     * @return     the image taken.
+     */
+    //public byte[] getImageIcon (Rectangle rect)
+    public BufferedImage getImageIcon (Rectangle rect)
+    {
+	BufferedImage image;
+	image = null;
+	
+	//try
+	//  {
+		img = mRobot.createScreenCapture(rect);
+		
+		int w,h;
+		boolean rescale;
+
+		rescale = false;
+		w = rect.width;
+		
+		if (w >= iw)
+		    {
+			w = iw - 50;
+			rescale = true;
+		    }
+		
+		h = rect.height;
+		
+		if ( h >= ih)
+		    {
+			h = ih  - 50;
+			rescale = true;
+		    }
+		
+		Graphics2D big;
+		big = null;
+		
+		if (rescale == true)
+		    {
+			image = new BufferedImage(w,h, BufferedImage.TYPE_INT_RGB);
+			big = image.createGraphics();
+			big.drawImage(img.getScaledInstance(w,h,Image.SCALE_SMOOTH),0,0,null);
+		    }
+		else
+		    {
+			image = img;
+		    }
+
+		
+		/*ByteArrayOutputStream stream;
+		stream = new ByteArrayOutputStream();
+		ImageIO.write(image,"jpeg",stream);
+		byte[] bytes;
+		bytes = stream.toByteArray();*/
+		
+		if (big != null)
+		    big.dispose();
+		//image = null;
+		//img = null;
+		ActionRecorderDialog.setSavefinish(true);
+		return image;
+		//return bytes;
+		//  }
+		//catch(IOException ex) {ex.printStackTrace();}
+	
+	//return null;
+    }
+
+    /**
+     * This method will only take screen shot of the particular rectangle and encode
+     * the image to its string representation.
+     * @param rect is the specified rectangle that we want to take the screen shot of.
+     * @return     the string representation of the image taken.
+     */
+    public String getImage (Rectangle rect)
+    {
+	String txt;
+	txt = null;
+
+	BufferedImage image;
+	image = null;
+	
+	try
+	    {
+		img = mRobot.createScreenCapture(rect);
+		
+		int w,h;
+		boolean rescale;
+
+		rescale = false;
+		w = rect.width;
+		
+		if (w >= iw)
+		    {
+			w = iw - 50;
+			rescale = true;
+		    }
+		
+		h = rect.height;
+		
+		if ( h >= ih)
+		    {
+			h = ih  - 50;
+			rescale = true;
+		    }
+	
+		Graphics2D big;
+		big = null;
+
+		if (rescale == true)
+		    {
+			image = new BufferedImage(w,h, BufferedImage.TYPE_INT_RGB);
+			big = image.createGraphics();
+			big.drawImage(img.getScaledInstance(w,h,Image.SCALE_SMOOTH),0,0,null);
+		    }
+		else
+		    {
+			image = img;
+		    }
+
+		ByteArrayOutputStream stream;
+		stream = new ByteArrayOutputStream();
+		ImageIO.write(image,"gif",stream);
+		byte[] bytes;
+		bytes = stream.toByteArray();
+		txt = Base64.encodeBytes(bytes);
+		
+		bytes = null;
+		if (big != null)
+		    big.dispose();
+		image = null;
+		img = null;
+	    }
+	catch(IOException ex) {ex.printStackTrace();}
+	
+	ActionRecorderDialog.setSavefinish(true);
+	
+	return txt;
+    }
+
+    /**
+     * This method will return the buffered image of the whole screen size screen shot
+     * with the desired width and height.
+     * @return the buffered image with the desired height and width.
+     */
+    public BufferedImage getBuffImage()
+    {
+	return bi;
+    }
+
+    /**
+     * This method will take screen shot of the whole screen and resize it to the
+     * desired width and height.
+     */
+    public BufferedImage captureScreen()
+    {
+	img = mRobot.createScreenCapture(mRect);
+	
+	Graphics2D big;
+	bi = new BufferedImage(iw,ih, BufferedImage.TYPE_INT_RGB);
+	big = bi.createGraphics();
+	big.drawImage(img.getScaledInstance(iw,ih,Image.SCALE_SMOOTH),0,0,null);
+	big.dispose();
+	big = null;
+
+	return bi;
+    }
+
+    /**
+     * This method will return the desired width.
+     * @return the desired width.
+     */
+    public int getWidth()
+    {
+	return iw;
+    }
+
+    /**
+     * This method will return the desired height.
+     * @return the desired height.
+     */
+    public int getHeight()
+    {
+	return ih;
+    }
+}
+
+
+
+
+
+
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/SelectPicture.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/SelectPicture.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/SelectPicture.java	(revision 13928)
@@ -0,0 +1,819 @@
+package org.greenstone.gatherer.feedback;
+
+import java.awt.image.*;
+import javax.swing.BoxLayout;
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+import javax.swing.*;
+import javax.swing.event.MouseInputAdapter;
+import java.awt.*;
+import java.awt.geom.*;
+import java.awt.geom.Line2D.*;
+import java.awt.geom.Line2D.Double;
+import java.awt.event.*;
+import java.awt.event.MouseEvent;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.text.MessageFormat;
+import javax.swing.border.*;
+import javax.swing.BorderFactory;
+
+import org.greenstone.gatherer.util.JarTools;
+
+/**
+ * This class allows user to make scribble lines in the image.
+ * This class will display an image to a label and if the user drag inside the label
+ * then it will draw coloured line as the user drag the mouse.
+ * Image here is the screen shot of the whole screen size.
+ * @author Veronica Liesaputra
+ */
+public class SelectPicture extends WindowAdapter
+{
+    /**
+     * This is the images that stored all the images for the whole screen size image.
+     */
+    private BufferedImage[] screen;
+  
+    /**
+     * This is the images that stored all the images for the window image.
+     */
+    private BufferedImage[] window;
+
+    /**
+     * This is the buffered image that contains the line that are drawn all
+     * over the screen image.
+     */
+    private BufferedImage bi;
+    
+    /**
+     * This is the buffered image of the line that are drawn all over the screen image.
+     */
+    private BufferedImage bi2;
+
+    /**
+     * This is the buffered image of the screen image.
+     */
+    private BufferedImage bi3;
+
+    /**
+     * This is the buffered image that contains the line that are drawn all over the window image.
+     */
+    private BufferedImage bi4;
+
+    /**
+     * This is the buffered image of the line that are drawn all over the window image.
+     */
+    private BufferedImage bi5;
+
+    /**
+     * This is the buffered image of the window image.
+     */
+    private BufferedImage bi6;
+
+    /**
+     * This is the window's x-coord in the screen image.
+     */
+    private int xcoord;
+
+    /**
+     * This is the window's y-coord in the screen image.
+     */
+    private int ycoord;
+
+    /**
+     * This is the window's width in the screen image.
+     */
+    private int width;
+
+    /**
+     * This is the window's height in the screen image.
+     */
+    private int height;
+    
+    /**
+     * This is to block all the input in this window while waiting.
+     */
+    private MouseListener mouse_blocker_listener = new MouseAdapter() {};
+    
+    /**
+     * This variable will hold the resource of the words that is stored in Messages.properties file.
+     * The calling using messages.getString(someString) will caused someString to be translated
+     * into some other string that is hold in that file.usually it will caused it to be translated
+     * to the language that the user use or choose to have as stated in Locale.
+     */
+    private static ResourceBundle messages;
+    
+    /**
+     * This variable hold the comments that user entered when they are drawing lines into the image.
+     */
+    private String details;
+    
+    /**
+     * This variable is a flag to say whether or not user wants to send the feedback straight away.
+     */
+    private boolean sendNow;
+
+    /**
+     * This variable is a flag to say whether the user wants to draw the scribble lines or
+     * to erase the image.
+     */
+    private boolean drawNow;
+
+    /**
+     * This variable is a flag to say whether or not the image user wants to send is window
+     * or the whole screen image.
+     */
+    private boolean windowNow;
+
+    /**
+     * This method will make a modal-dialog that will allow user to draw a line all over the image.
+     * @param sh the buffered images of the screen image.
+     * @param wh the buffered images of the window image.
+     * @param iswindow the flag to say whether user wants to send window or whole screen image.
+     * @param screen_details the comments that user typed for this screenshot.
+     * @param msg hold the resource of the words that is stored in Messages.properties file.
+     */
+    public SelectPicture(BufferedImage[] sh,BufferedImage[] wh,boolean iswindow,String screen_details,ResourceBundle msg)
+    {
+	windowNow = iswindow;
+	drawNow = true;
+	details = screen_details;
+	messages = msg;
+	window = wh;
+	screen = sh;
+    }
+    
+    /**
+     * This method setting up the window's bounds inside the screen image.
+     * @param x the window's x-coordinate in the screen image.
+     * @param y the window's y-coordniate in the screen image.
+     * @param w the window's width in the screen image.
+     * @param h the window's height in the screen image.
+     */
+    public void setWindowBounds (int x,int y,int w,int h)
+    {
+	xcoord = x;
+	ycoord = y;
+	width = w;
+	height = h;
+	makeNewWindow();
+    }
+
+    /**
+     * This method will get which one user wants to send the window or screen image.
+     * @return the flag whether user wants to send window or screen image. 
+     */
+    public boolean getIsWindow()
+    {
+	return windowNow;
+    }
+
+    /**
+     * This method will get the screen image of the screenshot with the line drawn all over it.
+     * @return  this is the screen image with the line drawn all over it.
+     */
+    public BufferedImage getImage()
+    {
+	return bi;
+    }
+
+    /**
+     * This method will get the screen image of the screenshot.
+     * @return  this is the screen image.
+     */
+    public BufferedImage getImage3()
+    {
+	return bi5;
+    }
+
+    /**
+     * This method will get the screen image of only the line that drawn all over the image of
+     * the screenshot.
+     * @return  this is the screen image of only the line.
+     */
+    public BufferedImage getImage2()
+    {
+	return bi2;
+    }
+
+    /**
+     * This method will get the window image of the screenshot with the line drawn all over it.
+     * @return  this is the image with the line drawn all over it.
+     */
+    public BufferedImage getWindowImage()
+    {
+	return bi3;
+    }
+
+    /**
+     * This method will get the window image of the screenshot.
+     * @return  this is the window image.
+     */
+    public BufferedImage getWindowImage3()
+    {
+	return bi6;
+    }
+
+    /**
+     * This method will get the window image of only the line that drawn all over the image of
+     * the screenshot.
+     * @return  this is the window image of only the line.
+     */
+    public BufferedImage getWindowImage2()
+    {
+	return bi4;
+    }
+
+    /**
+     * This method will give the comments user made when they are drawing line over the picture.
+     * @return this is the comment user made.
+     */
+    public String getDetails ()
+    {
+	return details;
+    }
+
+    public boolean getSendNow()
+    {
+	return sendNow;
+    }
+
+    /**
+     * This method will make a modal-dialog that will have the image of the screen shot in the label,
+     * allow user to draw a line all over the image and comments it as well. 
+     */
+    public void makeNewWindow()
+    {
+	JDialog f;
+	f = new Selecting(this);
+	f.setLocation(0,0);
+    }
+
+    /**
+     * This class will make a modal-dialog that will have the image of the screen shot in the label,
+     * allow user to draw a line all over the image and comments it as well. 
+     */
+    class Selecting extends JDialog implements ActionListener
+    {
+	/**
+	 * This is the modal-dialog.
+	 */
+	private JDialog frame;
+	
+	/**
+	 * This is the special label that allows user to draw a line all over the icon set in the label.
+	 */
+	private SelectionArea area;
+	
+	/**
+	 * This is the text area where user can enter the comments they want to add.
+	 */
+	private JTextArea problem_details;
+	
+	/**
+	 * This is the owner of this modal-dialog.
+	 */
+	private SelectPicture framework = null;
+	
+	/**
+	 * This is the graphs that will allow to draw the line all over the screen image in the label and getting
+	 * the image of it.
+	 */
+	private Graphs gp;
+
+	/**
+	 * This is the graphs that will allow to draw the line all over the window image in the label and getting
+	 * the image of it.
+	 */
+	private Graphs gp2;
+
+	/**
+	 * This constructor will make  a modal-dialog that will have the image of the screen shot in the label,
+	 * allow user to draw a line all over the image and comments it as well. 
+	 * @param controller this is the owner of the modal-dialog.
+	 */
+	public Selecting(SelectPicture controller)
+	{
+	    Container contentPane;
+   
+	    contentPane = getContentPane();
+
+	    gp = new Graphs(screen);
+	    
+	    window = gp.getWindowVersion(xcoord,ycoord,width,height);
+	  
+	    gp2 = new Graphs(window);
+
+	    buildUI(contentPane);
+	
+	    framework = controller;
+	   
+	    setTitle(messages.getString("Showwhereistheproblem"));
+	    setDefaultLookAndFeelDecorated(true);
+	    setModal(true);
+
+	    frame = this;
+	    addWindowListener(framework);
+	    setBackground(new Color(176,208,176)); 
+	    
+	    setLocation(0,0);
+	  
+	    pack();
+	    setVisible(true);
+	}
+
+	/**
+	 * This method will setup the contentpane of the modal-dialog.It will set the cursor for
+	 * the label to be from the file pen.gif and set the image icon for the label.
+	 * @param content this is the contentPane of the modal-dialog.
+	 */
+	private void buildUI(Container content) 
+	{
+	    final JPanel container;
+	    container = new JPanel();
+	    container.setLayout(new BoxLayout(container, BoxLayout.PAGE_AXIS));
+	    container.setBackground(new Color(176,208,176));
+	    container.setBorder(new EmptyBorder(5,5,5,5));
+
+	   
+	    ImageIcon image = createImageIcon(windowNow);
+	    area = new SelectionArea(image, this);
+	    area.setBackground(new Color(224,240,224));
+	    area.setBorder(BorderFactory.createCompoundBorder
+			   (BorderFactory.createLineBorder(Color.blue,4),
+			    new EmptyBorder(10,10,10,10)));
+	   
+	    ImageIcon imgicon,imgicon2;
+	    Image img,img2;
+	    imgicon = JarTools.getImage("pen.gif");
+	    img = imgicon.getImage();
+	    img = img.getScaledInstance(24,24,Image.SCALE_SMOOTH);
+	    imgicon2 = JarTools.getImage("eraserpen.gif");
+	    img2 = imgicon2.getImage();
+	    final Cursor cursor;
+	    final Cursor cursor2;
+	    cursor = Toolkit.getDefaultToolkit().createCustomCursor(img,new Point(0,0),"crayon");
+	    cursor2 = Toolkit.getDefaultToolkit().createCustomCursor(img2,new Point(0,0),"eraser");
+	    
+	    area.setCursor(cursor);
+
+	    Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
+	    final JPanel iconarea = new JPanel();
+	    iconarea.setBackground(new Color(176,208,176));
+	    iconarea.add(area);
+	    container.add(iconarea);
+	    
+	    String screen_label;
+	    screen_label = " " + messages.getString("ScreenShotLabel");
+	    JLabel label;
+	    label = new JLabel(screen_label);
+	    label.setBackground(new Color(176,208,176));
+	    container.add(label);
+
+	    JPanel panes;
+	    panes = new JPanel();
+	    panes.setLayout(new GridLayout(0,2));
+	    panes.setBackground(new Color(176,208,176));
+
+	    problem_details = new JTextArea(details);
+	    problem_details.setWrapStyleWord(true);
+	    problem_details.setEditable(true);
+	    problem_details.setBackground(new Color(224,240,224));
+	    JScrollPane scroll;
+	    scroll = new JScrollPane(problem_details);
+	    scroll.setBackground(new Color(176,208,176));
+	    scroll.setPreferredSize(new Dimension(50,100));
+	    scroll.setBorder(BorderFactory.createTitledBorder(
+							      new EmptyBorder(0,0,0,0),
+							      "Screen shot " + 
+							      messages.getString("ProblemDetails")));
+
+	    panes.add(scroll);
+
+	    JPanel pane;
+	    pane = new JPanel();
+	    pane.setLayout(new GridLayout(2,3));
+	    pane.setBackground(new Color(176,208,176));
+	    pane.setBorder(new EmptyBorder(15,15,15,15));
+
+	    if ((window == null) || (screen == null)) {System.out.println("How come!");}
+	    else
+		{
+		    final JButton toggle;
+		    
+		    if (windowNow == false)
+			{
+			    toggle = new JButton("GLI window."); 
+			    toggle.setToolTipText("Showing only GLI window.");
+			}
+		    else
+			{
+			    toggle = new JButton("Whole screen.");
+			    toggle.setToolTipText("Showing whole screen.");
+			}
+		    toggle.setActionCommand("Toggle");
+		    toggle.addActionListener(new ActionListener ()
+			{
+			    public void actionPerformed (ActionEvent e)
+			    {
+				frame.addMouseListener(mouse_blocker_listener);
+				frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+				if (windowNow == true)
+				    {
+					windowNow = false;
+					toggle.setText("GLI window.");
+					toggle.setToolTipText("Showing only GLI window.");
+					window[0] = gp2.getScreenImage();
+					window[1] = gp2.getImage();
+					window[2] = gp2.getImage2();
+					gp.setScreenVersion(window,xcoord,ycoord,width,height);
+					area.setIcon(new ImageIcon(gp.getImage()));
+				    }
+				else
+				    {
+					windowNow = true;
+					toggle.setText("Whole screen.");
+					toggle.setToolTipText("Showing whole screen.");
+					
+					window[0].flush();
+					window[0] = null;
+					window[1].flush();
+					window[1] = null;
+					window[2].flush();
+					window[2] = null;
+					window = null;
+					BufferedImage tmp;
+					gp2.getImage().flush();
+					tmp = gp2.getImage();
+					tmp.flush();
+					tmp = null;
+					gp2.getImage2().flush();
+					tmp = gp2.getImage2();
+					tmp.flush();
+					tmp = null;
+					gp2.flush();
+					gp2 = null;
+					System.gc();
+
+					window = gp.getWindowVersion(xcoord,ycoord,width,height);
+					gp2 = new Graphs(window);
+					area.setIcon(new ImageIcon(gp2.getImage()));
+				    }
+
+				frame.pack();
+				frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+				frame.removeMouseListener(mouse_blocker_listener);	
+			    }
+			});
+		    toggle.setBackground(new Color(176,208,176));
+		    pane.add(toggle);
+		}
+				     
+
+	    JButton pen;
+	    pen = new JButton(JarTools.getImage("penicon.gif"));
+	    pen.setText("Pen");
+	    pen.setPreferredSize(new Dimension(30,20));
+	    pen.setActionCommand("Pen");
+	    pen.setToolTipText("Draw.");
+	    pen.addActionListener(new ActionListener ()
+		{
+		    public void actionPerformed (ActionEvent e)
+		    {
+			area.setCursor(cursor);
+			drawNow = true;
+		    }
+		});
+	    pen.setBackground(new Color(176,208,176));
+	    pane.add(pen);
+
+	    JButton eraser;
+	    eraser = new JButton(JarTools.getImage("eraser.gif"));
+	    eraser.setText("Eraser");
+	    eraser.setActionCommand("Eraser");
+	    eraser.setPreferredSize(new Dimension(30,20));
+	    eraser.setToolTipText("Erase.");
+	    eraser.addActionListener(new ActionListener ()
+		{
+		    public void actionPerformed (ActionEvent e)
+		    {
+			area.setCursor(cursor2);
+			drawNow = false;
+		    }
+		});
+	    eraser.setBackground(new Color(176,208,176));
+	    pane.add(eraser);
+
+	    if ((window == null) || (screen == null)) 
+		{
+		    JLabel empty = new JLabel(" ");
+		    empty.setBackground(new Color(176,208,176));
+		    pane.add(empty);
+		}
+
+	    JButton button;
+	    button = new JButton("Clear Scribble");
+	    button.setActionCommand("Clear");
+	    button.setToolTipText("Clear all the scribble lines.");
+	    button.addActionListener(this);
+	    button.setBackground(new Color(176,208,176));
+	    pane.add(button);
+
+	    JButton button2;
+	    button2 = new JButton("Finish Scribble");
+	    button2.setActionCommand(messages.getString("Send"));
+	    button2.setToolTipText("Back to Feedback form.");
+	    button2.addActionListener(this);
+	    button2.setBackground(new Color(176,208,176));
+	    pane.add(button2);
+
+	    JButton button3;
+	    button3 = new JButton("Send");
+	    button3.setActionCommand("SendNow");
+	    button3.setToolTipText("Finish reporting feedback and send all information now.");
+	    button3.addActionListener(this);
+	    button3.setBackground(new Color(176,208,176));
+	    pane.add(button3);
+
+	    panes.add(pane);
+
+	    container.add(panes);
+	    
+	    panes.setAlignmentX(Component.LEFT_ALIGNMENT);
+	    label.setAlignmentX(Component.LEFT_ALIGNMENT);
+	    iconarea.setAlignmentX(Component.LEFT_ALIGNMENT);
+	   
+	    container.setSize(container.getPreferredSize());
+	    content.add(container);
+	}
+
+	/**
+	 * This method will tell what the program should do when user click the buttons.
+	 * @param e this is the event when user click button.
+	 */
+	public void actionPerformed (ActionEvent e)
+	{
+	    if(messages.getString("Send").equals(e.getActionCommand()))
+		{
+		    frame.addMouseListener(mouse_blocker_listener);
+		    frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+		    sendNow = false;
+		    if (windowNow == false)
+			{
+			    window = gp.getWindowVersion(xcoord,ycoord,width,height);
+			}
+		    else
+			{
+			    window[0] = gp2.getScreenImage();
+			    window[1] = gp2.getImage();
+			    window[2] = gp2.getImage2();
+			    gp.setScreenVersion(window,xcoord,ycoord,width,height);
+			}
+ 
+		    bi5 = gp.getScreenImage();
+		    bi = gp.getImage();
+		    bi2 = gp.getImage2();
+		    bi3 = window[1];
+		    bi4 = window[2];
+		    bi6 = window[0];
+
+		    details = problem_details.getText();
+		    frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+		    frame.removeMouseListener(mouse_blocker_listener);	
+		    dispose();
+		}
+	    if ("Clear".equals(e.getActionCommand()))
+		{
+		    if (windowNow == false)
+			{
+			    gp.reset();
+			    area.setIcon(new ImageIcon(gp.getScreenImage()));
+			}
+		    else
+			{
+			    gp2.reset();
+			    area.setIcon(new ImageIcon(gp2.getScreenImage()));
+			}
+		}
+
+	    if ("SendNow".equals(e.getActionCommand()))
+		{
+		    frame.addMouseListener(mouse_blocker_listener);
+		    frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+		    sendNow = true;
+
+		    if (windowNow == false)
+			{
+			    window = gp.getWindowVersion(xcoord,ycoord,width,height);
+			}
+		    else
+			{
+			    window[0] = gp2.getScreenImage();
+			    window[1] = gp2.getImage();
+			    window[2] = gp2.getImage2();
+			    gp.setScreenVersion(window,xcoord,ycoord,width,height);
+			}
+ 
+		    bi5 = gp.getScreenImage();
+		    bi = gp.getImage();
+		    bi2 = gp.getImage2();
+		    bi3 = window[1];
+		    bi4 = window[2];
+		    bi6 = window[0];
+
+		    details = problem_details.getText();
+		    frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+		    frame.removeMouseListener(mouse_blocker_listener);	
+		    dispose();
+		}
+	}
+
+	/**
+	 * This method will create ImageIcon of the buffered image get from the screen shot instance.
+	 * The image is screen shot whole screen size image.
+	 * @return ImageIcon of the screen shot image.
+	 */
+	protected ImageIcon createImageIcon(boolean iswindow)
+	{
+	    if (iswindow == false)
+		{
+		    if (screen[1] == null)
+			return new ImageIcon(screen[0]);
+		    else
+			return new ImageIcon(screen[1]);
+		}
+	    else
+		{
+		    if (window[1] == null)
+			return new ImageIcon(window[0]);
+		    else
+			return new ImageIcon(window[1]);
+		}
+	}
+	
+	/**
+	 * This is the special class, that will allows user to draw a line all over the label when 
+	 * user dragged the mouse inside the area.
+	 */
+      	private class SelectionArea extends JLabel 
+	{
+	    /**
+	     * This is the owner of this label.
+	     */
+	    private Selecting controller;
+	    /**
+	     * This is the x coordinate of the first point.
+	     */
+	    private int x1;
+	    /**
+	     * This is the x coordinate of the second point.
+	     */
+	    private int x2;
+	    /**
+	     * This is the y coordinate of the first point.
+	     */
+	    private int y1;
+	    /**
+	     * This is the y coordinate of the second point.
+	     */
+	    private int y2;
+	    /**
+	     * This is the flag to say that user is over the label of the screen image 
+	     * and they are doing the mouse input from there.
+	     */
+	    private boolean ismouse;
+
+	    /**
+	     * This method will create a label with the specified image 
+	     * icon and it will added with mouse listener that will
+	     * allow user to draw a line all over the image.
+	     * @param image image icon to be added to the label.
+	     * @param controller this is the owner of this label.
+	     */
+	    public SelectionArea(ImageIcon image, Selecting controller) 
+	    {
+		super(image);
+		this.controller = controller;
+		setOpaque(true);
+		
+		MyListener myListener;
+		myListener = new MyListener();
+		addMouseListener(myListener);
+		addMouseMotionListener(myListener);
+	    } 
+	    
+	    /**
+	     * This is the modified mouse listener that will allow user to draw
+	     * a line all over the label while user dragging the mouse.
+	     */
+	    private class MyListener extends MouseInputAdapter 
+	    {
+		/**
+		 * This method will make a red dot in the place where user pressed the mouse.
+		 * @param e the mouse event
+		 */
+		public void mousePressed(MouseEvent e) 
+		{
+		    int x;
+		    x = e.getX();
+		    int y;
+		    y = e.getY();
+		
+		    x2 = x;
+		    y2 = y;
+		    
+		    x1 = x2;
+		    y1 = y2;
+		}
+
+		/**
+		 * This method will make a red line from (x1,y1) to the coordinate where
+		 * the mouse is located now.
+		 * @param e the mouse event.
+		 */
+		public void mouseDragged(MouseEvent e) 
+		{
+		    ismouse = true;
+		    updateSize(e);
+		}
+
+		
+		/**
+		 * This method will make a red line from (x1,y1) to the coordinate where
+		 * the mouse is located now.
+		 * @param e the mouse event.
+		 */
+		public void updateSize(MouseEvent e) 
+		{
+		    int x;
+		    x = e.getX();
+		    int y;
+		    y = e.getY();
+		
+		    x2 = x;
+		    y2 = y;
+	
+		    repaint();    
+		}
+	    }
+	    
+	    /**
+	     * This method will repaint all the component inside the dialog-window.
+	     * It will draw a red line from (x1,y1) to (x2,y2) coordinates and
+	     * updates the value of x1,y1 and the icon for the label. 
+	     * @param g the graphics of this dialog-window.
+	     */
+	    public void paintComponent(Graphics g) 
+	    {
+		super.paintComponent(g);
+
+		if (ismouse == true)
+		    {
+			if (windowNow == false)
+			    {
+				if (drawNow == true)
+				    gp.drawLines(x1,y1,x2,y2);
+				else
+				    gp.eraseLines(x1,y1,x2,y2);
+			    }
+			else
+			    {
+				if (drawNow == true)
+				    gp2.drawLines(x1,y1,x2,y2);
+				else
+				    gp2.eraseLines(x1,y1,x2,y2);
+			    }
+			
+			x1 = x2;
+			y1 = y2;
+
+			if (windowNow == false)
+			    {
+				area.setIcon(new ImageIcon(gp.getImage()));
+			    }
+			else
+			    {
+				area.setIcon(new ImageIcon(gp2.getImage()));
+			    }
+			
+			ismouse = false;
+		    }
+	    }
+	}
+    }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/SendHTTP.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/SendHTTP.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/SendHTTP.java	(revision 13928)
@@ -0,0 +1,421 @@
+package org.greenstone.gatherer.feedback;
+
+import java.util.Properties;
+import java.net.*;
+import java.io.*;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.text.MessageFormat;
+import javax.swing.*;
+import java.awt.Dimension;
+
+/**
+ * This class will send the 2 jar files to the server using HTTP Post.
+ */
+public class SendHTTP
+{
+    /**
+     * This is variable will hold the arguments provided by user in order to send 
+     */
+    private String[] argument;
+    /**
+     * This variable will hold the resource of the words that is stored in Messages.properties file.
+     * The calling using messages.getString(someString) will caused someString to be translated
+     * into some other string that is hold in that file.usually it will caused it to be translated
+     * to the language that the user use or choose to have as stated in Locale.
+     */
+    private static ResourceBundle msg;
+    /**
+     * This variable will hold the jar file unique code.
+     * For example: Jar123File.jar then file_code = 123
+     */
+    private String file_code;
+    /**
+     * This is the flag that will say whether or not the sending is successful.
+     * If failed = false means its succesful otherwise its failed.
+     */
+    private boolean failed = false;
+
+    /**
+     * Crates instance of SendHTTP
+     */
+    public SendHTTP () {}
+  
+    /**
+     * This method will send 2 files back to the server.
+     * It will also send  the code if the sending is failed then it will give user a message saying whats
+     * the possible error of it, and it will make the jar file changed into
+     * Unsend_Jar123File.jar file.
+     * If the sending is succesful then it will try to send all the other jar files
+     * that were failed to send before.And then it will deletes all the jar files
+     * that are send successfully.
+     * @param args the argument provided to send the email.
+     * @param messages hold the resource of the words that is stored in Messages.properties file.
+     * @param code the code of the email to be send.
+     */
+    public void  sendMail(String[] args,ResourceBundle messages,String code) 
+    {
+	argument = args;
+	msg = messages;
+	file_code = code;
+
+	try
+	    {
+		String BND = "---------------------------7d021a37605f0";
+		String hostURL =  "http://kanuka.cs.waikato.ac.nz:8090/glifeedback/Upload";
+
+		URL mURL = new URL(hostURL+"?name=posting");
+		URLConnection conn = mURL.openConnection();
+		
+		if (conn instanceof HttpURLConnection)
+		    ((HttpURLConnection) conn).setRequestMethod("POST");
+		 
+		conn.setDoInput(true);
+		conn.setDoOutput(true);
+		conn.setUseCaches(false);
+		conn.setDefaultUseCaches(false);
+		conn.setRequestProperty("Accept","*/*");
+		conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BND);
+		conn.setRequestProperty("Connection","Keep-Alive");
+		conn.setRequestProperty("Cache-Control","no-cache");
+
+		DataOutputStream out;
+		out = new DataOutputStream(conn.getOutputStream());
+
+		//--- Sending subject -------
+		String txt;
+		txt = "--" + BND + "\r\n";
+		out.writeBytes(txt);
+
+		txt = "Content-Disposition: form-data; ";
+		out.writeBytes(txt);
+
+		String subject;
+		subject = "Send Feedback" + code;
+		txt = "name=\"" + "Subject" + "\"\r\n"; 
+		out.writeBytes(txt);
+		
+		txt = "\r\n";
+		out.writeBytes(txt);
+
+		txt = subject + "\r\n";
+		out.writeBytes(txt);
+		
+		out.flush();
+
+		//--- Sending text ------
+		txt = "--" + BND + "\r\n";
+		out.writeBytes(txt);
+
+		txt = "Content-Disposition: form-data; ";
+		out.writeBytes(txt);
+
+		String attmnt;
+		attmnt = "We have succesfully received your feedback report.\n" +
+		    "To check what files we have received go to this link: " + hostURL +
+		    "/?name=" + code + "\n" + 
+		    "Please keep referencing to this ID Code for this feedback report.\n" +
+		    "ID Code: " + code;
+
+		txt = "name=\"" + "Text" + "\"\r\n";
+		out.writeBytes(txt);
+		
+		txt = "\r\n";
+		out.writeBytes(txt);
+		
+		txt = attmnt + "\r\n";
+		out.writeBytes(txt);
+
+		out.flush();
+
+		//--------- Sending xml-jar file
+		FileInputStream fis;
+		File f;
+		String name,path;
+		
+		f = new File(args[1]);
+		
+		txt = "--" + BND + "\r\n";
+		out.writeBytes(txt);
+
+		txt = "Content-Disposition: form-data; ";
+		out.writeBytes(txt);
+		
+		name = f.getName();
+		txt = "name=\"" + name + "\"; ";
+		out.writeBytes(txt);
+		
+		path = f.getAbsolutePath();
+		txt = "filename=\"" + path + "\"\r\n";
+		out.writeBytes(txt);
+
+		txt = "Content-Type: aplication/octet-stream\r\n";
+		out.writeBytes(txt);
+
+		txt = "\r\n";
+		out.writeBytes(txt);
+
+		fis = new FileInputStream(f);
+		byte[] data = new byte[1024];		
+		int r = 0;
+		while((r = fis.read(data, 0, data.length)) != -1) 
+		    {			
+			out.write(data, 0, r);		
+		    }
+		fis.close();
+
+		txt = "\r\n";
+		out.writeBytes(txt);
+
+		out.flush();
+
+		//--- Sending parser.jar ----
+		txt = "--" + BND + "\r\n";
+		out.writeBytes(txt);
+		
+		txt = "Content-Disposition: form-data; ";
+		out.writeBytes(txt);
+		
+		f = new File(args[4]);
+		
+		name = f.getName();
+		txt = "name=\"" + name + "\"; ";
+		out.writeBytes(txt);
+		
+		path = f.getAbsolutePath();
+		txt = "filename=\"" + path + "\"\r\n";
+		out.writeBytes(txt);
+
+		txt = "Content-Type: application/octet-stream\r\n";
+		out.writeBytes(txt);
+
+		txt = "\r\n";
+		out.writeBytes(txt);
+
+		fis = new FileInputStream(f);
+	        data = new byte[1024];		
+		r = 0;
+		while((r = fis.read(data, 0, data.length)) != -1) 
+		    {			
+			out.write(data, 0, r);		
+		    }
+		fis.close();
+		
+		txt = "\r\n";
+		out.writeBytes(txt);
+
+		out.flush();
+
+		//----- finished sending -----
+		txt = "--" + BND + "--";
+		out.writeBytes(txt);
+
+		out.flush();
+		out.close();
+
+		//----- getting the response ------
+		BufferedReader reader;
+		reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
+		String responseLine;
+		responseLine = null;
+
+		StringBuffer response;
+		response = new StringBuffer();
+		while ((responseLine = reader.readLine()) != null)
+		    response.append(responseLine+"\n");
+
+		reader.close();
+	 
+
+		//------ our application's response to server's response
+		/*if (response.equals("failed"))
+		    {
+			failed = true;
+		
+			JOptionPane.showMessageDialog(null,messages.getString("InternalError")+ "\n" + 
+						      messages.getString("Emaillater"),messages.getString("Error"),
+						      JOptionPane.ERROR_MESSAGE);
+			//Conformation.setFinish(true);
+		    }
+		else if (response.equals("success"))
+		    failed = false;
+		else
+		{*/
+			failed = false;
+			JDialog.setDefaultLookAndFeelDecorated(false);
+			JDialog dlg = new JDialog();
+			JLabel lbl = new JLabel (response.toString());
+			
+			dlg.getContentPane().add(lbl);
+			dlg.pack();
+			dlg.setVisible(true);
+			// }
+
+		//Conformation.setFinish(true);
+	    }
+	catch (MalformedURLException exp) 
+	    {
+		failed = true;
+		
+		JOptionPane.showMessageDialog(null,"malformed URL" + "\n" + 
+					      messages.getString("Emaillater"),messages.getString("Error"),
+					      JOptionPane.ERROR_MESSAGE); 
+		System.out.println("malformed URL"); 
+	    }
+	catch (IOException e) 
+	    { 
+		failed = true;
+		
+		JOptionPane.showMessageDialog(null,messages.getString("InternalError")+ "\n" + 
+					      messages.getString("Emaillater"),messages.getString("Error"),
+					      JOptionPane.ERROR_MESSAGE);e.printStackTrace();
+	    }
+
+	String dirname;
+	dirname = "xmlfeedback/";
+	
+	if (failed == false)
+	    {
+		File f;
+		f = new File(dirname + "Jar" + file_code + "File.jar");
+		f.delete();
+		
+		File file;
+		file = new File(dirname + ".");
+		File[] fileList;
+		fileList = file.listFiles();
+		
+		int y;
+		for (y = 0 ; y < fileList.length ; y++)
+		    {
+			String filename;
+			filename = isRightJarFile(fileList[y]);
+			if (filename != null)
+			    {
+				renameTo(fileList[y],new File(filename));
+				argument[1] = filename;
+				sendMail(argument,msg,getCode(filename));
+			    }
+		    }
+	    }
+	else
+	    {
+		File f2;
+		f2 = new File(dirname + "Jar" + file_code + "File.jar");
+		renameTo(f2,new File(dirname + "Unsend_Jar" + file_code + "File.jar"));
+	    }
+	
+    }
+    
+    /**
+     * This method will rename file.
+     * @param src is the name of the file to be renamed.
+     * @param dest is the desired file name.
+     */
+    private void renameTo (File src, File dest)
+    {
+	if (src.renameTo(dest) == false)
+	    {
+		try
+		    {
+			FileInputStream in;
+			in = new FileInputStream(src);
+			FileOutputStream out;
+			out = new FileOutputStream(dest);
+			int next;
+			
+			while (true)
+			    {
+				next = in.read();
+				if (next == -1)
+				    break;
+				else
+				    out.write((byte) next);
+			    }
+			
+			in.close();
+			out.close();
+		    }
+		catch (IOException exp) {exp.printStackTrace();}
+	    }
+    }
+
+    /**
+     * This method will get the extension of the file.
+     * @param f is the file that we want to get the extension.
+     * @return  the file extension
+     */
+    private String getExtension(File f)
+    {
+	String ext;
+	ext = null;
+	String s;
+	s = f.getName();
+	int i;
+	i = s.lastIndexOf('.');
+	
+	if (i > 0 &&  i < s.length() - 1)
+	    {
+		ext = s.substring(i+1).toLowerCase();
+	    }
+	return ext;
+    }
+    
+    /**
+     * This method will get all the name of the file after "_" if the file its a jar file.
+     * For example Unsend_Jar123File.jar then this method will return Jar123File, otherwise
+     * file with any other format will return null.
+     * @param f is the file that we want to get the name.
+     */
+    private String isRightJarFile(File f)
+    {
+	String ext;
+	ext = null;
+	
+	if (f.isDirectory() == true)
+	    return null;
+	
+	if (getExtension(f).compareTo("jar") == 0)
+	    {
+		String s;
+		s = f.getName();
+		int i;
+		i = s.lastIndexOf("_");
+
+		if (i > 0 &&  i < s.length() - 1)
+		    {
+			ext = s.substring(i+1,s.length());
+		    }
+		else
+		    ext = null;
+		
+		return ext;
+	    }
+	else
+	    return null;
+    }
+    
+    /**
+     * This method will getting the code that inside the Jar filename.
+     * For example Jar123File then this method will return 123. 
+     */
+    private String getCode (String s)
+	{
+	    int i;
+	    i = s.lastIndexOf("Jar");
+	    int j;
+	    j = s.indexOf("File");
+	    String code;
+	    code = s.substring((i+3),j);
+	    return code;
+	}
+}
+
+
+
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/SeparateGraphs.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/SeparateGraphs.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/SeparateGraphs.java	(revision 13928)
@@ -0,0 +1,105 @@
+/** This class is not currently used and therefore will not be compiled by makegli. */
+
+package org.greenstone.gatherer.feedback;
+
+import java.io.*;
+import javax.imageio.*;
+import java.awt.*;
+import java.awt.image.*;
+import com.sun.image.codec.jpeg.*;
+import javax.swing.*;
+
+/**
+ * This class will separate a image file into 2 jpeg image files by taking
+ * all the point in that image file that has the color red and save all that
+ * points to another image file, while all the other point to another image
+ * file.
+ * @author Veronica Liesaputra
+ */
+public class SeparateGraphs
+{
+    /**
+     * This is the BufferedImage that we want to separate.
+     */
+    private BufferedImage bi;
+
+    /**
+     * This constructor will save the image inside the file with the specified 
+     * filename to the BufferedImage.
+     */
+    public SeparateGraphs(String filename)
+    {
+	try
+	    {
+		File f = new File(filename);
+		bi = ImageIO.read(f);
+	    }
+	catch(IOException exp) {}
+    }
+
+    /**
+     * This method will separate bi into 2 image and save it to
+     * jpeg files with the specified filename.
+     * The 2 image separated will be, 1 image is the image of all the points in bi that
+     * have the color red and another image is the image of all other points in bi that
+     * do not have the color red.
+     * @param file1 this is the filename for the image of all other points that do not have color red.
+     * @param file2 this is the filename for the image of all points that have the color red.
+     */
+    public void separate(String file1,String file2)
+    {
+	BufferedImage bi1,bi2;
+	
+	int width = bi.getWidth();
+	int height = bi.getHeight();
+	
+	bi1 = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
+	bi2 = new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);
+
+	for (int y = 0 ; y < height ; y++) 
+	    {
+		for (int x = 0 ; x < width ; x++)
+		    {
+			int rgb = bi.getRGB(x,y);
+			Color c = new Color(rgb,true);
+			if (c != Color.RED)
+			    {
+				bi1.setRGB(x,y,rgb);
+			    }
+			else
+			    {
+				bi2.setRGB(x,y,rgb);
+			    }
+		    }
+	    }
+
+	save(bi1,file1);
+	save(bi2,file2);
+    }
+
+    /**
+     * This method will save the BufferedImage into a jpeg file with the specified filenames.
+     * @param b is the BufferedImage to be saved.
+     * @param filename is the name of the jpeg files.
+     */
+    public void save(BufferedImage b,String filename)
+    {
+	try 
+	    {
+		File file = new File(filename);
+		FileOutputStream out = new FileOutputStream(file);
+	    
+		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
+		JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(b);
+		param.setQuality(1.0f, false);
+		encoder.setJPEGEncodeParam(param);
+		encoder.encode(b);
+		
+	    } catch (Exception ex) {}
+    }
+}
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/Separating.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/Separating.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/Separating.java	(revision 13928)
@@ -0,0 +1,108 @@
+/** This class is not currently used and therefore will not be compiled by makegli. */
+
+package org.greenstone.gatherer.feedback;
+
+import java.io.*;
+import javax.imageio.*;
+import java.awt.*;
+import java.awt.image.*;
+import com.sun.image.codec.jpeg.*;
+import javax.swing.*;
+
+/**
+ * This method will separate 1 image file into 2 image  with the help of
+ * another file and sace the difference into a jpeg files.
+ * For example : We have 1 image file which is a screen shot and another image file
+ *               is the screenshot with some line in it.
+ *               This class will separate the screen shot and the line into 2 separates 
+ *               images.And then it will save the line into a jpeg files.
+ * 
+ * @author Veronica Liesaputra
+ */
+public class Separating
+{
+    /**
+     * This is the BufferedImage of image inside the reference image file.
+     */
+    private BufferedImage bi;
+    /**
+     * This is the BufferedImage of image that we want to separate into
+     * 2 different image using the reference file.
+     */
+    private BufferedImage src_bi;
+
+    /**
+     * It will read whats inside the 2 given filenames and put it in the
+     * right BufferedImage.
+     * @param filename1 this is the file name of the reference image file.
+     * @param filename2 this is the file name of the file we want to separate into 2.
+     */
+    public Separating(String filename1,String filename2)
+    {
+	try
+	    {
+		File f1 = new File(filename1);
+		File f2 = new File(filename2);
+		bi = ImageIO.read(f1);
+		src_bi = ImageIO.read(f2);
+	    }
+	catch(IOException exp) {}
+    }
+
+    /**
+     * This method will get the difference that exist between bi and src_bi and
+     * will save the difference inside a jpeg file with the specified file name.
+     * @param file1 is the name of the file where we want to save the image.
+     */
+    public void separate(String file1)
+    {
+	BufferedImage bi1;
+	
+	int width = bi.getWidth();
+	int height = bi.getHeight();
+	
+	bi1 = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
+
+	for (int y = 0 ; y < height ; y++) 
+	    {
+		for (int x = 0 ; x < width ; x++)
+		    {
+			int rgb = bi.getRGB(x,y);
+			int src_rgb = src_bi.getRGB(x,y);
+			
+			if (src_rgb != rgb)
+			    {
+				bi1.setRGB(x,y,rgb);
+			    }
+		    }
+	    }
+
+	save(bi1,file1);
+    }
+
+    /**
+     * This method will save a BufferedImage to a jpeg file with the specified filename.
+     * @param b is the BufferedImage to be saved.
+     * @param filename is the name of the jpeg file.
+     */
+    public void save(BufferedImage b,String filename)
+    {
+	try 
+	    {
+		File file = new File(filename);
+		FileOutputStream out = new FileOutputStream(file);
+	    
+		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
+		JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(b);
+		param.setQuality(1.0f, false);
+		encoder.setJPEGEncodeParam(param);
+		encoder.encode(b);
+		
+	    } catch (Exception ex) {}
+    }
+}
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/UserComponent.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/UserComponent.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/UserComponent.java	(revision 13928)
@@ -0,0 +1,439 @@
+package org.greenstone.gatherer.feedback;
+
+import java.util.*;
+import java.awt.image.*;
+import java.io.*;
+import javax.imageio.*;
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * This class willl hold the information about a component and the contents inside the component.
+ * @author Veronica Liesaputra
+ */
+public class UserComponent implements Serializable
+{
+    /**
+     * This variable will hold what is the type of instance this component is.
+     */
+    private String type = null;
+
+    /**
+     * This variable will store the title of this component.
+     */
+    private String title = null;
+
+    /**
+     * This varaible will store the array list of the contents of this component.
+     */
+    private ArrayList content = null;
+
+    /**
+     * This variable will store the status of this component, whether or not
+     * this component is selected by the user.
+     */
+    private String selected = null;
+
+    /**
+     * This variable will store the status of this component, whether or not
+     * this component is visible.
+     */
+    private String visible = null;
+
+    /**
+     * This variable will hold the descrption text saying that there is no
+     * image in this component.
+     */
+    private String image = null;
+
+    /**
+     * This is the supposed filename of the image that is in this component should use if 
+     * we want to save it to a jpeg file.
+     */
+    private String img = null;
+
+    /**
+     * This is the string representation of the image that is in this component.
+     */
+    private String imgFile = null;
+
+    /**
+     * This is the index that will help storing the data to the correct data member.
+     */
+    private int index;
+
+    /**
+     * This is the height of the image that is in this component.
+     */
+    private String height;
+
+    /**
+     * This is the width of the image that is in this component.
+     */
+    private String width;
+
+    /**
+     * This variable will hold the tooltiptext set for this component.
+     */
+    private String tooltip;
+
+    /**
+     * This will initialized content to a new empty Arrray list.
+     */
+    public UserComponent()
+    {
+	content = new ArrayList();
+    }
+
+    /**
+     * This method will get the width of the image that is inside this component.
+     * @return image's width.
+     */
+    public String getWidth()
+    {
+	return width;
+    }
+
+    /**
+     * This method will get the height of the image that is inside this component.
+     * @return image's height.
+     */
+    public String getHeight()
+    {
+	return height;
+    }
+
+    /**
+     * This method will get the type of instance this component is.
+     * @return component's type.
+     */
+    public String getType()
+    {
+	return type;
+    }
+
+    /**
+     * This method will get the tooltiptext set for this component.
+     * @return component's tooltiptext.
+     */
+    public String getToolTip()
+    {
+	return tooltip;
+    }
+
+    /**
+     * This method will get the title for this component.
+     * @return component's title.
+     */
+    public String getTitle()
+    {
+	return title;
+    }
+
+    /**
+     * This method will get the content inside this component.
+     * @return component's content.
+     */
+    public ArrayList getContent()
+    {
+	return content;
+    }
+
+    /**
+     * This method will get whether or not this component is 
+     * selected by the user.
+     * @return component selected or not.
+     */
+    public String getSelected()
+    {
+	return selected;
+    }
+
+    /**
+     * This method will get whether or not this component is 
+     * visible.
+     * @return component visible or not.
+     */
+    public String getVisible()
+    {
+	return visible;
+    }
+
+    /**
+     * This method will get the descrption text saying that there is no
+     * image in this component.
+     * @return the description text.
+     */
+    public String getImage()
+    {
+	return image;
+    }
+
+    /**
+     * This method will get the supposed filename of the image that is in this component should use if 
+     * we want to save it to a jpeg file.
+     * @return the image file name.
+     */
+    public String getImageFileName()
+    {
+	return img;
+    }
+
+    /**
+     * This method will get the string representation of the image that is in this component.
+     * @return the image.
+     */
+    public String getImageFile()
+    {
+	return imgFile;
+    }
+
+    /**
+     * This method will set the index value.
+     * (Precondition: (num > 0))
+     * @param num the new index value.
+     */
+    public void startContent (int num)
+    {
+	index = num;
+    }
+    
+    /**
+     * This method will add the UserComponent to the content array list.
+     * @param comp the content of the component.
+     */
+    public void saveContent (UserComponent comp)
+    {
+	content.add(comp);
+    }
+
+    /**
+     * This method will set the data member value to the text passed
+     * to this method depending on the index value.
+     * @param text the value to be set to the data member.
+     */
+    public void saveContent (String text)
+    {
+	if (text == null)
+	    text = " ";
+
+	switch (index)
+	    {
+	    case 1 : type = text; break;
+	    case 2 : title = text; break;
+	    case 3 : content.add(text); break;
+	    case 4 : selected = text;break;
+            case 5 : visible = text;break;
+	    case 6 : image = text; break;
+	    case 7 : tooltip = text;break;
+            }
+    }
+
+    /**
+     * This method will encode the ImageIcon into its String representation using Based64encoder and
+     * it will also set the image's filename,height and width.
+     * @param image is the image to be converted.
+     * @param filename is the file name of the image.
+     */
+    public void saveImage (ImageIcon image,String filename) 
+    {
+	/*int w;
+	w = image.getIconWidth();
+	int h;
+	h = image.getIconHeight();
+
+	height = "" + h;
+	width = "" + w;
+	img = filename;
+	
+	if (w > 50)
+	    w = w - 50;
+	
+	if (h > 50)
+	    h = h - 50;
+	
+	ImageIcon icon;
+	icon = new ImageIcon(image.getImage().getScaledInstance(w,h,Image.SCALE_SMOOTH));
+   
+	if ( w < 0 || h < 0)
+	    {
+		System.out.println(img);
+		return;
+	    }
+
+	BufferedImage bi;
+	bi =new BufferedImage(w,h, BufferedImage.TYPE_INT_RGB);
+	Graphics2D big;
+	big = bi.createGraphics();
+	
+	big.drawImage(icon.getImage(),0,0,null);
+	
+	try	
+	    {
+		ByteArrayOutputStream stream;
+		stream = new ByteArrayOutputStream();
+		ImageIO.write(bi,"jpeg",stream);
+		byte[] bytes;
+		bytes = stream.toByteArray();
+		imgFile = Base64.encodeBytes(bytes);
+	    }
+	catch (IOException exp) {}
+	
+	big.dispose();
+	image = null;
+	bi = null;
+	icon = null;*/
+    }
+
+    /**
+     * This method will encode the Icon into its String representation using Based64encoder and
+     * it will also set the image's filename,height and width.
+     * @param image is the image to be converted.
+     * @param filename is the file name of the image
+     */
+    public void saveImage (Icon image,String filename)
+    {
+	if (image == null)
+	    System.out.println("null image??");
+	else if (image instanceof ImageIcon)
+	    saveImage((ImageIcon)image, filename);
+	else
+	    System.out.println("Its a icon");
+	    //saveIcon (image,filename);
+    }
+
+    /**
+     * This method will encode the Icon into its String representation using Based64encoder and
+     * it will also set the image's filename,height and width.
+     * @param image is the image to be converted.
+     * @param filename is the file name of the image.
+     */
+    private void saveIcon (Icon image,String filename)
+    {
+	JFrame lbl = new JFrame();
+	lbl.setVisible(false);
+
+	ImageIcon icon;
+	Image img;
+	img = iconToImage(image,lbl);
+	icon = new ImageIcon(img);
+	lbl.dispose();
+	lbl = null;
+	saveImage(icon,filename);
+    }
+
+    /**
+     * This method will save to content of this UserComponent to an xml file.
+     * The xml file should already have an opening tag and closing tag first before calling
+     * this method or it wont make a valid xml file.
+     * @param sx this is the xml file where we want to save it.
+     */
+    public void sendingXML (SaveToXML sx)
+    {
+	if (type != null)
+	    {
+		sx.startContent(1);
+		sx.saveContent(type);
+		sx.closeContent(1);
+	    }
+
+	if (title != null)
+	    {
+		sx.startContent(2);
+		sx.saveContent(title);
+		sx.closeContent(2);
+	    }
+
+	if (content != null)
+	    {
+		sx.startContent(3);
+		for (int j = 0 ; j < content.size() ; j++)
+		    {
+			if (content.get(j) instanceof String)
+			    sx.saveContent((String) content.get(j));
+			else
+			    {
+				sx.startContent(0);
+				UserComponent cmp;
+				cmp = (UserComponent) content.get(j);
+				cmp.sendingXML(sx);
+				sx.closeContent(0);
+			    }
+		    }
+		sx.closeContent(3);
+	    }
+
+	if (selected != null)
+	    {
+		sx.startContent(4);
+		sx.saveContent(selected);
+		sx.closeContent(4);
+	    }
+
+	if (visible != null)
+	    {
+		sx.startContent(5);
+		sx.saveContent(visible);
+		sx.closeContent(5);
+	    }
+
+	if (img != null)
+	    {
+		sx.startContent(6);
+		sx.saveImage(imgFile,img,width,height);
+		sx.closeContent(6);
+	    }
+	else
+	    {
+		if (image != null)
+		    {
+			sx.startContent(11);
+			sx.saveContent(image);
+			sx.closeContent(11);
+		    }
+	    }
+
+	if (tooltip != null)
+	    {
+		sx.startContent(12);
+		sx.saveContent(tooltip);
+		sx.closeContent(12);
+	    }
+    }
+
+    /**
+     * This method will convert an Icon to a BufferedImage.
+     * @param icon icon to be converted.
+     * @param targetComponent is the component where we want to draw this BufferedImage.
+     * @return is the BufferedImage of the icon.
+     */
+    public BufferedImage iconToImage(Icon icon, Component targetComponent) 
+    {
+	int w,h;
+	w = icon.getIconWidth();
+	h = icon.getIconHeight();
+	GraphicsConfiguration gc;
+	gc = targetComponent.getGraphicsConfiguration();
+	BufferedImage image;
+	image = gc.createCompatibleImage(w, h,Transparency.TRANSLUCENT);
+	
+	Graphics2D g;
+	g = image.createGraphics();
+	icon.paintIcon(targetComponent,g,0,0);
+	g.dispose();
+	return image;
+    }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/ZipFile.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/ZipFile.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/feedback/ZipFile.java	(revision 13928)
@@ -0,0 +1,266 @@
+package org.greenstone.gatherer.feedback;
+
+import java.io.*;
+import java.util.jar.*;
+import java.util.zip.*;
+
+/**
+ * This class will help to zip and unzip files.
+ * @author Veronica Liesaputra
+ */
+public class ZipFile 
+{
+    /**
+     * This is the specified buffer size.
+     */
+    private static final int BUFFER = 2048;
+    
+    public ZipFile ()
+    {}
+
+    /**
+     * This method will unzip the MyZipFile.zip file and delete the file.
+     */
+    public void unZipFile ()
+    {
+	try
+	    {
+		BufferedOutputStream dest;
+		dest = null;
+		FileInputStream fis;
+		fis = new FileInputStream("MyZipFile.zip");
+		ZipInputStream zis;
+		zis = new ZipInputStream(new BufferedInputStream(fis));
+		ZipEntry entry;
+		while((entry = zis.getNextEntry()) != null) 
+		    {
+			int count;
+			byte data[];
+			data = new byte[BUFFER];
+			// write the files to the disk
+			File f;
+			f = new File(entry.getName());
+			if (isRightLogExtension(f) == true)
+			    {
+				FileOutputStream fos;
+				fos = new FileOutputStream(entry.getName());
+				dest = new BufferedOutputStream(fos, BUFFER);
+				while ((count = zis.read(data, 0, BUFFER)) != -1) 
+				    {
+					dest.write(data, 0, count);
+				    }
+				dest.flush();
+				dest.close();
+			    }
+		    }
+		zis.close();
+		File f3;
+		f3 = new File("MyZipFile.zip");
+		f3.delete();
+	    } 
+	catch (FileNotFoundException fexp) {}
+	catch(Exception e) 
+	    {
+		e.printStackTrace();
+	    }
+    } 
+
+    /**
+     * This method will zip all the xml files into one Jar file.
+     */
+    public void sendZipXMLFile ()
+     {
+	try 
+	    {
+		String dirname;
+		dirname = "xmlfeedback/";
+		BufferedInputStream origin;
+		origin = null;
+		FileOutputStream dest;
+		dest = new FileOutputStream(dirname + "Jar" + 
+					    FeedbackInterface.getCode() + 
+					    "File.jar");
+		JarOutputStream out;
+		out = new JarOutputStream(new BufferedOutputStream(dest));
+		out.setMethod(ZipOutputStream.DEFLATED);
+		byte data[];
+		data = new byte[BUFFER];
+		
+		File f;
+		f = new File(dirname + ".");
+		File[] fileList;
+		fileList = f.listFiles();
+		File[] files;
+		files = new File[fileList.length + 8];
+		
+		int index,j,i;
+		index = 0;
+		for (j = 0 ; j < fileList.length ; j++)
+		    {
+			String name;
+			name = fileList[j].getName();
+			
+			if (isRightXMLExtension(fileList[j]) == true)
+			    {
+				files[index] = fileList[j];
+				index++;
+			    }
+		    }
+		
+		for ( i = 0; i < index; i++) 
+		    {
+			FileInputStream fi;
+			fi = new FileInputStream(files[i]);
+			origin = new BufferedInputStream(fi, BUFFER);
+			ZipEntry entry;
+			entry = new ZipEntry(files[i].getName());
+			out.putNextEntry(entry);
+			int count;
+			while((count = origin.read(data, 0,BUFFER)) != -1) 
+			    {
+				out.write(data, 0, count);
+			    }
+			origin.close();
+		    }	
+
+		out.close();
+	    } 
+	catch(Exception e) 
+	    {
+		e.printStackTrace();
+	    }
+    }
+
+    /**
+     * This method will zip all .log file to MyZipFile.zip file and it will
+     * delete the history.log file.
+     */
+    public void sendZipFile ()
+    {
+	try 
+	    {
+		BufferedInputStream origin;
+		origin = null;
+		FileOutputStream dest;
+		dest = new FileOutputStream("MyZipFile.zip");
+		ZipOutputStream out;
+		out = new ZipOutputStream(new BufferedOutputStream(dest));
+		out.setMethod(ZipOutputStream.DEFLATED);
+		byte data[];
+		data = new byte[BUFFER];
+		
+		File f;
+		f = new File(".");
+		File[] fileList;
+		fileList = f.listFiles();
+		File[] files;
+		files = new File[fileList.length];
+		
+		int index,i,j;
+		index = 0;
+		for ( j = 0 ; j < fileList.length ; j++)
+		    {
+			if (isRightLogExtension(fileList[j]) == true)
+			    {
+				files[index] = fileList[j];
+				index++;
+			    }
+		    }
+		
+		for (i = 0; i < index; i++) 
+		    {
+			FileInputStream fi;
+			fi = new FileInputStream(files[i]);
+			origin = new BufferedInputStream(fi, BUFFER);
+			ZipEntry entry;
+			entry = new ZipEntry(files[i].getName());
+			out.putNextEntry(entry);
+			int count;
+			while((count = origin.read(data, 0,BUFFER)) != -1) 
+			    {
+				out.write(data, 0, count);
+			    }
+			origin.close();
+		    }
+		out.close();
+		File f2;
+		f2 = new File("history.log");
+		f2.delete();
+	    } 
+	catch(Exception e) 
+	    {
+		e.printStackTrace();
+	    }
+    }
+    
+    /**
+     * This method will get the extension of the given file.
+     * @param f the file we want to know the extension.
+     * @return  the file extension.
+     */
+    public String getExtension(File f)
+    {
+        String ext;
+	ext = null;
+        String s;
+	s = f.getName();
+        int i;
+	i = s.lastIndexOf('.');
+	
+        if (i > 0 &&  i < s.length() - 1)
+	    {
+		ext = s.substring(i+1).toLowerCase();
+	    }
+        return ext;
+    }
+   
+    /**
+     * This method will check whether or not the give file has
+     * an .xml extension.
+     * @param f the file we want to check the extension.
+     * @return  whether or not the file has xml as its file extension.
+     */
+    public boolean isRightXMLExtension(File f)
+    {
+	if (f.isDirectory() == true)
+	    {
+		return false;
+	    }
+	String ext;
+	ext = getExtension(f);
+	if ((ext != null) && (ext.compareTo("xml") == 0))
+	    return true;
+	else
+	    return false;
+    }
+
+    /**
+     * This method will check whether or not the give file has
+     * an .log extension.
+     * @param f the file we want to check the extension.
+     * @return  whether or not the file has log as its file extension.
+     */
+    public boolean isRightLogExtension(File f)
+    {
+	if (f.isDirectory() == true)
+	    return false;
+	
+	String ext;
+	ext = getExtension(f);
+	
+	if ((ext != null) && (ext.compareTo("log") == 0))
+	    return true;
+	else
+	    return false;
+    }
+}
+
+
+
+
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileAlreadyExistsException.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileAlreadyExistsException.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileAlreadyExistsException.java	(revision 13928)
@@ -0,0 +1,11 @@
+package org.greenstone.gatherer.file;
+
+import java.lang.Exception;
+
+public class FileAlreadyExistsException
+    extends Exception {
+
+    public FileAlreadyExistsException() {
+	super();
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileAssociationManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileAssociationManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileAssociationManager.java	(revision 13928)
@@ -0,0 +1,333 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.file;
+
+import java.io.*;
+import java.util.regex.*;
+import javax.swing.table.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.gui.FileAssociationDialog;
+import org.greenstone.gatherer.gui.PreviewCommandDialog;
+import org.greenstone.gatherer.util.ExternalProgram;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.util.XMLTools;
+import org.w3c.dom.*;
+
+public class FileAssociationManager 
+    extends AbstractTableModel {
+    static final public String FILENAME_ARG = "%1";
+    static final private String ESCAPE = "\\\\"; // '\'
+    static final private String ESCAPED_ESCAPE = "\\\\\\\\"; // '\\'
+    static final private String SPACE = " ";
+    static final private String ESCAPED_SPACE = "\\\\ ";
+    private Element associations_element;
+    private File data_file;   
+
+    public FileAssociationManager() {
+	// Retrieve the associations_element from the config
+	associations_element = Configuration.getFileAssociations();
+	// Initialize the associations. This involves looking through all current associations searching for those with a command of "".
+	if(associations_element != null) {
+	    NodeList entries = associations_element.getElementsByTagName(StaticStrings.ENTRY_ELEMENT);
+	    for(int i = 0; i < entries.getLength(); i++) {
+		Element entry = (Element) entries.item(i);
+		String command = XMLTools.getValue(entry);
+		// If we encounter a command of ""...
+		if(command.length() == 0) {
+		    // if we are on windows, we default to the start command
+		    if(Utility.isWindows()) {
+			if (Utility.isWindows9x()) {
+			    XMLTools.setValue(entry, StaticStrings.WIN_9X_OPEN_COMMAND);
+			} else {
+			    XMLTools.setValue(entry, StaticStrings.WIN_OPEN_COMMAND);
+			}
+		    }
+		    // and if we are on mac, we default to the open program
+		    else if(Utility.isMac()) {
+			XMLTools.setValue(entry, StaticStrings.MAC_OPEN_COMMAND);
+		    }
+		}
+		command = null;
+		entry = null;
+	    }
+	    entries = null;
+	}
+	else {
+	    DebugStream.println("Didn't parse anything. About to crash.");
+	}
+    }
+    
+    public void edit() {
+	FileAssociationDialog dialog = new FileAssociationDialog(this);
+	dialog.display(null);
+	dialog = null;		  
+    }
+
+    public String getBrowserCommand(String url) {
+	DebugStream.println("Get browser command: " + url);
+	// First off we try to retrieve one from the configuration
+	String command = Configuration.getPreviewCommand();
+	// If that worked, substitute in the url and return
+	if(command != null && command.length() > 0) {
+	    command = command.replaceAll("%1", url);
+	    DebugStream.println("Result = " + command);
+	    return command;
+	}
+	command = null;
+	// Failing that we have a guess at a sensible default 
+	if(Utility.isWindows()) {
+	    // we use cmd and start
+	    if (Utility.isWindows9x()) {
+		command = StaticStrings.WIN_9X_OPEN_COMMAND;//"command.com /c start \""+url+"\"";
+	    } else {
+		command = StaticStrings.WIN_OPEN_COMMAND;//"cmd.exe /c start \"\" \""+url+"\"";
+	    }
+	} else if (Utility.isMac()) {
+	    command = StaticStrings.MAC_OPEN_COMMAND; // "open %1"
+	} else {
+	    // we try to look for a browser
+	    String [] browsers = new String [] {"mozilla", "netscape"};
+	    for (int i=0; i<browsers.length; i++) {
+		if (isAvailable(browsers[i])) {
+		    command = browsers[i]+ " %1";
+		    break;
+		}
+	    }
+	}
+
+	// if we still haven't found something, prompt the user
+	if (command == null) {
+	    PreviewCommandDialog dialog = new PreviewCommandDialog();
+	    command = dialog.display();
+	    dialog.dispose();
+	    dialog = null;
+	}
+
+	// Store the result if any
+	if(command != null && !command.equals("")) {
+	    Configuration.setPreviewCommand(command);
+	    command = command.replaceAll(FILENAME_ARG, url);
+	    DebugStream.println("Result = " + command);
+	    return command;
+	}
+	// if we haven't got a command by now, we'll never get one
+	DebugStream.println("Result = null");
+	return null;
+	
+    }
+
+    public int getColumnCount() {
+	return 2;
+    }
+
+    public String getColumnName(int column) {
+	String name;
+	switch(column) {
+	case 0:
+	    name = Dictionary.get("FileAssociationDialog.Table.Extension");
+	    break;
+	default:
+	    name = Dictionary.get("FileAssociationDialog.Table.Command");
+	}
+	return name;
+    }
+   
+    public String [] getCommand(File file) {
+	String command = null;
+	String [] commands = null;
+	if(file.isFile()) {
+	    // Determine extension
+	    String filename = file.getAbsolutePath();
+	    String extension = filename.substring(filename.lastIndexOf(".") + 1);
+	    // Try to retrieve a value from cache
+	    Element entry = getCommand(extension);
+	    if(entry != null) {
+		///ystem.err.println("Retrieved Value From Cache");
+		command = XMLTools.getValue(entry); 
+	    }
+	    if(command == null || command.length() == 0) {
+		///ystem.err.println("No Existing Command");
+		// If command is null, and we are on windows try searching the registry.
+		if(Utility.isWindows()) {
+		    //try the start command
+		    if (Utility.isWindows9x()) {
+			command = StaticStrings.WIN_9X_OPEN_COMMAND;
+		    } else {
+			command = StaticStrings.WIN_OPEN_COMMAND;
+		    }
+		    
+		}
+		
+		// If we are on a mac, default to using the open program
+		else if(Utility.isMac()) {
+		    command = StaticStrings.MAC_OPEN_COMMAND;
+		}
+
+		// Otherwise display the dialog and ask the user to enter launching command.
+		if(command == null || command.length() == 0) {
+		    ///ystem.err.println("Show Dialog");
+		    // Show the dialog which forces a user to select the launch command for a certain file.
+		    FileAssociationDialog dialog = new FileAssociationDialog(this);
+		    command = dialog.display(extension);
+		    dialog = null;
+		}
+
+		// Hopefully by now we have a command, or else we're never going to get one. Add the association.
+		if (command != null && !command.equals("")) {
+		    // If no previous entry existed create one.
+		    if(entry == null) {
+			entry = associations_element.getOwnerDocument().createElement(StaticStrings.ENTRY_ELEMENT);
+			entry.setAttribute(StaticStrings.EXTENSION_ATTRIBUTE, extension);
+			associations_element.appendChild(entry);
+		    }
+		    // Replace the text in this node. Remember to replace the dummy filename with %1 - I dont think the filename will ever be in the comand now
+		    //XMLTools.setValue(entry, command.replaceAll(filename, FILENAME_ARG));
+		    XMLTools.setValue(entry, command);
+		}
+	    }
+
+	    if (command != null && !command.equals("")) {
+		// Make the command into a string []		
+		commands = command.split(" ");
+
+		// Now substitute any occurrences of %1 with its filename
+		// Note this is done after the split on spaces to avoid
+		// any conflict with filenames with spaces in them.
+
+		// We have to fix filename under windows to escape the backslashes
+		filename = filename.replaceAll(ESCAPE, ESCAPED_ESCAPE);
+
+		for (int i=0; i<commands.length; i++) {
+		    // Replace %1 with the appropriate filename
+		    commands[i] = commands[i].replaceAll(FILENAME_ARG, filename);
+		}
+	    }
+	    
+	    entry = null;
+	    extension = null;
+	    filename = null;
+	}
+	return commands;
+    }
+
+    public Element getCommand(String target_extension) {
+	NodeList entries = associations_element.getElementsByTagName(StaticStrings.ENTRY_ELEMENT);
+	for(int i = 0; i < entries.getLength(); i++) { 
+	    Element entry = (Element) entries.item(i);
+	    String extension = entry.getAttribute(StaticStrings.EXTENSION_ATTRIBUTE);
+	    if(extension.equalsIgnoreCase(target_extension)) {
+		entries = null;
+		extension = null;
+		return entry;
+	    }
+	}
+	entries = null;
+	return null;
+    }
+
+    public String getCommandString(String target_extension) {
+	Element entry = getCommand(target_extension);
+	if(entry != null) {
+	    return XMLTools.getValue(entry);
+	}
+	else {
+	    return "";
+	}
+    }
+
+    public String getExtension(int index) {
+	NodeList entries = associations_element.getElementsByTagName(StaticStrings.ENTRY_ELEMENT);
+	if(0 <= index && index < entries.getLength()) {
+	    Element entry = (Element) entries.item(index);
+	    return entry.getAttribute(StaticStrings.EXTENSION_ATTRIBUTE);
+	}
+	return "";
+    }
+
+    public int getRowCount() {
+	return size();
+    }
+
+    public Object getValueAt(int row, int column) {
+	String extension = getExtension(row);
+	switch(column) {
+	case 0:
+	    return extension;
+	default:
+	    return getCommandString(extension);
+	}
+    }
+
+    public void save() {
+    }
+
+    public void setCommand(String extension, String command) {
+	DebugStream.println("Set Launch: " + extension + " with " + command);
+	// Retrieve any existing entry for this extension
+	Element entry = getCommand(extension);
+	// If no previous entry existed create one.
+	if(entry == null && command != null) {
+	    entry = associations_element.getOwnerDocument().createElement(StaticStrings.ENTRY_ELEMENT);
+	    entry.setAttribute(StaticStrings.EXTENSION_ATTRIBUTE, extension);
+	    associations_element.appendChild(entry);
+	}
+
+	if(command != null) {
+	    // Replace the text in this node. If the user has used filename instead of %1 then too bad.
+	    XMLTools.setValue(entry, command);
+	}
+	else {
+	    // Remove the entry
+	    associations_element.removeChild(entry);
+	}
+	entry = null;
+	fireTableDataChanged(); // Can't be anymore efficient as DOM does not gareuntee ordering of new child nodes is consistant
+    }
+
+    public int size() {
+	NodeList entries = associations_element.getElementsByTagName(StaticStrings.ENTRY_ELEMENT);
+	return entries.getLength();
+    }
+
+
+    protected boolean isAvailable(String program) {
+	try {
+	    ExternalProgram e = new ExternalProgram("which", program);
+	    e.exitProgram();
+	    String out = e.getLineOfProgramOutput();
+	    if (out == null) {
+		return false;
+	    }
+	    return true;
+	} catch (Exception exc) {
+	    return false;
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileFilter.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileFilter.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileFilter.java	(revision 13928)
@@ -0,0 +1,10 @@
+package org.greenstone.gatherer.file;
+
+public class FileFilter {
+    public boolean exclude;
+    public String filter;
+    public FileFilter(String filter, boolean exclude) {
+	this.exclude = exclude;
+	this.filter = filter;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileJob.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileJob.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileJob.java	(revision 13928)
@@ -0,0 +1,168 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.file;
+
+import javax.swing.tree.*;
+import org.greenstone.gatherer.util.DragComponent;
+
+/** This object encapsulates all the information about a certain file movement job. This job be to create a copy of a file from one place to another, or to simply delete a file. 
+ * @author John Thompson
+ * @version 2.3c
+ */
+public class FileJob {
+    /** true to mark that this file has already been copied, false otherwise. */
+    public boolean done = false;
+
+    /** The type of this movement as an byte. */
+    public byte type = 0;
+    /** The DragComponent source of this file, most likely a GTree. */
+    public DragComponent source       = null;
+    /** The DragComponent to move the file to, again most likely a GTree. */
+    public DragComponent target       = null;
+    /** The unique identifier shared by all jobs created by the same action. */
+    private long id = 0;
+    /** The path to the destination node as a string. Used because any reference based path or variables quickly becomes obsolete. */
+    private TreePath destination_path = null;
+    /** The path to the origin node as a string. Used because any reference based path or variables quickly becomes obsolete. */
+    private TreePath origin_path = null;
+    /** An element of the job type enumeration indicating a copy action. */
+    static final public byte COPY   = 1;
+    /** An element of the job type enumeration indicating a delete action. */
+    static final public byte DELETE = 2;
+    /** An element of the job type enumeration indicating a move action. */
+    static final public byte MOVE   = 3;
+    /** An element of the job type enumeration indicating a new folder action. */
+    static final public byte NEW_FOLDER = 4;
+    /** An element of the job type enumeration indicating an empty folder delete action. */
+    static final public byte DELETE_EMPTY_DIRECTORY = 5;
+    /** An element of the job type enumeration indicating a rename action. */
+    static final public byte RENAME = 6;
+    /** An element of the job type enumeration indicating a replace action. */
+    static final public byte REPLACE = 7;
+    /** An element of the job type enumeration indicating a copy action (but don't look for metadata. */
+    static final public byte COPY_FILE_ONLY   = 8;
+
+    /** Constructor.
+     * @param id A unique identifier for this job (and others created with a single gesture) as a long.
+     * @param source The DragComponent source of this file, most likely a GTree.
+     * @param orig The FileNode you wish to mode.
+     * @param target The DragComponent to move the file to, again most likely a GTree.
+     * @param dest The files new FileNode parent within the target.
+     * @param type The type of this movement as an int, either COPY or DELETE.
+     */
+    public FileJob(long id, DragComponent source, FileNode orig, DragComponent target, FileNode dest, byte type) {
+	this.id = id;
+	this.source = source;
+	this.target = target;
+	this.type = type;
+	///ystem.err.println("New Job: " + type + ", " + source + ", " + target);
+	// Dont store FileNodes which can go stale. Store paths instead, which are used to locate current 'fresh' versions of nodes.
+	if(dest != null) {
+	    this.destination_path = new TreePath(dest.getPath());
+	    ///ystem.err.println("Destination Path: " + destination_path);
+	}
+	if(orig != null) {
+	    this.origin_path = new TreePath(orig.getPath());
+	    ///atherer.println("Origin Path: " + origin_path);
+	}
+    }
+
+    /** Retrieve the destination node. Watch out for stale versions by always attempting to load the node at destination_path first. */
+    public FileNode getDestination() {
+	FileNode destination = null;
+	if(destination_path != null) {
+	    if(target != null) {
+		FileSystemModel model = (FileSystemModel)target.getTreeModel();
+		destination = model.getNode(destination_path);
+	    }
+	    // If the above fails, a stale copy may be better than nothing.
+	    else {
+		destination = (FileNode) destination_path.getLastPathComponent();
+	    }
+	}
+	return destination;
+    }
+
+    /** Retrieve the origin node. Watch out for stale versions by always attempting to load the node at origin_path first. */
+    public FileNode getOrigin() {
+	FileNode origin = null;
+	if(origin_path != null) {
+	    if(source != null) {
+		FileSystemModel model = (FileSystemModel)source.getTreeModel();
+		origin = model.getNode(origin_path);
+	    }
+	    // If the above fails, a stale copy may be better than nothing.
+	    else {
+		origin = (FileNode) origin_path.getLastPathComponent();
+	    }
+	}
+	return origin;
+    }
+
+    /** Retrieve the id for this job. */
+    public long ID() {
+	return id;
+    }
+
+    public String toString() {
+	StringBuffer text = new StringBuffer("");
+	switch(type) {
+	case COPY:
+	    text.append("copy ");
+	    break;
+	case DELETE:
+	    text.append("delete ");
+	    break;
+	case MOVE:
+	    text.append("move ");
+	    break;
+	case DELETE_EMPTY_DIRECTORY:
+	    text.append("empty directory delete ");
+	    break;
+	default:
+	    text.append("unknown ");
+	}
+	FileNode origin = getOrigin();
+	if(origin != null) {
+	    text.append(origin.getFile().getAbsolutePath());
+	}
+	else {
+	    text.append("ERROR!");
+	}
+	if (type != DELETE && type != DELETE_EMPTY_DIRECTORY) {
+	    text.append(" -> ");
+	    FileNode destination = getDestination();
+	    if(destination != null) {
+		text.append(destination.getFile().getAbsolutePath());
+	    }  
+	    else {
+		text.append("Recycle Bin");
+	    }
+	}
+	return text.toString();
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileManager.java	(revision 13928)
@@ -0,0 +1,447 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, NZDL Project, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 2005 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.file;
+
+import java.io.File;
+import javax.swing.*;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.collection.CollectionTree;
+import org.greenstone.gatherer.collection.CollectionTreeNode;
+import org.greenstone.gatherer.gui.ExplodeMetadataDatabasePrompt;
+import org.greenstone.gatherer.gui.GProgressBar;
+import org.greenstone.gatherer.gui.NewFolderOrFilePrompt;
+import org.greenstone.gatherer.gui.RenamePrompt;
+import org.greenstone.gatherer.gui.tree.DragTree;
+import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
+import org.greenstone.gatherer.util.DragComponent;
+import org.greenstone.gatherer.util.Utility;
+
+/** Manages the moving of files within a separate thread.
+ * @author John Thompson, NZDL Project, University of Waikato
+ */
+public class FileManager
+{
+    /** Not only the queue of files to be moved, but also the object that moves them. */
+    static private FileQueue file_queue = null;
+
+    public static int FILE_TYPE = 0;
+    public static int FOLDER_TYPE = 1;
+    protected static File startup_directory = null;
+
+
+    /** Constructor.
+     * @see org.greenstone.gatherer.file.FileQueue
+     */
+    public FileManager()
+    {
+	file_queue = new FileQueue();
+	file_queue.start();
+    }
+
+
+    /** Determine what action should be carried out by the file queue, and add all of the necessary file jobs. */
+    public void action(DragComponent source, FileNode[] source_nodes, DragComponent target, FileNode target_node)
+    {
+	// Check there is something to do
+	if (source_nodes == null || source_nodes.length == 0) {
+	    return;
+	}
+
+	// We need a unique ID for each file task
+	long id = System.currentTimeMillis();
+
+	// If source and target are the same we're moving
+	if (source == target) {
+	    // Start a new move FileTask and we're done
+	    (new FileTask(id, source, source_nodes, target, target_node, FileJob.MOVE)).start();
+	    return;
+	}
+
+	// If target isn't the RecycleBin, we're copying
+	if (!(target instanceof RecycleBin)) {
+	    // Start a new copy FileTask and we're done
+	    (new FileTask(id, source, source_nodes, target, target_node, FileJob.COPY)).start();
+	    return;
+	}
+
+	// We're deleting... but first make sure source isn't read-only
+	boolean read_only_source = false;
+
+	// The workspace tree is read-only...
+	if (source.toString().equals("Workspace")) {
+	    read_only_source = true;
+
+	    // ...except for files from the "Downloaded Files" folder
+	    String downloaded_files_folder_path = Gatherer.getGLIUserCacheDirectoryPath();
+	    for (int i = 0; i < source_nodes.length; i++) {
+		// Is this the "Downloaded Files" folder?
+		if (source_nodes[i].getFile().getAbsolutePath().startsWith(downloaded_files_folder_path)) {
+		    read_only_source = false;
+		}
+	    }
+	}
+
+	// The source is read-only, so tell the user and abort
+	if (read_only_source) {
+	    JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("FileActions.Read_Only"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
+	    return;
+	}
+
+	// Start a new delete FileTask and we're done
+	(new FileTask(id, source, source_nodes, target, target_node, FileJob.DELETE)).start();
+    }
+
+
+    /** Retrieves the file queue object. */
+    public FileQueue getQueue()
+    {
+	return file_queue;
+    }
+
+
+    private class FileTask
+	extends Thread
+    {
+	private long id;
+	private DragComponent source;
+	private FileNode[] source_nodes;
+	private DragComponent target;
+	private FileNode target_node;
+	private byte type;
+
+
+	public FileTask(long id, DragComponent source, FileNode[] source_nodes, DragComponent target, FileNode target_node, byte type)
+	{
+	    this.id = id;
+	    this.source = source;
+	    this.source_nodes = source_nodes;
+	    this.target = target;
+	    this.target_node = target_node;
+	    this.type = type;
+	}
+
+
+	public void run()
+	{
+	    // Reset the progress bar and set it to indeterminate while calculating its size
+	    GProgressBar progress_bar = file_queue.getProgressBar();
+	    progress_bar.reset();
+	    progress_bar.setIndeterminate(true);
+
+	    // Calculate the progress bar size
+	    boolean cancelled = file_queue.calculateSize(source_nodes);
+	    if (!cancelled) {
+		file_queue.addJob(id, source, source_nodes, target, target_node, type);
+		if (Gatherer.isGsdlRemote) {
+		    String collection_name = CollectionManager.getLoadedCollectionName();
+
+		    // Perform the appropriate action based on the job type (RemoteGreenstoneServer will queue)
+		    if (type == FileJob.COPY) {
+			// Copies: upload all the files at once in one zip file
+			File[] source_files = new File[source_nodes.length];
+			for (int i = 0; i < source_nodes.length; i++) {
+			    source_files[i] = source_nodes[i].getFile();
+			}
+			RemoteGreenstoneServer.uploadFilesIntoCollection(collection_name, source_files, target_node.getFile());
+		    }
+		    else if (type == FileJob.DELETE) {
+			// Deletes: delete each top-level file/directory one at a time
+			for (int i = 0; i < source_nodes.length; i++) {
+			    RemoteGreenstoneServer.deleteCollectionFile(collection_name, source_nodes[i].getFile());
+			}
+		    }
+		    else if (type == FileJob.MOVE) {
+			// Moves: move each top-level file/directory one at a time
+			for (int i = 0; i < source_nodes.length; i++) {
+			    RemoteGreenstoneServer.moveCollectionFile(collection_name, source_nodes[i].getFile(), target_node.getFile());
+			}
+		    }
+		}
+	    }
+
+	    progress_bar.setIndeterminate(false);
+	    progress_bar.clear();
+	}
+    }
+
+
+    public void explodeMetadataDatabase(File file)
+    {
+	// This must go in a separate thread because we need the progress bar to work (remote Greenstone server)
+	new ExplodeMetadataDatabasePromptTask(file).start();
+    }
+
+
+    private class ExplodeMetadataDatabasePromptTask
+	extends Thread
+    {
+	private File metadata_database_file = null;
+
+	public ExplodeMetadataDatabasePromptTask(File metadata_database_file)
+	{
+	    this.metadata_database_file = metadata_database_file;
+	}
+
+	public void run()
+	{
+	    ExplodeMetadataDatabasePrompt emp = new ExplodeMetadataDatabasePrompt(metadata_database_file);
+	}
+    }
+
+
+    public void openFileInExternalApplication(File file)
+    {
+	// This must go in a separate thread because we need the progress bar to work (remote Greenstone server)
+	new OpenFileInExternalApplicationTask(file).start();
+    }
+
+
+    private class OpenFileInExternalApplicationTask
+	extends Thread
+    {
+	private File file = null;
+
+	public OpenFileInExternalApplicationTask(File file)
+	{
+	    this.file = file;
+	}
+
+	public void run()
+	{
+	    // If we're using a remote Greenstone server, we need to download the file before viewing it...
+	    if (Gatherer.isGsdlRemote) {
+		// ... but only if it is inside the collection and we haven't already downloaded it
+		if (file.getAbsolutePath().startsWith(Gatherer.getCollectDirectoryPath()) && file.length() == 0) {
+		    if (RemoteGreenstoneServer.downloadCollectionFile(CollectionManager.getLoadedCollectionName(), file).equals("")) {
+			// Something has gone wrong downloading the file
+			return;
+		    }
+		}
+	    }
+
+	    // View the file in an external application
+	    Gatherer.spawnApplication(file);
+	}
+    }
+
+
+    public void newDummyDoc(DragTree tree, CollectionTreeNode parent_node){
+	newFolderOrDummyDoc(tree, parent_node, FILE_TYPE);
+    }
+
+
+    public void newFolder(DragTree tree, CollectionTreeNode parent_node) {
+	newFolderOrDummyDoc(tree, parent_node, FOLDER_TYPE);
+    }
+
+
+    protected void newFolderOrDummyDoc(DragTree tree, CollectionTreeNode parent_node, int type) {
+	(new NewFolderOrDummyDocumentTask(tree, parent_node, type)).start();
+    }
+
+
+    private class NewFolderOrDummyDocumentTask
+	extends Thread
+    {
+	private DragTree tree = null;
+	private CollectionTreeNode parent_node = null;
+	private int type;
+
+	public NewFolderOrDummyDocumentTask(DragTree tree, CollectionTreeNode parent_node, int type)
+	{
+	    this.tree = tree;
+	    this.parent_node = parent_node;
+	    this.type = type;
+	}
+
+	public void run()
+	{
+	    // Ask the user for the directories name.
+	    String extension = "";
+	    if (type == FILE_TYPE) {
+		extension = ".nul";
+	    }
+
+	    NewFolderOrFilePrompt new_folder_prompt = new NewFolderOrFilePrompt(parent_node, type, extension);
+	    String name = new_folder_prompt.display();
+	    new_folder_prompt.dispose();
+	    new_folder_prompt = null;
+
+	    // And if the name is non-null...
+	    if (name != null) {
+		FileSystemModel model = (FileSystemModel) tree.getModel();
+		File folder_file = new File(parent_node.getFile(), name);
+
+		//... check if it already exists.
+		if (folder_file.exists()) { 
+		    if (type == FILE_TYPE) {
+			JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("FileActions.File_Already_Exists_No_Create", name), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
+		    }
+		    else {
+			JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("FileActions.Folder_Already_Exists", name), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
+		    }
+		}
+		// Otherwise create it.
+		else {
+		    try {
+			if (type == FILE_TYPE) {
+			    folder_file.createNewFile();
+			    if (Gatherer.isGsdlRemote) {
+				RemoteGreenstoneServer.uploadCollectionFile(CollectionManager.getLoadedCollectionName(), folder_file);
+			    }
+			}
+			else {
+			    folder_file.mkdirs();
+			    if (Gatherer.isGsdlRemote) {
+				RemoteGreenstoneServer.newCollectionDirectory(CollectionManager.getLoadedCollectionName(), folder_file);
+			    }
+			}
+
+			// Update the parent node to show the new folder
+			parent_node.refresh();
+
+			// Refresh workspace tree (collection tree is done automatically)
+			Gatherer.g_man.refreshWorkspaceTree(DragTree.COLLECTION_CONTENTS_CHANGED);
+		    }
+		    catch (Exception exception) {
+			if (type == FILE_TYPE) {
+			    JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("FileActions.File_Create_Error", name), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
+			}
+			else {
+			    JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("FileActions.Folder_Create_Error", name), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
+			}
+		    }
+		}
+		
+		folder_file = null;
+		model = null;
+	    }
+	    name = null;
+	}
+    }
+
+
+    public void renameCollectionFile(CollectionTree collection_tree, CollectionTreeNode collection_tree_node)
+    {
+	// This must go in a separate thread because we need the progress bar to work (remote Greenstone server)
+	new RenameTask(collection_tree, collection_tree_node).start();
+    }
+
+
+    private class RenameTask
+	extends Thread
+    {
+	private CollectionTree collection_tree = null;
+	private CollectionTreeNode collection_tree_node = null;
+
+	public RenameTask(CollectionTree collection_tree, CollectionTreeNode collection_tree_node)
+	{
+	    this.collection_tree = collection_tree;
+	    this.collection_tree_node = collection_tree_node;
+	}
+
+	public void run()
+	{
+	    RenamePrompt rename_prompt = new RenamePrompt(collection_tree_node);
+	    String new_collection_file_name = rename_prompt.display();
+	    rename_prompt.dispose();
+	    rename_prompt = null;
+
+	    if (new_collection_file_name != null) {
+		File collection_file = collection_tree_node.getFile();
+		File new_collection_file = new File(collection_file.getParentFile(), new_collection_file_name);
+		CollectionTreeNode new_collection_tree_node = new CollectionTreeNode(new_collection_file);
+		file_queue.addJob(System.currentTimeMillis(), collection_tree, new FileNode[] { collection_tree_node }, collection_tree, new_collection_tree_node, FileJob.RENAME);
+		if (Gatherer.isGsdlRemote) {
+		    RemoteGreenstoneServer.moveCollectionFile(CollectionManager.getLoadedCollectionName(), collection_file, new_collection_file);
+		}
+	    }
+	}
+    }
+
+    public void replaceCollectionFile(CollectionTree collection_tree, CollectionTreeNode collection_tree_node)
+    {
+	// This must go in a separate thread because we need the progress bar to work (remote Greenstone server)
+	new ReplaceTask(collection_tree, collection_tree_node).start();
+    }
+
+
+    private class ReplaceTask
+	extends Thread
+    {
+	private CollectionTree collection_tree = null;
+	private CollectionTreeNode collection_tree_node = null;
+
+	public ReplaceTask(CollectionTree collection_tree, CollectionTreeNode collection_tree_node)
+	{
+	    this.collection_tree = collection_tree;
+	    this.collection_tree_node = collection_tree_node;
+	}
+
+	public void run()
+	{
+	    JFileChooser file_chooser = new JFileChooser(startup_directory);
+	    file_chooser.setDialogTitle(Dictionary.get("ReplacePrompt.Title"));
+	    File new_file = null;
+	    int return_val = file_chooser.showOpenDialog(null);
+	    if(return_val == JFileChooser.APPROVE_OPTION) {
+		new_file = file_chooser.getSelectedFile();
+	    }
+	    
+	    if (new_file == null) {
+		return;
+	    }
+	    
+	    // save the search path for next time
+	    startup_directory = new_file.getParentFile();
+	    // make up a node for the file to bring in
+	    WorkspaceTreeNode source_node = new WorkspaceTreeNode(new_file);
+
+	    File target_directory = collection_tree_node.getFile().getParentFile();
+	    CollectionTreeNode new_collection_tree_node = new CollectionTreeNode(new File(target_directory, new_file.getName()));
+	    // copy the new file in - but don't bring metadata
+	    file_queue.addJob(System.currentTimeMillis(), Gatherer.g_man.gather_pane.workspace_tree, new FileNode[] { source_node }, collection_tree, (FileNode)collection_tree_node.getParent(),  FileJob.COPY_FILE_ONLY);
+	    if (Gatherer.isGsdlRemote) {
+		RemoteGreenstoneServer.uploadFilesIntoCollection(CollectionManager.getLoadedCollectionName(), new File[] { new_file }, target_directory);
+	    }
+	    // do a replace of old file with new file
+	    file_queue.addJob(System.currentTimeMillis(), collection_tree, new FileNode[] { collection_tree_node }, collection_tree, new_collection_tree_node, FileJob.REPLACE);
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileNode.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileNode.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileNode.java	(revision 13928)
@@ -0,0 +1,348 @@
+package org.greenstone.gatherer.file;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import javax.swing.*;
+import javax.swing.filechooser.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.util.ArrayTools;
+
+
+public abstract class FileNode
+    implements MutableTreeNode
+{
+    protected boolean allows_children = true;
+    protected ArrayList child_nodes = null;
+    protected ArrayList child_nodes_unfiltered = null;
+    protected File file = null;
+    protected FileSystemModel model = null;
+    protected MutableTreeNode parent = null;
+
+
+    public FileNode(File file)
+    {
+	this.file = file;
+
+	// Files cannot have children
+	if (file != null && file.isFile()) {
+	    // Cache this result to prevent unceasing missing disk messages being thrown if the
+	    // removable media was, um, removed after directory mapped
+	    this.allows_children = false;
+	}
+    }
+
+
+    /** Returns the children of the node as an Enumeration. */
+    public Enumeration children()
+    {
+	return new FileEnumeration();
+    }
+
+
+    /** Returns true if the receiver allows children.  */
+    public boolean getAllowsChildren()
+    {
+	return allows_children;
+    }
+
+
+    /** Returns the child TreeNode at index childIndex. */
+    public TreeNode getChildAt(int index)
+    {
+	return (TreeNode) child_nodes.get(index);
+    }
+
+
+    /** Returns the number of children TreeNodes the receiver contains. */
+    public int getChildCount()
+    {
+	map();
+
+	// Use the number of (filtered) child nodes
+	if (child_nodes != null) {
+	    return child_nodes.size();
+	}
+
+	return 0;
+    }
+
+
+    /** Returns the index of node in the receivers children. */
+    public int getIndex(TreeNode node)
+    {
+	if (child_nodes != null) {
+	    return child_nodes.indexOf(node);
+	}
+
+	return -1;
+    }
+
+
+    /** Returns the parent TreeNode of the receiver. */
+    public TreeNode getParent()
+    {
+	return parent;
+    }
+
+
+    /** Adds child to the receiver at index. */
+    public void insert(MutableTreeNode child, int index)
+    {
+	DebugStream.println("Insert " + child + " in " + this + " at index " + index + " [Model: " + model + "]");
+	if (child == null) {
+	    return;
+	}
+
+	try {
+	    FileNode child_node = (FileNode) child;
+	    child_nodes.add(index, child_node);
+	    child_node.model = model;
+	    child_node.parent = this;
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+    }
+
+
+    /** Returns true if the receiver is a leaf. */
+    public boolean isLeaf()
+    {
+	return (allows_children == false);
+    }
+
+
+    /** Removes the child at index from the receiver. */
+    public void remove(int index)
+    {
+	if (index >= 0 && index < child_nodes.size()) {
+	    child_nodes.remove(index);
+	}
+    }
+
+
+    /** Removes node from the receiver. */
+    public void remove(MutableTreeNode node)
+    {
+	remove(getIndex(node));
+    }
+
+
+    /** Removes the receiver from its parent. */
+    public void removeFromParent()
+    {
+	parent.remove(this);
+	parent = null;
+    }
+
+
+    /** Resets the user object of the receiver to object. */
+    public void setUserObject(Object object) {
+	try {
+	    file = (File) object;
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+    }
+
+
+    // -------------------------------------------------------------------------------
+
+
+    public void add(MutableTreeNode child)
+    {
+	insert(child, child_nodes.size());
+    }
+
+
+    protected abstract FileNode addChildNode(File file);
+
+
+    /** Compare two FileNodes for equality. */
+    public boolean equals(FileNode node)
+    {
+	if (node == null) {
+	    // Definitely not a match
+	    return false;
+	}
+
+	if (file != null) {
+	    return file.equals(node.getFile());
+	}
+	else {
+	    return toString().equals(node.toString());
+	}
+    }
+
+
+    /** Retrieve the file node at the given index, regardless of filters set. */
+    public FileNode getChildAtUnfiltered(int index)
+    {
+ 	if (index >= 0 && index < size()) {
+ 	    return (FileNode) child_nodes_unfiltered.get(index);
+ 	}
+ 	return null;
+    }
+
+
+    public File getFile() {
+	return file;
+    }
+
+
+    /** Retrieves the tree path from the root node to this node. */
+    public TreeNode[] getPath() {
+	int count = 0;
+	TreeNode current = this;
+	while(current != null) {
+	    count++;
+	    current = current.getParent();
+	}
+	TreeNode[] path = new TreeNode[count];
+	current = this;
+	while(current != null) {
+	    path[count - 1] = current;
+	    count--;
+	    current = current.getParent();
+	}
+	return path;
+    }
+
+
+    public boolean isFileSystemRoot() {
+	if (file != null) {
+	    return FileSystemView.getFileSystemView().isFileSystemRoot(file);
+	}
+	else {
+	    return false;
+	}
+    }
+
+
+    /** Overridden if necessary by subclasses. */
+    public boolean isInLoadedCollection()
+    {
+	return false;
+    }
+
+
+    /** Overridden if necessary by subclasses. */
+    public boolean isReadOnly()
+    {
+	return false;
+    }
+
+
+    public void map()
+    {
+	// If this node has already been mapped, don't bother doing it again
+	if (child_nodes != null) {
+	    return;
+	}
+	child_nodes = new ArrayList();
+
+	// General case, only map if children are allowed
+	if (file != null && getAllowsChildren()) {
+	    File[] files = file.listFiles();
+	    if (files != null && files.length > 0) {
+		// Sort the child files
+		ArrayTools.sort(files);
+
+		// Now add them to child_nodes_unfiltered
+		child_nodes_unfiltered = new ArrayList();
+		for (int i = 0; i < files.length; i++) {
+		    FileNode child_node = this.addChildNode(files[i]);
+		    child_nodes_unfiltered.add(child_node);
+		}
+
+		// Apply the filters set in the model
+		FileFilter[] filters = model.getFilters();
+		for (int i = 0; filters != null && i < filters.length; i++) {
+		    files = ArrayTools.filter(files, filters[i].filter, filters[i].exclude);
+		}
+
+		// Add the files left after filtering to child_nodes
+		for (int i = 0, j = 0; (i < child_nodes_unfiltered.size() && j < files.length); i++) {
+		    // Use the FileNode object in child_nodes_unfiltered rather than creating another
+		    FileNode file_node = (FileNode) child_nodes_unfiltered.get(i);
+		    if (file_node.getFile().equals(files[j])) {
+			child_nodes.add(file_node);
+			j++;
+		    }
+		}
+	    }
+
+	    model.nodeStructureChanged(this);
+	}
+    }
+
+
+    public void refresh()
+    {
+  	unmap();
+  	map();
+    }
+
+
+    public void setModel(FileSystemModel model) {
+	this.model = model;
+    }
+
+    public void setParent(MutableTreeNode parent) {
+	this.parent = parent;
+    }
+
+
+    /** Return the total number of child files for the file this node represents, irrespective of filters set. */
+    public int size() {
+	if (child_nodes_unfiltered != null) {
+	    return child_nodes_unfiltered.size();
+	}
+	return 0;
+    }
+
+
+    public String toString()
+    {
+	if (isFileSystemRoot()) {
+	    return file.getAbsolutePath();
+	}
+	else {
+	    return file.getName();
+	}
+    }
+
+
+    /** Unmap this node's children. */
+    public void unmap()
+    {
+	DebugStream.println("Unmapping " + this + "...");
+	child_nodes_unfiltered = null;
+	child_nodes = null;
+    }
+
+
+    private class FileEnumeration
+	implements Enumeration
+    {
+	private int index = 0;
+
+	/** Tests if this enumeration contains more elements. */
+	public boolean hasMoreElements() {
+	    return (index < child_nodes.size());
+	}
+
+	/** Returns the next element of this enumeration if this enumeration object has at least one more element to provide. */
+	public Object nextElement() {
+	    Object result = null;
+	    if (index < child_nodes.size()) {
+		result = child_nodes.get(index);
+		index++;
+	    }
+	    return result;
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileOpenActionListener.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileOpenActionListener.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileOpenActionListener.java	(revision 13928)
@@ -0,0 +1,101 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.file;
+
+import java.awt.event.*;
+import java.io.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Gatherer;
+
+/** This class listens for mouse clicks and responds to double-clicks (spawn a new application to view the selected file) and right mouse button clicks (popup menu). 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3b
+ */
+public class FileOpenActionListener
+    extends MouseAdapter 
+    implements TreeExpansionListener {
+    /** This flag gets toggled to <i>true</i> if the listener determines that the next mouse clicked event it will recieve is actually caused by the tree expanding or collapsing. */
+    private boolean ignore = false;
+    /** The constructor. */
+    public FileOpenActionListener() {
+    }
+    /** Any subclass of MouseAdapter can override this method to respond to mouse click events. In this case we want to start an external application if someone double clicks on an appropriate file record. 
+     * @param event A <strong>MouseEvent</strong> containing further information about the mouse click performed.
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.file.FileNode
+     * @see org.greenstone.gatherer.gui.tree.DragTree
+     */ 
+    public void mouseClicked(MouseEvent event) {
+	///ystem.err.println("Mouse clicked");
+	if(!ignore) {
+	    if(event.getClickCount() >= 2) {
+		// Find the file we're clicking on.
+		JTree tree = (JTree)event.getSource();
+		TreePath path = tree.getClosestPathForLocation(event.getX(), event.getY());
+		if(path != null) {
+		    FileNode record = (FileNode)path.getLastPathComponent();
+		    ///ystem.err.println("Double clicked on " + record);
+		    File file = record.getFile();
+		    if (file != null && file.isFile()) {
+			///ystem.err.println("Running " + file);
+			Gatherer.f_man.openFileInExternalApplication(file);
+		    }
+		}
+	    }
+	}
+	else {
+	    ///ystem.err.println("Caused by tree expansion / collapse. Ignoring.");
+	    ignore = false;
+	}
+    }
+    /** Any implementation of TreeExpansionListener must include this method so that we can be informed when a tree node has been collapsed, thus indicating that any mouse click events about to be recieved are most likely related to this event.
+     * @param event A <strong>TreeExpansionEvent</strong> containing information about the node collapsed.
+     */
+    public void treeCollapsed(TreeExpansionEvent event) {
+	///ystem.err.println("Tree Collapsed");
+	ignore = true;
+    }
+    /** Any implementation of TreeExpansionListener must include this method so that we can be informed when a tree node has been expanded, thus indicating that any mouse click events about to be recieved are most likely related to this event.
+     * @param event A <strong>TreeExpansionEvent</strong> containing information about the node expanded.
+     */
+    public void treeExpanded(TreeExpansionEvent event) {
+	///ystem.err.println("Tree Expanded");
+	ignore = true;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileQueue.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileQueue.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileQueue.java	(revision 13928)
@@ -0,0 +1,836 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.file;
+
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.CollectionTreeNode;
+import org.greenstone.gatherer.gui.GProgressBar;
+import org.greenstone.gatherer.gui.tree.DragTree;
+import org.greenstone.gatherer.metadata.MetadataValue;
+import org.greenstone.gatherer.metadata.MetadataXMLFileManager;
+import org.greenstone.gatherer.util.DragComponent;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.SynchronizedTreeModelTools;
+import org.greenstone.gatherer.util.Utility;
+
+/** A threaded object which processes a queue of file actions such as copying and movement. It also handles updating the various trees involved so they are an accurate representation of the file system they are meant to match.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class FileQueue
+    extends Thread
+{
+    /** The size of the io buffer, in bytes. */
+    static final private int BUFFER_SIZE = 1024;
+
+    /** When someone requests the movement queue to be dumped this cancel flag is set to true. */
+    private boolean cancel_action = false;
+    /** The button which controls the stopping of the file queue. */
+    private JButton stop_button = null;
+    /** true if the user has selected yes to all from a file 'clash' dialog. */
+    private boolean yes_to_all = false;
+    /** A label explaining the current moving files status. */
+    private JLabel file_status = null;
+    /** A list containing a queue of waiting movement jobs. */
+    private ArrayList queue = null;
+    /** A progress bar which shows how many bytes, out of the total size of bytes, has been moved. */
+    private GProgressBar progress = null;
+
+
+    /** Constructor.
+     */
+    public FileQueue() {
+	DebugStream.println("FileQueue started.");
+	this.queue = new ArrayList();
+	file_status = new JLabel(Dictionary.get("FileActions.No_Activity"));
+	progress = new GProgressBar();
+	progress.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+	progress.setForeground(Configuration.getColor("coloring.collection_tree_foreground", false));
+	progress.setString(Dictionary.get("FileActions.No_Activity"));
+	progress.setStringPainted(true);
+    }
+
+
+    /** Add a new job to the queue, specifiying as many arguments as is necessary to complete this type of job (ie delete needs no target information).
+     * @param id A long id unique to all jobs created by a single action.
+     * @param source The DragComponent source of this file, most likely a DragTree.
+     * @param child The FileNode you wish to mode.
+     * @param target The DragComponent to move the file to, again most likely a DragTree.
+     * @param parent The files new FileNode parent within the target.
+     * @param type The type of this movement as an int, either COPY or DELETE.
+     */
+    public void addJob(long id, DragComponent source, FileNode[] children, DragComponent target, FileNode parent, byte type)
+    {
+	// Queue the sub-job(s) (this may fail if we are asked to delete a read only file)
+	for (int i = 0; i < children.length; i++) {
+	    addJob(id, source, children[i], target, parent, type, -1);
+	}
+    }
+    
+    synchronized private void addJob(long id, DragComponent source, FileNode child, DragComponent target, FileNode parent, byte type, int position) {
+ 	FileJob job = new FileJob(id, source, child, target, parent, type);
+	DebugStream.println("Adding job: " + job);
+ 	if(position != -1 && position <= queue.size() + 1) {
+ 	    queue.add(position, job);
+ 	}
+ 	else {
+	    queue.add(job);
+ 	}
+ 	notify();
+    }
+
+    /** Calculates the total deep file size of the selected file nodes.
+     * @param files a FileNode[] of selected files
+     * @return true if a cancel was signalled, false otherwise
+     * @see org.greenstone.gatherer.file.FileManager.Task#run()
+     */
+    public boolean calculateSize(FileNode[] files)
+    {
+	file_status.setText(Dictionary.get("FileActions.Calculating_Size"));
+	progress.setString(Dictionary.get("FileActions.Calculating_Size"));
+
+	// Calculate the total file size of all the selected file nodes
+	Vector remaining = new Vector();
+	for (int i = 0; !cancel_action && i < files.length; i++) {
+	    remaining.add(files[i]);
+	}
+	while (!cancel_action && remaining.size() > 0) {
+	    FileNode node = (FileNode) remaining.remove(0);
+	    if (node.isLeaf()) {
+		progress.addMaximum(node.getFile().length());
+	    }
+	    else {
+		for (int i = 0; !cancel_action && i < node.getChildCount(); i++) {
+		    remaining.add(node.getChildAt(i));
+		}
+	    }
+	}
+
+	// Now we return if calculation was cancelled so that the FileManagers Task can skip the addJob phase correctly.
+	if (cancel_action) {
+	    cancel_action = false; // reset
+	    return true;
+	}
+	else {
+	    return false;
+	}
+    }
+
+    /** This method is called to cancel the job queue at the next available moment. */
+    public void cancelAction() {
+	cancel_action = true;
+	clearJobs();
+    }
+
+
+    /** Format the given filename path string so that it is no longer than the given width. If it is wider replace starting directories with ...
+     * @param key The key <strong>String</Strong> used to retrieve a phrase from the dictionary for this item.
+     * @param raw The raw filename path <strong>String</strong>.
+     * @param width The maximum width as an <i>int</i>.
+     * @return A path <strong>String</strong> no longer than width.
+     */
+    private String formatPath(String key, String raw, int width)
+    {
+	JLabel label = new JLabel(Dictionary.get(key, raw));
+	int position = -1;
+	while(label.getPreferredSize().width > width && (position = raw.indexOf(File.separator)) != -1) {
+	    raw = "..." + raw.substring(position + 1);
+	    label.setText(Dictionary.get(key, raw));
+	}
+	if(raw.indexOf(File.separator) == -1 && raw.startsWith("...")) {
+	    raw = raw.substring(3);
+	}
+	return raw;
+    }
+
+
+    /** Access to the file state label. */
+    public JLabel getFileStatus() {
+	return file_status;
+    }
+
+    /** Access to the progress bar. */
+    public GProgressBar getProgressBar() {
+	return progress;
+    }
+
+
+    synchronized private void addFileJob(long id, DragComponent source, FileNode child, DragComponent target, FileNode parent, byte type)
+    {
+	queue.add(new FileJob(id, source, child, target, parent, type));
+	notify();
+    }
+
+
+    private void doEmptyDirectoryDelete(FileJob file_job)
+    {
+	FileNode source_node = file_job.getOrigin();
+	File source_directory = source_node.getFile();
+
+	// If the directory isn't empty then this will fail
+	if (source_directory.delete() == false) {
+	    // The source directory couldn't be deleted, so give the user the option of continuing or cancelling
+	    if (showErrorDialog(Dictionary.get("FileActions.Could_Not_Delete", source_directory.getAbsolutePath())) == JOptionPane.CANCEL_OPTION) {
+		clearJobs();  // Aborting action
+	    }
+	    return;
+	}
+
+	// Remove the node from the model
+	SynchronizedTreeModelTools.removeNodeFromParent(file_job.source.getTreeModel(), source_node);
+    }
+
+
+    private void doDirectoryDelete(FileJob file_job)
+    {
+	FileNode source_node = file_job.getOrigin();
+	File source_directory = source_node.getFile();
+
+	// The last thing we will do is delete this directory (which should be empty by then)
+	addFileJob(file_job.ID(), file_job.source, source_node, null, null, FileJob.DELETE_EMPTY_DIRECTORY);
+
+	// Add a new Delete job for each child of this directory (except metadata.xml files)
+	source_node.refresh();
+	for (int i = 0; i < source_node.size(); i++) {
+	    FileNode child_file_node = (FileNode) source_node.getChildAtUnfiltered(i);
+	    if (!child_file_node.getFile().getName().equals(StaticStrings.METADATA_XML)) {
+		addFileJob(file_job.ID(), file_job.source, child_file_node, null, null, FileJob.DELETE);
+	    }
+	}
+
+	// Treat metadata.xml files specially: delete them first
+	for (int i = 0; i < source_node.size(); i++) {
+	    FileNode child_file_node = (FileNode) source_node.getChildAtUnfiltered(i);
+	    if (child_file_node.getFile().getName().equals(StaticStrings.METADATA_XML)) {
+		addFileJob(file_job.ID(), file_job.source, child_file_node, null, null, FileJob.DELETE);
+		break;
+	    }
+	}
+    }
+
+
+    private void doDirectoryCopy(FileJob file_job)
+    {
+	FileNode source_node = file_job.getOrigin();
+	FileNode target_node = file_job.getDestination();
+
+	File source_directory = source_node.getFile();
+	File target_directory = new File(target_node.getFile(), source_directory.getName());
+
+	// Check that the source directory doesn't contain the target directory (will create a cyclic loop)
+	if (target_directory.getAbsolutePath().startsWith(source_directory.getAbsolutePath())) {
+	    if (showErrorDialog(Dictionary.get("FileActions.Cyclic_Path", source_directory.getName())) == JOptionPane.CANCEL_OPTION) {
+		clearJobs();  // Aborting action
+	    }
+	    return;
+	}
+
+	// The target directory shouldn't already exist
+	if (target_directory.exists()) {
+	    if (showErrorDialog(Dictionary.get("FileActions.Folder_Already_Exists", target_directory.getAbsolutePath())) == JOptionPane.CANCEL_OPTION) {
+		clearJobs();  // Aborting action
+	    }
+	    return;
+	}
+	target_directory.mkdirs();
+
+	// Create a node for the new directory in the collection tree
+	FileSystemModel target_model = (FileSystemModel) file_job.target.getTreeModel();
+	CollectionTreeNode new_target_node = new CollectionTreeNode(target_directory);
+	SynchronizedTreeModelTools.insertNodeInto(target_model, target_node, new_target_node);
+	new_target_node.setParent(target_node);
+
+	// Copy the non-folder level metadata assigned to the original directory to the new directory
+	ArrayList assigned_metadata = MetadataXMLFileManager.getMetadataAssignedDirectlyToExternalFile(source_directory);
+	MetadataXMLFileManager.addMetadata((CollectionTreeNode) new_target_node, assigned_metadata);
+
+	// Add a new Copy job for each child of this directory (except metadata.xml files)
+	source_node.refresh();
+	for (int i = 0; i < source_node.size(); i++) {
+	    FileNode child_file_node = (FileNode) source_node.getChildAtUnfiltered(i);
+	    if (!child_file_node.getFile().getName().equals(StaticStrings.METADATA_XML)) {
+		addFileJob(file_job.ID(), file_job.source, child_file_node, file_job.target, new_target_node, FileJob.COPY);
+	    }
+	}
+    }
+
+
+    private void doDirectoryMove(FileJob file_job)
+    {
+	FileNode source_node = file_job.getOrigin();
+	FileNode target_node = file_job.getDestination();
+
+	File source_directory = source_node.getFile();
+	File target_directory = new File(target_node.getFile(), source_directory.getName());
+	if (file_job.type == FileJob.RENAME) {
+	    // This is the only difference between moves and renames
+	    target_directory = target_node.getFile();
+	    target_node = (FileNode) source_node.getParent();
+	}
+
+	// Check the target directory isn't the source directory
+	if (target_directory.equals(source_directory)) {
+	    DebugStream.println("Target directory is the source directory!");
+	    return;
+	}
+
+	// The target directory shouldn't already exist
+	if (target_directory.exists()) {
+	    if (showErrorDialog(Dictionary.get("FileActions.Folder_Already_Exists", target_directory.getAbsolutePath())) == JOptionPane.CANCEL_OPTION) {
+		clearJobs();  // Aborting action
+	    }
+	    return;
+	}
+	target_directory.mkdirs();
+
+	// Create a node for the new directory in the collection tree
+	FileSystemModel target_model = (FileSystemModel) file_job.target.getTreeModel();
+	CollectionTreeNode new_target_node = new CollectionTreeNode(target_directory);
+	SynchronizedTreeModelTools.insertNodeInto(target_model, target_node, new_target_node);
+	new_target_node.setParent(target_node);
+
+	// Move the folder level metadata assigned to the original directory to the new directory
+	ArrayList assigned_metadata = MetadataXMLFileManager.getMetadataAssignedDirectlyToFile(source_directory);
+	MetadataXMLFileManager.removeMetadata((CollectionTreeNode) source_node, assigned_metadata);
+	MetadataXMLFileManager.addMetadata((CollectionTreeNode) new_target_node, assigned_metadata);
+
+	// The last thing we will do is delete this directory
+	addFileJob(file_job.ID(), file_job.source, source_node, null, null, FileJob.DELETE);
+
+	// Treat metadata.xml files specially: delete them last
+	source_node.refresh();
+	for (int i = 0; i < source_node.size(); i++) {
+	    FileNode child_file_node = (FileNode) source_node.getChildAtUnfiltered(i);
+	    if (child_file_node.getFile().getName().equals(StaticStrings.METADATA_XML)) {
+		addFileJob(file_job.ID(), file_job.source, child_file_node, null, null, FileJob.DELETE);
+		break;
+	    }
+	}
+
+	// Add a new Move job for each child of this directory (except metadata.xml files)
+	for (int i = 0; i < source_node.size(); i++) {
+	    FileNode child_file_node = (FileNode) source_node.getChildAtUnfiltered(i);
+	    if (!child_file_node.getFile().getName().equals(StaticStrings.METADATA_XML)) {
+		addFileJob(file_job.ID(), file_job.source, child_file_node, file_job.target, new_target_node, FileJob.MOVE);
+	    }
+	}
+    }
+
+
+    private void doFileDelete(FileJob file_job)
+    {
+	FileNode source_node = file_job.getOrigin();
+	File source_file = source_node.getFile();
+
+	// Almost all files will be deleted from the collection tree (exception: files in "Downloaded Files")
+	if (source_node instanceof CollectionTreeNode) {
+	    // If we're deleting a metadata.xml file we must unload it
+	    boolean metadata_xml_file = source_file.getName().equals(StaticStrings.METADATA_XML);
+	    if (metadata_xml_file) {
+		MetadataXMLFileManager.unloadMetadataXMLFile(source_file);
+	    }
+	    // Otherwise remove any metadata assigned directly to the file
+	    else {
+		ArrayList assigned_metadata = MetadataXMLFileManager.getMetadataAssignedDirectlyToFile(source_file);
+		MetadataXMLFileManager.removeMetadata((CollectionTreeNode) source_node, assigned_metadata);
+	    }
+	}
+
+	// Delete the source file
+	if (!Utility.delete(source_file)) {
+	    // The source file couldn't be deleted, so give the user the option of continuing or cancelling
+	    if (showErrorDialog(Dictionary.get("FileActions.File_Not_Deleted_Message", source_file.getAbsolutePath())) == JOptionPane.CANCEL_OPTION) {
+		clearJobs();  // Aborting action
+	    }
+	    return;
+	}
+
+	// Remove the node from the model
+	SynchronizedTreeModelTools.removeNodeFromParent(file_job.source.getTreeModel(), source_node);
+    }
+
+
+    private void doFileCopy(FileJob file_job)
+    {
+	FileNode source_node = file_job.getOrigin();
+	FileNode target_node = file_job.getDestination();
+
+	File source_file = source_node.getFile();
+	File target_file = new File(target_node.getFile(), source_file.getName());
+
+	// The target file shouldn't already exist -- if it does ask the user whether they want to overwrite
+	boolean overwrite_file = false;
+	if (target_file.exists()) {
+	    int result = showOverwriteDialog(target_file.getName());
+	    if (result == JOptionPane.NO_OPTION) {
+		// Don't overwrite
+		return;
+	    }
+	    if (result == JOptionPane.CANCEL_OPTION) {
+		clearJobs();  // Aborting action
+		return;
+	    }
+
+	    overwrite_file = true;
+	}
+
+	// Copy the file
+	try {
+	    copyFile(source_file, target_file, true);
+	}
+	catch (FileAlreadyExistsException exception) {
+	    // This should not ever happen, since we've called copyFile with overwrite set
+	    DebugStream.printStackTrace(exception);
+	    return;
+	}
+	catch (FileNotFoundException exception) {
+	    DebugStream.printStackTrace(exception);
+	    if (showErrorDialog(Dictionary.get("FileActions.File_Not_Found_Message", source_file.getAbsolutePath())) == JOptionPane.CANCEL_OPTION) {
+		clearJobs();  // Aborting action
+	    }
+	    // Refresh the source tree model
+	    FileSystemModel source_model = file_job.source.getTreeModel();
+	    source_model.refresh(new TreePath(((FileNode) file_job.getOrigin().getParent()).getPath()));
+	    return;
+	}
+	catch (InsufficientSpaceException exception) {
+	    DebugStream.printStackTrace(exception);
+	    if (showErrorDialog(Dictionary.get("FileActions.Insufficient_Space_Message", exception.getMessage())) == JOptionPane.CANCEL_OPTION) {
+		clearJobs();  // Aborting action
+	    }
+	    return;
+	}
+	catch (IOException exception) {
+	    DebugStream.printStackTrace(exception);
+	    if (showErrorDialog(exception.getMessage()) == JOptionPane.CANCEL_OPTION) {
+		clearJobs();  // Aborting action
+	    }
+	    return;
+	}
+	catch (ReadNotPermittedException exception) {
+	    DebugStream.printStackTrace(exception);
+	    if (showErrorDialog(Dictionary.get("FileActions.Read_Not_Permitted_Message", source_file.getAbsolutePath())) == JOptionPane.CANCEL_OPTION) {
+		clearJobs();  // Aborting action
+	    }
+	    return;
+	}
+	catch (UnknownFileErrorException exception) {
+	    DebugStream.printStackTrace(exception);
+	    if (showErrorDialog(Dictionary.get("FileActions.Unknown_File_Error_Message")) == JOptionPane.CANCEL_OPTION) {
+		clearJobs();  // Aborting action
+	    }
+	    return;
+	}
+	catch (WriteNotPermittedException exception) {
+	    DebugStream.printStackTrace(exception);
+	    if (showErrorDialog(Dictionary.get("FileActions.Write_Not_Permitted_Message", target_file.getAbsolutePath())) == JOptionPane.CANCEL_OPTION) {
+		clearJobs();  // Aborting action
+	    }
+	    return;
+	}
+
+	CollectionTreeNode new_target_node = new CollectionTreeNode(target_file);
+	if (overwrite_file == false) {
+	    // Add the new node into the tree
+	    FileSystemModel target_model = file_job.target.getTreeModel();
+	    SynchronizedTreeModelTools.insertNodeInto(target_model, target_node, new_target_node);
+	}
+	Gatherer.c_man.fireFileAddedToCollection(target_file);
+
+	// Copy the non-folder level metadata assigned to the original file to the new file
+	if (file_job.type == FileJob.COPY) {
+	    // do metadata too
+	    ArrayList assigned_metadata = MetadataXMLFileManager.getMetadataAssignedDirectlyToExternalFile(source_file);
+	    MetadataXMLFileManager.addMetadata((CollectionTreeNode) new_target_node, assigned_metadata);
+	}
+    }
+
+
+    private void doFileMove(FileJob file_job)
+    {
+	FileNode source_node = file_job.getOrigin();
+	FileNode target_node = file_job.getDestination();
+
+	File source_file = source_node.getFile();
+	File target_file = new File(target_node.getFile(), source_file.getName());
+	if (file_job.type == FileJob.RENAME) {
+	    // This is the only difference between moves and renames
+	    target_file = target_node.getFile();
+	    target_node = (FileNode) source_node.getParent();
+	}
+
+	// Check the target file isn't the source file
+	if (target_file.equals(source_file)) {
+	    DebugStream.println("Target file is the source file!");
+	    return;
+	}
+
+	// The target file shouldn't already exist
+	if (target_file.exists()) {
+	    int result = showOverwriteDialog(target_file.getName());
+	    if (result == JOptionPane.NO_OPTION) {
+		// Don't overwrite
+		return;
+	    }
+	    if (result == JOptionPane.CANCEL_OPTION) {
+		clearJobs();  // Aborting action
+		return;
+	    }
+	}
+
+	// Move the file by renaming it
+	if (!source_file.renameTo(target_file)) {
+	    String args[] = { source_file.getName(), target_file.getAbsolutePath() };
+	    if (showErrorDialog(Dictionary.get("FileActions.File_Move_Error_Message", args)) == JOptionPane.CANCEL_OPTION) {
+		clearJobs();  // Aborting action
+	    }
+	    return;
+	}
+
+	// Remove the node from the source model and add it to the target model
+	SynchronizedTreeModelTools.removeNodeFromParent(file_job.source.getTreeModel(), source_node);
+	CollectionTreeNode new_target_node = new CollectionTreeNode(target_file);
+	FileSystemModel target_model = file_job.target.getTreeModel();
+	SynchronizedTreeModelTools.insertNodeInto(target_model, target_node, new_target_node);
+
+	// Move the non-folder level metadata assigned to the original file to the new file
+	ArrayList assigned_metadata = MetadataXMLFileManager.getMetadataAssignedDirectlyToFile(source_file);
+	MetadataXMLFileManager.removeMetadata((CollectionTreeNode) source_node, assigned_metadata);
+	MetadataXMLFileManager.addMetadata((CollectionTreeNode) new_target_node, assigned_metadata);
+    }
+
+    
+    /** all this does is move the metadata, and delete the source */
+    private void doFileReplace(FileJob file_job)
+    {
+	FileNode source_node = file_job.getOrigin();
+	FileNode target_node = file_job.getDestination();
+
+	File source_file = source_node.getFile();
+	File target_file = target_node.getFile();
+
+	// Move the non-folder level metadata assigned to the original file to the new file
+	CollectionTreeNode new_target_node = new CollectionTreeNode(target_file);
+	ArrayList assigned_metadata = MetadataXMLFileManager.getMetadataAssignedDirectlyToFile(source_file);
+	MetadataXMLFileManager.removeMetadata((CollectionTreeNode) source_node, assigned_metadata);
+	MetadataXMLFileManager.addMetadata((CollectionTreeNode) new_target_node, assigned_metadata);
+
+	// now delete the original
+	doFileDelete(file_job);
+    }
+
+
+    private void processFileJob(FileJob file_job)
+    {
+	DebugStream.println("Processing file job " + file_job + "...");
+
+	// Ensure that the source file exists
+	File source_file = file_job.getOrigin().getFile();
+	if (!source_file.exists()) {
+	    // The source file doesn't exist, so give the user the option of continuing or cancelling
+	    if (showErrorDialog(Dictionary.get("FileActions.File_Not_Found_Message", source_file.getAbsolutePath())) == JOptionPane.CANCEL_OPTION) {
+		clearJobs();  // Aborting action
+	    }
+	    // Refresh the source tree model
+	    FileSystemModel source_model = file_job.source.getTreeModel();
+	    source_model.refresh(new TreePath(((FileNode) file_job.getOrigin().getParent()).getPath()));
+	    return;
+	}
+
+	// Enable the "Stop" button
+	stop_button.setEnabled(true);
+
+	// Delete empty directory job
+	if (file_job.type == FileJob.DELETE_EMPTY_DIRECTORY) {
+	    file_status.setText(Dictionary.get("FileActions.Deleting", formatPath("FileActions.Deleting", source_file.getAbsolutePath(), file_status.getSize().width)));
+	    doEmptyDirectoryDelete(file_job);
+	    return;
+	}
+
+	// Delete job
+	if (file_job.type == FileJob.DELETE) {
+	    file_status.setText(Dictionary.get("FileActions.Deleting", formatPath("FileActions.Deleting", source_file.getAbsolutePath(), file_status.getSize().width)));
+	    if (source_file.isFile()) {
+		long source_file_size = source_file.length();
+		doFileDelete(file_job);
+		progress.addValue(source_file_size);  // Update progress bar
+	    }
+	    else {
+		doDirectoryDelete(file_job);
+	    }
+	    return;
+	}
+
+	// Copy job
+	if (file_job.type == FileJob.COPY || file_job.type == FileJob.COPY_FILE_ONLY) {
+	    file_status.setText(Dictionary.get("FileActions.Copying", formatPath("FileActions.Copying", source_file.getAbsolutePath(), file_status.getSize().width)));
+	    if (source_file.isFile()) {
+		long source_file_size = source_file.length();
+		doFileCopy(file_job);
+		progress.addValue(source_file_size);  // Update progress bar
+	    }
+	    else {
+		doDirectoryCopy(file_job);
+	    }
+	    return;
+	}
+
+	// Move (or rename) job
+	if (file_job.type == FileJob.MOVE || file_job.type == FileJob.RENAME) {
+	    file_status.setText(Dictionary.get("FileActions.Moving", formatPath("FileActions.Moving", source_file.getAbsolutePath(), file_status.getSize().width)));
+	    if (source_file.isFile()) {
+		long source_file_size = source_file.length();
+		doFileMove(file_job);
+		progress.addValue(source_file_size);  // Update progress bar
+	    }
+	    else {
+		doDirectoryMove(file_job);
+	    }
+	    return;
+	}
+
+	// Replace job
+	if (file_job.type == FileJob.REPLACE) {
+	    file_status.setText(Dictionary.get("FileActions.Replacing", formatPath("FileActions.Replacing", source_file.getAbsolutePath(), file_status.getSize().width)));
+	    doFileReplace(file_job);
+	    return;
+	}
+    }
+
+
+    private int showErrorDialog(String error_message)
+    {
+	Object[] options = { Dictionary.get("General.OK"), Dictionary.get("General.Cancel") };
+	int result = JOptionPane.showOptionDialog(Gatherer.g_man, error_message, Dictionary.get("General.Error"), JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE, null, options, options[0]);
+	if (result == 0) {
+	    return JOptionPane.OK_OPTION;
+	}
+	else {
+	    return JOptionPane.CANCEL_OPTION;
+	}
+    }
+
+
+    private int showOverwriteDialog(String target_file_name)
+    {
+	// Has "yes to all" been set?
+	if (yes_to_all) {
+	    return JOptionPane.YES_OPTION;
+	}
+
+	Object[] options = { Dictionary.get("General.Yes"), Dictionary.get("FileActions.Yes_To_All"), Dictionary.get("General.No"), Dictionary.get("General.Cancel") };
+	int result = JOptionPane.showOptionDialog(Gatherer.g_man, Dictionary.get("FileActions.File_Exists", target_file_name), Dictionary.get("General.Warning"), JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options[0]);
+	if (result == 0) {
+	    return JOptionPane.YES_OPTION;
+	}
+	else if (result == 1) {
+	    yes_to_all = true;
+	    return JOptionPane.YES_OPTION;
+	}
+	else if (result == 2) {
+	    return JOptionPane.NO_OPTION;
+	}
+	else {
+	    return JOptionPane.CANCEL_OPTION;
+	}
+    }
+
+
+    public void run()
+    {
+	super.setName("FileQueue");
+
+	while (!Gatherer.exit) {
+	    // Retrieve the next job
+	    int position = queue.size() - 1;
+	    if (position >= 0) {
+		// We have a file job, so process it
+		processFileJob((FileJob) queue.remove(position));
+	    }
+	    else {
+		// No jobs, so reset and wait until we are notified of one
+		synchronized(this) {
+		    // Force both workspace and collection trees to refresh
+		    if (Gatherer.g_man != null && Gatherer.c_man.ready()) {
+			Gatherer.g_man.refreshWorkspaceTree(DragTree.COLLECTION_CONTENTS_CHANGED);
+			// Gatherer.g_man.refreshCollectionTree(DragTree.COLLECTION_CONTENTS_CHANGED);
+		    }
+
+		    // Reset status area
+		    file_status.setText(Dictionary.get("FileActions.No_Activity"));
+		    progress.reset();
+		    progress.setString(Dictionary.get("FileActions.No_Activity"));
+
+		    // Reset "yes to all" and "cancel" flags
+		    yes_to_all = false;
+		    cancel_action = false;
+
+		    // Wait for a new file job
+		    try {
+			wait();
+		    }
+		    catch (InterruptedException exception) {}
+		}
+	    }
+	}
+    }
+
+
+    /** Register the button that will be responsible for stopping executing file actions. 
+     * @param stop_button a JButton
+     */
+    public void registerStopButton(JButton stop_button) {
+	this.stop_button = stop_button;
+    }
+
+
+    synchronized private void clearJobs() {
+	queue.clear();
+    }
+    
+    /** Copy the contents from the source directory to the destination 
+     * directory.
+     * @param source The source directory
+     * @param destination The destination directory
+     * @see org.greenstone.gatherer.Gatherer
+     */
+    public void copyDirectoryContents(File source, File destination) 
+	throws FileAlreadyExistsException, FileNotFoundException, InsufficientSpaceException, IOException, ReadNotPermittedException, UnknownFileErrorException, WriteNotPermittedException
+    {
+	if (!source.isDirectory()) return;
+	// check that dest dirs exist
+	destination.mkdirs();
+	
+	File [] src_files = source.listFiles();
+	if (src_files.length == 0) return; // nothing to copy
+	for (int i=0; i<src_files.length; i++) {
+	    File f = src_files[i];
+	    String f_name = f.getName();
+	    File new_file = new File(destination, f_name);
+	    if (f.isDirectory()) {
+		copyDirectoryContents(f, new_file);
+	    } else if (f.isFile()) {
+		copyFile(f, new_file, false);
+	    }
+	}
+    }
+
+    
+    /** Copy a file from the source location to the destination location.
+     * @param source The source File.
+     * @param destination The destination File.
+     * @see org.greenstone.gatherer.Gatherer
+     */
+    public void copyFile(File source, File destination, boolean overwrite)
+	throws FileAlreadyExistsException, FileNotFoundException, InsufficientSpaceException, IOException, ReadNotPermittedException, UnknownFileErrorException, WriteNotPermittedException
+    {
+	if (source.isDirectory()) {
+	    destination.mkdirs();
+	    return;
+	}
+
+	// Check if the origin file exists.
+	if (!source.exists()) {
+	    DebugStream.println("Couldn't find the source file.");
+	    throw new FileNotFoundException();
+	}
+
+	// Make sure the destination file does not exist.
+	if (destination.exists() && !overwrite) {
+	    throw new FileAlreadyExistsException();
+	}
+
+	// Open an input stream to the source file
+	FileInputStream f_in = null;
+	try {
+	    f_in = new FileInputStream(source);
+	}
+	catch (FileNotFoundException exception) {
+	    // A FileNotFoundException translates into a ReadNotPermittedException in this case
+	    throw new ReadNotPermittedException(exception.toString());		
+	}
+
+	// Create an necessary directories for the target file
+	File dirs = destination.getParentFile();
+	dirs.mkdirs();
+
+	// Open an output stream to the target file
+	FileOutputStream f_out = null;
+	try {
+	    f_out = new FileOutputStream(destination);
+	}
+	catch (FileNotFoundException exception) {
+	    // A FileNotFoundException translates into a WriteNotPermittedException in this case
+	    throw new WriteNotPermittedException(exception.toString());
+	}
+
+	// Copy the file
+	byte data[] = new byte[BUFFER_SIZE];
+	int data_size = 0;
+	while ((data_size = f_in.read(data, 0, BUFFER_SIZE)) != -1 && !cancel_action) {
+	    long destination_size = destination.length();
+	    try {
+		f_out.write(data, 0, data_size);
+	    }
+	    // If an IO exception occurs, we can do some maths to determine if the number of bytes written to the file was less than expected. If so we assume a InsufficientSpace exception. If not we just throw the exception again.
+	    catch (IOException io_exception) {
+		if (destination_size + (long) data_size > destination.length()) {
+		    // Determine the difference (which I guess is in bytes).
+		    long difference = (destination_size + (long) data_size) - destination.length();
+		    // Transform that into a human readable string.
+		    String message = Utility.formatFileLength(difference);
+		    throw new InsufficientSpaceException(message);
+		}
+		else {
+		    throw(io_exception);
+		}
+	    }
+	}
+
+	// Flush and close the streams to ensure all bytes are written.
+	f_in.close();
+	f_out.close();
+
+	// We have now, in theory, produced an exact copy of the source file. Check this by comparing sizes.
+	if(!destination.exists() || (!cancel_action && source.length() != destination.length())) {
+	    throw new UnknownFileErrorException();
+	}
+
+	// If we were cancelled, ensure that none of the destination file exists.
+	if (cancel_action) {
+	    destination.delete();
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileSystem.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileSystem.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileSystem.java	(revision 13928)
@@ -0,0 +1,63 @@
+package org.greenstone.gatherer.file;
+
+import java.io.File;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+
+
+public class FileSystem
+{
+    static public WorkspaceTreeNode getLocalFilespaceNode(FileSystemModel model)
+    {
+	// Get all the available roots mounted on the filesystem
+	File[] roots = File.listRoots();
+	if (roots == null) {
+	    return null;
+	}
+
+	// If there is just one root use it as the tree root (Unix)
+	if (roots.length == 1) {
+	    return new WorkspaceTreeNode(roots[0], Dictionary.get("Tree.Root"));
+	}
+
+	// Otherwise build a dummy node which has the roots as children (Windows)
+	else {
+	    return new WorkspaceTreeNode(null, Dictionary.get("Tree.Root"));
+	}
+    }
+
+
+    static public WorkspaceTreeNode getHomeFolderNode()
+    {
+	// Get the name of the OS we're running on
+	String os_name = System.getProperty("os.name");
+	if (os_name == null) {
+	    return null;
+	}
+
+	// Make sure we're running on a multiuser OS where the idea of a "user home" is valid
+	DebugStream.println("Property os.name: " + os_name);
+	String os_name_lc = os_name.toLowerCase();
+	if (os_name_lc.equals("windows 95") || os_name_lc.equals("windows 98") || os_name_lc.equals("windows me")) {
+	    return null;
+	}
+
+	// Get the user's home folder
+ 	String home_folder_str = System.getProperty("user.home");
+	if (home_folder_str == null || home_folder_str.length() == 0) {
+	    return null;
+	}
+
+	// Generate a special mapping to the user home folder
+	File home_folder = new File(home_folder_str);
+	return new WorkspaceTreeNode(home_folder, Dictionary.get("Tree.Home", home_folder.getName()));
+    }
+
+
+    static public WorkspaceTreeNode getDownloadedFilesNode()
+    {
+	// Return a mapping to the downloaded files folder
+	return new WorkspaceTreeNode(new File(Gatherer.getGLIUserCacheDirectoryPath()), Dictionary.get("Tree.DownloadedFiles"));
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileSystemModel.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileSystemModel.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/FileSystemModel.java	(revision 13928)
@@ -0,0 +1,278 @@
+package org.greenstone.gatherer.file;
+
+import java.io.File;
+import java.util.*;
+import java.util.regex.*;
+import javax.swing.event.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.gui.tree.DragTree;
+
+
+public class FileSystemModel
+    extends DefaultTreeModel 
+    implements TreeExpansionListener, TreeWillExpandListener
+{
+    private DragTree tree = null;
+    private FileFilter current_filter = null;
+    private FileFilter[] filters = null;
+    /** The filters in place for any file system model. */
+    private FileFilter[] default_filters = { new FileFilter("\\..*", true), new FileFilter("metadata\\.xml", true) };
+
+    public FileSystemModel(FileNode root) {
+	super(root);
+	root.setModel(this);
+	root.refresh();
+    }
+
+    public int getChildCount(Object parent) {
+	return ((TreeNode)parent).getChildCount();
+    }
+
+    public FileFilter[] getFilters() {
+	if(filters == null) {
+	    if(current_filter != null) {
+		filters = new FileFilter[default_filters.length + 1];
+		filters[default_filters.length] = current_filter;
+	    }
+	    else {
+		filters = new FileFilter[default_filters.length];
+	    }
+	    System.arraycopy(default_filters, 0, filters, 0, default_filters.length);
+	}
+	return filters;
+    }
+	 
+    /** Retrieve the node denoted by the given tree path. Note that this isn't equivelent to saying path.lastPathComponent, as the references within the path may be stale. */
+    public FileNode getNode(TreePath path) {
+	FileNode last = (FileNode)path.getLastPathComponent();
+	DebugStream.println("Last Path Component = " + last);
+	return last;
+	/*
+	///atherer.println("**** getNode(" + path + ") ****");
+	FileNode current = (FileNode)root;
+	// Special case for the root node. Check the first path component is the root node.
+	FileNode first_node = (FileNode)path.getPathComponent(0);
+	if(current.equals(first_node)) {
+	    DebugStream.println("First path component matches root node.");
+	    // For each path with this tree path
+	    for(int i = 1; current != null && i < path.getPathCount(); i++) {
+		// Retrieve the stale path
+		Object stale_object = path.getPathComponent(i);
+		FileNode stale_node = null;
+		if(stale_object instanceof FileNode) {
+		    stale_node = (FileNode) stale_object;
+		}
+		DebugStream.print("Searching for '" + stale_object + "': ");
+		// Locate the fresh node by searching current's children. Remember to ensure that current is mapped.
+		boolean found = false;
+
+		// First we search through the mapped children
+		for(int j = 0; !found && j < current.getChildCount(); j++) {
+		    FileNode child_node = (FileNode) current.getChildAt(j);
+		    DebugStream.print(child_node + " ");
+		    if((stale_node != null && stale_node.equals(child_node)) || stale_object.toString().equals(child_node.toString())) {
+			found = true;
+			current = child_node;
+			DebugStream.println("Found!");
+		    }
+		    child_node = null;
+		}
+		// Failing that we search through all the children, including filtered files
+		for(int j = 0; !found && j < current.size(); j++) {
+		    FileNode child_node = (FileNode) current.getChildAtUnfiltered(j);
+		    DebugStream.print(child_node + " ");
+		    if((stale_node != null && stale_node.equals(child_node)) || stale_object.toString().equals(child_node.toString())) {
+			found = true;
+			current = child_node;
+			DebugStream.println("Found!");
+		    }
+		    child_node = null;
+		}
+		// If no match is found, then set current to null and exit.
+		if(!found) {
+		    current = null;
+		    DebugStream.println("Not Found!");
+		}
+		else {
+		    DebugStream.println("Returning node: " + new TreePath(current.getPath()));
+		}
+		// Repeat as necessary
+	    }
+	}
+	return current;
+	*/
+    }
+
+    public void insertNodeInto(MutableTreeNode newChild, MutableTreeNode parent, int index) {
+	///ystem.err.println("insertNodeInto(" + newChild + ", " + parent + ", " + index + ")");
+	super.insertNodeInto(newChild, parent, index);
+    }
+
+
+    public void refresh(TreePath path)
+    {
+	// Can only refresh if the model is currently being displayed in a tree
+	if (tree == null) {
+	    return;
+	}
+
+	// If no path is set, take the path to the root node (ie. update the whole tree)
+	if (path == null) {
+	    // System.err.println("\nFileSystemModel.refresh(entire tree).");
+	    path = new TreePath(((FileNode) root).getPath());
+
+	    // Make sure the root node is expanded
+	    tree.expandPath(path);
+	}
+	// else {
+	//     System.err.println("\nFileSystemModel.refresh(" + path + ").");
+	// }
+
+	// Record all the expanded paths under this node
+	Enumeration old_expanded_paths_enumeration = tree.getExpandedDescendants(path);
+	if (old_expanded_paths_enumeration == null) {
+	    return;
+	}
+
+	// Map and unmap the node to refresh its contents
+	FileNode node = (FileNode) path.getLastPathComponent();
+	node.refresh();
+
+	// Fire the appropriate event
+	nodeStructureChanged(node);
+
+	// Sort the old expanded paths by length, smallest first
+	ArrayList old_expanded_paths_list = Collections.list(old_expanded_paths_enumeration);
+	Collections.sort(old_expanded_paths_list, new TreePathComparator());
+
+	// Restore each of the expanded paths
+	for (int i = 0; i < old_expanded_paths_list.size(); i++) {
+  	    TreePath old_expanded_path = (TreePath) old_expanded_paths_list.get(i);
+	    // System.err.println("Expanded path: " + old_expanded_path);
+
+	    // Build up the new path in the tree
+	    TreePath current_path = new TreePath(path.getPath());
+  	    FileNode current_node = node;
+
+	    // Traverse the tree to find the node to expand (or find it no longer exists)
+	    while (!current_path.toString().equals(old_expanded_path.toString())) {
+		// System.err.println("Current path: " + current_path);
+
+		FileNode old_expanded_node =
+		    (FileNode) old_expanded_path.getPathComponent(current_path.getPathCount());
+		// System.err.println("Looking for: " + old_expanded_node);
+
+		// Find the child node that matches the next element in the path
+		boolean found = false;
+		for (int j = 0; j < current_node.getChildCount(); j++) {
+		    FileNode child_node = (FileNode) current_node.getChildAt(j);
+		    // System.err.println("Child node: " + child_node);
+		    if (child_node.equals(old_expanded_node)) {
+			// System.err.println("Found!");
+			current_path = current_path.pathByAddingChild(child_node);
+			current_node = child_node;
+			found = true;
+			break;
+		    }
+		}
+
+		// The node was not found, so we cannot expand this path
+		if (!found) {
+		    // System.err.println("Not found...");
+		    break;
+		}
+	    }
+
+	    // If we have built up the correct path, expand it
+	    if (current_path.toString().equals(old_expanded_path.toString())) {
+		tree.expandPath(current_path);
+	    }
+	}
+    }
+
+
+    // The file tree can be filtered, so check that the node to be removed is actually part of the model
+    public void removeNodeFromParent(MutableTreeNode node)
+    {
+	TreeNode parent_node = ((FileNode) node).getParent();
+	if (parent_node != null && parent_node.getIndex((FileNode) node) != -1) {
+	    super.removeNodeFromParent(node);
+	}
+    }
+
+
+    private class TreePathComparator
+	implements Comparator {
+
+	public int compare(Object o1, Object o2)
+	{
+	    return (((TreePath) o1).getPathCount() - ((TreePath) o2).getPathCount());
+	}
+    }
+
+
+    public void setFilter(String pattern) {
+  	if(pattern != null) {
+  	    current_filter = new FileFilter(pattern, false);
+  	}
+  	else {
+  	    current_filter = null;
+  	}
+  	filters = null;
+    }
+
+    public void setTree(DragTree tree) {
+	this.tree = tree;
+    }
+
+    public String toString() {
+	if(tree != null) {
+	    return tree.toString();
+	}
+	return "FileSystemModel";
+    }
+
+    /** Called whenever an item in the tree has been collapsed. */
+    public void treeCollapsed(TreeExpansionEvent event) {
+	// Deallocate the affected nodes children. Don't need to do this in a swing worker, as the nodes children are currently not visable.
+	TreePath path = event.getPath();
+	FileNode node = (FileNode) path.getLastPathComponent();
+	node.unmap();
+	// Fire the appropriate event.
+	nodeStructureChanged(node);
+    }
+
+    /** Called whenever an item in the tree has been expanded. */
+    public void treeExpanded(TreeExpansionEvent event) {
+    }
+
+    /** Invoked whenever a node in the tree is about to be collapsed. */
+    public void treeWillCollapse(TreeExpansionEvent event) 
+	throws ExpandVetoException {
+	// Veto the event if the user is attempting to collapse the root node (regardless of whether it is visible).
+	TreePath path = event.getPath();
+	if(path.getPathCount() == 1) {
+	    throw new ExpandVetoException(event, "Cannot collapse root node!");
+	}
+    }
+
+
+    /** Invoked whenever a node in the tree is about to be expanded. */
+    public void treeWillExpand(TreeExpansionEvent event) 
+	throws ExpandVetoException
+    {
+	// Set the wait cursor
+	Gatherer.g_man.wait(true);
+
+	// Allocate the children (don't need a swing worker since the node's children are currently not visible)
+	TreePath path = event.getPath();
+	FileNode node = (FileNode) path.getLastPathComponent();
+	node.refresh();
+	nodeStructureChanged(node);
+
+	// Restore the cursor
+	Gatherer.g_man.wait(false);
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/InsufficientSpaceException.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/InsufficientSpaceException.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/InsufficientSpaceException.java	(revision 13928)
@@ -0,0 +1,11 @@
+package org.greenstone.gatherer.file;
+
+import java.lang.Exception;
+
+public class InsufficientSpaceException
+    extends Exception {
+
+    public InsufficientSpaceException(String message) {
+	super(message);
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/ReadNotPermittedException.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/ReadNotPermittedException.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/ReadNotPermittedException.java	(revision 13928)
@@ -0,0 +1,11 @@
+package org.greenstone.gatherer.file;
+
+import java.lang.Exception;
+
+public class ReadNotPermittedException
+    extends Exception
+{
+    public ReadNotPermittedException(String message) {
+	super(message);
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/RecycleBin.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/RecycleBin.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/RecycleBin.java	(revision 13928)
@@ -0,0 +1,188 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.file;
+
+import java.awt.*;
+import java.awt.dnd.*;
+import java.awt.event.*;
+import java.awt.geom.AffineTransform;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.gui.GLIButton;
+import org.greenstone.gatherer.util.DragComponent;
+import org.greenstone.gatherer.util.DragGroup;
+import org.greenstone.gatherer.util.JarTools;
+
+
+public class RecycleBin
+    extends GLIButton
+    implements DragComponent, DropTargetListener {
+
+    private boolean ignore = false;
+    /** The group encompasses all of the objects you plan to drag and drop within, and ensures that only one has focus (as clearly identified by the colour of the selection field or, in this particular case, the background) and that actions only occur between components in the same group. */
+    private DragGroup group;
+    /** In order to make this button a drop target we have to create a DropTarget instance with the button as its target. */
+    private DropTarget drop_target;
+    private FileSystemModel model;
+    /** What sort of action should a drag resemble. Not really used as we override with custom drag icon. */
+    private int drag_action = DnDConstants.ACTION_MOVE;
+    /** The last point the mouse was at. Used to repaint 'spoilt' area. */
+    private Point pt_last = null;
+    /** The area covered by the drag ghost, our custom drag icon. */
+    private Rectangle ra_ghost = new Rectangle();
+
+
+    public RecycleBin()
+    {
+	super(JarTools.getImage("bin.gif"));
+	this.drop_target = new DropTarget(this, drag_action, this, true);
+
+	setBackground(Configuration.getColor("coloring.button_background", true));
+	setForeground(Configuration.getColor("coloring.button_foreground", true));
+	setOpaque(true);
+
+	this.model = new FileSystemModel(new RecycleBinNode(new File(Gatherer.getGLIUserDirectoryPath() + "recycle")));
+    }
+
+
+    /** In order for the appearance to be consistant, given we may be in the situation where the pointer has left our focus but the ghost remains, this method allows other members of the GGroup to tell this component to repair the 'spoilt' region left by its ghost. */
+    public void clearGhost(){
+    }
+
+
+    /** Any implementation of DropTargetListener must include this method so we can be notified when the drag focus enters this component. We want to provide some sort of indication whether the current component is an acceptable drop target as well as indicating focus. */
+    public void dragEnter(DropTargetDragEvent event) {
+	group.grabFocus(this);
+	setBackground(Configuration.getColor("coloring.button_selected_background", true));
+	setForeground(Configuration.getColor("coloring.button_selected_foreground", true));
+    }
+
+    /** Any implementation of DropTargetListener must include this method so we can be notified when the drag focus leaves this component. We need to indicate that we have lost focus. */
+    public void dragExit(DropTargetEvent event) {
+	setBackground(Configuration.getColor("coloring.button_background", true));
+	setForeground(Configuration.getColor("coloring.button_foreground", true));
+    }
+
+    /** Any implementation of DropTargetListener must include this method so we can be notified when the drag moves in this component. This is where we repaint our ghost icon at the tip of the mouse pointer. */
+    public void dragOver(DropTargetDragEvent event) {
+	Graphics2D g2 = (Graphics2D) getGraphics();
+	Point pt = event.getLocation();
+	if(pt_last != null && pt.equals(pt_last)) {
+	    return;
+	}
+	pt_last = pt;
+	if(!DragSource.isDragImageSupported()) {
+	    // Erase the last ghost image and or cue line
+	    paintImmediately(ra_ghost.getBounds());
+	    // Remember where you are about to draw the new ghost image
+	    ra_ghost.setRect(pt.x - group.mouse_offset.x, pt.y - group.mouse_offset.y, group.image_ghost.getWidth(), group.image_ghost.getHeight());
+	    // Draw the ghost image
+	    g2.drawImage(group.image_ghost, AffineTransform.getTranslateInstance(ra_ghost.getX(), ra_ghost.getY()), null);
+	}
+    }
+
+    /** Any implementation of DropTargetListener must include this method so we can be notified when the drag ends, ie the transferable is dropped. This in turn triggers a series of add events preceded by a pre() and followed by a post(). */
+    public void drop(DropTargetDropEvent event) {
+	ignore = true;
+	group.grabFocus(this);
+	setBackground(Configuration.getColor("coloring.button_background", true));
+	setForeground(Configuration.getColor("coloring.button_foreground", true));
+
+	try {
+	    DragComponent source = group.getSource();
+	    TreePath[] selection = group.getSelection();
+	    FileNode[] source_nodes = new FileNode[selection.length];
+	    for(int i = 0; i < source_nodes.length; i++) {
+		source_nodes[i] = (FileNode) selection[i].getLastPathComponent();
+	    }
+	    event.acceptDrop(drag_action);
+	    // Action delete
+	    Gatherer.f_man.action(source, source_nodes, this, null);
+	    group.setSource(null);
+	    group.setSelection(null);
+	}
+	catch(Exception error) {
+	    error.printStackTrace();
+	    event.rejectDrop();
+	}
+	ignore = false;
+	// Clear up the group.image_ghost
+	paintImmediately(ra_ghost.getBounds());
+	event.getDropTargetContext().dropComplete(true);
+    }
+
+    /** Any implementation of DropTargetListener must include this method so we can be notified when the action to be taken upon drop changes. We never change so we don't do anything here. */
+    public void dropActionChanged(DropTargetDragEvent event) {
+    }
+
+    /** Used to notify this component that it has gained focus by some method other that mouse focus. */
+    public void gainFocus() {
+    }
+
+    /** Any implementation of DragComponent must include this method so that a outsider can get at the underlying tree model behind the component. */
+    public FileSystemModel getTreeModel(){
+  	return (FileSystemModel) model;
+    }
+
+    public boolean ignore() {
+	return ignore;
+    }
+
+    /** This method is used to inform this component when it loses focus by means other than a drag mouse event, and should indicate this somehow. */
+    public void loseFocus() {
+    }
+
+    public void setGroup(DragGroup group) {
+	this.group = group;
+    }
+
+
+    public class RecycleBinNode
+	extends FileNode
+    {
+	public RecycleBinNode(File file)
+	{
+	    super(file);
+	}
+
+	public FileNode addChildNode(File file) { return null; }
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/UnknownFileErrorException.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/UnknownFileErrorException.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/UnknownFileErrorException.java	(revision 13928)
@@ -0,0 +1,11 @@
+package org.greenstone.gatherer.file;
+
+import java.lang.Exception;
+
+public class UnknownFileErrorException
+    extends Exception {
+
+    public UnknownFileErrorException() {
+	super();
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/WorkspaceTree.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/WorkspaceTree.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/WorkspaceTree.java	(revision 13928)
@@ -0,0 +1,385 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.file;
+
+import java.awt.event.*;
+import java.io.File;
+import java.util.Enumeration;
+import javax.swing.*;
+import javax.swing.tree.TreePath;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.gui.CreateShortcutPrompt;
+import org.greenstone.gatherer.gui.tree.DragTree;
+
+
+public class WorkspaceTree
+    extends DragTree
+    implements MouseListener
+{
+    static public final int LIBRARY_CONTENTS_CHANGED = 10;
+    static public final int DOWNLOADED_FILES_CHANGED = 11;
+    static public final int FOLDER_SHORTCUTS_CHANGED = 12;
+
+
+    public WorkspaceTree()
+    {
+	super(WorkspaceTreeModel.getWorkspaceTreeModel(), true);
+	addMouseListener(this);
+
+	setBackgroundNonSelectionColor(Configuration.getColor("coloring.workspace_tree_background", false));
+	setBackgroundSelectionColor(Configuration.getColor("coloring.workspace_selection_background", false));
+	setTextNonSelectionColor(Configuration.getColor("coloring.workspace_tree_foreground", false));
+	setTextSelectionColor(Configuration.getColor("coloring.workspace_selection_foreground", false));
+
+	filter.setBackground(Configuration.getColor("coloring.workspace_heading_background", false));
+	filter.setEditable(Configuration.getMode() > Configuration.LIBRARIAN_MODE);
+    }
+
+
+    public void addDirectoryMapping(String name, File file)
+    {
+	// Update the information stored in the user's configuration
+	Configuration.addDirectoryMapping(name, file);
+
+	// Now update the tree
+	refresh(FOLDER_SHORTCUTS_CHANGED);
+    }
+
+
+    public boolean isDraggable()
+    {
+	return true;
+    }
+
+
+    public boolean isDroppable()
+    {
+	return false;
+    }
+
+
+    public void mouseClicked(MouseEvent event)
+    {
+	if (SwingUtilities.isRightMouseButton(event)) {
+	    new WorkspaceTreeRightClickMenu(this, event);
+	}
+    }
+
+    public void mouseEntered(MouseEvent event) { }
+
+    public void mouseExited(MouseEvent event) { }
+
+    public void mousePressed(MouseEvent event) { }
+
+    public void mouseReleased(MouseEvent event) { }
+
+
+    public void refresh(int refresh_reason)
+    {
+	DebugStream.println("WorkspaceTree::refresh()... ");
+
+	// The method for displaying the tree has changed - redraw the tree
+  	if (refresh_reason == DragTree.TREE_DISPLAY_CHANGED) {
+  	    DebugStream.println("...Reason: tree display changed.");
+  	    updateUI();
+  	}
+
+	// The loaded collection has changed - currently do nothing
+	if (refresh_reason == DragTree.LOADED_COLLECTION_CHANGED) {
+	    DebugStream.println("...Reason: loaded collection changed.");
+	}
+
+	// The collection's contents have changed - refresh collection's import folder
+	if (refresh_reason == DragTree.COLLECTION_CONTENTS_CHANGED) {
+	    DebugStream.println("...Reason: collection contents changed.");
+	    String collection_import_directory_path = CollectionManager.getLoadedCollectionImportDirectoryPath();
+	    refreshEveryNodeShowingFolder(collection_import_directory_path);
+	}
+
+	// The collections in the library have changed - refresh the collect directory
+	if (refresh_reason == WorkspaceTree.LIBRARY_CONTENTS_CHANGED) {
+	    DebugStream.println("...Reason: library contents changed.");
+	    String collect_directory_path = Gatherer.getCollectDirectoryPath();
+	    refreshEveryNodeShowingFolder(collect_directory_path);
+	    WorkspaceTreeModel.refreshGreenstoneCollectionsNode();
+	}
+
+	// The downloaded files have changed - refresh that node
+	if (refresh_reason == WorkspaceTree.DOWNLOADED_FILES_CHANGED) {
+	    DebugStream.println("...Reason: downloaded files changed.");
+	    WorkspaceTreeModel.refreshDownloadedFilesNode();
+	}
+
+	// The folder shortcuts have changed - refresh only them
+	if (refresh_reason == WorkspaceTree.FOLDER_SHORTCUTS_CHANGED) {
+	    DebugStream.println("...Reason: folder shortcuts changed.");
+	    WorkspaceTreeModel.refreshFolderShortcuts();
+	}
+    }
+
+
+    private void refreshEveryNodeShowingFolder(String folder_path_str)
+    {
+	// Search through the expanded tree paths, checking if any show the given folder
+	TreePath tree_root_path = new TreePath(getModel().getRoot());
+	Enumeration expanded_tree_paths = getExpandedDescendants(tree_root_path);
+	while (expanded_tree_paths.hasMoreElements()) {
+	    TreePath expanded_tree_path = (TreePath) expanded_tree_paths.nextElement();
+	    WorkspaceTreeNode tree_node = (WorkspaceTreeNode) expanded_tree_path.getLastPathComponent();
+
+	    File tree_node_file = tree_node.getFile();
+	    if (tree_node_file == null) {
+		continue;
+	    }
+
+	    // Get the path of the open tree node
+	    String tree_node_path_str = tree_node_file.toString();
+	    if (!tree_node_path_str.endsWith(File.separator)) {
+		tree_node_path_str = tree_node_path_str + File.separator;
+	    }
+
+	    // If the specified folder is open, it must be refreshed
+	    if (tree_node_path_str.equals(folder_path_str)) {
+		System.err.println("Must refresh node " + tree_node_path_str + "!");
+		((WorkspaceTreeModel) getModel()).refresh(expanded_tree_path);
+	    }
+	}
+    }
+
+
+    public void removeDirectoryMapping(WorkspaceTreeNode target)
+    {
+	// Update the information stored in the user's configuration
+	Configuration.removeDirectoryMapping(target.toString());
+
+	// Update tree
+	refresh(FOLDER_SHORTCUTS_CHANGED);
+    }
+
+
+    public String toString()
+    {
+	return "Workspace";
+    }
+
+
+    /** When a user right-clicks within the workspace and collection trees they are presented with a small popup menu of context based options. This class provides such functionality.
+     */
+    private class WorkspaceTreeRightClickMenu
+	extends JPopupMenu
+	implements ActionListener
+    {
+	/** The tree over which the right click action occurred. */
+	private WorkspaceTree workspace_tree = null;
+	/** The tree nodes selected when the right click action occurred. */
+	private TreePath[] selection_paths = null;
+	/** The file record over which the right click action occurred. */
+	private WorkspaceTreeNode node = null;
+
+	private JMenuItem create_shortcut = null;
+	private JMenuItem delete_shortcut = null;
+	private JMenuItem collapse_folder = null;
+	private JMenuItem expand_folder = null;
+	private JMenuItem explode_metadata_database = null;
+	private JMenuItem delete = null;
+	private JMenuItem metaaudit = null;
+	private JMenuItem new_folder = null;
+	private JMenuItem new_dummy_doc = null;
+	private JMenuItem open_externally = null;
+	private JMenuItem rename = null;
+	private JMenuItem replace = null;
+
+
+	private WorkspaceTreeRightClickMenu(WorkspaceTree workspace_tree, MouseEvent event)
+	{
+	    super();
+	    this.workspace_tree = workspace_tree;
+
+	    // Note we have to use setImmediate() with the set selction paths
+	    // otherwise the selection doesn't get updated until after the 
+	    // popup comes up.
+
+	    // the right click position
+	    TreePath right_click_path = workspace_tree.getPathForLocation(event.getX(), event.getY());
+	    if (right_click_path == null) {
+		// user has clicked outside of the tree, clear the selection
+		selection_paths = null;
+		workspace_tree.setImmediate(true);
+		workspace_tree.clearSelection();
+		workspace_tree.setImmediate(false);
+	    }
+	    else {
+		// Get the paths currently selected in the tree
+		selection_paths = workspace_tree.getSelectionPaths();
+		if (selection_paths == null) {
+		    // nothing currently selected - we shift the selection to 
+		    // the node that was right clicked on
+		    selection_paths = new TreePath[1];
+		    selection_paths[0] = right_click_path;
+		    workspace_tree.setImmediate(true);
+		    workspace_tree.setSelectionPath(right_click_path);
+		    workspace_tree.setImmediate(false);
+		}
+		else if (selection_paths.length == 1 && ! selection_paths[0].equals( right_click_path)) {
+		    workspace_tree.setImmediate(true);
+		    workspace_tree.clearSelection();
+		    workspace_tree.setSelectionPath(right_click_path);
+		    workspace_tree.setImmediate(false);
+		    selection_paths[0] = right_click_path;
+		}
+		else {
+		    // we had multiply selected paths in the tree.
+		    // if we clicked on one of those paths, then use all the 
+		    // current selection, otherwise clear the selection and 
+		    // select the one we right clicked on
+		    boolean clicked_in_selection = false;
+		    for (int i = 0; i < selection_paths.length; i++) {
+			if (selection_paths[i].equals(right_click_path)) {
+			    clicked_in_selection = true;
+			    break;
+			}
+		    }
+		    if (!clicked_in_selection) {
+			// want the tree to update right away
+			workspace_tree.setImmediate(true);
+			workspace_tree.clearSelection();
+			workspace_tree.setSelectionPath(right_click_path);
+			workspace_tree.setImmediate(false);
+			selection_paths = new TreePath[1];
+			selection_paths[0] = right_click_path;
+		    }
+		}
+	    }
+	    
+	    // Create an appropriate context menu, based on what is selected
+	    buildContextMenu(selection_paths);
+
+	    // Show the popup menu on screen
+	    show(workspace_tree, event.getX(), event.getY());
+	}
+
+
+	private void buildContextMenu(TreePath[] selection_paths)
+	{
+	    // If nothing is selected, no options are available...
+	    if (selection_paths == null) {
+		return;
+	    }
+
+	    // Only meta-audit and delete are available if multiple items are selected...
+	    if (selection_paths.length > 1) {
+		return;
+	    }
+
+	    TreePath path = selection_paths[0];
+	    node = (WorkspaceTreeNode) path.getLastPathComponent();
+
+	    // ---- Options for file nodes ----
+	    if (node.isLeaf()) {
+		// Open the file in an external program
+		open_externally = new JMenuItem(Dictionary.get("Menu.Open_Externally"), KeyEvent.VK_O);
+		open_externally.addActionListener(this);
+		add(open_externally);
+
+		return;
+	    }
+
+	    // ---- Options for folder nodes ----
+	    // Collapse or expand, depending on current status
+	    if (workspace_tree.isExpanded(path)) {
+		collapse_folder = new JMenuItem(Dictionary.get("Menu.Collapse"), KeyEvent.VK_C);
+		collapse_folder.addActionListener(this);
+		add(collapse_folder);
+	    }
+	    else {
+		expand_folder = new JMenuItem(Dictionary.get("Menu.Expand"), KeyEvent.VK_O);
+		expand_folder.addActionListener(this);
+		add(expand_folder);
+	    }
+
+	    // Create/remove shortcut option, for workspace tree only
+	    if (workspace_tree == workspace_tree) {
+		// The "built-in" folders can't be modified
+		String node_name = node.toString();
+		if (node_name.equals(Dictionary.get("Tree.World")) || node_name.equals(Dictionary.get("Tree.Root")) || node_name.equals(Dictionary.get("Tree.DownloadedFiles"))) {
+		    return;
+		}
+
+		// You can unmap 1st level nodes
+		WorkspaceTreeNode root = (WorkspaceTreeNode) workspace_tree.getModel().getRoot();
+		if (root.getIndex(node) != -1) {
+		    delete_shortcut = new JMenuItem(Dictionary.get("MappingPrompt.Unmap"), KeyEvent.VK_R);
+		    delete_shortcut.addActionListener(this);
+		    add(delete_shortcut);
+		}
+		// Or map any other level directories
+		else {
+		    create_shortcut = new JMenuItem(Dictionary.get("MappingPrompt.Map"), KeyEvent.VK_S);
+		    create_shortcut.addActionListener(this);
+		    add(create_shortcut);
+		}
+	    }
+	}
+
+
+	/** Called whenever one of the menu items is clicked, this method then causes the appropriate effect. */
+	public void actionPerformed(ActionEvent event)
+	{
+  	    Object source = event.getSource();
+
+	    // Create shortcut
+	    if (source == create_shortcut) {
+ 		CreateShortcutPrompt csp = new CreateShortcutPrompt(workspace_tree, node.getFile());
+ 		csp.destroy();
+	    }
+
+	    // Delete shortcut
+  	    else if (source == delete_shortcut) {
+  		workspace_tree.removeDirectoryMapping(node);
+  	    }
+
+	    // Collapse folder
+	    else if (source == collapse_folder) {
+		workspace_tree.collapsePath(selection_paths[0]);
+	    }
+
+	    // Expand folder
+	    else if (source == expand_folder) {
+		workspace_tree.expandPath(selection_paths[0]);
+	    }
+
+	    // Open in external program
+	    else if (source == open_externally) {
+		Gatherer.f_man.openFileInExternalApplication(node.getFile());
+	    }
+  	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/WorkspaceTreeModel.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/WorkspaceTreeModel.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/WorkspaceTreeModel.java	(revision 13928)
@@ -0,0 +1,173 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2004 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.file;
+
+import java.io.*;
+import java.util.*;
+import javax.swing.tree.TreePath;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.util.SynchronizedTreeModelTools;
+
+
+public class WorkspaceTreeModel
+    extends FileSystemModel
+{
+    static private WorkspaceTreeModel workspace_tree_model = null;
+    static private WorkspaceTreeNode workspace_tree_root = null;
+
+    static private WorkspaceTreeNode greenstone_collections_node = null;
+    static private WorkspaceTreeNode local_filespace_node = null;
+    static private WorkspaceTreeNode downloaded_files_node = null;
+    static private WorkspaceTreeNode[] folder_shortcuts = null;
+
+
+    public WorkspaceTreeModel(WorkspaceTreeNode root_node)
+    {
+	super(root_node);
+    }
+
+
+    static public WorkspaceTreeNode[] getFolderShortcuts()
+    {
+	// Return any predefined special directories
+	HashMap mappings = Configuration.getDirectoryMappings();
+	WorkspaceTreeNode[] mapping_nodes = new WorkspaceTreeNode[mappings.size()];
+	Iterator mappings_iterator = mappings.keySet().iterator();
+	for (int i = 0; mappings_iterator.hasNext(); i++) {
+	    String mapping_name = (String) mappings_iterator.next();
+	    File mapping_file = (File) mappings.get(mapping_name);
+	    mapping_nodes[i] = new WorkspaceTreeNode(mapping_file, mapping_name);
+	}
+	return mapping_nodes;
+    }
+
+
+    static public WorkspaceTreeModel getWorkspaceTreeModel()
+    {
+	// Create a root node to contain the various nodes in the workspace tree
+ 	workspace_tree_root = new WorkspaceTreeNode(null, "ABS_ROOT");
+	workspace_tree_model = new WorkspaceTreeModel(workspace_tree_root);
+
+	// Add the "Documents in Greenstone Collections" node
+	greenstone_collections_node = new WorkspaceTreeNode(null, Dictionary.get("Tree.World"));
+	workspace_tree_root.add(greenstone_collections_node);
+
+	// Add the "Local Filespace" node
+	local_filespace_node = FileSystem.getLocalFilespaceNode(workspace_tree_model);
+	workspace_tree_root.add(local_filespace_node);
+
+	// Add the "Home Folder" node
+	workspace_tree_root.add(FileSystem.getHomeFolderNode());
+
+	// Add the "Downloaded Files" node, if the Download pane is enabled
+	if (Gatherer.g_man.download_pane != null) {
+	    downloaded_files_node = FileSystem.getDownloadedFilesNode();
+	    workspace_tree_root.add(downloaded_files_node);
+	}
+
+	// Add any folder shortcuts the user has created
+	refreshFolderShortcuts();
+
+ 	return workspace_tree_model;
+    }
+
+
+    static public void refreshGreenstoneCollectionsNode()
+    {
+	greenstone_collections_node.refresh();
+    }
+
+
+    static public void refreshDownloadedFilesNode()
+    {
+	downloaded_files_node.refresh();
+    }
+
+
+    static public void refreshFolderShortcuts()
+    {
+	// Check for new/deleted folder shortcuts
+	WorkspaceTreeNode[] old_folder_shortcuts = folder_shortcuts;
+	folder_shortcuts = getFolderShortcuts();
+
+	// Remove any deleted shortcuts from the tree
+	if (old_folder_shortcuts != null) {
+	    for (int i = 0; i < old_folder_shortcuts.length; i++) {
+		if (!doesArrayContain(folder_shortcuts, old_folder_shortcuts[i])) {
+		    DebugStream.println("Deleted shortcut: " + old_folder_shortcuts[i]);
+		    SynchronizedTreeModelTools.removeNodeFromParent(workspace_tree_model, old_folder_shortcuts[i]);
+		}
+	    }
+	}
+
+	// Add any new shortcuts to the tree
+	if (folder_shortcuts != null) {
+	    for (int i = 0; i < folder_shortcuts.length; i++) {
+		if (!doesArrayContain(old_folder_shortcuts, folder_shortcuts[i])) {
+		    DebugStream.println("Added shortcut: " + folder_shortcuts[i]);
+		    SynchronizedTreeModelTools.insertNodeInto(workspace_tree_model, workspace_tree_root, folder_shortcuts[i], false);
+		}
+	    }
+	}
+    }
+
+
+    // -- This code is necessary to support the workspace tree file filter --
+    public void refresh(TreePath path)
+    {
+	// If we're not refreshing the whole tree just refresh a certain path
+	if (path != null) {
+	    super.refresh(path);
+	    return;
+	}
+
+	// Refresh each of the nodes in the workspace tree
+	for (int i = 0; i < workspace_tree_root.getChildCount(); i++) {
+	    WorkspaceTreeNode child_node = (WorkspaceTreeNode) workspace_tree_root.getChildAt(i);
+	    super.refresh(new TreePath(child_node.getPath()));
+	}
+    }
+
+
+    static private boolean doesArrayContain(Object[] array, Object item)
+    {
+	if (array == null) {
+	    return false;
+	}
+
+	for (int i = 0; i < array.length; i++) {
+	    if (item.toString().equals(array[i].toString())) {
+		return true;
+	    }
+	}
+
+	return false;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/WorkspaceTreeNode.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/WorkspaceTreeNode.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/WorkspaceTreeNode.java	(revision 13928)
@@ -0,0 +1,193 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2004 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.file;
+
+
+import java.io.*;
+import java.util.*;
+import javax.swing.filechooser.FileSystemView;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.BasicCollectionConfiguration;  // !!! Don't like this here
+import org.greenstone.gatherer.collection.CollectionManager;  // !!! Don't like this here
+import org.greenstone.gatherer.util.ArrayTools;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+
+
+/** This class represents one node in the workspace tree. */
+public class WorkspaceTreeNode
+    extends FileNode
+{
+    private boolean is_gs3_site_node = false;
+    private boolean is_in_loaded_collection = false;
+    private String title = null;
+
+
+    public WorkspaceTreeNode(File file)
+    {
+	super(file);
+    }
+
+
+    public WorkspaceTreeNode(File file, String title)
+    {
+	this(file);
+	this.title = title;
+    }
+
+
+    public FileNode addChildNode(File file)
+    {
+	WorkspaceTreeNode child_node = new WorkspaceTreeNode(file);
+	child_node.setModel(model);
+	child_node.setParent(this);
+	return child_node;
+    }
+
+
+    /** Is this file node within the currently loaded collection? */
+    public boolean isInLoadedCollection()
+    {
+	if (is_in_loaded_collection) {
+	    return true;
+	}
+	else {
+	    FileNode parent = (FileNode) getParent();
+	    if (parent != null) {
+		return parent.isInLoadedCollection();
+	    }
+	}
+	return false;
+    }
+
+
+    public boolean isReadOnly()
+    {
+	// The workspace tree is read only
+	return true;
+    }
+
+
+    public void map()
+    {
+	// Special Case: "Documents in Greenstone Collections" -- map the collections installed in Greenstone
+	if (file == null) { // a special mapping folder
+	    if (child_nodes != null) {
+		// don't bother mapping again if we already have children
+		return;
+	    }
+	    child_nodes = new ArrayList();
+	    if (title.equals(Dictionary.get("Tree.World")) && Gatherer.GS3) {
+		// the Greenstone collections folder for GS3 - this contains a 
+		// folder for each site
+
+		File start = new File(Utility.getSitesDir(Configuration.gsdl3_path));
+		File sites[] = start.listFiles();
+		ArrayTools.sort(sites);
+		for (int i = 0; sites != null && i < sites.length; i++) {
+		    File collect_dir = new File(sites[i], "collect");
+		    if (!collect_dir.exists()) {
+			continue;
+		    }
+
+		    WorkspaceTreeNode child = new WorkspaceTreeNode(null, sites[i].getName());
+		    child.is_gs3_site_node = true;
+		    child.unmap();
+		    child.setModel(model);
+		    child.setParent(this);
+		    child.map();
+		    child_nodes.add(child);
+		}
+		model.nodeStructureChanged(this);
+		
+	    } else if (title.equals(Dictionary.get("Tree.World")) || is_gs3_site_node) {
+		// For each of the children directories, which are collections...
+		File start;
+		if (is_gs3_site_node) {
+		    start = new File(Gatherer.getSitesDirectoryPath() + title + File.separator + "collect" + File.separator);
+		} else {
+		    start = new File(Gatherer.getCollectDirectoryPath());
+		}
+		File cols[] = start.listFiles();
+		ArrayTools.sort(cols);
+
+		// We add their import directories, except for the model collection
+		for (int i = 0; cols != null && i < cols.length; i++) {
+		    if (!cols[i].getName().equals(StaticStrings.MODEL_COLLECTION_NAME)) {
+			File import_dir = new File(cols[i], "import");
+			if (!import_dir.exists()) {
+			    continue;
+			}
+
+			// we don't care if there is no config file
+			BasicCollectionConfiguration collect_cfg = new BasicCollectionConfiguration(new File(cols[i], Utility.CONFIG_FILE));
+			WorkspaceTreeNode collection_root = new WorkspaceTreeNode(import_dir, collect_cfg.toString());
+			collection_root.setParent(this);
+			collection_root.setModel(model);
+
+			// One last piece of magic so we can determine the current collection
+			collection_root.is_in_loaded_collection = cols[i].getName().equals(CollectionManager.getLoadedCollectionName());
+			child_nodes.add(collection_root);
+		    }
+		}
+		model.nodeStructureChanged(this);
+	    }
+	    else if (title.equals(Dictionary.get("Tree.Root"))) {
+		// Special Case: "Local Filespace" on Windows -- create a node for each filesystem root (drive letter)
+		
+		// Sort the roots into alphabetical order
+		File[] roots = File.listRoots();
+		ArrayTools.sort(roots);
+		for (int i = 0; i < roots.length; i++) {
+		    // Only add root if it isn't a floppy drive
+		    // this used to cause problems, I don't think it does now...
+		    //if (!FileSystemView.getFileSystemView().isFloppyDrive(roots[i])) {
+		    child_nodes.add(addChildNode(roots[i]));
+			// }
+		}
+	    }
+	} // if file == null
+	
+	// General case
+	else {
+	    super.map();
+	}
+    }
+
+
+    public String toString()
+    {
+	if (title != null) {
+	    return title;
+	}
+
+	return super.toString();
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/WriteNotPermittedException.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/WriteNotPermittedException.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/file/WriteNotPermittedException.java	(revision 13928)
@@ -0,0 +1,11 @@
+package org.greenstone.gatherer.file;
+
+import java.lang.Exception;
+
+public class WriteNotPermittedException
+    extends Exception {
+
+    public WriteNotPermittedException(String message) {
+	super(message);
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/Attribute.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/Attribute.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/Attribute.java	(revision 13928)
@@ -0,0 +1,122 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gems;
+
+
+/**
+ *  Wrapper class for attributes displayed in the table 
+ * @author Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ */
+public class Attribute
+{
+    private String name="";
+    private String value="";
+    private String lang="";
+    private boolean isRequired;
+    //private boolean isLanguageDependent;
+
+    public Attribute() {}
+
+    public Attribute(String name, String value, String lang, boolean isRequired /*, boolean isLangDep*/){
+	this.name = name;
+	this.value = value;
+	this.lang = lang;
+	this.isRequired = isRequired;
+	//this.isLanguageDependent = isLangDep;
+    }
+
+    public Attribute(String name, String value, boolean isRequired/*, boolean isLangDep*/){
+	this.name = name;
+	this.value = value;
+	//this.lang = lang;
+	this.isRequired = isRequired;
+	//this.isLanguageDependent = isLangDep;
+    }
+
+    public Attribute(String name, String value){
+	this.name = name;
+	this.value = value;
+    }
+
+    public String getName(){
+	return name;
+    }
+
+    public String getValue() {
+	return value;
+    }
+
+    public String getLanguage() {
+	return lang;
+    }
+  
+    public boolean isRequired(){
+	return this.isRequired;
+    }
+
+//     public boolean isLanguageDependent(){
+// 	return this.isLanguageDependent;
+//     }
+       
+    public void setName(String name) {
+	if (name.trim().equals(this.name)) return;
+	this.name = name.trim();
+        
+    }
+    
+    public void setValue(String value) {
+	if (value.trim().equals(this.value)) return;
+	this.value = value.trim();
+    }
+
+    public void setLanguage(String lang) {
+	if (lang.trim().equals(this.lang)) return;
+	this.lang = lang;
+    }
+
+    public void setRequired(boolean isRequired) {
+	this.isRequired = isRequired;
+    } 
+    
+//     public void setLanguageDependent(boolean isLangDep) {
+// 	this.isLanguageDependent = isLangDep;
+//     }
+
+    public String toString() {
+	return (this.name + " " + this.value +" " + this.lang);
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/AttributeContainer.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/AttributeContainer.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/AttributeContainer.java	(revision 13928)
@@ -0,0 +1,183 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Katherine Don, New Zealand Digital Library Project, 
+ *          University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gems;
+
+import org.greenstone.gatherer.Configuration;
+
+import java.util.ArrayList;
+
+
+/** this is used as a base class for MetadataSetInfo and MetadataElementModel
+ * Both of thesee have some attributes which are language independent, and
+ * some which are language dependent
+ */ 
+public class AttributeContainer {
+    
+    protected ArrayList attributes;     
+    protected ArrayList language_dependent_attributes;    
+    
+    String [] required_attribute_names = null;
+    String [] language_dependent_attribute_names = null;
+    
+    public AttributeContainer() {}
+    public AttributeContainer(String [] required_atts, String []lang_dependent_atts) {       
+	
+	attributes = new ArrayList();
+	language_dependent_attributes =  new ArrayList();               
+
+	if (required_atts != null) {
+	    required_attribute_names = required_atts;
+	    for(int i=0;i<required_atts.length;i++){
+		String reName = required_atts[i];
+		Attribute attr = new Attribute(reName,"",true);
+		attributes.add(attr);            
+	    }
+	}
+
+	if (lang_dependent_atts != null) {
+	    language_dependent_attribute_names = lang_dependent_atts;
+	    for(int i=0;i<lang_dependent_atts.length;i++){
+		String reName = lang_dependent_atts[i];
+		Attribute attr = new Attribute(reName,"",Configuration.getLanguage(),true);
+		language_dependent_attributes.add(attr);            
+	    }
+	}
+	
+    }
+
+    public ArrayList getAttributes(){
+	return attributes;
+    }
+    
+    public void setAttributes(ArrayList atts) {
+	attributes.clear();
+	attributes = atts;
+    }
+
+    public String [] getLanguageDependentAttributeNames() {
+	return language_dependent_attribute_names;
+    }
+    public ArrayList getLanguageDependentAttributes(){
+	return language_dependent_attributes; 
+    }
+    
+    public void setLanguageDependentAttributes(ArrayList lda){
+	language_dependent_attributes.clear();
+	language_dependent_attributes = lda;
+    }
+
+
+    protected ArrayList getAllLanguages(){
+	ArrayList langs = new ArrayList();    
+
+       for(int i=0;i<language_dependent_attributes.size();i++){
+	    Attribute attr = (Attribute) language_dependent_attributes.get(i);
+            if (!langs.contains(attr.getLanguage()) && !attr.getLanguage().trim().equals("")){
+		langs.add(attr.getLanguage());
+	    } 
+	}   
+
+       return langs;
+    }
+
+    public int languageExists(String lang){
+	for(int i=0;i<language_dependent_attributes.size();i++){
+	    Attribute attr = (Attribute) language_dependent_attributes.get(i);
+	    if (attr.getLanguage().trim().equals(lang.trim())){
+		return i;
+	    } 
+	}   
+	
+	return -1;
+    }
+
+    protected Attribute getAttributeByName(String name){
+        for(int i=0;i<attributes.size();i++){
+	    Attribute attr = (Attribute) attributes.get(i);
+            if (attr.getName() != null && attr.getName().trim().equals(name.trim())){
+		return attr;
+	    } 
+	}
+
+	return null;
+    }
+
+    protected Attribute getAttributeByNameAndLanguage(String name, String lang){
+	for(int i=0;i<language_dependent_attributes.size();i++){
+	    Attribute attr = (Attribute) language_dependent_attributes.get(i);
+	    if (attr.getName() != null || attr.getLanguage()!=null){
+		if (attr.getName().trim().equals(name.trim()) && (attr.getLanguage().trim().equals(lang.trim()))){
+		    return attr;
+		}
+	    } 
+	}
+	
+	return null;
+    
+    }
+
+    protected ArrayList getAttributesByLanguage(String lang){
+	  ArrayList attrs = new ArrayList();    
+	  
+	  for(int i=0;i<language_dependent_attributes.size();i++){
+	      Attribute attr = (Attribute) language_dependent_attributes.get(i);
+	      if (!attr.getLanguage().trim().equals("") && attr.getLanguage().trim().equals(lang)){
+		  attrs.add(attr);
+	      } 
+	  }   
+	  
+	  return attrs;
+      }
+
+   protected boolean isAttributeRequired(String name) {
+       for(int i=0;i<required_attribute_names.length;i++){
+            if (name.equals(required_attribute_names[i])) return true;
+	}
+	return false;
+
+    }
+
+    protected boolean isLangDependentAttributeRequired(String name) {
+	for(int i=0;i<language_dependent_attribute_names.length;i++){
+            if (name.equals(language_dependent_attribute_names[i])) return true;
+	}
+	return false;
+
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/AttributeEvent.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/AttributeEvent.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/AttributeEvent.java	(revision 13928)
@@ -0,0 +1,52 @@
+
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at th * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################## ##########################
+ */
+package org.greenstone.gatherer.gems;
+
+public class AttributeEvent{
+    Attribute attribute;
+
+    public AttributeEvent(Attribute attr){
+        attribute = attr;
+
+    }
+
+     public Attribute getSource(){
+	 return attribute;
+    }
+
+    //add get and set method 
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/AttributeListener.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/AttributeListener.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/AttributeListener.java	(revision 13928)
@@ -0,0 +1,43 @@
+
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at th * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################## ##########################
+ */
+package org.greenstone.gatherer.gems;
+
+public interface AttributeListener{
+
+    public void attributeChanged(AttributeEvent ae);
+
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/AttributeTable.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/AttributeTable.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/AttributeTable.java	(revision 13928)
@@ -0,0 +1,323 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gems;
+
+import javax.swing.table.*; 
+import javax.swing.JTable; 
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.util.ArrayList; 
+import java.awt.Rectangle;
+import javax.swing.JOptionPane;
+import javax.swing.DefaultCellEditor;
+import javax.swing.JTextField;
+import javax.swing.ListSelectionModel;
+
+import org.greenstone.gatherer.Dictionary;
+
+public class AttributeTable
+    extends JTable 
+    implements MetadataElementListener, MetadataSetListener, ActionListener {
+
+    // self reference
+    JTable this_table; 
+    
+    private ArrayList listeners = new ArrayList();
+    private JTextField metadata_value_text_field = new JTextField();
+    private boolean language_dependent;
+    
+    public AttributeTable(boolean lang_dependent){
+	super();       
+        setRowHeight(20);
+	language_dependent = lang_dependent;
+	
+    	metadata_value_text_field.setBorder(null);
+	DefaultCellEditor cellEditor = new DefaultCellEditor(metadata_value_text_field);
+	cellEditor.setClickCountToStart(1);
+	setDefaultEditor(String.class,cellEditor);   
+        this_table = this;
+	setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+      }
+
+    /* not currently used */
+    public void actionPerformed(ActionEvent e){
+	String command = e.getActionCommand();
+   
+        if (command.equals(GEMSConstants.ADD_ATTRIBUTE)){
+	    addAttribute();
+ 	    return ;
+	}
+       
+       if (command.equals(GEMSConstants.DELETE_ATTRIBUTE)){
+           deleteAttribute();
+	}   
+           
+    }
+
+    public void addNewLanguage(String lang) {
+	AttributeTableModel model = (AttributeTableModel)getModel();
+	model.addNewLanguage(lang);
+    }
+
+    public void metadataElementChanged(MetadataElementEvent mee){
+	MetadataElementModel model = mee.getMetadataElementModel();      
+        if (model == null){ //this model has been deleted
+	    setModel(new DefaultTableModel());
+            return;
+	} 
+	populateAttributeTable(model);
+    }
+
+    public void metadataSetChanged(MetadataSetEvent mse){
+	MetadataSetInfo info = mse.getMetadataSetInfo();
+	if (info == null){
+	    setModel(new DefaultTableModel());
+	    return;
+	}
+        populateAttributeTable(info);
+    }
+    
+    public void addAttributeListener(AttributeListener al){
+	if (!listeners.contains(al)){
+	    listeners.add(al);    
+	}
+    }
+
+    public void removeAttributeListener(AttributeListener al){
+	listeners.remove(al);   
+    }
+
+    private void addAttribute(){
+	AttributeTableModel model = (AttributeTableModel)getModel();
+	model.addNewRow();
+    }
+
+   
+    private void deleteAttribute(){
+	int index = getSelectedRow();
+	AttributeTableModel model = (AttributeTableModel)getModel();
+	model.deleteRow(index);
+    }
+    
+    private void populateAttributeTable(AttributeContainer container){
+	AttributeTableModel model = new AttributeTableModel(container, language_dependent);
+	setModel(model);
+	TableColumnModel tcm = getColumnModel();
+	if (language_dependent) {
+	    tcm.getColumn(0).setPreferredWidth(100);
+	    tcm.getColumn(1).setPreferredWidth(50);
+	    tcm.getColumn(2).setPreferredWidth(350);         
+	}
+	else {
+	    tcm.getColumn(0).setPreferredWidth(100);
+	    tcm.getColumn(1).setPreferredWidth(400);         
+	} 
+    }
+
+
+
+    private void notifyListeners(Attribute attr){
+	AttributeEvent ae = new AttributeEvent(attr);
+	for(int i=0;i<listeners.size();i++){
+	    AttributeListener al = (AttributeListener) listeners.get(i);
+	    al.attributeChanged(ae);
+	    
+	}
+    }
+
+
+
+    protected class AttributeTableModel extends AbstractTableModel {
+    
+	AttributeContainer attribute_container;
+	ArrayList attributes;
+	boolean language_dependent;
+    
+	String[] column_names;
+
+	public AttributeTableModel(AttributeContainer container, boolean lang_dependent) {
+	    attribute_container = container;
+	    language_dependent = lang_dependent;
+	    if (language_dependent) {
+		attributes = container.getLanguageDependentAttributes();
+		column_names = GEMSConstants.LANG_DEPENDENT_ATTRIBUTES_COLUMN_NAMES;
+	    } 
+	    else {
+		attributes = container.getAttributes();
+		column_names = GEMSConstants.ATTRIBUTES_COLUMN_NAMES;
+	    }
+	}
+
+	public int getRowCount(){
+	    return attributes.size();
+	}
+       
+	public String getColumnName(int column){
+	    return column_names[column];
+	}
+	
+	public Class getColumnClass(int columnIndex){
+	    return String.class;
+	}    
+	public int getColumnCount(){
+	    return column_names.length;
+	}
+	public boolean isCellEditable(int row, int col) {
+	    Attribute attr = (Attribute)attributes.get(row);	   
+	    if (col == 0 && attr.isRequired()) return false;
+	    return true;
+	}
+
+	public Object getValueAt(int row, int column){
+	    if (row < attributes.size()){
+		Attribute attr = (Attribute)attributes.get(row);
+		// 	String name = attr.getName();
+		//  if (attr.isRequired()){
+		//    name = "<html><body Color=blue>"+name+"</body></html>";
+		// 	}
+
+		if (column == 0) return attr.getName();
+		if (language_dependent) {
+		    if (column == 1) return attr.getLanguage();
+		    if (column == 2) return attr.getValue();
+		}
+		else {
+		    if (column == 1) return attr.getValue();
+		}
+	    }	
+	    return null; 
+	}	    	    
+
+	public void setValueAt(Object value, int row, int column){    
+	    if (row < attributes.size() && attributes.size()>0 ){
+		Attribute attr = (Attribute)attributes.get(row);
+		if (attr.isRequired() && ((String)value).trim().equals("") && !getValueAt(row,column).equals("")) {
+		    JOptionPane.showMessageDialog(null,Dictionary.get("GEMS.Attribute_Edition_Error_Message"), Dictionary.get("GEMS.Attribute_Edition_Error"),JOptionPane.ERROR_MESSAGE);
+		    return; 
+		}
+		
+		// TODO: check namespace conflict
+		if (column == 0) attr.setName((String)value);
+		else {
+		    if (language_dependent) {
+			if (column == 1) attr.setLanguage((String)value);
+			else if (column == 2) attr.setValue((String)value); 
+		    }
+		    else {
+			if (column == 1) attr.setValue((String)value);
+		    }
+		}
+		notifyListeners(attr);
+
+		/// check this stuff
+		if (attribute_container instanceof MetadataElementModel) {
+		    if (attr.getName().trim().equals(GEMSConstants.NAME_ATTRIBUTE)) {
+			((MetadataElementModel)attribute_container).setName((String)value);
+		    }
+		} else if (attribute_container instanceof MetadataSetInfo) {
+		    ((MetadataSetInfo)attribute_container).infoChanged(); 
+		}
+	    }
+	}
+
+	/** used only for language dependent attribute tables */
+	public void addNewLanguage(String lang)
+	{
+	    if (!language_dependent) return;
+	    int index = attribute_container.languageExists(lang);  
+	    if (index >=0){
+		this_table.getSelectionModel().setSelectionInterval(index,index);
+		Rectangle rect = this_table.getCellRect(index, 0, true);
+		this_table.scrollRectToVisible(rect);
+	    }
+	    else {
+		String [] attrNames = attribute_container.getLanguageDependentAttributeNames();
+		if (attrNames == null){
+		    JOptionPane.showMessageDialog(null,Dictionary.get("GEMS.Add_Lang_Depend_Attr_Error_Message"),Dictionary.get("GEMS.Add_Lang_Depend_Attr_Error"),JOptionPane.ERROR_MESSAGE);
+		    return ;
+		}
+		for(int i=0;i<attrNames.length;i++){
+		    Attribute attr = new Attribute(attrNames[i].trim(),"", true);
+		    attr.setLanguage(lang);
+		    attributes.add(attr); 
+		    notifyListeners(attr);
+		}
+		fireTableDataChanged();
+		// first att from new lot
+		int first_new_att_index = attributes.size()-attrNames.length;
+		this_table.editCellAt(first_new_att_index, 2);
+		if (this_table.isEditing()) {
+		    this_table.getEditorComponent().requestFocus();
+		}
+	    
+		this_table.getSelectionModel().setSelectionInterval(attributes.size()-attrNames.length,attributes.size()-1); 
+		Rectangle rect = this_table.getCellRect(attributes.size()-1, 0, true);
+		this_table.scrollRectToVisible(rect); 
+	    }
+	}
+    
+	/* not currently used */
+	public void addNewRow(){
+	    Attribute attr = new Attribute();
+	    attributes.add(attr);
+	    fireTableDataChanged(); 
+	    this_table.getSelectionModel().setSelectionInterval(attributes.size()-1,attributes.size()-1);
+	    Rectangle rect = this_table.getCellRect(attributes.size()-1, 0, true);
+	    this_table.scrollRectToVisible(rect);    
+	}
+
+	/* not currently used */
+	public void deleteRow(int index){           
+	    if (index < attributes.size() && index >=0){
+		Attribute attr = (Attribute)attributes.get(index);          
+		if (attr.isRequired()){
+		    JOptionPane.showMessageDialog(null,Dictionary.get("GEMS.Attribute_Deletion_Error_Message"), Dictionary.get("GEMS.Attribute_Deletion_Error"),JOptionPane.ERROR_MESSAGE);
+		    return;
+		}
+
+		// 		int result = JOptionPane.showOptionDialog(null, Dictionary.get("GEMS.Confirm_Removal", Dictionary.get("GEMS.Attribute") + " " +  Dictionary.get("GEMS.Cannot_Undo")), Dictionary.get("GEMS.Confirm_Removal_Title"), JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE,null,GEMSConstants.DIALOG_OPTIONS,GEMSConstants.DIALOG_OPTIONS[0] );
+         	
+		//if (result !=JOptionPane.OK_OPTION) return;
+		notifyListeners(attr);
+		attributes.remove(index);
+		fireTableDataChanged();  
+	    }
+	
+	}
+    
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/DeleteMetadataSetPrompt.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/DeleteMetadataSetPrompt.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/DeleteMetadataSetPrompt.java	(revision 13928)
@@ -0,0 +1,273 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gems;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Vector;
+import java.util.HashMap;
+
+
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.gui.ModalDialog;
+import org.greenstone.gatherer.gui.GLIButton;
+
+public class DeleteMetadataSetPrompt 
+    extends ModalDialog { 
+
+    static private Dimension SIZE = new Dimension(500, 500);
+        
+    private ArrayList available_metadata_sets;
+    private ArrayList listeners;
+
+    private JCheckBox confirmation = null;
+    private JButton delete_button = null;
+    private JButton close_button = null;    
+    private JList available_set_list = null;
+    /** The model behind the list. */
+    private DefaultListModel list_model = null;
+    private JTextArea description_textarea = null;
+    private DeleteMetadataSetPrompt self;
+    private MetadataSetManager meta_manager;
+  
+    public DeleteMetadataSetPrompt(Frame parent,MetadataSetManager msm) {
+	super(parent, true);
+
+        self = this;
+	meta_manager = msm;
+        listeners = new ArrayList();      
+
+	setSize(SIZE);
+	setTitle(Dictionary.get("GEMS.DeleteMetadataSetPrompt.Title"));
+   
+	JPanel content_pane = (JPanel) getContentPane();
+        content_pane.setOpaque(true);
+	
+
+	JLabel available_metadata_sets_label = new JLabel(Dictionary.get("GEMS.DeleteMetadataSetPrompt.Available_Sets"));
+	available_metadata_sets_label.setOpaque(true);
+	
+	list_model = new DefaultListModel();
+	
+        available_set_list = new JList();
+	available_set_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+	available_set_list.setModel(list_model);
+	available_set_list.setCellRenderer(new MetadatSetListCellRenderer()); 
+	available_set_list.setFixedCellHeight(20);
+	available_set_list.addListSelectionListener(new MetadataSetListSelectionListener());
+
+	JPanel set_pane = new JPanel();
+        set_pane.setLayout(new BorderLayout());
+        set_pane.add(available_metadata_sets_label,BorderLayout.NORTH);
+	set_pane.add(new JScrollPane(available_set_list),BorderLayout.CENTER);
+
+
+	JLabel metadata_set_des_label = new JLabel(Dictionary.get("GEMS.Set_Description"));
+	metadata_set_des_label.setOpaque(true);
+
+	description_textarea = new JTextArea();
+        description_textarea.setOpaque(true);
+        description_textarea.setEditable(false);
+        description_textarea.setLineWrap(true); 
+        description_textarea.setWrapStyleWord(true);
+	
+	JPanel des_pane = new JPanel();
+        des_pane.setLayout(new BorderLayout());
+        des_pane.add(metadata_set_des_label,BorderLayout.NORTH);
+	des_pane.add(new JScrollPane(description_textarea),BorderLayout.CENTER);
+	
+	JPanel button_pane = new JPanel();
+	delete_button = new GLIButton(Dictionary.get("GEMS.DeleteMetadataSetPrompt.Delete"), Dictionary.get("GEMS.DeleteMetadataSetPrompt.Delete_Tooltip"));
+	delete_button.setEnabled(false);
+	
+
+	confirmation = new JCheckBox(Dictionary.get("GEMS.DeleteMetadataSetPrompt.Confirm_Delete"));
+	confirmation.setEnabled(false);
+	confirmation.setSelected(false);
+
+	close_button = new GLIButton(Dictionary.get("General.Close"), Dictionary.get("General.Close_Tooltip"));
+	close_button.setEnabled(true);
+
+	confirmation.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent event) {
+		    delete_button.setEnabled(confirmation.isSelected());
+		    //confirmation.setEnabled(false);
+		    //confirmation.setSelected(false);
+		}
+	    });
+
+	// Add listeners
+	delete_button.addActionListener(new DeleteButtonListener());
+	
+	close_button.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent event) {
+		    self.dispose();
+		}
+	    });
+
+       
+	button_pane.setLayout(new GridLayout(1,2));
+	button_pane.add(delete_button);
+	button_pane.add(close_button);
+
+        JPanel bottom_pane = new JPanel();
+        bottom_pane.setLayout(new BorderLayout());
+	bottom_pane.add(confirmation,BorderLayout.NORTH);
+	bottom_pane.add(button_pane, BorderLayout.CENTER);
+
+
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(set_pane, BorderLayout.NORTH);
+	content_pane.add(des_pane, BorderLayout.CENTER);
+	content_pane.add(bottom_pane, BorderLayout.SOUTH);
+	
+	// Show
+	Dimension screen_size = Configuration.screen_size;
+	setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+	setVisible(false);
+    }
+
+      
+    public void display() {
+	available_metadata_sets = meta_manager.getAvailableMetadataSets();
+	for (int i=0; i<available_metadata_sets.size(); i++) {
+	    list_model.addElement(available_metadata_sets.get(i));
+	}
+	//available_set_list.setListData(new Vector((Collection)available_metadata_sets));
+	delete_button.setEnabled(false);
+	confirmation.setEnabled(false);
+	confirmation.setSelected(false);
+       	setVisible(true); 
+        
+    }
+
+
+    /** The Delete button listener implementation. */
+    private class DeleteButtonListener 
+	implements ActionListener {
+	/** Any implementation of ActionListener must include this method so we can be informed when the button is actioned.
+	 * @param event An <strong>ActionEvent</strong> containing all the relevant information garnered from the event itself.
+	 * @see org.greenstone.gatherer.Configuration
+	 * @see org.greenstone.gatherer.Gatherer
+	 * @see org.greenstone.gatherer.util.Utility
+	 */
+	public void actionPerformed(ActionEvent event) {
+	    // Delete the selected MetadataSet.
+	    Object selectedValue = available_set_list.getSelectedValue();
+		
+	    if (selectedValue !=null && (selectedValue instanceof MetadataSetInfo)){
+		((MetadataSetInfo)selectedValue).deleteMetadataSet();
+		list_model.removeElement(selectedValue);
+	    }
+	    delete_button.setEnabled(false);
+	    confirmation.setEnabled(false);
+	    confirmation.setSelected(false);
+	    description_textarea.setText(Dictionary.get("GEMS.DeleteMetadataSetPrompt.No_Set"));
+	    //self.dispose();
+	}
+
+    }
+
+
+    private class MetadatSetListCellRenderer extends JLabel implements ListCellRenderer {
+	public MetadatSetListCellRenderer() {
+	    setOpaque(true);
+	}
+	
+	public Component getListCellRendererComponent(JList list,
+						      Object value,
+						      int index,
+						      boolean isSelected,
+						      boolean cellHasFocus)
+	{
+	    String name= "unknown";
+
+	    if (value instanceof MetadataSetInfo){
+		MetadataSetInfo meta_info = (MetadataSetInfo) value;
+		name = meta_info.getMetadataSetName(); 
+	    }
+  
+            setText(name);
+            if (isSelected) {
+		setBackground(list.getSelectionBackground());
+		setForeground(list.getSelectionForeground());
+	    }
+	    else {
+		setBackground(list.getBackground());
+		setForeground(list.getForeground());
+	    }
+	              
+	    return this;
+	}
+    }
+
+   
+    private class MetadataSetListSelectionListener implements ListSelectionListener  {
+        public void valueChanged(ListSelectionEvent lse){
+	    if (lse.getValueIsAdjusting()) return;
+	    
+	    delete_button.setEnabled(false);
+	   
+	    Object selectedValue = available_set_list.getSelectedValue();
+
+            if (selectedValue !=null && (selectedValue instanceof MetadataSetInfo)){
+                MetadataSetInfo meta_info = (MetadataSetInfo)selectedValue; 
+		description_textarea.setText(meta_info.getMetadataSetDescription());
+		confirmation.setEnabled(true);
+		confirmation.setSelected(false);
+	    }
+	    else {
+		confirmation.setEnabled(false);
+		description_textarea.setText(Dictionary.get("GEMS.DeleteMetadataSetPrompt.No_Set"));
+	    }      
+
+	}
+    }
+    
+
+    
+    public void addMetadataSetListener(MetadataSetListener msl){
+        listeners.add(msl);  
+    }
+
+
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/GEMS.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/GEMS.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/GEMS.java	(revision 13928)
@@ -0,0 +1,583 @@
+ /**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at th * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################## ##########################
+ */
+package org.greenstone.gatherer.gems;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import javax.swing.*;
+import java.lang.String;
+import javax.swing.event.*;
+import javax.swing.filechooser.*;
+import javax.swing.text.*;
+import javax.swing.tree.*;
+import java.awt.*;
+import java.awt.event.*;
+
+import java.io.File;
+
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.GetOpt;
+import org.greenstone.gatherer.gui.GComboBox;
+import org.greenstone.gatherer.gui.GLIButton;
+import org.greenstone.gatherer.gui.HelpFrame;
+import org.greenstone.gatherer.gui.ModalDialog;
+import org.greenstone.gatherer.gui.NonWhitespaceField;
+import org.greenstone.gatherer.util.Codec;
+import org.greenstone.gatherer.util.JarTools;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.util.XMLTools;
+import org.greenstone.gatherer.Dictionary;
+import org.w3c.dom.*;
+
+
+/* 
+ * @author Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ * @version 2.4
+ */ 
+public class GEMS
+    extends JFrame implements WindowFocusListener 
+{
+ 
+    static final private Dimension SIZE = new Dimension(800,550);
+
+    // we have a card pane to switch between the no set loaded view, and the 
+    // set loaded view
+    private CardLayout card_layout = null;
+    private JPanel card_pane = null;
+    /** The name of the panel containing the "set loaded" card. */
+    private String SET_LOADED_CARD = "";
+    /** The name of the panel containing the "no set loaded" placeholder */
+    private String NO_SET_LOADED_CARD = "No set loaded";
+
+    private GEMS self = null;
+
+    private OpenMetadataSetPrompt open_prompt;
+    private DeleteMetadataSetPrompt delete_prompt;
+    private NewMetadataSetPrompt new_prompt;   
+    
+    // this is the main panel that gets switched in once a set is loaded
+    private JSplitPane metadata_set_details_split_pane = null;
+    // this is the split with the attribute tables in it
+    private JSplitPane attribute_tables_split_pane = null;
+     
+    /** Um, the size of the screen I'd guess. */
+    private Dimension screen_size = null;
+    
+    private MetadataSetManager msm;
+
+    private AttributeTable attribute_table;  // meta_element_table
+    private AttributeTable language_dependent_attribute_table; //lang_element_table; 
+
+    private MetadataSetTree meta_set_tree;     
+
+    private MetadataSetModel metadata_set_model;
+
+    private boolean stand_alone = true;
+
+    private ArrayList listeners;
+
+    static public void main(String[] args)
+    {
+	//TODO: add an option to open a paticular metadata set
+
+	// Parse arguments
+	GetOpt go = new GetOpt(args);
+
+	if (go.debug) {
+	    DebugStream.enableDebugging();
+
+	    Calendar now = Calendar.getInstance();
+	    String debug_file_path = "debug" + now.get(Calendar.DATE) + "-" + now.get(Calendar.MONTH) + "-" + now.get(Calendar.YEAR) + ".txt";
+	    
+	    // Debug file is created in the GLI directory
+	    DebugStream.println("Debug file path: " + debug_file_path);
+	    DebugStream.setDebugFile(debug_file_path);   
+
+	}
+
+	  new GEMS(go.gsdl_path,go.gsdl3_path,go.metadata_path,true,go.new_set);
+       
+    }
+
+
+    /** Constructor.
+     */
+    public GEMS(String gsdl_path, String gsdl3_path, String metadata_path, boolean standalone, boolean new_set)
+    {
+	self = this;
+	JarTools.initialise(this);        
+	screen_size = Configuration.screen_size;
+        msm = new MetadataSetManager(gsdl_path,gsdl3_path);       
+        stand_alone = standalone;
+	listeners = new ArrayList();
+
+        addWindowListener(new WindowAdapter(){
+		public void windowClosing(WindowEvent e){
+		    metadata_set_model.save(true);
+		    if (stand_alone){
+			System.exit(0);
+		    }
+		    else {
+			notifyListeners();
+			setVisible(false);
+		    }
+		}
+	    });
+	
+	setSize(SIZE);
+	setTitle(Dictionary.get("GEMS.Title"));
+	setJMenuBar(new GEMSMenuBar());
+
+	addWindowFocusListener(this);
+
+	card_layout = new CardLayout();
+	card_pane = new JPanel();
+
+        metadata_set_model = new MetadataSetModel(msm);
+        msm.setMetadataSetModel(metadata_set_model);
+	meta_set_tree = new MetadataSetTree(self);
+        metadata_set_model.addObserver(meta_set_tree);
+
+	attribute_table = new AttributeTable(false);
+	MetadataElementModel mem = new MetadataElementModel();
+        mem.addMetadataElementListener((MetadataElementListener)attribute_table);
+	attribute_table.addAttributeListener(metadata_set_model);
+
+	language_dependent_attribute_table = new AttributeTable(true);
+        mem.addMetadataElementListener((MetadataElementListener)language_dependent_attribute_table);
+	language_dependent_attribute_table.addAttributeListener(metadata_set_model);
+
+      	MetadataSetInfo msti= new MetadataSetInfo();
+        msti.addMetadataSetListener((MetadataSetListener)attribute_table);
+        msti.addMetadataSetListener((MetadataSetListener)language_dependent_attribute_table);
+        msti.setMetadataSetModel(metadata_set_model);
+        
+        open_prompt = new OpenMetadataSetPrompt(self,msm);
+        open_prompt.addMetadataSetListener((MetadataSetListener)metadata_set_model);
+        open_prompt.addMetadataSetListener((MetadataSetListener)attribute_table);        
+	open_prompt.addMetadataSetListener((MetadataSetListener)language_dependent_attribute_table); 	
+	
+        delete_prompt = new DeleteMetadataSetPrompt(self,msm);
+        delete_prompt.addMetadataSetListener((MetadataSetListener)metadata_set_model); 
+        delete_prompt.addMetadataSetListener((MetadataSetListener)attribute_table);
+	delete_prompt.addMetadataSetListener((MetadataSetListener)language_dependent_attribute_table);
+	
+        new_prompt = new NewMetadataSetPrompt(self,msm);
+        new_prompt.addMetadataSetListener((MetadataSetListener)metadata_set_model); 
+        new_prompt.addMetadataSetListener((MetadataSetListener)attribute_table);
+        new_prompt.addMetadataSetListener((MetadataSetListener)language_dependent_attribute_table);
+  
+
+        // load the initial metadataset
+        if (metadata_path !=null && !metadata_path.equals("")){
+	    open_prompt.openMetadataSet(metadata_path);
+	}
+	else{
+	    if (new_set) new_prompt.display();
+	}
+
+	// the set tree
+        JScrollPane treePane = new JScrollPane(meta_set_tree);
+	// the language independent attributes
+	JScrollPane tablePane = new JScrollPane(attribute_table);
+	// the language dependent attributes
+	JScrollPane langTablePane =  new JScrollPane(language_dependent_attribute_table);
+
+	// no set loaded pane
+	JPanel no_set_loaded_pane = new JPanel();
+	no_set_loaded_pane.setBackground(Color.lightGray);
+	JLabel no_set_loaded_label = new JLabel(Dictionary.get("GEMS.No_Set_Loaded"));
+	no_set_loaded_label.setHorizontalAlignment(JLabel.CENTER);
+	no_set_loaded_label.setVerticalAlignment(JLabel.CENTER);
+
+	no_set_loaded_pane.setLayout(new BorderLayout());
+	no_set_loaded_pane.add(no_set_loaded_label, BorderLayout.CENTER);
+
+        JPanel buttonPane = new JPanel(new GridLayout(1,2));
+        
+        JButton arrow_up_button = new GLIButton(Dictionary.get("GEMS.Move_Up"));
+	arrow_up_button.setIcon(JarTools.getImage("arrow-up.gif"));
+
+        JButton arrow_down_button = new GLIButton(Dictionary.get("GEMS.Move_Down"));
+	arrow_down_button.setIcon(JarTools.getImage("arrow-down.gif")); 
+        
+        arrow_up_button.setActionCommand(GEMSConstants.MOVE_UP);
+	arrow_up_button.addActionListener(meta_set_tree);
+        arrow_down_button.addActionListener(meta_set_tree);
+	arrow_down_button.setActionCommand(GEMSConstants.MOVE_DOWN);
+	
+	buttonPane.add(arrow_up_button);
+        buttonPane.add(arrow_down_button);
+        
+        JPanel leftPane =  new JPanel(new BorderLayout());          
+        leftPane.add(treePane,BorderLayout.CENTER);  
+	leftPane.add(buttonPane,BorderLayout.SOUTH);  
+         
+	JLabel selected_language_label = new JLabel(Dictionary.get("GEMS.SelectedLanguage"));
+	selected_language_label.setOpaque(true);
+        
+	Vector language_vector = new Vector(msm.getLanguageList());
+        language_vector.add(0, Dictionary.get("GEMS.Language"));
+	JComboBox language_combo = new JComboBox(language_vector);
+	
+	language_combo.addActionListener(new ActionListener(){
+		public void actionPerformed(ActionEvent e){
+		    JComboBox language_combo = (JComboBox) e.getSource();
+		    String langInfo = (String)language_combo.getSelectedItem(); 
+		    if (!langInfo.equals(Dictionary.get("GEMS.Language"))) {
+			String lang = langInfo.split("\\s")[0];     		    
+			language_dependent_attribute_table.addNewLanguage(lang);
+		    }
+		}
+
+	    });      
+
+       	JLabel language_label = new JLabel(Dictionary.get("GEMS.LanguageDependent"));
+	language_label.setOpaque(true);
+      
+         	
+	JPanel selectLangPane = new JPanel(new BorderLayout(5,5));
+        selectLangPane.add(selected_language_label,BorderLayout.WEST);
+        selectLangPane.add(language_combo, BorderLayout.CENTER);   
+
+
+        JPanel languagePane =  new JPanel(new BorderLayout(5,5));
+	languagePane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	languagePane.add(language_label,BorderLayout.NORTH);  
+        languagePane.add(selectLangPane,BorderLayout.CENTER);        
+
+
+        JPanel languageAttributePane =  new JPanel(new BorderLayout());
+	languageAttributePane.add(languagePane,BorderLayout.NORTH);  
+        languageAttributePane.add(langTablePane,BorderLayout.CENTER);        
+
+	JLabel attribute_label = new JLabel(Dictionary.get("GEMS.Attribute_Table"));
+	attribute_label.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	JPanel mainAttributePane = new JPanel(new BorderLayout());
+	mainAttributePane.add(attribute_label, BorderLayout.NORTH);
+	mainAttributePane.add(tablePane, BorderLayout.CENTER);
+	
+	attribute_tables_split_pane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,mainAttributePane,languageAttributePane);
+	
+	metadata_set_details_split_pane =  new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,leftPane,attribute_tables_split_pane); 	
+
+	card_pane.setLayout(card_layout);
+	card_pane.add(no_set_loaded_pane, NO_SET_LOADED_CARD);
+	card_pane.add(metadata_set_details_split_pane, SET_LOADED_CARD);
+
+	getContentPane().add(card_pane,BorderLayout.CENTER);
+	setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+	if (stand_alone)
+	    setVisible(true);
+    }
+
+    public void setVisible(boolean visible) {
+	super.setVisible(visible);
+	if (visible) {
+	    attribute_tables_split_pane.setDividerLocation(0.3);
+	}
+    }
+    
+    // called from GLI
+    public void displayMetadataSet(String metadata_path){
+	open_prompt.openMetadataSet(metadata_path);
+	updateCardLayout(true);
+	setVisible(true);
+    }   
+
+    // called from GLI
+    public void newMetadataSet(){
+	new_prompt.display();
+	if (!new_prompt.isCancelled()) {
+	    updateCardLayout(true);
+	    setVisible(true);
+	}
+
+    }
+
+    public void addGEMSListener(GEMSListener listener){
+	listeners.add(listener);
+    }  
+
+    public void removeGEMSListener(GEMSListener listener){
+	listeners.remove(listener);
+    }  
+
+    public void notifyListeners(){
+	for (int i=0;i<listeners.size();i++){
+	    GEMSListener listener = (GEMSListener) listeners.get(i); 
+	    listener.gemsIsClosed();
+	}
+    }
+
+
+    public void exit(){
+	//clean up things
+	cleanUpListeners();
+    }
+    
+    protected void cleanUpListeners() {
+	MetadataSetInfo msti= new MetadataSetInfo();
+	msti.removeAllMetadataSetListeners();
+	MetadataElementModel mem= new MetadataElementModel();
+	mem.removeAllMetadataElementListeners();
+
+    }
+    
+    public void windowGainedFocus(WindowEvent e) {
+	//System.out.println("windowGainedFocus.");
+    }
+
+    public void windowLostFocus(WindowEvent e) {
+        //System.out.println("windowLostFocus.");
+          
+	//save stuff
+	
+    }
+
+    protected void updateCardLayout(boolean set_loaded) {
+	if (set_loaded) {
+	    card_layout.show(card_pane, SET_LOADED_CARD);
+	} else {
+	    card_layout.show(card_pane, NO_SET_LOADED_CARD);
+	}
+    }
+   
+    private class GEMSMenuBar
+	extends JMenuBar
+	implements ActionListener
+    {
+	private JMenu file = null;
+	private JMenu edit = null;
+
+	public JMenuItem file_exit   = null;
+	public JMenuItem file_new    = null;
+	public JMenuItem file_open   = null;
+	public JMenuItem file_close   = null;
+	public JMenuItem file_save   = null;
+	public JMenuItem edit_copy   = null;
+	public JMenuItem edit_cut    = null;
+	public JMenuItem edit_paste  = null;
+	public JMenuItem help_help   = null;
+        public JMenuItem file_delete = null;
+        //public JMenuItem file_preferences = null;
+	public GEMSMenuBar()
+	{
+	    file = new JMenu();
+	    file.setText(Dictionary.get("Menu.File"));
+	    
+	    file_exit = new JMenuItem(Dictionary.get("Menu.File_Exit"));
+	    file_exit.addActionListener(this);
+	    
+	    file_new = new JMenuItem(Dictionary.get("Menu.File_New"));
+	    file_new.addActionListener(this);
+
+	    file_open = new JMenuItem(Dictionary.get("Menu.File_Open"));
+	    file_open.addActionListener(this);
+	    
+	    file_close = new JMenuItem(Dictionary.get("Menu.File_Close"));
+	    file_close.addActionListener(this);
+
+	    file_save = new JMenuItem(Dictionary.get("Menu.File_Save"));
+	    file_save.addActionListener(this);
+   
+            file_delete = new JMenuItem(Dictionary.get("Menu.File_Delete"));
+	    file_delete.addActionListener(this);
+	                
+            //file_preferences = new JMenuItem(Dictionary.get("Menu.File_Options"));
+	    //file_preferences.addActionListener(this);
+	    
+	    if (!stand_alone) {
+		// when running from GLI, we disable most of the menu so 
+		// that we have control over what sets the user is editing
+		file_new.setEnabled(false);
+		file_open.setEnabled(false);
+		file_close.setEnabled(false);
+		file_delete.setEnabled(false);
+	    }
+	    
+	    // Layout (file menu)
+	    file.add(file_new);
+	    file.add(file_open);
+	    file.add(file_close);
+	    file.add(file_save);
+            file.add(file_delete);
+	    file.add(new JSeparator());
+            //file.add(file_preferences);
+            //file.add(new JSeparator());
+	    file.add(file_exit);
+            
+	    // Edit menu
+	    edit = new JMenu();
+	    edit.setText(Dictionary.get("Menu.Edit"));
+	    
+	    edit_cut = new JMenuItem(Dictionary.get("Menu.Edit_Cut"));
+	    edit_cut.addActionListener(this);
+	    
+	    edit_copy = new JMenuItem(Dictionary.get("Menu.Edit_Copy"));
+	    edit_copy.addActionListener(this);
+	    
+	    edit_paste = new JMenuItem(Dictionary.get("Menu.Edit_Paste"));
+	    edit_paste.addActionListener(this);
+	    
+	    // Layout (edit menu)
+	    edit.add(edit_cut);
+	    edit.add(edit_copy);
+	    edit.add(edit_paste);
+
+	
+	    // Layout (menu bar)
+	    this.add(file);
+	    this.add(Box.createHorizontalStrut(15));
+	    this.add(edit);
+	    this.add(Box.createHorizontalGlue());
+	    //this.add(help);
+	}
+
+
+	public void actionPerformed(ActionEvent event)
+	{
+	    Object event_source = event.getSource();
+
+	    // File -> New
+	    if (event_source == file_new) {
+		new_prompt.display();
+		if (!new_prompt.isCancelled()) {
+		    updateCardLayout(true);
+		}
+ 		return;
+	    }
+
+	    // File -> Open
+	    if (event_source == file_open) {               
+		open_prompt.display();
+		if (!open_prompt.isCancelled()) {
+		    updateCardLayout(true);
+		}
+		return;
+	    }
+
+	    // File -> Close
+	    if (event_source == file_close) {
+		metadata_set_model.save(true); 
+		updateCardLayout(false);
+		return;
+	    }
+              // File -> Delete
+	    if (event_source == file_delete) {               
+                delete_prompt.display();
+		return;
+	    }
+
+
+	    // File -> Save
+	    if (event_source == file_save) {
+		metadata_set_model.save(false);
+		return;
+	    }        
+
+	    // File -> Exit
+	    if (event_source == file_exit) {
+               	metadata_set_model.save(true); 
+		if (stand_alone){
+		    System.exit(0);
+		}
+		else {
+		    self.notifyListeners();
+		    self.setVisible(false);
+		    return;
+		}
+	    }
+
+	    /// File -> Preferences
+	    // if(event_source == file_preferences){
+		// GEMSPreferences GemsPreferences = new GEMSPreferences();  
+            //}
+
+	    // Edit -> Cut
+	    if (event_source == edit_cut) {
+		try {
+		    KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
+		    // Get the component with selected text as a JTextComponent
+		    JTextComponent text = (JTextComponent) kfm.getPermanentFocusOwner();
+		    // Cut the text to the clipboard
+		    text.cut();
+		}
+		catch (ClassCastException cce) {
+		    // If the component is not a text component ignore the cut command
+		    DebugStream.println(cce.toString());
+		}
+		return;
+	    }
+
+	    // Edit -> Copy
+	    if (event_source == edit_copy) {
+		try {
+		    KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
+		    // Get the component with selected text as a JTextComponent
+		    JTextComponent text = (JTextComponent) kfm.getPermanentFocusOwner();//getFocusOwner();
+		    text.copy();
+		}
+		catch (Exception cce) {
+		    // If the component is not a text component ignore the copy command
+		    DebugStream.println(cce.toString());
+		}
+		return;
+	    }
+
+	    // Edit -> Paste
+	    if (event_source == edit_paste) {
+		try {
+		    KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
+		    // Get the component with selected text as a JTextComponent
+		    JTextComponent text = (JTextComponent) kfm.getPermanentFocusOwner();
+		    // Cut the text to the clipboard
+		    text.paste();
+		}
+		catch (ClassCastException cce) {
+		    // If the component is not a text component ignore the paste command
+		    DebugStream.println(cce.toString());
+		}
+		return;
+	    }
+	  
+	}
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/GEMSConstants.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/GEMSConstants.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/GEMSConstants.java	(revision 13928)
@@ -0,0 +1,94 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gems;
+
+import org.greenstone.gatherer.Dictionary;
+
+public class GEMSConstants
+{
+    
+    static String NAMESPACE_ATTRIBUTE = "namespace";
+    static String NAME_ATTRIBUTE = "name";
+    static String DESCRIPTION_ATTRIBUTE = "description";
+    static String CODE_ATTRIBUTE = "code";
+    static String LANGUAGE_ATTRIBUTE = "language";
+    static String SET_LANGUAGE_ELEMENT = "SetLanguage";
+    static String LANGUAGE_ELEMENT = "Language";
+    static String NAME_ELEMENT = "Name";
+    static String DESCRIPTION_ELEMENT = "Description";
+    static String DEFAULT_LANGUAGE ="en";
+    static String ATTRIBUTE_ELEMENT="Attribute";
+    static String ELEMENT_ELEMENT="Element";  
+    static String METADATASET_ELEMENT="MetadataSet"; 
+    static String ADD_ATTRIBUTE = "addAttribute";
+    static String DELETE_ATTRIBUTE = "deleteAttribute";
+    static String ADD_ELEMENT = "addElement";
+    static String ADD_SUBELEMENT = "addSubElement";
+    static String DELETE_ELEMENT = "deleteElement";
+    static int METADATA_INFO = 0;
+    static int METADATA_ELEMENT = 0;
+    static String NEW_ELEMENT = "ELEMENT";
+    static String MOVE_UP = "moveUp";
+    static String MOVE_DOWN = "moveDown"; 
+    static String EXTRACTED_METADATA_NAMESPACE = "ex";
+
+    static String[] SET_REQUIRED_ATTRIBUTES = new String[]{"contact","creator","family","lastchanged","namespace"};
+    static String[] SET_LANG_DEPEND_ATTR_NAMES = new String[]{"name","description"};
+
+    static String UNKNOWN_NAME="unknown";  
+
+    static String MATADATASET_NAME="MetadataSet";
+    
+    static String SYSTEM_ID = "http://www.greenstone.org/dtd/MetadataSet/1.0/MetadataSet.dtd";
+
+    static String[] DIALOG_OPTIONS = new String[]{Dictionary.get("General.OK"),Dictionary.get("General.Cancel")};
+
+    static String LABEL_ATTRIBUTE = "label";
+    static String DEFINITION_ATTRIBUTE = "definition";
+    static String COMMENT_ATTRIBUTE = "comment";
+
+    static String [] ELEMENT_REQUIRED_ATTRIBUTES = new String[] {"name"};
+    
+    static String [] ELEMENT_LANG_DEPEND_ATTR_NAMES = new String[] {LABEL_ATTRIBUTE, DEFINITION_ATTRIBUTE, COMMENT_ATTRIBUTE};
+
+    static String [] ATTRIBUTES_COLUMN_NAMES = new String [] {
+	Dictionary.get("GEMS.AttributeTable.Name"), Dictionary.get("GEMS.AttributeTable.Value")};
+    static String [] LANG_DEPENDENT_ATTRIBUTES_COLUMN_NAMES = new String [] {
+	Dictionary.get("GEMS.AttributeTable.Name"), Dictionary.get("GEMS.AttributeTable.Language"), Dictionary.get("GEMS.AttributeTable.Value")};
+
+    static String METADATA_SET_FILE_EXTENSION = ".mds";
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/GEMSListener.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/GEMSListener.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/GEMSListener.java	(revision 13928)
@@ -0,0 +1,43 @@
+
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at th * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################## ##########################
+ */
+package org.greenstone.gatherer.gems;
+
+public interface GEMSListener{
+
+    public void gemsIsClosed();
+
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataElementEvent.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataElementEvent.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataElementEvent.java	(revision 13928)
@@ -0,0 +1,50 @@
+
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at th * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################## ##########################
+ */
+package org.greenstone.gatherer.gems;
+
+public class MetadataElementEvent{
+    private MetadataElementModel meta_element;
+
+    public MetadataElementEvent(MetadataElementModel mee){
+	meta_element = mee;
+
+    }
+
+    public MetadataElementModel getMetadataElementModel(){
+	return  meta_element;
+    } 
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataElementListener.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataElementListener.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataElementListener.java	(revision 13928)
@@ -0,0 +1,43 @@
+
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at th * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################## ##########################
+ */
+package org.greenstone.gatherer.gems;
+
+public interface MetadataElementListener{
+
+    public void metadataElementChanged(MetadataElementEvent mse);
+
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataElementModel.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataElementModel.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataElementModel.java	(revision 13928)
@@ -0,0 +1,350 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gems;
+
+import org.greenstone.gatherer.util.XMLTools;
+import org.greenstone.gatherer.Configuration;
+
+import org.w3c.dom.Document;
+import  org.w3c.dom.Element;
+import  org.w3c.dom.Text;
+import  org.w3c.dom.Node;
+
+import java.util.Observable ;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * @author Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ * @version 2.4
+ */
+public class MetadataElementModel
+    extends AttributeContainer 
+{
+    private Element metadata_element;
+    private ArrayList children;
+    private MetadataElementModel parent;
+    private static ArrayList listeners = new ArrayList(); 
+    private MetadataSetInfo metadataSetInfo;
+    private String name;
+    private static int count = 0;    
+    
+    public MetadataElementModel(){}
+    
+    // do we need this one?
+    public MetadataElementModel(MetadataSetInfo info){
+	this(info, null);
+    }
+    
+    public MetadataElementModel(MetadataSetInfo info, String new_name){
+	super(null, GEMSConstants.ELEMENT_LANG_DEPEND_ATTR_NAMES);
+	required_attribute_names = GEMSConstants.ELEMENT_REQUIRED_ATTRIBUTES;
+	metadataSetInfo = info;
+	children = new ArrayList(); 
+	if (new_name != null) {
+	    name = new_name;       
+	} else {
+	    name = GEMSConstants.NEW_ELEMENT+(count++);  
+	}
+	// add name in as an attribute - lang independent
+	Attribute attr = new Attribute(GEMSConstants.NAME_ATTRIBUTE, name, true);
+	attributes.add(attr);
+	// also add in a default label attribute
+	attr = getAttributeByNameAndLanguage(GEMSConstants.LABEL_ATTRIBUTE, Configuration.getLanguage());
+	attr.setValue(name);
+
+    }
+     
+    public MetadataElementModel(Element metadataElement, MetadataSetInfo info){
+	super(null, null);
+	required_attribute_names = GEMSConstants.ELEMENT_REQUIRED_ATTRIBUTES;
+	language_dependent_attribute_names = GEMSConstants.ELEMENT_LANG_DEPEND_ATTR_NAMES;
+	metadataSetInfo = info;
+	metadata_element = metadataElement;
+	
+	children = new ArrayList(); 
+	
+	constructModel(metadata_element);     
+	
+	ArrayList child_elements =XMLTools.getChildElementsByTagName(metadata_element,GEMSConstants.ELEMENT_ELEMENT);
+	
+	for(int i=0;i<child_elements.size();i++){    
+	    Element element = (Element)child_elements.get(i);
+	    MetadataElementModel submodel = new MetadataElementModel(element,metadataSetInfo); 
+	    submodel.setParent(this);    
+	    children.add(submodel);
+	}
+    }
+    
+    private void constructModel(Element meta_element){
+	name = meta_element.getAttribute(GEMSConstants.NAME_ATTRIBUTE);
+	
+	// add name in as an attribute - the only lang independent one
+	Attribute attr = new Attribute(GEMSConstants.NAME_ATTRIBUTE, name, true);
+	attributes.add(attr);
+
+	// common attributes
+	ArrayList attribute_nodes =XMLTools.getChildElementsByTagName(metadata_element,GEMSConstants.ATTRIBUTE_ELEMENT);
+	  
+	for(int i=0;i< attribute_nodes.size();i++){
+	    Element attr_element = (Element)attribute_nodes.get(i);
+	    String name = attr_element.getAttribute(GEMSConstants.NAME_ATTRIBUTE).trim();
+	     
+	    String value =  XMLTools.getElementTextValue(attr_element);
+	    attr = new Attribute(name,value);
+	    String lang = attr_element.getAttribute(GEMSConstants.LANGUAGE_ATTRIBUTE);
+	    if (lang.equals("")) {
+		// lang independent
+		attr.setRequired(isAttributeRequired(name));
+		attributes.add(attr);
+	    } else {
+		attr.setLanguage(lang);
+		attr.setRequired(isLangDependentAttributeRequired(name));
+		language_dependent_attributes.add(attr);
+	    }  
+	}
+	
+	//language specific attribute  
+	ArrayList language_elements =XMLTools.getChildElementsByTagName(metadata_element,GEMSConstants.LANGUAGE_ELEMENT);
+	  
+	for(int i=0;i< language_elements.size();i++){
+	    Element language_element = (Element)language_elements.get(i);
+	    String lang = language_element.getAttribute(GEMSConstants.CODE_ATTRIBUTE);
+	    //Attribute element
+	    ArrayList subattributes =XMLTools.getChildElementsByTagName(language_element,GEMSConstants.ATTRIBUTE_ELEMENT);
+	      
+	    for(int j=0;j< subattributes.size();j++){
+		Element attr_element = (Element)subattributes.get(j);
+		String name = attr_element.getAttribute(GEMSConstants.NAME_ATTRIBUTE).trim();
+		String value =  XMLTools.getElementTextValue(attr_element);
+		attr = new Attribute(name,value, isLangDependentAttributeRequired(name));
+		attr.setLanguage(lang);
+		language_dependent_attributes.add(attr);			    
+	    }
+	      
+	}
+	  
+    }
+      
+    public void addMetadataElementListener(MetadataElementListener msl){
+	if (!listeners.contains(msl))
+	    listeners.add(msl);   
+    }
+      
+
+    public void removeMetadataElementListener(MetadataElementListener msl){
+	listeners.remove(msl);   
+    } 
+      
+    public void removeAllMetadataElementListeners(){
+	listeners.clear();
+    }
+     
+      
+    public boolean doesChildWithThisNameExist(String name) {
+	for (int i=0; i<children.size(); i++) {
+	    if (name.equals(((MetadataElementModel)children.get(i)).getName())) {
+		return true;
+	    }
+	}
+	return false;
+    }
+
+
+    public Element getMetadataElement(){
+	return metadata_element;
+    }
+      
+    public void notifyListeners(boolean isDeleted){
+
+	MetadataElementEvent mee = new MetadataElementEvent(this);
+        if (!isDeleted){
+	    mee = new MetadataElementEvent(this);
+	}
+	else{
+	    mee = new MetadataElementEvent(null);
+	}
+	
+	for(int i=0;i<listeners.size();i++){
+	    MetadataElementListener msl = (MetadataElementListener) listeners.get(i);
+            msl.metadataElementChanged(mee);          
+	}
+    }
+
+    public ArrayList getChildElements(){
+	return children;
+    }
+
+    public void addChild(MetadataElementModel child){
+	metadataSetInfo.getMetadataSetModel().setChanged(true);
+	child.setParent(this);
+	children.add(child);
+    }
+
+    public void removeChild(MetadataElementModel element_model){
+	metadataSetInfo.getMetadataSetModel().setChanged(true);
+	children.remove(element_model);
+    }
+      
+    public String getName(){
+	return name;
+    }
+
+    public void setName(String new_name){
+	metadataSetInfo.getMetadataSetModel().setChanged(true);
+	name = new_name;
+              
+	MetadataSetModel metadata_model = metadataSetInfo.getMetadataSetModel();
+	metadata_model.valueChanged();
+    }
+
+    public String getFullName(){
+	if (parent == null){
+	    return metadataSetInfo.getNamespace() +"."+name;
+	}
+	else{
+	    return parent.getFullName() +"^"+ name;
+	}
+    }
+
+    public void setParent(MetadataElementModel pr){
+	parent = pr;
+    }
+
+    public MetadataElementModel getParent(){
+	return parent;
+    }
+
+        
+    public boolean moveUp(MetadataElementModel child){
+	metadataSetInfo.getMetadataSetModel().setChanged(true);
+	int index = children.indexOf(child);
+	if (index-1 >=0){
+	    children.remove(child);
+	    children.add(index-1,child);
+	    return true;
+	}        
+	return false;
+    }
+
+    public boolean moveDown(MetadataElementModel child){
+	metadataSetInfo.getMetadataSetModel().setChanged(true);
+	int index = children.indexOf(child);
+	if (index+1 < children.size()){
+	    children.remove(child);
+	    children.add(index+1,child);
+	    return true;
+	}        
+
+	return false;
+    }
+
+    public void save(){
+	saveElement();
+	 
+	for(int i=0;i<children.size();i++){
+	    MetadataElementModel model = (MetadataElementModel)children.get(i);
+	    model.save();
+	}   
+	    
+    }
+
+
+    private void saveElement(){
+	Document doc = metadataSetInfo.getMetadataSetDocument();        
+
+	Node parent_element = null;
+	  
+	if (parent !=null){
+	    parent_element = parent.getMetadataElement();
+	}
+	else{
+	    parent_element = doc.getDocumentElement();
+	}
+	  
+	  
+	metadata_element = save(doc);
+
+	parent_element.appendChild(metadata_element); 
+	                           
+	    
+    }
+
+
+    private Element save(Document doc){
+	
+	metadata_element = doc.createElement(GEMSConstants.ELEMENT_ELEMENT);
+	metadata_element.setAttribute(GEMSConstants.NAME_ATTRIBUTE,name);
+              
+	//non language dependent attributes
+	for(int i=0;i<attributes.size();i++){
+	    Attribute attr = (Attribute)attributes.get(i);
+	    if (attr.getName() == null || attr.getName().trim().equals("")) continue;
+	    if (attr.getName().equals("name")) continue;
+	    Element attrElement =  doc.createElement(GEMSConstants.ATTRIBUTE_ELEMENT);
+	    attrElement.setAttribute(GEMSConstants.NAME_ATTRIBUTE,attr.getName());
+	    attrElement.appendChild(doc.createTextNode(attr.getValue()));
+	    metadata_element.appendChild(attrElement);
+	}
+
+	  
+	//language dependent attributes
+	ArrayList langs = getAllLanguages();
+	for (int i=0;i<langs.size();i++){
+	    String lang = (String)langs.get(i);
+	    Element langElement =  doc.createElement(GEMSConstants.LANGUAGE_ELEMENT);
+	    langElement.setAttribute(GEMSConstants.CODE_ATTRIBUTE,lang);
+	    ArrayList langAttrs = getAttributesByLanguage(lang);
+	    for (int j=0;j<langAttrs.size();j++){
+		Attribute attr = (Attribute)langAttrs.get(j);
+		Element attrElement =  doc.createElement(GEMSConstants.ATTRIBUTE_ELEMENT);
+		attrElement.setAttribute(GEMSConstants.NAME_ATTRIBUTE,attr.getName());
+		attrElement.appendChild(doc.createTextNode(attr.getValue()));  
+		langElement.appendChild(attrElement);
+	                    
+	    }
+	    metadata_element.appendChild(langElement);   
+	}              
+
+	return metadata_element;
+           
+    }
+
+ 
+  
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataSetEvent.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataSetEvent.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataSetEvent.java	(revision 13928)
@@ -0,0 +1,50 @@
+
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at th * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################## ##########################
+ */
+package org.greenstone.gatherer.gems;
+
+public class MetadataSetEvent{
+    private MetadataSetInfo meta_info;
+
+    public MetadataSetEvent(MetadataSetInfo info){
+	meta_info = info;
+
+    }
+
+    public MetadataSetInfo getMetadataSetInfo(){
+	return  meta_info;
+    } 
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataSetInfo.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataSetInfo.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataSetInfo.java	(revision 13928)
@@ -0,0 +1,333 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gems;
+
+import org.apache.xerces.dom.*;// for new Documents
+import org.w3c.dom.Document; 
+import org.w3c.dom.DocumentType; 
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Attr;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.NodeList;
+
+import java.util.HashMap;
+import java.util.ArrayList;
+
+import org.greenstone.gatherer.util.XMLTools;
+
+/**
+ * @author Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ */
+public class MetadataSetInfo
+    extends AttributeContainer
+{
+ 	
+    private String file_path="";  
+
+    private static ArrayList listeners = new ArrayList();  
+
+    private static MetadataSetModel metadata_model;
+       
+    private String current_language = GEMSConstants.DEFAULT_LANGUAGE;
+
+    private boolean isNew = false;
+
+    public MetadataSetInfo(){       
+	super(GEMSConstants.SET_REQUIRED_ATTRIBUTES, GEMSConstants.SET_LANG_DEPEND_ATTR_NAMES);
+    } 
+
+    public boolean isNamespaceAlreadyUsed(String namespace){
+	if(metadata_model != null) {
+	    return metadata_model.getMetadataSetManager().isNamespaceAlreadyUsed(namespace);
+	}
+	return false;
+    }
+
+    public void setNew(boolean isNew){
+	this.isNew = isNew;
+    }
+
+    public boolean isNew(){
+	return isNew;
+    }
+    
+    public Document getMetadataSetDocument(){
+	return  metadata_model.getMetadataSetDocument();
+    }
+    
+    public MetadataSetModel getMetadataSetModel(){
+        return metadata_model;
+    } 
+    
+     public void setMetadataSetModel(MetadataSetModel model){
+	 metadata_model = model;
+     } 
+    
+
+    public String getMetadataSetName(){  
+	return getMetadataSetName(getCurrentLanguage());
+    }
+
+    public String getMetadataSetName(String lang){    
+        Attribute attr = getAttributeByNameAndLanguage(GEMSConstants.NAME_ATTRIBUTE,lang);
+	if (attr != null) { 
+	    return attr.getValue();
+	}
+	else {
+	    return GEMSConstants.UNKNOWN_NAME;
+	}      
+    }
+
+     public void setMetadataSetName(String name){ 
+	 setMetadataSetName(name, getCurrentLanguage());
+     }
+
+    public void setMetadataSetName(String name,String lang){  
+	Attribute attr =  getAttributeByNameAndLanguage(GEMSConstants.NAME_ATTRIBUTE,lang);
+         if (attr != null){ 
+	     attr.setValue(name);
+	 } 
+	 else {
+	     attr = new Attribute(GEMSConstants.NAME_ATTRIBUTE, name, lang, true);
+	     language_dependent_attributes.add(attr);    
+	 }
+    }
+
+
+  
+    public String getMetadataSetDescription(){  
+	return getMetadataSetDescription(getCurrentLanguage());	 
+    }
+    
+    public String getMetadataSetDescription(String lang){    
+	Attribute attr = getAttributeByNameAndLanguage(GEMSConstants.DESCRIPTION_ATTRIBUTE,lang); 
+	if (attr != null) { 
+	    return attr.getValue();
+	}
+	else {
+	    return "";
+	}	 
+    }
+ 
+    public void setMetadataSetDescription(String desc) {
+	setMetadataSetDescription(desc, getCurrentLanguage());
+    }
+    
+    public void setMetadataSetDescription(String desc, String lang) {
+	Attribute attr =  getAttributeByNameAndLanguage(GEMSConstants.DESCRIPTION_ATTRIBUTE,lang);
+         if (attr != null){ 
+	     attr.setValue(desc);
+	 }
+	 else {
+	     attr = new Attribute(GEMSConstants.DESCRIPTION_ATTRIBUTE, desc, lang, true);
+	     language_dependent_attributes.add(attr);    
+	 }  
+    }
+    
+    public String getCurrentLanguage(){
+	return current_language;	
+    }
+
+    public void setCurrentLanguage(String lang){
+	current_language = lang;	
+    }
+    
+    public String getNamespace(){
+      	Attribute attr = getAttributeByName(GEMSConstants.NAMESPACE_ATTRIBUTE); 
+	if (attr != null){ 
+	    return attr.getValue();
+	 }
+	else{
+	    return "";
+	 }       
+    }
+  
+     public void setNamespace(String namespace){  
+	Attribute attr =  getAttributeByName(GEMSConstants.NAMESPACE_ATTRIBUTE);
+         if (attr != null){ 
+	     attr.setValue(namespace);
+	 }
+	 else {
+	     attr = new Attribute(GEMSConstants.NAMESPACE_ATTRIBUTE, namespace, true);
+	     attributes.add(attr);
+	 }    
+
+    }
+
+  
+    public String getFilePath(){
+	return file_path;
+    }     
+    
+    
+    public void infoChanged(){
+	metadata_model.valueChanged();
+    }
+    
+    public void setFilePath(String path){
+        file_path = path;
+    }     
+    
+    
+    public void addMetadataSetListener(MetadataSetListener msl){
+	if (!listeners.contains(msl))
+	    listeners.add(msl);   
+    }
+    
+    public void removeMetadataSetListener(MetadataSetListener msl){
+        listeners.remove(msl);   
+    }
+     
+    public void removeAllMetadataSetListeners(){
+	  listeners.clear();
+    }
+
+    public void deleteMetadataSet(){
+	metadata_model.getMetadataSetManager().deleteMetadataSet(this);
+
+      	if (metadata_model.getMetadataSetInfo() != null 
+	    && metadata_model.getMetadataSetInfo().getFilePath().equals(this.getFilePath())){
+	    metadata_model.metadataSetDeleted();
+	    MetadataSetEvent mse = new MetadataSetEvent(null);
+	    for(int i=0;i<listeners.size();i++){
+		MetadataSetListener msl = (MetadataSetListener) listeners.get(i);
+		msl.metadataSetChanged(mse);          
+	    }
+	}
+    }
+
+    public void notifyListeners(){
+        MetadataSetEvent mse = new MetadataSetEvent(this);
+	for(int i=0;i<listeners.size();i++){
+	    MetadataSetListener msl = (MetadataSetListener) listeners.get(i);
+	    msl.metadataSetChanged(mse);          
+	}
+    }
+ 
+    public void save(){
+	Document doc = metadata_model.getMetadataSetDocument();
+
+        //new metadata set
+        if (doc == null){
+	    doc = new DocumentImpl(); 
+            DocumentType docType = new DocumentTypeImpl((DocumentImpl)doc,GEMSConstants.MATADATASET_NAME,null,GEMSConstants.SYSTEM_ID);                         
+	    doc.appendChild(doc.createElement(GEMSConstants.METADATASET_ELEMENT));
+	    doc.appendChild(docType);
+	    metadata_model.setMetadataSetDocument(doc);          
+	} 
+    
+        Element doc_element = doc.getDocumentElement(); 
+	//remove all attributes
+	NamedNodeMap attrs = doc.getDocumentElement().getAttributes();
+	for (int i=0;i<attrs.getLength();i++){
+	    Attr item = (Attr)attrs.item(i);
+	    doc_element.removeAttribute(item.getName());
+	}
+       
+	//add attributes
+	for (int i=0;i<attributes.size();i++){
+	    Attribute attr = (Attribute)attributes.get(i);
+	    if (attr.getName() == null || attr.getName().trim().equals("")) continue;
+            doc_element.setAttribute(attr.getName(),attr.getValue());
+	}
+
+        //remove all language dependent name and description elements
+	NodeList setLanguages = doc_element.getElementsByTagName(GEMSConstants.SET_LANGUAGE_ELEMENT);  
+
+	for (int i=setLanguages.getLength()-1;i>=0;--i){
+	    Node set_language = setLanguages.item(i);
+	    doc_element.removeChild(set_language);
+	}
+
+	 ArrayList names = XMLTools.getChildElementsByTagName(doc_element,GEMSConstants.NAME_ELEMENT);   
+         for(int i=0;i< names.size();i++){
+	     Element name_element = (Element)names.get(i);
+	     doc_element.removeChild(name_element);
+	 } 
+
+        ArrayList deses = XMLTools.getChildElementsByTagName(doc_element,GEMSConstants.DESCRIPTION_ELEMENT);   
+         for(int i=0;i< deses.size();i++){
+	     Element des_element = (Element)deses.get(i);
+	     doc_element.removeChild(des_element);
+	 } 
+
+	 Node first_child = doc_element.getFirstChild(); 
+
+	 Node previous_element = null;
+
+	 //add setLanguage elements
+        ArrayList langs = getAllLanguages();
+	for (int i=0;i<langs.size();i++){
+	    String lang = (String)langs.get(i);
+	    Attribute name = getAttributeByNameAndLanguage(GEMSConstants.NAME_ATTRIBUTE,lang);
+	    if (name !=null){
+		Element set_element = doc.createElement(GEMSConstants.SET_LANGUAGE_ELEMENT); 
+		set_element.setAttribute(GEMSConstants.CODE_ATTRIBUTE,lang);
+		Element name_element = doc.createElement(GEMSConstants.NAME_ELEMENT);
+                name_element.appendChild(doc.createTextNode(name.getValue()));
+		set_element.appendChild(name_element); 
+               	Attribute des = getAttributeByNameAndLanguage(GEMSConstants.DESCRIPTION_ATTRIBUTE,lang);
+                 if (des !=null){
+		     Element des_element = doc.createElement(GEMSConstants.DESCRIPTION_ELEMENT);
+		     des_element.appendChild(doc.createTextNode(des.getValue()));
+		     set_element.appendChild(des_element);
+		 }	 
+
+		 if (first_child == null){
+		    
+		     if (previous_element !=null && previous_element.getNextSibling() !=null){ 
+                         doc_element.insertBefore(set_element,previous_element.getNextSibling());  
+		     }
+		      else{
+			  doc_element.appendChild(set_element);
+		      }
+		 }
+		 else {
+		     doc_element.insertBefore(set_element,first_child);
+		     first_child = null;
+		     previous_element = set_element;
+		 }
+	    }
+	}
+
+           
+    }
+
+ 
+
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataSetListener.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataSetListener.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataSetListener.java	(revision 13928)
@@ -0,0 +1,43 @@
+
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at th * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################## ##########################
+ */
+package org.greenstone.gatherer.gems;
+
+public interface MetadataSetListener{
+
+    public void metadataSetChanged(MetadataSetEvent mse);
+
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataSetManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataSetManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataSetManager.java	(revision 13928)
@@ -0,0 +1,385 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gems;
+
+import java.io.*;
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+import java.util.ArrayList;
+
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.file.*;
+import org.greenstone.gatherer.util.XMLTools;
+import org.greenstone.gatherer.Dictionary;
+
+import org.apache.xerces.parsers.*;
+import org.apache.xml.serialize.*;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+
+
+
+/** This class is responsible for managing all the metadata sets in the collection and for providing methods for manipulating the aforementioned sets contents. 
+ * @author Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ * @version 2.4
+ */
+public class MetadataSetManager
+{
+   
+    private ArrayList mds_list = new ArrayList();                      
+    
+    private MetadataSetModel metadata_set_model;
+
+    private ArrayList languageList; 
+
+    private String current_language = GEMSConstants.DEFAULT_LANGUAGE; 
+
+    /** Constructor. */
+    public MetadataSetManager(String gsdl_path, String gsdl3_path) {
+    	// Determine the GLI user directory path
+	String gli_user_directory_path = System.getProperty("user.home") + File.separator;
+	
+        if (Utility.isWindows()) {
+	    gli_user_directory_path += "Application Data" + File.separator + "Greenstone" + File.separator + "GLI" + File.separator;
+        }
+        else {
+            gli_user_directory_path += ".gli" + File.separator;
+        }
+
+	new Configuration(gli_user_directory_path, gsdl_path, gsdl3_path, null, null);         
+	current_language = Configuration.getLanguage(); 
+
+        languageList = new ArrayList();
+    }
+
+    public ArrayList getLanguageList(){
+        //already loaded
+	if (languageList.size() > 0 ) return languageList;
+  	
+	Document document = XMLTools.parseXMLFile(getLanguageXMLPath(), true);        
+
+	NodeList languages = document.getDocumentElement().getElementsByTagName(GEMSConstants.LANGUAGE_ELEMENT);
+        for(int i=0; i< languages.getLength();i++){
+            Element language_element = (Element)languages.item(i);
+            languageList.add(language_element.getAttribute(GEMSConstants.CODE_ATTRIBUTE).toLowerCase()+"   "+language_element.getAttribute(GEMSConstants.NAME_ATTRIBUTE));
+	}  
+   
+	return languageList;
+    }
+
+
+    public boolean isAttributeRequired(String name){
+	String tmp_name = name.trim();
+	for(int i=0;i<GEMSConstants.SET_REQUIRED_ATTRIBUTES.length;i++){
+            if (tmp_name.equals(GEMSConstants.SET_REQUIRED_ATTRIBUTES[i])) return true;
+	}
+	return false;
+    }
+
+    public void save(boolean confirm) {
+	MetadataSetInfo meta_info =  metadata_set_model.getMetadataSetInfo();
+	
+	if (meta_info ==null) return;
+
+	if (confirm){
+
+	    //int result = JOptionPane.showOptionDialog(null, Dictionary.get("GEMS.Confirm_Save"), Dictionary.get("GEMS.Confirm_Save_Title"), JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE,null,Dictionary.get("General.No"),Dictionary.get("General.No"));
+	    int result = JOptionPane.showConfirmDialog(null, Dictionary.get("GEMS.Confirm_Save"), Dictionary.get("GEMS.Confirm_Save_Title"), JOptionPane.YES_NO_OPTION);
+	    if (result != JOptionPane.YES_OPTION) return;
+	}
+	
+
+        File file_path = null;
+	//get new file name
+        if(meta_info.isNew()){
+	    JFileChooser file_chooser =  new JFileChooser(new File(getGLIMetadataDirectoryPath()));
+	    file_chooser.setMultiSelectionEnabled(false);
+	    file_chooser.setSelectedFile(new File(getGLIMetadataDirectoryPath(), meta_info.getNamespace()+GEMSConstants.METADATA_SET_FILE_EXTENSION));
+	    int result = file_chooser.showSaveDialog(null);
+	    if (result == JFileChooser.APPROVE_OPTION){
+		file_path = file_chooser.getSelectedFile();
+		meta_info.setFilePath(file_path.toString());
+		meta_info.setNew(false);
+	    } 
+	}
+	else {
+	    file_path = new File(meta_info.getFilePath());
+	}
+
+	if (file_path != null) save(file_path);
+
+	for(int i=0;i<mds_list.size();i++){
+	    MetadataSetInfo infoItem = (MetadataSetInfo)mds_list.get(i);
+	    if (infoItem.getFilePath().trim().equals(meta_info.getFilePath().trim())) {
+		mds_list.remove(infoItem);
+		mds_list.add(meta_info); 
+		break;
+	    }	    
+	}
+	return;
+
+    }
+
+
+    private void save(File file_path){
+
+	try {
+	    
+	    XMLTools.writeXMLFile(file_path, metadata_set_model.getMetadataSetDocument());
+	    
+	}
+	catch (Exception error) {
+	    error.printStackTrace();
+	}
+    
+    }
+
+
+    public Document getMetadataSetDocument(String filePath){ 
+	if (filePath == null || filePath.equals("")) return null;
+        return  XMLTools.parseXMLFile(filePath, true);
+    }
+
+    public void setMetadataSetModel(MetadataSetModel model){
+	metadata_set_model = model;
+    }
+
+    public MetadataSetModel getMetadataSetModel(){
+        return  metadata_set_model;
+    }
+    
+
+    public ArrayList getAvailableMetadataSets(){
+	mds_list.clear();        
+	// Load all the core metadata sets (in the GLI "metadata" directory)
+	File metadata_directory = new File(getGLIMetadataDirectoryPath());
+	if (metadata_directory.exists()) {
+	    // Load just those .mds files in this directory, and return them
+	    File[] directory_files = metadata_directory.listFiles();
+	    for (int i = 0; i < directory_files.length; i++) {
+		File child_file = directory_files[i];
+               
+     		if (!child_file.isDirectory() && child_file.getName().endsWith(GEMSConstants.METADATA_SET_FILE_EXTENSION)) {
+                   Document document = XMLTools.parseXMLFile(child_file.toString(), true);
+                   MetadataSetInfo info = constructMetadataInfo(document);
+                   info.setFilePath(child_file.toString());                              
+		   mds_list.add(info);		        	    
+		}
+	    }
+	}
+
+	return  mds_list;
+    }
+
+    public boolean isNamespaceAlreadyUsed(String namespace){
+	for(int i=0;i<mds_list.size();i++){
+	    MetadataSetInfo info = (MetadataSetInfo)mds_list.get(i);
+	    if (info.getNamespace().trim().equals(namespace)) return true;	    
+	}
+	return false;
+    }
+
+    public MetadataSetInfo getMetadataSet(String metadata_path){
+	MetadataSetInfo info = constructMetadataInfo(XMLTools.parseXMLFile(metadata_path,true));
+
+	// check whether there is metadata set name for the current language
+	// if not reset the current_language to the language first encountered
+        ArrayList attrs = info.getLanguageDependentAttributes();
+	boolean foundLanguage = false;
+        for (int i=0;i<attrs.size();i++){
+	    Attribute attr = (Attribute)attrs.get(i);
+	    if (attr.getLanguage().equals(current_language)) {
+		info.setCurrentLanguage(current_language);
+		foundLanguage = true;
+                break;
+	    }
+	    
+	}              
+        if (!foundLanguage && attrs.size()>0){
+	    info.setCurrentLanguage(((Attribute)attrs.get(0)).getLanguage());
+	}      
+	
+	info.setFilePath(metadata_path);            
+        return info;
+
+    }     
+    
+    public void deleteMetadataSet(MetadataSetInfo info){
+	String filepath = info.getFilePath();
+
+        if(filepath != null && !filepath.trim().equals("")){
+	    File file = new File(filepath);
+	  
+	  boolean deleted = file.delete();
+	  if (!deleted){
+	        JOptionPane.showMessageDialog(null,Dictionary.get("GEMS.File_Deletion_Error_Message"), Dictionary.get("GEMS.File_Deletion_Error"),JOptionPane.ERROR_MESSAGE);
+	  }
+	  else{
+	      	for(int i=0;i<mds_list.size();i++){
+		    MetadataSetInfo infoItem = (MetadataSetInfo)mds_list.get(i);
+		    if (infoItem.getFilePath().trim().equals(info.getFilePath().trim())) {
+			mds_list.remove(infoItem);
+			break;
+		    }	    
+		}
+	  }
+	}
+    }
+
+    public String getCurrentLanguage(){
+	return current_language;
+    }
+
+    private MetadataSetInfo constructMetadataInfo(Document document){      
+	NamedNodeMap attrs = document.getDocumentElement().getAttributes();
+        ArrayList attrList = new ArrayList();
+        String lang = null;
+        boolean findLang = false;
+	
+        for (int i=0;i<attrs.getLength();i++){
+	    Attr item = (Attr)attrs.item(i);
+	    Attribute attr = new Attribute(item.getName(),item.getValue());
+            attr.setRequired(isAttributeRequired(attr.getName()));
+	    attrList.add(attr);
+	}
+
+	ArrayList languageList = new ArrayList();
+ 
+        //load all <SetLanguage> elements
+        NodeList setLanguages = document.getDocumentElement().getElementsByTagName(GEMSConstants.SET_LANGUAGE_ELEMENT);
+	
+        if (setLanguages.getLength() >0){
+	    for(int i=0;i<setLanguages.getLength();i++){
+		Element set_language = (Element)setLanguages.item(i);
+                lang = set_language.getAttribute(GEMSConstants.CODE_ATTRIBUTE); 
+		setNameAndDescription(languageList, set_language,lang); 	
+	    }
+	    
+	}
+        //no set langugae elements, try load name and description elements
+        else{
+            setNameAndDescription(languageList, document.getDocumentElement(),lang);     
+	}
+	
+	MetadataSetInfo info = new MetadataSetInfo();
+	info.setLanguageDependentAttributes(languageList);
+	info.setAttributes(attrList);       
+	return info;
+    }
+
+    private void setNameAndDescription(ArrayList languageList, Element parent,String lang){
+
+	ArrayList names = XMLTools.getChildElementsByTagName(parent,GEMSConstants.NAME_ELEMENT);         
+        String name_lang = "";       
+
+	if (names.size() > 0){
+	    Element name_element = (Element)names.get(0);
+            Attribute attr = new Attribute(GEMSConstants.NAME_ATTRIBUTE,XMLTools.getElementTextValue(name_element), true);
+	    if (lang == null){
+		attr.setLanguage(name_element.getAttribute(GEMSConstants.LANGUAGE_ATTRIBUTE));
+                name_lang = attr.getLanguage();
+	    }
+	    else{
+		attr.setLanguage(lang); 
+	    }
+	    languageList.add(attr);
+// 	    if (current_language.equals(attr.getLanguage())){
+// 		attr.setRequired(true);
+//                 languageList.add(0,attr);
+// 	    }
+// 	    else{
+// 		languageList.add(attr);
+// 	    }    
+            
+	}
+      	
+	
+	ArrayList des = XMLTools.getChildElementsByTagName(parent,GEMSConstants.DESCRIPTION_ELEMENT);
+	if (des.size() > 0){
+	    Element des_element = (Element)des.get(0);
+	    Attribute attr = new Attribute(GEMSConstants.DESCRIPTION_ATTRIBUTE,XMLTools.getElementTextValue(des_element), true); 
+	    if (lang == null){
+		attr.setLanguage(des_element.getAttribute(GEMSConstants.LANGUAGE_ATTRIBUTE));
+	    }
+	      else{
+		  attr.setLanguage(lang); 
+	      }
+	    languageList.add(attr);
+	}
+	else{
+	    Attribute attr = new Attribute(GEMSConstants.DESCRIPTION_ATTRIBUTE,"", true);
+            if (lang == null){
+		attr.setLanguage(name_lang);
+	    }
+	    else{
+		attr.setLanguage(lang); 
+	    }
+	    
+	    languageList.add(attr); 
+	}
+	
+    }
+
+    
+    static public String getGLIDirectoryPath()
+    {
+	return System.getProperty("user.dir") + File.separator;
+    }
+
+
+    static public String getGLIMetadataDirectoryPath()
+    {
+	return getGLIDirectoryPath() + "metadata" + File.separator;
+    }
+  
+    static public String getLanguageXMLPath()
+    {
+	return getGLIDirectoryPath() + "classes" + File.separator+"xml"+ File.separator+ "languages.xml";
+    }
+      
+     static public String getCollectionPath()
+    {
+        if (Configuration.gsdl3_path != null){
+	    return Configuration.gsdl3_path + File.separator + "sites"; 
+
+	}
+	else{
+	    return Configuration.gsdl_path + File.separator + "collect";
+	}
+    } 
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataSetModel.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataSetModel.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataSetModel.java	(revision 13928)
@@ -0,0 +1,216 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gems;
+
+import org.w3c.dom.Document;
+import  org.w3c.dom.Element;
+import org.greenstone.gatherer.util.XMLTools;
+
+ 
+import java.util.Observable;
+import java.util.ArrayList;
+
+/**
+ * @author Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ * @version 2.4
+ */
+public class MetadataSetModel 
+    extends Observable implements MetadataSetListener, AttributeListener{
+
+    private Document metadata_doc;
+
+    private MetadataSetManager meta_manager;
+
+    private ArrayList model;      
+
+    private MetadataSetInfo meta_info;
+    
+    private boolean changed = false;
+
+
+    //construt a new MetadataSet
+    public MetadataSetModel(MetadataSetManager msm){
+        meta_manager = msm;
+	model = new ArrayList(); 
+    }
+
+    public String getCurrentLanguage(){
+	return meta_manager.getCurrentLanguage();
+    }
+
+    public void metadataSetChanged(MetadataSetEvent mse){
+	if (meta_info !=null) save(true); //save the last metadata set
+
+	model = new ArrayList();
+        meta_info = mse.getMetadataSetInfo();
+	meta_info.setMetadataSetModel(this);
+	metadata_doc = meta_manager.getMetadataSetDocument(meta_info.getFilePath());     
+	
+	constructModel();
+    
+        setChanged();
+	notifyObservers();
+	clearChanged();
+     	changed = false;  
+   
+    } 
+
+    public void valueChanged(){
+        setChanged();
+	notifyObservers(new Boolean(false));
+	clearChanged();
+    }
+    
+
+    private void constructModel(){
+	if (metadata_doc == null) return;
+	ArrayList elements =XMLTools.getChildElementsByTagName(metadata_doc.getDocumentElement(),GEMSConstants.ELEMENT_ELEMENT);
+	for(int i=0;i<elements.size();i++){    
+	    Element element = (Element)elements.get(i);     
+	    model.add(new MetadataElementModel(element,meta_info));
+	}                       
+    }
+    
+    public boolean doesChildWithThisNameExist(String name) {
+	for (int i=0; i<model.size(); i++) {
+	    if (name.equals(((MetadataElementModel)model.get(i)).getName())) {
+		return true;
+	    }
+	}
+	return false;
+    }
+
+    public Document getMetadataSetDocument(){
+	return metadata_doc;
+    }
+
+    public void setMetadataSetDocument(Document doc){
+	metadata_doc = doc;
+    }
+
+    public MetadataSetManager getMetadataSetManager(){
+	return meta_manager;
+    } 
+ 
+    public ArrayList getMetadataSetModel(){
+	return model;
+    }
+
+    
+    public void addChild(MetadataElementModel element_model){
+	model.add(element_model);
+	changed = true;
+    }
+    
+    public void removeChild(MetadataElementModel element_model){
+	model.remove(element_model);
+	changed = true;
+    }
+
+   
+    public void attributeChanged(AttributeEvent ae){      
+    	changed = true;
+    }
+    
+    public void setChanged(boolean ischanged){
+	changed = ischanged;
+    }
+
+    public void save(boolean confirm){
+	if ( meta_info == null || (!changed  && !meta_info.isNew())) return;
+
+	meta_info.save();
+	    
+	if (metadata_doc !=null){
+	    //remove all element elements
+	    Element doc_element = metadata_doc.getDocumentElement();
+	    ArrayList elements = XMLTools.getChildElementsByTagName(doc_element,GEMSConstants.ELEMENT_ELEMENT);   
+	    for(int i=0;i< elements.size();i++){
+		Element element = (Element)elements.get(i);
+		doc_element.removeChild(element);
+	    } 
+	}
+
+	for(int i=0;i< model.size();i++){
+	    MetadataElementModel element_model = (MetadataElementModel)model.get(i);
+            element_model.save();
+	} 
+	
+	meta_manager.save(confirm);
+	changed = false;
+	
+    }
+
+    public MetadataSetInfo getMetadataSetInfo(){
+	return meta_info; 
+    } 
+
+    public void metadataSetDeleted(){
+	meta_info = null;
+	setChanged();
+	notifyObservers();
+	clearChanged();
+     	changed = false; 	
+
+    }
+
+
+    public boolean moveUp(MetadataElementModel child){
+	int index = model.indexOf(child);
+	if (index-1 >=0){
+	    changed = true;
+	    model.remove(child);
+	    model.add(index-1,child);
+	    return true;
+	}        
+
+	return false;
+    }
+
+    public boolean moveDown(MetadataElementModel child){
+	int index = model.indexOf(child);
+	if (index+1 < model.size()){
+	    changed = true;
+	    model.remove(child);
+	    model.add(index+1,child);
+	    return true;
+	}        
+
+	return false;
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataSetTree.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataSetTree.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/MetadataSetTree.java	(revision 13928)
@@ -0,0 +1,435 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gems;
+
+import org.w3c.dom.Document;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.tree.*; 
+
+import java.util.Observer;
+import java.util.Observable;
+import java.util.ArrayList;
+
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+
+/**
+ * @author Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ * @version 2.4
+ */
+public class MetadataSetTree 
+    extends JTree 
+    implements Observer, ActionListener, MouseListener {
+    
+    private MetadataSetTree self;
+    private MetadataSetModel metadata_model;
+    protected JFrame parent_frame;
+    public MetadataSetTree(JFrame parent){
+
+        setCellRenderer(new MetadataSetCellRenderer());
+        setRowHeight(20);
+        setEditable(false);
+        getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+	setModel(null);
+        self = this;
+	parent_frame = parent;
+	addMouseListener(this);	
+    }
+    
+    public void mouseClicked(MouseEvent event) {
+	// right click
+	if (SwingUtilities.isRightMouseButton(event)) {
+            new MetadataSetTreeRightClickMenu(this, event);
+        } else {
+	    TreePath tse = self.getSelectionPath();
+	    if (tse!=null){
+		DefaultMutableTreeNode snode= (DefaultMutableTreeNode)tse.getLastPathComponent();
+		
+		Object data = snode.getUserObject();
+		
+		if (data instanceof MetadataElementModel){
+		    
+		    ((MetadataElementModel)data).notifyListeners(false);
+		}
+		else{
+		    if (data instanceof MetadataSetInfo){
+			((MetadataSetInfo)data).notifyListeners();
+		    }
+		}			  
+	    }
+	}
+	
+    }
+    
+    public void mouseEntered(MouseEvent event) { }
+
+    public void mouseExited(MouseEvent event) { }
+
+    public void mousePressed(MouseEvent event) { }
+
+    public void mouseReleased(MouseEvent event) { }
+
+    public void update(Observable o,Object arg){ 
+        if (arg !=null){
+	    Boolean replaceModel = (Boolean)arg;
+            if (!replaceModel.booleanValue()){ 
+                repaint();               
+	 	expandAll();
+	    }
+	}      
+        metadata_model = (MetadataSetModel)o;
+
+	populateMetadataSetTree(metadata_model);
+
+    }
+
+    private void expandAll() { 
+	int row = 0; 
+	while (row < getRowCount()) {
+	    expandRow(row);
+	    row++;
+	}
+    } 
+
+
+
+    public void actionPerformed(ActionEvent e){
+        String command = e.getActionCommand();
+   
+        if (command.equals(GEMSConstants.ADD_ELEMENT)){
+	    addElement(false);
+ 	    return ;
+	}
+        if (command.equals(GEMSConstants.ADD_SUBELEMENT)){
+	    addElement(true);
+ 	    return ;
+	}
+       
+	if (command.equals(GEMSConstants.DELETE_ELEMENT)){
+	    deleteElement();
+	}          
+
+
+	if (command.equals(GEMSConstants.MOVE_UP)){
+	    moveUpElement();
+	}
+       
+	if (command.equals(GEMSConstants.MOVE_DOWN)){
+	    moveDownElement(); 
+	}
+       
+    }
+
+     
+    public void addElement(boolean subelement){
+	TreePath tse = self.getSelectionPath();
+	if (tse == null) return;
+	
+	DefaultTreeModel dtm = (DefaultTreeModel)getModel();
+	DefaultMutableTreeNode snode=(DefaultMutableTreeNode)tse.getLastPathComponent();
+	Object data = snode.getUserObject();
+	if (data instanceof MetadataSetInfo){
+	    data = metadata_model;
+	}
+	NewMetadataElementNamePrompt name_prompt = new NewMetadataElementNamePrompt(parent_frame, subelement, data);
+	if (name_prompt.isCancelled()) {
+	    return;
+	}
+	String new_name = name_prompt.getName();
+	
+	MetadataElementModel element_model = new MetadataElementModel(metadata_model.getMetadataSetInfo(), new_name);
+	DefaultMutableTreeNode new_node = new DefaultMutableTreeNode(element_model);
+	dtm.insertNodeInto(new_node,snode,snode.getChildCount());
+	//update model
+	if (data instanceof MetadataElementModel){
+	    ((MetadataElementModel) data).addChild(element_model);
+	}
+	else if(data instanceof MetadataSetModel){
+	    ((MetadataSetModel)data).addChild(element_model);
+		
+	}
+	
+	
+	dtm.reload(snode);
+	expandPath(tse);
+	tse = tse.pathByAddingChild(new_node);
+	self.setSelectionPath(tse);
+	element_model.notifyListeners(false); 
+    }
+    
+    
+
+    public void deleteElement(){
+	
+	//int result = JOptionPane.showConfirmDialog(null, Dictionary.get("GEMS.Confirm_DeleteElement", "(Put name here)"), Dictionary.get("GEMS.Confirm_DeleteElement_Title"), JOptionPane.OK_CANCEL_OPTION);
+	//if (result != JOptionPane.OK_OPTION) return;
+
+	TreePath tse = self.getSelectionPath();
+       	 
+	if (tse!=null){
+	    DefaultTreeModel dtm = (DefaultTreeModel)getModel();
+	    DefaultMutableTreeNode snode=(DefaultMutableTreeNode)tse.getLastPathComponent();
+	    DefaultMutableTreeNode parent = (DefaultMutableTreeNode) snode.getParent();
+	    snode.removeFromParent();
+            
+	    Object parent_data = parent.getUserObject();
+	    Object data = snode.getUserObject();
+	    MetadataElementModel selected_model =  null;
+	    if (parent_data instanceof MetadataElementModel){
+		MetadataElementModel parent_model = (MetadataElementModel) parent_data;
+		selected_model = (MetadataElementModel) data; 
+		parent_model.removeChild(selected_model);
+		parent_model.notifyListeners(false);
+	    }
+	    else{
+		if(parent_data instanceof MetadataSetInfo){
+		    selected_model = (MetadataElementModel) data; 
+		    metadata_model.removeChild(selected_model);
+		    ((MetadataSetInfo)parent_data).notifyListeners();
+		    
+		}
+	    }
+	     
+	    dtm.reload(parent);
+	    self.setSelectionPath(tse.getParentPath());
+	    //selected_model.notifyListeners(true);// notify its listeners that it's been deleted
+	}  
+
+    } 
+
+    private void moveUpElement(){
+	TreePath tse = self.getSelectionPath();
+        
+	if (tse!=null){
+	    DefaultMutableTreeNode snode= (DefaultMutableTreeNode)tse.getLastPathComponent();
+	    int row =  getSelectionRows()[0];                      
+	    boolean moved = false;
+
+	    Object data = snode.getUserObject();
+	    
+	    if (data instanceof MetadataElementModel){
+		MetadataElementModel element_model = (MetadataElementModel)data;
+                //top level element
+                if (element_model.getParent() == null){
+		    moved = metadata_model.moveUp(element_model);
+                 
+		}
+                else{
+		    MetadataElementModel parent = element_model.getParent();
+		    moved = parent.moveUp(element_model);                
+		} 
+	       	if (moved){
+                    DefaultTreeModel dtm = (DefaultTreeModel)getModel();
+		    DefaultMutableTreeNode pnode= (DefaultMutableTreeNode) snode.getParent();
+                    int index = pnode.getIndex(snode);
+		    dtm.removeNodeFromParent(snode);
+		    dtm.insertNodeInto(snode,pnode,--index);
+                    dtm.reload(pnode);
+		    setSelectionRow(--row);                         
+		} 
+	    }
+	}
+
+    }
+
+    private void moveDownElement(){
+	TreePath tse = self.getSelectionPath();
+        
+	if (tse!=null){         
+	    boolean moved = false;
+	    DefaultMutableTreeNode snode= (DefaultMutableTreeNode)tse.getLastPathComponent();
+	    int row =  getSelectionRows()[0]; 	    
+	    Object data = snode.getUserObject();
+	    
+	    if (data instanceof MetadataElementModel){
+		MetadataElementModel element_model = (MetadataElementModel)data;
+                //top level element
+                if (element_model.getParent() == null){
+		    moved = metadata_model.moveDown(element_model);
+		}
+                else{
+		    MetadataElementModel parent = element_model.getParent();
+		    moved = parent.moveDown(element_model);                
+		} 
+		// move the node down the tree     
+		if (moved){
+		    DefaultTreeModel dtm = (DefaultTreeModel)getModel();
+		    DefaultMutableTreeNode pnode= (DefaultMutableTreeNode) snode.getParent();
+                    int index = pnode.getIndex(snode);
+		    dtm.removeNodeFromParent(snode);
+		    dtm.insertNodeInto(snode,pnode,++index);
+                    dtm.reload(pnode);
+		    setSelectionRow(++row); 		                         
+		} 
+	    }
+	}
+    }
+    
+
+    private void populateMetadataSetTree(MetadataSetModel metadata_model){
+	setModel(null);
+      	MetadataSetInfo info= metadata_model.getMetadataSetInfo();
+	if (info == null) {
+	    repaint();
+	    
+	    return;
+	}
+
+        ArrayList metadata_elements = metadata_model.getMetadataSetModel();        	 
+
+        DefaultTreeModel dtm = new DefaultTreeModel(new DefaultMutableTreeNode(info));
+	DefaultMutableTreeNode root = (DefaultMutableTreeNode)dtm.getRoot();
+       
+        for(int i=0;i <metadata_elements.size();i++){
+            MetadataElementModel element_model = (MetadataElementModel)metadata_elements.get(i);
+	    DefaultMutableTreeNode element = new DefaultMutableTreeNode(element_model);            
+	    dtm.insertNodeInto(element,root,root.getChildCount());
+            ArrayList subelements = element_model.getChildElements();
+	    for(int j=0;j <subelements.size();j++){
+                MetadataElementModel subelement_model = (MetadataElementModel)subelements.get(j);
+		DefaultMutableTreeNode subelement = new DefaultMutableTreeNode(subelement_model);            
+		dtm.insertNodeInto(subelement,element,element.getChildCount());
+            }
+	} 	 
+	 
+	dtm.reload(root);
+	setModel(dtm);       
+             
+    } 
+
+    private class MetadataSetTreeRightClickMenu
+	extends JPopupMenu {
+
+	private MetadataSetTreeRightClickMenu(MetadataSetTree meta_set_tree, 
+					      MouseEvent event)
+	{
+
+	    super();
+	    
+            // the right click position
+	    boolean root_node = false;
+	    boolean element_node = false;
+	    TreePath root_path = meta_set_tree.getPathForRow(0);
+            TreePath right_click_path = meta_set_tree.getPathForLocation(event.getX(), event.getY());
+            if (right_click_path == null) {
+		right_click_path = root_path;
+		root_node = true;
+	    } else if (right_click_path.equals(root_path)) {
+		root_node = true;
+	    } else if (right_click_path.getParentPath().equals(root_path)) {
+		element_node = true;
+	    } // else its a subelement
+	    
+	    meta_set_tree.clearSelection();
+	    meta_set_tree.setSelectionPath(right_click_path);
+
+	    JMenuItem add_element = new JMenuItem();
+	    if (root_node) {
+		add_element.setText(Dictionary.get("GEMS.Popup.AddElement"));
+		add_element.setActionCommand(GEMSConstants.ADD_ELEMENT);
+	    } else {
+		add_element.setText(Dictionary.get("GEMS.Popup.AddSubElement"));
+		add_element.setActionCommand(GEMSConstants.ADD_SUBELEMENT);
+
+	    }
+	    add_element.addActionListener(meta_set_tree);
+	    add(add_element);
+	    if (!root_node) {
+		// delete element also
+		JMenuItem delete_element = new JMenuItem();
+		if (element_node) {
+		    delete_element.setText(Dictionary.get("GEMS.Popup.DeleteElement"));
+		} else {
+		    delete_element.setText(Dictionary.get("GEMS.Popup.DeleteSubElement"));
+		}
+		delete_element.addActionListener(meta_set_tree);
+		delete_element.setActionCommand(GEMSConstants.DELETE_ELEMENT);
+		add(delete_element);
+	    }
+
+            // Show the popup menu on screen
+            show(meta_set_tree, event.getX(), event.getY());
+        }
+
+    }
+}
+
+
+class MetadataSetCellRenderer extends JLabel implements TreeCellRenderer {
+    
+    private Color SELECTED_COLOR = Color.lightGray;
+    private Color SELECTED_BORDER_COLOR = Color.gray;
+      
+   
+    public Component getTreeCellRendererComponent(JTree tree,
+						  Object value,
+						  boolean selected,
+						  boolean expanded,
+						  boolean leaf,
+						  int row,
+						  boolean hasFocus){
+	
+        DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
+        Object userObject = node.getUserObject();
+
+	if (userObject instanceof MetadataElementModel){
+	    MetadataElementModel model = (MetadataElementModel)userObject;
+	    setText(model.getFullName());
+	}
+	else{
+	    if (userObject instanceof MetadataSetInfo){
+		MetadataSetInfo info = (MetadataSetInfo)userObject;
+                setText(info.getMetadataSetName());	
+	    }
+	}
+   	 
+	if (selected){
+	    setBackground(SELECTED_COLOR);  
+        
+	}
+	else{
+	    setBackground(tree.getBackground());  
+	}
+	setForeground(tree.getForeground());  
+	setOpaque(true);
+	return this;
+    }
+
+} 
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/NewMetadataElementNamePrompt.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/NewMetadataElementNamePrompt.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/NewMetadataElementNamePrompt.java	(revision 13928)
@@ -0,0 +1,148 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Katherine Don, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gems;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.gui.GLIButton;
+import org.greenstone.gatherer.gui.ModalDialog;
+
+public class NewMetadataElementNamePrompt
+    extends ModalDialog {
+    private Dimension SIZE = new Dimension(350, 120);
+
+    private boolean cancelled = false;
+    private String element_name = null;
+    private JTextField name_textfield = null;
+    private JDialog prompt;
+    private Object model;
+    public NewMetadataElementNamePrompt(Frame parent, boolean subelement, Object model) {
+	super(parent, true);
+	setSize(SIZE);
+	prompt = this;
+	this.model = model;
+	JPanel content_pane = (JPanel) getContentPane();
+	content_pane.setOpaque(true);
+	    
+	JLabel name_label = new JLabel();
+	if (subelement) {
+	    setTitle(Dictionary.get("GEMS.NewMetadataElementNamePrompt.SubTitle"));
+	    name_label.setText(Dictionary.get("GEMS.NewMetadataElementNamePrompt.SubName"));
+	} else {
+	    setTitle(Dictionary.get("GEMS.NewMetadataElementNamePrompt.Title"));
+	    name_label.setText(Dictionary.get("GEMS.NewMetadataElementNamePrompt.Name"));
+	}
+
+	name_textfield = new JTextField();
+	    
+	name_textfield.addKeyListener(new KeyAdapter() {
+		public void keyPressed(KeyEvent e) {
+		    if (e.getKeyCode() == KeyEvent.VK_ENTER) {
+			//same as clicking OK button
+			validateElementName();
+		    }
+		}
+	    });
+
+	JPanel details_pane = new JPanel();
+	details_pane.setLayout(new GridLayout(2,1));
+	details_pane.add(name_label);
+	details_pane.add(name_textfield);
+	    
+	JPanel button_pane = new JPanel();
+	button_pane.setLayout(new GridLayout(1,2));
+	GLIButton ok_button = new GLIButton(Dictionary.get("General.OK"), Dictionary.get("General.OK_Tooltip"));       	
+	GLIButton cancel_button = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("General.Cancel_Tooltip"));
+	button_pane.add(ok_button);
+	button_pane.add(cancel_button);
+	    
+	// Add listeners
+	ok_button.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent event) {
+		    validateElementName();
+		}
+	    });
+	cancel_button.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent event) {
+		    cancelled = true;
+		    prompt.dispose();
+		}
+	    });
+	    
+	content_pane.setLayout(new BorderLayout(5,5));
+	content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	content_pane.add(details_pane, BorderLayout.CENTER);
+	content_pane.add(button_pane, BorderLayout.SOUTH);
+	    
+	Dimension screen_size = Configuration.screen_size;
+	setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+	setVisible(true);
+	    
+    }
+
+    public String getName() {
+	return element_name;
+    }
+
+    public boolean isCancelled() {
+	return cancelled;
+    }
+
+    private void validateElementName() {
+	String name = name_textfield.getText();
+	if (name.equals("")) {
+	    JOptionPane.showMessageDialog(prompt,Dictionary.get("GEMS.NewMetadataElementNamePrompt.EmptyName_Error_Message"), Dictionary.get("GEMS.NewMetadataElementNamePrompt.Name_Error"), JOptionPane.ERROR_MESSAGE);
+	    return;
+	} 
+	boolean already_used = false;
+	if (model instanceof MetadataSetModel) {
+	    already_used = ((MetadataSetModel)model).doesChildWithThisNameExist(name);
+	} else if (model instanceof MetadataElementModel) {
+	    already_used = ((MetadataElementModel)model).doesChildWithThisNameExist(name);
+	}
+	if (!already_used) {
+	    element_name = name;
+	    prompt.dispose();
+	} else {
+	    JOptionPane.showMessageDialog(prompt,Dictionary.get("GEMS.NewMetadataElementNamePrompt.Name_Error_Message"), Dictionary.get("GEMS.NewMetadataElementNamePrompt.Name_Error"), JOptionPane.ERROR_MESSAGE);
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/NewMetadataSetPrompt.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/NewMetadataSetPrompt.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/NewMetadataSetPrompt.java	(revision 13928)
@@ -0,0 +1,299 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gems;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Collection;
+import java.util.Vector;
+
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.gui.ModalDialog;
+import org.greenstone.gatherer.gui.GLIButton;
+
+public class NewMetadataSetPrompt 
+    extends ModalDialog {
+
+    static private Dimension SIZE = new Dimension(500, 320);
+        
+    private ArrayList available_metadata_sets;
+    private ArrayList listeners; 
+
+    private JButton ok_button = null;
+    private JButton cancel_button = null;    
+    private JComboBox base_metadata_combo;
+    private NewMetadataSetPrompt self;
+    private MetadataSetManager meta_manager;
+    private JTextArea description_textarea = null;
+    private JTextField title_field;
+    private JTextField namespace_field;
+
+    private boolean cancelled = false;
+    
+    public NewMetadataSetPrompt(Frame parent,MetadataSetManager msm) {
+	super(parent, true);
+        self = this;
+	listeners = new ArrayList();
+	meta_manager = msm;
+
+	setSize(SIZE);
+	setTitle(Dictionary.get("GEMS.NewMetadataSetPrompt.Title"));
+	
+	JPanel content_pane = (JPanel) getContentPane();
+        content_pane.setOpaque(true);
+	
+	JLabel  instruction_label = new JLabel(Dictionary.get("GEMS.NewMetadataSetPrompt.Instructions"));
+	instruction_label.setOpaque(true);
+	
+	JLabel  title_label = new JLabel(Dictionary.get("GEMS.NewMetadataSetPrompt.Metadata_Title"));
+	title_label.setOpaque(true);
+                 
+        title_field = new JTextField();
+
+	JPanel title_pane = new JPanel(new BorderLayout(5,5));
+        title_pane.add(title_label,BorderLayout.WEST);
+        title_pane.add(title_field, BorderLayout.CENTER);
+
+	
+	JLabel  namespace_label = new JLabel(Dictionary.get("GEMS.NewMetadataSetPrompt.Metadata_Namespace"));
+ 	namespace_label.setOpaque(true);
+                 
+        namespace_field = new JTextField();
+
+	JPanel namespace_pane = new JPanel(new BorderLayout(5,5));
+        namespace_pane.add(namespace_label,BorderLayout.WEST);
+        namespace_pane.add(namespace_field, BorderLayout.CENTER);
+
+        
+        JPanel info_pane = new JPanel();
+        info_pane.setLayout(new BorderLayout(5,5));
+        info_pane.add(instruction_label,BorderLayout.NORTH);
+	info_pane.add(title_pane,BorderLayout.CENTER);
+        info_pane.add(namespace_pane,BorderLayout.SOUTH);
+        
+
+	JLabel description_label = new JLabel(Dictionary.get("GEMS.Set_Description"));
+	description_label.setOpaque(true);
+
+	description_textarea = new JTextArea();
+        description_textarea.setLineWrap(true); 
+        description_textarea.setWrapStyleWord(true);
+
+	JPanel description_pane = new JPanel();
+        description_pane.setLayout(new BorderLayout());
+        description_pane.add(description_label,BorderLayout.NORTH);
+	description_pane.add(new JScrollPane(description_textarea),BorderLayout.CENTER);
+
+       
+	JLabel  base_label = new JLabel(Dictionary.get("GEMS.NewMetadataSetPrompt.Base_MetadataSet"));
+	base_label.setOpaque(true);
+        
+        base_metadata_combo = new JComboBox();
+	base_metadata_combo.setRenderer(new MetadatSetListCellRenderer());
+	
+	JPanel base_pane = new JPanel(new BorderLayout(5,5));
+        base_pane.add(base_label,BorderLayout.WEST);
+        base_pane.add(base_metadata_combo, BorderLayout.CENTER);
+
+
+	JPanel button_pane = new JPanel();
+	ok_button = new GLIButton(Dictionary.get("General.OK"), Dictionary.get("General.OK_Tooltip"));       	
+	cancel_button = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("General.Cancel_Tooltip"));
+      
+
+	// Add listeners
+	ok_button.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent event) {
+		    if (createNewSet()) {
+			self.dispose();
+		    } // else if that returned false, then we leave the
+		    // prompt there for them to change their input
+		}
+	    });
+
+				    
+	cancel_button.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent event) {
+		    cancelled = true;
+		    self.dispose();
+		}
+	    });
+	
+ 
+	button_pane.setLayout(new GridLayout(1,2));
+	button_pane.add(ok_button);
+	button_pane.add(cancel_button);
+	
+	JPanel bottom_pane = new JPanel(new GridLayout(2,1,5,5));
+	bottom_pane.add(base_pane);
+	bottom_pane.add(button_pane);
+	
+	content_pane.setLayout(new BorderLayout(5,5));
+	content_pane.add(info_pane, BorderLayout.NORTH);
+	content_pane.add(description_pane, BorderLayout.CENTER);
+	content_pane.add(bottom_pane, BorderLayout.SOUTH);
+	content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	
+	// Show
+	Dimension screen_size = Configuration.screen_size;
+	setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+	setVisible(false);
+	
+    }
+    
+    
+    public void display(){
+	cancelled = false;
+	available_metadata_sets =  meta_manager.getAvailableMetadataSets();
+	Vector data = new Vector((Collection)available_metadata_sets);
+	data.add(0,Dictionary.get("GEMS.NewMetadataSetPrompt.New_Metadata"));
+	DefaultComboBoxModel  model = new DefaultComboBoxModel(data);
+	title_field.setText("");
+	namespace_field.setText("");
+	description_textarea.setText("");
+	base_metadata_combo.setModel(model); 
+	setVisible(true);          
+    }
+
+    public boolean isCancelled() {
+	return cancelled;
+    }
+    
+    public void addMetadataSetListener(MetadataSetListener msl){
+	listeners.add(msl);
+   
+    }
+
+    private boolean createNewSet() {
+
+	String title = title_field.getText();
+	String namespace = namespace_field.getText();
+	String description = description_textarea.getText();
+
+	if (title == null || title.trim().equals("")){
+	    JOptionPane.showMessageDialog(self, Dictionary.get("GEMS.NewMetadataSetPrompt.Title_Error_Message"), Dictionary.get("GEMS.NewMetadataSetPrompt.Title_Error"), JOptionPane.ERROR_MESSAGE);
+
+	    return false;
+	}
+
+	if (namespace == null || namespace.trim().equals("")){
+	    JOptionPane.showMessageDialog(self, Dictionary.get("GEMS.NewMetadataSetPrompt.Namespace_Error_Message"), Dictionary.get("GEMS.NewMetadataSetPrompt.Namespace_Error"), JOptionPane.ERROR_MESSAGE);
+	    return false;
+	}
+
+	//check namespace conflict
+	if (meta_manager.isNamespaceAlreadyUsed(namespace)) {
+	    int result = JOptionPane.showOptionDialog(null,Dictionary.get("GEMS.Namespace_Conflict_Message"), Dictionary.get("GEMS.Namespace_Conflict"),JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE,null,GEMSConstants.DIALOG_OPTIONS,GEMSConstants.DIALOG_OPTIONS[0] );
+	     
+	    if (result != JOptionPane.OK_OPTION) return false;
+	}
+
+	Object selectedValue = base_metadata_combo.getSelectedItem();
+        
+	if (selectedValue != null ){
+	    MetadataSetInfo meta_info = null;
+               
+	    if ((selectedValue instanceof MetadataSetInfo)){	  
+		meta_info = (MetadataSetInfo)selectedValue;
+	    }
+	    else{
+		meta_info = new MetadataSetInfo();                	
+	    }
+                
+	    meta_info.setNew(true);
+	    // clear all the language dependent attributes
+	    meta_info.setLanguageDependentAttributes(new ArrayList());
+	    meta_info.setMetadataSetName(title); 
+	    meta_info.setMetadataSetDescription(description);
+	    meta_info.setNamespace(namespace);
+	    meta_info.setCurrentLanguage(meta_manager.getCurrentLanguage());
+	    notifyListeners(meta_info);
+	}
+	return true;
+    }
+
+ 
+    private void notifyListeners(MetadataSetInfo set_info){
+	MetadataSetEvent mse = new MetadataSetEvent(set_info);
+	for(int i=0;i<listeners.size();i++){
+	    MetadataSetListener msl = (MetadataSetListener)listeners.get(i);
+	    msl.metadataSetChanged(mse);          
+	}	
+    }
+
+    private class MetadatSetListCellRenderer extends JLabel 
+	implements ListCellRenderer {
+	public  MetadatSetListCellRenderer() {
+	    setOpaque(true);
+	}
+	
+	public Component getListCellRendererComponent(JList list,
+						      Object value,
+						      int index,
+						      boolean isSelected,
+						      boolean cellHasFocus)
+	{
+	    String name= "unknown";
+
+	    if (value instanceof MetadataSetInfo){
+		MetadataSetInfo meta_info = (MetadataSetInfo) value;
+		name = meta_info.getMetadataSetName(); //get the name of metadata set
+		setText(name);
+	    }
+	    else {
+		setText(value.toString());
+	    }
+
+	    if (isSelected) {
+		setBackground(list.getSelectionBackground());
+		setForeground(list.getSelectionForeground());
+	    }
+	    else {
+		setBackground(list.getBackground());
+		setForeground(list.getForeground());
+	    }
+	              
+	    return this;
+	}
+    }
+       
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/OpenMetadataSetPrompt.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/OpenMetadataSetPrompt.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gems/OpenMetadataSetPrompt.java	(revision 13928)
@@ -0,0 +1,275 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Shaoqun Wu, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gems;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Collection;
+import java.util.Vector;
+import java.io.File;
+
+
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.gui.ModalDialog;
+import org.greenstone.gatherer.gui.GLIButton;
+
+public class OpenMetadataSetPrompt 
+    extends ModalDialog {
+
+    static private Dimension SIZE = new Dimension(500, 500);
+        
+    private ArrayList available_metadata_sets;
+    private ArrayList listeners; 
+
+    private JButton open_button = null;
+    private JButton cancel_button = null; 
+    private JButton browse_button = null; 
+    private JList  available_set_list = null;
+    private OpenMetadataSetPrompt self;
+    private MetadataSetManager meta_manager;
+    private JTextArea description_textarea = null;
+
+    private boolean cancelled = false;
+    
+    public OpenMetadataSetPrompt(Frame parent,MetadataSetManager msm) {
+	super(parent, true);
+
+        self = this;
+	meta_manager = msm;
+	setSize(SIZE);
+	setTitle(Dictionary.get("GEMS.OpenMetadataSetPrompt.Title"));
+	listeners = new ArrayList();
+
+	JPanel content_pane = (JPanel) getContentPane();
+        content_pane.setOpaque(true);
+	
+	JLabel  available_metadata_sets_label = new JLabel(Dictionary.get("GEMS.OpenMetadataSetPrompt.Available_Sets"));
+	available_metadata_sets_label.setOpaque(true);
+
+        available_set_list = new JList();
+	available_set_list.setCellRenderer(new MetadatSetListCellRenderer());
+	available_set_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+        available_set_list.setFixedCellHeight(20);
+	available_set_list.addListSelectionListener(new MetadataSetListSelectionListener());
+
+        JPanel set_pane = new JPanel();
+        set_pane.setLayout(new BorderLayout());
+        set_pane.add(available_metadata_sets_label,BorderLayout.NORTH);
+	set_pane.add(new JScrollPane(available_set_list),BorderLayout.CENTER);
+        
+
+	JLabel  metadata_set_des_label = new JLabel(Dictionary.get("GEMS.Set_Description"));
+	metadata_set_des_label.setOpaque(true);
+
+	description_textarea = new  JTextArea();
+        description_textarea.setOpaque(true);
+        description_textarea.setEditable(false);
+        description_textarea.setLineWrap(true); 
+        description_textarea.setWrapStyleWord(true);
+
+	JPanel des_pane = new JPanel();
+        des_pane.setLayout(new BorderLayout());
+        des_pane.add(metadata_set_des_label,BorderLayout.NORTH);
+	des_pane.add(new JScrollPane(description_textarea),BorderLayout.CENTER);
+
+	JPanel button_pane = new JPanel();
+	open_button = new GLIButton(Dictionary.get("GEMS.OpenMetadataSetPrompt.Open"), Dictionary.get("GEMS.OpenMetadataSetPrompt.Open_Tooltip"));
+	open_button.setEnabled(true);
+	
+	browse_button = new GLIButton(Dictionary.get("General.Browse"));
+        browse_button.setEnabled(true);
+
+	cancel_button = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("General.Cancel_Tooltip"));
+	cancel_button.setEnabled(true);
+
+
+	// Add listeners
+	open_button.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent event) {
+		    notifyListeners();
+		    self.dispose();
+		}
+	    });
+
+	browse_button.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent event) {
+		    String collect_dir = meta_manager.getCollectionPath();
+		    JFileChooser file_chooser =  new JFileChooser(new File(collect_dir));
+		    file_chooser.setMultiSelectionEnabled(false);
+		    int result = file_chooser.showOpenDialog(null);
+		    if (result == JFileChooser.APPROVE_OPTION){
+			String file_path = file_chooser.getSelectedFile().toString();
+			MetadataSetInfo meta_info = meta_manager.getMetadataSet(file_path);
+			meta_info.setNew(false);
+			MetadataSetEvent mse = new MetadataSetEvent(meta_info);
+			for(int i=0;i<listeners.size();i++){
+			    MetadataSetListener msl = (MetadataSetListener)listeners.get(i);
+			    msl.metadataSetChanged(mse);          
+			}
+			
+		    }     
+		    notifyListeners();
+		    self.dispose();
+		}
+	    });
+
+
+
+	cancel_button.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent event) {
+		    cancelled = true;
+		    self.dispose();
+		}
+	    });
+
+
+	button_pane.setLayout(new GridLayout(1,3));
+	button_pane.add(open_button);
+	button_pane.add(browse_button);
+	button_pane.add(cancel_button);
+	
+
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(set_pane, BorderLayout.NORTH);
+	content_pane.add(des_pane, BorderLayout.CENTER);
+	content_pane.add(button_pane, BorderLayout.SOUTH);
+	
+	// Show
+	Dimension screen_size = Configuration.screen_size;
+	setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+	setVisible(false);
+
+    }
+
+
+    public void display(){
+	cancelled = false;
+        available_metadata_sets = meta_manager.getAvailableMetadataSets();
+	available_set_list.setListData(new Vector((Collection)available_metadata_sets)); 
+        setVisible(true);          
+    }
+
+    public void addMetadataSetListener(MetadataSetListener msl){
+        listeners.add(msl);
+   
+    }
+
+    public boolean isCancelled() {
+	return cancelled;
+    }
+
+    private void notifyListeners(){
+	Object selectedValue = available_set_list.getSelectedValue();
+	
+	if (selectedValue !=null && (selectedValue instanceof MetadataSetInfo)){
+	    MetadataSetEvent mse = new MetadataSetEvent((MetadataSetInfo)selectedValue);
+	    for(int i=0;i<listeners.size();i++){
+		MetadataSetListener msl = (MetadataSetListener)listeners.get(i);
+		msl.metadataSetChanged(mse);          
+	    }
+	}
+    }
+
+    public void openMetadataSet(String metadata_path){
+       MetadataSetInfo set_info = meta_manager.getMetadataSet(metadata_path);                       
+	notifyListeners(set_info);   
+    }
+
+    private void notifyListeners(MetadataSetInfo set_info){
+	MetadataSetEvent mse = new MetadataSetEvent(set_info);
+	for(int i=0;i<listeners.size();i++){
+	    MetadataSetListener msl = (MetadataSetListener)listeners.get(i);
+	    msl.metadataSetChanged(mse);          
+	}	
+    }
+
+    private class MetadatSetListCellRenderer extends JLabel implements ListCellRenderer {
+	public  MetadatSetListCellRenderer() {
+	    setOpaque(true);
+	}
+	
+     public Component getListCellRendererComponent(
+						   JList list,
+						   Object value,
+						   int index,
+						   boolean isSelected,
+         boolean cellHasFocus)
+	{
+	    String name= "unknown";
+
+	    if (value instanceof MetadataSetInfo){
+		MetadataSetInfo meta_info = (MetadataSetInfo) value;
+		name = meta_info.getMetadataSetName(); //get the name of metadata set
+	    }
+  
+            setText(name);
+            if (isSelected) {
+		setBackground(list.getSelectionBackground());
+		setForeground(list.getSelectionForeground());
+	    }
+	    else {
+		setBackground(list.getBackground());
+		setForeground(list.getForeground());
+	    }
+	              
+	    return this;
+	}
+    }
+   
+    
+    private class MetadataSetListSelectionListener implements ListSelectionListener  {
+        public void valueChanged(ListSelectionEvent lse){
+	    if (lse.getValueIsAdjusting()) return;
+
+	    Object selectedValue = available_set_list.getSelectedValue();
+
+            if (selectedValue !=null && (selectedValue instanceof MetadataSetInfo)){
+                MetadataSetInfo meta_info = (MetadataSetInfo)selectedValue; 
+		String des = meta_info.getMetadataSetDescription(); //get the description of the metadata set
+                description_textarea.setText(des);
+	    }      
+
+	}
+    }
+   
+ 
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/greenstone/Classifiers.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/greenstone/Classifiers.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/greenstone/Classifiers.java	(revision 13928)
@@ -0,0 +1,306 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.greenstone;
+
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.Argument;
+import org.greenstone.gatherer.cdm.Classifier;
+import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.util.XMLTools;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+
+
+public class Classifiers
+{
+    // A list of all the classifiers in the core Greenstone "perllib/classify" folder (arguments may not be loaded)
+    static private ArrayList core_greenstone_classifiers_list = null;
+    // The name of the loaded collection
+    static private String collection_name = null;
+    // A list of all the classifiers in the loaded collection's "perllib/classify" folder (arguments may not be loaded)
+    static private ArrayList collection_specific_classifiers_list = new ArrayList();
+
+
+    static public Classifier getClassifier(String classifier_name, boolean arguments_required)
+    {
+	Classifier classifier = null;
+	boolean collection_specific = false;
+
+	// Check the collection-specific classifiers first
+	for (int i = 0; i < collection_specific_classifiers_list.size(); i++) {
+	    Classifier collection_specific_classifier = (Classifier) collection_specific_classifiers_list.get(i);
+	    if (collection_specific_classifier.getName().equals(classifier_name)) {
+		classifier = collection_specific_classifier;
+		collection_specific = true;
+		break;
+	    }
+	}
+
+	// Try the core Greenstone classifiers if necessary
+	if (classifier == null) {
+	    for (int i = 0; i < core_greenstone_classifiers_list.size(); i++) {
+		Classifier core_greenstone_classifier = (Classifier) core_greenstone_classifiers_list.get(i);
+		if (core_greenstone_classifier.getName().equals(classifier_name)) {
+		    classifier = core_greenstone_classifier;
+		    break;
+		}
+	    }
+	}
+
+	// If we've found the classifier, load its arguments now, if required
+	if (classifier != null && arguments_required) {
+	    if (classifier.getArguments().size() == 0 && classifier.didLoadingOptionsFail() == false) {
+		loadClassifierInfo(classifier, collection_specific);
+	    }
+	    else {
+		DebugStream.println("Already loaded arguments for " + classifier_name + "!");
+	    }
+	}
+
+	return classifier;
+    }
+
+
+    /** Returns a new list from merging the collection-specific and the core Greenstone classifiers. */
+    static public ArrayList getClassifiersList()
+    {
+	ArrayList classifiers_list = new ArrayList();
+	classifiers_list.addAll(collection_specific_classifiers_list);
+
+	// Add in the core Greenstone classifiers, taking care not to overwrite any collection-specific ones
+	for (int i = 0; i < core_greenstone_classifiers_list.size(); i++) {
+	    Classifier core_greenstone_classifier = (Classifier) core_greenstone_classifiers_list.get(i);
+
+	    boolean found = false;
+	    for (int j = 0; j < collection_specific_classifiers_list.size(); j++) {
+		Classifier collection_specific_classifier = (Classifier) collection_specific_classifiers_list.get(j);
+		if (core_greenstone_classifier.getName().equals(collection_specific_classifier.getName())) {
+		    found = true;
+		    break;
+		}
+	    }
+
+	    if (!found) {
+		classifiers_list.add(core_greenstone_classifier);
+	    }
+	}
+
+	return classifiers_list;
+    }
+
+
+    static private void loadClassifierInfo(Classifier classifier, boolean collection_specific)
+    {
+	DebugStream.println("Loading arguments for " + classifier.getName() + "...");
+
+	// Run classifierfo.pl to get the list of classifiers
+	try {
+	    String classinfo_xml = null;
+	    if (Gatherer.isGsdlRemote) {
+		String classinfo_options = "&classifier=" + classifier;
+		if (collection_specific) {
+		    classinfo_options += "&collection=" + collection_name;
+		}
+		classinfo_xml = RemoteGreenstoneServer.getScriptOptions("classinfo.pl", classinfo_options);
+	    }
+	    else {
+		ArrayList args = new ArrayList();
+		if (Utility.isWindows()) {
+		    args.add(Configuration.perl_path);
+		    args.add("-S");
+		}
+		args.add(LocalGreenstone.getBinScriptDirectoryPath() + "classinfo.pl");
+		if (collection_specific) {
+		    args.add("-collection");
+		    args.add(collection_name);
+		}
+		args.add("-xml");
+		args.add("-language");
+		args.add(Configuration.getLanguage());
+		args.add(classifier.getName());
+
+		// Run the classinfo.pl process
+		Runtime runtime = Runtime.getRuntime();
+		Process process = runtime.exec((String[]) args.toArray(new String[] { }));
+		InputStream input_stream = process.getErrorStream();
+		StringBuffer classinfo_xml_buffer = XMLTools.readXMLStream(input_stream);
+		if (classinfo_xml_buffer != null) {
+		    classinfo_xml = classinfo_xml_buffer.toString();
+		}
+	    }
+
+	    // Check the XML output was obtained successfully
+	    if (classinfo_xml == null || classinfo_xml.length() == 0) {
+		classifier.setLoadingOptionsFailed();
+		JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.ClassifierManager.Classifier_XML_Parse_Failed", classifier.getName()), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
+		return;
+	    }
+
+	    parseClassifierInfoXML(classifier, classinfo_xml);
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+    }
+
+
+    static public void loadClassifiersList(String collection_name_arg)
+    {
+	DebugStream.println("In loadClassifiersList()...");
+
+	// If we're getting the collection-specific classifiers, clear the old list no matter what
+	if (collection_name_arg != null) {
+	    collection_name = collection_name_arg;
+	    collection_specific_classifiers_list = new ArrayList();
+	}
+
+	// Run classifierfo.pl to get the list of classifiers
+	try {
+	    StringBuffer xml = null;
+	    if (Gatherer.isGsdlRemote) {
+		String classinfo_options = "&listall";
+		if (collection_name != null) {
+		    classinfo_options += "&collection=" + collection_name;
+		}
+		String classinfo_output = RemoteGreenstoneServer.getScriptOptions("classinfo.pl", classinfo_options);
+		xml = new StringBuffer(classinfo_output);
+	    }
+	    else {
+		ArrayList args = new ArrayList();
+		if (Utility.isWindows()) {
+		    args.add(Configuration.perl_path);
+		    args.add("-S");
+		}
+		args.add(LocalGreenstone.getBinScriptDirectoryPath() + "classinfo.pl");
+		if (collection_name != null) {
+		    args.add("-collection");
+		    args.add(collection_name);
+		}
+		args.add("-listall");
+		args.add("-xml");
+
+		// Run the classinfo.pl process
+		Runtime runtime = Runtime.getRuntime();
+		Process process = runtime.exec((String[]) args.toArray(new String[] { }));
+		InputStream input_stream = process.getErrorStream();
+		xml = XMLTools.readXMLStream(input_stream);
+	    }
+
+	    // Check the XML output was obtained successfully
+	    if (xml == null || xml.length() == 0) {
+		JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.ClassifierManager.Classifier_List_XML_Parse_Failed"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
+		return;
+	    }
+
+	    if (collection_name != null) {
+		collection_specific_classifiers_list = parseClassifiersListXML(xml.toString());
+	    }
+	    else {
+		core_greenstone_classifiers_list = parseClassifiersListXML(xml.toString());
+	    }
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+    }
+
+
+    static private void parseClassifierInfoXML(Classifier classifier, String xml)
+    {
+	Document document = XMLTools.parseXML(new StringReader(xml));
+	if (document == null) {
+	    classifier.setLoadingOptionsFailed();
+	    JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.ClassifierManager.Classifier_XML_Parse_Failed", classifier.getName()), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
+	    return;
+	}
+
+	parseClassifierInfoXMLNode(classifier, document.getDocumentElement());
+    }
+
+
+    static private void parseClassifierInfoXMLNode(Classifier classifier, Node root_node)
+    {
+	for (Node node = root_node.getFirstChild(); node != null; node = node.getNextSibling()) {
+	    String node_name = node.getNodeName();
+
+	    if (node_name.equalsIgnoreCase("Name")) {
+		classifier.setName(XMLTools.getValue(node));
+	    }
+	    else if (node_name.equals("Desc")) {
+		classifier.setDescription(XMLTools.getValue(node));
+	    }
+	    else if (node_name.equals("Abstract")) {
+		classifier.setIsAbstract(XMLTools.getValue(node).equalsIgnoreCase(StaticStrings.YES_STR));
+	    }
+	    // Parse the classifier arguments
+	    else if (node_name.equalsIgnoreCase("Arguments")) {
+		for (Node argument_node = node.getFirstChild(); argument_node != null; argument_node = argument_node.getNextSibling()) {
+		    // An option
+		    if (argument_node.getNodeName().equalsIgnoreCase("Option")) {
+			Argument argument = new Argument();
+			argument.parseXML((Element) argument_node);
+			classifier.addArgument(argument);
+		    }
+		}
+	    }
+	    // A super classifier class
+	    else if (node_name.equalsIgnoreCase("ClassInfo")) {
+		Classifier super_classifier = new Classifier();
+		parseClassifierInfoXMLNode(super_classifier, node);
+		classifier.setSuper(super_classifier);
+	    }
+	}
+    }
+
+
+    static private ArrayList parseClassifiersListXML(String xml)
+    {
+	ArrayList classifiers_list = new ArrayList();
+
+	Document document = XMLTools.parseXML(new StringReader(xml));
+	Node root = document.getDocumentElement();
+	for (Node node = root.getFirstChild(); node != null; node = node.getNextSibling()) {
+	    String node_name = node.getNodeName();
+
+	    if (node_name.equals("ClassInfo")) {
+		Classifier classifier = new Classifier();
+		parseClassifierInfoXMLNode(classifier, node);
+		classifiers_list.add(classifier);
+	    }
+	}
+
+	return classifiers_list;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/greenstone/LocalGreenstone.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/greenstone/LocalGreenstone.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/greenstone/LocalGreenstone.java	(revision 13928)
@@ -0,0 +1,64 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2005 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.greenstone;
+
+
+import java.io.*;
+
+
+/**
+ * This class contains static functions that only make sense when running with a local Greenstone.
+ * None of these functions should be called if the GLI is using a remote Greenstone.
+ */
+public class LocalGreenstone
+{
+    static private String gsdl_directory_path = null;
+
+
+    static public String getBinScriptDirectoryPath()
+    {
+	return gsdl_directory_path + "bin" + File.separator + "script" + File.separator;
+    }
+
+
+    static public String getDirectoryPath()
+    {
+	return gsdl_directory_path;
+    }
+
+
+    static public String getTmpDirectoryPath()
+    {
+	return gsdl_directory_path + "tmp" + File.separator;
+    }
+
+
+    static public void setDirectoryPath(String gsdl_directory_path_arg)
+    {
+	gsdl_directory_path = gsdl_directory_path_arg;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/greenstone/LocalLibraryServer.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/greenstone/LocalLibraryServer.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/greenstone/LocalLibraryServer.java	(revision 13928)
@@ -0,0 +1,466 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2004 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.greenstone;
+
+
+import java.io.*;
+import java.lang.*;
+import java.net.*;
+import java.util.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+
+
+public class LocalLibraryServer
+{
+    static final private String ADD_COMMAND = "?a=config&cmd=add-collection&c=";
+    static final private String RELEASE_COMMAND = "?a=config&cmd=release-collection&c=";
+    static final private String QUIT_COMMAND = "?a=config&cmd=kill";
+
+    static private GSDLSiteConfig gsdlsite_cfg_file = null;
+    static private File local_library_server_file = null;
+
+    static private boolean running = false;
+
+    static public void addCollection(String collection_name)
+    {
+	config(ADD_COMMAND + collection_name);
+    }
+
+
+    // Used to send messages to the local library
+    static private void config(String command)
+    {
+	if (Configuration.library_url == null) {
+	    System.err.println("Error: Trying to configure local library with null Configuration.library_url!");
+	    return;
+	}
+
+	try {
+	    URL url = new URL(Configuration.library_url.toString() + command);
+	    HttpURLConnection library_connection = (HttpURLConnection) url.openConnection();
+
+	    // It's very important that we read the output of the command
+	    // This ensures that the command has actually finished
+	    // (The response code is returned immediately)
+	    InputStream library_is = library_connection.getInputStream();
+	    BufferedReader library_in = new BufferedReader(new InputStreamReader(library_is, "UTF-8"));
+	    String library_output_line = library_in.readLine();
+	    while (library_output_line != null) {
+		DebugStream.println("Local library server output: " + library_output_line);
+		library_output_line = library_in.readLine();
+	    }
+	    library_in.close();
+
+	    int response_code = library_connection.getResponseCode();
+	    if (response_code >= HttpURLConnection.HTTP_OK && response_code < HttpURLConnection.HTTP_MULT_CHOICE) {
+		DebugStream.println("200 - Complete.");
+	    }
+	    else {
+		DebugStream.println("404 - Failed.");
+	    }
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+    }
+
+
+    static public boolean isRunning()
+    {
+	if (!running) return false;
+	gsdlsite_cfg_file.load();
+	if (gsdlsite_cfg_file.getURL() == null)  return false;
+	return true;
+    }
+
+
+    static public void releaseCollection(String collection_name)
+    {
+	config(RELEASE_COMMAND + collection_name);
+    }
+
+
+    static public void start(String gsdl_path, String local_library_server_file_path)
+    {
+	// Check the local library server.exe file exists
+	local_library_server_file = new File(local_library_server_file_path);
+	if (!local_library_server_file.exists()) {
+	    DebugStream.println("No local library at given file path.");
+
+	    local_library_server_file = new File(gsdl_path + "server.exe");
+	    if (!local_library_server_file.exists()) {
+		DebugStream.println("No local library at all.");
+		return;
+	    }
+	}
+
+	// Check if the server is already running
+	gsdlsite_cfg_file = new GSDLSiteConfig(local_library_server_file);
+	String url = gsdlsite_cfg_file.getURL();
+	if (url != null) {
+	    // If it is already running then set the Greenstone web server address and we're done
+	    try {
+		Configuration.library_url = new URL(url);
+		running = true;
+		return;
+	    }
+	    catch (MalformedURLException exception) {
+		DebugStream.printStackTrace(exception);
+	    }
+	}
+
+	// Configure the server for immediate entry
+	gsdlsite_cfg_file.set();
+
+	// Spawn local library server process
+	String local_library_server_command = local_library_server_file.getAbsolutePath() + " " + gsdlsite_cfg_file.getSiteConfigFilename();
+	Gatherer.spawnApplication(local_library_server_command);
+
+	// Wait until program has started, by reloading and checking the URL field
+	gsdlsite_cfg_file.load();
+	int attempt_count = 0;
+	while (gsdlsite_cfg_file.getURL() == null) {
+	    new OneSecondWait();  // Wait one second (give or take)
+	    gsdlsite_cfg_file.load();
+	    attempt_count++;
+
+	    // After waiting a minute ask the user whether they want to wait another minute
+	    if (attempt_count == 60) {
+		int try_again = JOptionPane.showConfirmDialog(Gatherer.g_man, Dictionary.get("Server.QuitTimeOut"), Dictionary.get("General.Warning"), JOptionPane.YES_NO_OPTION);
+		if (try_again == JOptionPane.NO_OPTION) {
+		    return;
+		}
+		attempt_count = 0;
+	    }
+	}
+
+	// Ta-da. Now the url should be available
+	try {
+	    Configuration.library_url = new URL(gsdlsite_cfg_file.getURL());
+	}
+	catch (MalformedURLException exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+
+	// A quick test involves opening a connection to get the home page for this collection
+	try {
+	    DebugStream.println("Try connecting to server on config url: '" + Configuration.library_url+ "'");
+	    URLConnection connection = Configuration.library_url.openConnection();
+	    connection.getContent();
+	}
+	catch (IOException bad_url_connection) {
+	    try {
+		// If this fails then we try changing the url to be localhost
+		Configuration.library_url = new URL(gsdlsite_cfg_file.getLocalHostURL());
+		DebugStream.println("Try connecting to server on local host: '" + Configuration.library_url + "'");
+		URLConnection connection = Configuration.library_url.openConnection();
+		connection.getContent();
+	    }
+	    catch (IOException worse_url_connection) {
+		DebugStream.println("Can't connect to server on either address.");
+		Configuration.library_url = null;
+		return;
+	    }
+	}
+
+	running = true;
+    }
+
+
+    static public void stop()
+    {
+	if (running == false) {
+	    return;
+	}
+
+	// Send the command for it to exit.
+	config(QUIT_COMMAND);
+
+	// Wait until program has stopped, by reloading and checking the URL field
+	gsdlsite_cfg_file.load();
+	int attempt_count = 0;
+	while (gsdlsite_cfg_file.getURL() != null) {
+	    new OneSecondWait();  // Wait one second (give or take)
+	    gsdlsite_cfg_file.load();
+	    attempt_count++;
+
+	    // After waiting a minute ask the user whether they want to wait another minute
+	    if (attempt_count == 60) {
+		int try_again = JOptionPane.showConfirmDialog(Gatherer.g_man, Dictionary.get("Server.QuitTimeOut"), Dictionary.get("General.Warning"), JOptionPane.YES_NO_OPTION);
+		if (try_again == JOptionPane.NO_OPTION) {
+		    return;
+		}
+		attempt_count = 0;
+	    }
+	}
+
+	// Restore the gsdlsite_cfg.
+	gsdlsite_cfg_file.restore();
+
+	// If the local server is still running then our changed values will get overwritten.
+	if (gsdlsite_cfg_file.getURL() != null) {
+	    JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("Server.QuitManual"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
+	}
+
+	running = false;
+    }
+    
+    static public void checkServerRunning() {
+	if (!running) return; // don't worry about it if its not supposed to be running 
+	gsdlsite_cfg_file.load();
+	if (gsdlsite_cfg_file.getURL() == null) {
+	    // need to restart the server again
+	    gsdlsite_cfg_file.set();
+
+	    // Spawn local library server process
+	    String local_library_server_command = local_library_server_file.getAbsolutePath() + " " + gsdlsite_cfg_file.getSiteConfigFilename();
+	    Gatherer.spawnApplication(local_library_server_command);
+
+	}
+    }
+    static private class OneSecondWait
+    {
+	public OneSecondWait()
+	{
+	    synchronized(this) {
+		try {
+		    wait(1000);
+		}
+		catch (InterruptedException exception) {
+		}
+	    }
+	}
+    }
+
+
+    static public class GSDLSiteConfig
+	extends LinkedHashMap {
+	private File gsdlsite_cfg;
+	private File glisite_cfg;
+	private String autoenter_initial;
+	private String start_browser_initial;
+    
+	static final private String AUTOENTER = "autoenter";
+	static final private String COLON = ":";
+	static final private String ENTERLIB = "enterlib";
+	static final private String FALSE = "0";
+	static final private String GLISITE_CFG = "glisite.cfg";
+	static final private String GSDL = "gsdl";
+	static final private String GSDLSITE_CFG = "gsdlsite.cfg";
+	static final private String LOCAL_HOST = "http://localhost"; 
+	static final private String PORTNUMBER = "portnumber";
+	static final private String SEPARATOR = "/";
+	static final private String SPECIFIC_CONFIG = "--config=";
+	static final private String STARTBROWSER = "start_browser";
+	static final private String TRUE = "1";
+	static final private String URL = "url";
+
+	public GSDLSiteConfig(File server_exe) {
+	    debug("New GSDLSiteConfig for: " + server_exe.getAbsolutePath());
+	    gsdlsite_cfg = new File(server_exe.getParentFile(), GSDLSITE_CFG);
+	    glisite_cfg = new File(server_exe.getParentFile(), GLISITE_CFG);
+	    autoenter_initial = null;
+	    start_browser_initial = null;
+	    if(gsdlsite_cfg.exists()) {
+		debug("Load: " + gsdlsite_cfg.getAbsolutePath());
+		clear();
+		try {
+		    BufferedReader in = new BufferedReader(new FileReader(gsdlsite_cfg));
+		    String line = null;
+		    while((line = in.readLine()) != null) {
+			String key = null;
+			String value = null;
+			int index = -1;
+			if((index = line.indexOf("=")) != -1 && line.length() >= index + 1) {
+			    key = line.substring(0, index);
+			    value = line.substring(index + 1);
+			}
+			else {
+			    key = line;
+			}
+			put(key, value);
+		    }
+		    in.close();
+		}
+		catch (Exception error) {
+		    error.printStackTrace();
+		}
+	    }
+	    else {
+		debug("No GSDLsite.cfg file can be found!");
+	    }
+	}
+
+	public boolean exists() {
+	    return gsdlsite_cfg.exists();
+	}
+
+	public String getLocalHostURL() {
+	    StringBuffer url = new StringBuffer(LOCAL_HOST);
+	    url.append(COLON);
+	    url.append((String)get(PORTNUMBER));
+	    String enterlib = (String)get(ENTERLIB);
+	    if(enterlib == null || enterlib.length() == 0) {
+		// Use the default /gsdl and hope for the best.
+		url.append(SEPARATOR);
+		url.append(GSDL);
+	    }
+	    else {
+		if(!enterlib.startsWith(SEPARATOR)) {
+		    url.append(SEPARATOR);
+		}
+		url.append(enterlib);
+	    }
+	    enterlib = null;
+	    debug("Found Local Library Address: " + url.toString());
+	    return url.toString();
+	}
+
+	public String getSiteConfigFilename() {
+	    return SPECIFIC_CONFIG + glisite_cfg.getAbsolutePath();
+	}
+
+	public String getURL() {
+	    // URL is made from url and portnumber
+	    String url = (String) get(URL);
+	    if(url != null) {
+		StringBuffer temp = new StringBuffer(url);
+		temp.append(COLON);
+		temp.append((String)get(PORTNUMBER));
+		String enterlib = (String)get(ENTERLIB);
+		if(enterlib == null || enterlib.length() == 0) {
+		    // Use the default /gsdl and hope for the best.
+		    temp.append(SEPARATOR);
+		    temp.append(GSDL);
+		}
+		else {
+		    if(!enterlib.startsWith(SEPARATOR)) {
+			temp.append(SEPARATOR);
+		    }
+		    temp.append(enterlib);
+		}
+		enterlib = null;
+		url = temp.toString();
+	    }
+	    debug("Found Local Library Address: " + url);
+	    return url;
+	}
+
+	public void load() {
+	    if(glisite_cfg.exists()) {
+		debug("Load: " + glisite_cfg.getAbsolutePath());
+		clear();
+		try {
+		    BufferedReader in = new BufferedReader(new FileReader(glisite_cfg));
+		    String line = null;
+		    while((line = in.readLine()) != null) {
+			String key = null;
+			String value = null;
+			int index = -1;
+			if((index = line.indexOf("=")) != -1 && line.length() >= index + 1) {
+			    key = line.substring(0, index);
+			    value = line.substring(index + 1);
+			}
+			else {
+			    key = line;
+			}
+			put(key, value);
+		    }
+		    in.close();
+		}
+		catch (Exception error) {
+		    error.printStackTrace();
+		}
+	    }
+	    else {
+		debug("No GSDLsite.cfg file can be found!");
+	    }
+	}
+
+	/** Restore the autoenter value to its initial value, and remove url if present. */
+	public void restore() {
+	    if(glisite_cfg != null) {
+		// Delete the file
+		glisite_cfg.delete();
+	    }
+	    else {
+		debug("Restore Initial Settings");
+		put(AUTOENTER, autoenter_initial);
+		put(STARTBROWSER, start_browser_initial);
+		remove(URL);
+		save();
+	    }
+	}
+
+	public void set() {
+	    debug("Set Session Settings");
+	    if(autoenter_initial == null) {
+		autoenter_initial = (String) get(AUTOENTER);
+		debug("Remember autoenter was: " + autoenter_initial);
+	    }
+	    put(AUTOENTER, TRUE);
+	    if(start_browser_initial == null) {
+		start_browser_initial = (String) get(STARTBROWSER);
+		debug("Remember start_browser was: " + start_browser_initial);
+	    }
+	    put(STARTBROWSER, FALSE);
+	    save();
+	}
+
+	private void debug(String message) {
+	    ///ystem.err.println(message);
+	}
+
+	private void save() {
+	    //debug("Save: " + gsdlsite_cfg.getAbsolutePath());
+	    debug("Save: " + glisite_cfg.getAbsolutePath());
+	    try {
+		//BufferedWriter out = new BufferedWriter(new FileWriter(gsdlsite_cfg, false));
+		BufferedWriter out = new BufferedWriter(new FileWriter(glisite_cfg, false));
+		for(Iterator keys = keySet().iterator(); keys.hasNext(); ) {
+		    String key = (String) keys.next();
+		    String value = (String) get(key);
+		    out.write(key, 0, key.length());
+		    if(value != null) {
+			out.write('=');
+			out.write(value, 0, value.length());
+		    }
+		    out.newLine();
+		}
+		out.flush();
+		out.close();
+	    }
+	    catch (Exception error) {
+		error.printStackTrace();
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/greenstone/Plugins.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/greenstone/Plugins.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/greenstone/Plugins.java	(revision 13928)
@@ -0,0 +1,316 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.greenstone;
+
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.Argument;
+import org.greenstone.gatherer.cdm.Plugin;
+import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.util.XMLTools;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+
+
+/** This class is for maintaining a list of known plug-ins, and importing new plugins using the parser. */
+public class Plugins
+{
+    // A list of all the plugins in the core Greenstone "perllib/plugins" folder (arguments may not be loaded)
+    static private ArrayList core_greenstone_plugins_list = null;
+    // The name of the loaded collection
+    static private String collection_name = null;
+    // A list of all the plugins in the loaded collection's "perllib/plugins" folder (arguments may not be loaded)
+    static private ArrayList collection_specific_plugins_list = new ArrayList();
+
+
+    static public Plugin getPlugin(String plugin_name, boolean arguments_required)
+    {
+	Plugin plugin = null;
+	boolean collection_specific = false;
+
+	// Check the collection-specific plugins first
+	for (int i = 0; i < collection_specific_plugins_list.size(); i++) {
+	    Plugin collection_specific_plugin = (Plugin) collection_specific_plugins_list.get(i);
+	    if (collection_specific_plugin.getName().equals(plugin_name)) {
+		plugin = collection_specific_plugin;
+		collection_specific = true;
+		break;
+	    }
+	}
+
+	// Try the core Greenstone plugins if necessary
+	if (plugin == null) {
+	    for (int i = 0; i < core_greenstone_plugins_list.size(); i++) {
+		Plugin core_greenstone_plugin = (Plugin) core_greenstone_plugins_list.get(i);
+		if (core_greenstone_plugin.getName().equals(plugin_name)) {
+		    plugin = core_greenstone_plugin;
+		    break;
+		}
+	    }
+	}
+
+	// If we've found the plugin, load its arguments now, if required
+	if (plugin != null && arguments_required) {
+	    if (plugin.getArguments().size() == 0 && plugin.didLoadingOptionsFail() == false) {
+		loadPluginInfo(plugin, collection_specific);
+	    }
+	    else {
+		DebugStream.println("Already loaded arguments for " + plugin_name + "!");
+	    }
+	}
+
+	return plugin;
+    }
+
+
+    /** Returns a new list from merging the collection-specific and the core Greenstone plugins. */
+    static public ArrayList getPluginsList()
+    {
+	ArrayList plugins_list = new ArrayList();
+	plugins_list.addAll(collection_specific_plugins_list);
+
+	// Add in the core Greenstone plugins, taking care not to overwrite any collection-specific ones
+	for (int i = 0; i < core_greenstone_plugins_list.size(); i++) {
+	    Plugin core_greenstone_plugin = (Plugin) core_greenstone_plugins_list.get(i);
+
+	    boolean found = false;
+	    for (int j = 0; j < collection_specific_plugins_list.size(); j++) {
+		Plugin collection_specific_plugin = (Plugin) collection_specific_plugins_list.get(j);
+		if (core_greenstone_plugin.getName().equals(collection_specific_plugin.getName())) {
+		    found = true;
+		    break;
+		}
+	    }
+
+	    if (!found) {
+		plugins_list.add(core_greenstone_plugin);
+	    }
+	}
+
+	return plugins_list;
+    }
+
+
+    static private void loadPluginInfo(Plugin plugin, boolean collection_specific)
+    {
+	DebugStream.println("Loading arguments for " + plugin.getName() + "...");
+
+	// Run pluginfo.pl to get the list of plugins
+	try {
+	    String pluginfo_xml = null;
+	    if (Gatherer.isGsdlRemote) {
+		String pluginfo_options = "&plugin=" + plugin;
+		if (collection_specific) {
+		    pluginfo_options += "&collection=" + collection_name;
+		}
+		pluginfo_xml = RemoteGreenstoneServer.getScriptOptions("pluginfo.pl", pluginfo_options);
+	    }
+	    else {
+		ArrayList args = new ArrayList();
+		if (Utility.isWindows()) {
+		    args.add(Configuration.perl_path);
+		    args.add("-S");
+		}
+		args.add(LocalGreenstone.getBinScriptDirectoryPath() + "pluginfo.pl");
+		if (collection_specific) {
+		    args.add("-collection");
+		    args.add(collection_name);
+		}
+		args.add("-xml");
+		args.add("-language");
+		args.add(Configuration.getLanguage());
+		args.add(plugin.getName());
+
+		// Run the pluginfo.pl process
+		Runtime runtime = Runtime.getRuntime();
+		Process process = runtime.exec((String[]) args.toArray(new String[] { }));
+		InputStream input_stream = process.getErrorStream();
+		StringBuffer pluginfo_xml_buffer = XMLTools.readXMLStream(input_stream);
+		if (pluginfo_xml_buffer != null) {
+		    pluginfo_xml = pluginfo_xml_buffer.toString();
+		}
+	    }
+
+	    // Check the XML output was obtained successfully
+	    if (pluginfo_xml == null || pluginfo_xml.length() == 0) {
+		plugin.setLoadingOptionsFailed();
+		JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.PlugInManager.PlugIn_XML_Parse_Failed", plugin.getName()), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
+		return;
+	    }
+
+	    parsePluginInfoXML(plugin, pluginfo_xml);
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+    }
+
+
+    static public void loadPluginsList(String collection_name_arg)
+    {
+	DebugStream.println("In loadPluginsList()...");
+
+	// If we're getting the collection-specific plugins, clear the old list no matter what
+	if (collection_name_arg != null) {
+	    collection_name = collection_name_arg;
+	    collection_specific_plugins_list = new ArrayList();
+	}
+
+	// Run pluginfo.pl to get the list of plugins
+	try {
+	    StringBuffer xml = null;
+	    if (Gatherer.isGsdlRemote) {
+		String pluginfo_options = "&listall";
+		if (collection_name != null) {
+		    pluginfo_options += "&collection=" + collection_name;
+		}
+		String pluginfo_output = RemoteGreenstoneServer.getScriptOptions("pluginfo.pl", pluginfo_options);
+		xml = new StringBuffer(pluginfo_output);
+	    }
+	    else {
+		ArrayList args = new ArrayList();
+		if (Utility.isWindows()) {
+		    args.add(Configuration.perl_path);
+		    args.add("-S");
+		}
+		args.add(LocalGreenstone.getBinScriptDirectoryPath() + "pluginfo.pl");
+		if (collection_name != null) {
+		    args.add("-collection");
+		    args.add(collection_name);
+		}
+		args.add("-listall");
+		args.add("-xml");
+
+		// Run the pluginfo.pl process
+		Runtime runtime = Runtime.getRuntime();
+		Process process = runtime.exec((String[]) args.toArray(new String[] { }));
+		InputStream input_stream = process.getErrorStream();
+		xml = XMLTools.readXMLStream(input_stream);
+	    }
+
+	    // Check the XML output was obtained successfully
+	    if (xml == null || xml.length() == 0) {
+		JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.PluginManager.Plugin_List_XML_Parse_Failed"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
+		return;
+	    }
+
+	    if (collection_name != null) {
+		collection_specific_plugins_list = parsePluginsListXML(xml.toString());
+	    }
+	    else {
+		core_greenstone_plugins_list = parsePluginsListXML(xml.toString());
+	    }
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+    }
+
+
+    static private void parsePluginInfoXML(Plugin plugin, String xml)
+    {
+	Document document = XMLTools.parseXML(new StringReader(xml));
+	if (document == null) {
+	    plugin.setLoadingOptionsFailed();
+	    JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.PlugInManager.PlugIn_XML_Parse_Failed", plugin.getName()), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
+	    return;
+	}
+
+	parsePluginInfoXMLNode(plugin, document.getDocumentElement());
+    }
+
+
+    static private void parsePluginInfoXMLNode(Plugin plugin, Node root_node)
+    {
+	for (Node node = root_node.getFirstChild(); node != null; node = node.getNextSibling()) {
+	    String node_name = node.getNodeName();
+
+	    if (node_name.equalsIgnoreCase("Name")) {
+		plugin.setName(XMLTools.getValue(node));
+	    }
+	    else if (node_name.equals("Desc")) {
+		plugin.setDescription(XMLTools.getValue(node));
+	    }
+	    else if (node_name.equals("Abstract")) {
+		plugin.setIsAbstract(XMLTools.getValue(node).equalsIgnoreCase(StaticStrings.YES_STR));
+	    }
+	    else if (node_name.equalsIgnoreCase("Explodes")) {
+		plugin.setDoesExplodeMetadataDatabases(XMLTools.getValue(node).equalsIgnoreCase(StaticStrings.YES_STR));
+	    }
+	    else if (node_name.equalsIgnoreCase("Processes")) {
+		plugin.setDefaultProcessExpression(XMLTools.getValue(node));
+	    }
+	    else if (node_name.equalsIgnoreCase("Blocks")) {
+		plugin.setDefaultBlockExpression(XMLTools.getValue(node));
+	    }
+	    // Parse the plugin arguments
+	    else if (node_name.equalsIgnoreCase("Arguments")) {
+		for (Node argument_node = node.getFirstChild(); argument_node != null; argument_node = argument_node.getNextSibling()) {
+		    // An option
+		    if (argument_node.getNodeName().equalsIgnoreCase("Option")) {
+			Argument argument = new Argument();
+			argument.parseXML((Element) argument_node);
+			plugin.addArgument(argument);
+		    }
+		}
+	    }
+	    // A super plugin class
+	    else if (node_name.equalsIgnoreCase("PlugInfo")) {
+		Plugin super_plugin = new Plugin();
+		parsePluginInfoXMLNode(super_plugin, node);
+		plugin.setSuper(super_plugin);
+	    }
+	}
+    }
+
+
+    static private ArrayList parsePluginsListXML(String xml)
+    {
+	ArrayList plugins_list = new ArrayList();
+
+	Document document = XMLTools.parseXML(new StringReader(xml));
+	Node root = document.getDocumentElement();
+	for (Node node = root.getFirstChild(); node != null; node = node.getNextSibling()) {
+	    String node_name = node.getNodeName();
+
+	    if (node_name.equals("PlugInfo")) {
+		Plugin plugin = new Plugin();
+		parsePluginInfoXMLNode(plugin, node);
+		plugins_list.add(plugin);
+	    }
+	}
+
+	return plugins_list;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/greenstone3/ServletConfiguration.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/greenstone3/ServletConfiguration.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/greenstone3/ServletConfiguration.java	(revision 13928)
@@ -0,0 +1,158 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.greenstone3;
+
+import java.awt.*;
+import java.io.*;
+import java.lang.ref.*;
+import java.net.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.plaf.*;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.util.ArrayTools;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.util.XMLTools;
+import org.w3c.dom.*;
+
+/** This class stores the mapping between sites and servlets available for them. The info is read in from the web.xml file.
+ * @author Katherine Don, New Zealand Digital Library, University of Waikato
+ * @version 
+ */
+public class ServletConfiguration {
+    
+    static public String ADD_COMMAND = "?a=s&sa=a&st=collection&sn=";
+    static public String DEACTIVATE_COMMAND = "?a=s&sa=d&st=collection&sn=";
+    private String gsdl3_path = "";
+    private ArrayList sites = null;
+    private HashMap mappings = null;
+
+    public ServletConfiguration(String gsdl3_path) {
+	
+	this.gsdl3_path = gsdl3_path;
+	
+	//String web_xml_path = gsdl3_path + File.separator + "web" + File.separator + "WEB-INF"+ File.separator + "web.xml";
+	File web_xml = new File(gsdl3_path + "WEB-INF"+ File.separator + "web.xml");
+
+	if (!web_xml.exists()) {
+	    DebugStream.println("Error: no web.xml found at "+web_xml.toString());
+	    return;
+	}
+
+	this.sites = new ArrayList();
+	// find the sites
+	File start = new File(Utility.getSitesDir(gsdl3_path));
+	File possible_sites[] = start.listFiles();
+	ArrayTools.sort(possible_sites);
+	for (int i=0; possible_sites != null && i < possible_sites.length; i++) {
+	    File site_config = new File(possible_sites[i], "siteConfig.xml");
+	    if (site_config.exists()) {
+		this.sites.add(possible_sites[i].getName());
+	    }
+	}
+	
+	this.mappings = new HashMap();
+	Document web_config = XMLTools.parseXMLFile(web_xml.getAbsolutePath(), false);
+       
+	NodeList servlet_mappings = web_config.getElementsByTagName("servlet-mapping");
+	// make a little map class
+	HashMap url_mappings = new HashMap();
+	for (int i=0; i<servlet_mappings.getLength(); i++) {
+	    Element map = (Element)servlet_mappings.item(i);
+	    String name = XMLTools.getValue(XMLTools.getNodeFromNamed(map, "servlet-name"));
+	    String pattern = XMLTools.getValue(XMLTools.getNodeFromNamed(map, "url-pattern"));
+	    url_mappings.put(name, pattern);
+
+	}
+
+	NodeList servlets = web_config.getElementsByTagName("servlet");
+	for (int i=0; i<servlets.getLength(); i++) {
+	    Element servlet = (Element)servlets.item(i);
+	    String name = XMLTools.getValue(XMLTools.getNodeFromNamed(servlet, "servlet-name"));
+	    String description = XMLTools.getValue(XMLTools.getNodeFromNamed(servlet, "description"));
+	    String site = getServletSite(servlet);
+	       
+	    if (site != null) {
+		ArrayList this_site = (ArrayList)mappings.get(site);
+		if (this_site == null) {
+		    this_site = new ArrayList();
+		}
+		String url = (String)url_mappings.get(name);
+		this_site.add(url);
+		mappings.put(site, this_site);
+	    }
+	    
+	}
+
+	web_config = null;
+	url_mappings = null;
+    }
+    
+    public ArrayList getSites() {
+	return this.sites;
+    }
+
+    public ArrayList getServletsForSite(String site) {
+	return (ArrayList)this.mappings.get(site);
+    }
+    public String getServletPath(String site) {
+	
+	// for now, get the first one
+	ArrayList servlets = (ArrayList)mappings.get(site);
+	if(servlets == null) {
+	    return null;
+	}
+	return (String)servlets.get(0);
+    }
+
+    private String getServletSite(Element servlet) {
+	
+	NodeList params = servlet.getElementsByTagName("init-param");
+	if ( params == null || params.getLength() == 0) {
+	    return null;
+	}
+	String site = null;
+	for (int i=0; i<params.getLength()&& site == null; i++) {
+	    String p_name = XMLTools.getValue(XMLTools.getNodeFromNamed(params.item(i), "param-name"));
+	    if (p_name.equals("site_name")) {
+		site = XMLTools.getValue(XMLTools.getNodeFromNamed(params.item(i), "param-value"));
+	    }
+	}
+	return site;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/AboutDialog.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/AboutDialog.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/AboutDialog.java	(revision 13928)
@@ -0,0 +1,160 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Greenstone Librarian Interface (GLI) application, 
+ * part of the Greenstone digital library software suite from the New 
+ * Zealand Digital Library Project at the University of Waikato, 
+ * New Zealand.
+ *
+ * Author: John Thompson
+ *         Greenstone Project, New Zealand Digital Library
+ *         University of Waikato
+ *         http://www.nzdl.org
+ *
+ * Copyright (C) 2004 New Zealand Digital Library, University of Waikato
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.util.JarTools;
+import org.greenstone.gatherer.util.Utility;
+
+/** Generates a pretty about dialog which not only thanks those for their contributions but also meets our legal requirements if we wish to ship the JVM with GLI.
+ * @author John Thompson, Greenstone Project, New Zealand Digital Library, University of Waikato
+ * @version 2.41 final
+ */
+// RICOH SOURCE CODE PUBLIC LICENSE - http://www.risource.org/RPL/RPL-1.0A.shtml
+public class AboutDialog
+    extends JDialog {
+    /** The default size of the about dialog. */
+    static final private Dimension SIZE = new Dimension(600, 325);
+    /** The size of the GLI icon to display on dialog. */
+    static final private int ICON_SIZE = 65;
+    /** A reference to ourself so that our inner classes can dismiss us. */
+    private AboutDialog self;
+    /** The button used for dismissing the about dialog. */
+    private JButton close_button;
+    /** The constructor not only builds, but displays the about dialog. This method doesn't return until the dialog is dismissed.
+     * @param parent the JFrame which owns this dialog for use in centering the dialog
+     * @see org.greenstone.gatherer.Dictionary#get
+     * @see org.greenstone.gatherer.Dictionary#setBoth
+     * @see org.greenstone.gatherer.Dictionary#setText
+     * @see org.greenstone.gatherer.gui.AboutDialog.CloseButtonListener
+     * @see org.greenstone.gatherer.gui.GLIButton
+     */
+    public AboutDialog(JFrame parent) {
+	super(parent, Dictionary.get("AboutDialog.Title"), true);
+	this.self = this;
+	setSize(SIZE);
+		  
+	JPanel content_pane = (JPanel) getContentPane();
+	JPanel upper_pane = new JPanel();
+	ImageIcon icon = JarTools.getImage("gatherer_medium.gif");
+	ImageIcon scaled_icon = new ImageIcon(icon.getImage().getScaledInstance(ICON_SIZE, ICON_SIZE, Image.SCALE_DEFAULT));
+	JLabel icon_label = new JLabel(scaled_icon);
+	JPanel title_pane = new JPanel();
+	JLabel title_one_label = new JLabel(Dictionary.get("AboutDialog.Title_One"));
+	JLabel title_two_label = new JLabel(Gatherer.PROGRAM_NAME + " " + Gatherer.PROGRAM_VERSION + " " + Dictionary.get("AboutDialog.Date"));
+	JLabel title_three_label = new JLabel(Dictionary.get("AboutDialog.Title_Two"));
+	JLabel copyright_label = new JLabel(Dictionary.get("AboutDialog.Copyright"));
+	JLabel gpl_label = new JLabel(Dictionary.get("AboutDialog.Copyright_Two"));
+	
+	JTextArea text = new JTextArea();
+	text.setLineWrap(true);
+	text.setWrapStyleWord(true);
+
+	JPanel button_pane = new JPanel();
+	close_button = new GLIButton(Dictionary.get("General.Close"), Dictionary.get("General.Close_Tooltip"));
+	
+	// Connection
+	close_button.addActionListener(new CloseButtonListener());
+
+	// Layout
+	icon_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,10));
+
+	title_pane.setLayout(new GridLayout(5,1,0,2));
+	title_pane.add(title_one_label);
+	title_pane.add(title_two_label);
+	title_pane.add(title_three_label);
+	title_pane.add(copyright_label);
+	title_pane.add(gpl_label);
+		  
+	upper_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
+	upper_pane.setLayout(new BorderLayout());
+	upper_pane.add(icon_label, BorderLayout.WEST);
+	upper_pane.add(title_pane, BorderLayout.CENTER);
+
+	button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	button_pane.setLayout(new BorderLayout());
+	button_pane.add(close_button, BorderLayout.EAST);
+
+	content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(upper_pane, BorderLayout.NORTH);
+	content_pane.add(new JScrollPane(text), BorderLayout.CENTER);
+	content_pane.add(button_pane, BorderLayout.SOUTH);
+
+	// Build text content
+	text.append(Dictionary.get("AboutDialog.Java_Req"));
+	text.append("\n");
+	text.append(Dictionary.get("AboutDialog.Java_Req_One"));
+	text.append("\n");
+	text.append(Dictionary.get("AboutDialog.Java_Req_Two"));
+	text.append("\n\n");
+	text.append("*****" + Dictionary.get("AboutDialog.Acknowledgement") + "*****");
+	text.append("\n\n");
+	text.append(Dictionary.get("AboutDialog.Item0"));
+	text.append("\n\n");
+	text.append(Dictionary.get("AboutDialog.Item2"));
+	text.append("\n\n");
+	text.append(Dictionary.get("AboutDialog.Item3"));
+	text.append("\n\n");
+	text.append("*****" + Dictionary.get("AboutDialog.Thanks") + "*****");
+	text.append("\n\n");
+	text.append(Dictionary.get("AboutDialog.Item4"));
+	text.append("\n\n");
+	text.append(Dictionary.get("AboutDialog.Item5"));
+	text.append("\n\n");
+	text.append(Dictionary.get("AboutDialog.Item6"));
+	text.append("\n\n");
+	text.append(Dictionary.get("AboutDialog.Item7"));
+	text.append("\n\n");
+	text.append(Dictionary.get("AboutDialog.Item8"));
+	text.setCaretPosition(0);
+
+	// Show
+	Rectangle frame_bounds = parent.getBounds();
+	setLocation(frame_bounds.x + (frame_bounds.width - SIZE.width) / 2, frame_bounds.y + (frame_bounds.height - SIZE.height) / 2);
+	setVisible(true);
+    }
+    /** Listens for actions upon the close button, and when detected closes the dialog. */
+    private class CloseButtonListener
+	implements ActionListener {
+	/** Called whenever an action occurs on the close button, thus asking the dialog to close.
+	 * @param event an ActionEvent containing information about the button press
+	 */
+	public void actionPerformed(ActionEvent event) {
+	    self.setVisible(false);
+	    self.dispose();
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/BaseConfigPane.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/BaseConfigPane.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/BaseConfigPane.java	(revision 13928)
@@ -0,0 +1,247 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.CollectionDesignManager;
+import org.greenstone.gatherer.cdm.Control;
+
+/** This class is responsible for generating the necessary GUI components. It does this by calling the getEditControls() method of the appropriate class (i.e. IndexManager for index related edits). It also is in charge of correctly adding (and removing) listeners, using phrases from the <strong>Dictionary</strong> rather than the text keys inserted in the component classes, and several other aspects of the design page, including the config file section tree.
+
+/** This is a base class for Design and Format panes, which are very similar except that they have different components.  */
+public abstract class BaseConfigPane 
+    extends JPanel {
+
+    /* This should list the contents of the contents */
+    protected String contents[]; 
+    
+    /** The preferred size of the contents tree. */
+    static final private Dimension TREE_SIZE = new Dimension(200, 500);
+
+    /** The panel apon which is rendered the currently selected section screen. */
+    protected Control view = null;
+    protected String view_type = null;
+    /** The collection manager is responsible for parsing in, and allowing the editing of, a single collections configuration file. */
+    protected CollectionDesignManager cdm = null;
+    /** A tree to serve as a 'table of contents' for this design tool. We decided on a tree rather than a list, as it allows us to break sections into subsections if they become to complicated. */
+    protected DesignTree tree;
+    protected JPanel tree_pane;
+    /** The constructor. */
+    public BaseConfigPane() {
+	super();
+	DebugStream.println("BaseConfigPane: Main GUI components created.");
+	// Creation
+	tree_pane = new JPanel();
+
+	tree = new DesignTree();
+	
+	// Connect
+	tree.addTreeSelectionListener(new TreeListener());
+
+	// Layout
+	tree_pane.setLayout(new BorderLayout());
+	tree_pane.setPreferredSize(TREE_SIZE);
+	tree_pane.add(new JScrollPane(tree), BorderLayout.CENTER);
+	setLayout(new BorderLayout());
+	setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	
+	add(tree_pane, BorderLayout.WEST);
+
+
+    }
+
+    abstract protected Control getSubControls(String type);
+    
+    /** Called to cause the components to lay themselves out and be displayed.
+     */
+    public void display() {
+    }
+
+
+    public void gainFocus()
+    {
+	if (cdm == null && Gatherer.c_man.ready()) {
+	    // Retrieve the new config manager.
+	    cdm = Gatherer.c_man.getCollection().cdm;
+	}
+	if (view != null) {
+	    view.gainFocus();
+	}
+    }
+
+
+    public void loseFocus()
+    {
+	if (view != null) {
+	    view.loseFocus();
+	}
+	if (cdm != null) {
+	    Gatherer.c_man.saveCollection();
+	}
+    }
+
+
+    public void destroy() {
+	tree = null;
+	view = null;
+    }
+
+    /** Called whenever the detail mode changes to ensure the filters are at an appropriate level (ie only editable by those that understand regular expression matching)
+     * @param mode the mode level as an int
+     */
+    public void modeChanged(int mode) {
+	if (cdm != null) {
+	    cdm.modeChanged(mode);
+	}
+    }
+
+    /** This method is called whenever the state of the current collection changes.
+     */
+    public void refresh(int refresh_reason, boolean ready)
+    {
+	if (ready) {
+	    // Retrieve the new config manager.
+	    cdm = Gatherer.c_man.getCollection().cdm;
+	    tree.resetModel(Configuration.getMode()); // does this set view??
+	}
+    }
+
+
+    /** Force the display to show a certain pane of controls.
+     * @param type a String giving the name of the information manager or view we wish to display
+     */
+    public void setSelectedView(String type) {
+	tree.setSelectedView(type);
+    }
+
+    /** This tree provides a 'table of contents' for the various components of the design process (collection configuration in more technical terms). */
+    private class DesignTree
+	extends JTree {
+	private DesignNode root = null;
+	/** Constructor. Automatically generates all of the nodes, in the order of contents. */
+	public DesignTree() {
+	    super();
+	}
+
+	/** Reset the model used by the design page contents tree. This is necessary to hide the partitions entry when in lower detail modes
+	 * @param mode the current detail mode as an int
+	 */
+	public void resetModel(int mode) {
+	    root = new DesignNode("CDM.GUI.Root");
+	    // Now add the design categories.
+	    for(int i = 0; i < contents.length; i++) {
+		root.add(new DesignNode(contents[i]));
+	    }
+	    this.setModel(new DefaultTreeModel(root));
+	    expandRow(0);
+	    setRootVisible(false);
+	    setSelectionRow(0);
+	    updateUI();
+	}
+	/** Set the current view to the one specified.
+	 * @param type the name of the desired view as a String
+	 */
+	public void setSelectedView(String type) {
+	    type = Dictionary.get(type);
+	    for(int i = 0; i < root.getChildCount(); i++) {
+		DesignNode child = (DesignNode) root.getChildAt(i);
+		if(child.toString().equals(type)) {
+		    TreePath path = new TreePath(child.getPath());
+		    setSelectionPath(path);
+		}
+	    }
+	}
+    }
+    /** A tree node that retains a reference to one of the possible design sub-views relating to the different sub-managers. */
+    private class DesignNode
+	extends DefaultMutableTreeNode {
+	/** Constructor.
+	 * @param object The <strong>Object</strong> assigned to this node.
+	 */
+	public DesignNode(String object) {
+	    super(object);
+	}
+	/** Retrieve a textual representation of the object.
+	 * @return a String
+	 */
+	public String toString() {
+	    // return Dictionary.get("CDM.GUI." + (String)getUserObject());
+	    return Dictionary.get((String) getUserObject());
+	}
+    }
+    /** Listens for selection changes in the 'contents' tree, and switches to the appropriate view. */
+    private class TreeListener
+	implements TreeSelectionListener {
+	/** Called whenever the selection changes, we must update the view so it matches the node selected.
+	 * @param event A <strong>TreeSelectionEvent</strong> containing more information about the tree selection.
+	 */
+	public void valueChanged(TreeSelectionEvent event) {
+	    if(!tree.isSelectionEmpty()) {
+		TreePath path = tree.getSelectionPath();
+		DesignNode node = (DesignNode)path.getLastPathComponent();
+		String type = (String)node.getUserObject();
+		// Wait begins
+		Gatherer.g_man.wait(true);
+		// Save information in current view
+		if (view != null) { // can we get rid of this??
+		    view.loseFocus();
+		    remove((JPanel)view);
+		}
+		view_type = type;
+		// Change panes.
+		view = getSubControls(type);
+		if (view != null) {
+		    add((JPanel)view, BorderLayout.CENTER);
+		    // Update information on visible pane
+		    view.gainFocus();
+		}
+		repaint();
+		// Wait ends
+		Gatherer.g_man.wait(false);
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/CreatePane.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/CreatePane.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/CreatePane.java	(revision 13928)
@@ -0,0 +1,908 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.text.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.BuildTypeManager;
+import org.greenstone.gatherer.cdm.CollectionDesignManager;
+import org.greenstone.gatherer.collection.Collection;
+import org.greenstone.gatherer.shell.GBuildProgressMonitor;
+import org.greenstone.gatherer.shell.GImportProgressMonitor;
+import org.greenstone.gatherer.shell.GShell;
+import org.greenstone.gatherer.shell.GShellEvent;
+import org.greenstone.gatherer.shell.GShellListener;
+import org.greenstone.gatherer.shell.GShellProgressMonitor;
+import org.greenstone.gatherer.util.AppendLineOnlyFileDocument;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+
+
+/** This class provides a GUI view showing some statistics on your current collection, and options for building it. As the collection is built this initial view is replaced with one showing progress bars and a message log of the creation process. This log can be later accessed via the options tree located in the center of the initial pane. This class is also responsible for creating the GShellProgressMonitors that are then attatched to external shell processes, and calling the methods in the CollectionManager for actually importing and building the collection. <br><BR>
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class CreatePane
+    extends JPanel
+    implements GShellListener {
+
+    static private Dimension ARGUMENT_SIZE = new Dimension(800,90);
+    /** The threshold for when the simple view is replaced by the complex one. */
+    static private final int THRESHOLD = Configuration.EXPERT_MODE;
+    /** An identifier for the control panel within the card layout. */
+    static private String CONTROL  = "Control";
+    /** An identifier for the progress panel within the card layout. */
+    static private String PROGRESS = "Progress";
+    /** An identifier for the simple panel within the card layout. */
+    static private String SIMPLE   = "Simple";
+
+    /** Determines the current view that should be shown for this pane. */
+    public boolean processing = false;
+    /** The options pane generates all the various option sheet configuations. */
+    public OptionsPane options_pane = null;
+    private AppendLineOnlyFileDocument document;
+    /** A card layout is used to store the separate configuration and progress panes. */
+    private CardLayout card_layout = null;
+    /** Stores a reference to the current collection. */
+    private Collection previous_collection = null;
+    /** This monitor tracks the build processes progress. */
+    private GShellProgressMonitor build_monitor = null;
+    /** This monitor tracks the import processes progress. */
+    private GShellProgressMonitor import_monitor = null;
+    /** The button for begining the building processes. */
+    private JButton build_button = null;
+    /** The button for stopping the building processes. */
+    private JButton cancel_button = null;
+    /** The button for viewing the collection. */
+    private JButton preview_button = null;
+    private JButton simple_build_button;
+    private JButton simple_cancel_button;
+    private JButton simple_preview_button;
+    /** The radio buttons for chnaging the build type (incremental/full) */
+    private JRadioButton full_build_radio_button;
+    private JRadioButton incremental_build_radio_button;
+    private JRadioButton sfull_build_radio_button;
+    private JRadioButton sincremental_build_radio_button;
+    /** The label displaying the number of documents in this collection. */
+    private JLabel document_count = null;
+    /** The label alongside the build progress bar gets some special treatment so... */
+    private JLabel progress_build_label = null;
+    /** The label alongside the import progress bar gets some special treatment so... */
+    private JLabel progress_import_label = null;
+    private JPanel bar_area;
+    /** The panel on which buttons are rendered on higher detail modes. */
+    private JPanel button_pane;
+    /** The pane which contains the controls for configuration. */
+    private JPanel control_pane = null;
+    /** The pane which has the card layout as its manager. */
+    private JPanel main_pane = null;
+    /** The pane which contains the progress information. */
+    private JPanel progress_pane = null;
+    /** The pane on the right-hand side - shows the requested options view */
+    private JPanel right = null;
+    /** The simple panel on which all of the available arguments are rendered. */
+    private JPanel sargument_configuration_panel;
+    /** The panel on which buttons are rendered on lower details modes. */
+    private JPanel sbutton_panel;
+    /** A simplified version for lower detail modes containing both the control and progress panes smooshed together. */
+    private JSplitPane simple_panel;
+    /** The lower part of the panel which is global so the log pane can be added and removed from it */
+    private JPanel slower_panel;
+    /** The inner panel of the simple pane which is global so that the bar_area can be added and removed from it. */
+    private JPanel sinner_panel;
+    /** The scrolling pane for the log. */
+    private JScrollPane log_scroll;
+    /** The scrolling pane the simple arguments are rendered within. */
+    private JScrollPane sargument_configuration_scroll;
+    /** the scrolling pane the righthand side is inside - only used for import and build options. the log and log list are not inside a scrollpane */
+    private JScrollPane scroll_pane;
+    /** The message log for the entire session. */
+    private JTextArea log_textarea;
+    /** A tree used to display the currently available option views. */
+    private OptionTree tree = null;
+    /** An array used to pass arguments with dictionary calls. */
+    private String args[] = null;
+    /** The homepage address of the current collection */
+    public String homepage = null;
+
+
+    /** The constructor creates important helper classes, and initializes all the components.
+     * @see org.greenstone.gatherer.collection.CollectionManager
+     * @see org.greenstone.gatherer.gui.BuildOptions
+     * @see org.greenstone.gatherer.gui.CreatePane.BuildButtonListener
+     * @see org.greenstone.gatherer.gui.CreatePane.CancelButtonListener
+     * @see org.greenstone.gatherer.gui.CreatePane.OptionTree
+     * @see org.greenstone.gatherer.gui.OptionsPane
+     * @see org.greenstone.gatherer.shell.GBuildProgressMonitor
+     * @see org.greenstone.gatherer.shell.GImportProgressMonitor
+     * @see org.greenstone.gatherer.shell.GShellProgressMonitor
+     */
+    public CreatePane() {
+	log_textarea = new JTextArea();
+	log_scroll = new JScrollPane(log_textarea);
+
+	// Create components
+	card_layout = new CardLayout();
+	// Control Pane
+	control_pane = new JPanel();
+	tree = new OptionTree();
+	button_pane = new JPanel();
+
+	// Progress Pane
+	progress_pane = new JPanel(); // One owner of the bar component
+	bar_area = new JPanel(); // This component will be shared about
+
+	progress_import_label = new JLabel(Dictionary.get("CreatePane.Import_Progress"));
+	
+	import_monitor = new GImportProgressMonitor();
+	Gatherer.c_man.registerImportMonitor(import_monitor);
+
+	progress_build_label = new JLabel(Dictionary.get("CreatePane.Build_Progress"));
+	
+	build_monitor = new GBuildProgressMonitor(import_monitor.getSharedProgress());
+	Gatherer.c_man.registerBuildMonitor(build_monitor);
+
+	// And the simple panel
+	slower_panel = new JPanel();
+	sbutton_panel = new JPanel();
+	sinner_panel = new JPanel();
+
+	//Radio buttons
+	incremental_build_radio_button = new JRadioButton(Dictionary.get("CreatePane.Minimal_Build"));
+	incremental_build_radio_button.setToolTipText(Dictionary.get("CreatePane.Minimal_Build_Tooltip"));
+	full_build_radio_button = new JRadioButton(Dictionary.get("CreatePane.Full_Build"));
+	full_build_radio_button.setToolTipText(Dictionary.get("CreatePane.Full_Build_Tooltip"));
+	sincremental_build_radio_button = new JRadioButton(Dictionary.get("CreatePane.Minimal_Build"));
+	sincremental_build_radio_button.setToolTipText(Dictionary.get("CreatePane.Minimal_Build_Tooltip"));
+	sfull_build_radio_button = new JRadioButton(Dictionary.get("CreatePane.Full_Build"));
+	sfull_build_radio_button.setToolTipText(Dictionary.get("CreatePane.Full_Build_Tooltip"));
+
+
+	// Buttons
+	BuildButtonListener bbl = new BuildButtonListener();
+	CancelButtonListener cbl = new CancelButtonListener();
+	
+	build_button = new GLIButton(Dictionary.get("CreatePane.Build_Collection"), Dictionary.get("CreatePane.Build_Collection_Tooltip"));
+	build_button.addActionListener(bbl);
+	
+	cancel_button = new GLIButton(Dictionary.get("CreatePane.Cancel_Build"), Dictionary.get("CreatePane.Cancel_Build_Tooltip"));
+	cancel_button.addActionListener(cbl);
+	cancel_button.setEnabled(false);
+	
+	preview_button = new PreviewButton(Dictionary.get("CreatePane.Preview_Collection"), Dictionary.get("CreatePane.Preview_Collection_Tooltip"));
+	//preview_button.addActionListener(pbl);
+	if(Gatherer.c_man != null) {
+	    preview_button.setEnabled(Gatherer.c_man.built());
+	}
+	else {
+	    preview_button.setEnabled(false);
+	}
+	
+	simple_build_button = new GLIButton(Dictionary.get("CreatePane.Build_Collection"), Dictionary.get("CreatePane.Build_Collection_Tooltip"));
+	simple_build_button.addActionListener(bbl);
+	
+	simple_cancel_button = new GLIButton(Dictionary.get("CreatePane.Cancel_Build"), Dictionary.get("CreatePane.Cancel_Build_Tooltip"));
+	simple_cancel_button.addActionListener(cbl);
+	simple_cancel_button.setEnabled(false);
+	
+	simple_preview_button = new PreviewButton(Dictionary.get("CreatePane.Preview_Collection"), Dictionary.get("CreatePane.Preview_Collection_Tooltip"));
+	//simple_preview_button.addActionListener(pbl);
+	if(Gatherer.c_man != null) {
+	    simple_preview_button.setEnabled(Gatherer.c_man.built());
+	}
+	else {
+	    simple_preview_button.setEnabled(false);
+	}
+	
+	bbl = null;
+	cbl = null;
+	//pbl = null;
+    }
+
+
+    public void destroy() {
+	if(document != null) {
+	    document.destroy();
+	}
+    }
+    
+    /** This method is called to actually layout the components.
+     * @see org.greenstone.gatherer.Configuration
+     * @see org.greenstone.gatherer.Gatherer
+     */
+    public void display() {
+
+	int current_mode = Configuration.getMode();
+
+	//Complete/incremental build options panel
+	//For some reason I need to create seperate objects for each mode. Is there a better way??
+	ButtonGroup build_type_group = new ButtonGroup();
+	build_type_group.add(incremental_build_radio_button);
+	full_build_radio_button.setSelected(true);
+	build_type_group.add(full_build_radio_button);
+	ButtonGroup sbuild_type_group = new ButtonGroup();
+	sbuild_type_group.add(sincremental_build_radio_button);
+	sfull_build_radio_button.setSelected(true);
+	sbuild_type_group.add(sfull_build_radio_button);
+	JPanel build_type_pane = new JPanel(new GridLayout(2,1));
+	build_type_pane.add(full_build_radio_button);
+	build_type_pane.add(incremental_build_radio_button);
+	JPanel sbuild_type_pane = new JPanel(new GridLayout(2,1));
+	sbuild_type_pane.add(sfull_build_radio_button);
+	sbuild_type_pane.add(sincremental_build_radio_button);
+	
+	
+
+	// Build control_pane
+	JPanel left = new JPanel();
+	left.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
+	left.setLayout(new BorderLayout());
+	left.add(tree, BorderLayout.CENTER);
+	left.add(build_type_pane, BorderLayout.SOUTH);
+	//left.add(full_build_radio_button, BorderLayout.SOUTH);
+
+	right = new JPanel();
+	right.setBorder(BorderFactory.createEmptyBorder(0,0,5,5));
+	right.setLayout(new BorderLayout());
+
+	JPanel options_area = new JPanel();
+	options_area.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,5,5,5), BorderFactory.createTitledBorder(Dictionary.get("CreatePane.Options_Title"))));
+	options_area.setLayout(new BorderLayout());
+	options_area.add(left, BorderLayout.WEST);
+	options_area.add(right, BorderLayout.CENTER);
+
+	button_pane = new JPanel();
+	button_pane.setBorder(BorderFactory.createEmptyBorder(5,10,10,10));
+	button_pane.setLayout(new GridLayout(1,4));
+	button_pane.add(build_button);
+	button_pane.add(cancel_button);
+	button_pane.add(preview_button);
+
+	control_pane.setLayout(new BorderLayout());
+	control_pane.add(options_area, BorderLayout.CENTER);
+	control_pane.add(button_pane, BorderLayout.SOUTH);
+
+	// Build progress_pane
+	JPanel labels_pane = new JPanel();
+	labels_pane.setLayout(new GridLayout(2,1,0,5));
+	labels_pane.add(progress_import_label);
+	labels_pane.add(progress_build_label);
+
+	JPanel monitors_pane = new JPanel();
+	monitors_pane.setLayout(new GridLayout(2,1,0,5));
+	monitors_pane.add(import_monitor.getProgress());
+	monitors_pane.add(build_monitor.getProgress());
+
+	bar_area.setBorder(BorderFactory.createEmptyBorder(10,10,5,10));
+	bar_area.setLayout(new BorderLayout(5,5));
+	bar_area.add(labels_pane, BorderLayout.WEST);
+	bar_area.add(monitors_pane, BorderLayout.CENTER);
+
+	progress_pane.setBorder(BorderFactory.createEmptyBorder(20,20,20,20));
+	progress_pane.setLayout(new BorderLayout());
+	progress_pane.add(bar_area, BorderLayout.NORTH);
+	if(current_mode >= THRESHOLD) {
+	    progress_pane.add(log_scroll, BorderLayout.CENTER);
+	}
+
+	// Simple panel
+	sbutton_panel.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	sbutton_panel.setLayout(new GridLayout(1,3));
+	sbutton_panel.add(simple_build_button);
+	sbutton_panel.add(simple_cancel_button);
+	sbutton_panel.add(simple_preview_button);
+
+	JPanel simple_bar_area = new JPanel(new GridLayout(2,1));
+	simple_bar_area.setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
+	simple_bar_area.add(import_monitor.getSharedProgress());
+	simple_bar_area.add(sbutton_panel);
+
+	sinner_panel.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
+	sinner_panel.setLayout(new BorderLayout());
+	sinner_panel.add(sbuild_type_pane, BorderLayout.WEST);
+	//sinner_panel.add(full_build_radio_button, BorderLayout.WEST);
+	sinner_panel.add(simple_bar_area, BorderLayout.CENTER);
+	
+	if(options_pane != null) {
+	    sargument_configuration_panel = options_pane.buildImport(null);
+	    sargument_configuration_panel = options_pane.buildBuild(sargument_configuration_panel);
+	}
+	else {
+	    sargument_configuration_panel = new JPanel();
+	}
+	sargument_configuration_scroll = new JScrollPane(sargument_configuration_panel);
+	sargument_configuration_scroll.setPreferredSize(ARGUMENT_SIZE);
+	
+	slower_panel.setLayout(new BorderLayout());
+	slower_panel.add(sinner_panel, BorderLayout.NORTH);
+	if(current_mode < THRESHOLD) {
+	    slower_panel.add(log_scroll, BorderLayout.CENTER);
+	}
+	
+	simple_panel = new JSplitPane(JSplitPane.VERTICAL_SPLIT, sargument_configuration_scroll, slower_panel);
+	// Main pane
+	main_pane = new JPanel(card_layout);
+	if(current_mode < THRESHOLD) { // Simple mode - add first
+	    main_pane.add(simple_panel, SIMPLE);
+	}
+	main_pane.add(control_pane, CONTROL);
+	main_pane.add(progress_pane, PROGRESS);
+	if(current_mode >= THRESHOLD) { // Expert mode - add last
+	    main_pane.add(simple_panel, SIMPLE);
+	}
+
+	this.setLayout(new BorderLayout());
+	this.add(main_pane, BorderLayout.CENTER);
+    }
+
+    /** This method is called whenever the 'Create' tab is selected from the view bar. It allows this view to perform any preactions required prior to display. In this case this entails gathering up to date information about the status of the collection including number of documents etc.
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.collection.CollectionManager
+     * @see org.greenstone.gatherer.gui.CreatePane.OptionTree
+     */
+    public void gainFocus() {
+	if(Configuration.getMode() < THRESHOLD) {
+	    card_layout.show(main_pane, SIMPLE);
+	}
+	else if(!processing) {
+	    // Move the buttons to control
+	    control_pane.add(button_pane, BorderLayout.SOUTH);
+	    card_layout.show(main_pane, CONTROL);
+	}
+	else {
+	    // Move the buttons to progress
+	    progress_pane.add(button_pane, BorderLayout.SOUTH);
+	    card_layout.show(main_pane, PROGRESS);
+	}
+	// Refresh the set of controls.
+	TreePath path = tree.getSelectionPath();
+	tree.clearSelection();
+	tree.setSelectionPath(path);
+
+	//Disable the full/incremental buttons if the collection has not been built.
+	if(Gatherer.c_man.built()) {
+	    full_build_radio_button.setEnabled(true);
+	    incremental_build_radio_button.setEnabled(true);
+	    sfull_build_radio_button.setEnabled(true);
+	    sincremental_build_radio_button.setEnabled(true);
+	}
+	else {
+	    full_build_radio_button.setEnabled(false);
+	    incremental_build_radio_button.setEnabled(false);
+	    sfull_build_radio_button.setEnabled(false);
+	    sincremental_build_radio_button.setEnabled(false);
+	}
+    }
+
+    /** We are informed when this view pane loses focus so we can update build options. */
+    public void loseFocus() {
+	tree.valueChanged(null);
+    }
+
+    /**
+     * Check to see if doing an incremental build is chosen.
+     * If not, the full rebuild option must be chosen.
+     * @return boolean - true if the collection should be rebuilt incrementally.
+     */
+    public boolean isIncremental() {
+	boolean incremental = false;
+
+	//This is horrible. What if the mode is changed, and different options are chosen on different modes??
+	if(Gatherer.c_man.built()) {
+	    if(Configuration.getMode() >= THRESHOLD) {
+		incremental = incremental_build_radio_button.isSelected();
+	    }
+	    else {
+		incremental = sincremental_build_radio_button.isSelected();
+	    }
+	}
+	else {
+	    incremental = false; //The collection has not yet been built
+	}
+	return incremental;
+    }
+
+    /** All implementation of GShellListener must include this method so the listener can be informed of messages from the GShell.
+     * @param event A <strong>GShellEvent</strong> that contains, amoung other things, the message.
+     */
+    public synchronized void message(GShellEvent event) {
+	// Ignore the messages from RecPlug (used for progress bars)
+	if (event.getMessage().startsWith("import.pl> RecPlug - ")) {
+	    return;
+	}
+	document.appendLine(event.getMessage());
+	log_textarea.setCaretPosition(document.getLengthToNearestLine());
+    }
+
+    /** Called when the detail mode has changed which in turn may cause several import/build configuration arguments to be available/hidden
+     * @param mode the new mode as an int
+     */
+    public void modeChanged(int mode) {
+	// If we are below the complexity threshold ensure the simple controls are being shown
+	if(Configuration.getMode() < THRESHOLD) {
+	    // Update the arguments
+	    simple_panel.remove(sargument_configuration_scroll);
+	    if(options_pane != null) {
+		sargument_configuration_panel = options_pane.buildImport(null);
+		sargument_configuration_panel = options_pane.buildBuild(sargument_configuration_panel);
+	    }
+	    else {
+		sargument_configuration_panel = new JPanel();
+	    }
+	    sargument_configuration_scroll = new JScrollPane(sargument_configuration_panel);
+	    sargument_configuration_scroll.setPreferredSize(ARGUMENT_SIZE);
+	    simple_panel.setTopComponent(sargument_configuration_scroll);
+	    // Remove the shared components from the expert panels
+	    progress_pane.remove(log_scroll);
+	    // And add to simple one
+	    slower_panel.add(log_scroll, BorderLayout.CENTER);
+	    // And bring the card to the front
+	    card_layout.show(main_pane, SIMPLE);
+	}
+	// And if we are above the threshold change to the complex controls
+	else {
+	    // Remove the shared components from the simple panel
+	    slower_panel.remove(log_scroll);
+	    // And add then to the expert ones
+	    progress_pane.add(log_scroll, BorderLayout.CENTER);
+	    // And bring the appropriate card to the front
+	    if(!processing) {
+		control_pane.add(button_pane, BorderLayout.SOUTH);
+		card_layout.show(main_pane, CONTROL);
+	    }
+	    else {
+		progress_pane.add(button_pane, BorderLayout.SOUTH);
+		card_layout.show(main_pane, PROGRESS);
+	    }
+	}
+	tree.valueChanged(null); // Ensure tree argument panels are rebuilt
+    }
+
+    /** All implementation of GShellListener must include this method so the listener can be informed when a GShell begins its task. Implementation side-effect, not actually used.
+     * @param event A <strong>GShellEvent</strong> that contains details of the initial state of the <strong>GShell</strong> before task comencement.
+     */
+    public synchronized void processBegun(GShellEvent event) {
+	// We don't care. We'll get a more acurate start from the progress monitors.
+    }
+    /** All implementation of GShellListener must include this method so the listener can be informed when a GShell completes its task.
+     * @param event A <strong>GShellEvent</strong> that contains details of the final state of the <strong>GShell</strong> after task completion.
+     */
+    public synchronized void processComplete(GShellEvent event) {
+	DebugStream.println("In CreatePane::processComplete(" + event.getType() + ")...");
+	if(event.getStatus() == GShell.OK) {
+	    if(event.getType() == GShell.BUILD) {
+		processing = false;
+		build_button.setEnabled(true);
+		cancel_button.setEnabled(false);
+		//preview_button.setEnabled(true);
+		simple_build_button.setEnabled(true);
+		simple_cancel_button.setEnabled(false);
+		//simple_preview_button.setEnabled(true);
+		int status = event.getStatus();
+		document.setSpecialCharacter(OptionsPane.SUCCESSFUL);
+		options_pane.resetFileEntry();
+		build_monitor.reset();
+		import_monitor.reset();
+		if(Configuration.getMode() >= THRESHOLD) {
+		    control_pane.add(button_pane, BorderLayout.SOUTH);
+		    card_layout.show(main_pane, CONTROL);
+		}
+	    }
+	    // Otherwise its completed import but still got build to go
+	}
+	else {
+	    processing = false;
+	    cancel_button.setEnabled(false);
+	    build_button.setEnabled(true);
+	    // The build may have failed, but a previous index may still be in place
+	    //preview_button.setEnabled(Gatherer.c_man.built());
+
+	    simple_build_button.setEnabled(true);
+	    simple_cancel_button.setEnabled(false);
+	    //simple_preview_button.setEnabled(Gatherer.c_man.built());
+	    if(event.getStatus() == GShell.CANCELLED) {
+		document.setSpecialCharacter(OptionsPane.CANCELLED);
+	    }
+	    else {
+		document.setSpecialCharacter(OptionsPane.UNSUCCESSFUL);
+	    }
+	    options_pane.resetFileEntry();
+	    if(Configuration.getMode() >= THRESHOLD) {
+		control_pane.add(button_pane, BorderLayout.SOUTH);
+		card_layout.show(main_pane, CONTROL);
+	    }
+	}
+    }
+
+
+    /** This method is invoked at any time there has been a significant change in the collection, such as saving, loading or creating.
+     * @param ready A <strong>boolean</strong> indicating if a collection is currently available.
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.collection.CollectionManager
+     * @see org.greenstone.gatherer.gui.BuildOptions
+     * @see org.greenstone.gatherer.gui.OptionsPane
+     */
+    public void refresh(int refresh_reason, boolean ready)
+    {
+	if (Gatherer.c_man == null || !ready) {
+	    return;
+	}
+	Collection current_collection = Gatherer.c_man.getCollection();
+	if (current_collection != previous_collection && !Gatherer.c_man.isImporting()) {
+	    this.options_pane = new OptionsPane(current_collection.import_options, current_collection.build_options);
+	    if (previous_collection != null) {
+		// clear the log
+		Document log_document = log_textarea.getDocument();
+		if (log_document instanceof AppendLineOnlyFileDocument) {
+		    ((AppendLineOnlyFileDocument) log_document).destroy();
+		}
+	    }
+	    previous_collection = current_collection;
+	   
+	} 
+	// If we are in simple mode, we have to rebuild the simple arguments list
+	if(Configuration.getMode() < THRESHOLD) {
+	    simple_panel.remove(sargument_configuration_scroll);
+	    sargument_configuration_panel = options_pane.buildImport(null);
+	    sargument_configuration_panel = options_pane.buildBuild(sargument_configuration_panel);
+	    sargument_configuration_scroll = new JScrollPane(sargument_configuration_panel);
+	    sargument_configuration_scroll.setPreferredSize(ARGUMENT_SIZE);
+	    simple_panel.setTopComponent(sargument_configuration_scroll);
+	}
+	tree.valueChanged(null);
+
+	// Validate the preview button
+	if (Gatherer.c_man.built() && Configuration.library_url != null) {
+	    preview_button.setEnabled(true);
+	    simple_preview_button.setEnabled(true);
+	}
+	else {
+	    preview_button.setEnabled(false);
+	    simple_preview_button.setEnabled(false);
+	}
+    }
+
+    /** This class serves as the listener for actions on the build button. */
+    private class BuildButtonListener
+	implements ActionListener {
+	/**
+	 * This method checks to see what needs to be done for a build, and starts the process off.
+	 * A complete build proccess is started by {@link CollectionManager.importCollection()}, which then imports and builds the collection.
+	 * However, this doesn't always happen, as sometimes an incremental build will do :-)
+	 * @param event An <strong>ActionEvent</strong> who, thanks to the power of object oriented programming, we don't give two hoots about.
+	 * @see org.greenstone.gatherer.Gatherer
+	 * @see org.greenstone.gatherer.collection.CollectionManager
+	 * @see org.greenstone.gatherer.gui.BuildOptions
+	 * @see org.greenstone.gatherer.shell.GShellProgressMonitor
+	 */
+	public void actionPerformed(ActionEvent event) {
+	    Collection collection = Gatherer.c_man.getCollection();
+	    String collection_name = collection.getName();
+	    if(!collection.getMetadataChanged() && !collection.getFilesChanged() && isIncremental()) {
+		//Only design options have changes, and we want to be smart in the way we handle them.
+		int rebuildTypeRequired = CollectionDesignManager.getRebuildTypeRequired();
+		if (rebuildTypeRequired == CollectionDesignManager.BUILDCOL) {
+		    // Just run the buildcol command.
+		    DebugStream.println("Just want to run buildcol.pl");
+		    prepareForBuild();
+		    Gatherer.c_man.buildCollection(isIncremental());
+		}
+		else if (rebuildTypeRequired == CollectionDesignManager.ALL) {
+		    // Do both import and buildcol
+		    DebugStream.println("Want to do a complete build");
+		    prepareForBuild();
+		    Gatherer.c_man.importCollection(); //This starts the building process.
+		}
+		else {
+		    //Nothing at all needs doing.
+		    //This is bad HCI. Maybe should disable the build button in this situation?
+		    JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CreatePane.Minimal_Build_Not_Required"));
+		}
+	    }
+	    else {
+		//Do a complete build.
+		prepareForBuild();
+		Gatherer.c_man.importCollection(); //This starts the building process.
+	    }
+	    //Re-setting the rebuildTypeRequired is handled by CollectionManager.processComplete(GShellEvent)
+	}
+
+	/**
+	 * This does some stuff that is needed before a collection can be built.
+	 * For example, buttons are enabled/disabled, and certain flags are set.
+	 * This is called from {@link actionPerformed(ActionEvent)}
+	 */
+	private void prepareForBuild() {
+	    // First we force the build options to be updated if we haven't already.
+	    tree.valueChanged(null);
+	    
+	    // Remember that for lower thresholds the above doesn't work, so try this instead
+	    if(Configuration.getMode() < THRESHOLD) {
+		options_pane.update(sargument_configuration_panel);
+	    }
+	    
+	    // Now go about building.
+	    build_button.setEnabled(false);
+	    cancel_button.setEnabled(true);
+	    preview_button.setEnabled(false);
+	    
+	    simple_build_button.setEnabled(false);
+	    simple_cancel_button.setEnabled(true);
+	    simple_preview_button.setEnabled(false);
+	    
+	    document = options_pane.createNewLogDocument();
+	    log_textarea.setDocument(document);
+	    options_pane.log_textarea.setDocument(document);
+	    // Change the view.
+	    processing = true;
+	    if(Configuration.getMode() >= THRESHOLD) {
+		progress_pane.add(button_pane, BorderLayout.SOUTH);
+		card_layout.show(main_pane, PROGRESS);
+	    }
+	    // Reset the stop flag in all the process monitors, just incase.
+	    ((GBuildProgressMonitor)build_monitor).reset();
+	    import_monitor.setStop(false);
+	}
+    }
+    
+    
+    /** This class serves as the listener for actions on the cancel button. */
+    private class CancelButtonListener
+	implements ActionListener {
+	/** This method attempts to cancel the current GShell task. It does this by first telling CollectionManager not to carry out any further action. This it turn tells the GShell to break from the current job immediately, without waiting for the processEnded message, and then kills the thread in an attempt to stop the process. The results of such an action are debatable.
+	 * @param event An <strong>ActionEvent</strong> who, thanks to the power of object oriented programming, we don't give two hoots about.
+	 * @see org.greenstone.gatherer.Gatherer
+	 * @see org.greenstone.gatherer.collection.CollectionManager
+	 * @see org.greenstone.gatherer.gui.BuildOptions
+	 * @see org.greenstone.gatherer.shell.GShellProgressMonitor
+	 */
+	public void actionPerformed(ActionEvent event) {
+	    build_button.setEnabled(false);
+	    cancel_button.setEnabled(false);
+	    preview_button.setEnabled(false);
+
+	    simple_build_button.setEnabled(false);
+	    simple_cancel_button.setEnabled(false);
+	    simple_preview_button.setEnabled(false);
+
+	    processing = false;
+	    document.setSpecialCharacter(OptionsPane.CANCELLED);
+	    if(Configuration.getMode() >= THRESHOLD) {
+		control_pane.add(button_pane, BorderLayout.SOUTH);
+		card_layout.show(main_pane, CONTROL);
+	    }
+	    // Set the stop flag in all the process monitor.
+	    import_monitor.setStop(true);
+	    import_monitor.reset();
+	    build_monitor.setStop(true);
+	    build_monitor.reset();
+
+	    // Remove the collection lock.
+	    //Gatherer.g_man.lockCollection(false, false);
+	}
+    }
+
+    
+    /** The OptionTree is simply a tree structure that has a root node labelled "Options" and then has a child node for each available options screen. These screens are either combinations of the available import and build arguments, or a message log detailing the shell processes progress. */
+    private class OptionTree
+	extends JTree
+	implements TreeSelectionListener {
+	/** The model behind the tree. */
+	private DefaultTreeModel model = null;
+	/** The previous options view displayed, which is sometimes needed to refresh properly. */
+	private JPanel previous_pane = null;
+	/** The node corresponding to the building options view. */
+	private OptionTreeNode building  = null;
+	/** The node corresponding to the importing options view. */
+	private OptionTreeNode importing = null;
+	/** The node corresponding to the log view. */
+	private OptionTreeNode log       = null;
+	/** The root node of the options tree, which has no associated options view. */
+	private OptionTreeNode options   = null;
+	/** Constructor.
+	 * @see org.greenstone.gatherer.gui.CreatePane.OptionTreeNode
+	 */
+	public OptionTree() {
+	    super();
+
+	    ToolTipManager.sharedInstance().registerComponent(this);
+	    addTreeSelectionListener(this);
+	    getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+	    setCellRenderer(new ToolTipTreeCellRenderer());
+	    setRootVisible(false);
+	    setToggleClickCount(1);
+
+	    // Create tree.
+	    building = new OptionTreeNode(Dictionary.get("CreatePane.Build"));
+	    building.setToolTipText(Dictionary.get("CreatePane.Build_Tooltip"));
+	    importing = new OptionTreeNode(Dictionary.get("CreatePane.Import"));
+	    importing.setToolTipText(Dictionary.get("CreatePane.Import_Tooltip"));
+	    log = new OptionTreeNode(Dictionary.get("CreatePane.Log"));
+	    log.setToolTipText(Dictionary.get("CreatePane.Log_Tooltip"));
+	    options = new OptionTreeNode(Dictionary.get("CreatePane.Options"));
+
+	    model = new DefaultTreeModel(options);
+	    setModel(model);
+	    model.insertNodeInto(importing, options, 0);
+	    model.insertNodeInto(building, options, 1);
+	    model.insertNodeInto(log, options, 2);
+	    // Expand the root node
+	    expandPath(new TreePath(options));
+	}
+	/** Any implementation of TreeSelectionListener must include this method to allow this listener to know when the selection has changed. Here we swap the options view depending on the selected OptionTreeNode.
+	 * @param event A <Strong>TreeSelectionEvent</strong> which contains all the information garnered when the event occured.
+	 * @see org.greenstone.gatherer.gui.CreatePane.OptionTreeNode
+	 */
+	public void valueChanged(TreeSelectionEvent event) {
+	    TreePath path = null;
+	    OptionTreeNode node = null;
+	    //if(event != null) {
+	    //path = event.getPath();
+	    path = getSelectionPath();
+	    if(path != null) {
+		node = (OptionTreeNode)path.getLastPathComponent();
+	    }
+				//}
+	    if(previous_pane != null) {
+		//target_pane.remove(previous_pane);
+		options_pane.update(previous_pane);
+		if(scroll_pane != null) {
+		    right.remove(scroll_pane);
+		}
+		else {
+		    right.remove(previous_pane);
+		}
+		previous_pane = null;
+		scroll_pane = null;
+	    }
+	    if(node != null && node.equals(building)) {
+		previous_pane = options_pane.buildBuild(null);
+		scroll_pane = new JScrollPane(previous_pane);
+		right.add(scroll_pane, BorderLayout.CENTER);
+		//target_pane.add(previous_pane, BorderLayout.CENTER);
+	    }
+	    else if(node != null && node.equals(importing)) {
+		previous_pane = options_pane.buildImport(null);
+		scroll_pane = new JScrollPane(previous_pane);
+		right.add(scroll_pane, BorderLayout.CENTER);
+		//target_pane.add(previous_pane, BorderLayout.CENTER);
+	    }
+	    else {
+		if (options_pane != null) {
+		    previous_pane = options_pane.buildLog();
+		    right.add(previous_pane, BorderLayout.CENTER);
+		    right.updateUI(); // we need to repaint the log pane, cos it hasn't changed since last time
+		    ///ystem.err.println("I've added the log back to the right pane again.");
+		    //target_pane.add(previous_pane, BorderLayout.CENTER);
+		}
+	    }
+	    //scroll_pane.setViewportView(previous_pane);
+	    //previous_pane.validate();
+	    right.validate();
+	    //System.err.println("Current pane size: " + previous_pane.getSize());
+	    //System.err.println("While its preferred size is: " + previous_pane.getPreferredSize());
+	}
+    }
+
+    /** The <strong>OptionTree</strong> is built from these nodes, each of which has several methods used in creating the option panes.
+     */
+    private class OptionTreeNode
+	extends DefaultMutableTreeNode
+	implements Comparable {
+	/** The text label given to this node in the tree. */
+	private String title = null;
+	/** a tool tip to be used for this node in the tree */
+	private String tool_tip = null;
+	/** Constructor.
+	 * @param title The <strong>String</strong> which serves as this nodes title.
+	 */
+	public OptionTreeNode(String title) {
+	    super();
+	    this.title = title;
+	}
+
+	/** This method compares two nodes for ordering.
+	 * @param obj The <strong>Object</strong> to compare to.
+	 * @return An <strong>int</strong> of one of the possible values -1, 0 or 1 indicating if this node is less than, equal to or greater than the target node respectively.
+	 */
+	public int compareTo(Object obj) {
+	    return title.compareTo(obj.toString());
+	}
+
+	/** This method checks if two nodes are equivalent.
+	 * @param obj The <strong>Object</strong> to be tested against.
+	 * @return A <strong>boolean</strong> which is <i>true</i> if the objects are equal, <i>false</i> otherwise.
+	 */
+	public boolean equals(Object obj) {
+	    if(compareTo(obj) == 0) {
+		return true;
+	    }
+	    return false;
+	}
+
+	/** get the tool tip */
+	public String getToolTipText() {
+	    return tool_tip;
+	}
+
+	/** set the tool tip */
+	public void setToolTipText(String tip) {
+	    tool_tip = tip;
+	}
+	
+	/** Method to translate this node into a textual representation.
+	 * @return A <strong>String</strong> which in this case is the title.
+	 */
+	public String toString() {
+	    return title;
+	}
+    }
+
+    // Adds tooltips to the tree nodes
+    private class ToolTipTreeCellRenderer
+	extends DefaultTreeCellRenderer {
+
+	public Component getTreeCellRendererComponent(JTree tree,
+						      Object value,
+						      boolean sel,
+						      boolean expanded,
+						      boolean leaf,
+						      int row,
+						      boolean hasFocus) {
+
+	    super.getTreeCellRendererComponent(tree, value, sel,
+					       expanded, leaf, row,
+					       hasFocus);
+	    if (value instanceof OptionTreeNode) {
+		String tip = ((OptionTreeNode) value).getToolTipText();
+		if (tip != null) {
+		    setToolTipText(tip);
+		}
+	    }
+	    return this;
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/CreateShortcutPrompt.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/CreateShortcutPrompt.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/CreateShortcutPrompt.java	(revision 13928)
@@ -0,0 +1,142 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.io.*;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.file.WorkspaceTree;
+
+
+public class CreateShortcutPrompt	
+    extends JDialog
+    implements ActionListener, KeyListener
+{
+    /** The default size of a special mapping dialog. */
+    static final Dimension DIALOG_SIZE = new Dimension(400, 120);
+
+    private boolean cancelled = false;
+    private JButton cancel_button = null;
+    private JButton ok_button = null;
+    private JTextField name_field = null;
+
+
+    public CreateShortcutPrompt(WorkspaceTree workspace_tree, File file)
+    {
+	super(Gatherer.g_man);
+
+	setModal(true);
+	setSize(DIALOG_SIZE);
+	setTitle(Dictionary.get("MappingPrompt.Title"));
+	
+	// Creation
+	JPanel content_pane = (JPanel) getContentPane();
+	JPanel center_pane = new JPanel();
+	JPanel labels_pane = new JPanel();
+	JPanel fields_pane = new JPanel();
+
+	JLabel file_label = new JLabel(Dictionary.get("MappingPrompt.File"));
+	JLabel file_field = new JLabel(file.getAbsolutePath());
+
+	JLabel name_label = new JLabel(Dictionary.get("MappingPrompt.Name"));
+	name_field = new JTextField(file.getName());
+
+	JPanel button_pane = new JPanel();
+	ok_button = new GLIButton(Dictionary.get("General.OK"), Dictionary.get("General.OK_Tooltip"));
+	ok_button.setEnabled(name_field.getText().length() > 0);
+	cancel_button = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("General.Cancel_Tooltip"));
+	
+	// Connection
+	cancel_button.addActionListener(this);
+	ok_button.addActionListener(this);
+	name_field.addKeyListener(this);
+
+	// Layout
+	labels_pane.setLayout(new GridLayout(2,1,5,0));
+	labels_pane.add(file_label);
+	labels_pane.add(name_label);
+    
+	fields_pane.setLayout(new GridLayout(2,1,5,0));
+	fields_pane.add(file_field);
+	fields_pane.add(name_field);
+
+	center_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
+	center_pane.setLayout(new BorderLayout(5,0));
+	center_pane.add(labels_pane, BorderLayout.WEST);
+	center_pane.add(fields_pane, BorderLayout.CENTER);
+
+	button_pane.setLayout(new GridLayout(1,2,5,5));
+	button_pane.add(ok_button);
+	button_pane.add(cancel_button);
+
+	content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(center_pane, BorderLayout.CENTER);
+	content_pane.add(button_pane, BorderLayout.SOUTH);
+
+	// Display
+	Dimension screen_size = Configuration.screen_size;
+	setLocation((screen_size.width - DIALOG_SIZE.width) / 2, (screen_size.height - DIALOG_SIZE.height) / 2);
+	setVisible(true);
+
+	// If not cancelled create mapping.
+	if (!cancelled) {
+	    workspace_tree.addDirectoryMapping(name_field.getText(), file);
+	}
+    }
+
+
+    public void actionPerformed(ActionEvent event)
+    {
+	if (event.getSource() == cancel_button) {
+	    cancelled = true;
+	}
+	dispose();
+    }
+
+
+    public void destroy()
+    {
+	cancel_button = null;
+	ok_button = null;
+	name_field = null;
+    }
+
+
+    public void keyPressed(KeyEvent event) { }
+
+    public void keyReleased(KeyEvent event)
+    {
+	ok_button.setEnabled(name_field.getText().length() > 0);
+    }
+
+    public void keyTyped(KeyEvent event) { }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/DeleteCollectionPrompt.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/DeleteCollectionPrompt.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/DeleteCollectionPrompt.java	(revision 13928)
@@ -0,0 +1,313 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.net.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.BasicCollectionConfiguration;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.file.WorkspaceTree;  // !!! Don't like this here
+import org.greenstone.gatherer.util.ArrayTools;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+
+/** This class provides the functionality to delete current collections from the GSDLHOME/collect/ directory. The user chooses the collection from a list, where each entry also displays details about itself, confirms the delete of a collection by checking a checkbox then presses the ok button to actually delete the collection.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class DeleteCollectionPrompt
+    extends ModalDialog {
+    /** The currently selected collection for deletion. */
+    private BasicCollectionConfiguration collection = null;
+    /** The model behind the list. */
+    private DefaultListModel list_model = null;
+    /** A reference to ourself so any inner-classes can dispose of us. */
+    private DeleteCollectionPrompt prompt = null;
+    /** The close button, which exits the prompt without deleting anything. */
+    private JButton close_button = null;
+    /** The ok button which causes the selected collection to be deleted. */
+    private JButton ok_button = null;
+    /** The confirmation check box. */
+    private JCheckBox confirmation = null;
+    /** The label above details. */
+    private JLabel details_label = null;
+    /** The label above the list. */
+    private JLabel list_label = null;
+    /** The list of available collections. */
+    private JList list = null;
+    /** The text area used to display details about the collection selected. */
+    private JTextArea details = null;
+    /** A string array used to pass arguments to the phrase retrieval method. */
+    private String args[] = null;
+
+    private boolean current_coll_deleted = false;
+    /** The size of the delete prompt screen. */
+    public static final Dimension SIZE = new Dimension(500, 500);
+
+    /** Constructor.
+     */
+    public DeleteCollectionPrompt() {
+	super(Gatherer.g_man);
+	close_button = new GLIButton(Dictionary.get("General.Close"), Dictionary.get("General.Close_Tooltip"));
+	
+	confirmation = new JCheckBox(Dictionary.get("DeleteCollectionPrompt.Confirm_Delete"));
+	details = new JTextArea(Dictionary.get("DeleteCollectionPrompt.No_Collection"));
+	details.setEditable(false);
+	details_label = new JLabel(Dictionary.get("DeleteCollectionPrompt.Collection_Details"));
+
+	list = new JList();
+	list_label = new JLabel(Dictionary.get("DeleteCollectionPrompt.Collection_List"));
+	
+	list_model = new DefaultListModel();
+	ok_button = new GLIButton(Dictionary.get("DeleteCollectionPrompt.Delete"), Dictionary.get("DeleteCollectionPrompt.Delete_Tooltip"));
+	
+	prompt = this;
+	setModal(true);
+	setSize(SIZE);
+	setTitle(Dictionary.get("DeleteCollectionPrompt.Title"));
+	
+	setJMenuBar(new SimpleMenuBar("deletingcollections")); 
+	close_button.addActionListener(new CloseButtonListener());
+	confirmation.addActionListener(new ConfirmationCheckBoxListener());
+	confirmation.setEnabled(false);
+	confirmation.setSelected(false);
+	list.addListSelectionListener(new CollectionListListener());
+	list.clearSelection();
+	list.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+	list.setModel(list_model);
+	ok_button.addActionListener(new OKButtonListener());
+	ok_button.setEnabled(false);
+	scanForCollections();
+    }
+
+    /** Destructor. */
+    public void destroy() {
+	list_model.clear();
+	list_model = null;
+	close_button = null;
+	confirmation = null;
+	details = null;
+	details_label = null;
+	list = null;
+	ok_button = null;
+	prompt = null;
+    }
+
+    /** This method causes the modal prompt to be displayed. 
+     * returns true if it has deleted the collection that is currently open */
+    public boolean display() {
+	// Central pane
+	JPanel list_pane = new JPanel(new BorderLayout());
+	list_pane.add(list_label, BorderLayout.NORTH);
+	list_pane.add(new JScrollPane(list), BorderLayout.CENTER);
+	list_pane.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0));
+
+	JPanel details_pane = new JPanel(new BorderLayout());
+	details_pane.add(details_label, BorderLayout.NORTH);
+	details_pane.add(new JScrollPane(details), BorderLayout.CENTER);
+	details_pane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
+
+	JPanel central_pane = new JPanel(new GridLayout(2, 1));
+	central_pane.add(list_pane);
+	central_pane.add(details_pane);
+	central_pane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+
+	// Lower pane
+	JPanel confirmation_pane = new JPanel(new BorderLayout());
+	confirmation_pane.add(confirmation, BorderLayout.CENTER);
+	confirmation_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
+
+	JPanel button_pane = new JPanel(new GridLayout(1, 2));
+	button_pane.add(ok_button);
+	button_pane.add(close_button);
+	button_pane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
+
+	JPanel lower_pane = new JPanel(new BorderLayout());
+	lower_pane.add(confirmation_pane, BorderLayout.NORTH);
+	lower_pane.add(button_pane, BorderLayout.SOUTH);
+	lower_pane.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
+
+	// Final.
+	JPanel content_pane = (JPanel)this.getContentPane();
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(central_pane, BorderLayout.CENTER);
+	content_pane.add(lower_pane, BorderLayout.SOUTH);
+
+	// Center and display.
+	Dimension screen_size = Configuration.screen_size;
+	this.setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+	this.setVisible(true); // blocks until the dialog is killed
+	return current_coll_deleted;
+    }
+
+
+    /** Shows a delete complete prompt. 
+     * @param success A <strong>boolean</strong> indicating if the collection was successfully deleted.
+     * @see org.greenstone.gatherer.collection.Collection
+     */
+    public void resultPrompt(boolean success) {
+	args = new String[1];
+	args[0] = collection.getName();
+	if (success) {
+	    JOptionPane.showMessageDialog(prompt,Dictionary.get("DeleteCollectionPrompt.Successful_Delete", args),Dictionary.get("DeleteCollectionPrompt.Successful_Title"),JOptionPane.INFORMATION_MESSAGE);
+	}
+	else {
+	    JOptionPane.showMessageDialog(prompt,Dictionary.get("DeleteCollectionPrompt.Failed_Delete", args),Dictionary.get("DeleteCollectionPrompt.Failed_Title"),JOptionPane.WARNING_MESSAGE);
+	}
+    }
+
+    /** Method to scan the collect directory retrieving and reloading each collection it finds, while building the list of known collections.
+     * @see org.greenstone.gatherer.Configuration
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.util.ArrayTools
+     * @see org.greenstone.gatherer.util.Utility
+     */
+    private void scanForCollections() {
+	// Start at the collect dir.
+	File collect_directory = new File(Gatherer.getCollectDirectoryPath());
+	if (collect_directory.exists()) {
+	    // Now for each child directory see if it contains a .col file and
+	    // if so try to load it..
+	    File collections[] = collect_directory.listFiles();
+	    ArrayTools.sort(collections);
+	    for(int i = 0; collections != null && i < collections.length; i++) {
+		if(collections[i].isDirectory() && !collections[i].getName().equals(StaticStrings.MODEL_COLLECTION_NAME)) {
+		    File config_file = new File(collections[i], Utility.CONFIG_FILE);
+		    if (config_file.exists()) {
+			BasicCollectionConfiguration config = new BasicCollectionConfiguration(config_file);
+			list_model.addElement(config);
+			config = null;
+		    }
+		}
+	    }
+	}
+	// Otherwise the collect directory doesn't actually exist, so there ain't much we can do.
+    }
+
+    /** A button listener implementation, which listens for actions on the close button and disposes of the dialog when detected. */
+    private class CloseButtonListener 
+	implements ActionListener {
+	/** Any implementation of ActionListener must include this method so we can be informed when the button is actioned.
+	 * @param event An <strong>ActionEvent</strong> containing all the relevant information garnered from the event itself.
+	 */
+	public void actionPerformed(ActionEvent event) {
+	    // Done
+	    prompt.dispose();
+	}
+    }
+
+    /** This private class listens for selection events in from the list and then displays the appropriate details for that collection.
+     */
+    private class CollectionListListener 
+	implements ListSelectionListener {
+	/** Any implementation of ListSelectionListener must include this method so we can be informed when the list selection changes.
+	 * @param  event a <strong>ListSelectionEvent</strong> containing all the relevant information garnered from the event itself
+	 */
+	public void valueChanged(ListSelectionEvent event) {
+	    ok_button.setEnabled(false);
+	    confirmation.setSelected(false);
+	    if(!list.isSelectionEmpty()) {
+		confirmation.setEnabled(true);
+		collection = (BasicCollectionConfiguration) list.getSelectedValue();
+		args = new String[3];
+		args[0] = collection.getCreator();
+		args[1] = collection.getMaintainer();
+		args[2] = collection.getDescription();
+		details.setText(Dictionary.get("DeleteCollectionPrompt.Details", args));
+		details.setCaretPosition(0);
+	    }
+	    else {
+		confirmation.setEnabled(false);
+		details.setText(Dictionary.get("DeleteCollectionPrompt.No_Collection"));
+	    }
+	}
+    }
+
+    /** A check box listener so we can tell if the user has confirmed the deletion */
+    private class ConfirmationCheckBoxListener
+	implements ActionListener {
+	/** Any implementation of ActionListener must include this method so we can be informed when the button is actioned.
+	 * @param event An <strong>ActionEvent</strong> containing all the relevant information garnered from the event itself.
+	 */
+	public void actionPerformed(ActionEvent event) {
+	    // OK button is only enabled if the confirmation check box is ticked
+	    ok_button.setEnabled(confirmation.isSelected());
+	}
+    }
+
+    /** The OK button listener implementation. */
+    private class OKButtonListener 
+	implements ActionListener {
+	/** Any implementation of ActionListener must include this method so we can be informed when the button is actioned.
+	 * @param event An <strong>ActionEvent</strong> containing all the relevant information garnered from the event itself.
+	 * @see org.greenstone.gatherer.Configuration
+	 * @see org.greenstone.gatherer.Gatherer
+	 * @see org.greenstone.gatherer.util.Utility
+	 */
+	public void actionPerformed(ActionEvent event)
+	{
+	    // Delete the selected collection.
+	    if (Gatherer.c_man.deleteCollection(collection.getShortName())) {
+		// Refresh the collections shown in the workspace tree
+		Gatherer.g_man.refreshWorkspaceTree(WorkspaceTree.LIBRARY_CONTENTS_CHANGED);
+
+		if (collection.getShortName().equals(CollectionManager.getLoadedCollectionName())) {
+		    current_coll_deleted = true;
+		}
+		list_model.removeElement(collection);
+
+		resultPrompt(true);
+		details.setText(Dictionary.get("DeleteCollectionPrompt.No_Collection"));
+		confirmation.setEnabled(false);
+		confirmation.setSelected(false);
+		ok_button.setEnabled(false);
+		collection = null;
+	    }
+	    else {
+		resultPrompt(false);
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/DesignPane.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/DesignPane.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/DesignPane.java	(revision 13928)
@@ -0,0 +1,68 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import org.greenstone.gatherer.cdm.CollectionDesignManager;
+import org.greenstone.gatherer.cdm.Control;
+public class DesignPane 
+    extends BaseConfigPane {
+
+    /** The constructor. */
+    public DesignPane() {
+	super();
+	contents = new String [] { "CDM.GUI.Plugins", "CDM.GUI.Indexes", "CDM.GUI.Subcollections",  "CDM.GUI.Classifiers" };
+	
+    }
+
+    protected Control getSubControls(String type) {
+	if(type.equals("CDM.GUI.Plugins")) {
+	    return  CollectionDesignManager.plugin_manager.getControls();
+	}
+	if(type.equals("CDM.GUI.Indexes")) {
+	    return CollectionDesignManager.index_manager.getControls();
+	}
+	if(type.equals("CDM.GUI.Subcollections")) {
+	    return CollectionDesignManager.subcollection_manager.getControls();
+	}
+	if(type.equals("CDM.GUI.Classifiers")) {
+	    return CollectionDesignManager.classifier_manager.getControls();
+	}
+
+	return null;
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/DesignPaneHeader.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/DesignPaneHeader.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/DesignPaneHeader.java	(revision 13928)
@@ -0,0 +1,79 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Katherine Don, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.gui.HelpFrame;
+import org.greenstone.gatherer.gui.MenuBar;
+
+/** creates a header pane containing the title of the screen, and a help button which links to the appropriate help page */
+public class DesignPaneHeader
+    extends JPanel
+{
+    protected String help_key_name;
+
+
+    public DesignPaneHeader(String label_key, String help_key)
+    {
+	JLabel title_label = new JLabel("<HTML><STRONG><FONT FACE={FONT} COLOR=Black SIZE=5>" + Dictionary.get(label_key) + "</FONT></STRONG></HTML>");
+
+	JPanel title_pane = new JPanel();
+	title_pane.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
+	title_pane.setLayout(new BorderLayout());
+	title_pane.add(title_label, BorderLayout.CENTER);
+	title_pane.add(new JSeparator(), BorderLayout.SOUTH);
+
+	GLIButton help_button = new GLIButton(Dictionary.get("CDM.HelpButton"), Dictionary.get("CDM.HelpButton_Tooltip"));
+	this.help_key_name = help_key;
+	help_button.setIcon(MenuBar.HELP_ICON);
+	help_button.addActionListener(new ActionListener()
+	    {
+		public void actionPerformed(ActionEvent event) {
+		    HelpFrame.setView(help_key_name);
+		}
+	    });
+
+	setLayout(new BorderLayout());
+	add(title_pane, BorderLayout.CENTER);
+	add(help_button, BorderLayout.EAST);
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/DownloadPane.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/DownloadPane.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/DownloadPane.java	(revision 13928)
@@ -0,0 +1,638 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.border.*;
+import javax.swing.event.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.file.WorkspaceTree;
+import org.greenstone.gatherer.greenstone.LocalGreenstone;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.download.Download;
+import org.greenstone.gatherer.download.DownloadScrollPane;
+import org.greenstone.gatherer.download.ServerInfoDialog;
+import org.greenstone.gatherer.util.XMLTools;
+import org.greenstone.gatherer.cdm.*;
+import org.greenstone.gatherer.gui.*;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+import org.greenstone.gatherer.GAuthenticator;
+
+/**
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.1
+ */
+public class DownloadPane
+    extends JPanel {
+
+    static final private Dimension LABEL_SIZE = new Dimension(225, 25);
+    static final private Dimension TREE_SIZE = new Dimension(150, 500);
+    static final private String CONTENTS[] = { "DOWNLOAD.MODE.WebDownload", "DOWNLOAD.MODE.OAIDownload", "DOWNLOAD.MODE.ZDownload" , "DOWNLOAD.MODE.SRWDownload"};
+
+    private boolean download_button_enabled = false;
+    private boolean ready = false;
+
+    private JPanel options_pane;
+    // TODO should use Vector to store all loaded downloads!!
+
+    private DesignTree tree;
+    private HashMap download_map;
+    private ServerInfoDialog server_info;
+    private JScrollPane list_scroll;
+    private DownloadScrollPane getter;
+    private String mode = null;
+    private TreePath previous_path;
+    private String proxy_url = "";
+	    
+    /** Main System code */
+    public DownloadPane() {
+	super();
+
+	// TODO: Download the WDownload and the download panel fixed!!
+        getter = new DownloadScrollPane();
+        getter.start();
+	list_scroll = getter.getDownloadJobList();
+
+	// TODO should use Vector to store all loaded downloads!!
+	String lang = Configuration.getLanguage();
+	download_map = new HashMap();
+	download_map.put("Web", loadDownload("WebDownload",lang));
+	download_map.put("OAI", loadDownload("OAIDownload",lang));
+	download_map.put("Z3950", loadDownload("Z3950Download",lang));
+	download_map.put("SRW", loadDownload("SRWDownload",lang));
+
+	// Creation
+	tree = new DesignTree();
+	options_pane = new JPanel();
+
+	
+	JButton clear_cache_button = new GLIButton(Dictionary.get("Mirroring.ClearCache"), Dictionary.get("Mirroring.ClearCache_Tooltip"));
+	clear_cache_button.setEnabled(true);
+	clear_cache_button.setMnemonic(KeyEvent.VK_C);
+
+	JButton download_button = new GLIButton(Dictionary.get("Mirroring.Download"), Dictionary.get("Mirroring.Download_Tooltip"));
+	download_button.setEnabled(true);
+	download_button.setMnemonic(KeyEvent.VK_D);
+
+	JButton information_button =  new GLIButton(Dictionary.get("Download.ServerInformation"), Dictionary.get("Download.ServerInformation_Tooltip"));
+	information_button.setEnabled(true);
+	information_button.setMnemonic(KeyEvent.VK_S);
+
+
+       	JButton preferences_button =  new GLIButton(Dictionary.get("Mirroring.Preferences"), Dictionary.get("Mirroring.Preferences_Tooltip"));
+	preferences_button.setEnabled(true);
+	preferences_button.setMnemonic(KeyEvent.VK_P);
+
+	// Connect
+	clear_cache_button.addActionListener(new ClearCacheListener());
+	download_button.addActionListener(new DownloadButtonListener());
+	preferences_button.addActionListener(new PreferencesButtonActionListener());
+	information_button.addActionListener(new InformationButtonActionListener());
+	tree.addTreeSelectionListener(new TreeListener());
+
+	// Add to Panel
+	JPanel button_pane = new JPanel();
+	button_pane.setLayout(new FlowLayout(FlowLayout.CENTER,20,5));
+	button_pane.setBorder(BorderFactory.createEtchedBorder());
+	button_pane.add(clear_cache_button);
+	button_pane.add(download_button);
+	button_pane.add(information_button);
+	button_pane.add(preferences_button);
+
+	JPanel tree_pane = new JPanel();
+	tree_pane.setLayout(new BorderLayout());
+       	tree_pane.add(new JScrollPane(tree), BorderLayout.CENTER);
+	tree_pane.setPreferredSize(TREE_SIZE);
+ 
+
+	Color colour_two = Configuration.getColor("coloring.collection_tree_background", false);
+	options_pane.setBackground(colour_two);
+	options_pane.setBorder(BorderFactory.createEtchedBorder());
+
+
+	JScrollPane options_scroll_pane = new JScrollPane(options_pane);
+	JSplitPane mode_pane = new JSplitPane();
+	mode_pane.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
+	mode_pane.add(tree_pane,JSplitPane.LEFT);
+	mode_pane.add(options_scroll_pane,JSplitPane.RIGHT);
+	mode_pane.setDividerLocation(TREE_SIZE.width);
+    
+	JPanel edit_pane = new JPanel();
+	edit_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(2,0,0,0), BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Download Setting"), BorderFactory.createEmptyBorder(2,2,2,2))));
+	edit_pane.setLayout(new BorderLayout());
+	edit_pane.add(mode_pane,BorderLayout.CENTER);
+	edit_pane.add(button_pane,BorderLayout.PAGE_END);
+
+	// Add to "this"
+	setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	setLayout(new GridLayout(2,1));
+	add(edit_pane);
+	add(list_scroll);
+
+	mode = "Web";
+	generateOptions(options_pane,(Download)download_map.get(mode));
+	previous_path = tree.getSelectionPath();
+    }
+
+    /** System Utilities */
+    public void modeChanged(int gli_mode) {
+	// do nothing at this stage - should we be renewing download options??
+    }
+
+    private void addHeader(String name, Color color, JPanel target_pane) {
+	JPanel header = new JPanel();
+	header.setBackground(color);
+	JPanel inner_pane = new JPanel();
+	inner_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,5,5,5), BorderFactory.createRaisedBevelBorder()));
+	inner_pane.setBackground(color);
+	JLabel header_label = new JLabel("<html><strong>" + name + "</strong></html>");
+	header_label.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
+	header_label.setHorizontalAlignment(JLabel.CENTER);
+	header_label.setOpaque(true);
+
+	// Layout
+	inner_pane.setLayout(new BorderLayout());
+	inner_pane.add(header_label, BorderLayout.CENTER);
+
+	header.setLayout(new BorderLayout());
+	header.add(inner_pane, BorderLayout.CENTER);
+	target_pane.add(header);
+    }
+
+    /** Supporting Functions */
+    private Download loadDownload(String download_name, String lang) {
+	Document document = null;
+	InputStream input_stream = null;
+	
+	try {
+	    if (Gatherer.isGsdlRemote) {
+		StringBuffer launch_str = new StringBuffer();
+		launch_str.append(Gatherer.cgiBase);
+		launch_str.append("launch");
+		launch_str.append("?cmd=downloadinfo.pl&xml=&language=");
+		launch_str.append(lang);
+		launch_str.append("&plug=");
+		launch_str.append(download_name);
+
+		String launch = launch_str.toString();		
+		System.err.println("*** launch = " + launch);
+		
+		URL launch_url = new URL(launch);
+		URLConnection launch_connection = launch_url.openConnection();
+		input_stream = launch_connection.getInputStream();
+	    }
+	    else {
+		ArrayList args_list = new ArrayList();
+		String args[] = null;
+		if(Utility.isWindows()) {
+		    if(Configuration.perl_path != null) {
+			args_list.add(Configuration.perl_path);
+		    }
+		    else {
+			args_list.add("Perl.exe");
+		    }
+		}
+		args_list.add(LocalGreenstone.getBinScriptDirectoryPath()+"downloadinfo.pl");
+		args_list.add("-xml");
+		args_list.add("-language");
+		args_list.add(lang);
+		args_list.add(download_name);
+		
+		// Create the process.
+		args = (String []) args_list.toArray(new String[0]);
+		Runtime runtime = Runtime.getRuntime();
+		DebugStream.println("Getting Download Info: "+args_list);
+		Process process = runtime.exec(args);
+		
+		input_stream = process.getErrorStream();
+	    }
+
+            document = XMLTools.parseXML(input_stream);
+	}
+	catch (Exception error) {
+	    System.err.println("Failed when trying to parse: " + download_name);
+	    error.printStackTrace();
+	}
+
+	if(document != null) {
+	    return parseXML(document.getDocumentElement());
+	}
+
+	return null;
+    }
+
+    private Download parseXML(Node root) {
+	Download download = new Download();
+	String node_name = null;
+	for (Node node = root.getFirstChild(); node != null; node = node.getNextSibling()) {
+	    node_name = node.getNodeName();
+	    if(node_name.equalsIgnoreCase("Name")) {
+		String name = XMLTools.getValue(node);
+		download.setName(name);
+	    }
+	    else if (node_name.equalsIgnoreCase("Desc")) {
+		download.setDescription(XMLTools.getValue(node));
+	    }
+	    else if (node_name.equalsIgnoreCase("Abstract")) {
+		download.setIsAbstract(XMLTools.getValue(node).equalsIgnoreCase(StaticStrings.YES_STR));
+	    }
+	    else if(node_name.equalsIgnoreCase("Arguments")) {
+		for(Node arg = node.getFirstChild(); arg != null; arg = arg.getNextSibling()) {
+		    node_name = arg.getNodeName();
+                     if(node_name.equalsIgnoreCase("Option")) {
+			Argument argument = new Argument((Element)arg);
+			argument.parseXML((Element)arg);
+			argument.setValue(argument.getDefaultValue());
+			download.addArgument(argument);
+		     }
+		   
+		}
+	    }
+            else if(node_name.equalsIgnoreCase("DownloadInfo")) {
+                Download super_download = parseXML(node);
+		download.setSuper(super_download);
+	    }
+	}
+
+	if(download.getName() != null) {
+	    return download;
+	}
+	return null;
+    }
+
+    /** Update the previous setup */
+    private boolean updateArguments(boolean checkRequired)
+    {
+	boolean cont = true;
+	for(int i = 0; i < options_pane.getComponentCount(); i++) {
+	   
+	    Component component = options_pane.getComponent(i);
+	    if(component instanceof ArgumentControl) {
+		cont = cont && ((ArgumentControl)component).updateArgument(checkRequired);
+	    }
+	}
+
+	if(cont){return true; }
+
+	return false;
+    }
+    
+    /** Generate Controls for Options */
+    /* at some stage we should think about which options should be shown for
+     * different modes. Currently, always show all options (unless hidden)*/
+    private void generateOptions(JPanel options_pane, ArgumentContainer data) {
+	options_pane.removeAll();
+	/** Create the current option panel */
+
+	ArrayList arguments = data.getArguments(true, false);
+      	int mode = Configuration.getMode();
+        ArrayList added_arguments = new ArrayList();
+     
+	for(int i = 0; i < arguments.size(); i++) {
+	    Argument argument = (Argument) arguments.get(i);
+
+	    if (argument.isHiddenGLI()) continue;
+	    ArgumentControl argument_control = new ArgumentControl(argument,false,null);
+	    added_arguments.add(argument_control);
+	}
+	
+
+       	options_pane.setLayout(new GridLayout(added_arguments.size(),1));
+        for(int i = 0; i <  added_arguments.size(); i++) { 
+	    options_pane.add((ArgumentControl)added_arguments.get(i));
+	    
+	}
+    }
+
+    /** Behaviour Functions */
+    public void afterDisplay() {
+	ready = true;
+    }
+
+
+    public void gainFocus() {
+	if(!ready) {
+	    return;
+	}
+
+	// It is also a good time to determine if the download should be enabled - ie if its allowed to be enabled and a valid URL is present in the field.
+	download_button_enabled = true;
+	//download_button.setEnabled(download_button_enabled);
+    }
+
+
+
+    public void refresh(int refresh_reason, boolean ready)
+    {
+    }
+
+    /** Private classes */
+    /** This tree provides a 'table of contents' for the various components of the design process (collection configuration in more technical terms). */
+    private class DesignTree extends JTree {
+
+	private DesignNode root = null;
+	/** Constructor. Automatically generates all of the nodes, in the order of CONTENTS. */
+	public DesignTree() {
+	    super();
+	    resetModel(Configuration.getMode());
+	    expandRow(0);
+	    setRootVisible(false);
+	    setSelectionRow(0);
+	}
+
+	/** Reset the model used by the design page contents tree. This is necessary to hide the partitions entry when in lower detail modes
+	 * @param mode the current detail mode as an int
+	 */
+	public void resetModel(int mode) {
+	    root = new DesignNode("DOWNLOAD.MODE.Root");
+	    // Now add the design categories.
+	    for(int i = 0; i < CONTENTS.length; i++) {
+		root.add(new DesignNode(CONTENTS[i]));
+	    }
+	    this.setModel(new DefaultTreeModel(root));
+	    updateUI();
+	}
+	/** Set the current view to the one specified.
+	 * @param type the name of the desired view as a String
+	 */
+	public void setSelectedView(String type) {
+	    type = Dictionary.get(type);
+	    for(int i = 0; i < root.getChildCount(); i++) {
+		DesignNode child = (DesignNode) root.getChildAt(i);
+		if(child.toString().equals(type)) {
+		    TreePath path = new TreePath(child.getPath());
+		    setSelectionPath(path);
+		}
+	    }
+	}
+    }
+
+    /** A tree node that retains a reference to one of the possible design sub-views relating to the different sub-managers. */
+    private class DesignNode extends DefaultMutableTreeNode {
+	/** Constructor.
+	 * @param object The <strong>Object</strong> assigned to this node.
+	 */
+	public DesignNode(String object) {
+	    super(object);
+	}
+	/** Retrieve a textual representation of the object.
+	 * @return a String
+	 */
+	public String toString() {
+	    // return Dictionary.get("CDM.GUI." + (String)getUserObject());
+	    return Dictionary.get((String) getUserObject());
+	}
+    }
+
+    /** Listens for selection changes in the 'contents' tree, and switches to the appropriate view. */
+    private class TreeListener
+	implements TreeSelectionListener {
+	/** Called whenever the selection changes, we must update the view so it matches the node selected.
+	 * @param event A <strong>TreeSelectionEvent</strong> containing more information about the tree selection.
+	 * @see org.greenstone.gatherer.cdm.ClassifierManager
+	 * @see org.greenstone.gatherer.cdm.CollectionDesignManager
+	 * @see org.greenstone.gatherer.cdm.CollectionMetaManager
+	 * @see org.greenstone.gatherer.cdm.FormatManager
+	 * @see org.greenstone.gatherer.cdm.LanguageManager
+	 * @see org.greenstone.gatherer.cdm.MetadataSetView
+	 * @see org.greenstone.gatherer.cdm.SubcollectionManager
+	 * @see org.greenstone.gatherer.cdm.TranslationView
+	 * @see org.greenstone.gatherer.cdm.PlugInManager
+	 */
+	public void valueChanged(TreeSelectionEvent event) {
+	    if(!tree.isSelectionEmpty()) {
+		TreePath path = tree.getSelectionPath();
+
+		DesignNode node = (DesignNode)path.getLastPathComponent();
+		String type = (String)node.getUserObject();
+		Gatherer.g_man.wait(true);
+		if(type == CONTENTS[0]) {
+		    mode = "Web";
+		    generateOptions(options_pane,(Download)download_map.get(mode));
+		}
+		else if(type == CONTENTS[1]) {
+		    mode = "OAI";
+		    generateOptions(options_pane,(Download)download_map.get(mode));
+		}
+		else if(type == CONTENTS[2]) {
+		    mode = "Z3950";
+		    generateOptions(options_pane,(Download)download_map.get(mode));
+		}
+		else if(type == CONTENTS[3]) {
+		    mode = "SRW";
+		    generateOptions(options_pane,(Download)download_map.get(mode));
+		}
+		tree.setSelectionPath(path);
+		previous_path = path;
+		repaint();
+
+		Gatherer.g_man.wait(false);
+	    }
+	}
+    }
+
+    private class ClearCacheListener
+	implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    // Retrieve the cache folder and delete it.
+	    Utility.delete(Utility.getCacheDir());
+	    // ...and refresh the node in the workspace tree to show it's all gone
+	    Gatherer.g_man.refreshWorkspaceTree(WorkspaceTree.DOWNLOADED_FILES_CHANGED);
+	}
+    }
+
+    private class DownloadButtonListener
+	implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    
+	    if(checkURL(true) && checkProxy() == true) {
+		
+		getter.newDownloadJob((Download)download_map.get(mode) ,mode,proxy_url);
+	    }
+	}
+    }
+    
+
+    private boolean checkURL(boolean checkRequired){
+	
+	if (!updateArguments(checkRequired)){
+	    return false;
+	}
+
+	Download current_download = (Download)download_map.get(mode);
+	Argument arg_url = current_download.getArgument("url");
+	
+        if (arg_url == null) return true;
+ 
+	String url_str = arg_url.getValue();
+	URL url = null;
+	try {
+	    url = new URL(url_str);
+	}
+	catch(MalformedURLException error) {
+	    JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("Mirroring.Invalid_URL"), Dictionary.get("Mirroring.Invalid_URL_Title"), JOptionPane.ERROR_MESSAGE);
+	    return false;
+	}
+
+	return true;
+    }
+
+    
+    private boolean checkProxy(){
+	 
+	proxy_url = null;
+
+	Download current_download = (Download)download_map.get(mode);
+	
+        Argument arg = current_download.getArgument("proxy_on");
+  
+	if (arg == null) return true;
+	
+	// Determine if we have to use a proxy.
+	if(Configuration.get("general.use_proxy", true)) {
+          
+	    String proxy_host = Configuration.getString("general.proxy_host", true);
+	    String proxy_port = Configuration.getString("general.proxy_port", true);
+	    // Find out whether the user has already authenticated themselves
+	    String user_pass = "";
+	    String address = proxy_host + ":" + proxy_port;
+	    
+            int count = 0;
+	    while(count < 3 && (user_pass = (String) GAuthenticator.authentications.get(address)) == null) {
+		Authenticator.requestPasswordAuthentication(proxy_host, null, Integer.parseInt(proxy_port), "http://", Dictionary.get("WGet.Prompt"), "HTTP");
+		count++;
+	    }
+
+	    if(count >= 3) {
+		return false;
+	    }
+
+	    if(user_pass.indexOf("@") != -1) {
+			
+		// Write the use proxy command - we don't do this anymore, instead we set environment variables - hopefully these can't be spied on like the follwoing can (using ps) - actually the environment stuff didn't work for windows, so lets go back to this
+		if (Utility.isWindows()) {
+		     
+		   arg.setValue("true");
+		   arg.setAssigned(true);
+
+		   arg = current_download.getArgument("proxy_host");
+		   arg.setValue(proxy_host);
+		   arg.setAssigned(true);
+
+		   arg = current_download.getArgument("proxy_port");
+		   arg.setValue(proxy_port);
+		   arg.setAssigned(true);
+
+		   arg = current_download.getArgument("user_name");
+		   arg.setValue(user_pass.substring(0, user_pass.indexOf("@")));
+		   arg.setAssigned(true);
+
+		   arg = current_download.getArgument("user_password");
+		   arg.setValue(user_pass.substring(user_pass.indexOf("@") + 1));
+		   arg.setAssigned(true);
+		  }
+	       else{
+ 		    String user_name = user_pass.substring(0, user_pass.indexOf("@"));
+ 		    String user_pwd = user_pass.substring(user_pass.indexOf("@") + 1);
+ 		    proxy_url = user_name+":"+user_pwd+"@"+proxy_host+":"+proxy_port+"/";
+		   
+ 	       }
+
+	       return true;
+	    }
+	    else{
+		return false;
+	    }
+
+	}
+
+	return true;
+    }
+
+    /*
+    private class PreferencesButtonActionListener
+    implements ActionListener {
+    public void actionPerformed(ActionEvent event) {
+    new Preferences(Preferences.CONNECTION_PREFS);
+    }
+    }*/
+    
+    private class InformationButtonActionListener
+	implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    //turn off the check for find argument
+	    Download current_download = (Download)download_map.get(mode);
+
+            if (!checkProxy() || !checkURL(false) )return;
+
+
+	    if(server_info != null) {
+		server_info.dispose();
+	    }
+
+	   
+	    Argument arg_url = current_download.getArgument("url");
+	    String str_url = "";
+
+	    if( arg_url!= null && arg_url.isAssigned()) {
+		str_url = arg_url.getValue();
+	    }
+
+            
+ 	    server_info = new ServerInfoDialog(str_url ,proxy_url, mode,(Download)download_map.get(mode));
+ 	    
+	}
+    }
+
+     private class PreferencesButtonActionListener
+	implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    new Preferences(Preferences.CONNECTION_PREFS);
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/EditorDialog.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/EditorDialog.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/EditorDialog.java	(revision 13928)
@@ -0,0 +1,149 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+
+/** A class that extends a JDialog into a editor for editing large block of text for the metadata value.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+final public class EditorDialog
+    extends ModalDialog 
+    implements ActionListener {
+   /** Is this dialog editable? */
+   private boolean editable = true;
+   /** The cancel, and I don't want the text I've typed, button. */
+    private JButton cancel = null;
+    /** The ok, I'll save what I've just typed in, button. */
+    private JButton ok = null;
+    /** The area in which we type. */
+    private JTextArea text = null;
+    /** And what result should be passed back to our caller. */
+    private String result = null;
+    /** The size of the edit pop-up. */
+    final static private Dimension SIZE = new Dimension(400, 300);
+
+    /** Constructor */
+    public EditorDialog() {
+	super(Gatherer.g_man);
+    }
+
+    /** Any implementation of ActionListener must include this method so we can be informed when an action has been performed on one of our target controls. In this case we generate a pop-up window to edit in.
+     * @param event An <strong>ActionEvent</strong> containing information about the event.
+     */
+    public void actionPerformed(ActionEvent event) {
+	if (event.getSource() == ok) {
+	    result = text.getText();
+	}
+	dispose();
+    }
+
+    /** Method to display the editing box on screen.
+     * @param value The initial text to be displayed in the editing area, as a <strong>String</strong>.
+     * @return The new value for the metadata value as a <strong>String</strong> or <i>null</i> if the user has pressed cancel.
+     */
+    public String display(String value) {
+	setModal(true);
+	setSize(SIZE);
+	setJMenuBar(new SimpleMenuBar("theenrichview"));
+	if (editable) {
+	    setTitle(Dictionary.get("General.Edit"));
+	} else {
+	    setTitle(Dictionary.get("General.View"));
+	}
+	// Create
+	text = new JTextArea(value);
+	text.setCaretPosition(value.length());
+	text.setEditable(editable);
+	text.setLineWrap(true);
+	text.setWrapStyleWord(false);
+	if (editable) {
+	    text.setToolTipText(Dictionary.get("EnrichPane.Value_Field_Tooltip"));
+	} else {
+	    text.setToolTipText(Dictionary.get("EnrichPane.Value_Field_Tooltip_Uneditable"));
+	}
+
+	cancel = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("General.Pure_Cancel_Tooltip"));
+	
+	ok = new GLIButton(Dictionary.get("General.OK"), Dictionary.get("General.OK_Tooltip"));
+	
+
+	// Listeners
+	cancel.addActionListener(this);
+	ok.addActionListener(this);
+
+	// Layout
+	JPanel button_pane = new JPanel();
+	button_pane.setLayout(new GridLayout(1,2));
+	if(editable) {
+	   button_pane.add(ok);
+	   button_pane.add(cancel);
+	}
+	else {
+	   button_pane.add(new JPanel());
+	   button_pane.add(ok);
+	}
+		  
+	JPanel content_pane = (JPanel) getContentPane();
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(new JScrollPane(text), BorderLayout.CENTER);
+	content_pane.add(button_pane, BorderLayout.SOUTH);
+		  
+	Dimension screen_size = Configuration.screen_size;
+	setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+	setVisible(true);
+	return result;
+    }
+
+    /** Specify if this text dialog should be editable or readonly
+     * @param editable true to allow editing, false otherwise
+     */
+    public void setEditable(boolean editable) {
+      if(text == null) {
+	 this.editable = editable;
+      }
+      else {
+	 text.setEditable(editable);
+      }
+   }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/EmailField.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/EmailField.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/EmailField.java	(revision 13928)
@@ -0,0 +1,67 @@
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.util.regex.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.text.*;
+
+public class EmailField
+    extends JTextField 
+    implements DocumentListener {
+
+    static final public Pattern EMAIL_PATTERN = Pattern.compile("([^()\\-<> @,;:\"][^()<> @,;:\"]*|\"[^()<>@,;:\"]+\")@([A-Za-z](-*[A-Za-z0-9])*(\\.[A-Za-z](-*[A-Za-z0-9])*)*)");
+
+    private boolean invalid = false;
+    private Color background;
+    private Color invalid_background;
+
+    public EmailField(Color invalid_background) {
+	super();
+	this.invalid_background = invalid_background;
+    }
+
+    public EmailField(String email, Color invalid_background) {
+	super(email);
+	this.invalid_background = invalid_background;
+    }
+
+    /** Gives notification that an attribute or set of attributes changed.
+     * @param e
+     */
+    public void changedUpdate(DocumentEvent e) {
+	validateEmail();
+    }
+          
+    /** Gives notification that there was an insert into the document.
+     * @param e
+     */
+    public void insertUpdate(DocumentEvent e) {
+	validateEmail();
+    }
+          
+    /** Gives notification that a portion of the document has been removed. 
+     * @param e
+     */
+    public void removeUpdate(DocumentEvent e) {
+	validateEmail();
+    }
+
+    private void validateEmail() {
+	Matcher m = EMAIL_PATTERN.matcher(getText());
+	if(m.matches()) {
+	    // It was invalid, but now its valid again
+	    if(invalid) {
+		setBackground(background);
+		invalid = false;
+	    }
+	    // Otherwise nothings changed so why do anything
+	}
+	else {
+	    background = getBackground();
+	    setBackground(invalid_background);
+	    invalid = true;
+	}
+	m = null;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/EnrichPane.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/EnrichPane.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/EnrichPane.java	(revision 13928)
@@ -0,0 +1,394 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ * Based on code by John Thompson
+ *
+ * Copyright (C) 2005 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.gui;
+
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.text.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.CollectionTree;
+import org.greenstone.gatherer.collection.CollectionTreeNode;
+import org.greenstone.gatherer.gui.tree.DragTree;
+import org.greenstone.gatherer.metadata.MetadataElement;
+import org.greenstone.gatherer.metadata.MetadataValue;
+import org.greenstone.gatherer.metadata.MetadataValueTableEntry;
+import org.greenstone.gatherer.metadata.MetadataValueTreeNode;
+import org.greenstone.gatherer.metadata.MetadataXMLFileManager;
+
+
+/** Provides a view of controls for the editing of metadata.
+ */
+public class EnrichPane
+    extends JPanel
+    implements TreeSelectionListener
+{
+    static private Dimension MINIMUM_SIZE = new Dimension(100, 100);
+    static private Dimension COLLECTION_TREE_SIZE = new Dimension(250, 500);
+
+    private boolean has_focus = false;
+    /** The collection tree. */
+    private CollectionTree collection_tree = null;
+    /** The currently reported selection. */
+    private CollectionTreeNode[] file_nodes = null;
+    /** Used to dynamically filter the collection tree. */
+    private Filter collection_filter = null;
+    /** The label at the top of the collection tree, which shows the collection name. */
+    private JLabel collection_label;
+    /** The panel that contains the collection tree. */
+    private JPanel collection_pane = null;
+    /** The scrollable area into which the collection tree is placed. */
+    private JScrollPane collection_scroll = null;
+    /** The splitpane dividing the collection tree and the metadata editing controls. */
+    private JSplitPane external_split;
+    /** The metadata value table shows the metadata values that are currently assigned to a file. */
+    private MetadataValueTablePane metadata_value_table_pane = null;
+    /** The metadata value tree shows the metadata values that are currently assigned to a metadata element. */
+    private MetadataValueTreePane metadata_value_tree_pane = null;
+
+
+    public EnrichPane()
+    {
+	// Create the metadata value tree pane
+	metadata_value_tree_pane = new MetadataValueTreePane();
+	metadata_value_tree_pane.addMetadataValueTreeSelectionListener(new MetadataValueTreeSelectionListener());
+
+	// Create metadata value table pane
+	metadata_value_table_pane = new MetadataValueTablePane();
+	metadata_value_table_pane.addMetadataValueTableListSelectionListener(new MetadataValueTableListSelectionListener());
+	metadata_value_table_pane.addMetadataValueTableMouseListener(new MetadataValueTableMouseListener());
+	metadata_value_table_pane.addMetadataValueTextFieldDocumentListener(new MetadataValueTextFieldDocumentListener());
+	metadata_value_table_pane.addMetadataValueTextFieldKeyListener(new MetadataValueTextFieldKeyListener());
+    }
+
+
+    /** Some actions can only occur after this panel has been displayed on-screen, so this method is provided to do exactly that. Such actions include the proportioning of the split panes and the setting of table column widths.
+     */
+    public void afterDisplay()
+    {
+	external_split.setDividerLocation(0.3);
+    }
+
+
+    /** Used to create, connect and layout the components to be shown on this control panel.
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.file.FileOpenActionListener
+     * @see org.greenstone.gatherer.gui.Filter
+     */
+    public void display()
+    {
+	JPanel left_hand_pane = new JPanel(new BorderLayout());
+	GLIButton metadata_set_button = new GLIButton(Dictionary.get("EnrichPane.ManageMetadataSets"), Dictionary.get("EnrichPane.ManageMetadataSets_Tooltip"));
+	metadata_set_button.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent event) {
+		    MetadataSetDialog msd = new MetadataSetDialog();
+		    if (msd.setsChanged()) {
+			valueChanged(null);
+		    } 
+		}
+	    });
+	
+	// Collection Tree
+	collection_pane = new JPanel(new BorderLayout());
+	collection_pane.setMinimumSize(MINIMUM_SIZE);
+	collection_pane.setPreferredSize(COLLECTION_TREE_SIZE);
+
+	collection_label = new JLabel(Dictionary.get("Collection.No_Collection"));
+	collection_label.setOpaque(true);
+
+	collection_tree = Gatherer.c_man.getCollectionTree();
+	collection_tree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
+	collection_tree.addTreeSelectionListener(this);
+	collection_filter = collection_tree.getFilter();
+
+	external_split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
+
+	// Layout
+	collection_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(3,3,3,3), BorderFactory.createLoweredBevelBorder()));
+	collection_pane.setMinimumSize(MINIMUM_SIZE);
+	collection_pane.setPreferredSize(new Dimension(Gatherer.g_man.getSize().width / 3, Gatherer.g_man.getSize().height));
+
+	// Collection Pane
+	collection_pane.add(collection_label, BorderLayout.NORTH);
+
+	JSplitPane metadata_editing_pane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
+	metadata_editing_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
+	metadata_editing_pane.setDividerSize(8);
+
+	metadata_editing_pane.add(metadata_value_table_pane, JSplitPane.TOP);
+	metadata_editing_pane.add(metadata_value_tree_pane, JSplitPane.BOTTOM);
+	metadata_editing_pane.setDividerLocation(250);
+
+	left_hand_pane.add(collection_pane, BorderLayout.CENTER);
+	left_hand_pane.add(metadata_set_button, BorderLayout.SOUTH);
+	external_split.add(left_hand_pane, JSplitPane.LEFT);
+	external_split.add(metadata_editing_pane, JSplitPane.RIGHT);
+
+
+	
+	this.setLayout(new BorderLayout());
+	this.add(external_split, BorderLayout.CENTER);
+    }
+
+
+    /** Called to inform this pane that it has just gained focus as an effect of the user clicking on its tab
+     */
+    public void gainFocus()
+    {
+	// Remember that we currently have focus
+	has_focus = true;
+
+	// Add the collection tree and filter back into this pane
+	collection_scroll = new JScrollPane(collection_tree);
+	collection_pane.add(collection_scroll, BorderLayout.CENTER);
+	collection_pane.add(collection_filter, BorderLayout.SOUTH);
+
+	// Select the first node in the tree if nothing is already selected
+	if (collection_tree.getSelectionPaths() == null && collection_tree.getRowCount() > 0) {
+ 	    collection_tree.setImmediate(true);
+ 	    collection_tree.setSelectionRow(0);
+ 	    collection_tree.setImmediate(false);
+	    return;
+	}
+
+	// Force all of the controls to be updated
+	valueChanged(null);
+    }
+
+
+    /** Called to inform this pane that it has just lost focus as an effect of the user clicking on another tab
+     */
+    public void loseFocus()
+    {
+	// Very important: make sure metadata value is saved before leaving the pane
+	metadata_value_table_pane.stopEditingAndRebuild(file_nodes);
+
+	// Make sure all the metadata has been saved to file
+	MetadataXMLFileManager.saveMetadataXMLFiles();
+
+	// Remove the collection tree and filter from this pane so it can be added to the Gather pane
+	collection_pane.remove(collection_scroll);
+	collection_pane.remove(collection_filter);
+
+	// Remember that we no longer have focus
+	has_focus = false;
+    }
+
+
+    /** Called whenever the detail mode changes to ensure the filters are at an appropriate level (ie only editable by those that understand regular expression matching)
+     * @param mode the mode level as an int
+     */
+    public void modeChanged(int mode)
+    {
+	collection_filter.setEditable(mode > Configuration.LIBRARIAN_MODE);
+    }
+
+
+    /** Refresh this pane, depending on what has just happened (refresh_reason). */
+    public void refresh(int refresh_reason, boolean collection_loaded)
+    {
+	if (collection_loaded) {
+	    // Update collection label
+	    collection_label.setText(Dictionary.get("Collection.Collection"));
+	    collection_label.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
+	    collection_label.setForeground(Configuration.getColor("coloring.collection_heading_foreground", false));
+
+	    // Update collection tree
+	    if (refresh_reason == Gatherer.COLLECTION_OPENED) {
+		collection_tree.setModel(Gatherer.c_man.getCollectionTreeModel());
+	    }
+
+	    // Update collection filter
+	    collection_filter.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
+	}
+	else {
+	    // Update collection label
+	    collection_label.setText(Dictionary.get("Collection.No_Collection"));
+	    collection_label.setBackground(Color.lightGray);
+	    collection_label.setForeground(Color.black);
+
+	    // Update collection tree
+	    collection_tree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode("Error")));
+
+	    // Update collection filter
+	    collection_filter.setBackground(Color.lightGray);
+	}
+
+	// Enable or disable the controls
+	collection_tree.setEnabled(collection_loaded);
+	collection_filter.setEnabled(collection_loaded);
+
+	// Force the metadata table to be rebuilt (for switching extracted metadata on or off)
+	if (refresh_reason == Gatherer.PREFERENCES_CHANGED) {
+	    metadata_value_table_pane.stopEditingAndRebuild(file_nodes);
+	}
+    }
+
+
+    /** Called whenever the collection tree selection changes. This causes the metadata value table to be rebuilt. */
+    public void valueChanged(TreeSelectionEvent event)
+    {
+	// If we haven't got focus then it must have been a selection in the Gather pane, so don't bother rebuilding
+	if (has_focus == false) {
+	    return;
+	}
+
+	// Nothing selected in the collection tree
+	if (collection_tree.getSelectionCount() == 0) {
+	    file_nodes = null;
+	}
+
+	// Some files selected in the collection tree
+	else {
+	    TreePath paths[] = collection_tree.getSelectionPaths();
+	    file_nodes = new CollectionTreeNode[paths.length];
+	    for (int i = 0; i < paths.length; i++) {
+		file_nodes[i] = (CollectionTreeNode) paths[i].getLastPathComponent();
+	    }
+	}
+
+	// Update the metadata value table (and consequently, the metadata value tree)
+	metadata_value_table_pane.stopEditingAndRebuild(file_nodes);
+    }
+
+
+    private class MetadataValueTableListSelectionListener
+	implements ListSelectionListener
+    {
+	public void valueChanged(ListSelectionEvent list_selection_event)
+	{
+	    // We only want to handle one event per selection, so wait for the value to stabilise
+	    if (list_selection_event.getValueIsAdjusting()) {
+		return;
+	    }
+
+	    // Update the metadata value tree for the current table selection
+	    metadata_value_tree_pane.rebuild(metadata_value_table_pane.getSelectedMetadataValueTableEntry());
+	}
+    }
+
+
+    private class MetadataValueTableMouseListener
+	extends MouseAdapter
+    {
+	public void mouseClicked(MouseEvent mouse_event)
+	{
+	    // We're only interested in clicks on the inherited column
+	    if (metadata_value_table_pane.isMouseEventForInheritedMetadataValueTableColumn(mouse_event) == false) {
+		return;
+	    }
+
+	    // If the selected metadata is inherited, switch to the folder it came from
+	    MetadataValueTableEntry selected_metadata_value_table_entry = metadata_value_table_pane.getSelectedMetadataValueTableEntry();
+	    if (selected_metadata_value_table_entry.isInheritedMetadata()) {
+		collection_tree.setSelection(selected_metadata_value_table_entry.getFolderMetadataInheritedFrom());
+	    }
+	}
+    }
+
+
+    private class MetadataValueTextFieldDocumentListener
+	implements DocumentListener
+    {
+	/** Gives notification that an attribute or set of attributes changed */
+	public void changedUpdate(DocumentEvent document_event) {
+	    validate(document_event);
+	}
+
+	/** Gives notification that there was an insert into the document */
+	public void insertUpdate(DocumentEvent document_event) {
+	    validate(document_event);
+	}
+
+	/** Gives notification that a portion of the document has been removed */
+	public void removeUpdate(DocumentEvent document_event) {
+	    validate(document_event);
+	}
+
+
+	/** Ensures that the value tree is updated in response to changes in the value text field */
+	private void validate(DocumentEvent document_event)
+	{
+	    try {
+		Document document = document_event.getDocument();
+		String metadata_value_string = document.getText(0, document.getLength());
+		metadata_value_tree_pane.selectBestPathForMetadataValue(metadata_value_string);
+	    }
+	    catch (Exception exception) {
+		DebugStream.printStackTrace(exception);
+	    }
+	}
+    }
+
+
+    private class MetadataValueTextFieldKeyListener
+	extends KeyAdapter
+    {
+	/** Gives notification of key events on the text field */
+	public void keyPressed(KeyEvent key_event)
+	{
+	    // Tab: Auto-complete what is selected in the metadata value tree
+	    if (key_event.getKeyCode() == KeyEvent.VK_TAB) {
+		MetadataValueTreeNode selected_metadata_value_tree_node = metadata_value_tree_pane.getSelectedMetadataValueTreeNode();
+		if (selected_metadata_value_tree_node != null) {
+		    metadata_value_table_pane.setMetadataValueTextFieldValue(selected_metadata_value_tree_node.getFullValue());
+		}
+
+		// We do not want this event to be processed by the table also
+		key_event.consume();
+	    }
+
+	    // Enter: save the current value then add a blank row for the selected metadata element
+	    if (key_event.getKeyCode() == KeyEvent.VK_ENTER) {
+		metadata_value_table_pane.stopEditingAndAddBlankRowForSelectedMetadataElement();
+	    }
+	}
+    }
+
+
+    private class MetadataValueTreeSelectionListener
+	implements TreeSelectionListener
+    {
+	public void valueChanged(TreeSelectionEvent tree_selection_event)
+	{
+	    // When a node is selected in the tree, fill the metadata value text field with the selected node's value
+	    MetadataValueTreeNode selected_metadata_value_tree_node = metadata_value_tree_pane.getSelectedMetadataValueTreeNode();
+	    if (selected_metadata_value_tree_node != null) {
+		metadata_value_table_pane.setMetadataValueTextFieldValue(selected_metadata_value_tree_node.getFullValue());
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/ExplodeMetadataDatabasePrompt.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/ExplodeMetadataDatabasePrompt.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/ExplodeMetadataDatabasePrompt.java	(revision 13928)
@@ -0,0 +1,362 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Katherine Don, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 2005 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.text.*;
+import java.io.*;
+import java.util.ArrayList;
+
+import org.w3c.dom.Document;
+
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.Argument;
+import org.greenstone.gatherer.cdm.ArgumentControl;
+import org.greenstone.gatherer.cdm.CollectionDesignManager;
+import org.greenstone.gatherer.cdm.Plugin;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.collection.ScriptOptions;
+import org.greenstone.gatherer.collection.Collection;
+import org.greenstone.gatherer.greenstone.LocalGreenstone;
+import org.greenstone.gatherer.gui.tree.DragTree;
+import org.greenstone.gatherer.metadata.MetadataXMLFileManager;
+import org.greenstone.gatherer.metadata.MetadataElement;
+import org.greenstone.gatherer.metadata.MetadataSet;
+import org.greenstone.gatherer.metadata.MetadataSetManager;
+import org.greenstone.gatherer.metadata.MetadataTools;
+import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
+import org.greenstone.gatherer.shell.GShell;
+import org.greenstone.gatherer.shell.GShellEvent;
+import org.greenstone.gatherer.shell.GShellListener;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.util.XMLTools;
+
+public class ExplodeMetadataDatabasePrompt	
+    extends ModalDialog
+    implements GShellListener
+{
+    /** The size of this new collection dialog box. */
+    static private Dimension SIZE = new Dimension(675, 350);
+    private JDialog self;
+    
+    /** the file we wil be exploding */
+    private File metadata_file = null;
+    /** the list of potential plugins to be used */
+    private Argument plugin_arg = null;
+    /** holds all the available options for the exploding script */
+    private ScriptOptions options = null;
+    /** the pane containing the options */
+    private JPanel options_pane = null;
+    /** the error message if any */
+    private StringBuffer error_message = null;
+    /** whether we were successful or not */
+    private boolean successful;
+
+
+    public ExplodeMetadataDatabasePrompt(File source_file) {
+	super(Gatherer.g_man, true);
+	this.self = this;
+	this.metadata_file = source_file;
+
+	// check that we actually have an explodable file
+	ArrayList exp_plugins = CollectionDesignManager.plugin_manager.getExploderPlugins(source_file);
+	if (exp_plugins.size() == 0) {
+	    JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("ExplodeMetadataPrompt.NotExplodable"), Dictionary.get("ExplodeMetadataPrompt.Title"), JOptionPane.ERROR_MESSAGE);
+	    return;
+	}
+	plugin_arg = createPluginArgument(exp_plugins);
+	setJMenuBar(new SimpleMenuBar("explodingmetadata"));
+	setSize(SIZE);
+	setTitle(Dictionary.get("ExplodeMetadataPrompt.Title"));
+	
+	// set up the script options
+	// we have empty initial values
+	String dom_string = "<Options/>";
+	Document doc = XMLTools.parseXML(new StringReader(dom_string));
+	options = new ScriptOptions(doc.getDocumentElement(), "explode_metadata_database.pl");
+	
+	// Creation
+	JPanel content_pane = (JPanel) getContentPane();
+	content_pane.setOpaque(true);
+	
+	options_pane = new JPanel();
+	addScriptOptions(options_pane);
+	JScrollPane middle_pane = new JScrollPane(options_pane);
+
+	JTextArea instructions_area = new JTextArea(Dictionary.get("ExplodeMetadataPrompt.Instructions"));
+	instructions_area.setEditable(false);
+	instructions_area.setLineWrap(true);
+	instructions_area.setRows(5);
+	instructions_area.setWrapStyleWord(true);
+	
+	JPanel button_pane = new JPanel();
+	JButton explode_button = new GLIButton(Dictionary.get("ExplodeMetadataPrompt.Explode"), Dictionary.get("ExplodeMetadataPrompt.Explode_Tooltip"));
+	JButton cancel_button = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("General.Cancel_Tooltip"));
+	
+	// Connection
+	cancel_button.addActionListener(new CancelListener());
+	explode_button.addActionListener(new ExplodeListener());
+
+	// Layout
+
+	button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	button_pane.setLayout(new GridLayout(1,2));
+	button_pane.add(explode_button);
+	button_pane.add(cancel_button);
+
+	content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(instructions_area, BorderLayout.NORTH);
+	content_pane.add(middle_pane, BorderLayout.CENTER);
+	content_pane.add(button_pane, BorderLayout.SOUTH);
+
+	// Final dialog setup & positioning.
+	Dimension screen_size = Configuration.screen_size;
+	setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+	setVisible(true);
+    }
+
+    public void destroy() 
+    {
+       	
+    }
+
+    /** All implementation of GShellListener must include this method so the listener can be informed of messages from the GShell.
+     * @param event A <strong>GShellEvent</strong> that contains, amoung other things, the message.
+     */
+    public synchronized void message(GShellEvent event) {
+	String message = event.getMessage();
+	if (message.startsWith("explode_metadata_database.pl>")) {
+	    message = message.substring(29);
+	    error_message.append(message);
+	    error_message.append("\n");
+	}
+    }
+
+    /** All implementation of GShellListener must include this method so the listener can be informed when a GShell begins its task. Implementation side-effect, not actually used.
+     * @param event A <strong>GShellEvent</strong> that contains details of the initial state of the <strong>GShell</strong> before task comencement.
+     */
+    public synchronized void processBegun(GShellEvent event) {
+	// We don't care. 
+    }
+    
+    /** All implementation of GShellListener must include this method so the listener can be informed when a GShell completes its task.
+     * @param event A <strong>GShellEvent</strong> that contains details of the final state of the <strong>GShell</strong> after task completion.
+     */
+    public synchronized void processComplete(GShellEvent event) {
+	successful = false;
+	if(event.getStatus() == GShell.OK) {
+	    successful = true;
+	}
+    }
+
+    private Argument createPluginArgument(ArrayList plugin_list) {
+	Argument arg = new Argument();
+	arg.setName("plugin");
+	arg.setDescription(Dictionary.get("ExplodeMetadataPrompt.Plugin"));
+	arg.setRequired(true);
+	arg.setType(Argument.ENUM);
+	for (int i=0; i<plugin_list.size(); i++) {
+	    Plugin p = (Plugin)plugin_list.get(i);
+	    arg.addOption(p.getName(), p.getName());
+	}
+	return arg;
+    }
+    private void addScriptOptions(JPanel options_pane) {
+
+	options_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	options_pane.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
+	options_pane.setLayout(new BoxLayout(options_pane, BoxLayout.Y_AXIS));
+
+	int current_mode = Configuration.getMode();
+	int total_argument_count = options.getArgumentCount();
+       
+	// first we add the plugin arg
+	ArgumentControl argument_control = new ArgumentControl(plugin_arg, true, null);
+	argument_control.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
+	options_pane.add((JComponent)argument_control);
+	for(int i = 0; i < total_argument_count; i++) {
+	    // Retrieve the argument so we know how to format the control.
+	    Argument argument = options.getArgument(i);
+	    if(!argument.isHiddenGLI() && argument.getModeLevel() <= current_mode) {
+		if (argument.getName().equals("metadata_set")) {
+		    argument.setType(Argument.METADATA_SET_NAMESPACE);
+		    argument_control = new ArgumentControl(argument, true, "Exploded Metadata Set (exp)");
+		}
+		else {
+		    // by default, all args are disabled, and no value
+		    argument_control = new ArgumentControl(argument, false, null);
+		}
+		// make sure they are coloured the way we want - this is not the standard arg control coloring
+		argument_control.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
+		options_pane.add((JComponent)argument_control);
+	    }
+	}
+    }
+
+    private void updateScriptOptions() {
+	for(int i = 0; i < options_pane.getComponentCount(); i++) {
+	    Component component = options_pane.getComponent(i);
+	    if(component instanceof ArgumentControl) {
+		ArgumentControl ac = (ArgumentControl)component;
+		String name = ac.getArgumentName();
+		String value = ac.getValue();
+		boolean enabled = ac.isEnabled();
+		if (!enabled && value==null) {
+		    // flag type, remove from options altogether
+		    options.removeValue(name);
+		} else {
+		    if (value.equals("")) {
+			// if the value is empty, we don't want it to be passed to the script
+			options.setValue(name, false, value);
+		    } else {
+			options.setValue(name, enabled, value);
+		    }
+		}
+
+	    }
+	}
+    }
+
+    private int explodeMetadata()
+    {
+	// Generate the explode_metadata_database.pl command
+	ArrayList command_parts_list = new ArrayList();
+	if (Utility.isWindows() && (!Gatherer.isGsdlRemote)) {
+	    command_parts_list.add(Configuration.perl_path);
+	    command_parts_list.add("-S");
+	}
+	command_parts_list.add(LocalGreenstone.getBinScriptDirectoryPath() + "explode_metadata_database.pl");
+	
+	// Add in all the options from the user
+	String[] explode_options = options.getValues();
+	for (int i = 0; i < explode_options.length; i++) {
+	    command_parts_list.add(explode_options[i]);
+	}
+
+	// Local case
+	if (!Gatherer.isGsdlRemote) {
+	    // Add in the filename
+	    command_parts_list.add(metadata_file.getPath());
+	}
+	// Remote case
+	else {
+	    // Add in the filename, relative to the collection directory
+	    String collection_name = CollectionManager.getLoadedCollectionName();
+	    String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name);
+	    String metadata_file_relative_path = RemoteGreenstoneServer.getPathRelativeToDirectory(metadata_file, collection_directory_path);
+	    command_parts_list.add("-file");
+	    command_parts_list.add(metadata_file_relative_path);
+
+	    // When running remotely we also need the collection name as the last argument
+	    command_parts_list.add(collection_name);
+	}
+
+	// Run the explode_metadata_database.pl command
+	String[] command_parts = (String[]) command_parts_list.toArray(new String[0]);
+	this.error_message = new StringBuffer();
+	GShell process = new GShell(command_parts, GShell.EXPLODE, 3, this, null, GShell.GSHELL_EXPLODE);
+	//process.start();
+	process.run();
+	
+	if (successful) {
+	    return 0;
+	} 
+	return -1;
+    }
+
+    private void resultPrompt(boolean success, String message)
+    {
+	if (success) {
+	    // !!! TO DO: Get explode_metadata_database.pl strings translated and use SimpleResultDialog below
+	    JOptionPane.showMessageDialog(null, Dictionary.get("ExplodeMetadataPrompt.Successful_Explode", metadata_file.getName()), Dictionary.get("ExplodeMetadataPrompt.Successful_Title"), JOptionPane.INFORMATION_MESSAGE);
+	}
+	else {
+	    String title = Dictionary.get("ExplodeMetadataPrompt.Failed_Title");
+	    String label = Dictionary.get("ExplodeMetadataPrompt.Failed_Explode", metadata_file.getName());
+	    SimpleResultDialog result_dialog = new SimpleResultDialog(title, label, message);
+	    result_dialog.setVisible(true); // Blocks
+	    result_dialog.dispose();
+	    result_dialog = null;
+	}
+    }
+
+    private class CancelListener
+	implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    self.dispose();
+	}
+    }
+    
+    private class ExplodeListener
+	implements ActionListener {
+	
+	public void actionPerformed(ActionEvent event) {
+	    Gatherer.g_man.wait(true);
+	    // update the options
+	    updateScriptOptions();
+	    self.dispose();  
+	    (new ExplodeMetadataDatabaseTask()).start();
+	}
+    }
+
+
+    private class ExplodeMetadataDatabaseTask
+	extends Thread
+    {
+	public ExplodeMetadataDatabaseTask()
+	{
+	}
+
+	public void run()
+	{
+	    int exit_value = explodeMetadata();
+	    if (exit_value == 0) { // success
+		// Clear out the old directory containing the metadata file and download the new directory
+		if (Gatherer.isGsdlRemote) {
+		    Utility.delete(metadata_file.getParentFile());
+		    RemoteGreenstoneServer.downloadCollectionFile(CollectionManager.getLoadedCollectionName(), metadata_file.getParentFile());
+		}
+
+		// Load the new metadata.xml files
+                Collection collection = Gatherer.c_man.getCollection();
+             	MetadataXMLFileManager.loadMetadataXMLFiles(metadata_file.getParentFile(),collection.toSkimFile());
+		Gatherer.g_man.refreshCollectionTree(DragTree.COLLECTION_CONTENTS_CHANGED);
+		resultPrompt(true, error_message.toString());
+	    } else { // failure
+		resultPrompt(false, error_message.toString());
+	    }
+	    error_message = null;
+	    Gatherer.g_man.wait(false);
+	}
+    }    
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/ExportAsPrompt.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/ExportAsPrompt.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/ExportAsPrompt.java	(revision 13928)
@@ -0,0 +1,921 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import javax.swing.*;
+import javax.swing.event.*;
+
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.BasicCollectionConfiguration;
+import org.greenstone.gatherer.greenstone.LocalGreenstone;
+import org.greenstone.gatherer.shell.GShell;
+import org.greenstone.gatherer.shell.GShellEvent;
+import org.greenstone.gatherer.shell.GShellListener;
+import org.greenstone.gatherer.shell.GDefaultProgressMonitor;
+import org.greenstone.gatherer.util.ArrayTools;
+import org.greenstone.gatherer.util.CheckList;
+import org.greenstone.gatherer.util.CheckListEntry;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+
+/** This class provides the functionality to export a set of current
+ * collections from the GSDLHOME/collect/ directory to various formats
+ * (hence ExportAs) using export.pl. The user chooses the collection from a
+ * list, where each entry also displays details about itself, confirms the
+ * delete of a collection by checking a checkbox then presses the ok button
+ * to actually delete the collection.  
+ * Copied from WriteCDImagePrompt
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class ExportAsPrompt
+    extends ModalDialog 
+    implements GShellListener {
+
+    static final private Dimension LABEL_SIZE = new Dimension(120, 25);
+    
+    private OKButtonListener ok_button_listener;
+
+    private JLabel saveas_label = null;
+    private JComboBox saveas_combobox = null;
+
+    private ArrayList all_collections = null;
+    private ArrayList selected_collections = null;
+    /** The list of collections to include in exported cd-rom/dvd image */
+    private CheckList list = null;
+    /** The currently selected collection for deletion. */
+    private BasicCollectionConfiguration collection = null;
+    /** A reference to ourself so any inner-classes can dispose of us. */
+    private ExportAsPrompt prompt = null;
+    /** The close button, which exits the prompt without deleting anything. */
+    private JButton cancel_button = null;
+    /** The ok button which causes the selected collection to be deleted. */
+    private JButton ok_button = null;
+    /** The label above details. */
+    private JLabel details_label = null;
+    /** The label above the list. */
+    private JLabel list_label = null;
+    /** The text area used to display details about the collection selected. */
+    private JTextArea details_textarea = null;
+    /** The text area used to display instructions for the cd-rom/dvd export */
+    private JTextArea instructions_textarea;
+    /** A string array used to pass arguments to the phrase retrieval method. */
+    private JTextField title_field = null;
+    private JLabel title_label = null;
+    private String args[] = null;
+    private String cd_title = null;
+    /** whether the exporting was successful or not */
+    private boolean successful = false;
+    /** whether we are trying to export or not */
+    private boolean exporting = false;
+    /** the error message if any */
+    private StringBuffer error_message = null;
+    /** The size of the export prompt screen. */
+    public static final Dimension SIZE = new Dimension(500, 540);  
+    private GDefaultProgressMonitor progress_monitor;    
+
+    private JButton convert_xml_button1 = null;
+    private JButton convert_xml_button2 = null;
+    private JButton convert_xml_button3 = null;
+    private JButton folder_button = null;
+
+    private JPanel instructions_pane = null;
+    
+    private JPanel convert_xml_pane1 = null;
+    private JPanel convert_xml_pane2 = null;
+    private JPanel mapping_xml_pane = null;
+
+    private JCheckBox convert_xml_checkbox1 = null; 
+    private JCheckBox convert_xml_checkbox2 = null;
+    private JCheckBox mapping_xml_checkbox = null;
+    
+    private JCheckBox output_single_checkbox = null;  
+
+    private JTextField convert_xml_field1 = null;
+    private JTextField convert_xml_field2 = null;
+    private JTextField mapping_xml_field = null;
+
+
+    private File xsl_file1 = null;
+    private File xsl_file2 = null;
+    private File mapping_file = null;
+
+    private JPanel convert_xml_pane = null; 
+
+    private HashMap plugoutMap = new HashMap();
+  
+
+    /** Constructor.
+     * @see org.greenstone.gatherer.collection.ExportAsPrompt.CancelButtonListener
+     * @see org.greenstone.gatherer.collection.ExportAsPrompt.CollectionListListener
+     * @see org.greenstone.gatherer.collection.ExportAsPrompt.OKButtonListener
+     */
+    public ExportAsPrompt() {
+	super(Gatherer.g_man, true);
+	
+	plugoutMap.clear();         
+	plugoutMap.put("DSpace","dublin-core.xml");
+        plugoutMap.put("MARCXML","doc.xml");   
+	plugoutMap.put("METS","doctxt.xml,docmets.xml");     
+	plugoutMap.put("GA","doc.xml");
+
+        cancel_button = new GLIButton(Dictionary.get("General.Close"), Dictionary.get("General.Close_Tooltip"));
+	
+	details_textarea = new JTextArea(Dictionary.get("DeleteCollectionPrompt.No_Collection"));
+	details_textarea.setEditable(false);
+	
+	details_label = new JLabel(Dictionary.get("DeleteCollectionPrompt.Collection_Details"));
+	
+
+	instructions_textarea = new JTextArea(Dictionary.get("ExportAsPrompt.Instructions"));
+	instructions_textarea.setCaretPosition(0);
+	instructions_textarea.setEditable(false);
+	instructions_textarea.setLineWrap(true);
+	instructions_textarea.setRows(4);
+	instructions_textarea.setWrapStyleWord(true);
+	
+             
+        // Save As
+	ArrayList saveas_formats = new ArrayList(plugoutMap.keySet());
+       
+        saveas_label = new JLabel(Dictionary.get("ExportAsPrompt.SaveAs")
+);
+        //saveas_label.setPreferredSize(LABEL_SIZE);
+        
+        saveas_combobox = new JComboBox(saveas_formats.toArray());
+	saveas_combobox.setOpaque(false);
+	saveas_combobox.setToolTipText(Dictionary.get("ExportAsPrompt.SaveAs_Tooltip"));
+        
+
+	// Add xml conversion feature
+	convert_xml_button1 = new GLIButton(Dictionary.get("ExportAsPrompt.Browse"),Dictionary.get("ExportAsPrompt.Browse_Tooltip"));
+	convert_xml_button1.setEnabled(false);
+
+	convert_xml_button2 = new GLIButton(Dictionary.get("ExportAsPrompt.Browse"),Dictionary.get("ExportAsPrompt.Browse_Tooltip"));
+	convert_xml_button2.setEnabled(false);
+	
+	convert_xml_button3 = new GLIButton(Dictionary.get("ExportAsPrompt.Browse"),Dictionary.get("ExportAsPrompt.Browse_Tooltip"));
+	convert_xml_button3.setEnabled(false);
+
+	convert_xml_checkbox1 = new JCheckBox();
+        convert_xml_checkbox1.setText(Dictionary.get("ExportAsPrompt.ApplyXSL","doc.xml"));
+        convert_xml_checkbox1.setToolTipText(Dictionary.get("ExportAsPrompt.ApplyXSL_Tooltip"));
+        
+	convert_xml_checkbox2 = new JCheckBox();
+        convert_xml_checkbox2.setToolTipText(Dictionary.get("ExportAsPrompt.ApplyXSL_Tooltip"));
+
+
+        output_single_checkbox = new JCheckBox();
+	output_single_checkbox.setText(Dictionary.get("ExportAsPrompt.MARCXMLGroup"));
+        output_single_checkbox.setToolTipText(Dictionary.get("ExportAsPrompt.MARCXMLGroup_Tooltip"));
+
+
+        mapping_xml_checkbox = new JCheckBox();
+	mapping_xml_checkbox.setText(Dictionary.get("ExportAsPrompt.MappingXML"));
+        mapping_xml_checkbox.setToolTipText(Dictionary.get("ExportAsPrompt.MappingXML_Tooltip"));
+
+
+        convert_xml_field1 = new JTextField();
+	convert_xml_field2 = new JTextField();
+	mapping_xml_field = new JTextField();
+
+        convert_xml_pane1 = new JPanel(new BorderLayout());
+	
+	convert_xml_pane2 = new JPanel(new BorderLayout());
+
+	mapping_xml_pane = new JPanel(new BorderLayout());
+
+	convert_xml_pane = new JPanel(new GridLayout(3,1));
+
+	all_collections = new ArrayList();
+	list = new CheckList(true);
+	list_label = new JLabel(Dictionary.get("DeleteCollectionPrompt.Collection_List"));
+	
+	ok_button = new GLIButton(Dictionary.get("ExportAsPrompt.Export"), Dictionary.get("ExportAsPrompt.Export_Tooltip"));
+	
+	title_field = new JTextField();
+	title_field.setToolTipText(Dictionary.get("ExportAsPrompt.Export_Name_Tooltip"));
+	title_label = new JLabel(Dictionary.get("ExportAsPrompt.Export_Name"));
+
+        folder_button = new GLIButton(Dictionary.get("ExportAsPrompt.Browse"),Dictionary.get("ExportAsPrompt.Browse_Tooltip"));
+	folder_button.addActionListener(new FolderButtonListener());
+   
+	
+	scanForCollections();
+	list.setListData(all_collections);
+
+	prompt = this;
+	setSize(SIZE);
+	setTitle(Dictionary.get("ExportAsPrompt.Title"));
+
+	setJMenuBar(new SimpleMenuBar("exporting")); 
+	cancel_button.addActionListener(new CancelButtonListener());
+	list.addListSelectionListener(new CollectionListListener());
+	list.clearSelection();
+	list.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+	ok_button_listener = new OKButtonListener();
+	ok_button.addActionListener(ok_button_listener);
+	ok_button.setEnabled(false);
+	//title.getDocument().addDocumentListener(new DocumentListener());
+
+       	convert_xml_button1.addActionListener(new ConvertXMLButtonListener());
+	convert_xml_checkbox1.addActionListener(new ConvertXMLCheckboxListener());
+	mapping_xml_checkbox.addActionListener(new ConvertXMLCheckboxListener());
+	convert_xml_button3.addActionListener(new ConvertXMLButtonListener());
+   
+	convert_xml_button2.addActionListener(new ConvertXMLButtonListener());
+	convert_xml_checkbox2.addActionListener(new ConvertXMLCheckboxListener());
+
+        saveas_combobox.addActionListener(new SaveasListener());        
+
+    }
+
+    /** Destructor. */
+    public void destroy() {
+        saveas_label = null;
+	saveas_combobox = null;
+	all_collections.clear();
+	all_collections = null;
+	cancel_button = null;
+	details_textarea = null;
+	details_label = null;
+	list = null;
+	ok_button = null;
+	prompt = null;
+	if (selected_collections!=null) {
+	    selected_collections.clear();
+	    selected_collections = null;
+	}
+	title_field = null;
+	title_label = null;
+    }
+
+    /** This method causes the modal prompt to be displayed. 
+     * returns true if it has exported the collections that are currently selected */
+    public boolean display() {
+	// Top pane
+	instructions_pane = new JPanel(new BorderLayout());
+	instructions_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,5));
+	instructions_pane.add(new JScrollPane(instructions_textarea), BorderLayout.CENTER);
+	
+	title_label.setBorder(BorderFactory.createEmptyBorder(0,5,0,15));
+
+	JPanel title_pane = new JPanel(new BorderLayout());
+	title_pane.add(title_label, BorderLayout.WEST);
+	title_pane.add(title_field, BorderLayout.CENTER);
+        title_pane.add(folder_button, BorderLayout.EAST);
+        //apply xsl pane
+          
+	convert_xml_pane1.removeAll();
+        convert_xml_pane2.removeAll();
+	mapping_xml_pane.removeAll();
+	convert_xml_pane.removeAll();
+
+	convert_xml_pane1.add(convert_xml_checkbox1, BorderLayout.WEST);
+	convert_xml_pane1.add(convert_xml_field1, BorderLayout.CENTER);
+	convert_xml_pane1.add(convert_xml_button1, BorderLayout.EAST);
+
+	convert_xml_pane2.add(convert_xml_checkbox2, BorderLayout.WEST);
+	convert_xml_pane2.add(convert_xml_field2, BorderLayout.CENTER);
+	convert_xml_pane2.add(convert_xml_button2, BorderLayout.EAST);
+      
+	mapping_xml_pane.add(mapping_xml_checkbox, BorderLayout.WEST);
+	mapping_xml_pane.add(mapping_xml_field, BorderLayout.CENTER);
+	mapping_xml_pane.add(convert_xml_button3, BorderLayout.EAST);
+
+	convert_xml_pane.add(convert_xml_pane1);
+       	
+        String saveas = (String)saveas_combobox.getSelectedItem();
+	if (saveas.equals("MARCXML")){
+	    convert_xml_pane.add(mapping_xml_pane);
+            convert_xml_pane.add(output_single_checkbox); 
+	}
+        else{
+	    if (saveas.equals("METS")){
+		convert_xml_pane.add(convert_xml_pane2); 
+	    }
+	}
+	convert_xml_pane.revalidate();
+	convert_xml_pane.repaint();
+
+        // Save as pane
+	JPanel saveas_pane = new JPanel(new BorderLayout());
+	saveas_label.setBorder(BorderFactory.createEmptyBorder(0,5,0,15));
+	saveas_pane.add(saveas_label, BorderLayout.WEST);
+	saveas_pane.add(saveas_combobox, BorderLayout.CENTER);
+
+        JPanel tmp_pane = new JPanel(new BorderLayout());
+        tmp_pane.add(saveas_pane, BorderLayout.NORTH);
+	tmp_pane.add(title_pane, BorderLayout.CENTER);
+
+	instructions_pane.add(tmp_pane, BorderLayout.NORTH);          
+
+	instructions_pane.add(convert_xml_pane, BorderLayout.CENTER);
+
+	// Central pane
+	JPanel list_pane = new JPanel(new BorderLayout());
+	list_pane.add(list_label, BorderLayout.NORTH);
+	list_pane.add(new JScrollPane(list), BorderLayout.CENTER);
+	list_pane.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0));
+
+	JPanel details_pane = new JPanel(new BorderLayout());
+	details_pane.add(details_label, BorderLayout.NORTH);
+	details_pane.add(new JScrollPane(details_textarea), BorderLayout.CENTER);
+	details_pane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
+
+	JPanel central_pane = new JPanel(new GridLayout(2, 1));
+	central_pane.add(list_pane);
+	central_pane.add(details_pane);
+	central_pane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+
+	// Lower pane
+	JPanel button_pane = new JPanel(new GridLayout(1, 2));
+	button_pane.add(ok_button);
+	button_pane.add(cancel_button);
+	button_pane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
+
+	JPanel lower_pane = new JPanel(new BorderLayout());
+	lower_pane.add(button_pane, BorderLayout.SOUTH);
+	lower_pane.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
+
+	// Final.
+	JPanel content_pane = (JPanel)this.getContentPane();
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(instructions_pane, BorderLayout.NORTH);
+	content_pane.add(central_pane, BorderLayout.CENTER);
+	content_pane.add(lower_pane, BorderLayout.SOUTH);
+
+	// Center and display.
+	Dimension screen_size = Configuration.screen_size;
+	this.setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+	this.setVisible(true); // blocks until the dialog is killed
+	return true;
+	
+    }
+
+    
+    /** This method calls the builcol.pl scripts via a GShell so as to not lock up the processor.
+     * @see org.greenstone.gatherer.Configuration
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.collection.Collection
+     * @see org.greenstone.gatherer.gui.BuildOptions
+     * @see org.greenstone.gatherer.shell.GShell
+     * @see org.greenstone.gatherer.shell.GShellListener
+     * @see org.greenstone.gatherer.shell.GShellProgressMonitor
+     * @see org.greenstone.gatherer.util.Utility
+     */
+    public void exportAsCollections() {
+	DebugStream.println("ExportAsPrompt.exportAsCollections()");
+
+	int num_collections = selected_collections.size();
+	if (num_collections == 0) return;
+	cd_title = title_field.getText();
+
+	String export_type = (String) saveas_combobox.getSelectedItem();
+      
+	// Generate the export.pl command
+	ArrayList command_parts_list = new ArrayList();
+	if (Utility.isWindows() && (!Gatherer.isGsdlRemote)) {
+	    command_parts_list.add(Configuration.perl_path);
+	    command_parts_list.add("-S");
+	}
+	command_parts_list.add(LocalGreenstone.getBinScriptDirectoryPath() + "export.pl");
+	command_parts_list.add("-gli");
+	command_parts_list.add("-language");
+	command_parts_list.add(Configuration.getLanguage());
+	command_parts_list.add("-removeold");
+	command_parts_list.add("-saveas");
+	command_parts_list.add(export_type);
+	command_parts_list.add("-exportdir");
+	String export_dir = LocalGreenstone.getTmpDirectoryPath();
+       	if (cd_title.equals("")) {
+            export_dir += "exported_" + export_type;
+	}
+	else {
+	    File cd_file = new File(cd_title);
+            if (cd_file.isAbsolute())
+		export_dir = cd_title + File.separator + "exported_" + export_type;
+	    else{
+                cd_title = cd_title.replaceAll("\\s+","");
+                cd_title = cd_title.replaceAll("\\\\+","/");
+                cd_title = cd_title.replaceAll("/+","/");
+            	export_dir +=cd_title;
+	    }
+	}
+
+        command_parts_list.add(export_dir);
+
+        if (!export_type.equals("METS") && xsl_file1 !=null){
+             command_parts_list.add("-xsltfile");
+             command_parts_list.add(xsl_file1.getPath()); 
+	}
+
+	//add command specific to MARCXML 
+	if (export_type.equals("MARCXML")){
+	    //add default transformation file
+	    if (xsl_file1 == null){
+		command_parts_list.add("-xsltfile");	
+		command_parts_list.add(Configuration.gsdl_path+"etc"+File.separator+"dc2marc.xsl");
+	    }  
+
+	    command_parts_list.add("-mapping_file");
+	    //default mapping file
+	    if (mapping_file == null){
+		command_parts_list.add(Configuration.gsdl_path+"etc"+File.separator+"dc2marc-mapping.xml");
+	    }
+	    else{
+		command_parts_list.add(mapping_file.getPath());	
+	    }
+
+	    if (output_single_checkbox.isSelected()){
+		command_parts_list.add("-group_marc");
+	    }
+
+	}
+
+            
+        if (export_type.equals("METS") && xsl_file1 !=null){
+             command_parts_list.add("-xslt_txt");
+             command_parts_list.add(xsl_file1.getPath()); 
+	}
+
+         if (export_type.equals("METS") && xsl_file2 !=null){
+             command_parts_list.add("-xslt_mets");
+             command_parts_list.add(xsl_file2.getPath()); 
+	}
+       
+	for (int i = 0; i < num_collections; i++) {
+	    command_parts_list.add(((BasicCollectionConfiguration) selected_collections.get(i)).getShortName());
+	}
+
+	DebugStream.print("export command = ");
+	for (int i = 0; i < command_parts_list.size(); i++) {
+	    DebugStream.print(command_parts_list.get(i) + " ");
+	    //System.err.print(command_parts_list.get(i) + " ");          
+	}
+	DebugStream.println("");
+
+	// Run the export.pl command
+	String[] command_parts = (String[]) command_parts_list.toArray(new String[0]);
+
+        progress_monitor = new  GDefaultProgressMonitor();
+
+	GShell process = new GShell(command_parts, GShell.EXPORTAS, 3, this,progress_monitor , GShell.GSHELL_EXPORTAS);
+	process.start();
+	//process.run();
+	DebugStream.println("ExportAsPrompt.exportAsCollections().return");
+	
+    }
+
+
+    public void cancelExporting(){
+	progress_monitor.setStop(true);           
+    }
+
+
+    /** Shows an export complete prompt. 
+     * @param success A <strong>boolean</strong> indicating if the collection was successfully deleted.
+     * @see org.greenstone.gatherer.collection.Collection
+     */
+    public void resultPrompt(boolean success, String extra) {
+	args = new String[2];
+	StringBuffer coll_names = new StringBuffer();
+	for (int i=0; i<selected_collections.size();i++) {
+	    if (i>0) {
+		coll_names.append(", ");
+	    }
+	    BasicCollectionConfiguration complete_collection = (BasicCollectionConfiguration)selected_collections.get(i);
+	    coll_names.append(complete_collection.getName() + StaticStrings.SPACE_CHARACTER + StaticStrings.OPEN_PARENTHESIS_CHARACTER + complete_collection.getShortName() + StaticStrings.CLOSE_PARENTHESIS_CHARACTER);
+	    complete_collection = null;
+	}
+	
+	args[0] = coll_names.toString();
+	
+	String export_type = (String) saveas_combobox.getSelectedItem();       
+       	args[1] = LocalGreenstone.getTmpDirectoryPath();
+       	if (cd_title.equals("")) {
+           args[1] += "exported_" + export_type;
+	}
+	else {
+	    File cd_file = new File(cd_title);
+            if (cd_file.isAbsolute())
+		args[1] = cd_title + File.separator + "exported_" + export_type;
+	    else{
+                cd_title = cd_title.replaceAll("\\s+","");
+                cd_title = cd_title.replaceAll("\\\\+","/");
+                cd_title = cd_title.replaceAll("/+","/");
+            	args[1] +=cd_title;
+	    }
+	}
+        
+
+	String title;
+	String label;
+	String details;
+
+	if (success) {
+	    String successMessage
+		= (selected_collections.size()==1) 
+		? "ExportAsPrompt.Successful_ExportOne"
+		: "ExportAsPrompt.Successful_ExportMany";
+
+	    title = Dictionary.get("ExportAsPrompt.Successful_Title");
+	    label = Dictionary.get(successMessage, args);
+	    details = Dictionary.get("ExportAsPrompt.Successful_Details", args);
+	} else {
+	    String failedMessage
+		= (selected_collections.size()==1) 
+		? "ExportAsPrompt.Failed_ExportOne"
+		: "ExportAsPrompt.Failed_ExportMany";
+
+	    title = Dictionary.get("ExportAsPrompt.Failed_Title");
+	    label = Dictionary.get(failedMessage, args);
+	    details = Dictionary.get("ExportAsPrompt.Failed_Details", args);
+	}
+	SimpleResultDialog result_dialog = new SimpleResultDialog(title, label, details);
+	result_dialog.setVisible(true); // Blocks
+	result_dialog.dispose();
+	result_dialog = null;
+    }
+
+    /** Method to scan the collect directory retrieving and reloading each collection it finds, while building the list of known collections.
+     * @see org.greenstone.gatherer.Configuration
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.util.ArrayTools
+     * @see org.greenstone.gatherer.util.Utility
+     */
+    private void scanForCollections() {
+	// Start at the collect dir.
+	File collect_directory = new File(Gatherer.getCollectDirectoryPath());
+	if (collect_directory.exists()) {
+	    // Now for each child directory see if it contains a .col file and
+	    // if so try to load it..
+	    File collections[] = collect_directory.listFiles();
+	    ArrayTools.sort(collections);
+	    for(int i = 0; collections != null && i < collections.length; i++) {
+		if(collections[i].isDirectory() && !collections[i].getName().equals(StaticStrings.MODEL_COLLECTION_NAME)) {
+		    File config_file = new File(collections[i], Utility.CONFIG_FILE);
+		    if (config_file.exists()) {
+			BasicCollectionConfiguration config = new BasicCollectionConfiguration(config_file);
+			all_collections.add(config);		        
+			config = null;
+		    }
+		}
+	    }
+	}
+	// Otherwise the collect directory doesn't actually exist, so there ain't much we can do.
+    }
+
+
+    /** All implementation of GShellListener must include this method so the listener can be informed of messages from the GShell.
+     * @param event A <strong>GShellEvent</strong> that contains, amoung other things, the message.
+     */
+    public synchronized void message(GShellEvent event) {
+	// Ignore the messages from RecPlug with 'show_progress' set (used for progress bars)
+	String message = event.getMessage();
+	if (message.startsWith("export.pl>")) {
+	    message = message.substring(13);
+	    //DebugStream.println("message = "+event.getMessage());
+	    error_message.append(message);
+	    error_message.append("\n");
+	}
+    }
+
+    /** All implementation of GShellListener must include this method so the listener can be informed when a GShell begins its task. Implementation side-effect, not actually used.
+     * @param event A <strong>GShellEvent</strong> that contains details of the initial state of the <strong>GShell</strong> before task comencement.
+     */
+    public synchronized void processBegun(GShellEvent event) {
+	// We don't care. 
+    }
+    /** All implementation of GShellListener must include this method so the listener can be informed when a GShell completes its task.
+     * @param event A <strong>GShellEvent</strong> that contains details of the final state of the <strong>GShell</strong> after task completion.
+     */
+    public synchronized void processComplete(GShellEvent event) {
+	successful = false;
+	if(event.getStatus() == GShell.OK) {
+	    if(event.getType() == GShell.EXPORTAS) {
+		successful = true;
+	    }
+	}
+	ok_button_listener.processComplete();
+    }
+
+    /** A button listener implementation, which listens for actions on the close button and disposes of the dialog when detected. */
+    private class CancelButtonListener 
+	implements ActionListener {
+	/** Any implementation of ActionListener must include this method so we can be informed when the button is actioned.
+	 * @param event An <strong>ActionEvent</strong> containing all the relevant information garnered from the event itself.
+	 */
+	public void actionPerformed(ActionEvent event) {
+	    prompt.dispose();
+	}
+    }
+
+    /** This private class listens for selection events in from the list and then displays the appropriate details for that collection.
+     */
+    private class CollectionListListener 
+	implements ListSelectionListener
+    {
+	/** Any implementation of ListSelectionListener must include this method so we can be informed when the list selection changes.
+	 * @param  event a <strong>ListSelectionEvent</strong> containing all the relevant information garnered from the event itself
+	 */
+	public void valueChanged(ListSelectionEvent event)
+	{
+	    // Can only export when something is ticked
+	    ok_button.setEnabled(!list.isNothingTicked());
+
+	    if (list.isSelectionEmpty()) {
+		// This only happens when the dialog is first entered
+		details_textarea.setText(Dictionary.get("DeleteCollectionPrompt.No_Collection"));
+		return;
+	    }
+
+	    collection = (BasicCollectionConfiguration) ((CheckListEntry) list.getSelectedValue()).getObject();
+	    args = new String[3];
+	    args[0] = collection.getCreator();
+	    args[1] = collection.getMaintainer();
+	    args[2] = collection.getDescription();
+	    details_textarea.setText(Dictionary.get("DeleteCollectionPrompt.Details", args));
+	    details_textarea.setCaretPosition(0);
+	}
+    }
+
+
+    /** The OK button listener implementation. */
+    private class OKButtonListener 
+	implements ActionListener {
+	private Component glass_pane;
+	private MouseListener mouse_blocker_listener;
+	private ProgressDialog progress_dialog;
+
+	/** Any implementation of ActionListener must include this method so we can be informed when the button is actioned.
+	 * @param event An <strong>ActionEvent</strong> containing all the relevant information garnered from the event itself.
+	 * @see org.greenstone.gatherer.Configuration
+	 * @see org.greenstone.gatherer.Gatherer
+	 * @see org.greenstone.gatherer.util.Utility
+	 */
+	public void actionPerformed(ActionEvent event) {
+	    ///ystem.err.println("OK Clicked");
+	    // Make sure there are some colls specified
+	    selected_collections = list.getTicked();
+	    error_message = new StringBuffer();
+	    
+	    // Set the cursor to hourglass
+	    glass_pane = getGlassPane();
+	    mouse_blocker_listener = new MouseAdapter() {};
+	    glass_pane.addMouseListener(mouse_blocker_listener);
+	    glass_pane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+	    glass_pane.setVisible(true);
+
+	    // Export the selected collection.
+	    ///ystem.err.println("Exporting As for named collections");
+	    exportAsCollections();
+
+	    // Show progress dialog
+	    ///ystem.err.println("Showing progress dialog");
+	    progress_dialog = new ProgressDialog();
+	    progress_dialog.setVisible(true);
+	}
+
+	public void processComplete() {
+	    ///ystem.err.println("Process complete");
+	    // Dispose of progress dialog
+   
+	  
+	    progress_dialog.setVisible(false);
+	    progress_dialog.dispose();
+	    progress_dialog = null;
+
+	    // unset the cursor
+	    glass_pane.setVisible(false);
+	    glass_pane.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+	    glass_pane.removeMouseListener(mouse_blocker_listener);
+	    glass_pane = null;
+	    mouse_blocker_listener= null;
+	    
+	    if (successful) {
+		resultPrompt(true, error_message.toString());
+	    } else {
+		resultPrompt(false, error_message.toString());
+	    }
+	    error_message = null;
+             
+            convert_xml_button1.setEnabled(false); 
+            xsl_file1 = null;
+            convert_xml_field1.setText("");
+            convert_xml_checkbox1.setSelected(false);
+
+	    convert_xml_button2.setEnabled(false); 
+            xsl_file2 = null;
+            convert_xml_field2.setText("");
+            convert_xml_checkbox2.setSelected(false);
+
+	    mapping_xml_checkbox.setSelected(false);
+	    output_single_checkbox.setSelected(false);
+	    convert_xml_button3.setEnabled(false);
+            mapping_xml_field.setText("");
+	    mapping_file = null;
+
+	}
+
+	private class ProgressDialog 
+	    extends ModalDialog {
+	    
+	    private Dimension size = new Dimension(400,110);
+	    
+	    public ProgressDialog() {
+		super(Gatherer.g_man, Dictionary.get("ExportAsPrompt.Title"), true);
+		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
+		setSize(size);
+		JPanel content_pane = (JPanel) getContentPane();
+		JLabel progress_label = new JLabel(Dictionary.get("ExportAsPrompt.Progress_Label"));
+		
+		JProgressBar progress_bar = new JProgressBar();
+		progress_bar.setIndeterminate(true);
+		content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+		GLIButton cancel_button = new GLIButton(Dictionary.get("ExportAsPrompt.Cancel"),Dictionary.get("ExportAsPrompt.Cancel_Tooltip"));
+		cancel_button.setMnemonic(KeyEvent.VK_C);
+	
+		cancel_button.addActionListener(new ActionListener(){
+			public void actionPerformed(ActionEvent e){
+			    cancelExporting();
+			}
+
+                });
+
+                JPanel cancel_panel = new JPanel(new FlowLayout(FlowLayout.CENTER,0,0));
+		cancel_panel.add(cancel_button);
+                                    
+		content_pane.setLayout(new BorderLayout(0,5));
+		content_pane.add(progress_label, BorderLayout.NORTH);
+		content_pane.add(progress_bar, BorderLayout.CENTER);
+		content_pane.add(cancel_panel, BorderLayout.SOUTH);
+
+		// Position
+		Rectangle frame_bounds = Gatherer.g_man.getBounds();
+		setLocation(frame_bounds.x + (frame_bounds.width - size.width) / 2, frame_bounds.y + (frame_bounds.height - size.height) / 2);
+	    }
+	}
+    }
+
+   private class ConvertXMLCheckboxListener implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	  
+	    convert_xml_button1.setEnabled(convert_xml_checkbox1.isSelected());
+	    convert_xml_button2.setEnabled(convert_xml_checkbox2.isSelected());
+	    convert_xml_button3.setEnabled(mapping_xml_checkbox.isSelected());
+			
+	}
+    }
+
+
+     
+    private class SaveasListener implements ActionListener {
+    
+	public void actionPerformed(ActionEvent event) {
+		
+	    convert_xml_checkbox1.setSelected(false);
+	    convert_xml_checkbox2.setSelected(false);
+	    mapping_xml_checkbox.setSelected(false);
+	    output_single_checkbox.setSelected(false);
+
+	    convert_xml_button1.setEnabled(false);
+            convert_xml_button2.setEnabled(false);
+	    convert_xml_button3.setEnabled(false);
+
+            convert_xml_field1.setText("");
+	    convert_xml_field2.setText("");
+	    mapping_xml_field.setText("");
+	    
+	    String saveas = (String)saveas_combobox.getSelectedItem();
+
+	    if (convert_xml_pane.getComponentCount() > 1){
+		convert_xml_pane.remove(1);
+		if (convert_xml_pane.getComponentCount() > 1){
+		    convert_xml_pane.remove(1);
+		}
+	    }
+
+	    if (!saveas.equals("METS")){
+	
+		convert_xml_checkbox1.setText(Dictionary.get("ExportAsPrompt.ApplyXSL",(String)plugoutMap.get(saveas)));	
+		if (saveas.equals("MARCXML")){
+		    convert_xml_pane.add(mapping_xml_pane);
+		    convert_xml_pane.add(output_single_checkbox);
+		}		
+	    }
+	    else{
+		String[] docs = ((String)plugoutMap.get(saveas)).split(",");
+		convert_xml_checkbox1.setText(Dictionary.get("ExportAsPrompt.ApplyXSL",docs[0]));
+		convert_xml_checkbox2.setText(Dictionary.get("ExportAsPrompt.ApplyXSL",docs[1])); 
+		convert_xml_pane.add(convert_xml_pane2); 		
+	    }
+	    
+	    convert_xml_pane.revalidate();
+	    convert_xml_pane.repaint();
+            instructions_pane.revalidate();
+            instructions_pane.repaint();
+             
+	}
+	
+    }
+       
+     private class ConvertXMLButtonListener implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    JFileChooser chooser = new JFileChooser();
+	    // Note: source for ExampleFileFilter can be found in FileChooserDemo,
+	    // under the demo/jfc directory in the Java 2 SDK, Standard Edition.
+	    javax.swing.filechooser.FileFilter filter = new javax.swing.filechooser.FileFilter(){
+		    public boolean accept(File f){
+			return f.getPath().endsWith(".xsl")||f.isDirectory()||f.getPath().endsWith(".xml");
+		    }  
+
+		    public String getDescription(){
+			return "XSL or XML file";
+		    }          
+      };
+	    
+	    chooser.setFileFilter(filter);
+	    int returnVal = chooser.showOpenDialog(prompt);        
+
+	    if(returnVal == JFileChooser.APPROVE_OPTION) {
+		if (event.getSource() == convert_xml_button1){
+
+		    xsl_file1 = chooser.getSelectedFile();
+		    convert_xml_field1.setText(xsl_file1.getPath());
+		}
+                else if (event.getSource() == convert_xml_button2){ 
+                     xsl_file2 = chooser.getSelectedFile();
+		    convert_xml_field2.setText(xsl_file2.getPath());
+		   
+		}
+		else {
+		    mapping_file = chooser.getSelectedFile();
+		    mapping_xml_field.setText(mapping_file.getPath()); 
+		}
+	    }
+	}
+     }
+
+ private class FolderButtonListener implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    JFileChooser chooser = new JFileChooser();
+	    chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+	   
+	    int returnVal = chooser.showOpenDialog(prompt);        
+	    
+	    if(returnVal == JFileChooser.APPROVE_OPTION) {
+		File folder_name = chooser.getSelectedFile();
+		title_field.setText(folder_name.getPath());
+	    }
+	    
+	}
+ }
+}
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/FileAssociationDialog.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/FileAssociationDialog.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/FileAssociationDialog.java	(revision 13928)
@@ -0,0 +1,475 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.File;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.filechooser.*;
+import javax.swing.table.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.file.FileAssociationManager;
+import org.greenstone.gatherer.util.TableUtils;
+import org.greenstone.gatherer.util.Utility;
+
+/** The file association allows the entry of new file associations and the modification of existing ones.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class FileAssociationDialog
+    extends ModalDialog {
+
+    /** The default size for the dialog. */
+    static final private Dimension SIZE = new Dimension(600, 450);
+
+    private boolean ignore = false;
+    private FileAssociationDialog self;
+    private FileAssociationManager file_association_manager;
+    private JButton add_button;
+    private JButton browse_button;
+    private JButton close_button;
+    private JButton remove_button;
+    private JButton replace_button;
+    private JTable existing_associations_table;
+    private JTextField command_field;
+    private JTextField extension_field;
+
+    /** Create a new file association dialog.
+     * @param file_association_manager A reference to the <strong>FileAssociationManager</strong> so we can determine what extensions are already associated.
+     */
+    public FileAssociationDialog(FileAssociationManager file_association_manager) {
+	super(Gatherer.g_man);
+	this.file_association_manager = file_association_manager;
+	this.self = this;
+		  
+	// Creation
+	setModal(true);
+	setSize(SIZE);
+	setTitle(Dictionary.get("FileAssociationDialog.Title"));
+	setJMenuBar(new SimpleMenuBar("fileassociations"));
+
+	JPanel content_pane = (JPanel) getContentPane();
+	content_pane.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
+
+	JTextArea instructions_area = new JTextArea(Dictionary.get("FileAssociationDialog.Instructions"));
+	instructions_area.setEditable(false);
+	instructions_area.setLineWrap(true);
+	instructions_area.setRows(5);
+	instructions_area.setWrapStyleWord(true);
+	
+	JPanel control_pane = new JPanel();
+	existing_associations_table = new JTable(file_association_manager);
+	existing_associations_table.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
+	existing_associations_table.setColumnSelectionAllowed(false);
+	existing_associations_table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+	JPanel lower_pane = new JPanel();
+	JPanel details_pane = new JPanel();
+
+	JPanel extension_pane = new JPanel();
+	JLabel extension_label = new JLabel(Dictionary.get("FileAssociationDialog.Extension"));
+	extension_field = new NonWhitespaceField();
+	extension_field.setToolTipText(Dictionary.get("FileAssociationDialog.Extension_Tooltip"));
+
+	JLabel command_label = new JLabel(Dictionary.get("FileAssociationDialog.Command"));
+	JPanel command_pane = new JPanel();
+	command_field = new JTextField();
+	command_field.setToolTipText(Dictionary.get("FileAssociationDialog.Command_Tooltip"));
+	browse_button = new GLIButton(Dictionary.get("FileAssociationDialog.Browse"));
+	browse_button.setEnabled(!Utility.isMac());
+	if (Utility.isMac()) {
+	    browse_button.setToolTipText(Dictionary.get("FileAssociationDialog.Browse_Tooltip_Mac"));
+	} else {
+	    browse_button.setToolTipText(Dictionary.get("FileAssociationDialog.Browse_Tooltip"));
+	}
+
+
+	JPanel button_pane = new JPanel();
+	
+	add_button = new GLIButton(Dictionary.get("FileAssociationDialog.Add"), Dictionary.get("FileAssociationDialog.Add_Tooltip"));
+	add_button.setEnabled(false);
+	
+	replace_button = new GLIButton(Dictionary.get("FileAssociationDialog.Replace"), Dictionary.get("FileAssociationDialog.Replace_Tooltip"));
+	replace_button.setEnabled(false);
+	
+	remove_button = new GLIButton(Dictionary.get("FileAssociationDialog.Remove"), Dictionary.get("FileAssociationDialog.Remove_Tooltip"));
+	remove_button.setEnabled(false);
+	
+	close_button = new GLIButton(Dictionary.get("FileAssociationDialog.Close"), Dictionary.get("FileAssociationDialog.Close_Tooltip"));
+	
+	// Connection
+	add_button.addActionListener(new AddButtonListener());
+	browse_button.addActionListener(new BrowseButtonListener());
+	close_button.addActionListener(new CloseButtonListener());
+	remove_button.addActionListener(new RemoveButtonListener());
+	replace_button.addActionListener(new ReplaceButtonListener());
+	CommandOrExtensionFieldListener coefl = new CommandOrExtensionFieldListener();
+	command_field.getDocument().addDocumentListener(coefl);
+	extension_field.getDocument().addDocumentListener(coefl);
+	coefl = null;
+	existing_associations_table.getSelectionModel().addListSelectionListener(new ExistingAssociationsTableListener());
+
+	// Layout
+	extension_pane.setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
+	extension_pane.setLayout(new BorderLayout(5,0));
+	extension_pane.add(extension_label, BorderLayout.WEST);
+	extension_pane.add(extension_field, BorderLayout.CENTER);
+
+	command_pane.setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
+	command_pane.setLayout(new BorderLayout());
+	command_pane.add(command_field, BorderLayout.CENTER);
+	command_pane.add(browse_button, BorderLayout.EAST);
+
+	details_pane.setBorder(BorderFactory.createTitledBorder(Dictionary.get("FileAssociationDialog.Details")));
+	details_pane.setLayout(new GridLayout(3,1));
+	details_pane.add(extension_pane);
+	details_pane.add(command_label);
+	details_pane.add(command_pane);
+
+	lower_pane.setBorder(BorderFactory.createEmptyBorder(2,0,0,0));
+	button_pane.setLayout(new GridLayout(2,3));
+	button_pane.add(add_button);
+	button_pane.add(replace_button);
+	button_pane.add(remove_button);
+	button_pane.add(new JPanel());
+	button_pane.add(new JPanel());
+	button_pane.add(close_button);
+
+	lower_pane.setBorder(BorderFactory.createEmptyBorder(2,0,0,0));
+	lower_pane.setLayout(new BorderLayout());
+	lower_pane.add(details_pane, BorderLayout.CENTER);
+	lower_pane.add(button_pane, BorderLayout.SOUTH);
+
+	control_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	control_pane.setLayout(new BorderLayout());
+	control_pane.add(new JScrollPane(existing_associations_table), BorderLayout.CENTER);
+	control_pane.add(lower_pane, BorderLayout.SOUTH);
+
+	content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(new JScrollPane(instructions_area), BorderLayout.NORTH);
+	content_pane.add(control_pane, BorderLayout.CENTER);
+
+	Rectangle screen = Gatherer.g_man.getBounds(null);
+	setLocation((int)(screen.getX() + (screen.getWidth() - SIZE.width) / 2), (int)(screen.getY() + (screen.getHeight() - SIZE.height) / 2));
+	screen = null;
+    }
+
+    public void destroy() {
+	// Disconnect
+	// Clean up
+	file_association_manager = null;
+	self = null;
+    }
+
+    /** Redisplay the dialog, ensuring that the details (or lack thereof) for a certain extension is apparent. In fact if an extension is provided force the user to add it or cancel.
+     * @param new_extension The extension code as a <strong>String</strong>.
+     */
+    public String display(String new_extension) {
+	// Clear the current selection
+	existing_associations_table.clearSelection();
+	if(new_extension != null) {
+	    extension_field.setText(new_extension);
+	}
+	setVisible(true);
+	if(new_extension != null) {
+	    return file_association_manager.getCommandString(new_extension);
+	}
+	return null;
+    }
+
+    protected void processWindowEvent(WindowEvent event) {
+	if(event.getID() == WindowEvent.WINDOW_ACTIVATED) {
+	    TableUtils.fixColumnToPreferredWidth(existing_associations_table, 0); 
+	}
+	else {
+	    super.processWindowEvent(event);
+	}
+    }
+
+    private class AddButtonListener
+	implements ActionListener {
+	
+	public void actionPerformed(ActionEvent event) {
+	    String extension_str = extension_field.getText();
+	    file_association_manager.setCommand(extension_str, command_field.getText());
+	    // Select the appropriate entry in the table
+	    int index = -1;
+	    for(int i = 0; index == -1 && i < file_association_manager.size(); i++) {
+		if(file_association_manager.getExtension(i).equals(extension_str)) {
+		    index = i;
+		}
+	    }
+	    if(index > -1) {
+		existing_associations_table.setRowSelectionInterval(index, index);
+	    }
+	    // And update buttons
+	    add_button.setEnabled(false);
+	    remove_button.setEnabled(true);
+	}
+    }
+
+    /** Batch filter shows only files ending in bat. Based on ImageFilter.java which is a 1.4 example used by FileChooserDemo2.java. */
+    private class BatchFileFilter
+	extends FileFilter {
+
+	/** Accept all .exe files
+	 * @param file a File
+	 * @return true is this file should be shown, false otherwise
+	 */
+	public boolean accept(File file) {
+	    return file.getName().toLowerCase().endsWith(".bat");
+	}
+
+	/** The description of this filter
+	 * @return a String
+	 */
+	public String getDescription() {
+	    return Dictionary.get("FileAssociationDialog.Batch_File");
+	}
+    }
+
+    /** Whenever the user clicks the browse button, we should open up a file browser to allow them to select an executable file from somewhere in the file system. */
+    private class BrowseButtonListener 
+	implements ActionListener {
+	/** Open up a simple JFileChooser when the user clicks the button. 
+	 * @param event An <strong>ActionEvent</strong> containing information about the event.
+	 */
+	public void actionPerformed(ActionEvent event) {
+	    JFileChooser chooser = new JFileChooser(new File(Gatherer.getGLIUserDirectoryPath()));
+	    GUIUtils.disableRename(chooser);
+	    chooser.setDialogTitle(Dictionary.get("FileAssociationDialog.Browse_Title"));
+	    chooser.setFileFilter(new BatchFileFilter());
+	    chooser.setFileFilter(new CoreObjectModelFileFilter());
+	    chooser.setFileFilter(new ExecutableFileFilter());
+	    chooser.setAcceptAllFileFilterUsed(true);
+	    if(chooser.showOpenDialog(Gatherer.g_man) == JFileChooser.APPROVE_OPTION) {
+		command_field.setText(chooser.getSelectedFile().getAbsolutePath());
+	    }
+	}
+    }
+
+    private class CloseButtonListener
+	implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    existing_associations_table.clearSelection();
+	    add_button.setEnabled(false);
+	    remove_button.setEnabled(false);
+	    replace_button.setEnabled(false);
+	    self.dispose();
+	}
+    }
+
+    /** Command filter shows only files ending in com. Based on ImageFilter.java which is a 1.4 example used by FileChooserDemo2.java. */
+    private class CoreObjectModelFileFilter
+	extends FileFilter {
+
+	/** Accept all .exe files
+	 * @param file a File
+	 * @return true is this file should be shown, false otherwise
+	 */
+	public boolean accept(File file) {
+	    return file.getName().toLowerCase().endsWith(".com");
+	}
+
+	/** The description of this filter
+	 * @return a String
+	 */
+	public String getDescription() {
+	    return Dictionary.get("FileAssociationDialog.Command_File");
+	}
+    }
+
+    private class CommandOrExtensionFieldListener
+	implements DocumentListener {
+	/** Gives notification that an attribute or set of attributes changed. */
+	public void changedUpdate(DocumentEvent e) {
+	    changed();
+	}
+	/** Gives notification that there was an insert into the document. */
+	public void insertUpdate(DocumentEvent e) {
+	    changed();
+	}
+	/** Gives notification that a portion of the document has been removed. */
+	public void removeUpdate(DocumentEvent e) {
+	    changed();
+	} 
+
+	private void changed() {
+	    ignore = true;
+	    String extension_str = extension_field.getText();
+	    String command_str = command_field.getText();
+	    // Determine if there is currently an association selected
+	    int selected_index = -1;
+	    if((selected_index = existing_associations_table.getSelectionModel().getMinSelectionIndex()) != -1) {
+		String current_extension_str = file_association_manager.getExtension(selected_index);
+		String current_command_str = file_association_manager.getCommandString(current_extension_str);
+		// What buttons are enabled depends a lot on the file extension, taken to be the 'key'
+		if(extension_str.equals(current_extension_str)) {
+		    // If the extensions are the same then remove is enabled
+		    remove_button.setEnabled(true);
+		    // But if the command is different, then enable replace
+		    if(current_command_str.length() == 0) {
+			add_button.setEnabled(true);
+			replace_button.setEnabled(false);
+		    }
+		    else if(!command_str.equals(current_command_str)) {
+			add_button.setEnabled(false);
+			replace_button.setEnabled(true);
+		    }
+		    else {
+			add_button.setEnabled(false);
+			replace_button.setEnabled(false);
+		    }
+		}
+		// We can add it, but we first clear the selection
+		else {
+		    existing_associations_table.clearSelection();
+		    add_button.setEnabled(true);
+		    remove_button.setEnabled(false);
+		    replace_button.setEnabled(false);
+		}
+	    }
+	    // If not, we must first test if the extension is in use
+	    else {
+		int index = -1;
+		for(int i = 0; index == -1 && i < file_association_manager.size(); i++) {
+		    String existing_extension_str = file_association_manager.getExtension(i);
+		    if(existing_extension_str.equals(extension_str)) {
+			index = i;
+		    }
+		}
+		if(index != -1) {
+		    // Selection that index
+		    existing_associations_table.setRowSelectionInterval(index, index);
+		    // Set replace and remove enabled
+		    add_button.setEnabled(false);
+		    remove_button.setEnabled(true);
+		    replace_button.setEnabled(true);
+		}
+		// Otherwise if there is some text in both extension and command, enable add only
+		else if(extension_str.length() > 0 && command_str.length() > 0) {
+		    add_button.setEnabled(true);
+		    remove_button.setEnabled(false);
+		    replace_button.setEnabled(false);
+		}
+		// Otherwise disable everything
+		else {
+		    add_button.setEnabled(false);
+		    remove_button.setEnabled(false);
+		    replace_button.setEnabled(false);
+		}
+	    }
+	    ignore = false;
+	}
+    }
+
+    /** Executable filter shows only files ending in exe. Based on ImageFilter.java which is a 1.4 example used by FileChooserDemo2.java. */
+    private class ExecutableFileFilter
+	extends FileFilter {
+
+	/** Accept all .exe files
+	 * @param file a File
+	 * @return true is this file should be shown, false otherwise
+	 */
+	public boolean accept(File file) {
+	    return file.getName().toLowerCase().endsWith(".exe");
+	}
+
+	/** The description of this filter
+	 * @return a String
+	 */
+	public String getDescription() {
+	    return Dictionary.get("FileAssociationDialog.Executable_File");
+	}
+    }
+
+    private class ExistingAssociationsTableListener
+	implements ListSelectionListener {
+
+	public void valueChanged(ListSelectionEvent event) {
+	    if(!event.getValueIsAdjusting() && !ignore) {
+		int selected_index = -1;
+		if((selected_index = existing_associations_table.getSelectionModel().getMinSelectionIndex()) != -1) {
+		    // Propagate the details of the selection down into the fields
+		    String extension_str = file_association_manager.getExtension(selected_index);
+		    extension_field.setText(extension_str);
+		    command_field.setText(file_association_manager.getCommandString(extension_str));
+		    extension_str = null;
+		    remove_button.setEnabled(true);
+		}
+		else {
+		    // Clear the fields
+		    extension_field.setText("");
+		    command_field.setText("");
+		    remove_button.setEnabled(false);
+		}
+		add_button.setEnabled(false);
+		replace_button.setEnabled(false);
+	    }
+	}
+    }
+
+    private class RemoveButtonListener 
+	implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    file_association_manager.setCommand(extension_field.getText(), null);
+	    // And update buttons
+	    add_button.setEnabled(true);
+	    remove_button.setEnabled(false);
+	}
+    }
+
+    private class ReplaceButtonListener 
+	implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    file_association_manager.setCommand(extension_field.getText(), command_field.getText());
+	    // And update buttons
+	    replace_button.setEnabled(false);
+	}
+    }
+}
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/Filter.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/Filter.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/Filter.java	(revision 13928)
@@ -0,0 +1,323 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import java.util.regex.*;
+import javax.swing.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.file.FileSystemModel;
+import org.greenstone.gatherer.gui.tree.DragTree;
+
+/** <p>This object allows the user to set a filter on one of the workspace trees, specifying a preset type, or a regular expression that a files must match to be in the tree. Note that all directories are included. This class includes the controls for editing the filter. The trick is that several instances of the Filter class can share the same internal data (termed a 'run' of filters), so that the filter set on the GatherPane and the EnrichPane are virtually the same.</p>
+ * <p>The regular expression typed uses '*' as a wildcard character (equivalent to '.*'), and does not use '.' to match any single character (use '?' instead).</p>
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class Filter
+    extends JPanel {
+    /** The other filters in this run of filters, used to ensure they all show the same thing. */
+    private ArrayList others = null;
+    /** Is this the first filter of this run of filters created (later filters will share the same information). */
+    private boolean first = true;
+    /** Prevent any changes we make in the class from causing events which we then process causing events... */
+    private boolean ignore = false;
+    /** A reference to ourselves so inner classes can refer to us. */
+    private Filter this_filter = null;
+    /** The check box to enable/disable filter. */
+    private JCheckBox checkbox = null;
+    /** The editable combobox where you either choose a predefined filter, or type a new pseudo-regular expression. */
+    private GComboBox combobox = null;
+    /** The label shown on the filter controls. */
+    private JLabel label = null;
+    /** A reference to the tree this filter is being applied to. */
+    private DragTree tree = null;
+    /** The default size for the label. */
+    static final private Dimension SIZE = new Dimension(100,30);
+    /** Preprogrammed default filters. */
+    static final private String DEFAULTS[] = {"^.*\\.html?$", "^.*\\.xml$", "^.*\\.txt$", "(^.*\\.jpe?g$)|(^.*\\.png$)|(^.*\\.gif$)|(^.*\\.bmp$)|(^.*\\.tiff?$)"};
+
+    /** Constructor.
+     * @param tree A reference to the <strong>JTree</strong> being affected.
+     */
+    public Filter(DragTree tree) {
+	this(tree, null);
+    }
+
+    /** Constructor.
+     * @param tree A reference to the <strong>JTree</strong> being affected.
+     * @param others An <strong>ArrayList</strong> of the other Filters already in this run.
+     */
+    public Filter(DragTree tree, ArrayList others) {
+	super();
+	if (others == null) {
+	    others = new ArrayList();
+	}
+	this.others = others;
+	this.others.add(this);
+	this.this_filter = this;
+	this.tree = tree;
+	// Create components.
+	combobox = new GComboBox(true);
+	try {
+	    combobox.add(new Entry());
+	}
+	catch (Exception error) {
+	    error.printStackTrace();
+	}
+	for(int i = 0; i < DEFAULTS.length; i++) {
+	    try {
+		Entry entry = new Entry(Dictionary.get("Filter." + i), Pattern.compile(DEFAULTS[i]));
+		combobox.add(entry);
+	    }
+	    catch (Exception error) {
+		error.printStackTrace();
+	    }
+	}
+	label = new JLabel(Dictionary.get("Filter.Filter_Tree"));
+	combobox.setToolTipText(Dictionary.get("Collection.Filter_Tooltip"));
+	
+	// Add listeners.
+	combobox.addActionListener(new ComboBoxListener());
+	// Layout.
+	label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
+
+	setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
+	setLayout(new BorderLayout());
+	add(label, BorderLayout.WEST);
+	add(combobox, BorderLayout.CENTER);
+    }
+
+    /** Used to restore the filter state to enabled, the normal state during collection editing.
+     * @param state The new state for the filter. <i>true</i> for enabled, <i>false</i> otherwise.
+     */
+    public void setEnabled(boolean state) {
+	ignore = true;
+	combobox.setEnabled(state);
+	ignore = false;
+    }
+
+    /** Set the combobox model for this filter.
+     * @param model The new <strong>ComboBoxModel</strong> to use.
+     */
+    public void setComboBoxModel(ComboBoxModel model) {
+	combobox.setModel(model);
+    }
+
+    /** Ensure that a certain entry is selected from the combobox.
+     * @param selection The <strong>Entry</strong> that should be selected.
+     */
+    public void setComboBoxSelection(Entry selection) {
+	ignore = true;
+	combobox.setSelectedItem(selection);
+	ignore = false;
+    }
+
+    /** Sets whether this combobox is editable or not
+     * @param value true to make the control editable, false otherwise
+     */
+    public void setEditable(boolean value) {
+	combobox.setEditable(value);	    
+    }
+
+    /** Set to signify that this filter is the first in a new run of filters.
+     * @param first <i>true</i> if this is the first filter in a run, <i>false</i> if it will just be added to the current run.
+     */
+    public void setFirst(boolean first) {
+	this.first = first;
+    }
+
+    /** Encode an expression in pseudo-regular expression into regular expression.
+     * @param raw The pseudo-regular expression <strong>String</strong> which includes several characters which differ in meaning from regular expression queries.
+     * @return A proper regular expression as a <strong>String</strong>.
+     */
+    private String encode(String raw) {
+	StringBuffer working = new StringBuffer();
+	for(int i = 0; i < raw.length(); i++) {
+	    char c = raw.charAt(i);
+	    switch(c) {
+	    case '.':
+		working.append("\\.");
+		break;
+	    case '*':
+		working.append(".*");
+		break;
+	    case '?':
+		working.append(".");
+		break;
+	    default:
+		working.append(Character.toLowerCase(c));
+	    }
+	}
+	return working.toString();
+    }
+    /** This method applies the given pattern to the tree registered as belonging to this filter.*/
+    private void setFilter(Pattern pattern) {
+	// Show busy cursor.
+	Gatherer.g_man.wait(true);
+	FileSystemModel model = (FileSystemModel) tree.getModel();
+	// Apply filter
+	if(pattern != null) {
+	    model.setFilter(pattern.pattern());
+	}
+	else {
+	    model.setFilter(null);
+	}
+	// Ask tree to completely refresh
+	tree.refresh(null);
+	// Restore cursor
+	Gatherer.g_man.wait(false);
+    }
+
+    /** Listens for changes in the combobox as when one is detected attempts to compile a regular expression from whatever text was entered. If successful, or if the item chosen was a predefined filter, it then applies the filter to the target tree. */
+    private class ComboBoxListener
+	implements ActionListener {
+	/** Called when a new item is selected from the filter combobox, we treat the new entry as a pseudo-regular expression, compile it and then apply it to the tree.
+	 * @param event An <strong>ActionEvent</strong> containing more information about the change performed.
+	 * @see org.greenstone.gatherer.gui.Filter.Entry
+	 */
+	public void actionPerformed(ActionEvent event) {
+	    try {
+		Object temp = combobox.getSelectedItem();
+		Entry entry = null;
+		if(temp instanceof String) {
+		    String temp_str = (String) temp;
+		    ///ystem.err.println("Filter = " + temp_str);
+
+		    // Ignore any string which matches a predefined filter
+		    if(temp_str.equals(Dictionary.get("Filter.All_Files"))) {
+		    }
+		    // HTM & HTML
+		    else if(temp_str.equals(Dictionary.get("Filter.0"))) {
+		    }
+		    // XML
+		    else if(temp_str.equals(Dictionary.get("Filter.1"))) {
+		    }
+		    // Text files
+		    else if(temp_str.equals(Dictionary.get("Filter.2"))) {
+		    }
+		    // Images
+		    else if(temp_str.equals(Dictionary.get("Filter.3"))) {
+		    }
+		    else {
+			// Make sure the filter isn't already in the list
+			boolean already_exists = false;
+			for (int i = 0; i < combobox.getItemCount(); i++) {
+			    if (temp_str.equals(combobox.getItemAt(i).toString())) {
+				already_exists = true;
+				entry = (Entry) combobox.getItemAt(i);
+				break;
+			    }
+			}
+
+			if (already_exists == false) {
+			    entry = new Entry(temp_str, Pattern.compile(encode(temp_str)));
+			    int position = combobox.getItemCount();
+			    combobox.insertItemAt(entry, position);
+			    combobox.setSelectedIndex(position);
+			}
+		    }
+		}
+		else {
+		    ///ystem.err.println("Custom Filter");
+		    entry = (Entry) temp;
+		}
+		if(entry != null) {
+		    setFilter(entry.getPattern());
+		}
+		// Else we ignore this event as being one of the painfully erroneous events we receive because we've been silly enough to have an editable combobox.
+	    }
+	    catch (PatternSyntaxException error) {
+		if(first) {
+		    JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("Filter.Invalid_Pattern"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
+		}
+	    }
+	}
+    }
+    /** An object that holds a filter entry. This is string used for the filter pattern and, if not custom built, its name. */
+    private class Entry
+	implements Comparable {
+	/** The compiled pattern created from a regular expression. */
+	private Pattern pattern = null;
+	/** The name of this filter entry. */
+	private String name = null;
+	/** Constructor. */
+	public Entry() {
+	}
+	/** Constructor.
+	 * @param name The name of this entry as a <strong>String</strong>.
+	 * @param pattern The compiled regular expression as a <strong>Pattern</strong>.
+	 */
+	public Entry(String name, Pattern pattern) {
+	    this.name = name;
+	    this.pattern = pattern;
+	}
+	/** Compare two Entrys for ordering.
+	 * @param object The other Entry to compare to, as an <strong>Object</strong>.
+	 * @return An <i>int</i> indicating the respective ordering, as defined in java.lang.String#compareTo
+	 */
+	public int compareTo(Object object) {
+	    return toString().compareTo(object.toString());
+	}
+	/** Retrieve the pattern associated with this entry.
+	 * @return The <strong>Pattern</strong>.
+	 */
+	public Pattern getPattern() {
+	    return pattern;
+	}
+	/** Translate this entry into a textual representation.
+	 * @return A <strong>String</strong> containing the representation.
+	 */
+	public String toString() {
+	    String result = null;
+	    if (name != null) {
+		result = name;
+	    }
+	    else if (pattern == null) {
+		result = Dictionary.get("Filter.All_Files");
+	    }
+	    else {
+		result = pattern.pattern();
+	    }
+	    return result;
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/FormatPane.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/FormatPane.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/FormatPane.java	(revision 13928)
@@ -0,0 +1,206 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.CollectionDesignManager;
+import org.greenstone.gatherer.cdm.FormatManager;
+import org.greenstone.gatherer.cdm.Format;
+import org.greenstone.gatherer.cdm.Control;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.shell.GShell;
+import org.greenstone.gatherer.shell.GShellEvent;
+import org.greenstone.gatherer.shell.GShellListener;
+
+public class FormatPane 
+    extends BaseConfigPane 
+    implements PreviewButtonOwner,GShellListener{
+    
+
+    /** The button for viewing the collection. */
+    private PreviewButton preview_button = null;
+    private boolean buildCanceled = false;
+
+    /** The constructor. */
+    public FormatPane() {
+	super();
+	if (Gatherer.GS3) {
+	    contents = new String []{ "CDM.GUI.General", "CDM.GUI.SearchMetadata", "CDM.GUI.Formats", "CDM.GUI.Translation" };
+	} else {
+	    contents = new String []{ "CDM.GUI.General", "CDM.GUI.SearchMetadata", "CDM.GUI.Formats", "CDM.GUI.Translation", "CDM.GUI.SuperCollection","CDM.GUI.Macros" };
+	}
+	JPanel side_panel = new JPanel();
+	side_panel.setLayout(new BorderLayout());
+	remove(tree_pane);
+	side_panel.add(tree_pane, BorderLayout.CENTER);
+	JPanel preview_pane = new JPanel();
+	preview_pane.setLayout(new BorderLayout());
+	preview_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+
+	preview_button = new PreviewButton(Dictionary.get("CreatePane.Preview_Collection"), Dictionary.get("CreatePane.Preview_Collection_Tooltip"));
+	preview_button.setEnabled(true);
+	preview_button.setVariablePreview(true);
+	preview_button.setOwner(this);
+	preview_pane.add(preview_button, BorderLayout.CENTER);
+
+
+	preview_button.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent event) {
+ 		    if (view != null) {
+ 			view.loseFocus();
+		    }
+	        
+		    if (buildCanceled){
+			WarningDialog dialog = new WarningDialog("warning.ShowPreviousCollection", Dictionary.get("ShowPreviousCollection.Title"), Dictionary.get("ShowPreviousCollection.Message"), null, false);
+			dialog.display();
+                        dialog.dispose();
+		    }
+		}
+
+	    });
+	side_panel.add(preview_pane, BorderLayout.SOUTH);
+
+	add(side_panel, BorderLayout.WEST);
+    }
+
+    public void gainFocus(){
+
+  	if (Gatherer.c_man.built() && Configuration.library_url != null) {
+	    preview_button.setEnabled(true);
+	}  
+	else{
+	    preview_button.setEnabled(false); 
+	}    
+	
+    }
+
+
+    /** All implementation of GShellListener must include this method so the listener can be informed of messages from the GShell.
+     * @param event A <strong>GShellEvent</strong> that contains, amoung other things, the message.
+     */
+    public synchronized void message(GShellEvent event) {
+        // We don't care.  
+    }
+
+    
+    /** All implementation of GShellListener must include this method so the listener can be informed when a GShell begins its task. Implementation side-effect, not actually used.
+     * @param event A <strong>GShellEvent</strong> that contains details of the initial state of the <strong>GShell</strong> before task comencement.
+     */
+    public synchronized void processBegun(GShellEvent event) {
+	buildCanceled = false;
+    }
+    
+    /** All implementation of GShellListener must include this method so the listener can be informed when a GShell completes its task.
+     * @param event A <strong>GShellEvent</strong> that contains details of the final state of the <strong>GShell</strong> after task completion.
+     */
+    public synchronized void processComplete(GShellEvent event) {
+	if(event.getStatus() == GShell.OK) {
+	    if(event.getType() == GShell.BUILD) {
+	        buildCanceled = false;
+	    }
+	}	   
+	else {
+	    buildCanceled = true;   
+	}
+    }
+
+
+
+    protected Control getSubControls(String type) {
+	if(type.equals("CDM.GUI.General")) {
+	    return CollectionDesignManager.general_manager.getControls();
+	}
+	if (type.equals("CDM.GUI.SearchMetadata")) {
+	    return CollectionDesignManager.searchmetadata_manager.getControls();
+	}
+	if(type.equals("CDM.GUI.Formats")) {
+	    return CollectionDesignManager.format_manager.getControls();
+	}
+	if (type.equals("CDM.GUI.Translation")) {
+	    return CollectionDesignManager.translation_manager.getControls();
+	}
+	if (type.equals("CDM.GUI.Macros")) {
+	    return CollectionDesignManager.macros_manager.getControls();
+	}
+	if(type.equals("CDM.GUI.SuperCollection")) {
+	    return CollectionDesignManager.supercollection_manager.getControls();
+	}
+	return null;
+    }
+
+    private int page_type = PreviewButton.HOME_PAGE;
+    private String page_params = "";
+    public int getPageType() {
+	System.err.println("view type = "+view_type);
+	if (view_type.equals("CDM.GUI.General") || view_type.equals("CDM.GUI.Translation")) {
+	    page_type = PreviewButton.HOME_PAGE;
+	} else {
+	    Format current_format = ((FormatManager.FormatControl)view).getCurrentFormat();
+	    String feature_name = current_format.getFeatureName();
+	    System.err.println("current format = "+feature_name);
+	    if (feature_name.equals("")) {
+		// must be modifying VList or HList
+		// what should we do???
+		page_type = PreviewButton.CLASSIFIER_PAGE;
+		page_params = "CL1";
+	    }
+	    if (feature_name.startsWith("CL")) {
+		page_type = PreviewButton.CLASSIFIER_PAGE;
+		page_params = current_format.getFeatureName();
+	    }
+	    else if (feature_name.startsWith("Document")) {
+		page_type = PreviewButton.DOCUMENT_PAGE;
+		page_params = "HASH01e4da6100fdbb11b7ef244b";
+	    } 
+	    else if (feature_name.equals("Search")) {
+		page_type = PreviewButton.SEARCH_PAGE;
+		page_params = "the";
+	    }
+	}
+	return page_type;
+    }
+
+    public String getPageParams() {
+	return page_params;
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/GComboBox.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/GComboBox.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/GComboBox.java	(revision 13928)
@@ -0,0 +1,385 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.plaf.basic.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.util.Utility;
+
+/**
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class GComboBox
+    extends JComboBox {
+
+    private Color background = null;
+    private Color foreground = null;
+    private Color editable_background = null;
+    private Color editable_foreground = null;
+    private Color selection_background = null;
+    private Color selection_foreground = null;
+
+    private boolean sort_objects = true;
+
+    public GComboBox() {
+	super();
+	init();
+	setOpaque(!Utility.isMac());
+    }
+
+    public GComboBox(boolean editable) {
+	super();
+	setOpaque(!Utility.isMac());
+	setEditable(editable);
+	init();
+
+    }
+
+    public GComboBox(ArrayList data) {
+	super(data.toArray());
+	setOpaque(!Utility.isMac());
+	init();
+    }
+
+    public GComboBox(ArrayList data, boolean editable) {
+	super(data.toArray());
+	setOpaque(!Utility.isMac());
+	setEditable(editable);
+	init();
+    }
+
+    public GComboBox(ArrayList data, boolean editable, boolean sorted) {
+	super(data.toArray());
+	setOpaque(!Utility.isMac());
+	setEditable(editable);
+	setSorted(sorted);
+	init();
+    }
+
+    public GComboBox(ComboBoxModel model) {
+	super(model);
+	setOpaque(!Utility.isMac());
+	init();
+    }
+
+    public GComboBox(ComboBoxModel model, boolean editable) {
+	super(model);
+	setOpaque(!Utility.isMac());
+	setEditable(editable);
+	init();
+    }
+
+    public GComboBox(Object data[]) {
+	super(data);
+	setOpaque(!Utility.isMac());
+	init();
+    }
+
+    public GComboBox(Object data[], boolean editable) {
+	super(data);
+	setOpaque(!Utility.isMac());
+	setEditable(editable);
+	init();
+    }
+
+    public GComboBox(Object data[], boolean editable, boolean sorted) {
+	super(data);
+	setOpaque(!Utility.isMac());
+	setEditable(editable);
+	setSorted(sorted);
+	init();
+    }
+
+    public GComboBox(Vector data) {
+	super(data);
+	setOpaque(!Utility.isMac());
+	init();
+    }
+
+    public GComboBox(Vector data, boolean editable) {
+	super(data);
+	setOpaque(!Utility.isMac());
+	setEditable(editable);
+	init();
+    }
+
+    public void setSorted(boolean sort) {
+	sort_objects = sort;
+    }
+    public int add(Object object) {
+	if (dataModel instanceof Model) {
+	    return ((Model) dataModel).add(object);
+	}
+	else {
+	    return -1;
+	}
+    }
+
+    public Object get(int index) {
+	return dataModel.getElementAt(index);
+    }
+
+    public void clear() {
+	if (dataModel instanceof Model) {
+	    ((Model) dataModel).clear();
+	}
+    }
+
+    public void init() {
+	Model model = new Model();
+	ComboBoxModel old_model = (ComboBoxModel) getModel();
+	setModel(model);
+	setOpaque(true);
+
+	// Restore any data given into our model
+	for(int i = 0; i < old_model.getSize(); i++) {
+	    model.add(old_model.getElementAt(i));
+	}
+
+	// Change component
+	UI ui = new UI();
+	setUI(ui);
+	ui.setButtonBackground();
+
+	// Initialization
+	this.background = Configuration.getColor("coloring.collection_tree_background", false);
+	this.foreground = Configuration.getColor("coloring.collection_tree_foreground", false);
+	this.editable_background = Configuration.getColor("coloring.editable_background", false);
+	this.editable_foreground = Configuration.getColor("coloring.editable_foreground", false);
+	this.selection_background = Configuration.getColor("coloring.collection_selection_background", false);
+	this.selection_foreground = Configuration.getColor("coloring.collection_selection_foreground", false);
+	if (isEditable()) {
+	    this.setBackground(editable_background);
+	    this.setForeground(editable_foreground);
+	}
+	else {
+	    this.setBackground(background);
+	    this.setForeground(foreground);
+	}
+	setBorder(BorderFactory.createLoweredBevelBorder());
+	setRenderer(new Renderer());
+    }
+
+    /** Overridden to do nothing. 
+     * @param background
+     */
+    public void setBackground(Color background) {
+    }
+
+    public void setBackgroundEditableColor(Color editable_background) {
+	this.editable_background = editable_background;
+    }
+
+    public void setBackgroundNonSelectionColor(Color background) {
+	this.background = background;
+    }
+
+    public void setBackgroundSelectionColor(Color selection_background) {
+	this.selection_background = selection_background;
+    }
+
+    public void setEditable(boolean editable) {
+	setEditor(new Editor());
+	super.setEditable(editable);
+	if (isEditable()) {
+	    this.setBackground(editable_background);
+	    this.setForeground(editable_foreground);
+	}
+	else {
+	    this.setBackground(background);
+	    this.setForeground(foreground);
+	}
+    }
+
+    public void setTextEditableColor(Color editable_foreground) {
+	this.editable_foreground = editable_foreground;
+    }
+
+    public void setTextNonSelectionColor(Color foreground) {
+	this.foreground = foreground;
+    }
+
+    public void setTextSelectionColor(Color selection_foreground) {
+	this.selection_foreground = selection_foreground;
+    }
+
+
+    private class Editor
+	extends JTextField
+	implements ComboBoxEditor {
+	public Editor() {
+	    setOpaque(true);
+	    if (isEditable()) {
+		setBackground(editable_background);
+		setForeground(editable_foreground);
+	    }
+	    else {
+		setBackground(background);
+		setForeground(foreground);
+	    }
+	    setSelectionColor(selection_background);
+	    setSelectedTextColor(selection_foreground);
+	}
+
+	public Component getEditorComponent() {
+	    return this;
+	}
+
+	public Object getItem() {
+	    return getText();
+	}
+
+	public void setItem(Object item) {
+	    if(item != null) {
+		setText(item.toString());
+	    }
+	    else {
+		setText("");
+	    }
+	}
+    }
+
+    private class Model
+	extends DefaultComboBoxModel {
+	
+	
+	public int add(Object extension) {
+	    int position = 0;
+	    String extension_str = extension.toString().toLowerCase();
+	    while(extension != null && position < getSize()) {
+		String sibling = getElementAt(position).toString().toLowerCase();
+		int order = extension_str.compareTo(sibling);
+		// If we are now less than the sibling, insert here.
+		if(sort_objects && order < 0) {
+		    insertElementAt(extension, position);
+		    extension = null;
+		}
+		// We are equal to the sibling, thus we already exist in list. Done.
+		else if(order == 0) {
+		    extension = null;
+		}
+		// Continue searching.
+		else {
+		    position++;
+		}
+	    }
+	    if(extension != null) {
+		position = getSize();
+		addElement(extension);
+	    }
+	    return position;
+	}
+
+	public void clear() {
+	    removeAllElements();
+	}
+    }
+
+    private class Renderer
+	extends JLabel
+	implements ListCellRenderer {
+	public Renderer() {
+	    super("");
+	    this.setOpaque(true);
+	}
+	public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+	    if(value != null) {
+		this.setText(value.toString());
+	    }
+	    else {
+		this.setText("");
+	    }
+	    if(isSelected) {
+		this.setBackground(selection_background);
+		this.setForeground(selection_foreground);
+	    }
+	    else if (isEditable()) {
+		this.setBackground(editable_background);
+		this.setForeground(editable_foreground);
+	    }
+	    else {
+		this.setBackground(background);
+		this.setForeground(foreground);
+	    }
+	    return this;
+	}
+    }
+
+    private class UI
+	extends BasicComboBoxUI {
+	public UI() {
+	    super();
+	}
+
+	protected ComboPopup createPopup() {
+	    BasicComboPopup popup = new BasicComboPopup(comboBox);
+	    // ---- I don't know why this code is here... maybe it is needed for the Mac? ----
+// 	    {
+// 		    public void show() {
+// 			if(comboBox.getMaximumRowCount() > 0) {
+// 			    Dimension popupSize = new Dimension( comboBox.getWidth(), getPopupHeightForRowCount( comboBox.getMaximumRowCount()));
+// 			    Rectangle popupBounds = new Rectangle( 0, 0, popupSize.width, popupSize.height);
+// 			    scroller.setMaximumSize( popupBounds.getSize() );
+// 			    scroller.setPreferredSize( popupBounds.getSize() );
+// 			    scroller.setMinimumSize( popupBounds.getSize() );
+// 			    list.invalidate();
+// 			    int selectedIndex = comboBox.getSelectedIndex();
+// 			    if ( selectedIndex == -1 ) {
+// 				list.clearSelection();
+// 			    }
+// 			    else {
+// 				list.setSelectedIndex( selectedIndex );
+// 			    }
+// 			    list.ensureIndexIsVisible( list.getSelectedIndex() );
+// 			    setLightWeightPopupEnabled( comboBox.isLightWeightPopupEnabled() );
+// 			    show(arrowButton, arrowButton.getSize().width - (popupSize.width + 4), arrowButton.getSize().height);
+// 			}
+// 		    }
+// 		};
+	    popup.getAccessibleContext().setAccessibleParent(comboBox);
+	    return popup;
+	}
+
+	public void setButtonBackground() {
+		arrowButton.setBackground(Configuration.getColor("coloring.button_background", false));
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/GLIButton.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/GLIButton.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/GLIButton.java	(revision 13928)
@@ -0,0 +1,85 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import org.greenstone.gatherer.util.Utility;
+
+/** A button that knows whether it should paint itself as opaque or otherwise. */
+public class GLIButton
+    extends JButton {
+
+    public GLIButton() {
+	super();
+	setOpaque(!Utility.isMac());
+    }
+
+    public GLIButton(ImageIcon icon) {
+	super(icon);
+	setOpaque(!Utility.isMac());
+    }
+
+    public GLIButton(String title) {
+	super(title);
+	setOpaque(!Utility.isMac());
+    }
+
+    public GLIButton(String title, ImageIcon icon) {
+	super(title, icon);
+	setOpaque(!Utility.isMac());
+    }
+
+    public GLIButton(ImageIcon icon, String tooltip) {
+	super(icon);
+	setOpaque(!Utility.isMac());
+	setToolTipText(tooltip);
+    }
+    public GLIButton(String title, String tooltip) {
+	super(title);
+	setOpaque(!Utility.isMac());
+	setToolTipText(tooltip);
+    }
+
+    public GLIButton(String title, ImageIcon icon, String tooltip) {
+	super(title, icon);
+	setOpaque(!Utility.isMac());
+	setToolTipText(tooltip);
+    }
+
+   
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/GProgressBar.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/GProgressBar.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/GProgressBar.java	(revision 13928)
@@ -0,0 +1,205 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+
+import javax.swing.*;
+
+
+/** A progress bar that doesn't pack a sad when you feed it longs (such as the sizes of files) which get mangled into negative numbers. I know how it feels, as I often have negative progress. Also tries to be efficent when updating the JProgressBar, so only updates when the value actually changes, which become necessary when you move a large number of files with millions of bytes (where upon shifting a file of a thousand bytes would be pretty insignificant, maybe not even a percent, but would fire several progress updates). 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ */
+public class GProgressBar
+    extends JProgressBar
+{
+    private long cur_value = 0L;
+    private long max_value = 0L;
+
+    /** The previous percentage value. */
+    private int previous = -1;
+
+
+    public GProgressBar()
+    {
+	super(0, 100);
+    }
+
+
+    public void addMaximum(long amount)
+    {
+	if (amount > 0) {
+	    max_value = max_value + amount;
+	    update();
+	}
+    }
+
+
+    public void addValue(long amount)
+    {
+	if (amount > 0) {
+	    cur_value = cur_value + amount;
+	    update();
+	}
+    }
+
+
+    public void clear()
+    {
+ 	previous = -1;
+ 	update();
+    }
+
+
+    public void reset()
+    {
+ 	cur_value = 0L;
+ 	max_value = 0L;
+ 	previous = -1;
+ 	update();
+    }
+
+
+    public void setIndeterminate(boolean indeterminate)
+    {
+	SwingUtilities.invokeLater(new SafeSetIndeterminateTask(indeterminate));		  
+    }
+
+
+    public void setString(String label)
+    {
+	SwingUtilities.invokeLater(new SafeSetStringTask(label));
+    }
+
+
+    public void setMaximum(int value)
+    {
+	max_value = value;
+	update();
+    }
+
+	 
+    public void setValue(int value)
+    {
+	cur_value = value;
+	update();
+    }
+
+
+    /** Only bother updating the progress bar if the percentage has changed. */
+    private void update()
+    {
+	int percentage = -1;
+	if (cur_value == 0L || max_value == 0L) {
+	    percentage = 0;
+	}
+	else {
+	    long per_value = (cur_value * 100) / max_value;
+	    percentage = (int) per_value;
+	    if (percentage > 100) {
+		percentage = 100;
+	    }
+	}
+
+	if (percentage != previous) {
+	    previous = percentage;
+	    setString(percentage + "%");
+	    SwingUtilities.invokeLater(new SafeSetValueTask(percentage));
+	}
+    }
+
+
+    /** Internal class to call JProgressBar.setIndeterminate safely. */
+    private class SafeSetIndeterminateTask
+	implements Runnable
+    {
+	private boolean indeterminate;
+
+	public SafeSetIndeterminateTask(boolean indeterminate)
+	{
+	    this.indeterminate = indeterminate;
+	}
+
+	public void run()
+	{
+	    unsafeSetIndeterminate(indeterminate);
+	}
+    }
+
+    /** This method is unsafe, -unless- it is called from the Event Queue (eg. from SafeSetIndeterminateTask). */
+    private void unsafeSetIndeterminate(boolean indeterminate)
+    {
+	super.setIndeterminate(indeterminate);
+    }
+
+
+    /** Internal class to call JProgressBar.setString safely. */
+    private class SafeSetStringTask
+	implements Runnable
+    {
+	private String label;
+
+	public SafeSetStringTask(String label)
+	{
+	    this.label = label;
+	}
+
+	public void run()
+	{
+	    unsafeSetString(label);
+	}
+    }
+
+    /** This method is unsafe, -unless- it is called from the Event Queue (eg. from SafeSetStringTask). */
+    private void unsafeSetString(String label)
+    {
+	super.setString(label);
+    }
+
+
+    /** Internal class to call JProgressBar.setValue safely. */
+    private class SafeSetValueTask
+	implements Runnable
+    {
+	private int value;
+
+	public SafeSetValueTask(int value)
+	{
+	    this.value = value;
+	}
+
+	public void run()
+	{
+	    unsafeSetValue(value);
+	}
+    }
+
+    /** This method is unsafe, -unless- it is called from the Event Queue (eg. from SafeSetValueTask). */
+    private void unsafeSetValue(int value)
+    {
+	super.setValue(value);
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/GUIManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/GUIManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/GUIManager.java	(revision 13928)
@@ -0,0 +1,952 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.datatransfer.*;
+import java.awt.event.*;
+import java.io.File;
+import java.lang.*;
+import java.net.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.filechooser.*;
+import javax.swing.plaf.*;
+import javax.swing.text.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.Collection;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.file.FileOpenActionListener;
+import org.greenstone.gatherer.file.WorkspaceTree;
+import org.greenstone.gatherer.gui.metaaudit.MetaAuditFrame;
+import org.greenstone.gatherer.gui.tree.DragTree;
+import org.greenstone.gatherer.metadata.MetadataSet;
+import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
+import org.greenstone.gatherer.util.JarTools;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+
+/** The GUIManager is in charge of creating the Gatherer window frame then filling it with the goodness of the view panes. GUIManager not only creates these panes, but allows some messaging between them. Furthermore GUIManager includes functionality from menu driven choices, simply as it was easier to put it here once and have it accessible from all pane children. */
+public class GUIManager
+    extends JFrame
+    implements ActionListener, ChangeListener,  WindowFocusListener{
+    /** The download pane contains controls for downloading internet sites. */
+    public DownloadPane download_pane = null;
+    /** The gather pane is more like a file manager where you drag files from one tree to another. */
+    public GatherPane gather_pane = null;
+    /** The enrich pane is used to assign, edit and remove metadata from files within the collection. */
+    public EnrichPane enrich_pane = null;
+    /** The design pane allows you to edit the design of the library in terms of the collection configuration file. - the stuff that requires rebuilding */
+    public DesignPane design_pane = null;
+    /** The create pane contains scripting options for importing and building collections into libraries. */
+    public CreatePane create_pane = null;
+    /** The format pane allows you to edit the design of the library in terms of the collection configuration file. - the stuff that doesn't require rebuilding */
+    public FormatPane format_pane = null;
+    
+    public FileOpenActionListener foa_listener = new FileOpenActionListener();
+
+
+    /** A reference to the currently instantiated help window, if any. */
+    private HelpFrame help = null;
+    /** The menu bar. */
+    public MenuBar menu_bar = null;
+    public MetaAuditFrame meta_audit;
+    /** Are certain panes currently locked? */
+    private boolean locked = false;
+    /** The size of the Gatherer window. */
+    private Dimension size = null;
+    /** The panel within the window that other components are placed on. */
+    private JPanel content_pane = null;
+    /** The last view pane selected. */
+    private JPanel previous_pane;
+    /** The main tab pane containing the different views, available here to trap view change events. */
+    private JTabbedPane tab_pane = null;
+    /** A threaded tab changer to try and avoid NPE on exit. */
+    private TabUpdater tab_updater = null;
+
+
+
+
+
+  final static String newline = "\n";
+    final static String space = "    ";
+   
+
+    /**Constructor. Enable window events and arranges all other components.
+     * @param size The intial <strong>Dimension</strong> of the screen.
+     */
+    public GUIManager(Dimension size) {
+	super();
+	// Initialization
+	this.help = new HelpFrame();
+	this.size = size;
+	
+	this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
+
+	// Add a focus listener to ourselves. Thus if we gain focus when a Modal Dialog should instead have it, we can try to bring the modal dialog to the fore.
+	this.addFocusListener(new GLIGUIFocusListener());
+
+	this.addWindowFocusListener(this);
+     
+	// Make the Tool tip hang around for a rediculous amount of time.
+	ToolTipManager.sharedInstance().setDismissDelay(10000);
+
+	// Set up some other UI stuff. (fonts handled in Gatherer.main())
+	UIManager.put("FileChooser.lookInLabelText", Dictionary.get("SaveCollectionBox.Look_In"));
+	UIManager.put("FileChooser.filesOfTypeLabelText", Dictionary.get("SaveCollectionBox.Files_Of_Type"));
+	UIManager.put("FileChooser.fileNameLabelText", Dictionary.get("SaveCollectionBox.File_Name"));
+    }
+
+
+    public void windowGainedFocus(WindowEvent e)
+    {
+    }
+
+
+    public void windowLostFocus(WindowEvent e)
+    {
+	// Save the loaded collection
+	if (Gatherer.c_man != null && Gatherer.c_man.ready() && Gatherer.c_man.getCollection().cdm != null) {
+	    Gatherer.c_man.saveCollection();
+	}
+    }
+
+
+    private class GLIGUIFocusListener
+	extends FocusAdapter {
+	public void focusGained(FocusEvent e) {
+            if (ModalDialog.current_modal != null) {
+		ModalDialog.current_modal.makeVisible();
+		ModalDialog.current_modal.toFront();
+	    }
+	}
+    }
+
+    /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured. In this case we are listening to actions from the menu-bar, and should react appropriately.
+     * @param event An <strong>ActionEvent</strong> containing information about the action that has occured.
+     */
+    public void actionPerformed(ActionEvent event) {
+	Object esrc = event.getSource();
+	// *************
+	// File Options.
+	// *************
+	if (esrc == menu_bar.file_associations) {
+	    Gatherer.assoc_man.edit();
+	}
+	else if (esrc == menu_bar.file_close) {
+	    saveThenCloseCurrentCollection();
+	}
+	else if (esrc == menu_bar.file_delete) {
+	    new DeleteCollectionTask().start();
+	}
+	else if (esrc == menu_bar.file_cdimage) {
+	    WriteCDImagePrompt wcdip = new WriteCDImagePrompt();
+	    wcdip.display();
+	    wcdip.destroy();
+	    wcdip = null;
+	}
+	else if (esrc == menu_bar.file_exportas) {
+	    ExportAsPrompt eap = new ExportAsPrompt();
+	    eap.display();
+	    eap.destroy();
+	    eap = null;
+	}
+        else if (esrc == menu_bar.file_new) {
+	    new NewCollectionTask().start();
+	}
+	else if (esrc == menu_bar.file_open) {
+	    new OpenCollectionTask().start();
+	}
+	else if (esrc == menu_bar.file_options) {
+	    new Preferences();
+	}
+	else if (esrc == menu_bar.file_save) {
+	    Gatherer.c_man.saveCollection();
+	}
+	else if (esrc == menu_bar.file_exit) {
+	    new ExitTask().start();
+	}
+
+	// *************
+	// Edit Options.
+	// *************
+	else if(esrc == menu_bar.edit_copy) {
+	    try {
+		KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
+		// Get the component with selected text as a JTextComponent
+		JTextComponent text = (JTextComponent) kfm.getPermanentFocusOwner();//getFocusOwner();
+		text.copy();
+	    }
+	    catch (Exception cce) {
+		// If the component is not a text component ignore the copy command
+		DebugStream.println(cce.toString());
+	    }
+	}
+	else if(esrc == menu_bar.edit_cut) {
+	    try {
+		KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
+		// Get the component with selected text as a JTextComponent
+		JTextComponent text = (JTextComponent) kfm.getPermanentFocusOwner();
+		// Cut the text to the clipboard
+		text.cut();
+	    }
+	    catch (ClassCastException cce) {
+		// If the component is not a text component ignore the cut command
+		DebugStream.println(cce.toString());
+	    }
+	}
+	else if(esrc == menu_bar.edit_paste) {
+	    try {
+		KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
+		// Get the component with selected text as a JTextComponent
+		JTextComponent text = (JTextComponent) kfm.getPermanentFocusOwner();
+		// Cut the text to the clipboard
+		text.paste();
+	    }
+	    catch (ClassCastException cce) {
+		// If the component is not a text component ignore the paste command
+		DebugStream.println(cce.toString());
+	    }
+	}
+
+	// *************
+	// Help Options.
+	// *************
+	else if (esrc == menu_bar.help_general) {
+	    HelpFrame.setView("introduction");
+	}
+	else if (esrc == menu_bar.help_download) {
+	    HelpFrame.setView("downloadingfiles");
+	}
+	else if (esrc == menu_bar.help_gather) {
+	    HelpFrame.setView("collectingfiles");
+	}
+	else if (esrc == menu_bar.help_enrich) {
+	    HelpFrame.setView("enrichingacollection");
+	}
+	else if (esrc == menu_bar.help_design) {
+	    HelpFrame.setView("designingacollection");
+	}
+	else if (esrc == menu_bar.help_create) {
+	    HelpFrame.setView("producingthecollection");
+	}
+	else if (esrc == menu_bar.help_format) {
+	    HelpFrame.setView("formattingacollection");
+	}
+	else if (esrc == menu_bar.help_about) {
+	    new AboutDialog(this);
+	}
+    }
+
+
+    /** Any actions that should happen after the display of the Gatherer window can be called here. Currently only updates the browser pane if it is active to work around bug in Mozilla renderer implementation.
+     */
+    public void afterDisplay() {
+	if (download_pane != null) {
+	    download_pane.afterDisplay();
+	}
+	enrich_pane.afterDisplay();
+    }
+
+
+    public void closeCurrentCollection()
+    {
+	tab_pane.setSelectedComponent(gather_pane);
+	Gatherer.c_man.closeCollection();
+    }
+
+
+    public void saveThenCloseCurrentCollection()
+    {
+   	Gatherer.c_man.saveCollection();
+	closeCurrentCollection();
+    }
+
+
+    /** This is called when we're absolutely finished with the GLI. It is *not* called when the applet is suspended.
+     */
+    public void destroy()
+    {
+	// Destroying create pane ensures the latest log has been closed
+	if (create_pane != null) {
+	    create_pane.destroy();
+	}
+
+	// Deal to help
+	if (help != null) {
+	    help.destroy();
+	    help = null;
+	}
+    }
+
+
+    /** Enabled events on the window to be trapped, creates all the visual components, then builds the tab and other layouts.
+     */
+    public void display() {
+	content_pane = (JPanel) this.getContentPane();
+	// Enable window-type events to be fired.
+	enableEvents(AWTEvent.WINDOW_EVENT_MASK);
+	// Initialise and layout sub-components, plus other window dressing.
+	try {
+	    this.setSize(size);
+
+	    // Set the title
+	    String collection_title = null;
+	    String collection_name = null;
+	    if (Gatherer.c_man.ready()) {
+		Collection collection = Gatherer.c_man.getCollection();
+		collection_title = collection.getTitle();
+		collection_name = collection.getName();
+		collection = null;
+	    }
+	    setTitle(collection_title, collection_name);
+	    collection_title = null;
+	    collection_name = null;
+
+	    // Pretty corner icon
+	    this.setIconImage(JarTools.getImage("gatherer_small.gif").getImage());
+	    // BorderLayout for the main screen. I'll try my best to avoid these in subcomponents as they're space greedy.
+	    content_pane.setLayout(new BorderLayout());
+	    // Create the menu-bar and stick it up the top.
+	    menu_bar = new MenuBar(new MenuListenerImpl());
+
+	    //feedback changes
+	    //content_pane.add(menu_bar, BorderLayout.NORTH);
+	    this.setJMenuBar(menu_bar);
+	    // end feedback changes
+
+	    // Create the tabbed pane and plop it in the center where it will
+	    // expand to consume all available space like any good gas would.
+	    tab_pane = new JTabbedPane();
+	    tab_pane.addChangeListener(this);
+	    tab_pane.setFont(Configuration.getFont("general.font", false));
+
+	    if (Configuration.get("workflow.download", true)) {
+		download_pane = new DownloadPane();
+		// "GUI.Download_Tooltip" is used automatically
+		tab_pane.addTab(Dictionary.get("GUI.Download"), JarTools.getImage("download.gif"), download_pane, Dictionary.get("GUI.Download_Tooltip"));
+		tab_pane.setEnabledAt(tab_pane.indexOfComponent(download_pane), Configuration.get("workflow.download", false));
+	    }
+
+	    gather_pane = new GatherPane();
+	    gather_pane.display();
+	    if (Configuration.get("workflow.gather", true)) {
+		// "GUI.Gather_Tooltip" is used automatically
+		tab_pane.addTab(Dictionary.get("GUI.Gather"), JarTools.getImage("gather.gif"), gather_pane, Dictionary.get("GUI.Gather_Tooltip"));
+		tab_pane.setEnabledAt(tab_pane.indexOfComponent(gather_pane), Configuration.get("workflow.gather", false));
+	    }
+
+	    enrich_pane = new EnrichPane();
+	    enrich_pane.display();
+	    if (Configuration.get("workflow.enrich", true)) {
+		// "GUI.Enrich_Tooltip" is used automatically
+		tab_pane.addTab(Dictionary.get("GUI.Enrich"), JarTools.getImage("enrich.gif"), enrich_pane, Dictionary.get("GUI.Enrich_Tooltip"));
+		tab_pane.setEnabledAt(tab_pane.indexOfComponent(enrich_pane), false);
+	    }
+
+	    design_pane = new DesignPane();
+	    design_pane.display();
+	    if (Configuration.get("workflow.design", true)) {
+		// "GUI.Design_Tooltip" is used automatically
+		tab_pane.addTab(Dictionary.get("GUI.Design"), JarTools.getImage("design.gif"), design_pane, Dictionary.get("GUI.Design_Tooltip"));
+		tab_pane.setEnabledAt(tab_pane.indexOfComponent(design_pane), false);
+	    }
+
+	    create_pane = new CreatePane();
+	    create_pane.display();
+	    if (Configuration.get("workflow.create", true)) {
+		// "GUI.Create_Tooltip" is used automatically
+		tab_pane.addTab(Dictionary.get("GUI.Create"), JarTools.getImage("create.gif"), create_pane, Dictionary.get("GUI.Create_Tooltip"));
+		tab_pane.setEnabledAt(tab_pane.indexOfComponent(create_pane), false);
+	    }
+
+	    format_pane = new FormatPane();
+	    format_pane.display();
+	    if (Configuration.get("workflow.format", true)) {
+		tab_pane.addTab(Dictionary.get("GUI.Format"), JarTools.getImage("format.gif"), format_pane, Dictionary.get("GUI.Format_Tooltip"));
+		tab_pane.setEnabledAt(tab_pane.indexOfComponent(format_pane), false);
+	    }
+	    
+	    // The MetaAuditFrame must be created after the gather/enrich panes but before they get focus
+	    meta_audit = new MetaAuditFrame();
+
+	    // Select the collect pane if it is available
+	    if (tab_pane.indexOfComponent(gather_pane) != -1) {
+		tab_pane.setSelectedComponent(gather_pane);
+	    }
+	    // Otherwise find the first tab that is enabled and select that.
+	    else {
+		for (int i = 0; i < tab_pane.getTabCount(); i++) {
+		    if (tab_pane.isEnabledAt(i)) {
+			tab_pane.setSelectedIndex(i);
+			break;
+		    }
+		}
+	    }
+
+	    content_pane.add(tab_pane, BorderLayout.CENTER);
+
+	    // Add an extra progress bar at the bottom of every screen when using a remote Greenstone server
+	    if (Gatherer.isGsdlRemote) {
+		JPanel remote_greenstone_server_progress_panel = new JPanel();
+		JLabel remote_greenstone_server_progress_label = new JLabel(Dictionary.get("RemoteGreenstoneServer.Progress"));
+		remote_greenstone_server_progress_panel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+		remote_greenstone_server_progress_panel.setLayout(new BorderLayout());
+		remote_greenstone_server_progress_panel.add(remote_greenstone_server_progress_label, BorderLayout.WEST);
+		remote_greenstone_server_progress_panel.add(RemoteGreenstoneServer.getProgressBar(), BorderLayout.CENTER);
+		content_pane.add(remote_greenstone_server_progress_panel, BorderLayout.SOUTH);
+	    }
+
+	    // Call refresh to update all controls to reflect current collection status.
+	    refresh(-1, Gatherer.c_man.ready());
+	}
+	catch (Exception e) {
+	    DebugStream.printStackTrace(e);
+	    // The GUI failing to build is an app killer
+	    e.printStackTrace();
+	    System.exit(1);
+	}
+    }
+
+    public void exit() 
+    {
+	exit(0);
+    }
+	
+    /** This method ensures that all the things needing saving are saved before Gatherer.exit() is called.
+     */
+    public void exit(int exit_status)
+    {
+	// If we have a collection open remember it for next time, then save it and close it
+	if (Gatherer.c_man.ready()) {
+	    Configuration.setString("general.open_collection", true, CollectionManager.getLoadedCollectionColFilePath());
+	    saveThenCloseCurrentCollection();
+	}
+	else {
+	    Configuration.setString("general.open_collection", true, null);
+	}
+
+	// Store the current position and size of the GLI for next time
+	Configuration.setBounds("general.bounds", true, getBounds());
+
+	// Save configuration
+	Configuration.save();
+
+	// Hide the main window
+	setVisible(false);
+
+	// If we're running as an applet we don't quit here (we quit when the browser calls GathererApplet.destroy())
+	if (!Gatherer.isApplet) {
+	    Gatherer.exit(exit_status);
+	}
+    }
+
+
+    /** This method is called when the collection is being built, and is used to disable all controls in all pane which could change the state of the collection.
+     */
+    public void lockCollection(boolean import_stage, boolean lock)
+    {
+	locked = lock;
+
+	if (import_stage) {
+	    int gather_pos = tab_pane.indexOfComponent(gather_pane);
+	    if (gather_pos != -1) {
+		tab_pane.setEnabledAt(gather_pos, !lock);
+	    }
+	    int enrich_pos = tab_pane.indexOfComponent(enrich_pane);
+	    if (enrich_pos != -1) {
+		tab_pane.setEnabledAt(enrich_pos, !lock);
+	    }
+	}
+
+	int design_pos = tab_pane.indexOfComponent(design_pane);
+	if (design_pos != -1) {
+	    tab_pane.setEnabledAt(design_pos, !lock);
+	}
+    }
+
+
+    public void modeChanged(int mode) {
+	// Set the title
+	String collection_title = null;
+	String collection_name = null;
+	if (Gatherer.c_man.ready()) {
+	    Collection collection = Gatherer.c_man.getCollection();
+	    collection_title = collection.getTitle();
+	    collection_name = collection.getName();
+	    collection = null;
+	}
+	setTitle(collection_title, collection_name);
+	collection_title = null;
+	collection_name = null;
+	// Now pass on the message to anyone who cares
+	if (download_pane != null) {
+	    download_pane.modeChanged(mode);
+	}
+	if (gather_pane != null) {
+	    gather_pane.modeChanged(mode);
+	}
+	if (enrich_pane != null) {
+	    enrich_pane.modeChanged(mode);
+	}
+	if (design_pane != null) {
+	    design_pane.modeChanged(mode);
+	}
+	if (create_pane != null) {
+	    create_pane.modeChanged(mode);
+	}
+	if (format_pane != null) {
+	    format_pane.modeChanged(mode);
+	}
+    }
+
+
+    public void refresh(int refresh_reason, boolean collection_loaded)
+    {
+	// Set the collection information in the title bar
+	if (collection_loaded) {
+	    Collection collection = Gatherer.c_man.getCollection();
+	    setTitle(collection.getTitle(), collection.getName());
+	}
+	else {
+	    setTitle(null, null);
+	}
+
+	// Update the menu bar
+	menu_bar.refresh(refresh_reason, collection_loaded);
+
+	// Update the loaded panes
+	if (download_pane != null) {
+	    download_pane.refresh(refresh_reason, collection_loaded);
+	}
+	if (gather_pane != null) {
+	    gather_pane.refresh(refresh_reason, collection_loaded);
+	}
+	if (enrich_pane != null) {
+	    enrich_pane.refresh(refresh_reason, collection_loaded);
+	}
+	if (design_pane != null) {
+	    design_pane.refresh(refresh_reason, collection_loaded);
+	}
+	if (create_pane != null) {
+	    create_pane.refresh(refresh_reason, collection_loaded);
+	}
+	if (format_pane != null) {
+	    format_pane.refresh(refresh_reason, collection_loaded);
+	}
+
+	// Now enable tabs as necessary. Do this on event queue to prevent crazy NPEs
+	if (!locked) {
+	    if (tab_updater == null) {
+		tab_updater = new TabUpdater(tab_pane, collection_loaded);
+	    }
+	    else {
+		tab_updater.setReady(collection_loaded);
+	    }
+	    SwingUtilities.invokeLater(tab_updater);
+	}
+    }
+
+
+    public void refreshCollectionTree(int refresh_reason)
+    {
+	if (gather_pane != null) {
+	    gather_pane.refreshCollectionTree(refresh_reason);
+	}
+    }
+
+
+    public void refreshWorkspaceTree(int refresh_reason)
+    {
+	if (gather_pane != null) {
+	    gather_pane.refreshWorkspaceTree(refresh_reason);
+	}
+    }
+
+
+    /** Specifies whether a certain tab is enabled or not. */
+    private void setTabEnabled(String rawname, boolean state) {
+	// Retrieve the dictionary based name.
+	String name = Dictionary.get("GUI." + rawname);
+	int index = tab_pane.indexOfTab(name);
+	// Of course we may not have this tab available.
+	if(index != -1) {
+	    // Some tabs are also dependant on if a collection is ready
+	    Component component = tab_pane.getComponentAt(index);
+	    if(component == enrich_pane || component == design_pane || component == create_pane || component == format_pane) {
+		tab_pane.setEnabledAt(index, state && Gatherer.c_man != null && Gatherer.c_man.ready());
+	    }
+	    else {
+		tab_pane.setEnabledAt(index, state);
+	    }
+	    // If this was the currently selected tab and it is now disabled, change the view to the first enabled tab.
+	    if(tab_pane.getSelectedIndex() == index && !state) {
+		boolean found = false;
+		for(int i = 0; !found && i < tab_pane.getTabCount(); i++) {
+		    if(tab_pane.isEnabledAt(i)) {
+			tab_pane.setSelectedIndex(i);
+			found = true;
+		    }
+		}
+		// If there are no tabs enabled, which should be impossible, then select the first tab
+		if(!found) {
+		    tab_pane.setSelectedIndex(0);
+		}
+	    }
+	}
+    }
+
+    /** Change the string shown in the title bar of the main gui frame. If either value is null, the 'No Collection' string is shown instead.
+     * @param title
+     * @param name
+     */
+    public void setTitle(String title, String name) {
+	// Finally display the collection name in the title bar.
+	StringBuffer title_buffer = new StringBuffer(Gatherer.PROGRAM_NAME);
+	title_buffer.append(StaticStrings.SPACE_CHARACTER);
+	title_buffer.append(Gatherer.PROGRAM_VERSION);
+	title_buffer.append(StaticStrings.SPACE_CHARACTER);
+	title_buffer.append(StaticStrings.SPACE_CHARACTER);
+	// Describe the current user mode
+	title_buffer.append(StaticStrings.MODE_STR);
+	title_buffer.append(Configuration.getModeAsString());
+	title_buffer.append(StaticStrings.SPACE_CHARACTER);
+	title_buffer.append(StaticStrings.SPACE_CHARACTER);
+	// Now for the current collection
+	title_buffer.append(StaticStrings.COLLECTION_STR);
+	if (title != null && name != null) {
+	    title_buffer.append(title);
+	    title_buffer.append(StaticStrings.SPACE_CHARACTER);
+	    title_buffer.append(StaticStrings.OPEN_PARENTHESIS_CHARACTER);
+	    title_buffer.append(name);
+	    title_buffer.append(StaticStrings.CLOSE_PARENTHESIS_CHARACTER);
+	}
+	else {
+	    title_buffer.append(Dictionary.get("Collection.No_Collection"));
+	}
+	this.setTitle(title_buffer.toString());
+	title_buffer = null;
+    }
+
+
+    private class OpenCollectionTask
+        extends Thread
+    {
+	public void run()
+	{
+	    String collection_file_path = showOpenCollectionDialog();
+
+	    // User has selected a collection to open
+	    if (collection_file_path != null) {
+		// If there is already a collection open, save and close it
+		if (Gatherer.c_man.ready()) {
+		    saveThenCloseCurrentCollection();
+		}
+
+		// Open the selected collection
+		Gatherer.c_man.loadCollection(collection_file_path);
+	    }
+	}
+    }
+
+
+    /** When the load collection option is chosen this method is called to produce the modal file load prompt.
+     */
+    private String showOpenCollectionDialog()
+    {
+	OpenCollectionDialog dialog = new OpenCollectionDialog();
+	if (dialog.display() == OpenCollectionDialog.OK_OPTION) {
+	    return dialog.getFileName();
+	}
+
+	// User must have cancelled the action
+	return null;
+    }
+
+
+    /** When called this method causes the MetadataAuditTable to display a nice dialog box which contains all the metadata assigned in the collection.
+     */
+    public void showMetaAuditBox() {
+	wait(true);
+	meta_audit.display();
+	wait(false);
+    }
+
+
+    private class NewCollectionTask
+	extends Thread
+    {
+	public void run()
+	{
+	    // Create the collection details prompt from new collection prompt
+	    NewCollectionDetailsPrompt ncd_prompt = new NewCollectionDetailsPrompt();
+
+	    // Create the new collection (if not cancelled) in a new thread.
+	    if (!ncd_prompt.isCancelled()) {
+		// If there is already a collection open, save and close it.
+		if (Gatherer.c_man.ready()) {
+		    saveThenCloseCurrentCollection();
+		}
+		
+		// Create new collection.
+		Gatherer.c_man.createCollection(ncd_prompt.getDescription(), Configuration.getEmail(), ncd_prompt.getName(), ncd_prompt.getTitle(), ncd_prompt.getBase(), new ArrayList());
+		ncd_prompt.dispose();
+	    }
+
+	    // Done
+	    ncd_prompt = null;
+	}
+    }
+
+
+    private class DeleteCollectionTask
+	extends Thread
+    {
+	public void run()
+	{
+	    // The rest is handled by the DeleteCollectionPrompt
+	    DeleteCollectionPrompt dc_prompt = new DeleteCollectionPrompt();
+	    if (dc_prompt.display()) {
+		closeCurrentCollection();
+	    }
+	    dc_prompt.destroy();
+	    dc_prompt = null;
+	}
+    }
+
+
+    private class ExitTask
+	extends Thread
+    {
+	public void run()
+	{
+	    exit();
+	}
+    }
+
+
+    /** Any implementation of ChangeListener must include this method so we can be informed when the state of one of the registered objects changes. In this case we are listening to view changes within the tabbed pane.
+     * @param event A ChangeEvent containing information about the event that fired this call.
+     */
+    public void stateChanged(ChangeEvent event)
+    {
+	if (previous_pane != null) {
+	    if (previous_pane == gather_pane) {
+		gather_pane.loseFocus();
+	    }
+	    else if (previous_pane == enrich_pane) {
+		enrich_pane.loseFocus();
+	    }
+	    else if (previous_pane == design_pane) {
+		design_pane.loseFocus();
+	    }
+	    else if (previous_pane == create_pane) {
+		create_pane.loseFocus();
+	    }
+	    else if (previous_pane == format_pane) {
+		format_pane.loseFocus();
+	    }
+	}
+
+	menu_bar.tabSelected(tab_pane.getSelectedIndex());
+	int selected_index = tab_pane.getSelectedIndex();
+	if (selected_index == tab_pane.indexOfComponent(download_pane)) {
+	    download_pane.gainFocus();
+	}
+	else if (selected_index == tab_pane.indexOfComponent(gather_pane)) {
+	    gather_pane.gainFocus();
+	}
+	else if (selected_index == tab_pane.indexOfComponent(enrich_pane)) {
+	    enrich_pane.gainFocus();
+	}
+	else if (selected_index == tab_pane.indexOfComponent(design_pane)) {
+	    design_pane.gainFocus();
+	}
+	else if (selected_index == tab_pane.indexOfComponent(create_pane)) {
+	    create_pane.gainFocus();
+	}
+	else if (selected_index == tab_pane.indexOfComponent(format_pane)) {
+	    format_pane.gainFocus();
+	}
+
+	previous_pane = (JPanel) tab_pane.getSelectedComponent();
+	
+    }
+
+
+    private MouseListener mouse_blocker_listener = new MouseAdapter() {};
+
+    public void updateUI()
+    {
+	JPanel pane = (JPanel) getContentPane();
+	pane.updateUI();
+	// Also update all of the tabs according to workflow.
+	workflowUpdate("Download", Configuration.get("workflow.download", false));
+	workflowUpdate("Gather", Configuration.get("workflow.gather", false));
+	workflowUpdate("Enrich", Configuration.get("workflow.enrich", false));
+	workflowUpdate("Design", Configuration.get("workflow.design", false));
+	workflowUpdate("Create", Configuration.get("workflow.create", false));
+	workflowUpdate("Format", Configuration.get("workflow.format", false));
+    }
+
+    public void wait(boolean waiting) {
+	Component glass_pane = getGlassPane();
+	if(waiting) {
+	    // Show wait cursor.
+	    glass_pane.addMouseListener(mouse_blocker_listener);
+	    glass_pane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+	    glass_pane.setVisible(true);
+	}
+	else {
+	    // Hide wait cursor.
+	    glass_pane.setVisible(false);
+	    glass_pane.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+	    glass_pane.removeMouseListener(mouse_blocker_listener);
+	}
+	glass_pane = null;
+    }
+
+    public void workflowUpdate(String raw, boolean state) {
+	WorkflowUpdater task = new WorkflowUpdater(raw, state);
+	SwingUtilities.invokeLater(task);
+	task = null;
+    }
+
+
+    /**Overridden from JFrame so we can exit safely when window is closed (or destroyed).
+     * @param event A <strong>WindowEvent</strong> containing information about the event that fired this call.
+     */
+    protected void processWindowEvent(WindowEvent event) {
+	if(event.getID() == WindowEvent.WINDOW_CLOSING) {
+	    exit();
+	}
+    }
+
+
+    /** Listens to actions upon the menu bar, and if it detects a click over the help menu brings the help window to the front if it has become hidden.
+     */
+    private class MenuListenerImpl
+	implements MenuListener {
+	/** Called whenever a popup menu is hidden, but we don't care.
+	 * @param e Some <strong>MenuEvent</strong> that we could care less about.
+	 */
+	public void menuCanceled(MenuEvent e) {
+	}
+	/** Called whenever a menu header (ie button) becomes unselected, but we don't care.
+	 * @param e Some <strong>MenuEvent</strong> that we could care less about.
+	 */
+	public void menuDeselected(MenuEvent e) {
+	}
+	/** This method, when a menu is first opened, is the only one we respond to by bringing the help window to the front if possible, but only if there is a help window and the help menu is the one opening.
+	 * @param e The <strong>MenuEvent</strong> whose source is checked.
+	 */
+	public void menuSelected(MenuEvent e) {
+	    if(e.getSource() == menu_bar.help) {
+		if(menu_bar.help.isSelected()) {
+		    menu_bar.help.doClick(10);
+		}
+	    }
+	}
+    }
+
+    private class TabUpdater
+	implements Runnable {
+	private boolean ready = false;
+	private int download_pos = -1;
+	private int enrich_pos = -1;
+	private int design_pos = -1;
+	private int create_pos = -1;
+	private int format_pos = -1;
+	private int export_pos = -1;
+	private JTabbedPane tab_pane = null;
+
+	public TabUpdater(JTabbedPane tab_pane, boolean ready) {
+	    this.ready = ready;
+	    this.tab_pane = tab_pane;
+	    download_pos = tab_pane.indexOfComponent(download_pane);
+	    enrich_pos = tab_pane.indexOfComponent(enrich_pane);
+	    design_pos = tab_pane.indexOfComponent(design_pane);
+	    create_pos = tab_pane.indexOfComponent(create_pane);
+	    format_pos = tab_pane.indexOfComponent(format_pane);
+	}
+
+	public void run()
+	{
+	    if (download_pos != -1) {
+		if (ready) {
+		    tab_pane.setEnabledAt(download_pos, Configuration.get("workflow.download", false));
+		}
+		else {
+		    tab_pane.setEnabledAt(download_pos, Configuration.get("workflow.download", true));
+		}
+	    }
+	    if (enrich_pos != -1) {
+		tab_pane.setEnabledAt(enrich_pos, ready && Configuration.get("workflow.enrich", false));
+	    }
+	    if (design_pos != -1) {
+		tab_pane.setEnabledAt(design_pos, ready && Configuration.get("workflow.design", false) && Configuration.getMode() > Configuration.ASSISTANT_MODE);
+	    }
+	    if (create_pos != -1) {
+		tab_pane.setEnabledAt(create_pos, ready && Configuration.get("workflow.create", false));
+	    }
+	    if (format_pos != -1) {
+		tab_pane.setEnabledAt(format_pos, ready && Configuration.get("workflow.format", false) && Configuration.getMode() > Configuration.ASSISTANT_MODE);
+	    }
+	}
+
+	public void setReady(boolean ready) {
+	    this.ready = ready;
+	}
+    }
+
+    private class WorkflowUpdater
+	implements Runnable {
+	private boolean state;
+	private String raw;
+	public WorkflowUpdater(String raw, boolean state) {
+	    this.raw = raw;
+	    this.state = state;
+	}
+	public void run() {
+	    setTabEnabled(raw, state);
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/GUIUtils.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/GUIUtils.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/GUIUtils.java	(revision 13928)
@@ -0,0 +1,69 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.util.*;
+
+public class GUIUtils {
+
+    /** The name of the mouse listener that initiates editing on a double click. */
+    static final private String SINGLE_CLICK_LISTENER = "SingleClickListener";
+
+    /** Neat method to disable file renaming in filechooser.
+     * Thanks to: vladi21 from www.experts-exchange.com
+     */
+    static public void disableRename(Component c) {
+	if (c instanceof JList){
+	    EventListener[] listeners=c.getListeners(MouseListener.class);
+	    for(int i=0; listeners != null && i < listeners.length; i++) {
+		if (listeners[i].toString().indexOf(SINGLE_CLICK_LISTENER) != -1) {
+		    c.removeMouseListener((MouseListener)listeners[i]);
+		}
+	    }
+	    return;
+	}
+	if (c instanceof Container) {
+	    Component[] children = null;
+	    children = ((Container)c).getComponents();
+	    if (children != null) {
+		for(int i = 0; children != null && i < children.length; i++) {
+		    disableRename(children[i]);
+		}
+	    }
+	}
+    }
+
+
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/GatherPane.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/GatherPane.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/GatherPane.java	(revision 13928)
@@ -0,0 +1,412 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.CollectionTree;
+import org.greenstone.gatherer.collection.CollectionTreeNode;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.file.FileOpenActionListener;
+import org.greenstone.gatherer.file.FileQueue;
+import org.greenstone.gatherer.file.FileSystemModel;
+import org.greenstone.gatherer.file.RecycleBin;
+import org.greenstone.gatherer.file.WorkspaceTree;
+import org.greenstone.gatherer.file.WorkspaceTreeNode;
+import org.greenstone.gatherer.gui.tree.DragTree;
+import org.greenstone.gatherer.util.DragComponent;
+import org.greenstone.gatherer.util.DragGroup;
+import org.greenstone.gatherer.util.JarTools;
+import org.greenstone.gatherer.util.Utility;
+
+
+/** The collection pane is analogous with a file manager. It is there that the user chooses which files to include in their collection and what structure the file hierarchy should take. The later aspect is not important for the Greenstone Suite, but is usefull for grouping files for ease of metadata markup. The view essentially consists of two file trees, one denoting the entire source workspace and the other the files within your collection. The trees themselves have a title bar at the top, a filter control at the bottom, and are coloured to indicate activity (grey for disabled). The remainder of the screen is taken by a status area, to indicate current file job progress during copying etc, and three buttons for controlling features of the view.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class GatherPane
+    extends JPanel
+    implements ActionListener
+{
+    private CardLayout card_layout = null;
+    private JPanel card_pane = null;
+    /** The name of the panel containing the "collection loaded" (collection tree) card. */
+    private String COLLECTION_LOADED_CARD = "";
+    /** The name of the panel containing the "no collection loaded" placeholder */
+    private String NO_COLLECTION_LOADED_CARD = "No collection loaded";
+    /** The group encompassing all of the components available as drop targets for drag and drop actions. Required so that only one component renders the ghost and higlights itself as a target, which the other members are restored to their original, pristine, condition. */
+    private DragGroup group = null;
+    /** The tree showing the files within the collection. */
+    private CollectionTree collection_tree = null;
+    /** The threaded queue that handles the actually movement of files, so that the gui remains responsive. */
+    private FileQueue file_queue = null;
+    /** The filter currently applied to the collection tree. */
+    private Filter collection_filter = null;
+    /** The filter currently applied to the workspace tree. */
+    private Filter workspace_filter = null;
+    /** The button used to cancel all pending file queue jobs. */
+    private JButton stop_action =  null;
+    /** The button used to create a new folder in the collection tree. */
+    private JButton new_folder =  null;
+    /** The label shown at the top of the collection tree. */
+    private JLabel collection_label = null;
+    /** The label shown in the status area explaining the file apon which action is taking place. */
+    private JLabel filename_label = null;
+    /** The label shown explaining the current state of the file queue thread. */
+    private JLabel status_label	= null;
+    /** The label at the top of the workspace tree. */
+    private JLabel workspace_label = null;
+    /** The panel that contains the collection tree. */
+    private JPanel collection_pane = null;
+    /** The panel that contains the various controls including the status area. */
+    private JPanel control_pane = null;
+    /** The panel that contains the workspace tree. */
+    private JPanel workspace_pane = null;
+    /** The scrollable area into which the collection tree is placed. */
+    private JScrollPane collection_scroll = null;
+    /** The scrollable area into which the workspace tree is placed. */
+    private JScrollPane workspace_scroll = null;
+    /** A split pane seperating the two trees, allowing for the screen real-estate for each to be changed. */
+    private JSplitPane tree_pane = null;
+    /** The minimum size a gui component can become. */
+    static private Dimension MIN_SIZE = new Dimension( 90,  90);
+    /** The default size of the status area. */
+    static private Dimension STATUS_SIZE = new Dimension(450, 120);
+    /** The initial size of the trees. */
+    static private Dimension TREE_SIZE = new Dimension(400, 430);
+
+    /** The tree showing the available source workspace. */
+    public WorkspaceTree workspace_tree = null;
+
+
+    public GatherPane()
+    {
+	this.group = new DragGroup();
+	this.file_queue = Gatherer.f_man.getQueue();
+
+	// Create components.
+	stop_action = new GLIButton(Dictionary.get("Collection.Stop"), Dictionary.get("Collection.Stop_Tooltip"));
+	stop_action.addActionListener(this);
+	stop_action.setEnabled(false);
+	file_queue.registerStopButton(stop_action);
+		
+	new_folder = new GLIButton(JarTools.getImage("folder.gif"), Dictionary.get("Collection.New_Folder_Tooltip"));
+	new_folder.addActionListener(this);
+	new_folder.setEnabled(false);
+	new_folder.setMinimumSize(MIN_SIZE);
+	new_folder.setPreferredSize(MIN_SIZE);
+	
+    }
+
+    /** Any implementation of ActionListener requires this method so that when an action is performed the appropriate effect can occur. In this case there are three valid possibilities. If the action occured on the recycle bin, then delete the current selection from the collection tree. If the action instead occured on the new folder button, then create a new folder under the current (single) selection in the collection tree. And finally if the cancel button was pressed, cancel the current, and remaining, jobs on the file queue. */
+    public void actionPerformed(ActionEvent event) {
+	// If a user has clicked on the bin button directly remove whatever
+	// files are selected in the active tree.
+	if (event.getSource() == Gatherer.recycle_bin) {
+	    if (!Gatherer.recycle_bin.ignore()) {
+		// Find the active tree (you've made selections in).
+		DragTree tree = (DragTree) group.getActive();
+		// Fudge things a bit
+		group.setSource(tree);
+		// Determine the selection.
+		TreePath paths[] = tree.getSelectionPaths();
+		if(paths != null) {
+		    FileNode[] source_nodes = new FileNode[paths.length];
+		    for(int i = 0; i < paths.length; i++) {
+			source_nodes[i] = (FileNode)(paths[i].getLastPathComponent());
+		    }
+		    Gatherer.f_man.action(tree, source_nodes, Gatherer.recycle_bin, null);
+		}
+	    }
+	}
+	// If a user has clicked on new_folder create a new folder under
+	// whatever node is selected.
+	else if(event.getSource() == new_folder && collection_tree != null) {
+	    int count = collection_tree.getSelectionCount();
+	    boolean error = false;
+	    if(count == 1) {
+		TreePath path = collection_tree.getSelectionPath();
+		CollectionTreeNode node = (CollectionTreeNode) path.getLastPathComponent();
+		if (node.getAllowsChildren()) {
+		    Gatherer.f_man.newFolder(collection_tree, node);
+		}
+		else {
+		    // try the parent
+		    CollectionTreeNode parent = (CollectionTreeNode) node.getParent();
+		    if (parent!=null && parent.getAllowsChildren()) {
+			Gatherer.f_man.newFolder(collection_tree, parent);
+		    } else {
+			error = true;
+		    }
+		}
+	    }
+	    else {
+		error = true;
+	    }
+	    if(error) {
+		// instead of an error, we now create a new folder at the root
+		CollectionTreeNode node = (CollectionTreeNode) collection_tree.getModel().getRoot();
+		Gatherer.f_man.newFolder(collection_tree, node);
+	    }
+	}
+	else if(event.getSource() == stop_action) {
+	    file_queue.cancelAction();
+	}
+    }
+
+
+    /** Generates the pane on controls used to 'collect' files into the collection. Resposible for creating, connecting and laying out these controls. */
+    public void display()
+    {
+	// Workspace Tree
+	workspace_pane = new JPanel();
+	workspace_pane.setMinimumSize(MIN_SIZE);
+	workspace_pane.setPreferredSize(TREE_SIZE);
+	workspace_pane.setSize(TREE_SIZE);
+
+	workspace_label = new JLabel(Dictionary.get("Collection.Workspace"));
+	workspace_label.setOpaque(true);
+	workspace_label.setBackground(Configuration.getColor("coloring.workspace_heading_background", false));
+	workspace_label.setForeground(Configuration.getColor("coloring.workspace_heading_foreground", false));
+	
+	workspace_tree = new WorkspaceTree();
+	group.add(workspace_tree);
+	workspace_scroll = new JScrollPane(workspace_tree);
+	workspace_filter = workspace_tree.getFilter();
+
+	card_layout = new CardLayout();
+
+	// Collection Tree
+	collection_pane = new JPanel();
+	collection_pane.setMinimumSize(MIN_SIZE);
+	collection_pane.setPreferredSize(TREE_SIZE);
+	collection_pane.setSize(TREE_SIZE);
+
+	collection_label = new JLabel(Dictionary.get("Collection.Collection"));
+	collection_label.setOpaque(true);
+	
+	collection_tree = Gatherer.c_man.getCollectionTree();
+	collection_tree.setEnabled(Gatherer.c_man.getCollectionTreeModel() != null);
+	group.add(collection_tree);
+	collection_filter = collection_tree.getFilter();
+
+	tree_pane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
+
+	// No collection loaded pane
+	JPanel no_collection_pane = new JPanel();
+	no_collection_pane.setBackground(Color.lightGray);
+
+	JLabel no_collection_label = new JLabel(Dictionary.get("Collection.Collection"));
+	no_collection_label.setBackground(Color.lightGray);
+	no_collection_label.setForeground(Color.black);
+	no_collection_label.setOpaque(true);
+	
+	JPanel no_collection_loaded_panel = new JPanel();
+	no_collection_loaded_panel.setBorder(BorderFactory.createLineBorder(Color.black));
+	no_collection_loaded_panel.setBackground(Color.lightGray);
+
+	JLabel no_collection_loaded_label = new JLabel(Dictionary.get("Collection.No_Collection_Loaded"));
+	no_collection_loaded_label.setHorizontalAlignment(JLabel.CENTER);
+	no_collection_loaded_label.setVerticalAlignment(JLabel.CENTER);
+	
+	// Status pane
+	control_pane = new JPanel();
+
+	JPanel inner_pane = new JPanel();
+	inner_pane.setSize(STATUS_SIZE);
+
+	card_pane = new JPanel();
+	JPanel file_pane = new JPanel();
+	JPanel progress_pane = new JPanel();
+	JLabel file_status = file_queue.getFileStatus();
+
+	JProgressBar progress_bar = file_queue.getProgressBar();
+
+	JPanel button_pane = new JPanel();
+
+	RecycleBin recycle_bin = Gatherer.recycle_bin;
+	recycle_bin.addActionListener(this);
+	recycle_bin.setMinimumSize(MIN_SIZE);
+	recycle_bin.setPreferredSize(MIN_SIZE);
+	recycle_bin.setToolTipText(Dictionary.get("Collection.Delete_Tooltip"));
+	group.add(recycle_bin);
+
+	// Layout Components.
+	workspace_pane.setLayout(new BorderLayout());
+	workspace_pane.add(workspace_label, BorderLayout.NORTH);
+	workspace_pane.add(workspace_scroll, BorderLayout.CENTER);
+	workspace_pane.add(workspace_filter, BorderLayout.SOUTH);
+	
+	collection_pane.setLayout(new BorderLayout());
+	collection_pane.add(collection_label, BorderLayout.NORTH);
+
+	no_collection_loaded_panel.setLayout(new BorderLayout());
+	no_collection_loaded_panel.add(no_collection_loaded_label, BorderLayout.CENTER);
+
+	no_collection_pane.setLayout(new BorderLayout());
+	no_collection_pane.add(no_collection_label, BorderLayout.NORTH);
+	no_collection_pane.add(no_collection_loaded_panel, BorderLayout.CENTER);
+
+	card_pane.setLayout(card_layout);
+	card_pane.add(no_collection_pane, NO_COLLECTION_LOADED_CARD);
+	card_pane.add(collection_pane, COLLECTION_LOADED_CARD);
+
+	tree_pane.add(workspace_pane, JSplitPane.LEFT);
+	tree_pane.add(card_pane, JSplitPane.RIGHT);
+	tree_pane.setDividerLocation(TREE_SIZE.width - 10);
+
+	file_pane.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
+	file_pane.setLayout(new BorderLayout());
+	file_pane.add(file_status, BorderLayout.CENTER);
+	file_pane.add(stop_action, BorderLayout.EAST);
+
+	progress_pane.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
+	progress_pane.setLayout(new BorderLayout());
+	progress_pane.add(progress_bar, BorderLayout.CENTER);
+
+	inner_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(10,10,10,10), BorderFactory.createLoweredBevelBorder()));
+	inner_pane.setLayout(new GridLayout(2,1));
+	inner_pane.add(file_pane);
+	inner_pane.add(progress_pane);
+
+	button_pane.add(new_folder);
+	button_pane.add(recycle_bin);
+
+	control_pane.setLayout(new BorderLayout());
+	control_pane.add(inner_pane, BorderLayout.CENTER);
+	control_pane.add(button_pane, BorderLayout.EAST);
+
+	this.setLayout(new BorderLayout());
+	this.add(tree_pane, BorderLayout.CENTER);
+	this.add(control_pane, BorderLayout.SOUTH);
+    }
+
+
+    /** Called to inform this control panel that it has just gained focus as an effect of the user clicking on its tab.
+     */
+    public void gainFocus()
+    {
+	// Add the collection tree and filter back into this pane
+	collection_scroll = new JScrollPane(collection_tree);
+	collection_pane.add(collection_scroll, BorderLayout.CENTER);
+	collection_pane.add(collection_filter, BorderLayout.SOUTH);
+    }
+
+
+    /** Called to inform this pane that it has just lost focus as an effect of the user clicking on another tab
+     */
+    public void loseFocus()
+    {
+	// Remove the collection tree and filter from this pane so it can be added to the Enrich pane
+	collection_pane.remove(collection_scroll);
+	collection_pane.remove(collection_filter);
+    }
+
+
+    /** Retrieve a list of the currently selected file records in the collection tree. */
+    private CollectionTreeNode[] getCollectionTreeSelection()
+    {
+	TreePath paths[] = collection_tree.getSelectionPaths();
+	CollectionTreeNode records[] = null;
+	if (paths != null) {
+	    records = new CollectionTreeNode[paths.length];
+	    for (int i = 0; i < records.length; i++) {
+		records[i] = (CollectionTreeNode) paths[i].getLastPathComponent();
+	    }
+	}
+	return records;
+    }
+
+    
+    /** Called whenever the detail mode changes to ensure the filters are at an appropriate level (ie only editable by those that understand regular expression matching)
+     * @param mode the mode level as an int
+     */
+    public void modeChanged(int mode) {
+	collection_filter.setEditable(mode > Configuration.LIBRARIAN_MODE);
+	workspace_filter.setEditable(mode > Configuration.LIBRARIAN_MODE);
+    }
+
+
+    /** Refresh this pane, depending on what has just happened (refresh_reason). */
+    public void refresh(int refresh_reason, boolean collection_loaded)
+    {
+	if (collection_loaded) {
+	    // Update collection tree
+	    if (refresh_reason == Gatherer.COLLECTION_OPENED) {
+		collection_tree.setModel(Gatherer.c_man.getCollectionTreeModel());
+	    }
+
+	    card_layout.show(card_pane, COLLECTION_LOADED_CARD);
+	}
+	else {
+	    // Update collection tree
+	    collection_tree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode("Error")));
+
+	    card_layout.show(card_pane, NO_COLLECTION_LOADED_CARD);
+	}
+
+	// File sizes turned on/off
+	if (refresh_reason == Gatherer.PREFERENCES_CHANGED) {
+	    refreshWorkspaceTree(DragTree.TREE_DISPLAY_CHANGED);
+	    refreshCollectionTree(DragTree.TREE_DISPLAY_CHANGED);
+	}
+
+	// Enable or disable the controls
+	collection_tree.setEnabled(collection_loaded);
+	collection_filter.setEnabled(collection_loaded);
+	new_folder.setEnabled(collection_loaded);
+    }
+
+
+    public void refreshCollectionTree(int refresh_reason) {
+	collection_tree.refresh(null);
+    }
+
+
+    public void refreshWorkspaceTree(int refresh_reason) {
+	workspace_tree.refresh(refresh_reason);
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/HelpFrame.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/HelpFrame.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/HelpFrame.java	(revision 13928)
@@ -0,0 +1,364 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Principal Author: John Thompson, NZDL Project, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.util.JarTools;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.XMLTools;
+import org.w3c.dom.*;
+
+
+/**
+ * This class provides a nice help facility. It is a separate frame that can be positioned
+ * as the user wishes, and provides a contents page and the help information.
+ * @author Michael Dewsnip, NZDL Project
+ */
+public class HelpFrame 
+    extends JFrame
+{
+    /** The size of the frame */
+    static private final Dimension SIZE = new Dimension(800, 560);
+
+    static private HelpFrame self = null;
+
+    /** The help view at the bottom of the frame. */
+    static private JEditorPane help_pane = null;
+    /** The help contents tree at the top of the frame. */
+    static private JTree help_contents_tree = null;
+    /** The help contents tree model. */
+    static private HelpContentsTreeModel help_contents_tree_model = null;
+    /** The split between the contents tree and the page view. */
+    static private JSplitPane split_pane = null;
+
+    public HelpFrame()
+    {
+	setDefaultCloseOperation(HIDE_ON_CLOSE);
+	setSize(SIZE);
+	setTitle(Dictionary.get("Help.Title"));
+
+	help_pane = new JEditorPane();
+	help_pane.setEditable(false);
+	help_pane.addHyperlinkListener(new HelpPaneHyperlinkListener());
+
+	HelpContentsTreeNode help_tree_root_node = new HelpContentsTreeNode(null, Dictionary.get("Help.Contents"));
+	help_contents_tree_model = new HelpContentsTreeModel(help_tree_root_node);
+	help_contents_tree = new JTree((DefaultTreeModel) help_contents_tree_model);
+	help_contents_tree.addTreeSelectionListener(new HelpContentsTreeSelectionListener());
+	help_contents_tree.setExpandsSelectedPaths(true);
+
+	// Creation
+	JPanel content_pane = (JPanel) this.getContentPane();
+	split_pane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
+	JScrollPane help_contents_tree_scroll = new JScrollPane(help_contents_tree);
+	JScrollPane help_pane_scroll = new JScrollPane(help_pane);
+
+	// Layout
+	split_pane.add(help_contents_tree_scroll, JSplitPane.LEFT);
+	split_pane.add(help_pane_scroll, JSplitPane.RIGHT);
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(split_pane, BorderLayout.CENTER);
+
+	// Center
+	Dimension screen_size = Toolkit.getDefaultToolkit().getScreenSize();
+	setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+
+	// Pretty corner icon
+	this.setIconImage(JarTools.getImage("gatherer_small.gif").getImage());
+
+	self = this;
+    }
+
+    public void destroy()
+    {
+	help_contents_tree = null;
+	help_pane = null;
+    }
+
+
+    /** Retrieve the relative file path to the language-specific help index xml file. */
+    private String getHelpFolder()
+    {
+	String help_folder = "help/" + Configuration.getLanguage() + "/";
+
+	// Applet case: get help files out of JAR file
+	if (Gatherer.isApplet && JarTools.getResource("/" + help_folder) != null) {
+	    return help_folder;
+	}
+
+	// Normal case: get help files out of GLI "help" folder
+	if (new File(help_folder).exists()) {
+	    return help_folder;
+	}
+
+	// Resort to English
+	return "help/" + StaticStrings.ENGLISH_LANGUAGE_STR  + "/";
+    }
+
+
+    private URL getURLForSection(String section_name)
+    {
+	// Form the path to the help file from the section name
+	if (section_name != null) {
+	    String help_file_path = getHelpFolder() + section_name + StaticStrings.HTM_FILE_EXTENSION;
+
+	    try {
+		// Applet case: get help file out of JAR file
+		if (Gatherer.isApplet) {
+		    return JarTools.getResource("/" + help_file_path);
+		}
+
+		// Normal case: get help file out of GLI "help" folder
+		return (new File(help_file_path)).toURL();
+	    }
+	    catch (Exception exception) {
+		DebugStream.printStackTrace(exception);
+	    }
+	}
+
+	return null;
+    }
+
+
+    static private void selectHelpContentsTreeNode(String section_name)
+    {
+	// Find the tree node with this section name, then select it
+	selectHelpContentsTreeNode(help_contents_tree_model.getHelpContentsTreeNodeNamed(section_name));
+    }
+
+
+    static private void selectHelpContentsTreeNode(HelpContentsTreeNode help_tree_node)
+    {
+	// Ensure the node in the help contents tree is selected and visible
+	TreePath help_tree_node_path = new TreePath(help_tree_node.getPath());
+	help_contents_tree.setSelectionPath(help_tree_node_path);
+	help_contents_tree.scrollPathToVisible(help_tree_node_path);
+    }
+
+
+    static public void setView(String section_name)
+    {
+	// Select the appropriate node in the help contents tree
+	selectHelpContentsTreeNode(section_name);
+
+	// Show the help page with the specified section name
+	self.showHelpPage(section_name);
+    }
+
+
+    private void showHelpPage(String section_name)
+    {
+	// Find the tree node with this section name, then show the page for the node
+	showHelpPage(getURLForSection(section_name));
+    }
+
+
+    private void showHelpPage(URL help_page_url)
+    {
+	// Display the selected page
+	if (help_page_url != null) {
+	    try {
+		help_pane.setPage(help_page_url);
+	    }
+	    catch (Exception exception) {
+		DebugStream.printStackTrace(exception);
+	    }
+	}
+
+	// Make the help frame visible
+	setVisible(true);
+	split_pane.setDividerLocation(0.4);
+    }
+
+
+    private class HelpContentsTreeModel
+	extends DefaultTreeModel
+    {
+	public HelpContentsTreeModel(MutableTreeNode help_tree_root_node)
+	{
+	    super(help_tree_root_node);
+
+	    // Load the XML help index file and build the contents structure from it
+	    try {
+		String help_index_file_path = getHelpFolder() + "help_index.xml";
+		Document document = XMLTools.parseXMLFile(help_index_file_path, true);
+
+		// Traverse the help hierarchy, building a tree representing its structure
+		Node document_node = document.getFirstChild();
+
+		// Add a help contents tree node for each major section
+		int section_number = 0;
+		NodeList children = document_node.getChildNodes();
+		for (int i = 0; i < children.getLength(); i++) {
+		    Node child = children.item(i);
+		    if (child.getNodeName().equals(StaticStrings.SECTION_ELEMENT)) {
+			section_number++;
+			buildHelpContentsTree(help_tree_root_node, section_number + StaticStrings.EMPTY_STR, child);
+		    }
+		}
+	    }
+	    catch (Exception exception) {
+		DebugStream.printStackTrace(exception);
+	    }
+	}
+
+
+	private void buildHelpContentsTree(MutableTreeNode parent, String pos, Node node)
+	{
+	    // Determine the section name
+	    String section_name = ((Element) node).getAttribute(StaticStrings.NAME_ATTRIBUTE);
+
+	    // Determine the section title
+	    String section_title = "";
+	    NodeList children = node.getChildNodes();
+	    for (int i = 0; i < children.getLength(); i++) {
+		Node child = children.item(i);
+		if (child.getNodeName().equals(StaticStrings.TITLE_ELEMENT)) {
+		    section_title = pos + ": ";
+		    if (child.getFirstChild() != null) {
+			section_title += child.getFirstChild().getNodeValue();
+		    }
+		}
+	    }
+
+	    // Add the node into the tree
+	    HelpContentsTreeNode help_tree_node = new HelpContentsTreeNode(section_name, section_title);
+	    insertNodeInto(help_tree_node, parent, parent.getChildCount());
+
+	    // Apply recursively to the children of this node
+	    int section_number = 0;
+	    for (int i = 0; i < children.getLength(); i++) {
+		Node child = children.item(i);
+		if (child.getNodeName().equals(StaticStrings.SECTION_ELEMENT)) {
+		    section_number++;
+		    buildHelpContentsTree(help_tree_node, pos + StaticStrings.STOP_CHARACTER + section_number, child);
+		}
+	    }
+	}
+
+
+	private HelpContentsTreeNode getHelpContentsTreeNodeNamed(String section_name)
+	{
+	    // Find the node with name matching section name, somewhere in the tree
+	    if (section_name != null) {
+		Enumeration descendants = ((DefaultMutableTreeNode) root).preorderEnumeration();
+		while (descendants.hasMoreElements()) {
+		    HelpContentsTreeNode help_tree_node = (HelpContentsTreeNode) descendants.nextElement();
+		    if (section_name.equals(help_tree_node.section_name)) {
+			return help_tree_node;
+		    }
+		}
+	    }
+
+	    // Couldn't be found, so just return the root (Contents) node
+	    return (HelpContentsTreeNode) root;
+	}
+    }
+
+
+    /** This listener is used to listen for selection changes in the contents tree, and
+     * to show the appropriate page as required.
+     */
+    private class HelpContentsTreeSelectionListener
+	implements TreeSelectionListener
+    {
+	/** Any implementation of <i>TreeSelectionListener</i> must include this method so we can be informed when the tree selection changes.
+	 * @param event A <strong>TreeSelectionEvent</strong> containing al the relevant information about the event itself.
+	 */
+	public void valueChanged(TreeSelectionEvent event)
+	{
+	    HelpContentsTreeNode help_tree_node = (HelpContentsTreeNode) event.getPath().getLastPathComponent();
+	    selectHelpContentsTreeNode(help_tree_node);
+	    showHelpPage(help_tree_node.section_name);
+	}
+    }
+
+
+    /** This class provides a wrapper around a <strong>DefaultMutableTreeNode</strong> which
+     * provides the ability to set an html page to be loaded when this node is selected.
+     */
+    private class HelpContentsTreeNode 
+	extends DefaultMutableTreeNode
+    {
+	/** The unique name of the section (matches the HTML filename) */
+	public String section_name = null;
+	/** The title to be displayed for this tree node. */
+	public String section_title = null;
+
+	public HelpContentsTreeNode(String section_name, String section_title)
+	{
+	    this.section_name = section_name;
+	    this.section_title = section_title;
+	}
+
+	public String toString()
+	{
+	    return section_title;
+	}
+    }
+
+
+    private class HelpPaneHyperlinkListener
+	implements HyperlinkListener
+    {
+	public void hyperlinkUpdate(HyperlinkEvent e)
+	{
+	    if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
+		// Determine which node in the help contents tree to select, then select it
+		String section_link = e.getURL().getFile();
+		if (section_link.endsWith(".htm")) {
+		    section_link = section_link.substring(section_link.lastIndexOf("/") + 1);
+		    section_link = section_link.substring(0, section_link.length() - ".htm".length());
+		    selectHelpContentsTreeNode(section_link);
+		}
+
+		// Change to the page specified by the link
+		showHelpPage(e.getURL());
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/LockFileDialog.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/LockFileDialog.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/LockFileDialog.java	(revision 13928)
@@ -0,0 +1,224 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.util.JarTools;
+import org.greenstone.gatherer.util.XMLTools;
+import org.w3c.dom.*;
+
+/** A lock file dialog is shown whenever GLI detects an existing lock on a collection it is trying to open. The user can look at the details provided with the dialog, and decide whether to 'steal' the lock or to cancel the loading. */
+public class LockFileDialog
+    extends ModalDialog {
+
+    private int choice;
+    private Document document;
+    private JButton cancel_button;
+    private JButton ok_button;
+    private LockFileDialog self;
+
+    static final public int NO_OPTION  = 0;
+    static final public int YES_OPTION = 1;
+
+    static final private Dimension LABEL_SIZE = new Dimension(100, 25);
+    static final private Dimension SIZE = new Dimension(500, 250);
+    static final private int ICON_SIZE = 30;
+
+    public LockFileDialog(JFrame parent, String name, File lock_file) {
+	super(parent, Dictionary.get("LockFileDialog.Title"), true);
+	setSize(SIZE);
+	setJMenuBar(new SimpleMenuBar("openingacollection"));
+	this.self = this;
+
+	// Parse the lock file
+	document = XMLTools.parseXMLFile(lock_file);
+
+	// Creation
+	JPanel content_pane = (JPanel) getContentPane();
+	JPanel upper_pane = new JPanel();
+	ImageIcon icon = JarTools.getImage("lcolicn.gif");
+	ImageIcon scaled_icon = new ImageIcon(icon.getImage().getScaledInstance(ICON_SIZE, ICON_SIZE, Image.SCALE_DEFAULT));
+	JLabel icon_label = new JLabel(scaled_icon);
+	JPanel title_pane = new JPanel();
+	JLabel title_one_label = new JLabel(Dictionary.get("General.Warning"));
+	
+	JTextArea title_two_textarea = new JTextArea(Dictionary.get("LockFileDialog.Lockfile_Message_One"));
+	title_two_textarea.setEditable(false);
+	title_two_textarea.setLineWrap(true);
+	title_two_textarea.setOpaque(false);
+	title_two_textarea.setRows(3);
+	title_two_textarea.setWrapStyleWord(true);
+	
+	JPanel central_pane = new JPanel();
+
+	JPanel name_pane = new JPanel();
+	JLabel name_label = new JLabel(Dictionary.get("LockFileDialog.Name"));
+	name_label.setPreferredSize(LABEL_SIZE);
+	
+	JTextField name_field = new JTextField(name);
+	name_field.setEditable(false);
+	name_field.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+
+	JPanel person_pane = new JPanel();
+	JLabel person_label = new JLabel(Dictionary.get("LockFileDialog.User"));
+	person_label.setPreferredSize(LABEL_SIZE);
+	
+	JTextField person_field = new JTextField(getValue("User"));
+	person_field.setEditable(false);
+	person_field.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+
+	JPanel machine_pane = new JPanel();
+	JLabel machine_label = new JLabel(Dictionary.get("LockFileDialog.Machine"));
+	machine_label.setPreferredSize(LABEL_SIZE);
+	
+	JTextField machine_field = new JTextField(getValue("Machine"));
+	machine_field.setEditable(false);
+	machine_field.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+
+	JPanel created_pane = new JPanel();
+	JLabel created_label = new JLabel(Dictionary.get("LockFileDialog.Date"));
+	created_label.setPreferredSize(LABEL_SIZE);
+	
+	JTextField created_field = new JTextField(getValue("Date"));
+	created_field.setEditable(false);
+	created_field.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+
+	JLabel central_label = new JLabel(Dictionary.get("LockFileDialog.Lockfile_Message_Two"));
+	
+	JPanel button_pane = new JPanel();
+	ok_button = new GLIButton(Dictionary.get("General.OK"), Dictionary.get("LockFileDialog.OK_Tooltip"));
+	
+	cancel_button = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("LockFileDialog.Cancel_Tooltip"));
+	
+	// Connection
+	ok_button.addActionListener(new MyActionListener());
+	cancel_button.addActionListener(new MyActionListener());
+
+	// Layout
+	icon_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,10));
+
+	title_pane.setLayout(new BorderLayout());
+	title_pane.add(title_one_label, BorderLayout.NORTH);
+	title_pane.add(title_two_textarea, BorderLayout.CENTER);
+
+	upper_pane.setLayout(new BorderLayout());
+	upper_pane.add(icon_label, BorderLayout.WEST);
+	upper_pane.add(title_pane, BorderLayout.CENTER);
+
+	name_pane.setLayout(new BorderLayout());
+	name_pane.add(name_label, BorderLayout.WEST);
+	name_pane.add(name_field, BorderLayout.CENTER);
+
+	person_pane.setLayout(new BorderLayout());
+	person_pane.add(person_label, BorderLayout.WEST);
+	person_pane.add(person_field, BorderLayout.CENTER);
+
+	machine_pane.setLayout(new BorderLayout());
+	machine_pane.add(machine_label, BorderLayout.WEST);
+	machine_pane.add(machine_field, BorderLayout.CENTER);
+
+	created_pane.setLayout(new BorderLayout());
+	created_pane.add(created_label, BorderLayout.WEST);
+	created_pane.add(created_field, BorderLayout.CENTER);
+
+	central_pane.setLayout(new GridLayout(5,1,0,5));
+	central_pane.add(name_pane);
+	central_pane.add(person_pane);
+	central_pane.add(machine_pane);
+	central_pane.add(created_pane);
+	central_pane.add(central_label);
+
+	button_pane.setLayout(new GridLayout(1,2,5,0));
+	button_pane.add(ok_button);
+	button_pane.add(cancel_button);
+
+	content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(upper_pane, BorderLayout.NORTH);
+	content_pane.add(central_pane, BorderLayout.CENTER);
+	content_pane.add(button_pane, BorderLayout.SOUTH);
+
+	// Display
+	if (parent != null) {
+	    Rectangle frame_bounds = parent.getBounds();
+	    setLocation(frame_bounds.x + (frame_bounds.width - SIZE.width) / 2, frame_bounds.y + (frame_bounds.height - SIZE.height) / 2);
+	}
+	else {
+	    Dimension screen_size = Toolkit.getDefaultToolkit().getScreenSize();
+	    setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+	}
+    }
+
+    public int getChoice() {
+	setVisible(true);
+	return choice;
+    }
+
+    private String getValue(String name) {
+	String value = "";
+	if(document != null) {
+	    try {
+		Element value_element = (Element) XMLTools.getNodeFromNamed(document.getDocumentElement(), name);
+		value = XMLTools.getValue(value_element);
+	    }
+	    catch (Exception error) {
+	    }
+	}
+	else {
+	    value = Dictionary.get("LockFileDialog.Error");
+	}
+	return value;
+    }
+
+    private class MyActionListener
+	implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    if(event.getSource() == ok_button) {
+		choice = YES_OPTION;
+	    }
+	    else {
+		choice = NO_OPTION;
+	    }
+	    self.dispose();
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/MenuBar.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/MenuBar.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/MenuBar.java	(revision 13928)
@@ -0,0 +1,255 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.util.JarTools;
+
+/** The menu bar for the Gatherer main GUI. 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.2
+ */
+public class MenuBar
+    extends JMenuBar
+{
+    static public ImageIcon BLANK_ICON = JarTools.getImage("blank.gif");
+    static public ImageIcon HELP_ICON = JarTools.getImage("help.gif");
+
+    /** The icon to be displayed alongside the context choosen help file. */
+    private int current_tab          = -1;
+
+    private JMenu file               = null;
+    private JMenu edit               = null;
+    public JMenu help                = null;
+    public JMenuItem file_associations;
+    public JMenuItem file_cdimage    = null;
+    public JMenuItem file_close      = null;
+    public JMenuItem file_delete     = null;
+    public JMenuItem file_exit       = null;
+    public JMenuItem file_exportas   = null;
+    public JMenuItem file_new        = null;
+    public JMenuItem file_open       = null;
+    public JMenuItem file_options    = null;
+    public JMenuItem file_save       = null;
+    public JMenuItem edit_copy;
+    public JMenuItem edit_cut;
+    public JMenuItem edit_paste;
+    public JMenuItem help_general;
+    public JMenuItem help_download;
+    public JMenuItem help_gather;
+    public JMenuItem help_enrich;
+    public JMenuItem help_design;
+    public JMenuItem help_create;
+    public JMenuItem help_format;
+    public JMenuItem help_about;
+
+
+    public MenuBar(MenuListener menu_listener)
+    {
+	file = new JMenu();
+	file.setText(Dictionary.get("Menu.File"));
+	
+	file_associations = new JMenuItem(Dictionary.get("Menu.File_Associations"));
+	file_associations.addActionListener(Gatherer.g_man);	  
+	
+	file_cdimage = new JMenuItem(Dictionary.get("Menu.File_CDimage"));
+	file_cdimage.addActionListener(Gatherer.g_man);
+	file_cdimage.setEnabled(!Gatherer.isGsdlRemote);
+	
+	file_close = new JMenuItem(Dictionary.get("Menu.File_Close"));
+	file_close.addActionListener(Gatherer.g_man);
+	file_close.setEnabled(false);
+	
+	file_delete = new JMenuItem(Dictionary.get("Menu.File_Delete"));
+	file_delete.addActionListener(Gatherer.g_man);
+	
+	file_exit = new JMenuItem(Dictionary.get("Menu.File_Exit"));
+	file_exit.addActionListener(Gatherer.g_man);
+	
+	file_exportas = new JMenuItem(Dictionary.get("Menu.File_ExportAs"));
+	file_exportas.addActionListener(Gatherer.g_man);
+	file_exportas.setEnabled((!Gatherer.isGsdlRemote && !Gatherer.GS3)); 
+      	
+	file_new = new JMenuItem(Dictionary.get("Menu.File_New"));
+	file_new.addActionListener(Gatherer.g_man);
+	
+	file_open = new JMenuItem(Dictionary.get("Menu.File_Open"));
+	file_open.addActionListener(Gatherer.g_man);
+	
+	file_options = new JMenuItem(Dictionary.get("Menu.File_Options"));
+	file_options.addActionListener(Gatherer.g_man);
+	
+	file_save = new JMenuItem(Dictionary.get("Menu.File_Save"));
+	file_save.addActionListener(Gatherer.g_man);
+	file_save.setEnabled(false);
+	
+	// Layout (file menu)
+	file.add(file_new);
+	file.add(file_open);
+	file.add(file_save);
+	file.add(file_close);
+	file.add(new JSeparator());
+	file.add(file_delete);
+	file.add(file_exportas);
+	file.add(file_cdimage);
+	file.add(new JSeparator());
+	file.add(file_associations);
+	file.add(file_options);
+	file.add(new JSeparator());
+	file.add(file_exit);
+
+	// Edit menu
+	edit = new JMenu();
+	edit.setText(Dictionary.get("Menu.Edit"));
+			  
+	edit_cut = new JMenuItem(Dictionary.get("Menu.Edit_Cut"));
+	edit_cut.addActionListener(Gatherer.g_man);
+	
+	edit_copy = new JMenuItem(Dictionary.get("Menu.Edit_Copy"));
+	edit_copy.addActionListener(Gatherer.g_man);
+	
+	edit_paste = new JMenuItem(Dictionary.get("Menu.Edit_Paste"));
+	edit_paste.addActionListener(Gatherer.g_man);
+	
+	// Layout (edit menu)
+	edit.add(edit_cut);
+	edit.add(edit_copy);
+	edit.add(edit_paste);
+
+	// Help menu
+	help = new JMenu();
+	help.setIcon(HELP_ICON);
+	help.setText(Dictionary.get("Menu.Help"));
+	
+	help_general = new JMenuItem(Dictionary.get("Source.General"));
+	help_general.addActionListener(Gatherer.g_man);
+	
+	help_download = new JMenuItem(Dictionary.get("GUI.Download"), BLANK_ICON);
+	help_download.addActionListener(Gatherer.g_man);
+	
+	help_gather = new JMenuItem(Dictionary.get("GUI.Gather"), BLANK_ICON);
+	help_gather.addActionListener(Gatherer.g_man);
+	
+	help_enrich = new JMenuItem(Dictionary.get("GUI.Enrich"), BLANK_ICON);
+	help_enrich.addActionListener(Gatherer.g_man);
+	
+	help_design = new JMenuItem(Dictionary.get("GUI.Design"), BLANK_ICON);
+	help_design.addActionListener(Gatherer.g_man);
+	
+	help_create = new JMenuItem(Dictionary.get("GUI.Create"), BLANK_ICON);
+	help_create.addActionListener(Gatherer.g_man);
+	
+	help_format = new JMenuItem(Dictionary.get("GUI.Format"), BLANK_ICON);
+	help_format.addActionListener(Gatherer.g_man);
+	
+	help_about = new JMenuItem(Dictionary.get("Menu.Help_About"));
+	help_about.addActionListener(Gatherer.g_man);
+	
+	// Layout (help menu)
+	help.add(help_general);
+	help.add(new JSeparator());
+	if (Configuration.get("workflow.download", true)) {
+	    help.add(help_download);
+	}
+	if (Configuration.get("workflow.gather", true)) {
+	    help.add(help_gather);
+	}
+	if (Configuration.get("workflow.enrich", true)) {
+	    help.add(help_enrich);
+	}
+	if (Configuration.get("workflow.design", true)) {
+	    help.add(help_design);
+	}
+	if (Configuration.get("workflow.create", true)) {
+	    help.add(help_create);
+	}
+	if (Configuration.get("workflow.format", true)) {
+	    help.add(help_format);
+	}
+	help.add(new JSeparator());
+	help.add(help_about);
+
+	// Layout (menu bar)
+	this.add(file);
+	this.add(Box.createHorizontalStrut(15));
+	this.add(edit);
+	this.add(Box.createHorizontalGlue());
+	this.add(help);
+    }
+
+    /** Once a quit has been requested by the user, prevent any further menu selections. */
+    public void exit() {
+	file.setEnabled(false);
+	edit.setEnabled(false);
+	help.setEnabled(false);
+    }
+
+    public void refresh(int refresh_reason, boolean ready)
+    {
+	file_close.setEnabled(ready);
+	file_save.setEnabled(ready);
+    }
+
+
+    /** In order to provide context aware help advice we keep track of which
+     *  tab the user has open, and then highlight that help menu item with
+     *  separators.
+     *  @param tab_index The index of the selected tab (0-7).
+     */
+    public void tabSelected(int tab_index) {
+	JMenuItem selected;
+	if(current_tab != -1) {
+	    // Remove the image
+	    selected = help.getItem(current_tab);
+	    if(selected != null) {
+		selected.setIcon(BLANK_ICON);
+	    }
+	}
+	current_tab = tab_index + 2;
+	selected = help.getItem(current_tab);
+	if(selected != null) {
+	    selected.setIcon(HELP_ICON);
+	}
+	selected = null;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/MetadataElementListCellRenderer.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/MetadataElementListCellRenderer.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/MetadataElementListCellRenderer.java	(revision 13928)
@@ -0,0 +1,82 @@
+package org.greenstone.gatherer.gui;
+
+
+import java.awt.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.metadata.MetadataElement;
+import org.greenstone.gatherer.metadata.MetadataTools;
+
+
+public class MetadataElementListCellRenderer
+    extends JLabel
+    implements ListCellRenderer
+{
+    private byte previous_directionality = Character.DIRECTIONALITY_UNDEFINED;
+
+
+    public byte getDirectionality()
+    {
+	if (previous_directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT || previous_directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC || previous_directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING || previous_directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE) {
+	    return Character.DIRECTIONALITY_RIGHT_TO_LEFT;
+	}
+	else {
+	    return Character.DIRECTIONALITY_LEFT_TO_RIGHT;
+	}
+    }
+
+
+    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
+    {
+	if (value instanceof MetadataElement) {
+	    MetadataElement metadata_element = (MetadataElement) value;
+
+	    String interface_language_code = Configuration.getLanguage();
+	    String metadata_element_display = "";
+
+	    String metadata_element_display_name = metadata_element.getDisplayName();
+	    if (metadata_element_display_name != null) {
+		metadata_element_display += metadata_element_display_name + ":";
+	    }
+	    else {
+		metadata_element_display += metadata_element.getName() + ":";
+	    }
+
+	    String metadata_element_definition = MetadataTools.getMetadataElementAttribute(metadata_element, "definition", interface_language_code, "en");
+	    if (metadata_element_definition != null) {
+		metadata_element_display += " " + metadata_element_definition;
+	    }
+
+// 	    String metadata_element_comment = MetadataTools.getMetadataElementAttribute(metadata_element, "comment", interface_language_code, "en");
+// 	    if (metadata_element_comment != null) {
+// 		metadata_element_display += " " + metadata_element_comment;
+// 	    }
+
+	    setText(metadata_element_display);
+
+// 	    // Determine if the text should be left aligned or right aligned
+// 	    String text = metadata_element_display;
+// 	    int text_index = 0;
+// 	    byte directionality = Character.DIRECTIONALITY_UNDEFINED;
+// 	    while (directionality == Character.DIRECTIONALITY_UNDEFINED && text_index < text.length()) {
+// 		directionality = Character.getDirectionality(text.charAt(text_index));
+// 		text_index++;
+// 	    }
+// 	    if (directionality != previous_directionality) {
+// 		previous_directionality = directionality;
+// 		if (directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT || directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC || directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING || directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE) {
+// 		    setHorizontalAlignment(JLabel.TRAILING);
+// 		    setHorizontalTextPosition(JLabel.TRAILING);
+// 		    setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
+// 		}
+// 		else {
+// 		    setHorizontalAlignment(JLabel.LEADING);
+// 		    setHorizontalTextPosition(JLabel.LEADING);
+// 		    setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
+// 		}
+// 	    }
+	}
+
+	return this;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/MetadataImportMappingPrompt.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/MetadataImportMappingPrompt.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/MetadataImportMappingPrompt.java	(revision 13928)
@@ -0,0 +1,178 @@
+package org.greenstone.gatherer.gui;
+
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.metadata.MetadataElement;
+import org.greenstone.gatherer.metadata.MetadataSet;
+import org.greenstone.gatherer.metadata.MetadataSetManager;
+import org.greenstone.gatherer.metadata.MetadataTools;
+
+
+public class MetadataImportMappingPrompt
+    implements ActionListener
+{
+    final static public int ADD_BUTTON_PRESSED = 0;
+    final static public int MERGE_BUTTON_PRESSED = 1;
+    final static public int IGNORE_BUTTON_PRESSED = 2;
+    final static private Dimension DIALOG_SIZE = new Dimension(640, 180);
+
+    private int result;
+    private String metadata_element_name_full = null;
+    private GComboBox metadata_sets_combobox = null;
+    private GComboBox metadata_elements_combobox = null;
+    private JButton add_button = null;
+    private JButton merge_button = null;
+    private JButton ignore_button = null;
+    private JDialog on_screen = null;
+
+
+    public MetadataImportMappingPrompt(String metadata_element_name_full)
+    {
+	this.metadata_element_name_full = metadata_element_name_full;
+
+	// Construction and configuration
+	JDialog dialog = new ModalDialog(Gatherer.g_man);
+	dialog.setModal(true);
+	dialog.setSize(DIALOG_SIZE);
+	dialog.setJMenuBar(new SimpleMenuBar("importingpreviouslyassignedmetadata"));
+	dialog.setTitle(Dictionary.get("MIMP.Title"));
+	
+	// All the loaded metadata sets except the extracted metadata set are applicable
+	ArrayList metadata_sets = MetadataSetManager.getMetadataSets();
+	for (int i = metadata_sets.size() - 1; i >= 0; i--) {
+	    if (((MetadataSet) metadata_sets.get(i)).getNamespace().equals(MetadataSetManager.EXTRACTED_METADATA_NAMESPACE)) {
+		metadata_sets.remove(i);
+	    }
+	}
+
+  	add_button = new GLIButton(Dictionary.get("MIMP.Add"), Dictionary.get("MIMP.Add_Tooltip"));
+ 	add_button.addActionListener(this);
+  	
+  	merge_button = new GLIButton(Dictionary.get("MIMP.Merge"), Dictionary.get("MIMP.Merge_Tooltip"));
+  	merge_button.addActionListener(this);
+  	merge_button.setEnabled(true);
+  	
+  	ignore_button = new GLIButton(Dictionary.get("MIMP.Ignore"), Dictionary.get("MIMP.Ignore_Tooltip"));
+  	ignore_button.addActionListener(this);
+  	ignore_button.setEnabled(true);
+  	
+	// !! Need to add instructions: "MIMP.Instructions", args: source elem
+	metadata_elements_combobox = new GComboBox();
+
+	metadata_sets_combobox = new GComboBox(metadata_sets);
+	metadata_sets_combobox.addActionListener(new MetadataSetListSelectionListener());
+	metadata_sets_combobox.setSelectedIndex(0);
+
+	// Layout
+	JPanel left_pane = new JPanel();
+	left_pane.setLayout(new GridLayout(3,1));
+	left_pane.add(new JLabel(Dictionary.get("MIMP.Source_Element")));
+	left_pane.add(new JLabel(Dictionary.get("MIMP.Target_Set")));
+	left_pane.add(new JLabel(Dictionary.get("MIMP.Target_Element")));
+
+	JPanel right_pane = new JPanel();
+	right_pane.setLayout(new GridLayout(3,1));
+	right_pane.add(new JLabel(metadata_element_name_full));
+	right_pane.add(metadata_sets_combobox);
+	right_pane.add(metadata_elements_combobox);
+
+	JPanel button_pane = new JPanel();
+	button_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
+	button_pane.setLayout(new GridLayout(1,3));
+	button_pane.add(add_button);
+	button_pane.add(merge_button);
+	button_pane.add(ignore_button);
+
+	JPanel content_pane = (JPanel) dialog.getContentPane();
+	content_pane.setLayout(new BorderLayout());
+	content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	content_pane.add(left_pane, BorderLayout.WEST);
+	content_pane.add(right_pane, BorderLayout.CENTER);
+	content_pane.add(button_pane, BorderLayout.SOUTH);
+
+	// Display
+	Dimension screen_size = Configuration.screen_size;
+	dialog.setLocation((screen_size.width - DIALOG_SIZE.width) / 2, (screen_size.height - DIALOG_SIZE.height) / 2);
+	on_screen = dialog;
+	on_screen.setVisible(true); // Blocks until hidden.
+	on_screen.dispose();
+	on_screen = null;
+    }
+
+
+    /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured.
+     * @param event An <strong>ActionEvent</strong> containing information gatherer when this event occured.
+     */
+    public void actionPerformed(ActionEvent event)
+    {
+	Object esrc = event.getSource();
+
+	if (esrc == add_button) {
+	    result = ADD_BUTTON_PRESSED;
+	}
+	if (esrc == merge_button) {
+	    result = MERGE_BUTTON_PRESSED;
+	}
+	if (esrc == ignore_button) {
+	    result = IGNORE_BUTTON_PRESSED;
+	}
+
+	on_screen.setVisible(false);
+    }
+
+
+    public MetadataElement getSelectedMetadataElement()
+    {
+	return (MetadataElement) metadata_elements_combobox.getSelectedItem();
+    }
+
+
+    public MetadataSet getSelectedMetadataSet()
+    {
+	return (MetadataSet) metadata_sets_combobox.getSelectedItem();
+    }
+
+
+    public int getResult()
+    {
+	return result;
+    }
+
+
+    private class MetadataSetListSelectionListener
+	implements ActionListener
+    {
+	public void actionPerformed(ActionEvent event)
+	{
+	    boolean enable_add_button = true;
+	    String metadata_element_name = MetadataTools.getMetadataElementName(metadata_element_name_full);
+
+	    MetadataSet metadata_set = (MetadataSet) metadata_sets_combobox.getSelectedItem();
+	    ArrayList metadata_elements = metadata_set.getMetadataSetElements();
+
+	    metadata_elements_combobox.removeAllItems();
+	    for (int i = 0; i < metadata_elements.size(); i++) {
+		MetadataElement metadata_element = (MetadataElement) metadata_elements.get(i);
+		metadata_elements_combobox.addItem(metadata_element);
+		if (metadata_element.getName().equals(metadata_element_name)) {
+		    metadata_elements_combobox.setSelectedIndex(i);
+		    enable_add_button = false;
+		}
+	    }
+
+	    add_button.setEnabled(enable_add_button);
+
+	    // are there any elements in the set? if not (e.g. with exp set),
+	    // disable merge
+	    if (metadata_elements.size()==0) {
+		merge_button.setEnabled(false);
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/MetadataSetDialog.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/MetadataSetDialog.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/MetadataSetDialog.java	(revision 13928)
@@ -0,0 +1,411 @@
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import java.util.ArrayList;
+import java.util.Vector;
+import java.io.File;
+import java.util.Observer;
+import java.util.Observable;
+
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.DynamicListModel;
+import org.greenstone.gatherer.metadata.MetadataSet;
+import org.greenstone.gatherer.metadata.MetadataSetManager;
+import org.greenstone.gatherer.gems.*;
+
+public class MetadataSetDialog 
+    extends ModalDialog {
+
+    static private Dimension SIZE = new Dimension(600, 300);
+    static private Dimension ADD_SIZE = new Dimension(600, 500);
+    
+    private ArrayList current_metadata_sets;
+    private DynamicListModel current_metadata_model;
+
+    private JButton add_button = null;
+    private JButton edit_button = null;
+    private JButton remove_button = null;
+
+    private JButton close_button = null;
+    
+    private JList current_set_list = null;
+    private MetadataSetDialog set_dialog = null;
+    private boolean sets_changed = false;
+
+    private GEMS gems = null;
+    
+    public MetadataSetDialog() {
+	super(Gatherer.g_man, true);
+	set_dialog = this;
+	
+	setJMenuBar(new SimpleMenuBar("selectingmetadatasets"));
+	setSize(SIZE);
+	setTitle(Dictionary.get("MetadataSetDialog.Title"));
+	
+	current_metadata_sets = MetadataSetManager.getMetadataSets();
+	current_metadata_model = new DynamicListModel();
+	
+	int current_size = current_metadata_sets.size();
+	for (int i=0; i<current_size; i++) {
+	    current_metadata_model.addElement(current_metadata_sets.get(i));
+	}
+	JPanel content_pane = (JPanel) getContentPane();
+        content_pane.setOpaque(true);
+	
+	JLabel current_metadata_sets_label = new JLabel(Dictionary.get("MetadataSetDialog.Current_Sets"));
+	current_metadata_sets_label.setOpaque(true);
+	current_set_list = new JList(current_metadata_model);
+	current_set_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+
+	JPanel button_pane = new JPanel();
+	add_button = new GLIButton(Dictionary.get("MetadataSetDialog.Add"), Dictionary.get("MetadataSetDialog.Add_Tooltip"));
+	add_button.setEnabled(true);
+	
+	edit_button = new GLIButton(Dictionary.get("MetadataSetDialog.Edit"), Dictionary.get("MetadataSetDialog.Edit_Tooltip"));
+	edit_button.setEnabled(false);
+	
+	remove_button = new GLIButton(Dictionary.get("MetadataSetDialog.Remove"), Dictionary.get("MetadataSetDialog.Remove_Tooltip"));
+	remove_button.setEnabled(false);
+	
+	close_button = new GLIButton(Dictionary.get("General.Close"), Dictionary.get("General.Close_Tooltip"));
+	close_button.setEnabled(true);
+
+
+	// Add listeners
+	add_button.addActionListener(new AddButtonListener());
+	edit_button.addActionListener(new EditButtonListener());
+	remove_button.addActionListener(new RemoveButtonListener());
+	close_button.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent event) {
+		    set_dialog.dispose();
+		}
+	    });
+	current_set_list.addListSelectionListener(new MetadataSetListSelectionListener());
+
+	button_pane.setLayout(new GridLayout(2,3));
+	button_pane.add(add_button);
+	button_pane.add(edit_button);
+	button_pane.add(remove_button);
+	button_pane.add(new JPanel());
+	button_pane.add(new JPanel());
+	button_pane.add(close_button);
+
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(current_metadata_sets_label, BorderLayout.NORTH);
+	content_pane.add(new JScrollPane(current_set_list), BorderLayout.CENTER);
+	content_pane.add(button_pane, BorderLayout.SOUTH);
+	
+	// Show
+	Dimension screen_size = Configuration.screen_size;
+	setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+	setVisible(true);
+
+    }
+
+    public boolean setsChanged() {
+	return sets_changed;
+    }
+    
+    private class AddButtonListener
+	implements ActionListener {
+
+	public void actionPerformed(ActionEvent event) {
+	    AddMetadataSetPrompt amsp = new AddMetadataSetPrompt();
+	    if (!amsp.isCancelled()) {
+		sets_changed = true;
+	    }
+	}
+    }
+    
+    private class EditButtonListener
+	implements ActionListener, GEMSListener {
+	
+	public void actionPerformed(ActionEvent event) {
+	    // do a pop up message
+	    MetadataSet metadata_set = (MetadataSet) current_set_list.getSelectedValue();
+	    String metadata_path = metadata_set.getMetadataSetFile().toString();
+	    if (gems == null){
+		gems = new GEMS(Configuration.gsdl_path,Configuration.gsdl3_path,"", false, false);
+		gems.addGEMSListener(this);
+	    }
+	    gems.displayMetadataSet(metadata_path);
+	}
+
+	public void gemsIsClosed()
+	{
+	    // We assume that the selected metadata was edited, so reload it and remember to update the table
+	    MetadataSet edited_metadata_set = (MetadataSet) current_set_list.getSelectedValue();
+	    MetadataSetManager.unloadMetadataSet(edited_metadata_set);
+	    MetadataSetManager.loadMetadataSet(edited_metadata_set.getMetadataSetFile());
+	    sets_changed = true;
+	}
+    }
+
+    private class RemoveButtonListener
+	implements ActionListener {
+	
+	public void actionPerformed(ActionEvent event) {
+	    MetadataSet metadata_set = (MetadataSet) current_set_list.getSelectedValue();
+	    current_metadata_model.removeElement(metadata_set);
+	    Gatherer.c_man.removeMetadataSet(metadata_set);
+	    sets_changed = true;
+	    
+	}
+
+    }
+
+
+    private class MetadataSetListSelectionListener
+	implements ListSelectionListener {
+	
+	public void valueChanged(ListSelectionEvent event)
+	{
+	    // Wait until we get a stable event
+	    if (event.getValueIsAdjusting()) {
+		return;
+	    }
+
+	    // Now we can process it
+	    if (!current_set_list.isSelectionEmpty() && !((MetadataSet)current_set_list.getSelectedValue()).getNamespace().equals(MetadataSetManager.EXTRACTED_METADATA_NAMESPACE)) {
+		remove_button.setEnabled(true);
+		edit_button.setEnabled(true);
+	    }
+	    else { 
+		remove_button.setEnabled(false);
+		edit_button.setEnabled(false);
+	    }
+	    
+	}
+	
+    }
+
+    private class AddMetadataSetPrompt
+	extends ModalDialog implements GEMSListener{
+	
+	private JDialog add_set_dialog;
+	private boolean cancelled = false;
+	
+	private JList elements_list;
+	private JList available_sets_list;
+
+	private JButton add_button;
+
+	private JButton new_button;
+     
+	private  GEMSListener self;
+
+	public AddMetadataSetPrompt() {
+	    super(Gatherer.g_man, true);
+	    add_set_dialog = this;
+	    setModal(true);
+	    setJMenuBar(new SimpleMenuBar("choosingmetadatasets"));
+	    setSize(ADD_SIZE);
+	    setTitle(Dictionary.get("MetadataSetDialog.Add_Title"));
+	    self = this;
+	   
+
+	    JPanel center_pane = new JPanel();
+	    JPanel sets_pane = new JPanel();
+	    JLabel sets_label = new JLabel(Dictionary.get("MetadataSetDialog.Available_Sets"));
+	    sets_label.setOpaque(false);
+	    
+	    available_sets_list = new JList(getValidSetModel());
+	    available_sets_list.addListSelectionListener(new AvailableSetListSelectionListener());
+	    available_sets_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+	    JPanel elements_pane = new JPanel();
+	    JLabel elements_label = new JLabel(Dictionary.get("MetadataSetDialog.Elements"));
+	    
+	    elements_list = new JList();
+	    elements_list.setCellRenderer(new MetadataElementListCellRenderer());
+	    elements_list.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+	    elements_list.setForeground(Configuration.getColor("coloring.collection_tree_foreground", false));
+	    elements_list.setSelectionBackground(Configuration.getColor("coloring.collection_tree_background", false));
+	    elements_list.setSelectionForeground(Configuration.getColor("coloring.collection_tree_foreground", false));
+	    
+	    JPanel button_pane = new JPanel();
+	    add_button = new GLIButton(Dictionary.get("MetadataSetDialog.Add_Set"), Dictionary.get("MetadataSetDialog.Add_Set_Tooltip"));
+	    add_button.setEnabled(false);
+          
+	    new_button = new GLIButton(Dictionary.get("MetadataSetDialog.New_Set"), Dictionary.get("MetadataSetDialog.New_Set_Tooltip"));
+	   
+	    JButton browse_button = new GLIButton(Dictionary.get("MetadataSetDialog.Browse"), Dictionary.get("MetadataSetDialog.Browse_Tooltip"));
+	    browse_button.setEnabled(true);
+	    JButton cancel_button = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("General.Pure_Cancel_Tooltip"));
+	    
+	    add_button.addActionListener(new AddSetActionListener());
+	    browse_button.addActionListener(new BrowseActionListener());
+	    cancel_button.addActionListener(new ActionListener() {
+		    public void actionPerformed(ActionEvent event) {
+			cancelled = true;
+			if (gems != null) {
+			    gems.removeGEMSListener(self);
+			}
+			add_set_dialog.dispose();
+		    }
+		});
+	    
+	    new_button.addActionListener(new ActionListener() {
+		    public void actionPerformed(ActionEvent event) {
+			if (gems == null) {
+			    gems = new GEMS(Configuration.gsdl_path, Configuration.gsdl3_path, "", false, false);
+			}
+			gems.newMetadataSet();
+			gems.addGEMSListener(self);
+		    }
+		});
+            	    	    
+
+	    // Layout
+	    sets_pane.setLayout(new BorderLayout());
+	    sets_pane.add(sets_label, BorderLayout.NORTH);
+	    sets_pane.add(new JScrollPane(available_sets_list), BorderLayout.CENTER);
+
+	    elements_pane.setLayout(new BorderLayout());
+	    elements_pane.add(elements_label, BorderLayout.NORTH);
+	    elements_pane.add(new JScrollPane(elements_list), BorderLayout.CENTER);
+
+	    center_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	    center_pane.setLayout(new GridLayout(2,1,0,5));
+	    center_pane.add(sets_pane);
+	    center_pane.add(elements_pane);
+	    
+	    button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	    button_pane.setLayout(new GridLayout(1,4,5,0));
+	    button_pane.add(add_button);
+	    button_pane.add(new_button); 
+	    button_pane.add(browse_button);
+	    button_pane.add(cancel_button);
+	    
+	    JPanel content_pane = (JPanel) getContentPane();
+	    content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	    content_pane.setLayout(new BorderLayout());
+	    content_pane.add(center_pane, BorderLayout.CENTER);
+	    content_pane.add(button_pane, BorderLayout.SOUTH);
+
+	    // Show
+	    Dimension screen_size = Configuration.screen_size;
+	    setLocation((screen_size.width - ADD_SIZE.width) / 2, (screen_size.height - ADD_SIZE.height) / 2);
+	    setVisible(true);
+	    
+
+	    
+	}
+	
+	public DynamicListModel getValidSetModel(){
+	    // Show the metadata sets (except extracted, exploded, and currently assigned sets) in the GLI metadata folder
+	    ArrayList all_metadata_sets = MetadataSetManager.listMetadataSets(new File(Gatherer.getGLIMetadataDirectoryPath()));
+	    ArrayList current_metadata_sets = MetadataSetManager.getMetadataSets();
+	    DynamicListModel valid_sets_model = new DynamicListModel();
+	    for (int i=0; i<all_metadata_sets.size(); i++) {
+		 MetadataSet set = (MetadataSet) all_metadata_sets.get(i);
+		 if (set.getNamespace().equals(MetadataSetManager.EXTRACTED_METADATA_NAMESPACE) || set.getNamespace().equals(MetadataSetManager.EXPLODED_METADATA_NAMESPACE)) {
+		    continue;
+		 }
+		// indexOf uses the equals() method, which for MetadataSets compares the toString() output, not the objects
+		 if (current_metadata_sets.indexOf(set)!=-1) {
+		    continue;
+		 }
+		 valid_sets_model.addElement(set);
+	     }
+	     
+	    return valid_sets_model;
+	}
+
+	
+	public void  gemsIsClosed(){ 
+	    available_sets_list.setModel(getValidSetModel()); 
+	}
+
+	public boolean isCancelled() {
+	    return cancelled;
+	}
+
+	private class AddSetActionListener
+	    implements ActionListener {
+
+	    public void actionPerformed(ActionEvent event) {
+		if (available_sets_list.isSelectionEmpty()) {
+		    return;
+		}
+		MetadataSet metadata_set = (MetadataSet) available_sets_list.getSelectedValue();
+		String namespace = metadata_set.getNamespace();
+		// have we got a variant already in the collection??
+		MetadataSet existing_set = null;
+		if ((existing_set = MetadataSetManager.getMetadataSet(namespace)) != null) {
+		    // warn that we are replacing
+		    String [] args = new String [] {metadata_set.toString(), existing_set.toString()};
+		    WarningDialog namespace_clash_dialog = new WarningDialog("warning.MetadataSetNamespaceClash", Dictionary.get("MetadataSetNamespaceClash.Title"), Dictionary.get("MetadataSetNamespaceClash.Message", args), null, true);
+		    if (namespace_clash_dialog.display()==JOptionPane.CANCEL_OPTION) {
+			namespace_clash_dialog.dispose();
+			return;
+		    }
+		    // if we have got here, then we remove the old set
+		    current_metadata_model.removeElement(existing_set);
+		    Gatherer.c_man.removeMetadataSet(existing_set);
+		    sets_changed = true;
+		    namespace_clash_dialog.dispose();
+		}
+		
+		
+		Gatherer.c_man.importMetadataSet(metadata_set);
+		metadata_set = MetadataSetManager.getMetadataSet(namespace);
+		current_metadata_model.addElement(metadata_set);
+		sets_changed = true;
+		cancelled = false;
+		add_set_dialog.dispose();
+
+	    }
+	}
+
+	private class BrowseActionListener
+	    implements ActionListener {
+
+	    public void actionPerformed(ActionEvent event) {
+		JFileChooser chooser = new JFileChooser(new File(Gatherer.getGLIMetadataDirectoryPath()));
+		chooser.setFileFilter(new MetadataSet.MetadataSetFileFilter());
+		chooser.setDialogTitle(Dictionary.get("MetadataSetDialog.Add_Title"));
+		int return_val = chooser.showDialog(Gatherer.g_man, Dictionary.get("MetadataSetDialog.Add_Set"));
+		if (return_val == JFileChooser.APPROVE_OPTION) {
+		    MetadataSet meta_set = new MetadataSet(chooser.getSelectedFile());
+		    Gatherer.c_man.importMetadataSet(meta_set);
+		    current_metadata_model.addElement(meta_set);
+		    cancelled = false;
+		    add_set_dialog.dispose();
+		} else {
+		    // we do nothing - user may want to add from the other dialog
+		}
+	    }
+	}
+	
+		
+	private class AvailableSetListSelectionListener 
+	    implements ListSelectionListener
+	{
+	    public void valueChanged(ListSelectionEvent event)
+	    {
+		// Wait until we get a stable event
+		if (event.getValueIsAdjusting()) {
+		    return;
+		}
+
+		if (!available_sets_list.isSelectionEmpty()) {
+		    // Retrieve the selected set
+		    MetadataSet metadata_set = (MetadataSet) available_sets_list.getSelectedValue();
+		    elements_list.setListData(new Vector(metadata_set.getMetadataSetElements()));
+		    add_button.setEnabled(true);
+		}
+		else {
+		    elements_list.setListData(new String[0]);
+		    add_button.setEnabled(false);
+		}
+	    }
+	}
+	
+	
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/MetadataValueTablePane.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/MetadataValueTablePane.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/MetadataValueTablePane.java	(revision 13928)
@@ -0,0 +1,417 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2005 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.gui;
+
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.table.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.collection.CollectionTreeNode;
+import org.greenstone.gatherer.metadata.MetadataChangedListener;
+import org.greenstone.gatherer.metadata.MetadataElement;
+import org.greenstone.gatherer.metadata.MetadataTools;
+import org.greenstone.gatherer.metadata.MetadataValue;
+import org.greenstone.gatherer.metadata.MetadataValueTableEntry;
+import org.greenstone.gatherer.metadata.MetadataValueTableModel;
+import org.greenstone.gatherer.metadata.MetadataXMLFileManager;
+import org.greenstone.gatherer.util.JarTools;
+import org.greenstone.gatherer.util.Utility;
+
+
+public class MetadataValueTablePane
+    extends JPanel
+{
+    private MetadataValueTable metadata_value_table = null;
+    /** Used to display either the MetadataValueTable (when files are selected) or a placeholder panel */
+    private CardLayout card_layout = null;
+    /** The name of the panel containing the metadata value table */
+    private String METADATA_VALUE_TABLE_CARD = "";
+    /** The name of the panel containing the "no metadata available" placeholder */
+    private String NO_METADATA_AVAILABLE_CARD = "No metadata available";
+    /** The name of the panel containing the "no files selected" placeholder */
+    private String NO_FILES_SELECTED_CARD = "No files selected";
+
+
+    public MetadataValueTablePane()
+    {
+	super();
+
+	metadata_value_table = new MetadataValueTable();
+
+	JScrollPane metadata_value_table_scroll = new JScrollPane(metadata_value_table);
+	metadata_value_table_scroll.getViewport().setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+	metadata_value_table_scroll.setOpaque(true);
+
+	JPanel metadata_value_table_pane = new JPanel();
+	metadata_value_table_pane.setLayout(new BorderLayout());
+	metadata_value_table_pane.add(metadata_value_table_scroll, BorderLayout.CENTER);
+
+	JLabel no_metadata_available_label = new JLabel(Dictionary.get("EnrichPane.No_Metadata"));
+	no_metadata_available_label.setHorizontalAlignment(JLabel.CENTER);
+	no_metadata_available_label.setOpaque(false);
+	no_metadata_available_label.setVerticalAlignment(JLabel.CENTER);
+	
+	JPanel no_metadata_available_pane = new JPanel();
+	no_metadata_available_pane.setLayout(new BorderLayout());
+	no_metadata_available_pane.add(no_metadata_available_label, BorderLayout.CENTER);
+
+	JLabel no_files_selected_label = new JLabel(Dictionary.get("EnrichPane.No_File"));
+	no_files_selected_label.setHorizontalAlignment(JLabel.CENTER);
+	no_files_selected_label.setOpaque(false);
+	no_files_selected_label.setVerticalAlignment(JLabel.CENTER);
+	
+	JPanel no_files_selected_pane = new JPanel();
+	no_files_selected_pane.setLayout(new BorderLayout());
+	no_files_selected_pane.add(no_files_selected_label, BorderLayout.CENTER);
+
+	card_layout = new CardLayout();
+
+	this.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
+	this.setFont(Configuration.getFont("general.font", false));
+	this.setLayout(card_layout);
+	this.add(metadata_value_table_pane, METADATA_VALUE_TABLE_CARD);
+	this.add(no_metadata_available_pane, NO_METADATA_AVAILABLE_CARD);
+	this.add(no_files_selected_pane, NO_FILES_SELECTED_CARD);
+    }
+
+
+    public void addMetadataValueTableListSelectionListener(ListSelectionListener list_selection_listener)
+    {
+	metadata_value_table.getSelectionModel().addListSelectionListener(list_selection_listener);
+    }
+
+
+    public void addMetadataValueTableMouseListener(MouseListener mouse_listener)
+    {
+	metadata_value_table.addMouseListener(mouse_listener);
+    }
+
+
+    public void addMetadataValueTextFieldDocumentListener(DocumentListener document_listener)
+    {
+	metadata_value_table.getMetadataValueTextField().getDocument().addDocumentListener(document_listener);
+    }
+
+
+    public void addMetadataValueTextFieldKeyListener(KeyListener key_listener)
+    {
+	metadata_value_table.getMetadataValueTextField().addKeyListener(key_listener);
+    }
+
+
+    public MetadataValueTableEntry getSelectedMetadataValueTableEntry()
+    {
+	return metadata_value_table.getSelectedMetadataValueTableEntry();
+    }
+
+
+    public boolean isMouseEventForInheritedMetadataValueTableColumn(MouseEvent mouse_event)
+    {
+	return metadata_value_table.isMouseEventForInheritedMetadataValueTableColumn(mouse_event);
+    }
+
+
+    public void setMetadataValueTextFieldValue(String metadata_value_string)
+    {
+	metadata_value_table.setMetadataValueTextFieldValue(metadata_value_string);
+    }
+
+
+    public void stopEditingAndAddBlankRowForSelectedMetadataElement()
+    {
+	metadata_value_table.stopEditing();
+	metadata_value_table.addBlankRowForSelectedMetadataElement();
+    }
+
+
+    public void stopEditingAndRebuild(CollectionTreeNode[] file_nodes)
+    {
+	metadata_value_table.stopEditing();
+	metadata_value_table.rebuild(file_nodes);
+
+	// If no files are selected display the "no file selected" card
+	if (file_nodes == null) {
+	    card_layout.show(this, NO_FILES_SELECTED_CARD);
+	}
+	// If the metadata value table is empty display the "no metadata available" card
+	else if (metadata_value_table.getRowCount() == 0) {
+	    card_layout.show(this, NO_METADATA_AVAILABLE_CARD);
+	}
+	// Otherwise display the card with the metadata value table
+	else {
+	    card_layout.show(this, METADATA_VALUE_TABLE_CARD);
+	}
+    }
+
+
+    private class MetadataValueTable
+	extends JTable
+	implements MetadataChangedListener
+    {
+	private int MINIMUM_TABLE_HEADER_SIZE = 15;
+
+	private MetadataValueTableModel metadata_value_table_model = null;
+	private JTextField metadata_value_text_field = new JTextField();
+
+
+	public MetadataValueTable()
+	{
+	    // Create the model for the table
+	    metadata_value_table_model = new MetadataValueTableModel();
+	    setModel(metadata_value_table_model);
+
+	    // We allow only one row in the table to be selected at a time
+	    setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+
+	    // We use our own editor for the value column so we have easy access to the underlying text field
+	    setDefaultEditor(String.class, new DefaultCellEditor(metadata_value_text_field));
+
+	    // We need to listen for double clicks on the text field to open the editor dialog
+	    metadata_value_text_field.addMouseListener(new MetadataValueTextFieldMouseListener());
+	    metadata_value_text_field.setBorder(null);
+
+	    // We need to listen for key presses so we can catch Enter presses
+	    addKeyListener(new MetadataValueTableKeyListener());
+
+	    // We need to listen for metadata changes so we can rebuild the table
+	    MetadataXMLFileManager.addMetadataChangedListener(this);
+
+	    // We also have to ensure that the table column header hasn't gone on a severe Jenny Craig binge and has somehow lost 7/8th of its component size
+	    JTableHeader table_header = getTableHeader();
+	    Dimension table_header_preferred_size = table_header.getPreferredSize();
+	    if (table_header_preferred_size.height < MINIMUM_TABLE_HEADER_SIZE) {
+		table_header_preferred_size.setSize(table_header_preferred_size.width, MINIMUM_TABLE_HEADER_SIZE);
+		table_header.setPreferredSize(table_header_preferred_size);
+	    }
+
+	    // Set the size of the table columns: 2/7 for element, 5/7 for value (actual numbers don't matter) 
+	    TableColumnModel column_model = getColumnModel();
+	    TableColumn inherited_column = column_model.getColumn(0);
+	    inherited_column.setMinWidth(25);
+	    inherited_column.setPreferredWidth(25);
+	    inherited_column.setMaxWidth(25);
+	    TableColumn element_column = column_model.getColumn(1);
+	    element_column.setPreferredWidth(200);
+	    TableColumn value_column = column_model.getColumn(2);
+	    value_column.setPreferredWidth(500);
+
+	    // Use our own renderer for the table cells
+	    MetadataValueTableCellRenderer metadata_value_table_cell_renderer = new MetadataValueTableCellRenderer();
+	    inherited_column.setCellRenderer(metadata_value_table_cell_renderer);
+	    element_column.setCellRenderer(metadata_value_table_cell_renderer);
+	    value_column.setCellRenderer(metadata_value_table_cell_renderer);
+	}
+
+
+	private void addBlankRowForSelectedMetadataElement()
+	{
+	    // Add a blank entry for the selected metadata element, then switch to it
+	    MetadataElement selected_metadata_element = getSelectedMetadataValueTableEntry().getMetadataElement();
+	    int blank_row = metadata_value_table_model.addBlankRowForMetadataElement(selected_metadata_element);
+	    changeSelection(blank_row, 2, false, false);
+	}
+
+
+	private JTextField getMetadataValueTextField()
+	{
+	    return metadata_value_text_field;
+	}
+
+
+	private MetadataValueTableEntry getSelectedMetadataValueTableEntry()
+	{
+	    return metadata_value_table_model.getMetadataValueTableEntry(getSelectedRow());
+	}
+
+
+	private boolean isMouseEventForInheritedMetadataValueTableColumn(MouseEvent mouse_event)
+	{
+	    return (columnAtPoint(mouse_event.getPoint()) == 0);
+	}
+
+
+	public void metadataChanged(CollectionTreeNode[] file_nodes)
+	{
+	    rebuild(file_nodes);
+	}
+
+
+	private void rebuild(CollectionTreeNode[] file_nodes)
+	{
+	    // Note the metadata value table entry currently selected
+	    MetadataValueTableEntry selected_metadata_value_table_entry = getSelectedMetadataValueTableEntry();
+
+	    // We don't want a lot of ListSelectionEvents while the table is rebuilding
+	    clearSelection();
+
+	    // Rebuild the metadata value table model
+	    metadata_value_table_model.rebuild(file_nodes);
+
+	    // Restore the metadata value table entry selection
+	    if (selected_metadata_value_table_entry != null) {
+		int row_to_select = metadata_value_table_model.findMetadataValueTableEntryToSelect(selected_metadata_value_table_entry);
+		changeSelection(row_to_select, 2, false, false);
+	    }
+	}
+
+
+	private void setMetadataValueTextFieldValue(String metadata_value_string)
+	{
+	    metadata_value_text_field.setText(metadata_value_string);
+	    metadata_value_text_field.requestFocus();
+	}
+
+
+	private void stopEditing()
+	{
+	    // Save the current value in the text field, then remove the editor so it doesn't get saved again
+	    TableCellEditor table_cell_editor = getCellEditor();
+	    if (table_cell_editor != null) {
+		Object new_metadata_value = table_cell_editor.getCellEditorValue();
+		setValueAt(new_metadata_value, editingRow, editingColumn);
+		removeEditor();
+	    }
+	}
+
+
+	private class MetadataValueTableCellRenderer
+	    extends DefaultTableCellRenderer
+	{
+	    /** Returns the default table cell renderer.
+	     * @param table The <strong>JTable</strong>.
+	     * @param value The value to assign to the cell at [row, column] as an <strong>Object</strong>.
+	     * @param isSelected <i>true</i> if cell is selected.
+	     * @param hasFocus <i>true</i> if cell has focus.
+	     * @param row The row of the cell to render as an <i>int</i>.
+	     * @param column The column of the cell to render as an <i>int</i>.
+	     * @return The default table cell renderer <strong>Component</strong>.
+	     */
+	    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
+	    {
+		JComponent component = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+
+		int real_column = table.convertColumnIndexToModel(column);
+		// First column: inherited metadata icon
+		if (real_column == 0 && value != null) {
+		    component = new JLabel(JarTools.getImage("upfolder.gif"));
+		    component.setToolTipText(Dictionary.get("EnrichPane.InheritedMetadata_Tooltip"));
+		}
+
+		// Make sure the focus always stay in the value cell of the selected row
+		if (real_column == 2 && isSelected) {
+		    table.editCellAt(row, column);
+		    if (table.isEditing()) {
+			table.getEditorComponent().requestFocus();
+		    }
+		}
+
+		// Set up the component
+		component.setOpaque(true);
+
+		// Foreground
+		if (metadata_value_table_model.isCommon(row)) {
+		    component.setForeground(Color.black);
+		}
+		else {
+		    component.setForeground(Color.gray);
+		}
+
+		// Background
+		if (isSelected) {
+		    component.setBackground(Configuration.getColor("coloring.workspace_heading_background", true));
+		}
+		else {
+		    if (real_column < 2) {
+			component.setBackground(Configuration.getColor("coloring.collection_heading_background", true));
+		    }
+		    else {
+			component.setBackground(Configuration.getColor("coloring.collection_tree_background", true));
+		    }
+		}
+
+		// The value column of cells never paints focus
+		if (real_column == 2) {
+		    component.setBorder(BorderFactory.createEmptyBorder(0,2,0,0));
+		}
+
+		// We set a tooltip over the element column containing the definition of the element
+		if (value instanceof MetadataElement) {
+		    String interface_language_code = Configuration.getLanguage();
+		    String metadata_element_definition = MetadataTools.getMetadataElementAttribute((MetadataElement) value, "definition", interface_language_code, "en");
+		    if (metadata_element_definition != null) {
+			component.setToolTipText(Utility.formatHTMLWidth(metadata_element_definition, 60));
+		    }
+		}
+
+		return component;
+	    }
+	}
+
+
+	private class MetadataValueTableKeyListener
+	    extends KeyAdapter
+	{
+	    /** Gives notification of key events on the text field */
+	    public void keyPressed(KeyEvent key_event)
+	    {
+		// Enter: save the current value then add a blank row for the selected metadata element
+		if (key_event.getKeyCode() == KeyEvent.VK_ENTER) {
+		    // ...but not for extracted metadata elements of course
+		    MetadataValueTableEntry metadata_value_table_entry = getSelectedMetadataValueTableEntry();
+		    if (!metadata_value_table_entry.getMetadataElement().isExtractedMetadataElement()) {
+			addBlankRowForSelectedMetadataElement();
+		    }
+
+		    // We do not want this event to be processed by the table also
+		    key_event.consume();
+		}
+	    }
+	}
+
+
+	private class MetadataValueTextFieldMouseListener
+	    extends MouseAdapter
+	{
+	    public void mouseClicked(MouseEvent mouse_event)
+	    {
+		// Double-click: pop up an editor dialog for large metadata values
+		if (mouse_event.getClickCount() == 2) {
+ 		    EditorDialog editor_dialog = new EditorDialog();
+ 		    String new_metadata_value_string = editor_dialog.display(metadata_value_text_field.getText());
+ 		    if (new_metadata_value_string != null) {
+ 			setMetadataValueTextFieldValue(new_metadata_value_string);
+ 		    }
+		}
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/MetadataValueTreePane.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/MetadataValueTreePane.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/MetadataValueTreePane.java	(revision 13928)
@@ -0,0 +1,317 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2005 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.gui;
+
+
+import java.awt.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.metadata.MetadataElement;
+import org.greenstone.gatherer.metadata.MetadataValue;
+import org.greenstone.gatherer.metadata.MetadataValueTreeNode;
+import org.greenstone.gatherer.util.PatternTokenizer;
+
+
+/**
+ * This class is a little bit complex, a little bit subtle, and a little bit odd.
+ * The strange interaction model is due to the fact that it is very tightly
+ * coupled to the EnrichPane.
+ *
+ * The interaction is complex because there are three separate controls that the
+ * user may interact with, each of which can affect the other two. The three
+ * controls are:
+ *   - The "assigned metadata" table, at the top right of the meta edit pane.
+ *   - The "metadata value" text field, where users can type in new values.
+ *   - The "metadata value tree", which shows other values that have been
+ *     assigned to the selected metadata element.
+ *
+ * The interactions are:
+ *   - The "assigned metadata" table
+ *     Users may select one (and only one) row in this table. Selecting a row
+ *     chooses one metadata element. The text field will be set to the current
+ *     value of the metadata element. This value will also be selected in the
+ *     metadata value tree.
+ *
+ *   - The "metadata value" text field
+ *     If the value the user has typed in this is a prefix of an entry in the
+ *     value tree, this value will be selected in the value tree. In this case,
+ *     pressing "Tab" will complete the value (ie. make the value in the text
+ *     field the same as the value in the tree). This is to allow users to
+ *     quickly and easily assign existing metadata values to new documents.
+ *
+ *   - The "metadata value tree"
+ *     Selecting a value in the tree will set the text field to this value.
+ */
+public class MetadataValueTreePane
+    extends JPanel
+{
+    private boolean ignore_tree_selection_event = false;
+    /** The metadata value that the tree pane is built on */
+    private MetadataValue metadata_value = null;
+
+    /** Used to display either the MetadataValueTree (when metadata is selected) or a placeholder panel */
+    private CardLayout card_layout = null;
+    /** The name of the panel containing the metadata value tree */
+    private String METADATA_VALUE_TREE_CARD = "";
+    /** The name of the panel containing the "extracted metadata element selected" placeholder */
+    private String EXTRACTED_METADATA_ELEMENT_SELECTED_CARD = "Extracted metadata element selected";
+    /** The name of the panel containing the "inherited metadata selected" placeholder */
+    private String INHERITED_METADATA_SELECTED_CARD = "Inherited metadata selected";
+    /** The name of the panel containing the "not only file only metadata selected" placeholder */
+    private String NOT_ONE_FILE_ONLY_METADATA_SELECTED_CARD = "Not one file only metadata selected";
+    /** The name of the panel containing the "no metadata element selected" placeholder */
+    private String NO_METADATA_ELEMENT_SELECTED_CARD = "No metadata element selected";
+
+    private JLabel metadata_value_tree_label = new JLabel();
+    private JTextArea extracted_metadata_element_selected_message;
+    private JTree metadata_value_tree;
+
+
+    public MetadataValueTreePane()
+    {
+	super();
+
+	// Card containing the metadata value tree
+	metadata_value_tree = new JTree();
+	metadata_value_tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+	metadata_value_tree.setModel(null);
+	metadata_value_tree.setRootVisible(false);
+	metadata_value_tree.putClientProperty("JTree.lineStyle", "Angled");
+
+	JPanel metadata_value_tree_pane = new JPanel();
+	metadata_value_tree_pane.setLayout(new BorderLayout());
+	metadata_value_tree_pane.add(metadata_value_tree_label, BorderLayout.NORTH);
+	metadata_value_tree_pane.add(new JScrollPane(metadata_value_tree), BorderLayout.CENTER);
+
+	// Card containing the "extracted metadata element selected" message
+	extracted_metadata_element_selected_message = new JTextArea("");
+	extracted_metadata_element_selected_message.setEditable(false);
+	extracted_metadata_element_selected_message.setLineWrap(true);
+	extracted_metadata_element_selected_message.setOpaque(false);
+	extracted_metadata_element_selected_message.setWrapStyleWord(true);
+
+	JPanel extracted_metadata_element_selected_pane = new JPanel();
+	extracted_metadata_element_selected_pane.setBorder(BorderFactory.createEmptyBorder(25,0,0,0));
+	extracted_metadata_element_selected_pane.setLayout(new BorderLayout());
+	extracted_metadata_element_selected_pane.add(extracted_metadata_element_selected_message, BorderLayout.CENTER);
+
+	// Card containing the "inherited metadata selected" message
+	JTextArea inherited_metadata_selected_message = new JTextArea(Dictionary.get("EnrichPane.InheritedMetadataSelected"));
+	inherited_metadata_selected_message.setEditable(false);
+	inherited_metadata_selected_message.setLineWrap(true);
+	inherited_metadata_selected_message.setOpaque(false);
+	inherited_metadata_selected_message.setWrapStyleWord(true);
+	
+	JPanel inherited_metadata_selected_pane = new JPanel();
+	inherited_metadata_selected_pane.setBorder(BorderFactory.createEmptyBorder(25,0,0,0));
+	inherited_metadata_selected_pane.setLayout(new BorderLayout());
+	inherited_metadata_selected_pane.add(inherited_metadata_selected_message, BorderLayout.CENTER);
+
+	// Card containing the "not one file only metadata selected" message
+	JTextArea not_one_file_only_metadata_selected_message = new JTextArea(Dictionary.get("EnrichPane.NotOneFileOnlyMetadataSelected"));
+	not_one_file_only_metadata_selected_message.setEditable(false);
+	not_one_file_only_metadata_selected_message.setLineWrap(true);
+	not_one_file_only_metadata_selected_message.setOpaque(false);
+	not_one_file_only_metadata_selected_message.setWrapStyleWord(true);
+	
+	JPanel not_one_file_only_metadata_selected_pane = new JPanel();
+	not_one_file_only_metadata_selected_pane.setBorder(BorderFactory.createEmptyBorder(25,0,0,0));
+	not_one_file_only_metadata_selected_pane.setLayout(new BorderLayout());
+	not_one_file_only_metadata_selected_pane.add(not_one_file_only_metadata_selected_message, BorderLayout.CENTER);
+
+	// Card containing the "no metadata element selected" message
+	JLabel no_metadata_element_selected_label = new JLabel(Dictionary.get("EnrichPane.No_Metadata_Element"));
+	no_metadata_element_selected_label.setHorizontalAlignment(JLabel.CENTER);
+	no_metadata_element_selected_label.setOpaque(false);
+	no_metadata_element_selected_label.setVerticalAlignment(JLabel.CENTER);
+	
+	JPanel no_metadata_element_selected_pane = new JPanel();
+	no_metadata_element_selected_pane.setLayout(new BorderLayout());
+	no_metadata_element_selected_pane.add(no_metadata_element_selected_label, BorderLayout.CENTER);
+
+	card_layout = new CardLayout();
+
+	this.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	this.setFont(Configuration.getFont("general.font", false));
+	this.setLayout(card_layout);
+	this.add(no_metadata_element_selected_pane, NO_METADATA_ELEMENT_SELECTED_CARD);
+	this.add(extracted_metadata_element_selected_pane, EXTRACTED_METADATA_ELEMENT_SELECTED_CARD);
+	this.add(inherited_metadata_selected_pane, INHERITED_METADATA_SELECTED_CARD);
+	this.add(not_one_file_only_metadata_selected_pane, NOT_ONE_FILE_ONLY_METADATA_SELECTED_CARD);
+	this.add(metadata_value_tree_pane, METADATA_VALUE_TREE_CARD);
+    }
+
+
+    public void addMetadataValueTreeSelectionListener(TreeSelectionListener tree_selection_listener)
+    {
+	metadata_value_tree.addTreeSelectionListener(tree_selection_listener);
+    }
+
+
+    /** Returns a TreePath for the node most closely matching the metadata value. */
+    private TreePath getClosestPath(String metadata_value_string)
+    {
+	if (metadata_value_tree.getModel() == null) {
+	    return null;
+	}
+
+	// Start at the root of the tree
+	MetadataValueTreeNode tree_node = (MetadataValueTreeNode) metadata_value_tree.getModel().getRoot();
+
+	// Separate hierarchical values
+	PatternTokenizer tokenizer = new PatternTokenizer(metadata_value_string, MetadataValueTreeNode.METADATA_VALUE_TREE_NODE_HIERARCHY_TOKEN);
+	while (tokenizer.hasMoreTokens()) {
+	    String token = tokenizer.nextToken();
+
+	    // All components except the last must match exactly
+	    if (tokenizer.hasMoreTokens()) {
+		for (int i = 0; i < tree_node.getChildCount(); i++) {
+		    MetadataValueTreeNode child_node = (MetadataValueTreeNode) tree_node.getChildAt(i);
+		    if (child_node.getValue().equals(token)) {
+			// The matching node has been found, so move onto the next token
+			tree_node = child_node;
+			break;
+		    }
+		}
+	    }
+
+	    // The last component may match partially
+	    else {
+		for (int i = 0; i < tree_node.getChildCount(); i++) {
+		    MetadataValueTreeNode child_node = (MetadataValueTreeNode) tree_node.getChildAt(i);
+		    if (child_node.getFullValue().startsWith(metadata_value_string)) {
+			// The closest node has been found, so return its path
+			return new TreePath(child_node.getPath());
+		    }
+		}
+
+		// Not even a partial match
+		return null;
+	    }
+	}
+
+	// If nothing else, return the path of the root node
+	return new TreePath(tree_node.getPath());
+    }
+
+
+    public MetadataValueTreeNode getSelectedMetadataValueTreeNode()
+    {
+	if (metadata_value_tree.getSelectionCount() == 0 || ignore_tree_selection_event) {
+	    return null;
+	}
+
+	return (MetadataValueTreeNode) metadata_value_tree.getSelectionPath().getLastPathComponent();
+    }
+
+
+    public void rebuild(MetadataValue new_metadata_value)
+    {
+	// If the metadata value hasn't changed there is nothing to do
+	if (new_metadata_value == metadata_value) {
+	    return;
+	}
+
+	MetadataElement metadata_element = ((metadata_value != null) ? metadata_value.getMetadataElement() : null);
+	metadata_value = new_metadata_value;
+
+	// Selection cleared, so display "no metadata element selected" card and we're done
+	if (new_metadata_value == null) {
+	    metadata_value_tree.setModel(null);
+	    card_layout.show(this, NO_METADATA_ELEMENT_SELECTED_CARD);
+	    return;
+	}
+
+	// If a piece of inherited metadata is selected, display "inherited metadata selected" card and we're done
+	if (new_metadata_value.isInheritedMetadata()) {
+	    card_layout.show(this, INHERITED_METADATA_SELECTED_CARD);
+	    return;
+	}
+
+	// If the metadata applies to multiple files, display "not one file only metadata selected" card and we're done
+	if (new_metadata_value.isOneFileOnlyMetadata() == false) {
+	    card_layout.show(this, NOT_ONE_FILE_ONLY_METADATA_SELECTED_CARD);
+	    return;
+	}
+
+	// If an extracted metadata element is selected, display "extracted metadata element selected" card
+	MetadataElement new_metadata_element = new_metadata_value.getMetadataElement();
+	if (new_metadata_element.isExtractedMetadataElement()) {
+	    String[] args = new String[1];
+	    args[0] = new_metadata_element.getDisplayName();
+	    extracted_metadata_element_selected_message.setText(Dictionary.get("EnrichPane.AutoMessage", args));
+	    card_layout.show(this, EXTRACTED_METADATA_ELEMENT_SELECTED_CARD);
+	    return;
+	}
+
+	// Display the value tree for the selected metadata element
+	String[] args = new String[1];
+	args[0] = new_metadata_element.getDisplayName();
+	metadata_value_tree_label.setText(Dictionary.get("EnrichPane.ExistingValues", args));
+	
+	metadata_value_tree.setModel(new_metadata_element.getMetadataValueTreeModel());
+	card_layout.show(this, METADATA_VALUE_TREE_CARD);
+	selectBestPathForMetadataValue(new_metadata_value.getFullValue());
+    }
+
+
+    public void selectBestPathForMetadataValue(String metadata_value_string)
+    {
+	TreePath best_path = getClosestPath(metadata_value_string);
+
+	// Select the new path in the tree
+	// The tree selection event this causes must be ignored, since it alters the metadata text field value
+	ignore_tree_selection_event = true;
+	metadata_value_tree.setSelectionPath(best_path);
+	ignore_tree_selection_event = false;
+
+	// If a folder has been specified, make sure it is expanded
+	if (metadata_value_string.endsWith(MetadataValueTreeNode.METADATA_VALUE_TREE_NODE_HIERARCHY_TOKEN) && !metadata_value_tree.isExpanded(best_path)) {
+	    metadata_value_tree.expandPath(best_path);
+	}
+
+	// Make sure the tree path is expanded
+	metadata_value_tree.makeVisible(best_path);
+
+	// Make sure the tree path is visible on screen
+	final Rectangle bounds = metadata_value_tree.getPathBounds(best_path);
+	if (bounds != null) {
+	    bounds.x = 0;  // Want the tree to be always flushed left
+
+	    // Scrolling the path to be visible must be done on the GUI thread
+	    Runnable task = new Runnable() {
+		    public void run() {
+			metadata_value_tree.scrollRectToVisible(bounds);
+		    }
+		};
+	    SwingUtilities.invokeLater(task);
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/ModalDialog.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/ModalDialog.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/ModalDialog.java	(revision 13928)
@@ -0,0 +1,208 @@
+/*#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import org.greenstone.gatherer.DebugStream;
+
+
+/** An extension of the JDialog that overrides the JVM's typical modal behaviour. This typical behaviour is that when a modal dialog is opened, all other windows cease to respond to user events until the modal dialog is disposed. However this prevents us opening the help documents property whenever a modal dialog is open. Thus we override the modal behaviour so that only the owner frame or dialog is blocked. 
+ * Note that because we always call the super constructor with modal set to false, this should be made visible with setVisible(true) rather than show() which will return straight away. */
+// feedback note: veronika had changed all the super constructor calls to 
+// use modal instead of false - not sure if this is needed so I have not 
+// put that in. --kjdon
+public class ModalDialog
+    extends JDialog {
+
+    /** The current modal dialog being shown on screen, if any. */
+    static public ModalDialog current_modal = null;
+
+    /** true if this dialog should be modal, ie block user actions to its owner window, false otherwise. */
+    protected boolean modal = false;
+    /** true if this dialog is currently waiting some thread. */
+    protected boolean waiting = false;
+
+    /** Constructor.
+     */
+    public ModalDialog() {
+	super((Frame)null, "", false);
+    }
+
+    /** Constructor.
+     * @param parent the Dialog which is the owener of this dialog.
+    */
+    public ModalDialog(Dialog parent) {
+	super(parent, "", false);
+    }
+
+    /** Constructor.
+     * @param parent the Dialog which is the owener of this dialog.
+     * @param modal true if this dialog should be modal, ie block user actions to its owner window, false otherwise.
+     */
+    public ModalDialog(Dialog parent, boolean modal) {
+	super(parent, "", false);
+	this.modal = modal;
+    }
+    
+    /** Constructor.
+     * @param parent the Dialog which is the owner of this dialog.
+     * @param title the String to use as the title for this dialog.
+     */
+    public ModalDialog(Dialog parent, String title) {
+	super (parent, title, false);
+	this.modal = false;
+    }
+
+    /** Constructor.
+     * @param parent the Dialog which is the owener of this dialog.
+     * @param title the String to use as the title for this dialog.
+     * @param modal true if this dialog should be modal, ie block user actions to its owner window, false otherwise.
+     */
+    public ModalDialog(Dialog parent, String title, boolean modal) {
+	super (parent, title, false);
+	this.modal = modal;
+    }
+
+   /** Constructor.
+     * @param parent the Frame which is the owener of this dialog.
+     */
+    public ModalDialog(Frame parent) {
+	super(parent, "", false);
+    }
+
+    /** Constructor.
+     * @param parent the Frame which is the owener of this dialog.
+     * @param modal whether this dialog is modal or not
+     */
+    public ModalDialog(Frame parent, boolean modal) {
+	super(parent, "", false);
+	this.modal = modal;
+    }
+    
+    /** Constructor.
+     * @param parent the Frame which is the owner of this dialog.
+     * @param title the String to use as the title for this dialog.
+     */
+    public ModalDialog(Frame parent, String title) {
+	super (parent, title, false);
+    }
+
+    /** Constructor.
+     * @param parent the Frame which is the owener of this dialog.
+     * @param title the String to use as the title for this dialog.
+     * @param modal true if this dialog should be modal, ie block user actions to its owner window, false otherwise.
+     */
+    public ModalDialog(Frame parent, String title, boolean modal) {
+	super (parent, title, false);
+	this.modal = modal;
+    }
+
+    public void dispose() {
+	super.dispose();
+    }
+
+    /** Ensures the current dialog is visible. */
+    public void makeVisible() {
+	super.setVisible(true);
+    }
+
+    /** The set visible method is overriden to provide modal functionality. It essentially hijacks control of the event dispatch thread while the dialog is open, only allowing non-user events to be passed to the parent dialog. Furthermore it only has this effect within the current AWT component tree by utilitizing the TreeLock.
+     * @param visible true if this dialog should be painted on-screen, false otherwise.
+     */
+    public void setVisible(boolean visible)
+    {
+	if (visible) {
+	    current_modal = this;
+	}
+	else {
+	    current_modal = null;
+	}
+
+	// If we are in the AWT Dispatch thread then it is all good.
+ 	if (SwingUtilities.isEventDispatchThread()) {
+ 	    super.setVisible(visible);
+	    if (modal && visible) {
+		EventQueue theQueue = getToolkit().getSystemEventQueue();
+		while (isVisible()) {
+		    try {
+			AWTEvent event = theQueue.getNextEvent();
+			Object src = event.getSource();
+
+			// Block all keyboard and mouse events to the parent component
+			if (src.equals(getParent())) {
+			    if (event instanceof KeyEvent || event instanceof MouseEvent) {
+				// System.err.println("Event to parent component blocked.");
+				continue;
+			    }
+			}
+
+			// Re-dispatch other events
+			if (event instanceof ActiveEvent) {
+  			    ((ActiveEvent) event).dispatch();
+  			}			    
+			else if (src instanceof Component) {
+			    ((Component) src).dispatchEvent(event);
+			}
+		    }
+		    catch (Exception exception) {
+			DebugStream.printStackTrace(exception);
+		    }
+		}
+	    }
+ 	}
+ 	else {
+ 	    try {
+ 		SwingUtilities.invokeAndWait(new MakeDialogVisibleTask(this, visible));
+ 	    }
+ 	    catch (Exception exception) {
+ 		DebugStream.printStackTrace(exception);
+ 	    }
+ 	}
+    }
+    
+    private class MakeDialogVisibleTask
+	implements Runnable {
+	private boolean make_visible;
+	private ModalDialog dialog;
+	public MakeDialogVisibleTask(ModalDialog dialog, boolean make_visible) {
+	    this.dialog = dialog;
+	    this.make_visible = make_visible;
+	}
+	public void run() {
+	    // Blocks until the user dismisses the dialog
+	    dialog.setVisible(make_visible);
+	}
+    }
+
+    /** Overridden method so we can control modality and not rely on the Dialog default.
+     * @param modal true if this dialog should be modal, ie block user actions to its owner window, false otherwise.
+     */
+    public void setModal (boolean modal) {
+	this.modal = modal;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/ModalProgressPopup.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/ModalProgressPopup.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/ModalProgressPopup.java	(revision 13928)
@@ -0,0 +1,84 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2005 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.gui;
+
+
+import java.awt.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Gatherer;
+
+
+public class ModalProgressPopup
+    extends ModalDialog
+{
+    /** The size of the popup */
+    final static private Dimension SIZE = new Dimension(300, 75);
+
+    private String message = null;
+
+
+    public ModalProgressPopup(String title, String message)
+    {
+	super(Gatherer.g_man, title);
+	this.message = message;
+    }
+
+
+    /** Method to close the popup. */
+    public void close()
+    {
+	setVisible(false);
+	Gatherer.g_man.wait(false);
+    }
+
+
+    /** Method to display the popup on screen. */
+    public void display()
+    {
+	setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
+	setSize(SIZE);
+
+	// Create
+	JProgressBar progress_bar = new JProgressBar();
+	progress_bar.setIndeterminate(true);
+
+	// Layout
+	JPanel content_pane = (JPanel) getContentPane();
+	content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(new JLabel(message), BorderLayout.NORTH);
+	content_pane.add(progress_bar, BorderLayout.CENTER);
+
+	Dimension screen_size = Configuration.screen_size;
+	setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+	setVisible(true);
+
+	// Lock the rest of the GLI interface until close() is called
+	Gatherer.g_man.wait(true);
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/NewCollectionDetailsPrompt.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/NewCollectionDetailsPrompt.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/NewCollectionDetailsPrompt.java	(revision 13928)
@@ -0,0 +1,408 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Project, NZDL, University of Waikato
+ *
+ * Copyright (C) 2003 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.File;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.text.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.BasicCollectionConfiguration;
+import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+
+public class NewCollectionDetailsPrompt
+    extends ModalDialog {
+
+    static public boolean titleClashes(String title, File current_config_file) {
+	// An empty collection title never clashes with anything. It may look ugly in the final collection but there is nothing wrong with having no title for a particular language.
+	if(title == null || title.length() == 0) {
+	    return false;
+	}
+	File collect_directory = new File(Gatherer.getCollectDirectoryPath());
+	File children[] = collect_directory.listFiles();
+	for(int i = 0; children != null && i < children.length; i++) {
+	    if(children[i].isDirectory()) {
+		File config_file = new File(children[i], Utility.CONFIG_FILE);
+		if(current_config_file == null || !config_file.equals(current_config_file)) {
+		    BasicCollectionConfiguration other_collection = new BasicCollectionConfiguration(config_file);
+		    if(other_collection.getName().equalsIgnoreCase(title)) {  
+			return true;
+		    }
+		    other_collection = null;
+		}
+		config_file = null;
+	    }
+	}
+	return false;
+    }
+
+    private boolean cancelled;
+    private File base_final;
+    private JButton create_button;
+    private JComboBox base_collection;
+    private JDialog self;
+    private JRadioButton personal_collection_button = null;
+    private JTextArea description;
+    private JTextField title;
+    private String description_final;
+    private String title_final="";
+    static private Dimension COMPONENT_SIZE = new Dimension(230, 25);
+    /** The size of this new collection dialog box. */
+    static private Dimension SIZE = new Dimension(600, 280);
+    static private int FILENAME_SIZE = 8;
+
+    /** Constructor.
+     * @see org.greenstone.gatherer.util.Utility
+     */
+    public NewCollectionDetailsPrompt() {
+	super(Gatherer.g_man, true);
+	this.cancelled = true;
+	this.self = this;
+	// Setup
+	setJMenuBar(new SimpleMenuBar("creatingacollection"));
+	setSize(SIZE);
+	setTitle(Dictionary.get("NewCollectionPrompt.Title"));
+	
+	// Model building. Build a model of all of the collections in the gsdl collect directory with the appropriate directories.
+	Vector base_collection_model = new Vector();
+	// need to modify this to base a coll on any collection from any site
+	if (Gatherer.GS3) {
+	    File sites_dir = new File(Gatherer.getSitesDirectoryPath());
+	    File [] sites = sites_dir.listFiles();
+	    for (int i=0; i<sites.length; i++) {
+		File collect_directory = new File(Gatherer.getSitesDirectoryPath() + sites[i].getName() + File.separator + "collect");
+		if (collect_directory.exists()) {
+		    addCollectionsToModel(base_collection_model, collect_directory, sites[i].getName());
+		}
+	    }
+	} else {
+	   File collect_directory = new File(Gatherer.getCollectDirectoryPath());
+	   addCollectionsToModel(base_collection_model, collect_directory, null);
+	}
+
+	// Sort the result.
+	Collections.sort(base_collection_model);
+	base_collection_model.add(0, new Item(null, Dictionary.get("NewCollectionPrompt.NewCollection")));
+
+	// Creation
+	JPanel content_pane = (JPanel) getContentPane();
+	content_pane.setOpaque(true);
+	JPanel upper_pane = new JPanel();
+	JLabel instructions_label = new JLabel(Dictionary.get("NewCollectionPrompt.Instructions"));
+	
+	JPanel title_pane = new JPanel();
+	JLabel title_label = new JLabel(Dictionary.get("CDM.General.Collection_Name"));
+	title = new JTextField();
+	title.setPreferredSize(COMPONENT_SIZE);
+	title.setToolTipText(Dictionary.get("CDM.General.Collection_Name_Tooltip"));
+	JLabel name_label = new JLabel(Dictionary.get("NewCollectionPrompt.Collection_Name"));
+	
+	JPanel center_pane = new JPanel();
+	JPanel description_pane = new JPanel();
+	JLabel description_label = new JLabel(Dictionary.get("NewCollectionPrompt.Collection_Description"));
+	description = new JTextArea();
+	description.setBackground(Configuration.getColor("coloring.editable_background", false));
+	description.setForeground(Configuration.getColor("coloring.editable_foreground", false));
+	description.setRows(5);
+	description.setToolTipText(Dictionary.get("CDM.General.Collection_Extra_Tooltip"));
+	
+	JPanel bottom_pane = new JPanel();
+	// Base Collection
+	JPanel base_collection_pane = new JPanel();
+	JLabel base_collection_label = new JLabel(Dictionary.get("NewCollectionPrompt.Base_Collection"));
+	base_collection = new JComboBox(base_collection_model);
+	base_collection.setOpaque(false);
+	base_collection.setToolTipText(Dictionary.get("NewCollectionPrompt.Base_Collection_Tooltip"));
+	
+	JPanel collection_scope_pane = new JPanel();
+	personal_collection_button = new JRadioButton(Dictionary.get("NewCollectionPrompt.Collection_Scope_Personal"));
+	personal_collection_button.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+	personal_collection_button.setOpaque(false);
+	JRadioButton shared_collection_button = new JRadioButton(Dictionary.get("NewCollectionPrompt.Collection_Scope_Shared"));
+	shared_collection_button.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+	shared_collection_button.setOpaque(false);
+	ButtonGroup collection_scope_group = new ButtonGroup();
+	collection_scope_group.add(personal_collection_button);
+	collection_scope_group.add(shared_collection_button);
+	personal_collection_button.setSelected(true);
+
+	JPanel button_pane = new JPanel();
+	create_button = new GLIButton(Dictionary.get("General.OK"), Dictionary.get("General.OK_Tooltip"));
+	JButton cancel_button = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("General.Cancel_Tooltip"));
+
+	// Connection
+	cancel_button.addActionListener(new CancelListener());
+	create_button.addActionListener(new CreateListener());
+	description.addKeyListener(new DescriptionListener());
+
+	// Layout
+	title_pane.setLayout(new BorderLayout(5,0));
+	title_pane.add(title_label, BorderLayout.WEST);
+	title_pane.add(title, BorderLayout.CENTER);
+
+	upper_pane.setLayout(new GridLayout(2,1));
+	upper_pane.add(instructions_label);
+	upper_pane.add(title_pane);
+
+	description_pane.setLayout(new BorderLayout());
+	description_pane.add(description_label, BorderLayout.NORTH);
+	description_pane.add(new JScrollPane(description), BorderLayout.CENTER);
+
+	base_collection_pane.setLayout(new BorderLayout(5,0));
+	base_collection_pane.add(base_collection_label, BorderLayout.WEST);
+	base_collection_pane.add(base_collection, BorderLayout.CENTER);
+
+	collection_scope_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	collection_scope_pane.setLayout(new GridLayout(1,2));
+	collection_scope_pane.add(personal_collection_button);
+	collection_scope_pane.add(shared_collection_button);
+
+	center_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
+	center_pane.setLayout(new BorderLayout());
+	center_pane.add(description_pane, BorderLayout.CENTER);
+
+	bottom_pane.setLayout(new BorderLayout());
+	bottom_pane.add(base_collection_pane, BorderLayout.NORTH);
+	if (Gatherer.isGsdlRemote) {
+	    bottom_pane.add(collection_scope_pane, BorderLayout.CENTER);
+	    bottom_pane.add(button_pane, BorderLayout.SOUTH);
+	}
+	else {
+	    bottom_pane.add(button_pane, BorderLayout.CENTER);
+	}
+
+	button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	button_pane.setLayout(new GridLayout(1,2));
+	button_pane.add(create_button);
+	button_pane.add(cancel_button);
+
+	content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(upper_pane, BorderLayout.NORTH);
+	content_pane.add(center_pane, BorderLayout.CENTER);
+	content_pane.add(bottom_pane, BorderLayout.SOUTH);
+	// Final dialog setup & positioning.
+	Dimension screen_size = Configuration.screen_size;
+	setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+	setVisible(true);
+    }
+
+    public boolean isCancelled() {
+	return cancelled;
+    }
+
+    public File getBase() {
+	return base_final;
+    }
+
+    public String getDescription() {
+	return description_final;
+    }
+ 
+    /** Generates the collection short filename by taking the first eight characters of the title (spaces removed) and then adjusting by further truncating and then adding an unique suffix as necessary.
+     * @return the filename as a String
+     */
+    public String getName()
+    {
+	// Retrieve the first 8 non-whitespace ASCII characters of title_final.
+	StringBuffer name_buffer = new StringBuffer("");
+	for (int i = 0, u = 0; (i < title_final.length() && u < 8); i++) {
+	    // To be safe we make sure the internal collection name (folder name) contains only ASCII characters
+	    char c = title_final.charAt(i);
+	    if ((int) c < 128 && Character.isLetterOrDigit(c)) {
+		name_buffer.append(Character.toLowerCase(c));
+		u++;
+	    }
+	}
+
+	// Use "col" as the base collection name if we have nothing left
+	if (name_buffer.length() == 0) {
+	    name_buffer = new StringBuffer("col");
+	}
+
+	// Remote collections that aren't shared have the user's username prefixed to the collection name
+	if (Gatherer.isGsdlRemote && personal_collection_button.isSelected()) {
+	    name_buffer = new StringBuffer(RemoteGreenstoneServer.getUsername() + "-" + name_buffer.toString());
+	}
+
+	// We need to ensure the filename is unique
+	int counter = 0;
+	StringBuffer new_name_buffer = new StringBuffer(name_buffer.toString());
+	while(filenameClashes(new_name_buffer.toString())) {
+	    new_name_buffer = new StringBuffer(name_buffer.toString());
+	    counter++;
+	    String suffix = String.valueOf(counter);
+	    // If we have to truncate the namestring so as to fit the suffix
+	    if(suffix.length() + new_name_buffer.length() > 8) {
+		new_name_buffer.replace(new_name_buffer.length() - suffix.length(), new_name_buffer.length(), suffix);
+	    }
+	    // Or just append it if that isn't necessary
+	    else {
+		new_name_buffer.append(suffix);
+	    }
+	}
+
+	// All done
+	return new_name_buffer.toString();
+    }
+    
+    private boolean filenameClashes(String filename)
+    {
+	File collect_directory = new File(Gatherer.getCollectDirectoryPath());
+	File children[] = collect_directory.listFiles();
+	for(int i = 0; children != null && i < children.length; i++) {
+	    if(children[i].getName().equals(filename)) {
+		return true;
+	    }
+	}
+	return false;
+    }
+
+    public String getTitle() {
+	return title_final;
+    }
+
+    private void addCollectionsToModel(Vector base_collection_model, File collect_directory, String site) {
+	File[] possible_collections = collect_directory.listFiles();
+	for (int i = 0; possible_collections != null && i < possible_collections.length; i++) {
+	    // If the directory has a etc/collect.cfg file then it looks like a collection
+	    File collect_cfg_file = new File(possible_collections[i], Utility.CONFIG_FILE);
+	    if (collect_cfg_file.exists()) {
+		// If the directory has a metadata/ then the collection can be used as a base
+		File metadata_directory = new File(possible_collections[i], "metadata");
+		if (metadata_directory.exists()) {
+		    // Add to model
+		    BasicCollectionConfiguration collect_cfg = new BasicCollectionConfiguration(collect_cfg_file);
+		    if (Gatherer.GS3 && site != null) {
+			collect_cfg.setSite(site);
+		    }
+		    Item item = new Item(possible_collections[i], collect_cfg);
+		    if (!base_collection_model.contains(item)) {
+			base_collection_model.add(item);
+		    }
+		}
+	    }
+	}
+       
+    }
+
+    private class CancelListener
+	implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    cancelled = true;
+	    self.dispose();
+	}
+    }
+
+    
+    private class CreateListener
+	implements ActionListener {
+	
+	public void actionPerformed(ActionEvent event) {
+	    // Validate.
+	    title_final = title.getText();
+	    if(title_final.length() == 0) {
+		JOptionPane jOptionPane=new JOptionPane();
+		jOptionPane.setOpaque(!Utility.isMac());
+		jOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("NewCollectionPrompt.Title_Error"), Dictionary.get("NewCollectionPrompt.Error"), JOptionPane.ERROR_MESSAGE);
+		return;
+	    }
+	    // We must ensure that the collection title is unique. This is a pain in the nether regions as we are forced to load the collect.cfg of each other collection in turn looking for a conflicting title
+	    else {
+		if(titleClashes(title_final, null)) {
+		    JOptionPane jOptionPane=new JOptionPane();
+		    jOptionPane.setOpaque(!Utility.isMac());
+		    if (jOptionPane.showConfirmDialog(Gatherer.g_man, Dictionary.get("NewCollectionPrompt.Title_Clash"), Dictionary.get("General.Warning"), JOptionPane.YES_NO_OPTION) == JOptionPane.NO_OPTION) {
+			return;
+		    }
+		}
+	    }
+
+	    description_final = description.getText();
+
+	    // If we got this far there are no errors.
+	    Item item_final = (Item) base_collection.getSelectedItem();
+	    base_final = item_final.getFile();
+	    
+	    cancelled = false;
+	    
+	    self.dispose();
+	}
+    }
+    
+    private class DescriptionListener
+	extends KeyAdapter {
+	public void keyPressed(KeyEvent event) {
+	    if(event.getKeyCode() == KeyEvent.VK_TAB) {
+		event.consume();
+		base_collection.grabFocus();
+	    }
+	}
+    }
+
+    private class Item
+	implements Comparable {
+	private BasicCollectionConfiguration config;
+	private File file;
+	private String name;
+	public Item(File file, BasicCollectionConfiguration config) {
+	    this.config = config;
+	    this.file = file;
+	    this.name = null;
+	}
+	public Item(File file, String name) {
+	    this.config = null;
+	    this.file = file;
+	    this.name = name;
+	}
+	public int compareTo(Object other) {
+	    return toString().toLowerCase().compareTo(other.toString().toLowerCase());
+	}
+	public boolean equals(Object other) {
+	    return compareTo(other) == 0;
+	}
+	public File getFile() {
+	    return file;
+	}
+	public String toString() {
+	    if(name == null && config != null) {
+		name = config.toString();
+	    }
+	    return name;
+	}
+    }
+}
+
+
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/NewFolderOrFilePrompt.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/NewFolderOrFilePrompt.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/NewFolderOrFilePrompt.java	(revision 13928)
@@ -0,0 +1,172 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.CollectionTreeNode;
+import org.greenstone.gatherer.file.FileManager;
+
+public class NewFolderOrFilePrompt
+    extends JDialog 
+    implements ActionListener {
+    private CollectionTreeNode node;
+    private JButton cancel_button;
+    private JButton ok_button;
+    private JTextField name_field;
+    private String name;
+
+    private int type;
+    private String extension="";
+    static final private Dimension SIZE = new Dimension(350,115);
+
+    public NewFolderOrFilePrompt(CollectionTreeNode node, int type, String extension) {
+	super(Gatherer.g_man, true);
+	if (type == FileManager.FILE_TYPE) {
+	    setTitle(Dictionary.get("NewFolderOrFilePrompt.Title_File"));
+	} else {
+	    setTitle(Dictionary.get("NewFolderOrFilePrompt.Title_Folder"));
+	}
+	this.type = type;
+	if (extension != null) {
+	    this.extension = extension;
+	}
+	this.node = node;
+    }
+
+    public void actionPerformed(ActionEvent event) {
+	if (event.getSource() == ok_button) {
+	    name = name_field.getText()+extension;
+	}
+	else if(event.getSource() == cancel_button) {
+	    name = null;
+	}
+	dispose();
+    }
+
+    public String display() {
+	setSize(SIZE);
+	JPanel content_pane = (JPanel) getContentPane();
+
+	JPanel labels_pane = new JPanel();
+	JPanel fields_pane = new JPanel();
+	JPanel info_pane = new JPanel();
+
+	JLabel destination_label = new JLabel(Dictionary.get("NewFolderOrFilePrompt.Destination_Name"));
+
+	JTextField destination_textfield = new JTextField(node.getFile().getName());
+	destination_textfield.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+	destination_textfield.setEditable(false);
+	
+	JLabel name_label = new JLabel();
+	name_field = new JTextField(getAutomaticName());
+	if (type == FileManager.FILE_TYPE) {
+	    name_label.setText(Dictionary.get("NewFolderOrFilePrompt.File_Name"));
+	    name_field.setToolTipText(Dictionary.get("NewFolderOrFilePrompt.File_Name_Tooltip"));
+	} else {
+	    name_label.setText(Dictionary.get("NewFolderOrFilePrompt.Folder_Name"));
+	    name_field.setToolTipText(Dictionary.get("NewFolderOrFilePrompt.Folder_Name_Tooltip"));
+	}
+	JPanel button_pane = new JPanel();
+	ok_button = new GLIButton(Dictionary.get("General.OK"), Dictionary.get("General.OK_Tooltip"));
+	
+	cancel_button = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("General.Pure_Cancel_Tooltip"));
+	
+	// Connection
+	cancel_button.addActionListener(this);
+	ok_button.addActionListener(this);
+
+	// Layout
+	labels_pane.setLayout(new GridLayout(2,1, 5,0));
+	labels_pane.add(destination_label);
+	labels_pane.add(name_label);
+
+	fields_pane.setLayout(new GridLayout(2,1,0,5));
+	fields_pane.add(destination_textfield);
+	fields_pane.add(name_field);
+	
+	info_pane.setLayout(new BorderLayout(5,0));
+	info_pane.add(labels_pane, BorderLayout.WEST);
+	info_pane.add(fields_pane, BorderLayout.CENTER);
+
+	button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	button_pane.setLayout(new GridLayout(1,2,0,5));
+	button_pane.add(ok_button);
+	button_pane.add(cancel_button);
+
+	content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(info_pane, BorderLayout.CENTER);
+	content_pane.add(button_pane, BorderLayout.SOUTH);
+
+	// Display
+	Rectangle frame_bounds = Gatherer.g_man.getBounds();
+	setLocation(frame_bounds.x + (frame_bounds.width - SIZE.width) / 2, frame_bounds.y + (frame_bounds.height - SIZE.height) / 2);
+	setVisible(true);
+	return name;
+    }
+
+    private String getAutomaticName()
+    {
+	File file = node.getFile();
+	String default_name;
+	if (type == FileManager.FILE_TYPE) {
+	    default_name = Dictionary.get("NewFolderOrFilePrompt.Default_File_Name");
+	} else {
+	    default_name = Dictionary.get("NewFolderOrFilePrompt.Default_Folder_Name");
+	}
+	
+	File temp_file = new File(file, default_name+extension);
+	int count = 1;
+	while (temp_file.exists()) {
+	    temp_file = new File(file, default_name + " " + count+extension);
+	    count++;
+	}
+	if (extension.equals("")) {
+	    return temp_file.getName();
+	} 
+	String name = temp_file.getName();
+	// remove the extension
+	return name.substring(0, name.length()-extension.length());
+	
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/NonWhitespaceField.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/NonWhitespaceField.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/NonWhitespaceField.java	(revision 13928)
@@ -0,0 +1,73 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+/**************************************************************************************
+ * Written:     04/07/03
+ * Revised:     
+ **************************************************************************************/
+import javax.swing.*;
+import javax.swing.text.*;
+/** A JTextField that doesn't allow whitespace characters. 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.4
+ */
+public class NonWhitespaceField 
+    extends JTextField {
+ 
+    public NonWhitespaceField() {
+	super();
+    }
+
+    public NonWhitespaceField(String text) {
+	super(text);
+    }
+ 
+    protected Document createDefaultModel() {
+	return new NonWhitespaceDocument();
+    }
+ 
+    static class NonWhitespaceDocument 
+	extends PlainDocument {
+		  
+	public void insertString(int offs, String str, AttributeSet a) 
+	    throws BadLocationException {
+				
+	    if (str == null) {
+		return;
+	    }
+	    char[] raw = str.toCharArray();
+	    StringBuffer result = new StringBuffer("");
+	    for (int i = 0; i < raw.length; i++) {
+		if(!Character.isWhitespace(raw[i])) {
+		    result.append(raw[i]);
+		}
+	    }
+	    super.insertString(offs, result.toString(), a);
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/OpenCollectionDialog.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/OpenCollectionDialog.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/OpenCollectionDialog.java	(revision 13928)
@@ -0,0 +1,309 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.BasicCollectionConfiguration;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+
+/** A dialog which provides a straight-forward access to the currently installed collections. It also will contain the ability to continue through to the original OpenCollectionDialog if your source collection is located somewhere other than the gsdl collect folder. */
+public class OpenCollectionDialog
+    extends ModalDialog {
+
+    static final public int OK_OPTION = 0;
+    static final public int CANCEL_OPTION = 1;
+
+    static final private Dimension SIZE = new Dimension(640,480);
+    static final private String BLANK = "b";
+    static final private String DESCRIPTION = "d";
+
+    private CardLayout card_layout;
+    private int result;
+    private JButton cancel_button;
+    private JButton open_button;
+    private JList collection_list;
+    private JTextArea description_textarea;
+    private JPanel description_pane;
+    private String filename;
+
+    public OpenCollectionDialog() {
+	super(Gatherer.g_man, "", true);
+	setJMenuBar(new SimpleMenuBar("openingacollection"));
+	setSize(SIZE);
+	setTitle(Dictionary.get("OpenCollectionDialog.Title"));
+	
+	// Creation
+	JPanel content_pane = (JPanel) getContentPane();
+
+	JPanel center_pane = new JPanel();
+
+	JPanel collection_list_pane = new JPanel();
+	JLabel collection_list_label = new JLabel(Dictionary.get("OpenCollectionDialog.Available_Collections"));
+	collection_list = new JList(new CollectionListModel());
+	description_pane = new JPanel();
+	card_layout = new CardLayout();
+
+	JPanel blank_pane = new JPanel();
+
+	JPanel description_textarea_pane = new JPanel();
+	JLabel description_textarea_label = new JLabel(Dictionary.get("OpenCollectionDialog.Description"));
+	description_textarea = new JTextArea();
+
+	JPanel button_pane = new JPanel();
+	open_button = new GLIButton(Dictionary.get("OpenCollectionDialog.Open"), Dictionary.get("OpenCollectionDialog.Open_Tooltip"));
+	open_button.setEnabled(false);
+	
+	cancel_button = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("General.Pure_Cancel_Tooltip"));
+	
+	// Connection
+	cancel_button.addActionListener(new CancelListener());
+	open_button.addActionListener(new OpenListener());
+	CollectionListSelectionListener clsl = new CollectionListSelectionListener();
+	collection_list.addListSelectionListener(clsl);
+	collection_list.addMouseListener(clsl);
+	clsl = null;
+
+	// Layout
+	collection_list_pane.setLayout(new BorderLayout());
+	collection_list_pane.add(collection_list_label, BorderLayout.NORTH);
+	collection_list_pane.add(new JScrollPane(collection_list), BorderLayout.CENTER);
+
+	description_textarea_pane.setLayout(new BorderLayout());
+	description_textarea_pane.add(description_textarea_label, BorderLayout.NORTH);
+	description_textarea_pane.add(new JScrollPane(description_textarea), BorderLayout.CENTER);
+
+	description_pane.setLayout(card_layout);
+	description_pane.add(description_textarea_pane, DESCRIPTION);
+	description_pane.add(blank_pane, BLANK);
+
+	center_pane.setLayout(new GridLayout(2,1,0,5));
+	center_pane.add(collection_list_pane);
+	center_pane.add(description_pane);
+
+	button_pane.setLayout(new GridLayout(1,4));
+	button_pane.add(new JPanel());
+	button_pane.add(open_button);
+	button_pane.add(cancel_button);
+
+	content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(center_pane, BorderLayout.CENTER);
+	content_pane.add(button_pane, BorderLayout.SOUTH);
+
+	Dimension screen_size = Configuration.screen_size;
+	setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+	screen_size = null;
+    }
+
+    public void destroy() {
+    }
+
+    public int display() {
+	setVisible(true);
+	return result;
+    }
+
+    public String getFileName() {
+	return this.filename;
+    }
+
+    private class CancelListener
+	implements ActionListener {
+
+	public void actionPerformed(ActionEvent event) {
+	    result = CANCEL_OPTION;
+	    OpenCollectionDialog.this.dispose();
+	}
+    }
+
+    private class CollectionListSelectionListener
+	extends MouseAdapter
+	implements ListSelectionListener {
+
+	public void mouseClicked(MouseEvent event) {
+	    ///ystem.err.println("Mouse clicked");
+	    if(event.getClickCount() >= 2) {
+		Point location = event.getPoint();
+		int index = collection_list.locationToIndex(location);
+		collection_list.setSelectedIndex(index);
+		location = null;
+		open_button.doClick();
+	    }
+	}
+
+	public void valueChanged(ListSelectionEvent event) {
+	    if(collection_list.isSelectionEmpty()) {
+		card_layout.show(description_pane, BLANK);
+		open_button.setEnabled(false);
+	    }
+	    else {
+		BasicCollectionConfiguration collection_configuration = (BasicCollectionConfiguration) collection_list.getSelectedValue();
+		description_textarea.setText(collection_configuration.getDescription());
+		description_textarea.setCaretPosition(0);
+		card_layout.show(description_pane, DESCRIPTION);
+		open_button.setEnabled(true);
+	    }
+	}
+    }
+
+    // use this if we ever go back to viewing all colls at once
+    /*    private class GS3CollectionListModel
+	extends AbstractListModel {
+
+	private TreeSet data;
+
+	public GS3CollectionListModel() {
+	    data = new TreeSet();
+	    File sites_folder = new File(Utility.getSitesDir(Configuration.gsdl3_path));
+	    File sites[] = sites_folder.listFiles();
+	    for (int s=0; s<sites.length; s++) {
+		String site_name = sites[s].getName();
+		System.err.println("found site "+site_name);
+		File collect_folder = new File(Utility.getCollectDir(Configuration.gsdl3_path, site_name) );
+		if (!collect_folder.exists()) {
+		    continue;
+		}
+		File[] collection_folders = collect_folder.listFiles();
+		for(int i = 0; i < collection_folders.length; i++) {
+		    File collection_folder = collection_folders[i];
+		    String collection_foldername = collection_folder.getName();
+		    if(!collection_folder.isFile() && !collection_foldername.equals(StaticStrings.MODEL_COLLECTION_NAME)) {
+			BasicCollectionConfiguration collection_configuration = new BasicCollectionConfiguration(new File(collection_folder, Utility.CONFIG_FILE), site_name);
+			if(!collection_configuration.getName().equals(StaticStrings.ERROR_STR)) {
+			    data.add(collection_configuration);
+			}
+		    }
+		    collection_foldername = null;
+		    collection_folder = null;
+		} // for each collection
+		collection_folders = null;
+		collect_folder = null;
+	    } // for each site
+	    sites_folder = null;
+	    sites = null;
+	}
+
+	public Object getElementAt(int index) {
+	    Iterator iterator = data.iterator();
+	    for(int i = 0; iterator.hasNext(); i++) {
+		Object object = iterator.next();
+		if(i == index) {
+		    iterator = null;
+		    return object;
+		}
+		object = null;
+	    }
+	    iterator = null;
+	    return null;
+	}
+
+	public int getSize() {
+	    return data.size();
+	}
+    }
+    */	
+    private class CollectionListModel
+	extends AbstractListModel {
+
+	private TreeSet data;
+
+	public CollectionListModel() {
+	    data = new TreeSet();
+	    File collect_directory = new File(Gatherer.getCollectDirectoryPath());
+	    if (!collect_directory.exists()) {
+		collect_directory = null;
+		return;
+	    }
+	    File[] collection_folders = collect_directory.listFiles();
+	    for(int i = 0; i < collection_folders.length; i++) {
+		File collection_folder = collection_folders[i];
+		String collection_foldername = collection_folder.getName();
+		if(collection_folder.isDirectory() && !collection_foldername.equals(StaticStrings.MODEL_COLLECTION_NAME)) {
+		    File config_file = new File(collection_folder, Utility.CONFIG_FILE);
+		    if (config_file.exists()) {
+			BasicCollectionConfiguration collection_configuration = new BasicCollectionConfiguration(config_file);
+			data.add(collection_configuration);
+		    }
+		    config_file = null;
+		}
+		collection_foldername = null;
+		collection_folder = null;
+	    }
+	    collection_folders = null;
+	    collect_directory = null;
+	}
+
+	public Object getElementAt(int index) {
+	    Iterator iterator = data.iterator();
+	    for(int i = 0; iterator.hasNext(); i++) {
+		Object object = iterator.next();
+		if(i == index) {
+		    iterator = null;
+		    return object;
+		}
+		object = null;
+	    }
+	    iterator = null;
+	    return null;
+	}
+
+	public int getSize() {
+	    return data.size();
+	}
+    }
+
+    private class OpenListener
+	implements ActionListener {
+
+	public void actionPerformed(ActionEvent event) {
+	    result = OK_OPTION;
+	    Object selected_object = collection_list.getSelectedValue();
+	    if (selected_object instanceof BasicCollectionConfiguration) {
+		BasicCollectionConfiguration collection_configuration = (BasicCollectionConfiguration)selected_object; //(BasicCollectionConfiguration) collection_list.getSelectedValue();
+		//*************888
+		File collect_cfg_file = collection_configuration.getFile(); // returns the collect.cfg file
+		File etc_folder = collect_cfg_file.getParentFile();
+		File collection_folder = etc_folder.getParentFile();
+		filename = collection_folder.getAbsolutePath() + File.separator + collection_folder.getName() + ".col";
+		collection_folder = null;
+		etc_folder = null;
+		collect_cfg_file = null;
+		collection_configuration = null;
+		OpenCollectionDialog.this.dispose();
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/OptionsPane.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/OptionsPane.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/OptionsPane.java	(revision 13928)
@@ -0,0 +1,551 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.text.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.Argument;
+import org.greenstone.gatherer.cdm.ArgumentControl;
+import org.greenstone.gatherer.collection.ScriptOptions;
+import org.greenstone.gatherer.collection.Collection;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.util.AppendLineOnlyFileDocument;
+import org.greenstone.gatherer.util.AppendLineOnlyFileDocumentOwner;
+
+/** This class serves as the data holder for all subclasses of option panes, such as Import options or All options. It also contains methods for creating each of the option lines as they would appear in the subpane. Futhermore it has a method for considering all the arguments and generating a <strong>String[]</strong> to allow you to pass them to the <strong>GShell</strong>.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.2
+ */
+public class OptionsPane
+    extends JPanel 
+    implements AppendLineOnlyFileDocumentOwner, MouseListener {
+
+    static final public char SUCCESSFUL = 's';
+    static final public char UNSUCCESSFUL = 'u';
+    static final public char CANCELLED = 'c';
+    static final public char UNKNOWN = 'x';
+
+    static private int BUILD = 0;
+    static private int IMPORT = 1;
+    static private int MINIMUM_ROWS = 11;
+    
+    /** All process messages are written to this log text area. */
+    public JTextArea log_textarea = null;
+
+    private ArrayList current_controls;
+
+    /** The <strong>ScriptOptions</strong> data object contains all the option settings we wish to persist between Gatherer sessions (and thus is stored in <strong>Collection</strong>). */
+    private ScriptOptions build_options = null;
+    private ScriptOptions import_options = null;
+
+    private FileEntry file_entry = null;
+
+    /** the log pane - we only create it once now, not each time */
+    private JPanel log_pane = null;
+    /** the list of previous log messages */
+    private JList log_list = null;
+    private Vector writing_documents;
+
+
+    /** The default constructor creates the few session length options, but either retrieves the rest from the current collection, or creates a default set of options. */
+    public OptionsPane(ScriptOptions import_options, ScriptOptions build_options) {
+	this.build_options = build_options;
+	this.import_options = import_options;
+	this.current_controls = new ArrayList();
+	this.writing_documents = new Vector();
+
+	// Have to do this here, not in display, as the message log view may not have been displayed yet.
+	log_textarea = new JTextArea();
+	log_textarea.setEditable(false);
+    }
+
+    /** This method creates the panel with all the build only options on it.
+     * @param pane a JPanel which already has previous arguments available on it, to allow for lower moes to concatenate all of the arguments together
+     * @return a JPanel which can be used to display all the build only options
+     * @see org.greenstone.gatherer.Configuration#EXPERT_MODE
+     * @see org.greenstone.gatherer.Configuration#getColor
+     * @see org.greenstone.gatherer.Configuration#getMode
+     * @see org.greenstone.gatherer.Gatherer#config
+     * @see org.greenstone.gatherer.cdm.Argument
+     * @see org.greenstone.gatherer.collection.BuildOptions#getBuildArgument
+     * @see org.greenstone.gatherer.collection.BuildOptions#getBuildArgumentCount
+     * @see org.greenstone.gatherer.collection.BuildOptions#getBuildValue
+     * @see org.greenstone.gatherer.collection.BuildOptions#getBuildValueEnabled
+     * @see org.greenstone.gatherer.gui.OptionsPane.MyArgumentControl
+     */
+    public JPanel buildBuild(JPanel pane) {
+	// Reset the arguments
+	if(pane == null) {
+	    current_controls.clear();
+	}
+	ArrayList build_arguments = new ArrayList();
+	int current_mode = Configuration.getMode();
+	int total_build_argument_count = build_options.getArgumentCount();
+       
+	for(int i = 0; i < total_build_argument_count; i++) {
+	    // Retrieve the argument so we know how to format the control.
+	    Argument argument = build_options.getArgument(i);
+	    if(!argument.isHiddenGLI() && argument.getModeLevel() <= current_mode) {
+		// Now attempt to retrieve any existing value for this argument.
+		boolean enabled = build_options.getValueEnabled(argument.getName());
+		String value = build_options.getValue(argument.getName());
+		MyArgumentControl argument_control = new MyArgumentControl(BUILD, argument, enabled, value);
+		build_arguments.add(argument_control);
+	    }
+	}
+	current_controls.addAll(build_arguments);
+
+	// Now that we know how many arguments there are we can build the pane to view them on. Modes lower than EXPERT can provide a previous pane on which to add the arguments.
+	if(pane == null || current_mode >= Configuration.EXPERT_MODE) {
+	    pane = new JPanel();
+	    pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	    pane.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+	    int argument_count = build_arguments.size();
+	    // If in any of the higher detail modes, and assuming we don't want super phat argument controls, we better ensure there is a minimum number of lines in the grid layout
+	    if(current_mode >= Configuration.EXPERT_MODE) {
+		if(argument_count < MINIMUM_ROWS) {
+		    argument_count = MINIMUM_ROWS;
+		}
+		pane.setLayout(new GridLayout(argument_count, 1, 5, 5));
+	    }
+	    // Otherwise we're just going to throw them on one after another and chuck it in a scroll pane anyway
+	    else {
+		// use  GridLayout with 0 rows == as many rows as needed. Unfortunately, rows will 
+		// grow fat if space too large, but we don't know how many rows we'll need yet.
+		pane.setLayout(new GridLayout(0, 1, 5, 5));
+	    }
+	}
+
+	for(int j = 0; j < build_arguments.size(); j++) {
+	    pane.add((JComponent)build_arguments.get(j));
+	}
+	pane.addMouseListener(this);
+	build_arguments = null;
+	return pane;
+    }
+
+    /** This method creates the panel with all the import only options on it.
+     * @param pane a JPanel which already has previous arguments available on it, to allow for lower moes to concatenate all of the arguments together
+     * @return a JPanel which can be used to display all the build only options
+     * @see org.greenstone.gatherer.Configuration#EXPERT_MODE
+     * @see org.greenstone.gatherer.Configuration#getColor
+     * @see org.greenstone.gatherer.Configuration#getMode
+     * @see org.greenstone.gatherer.Gatherer#config
+     * @see org.greenstone.gatherer.cdm.Argument
+     * @see org.greenstone.gatherer.collection.BuildOptions#getImportArgument
+     * @see org.greenstone.gatherer.collection.BuildOptions#getImportArgumentCount
+     * @see org.greenstone.gatherer.collection.BuildOptions#getImportValue
+     * @see org.greenstone.gatherer.collection.BuildOptions#getImportValueEnabled
+     * @see org.greenstone.gatherer.gui.OptionsPane.ArgumentControl
+     */
+    public JPanel buildImport(JPanel pane) {
+	// Reset the arguments
+	if(pane == null) {
+	    current_controls.clear();
+	}
+	ArrayList import_arguments = new ArrayList();
+	int current_mode = Configuration.getMode();
+	int total_import_argument_count = import_options.getArgumentCount();       
+	for(int i = 0; i < total_import_argument_count; i++) {
+	    // Retrieve the argument so we know how to format the control.
+	    Argument argument = import_options.getArgument(i);
+	    if(!argument.isHiddenGLI() && argument.getModeLevel() <= current_mode) {
+		// Now attempt to retrieve any existing value for this argument.
+		boolean enabled = import_options.getValueEnabled(argument.getName());
+		String value = import_options.getValue(argument.getName());
+		MyArgumentControl argument_control = new MyArgumentControl(IMPORT, argument, enabled, value);
+		import_arguments.add(argument_control);
+	    }
+	}
+	current_controls.addAll(import_arguments);
+	// Now that we know how many arguments there are we can build the pane to view them on. Modes lower than EXPERT can provide a previous pane on which to add the arguments.
+	if(pane == null || current_mode >= Configuration.EXPERT_MODE) {
+	    pane = new JPanel();
+	    pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	    pane.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+	    int argument_count = import_arguments.size();	    
+	    // If in any of the higher detail modes, and assuming we don't want super phat argument controls, we better ensure there is a minimum number of lines in the grid layout
+	    if(current_mode >= Configuration.EXPERT_MODE) {
+		if(argument_count < MINIMUM_ROWS) {
+		    argument_count = MINIMUM_ROWS;
+		}
+		pane.setLayout(new GridLayout(argument_count, 1, 5, 5));
+	    }
+	    // Otherwise we're just going to throw them on one after another and chuck it in a scroll pane anyway
+	    else {
+		// use  GridLayout with 0 rows == as many rows as needed. Unfortunately, rows will 
+		// grow fat if space too large, but we don't know how many rows we'll need yet.
+		pane.setLayout(new GridLayout(0, 1, 5, 5));
+	    }
+	} 
+
+	for(int j = 0; j < import_arguments.size(); j++) {
+	    pane.add((JComponent)import_arguments.get(j));
+	}
+	pane.addMouseListener(this);
+	import_arguments = null;
+	return pane;
+    }
+
+    /** This method is used to build a panel based on the message log, which is nothing like any of the other panels.
+     * @return A <strong>JPanel</strong> containing a scrollable text area which represents the shell process message log.
+     */
+    public JPanel buildLog() {
+	// we now save the log pane
+	if (log_pane == null) {
+	    log_pane = new JPanel(new BorderLayout());
+
+	    // Build a list of the log files available, ordering by last modified. Log files are like build_log.date.txt
+	    DefaultListModel contents = new DefaultListModel();
+	    File log_directory = new File(CollectionManager.getLoadedCollectionLogDirectoryPath());
+	    File children[] = log_directory.listFiles();
+	    for(int i = 0; children != null && i < children.length; i++) {
+		String filename = children[i].getName();
+		if(filename.startsWith("build_log.") && filename.endsWith(".txt") ) {
+		    String datestamp = filename.substring(filename.indexOf(".") + 1, filename.lastIndexOf(".")).toLowerCase();
+		    if(datestamp.indexOf("s") == -1 && datestamp.indexOf("u") == -1 && datestamp.indexOf("c") == -1 && datestamp.indexOf("x") == -1) {
+			FileEntry entry = new FileEntry(children[i].getName(), children[i].getAbsolutePath());
+			// We are about to insert it. But where.
+			boolean found = false;
+			for(int j = 0; !found && j < contents.size(); j++) {
+			    FileEntry sibling = (FileEntry) contents.getElementAt(j);
+			    int order = entry.compareTo(sibling);
+			    if(order > 0) {
+				contents.insertElementAt(entry, j);
+				found = true;
+			    }
+			}
+			if(!found) {
+			    contents.addElement(entry);
+			}
+		    }
+		}
+	    }
+
+	    log_list = new JList(contents);
+	    log_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+	    log_list.setLayoutOrientation(JList.VERTICAL);
+	    log_list.setPreferredSize(new Dimension(600, 100));
+	    log_list.setVisibleRowCount(3);
+	    log_list.addListSelectionListener(new LogListListener());
+
+	    JLabel log_history_label = new JLabel(Dictionary.get("OptionsPane.LogHistory"));
+	    JPanel log_history_pane = new JPanel();
+	    log_history_pane.setPreferredSize(new Dimension(600, 100));
+	    log_history_pane.setLayout(new BorderLayout());
+	    log_history_pane.add(log_history_label, BorderLayout.NORTH);
+	    log_history_pane.add(new JScrollPane(log_list), BorderLayout.CENTER);
+	    
+	    log_pane.add(new JScrollPane(log_textarea), BorderLayout.CENTER);
+	    log_pane.add(log_history_pane, BorderLayout.SOUTH);
+	}
+	return log_pane;
+    }
+
+    public AppendLineOnlyFileDocument createNewLogDocument() {
+	long time = System.currentTimeMillis();
+	StringBuffer name = new StringBuffer();
+	name.append("build_log.");
+	name.append(time);
+	name.append(".txt");
+	// just in case there is no log directory
+	File file = new File(CollectionManager.getLoadedCollectionLogDirectoryPath() + name.toString());
+	File parent_file = file.getParentFile();
+	parent_file.mkdirs();
+	parent_file = null;
+	// create the file entry and add it to the list at pos 0 - it will always be the newest one created
+	file_entry = new FileEntry(name.toString(), file.getAbsolutePath());
+	((DefaultListModel)log_list.getModel()).add(0, file_entry);
+	log_list.setSelectedIndex(0);
+	// Finally retrieve and return the document associated with this file entry
+	return file_entry.getDocument();
+    }
+
+
+    /** Attempts to discover the latest document count.
+     * @return An <strong>int</strong> detailing the number of documents in this collection.
+     */
+    public int getDocumentCount() {
+	if(Gatherer.c_man.ready()) {
+	    int count = Gatherer.c_man.getCollection().getDocumentCount();
+	    if(count != 0) {
+		return count;
+	    }
+	}
+	return 1;
+    }
+
+    /** Called by our magic log documents after they have finished writing themselves to file, whereapon it is no longer necessary to hold a reference to them. */
+    public void remove(AppendLineOnlyFileDocument document) {
+	writing_documents.remove(document);
+    }
+
+    public void resetFileEntry() {
+	if(file_entry != null) {
+	    file_entry.reset();
+	}
+    }
+
+    /** Given a panel containing ArgumentControls, update the values associated with them. */
+    public void update(JPanel panel) {
+	if(panel == log_pane) {
+	    return;
+	}
+
+	for(int i = 0; i < panel.getComponentCount(); i++) {
+	    Component component = panel.getComponent(i);
+	    if(component instanceof MyArgumentControl) {
+		((MyArgumentControl)component).update();
+	    }
+	}
+    }
+
+    /** Implementation side-effect
+     * @param e a MouseEvent
+     */
+    public void mouseClicked(MouseEvent e) {}
+
+    /** Implementation side-effect
+     * @param e a MouseEvent
+     */
+    public void mouseEntered(MouseEvent e) {}
+
+    /** Implemented to ensure that, by the time the mouse pointer leaves the current build options screen, ang changes to the value the JSpinners have been commited
+     * @param e a MouseEvent
+     */
+    public void mouseExited(MouseEvent e) {
+	// Loop through the controls, and if the current control is a JSpinner, commit its current editing
+	for(int i = 0; i < current_controls.size(); i++) {
+	    MyArgumentControl control = (MyArgumentControl) current_controls.get(i);
+	    JComponent value_control = control.getValueControl();
+	    if(value_control instanceof JSpinner) {
+		try {
+		    ((JSpinner)value_control).commitEdit();
+		}
+		catch(Exception exception) {
+		    DebugStream.println("Exception in OptionsPane.mouseExited() - unexpected");
+		    DebugStream.printStackTrace(exception);
+		}
+	    }
+	    value_control = null;
+	    control = null;
+	}
+    }
+
+    /** Implementation side-effect
+     * @param e a MouseEvent
+     */
+    public void mousePressed(MouseEvent e) {}
+
+    /** Implementation side-effect
+     * @param e a MouseEvent
+     */
+    public void mouseReleased(MouseEvent e) {}
+
+    private class MyArgumentControl
+	extends ArgumentControl {
+	private int type;
+
+	public MyArgumentControl(int type, Argument argument, boolean enable, String value) {
+	    super(argument, enable, value);
+	    this.type = type;
+	}
+
+	/** Update the values stored in the collection so as to remember the current state of this argument. */
+	public void update() {
+	    String name = getArgumentName();
+	    boolean enable = isEnabled();
+	    String value = getValue();
+	    // If this argument was a flag, but is now disabled, remove from the build options altogether
+	    if(!enable && value == null) {
+		if(type == BUILD) {
+		    build_options.removeValue(name);
+		}
+		else {
+		    import_options.removeValue(name);
+		}
+	    }
+	    // Otherwise update the argument value
+	    else {
+		if(type == BUILD) {
+		    build_options.setValue(name, enable, value);
+		}
+		else {
+		    import_options.setValue(name, enable, value);
+		}
+	    }
+	}
+    }
+
+    /** Holds a File which has a particular naming convention build_log.date.txt also keeps a Date corresponding to the date in its name*/
+    private class FileEntry {
+
+       private AppendLineOnlyFileDocument current_document;
+       private Date date;
+       private long last_modified;
+       private String display;
+       private String filename;
+       private String filepath;
+       
+       public FileEntry(String filename, String filepath) {
+	  this.date = null;
+	  this.display = null;
+	  this.filename = filename;
+	  this.filepath = filepath;
+	  this.last_modified = 0L;
+       }
+
+	/** returns 0 if the dates are the same, -ve number if the current FileEntry is earlier than the fe FileEntry ...*/
+	public int compareTo(FileEntry file_entry) {
+	    Date our_date = getDate();
+	    Date other_date = file_entry.getDate();
+	    return our_date.compareTo(other_date);
+	}
+
+	public Date getDate() {
+	    if(date == null) {
+		// Need to exclude first '.'
+		int first_index = filename.indexOf(".") + 1;
+		// Need to exclude the last '.'
+		int last_index = filename.lastIndexOf(".");
+		if(first_index > 0 && last_index > 0 && first_index < last_index) {
+		    String date_string = filename.substring(first_index, last_index);
+		    date = new Date(Long.parseLong(date_string));
+		}
+		else {
+		    date = new Date(); // Current date
+		}
+	    }
+	    return date;
+	}
+
+       public AppendLineOnlyFileDocument getDocument() {
+	  if(current_document == null) {
+	     current_document = new AppendLineOnlyFileDocument(filepath);
+	  }
+	  return current_document;
+	}
+
+	public void reset() {
+	    display = null;
+	}
+
+	/** we only want the date out of the file name, not the whole path */
+	public String toString() {
+	    File file = new File(filename);
+	    if(display == null) {
+		last_modified = file.lastModified();
+		StringBuffer d = new StringBuffer();
+		Date date = getDate();
+		d.append(date.toString());
+		char success = UNKNOWN;
+		File the_file = new File(filepath);
+		if(the_file.exists()) {
+		   try {
+		      FileInputStream in = new FileInputStream(the_file);
+		      success = (char) in.read();
+		      in.close();
+		      in = null;
+		   }
+		   catch(Exception error) {
+		      ///ystem.err.println("Log '" + filepath + "' not found!");
+		      ///atherer.printStackTrace(error);
+		   }
+		}
+		the_file = null;
+		switch (success) {
+		case SUCCESSFUL:
+		    d.append(Dictionary.get("OptionsPane.Successful"));
+		    break;
+		case UNSUCCESSFUL:
+		    d.append(Dictionary.get("OptionsPane.Unsuccessful"));
+		    break;
+		case CANCELLED:
+		    d.append(Dictionary.get("OptionsPane.Cancelled"));
+		    break;
+		default:
+		    d.append(Dictionary.get("OptionsPane.Unknown"));
+		}
+		display = d.toString();
+	    }
+	    return display;
+	}
+    }
+
+    /** a ListSelectionListener that triggers the load of a newly selected log */
+    private class LogListListener implements ListSelectionListener {
+
+	public void valueChanged(ListSelectionEvent e) {
+	    if (!e.getValueIsAdjusting()) { // we get two events for one change in list selection - use the false one ( the second one)
+		///ystem.err.println("Log change detected.");
+		JList source  = (JList)e.getSource();
+		file_entry = (FileEntry) source.getSelectedValue();
+		// First we determine if the old log has been completely written to file
+		Document document = log_textarea.getDocument();
+		///ystem.err.println(" * current document: " + document);
+		///ystem.err.println(" * new document:     " + file_entry.getDocument());
+		// If we are dealing with the same document don't do anything.
+		if(document != file_entry.getDocument()) {
+		    if(document instanceof AppendLineOnlyFileDocument) {
+			AppendLineOnlyFileDocument append_line_only_file_document = (AppendLineOnlyFileDocument) document;
+			if(append_line_only_file_document.isStillWriting()) {
+			    ///ystem.err.println("Current log is still active... finishing.");
+			    writing_documents.add(append_line_only_file_document); // We have to maintain a reference until they are all done.
+			    append_line_only_file_document.setOwner(OptionsPane.this);
+			    append_line_only_file_document.setExit();
+			}
+			else {
+			    ///ystem.err.println("Current log is complete. Nothing to do.");
+			}
+		    }
+		    // Load the new log
+		    log_textarea.setDocument(file_entry.getDocument());
+		}
+	    }
+	}
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/Preferences.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/Preferences.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/Preferences.java	(revision 13928)
@@ -0,0 +1,944 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.plaf.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.ClassifierManager;
+import org.greenstone.gatherer.cdm.LanguageManager;
+import org.greenstone.gatherer.cdm.PluginManager;
+import org.greenstone.gatherer.collection.Collection;
+import org.greenstone.gatherer.gui.tree.DragTree;
+import org.greenstone.gatherer.util.ArrayTools; // just for debug
+import org.greenstone.gatherer.util.CheckList;
+import org.greenstone.gatherer.util.CheckListEntry;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.XMLTools;
+import org.w3c.dom.*;
+
+public class Preferences
+    extends ModalDialog
+{
+    static final public String CONNECTION_PREFS = "connection";
+    static final public String GENERAL_PREFS = "general";
+
+    static final private Dimension LABEL_SIZE = new Dimension(280, 25);
+    static final private Dimension ROW_SIZE = new Dimension(640, 25);
+    static final private Dimension SIZE = new Dimension(640, 345);
+    static final private String TRUE = "true";
+
+    private CheckList warning_preferences_check_list;
+    private EmailField email_field;
+    private JButton apply_button;
+    private JButton cancel_button;
+    private JButton ok_button;
+    private JCheckBox show_file_size_checkbox;
+    private JCheckBox use_proxy_checkbox;
+    private JCheckBox view_extracted_metadata_checkbox;
+    private JCheckBox workflow_download;
+    private JCheckBox workflow_gather;
+    private JCheckBox workflow_enrich;
+    private JCheckBox workflow_design;
+    private JCheckBox workflow_create;
+    private JCheckBox workflow_format;
+    private JComboBox language_combobox;
+    private JComboBox servlet_combobox; // GS3
+    private JComboBox site_combobox; // GS3
+    private JRadioButton assistant_mode_radio_button;
+    private JRadioButton expert_mode_radio_button;
+    private JRadioButton librarian_mode_radio_button;
+    private JRadioButton systems_mode_radio_button;
+    private JSpinner proxy_port_field;
+    private JTabbedPane tab_pane;
+    private JTextArea mode_description_textarea;
+    private JTextField font_field;
+    private JTextField gliserver_url_field;
+    private JTextField library_path_field;
+    private JTextField program_field;
+    private JTextField proxy_host_field;
+    private Preferences self;
+
+    private String current_site_selection;
+
+    public Preferences() {
+	this(GENERAL_PREFS);
+    }
+
+    public Preferences(String initial_view) {
+	// Initialize
+	super(Gatherer.g_man, true);
+	this.self = this;
+	setSize(SIZE);
+	setTitle(Dictionary.get("Preferences"));
+	setJMenuBar(new SimpleMenuBar("preferences"));
+
+	// Creation
+	JPanel content_pane = (JPanel) getContentPane();
+	tab_pane = new JTabbedPane();
+	JPanel general_preferences = createGeneralPreferences();
+	tab_pane.addTab(Dictionary.get("Preferences.General"), null, general_preferences, Dictionary.get("Preferences.General_Tooltip")); 
+	tab_pane.addTab(Dictionary.get("Preferences.Mode"), null, createModePreferences(), Dictionary.get("Preferences.Mode_Tooltip"));
+	//	tab_pane.addTab(Dictionary.get("Preferences.Workflow"), null, createWorkflowPreferences(), Dictionary.get("Preferences.Workflow_Tooltip")); 
+	JPanel connection_preferences = createConnectionPreferences();
+	tab_pane.addTab(Dictionary.get("Preferences.Connection"), null, connection_preferences, Dictionary.get("Preferences.Connection_Tooltip")); 
+	tab_pane.addTab(Dictionary.get("Preferences.Warnings"), null, createWarningPreferences(), Dictionary.get("Preferences.Warnings_Tooltip")); 
+	
+	JPanel button_pane = new JPanel();
+	ok_button = new GLIButton(Dictionary.get("General.OK"), Dictionary.get("General.OK_Tooltip"));
+	
+	apply_button = new GLIButton(Dictionary.get("General.Apply"), Dictionary.get("General.Apply_Tooltip"));
+	
+	cancel_button = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("General.Cancel_Tooltip"));
+	
+	// Connection
+	ok_button.addActionListener(new OKButtonListener(true));
+	apply_button.addActionListener(new OKButtonListener(false));
+	cancel_button.addActionListener(new CancelButtonListener());
+
+	// Layout
+	button_pane.setBorder(BorderFactory.createEmptyBorder(5,2,2,2));
+	button_pane.setLayout(new GridLayout(1,3,0,5));
+	button_pane.add(ok_button);
+	button_pane.add(apply_button);
+	button_pane.add(cancel_button);
+
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(tab_pane, BorderLayout.CENTER);
+	content_pane.add(button_pane, BorderLayout.SOUTH);
+
+	Dimension frame_size = Gatherer.g_man.getSize();
+	Point frame_location = Gatherer.g_man.getLocation();
+	setLocation(((frame_size.width - SIZE.width) / 2), ((frame_size.height - SIZE.height)));
+
+	// Bring the desired pane to the fore
+	if (initial_view.equals(CONNECTION_PREFS)) {
+	    tab_pane.setSelectedComponent(connection_preferences);
+	}
+	else {
+	    tab_pane.setSelectedComponent(general_preferences);
+	}
+	
+	// Clean up
+	general_preferences = null;
+	connection_preferences = null;
+	frame_location = null;
+	frame_size = null;
+	cancel_button = null;
+	ok_button = null;
+	button_pane = null;
+	tab_pane = null;
+	content_pane = null;
+
+	setVisible(true);
+    }
+
+    private JPanel createConnectionPreferences() {
+	JPanel program_pane = new JPanel();
+	program_pane.setPreferredSize(ROW_SIZE);
+	JLabel program_label = new JLabel(Dictionary.get("Preferences.Connection.ProgramCommand"));
+	program_label.setPreferredSize(LABEL_SIZE);
+	
+	program_field = new JTextField(Configuration.getPreviewCommand());
+	program_field.setCaretPosition(0);
+	program_field.setToolTipText(Dictionary.get("Preferences.Connection.ProgramCommand_Tooltip"));
+	
+	JPanel library_path_pane = new JPanel();
+	library_path_pane.setPreferredSize(ROW_SIZE);
+	JLabel library_path_label = new JLabel();
+	library_path_label.setPreferredSize(LABEL_SIZE);
+	String library_url_string = "";
+	if (Configuration.library_url != null) {
+	    library_url_string = Configuration.library_url.toString();
+	}
+	library_path_field = new JTextField(library_url_string);
+	library_path_field.setCaretPosition(0);
+	if (Gatherer.GS3) {
+	    library_path_label.setText(Dictionary.get("Preferences.Connection.Library_Path_GS3"));
+	    library_path_field.setToolTipText(Dictionary.get("Preferences.Connection.Library_Path_Tooltip_GS3"));
+	} else {
+	    library_path_label.setText(Dictionary.get("Preferences.Connection.Library_Path"));
+	    library_path_field.setToolTipText(Dictionary.get("Preferences.Connection.Library_Path_Tooltip"));
+	}
+	    
+	// Disable this field when using the applet, as it is automatically determined
+	library_path_label.setEnabled(!Gatherer.isApplet);
+	library_path_field.setEnabled(!Gatherer.isApplet);
+
+	JPanel gliserver_url_pane = null;
+	JLabel gliserver_url_label = null;
+	if (Gatherer.isGsdlRemote) {
+	    gliserver_url_pane = new JPanel();
+	    gliserver_url_pane.setPreferredSize(ROW_SIZE);
+	    gliserver_url_label = new JLabel(Dictionary.get("Preferences.Connection.GLIServer_URL"));
+	    gliserver_url_label.setPreferredSize(LABEL_SIZE);
+	    String gliserver_url_string = "";
+	    if (Configuration.gliserver_url != null) {
+		gliserver_url_string = Configuration.gliserver_url.toString();
+	    }
+	    gliserver_url_field = new JTextField(gliserver_url_string);
+	    gliserver_url_field.setCaretPosition(0);
+	    gliserver_url_field.setToolTipText(Dictionary.get("Preferences.Connection.GLIServer_URL_Tooltip"));
+	    
+	    // Disable this field when using the applet, as it is automatically determined
+	    gliserver_url_label.setEnabled(!Gatherer.isApplet);
+	    gliserver_url_field.setEnabled(!Gatherer.isApplet);
+	}
+
+	JPanel site_pane = null;
+	JLabel site_label = null;
+	JPanel servlet_pane = null;
+	JLabel servlet_label = null;
+	if (Gatherer.GS3) {
+	    site_pane = new JPanel();
+	    site_pane.setPreferredSize(ROW_SIZE);
+	    site_label = new JLabel(Dictionary.get("Preferences.Connection.Site"));
+	    site_label.setPreferredSize(LABEL_SIZE);
+	    // what should we do if Gatherer.servlet_config.getSites() is null?
+	    site_combobox = new JComboBox(Gatherer.servlet_config.getSites().toArray());
+	    site_combobox.setOpaque(false);
+	    site_combobox.setToolTipText(Dictionary.get("Preferences.Connection.Site_Tooltip"));
+	    
+	    servlet_pane = new JPanel();
+	    servlet_pane.setPreferredSize(ROW_SIZE);
+	    servlet_label = new JLabel(Dictionary.get("Preferences.Connection.Servlet"));
+	    servlet_label.setPreferredSize(LABEL_SIZE);
+	    servlet_combobox = new JComboBox();
+	    servlet_combobox.setOpaque(false);
+	    // try to locate and select the current site
+	    String this_site = Configuration.site_name;
+	    for(int b = 0; b < site_combobox.getItemCount(); b++) {
+		String entry = (String) site_combobox.getItemAt(b);
+		if(this_site.equals(entry)) {
+		    site_combobox.setSelectedIndex(b);
+		    break;
+		}
+	    }
+
+	    // just in case its not the current one?
+	    current_site_selection = (String)site_combobox.getSelectedItem();
+
+	    ArrayList servlet_options = Gatherer.servlet_config.getServletsForSite(current_site_selection);
+	    if (servlet_options == null) {
+		servlet_combobox.setToolTipText(Dictionary.get("Preferences.Connection.Servlet_Tooltip2"));
+		//servlet_combobox.setModel(new DefaultComboBoxModel());
+		servlet_combobox.setEnabled(false);
+	    } else {
+		///ystem.err.println(ArrayTools.objectArrayToString(servlet_options.toArray()));
+
+		servlet_combobox.setModel(new DefaultComboBoxModel(servlet_options.toArray()));
+		servlet_combobox.setToolTipText(Dictionary.get("Preferences.Connection.Servlet_Tooltip"));
+		servlet_combobox.setEnabled(true);
+		// try to locate and select the current servlet
+		String this_servlet = Configuration.getServletPath();
+		for(int b = 0; b < servlet_combobox.getItemCount(); b++) {
+		    String entry = (String) servlet_combobox.getItemAt(b);
+		    if(this_servlet.equals(entry)) {
+			servlet_combobox.setSelectedIndex(b);
+			break;
+		    }
+		}
+		
+	    }
+	}
+	
+	boolean currently_enabled = Configuration.get("general.use_proxy", true);
+	// Creation
+	JPanel connection_pane = new JPanel();
+	use_proxy_checkbox = new JCheckBox(Dictionary.get("Preferences.Connection.Use_Proxy"));
+	use_proxy_checkbox.setSelected(currently_enabled);
+	
+	use_proxy_checkbox.setPreferredSize(ROW_SIZE);
+	JPanel proxy_host_pane = new JPanel();
+	proxy_host_pane.setPreferredSize(ROW_SIZE);
+	JLabel proxy_host_label = new JLabel(Dictionary.get("Preferences.Connection.Proxy_Host"));
+	proxy_host_label.setPreferredSize(LABEL_SIZE);
+	
+	proxy_host_field = new JTextField(Configuration.getString("general.proxy_host", true));
+	proxy_host_field.setEnabled(currently_enabled);
+	proxy_host_field.setToolTipText(Dictionary.get("Preferences.Connection.Proxy_Host_Tooltip"));
+	
+	JPanel proxy_port_pane = new JPanel();
+	proxy_port_pane.setPreferredSize(ROW_SIZE);
+	JLabel proxy_port_label = new JLabel(Dictionary.get("Preferences.Connection.Proxy_Port"));
+	proxy_port_label.setPreferredSize(LABEL_SIZE);
+	
+	String port_value = Configuration.getString("general.proxy_port", true);
+	if(port_value.length() > 0) {
+	   proxy_port_field = new JSpinner(new SpinnerNumberModel((new Integer(port_value)).intValue(), 0, 65535, 1));
+	}
+	else {
+	   proxy_port_field = new JSpinner(new SpinnerNumberModel(0, 0, 65535, 1));
+	}
+	proxy_port_field.setEnabled(currently_enabled);
+	proxy_port_field.setToolTipText(Dictionary.get("Preferences.Connection.Proxy_Port_Tooltip"));
+	
+	// Connection
+	use_proxy_checkbox.addActionListener(new UseProxyListener());
+	if (Gatherer.GS3) {
+	    site_combobox.addActionListener(new SiteComboboxListener());
+	}
+
+	// Layout
+	program_pane.setLayout(new BorderLayout());
+	program_pane.add(program_label, BorderLayout.WEST);
+	program_pane.add(program_field, BorderLayout.CENTER);
+
+	library_path_pane.setLayout(new BorderLayout());
+	library_path_pane.add(library_path_label, BorderLayout.WEST);
+	library_path_pane.add(library_path_field, BorderLayout.CENTER);
+
+	if (Gatherer.isGsdlRemote) {
+	    gliserver_url_pane.setLayout(new BorderLayout());
+	    gliserver_url_pane.add(gliserver_url_label, BorderLayout.WEST);
+	    gliserver_url_pane.add(gliserver_url_field, BorderLayout.CENTER);
+	}
+
+	if (Gatherer.GS3) {
+	    site_pane.setLayout(new BorderLayout());
+	    site_pane.add(site_label, BorderLayout.WEST);
+	    site_pane.add(site_combobox, BorderLayout.CENTER);
+
+	    servlet_pane.setLayout(new BorderLayout());
+	    servlet_pane.add(servlet_label, BorderLayout.WEST);
+	    servlet_pane.add(servlet_combobox, BorderLayout.CENTER);
+	}
+
+	proxy_host_pane.setLayout(new BorderLayout());
+	proxy_host_pane.add(proxy_host_label, BorderLayout.WEST);
+	proxy_host_pane.add(proxy_host_field, BorderLayout.CENTER);
+
+	proxy_port_pane.setLayout(new BorderLayout());
+	proxy_port_pane.add(proxy_port_label, BorderLayout.WEST);
+	proxy_port_pane.add(proxy_port_field, BorderLayout.CENTER);
+
+	connection_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	connection_pane.setLayout(new GridLayout(8,1,0,2));
+	connection_pane.add(program_pane);
+	connection_pane.add(library_path_pane);
+	if (Gatherer.isGsdlRemote) {
+	    connection_pane.add(gliserver_url_pane);
+	}
+	if (Gatherer.GS3) {
+	    connection_pane.add(site_pane);
+	    connection_pane.add(servlet_pane);
+	}
+	connection_pane.add(use_proxy_checkbox);
+	connection_pane.add(proxy_host_pane);
+	connection_pane.add(proxy_port_pane);
+
+	return connection_pane;
+    }
+
+    private JPanel createGeneralPreferences() {
+	JPanel general_pane = new JPanel();
+
+	// Build the model of available languages
+	ArrayList dictionary_model = new ArrayList();
+
+	// The new method makes use of the successor to the languages.dat file, classes/xml/languages.xml
+	NodeList language_elements = LanguageManager.LANGUAGES_DOCUMENT.getDocumentElement().getElementsByTagName(StaticStrings.LANGUAGE_ELEMENT);
+	for(int i = 0; i < language_elements.getLength(); i++) {
+	    Element language_element = (Element) language_elements.item(i);
+	    if((language_element.getAttribute(StaticStrings.GLI_ATTRIBUTE)).equalsIgnoreCase(StaticStrings.TRUE_STR) || (language_element.getAttribute(StaticStrings.MDS_ATTRIBUTE)).equalsIgnoreCase(StaticStrings.TRUE_STR)) {
+		Locale locale = new Locale(language_element.getAttribute(StaticStrings.CODE_ATTRIBUTE));
+		String description = language_element.getAttribute(StaticStrings.NAME_ATTRIBUTE);
+		DictionaryEntry entry = new DictionaryEntry(description, locale);
+		if(!dictionary_model.contains(entry)) {
+		    dictionary_model.add(entry);
+		}
+		entry = null;
+		description = null;
+		locale = null;
+	    }
+	    language_element = null;
+	}
+	language_elements = null;
+
+	// Users email
+	JPanel email_pane = new JPanel();
+	JLabel email_label = new JLabel(Dictionary.get("Preferences.General.Email"));
+	email_label.setPreferredSize(LABEL_SIZE);
+	email_field = new EmailField(Configuration.getColor("coloring.error_background", false));
+	email_field.setText(Configuration.getEmail());
+	email_field.setToolTipText(Dictionary.get("Preferences.General.Email_Tooltip"));
+	
+	// Font selection
+	JPanel font_pane = new JPanel();
+	JLabel font_label = new JLabel(Dictionary.get("Preferences.General.Font"));
+	font_label.setPreferredSize(LABEL_SIZE);
+	font_field = new JTextField(Configuration.getString("general.font", true));
+	font_field.setToolTipText(Dictionary.get("Preferences.General.Font_Tooltip"));
+	
+	// Extracted metadata
+	view_extracted_metadata_checkbox = new JCheckBox(Dictionary.get("Preferences.General.View_Extracted_Metadata"));
+	view_extracted_metadata_checkbox.setSelected(false);
+	if (Configuration.get("general.view_extracted_metadata", Configuration.COLLECTION_SPECIFIC)) {
+	    view_extracted_metadata_checkbox.setSelected(true);
+	}
+	view_extracted_metadata_checkbox.setToolTipText(Dictionary.get("Preferences.General.View_Extracted_Metadata_Tooltip"));
+	
+	// Show file sizes
+	show_file_size_checkbox = new JCheckBox(Dictionary.get("Preferences.General.Show_File_Size"));
+	show_file_size_checkbox.setSelected(false);
+	if (Configuration.get("general.show_file_size", Configuration.COLLECTION_SPECIFIC)) {
+	    show_file_size_checkbox.setSelected(true);
+	}
+	show_file_size_checkbox.setToolTipText(Dictionary.get("Preferences.General.Show_File_Size_Tooltip"));
+	
+	// Language
+	JPanel language_pane = new JPanel();
+	JLabel language_label = new JLabel(Dictionary.get("Preferences.General.Interface_Language"));
+	language_label.setPreferredSize(LABEL_SIZE);
+	
+	language_combobox = new JComboBox(dictionary_model.toArray());
+	language_combobox.setOpaque(false);
+	language_combobox.setToolTipText(Dictionary.get("Preferences.General.Interface_Language_Tooltip"));
+	
+	// Try to locate and select the current language
+	String language_code = Configuration.getLanguage();
+	for (int b = 0; b < language_combobox.getItemCount(); b++) {
+	    DictionaryEntry entry = (DictionaryEntry) language_combobox.getItemAt(b);
+	    if (language_code.equalsIgnoreCase(entry.getLocale().getLanguage())) {
+		language_combobox.setSelectedIndex(b);
+		break;
+	    }
+	}
+
+	// Layout
+	email_pane.setLayout(new BorderLayout());
+	email_pane.add(email_label, BorderLayout.WEST);
+	email_pane.add(email_field, BorderLayout.CENTER);
+
+	language_pane.setLayout(new BorderLayout());
+	language_pane.add(language_label, BorderLayout.WEST);
+	language_pane.add(language_combobox, BorderLayout.CENTER);
+
+	font_pane.setLayout(new BorderLayout());
+	font_pane.add(font_label, BorderLayout.WEST);
+	font_pane.add(font_field, BorderLayout.CENTER);
+
+	general_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	general_pane.setLayout(new GridLayout(5,1,0,5));
+	general_pane.add(email_pane);
+	general_pane.add(language_pane);
+	general_pane.add(font_pane);
+	general_pane.add(view_extracted_metadata_checkbox);
+	general_pane.add(show_file_size_checkbox);
+
+	return general_pane;
+    }
+
+    /** Generate the controls for altering the detail mode.
+     * @return a JPanel of controls
+     */
+    private JPanel createModePreferences() {
+	// Create Controls
+	JPanel mode_panel = new JPanel();
+	JPanel button_panel = new JPanel();
+	ButtonGroup mode_button_group = new ButtonGroup();
+	assistant_mode_radio_button = new JRadioButton(Dictionary.get("Preferences.Mode.Assistant"));
+	assistant_mode_radio_button.setOpaque(false);
+	mode_button_group.add(assistant_mode_radio_button);
+	expert_mode_radio_button = new JRadioButton(Dictionary.get("Preferences.Mode.Expert"));
+	expert_mode_radio_button.setOpaque(false);
+	mode_button_group.add(expert_mode_radio_button);
+	librarian_mode_radio_button = new JRadioButton(Dictionary.get("Preferences.Mode.Librarian"));
+	librarian_mode_radio_button.setOpaque(false);
+	mode_button_group.add(librarian_mode_radio_button);
+	systems_mode_radio_button = new JRadioButton(Dictionary.get("Preferences.Mode.Systems"));
+	systems_mode_radio_button.setOpaque(false);
+	mode_button_group.add(systems_mode_radio_button);
+	mode_description_textarea = new JTextArea();
+	mode_description_textarea.setEditable(false);
+	mode_description_textarea.setLineWrap(true);
+	mode_description_textarea.setWrapStyleWord(true);
+	// Determine which value is already selected
+	switch(Configuration.getMode()) {
+	case Configuration.ASSISTANT_MODE:
+	    assistant_mode_radio_button.setSelected(true);
+	    mode_description_textarea.setText(Dictionary.get("Preferences.Mode.Assistant_Description"));
+	    break;
+	case Configuration.SYSTEMS_MODE:
+	    systems_mode_radio_button.setSelected(true);
+	    mode_description_textarea.setText(Dictionary.get("Preferences.Mode.Systems_Description"));
+	    break;
+	case Configuration.EXPERT_MODE:
+	    expert_mode_radio_button.setSelected(true);
+	    mode_description_textarea.setText(Dictionary.get("Preferences.Mode.Expert_Description"));
+	    break;
+	default:
+	    librarian_mode_radio_button.setSelected(true);
+	    mode_description_textarea.setText(Dictionary.get("Preferences.Mode.Librarian_Description"));
+	}
+	// Connection - when a radio button is selected we have to change the description
+	ModeRadioButtonListener listener = new ModeRadioButtonListener();
+	assistant_mode_radio_button.addActionListener(listener);
+	expert_mode_radio_button.addActionListener(listener);
+	librarian_mode_radio_button.addActionListener(listener);
+	systems_mode_radio_button.addActionListener(listener);
+	listener = null;
+	// Layout
+	button_panel.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
+	button_panel.setLayout(new GridLayout(4,1,2,2));
+	button_panel.add(assistant_mode_radio_button);
+	button_panel.add(librarian_mode_radio_button);
+	button_panel.add(systems_mode_radio_button);
+	button_panel.add(expert_mode_radio_button);
+
+	mode_panel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	mode_panel.setLayout(new BorderLayout());
+	mode_panel.add(button_panel, BorderLayout.NORTH);
+	mode_panel.add(new JScrollPane(mode_description_textarea), BorderLayout.CENTER);
+
+	return mode_panel;
+    }
+
+
+    /** The warning preferences are controlled through a checklist. */
+    private JPanel createWarningPreferences()
+    {
+	warning_preferences_check_list = new CheckList(false);
+
+	// Read all the warnings from the general xml/config.xml file, and their values from the user config.xml file
+	Document general_config_xml_file_document = XMLTools.parseXMLFile("xml/config.xml", true);
+	NodeList argument_elements_nodelist = general_config_xml_file_document.getDocumentElement().getElementsByTagName("Argument");
+	for (int i = 0; i < argument_elements_nodelist.getLength(); i++) {
+	    Element argument_element = (Element) argument_elements_nodelist.item(i);
+	    String argument_element_name = argument_element.getAttribute("name");
+	    if (argument_element_name.startsWith("warning.")) {
+		String warning_title = Dictionary.get(argument_element_name.substring("warning.".length()) + ".Title");
+		boolean warning_enabled = Configuration.get(argument_element_name, true);
+		CheckListEntry warning_entry = new CheckListEntry(warning_title, warning_enabled);
+		warning_entry.setProperty(argument_element_name);
+		warning_preferences_check_list.addEntry(warning_entry);
+	    }
+	}
+
+	JPanel warning_preferences_pane = new JPanel();
+	warning_preferences_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	warning_preferences_pane.setLayout(new BorderLayout());
+	warning_preferences_pane.add(new JScrollPane(warning_preferences_check_list), BorderLayout.CENTER);
+	return warning_preferences_pane;
+    }
+
+
+    private JPanel createWorkflowPreferences() {
+	// Read in the predefined configurations file
+	Vector predefined = new Vector();
+	Document predefined_document = XMLTools.parseXMLFile("xml/workflows.xml", true);
+	Element predefined_element = predefined_document.getDocumentElement();
+	NodeList workflow_elements = predefined_element.getElementsByTagName("Workflow");
+	for(int i = 0; i < workflow_elements.getLength(); i++) {
+	    predefined.add(new WorkflowElementWrapper((Element)workflow_elements.item(i)));
+	}
+
+	// Creation
+	JPanel workflow_preferences_pane = new JPanel();
+	JPanel checklist_pane = new JPanel();
+	JLabel title_label = new JLabel(Dictionary.get("Preferences.Workflow.Title"));
+	title_label.setPreferredSize(ROW_SIZE);
+	
+	workflow_download = new JCheckBox(Dictionary.get("GUI.Download")+" - "+Dictionary.get("GUI.Download_Tooltip"));
+	workflow_download.setSelected(Configuration.get("workflow.download", false));
+	workflow_download.setPreferredSize(ROW_SIZE);
+	
+	workflow_gather = new JCheckBox(Dictionary.get("GUI.Gather")+" - "+Dictionary.get("GUI.Gather_Tooltip"));
+	workflow_gather.setSelected(Configuration.get("workflow.gather", false));
+	workflow_gather.setPreferredSize(ROW_SIZE);
+	
+	workflow_enrich = new JCheckBox(Dictionary.get("GUI.Enrich")+" - "+Dictionary.get("GUI.Enrich_Tooltip"));
+	workflow_enrich.setSelected(Configuration.get("workflow.enrich", false));
+	workflow_enrich.setPreferredSize(ROW_SIZE);
+	
+	workflow_design = new JCheckBox(Dictionary.get("GUI.Design")+" - "+Dictionary.get("GUI.Design_Tooltip"));
+	workflow_design.setSelected(Configuration.get("workflow.design", false));
+	workflow_design.setPreferredSize(ROW_SIZE);
+	
+	workflow_create = new JCheckBox(Dictionary.get("GUI.Create")+" - "+Dictionary.get("GUI.Create_Tooltip"));
+	workflow_create.setSelected(Configuration.get("workflow.create", false));
+	workflow_create.setPreferredSize(ROW_SIZE);
+	
+
+	workflow_format = new JCheckBox(Dictionary.get("GUI.Format")+" - "+Dictionary.get("GUI.Format_Tooltip"));
+	workflow_format.setSelected(Configuration.get("workflow.format", false));
+	workflow_format.setPreferredSize(ROW_SIZE);
+	
+	JPanel predefined_pane = new JPanel();
+	JLabel predefined_label = new JLabel(Dictionary.get("Preferences.Workflow.Predefined.Label"));
+	JComboBox predefined_combobox = new JComboBox(predefined);
+	predefined_combobox.setOpaque(false);
+	// Connection
+	predefined_combobox.addActionListener(new PredefinedActionListener());
+
+	// Layout
+	checklist_pane.setLayout(new BoxLayout(checklist_pane, BoxLayout.Y_AXIS));
+	checklist_pane.add(title_label);
+	if (Configuration.get("workflow.download", true)) {
+	    checklist_pane.add(workflow_download);
+	}
+	if (Configuration.get("workflow.gather", true)) {
+	    checklist_pane.add(workflow_gather);
+	}
+	if (Configuration.get("workflow.enrich", true)) {
+	    checklist_pane.add(workflow_enrich);
+	}
+	if (Configuration.get("workflow.design", true)) {
+	    checklist_pane.add(workflow_design);
+	}
+	if (Configuration.get("workflow.create", true)) {
+	    checklist_pane.add(workflow_create);
+	}
+	if (Configuration.get("workflow.format", true)) {
+	    checklist_pane.add(workflow_format);
+	}
+	
+	predefined_pane.setLayout(new BorderLayout(5,0));
+	predefined_pane.add(predefined_label, BorderLayout.WEST);
+	predefined_pane.add(predefined_combobox, BorderLayout.CENTER);
+
+	workflow_preferences_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	workflow_preferences_pane.setLayout(new BorderLayout());
+	workflow_preferences_pane.add(checklist_pane, BorderLayout.CENTER);
+	workflow_preferences_pane.add(predefined_pane, BorderLayout.SOUTH);
+
+	return workflow_preferences_pane;
+    }
+
+
+    private class OKButtonListener
+	implements ActionListener {
+	private boolean close;
+	public OKButtonListener(boolean close) {
+	    this.close = close;
+	}
+	public void actionPerformed(ActionEvent event)
+	{
+	    // Connection preferences
+	    String program_str = program_field.getText();
+	    if (program_str.length() > 0 && program_str.indexOf("%1") == -1) {
+		program_str = program_str + " %1";
+	    }
+	    Configuration.setPreviewCommand(program_str);
+
+	    String library_url_string = library_path_field.getText();
+	    if (library_url_string.equals("")) {
+		Configuration.library_url = null;
+	    }
+	    else {
+		try {
+		    Configuration.library_url = new URL(library_url_string);
+		}
+		catch (MalformedURLException exception) {
+		    DebugStream.printStackTrace(exception);
+		}
+	    }
+	    Configuration.setString("general.library_url", true, library_url_string);
+
+	    if (Gatherer.isGsdlRemote) {
+		String gliserver_url_string = gliserver_url_field.getText();
+		if (gliserver_url_string.equals("")) {
+		    Configuration.gliserver_url = null;
+		}
+		else {
+		    try {
+			Configuration.gliserver_url = new URL(gliserver_url_string);
+		    }
+		    catch (MalformedURLException exception) {
+			DebugStream.printStackTrace(exception);
+		    }
+		}
+		Configuration.setString("general.gliserver_url", true, gliserver_url_string);
+	    }
+
+	    boolean site_changed = false;
+	    if (Gatherer.GS3) {
+		String current_site = Configuration.site_name;
+		String new_site =(String)site_combobox.getSelectedItem() ;
+		if (!new_site.equals(current_site)) {
+		    site_changed = true;
+		}
+		Configuration.setSiteAndServlet(new_site, (String)servlet_combobox.getSelectedItem());
+	    }
+
+	    Configuration.set("general.use_proxy", true, use_proxy_checkbox.isSelected());
+	    Configuration.setString("general.proxy_host", true, proxy_host_field.getText());
+	    Configuration.setString("general.proxy_port", true, proxy_port_field.getValue() + "");
+	    Gatherer.setProxy();
+
+	    // General preferences
+	    Configuration.setEmail(email_field.getText());
+	    Configuration.set("general.show_file_size", Configuration.COLLECTION_SPECIFIC, show_file_size_checkbox.isSelected());
+	    Configuration.set("general.view_extracted_metadata", Configuration.COLLECTION_SPECIFIC, view_extracted_metadata_checkbox.isSelected());
+
+	    // Two options requiring restarting the GLI to apply: interface font, and interface language
+	    boolean restart_required = false;
+
+	    // GLI interface font
+	    String current_font = Configuration.getString("general.font", true);
+	    if (!current_font.equals(font_field.getText())) {
+		Configuration.setString("general.font", true, font_field.getText());
+		restart_required = true;
+	    }
+
+	    // GLI interface language
+	    String current_lang = Configuration.getLanguage();
+	    if (!current_lang.equals(((DictionaryEntry) language_combobox.getSelectedItem()).getLocale().getLanguage())) {
+		Configuration.setLocale("general.locale", Configuration.GENERAL_SETTING, ((DictionaryEntry) language_combobox.getSelectedItem()).getLocale());
+		restart_required = true;
+	    }
+
+	    // Inform the user that a restart is required, if necessary
+	    if (restart_required) {
+		JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("Preferences.General.Restart_Required"), Dictionary.get("General.Warning"), JOptionPane.WARNING_MESSAGE);
+	    }
+
+	    // Mode preferences
+	    int current_mode = Configuration.getMode();
+	    int new_mode;
+	    if (assistant_mode_radio_button.isSelected()) {
+		new_mode = Configuration.ASSISTANT_MODE;
+	    }
+	    else if (systems_mode_radio_button.isSelected()) {
+		new_mode = Configuration.SYSTEMS_MODE;
+	    }
+	    else if (expert_mode_radio_button.isSelected()) {
+		new_mode = Configuration.EXPERT_MODE;
+	    }
+	    else {
+		new_mode = Configuration.LIBRARIAN_MODE;
+	    }
+
+	    // If there has been a change in modes, update the config, and also inform the persistant gui views that have a need to know
+	    if (new_mode != current_mode) {
+		Configuration.setMode(new_mode);
+		Collection collection = Gatherer.c_man.getCollection();
+		if (collection != null) {
+		    collection.cdm.modeChanged(new_mode);
+		}
+		Gatherer.g_man.modeChanged(new_mode);
+	    }
+
+	    // Warning preferences
+	    ListModel warning_preferences_check_list_model = warning_preferences_check_list.getModel();
+	    for (int i = 0; i < warning_preferences_check_list_model.getSize(); i++) {
+		CheckListEntry entry = (CheckListEntry) warning_preferences_check_list_model.getElementAt(i);
+		Configuration.set(entry.getProperty(), true, entry.isSelected());
+	    }
+
+	    if (Gatherer.GS3 && site_changed && Gatherer.c_man.getCollection() != null) {
+		// shut down the collection
+		System.err.println("shutting down teh collection");
+		Gatherer.g_man.saveThenCloseCurrentCollection();
+	    }
+
+	    // Workflow preferences
+// 	    Configuration.set("workflow.download", false, workflow_download.isSelected());
+// 	    Configuration.set("workflow.gather", false, workflow_gather.isSelected());
+// 	    Configuration.set("workflow.enrich", false, workflow_enrich.isSelected());
+// 	    Configuration.set("workflow.design", false, workflow_design.isSelected());
+// 	    Configuration.set("workflow.create", false, workflow_create.isSelected());
+// 	    Configuration.set("workflow.format", false, workflow_format.isSelected());
+	    
+// 	    Gatherer.g_man.workflowUpdate("Download", workflow_download.isSelected());
+// 	    Gatherer.g_man.workflowUpdate("Gather", workflow_gather.isSelected());
+// 	    Gatherer.g_man.workflowUpdate("Enrich", workflow_enrich.isSelected());
+// 	    Gatherer.g_man.workflowUpdate("Design", (workflow_design.isSelected() && Configuration.getMode() > Configuration.ASSISTANT_MODE));
+// 	    Gatherer.g_man.workflowUpdate("Create", workflow_create.isSelected());
+// 	    Gatherer.g_man.workflowUpdate("Format", workflow_format.isSelected());
+
+	    // Always save configuration changes immediately (in case the GLI crashes)
+	    Configuration.save();
+
+	    // Refresh the GLI to account for the configuration changes
+	    Gatherer.refresh(Gatherer.PREFERENCES_CHANGED);
+
+	    // Hide dialog
+	    if (close) {
+		self.dispose();
+	    }
+
+	    if (restart_required) {
+		Gatherer.g_man.exit(Gatherer.EXIT_THEN_RESTART);
+	    }
+	}
+    }
+
+    private class CancelButtonListener
+	implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    self.dispose();
+	}
+    }
+
+    private class DictionaryEntry
+	implements Comparable {
+	private Locale locale;
+	private String description;
+	public DictionaryEntry(Locale locale) {
+	    this.description = null;
+	    this.locale = locale;
+	}
+	public DictionaryEntry(String description, Locale locale) {
+	    this.description = description;
+	    this.locale = locale;
+	}
+	public int compareTo(Object object) {
+	    return toString().compareTo(object.toString());
+	}
+	public boolean equals(Object object) {
+	    return toString().equals(object.toString());
+	}
+	public Locale getLocale() {
+	    return locale;
+	}
+	public String toString() {
+	    if(description != null) {
+		return description;
+	    }
+	    else {
+		return locale.getDisplayName();
+	    }
+	}
+    }
+
+    /** This listener updates the mode description depending on what mode is selected. */
+    private class ModeRadioButtonListener
+	implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    Object source = event.getSource();
+	    if(source == assistant_mode_radio_button) {
+		mode_description_textarea.setText(Dictionary.get("Preferences.Mode.Assistant_Description"));
+	    }
+	    else if(source == expert_mode_radio_button) {
+		mode_description_textarea.setText(Dictionary.get("Preferences.Mode.Expert_Description"));
+	    }
+	    else if(source == systems_mode_radio_button) {
+		mode_description_textarea.setText(Dictionary.get("Preferences.Mode.Systems_Description"));
+	    }
+	    else {
+		mode_description_textarea.setText(Dictionary.get("Preferences.Mode.Librarian_Description"));
+	    }
+	    source = null;
+	}
+    }
+
+    private class PredefinedActionListener
+	implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    JComboBox cb = (JComboBox) event.getSource();
+	    WorkflowElementWrapper element = (WorkflowElementWrapper) cb.getSelectedItem();
+	    CheckboxUpdater task = new CheckboxUpdater(element);
+	    SwingUtilities.invokeLater(task);
+	}
+
+	private class CheckboxUpdater
+	    implements Runnable {
+	    private WorkflowElementWrapper element;
+	    public CheckboxUpdater(WorkflowElementWrapper element) {
+		this.element = element;
+	    }
+	    public void run() {
+		workflow_download.setSelected(element.getEnabled("download"));
+		workflow_gather.setSelected(element.getEnabled("gather"));
+		workflow_enrich.setSelected(element.getEnabled("enrich"));
+		workflow_design.setSelected(element.getEnabled("design"));
+		workflow_create.setSelected(element.getEnabled("create"));
+		workflow_format.setSelected(element.getEnabled("format"));
+	    }
+	}
+    }
+
+
+    private class SiteComboboxListener
+	implements ActionListener {
+	private boolean ignore_event=false;
+	public void actionPerformed(ActionEvent event) {
+	    System.err.println("event occurred "+event.paramString());
+	    String site = (String) site_combobox.getSelectedItem();
+	    System.err.println("new site = "+site);
+	    if (!site.equals(current_site_selection)) {
+		current_site_selection = site;
+		System.err.println("changed the current selection");
+		ArrayList servlet_options = Gatherer.servlet_config.getServletsForSite(current_site_selection);
+		if (servlet_options == null) {
+		    ///ystem.err.println("no servlets for this site");
+		    servlet_combobox.setModel(new DefaultComboBoxModel());
+		    servlet_combobox.setToolTipText(Dictionary.get("Preferences.Connection.Servlet_Tooltip2"));
+		    servlet_combobox.setEnabled(false);
+
+		} else {
+		    ///ystem.err.println(ArrayTools.objectArrayToString(servlet_options.toArray()));
+		    servlet_combobox.setModel(new DefaultComboBoxModel(servlet_options.toArray()));
+		    servlet_combobox.setToolTipText(Dictionary.get("Preferences.Connection.Servlet_Tooltip"));
+		    servlet_combobox.setEnabled(true);
+		}
+	    }
+	}    
+    }
+
+    private class UseProxyListener
+	implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    boolean enabled = use_proxy_checkbox.isSelected();
+	    Configuration.set("general.use_proxy", true, enabled);
+	    // Fortunately this is already driven by the event thread.
+	    proxy_host_field.setEnabled(enabled);
+	    proxy_port_field.setEnabled(enabled);
+	}
+    }
+
+    private class WorkflowElementWrapper {
+	private Element element;
+	private String text;
+	public WorkflowElementWrapper(Element element) {
+	    this.element = element;
+	}
+	public boolean getEnabled(String name) {
+	    boolean result = true;
+	    if(element.getAttribute(name).equalsIgnoreCase("false")) {
+		result = false;
+	    }
+	    return result;
+	}
+	public String toString() {
+	    if (text == null) {
+		text = Dictionary.get(element.getFirstChild().getNodeValue());
+	    }
+	    return text;
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/PreviewButton.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/PreviewButton.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/PreviewButton.java	(revision 13928)
@@ -0,0 +1,139 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.greenstone.LocalLibraryServer;
+import org.greenstone.gatherer.greenstone3.ServletConfiguration;
+import org.greenstone.gatherer.util.StaticStrings;
+
+
+public class PreviewButton 
+    extends GLIButton {
+
+
+    static final public int HOME_PAGE = 1;
+    static final public int SEARCH_PAGE = 2;
+    static final public int CLASSIFIER_PAGE = 3;
+    static final public int DOCUMENT_PAGE = 4;
+
+    private String preview_address;
+    private int page_type = HOME_PAGE;
+    private boolean variable_preview = false;
+    
+    private PreviewButtonOwner owner = null;
+    public PreviewButton() {
+	super();
+	PreviewButtonListener pbl = new PreviewButtonListener();
+	addActionListener(pbl);
+    }
+    public PreviewButton(String text, String tooltip) {
+	super(text, tooltip);
+	PreviewButtonListener pbl = new PreviewButtonListener();
+	addActionListener(pbl);
+    }
+
+    public void setOwner(PreviewButtonOwner o) {
+	owner = o;
+    }
+    public void setVariablePreview(boolean vp) {
+	variable_preview = vp;
+    }
+    protected void configureHomeURL() {
+	// set up the home page for the current collection
+	if (Gatherer.GS3) {
+	    // don't do anything fancy here
+	    preview_address = Configuration.library_url.toString() + Configuration.getServletPath() + "?a=p&sa=about&c=" + CollectionManager.getLoadedCollectionName() + "&l=" + Configuration.getLanguage();
+	    return;
+	}
+	preview_address = Configuration.library_url.toString() + "?c=" + CollectionManager.getLoadedCollectionName() + "&l=" + Configuration.getLanguage();
+
+	String main_args = "&a=p&p=about";
+	/* this code is for switching the preview page depending on what 
+	    is currently active. but it is not complete yet
+	String main_args = null;
+	String params = null;
+	if (!variable_preview || owner == null) {
+	    main_args = "&a=p&p=about";
+	} else {
+	    page_type = owner.getPageType();
+	    params = owner.getPageParams();
+	    
+	    switch (page_type) {
+	    case SEARCH_PAGE:
+		main_args = "&a=q&q="+params;
+		break;
+	    case CLASSIFIER_PAGE:
+		main_args = "&a=d&cl="+params;
+		break;
+	    case DOCUMENT_PAGE:
+		  main_args = "&a=d&d="+params;
+		break;
+	    case HOME_PAGE:
+	    default:
+		main_args = "&a=p&p=about";
+		
+		
+	    }
+	    
+
+	}
+	*/
+	preview_address += main_args+StaticStrings.TIMESTAMP_ARGUMENT + System.currentTimeMillis();
+	
+    }
+    private class PreviewButtonListener
+	implements ActionListener {
+
+	public void actionPerformed(ActionEvent event) {
+	    Gatherer.c_man.saveCollection();
+	    
+	    configureHomeURL();
+	    // check that the local library server is still running  - doesn't do anything if its not supposed to be running
+	    // !! Don't like this here
+	    LocalLibraryServer.checkServerRunning();
+	    if (Gatherer.GS3) {
+		// we need to rerun the convert in case the format stuff has changed
+		Gatherer.c_man.convertToGS3Collection();
+		Gatherer.configGS3Server(Configuration.site_name, ServletConfiguration.ADD_COMMAND + Gatherer.c_man.getLoadedCollectionName());
+	    }
+	    Gatherer.spawnBrowser(preview_address);
+
+	}
+
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/PreviewButtonOwner.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/PreviewButtonOwner.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/PreviewButtonOwner.java	(revision 13928)
@@ -0,0 +1,40 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+public interface PreviewButtonOwner {
+
+    public int getPageType();
+
+    public String getPageParams();
+
+
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/PreviewCommandDialog.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/PreviewCommandDialog.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/PreviewCommandDialog.java	(revision 13928)
@@ -0,0 +1,258 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.File;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.filechooser.*;
+import javax.swing.table.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.util.Utility;
+
+/** This dialog allows the user to choose which browser to use for the preview command 
+ * @author Katherine Don, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class PreviewCommandDialog
+    extends ModalDialog {
+
+    /** The default size for the dialog. */
+    static final private Dimension SIZE = new Dimension(500, 195);
+
+    private PreviewCommandDialog self;
+    private JButton browse_button;
+    private JButton cancel_button;
+    private JButton ok_button;
+    private JTextField command_field;
+    private String preview_command=null;
+    /** Create a new PreviewCommandDialog
+     */
+    public PreviewCommandDialog() {
+	super(Gatherer.g_man);
+	this.self = this;
+		  
+	// Creation
+	setModal(true);
+	setSize(SIZE);
+	setJMenuBar(new SimpleMenuBar("thepreviewview"));
+	setTitle(Dictionary.get("PreviewCommandDialog.Title"));
+	
+	JPanel content_pane = (JPanel) getContentPane();
+	content_pane.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
+
+	JTextArea instructions_area = new JTextArea(Dictionary.get("PreviewCommandDialog.Instructions"));
+	instructions_area.setEditable(false);
+	instructions_area.setLineWrap(true);
+	instructions_area.setRows(5);
+	instructions_area.setWrapStyleWord(true);
+	
+	JPanel button_pane = new JPanel();
+	JPanel lower_pane = new JPanel();
+
+	JPanel command_pane = new JPanel();
+	command_field = new JTextField();
+	browse_button = new GLIButton(Dictionary.get("FileAssociationDialog.Browse"));
+	browse_button.setEnabled(!Utility.isMac());
+	if (Utility.isMac()) {
+	    browse_button.setToolTipText(Dictionary.get("FileAssociationDialog.Browse_Tooltip_Mac"));
+	} else {
+	    browse_button.setToolTipText(Dictionary.get("FileAssociationDialog.Browse", "FileAssociationDialog.Browse_Tooltip"));
+	}
+	ok_button = new GLIButton(Dictionary.get("General.OK"), Dictionary.get("FileAssociationDialog.Close_Tooltip"));
+	cancel_button = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("General.Pure_Cancel_Tooltip"));
+	
+	// Connection
+	browse_button.addActionListener(new BrowseButtonListener());
+	ok_button.addActionListener(new OkButtonListener());
+	cancel_button.addActionListener(new CancelButtonListener());
+	
+	// Layout
+	command_pane.setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
+	command_pane.setLayout(new BorderLayout());
+	command_pane.add(command_field, BorderLayout.CENTER);
+	command_pane.add(browse_button, BorderLayout.EAST);
+
+	lower_pane.setBorder(BorderFactory.createEmptyBorder(2,0,0,0));
+
+	button_pane.setLayout(new GridLayout(1,2,5,0));
+	button_pane.add(ok_button);
+	button_pane.add(cancel_button);
+
+	lower_pane.setBorder(BorderFactory.createEmptyBorder(2,0,0,0));
+	lower_pane.setLayout(new BorderLayout());
+	lower_pane.add(command_pane, BorderLayout.CENTER);
+	lower_pane.add(button_pane, BorderLayout.SOUTH);
+
+
+	content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(new JScrollPane(instructions_area), BorderLayout.NORTH);
+	content_pane.add(lower_pane, BorderLayout.CENTER);
+
+	Rectangle screen = Gatherer.g_man.getBounds(null);
+	setLocation((int)(screen.getX() + (screen.getWidth() - SIZE.width) / 2), (int)(screen.getY() + (screen.getHeight() - SIZE.height) / 2));
+	screen = null;
+    }
+
+    public void destroy() {
+	// Disconnect
+	// Clean up
+	self = null;
+    }
+
+    /** Redisplay the dialog
+     */
+    public String display() {
+	setVisible(true);
+	return preview_command;
+    }
+
+
+    private class OkButtonListener
+	implements ActionListener {
+	
+	public void actionPerformed(ActionEvent event) {
+	    preview_command = command_field.getText();
+	    self.dispose();
+	    
+	}
+    }
+
+
+    /** Whenever the user clicks the browse button, we should open up a file browser to allow them to select an executable file from somewhere in the file system. */
+    private class BrowseButtonListener 
+	implements ActionListener {
+	/** Open up a simple JFileChooser when the user clicks the button. 
+	 * @param event An <strong>ActionEvent</strong> containing information about the event.
+	 */
+	public void actionPerformed(ActionEvent event) {
+	    JFileChooser chooser = new JFileChooser(new File(Gatherer.getGLIUserDirectoryPath()));
+	    GUIUtils.disableRename(chooser);
+	    chooser.setDialogTitle(Dictionary.get("FileAssociationDialog.Browse_Title"));
+	    chooser.setFileFilter(new BatchFileFilter());
+	    chooser.setFileFilter(new CoreObjectModelFileFilter());
+	    chooser.setFileFilter(new ExecutableFileFilter());
+	    chooser.setAcceptAllFileFilterUsed(true);
+	    if(chooser.showOpenDialog(Gatherer.g_man) == JFileChooser.APPROVE_OPTION) {
+		command_field.setText(chooser.getSelectedFile().getAbsolutePath());
+	    }
+	}
+    }
+
+    
+    private class CancelButtonListener
+	implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    self.dispose();
+	}
+    }
+
+    /** Batch filter shows only files ending in bat. Based on ImageFilter.java which is a 1.4 example used by FileChooserDemo2.java. */
+    private class BatchFileFilter
+	extends FileFilter {
+
+	/** Accept all .exe files
+	 * @param file a File
+	 * @return true is this file should be shown, false otherwise
+	 */
+	public boolean accept(File file) {
+	    return file.getName().toLowerCase().endsWith(".bat");
+	}
+
+	/** The description of this filter
+	 * @return a String
+	 */
+	public String getDescription() {
+	    return Dictionary.get("FileAssociationDialog.Batch_File");
+	}
+    }
+
+    /** Command filter shows only files ending in com. Based on ImageFilter.java which is a 1.4 example used by FileChooserDemo2.java. */
+    private class CoreObjectModelFileFilter
+	extends FileFilter {
+
+	/** Accept all .com files
+	 * @param file a File
+	 * @return true is this file should be shown, false otherwise
+	 */
+	public boolean accept(File file) {
+	    return file.getName().toLowerCase().endsWith(".com");
+	}
+
+	/** The description of this filter
+	 * @return a String
+	 */
+	public String getDescription() {
+	    return Dictionary.get("FileAssociationDialog.Command_File");
+	}
+    }
+
+
+    /** Executable filter shows only files ending in exe. Based on ImageFilter.java which is a 1.4 example used by FileChooserDemo2.java. */
+    private class ExecutableFileFilter
+	extends FileFilter {
+
+	/** Accept all .exe files
+	 * @param file a File
+	 * @return true is this file should be shown, false otherwise
+	 */
+	public boolean accept(File file) {
+	    return file.getName().toLowerCase().endsWith(".exe");
+	}
+
+	/** The description of this filter
+	 * @return a String
+	 */
+	public String getDescription() {
+	    return Dictionary.get("FileAssociationDialog.Executable_File");
+	}
+    }
+
+
+}
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/RenamePrompt.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/RenamePrompt.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/RenamePrompt.java	(revision 13928)
@@ -0,0 +1,126 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2006 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.CollectionTreeNode;
+
+
+public class RenamePrompt
+    extends JDialog 
+    implements ActionListener, KeyListener
+{
+    private JButton cancel_button;
+    private JButton ok_button;
+    private JTextField name_textfield;
+    private String name;
+
+    static final private Dimension SIZE = new Dimension(350, 100);
+
+
+    public RenamePrompt(CollectionTreeNode collection_tree_node)
+    {
+	super(Gatherer.g_man, true);
+	setTitle(Dictionary.get("RenamePrompt.Title"));
+	name = collection_tree_node.getFile().getName();
+    }
+
+
+    public void actionPerformed(ActionEvent event)
+    {
+	if (event.getSource() == ok_button) {
+	    name = name_textfield.getText();
+	}
+	else if (event.getSource() == cancel_button) {
+	    name = null;
+	}
+	dispose();
+    }
+
+    public void keyPressed(KeyEvent e) {
+	if (e.getKeyCode() == KeyEvent.VK_ENTER) {
+            // Enter: Click the button in focus
+            Object source = e.getSource();
+            if (source instanceof AbstractButton) {
+                ((AbstractButton) source).doClick();
+            } else if (source == name_textfield) {
+		ok_button.doClick();
+	    }
+        }
+    }
+
+    public void keyReleased(KeyEvent e) { }
+    
+    public void keyTyped(KeyEvent e) { }
+
+
+    public String display()
+    {
+	setSize(SIZE);
+	JPanel content_pane = (JPanel) getContentPane();
+
+	JPanel info_pane = new JPanel();
+
+	JLabel name_label = new JLabel(Dictionary.get("RenamePrompt.Name"));
+	name_textfield = new JTextField(name);
+
+	JPanel button_pane = new JPanel();
+	ok_button = new GLIButton(Dictionary.get("General.OK"), Dictionary.get("General.OK_Tooltip"));
+	cancel_button = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("General.Pure_Cancel_Tooltip"));
+	
+	// Connection
+	cancel_button.addActionListener(this);
+	ok_button.addActionListener(this);
+	ok_button.addKeyListener(this);
+	name_textfield.addKeyListener(this);
+
+	// Layout
+	info_pane.setLayout(new BorderLayout(5,0));
+	info_pane.add(name_label, BorderLayout.WEST);
+	info_pane.add(name_textfield, BorderLayout.CENTER);
+
+	button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	button_pane.setLayout(new GridLayout(1,2,0,5));
+	button_pane.add(ok_button);
+	button_pane.add(cancel_button);
+
+	content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(info_pane, BorderLayout.CENTER);
+	content_pane.add(button_pane, BorderLayout.SOUTH);
+
+	// Display
+	Rectangle frame_bounds = Gatherer.g_man.getBounds();
+	setLocation(frame_bounds.x + (frame_bounds.width - SIZE.width) / 2, frame_bounds.y + (frame_bounds.height - SIZE.height) / 2);
+	setVisible(true);
+	return name;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/SimpleMenuBar.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/SimpleMenuBar.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/SimpleMenuBar.java	(revision 13928)
@@ -0,0 +1,33 @@
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.util.JarTools;
+
+public class SimpleMenuBar
+    extends JMenuBar
+    implements ActionListener {
+
+    private String page_name;
+
+    public SimpleMenuBar(String page_name) {
+	this.page_name = page_name;
+	JMenu help = new JMenu();
+	help.setIcon(JarTools.getImage("help.gif"));
+	help.setText(Dictionary.get("Menu.Help"));
+
+	JMenuItem help_help = new JMenuItem(Dictionary.get("Menu.Help"));
+	help_help.addActionListener(this);
+	
+	help.add(help_help);
+
+	add(Box.createHorizontalGlue());
+	add(help);
+    }
+
+    public void actionPerformed(ActionEvent event) {
+	HelpFrame.setView(page_name);
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/SimpleResultDialog.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/SimpleResultDialog.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/SimpleResultDialog.java	(revision 13928)
@@ -0,0 +1,103 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.ArrayList;
+import javax.swing.*;
+import javax.swing.event.*;
+
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.Dictionary;
+
+public class SimpleResultDialog
+    extends ModalDialog {
+    
+    private Dimension size = new Dimension(600,300);
+    private SimpleResultDialog self;
+    
+    public SimpleResultDialog(String title, String label, String results) {
+	super(Gatherer.g_man, title, true);
+	this.self = this;
+	
+	setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
+	setSize(size);
+	
+	JPanel content_pane = (JPanel) getContentPane();
+	JLabel result_label = new JLabel(label);
+	
+	JPanel button_pane = new JPanel();
+	JButton close_button = new GLIButton(Dictionary.get("General.Close"));
+	close_button.addActionListener(new CloseButtonListener());
+	
+	JPanel output_pane = new JPanel();
+	JLabel output_label = new JLabel(Dictionary.get("General.Review_Output"));
+		
+	JTextArea output_textarea = new JTextArea(results);
+	output_textarea.setCaretPosition(0);
+	output_textarea.setEditable(false);
+	output_textarea.setLineWrap(true);
+	output_textarea.setWrapStyleWord(true);
+	
+	button_pane.setLayout(new BorderLayout());
+	button_pane.add(close_button, BorderLayout.EAST);
+	
+	output_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
+	output_pane.setLayout(new BorderLayout());
+	output_pane.add(output_label, BorderLayout.NORTH);
+	output_pane.add(new JScrollPane(output_textarea), BorderLayout.CENTER);
+	
+	content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(result_label, BorderLayout.NORTH);
+	content_pane.add(output_pane, BorderLayout.CENTER);
+	content_pane.add(button_pane, BorderLayout.SOUTH);
+	
+	// Position
+	Rectangle frame_bounds = Gatherer.g_man.getBounds();
+	setLocation(frame_bounds.x + (frame_bounds.width - size.width) / 2, frame_bounds.y + (frame_bounds.height - size.height) / 2);
+    }
+    
+    private class CloseButtonListener
+	implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    self.setVisible(false);
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/URLField.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/URLField.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/URLField.java	(revision 13928)
@@ -0,0 +1,36 @@
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.net.*;
+import javax.swing.*;
+
+
+public class URLField
+    extends JTextField
+{
+    public URLField(Color foreground, Color background)
+    {
+	super();
+	setBackground(background);
+	setForeground(foreground);
+    }
+
+
+    public boolean validateURL()
+    {
+	String url_string = getText();
+	if (!url_string.equals("")) {
+	    // Check the URL string is valid by trying to create a URL object from it
+	    try {
+		new URL(url_string);
+	    }
+	    catch (MalformedURLException exception) {
+		// URL string is invalid
+		return false;
+	    }
+	}
+
+	// URL string is valid
+	return true;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/WarningDialog.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/WarningDialog.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/WarningDialog.java	(revision 13928)
@@ -0,0 +1,253 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Project, NZDL, University of Waikato
+ *
+ * Copyright (C) 2003 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.util.JarTools;
+
+
+/** A dialog that warns about something, and allows the user to turn off the warning in the future. */
+public class WarningDialog
+    extends ModalDialog 
+    implements ActionListener, KeyListener
+{
+    static final private Dimension NORMAL_SIZE = new Dimension(450, 160);
+    static final private Dimension SETTING_SIZE = new Dimension(450, 200);
+
+    private int result = JOptionPane.CANCEL_OPTION;
+    private JButton cancel_button;
+    private JButton ok_button;
+    private JCheckBox show_check;
+    private JTextField value_field;
+    private JPanel value_panel;
+    private String affected_property;
+    private String full_property;
+
+
+    public WarningDialog(String warning_name, String warning_title, String warning_message, String affected_property, boolean can_cancel)
+    {
+	super(Gatherer.g_man, "Warning", true);
+
+	// Determine the name of this prompt.
+	this.affected_property = affected_property;
+	this.full_property = warning_name;
+
+	// Now build dialog.
+	if (affected_property != null) {
+	    setSize(SETTING_SIZE);
+	}
+	else {
+	    setSize(NORMAL_SIZE);
+	}
+	setTitle(warning_title);
+	
+	// Creation
+	JPanel content_pane = (JPanel) getContentPane();
+	JPanel text_pane = new JPanel();
+	JLabel icon_label = new JLabel(JarTools.getImage("gatherer_medium.gif"));
+
+	JTextArea text_area = new JTextArea();
+	text_area.setEditable(false);
+	text_area.setLineWrap(true);
+	text_area.setText(warning_message);
+	text_area.setCaretPosition(0);
+	text_area.setWrapStyleWord(true);
+
+	value_panel = new JPanel();
+	JLabel value_label = new JLabel(Dictionary.get("WarningDialog.Value"));
+	
+	value_field = new JTextField();
+	JPanel bottom_pane = new JPanel();
+	show_check = new JCheckBox(Dictionary.get("WarningDialog.Dont_Show_Again"));
+	JPanel control_pane = new JPanel();
+	ok_button = new GLIButton(Dictionary.get("General.OK"), Dictionary.get("General.OK_Tooltip"));
+	cancel_button = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("General.Pure_Cancel_Tooltip"));
+	
+	// Connection
+	ok_button.addActionListener(this);
+	cancel_button.addActionListener(this);
+	ok_button.addKeyListener(this);
+	cancel_button.addKeyListener(this);
+	getRootPane().setDefaultButton(ok_button);
+
+	// Layout
+	icon_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
+
+	value_label.setBorder(BorderFactory.createEmptyBorder(0, icon_label.getPreferredSize().width, 0, 0));
+
+	value_panel.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	value_panel.setLayout(new BorderLayout(5,0));
+	value_panel.add(value_label, BorderLayout.WEST);
+	value_panel.add(value_field, BorderLayout.CENTER);
+
+	text_pane.setLayout(new BorderLayout());
+	text_pane.add(icon_label, BorderLayout.WEST);
+	text_pane.add(new JScrollPane(text_area), BorderLayout.CENTER);
+	if(affected_property != null) {
+	    text_pane.add(value_panel, BorderLayout.SOUTH);
+	}
+
+	if(can_cancel) {
+	    control_pane.setLayout(new GridLayout(1,2,5,0));
+	    control_pane.add(ok_button);
+	    control_pane.add(cancel_button);
+	}
+	else {
+	    control_pane.setLayout(new BorderLayout());
+	    control_pane.add(ok_button, BorderLayout.EAST);
+	}
+
+	bottom_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	bottom_pane.setLayout(new BorderLayout());
+	bottom_pane.add(show_check, BorderLayout.CENTER);
+	bottom_pane.add(control_pane, BorderLayout.EAST);
+
+	content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(text_pane, BorderLayout.CENTER);
+	content_pane.add(bottom_pane, BorderLayout.SOUTH);
+
+	// Position
+	Dimension size = getSize();
+	if (Gatherer.g_man != null) {
+	    Rectangle frame_bounds = Gatherer.g_man.getBounds();
+	    setLocation(frame_bounds.x + (frame_bounds.width - size.width) / 2, frame_bounds.y + (frame_bounds.height - size.height) / 2);
+	}
+	else {
+	    Dimension screen_size = Toolkit.getDefaultToolkit().getScreenSize();
+	    setLocation((screen_size.width - size.width) / 2, (screen_size.height - size.height) / 2);
+	}
+    }
+
+    public void actionPerformed(ActionEvent event) {
+	boolean bad_value = false;
+	if(event.getSource() == ok_button) {
+	    if(affected_property != null && Configuration.self != null) {
+		String value = value_field.getText();
+		if(value.length() > 0) {
+		   if(value_field instanceof URLField) {
+		      bad_value = !((URLField)value_field).validateURL();
+		   }
+		   if(!bad_value) {
+		      // Store the value of the property
+		      Configuration.setString(affected_property, true, value_field.getText());
+		   }
+		}
+	    }
+	    if(!bad_value) {
+		result = JOptionPane.OK_OPTION;
+	    }
+	}
+	if(!bad_value) {
+	    if (Configuration.self != null) {
+		// Store the state of the show message checkbox.
+		Configuration.set(full_property, true, !show_check.isSelected());
+	    }
+	    // Done.
+	    setVisible(false);
+	}
+	else {
+	    JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("WarningDialog.Invalid_Value"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
+	}
+    }
+
+    /** Gives notification of key events on the buttons */
+    public void keyPressed(KeyEvent e) {
+	if (e.getKeyCode() == KeyEvent.VK_ENTER) {
+	    // Enter: Click the button in focus
+	    Object source = e.getSource();
+	    if (source instanceof AbstractButton) {
+		((AbstractButton) source).doClick();
+	    }
+	}
+    }
+
+    public void keyReleased(KeyEvent e) { }
+
+    public void keyTyped(KeyEvent e) { }
+
+
+    public int display() {
+	if (Configuration.self == null || Configuration.get(full_property, false)) {
+	    setVisible(true);
+	}
+	// We are no longer showing this dialog, so result must always be true.
+	else {
+	    result = JOptionPane.OK_OPTION;
+	}
+	// Ask the parent to repaint, just to be sure
+	if(Gatherer.g_man != null) {
+	    Gatherer.g_man.repaint();
+	}
+	return result;
+    }
+
+    /** Allows you to specify whether this dialog is a warning dialog, or only a message dialog.
+     * @param message_only true if this dialog shows a message, false for a warning
+     */
+    public void setMessageOnly(boolean message_only) {
+	// If this is a message then change the checkbox
+	if(message_only) {
+	    show_check.setText(Dictionary.get("WarningDialog.Dont_Show_Again_Message"));
+	}
+	// And if its a warning, change them back
+	else {
+	    show_check.setText(Dictionary.get("WarningDialog.Dont_Show_Again"));
+	}
+    }
+
+    /** Allows you to replace the generic text field control with a JTextField subclass with further functionality. For instance you might provide a URLField to allow only valid URLs to be accepted.
+     * @param  control the JTextField subclass you want to use for the control
+     */
+    public void setValueField(JTextField control) {
+	// Remove the current control
+	value_panel.remove(value_field);
+	// Replace with the new one
+	value_field = control;
+	// Re-add
+	value_panel.add(value_field, BorderLayout.CENTER);
+    }
+
+    protected void processWindowEvent(WindowEvent event) {
+	if(event.getID() == WindowEvent.WINDOW_ACTIVATED) {
+	    if(affected_property != null) {
+		value_field.requestFocus();
+	    }
+	    else {
+		ok_button.requestFocus();
+	    }
+	}
+	else {
+	    super.processWindowEvent(event);
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/WriteCDImagePrompt.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/WriteCDImagePrompt.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/WriteCDImagePrompt.java	(revision 13928)
@@ -0,0 +1,618 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.ArrayList;
+import javax.swing.*;
+import javax.swing.event.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.BasicCollectionConfiguration;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.greenstone.LocalGreenstone;
+import org.greenstone.gatherer.shell.GShell;
+import org.greenstone.gatherer.shell.GShellEvent;
+import org.greenstone.gatherer.shell.GShellListener;
+import org.greenstone.gatherer.util.ArrayTools;
+import org.greenstone.gatherer.util.CheckList;
+import org.greenstone.gatherer.util.CheckListEntry;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+
+/** This class provides the functionality to write a CD-ROM/DVD image of current collections from the GSDLHOME/collect/ directory to CDROM. The user chooses the collection from a list, where each entry also displays details about itself, confirms the delete of a collection by checking a checkbox then presses the ok button to actually delete the collection.
+    Copied from DeleteCollectionPrompt
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class WriteCDImagePrompt
+    extends ModalDialog 
+    implements GShellListener {
+    
+    private OKButtonListener ok_button_listener;
+    private ArrayList all_collections = null;
+    private ArrayList selected_collections = null;
+    /** The list of collections to include in exported cd-rom/dvd image */
+    private CheckList list = null;
+    /** The currently selected collection for deletion. */
+    private BasicCollectionConfiguration collection = null;
+    /** A reference to ourself so any inner-classes can dispose of us. */
+    private WriteCDImagePrompt prompt = null;
+    /** The close button, which exits the prompt without deleting anything. */
+    private JButton cancel_button = null;
+    /** The ok button which causes the selected collection to be deleted. */
+    private JButton ok_button = null;
+    /** The label above details. */
+    private JLabel details_label = null;
+    /** The label above the list. */
+    private JLabel list_label = null;
+    /** The text area used to display details about the collection selected. */
+    private JTextArea details_textarea = null;
+    /** The text area used to display instructions for the cd-rom/dvd export */
+    private JTextArea instructions_textarea;
+
+    /** The radio button for switching on the noinstall option */
+    private JRadioButton noinstall_button = null;
+    private JRadioButton install_button = null;
+    private JTextField title_field = null;
+    private JTextField estimated_size_field = null;
+    private JLabel title_label = null;
+    private JLabel estimated_size_label = null;
+    /** A string array used to pass arguments to the exportcol.pl script */
+    private String args[] = null;
+    private String cd_title = null;
+    /** whether the exporting was successful or not */
+    private boolean successful = false;
+    /** whether we are trying to export or not */
+    private boolean exporting = false;
+    /** the error message if any */
+    private StringBuffer error_message = null;
+    /** This is the size of the exported stuff on its own without collections. */
+    private long total_exported_size = 14000000;
+    /** The size of the export prompt screen. */
+    public static final Dimension SIZE = new Dimension(500, 500);
+
+    /** Constructor.
+     * @see org.greenstone.gatherer.collection.WriteCDImagePrompt.CancelButtonListener
+     * @see org.greenstone.gatherer.collection.WriteCDImagePrompt.CollectionListListener
+     * @see org.greenstone.gatherer.collection.WriteCDImagePrompt.OKButtonListener
+     */
+    public WriteCDImagePrompt() {
+	super(Gatherer.g_man, true);
+	cancel_button = new GLIButton(Dictionary.get("General.Close"), Dictionary.get("General.Close_Tooltip"));
+	
+	details_textarea = new JTextArea(Dictionary.get("DeleteCollectionPrompt.No_Collection"));
+	details_textarea.setEditable(false);
+	
+	details_label = new JLabel(Dictionary.get("DeleteCollectionPrompt.Collection_Details"));
+	
+	instructions_textarea = new JTextArea(Dictionary.get("WriteCDImagePrompt.Instructions"));
+	instructions_textarea.setCaretPosition(0);
+	instructions_textarea.setEditable(false);
+	instructions_textarea.setLineWrap(true);
+	instructions_textarea.setRows(4);
+	instructions_textarea.setWrapStyleWord(true);
+	
+	all_collections = new ArrayList();
+	list = new CheckList(true);
+	list_label = new JLabel(Dictionary.get("DeleteCollectionPrompt.Collection_List"));
+	
+	ok_button = new GLIButton(Dictionary.get("WriteCDImagePrompt.Export"), Dictionary.get("WriteCDImagePrompt.Export_Tooltip"));
+	
+	title_field = new JTextField();
+	// Dictionary.setTooltip(title_field, "WriteCDImagePrompt.CD_Name_Tooltip");
+	title_label = new JLabel(Dictionary.get("WriteCDImagePrompt.CD_Name"));
+	
+
+	estimated_size_field = new JTextField();
+	estimated_size_field.setEditable(false);
+
+	// work out the size of the images directory - could be large if they
+	// have the classic interface pack installed
+	total_exported_size += getFileSize(new File(LocalGreenstone.getDirectoryPath()+File.separator+"images"));
+	estimated_size_field.setText(Utility.formatFileLength(total_exported_size));
+	estimated_size_field.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+	estimated_size_label = new JLabel(Dictionary.get("WriteCDImagePrompt.Size_Label"));
+	
+	scanForCollections();
+	list.setListData(all_collections);
+
+	prompt = this;
+	setSize(SIZE);
+	setTitle(Dictionary.get("WriteCDImagePrompt.Export"));
+	
+	setJMenuBar(new SimpleMenuBar("exportingcollections")); 
+	cancel_button.addActionListener(new CancelButtonListener());
+	list.addListSelectionListener(new CollectionListListener());
+	list.clearSelection();
+	list.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+	ok_button_listener = new OKButtonListener();
+	ok_button.addActionListener(ok_button_listener);
+	ok_button.setEnabled(false);
+	//title.getDocument().addDocumentListener(new DocumentListener());
+	
+	noinstall_button = new JRadioButton(Dictionary.get("WriteCDImagePrompt.NoInstall"));
+	noinstall_button.setToolTipText(Dictionary.get("WriteCDImagePrompt.NoInstall_Tooltip"));
+	
+	
+	install_button = new JRadioButton(Dictionary.get("WriteCDImagePrompt.Install"));
+	install_button.setToolTipText(Dictionary.get("WriteCDImagePrompt.Install_Tooltip"));
+	
+
+	
+    }
+
+    /** Destructor. */
+    public void destroy() {
+	all_collections.clear();
+	all_collections = null;
+	cancel_button = null;
+	details_textarea = null;
+	details_label = null;
+	list = null;
+	ok_button = null;
+	prompt = null;
+	if (selected_collections!=null) {
+	    selected_collections.clear();
+	    selected_collections = null;
+	}
+	title_field = null;
+	title_label = null;
+    }
+
+    /** This method causes the modal prompt to be displayed. 
+     * returns true if it has exported the collections that are currently selected */
+    public boolean display() {
+
+	// Radio buttons
+	ButtonGroup radio_group = new ButtonGroup();
+	radio_group.add(install_button);
+	install_button.setSelected(true);
+	radio_group.add(noinstall_button);
+
+	// Top pane
+	JPanel instructions_pane = new JPanel(new BorderLayout());
+	instructions_pane.setBorder(BorderFactory.createEmptyBorder(5,5,0,5));
+	instructions_pane.add(new JScrollPane(instructions_textarea), BorderLayout.CENTER);
+	
+	title_label.setBorder(BorderFactory.createEmptyBorder(0,5,0,15));
+
+	JPanel title_pane = new JPanel(new BorderLayout());
+	title_pane.add(title_label, BorderLayout.WEST);
+	title_pane.add(title_field, BorderLayout.CENTER);
+	title_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
+
+	JPanel radio_pane = new JPanel(new GridLayout(2,1));
+	install_button.setBackground(Configuration.getColor("coloring.collection_heading_background", true));
+	noinstall_button.setBackground(Configuration.getColor("coloring.collection_heading_background", true));
+	radio_pane.add(install_button);
+	radio_pane.add(noinstall_button);
+	
+	
+	JPanel options_pane = new JPanel(new BorderLayout());
+	options_pane.add(title_pane, BorderLayout.NORTH);
+	options_pane.add(radio_pane, BorderLayout.CENTER);
+	instructions_pane.add(options_pane, BorderLayout.SOUTH);
+
+	// Central pane
+	JPanel list_pane = new JPanel(new BorderLayout());
+	list_pane.add(list_label, BorderLayout.NORTH);
+	list_pane.add(new JScrollPane(list), BorderLayout.CENTER);
+	list_pane.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0));
+
+	JPanel details_pane = new JPanel(new BorderLayout());
+	details_pane.add(details_label, BorderLayout.NORTH);
+	details_pane.add(new JScrollPane(details_textarea), BorderLayout.CENTER);
+	details_pane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
+
+	JPanel central_pane = new JPanel(new GridLayout(2, 1));
+	central_pane.add(list_pane);
+	central_pane.add(details_pane);
+	central_pane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+
+	// Lower pane
+	JPanel estimated_size_pane = new JPanel(new BorderLayout());
+	estimated_size_pane.add(estimated_size_label, BorderLayout.WEST);
+	estimated_size_pane.add(estimated_size_field, BorderLayout.CENTER);
+	estimated_size_pane.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0));
+
+	JPanel button_pane = new JPanel(new GridLayout(1, 2));
+	button_pane.add(ok_button);
+	button_pane.add(cancel_button);
+	button_pane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
+
+	JPanel lower_pane = new JPanel(new BorderLayout());
+	lower_pane.add(estimated_size_pane, BorderLayout.NORTH);
+	lower_pane.add(button_pane, BorderLayout.SOUTH);
+	lower_pane.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
+
+	// Final.
+	JPanel content_pane = (JPanel)this.getContentPane();
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(instructions_pane, BorderLayout.NORTH);
+	content_pane.add(central_pane, BorderLayout.CENTER);
+	content_pane.add(lower_pane, BorderLayout.SOUTH);
+
+	// Center and display.
+	Dimension screen_size = Configuration.screen_size;
+	this.setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+	this.setVisible(true); // blocks until the dialog is killed
+	return true;
+	
+    }
+
+    
+    private long getFileSize(File file)
+    {
+	long file_size = 0;
+	
+	// Directory case
+	if (file.isDirectory()) {
+	    File files[] = file.listFiles();
+	    for (int i = 0; i < files.length; i++) {
+		file_size += getFileSize(files[i]);
+	    }
+	}
+	// File case
+	else {
+	    file_size = file.length();
+	}
+	
+	return file_size;
+    }
+
+    /** This method calls the builcol.pl scripts via a GShell so as to not lock up the processor.
+     * @see org.greenstone.gatherer.Configuration
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.collection.Collection
+     * @see org.greenstone.gatherer.gui.BuildOptions
+     * @see org.greenstone.gatherer.shell.GShell
+     * @see org.greenstone.gatherer.shell.GShellListener
+     * @see org.greenstone.gatherer.shell.GShellProgressMonitor
+     * @see org.greenstone.gatherer.util.Utility
+     */
+    public void writeCDImageCollections()
+    {
+	DebugStream.println("WriteCDImagePrompt.writeCDImageCollections()");
+
+	int num_collections = selected_collections.size();
+	if (num_collections == 0) return;
+	cd_title = title_field.getText();
+	cd_title = cd_title.trim();
+	cd_title = cd_title.replaceAll("\"","");
+	
+	// Generate the exportcol.pl command
+	ArrayList command_parts_list = new ArrayList();
+	if (Utility.isWindows() && (!Gatherer.isGsdlRemote)) {
+	    command_parts_list.add(Configuration.perl_path);
+	    command_parts_list.add("-S");
+	}
+	command_parts_list.add(LocalGreenstone.getBinScriptDirectoryPath() + "exportcol.pl");
+
+	command_parts_list.add("-gli");
+	command_parts_list.add("-language");
+	command_parts_list.add(Configuration.getLanguage());
+
+	if (cd_title.equals("")) {
+	    command_parts_list.add("-cdname");
+	    command_parts_list.add("Greenstone Collections");
+
+	    command_parts_list.add("-cddir");
+	    command_parts_list.add("exported_collections");
+	}
+	else {
+	    command_parts_list.add("-cdname");
+	    command_parts_list.add(cd_title);
+
+	    String cd_dir = "exported_"+cd_title.replaceAll("\\s","");
+	    command_parts_list.add("-cddir");
+	    command_parts_list.add(cd_dir);
+	}
+
+	if (noinstall_button.isSelected()) {
+	    command_parts_list.add("-noinstall");
+	}
+
+	for (int i = 0; i < num_collections; i++) {
+	    command_parts_list.add(((BasicCollectionConfiguration) selected_collections.get(i)).getShortName());
+	}
+
+	DebugStream.print("export command = ");
+	for (int i = 0; i < command_parts_list.size(); i++) {
+	    DebugStream.print(command_parts_list.get(i) + " ");
+	}
+	DebugStream.println("");
+	// Run the exportcol.pl command
+	String[] command_parts = (String[]) command_parts_list.toArray(new String[0]);
+	GShell process = new GShell(command_parts, GShell.CDIMAGE, 3, this, null, GShell.GSHELL_CDIMAGE);
+	process.start();
+	//process.run();
+	DebugStream.println("WriteCDImagePrompt.writeCDImageCollections().return");
+	
+    }
+
+    /** Shows an export complete prompt. 
+     * @param success A <strong>boolean</strong> indicating if the collection was successfully deleted.
+     * @see org.greenstone.gatherer.collection.Collection
+     */
+    public void resultPrompt(boolean success, String extra) {
+	args = new String[2];
+	StringBuffer coll_names = new StringBuffer();
+	for (int i=0; i<selected_collections.size();i++) {
+	    if (i>0) {
+		coll_names.append(", ");
+	    }
+	    BasicCollectionConfiguration complete_collection = (BasicCollectionConfiguration)selected_collections.get(i);
+	    coll_names.append(complete_collection.getName() + StaticStrings.SPACE_CHARACTER + StaticStrings.OPEN_PARENTHESIS_CHARACTER + complete_collection.getShortName() + StaticStrings.CLOSE_PARENTHESIS_CHARACTER);
+	    complete_collection = null;
+	}
+	
+	args[0] = coll_names.toString();
+	args[1] = LocalGreenstone.getTmpDirectoryPath();
+	if(cd_title.equals("")) {
+	    args[1] += "exported_collections";
+	} else {
+	    args[1] += "exported_"+cd_title.replaceAll("\\s","");
+	}
+	String title;
+	String label;
+	if (success) {
+	    title = Dictionary.get("WriteCDImagePrompt.Successful_Title");
+	    label = Dictionary.get("WriteCDImagePrompt.Successful_Export", args);
+	} else {
+	    title = Dictionary.get("WriteCDImagePrompt.Failed_Title");
+	    label = Dictionary.get("WriteCDImagePrompt.Failed_Export", args);
+	}
+	SimpleResultDialog result_dialog = new SimpleResultDialog(title, label, extra);
+	result_dialog.setVisible(true); // Blocks
+	result_dialog.dispose();
+	result_dialog = null;
+    }
+
+    /** Method to scan the collect directory retrieving and reloading each collection it finds, while building the list of known collections.
+     * @see org.greenstone.gatherer.Configuration
+     * @see org.greenstone.gatherer.Gatherer
+     * @see org.greenstone.gatherer.util.ArrayTools
+     * @see org.greenstone.gatherer.util.Utility
+     */
+    private void scanForCollections() {
+	// Start at the collect dir.
+	File collect_directory = new File(Gatherer.getCollectDirectoryPath());
+	if (collect_directory.exists()) {
+	    // Now for each child directory see if it contains a .col file and
+	    // if so try to load it..
+	    File collections[] = collect_directory.listFiles();
+	    ArrayTools.sort(collections);
+	    for(int i = 0; collections != null && i < collections.length; i++) {
+		if(collections[i].isDirectory() && !collections[i].getName().equals(StaticStrings.MODEL_COLLECTION_NAME)) {
+		    File config_file = new File(collections[i], Utility.CONFIG_FILE);
+		    if (config_file.exists()) {
+			BasicCollectionConfiguration config = new BasicCollectionConfiguration(config_file);
+			all_collections.add(config);		        
+			config = null;
+		    }
+		}
+	    }
+	}
+	// Otherwise the collect directory doesn't actually exist, so there ain't much we can do.
+    }
+
+
+    /** All implementation of GShellListener must include this method so the listener can be informed of messages from the GShell.
+     * @param event A <strong>GShellEvent</strong> that contains, amoung other things, the message.
+     */
+    public synchronized void message(GShellEvent event) {
+	// Ignore the messages from RecPlug with 'show_progress' set (used for progress bars)
+	String message = event.getMessage();
+	if (message.startsWith("exportcol.pl>")) {
+	    message = message.substring(13);
+	    //DebugStream.println("message = "+event.getMessage());
+	    error_message.append(message);
+	    error_message.append("\n");
+	}
+    }
+
+    /** All implementation of GShellListener must include this method so the listener can be informed when a GShell begins its task. Implementation side-effect, not actually used.
+     * @param event A <strong>GShellEvent</strong> that contains details of the initial state of the <strong>GShell</strong> before task comencement.
+     */
+    public synchronized void processBegun(GShellEvent event) {
+	// We don't care. 
+    }
+    /** All implementation of GShellListener must include this method so the listener can be informed when a GShell completes its task.
+     * @param event A <strong>GShellEvent</strong> that contains details of the final state of the <strong>GShell</strong> after task completion.
+     */
+    public synchronized void processComplete(GShellEvent event) {
+	successful = false;
+	if(event.getStatus() == GShell.OK) {
+	    if(event.getType() == GShell.CDIMAGE) {
+		successful = true;
+	    }
+	}
+	ok_button_listener.processComplete();
+    }
+
+    /** A button listener implementation, which listens for actions on the close button and disposes of the dialog when detected. */
+    private class CancelButtonListener 
+	implements ActionListener {
+	/** Any implementation of ActionListener must include this method so we can be informed when the button is actioned.
+	 * @param event An <strong>ActionEvent</strong> containing all the relevant information garnered from the event itself.
+	 */
+	public void actionPerformed(ActionEvent event) {
+	    prompt.dispose();
+	}
+    }
+
+    /** This private class listens for selection events in from the list and then displays the appropriate details for that collection.
+     */
+    private class CollectionListListener 
+	implements ListSelectionListener
+    {
+	/** Any implementation of ListSelectionListener must include this method so we can be informed when the list selection changes.
+	 * @param  event a <strong>ListSelectionEvent</strong> containing all the relevant information garnered from the event itself
+	 */
+	public void valueChanged(ListSelectionEvent event)
+	{
+	    // Wait for things to settle down a bit
+	    if (event.getValueIsAdjusting()) {
+		return;
+	    }
+
+	    // Can only export when something is ticked
+	    ok_button.setEnabled(!list.isNothingTicked());
+
+	    if (list.isSelectionEmpty()) {
+		// This only happens when the dialog is first entered
+		details_textarea.setText(Dictionary.get("DeleteCollectionPrompt.No_Collection"));
+		return;
+	    }
+
+	    collection = (BasicCollectionConfiguration) ((CheckListEntry) list.getSelectedValue()).getObject();
+	    args = new String[3];
+	    args[0] = collection.getCreator();
+	    args[1] = collection.getMaintainer();
+	    args[2] = collection.getDescription();
+	    details_textarea.setText(Dictionary.get("DeleteCollectionPrompt.Details", args));
+	    details_textarea.setCaretPosition(0);
+
+	    // Find the size of the "etc", "images" and "index" directories of the collection
+	    String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection.getShortName());
+	    File etc_directory = new File(collection_directory_path + "etc");
+	    File images_directory = new File(collection_directory_path + "images");
+	    File index_directory = new File(collection_directory_path + "index");
+	    long collection_size_built = getFileSize(etc_directory) + getFileSize(images_directory) + getFileSize(index_directory);
+
+	    // Add/subtract it from the total, depending on whether the collection has just been ticked/unticked
+	    if (((CheckListEntry) list.getSelectedValue()).isSelected()) {
+		total_exported_size += collection_size_built;
+	    }
+	    else {
+		total_exported_size -= collection_size_built;
+	    }
+
+	    // Update the size field
+	    estimated_size_field.setText(Utility.formatFileLength(total_exported_size));
+	}
+    }
+
+
+    /** The OK button listener implementation. */
+    private class OKButtonListener 
+	implements ActionListener {
+	private Component glass_pane;
+	private MouseListener mouse_blocker_listener;
+	private ProgressDialog progress_dialog;
+
+	/** Any implementation of ActionListener must include this method so we can be informed when the button is actioned.
+	 * @param event An <strong>ActionEvent</strong> containing all the relevant information garnered from the event itself.
+	 * @see org.greenstone.gatherer.Configuration
+	 * @see org.greenstone.gatherer.Gatherer
+	 * @see org.greenstone.gatherer.util.Utility
+	 */
+	public void actionPerformed(ActionEvent event) {
+	    ///ystem.err.println("OK Clicked");
+	    // Make sure there are some colls specified
+	    selected_collections = list.getTicked();
+	    error_message = new StringBuffer();
+	    
+	    // Set the cursor to hourglass
+	    glass_pane = getGlassPane();
+	    mouse_blocker_listener = new MouseAdapter() {};
+	    glass_pane.addMouseListener(mouse_blocker_listener);
+	    glass_pane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+	    glass_pane.setVisible(true);
+
+	    // Export the selected collection.
+	    ///ystem.err.println("Write CD-ROM/DVD image for named collections");
+	    writeCDImageCollections();
+
+	    // Show progress dialog
+	    ///ystem.err.println("Showing progress dialog");
+	    progress_dialog = new ProgressDialog();
+	    progress_dialog.setVisible(true);
+	}
+
+	public void processComplete() {
+	    ///ystem.err.println("Process complete");
+	    // Dispose of progress dialog
+	    progress_dialog.setVisible(false);
+	    progress_dialog.dispose();
+	    progress_dialog = null;
+
+	    // unset the cursor
+	    glass_pane.setVisible(false);
+	    glass_pane.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+	    glass_pane.removeMouseListener(mouse_blocker_listener);
+	    glass_pane = null;
+	    mouse_blocker_listener= null;
+	    
+	    if (successful) {
+		resultPrompt(true, error_message.toString());
+	    } else {
+		resultPrompt(false, error_message.toString());
+	    }
+	    error_message = null;
+	}
+
+	private class ProgressDialog 
+	    extends ModalDialog {
+	    
+	    private Dimension size = new Dimension(400,65);
+	    
+	    public ProgressDialog() {
+		super(Gatherer.g_man, Dictionary.get("WriteCDImagePrompt.Title"), true);
+		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
+		setSize(size);
+		JPanel content_pane = (JPanel) getContentPane();
+		JLabel progress_label = new JLabel(Dictionary.get("WriteCDImagePrompt.Progress_Label"));
+		
+		JProgressBar progress_bar = new JProgressBar();
+		progress_bar.setIndeterminate(true);
+		content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+		content_pane.setLayout(new BorderLayout());
+		content_pane.add(progress_label, BorderLayout.NORTH);
+		content_pane.add(progress_bar, BorderLayout.CENTER);
+		// Position
+		Rectangle frame_bounds = Gatherer.g_man.getBounds();
+		setLocation(frame_bounds.x + (frame_bounds.width - size.width) / 2, frame_bounds.y + (frame_bounds.height - size.height) / 2);
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/metaaudit/Autofilter.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/metaaudit/Autofilter.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/metaaudit/Autofilter.java	(revision 13928)
@@ -0,0 +1,379 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui.metaaudit;
+
+
+import java.util.ArrayList;
+import org.greenstone.gatherer.util.StaticStrings;
+
+/** An Autofilter object stores the filters set on a single column, and provides a method for determining if a certain value passes the filter.
+ * @author John Thompson
+ * @version 2.3
+ */
+public class Autofilter {
+
+    static public void main(String[] args) {
+	if(args.length != 2) {
+	    System.err.println("Usage: java Autofilter <string> <pattern>");
+	}
+	else {
+	    switch(compareToPattern(args[0], args[1])) {
+	    case LESS_THAN:
+		System.err.print(args[0] + " is less than");
+		break;
+	    case GREATER_THAN:
+		System.err.print(args[0] + " is greater than");
+		break;
+	    case EQUAL:
+		System.err.print(args[0] + " is equal to");
+		break;
+	    default:
+		System.err.print(args[0] + " is something to");
+	    }
+	    System.err.println(" " + args[1]);
+	}
+    }
+
+    /** A String comparison which also recognises the WildCard character. The basic idea is that '*' matches zero or more of any characters, and if we limited patterns to be like "a*" then as soon as we hit the star we could return a match. The problem is that we want patterns like "b*y" which would match "boy" but not "bee" nor "bus" (but should return less than or greater than for each of these respectively). Thus our testing has to become non-deterministic so the matches are conducted like so: 
+     * Given p = [ b * y ]
+     * Test  s = [ b e e ]  Result: p0=s0,{(p2>s1=>ERROR),(p1=s1,{(p1>s2=>ERROR),(p2>s2=>LESS_THAN)})} => LESS_THAN
+     * Test  s = [ b o y ]  Result: p0=s0,{(p2>s1=>ERROR),(p1=s1,{(p1>s2=>ERROR),(p2=s2=>EQUAL)})} => EQUAL
+     * Test  s = [ b u s ]  Result: p0=s0,{(p2>s1=>ERROR),(p1=s1,{(p1>s2=>ERROR),(p2<s2=>GREATER_THAN)})} => GREATER_THAN
+     * where the two () phrases within a {} represent two different 'threads' of processing. Errors are generated when one string runs out of characters before the other. Only non-error results are propogated. I've decided to implement this non-deterministic matching as a recursive function call.
+     * If you analyse it you can see there are three possible actions when a '*' is detected.
+     * 1. * is an empty string, ignore it in pattern and try to compare the next character in p with the current character in s. This case only occurs if there are more characters in p (otherwise apple would be greater than a*)
+     * 2. * matches exactly the current character in s, try to match the next character in p with the next character in s
+     * 3. * matches some string of characters including the current character in s, try to match '*' against the next character in s
+     * @param  s the String being matched
+     * @param  p the Pattern to match it against
+     * @return -1 if s is less than p, 0 if they are equal, 1 if s is greater than p
+     */
+    static private int compareToPattern(String s, String p) {
+	if(p.indexOf(StaticStrings.STAR_CHAR) == -1) {
+	    return compareToPattern(s, p, 0, 0, false);
+	}
+	else {
+	    return compareToPattern(s, p, 0, 0, true);
+	}
+    }
+
+    static final private int LESS_THAN = -1;
+    static final private int EQUAL = 0;
+    static final private int GREATER_THAN = 1;
+    static final private int ERROR = 42;
+
+    static private int compareToPattern(String s, String p, int s_index, int p_index, boolean wildcard_matching) {
+	// Lets do the simple cases first.
+	// Both out of characters at the same time
+	if(s_index >= s.length() && p_index >= p.length()) {
+	    ///ystem.err.println("Both out of characters. Equal.");
+	    return EQUAL;
+	}
+	// s out of characters first
+	if(s_index >= s.length()) {
+	    // Not allowed to run out if matching wildcard
+	    if(wildcard_matching) {
+		return ERROR;
+	    }
+	    // Remember that wildcard matches the empty string too, so as long as there are only '*' characters left in the pattern we can say they are equal as well.
+	    else {
+		while(p_index < p.length()) {
+		    if(p.charAt(p_index) == StaticStrings.STAR_CHAR) {
+			p_index++;
+		    }
+		    else {
+			///ystem.err.println("S out of characters. Less Than.");
+			return LESS_THAN;
+		    }
+		}
+		// We've run out of pattern and it only contained '*' so we're still equal
+		///ystem.err.println("Both out of characters. Equal.");
+		return EQUAL;
+	    }
+	}
+	// p out of characters first
+	if(p_index >= p.length()) {
+	    // Not allowed to run out if matching wildcard
+	    if(wildcard_matching) {
+		return ERROR;
+	    }
+	    // so it is greater than
+	    else {
+		///ystem.err.println("P out of characters. Greater Than.");
+		return GREATER_THAN;
+	    }
+	}
+	char s_char = s.charAt(s_index);
+	char p_char = p.charAt(p_index);
+	///ystem.err.println("Comparing " + s_char + " against pattern character " + p_char);
+	// Equivelent characters
+	// Now the tricky-dicky bit - WildCard matching.
+	if(p_char == StaticStrings.STAR_CHAR) {
+	    int result;
+	    // Case 1
+	    ///ystem.err.println("WildCard Case 1");
+	    if(p_index + 1 < p.length()) {
+		if((result = compareToPattern(s, p, s_index, p_index + 1, wildcard_matching)) != ERROR) {
+		    return result;
+		}
+	    }
+	    // Case 2
+	    ///ystem.err.println("WildCard Case 2");
+	    if((result = compareToPattern(s, p, s_index + 1, p_index + 1, wildcard_matching)) != ERROR) {
+		return result;
+	    } 
+	    // Case 3
+	    ///ystem.err.println("WildCard Case 3");
+	    if((result = compareToPattern(s, p, s_index + 1, p_index, wildcard_matching)) != ERROR) {
+		return result;
+	    }
+	}
+	if(s_char == p_char) {
+	    return compareToPattern(s, p, s_index + 1, p_index + 1, wildcard_matching);
+	}
+	// A preceeding character
+	if(s_char < p_char) {
+	    ///ystem.err.println("s char is less than p char");
+	    if(wildcard_matching) {
+		///ystem.err.println("Because we are wildcard matching we still have to match the rest of s incase of errors.");
+		if(compareToPattern(s, p, s_index + 1, p_index + 1, wildcard_matching) != ERROR) {
+		    ///ystem.err.println("No error. Less than.");
+		    return LESS_THAN;
+		}
+		else {
+		    ///ystem.err.println("Error detected.");
+		    return ERROR;
+		}
+	    }
+	    else {
+		///ystem.err.println("Less than.");
+		return LESS_THAN;
+	    }
+	}
+	// A succeeding character
+	if(s_char > p_char) {
+	    ///ystem.err.println("s char is greater than p char");
+	    if(wildcard_matching) {
+		///ystem.err.println("Because we are wildcard matching we still have to match the rest of s incase of errors.");
+		if(compareToPattern(s, p, s_index + 1, p_index + 1, wildcard_matching) != ERROR) {
+		    ///ystem.err.println("No error. Greater than.");
+		    return GREATER_THAN;
+		}
+		else {
+		    ///ystem.err.println("Error detected.");
+		    return ERROR;
+		}
+	    }
+	    else {
+		///ystem.err.println("Greater than.");
+		return GREATER_THAN;
+	    }
+	}
+	// Oh-No. Well, we'll just assume that string is less than pattern
+	return LESS_THAN;
+    }
+
+    /** <i>true</i> if the filter should be applied, <i>false</i> to indicate the filter is turned off. */
+    public boolean active;
+    /** <i>true</i> if the matching for the first expression should be case sensitive, <i>false</i> otherwise. */
+    public boolean casesense_one;
+    /** <i>true</i> if the matching for the second expression should be case sensitive, <i>false</i> otherwise. */
+    public boolean casesense_two;
+    /** Used to determine the operation intended when applying two filters, and set using the values of the OPERATION_TYPE enumeration. */
+    public boolean operation;
+    /** Used to determine how the column this filter is applied to should be sorted, and set using the values of the SORT_TYPE enumeration. */
+    public boolean sort;
+    /** The method to be used for the first filter expression, set from the values of the METHOD_LIST enumeration. */
+    public int method_one;
+    /** The method to be used for the second filter expression, set from the values of the METHOD_LIST enumeration. */
+    public int method_two;
+    /** The value to be matched against for the first expression. */
+    public String value_one;
+    /** The value to be matched against for the second expression. */
+    public String value_two;
+    /** An element of the SORT_TYPE enumeration, indicates lowest to highest value column ordering. */
+    public static final boolean ASCENDING = true;
+    /** An element of the OPERATION_TYPE enumeration, indicates that both filter expressions must be met (conjunction). */
+    public static final boolean AND = true;
+    /** An element of the SORT_TYPE enumeration, indicates highest to lowest value column ordering. */
+    public static final boolean DESCENDING = false;
+    /** An element of the OPERATION_TYPE enumeration, indicates that either (or both) filter expressions must be met (disjunction). */
+    public static final boolean OR = false;
+    /** An enumeration of symbolic names of various matching methods. */
+    public static final String METHOD_LIST[] = { "Autofilter.eqeq", "Autofilter.!eq", "Autofilter.<", "Autofilter.<eq", "Autofilter.>", "Autofilter.>eq", "Autofilter.^", "Autofilter.!^", "Autofilter.$", "Autofilter.!$", "Autofilter.?", "Autofilter.!?" };
+
+    /** Default Constructor. */
+    public Autofilter() {
+	operation = OR;
+	sort = ASCENDING;
+    }
+    /** Determine if this filter is currently active.
+     * @return <i>true</i> if it is active, <i>false</i> otherwise.
+     */
+    public boolean active() {
+	return active;
+    }
+    /** Determine if this list of values (for a certain cell) passes the filter.
+     * @param values An <strong>ArrayList</strong> of values sourced from a single cell in the associated column.
+     * @return <i>true</i> if the values match and should be displayed, <i>false</i> otherwise.
+     */
+    public boolean filter(ArrayList values) {
+	boolean result = false;
+	if(value_one != null) {
+	    result = filter(values, method_one, value_one, casesense_one);
+	    if(result) {
+		if(operation == AND && value_two != null) {
+		    result = filter(values, method_two, value_two, casesense_two);
+		}
+	    }
+	    else if(operation == OR && value_two != null) {
+		result = filter(values, method_two, value_two, casesense_two);
+	    }
+	}
+	return result;
+    }
+    /** Set the current activity state of this filter.
+     * @param active The new state of this filter, <i>true</i> to activate, <i>false</i> otherwise.
+     */
+    public void setActive(boolean active) {
+	this.active = active;
+    }
+    /** Set one of the filter expressions using the given information.
+     * @param number The number of the filter you wish to set as an <i>int</i>. Either 1 or 2.
+     * @param method An <i>int</i> indicating the method to be used when matching.
+     * @param value The <strong>String</strong> to be matched against.
+     * @param casesense <i>true</i> if this expression should be case sensitive, <i>false</i> otherwise.
+     */
+    public void setFilter(int number, int method, String value, boolean casesense) {
+	if(!casesense && value != null) {
+	    value = value.toLowerCase();
+	}
+	if(number == 1) {
+	    casesense_one = casesense;
+	    method_one = method;
+	    value_one = value;
+	}
+	else {
+	    casesense_two = casesense;
+	    method_two = method;
+	    value_two = value;
+	}
+    }
+    /** Set the operation to be used to join the two filters (if a second filter is set).
+     * @param operation <i>true</i> for conjunct filters, <i>false</i> for disjunct.
+     */ 
+    public void setOperation(boolean operation) {
+	this.operation = operation;
+    }
+    /** Set the sort order of this column.
+     * @param sort <i>true</i> for ascending sort, <i>false</i> for descending.
+     */
+    public void setSort(boolean sort) {
+	this.sort = sort;
+    }
+    /** Decide whether a row should be displayed or filtered. The result depends on the selector set with setFilterType.
+     * @param values An <strong>ArrayList</strong> of values to be checked against the filter.
+     * @param method The method of matching to be used, as an <i>int</i>.
+     * @param target The <strong>String</Strong> to match against.
+     * @param casesense <i>true</i> if the match is to be case sensitive, <i>false</i> otherwise.
+     * @return <i>true</i> to display the row, <i>false</i> to hide it.
+     */
+    public boolean filter(ArrayList values, int method, String target, boolean casesense) {
+	boolean result = false;
+	// There are several special cases when the filter always returns turn, such as when the target is the wildcard character.
+	if(target == null || target.length() == 0 || target.equals("*")) {
+	    result = true;
+	}
+	else {
+	    // For each value in the list...
+	    for(int i = 0; i < values.size(); i++) {
+		boolean pass;
+		String source;
+		// Account for case sensitivity.
+		if(casesense) {
+		    source = values.get(i).toString();
+		}
+		else {
+		    source = values.get(i).toString().toLowerCase();
+		}
+		///ystem.err.println("Testing " + source + " against pattern " + target);
+		// Perform the match, based on the selected method.
+		switch(method) {
+		case 1: // !EQ
+		    pass = (compareToPattern(source, target) != 0);
+		    break;
+		case 2: // <
+		    pass = (compareToPattern(source, target) < 0);
+		    break;
+		case 3: // <eq
+		    pass = (compareToPattern(source, target) <= 0);
+		    break;
+		case 4: // >
+		    pass = (compareToPattern(source, target) > 0);
+		    break;
+		case 5: // >eq
+		    pass = (compareToPattern(source, target) >= 0);
+		    break;
+		case 6: // ^
+		    pass = source.startsWith(target);
+		    break;
+		case 7: // !^
+		    pass = !(source.startsWith(target));
+		    break;
+		case 8: // $
+		    pass = source.endsWith(target);
+		    break;
+		case 9: // !$
+		    pass = !(source.endsWith(target));
+		    break;
+		case 10: // ?
+		    pass = (source.indexOf(target) != -1);
+		    break;
+		case 11: // !?
+		    pass = (source.indexOf(target) == -1);
+		    break;
+		default: // EQEQ
+		    pass = (compareToPattern(source, target) == 0);
+		    break;
+		}
+		result = result || pass;
+	    }
+	}
+	return result;		 
+    }
+    /** Produce a textual representation of this autofilter.
+     * @return A <strong>String</strong> displaying details of this autofilter.
+     */
+    public String toString() {
+	String result = "One: " + method_one + " - " + value_one + " - " + casesense_one;
+	if(value_two != null) {
+	    result = result + "\n" + "Operation: " + (operation?"AND":"OR") + "\n";
+	    result = result + "Two: " + method_two + " - " + value_two + " - " + casesense_two;
+	}
+	return result;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/metaaudit/AutofilterDialog.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/metaaudit/AutofilterDialog.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/metaaudit/AutofilterDialog.java	(revision 13928)
@@ -0,0 +1,410 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui.metaaudit;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.gui.GLIButton;
+import org.greenstone.gatherer.gui.SimpleMenuBar;
+import org.greenstone.gatherer.gui.ModalDialog;
+
+/** The autofilter concept comes from Microsoft Excel spreadsheets that use autofilters to filter to the sheet. When you click on the heading of a column, a new prompt allows you to specify what filter should be acting apon the selected column. Any new filter is conjoined with any previous filters to provide a sheet containing only rows that match all current filters. Each column must also provide an indicator for determining if a filter is set (in this case a special icon) and and a method for removing a filter (use the clear filter button within the autofilter dialog). Having recently discovered that most JVMs aren't very good at recoving memory used by dialog and frame windows, special care must be made to deallocate all references properly, as a user may open several dozen autofilter prompts over the lifetime of a session.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public final class AutofilterDialog
+    extends ModalDialog {
+    /** The filter being edited. */
+    private Autofilter filter;
+    /** A reference to ourselves so our inner classes can reference us. */
+    private AutofilterDialog self;
+
+    private boolean cancelled;
+    /** The value returned from the filter dialog prompt. Used to determine if a prompt was set or unset, and what subsequent action to take. */
+    private byte return_value = 0;
+    /** The button used to cancel the prompt. */
+    private JButton cancel_button = null;
+    private JButton remove_button = null;
+    private JButton set_button = null;
+    /** Used to specify that the given filters should be applied conjunctly. */
+    private JRadioButton and_radiobutton = null;
+    /** The check box used to specify whether the first filter is case sensitive. */
+    private JCheckBox first_case = null;
+    /** Used to disable the second filter. */
+    private JRadioButton none_radiobutton = null;
+    /** Used to specify that the given filters should be applied disjunctly. */
+    private JRadioButton or_radiobutton = null;
+    /** The check box used to specify whether the second filter is case sensitive. */
+    private JCheckBox second_case = null;
+    /** Used to specify the order of the resulting set: Ascending or Descending. */
+    private JRadioButton ascending_radiobutton = null;
+    private JRadioButton descending_radiobutton = null;
+    /** The method used to match the first filter: Contains, Doesn't contain etc. */
+    private JComboBox first_method = null;
+    /** The value to be matched for the first filter. */
+    private JComboBox first_value = null;
+    /** The method used to match the first filter. Options as for the first method. */
+    private JComboBox second_method = null;
+    /** The value to be matched for the second filter. */
+    private JComboBox second_value = null;
+    /** Used for the most basic filter where an Equals, Case sensitive method is automatically used. */
+    private JComboBox value = null;
+    /** The label which displays the name of the currently selected column (the column that will be associated with the autofilter this dialog produces). */
+    private JLabel name;
+    /** The autofilter prompt contains two different panes, one for basic functionality and one for advanced. This containiner component is used to allow access to each via a 'tabbed' interface. */
+    private JTabbedPane control = null;
+    /** A reference back to the MetaAudit dialog that spawned this prompt. Used to make sure that any open dialog window is always in front of the audit pane. */
+    private MetaAuditFrame dialog;
+    /** The default size for the autofilter control. */
+    static final private Dimension SIZE = new Dimension(640, 245);
+
+    /** Constructor.
+     * @param dialog A reference to the <strong>MetaAuditFrame</strong> that spawned this dialog.
+     * @see org.greenstone.gatherer.gui.metaaudit.Autofilter
+     * @see org.greenstone.gatherer.gui.metaaudit.AutofilterDialog.ButtonListener
+     * @see org.greenstone.gatherer.gui.metaaudit.AutofilterDialog.CheckListener
+     */
+    public AutofilterDialog(MetaAuditFrame dialog) {
+	super(Gatherer.g_man);
+	this.dialog = dialog;
+	this.self = this;
+	setModal(true);
+	setJMenuBar(new SimpleMenuBar("reviewingmetadata")); 
+	setSize(SIZE);
+	setTitle(Dictionary.get("Autofilter.Title"));
+	
+	// Creation
+	JPanel content_pane = (JPanel) getContentPane();
+	JPanel name_pane = new JPanel();
+	JLabel name_label = new JLabel(Dictionary.get("Autofilter.Name"));
+	JTextField name_template = new JTextField();
+	name = new JLabel();
+	name.setBorder(name_template.getBorder());
+	control = new JTabbedPane();
+	JPanel value_pane = new JPanel();
+	JPanel inner_value_pane = new JPanel();
+	JLabel value_label = new JLabel(Dictionary.get("Autofilter.eqeq"));
+	value = new JComboBox();
+	value.setOpaque(false);
+	value.setEditable(false);
+	JPanel custom_pane = new JPanel();
+
+	JPanel first_pane = new JPanel();
+	first_method = new JComboBox();
+	first_method.setOpaque(false);
+	first_value = new JComboBox();
+	first_value.setOpaque(false);
+	first_value.setEditable(true);
+	first_value.addItem("");
+	first_value.setSelectedItem("");
+	first_case = new JCheckBox(Dictionary.get("Autofilter.Case_Sensitive"));
+	JPanel operator_pane = new JPanel();
+	JLabel operator_label = new JLabel(Dictionary.get("Autofilter.Operator"));
+	ButtonGroup operator_group = new ButtonGroup();
+	and_radiobutton = new JRadioButton(Dictionary.get("Autofilter.AND"));
+	and_radiobutton.setOpaque(false);
+	none_radiobutton = new JRadioButton(Dictionary.get("Autofilter.None"));
+	none_radiobutton.setOpaque(false);
+	none_radiobutton.setSelected(true);
+	or_radiobutton = new JRadioButton(Dictionary.get("Autofilter.OR"));
+	or_radiobutton.setOpaque(false);
+	operator_group.add(none_radiobutton);
+	operator_group.add(and_radiobutton);
+	operator_group.add(or_radiobutton);
+
+	JPanel second_pane = new JPanel();
+	second_method = new JComboBox();
+	second_method.setOpaque(false);
+	second_method.setEnabled(false);
+	second_value = new JComboBox();
+	second_value.setOpaque(false);
+	second_value.setEditable(true);
+	second_value.setEnabled(false);
+	second_value.addItem("");
+	second_value.setSelectedItem("");
+	second_case = new JCheckBox(Dictionary.get("Autofilter.Case_Sensitive"));
+	JPanel lower_pane = new JPanel();
+	JPanel order_pane = new JPanel();
+	order_pane.setToolTipText(Dictionary.get("Autofilter.Order_Tooltip"));
+	JLabel order_label = new JLabel(Dictionary.get("Autofilter.Order"));
+	
+	ButtonGroup order_group = new ButtonGroup();
+	ascending_radiobutton = new JRadioButton(Dictionary.get("Autofilter.Ascending"));
+	ascending_radiobutton.setOpaque(false);
+	ascending_radiobutton.setSelected(true);
+	descending_radiobutton = new JRadioButton(Dictionary.get("Autofilter.Descending"));
+	descending_radiobutton.setOpaque(false);
+	order_group.add(ascending_radiobutton);
+	order_group.add(descending_radiobutton);
+
+	// Assign values to method comboboxes.
+	for(int i = 0; i < Autofilter.METHOD_LIST.length; i++) {
+	    first_method.addItem(Dictionary.get(Autofilter.METHOD_LIST[i]));
+	    second_method.addItem(Dictionary.get(Autofilter.METHOD_LIST[i]));
+	}
+	JPanel button_pane = new JPanel();
+	cancel_button = new GLIButton(Dictionary.get("General.Cancel"), Dictionary.get("General.Pure_Cancel_Tooltip"));
+	remove_button = new GLIButton(Dictionary.get("Autofilter.Remove"), Dictionary.get("Autofilter.Remove_Tooltip"));
+	set_button = new GLIButton(Dictionary.get("Autofilter.Set"), Dictionary.get("Autofilter.Set_Tooltip"));
+	
+	// Connection
+	and_radiobutton.addActionListener(new CheckListener(true));
+	none_radiobutton.addActionListener(new CheckListener(false));
+	or_radiobutton.addActionListener(new CheckListener(true));
+	cancel_button.addActionListener(new ButtonListener()); // It returns any currently set filter
+	remove_button.addActionListener(new ButtonListener(false));
+	set_button.addActionListener(new ButtonListener(true));
+
+	// Layout		  
+	name_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
+
+	name_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
+	name_pane.setLayout(new BorderLayout());
+	name_pane.add(name_label, BorderLayout.WEST);
+	name_pane.add(name, BorderLayout.CENTER);
+
+	value_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
+
+	inner_value_pane.setLayout(new BorderLayout());
+	inner_value_pane.add(value_label, BorderLayout.WEST);
+	inner_value_pane.add(value, BorderLayout.CENTER);
+
+	value_pane.setBorder(BorderFactory.createEmptyBorder(5,10,5,10));
+	value_pane.setLayout(new BorderLayout());
+	value_pane.add(inner_value_pane, BorderLayout.NORTH);
+
+	first_pane.setLayout(new BorderLayout());
+	first_pane.add(first_method, BorderLayout.WEST);
+	first_pane.add(first_value, BorderLayout.CENTER);
+	first_pane.add(first_case, BorderLayout.EAST);
+
+	operator_pane.setLayout(new GridLayout(1,4));
+	operator_pane.add(operator_label);
+	operator_pane.add(none_radiobutton);
+	operator_pane.add(and_radiobutton);
+	operator_pane.add(or_radiobutton);
+
+	second_pane.setLayout(new BorderLayout());
+	second_pane.add(second_method, BorderLayout.WEST);
+	second_pane.add(second_value, BorderLayout.CENTER);
+	second_pane.add(second_case, BorderLayout.EAST);
+
+	order_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	order_pane.setLayout(new GridLayout(1,2));
+	order_pane.add(order_label);
+	order_pane.add(ascending_radiobutton);
+	order_pane.add(descending_radiobutton);
+
+	custom_pane.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
+	custom_pane.setLayout(new GridLayout(3,1));
+	custom_pane.add(first_pane);
+	custom_pane.add(operator_pane);
+	custom_pane.add(second_pane);
+
+	control.add(Dictionary.get("Autofilter.Filter_By_Value"), value_pane);
+	control.add(Dictionary.get("Autofilter.Custom_Filter"), custom_pane);
+
+	button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+	button_pane.setLayout(new GridLayout(1, 3));
+	button_pane.add(set_button);
+	button_pane.add(remove_button);
+	button_pane.add(cancel_button);
+
+	lower_pane.setLayout(new BorderLayout());
+	lower_pane.add(order_pane, BorderLayout.CENTER);
+	lower_pane.add(button_pane, BorderLayout.SOUTH);
+
+	content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(name_pane, BorderLayout.NORTH);
+	content_pane.add(control, BorderLayout.CENTER);
+	content_pane.add(lower_pane, BorderLayout.SOUTH);
+
+	Dimension screen_size = Configuration.screen_size;
+	setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+	screen_size = null;
+    }
+
+    public boolean cancelled() {
+	return cancelled;
+    }
+
+    /** Destructor. */
+    public void destroy() {
+	dispose();
+	first_case = null;
+	second_case = null;
+	first_method = null;
+	first_value = null;
+	second_method = null;
+	second_value = null;
+	value = null;
+	control = null;
+	dialog = null;
+	self = null;
+	name = null;
+    }
+    /** Display the modal dialog box, allowing the user to define the filter. When the user presses one of the buttons, dispose and return to the caller providing an indication of which button was pressed.
+     * @return An <i>int</i> which indicates which button was pressed to dismiss the dialog.
+     */
+    public Autofilter display(Autofilter filter, ArrayList raw_values, String column_name) {
+	this.cancelled = false;
+	this.filter = filter;
+	name.setText(column_name);
+	// Prune values so it only contains unique entries, then order.
+	TreeSet values = new TreeSet(raw_values);
+	value.setModel(new DefaultComboBoxModel(values.toArray()));
+	String star = "*";
+	value.insertItemAt(star, 0);
+	value.setSelectedItem(star);
+	first_value.setModel(new DefaultComboBoxModel(values.toArray()));
+	second_value.setModel(new DefaultComboBoxModel(values.toArray()));
+	// Restore previous values.
+	if(filter != null && filter.value_one != null) {
+	    value.setSelectedItem(filter.value_one);
+	    first_method.setSelectedIndex(filter.method_one);
+	    first_value.setSelectedItem(filter.value_one);
+	    first_case.setSelected(filter.casesense_one);
+	    if (filter.value_two == null) {
+		none_radiobutton.setSelected(true);
+	    }
+	    else {
+		if (filter.operation) {
+		    and_radiobutton.setSelected(true);
+		}
+		else {
+		    or_radiobutton.setSelected(true);
+		}
+		second_method.setSelectedIndex(filter.method_two);
+		second_value.setSelectedItem(filter.value_two);
+		second_case.setSelected(filter.casesense_two);
+	    }
+	    if (filter.sort) {
+		ascending_radiobutton.setSelected(true);
+		// order.setSelectedIndex(0);
+	    }
+	    else {
+		descending_radiobutton.setSelected(true);
+		// order.setSelectedIndex(1);
+	    }
+	}
+	// Display	  
+	setVisible(true);
+	dialog.toFront();
+	return this.filter;
+    }
+
+    /** Listens for actions on the button it is attached to, and when notified sets the return_value and disposes of the dialog. */
+    private final class ButtonListener
+	implements ActionListener {
+	private boolean cancel_button;
+	private boolean return_filter;
+	
+	/** Default constructor. Returns any filter that was already set */
+	public ButtonListener() {
+	    this.cancel_button = true;
+	}
+
+	/** Does an action on this button cause a filter to be returned. */
+	/** Constructor takes an associated return value as an argument.
+	 * @param return_filter <i>true</i> if we update then return the filter, <i>false</i> to clear existing filter.
+	 */
+	public ButtonListener(boolean return_filter) {
+	    this.cancel_button = false;
+	    this.return_filter = return_filter;
+	}
+	/** When any registered component is actioned apon, set the value and hide the dialog. We hide rather than dispose, because hide assures the data values will be retained. 
+	 * @param event An <strong>ActionEvent</strong> containing information about the action that caused this method call.
+	 * @see org.greenstone.gatherer.gui.metaaudit.Autofilter
+	 */
+	public void actionPerformed(ActionEvent event) {
+	    if(cancel_button) {
+		cancelled = true;
+	    }
+	    else if(return_filter) {
+		if(control.getSelectedIndex() == 0) {
+		    filter.setFilter(1, 0, (String)value.getSelectedItem(), true);
+		    filter.setFilter(2, 0, null, true);
+		}
+		else {
+		    filter.setFilter(1, first_method.getSelectedIndex(), (String)first_value.getSelectedItem(), first_case.isSelected());
+		    if(!none_radiobutton.isSelected()) {
+			if (and_radiobutton.isSelected()) {
+			    filter.setOperation(Autofilter.AND);
+			}
+			else {
+			    filter.setOperation(Autofilter.OR);
+			}
+			filter.setFilter(2, second_method.getSelectedIndex(), (String)second_value.getSelectedItem(), second_case.isSelected());
+		    }
+		}
+		if (ascending_radiobutton.isSelected()) {
+		    filter.setSort(Autofilter.ASCENDING);
+		}
+		else {
+		    filter.setSort(Autofilter.DESCENDING);
+		}
+	    }
+	    else {
+		filter = null;
+	    }
+	    setVisible(false);
+	}
+    }
+    /** Listens for actions on the check box it is attached to, and when notified sets the state of the second method and value to the specified state. */
+    private final class CheckListener
+	implements ActionListener {
+	/** The default desire state any check button this listens to. */
+	private boolean desired_state = false;
+	/** The constructor takes an associated desired state.
+	 * @param desired_state The state that should be set when this is actioned, as a <i>boolean</i>.
+			*/
+	public CheckListener(boolean desired_state) {
+	    this.desired_state = desired_state;
+	}
+	/** Whenever our registered components are actioned apon, set the state of the second method and value to the desired state. */
+	public void actionPerformed(ActionEvent event) {
+	    second_method.setEnabled(desired_state);
+	    second_value.setEnabled(desired_state);
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/metaaudit/Filter.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/metaaudit/Filter.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/metaaudit/Filter.java	(revision 13928)
@@ -0,0 +1,151 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui.metaaudit;
+
+/**************************************************************************************
+ * Title:        Gatherer
+ * Description:  The Gatherer: a tool for gathering and enriching a digital collection.
+ * Company:      The University of Waikato
+ * Written:      03/09/02
+ * Revised:      04/10/02 - Commented
+ **************************************************************************************/
+import de.qfs.lib.gui.TableModelFilter;
+import de.qfs.lib.gui.TableModelFilterEvent;
+import de.qfs.lib.gui.TableModelFilterListener;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Vector;
+import javax.swing.table.TableModel;
+
+/** This class essentially manages the autofilters applied to the metaaudit table.
+ * @author John Thompson
+ * @version 2.3
+ */
+public class Filter
+    implements TableModelFilter {
+    /** An array of autofilters. */
+    private Autofilter filters[];
+    /** The registered TableModelFilterListeners. */
+    private Vector listeners = new Vector ();
+    /** Constructor. 
+     * @param columns The number of columns this Filter will be expected to filter, as an <i>int</i>. 
+     */
+    public Filter(int columns) {
+	filters = new Autofilter[columns];
+    }
+    /** Add a TableModelFilterListener to the TableModelFilter. 
+     * @param listener The <strong>TableModelFilterListener</strong> to add, if it isn't already registered.
+     */
+    public synchronized void addTableModelFilterListener(TableModelFilterListener listener) {
+	if (!listeners.contains(listener)) {
+	    listeners.addElement(listener);
+	}
+    }
+    /** Remove a filter from a column.
+     * @param column The column number to remove the filter from, as an <i>int</i>.
+     */
+    public void clearFilter(int column) {
+	if(filters[column] != null) {
+	    filters[column].setActive(false);
+	}
+    }
+
+
+    /** Determine if a certain row should be shown in the table by checking it against all the current filters.
+     * @param model The <strong>TableModel</strong> the row is from.
+     * @param row The row number as an <i>int</i>
+     * @return <i>true</i> if the rows data matches all autofilters set and should be displayed, <i>false</i> otherwise.
+     */
+    public boolean filter(TableModel model, int row)
+    {
+	for (int i = 0; i < filters.length; i++) {
+	    if (filters[i] != null && filters[i].active()) {
+		ArrayList values = (ArrayList) model.getValueAt(row, i);
+		if (filters[i].filter(values) == false) {
+		    return false;
+		}
+	    }
+	}
+
+	return true;
+    }
+
+
+    /** Retrieve the autofilter associated with a certain column.
+     * @param column The column number as an <i>int</i>.
+     * @return The <strong>Autofilter</strong> assigned to that column.
+     */
+    public Autofilter getFilter(int column) {
+	Autofilter filter = filters[column];
+	if(filter == null) {
+	    filter = new Autofilter();
+	    filters[column] = filter;
+	}
+	return filter;
+    }
+    /** Determine if a certain column is filtered.
+     * @param column The column number as an <i>int</i>.
+     * @return <i>true</i> if there is an active autofilter assigned to this column, <i>false</i> otherwise.
+     */
+    public boolean isFiltered(int column) {
+	boolean result = false;
+	if(filters[column] != null) {
+	    result = filters[column].active();
+	}
+	return result;
+    }
+    /** Remove a TableModelFilterListener from the TableModelFilter.
+     * @param listener The <strong>TableModelFilterListener</strong> to remove.
+     */
+    public synchronized  void removeTableModelFilterListener(TableModelFilterListener listener) {
+	listeners.removeElement(listener);
+    }
+    /** Called whenever the filters assigned changes significantly, thus prompting a reload of the table model data. */
+    public void fireFilterChanged() {
+	///ystem.err.println("Filter Changed!");
+	Vector tmp;
+	synchronized(this) {
+	    tmp = (Vector) listeners.clone();
+	}
+		  
+	TableModelFilterEvent event = new TableModelFilterEvent (this);
+	Enumeration enumeration = tmp.elements();
+	while (enumeration.hasMoreElements()) {
+	    ((TableModelFilterListener) enumeration.nextElement()).filterChanged(event);
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/metaaudit/HeaderListener.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/metaaudit/HeaderListener.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/metaaudit/HeaderListener.java	(revision 13928)
@@ -0,0 +1,79 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui.metaaudit;
+
+
+import de.qfs.lib.gui.TableModelSorter;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import org.greenstone.gatherer.metadata.MetadataAuditTableModel;
+
+public class HeaderListener
+    extends MouseAdapter {
+    private MetaAuditFrame parent_frame;
+    private MetaAuditTable table;
+    public HeaderListener(MetaAuditFrame parent_frame, MetaAuditTable table) {
+	this.parent_frame = parent_frame;
+	this.table = table;
+    }
+
+    public void mouseClicked(MouseEvent event) {
+	// Determine the column this was clicked on.
+	int column = table.getColumnModel().getColumnIndexAtX(event.getX());
+	int clicked_column = table.convertColumnIndexToModel(column);
+	// Display the currently assigned filter.
+	Filter filter_model = table.getFilter();
+	Autofilter filter = filter_model.getFilter(clicked_column);
+	MetadataAuditTableModel model = table.getOriginalModel();
+	ArrayList default_values = model.getColumnValues(clicked_column);
+	String column_name = model.getColumnName(clicked_column);
+	filter = parent_frame.autofilter_dialog.display(filter, default_values, column_name);
+	if(!parent_frame.autofilter_dialog.cancelled()) {
+	    if(filter == null) {
+		filter_model.clearFilter(clicked_column);
+	    }
+	    else {
+		filter.setActive(true);
+		TableModelSorter sorter = table.getSorter();
+		sorter.setSortColumn(clicked_column);
+		sorter.setSortAscending(filter.sort);
+	    }
+	    filter_model.fireFilterChanged();
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/metaaudit/HeaderRenderer.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/metaaudit/HeaderRenderer.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/metaaudit/HeaderRenderer.java	(revision 13928)
@@ -0,0 +1,79 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui.metaaudit;
+
+import java.awt.*;
+import javax.swing.*;
+import javax.swing.table.TableCellRenderer;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.util.JarTools;
+
+/** This custom button renderer replaces the boring old column headers with clickable versions which are based on JToggleButtons.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class HeaderRenderer 
+    extends JToggleButton
+    implements TableCellRenderer {
+
+    /** The constructor sets up a margin around the button, and adds the filter icons.
+     */
+    public HeaderRenderer() {
+	setMargin(new Insets(0,0,0,0));
+	setIcon(JarTools.getImage("filter.gif"));
+	setSelectedIcon(JarTools.getImage("filter-on.gif")); 
+    }
+
+    /** Called to create the component to be used as the 'rubber-stamp' for the table cell given the follwing arguments.
+     * @param table The <strong>JTable</strong> that is asking the renderer to draw; can be <i>null</i>.
+     * @param value The value of the cell to be rendered as an <strong>Object</strong>. It is up to the specific renderer to interpret and draw the value. For example, if value is the string "true", it could be rendered as a string or it could be rendered as a check box that is checked. null is a valid value.
+     * @param isSelected <i>true</i> if the cell is to be rendered with the selection highlighted; otherwise <i>false</i>.
+     * @param hasFocus If <i>true</i>, render cell appropriately. For example, put a special border on the cell, if the cell can be edited, render in the color used to indicate editing.
+     * @param row The row index of the cell being drawn as an <i>int</i>. When drawing the header, the value of row is -1.
+     * @param column The column index of the cell being drawn as an <i>int</i>.
+     * @see org.greenstone.gatherer.gui.metaaudit.MetaAuditTable
+     */
+    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
+	setText(value.toString());
+	setToolTipText(Dictionary.get("Autofilter.Table_Header_Tooltip", value.toString()));
+	MetaAuditTable temp = (MetaAuditTable) table;
+	if (temp != null) { // And it may if this is called during table init.
+	    setSelected(temp.isFiltered(column));
+	}
+	return this;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/metaaudit/MetaAuditFrame.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/metaaudit/MetaAuditFrame.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/metaaudit/MetaAuditFrame.java	(revision 13928)
@@ -0,0 +1,214 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui.metaaudit;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.CollectionTreeNode;
+import org.greenstone.gatherer.gui.GLIButton;
+import org.greenstone.gatherer.gui.SimpleMenuBar;
+import org.greenstone.gatherer.gui.ModalDialog;
+
+
+/** The MetaAuditFrame provides a table view of all of the metadata assigned to a selection of CollectionTreeNodes. All values for a certain file and a certain metadata element appear in the same cell. This table can be sorted by any column, and also has a MS Excel-like AutoFilter allowing you to restrict the rows visible to only those that match a certain set of criteria (applied to each column, and then 'ANDED', or cojoined, to determine the filter). Finally this dialog does not block the Gatherer tool, so the file selection can be changed and the dialog will just generate a new table dynamically.<BR>
+ * Much effort has gone into optimizing this table, as it quickly becomes slow and unresponsive to build/filter/sort when the number of records selected is high. However its performance is still nowhere as good as the Excel spreadsheet, and selections of 1000+ records can cause some serious waiting problems. Performance progression, shown in terms of time taken to perform action, are shown below. Note that building includes both the creation of the data model, and/or the time taken to lay out row and column sizes (due to this using multiple entry cells). Also all tables, by default, must be sorted by one column, which is initially the first column in ascending order:<BR><BR>
+ * <TABLE border=1 cellspacing=0 cellpadding=5>
+ * <TR><TD align=center colspan=5>Time Taken with 1000 records (ms)</TD></TR>
+ * <TR><TD>Action</TD><TD>Original</TD><TD>Revision 1</TD><TD>Revision 2</TD><TD>Revision 3</TD></TR>
+ * <TR><TD>Build</TD><TD align=right>113013</TD><TD align=right>1500</TD><TD align=right>1280</TD><TD align=right>665</TD></TR>
+ * <TR><TD>Sort</TD><TD align=right>34228</TD><TD align=right>353</TD><TD align=right>341</TD><TD align=right>338</TD></TR>
+ * <TR><TD>Filter</TD><TD align=right>57110</TD><TD align=right>485</TD><TD align=right>485</TD><TD align=right>485</TD></TR>
+ * </TABLE>
+ * <BR><BR>
+ * <TABLE border=1 cellspacing=0 cellpadding=5>
+ * <TR><TD align=center colspan=5>Time Taken with 10,000 records (ms) [hdlsub]</TD></TR>
+ * <TR><TD>Action</TD><TD>Original</TD><TD>Revision 1</TD><TD>Revision 2</TD><TD>Revision 3</TD></TR>
+ * <TR><TD>Build</TD><TD align=right>DNF</TD><TD align=right>8667</TD><TD align=right>6784</TD><TD align=right>3081</TD></TR>
+ * <TR><TD>Sort</TD><TD align=right>DNF</TD><TD align=right>236</TD><TD align=right>241</TD><TD align=right>228</TD></TR>
+ * <TR><TD>Filter</TD><TD align=right>DNF</TD><TD align=right>59272</TD><TD align=right>59767</TD><TD align=right>59614</TD></TR>
+ * </TABLE>
+ * <BR><BR>
+ * <TABLE border=1 cellspacing=0 cellpadding=5>
+ * <TR><TD align=center colspan=5>Time Taken with 30,000 records (ms) [hdl]</TD></TR>
+ * <TR><TD>Action</TD><TD>Original</TD><TD>Revision 1</TD><TD>Revision 2</TD><TD>Revision 3</TD></TR>
+ * <TR><TD>Build</TD><TD align=right>DNF</TD><TD align=right>19037</TD><TD align=right>16478</TD><TD align=right>8111</TD></TR>
+ * <TR><TD>Sort</TD><TD align=right>DNF</TD><TD align=right>314</TD><TD align=right>301</TD><TD align=right>385</TD></TR>
+ * <TR><TD>Filter</TD><TD align=right>DNF</TD><TD align=right>[300000]</TD><TD align=right>[300000]</TD><TD align=right>[300000]</TD></TR>
+ * </TABLE><BR><BR>
+ * It is easy to see that while building and sorting have become quite fast and reasonable, sorting is still unacceptable in terms of performance. The difficulty is this, that while sorting is easy (and fast) to implement via the Decorator pattern (making the overall table model a MDVC one) it requires the entire contents of a column to be available. Thus no matter the speed of your sort algorithm you will end up making N calls to getValueAt() in the table data model, for N records. This is not a problem for the initial model, hence the small sort times. However when you attempt to place another deocrator model (or modify the existing one) in order to filter only selected rows, even if the filtering itself takes little time, this little time quickly grows to unacceptable levels. In fact testing has shown it to grow much faster than linear time (though I'm not sure where). Doubling the number of records to filter increases the processing time by 5-7 times.<BR>
+ * In attempting to solve this problem, I have found many resources that mention a similar problem when trying to build visual representations of database tables, especially over networks or other temporally-non-deterministic connections. The common solution is to 'page' only those records necessary into memory on demand, thus making initial response significantly faster, while paying a small price for subsequent page seeks. There are even studies and algorithms for determining pages loads etc, I would imagine garnered from the memory management community. However none of these really help me usless I can get around the problem of having to have the entire columns population immeditaly accessable for sorting purposes.<BR>
+ * I believe with more time is would be possible to make a hybrid table model with properties such as you would require for the aforemenetioned database application, but which also provides fast methods for determining the highest and lowest records perhaps by building traversable heaps in the original model. Such a solution would incur a build penalty, and could consume significant memory, but would provide ordered and sequential access to the data within.<BR>
+ * The discussion aside, I have run out of time to do anything further on this, so will include as is, and provide a warning dialog whenever the number of records might suffer slow processing (1000+ records).
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class MetaAuditFrame
+    extends ModalDialog 
+    implements TreeSelectionListener {
+    public AutofilterDialog autofilter_dialog;
+    /** Whether the selection has changed since the last time we built the model (because it has been hidden and theres no point refreshing a model you can't see!). */
+    private boolean invalid = true;
+    /** An array holding the most recent list of paths selected (plus some nulls for those paths removed). */
+    private CollectionTreeNode[] records = null;
+    /** A reference to ourselves so that inner classes can interact with us. */
+    private MetaAuditFrame self;
+    /** The table in which the metadata is shown. */
+    private MetaAuditTable table;
+    /** The default size for the metaaudit dialog. */
+    static final private Dimension SIZE = new Dimension(640,505);
+
+
+    public MetaAuditFrame()
+    {
+	super(Gatherer.g_man);
+
+	// Arguments
+	this.autofilter_dialog = new AutofilterDialog(this);
+	this.self = this;
+	this.table = new MetaAuditTable(this);
+
+	// Creation
+	setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
+	setSize(SIZE);
+	setTitle(Dictionary.get("MetaAudit.Title"));
+	setJMenuBar(new SimpleMenuBar("reviewingmetadata")); 
+	
+	JPanel content_pane = (JPanel) getContentPane();
+	JPanel button_pane = new JPanel();
+
+	JButton close_button = new GLIButton(Dictionary.get("MetaAudit.Close"), Dictionary.get("MetaAudit.Close_Tooltip"));
+	
+	// Connection
+	close_button.addActionListener(new CloseListener());
+	Gatherer.c_man.getCollectionTree().addTreeSelectionListener(this);
+
+	// Layout
+	button_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	button_pane.setLayout(new BorderLayout());
+	button_pane.add(close_button, BorderLayout.CENTER);
+		 
+	content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	content_pane.setLayout(new BorderLayout());
+	content_pane.add(new JScrollPane(table), BorderLayout.CENTER);
+	content_pane.add(button_pane, BorderLayout.SOUTH);
+		  
+	Dimension screen_size = Configuration.screen_size;
+	setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+	screen_size = null;
+	close_button = null;
+	button_pane = null;
+	content_pane = null;
+    }
+
+    /** Destructor. */
+    public void destroy() {
+	records = null;
+	self = null;
+	table = null;
+    }
+
+    /** Display the dialog on screen. */
+    public void display() {
+	if(invalid) {
+	    rebuildModel();
+	}
+	setVisible(true);
+    }
+
+    /** This method is called whenever the selection within the collection tree changes. This causes the table to be rebuilt with a new model.
+     * @param event A <strong>TreeSelectionEvent</strong> containing information about the event.
+     */
+    public void valueChanged(TreeSelectionEvent event) {
+	Object source = event.getSource();
+	if(source instanceof JTree) {
+	    TreePath paths[] = ((JTree)source).getSelectionPaths();
+	    if(paths != null) {
+		records = new CollectionTreeNode[paths.length];
+		for(int i = 0; i < paths.length; i++) {
+		    records[i] = (CollectionTreeNode) paths[i].getLastPathComponent();
+		}
+		if(isVisible()) {
+		    rebuildModel();
+		}
+		else {
+		    invalid = true;
+		}
+	    }
+	}
+    }
+
+    public void wait(boolean waiting) {
+	Component glass_pane = getGlassPane();
+	if(waiting) {
+	    // Show wait cursor.
+	    glass_pane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+	    glass_pane.setVisible(true);
+	}
+	else {
+	    // Hide wait cursor.
+	    glass_pane.setVisible(false);
+	    glass_pane.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+	}
+	glass_pane = null;
+    }
+
+    /** Rebuild the metaaudit table model using the current collection tree selection. 
+     */
+    private void rebuildModel() {
+	// Build and set model
+	table.newModel(records);
+	// Done.
+	invalid = false;
+    }
+
+    /** Listens for actions upon the close button, and if detected closes the dialog */
+    private class CloseListener
+	implements ActionListener {
+	/** Any implementation of ActionListener must include this method so that we can be informed when an action has been performed on our target control(s).
+	 * @param event An <strong>ActionEvent</strong> containing information about the event.
+	 */
+	public void actionPerformed(ActionEvent event) {
+	    self.setVisible(false);
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/metaaudit/MetaAuditRenderer.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/metaaudit/MetaAuditRenderer.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/metaaudit/MetaAuditRenderer.java	(revision 13928)
@@ -0,0 +1,63 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui.metaaudit;
+
+import java.awt.*;
+import java.util.ArrayList;
+import javax.swing.*;
+import javax.swing.table.DefaultTableCellRenderer;
+
+public class MetaAuditRenderer
+    extends DefaultTableCellRenderer {
+
+    public Component getTableCellRendererComponent(JTable table, Object value, boolean is_selected, boolean has_focus, int row, int column) {
+	ArrayList array = (ArrayList) value;
+	JLabel label = (JLabel) super.getTableCellRendererComponent(table, "", is_selected, has_focus, row, column);
+	JPanel panel = new JPanel();
+	panel.setBackground(label.getBackground());
+	panel.setBorder(label.getBorder());
+	if(array != null) {
+	    panel.setLayout(new GridLayout(array.size(), 1));
+	    for(int i = 0; i < array.size(); i++) {
+		JLabel entry = new JLabel(array.get(i).toString());
+		entry.setFont(label.getFont());
+		panel.add(entry);
+	    }
+	}
+	return panel;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/metaaudit/MetaAuditTable.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/metaaudit/MetaAuditTable.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/metaaudit/MetaAuditTable.java	(revision 13928)
@@ -0,0 +1,198 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui.metaaudit;
+
+import de.qfs.lib.gui.*;
+import java.awt.*;
+import java.util.ArrayList;
+import javax.swing.JTable;
+import javax.swing.event.TableModelEvent;
+import javax.swing.table.*;
+import org.greenstone.gatherer.collection.CollectionTreeNode;
+import org.greenstone.gatherer.metadata.MetadataAuditTableModel;
+
+
+/**
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class MetaAuditTable
+    extends JTable 
+    implements TableModelSorterListener {
+
+    private boolean initial_state;
+
+    private Filter filter;
+
+    private HeaderRenderer header_renderer;
+
+    private MetaAuditFrame parent_frame;
+
+    private MetaAuditRenderer cell_renderer;
+
+    private MetadataAuditTableModel metadata_audit_table_model;
+
+    private SortedTableHelper helper;
+
+    static final private int MARGIN = 10;
+
+    public MetaAuditTable(MetaAuditFrame parent_frame) {
+	super();
+	this.cell_renderer = new MetaAuditRenderer();
+	this.header_renderer = new HeaderRenderer();
+	this.parent_frame = parent_frame;
+	getTableHeader().addMouseListener(new HeaderListener(parent_frame, this));
+	setAutoResizeMode(AUTO_RESIZE_OFF);
+    }
+
+    public Filter getFilter() {
+	return filter;
+    }
+
+
+   public MetadataAuditTableModel getOriginalModel()
+   {
+      return metadata_audit_table_model;
+   }
+
+
+    public TableModelSorter getSorter() {
+	return helper.getTableModelSorter();
+    }
+
+    public boolean isFiltered(int column) {
+	if(filter == null) {
+	    return false;
+	}
+	return filter.isFiltered(column);
+    }
+
+    public void newModel(CollectionTreeNode records[]) {
+	if(records == null || records.length == 0) {
+	    setModel(new DefaultTableModel());
+	    return;
+	}
+	wait(true);
+	initial_state = true;
+	// System.err.println("Build new Model - should only be called once per click!");
+	metadata_audit_table_model = new MetadataAuditTableModel();
+	metadata_audit_table_model.rebuild(records);
+	setModel(metadata_audit_table_model);
+	filter = new Filter(metadata_audit_table_model.getColumnCount());
+	helper = new SortedTableHelper (this, filter, new DefaultTableModelSorter(), header_renderer, null);
+	helper.prepareTable();
+	// Add renderer to columns.
+	TableColumnModel column_model = getColumnModel();
+	for(int i = 0; i < column_model.getColumnCount(); i++) {
+	    column_model.getColumn(i).setCellRenderer(cell_renderer);
+	    column_model.getColumn(i).setHeaderRenderer(header_renderer);
+	}
+	wait(false);
+	initial_state = false;
+    }
+
+    public void tableChanged(TableModelEvent e) {
+	wait(true);
+	super.tableChanged(e);
+
+	// Create storage area
+	ArrayList heights[] = new ArrayList[dataModel.getRowCount()];
+	int widths_value[] = new int[dataModel.getColumnCount()];
+	ArrayList widths[] = new ArrayList[dataModel.getColumnCount()];
+
+	// Iterate through cell values finding tallest and widest for each row and column respectively.
+	for (int j = 0; j < dataModel.getRowCount(); j++) {
+	    for (int k = 0; k < dataModel.getColumnCount(); k++) {
+		Object object = dataModel.getValueAt(j, k);
+		if (object instanceof ArrayList) {
+		    ArrayList data = (ArrayList) object;
+		    if (heights[j] == null || data.size() > heights[j].size()) {
+			heights[j] = data;
+		    }
+		    String longest = "";
+		    for (int i = 0; i < data.size(); i++) {
+			String temp = data.get(i).toString();
+			if (temp.length() > longest.length()) {
+			    longest = temp;
+			}
+		    }
+		    if (widths[k] == null || longest.length() > widths_value[k]) {
+			widths_value[k] = longest.length();
+			widths[k] = data;
+		    }
+		}
+	    }
+	}
+
+	// Now assign the dimensions we have determined to be the largest.
+	for (int l = 0; l < heights.length; l++) {
+	    if (heights[l] != null) {
+		Component component = cell_renderer.getTableCellRendererComponent(this, heights[l], false, false, 0, 0);
+		Dimension size = component.getPreferredSize();
+		setRowHeight(l, size.height);
+	    }
+	}
+	for (int m = 0; m < widths.length; m++) {
+	    if (widths[m] != null) {
+		Component component = cell_renderer.getTableCellRendererComponent(this, widths[m], false, false, 0, 0);
+		Dimension size = component.getPreferredSize();
+		int width = size.width + MARGIN;
+		if (width > (2 * parent_frame.getSize().width) / 3) {
+		    width = (2 * parent_frame.getSize().width) / 3;
+		}
+
+		Component header = header_renderer.getTableCellRendererComponent(this, dataModel.getColumnName(m), false, false, 0, 0);
+		if (header.getPreferredSize().width + MARGIN > width) {
+		    width = header.getPreferredSize().width + MARGIN;
+		}
+		columnModel.getColumn(m).setPreferredWidth(width);
+	    }
+	}
+
+	wait(initial_state);
+    }
+
+
+    public void sortOrderChanged(TableModelSorterEvent event) {
+    }
+
+    private void wait(boolean waiting) {
+	if(parent_frame != null) {
+	    parent_frame.wait(waiting);
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/tree/DragTree.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/tree/DragTree.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/tree/DragTree.java	(revision 13928)
@@ -0,0 +1,820 @@
+package org.greenstone.gatherer.gui.tree;
+
+import java.awt.*;
+import java.awt.datatransfer.*;
+import java.awt.dnd.*;
+import java.awt.event.*;
+import java.awt.geom.AffineTransform;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.plaf.basic.BasicTreeUI;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.file.FileSystemModel;
+import org.greenstone.gatherer.gui.Filter;
+import org.greenstone.gatherer.util.DragComponent;
+import org.greenstone.gatherer.util.DragGroup;
+import org.greenstone.gatherer.util.DragTreeSelectionModel;
+import org.greenstone.gatherer.util.Utility;
+
+public abstract class DragTree
+    extends JTree
+    implements Autoscroll, DragGestureListener, DragSourceListener, DropTargetListener, DragComponent, TreeSelectionListener {
+    /** The normal background color. */
+    private Color background_color;
+    /** The normal foreground color. */
+    private Color foreground_color;
+    /** The Group this component belongs to. */
+    private DragGroup group;
+    /** The filter for this tree. */
+    protected Filter filter = null;
+    /** The image to use for the disabled background. */
+    private ImageIcon disabled_background;
+    /** The image to use for a normal background. */
+    private ImageIcon normal_background;
+    /** The icon to use for multiple node drag'n'drops. We decided against using the windows paradigm or a block of x horizontal lines for x files. */
+    private ImageIcon multiple_icon = new ImageIcon("resource"+File.separator+"multiple.gif");
+    /** The default drag action, although its not that important as we provide custom icons during drags. */
+    private int drag_action = DnDConstants.ACTION_MOVE;
+    /** The location of the last ghost drawn, so that we can repair the 'spoilt' area. */
+    private Point pt_last = null;
+    /** The region borderer by the lower cue line. */
+    private Rectangle lower_cue_line;
+    /** The region covered by the drag ghost icon. */
+    private Rectangle ra_ghost = new Rectangle();
+    /** The region borderer by the upper cue line. */
+    private Rectangle upper_cue_line;
+    /** The last tree path the drag was hovered over. */
+    private TreePath previous_path = null;
+
+    static private Cursor NO_DRAG_CURSOR = null;
+
+    static private final Color TRANSPARENT_COLOR = new Color(0,0,0,0);
+    /** The distance from the edge of the current view within the scroll bar which if entered causes the view to scroll. */
+    static private final int AUTOSCROLL_MARGIN = 12;
+
+    static public final int TREE_DISPLAY_CHANGED        = 0;
+    static public final int LOADED_COLLECTION_CHANGED   = 1;
+    static public final int COLLECTION_CONTENTS_CHANGED = 2;
+
+
+    public DragTree(TreeModel model, boolean mixed_selection)
+    {
+	super();
+
+	// For some reason these aren't set with Java 1.4.2 and the GTK look and feel?
+	if (UIManager.get("Tree.leftChildIndent") == null) {
+	    UIManager.put("Tree.leftChildIndent", new Integer(7));
+	}
+	if (UIManager.get("Tree.rightChildIndent") == null) {
+	    UIManager.put("Tree.rightChildIndent", new Integer(13));
+	}
+
+	init(mixed_selection);
+	if (model != null) {
+	    setModel(model);
+	}
+    }
+
+    public void init(boolean mixed_selection) {
+	if (NO_DRAG_CURSOR == null) {
+	    NO_DRAG_CURSOR = DragSource.DefaultMoveNoDrop;
+	}
+
+	// Init
+	this.filter = new Filter(this, null);
+
+	// Creation
+	this.putClientProperty("JTree.lineStyle", "Angled");
+	this.setAutoscrolls(true);
+	this.setEditable(false);
+	this.setLargeModel(true);
+	this.setOpaque(true);
+	this.setRootVisible(false);
+	this.setSelectionModel(new DragTreeSelectionModel(this, mixed_selection));
+	this.setShowsRootHandles(true);
+	this.setUI(new BasicTreeUI());
+
+	// Connection
+	addKeyListener(new DragTreeKeyListener());
+	addMouseListener(Gatherer.g_man.foa_listener);
+	addTreeExpansionListener(Gatherer.g_man.foa_listener);
+	addTreeSelectionListener(this);
+
+	DragTreeCellRenderer renderer = new DragTreeCellRenderer();
+	//make the renderer paint nodes as transparent when not selected
+	//renderer.setBackgroundNonSelectionColor(new Color(0,0,0,0));
+	setCellRenderer(renderer);
+	// It turns out VariableHeightLayoutCache is buggy under MacOS, so I'll force it to use FixedHeightLayoutCache. To do that I have to set a cell height, ala below, and set the large model property to true, ala above. And buggy VariableHeightLayoutCache goes away. Plus this actually provides a minor performance boost as the layout manager doesn't have to calculate new bounds each time (well... I suppose any gain is actually pretty much eclipsed by the time taken for file access while we determine what a certain nodes children are).
+	// And once we have the cell renderer, use it to determine a fixed height for the rows
+	Component prototype_row = renderer.getTreeCellRendererComponent(this, "Prototype", true, true, false, 0, true);
+	this.setRowHeight(prototype_row.getSize().height);
+	prototype_row = null;
+
+
+	// Drag'n'drop Setup
+	// Drag source setup.
+	DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(this, drag_action, this);
+	// Drop destination setup.
+	new DropTarget(this, drag_action, this, true);
+    }
+
+    // Autoscroll Interface - Scroll because the mouse cursor is in our scroll zone.<br>
+    // The following code was borrowed from the book:<br>
+    //              Java Swing<br>
+    //              By Robert Eckstein, Marc Loy & Dave Wood<br>
+    //              Paperback - 1221 pages 1 Ed edition (September 1998)<br>
+    //              O'Reilly & Associates; ISBN: 156592455X<br>
+    // The relevant chapter of which can be found at:<br>
+    //              http://www.oreilly.com/catalog/jswing/chapter/dnd.beta.pdf<br>
+    // But I've probably tortured it beyond all recognition anyway.
+    public void autoscroll(Point pt) {
+	// Figure out which row we're on.
+	int row = getRowForLocation(pt.x, pt.y);
+	// If we are not on a row then ignore this autoscroll request
+	if (row < 0) return;
+	Rectangle bounds = getBounds();// Yes, scroll up one row
+	// Now decide if the row is at the top of the screen or at the bottom. We do this to make the previous row (or the next row) visible as appropriate. If we're at the absolute top or bottom, just return the first or last row respectively.
+	// Is row at top of screen?
+	if(pt.y + bounds.y <= AUTOSCROLL_MARGIN) {
+	    // Yes, scroll up one row
+	    if(row <= 0) {
+		row = 0;
+	    }
+	    else {
+		row = row - 1;
+	    }
+	}
+	else {
+	    // No, scroll down one row
+	    if(row < getRowCount() - 1) {
+		row = row + 1;
+	    }
+	}
+	this.scrollRowToVisible(row);
+    }
+
+    /** In order for the appearance to be consistant, given we may be in the situation where the pointer has left our focus but the ghost remains, this method allows other members of the GGroup to tell this component to clear its ghost.
+     */
+    public void clearGhost() {
+	// Erase the last ghost image and cue line
+	paintImmediately(ra_ghost.getBounds());
+    }
+
+    /** Any implementation of DragSourceListener must include this method so we can be notified when the drag event ends (somewhere else), which will in turn remove actions.
+     * @param event A <strong>DragSourceDropEvent</strong> containing all the information about the end of the drag event.
+     */
+    public void dragDropEnd(DragSourceDropEvent event) {
+    }
+
+    /** Any implementation of DragSourceListener must include this method so we can be notified when the drag focus enters this component.
+     * @param event A <strong>DragSourceDragEvent</strong> containing all the information
+     * about the drag event.
+     */
+    public void dragEnter(DragSourceDragEvent event) {
+	// Handled elsewhere.
+    }
+    /** Any implementation of DropTargetListener must include this method so we can be notified when the drag focus enters this component, which in this case is to grab focus from within our group.
+     * @param event A <strong>DropTargetDragEvent</strong> containing all the information about the drag event.
+     */
+    public void dragEnter(DropTargetDragEvent event) {
+	group.grabFocus(this);
+    }
+    /** Any implementation of DragSourceListener must include this method so we can be notified when the drag focus leaves this component.
+     * @param event A <strong>DragSourceEvent</strong> containing all the information about the drag event.
+     */
+    public void dragExit(DragSourceEvent event) {
+	clearGhost();
+    }
+
+    /** Any implementation of DropTargetListener must include this method
+     * so we can be notified when the drag focus leaves this component.
+     * @param event A DropTargetEvent containing all the information
+     * about the drag event.
+     */
+    public void dragExit(DropTargetEvent event) {
+	clearGhost();
+    }
+
+    /** Any implementation of DragGestureListener must include this method
+     * so we can be notified when a drag action has been noticed, thus a
+     * drag action has begun.
+     * @param event A DragGestureEvent containing all the information about
+     * the drag event.
+     */
+    public void dragGestureRecognized(DragGestureEvent event)
+    {
+	// Check that the tree is draggable
+	if (!isDraggable()) {
+	    return;
+	}
+
+	// Disable editing, unless you want to have the edit box pop-up part way through dragging.
+	this.setEditable(false);
+	// We need this to find one of the selected nodes.
+	Point origin = event.getDragOrigin();
+	TreePath path = this.getPathForLocation(origin.x, origin.y);
+	// Taking into account our delayed model of selection, it is possible the user has performed a select and drag in one click. Here we utilize the Windows paradigm like so: If the node at the origin of the drag and drop is already in our selection then we perform multiple drag and drop. Otherwise we recognise that this is a distinct drag-drop and move only the origin node.
+	if(!isPathSelected(path)) {
+	    ((DragTreeSelectionModel)selectionModel).setImmediate(true);
+	    setSelectionPath(path);
+	    ((DragTreeSelectionModel)selectionModel).setImmediate(false);
+	}
+	if(path == null) {
+	    return;
+	}
+	if (!isValidDrag()) {
+	    try {
+		event.startDrag(NO_DRAG_CURSOR, new StringSelection("dummy"), this);
+		//dragging = true;
+	    }
+	    catch(Exception error) {
+		error.printStackTrace();
+	    }
+	    return;
+	}
+	// Now update the selection stored as far as the group is concerned.
+	group.setSelection(getSelectionPaths());
+	group.setSource(this);
+	// First grab ghost.
+	group.grabFocus(this);
+	// Ghost Image stuff.
+	Rectangle rect = this.getPathBounds(path);
+	group.mouse_offset = new Point(origin.x - rect.x, origin.y - rect.y);
+	// Create the ghost image.
+	// Retrieve the selected files.
+	int selection_count = getSelectionCount();
+	if(selection_count > 0) {
+	    JLabel label;
+	    if(selection_count == 1) {
+		TreePath node_path = getSelectionPath();
+		FileNode node = (FileNode) path.getLastPathComponent();
+		label = new JLabel(node.toString(), ((DefaultTreeCellRenderer)getCellRenderer()).getLeafIcon(), JLabel.CENTER);
+	    }
+	    else {
+		String title = getSelectionCount() + " " + Dictionary.get("Tree.Files");
+		label = new JLabel(title, ((DefaultTreeCellRenderer)getCellRenderer()).getClosedIcon(), JLabel.CENTER);
+		title = null;
+	    }
+	    // The layout manager normally does this.
+	    Dimension label_size = label.getPreferredSize();
+	    label.setSize(label_size);
+	    label.setBackground(TRANSPARENT_COLOR);
+	    label.setOpaque(true);
+	    // Get a buffered image of the selection for dragging a ghost image.
+	    group.image_ghost = new BufferedImage(label_size.width, label_size.height, BufferedImage.TYPE_INT_ARGB_PRE);
+	    label_size = null;
+	    // Get a graphics context for this image.
+	    Graphics2D g2 = group.image_ghost.createGraphics();
+	    // Make the image ghostlike
+	    g2.setComposite(AlphaComposite.getInstance (AlphaComposite.SRC, 0.5f));
+	    // Ask the cell renderer to paint itself into the BufferedImage
+	    label.paint(g2);
+	    g2 = null;
+	    label = null;
+	    try {
+		event.startDrag(new Cursor(Cursor.DEFAULT_CURSOR), group.image_ghost, group.mouse_offset, new StringSelection("dummy"), this);
+		//dragging = true;
+	    }
+	    catch(Exception error) {
+		error.printStackTrace();
+	    }
+	}
+
+    }
+
+    /** Implementation side-effect.
+     * @param event A DragSourceDragEvent containing all the information about the drag event.
+     */
+    public void dragOver(DragSourceDragEvent event) {
+    }
+
+    /** Any implementation of DropTargetListener must include this method
+     * so we can be notified when the drag moves in this component.
+     * @param event A DropTargetDragEvent containing all the information
+     * about the drag event.
+     */
+    public void dragOver(DropTargetDragEvent event) {
+	// Draw the mouse ghost
+	Graphics2D g2 = (Graphics2D) getGraphics();
+	Point pt = event.getLocation();
+	if(pt_last != null && pt.equals(pt_last)) {
+	    return;
+	}
+	pt_last = pt;
+	if(!DragSource.isDragImageSupported() && group.image_ghost != null) {
+	    // Erase the last ghost image and cue line
+	    paintImmediately(ra_ghost.getBounds());
+	    // Remember where you are about to draw the new ghost image
+	    ra_ghost.setRect(pt.x - group.mouse_offset.x, pt.y - group.mouse_offset.y, group.image_ghost.getWidth(), group.image_ghost.getHeight());
+	    // Draw the ghost image
+	    g2.drawImage(group.image_ghost, AffineTransform.getTranslateInstance(ra_ghost.getX(), ra_ghost.getY()), null);
+	}
+	// Now we highlight the target node if it is a valid drop target. Of course we don't bother if we are still over a node which has already been identified as to whether its a drop target
+	TreePath target_path = this.getPathForLocation(pt.x, pt.y);
+	
+	if (target_path == null) {
+	    // the user has moved the mouse into background area - need to remove any existing cue lines
+	    if(upper_cue_line != null && lower_cue_line != null) {
+		paintImmediately(upper_cue_line.getBounds());
+		paintImmediately(lower_cue_line.getBounds());
+		previous_path = null;
+	    }
+	    // don't need to display anything
+	    return;
+	} 
+	
+	if(previous_path == null || target_path != null && !target_path.equals(previous_path)) {
+	    // Immediately clear the old cue lines.
+	    if(upper_cue_line != null && lower_cue_line != null) {
+		paintImmediately(upper_cue_line.getBounds());
+		paintImmediately(lower_cue_line.getBounds());
+	    }
+	    if(isValidDrop(target_path)) {
+		// Get the drop target's bounding rectangle
+		Rectangle raPath = getPathBounds(target_path);
+		// Cue line bounds (2 pixels beneath the drop target)
+		upper_cue_line = new Rectangle(0, raPath.y + (int)raPath.getHeight(), getWidth(), 2);
+		lower_cue_line = new Rectangle(0, raPath.y, getWidth(), 2);
+		g2.setColor(((DefaultTreeCellRenderer)cellRenderer).getBackgroundSelectionColor()); // The cue line color
+		g2.fill(upper_cue_line);         // Draw the cue line
+		g2.fill(lower_cue_line);
+	    }
+	    else {
+		upper_cue_line = null;
+		lower_cue_line = null;
+	    }
+	}
+    }
+
+    /** Any implementation of DropTargetListener must include this method
+	  * so we can be notified when the drag ends, ie the transferable is
+	  * dropped.
+	  * @param event A DropTargetDropEvent containing all the information
+	  * about the end of the drag event.
+	  */
+    public void drop(DropTargetDropEvent event) {
+	///start = System.currentTimeMillis();
+	///ystem.err.println("Drop target drop: " + this);
+	if (!isDroppable()) {
+	    return;
+	}
+
+	event.acceptDrop(drag_action);
+
+	// Determine what node we dropped over.
+	Point pt = event.getLocation();
+	TreePath target_path = this.getPathForLocation(pt.x, pt.y);
+	FileNode target = null;
+	if(target_path != null) {
+	    if(isValidDrop(target_path)) {
+		target = (FileNode) target_path.getLastPathComponent();
+	    } else if (isValidDropOntoFile(target_path)) {
+		target = (FileNode) target_path.getParentPath().getLastPathComponent();
+	    }
+	}
+	else {
+	    TreeModel m = getModel();
+	    // check that we have a model and is a FileSystemModel (ie check that a collection is loaded
+	    if (m != null && m instanceof FileSystemModel) {
+		target = (FileNode) m.getRoot();
+	    }
+	}
+	target_path = null;
+	pt = null;
+	if(target != null) {
+	    ///ystem.err.println("Valid drop.");
+	    TreePath[] selection = group.getSelection();
+	    if(target != null && selection != null) {
+		FileNode[] source_nodes = new FileNode[selection.length];
+		for(int i = 0; i < source_nodes.length; i++) {
+		    source_nodes[i] = (FileNode) selection[i].getLastPathComponent();
+		}
+		Gatherer.f_man.action(group.getSource(), source_nodes, this, target);
+		source_nodes = null;
+	    }
+	    group.setSelection(null);
+	    group.setSource(null);
+	    selection = null;
+	    target = null;
+	}
+
+	// Clear up the group.image_ghost
+	paintImmediately(ra_ghost.getBounds());
+	event.getDropTargetContext().dropComplete(true);
+	group.image_ghost = null;
+    }
+
+
+    /** Any implementation of DragSourceListener must include this method
+     * so we can be notified when the action to be taken upon drop changes.
+     * @param event A DragSourceDragEvent containing all the information
+     * about the drag event.
+     */
+    public void dropActionChanged(DragSourceDragEvent event) {
+    }
+
+    /** Any implementation of DropTargetListener must include this method
+     * so we can be notified when the action to be taken upon drop changes.
+     * @param event A DropTargetDragEvent containing all the information
+     * about the drag event.
+     */
+    public void dropActionChanged(DropTargetDragEvent event) {
+    }
+
+    /** Used to notify this component that it has gained focus. It should
+     * make some effort to inform the user of this.
+     */
+    public void gainFocus() {
+	///ystem.err.println("Gained focus: " + this);
+	((DragTreeCellRenderer)cellRenderer).gainFocus();
+	repaint();
+    }
+
+    /** Autoscroll Interface...
+     * The following code was borrowed from the book:
+     *              Java Swing
+     *              By Robert Eckstein, Marc Loy & Dave Wood
+     *              Paperback - 1221 pages 1 Ed edition (September 1998)
+     *              O'Reilly & Associates; ISBN: 156592455X
+     *
+     * The relevant chapter of which can be found at:
+     *              http://www.oreilly.com/catalog/jswing/chapter/dnd.beta.pdf
+     * Calculate the insets for the *JTREE*, not the viewport
+     * the tree is in. This makes it a bit messy.
+     */
+    public Insets getAutoscrollInsets()
+    {
+	Rectangle raOuter = this.getBounds();
+	Rectangle raInner = this.getParent().getBounds();
+	return new Insets(raInner.y - raOuter.y + AUTOSCROLL_MARGIN,
+			  raInner.x - raOuter.x + AUTOSCROLL_MARGIN,
+			  raOuter.height - raInner.height - raInner.y + raOuter.y + AUTOSCROLL_MARGIN,
+			  raOuter.width - raInner.width - raInner.x + raOuter.x + AUTOSCROLL_MARGIN);
+    }
+
+    public Filter getFilter() {
+	return filter;
+    }
+
+    public String getSelectionDetails() {
+	return ((DragTreeSelectionModel)selectionModel).getDetails();
+    }
+
+    public FileSystemModel getTreeModel() {
+	return (FileSystemModel) getModel();
+    }
+
+
+    protected abstract boolean isDraggable();
+
+
+    protected abstract boolean isDroppable();
+
+
+    /** This method is used to inform this component when it loses focus,
+     * and should indicate this somehow.
+     */
+    public void loseFocus() {
+	///ystem.err.println("Lost focus: " + this);
+	((DragTreeCellRenderer)cellRenderer).loseFocus();
+	repaint();
+    }
+
+
+    public void paint(Graphics g) {
+	if(disabled_background != null) {
+	    int height = getSize().height;
+	    int offset = 0;
+	    ImageIcon background;
+	    if(isEnabled()) {
+		background = normal_background;
+	    }
+	    else {
+		background = disabled_background;
+	    }
+	    while((height - offset) > 0) {
+		g.drawImage(background.getImage(), 0, offset, null);
+		offset = offset + background.getIconHeight();
+	    }
+	    background = null;
+	}
+	super.paint(g);
+    }
+
+    public void refresh(TreePath path) {
+	if (treeModel instanceof FileSystemModel) {
+	    ((FileSystemModel)treeModel).refresh(path);
+	}
+	else {
+	    // System.err.println("DragTree::refresh - Tree model is " + treeModel);
+	}
+    }
+
+    public void setBackgroundNonSelectionColor(Color color) {
+	background_color = color;
+	if(isEnabled()) {
+	    setBackground(color);
+	    ((DefaultTreeCellRenderer)cellRenderer).setBackgroundNonSelectionColor(color);
+	}
+	else {
+	    setBackground(Color.lightGray);
+	    ((DefaultTreeCellRenderer)cellRenderer).setBackgroundNonSelectionColor(Color.lightGray);
+	}
+	repaint();
+    }
+
+    public void setBackgroundSelectionColor(Color color) {
+	((DefaultTreeCellRenderer)cellRenderer).setBackgroundSelectionColor(color);
+	repaint();
+    }
+
+    /** Override the normal setEnabled so the Tree exhibits a little more
+     * change, which in this instance is the background colour changing.
+     * @param state Whether this GTree should be in an enabled state.
+     */
+    public void setEnabled(boolean state) {
+	super.setEnabled(state);
+
+	// Change some colors
+	if(state) {
+	    setBackground(background_color);
+	    ((DefaultTreeCellRenderer)cellRenderer).setBackgroundNonSelectionColor(background_color);
+	    ((DefaultTreeCellRenderer)cellRenderer).setTextNonSelectionColor(foreground_color);
+	}
+	else {
+	    setBackground(Color.lightGray);
+	    ((DefaultTreeCellRenderer)cellRenderer).setBackgroundNonSelectionColor(Color.lightGray);
+	    ((DefaultTreeCellRenderer)cellRenderer).setTextNonSelectionColor(Color.black);
+	}
+	repaint();
+    }
+
+    public void setGroup(DragGroup group) {
+	this.group = group;
+    }
+
+    /** Determines whether the following selection attempts should go through the normal delayed selection model, or should happen immediately.*/
+    public void setImmediate(boolean state) {
+	((DragTreeSelectionModel)selectionModel).setImmediate(state);
+    }
+
+    public void setModel(TreeModel model) {
+	super.setModel(model);
+	if(model instanceof FileSystemModel) {
+	    FileSystemModel file_system_model = (FileSystemModel) model;
+	    file_system_model.setTree(this);
+	    removeTreeExpansionListener(file_system_model);
+	    addTreeExpansionListener(file_system_model);
+	    removeTreeWillExpandListener(file_system_model);
+	    addTreeWillExpandListener(file_system_model);
+	    file_system_model = null;
+	}
+    }
+
+    /** Ensure that that file node denoted by the given file is selected. */
+    public void setSelection(File file) {
+	// We know the file exists, and thus that it must exists somewhere in our tree hierarchy.
+	// 1. Retrieve the root node of our tree.
+	FileNode current = (FileNode) getModel().getRoot();
+	// 2. Find that node in the file parents, keeping track of each intermediate file.
+	ArrayList files = new ArrayList();
+	while(file != null && !current.toString().equals(file.getName())) {
+	    files.add(0, file);
+	    file = file.getParentFile();
+	}
+	if(file == null) {
+	    return;
+	}
+	// 3. While there are still remaining intermediate files.
+	while(files.size() > 0) {
+	    file = (File) files.remove(0);
+				// 3a. Find the next file in the current nodes children.
+	    boolean found = false;
+	    current.map();
+	    for(int i = 0; !found && i < current.getChildCount(); i++) {
+		FileNode child = (FileNode) current.getChildAt(i);
+		if(child.toString().equals(file.getName())) {
+		    // 3b. Make the current node this node (if found) and continue.
+		    found = true;
+		    current = child;
+		}
+	    }
+	    // 3c. If not found then return as this node can't exists somehow.
+	    if(!found) {
+		return;
+	    }
+	}
+	// 4. We should now have the desired node. Remember to make the selection immediate.
+	TreePath path = new TreePath(current.getPath());
+	setImmediate(true);
+	setSelectionPath(path);
+	setImmediate(false);
+    }
+
+    public void setTextNonSelectionColor(Color color) {
+	foreground_color = color;
+	if(isEnabled()) {
+	    ((DefaultTreeCellRenderer)cellRenderer).setTextNonSelectionColor(color);
+	}
+	else {
+	    ((DefaultTreeCellRenderer)cellRenderer).setTextNonSelectionColor(Color.black);
+	}
+	repaint();
+    }
+
+    public void setTextSelectionColor(Color color) {
+	((DefaultTreeCellRenderer)cellRenderer).setTextSelectionColor(color);
+	repaint();
+    }
+
+    public void valueChanged(TreeSelectionEvent event) {
+	if(group == null) {
+	    ///ystem.err.println("Oh my god, this tree has no group: " + this);
+	}
+	else {
+	    group.grabFocus(this);
+	}
+    }
+
+    /** returns false for dummy nodes (ones without files), and system root
+     * nodes */
+    private boolean isValidDrag() {
+	//because you cant select nodes that are children of another selection, and we use a contiguous selection model, we just test the first selection path
+	TreePath node_path = getSelectionPath();
+	FileNode node = (FileNode) node_path.getLastPathComponent();
+
+	if (node.getFile() == null) {
+	    return false;
+	}
+	if (node.isFileSystemRoot()) {
+	    return false;
+	}
+	// We also don't allow the user to select files that reside within the currently loaded collection
+	TreePath[] paths = getSelectionPaths();
+	for(int i = 0; i < paths.length; i++) {
+	    FileNode child = (FileNode) paths[i].getLastPathComponent();
+	    if (child.isInLoadedCollection()) {
+		return false;
+	    }
+	}
+	return true;
+    }
+
+    private boolean isValidDropOntoFile(TreePath target_path) {
+	boolean valid = false;
+	if(target_path != null) {
+	    FileNode target_node = (FileNode) target_path.getLastPathComponent();
+	    if (target_node.isLeaf()) {
+		// check the parent node for being a valid drop
+		return isValidDrop(target_path.getParentPath());
+	    }
+	}
+	return false;
+    }
+
+		
+    private boolean isValidDrop(TreePath target_path) {
+	boolean valid = false;
+	if(target_path == null) {
+	    previous_path = null;
+	} 
+	else {
+	    FileNode target_node = (FileNode) target_path.getLastPathComponent();
+	    // We can only continue testing if the node is a folder.
+	    if(!target_node.isLeaf()) {
+		// Now we check if the node is readonly.
+		if(!target_node.isReadOnly()) {
+		    // Finally we check the target path against the paths in the selection to ensure we are not adding to our own ancestors!
+		    TreePath[] selection = group.getSelection();
+		    boolean failed = false;
+		    for(int i = 0; !failed && selection != null && i < selection.length; i++) {
+			failed = selection[i].isDescendant(target_path);
+		    }
+		    // Having finally completed all the tests, we can highlight the drop target.
+		    if(!failed) {
+			valid = true;
+		    }
+		    else {
+			///ystem.err.println("Invalid. Target is descendant of itself.");
+		    }
+		}
+		else {
+		    ///ystem.err.println("Read only.");
+		}
+	    }
+	    else {
+		///ystem.err.println("Leaf node. Children not allowed.");
+	    }
+	    previous_path = target_path;
+	}
+	return valid;
+    }
+
+
+    /** This class listens for certain key presses, such as [Enter] or [Delete], and responds appropriately. */
+    private class DragTreeKeyListener
+	extends KeyAdapter
+    {
+	private boolean vk_left_pressed = false;
+	/** Called whenever a key that was pressed is released, it is this action that will cause the desired effects (this allows for the key event itself to be processed prior to this listener dealing with it). */
+	public void keyReleased(KeyEvent event) {
+	    ///ystem.err.println("Key Release detected. " + event.getKeyCode());
+	    if(event.getKeyCode() == KeyEvent.VK_DELETE) {
+		// Get the selected files from the tree and removal them using the default dnd removal method.
+		// Find the active tree (you've made selections in).
+		DragTree tree = (DragTree) group.getActive();
+		// Fudge things a bit
+		group.setSource(tree);
+		// Determine the selection.
+		TreePath paths[] = tree.getSelectionPaths();
+		if(paths != null) {
+		    FileNode[] source_nodes = new FileNode[paths.length];
+		    for(int i = 0; i < source_nodes.length; i++) {
+			source_nodes[i] = (FileNode) paths[i].getLastPathComponent();
+		    }
+		    Gatherer.f_man.action(tree, source_nodes, Gatherer.recycle_bin, null);
+		    source_nodes = null;
+		}
+	    }
+	    else if(event.getKeyCode() == KeyEvent.VK_ENTER) {
+		// Get the first selected file.
+		DragTree tree = (DragTree)event.getSource();
+		TreePath path = tree.getSelectionPath();
+		if(path != null) {
+		    File file = ((FileNode)path.getLastPathComponent()).getFile();
+		    if (file != null && file.isFile()) {
+			Gatherer.f_man.openFileInExternalApplication(file);
+		    }
+		    else {
+			if(!tree.isExpanded(path)) {
+			    tree.expandPath(path);
+			}
+			else {
+			    tree.collapsePath(path);
+			}
+		    }
+		}
+	    } else if (event.getKeyCode() == KeyEvent.VK_UP || event.getKeyCode() == KeyEvent.VK_DOWN) {
+		DragTree tree = (DragTree)event.getSource();
+		// we need to manually do the up and down selections
+		boolean up = (event.getKeyCode() == KeyEvent.VK_UP);
+		int current_row = tree.getLeadSelectionRow();
+		tree.setImmediate(true);
+		if (up) {
+		    if (current_row > 0) {
+			tree.clearSelection();
+			tree.setSelectionRow(current_row-1);
+		    }
+		} else {
+		    if (current_row < tree.getRowCount()-1){
+			tree.clearSelection();
+			tree.setSelectionRow(current_row+1);
+		    }
+		}
+		tree.setImmediate(false);
+	    } else if (event.getKeyCode() == KeyEvent.VK_LEFT) {
+		// left key on a file shifts the selection to the parent folder
+		DragTree tree = (DragTree)event.getSource();
+		TreePath path = tree.getLeadSelectionPath();
+		if(path != null) {
+		    File file = ((FileNode)path.getLastPathComponent()).getFile();
+		    if(file != null) {
+			if (file.isFile() || vk_left_pressed) {
+			    vk_left_pressed = false;
+			    TreePath parent_path = path.getParentPath();
+			    if (parent_path != null && parent_path.getParentPath() != null) {
+				// if this file is in the top level folder, don't move the focus 
+				tree.setImmediate(true);
+				tree.clearSelection();
+				tree.setSelectionPath(parent_path);
+				tree.setImmediate(false);
+			    }
+			}
+		    }
+		}
+	    }
+	}
+	
+	// we need to watch for left clicks on an unopened folder - should shift the focus to teh parent folder. But because there is some other mysterious key listener that does opening and closing folders on right and left clicks, we must detect the situation before the other handler has done its job, and process it after. 
+	public void keyPressed(KeyEvent event) {
+	    if (event.getKeyCode() == KeyEvent.VK_LEFT) {
+		// left key on  closed directory shifts the selection to the parent folder
+		DragTree tree = (DragTree)event.getSource();
+		TreePath path = tree.getLeadSelectionPath();
+		if(path == null) return; 
+		File file = ((FileNode)path.getLastPathComponent()).getFile();
+		if(file == null) return;
+		
+		if (file.isDirectory() && tree.isCollapsed(path)) {
+		    vk_left_pressed = true;
+		}
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/tree/DragTreeCellRenderer.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/tree/DragTreeCellRenderer.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/gui/tree/DragTreeCellRenderer.java	(revision 13928)
@@ -0,0 +1,89 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.gui.tree;
+
+import java.awt.*;
+import javax.swing.*;
+import javax.swing.tree.DefaultTreeCellRenderer;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.greenstone.gatherer.util.Utility;
+
+public class DragTreeCellRenderer
+    extends DefaultTreeCellRenderer
+{
+    private Color selection_background;
+    private Color selection_foreground;
+
+    public DragTreeCellRenderer() {
+	super();
+	// Have to wait until this image is loaded
+	selection_background = getBackgroundSelectionColor();
+	selection_foreground = getTextSelectionColor();
+    }
+
+    public void gainFocus() {
+	setBackgroundSelectionColor(selection_background);
+	setTextSelectionColor(selection_foreground);
+    }
+
+    /** Configures the renderer based on the passed in components. */
+    public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus)
+    {
+	// Rendering FileNodes
+	if (value instanceof FileNode) {
+	    FileNode node = (FileNode) value;
+	    String node_text = node.toString();
+
+	    // Add file sizes if necessary
+	    if (Configuration.get("general.show_file_size", Configuration.COLLECTION_SPECIFIC) && node.getFile() != null && !node.getAllowsChildren()) {
+		node_text = node_text + StaticStrings.SPACE_CHARACTER + StaticStrings.LBRACKET_CHARACTER + Utility.formatFileLength(node.getFile().length()) + StaticStrings.RBRACKET_CHARACTER;
+	    }
+
+	    return (JLabel) super.getTreeCellRendererComponent(tree, node_text, sel, expanded, leaf, row, hasFocus);
+	}
+
+	// Use default renderer for anything else
+	return (JLabel) super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
+    }
+
+    public void loseFocus() {
+	setBackgroundSelectionColor(Color.lightGray);
+	setTextSelectionColor(Color.black);
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/DocXMLFile.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/DocXMLFile.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/DocXMLFile.java	(revision 13928)
@@ -0,0 +1,280 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2004 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.metadata;
+
+
+import java.io.*;
+import java.util.*;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.util.Utility;
+
+
+/** This class represents one doc.xml file */
+public class DocXMLFile
+    extends File
+{
+    private HashMap source_file_name_to_description_elements_mapping = new HashMap();
+
+
+    public DocXMLFile(String doc_xml_file_path)
+    {
+	super(doc_xml_file_path);
+    }
+
+
+    public ArrayList getMetadataExtractedFromFile(File file)
+    {
+	// Build up a list of metadata extracted from this file
+	ArrayList metadata_values = new ArrayList();
+
+	String file_relative_path = file.getAbsolutePath();
+	int import_index = file_relative_path.indexOf("import");
+	if (import_index != -1) {
+	    file_relative_path = file_relative_path.substring(import_index + "import".length() + 1);
+	}
+
+	// Check whether this doc.xml file contains extracted metadata for the specified file
+	ArrayList description_elements_list = (ArrayList) source_file_name_to_description_elements_mapping.get(file_relative_path);
+	if (description_elements_list == null) {
+	    // ...it doesn't
+	    return metadata_values;
+	}
+
+ 	MetadataSet extracted_metadata_set = MetadataSetManager.getMetadataSet(MetadataSetManager.EXTRACTED_METADATA_NAMESPACE);
+
+	// Parse the doc.xml file
+	DebugStream.println("Applicable doc.xml file: " + this);
+	try {
+	    BufferedReader buffered_reader = new BufferedReader(new FileReader(this));
+
+	    int description_element_num = 0;
+	    int next_description_element_start = ((Integer) description_elements_list.get(description_element_num)).intValue();
+	    boolean in_relevant_description_element = false;
+
+	    String line = null;
+	    for (int line_num = 0; (line = buffered_reader.readLine()) != null; line_num++) {
+		// Check if this line contains the start of a relevant Description element
+		if (line_num == next_description_element_start) {
+		    in_relevant_description_element = true;
+		    continue;
+		}
+
+		// If we're not in a relevant Description element we don't care about anything
+		if (in_relevant_description_element == false) {
+		    continue;
+		}
+
+		// Check if this line contains the end of the relevant Description element
+		if (line.indexOf("</Description>") != -1) {
+		    description_element_num++;
+		    if (description_element_num == description_elements_list.size()) {
+			break;
+		    }
+
+		    next_description_element_start = ((Integer) description_elements_list.get(description_element_num)).intValue();
+		    in_relevant_description_element = false;
+		    continue;
+		}
+
+		// If this line doesn't contain a complete Metadata element, we're not interested
+		if (line.indexOf("<Metadata ") == -1 || line.indexOf("</Metadata>") == -1) {
+		    continue;
+		}
+
+		// Extract the metadata element name
+		int name_index = line.indexOf(" name=\"") + " name=\"".length();
+		String metadata_element_name_full = line.substring(name_index, line.indexOf("\"", name_index));
+
+		// If the metadata has a namespace it isn't extracted metadata, so we're not interested
+		String metadata_set_namespace = MetadataTools.getMetadataSetNamespace(metadata_element_name_full);
+		if (!metadata_set_namespace.equals("")) {
+		    continue;
+		}
+
+		// Extracted metadata!
+		String metadata_element_name = metadata_element_name_full;
+
+		// We completely ignore bibliographic data
+		if (metadata_element_name.equals("SourceSegment")) {
+		    buffered_reader.close();
+		    return new ArrayList();
+		}
+
+		// Ignore metadata starting with gsdl (used to be lowercase metadata and /metadata)
+		if (metadata_element_name.startsWith("gsdl")) {
+		    continue;
+		}
+
+		MetadataElement metadata_element = extracted_metadata_set.getMetadataElementWithName(metadata_element_name);
+
+		// Value trees are not stored for extracted metadata, so create a new value tree node now
+		int value_index = line.indexOf(">", name_index) + ">".length();
+		String metadata_element_value = line.substring(value_index, line.lastIndexOf("</Metadata>"));
+
+		metadata_element.addMetadataValue(metadata_element_value);
+		MetadataValueTreeNode metadata_value_tree_node = metadata_element.getMetadataValueTreeNode(metadata_element_value);
+
+		// Add the new metadata value to the list
+		MetadataValue metadata_value = new MetadataValue(metadata_element, metadata_value_tree_node);
+		metadata_values.add(metadata_value);
+	    }
+
+	    buffered_reader.close();
+	}
+	catch (FileNotFoundException exception) {
+ 	    DebugStream.printStackTrace(exception);
+ 	}
+	catch (IOException exception) {
+ 	    DebugStream.printStackTrace(exception);
+ 	}
+
+	return metadata_values;
+    }
+
+
+    /**
+     * Every doc.xml file must be skimmed when a collection is opened, for two reasons:
+     *   - To build a mapping from source file to its corresponding doc.xml file
+     *   - To get a complete list of all extracted metadata elements
+     */
+    public void skimFile()
+    {
+	MetadataSet extracted_metadata_set = MetadataSetManager.getMetadataSet(MetadataSetManager.EXTRACTED_METADATA_NAMESPACE);
+
+	// Skim the doc.xml file as quickly as possible (don't parse as XML), looking at the Metadata elements
+	DebugStream.println("Skimming doc.xml file " + this + "...");
+	try {
+	    BufferedReader buffered_reader = new BufferedReader(new FileReader(this));
+	    int description_element_start = -1;
+
+	    String line = null;
+	    for (int line_num = 0; (line = buffered_reader.readLine()) != null; line_num++) {
+		// This line contains the start of a Description element
+		if (line.indexOf("<Description>") != -1) {
+		    if (description_element_start != -1) {
+			System.err.println("Parse error: previous Description element unfinished!");
+		    }
+		    description_element_start = line_num;
+		    continue;
+		}
+
+		// This line contains the end of a Description element
+		if (line.indexOf("</Description>") != -1) {
+		    if (description_element_start == -1) {
+			System.err.println("Parse error: Description element unstarted!");
+		    }
+		    description_element_start = -1;
+		    continue;
+		}
+
+		// If we're not in a Description element there shouldn't be any Metadata elements
+		if (description_element_start == -1) {
+		    continue;
+		}
+
+		// This line doesn't contain a Metadata element, so we're not interested
+		if (line.indexOf("<Metadata ") == -1) {
+		    DebugStream.println("Warning: Description element line doesn't contain Metadata element.");
+		    continue;
+		}
+
+		// Extract the metadata element name
+		int name_index = line.indexOf(" name=\"") + " name=\"".length();
+		String metadata_element_name_full = line.substring(name_index, line.indexOf("\"", name_index));
+
+		// If the metadata has a namespace it isn't extracted metadata, so we're not interested
+		String metadata_set_namespace = MetadataTools.getMetadataSetNamespace(metadata_element_name_full);
+		if (!metadata_set_namespace.equals("")) {
+		    continue;
+		}
+
+		// Extracted metadata!
+		String metadata_element_name = metadata_element_name_full;
+
+		// Note which file this doc.xml is for
+		if (metadata_element_name.equals("gsdlsourcefilename")) {
+		    // Extract the gsdlsourcefilename element value
+		    int value_index = line.indexOf(">", name_index) + ">".length();
+		    String gsdlsourcefilename_value = line.substring(value_index, line.indexOf("<", value_index));
+
+		    // We're only interested in the path relative to the import folder
+		    int import_index = gsdlsourcefilename_value.indexOf("import");
+		    if (import_index != -1) {
+			gsdlsourcefilename_value = gsdlsourcefilename_value.substring(import_index + "import".length());
+
+			boolean is_unix_path = gsdlsourcefilename_value.startsWith("/");
+			gsdlsourcefilename_value = gsdlsourcefilename_value.substring(1);
+
+			// Make sure the path matches the OS that is running
+			if (is_unix_path && Utility.isWindows()) {
+			    // Convert path from Unix to Windows
+			    gsdlsourcefilename_value = gsdlsourcefilename_value.replaceAll("\\/", "\\\\");
+			}
+			else if (!is_unix_path && !Utility.isWindows()) {
+			    // Convert path from Windows to Unix
+			    gsdlsourcefilename_value = gsdlsourcefilename_value.replaceAll("\\\\", "/");
+			}
+
+			// Remember this for quick access later
+			if (source_file_name_to_description_elements_mapping.get(gsdlsourcefilename_value) == null) {
+			    source_file_name_to_description_elements_mapping.put(gsdlsourcefilename_value, new ArrayList());
+			}
+
+			((ArrayList) source_file_name_to_description_elements_mapping.get(gsdlsourcefilename_value)).add(new Integer(description_element_start));
+		    }
+
+		    // Warn about an odd gsdlsourcefilename, except if it is the Greenstone "tmp" directory
+		    // This is true when the source files come from a zip file processed by ZIPPlug, for example
+		    else if (gsdlsourcefilename_value.indexOf("tmp") == -1) {
+			// We don't really know what is going on...
+			System.err.println("Warning: Could not understand gsdlsourcefilename " + gsdlsourcefilename_value);
+		    }
+		}
+
+		// Ignore metadata starting with gsdl (used to be lowercase metadata and /metadata)
+		if (metadata_element_name.startsWith("gsdl")) {
+		    continue;
+		}
+
+		MetadataElement metadata_element = extracted_metadata_set.getMetadataElementWithName(metadata_element_name);
+		if (metadata_element == null) {
+		    // This element isn't defined in ex.mds, so create it for this session
+		    DebugStream.println("Extracted metadata element not defined: " + metadata_element_name);
+		    extracted_metadata_set.addMetadataElementForThisSession(metadata_element_name);
+		}
+	    }
+
+	    buffered_reader.close();
+	}
+	catch (FileNotFoundException exception) {
+ 	    DebugStream.printStackTrace(exception);
+ 	}
+	catch (IOException exception) {
+ 	    DebugStream.printStackTrace(exception);
+ 	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/DocXMLFileManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/DocXMLFileManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/DocXMLFileManager.java	(revision 13928)
@@ -0,0 +1,96 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2004 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.metadata;
+
+
+import java.io.*;
+import java.util.*;
+import org.greenstone.gatherer.DebugStream;
+
+
+/** This class is a static class that manages the doc.xml files */
+public class DocXMLFileManager
+{
+    static private ArrayList doc_xml_files = new ArrayList();
+
+
+    static public void clearDocXMLFiles()
+    {
+	doc_xml_files.clear();
+    }
+
+
+    static public ArrayList getMetadataExtractedFromFile(File file)
+    {
+	// Build up a list of metadata values extracted from this file
+	ArrayList metadata_values = new ArrayList();
+
+	// Look at each loaded doc.xml file to see if any have extracted metadata for this file
+	for (int i = 0; i < doc_xml_files.size(); i++) {
+	    DocXMLFile doc_xml_file = (DocXMLFile) doc_xml_files.get(i);
+	    metadata_values.addAll(doc_xml_file.getMetadataExtractedFromFile(file));
+	}
+
+	return metadata_values;
+    }
+
+
+    static public void loadDocXMLFiles(File directory)
+    {
+	// Make sure the directory (archives) exists
+	if (directory.exists() == false) {
+	    return;
+	}
+
+	// Look recursively at each subfile of the directory for doc.xml files
+	File[] directory_files = directory.listFiles();
+	for (int i = 0; i < directory_files.length; i++) {
+	    File child_file = directory_files[i];
+	    if (child_file.isDirectory()) {
+		loadDocXMLFiles(child_file);
+	    }
+	    else if (child_file.getName().equals("doc.xml")) {
+		loadDocXMLFile(child_file);
+	    }
+	}
+    }
+
+
+    static private void loadDocXMLFile(File doc_xml_file_file)
+    {
+	DocXMLFile doc_xml_file = new DocXMLFile(doc_xml_file_file.getAbsolutePath());
+	try {
+	    doc_xml_file.skimFile();
+	    doc_xml_files.add(doc_xml_file);
+	}
+	catch (Exception exception) {
+	    // We catch any exceptions here so errors in doc.xml files don't stop the collection from loading
+	    System.err.println("Error: Could not skim doc.xml file " + doc_xml_file.getAbsolutePath());
+	    DebugStream.printStackTrace(exception);
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataAuditTableModel.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataAuditTableModel.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataAuditTableModel.java	(revision 13928)
@@ -0,0 +1,240 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2004 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.metadata;
+
+
+import java.awt.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.table.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.collection.CollectionTreeNode;
+
+
+public class MetadataAuditTableModel
+    extends AbstractTableModel
+{
+    /** It is not expected that this class will ever be serialized */
+    private static final long serialVersionUID = 0L;
+
+    /** The CollectionTreeNodes this model is built for */
+    private CollectionTreeNode[] file_nodes = null;
+    /** The list of MetadataElements in the table (columns) */
+    private ArrayList metadata_elements = new ArrayList();
+    /** The list of MetadataAuditTableEntries in the table (rows) */
+    private ArrayList metadata_audit_table_entries = new ArrayList();
+
+
+    /** Returns the number of columns in this table. */
+    public int getColumnCount()
+    {
+	return 1 + metadata_elements.size();
+    }
+
+
+    /** Returns the name of the specified column. */
+    public String getColumnName(int col)
+    {
+	// First column: filename
+	if (col == 0) {
+	    return Dictionary.get("AuditTable.File");
+	}
+
+	int metadata_element_index = col - 1;
+	return metadata_elements.get(metadata_element_index).toString();
+    }
+
+
+    /** Returns the values in a particular column. */
+    public ArrayList getColumnValues(int col)
+    {
+	// First column: filename
+	if (col == 0) {
+	    ArrayList column_values = new ArrayList();
+	    for (int i = 0; i < metadata_audit_table_entries.size(); i++) {
+		MetadataAuditTableEntry metadata_audit_table_entry = (MetadataAuditTableEntry) metadata_audit_table_entries.get(i);
+		column_values.add(metadata_audit_table_entry.getFilename());
+	    }
+
+	    return column_values;
+	}
+
+	// Check values are reasonable
+	int metadata_element_index = col - 1;
+	if (metadata_element_index < 0 || metadata_element_index >= metadata_elements.size()) {
+	    return null;
+	}
+
+	ArrayList column_values = new ArrayList();
+	for (int i = 0; i < metadata_audit_table_entries.size(); i++) {
+	    MetadataAuditTableEntry metadata_audit_table_entry = (MetadataAuditTableEntry) metadata_audit_table_entries.get(i);
+	    MetadataValueTreeNode[] metadata_value_tree_nodes = metadata_audit_table_entry.getMetadataValueTreeNodes(metadata_element_index);
+	    if (metadata_value_tree_nodes != null) {
+		for (int j = 0; j < metadata_value_tree_nodes.length; j++) {
+		    column_values.add(metadata_value_tree_nodes[j].toString());
+		}
+	    }
+	}
+
+	return column_values;
+    }
+
+
+    /** Returns the number of rows in this table. */
+    public int getRowCount()
+    {
+	return metadata_audit_table_entries.size();
+    }
+
+
+    /** Returns the cell value at a given row and column as an Object. */
+    public Object getValueAt(int row, int col)
+    {
+	// Check values are reasonable
+	if (row < 0 || row >= metadata_audit_table_entries.size()) {
+	    return null;
+	}
+
+	// First column: filename
+	if (col == 0) {
+	    ArrayList cell_values = new ArrayList();
+	    cell_values.add(((MetadataAuditTableEntry) metadata_audit_table_entries.get(row)).getFilename());
+	    return cell_values;
+	}
+
+	// Check values are reasonable
+	int metadata_element_index = col - 1;
+	if (metadata_element_index < 0 || metadata_element_index >= metadata_elements.size()) {
+	    return null;
+	}
+
+	ArrayList cell_values = new ArrayList();
+	MetadataAuditTableEntry metadata_audit_table_entry = (MetadataAuditTableEntry) metadata_audit_table_entries.get(row);
+	MetadataValueTreeNode[] metadata_value_tree_nodes = metadata_audit_table_entry.getMetadataValueTreeNodes(metadata_element_index);
+	if (metadata_value_tree_nodes != null) {
+	    for (int j = 0; j < metadata_value_tree_nodes.length; j++) {
+		cell_values.add(metadata_value_tree_nodes[j].toString());
+	    }
+	}
+
+	return cell_values;
+    }
+
+
+    public void rebuild(CollectionTreeNode[] file_nodes)
+    {
+	metadata_elements = MetadataSetManager.getEveryMetadataSetElement();
+	metadata_audit_table_entries.clear();
+
+	this.file_nodes = file_nodes;
+	if (file_nodes != null && file_nodes.length > 0) {
+	    // Create model builder
+	    MetadataAuditTableModelBuilder builder = new MetadataAuditTableModelBuilder();
+	    builder.run();
+	}
+    }
+
+
+    private class MetadataAuditTableModelBuilder
+    {
+	// Build a list of MetadataAuditTableEntries that represent the metadata asssigned to the selected files
+	public void run()
+	{
+	    // Process each of the selected files in turn
+	    for (int i = 0; i < file_nodes.length; i++) {
+		File current_file = file_nodes[i].getFile();
+
+		// Get the metadata assigned to this file
+		ArrayList current_file_metadata = MetadataXMLFileManager.getMetadataAssignedToFile(current_file);
+
+		// Get the extracted metadata for this file, if desired
+		if (Configuration.get("general.view_extracted_metadata", Configuration.COLLECTION_SPECIFIC) == true) {
+		    current_file_metadata.addAll(DocXMLFileManager.getMetadataExtractedFromFile(current_file));
+		}
+
+		MetadataAuditTableEntry metadata_audit_table_entry = new MetadataAuditTableEntry(current_file, current_file_metadata);
+		metadata_audit_table_entries.add(metadata_audit_table_entry);
+	    }
+	}
+    }
+
+
+    /** This class represents one (file, metadata) pair */
+    private class MetadataAuditTableEntry
+    {
+	private File file = null;
+	private ArrayList[] metadata_values = null;
+
+
+	public MetadataAuditTableEntry(File file, ArrayList metadata_values_list)
+	{
+	    this.file = file;
+
+	    metadata_values = new ArrayList[metadata_elements.size()];
+	    for (int i = 0; i < metadata_values.length; i++) {
+		metadata_values[i] = new ArrayList();
+	    }
+
+	    for (int i = 0; i < metadata_values_list.size(); i++) {
+		MetadataValue metadata_value = (MetadataValue) metadata_values_list.get(i);
+		MetadataElement metadata_element = metadata_value.getMetadataElement();
+
+		// Find the right column to put the value in
+		for (int j = 0; j < metadata_elements.size(); j++) {
+		    if (metadata_element.equals(metadata_elements.get(j))) {
+			metadata_values[j].add(metadata_value);
+			break;
+		    }
+		}
+	    }
+	}
+
+
+	public String getFilename()
+	{
+	    return file.getName();
+	}
+
+
+ 	public MetadataValueTreeNode[] getMetadataValueTreeNodes(int metadata_element_index)
+ 	{
+	    ArrayList metadata_values_list = metadata_values[metadata_element_index];
+ 	    if (metadata_values_list == null) {
+ 		return null;
+ 	    }
+
+	    MetadataValueTreeNode[] metadata_value_tree_nodes = new MetadataValueTreeNode[metadata_values_list.size()];
+	    for (int i = 0; i < metadata_values_list.size(); i++) {
+		metadata_value_tree_nodes[i] = ((MetadataValue) metadata_values_list.get(i)).getMetadataValueTreeNode();
+	    }
+
+ 	    return metadata_value_tree_nodes;
+ 	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataChangedListener.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataChangedListener.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataChangedListener.java	(revision 13928)
@@ -0,0 +1,37 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2005 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.metadata;
+
+
+import org.greenstone.gatherer.collection.CollectionTreeNode;
+
+
+public interface MetadataChangedListener
+{
+    /** Notification that the metadata assigned to the collection has changed. */
+    public void metadataChanged(CollectionTreeNode[] file_nodes);
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataElement.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataElement.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataElement.java	(revision 13928)
@@ -0,0 +1,217 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2004 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.metadata;
+
+
+import java.io.File;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.util.XMLTools;
+import org.greenstone.gatherer.util.StaticStrings;
+import org.w3c.dom.*;
+
+
+/** This class represents one Metadata element */
+public class MetadataElement
+{
+    // Language-independent metadata element name, with namespace (eg. dc.Subject)
+    private String metadata_element_name_full = null;
+    private Element metadata_element_element = null;
+    private MetadataValueTreeModel metadata_value_tree_model = null;
+    /* this is true if the metadata element comes with a pre defined set of values */
+    private boolean predefined_values = false;
+    /* This restricts the user to only the predefined values */
+    private boolean restricted_values = false;
+
+    public MetadataElement(String metadata_element_name_full, Element metadata_element_element)
+    {
+	this.metadata_element_name_full = metadata_element_name_full;
+	this.metadata_element_element = metadata_element_element;
+	this.metadata_value_tree_model = new MetadataValueTreeModel(this);
+	if (metadata_element_element != null) {
+	    if (metadata_element_element.getAttribute(StaticStrings.PREDEFINED_METADATA_ATTRIBUTE).equals("true")) {
+		predefined_values = true;
+		loadOptionList();
+		if (metadata_element_element.getAttribute(StaticStrings.RESTRICTED_METADATA_ATTRIBUTE).equals("true")) {
+		    // cant have restricted values if no predefined values
+		    restricted_values = true;
+		}
+	    }
+	}
+    }
+	
+    // do this better
+    protected boolean loadOptionList() {
+	NodeList values = metadata_element_element.getElementsByTagName("Value");
+	for (int i=0; i<values.getLength(); i++) {
+	    String val = XMLTools.getValue(values.item(i));
+	    addMetadataValue(val);
+	}
+	return true;
+    }
+    public MetadataValueTreeNode addMetadataValue(String metadata_value)
+    {
+	return metadata_value_tree_model.addMetadataValue(metadata_value);
+    }
+
+
+    public String getAttribute(String attribute_name, String language_code)
+    {
+	// Some extracted metadata elements may not be in ex.mds, and so have no attributes
+	if (metadata_element_element == null) {
+	    return null;
+	}
+
+	Element parent_element = metadata_element_element;
+	boolean language_matches = false;
+
+	NodeList language_elements_nodelist = metadata_element_element.getElementsByTagName("Language");
+	for (int i = 0; i < language_elements_nodelist.getLength(); i++) {
+	    Element current_language_element = (Element) language_elements_nodelist.item(i);
+	    String current_language_element_code = current_language_element.getAttribute("code");
+	    if (current_language_element_code.equals(language_code)) {
+		// Found language; use it for the next step
+		parent_element = current_language_element;
+		language_matches = true;
+		break;
+	    }
+	}
+
+	NodeList attribute_elements_nodelist = parent_element.getElementsByTagName("Attribute");
+	for (int i = 0; i < attribute_elements_nodelist.getLength(); i++) {
+	    Element current_attribute_element = (Element) attribute_elements_nodelist.item(i);
+	    String current_attribute_element_name = current_attribute_element.getAttribute("name");
+	    if (!current_attribute_element_name.equals(attribute_name)) {
+		// Move on to the next Attribute element if the name doesn't match
+		continue;
+	    }
+
+	    // Check if the language matches
+	    String current_attribute_element_language = current_attribute_element.getAttribute("language");
+	    if (language_matches || current_attribute_element_language.equals(language_code)) {
+		// Found attribute; returns its value
+		return XMLTools.getElementTextValue(current_attribute_element);
+	    }
+	}
+
+	return null;
+    }
+
+
+    /** Returns language-dependent metadata element name, with namespace (eg. dc.Subject and Keywords) */ 
+    public String getDisplayName()
+    {
+	// now we use label, previously we used identifier
+	String metadata_element_display_name = MetadataTools.getMetadataElementAttribute(this, "label", Configuration.getLanguage(), "en");
+	if (metadata_element_display_name == null) {
+	    // try identifier
+	    metadata_element_display_name = MetadataTools.getMetadataElementAttribute(this, "identifier", Configuration.getLanguage(), "en");
+	}
+	// Root case (no subelements)
+	if (metadata_element_name_full.indexOf(MetadataTools.SUBELEMENT_SEPARATOR) == -1) {
+	    if (metadata_element_display_name != null) {
+		return getNamespace() + "." + metadata_element_display_name;
+	    }
+
+	    return metadata_element_name_full;
+	}
+
+	// Recursive case (hierarchical metadata elements)
+	else {
+	    String parent_metadata_element_name_full = metadata_element_name_full.substring(0, metadata_element_name_full.lastIndexOf(MetadataTools.SUBELEMENT_SEPARATOR));
+	    MetadataElement parent_metadata_element = MetadataTools.getMetadataElementWithName(parent_metadata_element_name_full);
+
+	    String parent_metadata_element_display_name = parent_metadata_element_name_full;
+	    if (parent_metadata_element != null) {
+		parent_metadata_element_display_name = parent_metadata_element.getDisplayName();
+	    }
+
+	    if (metadata_element_display_name != null) {
+		return parent_metadata_element_display_name + MetadataTools.SUBELEMENT_SEPARATOR + metadata_element_display_name;
+	    }
+
+	    return parent_metadata_element_display_name + metadata_element_name_full.substring(parent_metadata_element_name_full.length());
+	}
+    }
+
+
+    public MetadataValueTreeModel getMetadataValueTreeModel()
+    {
+	return metadata_value_tree_model;
+    }
+
+
+    public MetadataValueTreeNode getMetadataValueTreeNode(String metadata_value)
+    {
+	return metadata_value_tree_model.getMetadataValueTreeNode(metadata_value);
+    }
+
+
+    /** Returns language-independent metadata element name, with namespace (eg. dc.Subject) */
+    public String getFullName()
+    {
+	return metadata_element_name_full;
+    }
+
+
+    public String getNamespace()
+    {
+	return MetadataTools.getMetadataSetNamespace(metadata_element_name_full);
+    }
+
+
+    /** Returns language-independent metadata element name, *without* namespace (eg. Subject) */
+    public String getName()
+    {
+	return MetadataTools.getMetadataElementName(metadata_element_name_full);
+    }
+
+
+    public boolean isExtractedMetadataElement()
+    {
+	return getNamespace().equals(MetadataSetManager.EXTRACTED_METADATA_NAMESPACE);
+    }
+
+    public boolean isPredefined() {
+	return predefined_values;
+    }
+
+    public boolean isRestricted() {
+	return restricted_values;
+    }
+
+    public boolean isSubelement()
+    {
+	return (metadata_element_name_full.indexOf(MetadataTools.SUBELEMENT_SEPARATOR) != -1);
+    }
+
+
+    /** This is used to display the element in the metadata value table */
+    public String toString()
+    {
+	return getDisplayName();
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataSet.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataSet.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataSet.java	(revision 13928)
@@ -0,0 +1,226 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2004 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.metadata;
+
+
+import java.io.File;
+import java.util.*;
+import javax.swing.filechooser.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.util.XMLTools;
+import org.w3c.dom.*;
+
+
+/** This class represents one metadata set */
+public class MetadataSet
+{
+    private File metadata_set_file = null;
+    private ArrayList metadata_set_elements = new ArrayList();
+    private String metadata_set_namespace = null;
+
+
+    public MetadataSet(File metadata_set_file)
+    {
+	this.metadata_set_file = metadata_set_file;
+
+	// Parse the specified metadata set file
+	Document document = XMLTools.parseXMLFile(metadata_set_file);
+	if (document == null) {
+	    System.err.println("Error: Could not parse metadata set file " + metadata_set_file.getAbsolutePath());
+	    return;
+	}
+
+	// Read the metadata set's namespace
+	metadata_set_namespace = document.getDocumentElement().getAttribute("namespace");
+
+	// Read the Element elements in the metadata set
+	NodeList element_elements_nodelist = document.getElementsByTagName("Element");
+	for (int i = 0; i < element_elements_nodelist.getLength(); i++) {
+	    Element metadata_element_element = (Element) element_elements_nodelist.item(i);
+	    String metadata_element_name = metadata_element_element.getAttribute("name");
+
+	    // Deal with hierarchical metadata elements
+	    Element parent_metadata_element_element = (Element) metadata_element_element.getParentNode();
+	    while (parent_metadata_element_element.getTagName().equals("Element")) {
+		String parent_metadata_element_name = parent_metadata_element_element.getAttribute("name");
+		metadata_element_name = parent_metadata_element_name + MetadataTools.SUBELEMENT_SEPARATOR + metadata_element_name;
+		parent_metadata_element_element = (Element) parent_metadata_element_element.getParentNode();
+	    }
+
+	    String metadata_element_name_full = metadata_set_namespace + MetadataTools.NAMESPACE_SEPARATOR + metadata_element_name;
+	    metadata_set_elements.add(new MetadataElement(metadata_element_name_full, metadata_element_element));
+	}
+    }
+
+
+    public MetadataElement addMetadataElementForThisSession(String metadata_element_name)
+    {
+	String metadata_element_name_full = metadata_set_namespace + MetadataTools.NAMESPACE_SEPARATOR + metadata_element_name;
+	MetadataElement metadata_element = new MetadataElement(metadata_element_name_full, null);
+	metadata_set_elements.add(metadata_element);
+	return metadata_element;
+    }
+
+
+    public int compareMetadataElements(MetadataElement metadata_element_a, MetadataElement metadata_element_b)
+    {
+	// Extracted metadata is sorted alphabetically
+	if (metadata_set_namespace.equals(MetadataSetManager.EXTRACTED_METADATA_NAMESPACE)) {
+	    return metadata_element_a.getName().compareTo(metadata_element_b.getName());
+	}
+
+	// Elements in metadata sets are sorted according to the other they are specified in the .mds file
+	return metadata_set_elements.indexOf(metadata_element_a) - metadata_set_elements.indexOf(metadata_element_b);
+    }
+
+    /** we consider MetadataSets to be equal if their names and namespaces match */
+    public boolean equals(Object obj) {
+	if (obj instanceof MetadataSet) {
+	    return toString().equals(obj.toString());
+	}
+	return false;
+    }
+
+
+    public String getAttribute(String attribute_name, String language_code)
+    {
+	// Parse the specified metadata set file
+	Document document = XMLTools.parseXMLFile(metadata_set_file);
+	if (document == null) {
+	    System.err.println("Error: Could not parse metadata set file " + metadata_set_file.getAbsolutePath());
+	    return null;
+	}
+
+	Element document_element = document.getDocumentElement();
+	Element parent_element = document_element;
+	boolean language_matches = false;
+
+	NodeList setlanguage_elements_nodelist = document_element.getElementsByTagName("SetLanguage");
+	for (int i = 0; i < setlanguage_elements_nodelist.getLength(); i++) {
+	    Element current_setlanguage_element = (Element) setlanguage_elements_nodelist.item(i);
+	    String current_setlanguage_element_code = current_setlanguage_element.getAttribute("code");
+	    if (current_setlanguage_element_code.equals(language_code)) {
+		// Found language; use it for the next step
+		parent_element = current_setlanguage_element;
+		language_matches = true;
+		break;
+	    }
+	}
+
+	NodeList attribute_elements_nodelist = parent_element.getElementsByTagName(attribute_name);
+	for (int i = 0; i < attribute_elements_nodelist.getLength(); i++) {
+	    Element current_attribute_element = (Element) attribute_elements_nodelist.item(i);
+
+	    // Check if the language matches
+	    String current_attribute_element_language = current_attribute_element.getAttribute("language");
+	    if (language_matches || current_attribute_element_language.equals(language_code)) {
+		// Found attribute; returns its value
+		return XMLTools.getElementTextValue(current_attribute_element);
+	    }
+	}
+
+	return null;
+    }
+
+
+    public MetadataElement getMetadataElementWithDisplayName(String metadata_element_display_name_full)
+    {
+	// Find the desired metadata element in the list
+	for (int i = 0; i < metadata_set_elements.size(); i++) {
+	    MetadataElement metadata_element = (MetadataElement) metadata_set_elements.get(i);
+	    if (metadata_element.getDisplayName().equals(metadata_element_display_name_full)) {
+		return metadata_element;
+	    }
+	}
+
+	// Not found
+	return null;
+    }
+
+
+    public MetadataElement getMetadataElementWithName(String metadata_element_name)
+    {
+	// Find the desired metadata element in the list
+	for (int i = 0; i < metadata_set_elements.size(); i++) {
+	    MetadataElement metadata_element = (MetadataElement) metadata_set_elements.get(i);
+	    if (metadata_element.getName().equals(metadata_element_name)) {
+		return metadata_element;
+	    }
+	}
+
+	// Not found
+	return null;
+    }
+
+
+    public ArrayList getMetadataSetElements()
+    {
+	// We don't want anyone to modify the list, so return a copy of it
+	return (ArrayList) metadata_set_elements.clone();
+    }
+
+
+    public File getMetadataSetFile()
+    {
+	return metadata_set_file;
+    }
+
+
+    public String getNamespace()
+    {
+	return metadata_set_namespace;
+    }
+
+
+    /** This is used to display the metadata set in the metadata import mapping and explode metadata prompts */
+    public String toString()
+    {
+	return MetadataTools.getMetadataSetAttribute(this, "Name", Configuration.getLanguage(), "en") + " (" + metadata_set_namespace + ")";
+    }
+
+
+    static public class MetadataSetFileFilter
+	extends FileFilter
+    {
+	public boolean accept(File file)
+	{
+	    String file_name = file.getName().toLowerCase();
+	    if (file_name.endsWith(".mds") || file_name.indexOf(".") == -1) {
+		return true;
+	    }
+
+	    return false;
+	}
+
+
+	public String getDescription()
+	{
+	    return Dictionary.get("MetadataSet.Files");
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataSetManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataSetManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataSetManager.java	(revision 13928)
@@ -0,0 +1,208 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2004 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.metadata;
+
+
+import java.io.*;
+import java.util.*;
+import org.greenstone.gatherer.gui.MetadataImportMappingPrompt;
+
+
+/** This class is a static class that manages the metadata sets */
+public class MetadataSetManager
+{
+    static public final String EXTRACTED_METADATA_NAMESPACE = "ex";
+    static public final String EXPLODED_METADATA_NAMESPACE = "exp";
+
+    static private ArrayList metadata_sets = new ArrayList();
+
+
+    static public void clearMetadataSets()
+    {
+	metadata_sets.clear();
+    }
+
+
+    static public int compareMetadataElements(MetadataElement metadata_element_a, MetadataElement metadata_element_b)
+    {
+	// First compare the namespaces of the two metadata elements
+	if (!metadata_element_a.getNamespace().equals(metadata_element_b.getNamespace())) {
+	    return metadata_element_a.getNamespace().compareTo(metadata_element_b.getNamespace());
+	}
+
+	// Otherwise compare the two elements within the one set
+	MetadataSet metadata_set = getMetadataSet(metadata_element_a.getNamespace());
+	return metadata_set.compareMetadataElements(metadata_element_a, metadata_element_b);
+    }
+
+
+    static public ArrayList getEveryMetadataSetElement()
+    {
+	ArrayList every_metadata_set_element = new ArrayList();
+
+	for (int i = 0; i < metadata_sets.size(); i++) {
+	    MetadataSet metadata_set = (MetadataSet) metadata_sets.get(i);
+	    every_metadata_set_element.addAll(metadata_set.getMetadataSetElements());
+	}
+
+	return every_metadata_set_element;
+    }
+
+
+    static public MetadataSet getMetadataSet(String metadata_set_namespace)
+    {
+	// Find the desired metadata set in the list
+	for (int i = 0; i < metadata_sets.size(); i++) {
+	    MetadataSet metadata_set = (MetadataSet) metadata_sets.get(i);
+	    if (metadata_set.getNamespace().equals(metadata_set_namespace)) {
+		return metadata_set;
+	    }
+	}
+
+	// Not found
+	return null;
+    }
+
+
+    static public ArrayList getMetadataSets()
+    {
+	// We don't want anyone to modify the list, so return a copy of it
+	return (ArrayList) metadata_sets.clone();
+    }
+
+
+    static public ArrayList listMetadataSets(File directory)
+    {
+	// Make sure the directory (metadata) exists
+	if (directory.exists() == false) {
+	    return null;
+	}
+
+	// Load just those .mds files in this directory, and return them
+	ArrayList directory_metadata_sets = new ArrayList();
+	File[] directory_files = directory.listFiles();
+	for (int i = 0; i < directory_files.length; i++) {
+	    File child_file = directory_files[i];
+	    if (!child_file.isDirectory() && child_file.getName().endsWith(".mds")) {
+		MetadataSet metadata_set = new MetadataSet(child_file);
+		directory_metadata_sets.add(metadata_set);
+	    }
+	}
+
+	return directory_metadata_sets;
+    }
+
+
+    static public void loadMetadataSets(File directory)
+    {
+	// Make sure the directory (metadata) exists
+	if (directory.exists() == false) {
+	    return;
+	}
+
+	// Look recursively at each subfile of the directory for .mds files
+	File[] directory_files = directory.listFiles();
+	for (int i = 0; i < directory_files.length; i++) {
+	    File child_file = directory_files[i];
+	    if (child_file.isDirectory()) {
+		loadMetadataSets(child_file);
+	    }
+	    else if (child_file.getName().endsWith(".mds")) {
+		loadMetadataSet(child_file);
+	    }
+	}
+    }
+
+
+    static public void loadMetadataSet(File metadata_set_file)
+    {
+	MetadataSet metadata_set = new MetadataSet(metadata_set_file);
+
+	// Ignore legacy crap
+	if (metadata_set.getNamespace().equals("hidden")) {
+	    return;
+	}
+
+	metadata_sets.add(metadata_set);
+    }
+
+
+    static public String mapUnloadedMetadataElement(String metadata_element_name_full)
+    {
+	// Check if we have an import mapping for this metadata element
+	String target_metadata_element_name_full = ProfileXMLFileManager.getMetadataElementFor(metadata_element_name_full);
+	if (target_metadata_element_name_full != null) {
+	    // Yes, so return it
+	    return target_metadata_element_name_full;
+	}
+
+	// If there are no metadata sets (except extracted) loaded then there is nothing to map the element into
+	if (metadata_sets.size() <= 1) {
+	    return null;
+	}
+
+	// Ask the user how they want to deal with this element
+	MetadataImportMappingPrompt metadata_import_mapping_prompt = new MetadataImportMappingPrompt(metadata_element_name_full);
+	int result = metadata_import_mapping_prompt.getResult();
+
+	// Add the element into an existing metadata set
+	if (result == MetadataImportMappingPrompt.ADD_BUTTON_PRESSED) {
+	    MetadataSet target_metadata_set = metadata_import_mapping_prompt.getSelectedMetadataSet();
+	    String metadata_element_name = MetadataTools.getMetadataElementName(metadata_element_name_full);
+	    target_metadata_set.addMetadataElementForThisSession(metadata_element_name);
+	    target_metadata_element_name_full = target_metadata_set.getNamespace() + "." + metadata_element_name;
+	}
+
+	// Replace the element with an element in an existing metadata set
+	if (result == MetadataImportMappingPrompt.MERGE_BUTTON_PRESSED) {
+	    MetadataElement target_metadata_element = metadata_import_mapping_prompt.getSelectedMetadataElement();
+	    target_metadata_element_name_full = target_metadata_element.getFullName();
+	}
+
+	// Ignore the element
+	if (result == MetadataImportMappingPrompt.IGNORE_BUTTON_PRESSED) {
+	    target_metadata_element_name_full = "";
+	}
+
+	// Store this import mapping for future elements with the same name
+	ProfileXMLFileManager.mapElement(metadata_element_name_full, target_metadata_element_name_full);
+
+	return target_metadata_element_name_full;
+    }
+
+
+    static public void unloadMetadataSet(MetadataSet metadata_set)
+    {
+	// Find the metadata set in the list of loaded sets, and remove it
+	for (int i = 0; i < metadata_sets.size(); i++) {
+	    if (metadata_set == (MetadataSet) metadata_sets.get(i)) {
+		metadata_sets.remove(i);
+		break;
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataTools.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataTools.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataTools.java	(revision 13928)
@@ -0,0 +1,137 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2004 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.metadata;
+
+
+/** This class is a static class containing useful metadata functions */
+public class MetadataTools
+{
+    static final public String NAMESPACE_SEPARATOR = ".";
+    static final public String SUBELEMENT_SEPARATOR = "^";
+
+
+    static public String getDisplayNameForMetadataElementWithName(String metadata_element_name_full)
+    {
+	MetadataElement metadata_element = getMetadataElementWithName(metadata_element_name_full);
+	if (metadata_element != null) {
+	    return metadata_element.getDisplayName();
+	}
+
+	return metadata_element_name_full;
+    }
+
+
+    static public String getMetadataElementAttribute(MetadataElement metadata_element, String attribute_name, String language_code, String fallback_language_code)
+    {
+	String metadata_element_attribute = metadata_element.getAttribute(attribute_name, language_code);
+
+	// If the attribute isn't defined in the desired language, resort to the fallback
+	if (metadata_element_attribute == null && !language_code.equals(fallback_language_code)) {
+	    metadata_element_attribute = metadata_element.getAttribute(attribute_name, fallback_language_code);
+	}
+
+	return metadata_element_attribute;
+    }
+
+
+    static public String getMetadataElementName(String metadata_element_name_full)
+    {
+	// Full element name contains namespace
+	if (metadata_element_name_full.indexOf(NAMESPACE_SEPARATOR) != -1) {
+	    return metadata_element_name_full.substring(metadata_element_name_full.indexOf(NAMESPACE_SEPARATOR) + 1);
+	}
+
+	// No namespace
+	return metadata_element_name_full;      
+    }
+
+
+    static public MetadataElement getMetadataElementWithDisplayName(String metadata_element_display_name_full)
+    {
+	String metadata_set_namespace = getMetadataSetNamespace(metadata_element_display_name_full);
+	MetadataSet metadata_set = MetadataSetManager.getMetadataSet(metadata_set_namespace);
+	if (metadata_set == null) {
+	    return null;
+	}
+
+	return metadata_set.getMetadataElementWithDisplayName(metadata_element_display_name_full);
+    }
+
+
+    static public MetadataElement getMetadataElementWithName(String metadata_element_name_full)
+    {
+	String metadata_set_namespace = getMetadataSetNamespace(metadata_element_name_full);
+	MetadataSet metadata_set = MetadataSetManager.getMetadataSet(metadata_set_namespace);
+	if (metadata_set == null) {
+	    return null;
+	}
+
+	String metadata_element_name = getMetadataElementName(metadata_element_name_full);
+	return metadata_set.getMetadataElementWithName(metadata_element_name);
+    }
+
+
+    static public String getMetadataSetAttribute(MetadataSet metadata_set, String attribute_name, String language_code, String fallback_language_code)
+    {
+	String metadata_set_attribute = metadata_set.getAttribute(attribute_name, language_code);
+
+	// If the attribute isn't defined in the desired language, resort to the fallback
+	if (metadata_set_attribute == null && !language_code.equals(fallback_language_code)) {
+	    metadata_set_attribute = metadata_set.getAttribute(attribute_name, fallback_language_code);
+	}
+
+	return metadata_set_attribute;
+    }
+
+
+    static public String getMetadataSetNamespace(String metadata_element_name_full)
+    {
+	// Full element name contains namespace
+	if (metadata_element_name_full.indexOf(NAMESPACE_SEPARATOR) != -1) {
+	    return metadata_element_name_full.substring(0, metadata_element_name_full.indexOf(NAMESPACE_SEPARATOR));
+	}
+
+	// No namespace
+	return "";
+    }
+
+
+    static public String getRegularExpressionThatMatchesFilePath(String file_path)
+    {
+	// Convert the file path into a regular expression that will match it
+	String file_path_regexp = file_path;
+	file_path_regexp = file_path_regexp.replaceAll("\\.", "\\\\.");
+	file_path_regexp = file_path_regexp.replaceAll("\\(", "\\\\(");
+	file_path_regexp = file_path_regexp.replaceAll("\\)", "\\\\)");
+	file_path_regexp = file_path_regexp.replaceAll("\\[", "\\\\[");
+	file_path_regexp = file_path_regexp.replaceAll("\\]", "\\\\]");
+	file_path_regexp = file_path_regexp.replaceAll("\\{", "\\\\{");
+	file_path_regexp = file_path_regexp.replaceAll("\\}", "\\\\}");
+	file_path_regexp = file_path_regexp.replaceAll("\\+", "\\\\+");
+	return file_path_regexp;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataValue.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataValue.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataValue.java	(revision 13928)
@@ -0,0 +1,132 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2004 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.metadata;
+
+
+import java.io.*;
+
+
+/** This class represents one metadata (element, value) pair */
+public class MetadataValue
+    implements Comparable
+{
+    /** The folder that this piece of metadata was inherited from, if applicable */
+    private File folder_metadata_inherited_from = null;
+    private MetadataElement metadata_element = null;
+    private MetadataValueTreeNode metadata_value_tree_node = null;
+    private boolean is_accumulating_metadata = false;
+    /** Whether this metadata applies to only one file (ie. there are no wildcards in the FileSet value) */
+    private boolean is_one_file_only_metadata = true;
+
+
+    public MetadataValue(MetadataElement metadata_element, MetadataValueTreeNode metadata_value_tree_node)
+    {
+	this.metadata_element = metadata_element;
+	this.metadata_value_tree_node = metadata_value_tree_node;
+    }
+
+
+    public int compareTo(Object metadata_value_object)
+    {
+	MetadataValue metadata_value = (MetadataValue) metadata_value_object;
+
+	// First compare the metadata elements
+	int c = MetadataSetManager.compareMetadataElements(this.getMetadataElement(), metadata_value.getMetadataElement());
+	if (c != 0) {
+	    return c;
+	}
+
+	// Then use the metadata values
+	return this.getFullValue().compareTo(metadata_value.getFullValue());
+    }
+
+
+    public File getFolderMetadataInheritedFrom()
+    {
+	return folder_metadata_inherited_from;
+    }
+
+
+    public MetadataElement getMetadataElement()
+    {
+	return metadata_element;
+    }
+
+
+    public String getFullValue()
+    {
+	return metadata_value_tree_node.getFullValue();
+    }
+
+
+    public String getValue()
+    {
+	return metadata_value_tree_node.getValue();
+    }
+
+
+    public MetadataValueTreeNode getMetadataValueTreeNode()
+    {
+	return metadata_value_tree_node;
+    }
+
+
+    public void inheritsMetadataFromFolder(File folder_metadata_inherited_from)
+    {
+	this.folder_metadata_inherited_from = folder_metadata_inherited_from;
+    }
+
+
+    public boolean isAccumulatingMetadata()
+    {
+	return is_accumulating_metadata;
+    }
+
+
+    public boolean isInheritedMetadata()
+    {
+	return (folder_metadata_inherited_from != null);
+    }
+
+
+    public boolean isOneFileOnlyMetadata()
+    {
+	return is_one_file_only_metadata;
+    }
+
+
+    public void setIsAccumulatingMetadata(boolean is_accumulating_metadata)
+    {
+	this.is_accumulating_metadata = is_accumulating_metadata;
+    }
+
+
+    public void setIsOneFileOnlyMetadata(boolean is_one_file_only_metadata)
+    {
+	this.is_one_file_only_metadata = is_one_file_only_metadata;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataValueTableEntry.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataValueTableEntry.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataValueTableEntry.java	(revision 13928)
@@ -0,0 +1,69 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2005 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.metadata;
+
+
+/** This class represents one entry in the metadata value table. */
+public class MetadataValueTableEntry
+    extends MetadataValue
+{
+    private int occurrences = 0;
+
+
+    public MetadataValueTableEntry(MetadataElement metadata_element, MetadataValueTreeNode metadata_value_tree_node)
+    {
+	super(metadata_element, metadata_value_tree_node);
+
+	occurrences = 1;
+    }
+
+
+    public MetadataValueTableEntry(MetadataValue metadata_value)
+    {
+	this(metadata_value.getMetadataElement(), metadata_value.getMetadataValueTreeNode());
+	inheritsMetadataFromFolder(metadata_value.getFolderMetadataInheritedFrom());
+	setIsOneFileOnlyMetadata(metadata_value.isOneFileOnlyMetadata());
+    }
+
+
+    public void anotherOccurrence()
+    {
+	occurrences++;
+    }
+
+
+    public int getOccurrences()
+    {
+	return occurrences;
+    }
+
+
+    public void setOccurrences(int occurrences)
+    {
+	this.occurrences = occurrences;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataValueTableModel.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataValueTableModel.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataValueTableModel.java	(revision 13928)
@@ -0,0 +1,478 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2004 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.metadata;
+
+
+import java.awt.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.table.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.CollectionTreeNode;
+import org.greenstone.gatherer.gui.WarningDialog;
+
+
+public class MetadataValueTableModel
+    extends AbstractTableModel
+{
+    /** It is not expected that this class will ever be serialized */
+    private static final long serialVersionUID = 0L;
+
+    /** The CollectionTreeNodes this model is built for */
+    private CollectionTreeNode[] file_nodes = null;
+    /** The list of MetadataValueTableEntries in the table */
+    private ArrayList metadata_value_table_entries = new ArrayList();
+
+    static final private String[] COLUMN_NAMES = { "", Dictionary.get("Metadata.Element"), Dictionary.get("Metadata.Value") };
+
+
+    public int addBlankRowForMetadataElement(MetadataElement metadata_element)
+    {
+	MetadataValueTableModelBuilder metadata_value_table_model_builder = new MetadataValueTableModelBuilder();
+	MetadataValue blank_metadata_value = new MetadataValue(metadata_element, new MetadataValueTreeNode(""));
+	return metadata_value_table_model_builder.insertMetadataValue(blank_metadata_value);
+    }
+
+
+    public int findMetadataValueTableEntryToSelect(MetadataValueTableEntry metadata_value_table_entry)
+    {
+	MetadataElement metadata_element = metadata_value_table_entry.getMetadataElement();
+
+	// Find the correct entry to select
+	for (int i = 0; i < metadata_value_table_entries.size(); i++) {
+	    MetadataValueTableEntry current_metadata_value_table_entry = (MetadataValueTableEntry) metadata_value_table_entries.get(i);
+	    int element_comparison = MetadataSetManager.compareMetadataElements(current_metadata_value_table_entry.getMetadataElement(), metadata_element);
+
+	    // We've found the right element, so check if the value already exists
+	    if (element_comparison == 0) {
+		int value_comparison = current_metadata_value_table_entry.compareTo(metadata_value_table_entry);
+		if (value_comparison == 0) {
+		    // Entry found!
+		    return i;
+		}
+	    }
+
+	    // We've just gone past the correct entry to select
+	    if (element_comparison > 0) {
+		return i - 1;
+	    }
+	}
+
+	// Have to select the last entry
+	return metadata_value_table_entries.size() - 1;
+    }
+
+
+    public Class getColumnClass(int col)
+    {
+	return getValueAt(0, col).getClass();
+    }
+
+
+    /** Returns the number of columns in this table. */
+    public int getColumnCount()
+    {
+	return COLUMN_NAMES.length;
+    }
+
+
+    /** Retrieves the name of the specified column. */
+    public String getColumnName(int col)
+    {
+	return COLUMN_NAMES[col];
+    }
+
+
+    /* Called to retrieve the MetadataValueTableEntry at a certain row. Usually caused by the user selecting a row in the table. It is synchronized so that the model doesn't up and change while we're trying to retrieve the indicated element. */
+    public synchronized MetadataValueTableEntry getMetadataValueTableEntry(int row)
+    {
+	if (row >= 0 && row < metadata_value_table_entries.size()) {
+	    return (MetadataValueTableEntry) metadata_value_table_entries.get(row);
+	}
+
+	return null;
+    }
+
+
+    /** Returns the number of rows in this table. */
+    public int getRowCount()
+    {
+	return metadata_value_table_entries.size();
+    }
+
+
+    /** Returns the cell value at a given row and column as an Object. */
+    public Object getValueAt(int row, int col)
+    {
+	// Check values are reasonable
+	if (row < 0 || row >= metadata_value_table_entries.size() || col < 0 || col >= COLUMN_NAMES.length) {
+	    return null;
+	}
+
+	MetadataValueTableEntry metadata_value_table_entry = (MetadataValueTableEntry) metadata_value_table_entries.get(row);
+	if (col == 0 && metadata_value_table_entry.isInheritedMetadata()) {
+	    return metadata_value_table_entry.getFolderMetadataInheritedFrom();
+	}
+
+	if (col == 1) {
+	    return metadata_value_table_entry.getMetadataElement();
+	}
+
+	if (col == 2) {
+	    return metadata_value_table_entry.getFullValue();
+	}
+
+	return null;
+    }
+
+
+    public boolean isCellEditable(int row, int col)
+    {
+	// The inherited and element columns are never editable
+	if (col < 2) {
+	    return false;
+	}
+
+	// Extracted and inherited metadata is not editable
+	MetadataValueTableEntry metadata_value_table_entry = (MetadataValueTableEntry) metadata_value_table_entries.get(row);
+	if (metadata_value_table_entry.getMetadataElement().isExtractedMetadataElement() || metadata_value_table_entry.isInheritedMetadata()) {
+	    return false;
+	}
+
+	return true;
+    }
+
+
+    /** Determine if the given metadata is common to all selected file nodes. */
+    public boolean isCommon(MetadataValueTableEntry metadata_value_table_entry)
+    {
+	return (file_nodes != null && metadata_value_table_entry.getOccurrences() == file_nodes.length);
+    }
+
+
+    /** Determine if the given metadata is common to all selected file nodes. */
+    public boolean isCommon(int row)
+    {
+	if (row >= 0 && row < metadata_value_table_entries.size()) {
+	    return isCommon((MetadataValueTableEntry) metadata_value_table_entries.get(row));
+	}
+
+	return false;
+    }
+
+
+    public void rebuild(CollectionTreeNode[] file_nodes)
+    {
+	this.file_nodes = file_nodes;
+	metadata_value_table_entries.clear();
+
+	// Collection is in a state of flux
+	if (!Gatherer.c_man.ready()) {
+	    return;
+	}
+
+	if (file_nodes == null || file_nodes.length == 0) {
+	    return;
+	}
+
+	// Create model builder
+	MetadataValueTableModelBuilder builder = new MetadataValueTableModelBuilder();
+	builder.run();
+    }
+
+
+    public void setValueAt(Object new_metadata_value, int row, int col)
+    {
+	MetadataValueTableEntry metadata_value_table_entry = getMetadataValueTableEntry(row);
+
+	// If nothing has changed no action is necessary
+	String old_metadata_value = metadata_value_table_entry.getFullValue();
+	if (new_metadata_value.equals(old_metadata_value)) {
+	    return;
+	}
+
+	// Lock the interface so nothing can be changed while the metadata edit is being processed
+	Gatherer.g_man.wait(true);
+
+	
+	// Check for a restricted metadata element
+	MetadataElement metadata_element = metadata_value_table_entry.getMetadataElement();
+	if (!new_metadata_value.equals("") && metadata_element.isRestricted()) {
+	    if (metadata_element.getMetadataValueTreeNode((String)new_metadata_value)==null) {
+		WarningDialog dialog = new WarningDialog("warning.InvalidMetadata", Dictionary.get("InvalidMetadata.Title"), Dictionary.get("InvalidMetadata.Message"), null, false);
+		int dialog_result = dialog.display();
+		dialog.dispose();
+		Gatherer.g_man.wait(false);
+		return;
+		
+	    }
+	}
+	
+	// Metadata value added
+	if (old_metadata_value.equals("") && !new_metadata_value.equals("")) {    
+	    // If we're adding metadata to folders display the warning
+ 	    if (!file_nodes[0].isLeaf()) {
+ 		WarningDialog dialog = new WarningDialog("warning.DirectoryLevelMetadata", Dictionary.get("DirectoryLevelMetadata.Title"), Dictionary.get("DirectoryLevelMetadata.Message"), null, true);
+ 		int dialog_result = dialog.display();
+ 		dialog.dispose();
+ 		if (dialog_result != JOptionPane.OK_OPTION) {
+		    Gatherer.g_man.wait(false);
+ 		    return;
+ 		}
+ 	    }
+
+	    MetadataValueTreeNode metadata_value_tree_node = metadata_element.addMetadataValue((String) new_metadata_value);
+	    MetadataValue metadata_value = new MetadataValue(metadata_element, metadata_value_tree_node);
+	    metadata_value.setIsAccumulatingMetadata(true);
+	    (new AppendMetadataTask(metadata_value)).run();
+	}
+
+	// Metadata value removed
+	else if (!old_metadata_value.equals("") && new_metadata_value.equals("")) {
+	    (new RemoveMetadataTask(metadata_value_table_entry)).run();
+	}
+
+	// Metadata value replaced
+	else {
+	    MetadataValueTreeNode metadata_value_tree_node = metadata_element.addMetadataValue((String) new_metadata_value);
+	    MetadataValue metadata_value = new MetadataValue(metadata_element, metadata_value_tree_node);
+	    metadata_value.setIsAccumulatingMetadata(!metadata_value_table_entry.isInheritedMetadata());
+	    (new ReplaceMetadataTask(metadata_value_table_entry, metadata_value)).run();
+	}
+    }
+
+
+    private class AppendMetadataTask
+	// extends Thread
+    {
+	private MetadataValue metadata_value = null;
+
+	private AppendMetadataTask(MetadataValue metadata_value)
+	{
+	    this.metadata_value = metadata_value;
+	}
+
+	public void run()
+	{
+	    try {
+		// Edit metadata.xml files to add the metadata
+		MetadataXMLFileManager.addMetadata(file_nodes, metadata_value);
+	    }
+	    catch (Exception exception) {
+		// We need to catch any exceptions here so the interface is unlocked below
+		DebugStream.printStackTrace(exception);
+	    }
+
+	    // Operation finished, so turn busy cursor off and unlock interface
+	    Gatherer.g_man.wait(false);
+	}
+    }
+
+
+    private class ReplaceMetadataTask
+	// extends Thread
+    {
+	private MetadataValueTableEntry selected_metadata_value_table_entry = null;
+	private MetadataValue metadata_value = null;
+
+	private ReplaceMetadataTask(MetadataValueTableEntry selected_metadata_value_table_entry, MetadataValue metadata_value)
+	{
+	    this.selected_metadata_value_table_entry = selected_metadata_value_table_entry;
+	    this.metadata_value = metadata_value;
+	}
+
+	public void run()
+	{
+	    try {
+		// Edit metadata.xml files to replace the metadata
+		MetadataXMLFileManager.replaceMetadata(file_nodes, selected_metadata_value_table_entry, metadata_value);
+	    }
+	    catch (Exception exception) {
+		// We need to catch any exceptions here so the interface is unlocked below
+		DebugStream.printStackTrace(exception);
+	    }
+
+	    // Operation finished, so turn busy cursor off and unlock interface
+	    Gatherer.g_man.wait(false);
+	}
+    }
+
+
+    private class RemoveMetadataTask
+	// extends Thread
+    {
+	private MetadataValueTableEntry selected_metadata_value_table_entry = null;
+
+	private RemoveMetadataTask(MetadataValueTableEntry selected_metadata_value_table_entry)
+	{
+	    this.selected_metadata_value_table_entry = selected_metadata_value_table_entry;
+	}
+
+	public void run()
+	{
+	    try {
+		// Edit metadata.xml files to remove the metadata
+		MetadataXMLFileManager.removeMetadata(file_nodes, selected_metadata_value_table_entry);
+	    }
+	    catch (Exception exception) {
+		// We need to catch any exceptions here so the interface is unlocked below
+		DebugStream.printStackTrace(exception);
+	    }
+
+	    // Operation finished, so turn busy cursor off and unlock interface
+	    Gatherer.g_man.wait(false);
+	}
+    }
+
+
+    private class MetadataValueTableModelBuilder
+    {
+	public void run()
+	{
+	    // System.err.println("Building MetadataValueTableModel...");
+
+	    // Build a list of MetadataValueTableEntries that represent the metadata asssigned to the selected files
+	    boolean hid_extracted_metadata = false;
+	    ArrayList metadata_elements_seen = new ArrayList();
+
+	    // Process each of the selected files in turn
+	    for (int i = 0; i < file_nodes.length; i++) {
+		File current_file = file_nodes[i].getFile();
+
+		// Get the metadata assigned to this file
+		ArrayList assigned_metadata = MetadataXMLFileManager.getMetadataAssignedToFile(current_file);
+		for (int j = 0; j < assigned_metadata.size(); j++) {
+		    MetadataValue metadata_value = (MetadataValue) assigned_metadata.get(j);
+		    MetadataElement metadata_element = metadata_value.getMetadataElement();
+
+		    // Insert this metadata value into the table, unless it already exists (in which case increment its count)
+		    insertMetadataValue(metadata_value);
+
+		    // Remember we have seen this metadata element
+		    if (metadata_elements_seen.contains(metadata_element) == false) {
+			metadata_elements_seen.add(metadata_element);
+		    }
+		}
+
+		// Get the extracted metadata for this file, if desired
+		if (Configuration.get("general.view_extracted_metadata", Configuration.COLLECTION_SPECIFIC) == true) {
+		    ArrayList extracted_metadata = DocXMLFileManager.getMetadataExtractedFromFile(current_file);
+		    for (int k = 0; k < extracted_metadata.size(); k++) {
+			MetadataValue metadata_value = (MetadataValue) extracted_metadata.get(k);
+
+			// Insert this metadata value into the table, unless it already exists (in which case increment its count)
+			insertMetadataValue(metadata_value);
+		    }
+		}
+	    }
+
+	    // Make sure each non-extracted metadata element appears in the table (even if blank)
+	    ArrayList every_metadata_set_element = MetadataSetManager.getEveryMetadataSetElement();
+	    for (int i = 0; i < every_metadata_set_element.size(); i++) {
+		MetadataElement metadata_element = (MetadataElement) every_metadata_set_element.get(i);
+
+		// If we haven't seen this metadata element and it isn't extracted, add it now
+		if (!metadata_elements_seen.contains(metadata_element) && !metadata_element.isExtractedMetadataElement()) {
+		    MetadataValueTableEntry metadata_value_table_entry = new MetadataValueTableEntry(metadata_element, new MetadataValueTreeNode(""));
+
+		    // Blank metadata is common to all selected files (otherwise it wouldn't be blank!)
+		    metadata_value_table_entry.setOccurrences(file_nodes.length);
+
+		    // Add it to the table
+		    insertMetadataValueTableEntry(metadata_value_table_entry);
+		}
+	    }
+
+	    // If extracted metadata was hidden, display the warning
+	    if (hid_extracted_metadata) {
+		showExtractedMetadataWarning();
+	    }
+	}
+
+
+	/** Inserts the new metadata value into the table */
+	private int insertMetadataValue(MetadataValue metadata_value)
+	{
+	    return insertMetadataValueTableEntry(new MetadataValueTableEntry(metadata_value));
+	}
+
+
+	/** Inserts the new metadata value table entry into the table */
+	private int insertMetadataValueTableEntry(MetadataValueTableEntry metadata_value_table_entry)
+	{
+	    MetadataElement metadata_element = metadata_value_table_entry.getMetadataElement();
+
+	    // Find the correct place to insert the table entry
+	    for (int i = 0; i < metadata_value_table_entries.size(); i++) {
+		MetadataValueTableEntry current_metadata_value_table_entry = (MetadataValueTableEntry) metadata_value_table_entries.get(i);
+		int element_comparison = MetadataSetManager.compareMetadataElements(current_metadata_value_table_entry.getMetadataElement(), metadata_element);
+
+		// We've found the right element, so check if the value already exists
+		if (element_comparison == 0) {
+		    int value_comparison = current_metadata_value_table_entry.compareTo(metadata_value_table_entry);
+		    if (value_comparison == 0) {
+			// Entry already exists, so increment count (except for blank entries)
+			if (!metadata_value_table_entry.getFullValue().equals("")) {
+			    current_metadata_value_table_entry.anotherOccurrence();
+			}
+			return i;
+		    }
+		}
+
+		// Found insertion point
+		if (element_comparison > 0) {
+		    metadata_value_table_entries.add(i, metadata_value_table_entry);
+		    fireTableRowsInserted(i, i);
+		    return i;
+		}
+	    }
+
+	    // Must go at the end of the table
+	    metadata_value_table_entries.add(metadata_value_table_entry);
+	    fireTableRowsInserted(metadata_value_table_entries.size() - 1, metadata_value_table_entries.size() - 1);
+	    return metadata_value_table_entries.size() - 1;
+	}
+
+
+	private void showExtractedMetadataWarning()
+	{
+	    Runnable task = new Runnable() {
+		    public void run() {
+			WarningDialog dialog = new WarningDialog("warning.ExtractedMetadata", Dictionary.get("ExtractedMetadata.Title"), Dictionary.get("ExtractedMetadata.Message"), null, false);
+			dialog.display();
+			dialog.dispose();
+			dialog = null;
+		    }
+		};
+	    SwingUtilities.invokeLater(task);
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataValueTreeModel.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataValueTreeModel.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataValueTreeModel.java	(revision 13928)
@@ -0,0 +1,137 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2004 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.metadata;
+
+
+import java.io.*;
+import java.util.*;
+import javax.swing.tree.*;
+
+
+/** This class represents all the metadata values for one metadata element */
+public class MetadataValueTreeModel
+    extends DefaultTreeModel
+{
+    public MetadataValueTreeModel(MetadataElement metadata_element)
+    {
+	// The root node of the value tree is the MetadataElement it represents
+	super(new MetadataValueTreeNode(metadata_element));
+    }
+
+
+    public MetadataValueTreeNode addMetadataValue(String metadata_value)
+    {
+	return addMetadataValueInternal((MetadataValueTreeNode) root, metadata_value);
+    }
+
+
+    private MetadataValueTreeNode addMetadataValueInternal(MetadataValueTreeNode parent_metadata_value_tree_node, String metadata_value_remaining)
+    {
+	// Split the metadata value into a hierarchy
+	int split_point = metadata_value_remaining.indexOf(MetadataValueTreeNode.METADATA_VALUE_TREE_NODE_HIERARCHY_TOKEN);
+	String metadata_value = ((split_point == -1) ? metadata_value_remaining : metadata_value_remaining.substring(0, split_point));
+	metadata_value_remaining = ((split_point == -1) ? "" : metadata_value_remaining.substring(split_point + 1));
+
+	// Add the value into the tree in the correct place (sorted)
+	MetadataValueTreeNode metadata_value_tree_node = null;
+	for (int i = 0; i < parent_metadata_value_tree_node.getChildCount(); i++) {
+	    MetadataValueTreeNode child_metadata_value_tree_node = (MetadataValueTreeNode) parent_metadata_value_tree_node.getChildAt(i);
+	    int c = metadata_value.compareTo(child_metadata_value_tree_node.getValue());
+
+	    // Insert node before existing value
+	    if (c < 0) {
+		metadata_value_tree_node = new MetadataValueTreeNode(metadata_value);
+		insertNodeInto(metadata_value_tree_node, parent_metadata_value_tree_node, i);
+		break;
+	    }
+
+	    // Node already exists (don't add again)
+	    if (c == 0) {
+		metadata_value_tree_node = child_metadata_value_tree_node;
+		break;
+	    }
+	}
+
+	// If no node has been added yet, it must go at the end of the list
+	if (metadata_value_tree_node == null) {
+	    metadata_value_tree_node = new MetadataValueTreeNode(metadata_value);
+	    insertNodeInto(metadata_value_tree_node, parent_metadata_value_tree_node, parent_metadata_value_tree_node.getChildCount());
+	}
+
+	// If there is some of the metadata value remaining, add that hierarchically
+	if (!metadata_value_remaining.equals("")) {
+	    metadata_value_tree_node = addMetadataValueInternal(metadata_value_tree_node, metadata_value_remaining);
+	}
+
+	return metadata_value_tree_node;
+    }
+
+
+    public MetadataValueTreeNode getMetadataValueTreeNode(String metadata_value)
+    {
+	return getMetadataValueTreeNodeInternal((MetadataValueTreeNode) root, metadata_value);
+    }
+
+
+    private MetadataValueTreeNode getMetadataValueTreeNodeInternal(MetadataValueTreeNode parent_metadata_value_tree_node, String metadata_value_remaining)
+    {
+	// Split the metadata value into a hierarchy
+	int split_point = metadata_value_remaining.indexOf(MetadataValueTreeNode.METADATA_VALUE_TREE_NODE_HIERARCHY_TOKEN);
+	String metadata_value = ((split_point == -1) ? metadata_value_remaining : metadata_value_remaining.substring(0, split_point));
+	metadata_value_remaining = ((split_point == -1) ? "" : metadata_value_remaining.substring(split_point + 1));
+
+	// Find the value in the tree in the correct place (sorted)
+	MetadataValueTreeNode metadata_value_tree_node = null;
+	for (int i = 0; i < parent_metadata_value_tree_node.getChildCount(); i++) {
+	    MetadataValueTreeNode child_metadata_value_tree_node = (MetadataValueTreeNode) parent_metadata_value_tree_node.getChildAt(i);
+	    int c = metadata_value.compareTo(child_metadata_value_tree_node.getValue());
+
+	    // Node doesn't exist in the tree
+	    if (c < 0) {
+		return null;
+	    }
+	 
+	    // Node exists
+	    if (c == 0) {
+		metadata_value_tree_node = child_metadata_value_tree_node;
+		break;
+	    }
+	}
+
+	// If no node has been found, it doesn't exist
+	if (metadata_value_tree_node == null) {
+	    return null;
+	}
+
+	// If there is some of the metadata value remaining, find that recursively
+	if (!metadata_value_remaining.equals("")) {
+	    metadata_value_tree_node = getMetadataValueTreeNodeInternal(metadata_value_tree_node, metadata_value_remaining);
+	}
+
+	return metadata_value_tree_node;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataValueTreeNode.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataValueTreeNode.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataValueTreeNode.java	(revision 13928)
@@ -0,0 +1,79 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2004 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.metadata;
+
+
+import javax.swing.tree.*;
+
+
+/** This class represents one Metadata value */
+public class MetadataValueTreeNode
+    extends DefaultMutableTreeNode
+{
+    static public final String METADATA_VALUE_TREE_NODE_HIERARCHY_TOKEN = "|";
+
+    private String value = null;
+
+
+    public MetadataValueTreeNode(Object object)
+    {
+	super(object);
+    }
+
+
+    public MetadataValueTreeNode(String value)
+    {
+	this.value = value;
+    }
+
+
+    public String getFullValue()
+    {
+	if (parent == null) {
+	    return "";
+	}
+
+	if (((MetadataValueTreeNode) parent).isRoot()) {
+	    return value;
+	}
+
+	return ((MetadataValueTreeNode) parent).getFullValue() + METADATA_VALUE_TREE_NODE_HIERARCHY_TOKEN + value;
+    }
+
+
+    public String getValue()
+    {
+	return value;
+    }
+
+
+    /** This is used to display the node in the value tree */
+    public String toString()
+    {
+	return value;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataXMLFile.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataXMLFile.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataXMLFile.java	(revision 13928)
@@ -0,0 +1,641 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2004 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.metadata;
+
+
+import java.io.*;
+import java.util.*;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.util.XMLTools;
+import org.w3c.dom.*;
+
+
+/** This class represents one metadata.xml file */
+public class MetadataXMLFile
+    extends File
+{
+    static final private String DESCRIPTION_ELEMENT = "Description";
+    static final private String DIRECTORY_FILENAME = ".*";
+    static final private String FILENAME_ELEMENT = "FileName";
+    static final private String FILESET_ELEMENT = "FileSet";
+    static final private String METADATA_ELEMENT = "Metadata";
+
+    // To speed things up a bit we keep the last accessed metadata.xml file in memory
+    static private File loaded_file = null;
+    static private Document loaded_file_document = null;
+    static private boolean loaded_file_changed = false;
+
+
+    public MetadataXMLFile(String metadata_xml_file_path)
+    {
+	super(metadata_xml_file_path);
+    }
+
+
+    public void addMetadata(File file, ArrayList metadata_values)
+    {
+	// If this metadata.xml file isn't the one currently loaded, load it now
+	if (loaded_file != this) {
+	    // First we must save out the currently loaded file
+	    saveLoadedFile();
+
+	    // Parse the metadata.xml file
+	    Document document = XMLTools.parseXMLFile(this);
+            if (document == null) {
+		System.err.println("Error: Could not parse metadata.xml file " + getAbsolutePath());
+		return;
+	    }
+
+	    loaded_file = this;
+	    loaded_file_document = document;
+	}
+
+	// Determine the file's path relative to the location of the metadata.xml file
+	String metadata_xml_file_directory_path = getParentFile().getAbsolutePath();
+	String file_relative_path = file.getAbsolutePath().substring(metadata_xml_file_directory_path.length());
+	if (file_relative_path.startsWith(File.separator)) {
+	    file_relative_path = file_relative_path.substring(File.separator.length());
+	}
+
+	// Form a regular expression that specifies the scope of the metadata
+	String file_path_regexp;
+	if (file_relative_path.equals("")) {
+	    // Special case for matching all files in the directory
+	    file_path_regexp = DIRECTORY_FILENAME;
+	}
+	else {
+	    // Convert the file path into a regular expression that will match it
+	    file_path_regexp = MetadataTools.getRegularExpressionThatMatchesFilePath(file_relative_path);
+	}
+
+	// Find the appropriate FileSet element for this file
+	Element appropriate_fileset_element = null;
+
+	// Read all the FileSet elements in the file
+	NodeList fileset_elements_nodelist = loaded_file_document.getElementsByTagName(FILESET_ELEMENT);
+	for (int i = 0; i < fileset_elements_nodelist.getLength(); i++) {
+	    Element current_fileset_element = (Element) fileset_elements_nodelist.item(i);
+
+	    // Check the FileName elements of the FileSet to see if we have a match
+	    NodeList filename_elements_nodelist = current_fileset_element.getElementsByTagName(FILENAME_ELEMENT);
+	    for (int j = 0; j < filename_elements_nodelist.getLength(); j++) {
+		Element current_filename_element = (Element) filename_elements_nodelist.item(j);
+		String current_filename_element_value = XMLTools.getElementTextValue(current_filename_element);
+
+		// Only exact matches can be extended with new metadata
+		if (current_filename_element_value.equals(file_path_regexp)) {
+		    appropriate_fileset_element = current_fileset_element;
+		    break;
+		}
+	    }
+	}
+
+	// If no appropriate FileSet element exists create a new one for this file
+	if (appropriate_fileset_element == null) {
+	    DebugStream.println("Creating new FileSet element for file since none exists...");
+	    appropriate_fileset_element = loaded_file_document.createElement(FILESET_ELEMENT);
+
+	    Element new_filename_element = loaded_file_document.createElement(FILENAME_ELEMENT);
+	    new_filename_element.appendChild(loaded_file_document.createTextNode(file_path_regexp));
+	    appropriate_fileset_element.appendChild(new_filename_element);
+
+	    Element new_description_element = loaded_file_document.createElement(DESCRIPTION_ELEMENT);
+	    appropriate_fileset_element.appendChild(new_description_element);
+
+	    loaded_file_document.getDocumentElement().appendChild(appropriate_fileset_element);
+	}
+
+	// Add each of the metadata values to the FileSet's Description element
+	Element description_element = (Element) appropriate_fileset_element.getElementsByTagName(DESCRIPTION_ELEMENT).item(0);
+	for (int i = 0; i < metadata_values.size(); i++) {
+	    MetadataValue metadata_value = (MetadataValue) metadata_values.get(i);
+	    String metadata_element_name_full = metadata_value.getMetadataElement().getFullName();
+
+	    // Remove any characters that are invalid in XML
+	    String metadata_value_string = XMLTools.removeInvalidCharacters(metadata_value.getFullValue());
+
+	    // Square brackets need to be escaped because they are a special character in Greenstone
+	    metadata_value_string = metadata_value_string.replaceAll("\\[", "&#091;");
+	    metadata_value_string = metadata_value_string.replaceAll("\\]", "&#093;");
+
+	    // Check if this piece of metadata has already been assigned to this FileSet element
+	    boolean metadata_already_assigned = false;
+	    NodeList metadata_elements_nodelist = description_element.getElementsByTagName(METADATA_ELEMENT);
+	    for (int k = 0; k < metadata_elements_nodelist.getLength(); k++) {
+		Element current_metadata_element = (Element) metadata_elements_nodelist.item(k);
+
+		// Check if the metadata element name matches
+		String current_metadata_element_name_full = current_metadata_element.getAttribute("name");
+		if (current_metadata_element_name_full.equals(metadata_element_name_full)) {
+		    // Check if the metadata element value matches
+		    String current_metadata_value_string = XMLTools.getElementTextValue(current_metadata_element);
+		    if (current_metadata_value_string.equals(metadata_value_string)) {
+			// Metadata already assigned
+			metadata_already_assigned = true;
+			break;
+		    }
+		}
+	    }
+
+	    // If the piece of metadata hasn't already been assigned, add it now
+	    if (!metadata_already_assigned) {
+		// Create a new Metadata element to record this metadata
+		Element new_metadata_element = loaded_file_document.createElement(METADATA_ELEMENT);
+		new_metadata_element.setAttribute("name", metadata_value.getMetadataElement().getFullName());
+		new_metadata_element.setAttribute("mode", (metadata_value.isAccumulatingMetadata() ? "accumulate" : "override"));
+		new_metadata_element.appendChild(loaded_file_document.createTextNode(metadata_value_string));
+
+		// Accumulating metadata: add at the end
+		if (metadata_value.isAccumulatingMetadata()) {
+		    description_element.appendChild(new_metadata_element);
+		}
+		// Override metadata: add at the start (so it overrides inherited metadata without affecting other assigned metadata)
+		else {
+		    description_element.insertBefore(new_metadata_element, description_element.getFirstChild());
+		}
+	    }
+	}
+
+	// Remember that we've changed the file so it gets saved when a new one is loaded
+	loaded_file_changed = true;
+    }
+
+
+    public ArrayList getMetadataAssignedToFile(File file)
+    {
+	// If this metadata.xml file isn't the one currently loaded, load it now
+	if (loaded_file != this) {
+	    // First we must save out the currently loaded file
+	    saveLoadedFile();
+
+	    // Parse the metadata.xml file
+	    Document document = XMLTools.parseXMLFile(this);
+              if (document == null) {
+		System.err.println("Error: Could not parse metadata.xml file " + getAbsolutePath());
+		return new ArrayList();
+	    }
+
+	    loaded_file = this;
+	    loaded_file_document = document;
+	}
+
+	// Determine the file's path relative to the location of the metadata.xml file
+	File metadata_xml_file_directory = getParentFile();
+	String file_relative_path = file.getAbsolutePath().substring(metadata_xml_file_directory.getAbsolutePath().length());
+	if (file_relative_path.startsWith(File.separator)) {
+	    file_relative_path = file_relative_path.substring(File.separator.length());
+	}
+
+	// Build up a list of metadata assigned to this file
+	ArrayList metadata_values = new ArrayList();
+
+	// Read all the FileSet elements in the file
+	NodeList fileset_elements_nodelist = loaded_file_document.getElementsByTagName(FILESET_ELEMENT);
+	for (int i = 0; i < fileset_elements_nodelist.getLength(); i++) {
+	    Element current_fileset_element = (Element) fileset_elements_nodelist.item(i);
+	    boolean current_fileset_matches = false;
+	    boolean is_one_file_only_metadata = true;
+	    File folder_metadata_inherited_from = null;
+
+	    // Check the FileName elements of the FileSet to see if we have a match
+	    NodeList filename_elements_nodelist = current_fileset_element.getElementsByTagName(FILENAME_ELEMENT);
+	    for (int j = 0; j < filename_elements_nodelist.getLength(); j++) {
+		Element current_filename_element = (Element) filename_elements_nodelist.item(j);
+		String current_filename_element_value = XMLTools.getElementTextValue(current_filename_element);
+
+		// Does this fileset specify metadata for one file only?
+		is_one_file_only_metadata = true;
+		if (current_filename_element_value.indexOf("*") != -1 && !current_filename_element_value.equals(DIRECTORY_FILENAME)) {
+		    // No, it specifies metadata for multiple files (but not all the files in the directory)
+		    is_one_file_only_metadata = false;
+		}
+
+		// This fileset specifies metadata for the file
+		if (file_relative_path.matches(current_filename_element_value)) {
+		    current_fileset_matches = true;
+		    if (!file_relative_path.equals("") && current_filename_element_value.equals(DIRECTORY_FILENAME)) {
+			folder_metadata_inherited_from = metadata_xml_file_directory;
+		    }
+		    break;
+		}
+
+		// This fileset specifies metadata for the folder the file is in
+		if (file_relative_path.startsWith(current_filename_element_value + File.separator)) {
+		    current_fileset_matches = true;
+		    folder_metadata_inherited_from = new File(metadata_xml_file_directory, current_filename_element_value);
+		    break;
+		}
+	    }
+
+	    // The FileSet doesn't apply, so move onto the next one
+	    if (current_fileset_matches == false) {
+		continue;
+	    }
+
+	    // Read all the Metadata elements in the fileset
+	    NodeList metadata_elements_nodelist = current_fileset_element.getElementsByTagName(METADATA_ELEMENT);
+	    for (int k = 0; k < metadata_elements_nodelist.getLength(); k++) {
+		Element current_metadata_element = (Element) metadata_elements_nodelist.item(k);
+		String metadata_element_name_full = current_metadata_element.getAttribute("name");
+		String metadata_set_namespace = MetadataTools.getMetadataSetNamespace(metadata_element_name_full);
+
+		// Ignore legacy crap
+		if (metadata_set_namespace.equals("hidden")) {
+		    continue;
+		}
+
+		MetadataSet metadata_set = MetadataSetManager.getMetadataSet(metadata_set_namespace);
+		if (metadata_set == null) {
+		    // The metadata set isn't loaded, so give the option of mapping the element into a loaded set
+		    String target_metadata_element_name_full = MetadataSetManager.mapUnloadedMetadataElement(metadata_element_name_full);
+		    if (target_metadata_element_name_full == null || target_metadata_element_name_full.equals("")) {
+			// Skip this element if we still don't have a loaded element for it
+			continue;
+		    }
+
+		    metadata_element_name_full = target_metadata_element_name_full;
+		    metadata_set_namespace = MetadataTools.getMetadataSetNamespace(metadata_element_name_full);
+		    metadata_set = MetadataSetManager.getMetadataSet(metadata_set_namespace);
+		}
+
+		MetadataElement metadata_element = MetadataTools.getMetadataElementWithName(metadata_element_name_full);
+
+                String metadata_element_name = MetadataTools.getMetadataElementName(metadata_element_name_full);
+		// If the element doesn't exist in the metadata set, we're not interested
+                //Shaoqun modified. It needs to be added to metadata_set because the user might disable skim file   
+		if (metadata_element == null) {
+		    metadata_element = metadata_set.addMetadataElementForThisSession(metadata_element_name);
+		    // continue;
+		}
+
+		// Square brackets need to be escaped because they are a special character in Greenstone
+		String metadata_value_string = XMLTools.getElementTextValue(current_metadata_element);
+		metadata_value_string = metadata_value_string.replaceAll("&#091;", "[");
+		metadata_value_string = metadata_value_string.replaceAll("&#093;", "]");
+
+		MetadataValueTreeNode metadata_value_tree_node = metadata_element.getMetadataValueTreeNode(metadata_value_string);
+
+		// If there is no metadata value tree node for this value, create it
+		if (metadata_value_tree_node == null) {
+		    DebugStream.println("Note: No value tree node for metadata value \"" + metadata_value_string + "\"");
+		    metadata_element.addMetadataValue(metadata_value_string);
+		    metadata_value_tree_node = metadata_element.getMetadataValueTreeNode(metadata_value_string);
+		}
+
+		MetadataValue metadata_value = new MetadataValue(metadata_element, metadata_value_tree_node);
+		metadata_value.inheritsMetadataFromFolder(folder_metadata_inherited_from);
+		metadata_value.setIsOneFileOnlyMetadata(is_one_file_only_metadata);
+
+		// Is this accumulating metadata?
+		if (current_metadata_element.getAttribute("mode").equals("accumulate")) {
+		    metadata_value.setIsAccumulatingMetadata(true);
+		}
+
+		// Add the new metadata value to the list
+		metadata_values.add(metadata_value);
+	    }
+	}
+
+	return metadata_values;
+    }
+
+
+    public void removeMetadata(File file, ArrayList metadata_values)
+    {
+	// If this metadata.xml file isn't the one currently loaded, load it now
+	if (loaded_file != this) {
+	    // First we must save out the currently loaded file
+	    saveLoadedFile();
+
+	    // Parse the metadata.xml file
+	    Document document = XMLTools.parseXMLFile(this);
+	    if (document == null) {
+		System.err.println("Error: Could not parse metadata.xml file " + getAbsolutePath());
+		return;
+	    }
+
+	    loaded_file = this;
+	    loaded_file_document = document;
+	}
+
+	// Determine the file's path relative to the location of the metadata.xml file
+	String metadata_xml_file_directory_path = getParentFile().getAbsolutePath();
+	String file_relative_path = file.getAbsolutePath().substring(metadata_xml_file_directory_path.length());
+	if (file_relative_path.startsWith(File.separator)) {
+	    file_relative_path = file_relative_path.substring(File.separator.length());
+	}
+
+	// Form a regular expression that specifies the scope of the metadata
+	String file_path_regexp;
+	if (file_relative_path.equals("")) {
+	    // Special case for matching all files in the directory
+	    file_path_regexp = DIRECTORY_FILENAME;
+	}
+	else {
+	    // Convert the file path into a regular expression that will match it
+	    file_path_regexp = MetadataTools.getRegularExpressionThatMatchesFilePath(file_relative_path);
+	}
+
+	// Find the appropriate FileSet element for this file
+	Element appropriate_fileset_element = null;
+
+	// Read all the FileSet elements in the file
+	NodeList fileset_elements_nodelist = loaded_file_document.getElementsByTagName(FILESET_ELEMENT);
+	for (int i = 0; i < fileset_elements_nodelist.getLength(); i++) {
+	    Element current_fileset_element = (Element) fileset_elements_nodelist.item(i);
+
+	    // Check the FileName elements of the FileSet to see if we have a match
+	    NodeList filename_elements_nodelist = current_fileset_element.getElementsByTagName(FILENAME_ELEMENT);
+	    for (int j = 0; j < filename_elements_nodelist.getLength(); j++) {
+		Element current_filename_element = (Element) filename_elements_nodelist.item(j);
+		String current_filename_element_value = XMLTools.getElementTextValue(current_filename_element);
+
+		// Only exact matches can be extended with new metadata
+		if (current_filename_element_value.equals(file_path_regexp)) {
+		    appropriate_fileset_element = current_fileset_element;
+		    break;
+		}
+	    }
+	}
+
+	// If no appropriate FileSet element exists the metadata isn't assigned in this metadata.xml file
+	if (appropriate_fileset_element == null) {
+	    DebugStream.println("Note: No appropriate FileSet element found when removing metadata from " + this);
+	    return;
+	}
+
+	// Remove each of the metadata values from the FileSet's Description element
+	for (int i = 0; i < metadata_values.size(); i++) {
+	    MetadataValue metadata_value = (MetadataValue) metadata_values.get(i);
+
+	    // Remove any characters that are invalid in XML
+	    String metadata_value_string = XMLTools.removeInvalidCharacters(metadata_value.getFullValue());
+
+	    // Square brackets need to be escaped because they are a special character in Greenstone
+	    metadata_value_string = metadata_value_string.replaceAll("\\[", "&#091;");
+	    metadata_value_string = metadata_value_string.replaceAll("\\]", "&#093;");
+
+	    // Find the Metadata element to delete from the fileset
+	    String metadata_element_name_full = metadata_value.getMetadataElement().getFullName();
+	    NodeList metadata_elements_nodelist = appropriate_fileset_element.getElementsByTagName(METADATA_ELEMENT);
+	    for (int k = 0; k < metadata_elements_nodelist.getLength(); k++) {
+		Element current_metadata_element = (Element) metadata_elements_nodelist.item(k);
+
+		// Check the metadata element name matches
+		String current_metadata_element_name_full = current_metadata_element.getAttribute("name");
+		if (current_metadata_element_name_full.equals(metadata_element_name_full)) {
+		    // Check the metadata element value matches
+		    String current_metadata_value_string = XMLTools.getElementTextValue(current_metadata_element);
+		    if (current_metadata_value_string.equals(metadata_value_string)) {
+			// Remove this Metadata element
+			current_metadata_element.getParentNode().removeChild(current_metadata_element);
+
+			// If there are no Metadata elements left now, remove the (empty) FileSet element
+			if (metadata_elements_nodelist.getLength() == 0) {
+			    appropriate_fileset_element.getParentNode().removeChild(appropriate_fileset_element);
+			}
+
+			break;
+		    }
+		}
+	    }
+	}
+
+	// Remember that we've changed the file so it gets saved when a new one is loaded
+	loaded_file_changed = true;
+    }
+
+
+    public void replaceMetadata(File file, MetadataValue old_metadata_value, MetadataValue new_metadata_value)
+    {
+	// If this metadata.xml file isn't the one currently loaded, load it now
+	if (loaded_file != this) {
+	    // First we must save out the currently loaded file
+	    saveLoadedFile();
+
+	    // Parse the metadata.xml file
+	    Document document = XMLTools.parseXMLFile(this);
+	    if (document == null) {
+		System.err.println("Error: Could not parse metadata.xml file " + getAbsolutePath());
+		return;
+	    }
+
+	    loaded_file = this;
+	    loaded_file_document = document;
+	}
+
+	// Determine the file's path relative to the location of the metadata.xml file
+	String metadata_xml_file_directory_path = getParentFile().getAbsolutePath();
+	String file_relative_path = file.getAbsolutePath().substring(metadata_xml_file_directory_path.length());
+	if (file_relative_path.startsWith(File.separator)) {
+	    file_relative_path = file_relative_path.substring(File.separator.length());
+	}
+
+	// Form a regular expression that specifies the scope of the metadata
+	String file_path_regexp;
+	if (file_relative_path.equals("")) {
+	    // Special case for matching all files in the directory
+	    file_path_regexp = DIRECTORY_FILENAME;
+	}
+	else {
+	    // Convert the file path into a regular expression that will match it
+	    file_path_regexp = MetadataTools.getRegularExpressionThatMatchesFilePath(file_relative_path);
+	}
+
+	// Remove any characters that are invalid in XML
+	String old_metadata_value_string = XMLTools.removeInvalidCharacters(old_metadata_value.getFullValue());
+	String new_metadata_value_string = XMLTools.removeInvalidCharacters(new_metadata_value.getFullValue());
+
+	// Square brackets need to be escaped because they are a special character in Greenstone
+	old_metadata_value_string = old_metadata_value_string.replaceAll("\\[", "&#091;");
+	old_metadata_value_string = old_metadata_value_string.replaceAll("\\]", "&#093;");
+	new_metadata_value_string = new_metadata_value_string.replaceAll("\\[", "&#091;");
+	new_metadata_value_string = new_metadata_value_string.replaceAll("\\]", "&#093;");
+
+	// Read all the FileSet elements in the file
+	NodeList fileset_elements_nodelist = loaded_file_document.getElementsByTagName(FILESET_ELEMENT);
+	for (int i = 0; i < fileset_elements_nodelist.getLength(); i++) {
+	    Element current_fileset_element = (Element) fileset_elements_nodelist.item(i);
+	    boolean current_fileset_matches = false;
+
+	    // Check the FileName elements of the FileSet to see if we have a match
+	    NodeList filename_elements_nodelist = current_fileset_element.getElementsByTagName(FILENAME_ELEMENT);
+	    for (int j = 0; j < filename_elements_nodelist.getLength(); j++) {
+		Element current_filename_element = (Element) filename_elements_nodelist.item(j);
+		String current_filename_element_value = XMLTools.getElementTextValue(current_filename_element);
+
+		// Only exact matches can be edited
+		if (current_filename_element_value.equals(file_path_regexp)) {
+		    current_fileset_matches = true;
+		    break;
+		}
+	    }
+
+	    // The FileSet doesn't apply, so move onto the next one
+	    if (current_fileset_matches == false) {
+		continue;
+	    }
+
+	    // Each metadata value is only allowed to be assigned once
+	    boolean new_metadata_value_already_exists = false;
+	    Element metadata_element_to_edit = null;
+
+	    // Find the Metadata element to replace in the fileset
+	    String metadata_element_name_full = old_metadata_value.getMetadataElement().getFullName();
+	    NodeList metadata_elements_nodelist = current_fileset_element.getElementsByTagName(METADATA_ELEMENT);
+	    for (int k = 0; k < metadata_elements_nodelist.getLength(); k++) {
+		Element current_metadata_element = (Element) metadata_elements_nodelist.item(k);
+
+		// Check the metadata element name matches
+		String current_metadata_element_name_full = current_metadata_element.getAttribute("name");
+		if (!current_metadata_element_name_full.equals(metadata_element_name_full)) {
+		    continue;
+		}
+
+		// Check the new metadata value doesn't already exist
+		String current_metadata_value_string = XMLTools.getElementTextValue(current_metadata_element);
+		if (current_metadata_value_string.equals(new_metadata_value_string)) {
+		    new_metadata_value_already_exists = true;
+		}
+
+		// Check the metadata element value matches
+		if (current_metadata_value_string.equals(old_metadata_value_string)) {
+		    metadata_element_to_edit = current_metadata_element;
+		}
+	    }
+
+	    // If the new metadata value already existed, remove the original value
+	    if (new_metadata_value_already_exists) {
+		metadata_element_to_edit.getParentNode().removeChild(metadata_element_to_edit);
+	    }
+	    // Otherwise replace the old value with the new value
+	    // Ensure metadata_element_to_edit isn't null (may occur when multiple files are selected)
+	    else if (metadata_element_to_edit != null) {
+		XMLTools.setElementTextValue(metadata_element_to_edit, new_metadata_value_string);
+	    }
+	}
+
+	// Remember that we've changed the file so it gets saved when a new one is loaded
+	loaded_file_changed = true;
+    }
+
+
+    static public void saveLoadedFile()
+    {
+	// If we have a file loaded into memory and it has been modified, save it now
+	if (loaded_file != null && loaded_file_changed == true) {
+	    XMLTools.writeXMLFile(loaded_file, loaded_file_document);
+	    loaded_file_changed = false;
+	}
+    }
+
+
+    /**
+     * Every metadata.xml file must be skimmed when a collection is opened, for three very important reasons:
+     *   - To handle any non-namespaced metadata in the metadata.xml files (this is mapped and the files rewritten)
+     *   - To get a complete list of the metadata elements in the collection (used in Design and Format panes)
+     *   - To build complete and accurate metadata value trees (used in the Enrich pane)
+     */
+    public void skimFile()
+    {
+	boolean file_changed = false;
+
+	// Parse the metadata.xml file
+	DebugStream.println("Skimming metadata.xml file " + this + "...");
+	       
+	Document document = XMLTools.parseXMLFile(this);
+	if (document == null) {
+	    System.err.println("Error: Could not parse metadata.xml file " + getAbsolutePath());
+	    return;
+	}
+
+	// Read all the Metadata elements in the file
+	HashMap target_metadata_element_name_attrs_cache = new HashMap();
+	NodeList metadata_elements_nodelist = document.getElementsByTagName(METADATA_ELEMENT);
+	for (int i = 0; i < metadata_elements_nodelist.getLength(); i++) {
+	    Element current_metadata_element = (Element) metadata_elements_nodelist.item(i);
+	    String metadata_element_name_full = current_metadata_element.getAttribute("name");
+	    String metadata_set_namespace = MetadataTools.getMetadataSetNamespace(metadata_element_name_full);
+
+	    // Ignore legacy crap
+	    if (metadata_set_namespace.equals("hidden")) {
+		continue;
+	    }
+
+	    MetadataSet metadata_set = MetadataSetManager.getMetadataSet(metadata_set_namespace);
+	    if (metadata_set == null) {
+		// The metadata set isn't loaded, so give the option of mapping the element into a loaded set
+		String target_metadata_element_name_full = MetadataSetManager.mapUnloadedMetadataElement(metadata_element_name_full);
+		if (target_metadata_element_name_full == null || target_metadata_element_name_full.equals("")) {
+		    // Skip this element if we still don't have a loaded element for it
+		    continue;
+		}
+
+		// Update the metadata.xml file to have the new (namespaced) element name
+		// Instead of using current_metadata_element.setAttribute("name", target_metadata_element_name_full)
+		//   we create an Attr object for each target metadata element name, and cache them
+		// This makes a *huge* difference (namespacing a metadata.xml file with 45000 metadata entries now
+		//   takes 45 seconds instead of 30 minutes!) -- why is setting the value of a Node so slow?
+		Attr target_metadata_element_name_attr = (Attr) target_metadata_element_name_attrs_cache.get(target_metadata_element_name_full);
+		if (target_metadata_element_name_attr == null) {
+		    target_metadata_element_name_attr = document.createAttribute("name");
+		    target_metadata_element_name_attr.setValue(target_metadata_element_name_full);
+		    target_metadata_element_name_attrs_cache.put(target_metadata_element_name_full, target_metadata_element_name_attr);
+		}
+
+		// Remove the old name attribute and add the new (namespaced) one
+		current_metadata_element.removeAttribute("name");
+		current_metadata_element.setAttributeNode((Attr) target_metadata_element_name_attr.cloneNode(false));
+		file_changed = true;
+
+		metadata_element_name_full = target_metadata_element_name_full;
+		metadata_set_namespace = MetadataTools.getMetadataSetNamespace(metadata_element_name_full);
+		metadata_set = MetadataSetManager.getMetadataSet(metadata_set_namespace);
+	    }
+
+	    String metadata_element_name = MetadataTools.getMetadataElementName(metadata_element_name_full);
+	    MetadataElement metadata_element = metadata_set.getMetadataElementWithName(metadata_element_name);
+
+	    // If the element doesn't exist in the metadata set, add it
+	    if (metadata_element == null) {
+		metadata_element = metadata_set.addMetadataElementForThisSession(metadata_element_name);
+	    }
+
+	    // Square brackets need to be escaped because they are a special character in Greenstone
+	    String metadata_value_string = XMLTools.getElementTextValue(current_metadata_element);
+	    metadata_value_string = metadata_value_string.replaceAll("&#091;", "[");
+	    metadata_value_string = metadata_value_string.replaceAll("&#093;", "]");
+
+	    metadata_element.addMetadataValue(metadata_value_string);
+	}
+
+	// Rewrite the metadata.xml file if it has changed
+	if (file_changed) {
+	    XMLTools.writeXMLFile(this, document);
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataXMLFileManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataXMLFileManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/MetadataXMLFileManager.java	(revision 13928)
@@ -0,0 +1,389 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2005 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.metadata;
+
+
+import java.io.*;
+import java.util.*;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.collection.CollectionTreeNode;
+import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
+import org.greenstone.gatherer.util.XMLTools;
+
+
+/** This class is a static class that manages the metadata.xml files */
+public class MetadataXMLFileManager
+{
+    static private ArrayList metadata_xml_files = new ArrayList();
+    /** The objects listening for MetadataChanged events. */
+    static private ArrayList metadata_changed_listeners = new ArrayList();
+    /** Keep track of which metadata.xml files have been modified so we can upload them to the server */
+    static private ArrayList modified_metadata_xml_files = new ArrayList();
+
+
+    static public void addMetadata(CollectionTreeNode file_node, ArrayList metadata_values)
+    {
+	addMetadata(new CollectionTreeNode[] { file_node }, metadata_values);
+    }
+
+
+    static public void addMetadata(CollectionTreeNode[] file_nodes, MetadataValue metadata_value)
+    {
+	ArrayList metadata_values = new ArrayList();
+	metadata_values.add(metadata_value);
+	addMetadata(file_nodes, metadata_values);
+    }
+
+
+    static public void addMetadata(CollectionTreeNode[] file_nodes, ArrayList metadata_values)
+    {
+	// Check the list of metadata values is non-empty
+	if (metadata_values.isEmpty()) {
+	    return;
+	}
+
+	// Add the metadata to each file node in turn
+	for (int i = 0; i < file_nodes.length; i++) {
+	    File current_file = file_nodes[i].getFile();
+	    DebugStream.println("Adding metadata to " + current_file.getAbsolutePath());
+
+	    // Find which metadata.xml file needs editing
+	    boolean applicable_metadata_xml_file_found = false;
+	    File current_file_directory = (current_file.isDirectory() ? current_file : current_file.getParentFile());
+	    String current_file_directory_path = current_file_directory.getAbsolutePath();
+	    for (int j = 0; j < metadata_xml_files.size(); j++) {
+		MetadataXMLFile metadata_xml_file = (MetadataXMLFile) metadata_xml_files.get(j);
+
+		// This metadata.xml file is only applicable if it is at the same level as the file
+		if (current_file_directory_path.equals(metadata_xml_file.getParentFile().getAbsolutePath())) {
+		    applicable_metadata_xml_file_found = true;
+		    metadata_xml_file.addMetadata(current_file, metadata_values);
+		    if (!modified_metadata_xml_files.contains(metadata_xml_file)) {
+			modified_metadata_xml_files.add(metadata_xml_file);
+		    }
+		}
+	    }
+
+	    // If no applicable metadata.xml file exists, we have to create a new one
+	    if (!applicable_metadata_xml_file_found) {
+		// Create a new (empty) metadata.xml file in the file's directory...
+		File new_metadata_xml_file_file = new File(current_file_directory, "metadata.xml");
+		XMLTools.writeXMLFile(new_metadata_xml_file_file, XMLTools.parseXMLFile("xml/metadata.xml", true));
+
+		// ...load it...
+		MetadataXMLFile new_metadata_xml_file = loadMetadataXMLFile(new_metadata_xml_file_file,true);
+
+		// ...and add the metadata
+		new_metadata_xml_file.addMetadata(current_file, metadata_values);
+		if (!modified_metadata_xml_files.contains(new_metadata_xml_file)) {
+		    modified_metadata_xml_files.add(new_metadata_xml_file);
+		}
+	    }
+	}
+
+	// Let any listeners know that the metadata has changed
+	fireMetadataChangedEvent(file_nodes);
+    }
+
+
+    static public void addMetadataChangedListener(MetadataChangedListener metadata_changed_listener)
+    {
+	metadata_changed_listeners.add(metadata_changed_listener);
+    }
+
+
+    static public void clearMetadataXMLFiles()
+    {
+	metadata_xml_files.clear();
+    }
+
+
+    static private void fireMetadataChangedEvent(CollectionTreeNode[] file_nodes)
+    {
+	// Send the event off to all the MetadataChangedListeners
+	for (int i = 0; i < metadata_changed_listeners.size(); i++) {
+	    ((MetadataChangedListener) metadata_changed_listeners.get(i)).metadataChanged(file_nodes);
+	}
+    }
+
+
+    /** Returns the metadata assigned to a file outside the collection, excluding folder-level/inherited metadata. */
+    static public ArrayList getMetadataAssignedDirectlyToExternalFile(File file)
+    {
+	DebugStream.println("Getting metadata assigned directly to external file " + file + "...");
+
+	// Build up a list of applicable metadata.xml files
+	ArrayList applicable_metadata_xml_files = new ArrayList();
+
+	File directory = (file.isDirectory() ? file : file.getParentFile());
+	while (directory != null) {
+	    File metadata_xml_file = new File(directory, "metadata.xml");
+	    if (metadata_xml_file.exists() && !metadata_xml_file.isDirectory()) {
+		// It is very important that shallower files come before deeper ones
+		applicable_metadata_xml_files.add(0, new MetadataXMLFile(metadata_xml_file.getAbsolutePath()));
+	    }
+
+	    directory = directory.getParentFile();
+	}
+
+	// Get the metadata assigned to the specified file from the applicable metadata.xml files
+	ArrayList assigned_metadata = getMetadataAssignedToFile(file, applicable_metadata_xml_files);
+
+	// Remove any folder-level metadata
+	for (int i = assigned_metadata.size() - 1; i >= 0; i--) {
+	    if (((MetadataValue) assigned_metadata.get(i)).isInheritedMetadata()) {
+		assigned_metadata.remove(i);
+	    }
+	}
+
+	return assigned_metadata;
+    }
+
+
+    /** Returns the metadata assigned to a file inside the collection, excluding folder-level/inherited metadata. */
+    static public ArrayList getMetadataAssignedDirectlyToFile(File file)
+    {
+	// Get all the metadata assigned to the specified file...
+	ArrayList assigned_metadata = getMetadataAssignedToFile(file);
+
+	// ...then remove any folder-level metadata
+	for (int i = assigned_metadata.size() - 1; i >= 0; i--) {
+	    if (((MetadataValue) assigned_metadata.get(i)).isInheritedMetadata()) {
+		assigned_metadata.remove(i);
+	    }
+	}
+
+	return assigned_metadata;
+    }
+
+
+    /** Returns all the metadata assigned to a file inside the collection. */
+    static public ArrayList getMetadataAssignedToFile(File file)
+    {
+	// Build up a list of applicable metadata.xml files
+	ArrayList applicable_metadata_xml_files = new ArrayList();
+
+	// Look at each loaded metadata.xml file to see if it is potentially applicable
+	String file_directory_path = (file.isDirectory() ? file : file.getParentFile()).getAbsolutePath() + File.separator;
+	for (int i = 0; i < metadata_xml_files.size(); i++) {
+	    MetadataXMLFile metadata_xml_file = (MetadataXMLFile) metadata_xml_files.get(i);
+
+	    // This metadata.xml file is only potentially applicable if it is above or at the same level as the file
+	    if (file_directory_path.startsWith(metadata_xml_file.getParentFile().getAbsolutePath() + File.separator)) {
+		applicable_metadata_xml_files.add(metadata_xml_file);
+	    }
+	}
+
+	// Return the metadata assigned to the specified file from the applicable metadata.xml files
+	return getMetadataAssignedToFile(file, applicable_metadata_xml_files);
+    }
+
+
+    static private ArrayList getMetadataAssignedToFile(File file, ArrayList applicable_metadata_xml_files)
+    {
+	// Build up a list of metadata values assigned to this file
+	ArrayList metadata_values_all = new ArrayList();
+
+	// Look at each applicable metadata.xml file to see if it assigns metadata to this file
+	for (int i = 0; i < applicable_metadata_xml_files.size(); i++) {
+	    MetadataXMLFile metadata_xml_file = (MetadataXMLFile) applicable_metadata_xml_files.get(i);
+	    DebugStream.println("Applicable metadata.xml file: " + metadata_xml_file);
+
+	    ArrayList metadata_values = metadata_xml_file.getMetadataAssignedToFile(file);
+	    for (int j = 0; j < metadata_values.size(); j++) {
+		MetadataValue metadata_value = (MetadataValue) metadata_values.get(j);
+
+		// Overriding metadata: remove any values with this metadata element
+		if (metadata_value.isAccumulatingMetadata() == false) {
+		    for (int k = metadata_values_all.size() - 1; k >= 0; k--) {
+			if (((MetadataValue) metadata_values_all.get(k)).getMetadataElement().equals(metadata_value.getMetadataElement())) {
+			    metadata_values_all.remove(k);
+			}
+		    }
+		}
+
+		metadata_values_all.add(metadata_value);
+	    }
+	}
+
+	return metadata_values_all;
+    }
+
+
+    static public void loadMetadataXMLFiles(File directory, boolean skimfile)
+    {
+	// Make sure the directory (import) exists
+	if (directory.exists() == false) {
+	    return;
+	}
+
+	// Look recursively at each subfile of the directory for metadata.xml files
+	File[] directory_files = directory.listFiles();
+	for (int i = 0; i < directory_files.length; i++) {
+	    File child_file = directory_files[i];
+	    if (child_file.isDirectory()) {
+		loadMetadataXMLFiles(child_file,skimfile);
+	    }
+	    else if (child_file.getName().equals("metadata.xml")) {
+		loadMetadataXMLFile(child_file,skimfile);
+	    }
+	}
+    }
+
+
+    static private MetadataXMLFile loadMetadataXMLFile(File metadata_xml_file_file, boolean skimfile)
+    {
+	MetadataXMLFile metadata_xml_file = new MetadataXMLFile(metadata_xml_file_file.getAbsolutePath());
+	if (metadata_xml_files.contains(metadata_xml_file)) {
+	    // This metadata.xml file has already been loaded, so return the loaded object
+	    return (MetadataXMLFile) metadata_xml_files.get(metadata_xml_files.indexOf(metadata_xml_file));
+	}
+	if(skimfile){
+	   metadata_xml_file.skimFile();
+	}
+	metadata_xml_files.add(metadata_xml_file);
+	return metadata_xml_file;
+    }
+
+
+    static public void removeMetadata(CollectionTreeNode file_node, ArrayList metadata_values)
+    {
+	removeMetadata(new CollectionTreeNode[] { file_node }, metadata_values);
+    }
+
+
+    static public void removeMetadata(CollectionTreeNode[] file_nodes, MetadataValue metadata_value)
+    {
+	ArrayList metadata_values = new ArrayList();
+	metadata_values.add(metadata_value);
+	removeMetadata(file_nodes, metadata_values);
+    }
+
+
+    static public void removeMetadata(CollectionTreeNode[] file_nodes, ArrayList metadata_values)
+    {
+	// Check the list of metadata values is non-empty
+	if (metadata_values.isEmpty()) {
+	    return;
+	}
+
+	// Remove the metadata from each file node in turn
+	for (int i = 0; i < file_nodes.length; i++) {
+	    File current_file = file_nodes[i].getFile();
+	    DebugStream.println("Removing metadata from " + current_file.getAbsolutePath());
+
+	    // Find which metadata.xml file needs editing
+	    File current_file_directory = (current_file.isDirectory() ? current_file : current_file.getParentFile());
+	    String current_file_directory_path = current_file_directory.getAbsolutePath();
+	    for (int j = 0; j < metadata_xml_files.size(); j++) {
+		MetadataXMLFile metadata_xml_file = (MetadataXMLFile) metadata_xml_files.get(j);
+
+		// This metadata.xml file is only potentially applicable if it is above or at the same level as the file
+		if (current_file_directory_path.startsWith(metadata_xml_file.getParentFile().getAbsolutePath())) {
+		    metadata_xml_file.removeMetadata(current_file, metadata_values);
+		    if (!modified_metadata_xml_files.contains(metadata_xml_file)) {
+			modified_metadata_xml_files.add(metadata_xml_file);
+		    }
+		}
+	    }
+	}
+
+	// Let any listeners know that the metadata has changed
+	fireMetadataChangedEvent(file_nodes);
+    }
+
+
+    static public void removeMetadataChangedListener(MetadataChangedListener metadata_changed_listener)
+    {
+	metadata_changed_listeners.remove(metadata_changed_listener);
+    }
+
+
+    static public void replaceMetadata(CollectionTreeNode[] file_nodes, MetadataValue old_metadata_value, MetadataValue new_metadata_value)
+    {
+	// Replace the metadata in each file node in turn
+	for (int i = 0; i < file_nodes.length; i++) {
+	    File current_file = file_nodes[i].getFile();
+	    DebugStream.println("Replacing metadata in " + current_file.getAbsolutePath());
+
+	    // Find which metadata.xml file needs editing
+	    File current_file_directory = (current_file.isDirectory() ? current_file : current_file.getParentFile());
+	    String current_file_directory_path = current_file_directory.getAbsolutePath();
+	    for (int j = 0; j < metadata_xml_files.size(); j++) {
+		MetadataXMLFile metadata_xml_file = (MetadataXMLFile) metadata_xml_files.get(j);
+
+		// This metadata.xml file is only applicable if it is at the same level as the file
+		if (current_file_directory_path.equals(metadata_xml_file.getParentFile().getAbsolutePath())) {
+		    metadata_xml_file.replaceMetadata(current_file, old_metadata_value, new_metadata_value);
+		    if (!modified_metadata_xml_files.contains(metadata_xml_file)) {
+			modified_metadata_xml_files.add(metadata_xml_file);
+		    }
+		}
+	    }
+	}
+
+	// Let any listeners know that the metadata has changed
+	fireMetadataChangedEvent(file_nodes);
+    }
+
+
+    /** Ensures that all the metadata is written to metadata.xml files. */
+    static public void saveMetadataXMLFiles()
+    {
+	// Save the file currently loaded into memory out to disk
+	MetadataXMLFile.saveLoadedFile();
+
+	// If the collection is stored on a remote server, upload all the modified files now
+	if (Gatherer.isGsdlRemote) {
+	    if (modified_metadata_xml_files.isEmpty()) {
+		DebugStream.println("No modified metadata.xml files to upload.");
+		return;
+	    }
+
+	    // Upload the files modified since last time, then reset the list
+	    RemoteGreenstoneServer.uploadCollectionFiles(CollectionManager.getLoadedCollectionName(), (File[]) modified_metadata_xml_files.toArray(new File[0]));
+	    modified_metadata_xml_files.clear();
+	}
+    }
+
+
+    static public void unloadMetadataXMLFile(File metadata_xml_file_file)
+    {
+	DebugStream.println("Unloading metadata.xml file " + metadata_xml_file_file);
+
+	// Find the metadata.xml file in the list of loaded files, and remove it
+	for (int i = 0; i < metadata_xml_files.size(); i++) {
+	    MetadataXMLFile metadata_xml_file = (MetadataXMLFile) metadata_xml_files.get(i);
+	    if (metadata_xml_file_file.getAbsolutePath().equals(metadata_xml_file.getAbsolutePath())) {
+		metadata_xml_files.remove(i);
+		break;
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/ProfileXMLFile.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/ProfileXMLFile.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/ProfileXMLFile.java	(revision 13928)
@@ -0,0 +1,118 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2004 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.metadata;
+
+
+import java.io.*;
+import java.util.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
+import org.greenstone.gatherer.util.XMLTools;
+import org.w3c.dom.*;
+
+
+/** This class represents one profile.xml file */
+public class ProfileXMLFile
+    extends File
+{
+    private HashMap metadata_mapping = null;
+
+
+    public ProfileXMLFile(String profile_xml_file_path)
+    {
+	super(profile_xml_file_path);
+    }
+
+
+    public String getMetadataElementFor(String metadata_element_name_full)
+    {
+	if (getMetadataMapping() == null) {
+	    return null;
+	}
+
+	return (String) metadata_mapping.get(metadata_element_name_full);
+    }
+
+
+    public HashMap getMetadataMapping()
+    {
+	// If we have already loaded the metadata mapping, use it
+	if (metadata_mapping != null) {
+	    return metadata_mapping;
+	}
+
+	// Build the metadata mapping from the profile.xml file
+	metadata_mapping = new HashMap();
+
+	// Parse the profile.xml file
+	Document document = XMLTools.parseXMLFile(this);
+	if (document == null) {
+	    System.err.println("Error: Could not parse profile.xml file " + getAbsolutePath());
+	    return null;
+	}
+
+	// Read all the Action elements in the file
+	NodeList action_elements_nodelist = document.getElementsByTagName("Action");
+	for (int i = 0; i < action_elements_nodelist.getLength(); i++) {
+	    Element current_action_element = (Element) action_elements_nodelist.item(i);
+	    String source_metadata_element_name_full = current_action_element.getAttribute("source");
+	    String target_metadata_element_name_full = current_action_element.getAttribute("target");
+	    metadata_mapping.put(source_metadata_element_name_full, target_metadata_element_name_full);
+	}
+
+	return metadata_mapping;
+    }
+
+
+    public void mapElement(String source_metadata_element_name_full, String target_metadata_element_name_full)
+    {
+	// Parse the profile.xml file
+	Document document = XMLTools.parseXMLFile(this);
+	if (document == null) {
+	    System.err.println("Error: Could not parse profile.xml file " + getAbsolutePath());
+	    return;
+	}
+
+	// Create a new Action element to record this mapping
+	Element new_action_element = document.createElement("Action");
+	new_action_element.setAttribute("source", source_metadata_element_name_full);
+	new_action_element.setAttribute("target", target_metadata_element_name_full);
+	document.getDocumentElement().appendChild(new_action_element);
+
+	// Rewrite the profile.xml file
+	XMLTools.writeXMLFile(this, document);
+
+	// This is inefficient but for simplicity we'll just upload the file every time it is changed
+	if (Gatherer.isGsdlRemote) {
+	    RemoteGreenstoneServer.uploadCollectionFile(CollectionManager.getLoadedCollectionName(), this);
+	}
+
+	// Invalidate the metadata mapping
+	metadata_mapping = null;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/ProfileXMLFileManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/ProfileXMLFileManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/metadata/ProfileXMLFileManager.java	(revision 13928)
@@ -0,0 +1,90 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2004 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.metadata;
+
+
+import java.io.*;
+import java.util.*;
+import org.greenstone.gatherer.util.XMLTools;
+
+
+/** This class is a static class that manages the profile.xml file */
+public class ProfileXMLFileManager
+{
+    static private ProfileXMLFile profile_xml_file = null;
+
+
+    static public void clearProfileXMLFile()
+    {
+	profile_xml_file = null;
+    }
+
+
+    static public void loadProfileXMLFile(File directory)
+    {
+	// Make sure the directory (metadata) exists
+	if (directory.exists() == false) {
+	    directory.mkdir();
+	}
+
+	File profile_xml_file_file = new File(directory, "profile.xml");
+	if (!profile_xml_file_file.exists()) {
+	    // Create a new (empty) profile.xml file in this directory...
+	    XMLTools.writeXMLFile(profile_xml_file_file, XMLTools.parseXMLFile("xml/profile.xml", true));
+	}
+
+	profile_xml_file = new ProfileXMLFile(profile_xml_file_file.getAbsolutePath());
+    }
+
+
+    static public String getMetadataElementFor(String metadata_element_name_full)
+    {
+	if (profile_xml_file == null) {
+	    return null;
+	}
+
+	return profile_xml_file.getMetadataElementFor(metadata_element_name_full);
+    }
+
+
+    static public HashMap getMetadataMapping()
+    {
+	if (profile_xml_file == null) {
+	    return null;
+	}
+
+	return profile_xml_file.getMetadataMapping();
+    }
+
+
+    static public void mapElement(String metadata_element_name_full, String target_metadata_element_name_full)
+    {
+	if (profile_xml_file != null) {
+	    profile_xml_file.mapElement(metadata_element_name_full, target_metadata_element_name_full);
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/remote/RemoteGreenstoneServer.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/remote/RemoteGreenstoneServer.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/remote/RemoteGreenstoneServer.java	(revision 13928)
@@ -0,0 +1,1154 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato
+ *
+ * Copyright (C) 2005 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+
+package org.greenstone.gatherer.remote;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.util.zip.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.GAuthenticator;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.shell.GShell;
+import org.greenstone.gatherer.util.UnzipTools;
+import org.greenstone.gatherer.util.Utility;
+
+
+public class RemoteGreenstoneServer
+{
+    // ----------------------------------------------------------------------------------------------------
+    //   PUBLIC LAYER
+    // ----------------------------------------------------------------------------------------------------
+
+
+    static public String deleteCollection(String collection_name)
+    {
+	return performAction(new RemoteGreenstoneServerDeleteCollectionAction(collection_name));
+    }
+
+
+    static public String deleteCollectionFile(String collection_name, File collection_file)
+    {
+	return performAction(new RemoteGreenstoneServerDeleteCollectionFileAction(collection_name, collection_file));
+    }
+
+
+    static public String downloadCollection(String collection_name)
+    {
+	return performAction(new RemoteGreenstoneServerDownloadCollectionAction(collection_name));
+    }
+
+
+    static public String downloadCollectionArchives(String collection_name)
+    {
+	return performAction(new RemoteGreenstoneServerDownloadCollectionArchivesAction(collection_name));
+    }
+
+
+    static public String downloadCollectionConfigurations()
+    {
+	return performAction(new RemoteGreenstoneServerDownloadCollectionConfigurationsAction());
+    }
+
+
+    static public String downloadCollectionFile(String collection_name, File collection_file)
+    {
+	return performAction(new RemoteGreenstoneServerDownloadCollectionFileAction(collection_name, collection_file));
+    }
+
+
+    static public String getScriptOptions(String script_name, String script_arguments)
+    {
+	return performAction(new RemoteGreenstoneServerGetScriptOptionsAction(script_name, script_arguments));
+    }
+
+
+    static public String moveCollectionFile(String collection_name, File source_collection_file, File target_collection_file)
+    {
+	return performAction(new RemoteGreenstoneServerMoveCollectionFileAction(collection_name, source_collection_file, target_collection_file));
+    }
+
+
+    static public String newCollectionDirectory(String collection_name, File new_collection_directory)
+    {
+	return performAction(new RemoteGreenstoneServerNewCollectionDirectoryAction(collection_name, new_collection_directory));
+    }
+
+
+    static public String runScript(String collection_name, String script_name, String script_arguments, GShell shell)
+    {
+	return performAction(new RemoteGreenstoneServerRunScriptAction(collection_name, script_name, script_arguments, shell));
+    }
+
+
+    static public String uploadCollectionFile(String collection_name, File collection_file)
+    {
+	return performAction(new RemoteGreenstoneServerUploadCollectionFilesAction(collection_name, new File[] { collection_file }));
+    }
+
+
+    static public String uploadCollectionFiles(String collection_name, File[] collection_files)
+    {
+	return performAction(new RemoteGreenstoneServerUploadCollectionFilesAction(collection_name, collection_files));
+    }
+
+
+    static public String uploadFilesIntoCollection(String collection_name, File[] source_files, File target_collection_directory)
+    {
+	return performAction(new RemoteGreenstoneServerUploadFilesIntoCollectionAction(collection_name, source_files, target_collection_directory));
+    }
+
+
+    // ----------------------------------------------------------------------------------------------------
+
+
+    static public void exit()
+    {
+	System.err.println("Exiting, number of jobs on queue: " + remote_greenstone_server_action_queue.size());
+
+	// If there are still jobs on the queue we must wait for the jobs to finish
+	while (remote_greenstone_server_action_queue.size() > 0) {
+	    synchronized (remote_greenstone_server_action_queue) {
+		try {
+		    DebugStream.println("Waiting for queue to become empty...");
+		    remote_greenstone_server_action_queue.wait(500);
+		}
+		catch (InterruptedException exception) {}
+	    }
+	}
+    }
+
+
+    // ----------------------------------------------------------------------------------------------------
+    //   QUEUE LAYER
+    // ----------------------------------------------------------------------------------------------------
+
+
+    /** Returns null if we cannot wait for the action to finish, "" if the action failed, or the action output. */
+    static private String performAction(RemoteGreenstoneServerAction remote_greenstone_server_action)
+    {
+	// Add the action to the queue
+	remote_greenstone_server_action_queue.addAction(remote_greenstone_server_action);
+
+	// If we're running in the GUI thread we must return immediately
+	// We cannot wait for the action to complete because this will block any GUI updates
+	if (SwingUtilities.isEventDispatchThread()) {
+	    System.err.println("WARNING: In event dispatch thread, returning immediately...");
+	    return null;
+	}
+
+	// Otherwise wait until the action is processed
+	while (!remote_greenstone_server_action.processed) {
+	    synchronized (remote_greenstone_server_action) {
+		try {
+		    DebugStream.println("Waiting for action to complete...");
+		    remote_greenstone_server_action.wait(500);
+		}
+		catch (InterruptedException exception) {}
+	    }
+	}
+
+	// Return "" if the action failed
+	if (!remote_greenstone_server_action.processed_successfully) {
+	    return "";
+	}
+	// Otherwise return the action output
+	return remote_greenstone_server_action.action_output;
+    }
+
+
+    static private RemoteGreenstoneServerActionQueue remote_greenstone_server_action_queue = new RemoteGreenstoneServerActionQueue();
+
+
+    static private class RemoteGreenstoneServerActionQueue
+	extends Thread
+    {
+	/** The queue of waiting jobs. */
+	private ArrayList queue = null;
+
+
+	public RemoteGreenstoneServerActionQueue()
+	{
+	    if (Gatherer.isGsdlRemote) {
+		queue = new ArrayList();
+		start();
+	    }
+	}
+
+
+	synchronized public void addAction(RemoteGreenstoneServerAction remote_greenstone_server_action)
+	{
+	    queue.add(remote_greenstone_server_action);
+	    notifyAll();
+	}
+
+
+	public int size()
+	{
+	    return queue.size();
+	}
+
+
+	public void run()
+	{
+	    while (true) {
+		// If there are jobs on the queue, get the next in line and process it
+		if (queue.size() > 0) {
+		    RemoteGreenstoneServerAction remote_greenstone_server_action = (RemoteGreenstoneServerAction) queue.get(0);
+
+		    try {
+			remote_greenstone_server_action.perform();
+
+			// No exceptions were thrown, so the action was successful
+			remote_greenstone_server_action.processed_successfully = true;
+		    }
+		    catch (RemoteGreenstoneServerActionCancelledException exception) {
+			remote_greenstone_server_action.processed_successfully = false;
+		    }
+		    catch (Exception exception) {
+			DebugStream.printStackTrace(exception);
+			JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Error", exception.getMessage()), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.ERROR_MESSAGE);
+			remote_greenstone_server_action.processed_successfully = false;
+		    }
+
+		    // We're done with this action, for better or worse
+		    remote_greenstone_server_action.processed = true;
+		    queue.remove(0);
+		}
+
+		// Otherwise the queue is empty
+		else {
+		    progress_bar.setAction(null);
+
+		    // Wait until we are notify()ed by addAction that there is a new job on the queue
+		    synchronized (this) {
+			try {
+			    wait();
+			}
+			catch (InterruptedException exception) { }
+		    }
+		}
+	    }
+	}
+    }
+
+
+    // ----------------------------------------------------------------------------------------------------
+    //   PROGRESS BAR
+    // ----------------------------------------------------------------------------------------------------
+
+
+    static private RemoteGreenstoneServerProgressBar progress_bar = new RemoteGreenstoneServerProgressBar();
+
+
+    static private class RemoteGreenstoneServerProgressBar
+	extends JProgressBar
+    {
+	public RemoteGreenstoneServerProgressBar()
+	{
+	    setBackground(Configuration.getColor("coloring.collection_tree_background", false));
+	    setForeground(Configuration.getColor("coloring.collection_tree_foreground", false));
+	    setString(Dictionary.get("FileActions.No_Activity"));
+	    setStringPainted(true);
+	}
+
+
+	public void setAction(String action)
+	{
+	    if (action != null) {
+		DebugStream.println(action);
+	    }
+
+	    // We cannot call this from the GUI thread otherwise the progress bar won't start
+	    if (SwingUtilities.isEventDispatchThread()) {
+		System.err.println("ERROR: RemoteGreenstoneServerProgressBar.setAction() called from event dispatch thread!");
+		return;
+	    }
+
+	    // Set the string on the progress bar, and start or stop it
+	    if (action == null) {
+		setString(Dictionary.get("FileActions.No_Activity"));
+		setIndeterminate(false);
+	    }
+	    else {
+		setString(action);
+		setIndeterminate(true);
+	    }
+	}
+    }
+
+
+    static public RemoteGreenstoneServerProgressBar getProgressBar()
+    {
+	return progress_bar;
+    }
+
+
+    // ----------------------------------------------------------------------------------------------------
+    //   ACTIONS
+    // ----------------------------------------------------------------------------------------------------
+
+
+    static private abstract class RemoteGreenstoneServerAction
+    {
+	public String action_output = null;
+	public boolean processed = false;
+	public boolean processed_successfully;
+
+	abstract public void perform()
+	    throws Exception;
+    }
+
+
+    static private class RemoteGreenstoneServerActionCancelledException
+	extends Exception
+    {
+    }
+
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    DELETE COLLECTION
+     * --------------------------------------------------------------------------------------------
+     */
+    static private class RemoteGreenstoneServerDeleteCollectionAction
+	extends RemoteGreenstoneServerAction
+    {
+	private String collection_name;
+
+	public RemoteGreenstoneServerDeleteCollectionAction(String collection_name)
+	{
+	    this.collection_name = collection_name;
+	}
+
+	public void perform()
+	    throws Exception
+	{
+	    progress_bar.setAction("Deleting collection " + collection_name + "...");
+
+	    String delete_collection_command = "cmd=delete-collection";
+	    delete_collection_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
+	    action_output = sendCommandToServer(delete_collection_command, null);
+	}
+    }
+
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    DELETE COLLECTION FILE
+     * --------------------------------------------------------------------------------------------
+     */
+    static private class RemoteGreenstoneServerDeleteCollectionFileAction
+	extends RemoteGreenstoneServerAction
+    {
+	private String collection_name;
+	private File collection_file;
+
+	public RemoteGreenstoneServerDeleteCollectionFileAction(String collection_name, File collection_file)
+	{
+	    this.collection_name = collection_name;
+	    this.collection_file = collection_file;
+	}
+
+	public void perform()
+	    throws Exception
+	{
+	    String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name);
+	    String collection_file_relative_path = getPathRelativeToDirectory(collection_file, collection_directory_path);
+	    collection_file_relative_path = collection_file_relative_path.replaceAll((Utility.isWindows() ? "\\\\" : "\\/"), "|");
+	    progress_bar.setAction("Deleting collection file " + collection_file_relative_path + "...");
+
+	    String delete_collection_file_command = "cmd=delete-collection-file";
+	    delete_collection_file_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
+	    delete_collection_file_command += "&file=" + URLEncoder.encode(collection_file_relative_path, "UTF-8");
+	    action_output = sendCommandToServer(delete_collection_file_command, null);
+	}
+    }
+
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    DOWNLOAD COLLECTION
+     * --------------------------------------------------------------------------------------------
+     */
+    static private class RemoteGreenstoneServerDownloadCollectionAction
+	extends RemoteGreenstoneServerAction
+    {
+	private String collection_name;
+
+	public RemoteGreenstoneServerDownloadCollectionAction(String collection_name)
+	{
+	    this.collection_name = collection_name;
+	}
+
+	public void perform()
+	    throws Exception
+	{
+	    progress_bar.setAction("Downloading remote collection " + collection_name + "...");
+
+	    String download_collection_command = "cmd=download-collection";
+	    download_collection_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
+	    String zip_file_path = Gatherer.getCollectDirectoryPath() + collection_name + ".zip";
+	    action_output = downloadFile(download_collection_command, zip_file_path);
+
+	    // Delete the existing (local) collection directory
+	    Utility.delete(new File(CollectionManager.getCollectionDirectoryPath(collection_name)));
+
+	    // Unzip the collection just downloaded
+	    UnzipTools.unzipFile(zip_file_path, Gatherer.getCollectDirectoryPath());
+	}
+    }
+
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    DOWNLOAD COLLECTION ARCHIVES
+     * --------------------------------------------------------------------------------------------
+     */
+    static private class RemoteGreenstoneServerDownloadCollectionArchivesAction
+	extends RemoteGreenstoneServerAction
+    {
+	private String collection_name;
+
+	public RemoteGreenstoneServerDownloadCollectionArchivesAction(String collection_name)
+	{
+	    this.collection_name = collection_name;
+	}
+
+	public void perform()
+	    throws Exception
+	{
+	    progress_bar.setAction("Downloading collection archives for " + collection_name + "...");
+
+	    String download_collection_archives_command = "cmd=download-collection-archives";
+	    download_collection_archives_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
+	    String zip_file_path = Gatherer.getCollectDirectoryPath() + collection_name + "-archives.zip";
+	    action_output = downloadFile(download_collection_archives_command, zip_file_path);
+
+	    // Delete the existing (local) collection archives
+	    Utility.delete(new File(CollectionManager.getLoadedCollectionArchivesDirectoryPath()));
+
+	    // Unzip the collection archives just downloaded
+	    UnzipTools.unzipFile(zip_file_path, Gatherer.getCollectDirectoryPath());
+	}
+    }
+
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    DOWNLOAD COLLECTION CONFIGURATIONS
+     * --------------------------------------------------------------------------------------------
+     */
+    static private class RemoteGreenstoneServerDownloadCollectionConfigurationsAction
+	extends RemoteGreenstoneServerAction
+    {
+	public RemoteGreenstoneServerDownloadCollectionConfigurationsAction()
+	{
+	}
+
+	public void perform()
+	    throws Exception
+	{
+	    progress_bar.setAction("Downloading collection configurations...");
+
+	    // Delete the existing (local) collect directory
+	    Utility.delete(new File(Gatherer.getCollectDirectoryPath()));
+	    new File(Gatherer.getCollectDirectoryPath()).mkdirs();
+
+	    String download_collection_configurations_command = "cmd=download-collection-configurations";
+	    String zip_file_path = Gatherer.getCollectDirectoryPath() + "collections.zip";
+	    action_output = downloadFile(download_collection_configurations_command, zip_file_path);
+
+	    // Unzip the collection configurations just downloaded
+	    UnzipTools.unzipFile(zip_file_path, Gatherer.getCollectDirectoryPath());
+	}
+    }
+
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    DOWNLOAD COLLECTION FILE
+     * --------------------------------------------------------------------------------------------
+     */
+    static private class RemoteGreenstoneServerDownloadCollectionFileAction
+	extends RemoteGreenstoneServerAction
+    {
+	private String collection_name;
+	private File collection_file;
+
+	public RemoteGreenstoneServerDownloadCollectionFileAction(String collection_name, File collection_file)
+	{
+	    this.collection_name = collection_name;
+	    this.collection_file = collection_file;
+	}
+
+	public void perform()
+	    throws Exception
+	{
+	    String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name);
+	    String collection_file_relative_path = getPathRelativeToDirectory(collection_file, collection_directory_path);
+	    collection_file_relative_path = collection_file_relative_path.replaceAll((Utility.isWindows() ? "\\\\" : "\\/"), "|");
+	    progress_bar.setAction("Downloading collection file " + collection_file_relative_path + "...");
+
+	    String download_collection_file_command = "cmd=download-collection-file";
+	    download_collection_file_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
+	    download_collection_file_command += "&file=" + URLEncoder.encode(collection_file_relative_path, "UTF-8");
+	    String zip_file_name = collection_name + "-" + collection_file.getName() + ".zip";
+	    String zip_file_path = collection_directory_path + zip_file_name;
+	    action_output = downloadFile(download_collection_file_command, zip_file_path);
+
+	    // Unzip the collection file just downloaded
+	    UnzipTools.unzipFile(zip_file_path, collection_directory_path);
+	}
+    }
+
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    GET SCRIPT OPTIONS
+     * --------------------------------------------------------------------------------------------
+     */
+    static private class RemoteGreenstoneServerGetScriptOptionsAction
+	extends RemoteGreenstoneServerAction
+    {
+	private String script_name;
+	private String script_arguments;
+
+	public RemoteGreenstoneServerGetScriptOptionsAction(String script_name, String script_arguments)
+	{
+	    this.script_name = script_name;
+	    this.script_arguments = script_arguments;
+	}
+
+	public void perform()
+	    throws Exception
+	{
+	    progress_bar.setAction("Getting options for " + script_name + "...");
+
+	    String get_script_options_command = "cmd=get-script-options";
+	    get_script_options_command += "&script=" + script_name;
+	    get_script_options_command += "&xml=";
+	    get_script_options_command += "&language=" + Configuration.getLanguage();
+	    get_script_options_command += script_arguments;
+	    action_output = sendCommandToServer(get_script_options_command, null);
+	}
+    }
+
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    MOVE COLLECTION FILE
+     * --------------------------------------------------------------------------------------------
+     */
+    static private class RemoteGreenstoneServerMoveCollectionFileAction
+	extends RemoteGreenstoneServerAction
+    {
+	private String collection_name;
+	private File source_collection_file;
+	private File target_collection_file;
+
+	public RemoteGreenstoneServerMoveCollectionFileAction(String collection_name, File source_collection_file, File target_collection_file)
+	{
+	    this.collection_name = collection_name;
+	    this.source_collection_file = source_collection_file;
+	    this.target_collection_file = target_collection_file;
+	}
+
+	public void perform()
+	    throws Exception
+	{
+	    String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name);
+	    String source_collection_file_relative_path = getPathRelativeToDirectory(source_collection_file, collection_directory_path);
+	    source_collection_file_relative_path = source_collection_file_relative_path.replaceAll((Utility.isWindows() ? "\\\\" : "\\/"), "|");
+	    String target_collection_file_relative_path = getPathRelativeToDirectory(target_collection_file, collection_directory_path);
+	    target_collection_file_relative_path = target_collection_file_relative_path.replaceAll((Utility.isWindows() ? "\\\\" : "\\/"), "|");
+	    progress_bar.setAction("Moving file " + source_collection_file_relative_path + " -> " + target_collection_file_relative_path + "...");
+
+	    String move_collection_file_command = "cmd=move-collection-file";
+	    move_collection_file_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
+	    move_collection_file_command += "&source=" + URLEncoder.encode(source_collection_file_relative_path, "UTF-8");
+	    move_collection_file_command += "&target=" + URLEncoder.encode(target_collection_file_relative_path, "UTF-8");
+	    action_output = sendCommandToServer(move_collection_file_command, null);
+	}
+    }
+
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    NEW COLLECTION DIRECTORY
+     * --------------------------------------------------------------------------------------------
+     */
+    static private class RemoteGreenstoneServerNewCollectionDirectoryAction
+	extends RemoteGreenstoneServerAction
+    {
+	private String collection_name;
+	private File new_collection_directory;
+
+	public RemoteGreenstoneServerNewCollectionDirectoryAction(String collection_name, File new_collection_directory)
+	{
+	    this.collection_name = collection_name;
+	    this.new_collection_directory = new_collection_directory;
+	}
+
+	public void perform()
+	    throws Exception
+	{
+	    String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name);
+	    String new_collection_directory_relative_path = getPathRelativeToDirectory(new_collection_directory, collection_directory_path);
+	    new_collection_directory_relative_path = new_collection_directory_relative_path.replaceAll((Utility.isWindows() ? "\\\\" : "\\/"), "|");
+	    progress_bar.setAction("Creating new directory " + new_collection_directory_relative_path + "...");
+
+	    String new_collection_directory_command = "cmd=new-collection-directory";
+	    new_collection_directory_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
+	    new_collection_directory_command += "&directory=" + URLEncoder.encode(new_collection_directory_relative_path, "UTF-8");
+	    action_output = sendCommandToServer(new_collection_directory_command, null);
+	}
+    }
+
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    RUN SCRIPT
+     * --------------------------------------------------------------------------------------------
+     */
+    static private class RemoteGreenstoneServerRunScriptAction
+	extends RemoteGreenstoneServerAction
+    {
+	private String collection_name;
+	private String script_name;
+	private String script_arguments;
+	private GShell shell;
+
+	public RemoteGreenstoneServerRunScriptAction(String collection_name, String script_name, String script_arguments, GShell shell)
+	{
+	    this.collection_name = collection_name;
+	    this.script_name = script_name;
+	    this.script_arguments = script_arguments;
+	    this.shell = shell;
+	}
+
+	public void perform()
+	    throws Exception
+	{
+	    progress_bar.setAction("Running " + script_name + "...");
+
+	    String run_script_command = "cmd=run-script";
+	    run_script_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
+	    run_script_command += "&script=" + script_name;
+	    run_script_command += "&language=" + Configuration.getLanguage();
+	    run_script_command += script_arguments;
+	    action_output = sendCommandToServer(run_script_command, shell);
+	}
+    }
+
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    UPLOAD COLLECTION FILE
+     * --------------------------------------------------------------------------------------------
+     */
+    static private class RemoteGreenstoneServerUploadCollectionFilesAction
+	extends RemoteGreenstoneServerAction
+    {
+	private String collection_name;
+	private File[] collection_files;
+
+
+	public RemoteGreenstoneServerUploadCollectionFilesAction(String collection_name, File[] collection_files)
+	{
+	    this.collection_name = collection_name;
+	    this.collection_files = collection_files;
+	}
+
+
+	public void perform()
+	    throws Exception
+	{
+	    progress_bar.setAction("Uploading collection files...");
+
+	    // Determine the file paths relative to the collection directory
+	    String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name);
+	    String[] collection_file_relative_paths = new String[collection_files.length];
+	    for (int i = 0; i < collection_files.length; i++) {
+		collection_file_relative_paths[i] = getPathRelativeToDirectory(collection_files[i], collection_directory_path);
+	    }
+
+	    // Zip up the files to send to the server
+	    String zip_file_name = collection_name + "-" + System.currentTimeMillis() + ".zip";
+	    String zip_file_path = collection_directory_path + zip_file_name;
+	    ZipTools.zipFiles(zip_file_path, collection_directory_path, collection_file_relative_paths);
+
+	    // Upload the zip file
+	    String upload_collection_file_command = "cmd=upload-collection-file";
+	    upload_collection_file_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
+	    upload_collection_file_command += "&file=" + URLEncoder.encode(zip_file_name, "UTF-8");
+	    upload_collection_file_command += "&directory=";
+	    upload_collection_file_command += "&zip=true";
+	    action_output = uploadFile(upload_collection_file_command, zip_file_path);
+	}
+    }
+
+
+    /**
+     * --------------------------------------------------------------------------------------------
+     *    UPLOAD FILES INTO COLLECTION
+     * --------------------------------------------------------------------------------------------
+     */
+    static private class RemoteGreenstoneServerUploadFilesIntoCollectionAction
+	extends RemoteGreenstoneServerAction
+    {
+	private String collection_name;
+	private File[] source_files;
+	private File target_collection_directory;
+
+
+	public RemoteGreenstoneServerUploadFilesIntoCollectionAction(String collection_name, File[] source_files, File target_collection_directory)
+	{
+	    this.collection_name = collection_name;
+	    this.source_files = source_files;
+	    this.target_collection_directory = target_collection_directory;
+	}
+
+
+	public void perform()
+	    throws Exception
+	{
+	    String collection_directory_path = CollectionManager.getCollectionDirectoryPath(collection_name);
+	    String target_collection_directory_relative_path = getPathRelativeToDirectory(target_collection_directory, collection_directory_path);
+	    target_collection_directory_relative_path = target_collection_directory_relative_path.replaceAll((Utility.isWindows() ? "\\\\" : "\\/"), "|");
+	    progress_bar.setAction("Uploading files into collection...");
+
+	    String zip_file_name = collection_name + "-" + System.currentTimeMillis() + ".zip";
+	    String zip_file_path = Gatherer.getCollectDirectoryPath() + zip_file_name;
+	    DebugStream.println("Zip file path: " + zip_file_path);
+
+	    String base_directory_path = source_files[0].getParentFile().getAbsolutePath();
+	    DebugStream.println("Base directory path: " + base_directory_path);
+	    String[] source_file_relative_paths = new String[source_files.length];
+	    for (int i = 0; i < source_files.length; i++) {
+		DebugStream.println("Source file path: " + source_files[i]);
+		source_file_relative_paths[i] = getPathRelativeToDirectory(source_files[i], base_directory_path);
+	    }
+
+	    ZipTools.zipFiles(zip_file_path, base_directory_path, source_file_relative_paths);
+
+	    String upload_collection_file_command = "cmd=upload-collection-file";
+	    upload_collection_file_command += "&c=" + URLEncoder.encode(collection_name, "UTF-8");
+	    upload_collection_file_command += "&file=" + URLEncoder.encode(zip_file_name, "UTF-8");
+	    upload_collection_file_command += "&directory=" + URLEncoder.encode(target_collection_directory_relative_path, "UTF-8");
+	    upload_collection_file_command += "&zip=true";
+	    action_output = uploadFile(upload_collection_file_command, zip_file_path);
+	}
+    }
+
+
+    // ----------------------------------------------------------------------------------------------------
+    //   AUTHENTICATION LAYER
+    // ----------------------------------------------------------------------------------------------------
+
+
+    static private PasswordAuthentication remote_greenstone_server_authentication = null;
+    // static private PasswordAuthentication remote_greenstone_server_authentication = new PasswordAuthentication(System.getProperty("user.name"), new char[] { });
+
+
+    static private class RemoteGreenstoneServerAuthenticateTask
+	extends Thread
+    {
+	public void run()
+	{
+	    remote_greenstone_server_authentication = new RemoteGreenstoneServerAuthenticator().getAuthentication();
+	}
+
+
+	static private class RemoteGreenstoneServerAuthenticator
+	    extends GAuthenticator
+	{
+	    public PasswordAuthentication getAuthentication()
+	    {
+		return getPasswordAuthentication();
+	    }
+
+	    protected String getMessageString()
+	    {
+		return Dictionary.get("RemoteGreenstoneServer.Authentication_Message");
+	    }
+ 	}
+    }
+
+
+    static private void authenticateUser()
+	throws RemoteGreenstoneServerActionCancelledException
+    {
+	// If we don't have any authentication information then ask for it now
+	if (remote_greenstone_server_authentication == null) {
+	    try {
+		// We have to do this on the GUI thread
+		SwingUtilities.invokeAndWait(new RemoteGreenstoneServerAuthenticateTask());
+	    }
+	    catch (Exception exception) {
+		DebugStream.printStackTrace(exception);
+	    }
+
+	    // If it is still null then the user has cancelled the authentication, so the action is cancelled
+	    if (remote_greenstone_server_authentication == null) {
+		throw new RemoteGreenstoneServerActionCancelledException();
+	    }
+	}
+    }
+
+
+    static public String getUsername()
+    {
+	if (remote_greenstone_server_authentication != null) {
+	    return remote_greenstone_server_authentication.getUserName();
+	}
+
+	return null;
+    }
+
+
+    // ----------------------------------------------------------------------------------------------------
+    //   REQUEST LAYER
+    // ----------------------------------------------------------------------------------------------------
+
+
+    /** Returns the command output if the action completed, throws some kind of exception otherwise. */
+    static private String downloadFile(String gliserver_args, String file_path)
+	throws Exception
+    {
+	while (true) {
+	    // Check that Configuration.gliserver_url is set
+	    if (Configuration.gliserver_url == null) {
+		throw new Exception("Empty gliserver URL: please set this in Preferences before continuing.");
+	    }
+
+	    // Ask for authentication information (if necessary), then perform the action
+	    authenticateUser();
+	    String gliserver_url_string = Configuration.gliserver_url.toString();
+	    String command_output = downloadFileInternal(gliserver_url_string, gliserver_args, file_path);
+
+	    // Check the first line to see if authentication has failed; if so, go around the loop again
+	    if (command_output.startsWith("ERROR: Authentication failed:")) {
+		JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Error", command_output.substring("ERROR: ".length())), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.ERROR_MESSAGE);
+		remote_greenstone_server_authentication = null;
+		continue;
+	    }
+	    // Check if the collection is locked by someone else; if so, see if the user wants to steal the lock
+	    else if (command_output.startsWith("ERROR: Collection is locked by: ")) {
+		if (JOptionPane.showConfirmDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Steal_Lock_Message", command_output.substring("ERROR: Collection is locked by: ".length())), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.YES_NO_OPTION) == JOptionPane.NO_OPTION) {
+		    // The user has decided to cancel the action
+		    throw new RemoteGreenstoneServerActionCancelledException();
+		}
+
+		// The user has decided to steal the lock... rerun the command with "&steal_lock="
+		gliserver_args += "&steal_lock=";
+		continue;
+	    }
+	    // Handle other types of errors by throwing an exception
+	    else if (command_output.startsWith("ERROR: ")) {
+		throw new Exception(command_output.substring("ERROR: ".length()));
+	    }
+
+	    // There were no exceptions thrown so the action must have succeeded
+	    return command_output;
+	}
+    }
+
+
+    /** Returns the command output if the action completed, throws some kind of exception otherwise. */
+    static private String sendCommandToServer(String gliserver_args, GShell shell)
+	throws Exception
+    {
+	while (true) {
+	    // Check that Configuration.gliserver_url is set
+	    if (Configuration.gliserver_url == null) {
+		throw new Exception("Empty gliserver URL: please set this in Preferences before continuing.");
+	    }
+
+	    // Ask for authentication information (if necessary), then perform the action
+	    authenticateUser();
+	    String gliserver_url_string = Configuration.gliserver_url.toString();
+	    String command_output = sendCommandToServerInternal(gliserver_url_string, gliserver_args, shell);
+	    // System.err.println("Command output: " + command_output);
+
+	    // Check the first line to see if authentication has failed; if so, go around the loop again
+	    if (command_output.startsWith("ERROR: Authentication failed:")) {
+		JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Error", command_output.substring("ERROR: ".length())), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.ERROR_MESSAGE);
+		remote_greenstone_server_authentication = null;
+		continue;
+	    }
+	    // Check if the collection is locked by someone else; if so, see if the user wants to steal the lock
+	    else if (command_output.startsWith("ERROR: Collection is locked by: ")) {
+		if (JOptionPane.showConfirmDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Steal_Lock_Message", command_output.substring("ERROR: Collection is locked by: ".length())), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.YES_NO_OPTION) == JOptionPane.NO_OPTION) {
+		    // The user has decided to cancel the action
+		    throw new RemoteGreenstoneServerActionCancelledException();
+		}
+
+		// The user has decided to steal the lock... rerun the command with "&steal_lock="
+		gliserver_args += "&steal_lock=";
+		continue;
+	    }
+	    // Handle other types of errors by throwing an exception
+	    else if (command_output.startsWith("ERROR: ")) {
+		throw new Exception(command_output.substring("ERROR: ".length()));
+	    }
+
+	    // There were no exceptions thrown so the action must have succeeded
+	    return command_output;
+	}
+    }
+
+
+    /** Returns the command output if the action completed, throws some kind of exception otherwise. */
+    static private String uploadFile(String gliserver_args, String file_path)
+	throws Exception
+    {
+	while (true) {
+	    // Check that Configuration.gliserver_url is set
+	    if (Configuration.gliserver_url == null) {
+		throw new Exception("Empty gliserver URL: please set this in Preferences before continuing.");
+	    }
+
+	    // Ask for authentication information (if necessary), then perform the action
+	    authenticateUser();
+	    String gliserver_url_string = Configuration.gliserver_url.toString();
+	    String command_output = uploadFileInternal(gliserver_url_string, gliserver_args, file_path);
+	    // System.err.println("Command output: " + command_output);
+
+	    // Check the first line to see if authentication has failed; if so, go around the loop again
+	    if (command_output.startsWith("ERROR: Authentication failed:")) {
+		JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Error", command_output.substring("ERROR: ".length())), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.ERROR_MESSAGE);
+		remote_greenstone_server_authentication = null;
+		continue;
+	    }
+	    // Check if the collection is locked by someone else; if so, see if the user wants to steal the lock
+	    else if (command_output.startsWith("ERROR: Collection is locked by: ")) {
+		if (JOptionPane.showConfirmDialog(Gatherer.g_man, Dictionary.get("RemoteGreenstoneServer.Steal_Lock_Message", command_output.substring("ERROR: Collection is locked by: ".length())), Dictionary.get("RemoteGreenstoneServer.Error_Title"), JOptionPane.YES_NO_OPTION) == JOptionPane.NO_OPTION) {
+		    // The user has decided to cancel the action
+		    throw new RemoteGreenstoneServerActionCancelledException();
+		}
+
+		// The user has decided to steal the lock... rerun the command with "&steal_lock="
+		gliserver_args += "&steal_lock=";
+		continue;
+	    }
+	    // Handle other types of errors by throwing an exception
+	    else if (command_output.startsWith("ERROR: ")) {
+		throw new Exception(command_output.substring("ERROR: ".length()));
+	    }
+
+	    // There were no exceptions thrown so the action must have succeeded
+	    return command_output;
+	}
+    }
+
+
+    // ----------------------------------------------------------------------------------------------------
+    //   NETWORK LAYER
+    // ----------------------------------------------------------------------------------------------------
+
+
+    /** Returns the command output if the action completed, throws some kind of exception otherwise. */
+    static private String downloadFileInternal(String download_cgi, String cgi_args, String file_path)
+	throws Exception
+    {
+	DebugStream.println("gliserver URL: " + download_cgi);
+	System.err.println("gliserver args: " + cgi_args);
+
+	// Add username and password, and a timestamp
+	cgi_args += "&un=" + remote_greenstone_server_authentication.getUserName();
+	cgi_args += "&pw=" + new String(remote_greenstone_server_authentication.getPassword());
+	cgi_args += "&ts=" + System.currentTimeMillis();
+
+	URL download_url = new URL(download_cgi);
+	URLConnection dl_connection = download_url.openConnection();
+	dl_connection.setDoOutput(true);
+	OutputStream dl_os = dl_connection.getOutputStream();
+
+	PrintWriter dl_out = new PrintWriter(dl_os);
+	dl_out.println(cgi_args);
+	dl_out.close();
+
+	// Download result from running cgi script
+	InputStream dl_is = dl_connection.getInputStream();
+	BufferedInputStream dl_bis = new BufferedInputStream(dl_is);
+	DataInputStream dl_dbis = new DataInputStream(dl_bis);
+
+	String first_line = "";
+	byte[] buf = new byte[1024];
+	int len = dl_dbis.read(buf);
+	if (len >= 0) {
+	    String first_chunk = new String(buf, 0, len);
+	    first_line = first_chunk.substring(0, ((first_chunk.indexOf("\n") != -1) ? first_chunk.indexOf("\n") : len));
+
+	    // Save the data to file
+	    FileOutputStream zip_fos = new FileOutputStream(file_path);
+	    BufferedOutputStream zip_bfos = new BufferedOutputStream(zip_fos);
+
+	    while (len >= 0) {
+		zip_bfos.write(buf, 0, len);
+		len = dl_dbis.read(buf);
+	    }
+
+	    zip_bfos.close();
+	    zip_fos.close();
+	}
+
+	dl_dbis.close();
+	dl_bis.close();
+	dl_is.close();
+	return first_line;
+    }
+
+
+    /** Returns the command output if the action completed, throws some kind of exception otherwise. */
+    static private String sendCommandToServerInternal(String gliserver_url_string, String cgi_args, GShell shell)
+	throws Exception
+    {
+	DebugStream.println("gliserver URL: " + gliserver_url_string);
+	System.err.println("gliserver args: " + cgi_args);
+
+	// Add username and password, and a timestamp
+	cgi_args += "&un=" + remote_greenstone_server_authentication.getUserName();
+        cgi_args += "&pw=" + new String(remote_greenstone_server_authentication.getPassword());
+	cgi_args += "&ts=" + System.currentTimeMillis();
+
+	URL gliserver_url = new URL(gliserver_url_string + "?" + cgi_args);
+	URLConnection gliserver_connection = gliserver_url.openConnection();
+
+	// Read the output of the command from the server, and return it
+	StringBuffer command_output_buffer = new StringBuffer(2048);
+	InputStream gliserver_is = gliserver_connection.getInputStream();
+	BufferedReader gliserver_in = new BufferedReader(new InputStreamReader(gliserver_is, "UTF-8"));
+	String gliserver_output_line = gliserver_in.readLine();
+	while (gliserver_output_line != null) {
+	    if (shell != null) {
+		shell.fireMessage(gliserver_output_line);
+		if (shell.hasSignalledStop()) {
+		    throw new RemoteGreenstoneServerActionCancelledException();
+		}
+	    }
+	    command_output_buffer.append(gliserver_output_line + "\n");
+	    gliserver_output_line = gliserver_in.readLine();
+	}
+	gliserver_in.close();
+
+	return command_output_buffer.toString();
+    }
+
+
+    /** Returns the command output if the action completed, throws some kind of exception otherwise. */
+    static private String uploadFileInternal(String upload_cgi, String cgi_args, String file_path)
+	throws Exception
+    {
+	DebugStream.println("gliserver URL: " + upload_cgi);
+	System.err.println("gliserver args: " + cgi_args);
+
+	// Add username and password, and a timestamp
+	cgi_args += "&un=" + remote_greenstone_server_authentication.getUserName();
+	cgi_args += "&pw=" + new String(remote_greenstone_server_authentication.getPassword());
+	cgi_args += "&ts=" + System.currentTimeMillis();
+
+	// Open a HTTP connection to the URL
+	URL url = new URL(upload_cgi);
+	HttpURLConnection gliserver_connection = (HttpURLConnection) url.openConnection();
+
+	gliserver_connection.setDoInput(true);         // Allow Inputs
+	gliserver_connection.setDoOutput(true);        // Allow Outputs
+	gliserver_connection.setUseCaches(false);      // Don't use a cached copy.
+
+	gliserver_connection.setRequestProperty("Connection", "Keep-Alive");	    
+
+	DataOutputStream dos = new DataOutputStream(gliserver_connection.getOutputStream());
+	dos.writeBytes(cgi_args + "\n");
+
+	// Send zip file to server
+	File file = new File(file_path);
+	FileInputStream fileInputStream = new FileInputStream(file);
+
+	// create a buffer of maximum size
+	final int maxBufferSize = 1024;
+	int bytesAvailable = fileInputStream.available();
+	int bufferSize = Math.min(bytesAvailable, maxBufferSize);
+	byte[] buffer = new byte[bufferSize];
+
+	// read file and write it into form...
+	// !! This uses a lot of memory when the file being uploaded is big -- Java seems to need to keep
+	//   the entire file in the DataOutputStream? (Use Runtime.getRuntime().totalMemory() to see)
+	int bytesRead = fileInputStream.read(buffer, 0, bufferSize);
+	while (bytesRead > 0) {
+	    dos.write(buffer, 0, bufferSize);
+	    bytesAvailable = fileInputStream.available();
+	    bufferSize = Math.min(bytesAvailable, maxBufferSize);
+	    bytesRead = fileInputStream.read(buffer, 0, bufferSize);
+	}
+
+	// close streams
+	fileInputStream.close();
+	dos.flush();
+	dos.close();
+
+	// Read the output of the command from the server, and return it
+	String command_output = "";
+	InputStream gliserver_is = gliserver_connection.getInputStream();
+	BufferedReader gliserver_in = new BufferedReader(new InputStreamReader(gliserver_is, "UTF-8"));
+	String gliserver_output_line = gliserver_in.readLine();
+	while (gliserver_output_line != null) {
+	    command_output += gliserver_output_line + "\n";
+	    gliserver_output_line = gliserver_in.readLine();
+	}
+	gliserver_in.close();
+
+	return command_output;
+    }
+
+
+    // ----------------------------------------------------------------------------------------------------
+    //   UTILITIES
+    // ----------------------------------------------------------------------------------------------------
+
+
+    static public String getPathRelativeToDirectory(File file, String directory_path)
+    {
+	String file_path = file.getAbsolutePath();
+	if (!file_path.startsWith(directory_path)) {
+	    System.err.println("ERROR: File path " + file_path + " is not a child of " + directory_path);
+	    return file_path;
+	}
+
+	String relative_file_path = file_path.substring(directory_path.length());
+	if (relative_file_path.startsWith(File.separator)) {
+	    relative_file_path = relative_file_path.substring(File.separator.length());
+	}
+	return relative_file_path;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/remote/Unzip.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/remote/Unzip.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/remote/Unzip.java	(revision 13928)
@@ -0,0 +1,119 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: David Bainbridge, NZDL Project, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 2005 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+
+package org.greenstone.gatherer.remote;
+
+import java.io.*;
+import java.util.*;
+import java.util.zip.*;
+
+
+public class Unzip 
+{
+
+    public static final void copyInputStream(InputStream in, OutputStream out)
+	throws IOException
+    {
+	byte[] buffer = new byte[1024];
+	int len;
+
+	while((len = in.read(buffer)) >= 0)
+	    out.write(buffer, 0, len);
+
+	in.close();
+	out.close();
+    }
+
+
+    static public void main(String[] args) 
+    {
+	if (args.length != 2) {
+	    System.err.println("Usage: Unzip <zip-file> <destination-directory>");
+	    return;
+	}
+
+	String zip_file_path = args[0];
+	// System.err.println("Zip file path: " + zip_file_path);
+	String destination_directory_path = args[1];
+	if (!destination_directory_path.endsWith(File.separator)) {
+	    destination_directory_path += File.separator;
+	}
+	// System.err.println("Destination directory path: " + destination_directory_path);
+
+	try {
+	    ZipFile zipFile = new ZipFile(zip_file_path);
+
+	    Enumeration entries = zipFile.entries();
+	    while (entries.hasMoreElements()) {
+		ZipEntry entry = (ZipEntry) entries.nextElement();
+
+		if (entry.isDirectory()) {
+		    // Assume directories are stored parents first then children.
+		    // System.err.println("Extracting directory: " + entry.getName());
+		    // This is not robust, just for demonstration purposes.
+		    String dir_name = entry.getName();
+		    String full_dir_name = destination_directory_path + dir_name;
+		    // System.err.println("Full directory name: " + full_dir_name);
+		    File dirFile = new File(full_dir_name);
+		    dirFile.mkdir();
+		}
+		else {
+		    // System.err.println("Extracting file: " + entry.getName());
+		    String file_name = entry.getName();
+		    String full_file_name = destination_directory_path + file_name;
+		    File directory = (new File(full_file_name)).getParentFile();
+		    // System.err.println("Full file name: " + full_file_name);
+		    if (!directory.exists() && !directory.mkdirs()) {
+			System.err.println("Error: Could not create directory " + directory + "!");
+		    }
+
+		    FileOutputStream fos = new FileOutputStream(full_file_name);
+		    BufferedOutputStream bos = new BufferedOutputStream(fos);
+
+		    copyInputStream(zipFile.getInputStream(entry),bos);
+		}
+	    }
+
+	    zipFile.close();
+	}
+	catch (Exception exception) {
+	    System.out.println("ERROR: " + exception);
+	    exception.printStackTrace();
+	    System.exit(1);
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/remote/ZipCollectionArchives.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/remote/ZipCollectionArchives.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/remote/ZipCollectionArchives.java	(revision 13928)
@@ -0,0 +1,117 @@
+package org.greenstone.gatherer.remote;
+
+import java.io.*;
+import java.util.zip.*;
+
+
+/**
+ */
+public class ZipCollectionArchives
+{
+    static public void main(String[] args)
+    {
+	if (args.length != 3) {
+	    System.err.println("Usage: ZipCollectionArchives <zip-file> <collect-directory-path> <collection-name>");
+	    return;
+	}
+
+	String zip_file_path = args[0];
+	String collect_directory_path = args[1];
+	String collection_name = args[2];
+
+	if (!collect_directory_path.endsWith(File.separator)) {
+	    collect_directory_path += File.separator;
+	}
+
+ 	try {
+	    ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip_file_path));
+
+	    // Add archives directory, with doc.xml files only
+	    String archives_relative_path = collection_name + File.separator + "archives";
+	    ZipTools.ZipFilter collection_archives_zip_filter = new CollectionArchivesZipFilter();
+	    ZipTools.addFileToZip(zos, collect_directory_path, archives_relative_path, collection_archives_zip_filter);
+
+	    zos.close();
+	}
+	catch (Exception exception) {
+	    exception.printStackTrace();
+	}
+    }
+
+
+    static public class CollectionArchivesZipFilter
+	extends ZipTools.NullZipFilter
+    {
+	private byte[] bytes_remaining = new byte[0];
+	private int section_depth = 0;
+	private boolean in_section_content = false;
+
+
+	public boolean shouldIncludeFile(String relative_file_path)
+	{
+	    // Only doc.xml files are strictly required, but we include archives.inf as well to prevent
+	    //   errors when zipping up the archives of a collection where no files were imported
+	    //   (in this case the zip file would contain nothing at all)
+	    return (relative_file_path.equals("archives.inf") || relative_file_path.endsWith(File.separator + "archives.inf") || relative_file_path.equals("doc.xml") || relative_file_path.endsWith(File.separator + "doc.xml"));
+	}
+
+
+	public boolean shouldIncludeFileContent(String relative_file_path)
+	{
+	    // Only content for doc.xml files is included
+	    return (relative_file_path.equals("doc.xml") || relative_file_path.endsWith(File.separator + "doc.xml"));
+	}
+
+
+	public void filterFileContent(String relative_file_path, BufferedInputStream bis, ZipOutputStream zos)
+	{
+	    // Reset the status in case there were errors in previous doc.xml files
+	    section_depth = 0;
+	    in_section_content = false;
+
+	    // Filter out the <Content>...</Content> of the doc.xml files
+	    try {
+		BufferedReader reader = new BufferedReader(new InputStreamReader(bis, "UTF-8"));
+		String line = null;
+		while ((line = reader.readLine()) != null) {
+		    // If this line isn't filtered, write it out to zos
+		    if (!filterFileLine(line)) {
+			line += "\n";
+			byte[] bytes = line.getBytes("UTF-8");
+			zos.write(bytes, 0, bytes.length);
+		    }
+		}
+	    }
+	    catch (Exception exception) {
+		exception.printStackTrace();
+	    }
+	}
+
+
+	private boolean filterFileLine(String line)
+	{
+	    boolean filter_line = false;
+
+	    if (line.indexOf("<Section>") != -1) {
+		section_depth++;
+	    }
+	    if (line.indexOf("<Content>") != -1) {
+		in_section_content = true;
+	    }
+
+	    // If we're in a subsection or in a content element, filter this line
+	    if (section_depth > 1 || in_section_content) {
+		filter_line = true;
+	    }
+
+	    if (line.indexOf("</Content>") != -1) {
+		in_section_content = false;
+	    }
+	    if (line.indexOf("</Section>") != -1) {
+		section_depth--;
+	    }
+
+	    return filter_line;
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/remote/ZipCollectionConfigurations.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/remote/ZipCollectionConfigurations.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/remote/ZipCollectionConfigurations.java	(revision 13928)
@@ -0,0 +1,100 @@
+package org.greenstone.gatherer.remote;
+
+import java.io.*;
+import java.util.zip.*;
+
+
+/**
+ */
+public class ZipCollectionConfigurations
+{
+    static public void main(String[] args)
+    {
+	if (args.length != 4) {
+	    System.err.println("Usage: ZipCollectionConfigurations <zip-file> <collect-directory-path> <user-name> <user-groups>");
+	    return;
+	}
+
+	String zip_file_path = args[0];
+	String collect_directory_path = args[1];
+	String user_name = args[2];
+	String user_groups = args[3];
+
+	if (!collect_directory_path.endsWith(File.separator)) {
+	    collect_directory_path += File.separator;
+	}
+	File collect_directory = new File(collect_directory_path);
+
+ 	try {
+	    ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip_file_path));
+	    ZipTools.ZipFilter collection_etc_zip_filter = new CollectionEtcZipFilter();
+	    ZipTools.ZipFilter collection_metadata_zip_filter = new CollectionMetadataZipFilter();
+
+	    // Add the etc and metadata directories from each of the collections the user has access to
+	    File[] collection_directories = collect_directory.listFiles();
+	    for (int i = 0; i < collection_directories.length; i++) {
+		if (collection_directories[i].isDirectory()) {
+		    String collection_name = collection_directories[i].getName();
+		    if (checkAccess(collection_name, user_name, user_groups)) {
+			String etc_relative_path = collection_directories[i].getName() + File.separator + "etc";
+			ZipTools.addFileToZip(zos, collect_directory_path, etc_relative_path, collection_etc_zip_filter);
+
+			// The "metadata" directory may not exist (non-GLI collections)
+			String metadata_relative_path = collection_directories[i].getName() + File.separator + "metadata";
+			File metadata_directory = new File(collect_directory_path + File.separator + metadata_relative_path);
+			if (metadata_directory.exists()) {
+			    ZipTools.addFileToZip(zos, collect_directory_path, metadata_relative_path, collection_metadata_zip_filter);
+			}
+		    }
+		}
+	    }
+
+	    zos.putNextEntry(new ZipEntry(".gli"));
+	    zos.close();
+	}
+	catch (Exception exception) {
+	    exception.printStackTrace();
+	}
+    }
+
+
+    static private boolean checkAccess(String collection_name, String user_name, String user_groups)
+    {
+	String[] user_groups_array = user_groups.split(",");
+	for (int i = 0; i < user_groups_array.length; i++) {
+	    if (user_groups_array[i].equals("all-collections-editor")) {
+		return true;
+	    }
+	    if (user_groups_array[i].equals("personal-collections-editor") && collection_name.startsWith(user_name + "-")) {
+		return true;
+	    }
+	    if (user_groups_array[i].equals(collection_name + "-collection-editor")) {
+		return true;
+	    }
+	}
+
+	return false;
+    }
+
+
+    static private class CollectionEtcZipFilter
+	extends ZipTools.NullZipFilter
+    {
+	public boolean shouldIncludeFile(String relative_file_path)
+	{
+	    // Only collect.cfg files are included
+	    return (relative_file_path.equals("collect.cfg") || relative_file_path.endsWith(File.separator + "collect.cfg"));
+	}
+    }
+
+
+    static private class CollectionMetadataZipFilter
+	extends ZipTools.NullZipFilter
+    {
+	public boolean shouldIncludeFileContent(String relative_file_path)
+	{
+	    // We don't include content for any of the metadata set files
+	    return false;
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/remote/ZipCollectionShell.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/remote/ZipCollectionShell.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/remote/ZipCollectionShell.java	(revision 13928)
@@ -0,0 +1,77 @@
+package org.greenstone.gatherer.remote;
+
+import java.io.*;
+import java.util.zip.*;
+
+
+/**
+ */
+public class ZipCollectionShell
+{
+    static public void main(String[] args)
+    {
+	if (args.length != 3) {
+	    System.err.println("Usage: ZipCollectionShell <zip-file> <collect-directory-path> <collection-name>");
+	    return;
+	}
+
+	String zip_file_path = args[0];
+	String collect_directory_path = args[1];
+	String collection_name = args[2];
+
+	if (!collect_directory_path.endsWith(File.separator)) {
+	    collect_directory_path += File.separator;
+	}
+
+ 	try {
+	    ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip_file_path));
+	    ZipTools.ZipFilter null_zip_filter = new ZipTools.NullZipFilter();
+
+	    // Add archives directory, with doc.xml files only
+	    String archives_relative_path = collection_name + File.separator + "archives";
+	    ZipTools.ZipFilter collection_archives_zip_filter = new ZipCollectionArchives.CollectionArchivesZipFilter();
+	    ZipTools.addFileToZip(zos, collect_directory_path, archives_relative_path, collection_archives_zip_filter);
+
+	    // Add etc/collect.cfg file
+	    String collect_cfg_relative_path = collection_name + File.separator + "etc" + File.separator + "collect.cfg";
+	    ZipTools.addFileToZip(zos, collect_directory_path, collect_cfg_relative_path, null_zip_filter);
+
+	    // Add images directory
+	    String images_relative_path = collection_name + File.separator + "images";
+	    ZipTools.addFileToZip(zos, collect_directory_path, images_relative_path, null_zip_filter);
+
+	    // Add import directory, with zero-length files except for metadata.xml
+	    String import_relative_path = collection_name + File.separator + "import";
+	    ZipTools.ZipFilter collection_import_zip_filter = new CollectionImportZipFilter();
+	    ZipTools.addFileToZip(zos, collect_directory_path, import_relative_path, collection_import_zip_filter);
+
+	    // Add index/build.cfg file
+	    String build_cfg_relative_path = collection_name + File.separator + "index" + File.separator + "build.cfg";
+	    ZipTools.addFileToZip(zos, collect_directory_path, build_cfg_relative_path, null_zip_filter);
+
+	    // Add macros/extra.dm file
+	    String extra_dm_relative_path = collection_name + File.separator + "macros" + File.separator + "extra.dm";
+	    ZipTools.addFileToZip(zos, collect_directory_path, extra_dm_relative_path, null_zip_filter);
+
+	    // Add metadata directory
+	    String metadata_relative_path = collection_name + File.separator + "metadata";
+	    ZipTools.addFileToZip(zos, collect_directory_path, metadata_relative_path, null_zip_filter);
+
+	    zos.close();
+	}
+	catch (Exception exception) {
+	    exception.printStackTrace();
+	}
+    }
+
+
+    static private class CollectionImportZipFilter
+	extends ZipTools.NullZipFilter
+    {
+	public boolean shouldIncludeFileContent(String relative_file_path)
+	{
+	    // We only include file content for metadata.xml files
+	    return (relative_file_path.equals("metadata.xml") || relative_file_path.endsWith(File.separator + "metadata.xml"));
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/remote/ZipFiles.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/remote/ZipFiles.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/remote/ZipFiles.java	(revision 13928)
@@ -0,0 +1,28 @@
+package org.greenstone.gatherer.remote;
+
+import java.io.File;
+import java.util.ArrayList;
+
+
+/**
+ */
+public class ZipFiles
+{
+    static public void main(String[] args)
+    {
+	if (args.length < 3) {
+	    System.err.println("Usage: ZipFiles <zip-file> <base-directory-path> (<files> ...)");
+	    return;
+	}
+
+	String zip_file_path = args[0];
+	String base_directory_path = args[1];
+	ArrayList relative_file_paths_list = new ArrayList();
+	for (int i = 2; i < args.length; i++) {
+	    relative_file_paths_list.add(args[i]);
+	}
+
+	String[] relative_file_paths = (String[]) relative_file_paths_list.toArray(new String[0]);
+	ZipTools.zipFiles(zip_file_path, base_directory_path, relative_file_paths);
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/remote/ZipTools.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/remote/ZipTools.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/remote/ZipTools.java	(revision 13928)
@@ -0,0 +1,144 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: David Bainbridge, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2005 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.remote;
+
+
+import java.io.*;
+import java.util.zip.*;
+
+
+public class ZipTools
+{
+    static public void zipFiles(String zip_file_path, String base_directory_path, String[] relative_file_paths)
+    {
+	try {
+	    ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip_file_path));
+	    ZipFilter null_zip_filter = new NullZipFilter();
+
+	    // Add each file/directory in turn to the zip file
+	    for (int i = 0; i < relative_file_paths.length; i++) {
+		String relative_file_path = relative_file_paths[i];
+		addFileToZip(zos, base_directory_path, relative_file_path, null_zip_filter);
+	    }
+
+	    zos.close();
+	}
+	catch (Exception exception) {
+	    exception.printStackTrace();
+	}
+    }
+
+
+    static public void addFileToZip(ZipOutputStream zos, String base_directory_path, String relative_file_path, ZipFilter zip_filter)
+    {
+	File file = new File(base_directory_path + File.separator + relative_file_path);
+
+	// Check that the file/directory exists
+	if (!file.exists()) {
+	    System.err.println("File " + file + " does not exist!");
+	    return;
+	}
+
+	try {
+	    // Directory case
+	    if (file.isDirectory()) {
+		// Add a zip entry for this directory
+		// Actually, don't -- this messes things up completely on Windows and doesn't seem to matter on Linux
+		// zos.putNextEntry(new ZipEntry(relative_file_path + File.separator));
+
+		// Apply recursively to each of the children of the directory
+		File[] child_files = file.listFiles();
+		for (int i = 0; i < child_files.length; i++) {
+		    addFileToZip(zos, base_directory_path, relative_file_path + File.separator + child_files[i].getName(), zip_filter);
+		}
+	    }
+
+	    // File case
+	    else {
+		// Add a zip entry for this file
+		if (zip_filter.shouldIncludeFile(relative_file_path)) {
+		    // Always use Unix style paths in zip files, even on Windows
+		    zos.putNextEntry(new ZipEntry(relative_file_path.replace('\\', '/')));
+
+		    if (zip_filter.shouldIncludeFileContent(relative_file_path)) {
+			BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
+			zip_filter.filterFileContent(relative_file_path, bis, zos);
+			bis.close();
+		    }
+		}
+	    }
+	}
+	catch (Exception exception) {
+	    exception.printStackTrace();
+	}
+    }
+
+
+    public interface ZipFilter
+    {
+	public boolean shouldIncludeFile(String relative_file_path);
+
+	public boolean shouldIncludeFileContent(String relative_file_path);
+
+	public void filterFileContent(String relative_file_path, BufferedInputStream bis, ZipOutputStream zos);
+    }
+
+
+    static public class NullZipFilter
+	implements ZipFilter
+    {
+	public boolean shouldIncludeFile(String relative_file_path)
+	{
+	    // All files are included
+	    return true;
+	}
+
+
+	public boolean shouldIncludeFileContent(String relative_file_path)
+	{
+	    // Content for all files is included
+	    return true;
+	}
+
+
+	public void filterFileContent(String relative_file_path, BufferedInputStream bis, ZipOutputStream zos)
+	{
+	    // No filtering: just read the file and write it directly out to zip
+	    try {
+		byte[] data = new byte[1024];
+		int bytes_read;
+		while ((bytes_read = bis.read(data, 0, 1024)) > -1) {
+		    zos.write(data, 0, bytes_read);
+		}
+	    }
+	    catch (Exception exception) {
+		// We can't use DebugStream here
+		exception.printStackTrace();
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/shell/GBuildProgressMonitor.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/shell/GBuildProgressMonitor.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/shell/GBuildProgressMonitor.java	(revision 13928)
@@ -0,0 +1,598 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.shell;
+
+import java.awt.Component;
+import java.util.ArrayList;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.CollectionDesignManager;
+import org.greenstone.gatherer.gui.GProgressBar;
+import org.greenstone.gatherer.util.StaticStrings;
+/** This implementation of <i>GShellProgressMonitor</i> is designed to parse and translate the progress of a buildcol.pl call.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class GBuildProgressMonitor
+    implements GShellProgressMonitor {
+    /** The minimum value = 0 */
+    static final private int MIN = 0;
+    /** In order to get a smoothish progress bar, set the maximum to a large number = 1000000 */
+    static final private int MAX = 1000000;
+    /** The various states the build progress state machine can be in, starting at the base state. */
+    static final int BASE                          = -1;
+    static final int BUILD                         =  0;
+    static final int COMPRESSTEXT                  = 10;
+    static final int COMPRESSTEXT_COLLECTTEXTSTATS = 11;
+    static final int COMPRESSTEXT_CREATINGCOMPRESS = 12;
+    static final int COMPRESSTEXT_COMPRESSINGTEXT  = 13;
+    static final int INDEX                         = 20;
+    static final int INDEX_CREATINGINDEXDIC        = 21;
+    static final int INDEX_INVERTINGTEXT           = 22;
+    static final int INDEX_CREATETHEWEIGHTS        = 23;
+    static final int INDEX_CREATESTEMMEDDIC        = 24;
+    static final int INDEX_CREATINGSTEMINDX        = 25;
+    static final int CREATEINFODATA                = 30;
+    static final int PHIND                         = 40;
+    static final int PHIND_EXTRACTINGVOCAB         = 41;
+    static final int PHIND_EXTRACTINGPHRASE        = 42;
+    static final int PHIND_SORTANDRENUMBER         = 43;
+    static final int PHIND_PHRASEDATABASES         = 44;
+    static final int PHIND_WORDLEVELINDEXES        = 45;
+    static final int PHIND_DOCINFODATABASES        = 46;
+    static final int CREATINGAUXILARY              = 50;
+    /** Now the language independant sentinel strings. */
+    static final String BADARGUMENT_ELEMENT    = "BadArgument";
+    static final String BADARGUMENTVALUE_ELEMENT = "BadArgumentValue";
+    static final String BADCLASSIFIER_ELEMENT = "BadClassifier";
+    static final String BADPLUGIN_ELEMENT = "BadPlugin";
+    static final String BUILD_ELEMENT          = "Build";
+    static final String COLLECTTEXTSTATS_VALUE = "CollectTextStats";
+    static final String COMPRESSINGTEXT_VALUE  = "CompressingText";
+    static final String COMPRESSTEXT_VALUE     = "CompressText";
+    static final String CREATINGAUXILARY_VALUE = "CreatingAuxilary";
+    static final String CREATINGCOMPRESS_VALUE = "CreatingCompress";
+    static final String CREATINGINDEXDIC_VALUE = "CreatingIndexDic";
+    static final String CREATINGSTEMINDX_VALUE = "CreatingStemIndx";
+    static final String CREATEINFODATA_VALUE   = "CreateInfoData";
+    static final String CREATESTEMMEDDIC_VALUE = "CreateStemmedDic";
+    static final String CREATETHEWEIGHTS_VALUE = "CreateTheWeights";
+    static final String DOCINFODATABASES_VALUE = "DocInfoDatabases";
+    static final String EXTRACTINGPHRASE_VALUE = "ExtractingPhrase";
+    static final String EXTRACTINGVOCAB_VALUE  = "ExtractingVocab";
+    static final String FATALERROR_ELEMENT     = "FatalError";
+    static final String INDEX_VALUE            = "Index";
+    static final String INVERTINGTEXT_VALUE    = "InvertingText";
+    static final String NAME_ATTRIBUTE         = "name";
+    static final String PHASE_ELEMENT          = "Phase";
+    static final String PHIND_VALUE            = "Phind";
+    static final String PHRASEDATABASES_VALUE  = "PhraseDatabases";
+    static final String SKIPCREATINGCOMP_VALUE = "SkipCreatingComp";
+    static final String SORTANDRENUMBER_VALUE  = "SortAndRenumber";
+    static final String SOURCE_ATTRIBUTE       = "source";
+    static final String STAGE_ELEMENT          = "Stage";
+    static final String WARNING_ELEMENT        = "Warning";   
+    static final String WORDLEVELINDEXES_VALUE = "WordLevelIndexes";
+
+    static final private String ARGUMENT_ATTRIBUTE = "a";
+    static final private String CLASSIFIER_ATTRIBUTE = "c";
+    static final private String PLUGIN_ATTRIBUTE = "p";
+
+    /** Indicates if the GUI has asked the process this object monitors to stop. */
+    private boolean stop = false;
+    /** The current number of stages we have completed. */
+    private int current_stages = 0;
+    /** The number of stages we are expecting to complete. */
+    private int expected_stages = 0;
+
+    private int threshold = Configuration.SYSTEMS_MODE;
+    /** The current state we are in. The state will change depending on the next flag recieved. */
+    private int state = BASE;
+    /** The progress bar this monitor updates. */
+    private GProgressBar progress_bar;
+    /** A progress bar that is shared between this this listener and the Import monitor. */
+    private GProgressBar shared_progress_bar;
+
+    /** Construct a new GBuildProgressMonitor. */
+    public GBuildProgressMonitor(GProgressBar shared_progress_bar) {
+	this.shared_progress_bar = shared_progress_bar;
+	progress_bar = new GProgressBar();
+	progress_bar.setMaximum(MAX);
+	progress_bar.setMinimum(MIN);
+	progress_bar.setString(null);
+	progress_bar.setStringPainted(true);
+	setValue(MIN);
+    }
+
+    /** Method to register a new progress bar with this monitor.
+     * @param progress_bar The new <strong>GProgressBar</strong>.
+     */	 
+    public void addProgressBar(GProgressBar progress_bar) {
+	this.progress_bar = progress_bar;
+	progress_bar.setMaximum(MAX);
+	progress_bar.setMinimum(MIN);
+	progress_bar.setStringPainted(false);
+	progress_bar.setString(null);
+	setValue(MIN);
+    }
+
+    /** Determine the script exit value according to the progress monitor. This gets around a problem where several script failures actually result with a successful exit value.
+     * @return A <i>int</i> with a value of zero if and only if the script was successful.
+     */
+    public int exitValue() {
+	if(state == BASE) {
+	    return 0;
+	}
+	return 1;
+    }
+    /** Method to retrieve whatever control is being used as the progress indicator. Usually a <strong>GProgressBar</strong> but there may be others implemented later.
+     * @return A <strong>Component</strong> on which the progress of the process is being displayed.
+     */
+    public Component getProgress() {
+	return progress_bar;
+    }
+
+    public GProgressBar getSharedProgress() {
+	return shared_progress_bar;
+    }
+
+    public void messageOnProgressBar(String message)
+    {
+	if (message!=null && !message.equals("")) {
+	    progress_bar.setString(message);
+	    shared_progress_bar.setString(message);
+	}
+	else {
+	    progress_bar.setString(null);
+	    shared_progress_bar.setString(null);
+	}
+    }
+
+    /** Method to determine the state of the stop flag, which may be set by the visual component that created this monitor.
+     * @return A <strong>boolean</strong> indicating if the process has been asked to stop.
+     */
+    public synchronized boolean hasSignalledStop() {
+	return stop;
+    }
+    /** Inform the progress bar that it should programatically increment progress by one step. */
+    public void increment() {
+	// There is no reason this should be called for a build.
+    }
+
+    /** This method is used to 'feed in' a line of text captured from the process.
+     * @param queue a queue which at the moment should contain a single GShellEvent
+     */
+    public void process(ArrayList queue) {
+	GShellEvent event = (GShellEvent) queue.get(0);
+	// Remove 'build.pl> ' bit
+	String line = event.getMessage();
+	line = line.substring(line.indexOf(StaticStrings.GREATER_THAN_CHARACTER) + 1);
+	line = line.trim();
+	// We are only really interested in processing pseudo-XML tags
+	if(line.startsWith(StaticStrings.LESS_THAN_CHARACTER) && line.endsWith(StaticStrings.GREATER_THAN_CHARACTER)) {
+	    // All events are vetoed
+	    event.veto();
+	    
+	    // Create a new element from it
+	    GShellElement element = new GShellElement(line);
+	    // Now change states within the state machine as appropriate. A state change may subsequently incur a progress update.
+	    String name = null;
+	    String value = null;
+	    switch(state) {
+	    case BASE:
+		// The only thing we would expect is a build message
+		name = element.getElementName();
+		if(name.equals(BUILD_ELEMENT)) {
+		    progress_bar.setIndeterminate(false);
+		    state = BUILD;
+		    // Produce a lower detail message if required
+		    if(Configuration.getMode() <= threshold && !stop) {
+			queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Build.BuildBegun1"), event.getStatus()));
+		    }
+		}
+		else {
+		    // Unknown command, go indeterminate
+		    DebugStream.println("Unknown name: " + name);
+		    progress_bar.setIndeterminate(true);
+		}
+		name = null;
+		break;
+	    case BUILD:
+		// The only thing we would expect is a stage element or a 
+		// bad classifier arg name
+		name = element.getElementName();
+
+		if(name.equals(STAGE_ELEMENT)) {
+		    progress_bar.setIndeterminate(false);
+		    // Now we determine what stage we are moving to
+		    value = element.getAttribute(NAME_ATTRIBUTE);
+		    if(value.equals(COMPRESSTEXT_VALUE)) {
+			state = COMPRESSTEXT;
+			if(Configuration.getMode() <= threshold) {
+			    queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Build.CompressText"), event.getStatus()));
+			}
+		    }
+		    else if(value.equals(INDEX_VALUE)) {
+			state = INDEX;
+			if(Configuration.getMode() <= threshold) {
+			    String args[] = new String[1];
+			    args[0] = element.getAttribute(SOURCE_ATTRIBUTE);
+			    queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Build.Index", args), event.getStatus()));
+			    args = null;
+			}
+		    }
+		    else if(value.equals(CREATEINFODATA_VALUE)) {
+			state = CREATEINFODATA;
+			if(Configuration.getMode() <= threshold) {
+			    queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Build.InfoDatabase"), event.getStatus()));
+			}
+		    }
+		    else if(value.equals(PHIND_VALUE)) {
+			state = PHIND;
+			if(Configuration.getMode() <= threshold) {
+			    queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Build.Phind"), event.getStatus()));
+			}
+		    }
+		    else if(value.equals(CREATINGAUXILARY_VALUE)) {
+			state = CREATINGAUXILARY;
+			if(Configuration.getMode() <= threshold) {
+			    queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Build.Auxilary"), event.getStatus()));
+			}
+		    }
+		    else {
+			// Unknown command, go indeterminate
+			DebugStream.println("Unknown value: " + value);
+			progress_bar.setIndeterminate(true);
+		    }
+		    value = null;
+		}
+		// The build end message indicates a successfulish build.
+		else if(name.equals(BUILD_ELEMENT) && element.isClosed()) {
+		    progress_bar.setIndeterminate(false);
+		    setValue(MAX);
+		    state = BASE;
+		    if(Configuration.getMode() <= threshold) {
+			queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Build.BuildComplete1"), event.getStatus()));
+		    }
+		}
+		// We had a bad argument to a plugin/classifier
+		else if (name.equals(BADARGUMENT_ELEMENT)) {
+		    if(Configuration.getMode() <= threshold) {
+			String args[] = new String[1];
+			args[0] = element.getAttribute(ARGUMENT_ATTRIBUTE);    
+			queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.BadArgument", args), event.getStatus()));
+			args = null;
+		    }
+		}
+		// We had a bad argument value to a plugin/clasifier
+		else if (name.equals(BADARGUMENTVALUE_ELEMENT)) {
+		    if(Configuration.getMode() <= threshold) {
+			String args[] = new String[1];
+			args[0] = element.getAttribute(ARGUMENT_ATTRIBUTE);    
+			queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.BadArgumentValue", args), event.getStatus()));
+			args = null;
+		    }
+		}
+		// And this one tellsa us the plugin
+		else if (name.equals(BADPLUGIN_ELEMENT)) {
+		    if(Configuration.getMode() <= threshold) {
+			String args[] = new String[1];
+			args[0] = element.getAttribute(PLUGIN_ATTRIBUTE);    
+			queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.BadPluginOptions", args), event.getStatus()));
+			args = null;
+		    }
+		}
+		// or the classifier
+		else if (name.equals(BADCLASSIFIER_ELEMENT)) {
+		    if(Configuration.getMode() <= threshold) {
+			String args[] = new String[1];
+			args[0] = element.getAttribute(CLASSIFIER_ATTRIBUTE);    
+			queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.BadClassifierOptions", args), event.getStatus()));
+			args = null;
+		    }
+		}
+		
+		else {
+		    // Unknown command, go indeterminate
+		    DebugStream.println("Unknown name: " + name);
+		    progress_bar.setIndeterminate(true);
+		}
+		name = null;
+		break;
+	    case COMPRESSTEXT:
+		// We are either dealing with a phase, aa fatal error or an end stage
+		name = element.getElementName();
+		if(name.equals(PHASE_ELEMENT)) {
+		    // There are three phases within compressing text (or of four possible ones)
+		    value = element.getAttribute(NAME_ATTRIBUTE);
+		    if(value.equals(COLLECTTEXTSTATS_VALUE)) {
+			// Nothing to do
+		    }
+		    else if(value.equals(CREATINGCOMPRESS_VALUE) || value.equals(SKIPCREATINGCOMP_VALUE)) {
+			// One third complete
+			progress_bar.setIndeterminate(false);
+			setValue((int)(((double)current_stages + 0.3d) * MAX) / expected_stages);
+		    }
+		    else if(value.equals(COMPRESSINGTEXT_VALUE)) {
+			// Two thirds complete
+			progress_bar.setIndeterminate(false);
+		        setValue((int)(((double)current_stages + 0.6d) * MAX) / expected_stages);
+		    }
+		    else {
+			// Unknown command, go indeterminate
+			DebugStream.println("Unknown value: " + value);
+			progress_bar.setIndeterminate(true);
+		    }
+		    value = null;
+		}
+		// Note that a fatal error is always followed by an end-stage, but not an end build. Thus the final state will be build (not base) and calls to exitValue() with indicate failure.
+		else if(name.equals(FATALERROR_ELEMENT)) {
+		    // On simplier modes produce a meaningful message
+		    queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Build.FatalError"), event.getStatus()));
+		}
+		else if(name.equals(STAGE_ELEMENT) && element.isClosed()) {
+		    // Increase progress so that stage is complete.
+		    current_stages++;
+		    progress_bar.setIndeterminate(false);
+		    setValue((current_stages * MAX) / expected_stages);
+		    state = BUILD;
+		}
+		else {
+		    // Unknown command, go indeterminate
+		    DebugStream.println("Unknown name: " + name);
+		    progress_bar.setIndeterminate(true);
+		}
+		name = null;
+		break;
+	    case INDEX:
+		/** @todo - If on lower modes output a meaningful message. */
+		name = element.getElementName();
+		if(name.equals(PHASE_ELEMENT)) {
+		    value = element.getAttribute(NAME_ATTRIBUTE);
+		    if(value.equals(CREATINGINDEXDIC_VALUE)) {
+			// Nothing to do
+		    }
+		    else if(value.equals(INVERTINGTEXT_VALUE)) {
+			// One fifth complete
+			progress_bar.setIndeterminate(false);
+			setValue((int)(((double)current_stages + 0.2d) * MAX) / expected_stages);
+		    }
+		    else if(value.equals(CREATETHEWEIGHTS_VALUE)) {
+			// Two fifths complete
+			progress_bar.setIndeterminate(false);
+			setValue((int)(((double)current_stages + 0.4d) * MAX) / expected_stages);
+		    }
+		    else if(value.equals(CREATESTEMMEDDIC_VALUE)) {
+			// Three fifths complete
+			progress_bar.setIndeterminate(false);
+			setValue((int)(((double)current_stages + 0.6d) * MAX) / expected_stages);
+		    }
+		    else if(value.equals(CREATINGSTEMINDX_VALUE)) {
+			// Four fifths complete
+			progress_bar.setIndeterminate(false);
+			setValue((int)(((double)current_stages + 0.8d) * MAX) / expected_stages);
+		    }
+		    else {
+			// Unknown command, go indeterminate
+			DebugStream.println("Unknown value: " + value);
+			progress_bar.setIndeterminate(true); 
+		    }
+		    value = null;
+		}
+		else if(name.equals(WARNING_ELEMENT)) {
+		    /** @todo - If on lower modes output a meaningful message. */
+		}
+		// Note that a fatal error is always followed by an end-stage, but not an end build. Thus the final state will be build (not base) and calls to exitValue() with indicate failure.
+		else if(name.equals(FATALERROR_ELEMENT)) {
+		    // On lower modes output a meaningful message.
+		    
+		}
+		else if(name.equals(STAGE_ELEMENT) && element.isClosed()) {
+		    // Increase progress so that stage is complete.
+		    current_stages++;
+		    progress_bar.setIndeterminate(false);
+		    setValue((current_stages * MAX) / expected_stages);
+		    state = BUILD;
+		}
+		else {
+		    // Unknown command, go indeterminate
+		    DebugStream.println("Unknown name: " + name);
+		    progress_bar.setIndeterminate(true); 
+		}
+		name = null;
+		break;
+	    case PHIND:
+		name = element.getElementName();
+		if(name.equals(PHASE_ELEMENT)) {
+		    value = element.getAttribute(NAME_ATTRIBUTE);
+		    if(value.equals(EXTRACTINGVOCAB_VALUE)) {
+			// Nothing to do
+		    }
+		    else if(value.equals(EXTRACTINGPHRASE_VALUE)) {
+			// One sixth complete
+			progress_bar.setIndeterminate(false);
+			setValue((int)(((double)current_stages + 0.16d) * MAX) / expected_stages);
+		    }
+		    else if(value.equals(SORTANDRENUMBER_VALUE)) {
+			// Two sixths complete
+			progress_bar.setIndeterminate(false);
+		        setValue((int)(((double)current_stages + 0.33d) * MAX) / expected_stages);
+		    }
+		    else if(value.equals(PHRASEDATABASES_VALUE)) {
+			// Three sixths complete
+			progress_bar.setIndeterminate(false);
+		        setValue((int)(((double)current_stages + 0.5d) * MAX) / expected_stages);
+		    }
+		    else if(value.equals(WORDLEVELINDEXES_VALUE)) {
+			// Four sixths complete
+			progress_bar.setIndeterminate(false);
+			setValue((int)(((double)current_stages + 0.66d) * MAX) / expected_stages);
+		    }
+		    else if(value.equals(DOCINFODATABASES_VALUE)) {
+			// Five sixths complete
+			progress_bar.setIndeterminate(false);
+			setValue((int)(((double)current_stages + 0.83d) * MAX) / expected_stages);
+		    }
+		    else {
+			// Unknown command, go indeterminate
+			DebugStream.println("Unknown value: " + value);
+			progress_bar.setIndeterminate(true); 
+		    }
+		    value = null;
+		}
+		else if(name.equals(STAGE_ELEMENT) && element.isClosed()) {
+		    // Increase progress so that stage is complete.
+		    current_stages++;
+		    progress_bar.setIndeterminate(false);
+		    setValue((current_stages * MAX) / expected_stages);
+		    state = BUILD;
+		}
+		else {
+		    // Unknown command, go indeterminate
+		    DebugStream.println("Unknown name: " + name);
+		    progress_bar.setIndeterminate(true); 
+		}
+		name = null;
+		break;
+	    case CREATEINFODATA:
+	    case CREATINGAUXILARY:
+		name = element.getElementName();
+		if(name.equals(STAGE_ELEMENT) && element.isClosed()) {
+		    // Another stage complete
+		    current_stages++;
+		    progress_bar.setIndeterminate(false);
+		    setValue((current_stages * MAX) / expected_stages);
+		    state = BUILD;
+		}
+		else {
+		    // Unknown command, go indeterminate
+		    DebugStream.println("Unknown name: " + name);
+		    progress_bar.setIndeterminate(true);
+		}
+		name = null;
+		break;
+	    default:
+		// Unknown command, go indeterminate
+		DebugStream.println("Unknown name: " + name);
+		progress_bar.setIndeterminate(true);
+	    }
+	}
+	// If we are dealing with lower detail modes then veto any other messages. We do this here as the progress monitors are garuenteed to recieve this message before anything else
+	else if(Configuration.getMode() <= threshold) {
+	    event.veto();
+	}
+    }
+
+    public void reset() {
+	current_stages = 0;
+	expected_stages = 0;
+	progress_bar.setIndeterminate(false);
+	progress_bar.setString(null);
+	setValue(MIN);
+	state = BASE;
+	progress_bar.updateUI();
+    }
+
+    public void saving() {
+    }
+
+    public void setSharedProgressBar(GProgressBar shared_progress_bar) {
+	this.shared_progress_bar = shared_progress_bar;
+    }
+
+    /** Since the creator of this process monitor is actually in the GUI, this class provides the simpliest way to send a cancel process message between the two.
+     * @param state The desired state of the stop flag as a <strong>boolean</strong>.
+     */
+    public synchronized void setStop(boolean state) {
+	this.stop = state;
+	progress_bar.setIndeterminate(false);
+    }
+    /** This method resets this monitor to the start, reseting the process parsing and progress bar.
+     * TODO Everthing.
+     */
+    public void start() {
+	stop = false;
+	setValue(MIN);
+	expected_stages = 3; // Always compress text, create info database and auxiliary creation
+	// Retrieve cdm.
+	CollectionDesignManager cdm = Gatherer.c_man.getCollection().cdm;
+	// If we are using MGPP the number of indexes is always 1
+	if(cdm.index_manager.isMGPP()) {
+	    expected_stages = expected_stages + 1;
+	} else if (cdm.index_manager.isLucene()) {
+	    // lucene no of indexes == number of levels
+	    int num_levels = cdm.index_manager.getNumLevels();
+	    if (num_levels == 0) num_levels = 1;
+	    expected_stages = expected_stages + num_levels;
+	}
+	else {
+	    int num_indexes = cdm.index_manager.getNumIndexes();
+	    int num_partitions = cdm.subcollectionindex_manager.getSize();
+	    if(num_partitions > 0) {
+		num_indexes = num_indexes * num_partitions;
+	    }
+	    int num_languages = cdm.language_manager.getSize();
+	    if(num_languages > 0) {
+		num_indexes = num_indexes * num_languages;
+	    }
+	    expected_stages = expected_stages + num_indexes;
+	}
+	// And if we have a phind classifier, we have one further index
+	if(cdm.classifier_manager.isPhindClassifierAssigned()) {
+	    expected_stages = expected_stages + 1;
+	}
+	cdm = null;
+    }
+    /** This method indicates the process is complete. 
+     * TODO Everthing.
+     */
+    public void stop() {
+	progress_bar.setIndeterminate(false);
+	setValue(MAX);
+    }
+
+    private void setValue(int value) {
+	progress_bar.setValue(value);
+	// Incrementing the shared progress bar is a little more problematic as we may very well be trying to set it to MIN but instead set it to halfway if we're not careful.
+	if(value > MIN) {
+	    shared_progress_bar.setValue(MAX + value);
+	}
+    }
+}
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/shell/GDefaultProgressMonitor.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/shell/GDefaultProgressMonitor.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/shell/GDefaultProgressMonitor.java	(revision 13928)
@@ -0,0 +1,90 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.shell;
+
+import org.greenstone.gatherer.gui.GProgressBar;
+import java.util.ArrayList;
+import java.awt.Component;
+
+public class GDefaultProgressMonitor implements GShellProgressMonitor{
+    private GProgressBar progress_bar = null; 
+    private boolean signalledStop = false;    
+
+    public void addProgressBar(GProgressBar progressBar){
+	progress_bar =  progressBar; 
+     }
+
+    public int exitValue(){
+	if (signalledStop){
+	    return 0;
+	}
+	return 1;
+      }
+
+    public GProgressBar getSharedProgress(){
+         return progress_bar;
+     }
+
+    public Component getProgress(){
+        return null;
+    }
+
+    public void messageOnProgressBar(String message){
+
+    }
+
+    public boolean hasSignalledStop(){
+	return signalledStop;
+    }
+   
+    public void increment(){}
+
+    public void process(ArrayList queue){}
+
+    public void reset(){}
+
+    public void saving(){}
+   
+    public void setStop(boolean state){
+        signalledStop = state; 
+    }
+
+    public void start(){}
+
+    public void stop(){}
+
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/shell/GImportProgressMonitor.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/shell/GImportProgressMonitor.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/shell/GImportProgressMonitor.java	(revision 13928)
@@ -0,0 +1,468 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.shell;
+
+import java.awt.Component;
+import java.util.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.gui.GProgressBar;
+import org.greenstone.gatherer.util.StaticStrings;
+
+/** This implementation of <i>GShellProgressMonitor</i> is designed to parse and translate the progress of a import.pl call.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.1
+ */
+public class GImportProgressMonitor
+    implements GShellProgressMonitor {
+    /** Indicates if the progress bar is currently showing a string. */
+    private boolean showing_string = false;
+    /** Indicates if the GUI has asked the process this object monitors to stop. */
+    private boolean stop = false;
+    /** A count of the extracted files processed so far. */
+    private int extracted_file_count;
+    /** The number of documents processed (or rejected) so far. */
+    private int file_count;
+    /** The next value to be set for the progress bar - I use this rather than a compounding progress measure to try to limit rounding inaccuracies (nothing looks worse than the progress bar having to jump the last 10-15%) */
+    private int next_progress_value;
+    /** The number of files expected to be scanned by this import process. */
+    private int num_expected_docs;
+    /** This holds the number of documents actually processed by the import command, as garnered from the final block of text output. */
+    private int num_docs;
+
+    private int threshold = Configuration.SYSTEMS_MODE;
+    /** The progress bar this monitor updates. */
+    private GProgressBar progress_bar;
+
+    /** The progress bar that is shared with build monitor. */
+    private GProgressBar shared_progress_bar;
+
+    /** */
+    static final private String BLOCKED_ATTRIBUTE = "blocked";
+    static final private String CONSIDERED_ATTRIBUTE = "considered";
+    static final private String FAILED_ATTRIBUTE = "failed";
+    static final private String IGNORED_ATTRIBUTE = "ignored";
+    static final private String IMPORT_ELEMENT = "Import";
+    static final private String PROCESSED_ATTRIBUTE = "processed";  
+
+    static final private String ARGUMENT_ATTRIBUTE = "a";
+    /** */
+    static final private String NAME_ATTRIBUTE = "n";
+    /** */
+    static final private String PLUGIN_ATTRIBUTE = "p";
+    static final private String REASON_ATTRIBUTE = "r";
+    /** The fixed portion of the progress bar used for the calculating of file size and other pre-import functions. */
+    static final private int CALCULATION = 50000;
+    /** The fixed portion of the progress bar used for extracted metadata. */
+    static final private int EXTRACTED = 200000;
+    /** The fixed portion of the progress bar used for processed documents. */
+    static final private int PROCESSED = 750000;
+    /** The maximum value for this progress bar. */
+    static final private int MAXIMUM = CALCULATION + EXTRACTED + PROCESSED;
+    /** The minimum value for this progress bar. */
+    static final private int MINIMUM = 0;
+    /** The element name of a file detected message. */
+    static final private String FILE_ELEMENT = "File";
+    /** The element name of a file processing message. */
+    static final private String PROCESSING_ELEMENT = "Processing";
+    /** The element name of a processing error message. */
+    static final private String PROCESSINGERROR_ELEMENT = "ProcessingError";
+    /** The element name of an import complete message. */
+    static final private String IMPORTCOMPLETE_ELEMENT = "ImportComplete";
+    /** The element name of a file not processed. */
+    static final private String NONPROCESSEDFILE_ELEMENT = "NonProcessedFile";
+    /** The element name of a file not recognised. */
+    static final private String NONRECOGNISEDFILE_ELEMENT = "NonRecognisedFile";
+    /** The element name of a BadArgument message */
+    static final private String BADARGUMENT_ELEMENT = "BadArgument";
+    static final private String BADARGUMENTVALUE_ELEMENT = "BadArgumentValue";
+    static final private String BADPLUGIN_ELEMENT = "BadPlugin";
+
+    public GImportProgressMonitor() {
+	progress_bar = new GProgressBar();
+	progress_bar.setIndeterminate(false);
+	progress_bar.setMaximum(MAXIMUM);
+	progress_bar.setMinimum(MINIMUM);
+	progress_bar.setString(null);
+	progress_bar.setStringPainted(true);
+	next_progress_value = CALCULATION;
+	shared_progress_bar = new GProgressBar();
+	shared_progress_bar.setIndeterminate(false);
+	shared_progress_bar.setMaximum(MAXIMUM * 2);
+	shared_progress_bar.setMinimum(MINIMUM);
+	shared_progress_bar.setString(null); // Default string
+	shared_progress_bar.setStringPainted(true);
+	setValue(MINIMUM);
+    }
+
+    /** Method to register a new progress bar with this monitor.
+     * @param progress_bar The new <strong>GProgressBar</strong>.
+     */
+    public void addProgressBar(GProgressBar progress_bar) {
+	this.progress_bar = progress_bar;
+	progress_bar.setMaximum(MAXIMUM);
+	progress_bar.setMinimum(MINIMUM);
+	setValue(MINIMUM);
+	next_progress_value = CALCULATION;
+    }
+
+    /** Determine the script exit value according to the progress monitor. This gets around a problem where several script failures actually result with a successful exit value.
+     * @return A <i>int</i> with a value of zero if and only if the script was successful.
+     */
+    public int exitValue() {
+	if(num_docs > 0) {
+	    return 0;
+	}
+	return 1;
+    }
+
+    /** Retrieve the number of documents recorded by the import monitor during the execution of the import scripts.
+     * @return An <i>int</i> giving the document number.
+     */
+    public int getNumberOfDocuments() {
+	return num_docs;
+    }
+
+    /** Method to retrieve whatever control is being used as the progress indicator. Usually a <strong>GProgressBar</strong> but there may be others implemented later.
+     * @return A <strong>Component</strong> on which the progress of the process is being displayed.
+     */
+    public Component getProgress() {
+	return progress_bar;
+    }
+
+    public GProgressBar getSharedProgress() {
+	return shared_progress_bar;
+    }
+
+    public void messageOnProgressBar(String message)
+    {
+	if (message!=null && !message.equals("")) {
+	    progress_bar.setString(message);
+	    shared_progress_bar.setString(message);
+	    showing_string = true;
+	}
+	else {
+	    progress_bar.setString(null);
+	    shared_progress_bar.setString(null);
+	    showing_string = false;
+	}
+    }
+
+    /** Method to determine the state of the stop flag, which may be set by the visual component that created this monitor.
+     * @return A <strong>boolean</strong> indicating if the process has been asked to stop.
+     */
+    public synchronized boolean hasSignalledStop() {
+	return stop;
+    }
+
+    /** Inform the progress bar that it should programatically increment progress by one step. This is only called during the metadata archive extraction so each step should be (1000000 / 5) / num_docs. */
+    public void increment() {
+	extracted_file_count++;
+	// The current progress is calculated to be:
+	// The fixed calculation value plus the fixed processed value plus some portion of the fixed extracted value. This portion is the extracted_file_count over the total number of documents available. Note that this breaks badly for bibliographical files (for now).
+	setValue(CALCULATION + PROCESSED + ((EXTRACTED * extracted_file_count) / num_docs));
+    }
+
+    /** This method is used to 'feed in' a line of text captured from the process.
+     * @param queue a queue which at the moment should contain a single GShellEvent
+     */
+    public void process(ArrayList queue) {
+	// Retrieve the first event.
+	GShellEvent event = (GShellEvent) queue.get(0);
+	// Remove 'import.pl> ' bit
+	String line = event.getMessage();
+	line = line.substring(line.indexOf(StaticStrings.GREATER_THAN_CHARACTER) + 1);
+	line = line.trim();
+	// System.err.println("**** line = " + line);
+
+	///ystem.err.println("Process: " + line);
+	if(line.startsWith(StaticStrings.LESS_THAN_CHARACTER) && line.endsWith(StaticStrings.GREATER_THAN_CHARACTER)) {
+	    // No original event is passed on, even in the lower modes
+	    event.veto();
+	    // Create a new element from it
+	    GShellElement element = new GShellElement(line);
+	    String name = element.getElementName();
+	    ///ystem.err.println("Gatherer tag: " + name);
+	    // We may be reading a file. Remember we have to offset process as we recieve this message 'before' a document is processed. Hence the use of 'next_progress_value'
+	    if(name.equals(IMPORT_ELEMENT)) {
+		///ystem.err.println("#Import");
+		// We're into parsing output, so we don't need the 'calculating file size' etc string.
+		if(showing_string) {
+		    progress_bar.setString(null);
+		    showing_string = false;
+		}
+		if(Configuration.getMode() <= threshold) {
+		    queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.ImportBegun1"), event.getStatus()));
+		}
+	    }
+	    else if(name.equals(FILE_ELEMENT)) {
+		///ystem.err.println("#File");
+		file_count++;
+		// Set the next progress
+		if(next_progress_value > 0) {
+		    setValue(next_progress_value);
+		}
+		// Now we calculate the next progress value
+		next_progress_value = CALCULATION + ((PROCESSED * file_count) / num_expected_docs);
+		event.veto(); // Unconditional veto
+	    }
+	    // Or we're being told what plugin is actually processing the file
+	    else if(name.equals(PROCESSING_ELEMENT)) {
+		///ystem.err.println("#FileProcessing");
+		// If we are at lower mode settings fire a new 'dumbed down' event
+		if(Configuration.getMode() <= threshold) {
+		    String args[] = new String[2];
+		    args[0] = element.getAttribute(NAME_ATTRIBUTE);
+		    args[1] = element.getAttribute(PLUGIN_ATTRIBUTE);
+		    queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.FileProcessing", args), event.getStatus()));
+		    args = null;
+		}
+	    }
+	    // processing error
+	    else if (name.equals(PROCESSINGERROR_ELEMENT)) {
+		if(Configuration.getMode() <= threshold) {
+		    String args[] = new String[1];
+		    args[0] = element.getAttribute(NAME_ATTRIBUTE);
+		    String reason = element.getAttribute(REASON_ATTRIBUTE);
+		    if (reason == null || reason.equals("")) {
+			queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.FileProcessingError", args), event.getStatus()));
+		    }
+		    else {
+			queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.FileProcessingError", args) + " (" + reason + ")", event.getStatus()));
+		    }
+		    args = null;
+		}
+	    }
+	    // unrecognised file
+	    else if (name.equals(NONRECOGNISEDFILE_ELEMENT)) {
+		if(Configuration.getMode() <= threshold) {
+		    String args[] = new String[1];
+		    args[0] =element.getAttribute(NAME_ATTRIBUTE);
+		    queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.FileNotRecognised", args), event.getStatus()));
+		    args = null;
+		}
+	    }
+	    // unprocessed file
+	    else if (name.equals(NONPROCESSEDFILE_ELEMENT)) {
+		if(Configuration.getMode() <= threshold) {
+		    String args[] = new String[1];
+		    args[0] =element.getAttribute(NAME_ATTRIBUTE);		    
+		    queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.FileNotProcessed", args), event.getStatus()));
+		    args = null;
+		}
+	    }
+	    // We had a bad argument to a plugin
+	    else if (name.equals(BADARGUMENT_ELEMENT)) {
+		if(Configuration.getMode() <= threshold) {
+		    String args[] = new String[1];
+		    args[0] = element.getAttribute(ARGUMENT_ATTRIBUTE);    
+		    queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.BadArgument", args), event.getStatus()));
+		    args = null;
+		}
+	    }
+	    // We had a bad argument value to a plugin
+	    else if (name.equals(BADARGUMENTVALUE_ELEMENT)) {
+		if(Configuration.getMode() <= threshold) {
+		    String args[] = new String[1];
+		    args[0] = element.getAttribute(ARGUMENT_ATTRIBUTE);    
+		    queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.BadArgumentValue", args), event.getStatus()));
+		    args = null;
+		}
+	    }
+	    // And this one tellsa us the plugin
+	    else if (name.equals(BADPLUGIN_ELEMENT)) {
+		if(Configuration.getMode() <= threshold) {
+		    String args[] = new String[1];
+		    args[0] = element.getAttribute(PLUGIN_ATTRIBUTE);    
+		    queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.BadPluginOptions", args), event.getStatus()));
+		    args = null;
+		}
+	    }
+	    // Or the import complete element
+	    else if(name.equals(IMPORTCOMPLETE_ELEMENT)) {
+		// Set the next progress
+		setValue(next_progress_value);
+		// If we are at lower mode settings fire a new 'dumbed down' event
+		if(Configuration.getMode() <= threshold) {
+		    queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.ImportComplete1"), event.getStatus()));
+		    String considered_str = element.getAttribute(CONSIDERED_ATTRIBUTE);
+
+		    if (considered_str.equals(StaticStrings.ONE_CHARACTER)) {
+			queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.ImportComplete2.1"), event.getStatus()));	
+		    } else {
+			queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.ImportComplete2", considered_str), event.getStatus()));
+		    }
+		    considered_str = null;
+		    // The number of documents processed
+		    String processed_str = element.getAttribute(PROCESSED_ATTRIBUTE);
+		    if(!processed_str.equals(StaticStrings.ZERO_CHARACTER)) {
+			if(processed_str.equals(StaticStrings.ONE_CHARACTER)) {
+			    queue.add(new GShellEvent(event.getSource(), 0, event.getType(), "    "+Dictionary.get("GShell.Import.ImportComplete.Processed.1"), event.getStatus()));
+			}
+			else {
+			    queue.add(new GShellEvent(event.getSource(), 0, event.getType(), "    "+Dictionary.get("GShell.Import.ImportComplete.Processed", processed_str), event.getStatus()));
+			}
+		    }
+		    // Try to set num docs
+		    try {
+			num_docs = Integer.parseInt(processed_str);
+		    }
+		    catch(Exception exception) {
+			num_docs = 0;
+		    }  
+		    processed_str = null;
+
+		    // The number of documents blocked
+		    String blocked_str = element.getAttribute(BLOCKED_ATTRIBUTE);
+		    if(!blocked_str.equals(StaticStrings.ZERO_CHARACTER)) {
+			if (blocked_str.equals(StaticStrings.ONE_CHARACTER)) {
+			    queue.add(new GShellEvent(event.getSource(), 0, event.getType(), "    "+Dictionary.get("GShell.Import.ImportComplete.Blocked.1"), event.getStatus()));
+			} else {
+			    queue.add(new GShellEvent(event.getSource(), 0, event.getType(), "    "+Dictionary.get("GShell.Import.ImportComplete.Blocked", blocked_str), event.getStatus()));
+			}
+		    }
+		    blocked_str = null;
+		    
+		    // The number of documents ignored
+		    String ignored_str = element.getAttribute(IGNORED_ATTRIBUTE);
+		    if(!ignored_str.equals(StaticStrings.ZERO_CHARACTER)) {
+			if(ignored_str.equals(StaticStrings.ONE_CHARACTER)) {
+			    queue.add(new GShellEvent(event.getSource(), 0, event.getType(), "    "+Dictionary.get("GShell.Import.ImportComplete.Ignored.1"), event.getStatus()));
+			} else {
+			    queue.add(new GShellEvent(event.getSource(), 0, event.getType(), "    "+Dictionary.get("GShell.Import.ImportComplete.Ignored", ignored_str), event.getStatus()));
+			}
+		    }
+		    ignored_str = null;
+		    
+		    // The number of documents failed
+		    String failed_str = element.getAttribute(FAILED_ATTRIBUTE);
+		    if(!failed_str.equals(StaticStrings.ZERO_CHARACTER)) {
+			if(failed_str.equals(StaticStrings.ONE_CHARACTER)) {
+			    queue.add(new GShellEvent(event.getSource(), 0, event.getType(), "    "+Dictionary.get("GShell.Import.ImportComplete.Failed.1"), event.getStatus()));
+			} else {
+			    queue.add(new GShellEvent(event.getSource(), 0, event.getType(), "    "+Dictionary.get("GShell.Import.ImportComplete.Failed", failed_str), event.getStatus()));
+			}
+		    }
+		    failed_str = null;
+		    // Message is finally ready
+		    queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.ImportComplete3"), event.getStatus()));
+		} // if mode below threshhold
+		else {
+		    // Try to set num docs
+		    String processed_str = element.getAttribute(PROCESSED_ATTRIBUTE);
+		    try {
+			num_docs = Integer.parseInt(processed_str);
+		    }
+		    catch(Exception exception) {
+			num_docs = 0;
+		    }
+		}
+	    }
+	    else {
+		// Veto it
+		event.veto();
+	    }
+	} // GLI output
+	else if(Configuration.getMode() <= threshold) {
+	    event.veto();
+	}
+    }
+
+    public void reset() {
+	setValue(MINIMUM);
+	progress_bar.setString(null);
+	progress_bar.updateUI();
+    }
+
+    public void saving() {
+	progress_bar.setString(Dictionary.get("SaveProgressDialog.Title"));
+	showing_string = true;
+    }
+
+    /** Since the creator of this process monitor is actually in the GUI, this class provides the simpliest way to send a cancel process message between the two.
+     * @param state The desired state of the stop flag as a <strong>boolean</strong>.
+     */
+    public synchronized void setStop(boolean state) {
+	this.stop = state;
+    }
+
+    /** This method resets this monitor to the start, reseting the process parsing and progress bar.
+     */
+    public void start() {
+	stop = false;
+	setValue(MINIMUM);
+	progress_bar.setString(Dictionary.get("FileActions.Calculating_Size"));
+	showing_string = true;
+	extracted_file_count = 0;
+	file_count = 0;
+	next_progress_value = -1;
+	num_docs = -1;
+	// !! HACK: This is multiplied by 2 because the metadata_read now outputs a <File> tag also
+	// Ideally the metadata read pass would be completely separate and the GLI could work out the number
+	//   of documents accurately and provide a much better progress bar
+	num_expected_docs = Gatherer.c_man.getCollection().getCount() * 2;
+    }
+
+    /** This method indicates the process is complete. 
+     */
+    public void stop() {
+	setValue(MAXIMUM);
+    }
+
+    int previous_value = -1;
+
+    private void setValue(int value)
+    {
+	// Don't let the value go higher than the maximum
+	if (value > MAXIMUM) {
+	    DebugStream.println("Error: Tried to set progress bar higher than maximum!\n");
+	    return;
+	}
+	// Don't let the value go backwards
+	if (value != 0 && value < previous_value) {
+	    DebugStream.println("Error: Tried to set progress bar smaller than previous!\n");
+	    return;
+	}
+
+	progress_bar.setValue(value);
+	shared_progress_bar.setValue(value);
+	previous_value = value;
+    }
+}
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/shell/GShell.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/shell/GShell.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/shell/GShell.java	(revision 13928)
@@ -0,0 +1,593 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.shell;
+
+import java.io.*;
+import java.net.*;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.regex.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.CollectionConfiguration;
+import org.greenstone.gatherer.cdm.CollectionDesignManager;
+import org.greenstone.gatherer.cdm.CollectionMetaManager;
+import org.greenstone.gatherer.cdm.CollectionMeta;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.metadata.DocXMLFileManager;
+import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
+import org.greenstone.gatherer.util.StaticStrings; 
+import org.greenstone.gatherer.util.Utility;
+
+
+/** The <strong>GShell</strong> is reponsible for running a separately threaded process in the command shell. This is necessary for executing the Perl Scripts and also for other system related funcitonality.
+ */
+public class GShell
+    extends Thread {
+    /** A flag used to determine if this process has been asked to cancel. */
+    private boolean cancel = false;
+    private BufferedOutputStream buffered_output_stream = null;
+    /** The list of listeners associated with this class. */
+    private EventListenerList listeners = null;
+    /** The current status of this shell process. */
+    private int status = -1;
+    /** The type of message being sent. */
+    private int msg_type = -1;
+    /** The type of shell process. */
+    private int type = -1;
+    /** The caller of this process, and thus the class most interested in messages. */
+    private GShellListener caller = null;
+    /** The progress monitor associated with this process. */
+    private GShellProgressMonitor progress = null;
+    /** Arguments to be given to the process (including the executable you are calling. */
+    private String args[] = null;
+    /** Elements in process type enumeration. */
+    static final public int BUILD = 0;
+    static final public int IMPORT = 1;
+    static final public int NEW = 2;
+    static final public int EXPORTAS = 3;
+    static final public int CDIMAGE = 4;
+    static final public int CONVERT = 5;
+    static final public int EXPLODE = 6;
+
+    /** Elements in status type enumeration. */
+    static final public int ERROR = 0;
+    static final public int OK = 1;
+    static final public int CANCELLED = 2;
+
+    /** Elements in process type name enumeration. */
+    static public String GSHELL_BUILD = "gshell_build";
+    static public String GSHELL_IMPORT = "gshell_import";
+    static public String GSHELL_NEW = "gshell_new";
+    static public String GSHELL_EXPORTAS = "gshell_exportas";
+    static public String GSHELL_CDIMAGE = "gshell_cdimage";
+    static public String GSHELL_CONVERT = "gshell_convert";
+    static public String GSHELL_EXPLODE = "gshell_explode";
+
+    /** Determine if the given process is still executing. It does this by attempting to throw an exception - not the most efficient way, but the only one as far as I know
+     * @param process the Process to test
+     * @return true if it is still executing, false otherwise
+     */
+    static public boolean processRunning(Process process) {
+	boolean process_running = false;
+
+	try {
+	    process.exitValue(); // This will throw an exception if the process hasn't ended yet.
+	}
+	catch(IllegalThreadStateException itse) {
+	    process_running = true;
+	}
+	catch(Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+	return process_running;
+    }
+
+    /** Constructor gatherer all the data required to create a new process, and emit meaningfull messages.
+     * @param args A <strong>String[]</strong> containing the arguments to the process thread, including the name of the executable.
+     * @param type An <strong>int</strong> that indicates what group of processes this process belongs to, as some are treated slightly differently (i.e an IMPORT type process is always followed by a BUILD one).
+     * @param msg_type As process threads may be background (like a makecol.pl call) or important processes in their own right (such as an IMPORT-BUILD) we must be able to set what level messages posted by this class will have by usings this <strong>int</strong>.
+     * @param caller The default <i>GShellListener</i> that is interested in the progress of this process.
+     * @param progress The <i>GShellProgressMonitor</i> associated with this process.
+     * @param name A <strong>String</strong> identifier given to the process, for convience and debug reasons.
+     */
+    public GShell(String args[], int type, int msg_type, GShellListener caller, GShellProgressMonitor progress, String name) {
+	super(name);
+	this.args = args;
+	this.msg_type = msg_type;
+	this.type = type;
+	this.caller = caller;
+	this.progress = progress;
+	this.status = 0;
+	// Lower this jobs priority
+	this.setPriority(Thread.MIN_PRIORITY);
+	listeners = new EventListenerList();
+	listeners.add(GShellListener.class, caller);
+    }
+    /** This method adds another shell listener to this process.
+     * @param listener The new <i>GShellListener</i>.
+     */
+    public void addGShellListener(GShellListener listener) {
+	listeners.add(GShellListener.class, listener);
+    }
+    /** This method removes a certain shell listener from this process.
+     * @param listener The <i>GShellListener</i> to be removed.
+     */
+    /* private void removeGShellListener(GShellListener listener) {
+       listeners.remove(GShellListener.class, listener);
+       } */
+
+    protected StringBuffer get_stream_char(InputStreamReader isr, StringBuffer line_buffer,
+				   BufferedOutputStream bos) throws IOException 
+    {
+	int c = isr.read();
+	///atherer.println("isr: '" + (char) c + "'");
+	if(c == '\n' || c == '\r') {
+	    if(line_buffer.length() > 0) {
+		String line = line_buffer.toString();
+		// DebugStream.println("* " + line + " *");
+		fireMessage(type, typeAsString(type) + "> " + line, status, bos);
+		line_buffer = new StringBuffer();
+	    }
+	}
+	else {
+	    line_buffer.append((char)c);
+	}
+
+	return line_buffer;
+    }
+
+
+    private void runRemote(String[] args, BufferedOutputStream bos)
+    {
+	// Make sure the process hasn't been cancelled
+	if (hasSignalledStop()) {
+	    return;
+	}
+
+	try {
+	    int directory_name_end = args[0].lastIndexOf(File.separator);
+	    String script_name = ((directory_name_end != -1) ? args[0].substring(directory_name_end + 1) : args[0]);
+	    System.err.println("Script name: " + script_name);
+	    String collection_name = args[args.length - 1];
+	    System.err.println("Collection name: " + collection_name);
+
+	    String script_args = "";
+	    for (int i = 1; i < (args.length - 1); i++) {
+		// Skip arguments that won't make sense on the server
+		if (args[i].equals("-collectdir") || args[i].equals("-importdir") || args[i].equals("-builddir")) {
+		    i++;
+		    continue;
+		}
+
+		// Script arguments get changed to CGI arguments
+		if (args[i].startsWith("-")) {
+		    script_args += "&" + args[i].substring(1) + "=";
+		    if ((i + 1) < (args.length - 1) && !args[i + 1].startsWith("-")) {
+			script_args += URLEncoder.encode(args[i + 1], "UTF-8");
+			i++;
+		    }
+		}
+	    }
+
+	    System.err.println("Script args: " + script_args);
+	    buffered_output_stream = bos;
+	    String command_output = RemoteGreenstoneServer.runScript(collection_name, script_name, script_args, this);
+	    status = (command_output.equals("") ? CANCELLED : OK);
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	    status = ERROR;
+	}
+    }
+
+
+    private void runLocal(String[] args, BufferedOutputStream bos) 
+    {
+	try {
+	    String command = "";
+	    for(int i = 0; i < args.length; i++) {
+		command = command + args[i] + " ";
+	    }
+	    
+	    ///ystem.err.println("Command: " + command);
+	    fireMessage(type, Dictionary.get("GShell.Command") + ": " + command, status, null);
+	    
+	    Runtime rt = Runtime.getRuntime();
+	    Process prcs = rt.exec(args);
+	    
+	    InputStreamReader eisr = new InputStreamReader( prcs.getErrorStream(), "UTF-8" );
+	    InputStreamReader stdisr = new InputStreamReader( prcs.getInputStream(), "UTF-8"  );
+	
+	    StringBuffer eline_buffer = new StringBuffer();
+	    StringBuffer stdline_buffer = new StringBuffer();
+	
+	    while(/*type != GShell.NEW &&*/ processRunning(prcs) && !hasSignalledStop()) {
+		// Hopefully this doesn't block if the process is trying to write to STDOUT.
+		if((eisr!=null) && eisr.ready()) { 
+		    eline_buffer = get_stream_char(eisr,eline_buffer,bos);
+		}
+		// Hopefully this won't block if the process is trying to write to STDERR
+		else if(stdisr.ready()) {
+		    stdline_buffer = get_stream_char(stdisr,stdline_buffer,bos);
+		}
+		else {
+		    try {
+			sleep(100);
+		    }
+		    catch(Exception exception) {
+		    }
+		}
+	    }
+	
+	    if(!hasSignalledStop()) {
+		// Of course, just because the process is finished doesn't
+		// mean the incoming streams are empty. Unfortunately I've
+		// got no chance of preserving order, so I'll process the
+		// error stream first, then the out stream
+		while(eisr.ready()) {
+		    eline_buffer = get_stream_char(eisr,eline_buffer,bos);
+		}
+	    
+		while(stdisr.ready()) {
+		    stdline_buffer = get_stream_char(stdisr,stdline_buffer,bos);
+		}
+	    
+		// Ensure that any messages still remaining in the string buffers are fired off.
+		if(eline_buffer.length() > 0) {
+		    String eline = eline_buffer.toString();
+		    //DebugStream.println("Last bit of eline: " + eline);
+		    fireMessage(type, typeAsString(type) + "> " + eline, status, bos);
+		    eline = null;
+		}
+	    
+		if(stdline_buffer.length() > 0) {
+		    String stdline = stdline_buffer.toString();
+		    //DebugStream.println("Last bit of stdline: " + stdline);
+		    fireMessage(type, typeAsString(type) + "> " + stdline, status, null);
+		    stdline = null;
+		}
+	    }
+	    else {
+		DebugStream.println("We've been asked to stop.");
+	    }
+	
+	
+	    if(!hasSignalledStop()) {
+		// Now display final message based on exit value
+	    
+		prcs.waitFor(); 
+
+		if(prcs.exitValue() == 0) {
+		    status = OK;
+		    fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Success"), status, null);
+		}
+		else {
+		    status = ERROR;
+		    fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Failure"), status, null);
+		}
+	    
+		eisr.close();
+		stdisr.close();
+	    }
+	    else {
+		// I need to somehow kill the child process. Unfortunately
+		// Thread.stop() and Process.destroy() both fail to do
+		// this. But now, thankx to the magic of Michaels 'close the
+		// stream suggestion', it works fine (no it doesn't!)
+		prcs.getInputStream().close();
+		prcs.getErrorStream().close();
+		prcs.getOutputStream().close();
+		prcs.destroy();
+		status = CANCELLED;
+	    }
+	}
+	// Exception
+	catch (Exception exception) {
+	    DebugStream.println("Exception in GShell.runLocal() - unexpected");
+	    DebugStream.printStackTrace(exception);
+	    status = ERROR;
+	}
+    }
+    
+    
+
+    /** Any threaded class must include this method to allow the thread body to be run. */
+    public void run() {
+	String col_name = args[args.length-1];		
+
+	// Determine if the user has asked for an outfile.
+	String out_name = null;
+	BufferedOutputStream bos = null;
+	if(type == IMPORT || type == BUILD) {
+	    if(type == IMPORT) {
+		out_name = (String) Gatherer.c_man.getCollection().import_options.getValue("out");
+	    }
+	    else {
+		out_name = (String) Gatherer.c_man.getCollection().build_options.getValue("out");
+	    }
+	    if(out_name != null && out_name.length() > 0) {
+		try {
+		    bos = new BufferedOutputStream(new FileOutputStream(new File(out_name), true));
+		}
+		catch (Exception error) {
+		    DebugStream.printStackTrace(error);
+		}
+	    }
+	}
+
+	// Issue a processBegun event
+	//ystem.err.println("\nFiring process begun for " + type + "...");
+	fireProcessBegun(type, status);
+	//ystem.err.println("Done process begun.");
+	if (Gatherer.isGsdlRemote) {
+	    runRemote(args,bos);
+	}
+	else {
+	    runLocal(args,bos);
+	}
+	//ystem.err.println("Done runLocal().");
+
+	if(status == OK) {
+	    if (type == NEW) {
+		if (Gatherer.isGsdlRemote) {
+		    RemoteGreenstoneServer.downloadCollection(col_name);
+		}
+	    }
+	    else if(type == IMPORT) {
+		
+		// download the archives directory (if gsdl server is remote)			
+		if (Gatherer.isGsdlRemote) {
+
+		    if (progress!=null) {
+			progress.messageOnProgressBar("Downloading archive data from server");
+		    }
+
+		    RemoteGreenstoneServer.downloadCollectionArchives(col_name);
+
+		    if (progress!=null) {
+			progress.messageOnProgressBar("");
+		    }      
+		}
+
+		// Refresh the DocXMLFileManager
+		fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Parsing_Metadata_Start"), status, null);
+		DocXMLFileManager.clearDocXMLFiles();
+		DocXMLFileManager.loadDocXMLFiles(new File(CollectionManager.getLoadedCollectionArchivesDirectoryPath()));
+		fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Parsing_Metadata_Complete"), status, null);
+	    }
+
+ 	    else if(type == BUILD) {
+ 		// download the building directory (if gsdl server is remote)
+ 		if (Gatherer.isGsdlRemote) {
+ 		    if (progress!=null) {
+ 			progress.messageOnProgressBar("Downloading index data from server");
+ 		    }
+
+		    // Only need to download build.cfg file
+		    File build_cfg_file = new File(CollectionManager.getLoadedCollectionBuildingDirectoryPath(), "build.cfg");
+		    RemoteGreenstoneServer.downloadCollectionFile(col_name, build_cfg_file);
+		    
+ 		    if (progress!=null) {
+ 			progress.messageOnProgressBar("");
+ 		    }
+ 		}
+ 	    }
+	    else if(type == CDIMAGE) {
+		// download exported files from tmp folder (if gsdl server is remote)			
+		if (Gatherer.isGsdlRemote) {
+		    if (progress!=null) {
+			progress.messageOnProgressBar("Downloading CD-ROM data from server");
+		    }
+
+		    // !! TO DO
+		    
+ 		    if (progress!=null) {
+ 			progress.messageOnProgressBar("");
+ 		    }
+		}
+	    }
+	}
+
+	// We're done.	
+	//ystem.err.println("Firing process complete for " + type + "...");
+	fireProcessComplete(type, status);
+	// Close bos
+	if(bos != null) {
+	    try {
+		bos.close();
+		bos = null;
+	    }
+	    catch(Exception error) {
+		DebugStream.printStackTrace(error);
+	    }
+	}
+    }
+
+
+    public void fireMessage(String message)
+    {
+	fireMessage(type, typeAsString(type) + "> " + message, status, buffered_output_stream);
+    }
+
+
+    /** Method for firing a message to all interested listeners.
+     * @param type An <strong>int</strong> indicating the process type.
+     * @param message The message as a <strong>String</strong>.
+     * @param status An <strong>int</strong> specifying the current status of the process.
+     */
+    public void fireMessage(int type, String message, int status, BufferedOutputStream bos) {
+	GShellEvent event = new GShellEvent(this, 0, type, message, status);
+	// If there is a progress monitor attached, pass the event to it first. Note that we pass a queue of messages as the processing may cause one message to be split into several.
+	ArrayList message_queue = new ArrayList();
+	message_queue.add(event);
+	if(progress != null) {
+	    progress.process(message_queue);
+	}
+	for(int j = 0; j < message_queue.size(); j++) {
+	    GShellEvent current_event = (GShellEvent) message_queue.get(j);
+	    // If the event hasn't been vetoed, pass it on to other listeners
+	    if(!current_event.isVetoed()) {
+		Object[] concerned = listeners.getListenerList();
+		for(int i = 0; i < concerned.length ; i++) {
+		    if(concerned[i] == GShellListener.class) {
+			((GShellListener)concerned[i+1]).message(current_event);
+		    }
+		}
+		concerned = null;
+	    }
+	}
+	// And if we have a buffered output stream from error messages, send the message there
+	if(bos != null) {
+	    try {
+		bos.write(message.getBytes(), 0, message.length());
+	    }
+	    catch(Exception exception) {
+		DebugStream.println("Exception in GShell.fireMessage() - unexpected");
+		DebugStream.printStackTrace(exception);
+	    }
+	}
+	message_queue = null;
+	event = null;
+    }
+
+    /** Method for firing a process begun event which is called, strangly enough, when the process begins.
+     * @param type An <strong>int</strong> indicating the process type.
+     * @param status An <strong>int</strong> specifying the current status of the process.
+     */
+    protected void fireProcessBegun(int type, int status) {
+	// Start the progres monitor if available
+	if(progress != null) {
+	    //ystem.err.println("About to call progress.start().");
+	    progress.start();
+	    //ystem.err.println("Called progress.start().");
+	}
+	// Fire an event
+	GShellEvent event = new GShellEvent(this, 0, type, "", status);
+	Object[] concerned = listeners.getListenerList();
+	for(int i = 0; i < concerned.length ; i++) {
+	    if(concerned[i] == GShellListener.class) {
+		((GShellListener)concerned[i+1]).processBegun(event);
+	    }
+	}
+    }
+
+
+    /** Method for firing a process complete event which is called, no surprise here, when the process ends.
+     * @param type An <strong>int</strong> indicating the process type.
+     * @param status An <strong>int</strong> specifying the current status of the process.
+     */
+    protected void fireProcessComplete(int type, int status) {
+	// Tidy up by stopping the progress bar. If it was cancelled then the cancel command has arrived via the progress bars and they don't need to be told again (it actually causes problems).
+	if(progress != null && status != CANCELLED) {
+	    progress.stop();
+	}
+	
+	// If we were cancelled, and we are lower details modes, fire off one last message.
+	if(status == CANCELLED && Configuration.getMode() <= Configuration.SYSTEMS_MODE) {
+	    GShellEvent current_event = new GShellEvent(this, 0, type, Dictionary.get("GShell.Build.BuildCancelled"), status);
+	    Object[] concerned = listeners.getListenerList();
+	    for(int i = 0; i < concerned.length ; i++) {
+		if(concerned[i] == GShellListener.class) {
+		    ((GShellListener)concerned[i+1]).message(current_event);
+		}
+	    }
+	    concerned = null;
+	}
+	// And firing off an event
+	GShellEvent event = new GShellEvent(this, 0, type, "", status);
+	Object[] concerned = listeners.getListenerList();
+	for(int i = 0; i < concerned.length ; i++) {
+	    if(concerned[i] == GShellListener.class) {
+		((GShellListener)concerned[i+1]).processComplete(event);
+	    }
+	}
+    }
+
+    /** Method to determine if the user, via the progress monitor, has signalled stop.
+     * @return A <strong>boolean</strong> indicating if the user wanted to stop.
+     */
+    public boolean hasSignalledStop() {
+	boolean has_signalled_stop = false;
+	if(progress != null) {
+	    has_signalled_stop = progress.hasSignalledStop();
+	}
+	if(has_signalled_stop) {
+	    status = CANCELLED;
+	}
+	return has_signalled_stop;
+    }
+
+    /** Converts a type into a text representation.
+     * @param type An <strong>int</strong> which maps to a shell process type.
+     * @return A <strong>String</strong> which is the thread process's text name.
+     */
+    public String typeAsString(int type) {
+	String name = null;
+	switch(type) {
+	case BUILD:
+	    name = "buildcol.pl";
+	    break;
+	case IMPORT:
+	    name = "import.pl";
+	    break;
+	case NEW:
+	    name = "mkcol.pl";
+	    break;
+	case EXPORTAS:
+	    name = "export.pl";
+	    break;
+	case CDIMAGE:
+	    name = "exportcol.pl";
+	    break;
+	case CONVERT:
+	    name = "convert_coll_from_gs2.pl";
+	    break;
+	case EXPLODE:
+	    name = "explode_metadata_database.pl";
+	    break;
+	default:
+	    name = "";
+	}
+	return name;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/shell/GShellElement.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/shell/GShellElement.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/shell/GShellElement.java	(revision 13928)
@@ -0,0 +1,106 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, New Zealand Digital Library, University of Waikato
+ *
+ * Copyright (C) 2004 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.shell;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+import org.greenstone.gatherer.util.StaticStrings;
+
+/** This class wraps around a pseudo-XML message we have recieved from an external script, and allows access to the element name, attributes etc via method calls. */
+public class GShellElement {
+    private boolean is_closed = false;
+    private HashMap attributes;
+    private String element_name;
+    /** Create a new element around the message string. The string is expected to start with < and end with > */
+    /** this is a hack - why aren't we using proper XML parsing?? */
+    public GShellElement(String message) {
+	// Remove the angle brackets
+	message = message.substring(1, message.length() - 1);
+	// Tokenize the message
+	StringTokenizer tokenizer = new StringTokenizer(message);
+	// The first token is the element name - be aware it may start with the close tag indicator
+	element_name = tokenizer.nextToken();
+	if(element_name.startsWith(StaticStrings.URL_SEPARATOR_CHARACTER)) {
+	    element_name = element_name.substring(1);
+	    is_closed = true;
+	}
+	// Now while we have remaining tokens
+	while(tokenizer.hasMoreTokens()) {
+	    int index = -1;
+	    // The next token might be a attribute=value pair or it could be the close tag indicator
+	    String token = tokenizer.nextToken();
+	    if(token.equals(StaticStrings.URL_SEPARATOR_CHARACTER)) {
+		is_closed = true;
+	    }
+	    else if(token.length() > 3 && (index = token.indexOf(StaticStrings.EQUALS_CHARACTER)) != -1) {
+		String attribute_name = token.substring(0, index);
+		String attribute_value = token.substring(index + 1);
+		// Value may end in a /
+		if(attribute_value.endsWith(StaticStrings.URL_SEPARATOR_CHARACTER)) {
+		    is_closed = true;
+		    attribute_value = attribute_value.substring(0, attribute_value.length() - 1);
+		}
+		// We may have to strip ' marks off value - if it starts with ' and doesn't end with ' we read in more tokens until we get an ending '
+		if(attribute_value.startsWith(StaticStrings.SINGLE_QUOTE_CHARACTER)) {
+		    while (!attribute_value.endsWith(StaticStrings.SINGLE_QUOTE_CHARACTER) && tokenizer.hasMoreTokens()) {
+			attribute_value += " "+tokenizer.nextToken();
+		    }
+		    if (attribute_value.endsWith(StaticStrings.SINGLE_QUOTE_CHARACTER)) {
+			attribute_value = attribute_value.substring(1, attribute_value.length() - 1);
+		    }
+		}
+		if(attributes == null) {
+		    attributes = new HashMap();
+		}
+		attributes.put(attribute_name, attribute_value);
+		attribute_value = null;
+		attribute_name = null;
+	    }
+	    token = null;
+	}
+	tokenizer = null;
+    }
+
+    public String getAttribute(String attribute_name) {
+	String result = null;
+	if(attributes != null) {
+	    result = (String) attributes.get(attribute_name);
+	}
+	if(result == null) {
+	    result = "";
+	}
+	return result;
+    }
+
+    public String getElementName() {
+	return element_name;
+    }
+
+    public boolean isClosed() {
+	return is_closed;
+    }
+}
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/shell/GShellEvent.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/shell/GShellEvent.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/shell/GShellEvent.java	(revision 13928)
@@ -0,0 +1,120 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.shell;
+
+/** Title:        The Gatherer<br>
+ * Description:  The Gatherer: a tool for gathering and enriching digital collections.<br>
+ * Copyright:    Copyright (c) 2001<br>
+ * Company:      The University of Waikato<br>
+ * Written:        /  /01<br>
+ * Revised:      12/05/02 - Commented<br>
+ *               29/05/02 - Moved into correct package<br>
+ * @author John Thompson, Greenstone Digital Libraries
+ * @version 2.1 */
+import java.awt.AWTEvent;
+
+/** This class encapsulates all the information created by an event within a <strong>GShell</strong> process. */
+public class GShellEvent 
+    extends AWTEvent {
+    /** Allows some part of the program to prevent this message being processed by other parts. */
+    private boolean vetoed = false;
+    /** The status of the process at the completion of event. */
+    private int status = -1;
+    /** The process type (such as COPY, BUILD or IMPORT). */
+    private int type = -1;
+    /** Any message associated with this event. */
+    private String message = null;
+
+    /* Constructor.
+     * @param source The <strong>GShell</strong> that fired this message.
+     * @param id The event identifier as an <strong>int</strong>.
+     * @param type The process type as an <strong>int</strong>.
+     * @param message A <strong>String</strong> representing any message attatched with this event.
+     * @param status The status of the process post event, as an <strong>int</strong>.
+     */
+    public GShellEvent(Object source, int id, int type, String message, int status) {
+	super(source, id);
+	this.message = message;
+	this.status = status;
+	this.type = type;
+    }
+
+    /** Gets the message associated with this event.
+     * @return The message as a <strong>String</strong> or <i>null</i>.
+     */
+    public String getMessage() {
+	return message;
+    }
+
+    /** Gets the status associated with this event. This status can then be matched back to the constants in <strong>GShell</strong>.
+     * @return An <strong>int</strong> signifying the process status.
+     */ 
+    public int getStatus() {
+	return status;
+    }
+
+    /** Gets the type associated with this event. This type can then be matched back to the constants in <strong>GShell</strong>.
+     * @return An <strong>int</strong> signifying the process type.
+     */ 
+    public int getType() {
+	return type;
+    }
+
+    /** Determine if this event has been vetoed by some other part of the GLI
+     * @return true if the event has, and thus shouldn't be further processed, false otherwise.
+     */
+    public boolean isVetoed() {
+	return vetoed;
+    }
+
+    /** Change the message to be displayed by this event - usually from something technical so something easier to understand.
+     * @param message the new message as a String
+     */
+    public void setMessage(String message) {
+	this.message = message;
+    }
+
+    public String toString() {
+	return "org.greenstone.gatherer.shell.GShellEvent[" + message + "," + status + "," + type + "]";
+    }
+
+    /** Prevent this event being processed by other parts of the GLI.
+     */
+    public void veto() {
+	vetoed = true;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/shell/GShellListener.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/shell/GShellListener.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/shell/GShellListener.java	(revision 13928)
@@ -0,0 +1,70 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.shell;
+
+/**
+ * Title:        The Gatherer<br>
+ * Description:  The Gatherer: a tool for gathering and enriching digital collections.<br>
+ * Copyright:    Copyright (c) 2001<br>
+ * Company:      The University of Waikato<br>
+ * Written:        /  /01<br>
+ * Revised:      12/05/02 - Commented<br>
+ *               29/05/02 - Moved into correct package<br>
+ * @author John Thompson, Greenstone Digital Libraries
+ * @version 2.1
+ */
+import java.util.EventListener;
+
+/** This interface details the methods required of a class that wishes to listen to a <strong>GShell</strong>.
+ */
+public interface GShellListener 
+    extends EventListener {
+    /** All implementation of <i>GShellListener</i> must include this method so the listener can be informed of messages from the <strong>GShell</strong>.
+     * @param event A <strong>GShellEvent</strong> that contains, amoung other things, the message.
+     */
+    public void message(GShellEvent event);
+
+    /** All implementation of <i>GShellListener</i> must include this method so the listener can be informed when a <strong>GShell</strong> begins its task.
+     * @param event A <strong>GShellEvent</strong> that contains details of the initial state of the <strong>GShell</strong> before task comencement.
+     */
+    public void processBegun(GShellEvent event);
+
+    /** All implementation of <i>GShellListener</i> must include this method so the listener can be informed when a <strong>GShell</strong> completes its task.
+     * @param event A <strong>GShellEvent</strong> that contains details of the final state of the <strong>GShell</strong> after task completion.
+     */
+    public void processComplete(GShellEvent event);
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/shell/GShellProgressMonitor.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/shell/GShellProgressMonitor.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/shell/GShellProgressMonitor.java	(revision 13928)
@@ -0,0 +1,105 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.shell;
+
+/**
+ * Title:        The Gatherer<br>
+ * Description:  The Gatherer: a tool for gathering and enriching digital collections.<br>
+ * Copyright:    Copyright (c) 2001<br>
+ * Company:      The University of Waikato<br>
+ * Written:        /  /01<br>
+ * Revised:      12/05/02 - Commented<br>
+ *               29/05/02 - Moved into correct package<br>
+ * @author John Thompson, Greenstone Digital Libraries
+ * @version 2.1
+ */
+import java.awt.Component;
+import java.util.ArrayList;
+import org.greenstone.gatherer.gui.GProgressBar;
+
+/** When implemented, this interface allows another class to monitor the progress of a <strong>GShell</strong> process. Specifically implementing classes should be designed to take the textual output from the process and then translate that message into some quanitive measure of progress which can then be shown on the progress bar.
+ */
+public interface GShellProgressMonitor {
+    /** Method to register a new progress bar with this monitor.
+     * @param progress_bar The new <strong>GProgressBar</strong>.
+     */
+    public void addProgressBar(GProgressBar progress_bar);
+
+    /** Determine the script exit value according to the progress monitor. This gets around a problem where several script failures actually result with a successful exit value.
+     * @return A <i>int</i> with a value of zero if and only if the script was successful.
+     */
+    public int exitValue();
+
+    public GProgressBar getSharedProgress();
+
+    /** Method to retrieve whatever control is being used as the progress indicator. Usually a <strong>GProgressBar</strong> but there may be others implemented later.
+     * @return A <strong>Component</strong> on which the progress of the process is being displayed.
+     */
+    public Component getProgress();
+
+    public void messageOnProgressBar(String message);
+
+    /** Method to determine the state of the stop flag, which may be set by the visual component that created this monitor.
+     * @return A <strong>boolean</strong> indicating if the process has been asked to stop.
+     */
+    public boolean hasSignalledStop();
+
+    /** Inform the progress bar that it should programatically increment progress by one step. */
+    public void increment();
+
+    /** This method is used to 'feed in' a line of text captured from the process.
+     * @param queue what will be used as a queue of events, but what, at the moment, should only have one event in it
+     */
+    public void process(ArrayList queue);
+
+    public void reset();
+
+    public void saving();
+
+    /** Since the creator of this process monitor is actually in the GUI, this class provides the simpliest way to send a cancel process message between the two.
+     * @param state The desired state of the stop flag as a <strong>boolean</strong>.
+     */
+    public void setStop(boolean state);
+
+    /** This method resets this monitor to the start, reseting the process parsing and progress bar.
+     */
+    public void start();
+
+    /** This method indicates the process is complete. 
+     */
+    public void stop();
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/AppendLineOnlyFileDocument.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/AppendLineOnlyFileDocument.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/AppendLineOnlyFileDocument.java	(revision 13928)
@@ -0,0 +1,982 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Greenstone Librarian Interface (GLI) application, 
+ * part of the Greenstone digital library software suite from the New 
+ * Zealand Digital Library Project at the University of Waikato, 
+ * New Zealand.
+ *
+ * Author: John Thompson, Greenstone Project, New Zealand Digital Library, 
+ *         University of Waikato
+ *         http://www.nzdl.org
+ *
+ * Copyright (C) 2004 New Zealand Digital Library, University of Waikato
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+
+package org.greenstone.gatherer.util;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.text.*;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.gui.GLIButton;
+
+/** A Document whose underlying data is stored in a RandomAccessFile, and whose Element implementations lack the memory hogging problems associated with anything that extends the AbstractDocument class. This Document, for reasons of time constraints and sanity, only provides an editting ability of appending new lines to the end of the current document, perfect for our logging needs, completely useless for text editing purposes. Furthermore, since the append actions tend to somewhat swamp the IO, I'll temporarily store strings in the structure model, and write them out using a separate thread. 
+ * @author John Thompson, Greenstone Project, New Zealand Digital Library, University of Waikato
+ * @version 2.41 final
+ */
+public class AppendLineOnlyFileDocument
+    implements Document {
+    /** A default string to append at the start of each log file. Of special note is the beginning '.' character that will, upon completion of the import/build process, be replaced with a letter indicating the final status of this build attempt. */
+    static final private String GLI_HEADER_STR = ".";
+    /** The root element of the document model. */
+    private AppendLineOnlyFileDocumentElement root_element;
+    /** The current owner of this document, useful for callbacks when certain tasks are complete. */
+    private AppendLineOnlyFileDocumentOwner owner;
+    /** Is this document a build log, and hence has some extra functionality, of just a straight log. */
+    private boolean build_log = false;
+    /** A list of listeners attached to this document. */
+    private EventListenerList listeners_list;
+    /** This properties hash map allows you to store any metadata about this document for later review. */
+    private HashMap properties;
+    /** Indicates the current length of the underlying file (which may not equal the current number of characters in the document). */
+    private long length;
+    /** The random access file which will back this document model. */
+    private RandomAccessFile file;
+    /** The filename given to the underlying file. */
+    private String filename;
+    /** An independant thread responsible for writing the 'in memory' contents of the document model to the random access file as appropriate. This is done so IO lag does not effect the gui as much as it used to. */
+    private WriterThread writer;
+
+    
+    public AppendLineOnlyFileDocument(String filename) {
+	this(filename, true);
+    }
+
+    /** The constructor is responsible for creating several necessary data structures as well as opening the random access file. When it creates the new file, as it is wont to do, it will immediately add the special header line defined above.
+     * @param filename the absolute path name of the file as a String
+     * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.AppendLineOnlyFileDocumentElement
+     * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.WriterThread
+     * @see org.greenstone.gatherer.util.StaticStrings#NEW_LINE_CHAR
+     */
+    public AppendLineOnlyFileDocument(String filename, boolean build_log) {
+	DebugStream.println("Creating log: " + filename);
+	// Initialization 
+	this.build_log = build_log;
+	this.filename = filename;
+	this.listeners_list = new EventListenerList();
+	this.properties = new HashMap();
+	this.writer = new WriterThread();
+	writer.start();
+	// Open underlying file
+	try {
+	    file = new RandomAccessFile(filename, "rw");
+	    // Create the root element.
+	    length = file.length();
+	    root_element = new AppendLineOnlyFileDocumentElement();
+	    // Now quickly read through the underlying file, building an Element for each line.
+	    long start_offset = 0L;
+	    file.seek(start_offset);
+	    int character = -1;
+	    while((character = file.read()) != -1) {
+		if(character == StaticStrings.NEW_LINE_CHAR) {
+		    long end_offset = file.getFilePointer();
+		    Element child_element = new AppendLineOnlyFileDocumentElement(start_offset, end_offset);
+		    root_element.add(child_element);
+		    child_element = null;
+		    start_offset = end_offset;
+		}
+	    }
+	    // If there we no lines found, and we are a build log, then append the file header.
+	    if(build_log && root_element.getElementCount() == 0) {
+		appendLine(GLI_HEADER_STR);
+	    }
+	}
+	catch (Exception error) {
+	    DebugStream.printStackTrace(error);
+	}
+    }
+
+    /** Adds a document listener for notification of any changes. 
+     * @param listener the new DocumentListener to keep track of
+     */
+    public void addDocumentListener(DocumentListener listener) {
+	///ystem.err.println("addDocumentListener(" + listener + ")");
+	listeners_list.add(DocumentListener.class, listener);
+    }
+
+    /** Append some content after the document. 
+     * @param str the String to add as a new line in the document
+     * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.AppendLineOnlyFileDocumentElement
+     * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.AppendLineOnlyFileDocumentEvent
+     * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.WriterThread#queue
+     */
+    public void appendLine(String str) {
+	// Ensure the string ends in a newline
+	try {
+	    if (!str.endsWith("\n")) {
+		str = str + "\n";
+	    }
+	    int str_length = str.getBytes("UTF-8").length;
+	    long start_offset = length;
+	    long end_offset = start_offset + (long) str_length;
+	    length = length + str_length;
+	    // Create a new element to represent this line
+	    AppendLineOnlyFileDocumentElement new_line_element = new AppendLineOnlyFileDocumentElement(start_offset, end_offset, str);
+	    root_element.add(new_line_element);
+	    // Queue the content to be written.
+	    writer.queue(new_line_element);
+	    // Now fire an event so everyone knows the content has changed.
+	    DocumentEvent event = new AppendLineOnlyFileDocumentEvent(new_line_element, (int)start_offset, str_length, DocumentEvent.EventType.INSERT);
+	    Object[] listeners = listeners_list.getListenerList();
+	    for (int i = listeners.length - 2; i >= 0; i = i - 2) {
+		if (listeners[i] == DocumentListener.class) {
+		    ((DocumentListener)listeners[i+1]).insertUpdate(event);
+		}
+	    }
+	    listeners = null;
+	    event = null;
+	    new_line_element = null;
+	}
+	catch(Exception error) {
+	    DebugStream.printStackTrace(error);
+	}
+    }
+
+    /** Returns a position that will track change as the document is altered. 
+     * @param offs the position offset as an int
+     * @return the Position to be monitored
+     *  @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.AppendLineOnlyFileDocumentPosition
+     */
+    public Position createPosition(int offs)  {
+	return new AppendLineOnlyFileDocumentPosition(offs);
+    }
+
+    /** The destructor is implemented to ensure the current log file has finished transferring from memory to disk, and that the random access file is properly closed, before GLI exits.
+     * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.WriterThread#finish
+     */
+    public void destroy() {
+	try {
+	    writer.finish();
+	    file.close();
+	}
+	catch(Exception exception) {
+	    DebugStream.println("Exception in AppendLineOnlyFileDocument.destroy() - unexpected");
+	    DebugStream.printStackTrace(exception);
+	}
+    }
+
+    /** Gets the default root element for the document model. 
+     * @return the root Element of this document
+     */
+    public Element getDefaultRootElement() {
+	return root_element;
+    }
+
+    /** Returns the length of the data. 
+     * @return the length as an int (not a long)
+     */
+    public int getLength() {
+	return (int) length;
+    }
+
+    /** A version of get length which returns the offset to the start of the last line in the document.
+     * @return the offset length as an int
+     * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.AppendLineOnlyFileDocumentElement
+     */
+    public int getLengthToNearestLine() {
+	AppendLineOnlyFileDocumentElement last_element = (AppendLineOnlyFileDocumentElement)root_element.getElement(root_element.getElementCount() - 1);
+	if(last_element != null ) {
+	    return last_element.getStartOffset();
+	}
+	else {
+	    return (int) length; // The best we can do.
+	}
+    }
+	
+    /** Retrieve a property that has previously been set for this document.
+     * @param key the key String under which the vaue is stored
+     * @return the value which is also a String, or null if no such value
+     */
+    public Object getProperty(Object key) {
+	return properties.get(key);
+    }
+
+    /** Determine if the writer thread is still running, ie a log file which is currently open for writing
+     * @return true if the writer is still active, false otherwise
+     * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.WriterThread#isStillWriting
+     */
+    public boolean isStillWriting() {
+	return writer.isStillWriting();
+    }
+
+    /** Gets a sequence of text from the document. 
+     * @param offset the starting offset for the fragment of text required, as an int
+     * @param l the length of the text, also as an int
+     * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.AppendLineOnlyFileDocumentElement
+     * @see org.greenstone.gatherer.util.StaticStrings#EMPTY_STR
+     */
+    public String getText(int offset, int l) 
+	throws BadLocationException {
+
+	if (l == 0) {
+	    return "";
+	}
+
+	try {
+	    return read((long) offset, l);
+	}
+	catch (Exception ex) {
+	}
+
+	return "";
+
+//  	// System.err.println("AppendLineOnlyFileDocument::getText() request...");
+//  	String request = "getText(" + offset + ", " + l + ")";
+//  	///ystem.err.println(request);
+//  	String text = null;
+//  	if(text == null || text.length() < l) {
+//  	    try {
+//  		int file_length = (int) file.length();
+//  		///ystem.err.println("file_length = " + file_length + ", length = " + length);
+//  		if(l == 0) {
+//  		    text = StaticStrings.EMPTY_STR;
+//  		}
+//  		else if(0 <= offset && offset < length && (offset + l) <= length) {
+//  		    if(offset < file_length) {
+//  			text = read((long)offset, l);
+//  			if(text.length() != l) {
+//  			    ///ystem.err.println("Asked for " + l + " characters of text. But only read " + text.length());
+//  			    throw new BadLocationException("AppendLineOnlyDocument.getText(" + offset + ", " + l + ")", offset); 
+//  			}
+//  		    }
+//  		    else {
+//  			int index = root_element.getElementIndex(offset);
+//  			if(index < root_element.getElementCount()) {
+//  			    AppendLineOnlyFileDocumentElement element = (AppendLineOnlyFileDocumentElement) root_element.getElement(index);
+//  			    text = element.getContent();
+//  			}
+//  			else {
+//  			    ///ystem.err.println("Index is " + index + " but there are only " + root_element.getElementCount() + " children.");
+//  			    throw new BadLocationException("AppendLineOnlyDocument.getText(" + offset + ", " + l + ")", offset); 
+//  			}
+//  		    }
+		    
+//  		}
+//  	    }
+//  	    catch (IOException error) {
+//  		DebugStream.printStackTrace(error);
+//  	    }
+//  	    if(text == null) {
+//  		///ystem.err.println("Text is null.");
+//  		throw new BadLocationException("AppendLineOnlyDocument.getText(" + offset + ", " + l + ")", offset);
+//  	    }
+//  	}
+//  	request = null;
+//  	return text;
+    }
+
+    /** Fetches the text contained within the given portion of the document. 
+     * @param offset the starting offset of the desired text fragment, as an int
+     * @param length the length of the text also as an int
+     * @param txt the Segment into which the text fragment should be placed
+     */
+    public void getText(int offset, int length, Segment txt) 
+	throws javax.swing.text.BadLocationException  {
+	String str = getText(offset, length);
+	txt.array = str.toCharArray();
+	txt.count = str.length();
+	txt.offset = 0;
+	str = null;
+    }
+	
+    /** Set a property for this document.
+     * @param key the key to store the value under, as a String
+     * @param value the property value itself also as a String
+     */
+    public void putProperty(Object key, Object value) {
+	properties.put(key, value);
+    }
+
+    /** Determine if this document is ready by testing if it has an open descriptor to the random access file.
+     * @return true if the file exists thus the document is ready, false otherwise
+     */
+    public boolean ready() {
+	return (file != null);
+    }
+	
+    /** Removes a document listener.
+     * @param listener the Document we wish to remove
+     */
+    public void removeDocumentListener(DocumentListener listener) {
+	listeners_list.remove(DocumentListener.class, listener);
+    }
+
+    /** Whenever the user requests a change of the loaded log, this method is called to ensure the previous log has been completely written to file. Note that this only garuentees that text fragments currently queued for writing will be correctly written - while the behaviour is undefined for text fragments added after this call (some may write depending on several race conditions).
+     * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.WriterThread#exit
+     * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.WriterThread#finish
+     */
+    public void setExit() {
+	writer.exit();
+	writer.finish();
+    }
+
+    /** Establish the current owner of this document.
+     * @param owner the current AppendLineOnlyFileDocumentOwner
+     */
+    public void setOwner(AppendLineOnlyFileDocumentOwner owner) {
+	this.owner = owner;
+    }
+
+    /** To record the final state of the logging process we reserve a single character at the start of the file, and then replace it when the build process is complete.
+     * @param character the final status char to replace the X at the start of the log
+     */
+    public synchronized void setSpecialCharacter(char character) {
+	if(build_log) {
+	    try {
+		file.seek(0L);
+		file.write((int)character);
+	    }
+	    catch (Exception error) {
+		DebugStream.printStackTrace(error);
+	    }
+	}
+    }
+
+    /** Request a text representation of this document which currently returns the filename.
+     * @return the text as a String
+     */
+    public String toString() {
+	return filename;
+    }
+
+    /** This method reads a fragment of text from the underlying random access file. It is synchronized so that the file isn't being written to at the same time.
+     * @param start_offset the offset within the file to set the read pointer at, as a long
+     * @param l the number of characters to read as an int
+     */
+    private synchronized String read(long start_offset, int l) 
+	throws IOException {
+	//print("read(" + start_offset + ", " + l + ")... ");
+	byte[] buffer = new byte[l];
+	file.seek(start_offset);
+	int result = file.read(buffer, 0, l);
+	return new String(buffer, "UTF-8");
+	//print("read() complete");
+    }
+
+    /** This methods writes a fragment of text to the underlying random access file. It is synchronized so that the file isn't being read from at the same time.
+     * @param start_offset the offset within the file to set the write pointer at, as a long
+     * @param end_offset the final offset of the new text fragment within the file, as a long. This is used to extend the file to be the correct length
+     * @param str the String to be written
+     * @param l the number of characters from str to be written, as an int
+     */
+    private synchronized void write(long start_offset, long end_offset, String str, int l) 
+	throws IOException {	
+	//print("write(" + start_offset + ", " + end_offset + ", " + str + ", " + l + ")");
+	file.setLength(end_offset);
+	file.seek(start_offset);
+	file.write(str.getBytes("UTF-8"), 0, l);
+	//print("write() complete");
+    }
+
+    /** This class provides the building-block for the document model. Each element is a line in the document, or has no content but contains several child elements. Due to the basic nature of what we are modelling only the root node has children. */
+    private class AppendLineOnlyFileDocumentElement
+	extends ArrayList
+	implements Element {
+	/** Our parent Element. */
+	private Element parent;
+	/** The offset to the end of our fragment(s) of text, in respect to the entire document. */
+	private long end;
+	/** The offset to the start of our fragment(s) of text, in respect to the entire document. */
+	private long start;
+	/** If we haven't been written to file yet, this contains the text fragment itself. */
+	private String content;
+
+	/** Construct a new root element, which can have no content, but calculates its start and end from its children. */
+	public AppendLineOnlyFileDocumentElement() {
+	    super();
+	    this.end = 0L;
+	    this.parent = null;
+	    this.start = 0L;
+	}
+
+	/** Construct a new element, whose content is found in bytes start to end - 1 within the random access file backing this document.
+	 * @param start the starting offset as a long
+	 * @param end the ending offset as a long
+	 */
+	public AppendLineOnlyFileDocumentElement(long start, long end) {
+	    super();
+	    this.end = end;
+	    this.parent = null;
+	    this.start = start;
+	}
+
+	/** Construct a new element, whose content is provided, but should at some later time be written to bytes start to end - 1 in the random access file backing this document.
+	 * @param start the starting offset as a long
+	 * @param end the ending offset as a long
+	 * @param content the text fragment String which we represent in the model
+	 */
+	public AppendLineOnlyFileDocumentElement(long start, long end, String content) {
+	    super();
+	    this.content = content;
+	    this.end = end;
+	    this.parent = null;
+	    this.start = start;
+	}
+
+	/** Add the given node as one of our children.
+	 * @param child the new child Element
+	 */
+	public void add(Element child) {
+	    super.add(child);
+	    ((AppendLineOnlyFileDocumentElement)child).setParent(this);
+	}
+
+	/** Having written the content to file this method removes it from the element. */ 
+	public void clearContent() {
+	    content = null;
+	}
+
+	/** This document does not allow content markup. 
+	 * @return always returns null
+	 */
+	public AttributeSet getAttributes() {
+	    return null;
+	}
+
+	/** Retrieve the current content of this element, which may be the text fragment this element represents.
+	 * @return either the text fragment as a String, or null if the fragment has already been written to disk
+	 */
+	public String getContent() {
+	    return content;
+	}
+
+	/** Fetches the document associated with this element. 
+	 * @return the AppendLineOnlyDocument containing this element
+	 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument
+	 */
+	public Document getDocument() {
+	    return AppendLineOnlyFileDocument.this;
+	}
+
+	/** Fetches the child element at the given index. 
+	 * @param index the int index of the element to retrieve
+	 * @return the requested Element
+	 */
+	public Element getElement(int index) {
+	    Element element;
+	    if(0 <= index && index < size()) {
+		element = (Element) get(index);
+	    }
+	    else {
+		throw new IndexOutOfBoundsException("AppendLineOnlyDocument.AppendLineOnlyFileDocumentElement.getElement(" + index + ")");
+	    }
+	    return element;
+	}
+          
+	/** Gets the number of child elements contained by this element. 
+	 * @return an int
+	 */
+	public int getElementCount() {
+	    return size();
+	}
+
+	/** Gets the child element index closest to the given offset.
+	 * @param offset the offset within the text of the document, which due to the way the model is built must fll within the bounds of one of our child nodes
+	 * @return the closest index as an int
+	 */
+	public int getElementIndex(int offset) {
+	    int index = -1;
+	    if(parent != null) {
+		index = -1;
+	    }
+	    else if(offset < 0) {
+		index = 0;
+	    }
+	    else if(offset >= length) {
+		index = size() - 1;
+	    }
+	    else {
+		int size = size();
+		for(int i = 0; index == -1 && i < size; i++) {
+		    Element child = (Element) get(i);
+		    if(child.getStartOffset() <= offset && offset < child.getEndOffset()) {
+			index = i;
+		    }
+		    child = null;
+		}
+	    }
+	    return index;
+	}
+          
+	/** Fetches the offset from the beginning of the document that this element ends at. 
+	 * @return the offset as an int
+	 */
+	public int getEndOffset() {
+	    if(parent != null) {
+		return (int) end;
+	    }
+	    // Return the Documents length.
+	    else {
+		return (int) length;
+	    }
+	}
+          
+	/** This method retrieves the name of the element, however names are not important in this document so the name is always an empty string.
+	 * @return an empty String
+	 * @see org.greenstone.gatherer.util.StaticStrings#EMPTY_STR
+	 */
+	public String getName() {
+	    return StaticStrings.EMPTY_STR;
+	}
+          
+	/** Fetches the parent element. 
+	 * @return the parent Element
+	 */
+	public Element getParentElement() {
+	    return parent;
+	}
+          
+	/** Fetches the offset from the beginning of the document that this element begins at. 
+	 * @return the offset as an int
+	 */
+	public int getStartOffset() {
+	    if(parent != null) {
+		return (int) start;
+	    }
+	    else {
+		return 0;
+	    }
+	}
+          
+	/** Since this is a very simple model, only the root node can have children. All the children are leaves. 
+	 * @return true if this is the root node, false otherwise
+	 */
+	public boolean isLeaf() {
+	    return (parent != null);
+	} 
+
+	/** Establish the parent of this element
+	 * @param parent the parent Element
+	 */
+	public void setParent(Element parent) {
+	    this.parent = parent;
+	}
+    }
+    // AppendLineOnlyFileDocumentElement
+
+    /** This event is created to encapsulate the details of some change to the document. */
+    private class AppendLineOnlyFileDocumentEvent
+	implements DocumentEvent {
+	/** The type of change event. */
+	private DocumentEvent.EventType type;
+	/** The element this change occured to, or in. */
+	private AppendLineOnlyFileDocumentElement element;
+	/** Another encapsulating class which contains further detail about the change itself. */
+	private AppendLineOnlyFileDocumentElementChange element_change;
+	/** The length of the text fragment affected by the change. */
+	private int len;
+	/** The offset within the document of the start of the change. */
+	private int offset;
+	
+	/** Construct a new AppendLineOnlyFileDocumentEvent given the pertinant details.
+	 * @param element the AppendLineOnlyFileDocumentElement affected by this change
+	 * @param offset the offset within the document of the start of the change
+	 * @param len the length of the text fragment affected by the change
+	 * @param type the type of change event
+	 */
+	public AppendLineOnlyFileDocumentEvent(AppendLineOnlyFileDocumentElement element, int offset, int len, DocumentEvent.EventType type) {
+	    this.element = element;
+	    this.element_change = null;
+	    this.len = len;
+	    this.offset = offset;
+	    this.type = type;
+	}
+
+	/** Retrieve the docment which generated this event.
+	 * @return the Document
+	 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument
+	 */
+	public Document getDocument() {
+	    return AppendLineOnlyFileDocument.this;
+	}
+
+	/** Retrieve the length of the change.
+	 * @return the length as an int
+	 */
+	public int getLength() {
+	    return len;
+	}
+
+	/** Retrieve the start offset of the change.
+	 * @return the offset as an int
+	 */
+	public int getOffset() {
+	    return offset;
+	}
+
+	/** Retrieve the type of change.
+	 * @return the type as a DocumentEvent.EventType
+	 */
+	public DocumentEvent.EventType getType() {
+	    return type;
+	}
+
+	/** Retrieve the element change object which further describes the changes. Of course given that we only allow the appending of new lines there really is only one type of event.
+	 * @param elem implementation side-effect
+	 * @return a DocumentEvent.ElementChange
+	 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.AppendLineOnlyFileDocumentEvent.AppendLineOnlyFileDocumentElementChange
+	 */
+	public DocumentEvent.ElementChange getChange(Element elem) {
+	    if(element_change == null) {
+		element_change = new AppendLineOnlyFileDocumentElementChange();
+	    }
+	    return element_change;
+	}
+
+	/** A pretty unexciting implementation of the document element change class. This usually describes the myriad of possible change events that can occur on a document. However we only allow line appends so there is really only one type of change. */
+	private class AppendLineOnlyFileDocumentElementChange
+	    implements DocumentEvent.ElementChange {
+	    /** This array always contains the one Element that was appended. */ 
+	    private Element[] children_added;
+	    /** This Element array is always empty. */
+	    private Element[] children_removed;
+	    /** The index of the affected element within its parents children. */
+	    private int index;
+	    /** Construct a new AppendLineOnlyFileDocumentElementChange with the default 'append line' details. */
+	    public AppendLineOnlyFileDocumentElementChange() {
+		children_added = new Element[1];
+		children_added[0] = element;
+		children_removed = new Element[0];
+		index = root_element.indexOf(element);
+	    }
+
+	    /** Gets the child element that was appended to the parent element. 
+	     * @return an Element[] containing the added element
+	     */
+	    public Element[] getChildrenAdded() {
+		return children_added;
+	    }
+
+	    /** This model does not allow elements to be removed.
+	     * @return an Element[] containing nothing
+	     */
+	    public Element[] getChildrenRemoved() {
+		return children_removed;
+	    }
+          
+	    /** Returns the root element, as our document structure is only two layers deep.
+	     * @return the root Element
+	     */
+	    public Element getElement() {
+		return root_element;
+	    }
+          
+	    /** Fetches the index within the element represented. 
+	     * @return an int specifying the index of change within the root element
+	     */
+	    public int getIndex() {
+		return index;
+	    }
+	}
+	// AppendLineOnlyFileDocumentElementChange
+    }
+    // AppendLineOnlyFileDocumentEvent
+    
+    /** This class denoted a position within our document by an offset. Quite possibly the last interesting class I've ever had to deal with, but you have to implement it so here goes... */
+    private class AppendLineOnlyFileDocumentPosition
+	implements Position {
+	/** The offset within our document. */
+	private int offset;
+	/** Construct a new position given an offset.
+	 * @param offset the offset as an int
+	 */
+	public AppendLineOnlyFileDocumentPosition(int offset) {
+	    this.offset = offset;
+	}
+	/** Retrieve the offset of this position.
+	 * @return the offset as an int
+	 */
+	public int getOffset() {
+	    return offset;
+	}
+    }
+    // AppendLineOnlyFileDocumentPosition
+    
+    /** This thread is responsible to writing the in memory text fragment contents of the document elements out to the random access file. The writing proceedure is implemented this way so that the gui doesn't take the performance hit of the IO. */
+    private class WriterThread
+	extends Thread {
+	/** When true was are being told to assume the contents of the queue are now static, and once completed the queue will be empty (and not expecting any new jobs). Used to finish the queue before the GLI exits. */
+	private boolean empty_queue;
+	/** Setting this flag to true tells the writer to stop regardless of whether there are items left on the queue. */
+	private boolean exit;
+	/** When the writer thread is busy writing content to the file this flag is set to true. */
+	private boolean running;
+	/** The fragment queue as a Vector (for thread reasons). */
+	private Vector queue;
+	/** Construct a new writer thread with an initially empty queue. */
+	public WriterThread() {
+	    super("WriterThread");
+	    empty_queue = false;
+	    exit = false;
+	    queue = new Vector();
+	}
+
+	/** This method is called to ask the writer thread to die after it finishes any current write proceceedure. */
+	public synchronized void exit() {
+	    //print("WriterThread.exit() start");
+	    exit = true;
+	    notify();
+	    //print("WriterThread.exit() complete");
+	}
+
+	/** When this returns there are no jobs waiting in the queue. */
+	public void finish() {
+	    if(!queue.isEmpty() && running) {
+		///ystem.err.println("Somethings gone wrong, as there are still " + queue.size() + " items to be written out and yet the thread seems to be waiting.");
+		empty_queue = true;
+		run();
+	    }
+	}
+
+	/** Determine if the writer is currently running.
+	 * @return true if it is, false if it has been exited or if it was never running in the first place (an old log)
+	 */
+	public boolean isStillWriting() {
+	    return running;
+	}
+
+	/** The run method of this thread checks if there are any document elements queued to be written to file, and then writes them as necessary.
+	 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument
+	 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.AppendLineOnlyFileDocumentElement
+	 */
+	public void run() {
+	    exit = false;
+	    running = true;
+	    while(!exit) {
+		if(!queue.isEmpty()) { 
+		    AppendLineOnlyFileDocumentElement element = (AppendLineOnlyFileDocumentElement) queue.remove(0);
+		    // Write the content to file.
+		    String content = element.getContent();
+		    if(content != null) {
+			try {
+			    write(element.getStartOffset(), element.getEndOffset(), content, content.getBytes("UTF-8").length);
+			}
+			catch(Exception error) {
+			    DebugStream.printStackTrace(error);
+			}
+			element.clearContent();
+		    }
+		}
+		else if(empty_queue) {
+		    exit = true;
+		}
+		else {
+		    synchronized(this) {
+			try {
+			    print("WriterThread.wait() start");
+			    wait();
+			}
+			catch(Exception exception) {
+			}
+			print("WriterThread.wait() complete");
+		   }
+		}
+	    }
+	    print("WriterThread completely finished. Exiting.");
+	    running = false;
+	    if(owner != null) {
+		owner.remove(AppendLineOnlyFileDocument.this);
+	    }
+	}
+
+	/** Enqueue a document element to have its text content written to file.
+	 * @param element the Element needing its content written out
+	 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.AppendLineOnlyFileDocumentElement#getContent
+	 */
+	public synchronized void queue(Element element) {
+	    print("WriterThread.queue(): " + ((AppendLineOnlyFileDocumentElement)element).getContent());
+	    queue.add(element);
+	    notify();
+	}
+    }
+    // WriterThread
+
+    // ***** METHODS WE ARE NOW IGNORING BECAUSE WE ARE VIRTUALLY READ-ONLY *****
+    
+    /** Not implemented. Add a new undo listener to this document.
+     * @param listener UndoableEditListener
+     */
+    public void addUndoableEditListener(UndoableEditListener listener) {}
+    	
+    /** Not implemented. Get the last position in the document.
+     * @return null
+     */
+    public Position getEndPosition() { return null; }
+
+    /** Not implemented. Gets all root elements defined.
+     * @return null
+     */
+    public Element[] getRootElements() { return null; }
+	
+    /** Not implemented. Retrieve the first position in the document.
+     * @return null
+     */
+    public Position getStartPosition() { return null; }
+    
+    /** Not implemented. Insert a text fragment into our document.
+     * @param offset int
+     * @param str String
+     * @param a AttributeSet
+     */
+    public void insertString(int offset, String str, AttributeSet a) {}
+
+    /** Not implemented. Removes some content from the document. 
+     * @param offs int
+     * @param len int
+     */
+    public void remove(int offs, int len) {}
+
+    /** Not implemented. Removes an undo listener. 
+     * @param listener UndoableEditListener
+     */
+    public void removeUndoableEditListener(UndoableEditListener listener) {}
+    
+    /** Not implemented. Renders a runnable apparently - whatever that means. 
+     * @param r Runnable
+     */
+    public void render(Runnable r) {}
+
+    // DEBUG ONLY
+
+    /** Print a message to the GLI debug file stream.
+     * @param message the message to be written as a String
+     */
+    static synchronized public void print(String message) {
+	if (message.endsWith("\n")) {
+	    DebugStream.print(message); 
+	}
+	else {
+	    DebugStream.println(message); 
+	}
+    }
+
+    /** Create a test document with the ability to add new lines of text as necessary.
+     * @param args the initial starting arguments as a String array
+     * @see org.greenstone.gatherer.gui.GLIButton
+     * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument
+     * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.ReadButtonListener
+     */
+    static public void main(String[] args) {
+	JFrame frame = new JFrame("AppendLineOnlyFileDocument Test");
+	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+	frame.setSize(640,480);
+	JPanel content = (JPanel) frame.getContentPane();
+	
+	//PlainDocument document = new PlainDocument();
+	//document.setAsynchronousLoadPriority(-1);
+	final AppendLineOnlyFileDocument document = new AppendLineOnlyFileDocument("temp.txt");
+
+	final JTextArea text_area = new JTextArea(document);
+
+	JButton read_button = new GLIButton("Read Huge File");
+	read_button.addActionListener(new ReadButtonListener(document));
+	content.setLayout(new BorderLayout());
+	content.add(new JScrollPane(text_area), BorderLayout.CENTER);
+	content.add(read_button, BorderLayout.SOUTH);
+
+	frame.setVisible(true);
+    }
+
+    /** Listens for actions on the read button, and if detected creates a new ReadTask to test the document. 
+     * @author John Thompson, Greenstone Project, New Zealand Digital Library, University of Waikato
+     * @version 2.41 final
+     */
+    static private class ReadButtonListener
+	implements ActionListener {
+	/** The AppendLineOnlyFileDocument object we are testing. */
+	private AppendLineOnlyFileDocument document;
+
+	/** All the constructor does is take a copy of the document to test.
+	 * @param document the Document
+	 */
+	public ReadButtonListener(AppendLineOnlyFileDocument document) {
+	    this.document = document;
+	}
+
+	/** When the button is clicked this method is called to create the new task and run it.
+	 * @param event an ActionEvent containing further information about the button click
+	 * @see org.greenstone.gatherer.util.AppendLineOnlyFileDocument.ReadTask
+	 */
+	public void actionPerformed(ActionEvent event) {
+	    Thread task = new ReadTask(document);
+	    task.start();
+	}
+    }
+
+    /** This threaded task opens a large document, aptly named 'big.txt', and then bombards the document object we are testing with lines from the file. This file should be several megs (such as Alice or TREC) to fully test functionality, thread conditions etc. 
+     * @author John Thompson, Greenstone Project, New Zealand Digital Library, University of Waikato
+     * @version 2.41 final
+     */ 
+    static private class ReadTask
+	extends Thread {
+	/** The AppendLineOnlyFileDocument object we are testing. */
+	private AppendLineOnlyFileDocument document;
+
+	/** Construct a new task which will perform testing on the given document.
+	 * @param document the AppendLineOnlyFileDocument to append lines to
+	 */
+	public ReadTask(AppendLineOnlyFileDocument document) {
+	    super("LoadHugeFileThread");
+	    this.document = document;
+	}
+
+	/** The runable part of this class opens the file, then reads it in a line at a time, appending these lines to the ever growing document. */
+	public void run() {
+	    // Load the specified document
+	    try {
+		BufferedReader in = new BufferedReader(new FileReader(new File("big.txt")));
+		String line;
+		
+		while ((line = in.readLine()) != null) {
+		    document.appendLine(line);
+		    try {
+			// Wait a random ammount of time.
+			synchronized(this) {
+			    //print("LoadHugeFileThread.wait() start");
+			    wait(100);
+			    //print("LoadHugeFileThread.wait() complete");
+			}
+		    }
+		    catch(Exception error) {
+			error.printStackTrace();
+		    }
+		}
+		in.close();
+	    }
+	    catch (Exception error) {
+		error.printStackTrace();
+	    }
+	}
+    }
+    // ReadTask
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/AppendLineOnlyFileDocumentOwner.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/AppendLineOnlyFileDocumentOwner.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/AppendLineOnlyFileDocumentOwner.java	(revision 13928)
@@ -0,0 +1,46 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Greenstone Librarian Interface (GLI) application, 
+ * part of the Greenstone digital library software suite from the New 
+ * Zealand Digital Library Project at the University of Waikato, 
+ * New Zealand.
+ *
+ * Author: John Thompson
+ *         Greenstone Project, New Zealand Digital Library
+ *         University of Waikato
+ *         http://www.nzdl.org
+ *
+ * Copyright (C) 2004 New Zealand Digital Library, University of Waikato
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.util;
+
+
+/** Any class that wants to act as the owner of an AppendLineOnlyFileDocument has to implement this.
+ * @author John Thompson, Greenstone Project, New Zealand Digital Library, University of Waikato
+ * @version 2.41 final
+ */
+public interface AppendLineOnlyFileDocumentOwner {
+    /** Remove the given document from the owner. The is called by the document itself when it no longer needs a hanging reference in the owner class.
+     * @param document the AppendLineOnlyFileDocument to remove
+     */
+    public void remove(AppendLineOnlyFileDocument document);
+}
+
+
+
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/ArrayTools.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/ArrayTools.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/ArrayTools.java	(revision 13928)
@@ -0,0 +1,341 @@
+/* GPL_HEADER */
+package org.greenstone.gatherer.util;
+
+/**************************************************************************************
+ * Title:        Gatherer
+ * Description:  The Gatherer: a tool for gathering and enriching a digital collection.
+ * Company:      The University of Waikato
+ * Written:        /  /01
+ * Revised:      16/08/02 Improved
+ **************************************************************************************/
+import java.awt.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.filechooser.*;
+import org.w3c.dom.*;
+
+/** This utility class contains a series of static methods for common array type manipulations including appending, casting and changing between containers.
+ * @author John Thompson
+ * @version 2.3
+ */
+public class ArrayTools {
+
+    /** Append a Component onto an array of Components. */
+    static public Component[] add(Component[] a, Component b) {
+	Component[] c = null;
+	if(a != null && b != null) {
+	    c = new Component[a.length + 1];
+	    System.arraycopy(a, 0, c, 0, a.length);
+	    c[c.length - 1] = b;
+	}
+	else if(a == null && b != null) {
+	    c = new Component[1];
+	    c[0] = b;
+	}
+	else if(a != null && b == null) {
+	    c = a;
+	}
+	return c;
+    }
+    /** This method efficiently appends a new element onto the end of a element array.
+     * @param a The initial <strong>Element[]</strong>.
+     * @param b The new <strong>Element</strong>.
+     * @return An <strong>Element[]</strong> containing a followed by b.
+     */
+    static public Element[] add(Element a[], Element b) {
+	Element[] c = null;
+	if(a != null && b != null) {
+	    c = new Element[a.length + 1];
+	    System.arraycopy(a, 0, c, 0, a.length);
+	    c[c.length - 1] = b;
+	}
+	else if(a == null && b != null) {
+	    c = new Element[1];
+	    c[0] = b;
+	}
+	else if(a != null && b == null) {
+	    c = a;
+	}
+	return c;
+    }
+    /** This method efficently appends one element array onto the end of another.
+     * @param a The initial <strong>Element[]</strong>.
+     * @param b The <strong>Element[]</strong> to append.
+     * @return An <strong>Element[]</strong> containing a followed by b.
+     */
+    static public Element[] add(Element a[], Element b[]) {
+	Element[] c = null;
+	if(a != null && b != null) {
+	    c = new Element[a.length + b.length];
+	    System.arraycopy(a, 0, c, 0, a.length);
+	    System.arraycopy(b, 0, c, a.length, b.length);
+	}
+	else if(a == null && b != null) {
+	    c = b;
+	}
+	else if(a != null && b == null) {
+	    c = a;
+	}
+	return c;
+    }
+    /** This method efficiently appends a new file onto the end of a file array.
+     * @param a The initial <strong>File[]</strong>.
+     * @param b The new <strong>File</strong>.
+     * @return A <strong>File[]</strong> containing a followed by b.
+     */
+    static public File[] add(File a[], File b) {
+	File[] c = null;
+	if(a != null && b != null) {
+	    c = new File[a.length + 1];
+	    System.arraycopy(a, 0, c, 0, a.length);
+	    c[c.length - 1] = b;
+	}
+	else if(a == null && b != null) {
+	    c = new File[1];
+	    c[0] = b;
+	}
+	else if(a != null && b == null) {
+	    c = a;
+	}
+	return c;
+    }
+    /** This method efficently appends one file array onto the end of another.
+     * @param a The initial <strong>File[]</strong>.
+     * @param b The <strong>File[]</strong> to append.
+     * @return A <strong>File[]</strong> containing a followed by b.
+     */
+    static public File[] add(File a[], File b[]) {
+	File[] c = null;
+	if(a != null && b != null) {
+	    c = new File[a.length + b.length];
+	    System.arraycopy(a, 0, c, 0, a.length);
+	    System.arraycopy(b, 0, c, a.length, b.length);
+	}
+	else if(a == null && b != null) {
+	    c = b;
+	}
+	else if(a != null && b == null) {
+	    c = a;
+	}
+	return c;
+    }
+
+
+    /** This method efficiently appends a new node onto the end of a node array.
+     * @param a The initial <strong>Node[]</strong>.
+     * @param b The new <strong>Node</strong>.
+     * @return A <strong>Node[]</strong> containing a followed by b.
+     */
+    static public Node[] add(Node a[], Node b) {
+	Node[] c = null;
+	if(a != null && b != null) {
+	    c = new Node[a.length + 1];
+	    System.arraycopy(a, 0, c, 0, a.length);
+	    c[c.length - 1] = b;
+	}
+	else if(a == null && b != null) {
+	    c = new Node[1];
+	    c[0] = b;
+	}
+	else if(a != null && b == null) {
+	    c = a;
+	}
+	return c;
+    }
+    /** This method efficently appends one node array onto the end of another.
+     * @param a The initial <strong>Node[]</strong>.
+     * @param b The <strong>Node[]</strong> to append.
+     * @return A <strong>Node[]</strong> containing a followed by b.
+     */
+    static public Node[] add(Node a[], Node b[]) {
+	Node[] c = null;
+	if(a != null && b != null) {
+	    c = new Node[a.length + b.length];
+	    System.arraycopy(a, 0, c, 0, a.length);
+	    System.arraycopy(b, 0, c, a.length, b.length);
+	}
+	else if(a == null && b != null) {
+	    c = b;
+	}
+	else if(a != null && b == null) {
+	    c = a;
+	}
+	return c;
+    }
+	 
+    /** This method efficiently appends a new string onto the end of a string array.
+     * @param a The initial <strong>String[]</strong>.
+     * @param b The new <strong>String</strong>.
+     * @return A <strong>String[]</strong> containing a followed by b.
+     */
+    static public String[] add(String a[], String b) {
+	String[] c = null;
+	if(a != null && b != null) {
+	    c = new String[a.length + 1];
+	    System.arraycopy(a, 0, c, 0, a.length);
+	    c[c.length - 1] = b;
+	}
+	else if(a == null && b != null) {
+	    c = new String[1];
+	    c[0] = b;
+	}
+	else if(a != null && b == null) {
+	    c = a;
+	}
+	return c;
+    }
+    /** This method efficently appends one string array onto the end of another.
+     * @param a The initial <strong>String[]</strong>.
+     * @param b The <strong>String[]</strong> to append.
+     * @return A <strong>String[]</strong> containing a followed by b.
+     */
+    static public String[] add(String a[], String b[]) {
+	String[] c = null;
+	if(a != null && b != null) {
+	    c = new String[a.length + b.length];
+	    System.arraycopy(a, 0, c, 0, a.length);
+	    System.arraycopy(b, 0, c, a.length, b.length);
+	}
+	else if(a == null && b != null) {
+	    c = b;
+	}
+	else if(a != null && b == null) {
+	    c = a;
+	}
+	return c;
+    }
+    /** This method takes an array list and creates a string array.
+     * @param a An <strong>ArrayList</strong> containing hopefully <strong>String</strong> or else this will fail.
+     * @return A <strong>String[]</strong> or <i>null</i> if the array could not be created.
+     */
+    static public String[] arrayListToStringArray(ArrayList a) {
+	String array[] = new String[a.size()];
+	for(int i = 0; i < array.length; i++) {
+	    array[i] = (String)a.get(i);
+	}
+	return array;
+    }
+
+    static public File[] filter(File[] files, String pattern, boolean exclude) {
+	int write_ptr = 0;
+	///ystem.err.println("Filtering by '" + pattern + "', Exclude? " + exclude + " :");
+	for(int read_ptr = 0; read_ptr < files.length; read_ptr++) {
+	    File current = files[read_ptr];
+	    files[write_ptr] = current;
+	    ///ystem.err.print("Testing " + current.getName() + " -> ");
+	    // Determine whether we move the write pointer or not.
+	    if(current.getName().toLowerCase().matches(pattern)) {
+		if(!exclude) {
+		    ///ystem.err.println("Match, Exclude.");
+		    write_ptr++;  
+		}
+		else {
+		    ///ystem.err.println("Match, Include.");
+		}
+	    }
+	    else {
+		// You can't exclude folders with an inclusion filter!
+		if(exclude || current.isDirectory()) {
+		    ///ystem.err.println("Nonmatch, Exclude.");
+		    write_ptr++;
+		}
+		else {
+		    ///ystem.err.println("Nonmatch, Include.");
+		}
+	    }
+	}
+	File[] result = new File[write_ptr];
+	System.arraycopy(files, 0, result, 0, result.length);
+	pattern = null;
+	files = null;
+	return result;
+    }
+
+
+    /** Transforms an Object array into a single string of the form '[o1,o2,...,on]'.
+     * @param objects An <strong>Object[]</strong>. Note that the objects in this array must support toString() reasonably.
+     * @return A <strong>String</strong> representing the given array.
+     */
+    static public String objectArrayToString(Object objects[]) {
+	StringBuffer result = new StringBuffer("[");
+	for(int i = 0; i < objects.length; i++) {
+	    result.append(objects[i].toString());
+	    if(i < objects.length - 1) {
+		result.append(",");
+	    }
+	}
+	result.append("]");
+	return result.toString();
+    }
+
+
+    /** Sorts an array of files, putting non-files first. Case insensitive.
+     * @param files_to_sort The File[] to be sorted.
+     */
+    static public void sort(File[] files_to_sort)
+    {
+	// Return if there is nothing to sort
+	if (files_to_sort == null || files_to_sort.length <= 1) {
+	    return;
+	}
+
+	FileSystemView fileSystemView = FileSystemView.getFileSystemView();
+	FileComparator comparator = new FileComparator();
+
+	// Separate the file system roots and directories from the files, and sort separately
+	ArrayList files_list = new ArrayList((files_to_sort.length * 3) / 4);
+	ArrayList non_files_list = new ArrayList((files_to_sort.length) / 4);
+	for (int i = 0; i < files_to_sort.length; i++) {
+	    File file = files_to_sort[i];
+
+	    // File is a system root
+	    if (fileSystemView.isFileSystemRoot(file)) {
+		non_files_list.add(file);
+	    }
+	    // File is a directory
+	    else if (file.isDirectory()) {
+		non_files_list.add(file);
+	    }
+	    // File is an actual file
+	    else {
+		files_list.add(file);
+	    }
+	}
+
+	// Sort files
+	Object[] files = files_list.toArray();
+	Arrays.sort(files, comparator);
+
+	// Sort non-files
+	Object[] non_files = non_files_list.toArray();
+	Arrays.sort(non_files, comparator);
+
+	// Merge the results, putting non-files before files
+	int j = 0;
+	for (int i = 0; i < non_files.length; i++) {
+	    files_to_sort[j++] = (File) non_files[i];
+	}
+	for (int i = 0; i < files.length; i++) {
+	    files_to_sort[j++] = (File) files[i];
+	}
+    }
+
+
+    /** Comparator used to order files. */
+    static private class FileComparator
+	implements Comparator {
+
+	/** Compare two files in terms of ordering of their paths.
+	 * @param o1 The <strong>Object</strong> that represents the first file.
+	 * @param o2 The other <strong>Object</strong>, also a file.
+	 * @return An <i>int</i> which is <1, 0 or >1 if o1 is <o2, =o2 or >o2 respectively.
+	 */
+	public int compare(Object o1, Object o2)
+	{
+	    File f1 = (File) o1;
+	    File f2 = (File) o2;
+
+	    return f1.getName().compareToIgnoreCase(f2.getName());
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/CheckList.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/CheckList.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/CheckList.java	(revision 13928)
@@ -0,0 +1,246 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.util;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.border.*;
+
+
+/** This class provides a visual component that has the form of a list, as provided by JList but uses JCheckBox for data selection. Thus several elements can be 'ticked' in the list, and this selection returned using the method getSelected().<BR>Parts of this code modified from Trevor Harmon's posting on www.dejanews.com.
+ * @author John Thompson
+ * @version 2.3
+ */ 
+public class CheckList
+    extends JList
+{
+    /** The border used when a list row is not in focus. */
+    static private Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
+
+    private boolean show_selected_row = true;
+
+
+    /** Constructor. */
+    public CheckList(boolean show_selected_row)
+    {
+	super();
+	this.show_selected_row = show_selected_row;
+
+	setCellRenderer(new CheckListCellRenderer());
+	setModel(new DefaultListModel());
+	setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+	addMouseListener(new CheckListMouseListener());
+    }
+
+
+    public void addEntry(CheckListEntry entry)
+    {
+	DefaultListModel model = (DefaultListModel) getModel();
+
+	// Add the entry in alpabetical order
+	String name = entry.toString();
+	for (int i = 0; i < model.size(); i++) {
+	    Object sibling = model.getElementAt(i);
+	    if (name.compareTo(sibling.toString()) <= 0) {
+		model.add(i, entry);
+		return;
+	    }
+	}
+
+	model.addElement(entry);
+    }
+
+
+    public void clearTicked()
+    {
+	DefaultListModel model = (DefaultListModel) getModel();
+	for (int i = 0; i < model.size(); i++) {
+	    ((CheckListEntry) model.get(i)).setSelected(false);
+	}
+	updateUI();
+    }
+
+    /** Retrieve all the entries from the list
+     */
+    public ArrayList getAll()
+    {
+	ArrayList result = new ArrayList();
+	DefaultListModel model = (DefaultListModel) getModel();
+	for (int i = 0; i < model.size(); i++) {
+	    CheckListEntry entry = (CheckListEntry) model.get(i);
+	    result.add(entry.getObject());
+	}
+	return result;
+    }
+	
+
+    /** Retrieve the currently ticked entries from this list.
+     * @return An <strong>ArrayList</strong> containing only those entries from the initial list that are checked.
+     * @see org.greenstone.gatherer.checklist.Entry
+     */
+    public ArrayList getTicked()
+    {
+	ArrayList result = new ArrayList();
+	DefaultListModel model = (DefaultListModel) getModel();
+	for (int i = 0; i < model.size(); i++) {
+	    CheckListEntry entry = (CheckListEntry) model.get(i);
+	    if (entry.isSelected()) {
+		result.add(entry.getObject());
+	    }
+	}
+	return result;
+    }
+
+
+    /** This is different from isSelectionEmpty! */
+    public boolean isNothingTicked()
+    {
+	DefaultListModel model = (DefaultListModel) getModel();
+	for (int i = 0; i < model.size(); i++) {
+	    if (((CheckListEntry) model.get(i)).isSelected()) {
+		return false;
+	    }
+	}
+
+	return true;
+    }
+
+
+    public void setListData(ArrayList list_data)
+    {
+ 	// Create a new model.
+	setModel(new DefaultListModel());
+
+	// Add the items from the list to the model
+ 	for (int i = 0; i < list_data.size(); i++) {
+ 	    Object list_object = list_data.get(i);
+ 	    if (list_object instanceof CheckListEntry) {
+ 		addEntry((CheckListEntry) list_object);
+ 	    }
+	    else {
+		addEntry(new CheckListEntry(list_object));
+	    }
+ 	}
+    }
+
+
+    public void setTickedObjects(Object[] objects)
+    {
+	if (objects == null) {
+	    return;
+	}
+
+	DefaultListModel model = (DefaultListModel) getModel();
+	for (int i = 0; i < model.size(); i++) {
+	    CheckListEntry entry = (CheckListEntry) model.get(i);
+	    for (int j = 0; j < objects.length; j++) {
+		if (entry.getObject().equals(objects[j])) {
+		    entry.setSelected(true);
+		}
+	    }
+	}
+	updateUI();
+    }
+
+    public void setAllTicked() {
+	DefaultListModel model = (DefaultListModel) getModel();
+	for (int i = 0; i < model.size(); i++) {
+	    CheckListEntry entry = (CheckListEntry) model.get(i);
+	    entry.setSelected(true);
+	}
+	updateUI();
+    }
+
+    /** A custom list cell renderer for producing rows which contain clickable check boxes. */
+    protected class CheckListCellRenderer 
+	implements ListCellRenderer
+    {
+	/** Return a component that has been configured to display the specified value. That component's paint method is then called to "render" the cell. If it is necessary to compute the dimensions of a list because the list cells do not have a fixed size, this method is called to generate a component on which getPreferredSize  can be invoked.
+	 * @param list The </strong>JList</strong> we're painting.
+	 * @param value The value returned by list.getModel().getElementAt(index), as an <strong>Object</strong>.
+	 * @param index The cells index as an <i>int</i>.
+	 * @param is_selected <i>true</i> if the specified cell was selected, <i>false</i> otherwise.
+	 * @param cell_has_focus <i>true</i> if and only if the specified cell has the focus.
+	 * @return A <strong>Component</strong> whose paint() method will render the specified value.
+	 */
+	public Component getListCellRendererComponent(JList list, Object value, int index, boolean is_selected, boolean cell_has_focus) {
+	    JCheckBox checkbox = (JCheckBox) value;
+	    if (show_selected_row) {
+		checkbox.setBackground(is_selected ? list.getSelectionBackground() : list.getBackground());
+		checkbox.setForeground(is_selected ? list.getSelectionForeground() : list.getForeground());
+		checkbox.setBorderPainted(true);
+	    }
+	    else {
+		checkbox.setBackground(list.getBackground());
+		checkbox.setForeground(list.getForeground());
+		checkbox.setBorderPainted(false);
+	    }
+	    checkbox.setEnabled(list.isEnabled());
+	    checkbox.setFont(list.getFont());
+	    checkbox.setFocusPainted(false);
+	    checkbox.setBorder((is_selected) ? UIManager.getBorder("List.focusCellHighlightBorder") : noFocusBorder);
+	    return checkbox;
+	}
+    }
+
+
+    /** Listens for clicks apon the checks within the list, and updates as necessary. */
+    private class CheckListMouseListener 
+	extends MouseAdapter
+    {
+	/** Called whenever the mouse is clicked over our list. We find the nearest checkbox and change its state.
+	 * @param e A <strong>MouseEvent</strong> containing everything you ever wanted to know about the mouse event but were afraid to ask.
+	 */
+	public void mousePressed(MouseEvent e)
+	{
+	    if (!isEnabled()) return;
+	    JList list = (JList) e.getSource();
+	    int index = list.locationToIndex(e.getPoint());
+	    CheckListEntry checkbox = (CheckListEntry) list.getModel().getElementAt(index);
+	    if (!checkbox.isFixed()) {
+		checkbox.setSelected(!checkbox.isSelected());
+	    }
+	    checkbox.grabFocus();
+
+	    // We need to cause a ListSelectionEvent -- this is ugly but I can't find a better way quickly
+	    list.removeSelectionInterval(0, 0);
+	    list.setSelectionInterval(index, index);
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/CheckListEntry.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/CheckListEntry.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/CheckListEntry.java	(revision 13928)
@@ -0,0 +1,78 @@
+package org.greenstone.gatherer.util;
+
+import javax.swing.JCheckBox;
+
+/** A CheckListEntry encapsulates a single row of the list, both its check box and the object the row represents. */
+public class CheckListEntry
+    extends JCheckBox 
+    implements Comparable {
+
+    /** Is this checkboxes state fixed. */
+    private boolean fixed = false;
+    /** The original object this row is based on, and whose toString() is used to generate the check box label. */
+    private Object object = null;
+    /** A sundry string for storing original values (rather than strings retrieved from dictionary). */
+    private String property;
+    /** Constructor. */
+    public CheckListEntry(Object object) {
+	super(object.toString());
+	this.object = object;
+    }
+
+    /** Constructor. */
+    public CheckListEntry(String text, boolean is_selected) {
+	super(text);
+	setSelected(is_selected);
+    }
+
+    /** Test this CheckListEntry against an Object for ordering. 
+     * @param obj the other Object.
+     * @return <0, 0 or >0 if this CheckListEntry is before, equal to or after the given object.
+     */
+    public int compareTo(Object obj) {
+	return toString().toLowerCase().compareTo(obj.toString().toLowerCase());
+    }
+    /** Test this CheckListEntry against an Object for equality. 
+     * @param obj the other Object.
+     * @return true if the two are equal, false otherwise.
+     */
+    public boolean equals(Object obj) {
+	if (obj == null) {
+	    return false;
+	}
+	return toString().equalsIgnoreCase(obj.toString());
+    }
+
+    /** Retrieve the object associated with this entry.
+     * @return An <strong>Object</strong>.
+     */
+    public Object getObject() {
+	if(object == null) {
+	    return getText();
+	}
+	return object;
+    }
+
+    public String getProperty() {
+	return property;
+    }
+
+    public boolean isFixed() {
+	return fixed;
+    }
+
+    public void setFixed(boolean fixed) {
+	this.fixed = fixed;
+    }
+
+    public void setProperty(String property) {
+	this.property = property;
+    }
+
+    public String toString() {
+	if(object == null) {
+	    return getText();
+	}
+	return object.toString();
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/Codec.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/Codec.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/Codec.java	(revision 13928)
@@ -0,0 +1,379 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.util;
+
+import java.util.*;
+
+/** Provides a standard, extensible way to convert from one format of string to another (given that each format has differing requirements regarding legal characters and escaped characters)
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3d
+ */
+public class Codec {
+    
+    static final public String DECODE_PATH = "DECODE_PATH";
+    static final public String DECODE_SQUARE_BRACKETS = "DECODE_SQUARE_BRACKETS";
+    static final public String DOM_TO_GREENSTONE = "DOM_TO_GREENSTONE";
+    static final public String DOM_TO_TEXT = "DOM_TO_TEXT";
+    static final public String ENCODE_PATH = "ENCODE_PATH";
+    static final public String ENCODE_SQUARE_BRACKETS = "ENCODE_SQUARE_BRACKETS";
+    static final public String GREENSTONE_TO_DOM = "GREENSTONE_TO_DOM";
+    static final public String GREENSTONE_TO_TEXT = "GREENSTONE_TO_TEXT";
+    static final public String TEXT_TO_DOM = "TEXT_TO_DOM";
+    static final public String TEXT_TO_GREENSTONE = "TEXT_TO_GREENSTONE";
+    static final public String TEXT_TO_REGEXP = "TEXT_TO_REGEXP";
+    static final public String TEXT_TO_SHELL_UNIX = "TEXT_TO_SHELL_UNIX";
+    static final public String TEXT_TO_SHELL_WINDOWS = "TEXT_TO_SHELL_WINDOWS";
+    
+    static final private int MAX_CACHE_SIZE = 100;
+    
+    static private HashMap TRANSFORMS;
+    static private HashMap3D CACHE;
+    
+    /** Static function called to construct TRANSFORMS mappings */
+    static {
+	TRANSFORMS = new HashMap();
+
+	String[] decode_path = {
+	    "\\|",    "\\\\",
+	    "&#124;", "\\|"
+	};
+	TRANSFORMS.put(DECODE_PATH, decode_path);
+	decode_path = null;
+
+	// Transform text into text, but without [ and ]
+	String[] decode_square_brackets = {
+	    "&#091;", "\\[",
+	    "&#093;", "\\]" 
+	};
+	TRANSFORMS.put(DECODE_SQUARE_BRACKETS, decode_square_brackets);
+	decode_square_brackets = null;
+
+	// Translate DOM encoded text into Greenstone encoding
+	String[] dom_to_greenstone = {
+	    "&apos;", "\\\\\'",
+	    "&gt;", ">",
+	    "&lt;", "<",
+	    "&quot;", "\\\\\"",
+	    "&amp;", "&"
+	};
+	//  removed "\n", "\\\\n", - config files are allowed new lines
+	// added "\\|", "\\\\"
+
+	TRANSFORMS.put(DOM_TO_GREENSTONE, dom_to_greenstone);
+	dom_to_greenstone = null;
+
+	// Transform DOM encoded text into plain text
+	String[] dom_to_text = {
+	   "&amp;#091;", "\\[",
+	   "&amp;#093;", "\\]",
+	   "&apos;", "\'",
+	   "&gt;", ">",
+	   "&lt;", "<",
+	   "&quot;", "\"",
+	   "&amp;", "&"
+	};
+	TRANSFORMS.put(DOM_TO_TEXT, dom_to_text);
+	dom_to_text = null;
+
+	// Transform text into a regular expression that will match it
+	String[] text_to_regexp = {
+	    "\\\\", "\\\\\\\\",
+	    "\\(", "\\\\(",
+	    "\\)", "\\\\)",
+	    "\\[", "\\\\[",
+	    "\\]", "\\\\]",
+	    "\\{", "\\\\{",
+	    "\\}", "\\\\}",
+	    "\\.", "\\\\."
+	};
+	TRANSFORMS.put(TEXT_TO_REGEXP, text_to_regexp);
+	text_to_regexp = null;
+
+	String[] encode_path = {
+	    "\\|",  "&#124;",
+	    "\\\\", "\\|"
+	};
+	TRANSFORMS.put(ENCODE_PATH, encode_path);
+	encode_path = null;
+
+	// Transform text into text, but without [ and ]
+	String[] encode_square_brackets = {
+	    "\\[", "&#091;",
+	    "\\]", "&#093;"
+	};
+	TRANSFORMS.put(ENCODE_SQUARE_BRACKETS, encode_square_brackets);
+	encode_square_brackets = null;
+
+	// Transform Greenstone encoded text to DOM encoding
+	String[] greenstone_to_dom = {
+	    "&", "&amp;",
+	    "<", "&lt;",
+	    ">", "&gt;",
+	    "\\\\\"", "&quot;",
+	    "\\\\\'", "&apos;",
+	    "\"", "&quot;",
+	    "\'", "&apos;"
+	};
+	// removed"\\\\n", "\n", added "\\\\", "\\|"
+
+	TRANSFORMS.put(GREENSTONE_TO_DOM, greenstone_to_dom);
+	greenstone_to_dom = null;
+
+	// Transform Greenstone encoded text to plain text
+	String[] greenstone_to_text = {
+	    "\\\\\"", "\"",
+	    "\\\\\'", "\'",
+	    "&quot;", "\"",
+	    "&apos;", "\'",
+	    "&#091;", "\\[",
+	    "&#093;", "\\]"
+	};
+	// removed    "\\\\n", "\n", "\\|", "\\\\"
+
+	TRANSFORMS.put(GREENSTONE_TO_TEXT, greenstone_to_text);
+	greenstone_to_text = null;
+
+	// Transform plain html text into something that can be placed in a DOM
+	String[] text_to_dom = {
+	    "&", "&amp;",
+	    "<", "&lt;",
+	    ">", "&gt;",
+	    "\"", "&quot;",
+	    "\'", "&apos;"
+	};
+	TRANSFORMS.put(TEXT_TO_DOM, text_to_dom);
+	text_to_dom = null;
+
+	// Transform plain html text into greenstone encoding
+	String[] text_to_greenstone = {
+
+	    "\\[", "&#091;",
+	    "\\]", "&#093;",
+	    "\"", "&quot;",
+	    "\n", "\\\\n"
+	};
+	// 	    "\'", "&apos;",
+	// removed "\\\\", "\\|",
+	TRANSFORMS.put(TEXT_TO_GREENSTONE, text_to_greenstone);
+	text_to_greenstone = null;
+
+	// Transform plain html text into something that can be placed in a shell command
+	String[] text_to_shell_unix = {
+	    "\"", "\\\\\"",
+	    "\'", "\\\\\'",
+	    "\n", "\\\\n"
+	};
+	TRANSFORMS.put(TEXT_TO_SHELL_UNIX, text_to_shell_unix);
+	text_to_shell_unix = null;
+
+	// Transform plain html text into something that can be placed in a shell command. Windows requires twice as many escaped for speech marks to be passed to underlying processes
+	String[] text_to_shell_windows = {
+	    "\"", "\\\\\\\\\\\\\"",
+	    "\'", "\\\\\'",
+	    "\n", "\\\\n"
+	};
+	TRANSFORMS.put(TEXT_TO_SHELL_WINDOWS, text_to_shell_windows);
+	text_to_shell_windows = null;
+
+	CACHE = new HashMap3D();
+    }
+
+    static public String transform(String raw, String transform) {
+	if(raw == null) {
+	    return raw;
+	}
+	// System.err.println("Transforming by "+transform+":\n" + raw);
+	String processed = (String) CACHE.get(transform, raw);
+	if(processed == null) {
+	    processed = raw;
+	    String[] transforms = (String[]) TRANSFORMS.get(transform);
+	    if(transforms != null) {
+		for(int i = 0; i < transforms.length; i = i + 2) {
+		    String target = transforms[i];
+		    String result = transforms[i+1];
+		    processed = processed.replaceAll(target, result);
+		}
+	    }
+	    //DebugStream.println("\n*** Transform: " + transform + " ***");
+	    //DebugStream.println("*** Raw      : '" + raw + "'");
+	    //DebugStream.println("*** Processed: '" + processed + "'");
+	    // If cache is at maximum size, empty it and start again
+	    if(CACHE.size() == MAX_CACHE_SIZE) {
+		CACHE.clear();
+	    }
+	    CACHE.put(transform, raw, processed);
+	}
+	return processed;
+    }
+
+    /** Transform either of the accepted unicode escape sequences styles from in the string into single characters */
+    static final private char AND_CHAR = '&';
+    static final private char ESCAPE_CHAR = '\\';
+    static final private char HASH_CHAR = '#';
+    static final private char LOWER_U_CHAR = 'u';
+    static final private char UPPER_U_CHAR = 'U';
+    static final private char SEMICOLON_CHAR = ';';
+
+    static public String transformUnicode(String raw) {
+	StringBuffer processed = new StringBuffer();
+	int index = 0;
+	int raw_length = raw.length();
+	while(index < raw_length) {
+	    char c0 = raw.charAt(index);
+	    switch(c0) {
+	    case AND_CHAR:
+		if(index + 1 < raw_length) {
+		    // First the HTML &#231; type
+		    char c1 = raw.charAt(index + 1);
+		    if(c1 == HASH_CHAR) {
+			StringBuffer number_str = new StringBuffer();
+			char c2;
+			int offset = 2;
+			while(index + offset < raw_length && (c2 = raw.charAt(index + offset)) != SEMICOLON_CHAR) {
+			    number_str.append(c2);
+			    offset++;
+			}
+			// We've either run out of characters or have parsed a number
+			if(index + offset < raw_length && raw.charAt(index + offset) == SEMICOLON_CHAR) {
+			    int number = Integer.parseInt(number_str.toString());
+			    processed.append((char)number);
+			    index = index + offset;
+			    number_str = null;
+			    break;
+			}
+			number_str = null;
+		    }
+		}
+		processed.append(c0);
+		break;
+	    case ESCAPE_CHAR:
+		// Now the \u00e7 type
+		if(index + 1 < raw_length) {
+		    char c3 = raw.charAt(index + 1);
+		    if((c3 == UPPER_U_CHAR || c3 == LOWER_U_CHAR) && index + 5 < raw_length) {
+			// We read four digits
+			String hex_str = raw.substring(index + 2, index + 6);
+			int number = Integer.parseInt(hex_str, 16);
+			hex_str = null;
+			processed.append((char)number);
+			index = index + 5;
+			break;
+		    }
+		}
+		processed.append(c0);
+		break;
+	    default:
+		processed.append(c0);
+	    }
+	    index++;
+	}
+	return processed.toString();
+    }
+
+    static public void main(String[] args) {
+	if(args.length < 2) {
+	    String processed;
+	    String raw;
+	    String transform;
+
+	    System.err.println("Running Test Suite");
+
+	    transform = "DOM_TO_GREENSTONE";
+	    System.err.println("Test " + transform);
+	    raw = "A &amp;lt;\nand a &lt;a href=&quot;here.html&quot;&gt;&lt;font size=&apos;2&apos;&gt;URL&lt;/font&gt;&lt;/a&gt;";
+	    System.err.println("Raw:       '" + raw + "'");
+	    processed = transform(raw, transform);
+	    System.err.println("Processed: '" + processed + "'");
+
+	    transform = "DOM_TO_TEXT";
+	    System.err.println("Test " + transform);
+	    raw = "A &amp;lt;\nand a &lt;a href=&quot;here.html&quot;&gt;&lt;font size=&apos;2&apos;&gt;URL&lt;/font&gt;&lt;/a&gt;";
+	    System.err.println("Raw:       '" + raw + "'");
+	    processed = transform(raw, transform);
+	    System.err.println("Processed: '" + processed + "'");
+
+	    transform = "GREENSTONE_TO_DOM";
+	    System.err.println("Test " + transform);
+	    raw = "A &lt;\\nand a <a href=\\\"here.html\\\"><font size=\\\'2\\\'URL</font></a>";
+	    System.err.println("Raw:       '" + raw + "'");
+	    processed = transform(raw, transform);
+	    System.err.println("Processed: '" + processed + "'");
+
+	    transform = "GREENSTONE_TO_TEXT";
+	    System.err.println("Test " + transform);
+	    raw = "These \\[ \\] should be escaped, and so should \\\\ that. These &quot; &apos; \\n are encoded.";
+	    System.err.println("Raw:       '" + raw + "'");
+	    processed = transform(raw, transform);
+	    System.err.println("Processed: '" + processed + "'");
+
+	    transform = "TEXT_TO_DOM";
+	    System.err.println("Test " + transform);
+	    raw = "A &lt;\nand a <a href=\"here.html\"><font size='2'>URL</font></a>";
+	    System.err.println("Raw:       '" + raw + "'");
+	    processed = transform(raw, transform);
+	    System.err.println("Processed: '" + processed + "'");
+
+	    transform = "TEXT_TO_GREENSTONE";
+	    System.err.println("Test " + transform);
+	    raw = "These [ ] should be escaped, and so should \\ that. These \" \' \n are encoded.";
+	    System.err.println("Raw:       '" + raw + "'");
+	    processed = transform(raw, transform);
+	    System.err.println("Processed: '" + processed + "'");
+
+	    transform = "TEXT_TO_SHELL";
+	    System.err.println("Test " + transform);
+	    if(Utility.isWindows()) {
+		System.err.println("[Windows Version]");
+		transform = "TEXT_TO_SHELL_WINDOWS";
+	    }
+	    else {
+		System.err.println("[Unix Version]");
+		transform = "TEXT_TO_SHELL_UNIX";
+	    }
+	    raw = "A &lt;\nand a <a href=\"here.html\"><font size='2'>URL</font></a>";
+	    System.err.println("Raw:       '" + raw + "'");
+	    processed = transform(raw, transform);
+	    System.err.println("Processed: '" + processed + "'");
+
+	    System.err.println("***** UNICODE TEST *****");
+	    System.err.println("\\u0030 => " + transformUnicode("\\u0030"));
+	    System.err.println("\\u0041 => " + transformUnicode("\\u0041"));
+	    System.err.println("\\u007a => " + transformUnicode("\\u007a"));
+	    System.err.println("\\u00e7 => " + transformUnicode("\\u00e7"));
+	    System.err.println("&#48;   => " + transformUnicode("&#48;"));
+	    System.err.println("&#65;   => " + transformUnicode("&#65;"));
+	    System.err.println("&#122;  => " + transformUnicode("&#122;"));
+	    System.err.println("&#231;  => " + transformUnicode("&#231;"));
+	}
+	else {
+	    System.err.println("Raw:       '" + args[0] + "'");
+	    System.err.println("Transform: " + args[1]);
+	    String processed = transform(args[0], args[1]);
+	    System.err.println("Processed: '" + processed + "'");
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/DOMTree.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/DOMTree.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/DOMTree.java	(revision 13928)
@@ -0,0 +1,149 @@
+package org.greenstone.gatherer.util;
+
+import java.util.*;
+import javax.swing.*;
+import javax.swing.tree.*;
+import org.w3c.dom.*;
+
+public class DOMTree
+    extends JTree {
+
+    public DOMTree(Document document) {
+	super();
+	setDocument(document);
+    }
+
+    public void setDocument(Document document) {
+	setModel(new DefaultTreeModel(new DOMTreeNode(document.getDocumentElement(), null)));
+    }
+
+    private class DOMTreeNode 
+	implements TreeNode {
+
+	private Node node = null;
+	private NodeList children = null;
+	private String text = null;
+	private TreeNode parent = null;
+	private TreeNode self = null;
+
+	DOMTreeNode(Node node, TreeNode parent) {
+	    this.node = node;
+	    this.parent = parent;
+	    this.self = this;
+	}
+	
+	/** Returns the children of the receiver as an Enumeration. */
+	public Enumeration children() {
+	    if(children == null) {
+		children = node.getChildNodes();
+	    }
+	    return new NodeListEnumeration();
+	}
+          
+	/** Returns true if the receiver allows children. */
+	public boolean getAllowsChildren() {
+	    return true;
+	}
+          
+	/** Returns the child TreeNode at index childIndex. */
+	public TreeNode getChildAt(int childIndex) {
+	    if(children == null) {
+		children = node.getChildNodes();
+	    }
+	    return new DOMTreeNode(children.item(childIndex), this);
+	}
+          
+	/** Returns the number of children TreeNodes the receiver contains. */
+	public int getChildCount() {
+	    if(children == null) {
+		children = node.getChildNodes();
+	    }
+	    return children.getLength();
+	}
+          
+	/** Returns the index of node in the receivers children. */
+	public int getIndex(TreeNode find_node) {
+	    if(children == null) {
+		children = node.getChildNodes();
+	    }
+	    Node target_node = ((DOMTreeNode)find_node).getNode();
+	    int children_count = children.getLength();
+	    for(int i = 0; i < children_count; i++) {
+		Node test_node = children.item(i);
+		if(target_node == test_node) {
+		    test_node = null;
+		    target_node = null;
+		    return i;
+		}
+		test_node = null;
+	    }
+	    target_node = null;
+	    return -1;
+	}
+	    
+	public Node getNode() {
+	    return node;
+	}
+
+	/** Returns the parent TreeNode of the receiver. */
+	public TreeNode getParent() {
+	    return parent;
+	}
+	    
+	/** Returns true if the receiver is a leaf. */
+	public boolean isLeaf() {
+	    return !node.hasChildNodes();
+	}
+
+	public String toString() {
+	    if(text == null) {
+		StringBuffer temp = new StringBuffer(node.getNodeName());
+		String value = node.getNodeValue();
+		if(value != null && value.length() != 0) {
+		    temp.append("=\"");
+		    temp.append(value);
+		    temp.append("\"");
+		}
+		value = null;
+		if(node instanceof Element) {
+		    Element element = (Element) node;
+		    temp.append(": ");
+		    NamedNodeMap attributes = element.getAttributes();
+		    int attribute_count = attributes.getLength();
+		    for(int i = 0; i < attribute_count; i++) {
+			Node attribute = attributes.item(i);
+			temp.append(attribute.getNodeName());
+			temp.append("=\"");
+			temp.append(attribute.getNodeValue());
+			if(i < attribute_count - 1) {
+			    temp.append("\" ");
+			}
+			else {
+			    temp.append("\"");
+			}
+		    }
+		    attributes = null;
+		    element = null;
+		}
+		text = temp.toString();
+		temp = null;
+	    }
+	    return text;
+	}
+
+	private class NodeListEnumeration
+	    implements Enumeration {
+	    private int index = 0;
+	    /** Tests if this enumeration contains more elements. */
+	    public boolean hasMoreElements() {
+		return index < children.getLength();
+	    }
+	    /** Returns the next element of this enumeration if this enumeration object has at least one more element to provide. */
+	    public Object nextElement() {
+		int old_index = index;
+		index = index + 1;
+		return new DOMTreeNode(children.item(old_index), self);
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/DragComponent.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/DragComponent.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/DragComponent.java	(revision 13928)
@@ -0,0 +1,65 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.util;
+/**
+ * Title:        Gatherer<br>
+ * Description:  The Gatherer: a tool for gathering and enriching a digital collection.<br>
+ * Copyright:    Copyright (c) 2001<br>
+ * Company:      The University of Waikato<br>
+ * Written:        /  /01<br>
+ * Revised:      21/06/02 - Moved into correct package and commented.<br>
+ * @author John Thompson, 9826509
+ * @version 2.1
+ */
+import java.awt.event.FocusListener;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.file.FileSystemModel;
+
+/** Any component that wants to act a GTree like drag'n'drop component must implement this. */
+public interface DragComponent {
+    public void addFocusListener(FocusListener listener);
+    /** In order for the appearance to be consistant, given we may be in the situation where the pointer has left our focus but the ghost remains, this method allows other members of the Group to tell this component to repair the 'spoilt' region left by its ghost. */
+    public void clearGhost();
+    /** Used to notify this component that it has gained focus by some method other that mouse focus. */
+    public void gainFocus();	 
+    /** Retrieve the model associated with this component. */
+    public FileSystemModel getTreeModel();
+    /** This method is used to inform this component when it loses focus by means other than a drag mouse event, and should indicate this somehow. */
+    public void loseFocus();
+    /** Set the components group. */
+    public void setGroup(DragGroup group);
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/DragGroup.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/DragGroup.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/DragGroup.java	(revision 13928)
@@ -0,0 +1,136 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.util;
+
+import java.awt.Point;
+import java.awt.event.*;
+import java.awt.image.BufferedImage;
+import java.util.Vector;
+import javax.swing.JComponent;
+import javax.swing.tree.TreePath;
+import org.greenstone.gatherer.gui.tree.DragTree;
+
+
+/** This class acts as a linker between all the various drag and drop enabled DragComponent. It provides methods for ensuring only one component is the drop target, showing extra user feedback, and maintains a single point of focus. Moreover it provides a storage space for necessary shared variables such as mouse_offset of initial drag etc. */
+public class DragGroup 
+    implements FocusListener {
+    /** The image used for the ghost icon when dragging. */
+    public BufferedImage image_ghost = null;
+    /** The initial offset of the mouse from the selection within a DragComponent. Then as you drag the mouse, the ghost appears in a visually consistant place, and remains at the same offset throughout the dragging process. */
+    public Point mouse_offset = null;
+    /** The component currently in charge of drawing the ghost icon. Note that this isn't necessarily the only component that needs to repaint 'spoilt' screen real-estate as a side effect of the ghost. */
+    private DragComponent ghost_owner = null;
+    /** The component where the drag began, so that extra information necessary for the drag can be garnered by the drop target, or so that focus can return to the source component if the drop is rejected. */
+    private DragTree drag_source = null;
+    /** The selected nodes, as determined when the drag begun. */
+    private TreePath[] selection = null;
+    /** A list of DragComponents registered as being part of this group. */
+    private Vector registered = new Vector();
+
+    /** Register a DragComponent as begin part of this group.
+     * @param component The DragComponent to add.
+     */
+    public void add(DragComponent component) {
+	if(!registered.contains(component)) {
+	    registered.add(component);
+	    component.addFocusListener(this);
+	    component.setGroup(this);
+	}
+    }
+
+    /** Invoked when a component gains the keyboard focus. */
+    public void focusGained(FocusEvent event) {
+	((DragComponent)event.getComponent()).gainFocus();
+    }
+          
+    /** Invoked when a component loses the keyboard focus. */
+    public void focusLost(FocusEvent event) {
+	((DragComponent)event.getComponent()).loseFocus();
+    }          
+    /** Determines the current 'active' component, ie that component with focus.
+     * @return The DragComponent which is currently responsible for drawing the ghost, and thus is active.
+     */
+    public DragComponent getActive() {
+	return ghost_owner;
+    }
+    /** Retrieve the nodes selected at the beginning of this drag operation.
+     * @return A TreePath[].
+     */
+    public TreePath[] getSelection() {
+	return selection;
+    }
+    /** Retrieve the component which served as the source of this drag action.
+     * @return The DragComponent in question.
+     */
+    public DragTree getSource() {
+	return drag_source;
+    }
+    /** When called this method asserts that one of the registered GComponents just became the proud owner of focus, and is henceforth responsible for drawing the ghost, and acting like a component thats in focus.
+     * @param new_owner The DragComponent that has gained focus during a drag action.
+     */
+    public void grabFocus(DragComponent new_owner) {
+	// Tell the previous owner of ghost to clear itself.
+	if(ghost_owner != null) {
+	    ghost_owner.clearGhost();
+	}
+	// Assign new owner
+	ghost_owner = new_owner;
+	// Then tell all other GComponents to indicate they aren't in focus in whatever way they do that (ie selected items of a GTree go gray). Of course the new owners told it is in focus.
+	for(int i = 0; i < registered.size(); i++) {
+	    DragComponent comp = (DragComponent)registered.get(i);
+	    if(comp == new_owner) {
+		comp.gainFocus();
+	    }
+	    else {
+		comp.loseFocus();
+	    }
+	}
+    }
+    /** Sets the value of selected_nodes.
+     * @param selection The new value for selected_nodes as a TreePath[].
+     */
+    public void setSelection(TreePath[] selection) {
+	this.selection = selection;
+    }
+    /** Sets the value of drag_source.
+     * @param drag_source The new value for drag_source as a DragTree.
+     */
+    public void setSource(DragTree drag_source) {
+	this.drag_source = drag_source;
+	///ystem.err.println("The drag source is now " + drag_source);
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/DragTreeSelectionModel.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/DragTreeSelectionModel.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/DragTreeSelectionModel.java	(revision 13928)
@@ -0,0 +1,278 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.util;
+
+import java.awt.Point;
+import java.awt.event.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.gui.tree.DragTree;
+
+public class DragTreeSelectionModel
+    extends DefaultTreeSelectionModel
+    implements MouseListener {
+
+    private boolean immediate = false;
+    private boolean mixed_selection = false;
+
+    private int type               = -1;
+
+    private TreePath temp_path     = null;
+    private TreePath temp_paths[]  = null;
+
+    static private final int NONE  = -1;
+    static private final int ADD   =  0;
+    static private final int SET   =  1;
+
+    /** Constructor.
+     * @param tree the DragTree which will use this selection model.
+     * @param mixed_selection true if this selection model allows selections to contain files and folders, false otherwise.
+     */
+    public DragTreeSelectionModel(DragTree tree, boolean mixed_selection) {
+	super();
+	this.mixed_selection = mixed_selection;
+	setSelectionMode(DISCONTIGUOUS_TREE_SELECTION);
+	tree.addMouseListener(this);
+    }
+
+    public void addSelectionPath(TreePath path) {
+	if(!immediate) {
+	    this.temp_path = path;
+	    this.type = this.ADD;
+	}
+	else if(isAppropriate(path)) {
+	    temp_path = null;
+	    super.addSelectionPath(path);
+	}
+    }
+
+    public void addSelectionPaths(TreePath paths[]) {
+	if(!immediate) {
+	    this.temp_paths = paths;
+	    this.type = this.ADD;
+	}
+	else if(isAppropriate(paths, true)) {
+	    temp_paths = null;
+	    super.setSelectionPaths(paths);
+	}
+    }
+
+    public String getDetails() {
+	String suffix = null;
+	int file_count = 0;
+	int folder_count = 0;
+	for(int i = 0; selection != null && i < selection.length; i++) {
+	    TreeNode node = (TreeNode) selection[i].getLastPathComponent();
+	    if(node.isLeaf()) {
+		file_count++;
+	    }
+	    else {
+		folder_count++;
+	    }
+	}
+
+	// Update the metaaudit_suffix
+	String args[] = null;
+	if(file_count > 0 && folder_count > 0) {
+	    if(file_count > 1 && folder_count > 1) {
+		args = new String[2];
+		args[0] = String.valueOf(file_count);
+		args[1] = String.valueOf(folder_count);
+		suffix = Dictionary.get("FileActions.Selected", args);
+	    }
+	    else if(file_count > 1) {
+		args = new String[1];
+		args[0] = String.valueOf(file_count);
+		suffix = Dictionary.get("FileActions.Files_And_Directory_Selected", args);
+	    }
+	    else if(folder_count > 1) {
+		args = new String[1];
+		args[0] = String.valueOf(folder_count);
+		suffix = Dictionary.get("FileActions.File_And_Directories_Selected", args);
+	    }
+	    else {
+		suffix = Dictionary.get("FileActions.File_And_Directory_Selected");
+	    }
+	}
+	else if(file_count > 0) {
+	    if(file_count > 1) {
+		args = new String[1];
+		args[0] = String.valueOf(file_count);
+		suffix = Dictionary.get("FileActions.Files_Selected", args);
+	    }
+	    else if(file_count == 1) {
+		suffix = Dictionary.get("FileActions.File_Selected");
+	    }
+	}
+	else if(folder_count > 0) {
+	    if(folder_count > 1) {
+		args = new String[1];
+		args[0] = String.valueOf(folder_count);
+		suffix = Dictionary.get("FileActions.Directories_Selected", args);
+	    }
+	    else {
+		suffix = Dictionary.get("FileActions.Directory_Selected");
+	    }
+	}
+	args = null;
+
+	return suffix;
+    }
+
+    /** Any implementation of MouseListener must include this method so
+     * we can be informed when the mouse is clicked.
+     * @param event A MouseEvent containing all the information about
+     * this mouse click.
+     */
+    public void mouseClicked(MouseEvent event) {
+    }
+
+    /** Any implementation of MouseListener must include this method so
+     * we can be informed when the mouse enters a component.
+     * @param event A MouseEvent containing all the information about
+     * this mouse action.
+     */
+    public void mouseEntered(MouseEvent event) {
+    }
+
+    /** Any implementation of MouseListener must include this method so
+     * we can be informed when the mouse exits a component.
+     * @param event A MouseEvent containing all the information about
+     * this mouse action.
+     */
+    public void mouseExited(MouseEvent event) {
+    }
+
+    /** Any implementation of MouseListener must include this method so
+     * we can be informed when the mouse is pressed (start of click).
+     * @param event A MouseEvent containing all the information about
+     * this mouse action.
+     */
+    public void mousePressed(MouseEvent event) {
+    }
+
+    /** Any implementation of MouseListener must include this method so
+     * we can be informed when the mouse is released (end of click).
+     * @param event A MouseEvent containing all the information about
+     * this mouse action.
+     */
+    public void mouseReleased(MouseEvent event) {
+	try {
+	switch(this.type) {
+	case 0: // this.ADD
+	    if(this.temp_path != null && isAppropriate(temp_path)) {
+		super.addSelectionPath(this.temp_path);
+		this.temp_path = null;
+	    }
+	    if(this.temp_paths != null && isAppropriate(temp_paths, true)) {
+		super.addSelectionPaths(this.temp_paths);
+		this.temp_paths = null;
+	    }
+	    this.type = this.NONE;
+	    break;
+	case 1: // this.SET
+	    if(this.temp_path != null) {
+		super.setSelectionPath(this.temp_path);
+		this.temp_path = null;
+	    }
+	    if(this.temp_paths != null && isAppropriate(temp_paths, false)) {
+		super.setSelectionPaths(this.temp_paths);
+		this.temp_paths = null;
+	    }
+	    this.type = this.NONE;
+	    break;
+	}
+	}
+	catch (Exception error) {
+		DebugStream.printStackTrace(error);
+	}
+    }
+
+    public void setImmediate(boolean value) {
+	immediate = value;
+    }
+
+    public void setSelectionPath(TreePath path) {
+	// Since this is only a single path we don't need to check whether its an appropriate selection.
+	if(!immediate) {
+	    this.temp_path = path;
+	    this.type = this.SET;
+	}
+	else {
+	    temp_path = null;
+	    super.setSelectionPath(path);
+	}
+    }
+
+    public void setSelectionPaths(TreePath paths[]) {
+	if(!immediate) {
+	    this.temp_paths = paths;
+	    this.type = this.SET;
+	}
+	else if(isAppropriate(paths, false)) {
+	    temp_paths = null;
+	    super.setSelectionPaths(paths);
+	}
+    }
+
+    /** Ensure that the given path is appropriate to add to the current selection, preventing mixed selections of files and folder if required. We also must check that no path is a ancestor/descendant of another.
+     */
+    private boolean isAppropriate(TreePath path) {
+	boolean appropriate = true;
+	TreeNode new_node = (TreeNode) path.getLastPathComponent();
+	// If there is a current selection
+	if(selection != null && selection.length > 0) {
+	    for(int i = 0; appropriate && i < selection.length; i++) {
+		TreeNode current_node = (TreeNode) selection[i].getLastPathComponent();
+		appropriate = appropriate && (mixed_selection || new_node.isLeaf() == current_node.isLeaf());
+		appropriate = appropriate && !path.isDescendant(selection[i]) && !selection[i].isDescendant(path);
+	    }
+	}
+	return appropriate;
+    }
+    /** Ensure that the given paths are appropriate to add to the current selection, preventing mixed selections of files and folder if required. We also must check that no path is a ancestor/descendant of another. One last detail to keep in mind is that adding selections depends upon the current selection, whereas set the selection paths doesn't (replaces them instead) and thus no check of the current paths is needed. */
+    private boolean isAppropriate(TreePath[] paths, boolean check_current) {
+	boolean appropriate = true;
+	if(check_current && paths != null && paths.length > 0) {
+	    for(int i = 0; appropriate && i < paths.length; i++) {
+		appropriate = appropriate && isAppropriate(paths[i]);
+	    }
+	}
+	return appropriate;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/ExternalProgram.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/ExternalProgram.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/ExternalProgram.java	(revision 13928)
@@ -0,0 +1,107 @@
+package org.greenstone.gatherer.util;
+
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import org.greenstone.gatherer.DebugStream;
+
+
+/**
+ * This class provides a convenient method of running external programs and viewing/analysing
+ * their output. The external programs may be run with or without arguments. 
+ */
+public class ExternalProgram
+{
+    private Process programProcess = null;
+
+    private BufferedReader programOut = null;
+    private BufferedReader programErr = null;
+
+
+    /**
+     * Prepares to run a specified external program with the specified arguments.
+     *
+     * @param programName The name (and path, if necessary) of the program to run.
+     * @param programArgs The arguments to provide to the program when run.
+     */
+    public ExternalProgram(String programName, String programArgs)
+	throws IOException
+    {
+	// Run the program
+	programProcess = Runtime.getRuntime().exec(programName + " " + programArgs);
+
+	// Grab the program output
+	programOut = new BufferedReader(new InputStreamReader(programProcess.getInputStream()));
+	programErr = new BufferedReader(new InputStreamReader(programProcess.getErrorStream()));
+
+    }
+
+
+
+    /**
+     */
+    public int exitProgram()
+	throws IOException
+    {
+	// Finished, thank you
+	//programIn.close();
+
+	// Wait for the process to finish
+	try {
+	    programProcess.waitFor();
+	}
+	catch (InterruptedException ex) {
+	    throw new Error("Internal Error: Process interrupted.\n" + ex);
+	}
+
+	// Return the program exit value
+	return programProcess.exitValue();
+    }
+
+
+    /**
+     * Returns a single line of output sent by the program to standard output.
+     *
+     * @return a single line of output sent by the program to standard output.
+     */
+    public String getLineOfProgramOutput()
+    {
+	// Read in a line from the program output
+	try {
+	    if (programOut.ready())
+		return programOut.readLine();
+	    else
+		return null;
+	}
+	catch (IOException ex) {
+	    DebugStream.println("Error: Exception occurred while reading program output.");
+	    DebugStream.println("Exception: " + ex);
+	    return null;
+	}
+    }
+
+
+    /**
+     * Returns a single line of output sent by the program to standard error.
+     *
+     * @return a single line of output sent by the program to standard error.
+     */
+    public String getLineOfProgramError()
+    {
+	// Read in a line from the program error
+	try {
+	    if (programErr.ready())
+		return programErr.readLine();
+	    else
+		return null;
+	}
+	catch (IOException ex) {
+	    DebugStream.println("Error: Exception occurred while reading program error.");
+	    DebugStream.println("Exception: " + ex);
+	    return null;
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/HTMLStringTokenizer.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/HTMLStringTokenizer.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/HTMLStringTokenizer.java	(revision 13928)
@@ -0,0 +1,142 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.util;
+
+
+/** This class functions much like a <strong>StringTokenizer</strong> in that it tokenizes a long string into tokens, however this tokenizer cleverly notices HTML formatting tags. */
+public class HTMLStringTokenizer {
+    /** The current position in the source string. */
+    private int pos = 0;
+    /** The current token, usually created by the last nextToken call. */
+    private String current = null;
+    /** The previous token. */
+    private String previous = null;
+    /** The string to be tokenized, including any HTML markup. */
+    private String source = null;
+    /** Constructor.
+     * @param source The source <strong>String</strong> to be tokenized.
+     */
+    public HTMLStringTokenizer(String source) {
+	this.source = source;
+	// Parse the first token.
+	parseToken();
+    }
+
+    /** Determines if there are still tokens remaining unparsed in the source.
+     * @return A <strong>boolean</strong> which is <i>true</i> if there are more tokens.
+     */ 
+    public boolean hasMoreTokens() {
+	if(current != null && current.length() > 0) {
+	    return true;
+	}
+	return false;
+    } 
+
+    /** Determines if the tag currently being returned by sameToken is a tag.
+     * @return A <strong>boolean</strong> indicating if the token is a tag.
+     */
+    public boolean isTag() {
+	if(previous.startsWith("<") && previous.endsWith(">")) {
+	    return true;
+	}
+	return false;
+    }
+
+    /** Retrieves the next token. 
+     * @return A <strong>String</strong> representing the token.
+     */
+    public String nextToken() {
+	previous = current;
+	// Get the next token.
+	parseToken();
+	// Return previous.
+	return previous;
+    }
+
+    /** Parses the next token and stores it in current.
+     */
+    private void parseToken() {
+	boolean found = false;
+	boolean tag = false;
+	boolean text = false;
+	// Reset current
+	current = "";
+	// Parse away
+	dumpWhiteSpace();
+	while(pos < source.length() && !found) {
+	    char c = (char)source.charAt(pos);
+	    if(!tag && !text) {
+		if(c == '<') {
+		    tag = true;
+		}
+		else {
+		    text = true;
+		}
+		current = current + c;
+	    }
+				// Reading a tag. Watch only for '>'.
+	    else if(tag) {
+		if(c == '>') {
+		    found = true;
+		}
+		current = current + c;
+	    }
+				// Reading text. Watch for ' ' and '<'. Rollback '<'.
+	    else if(text) {
+		if(c == ' ') {
+		    found = true;
+		}
+		else if(c == '<') {
+		    found = true;
+		    pos--;
+		}
+		else {
+		    current = current + c;
+		}
+	    }
+	    pos++;
+	}
+    }
+
+    /** Method to ignore whitespace in the source.
+     */
+    private void dumpWhiteSpace() {
+	while(pos < source.length() && source.charAt(pos) == ' ') {
+	    pos++;
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/HashMap3D.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/HashMap3D.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/HashMap3D.java	(revision 13928)
@@ -0,0 +1,138 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.util;
+
+/**************************************************************************************
+ * Written:      20/08/02
+ * Revised:      
+ **************************************************************************************/
+import java.util.HashMap;
+import java.util.Iterator;
+
+/** Provides a HashMap implementation that indexes by two keys. Perfect for the storage of metadata references based on their metadata element and assigned value. 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class HashMap3D
+    extends HashMap {
+
+    private int capacity = 4;
+
+    private int size = 0;
+
+    private Object last_key_one = null;
+    private Object last_key_two = null;
+    private Object last_value = null;
+
+    /** Default constructor.
+     */
+    public HashMap3D() {
+	super();
+    }
+    /** Constructor with a specific initial capacity.
+     * @param capacity The initial capacity as an <i>int</i>.
+     */
+    public HashMap3D(int capacity) {
+	super(capacity);
+	this.capacity = capacity;
+    }
+    /** Completely remove the contents of this HashMap and its child HashMaps. */
+    public void clear() {
+	size = 0;
+	Iterator iterator = values().iterator();
+	while(iterator.hasNext()) {
+	    HashMap inner_mapping = (HashMap) iterator.next();
+	    inner_mapping.clear();
+	    inner_mapping = null;
+	}
+	iterator = null;
+	super.clear();
+    }
+    /** Determine if this hash map contains an entry for the given keys. Also cache this entry because theres a good chance the next get call will ask for this entry.
+     * @param key_one The first key as an <strong>Object</strong>.
+     * @param key_two The second key as an <strong>Object</strong>.
+     * @return <i>true</i> if such an entry exists, <i>false</i> otherwise.
+     */
+    public boolean contains(Object key_one, Object key_two) {
+	boolean result = false;
+	// Retrieve the hash mapping at key_one.
+	HashMap map = (HashMap) get(key_one);
+	// If there is such a map then retrieve the value at key_two.
+	if(map != null) {
+	    last_value = map.get(key_two);
+	    if(last_value != null) {
+		last_key_one = key_one;
+		last_key_two = key_two;
+		result = true;
+	    }
+	}
+	return result;
+    }
+
+    /** Retrieve an entry from this three dimensional hash mapping.
+     * @param key_one The first key as an <strong>Object</strong>.
+     * @param key_two The second key as an <strong>Object</strong>.
+     * @return The value <strong>Object</strong> located at (key_one, key_two), or <i>null</i> if no such value.
+     */
+    public Object get(Object key_one, Object key_two) {
+	Object result = null;
+	if(key_one.equals(last_key_one) && key_two.equals(last_key_two)) {
+	    result = last_value;
+	}
+	else {
+	    // Retrieve the hash mapping at key_one.
+	    HashMap map = (HashMap) get(key_one);
+	    // If there is such a map then retrieve the value at key_two.
+	    if(map != null) {
+		result = map.get(key_two);
+		if(result != null) {
+		    last_key_one = key_one;
+		    last_key_two = key_two;
+		    last_value = result;
+		}
+	    }
+	}
+	return result;
+    }
+
+    /** Put an entry into this three dimensional hash mapping.
+     * @param key_one The first key, to store this value under, as an <strong>Object</strong>.
+     * @param key_two The second key, to store this value under, as an <strong>Object</strong>.
+     * @param value The value <strong>Object</strong> itself.
+     */
+    public void put(Object key_one, Object key_two, Object value) {
+	// Retrieve the hash mapping at key_one, or if none exists create one.
+	HashMap map = (HashMap) get(key_one);
+	if(map == null) {
+	    map = new HashMap(capacity);
+	    put(key_one, map);
+	}
+	// Now add the value to this mapping.
+	map.put(key_two, value);
+	size++;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/JarTools.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/JarTools.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/JarTools.java	(revision 13928)
@@ -0,0 +1,141 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2005 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.util;
+
+
+import java.awt.*;
+import java.io.*;
+import java.net.*;
+import javax.swing.*;
+import org.greenstone.gatherer.DebugStream;
+
+
+public class JarTools
+{
+    static private Class root_class = null;
+    static private ImageIcon ERROR_ICON = null; 
+
+
+    static public void initialise(Object root_object)
+    {
+	root_class = root_object.getClass();
+	ERROR_ICON = getImage("error.gif");
+    }
+
+
+    static public void extractFromJar(String filename, String dst_dir, boolean must_be_present) 
+    {
+	try {
+	    // setup input stream for slurping out file
+	    InputStream fis = root_class.getResourceAsStream("/"+filename);
+	    BufferedInputStream fbis = new BufferedInputStream(fis); 
+	    DataInputStream fdbis = new DataInputStream(fbis);
+
+	    // set up output stream for writing to disk
+	    String ofname = dst_dir + filename;
+	    FileOutputStream fos = new FileOutputStream(ofname);
+	    BufferedOutputStream bfos = new BufferedOutputStream(fos);
+
+	    byte[] buf = new byte[1024];
+	    int len;
+	    int total_bytes = 0;
+	    while ((len = fdbis.read(buf)) >= 0) {
+		bfos.write(buf,0,len);
+		total_bytes += len;
+	    }
+
+	    fdbis.close();
+	    bfos.close();
+	}
+	catch (Exception exception) {
+	    if (must_be_present) {
+		exception.printStackTrace();
+	    }
+	}
+    }
+
+
+    /** Method to retrieve an image icon with the given filename found in classpath or the resouces directory.
+     *  @return The specified <strong>ImageIcon</strong>, or an error image replacement if no such images exists.
+     */
+    static public ImageIcon getImage(String filename) {
+	return getImage(filename, false);
+    }
+
+    static public ImageIcon getImage(String filename, boolean wait_until_complete)
+    {
+	ImageIcon image = null;
+	try {
+	    image = new ImageIcon(root_class.getResource("/images/" + filename));
+	}
+	catch (NullPointerException exception) {
+	    System.err.println("Error: Could not load image " + filename);
+	    DebugStream.println("Error: Could not load image " + filename);
+	}
+
+	if (image == null) {
+	    image = ERROR_ICON;
+	}
+
+	if (wait_until_complete) {
+	    int load_status;
+	    do {
+		load_status = image.getImageLoadStatus();
+	    }
+	    while (load_status != MediaTracker.ABORTED && load_status != MediaTracker.ERRORED && load_status != MediaTracker.COMPLETE);
+	}
+
+	return image;
+    }
+
+
+    static public URL getResource(String resource_name)
+    {
+	return root_class.getResource(resource_name);
+    }
+
+
+    static public InputStream getResourceAsStream(String resource_name)
+    {
+	return root_class.getResourceAsStream(resource_name);
+    }
+
+
+    static public boolean isInJar(String filename) 
+    {
+	try {
+	    InputStream fis = root_class.getResourceAsStream("/" + filename);		    
+	    fis.close();
+	}
+	catch (Exception exception) {
+	    exception.printStackTrace();
+	    return false;
+	}
+
+	return true;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/PatternTokenizer.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/PatternTokenizer.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/PatternTokenizer.java	(revision 13928)
@@ -0,0 +1,72 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.util;
+
+public class PatternTokenizer {
+    private int index;
+    private String content;
+    private String pattern;
+    public PatternTokenizer(String content, String pattern) {
+	this.content = content;
+	this.index = 0;
+	this.pattern = pattern;
+    }
+    public boolean hasMoreTokens() {
+	return (index != -1 && content.length() - index > 0);
+    }
+    public String nextToken() {
+	// Special case when index is zero
+	if(index == 0) {
+	    index = content.indexOf(pattern);
+	    // No occurance of pattern, return whole string
+	    if(index == -1) {
+		return content;
+	    }
+	    // Return the fragment from 0 to index
+	    else {
+		return content.substring(0, index);
+	    }
+	}
+	// Otherwise
+	else {
+	    // We must first skip the pattern, as it should be at the head of our current view into content
+	    index = index + pattern.length();
+	    int end_index = content.indexOf(pattern, index);
+	    String fragment;
+	    // No occurance of pattern, return fragment from index to length
+	    if(end_index == -1) {
+		fragment = content.substring(index);
+	    }
+	    // Return the fragment from index to end index, then set index to end index
+	    else {
+		fragment = content.substring(index, end_index);
+	    }
+	    index = end_index;
+	    return fragment;
+	}
+    }    
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/StaticStrings.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/StaticStrings.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/StaticStrings.java	(revision 13928)
@@ -0,0 +1,223 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.util;
+
+
+/** Were you to guess that this is a class object choc-a-block full of static stringy goodness, you'd be right. They come in several flavours: Those ending _STR are strings you might find as values in XML, _ELEMENT are element names, _ATTRIBUTE are attribute names, _CHAR are particular characters while _CHARACTER are also characters but expressed as strings (for regex purposes ie startsWith, endsWith, indexOf and replaceAll); _PATTERN are strings which require extra escaping to put them through regex. Finally anything else is just a static string used within GLI. */
+public class StaticStrings {
+    static final public char CLOSEBRACKET_CHAR = ']';
+    static final public char DOUBLEQUOTE_CHAR = '\"';
+    static final public char BACKSLASH_CHAR = '\\';
+    static final public char FORWARDSLASH_CHAR = '/';
+    static final public char NEW_LINE_CHAR = '\n';
+    static final public char NS_SEP = '.';
+    static final public char OPENBRACKET_CHAR = '[';
+    static final public char SINGLEQUOTE_CHAR = '\'';
+    static final public char SPACE_CHAR = ' ';
+    static final public char STAR_CHAR = '*';
+    static final public String ACCENTFOLD_OPTION_STR = "accentfold";
+    static final public String ALLFIELDS_STR = "allfields";
+    static final public String ARCPLUG_STR = "ArcPlug";
+    static final public String ASSIGNED_ATTRIBUTE = "assigned";
+    static final public String ASSOCIATIONS_ELEMENT = "Associations";
+    static final public String ATTRIBUTE_ELEMENT = "Attribute";
+    static final public String BUILDTYPE_ELEMENT = "BuildType";
+    static final public String BUILDTYPE_STR = "buildtype";
+    static final public String CASEFOLD_OPTION_STR = "casefold";
+    static final public String CCS_STR = "ccs";
+    static final public String CLASSIFY_ELEMENT = "Classify";
+    static final public String CLASSIFY_STR = "classify";
+    static final public String CLOSE_PARENTHESIS_CHARACTER = ")";
+    static final public String CODE_ATTRIBUTE = "code";
+    static final public String COLNAME_PATTERN = "<col_name>";
+    static final public String COLLECT_CFG = "collect.cfg";
+    static final public String COLLECTDIR_ARGUMENT = "-collectdir";
+    static final public String COLLECTION_ELEMENT = "Collection";
+    static final public String COLLECTION_STR = "Collection: ";
+    static final public String COLLECTIONMETADATA_COLLECTIONNAME_STR = "collectionname";
+    static final public String COLLECTIONMETADATA_COLLECTIONEXTRA_STR = "collectionextra";
+    static final public String COLLECTIONMETADATA_CREATOR_ELEMENT = "Creator";
+    static final public String COLLECTIONMETADATA_CREATOR_STR = "creator";
+    static final public String COLLECTIONMETADATA_ELEMENT = "CollectionMetadata";
+    static final public String COLLECTIONMETADATA_ICONCOLLECTION_STR = "iconcollection";
+    static final public String COLLECTIONMETADATA_ICONCOLLECTIONSMALL_STR = "iconcollectionsmall";
+    static final public String COLLECTIONMETADATA_MAINTAINER_ELEMENT = "Maintainer";
+    static final public String COLLECTIONMETADATA_MAINTAINER_STR = "maintainer";
+    static final public String COLLECTIONMETADATA_PUBLIC_ELEMENT = "Public";
+    static final public String COLLECTIONMETADATA_PUBLIC_STR = "public";
+    static final public String COLLECTIONMETADATA_STR = "collectionmeta";
+    static final public String COLON_CHARACTER = ":";
+    static final public String COMMA_CHARACTER = ",";
+    static final public String COMMENTED_INDEXES_STR = "#indexes";
+    static final public String COMMENTED_INDEX_DEFAULT_STR = "#defaultindex";
+    static final public String COMMENTED_LEVELS_STR = "#levels";
+    static final public String COMMENTED_LEVEL_DEFAULT_STR = "#defaultlevel";
+    static final public String COMMENTED_STEMOPTIONS_STR = "#indexoptions";
+    static final public String CONTENT_ATTRIBUTE = "content";
+    static final public String CONTENT_ELEMENT = "content";
+    static final public String DATELIST_CLASSIFIER = "DateList";
+    static final public String DEBUG_ARGUMENT = "-debug";
+    static final public String DESCRIPTION_ELEMENT = "Description";
+    static final public String DIRECTORY_MAPPINGS_ELEMENT = "DirectoryMappings";
+    static final public String DOCUMENT_STR = "document";
+    static final public String EMPTY_STR = "";
+    static final public String ENGLISH_LANGUAGE_STR = "en";
+    static final public String ENTRY_ELEMENT = "Entry";
+    static final public String ENUM_STR = "enum";
+    static final public String EQUALS_CHARACTER = "=";
+    static final public String EXCLAMATION_CHARACTER = "!";
+    static final public String EXCLUDE_STR = "exclude";
+    static final public String EXTENSION_ATTRIBUTE = "extension";
+    static final public String EXTRACTED_NAMESPACE = "ex.";
+    static final public String FALSE_STR = "false";
+    static final public String FEEDBACK_ARGUMENT = "-feedback";
+    static final public String FILE_ATTRIBUTE = "file";
+    static final public String FILENAME_STR = "Filename";
+    static final public String FLAG_STR = "flag";
+    static final public String FORMAT_ELEMENT = "Format";
+    static final public String FORMAT_STR = "format";
+    static final public String FURTHER_DIALOG_INDICATOR = "...";
+    static final public String GLI_ATTRIBUTE = "gli";
+    static final public String GLISERVER_URL_ARGUMENT = "-gliserver_url";
+    static final public String GREATER_THAN_CHARACTER = ">";
+    static final public String GSDL_ARGUMENT = "-gsdl";
+    static final public String GSDL3_ARGUMENT = "-gsdl3";
+    static final public String GSDL3_SRC_ARGUMENT = "-gsdl3src";
+    static final public String GSDLOS_ARGUMENT = "-gsdlos";
+    static final public String HFILE_ARGUMENT = "-hfile";
+    static final public String HIERARCHY_CLASSIFIER = "Hierarchy";
+    static final public String HIERARCHY_STR = "hierarchy";
+    static final public String HELP_ARGUMENT = "-help";
+    static final public String HTM_FILE_EXTENSION = ".htm";
+    static final public String IMAGES_PATH_RELATIVE_TO_GSDL_PREFIX = "_httpprefix_/collect/<col_name>/images/";
+    static final public String INCLUDE_STR = "include";
+    static final public String INDEX_ELEMENT = "Index";
+    static final public String INDEX_DEFAULT_ELEMENT = "DefaultIndex";
+    static final public String INDEX_DEFAULT_STR = "defaultindex";
+    static final public String INDEX_STR = "indexes";
+    static final public String INDEXES_ELEMENT = "Indexes";
+    static final public String INDEXOPTION_ELEMENT = "Option";
+    static final public String INDEXOPTIONS_ELEMENT = "IndexOption";
+    static final public String INDEXOPTION_DEFAULT_ELEMENT = "DefaultIndexOption";
+    static final public String INT_STR = "int";
+    static final public String[] KEEP_PLUG = { "GAPlug", "METSPlug" };
+    static final public String LANGUAGE_ARGUMENT = "l=";
+    static final public String LANGUAGE_ATTRIBUTE = "language";
+    static final public String LANGUAGE_ELEMENT = "Language";
+    static final public String LANGUAGE_DEFAULT_ELEMENT = "DefaultLanguage";
+    static final public String LANGUAGE_DEFAULT_STR = "defaultlanguage";
+    static final public String LANGUAGE_METADATA_ELEMENT = "LanguageMetadata";
+    static final public String LANGUAGE_METADATA_STR = "languagemetadata";
+    static final public String LANGUAGE_STR = "language";
+    static final public String LANGUAGES_ELEMENT = "Languages";
+    static final public String LANGUAGES_STR = "languages";
+    static final public String LBRACKET_CHARACTER = "[";
+    static final public String LESS_THAN_CHARACTER = "<";
+    static final public String LEVEL_ATTRIBUTE = "level";
+    static final public String LEVEL_DEFAULT_STR = "defaultlevel";
+    static final public String LEVELS_STR = "levels";
+    static final public String LIBRARY_URL_ARGUMENT = "-library_url";
+    static final public String LOCAL_LIBRARY_ARGUMENT = "-local_library";
+    static final public String LOAD_ARGUMENT = "-load";
+    static final public String MAC_OPEN_COMMAND = "open %1";
+    static final public String MAPPING_ELEMENT = "Mapping";
+    static final public String MDS_ATTRIBUTE = "mds";
+    static final public String METADATA_ARGUMENT = "-metadata";
+    static final public String METADATA_ELEMENT = "Metadata";
+    static final public String METADATA_SET_EXTENSION = ".mds";
+    static final public String METADATA_STR = "metadata";
+    static final public String METADATA_TYPE_STR = "metadata";
+    static final public String METADATA_XML = "metadata.xml";
+    static final public String METADATAXMLPLUG_STR = "MetadataXMLPlug";
+    static final public String METADATUM_TYPE_STR = "metadatum";
+    static final public String MGPP_ATTRIBUTE = "mgpp_enabled";
+    static final public String MINUS_CHARACTER = "-";
+    static final public String MODE_STR = "Mode: ";
+    static final public String MODEL_COLLECTION_NAME = "modelcol";
+    static final public String NAME_ATTRIBUTE = "name";
+    static final public String NAME_ELEMENT = "Name";
+    static final public String NEWLINE_CHARACTER = "\\";
+    static final public String NO_LOAD_ARGUMENT = "-no_load";
+    static final public String ONE_CHARACTER = "1";
+    static final public String OPEN_PARENTHESIS_CHARACTER = "(";
+    static final public String OPTION_ELEMENT = "Option";
+    static final public String OPTIONS_ATTRIBUTE = "options";
+    static final public String PARAGRAPH_STR = "paragraph";
+    static final public String PERL_ARGUMENT = "-perl";
+    static final public String PHIND_CLASSIFIER = "Phind";
+    static final public String PLUGIN_ELEMENT = "Plugin";
+    static final public String PLUGIN_STR = "plugin";
+    static final public String PREDEFINED_METADATA_ATTRIBUTE = "predefined";          
+    static final public String RBRACKET_CHARACTER = "]";
+    static final public String RECPLUG_STR = "RecPlug";
+    static final public String REGEXP_STR = "regexp";
+    static final public String RESTRICTED_METADATA_ATTRIBUTE = "restricted";
+    static final public String SEARCHTYPE_STR = "searchtype";
+    static final public String SECTION_ELEMENT = "Section";
+    static final public String SECTION_STR = "section";
+    static final public String SEPARATOR_ATTRIBUTE = "separator";
+    static final public String SEPARATOR_CHARACTER = "/";
+    static final public String SERVLET_ARGUMENT ="-servlet";
+    static final public String SINGLE_QUOTE_CHARACTER = "'";
+    static final public String SITE_ARGUMENT = "-site";
+    static final public String SPACE_CHARACTER = " ";
+    static final public String SPECIAL_ATTRIBUTE = "special";
+    static final public String SPEECH_CHARACTER = "\"";
+    static final public String STEM_OPTION_STR = "stem";
+    static final public String STEMOPTIONS_STR = "indexoptions";
+    static final public String STOP_CHARACTER = ".";
+    static final public String SUBCOLLECTION_ELEMENT = "Subcollection";
+    static final public String SUBCOLLECTION_STR = "subcollection";
+    static final public String SUBCOLLECTION_DEFAULT_INDEX_ELEMENT = "DefaultSubcollection";
+    static final public String SUBCOLLECTION_DEFAULT_INDEX_STR = "defaultsubcollection";
+    static final public String SUBCOLLECTION_INDEX_STR = "indexsubcollections";
+    static final public String SUBCOLLECTION_INDEXES_ELEMENT = "SubcollectionIndexes";
+    static final public String SUPERCOLLECTION_ELEMENT = "Supercollection";
+    static final public String SUPERCOLLECTION_STR = "supercollection";
+    static final public String TAB_CHARACTER = "\t";
+    static final public String TEXT_NODE = "#text";
+    static final public String TEXT_STR = "text";
+    static final public String TIMESTAMP_ARGUMENT = "&uq=";
+    static final public String TITLE_ELEMENT = "Title";
+    static final public String TRUE_STR = "true";
+    static final public String TYPE_ATTRIBUTE = "type";
+    static final public String UNKNOWN_ELEMENT = "Unknown";
+    static final public String UNKNOWNPLUG_STR = "UnknownPlug";
+    static final public String USE_METADATA_FILES_ARGUMENT = "use_metadata_files";
+    static final public String USE_REMOTE_GREENSTONE_ARGUMENT = "-use_remote_greenstone";
+    static final public String URL_SEPARATOR_CHARACTER = "/";
+    static final public String VALUE_ATTRIBUTE = "value";
+    static final public String VERSION_ATTRIBUTE = "version";
+    static final public String WIN_9X_OPEN_COMMAND = "command.com /c start \"%1\"";
+    static final public String WIN_OPEN_COMMAND = "cmd.exe /c start \"\" \"%1\"";
+    static final public String YES_STR = "yes";
+    static final public String ZERO_CHARACTER = "0";
+    static final public String METADATA_PATH                              = "-metadata_path";
+    static final public String NEW_METADATASET                            = "-new_set";
+    static final public String CACHE_FOLDER                               = "cache";
+    static final public String CUSTOM_ATTRIBUTE                           = "custom";
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/SynchronizedTreeModelTools.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/SynchronizedTreeModelTools.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/SynchronizedTreeModelTools.java	(revision 13928)
@@ -0,0 +1,123 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.gatherer.util;
+
+import java.lang.Runnable;
+import javax.swing.SwingUtilities;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.DebugStream;
+
+/** Due to the TreeModel objects not having any synchronization, certain assumptions, such as the model state remaining constant during a repaint, don't always hold - especially given that I'm changing the tree model on a different thread. In order to get around this I will use the latest swing paradigm wherein you flag a section of code to be executed by the AWT GUI Event queue, as soon as other gui tasks have finished. This way I shouldn't have tree redraws throwing NPEs because the array size of the children of a certain node has changed -while- the repaint call was made, i.e. repaint() calls getChildCount() = 13, removeNodeFromParent() called, repaint calls getChildAt(12) = ArrayIndexOutOfBoundsException. 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3c
+ */
+public class SynchronizedTreeModelTools {
+    /** Adds an insertNodeInto model update onto the AWT Event queue. This gets around the lack of synchronization illustrated above. */
+    static final public Runnable insertNodeInto(DefaultTreeModel model, MutableTreeNode parent, MutableTreeNode target_node) {
+	return insertNodeInto(model, parent, target_node, true);
+    }
+
+    static final public Runnable insertNodeInto(final DefaultTreeModel model, final MutableTreeNode parent, final MutableTreeNode target_node, final boolean wait_allowed) {
+	final Runnable doInsertNodeInto = new Runnable() {
+		public void run() {
+		    ///ystem.err.print("Running task... ");
+		    DebugStream.println("insertNodeInto(" + model + ", " + parent + ", " + target_node + ", " + wait_allowed);
+		    int index = -1;
+		    int pos = 0;
+		    while(index == -1 && pos < parent.getChildCount()) {
+			TreeNode node = parent.getChildAt(pos);
+			int result = 0;
+			///ystem.err.println("Compare " + target_node + " to " + node);
+			if((target_node.isLeaf() && node.isLeaf()) || (!target_node.isLeaf() && !node.isLeaf())) {
+			    result = target_node.toString().toLowerCase().compareTo(node.toString().toLowerCase());
+			}
+			else if(target_node.isLeaf()) {
+			    result = 1;
+			}
+			else {
+			    result = -1;
+			}
+			if(result > 0) {
+			    ///ystem.err.println("Keep searching...");
+			    pos++;
+			}
+			else {
+			    ///ystem.err.println("Found!");
+			    index = pos;
+			}
+		    }
+		    if(index == -1) {
+			index = parent.getChildCount();
+		    }
+		    model.insertNodeInto(target_node, parent, index);
+		}
+	    };
+	///ystem.err.print("Queuing Task... ");
+	try {
+	    if(wait_allowed && !SwingUtilities.isEventDispatchThread()) {
+		///ystem.err.print("In another thread - invoke and wait... ");
+		SwingUtilities.invokeAndWait(doInsertNodeInto);
+	    }
+	    else {
+		///ystem.err.print("In Event Thread or wait not allowed - invoke later... ");
+		SwingUtilities.invokeLater(doInsertNodeInto);
+	    }
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+	///ystem.err.print("Added Task... ");
+	return doInsertNodeInto;
+    }
+
+
+    /** Adds a removeNodeFromParent model update onto the AWT Event queue. This gets around the lack of synchronization illustrated above.
+     * @param model The <strong>GTreeModel</strong> we want to remove the node from.
+     * @param target_node The <strong>GTreeNode</strong> to remove.
+     */
+    static final public void removeNodeFromParent(final DefaultTreeModel model, final MutableTreeNode target_node) {
+	///ystem.err.println("Remove " + target_node + " from parent in model " + model);
+	final Runnable doRemoveNodeFromParent = new Runnable() {
+		public void run() {
+		    model.removeNodeFromParent(target_node);
+		}
+	    };
+	try {
+	    //SwingUtilities.invokeLater(doRemoveNodeFromParent);
+	    SwingUtilities.invokeAndWait(doRemoveNodeFromParent);
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+	// If we've thrown an error because we tried to invoke the runnable task and wait, when we are in the AWTEvent thread already, then try agin but with an invoke later.
+	catch (java.lang.Error error) {
+	    if(error.toString().equals("java.lang.Error: Cannot call invokeAndWait from the event dispatcher thread")) {
+		SwingUtilities.invokeLater(doRemoveNodeFromParent);
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/TableUtils.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/TableUtils.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/TableUtils.java	(revision 13928)
@@ -0,0 +1,92 @@
+package org.greenstone.gatherer.util;
+
+import java.awt.*;
+import javax.swing.*;
+import javax.swing.table.*;
+
+/**
+ * Utilites for manipulating JTables.
+ *
+ * @author Marc Hedlund
+ *   <a href="mailto:marc@precipice.org">&lt;marc@precipice.org&gt;</a>
+ * @version $Revision$
+ */
+
+public class TableUtils  {
+
+  // This is based on code found at
+  // <http://java.sun.com/docs/books/tutorial/ui/swingComponents/table.html>,
+  // somewhat modified.
+
+//    public static void setPreferredCellSizes(JTable table) {
+//      TableModel model = table.getModel();
+//      TableColumnModel colModel = table.getColumnModel();
+
+//      for (int i = 0; i < model.getColumnCount(); i++) {
+//        TableColumn column = colModel.getColumn(i);
+
+//        int longestCell = 0;
+//        int highestCell = 0;
+
+//        for (int j = 0; j < model.getRowCount(); j++) {
+//          Object value = model.getValueAt(j, i);
+//          if (value == null) continue;
+
+//          Component cell =
+//            table.getDefaultRenderer(model.getColumnClass(i)).
+//            getTableCellRendererComponent(table, value,
+//                                          false, false, j, i);
+
+//          int width = cell.getPreferredSize().width;
+//          int height = cell.getPreferredSize().height;
+
+//          if (width > longestCell) longestCell = width;         
+//          if (height > highestCell) highestCell = height;
+//        }
+
+//        Component headerComp = column.getHeaderRenderer().
+//          getTableCellRendererComponent(table, column.getHeaderValue(),
+//                                        false, false, 0, 0);
+
+//        int headerWidth = headerComp.getPreferredSize().width;
+//        int headerHeight = headerComp.getPreferredSize().height;
+
+//        column.setPreferredWidth(Math.max(headerWidth, longestCell));
+
+//        int currentHeight = table.getRowHeight();
+//        int preferredHeight = Math.max(headerHeight, highestCell);
+
+//        table.setRowHeight(Math.max(currentHeight, preferredHeight));
+//      }
+//    }                                                                   
+
+  /**
+   * Takes a column in an existing table and makes it fixed-width.
+   * Specifically, it sets the column's minimum and maximum widths to
+   * its preferred width, and disables auto-resize for the table as a
+   * whole.
+   *
+   * <p>
+   *
+   * Later on this should take a column array for efficiency.
+   *
+   * @param table JTable The table to modify
+   * @param colIndex int Which column to fix
+   * @return int The width of the column as it was fixed
+   */
+
+  public static int fixColumnToPreferredWidth(JTable table, int colIndex) {
+    table.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
+
+    TableColumnModel tcm = table.getColumnModel();
+    TableColumn col = tcm.getColumn(colIndex);
+    int width = col.getPreferredWidth();
+
+    col.setMaxWidth(width);
+    col.setMinWidth(width);    
+
+    //table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
+
+    return width;
+  }
+}  
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/UnzipTools.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/UnzipTools.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/UnzipTools.java	(revision 13928)
@@ -0,0 +1,94 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: David Bainbridge, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2005 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.util;
+
+
+import java.io.*;
+import java.util.*;
+import java.util.zip.*;
+
+
+public class UnzipTools
+{
+    static public void unzipFile(String zip_file_path, String base_directory_path)
+    {
+	try {
+	    ZipFile zip_file = new ZipFile(new File(zip_file_path), ZipFile.OPEN_READ);
+	    
+	    Enumeration e = zip_file.entries(); 
+	    while (e.hasMoreElements()) {
+		ZipEntry zip_entry = (ZipEntry) e.nextElement();
+		File zip_entry_file = new File(base_directory_path + zip_entry.getName());
+		// System.err.println("    Unzipping: " + zip_entry_file.getAbsolutePath());
+
+		// Directory case
+		if (zip_entry.isDirectory()) {
+		    // Create named directory, if it doesn't already exist
+		    if (!zip_entry_file.exists() && !zip_entry_file.mkdirs()) {
+			System.err.println("Error: unable to create directory " + zip_entry_file);
+		    }
+		}
+
+		// File case
+		else {
+		    // Write out file to disk
+
+		    // Make sure its parent directory exists.
+		    File dir = new File(zip_entry_file.getParent());
+		    dir.mkdirs();
+
+		    // Set up input stream
+		    InputStream zis = zip_file.getInputStream(zip_entry); 
+		    BufferedInputStream bzis = new BufferedInputStream(zis); 
+		    DataInputStream dbzis = new DataInputStream(bzis);
+
+		    // Set up output stream
+		    FileOutputStream fzos = new FileOutputStream(zip_entry_file);
+		    BufferedOutputStream bfzos = new BufferedOutputStream(fzos);
+
+		    byte[] buf = new byte[1024];
+		    int len;
+		    while ((len = dbzis.read(buf)) >= 0) {
+			bfzos.write(buf,0,len);
+		    }
+
+		    dbzis.close();
+		    bzis.close();
+		    zis.close();
+
+		    bfzos.close();
+		    fzos.close();
+		}
+	    }
+
+	    zip_file.close();
+	} 
+	catch (Exception exception) {
+	    exception.printStackTrace();
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/Utility.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/Utility.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/Utility.java	(revision 13928)
@@ -0,0 +1,423 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+
+package org.greenstone.gatherer.util;
+
+
+// Don't even think about adding import java.awt.* here!
+// The functions in this class should not use any graphical classes. Put your function somewhere else buster!
+import java.io.*;
+import java.net.*;
+import java.util.*;
+// Don't even think about adding import javax.swing.* here!
+// The functions in this class should not use any graphical classes. Put your function somewhere else buster!
+import org.greenstone.gatherer.Dictionary;
+// Don't even think about adding import org.greenstone.gatherer.Gatherer in here!
+// The functions in this class should be independent of the Gatherer class. Put your function somewhere else buster!
+
+
+/** To provide a library of common methods, in a static context, for use in the Gatherer.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3b
+ */
+public class Utility
+{
+    /** Definition of an important directory name, in this case the file the collection configuration is expect to be in. */
+    static final public String CONFIG_FILE = "etc" + File.separator + "collect.cfg";
+    /** The default name of the perl executable under unix. */
+    static final public String PERL_EXECUTABLE_UNIX = "perl";
+    /** The default name of the perl executable under windows. */
+    static final public String PERL_EXECUTABLE_WINDOWS = "Perl.exe";
+
+
+    /**
+     * Delete a file or directory
+     * @param file The <strong>File</strong> you want to delete.
+     * @return A <i>boolean</i> which is <i>true</i> if the file specified was successfully deleted, <i>false</i> otherwise.
+     */
+    static public boolean delete(File file)
+    {
+	// Nothing to do if it doesn't exist
+	if (!file.exists()) {
+	    return true;
+	}
+
+	return deleteInternal(file);
+    }
+
+
+    /** Convenience function. */
+    static public boolean delete(String filename)
+    {
+	return delete(new File(filename));
+    }
+
+
+    /** In Java you have to make sure a directory is empty before you delete it, so recursively delete. */
+    static private boolean deleteInternal(File file)
+    {
+	// If file is a directory, we have to recursively delete its contents first
+	if (file.isDirectory()) {
+	    File files[] = file.listFiles();
+	    for (int i = 0; i < files.length; i++) {
+		if (deleteInternal(files[i]) == false) {
+		    System.err.println("Error: Could not delete folder " + file);
+		    return false;
+		}
+	    }
+	}
+
+	// Delete file
+	if (file.delete() == false) {
+	    System.err.println("Error: Could not delete file " + file);
+	    return false;
+	}
+
+	return true;
+    }
+
+
+    /** Convert a long, detailing the length of a file in bytes, into a nice human readable string using b, kb, Mb and Gb. */
+    static final public String BYTE_SUFFIX = " b";
+    static final public long GIGABYTE = 1024000000l;
+    static final public String GIGABYTE_SUFFIX = " Gb";
+    static final public long KILOBYTE =       1024l;
+    static final public String KILOBYTE_SUFFIX = " kb";
+    static final public long MEGABYTE =    1024000l;
+    static final public String MEGABYTE_SUFFIX = " Mb";
+    static final public String formatFileLength(long length) {
+	StringBuffer result = new StringBuffer("");
+	float number = 0f;
+	String suffix = null;
+	// Determine the floating point number and the suffix (radix) used.
+	if(length >= GIGABYTE) {
+	    number = (float) length / (float) GIGABYTE;
+	    suffix = GIGABYTE_SUFFIX;
+	}
+	else if(length >= MEGABYTE) {
+	    number = (float) length / (float) MEGABYTE;
+	    suffix = MEGABYTE_SUFFIX;
+	}
+	else if(length >= KILOBYTE) {
+	    number = (float) length / (float) KILOBYTE;
+	    suffix = KILOBYTE_SUFFIX;
+	}
+	else {
+	    // Don't need to do anything fancy if the file is smaller than a kilobyte
+	    return length + BYTE_SUFFIX;
+	}
+	// Create the formatted string remembering to round the number to 2.d.p. To do this copy everything in the number string from the start to the first occurance of '.' then copy two more digits. Finally search for and print anything that appears after (and including) the optional 'E' delimter.
+	String number_str = Float.toString(number);
+	char number_char[] = number_str.toCharArray();
+	int pos = 0;
+	// Print the characters up to the '.'
+	while(number_char != null && pos < number_char.length && number_char[pos] != '.') {
+	    result.append(number_char[pos]);
+	    pos++;
+	}
+	if(pos < number_char.length) {
+	    // Print the '.' and at most two characters after it
+	    result.append(number_char[pos]);
+	    pos++;
+	    for(int i = 0; i < 2 && pos < number_char.length; i++, pos++) {
+		result.append(number_char[pos]);
+	    }
+	    // Search through the remaining string for 'E'
+	    while(pos < number_char.length && number_char[pos] != 'E') {
+		pos++;
+	    }
+	    // If we still have string then we found an E. Copy the remaining string.
+	    while(pos < number_char.length) {
+		result.append(number_char[pos]);
+		pos++;
+	    }
+	}
+	// Add suffix
+	result.append(suffix);
+	// Done
+	return result.toString();
+    }
+
+    /** This method formats a given string, using HTML markup, so its width does not exceed the given width and its appearance if justified.
+     * @param text The <strong>String</strong> requiring formatting.
+     * @param width The maximum width per line as an <i>int</i>.
+     * @return A <strong>String</strong> formatted so as to have no line longer than the specified width.
+     * TODO Currently HTML formatting tags are simply removed from the text, as the effects of spreading HTML tags over a break are undetermined. To solve this we need to associate tags with a certain text token so if it gets broken on to the next line the tags go with it, or if the tags cover a sequence of words that are broken we need to close then reopen the tags. However all this is a major task and well beyond anything I have time to 'muck-round' on.
+     */
+    static public String formatHTMLWidth(String text, int width) {
+	if(text == null) {
+	    return "Error";
+	}
+	HTMLStringTokenizer html = new HTMLStringTokenizer(text);
+	int current_width = 0;
+	int threshold = width / 2;
+	Stack lines = new Stack();
+	String line = "";
+	while(html.hasMoreTokens()) {
+	    String token = html.nextToken();
+	    while(token != null) {
+		if(html.isTag()) {
+		    // Insert smart HTML tag code here.
+		    token = null;
+		}
+		else {
+		    // If the token is bigger than two thirds width, before we've even started break it down.
+		    if(current_width + 1 + token.length() > width && token.length() > threshold) {
+			if(width == current_width) {
+			    lines.push(line);
+			    line = token;
+			    current_width = token.length();
+			}
+			else {
+			    String prefix = token.substring(0, width - 1 - current_width);
+			    token = token.substring(prefix.length());
+			    if(current_width == 0) {
+				line = line + prefix;
+			    }
+			    else {
+				line = line + " " + prefix;
+			    }
+			    lines.push(line);
+			    line = "";
+			    current_width = 0;
+			}
+		    }
+		    // If adding the next token would push us over the maximum line width.
+		    else if(current_width + 1 + token.length() > width) {
+			lines.push(line);
+			line = token;
+			current_width = token.length();
+			token = null;
+		    }
+		    // Otherwise we should be able to just add the token, give or take.
+		    else {
+			if(current_width == 0) {
+			    line = line + token;
+			    current_width = token.length();
+			}
+			else {
+			    // Special case for standard punctuation which may exist after a tag like so:
+			    // My name is <scratchy>Slim Shady</scratchy>.   <-- Annoying punctuation.
+			    if(token.equals(".") || token.equals(",") || token.equals("!") || token.equals("?")) {
+				line = line + token;
+				current_width = current_width + 1;
+			    }
+			    else {
+				line = line + " " + token;
+				current_width = current_width + 1 + token.length();
+			    }
+			}
+			token = null;
+		    }
+		}
+	    }
+	}
+	String result = line;
+	while(!lines.empty()) {
+	    result = (String)lines.pop() + "<BR>" + result;
+	}
+	// Replace ' ' with "&nbsp;"
+	boolean tag = false;
+	int pos = 0;
+	while(pos < result.length()) {
+	    if(result.charAt(pos) == '<') {
+		tag = true;
+	    }
+	    else if(result.charAt(pos) == '>') {
+		tag = false;
+	    }
+	    else if(result.charAt(pos) == ' ' && !tag) {
+		String prefix = result.substring(0, pos);
+		String suffix = result.substring(pos + 1);
+		result = prefix + "&nbsp;" + suffix;
+	    }
+	    pos++;
+	}
+	result = "<HTML>" + result + "</HTML>";
+	return result;
+    }
+
+
+    static public String getDateString() {
+	Calendar current = Calendar.getInstance();
+	String day_name = null;
+	switch(current.get(Calendar.DAY_OF_WEEK)) {
+	case Calendar.MONDAY: day_name = "Dates.Mon"; break;
+	case Calendar.TUESDAY: day_name = "Dates.Tue"; break;
+	case Calendar.WEDNESDAY: day_name = "Dates.Wed"; break;
+	case Calendar.THURSDAY: day_name = "Dates.Thu"; break;
+	case Calendar.FRIDAY: day_name = "Dates.Fri"; break;
+	case Calendar.SATURDAY: day_name = "Dates.Sat"; break;
+	case Calendar.SUNDAY: day_name = "Dates.Sun"; break;
+	default: day_name = "";
+	}
+	String month_name = null;
+	switch(current.get(Calendar.MONTH)) {
+	case Calendar.JANUARY: month_name = "Dates.Jan"; break;
+	case Calendar.FEBRUARY: month_name = "Dates.Feb"; break;
+	case Calendar.MARCH: month_name = "Dates.Mar"; break;
+	case Calendar.APRIL: month_name = "Dates.Apr"; break;
+	case Calendar.MAY: month_name = "Dates.May"; break;
+	case Calendar.JUNE: month_name = "Dates.Jun"; break;
+	case Calendar.JULY: month_name = "Dates.Jul"; break;
+	case Calendar.AUGUST: month_name = "Dates.Aug"; break;
+	case Calendar.SEPTEMBER: month_name = "Dates.Sep"; break;
+	case Calendar.OCTOBER: month_name = "Dates.Oct"; break;
+	case Calendar.NOVEMBER: month_name = "Dates.Nov"; break;
+	case Calendar.DECEMBER: month_name = "Dates.Dec"; break;
+	default: month_name = "";
+	}
+	int day = current.get(Calendar.DAY_OF_MONTH);
+	int hour = current.get(Calendar.HOUR_OF_DAY);
+	int minute = current.get(Calendar.MINUTE);
+	int second = current.get(Calendar.SECOND);
+	int year = current.get(Calendar.YEAR);
+
+	return Dictionary.get(day_name) + " " + Dictionary.get(month_name) + " " + day + " " + year + " " + Utility.pad(String.valueOf(hour), 2, '0', true) + ":" + Utility.pad(String.valueOf(minute), 2, '0', true) + ":" + Utility.pad(String.valueOf(second), 2, '0', true);
+    }
+
+
+    /** Determine this machines name.
+     * @return The name as a <strong>String</strong>.
+     */
+    static public String getMachineName() {
+	try {
+	    return InetAddress.getLocalHost().getHostName();
+	}
+	catch(UnknownHostException ex) {
+	}
+	return "Unknown Machine";
+    }
+
+
+    static public String getSitesDir(String gsdl3_path) {
+	return gsdl3_path + "sites" + File.separator;
+
+    }
+
+
+    /** Method to determine if the host system is MacOS based.
+     * @return a boolean which is true if the platform is MacOS, false otherwise
+     */
+    public static boolean isMac() {
+	Properties props = System.getProperties();
+	String os_name = props.getProperty("os.name","");
+	if(os_name.startsWith("Mac OS")) {
+	    return true;
+	}
+	return false;
+    }
+
+   
+    /** Method to determine if the host system is Microsoft Windows based.
+     * @return A <i>boolean</i> which is <i>true</i> if the platform is Windows, <i>false</i> otherwise.
+     */
+    public static boolean isWindows() {
+	Properties props = System.getProperties();
+	String os_name = props.getProperty("os.name","");
+	if(os_name.startsWith("Windows")) {
+	    return true;
+	}
+	return false;
+    }
+
+    public static boolean isWindows9x() {
+	Properties props = System.getProperties();
+	String os_name = props.getProperty("os.name","");
+	if(os_name.startsWith("Windows") && os_name.indexOf("9") != -1) {
+	    return true;
+	}
+	return false;
+    }
+    /** Takes a string and a desired length and pads out the string to the length by adding spaces to the left.
+     * @param str The target <strong>String</strong> that needs to be padded.
+     * @param length The desired length of the string as an <i>int</i>.
+     * @return A <strong>String</strong> made from appending space characters with the string until it has a length equal to length.
+     */
+    static private String pad(String str_raw, int length, char fill, boolean end) {
+	StringBuffer str = new StringBuffer(str_raw);
+	while(str.length() < length) {
+	    if(end) {
+		str.insert(0, fill);
+	    }
+	    else {
+		str.append(fill);
+	    }
+	}
+	return str.toString();
+    }
+
+
+    /** Builds the cache dir by appending the user path and 'cache'.
+     * @return a File representing the path to the private file cache within the current collection.
+     */
+    public static File getCacheDir() {
+	return new File(getGLIUserFolder(), StaticStrings.CACHE_FOLDER);
+    }
+
+   /** Method which constructs the log directory given a certain collection.
+     * @param col_dir The location of the collection directory as a <strong>String</strong>.
+     * @return The location of the given collections log directory, also as a <strong>String</strong>.
+     */
+    public static String getLogDir(String col_dir) {
+	if(col_dir != null) {
+	    return col_dir + LOG_DIR;
+	}
+	else {
+	    return getGLIUserFolder().getAbsolutePath() + File.separator + LOG_DIR;
+	}
+    }
+
+    static final private String APPLICATION_DATA_FOLDER = "Application Data";
+    static final private String UNIX_GLI_CONFIG_FOLDER = ".gli";
+    static final private String USER_HOME_PROPERTY = "user.home";
+    static final private String WIN_GLI_CONFIG_FOLDER = "Greenstone" + File.separator + "GLI";
+     /** Definition of an important directory name, in this case the log directory for the collection. */
+    static final public String LOG_DIR = "log" + File.separator;
+
+    static public File getGLIUserFolder()
+    {
+	if (Utility.isWindows()) {
+	    return new File(System.getProperty(USER_HOME_PROPERTY) + File.separator + APPLICATION_DATA_FOLDER + File.separator + WIN_GLI_CONFIG_FOLDER + File.separator);
+	}
+	else {
+	    return new File(System.getProperty(USER_HOME_PROPERTY) + File.separator + UNIX_GLI_CONFIG_FOLDER + File.separator);
+	}
+    }
+
+
+}
Index: /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/XMLTools.java
===================================================================
--- /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/XMLTools.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gli/src/org/greenstone/gatherer/util/XMLTools.java	(revision 13928)
@@ -0,0 +1,344 @@
+package org.greenstone.gatherer.util;
+
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import org.apache.xerces.parsers.*;
+import org.apache.xml.serialize.*;
+import org.greenstone.gatherer.DebugStream;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+
+
+/** This class is a static class containing useful XML functions */
+public class XMLTools
+{
+    /** Remove all of the child nodes from a certain node. */
+    static final public void clear(Node node)
+    {
+	while (node.hasChildNodes()) {
+	    node.removeChild(node.getFirstChild());
+	}
+    }
+
+
+    static public ArrayList getChildElementsByTagName(Element parent_element, String element_name)
+    {
+	ArrayList child_elements = new ArrayList();
+
+	NodeList children_nodelist = parent_element.getChildNodes();
+	for (int i = 0; i < children_nodelist.getLength(); i++) {
+	    Node child_node = children_nodelist.item(i);
+	    if (child_node.getNodeType() == Node.ELEMENT_NODE && child_node.getNodeName().equals(element_name)) {
+		child_elements.add(child_node);
+	    }
+	}
+
+	return child_elements;
+    }
+
+
+    static public String getElementTextValue(Element element)
+    {
+	// Find the first text node child
+	NodeList children_nodelist = element.getChildNodes();
+	for (int i = 0; i < children_nodelist.getLength(); i++) {
+	    Node child_node = children_nodelist.item(i);
+	    if (child_node.getNodeType() == Node.TEXT_NODE) {
+		return child_node.getNodeValue();
+	    }
+	}
+
+	// None found
+	return "";
+    }
+
+
+    /** Method to retrieve the value of a given node.
+     * @param element The <strong>Element</strong> whose value we wish to find.
+     * Soon to be deprecated!
+     */
+    static final public String getValue(Node element) {
+	if (element == null) {
+	    return "";
+	}
+	// If we've been given a subject node first retrieve its value node.
+	if(element.getNodeName().equals("Subject")) {
+	    element = getNodeFromNamed(element, "Value");
+	}
+	// If we've got a value node, then reconstruct the text. Remember that DOM will split text over 256 characters into several text nodes
+	if(element != null && element.hasChildNodes()) {
+	    StringBuffer text_buffer = new StringBuffer();
+	    NodeList text_nodes = element.getChildNodes();
+	    for(int i = 0; i < text_nodes.getLength(); i++) {
+		Node possible_text = text_nodes.item(i);
+		if(possible_text.getNodeName().equals(StaticStrings.TEXT_NODE)) {
+		    text_buffer.append(possible_text.getNodeValue());
+		}
+	    }
+	    return text_buffer.toString();
+	}
+	return "";
+    }
+
+
+    /** Method to retrieve from the node given, a certain child node with the specified name.
+     * @param parent The <strong>Node</strong> whose children should be searched.
+     * @param name The required nodes name as a <strong>String</strong>.
+     * @return The requested <strong>Node</strong> if it is found, <i>null</i> otherwise.
+     * Soon to be deprecated!
+     */ 
+    static final public Node getNodeFromNamed(Node parent, String name) {
+	Node child = null;
+	for(Node i = parent.getFirstChild(); i != null && child == null; 
+	    i = i.getNextSibling()) {
+	    if(i.getNodeName().equals(name)) {
+		child = i;
+	    }
+	}
+	return child;
+    }
+
+
+    /** Parse an XML document from a given file path */
+    static public Document parseXMLFile(String xml_file_path, boolean use_class_loader)
+    {
+	if (use_class_loader == true) {
+	    InputStream is = JarTools.getResourceAsStream("/" + xml_file_path);
+	    if (is != null) {
+		return parseXML(is);
+	    }
+	}
+
+ 	// Try the file outside the classes directory
+ 	return parseXMLFile(new File(xml_file_path));
+    }
+
+
+    /** Parse an XML document from a given file */
+    static public Document parseXMLFile(File xml_file)
+    {
+	// No file? No point trying!
+	if (xml_file.exists() == false) {
+	    return null;
+	}
+
+	try {
+	    return parseXML(new FileInputStream(xml_file));
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	    return null;
+	}
+    }
+
+
+    /** Parse an XML document from a given input stream */
+    static public Document parseXML(InputStream xml_input_stream)
+    {
+	Document document = null;
+
+	try {
+	    InputStreamReader isr = new InputStreamReader(xml_input_stream, "UTF-8");
+	    Reader xml_reader = new BufferedReader(isr);
+	    document = parseXML(xml_reader);
+	    isr.close();
+	    xml_input_stream.close();
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+
+	return document;
+    }
+
+
+    /** Parse an XML document from a given reader */
+    static public Document parseXML(Reader xml_reader)
+    {
+	Document document = null;
+
+	try {
+	    InputSource isc       = new InputSource(xml_reader);
+	    DOMParser parser      = new DOMParser();
+	    parser.setFeature("http://xml.org/sax/features/validation", false);
+	    parser.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+	    // May or may not be ignored, the documentation for Xerces is contradictory. If it works then parsing -should- be faster.
+	    parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", true);
+	    parser.setFeature("http://apache.org/xml/features/dom/include-ignorable-whitespace", false);
+	    parser.parse(isc);
+	    document = parser.getDocument();
+	}
+	catch (SAXException exception) {
+	    System.err.println("SAX exception: " + exception.getMessage());
+	    DebugStream.printStackTrace(exception);
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+
+	return document;
+    }
+
+
+    static public StringBuffer readXMLStream(InputStream input_stream)
+    {
+	StringBuffer xml = new StringBuffer("");
+
+	try {
+	    InputStreamReader isr = new InputStreamReader(input_stream, "UTF-8");
+	    BufferedReader buffered_in = new BufferedReader(isr);
+
+	    String line = "";
+	    boolean xml_content = false;
+	    while((line = buffered_in.readLine()) != null) {
+		if(xml_content) {
+		    xml.append(line);
+		    xml.append("\n");
+		}
+		else if(line.trim().startsWith("<?xml")) {
+		    xml_content = true;
+		    xml.append(line);
+		    xml.append("\n");
+		}
+	    }
+	    buffered_in = null;
+	}
+	catch (Exception error) {
+	    System.err.println("Failed when trying to parse XML stream");
+	    error.printStackTrace();
+	}
+
+	return xml;
+    }
+
+
+    /** Removes characters that are invalid in XML (see http://www.w3.org/TR/2000/REC-xml-20001006#charsets) */
+    static public String removeInvalidCharacters(String text)
+    {
+	char[] safe_characters = new char[text.length()];
+	int j = 0;
+
+	char[] raw_characters = new char[text.length()];
+	text.getChars(0, text.length(), raw_characters, 0);
+	for (int i = 0; i < raw_characters.length; i++) {
+	    char character = raw_characters[i];
+	    if ((character >= 0x20 && character <= 0xD7FF) || character == 0x09 || character == 0x0A || character == 0x0D || (character >= 0xE000 && character <= 0xFFFD) || (character >= 0x10000 && character <= 0x10FFFF)) {
+		safe_characters[j] = character;
+		j++;
+	    }
+	}
+
+	return new String(safe_characters, 0, j);
+    }
+
+
+    static public void setElementTextValue(Element element, String text)
+    {
+	// Remove all text node children
+	NodeList children_nodelist = element.getChildNodes();
+	for (int i = children_nodelist.getLength() - 1; i >= 0; i--) {
+	    Node child_node = children_nodelist.item(i);
+	    if (child_node.getNodeType() == Node.TEXT_NODE) {
+		element.removeChild(child_node);
+	    }
+	}
+
+	// Add a new text node
+	if (text != null) {
+	    element.appendChild(element.getOwnerDocument().createTextNode(text));
+	}
+    }
+
+
+    /** Set the #text node value of some element.
+     * @param element the Element whose value we wish to set
+     * @param value the new value for the element as a String
+     * Soon to be deprecated!
+     */
+    static final public void setValue(Element element, String value) {
+	// Remove any existing child node(s)
+	clear(element);
+	// Add new text node.
+	if (value != null) {
+	    element.appendChild(element.getOwnerDocument().createTextNode(value));
+	}
+    }
+
+
+    /** Write an XML document to a given file */
+    static public void writeXMLFile(File xml_file, Document document)
+    {
+	try {
+	    OutputStream os = new FileOutputStream(xml_file);
+	    // Create an output format for our document.
+	    OutputFormat f = new OutputFormat(document);
+	    f.setEncoding("UTF-8");
+	    f.setIndenting(true);
+	    f.setLineWidth(0); // Why isn't this working!
+	    f.setPreserveSpace(false);
+	    // Create the necessary writer stream for serialization.
+	    OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
+	    Writer w               = new BufferedWriter(osw);
+	    // Generate a new serializer from the above.
+	    XMLSerializer s        = new XMLSerializer(w, f);
+	    s.asDOMSerializer();
+	    // Finally serialize the document to file.
+	    s.serialize(document);
+	    // And close.
+	    os.close();
+	}
+	catch (Exception exception) {
+	    DebugStream.printStackTrace(exception);
+	}
+    }
+
+    public static void printXMLNode(Node e) {
+	printXMLNode(e, 0) ;
+    }
+ 
+ public static void printXMLNode(Node e, int depth) { //recursive method call using DOM API...
+	
+	for (int i=0 ; i<depth ; i++) 
+	    System.out.print(' ') ;
+
+	if (e.getNodeType() == Node.TEXT_NODE){
+	    System.out.println("text") ;
+	    //System.out.println(e.getNodeValue()) ;
+	    return ;
+	}
+	
+	System.out.print('<');
+	System.out.print(e.getNodeName());
+	NamedNodeMap attrs = e.getAttributes();
+	for (int i = 0; i < attrs.getLength(); i++) {
+	    Node attr = attrs.item(i);
+	    System.out.print(' ');  
+	    System.out.print(attr.getNodeName());
+	    System.out.print("=\"");
+	    System.out.print(attr.getNodeValue());   
+	    System.out.print('"');
+	}
+
+	NodeList children = e.getChildNodes();
+
+	if (children == null || children.getLength() == 0)
+	    System.out.println("/>") ;
+	else {
+	    
+	    System.out.println('>') ;
+	    
+	    int len = children.getLength();
+	    for (int i = 0; i < len; i++) {
+		printXMLNode(children.item(i), depth + 1);
+	    }
+	    
+	    for (int i=0 ; i<depth ; i++) 
+		System.out.print(' ') ;
+	    
+	    System.out.println("</" + e.getNodeName() + ">");
+	}	
+
+    }
+}
Index: /tags/greenstone-3_02-distribution/gs2build-extra/Makefile.in
===================================================================
--- /tags/greenstone-3_02-distribution/gs2build-extra/Makefile.in	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gs2build-extra/Makefile.in	(revision 13928)
@@ -0,0 +1,104 @@
+###########################################################################
+#
+# Makefile -- gs2build module
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999  The New Zealand Digital Library Project
+#
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+srcdir = @srcdir@
+
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+
+@SET_MAKE@
+CC = @CC@
+CXX = @CXX@
+CFLAGS = @CFLAGS@
+CXXFLAGS = @CXXFLAGS@
+LIBS   = @LIBS@
+MDEFINES =
+
+GSDLOS = @gsdlos@
+
+COMPILE = $(CC) -c
+
+SOURCES = 
+
+OBJECTS = 
+
+ALLFILES = $(OBJECTS)
+
+INSTALLDIRS = indexers src/txt2db src/db2txt src/hashfile src/phind/generate packages 
+
+MODULEDIRS = @MODULEDIRS@
+
+OTHERDIRS = lib 
+
+all:
+	for odir in $(OTHERDIRS) $(INSTALLDIRS) $(MODULEDIRS); do \
+	  echo making $@ in $$odir; \
+	  (cd $$odir && $(MAKE) $(MDEFINES) $@) || exit 1; \
+	done
+
+install: all
+
+	for idir in $(INSTALLDIRS); do \
+	  echo installing $$idir; \
+	  (cd $$idir && $(MAKE) install) || exit 1; \
+	done
+
+# added test to check existence of Makefile, as src/recpt is in
+# both INSTALLDIRS and OTHERDIRS - can't make distclean twice!
+distclean: clean
+	rm -f Makefile config.cache config.h config.log stamp-h config.status
+	for subdir in $(INSTALLDIRS) $(OTHERDIRS); do \
+	  echo cleaning $@ in $$subdir; \
+	  (cd $$subdir && if test -e Makefile; then $(MAKE) distclean;fi) || exit 1; \
+	done
+
+clean:
+	for subdir in $(INSTALLDIRS) $(OTHERDIRS); do \
+	  echo cleaning $@ in $$subdir; \
+	  (cd $$subdir && $(MAKE) clean) || exit 1; \
+	done
+
+# commented out - jrm21 Dec 2004 - can get confused by cvs timestamps
+# (and might run the wrong version of autoconf)
+#
+## For an explanation of the following Makefile rules, see node
+## `Automatic Remaking' in GNU Autoconf documentation.
+#Makefile: Makefile.in config.status
+#	CONFIG_FILES=$@ CONFIG_HEADERS= ./config.status
+#config.status: configure
+#	./config.status --recheck
+#configure: configure.in aclocal.m4
+#	cd $(srcdir) && autoconf
+#
+#config.h: stamp-h
+#stamp-h: config.h.in config.status
+#	CONFIG_FILES= CONFIG_HEADERS=config.h ./config.status
+#config.h.in: stamp-h.in
+#stamp-h.in: configure.in aclocal.m4 acconfig.h
+#	cd $(srcdir) && autoheader
+#	$(TOUCH) $(srcdir)/stamp-h.in
+
+
+
Index: /tags/greenstone-3_02-distribution/gs2build-extra/configure
===================================================================
--- /tags/greenstone-3_02-distribution/gs2build-extra/configure	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gs2build-extra/configure	(revision 13928)
@@ -0,0 +1,8639 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.59.
+#
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)$' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+  	  /^X\/\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\/\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+	 case $as_dir in
+	 /*)
+	   if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+	     $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+	     $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+	     CONFIG_SHELL=$as_dir/$as_base
+	     export CONFIG_SHELL
+	     exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+	   fi;;
+	 esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='	' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" 	$as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete.  It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="lib/text_t.h"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+#  include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subdirs_all="$ac_subdirs_all packages indexers"
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS PACKAGE VERSION ENABLE_ACCENTFOLD CFLAGS CC LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX CXXFLAGS ac_ct_CXX AWK YACC build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE RANLIB ac_ct_RANLIB CPP EGREP U ANSI2KNR ALLOCA LIBOBJS STATIC GDBM_LIBPATH GDBM_INCLUDE gsdlos MODULEDIRS subdirs LTLIBOBJS'
+ac_subst_files=''
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+ac_prev=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_option in
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    eval "enable_$ac_feature=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_$ac_feature='$ac_optarg'" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_$ac_package='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/-/_/g'`
+    eval "with_$ac_package=no" ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+    eval "$ac_envvar='$ac_optarg'"
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+	      localstatedir libdir includedir oldincludedir infodir mandir
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then its parent.
+  ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$0" : 'X\(//\)[^/]' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r $srcdir/$ac_unique_file; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+   { (exit 1); exit 1; }; }
+  else
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+  fi
+fi
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+  { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+   { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CXX_set=${CXX+set}
+ac_env_CXX_value=$CXX
+ac_cv_env_CXX_set=${CXX+set}
+ac_cv_env_CXX_value=$CXX
+ac_env_CXXFLAGS_set=${CXXFLAGS+set}
+ac_env_CXXFLAGS_value=$CXXFLAGS
+ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set}
+ac_cv_env_CXXFLAGS_value=$CXXFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+  cat <<_ACEOF
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+			  [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+			  [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR           user executables [EPREFIX/bin]
+  --sbindir=DIR          system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR       program executables [EPREFIX/libexec]
+  --datadir=DIR          read-only architecture-independent data [PREFIX/share]
+  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
+  --libdir=DIR           object code libraries [EPREFIX/lib]
+  --includedir=DIR       C header files [PREFIX/include]
+  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
+  --infodir=DIR          info documentation [PREFIX/info]
+  --mandir=DIR           man documentation [PREFIX/man]
+_ACEOF
+
+  cat <<\_ACEOF
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+  --target=TARGET   configure for building compilers for TARGET [HOST]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --disable-accentfold          Disable Accent Folding for MGPP
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-gdbm=dir         Use local gdbm library and headers
+  --with-dmalloc          use dmalloc, as in
+                          ftp://ftp.letters.com/src/dmalloc/dmalloc.tar.gz
+  --with-regex            use older regex in lieu of GNU rx for matching
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
+              headers in a nonstandard directory <include dir>
+  CXX         C++ compiler command
+  CXXFLAGS    C++ compiler flags
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  ac_popdir=`pwd`
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d $ac_dir || continue
+    ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+    cd $ac_dir
+    # Check for guested configure; otherwise get Cygnus style configure.
+    if test -f $ac_srcdir/configure.gnu; then
+      echo
+      $SHELL $ac_srcdir/configure.gnu  --help=recursive
+    elif test -f $ac_srcdir/configure; then
+      echo
+      $SHELL $ac_srcdir/configure  --help=recursive
+    elif test -f $ac_srcdir/configure.ac ||
+	   test -f $ac_srcdir/configure.in; then
+      echo
+      $ac_configure --help
+    else
+      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi
+    cd $ac_popdir
+  done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+  cat <<\_ACEOF
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.59.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo               = `(hostinfo) 2>/dev/null               || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    2)
+      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+      # Get rid of the leading space.
+      ac_sep=" "
+      ;;
+    esac
+  done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+{
+  (set) 2>&1 |
+    case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      sed -n \
+	"s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+      ;;
+    *)
+      sed -n \
+	"s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+}
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=$`echo $ac_var`
+      echo "$ac_var='"'"'$ac_val'"'"'"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=$`echo $ac_var`
+	echo "$ac_var='"'"'$ac_val'"'"'"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      sed "/^$/d" confdefs.h | sort
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      echo "$as_me: caught signal $ac_signal"
+    echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core &&
+  rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+     ' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . $cache_file;;
+      *)                      . ./$cache_file;;
+    esac
+  fi
+else
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+	       sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+  eval ac_new_val="\$ac_env_${ac_var}_value"
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	{ echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	{ echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
+echo "$as_me:   former value:  $ac_old_val" >&2;}
+	{ echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
+echo "$as_me:   current value: $ac_new_val" >&2;}
+	ac_cache_corrupted=:
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+          ac_config_headers="$ac_config_headers config.h"
+
+
+PACKAGE=gsdl
+VERSION=2.1
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+
+
+
+
+# Check whether --with-gdbm or --without-gdbm was given.
+if test "${with_gdbm+set}" = set; then
+  withval="$with_gdbm"
+  gdbmdir=$withval
+fi;
+
+
+# Check whether --enable-accentfold or --disable-accentfold was given.
+if test "${enable_accentfold+set}" = set; then
+  enableval="$enable_accentfold"
+  ENABLE_ACCENTFOLD=0
+else
+  ENABLE_ACCENTFOLD=1
+fi;
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_ACCENTFOLD $ENABLE_ACCENTFOLD
+_ACEOF
+
+
+
+
+LDFLAGS=
+if test -z "$CFLAGS"; then
+CFLAGS=-O2
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$ac_ct_CC" && break
+done
+
+  CC=$ac_ct_CC
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+     "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+  (eval $ac_link_default) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Find the output, starting from the most likely.  This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+	;;
+    conftest.$ac_ext )
+	# This is the source file.
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+	ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	# FIXME: I believe we export ac_cv_exeext for Libtool,
+	# but it would be cool to find out if it's true.  Does anybody
+	# maintain Libtool? --akim.
+	export ac_cv_exeext
+	break;;
+    * )
+	break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  fi
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  export ac_cv_exeext
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std1 is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std1.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX			-qlanglvl=ansi
+# Ultrix and OSF/1	-std1
+# HP-UX 10.20 and later	-Ae
+# HP-UX older versions	-Aa -D_HPUX_SOURCE
+# SVR4			-Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+  x|xno)
+    echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+  *)
+    echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+    CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+# Some people use a C++ compiler to compile C.  Since we use `exit',
+# in C++ we need to declare it.  In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+  choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  for ac_declaration in \
+   '' \
+   'extern "C" void std::exit (int) throw (); using std::exit;' \
+   'extern "C" void std::exit (int); using std::exit;' \
+   'extern "C" void exit (int) throw ();' \
+   'extern "C" void exit (int);' \
+   'void exit (int);'
+do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+  echo '#ifdef __cplusplus' >>confdefs.h
+  echo $ac_declaration      >>confdefs.h
+  echo '#endif'             >>confdefs.h
+fi
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CXX+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+  echo "$as_me:$LINENO: result: $CXX" >&5
+echo "${ECHO_T}$CXX" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    test -n "$CXX" && break
+  done
+fi
+if test -z "$CXX"; then
+  ac_ct_CXX=$CXX
+  for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CXX"; then
+  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CXX="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+echo "${ECHO_T}$ac_ct_CXX" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$ac_ct_CXX" && break
+done
+test -n "$ac_ct_CXX" || ac_ct_CXX="g++"
+
+  CXX=$ac_ct_CXX
+fi
+
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+     "checking for C++ compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_cxx_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6
+GXX=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+CXXFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cxx_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_cxx_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cxx_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cxx_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+for ac_declaration in \
+   '' \
+   'extern "C" void std::exit (int) throw (); using std::exit;' \
+   'extern "C" void std::exit (int); using std::exit;' \
+   'extern "C" void exit (int) throw ();' \
+   'extern "C" void exit (int);' \
+   'void exit (int);'
+do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_cxx_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_cxx_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+  echo '#ifdef __cplusplus' >>confdefs.h
+  echo $ac_declaration      >>confdefs.h
+  echo '#endif'             >>confdefs.h
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_AWK+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AWK="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  echo "$as_me:$LINENO: result: $AWK" >&5
+echo "${ECHO_T}$AWK" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$AWK" && break
+done
+
+for ac_prog in 'bison -y' byacc
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_YACC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$YACC"; then
+  ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_YACC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+YACC=$ac_cv_prog_YACC
+if test -n "$YACC"; then
+  echo "$as_me:$LINENO: result: $YACC" >&5
+echo "${ECHO_T}$YACC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+  if test -f $ac_dir/install-sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f $ac_dir/install.sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f $ac_dir/shtool; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
+echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"
+ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
+
+# Make sure we can run config.sub.
+$ac_config_sub sun4 >/dev/null 2>&1 ||
+  { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5
+echo "$as_me: error: cannot run $ac_config_sub" >&2;}
+   { (exit 1); exit 1; }; }
+
+echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6
+if test "${ac_cv_build+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_build_alias=$build_alias
+test -z "$ac_cv_build_alias" &&
+  ac_cv_build_alias=`$ac_config_guess`
+test -z "$ac_cv_build_alias" &&
+  { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+   { (exit 1); exit 1; }; }
+ac_cv_build=`$ac_config_sub $ac_cv_build_alias` ||
+  { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6
+build=$ac_cv_build
+build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6
+if test "${ac_cv_host+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_host_alias=$host_alias
+test -z "$ac_cv_host_alias" &&
+  ac_cv_host_alias=$ac_cv_build_alias
+ac_cv_host=`$ac_config_sub $ac_cv_host_alias` ||
+  { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6
+host=$ac_cv_host
+host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+echo "$as_me:$LINENO: checking target system type" >&5
+echo $ECHO_N "checking target system type... $ECHO_C" >&6
+if test "${ac_cv_target+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_target_alias=$target_alias
+test "x$ac_cv_target_alias" = "x" &&
+  ac_cv_target_alias=$ac_cv_host_alias
+ac_cv_target=`$ac_config_sub $ac_cv_target_alias` ||
+  { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_target_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_target_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_target" >&5
+echo "${ECHO_T}$ac_cv_target" >&6
+target=$ac_cv_target
+target_cpu=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+  test "$program_prefix$program_suffix$program_transform_name" = \
+    NONENONEs,x,x, &&
+  program_prefix=${target_alias}-
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+	if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+	  if test $ac_prog = install &&
+	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+	    break 3
+	  fi
+	fi
+      done
+    done
+    ;;
+esac
+done
+
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL=$ac_install_sh
+  fi
+fi
+echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo "$as_me:$LINENO: checking whether ln -s works" >&5
+echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+  echo "$as_me:$LINENO: result: no, using $LN_S" >&5
+echo "${ECHO_T}no, using $LN_S" >&6
+fi
+
+echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'`
+if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.make <<\_ACEOF
+all:
+	@echo 'ac_maketemp="$(MAKE)"'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+  eval ac_cv_prog_make_${ac_make}_set=yes
+else
+  eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftest.make
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  SET_MAKE=
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":"
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  RANLIB=$ac_ct_RANLIB
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+    then ac_cv_prog_egrep='grep -E'
+    else ac_cv_prog_egrep='egrep'
+    fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+
+
+echo "$as_me:$LINENO: checking for AIX" >&5
+echo $ECHO_N "checking for AIX... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef _AIX
+  yes
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "yes" >/dev/null 2>&1; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+cat >>confdefs.h <<\_ACEOF
+#define _ALL_SOURCE 1
+_ACEOF
+
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+rm -f conftest*
+
+
+echo "$as_me:$LINENO: checking for library containing strerror" >&5
+echo $ECHO_N "checking for library containing strerror... $ECHO_C" >&6
+if test "${ac_cv_search_strerror+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+ac_cv_search_strerror=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char strerror ();
+int
+main ()
+{
+strerror ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_strerror="none required"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_strerror" = no; then
+  for ac_lib in cposix; do
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char strerror ();
+int
+main ()
+{
+strerror ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_strerror="-l$ac_lib"
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+  done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_strerror" >&5
+echo "${ECHO_T}$ac_cv_search_strerror" >&6
+if test "$ac_cv_search_strerror" != no; then
+  test "$ac_cv_search_strerror" = "none required" || LIBS="$ac_cv_search_strerror $LIBS"
+
+fi
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      exit(2);
+  exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+		  inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+if test "${ac_cv_header_minix_config_h+set}" = set; then
+  echo "$as_me:$LINENO: checking for minix/config.h" >&5
+echo $ECHO_N "checking for minix/config.h... $ECHO_C" >&6
+if test "${ac_cv_header_minix_config_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_minix_config_h" >&5
+echo "${ECHO_T}$ac_cv_header_minix_config_h" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking minix/config.h usability" >&5
+echo $ECHO_N "checking minix/config.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <minix/config.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking minix/config.h presence" >&5
+echo $ECHO_N "checking minix/config.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <minix/config.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: minix/config.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: minix/config.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: minix/config.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: minix/config.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: minix/config.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: minix/config.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: minix/config.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: minix/config.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: minix/config.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: minix/config.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: minix/config.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: minix/config.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: minix/config.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: minix/config.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: minix/config.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: minix/config.h: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for minix/config.h" >&5
+echo $ECHO_N "checking for minix/config.h... $ECHO_C" >&6
+if test "${ac_cv_header_minix_config_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_minix_config_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_minix_config_h" >&5
+echo "${ECHO_T}$ac_cv_header_minix_config_h" >&6
+
+fi
+if test $ac_cv_header_minix_config_h = yes; then
+  MINIX=yes
+else
+  MINIX=
+fi
+
+
+if test "$MINIX" = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define _POSIX_SOURCE 1
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define _POSIX_1_SOURCE 2
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define _MINIX 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for ${CC-cc} option to accept ANSI C" >&5
+echo $ECHO_N "checking for ${CC-cc} option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_stdc=no
+ac_save_CFLAGS="$CFLAGS"
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX			-qlanglvl=ansi
+# Ultrix and OSF/1	-std1
+# HP-UX			-Aa -D_HPUX_SOURCE
+# SVR4			-Xc
+for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" -Xc
+do
+  CFLAGS="$ac_save_CFLAGS $ac_arg"
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#if !defined(__STDC__) || __STDC__ != 1
+choke me
+#endif
+
+int
+main ()
+{
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_stdc="$ac_arg"; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+CFLAGS="$ac_save_CFLAGS"
+
+fi
+
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+case "x$ac_cv_prog_cc_stdc" in
+  x|xno) ;;
+  *) CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+
+echo "$as_me:$LINENO: checking for function prototypes" >&5
+echo $ECHO_N "checking for function prototypes... $ECHO_C" >&6
+if test "$ac_cv_prog_cc_stdc" != no; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  cat >>confdefs.h <<\_ACEOF
+#define PROTOTYPES 1
+_ACEOF
+
+  U= ANSI2KNR=
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+  U=_ ANSI2KNR=ansi2knr
+fi
+
+echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
+echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6
+if test "${ac_cv_c_const+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+  /* Ultrix mips cc rejects this.  */
+  typedef int charset[2];
+  const charset x;
+  /* SunOS 4.1.1 cc rejects this.  */
+  char const *const *ccp;
+  char **p;
+  /* NEC SVR4.0.2 mips cc rejects this.  */
+  struct point {int x, y;};
+  static struct point const zero = {0,0};
+  /* AIX XL C 1.02.0.0 rejects this.
+     It does not let you subtract one const X* pointer from another in
+     an arm of an if-expression whose if-part is not a constant
+     expression */
+  const char *g = "string";
+  ccp = &g + (g ? g-g : 0);
+  /* HPUX 7.0 cc rejects these. */
+  ++ccp;
+  p = (char**) ccp;
+  ccp = (char const *const *) p;
+  { /* SCO 3.2v4 cc rejects this.  */
+    char *t;
+    char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+    *t++ = 0;
+  }
+  { /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
+    int x[] = {25, 17};
+    const int *foo = &x[0];
+    ++foo;
+  }
+  { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+    typedef const int *iptr;
+    iptr p = 0;
+    ++p;
+  }
+  { /* AIX XL C 1.02.0.0 rejects this saying
+       "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+    struct s { int j; const int *ap[3]; };
+    struct s *b; b->j = 5;
+  }
+  { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+    const int foo = 10;
+  }
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_const=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_c_const=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+echo "${ECHO_T}$ac_cv_c_const" >&6
+if test $ac_cv_c_const = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define const
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for off_t" >&5
+echo $ECHO_N "checking for off_t... $ECHO_C" >&6
+if test "${ac_cv_type_off_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if ((off_t *) 0)
+  return 0;
+if (sizeof (off_t))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_off_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_off_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_off_t" >&5
+echo "${ECHO_T}$ac_cv_type_off_t" >&6
+if test $ac_cv_type_off_t = yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define off_t long
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for size_t" >&5
+echo $ECHO_N "checking for size_t... $ECHO_C" >&6
+if test "${ac_cv_type_size_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if ((size_t *) 0)
+  return 0;
+if (sizeof (size_t))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_size_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_size_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5
+echo "${ECHO_T}$ac_cv_type_size_t" >&6
+if test $ac_cv_type_size_t = yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5
+echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6
+if test "${ac_cv_header_time+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+
+int
+main ()
+{
+if ((struct tm *) 0)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_header_time=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_time=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5
+echo "${ECHO_T}$ac_cv_header_time" >&6
+if test $ac_cv_header_time = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TIME_WITH_SYS_TIME 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking whether struct tm is in sys/time.h or time.h" >&5
+echo $ECHO_N "checking whether struct tm is in sys/time.h or time.h... $ECHO_C" >&6
+if test "${ac_cv_struct_tm+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <time.h>
+
+int
+main ()
+{
+struct tm *tp; tp->tm_sec;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_struct_tm=time.h
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_struct_tm=sys/time.h
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_struct_tm" >&5
+echo "${ECHO_T}$ac_cv_struct_tm" >&6
+if test $ac_cv_struct_tm = sys/time.h; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TM_IN_SYS_TIME 1
+_ACEOF
+
+fi
+
+
+if test "$ac_cv_prog_cc_stdc" = '-Xc'; then
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+
+int
+main ()
+{
+ FILE *rubbish = popen("yes", "r");
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+CC="`echo $CC | sed 's/-Xc/-Xa/'`"    ac_cv_prog_cc_stdc='-Xa'
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+
+echo "$as_me:$LINENO: checking for main in -lg" >&5
+echo $ECHO_N "checking for main in -lg... $ECHO_C" >&6
+if test "${ac_cv_lib_g_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lg  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_g_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_g_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_g_main" >&5
+echo "${ECHO_T}$ac_cv_lib_g_main" >&6
+if test $ac_cv_lib_g_main = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBG 1
+_ACEOF
+
+  LIBS="-lg $LIBS"
+
+fi
+ac_cv_lib_g=ac_cv_lib_g_main
+
+
+echo "$as_me:$LINENO: checking for main in -lm" >&5
+echo $ECHO_N "checking for main in -lm... $ECHO_C" >&6
+if test "${ac_cv_lib_m_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_m_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_m_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_m_main" >&5
+echo "${ECHO_T}$ac_cv_lib_m_main" >&6
+if test $ac_cv_lib_m_main = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+  LIBS="-lm $LIBS"
+
+fi
+ac_cv_lib_m=ac_cv_lib_m_main
+
+
+echo "$as_me:$LINENO: checking for main in -lcrypt" >&5
+echo $ECHO_N "checking for main in -lcrypt... $ECHO_C" >&6
+if test "${ac_cv_lib_crypt_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcrypt  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_crypt_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_crypt_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_crypt_main" >&5
+echo "${ECHO_T}$ac_cv_lib_crypt_main" >&6
+if test $ac_cv_lib_crypt_main = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBCRYPT 1
+_ACEOF
+
+  LIBS="-lcrypt $LIBS"
+
+fi
+ac_cv_lib_crypt=ac_cv_lib_crypt_main
+
+if test $ENABLE_ACCENTFOLD = 1; then
+
+echo "$as_me:$LINENO: checking for main in -lICONV" >&5
+echo $ECHO_N "checking for main in -lICONV... $ECHO_C" >&6
+if test "${ac_cv_lib_ICONV_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lICONV  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_ICONV_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_ICONV_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_ICONV_main" >&5
+echo "${ECHO_T}$ac_cv_lib_ICONV_main" >&6
+if test $ac_cv_lib_ICONV_main = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBICONV 1
+_ACEOF
+
+  LIBS="-lICONV $LIBS"
+
+fi
+ac_cv_lib_ICONV=ac_cv_lib_ICONV_main
+
+fi
+
+
+
+
+
+
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do
+  as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5
+echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <$ac_hdr>
+
+int
+main ()
+{
+if ((DIR *) 0)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1
+_ACEOF
+
+ac_header_dirent=$ac_hdr; break
+fi
+
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+  echo "$as_me:$LINENO: checking for library containing opendir" >&5
+echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6
+if test "${ac_cv_search_opendir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+ac_cv_search_opendir=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
+int
+main ()
+{
+opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_opendir="none required"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_opendir" = no; then
+  for ac_lib in dir; do
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
+int
+main ()
+{
+opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_opendir="-l$ac_lib"
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+  done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
+echo "${ECHO_T}$ac_cv_search_opendir" >&6
+if test "$ac_cv_search_opendir" != no; then
+  test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS"
+
+fi
+
+else
+  echo "$as_me:$LINENO: checking for library containing opendir" >&5
+echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6
+if test "${ac_cv_search_opendir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+ac_cv_search_opendir=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
+int
+main ()
+{
+opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_opendir="none required"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_opendir" = no; then
+  for ac_lib in x; do
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
+int
+main ()
+{
+opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_opendir="-l$ac_lib"
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+  done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
+echo "${ECHO_T}$ac_cv_search_opendir" >&6
+if test "$ac_cv_search_opendir" != no; then
+  test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS"
+
+fi
+
+fi
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      exit(2);
+  exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+
+
+
+
+
+
+
+
+for ac_header in fcntl.h limits.h sys/time.h unistd.h crypt.h string.h memory.h sys/procfs.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "fread" >/dev/null 2>&1; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_FREAD_DECL 1
+_ACEOF
+
+fi
+rm -f conftest*
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "fgetc" >/dev/null 2>&1; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_FGETC_DECL 1
+_ACEOF
+
+fi
+rm -f conftest*
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/procfs.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "pr_brksize" >/dev/null 2>&1; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_PR_BRKSIZE 1
+_ACEOF
+
+fi
+rm -f conftest*
+
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments.  Useless!
+echo "$as_me:$LINENO: checking for working alloca.h" >&5
+echo $ECHO_N "checking for working alloca.h... $ECHO_C" >&6
+if test "${ac_cv_working_alloca_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <alloca.h>
+int
+main ()
+{
+char *p = (char *) alloca (2 * sizeof (int));
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_working_alloca_h=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_working_alloca_h=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_working_alloca_h" >&5
+echo "${ECHO_T}$ac_cv_working_alloca_h" >&6
+if test $ac_cv_working_alloca_h = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ALLOCA_H 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for alloca" >&5
+echo $ECHO_N "checking for alloca... $ECHO_C" >&6
+if test "${ac_cv_func_alloca_works+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+#  include <malloc.h>
+#  define alloca _alloca
+# else
+#  if HAVE_ALLOCA_H
+#   include <alloca.h>
+#  else
+#   ifdef _AIX
+ #pragma alloca
+#   else
+#    ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+#    endif
+#   endif
+#  endif
+# endif
+#endif
+
+int
+main ()
+{
+char *p = (char *) alloca (1);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_alloca_works=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_alloca_works=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_alloca_works" >&5
+echo "${ECHO_T}$ac_cv_func_alloca_works" >&6
+
+if test $ac_cv_func_alloca_works = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ALLOCA 1
+_ACEOF
+
+else
+  # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+# that cause trouble.  Some versions do not even contain alloca or
+# contain a buggy version.  If you still want to use their alloca,
+# use ar to extract alloca.o from them instead of compiling alloca.c.
+
+ALLOCA=alloca.$ac_objext
+
+cat >>confdefs.h <<\_ACEOF
+#define C_ALLOCA 1
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking whether \`alloca.c' needs Cray hooks" >&5
+echo $ECHO_N "checking whether \`alloca.c' needs Cray hooks... $ECHO_C" >&6
+if test "${ac_cv_os_cray+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#if defined(CRAY) && ! defined(CRAY2)
+webecray
+#else
+wenotbecray
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "webecray" >/dev/null 2>&1; then
+  ac_cv_os_cray=yes
+else
+  ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_os_cray" >&5
+echo "${ECHO_T}$ac_cv_os_cray" >&6
+if test $ac_cv_os_cray = yes; then
+  for ac_func in _getb67 GETB67 getb67; do
+    as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define CRAY_STACKSEG_END $ac_func
+_ACEOF
+
+    break
+fi
+
+  done
+fi
+
+echo "$as_me:$LINENO: checking stack direction for C alloca" >&5
+echo $ECHO_N "checking stack direction for C alloca... $ECHO_C" >&6
+if test "${ac_cv_c_stack_direction+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_c_stack_direction=0
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+int
+find_stack_direction ()
+{
+  static char *addr = 0;
+  auto char dummy;
+  if (addr == 0)
+    {
+      addr = &dummy;
+      return find_stack_direction ();
+    }
+  else
+    return (&dummy > addr) ? 1 : -1;
+}
+
+int
+main ()
+{
+  exit (find_stack_direction () < 0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_stack_direction=1
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_c_stack_direction=-1
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_stack_direction" >&5
+echo "${ECHO_T}$ac_cv_c_stack_direction" >&6
+
+cat >>confdefs.h <<_ACEOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+_ACEOF
+
+
+fi
+
+if test $ac_cv_c_compiler_gnu = yes; then
+    echo "$as_me:$LINENO: checking whether $CC needs -traditional" >&5
+echo $ECHO_N "checking whether $CC needs -traditional... $ECHO_C" >&6
+if test "${ac_cv_prog_gcc_traditional+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+    ac_pattern="Autoconf.*'x'"
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sgtty.h>
+Autoconf TIOCGETP
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "$ac_pattern" >/dev/null 2>&1; then
+  ac_cv_prog_gcc_traditional=yes
+else
+  ac_cv_prog_gcc_traditional=no
+fi
+rm -f conftest*
+
+
+  if test $ac_cv_prog_gcc_traditional = no; then
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <termio.h>
+Autoconf TCGETA
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "$ac_pattern" >/dev/null 2>&1; then
+  ac_cv_prog_gcc_traditional=yes
+fi
+rm -f conftest*
+
+  fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_gcc_traditional" >&5
+echo "${ECHO_T}$ac_cv_prog_gcc_traditional" >&6
+  if test $ac_cv_prog_gcc_traditional = yes; then
+    CC="$CC -traditional"
+  fi
+fi
+
+echo "$as_me:$LINENO: checking return type of signal handlers" >&5
+echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6
+if test "${ac_cv_type_signal+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+# undef signal
+#endif
+#ifdef __cplusplus
+extern "C" void (*signal (int, void (*)(int)))(int);
+#else
+void (*signal ()) ();
+#endif
+
+int
+main ()
+{
+int i;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_signal=void
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_signal=int
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_signal" >&5
+echo "${ECHO_T}$ac_cv_type_signal" >&6
+
+cat >>confdefs.h <<_ACEOF
+#define RETSIGTYPE $ac_cv_type_signal
+_ACEOF
+
+
+
+for ac_func in vprintf
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+echo "$as_me:$LINENO: checking for _doprnt" >&5
+echo $ECHO_N "checking for _doprnt... $ECHO_C" >&6
+if test "${ac_cv_func__doprnt+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define _doprnt to an innocuous variant, in case <limits.h> declares _doprnt.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define _doprnt innocuous__doprnt
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char _doprnt (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef _doprnt
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char _doprnt ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub__doprnt) || defined (__stub____doprnt)
+choke me
+#else
+char (*f) () = _doprnt;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != _doprnt;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func__doprnt=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func__doprnt=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func__doprnt" >&5
+echo "${ECHO_T}$ac_cv_func__doprnt" >&6
+if test $ac_cv_func__doprnt = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_DOPRNT 1
+_ACEOF
+
+fi
+
+fi
+done
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_func in ftime select strftime strtol getrusage times mallinfo setbuffer getpagesize strerror
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+
+
+for ac_func in ftruncate strstr strcasecmp
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  case $LIBOBJS in
+    "$ac_func.$ac_objext"   | \
+  *" $ac_func.$ac_objext"   | \
+    "$ac_func.$ac_objext "* | \
+  *" $ac_func.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS $ac_func.$ac_objext" ;;
+esac
+
+fi
+done
+
+
+
+echo "$as_me:$LINENO: checking for textdomain" >&5
+echo $ECHO_N "checking for textdomain... $ECHO_C" >&6
+if test "${ac_cv_func_textdomain+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define textdomain to an innocuous variant, in case <limits.h> declares textdomain.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define textdomain innocuous_textdomain
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char textdomain (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef textdomain
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char textdomain ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_textdomain) || defined (__stub___textdomain)
+choke me
+#else
+char (*f) () = textdomain;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != textdomain;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_textdomain=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_textdomain=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_textdomain" >&5
+echo "${ECHO_T}$ac_cv_func_textdomain" >&6
+if test $ac_cv_func_textdomain = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define ENABLE_NLS  1
+_ACEOF
+
+fi
+
+
+# *** Custom checking (based on GNU tar configure.in) ***
+# ---------------------------------------------------------------------------
+echo "$as_me:$LINENO: checking for HP-UX needing gmalloc" >&5
+echo $ECHO_N "checking for HP-UX needing gmalloc... $ECHO_C" >&6
+if test "`(uname -s) 2> /dev/null`" = 'HP-UX'; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  case $LIBOBJS in
+    "gmalloc.$ac_objext"   | \
+  *" gmalloc.$ac_objext"   | \
+    "gmalloc.$ac_objext "* | \
+  *" gmalloc.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS gmalloc.$ac_objext" ;;
+esac
+
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_VALLOC 1
+_ACEOF
+
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+
+for ac_func in valloc
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+fi
+
+# we cannot generate static libraries under Darwin
+echo "$as_me:$LINENO: checking for Apple MacOS X/Darwin" >&5
+echo $ECHO_N "checking for Apple MacOS X/Darwin... $ECHO_C" >&6
+if test "`(uname -s) 2> /dev/null`" = 'Darwin'; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  STATIC=""
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+  STATIC="-static "
+fi
+
+
+echo "$as_me:$LINENO: checking if malloc debugging is wanted" >&5
+echo $ECHO_N "checking if malloc debugging is wanted... $ECHO_C" >&6
+
+# Check whether --with-dmalloc or --without-dmalloc was given.
+if test "${with_dmalloc+set}" = set; then
+  withval="$with_dmalloc"
+  if test "$withval" = yes; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  cat >>confdefs.h <<\_ACEOF
+#define WITH_DMALLOC 1
+_ACEOF
+
+  LIBS="$LIBS -ldmalloc"
+  LDFLAGS="$LDFLAGS -g"
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi;
+
+echo "$as_me:$LINENO: checking which of rx or regex is wanted" >&5
+echo $ECHO_N "checking which of rx or regex is wanted... $ECHO_C" >&6
+
+# Check whether --with-regex or --without-regex was given.
+if test "${with_regex+set}" = set; then
+  withval="$with_regex"
+  if test "$withval" = yes; then
+  ac_with_regex=1
+  echo "$as_me:$LINENO: result: regex" >&5
+echo "${ECHO_T}regex" >&6
+  cat >>confdefs.h <<\_ACEOF
+#define WITH_REGEX 1
+_ACEOF
+
+  case $LIBOBJS in
+    "regex.$ac_objext"   | \
+  *" regex.$ac_objext"   | \
+    "regex.$ac_objext "* | \
+  *" regex.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS regex.$ac_objext" ;;
+esac
+
+fi
+fi;
+if test -z "$ac_with_regex"; then
+  echo "$as_me:$LINENO: result: rx" >&5
+echo "${ECHO_T}rx" >&6
+  echo "$as_me:$LINENO: checking for re_rx_search" >&5
+echo $ECHO_N "checking for re_rx_search... $ECHO_C" >&6
+if test "${ac_cv_func_re_rx_search+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define re_rx_search to an innocuous variant, in case <limits.h> declares re_rx_search.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define re_rx_search innocuous_re_rx_search
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char re_rx_search (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef re_rx_search
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char re_rx_search ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_re_rx_search) || defined (__stub___re_rx_search)
+choke me
+#else
+char (*f) () = re_rx_search;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != re_rx_search;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_re_rx_search=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_re_rx_search=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_re_rx_search" >&5
+echo "${ECHO_T}$ac_cv_func_re_rx_search" >&6
+if test $ac_cv_func_re_rx_search = yes; then
+  :
+else
+  case $LIBOBJS in
+    "rx.$ac_objext"   | \
+  *" rx.$ac_objext"   | \
+    "rx.$ac_objext "* | \
+  *" rx.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS rx.$ac_objext" ;;
+esac
+
+fi
+
+fi
+
+
+# ---------------------------------------------------------------------------
+if test "$ac_cv_func_alloca" = 'no'; then
+  case $LIBOBJS in
+    "xmalloc.$ac_objext"   | \
+  *" xmalloc.$ac_objext"   | \
+    "xmalloc.$ac_objext "* | \
+  *" xmalloc.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS xmalloc.$ac_objext" ;;
+esac
+
+  case $LIBOBJS in
+    "error.$ac_objext"   | \
+  *" error.$ac_objext"   | \
+    "error.$ac_objext "* | \
+  *" error.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS error.$ac_objext" ;;
+esac
+
+fi
+
+
+# ---------------------------------------------------------------------------
+
+ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+
+echo "$as_me:$LINENO: checking that the GDBM library is available" >&5
+echo $ECHO_N "checking that the GDBM library is available... $ECHO_C" >&6
+if test ! -z "$gdbmdir" ; then
+  # look in given directory for header file
+  if test -r $gdbmdir/include/gdbm.h ; then
+    GDBM_INCLUDE="-I$gdbmdir/include" ;
+  elif test -r $gdbmdir/gdbm.h ; then
+    GDBM_INCLUDE="-I$gdbmdir" ;
+  fi
+
+  # look in given directory for library
+  if test -r $gdbmdir/libgdbm.a ; then
+    GDBM_LIBPATH="-L$gdbmdir" ;
+  elif test -r $gdbmdir/lib/libgdbm.a ; then
+    GDBM_LIBPATH="-L$gdbmdir/lib" ;
+  elif test -r $gdbmdir/.libs/libgdbm.a ; then
+    GDBM_LIBPATH="-L$gdbmdir/.libs" ;
+  fi
+
+  if test ! -z "$GDBM_LIBPATH" -a ! -z "$GDBM_INCLUDE" ; then
+    echo "$as_me:$LINENO: result: $gdbmdir" >&5
+echo "${ECHO_T}$gdbmdir" >&6 ;
+  else
+    echo "$as_me:$LINENO: result: can't find gdbm.h and libgdbm.a in $gdbmdir" >&5
+echo "${ECHO_T}can't find gdbm.h and libgdbm.a in $gdbmdir" >&6;
+    echo "$as_me:$LINENO: checking looking for GDBM library in default locations" >&5
+echo $ECHO_N "checking looking for GDBM library in default locations... $ECHO_C" >&6
+  fi
+fi
+
+# look in default path and in /usr/local
+if test -z "$GDBM_INCLUDE" ; then
+  # try in system directory
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <gdbm.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_cxx_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  success=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+success=no
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+  if test $success = "no"; then
+# last chance - look in /usr/local (eg FreeBSD)
+    GDBM_LIBPATH=-L/usr/local/lib
+    GDBM_INCLUDE=-I/usr/local/include
+    ac_save_CXXFLAGS="$CXXFLAGS"
+    ac_save_LIBS="$LIBS"
+      CXXFLAGS="$CXXFLAGS -I/usr/local/include"
+      LIBS="$LIBS -L/usr/local/lib -lgdbm"
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <gdbm.h>
+#include <stdio.h>
+
+int
+main ()
+{
+printf("%s",gdbm_version);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_cxx_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  success=/usr/local
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+success=no
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+      CXXFLAGS=$ac_save_CXXFLAGS
+      LIBS=$ac_save_LIBS
+  fi
+
+  echo "$as_me:$LINENO: result: $success" >&5
+echo "${ECHO_T}$success" >&6
+  if test $success = "no"; then
+  { { echo "$as_me:$LINENO: error: GDBM Library not available - cannot install" >&5
+echo "$as_me: error: GDBM Library not available - cannot install" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+fi
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBGDBM  1
+_ACEOF
+
+
+
+
+
+echo "$as_me:$LINENO: checking that Perl 5 is available" >&5
+echo $ECHO_N "checking that Perl 5 is available... $ECHO_C" >&6
+success="no"
+pl_path="$PATH"
+IFS="${IFS=   }"; pl_save_ifs="$IFS"; IFS=":"
+for pl_dir in $pl_path; do
+  test -z "$pl_dir" && pl_dir=.
+  if test -x $pl_dir/perl; then
+    success="yes"
+    break
+  fi
+done
+IFS="$pl_save_ifs"
+
+if test $success = "yes"; then
+try=`perl configtest.pl` || try="0"
+try=`expr $try \> 5.000`
+if test $try = "1"; then
+echo "$as_me:$LINENO: result: \"yes\"" >&5
+echo "${ECHO_T}\"yes\"" >&6
+else
+success="no"
+fi
+fi
+
+if test $success = "no"; then
+echo "$as_me:$LINENO: result: \"no\"" >&5
+echo "${ECHO_T}\"no\"" >&6
+{ { echo "$as_me:$LINENO: error: \"Perl 5 not available - cannot install\"" >&5
+echo "$as_me: error: \"Perl 5 not available - cannot install\"" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+success=no
+echo "$as_me:$LINENO: checking \"whether STL library has known faults\"" >&5
+echo $ECHO_N "checking \"whether STL library has known faults\"... $ECHO_C" >&6
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <vector>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_cxx_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  success=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $success = "no"; then
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <vector.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_cxx_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  success="yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+if test $success = "no"; then
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ospace\\std\\vector>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_cxx_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  success="yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+if test $success = yes; then
+echo "$as_me:$LINENO: result: \"no\"" >&5
+echo "${ECHO_T}\"no\"" >&6
+else
+echo "$as_me:$LINENO: result: \"yes\"" >&5
+echo "${ECHO_T}\"yes\"" >&6
+{ { echo "$as_me:$LINENO: error: \"STL Broken - Obtain newer version of GNU C Compiler\"" >&5
+echo "$as_me: error: \"STL Broken - Obtain newer version of GNU C Compiler\"" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+gsdlos=`uname | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+# check for running bash under cygwin
+ if test "`echo $gsdlos | sed 's/cygwin//'`" != "$gsdlos" ;
+ then
+  gsdlos=windows
+ fi
+
+
+# check for endianness
+echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5
+echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6
+if test "${ac_cv_c_bigendian+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # See if sys/param.h defines the BYTE_ORDER macro.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
+ bogus endian macros
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_cxx_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  # It does; now see whether it defined to BIG_ENDIAN or not.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_cxx_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_bigendian=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_c_bigendian=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+# It does not; compile a test program.
+if test "$cross_compiling" = yes; then
+  # try to guess the endianness by grepping values into an object file
+  ac_cv_c_bigendian=unknown
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; }
+short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; }
+int
+main ()
+{
+ _ascii (); _ebcdic ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_cxx_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then
+  ac_cv_c_bigendian=yes
+fi
+if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+  if test "$ac_cv_c_bigendian" = unknown; then
+    ac_cv_c_bigendian=no
+  else
+    # finding both strings is unlikely to happen, but who knows?
+    ac_cv_c_bigendian=unknown
+  fi
+fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+int
+main ()
+{
+  /* Are we little or big endian?  From Harbison&Steele.  */
+  union
+  {
+    long l;
+    char c[sizeof (long)];
+  } u;
+  u.l = 1;
+  exit (u.c[sizeof (long) - 1] == 1);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_bigendian=no
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_c_bigendian=yes
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5
+echo "${ECHO_T}$ac_cv_c_bigendian" >&6
+case $ac_cv_c_bigendian in
+  yes)
+
+cat >>confdefs.h <<\_ACEOF
+#define WORDS_BIGENDIAN 1
+_ACEOF
+ ;;
+  no)
+     ;;
+  *)
+    { { echo "$as_me:$LINENO: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&5
+echo "$as_me: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+
+# ---------------------------------------------------------------------------
+if test "$ac_cv_func_alloca" = 'no'; then
+  case $LIBOBJS in
+    "xmalloc.o.$ac_objext"   | \
+  *" xmalloc.o.$ac_objext"   | \
+    "xmalloc.o.$ac_objext "* | \
+  *" xmalloc.o.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS xmalloc.o.$ac_objext" ;;
+esac
+
+  case $LIBOBJS in
+    "error.$ac_objext"   | \
+  *" error.$ac_objext"   | \
+    "error.$ac_objext "* | \
+  *" error.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS error.$ac_objext" ;;
+esac
+
+fi
+
+# ---------------------------------------------------------------------------
+
+moduleDirs=""
+MODULEDIRS=""
+for x in `find modules -mindepth 1 -maxdepth 2`; do
+  if test -d "$x"; then
+    d="$x/Makefile.in"
+    if test -e "$d"; then
+      moduleDirs="$moduleDirs $x/Makefile"
+      MODULEDIRS="$MODULEDIRS $x"
+    fi
+  fi
+done
+echo "Making$moduleDirs in modules directory"
+
+
+# ---------------------------------------------------------------------------
+
+# indexers needs bindir option to get the binaries into the
+# right place
+gsdlprefix=`pwd`
+ac_configure_args="$ac_configure_args --bindir=$gsdlprefix/bin/$gsdlos "
+
+
+
+subdirs="$subdirs packages indexers"
+
+
+# the list of folders in the src folder
+srclist="src/hashfile/Makefile src/txt2db/Makefile src/db2txt/Makefile src/phind/generate/Makefile "
+
+                                                  ac_config_files="$ac_config_files packages/Makefile lib/Makefile Makefile $srclist $moduleDirs"
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+  (set) 2>&1 |
+    case `(ac_space=' '; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;;
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n \
+	"s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+} |
+  sed '
+     t clear
+     : clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
+  if test -w $cache_file; then
+    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+    cat confcache >$cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[	 ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[	 ]*$//;
+}'
+fi
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_i=`echo "$ac_i" |
+	 sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+  # 2. Add them.
+  ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)$' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+  	  /^X\/\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\/\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+	 case $as_dir in
+	 /*)
+	   if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+	     $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+	     $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+	     CONFIG_SHELL=$as_dir/$as_base
+	     export CONFIG_SHELL
+	     exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+	   fi;;
+	 esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='	' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" 	$as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.  Logging --version etc. is OK.
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.59.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+  echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+  echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+  echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+  echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number, then exit
+  -q, --quiet      do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+  --file=FILE[:TEMPLATE]
+		   instantiate the configuration file FILE
+  --header=FILE[:TEMPLATE]
+		   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.59,
+  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+INSTALL="$INSTALL"
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value.  By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "x$1" : 'x\([^=]*\)='`
+    ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  -*)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  *) # This is not an option, so the user has probably given explicit
+     # arguments.
+     ac_option=$1
+     ac_need_defaults=false;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --vers* | -V )
+    echo "$ac_cs_version"; exit 0 ;;
+  --he | --h)
+    # Conflict between --help and --header
+    { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    echo "$ac_cs_usage"; exit 0 ;;
+  --debug | --d* | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+    ac_need_defaults=false;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1" ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+  echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+  exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+  case "$ac_config_target" in
+  # Handling of arguments.
+  "packages/Makefile" ) CONFIG_FILES="$CONFIG_FILES packages/Makefile" ;;
+  "lib/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;;
+  "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+  "$srclist" ) CONFIG_FILES="$CONFIG_FILES $srclist" ;;
+  "$moduleDirs" ) CONFIG_FILES="$CONFIG_FILES $moduleDirs" ;;
+  "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./confstat$$-$RANDOM
+  (umask 077 && mkdir $tmp)
+} ||
+{
+   echo "$me: cannot create a temporary directory in ." >&2
+   { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+  # Protect against being on the right side of a sed subst in config.status.
+  sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+   s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@PACKAGE@,$PACKAGE,;t t
+s,@VERSION@,$VERSION,;t t
+s,@ENABLE_ACCENTFOLD@,$ENABLE_ACCENTFOLD,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@CC@,$CC,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@CXX@,$CXX,;t t
+s,@CXXFLAGS@,$CXXFLAGS,;t t
+s,@ac_ct_CXX@,$ac_ct_CXX,;t t
+s,@AWK@,$AWK,;t t
+s,@YACC@,$YACC,;t t
+s,@build@,$build,;t t
+s,@build_cpu@,$build_cpu,;t t
+s,@build_vendor@,$build_vendor,;t t
+s,@build_os@,$build_os,;t t
+s,@host@,$host,;t t
+s,@host_cpu@,$host_cpu,;t t
+s,@host_vendor@,$host_vendor,;t t
+s,@host_os@,$host_os,;t t
+s,@target@,$target,;t t
+s,@target_cpu@,$target_cpu,;t t
+s,@target_vendor@,$target_vendor,;t t
+s,@target_os@,$target_os,;t t
+s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
+s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
+s,@INSTALL_DATA@,$INSTALL_DATA,;t t
+s,@LN_S@,$LN_S,;t t
+s,@SET_MAKE@,$SET_MAKE,;t t
+s,@RANLIB@,$RANLIB,;t t
+s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
+s,@CPP@,$CPP,;t t
+s,@EGREP@,$EGREP,;t t
+s,@U@,$U,;t t
+s,@ANSI2KNR@,$ANSI2KNR,;t t
+s,@ALLOCA@,$ALLOCA,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@STATIC@,$STATIC,;t t
+s,@GDBM_LIBPATH@,$GDBM_LIBPATH,;t t
+s,@GDBM_INCLUDE@,$GDBM_INCLUDE,;t t
+s,@gsdlos@,$gsdlos,;t t
+s,@MODULEDIRS@,$MODULEDIRS,;t t
+s,@subdirs@,$subdirs,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
+
+_ACEOF
+
+  cat >>$CONFIG_STATUS <<\_ACEOF
+  # Split the substitutions into bite-sized pieces for seds with
+  # small command number limits, like on Digital OSF/1 and HP-UX.
+  ac_max_sed_lines=48
+  ac_sed_frag=1 # Number of current file.
+  ac_beg=1 # First line for current file.
+  ac_end=$ac_max_sed_lines # Line after last line for current file.
+  ac_more_lines=:
+  ac_sed_cmds=
+  while $ac_more_lines; do
+    if test $ac_beg -gt 1; then
+      sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    else
+      sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    fi
+    if test ! -s $tmp/subs.frag; then
+      ac_more_lines=false
+    else
+      # The purpose of the label and of the branching condition is to
+      # speed up the sed processing (if there are no `@' at all, there
+      # is no need to browse any of the substitutions).
+      # These are the two extra sed commands mentioned above.
+      (echo ':t
+  /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+      if test -z "$ac_sed_cmds"; then
+	ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+      else
+	ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+      fi
+      ac_sed_frag=`expr $ac_sed_frag + 1`
+      ac_beg=$ac_end
+      ac_end=`expr $ac_end + $ac_max_sed_lines`
+    fi
+  done
+  if test -z "$ac_sed_cmds"; then
+    ac_sed_cmds=cat
+  fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+	cat >$tmp/stdin
+	ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+  ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+  { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+  ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_builddir$INSTALL ;;
+  esac
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    configure_input=
+  else
+    configure_input="$ac_file.  "
+  fi
+  configure_input=$configure_input"Generated from `echo $ac_file_in |
+				     sed 's,.*/,,'` by configure."
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+	 # Absolute (can't be DOS-style, as IFS=:)
+	 test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+	 echo "$f";;
+      *) # Relative
+	 if test -f "$f"; then
+	   # Build tree
+	   echo "$f"
+	 elif test -f "$srcdir/$f"; then
+	   # Source tree
+	   echo "$srcdir/$f"
+	 else
+	   # /dev/null tree
+	   { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+	 fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+s,@INSTALL@,$ac_INSTALL,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+  rm -f $tmp/stdin
+  if test x"$ac_file" != x-; then
+    mv $tmp/out $ac_file
+  else
+    cat $tmp/out
+    rm -f $tmp/out
+  fi
+
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_HEADER section.
+#
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s,^\([	 ]*\)#\([	 ]*define[	 ][	 ]*\)'
+ac_dB='[	 ].*$,\1#\2'
+ac_dC=' '
+ac_dD=',;t'
+# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_uA='s,^\([	 ]*\)#\([	 ]*\)undef\([	 ][	 ]*\)'
+ac_uB='$,\1#\2define\3'
+ac_uC=' '
+ac_uD=',;t'
+
+for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+	cat >$tmp/stdin
+	ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+	 # Absolute (can't be DOS-style, as IFS=:)
+	 test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+	 # Do quote $f, to prevent DOS paths from being IFS'd.
+	 echo "$f";;
+      *) # Relative
+	 if test -f "$f"; then
+	   # Build tree
+	   echo "$f"
+	 elif test -f "$srcdir/$f"; then
+	   # Source tree
+	   echo "$srcdir/$f"
+	 else
+	   # /dev/null tree
+	   { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+	 fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+  # Remove the trailing spaces.
+  sed 's/[	 ]*$//' $ac_file_inputs >$tmp/in
+
+_ACEOF
+
+# Transform confdefs.h into two sed scripts, `conftest.defines' and
+# `conftest.undefs', that substitutes the proper values into
+# config.h.in to produce config.h.  The first handles `#define'
+# templates, and the second `#undef' templates.
+# And first: Protect against being on the right side of a sed subst in
+# config.status.  Protect against being in an unquoted here document
+# in config.status.
+rm -f conftest.defines conftest.undefs
+# Using a here document instead of a string reduces the quoting nightmare.
+# Putting comments in sed scripts is not portable.
+#
+# `end' is used to avoid that the second main sed command (meant for
+# 0-ary CPP macros) applies to n-ary macro definitions.
+# See the Autoconf documentation for `clear'.
+cat >confdef2sed.sed <<\_ACEOF
+s/[\\&,]/\\&/g
+s,[\\$`],\\&,g
+t clear
+: clear
+s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*\)\(([^)]*)\)[	 ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
+t end
+s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
+: end
+_ACEOF
+# If some macros were called several times there might be several times
+# the same #defines, which is useless.  Nevertheless, we may not want to
+# sort them, since we want the *last* AC-DEFINE to be honored.
+uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
+sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
+rm -f confdef2sed.sed
+
+# This sed command replaces #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >>conftest.undefs <<\_ACEOF
+s,^[	 ]*#[	 ]*undef[	 ][	 ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
+_ACEOF
+
+# Break up conftest.defines because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
+echo '  if grep "^[	 ]*#[	 ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
+echo '  # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
+echo '  :' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.defines >/dev/null
+do
+  # Write a limited-size here document to $tmp/defines.sed.
+  echo '  cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#define' lines.
+  echo '/^[	 ]*#[	 ]*define/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
+  echo 'CEOF
+  sed -f $tmp/defines.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
+  rm -f conftest.defines
+  mv conftest.tail conftest.defines
+done
+rm -f conftest.defines
+echo '  fi # grep' >>$CONFIG_STATUS
+echo >>$CONFIG_STATUS
+
+# Break up conftest.undefs because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #undef templates' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.undefs >/dev/null
+do
+  # Write a limited-size here document to $tmp/undefs.sed.
+  echo '  cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#undef'
+  echo '/^[	 ]*#[	 ]*undef/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
+  echo 'CEOF
+  sed -f $tmp/undefs.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
+  rm -f conftest.undefs
+  mv conftest.tail conftest.undefs
+done
+rm -f conftest.undefs
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    echo "/* Generated by configure.  */" >$tmp/config.h
+  else
+    echo "/* $ac_file.  Generated by configure.  */" >$tmp/config.h
+  fi
+  cat $tmp/in >>$tmp/config.h
+  rm -f $tmp/in
+  if test x"$ac_file" != x-; then
+    if diff $ac_file $tmp/config.h >/dev/null 2>&1; then
+      { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+      { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+      rm -f $ac_file
+      mv $tmp/config.h $ac_file
+    fi
+  else
+    cat $tmp/config.h
+    rm -f $tmp/config.h
+  fi
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
+
+#
+# CONFIG_SUBDIRS section.
+#
+if test "$no_recursion" != yes; then
+
+  # Remove --cache-file and --srcdir arguments so they do not pile up.
+  ac_sub_configure_args=
+  ac_prev=
+  for ac_arg in $ac_configure_args; do
+    if test -n "$ac_prev"; then
+      ac_prev=
+      continue
+    fi
+    case $ac_arg in
+    -cache-file | --cache-file | --cache-fil | --cache-fi \
+    | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+      ac_prev=cache_file ;;
+    -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+    | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \
+    | --c=*)
+      ;;
+    --config-cache | -C)
+      ;;
+    -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+      ac_prev=srcdir ;;
+    -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+      ;;
+    -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+      ac_prev=prefix ;;
+    -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+      ;;
+    *) ac_sub_configure_args="$ac_sub_configure_args $ac_arg" ;;
+    esac
+  done
+
+  # Always prepend --prefix to ensure using the same prefix
+  # in subdir configurations.
+  ac_sub_configure_args="--prefix=$prefix $ac_sub_configure_args"
+
+  ac_popdir=`pwd`
+  for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue
+
+    # Do not complain, so a configure script can configure whichever
+    # parts of a large source tree are present.
+    test -d $srcdir/$ac_dir || continue
+
+    { echo "$as_me:$LINENO: configuring in $ac_dir" >&5
+echo "$as_me: configuring in $ac_dir" >&6;}
+    { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+    ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+
+    cd $ac_dir
+
+    # Check for guested configure; otherwise get Cygnus style configure.
+    if test -f $ac_srcdir/configure.gnu; then
+      ac_sub_configure="$SHELL '$ac_srcdir/configure.gnu'"
+    elif test -f $ac_srcdir/configure; then
+      ac_sub_configure="$SHELL '$ac_srcdir/configure'"
+    elif test -f $ac_srcdir/configure.in; then
+      ac_sub_configure=$ac_configure
+    else
+      { echo "$as_me:$LINENO: WARNING: no configuration information is in $ac_dir" >&5
+echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;}
+      ac_sub_configure=
+    fi
+
+    # The recursion is here.
+    if test -n "$ac_sub_configure"; then
+      # Make the cache file name correct relative to the subdirectory.
+      case $cache_file in
+      [\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;;
+      *) # Relative path.
+	ac_sub_cache_file=$ac_top_builddir$cache_file ;;
+      esac
+
+      { echo "$as_me:$LINENO: running $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5
+echo "$as_me: running $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;}
+      # The eval makes quoting arguments work.
+      eval $ac_sub_configure $ac_sub_configure_args \
+	   --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir ||
+	{ { echo "$as_me:$LINENO: error: $ac_sub_configure failed for $ac_dir" >&5
+echo "$as_me: error: $ac_sub_configure failed for $ac_dir" >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+
+    cd $ac_popdir
+  done
+fi
+
Index: /tags/greenstone-3_02-distribution/gs2build-extra/configure.in
===================================================================
--- /tags/greenstone-3_02-distribution/gs2build-extra/configure.in	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gs2build-extra/configure.in	(revision 13928)
@@ -0,0 +1,357 @@
+dnl Process this file with autoconf to produce a configure script.
+dnl Use autoconf-2.59 or later... it might not work anymore with
+dnl the older 2.1x versions - jrm21 12/2004
+AC_INIT(lib/text_t.h)
+AC_CONFIG_HEADER(config.h)
+
+PACKAGE=gsdl
+VERSION=2.1
+AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE")
+AC_DEFINE_UNQUOTED(VERSION, "$VERSION")
+AC_SUBST(PACKAGE)
+AC_SUBST(VERSION)
+
+dnl
+dnl look for libgdbm if not in standard location
+dnl
+AC_ARG_WITH(gdbm, [  --with-gdbm=dir         Use local gdbm library and headers], gdbmdir=$withval)
+
+
+dnl 
+dnl disable compilation of accent folding stuff for mgpp (and one day mg)
+dnl
+AC_ARG_ENABLE(accentfold, [  --disable-accentfold          Disable Accent Folding for MGPP], ENABLE_ACCENTFOLD=0, ENABLE_ACCENTFOLD=1)
+AC_DEFINE(ENABLE_ACCENTFOLD, $ENABLE_ACCENTFOLD)
+AC_SUBST(ENABLE_ACCENTFOLD)
+
+
+dnl Checks for programs.
+LDFLAGS=
+dnl only set CFLAGS if not already set in environment
+if test -z "$CFLAGS"; then
+CFLAGS=-O2
+fi
+AC_SUBST(CFLAGS)
+
+AC_PROG_CC
+AC_PROG_CXX
+AC_PROG_AWK
+AC_PROG_YACC
+dnl get $target_cpu, $target_vendor, and $target_os
+dnl (as well as host_*)
+AC_CANONICAL_SYSTEM
+dnl do we actually want this? It adds a prefix based on host, system etc
+dnl AC_ARG_PROGRAM
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+AC_PROG_RANLIB
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_AIX
+AC_ISC_POSIX
+AC_MINIX
+fp_C_PROTOTYPES
+AC_C_CONST
+AC_TYPE_OFF_T
+AC_TYPE_SIZE_T
+AC_HEADER_TIME
+AC_STRUCT_TM
+
+dnl --- This should be in the stdc checking -----------------
+if test "$ac_cv_prog_cc_stdc" = '-Xc'; then
+dnl The Pyramids running SMP_DC.OSx on MIPS r3000 chips with
+dnl /usr/opt/cc3.11/bin/cc treat -Xc as full ANSI mode - no POSIX or
+dnl XOPEN extensions (like popen).
+dnl Unfortunately -D_{XOPEN,POSIX}_SOURCE can't provide all that mg
+dnl needs. So drop back to -Xa
+AC_TRY_COMPILE(
+[#include <stdio.h>
+], [ FILE *rubbish = popen("yes", "r"); ],,
+[CC="`echo $CC | sed 's/-Xc/-Xa/'`"    ac_cv_prog_cc_stdc='-Xa'])
+fi
+dnl ----------------------
+
+
+dnl Checks for libraries.
+dnl check for -lg:
+AC_HAVE_LIBRARY(g)
+dnl check for -lm:
+AC_HAVE_LIBRARY(m)
+dnl check for -lcrypt:
+AC_HAVE_LIBRARY(crypt)
+if test $ENABLE_ACCENTFOLD = 1; then
+AC_HAVE_LIBRARY(ICONV)
+fi
+
+
+dnl Checks for header files.
+AC_HEADER_DIRENT
+AC_HEADER_STDC
+AC_CHECK_HEADERS(fcntl.h limits.h sys/time.h unistd.h crypt.h string.h memory.h sys/procfs.h)
+AC_EGREP_HEADER(fread, stdio.h, AC_DEFINE(HAVE_FREAD_DECL))
+AC_EGREP_HEADER(fgetc, stdio.h, AC_DEFINE(HAVE_FGETC_DECL))
+AC_EGREP_HEADER(pr_brksize, sys/procfs.h, AC_DEFINE(HAVE_PR_BRKSIZE))
+
+dnl Checks for library functions.
+AC_FUNC_ALLOCA
+AC_PROG_GCC_TRADITIONAL
+AC_TYPE_SIGNAL
+AC_FUNC_VPRINTF
+AC_CHECK_FUNCS(ftime select strftime strtol getrusage times mallinfo setbuffer getpagesize strerror)
+AC_REPLACE_FUNCS(ftruncate strstr strcasecmp)
+
+dnl see if gettext is in libc. (try the textdomain() function).
+AC_CHECK_FUNC(textdomain, AC_DEFINE(ENABLE_NLS ,1) )
+
+# *** Custom checking (based on GNU tar configure.in) ***
+# ---------------------------------------------------------------------------
+AC_MSG_CHECKING(for HP-UX needing gmalloc)
+if test "`(uname -s) 2> /dev/null`" = 'HP-UX'; then
+  AC_MSG_RESULT(yes)
+  AC_LIBOBJ([gmalloc])
+  AC_DEFINE(HAVE_VALLOC)
+else
+  AC_MSG_RESULT(no)
+  AC_CHECK_FUNCS(valloc)
+fi
+
+# we cannot generate static libraries under Darwin
+AC_MSG_CHECKING(for Apple MacOS X/Darwin)
+if test "`(uname -s) 2> /dev/null`" = 'Darwin'; then
+  AC_MSG_RESULT(yes)
+  STATIC=""
+else
+  AC_MSG_RESULT(no)
+  STATIC="-static "
+fi
+AC_SUBST(STATIC)
+
+fp_WITH_DMALLOC
+fp_WITH_REGEX
+
+# ---------------------------------------------------------------------------
+if test "$ac_cv_func_alloca" = 'no'; then
+dnl    support functions for alloca.c
+  AC_LIBOBJ([xmalloc])
+  AC_LIBOBJ([error])
+fi
+
+
+# ---------------------------------------------------------------------------
+
+dnl
+dnl Switch into C++
+dnl
+AC_LANG_CPLUSPLUS
+
+dnl
+dnl Check that the GDBM library is available
+dnl
+dnl check libgdbm manually, in case it's not in the standard location.
+
+AC_MSG_CHECKING(that the GDBM library is available)
+if test ! -z "$gdbmdir" ; then
+  # look in given directory for header file
+  if test -r $gdbmdir/include/gdbm.h ; then
+    GDBM_INCLUDE="-I$gdbmdir/include" ;
+  elif test -r $gdbmdir/gdbm.h ; then
+    GDBM_INCLUDE="-I$gdbmdir" ;
+  fi
+
+  # look in given directory for library
+  if test -r $gdbmdir/libgdbm.a ; then
+    GDBM_LIBPATH="-L$gdbmdir" ;
+  elif test -r $gdbmdir/lib/libgdbm.a ; then
+    GDBM_LIBPATH="-L$gdbmdir/lib" ;
+  elif test -r $gdbmdir/.libs/libgdbm.a ; then
+    GDBM_LIBPATH="-L$gdbmdir/.libs" ;
+  fi
+
+  if test ! -z "$GDBM_LIBPATH" -a ! -z "$GDBM_INCLUDE" ; then
+    AC_MSG_RESULT($gdbmdir) ;
+  else
+    AC_MSG_RESULT(can't find gdbm.h and libgdbm.a in $gdbmdir);
+    AC_MSG_CHECKING(   looking for GDBM library in default locations)
+  fi
+fi
+
+# look in default path and in /usr/local
+if test -z "$GDBM_INCLUDE" ; then
+  # try in system directory 
+  AC_TRY_COMPILE(
+  [#include <gdbm.h>
+],
+  [],
+  success=yes,
+  success=no
+  )
+
+  if test $success = "no"; then
+# last chance - look in /usr/local (eg FreeBSD)
+    GDBM_LIBPATH=-L/usr/local/lib
+    GDBM_INCLUDE=-I/usr/local/include
+    ac_save_CXXFLAGS="$CXXFLAGS"
+    ac_save_LIBS="$LIBS"
+      CXXFLAGS="$CXXFLAGS -I/usr/local/include"
+      LIBS="$LIBS -L/usr/local/lib -lgdbm"
+      AC_TRY_LINK(
+  	[#include <gdbm.h>
+#include <stdio.h>
+	],
+  	[printf("%s",gdbm_version);],
+  	success=/usr/local,
+  	success=no
+      )
+      CXXFLAGS=$ac_save_CXXFLAGS
+      LIBS=$ac_save_LIBS
+  fi
+
+  AC_MSG_RESULT($success)
+  if test $success = "no"; then
+  AC_MSG_ERROR(GDBM Library not available - cannot install)
+  fi
+fi
+dnl I don't think anything actually checks this define, but...
+AC_DEFINE(HAVE_LIBGDBM , 1)
+
+AC_SUBST(GDBM_LIBPATH)
+AC_SUBST(GDBM_INCLUDE)
+
+dnl
+dnl Now check that Perl is actually around, and can be found
+dnl
+AC_MSG_CHECKING(that Perl 5 is available)
+success="no"
+pl_path="$PATH"
+IFS="${IFS=   }"; pl_save_ifs="$IFS"; IFS=":"
+for pl_dir in $pl_path; do
+  test -z "$pl_dir" && pl_dir=.
+  if test -x $pl_dir/perl; then
+    success="yes"
+    break
+  fi
+done
+IFS="$pl_save_ifs"
+
+dnl
+dnl Perl actually can be run; now we see if it is version 5 by
+dnl running a sample script (which returns a "clean" version number
+dnl and then tests the result using expr.  If perl errors in some
+dnl way (eg. broken Perl executable, missing script), we set a failure
+dnl value ("0") and then proceed as best we can
+dnl
+if test $success = "yes"; then
+try=`perl configtest.pl` || try="0"
+try=`expr $try \> 5.000`
+if test $try = "1"; then
+AC_MSG_RESULT("yes")
+else
+success="no"
+fi
+fi
+
+if test $success = "no"; then
+AC_MSG_RESULT("no")
+AC_MSG_ERROR("Perl 5 not available - cannot install")
+fi
+
+dnl
+dnl Check if the STL library has any known faults;
+dnl In GCC 2.7.2.x series, some STL library headers are missing
+dnl a file called "new" which is referred to by other headers
+dnl (eg. vector/vector.h); if this applies, then all use of the
+dnl STL will cause a compile fail, so we'd better let the user
+dnl know now, before things really go wrong!
+dnl
+success=no
+AC_MSG_CHECKING("whether STL library has known faults")
+
+dnl - first shot, try simple good old vector on its own
+AC_TRY_COMPILE(
+[#include <vector>
+], 
+[],
+success=yes,
+)
+
+dnl - try using the .h equivalent
+if test $success = "no"; then
+AC_TRY_COMPILE(
+[#include <vector.h>
+], 
+[],
+success="yes",
+)
+fi
+
+dnl - now try for the objectspace headers
+if test $success = "no"; then
+AC_TRY_COMPILE(
+[#include <ospace\\std\\vector>
+], 
+[],
+success="yes",
+)
+fi
+
+if test $success = yes; then
+AC_MSG_RESULT("no")
+else
+AC_MSG_RESULT("yes")
+AC_MSG_ERROR("STL Broken - Obtain newer version of GNU C Compiler")
+fi
+
+gsdlos=`uname | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+# check for running bash under cygwin
+ if test "`echo $gsdlos | sed 's/cygwin//'`" != "$gsdlos" ;
+ then
+  gsdlos=windows
+ fi
+AC_SUBST(gsdlos)
+
+# check for endianness
+AC_C_BIGENDIAN
+# ---------------------------------------------------------------------------
+if test "$ac_cv_func_alloca" = 'no'; then
+dnl    support functions for alloca.c
+  AC_LIBOBJ([xmalloc.o])
+  AC_LIBOBJ([error])
+fi
+
+# ---------------------------------------------------------------------------
+
+dnl
+dnl Locate all children of the modules folder
+dnl
+moduleDirs=""
+MODULEDIRS=""
+for x in `find modules -mindepth 1 -maxdepth 2`; do
+  if test -d "$x"; then
+    d="$x/Makefile.in"
+    if test -e "$d"; then
+dnl      echo $d
+      moduleDirs="$moduleDirs $x/Makefile"
+      MODULEDIRS="$MODULEDIRS $x"
+    fi
+  fi
+done
+echo "Making$moduleDirs in modules directory"
+AC_SUBST(MODULEDIRS)
+
+# ---------------------------------------------------------------------------
+dnl for Darwin, as our packages don't (yet) correctly guess our system type.
+dnl not needed any more?
+dnl ac_configure_args="$ac_configure_args --build=$build --target=$target"
+
+# indexers needs bindir option to get the binaries into the 
+# right place
+gsdlprefix=`pwd`
+ac_configure_args="$ac_configure_args --bindir=$gsdlprefix/bin/$gsdlos "
+
+AC_CONFIG_SUBDIRS(packages indexers)
+
+# the list of folders in the src folder
+srclist="src/hashfile/Makefile src/txt2db/Makefile src/db2txt/Makefile src/phind/generate/Makefile "
+
+AC_OUTPUT(packages/Makefile lib/Makefile Makefile $srclist $moduleDirs)
Index: /tags/greenstone-3_02-distribution/gs2build-extra/lib.Makefile.in
===================================================================
--- /tags/greenstone-3_02-distribution/gs2build-extra/lib.Makefile.in	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gs2build-extra/lib.Makefile.in	(revision 13928)
@@ -0,0 +1,80 @@
+###########################################################################
+#
+# Makefile -- lib
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999  The New Zealand Digital Library Project
+#
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+AR = ar
+CC = @CC@
+CPP = @CXX@
+#CCFLAGS = @CFLAGS@ -Wall -Wunused -pedantic -W -Woverloaded-virtual
+CCFLAGS = @CFLAGS@
+DEFS = @DEFS@
+INCLUDES = -I../indexers/mg/lib -I..
+RANLIB = @RANLIB@
+
+COMPILE = $(CC) -c $(CCFLAGS) $(DEFS) $(INCLUDES)
+CPPCOMPILE = $(CPP) -c $(CCFLAGS) $(DEFS) $(INCLUDES)
+
+.SUFFIXES:
+.SUFFIXES: .c .o
+.c.o:
+	$(COMPILE) $<
+
+.SUFFIXES: .cpp .o
+.cpp.o:
+	$(CPPCOMPILE) $< 
+
+HEADERS = \
+ text_t.h gsdlconf.h 
+
+SOURCES = \
+  text_t.cpp 
+
+OBJECTS = \
+  text_t.o  
+
+
+all: gsdllib.a
+
+GSDLLIBOBJECTS = $(OBJECTS)
+
+gsdllib.a: $(GSDLLIBOBJECTS)
+	rm -f gsdllib.a
+	$(AR) cru gsdllib.a $(GSDLLIBOBJECTS)
+	$(RANLIB) gsdllib.a
+
+clean:
+	rm -f $(OBJECTS) gsdllib.a 
+
+distclean: clean
+	rm -f Makefile
+install:
+
+depend:
+	makedepend -Y -- $(DEFS) $(INCLUDES) $(CCFLAGS) -- $(SOURCES)
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gs2build-extra/lib.win32.mak
===================================================================
--- /tags/greenstone-3_02-distribution/gs2build-extra/lib.win32.mak	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gs2build-extra/lib.win32.mak	(revision 13928)
@@ -0,0 +1,81 @@
+###########################################################################
+#
+# win32 makefile -- lib
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999  The New Zealand Digital Library Project
+#
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+GSDLHOME = ..
+USE_STLPORT = 0
+DLL = 0
+DLLDEBUG = 0
+STLPATH = "$(GSDLHOME)\packages\windows\stlport\stlport"
+
+AR = lib
+CC = cl
+
+CPPFLAGS = -GX
+!IF $(DLL)
+CPPFLAGS = $(CPPFLAGS) -MD
+!ELSE
+!IF ($(DLLDEBUG))
+CPPFLAGS = $(CPPFLAGS) -MDd
+!ENDIF
+!ENDIF
+
+DEFS = -D__WIN32__ -DHAVE_CONFIG_H -DPARADOCNUM -D_LITTLE_ENDIAN \
+       -DSHORT_SUFFIX
+INCLUDES = -I"$(GSDLHOME)" -I"$(GSDLHOME)\indexers\mg\lib"
+!IF $(USE_STLPORT)
+DEFS = $(DEFS) -DGSDL_NAMESPACE_BROKEN -DGSDL_USE_IOS_H -D__STL_NO_NEW_IOSTREAMS
+INCLUDES = $(INCLUDES) -I$(STLPATH)
+!ENDIF
+
+COMPILE = $(CC) -c $(CPPFLAGS) $(DEFS) $(INCLUDES)
+
+.SUFFIXES:
+.SUFFIXES: .c .obj
+.c.obj:
+	$(COMPILE) $<
+
+.SUFFIXES: .cpp .obj
+.cpp.obj:
+	$(COMPILE) $< 
+
+HEADERS = text_t.h gsdlconf.h
+
+SOURCES = text_t.cpp 
+
+OBJECTS = text_t.obj 
+
+all: gsdllib.lib
+
+gsdllib.lib : $(OBJECTS)
+	if EXIST gsdllib.lib del gsdllib.lib
+	$(AR) /out:gsdllib.lib $(OBJECTS)
+
+clean:
+	del *.obj 
+	del gsdllib.lib
+
+install:
+
Index: /tags/greenstone-3_02-distribution/gs2build-extra/packages.Makefile.in
===================================================================
--- /tags/greenstone-3_02-distribution/gs2build-extra/packages.Makefile.in	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gs2build-extra/packages.Makefile.in	(revision 13928)
@@ -0,0 +1,58 @@
+###########################################################################
+#
+# Makefile -- Makefile for packages included with Greenstone
+#
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 2000 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+# PACKAGEDIRS contains the packages that we want to make and install.  It
+# is assumed that each package will have at least four rules: all, install,
+# clean, and distclean.
+
+PACKAGEDIRS =	wv/wv-gs rtftohtml/rtftohtml_src pdftohtml/pdftohtml_gs \
+		wget/wget-1.9 expat/ cpan/XML-Parser-2.34 \
+		xlhtml/xlhtml-0.4.9.0 isis-gdl 
+
+all:
+	for odir in $(PACKAGEDIRS); do \
+          echo making $@ in $$odir; \
+          (cd $$odir && $(MAKE) $(MDEFINES) $@) || exit 1; \
+        done
+
+install:
+	for idir in $(PACKAGEDIRS); do \
+          echo installing $$idir; \
+          (cd $$idir && $(MAKE) install) || exit 1; \
+        done
+
+clean:
+	for subdir in $(PACKAGEDIRS); do \
+          echo cleaning $@ in $$subdir; \
+          (cd $$subdir && $(MAKE) clean || exit 0) ; \
+        done
+
+distclean:
+	for subdir in $(PACKAGEDIRS); do \
+          echo cleaning $@ in $$subdir; \
+          (cd $$subdir && $(MAKE) distclean || exit 0) ; \
+        done
Index: /tags/greenstone-3_02-distribution/gs2build-extra/packages.configure
===================================================================
--- /tags/greenstone-3_02-distribution/gs2build-extra/packages.configure	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gs2build-extra/packages.configure	(revision 13928)
@@ -0,0 +1,172 @@
+#! /bin/sh
+
+PACKAGES=`pwd`
+cd ..
+GSDLHOME=`pwd`
+cd $PACKAGES
+
+GSDLOS=`uname -s |tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+# check for running bash under cygwin
+if test "`echo $GSDLOS | sed 's/cygwin//'`" != "$GSDLOS" ;
+then
+ GSDLOS=windows
+fi
+
+prefix=""
+bindir=""
+HOSTTARGETFLAGS=""
+# only some of the packages can take environment variables as options to 
+# configure 
+# format is VAR=value, e.g "LDFLAGS=-static"
+ENVIRONMENT=""
+
+# parse any arguments given from toplevel configure
+while test $# -ne 0; do
+    case "$1" in
+	--cache-file=*)
+	    cache_filename=`echo $1 | sed s/--cache-file=//`
+	    # turn relative path into an absolute path
+	    cache_dir=`echo $cache_filename | sed 's@/[^/]*$@@'`
+	    cache_dir=`cd $cache_dir 2>/dev/null && pwd`
+
+	    cache_basefile=`echo $cache_filename | sed 's@.*/@@'`
+	    cache_file="$cache_dir/$cache_basefile"
+	    if test ! -f "$cache_file"; then
+		CACHE_FILE=""
+	    else
+		CACHE_FILE="--cache-file=$cache_file"
+	    fi
+	    ;;
+	--prefix=*)
+	    prefix=`echo $1 | sed s/--prefix=//`
+	    ;;
+	--bindir=*)
+	    # where to install binaries to
+	    bindir=`echo $1 | sed s/--bindir=//`
+	    # turn relative path into an absolute path
+	    if test -d "$bindir" ; then
+	      bindir=`cd "$bindir" ; pwd `
+	      cd "$PACKAGES"
+	    elif test -z `echo $bindir | sed '/^\// p;D'` ; then
+	      rel_bindir="`echo $bindir | sed s@/.*@@`"
+	      cd "$rel_bindir"
+	      bindir="`pwd`/`echo $bindir | sed s@^[^/]*/@@`"
+	      cd "$PACKAGES"
+	    else
+	      # bindir doesn't exist, and isn't relative
+	      true
+	    fi
+	    ;;
+	--host=* | --target=*)
+	    HOSTTARGETFLAGS="$HOSTTARGETFLAGS $1"
+	    ;;
+	*)
+	    # ignore all other options for now
+	    ;;
+    esac
+    shift
+done
+
+# note! Our GSDL package currently always installs into it's source
+# directory, ignoring any --prefix given to configure.
+# When this is fixed, uncomment the relevant lines below...
+
+##if test -z "$prefix" ; then
+prefix="${GSDLHOME}"
+##fi
+
+##if test -z "$bindir" ; then
+bindir="${prefix}/bin/$GSDLOS"
+##fi
+
+# This loads the top configure's cache file, with variables already set.
+if test -f "$cache_file" ; then
+  . $cache_file
+fi
+
+# we assume that gzip and tar are on the search path.
+# non-GNU versions of tar don't take the -z option.
+
+# configure the wvWare Word document converter
+echo ""
+echo "Configuring wvWare"
+echo ""
+
+cd "$PACKAGES/wv"
+gzip -dc wv-0.7.1-gs.tar.gz | tar -xf -
+# datadir is for default location of wvHtml.xml config file
+cd wv-gs && \
+./configure $CACHE_FILE --prefix=$PACKAGES/wv --bindir="$bindir" --datadir="$prefix/etc/packages" $HOSTTARGETFLAGS
+
+# configure the pdftohtml converter
+echo ""
+echo "Configuring pdftohtml"
+echo ""
+
+cd "$PACKAGES/pdftohtml"
+gzip -dc pdftohtml_0_36_gs.tar.gz | tar -xf -
+cd pdftohtml_gs && \
+./configure $CACHE_FILE --prefix="$prefix" --bindir="$bindir" $HOSTTARGETFLAGS $ENVIRONMENT
+
+# rtftohtml converter
+echo ""
+echo "Configuring rtftohtml"
+echo ""
+
+cd "$PACKAGES/rtftohtml"
+gzip -dc rtftohtml-gs.tar.gz | tar -xf -
+cd rtftohtml_src && \
+./configure $CACHE_FILE --prefix="$prefix" --bindir="$bindir" $HOSTTARGETFLAGS
+
+# configure wget
+echo ""
+echo "Configuring wget"
+echo ""
+cd "$PACKAGES/wget"
+gzip -dc wget.tar.gz | tar -xf -
+cd "$PACKAGES/wget/wget-1.9" && \
+./configure $CACHE_FILE --prefix=$PACKAGES/wget --bindir="$bindir" $HOSTTARGETFLAGS
+
+# configure expat (needs to be done before XML::Parser
+echo ""
+echo "Configuring expat"
+echo ""
+cd "$PACKAGES/expat"
+gzip -dc expat-1.95.8.tar.gz | tar -xf -
+cd "$PACKAGES/expat/expat-1.95.8" && \
+./configure $CACHE_FILE --prefix=$PACKAGES/expat --bindir="$bindir" $HOSTTARGETFLAGS $ENVIRONMENT
+
+# configure XML::Parser perl module
+echo ""
+echo "Configuring XML::Parser"
+echo ""
+cd "$PACKAGES/cpan"
+perl_dir=`echo 'my $vn = $]; $vn =~ s/5\.00(\d).*$/perl-5.$1/; print "$vn" ' | perl`
+gzip -dc XML-Parser-2.34.tar.gz | tar -xf -
+cd "$PACKAGES/cpan/XML-Parser-2.34" && \
+perl Makefile.PL \
+  INSTALLSITELIB="$GSDLHOME/perllib/cpan/$perl_dir" \
+  PREFIX="$GSDLHOME/perllib/cpan/XML" \
+  INSTALLMAN1DIR="$GSDLHOME/perllib/cpan/$perl_dir" \
+  INSTALLMAN3DIR="$GSDLHOME/perllib/cpan/$perl_dir" \
+  SITEPREFIX="$GSDLHOME/perllib/cpan" \
+  EXPATINCPATH="$GSDLHOME/packages/expat/include" \
+  EXPATLIBPATH="$GSDLHOME/packages/expat/lib" 
+
+# configure powerpoint converter
+echo ""
+echo "Configuring xlhtml (powerpoint & excel converter)"
+echo ""
+cd "$PACKAGES/xlhtml"
+gzip -dc xlhtml-0.4.9.0-gs.tar.gz | tar -xf -
+cd xlhtml-0.4.9.0 && \
+./configure $CACHE_FILE --prefix="$prefix" --bindir="$bindir" $HOSTTARGETFLAGS
+
+
+# configure IsisGdl program
+echo ""
+echo "Configuring IsisGdl (CDS/ISIS database reader)"
+echo ""
+cd "$PACKAGES/isis-gdl" && \
+./configure $CACHE_FILE --prefix="$prefix" --bindir="$bindir" $HOSTTARGETFLAGS  $ENVIRONMENT
+
Index: /tags/greenstone-3_02-distribution/gs2build-extra/setup.bat
===================================================================
--- /tags/greenstone-3_02-distribution/gs2build-extra/setup.bat	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gs2build-extra/setup.bat	(revision 13928)
@@ -0,0 +1,51 @@
+@echo off
+set GSDLLANG=en
+
+if "%OS%" == "Windows_NT" goto WinNT
+if "%OS%" == "" goto Win95
+if "%GSDLLANG%" == "en" echo Setup failed - your PATH has not been set
+if "%GSDLLANG%" == "es" echo No se pudo realizar la configuraci¢n - no se ha establecido la RUTA.
+if "%GSDLLANG%" == "fr" echo Echc de l'installation - votre variable PATH n'a pas t ajuste
+if "%GSDLLANG%" == "ru" echo áâ ­®¢ª  ­¥ ã€ « áì -  ­¥ ¡ë« ãáâ ­®¢«¥­
+goto End
+
+:WinNT
+set GSDLHOME=@gsdlhome@
+set GSDLOS=windows
+set PATH=%GSDLHOME%\bin\windows\perl\bin;%GSDLHOME%\bin\windows;%GSDLHOME%\bin\script;%PATH%
+goto Success
+
+:Win95
+if "%1" == "SetEnv" goto Win95Env
+REM We'll invoke a second copy of the command processor to make
+REM sure there's enough environment space
+COMMAND /E:2048 /K %0 SetEnv
+goto End
+
+:Win95Env
+set GSDLHOME=@gsdlhome@
+set GSDLOS=windows
+set PATH="%GSDLHOME%\bin\windows\perl\bin";"%GSDLHOME%\bin\windows";"%GSDLHOME%\bin\script";"%PATH%"
+
+:Success
+if "%GSDLLANG%" == "en" echo Your environment has successfully been set up to run Greenstone.
+if "%GSDLLANG%" == "en" echo Note that these settings will only have effect within this MS-DOS
+if "%GSDLLANG%" == "en" echo session. You will therefore need to rerun setup.bat if you want
+if "%GSDLLANG%" == "en" echo to run Greenstone programs from a different MS-DOS session.
+
+if "%GSDLLANG%" == "es" echo Su ambiente ha sido configurado para correr los programas Greenstone.
+if "%GSDLLANG%" == "es" echo Recuerde que estos ajustes £nicamente tendr n efecto dentro de esta sesi¢n
+if "%GSDLLANG%" == "es" echo MS-DOS. Por lo tanto deber  ejecutar nuevamente setup.bat si desea
+if "%GSDLLANG%" == "es" echo correr los programas de Greenstone desde una sesi¢n MS-DOS diferente.
+
+if "%GSDLLANG%" == "fr" echo Votre environnement a t configure avec succs pour excuter Greenstone
+if "%GSDLLANG%" == "fr" echo Notez que ces paramtrages n'auront d'effet que dans cette session MS-DOS.
+if "%GSDLLANG%" == "fr" echo Vous devrez par consquent rexcuter setup.bat si vous voulez faire
+if "%GSDLLANG%" == "fr" echo lancer des programmes Greenstone dans une autre session MS-DOS.
+
+if "%GSDLLANG%" == "ru" echo  è¥ ®ªàãŠ¥­š¥ ¡ë«® ãá¯¥è­® ­ áâà®¥­®, çâ®¡ë ãáâ ­®¢šâì Greenstone ¡à âšâ¥
+if "%GSDLLANG%" == "ru" echo ¢­š¬ ­š¥, çâ® íâš ­ §­ ç¥­šï ¡ã€ãâ â®«ìª® š¬¥âì íää¥ªâ ¢ ¯à¥€¥« å íâ®£® MS DOS
+if "%GSDLLANG%" == "ru" echo á¥áášï. ë ¡ã€¥â¥ ¯®íâ®¬ã €®«Š­ë ¯®¢â®à­® ã¯à ¢«ïâì setup.bat, ¥á«š ë å®âšâ¥
+if "%GSDLLANG%" == "ru" echo ã¯à ¢«ïâì ¯à®£à ¬¬ ¬š ¥«ñ­ëå š§¢¥àŠ¥­­ëå ¯®à®€ ®â à §«šç­®© á¥áášš MS DOS.
+
+:End
Index: /tags/greenstone-3_02-distribution/gs2build-extra/win32.mak
===================================================================
--- /tags/greenstone-3_02-distribution/gs2build-extra/win32.mak	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gs2build-extra/win32.mak	(revision 13928)
@@ -0,0 +1,97 @@
+###########################################################################
+#
+# win32 makefile -- gsdl
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999  The New Zealand Digital Library Project
+#
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+AR = lib
+CC = cl
+CPPFLAGS =
+
+GSDLHOME = $(MAKEDIR)
+USE_STLPORT = 0
+DLL = 0
+DLLDEBUG = 0
+
+MDEFINES = /f win32.mak
+COMPILE = $(CC) -c $(CPPFLAGS) $(DEFS) $(INCLUDES)
+
+SOURCES = 
+
+OBJECTS = 
+
+OTHERDIRS = packages\windows\gdbm\gdbm packages\windows\crypt\crypt lib 
+
+INSTALLDIRS = src\txt2db src\db2txt src\hashfile src\phind\generate
+
+MAKECMD = $(MAKE) $(MDEFINES) GSDLHOME="$(GSDLHOME)"
+!IF $(USE_STLPORT)
+MAKECMD = $(MAKECMD) USE_STLPORT=1
+!ENDIF
+!IF $(DLL)
+MAKECMD = $(MAKECMD) DLL=1
+!ENDIF
+!IF $(DLLDEBUG)
+MAKECMD = $(MAKECMD) DLLDEBUG=1
+!ENDIF
+
+all: win32.mak indexers $(OTHERDIRS) $(INSTALLDIRS)
+
+install: win32.mak indexers-install $(INSTALLDIRS)
+
+$(OTHERDIRS): FORCE
+	cd "$@"
+	$(MAKECMD)
+	cd "$(GSDLHOME)"
+
+$(INSTALLDIRS): FORCE
+	cd "$@"
+	$(MAKECMD)
+	$(MAKECMD) install
+	cd "$(GSDLHOME)"
+
+indexers: FORCE
+	cd "indexers"
+	call winMake.bat all
+	cd "$(GSDLHOME)"
+
+indexers-install:
+	cd indexers
+	call winMake.bat install
+	cd "$(GSDLHOME)"
+
+FORCE:
+
+clean: win32.mak 
+	cd packages\windows\gdbm\gdbm 
+	$(MAKECMD) clean
+	cd ..\..\..\..
+        cd packages\windows\crypt\crypt 
+	$(MAKECMD) clean
+	cd ..\..\..\..
+	cd indexers
+	call winMake.bat clean
+	cd ..
+	cd lib
+	$(MAKECMD) clean
+	 cd ..
Index: /tags/greenstone-3_02-distribution/gsdl/WIN32cfg.h
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/WIN32cfg.h	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/WIN32cfg.h	(revision 13928)
@@ -0,0 +1,169 @@
+/* config.h.  Generated automatically by configure.  */
+/* config.h.in.  Generated automatically from configure.in by autoheader.  */
+
+/* Define if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+/* #undef _ALL_SOURCE */
+#endif
+
+/* Define if using alloca.c.  */
+/* #undef C_ALLOCA */
+
+/* Define to empty if the keyword does not work.  */
+/* #undef const */
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+   This function is required for alloca.c support on those systems.  */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define if you have alloca, as a function or macro.  */
+#define HAVE_ALLOCA 1
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix).  */
+/* #define HAVE_ALLOCA_H 1 */
+
+/* Define if you don't have vprintf but do have _doprnt.  */
+/* #undef HAVE_DOPRNT */
+
+/* Define if you have the vprintf function.  */
+#define HAVE_VPRINTF 1
+
+/* Define if on MINIX.  */
+/* #undef _MINIX */
+
+/* Define to `long' if <sys/types.h> doesn't define.  */
+/* #undef off_t */
+
+/* Define if the system does not provide POSIX.1 features except
+   with this defined.  */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define if you need to in order for stat and other things to work.  */
+/* #undef _POSIX_SOURCE */
+
+/* Define as the return type of signal handlers (int or void).  */
+#define RETSIGTYPE void
+
+/* Define to `unsigned' if <sys/types.h> doesn't define.  */
+/* #undef size_t */
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown
+ */
+/* #undef STACK_DIRECTION */
+
+/* Define if you have the ANSI C header files.  */
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both <sys/time.h> and <time.h>.  */
+/* #define TIME_WITH_SYS_TIME 1 */
+
+/* Define if your <sys/time.h> declares struct tm.  */
+/* #undef TM_IN_SYS_TIME */
+
+/* Define to the name of the distribution.  */
+#define PACKAGE "mg"
+
+/* Define to the version of the distribution.  */
+#define VERSION "1.2"
+
+/* Define to 1 if you have the valloc function.  */
+/* #define HAVE_VALLOC 1 */
+
+/* Define to 1 if ANSI function prototypes are usable.  */
+#define PROTOTYPES 1
+
+ 
+/* Define to 1 for better use of the debugging malloc library.  See
+   site ftp.antaire.com in antaire/src, file dmalloc/dmalloc.tar.gz.  */
+/* #undef WITH_DMALLOC */
+
+ 
+/* Define to 1 if GNU regex should be used instead of GNU rx.  */
+/* #undef WITH_REGEX */
+
+/* Some braindead header files do not have the requ'd function declarations */
+#define HAVE_FGETC_DECL 1
+#define HAVE_FREAD_DECL 1
+
+/* See if have this field in the prstatus_t structure */
+/* It stores the size of the process heap */
+/* #define HAVE_PR_BRKSIZE 1 */
+
+/* Define if you have the ftime function.  */
+/* #undef HAVE_FTIME */
+
+/* Define if you have the getpagesize function.  */
+/* #undef HAVE_GETPAGESIZE */
+
+/* Define if you have the getrusage function.  */
+/* #undef HAVE_GETRUSAGE */
+
+/* Define if you have the mallinfo function.  */
+/* #undef HAVE_MALLINFO */
+
+/* Define if you have the select function.  */
+#define HAVE_SELECT 1
+
+/* Define if you have the setbuffer function.  */
+/* #undef HAVE_SETBUFFER */
+
+/* Define if you have the strerror function.  */
+#define HAVE_STRERROR 1
+
+/* Define if you have the strftime function.  */
+#define HAVE_STRFTIME 1
+
+/* Define if you have the strstr function.  */
+#define HAVE_STRSTR 1
+
+/* Define if you have the strtol function.  */
+#define HAVE_STRTOL 1
+
+/* Define if you have the times function.  */
+/* #define HAVE_TIMES 1 */
+
+/* Define if you have the valloc function.  */
+/* #define HAVE_VALLOC 1 */
+
+/* Define if you have the <dirent.h> header file.  */
+/* #define HAVE_DIRENT_H 1 */
+
+/* Define if you have the <fcntl.h> header file.  */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <limits.h> header file.  */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <memory.h> header file.  */
+#define HAVE_MEMORY_H 1
+
+/* Define if you have the <ndir.h> header file.  */
+/* #undef HAVE_NDIR_H */
+
+/* Define if you have the <string.h> header file.  */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <sys/dir.h> header file.  */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define if you have the <sys/ndir.h> header file.  */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define if you have the <sys/procfs.h> header file.  */
+/* #define HAVE_SYS_PROCFS_H 1 */
+
+/* Define if you have the <sys/time.h> header file.  */
+/* #define HAVE_SYS_TIME_H 1 */
+
+/* Define if you have the <unistd.h> header file.  */
+/* #define HAVE_UNISTD_H 1 */
+
+/* Define if you have the m library (-lm).  */
+#define HAVE_LIBM 1
Index: /tags/greenstone-3_02-distribution/gsdl/acconfig.h
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/acconfig.h	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/acconfig.h	(revision 13928)
@@ -0,0 +1,50 @@
+/* Special definitions for mg, processed by autoheader.
+   Created by [TS:Aug/95] 
+   by grepping for AC_DEFINE on configure.in and using the appropriate defs 
+   of acconfig.h used by GNU tar.
+*/
+
+/* Define to the name of the distribution.  */
+#undef PACKAGE
+
+/* Define to the version of the distribution.  */
+#undef VERSION
+
+/* Define if `union wait' is the type of the first arg to wait functions.  */
+#undef HAVE_UNION_WAIT
+
+/* Define to 1 if you have the valloc function.  */
+#undef HAVE_VALLOC
+
+/* Define to 1 if ANSI function prototypes are usable.  */
+#undef PROTOTYPES
+ 
+/* Define to 1 for better use of the debugging malloc library.  See
+   site ftp.antaire.com in antaire/src, file dmalloc/dmalloc.tar.gz.  */
+#undef WITH_DMALLOC
+ 
+/* Define to 1 if GNU regex should be used instead of GNU rx.  */
+#undef WITH_REGEX
+
+/* Some braindead header files do not have the requ'd function declarations */
+#undef HAVE_FGETC_DECL
+#undef HAVE_FREAD_DECL
+
+/* See if have this field in the prstatus_t structure */
+/* It stores the size of the process heap */
+#undef HAVE_PR_BRKSIZE
+
+/* Define FASTCGI if needsbe */
+#undef USE_FASTCGI
+
+/* Define USE_CORBA if needsbe */
+#undef USE_CORBA
+
+/* Define MICO_DIR if needsbe */
+#undef MICO_DIR
+
+/* Define MICO_VERSION if required */
+#undef MICO_VERSION
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl/aclocal.m4
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/aclocal.m4	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/aclocal.m4	(revision 13928)
@@ -0,0 +1,140 @@
+# Local additions to Autoconf macros.
+# Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
+# François Pinard <pinard@iro.umontreal.ca>, 1992.
+
+# [TS:Aug/95] - chopped out the NLS stuff which I don't support
+
+## ------------------------------- ##
+## Check for function prototypes.  ##
+## ------------------------------- ##
+
+AC_DEFUN(fp_C_PROTOTYPES,
+[AC_REQUIRE([fp_PROG_CC_STDC])
+AC_MSG_CHECKING([for function prototypes])
+if test "$ac_cv_prog_cc_stdc" != no; then
+  AC_MSG_RESULT(yes)
+  AC_DEFINE(PROTOTYPES)
+  U= ANSI2KNR=
+else
+  AC_MSG_RESULT(no)
+  U=_ ANSI2KNR=ansi2knr
+fi
+AC_SUBST(U)dnl
+AC_SUBST(ANSI2KNR)dnl
+])
+
+## ----------------------------------------- ##
+## ANSIfy the C compiler whenever possible.  ##
+## ----------------------------------------- ##
+
+# @defmac AC_PROG_CC_STDC
+# @maindex PROG_CC_STDC
+# @ovindex CC
+# If the C compiler in not in ANSI C mode by default, try to add an option
+# to output variable @code{CC} to make it so.  This macro tries various
+# options that select ANSI C on some system or another.  It considers the
+# compiler to be in ANSI C mode if it defines @code{__STDC__} to 1 and
+# handles function prototypes correctly.
+#
+# If you use this macro, you should check after calling it whether the C
+# compiler has been set to accept ANSI C; if not, the shell variable
+# @code{ac_cv_prog_cc_stdc} is set to @samp{no}.  If you wrote your source
+# code in ANSI C, you can make an un-ANSIfied copy of it by using the
+# program @code{ansi2knr}, which comes with Ghostscript.
+# @end defmac
+
+AC_DEFUN(fp_PROG_CC_STDC,
+[AC_MSG_CHECKING(for ${CC-cc} option to accept ANSI C)
+AC_CACHE_VAL(ac_cv_prog_cc_stdc,
+[ac_cv_prog_cc_stdc=no
+ac_save_CFLAGS="$CFLAGS"
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX			-qlanglvl=ansi
+# Ultrix and OSF/1	-std1
+# HP-UX			-Aa -D_HPUX_SOURCE
+# SVR4			-Xc
+for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" -Xc
+do
+  CFLAGS="$ac_save_CFLAGS $ac_arg"
+  AC_TRY_COMPILE(
+[#if !defined(__STDC__) || __STDC__ != 1
+choke me
+#endif	
+], [int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};],
+[ac_cv_prog_cc_stdc="$ac_arg"; break])
+done
+CFLAGS="$ac_save_CFLAGS"
+])
+AC_MSG_RESULT($ac_cv_prog_cc_stdc)
+case "x$ac_cv_prog_cc_stdc" in
+  x|xno) ;;
+  *) CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+])
+
+## --------------------------------------------------------- ##
+## Use AC_PROG_INSTALL, supplementing it with INSTALL_SCRIPT ##
+## substitution.					     ##
+## --------------------------------------------------------- ##
+
+AC_DEFUN(fp_PROG_INSTALL,
+[AC_PROG_INSTALL
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL} -m 755'
+AC_SUBST(INSTALL_SCRIPT)dnl
+])
+
+## ----------------------------------- ##
+## Check if --with-dmalloc was given.  ##
+## ----------------------------------- ##
+
+# I just checked, and GNU rx seems to work fine with a slightly
+# modified GNU m4.  So, I put out the test below in my aclocal.m4,
+# and will try to use it in my things.  The idea is to distribute
+# rx.[hc] and regex.[hc] together, for a while.  The WITH_REGEX symbol
+# (which should also be documented in acconfig.h) is used to decide
+# which of regex.h or rx.h should be included in the application.
+#
+# If `./configure --with-regex' is given, the package will use
+# the older regex.  Else, a check is made to see if rx is already
+# installed, as with newer Linux'es.  If not found, the package will
+# use the rx from the distribution.  If found, the package will use
+# the system's rx which, on Linux at least, will result in a smaller
+# executable file.
+
+AC_DEFUN(fp_WITH_DMALLOC,
+[AC_MSG_CHECKING(if malloc debugging is wanted)
+AC_ARG_WITH(dmalloc,
+[  --with-dmalloc          use dmalloc, as in
+                          ftp://ftp.letters.com/src/dmalloc/dmalloc.tar.gz],
+[if test "$withval" = yes; then
+  AC_MSG_RESULT(yes)
+  AC_DEFINE(WITH_DMALLOC)
+  LIBS="$LIBS -ldmalloc"
+  LDFLAGS="$LDFLAGS -g"
+else
+  AC_MSG_RESULT(no)
+fi], [AC_MSG_RESULT(no)])
+])
+
+## --------------------------------- ##
+## Check if --with-regex was given.  ##
+## --------------------------------- ##
+
+AC_DEFUN(fp_WITH_REGEX,
+[AC_MSG_CHECKING(which of rx or regex is wanted)
+AC_ARG_WITH(regex,
+[  --with-regex            use older regex in lieu of GNU rx for matching],
+[if test "$withval" = yes; then
+  ac_with_regex=1
+  AC_MSG_RESULT(regex)
+  AC_DEFINE(WITH_REGEX)
+  AC_LIBOBJ([regex])
+fi])
+if test -z "$ac_with_regex"; then
+  AC_MSG_RESULT(rx)
+  AC_CHECK_FUNC(re_rx_search, , [AC_LIBOBJ([rx])])
+fi
+])
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/anonymiselog.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/anonymiselog.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/anonymiselog.pl	(revision 13928)
@@ -0,0 +1,120 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# anonymiselog.pl -- anonymise a log file by MD5 hashing all IP addresses
+#
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+use MD5;
+
+
+sub main
+{
+    # Get the name of the log file to process
+    local $logfilename = shift(@_);
+
+    # Check that the necessary arguments were supplied
+    if (!$logfilename) {
+	print STDERR "Usage: anonymiselog.pl <logfile-name>\n";
+	die "Error: Required argument missing.\n";
+    }
+
+    # Open the log file
+    open(LOG_FILE, "<$logfilename") or die "Error: Could not open log file $logfilename.\n";
+
+    # Open the output file
+    local $outfilename = $logfilename . ".anon";
+    open(OUT_FILE, ">$outfilename") or die "Error: Could not write file $outfilename.\n"; 
+
+    # Create a new MD5 (RSA Data Security Inc. MD5 Message Digest) object
+    local $md5 = new MD5;
+
+    # Process the log, one line at a time
+    local $entry = "";
+    while (<LOG_FILE>) {
+	local $line = $_;
+	# print "Line: $line";
+
+	# If this line starts a new entry, process the previous one
+	if ($line =~ /^\//) {
+	    print OUT_FILE &anonymise_log_entry($entry);
+	    $entry = "";
+	}
+
+	# Remove trailing whitespace, and skip blank lines
+	$line =~ s/(\s*)$//;
+	next if ($line =~ /^$/);
+
+	$entry = $entry . $line;
+    }
+
+    # Process the last entry
+    print OUT_FILE &anonymise_log_entry($entry);
+
+    # All done
+    close(LOG_FILE);
+    close(OUT_FILE);
+}
+
+
+sub anonymise_log_entry
+{
+    local $entry = shift(@_);
+    return "" if ($entry eq "");
+
+    # Parse the IP address from the entry
+    $entry =~ /^\S+\s((\w|-|\.)+)\s\[/;
+    if (!defined($1)) {
+	print STDERR "Could not extract IP address from entry: $entry\n";
+	return "";
+    }
+
+    # Casefold the IP address, hash using MD5, and take the last 16 characters
+    local $ipaddress = $1;
+    $ipaddress =~ tr/A-Z/a-z/;
+    local $hashedaddress = substr($md5->hexhash($ipaddress), -16);
+
+    # Replace the IP address with the hashed value
+    $entry =~ s/$ipaddress/$hashedaddress/ig;
+
+    # Parse the Greenstone user identifier (z variable) from the entry
+    $entry =~ /\sz=((\w|-|\.)+)/;
+    if (!defined($1)) {
+	print STDERR "No z variable in entry: $entry\n";
+	return "";
+    }
+
+    # Casefold the Greenstone user ID, hash using MD5, and take the last 16 characters
+    local $gsuserid = $1;
+    $gsuserid =~ tr/A-Z/a-z/;
+    local $hasheduserid = substr($md5->hexhash($gsuserid), -16);
+
+    # Replace the Greenstone user ID with the hashed value
+    $entry =~ s/$gsuserid/$hasheduserid/ig;
+    return $entry . "\n";
+}
+
+
+&main(@ARGV);
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/build
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/build	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/build	(revision 13928)
@@ -0,0 +1,663 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# build --
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 2000 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+# This perl script may be called directly or by running build.bat on
+# windows (build.bat is in bin\windows)
+
+# Note that this script has grown over time and now has many options for
+# use when called from within the collector. If it appears to
+# over-complicate things a little, that's why.
+
+package build;
+
+use FileHandle;
+use File::Copy;
+
+BEGIN {
+
+    die "GSDLHOME not set - did you remember to source setup.bash (unix) or " .
+	"run setup.bat (windows)?\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set - did you remember to source setup.bash (unix) or " .
+	"run setup.bat (windows)?\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+
+    STDOUT->autoflush(1);
+    STDERR->autoflush(1);
+}
+
+use lib qq($ENV{'GSDLHOME'}/perllib/cpan);
+use Mail::Sendmail;
+use parsargv;
+use util;
+use cfgread;
+
+# set up path - this allows for paths not to be supplied to system calls
+# and overcomes problems when GSDLHOME contains spaces (double quoting
+# the call doesn't work on win2k and probably other variants of winnt)
+my $path_separator = ":";
+$path_separator = ";" if $ENV{'GSDLOS'} =~ /^windows$/;
+$ENV{'PATH'} = &util::filename_cat($ENV{'GSDLHOME'}, "bin", $ENV{'GSDLOS'}) .
+    $path_separator . &util::filename_cat($ENV{'GSDLHOME'}, "bin", "script") .
+    $path_separator . $ENV{'PATH'};
+
+&parse_args (\@ARGV);
+
+my ($collection) = @ARGV;
+
+if (!defined $collection || $collection !~ /\w/) {
+    print STDERR "You must specify a collection to build\n";
+    &print_usage();
+    die "\n";
+}
+
+if ($optionfile =~ /\w/) {
+    open (OPTIONS, $optionfile) || die "Couldn't open $optionfile\n";
+    my $line = [];
+    my $options = [];
+    while (defined ($line = &cfgread::read_cfg_line ('build::OPTIONS'))) {
+	push (@$options, @$line);
+    }
+    close OPTIONS;
+    &parse_args ($options);
+}
+
+if ($maxdocs == -1) {
+    $maxdocs = "";
+} else {
+    $maxdocs = "-maxdocs $maxdocs";
+}
+
+my $cdir = $collectdir;
+$cdir = &util::filename_cat ($ENV{'GSDLHOME'}, "collect") unless $collectdir =~ /\w/;
+my $importdir = &util::filename_cat ($cdir, $collection, "import");
+my $archivedir = &util::filename_cat ($cdir, $collection, "archives");
+my $buildingdir = &util::filename_cat ($cdir, $collection, "building");
+my $indexdir = &util::filename_cat ($cdir, $collection, "index");
+my $bindir = &util::filename_cat ($ENV{'GSDLHOME'}, "bin");
+
+my $use_out = 0;
+my $outfile = $out;
+if ($out !~ /^(STDERR|STDOUT)$/i) {
+    open (OUT, ">$out") || die "Couldn't open output file $out\n";
+    $out = "OUT";
+    
+    # delete any existing .final file
+    &util::rm ("$outfile.final") if -e "$outfile.final";
+
+    $use_out = 1;
+}
+$out->autoflush(1);
+
+# delete any .kill file left laying around from a previously aborted build
+if (-e &util::filename_cat ($cdir, $collection, ".kill")) {
+    &util::rm (&util::filename_cat ($cdir, $collection, ".kill"));
+}
+
+# get maintainer email address from main.cfg
+my $maintainer = "NULL";
+my $main_cfg = &util::filename_cat ($ENV{'GSDLHOME'}, "etc", "main.cfg");
+my $cfgdata = &cfgread::read_cfg_file ($main_cfg, "maintainer");
+if (defined $cfgdata->{'maintainer'} && $cfgdata->{'maintainer'} =~ /\w/) {
+    $maintainer = $cfgdata->{'maintainer'};
+}
+# if maintainer is "NULL" email_events should be disabled
+if ($maintainer =~ /^NULL$/i) {
+    $email_events = "";
+}
+
+&main();
+
+if ($use_out) {
+    close OUT;
+
+    # if we've created a build log we'll copy it to the collection's etc
+    # directory
+    my ($etcdir);
+    if ($dontinstall) {
+	$etcdir = &util::filename_cat($collectdir, "etc", "build.log");
+    } else {
+	$etcdir = &util::filename_cat($ENV{'GSDLHOME'}, "collect", $collection, "etc", "build.log");
+    }
+    
+    &util::cp($outfile, $etcdir);
+}
+
+sub print_usage {
+    print STDOUT "\n";
+    print STDOUT "build: Builds a Greenstone collection (i.e. runs import.pl and buildcol.pl\n";
+    print STDOUT "       then copies the resulting indexes to the correct place).\n\n";
+    print STDOUT "  usage: $0 [options] collection-name\n\n";
+    print STDOUT "  options:\n";
+    print STDOUT "   -optionfile file        Get options from file, useful on systems where\n";
+    print STDOUT "                           long command lines may cause problems\n";
+    print STDOUT "   -indextype mg|mgpp|lucene \n";
+    print STDERR "                           Specify the type of indexer used in this collection\n";
+    print STDERR "                           If -append is used then -indextype is needed to \n";
+    print STDERR "                           determine how to run buildcol.pl as well as update\n";
+    print STDERR "                           'building' and 'index' according.\n";
+    print STDOUT "   -append                 Add new files to existing collection\n";
+    print STDOUT "   -manifest               Use manifest.xml file to determine which files to process.\n";
+    print STDOUT "   -remove_archives        Remove archives directory after successfully\n";
+    print STDOUT "                           building the collection.\n";
+    print STDOUT "   -remove_import          Remove import directory after successfully\n";
+    print STDOUT "                           importing the collection.\n";
+    print STDOUT "   -buildtype build|import If 'build' attempt to build directly\n";
+    print STDOUT "                           from archives directory (bypassing import\n";
+    print STDOUT "                           stage). Defaults to 'import'\n";
+    print STDOUT "   -maxdocs number         Maximum number of documents to build\n";
+    print STDOUT "   -download directory     Directory (or file) to get import documents from.\n";
+    print STDOUT "                           There may be multiple download directories and they\n";
+    print STDOUT "                           may be of type http://, ftp://, or file://\n";
+    print STDOUT "                           Note that any existing import directory will be\n";
+    print STDOUT "                           deleted to make way for the downloaded data if\n";
+    print STDOUT "                           a -download option is supplied\n";
+    print STDOUT "   -collectdir directory   Collection directory (defaults to " .
+	&util::filename_cat ($ENV{'GSDLHOME'}, "collect") . ")\n";
+    print STDOUT "   -dontinstall            Only applicable if -collectdir is set to something\n";
+    print STDOUT "                           other than the default. -dontinstall will suppress\n";
+    print STDOUT "                           the default behaviour which is to install the\n";
+    print STDOUT "                           collection to the gsdl/collect directory once it has\n";
+    print STDOUT "                           been built.\n";
+    print STDOUT "   -save_archives          Create a copy of the existing archives directory\n";
+    print STDOUT "                           called archives.org\n";
+    print STDOUT "   -out                    Filename or handle to print output status to.\n";
+    print STDOUT "                           The default is STDERR\n";
+    print STDOUT "   -statsfile name         Filename or handle to print import statistics to.\n";
+    print STDOUT "                           The default is STDERR\n";
+    print STDOUT "   -make_writable          If set build will make the collection and any\n";
+    print STDOUT "                           temporary files it created globally writable after\n";
+    print STDOUT "                           it finishes\n";
+    print STDOUT "   -log_events             Log important events (collection built successfully\n";
+    print STDOUT "                           etc.) to event_log_file\n";
+    print STDOUT "   -event_log_file file    File to append important events to (defaults to\n";
+    print STDOUT "                           " . &util::filename_cat ($ENV{'GSDLHOME'}, "etc", "events.txt") . "\n";
+    print STDOUT "   -email_events addr      Comma separated list of email addresses to mail\n";
+    print STDOUT "                           details of important collection building events\n";
+    print STDOUT "   -mail_server server     The outgoing (SMTP) mail server to be used by\n";
+    print STDOUT "                           email_events. email_events will be disabled if\n";
+    print STDOUT "                           mail_server isn't set\n";
+    print STDOUT "   -event_header file      File containing a header to go on any event\n";
+    print STDOUT "                           messages. If not specified build will create a\n";
+    print STDOUT "                           generic header\n\n";
+    print STDOUT "  [Type \"build | more\" if this help text scrolled off your screen]";
+    print STDOUT "\n" unless $ENV{'GSDLOS'} =~ /^windows$/i;
+}
+
+sub main {
+
+    if ($save_archives && -d $archivedir) {
+	print $out "caching original archives to ${archivedir}.org\n";
+	&util::cp_r ($archivedir, "${archivedir}.org");
+    }
+
+    # do the download thing if we have any -download options
+    if (scalar (@download)) {
+	# remove any existing import data
+	if (&has_content ($importdir)) {
+	    print $out "build: WARNING: removing contents of $importdir\n";
+	    &util::rm_r ($importdir);
+	}
+	
+	foreach $download_dir (@download) {
+
+	    # remove any leading or trailing whitespace from filenames (just in case)
+	    $download_dir =~ s/^\s+//;
+	    $download_dir =~ s/\s+$//;
+	    
+	    if ($download_dir =~ /^(http|ftp):\/\//) {
+		# use wget to mirror http or ftp urls
+		# options used are:
+		#  -P = the directory to download documents to
+		#  -np = don't ascend to parent directories. this means that only documents
+		#        that live in the same directory or below on the same server as
+		#        the given url will be downloaded
+		#  -nv = not too verbose
+		#  -r = recursively mirror
+		#  -N = use time-stamping to see if an up-to-date local copy of each 
+		#       file already exists. this may be useful if wget fails and 
+		#       is restarted
+		#  -l inf = infinite recursion depth
+		#  -R "*\?*" = don't download cgi based urls
+		#  -o = the output file to write download status to (only used if the -out
+		#       option was given to build)
+
+		my $download_cmd = "perl -S gsWget.pl -P \"$importdir\" -np -nv";
+		$download_cmd .= " -r -N -l inf -R \"*\\?*\"";
+		$download_cmd .= " -o \"$outfile.download\"" if $use_out;
+		$download_cmd .= " \"$download_dir\"";
+		system ($download_cmd);
+
+		# note that wget obeys the robot rules. this means that it will have
+		# downloaded a robots.txt file if one was present. since it's unlikely 
+		# anyone really wants to include it in a collection we'll delete it.
+		# robots.txt shouldn't be more than two directories deep (I think it will 
+		# always be exactly two deep but will look for it in the top directory too)
+		# so that's as far as we'll go looking for it.
+		if (opendir (DIR, $importdir)) {
+		    my @files = readdir DIR;
+		    closedir DIR;
+		    foreach my $file (@files) {
+			next if $file =~ /^\.\.?$/;
+			if ($file =~ /^robots.txt$/i) {
+			    &util::rm (&util::filename_cat ($importdir, $file));
+			    last;
+			} else {
+			    $file = &util::filename_cat ($importdir, $file);
+			    if (-d $file) {
+				if (opendir (DIR, $file)) {
+				    my @files2 = readdir DIR;
+				    closedir DIR;
+				    foreach my $file2 (@files2) {
+					if ($file2 =~ /^robots.txt$/i) {
+					    &util::rm (&util::filename_cat ($file, $file2));
+					    last;
+					}
+				    }
+				}
+			    }
+			}
+		    }
+		}
+
+		# if using output directory append the file download output to it
+		&append_file ($out, "$outfile.download");
+		
+	    } else {
+		# we assume anything not beginning with http:// or ftp://
+		# is a file or directory on the local file system.
+		$download_dir =~ s/^file:(\/\/)?//;
+		$download_dir =~ s/^\s+//; # may be whitespace between "file://" and the rest
+		
+		if (-e $download_dir) {
+		    # copy download_dir and all it contains to the import directory
+		    my $download_cmd = "perl -S filecopy.pl";
+		    $download_cmd .= " -collectdir \"$collectdir\"" if $collectdir =~ /\w/;
+		    $download_cmd .= " -out \"$outfile.download\"" if $use_out;
+		    $download_cmd .= " \"" . $download_dir . "\" " . $collection;
+		    system ($download_cmd);
+		    # if using output directory append the file download output to it
+		    &append_file ($out, "$outfile.download");
+		} else {
+		    print $out "WARNING: '$download_dir' does not exist\n";
+		}
+	    }
+	}
+    }
+
+    if (-e &util::filename_cat ($archivedir, "archives.inf")) {
+	if (&has_content ($importdir)) {
+	    if ($buildtype eq "build") {
+		&gsdl_build();
+	    } else {
+		&gsdl_import();
+		&gsdl_build();
+	    }
+	} else {
+	    # there are archives but no import, build directly from archives
+	    print $out "build: no import material was found, building directly\n";
+	    print $out "       from archives\n";
+	    &gsdl_build();
+	}
+    } else {
+	if (&has_content ($importdir)) {
+	    if ($buildtype eq "build") {
+		print $out "build: can't build directly from archives as no\n";
+		print $out "       imported archives exist (did you forget to\n";
+		print $out "       move the contents of $collection/import to\n";
+		print $out "       collection/archives?)\n";
+	    }
+	    &gsdl_import();
+	    if (&has_content ($archivedir, "^archives.inf\$")) {
+		&gsdl_build();
+	    } else {
+		my $msg = "build: ERROR: The collection could not be built as no\n";
+		$msg .=   "       valid data was imported. Are at least some of\n";
+		$msg .=   "       the files you imported in a format that can be\n";
+		$msg .=   "       processed by the specified Greenstone plugins?\n";
+		print $out $msg;
+		&log_event ($msg);
+		&final_out (6) if $use_out;
+		die "\n";
+	    }
+	} else {
+	    # no import or archives
+	    my $msg = "build: ERROR: The collection could not be built as it contains no data.\n";
+	    print $out $msg;
+	    &log_event ($msg);
+	    &final_out (1) if $use_out;
+	    die "\n";
+	}
+    }
+
+    if ($collectdir ne "" && !$dontinstall) {
+	my $install_collectdir = &util::filename_cat ($ENV{'GSDLHOME'}, "collect");
+	if (!&util::filenames_equal ($collectdir, $install_collectdir)) {
+	    
+	    # install collection to gsdl/collect
+	    print $out "installing the $collection collection\n";
+	    my $newdir = &util::filename_cat ($install_collectdir, $collection);
+	    my $olddir = &util::filename_cat ($collectdir, $collection);
+	    if (-d $newdir) {
+		my $msg = "build: Could not install collection as $newdir\n" .
+		    "       already exists. Collection will remain at\n$olddir\n";
+
+		print $out $msg;
+		&log_event ($msg);
+		&final_out (4) if $use_out;
+		die "\n";
+	    }
+	    if (!&File::Copy::move ($olddir, $newdir)) {
+		my $msg = "build: Failed to install collection to $newdir\n" .
+		    "       Collection will remain at $olddir\n";
+		print $out $msg;
+		&log_event ($msg);
+		&final_out (5) if $use_out;
+		die "\n";
+	    }
+	}
+    }
+
+    &log_event ("The $collection collection was built successfully\n");
+    &final_out (0) if $use_out;
+}
+
+sub gsdl_import {
+
+    print $out "importing the $collection collection\n\n";
+
+    my $import_cmd = "perl -S import.pl";
+    $import_cmd .= " -out \"$outfile.import\"" if $use_out;
+    if ($append) {
+	$import_cmd .= " -keepold";
+	if (not $manifest) {
+	    # if we are appending, with no manifest, assume incremental
+	    $import_cmd .= " -incremental";
+	}
+    } else {
+	$import_cmd .= " -removeold";
+    }
+
+    $import_cmd .= " -manifest manifest.xml" if ($manifest);
+    $import_cmd .= " -collectdir \"$collectdir\"" if $collectdir =~ /\w/;
+    $import_cmd .= " -statsfile \"$statsfile\"" if $statsfile =~ /\w/;
+    $import_cmd .= " $maxdocs $collection";
+
+    system ($import_cmd);
+    # if using output directory append the import output to it
+    &append_file ($out, "$outfile.import");
+
+    if (-e &util::filename_cat ($archivedir, "archives.inf")) {
+	print $out "$collection collection imported successfully\n\n";
+	if ($remove_import) {
+	    print $out "removing import directory ($importdir)\n";
+	    &util::rm_r ($importdir);
+	}
+    } else {
+	my $msg = "build: ERROR: import.pl failed\n";
+	print $out "\n$msg";
+	&log_event ($msg);
+	&final_out (2) if $use_out;
+	die "\n";
+    }
+}
+
+sub gsdl_build {
+
+    print $out "building the $collection collection\n\n";
+
+    my $build_cmd = "perl -S buildcol.pl";
+
+    my $removeold = 1;
+    if ($append) {
+	if ($indextype eq "lucene") {
+	    $build_cmd .= " -keepold -incremental -builddir $indexdir";
+	    $removeold = 0;
+	}
+	else {
+	    $build_cmd .= " -removeold";
+	}
+    }
+    else {
+	$build_cmd .= " -removeold";
+    }
+
+    $build_cmd .= " -out \"$outfile.build\"" if $use_out;
+    $build_cmd .= " -collectdir \"$collectdir\"" if $collectdir =~ /\w/;
+    $build_cmd .= " $maxdocs $collection";
+    system ($build_cmd);
+    # if using output directory append the buildcol output to it
+    &append_file ($out, "$outfile.build");
+
+    if (($removeold && (-e &util::filename_cat ($buildingdir, "text", "$collection.ldb") || -e &util::filename_cat ($buildingdir, "text", "$collection.bdb"))) ||
+	($removeold == 0 && (-e &util::filename_cat ($indexdir, "text", "$collection.ldb") || -e &util::filename_cat ($indexdir, "text", "$collection.bdb")))) {
+	print $out "$collection collection built successfully\n\n";
+	if ($remove_archives) {
+	    print $out "removing archives directory ($archivedir)\n";
+	    &util::rm_r ($archivedir);
+	}
+    } else {
+	my $msg = "build: ERROR: buildcol.pl failed\n";
+	print $out "\n$msg";
+	&log_event ($msg);
+	&final_out (3) if $use_out;
+	die "\n";
+    }
+
+    if ($removeold) {
+	# replace old indexes with new ones
+	if (&has_content ($indexdir)) {
+	    print $out "removing old indexes\n";
+	    &util::rm_r ($indexdir);
+	}
+	rmdir ($indexdir) if -d $indexdir;
+	&File::Copy::move ($buildingdir, $indexdir);
+    }
+    else {
+	# Do nothing. We have built into index dir rather than building dir
+    }
+
+    # remove the cached archives
+    if ($save_archives && -d "${archivedir}.org") {
+	&util::rm_r ("${archivedir}.org");
+    }
+}
+
+# return 1 if $dir directory contains any files or sub-directories (other
+# than those specified in the $ignore regular expression)
+sub has_content {
+    my ($dir, $ignore) = @_;
+
+    if (!-d $dir) {return 0;}
+    
+    opendir (DIR, $dir) || return 0;
+    my @files = readdir DIR;
+    closedir DIR;
+    
+    foreach my $file (@files) {
+	if ($file !~ /^\.{1,2}$/) {
+	    return 1 unless (defined $ignore && $file =~ /$ignore/);
+	}
+    }
+    return 0;
+}
+
+sub append_file {
+    my ($handle, $file) = @_;
+
+    open (FILE, $file) || return;
+    undef $/;
+    print $handle <FILE>;
+    $/ = "\n";
+    close FILE;
+    &util::rm ($file);
+}
+
+# creates a file called $outfile.final and writes an output code to it.
+# An output code of 0 specifies that there was no error
+sub final_out {
+    my ($exit_code) = @_;
+
+    if ($use_out && (!-e "$outfile.final")) {
+
+	if (open (FINAL, ">$outfile.final")) {
+	    print FINAL $exit_code;
+	    close FINAL;
+	}
+    }
+}
+
+sub log_event {
+    my ($msg) = @_;
+
+    return unless ($log_events || $email_events);
+
+    # get the event header
+    my $eheader = "[Build Event]\n";
+    $eheader .= "Date: " . scalar localtime() . "\n";
+    if ($event_header ne "" && open (HEADER, $event_header)) {
+	undef $/;
+	$eheader .= <HEADER>;
+	$/ = "\n";
+	close HEADER;
+    } else {
+	$eheader .= "Collection: $collection\n";
+	$eheader .= "GSDLHOME: $ENV{'GSDLHOME'}\n";
+	$eheader .= "Build Location: $collectdir\n";
+    }
+    
+    if ($log_events) {
+	my $fail = 0;
+	# append the event to the event log file
+	if ($event_log_file eq "" || !open (LOG, ">>$event_log_file")) {
+	    # log file defaults to $GSDLHOME/etc/events.txt
+	    $event_log_file = &util::filename_cat ($ENV{'GSDLHOME'}, "etc", "events.txt");
+	    if (!open (LOG, ">>$event_log_file")) {
+		print $out "build: ERROR: Couldn't open event log file $event_log_file\n";
+		$fail = 1;
+	    }
+	}
+	if (!$fail) {
+	    print LOG $eheader;
+	    print LOG $msg;
+	    print LOG "\n";
+	    close LOG;
+	}
+    }
+    
+    if ($email_events) {
+	# if mail_server isn't set email_events does nothing
+	if ($mail_server eq "") {
+	    print $out "build: WARNING: mail_server was not set - email_events option was ignored\n";
+	    return;
+	}
+	
+	my %mail = ('SMTP' => $mail_server, 
+		    'To' => $email_events,
+		    'From' => $maintainer,
+		    'Subject' => 'Greenstone Build Event'
+		    );
+	$mail{'Message'} = $eheader . $msg;
+	
+	if (!sendmail %mail) {
+	    print $out "build: ERROR sending mail to $email_events\n";
+	    print $out "'$Mail::Sendmail::error'\n";
+	}
+    }
+}
+
+
+sub parse_args {
+    my ($argref) = @_;
+
+    if (!parsargv::parse($argref, 
+			 'optionfile/.*/', \$optionfile,
+			 'indextype/^(mg|mgpp|lucene)$/mg', \$indextype,
+			 'append', \$append,
+			 'manifest', \$manifest,
+			 'remove_archives', \$remove_archives,
+			 'remove_import', \$remove_import,
+			 'buildtype/^(build|import)$/import', \$buildtype,
+			 'maxdocs/^\-?\d+/-1', \$maxdocs,
+			 'download/.+', \@download,
+			 'collectdir/.*/', \$collectdir,
+			 'dontinstall', \$dontinstall,
+			 'save_archives', \$save_archives,
+			 'out/.*/STDERR', \$out,
+			 'make_writable', \$make_writable,
+			 'log_events', \$log_events,
+			 'event_log_file/.*/', \$event_log_file,
+			 'email_events/.*/', \$email_events,
+			 'mail_server/.*/', \$mail_server,
+			 'statsfile/.*/STDERR', \$statsfile,
+			 'event_header/.*/', \$event_header)) {
+	
+	&print_usage();
+	die "\n";
+    }
+}
+
+
+END {
+
+    if ($make_writable) {
+	# chmod a+rw new collection
+	my $installed_collection = &util::filename_cat($ENV{'GSDLHOME'}, "collect", $collection);
+	&recursive_chmod($installed_collection);
+
+	# chmod a+rw anything we've left laying about in the tmp directory
+	if (($collectdir ne "") && 	
+	    (!&util::filenames_equal ($collectdir, &util::filename_cat($ENV{'GSDLHOME'}, "collect")))) {
+	    &recursive_chmod($collectdir);
+	}
+    }
+
+    # this will produce a .final file if one doesn't exist yet - that
+    # should only happen if there's been an error somewhere in the perl
+    # code
+    &final_out(7);
+
+    sub recursive_chmod {
+	my ($dir) = @_;
+	return unless -d $dir;
+
+	chmod (0777, $dir);
+
+	opendir (DIR, $dir) || die;
+	my @files = readdir DIR;
+	closedir DIR;
+	
+	foreach my $file (@files) {
+	    next if $file =~ /^\.\.?$/;
+	    $file = &util::filename_cat($dir, $file);
+	    if (-d $file) {
+		&recursive_chmod ($file);
+	    } else {
+		chmod (0777, $file);
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/buildcol.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/buildcol.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/buildcol.pl	(revision 13928)
@@ -0,0 +1,661 @@
+#!/usr/bin/perl -w
+
+## @file buildcol.pl
+# This program will build a particular collection.
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# @note 11/04/03 Added usage datastructure - John Thompson
+#
+# @author New Zealand Digital Library Project unless otherwise stated
+# @copy 1999 New Zealand Digital Library Project
+#
+package buildcol;
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/cpan");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/plugins");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/classify");
+}
+
+use colcfg;
+use util;
+use scriptutil;
+use FileHandle;
+use gsprintf;
+use printusage;
+use parse2;
+
+use strict;
+no strict 'refs'; # allow filehandles to be variables and vice versa
+no strict 'subs'; # allow barewords (eg STDERR) as function arguments
+
+my $mode_list =
+    [ { 'name' => "all",
+        'desc' => "{buildcol.mode.all}" },
+      { 'name' => "compress_text",
+        'desc' => "{buildcol.mode.compress_text}" },
+      { 'name' => "build_index",
+        'desc' => "{buildcol.mode.build_index}" },
+      { 'name' => "infodb",
+        'desc' => "{buildcol.mode.infodb}" } ];
+
+my $sec_index_list = 
+    [ {'name' => "never",
+       'desc' => "{buildcol.sections_index_document_metadata.never}" },
+      {'name' => "always",
+       'desc' => "{buildcol.sections_index_document_metadata.always}" },
+      {'name' => "unless_section_metadata_exists",
+       'desc' => "{buildcol.sections_index_document_metadata.unless_section_metadata_exists}" }
+      ];
+
+my $arguments =
+    [ { 'name' => "remove_empty_classifications",
+	'desc' => "{buildcol.remove_empty_classifications}",
+	'type' => "flag",
+	'reqd' => "no",
+	'modegli' => "2" },
+      { 'name' => "archivedir",
+	'desc' => "{buildcol.archivedir}",
+	'type' => "string",
+	'reqd' => "no",
+        'hiddengli' => "yes" },
+      { 'name' => "builddir",
+	'desc' => "{buildcol.builddir}",
+	'type' => "string",
+	'reqd' => "no",
+        'hiddengli' => "yes" },
+#     { 'name' => "cachedir",
+#	'desc' => "{buildcol.cachedir}",
+#	'type' => "string",
+#	'reqd' => "no" },
+      { 'name' => "collectdir",
+	'desc' => "{buildcol.collectdir}",
+	'type' => "string",
+	# parsearg left "" as default
+	#'deft' => &util::filename_cat ($ENV{'GSDLHOME'}, "collect"),
+	'reqd' => "no",
+        'hiddengli' => "yes" },
+      { 'name' => "create_images",
+	'desc' => "{buildcol.create_images}",
+	'type' => "flag",
+	'reqd' => "no",
+	'modegli' => "4" },
+      { 'name' => "debug",
+	'desc' => "{buildcol.debug}",
+	'type' => "flag",
+	'reqd' => "no",
+        'hiddengli' => "yes" },
+      { 'name' => "faillog",
+	'desc' => "{buildcol.faillog}",
+	'type' => "string",
+	# parsearg left "" as default
+	#'deft' => &util::filename_cat("<collectdir>", "colname", "etc", "fail.log"),
+	'reqd' => "no",
+	'modegli' => "4" },
+      { 'name' => "index",
+	'desc' => "{buildcol.index}",
+	'type' => "string",
+	'reqd' => "no",
+	'modegli' => "4" },
+      { 'name' => "incremental",
+	'desc' => "{buildcol.incremental}",
+	'type' => "flag",
+	'hiddengli' => "yes" },
+      { 'name' => "keepold",
+	'desc' => "{buildcol.keepold}",
+	'type' => "flag",
+	'reqd' => "no",
+        #'modegli' => "3",
+	'hiddengli' => "yes" },
+      { 'name' => "removeold",
+	'desc' => "{buildcol.removeold}",
+	'type' => "flag",
+	'reqd' => "no",
+	#'modegli' => "3",
+	'hiddengli' => "yes"  },
+      { 'name' => "language",
+	'desc' => "{scripts.language}",
+	'type' => "string",
+	'reqd' => "no",
+	'modegli' => "4" },
+      { 'name' => "maxdocs",
+	'desc' => "{buildcol.maxdocs}",
+	'type' => "int",
+	'reqd' => "no",
+        'hiddengli' => "yes" },
+      { 'name' => "maxnumeric",
+	'desc' => "{buildcol.maxnumeric}",
+	'type' => "int",
+	'reqd' => "no",
+	'deft' => "4",
+	'range' => "4,512",
+	'modegli' => "3" },
+      { 'name' => "mode",
+	'desc' => "{buildcol.mode}",
+	'type' => "enum",
+	'list' => $mode_list,
+	# parsearg left "" as default
+#	'deft' => "all",
+	'reqd' => "no",
+	'modegli' => "4" },
+      { 'name' => "no_strip_html",
+	'desc' => "{buildcol.no_strip_html}",
+	'type' => "flag",
+	'reqd' => "no",
+	'modegli' => "4" },
+      { 'name' => "no_text",
+	'desc' => "{buildcol.no_text}",
+	'type' => "flag",
+	'reqd' => "no",
+	'modegli' => "3" },
+      { 'name' => "sections_index_document_metadata",
+	'desc' => "{buildcol.sections_index_document_metadata}",
+	'type' => "enum",
+	'list' => $sec_index_list,
+	'reqd' => "no",
+	'modegli' => "3" },
+      { 'name' => "out",
+	'desc' => "{buildcol.out}",
+	'type' => "string",
+	'deft' => "STDERR",
+	'reqd' => "no",
+        'hiddengli' => "yes" },
+      { 'name' => "verbosity",
+	'desc' => "{buildcol.verbosity}",
+	'type' => "int",
+	# parsearg left "" as default
+	#'deft' => "2",
+	'reqd' => "no",
+	'modegli' => "4" },
+      { 'name' => "gli",
+	'desc' => "",
+	'type' => "flag",
+	'reqd' => "no",
+	'hiddengli' => "yes" },
+      { 'name' => "xml",
+	'desc' => "{scripts.xml}",
+	'type' => "flag",
+	'reqd' => "no",
+	'hiddengli' => "yes" }
+
+#      { 'name' => "incremental_dlc",
+#	'desc' => "{buildcol.incremental_dlc}",
+#	'type' => "flag",
+#	'reqd' => "no",
+#        'hiddengli' => "yes" } 
+      ];
+
+my $options = { 'name' => "buildcol.pl",
+		'desc' => "{buildcol.desc}",
+		'args' => $arguments };
+
+
+# globals
+my $collection;
+my $configfilename;
+my $out;
+
+## @method gsprintf()
+#  Print a string to the screen after looking it up from a locale dependant
+#  strings file. This function is losely based on the idea of resource
+#  bundles as used in Java.
+#
+#  @param  $error The STDERR stream.
+#  @param  $text The string containing GS keys that should be replaced with
+#                their locale dependant equivilents.
+#  @param  $out The output stream.
+#  @return The locale-based string to output.
+#
+sub gsprintf()
+{
+    return &gsprintf::gsprintf(@_);
+}
+## gsprintf() ##
+
+&main();
+
+## @method main()
+#
+#  [Parses up and validates the arguments to the build process before creating
+#  the appropriate build process to do the actual work - John]
+#
+#  @note Added true incremental support - John Thompson, DL Consulting Ltd.
+#  @note There were several bugs regarding using directories other than 
+#        "import" or "archives" during import and build quashed. - John 
+#        Thompson, DL Consulting Ltd.
+#
+#  @param  $incremental_dlc If true indicates this build should not regenerate all
+#                       the index and metadata files, and should instead just
+#                       append the information found in the archives directory
+#                       to the existing files. If this requires some complex
+#                       work so as to correctly insert into a classifier so be
+#                       it. Of course none of this is done here - instead the
+#                       incremental argument is passed to the document
+#                       processor.
+#
+sub main
+{
+    # command line args
+    my ($verbosity, $archivedir, $cachedir, $builddir, $maxdocs, 
+	$debug, $mode, $indexname, $removeold, $keepold, $incremental, 
+	$remove_empty_classifications,
+	$create_images, $collectdir, $build, $type, $textindex,
+	$no_strip_html, $no_text, $faillog, $gli, $index, $language,
+	$sections_index_document_metadata, $maxnumeric, $incremental_dlc);
+
+    my $xml = 0;
+    $incremental_dlc = 0; # this is hidden for now as it doesn't work for standard greenstone at the moment
+    my $hashParsingResult = {};
+    # general options available to all plugins
+    my $intArgLeftinAfterParsing = parse2::parse(\@ARGV,$arguments,$hashParsingResult,"allow_extra_options");
+
+    # If parse returns -1 then something has gone wrong
+    if ($intArgLeftinAfterParsing == -1)
+    {
+	&PrintUsage::print_txt_usage($options, "{buildcol.params}");
+	die "\n";
+    }
+    
+    foreach my $strVariable (keys %$hashParsingResult)
+    {
+	eval "\$$strVariable = \$hashParsingResult->{\"\$strVariable\"}";
+    }
+
+    # If $language has been specified, load the appropriate resource bundle
+    # (Otherwise, the default resource bundle will be loaded automatically)
+    if ($language && $language =~ /\S/) {
+	&gsprintf::load_language_specific_resource_bundle($language);
+    }
+
+    if ($xml) {
+        &PrintUsage::print_xml_usage($options);
+	print "\n";
+	return;
+    }
+
+    if ($gli) { # the gli wants strings to be in UTF-8
+	&gsprintf::output_strings_in_UTF8; 
+    }
+
+    # now check that we had exactly one leftover arg, which should be 
+    # the collection name. We don't want to do this earlier, cos 
+    # -xml arg doesn't need a collection name
+    # Or if the user specified -h, then we output the usage also
+    if ($intArgLeftinAfterParsing != 1 || (@ARGV && $ARGV[0] =~ /^\-+h/))
+    {
+	&PrintUsage::print_txt_usage($options, "{buildcol.params}");
+	die "\n";
+    }
+    
+    $textindex = "";
+    my $close_out = 0;
+    if ($out !~ /^(STDERR|STDOUT)$/i) {
+	open (OUT, ">$out") ||
+	    (&gsprintf(STDERR, "{common.cannot_open_output_file}\n", $out) && die);
+	$out = "buildcol::OUT";
+	$close_out = 1;
+    }
+    $out->autoflush(1);
+
+    # get and check the collection
+    if (($collection = &util::use_collection(@ARGV, $collectdir)) eq "") {
+	&PrintUsage::print_txt_usage($options, "{buildcol.params}");
+	die "\n";
+    }
+
+    if ($faillog eq "") {
+	$faillog = &util::filename_cat($ENV{'GSDLCOLLECTDIR'}, "etc", "fail.log");
+    }
+    # note that we're appending to the faillog here (import.pl clears it each time)
+    # this could potentially create a situation where the faillog keeps being added 
+    # to over multiple builds (if the import process is being skipped)
+    open (FAILLOG, ">>$faillog") ||
+	(&gsprintf(STDERR, "{common.cannot_open_fail_log}\n", $faillog) && die);
+    $faillog = 'buildcol::FAILLOG';
+    $faillog->autoflush(1);
+
+    unshift (@INC, "$ENV{'GSDLCOLLECTDIR'}/perllib");
+    # Don't know why this didn't already happen, but now collection specific
+    # classify and plugins directory also added to include path
+    unshift (@INC, "$ENV{'GSDLCOLLECTDIR'}/perllib/classify");
+    unshift (@INC, "$ENV{'GSDLCOLLECTDIR'}/perllib/plugins");
+
+    # read the configuration file
+    $configfilename = &util::filename_cat ($ENV{'GSDLCOLLECTDIR'}, "etc", "collect.cfg");
+    my ($collectcfg, $buildtype); 
+
+    if (!-e $configfilename) {
+	&gsprintf($out, "{common.cannot_find_cfg_file}\n", $configfilename) && die;
+    }
+    
+    $collectcfg = &colcfg::read_collect_cfg ($configfilename);
+    
+    if ($verbosity !~ /\d+/) {
+	if (defined $collectcfg->{'verbosity'} && $collectcfg->{'verbosity'} =~ /\d+/) {
+	    $verbosity = $collectcfg->{'verbosity'};
+	} else {
+	    $verbosity = 2; # the default
+	}
+    }
+    # we use searchtype for determining buildtype, but for old versions, use buildtype
+    if (defined $collectcfg->{'buildtype'}) {
+	$buildtype = $collectcfg->{'buildtype'};
+    } elsif (defined $collectcfg->{'searchtypes'} || defined $collectcfg->{'searchtype'}) {
+	$buildtype = "mgpp";
+    } else {
+	$buildtype = "mg"; #mg is the default
+    }
+    if (defined $collectcfg->{'archivedir'} && $archivedir eq "") {
+	$archivedir = $collectcfg->{'archivedir'};
+    }
+    if (defined $collectcfg->{'cachedir'} && $cachedir eq "") {
+	$cachedir = $collectcfg->{'cachedir'};
+    }
+    if (defined $collectcfg->{'builddir'} && $builddir eq "") {
+	$builddir = $collectcfg->{'builddir'};
+    }
+    if ($maxdocs !~ /\-?\d+/) {
+	if (defined $collectcfg->{'maxdocs'} && $collectcfg->{'maxdocs'} =~ /\-?\d+/) {
+	    $maxdocs = $collectcfg->{'maxdocs'};
+	} else {
+	    $maxdocs = -1; # the default
+	}
+    }
+    if (defined $collectcfg->{'maxnumeric'} && $collectcfg->{'maxnumeric'} =~ /\d+/) {
+	$maxnumeric = $collectcfg->{'maxnumeric'};
+    } 
+    
+    if ($maxnumeric < 4 || $maxnumeric > 512) {
+	$maxnumeric = 4;
+    }
+    
+    if (defined $collectcfg->{'debug'} && $collectcfg->{'debug'} =~ /^true$/i) {
+	$debug = 1;
+    }
+    if ($mode !~ /^(all|compress_text|build_index|infodb)$/) {
+	if (defined $collectcfg->{'mode'} && $collectcfg->{'mode'} =~ /^(all|compress_text|build_index|infodb)$/) {
+	    $mode = $collectcfg->{'mode'};
+	} else {
+	    $mode = "all"; # the default
+	}
+    }
+    if (defined $collectcfg->{'index'} && $indexname eq "") {
+	$indexname = $collectcfg->{'index'};
+    }
+    if (defined $collectcfg->{'no_text'} && $no_text == 0) {
+	if ($collectcfg->{'no_text'} =~ /^true$/i) {
+	    $no_text = 1;
+	}
+    }
+    if (defined $collectcfg->{'no_strip_html'} && $no_strip_html == 0) {
+	if ($collectcfg->{'no_strip_html'} =~ /^true$/i) {
+	    $no_strip_html = 1;
+	}
+    }
+    if (defined $collectcfg->{'remove_empty_classifications'} && $remove_empty_classifications == 0) {
+	if ($collectcfg->{'remove_empty_classifications'} =~ /^true$/i) {
+	    $remove_empty_classifications = 1;
+	}
+    }
+    
+    
+    if (defined $collectcfg->{'create_images'} && $collectcfg->{'create_images'} =~ /^true$/i) {
+	$create_images = 1;
+    }
+    if ($buildtype eq "mgpp" && defined $collectcfg->{'textcompress'}) {
+	$textindex = $collectcfg->{'textcompress'};
+    }
+    if (defined $collectcfg->{'gli'} && $collectcfg->{'gli'} =~ /^true$/i) {
+	$gli = 1;
+    }
+
+    if ($sections_index_document_metadata !~ /\S/ && defined $collectcfg->{'sections_index_document_metadata'}) {
+	$sections_index_document_metadata = $collectcfg->{'sections_index_document_metadata'};
+    }
+    
+    if ($sections_index_document_metadata !~ /^(never|always|unless_section_metadata_exists)$/) {
+	$sections_index_document_metadata = "never";
+    }
+    
+    ($removeold, $keepold, $incremental) = &scriptutil::check_removeold_and_keepold($removeold, $keepold, $incremental, "building", $collectcfg);
+ 
+    $gli = 0 unless defined $gli;
+
+    # New argument to track whether build is incremental
+    $incremental = 0 unless defined $incremental;
+
+    print STDERR "<Build>\n" if $gli;
+
+    #set the text index
+    if (($buildtype eq "mgpp") || ($buildtype eq "lucene")) {
+	if ($textindex eq "") {
+	    $textindex = "text";
+	}
+    }
+    else {
+	$textindex = "section:text";
+    }
+
+    # create default images if required
+    if ($create_images) {
+	my $collection_name = $collection;
+	$collection_name = $collectcfg->{'collectionmeta'}->{'collectionname'}->{'default'}
+	if defined $collectcfg->{'collectionmeta'}->{'collectionname'}->{'default'};
+	&create_images ($collection_name);
+    }
+
+    # fill in the default archives and building directories if none
+    # were supplied, turn all \ into / and remove trailing /
+
+    my ($realarchivedir, $realbuilddir);
+    # Modified so that the archivedir, if provided as an argument, is made
+    # absolute if it isn't already
+    if ($archivedir eq "")
+      {
+        $archivedir = &util::filename_cat ($ENV{'GSDLCOLLECTDIR'}, "archives");
+      }
+    else
+      {
+        $archivedir = &make_absolute($ENV{'GSDLCOLLECTDIR'}, $archivedir);
+      }
+    # End Mod
+    $archivedir =~ s/[\\\/]+/\//g;
+    $archivedir =~ s/\/$//;
+    $builddir = &util::filename_cat ($ENV{'GSDLCOLLECTDIR'}, "building") if $builddir eq "";
+    $builddir =~ s/[\\\/]+/\//g;
+    $builddir =~ s/\/$//;
+
+    # update the archive cache if needed
+    if ($cachedir) {
+	&gsprintf($out, "{buildcol.updating_archive_cache}\n")
+	    if ($verbosity >= 1);
+
+	$cachedir =~ s/[\\\/]+$//;
+	$cachedir .= "/collect/$collection" unless 
+	    $cachedir =~ /collect\/$collection/;
+
+	$realarchivedir = "$cachedir/archives";
+	$realbuilddir = "$cachedir/building";
+	&util::mk_all_dir ($realarchivedir);
+	&util::mk_all_dir ($realbuilddir);
+	&util::cachedir ($archivedir, $realarchivedir, $verbosity);
+
+    } else {
+	$realarchivedir = $archivedir;
+	$realbuilddir = $builddir;
+    }
+
+    # build it in realbuilddir
+    &util::mk_all_dir ($realbuilddir);
+
+    my ($buildertype, $builderdir,  $builder);
+    # if a builder class has been created for this collection, use it
+    # otherwise, use the mg or mgpp builder
+    if (-e "$ENV{'GSDLCOLLECTDIR'}/perllib/${collection}builder.pm") {
+	$builderdir = "$ENV{'GSDLCOLLECTDIR'}/perllib";
+	$buildertype = "${collection}builder";
+    } else {
+	$builderdir = "$ENV{'GSDLHOME'}/perllib";
+	if ($buildtype eq "lucene") {
+	    $buildertype = "lucenebuilder";
+	}
+	elsif ($buildtype eq "mgpp") {
+	    $buildertype = "mgppbuilder";
+	}
+	else {
+	    $buildertype = "mgbuilder";
+	}
+    }
+	
+    require "$builderdir/$buildertype.pm";
+
+    eval("\$builder = new $buildertype(\$collection, " .
+	 "\$realarchivedir, \$realbuilddir, \$verbosity, " .
+	 "\$maxdocs, \$debug, \$keepold, \$incremental, \$incremental_dlc, " .
+	 "\$remove_empty_classifications, " .
+	 "\$out, \$no_text, \$faillog, \$gli)");
+    die "$@" if $@;
+
+    $builder->init();
+    $builder->set_maxnumeric($maxnumeric);
+    
+    if (($buildertype eq "mgppbuilder") && $no_strip_html) {
+	$builder->set_strip_html(0);
+    }
+    if ($sections_index_document_metadata ne "never") {
+	$builder->set_sections_index_document_metadata($sections_index_document_metadata);
+    }
+        
+    if ($mode =~ /^all$/i) {
+	$builder->compress_text($textindex);
+	$builder->build_indexes($indexname);
+	$builder->make_infodatabase();
+	$builder->collect_specific();
+    } elsif ($mode =~ /^compress_text$/i) {
+	$builder->compress_text($textindex);
+    } elsif ($mode =~ /^build_index$/i) {
+	$builder->build_indexes($indexname);	
+    } elsif ($mode =~ /^infodb$/i) {
+	$builder->make_infodatabase();
+    } else {
+	(&gsprintf(STDERR, "{buildcol.unknown_mode}\n", $mode) && die);
+    }
+
+    $builder->make_auxiliary_files() if !$debug;
+    $builder->deinit();
+    
+    if (($realbuilddir ne $builddir) && !$debug) {
+	&gsprintf($out, "{buildcol.copying_back_cached_build}\n")
+	    if ($verbosity >= 1);
+	&util::rm_r ($builddir);
+	&util::cp_r ($realbuilddir, $builddir);
+    }
+
+    close OUT if $close_out;
+    close FAILLOG;
+
+    print STDERR "</Build>\n" if $gli;
+}
+## main() ##
+
+## @method create_images()
+#
+#  [Used to create default cover images... from what I'm not quite sure - John]
+#
+sub create_images {
+    my ($collection_name) = @_;
+
+    my $image_script = &util::filename_cat ($ENV{'GSDLHOME'}, "bin", "script", "gimp", "title_icon-1.2.pl");
+    if (!-e $image_script) {
+	&gsprintf($out, "{buildcol.no_image_script}", $image_script);
+	&gsprintf($out, "{buildcol.no_default_images}\n\n");
+	return;
+    }
+
+    my $imagedir = &util::filename_cat ($ENV{'GSDLCOLLECTDIR'}, "images");
+
+    &util::mk_all_dir ($imagedir);
+
+    # create the images
+    system ("$image_script -size 1.5 -image_dir \"$imagedir\" -filename $collection.gif -text \"$collection_name\"");
+    system ("$image_script -image_dir \"$imagedir\" -filename ${collection}sm.gif -text \"$collection_name\"");
+
+    # update the collect.cfg configuration file (this will need
+    # to be changed when the config file format changes)
+    if (!open (CFGFILE, $configfilename)) {
+	&gsprintf($out, "{buildcol.cannot_open_cfg_file}\n", $configfilename);
+	&gsprintf($out, "{buildcol.unlinked_col_images}\n");
+	return;
+    }
+
+    my $line = ""; my $file = "";
+    my $found = 0; my $foundsm = 0;
+    while (defined ($line = <CFGFILE>)) {
+	if ($line =~ /collectionmeta\s+iconcollection\s+/) {
+	    $line = "collectionmeta iconcollection _httpprefix_/collect/$collection/images/$collection.gif\n";
+	    $found = 1;
+	} elsif ($line =~ /collectionmeta\s+iconcollectionsmall\s+/) {
+	    $line = "collectionmeta iconcollectionsmall _httpprefix_/collect/$collection/images/${collection}sm.gif\n";
+	    $foundsm = 1;
+	}
+	$file .= $line;
+    }
+    close CFGFILE;
+
+    $file .= "collectionmeta iconcollection _httpprefix_/collect/$collection/images/$collection.gif\n" if !$found;
+    $file .= "collectionmeta iconcollectionsmall _httpprefix_/collect/$collection/images/${collection}sm.gif\n" if !$foundsm;
+
+    if (!open (CFGFILE, ">$configfilename")) {
+	&gsprintf($out, "{buildcol.cannot_open_cfg_file}\n", $configfilename);
+	&gsprintf($out, "{buildcol.unlinked_col_images}\n");
+	return;
+    }
+    print CFGFILE $file;
+    close CFGFILE;
+}
+## create_images() ##
+
+## @method make_absolute()
+#
+#  Ensure the given file path is absolute in respect to the given base path.
+#
+#  @param  $base_dir A string denoting the base path the given dir must be
+#                    absolute to.
+#  @param  $dir The directory to be made absolute as a string. Note that the
+#               dir may already be absolute, in which case it will remain
+#               unchanged.
+#  @return The now absolute form of the directory as a string.
+#
+#  @author John Thompson, DL Consulting Ltd.
+#  @copy 2006 DL Consulting Ltd.
+#
+sub make_absolute()
+  {
+    my ($base_dir, $dir) = @_;
+    $dir = $base_dir . "/$dir" if ($dir =~ m#^[^/]#);
+    $dir =~ s|^/tmp_mnt||;
+    1 while($dir =~ s|/[^/]*/\.\./|/|g);
+    $dir =~ s|/[.][.]?/|/|g;
+    $dir =~ tr|/|/|s;
+    return $dir;
+  }
+## make_absolute() ##
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/cancel_build.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/cancel_build.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/cancel_build.pl	(revision 13928)
@@ -0,0 +1,123 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# cancel_build.pl --
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 2000 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+# This program will create a .kill file within the GSDLCOLLECTDIR/collect-name
+# directory which will cause any import.pl or buildcol.pl processes running
+# on that collection to abort.
+# It then cleans any mess left laying around the collection (including the
+# import directory !!).
+# cancel_build.pl is really only intended to be called from within the 
+# library's collectoraction and isn't much use for anything else. As such it
+# should be rewritten in C++ one day and included in the collectoraction 
+# itself.
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use util;
+use parsargv;
+use File::Copy;
+
+sub print_usage {
+    print STDERR "\n";
+    print STDERR "cancel_build.pl: Cancel a build in progress. This script is\n";
+    print STDERR "                 called from the collector and is not intended\n";
+    print STDERR "                 for general use.\n\n";
+    print STDERR "  usage: $0 [options] collection-name\n\n";
+    print STDERR "  options:\n";
+    print STDERR "   -collectdir directory  Collection directory (defaults to " .
+	&util::filename_cat ($ENV{'GSDLHOME'}, "collect") . ")\n\n";
+}
+
+&main();
+
+sub main {
+    if (!parsargv::parse(\@ARGV, 'collectdir/.*/', \$collectdir)) {
+	&print_usage();
+	die "\n";
+    }
+
+    my $collection = pop @ARGV;
+    if (!defined $collection || $collection !~ /\w/) {
+	print STDERR "no collection specified\n";
+	&print_usage();
+	die "\n";
+    }
+
+    my $cdir = &util::filename_cat ($collectdir, $collection);
+    if ($collectdir eq "") {
+	$collectdir = &util::filename_cat ($ENV{'GSDLHOME'}, "collect");
+	$cdir = &util::filename_cat ($collectdir, $collection);
+    } elsif (!-d $cdir) {
+	$cdir = &util::filename_cat ($ENV{'GSDLHOME'}, "collect", $collection);
+    }
+
+    if (! -d $cdir) {
+	print STDERR "Collection does not exist ($cdir)\n";
+	exit (1);
+    }
+
+    # create .kill file
+    my $killfile = &util::filename_cat ($cdir, ".kill");
+    if (!open (KILLFILE, ">$killfile")) {
+	print STDERR "Couldn't create .kill file ($killfile)\n";
+	exit (1);
+    }
+    print KILLFILE "kill $collection\n";
+    close KILLFILE;
+
+    sleep (2); # just give it a chance to die gracefully;
+
+    # remove archives, building, and import directories
+    &util::rm_r (&util::filename_cat ($cdir, "import"));
+    &util::rm_r (&util::filename_cat ($cdir, "building"));
+    &util::rm_r (&util::filename_cat ($cdir, "archives"));
+
+    # remove any other temporary files that may have been left laying around
+    # by the build
+    my $buildfile = &util::filename_cat ($collectdir, ".build");
+    &util::rm ($buildfile) if -e $buildfile;
+    my $bldfile = &util::filename_cat ($collectdir, "$collection.bld");
+    &util::rm ($bldfile) if -e $bldfile;
+    my $bldfile_d = &util::filename_cat ($collectdir, "$collection.bld.download");
+    &util::rm ($bldfile_d) if -e $bldfile_d;
+    my $bldfile_i = &util::filename_cat ($collectdir, "$collection.bld.import");
+    &util::rm ($bldfile_i) if -e $bldfile_i;
+    my $bldfile_b = &util::filename_cat ($collectdir, "$collection.bld.build");
+    &util::rm ($bldfile_b) if -e $bldfile_b;
+    my $bldfile_f = &util::filename_cat ($collectdir, "$collection.bld.final");
+    &util::rm ($bldfile_f) if -e $bldfile_f;
+    
+    # if there's an archives.org directory, rename it back to archives
+    if (-d &util::filename_cat ($cdir, "archives.org")) {
+	&File::Copy::move (&util::filename_cat ($cdir, "archives.org"),
+			   &util::filename_cat ($cdir, "archives"));
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/classinfo.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/classinfo.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/classinfo.pl	(revision 13928)
@@ -0,0 +1,189 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# classinfo.pl -- provide information about classifiers
+#
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+use strict;
+no strict 'subs'; # allow barewords (eg STDERR) as function arguments
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/cpan");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/classify");
+}
+
+use classify;
+use util;
+use gsprintf;
+use printusage;
+
+use parse2;
+
+my $arguments =
+    [ { 'name' => "collection",
+	'desc' => "{classinfo.collection}",
+	'type' => "string",
+	'deft' => "",
+	'reqd' => "no" },
+      { 'name' => "xml",
+	'desc' => "{scripts.xml}",
+	'type' => "flag",
+	'reqd' => "no" },
+      { 'name' => "listall",
+	'desc' => "{scripts.listall}",
+	'type' => "flag",
+	'reqd' => "no" },
+      { 'name' => "describeall",
+	'desc' => "{scripts.describeall}",
+	'type' => "flag",
+	'reqd' => "no" },
+      { 'name' => "language",
+	'desc' => "{scripts.language}",
+	'type' => "string",
+	'reqd' => "no" } ];
+
+my $options = { 'name' => "classinfo.pl",
+		'desc' => "{classinfo.desc}",
+		'args' => $arguments };
+
+sub gsprintf
+{
+    return &gsprintf::gsprintf(@_);
+}
+
+sub main {
+    my $collection = "";
+    my $xml = 0;
+    my $listall = 0;
+    my $describeall = 0;
+    my $language;
+
+    my $hashParsingResult = {};
+    # general options available to all classifiers
+    my $intArgLeftinAfterParsing = parse2::parse(\@ARGV,$arguments,$hashParsingResult,"allow_extra_options");
+    # parse returns -1 if an error occurred
+    if($intArgLeftinAfterParsing == -1)
+    {
+	&PrintUsage::print_txt_usage($options, "{classinfo.params}");
+	die "\n";
+    }
+
+    foreach my $strVariable (keys %$hashParsingResult)
+    {
+	eval "\$$strVariable = \$hashParsingResult->{\"\$strVariable\"}";
+    }
+    # If $language has been specified, load the appropriate resource bundle
+    # (Otherwise, the default resource bundle will be loaded automatically)
+    if ($language) {
+	&gsprintf::load_language_specific_resource_bundle($language);
+    }
+    
+    # If there is not exactly 1 argument left (classifier name), then the arguments were wrong
+    # If the user specified -h, then we output the usage also
+    if((@ARGV && $ARGV[0] =~ /^\-+h/) )
+    {
+	PrintUsage::print_txt_usage($options, "{classinfo.params}");  
+        die "\n";
+    }
+
+    # If there is not exactly 1 argument left (classifier name), then the arguments were wrong (apart from if we had listall or describeall set)
+    if ($listall == 0 && $describeall ==0 && $intArgLeftinAfterParsing == 0) {
+	gsprintf(STDERR, "{classinfo.no_classifier_name}\n\n");
+	PrintUsage::print_txt_usage($options, "{classinfo.params}", 1);
+	die "\n";
+    }
+	
+    # we had some arguments that we weren't expecting
+    if ($intArgLeftinAfterParsing > 1) {
+	pop(@ARGV); # assume that the last arg is the classifier name
+	gsprintf(STDERR, "{common.invalid_options}\n\n", join (',', @ARGV));
+	PrintUsage::print_txt_usage($options, "{classinfo.params}", 1);
+	die "\n";
+    }
+
+    # Get classifier
+    my $classifier = shift (@ARGV);
+    if (defined $classifier) {
+	$classifier =~ s/\.pm$//; # allow xxx.pm as the argument
+    }
+
+    # make sure the classifier is loaded from the correct location - a hack.
+    if ($collection ne "") {
+	$ENV{'GSDLCOLLECTDIR'} = &util::filename_cat ($ENV{'GSDLHOME'}, "collect", $collection);
+    } else {
+	$ENV{'GSDLCOLLECTDIR'} = $ENV{'GSDLHOME'};
+    }
+ 
+    if ($listall || $describeall) {
+	my $classify_dir = &util::filename_cat($ENV{'GSDLCOLLECTDIR'}, "perllib", "classify");
+	my @classifier_list = ();
+	if (opendir (INDIR, $classify_dir)) {
+	    @classifier_list = grep (/\.pm$/, readdir (INDIR));
+	    closedir (INDIR);
+	}
+
+	print STDERR "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+	print STDERR "<ClassifyList length=\"" . scalar(@classifier_list) . "\">\n";
+	foreach my $classifier (@classifier_list) {
+	    $classifier =~ s/\.pm$//;
+	    my $classifierobj = &classify::load_classifier_for_info ($classifier);
+	    if ($describeall) {
+		$classifierobj->print_xml_usage(0);
+	    }
+	    else {
+		$classifierobj->print_xml_usage(0, 1);
+	    }
+	}
+	print STDERR "</ClassifyList>\n";
+    }
+    else {
+	&print_single_classifier($classifier, $xml, 1);
+    }
+}
+
+
+sub print_single_classifier {
+    my ($classifier, $xml, $header) = @_;
+    my $classobj = &classify::load_classifier_for_info ($classifier);
+    if ($xml) {
+	$classobj->print_xml_usage($header);
+    }
+    else {
+	&gsprintf(STDERR, "\n{classinfo.passing_options}\n\n");
+	&gsprintf(STDERR, "{classinfo.option_types}:\n\n");
+	&gsprintf(STDERR, "{classinfo.specific_options}\n\n");
+	&gsprintf(STDERR, "{classinfo.general_options}\n\n");
+	&gsprintf(STDERR, "$classifier {classinfo.info}:\n\n");
+	
+	$classobj->print_txt_usage();
+    }
+    
+}
+
+
+&main ();
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/cleantmp.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/cleantmp.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/cleantmp.pl	(revision 13928)
@@ -0,0 +1,80 @@
+#!/usr/bin/perl
+
+###########################################################################
+#
+# cleantmp.pl
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+# cleantmp.pl cleans up the gsdl/tmp directory
+# it's intended mainly for use by the collectoraction
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use parsargv;
+use util;
+
+sub print_usage {
+    print STDERR "\n";
+    print STDERR "cleantmp.pl: Cleans up the Greenstone tmp directory by deleting anything\n";
+    print STDERR "             more than -expire_days days old.\n\n";
+    print STDERR "\n  usage: $0 [options]\n\n";
+    print STDERR "  options:\n";
+    print STDERR "   -expire_days number   The number of days old information in the tmp\n";
+    print STDERR "                         directory must be before it is removed (defaults\n";
+    print STDERR "                         to 7 days)\n\n";
+}
+
+&main ();
+
+sub main {
+    
+    if (!parsargv::parse(\@ARGV, 'expire_days/\d/7', \$expire_days)) {
+	&print_usage();
+	die "\n";
+    }
+
+    my $current_time = time;
+    my $expire_time = ($current_time - ($expire_days*60*60*24));
+
+    my $tmpdir = &util::filename_cat ($ENV{'GSDLHOME'}, "tmp");
+
+    opendir (TMP, $tmpdir) || die "cleantmp.pl: couldn't open $tmpdir\n";
+    my @files = readdir TMP;
+    closedir TMP;
+
+    foreach $file (@files) {
+	next if ($file =~ /^\.\.$/);
+
+	if ($file =~ /^tbuild/) {
+	    my $thisfile = &util::filename_cat ($tmpdir, $file);
+	    my @stats = stat ($thisfile);
+	    if ($stats[9] < $expire_time) {
+		&util::rm_r ($thisfile);
+	    }
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/convert_collection.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/convert_collection.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/convert_collection.pl	(revision 13928)
@@ -0,0 +1,112 @@
+#! /usr/bin/perl -w
+
+# converts an old style humanity collection which uses an index.txt file to
+# use a single metadata.xml file instead
+
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use util;
+use cfgread;
+
+my $collection = $ARGV[0];
+my $collectdir = &util::filename_cat($ENV{'GSDLHOME'}, "collect", $collection);
+my $importdir = &util::filename_cat($collectdir, "import");
+
+die unless -d $importdir;
+
+# new import structure will be created in "import.new" directory
+my $importnewdir = $importdir . ".new";
+`mkdir $importnewdir`;
+
+
+# read in index.txt file and generate metadata.xml, in the process
+# converting the html files and copying them across to the import.new
+# directory
+
+my $metadata_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n";
+$metadata_xml .= "<!DOCTYPE DirectoryMetadata SYSTEM " .
+    "\"http://greenstone.org/dtd/DirectoryMetadata/1.0/DirectoryMetadata.dtd\">\n";
+$metadata_xml .= "<DirectoryMetadata>\n\n";
+
+my $index_txt = &util::filename_cat($importdir, "index.txt");
+
+open (INDEXTXT, $index_txt) || die;
+
+my $line = [];
+my @fields = ();
+my $count = 0;
+while (defined ($line = cfgread::read_cfg_line("main::INDEXTXT"))) {
+
+#    last if $count > 10;
+
+    if ($line->[0] eq "key:") {
+	shift @$line;
+	@fields = @$line;
+    } else {
+	
+	my $jobnumber = shift @$line;
+	&new_document($jobnumber);
+	$count ++;
+
+	my $i = 0;
+	for ($i = 0; $i < scalar(@$line); $i++) {
+	    if ($line->[$i] =~ /^<([^>]+)>(.*)$/) {
+		&set_metadata($1, $2);
+	    } else {
+		if (defined ($fields[$i])) {
+		    &set_metadata($fields[$i], $line->[$i]);
+		} else {
+		    print STDERR "error 1\n";
+		}
+	    }
+	}
+
+	$metadata_xml .= "    </Description>\n";
+	$metadata_xml .= "  </FileSet>\n\n";
+    }
+}
+close INDEXTXT;
+
+$metadata_xml .= "</DirectoryMetadata>\n";
+
+my $metafile = &util::filename_cat($importnewdir, "metadata.xml");
+open (META, ">$metafile") || die;
+print META $metadata_xml;
+close META;
+
+
+sub new_document {
+    my ($jobnumber) = @_;
+
+    print STDERR "creating new document ($jobnumber)\n";
+
+    my $docdir = &util::filename_cat($importdir, $jobnumber);
+    die unless -d $docdir;
+
+    # copy whole directory across to import.new
+    $jobnumber =~ s/^.*?\///;
+    my $newdocdir = &util::filename_cat($importnewdir, $jobnumber);
+    die if -e $newdocdir;
+    `cp -r $docdir $newdocdir`;
+
+    # convert the htm file to use the new syntax
+    my $htmfile = &util::filename_cat($newdocdir, "$jobnumber.htm");
+    die unless -e $htmfile;
+    `convert_toc.pl < $htmfile > $htmfile.new`;
+    `mv $htmfile.new $htmfile`;
+
+    # update metadata.xml
+    $metadata_xml .= "  <FileSet>\n";
+    $metadata_xml .= "    <FileName>$jobnumber</FileName>\n";
+    $metadata_xml .= "    <Description>\n";
+}
+
+sub set_metadata {
+    my ($key, $value) = @_;
+
+    $metadata_xml .= "      <Metadata name=\"$key\" mode=\"accumulate\">$value</Metadata>\n";
+}
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/convert_toc.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/convert_toc.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/convert_toc.pl	(revision 13928)
@@ -0,0 +1,124 @@
+#! /usr/bin/perl -w
+
+# convert_toc.pl converts old <<TOC>> marked up files to use the new
+# <Section> syntax (suitable for processing by HTMLPlug -description_tags
+
+use File::Basename;
+
+my $level = 0;
+
+sub main {
+  open STDIN, "<$ARGV[0]" or die "$ARGV[0]: $!\n";
+  open STDOUT, ">$ARGV[1]" or die "$ARGV[1]: $!\n";
+
+  my $dirname = &File::Basename::dirname($ARGV[0]);
+
+  my $content = "";
+  
+  while (<STDIN>) {
+    $_ =~ s/[\cJ\cM]+$/\n/;
+    $content .= $_;
+  }
+
+  # fix images
+  $content =~ s/&lt;&lt;I&gt;&gt;\s*(\w+\.(?:png|jpe?g|gif))\s*(.*?)<\/p>/rename_image_old($1, $2, $dirname)/iegs;
+  $content =~ s/<img\s+src=\"?(\w+\.(?:png|jpe?g|gif))\"?/rename_image($1, $dirname)/iegs;
+
+  # process section title
+  $content =~ s/(?:<P[^>]*>|<BR>)(?:\s*<\/?[^>]*>)*?&lt;&lt;TOC(\d+)&gt;&gt;(.*?)(?=<\/?P[^>]*>|<BR>)/
+      process_toc ($1, $2)/sige;
+
+  # close the remaining sections
+  my $section_ending = "<!--\n";
+  for (my $j = 0; $j < $level; $j++) {
+    $section_ending .= "</Section>\n";
+  }
+  $section_ending .= "-->\n";
+  $content =~ s/(<\/body>)/$section_ending.$1/sie;
+
+  print STDOUT $content;
+  close STDOUT; close STDIN;
+}
+
+sub process_toc {
+  my ($thislevel, $title) = @_;
+  my $toc = '';
+ 
+  $title =~ s/<[^>]+>//sg;
+  $title =~ s/^\s+//s;
+  $title =~ s/\s+$//s;
+  $title =~ s/\n/ /sg;
+
+  $toc .= "\n<!--\n";
+
+  if ($thislevel <= $level) {
+    for (my $i = 0; $i < ($level-$thislevel+1); $i++) {
+	$toc .= "</Section>\n";
+    }
+  }
+
+  $toc .= "<Section>\n".
+	"  <Description>\n".
+	"    <Metadata name=\"Title\">$title</Metadata>\n".
+	"  </Description>\n".
+	"-->\n";
+
+  $level = $thislevel;
+
+  return $toc;
+}
+
+sub rename_image_old {
+    my ($image_name, $following_text, $dirname) = @_;
+
+    &rename_image($image_name, $dirname);
+
+    return "<center><img src=\"$image_name\"><br>$following_text<\/center><\/p>\n";
+}
+
+
+# may need to rename image files if case isn't consistent
+# (i.e. collections prepared on windows may have images named
+# AAA.GIF which are linked into the HTML as aaa.gif)
+sub rename_image {
+    my ($image_name, $dirname) = @_;
+
+
+    if (!-e "$dirname/$image_name") {
+
+	my ($pre, $ext) = $image_name =~ /^([^\.]+)\.(.*)$/;
+	my $image_name_uc = uc($image_name);
+	my $image_name_lc = lc($image_name);
+	my $image_name_ul = uc($pre) . "." . lc($ext);
+	my $image_name_lu = lc($pre) . "." . uc($ext);
+
+	if (-e "$dirname/$image_name_uc") {
+	    print STDERR "renaming $dirname/$image_name_uc --> $dirname/$image_name\n";
+	    rename ("$dirname/$image_name_uc", "$dirname/$image_name");
+
+	} elsif (-e "$dirname/$image_name_lc") {
+	    print STDERR "renaming $dirname/$image_name_lc --> $dirname/$image_name\n";
+	    rename ("$dirname/$image_name_lc", "$dirname/$image_name");
+	
+	} elsif (-e "$dirname/$image_name_ul") {
+	    print STDERR "renaming $dirname/$image_name_ul --> $dirname/$image_name\n";
+	    rename ("$dirname/$image_name_ul", "$dirname/$image_name");
+	
+	} elsif (-e "$dirname/$image_name_lu") {
+	    print STDERR "renaming $dirname/$image_name_lu --> $dirname/$image_name\n";
+	    rename ("$dirname/$image_name_lu", "$dirname/$image_name");
+	
+	} else {
+	    print STDERR "ERROR**** $dirname/$image_name could not be found\n";
+	    if (open (ERROR, ">>error.txt")) {
+		print ERROR "ERROR**** $dirname/$image_name could not be found\n";
+		close ERROR;
+	    }
+	}
+    }
+    return "<img src=\"$image_name\"";
+}
+
+
+
+&main;
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/convert_toc_dir.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/convert_toc_dir.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/convert_toc_dir.pl	(revision 13928)
@@ -0,0 +1,41 @@
+#! /usr/bin/perl -w
+
+# run convert_toc.pl on any html files found in the directory passed in on
+# the command line (or any subdirs).
+
+die "\$GSDLOS not set !\n" if (!defined $ENV{GSDLOS});
+my ($move, $separator);
+if ($ENV{GSDLOS} eq "windows") {
+  $move = "move";
+  $separator = "\\";
+} else {
+  $move = "mv";
+  $separator = "/";
+}
+
+&recurse($ARGV[0]);
+
+sub recurse {
+    my ($dir) = @_;
+
+    if (!-d $dir) {
+	print STDERR "ERROR: $dir isn't a directory\n";
+	return;
+    }
+
+    opendir (DIR, $dir) || die;
+    my @files = readdir DIR;
+    closedir DIR;
+
+    foreach my $file (@files) {
+	next if $file =~ /^\.\.?$/;
+	my $fullpath = "$dir$separator$file";
+	if (-d $fullpath) {
+	    &recurse($fullpath);
+	} elsif ($file =~ /\.html?$/i) {
+	    print STDERR "converting $fullpath\n";
+	    `convert_toc.pl $fullpath $fullpath.new`;
+	    `$move $fullpath.new $fullpath`;
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/delcol.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/delcol.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/delcol.pl	(revision 13928)
@@ -0,0 +1,87 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# delcol.pl --
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use util;
+use parsargv;
+
+sub print_usage {
+    print STDERR "\n";
+    print STDERR "delcol.pl: Deletes (forever) a collection.\n\n";
+    print STDERR "  usage: $0 [options] collection-name\n\n";
+    print STDERR "  options:\n";
+    print STDERR "   -f                     Force deletion of collection without prompting\n\n";
+}
+
+&main();
+
+sub main {
+    my $force = 0;
+    if (!parsargv::parse(\@ARGV, 'f', \$force)) {
+	&print_usage();
+	die "\n";
+    }
+
+    # get and check the collection name
+    if (($collection = &util::use_collection(@ARGV)) eq "") {
+	&print_usage();
+	exit (1);
+    }
+
+    if (!$force) {
+	print STDOUT "Are you sure you want to completely remove the $collection collection?\n";
+	print STDOUT "(the $ENV{'GSDLCOLLECTDIR'} directory will be deleted). [y/n]\n";
+	my $in = <STDIN>;
+	if ($in !~ /^y(es)?$/i) {
+	    print STDOUT "Deletion of $collection collection cancelled\n";
+	    exit (0);
+	}
+    }
+    # delete any temporary files that are laying around
+    my $tmpdir = &util::filename_cat ($ENV{'GSDLHOME'}, "tmp");
+    if (opendir (TMPDIR, $tmpdir)) {
+	my @tmpfiles = readdir (TMPDIR);
+	closedir TMPDIR;
+	map { &util::rm(&util::filename_cat($tmpdir, $_)) if $_ =~ /^$collection/; } @tmpfiles;
+    }
+
+    &util::rm_r ($ENV{'GSDLCOLLECTDIR'});
+
+    # check if everything was deleted successfully
+    if (-d $ENV{'GSDLCOLLECTDIR'}) {
+	print STDERR "\ndelcol.pl WARNING: Not all files in $ENV{'GSDLCOLLECTDIR'} could\n";
+	print STDERR "be deleted\n";
+	exit (2);
+    }
+
+    print STDERR "$collection collection successfully deleted\n";
+    exit (0);
+}
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/downloadfrom.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/downloadfrom.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/downloadfrom.pl	(revision 13928)
@@ -0,0 +1,156 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# downloadfrom.pl -- program to download files from an external server
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 2006 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+package downloadfrom;
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/cpan");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/downloaders");         
+}
+
+use strict;
+no strict 'subs';
+use parse2;
+use download;
+use gsprintf 'gsprintf';
+use printusage;
+
+my $download_mode_list = 
+    [ { 'name' => "Web",
+        'desc' => "{downloadfrom.download_mode.Web}",
+	'downloadname' => "WebDownload" },
+      { 'name' => "OAI",
+        'desc' => "{downloadfrom.download_mode.OAI}",
+	'downloadname' => "OAIDownload" },
+      { 'name' => "Z3950",
+        'desc' => "{downloadfrom.download_mode.Z3950}",
+	'downloadname' => "Z3950Download" },
+      { 'name' => "SRW",
+        'desc' => "{downloadfrom.download_mode.SRW}",
+	'downloadname' => "SRWDownload" } ];
+
+my $arguments = 
+    [ { 'name' => "download_mode",
+	'desc' => "{downloadfrom.download_mode}",
+	'type' => "enum",
+	'list' => $download_mode_list,
+	'reqd' => "yes" },
+      { 'name' => "cache_dir",
+	'desc' => "{downloadfrom.cache_dir}",
+	'type' => "string",
+	'reqd' => "no" },
+      { 'name' => "gli",
+	'desc' => "",
+	'type' => "flag",
+	'reqd' => "no",
+	'hiddengli' => "yes" },
+      { 'name' => "info", ,  
+	'desc' => "{downloadfrom.info}",  
+	'type' => "flag",
+	'reqd' => "no"}
+      ];
+
+my $options = { 'name' => "downloadfrom.pl",
+		'desc' => "{downloadfrom.desc}",
+		'args' => $arguments };
+
+
+# This function return the coresponding mode with a given mode string.
+sub findMode
+{
+    my ($strInput) = @_;
+
+    foreach my $hashMode (@$download_mode_list)
+    {
+	if($strInput eq $hashMode->{'name'})
+	{
+	    return $hashMode->{'downloadname'};
+	}
+    }
+    return "";
+}
+
+# main program
+sub main
+{
+    
+   my $hashOptions = {};
+   my ($strMode,$objMode,$pntArg);
+   $pntArg = \@ARGV;
+
+   # Parsing the General options for downloadfrom.pl, 
+   # this parsing operation will allow extra options, 
+   # since there might be some arguments for Download.
+   # extra arguments will be detected by the Downloads
+   parse2::parse(\@ARGV,$arguments,$hashOptions,"allow_extra_options");
+   # hashOptions: This is a hash map which maps to 
+   #              downloadfrom's arguments
+   #              $hashOptions->{'cache_dir'}
+   #              $hashOptions->{'download_mode'}
+   #              $hashOptions->{'gli'}
+   #              $hashOptions->{'info'}
+
+   $strMode = &findMode($hashOptions->{'download_mode'});
+  
+    if ($strMode eq "") {
+       &gsprintf(STDERR, "{downloadfrom.incorrect_mode}\n");
+       &PrintUsage::print_txt_usage($options, "{downloadfrom.params}");
+       die "\n";
+
+   }
+   $objMode = &download::load_download($strMode, $pntArg);
+   
+   if($hashOptions->{'info'})
+    {
+    
+	my $blnResult = &download::get_information($objMode);
+    }
+    else
+    {
+	print "downloadfrom.pl start gathering data by using $strMode...\n\n";
+	
+	# need to remove trailing slash from cache dir
+	if (defined $hashOptions->{'cache_dir'}) {
+	    $hashOptions->{'cache_dir'} =~ s/[\/\\]$//;
+	}
+	my $blnResult = &download::process($objMode,$hashOptions);
+	
+	($blnResult eq "true")?
+	    print  "\ndownloadfrom.pl has completed data gathering\n":
+	    print "\ndownloadfrom.pl has failed to gather data\n";
+    } 
+
+     
+}
+
+
+&main();
+
+
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/downloadinfo.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/downloadinfo.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/downloadinfo.pl	(revision 13928)
@@ -0,0 +1,206 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# downloadinfo.pl -- prints out information about a download module
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 2006 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+use strict;
+no strict 'subs'; # allow barewords (eg STDERR) as function arguments
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/cpan");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/downloaders");
+}
+
+use download;
+use util;
+use gsprintf;
+use printusage;
+use parse2;
+
+my $arguments =
+    [ { 'name' => "collection",
+	'desc' => "{downloadinfo.collection}",
+	'type' => "string",
+	'reqd' => "no" },
+      { 'name' => "xml",
+	'desc' => "{scripts.xml}",
+	'type' => "flag",
+	'reqd' => "no"},
+      { 'name' => "listall",
+	'desc' => "{scripts.listall}",
+	'type' => "flag",
+	'reqd' => "no" },
+      { 'name' => "describeall",
+	'desc' => "{scripts.describeall}",
+	'type' => "flag",
+	'reqd' => "no" },
+      { 'name' => "language",
+	'desc' => "{scripts.language}",
+	'type' => "string",
+	'reqd' => "no" } ];
+
+my $options = { 'name' => "downloadinfo.pl",
+		'desc' => "{downloadinfo.desc}",
+		'args' => $arguments };
+
+sub gsprintf
+{
+    return &gsprintf::gsprintf(@_);
+}
+
+
+sub main {
+	
+    my $collection = "";
+    my $xml = 0;
+    my $listall = 0;
+    my $describeall = 0;
+    my ($language, $encoding);
+    my $hashParsingResult = {};
+    my $unparsed_args = parse2::parse(\@ARGV,$arguments,$hashParsingResult,"allow_extra_options");
+
+    # parse returns -1 on error
+    if ($unparsed_args == -1) {
+	PrintUsage::print_txt_usage($options, "{downloadinfo.params}");
+	die "\n";
+    }
+
+    foreach my $strVariable (keys %$hashParsingResult)
+    {
+	my $value = $hashParsingResult->{$strVariable};
+	# test to make sure the variable name is 'safe'
+	if ($strVariable !~ /^\w+$/) {
+ 	    die "variable name '$strVariable' isn't safe!";
+	}
+	eval "\$$strVariable = \$value";
+    }
+    
+    # if language wasn't specified, see if it is set in the environment
+    # (LC_ALL or LANG)
+    if (!$language && ($_=$ENV{'LC_ALL'} or $_=$ENV{'LANG'})) {
+	m/^([^\.]+)\.?(.*)/;
+	$language=$1;
+	$encoding=$2; # might be undef...
+# gsprintf::load_language* thinks "fr" is completely different to "fr_FR"...
+	$language =~ s/_.*$//;
+    }
+
+    # If $language has been set, load the appropriate resource bundle
+    # (Otherwise, the default resource bundle will be loaded automatically)
+    if ($language) {
+	gsprintf::load_language_specific_resource_bundle($language);
+	if ($encoding) {
+	    $encoding =~ tr/-/_/;
+	    $encoding = lc($encoding);
+	    $encoding =~ s/utf_8/utf8/; # special
+	    $gsprintf::specialoutputencoding=$encoding;
+	}
+    }
+    
+    # If there is not exactly one argument left (download name), then the arguments were wrong
+    # Or if the user specified -h, then we output the usage also
+
+    if((@ARGV && $ARGV[0] =~ /^\-+h/) )
+    {
+	PrintUsage::print_txt_usage($options, "{downloadinfo.params}");
+	die "\n";
+    }
+    
+    # If there is not exactly 1 argument left (download name), then the arguments were wrong (apart from if we had listall or describeall set)
+    if ($listall == 0 && $describeall ==0 && $unparsed_args == 0) {
+	gsprintf(STDERR, "{downloadinfo.no_download_name}\n\n");
+	PrintUsage::print_txt_usage($options, "{downloadinfo.params}", 1);
+	die "\n";
+    }
+
+    # we had some arguments that we weren't expecting
+    if ($unparsed_args > 1) {
+	pop(@ARGV); # assume that the last arg is the download name
+	gsprintf(STDERR, "{common.invalid_options}\n\n", join (',', @ARGV));
+	PrintUsage::print_txt_usage($options, "{downloadinfo.params}", 1);
+	die "\n";
+    }
+    my $download_name = shift (@ARGV);
+    if (defined $download_name) {
+	$download_name =~ s/\.pm$//; # allow xxx.pm as the argument
+    }
+
+    if ($collection ne "") {
+	$ENV{'GSDLCOLLECTDIR'} = &util::filename_cat ($ENV{'GSDLHOME'}, "collect", $collection);
+    } else {
+	$ENV{'GSDLCOLLECTDIR'} = $ENV{'GSDLHOME'};
+    }
+
+    if ($listall || $describeall) {
+	my $downloaders_dir = &util::filename_cat($ENV{'GSDLCOLLECTDIR'}, "perllib", "downloaders");
+	my @downloader_list = ();
+	if (opendir (INDIR, $downloaders_dir)) {
+	    @downloader_list = grep (/Download\.pm$/, readdir (INDIR));
+	    closedir (INDIR);
+	}
+
+	print STDERR "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+	print STDERR "<DownloadList length=\"" . scalar(@downloader_list) . "\">\n";
+	foreach my $downloader (@downloader_list) {
+	    $downloader =~ s/\.pm$//;
+	    my $downloaderobj = &download::load_download ($downloader);
+	    if ($describeall) {
+		$downloaderobj->print_xml_usage(0);
+	    }
+	    else {
+		$downloaderobj->print_xml_usage(0, 1);
+	    }
+	}
+	print STDERR "</DownloadList>\n";
+    }
+    else {
+	&print_single_download($download_name, $xml, 1);
+    }
+}
+
+
+sub print_single_download {
+    my ($download, $xml, $header) = @_;
+    my @options  = ("-gsdlinfo");
+    my $downloadobj = &download::load_download ($download, \@options );
+    if ($xml) {
+	$downloadobj->print_xml_usage($header);
+    }
+    else {
+	gsprintf(STDERR, "{downloadinfo.option_types}:\n\n");
+	gsprintf(STDERR, "{downloadinfo.specific_options}\n\n");
+	gsprintf(STDERR, "{downloadinfo.general_options}\n\n");
+	gsprintf(STDERR, "$download {common.info}:\n\n");
+	
+	$downloadobj->print_txt_usage();
+    }
+    
+}
+
+&main ();
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/expand_macros.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/expand_macros.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/expand_macros.pl	(revision 13928)
@@ -0,0 +1,1300 @@
+#! /usr/bin/perl
+
+##################################################################################
+#                                                                                #
+# expand_macros.pl -- recursively expand greenstone macros / 1080805 - 1230106   #
+#                                                                                #
+# Copyright (C) 2005,2006 Jens Wille <j_wille at gmx.net>                        #
+#                                                                                #
+# This program is free software; you can redistribute it and/or                  #
+# modify it under the terms of the GNU General Public License                    #
+# as published by the Free Software Foundation; either version 2                 #
+# of the License, or (at your option) any later version.                         #
+#                                                                                #
+# This program 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 for more details.                                   #
+#                                                                                #
+# You should have received a copy of the GNU General Public License              #
+# along with this program; if not, write to the Free Software                    #
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.    #
+#                                                                                #
+##################################################################################
+
+#
+# expand_macros.pl reads in specified greenstone macro files and prints the
+# definitions of requested macros and recursively the definitions of macros
+# used within these definitions.
+#
+#
+# FEATURES:
+#
+# - generic:
+#
+#   - additional/collection-specific macro files can be included
+#
+#   - macros set within the server can be included (though this might not be
+#     of much help without reading the respective source file)
+#
+# - "interactive browse mode" where you can select which macro (and from which
+#   package) to display next.
+#
+#   - readline support and persistent history
+#
+#   - interactive commands
+#
+#   - read files from within interactive browse mode
+#
+# - batch mode only:
+#
+#   - search for macros that use certain macros ("reverse" search)
+#
+#   - search for strings (regular expressions) in macro definitions
+#
+#
+# TODO:
+#
+# - add "reverse search" and "string search" for browse mode
+#
+# - handle macro options better (v, c, l, ...?)
+#
+# - implement some kind of "persistent" macro db (so that it doesn't need to be
+#   built each and every time)
+#
+#
+# KNOWN ISSUES:
+#
+# - for a sufficiently large file (> 12288 bytes == 12 k) (paged-)read will quit
+#   the program if not scrolled until the end of the file => SIGPIPE: broken pipe!
+#   SOLVED: the PIPE signal will simply be IGNOREd
+#
+
+use strict;
+use warnings;
+
+use Getopt::Long          qw(GetOptions);
+
+use File::Basename        qw(basename dirname);
+use File::Spec::Functions qw(catdir catfile curdir);
+
+use IO::Handle            qw(autoflush);
+STDOUT->autoflush(1);
+
+use Term::ReadLine;
+
+
+### progname and version
+
+my $NAME    = basename $0;
+my $VERSION = '0.22';
+
+
+### global patterns
+
+# my understanding of greenstone macro names:
+#   - enclosed in underscores ('_')
+#   - starts with a letter ([:alpha:])
+#   - followed by alphanumeric characters ([:alnum:])
+#     (consequently, it doesn't start with a number and
+#     particularly isn't a macro parameter, i.e. something like _1_)
+#   - also we might need to take care of escaped underscores ('\_')
+#
+#   => does this fit??? (see '<gsdl-source>/src/lib/display.cpp' for details,
+#      in particular the 'displayclass::loadparammacros' method)
+my $MACRO_PATTERN       = '[[:alpha:]][[:alnum:]]*';
+
+# package names: letters
+my $PACKAGE_NAME        = '[[:alpha:]]+';
+
+# package specification: package name followed by a colon (':')
+my $PACKAGE_PATTERN     = $PACKAGE_NAME . ':';
+
+# beginning/end of macro specification: underscore ('_'), not escaped,
+# i.e. not preceded by a backslash ('\')
+# (need to double-escape backslash here!)
+my $MACRO_AFFIX         = '(?<!\\\)_';
+
+# beginning of macro definition: opening curly bracket ('{')
+my $DEFINITION_START    = '\{';
+
+# end of macro definition: closing curly bracket ('}'), not escaped,
+# i.e. not preceded by a backslash ('\')
+# (need to double-escape backslash here!)
+my $DEFINITION_END      = '(?<!\\\)\}';
+
+# package declaration: 'package' (plus package name)
+my $PACKAGE_DECLARATION = 'package';
+
+
+### command line arguments
+
+# variable initialisation and default values
+my %ARG = (
+  'verbose'     => 0,
+  'version'     => 0,
+  'depth'       => 0,
+  'short'       => 0,
+  'reverse'     => 0,
+  'interactive' => 0,
+  'paged'       => 0,
+  'pager'       => $ENV{'PAGER'} || 'less',
+  'histfile'    => catfile($ENV{'HOME'} || curdir, '.expand_macros.history'),
+  'histsize'    => 100,
+  'macro_dirs'  => [catdir($ENV{'GSDLHOME'}, 'macros')],
+  'source_dir'  => $ENV{'GSDLSOURCE'} || '',
+  'args'        => []
+);
+
+# global vars
+my $TERM         = '';
+my $CURRENT_FILE = '';
+
+# usage information and help text
+my $USAGE = <<HERE_USAGE;
+usage:
+    $NAME [generic-options] [-s] [-d <depth>] [-r] {_[<package>:]<macro>_|<query>} ...
+    $NAME [generic-options] {-b|-i} [-p]
+    $NAME [-h|-?|--help]
+
+    generic options are: [-v] [-e <directory>,...] [-n <version>]
+HERE_USAGE
+
+my $HELP = <<HERE_HELP;
+$NAME: recursively expand greenstone macros (v$VERSION)
+
+$USAGE
+
+generic options:
+
+    -h, -?, --help                   display this help and exit
+    -v,     --verbose                output some extra information/warnings
+
+    {-e|--extra} <directory>,...     paths to extra macro directories, comma-separated list
+                                     [default directory: '$ARG{'macro_dirs'}[0]']
+
+            --source <directory>     path to greenstone source directory, so that macros which are
+                                     set within the server will be included
+                                     [default: '$ARG{'source_dir'}']
+                                     NOTE: you can set an environment variable GSDLSOURCE instead
+
+    {-n|--show-version} <version>    print only macro definitions for specified version (0=graphic/1=text)
+                                     [default: '$ARG{'version'}', set to '-1' for 'all']
+
+    -s,     --short                  short output, i.e. only macro names, no content
+
+
+batch mode:
+
+    {-d|--depth} <depth>             how deep to recurse through macros
+                                     [default: '$ARG{'depth'}', set to '-1' for 'unlimited']
+
+    -r,     --reverse                reverse search, recursively outputs the macros which use the specified macro
+
+    all non-option arguments will be treated as
+      - macro names (denoted by surrounding underscores '_')
+        or
+      - regular expressions to search for in macro definitions (otherwise)
+
+    (you can restrict your macro name query to a certain package by prepending the macro name with '<package-name>:')
+
+    EXAMPLES:
+
+      get definition of the 'pagescriptextra' macro
+      > $NAME _pagescriptextra_
+
+      get definition of the 'pagescriptextra' macro, package 'query' only
+      > $NAME _query:pagescriptextra_
+
+      get definition of the 'pagescriptextra' macro, package 'query' only -- and recursively get definitions of
+      macros used within that definition (up to level 2)
+      > $NAME -d 2 _query:pagescriptextra_
+
+      get all the macros that use the 'pagescriptextra' macro (names only)
+      > $NAME -r -s _pagescriptextra_
+
+
+interactive browse mode:
+
+    -b, -i, --browse                 interactive browse mode, allows you to select what to display next
+
+    -p,     --paged                  data output will be passed to a pager
+                                     [default: '$ARG{'pager'}']
+            --pager <pager>          pass paged output to specified pager instead of above named default
+
+            --histfile <file>        path to history file to keep history between sessions
+                                     [default: '$ARG{'histfile'}']
+            --histsize <num>         maximum number of lines to keep in histfile
+                                     [default: '$ARG{'histsize'}']
+                                     NOTE: in case you don\'t want the history to be stored you may set
+                                           <histfile> to '' or <histsize> to '0'
+                                           (however, this does not remove any existing history files)
+
+
+NOTE: for this script to run your greenstone environment needs to be set up (GSDLHOME set)
+HERE_HELP
+
+my $HELP_INTERACTIVE = <<HERE_HELP;
+$NAME: expand greenstone macros in ***interactive browse mode*** (v$VERSION)
+
+
+usage instructions:
+
+    - commands are equal to command line options, except that they start with a dot '.'
+      (NOTE: not all command line options are available as commands, see list below)
+
+    - commands that take an optional argument ([...]) will print their current value if
+      that argument is omitted (you can also use '.c' or '.config' to get a full overview)
+
+    - you can run several commands at once by separating them with semicolons
+
+    - you can quit the program at any time by hitting <ctrl>+d (<ctrl>+z on windows), or
+      by typing '.q', or '.quit'
+
+
+commands:
+
+    .h, .?, .help                    display this help
+
+    .q,     .quit                    exit program
+
+    .                                redisplay current stage
+
+    ..                               return to previous stage (same as leaving empty)
+
+    ..., .t, .top                    return to top to enter new macro name
+
+    {.n|.show-version} [<version>]   print only macro definitions for specified version (0=graphic/1=text)
+                                     [default: '0', set to '-1' for 'all']
+
+    .s,     .short                   short output, i.e. only macro names, no content
+
+    .p,     .paged                   data output will be passed to a pager
+                                     [default: '$ARG{'pager'}']
+            .pager [<pager>]         pass paged output to specified pager instead of above named default
+
+    .r,     .read [<file>]           display the contents of the specified file (by default the last file we came across)
+    .pr,    .paged-read [<file>]     same, but paged (without turning on paged mode permanently)
+
+    .c,     .config                  display current configuration
+HERE_HELP
+
+# allow for bundling of options
+Getopt::Long::Configure ("bundling");
+
+# parse arguments
+GetOptions( 'help|h|?'         => sub { print "$HELP\n"; exit 0 },
+            'verbose|v'        => \$ARG{'verbose'},
+            'only-version|n=i' => \$ARG{'version'},
+            'extra|e=s'        => \@{$ARG{'macro_dirs'}},
+            'source=s'         => \$ARG{'source_dir'},
+            'depth|d=i'        => \$ARG{'depth'},
+            'short|s'          => \$ARG{'short'},
+            'reverse|r'        => \$ARG{'reverse'},
+            'browse|b|i'       => \$ARG{'interactive'},
+            'paged|p'          => \$ARG{'paged'},
+            'pager=s'          => \$ARG{'pager'},
+            'histfile=s'       => \$ARG{'histfile'},
+            'histsize=i'       => \$ARG{'histsize'},
+            '<>'               => sub { push(@{$ARG{'args'}} => @_) } )
+  or die "$USAGE\n";
+
+
+### some sanity checks (dunno which one to check first ;-)
+
+# need one of our "actions": batch, query or interactive
+# ("batch" requiring at least one macro name or regexp specified)
+unless (@{$ARG{'args'}} || $ARG{'interactive'}) {
+  warn "$USAGE";
+
+  warn <<HERE_WARN unless $ENV{'GSDLHOME'};
+
+GSDLHOME not set!
+
+for this script to run your greenstone environment needs to be set up. please
+change into the directory where greenstone has been installed and run/source
+the appropriate setup script.
+HERE_WARN
+
+  die "\n";
+}
+
+# need GSDLHOME for default macro directory
+# (does also allow to have the script in gsdl bin path)
+die "GSDLHOME not set! please change into the directory where greenstone has been installed and run/source the appropriate setup script.\n"
+  unless $ENV{'GSDLHOME'};
+
+## need one of our "actions": batch, query or interactive
+# ("batch" requiring at least one macro name or regexp specified)
+#die "$USAGE\n"
+#  unless @{$ARG{'args'}} || $ARG{'interactive'};
+
+
+### action!
+
+# build hash of macro information
+my %macro_db = build_db();
+die "macro db empty!\n"
+  unless %macro_db;
+
+unless ($ARG{'interactive'}) {
+  # batch mode
+
+  my $n = 0;
+  foreach my $arg (@{$ARG{'args'}}) {
+    if ($arg =~ s/^$MACRO_AFFIX((?:$PACKAGE_PATTERN)?$MACRO_PATTERN)$MACRO_AFFIX$/$1/) {
+      # macro
+
+      print "*** macro: $arg", ($ARG{'reverse'} ? ' (reverse) ' : ' '), "***\n\n";
+
+      unless ($ARG{'reverse'}) {
+        # "normal" search
+
+        get_macro($arg);
+      }
+      else {
+        # "reverse" search
+
+        # get the macros that use the specified macro
+        my @refs = get_r_macros($arg);
+        print "no macro referencing '$arg'\n\n"
+          unless @refs;
+
+        # now recurse those macros
+        get_macro($_)
+          foreach @refs;
+      }
+    }
+    else {
+      # query
+
+      print "*** query: $arg", ($ARG{'reverse'} ? ' (reverse) ' : ' '), "***\n\n";
+
+      # get the macros that match the specified query
+      my @macros = get_r_macros($arg, 1);
+      print "no matches for '$arg'\n", ($ARG{'short'} ? '' : "\n")
+        unless @macros;
+
+      # now print those macros
+      get_macro($_)
+        foreach @macros;
+    }
+
+    # print separator _between_ requested macros (i.e. everytime but the last time)
+    # (need to add extra newline for short display)
+    print(($ARG{'short'} ? "\n" : ''), '-' x 80, "\n\n")
+      unless ++$n >= @{$ARG{'args'}};
+  }
+}
+else {
+  # interactive browse mode
+
+  # ignore 'broken pipe' error
+  $SIG{'PIPE'} = 'IGNORE';
+
+  # get the pager executable (no need to test if not in "paged" mode)
+  get_pager()
+    if $ARG{'paged'};
+
+  # create new Term::ReadLine object
+  $TERM = Term::ReadLine->new($NAME);
+
+  # don't want the prompt underlined
+  $TERM->ornaments(0);
+  # don't want autohistory (can't set autohistory explicitly, so use this "workaround")
+  $TERM->MinLine(undef);
+
+  # restore history
+  readhist();
+
+  # print help hint
+  print <<HERE_HINT;
+entered '$NAME' in ***interactive browse mode*** (v$VERSION)
+[you can get help at any time by typing '.h', '.?', or '.help']
+
+HERE_HINT
+
+  # repeat until explicit exit
+  while (1) {
+    my $macro = prompt("enter macro name (without package specification) [leave empty to quit]\n> ");
+
+    # remove surrounding '_'
+    $macro =~ s/^_//;
+    $macro =~ s/_$//;
+
+    exit 0 unless length $macro;                    # normal exit
+    next   if     $macro eq '0' || $macro eq '-1';  # a command was executed
+
+    # now get all packages for given macro, and begin recursion...
+    recurse_packages($macro);
+  }
+
+  # can't expect anything down here to be executed
+}
+
+END {
+  if ($ARG{'interactive'}) {
+    # save history
+    savehist();
+  }
+}
+
+
+### that's it ;-)
+
+exit 0;
+
+
+### subroutines
+
+# <sub build_db>
+# build hash of macro information ("macro db")
+#
+# hash structure:
+#   macro
+#   -> package
+#      -> {'0=graphic'|'1=text'}
+#         -> 'file'
+#         -> 'line'
+#         -> 'content'
+#
+# usage:
+#   %macro_db = build_db()
+#
+#  => macro_db: returned hash ("macro db")
+#
+sub build_db {
+  my %macro_db = ();
+  my @dm_list  = ();
+  my ($n, $m) = (0, 0);
+
+  # get all macro files (*.dm) from specified directories
+  foreach my $dir (@{$ARG{'macro_dirs'}}) {
+    opendir(DIR, "$dir")
+      or die "can't read macro directory '$dir': $!\n";
+
+    push(@dm_list => map { $_ = catfile($dir, $_) } grep { /\.dm$/ } readdir(DIR));
+
+    closedir DIR;
+  }
+
+  # now parse each macro file and build hash
+  foreach my $dm (sort @dm_list) {
+    open(DM, "< $dm")
+      or die "can't open macro file '$dm': $!\n";
+
+    my ($name, $content, $version, $curpkg, $contd)
+     = ('',    '',       '0',      '',      0);
+
+    while (my $line = <DM>) {
+      chomp($line);
+      next unless length $line;      # skip empty lines
+      next if     $line =~ /^\s*$/;  # skip "empty" lines
+      next if     $line =~ /^\s*#/;  # skip comments (hope this doesn't affect
+                                     # cases we actually wanted to keep)
+
+      if    ($line =~ /^$PACKAGE_DECLARATION\s*($PACKAGE_NAME)/) {
+        # remember the current package we are in
+        $curpkg = $1;
+      }
+      elsif ($line =~ /$MACRO_AFFIX($MACRO_PATTERN)$MACRO_AFFIX\s*(\[v=1\])?\s*$DEFINITION_START\s*(.*)/) {
+        # start of macro definition
+        $n++;
+
+        $name    = $1;
+        $version = (defined $2 && $2 eq '[v=1]') ? '1' : '0';
+        $content = $3 || '';
+
+        # don't include unnecessary version, unless we're interactive (where version may change during session)
+        next if $ARG{'version'} ne '-1' && $version ne $ARG{'version'} && ! $ARG{'interactive'};
+
+        if (exists $macro_db{$name}->{$curpkg}->{$version}) {
+          # everytime a macro definition already exists, it's simply
+          # overwritten - but we can give a warning
+          # (this might also serve debugging purposes)
+          $m++;
+
+          warn <<HERE_WARN if $ARG{'verbose'};
+duplicate definition of macro '$curpkg:$name' [v=$version] at '$dm', line $.
+(previously defined at $macro_db{$name}->{$curpkg}->{$version}->{'file'}, line $macro_db{$name}->{$curpkg}->{$version}->{'line'})
+HERE_WARN
+        }
+
+        # store the information we got so far
+        $macro_db{$name}->{$curpkg}->{$version}->{'file'}    = $dm;
+        $macro_db{$name}->{$curpkg}->{$version}->{'line'}    = $.;
+        $macro_db{$name}->{$curpkg}->{$version}->{'content'} = [$content] if length $content;
+
+        # is the macro definition already finished?
+        $contd = ($content =~ s/\s*$DEFINITION_END.*//) ? 0 : 1;
+      }
+      elsif ($contd) {
+        # continuation of macro definition
+
+        # store additional content
+        push(@{$macro_db{$name}->{$curpkg}->{$version}->{'content'}} => $line);
+
+        # is the macro definition already finished?
+        $contd = ($line =~ s/\s*$DEFINITION_END.*//) ? 0 : 1;
+      }
+      else {
+        # something else...
+
+        ($name, $content) = ('', '');
+      }
+    }
+
+    close DM;
+  }
+
+  # get server macros (overwriting already read macros)
+  if (length $ARG{'source_dir'}) {
+    if (-r $ARG{'source_dir'}) {
+      my $recpt_dir = catdir($ARG{'source_dir'}, 'src', 'src', 'recpt');
+      my @cpp_list  = ();
+
+      opendir(DIR, "$recpt_dir")
+        or die "can't read receptionist's source directory '$recpt_dir': $!\n";
+
+      push(@cpp_list => map { $_ = catfile($recpt_dir, $_) } grep { /\.cpp$/ } readdir(DIR));
+
+      close DIR;
+
+      foreach my $cpp (@cpp_list) {
+        open(CPP, "< $cpp")
+          or die "can't open source file '$cpp': $!\n";
+
+        my $args  = '';
+        my $contd = 0;
+        while (my $line = <CPP>) {
+          next unless $line =~ /disp\.setmacro\s*\((.*)/ || $contd;
+
+          unless (defined $1) {
+            $contd = 1;
+            next;
+          }
+
+          my $string = $1;
+
+          if    ($string =~ s/\);\s*$//) {
+            $args .= $string;
+            my ($name, $package, $value) = split(/\s*,\s*/ => $args, 3);
+
+            $name    =~ s/^\s*["']?//;
+            $name    =~ s/["']?\s*$//;
+            $package =~ s/^\s*["']?//;
+            $package =~ s/["']?\s*$//;
+
+            $package = 'Global'
+              if $package eq 'displayclass::defaultpackage';
+
+            $macro_db{$name}->{$package}->{'0'}->{'file'}    = 'SERVER: ' . $cpp;
+            $macro_db{$name}->{$package}->{'0'}->{'line'}    = $.;
+            $macro_db{$name}->{$package}->{'0'}->{'content'} = [$value];
+
+            $args = '';
+            ++$n;
+            $contd = 0;
+          }
+          elsif ($contd) {
+            $args .= ' ' . $string;
+          }
+          else {
+            $contd = 1;
+          }
+        }
+
+        close CPP;
+      }
+    }
+    else {
+      warn "can't find source directory '$ARG{'source_dir'}'! server macros will not be included\n";
+    }
+  }
+
+  # print some statistics
+  print "$n total macro definitions, $m duplicates\n"
+    if $ARG{'verbose'};
+
+  # we stored all information there is so we can return it
+  return %macro_db;
+}
+# </sub build_db>
+
+# <sub get_macro>
+# recursively print macro information
+#
+# usage:
+#   get_macro($macro[, $level])
+#
+#   macro:    macro name (optionally including package specification)
+#   level:    recursion level (optional)
+#
+#   => VOID CONTEXT
+#
+sub get_macro {
+  my ($macro, $level) = @_;
+  $level ||= 0;
+
+  # indent output according to recursion level
+  my $indent  = '    ' x $level;
+
+  # get all the packages which our macro is defined in
+  ($macro, my @packages) = get_packages($macro, $indent);
+  return unless @packages;
+
+  # macro definitions may occur in several packages so we display them all
+  # (unless a certain package was explicitly specified)
+  foreach my $pkg (@packages) {
+    foreach my $version (sort keys %{$macro_db{$macro}->{$pkg}}) {
+      print "$indent* $pkg:$macro [v=$version] ($macro_db{$macro}->{$pkg}->{$version}->{'file'}, line $macro_db{$macro}->{$pkg}->{$version}->{'line'})\n";
+
+      my $content = '';
+      # some macros are defined, but don't have any content
+      if (defined $macro_db{$macro}->{$pkg}->{$version}->{'content'}) {
+        # for batch display we condense the output a little bit...
+        map { s/^\s*//; s/\s*$// } @{$macro_db{$macro}->{$pkg}->{$version}->{'content'}};
+        # ...and put it on a single line
+        $content = join(' ' => @{$macro_db{$macro}->{$pkg}->{$version}->{'content'}});
+      }
+      print "$indent  { $content }\n\n"
+        unless $ARG{'short'};
+        # short display only, i.e. no content
+        # of the macro's definition
+
+      # only go (deeper) into referenced macros if we
+      # haven't reached the specified recursion level
+      if ($ARG{'depth'} eq '-1' || $level < $ARG{'depth'}) {
+        # get (referencing|referenced) macros...
+        my @refs = $ARG{'reverse'}
+                 ? get_r_macros($macro)
+                 : get_macros($content);
+
+        # ...and recurse above them (with increased recursion level)
+        foreach my $ref (@refs) {
+          get_macro($ref, $level + 1);
+        }
+      }
+    }
+  }
+}
+# </sub get_macro>
+
+# <sub get_macros>
+# returns a list of macros extracted from a content string
+# or a boolean value if a macro name was specified
+#
+# usage:
+#   @macros  = get_macros($content)
+#   $boolean = get_macros($content, $macro)
+#
+#   content: content string
+#   macro:   macro name
+#
+#   => macros:  list of macros
+#   => boolean: boolean value (true = 1 / false = empty list)
+#
+sub get_macros {
+  my ($content, $macro) = @_;
+  my @macro_list = ();
+  my %seen       = ();
+
+  # get each macro reference in the string
+  # (for macro name considerations see above)
+  while ($content =~ /$MACRO_AFFIX((?:$PACKAGE_PATTERN)?$MACRO_PATTERN)$MACRO_AFFIX/g) {
+    my $m = $1;
+
+                           # we want to skip some macros that have no content anyway (defined
+                           # from within the server) - unless we're doing a "reverse" search
+    next if $seen{$m}++ || ($m =~ /^(cgiarg.*|histvalue\d+|if|httpimg|gwcgi|(decoded)?compressedoptions)$/i
+                            && ! $ARG{'reverse'});
+
+    if (defined $macro) {
+      # is this the macro we wanted? then the current
+      # macro uses it => return true
+      return 1 if $m =~ /^(?:$PACKAGE_PATTERN)?$macro$/;
+    }
+    else {
+      # add macro to our list
+      push(@macro_list => $m);
+    }
+  }
+
+  # return the list of used macros
+  # (this evaluates to false (empty list) if there are no further
+  # macro calls or if this macro doesn't use the sought-after macro)
+  return sort @macro_list;
+}
+# </sub get_macros>
+
+# <sub get_r_macros>
+# returns a list of macro names which reference ("use") the
+# specified macro or match the query
+#
+# usage:
+#   @macros = get_r_macros($macro)
+#   @macros = get_r_macros($query, $is_query)
+#
+#   macro:    macro name
+#   query:    query string (regular expression)
+#   is_query: boolean value to indicate whether arg is a query or a macro
+#
+#   => macros: list of macros
+#
+sub get_r_macros {
+  my ($arg, $query) = @_;
+  $query ||= 0;
+  my %refs = ();
+
+  # need to test each single macro's...
+  foreach my $m (sort keys %macro_db) {
+    # ...each single package
+    foreach my $p (sort keys %{$macro_db{$m}}) {
+      foreach my $v (sort keys %{$macro_db{$m}->{$p}}) {
+        my $pm = "$p:$m";  # include package information in the macro name!
+
+        # does this macro have any content?
+        if (defined $macro_db{$m}->{$p}->{$v}->{'content'}) {
+          # stringify content!
+          my $content = join(' ' => @{$macro_db{$m}->{$p}->{$v}->{'content'}});
+
+          if ($query) {
+            # search regexp
+            $refs{$pm}++ if $content =~ /$arg/;
+          }
+          else {
+            # search macro
+            $refs{$pm}++ if get_macros($content, $arg);
+          }
+        }
+      }
+    }
+  }
+
+  # now we have all the macros which use our sought-after
+  return sort keys %refs;
+}
+# </sub get_r_macros>
+
+# <sub recurse_packages>
+# recurse all packages for a given macro
+#
+# usage:
+#   recurse_packages($macro)
+#
+#   macro:    macro name (any package specification will be dropped)
+#
+#   => VOID CONTEXT
+#
+sub recurse_packages {
+  my ($macro) = @_;
+
+  # repeat until explicit break/exit
+  while (1) {
+    # get all the packages which our macro is defined in
+    #($macro, my @packages) = get_packages($macro);
+    #return unless @packages;
+    my @packages = ();
+
+    my $n = 0;
+    my $package = '';
+    # ask for user's selection...
+    do {
+      # get all the packages which our macro is defined in
+      ($macro, @packages) = get_packages($macro);
+      return unless @packages;
+
+      # ask for user's selection...
+      print "select package for macro '$macro' [leave empty to return]\n";
+      foreach my $pkg (@packages) {
+        printf "    [%d]%s %s\n", ++$n, " " x (4 - length $n), $pkg;
+      }
+      $package = prompt();
+      $n = 0;
+    # ...until we return...
+    } until ($package eq '' || $package eq '-1'
+         # ...or a valid number is provided
+         || ($package =~ /^\d+$/ && $package > 0 && $package <= @packages));
+
+    return unless length $package;          # return to previous stage
+    return '-1'   if     $package eq '-1';  # return to top
+
+    # set selected package
+    $package = $packages[$package - 1];
+
+    foreach my $version (sort keys %{$macro_db{$macro}->{$package}}) {
+                  # all versions
+      next unless $ARG{'version'} eq '-1'
+                  # desired version
+               || $version eq $ARG{'version'}
+                  # fallback to 'graphic'
+               || ($version eq '0' && ! exists $macro_db{$macro}->{$package}->{'1'});
+
+                    # some macros are defined, but don't have any content
+      my $content = defined $macro_db{$macro}->{$package}->{$version}->{'content'}
+                    # now we want to retain the original structure
+                  ? join("\n" => @{$macro_db{$macro}->{$package}->{$version}->{'content'}})
+                  : '';
+
+      ($CURRENT_FILE = $macro_db{$macro}->{$package}->{$version}->{'file'}) =~ s/^SERVER: //;
+
+      my $content_string = "* $package:$macro [v=$version] ($macro_db{$macro}->{$package}->{$version}->{'file'}, line $macro_db{$macro}->{$package}->{$version}->{'line'})\n";
+      $content_string   .= "{ $content }\n"
+        unless $ARG{'short'};
+
+      print_output($content_string);
+
+      # now on to the macros referenced within this one
+      my $return = recurse_macros($content);
+
+      return $return if defined $return;
+    }
+  }
+}
+# </sub recurse_packages>
+
+# <sub get_packages>
+# returns list of packages for specified macro, also returns
+# modified macro name (without surrounding '_' and package specification)
+#
+# usage:
+#   ($macro, @packages) = get_packages($macro)
+#
+#   macro:    macro name
+#
+#   => macro:    modified macro name
+#   => packages: list of packages
+#
+sub get_packages {
+  my ($macro, $indent) = @_;
+  $indent ||= '';
+
+  # save original macro name (including package specification)
+  my $omacro = $macro;
+
+  my @packages = ();
+
+  if ($macro =~ /^($PACKAGE_PATTERN)?$MACRO_PATTERN$/) {
+    # valid macro name
+
+    # strip off package specification
+    my $package = ($macro =~ s/^($PACKAGE_NAME)://) ? $1 : '';
+
+    if (exists $macro_db{$macro}) {
+      # valid/existing macro
+
+      unless ($ARG{'interactive'}) {
+        if (length $package) {
+          # account for package specification
+
+          @packages = ($package)
+            if exists $macro_db{$macro}->{$package};
+        }
+        else {
+          # get all packages otherwise
+
+          @packages = sort keys %{$macro_db{$macro}};
+        }
+      }
+      else {
+        foreach my $pkg (sort keys %{$macro_db{$macro}}) {
+          push(@packages => $pkg)
+               # all versions
+            if $ARG{'version'} eq '-1'
+               # desired version
+            || exists $macro_db{$macro}->{$pkg}->{$ARG{'version'}}
+               # fallback to 'graphic'
+            || exists $macro_db{$macro}->{$pkg}->{'0'};
+        }
+      }
+    }
+  }
+  else {
+    # invalid macro name
+
+    warn "invalid macro name '$macro'!\n";
+    return;  # skip it
+  }
+
+  # no packages - no definition
+  unless (@packages) {
+    print "$indent- $omacro\n$indent  no definition for macro!\n\n";
+    return;  # skip it
+  }
+
+  # return modified macro name and packages found
+  return $macro, sort @packages;
+}
+# </sub get_packages>
+
+# <sub recurse_macros>
+# recurse all macros for a given content string
+#
+# usage:
+#   recurse_macros($content)
+#
+#   content:  content string
+#
+#   => VOID CONTEXT
+#
+sub recurse_macros {
+  my ($content) = @_;
+
+  # repeat until explicit break/exit
+  while (1) {
+    # get all the macros referenced within the current one
+    my @macros = get_macros($content);
+    return unless @macros;
+
+    my $n = 0;
+    my $macro = ''; 
+    # ask for user's selection...
+    do {
+      print "select macro [leave empty to return]\n";
+      foreach my $m (@macros) {
+        printf "    [%d]%s %s\n", ++$n, " " x (4 - length $n), $m;
+      }
+      $macro = prompt();
+      $n = 0;
+    # ...until we return...
+    } until ($macro eq '' || $macro eq '-1'
+         # ...or a valid number is provided
+         || ($macro =~ /^\d+$/ && $macro > 0 && $macro <= @macros));
+
+    return unless length $macro;          # return to previous stage
+    return '-1'   if     $macro eq '-1';  # return to top
+
+    # set selected macro
+    $macro = $macros[$macro - 1];
+
+    # now we want all the macro's packages again
+    my $return = recurse_packages($macro);
+
+    return $return if defined $return;
+  }
+}
+# </sub recurse_macros>
+
+# <sub prompt>
+# prompt for user input
+#
+# usage:
+#   $reply = prompt([$prompt])
+#
+#   prompt:  optional prompt (default: '> ')
+#
+#   => reply: user input
+#
+sub prompt {
+  my $prompt = shift || '> ';
+  my $term   = $TERM;
+
+  # read user input
+  my $reply = $term->readline($prompt);
+
+  if (defined $reply) {
+    # add input to history, unless it's just a number
+    $term->addhistory($reply)
+      if $reply =~ /[[:alpha:]]/;
+
+    if ($reply =~ s/^\s*["']*\s*\././) {
+      # execute command
+      my $return = parse_command($reply);
+
+      return $return if defined $return;
+    }
+    else {
+      return $reply;
+    }
+  }
+
+  # allow for exiting by hitting <ctrl>+d,
+  # or quitting by command (.q, .quit)
+  die "\n";
+}
+# </sub prompt>
+
+# <sub print_output>
+# print output, paged or not
+#
+# usage:
+#   print_output($output)
+#   print_output(@output)
+#
+#   output: text to print
+#
+#   => VOID CONTEXT
+#
+sub print_output {
+  my $output = join('' => @_);
+
+  if ($ARG{'paged'}) {
+    # pass output to pager
+    open(PAGER, "| $ARG{'pager'}")
+      or die "can't open pipe to '$ARG{'pager'}': $!";
+
+    print PAGER "$output";
+
+    close PAGER;
+  }
+  else {
+    # print to standard out...
+    print "\n$output\n";
+
+    # ...and wait for user reaction to continue
+    wait_for_user();
+  }
+}
+# </sub print_output>
+
+# <sub wait_for_user>
+# wait for user reaction to continue
+#
+# usage:
+#   wait_for_user()
+#
+#   => VOID CONTEXT
+#
+sub wait_for_user {
+  print "[press key to continue]";
+  print "\n" if <STDIN>;
+}
+# </sub wait_for_user>
+
+# <sub parse_command>
+# prompt for user input
+#
+# usage:
+#   parse_command($command_line)
+#
+#   command_line: command string
+#
+#   => VOID CONTEXT
+#
+sub parse_command {
+  my $command_line = shift;
+  my @commands = split(/\s*;\s*/ => $command_line);
+
+  my $return = 0;
+
+  foreach my $command (@commands) {
+    my $msg = "command executed: '$command'";
+
+    $command =~ s/^\.//;
+    $command =~ s/^(\w+)["']*/$1/;
+    $command =~ s/\s*$//;
+
+    if    ($command =~ /^(h|\?|help)$/) {
+      print "$HELP_INTERACTIVE\n";
+
+      # wait for user reaction to continue
+      wait_for_user();
+
+      next;
+    }
+    elsif ($command =~ /^(q|quit)$/) {
+      return undef;
+    }
+    elsif ($command =~ /^(\.)$/) {
+      $return = '';
+
+      next;
+    }
+    elsif ($command =~ /^(\..|t|top)$/) {
+      $return = '-1';
+
+      next;
+    }
+    elsif ($command =~ /^(n|show-version)(?:\s+["']*(0|1|-1)["']*)?$/) {
+      $ARG{'version'} = $2
+        if defined $2;
+
+      $msg = "'version' " . (defined $2 ? '' : 'is currently ') . "set to: '$ARG{'version'}'";
+    }
+    elsif ($command =~ /^(s|short)$/) {
+      $ARG{'short'} = ! $ARG{'short'};
+
+      $msg = "'short' output " . ($ARG{'short'} ? 'en' : 'dis') . "abled";
+    }
+    elsif ($command =~ /^(p|paged)$/) {
+      $ARG{'pager'} = get_pager();
+      $ARG{'paged'} = ! $ARG{'paged'}
+        if -x $ARG{'pager'};
+
+      $msg = "'paged' output " . ($ARG{'paged'} ? 'en' : 'dis') . "abled";
+    }
+    elsif ($command =~ /^(pager)(?:\s+["']*(\w+)["']*)?$/) {
+      $ARG{'pager'} = get_pager($2)
+        if defined $2;
+
+      $msg = "'pager' " . (defined $2 ? '' : 'is currently ') . "set to: '$ARG{'pager'}'";
+    }
+    elsif ($command =~ /^(p|paged-)?(r|read)(?:\s+(["']?.+["']?))?$/) {
+      my $paged = $1 || '';
+      my $file  = $3 || $CURRENT_FILE;
+      $CURRENT_FILE = $file;
+
+      if (-r $file) {
+        open(FILE, "< $file")
+          or die "can't open file '$file': $!\n";
+
+        my @lines = <FILE>;
+
+        close FILE;
+
+        my $previous_paged = $ARG{'paged'};
+        $ARG{'paged'}      = 1 if $paged;
+
+        #print_output("$file:\n\n", @lines);
+        print_output(@lines);
+
+        $ARG{'paged'}      = $previous_paged;
+
+        next;
+      }
+
+      $msg = "can't find file '$file'";
+    }
+    elsif ($command =~ /^(c|config)$/) {
+      my $short = $ARG{'short'} ? 'enabled' : 'disabled';
+      my $paged = $ARG{'paged'} ? 'enabled' : 'disabled';
+
+      $msg = <<HERE_MSG;
+current configuration for '$NAME - interactive browse mode':
+
+'version':         $ARG{'version'}
+'short' output:    $short
+'paged' output:    $paged
+'pager':           $ARG{'pager'}
+current file:      $CURRENT_FILE
+HERE_MSG
+    }
+    elsif (length $command) {
+      $msg = "invalid command: .$command";
+    }
+    else {
+      # probably the '.' command
+      $return = 0;
+
+      next;
+    }
+
+    print "% $msg\n";
+  }
+
+  return $return;
+}
+# </sub parse_command>
+
+# <sub readhist>
+# read history from histfile
+#
+# usage:
+#   readhist();
+#
+#   => VOID CONTEXT
+#
+sub readhist {
+  my $term = $TERM;
+
+  if (-r $ARG{'histfile'}) {
+    open(HIST, "< $ARG{'histfile'}")
+      or die "can't open histfile '$ARG{'histfile'}': $!\n";
+
+    while (<HIST>) {
+      chomp;
+      $term->AddHistory($_);
+    }
+
+    close HIST;
+
+    warn "history restored from '$ARG{'histfile'}'\n"
+      if $ARG{'verbose'};
+  }
+  else {
+    warn "history could not be restored (maybe no/wrong history file specified)\n"
+      if $ARG{'verbose'};
+  }
+}
+# </sub readhist>
+
+# <sub savehist>
+# save history to histfile
+#
+# usage:
+#   savehist();
+#
+#   => VOID CONTEXT
+#
+sub savehist {
+  return unless length $ARG{'histfile'} && $ARG{'histsize'};
+
+  my $term = $TERM;
+
+  return unless length $term;
+
+  if (-w $ARG{'histfile'} || (! -e $ARG{'histfile'} && -w dirname $ARG{'histfile'})) {
+    my @history = $term->GetHistory;
+
+    # drop (consecutive) duplicate entries
+    my @unified  = ();
+    my $previous = '';
+    foreach my $element (@history) {
+      push(@unified => $element)
+        unless $element eq $previous;
+      $previous = $element;
+    }
+    @history = @unified;
+
+    # cut history to specified maximum number of entries
+    splice(@history, 0, @history - $ARG{'histsize'})
+      if @history > $ARG{'histsize'};
+
+    open(HIST, "> $ARG{'histfile'}")
+      or die "can't open history file '$ARG{'histfile'}' for writing: $!\n";
+
+    {
+    local $, = "\n";
+
+    print HIST @history, "";
+    }
+
+    close HIST;
+
+    warn "history written to '$ARG{'histfile'}'\n"
+      if $ARG{'verbose'};
+  }
+  else {
+    warn "history could not be written (maybe no history file specified, or history file not writable)\n"
+      if $ARG{'verbose'};
+  }
+}
+# </sub savehist>
+
+# <sub get_pager>
+# get pager executable
+#
+# usage:
+#   $pager = get_pager([$candidate]);
+#
+#   canidate: candidate for pager executable (defaulting to $ARG{'pager'})
+#
+#   => pager: pager executable
+#
+sub get_pager {
+  my $candidate = shift || $ARG{'pager'};
+
+  return $candidate if -x $candidate;
+
+  # get first pager executable in PATH
+  foreach my $path (split(':' => $ENV{'PATH'})) {
+    return catfile($path, $candidate) if -x catfile($path, $candidate);
+  }
+
+  # still no executable!
+  warn "can't find pager '$candidate'! disabling 'paged' output\n";
+  $ARG{'paged'} = 0;
+
+  return '-1';
+}
+# </sub get_pager>
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/explode_metadata_database.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/explode_metadata_database.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/explode_metadata_database.pl	(revision 13928)
@@ -0,0 +1,378 @@
+#!/usr/bin/perl
+
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/plugins");
+}
+
+use strict;
+no strict 'subs'; # allow barewords (eg STDERR) as function arguments
+no strict 'refs'; # allow filehandles to be variables and vice versa
+
+use encodings;
+use printusage;
+use parse2;
+use FileHandle;
+
+my $unicode_list =
+    [ { 'name' => "auto",
+	'desc' => "{BasPlug.input_encoding.auto}" },
+      { 'name' => "ascii",
+	'desc' => "{BasPlug.input_encoding.ascii}" },
+      { 'name' => "utf8",
+	'desc' => "{BasPlug.input_encoding.utf8}" },
+      { 'name' => "unicode",
+	'desc' => "{BasPlug.input_encoding.unicode}" } ];
+
+my $e = $encodings::encodings;
+foreach my $enc (sort {$e->{$a}->{'name'} cmp $e->{$b}->{'name'}} keys (%$e)) 
+{
+    my $hashEncode =
+    {'name' => $enc,
+     'desc' => $e->{$enc}->{'name'}};
+    
+    push(@{$unicode_list},$hashEncode);
+}
+
+my $arguments = 
+    [ 
+      { 'name' => "language",
+	'desc' => "{scripts.language}",
+	'type' => "string",
+	'reqd' => "no",
+        'hiddengli' => "yes" },
+      { 'name' => "plugin",
+	'desc' => "{explode.plugin}",
+	'type' => "string",
+	'reqd' => "yes",
+	'hiddengli' => "yes"},
+      { 'name' => "input_encoding",
+	'desc' => "{explode.encoding}",
+	'type' => "enum",
+	'deft' => "auto",
+	'list' => $unicode_list,
+	'reqd' => "no" },
+      { 'name' => "metadata_set",
+	'desc' => "{explode.metadata_set}",
+	'type' => "string",
+	'reqd' => "no" },
+      { 'name' => "document_field",
+	'desc' => "{explode.document_field}",
+	'type' => "string",
+	'reqd' => "no"},
+       { 'name' => "document_prefix",
+	'desc' => "{explode.document_prefix}",
+	'type' => "string",
+	'reqd' => "no"},
+      { 'name' => "document_suffix",
+	'desc' => "{explode.document_suffix}",
+	'type' => "string",
+	'reqd' => "no"},
+      { 'name' => "records_per_folder",
+	'desc' => "{explode.records_per_folder}",
+	'type' => "int",
+	'range' => "0,",
+	'deft' => "100",
+	'reqd' => "no" },
+      { 'name' => "verbosity",
+	'desc' => "{import.verbosity}",
+	'type' => "int",
+	'range' => "0,",
+	'deft' => "1",
+	'reqd' => "no",
+	'modegli' => "4" },
+      { 'name' => "xml",
+	'desc' => "",
+	'type' => "flag",
+	'reqd' => "no",
+	'hiddengli' => "yes" }
+      ];
+	
+my $options = { 'name' => "explode_metadata_database.pl",
+		'desc' => "{explode.desc}",
+		'args' => $arguments };
+
+	    
+sub main
+{
+    my ($language, $input_encoding, $metadata_set, $plugin, 
+	$document_field, $document_prefix, $document_suffix, $records_per_folder, $verbosity);
+
+    my $xml = 0;
+
+    my $hashParsingResult = {};
+    # parse the options
+    my $intArgLeftinAfterParsing = parse2::parse(\@ARGV,$arguments,$hashParsingResult,"allow_extra_options");
+
+    # If parse returns -1 then something has gone wrong
+    if ($intArgLeftinAfterParsing == -1)
+    {
+	&PrintUsage::print_txt_usage($options, "{explode.params}");
+	die "\n";
+    }
+
+    foreach my $strVariable (keys %$hashParsingResult)
+    {
+	eval "\$$strVariable = \$hashParsingResult->{\"\$strVariable\"}";
+    }
+
+    # If $language has been specified, load the appropriate resource bundle
+    # (Otherwise, the default resource bundle will be loaded automatically)
+    if ($language && $language =~ /\S/) {
+	&gsprintf::load_language_specific_resource_bundle($language);
+    }
+
+    if ($xml) {
+        &PrintUsage::print_xml_usage($options);
+	print "\n";
+	return;
+    }
+
+    # There should one arg left after parsing (the filename)
+    # Or the user may have specified -h, in which case we output the usage
+    if($intArgLeftinAfterParsing != 1 || (@ARGV && $ARGV[0] =~ /^\-+h/))
+    {
+	&PrintUsage::print_txt_usage($options, "{explode.params}");
+	die "\n";
+    }
+
+    # The metadata database filename is the first value that remains after the options have been parsed out
+    my $filename = $ARGV[0];
+    if (!defined $filename || $filename !~ /\w/) { 
+	&PrintUsage::print_txt_usage($options, "{explode.params}");
+	print STDERR "You need to specify a filename";
+	die "\n";
+    }
+    # check that file exists
+    if (!-e $filename) {
+	print STDERR "File $filename doesn't exist...\n";
+	die "\n";
+    }
+    # check required options
+    if (!defined $plugin || $plugin !~ /\w/) {
+	&PrintUsage::print_txt_usage($options, "{explode.params}");
+	print STDERR "You need to specify a plugin";
+	die "\n";
+    }
+    
+    # check metadata set
+    if (defined $metadata_set && $metadata_set =~ /\w/) {
+	$metadata_set .= ".";
+    } else {
+	$metadata_set = "";
+    }
+
+    my $plugobj;
+    require "$plugin.pm";
+    eval ("\$plugobj = new $plugin()");
+    die "$@" if $@;
+
+    # ...and initialize it
+    $plugobj->init(1, "STDERR", "STDERR");
+    
+    if ($input_encoding eq "auto") {
+	($language, $input_encoding) = $plugobj->textcat_get_language_encoding ($filename);
+    }
+
+    my $text = "";
+    # Use the plugin's read_file function to avoid duplicating code
+    $plugobj->read_file($filename, $input_encoding, undef, \$text);
+    # is there any text in the file??
+    die "\n" unless length($text);
+
+    # Create a directory to store the document files...
+    my ($documents_directory_base) = ($filename =~ /(.*)\.[^\.]+$/);
+
+    # Split the text into records, using the plugin's split_exp
+    my $split_exp = $plugobj->{'split_exp'};
+    my @metadata_records = split(/$split_exp/, $text);
+    print STDERR "Number of records: " . scalar(@metadata_records) . "\n";
+
+    # Write the metadata from each record to the metadata.xml file
+    my $record_number = 1;
+    my $documents_directory;
+    foreach my $record_text (@metadata_records) {
+	# Check if we need to start a new directory for these records
+	if (($record_number % $records_per_folder) == 1) {
+	    $documents_directory = $documents_directory_base;
+	    if (scalar(@metadata_records) > $records_per_folder) {
+		$documents_directory .= "." . sprintf("%8.8d", $record_number);
+	    }
+	    if (-d $documents_directory) {
+		die "Error: document directory $documents_directory already exists (bailing).\n";
+	    }
+	    &util::mk_dir($documents_directory);
+
+	    my $documents_metadata_xml_file = &util::filename_cat($documents_directory, "metadata.xml");
+	    if (-e $documents_metadata_xml_file) {
+		die "Error: documents metadata.xml file $documents_metadata_xml_file already exists (bailing).\n";
+	    }
+
+	    # Start the metadata.xml file
+	    open(METADATA_XML_FILE, ">$documents_metadata_xml_file");
+	    print METADATA_XML_FILE
+		"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" .
+		"<!DOCTYPE DirectoryMetadata SYSTEM \"http://greenstone.org/dtd/DirectoryMetadata/1.0/DirectoryMetadata.dtd\">\n" .
+		"<DirectoryMetadata>\n";
+	}
+
+	# Use the plugin's process function to avoid duplicating code
+	my $doc_obj = new doc($filename, "nonindexed_doc");
+	$plugobj->process(\$record_text, undef, undef, $filename, undef, $doc_obj, 0);
+	# Get all the metadata assigned to this record
+	my $record_metadata = $doc_obj->get_all_metadata($doc_obj->get_top_section());
+	my $document_file;
+	
+	# try to get a doc to attach the metadata to
+	if (defined $document_field) {
+	    foreach my $pair (@$record_metadata) {
+		my ($field, $value) = (@$pair);
+		$value =~ s/\\\\/\\/g;
+
+		# Does this metadata element specify a document to obtain?
+		if ($field eq $document_field) {
+		    my $document_file_full = $document_prefix . $value . $document_suffix;
+		    $document_file = &obtain_document($document_file_full, $documents_directory, $verbosity);
+		    &write_metadata_xml_file_entry(METADATA_XML_FILE, $document_file, $record_metadata, $metadata_set);
+		}
+	    }
+	}
+	# Create a dummy .nul file if we haven't obtained any documents for this record
+	if (not defined $document_file) {
+	    $document_file = sprintf("%8.8d", $record_number) . ".nul";
+	    open(DUMMY_FILE, ">$documents_directory/$document_file");
+	    close(DUMMY_FILE);
+	    &write_metadata_xml_file_entry(METADATA_XML_FILE, $document_file, $record_metadata, $metadata_set);
+	}
+
+	if (($record_number % $records_per_folder) == 0 || $record_number == scalar(@metadata_records)) {
+	    # Finish and close the metadata.xml file
+	    print METADATA_XML_FILE "\n</DirectoryMetadata>\n";
+	    close(METADATA_XML_FILE);
+	}
+	$record_number = $record_number + 1;
+    }
+
+    # Explode means just that: the original file is deleted
+    &util::rm($filename);
+    $plugobj->clean_up_after_exploding();
+}
+
+
+sub write_metadata_xml_file_entry
+{
+    my $metadata_xml_file = shift(@_);
+    my $file_name = shift(@_);
+    my $record_metadata = shift(@_);
+    my $meta_prefix = shift(@_);
+    
+    # Make $file_name XML-safe
+    $file_name =~ s/&/&amp;/g;
+    $file_name =~ s/</&lt;/g;
+    $file_name =~ s/>/&gt;/g;
+
+    # Convert $file_name into a regular expression that matches it
+    $file_name =~ s/\./\\\./g;
+    $file_name =~ s/\(/\\\(/g;
+    $file_name =~ s/\)/\\\)/g;
+    $file_name =~ s/\{/\\\{/g;
+    $file_name =~ s/\}/\\\}/g;
+    $file_name =~ s/\[/\\\[/g;
+    $file_name =~ s/\]/\\\]/g;
+    
+    print $metadata_xml_file
+	"\n" .
+        "  <FileSet>\n" .
+	"    <FileName>$file_name</FileName>\n" .
+	"    <Description>\n";
+
+    foreach my $pair (@$record_metadata) {
+	my ($field, $value) = (@$pair);
+
+	# We're only interested in metadata from the database
+	next if ($field eq "lastmodified");
+	next if ($field eq "gsdlsourcefilename");
+	next if ($field eq "gsdldoctype");
+	next if ($field eq "FileFormat");
+
+	# Ignore the ^all metadata, since it will be invalid if the source metadata is changed
+	next if ($field =~ /\^all$/);  # ISISPlug specific!
+
+	# Make $value XML-safe
+	$value =~ s/&/&amp;/g;  # May mess up existing entities!
+	$value =~ s/</&lt;/g;
+	$value =~ s/>/&gt;/g;
+
+	# we are not allowed & in xml except in entities. 
+	# if there are undefined entities then parsing will also crap out.
+	# should we be checking for them too?
+	# this may not get all possibilities
+	# $value =~ s/&([^;\s]*(\s|$))/&amp;$1/g;
+
+	print $metadata_xml_file "      <Metadata mode=\"accumulate\" name=\"$meta_prefix$field\">$value</Metadata>\n";
+    }
+
+    print $metadata_xml_file
+	"    </Description>\n" .
+	    "  </FileSet>\n";
+}
+
+sub obtain_document
+{
+    my $document_file_full = shift(@_);
+    my $documents_directory = shift(@_);
+    my $verbosity = shift(@_);
+    
+    print STDERR "Obtaining document file $document_file_full...\n" if ($verbosity > 1);
+
+    my $document_file_name;
+    my $local_document_file;
+
+    # Document specified is on the web
+    if ($document_file_full =~ /^http:/ || $document_file_full =~ /^ftp:/) {
+	$document_file_full =~ /([^\/]+)$/;
+	$document_file_name = $1;
+	$local_document_file = &util::filename_cat($documents_directory, $document_file_name);
+
+	my $wget_options = "--quiet";
+	$wget_options = "--verbose" if ($verbosity > 2);
+	$wget_options .= " --timestamping";  # Only re-download files if they're newer
+	my $wget_command = "wget $wget_options \"$document_file_full\" --output-document \"$local_document_file\"";
+	`$wget_command`;
+
+	# Check the document was obtained successfully
+	if (!-e $local_document_file) {
+	    print STDERR "WARNING: Could not obtain document file $document_file_full\n";
+	}
+    }
+    # Document specified is on the disk
+    else {
+	my $dir_sep = &util::get_os_dirsep();
+	$document_file_full =~ /(.+$dir_sep)?(.*)$/;
+	$document_file_name = $2;
+	$local_document_file = &util::filename_cat($documents_directory, $document_file_name);
+
+	# Only bother trying to copy the file if it contained some path information
+	if ($document_file_full ne $document_file_name) {
+	    &util::cp($document_file_full, $documents_directory);
+
+	    # Check the document was obtained successfully
+	    if (!-e $local_document_file) {
+		print STDERR "WARNING: Could not obtain document file $document_file_full\n";
+	    }
+	}
+    }
+
+    # If the document wasn't obtained successfully, create a .nul file for it
+    if (!-e $local_document_file) {
+	$document_file_name .= ".nul";
+	open(NULL_FILE, ">$local_document_file.nul");
+	close(NULL_FILE);
+    }
+
+    return $document_file_name;
+}
+
+&main(@ARGV);
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/export.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/export.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/export.pl	(revision 13928)
@@ -0,0 +1,572 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# export.pl --
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+# This program will export a particular collection into a specific Format (e.g. METS or DSpace)
+# Author: Chi-Yu Huang Date: 08-10-2004
+
+package export;
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/cpan");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/plugins");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/plugouts");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/classify");
+}
+
+use strict;
+no strict 'refs'; # allow filehandles to be variables and vice versa
+no strict 'subs'; # allow barewords (eg STDERR) as function arguments
+
+use arcinfo;
+use colcfg;
+use plugin;
+use plugout;
+use util;
+use scriptutil;
+use FileHandle;
+use gsprintf;
+use printusage;
+use parse2;
+
+
+my $oidtype_list = 
+    [ { 'name' => "hash",
+        'desc' => "{import.OIDtype.hash}" },
+      { 'name' => "incremental",
+        'desc' => "{import.OIDtype.incremental}" },
+      { 'name' => "assigned",
+        'desc' => "{import.OIDtype.assigned}" },
+      { 'name' => "dirname",
+        'desc' => "{import.OIDtype.dirname}" } ];
+
+#** define to use the METS format or DSpace format
+my $saveas_list = 
+    [ { 'name' => "DSpace",
+        'desc' => "{export.saveas.DSpace}" },
+      { 'name' => "METS",
+        'desc' => "{export.saveas.METS}"},
+      { 'name' => "GA",
+        'desc' => "{export.saveas.GA}"},
+      { 'name' => "MARCXML",
+        'desc' => "{export.saveas.MARCXML}"}
+     ];
+
+
+# Possible attributes for each argument
+# name: The name of the argument
+# desc: A description (or more likely a reference to a description) for this argument
+# type: The type of control used to represent the argument. Options include: string, int, flag, regexp, metadata, language, enum etc
+# reqd: Is this argument required?
+# hiddengli: Is this argument hidden in GLI?
+# modegli: The lowest detail mode this argument is visible at in GLI
+
+my $saveas_argument =       
+      { 'name' => "saveas",
+	'desc' => "{export.saveas}",
+	'type' => "enum",
+	'list' => $saveas_list,
+	'deft' => "METS",
+	'reqd' => "no",
+	'modegli' => "3" };
+
+
+my $arguments = 
+    [ 
+      $saveas_argument,
+      { 'name' => "saveas_version",
+	'desc' => "{export.saveas_version}",
+	'type' => "string",
+	'reqd' => "no",
+       'deft' => "greenstone" },
+      { 'name' => "exportdir",
+	'desc' => "{export.exportdir}",
+	'type' => "string",
+	'reqd' => "no",
+        'hiddengli' => "yes" },
+      { 'name' => "importdir",
+	'desc' => "{import.importdir}",
+	'type' => "string",
+	'reqd' => "no",
+        'hiddengli' => "yes" },
+      { 'name' => "collectdir",
+	'desc' => "{export.collectdir}",
+	'type' => "string",
+	'deft' => &util::filename_cat ($ENV{'GSDLHOME'}, "collect"),
+	'reqd' => "no",
+        'hiddengli' => "yes" },
+      { 'name' => "listall",
+	'desc' => "{export.listall}",
+	'type' => "flag",
+	'reqd' => "no" },
+      { 'name' => "debug",
+	'desc' => "{export.debug}",
+	'type' => "flag",
+	'reqd' => "no",
+        'hiddengli' => "yes" },
+      { 'name' => "faillog",
+	'desc' => "{export.faillog}",
+	'type' => "string",
+	'deft' => "",
+	'reqd' => "no",
+        'modegli' => "4" },
+      { 'name' => "keepold",
+	'desc' => "{export.keepold}",
+	'type' => "flag",
+	'reqd' => "no",
+        'hiddengli' => "yes" },
+      { 'name' => "removeold",
+	'desc' => "{export.removeold}",
+	'type' => "flag",
+	'reqd' => "no",
+	'modegli' => "3" },
+      { 'name' => "language",
+	'desc' => "{scripts.language}",
+	'type' => "string",
+	'reqd' => "no",
+	'modegli' => "4" },
+      { 'name' => "maxdocs",
+	'desc' => "{export.maxdocs}",
+	'type' => "int",
+	'reqd' => "no",
+	'range' => "1,",
+	'modegli' => "1" },
+      { 'name' => "OIDtype",
+	'desc' => "{import.OIDtype}",
+	'type' => "enum",
+	'list' => $oidtype_list,
+	# parsearg left "" as default
+	#'deft' => "hash",
+	'reqd' => "no",
+	'modegli' => "3" },
+      { 'name' => "OIDmetadata",
+	'desc' => "{import.OIDmetadata}",
+	'type' => "metadata",
+	'deft' => "dc.Identifier",
+	'reqd' => "no",
+	'modegli' => "3" },
+      { 'name' => "out",
+	'desc' => "{export.out}",
+	'type' => "string",
+	'deft' => "STDERR",
+	'reqd' => "no",
+        'hiddengli' => "yes" },
+      { 'name' => "statsfile",
+	'desc' => "{export.statsfile}",
+	'type' => "string",
+	'deft' => "STDERR",
+	'reqd' => "no",
+        'hiddengli' => "yes" },
+      { 'name' => "xsltfile",
+	'desc' => "{BasPlugout.xslt_file}",
+	'type' => "string",
+	'reqd' => "no",
+        'hiddengli' => "yes" },
+      { 'name' => "xslt_txt",
+	'desc' => "{METSPlugout.xslt_txt}",
+	'type' => "string",
+	'reqd' => "no",
+        'hiddengli' => "no" },
+      { 'name' => "xslt_mets",
+	'desc' => "{METSPlugout.xslt_mets}",
+	'type' => "string",
+	'reqd' => "no",
+        'hiddengli' => "no" },
+      { 'name' => "mapping_file",
+	'desc' => "{MARCXMLPlugout.mapping_file}",
+	'type' => "string",
+	'reqd' => "no",
+        'hiddengli' => "no" },
+      { 'name' => "group_marc",
+	'desc' => "{MARCXMLPlugout.group}",
+	'type' => "flag",
+	'reqd' => "no",
+        'hiddengli' => "no" },
+      { 'name' => "verbosity",
+	'desc' => "{export.verbosity}",
+	'type' => "int",
+	'range' => "0,3",
+	'deft' => "2",
+	'reqd' => "no",
+	'modegli' => "4" },
+      { 'name' => "gli",
+	'desc' => "",
+	'type' => "flag",
+	'reqd' => "no",
+	'hiddengli' => "yes" },
+      { 'name' => "xml",
+	'desc' => "{scripts.xml}",
+	'type' => "flag",
+	'reqd' => "no",
+	'hiddengli' => "yes" }
+      ];
+
+my $options = { 'name' => "export.pl",
+		'desc' => "{export.desc}",
+		'args' => $arguments };
+
+my $listall_options = { 'name' => "export.pl",
+		        'desc' => "{export.desc}",
+		        'args' => [ $saveas_argument ] };
+
+sub gsprintf
+{
+    return &gsprintf::gsprintf(@_);
+}
+
+
+&main();
+
+sub main {
+    # params
+    my ($language, $verbosity, $importdir, $exportdir, $keepold, $listall,
+	$removeold, $saveas, $saveas_version, $debug, $OIDtype, $OIDmetadata,
+	$maxdocs, $statsfile, $xsltfile, $mapping_file, $out, $faillog, 
+	$collectdir, $gli,$xslt_mets,$xslt_txt,$group_marc);
+    my $xml = 0;
+    
+    # other vars
+    my ($configfilename, $collection, $export_info_filename, $export_info, $processor, $pluginfo);
+    my $service = "export";
+
+    my $hashParsingResult = {};
+    # general options available to all plugins
+    my $intArgLeftinAfterParsing = parse2::parse(\@ARGV,$arguments,$hashParsingResult,"allow_extra_options");
+    
+    # If parse returns -1 then something has gone wrong
+    if ($intArgLeftinAfterParsing == -1)
+    {
+	&PrintUsage::print_txt_usage($options, "{export.params}");
+	die "\n";
+    }
+
+    foreach my $strVariable (keys %$hashParsingResult)
+    {
+	eval "\$$strVariable = \$hashParsingResult->{\"\$strVariable\"}";
+    }
+
+    
+    # these are options used by other things - we just set default values
+    # undef means will be set from config file if there
+    my $gzip = undef; 
+    my $groupsize = 1;
+    #my $OIDtype = undef;
+    my $sortmeta = undef;
+
+    my $explicit_exportdir = (defined $exportdir) ? 1 : 0;
+
+    # save these command line settings. don't want config file settings in one
+    # coll used for other colls
+    # does this apply to other vars???
+    my $global_removeold = $removeold;
+    my $global_keepold = $keepold;
+    # If $language has been specified, load the appropriate resource bundle
+    # (Otherwise, the default resource bundle will be loaded automatically)
+    if ($language) {
+	&gsprintf::load_language_specific_resource_bundle($language);
+    }
+
+    if ($listall) {
+	if ($xml) {
+	    &PrintUsage::print_xml_usage($listall_options);
+	}
+	else
+	{
+	    &PrintUsage::print_txt_usage($listall_options,"{export.params}");
+	}
+	die "\n";
+    }
+    elsif ($xml) {
+        &PrintUsage::print_xml_usage($options);
+	die "\n";
+    }
+
+    # can have more than one collection name,  
+    # if the first extra option is -h, then output the help
+    if (scalar(@ARGV) == 0 || (@ARGV && $ARGV[0] =~ /^\-+h/)) {
+	&PrintUsage::print_txt_usage($options, "{export.params}");
+	die "\n";
+    }
+
+    if ($gli) { # the gli wants strings to be in UTF-8
+	&gsprintf::output_strings_in_UTF8; 
+    }
+    my $close_out = 0;
+    if ($out !~ /^(STDERR|STDOUT)$/i) {
+	open (OUT, ">$out") ||
+	    (&gsprintf(STDERR, "{common.cannot_open_output_file}\n", $out) && die);
+	$out = 'export::OUT';
+	$close_out = 1;
+    }
+    $out->autoflush(1);
+
+    while (scalar(@ARGV)>0) {
+	my $collect_name = shift @ARGV;
+	$ENV{'GSDLCOLLECTION'} = $collect_name;
+
+	eval {
+	    # get and check the collection name
+	    if (($collection = &util::use_collection($collect_name, $collectdir)) eq "") {
+		&PrintUsage::print_txt_usage($options, "{export.params}");
+		die "\n";
+	    }
+	    # add collection's perllib dir  into include path in 
+	    # case we have collection specific modules
+	    unshift (@INC, "$ENV{'GSDLCOLLECTDIR'}/perllib");
+	    
+	    if ($faillog eq "") {
+		$faillog = &util::filename_cat($ENV{'GSDLCOLLECTDIR'}, "etc", "fail.log");
+	    }
+	    open (FAILLOG, ">$faillog") ||
+		(&gsprintf(STDERR, "{export.cannot_open_fail_log}\n", $faillog) && die);
+	    my $faillogname = $faillog;
+	    $faillog = 'export::FAILLOG';
+	    $faillog->autoflush(1);
+	    
+	    # check sortmeta
+	    $sortmeta = undef unless defined $sortmeta && $sortmeta =~ /\S/;
+	    if (defined $sortmeta && $groupsize > 1) {
+		&gsprintf($out, "{export.cannot_sort}\n\n");
+		$sortmeta = undef;
+	    }
+	    
+	    # get the list of plugins for this collection and set any options that
+	    # were specified in the collect.cfg (all export.pl options except
+	    # -collectdir, -out and -faillog may be specified in the collect.cfg (these
+	    # options must be known before we read the collect.cfg))
+	    my $plugins = [];
+	    my @global_opts = ();
+	    
+	    $configfilename = &util::filename_cat ($ENV{'GSDLCOLLECTDIR'}, "etc", "collect.cfg");
+	    if (!-e $configfilename) {
+		(&gsprintf($out, "{common.cannot_find_cfg_file}\n", $configfilename) && die);
+	    }
+	    
+	    my $collectcfg = &colcfg::read_collect_cfg ($configfilename);
+	    if (defined $collectcfg->{'plugin'}) {
+		$plugins = $collectcfg->{'plugin'};
+	    }
+	    
+	    if ($verbosity !~ /\d+/) {
+		if (defined $collectcfg->{'verbosity'} && $collectcfg->{'verbosity'} =~ /\d+/) {
+		    $verbosity = $collectcfg->{'verbosity'};
+		} else {
+		    $verbosity = 2; # the default
+		}
+	    }
+	    if (defined $collectcfg->{'importdir'} && $importdir eq "") {
+		$importdir = $collectcfg->{'importdir'};
+	    }
+	    if (defined $collectcfg->{'exportdir'} && $exportdir eq "") {
+		$exportdir = $collectcfg->{'exportdir'};
+	    }
+
+	    if (defined $collectcfg->{'gzip'} && !$gzip) {
+		if ($collectcfg->{'gzip'} =~ /^true$/i) {
+		    $gzip = 1;
+		}
+	    }
+	    if ($maxdocs !~ /\-?\d+/) {
+		if (defined $collectcfg->{'maxdocs'} && $collectcfg->{'maxdocs'} =~ /\-?\d+/) {
+		    $maxdocs = $collectcfg->{'maxdocs'};
+		} else {
+		    $maxdocs = -1; # the default
+		}
+	    }
+	    if ($groupsize == 1) {
+		if (defined $collectcfg->{'groupsize'} && $collectcfg->{'groupsize'} =~ /\d+/) {
+		    $groupsize = $collectcfg->{'groupsize'};
+		}
+	    }
+	    if (!defined $OIDtype || ($OIDtype !~ /^(hash|incremental|assigned|dirname)$/)) {
+		if (defined $collectcfg->{'OIDtype'} && $collectcfg->{'OIDtype'} =~ /^(hash|incremental)$/) {
+		    $OIDtype = $collectcfg->{'OIDtype'};
+		} else {
+		    $OIDtype = "hash"; # the default
+		}
+	    }
+	    if (defined $collectcfg->{'sortmeta'} && $sortmeta eq "") {
+		$sortmeta = $collectcfg->{'sortmeta'};
+	    }
+	    if (defined $collectcfg->{'debug'} && $collectcfg->{'debug'} =~ /^true$/i) {
+		$debug = 1;
+	    }
+	    if (defined $collectcfg->{'gli'} && $collectcfg->{'gli'} =~ /^true$/i) {
+		$gli = 1;
+	    }
+	    
+	    # global plugin stuff
+	    if (defined $collectcfg->{'separate_cjk'}&& $collectcfg->{'separate_cjk'} =~ /^true$/i) {
+		push @global_opts, "-separate_cjk";
+	    }
+	    
+	    ($removeold, $keepold) = &scriptutil::check_removeold_and_keepold($global_removeold, $global_keepold, 0, "export", $collectcfg);
+
+	    $gli = 0 unless defined $gli;
+
+	    print STDERR "<export>\n" if $gli;
+	    
+	    # fill in the default import and export directories if none
+	    # were supplied, turn all \ into / and remove trailing /
+	    $importdir = &util::filename_cat ($ENV{'GSDLCOLLECTDIR'}, "import") if $importdir eq "";
+	    $importdir =~ s/[\\\/]+/\//g;
+	    $importdir =~ s/\/$//;
+	    $exportdir = &util::filename_cat ($ENV{'GSDLCOLLECTDIR'}, "export") if $exportdir eq "";
+	    $exportdir =~ s/[\\\/]+/\//g;
+	    $exportdir =~ s/\/$//;
+	    
+	    # load all the plugins
+	    $pluginfo = &plugin::load_plugins ($plugins, $verbosity, $out, $faillog, \@global_opts);
+	    
+	    if (scalar(@$pluginfo) == 0) {
+		&gsprintf($out, "{import.no_plugins_loaded}\n");
+		die "\n";
+	    }
+	    
+	    # remove the old contents of the export directory if needed
+	    if ($removeold && -e $exportdir) {
+		&gsprintf($out, "{export.removing_export}\n");
+		&util::rm_r ($exportdir);
+	    }
+	    
+	    # read the export information file
+	    
+	    # Export to DSpace Archive format or METs format
+	    # If saveas=DSpace, a "contents" file will be created, otherwise "export.inf"
+		
+	    # the plugouts should be doing this!!
+	    if ($saveas eq "DSpace"){
+		$export_info_filename = &util::filename_cat ($exportdir, "contents");
+	    } elsif ($saveas eq "METS" || $saveas eq "GA" || $saveas eq "MARC" ) {
+		$export_info_filename = &util::filename_cat ($exportdir, "export.inf");
+	    }
+	    
+	    $export_info = new arcinfo();
+	    $export_info -> load_info ($export_info_filename);	
+	    
+	    if ($saveas !~ /^(GA|METS|DSpace|MARCXML)$/) {
+		if (defined $collectcfg->{'plugout'} && $collectcfg->{'plugout'}[0] =~ /^(GAPlugout|METSPlugout)$/) {
+		    $saveas = $collectcfg->{'plugout'}[0];
+		} else {
+		    $saveas ="GAPlugout";
+		}
+	    }
+	    
+	    
+	    ####Use Plugout####
+	    my ($plugout_name);
+	    if ($saveas !~ /^(GA|METS|DSpace|MARCXML)Plugout$/  ){      
+		$plugout_name = $saveas."Plugout";
+	    }
+	    else {
+		$plugout_name = $saveas;
+	    } 
+	    
+	    my $opts=[];
+	    
+	    push @$opts,("-output_info",$export_info) if (defined $export_info); 
+	    push @$opts,("-verbosity",$verbosity) if (defined $verbosity);
+	    push @$opts,("-debug") if ($debug);
+	    push @$opts,("-gzip_output",$gzip) if (defined $gzip);
+	    push @$opts,("-group_size",$groupsize) if (defined $groupsize);
+	    push @$opts,("-output_handle",$out) if (defined $out);
+	    push @$opts,("-xslt_file",$xsltfile) if (defined $xsltfile);
+	    push @$opts,("-group") if ($group_marc && $plugout_name =~ /^MARCXMLPlugout$/);
+	    push @$opts,("-mapping_file",$mapping_file) if (defined $mapping_file && $plugout_name =~ /^MARCXMLPlugout$/);
+	    push @$opts,("-saveas_version",$saveas_version) if (defined $saveas_version && $plugout_name =~ /^METSPlugout$/);
+	    push @$opts,("-xslt_mets",$xslt_mets) if (defined $xslt_mets && $plugout_name =~ /^METSPlugout$/);
+	    push @$opts,("-xslt_txt",$xslt_txt) if (defined $xslt_txt && $plugout_name =~ /^METSPlugout$/);
+	    $processor = &plugout::load_plugout($plugout_name,$opts);    
+	    
+	    $processor->setoutputdir ($exportdir);
+	    
+	    $processor->set_sortmeta ($sortmeta) if defined $sortmeta;
+	    $processor->set_OIDtype ($OIDtype, $OIDmetadata);
+	    
+	    &plugin::begin($pluginfo, $importdir, $processor, $maxdocs);
+	    
+	    # process the import directory
+	    &plugin::read ($pluginfo, $importdir, "", {}, $processor, $maxdocs,0, $gli);
+	    
+	    &plugin::end($pluginfo, $processor);
+
+ 	    &plugin::deinit($pluginfo, $processor);
+	    
+	    # write out the export information file
+	    $processor->close_file_output() if $groupsize > 1;
+	    $processor->close_group_output() if $processor->is_group();
+	    if ($saveas eq "METS") {
+		$export_info->save_info($export_info_filename);
+	    }
+	    
+	    # write out export stats
+	    my $close_stats = 0;
+	    if ($statsfile !~ /^(STDERR|STDOUT)$/i) {
+		if (open (STATS, ">$statsfile")) {
+		    $statsfile = 'import::STATS';
+		    $close_stats = 1;
+		} else {
+		    &gsprintf($out, "{import.cannot_open_stats_file}", $statsfile);
+		    &gsprintf($out, "{import.stats_backup}\n");
+		    $statsfile = 'STDERR';
+		}
+	    }
+
+	    &gsprintf($out, "\n");
+	    &gsprintf($out, "*********************************************\n");
+
+	    &plugin::write_stats($pluginfo, $statsfile, $faillogname, $gli);
+	    if ($close_stats) {
+		close STATS;
+	    }
+
+	    &gsprintf($out, "*********************************************\n");
+
+	    close OUT if $close_out;
+
+	    close FAILLOG;
+	};
+
+	if ($@) {
+	    print STDERR $@;
+	}
+
+##	$ENV{'GSDLCOLLECTION'} = undef;
+	$importdir = "";
+	$removeold = 0 if ($explicit_exportdir);
+
+    } # while processing ARGV
+    
+    &gsprintf($out, "\n");
+    &gsprintf($out, "*********************************************\n");
+    &gsprintf($out, "* {export.complete}\n");
+    &gsprintf($out, "*********************************************\n");    
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/exportcol.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/exportcol.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/exportcol.pl	(revision 13928)
@@ -0,0 +1,373 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# exportcol.pl --
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use strict;
+no strict 'refs'; # allow filehandles to be variables and vice versa
+no strict 'subs'; # allow barewords (eg STDERR) as function arguments
+
+use util;
+use parse2;
+use printusage;
+
+my $arguments = 
+    [ 
+      { 'name' => "cdname",
+	'desc' => "{exportcol.cdname}",
+	'type' => "string",
+	'deft' => "Greenstone Collections",
+	'reqd' => "no" }, 
+      { 'name' => "cddir",
+	'desc' => "{exportcol.cddir}",
+	'type' => "string",
+	'deft' => "exported_collections",
+	'reqd' => "no" },
+      { 'name' => "noinstall",
+	'desc' => "{exportcol.noinstall}",
+	'type' => "flag",
+	'reqd' => "no" },
+      { 'name' => "language",
+	'desc' => "{scripts.language}",
+	'type' => "string",
+	'reqd' => "no" },
+      { 'name' => "out",
+	'desc' => "{exportcol.out}",
+	'type' => "string",
+	'deft' => "STDERR",
+	'reqd' => "no" },
+      { 'name' => "xml",
+	'desc' => "{scripts.xml}",
+	'type' => "flag",
+	'reqd' => "no",
+	'hiddengli' => "yes" },
+      { 'name' => "gli",
+	'desc' => "",
+	'type' => "flag",
+	'reqd' => "no",
+	'hiddengli' => "yes" },
+
+      ];
+
+my $options = { 'name' => "exportcol.pl",
+		'desc' => "{exportcol.desc}",
+		'args' => $arguments };
+
+sub gsprintf
+{
+    return &gsprintf::gsprintf(@_);
+}
+
+
+&main();
+
+sub main {
+    my ($language, $out, $cdname, $cddir);
+    
+    my $noinstall = 0;
+    my $xml = 0;
+    my $gli = 0;
+
+    my $hashParsingResult = {};
+
+    # parse options
+    my $intArgLeftinAfterParsing = parse2::parse(\@ARGV,$arguments,$hashParsingResult,"allow_extra_options");
+
+    # If parse returns -1 then something has gone wrong
+    if ($intArgLeftinAfterParsing == -1)
+    {
+	&PrintUsage::print_txt_usage($options, "{exportcol.params}");
+	die "\n";
+    }
+    
+    foreach my $strVariable (keys %$hashParsingResult)
+    {
+	eval "\$$strVariable = \$hashParsingResult->{\"\$strVariable\"}";
+    }
+    
+    # If $language has been specified, load the appropriate resource bundle
+    # (Otherwise, the default resource bundle will be loaded automatically)
+    if ($language && $language =~ /\S/) {
+	&gsprintf::load_language_specific_resource_bundle($language);
+    }
+    
+    if ($xml) {
+        &PrintUsage::print_xml_usage($options);
+	print "\n";
+	return;
+    }
+    
+    if ($gli) { # the gli wants strings to be in UTF-8
+	&gsprintf::output_strings_in_UTF8; 
+    }
+    
+    # can have more than one collection name,  
+    # if the first extra option is -h, then output the help
+    if (scalar(@ARGV) == 0 || (@ARGV && $ARGV[0] =~ /^\-+h/)) {
+	&PrintUsage::print_txt_usage($options, "{exportcol.params}");
+	die "\n";
+    }
+
+    my @coll_list = @ARGV;
+
+    my $close_out = 0;
+    if ($out !~ /^(STDERR|STDOUT)$/i) {
+	open (OUT, ">$out") || 
+	    (&gsprintf(STDERR, "{common.cannot_open_output_file}\n", $out) && die);
+	$out = 'main::OUT';
+	$close_out = 1;
+    }
+
+    # first we do a quick check to see if the export coll function has been 
+    # installed
+    my $gssetupexe = &util::filename_cat ($ENV{'GSDLHOME'}, "bin", "windows", "gssetup.exe"); 
+    if (!-e $gssetupexe) {
+	&gsprintf($out, "{exportcol.fail} {exportcol.export_coll_not_installed}\n");
+	die "\n";
+    }
+
+    # check each collection
+    my @valid_coll_list = ();
+    foreach my $c (@coll_list) {
+	my $colldir = &util::filename_cat ($ENV{'GSDLHOME'}, "collect", $c);
+	if (! -d $colldir) {
+	    &gsprintf($out, "{exportcol.coll_not_found}\n", $c, $colldir);
+	    next;
+	}
+	my $colindexdir = &util::filename_cat ($colldir, "index");
+	my $coletcdir = &util::filename_cat ($colldir, "etc");
+	if ((!-d $colindexdir) || (!-d $coletcdir)) {
+	    &gsprintf($out, "{exportcol.coll_dirs_not_found}\n", $c);
+	    &gsprintf($out, "  $colindexdir\n");
+	    &gsprintf($out, "  $coletcdir\n");
+	    next;
+	}
+	# the collection seems ok, we add it to the valid coll list
+	push @valid_coll_list, $c;
+    }
+
+    if (not @valid_coll_list) {
+	# no valid colls left
+	&gsprintf($out, "{exportcol.fail} {exportcol.no_valid_colls}\n");
+	die "\n";
+    }
+
+    # create exported directory
+    my $topdir = &util::filename_cat ($ENV{'GSDLHOME'}, "tmp", $cddir);
+    &util::mk_all_dir ($topdir);
+    if (!-d $topdir) {
+	&gsprintf($out, "{exportcol.fail} {exportcol.couldnt_create_dir}\n", $topdir);
+	die "\n";
+    }
+
+    # we create either a self installing cd, or one that runs off the cd (and
+    # doesn't install anything
+
+    # create all the directories - we assume that if we created the top dir ok,
+    # then all the other mkdirs will go ok
+    my $gsdldir;
+    if ($noinstall) {
+	$gsdldir = $topdir;
+    } 
+    else {
+	$gsdldir = &util::filename_cat ($topdir, "gsdl");
+	&util::mk_all_dir ($gsdldir);
+    }
+    
+    my $collectdir = &util::filename_cat ($gsdldir, "collect");
+    &util::mk_all_dir ($collectdir);
+    my $etcdir = &util::filename_cat ($gsdldir, "etc");
+    &util::mk_all_dir ($etcdir);
+    my $binjavadir = &util::filename_cat ($gsdldir, "bin", "java");
+    &util::mk_all_dir ($binjavadir);
+
+    #create the config files
+    if (!$noinstall) {
+	# create the install.cfg file
+	my $installcfg = &util::filename_cat ($topdir, "install.cfg");
+	if (!open (INSTALLCFG, ">$installcfg")) {
+	    &gsprintf($out, "{exportcol.fail} {exportcol.couldnt_create_file}\n", $installcfg);
+	    die "\n";
+	}
+	print INSTALLCFG "CompanyName:New Zealand Digital Library\n";
+	print INSTALLCFG "CollectionName:$cdname\n";
+	print INSTALLCFG "CollectionDirName:$cdname\n";
+	print INSTALLCFG "CollectionVersion:1.0\n";
+	print INSTALLCFG "CollectionVolume:1\n";
+	print INSTALLCFG "ProgramGroupName:Greenstone\n";
+	close INSTALLCFG;
+	
+	# create the manifest.cfg file
+	my $manifestcfg = &util::filename_cat ($topdir, "manifest.cfg");
+	if (!open (MANIFESTCFG, ">$manifestcfg")) {
+	    &gsprintf($out, "{exportcol.fail} {exportcol.couldnt_create_file}\n", $manifestcfg);
+	    die "\n";
+	}
+	print MANIFESTCFG "all:\n";
+	print MANIFESTCFG "  {library} {collection}\n\n";
+	print MANIFESTCFG "library:\n";
+	print MANIFESTCFG "  server.exe\n\n";
+	print MANIFESTCFG "database:\n";
+	print MANIFESTCFG '  etc ';
+	foreach my $c (@valid_coll_list) {
+	    print MANIFESTCFG "collect\\$c\\index\\text\\$c.ldb ";
+	}
+	print MANIFESTCFG "\n\n";
+	print MANIFESTCFG "collection:\n";
+	print MANIFESTCFG "  collect etc images macros mappings bin\n";
+	close MANIFESTCFG;
+	
+    }	
+
+    #create the autorun.inf file
+    my $autoruninf = &util::filename_cat ($topdir, "Autorun.inf");
+    if (!open (AUTORUNINF, ">$autoruninf")) {
+	&gsprintf($out, "{exportcol.fail} {exportcol.couldnt_create_file}\n", $autoruninf);
+	die "\n";
+    }
+    
+    print AUTORUNINF "[autorun]\n";
+    if ($noinstall) {
+	print AUTORUNINF "OPEN=server.exe\n";
+    } else {
+	print AUTORUNINF "OPEN=Setup.exe\n";
+    }
+    close AUTORUNINF;
+    
+    # copy the necessary stuff from GSDLHOME
+    my $imagesdir = &util::filename_cat ($ENV{'GSDLHOME'}, "images");
+    my $macrosdir = &util::filename_cat ($ENV{'GSDLHOME'}, "macros");
+    my $mappingsdir = &util::filename_cat ($ENV{'GSDLHOME'}, "mappings");
+    my $maincfg = &util::filename_cat ($ENV{'GSDLHOME'}, "etc", "main.cfg");
+    my $serverexe = &util::filename_cat ($ENV{'GSDLHOME'}, "bin", "windows", "server.exe");
+    my $setupexe = &util::filename_cat ($ENV{'GSDLHOME'}, "bin", "windows", "Setup.exe");
+    my $phindjar = &util::filename_cat ($ENV{'GSDLHOME'}, "bin", "java", "Phind.jar");
+    my $gsdlcollageappletjar = &util::filename_cat ($ENV{'GSDLHOME'}, "bin", "java", "GsdlCollageApplet.jar");
+
+    if ((!-d $imagesdir) || (!-d $macrosdir) || (!-d $mappingsdir) || (!-e $maincfg) ||
+	(!-e $serverexe) || (!-e $gssetupexe) || (!-e $setupexe) || (!-e $phindjar) ||
+	(!-e $gsdlcollageappletjar)) {
+	&gsprintf($out, "{exportcol.fail} {exportcol.non_exist_files}\n");
+	&gsprintf($out, "  $imagesdir\n");
+	&gsprintf($out, "  $macrosdir\n");
+	&gsprintf($out, "  $mappingsdir\n");
+	&gsprintf($out, "  $maincfg\n");
+	&gsprintf($out, "  $serverexe\n");
+	&gsprintf($out, "  $gssetupexe\n");
+	&gsprintf($out, "  $setupexe\n");
+	&gsprintf($out, "  $phindjar\n");
+	&gsprintf($out, "  $gsdlcollageappletjar\n");
+	die "\n";
+    }
+
+    &util::cp_r ($imagesdir, $gsdldir);
+    &util::cp_r ($macrosdir, $gsdldir);
+    &util::cp_r ($mappingsdir, $gsdldir);
+    &util::cp ($maincfg, $etcdir);
+    &util::cp ($serverexe, $gsdldir);
+    &util::cp ($phindjar, $binjavadir);
+    &util::cp ($gsdlcollageappletjar, $binjavadir);
+
+    if (!$noinstall) {
+	&util::cp ($gssetupexe, $topdir);
+	&util::cp ($setupexe, $topdir);
+    }	
+    
+    # now change the home.dm macro file to a simple version
+    my $newmacrodir = &util::filename_cat ($gsdldir, "macros");
+    my $exporthome = &util::filename_cat ($newmacrodir, "exported_home.dm");
+    my $oldhome = &util::filename_cat ($newmacrodir, "home.dm");
+    if (-e $exporthome) {
+	&util::rm($oldhome);
+	&util::mv($exporthome, $oldhome);
+    }
+
+    # copy the collections over 
+    foreach my $c (@valid_coll_list) {
+	#old directories
+	my $colldir = &util::filename_cat ($ENV{'GSDLHOME'}, "collect", $c);
+	my $colindexdir = &util::filename_cat ($colldir, "index");
+	my $coletcdir = &util::filename_cat ($colldir, "etc");
+	my $colimagesdir = &util::filename_cat ($colldir, "images");
+	my $colmacrosdir = &util::filename_cat ($colldir, "macros");
+	# new coll directory
+	my $newcoldir = &util::filename_cat ($collectdir, $c);
+
+	&util::mk_all_dir ($newcoldir);
+	&util::cp_r ($colindexdir, $newcoldir);
+	&util::cp_r ($coletcdir, $newcoldir);
+	&util::cp_r ($colimagesdir, $newcoldir) if (-e $colimagesdir);
+	&util::cp_r ($colmacrosdir, $newcoldir) if (-e $colmacrosdir);
+
+	# now we need to check the collect.cfg file to make sure it's public
+	my $collectcfg = &util::filename_cat ($newcoldir, "etc", "collect.cfg");
+	open INFILE, "<$collectcfg";
+	open OUTFILE, ">$collectcfg.tmp";
+	my $line;
+	while ($line = <INFILE>) {
+	    if ($line =~ /^\s*public\s+false/) {
+		print OUTFILE "public\ttrue\n";
+		last; # stop matching once we have found the line
+	    } else {
+		print OUTFILE "$line";
+	    }
+	}
+	# continue with no checking
+	while ($line = <INFILE>) {
+	    print OUTFILE "$line";
+	}
+	close INFILE;
+	close OUTFILE;
+	&util::mv("$collectcfg.tmp", $collectcfg);
+    }
+    &gsprintf($out, "{exportcol.success}");
+
+    my $successcolls = "";
+    my $first = 1;
+    foreach my $c (@valid_coll_list) {
+	if ($first) {
+	    $first=0;
+	} else {
+	    $successcolls .=", ";
+	}
+	$successcolls .= "$c";
+    }
+
+    my $gsdl_home = $ENV{'GSDLHOME'};
+    my $portable_topdir = $topdir;
+    # Disabled this because it isn't currently useful (the GLI applet doesn't do exporting)
+    # It doesn't work on Windows, either
+    # $portable_topdir =~ s/$gsdl_home/\$GSDLHOME/g;
+
+    &gsprintf($out, "{exportcol.output_dir}\n", $successcolls, $portable_topdir);
+    &gsprintf($out, "exportcol.pl succeeded:{exportcol.instructions}\n");
+    close OUT if $close_out;
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/extract_text.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/extract_text.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/extract_text.pl	(revision 13928)
@@ -0,0 +1,147 @@
+#! /usr/bin/perl -w
+
+# extract_text.pl extracts the text from macro files, install scripts
+# etc. for translation.
+
+# output is currently to a tab separated list, suitable for importing into
+# excel.
+
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+}
+
+my $installsh = "$ENV{'GSDLHOME'}/Install.sh";
+my $macrosdir = "$ENV{'GSDLHOME'}/macros";
+my $installshield = 'C:/My Installations/is_gsdl_cdrom/String Tables/0009-English/value.shl';
+
+my $texthash = {};
+
+# first extract all the itextn variables from Install.sh
+open (INSTALLSH, $installsh) || die;
+undef $/;
+my $file = <INSTALLSH>;
+$/ = "\n";
+close INSTALLSH;
+
+$texthash->{'install_sh'} = {};
+while ($file =~ s/^(itext\d+)=\"(.*?)(?<!\\)\"//sm) {
+    my $key = $1;
+    my $value = $2;
+    $value =~ s/\n/\\n/gs;
+    $value =~ s/\t/\\t/gs;
+    if (defined ($texthash->{'install_sh'}->{$key})) {
+	print STDERR "ERROR: $1 already defined\n";
+    }
+    $texthash->{'install_sh'}->{$key} = $value;
+}
+
+
+# now grab the text from the macro files
+$texthash->{'macros'} = {};
+
+# english.dm
+&grab_macros("$macrosdir/english.dm");
+# english2.dm
+&grab_macros("$macrosdir/english2.dm");
+
+
+# text from installshield installation
+$texthash->{'installshield'} = {};
+open (ISHIELD, $installshield) || die;
+my $line = "";
+my $textserver = {};
+while (defined ($line = <ISHIELD>)) {
+    next unless ($line =~ /\w/);
+    last if $line =~ /^\[General\]/;
+    next if $line =~ /^\[/;
+
+    $line =~ s/\n/\\n/gs;
+    $line =~ s/\t/\\t/gs;
+
+    if ($line =~ /^(TEXT_SERVERTXT_\d+)=(.*)$/) {
+	$textserver->{$1} = $2;
+    } else {
+	$line =~ /^([^=]+)=(.*)$/;
+	$texthash->{'installshield'}->{$1} = $2;
+    }
+}
+close ISHIELD;
+my $tserver = "";
+foreach my $stext (sort keys %{$textserver}) {
+    $tserver .= $textserver->{$stext};
+}
+$texthash->{'installshield'}->{'TEXT_SERVERTXT'} = $tserver;
+
+# print out the result
+foreach my $type (keys (%$texthash)) {
+    print STDOUT "type:\t$type\n";
+    foreach my $key (sort keys (%{$texthash->{$type}})) {
+	print STDOUT "$key\t$texthash->{$type}->{$key}\n";
+    }
+}
+
+sub grab_macros {
+    my ($filename) = @_;
+
+    my $line = "";
+    my $pack = "Global";
+    my $macroname = "";
+    my $macrovalue = "";
+    open (FILE, $filename) || die;
+    while (defined ($line = <FILE>)) {
+	if ($line =~ /^package (\w+)/) {
+	    $pack = $1;
+	    $macroname = "";
+	    $macrovalue = "";
+	    next;
+	}
+
+	if ($line =~ /^_([^_\s]+)_\s*(?:\[[^\]]*\])?\s*\{(.*)$/s) {
+	    die "ERROR 1\n" if ($macroname ne "" || $macrovalue ne "");
+	    $macroname = $1;
+	    $macrovalue = $2 if defined $2;
+	    if ($macrovalue =~ s/^(.*?)(?<!\\)\}/$1/) {
+		&addmacro($pack, \$macroname, \$macrovalue);
+	    }		
+	} elsif ($macroname ne "") {
+	    if ($line =~ /^(.*?)(?<!\\)\}/) {
+		$macrovalue .= $1 if defined $1;
+		&addmacro($pack, \$macroname, \$macrovalue);
+	    } else {
+		$macrovalue .= $line;
+	    }
+	} elsif ($line =~ /^\#\# \"([^\"]+)\" \#\# \w+ \#\# (\w+) \#\#/) {
+	    my $imagename = "image:$2";
+	    my $imagetext = $1;
+	    &addmacro($pack, \$imagename, \$imagetext);
+	}
+    }
+    close FILE;
+}
+
+sub addmacro {
+    my ($pack, $nameref, $valref) = @_;
+
+    if ($$nameref !~ /^(httpicon|width|height)/) {
+
+	my $name = "$pack:$$nameref";
+	
+	if (defined ($texthash->{'macros'}->{$name})) {
+	    print STDERR "ERROR: $name already defined\n";	
+	}
+
+
+	$$valref =~ s/\n/\\n/gs;
+	$$valref =~ s/\t/\\t/gs;
+
+	$texthash->{'macros'}->{$name} = $$valref;
+    }
+
+    else {
+#	print STDERR "ignoring $$nameref\n";
+    }
+
+    $$nameref = "";
+    $$valref = "";
+}
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/filecopy.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/filecopy.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/filecopy.pl	(revision 13928)
@@ -0,0 +1,184 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# filecopy.pl --
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+# This program will "download" the specified files/directories
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use util;
+use parsargv;
+use File::stat;
+use File::Basename;
+use FileHandle;
+
+sub print_usage {
+    print STDERR "\n";
+    print STDERR "filecopy.pl: Recursively copies files into a collections import directory.\n\n";
+    print STDERR "\n  usage: $0 [options] [directories] collection-name\n\n";
+
+    print STDERR "  options:\n";
+    print STDERR "   -follow_links           Follow symbolic links when recursing directory\n";
+    print STDERR "                           structure\n";
+    print STDERR "   -collectdir directory   Collection directory (defaults to " .
+	&util::filename_cat ($ENV{'GSDLHOME'}, "collect") . ")\n";
+    print STDERR "   -out                    Filename or handle to print output status to.\n";
+    print STDERR "                           The default is STDERR\n\n";
+}
+
+sub get_file_list {
+    my $dirhash = shift @_;
+    my $filehash = shift @_;
+    my $dirname = shift @_;
+
+    my $full_importname 
+	= &util::filename_cat($collectdir, $dirname, "import");
+
+    # check for .kill file
+    if (-e &util::filename_cat($collectdir, $dirname, ".kill")) {
+	print $out "filecopy.pl killed by .kill file\n";
+	die "\n";
+    }
+
+    foreach my $file (@_) {
+
+	$file =~ s/^\"//;
+	$file =~ s/\"$//;
+
+	if (!$follow_links && -l $file) {
+	    # do nothing as we don't want to follow symbolic links
+
+	} elsif (-d $file) {
+	    my $dst_dir = &get_dst_dir ($full_importname, $file);
+	    # add this directory to the list to be created
+	    $dirhash->{$dst_dir} = 1;
+
+	    # read in dir
+            if (!opendir (DIR, $file)) {
+                print $out "Error: Could not open directory $file\n";
+            } else {
+                my @sub_files = grep (!/^\.\.?$/, readdir (DIR));
+                closedir DIR;
+		map { $_ = &util::filename_cat($file, $_); } @sub_files;
+		&get_file_list($dirhash, $filehash, $dirname, @sub_files);
+	    }
+
+	} else {
+	    my $dst_file = &get_dst_dir ($full_importname, $file);
+
+	    # make sure files directory is included in dirhash
+	    $dirhash->{File::Basename::dirname($dst_file)} = 1;
+
+	    if (-e $dst_file) {
+		# if destination file exists already we'll only copy it if
+		# the source file is newer
+		my $src_stat = stat($file);
+		my $dst_stat = stat($dst_file);
+		$filehash->{$file} = $dst_file if ($src_stat->mtime > $dst_stat->mtime);
+	    } else {
+		$filehash->{$file} = $dst_file;
+	    }
+	}
+    }
+}
+
+
+sub main {
+
+    if (!parsargv::parse(\@ARGV, 
+			 'follow_links', \$follow_links,
+			 'collectdir/.*/', \$collectdir,
+			 'out/.*/STDERR', \$out)) {
+	&print_usage();
+	die "\n";
+    }
+
+    if ($collectdir !~ /\w/) {
+	$collectdir = &util::filename_cat ($ENV{'GSDLHOME'}, "collect");
+    }
+
+    my $collection = pop @ARGV;
+
+    my $close_out = 0;
+    if ($out !~ /^(STDERR|STDOUT)$/i) {
+	open (OUT, ">$out") || die "Couldn't open output file $out\n";
+	$out = OUT;
+	$close_out = 1;
+    }
+    $out->autoflush(1);
+
+    # first compile a list of all the files we want to copy (we do it this
+    # way rather than simply copying the files as we recurse the directory
+    # structure to avoid nasty infinite recursion if the directory we're
+    # copying to happens to be a subdirectory of one of the directories
+    # we're copying from)
+    my $dirhash = {};
+    my $filehash = {};
+    &get_file_list($dirhash, $filehash, $collection, @ARGV);
+
+    # create all the required destination directories
+    my $count = 0;
+    foreach my $dir (keys %$dirhash) {
+	# check for .kill file
+	if (($count ++ % 20 == 0) &&
+	    (-e &util::filename_cat($collectdir, $collection, ".kill"))) {
+	    print $out "filecopy.pl killed by .kill file\n";
+	    die "\n";
+	}
+	&util::mk_all_dir($dir);
+    }
+
+    # copy all the files
+    foreach my $file (keys %$filehash) {
+	# check for .kill file
+	if (($count ++ % 20 == 0) &&
+	    (-e &util::filename_cat($collectdir, $collection, ".kill"))) {
+	    print $out "filecopy.pl killed by .kill file\n";
+	    die "\n";
+	}
+	print $out "copying $file --> $filehash->{$file}\n";
+	&util::cp($file, $filehash->{$file});
+    }
+
+    close OUT if $close_out;
+    return 0;
+}
+
+sub get_dst_dir {
+    my ($full_importname, $dir) = @_;
+
+    if ($ENV{'GSDLOS'} eq "windows") {
+	# don't want windows filenames like c:\gsdl\...\import\c:\dir
+	$dir =~ s/^[a-z]:[\\\/]//i;
+    }
+    return &util::filename_cat($full_importname, $dir);
+}
+
+&main();
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/getdocument.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/getdocument.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/getdocument.pl	(revision 13928)
@@ -0,0 +1,32 @@
+#!/usr/bin/perl -w
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/bin/script");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/cpan");
+    unshift (@INC, "$ENV{'GSDLHOME'}/collect/lld/perllib");
+}
+
+use util;
+
+use IncrementalBuild; # Include John's incremental building API
+
+# Ensure the collection specific binaries are on the search path
+my $path_separator = ":";
+$ENV{'PATH'} = &util::filename_cat($ENV{'GSDLHOME'}, "bin", $ENV{'GSDLOS'}) .
+$path_separator . &util::filename_cat($ENV{'GSDLHOME'}, "bin", "script") .
+$path_separator . $ENV{'PATH'};
+
+if(!$ARGV[0] || !$ARGV[1]) {
+  print STDERR "Usage: getdocument <collection> <oid>\n";
+  exit;
+}
+
+my $collection = $ARGV[0];
+my $oid = $ARGV[1];
+
+&IncrementalBuild::getDocumentAsXML($collection, $oid);
+
+exit;
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/gimp/flash_button-1.2.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/gimp/flash_button-1.2.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/gimp/flash_button-1.2.pl	(revision 13928)
@@ -0,0 +1,382 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# flash_button.pl 
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+# Modified by Rachid Ben Kaddour <qben@oce.nl> for gimp1.2
+
+# flash_button.pl generates all the flashy javascript type
+# buttons used by Greenstone
+# these are the buttons described in macro files as:
+# top_nav_button
+# nav_bar_button
+# document_button
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use Gimp qw/:auto :DEFAULT/;
+use parsargv;
+use util;
+
+# set trace level to watch functions as they are executed
+#Gimp::set_trace(TRACE_ALL);
+#Gimp::set_trace(TRACE_CALL);
+
+my $gsdl_yellow = "#D2B464";
+my $black = "#000000";
+
+my ($cfg_file, $width, $height, $text, $filenamestem, $fixed_width,
+    $width_space, $whitespace, $dont_center, $bgcolor, $fontcolor, 
+    $fontsize, $fontfoundry, $fontname, $fontweight, $fontslant, $fontwidth, 
+    $fontspacing, $fontregistry, $fontencoding, $image_dir);
+
+sub print_usage {
+    print STDERR "\n  usage: $0 [options]\n\n";
+    print STDERR "  options:\n";
+    print STDERR "   -cfg_file file        configuration file containing one or more\n";
+    print STDERR "                         sets of the following options - use to create\n";
+    print STDERR "                         batches of images\n";
+    print STDERR "   -image_dir directory  directory to create images in [`pwd`]\n";
+    print STDERR "                         this should be full path to existing directory\n";
+    print STDERR "   -width number         width of button [65]\n";
+    print STDERR "   -height number        height of button [30]\n";
+    print STDERR "   -text string          button text\n";
+    print STDERR "   -filenamestem string  filename - two images will be produced -\n";
+    print STDERR "                         filenamestemon.gif and filenamestemof.gif\n";
+    print STDERR "   -fixed_width          fix width of image - if this isn't set\n";
+    print STDERR "                         image will be cropped with with width_space\n";
+    print STDERR "                         space at each side of text\n";
+    print STDERR "   -width_space number   width in pixels of blank space to leave at left\n";
+    print STDERR "                         and right edges of text [1]\n";
+    print STDERR "   -whitespace           add 1 pixel of white space at left and right edges\n";
+    print STDERR "                         of image\n";
+    print STDERR "   -dont_center          don't center text horizontally (only applicable if\n";
+    print STDERR "                         image is fixed width\n";
+    print STDERR "   -bgcolor hex_value    background color of button [$gsdl_yellow]\n";
+    print STDERR "   -fontcolor hex_value  text color [$black]\n";
+    print STDERR "   -fontsize number      font point size [10]\n";
+    print STDERR "   -foundry string       [*]\n";
+    print STDERR "   -fontname string      [lucida]\n";
+    print STDERR "   -fontweight string    [medium]\n";
+    print STDERR "   -fontslant            [r]\n";
+    print STDERR "   -fontwidth            [*]\n";
+    print STDERR "   -fontspacing          [*]\n\n";
+    print STDERR "   -fontregistry         [*]\n\n";
+    print STDERR "   -fontencoding         [*]\n\n";
+}
+
+sub reset_options {
+    $image_dir = "./";
+    $width = 65;
+    $height = 30;
+    $text = "";
+    $filenamestem = "";
+    $fixed_width = 0;
+    $width_space = 1;
+    $whitespace = 0;
+    $dont_center = 0;
+    $bgcolor = $gsdl_yellow;
+    $fontcolor = $black;
+    $fontsize = 10;
+    $fontfoundry = "*";
+    $fontname = "lucida";
+    $fontweight = "medium";
+    $fontslant = "r";
+    $fontwidth = "*";
+    $fontspacing = "*";
+    $fontregistry = "*";
+    $fontencoding = "*";
+}
+
+sub gsdl_flash_button {
+
+    if (!parsargv::parse(\@ARGV, 
+			 'cfg_file/.*/', \$cfg_file,
+			 'image_dir/.*/./', \$image_dir,
+			 'width/^\d+$/65', \$width,
+			 'height/^\d+$/30', \$height,
+			 'text/.*/', \$text,
+			 'filenamestem/.*', \$filenamestem,
+			 'fixed_width', \$fixed_width,
+			 'width_space/^\d+$/1', \$width_space,
+			 'whitespace', \$whitespace,
+			 'dont_center', \$dont_center,
+			 "bgcolor/#[0-9A-Fa-f]{6}/$gsdl_yellow", \$bgcolor,
+			 "fontcolor/#[0-9A-Fa-f]{6}/$black", \$fontcolor,
+			 'fontsize/^\d+$/10', \$fontsize,
+			 'foundry/.*/*', \$fontfoundry,
+			 'fontname/.*/lucida', \$fontname,
+			 'fontweight/.*/medium', \$fontweight,
+			 'fontslant/.*/r', \$fontslant,
+			 'fontwidth/.*/*', \$fontwidth,
+			 'fontspacing/.*/*', \$fontspacing,
+			 'fontregistry/.*/*', \$fontregistry,
+			 'fontencoding/.*/*', \$fontencoding)) {
+	&print_usage();
+	die "flash_button.pl: incorrect options\n";
+    }
+
+    # will create wherever gimp was started up from if we don't do this
+    if ($image_dir eq "./") {
+	$image_dir = `pwd`;
+	chomp $image_dir;
+    }
+
+    # replace any '\n' occurring in text with carriage return
+    $text =~ s/\\n/\n/gi;
+    
+    if ($cfg_file =~ /\w/) {
+	
+	open (CONF, $cfg_file) || die "couldn't open cfg_file $cfg_file\n";
+	while (1) {
+
+	    &reset_options ();
+	
+	    # read image configuration entry
+	    my $status = &read_config_entry (CONF);
+	    if ($filenamestem !~ /\w/) {
+		if ($status) {last;}
+		else {next;}
+	    }
+
+	    &produce_images (0);
+	    if ($status) {last;}
+	}
+
+	close CONF;
+
+    } else {
+
+	&produce_images (0);
+
+    }
+}
+
+sub produce_images {
+    my ($off_img) = @_;
+    
+    # create image, set background color etc.
+    my ($image, $backlayer) = &create_image ($off_img);
+    
+    # set the text if there is any
+    if (length($text)) {
+
+	my $textlayer = gimp_text ($image, $backlayer, 0, 0, $text, 0, 1, 
+				   $fontsize, PIXELS, $fontfoundry, $fontname, $fontweight, 
+				   $fontslant, $fontwidth, $fontspacing, $fontregistry, $fontencoding);
+
+	my $textwidth = gimp_drawable_width($textlayer);
+	my $textheight = gimp_drawable_height($textlayer);
+
+	# check that text fits within image
+	if ($textheight > $height) {
+	    die "'$text' at fontsize of $fontsize pixels does not fit within image\n" . 
+		"$height pixels high. Decrease fontsize or increase image height\n";
+	}
+
+	my $spacers = $width_space * 2;
+	$spacers += 2 if $whitespace;
+
+	if (!$fixed_width || $textwidth > $width) {
+
+	    if ($fixed_width) {
+		print STDERR "WARNING (flash_button.pl): '$text' does not fit within $width pixel fixed width ";
+		print STDERR "image. Image width was increased to ",$textwidth + $spacers, " pixels\n";
+	    }
+	    
+	    $width = $textwidth + $spacers;
+
+	    # recreate image in new size
+	    ($image, $backlayer) = &create_image ($off_img);
+	    $textlayer = gimp_text ($image, $backlayer, 0, 0, $text, 0, 1, 
+				    $fontsize, PIXELS, $fontfoundry, $fontname, $fontweight, 
+				    $fontslant, $fontwidth, $fontspacing, $fontregistry, $fontencoding);
+	    
+	}
+
+	my $y_offset = ($height-$textheight)-int($fontsize/5);
+	my $halfdescenders = "";
+
+	# Russian half descenders (KOI8-R)
+	# -- Uncomment if generating Russian images using KOI8-R encoded text --
+	# $halfdescenders .= chr(195) . chr(253);  # Checked
+	# $halfdescenders .= chr(196) . chr(198) . chr(221) . chr(227) . chr(228); # Unchecked
+
+	# Kazakh (and Russian) half descenders (Helvetica Kazakh font)
+	# -- Uncomment if generating Kazakh or Russian images using text encoded to match
+	#      a Kazakh Helvetica font:
+        #        http://www.unesco.kz/ci/projects/greenstone/kazakh_fonts/helv_k.ttf
+	#    Mapping for this encoding is: mapping/from_uc/kazakh.ump --
+	# $halfdescenders .= chr(178) . chr(179) . chr(187);             # Kazakh specific
+	# $halfdescenders .= chr(196) . chr(214) . chr(217) . chr(228);  # Generic Russian
+	# $halfdescenders .= chr(244) . chr(246) . chr(249);
+
+	# -- Uncomment if generating images using a font with half descenders --
+	# if ($text =~ /[$halfdescenders]/) {
+	    # half descenders - put text at fontsize/10 pixels above bottom
+	    # $y_offset = ($height-$textheight)-int($fontsize/10);
+	# }
+
+	my $descenders = "";
+
+	# Russian descenders (KOI8-R)
+	# -- Uncomment if generating Russian images using KOI8-R encoded text --
+	# $descenders .= chr(210) . chr(213);
+
+	# Kazakh (and Russian) descenders (Helvetica Kazakh font)
+	# -- Uncomment if generating Kazakh or Russian images using text encoded to match
+	#      a Kazakh Helvetica font:
+        #        http://www.unesco.kz/ci/projects/greenstone/kazakh_fonts/helv_k.ttf
+	#    Mapping for this encoding is: mapping/from_uc/kazakh.ump --
+	# $descenders .= chr(189) . chr(190);  # Kazakh specific
+	# $descenders .= chr(240) . chr(243);  # Generic Russian
+
+	if ($text =~ /[gjpqyJ$descenders]/) { ## capital J is a descender in lucida font
+	    # descenders - put text at bottom of image, otherwise 
+	    # go for fontsize/5 pixels above bottom. This is kind of hacky 
+	    # and may need some playing with for different fonts/fontsizes
+	    $y_offset = $height-$textheight;
+	}
+
+	if ($fixed_width) {
+	    if ($dont_center) {
+		# don't center text horizontally (start it width_space pixels from left edge)
+		my $x_offset = $width_space;
+		$x_offset += 1 if $whitespace;
+		gimp_layer_set_offsets ($textlayer, $x_offset, $y_offset);
+	    } else {
+		gimp_layer_set_offsets ($textlayer, ($width-$textwidth)/2, $y_offset);
+	    }
+	} else {
+	    gimp_layer_set_offsets ($textlayer, $spacers / 2, $y_offset); 
+	}
+    }
+    
+    # add pixel of whitespace to each edge if required
+    if ($whitespace) {
+	gimp_rect_select ($image, 0, 0, 1, $height, 0, 0, 0);
+	gimp_edit_clear ($backlayer);
+	gimp_selection_none ($image);
+	gimp_rect_select ($image, $width-1, 0, 1, $height, 0, 0, 0);
+	gimp_edit_clear ($backlayer);
+	gimp_selection_none ($image);
+    }
+    
+    # flatten the image
+    my $finishedlayer = gimp_image_flatten ($image);
+    
+    # make indexed colour 
+    gimp_convert_indexed ($image, NO_DITHER, MAKE_PALETTE, 256, 0, 1,"");
+    
+    # save image
+    my $filename = $filenamestem . "on.gif";
+    $filename = $filenamestem . "of.gif" if $off_img;
+    $filename = &util::filename_cat ($image_dir, $filename);
+
+    gimp_file_save (RUN_NONINTERACTIVE, $image, $finishedlayer, $filename, $filename);
+
+    &produce_images (1) unless $off_img;    
+}
+
+sub create_image {
+    my ($off_img) = @_;
+
+    # create the image
+    my $image = gimp_image_new ($width, $height, RGB_IMAGE);
+    
+    # background layer
+    my $backlayer = gimp_layer_new ($image, $width, $height, RGB_IMAGE, 
+				    "BGLayer", 100, NORMAL_MODE);
+    
+    # add the background layer
+    gimp_image_add_layer ($image, $backlayer, 0);
+    
+    # set colour of background
+    gimp_palette_set_foreground ($bgcolor);
+    
+    # clear the background
+    gimp_selection_all ($image);
+    gimp_edit_clear ($backlayer);
+    gimp_selection_none ($image);
+    
+    # create the gradient background
+    gimp_blend ($backlayer, 0, NORMAL_MODE, LINEAR, 70, 0, REPEAT_NONE, 0, 0, 0, 5, $height-3, 5, 0);
+    
+    # adjust lightness of "off" gif
+    gimp_hue_saturation ($backlayer, 0, 0, 100, 0) if $off_img;
+
+    # set colour of text
+    gimp_palette_set_foreground ($fontcolor);
+
+    return ($image, $backlayer);
+}
+
+# returns 1 if this is the last entry,
+sub read_config_entry {
+    my ($handle) = @_;
+
+    my $line = "";
+    while (defined ($line = <$handle>)) {
+	next unless $line =~ /\w/;
+	my @line = ();
+	if ($line =~ /^\-+/) {return 0;}
+	$line =~ s/^\#.*$//;   # remove comments
+	$line =~ s/\cM|\cJ//g; # remove end-of-line characters
+	$line =~ s/^\s+//;     # remove initial white space
+	while ($line =~ s/\s*(\"[^\"]*\"|\'[^\']*\'|\S+)\s*//) {
+	    if (defined $1) {
+		# remove any enclosing quotes
+		my $entry = $1;
+		$entry =~ s/^([\"\'])(.*)\1$/$2/;
+
+		# substitute any environment variables
+		$entry =~ s/\$(\w+)/$ENV{$1}/g;
+		$entry =~ s/\$\{(\w+)\}/$ENV{$1}/g;
+		
+		push (@line, $entry);
+	    } else {
+		push (@line, "");
+	    }
+	}
+	if (scalar (@line) == 2 && defined ${$line[0]}) {
+	    ${$line[0]} = $line[1];
+	}
+    }
+    return 1;
+}
+    
+sub query {
+
+  gimp_install_procedure("gsdl_flash_button", "create flashy javascript buttons for gsdl",
+                        "", "Stefan Boddie", "Stefan Boddie", "2000-03-10",
+                        "<Toolbox>/Xtns/gsdl_flash_button", "*", &PROC_EXTENSION,
+                        [[PARAM_INT32, "run_mode", "Interactive, [non-interactive]"]], []);
+}
+
+Gimp::on_net { gsdl_flash_button; };
+exit main;
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/gimp/flash_button.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/gimp/flash_button.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/gimp/flash_button.pl	(revision 13928)
@@ -0,0 +1,351 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# flash_button.pl 
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+# flash_button.pl generates all the flashy javascript type
+# buttons used by Greenstone
+# these are the buttons described in macro files as:
+# top_nav_button
+# nav_bar_button
+# document_button
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use Gimp;
+use parsargv;
+use util;
+use unicode;
+
+
+# set trace level to watch functions as they are executed
+#Gimp::set_trace(TRACE_ALL);
+#Gimp::set_trace(TRACE_CALL);
+
+my $gsdl_yellow = "#D2B464";
+my $black = "#000000";
+
+my ($cfg_file, $width, $height, $text, $filenamestem, $fixed_width,
+    $width_space, $whitespace, $dont_center, $bgcolor, $fontcolor, 
+    $fontsize, $foundry, $fontname, $fontweight, $fontslant, $fontwidth, 
+    $fontspacing, $image_dir);
+
+sub print_usage {
+    print STDERR "\n  usage: $0 [options]\n\n";
+    print STDERR "  options:\n";
+    print STDERR "   -cfg_file file        configuration file containing one or more\n";
+    print STDERR "                         sets of the following options - use to create\n";
+    print STDERR "                         batches of images\n";
+    print STDERR "   -image_dir directory  directory to create images in [`pwd`]\n";
+    print STDERR "                         this should be full path to existing directory\n";
+    print STDERR "   -width number         width of button [65]\n";
+    print STDERR "   -height number        height of button [30]\n";
+    print STDERR "   -text string          button text\n";
+    print STDERR "   -filenamestem string  filename - two images will be produced -\n";
+    print STDERR "                         filenamestemon.gif and filenamestemof.gif\n";
+    print STDERR "   -fixed_width          fix width of image - if this isn't set\n";
+    print STDERR "                         image will be cropped with with width_space\n";
+    print STDERR "                         space at each side of text\n";
+    print STDERR "   -width_space number   width in pixels of blank space to leave at left\n";
+    print STDERR "                         and right edges of text [1]\n";
+    print STDERR "   -whitespace           add 1 pixel of white space at left and right edges\n";
+    print STDERR "                         of image\n";
+    print STDERR "   -dont_center          don't center text horizontally (only applicable if\n";
+    print STDERR "                         image is fixed width\n";
+    print STDERR "   -bgcolor hex_value    background color of button [$gsdl_yellow]\n";
+    print STDERR "   -fontcolor hex_value  text color [$black]\n";
+    print STDERR "   -fontsize number      font point size [10]\n";
+    print STDERR "   -foundry string       [*]\n";
+    print STDERR "   -fontname string      [lucida]\n";
+    print STDERR "   -fontweight string    [medium]\n";
+    print STDERR "   -fontslant            [r]\n";
+    print STDERR "   -fontwidth            [*]\n";
+    print STDERR "   -fontspacing          [*]\n\n";
+}
+
+sub reset_options {
+    $image_dir = "./";
+    $width = 65;
+    $height = 30;
+    $text = "";
+    $filenamestem = "";
+    $fixed_width = 0;
+    $width_space = 1;
+    $whitespace = 0;
+    $dont_center = 0;
+    $bgcolor = $gsdl_yellow;
+    $fontcolor = $black;
+    $fontsize = 10;
+    $foundry = "*";
+    $fontname = "lucida";
+    $fontweight = "medium";
+    $fontslant = "r";
+    $fontwidth = "*";
+    $fontspacing = "*";
+}
+
+sub gsdl_flash_button {
+
+    if (!parsargv::parse(\@ARGV, 
+			 'cfg_file/.*/', \$cfg_file,
+			 'image_dir/.*/./', \$image_dir,
+			 'width/^\d+$/65', \$width,
+			 'height/^\d+$/30', \$height,
+			 'text/.*/', \$text,
+			 'filenamestem/.*', \$filenamestem,
+			 'fixed_width', \$fixed_width,
+			 'width_space/^\d+$/1', \$width_space,
+			 'whitespace', \$whitespace,
+			 'dont_center', \$dont_center,
+			 "bgcolor/#[0-9A-Fa-f]{6}/$gsdl_yellow", \$bgcolor,
+			 "fontcolor/#[0-9A-Fa-f]{6}/$black", \$fontcolor,
+			 'fontsize/^\d+$/10', \$fontsize,
+			 'foundry/.*/*', \$foundry,
+			 'fontname/.*/lucida', \$fontname,
+			 'fontweight/.*/medium', \$fontweight,
+			 'fontslant/.*/r', \$fontslant,
+			 'fontwidth/.*/*', \$fontwidth,
+			 'fontspacing/.*/*', \$fontspacing)) {
+	&print_usage();
+	die "flash_button.pl: incorrect options\n";
+    }
+
+    # will create wherever gimp was started up from if we don't do this
+    if ($image_dir eq "./") {
+	$image_dir = `pwd`;
+	chomp $image_dir;
+    }
+
+    # replace any '\n' occurring in text with carriage return
+    $text =~ s/\\n/\n/gi;
+
+    if ($cfg_file =~ /\w/) {
+	
+	open (CONF, $cfg_file) || die "couldn't open cfg_file $cfg_file\n";
+	while (1) {
+
+	    &reset_options ();
+	
+	    # read image configuration entry
+	    my $status = &read_config_entry (CONF);
+	    if ($filenamestem !~ /\w/) {
+		if ($status) {last;}
+		else {next;}
+	    }
+
+	    &produce_images (0);
+	    if ($status) {last;}
+	}
+
+	close CONF;
+
+    } else {
+
+	&produce_images (0);
+
+    }
+}
+
+sub produce_images {
+    my ($off_img) = @_;
+    
+    # create image, set background color etc.
+    my ($image, $backlayer) = &create_image ($off_img);
+    
+    # set the text if there is any
+    if (length($text)) {
+
+	my $textlayer = gimp_text ($image, $backlayer, 0, 0, $text, 0, 1, 
+				   $fontsize, PIXELS, $foundry, $fontname, $fontweight, 
+				   $fontslant, $fontwidth, $fontspacing);
+	
+
+	my $textwidth = gimp_drawable_width($textlayer);
+	my $textheight = gimp_drawable_height($textlayer);
+
+	# check that text fits within image
+	if ($textheight > $height) {
+	    die "'$text' at fontsize of $fontsize pixels does not fit within image\n" . 
+		"$height pixels high. Decrease fontsize or increase image height\n";
+	}
+
+	my $spacers = $width_space * 2;
+	$spacers += 2 if $whitespace;
+
+	if (!$fixed_width || $textwidth > $width) {
+
+	    if ($fixed_width) {
+		print STDERR "WARNING (flash_button.pl): '$text' does not fit within $width pixel fixed width ";
+		print STDERR "image. Image width was increased to ",$textwidth + $spacers, " pixels\n";
+	    }
+	    
+	    $width = $textwidth + $spacers;
+
+	    # recreate image in new size
+	    ($image, $backlayer) = &create_image ($off_img);
+	    $textlayer = gimp_text ($image, $backlayer, 0, 0, $text, 0, 1, 
+				    $fontsize, PIXELS, $foundry, $fontname, $fontweight, 
+				    $fontslant, $fontwidth, $fontspacing);
+	    
+	}
+
+	my $y_offset = ($height-$textheight)-int($fontsize/5);
+
+	my $descenders = "";
+
+	# russian descenders (KOI8-R)
+	# $descenders .= chr(0xD2);
+	# $descenders .= chr(0xD5);
+
+	if ($text =~ /[gjpqyJ$descenders]/) { ## capital J is a descender in lucida font
+	    # descenders - put text at bottom of image, otherwise 
+	    # go for fontsize/5 pixels above bottom. This is kind of hacky 
+	    # and may need some playing with for different fonts/fontsizes
+	    $y_offset = $height-$textheight;
+	}
+
+	if ($fixed_width) {
+	    if ($dont_center) {
+		# don't center text horizontally (start it width_space pixels from left edge)
+		my $x_offset = $width_space;
+		$x_offset += 1 if $whitespace;
+		gimp_layer_set_offsets ($textlayer, $x_offset, $y_offset);
+	    } else {
+		gimp_layer_set_offsets ($textlayer, ($width-$textwidth)/2, $y_offset);
+	    }
+	} else {
+	    gimp_layer_set_offsets ($textlayer, $spacers / 2, $y_offset); 
+	}
+    }
+    
+    # add pixel of whitespace to each edge if required
+    if ($whitespace) {
+	gimp_rect_select ($image, 0, 0, 1, $height, 0, 0, 0);
+	gimp_edit_clear ($image, $backlayer);
+	gimp_selection_none ($image);
+	gimp_rect_select ($image, $width-1, 0, 1, $height, 0, 0, 0);
+	gimp_edit_clear ($image, $backlayer);
+	gimp_selection_none ($image);
+    }
+    
+    # flatten the image
+    my $finishedlayer = gimp_image_flatten ($image);
+    
+    # make indexed colour 
+    gimp_convert_indexed ($image, 0, 256);
+    
+    # save image
+    my $filename = $filenamestem . "on.gif";
+    $filename = $filenamestem . "of.gif" if $off_img;
+    $filename = &util::filename_cat ($image_dir, $filename);
+
+    gimp_file_save (RUN_NONINTERACTIVE, $image, $finishedlayer, $filename, $filename);
+
+    &produce_images (1) unless $off_img;    
+}
+
+sub create_image {
+    my ($off_img) = @_;
+
+    # create the image
+    my $image = gimp_image_new ($width, $height, RGB_IMAGE);
+    
+    # background layer
+    my $backlayer = gimp_layer_new ($image, $width, $height, RGB_IMAGE, 
+				    "BGLayer", 100, NORMAL_MODE);
+    
+    # add the background layer
+    gimp_image_add_layer ($image, $backlayer, 0);
+    
+    # set colour of background
+    gimp_palette_set_foreground ($bgcolor);
+    
+    # clear the background
+    gimp_selection_all ($image);
+    gimp_edit_clear ($image, $backlayer);
+    gimp_selection_none ($image);
+    
+    # create the gradient background
+    gimp_blend ($image, $backlayer, 0, NORMAL_MODE, LINEAR, 70, 0, REPEAT_NONE, 0, 0, 0, 5, $height-3, 5, 0);
+    
+    # adjust lightness of "off" gif
+    gimp_hue_saturation ($image, $backlayer, 0, 0, 100, 0) if $off_img;
+
+    # set colour of text
+    gimp_palette_set_foreground ($fontcolor);
+
+    return ($image, $backlayer);
+}
+
+# returns 1 if this is the last entry,
+sub read_config_entry {
+    my ($handle) = @_;
+
+    my $line = "";
+    while (defined ($line = <$handle>)) {
+	next unless $line =~ /\w/;
+	my @line = ();
+	if ($line =~ /^\-+/) {return 0;}
+	$line =~ s/^\#.*$//;   # remove comments
+	$line =~ s/\cM|\cJ//g; # remove end-of-line characters
+	$line =~ s/^\s+//;     # remove initial white space
+	while ($line =~ s/\s*(\"[^\"]*\"|\'[^\']*\'|\S+)\s*//) {
+	    if (defined $1) {
+		# remove any enclosing quotes
+		my $entry = $1;
+		$entry =~ s/^([\"\'])(.*)\1$/$2/;
+
+		# substitute any environment variables
+		$entry =~ s/\$(\w+)/$ENV{$1}/g;
+		$entry =~ s/\$\{(\w+)\}/$ENV{$1}/g;
+		
+		push (@line, $entry);
+	    } else {
+		push (@line, "");
+	    }
+	}
+	if (scalar (@line) == 2 && defined ${$line[0]}) {
+	    ${$line[0]} = $line[1];
+	}
+    }
+    return 1;
+}
+    
+sub query {
+
+  gimp_install_procedure("gsdl_flash_button", "create flashy javascript buttons for gsdl",
+                        "", "Stefan Boddie", "Stefan Boddie", "2000-03-10",
+                        "<Toolbox>/Xtns/gsdl_flash_button", "*", &PROC_EXTENSION,
+                        [[PARAM_INT32, "run_mode", "Interactive, [non-interactive]"]], []);
+}
+
+sub net {
+  gsdl_flash_button;
+}
+
+exit main;
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/gimp/green_bar-1.2.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/gimp/green_bar-1.2.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/gimp/green_bar-1.2.pl	(revision 13928)
@@ -0,0 +1,342 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# green_bar.pl 
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+# Modified by Rachid Ben Kaddour <qben@oce.nl> for gimp1.2
+
+# green_bar.pl generates all the black on green gradient background
+# images used by Greenstone. 
+# these are the icons described in macro files as:
+# green version of nav_bar_button
+# green_bar_left_aligned
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use Gimp qw/:auto :DEFAULT/;
+use parsargv;
+use util;
+use unicode;
+
+# set trace level to watch functions as they are executed
+#Gimp::set_trace(TRACE_ALL);
+#Gimp::set_trace(TRACE_CALL);
+
+my $gsdl_green = "#96c19b";
+my $black = "#000000";
+
+my ($cfg_file, $width, $height, $text, $filename, $width_space, 
+    $dont_center, $bgcolor, $fontcolor, $fontsize, $foundry, $fontname, 
+    $fontweight, $fontslant, $fontwidth, $fontspacing, $fontregistry, $fontencoding, $image_dir);
+
+sub print_usage {
+    print STDERR "\n  usage: $0 [options] macrofile\n\n";
+    print STDERR "  options:\n";
+    print STDERR "   -cfg_file file        configuration file containing one or more\n";
+    print STDERR "                         sets of the following options - use to create\n";
+    print STDERR "                         batches of images\n";
+    print STDERR "   -image_dir directory  directory to create images in [`pwd`]\n";
+    print STDERR "                         this should be full path to existing directory\n";
+    print STDERR "   -width number         width of bar [87]\n";
+    print STDERR "   -height number        height of bar [17]\n";
+    print STDERR "   -text string          icon text\n";
+    print STDERR "   -filename string      filename of resulting image\n";
+    print STDERR "   -width_space number   width in pixels of blank space to leave at left\n";
+    print STDERR "                         and right edges of text [1]\n";
+    print STDERR "   -dont_center          don't center text horizontally\n";
+    print STDERR "   -bgcolor hex_value    background color of bar [$gsdl_green]\n";
+    print STDERR "   -fontcolor hex_value  text color [$black]\n";
+    print STDERR "   -fontsize number      font point size [17]\n";
+    print STDERR "   -foundry string       [*]\n";
+    print STDERR "   -fontname string      [lucida]\n";
+    print STDERR "   -fontweight string    [medium]\n";
+    print STDERR "   -fontslant            [r]\n";
+    print STDERR "   -fontwidth            [*]\n";
+    print STDERR "   -fontspacing          [*]\n";
+    print STDERR "   -fontregistry         [*]\n";
+    print STDERR "   -fontencoding         [*]\n\n";
+}
+
+sub reset_options {
+    $image_dir = "./";
+    $width = 87;
+    $height = 17;
+    $text = "";
+    $filename = "";
+    $width_space = 1;
+    $dont_center = 0;
+    $bgcolor = $gsdl_green;
+    $fontcolor = $black;
+    $fontsize = 17;
+    $foundry = "*";
+    $fontname = "lucida";
+    $fontweight = "medium";
+    $fontslant = "r";
+    $fontwidth = "*";
+    $fontspacing = "*";
+    $fontregistry = "*";
+    $fontencoding = "*";
+}
+
+sub gsdl_green_bar {
+
+    if (!parsargv::parse(\@ARGV, 
+			 'cfg_file/.*/', \$cfg_file,
+			 'image_dir/.*/./', \$image_dir,
+			 'width/^\d+$/87', \$width,
+			 'height/^\d+$/17', \$height,
+			 'text/.*/', \$text,
+			 'filename/.*', \$filename,
+			 'width_space/^\d+$/1', \$width_space,
+			 'dont_center', \$dont_center,
+			 "bgcolor/#[0-9A-Fa-f]{6}/$gsdl_green", \$bgcolor,
+			 "fontcolor/#[0-9A-Fa-f]{6}/$black", \$fontcolor,
+			 'fontsize/^\d+$/17', \$fontsize,
+			 'foundry/.*/*', \$foundry,
+			 'fontname/.*/lucida', \$fontname,
+			 'fontweight/.*/medium', \$fontweight,
+			 'fontslant/.*/r', \$fontslant,
+			 'fontwidth/.*/*', \$fontwidth,
+			 'fontregistry/.*/*', \$fontregistry,
+			 'fontencoding/.*/*', \$fontencoding,
+			 'fontspacing/.*/*', \$fontspacing)) {
+	&print_usage();
+	die "green_bar.pl: incorrect options\n";
+    }
+
+    # will create wherever gimp was started up from if we don't do this
+    if ($image_dir eq "./") {
+	$image_dir = `pwd`;
+	chomp $image_dir;
+    }
+    
+    if ($cfg_file =~ /\w/) {
+	
+	open (CONF, $cfg_file) || die "couldn't open cfg_file $cfg_file\n";
+	while (1) {
+
+	    &reset_options ();
+	
+	    # read image configuration entry
+	    my $status = &read_config_entry (CONF);
+	    if ($filename !~ /\w/) {
+		if ($status) {last;}
+		else {next;}
+	    }
+
+	    &produce_image ();
+	    if ($status) {last;}
+	}
+
+	close CONF;
+
+    } else {
+
+	&produce_image ();
+
+    }
+}
+
+sub produce_image {
+    
+    # create image, set background color etc.
+    my ($image, $backlayer) = &create_image ();
+    
+    # set the text if there is any
+    if (length($text)) {
+
+	my $textlayer = gimp_text ($image, $backlayer, 0, 0, $text, 0, 1, 
+				   $fontsize, PIXELS, $foundry, $fontname, $fontweight, 
+				   $fontslant, $fontwidth, $fontspacing, $fontregistry, $fontencoding);
+	
+
+	my $textwidth = gimp_drawable_width($textlayer);
+	my $textheight = gimp_drawable_height($textlayer);
+
+	# check that text fits within image
+	if ($textheight > $height) {
+	    die "'$text' at fontsize of $fontsize pixels does not fit within image\n" . 
+		"$height pixels high. Decrease fontsize or increase image height\n";
+	}
+
+	my $spacers = $width_space * 2;
+
+	if ($textwidth > $width) {
+
+	    print STDERR "WARNING (green_bar.pl): '$text' does not fit within $width pixel fixed width ";
+	    print STDERR "image. Image width was increased to ",$textwidth + $spacers, " pixels\n";
+	    
+	    $width = $textwidth + $spacers;
+
+	    # recreate image in new size
+	    ($image, $backlayer) = &create_image ();
+	    $textlayer = gimp_text ($image, $backlayer, 0, 0, $text, 0, 1, 
+				    $fontsize, PIXELS, $foundry, $fontname, $fontweight, 
+				    $fontslant, $fontwidth, $fontspacing, $fontregistry, $fontencoding);
+	    
+	}
+
+	my $y_offset = ($height-$textheight)-int($fontsize/5);
+
+	my $halfdescenders = "";
+
+	# Russian half descenders (KOI8-R)
+	# -- Uncomment if generating Russian images using KOI8-R encoded text --
+	# $halfdescenders .= chr(195) . chr(253);  # Checked
+	# $halfdescenders .= chr(196) . chr(198) . chr(221) . chr(227) . chr(228); # Unchecked
+
+	# Kazakh (and Russian) half descenders (Helvetica Kazakh font)
+	# -- Uncomment if generating Kazakh or Russian images using text encoded to match
+	#      a Kazakh Helvetica font:
+        #        http://www.unesco.kz/ci/projects/greenstone/kazakh_fonts/helv_k.ttf
+	#    Mapping for this encoding is: mapping/from_uc/kazakh.ump --
+	# $halfdescenders .= chr(178) . chr(179) . chr(187);             # Kazakh specific
+	# $halfdescenders .= chr(196) . chr(214) . chr(217) . chr(228);  # Generic Russian
+	# $halfdescenders .= chr(244) . chr(246) . chr(249);
+
+	# -- Uncomment if generating images using a font with half descenders --
+	# if ($text =~ /[$halfdescenders]/) {
+	    # half descenders - put text at fontsize/10 pixels above bottom
+	    # $y_offset = ($height-$textheight)-int($fontsize/10);
+	# }
+
+	my $descenders = "";
+
+	# Russian descenders (KOI8-R)
+	# -- Uncomment if generating Russian images using KOI8-R encoded text --
+	# $descenders .= chr(210) . chr(213);
+
+	# Kazakh (and Russian) descenders (Helvetica Kazakh font)
+	# -- Uncomment if generating Kazakh or Russian images using text encoded to match
+	#      a Kazakh Helvetica font:
+        #        http://www.unesco.kz/ci/projects/greenstone/kazakh_fonts/helv_k.ttf
+	#    Mapping for this encoding is: mapping/from_uc/kazakh.ump --
+	# $descenders .= chr(189) . chr(190);  # Kazakh specific
+	# $descenders .= chr(240) . chr(243);  # Generic Russian
+
+	if ($text =~ /[gjpqyJ$descenders]/) { ## capital J is a descender in lucida font
+	    # descenders - put text at bottom of image, otherwise 
+	    # go for fontsize/5 pixels above bottom. This is kind of hacky 
+	    # and may need some playing with for different fonts/fontsizes
+	    $y_offset = $height-$textheight;
+	}
+
+	if ($dont_center) {
+	    # don't center text horizontally (start it width_space pixels from left edge)
+	    my $x_offset = $width_space;
+	    gimp_layer_set_offsets ($textlayer, $x_offset, $y_offset);
+	} else {
+	    gimp_layer_set_offsets ($textlayer, ($width-$textwidth)/2, $y_offset);
+	}
+    }
+    
+    # flatten the image
+    my $finishedlayer = gimp_image_flatten ($image);
+    
+    # make indexed colour 
+    gimp_convert_indexed ($image, NO_DITHER, MAKE_PALETTE, 256, 0, 1,"");
+    
+    # save image
+    $filename = &util::filename_cat ($image_dir, $filename);
+
+    gimp_file_save (RUN_NONINTERACTIVE, $image, $finishedlayer, $filename, $filename);
+
+}
+
+sub create_image {
+    # create the image
+    my $image = gimp_image_new ($width, $height, RGB_IMAGE);
+    
+    # background layer
+    my $backlayer = gimp_layer_new ($image, $width, $height, RGB_IMAGE, 
+				    "BGLayer", 100, NORMAL_MODE);
+    
+    # add the background layer
+    gimp_image_add_layer ($image, $backlayer, 0);
+    
+    # set colour of background
+    gimp_palette_set_foreground ($bgcolor);
+    
+    # clear the background
+    gimp_selection_all ($image);
+    gimp_edit_clear ($backlayer);
+    gimp_selection_none ($image);
+    
+    # create the gradient background
+    gimp_blend ($backlayer, 0, NORMAL_MODE, LINEAR, 70, 0, REPEAT_NONE, 0, 0, 0, 5, $height-3, 5, 0);
+
+    # set colour of text
+    gimp_palette_set_foreground ($fontcolor);
+
+    return ($image, $backlayer);
+}
+
+# returns 1 if this is the last entry,
+sub read_config_entry {
+    my ($handle) = @_;
+
+    my $line = "";
+    while (defined ($line = <$handle>)) {
+	next unless $line =~ /\w/;
+	my @line = ();
+	if ($line =~ /^\-+/) {return 0;}
+	$line =~ s/^\#.*$//;   # remove comments
+	$line =~ s/\cM|\cJ//g; # remove end-of-line characters
+	$line =~ s/^\s+//;     # remove initial white space
+	while ($line =~ s/\s*(\"[^\"]*\"|\'[^\']*\'|\S+)\s*//) {
+	    if (defined $1) {
+		# remove any enclosing quotes
+		my $entry = $1;
+		$entry =~ s/^([\"\'])(.*)\1$/$2/;
+
+		# substitute any environment variables
+		$entry =~ s/\$(\w+)/$ENV{$1}/g;
+		$entry =~ s/\$\{(\w+)\}/$ENV{$1}/g;
+		
+		push (@line, $entry);
+	    } else {
+		push (@line, "");
+	    }
+	}
+	if (scalar (@line) == 2 && defined ${$line[0]}) {
+	    ${$line[0]} = $line[1];
+	}
+    }
+    return 1;
+}
+    
+sub query {
+
+  gimp_install_procedure("gsdl_green_bar", "create green bar icons for gsdl",
+                        "", "Stefan Boddie", "Stefan Boddie", "2000-03-10",
+                        "<Toolbox>/Xtns/gsdl_green_bar", "*", &PROC_EXTENSION,
+                        [[PARAM_INT32, "run_mode", "Interactive, [non-interactive]"]], []);
+}
+
+Gimp::on_net { gsdl_green_bar; };
+exit main;
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/gimp/green_bar.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/gimp/green_bar.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/gimp/green_bar.pl	(revision 13928)
@@ -0,0 +1,307 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# green_bar.pl 
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+# green_bar.pl generates all the black on green gradient background
+# images used by Greenstone. 
+# these are the icons described in macro files as:
+# green version of nav_bar_button
+# green_bar_left_aligned
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use Gimp;
+use parsargv;
+use util;
+use unicode;
+
+# set trace level to watch functions as they are executed
+#Gimp::set_trace(TRACE_ALL);
+#Gimp::set_trace(TRACE_CALL);
+
+my $gsdl_green = "#96c19b";
+my $black = "#000000";
+
+my ($cfg_file, $width, $height, $text, $filename, $width_space, 
+    $dont_center, $bgcolor, $fontcolor, $fontsize, $foundry, $fontname, 
+    $fontweight, $fontslant, $fontwidth, $fontspacing, $image_dir);
+
+sub print_usage {
+    print STDERR "\n  usage: $0 [options] macrofile\n\n";
+    print STDERR "  options:\n";
+    print STDERR "   -cfg_file file        configuration file containing one or more\n";
+    print STDERR "                         sets of the following options - use to create\n";
+    print STDERR "                         batches of images\n";
+    print STDERR "   -image_dir directory  directory to create images in [`pwd`]\n";
+    print STDERR "                         this should be full path to existing directory\n";
+    print STDERR "   -width number         width of bar [87]\n";
+    print STDERR "   -height number        height of bar [17]\n";
+    print STDERR "   -text string          icon text\n";
+    print STDERR "   -filename string      filename of resulting image\n";
+    print STDERR "   -width_space number   width in pixels of blank space to leave at left\n";
+    print STDERR "                         and right edges of text [1]\n";
+    print STDERR "   -dont_center          don't center text horizontally\n";
+    print STDERR "   -bgcolor hex_value    background color of bar [$gsdl_green]\n";
+    print STDERR "   -fontcolor hex_value  text color [$black]\n";
+    print STDERR "   -fontsize number      font point size [17]\n";
+    print STDERR "   -foundry string       [*]\n";
+    print STDERR "   -fontname string      [lucida]\n";
+    print STDERR "   -fontweight string    [medium]\n";
+    print STDERR "   -fontslant            [r]\n";
+    print STDERR "   -fontwidth            [*]\n";
+    print STDERR "   -fontspacing          [*]\n\n";
+}
+
+sub reset_options {
+    $image_dir = "./";
+    $width = 87;
+    $height = 17;
+    $text = "";
+    $filename = "";
+    $width_space = 1;
+    $dont_center = 0;
+    $bgcolor = $gsdl_green;
+    $fontcolor = $black;
+    $fontsize = 17;
+    $foundry = "*";
+    $fontname = "lucida";
+    $fontweight = "medium";
+    $fontslant = "r";
+    $fontwidth = "*";
+    $fontspacing = "*";
+}
+
+sub gsdl_green_bar {
+
+    if (!parsargv::parse(\@ARGV, 
+			 'cfg_file/.*/', \$cfg_file,
+			 'image_dir/.*/./', \$image_dir,
+			 'width/^\d+$/87', \$width,
+			 'height/^\d+$/17', \$height,
+			 'text/.*/', \$text,
+			 'filename/.*', \$filename,
+			 'width_space/^\d+$/1', \$width_space,
+			 'dont_center', \$dont_center,
+			 "bgcolor/#[0-9A-Fa-f]{6}/$gsdl_green", \$bgcolor,
+			 "fontcolor/#[0-9A-Fa-f]{6}/$black", \$fontcolor,
+			 'fontsize/^\d+$/17', \$fontsize,
+			 'foundry/.*/*', \$foundry,
+			 'fontname/.*/lucida', \$fontname,
+			 'fontweight/.*/medium', \$fontweight,
+			 'fontslant/.*/r', \$fontslant,
+			 'fontwidth/.*/*', \$fontwidth,
+			 'fontspacing/.*/*', \$fontspacing)) {
+	&print_usage();
+	die "green_bar.pl: incorrect options\n";
+    }
+
+    # will create wherever gimp was started up from if we don't do this
+    if ($image_dir eq "./") {
+	$image_dir = `pwd`;
+	chomp $image_dir;
+    }
+    
+    if ($cfg_file =~ /\w/) {
+	
+	open (CONF, $cfg_file) || die "couldn't open cfg_file $cfg_file\n";
+	while (1) {
+
+	    &reset_options ();
+	
+	    # read image configuration entry
+	    my $status = &read_config_entry (CONF);
+	    if ($filename !~ /\w/) {
+		if ($status) {last;}
+		else {next;}
+	    }
+
+	    &produce_image ();
+	    if ($status) {last;}
+	}
+
+	close CONF;
+
+    } else {
+
+	&produce_image ();
+
+    }
+}
+
+sub produce_image {
+    
+    # create image, set background color etc.
+    my ($image, $backlayer) = &create_image ();
+    
+    # set the text if there is any
+    if (length($text)) {
+
+	my $textlayer = gimp_text ($image, $backlayer, 0, 0, $text, 0, 1, 
+				   $fontsize, PIXELS, $foundry, $fontname, $fontweight, 
+				   $fontslant, $fontwidth, $fontspacing);
+	
+
+	my $textwidth = gimp_drawable_width($textlayer);
+	my $textheight = gimp_drawable_height($textlayer);
+
+	# check that text fits within image
+	if ($textheight > $height) {
+	    die "'$text' at fontsize of $fontsize pixels does not fit within image\n" . 
+		"$height pixels high. Decrease fontsize or increase image height\n";
+	}
+
+	my $spacers = $width_space * 2;
+
+	if ($textwidth > $width) {
+
+	    print STDERR "WARNING (green_bar.pl): '$text' does not fit within $width pixel fixed width ";
+	    print STDERR "image. Image width was increased to ",$textwidth + $spacers, " pixels\n";
+	    
+	    $width = $textwidth + $spacers;
+
+	    # recreate image in new size
+	    ($image, $backlayer) = &create_image ();
+	    $textlayer = gimp_text ($image, $backlayer, 0, 0, $text, 0, 1, 
+				    $fontsize, PIXELS, $foundry, $fontname, $fontweight, 
+				    $fontslant, $fontwidth, $fontspacing);
+	    
+	}
+
+	my $y_offset = ($height-$textheight)-int($fontsize/5);
+
+	my $descenders = "";
+
+	# russian descenders (KOI8-R)
+	# $descenders .= chr(0xD2);
+	# $descenders .= chr(0xD5);
+
+	if ($text =~ /[gjpqyJ$descenders]/) { ## capital J is a descender in lucida font
+	    # descenders - put text at bottom of image, otherwise 
+	    # go for fontsize/5 pixels above bottom. This is kind of hacky 
+	    # and may need some playing with for different fonts/fontsizes
+	    $y_offset = $height-$textheight;
+	}
+
+	if ($dont_center) {
+	    # don't center text horizontally (start it width_space pixels from left edge)
+	    my $x_offset = $width_space;
+	    gimp_layer_set_offsets ($textlayer, $x_offset, $y_offset);
+	} else {
+	    gimp_layer_set_offsets ($textlayer, ($width-$textwidth)/2, $y_offset);
+	}
+    }
+    
+    # flatten the image
+    my $finishedlayer = gimp_image_flatten ($image);
+    
+    # make indexed colour 
+    gimp_convert_indexed ($image, 0, 256);
+    
+    # save image
+    $filename = &util::filename_cat ($image_dir, $filename);
+
+    gimp_file_save (RUN_NONINTERACTIVE, $image, $finishedlayer, $filename, $filename);
+
+}
+
+sub create_image {
+    # create the image
+    my $image = gimp_image_new ($width, $height, RGB_IMAGE);
+    
+    # background layer
+    my $backlayer = gimp_layer_new ($image, $width, $height, RGB_IMAGE, 
+				    "BGLayer", 100, NORMAL_MODE);
+    
+    # add the background layer
+    gimp_image_add_layer ($image, $backlayer, 0);
+    
+    # set colour of background
+    gimp_palette_set_foreground ($bgcolor);
+    
+    # clear the background
+    gimp_selection_all ($image);
+    gimp_edit_clear ($image, $backlayer);
+    gimp_selection_none ($image);
+    
+    # create the gradient background
+    gimp_blend ($image, $backlayer, 0, NORMAL_MODE, LINEAR, 70, 0, REPEAT_NONE, 0, 0, 0, 5, $height-3, 5, 0);
+
+    # set colour of text
+    gimp_palette_set_foreground ($fontcolor);
+
+    return ($image, $backlayer);
+}
+
+# returns 1 if this is the last entry,
+sub read_config_entry {
+    my ($handle) = @_;
+
+    my $line = "";
+    while (defined ($line = <$handle>)) {
+	next unless $line =~ /\w/;
+	my @line = ();
+	if ($line =~ /^\-+/) {return 0;}
+	$line =~ s/^\#.*$//;   # remove comments
+	$line =~ s/\cM|\cJ//g; # remove end-of-line characters
+	$line =~ s/^\s+//;     # remove initial white space
+	while ($line =~ s/\s*(\"[^\"]*\"|\'[^\']*\'|\S+)\s*//) {
+	    if (defined $1) {
+		# remove any enclosing quotes
+		my $entry = $1;
+		$entry =~ s/^([\"\'])(.*)\1$/$2/;
+
+		# substitute any environment variables
+		$entry =~ s/\$(\w+)/$ENV{$1}/g;
+		$entry =~ s/\$\{(\w+)\}/$ENV{$1}/g;
+		
+		push (@line, $entry);
+	    } else {
+		push (@line, "");
+	    }
+	}
+	if (scalar (@line) == 2 && defined ${$line[0]}) {
+	    ${$line[0]} = $line[1];
+	}
+    }
+    return 1;
+}
+    
+sub query {
+
+  gimp_install_procedure("gsdl_green_bar", "create green bar icons for gsdl",
+                        "", "Stefan Boddie", "Stefan Boddie", "2000-03-10",
+                        "<Toolbox>/Xtns/gsdl_green_bar", "*", &PROC_EXTENSION,
+                        [[PARAM_INT32, "run_mode", "Interactive, [non-interactive]"]], []);
+}
+
+sub net {
+  gsdl_green_bar;
+}
+
+exit main;
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/gimp/green_bar_g12.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/gimp/green_bar_g12.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/gimp/green_bar_g12.pl	(revision 13928)
@@ -0,0 +1,309 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# green_bar.pl 
+#
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+# green_bar.pl 
+#
+# This script generates the black on green gradient background images
+# used by Greenstone.  these are the icons described in macro files as:
+# green version of nav_bar_button green_bar_left_aligned
+#
+# This version has been rewritten for the GIMP Version 1.2.  You
+# should be able to run it if you install gimp 1.2 with perl support.
+# In Debian this means running "apt-get install gimp1.2 gimp1.2perl"
+
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use Gimp ":auto";
+use Gimp::Fu; 
+
+use util;
+use unicode;
+
+# set trace level to watch functions as they are executed
+#Gimp::set_trace(TRACE_ALL);
+#Gimp::set_trace(TRACE_CALL);
+
+my $gsdl_green = "#96c19b";
+my $black      = "#000000";
+my $white      = "#FFFFFF";
+
+my ($current_dir) = `pwd`;
+chomp($current_dir);
+
+my ($cfg_file, $width, $height, $text, $filename, $width_space, 
+    $alignment, $fgcolor, $bgcolor, $fontcolor, $fontsize, $foundry, $fontname, 
+    $fontweight, $fontslant, $fontwidth, $fontspacing, $image_dir);
+
+sub reset_options {
+    $image_dir = "./";
+    $width = 87;
+    $height = 17;
+    $text = "";
+    $filename = "";
+    $width_space = 1;
+    $alignment = "eft";
+    $fgcolor = $white;
+    $bgcolor = $gsdl_green;
+    $fontcolor = $black;
+    $fontsize = 17;
+    $foundry = "*";
+    $fontname = "lucida";
+    $fontweight = "medium";
+    $fontslant = "r";
+    $fontwidth = "*";
+    $fontspacing = "*";
+}
+
+sub gsdl_green_bar {
+
+    ($text, $filename, $image_dir, $width, $height, $fgcolor, $bgcolor,
+    $fontcolor, $fontsize, $alignment, , $width_space, $foundry,
+    $fontname, $fontweight, $fontslant, $fontwidth, $fontspacing,
+    $cfg_file) = @_;
+
+    # Read a configuration file
+    if ($cfg_file =~ /\w/) {
+	
+	open (CONF, $cfg_file) || die "couldn't open cfg_file $cfg_file\n";
+	while (1) {
+
+	    &reset_options ();
+	
+	    # read image configuration entry
+	    my $status = &read_config_entry (CONF);
+	    if ($filename !~ /\w/) {
+		if ($status) {last;}
+		else {next;}
+	    }
+
+	    &produce_image ();
+	    if ($status) {last;}
+	}
+
+	close CONF;
+
+    }
+
+    # Produce an image based onlyon command-line parameters
+    else {
+
+	&produce_image ();
+
+    }
+}
+
+
+sub produce_image {
+
+    # Create background image
+    my ($image, $backlayer) = &create_image ();
+
+    # set the text if there is any
+    if (length($text)) {
+
+	my $textlayer = gimp_text ($image, $backlayer, 0, 0, $text, 0, 1, 
+				   $fontsize, PIXELS, $foundry, $fontname, $fontweight, 
+				   $fontslant, $fontwidth, $fontspacing, "*", "*");
+	
+
+	my $textwidth = gimp_drawable_width($textlayer);
+	my $textheight = gimp_drawable_height($textlayer);
+
+	# check that text fits within image
+	if ($textheight > $height) {
+	    die "'$text' at fontsize of $fontsize pixels does not fit within image\n" . 
+		"$height pixels high. Decrease fontsize or increase image height\n";
+	}
+
+	my $spacers = $width_space * 2;
+
+	if ($textwidth > $width) {
+
+	    print STDERR "WARNING (green_bar.pl): '$text' does not fit within $width pixel fixed width ";
+	    print STDERR "image. Image width was increased to ",$textwidth + $spacers, " pixels\n";
+	
+	    $width = $textwidth + $spacers;
+
+	    # recreate image in new size
+	    ($image, $backlayer) = &create_image ();
+	    $textlayer = gimp_text ($image, $backlayer, 0, 0, $text, 0, 1,
+				    $fontsize, PIXELS, $foundry, $fontname, $fontweight,
+				    $fontslant, $fontwidth, $fontspacing, "*", "*");
+	
+	}
+
+	my $y_offset = ($height-$textheight)-int($fontsize/5);
+
+	my $descenders = "";
+
+	# russian descenders (KOI8-R)
+	# $descenders .= chr(0xD2);
+	# $descenders .= chr(0xD5);
+
+	if ($text =~ /[gjpqyJ$descenders]/) { ## capital J is a descender in lucida font
+	    # descenders - put text at bottom of image, otherwise 
+	    # go for fontsize/5 pixels above bottom. This is kind of hacky 
+	    # and may need some playing with for different fonts/fontsizes
+	    $y_offset = $height-$textheight;
+	}
+
+	if ($alignment =~ /^l/i) {
+	    # align text to the left
+	    my $x_offset = $width_space;
+	    gimp_layer_set_offsets ($textlayer, $x_offset, $y_offset);
+	} elsif ($alignment =~ /^r/i) {
+	    # right alignment
+	    gimp_layer_set_offsets ($textlayer, ($width-($textwidth+$width_space)), $y_offset);
+	} else {
+	    # center alignment (the default)
+	    gimp_layer_set_offsets ($textlayer, ($width-$textwidth)/2, $y_offset);
+	}
+    }
+
+    # flatten the image
+    my $finishedlayer = gimp_image_flatten ($image);
+
+    # make indexed colour 
+    if ($filename =~ /\.gif$/i) {
+        # make indexed colour (may need to do this for 
+        # other formats as well as gif)
+        gimp_convert_indexed ($image, 0, MAKE_PALETTE, 256, 0, 0, "");
+    }
+
+    # save image
+    $filename = &util::filename_cat ($image_dir, $filename);
+    gimp_file_save (RUN_NONINTERACTIVE, $image, $finishedlayer, $filename, $filename);
+}
+
+
+sub create_image {
+    # create the image
+    my $image = gimp_image_new ($width, $height, RGB_IMAGE);
+
+    # background layer
+    my $backlayer = gimp_layer_new ($image, $width, $height, RGB_IMAGE, 
+				    "BGLayer", 100, NORMAL_MODE);
+
+    # add the background layer
+    gimp_image_add_layer ($image, $backlayer, 0);
+
+    # set colour of background
+    gimp_palette_set_foreground ($bgcolor);
+    gimp_palette_set_background ($fgcolor);
+
+    # clear the background
+    gimp_selection_all ($image);
+    gimp_edit_clear ($backlayer);
+    gimp_selection_none ($image);
+
+    # create the gradient background
+    gimp_blend ($backlayer, 0, NORMAL_MODE, LINEAR, 70, 0, REPEAT_NONE, 0, 0, 0, 5, $height-3, 5, 0);
+
+    # set colour of text
+    gimp_palette_set_foreground ($fontcolor);
+
+    return ($image, $backlayer);
+}
+
+# returns 1 if this is the last entry,
+sub read_config_entry {
+    my ($handle) = @_;
+
+    my $line = "";
+    while (defined ($line = <$handle>)) {
+	next unless $line =~ /\w/;
+	my @line = ();
+	if ($line =~ /^\-+/) {return 0;}
+	$line =~ s/^\#.*$//;   # remove comments
+	$line =~ s/\cM|\cJ//g; # remove end-of-line characters
+	$line =~ s/^\s+//;     # remove initial white space
+	while ($line =~ s/\s*(\"[^\"]*\"|\'[^\']*\'|\S+)\s*//) {
+	    if (defined $1) {
+		# remove any enclosing quotes
+		my $entry = $1;
+		$entry =~ s/^([\"\'])(.*)\1$/$2/;
+
+		# substitute any environment variables
+		$entry =~ s/\$(\w+)/$ENV{$1}/g;
+		$entry =~ s/\$\{(\w+)\}/$ENV{$1}/g;
+		
+		push (@line, $entry);
+	    } else {
+		push (@line, "");
+	    }
+	}
+	if (scalar (@line) == 2 && defined ${$line[0]}) {
+	    ${$line[0]} = $line[1];
+	}
+    }
+    return 1;
+}
+
+
+register("gsdl_green_bar", 
+	 "Create green bar icons for gsdl (gimp version 1.2)",
+	 "",
+	 "Stefan Boddie (1.0) and Gordon Paynter (1.2)",
+	 "Copyright 2000 Stefan Boddie and The New Zealand Digital Library Project",
+	 "2000-07-05",
+	 "<Toolbox>/Xtns/gsdl_green_bar", 
+	 "*",
+	 [
+           [PF_STRING, "text",        "Text appearing on bar", "greenstone"],
+
+           [PF_STRING, "filename",    "Output file", "green_bar.png"],
+           [PF_STRING, "image_dir",   "Directory to create images in", $current_dir],
+
+           [PF_INT,    "width",      "Width of the bar",  640],
+           [PF_INT,    "height",     "Height of the bar", 17],
+           [PF_STRING, "fgcolor",   "Foreground colour (top) of bar", $white],
+           [PF_STRING, "bgcolor",   "Background colour (bottom) of bar", $gsdl_green],
+           [PF_STRING, "fontcolor", "Colour of text on bar", $black],
+           [PF_INT,    "fontsize",  "Font size",    17],
+
+           [PF_STRING, "alignment",     "Alignment of text on the bar (left, center or right)", "left"],
+           [PF_INT,    "padding_space", "Space around the text",                   5],
+
+           [PF_STRING, "foundry",     "Font foundry", "*"],
+           [PF_STRING, "fontname",    "Font name",    "lucida"],
+           [PF_STRING, "fontweight",  "Font weight",  "medium"],
+           [PF_STRING, "fontslant",   "Font slant",   "r"],
+           [PF_STRING, "fontwidth",   "Font width",   "*"],
+           [PF_STRING, "fontspacing", "Font spacing", "*"],
+
+           [PF_STRING, "cfg_file",    "Configuration file", ""]
+
+         ], 
+         \&gsdl_green_bar);
+
+
+exit main;
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/gimp/title_icon-1.2.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/gimp/title_icon-1.2.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/gimp/title_icon-1.2.pl	(revision 13928)
@@ -0,0 +1,407 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# title_icon.pl 
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+# Modified by Rachid Ben Kaddour <qben@oce.nl> for gimp1.2
+
+# title_icon.pl generates all the green_title type icons and 
+# collection icons for Greenstone
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use Gimp qw/:auto :DEFAULT/;
+use parsargv;
+use util;
+use unicode;
+
+# set trace level to watch functions as they are executed
+#Gimp::set_trace(TRACE_ALL);
+#Gimp::set_trace(TRACE_CALL);
+
+my $gsdl_green = "#96c19b";
+my $black = "#000000";
+
+
+local ($cfg_file, $size, $imagefile, $width, $height, $imageheight, $stripecolor, $stripewidth, 
+       $stripe_alignment, $i_transparency, $text, $text_alignment, $filename, $textspace_x, 
+       $textspace_y, $bgcolor, $fontcolor, $fontsize, $minfontsize, $foundry, $fontname, 
+       $fontweight, $fontslant, $fontwidth, $fontspacing, $fontregistry, $fontencoding, $image_dir, $dont_wrap);
+
+sub print_usage {
+    print STDERR "\n  usage: $0 [options] macrofile\n\n";
+    print STDERR "  options:\n";
+    print STDERR "   -cfg_file file         configuration file containing one or more\n";
+    print STDERR "                          sets of the following options - use to create\n";
+    print STDERR "                          batches of images\n";
+    print STDERR "   -size number           the overall size ratio of the image (i.e. a size\n";
+    print STDERR "                          of 2 will create an image twice the default size)\n";
+    print STDERR "   -image_dir directory   directory to create images in [`pwd`]\n";
+    print STDERR "                          this should be full path to existing directory\n";
+    print STDERR "   -imagefile             filename of image to embed within new icon\n";
+    print STDERR "   -width number          width of icon [150]\n";
+    print STDERR "   -height number         height of icon [44]\n";
+    print STDERR "   -imageheight number    this is the height of the image if the image contains\n";
+    print STDERR "                          an image (like collection icons) [110]\n";
+    print STDERR "   -stripecolor hex_value color of vertical stripe [$gsdl_green]\n";
+    print STDERR "   -stripewidth           width of vertical stripe [40]\n";
+    print STDERR "   -stripe_alignment      alignment of vertical stripe (left or right) [left]\n";
+    print STDERR "   -i_transparency number transparency of image within icon (0 > transparent > 100) [60]\n"; 
+    print STDERR "   -text string           image text\n";
+    print STDERR "   -text_alignment        alignment of text (left or right) [left]\n";
+    print STDERR "   -filename string       filename of resulting image\n";
+    print STDERR "   -textspace_x number    space in pixels between left/right edge of image and\n";
+    print STDERR "                          left/right edge of text [3]\n";
+    print STDERR "   -textspace_y number    space in pixels between top of image and top of\n";
+    print STDERR "                          text [3]\n";
+    print STDERR "   -bgcolor hex_value     background color of icon [$gsdl_green]\n";
+    print STDERR "   -fontcolor hex_value   text color [$black]\n";
+    print STDERR "   -fontsize number       font point size [17]\n";
+    print STDERR "   -minfontsize number    minimum point size font will be reduced to fit image [10]\n";
+    print STDERR "   -foundry string        [*]\n";
+    print STDERR "   -fontname string       [lucida]\n";
+    print STDERR "   -fontweight string     [medium]\n";
+    print STDERR "   -fontslant             [r]\n";
+    print STDERR "   -fontwidth             [*]\n";
+    print STDERR "   -fontspacing           [*]\n";
+    print STDERR "   -fontregistry          [*]\n";
+    print STDERR "   -fontencoding          [*]\n";
+    print STDERR "   -dont_wrap             don't attempt to wrap text\n\n";
+}
+
+sub reset_options {
+    $image_dir = "./";
+    $imagefile = "";
+    $width = int (150 * $size);
+    $height = int (44 * $size);
+    $imageheight = int (110 * $size);
+    $stripecolor = $gsdl_green;
+    $stripewidth = int (40 * $size);
+    $stripe_alignment = "left";
+    $i_transparency = 60;
+    $text = "";
+    $text_alignment = "left";
+    $filename = "";
+    $textspace_x = int (3 * $size);
+    $textspace_y = int (3 * $size);
+    $bgcolor = $gsdl_green;
+    $fontcolor = $black;
+    $fontsize = int (17 * $size);
+    $minfontsize = int (10 * $size);
+    $foundry = "*";
+    $fontname = "lucida";
+    $fontweight = "medium";
+    $fontslant = "r";
+    $fontwidth = "*";
+    $fontspacing = "*";
+    $fontregistry = "*";
+    $fontencoding = "*";
+}
+
+sub gsdl_title_icon {
+
+    if (!parsargv::parse(\@ARGV, 
+			 'cfg_file/.*/', \$cfg_file,
+			 'size/\d+/1', \$size,
+			 'image_dir/.*/./', \$image_dir,
+			 'imagefile/.*/', \$imagefile,
+			 'width/^\d+$/150', \$width,
+			 'height/^\d+$/44', \$height,
+			 'imageheight/^\d+$/110', \$imageheight,
+			 "stripecolor/#[0-9A-Fa-f]{6}/$gsdl_green", \$stripecolor,
+			 'stripewidth/^\d+$/40', \$stripewidth,
+			 'stripe_alignment/^(left|right)$/left', \$stripe_alignment,
+			 'i_transparency/^\d+$/60', \$i_transparency,
+			 'text/.*/', \$text,
+			 'text_alignment/^(left|right)$/left', \$text_alignment,
+			 'filename/.*', \$filename,
+			 'textspace_x/^\d+$/3', \$textspace_x,
+			 'textspace_y/^\d+$/3', \$textspace_y,
+			 "bgcolor/#[0-9A-Fa-f]{6}/$gsdl_green", \$bgcolor,
+			 "fontcolor/#[0-9A-Fa-f]{6}/$black", \$fontcolor,
+			 'fontsize/^\d+$/17', \$fontsize,
+			 'minfontsize/^\d+$/10', \$minfontsize,
+			 'foundry/.*/*', \$foundry,
+			 'fontname/.*/lucida', \$fontname,
+			 'fontweight/.*/medium', \$fontweight,
+			 'fontslant/.*/r', \$fontslant,
+			 'fontwidth/.*/*', \$fontwidth,
+			 'fontspacing/.*/*', \$fontspacing,
+			 'fontregistry/.*/*', \$fontregistry,
+			 'fontencoding/.*/*', \$fontencoding,
+			 'dont_wrap', \$dont_wrap)) {
+	&print_usage();
+	die "title_icon.pl: incorrect options\n";
+    }
+
+    # will create wherever gimp was started up from if we don't do this
+    if ($image_dir eq "./") {
+	$image_dir = `pwd`;
+	chomp $image_dir;
+    }
+
+    if ($cfg_file =~ /\w/) {
+	
+	open (CONF, $cfg_file) || die "couldn't open cfg_file $cfg_file\n";
+	while (1) {
+
+	    &reset_options ();
+	
+	    # read image configuration entry
+	    my $status = &read_config_entry (CONF);
+	    if ($filename !~ /\w/) {
+		if ($status) {last;}
+		else {next;}
+	    }
+
+	    &produce_image ();
+	    if ($status) {last;}
+	}
+
+	close CONF;
+
+    } else {
+
+	&produce_image ();
+
+    }
+}
+
+sub produce_image {
+
+    &adjust_args ();
+    &wrap_text () unless $dont_wrap;
+
+    my $use_image = 0;
+    if ($imagefile =~ /\w/) {
+	if (!-r $imagefile) {
+	    print STDERR "WARNING (title_icon.pl): imagefile '$imagefile cannot be ";
+	    print STDERR "read - $filename will be created without the use of an image file\n";
+	} else {
+	    $use_image = 1;
+	    $height = $imageheight;
+	}
+    }
+
+    # create the image
+    my $image = gimp_image_new ($width, $height, RGB_IMAGE);
+	
+    # background layer
+    my $backlayer = gimp_layer_new ($image, $width, $height, RGB_IMAGE, 
+				    "BGLayer", 100, NORMAL_MODE);
+	
+    # add the background layer
+    gimp_image_add_layer ($image, $backlayer, 0);
+	
+    # set colour of stripe
+    gimp_palette_set_foreground ($stripecolor);
+	
+    # clear the background
+    gimp_selection_all ($image);
+    gimp_edit_clear ($backlayer);
+    gimp_selection_none ($image);
+	
+    # fill in stripe
+    if ($stripe_alignment eq "left") {
+	gimp_rect_select ($image, 0, 0, $stripewidth, $height, 0, 0, 0);
+    } else {
+	gimp_rect_select ($image, $width-$stripewidth, 0, $stripewidth, $height, 0, 0, 0);
+    }
+    gimp_bucket_fill ($backlayer, FG_BUCKET_FILL, NORMAL_MODE, 100, 0, 1, 0, 0);
+    gimp_selection_none ($image);
+
+    # get image file (image goes on opposite side to stripe)
+    if ($use_image) {
+	my $rimage = gimp_file_load (RUN_NONINTERACTIVE, $imagefile, $imagefile);
+	my $rdraw = gimp_image_active_drawable ($rimage);
+	gimp_scale ($rdraw, 1, 0, 0, $width-$stripewidth, $height);
+	gimp_edit_copy ($rdraw);
+	
+	my $imagelayer = gimp_layer_new ($image, $width, $height, RGB_IMAGE, 
+					 "ImageLayer", $i_transparency, NORMAL_MODE);
+	
+	gimp_image_add_layer ($image, $imagelayer, 0);
+	
+	# clear the new layer
+	gimp_selection_all ($image);
+	gimp_edit_clear ($imagelayer);
+	gimp_selection_none ($image);
+	
+	my $flayer = gimp_edit_paste ($imagelayer, 1); 
+	if ($stripe_alignment eq "left") {
+	    gimp_layer_set_offsets($flayer, $stripewidth, 0);
+	    gimp_layer_set_offsets($imagelayer, $stripewidth, 0);
+	} else {
+	    gimp_layer_set_offsets($flayer, 0, 0);
+	    gimp_layer_set_offsets($imagelayer, 0, 0);
+	}
+
+	$backlayer = gimp_image_flatten ($image);
+    }
+	
+    # set colour of text
+    gimp_palette_set_foreground ($fontcolor);
+	
+    # set the text if there is any
+    my ($textlayer, $textheight, $textwidth);
+    my $fsize = $fontsize;
+    if (length($text)) {
+	$text =~ s/\\n/\n/gi;
+
+	while (1) {
+
+	    $textlayer = gimp_text ($image, $backlayer, 0, 0, $text, 0, 1, $fsize, 
+				    PIXELS, $foundry, $fontname, $fontweight, $fontslant, 
+				    $fontwidth, $fontspacing, $fontregistry, $fontencoding);
+	    
+	    # check that text fits within image
+	    $textwidth = gimp_drawable_width($textlayer);
+	    $textheight = gimp_drawable_height($textlayer);
+	    if ((($textwidth + $textspace_x) > $width) || 
+		(($textheight + $textspace_y) > $height)) {
+		if ($fsize < $minfontsize) {
+		    die "Error (title_icon.pl): text '$text' doesn't fit on ${width}x${height} image " .
+			"(minimum font size tried: $minfontsize\n";
+		} else {
+		    gimp_selection_all ($image);
+		    gimp_edit_clear ($textlayer);
+		    gimp_selection_none ($image);
+		    $fsize --;
+		    print STDERR "WARNING (title_icon.pl): '$text' doesn't fit: reducing font size to $fsize\n";
+		}
+	    } else {
+		last;
+	    }
+	}
+	
+	# align text
+	if ($text_alignment eq "left") {
+	    gimp_layer_set_offsets ($textlayer, $textspace_x, $textspace_y);
+	} else {
+	    gimp_layer_set_offsets ($textlayer, ($width-$textwidth)-$textspace_x, $textspace_y);
+	}
+    }
+    
+    # flatten the image
+    my $finishedlayer = gimp_image_flatten ($image);
+	
+    if ($filename =~ /\.gif$/i) {
+	# make indexed colour (may need to do this for 
+	# other formats as well as gif)
+	gimp_convert_indexed ($image, NO_DITHER, MAKE_PALETTE, 256, 0, 1, "");
+    }
+	
+    # save image
+    my $filename = &util::filename_cat ($image_dir, $filename);
+    if ($filename =~ /\.jpe?g$/i) {
+	# gimp_file_save doesn't appear to work properly for jpegs
+	file_jpeg_save (RUN_NONINTERACTIVE, $image, $finishedlayer, 
+			$filename, $filename, 0.8, 0, 1);
+    } else {
+	gimp_file_save (RUN_NONINTERACTIVE, $image, $finishedlayer, 
+			$filename, $filename);
+    }
+}
+
+# returns 1 if this is the last entry,
+sub read_config_entry {
+    my ($handle) = @_;
+
+    my $line = "";
+    while (defined ($line = <$handle>)) {
+	next unless $line =~ /\w/;
+	my @line = ();
+	if ($line =~ /^\-+/) {return 0;}
+	$line =~ s/^\#.*$//;   # remove comments
+	$line =~ s/\cM|\cJ//g; # remove end-of-line characters
+	$line =~ s/^\s+//;     # remove initial white space
+	while ($line =~ s/\s*(\"[^\"]*\"|\'[^\']*\'|\S+)\s*//) {
+	    if (defined $1) {
+		# remove any enclosing quotes
+		my $entry = $1;
+		$entry =~ s/^([\"\'])(.*)\1$/$2/;
+
+		# substitute any environment variables
+		$entry =~ s/\$(\w+)/$ENV{$1}/g;
+		$entry =~ s/\$\{(\w+)\}/$ENV{$1}/g;
+		
+		push (@line, $entry);
+	    } else {
+		push (@line, "");
+	    }
+	}
+	if (scalar (@line) == 2 && defined ${$line[0]}) {
+	    ${$line[0]} = $line[1];
+	}
+    }
+    return 1;
+}
+
+# adjust arguments that are effected by the size argument
+sub adjust_args {    
+
+    if ($size != 1) {
+	my @size_args = ('width', 'height', 'imageheight', 'stripewidth',
+			 'textspace_x', 'textspace_y', 'fontsize', 'minfontsize');
+	foreach $arg (@size_args) {
+	    $$arg = int ($$arg * $size);
+	}
+    }
+}
+
+sub wrap_text {
+
+    # don't wrap text if it already contains carriage returns
+    return if $text =~ /\n/;
+
+    # the following assumes that all words are less than $wrap_length long
+    my $wrap_length = 14;
+
+    my $new_text = "";
+    while (length ($text) >= $wrap_length) {
+	my $line = substr ($text, 0, $wrap_length);
+	$text =~ s/^\Q$line\E//;
+	$line =~ s/\s([^\s]*)$/\n/;
+	$text = $1 . $text;
+	$new_text .= $line;
+    }
+    $new_text .= $text;
+    $text = $new_text;
+}
+    
+sub query {
+
+  gimp_install_procedure("gsdl_title_icon", "create title icons for gsdl",
+                        "", "Stefan Boddie", "Stefan Boddie", "2000-03-10",
+                        "<Toolbox>/Xtns/gsdl_title_icon", "*", &PROC_EXTENSION,
+                        [[PARAM_INT32, "run_mode", "Interactive, [non-interactive]"]], []);
+}
+
+Gimp::on_net { gsdl_title_icon; };
+exit main;
+
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/gimp/title_icon.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/gimp/title_icon.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/gimp/title_icon.pl	(revision 13928)
@@ -0,0 +1,399 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# title_icon.pl 
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+# title_icon.pl generates all the green_title type icons and 
+# collection icons for Greenstone
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use Gimp;
+use parsargv;
+use util;
+use unicode;
+
+# set trace level to watch functions as they are executed
+#Gimp::set_trace(TRACE_ALL);
+#Gimp::set_trace(TRACE_CALL);
+
+my $gsdl_green = "#96c19b";
+my $black = "#000000";
+
+
+local ($cfg_file, $size, $imagefile, $width, $height, $imageheight, $stripecolor, $stripewidth, 
+       $stripe_alignment, $i_transparency, $text, $text_alignment, $filename, $textspace_x, 
+       $textspace_y, $bgcolor, $fontcolor, $fontsize, $minfontsize, $foundry, $fontname, 
+       $fontweight, $fontslant, $fontwidth, $fontspacing, $image_dir, $dont_wrap);
+
+sub print_usage {
+    print STDERR "\n  usage: $0 [options] macrofile\n\n";
+    print STDERR "  options:\n";
+    print STDERR "   -cfg_file file         configuration file containing one or more\n";
+    print STDERR "                          sets of the following options - use to create\n";
+    print STDERR "                          batches of images\n";
+    print STDERR "   -size number           the overall size ratio of the image (i.e. a size\n";
+    print STDERR "                          of 2 will create an image twice the default size)\n";
+    print STDERR "   -image_dir directory   directory to create images in [`pwd`]\n";
+    print STDERR "                          this should be full path to existing directory\n";
+    print STDERR "   -imagefile             filename of image to embed within new icon\n";
+    print STDERR "   -width number          width of icon [150]\n";
+    print STDERR "   -height number         height of icon [44]\n";
+    print STDERR "   -imageheight number    this is the height of the image if the image contains\n";
+    print STDERR "                          an image (like collection icons) [110]\n";
+    print STDERR "   -stripecolor hex_value color of vertical stripe [$gsdl_green]\n";
+    print STDERR "   -stripewidth           width of vertical stripe [40]\n";
+    print STDERR "   -stripe_alignment      alignment of vertical stripe (left or right) [left]\n";
+    print STDERR "   -i_transparency number transparency of image within icon (0 > transparent > 100) [60]\n"; 
+    print STDERR "   -text string           image text\n";
+    print STDERR "   -text_alignment        alignment of text (left or right) [left]\n";
+    print STDERR "   -filename string       filename of resulting image\n";
+    print STDERR "   -textspace_x number    space in pixels between left/right edge of image and\n";
+    print STDERR "                          left/right edge of text [3]\n";
+    print STDERR "   -textspace_y number    space in pixels between top of image and top of\n";
+    print STDERR "                          text [3]\n";
+    print STDERR "   -bgcolor hex_value     background color of icon [$gsdl_green]\n";
+    print STDERR "   -fontcolor hex_value   text color [$black]\n";
+    print STDERR "   -fontsize number       font point size [17]\n";
+    print STDERR "   -minfontsize number    minimum point size font will be reduced to fit image [10]\n";
+    print STDERR "   -foundry string        [*]\n";
+    print STDERR "   -fontname string       [lucida]\n";
+    print STDERR "   -fontweight string     [medium]\n";
+    print STDERR "   -fontslant             [r]\n";
+    print STDERR "   -fontwidth             [*]\n";
+    print STDERR "   -fontspacing           [*]\n";
+    print STDERR "   -dont_wrap             don't attempt to wrap text\n\n";
+}
+
+sub reset_options {
+    $image_dir = "./";
+    $imagefile = "";
+    $width = int (150 * $size);
+    $height = int (44 * $size);
+    $imageheight = int (110 * $size);
+    $stripecolor = $gsdl_green;
+    $stripewidth = int (40 * $size);
+    $stripe_alignment = "left";
+    $i_transparency = 60;
+    $text = "";
+    $text_alignment = "left";
+    $filename = "";
+    $textspace_x = int (3 * $size);
+    $textspace_y = int (3 * $size);
+    $bgcolor = $gsdl_green;
+    $fontcolor = $black;
+    $fontsize = int (17 * $size);
+    $minfontsize = int (10 * $size);
+    $foundry = "*";
+    $fontname = "lucida";
+    $fontweight = "medium";
+    $fontslant = "r";
+    $fontwidth = "*";
+    $fontspacing = "*";
+}
+
+sub gsdl_title_icon {
+
+    if (!parsargv::parse(\@ARGV, 
+			 'cfg_file/.*/', \$cfg_file,
+			 'size/\d+/1', \$size,
+			 'image_dir/.*/./', \$image_dir,
+			 'imagefile/.*/', \$imagefile,
+			 'width/^\d+$/150', \$width,
+			 'height/^\d+$/44', \$height,
+			 'imageheight/^\d+$/110', \$imageheight,
+			 "stripecolor/#[0-9A-Fa-f]{6}/$gsdl_green", \$stripecolor,
+			 'stripewidth/^\d+$/40', \$stripewidth,
+			 'stripe_alignment/^(left|right)$/left', \$stripe_alignment,
+			 'i_transparency/^\d+$/60', \$i_transparency,
+			 'text/.*/', \$text,
+			 'text_alignment/^(left|right)$/left', \$text_alignment,
+			 'filename/.*', \$filename,
+			 'textspace_x/^\d+$/3', \$textspace_x,
+			 'textspace_y/^\d+$/3', \$textspace_y,
+			 "bgcolor/#[0-9A-Fa-f]{6}/$gsdl_green", \$bgcolor,
+			 "fontcolor/#[0-9A-Fa-f]{6}/$black", \$fontcolor,
+			 'fontsize/^\d+$/17', \$fontsize,
+			 'minfontsize/^\d+$/10', \$minfontsize,
+			 'foundry/.*/*', \$foundry,
+			 'fontname/.*/lucida', \$fontname,
+			 'fontweight/.*/medium', \$fontweight,
+			 'fontslant/.*/r', \$fontslant,
+			 'fontwidth/.*/*', \$fontwidth,
+			 'fontspacing/.*/*', \$fontspacing,
+			 'dont_wrap', \$dont_wrap)) {
+	&print_usage();
+	die "title_icon.pl: incorrect options\n";
+    }
+
+    # will create wherever gimp was started up from if we don't do this
+    if ($image_dir eq "./") {
+	$image_dir = `pwd`;
+	chomp $image_dir;
+    }
+
+    if ($cfg_file =~ /\w/) {
+	
+	open (CONF, $cfg_file) || die "couldn't open cfg_file $cfg_file\n";
+	while (1) {
+
+	    &reset_options ();
+	
+	    # read image configuration entry
+	    my $status = &read_config_entry (CONF);
+	    if ($filename !~ /\w/) {
+		if ($status) {last;}
+		else {next;}
+	    }
+
+	    &produce_image ();
+	    if ($status) {last;}
+	}
+
+	close CONF;
+
+    } else {
+
+	&produce_image ();
+
+    }
+}
+
+sub produce_image {
+
+    &adjust_args ();
+    &wrap_text () unless $dont_wrap;
+
+    my $use_image = 0;
+    if ($imagefile =~ /\w/) {
+	if (!-r $imagefile) {
+	    print STDERR "WARNING (title_icon.pl): imagefile '$imagefile cannot be ";
+	    print STDERR "read - $filename will be created without the use of an image file\n";
+	} else {
+	    $use_image = 1;
+	    $height = $imageheight;
+	}
+    }
+
+    # create the image
+    my $image = gimp_image_new ($width, $height, RGB_IMAGE);
+	
+    # background layer
+    my $backlayer = gimp_layer_new ($image, $width, $height, RGB_IMAGE, 
+				    "BGLayer", 100, NORMAL_MODE);
+	
+    # add the background layer
+    gimp_image_add_layer ($image, $backlayer, 0);
+	
+    # set colour of stripe
+    gimp_palette_set_foreground ($stripecolor);
+	
+    # clear the background
+    gimp_selection_all ($image);
+    gimp_edit_clear ($image, $backlayer);
+    gimp_selection_none ($image);
+	
+    # fill in stripe
+    if ($stripe_alignment eq "left") {
+	gimp_rect_select ($image, 0, 0, $stripewidth, $height, 0, 0, 0);
+    } else {
+	gimp_rect_select ($image, $width-$stripewidth, 0, $stripewidth, $height, 0, 0, 0);
+    }
+    gimp_bucket_fill ($image, $backlayer, FG_BUCKET_FILL, NORMAL_MODE, 100, 0, 1, 0, 0);
+    gimp_selection_none ($image);
+	
+    # get image file (image goes on opposite side to stripe)
+    if ($use_image) {
+	my $rimage = gimp_file_load (RUN_NONINTERACTIVE, $imagefile, $imagefile);
+	my $rdraw = gimp_image_active_drawable ($rimage);
+	gimp_scale ($rimage, $rdraw, 1, 0, 0, $width-$stripewidth, $height);
+	gimp_edit_copy ($rimage, $rdraw);
+	
+	my $imagelayer = gimp_layer_new ($image, $width, $height, RGB_IMAGE, 
+					 "ImageLayer", $i_transparency, NORMAL_MODE);
+	
+	gimp_image_add_layer ($image, $imagelayer, 0);
+	
+	# clear the new layer
+	gimp_selection_all ($image);
+	gimp_edit_clear ($image, $imagelayer);
+	gimp_selection_none ($image);
+	
+	my $flayer = gimp_edit_paste ($image, $imagelayer, 1); 
+	if ($stripe_alignment eq "left") {
+	    gimp_layer_set_offsets($flayer, $stripewidth, 0);
+	    gimp_layer_set_offsets($imagelayer, $stripewidth, 0);
+	} else {
+	    gimp_layer_set_offsets($flayer, 0, 0);
+	    gimp_layer_set_offsets($imagelayer, 0, 0);
+	}
+    }
+	
+    # set colour of text
+    gimp_palette_set_foreground ($fontcolor);
+	
+    # set the text if there is any
+    my ($textlayer, $textheight, $textwidth);
+    my $fsize = $fontsize;
+    if (length($text)) {
+	$text =~ s/\\n/\n/gi;
+
+	while (1) {
+	    $textlayer = gimp_text ($image, $backlayer, 0, 0, $text, 0, 1, $fsize, 
+				    PIXELS, $foundry, $fontname, $fontweight, $fontslant, 
+				    $fontwidth, $fontspacing);
+	    
+	    # check that text fits within image
+	    $textwidth = gimp_drawable_width($textlayer);
+	    $textheight = gimp_drawable_height($textlayer);
+	    if ((($textwidth + $textspace_x) > $width) || 
+		(($textheight + $textspace_y) > $height)) {
+		if ($fsize < $minfontsize) {
+		    die "Error (title_icon.pl): text '$text' doesn't fit on ${width}x${height} image " .
+			"(minimum font size tried: $minfontsize\n";
+		} else {
+		    gimp_selection_all ($image);
+		    gimp_edit_clear ($image, $textlayer);
+		    gimp_selection_none ($image);
+		    $fsize --;
+		    print STDERR "WARNING (title_icon.pl): '$text' doesn't fit: reducing font size to $fsize\n";
+		}
+	    } else {
+		last;
+	    }
+	}
+	
+	# align text
+	if ($text_alignment eq "left") {
+	    gimp_layer_set_offsets ($textlayer, $textspace_x, $textspace_y);
+	} else {
+	    gimp_layer_set_offsets ($textlayer, ($width-$textwidth)-$textspace_x, $textspace_y);
+	}
+    }
+    
+    # flatten the image
+    my $finishedlayer = gimp_image_flatten ($image);
+	
+    if ($filename =~ /\.gif$/i) {
+	# make indexed colour (may need to do this for 
+	# other formats as well as gif)
+	gimp_convert_indexed ($image, 0, 256);
+    }
+	
+    # save image
+    my $filename = &util::filename_cat ($image_dir, $filename);
+    if ($filename =~ /\.jpe?g$/i) {
+	# gimp_file_save doesn't appear to work properly for jpegs
+	file_jpeg_save (RUN_NONINTERACTIVE, $image, $finishedlayer, 
+			$filename, $filename, 0.8, 0, 1);
+    } else {
+	gimp_file_save (RUN_NONINTERACTIVE, $image, $finishedlayer, 
+			$filename, $filename);
+    }
+}
+
+# returns 1 if this is the last entry,
+sub read_config_entry {
+    my ($handle) = @_;
+
+    my $line = "";
+    while (defined ($line = <$handle>)) {
+	next unless $line =~ /\w/;
+	my @line = ();
+	if ($line =~ /^\-+/) {return 0;}
+	$line =~ s/^\#.*$//;   # remove comments
+	$line =~ s/\cM|\cJ//g; # remove end-of-line characters
+	$line =~ s/^\s+//;     # remove initial white space
+	while ($line =~ s/\s*(\"[^\"]*\"|\'[^\']*\'|\S+)\s*//) {
+	    if (defined $1) {
+		# remove any enclosing quotes
+		my $entry = $1;
+		$entry =~ s/^([\"\'])(.*)\1$/$2/;
+
+		# substitute any environment variables
+		$entry =~ s/\$(\w+)/$ENV{$1}/g;
+		$entry =~ s/\$\{(\w+)\}/$ENV{$1}/g;
+		
+		push (@line, $entry);
+	    } else {
+		push (@line, "");
+	    }
+	}
+	if (scalar (@line) == 2 && defined ${$line[0]}) {
+	    ${$line[0]} = $line[1];
+	}
+    }
+    return 1;
+}
+
+# adjust arguments that are effected by the size argument
+sub adjust_args {    
+
+    if ($size != 1) {
+	my @size_args = ('width', 'height', 'imageheight', 'stripewidth',
+			 'textspace_x', 'textspace_y', 'fontsize', 'minfontsize');
+	foreach $arg (@size_args) {
+	    $$arg = int ($$arg * $size);
+	}
+    }
+}
+
+sub wrap_text {
+
+    # don't wrap text if it already contains carriage returns
+    return if $text =~ /\n/;
+
+    # the following assumes that all words are less than $wrap_length long
+    my $wrap_length = 14;
+
+    my $new_text = "";
+    while (length ($text) >= $wrap_length) {
+	my $line = substr ($text, 0, $wrap_length);
+	$text =~ s/^$line//;
+	$line =~ s/\s([^\s]*)$/\n/;
+	$text = $1 . $text;
+	$new_text .= $line;
+    }
+    $new_text .= $text;
+    $text = $new_text;
+}
+    
+sub query {
+
+  gimp_install_procedure("gsdl_title_icon", "create title icons for gsdl",
+                        "", "Stefan Boddie", "Stefan Boddie", "2000-03-10",
+                        "<Toolbox>/Xtns/gsdl_title_icon", "*", &PROC_EXTENSION,
+                        [[PARAM_INT32, "run_mode", "Interactive, [non-interactive]"]], []);
+}
+
+sub net {
+  gsdl_title_icon;
+}
+
+exit main;
+
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/gimp/title_icon_g12.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/gimp/title_icon_g12.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/gimp/title_icon_g12.pl	(revision 13928)
@@ -0,0 +1,380 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# title_icon.pl
+#
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999-2001 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+# title_icon.pl
+#
+# This script generates collection title icons for greenstone.
+#
+# This version has been rewritten for the GIMP Version 1.2.  You
+# should be able to run it if you install gimp 1.2 with perl support.
+# In Debian this means running "apt-get install gimp1.2 gimp1.2perl"
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use Gimp ":auto";
+use Gimp::Fu; 
+
+use util;
+use unicode;
+
+# set trace level to watch functions as they are executed
+#Gimp::set_trace(TRACE_ALL);
+#Gimp::set_trace(TRACE_CALL);
+
+my $gsdl_green = "#96c19b";
+my $black = "#000000";
+my $white      = "#FFFFFF";
+
+my ($current_dir) = `pwd`;
+chomp($current_dir);
+
+
+my ($text, $filename, $image_dir, $size, $width, $height,
+    $stripecolor, $stripewidth, $stripe_alignment, $textspace_x,
+    $textspace_y, $dont_wrap, $imagefile, $imageheight, $i_transparency,
+    $bgcolor, $fontcolor, $fontsize, $minfontsize, $text_alignment,
+    $foundry, $fontname, $fontweight, $fontslant, $fontwidth,
+    $fontspacing, $cfg_file);
+
+sub reset_options {
+    $image_dir = "./";
+    $imagefile = "";
+    $width = int (150 * $size);
+    $height = int (44 * $size);
+    $imageheight = int (110 * $size);
+    $stripecolor = $gsdl_green;
+    $stripewidth = int (40 * $size);
+    $stripe_alignment = "left";
+    $i_transparency = 60;
+    $text = "";
+    $text_alignment = "left";
+    $filename = "";
+    $textspace_x = int (3 * $size);
+    $textspace_y = int (3 * $size);
+    $bgcolor = $gsdl_green;
+    $fontcolor = $black;
+    $fontsize = int (17 * $size);
+    $minfontsize = int (10 * $size);
+    $foundry = "*";
+    $fontname = "lucida";
+    $fontweight = "medium";
+    $fontslant = "r";
+    $fontwidth = "*";
+    $fontspacing = "*";
+}
+
+sub gsdl_title_icon {
+
+    ($text, $filename, $image_dir, $size, $width, $height,
+     $stripecolor, $stripewidth, $stripe_alignment, $textspace_x,
+     $textspace_y, $dont_wrap, $imagefile, $imageheight, $i_transparency,
+     $bgcolor, $fontcolor, $fontsize, $minfontsize, $text_alignment,
+     $foundry, $fontname, $fontweight, $fontslant, $fontwidth,
+     $fontspacing, $cfg_file) = @_;
+
+    # Create images using a configuration file
+    if ($cfg_file =~ /\w/) {
+	
+	open (CONF, $cfg_file) || die "couldn't open cfg_file $cfg_file\n";
+	while (1) {
+
+	    &reset_options ();
+	
+	    # read image configuration entry
+	    my $status = &read_config_entry (CONF);
+	    if ($filename !~ /\w/) {
+		if ($status) {last;}
+		else {next;}
+	    }
+	    &produce_image ();
+	    if ($status) {last;}
+	}
+	close CONF;
+    }
+
+    # Create a single image from the parameters we have
+    else {
+	&produce_image ();
+    }
+
+}
+
+sub produce_image {
+
+    &adjust_args ();
+    &wrap_text () unless $dont_wrap;
+
+    my $use_image = 0;
+    if ($imagefile =~ /\w/) {
+	if (!-r $imagefile) {
+	    print STDERR "WARNING (title_icon.pl): imagefile '$imagefile cannot be ";
+	    print STDERR "read - $filename will be created without the use of an image file\n";
+	} else {
+	    $use_image = 1;
+	    $height = $imageheight;
+	}
+    }
+
+    # create the image
+    my $image = gimp_image_new ($width, $height, RGB_IMAGE);
+	
+    # create and add the background layer
+    my $backlayer = gimp_layer_new ($image, $width, $height, RGB_IMAGE, 
+				    "BGLayer", 100, NORMAL_MODE);
+    gimp_image_add_layer ($image, $backlayer, 0);
+	
+    # clear the background
+    gimp_selection_all ($image);
+    gimp_edit_clear ($backlayer);
+    gimp_selection_none ($image);
+	
+    # fill in stripe
+    if ($stripewidth > 0) {
+        gimp_palette_set_foreground ($stripecolor);
+	if ($stripe_alignment eq "left") {
+	  gimp_rect_select ($image, 0, 0, $stripewidth, $height, 0, 0, 0);
+	} else {
+	  gimp_rect_select ($image, $width-$stripewidth, 0, $stripewidth, $height, 0, 0, 0);
+	}
+	gimp_bucket_fill ($backlayer, FG_BUCKET_FILL, NORMAL_MODE, 100, 0, 1, 0, 0);
+	gimp_selection_none ($image);
+    }
+
+    # get image file (image goes on opposite side to stripe)
+    if ($use_image) {
+	my $rimage = gimp_file_load (RUN_NONINTERACTIVE, $imagefile, $imagefile);
+	my $rdraw = gimp_image_active_drawable ($rimage);
+	gimp_scale ($rdraw, 1, 0, 0, $width-$stripewidth, $height);
+	gimp_edit_copy ($rdraw);
+	
+	# add the background image layer
+	my $imagelayer = gimp_layer_new ($image, $width, $height, RGB_IMAGE, 
+					 "ImageLayer", $i_transparency, NORMAL_MODE);
+	gimp_image_add_layer ($image, $imagelayer, 0);
+	
+	# clear the new layer
+	gimp_selection_all ($image);
+	gimp_edit_clear ($imagelayer);
+	gimp_selection_none ($image);
+	
+	my $flayer = gimp_edit_paste ($imagelayer, 1); 
+	if ($stripe_alignment eq "left") {
+	    gimp_layer_set_offsets($flayer, $stripewidth, 0);
+	    gimp_layer_set_offsets($imagelayer, $stripewidth, 0);
+	} else {
+	    gimp_layer_set_offsets($flayer, 0, 0);
+	    gimp_layer_set_offsets($imagelayer, 0, 0);
+	}
+    }
+
+    # flatten the image (otherwise the text will be "behind" the image)
+    $backlayer = gimp_image_flatten ($image);
+
+    # set colour of text
+    gimp_palette_set_foreground ($fontcolor);
+	
+    # set the text if there is any
+    my ($textlayer, $textheight, $textwidth);
+    my $fsize = $fontsize;
+    if (length($text)) {
+	$text =~ s/\\n/\n/gi;
+
+	while (1) {
+	    $textlayer = gimp_text ($image, $backlayer, 0, 0, $text, 0, 1, $fsize, 
+				    PIXELS, $foundry, $fontname, $fontweight, $fontslant, 
+				    $fontwidth, $fontspacing, "*", "*");
+	
+	    # check that text fits within image
+	    $textwidth = gimp_drawable_width($textlayer);
+	    $textheight = gimp_drawable_height($textlayer);
+	    if ((($textwidth + $textspace_x) > $width) || 
+		(($textheight + $textspace_y) > $height)) {
+		if ($fsize < $minfontsize) {
+		    die "Error (title_icon.pl): text '$text' doesn't fit on ${width}x${height} image " .
+			"(minimum font size tried: $minfontsize\n";
+		} else {
+		    gimp_selection_all ($image);
+		    gimp_edit_clear ($image, $textlayer);
+		    gimp_selection_none ($image);
+		    $fsize --;
+		    print STDERR "WARNING (title_icon.pl): '$text' doesn't fit: reducing font size to $fsize\n";
+		}
+	    } else {
+		last;
+	    }
+	}
+	
+	# align text
+	if ($text_alignment eq "left") {
+	    gimp_layer_set_offsets ($textlayer, $textspace_x, $textspace_y);
+	} else {
+	    gimp_layer_set_offsets ($textlayer, ($width-$textwidth)-$textspace_x, $textspace_y);
+	}
+    }
+
+    # flatten the image
+    my $finishedlayer = gimp_image_flatten ($image);
+	
+    if ($filename =~ /\.gif$/i) {
+	# make indexed colour (may need to do this for 
+	# other formats as well as gif)
+	gimp_convert_indexed ($image, 0, 256);
+    }
+	
+    # save image
+    my $filename = &util::filename_cat ($image_dir, $filename);
+    gimp_file_save (RUN_NONINTERACTIVE, $image, $finishedlayer, $filename, $filename);
+}
+
+# returns 1 if this is the last entry,
+sub read_config_entry {
+    my ($handle) = @_;
+
+    my $line = "";
+    while (defined ($line = <$handle>)) {
+	next unless $line =~ /\w/;
+	my @line = ();
+	if ($line =~ /^\-+/) {return 0;}
+	$line =~ s/^\#.*$//;   # remove comments
+	$line =~ s/\cM|\cJ//g; # remove end-of-line characters
+	$line =~ s/^\s+//;     # remove initial white space
+	while ($line =~ s/\s*(\"[^\"]*\"|\'[^\']*\'|\S+)\s*//) {
+	    if (defined $1) {
+		# remove any enclosing quotes
+		my $entry = $1;
+		$entry =~ s/^([\"\'])(.*)\1$/$2/;
+
+		# substitute any environment variables
+		$entry =~ s/\$(\w+)/$ENV{$1}/g;
+		$entry =~ s/\$\{(\w+)\}/$ENV{$1}/g;
+		
+		push (@line, $entry);
+	    } else {
+		push (@line, "");
+	    }
+	}
+	if (scalar (@line) == 2 && defined ${$line[0]}) {
+	    ${$line[0]} = $line[1];
+	}
+    }
+    return 1;
+}
+
+# adjust arguments that are effected by the size argument
+sub adjust_args {
+
+    if ($size != 1) {
+        $width *= $size;
+        $height *= $size;
+	$imageheight *= $size;
+	$stripewidth *= $size;
+	$textspace_x *= $size;
+	$textspace_y *= $size;
+	$fontsize *= $size;
+	$minfontsize *= $size;
+    }
+}
+
+sub wrap_text {
+
+    # don't wrap text if it already contains carriage returns
+    return if $text =~ /\n/;
+
+    # the following assumes that all words are less than $wrap_length long
+    my $wrap_length = 14;
+
+    my $new_text = "";
+    while (length ($text) >= $wrap_length) {
+	my $line = substr ($text, 0, $wrap_length);
+	$text =~ s/^$line//;
+	$line =~ s/\s([^\s]*)$/\n/;
+	$text = $1 . $text;
+	$new_text .= $line;
+    }
+    $new_text .= $text;
+    $text = $new_text;
+}
+
+
+register("gsdl_title_icon", 
+	 "Create title icons for gsdl (gimp version 1.2)",
+	 "", 
+	 "Stefan Boddie (1.0) and Gordon Paynter (1.2)",
+	 "Copyright 1999-2001 The New Zealand Digital Library Project",
+	 "2000-03-10",
+	 "<Toolbox>/Xtns/gsdl_title_icon", 
+	 "*",
+	 [
+           [PF_STRING, "text",      "Text appearing on icon", "greenstone collection"],
+
+           [PF_STRING, "filename",  "Output file", "title_icon.png"],
+           [PF_STRING, "image_dir", "Directory to create images in", $current_dir],
+
+           [PF_INT,    "size_ratio", "Size factor: a factor of 2 doulbles image size",  1],
+           [PF_INT,    "width",      "Width of the icon",  150],
+           [PF_INT,    "height",     "Height of the icon", 44],
+
+           [PF_STRING, "stripecolor", "Colour of the stripe", $gsdl_green],
+           [PF_INT,    "stripewidth", "Width of the stripe",  40],
+           [PF_STRING, "stripealign", "Alignment of stripe (left or right)", "left"],
+
+           [PF_INT,    "text_x_offset",    "Distance from left of image to text", 3],
+           [PF_INT,    "text_y_offset",    "Distance from top of image to text",  3],
+           [PF_STRING, "dont_wrap",        "don't attempt to wrap text", ""],
+
+           [PF_STRING, "imagefile",   "Filename of background image", ""],
+           [PF_INT,    "imageheight", "Height of background image", 110],
+           [PF_INT,    "imagetransp", "Transparency of background image (1-100)", 60],
+
+#           [PF_STRING, "fgcolor",     "Foreground colour (top) of bar", $white],
+           [PF_STRING, "bgcolor",     "Background colour (bottom) of bar", $gsdl_green],
+           [PF_STRING, "fontcolor",   "Colour of text on bar", $black],
+           [PF_INT,    "fontsize",    "Font size",    17],
+           [PF_INT,    "minfontsize", "Minimum font size if scaling required",    10],
+
+           [PF_STRING, "alignment",     "Alignment of text on the icon (left or right)", "left"],
+
+           [PF_STRING, "foundry",     "Font foundry", "*"],
+           [PF_STRING, "fontname",    "Font name",    "lucida"],
+           [PF_STRING, "fontweight",  "Font weight",  "medium"],
+           [PF_STRING, "fontslant",   "Font slant",   "r"],
+           [PF_STRING, "fontwidth",   "Font width",   "*"],
+           [PF_STRING, "fontspacing", "Font spacing", "*"],
+
+           [PF_STRING, "cfg_file",    "Configuration file", ""]
+
+         ], 
+         \&gsdl_title_icon);
+
+
+exit main;
+
+
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/grab_collection.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/grab_collection.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/grab_collection.pl	(revision 13928)
@@ -0,0 +1,570 @@
+#!/usr/bin/perl -w
+
+
+# Both this script and its associated process_html.pl were written by
+# Marcel ?, while a student at Waikato University. Unfortunately he
+# was very new to perl at the time so the code is neither as clean nor
+# as fast as it could be (I've cleaned up a few of the more serious
+# bottlenecks -- it could do with alot more work though).  The code
+# does work though, if a little slowly. It's not ready for primetime
+# however and is included in the Greenstone source tree mostly so that
+# I don't lose it. -- Stefan - 24 Jul 2001
+
+
+# This script will download an entire collection (and its associated pictures and files) 
+# and store them in a temporary directory ($outputdir). 
+# A second script (process_html.pl) can be then be used to 'rebuild' the collection and link all the
+# downloaded pages and pictures together into a usable static collection.
+
+# This script will generate a number of text files required by the second script
+# and for possible recovery, namely:
+# - links.txt        - contains all the http links that were downloaded
+# - images.txt       - contains a list of all the images that were downloaded  
+# - image_dirs.txt   - contains a list of all the image-prefixes that need to be wiped from the html files
+#                      (otherwise you won't get to see any pictures)
+
+# Both this script and the html processing script have a recovery feature built in, they can continue from wherever
+# they left off, but this only works if $outputdir and $finaldir are set to different values.
+   
+# This is where all the downloaded html files end up, eg. 'temp_html/'
+my $outputdir  = 'temp_html/';
+# This is where all the processed html files (and the pictures) will end up eg. 'my_static_collection/'
+my $finaldir   = 'envl_collection/';
+
+# This is where we start our mirroring
+$address = 'http://nowhere.com/cgi-bin/library?a=p&p=about&c=demo&u=1';
+
+
+# whatever is specified in $option will be attached to the end of each html link before it is downloaded.
+# eg. "&u=1" to disable various features in the greenstone collections that are not needed with a static
+#            collection.
+# another example : "&l=nl" to set the entire collection to dutch (NetherLands :)  
+my $option = "&u=1";
+
+# Most OS have a limit on the maximum amount of files per directory (or folder).
+# A static collection can easily contain >3000 html files. Putting all those files
+# into one single directory is just asking for trouble. It's also very unwieldy ;^)
+# Hence...this value will set how much html files will be stored in one directory. 
+# These directories themselves will be numbered, 
+# so if $dir_entries = 500 then the directories will be "0/", "500/", "1000/", "1500/", "2000/", etc. 
+my $dir_entries = 250;
+
+# Occasionally a page occurs which contains no data (because &cl is not set) This option fixes that. 
+my $fix_empty_pages = "&cl=CL1";
+
+# These are the files that wget will download.
+# more can be added if necessary.
+my @graphic_formats = ('.gif','.jpg','.bmp','.png','.pdf','.mov','.mpeg','.jpeg','.rm');
+
+# ---------------------------------------[ System specific options ]----------------------------------------------------
+
+# The lynx variable specifies the command line for the lynx web browser
+# -- This is what I use under dos/win32
+# my $lynx = 'e:\lynx_w32\lynx -cfg=e:\lynx_w32\lynx.cfg';
+
+# -- This is what I use under linux
+my $lynx = 'lynx';
+
+# and the same for the wget utility
+my $wget = 'wget';
+
+# NB: There is one other linux specific command all the way at the end of this script, where I've used 'cp' to copy a file.       
+
+# Another NB: When saving the dl-ed html files to disk, I've set lynx to dump the html-source to the standard output,
+#             which I then simply redirect to a target file, BUT
+#             this does not work under DOS/win32. Redirecting standard output in a script causes it to be displayed on
+#             the screen instead. The easiest way to get around this I found was by doing the actual redirection in a simple
+#             batch file (say grab.bat), which contains the following line:
+#             @e:\lynx_w32\lynx -cfg=e:\lynx_w32\lynx.cfg -dump -source "%1" > %2 
+#
+#             Then replace line nr 326 -> 'system ("$kommand > $target");' with 'system("grab.bat $address $target");'
+#             Not a very elegant solution, but it works :) 
+
+#------------------------------------------------------------------------------------------------------------------------
+
+my %image_list;
+my $image_pointer = 0;
+
+my %linkz_list;
+my %short_linkz_list;
+my $linkz_pointer = 0;
+
+my %image_dirs_list;
+my $image_dirs_pointer = 0;
+
+my $numberdir = 0;
+
+my $start_time = (times)[0];
+
+# check if directories exist and create them if necessary..
+if ((-e $outputdir)&&(-d $outputdir)) 
+{ 
+    print " ** ",$outputdir," directory already exists..\n"; 
+}
+else
+{
+    print " ** Creating ",$outputdir," directory..\n";
+    mkdir($outputdir, 0777) or die " Cannot create output directory: $!\n";
+}
+
+if ((-e $finaldir)&&(-d $finaldir))
+{ 
+    print " ** ",$finaldir," directory already exists..\n";
+}
+else
+{
+    print " ** Creating ",$finaldir," directory..\n";
+    mkdir($finaldir, 0777) or die " Cannot create final directory: $!\n";
+}
+
+#-----------------------------------------------------------------------------------------------
+# No need to start from scratch everytime, we can recover/continue from wherever we left off
+# simply by checking which html files have been created
+#-----------------------------------------------------------------------------------------------
+
+$linknumber    = 0;                    # used to name/number the dl-ed html files
+
+my $failed     = 0;
+while ($failed == 0)
+{
+    if ($linknumber % $dir_entries == 0) 
+	{
+	    if (!((-e $outputdir.$linknumber)&&(-d $outputdir.$linknumber)))
+	    {
+		$failed++;
+		mkdir($outputdir.$linknumber, 0777) or print " ** Cannot create ",$outputdir.$linknumber, "!: $!\n";
+	    }
+	    $numberdir = $linknumber;
+	}
+
+    $check_file = $outputdir.$numberdir."/".$linknumber.".html";
+    if ((-e $check_file)&&($failed == 0)) 
+    { 
+	$linknumber++;
+    } 
+    else
+    {
+	$failed++;
+	# I'm subtracting 1 from the starting link, 
+	# just in case it only loaded half the page ;^)
+	if($linknumber>0) 
+	{ 
+	    $linknumber--; 
+	}
+	print " Will start downloading at number $linknumber \n";
+    }
+}
+
+# if we're starting from scratch, then we might as well nuke the links file
+#if ($linknumber == 0) 
+#{ 
+#    print " Starting from scratch - clobbering the old text files...\n";
+#    if (-e 'links.txt')
+#    {
+#	print "   Removing links.txt...\n";   
+#	unlink <links.txt> or print " ** Cannot delete links textfile: $!\n";
+#    }
+#    if (-e 'images.txt')
+#    {
+#	print "   Removing images.txt...\n";
+#	unlink <images.txt> or print " ** Cannot delete images textfile: $!\n";
+#    }
+#    if (-e 'image_dirs.txt')
+#    {
+#	print "   Removing image_dirs.txt...\n";
+#	unlink <image_dirs.txt> or print " ** Cannot delete image_dirs textfile: $!\n";
+#    }
+#}
+
+# if we're NOT starting from scratch, then read in old links from links text file
+# and grab the old image-links as well...
+if ($linknumber != 0)
+{
+    # load the old links from links.txt, if it doesn't exist, then give up :(
+    my $this = "";
+    my $that = "";
+    open (CHECK, "links.txt") or die " ** Cannot find/open links.txt file!: $! **\n";
+    while(eof CHECK == 0)
+    {
+	while($this ne "\n")
+	{
+	    read CHECK, $this ,1;
+	    $that = $that.$this;   
+	}
+	$linkz_list[$linkz_pointer] = $that;
+	
+	for my $search(0 .. (length($that) - 3))
+	{
+	    if((substr($that, $search, 3) eq '?a=')||(substr($that, $search, 3) eq '&a='))
+	    {
+		$short_linkz_list[$linkz_pointer] = substr($that, $search);
+		last;
+	    }
+	}
+	$linkz_pointer++;
+	$that = ""; $this = "";
+    }
+    close(CHECK);
+    print "- I found ",($#linkz_list + 1)," links in links.txt -\n";
+    
+    #make sure that we start dl-ing the correct first page 
+    $address = $linkz_list[$linknumber];
+
+    # load the old image links from image.txt (if it doesn't exist, no big deal ;)
+    my $im_this = "";
+    my $im_that = "";
+    open (IMAGES, "images.txt") || print " ** Cannot find/open images.txt file! : $! **\n";
+    while(eof IMAGES == 0)
+    {
+	while($im_this ne "\n")
+	{
+	    read IMAGES, $im_this ,1;
+	    $im_that = $im_that.$im_this;   
+	}
+	$image_list[$image_pointer] = $im_that;
+	$image_pointer++;
+	$im_that = ""; $im_this = "";
+    }
+    close(IMAGES);
+    print "- I found ",($#image_list + 1)," picture-links in images.txt -\n";
+
+    #..and last but not least, load any image_dirs from image_dirs.txt
+    # again, if its not there, no big deal :)
+    my $imd_this = "";
+    my $imd_that = "";
+    open (IMAGE_DIR, "image_dirs.txt") || print " ** Cannot find/open image_dirs.txt file!: $! **\n";
+    while(eof IMAGE_DIR == 0)
+    {
+	while($imd_this ne "\n")
+	{
+	    read IMAGE_DIR, $imd_this ,1;
+	    $imd_that = $imd_that.$imd_this;   
+	}
+	$image_dirs_list[$image_dirs_pointer] = $imd_that;
+	$image_dirs_pointer++;
+	$imd_that = ""; $imd_this = "";
+    }
+    close(IMAGE_DIR);
+    print "- I found ",($#image_dirs_list + 1)," picture directories in image_dirs.txt -\n";
+}
+
+#  Just keep going till we can find no more new links
+while(($#linkz_list < 0)||($#linkz_list+1 > $linknumber)) 
+{
+
+    # This line specifies the command line for the lynx web browser
+    my $kommand = $lynx.' -dump -image_links "'.$address.'"';
+
+    # dump page into text-array and find starting-point of the references/links
+    chomp(@data=`$kommand`);
+    for my $i(0 .. $#data)
+    {
+	if ($data[$i] eq "References") {
+	    $here = $i;}
+    }
+    $here = $here+2;
+
+    # process references/links
+    for $i($here .. $#data){
+
+	$its_an_image = 0;	     	
+    
+	#chop-off refs leading number&spaces (eg. '1. http://www.cs.waikato.ac.nz')
+	#                                          ^^^
+	
+#	$temp = substr($data[$i],3);
+#	@temp = split(/ /, $temp, 2);
+    
+	#check if the last 4 characters of the link equal .gif .jpg .png .bmp .pdf .mov .mpeg etc etc
+    
+#	for my $g(0 .. $#graphic_formats)
+#	{
+#	    if(substr($temp[1],(length($graphic_formats[$g]) * -1)) eq $graphic_formats[$g])
+#	    {
+#		$its_an_image = 1;
+#	    }
+#	}
+
+	$data[$i] =~ s/^\s*\d+\.\s+//;
+	if ($data[$i] =~ /\.(gif|jpe?g|png|bmp|pdf|mov|mpe?g|rm)$/i) {
+	    $its_an_image = 1;
+	}
+
+	# ignore mailto urls
+	if ($data[$i] !~ /mailto:/i) {
+	
+	    #----------- the link is NOT an image ----------------		
+	    if ($its_an_image == 0)
+	    { 
+		&its_a_link($data[$i], $outputdir);
+	    }
+
+	    #----------- the link IS an image ----------------
+	    if ($its_an_image != 0)
+	    { 
+		&its_an_image($data[$i], $finaldir); 
+	    }
+	}
+    }	
+
+    # save the web page to disk (in the appropriate numbered directory)
+    $kommand = $lynx.' -dump -source "'.$address.'"';
+
+    if ($linknumber % $dir_entries == 0) 
+    {
+	if ((-e $outputdir.$linknumber)&&(-d $outputdir.$linknumber))
+	{
+	    print " ** ",$outputdir.$linknumber, " - Directory allready exists.\n";
+	}
+	else
+	{
+	    mkdir($outputdir.$linknumber, 0777) or print " ** Cannot create ",$outputdir.$linknumber, "!: $!\n";
+	    mkdir($finaldir.$linknumber, 0777)  or print " ** Cannot create ",$outputdir.$linknumber, "!: $!\n";
+	}
+	$numberdir = $linknumber;
+    }
+    my $target = $outputdir.$numberdir."/".$linknumber.".html";
+
+    #---------------------------------------------------------------------------------------------------------------
+    # NOTE: This next command will NOT work under win32/dos, as redirecting standard output in a script causes it to
+    #       be dumped straight to the screen as opposed to into the target file.
+    #---------------------------------------------------------------------------------------------------------------
+    system ("$kommand > $target");
+    #---------------------------------------------------------------------------------------------------------------
+
+    print " Saved $target\n";
+
+    $linknumber++;
+
+    $address = $linkz_list[$linknumber];
+}
+
+my $end_time = (times)[0];
+
+print "\n\n\n *----------------------------*\n";
+print " |  Whew! Task completed! :-D |\n";
+print " *----------------------------*\n";
+printf"  Script took %.2f CPU seconds to complete ;^)\n", $end_time - $start_time;
+print "\n\n"; 
+print "  Now execute the  process_html.pl  script to link the downloaded collection together.\n";
+print "  Please do make sure that it is executed with the same options as this script ;-)\n";
+
+sub its_a_link 
+{
+    local($found) = @_;
+#    local($ok = 0, $kommand);
+    local($kommand);
+    local $short_link = "";
+
+    return if ($found =~ /\#.*$/);
+
+    # attach the custom options
+    $found .= $option;
+    
+    #little bit of trickery here - check if there is a &d= option present in the link
+    #if there is, then wipe the &cl= option!
+    #This should cut down multiple copies by 75%!!
+    
+    #but, if there is no &d option, and the &cl option is not set, then we have to set the &cl option to something
+    #otherwise we get pages which contain no data :\
+
+    if ($found =~ /[&\?]a=d/) {
+	if ($found =~ /[&\?]d=/) {
+	    $found =~ s/[&\?]cl=[^&]*//;
+	} elsif ($found !~ /[&\?]cl=/) {
+	    $found .= $fix_empty_pages;
+	}
+    }
+
+    # we also want to sort out any xxx.pr OIDs that we come across
+    $found =~ s/([&\?](cl|d)=.*?)\.\d+\.pr/$1/g;
+
+    # attach the EOL character.
+    $found = $found."\n";
+
+
+    # the hard way !!!
+#    for my $search(0 .. (length($found) - 3))
+#    {
+#	if((substr($found, $search, 3) eq '?d=')||(substr($found, $search, 3) eq '&d='))
+#	{
+#	    for my $second_search(0 .. (length($found) - 4))  
+#	    {
+#		if((substr($found, $second_search, 4) eq '?cl=')||(substr($found, $second_search, 4) eq '&cl='))
+#		{
+#		    for my $third_search(($second_search + 3) .. (length($found) - 1))
+#		    {
+#			if((substr($found, $third_search, 1)) eq '&')
+#			{
+#			    substr($found, $second_search, $third_search - $second_search) = ""; 
+#			    last;
+#			}
+#		    }
+#		    last;
+#		}
+#	    } 
+#	    last;
+#	}
+#	else
+#	{
+#	    if( $search == (length($found) - 3))
+#	    {
+#		for my $second_search(0 .. (length($found) - 4))  
+#		{
+#		    if((substr($found, $second_search, 4) eq '?cl=')||(substr($found, $second_search, 4) eq '&cl='))
+#		    {
+#			for my $third_search(($second_search + 3) .. (length($found) - 1))
+#			{
+#			    if((substr($found, $third_search, 1)) eq '&')
+#			    {
+#				if (substr($found, $second_search, $third_search - $second_search) eq '&cl=')
+#				{
+#				    substr($found, $second_search, $third_search - $second_search) = $fix_empty_pages;	
+#				}
+#				last;
+#			    }
+#			}
+#			last;
+#		    }
+#		} 
+#	    }
+#	}
+#    }
+    
+    # grab the last part of the link (ignoring the start and the &e option)
+#    for my $search(0 .. (length($found) - 3))
+#    {
+#	if((substr($found, $search, 3) eq '?a=')||(substr($found, $search, 3) eq '&a='))
+#	{
+#	    $short_link = substr($found, $search);
+#	    last;
+#	}
+#    }
+
+    ($short_link) = $found =~ /\?(.*)$/;
+    $short_link =~ s/(^|&)e=[^&]*/$1/;
+
+    
+    # this filters out multiple copies of for example the help page, which has #something at the end of its links
+    # now do this first with regular expression above -- Stefan
+
+#    for my $search(0 .. length($found))
+#    {
+#	if ((substr($found, $search, 1)) eq '#')
+#	{
+#	    $ok++;
+#	    last;
+#	}
+#    }
+ 
+
+   
+    # compare the found link to the links we've stored in the arrays (compares both full link and partial link)
+    for my $search(0 .. $#linkz_list)
+    {
+	return if ($found eq $linkz_list[$search]);
+	return if ($short_link eq $short_linkz_list[$search]);
+    }
+		    
+    # if found link is not in links array, add it
+    open (DUMP, ">>links.txt") or die " ** Can't open links.txt!: $!\n";
+    print DUMP $found;
+    close(DUMP);
+    
+    $linkz_list[$linkz_pointer] = $found;
+    $short_linkz_list[$linkz_pointer] = $short_link;
+    $linkz_pointer++;
+}
+
+sub do_image_dirs
+{
+    local($found) = @_;
+    my $count = 0;
+    my @br_index;
+    my $image_dir = "";
+    my $new_dir = 0;
+
+    for my $search(1 .. (length($found) - 1 ))
+    {
+	$bracket = substr($found, ($search * - 1), 1);
+	if ($bracket eq '/')
+	{
+	    $count++;
+	    $br_index[$count] = $search;
+	}
+	if($count == 2) 
+	{
+	    $image_dir = substr($found, ($br_index[2] * -1) , ($br_index[2] - $br_index[1]));
+	}
+    }
+    
+    my $dirs_to_wipe = substr($found, $br_index[$#br_index - 2] * - 1, $br_index[$#br_index - 2] - $br_index[2] + 1)."\n";
+    
+    for my $counter(0 .. $#image_dirs_list)
+    {
+	if($dirs_to_wipe eq $image_dirs_list[$counter])
+	{
+	    $new_dir++;
+	}
+    }
+    
+    if ($new_dir == 0)
+    {
+	open (IMAGE_DIRS, ">>image_dirs.txt") or die " ** Can't open image_dirs.txt!: $!\n";
+	print IMAGE_DIRS $dirs_to_wipe;
+	close(IMAGE_DIRS);
+	$image_dirs_list[$image_dirs_pointer] = $dirs_to_wipe;
+	$image_dirs_pointer++;
+    }
+
+    print "   ",substr($finaldir, 0 ,length($finaldir) - 1).$image_dir.substr($found, ($br_index[1] * - 1), length($found) - (length($found) - $br_index[1])),"\n";	    
+    
+    return $image_dir;
+}
+
+sub its_an_image 
+{
+    local($found, $outpdir) = @_;
+    local($kommand);
+    my $new = 0;
+    
+    my $temp_found = $found . "\n";
+
+    # check if the image is in the list
+    for my $counter(0 .. $#image_list)
+    {
+	if($temp_found eq $image_list[$counter])
+	{
+	    $new++;
+	}
+    }
+    
+    # only download the image if its not in the list..
+    if($new == 0)
+    {    
+	my $image_dir = &do_image_dirs;
+	my $temp_outputdir = $outpdir;
+	if (substr($temp_outputdir, -1, 1) eq "/")
+	{
+	    substr($temp_outputdir, -1, 1) = "";
+	}
+	
+	# wget is set to 'q - quiet' and 'nc - dont clobber existing files'
+	$kommand = $wget.' -qnc --directory-prefix='.$temp_outputdir.$image_dir.' "'.$found.'"';
+	system ("$kommand");
+        
+	open (IMAGES, ">>images.txt") or die " ** Can't open images.txt!: $!\n";
+	print IMAGES $temp_found;
+	close(IMAGES);
+	
+	$image_list[$image_pointer] = $temp_found;
+	$image_pointer++;
+	
+        # grab corresponding ON pictures for navigation bar if we've just dl-ed the OFF picture
+	if(substr($found , -6) eq "of.gif") 
+	{
+	    substr($found, -6, 6) = "on.gif";
+	    &its_an_image($found, $outpdir);
+	}
+    }    
+}
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/gsConvert.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/gsConvert.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/gsConvert.pl	(revision 13928)
@@ -0,0 +1,1293 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# gsConvert.pl -- convert documents to HTML or TEXT format
+#
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999-2002 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+# gsConvert.pl converts documents in a range of formats to HTML or TEXT
+# by exploiting third-party programs.  The sources of these are usually found
+# in the $GSDLHOME/packages directory, and the executables should live in
+# $GSDLHOME/bin/$GSDLOS (which is on the search path).
+#
+# Currently, we can convert the following formats by using external
+# conversion utilities:
+# Microsoft Word (versions 2,6,7 [==95?], 8[==97?], 9[==2000?]), RTF,
+# Adobe PDF, PostScript, MS PowerPoint (95 and 97), and MS Excel (95 and 97).
+#
+# We can try to convert any file to text with a perl implementation of the
+# UNIX strings command.
+#
+# We try to convert Postscript files to text using "gs" which is often on
+# *nix machines. We fall back to performing weak text extraction by using
+# regular expressions.
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use parsargv;
+use util;
+use Cwd;
+use File::Basename;
+
+# Are we running on WinNT or Win2000 (or later)?
+my $is_winnt_2000=eval {require Win32; return (Win32::IsWinNT()); return 0;};
+if (!defined($is_winnt_2000)) {$is_winnt_2000=0;}
+
+my $use_strings;
+my $pdf_complex;
+my $pdf_nohidden;
+my $pdf_zoom;
+my $pdf_ignore_images;
+my $pdf_allow_images_only;
+my $windows_scripting;
+
+sub print_usage
+{
+    print STDERR "\n";
+    print STDERR "gsConvert.pl: Converts documents in a range of formats to html\n";
+    print STDERR "              or text using third-party programs.\n\n";
+    print STDERR "  usage: $0 [options] filename\n";
+    print STDERR "  options:\n\t-type\tdoc|dot|pdf|ps|ppt|rtf|xls\t(input file type)\n";
+    print STDERR "\t-errlog\t<filename>\t(append err messages)\n";
+    print STDERR "\t-output\tauto|html|text|pagedimg-jpg|pagedimg-gif|pagedimg-png\t(output file type)\n";
+    print STDERR "\t-timeout\t<max cpu seconds>\t(ulimit on unix systems)\n";
+    print STDERR "\t-use_strings\tuse strings to extract text if conversion fails\n";
+    print STDERR "\t-windows_scripting\tuse windows script when converting Microsoft Word and PPT via VB script\n";
+    print STDERR "\t-pdf_complex\tuse complex output when converting PDF to HTML\n";
+    print STDERR "\t-pdf_nohidden\tDon't attempt to extract hidden text from PDF files\n";
+    print STDERR "\t-pdf_ignore_images\tdon't attempt to extract images when\n";
+    print STDERR "\t\tconverting PDF to HTML\n";
+    print STDERR "\t-pdf_allow_images_only\tallow images only (continue even if no text is present when converting to HTML)\n";
+    print STDERR "\t-pdf_zoom\tfactor by which to zoom PDF (only useful if\n";
+    print STDERR "\t\t-pdf_complex is set\n";
+    exit(1);
+}
+
+my $faillogfile="";
+my $timeout=0;
+
+sub main
+{
+    my (@ARGV) = @_;
+    my ($input_type,$output_type,$verbose);
+
+    # read command-line arguments
+    if (!parsargv::parse(\@ARGV,
+			 'type/(doc|dot|pdf|ps|ppt|rtf|xls)/', \$input_type,
+			 '/errlog/.*/', \$faillogfile,
+			 'output/(auto|html|text|pagedimg).*/', \$output_type,
+			 'timeout/\d+/0',\$timeout,
+			 'verbose/\d+/0', \$verbose,
+			 'use_strings', \$use_strings,
+			 'windows_scripting',\$windows_scripting,
+			 'pdf_complex', \$pdf_complex,
+			 'pdf_ignore_images', \$pdf_ignore_images,
+			 'pdf_allow_images_only', \$pdf_allow_images_only,
+			 'pdf_nohidden', \$pdf_nohidden,
+			 'pdf_zoom/\d+/2', \$pdf_zoom
+			 ))
+    {
+	print_usage();
+    }
+      
+    # Make sure the input file exists and can be opened for reading
+    if (scalar(@ARGV!=1)) {
+	print_usage();
+    }
+
+    my $input_filename = $ARGV[0];
+    if (!-r $input_filename) {
+	print STDERR "Error: unable to open $input_filename for reading\n";
+	exit(1);
+    }
+
+    # Deduce filenames
+    my ($tailname,$dirname,$suffix) 
+	= File::Basename::fileparse($input_filename, "\\.[^\\.]+\$");
+    my $output_filestem = &util::filename_cat($dirname, "$tailname");
+
+    if ($input_type eq "")
+    {
+	$input_type = lc (substr($suffix,1,length($suffix)-1));
+    }
+    
+    # Change to temporary working directory
+    my $stored_dir = cwd();
+    chdir ($dirname) || die "Unable to change to directory $dirname";
+
+    # Select convert utility
+    if (!defined $input_type) {
+	print STDERR "Error: No filename extension or input type defined\n";
+	exit(1);
+    } 
+    elsif ($input_type eq "doc" || $input_type eq "dot") {
+	print &convertDOC($input_filename, $output_filestem, $output_type);
+	print "\n";
+    } 
+    elsif ($input_type eq "rtf") {
+	print &convertRTF($input_filename, $output_filestem, $output_type);
+	print "\n";
+    } 
+    elsif ($input_type eq "pdf") {
+	print &convertPDF($dirname, $input_filename, $output_filestem, $output_type);
+	print "\n";
+    } 
+    elsif ($input_type eq "ps") {
+	print &convertPS($input_filename, $output_filestem, $output_type);
+	print "\n";
+    } 
+    elsif ($input_type eq "ppt") {
+	print &convertPPT($input_filename, $output_filestem, $output_type);
+	print "\n";
+    } 
+    elsif ($input_type eq "xls") {
+	print &convertXLS($input_filename, $output_filestem, $output_type);
+	print "\n";
+    } 
+    else {
+	print STDERR "Error: Unable to convert type '$input_type'\n";
+	exit(1);
+    }
+    
+    # restore to original working directory
+    chdir ($stored_dir) || die "Unable to return to directory $stored_dir";
+
+}
+
+&main(@ARGV);
+
+
+
+# Document-type conversion functions
+#
+# The following functions attempt to convert documents from their
+# input type to the specified output type.  If no output type was
+# given, then they first attempt HTML, and then TEXT.
+#
+# Each returns the output type ("html" or "text") or "fail" if no 
+# conversion is possible.
+
+# Convert a Microsoft word document
+
+sub convertDOC {
+    ($input_filename, $output_filestem, $output_type) = @_;
+
+    # Many .doc files are not in fact word documents!
+    my $realtype = &find_docfile_type($input_filename);
+
+    if ($realtype eq "word6" || $realtype eq "word7" || $realtype eq "word8") {
+	return &convertWord678($input_filename, $output_filestem, $output_type);
+    } elsif ($realtype eq "rtf") {
+	return &convertRTF($input_filename, $output_filestem, $output_type);
+    } else {
+	return &convertAnything($input_filename, $output_filestem, $output_type);
+    }
+}
+
+# Convert a Microsoft word 6/7/8 document
+
+sub convertWord678 {
+    ($input_filename, $output_filestem, $output_type) = @_;
+
+    my $success = 0;
+    if (!$output_type || ($output_type =~ /html/i)){
+	if ($windows_scripting) {
+	    $success = &native_doc_to_html($input_filename, $output_filestem);
+	}
+	else {
+	    $success = &doc_to_html($input_filename, $output_filestem);	   
+	}
+	if ($success) {
+	   return "html";
+	}
+    }
+
+    return &convertAnything($input_filename, $output_filestem, $output_type);
+}
+
+
+# Convert a Rich Text Format (RTF) file
+
+sub convertRTF {
+    ($input_filename, $output_filestem, $output_type) = @_;
+
+    my $success = 0;
+
+    # Attempt specialised conversion to HTML
+    if (!$output_type || ($output_type =~ /html/i)) {
+
+	if ($windows_scripting) {
+	    $success = &native_doc_to_html($input_filename, $output_filestem);
+	}
+	else {
+	    $success = &rtf_to_html($input_filename, $output_filestem);
+	}
+	if ($success) {
+	    return "html";
+	}
+    }
+
+# rtf is so ugly that's it's not worth running strings over.
+# One day I'll write some quick'n'dirty regexps to try to extract text - jrm21
+#    return &convertAnything($input_filename, $output_filestem, $output_type);
+    return "fail";
+}
+
+
+# Convert an unidentified file
+
+sub convertAnything {
+    ($input_filename, $output_filestem, $output_type) = @_;
+    
+    my $success = 0;
+  
+    # Attempt simple conversion to HTML
+    if (!$output_type || ($output_type =~ /html/i)) {
+	$success = &any_to_html($input_filename, $output_filestem);
+	if ($success) {
+	    return "html";
+	}
+    }
+
+    # Convert to text
+    if (!$output_type || ($output_type =~ /text/i)) {
+	$success = &any_to_text($input_filename, $output_filestem);
+	if ($success) {
+	    return "text";
+	}
+    }
+    return "fail";
+}
+
+
+
+# Convert an Adobe PDF document
+
+sub convertPDF {
+    my ($dirname, $input_filename, $output_filestem, $output_type) = @_;
+
+    my $success = 0;
+    $output_type =~ s/.*\-(.*)/$1/i;
+    # Attempt coversion to Image
+    if ($output_type =~ /jp?g|gif|png/i) {
+	$success = &pdf_to_img($dirname, $input_filename, $output_filestem, $output_type);
+	if ($success){
+	    return "item";
+	}
+    }
+
+    # Attempt conversion to HTML
+    if (!$output_type || ($output_type =~ /html/i)) {
+	$success = &pdf_to_html($dirname, $input_filename, $output_filestem);
+	if ($success) {
+	    return "html";
+	}
+    }
+
+    # Attempt conversion to TEXT
+    if (!$output_type || ($output_type =~ /text/i)) {
+	$success = &pdf_to_text($dirname, $input_filename, $output_filestem);
+	if ($success) {
+	    return "text";
+	}
+    }
+
+    return "fail";
+
+}
+
+
+# Convert an Adobe PostScript document
+
+sub convertPS {
+    ($input_filename, $output_filestem, $output_type) = @_;
+
+    my $success = 0;
+    $output_type =~ s/.*\-(.*)/$1/i;
+    # Attempt coversion to Image
+    if ($output_type =~ /jp?g|gif|png/i) {
+	$success = &ps_to_img($dirname, $input_filename, $output_filestem, $output_type);
+	if ($success){
+	    return "item";
+	}
+    }
+
+    # Attempt conversion to TEXT
+    if (!$output_type || ($output_type =~ /text/i)) {
+	$success = &ps_to_text($input_filename, $output_filestem);
+	if ($success) {
+	    return "text";
+	}
+    }
+    return "fail";
+}
+
+
+sub convertPPT {
+    my ($input_filename, $output_filestem, $output_type) = @_;
+    my $success = 0;
+
+    my $ppt_convert_type = "";
+    #if (!$output_type || $windows_scripting ||($output_type !~ /html/i) ||($output_type !~ /text/i)){
+    if ($windows_scripting && ($output_type !~ /html/i) && ($output_type !~ /text/i)){
+	if ($output_type =~ /gif/i) {
+	    $ppt_convert_type = "-g";
+	} elsif ($output_type =~ /jp?g/i){
+	    $ppt_convert_type = "-j";
+	} elsif ($output_type =~ /png/i){
+	    $ppt_convert_type = "-p";
+	}
+	my $vbScript = &util::filename_cat($ENV{'GSDLHOME'}, "bin",
+					   $ENV{'GSDLOS'}, "pptextract");
+	$vbScript = "pptextract" if ($ENV{'GSDLOS'} =~ /^windows$/i);
+			
+	$cmd = "";
+	if ($timeout) {$cmd = "ulimit -t $timeout;";}
+	# if the converting directory has already existed
+	if (-d $output_filestem) {
+	    print STDERR "**The conversion directory has existed\n";
+	    return "item";
+	} else {
+	    $cmd .=  "$vbScript $ppt_convert_type \"$input_filename\" \"$output_filestem\"";
+	    $cmd .= " 2>\"$output_filestem.err\""
+		if ($ENV{'GSDLOS'} !~ /^windows$/i || $is_winnt_2000);
+	    if (system($cmd) !=0) {
+		print STDERR "Powerpoint VB Scripting convert failed\n";
+	    } else {
+		return "item";
+	    }
+	}
+    } elsif (!$output_type || ($output_type =~ /html/i)) {
+	# Attempt conversion to HTML
+	#if (!$output_type || ($output_type =~ /html/i)) {
+	# formulate the command
+	$cmd = "";
+	$cmd .= "perl -S ppttohtml.pl ";
+	$cmd .= " \"$input_filename\" \"$output_filestem.html\"";
+	$cmd .= " 2>\"$output_filestem.err\""
+	    if ($ENV{'GSDLOS'} !~ /^windows$/i || $is_winnt_2000);
+
+	# execute the command
+	$!=0;
+	if (system($cmd)!=0)
+	{
+	    print STDERR "Powerpoint 95/97 converter failed $!\n";
+	} else {
+	    return "html";
+	}
+    } 
+
+    $success = &any_to_text($input_filename, $output_filestem);
+    if ($success) {
+	return "text";
+    }
+    
+    return "fail";
+}
+
+
+sub convertXLS {
+    my ($input_filename, $output_filestem, $output_type) = @_;
+
+    my $success = 0;
+
+    # Attempt conversion to HTML
+    if (!$output_type || ($output_type =~ /html/i)) {
+	# formulate the command
+	$cmd = "";
+	$cmd .= "perl -S xlstohtml.pl ";
+	$cmd .= " \"$input_filename\" \"$output_filestem.html\"";
+	$cmd .= " 2>\"$output_filestem.err\""
+	    if ($ENV{'GSDLOS'} !~ /^windows$/i || $is_winnt_2000);
+	
+	
+	# execute the command
+	$!=0;
+	if (system($cmd)!=0)
+	{
+	    print STDERR "Excel 95/97 converter failed $!\n";
+	} else {
+	    return "html";
+	}
+    }
+
+    $success = &any_to_text($input_filename, $output_filestem);
+    if ($success) {
+	return "text";
+    }
+
+    return "fail";
+}
+
+
+
+# Find the real type of a .doc file
+#
+# We seem to have a lot of files with a .doc extension that are .rtf 
+# files or Word 5 files.  This function attempts to tell the difference.
+sub find_docfile_type {
+    ($input_filename) = @_;
+    
+    open(CHK, "<$input_filename");
+    binmode(CHK);
+    my $line = "";
+    my $first = 1;
+
+    while (<CHK>) {
+    
+	$line = $_;
+
+	if ($first) {
+	    # check to see if this is an rtf file
+	    if ($line =~ /^\{\\rtf/) {
+		close(CHK);
+		return "rtf";
+	    }
+	    $first = 0;
+	}
+	
+	# is this is a word 6/7/8 document?
+	if ($line =~ /Word\.Document\.([678])/) {
+	    close(CHK);
+	    return "word$1";
+	}
+
+    }
+
+    return "unknown";
+}
+
+
+# Specific type-to-type conversions
+#
+# Each of the following functions attempts to convert a document from 
+# a specific format to another.  If they succeed they return 1 and leave 
+# the output document(s) in the appropriate place; if they fail they 
+# return 0 and delete any working files.
+
+
+# Attempt to convert a word document to html with the wv program
+sub doc_to_html {
+    ($input_filename, $output_filestem) = @_;
+
+    my $wvWare = &util::filename_cat($ENV{'GSDLHOME'}, "bin", 
+				     $ENV{'GSDLOS'}, "wvWare");
+
+    # don't include path on windows (to avoid having to play about
+    # with quoting when GSDLHOME might contain spaces) but assume
+    # that the PATH is set up correctly
+    $wvWare = "wvWare" if ($ENV{'GSDLOS'} =~ /^windows$/i);
+
+    my $wv_conf = &util::filename_cat($ENV{'GSDLHOME'}, "etc", 
+				      "packages", "wv", "wvHtml.xml");
+    
+    my $cmd = "";
+    if ($timeout) {$cmd = "ulimit -t $timeout;";}
+    $cmd .= "$wvWare --charset utf-8 --config \"$wv_conf\"";
+    $cmd .= " \"$input_filename\" > \"$output_filestem.html\"";
+    
+    # redirecting STDERR is a bad idea on windows 95/98
+    $cmd .= " 2> \"$output_filestem.err\""
+	if ($ENV{'GSDLOS'} !~ /^windows$/i || $is_winnt_2000);
+    # execute the command
+    $!=0;
+    if (system($cmd)!=0)
+    {
+	print STDERR "Error executing wv converter:$!\n";
+	if (-s "$output_filestem.err") {
+	    open (ERRFILE, "<$output_filestem.err");
+
+	    my $write_to_fail_log=0;
+	    if ($faillogfile ne "" && defined(open(FAILLOG,">>$faillogfile")))
+	    {$write_to_fail_log=1;}
+
+	    my $line;
+	    while ($line=<ERRFILE>) {
+		if ($line =~ /\w/) {
+		    print STDERR "$line";
+		    print FAILLOG "$line" if ($write_to_fail_log);
+		}
+		if ($line !~ m/startup error/) {next;}
+		print STDERR " (given an invalid .DOC file?)\n";
+		print FAILLOG " (given an invalid .DOC file?)\n"
+		if ($write_to_fail_log);
+		
+	    } # while ERRFILE
+	    close FAILLOG if ($write_to_fail_log);
+	}
+	return 0; # we can try any_to_text
+    }
+
+    # Was the conversion successful?
+
+    if (-s "$output_filestem.html") {
+	open(TMP, "$output_filestem.html");
+	$line = <TMP>;
+	close(TMP);
+	if ($line && $line =~ /DOCTYPE HTML/) {
+	    &util::rm("$output_filestem.err") if -e "$output_filestem.err";
+	    return 1;
+	}
+    }
+	
+    # If here, an error of some sort occurred
+    &util::rm("$output_filestem.html") if -e "$output_filestem.html";
+    if (-e "$output_filestem.err") {
+	if ($faillogfile ne "" && defined(open(FAILLOG,">>$faillogfile"))) {
+	    open (ERRLOG,"$output_filestem.err");
+	    while (<ERRLOG>) {print FAILLOG $_;}
+	    close FAILLOG;
+	    close ERRLOG;
+	}
+	&util::rm("$output_filestem.err");
+    }
+    
+    return 0;
+}
+
+
+# Attempt to convert a word document to html with the word2html scripting program
+sub native_doc_to_html {
+    ($input_filename, $output_filestem) = @_;
+
+    my $vbScript = &util::filename_cat($ENV{'GSDLHOME'}, "bin",
+				       $ENV{'GSDLOS'}, "word2html");
+
+    $vbScript = "word2html" if ($ENV{'GSDLOS'} =~ /^windows$/i);
+    if (-e "$output_filestem.html") {
+	print STDERR "*** The conversion file has existed\n";
+	return 1;
+    }
+
+    my $cmd = "";
+    if ($timeout) {$cmd = "ulimit -t $timeout;";}
+    #$cmd .= "$vbScript \"$input_filename\" \"$output_filestem.html\"";
+    #$cmd .=  "$vbScript $input_filename $output_filestem.html";
+    $cmd .=  "$vbScript \"$input_filename\" \"$output_filestem.html\"";
+
+    # redirecting STDERR
+    $cmd .= " 2> \"$output_filestem.err\""
+	if ($ENV {'GSDLOS'} !~ /^windows$/i || $is_winnt_2000);
+    
+    # execute the command
+    $!=0;
+    if (system($cmd)!=0)
+    {
+	print STDERR "Error executing word2Html converter:$!\n";
+	if (-s "$output_filestem.err") {
+	    open (ERRFILE, "<$output_filestem.err");
+	    
+	    my $write_to_fail_log=0;
+	    if ($faillogfile ne "" && defined(open(FAILLOG,">>$faillogfile")))
+	    {$write_to_fail_log=1;}
+
+	    my $line;
+	    while ($line=<ERRFILE>) {
+		if ($line =~ /\w/) {
+		    print STDERR "$line";
+		    print FAILLOG "$line" if ($write_to_fail_log);
+		}
+		if ($line !~ m/startup error/) {next;}
+		print STDERR " (given an invalid .DOC file?)\n";
+		print FAILLOG " (given an invalid .DOC file?)\n"
+		if ($write_to_fail_log);
+		
+	    } # while ERRFILE
+	    close FAILLOG if ($write_to_fail_log);
+	}
+	return 0; # we can try any_to_text
+    }
+
+    # Was the conversion successful?
+    if (-s "$output_filestem.html") {
+	open(TMP, "$output_filestem.html");
+	$line = <TMP>;
+	close(TMP);
+	if ($line && $line =~ /html/) {
+	    &util::rm("$output_filestem.err") if -e "$output_filestem.err";
+	    return 1;
+	}
+    }
+	
+    # If here, an error of some sort occurred
+    &util::rm("$output_filestem.html") if -e "$output_filestem.html";
+    if (-e "$output_filestem.err") {
+	if ($faillogfile ne "" && defined(open(FAILLOG,">>$faillogfile"))) {
+	    open (ERRLOG,"$output_filestem.err");
+	    while (<ERRLOG>) {print FAILLOG $_;}
+	    close FAILLOG;
+	    close ERRLOG;
+	}
+	&util::rm("$output_filestem.err");
+    }
+    return 0;
+}
+
+# Attempt to convert an RTF document to html with rtftohtml
+
+sub rtf_to_html {
+    my ($input_filename, $output_filestem) = @_;
+
+    # formulate the command
+    $cmd = "";
+    if ($timeout) {$cmd = "ulimit -t $timeout;";}
+    $cmd .= "rtftohtml";
+    #$cmd .= "rtf-converter";
+
+    $cmd .= " -o \"$output_filestem.html\" \"$input_filename\"";
+
+    $cmd .= " 2>\"$output_filestem.err\""
+        if ($ENV{'GSDLOS'} !~ /^windows$/i || $is_winnt_2000);
+
+
+    # execute the command
+    $!=0;
+    if (system($cmd)!=0)
+    {
+	print STDERR "Error executing rtf converter $!\n";
+	# don't currently bother printing out error log...
+	# keep going, in case it still created an HTML file...
+    }
+
+    # Was the conversion successful?
+    my $was_successful=0;
+    if (-s "$output_filestem.html") {
+	# make sure we have some content other than header
+	open (HTML, "$output_filestem.html"); # what to do if fail?
+	my $line;
+	my $past_header=0;
+	while ($line=<HTML>) {
+
+	    if ($past_header == 0) {
+		if ($line =~ /<body>/) {$past_header=1;}
+		next;
+	    }
+
+	    $line =~ s/<[^>]+>//g;
+	    if ($line =~ /\w/ && $past_header) {  # we found some content...
+		$was_successful=1;
+		last;
+	    }
+	}
+	close HTML;
+    }
+
+    if ($was_successful) {
+	&util::rm("$output_filestem.err")
+	    if (-e "$output_filestem.err");
+	# insert the (modified) table of contents, if it exists.
+	if (-e "${output_filestem}_ToC.html") {
+	    &util::mv("$output_filestem.html","$output_filestem.src");
+	    my $open_failed=0;
+	    open HTMLSRC, "$output_filestem.src" || ++$open_failed;
+	    open TOC, "${output_filestem}_ToC.html" || ++$open_failed;
+	    open HTML, ">$output_filestem.html" || ++$open_failed;
+	    
+	    if ($open_failed) {
+		close HTMLSRC;
+		close TOC;
+		close HTML;
+		&util::mv("$output_filestem.src","$output_filestem.html");
+		return 1;
+	    }
+
+	    # print out header info from src html.
+	    while (defined($_ = <HTMLSRC>) && $_ =~ /\w/) {
+		print HTML "$_";
+	    }
+
+	    # print out table of contents, making links relative
+	    <TOC>; <TOC>; # ignore first 2 lines
+	    print HTML scalar(<TOC>); # line 3 = "<ol>\n"
+	    my $line;
+	    while ($line=<TOC>) {
+		$line =~ s@</body></html>$@@ ; # only last line has this
+		# make link relative
+		$line =~ s@href=\"[^\#]+@href=\"@;
+		print HTML $line;
+	    }
+	    close TOC;
+
+	    # rest of html src
+	    while (<HTMLSRC>) {
+		print HTML $_;
+	    }
+	    close HTMLSRC;
+	    close HTML;
+
+	    &util::rm("${output_filestem}_ToC.html");
+	    &util::rm("${output_filestem}.src");
+	}
+	# we don't yet do anything with footnotes ($output_filestem_fn.html) :(
+	return 1; # success
+    }
+
+    if (-e "$output_filestem.err") {
+	if ($faillogfile ne "" && defined(open(FAILLOG,">>$faillogfile")))
+	{
+	    print FAILLOG "Error - rtftohtml - couldn't extract text\n";
+	    #print FAILLOG "Error - rtf-converter - couldn't extract text\n";
+	    print FAILLOG " (rtf file might be too recent):\n";
+	    open (ERRLOG, "$output_filestem.err");
+	    while (<ERRLOG>) {print FAILLOG $_;}
+	    close ERRLOG;
+	    close FAILLOG;
+	}
+	&util::rm("$output_filestem.err");
+    }
+
+    &util::rm("$output_filestem.html") if (-e "$output_filestem.html");
+
+    return 0;
+}
+
+
+# Convert a pdf file to html with the pdftohtml command
+
+sub pdf_to_html {
+    my ($dirname, $input_filename, $output_filestem) = @_;
+
+    $cmd = "";
+    if ($timeout) {$cmd = "ulimit -t $timeout;";}
+    $cmd .= "perl -S pdftohtml.pl -zoom $pdf_zoom";
+    $cmd .= " -c" if ($pdf_complex);
+    $cmd .= " -i" if ($pdf_ignore_images);
+    $cmd .= " -a" if ($pdf_allow_images_only);
+    $cmd .= " -hidden" unless ($pdf_nohidden);
+    $cmd .= " \"$input_filename\" \"$output_filestem\"";
+    
+    if ($ENV{'GSDLOS'} !~ /^windows$/i || $is_winnt_2000) {
+	$cmd .= " > \"$output_filestem.out\" 2> \"$output_filestem.err\"";
+    } else {
+	$cmd .= " > \"$output_filestem.err\"";
+    }
+
+    $!=0;
+
+    my $retval=system($cmd);
+    if ($retval!=0)
+    {
+	print STDERR "Error executing pdftohtml.pl";
+	if ($!) {print STDERR ": $!";} 
+	print STDERR "\n";
+    }
+
+    # make sure the converter made something
+    if ($retval!=0 || ! -s "$output_filestem.html")
+    {
+	&util::rm("$output_filestem.out") if (-e "$output_filestem.out");
+	# print out the converter's std err, if any
+	if (-s "$output_filestem.err") {
+	    open (ERRLOG, "$output_filestem.err") || die "$!";
+	    print STDERR "pdftohtml error log:\n";
+	    while (<ERRLOG>) {
+		print STDERR "$_";
+	    }
+	    close ERRLOG;
+	}
+	&util::rm("$output_filestem.html") if (-e "$output_filestem.html");
+	if (-e "$output_filestem.err") {
+	    if ($faillogfile ne "" && defined(open(FAILLOG,">>$faillogfile")))
+	    {
+		open (ERRLOG, "$output_filestem.err");
+		while (<ERRLOG>) {print FAILLOG $_;}
+		close ERRLOG;
+		close FAILLOG;
+	    }	
+	    &util::rm("$output_filestem.err");
+	}
+	return 0;
+    }
+
+    &util::rm("$output_filestem.err") if (-e "$output_filestem.err");
+    &util::rm("$output_filestem.out") if (-e "$output_filestem.out");
+    return 1;
+}
+
+# Convert a pdf file to various types of image with the convert command
+
+sub pdf_to_img {
+    my ($dirname, $input_filename, $output_filestem, $output_type) = @_;
+
+    # Check that ImageMagick is installed and available on the path (except for Windows 95/98)
+    if (!($ENV{'GSDLOS'} eq "windows" && !Win32::IsWinNT())) {
+	my $result = `identify 2>&1`;
+	if ($? == -1 || $? == 256) {  # Linux and Windows return different values for "program not found"
+	    #ImageMagick is not installed, thus the convert utility is not available. 
+	    print STDERR "*** ImageMagick is not installed, the convert utility is not available\n";
+	    return 0;
+	}
+    }
+
+    $cmd = "";
+    if ($timeout) {$cmd = "ulimit -t $timeout;";}
+    $output_type =~ s/.*\_(.*)/$1/i;
+     $cmd .= "perl -S pdftoimg.pl -convert_to $output_type \"$input_filename\" \"$output_filestem\"";
+    if ($ENV{'GSDLOS'} !~ /^windows$/i || $is_winnt_2000) {
+	$cmd .= " > \"$output_filestem.out\" 2> \"$output_filestem.err\"";
+    } else {
+	$cmd .= " > \"$output_filestem.err\"";
+    }
+
+    # don't include path on windows (to avoid having to play about
+    # with quoting when GSDLHOME might contain spaces) but assume
+    # that the PATH is set up correctly
+    $!=0;
+    my $retval=system($cmd);
+    if ($retval!=0)
+    {
+	print STDERR "Error executing pdftoimg.pl";
+	if ($!) {print STDERR ": $!";} 
+	print STDERR "\n";
+    }
+
+    #make sure the converter made something
+    #if ($retval !=0) || ! -s "$output_filestem")
+    if ($retval !=0) 
+    {
+	&util::rm("$output_filestem.out") if (-e "$output_filestem.out");
+	#print out the converter's std err, if any
+	if (-s "$output_filestem.err") {
+	    open (ERRLOG, "$output_filestem.err") || die "$!";
+	    print STDERR "pdftoimg error log:\n";
+	    while (<ERRLOG>) {
+		print STDERR "$_";
+	    }
+	    close ERRLOG;
+	}
+	#&util::rm("$output_filestem.html") if (-e "$output_filestem.html");
+	if (-e "$output_filestem.err") {
+	    if ($faillogfile ne "" && defined(open(FAILLOG,">>$faillogfile")))
+	    {
+		open (ERRLOG, "$output_filestem.err");
+		while (<ERRLOG>) {print FAILLOG $_;}
+		close ERRLOG;
+		close FAILLOG;
+	   }	
+	    &util::rm("$output_filestem.err");
+	}
+	return 0;
+    }
+    &util::rm("$output_filestem.err") if (-e "$output_filestem.err");
+    &util::rm("$output_filestem.out") if (-e "$output_filestem.out");
+    return 1;
+}
+
+# Convert a PDF file to text with the pdftotext command
+
+sub pdf_to_text {
+    my ($dirname, $input_filename, $output_filestem) = @_;
+
+    my $cmd = "pdftotext \"$input_filename\" \"$output_filestem.text\"";
+
+    if ($ENV{'GSDLOS'} !~ /^windows$/i) {
+	$cmd .= " > \"$output_filestem.out\" 2> \"$output_filestem.err\"";
+    } else {
+	$cmd .= " > \"$output_filestem.err\"";
+    }
+    
+    if (system($cmd)!=0)
+    {
+	print STDERR "Error executing $cmd: $!\n";
+	&util::rm("$output_filestem.text") if (-e "$output_filestem.text");
+    }
+
+    # make sure there is some extracted text.
+    if (-e "$output_filestem.text") {
+	open (EXTR_TEXT, "$output_filestem.text") || warn "open: $!";
+	binmode(EXTR_TEXT); # just in case...
+	my $line="";
+	my $seen_text=0;
+	while (($seen_text==0) && ($line=<EXTR_TEXT>)) {
+	    if ($line=~ /\w/) {$seen_text=1;}
+	}
+	close EXTR_TEXT;
+	if ($seen_text==0) { # no text was extracted
+	    print STDERR "Error: pdftotext found no text\n";
+	    &util::rm("$output_filestem.text");
+	}
+    }
+
+    # make sure the converter made something
+    if (! -s "$output_filestem.text")
+    {
+	# print out the converters std err, if any
+	if (-s "$output_filestem.err") {
+	    open (ERRLOG, "$output_filestem.err") || die "$!";
+	    print STDERR "pdftotext error log:\n";
+	    while (<ERRLOG>) {
+		print STDERR "$_";
+	    }
+	    close ERRLOG;
+	}
+	# does this converter create a .out file?
+	&util::rm("$output_filestem.out") if (-e "$output_filestem.out");
+	&util::rm("$output_filestem.text") if (-e "$output_filestem.text");
+	if (-e "$output_filestem.err") {
+	    if ($faillogfile ne "" && defined(open(FAILLOG,">>$faillogfile")))
+	    {
+		open (ERRLOG,"$output_filestem.err");
+		while (<ERRLOG>) {print FAILLOG $_;}
+		close ERRLOG;
+		close FAILLOG;
+	    }
+	    &util::rm("$output_filestem.err");
+	}
+	return 0;
+    }
+    &util::rm("$output_filestem.err") if (-e "$output_filestem.err");
+    return 1;
+}
+
+# Convert a PostScript document to text
+# note - just using "ps2ascii" isn't good enough, as it
+# returns 0 for a postscript interpreter error. ps2ascii is just
+# a wrapper to "gs" anyway, so we use that cmd here.
+
+sub ps_to_text {
+    my ($input_filename, $output_filestem) = @_;
+
+    my $error = "";
+
+    # if we're on windows we'll fall straight through without attempting
+    # to use gs
+    if ($ENV{'GSDLOS'} =~ /^windows$/i) {
+	$error = "Windows does not support gs";
+
+    } else {
+	my $cmd = "";
+	if ($timeout) {$cmd = "ulimit -t $timeout; ";}
+	$cmd .= "gs -q -dNODISPLAY -dNOBIND -dWRITESYSTEMDICT -dSIMPLE -c save ";
+	$cmd .= "-f ps2ascii.ps \"$input_filename\" -c quit > \"$output_filestem.text\"";
+	#$cmd .= "pstotext -output \"$output_filestem.text\" $input_filename\"";
+	$cmd .= " 2> $output_filestem.err";
+	$!=0;
+
+	my $retcode=system($cmd);
+	$retcode = $? >> 8;  # see man perlfunc - system for this...
+	# if system returns -1 | 127 (couldn't start program), look at $! for message
+
+	if ($retcode!=0) {if ($!) {$error=$!;} else {$error="couldn't run.\n";}}
+	elsif (! -e "$output_filestem.text") {
+	    $error="did not create output file.\n";
+	}
+	else 
+	{   # make sure the interpreter didn't get an error. It is technically
+	    # possible for the actual text to start with this, but....
+	    open PSOUT, "$output_filestem.text";
+	    if (<PSOUT> =~ /^Error: (.*)/) {
+		$error="interpreter error - \"$1\"";
+	    }
+	    close PSOUT;
+	}
+    }
+
+    if ($error ne "")
+    {
+	print STDERR "Warning: Error executing gs: $error\n";
+	&util::rm("$output_filestem.text") if (-e "$output_filestem.text");
+
+	if ("$faillogfile" ne "" && defined(open (FAILLOG, ">>$faillogfile")))
+	{
+	    print FAILLOG "gs - $error\n";
+	    if (-e "$output_filestem.err") {
+		open(ERRLOG, "$output_filestem.err");
+		while (<ERRLOG>) {print FAILLOG $_;}
+		close ERRLOG;
+	    }
+	    close FAILLOG;
+	}
+	&util::rm("$output_filestem.err") if (-e "$output_filestem.err");
+
+
+	# Fine then. We'll just do a lousy job by ourselves...
+	# Based on 5-line regexp sed script found at:
+	# http://snark.ptc.spbu.ru/mail-archives/lout/brown/msg00003.html
+	# 
+	print STDERR "Stripping text from postscript\n";
+	my $errorcode=0;
+	open (IN, "$input_filename") 
+	    ||  ($errorcode=1, warn "Couldn't read file: $!");
+	open (OUT, ">$output_filestem.text") 
+	    ||  ($errorcode=1, warn "Couldn't write file: $!");
+	if ($errorcode) {print STDERR "errors\n";return 0;}
+	
+	my $text="";  # this is for whole .ps file...
+	$text = join('', <IN>); # see man perlport, under "System Resources"
+	close IN;
+
+	# Make sure this is a ps file...
+	if ($text !~ /^%!/) {
+	    print STDERR "Bad postscript header: not '%!'\n";
+	    if ($faillogfile ne "" && defined(open(FAILLOG, ">>$faillogfile")))
+	    {
+		print FAILLOG "Bad postscript header: not '%!'\n";
+		close FAILLOG;
+	    }
+	    return 0;
+	}
+
+	# if ps has Page data, then use it to delete all stuff before it.
+	$text =~ s/^.*?%%Page:.*?\n//s; # treat string as single line
+	
+	# remove all leading non-data stuff
+	$text =~ s/^.*?\(//s;
+
+	# remove all newline chars for easier processing
+	$text =~ s/\n//g;
+	
+	# Big assumption here - assume that if any co-ordinates are
+	# given, then we are at the end of a sentence.
+	$text =~ s/\)-?\d+\ -?\d+/\) \(\n\)/g;
+
+	# special characters--
+	$text =~ s/\(\|\)/\(\ - \)/g; # j -> em-dash?
+
+	# ? ps text formatting (eg italics?) ?
+	$text =~ s/Fn\(f\)/\(\{\)/g; # f -> {
+	$text =~ s/Fn\(g\)/\(\}\)/g; # g -> }
+	$text =~ s/Fn\(j\)/\(\|\)/g; # j -> |
+	# default - remove the rest
+	$text =~ s/\ ?F.\((.+?)\)/\($1\)/g;
+
+	# attempt to add whitespace between words... 
+	# this is based purely on observation, and may be completely wrong...
+	$text =~ s/([^F])[defghijkuy]\(/$1 \( /g;
+	# eg I notice "b(" is sometimes NOT a space if preceded by a 
+	# negative number.
+	$text =~ s/\)\d+ ?b\(/\) \( /g;
+
+	# change quoted braces to brackets
+	$text =~ s/([^\\])\\\(/$1\{/g;
+	$text =~ s/([^\\])\\\)/$1\}/g ;
+
+	# remove everything that is not between braces
+	$text =~ s/\)([^\(\)])+?\(//sg ;
+	
+	# remove any Trailer eof stuff.
+	$text =~ s/\)[^\)]*$//sg;
+
+	### ligatures have special characters...
+	$text =~ s/\\013/ff/g;
+	$text =~ s/\\014/fi/g;
+	$text =~ s/\\015/fl/g;
+	$text =~ s/\\016/ffi/g;
+	$text =~ s/\\214/fi/g;
+	$text =~ s/\\215/fl/g;
+	$text =~ s/\\017/\n\* /g; # asterisk?
+	$text =~ s/\\023/\023/g;  # e acute ('e)
+	$text =~ s/\\177/\252/g;  # u"
+#	$text =~ s/ ?? /\344/g;  # a"
+
+	print OUT "$text";
+	close OUT;
+    }
+    # wrap the text - use a minimum length. ie, first space after this length.
+    my $wrap_length=72;
+    &util::mv("$output_filestem.text", "$output_filestem.text.tmp");
+    open INFILE, "$output_filestem.text.tmp" ||
+	die "Couldn't open file: $!";
+    open OUTFILE, ">$output_filestem.text" ||
+	die "Couldn't open file for writing: $!";
+    my $line="";
+    while ($line=<INFILE>) {
+	while (length($line)>0) {
+	    if (length($line)>$wrap_length) {
+		$line =~ s/^(.{$wrap_length}[^\s]*)\s*//;
+		print OUTFILE "$1\n";
+	    } else {
+		print OUTFILE "$line";
+		$line="";
+	    }
+	}
+    }
+    close INFILE;
+    close OUTFILE;
+    &util::rm("$output_filestem.text.tmp");
+
+    &util::rm("$output_filestem.err") if (-e "$output_filestem.err");
+    return 1;
+}
+
+
+# Convert a PS file to various types of image with the convert utility
+sub ps_to_img {
+    my ($dirname, $input_filename, $output_filestem, $output_type) = @_;
+
+    # Check that ImageMagick is installed and available on the path (except for Windows 95/98)
+    if (!($ENV{'GSDLOS'} eq "windows" && !Win32::IsWinNT())) {
+	my $result = `identify 2>&1`;
+	if ($? == -1 || $? == 256) {  # Linux and Windows return different values for "program not found"
+	    #ImageMagick is not installed, thus the convert utility is not available. 
+	    print STDERR "*** ImageMagick is not installed, the convert utility is not available\n";
+	    return 0;
+	}
+    }
+
+    $cmd = "";
+    if ($timeout) {$cmd = "ulimit -t $timeout;";}
+    $output_type =~ s/.*\_(.*)/$1/i;
+    $cmd .= "perl -S pstoimg.pl -convert_to $output_type \"$input_filename\" \"$output_filestem\"";
+    if ($ENV{'GSDLOS'} !~ /^windows$/i || $is_winnt_2000) {
+	$cmd .= " > \"$output_filestem.out\" 2> \"$output_filestem.err\"";
+    } else {
+	$cmd .= " > \"$output_filestem.err\"";
+    }
+
+    # don't include path on windows (to avoid having to play about
+    # with quoting when GSDLHOME might contain spaces) but assume
+    # that the PATH is set up correctly
+    $!=0;
+    my $retval=system($cmd);
+    if ($retval!=0)
+    {
+	print STDERR "Error executing pstoimg.pl";
+	if ($!) {print STDERR ": $!";} 
+	print STDERR "\n";
+    }
+    
+    #make sure the converter made something
+    #if ($retval !=0) || ! -s "$output_filestem")
+    if ($retval !=0) 
+    {
+	&util::rm("$output_filestem.out") if (-e "$output_filestem.out");
+	#print out the converter's std err, if any
+	if (-s "$output_filestem.err") {
+	    open (ERRLOG, "$output_filestem.err") || die "$!";
+	    print STDERR "pstoimg error log:\n";
+	    while (<ERRLOG>) {
+		print STDERR "$_";
+	    }
+	    close ERRLOG;
+	}
+	#&util::rm("$output_filestem.html") if (-e "$output_filestem.html");
+	if (-e "$output_filestem.err") {
+	    if ($faillogfile ne "" && defined(open(FAILLOG,">>$faillogfile")))
+	    {
+		open (ERRLOG, "$output_filestem.err");
+		while (<ERRLOG>) {print FAILLOG $_;}
+		close ERRLOG;
+		close FAILLOG;
+	   }	
+	    &util::rm("$output_filestem.err");
+	}
+	return 0;
+    }
+    &util::rm("$output_filestem.err") if (-e "$output_filestem.err");
+    &util::rm("$output_filestem.out") if (-e "$output_filestem.out");
+    return 1;
+}
+
+# Convert any file to HTML with a crude perl implementation of the
+# UNIX strings command.
+
+sub any_to_html {
+    ($input_filename, $output_filestem) = @_;
+
+    # First generate a text file
+    return 0 unless (&any_to_text($input_filename, $output_filestem));
+
+    # create an HTML file from the text file
+    open(TEXT, "<$output_filestem.text");
+    open(HTML, ">$output_filestem.html");
+
+    print HTML "<html><head>\n";
+    print HTML "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html\">\n";
+    print HTML "<META NAME=\"GENERATOR\" CONTENT=\"Greenstone any_to_html\">\n";
+    print HTML "</head><body>\n\n";
+
+    my $line;
+    while ($line=<TEXT>) { 
+	$line =~ s/</&lt;/g;
+	$line =~ s/>/&gt;/g;
+	if ($line =~ /^\s*$/) {
+	    print HTML "<p>";
+	} else {
+	    print HTML "<br> ", $line;
+	}
+    }
+    print HTML "\n</body></html>\n";
+
+    close HTML;
+    close TEXT;
+
+    &util::rm("$output_filestem.text") if (-e "$output_filestem.text");
+    return 1;
+}
+
+# Convert any file to TEXT with a crude perl implementation of the
+# UNIX strings command.
+# Note - this assumes ascii charsets :(		(jrm21)
+
+sub any_to_text {
+    ($input_filename, $output_filestem) = @_;
+
+    if (!$use_strings) {
+      return 0;
+    }
+    
+    open(IN, "<$input_filename") || return 0;
+    binmode(IN);
+    open(OUT, ">$output_filestem.text") || return 0;
+
+    my ($line);
+    my $output_line_count = 0;
+    while (<IN>) { 
+	$line = $_;
+
+	# delete anything that isn't a printable character
+	$line =~ s/[^\040-\176]+/\n/sg;
+
+	# delete any string less than 10 characters long
+	$line =~ s/^.{0,9}$/\n/mg;
+	while ($line =~ /^.{1,9}$/m) {
+	    $line =~ s/^.{0,9}$/\n/mg;
+	    $line =~ s/\n+/\n/sg;
+	}
+
+	# remove extraneous whitespace
+	$line =~ s/\n+/\n/gs;
+	$line =~ s/^\n//gs;
+
+	# output whatever is left
+	if ($line =~ /[^\n ]/) {
+	    print OUT $line;
+	    ++$output_line_count;
+	}
+    }
+
+    close OUT;
+    close IN;
+
+    if ($output_line_count) { # try to protect against binary only formats
+	return 1;
+    }
+
+    &util::rm("$output_filestem.text");
+    return 0;
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/gsWget.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/gsWget.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/gsWget.pl	(revision 13928)
@@ -0,0 +1,72 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+# This program will download the specified urls (http:, ftp: and file:)
+
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use util;
+
+# wget should live in the Greenstone directory structure
+# we'll bail if we can't find it
+my $exe = &util::get_os_exe ();
+my $cmd = &util::filename_cat ($ENV{'GSDLHOME'}, "bin", $ENV{'GSDLOS'}, "wget");
+$cmd .= $exe;
+if (! -e "$cmd") {
+    die "gsWget.pl failed: $cmd doesn't exist\n";
+}
+
+# if on windows we expect wget to already be on the path -
+# this allows us to avoid problems when GSDLHOME contains spaces
+# (double quoting the call doesn't work on win2000)
+if ($ENV{'GSDLOS'} =~ /^windows$/) {
+    $cmd = "wget";
+}
+
+# command-line parameters
+my @quoted_argv = map { "\"$_\"" } @ARGV;
+my $args = join(' ', @quoted_argv);
+$cmd .= " $args";
+
+# run the command
+my $status = system($cmd);
+
+# We should check the error status of wget; unfortunately this
+# is set to 1 even when we exit successfully, so we ignore it.
+#
+#$status /= 256;
+#if ($status != 0) {
+#    print STDERR "Error executing $cmd: $!\n";
+#    exit($status);
+#}
+
+print "\nDone: $cmd\n";
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/gsdlinfo.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/gsdlinfo.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/gsdlinfo.pl	(revision 13928)
@@ -0,0 +1,142 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# gsdlinfo.pl --
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+# This program will look to see what collections are installed
+# under this file system
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use parsargv;
+use colcfg;
+
+if (scalar(@ARGV) && ($ARGV[0] eq "--help" || $ARGV[0] eq "-h")) {
+    print STDERR "\n";
+    print STDERR "gsdlinfo.pl: Prints information on any Greenstone collections\n";
+    print STDERR "             found on the local file system.\n\n";
+    exit;
+}
+
+
+# the collection information is stored as an array of hashes
+# (one hash for each collection). The hash contains all the 
+# information in the collect and build configuration files
+
+
+# read in all the collection configuration information
+
+opendir (DIR, "$ENV{'GSDLHOME'}/collect") ||
+    die "ERROR - couldn't read the directory $ENV{'GSDLHOME'}/collect\n";
+@dir = readdir (DIR);
+closedir (DIR);
+
+@collections = ();
+foreach $dir (@dir) {
+    if ($dir =~ /^(\..*|modelcol|CVS)$/) {
+	# do nothing
+
+    } else {
+	# read in the collection configuration file
+	my $collectcfg = {};
+	if (-e "$ENV{'GSDLHOME'}/collect/$dir/etc/collect.cfg") {
+	    $collectcfg = &colcfg::read_collect_cfg ("$ENV{'GSDLHOME'}/collect/$dir/etc/collect.cfg");
+	}
+	$collectcfg->{'collection'} = $dir;
+
+	# read in the build configuration file
+	my $buildcfg = {};
+	if (-e "$ENV{'GSDLHOME'}/collect/$dir/index/build.cfg") {
+	    $buildcfg = &colcfg::read_build_cfg ("$ENV{'GSDLHOME'}/collect/$dir/index/build.cfg");
+	}
+
+	# add the merged configuration files to the current list of collections
+	push (@collections, {%$collectcfg, %$buildcfg});
+    }
+}
+
+
+# do any sorting requested
+
+
+# print out the collection information
+
+# {'creator'}->string
+# {'maintainer'}->array of strings
+# {'public'}->string
+# {'beta'}->string
+# {'key'}->string
+# {'indexes'}->array of strings
+# {'defaultindex'}->string
+# {'builddate'}->string
+# {'metadata'}->array of strings
+# {'languages'}->array of strings
+# {'numdocs'}->string
+# {'numwords'}->string
+# {'numbytes'}->string
+
+print "\n";
+foreach $info (@collections) {
+    if (defined $info->{'collection'}) {
+	$collection = $info->{'collection'};
+	if (defined $info->{'public'}) {
+	    $public = $info->{'public'};
+	} else {
+	    $public = "?";
+	}
+	if (defined $info->{'beta'}) {
+	    $beta = $info->{'beta'};
+	} else {
+	    $beta = "?";
+	}
+	if (defined $info->{'numdocs'}) {
+	    $numdocs = $info->{'numdocs'};
+	} else {
+	    $numdocs = "?";
+	}
+	if (defined $info->{'numbytes'}) {
+	    $numMbytes = int(($info->{'numbytes'}/1024.0/1024.0)*1000)/1000.0;
+	} else {
+	    $numMbytes = "?";
+	}
+	write;
+    }
+}
+print "\n";
+
+exit;
+
+format STDOUT_TOP = 
+  name   public  beta   documents  size (Mbytes)
+-------- ------ ------ ----------- -------------
+.
+
+format STDOUT = 
+@>>>>>>> @>>>>> @>>>>> @>>>>>>>>>> @>>>>>>>>>>>>
+$collection, $public, $beta, $numdocs, $numMbytes
+.
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/gsw3mir.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/gsw3mir.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/gsw3mir.pl	(revision 13928)
@@ -0,0 +1,52 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# urldownload.pl --
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+# This program will download the specified urls (http:, ftp: and file:)
+
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/cpan/lib");
+    $ENV{'PATH'} = "$ENV{'GSDLHOME'}/perllib/cpan/bin:$ENV{'PATH'}";
+}
+
+my @quoted_argv = map { "\"$_\"" } @ARGV;
+
+my $args = join(' ', @quoted_argv);
+$cmd = "w3mir $args";
+
+my $status = system($cmd);
+$status /= 256;
+if ($status != 0)
+{
+    print STDERR "Error: failed to execute $cmd\n";
+    exit($status);
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/gti-process-spreadsheet.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/gti-process-spreadsheet.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/gti-process-spreadsheet.pl	(revision 13928)
@@ -0,0 +1,114 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# gti-process-excel-xml.pl
+#
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 2005 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+use strict;
+
+
+sub main
+{
+    # Required parameter: the path of the spreadsheet file saved in UTF-16 Excel text format
+    my $utf16_excel_txt_file_path = shift(@_);
+    if (!defined($utf16_excel_txt_file_path)) {
+	die "Usage: gti-process-spreadsheet.pl <txt-file-path>\n";
+    }
+
+    # Ensure the UTF-16 Excel text file exists
+    if (!-f $utf16_excel_txt_file_path) {
+	die "Error: UTF-16 Excel text file $utf16_excel_txt_file_path does not exist.\n";
+    }
+
+    # Convert the Excel text file from UTF-16 to UTF-8
+    my $excel_txt_file_path = $utf16_excel_txt_file_path . "-utf8";
+    if (!-f $excel_txt_file_path) {
+	# Only bother if the file doesn't already exist
+	`iconv -f UTF-16 -t UTF-8 $utf16_excel_txt_file_path -o $excel_txt_file_path`;
+    }
+
+    # Read the (UTF-8) Excel Unicode text file data
+    open(EXCEL_TXT_FILE, $excel_txt_file_path);
+    my @excel_txt_file_lines = <EXCEL_TXT_FILE>;
+    my $excel_txt_file_data = join("", @excel_txt_file_lines);
+    close(EXCEL_TXT_FILE);
+
+    # Remove any nasty carriage returns
+    $excel_txt_file_data =~ s/\r//g;
+
+    # Make sure the first line is where we want it, and remove all stray whitespace
+    $excel_txt_file_data =~ s/^(\n)*/\n\n/;
+    $excel_txt_file_data =~ s/\n(\s*)\n/\n\n/g;
+
+    # Split into chunks
+    my @chunks = split(/\n\nsource::/, $excel_txt_file_data);
+    shift(@chunks);  # Ignore the first (empty) chunk
+    print STDERR "Number of chunks: " . scalar(@chunks) . "\n";
+
+    # Check we've split the chunks correctly
+    my $total_number_of_chunks = ($excel_txt_file_data =~ s/source::/source::/g);
+    if (scalar(@chunks) != $total_number_of_chunks) {
+	die "Error: Expected $total_number_of_chunks chunks but only have " . scalar(@chunks) . " from splitting";
+    }
+
+    # Process each submitted chunk
+    foreach my $chunk (@chunks) {
+ 	my $source_file_chunk = (split(/\ntarget::/, $chunk))[0];
+ 	my $target_file_chunk = (split(/\ntarget::/, $chunk))[1];
+
+ 	# Parse the chunk key and chunk text
+ 	$source_file_chunk =~ /^(\S+)\s+((.|\n)*)$/;
+ 	my $source_file_chunk_key = $1;
+ 	my $source_file_chunk_text = $2;
+ 	$target_file_chunk =~ /^(\S+)\s+((.|\n)*)$/;
+ 	my $target_file_chunk_key = $1;
+ 	my $target_file_chunk_text = $2;
+
+ 	# Remove the quotes around multiline chunks
+ 	if ($source_file_chunk_text =~ /^\"/ && $source_file_chunk_text =~ /\"$/) {
+ 	    $source_file_chunk_text =~ s/^\"//;
+ 	    $source_file_chunk_text =~ s/\"$//;
+ 	}
+ 	if ($target_file_chunk_text =~ /^\"/ && $target_file_chunk_text =~ /\"$/) {
+ 	    $target_file_chunk_text =~ s/^\"//;
+ 	    $target_file_chunk_text =~ s/\"$//;
+ 	}
+
+        # Remove the blank space Excel adds at the start of each line
+ 	$source_file_chunk_text =~ s/\n /\n/g;
+ 	$target_file_chunk_text =~ s/\n /\n/g;
+
+ 	# Remove Excel's doubled-up quotes
+ 	$source_file_chunk_text =~ s/\"\"/\"/g;
+ 	$target_file_chunk_text =~ s/\"\"/\"/g;
+
+ 	print "<SourceFileText key=\"" . $source_file_chunk_key . "\">\n" . $source_file_chunk_text . "\n</SourceFileText>\n";
+ 	print "<TargetFileText key=\"" . $target_file_chunk_key . "\">\n" . $target_file_chunk_text . "\n</TargetFileText>\n";
+    }
+}
+
+
+&main(@ARGV);
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/gti.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/gti.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/gti.pl	(revision 13928)
@@ -0,0 +1,1428 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# gti.pl
+#
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 2005 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+
+use iso639;
+use strict;
+use util;
+
+
+my $anonymous_cvs_root = ":pserver:cvs_anon\@cvs.scms.waikato.ac.nz:2402/usr/local/global-cvs/gsdl-src";
+my $gsdl_root_directory = "$ENV{'GSDLHOME'}";
+my $gti_log_file = &util::filename_cat($gsdl_root_directory, "etc", "gti.log");
+my $source_language_code = "en";  # This is non-negiotable
+
+my $gti_translation_files =
+    [ # Greenstone macrofiles
+      { 'key' => "coredm",
+	'file_type' => "macrofile",
+	'source_file' => "macros/english.dm",
+	'target_file' => "macros/{bn:bengali;fa:farsi;gd:gaelic;id:indo;lv:latvian;pt-br:port-br;pt-pt:port-pt;zh-tr:chinese-trad;iso_639_1_target_language_name}.dm" },
+      { 'key' => "auxdm",
+	'file_type' => "macrofile",
+	'source_file' => "macros/english2.dm",
+	'target_file' => "macros/{bn:bengali;fa:farsi;gd:gaelic;id:indo;lv:latvian;pt-br:port-br;pt-pt:port-pt;zh-tr:chinese-trad;iso_639_1_target_language_name}2.dm" },
+
+      # GLI dictionary
+      # { 'key' => "glidict",
+	# 'file_type' => "resource_bundle",
+	# 'source_file' => "gli/classes/dictionary.properties",
+	# 'target_file' => "gli/classes/dictionary_{target_language_code}.properties" },
+
+      # GLI help
+      # { 'key' => "glihelp",
+	# 'file_type' => "greenstone_xml",
+	# 'source_file' => "gli/help/en/help.xml",
+	# 'target_file' => "gli/help/{target_language_code}/help.xml" },
+
+      # Greenstone Perl modules
+      { 'key' => "perlmodules",
+	'file_type' => "resource_bundle",
+	'source_file' => "perllib/strings.properties",
+	'target_file' => "perllib/strings_{target_language_code}.properties" },
+
+      # Greenstone tutorial exercises
+      # { 'key' => "tutorials",
+	# 'file_type' => "greenstone_xml",
+	# 'source_file' => "gsdl-tutorials/tutorial_en.xml",
+	# 'target_file' => "gsdl-tutorials/tutorial_{target_language_code}.xml" },
+
+      # Greenstone.org
+      # { 'key' => "greenorg",
+	# 'file_type' => "macrofile",
+	# 'source_file' => "greenorg/macros/english.dm",
+	# 'target_file' => "greenorg/macros/{iso_639_1_target_language_name}.dm" }
+    ];
+
+
+sub main
+{
+    # Get the command to process, and any arguments
+    my $gti_command = shift(@_);
+    my @gti_command_arguments = @_;
+
+    # Open the GTI log file for appending, or write to STDERR if that fails
+    if (!open(GTI_LOG, ">>$gti_log_file")) {
+	open(GTI_LOG, ">&STDERR");
+    }
+
+    # Log the command that launched this script
+    &log_message("Command: $0 @ARGV");
+
+    # Check that a command was supplied
+    if (!$gti_command) {
+	&throw_fatal_error("Missing command.");
+    }
+
+    # Process the command
+    if ($gti_command =~ /^get-all-chunks$/i) {
+	print &get_all_chunks(@gti_command_arguments);
+    }
+    if ($gti_command =~ /^get-first-n-chunks-requiring-work$/i) {
+	print &get_first_n_chunks_requiring_work(@gti_command_arguments);
+    }
+    if ($gti_command =~ /^get-language-status$/i) {
+	print &get_language_status(@gti_command_arguments);
+    }
+    if ($gti_command =~ /^search-chunks$/i) {
+	print &search_chunks(@gti_command_arguments);
+    }
+    if ($gti_command =~ /^submit-translations$/i) {
+	# This command cannot produce any output since it reads input
+	&submit_translations(@gti_command_arguments);
+    }
+
+    # The command was not recognized
+    # &throw_fatal_error("Unknown command \"$gti_command\".");
+}
+
+
+sub throw_fatal_error
+{
+    my $error_message = shift(@_);
+
+    # Write an XML error response
+    print "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
+    print "<GTIResponse>\n";
+    print "  <GTIError time=\"" . time() . "\">" . $error_message . "</GTIError>\n";
+    print "</GTIResponse>\n";
+
+    # Log the error message, then die
+    &log_message("Error: $error_message");
+    die "\n";
+}
+
+
+sub log_message
+{
+    my $log_message = shift(@_);
+    print GTI_LOG time() . " -- " . $log_message . "\n";
+}
+
+
+sub get_all_chunks
+{
+    # The code of the target language (ensure it is lowercase)
+    my $target_language_code = lc(shift(@_));
+    # The key of the file to translate (ensure it is lowercase)
+    my $translation_file_key = lc(shift(@_));
+
+    # Check that the necessary arguments were supplied
+    if (!$target_language_code || !$translation_file_key) {
+	&throw_fatal_error("Missing command argument.");
+    }
+
+    # Get (and check) the translation configuration
+    my ($source_file, $target_file, $translation_file_type)
+	= &get_translation_configuration($target_language_code, $translation_file_key);
+
+    # Parse the source language and target language files
+    my $source_file_path = &util::filename_cat($gsdl_root_directory, $source_file);
+    my @source_file_lines = &read_file_lines($source_file_path);
+    my %source_file_key_to_line_mapping = &build_key_to_line_mapping(\@source_file_lines, $translation_file_type);
+
+    my $target_file_path = &util::filename_cat($gsdl_root_directory, $target_file);
+    my @target_file_lines = &read_file_lines($target_file_path);
+    my %target_file_key_to_line_mapping = &build_key_to_line_mapping(\@target_file_lines, $translation_file_type);
+
+    # Filter out any automatically translated chunks
+    foreach my $chunk_key (keys(%source_file_key_to_line_mapping)) {
+	if (&is_chunk_automatically_translated($chunk_key, $translation_file_type)) {
+	    delete $source_file_key_to_line_mapping{$chunk_key};
+	    delete $target_file_key_to_line_mapping{$chunk_key};
+	}
+    }
+
+    my %source_file_key_to_text_mapping = &build_key_to_text_mapping(\@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
+    my %target_file_key_to_text_mapping = &build_key_to_text_mapping(\@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);
+    &log_message("Number of source chunks: " . scalar(keys(%source_file_key_to_text_mapping)));
+    &log_message("Number of target chunks: " . scalar(keys(%target_file_key_to_text_mapping)));
+
+    my %source_file_key_to_last_update_date_mapping = &build_key_to_last_update_date_mapping($source_file, \@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
+    my %target_file_key_to_last_update_date_mapping = &build_key_to_last_update_date_mapping($target_file, \@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);
+
+    # Form an XML response to the command
+    my $xml_response = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
+    $xml_response .= "<GTIResponse>\n";
+    $xml_response .= "  <TranslationFile"
+	. " key=\"" . $translation_file_key . "\""
+	. " target_file_path=\"" . $target_file . "\"\/>\n";
+
+    # Do all the chunks
+    $xml_response .= "  <Chunks size=\"" . scalar(keys(%source_file_key_to_text_mapping)) . "\">\n";
+    foreach my $chunk_key (keys(%source_file_key_to_text_mapping)) {
+	my $source_file_chunk_date = $source_file_key_to_last_update_date_mapping{$chunk_key};
+	my $source_file_chunk_text = &make_text_xml_safe($source_file_key_to_text_mapping{$chunk_key});
+
+	$xml_response .= "    <Chunk key=\"" . &make_text_xml_safe($chunk_key) . "\">\n";
+	$xml_response .= "      <SourceFileText date=\"$source_file_chunk_date\">$source_file_chunk_text</SourceFileText>\n";
+	if (defined($target_file_key_to_text_mapping{$chunk_key})) {
+	    my $target_file_chunk_date = $target_file_key_to_last_update_date_mapping{$chunk_key};
+	    my $target_file_chunk_text = &make_text_xml_safe($target_file_key_to_text_mapping{$chunk_key});
+	    $xml_response .= "      <TargetFileText date=\"$target_file_chunk_date\">$target_file_chunk_text</TargetFileText>\n";
+	}
+	else {
+	    $xml_response .= "      <TargetFileText></TargetFileText>\n";
+	}
+
+	$xml_response .= "    </Chunk>\n";
+    }
+    $xml_response .= "  </Chunks>\n";
+
+    $xml_response .= "</GTIResponse>\n";
+    return $xml_response;
+}
+
+
+sub get_first_n_chunks_requiring_work
+{
+    # The code of the target language (ensure it is lowercase)
+    my $target_language_code = lc(shift(@_));
+    # The key of the file to translate (ensure it is lowercase)
+    my $translation_file_key = lc(shift(@_));
+    # The number of chunks to return (defaults to one if not specified)
+    my $num_chunks_to_return = shift(@_) || "1";
+
+    # Check that the necessary arguments were supplied
+    if (!$target_language_code || !$translation_file_key) {
+	&throw_fatal_error("Missing command argument.");
+    }
+
+    # Get (and check) the translation configuration
+    my ($source_file, $target_file, $translation_file_type)
+	= &get_translation_configuration($target_language_code, $translation_file_key);
+
+    # Parse the source language and target language files
+    my $source_file_path = &util::filename_cat($gsdl_root_directory, $source_file);
+    my @source_file_lines = &read_file_lines($source_file_path);
+    my %source_file_key_to_line_mapping = &build_key_to_line_mapping(\@source_file_lines, $translation_file_type);
+
+    my $target_file_path = &util::filename_cat($gsdl_root_directory, $target_file);
+    my @target_file_lines = &read_file_lines($target_file_path);
+    my %target_file_key_to_line_mapping = &build_key_to_line_mapping(\@target_file_lines, $translation_file_type);
+
+    # Filter out any automatically translated chunks
+    foreach my $chunk_key (keys(%source_file_key_to_line_mapping)) {
+	if (&is_chunk_automatically_translated($chunk_key, $translation_file_type)) {
+	    delete $source_file_key_to_line_mapping{$chunk_key};
+	    delete $target_file_key_to_line_mapping{$chunk_key};
+	}
+    }
+
+    my %source_file_key_to_text_mapping = &build_key_to_text_mapping(\@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
+    my %target_file_key_to_text_mapping = &build_key_to_text_mapping(\@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);
+    &log_message("Number of source chunks: " . scalar(keys(%source_file_key_to_text_mapping)));
+    &log_message("Number of target chunks: " . scalar(keys(%target_file_key_to_text_mapping)));
+
+    # Determine the target file chunks requiring translation
+    my @target_file_keys_requiring_translation = &determine_chunks_requiring_translation(\%source_file_key_to_text_mapping, \%target_file_key_to_text_mapping);
+    &log_message("Number of target chunks requiring translation: " . scalar(@target_file_keys_requiring_translation));
+
+    # Determine the target file chunks requiring updating
+    my %source_file_key_to_last_update_date_mapping = &build_key_to_last_update_date_mapping($source_file, \@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
+    my %target_file_key_to_last_update_date_mapping = &build_key_to_last_update_date_mapping($target_file, \@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);
+    my @target_file_keys_requiring_updating = &determine_chunks_requiring_updating(\%source_file_key_to_last_update_date_mapping, \%target_file_key_to_last_update_date_mapping);
+    &log_message("Number of target chunks requiring updating: " . scalar(@target_file_keys_requiring_updating));
+
+    # Form an XML response to the command
+    my $xml_response = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
+    $xml_response .= "<GTIResponse>\n";
+    $xml_response .= "  <TranslationFile"
+	. " key=\"" . $translation_file_key . "\""
+	. " target_file_path=\"" . $target_file . "\""
+	. " num_chunks_translated=\"" . (scalar(keys(%source_file_key_to_text_mapping)) - scalar(@target_file_keys_requiring_translation)) . "\""
+	. " num_chunks_requiring_translation=\"" . scalar(@target_file_keys_requiring_translation) . "\""
+	. " num_chunks_requiring_updating=\"" . scalar(@target_file_keys_requiring_updating) . "\"\/>\n";
+
+    # Do chunks requiring translation first
+    if ($num_chunks_to_return > scalar(@target_file_keys_requiring_translation)) {
+	$xml_response .= "  <ChunksRequiringTranslation size=\"" . scalar(@target_file_keys_requiring_translation) . "\">\n";
+    }
+    else {
+	$xml_response .= "  <ChunksRequiringTranslation size=\"" . $num_chunks_to_return . "\">\n";
+    }
+
+    foreach my $chunk_key (@target_file_keys_requiring_translation) {
+	last if ($num_chunks_to_return == 0);
+
+	my $source_file_chunk_date = $source_file_key_to_last_update_date_mapping{$chunk_key};
+	my $source_file_chunk_text = &make_text_xml_safe($source_file_key_to_text_mapping{$chunk_key});
+
+	$xml_response .= "    <Chunk key=\"" . &make_text_xml_safe($chunk_key) . "\">\n";
+	$xml_response .= "      <SourceFileText date=\"$source_file_chunk_date\">$source_file_chunk_text</SourceFileText>\n";
+	$xml_response .= "      <TargetFileText></TargetFileText>\n";
+	$xml_response .= "    </Chunk>\n";
+
+	$num_chunks_to_return--;
+    }
+
+    $xml_response .= "  </ChunksRequiringTranslation>\n";
+
+    # Then do chunks requiring updating
+    if ($num_chunks_to_return > scalar(@target_file_keys_requiring_updating)) {
+	$xml_response .= "  <ChunksRequiringUpdating size=\"" . scalar(@target_file_keys_requiring_updating) . "\">\n";
+    }
+    else {
+	$xml_response .= "  <ChunksRequiringUpdating size=\"" . $num_chunks_to_return . "\">\n";
+    }
+
+    foreach my $chunk_key (@target_file_keys_requiring_updating) {
+	last if ($num_chunks_to_return == 0);
+
+	my $source_file_chunk_date = $source_file_key_to_last_update_date_mapping{$chunk_key};
+	my $source_file_chunk_text = &make_text_xml_safe($source_file_key_to_text_mapping{$chunk_key});
+	my $target_file_chunk_date = $target_file_key_to_last_update_date_mapping{$chunk_key};
+	my $target_file_chunk_text = &make_text_xml_safe($target_file_key_to_text_mapping{$chunk_key});
+
+	$xml_response .= "    <Chunk key=\"" . &make_text_xml_safe($chunk_key) . "\">\n";
+	$xml_response .= "      <SourceFileText date=\"$source_file_chunk_date\">$source_file_chunk_text</SourceFileText>\n";
+	$xml_response .= "      <TargetFileText date=\"$target_file_chunk_date\">$target_file_chunk_text</TargetFileText>\n";
+	$xml_response .= "    </Chunk>\n";
+
+	$num_chunks_to_return--;
+    }
+
+    $xml_response .= "  </ChunksRequiringUpdating>\n";
+
+    $xml_response .= "</GTIResponse>\n";
+    return $xml_response;
+}
+
+
+sub get_language_status
+{
+    # The code of the target language (ensure it is lowercase)
+    my $target_language_code = lc(shift(@_));
+
+    # Check that the necessary arguments were supplied
+    if (!$target_language_code) {
+	&throw_fatal_error("Missing command argument.");
+    }
+
+    # Form an XML response to the command
+    my $xml_response = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
+    $xml_response .= "<GTIResponse>\n";
+    $xml_response .= "  <LanguageStatus code=\"$target_language_code\">\n";
+
+    foreach my $translation_file (@$gti_translation_files) {
+	# Get (and check) the translation configuration
+	my ($source_file, $target_file, $translation_file_type)
+	    = &get_translation_configuration($target_language_code, $translation_file->{'key'});
+
+	# Parse the source language and target language files
+	my $source_file_path = &util::filename_cat($gsdl_root_directory, $source_file);
+	my @source_file_lines = &read_file_lines($source_file_path);
+	my %source_file_key_to_line_mapping = &build_key_to_line_mapping(\@source_file_lines, $translation_file_type);
+
+	my $target_file_path = &util::filename_cat($gsdl_root_directory, $target_file);
+	my @target_file_lines = &read_file_lines($target_file_path);
+	my %target_file_key_to_line_mapping = &build_key_to_line_mapping(\@target_file_lines, $translation_file_type);
+
+	# Filter out any automatically translated chunks
+	foreach my $chunk_key (keys(%source_file_key_to_line_mapping)) {
+	    if (&is_chunk_automatically_translated($chunk_key, $translation_file_type)) {
+		delete $source_file_key_to_line_mapping{$chunk_key};
+		delete $target_file_key_to_line_mapping{$chunk_key};
+	    }
+	}
+
+	my %source_file_key_to_text_mapping = &build_key_to_text_mapping(\@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
+	my %target_file_key_to_text_mapping = &build_key_to_text_mapping(\@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);
+	&log_message("Number of source chunks: " . scalar(keys(%source_file_key_to_text_mapping)));
+	&log_message("Number of target chunks: " . scalar(keys(%target_file_key_to_text_mapping)));
+
+	# Determine the target file chunks requiring translation
+	my @target_file_keys_requiring_translation = &determine_chunks_requiring_translation(\%source_file_key_to_text_mapping, \%target_file_key_to_text_mapping);
+	&log_message("Number of target chunks requiring translation: " . scalar(@target_file_keys_requiring_translation));
+
+	# Determine the target file chunks requiring updating
+	my @target_file_keys_requiring_updating = ();
+	if (-e $target_file_path) {
+	    my %source_file_key_to_last_update_date_mapping = &build_key_to_last_update_date_mapping($source_file, \@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
+	    my %target_file_key_to_last_update_date_mapping = &build_key_to_last_update_date_mapping($target_file, \@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);
+	    @target_file_keys_requiring_updating = &determine_chunks_requiring_updating(\%source_file_key_to_last_update_date_mapping, \%target_file_key_to_last_update_date_mapping);
+	    &log_message("Number of target chunks requiring updating: " . scalar(@target_file_keys_requiring_updating));
+	}
+
+	$xml_response .= "    <TranslationFile"
+	    . " key=\"" . $translation_file->{'key'} . "\""
+	    . " target_file_path=\"" . $target_file . "\""
+	    . " num_chunks_translated=\"" . (scalar(keys(%source_file_key_to_text_mapping)) - scalar(@target_file_keys_requiring_translation)) . "\""
+	    . " num_chunks_requiring_translation=\"" . scalar(@target_file_keys_requiring_translation) . "\""
+	    . " num_chunks_requiring_updating=\"" . scalar(@target_file_keys_requiring_updating) . "\"\/>\n";
+    }
+
+    $xml_response .= "  </LanguageStatus>\n";
+
+    $xml_response .= "</GTIResponse>\n";
+    return $xml_response;
+}
+
+
+sub search_chunks
+{
+    # The code of the target language (ensure it is lowercase)
+    my $target_language_code = lc(shift(@_));
+    # The key of the file to translate (ensure it is lowercase)
+    my $translation_file_key = lc(shift(@_));
+    # The query string
+    my $query_string = join(' ', @_);
+
+    # Check that the necessary arguments were supplied
+    if (!$target_language_code || !$translation_file_key || !$query_string) {
+	&throw_fatal_error("Missing command argument.");
+    }
+
+    # Get (and check) the translation configuration
+    my ($source_file, $target_file, $translation_file_type)
+	= &get_translation_configuration($target_language_code, $translation_file_key);
+
+    # Parse the source language and target language files
+    my $source_file_path = &util::filename_cat($gsdl_root_directory, $source_file);
+    my @source_file_lines = &read_file_lines($source_file_path);
+    my %source_file_key_to_line_mapping = &build_key_to_line_mapping(\@source_file_lines, $translation_file_type);
+
+    my $target_file_path = &util::filename_cat($gsdl_root_directory, $target_file);
+    my @target_file_lines = &read_file_lines($target_file_path);
+    my %target_file_key_to_line_mapping = &build_key_to_line_mapping(\@target_file_lines, $translation_file_type);
+
+    # Filter out any automatically translated chunks
+    foreach my $chunk_key (keys(%source_file_key_to_line_mapping)) {
+	if (&is_chunk_automatically_translated($chunk_key, $translation_file_type)) {
+	    delete $source_file_key_to_line_mapping{$chunk_key};
+	    delete $target_file_key_to_line_mapping{$chunk_key};
+	}
+    }
+
+    my %source_file_key_to_text_mapping = &build_key_to_text_mapping(\@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
+    my %target_file_key_to_text_mapping = &build_key_to_text_mapping(\@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);
+    &log_message("Number of source chunks: " . scalar(keys(%source_file_key_to_text_mapping)));
+    &log_message("Number of target chunks: " . scalar(keys(%target_file_key_to_text_mapping)));
+
+    # Determine the target file chunks matching the query
+    my @target_file_keys_matching_query = ();
+    foreach my $chunk_key (keys(%target_file_key_to_text_mapping)) {
+	my $target_file_text = $target_file_key_to_text_mapping{$chunk_key};
+	if ($target_file_text =~ /$query_string/i) {
+	    # &log_message("Chunk with key $chunk_key matches query.");
+	    push(@target_file_keys_matching_query, $chunk_key);
+	}
+    }
+
+    # Form an XML response to the command
+    my $xml_response = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
+    $xml_response .= "<GTIResponse>\n";
+
+    $xml_response .= "  <ChunksMatchingQuery size=\"" . scalar(@target_file_keys_matching_query) . "\">\n";
+    foreach my $chunk_key (@target_file_keys_matching_query) {
+ 	my $target_file_chunk_text = &make_text_xml_safe($target_file_key_to_text_mapping{$chunk_key});
+
+ 	$xml_response .= "    <Chunk key=\"$chunk_key\">\n";
+ 	$xml_response .= "      <TargetFileText>$target_file_chunk_text</TargetFileText>\n";
+ 	$xml_response .= "    </Chunk>\n";
+    }
+    $xml_response .= "  </ChunksMatchingQuery>\n";
+
+    $xml_response .= "</GTIResponse>\n";
+    return $xml_response;
+}
+
+
+sub submit_translations
+{
+    # The code of the target language (ensure it is lowercase)
+    my $target_language_code = lc(shift(@_));
+    # The key of the file to translate (ensure it is lowercase)
+    my $translation_file_key = lc(shift(@_));
+    # The username of the translation submitter
+    my $submitter_username = shift(@_);
+    # Whether to submit a target chunk even if it hasn't changed
+    my $force_submission_flag = shift(@_);
+
+    # Check that the necessary arguments were supplied
+    if (!$target_language_code || !$translation_file_key || !$submitter_username) {
+	&log_message("Fatal error (but cannot be thrown): Missing command argument.");
+	die "\n";
+    }
+
+    # Get (and check) the translation configuration
+    my ($source_file, $target_file, $translation_file_type)
+	= &get_translation_configuration($target_language_code, $translation_file_key);
+
+    # Parse the source language and target language files
+    my @source_file_lines = &read_file_lines(&util::filename_cat($gsdl_root_directory, $source_file));
+    my %source_file_key_to_line_mapping = &build_key_to_line_mapping(\@source_file_lines, $translation_file_type);
+    my %source_file_key_to_text_mapping = &build_key_to_text_mapping(\@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
+    my %source_file_key_to_gti_comment_mapping = &build_key_to_gti_comment_mapping(\@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
+    &log_message("Number of source chunks: " . scalar(keys(%source_file_key_to_text_mapping)));
+
+    my @target_file_lines = &read_file_lines(&util::filename_cat($gsdl_root_directory, $target_file));
+    my %target_file_key_to_line_mapping = &build_key_to_line_mapping(\@target_file_lines, $translation_file_type);
+    my %target_file_key_to_text_mapping = &build_key_to_text_mapping(\@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);
+    my %target_file_key_to_gti_comment_mapping = &build_key_to_gti_comment_mapping(\@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);
+    &log_message("Number of target chunks: " . scalar(keys(%target_file_key_to_text_mapping)));
+
+    # Submission date
+    my $day = (localtime)[3];
+    my $month = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")[(localtime)[4]];
+    my $year = (localtime)[5] + 1900;
+    my $submission_date = "$day-$month-$year";
+
+    open(SUBMISSION, "-");
+    my @submission_lines = <SUBMISSION>;
+    close(SUBMISSION);
+
+    # Remove any nasty carriage returns
+    &log_message("Submission:");
+    foreach my $submission_line (@submission_lines) {
+	$submission_line =~ s/\r$//;
+	&log_message("  $submission_line");
+    }
+
+    my %source_file_key_to_submission_mapping = ();
+    my %target_file_key_to_submission_mapping = ();
+    for (my $i = 0; $i < scalar(@submission_lines); $i++) {
+	# Read source file part of submission
+	if ($submission_lines[$i] =~ /^\<SourceFileText key=\"(.+)\"\>/) {
+	    my $chunk_key = $1;
+
+	    # Read the source file text
+	    my $source_file_chunk_text = "";
+	    $i++;
+	    while ($i < scalar(@submission_lines) && $submission_lines[$i] !~ /^\<\/SourceFileText\>/) {
+		$source_file_chunk_text .= $submission_lines[$i];
+ 		$i++;
+	    }
+	    $source_file_chunk_text =~ s/\n$//;  # Strip the extra newline character added
+	    $source_file_chunk_text = &unmake_text_xml_safe($source_file_chunk_text);
+
+	    &log_message("Source file key: $chunk_key");
+	    &log_message("Source file text: $source_file_chunk_text");
+	    $source_file_key_to_submission_mapping{$chunk_key} = $source_file_chunk_text;
+	}
+
+	# Read target file part of submission
+	if ($submission_lines[$i] =~ /^\<TargetFileText key=\"(.+)\"\>/) {
+	    my $chunk_key = $1;
+
+	    # Read the target file text
+	    my $target_file_chunk_text = "";
+	    $i++;
+	    while ($i < scalar(@submission_lines) && $submission_lines[$i] !~ /^\<\/TargetFileText\>/) {
+		$target_file_chunk_text .= $submission_lines[$i];
+ 		$i++;
+	    }
+	    $target_file_chunk_text =~ s/\n$//;  # Strip the extra newline character added
+	    $target_file_chunk_text = &unmake_text_xml_safe($target_file_chunk_text);
+
+	    &log_message("Target file key: $chunk_key");
+	    &log_message("Target file text: $target_file_chunk_text");
+	    $target_file_key_to_submission_mapping{$chunk_key} = $target_file_chunk_text;
+	}
+    }
+
+    # -----------------------------------------
+    #   Validate the translation submissions
+    # -----------------------------------------
+
+    # Check that the translations are valid
+    foreach my $chunk_key (keys(%source_file_key_to_submission_mapping)) {
+	# Make sure the submitted chunk still exists in the source file
+	if (!defined($source_file_key_to_text_mapping{$chunk_key})) {
+	    &log_message("Warning: Source chunk $chunk_key no longer exists (ignoring submission).");
+	    delete $source_file_key_to_submission_mapping{$chunk_key};
+	    delete $target_file_key_to_submission_mapping{$chunk_key};
+	    next;
+	}
+
+	# Make sure the submitted source chunk matches the source file chunk
+	if ($source_file_key_to_submission_mapping{$chunk_key} ne $source_file_key_to_text_mapping{$chunk_key}) {
+	    &log_message("Warning: Source chunk $chunk_key has changed (ignoring submission).");
+	    &log_message("Submission source: $source_file_key_to_submission_mapping{$chunk_key}");
+	    &log_message("      Source text: $source_file_key_to_text_mapping{$chunk_key}");
+	    delete $source_file_key_to_submission_mapping{$chunk_key};
+	    delete $target_file_key_to_submission_mapping{$chunk_key};
+	    next;
+	}
+    }
+
+    # Apply the submitted translations
+    foreach my $chunk_key (keys(%target_file_key_to_submission_mapping)) {
+	# Only apply the submission if it is a change, unless -force_submission has been specified
+	if ($force_submission_flag || !defined($target_file_key_to_text_mapping{$chunk_key}) || $target_file_key_to_submission_mapping{$chunk_key} ne $target_file_key_to_text_mapping{$chunk_key}) {
+	    $target_file_key_to_text_mapping{$chunk_key} = $target_file_key_to_submission_mapping{$chunk_key};
+	    $target_file_key_to_gti_comment_mapping{$chunk_key} = "Updated $submission_date by $submitter_username";
+	}
+    }
+
+    eval "&write_translated_${translation_file_type}(\$source_file, \\\@source_file_lines, \\\%source_file_key_to_text_mapping, \$target_file, \\\@target_file_lines, \\\%target_file_key_to_text_mapping, \\\%target_file_key_to_gti_comment_mapping, \$target_language_code)";
+}
+
+
+sub get_translation_configuration
+{
+    # Get the code of the target language
+    my $target_language_code = shift(@_);
+    # Get the key of the file to translate
+    my $translation_file_key = shift(@_);
+
+    # Read the translation data from the gti.cfg file
+    my ($source_file, $target_file, $translation_file_type) =
+	&get_translation_data_for($target_language_code, $translation_file_key);
+
+    # Check that the file to translate is defined in the gti.cfg file
+    if (!$source_file || !$target_file || !$translation_file_type) {
+	&throw_fatal_error("Missing or incomplete specification for translation file \"$translation_file_key\" in gti.pl.");
+    }
+
+    # Check that the source file exists
+    my $source_file_path = &util::filename_cat($gsdl_root_directory, $source_file);
+    if (!-e $source_file_path) {
+	&throw_fatal_error("Source file $source_file_path does not exist.");
+    }
+
+    # Check that the source file is up to date
+    # The "2>/dev/null" is very important! If it is missing this will never return when run from the receptionist
+    # unless ($translation_file_is_not_in_cvs) {
+	my $source_file_cvs_status = `cd $gsdl_root_directory; cvs -d $anonymous_cvs_root update $source_file 2>/dev/null`;
+	if ($source_file_cvs_status =~ /^C /) {
+	    &throw_fatal_error("Source file $source_file_path conflicts with the repository.");
+	}
+	if ($source_file_cvs_status =~ /^M /) {
+	    &throw_fatal_error("Source file $source_file_path contains uncommitted changes.");
+	}
+    # }
+
+    return ($source_file, $target_file, $translation_file_type);
+}
+
+
+sub get_translation_data_for
+{
+    my ($target_language_code, $translation_file_key) = @_;
+
+    foreach my $translation_file (@$gti_translation_files) {
+	# If this isn't the correct translation file, move onto the next one
+	next if ($translation_file_key ne $translation_file->{'key'});
+
+	# Resolve the target language file
+	my $target_language_file = $translation_file->{'target_file'};
+	if ($target_language_file =~ /(\{.+\;.+\})/) {
+	    my $unresolved_target_language_file_part = $1;
+
+	    # Check for a special case for the target language code
+	    if ($unresolved_target_language_file_part =~ /(\{|\;)$target_language_code:([^\;]+)(\;|\})/) {
+		my $resolved_target_language_file_part = $2;
+		$target_language_file =~ s/$unresolved_target_language_file_part/$resolved_target_language_file_part/;
+	    }
+	    # Otherwise use the last part as the default value
+	    else {
+		my ($default_target_language_file_part) = $unresolved_target_language_file_part =~ /([^\;]+)\}/;
+		$target_language_file =~ s/$unresolved_target_language_file_part/\{$default_target_language_file_part\}/;		    
+	    }
+	}
+
+	# Resolve instances of {iso_639_1_target_language_name}
+	my $iso_639_1_target_language_name = $iso639::fromiso639{$target_language_code};
+	$iso_639_1_target_language_name =~ tr/A-Z/a-z/ if $iso_639_1_target_language_name;
+	$target_language_file =~ s/\{iso_639_1_target_language_name\}/$iso_639_1_target_language_name/g;
+
+	# Resolve instances of {target_language_code}
+	$target_language_file =~ s/\{target_language_code\}/$target_language_code/g;
+
+	return ($translation_file->{'source_file'}, $target_language_file, $translation_file->{'file_type'});
+    }
+
+    return ();
+}
+
+
+sub read_file_lines
+{
+    my ($file_path) = @_;
+
+    if (!open(FILE_IN, "<$file_path")) {
+	&log_message("Note: Could not open file $file_path.");
+	return ();
+    }
+    my @file_lines = <FILE_IN>;
+    close(FILE_IN);
+
+    return @file_lines;
+}
+
+
+sub build_key_to_line_mapping
+{
+    my ($file_lines, $translation_file_type) = @_;
+    eval "return &build_key_to_line_mapping_for_${translation_file_type}(\@\$file_lines)";
+}
+
+
+sub build_key_to_text_mapping
+{
+    my ($file_lines, $key_to_line_mapping, $translation_file_type) = @_;
+
+    my %key_to_text_mapping = ();
+    foreach my $chunk_key (keys(%$key_to_line_mapping)) {
+	my $chunk_starting_line = (split(/-/, $key_to_line_mapping->{$chunk_key}))[0];
+	my $chunk_finishing_line = (split(/-/, $key_to_line_mapping->{$chunk_key}))[1];
+
+	my $chunk_text = @$file_lines[$chunk_starting_line];
+	for (my $l = ($chunk_starting_line + 1); $l <= $chunk_finishing_line; $l++) {
+	    $chunk_text .= @$file_lines[$l];
+	}
+
+	# Map from chunk key to text
+	eval "\$key_to_text_mapping{\${chunk_key}} = &import_chunk_from_${translation_file_type}(\$chunk_text)";
+    }
+
+    return %key_to_text_mapping;
+}
+
+
+sub build_key_to_last_update_date_mapping
+{
+    my ($file, $file_lines, $key_to_line_mapping, $translation_file_type) = @_;
+
+    # If the files aren't in CVS then we can't tell anything about what needs updating
+    # return () if ($translation_file_is_not_in_cvs);
+
+    # Build a mapping from key to CVS date
+    # Need to be careful with this mapping because the chunk keys won't necessarily all be valid
+    my %key_to_cvs_date_mapping = &build_key_to_cvs_date_mapping($file, $translation_file_type);
+
+    # Build a mapping from key to comment date
+    my %key_to_gti_comment_mapping = &build_key_to_gti_comment_mapping($file_lines, $key_to_line_mapping, $translation_file_type);
+
+    # Build a mapping from key to last update date (the latter of the CVS date and comment date)
+    my %key_to_last_update_date_mapping = ();
+    foreach my $chunk_key (keys(%$key_to_line_mapping)) {
+	# Use the CVS date as a starting point
+	my $chunk_cvs_date = $key_to_cvs_date_mapping{$chunk_key};
+	$key_to_last_update_date_mapping{$chunk_key} = $chunk_cvs_date;
+
+	# If a comment date exists and it is after the CVS date, use that instead
+	my $chunk_gti_comment = $key_to_gti_comment_mapping{$chunk_key};
+	if (defined($chunk_gti_comment) && $chunk_gti_comment =~ /(\d?\d-\D\D\D-\d\d\d\d)/) {
+	    my $chunk_comment_date = $1;
+	    if ((!defined($chunk_cvs_date) || &is_date_after($chunk_comment_date, $chunk_cvs_date))) {
+		$key_to_last_update_date_mapping{$chunk_key} = $chunk_comment_date;
+	    }
+	}
+    }
+
+    return %key_to_last_update_date_mapping;
+}
+
+
+sub build_key_to_cvs_date_mapping
+{
+    my ($filename, $translation_file_type) = @_;
+
+    # Use CVS to annotate each line of the file with the date it was last edited
+    # The "2>/dev/null" is very important! If it is missing this will never return when run from the receptionist
+    my $cvs_annotated_file = `cd $gsdl_root_directory; cvs -d $anonymous_cvs_root annotate -F $filename 2>/dev/null`;
+    my @cvs_annotated_file_lines = split(/\n/, $cvs_annotated_file);
+
+    my @cvs_annotated_file_lines_date = ();
+    foreach my $cvs_annotated_file_line (@cvs_annotated_file_lines) {
+	# Extract the date from the CVS annotation at the front
+	$cvs_annotated_file_line =~ s/^\S+\s+\(\S+\s+(\S+)\):\s//;
+	push(@cvs_annotated_file_lines_date, $1);
+    }
+
+    # Build a key to line mapping for the CVS annotated file, for matching the chunk key to the CVS date
+    my %key_to_line_mapping = &build_key_to_line_mapping(\@cvs_annotated_file_lines, $translation_file_type);
+
+    my %key_to_cvs_date_mapping = ();
+    foreach my $chunk_key (keys(%key_to_line_mapping)) {
+ 	my $chunk_starting_line = (split(/-/, $key_to_line_mapping{$chunk_key}))[0];
+ 	my $chunk_finishing_line = (split(/-/, $key_to_line_mapping{$chunk_key}))[1];
+
+ 	# Find the date this chunk was last edited, from the CVS annotation
+ 	my $chunk_date = $cvs_annotated_file_lines_date[$chunk_starting_line];
+ 	for (my $l = ($chunk_starting_line + 1); $l <= $chunk_finishing_line; $l++) {
+ 	    if (&is_date_after($cvs_annotated_file_lines_date[$l], $chunk_date)) {
+ 		# This part of the chunk has been updated more recently
+ 		$chunk_date = $cvs_annotated_file_lines_date[$l];
+ 	    }
+ 	}
+
+ 	# Map from chunk key to CVS date
+ 	$key_to_cvs_date_mapping{$chunk_key} = $chunk_date;
+    }
+
+    return %key_to_cvs_date_mapping;
+}
+
+
+sub build_key_to_gti_comment_mapping
+{
+    my ($file_lines, $key_to_line_mapping, $translation_file_type) = @_;
+
+    my %key_to_gti_comment_mapping = ();
+    foreach my $chunk_key (keys(%$key_to_line_mapping)) {
+	my $chunk_starting_line = (split(/-/, $key_to_line_mapping->{$chunk_key}))[0];
+	my $chunk_finishing_line = (split(/-/, $key_to_line_mapping->{$chunk_key}))[1];
+
+	my $chunk_text = @$file_lines[$chunk_starting_line];
+	for (my $l = ($chunk_starting_line + 1); $l <= $chunk_finishing_line; $l++) {
+	    $chunk_text .= @$file_lines[$l];
+	}
+
+	# Map from chunk key to GTI comment
+	my $chunk_gti_comment;
+	eval "\$chunk_gti_comment = &get_${translation_file_type}_chunk_gti_comment(\$chunk_text)";
+	$key_to_gti_comment_mapping{$chunk_key} = $chunk_gti_comment if (defined($chunk_gti_comment));
+    }
+
+    return %key_to_gti_comment_mapping;
+}
+
+
+sub determine_chunks_requiring_translation
+{
+    my $source_file_key_to_text_mapping = shift(@_);
+    my $target_file_key_to_text_mapping = shift(@_);
+
+    # Chunks needing translation are those in the source file with no translation in the target file
+    my @target_file_keys_requiring_translation = ();
+    foreach my $chunk_key (keys(%$source_file_key_to_text_mapping)) {
+	if ($source_file_key_to_text_mapping->{$chunk_key} && !$target_file_key_to_text_mapping->{$chunk_key}) {
+	    # &log_message("Chunk with key $chunk_key needs translating.");
+	    push(@target_file_keys_requiring_translation, $chunk_key);
+	}
+    }
+
+    return @target_file_keys_requiring_translation;
+}
+
+
+sub determine_chunks_requiring_updating
+{
+    my $source_file_key_to_last_update_date_mapping = shift(@_);
+    my $target_file_key_to_last_update_date_mapping = shift(@_);
+
+    # Chunks needing updating are those in the target file that have been more recently edited in the source file
+    my @target_file_keys_requiring_updating = ();
+    foreach my $chunk_key (keys(%$source_file_key_to_last_update_date_mapping)) {
+	my $source_chunk_last_update_date = $source_file_key_to_last_update_date_mapping->{$chunk_key};
+ 	my $target_chunk_last_update_date = $target_file_key_to_last_update_date_mapping->{$chunk_key};
+	if (defined($target_chunk_last_update_date) && &is_date_after($source_chunk_last_update_date, $target_chunk_last_update_date)) {
+	    # &log_message("Chunk with key $chunk_key needs updating.");
+	    push(@target_file_keys_requiring_updating, $chunk_key);
+ 	}
+    }
+
+    return @target_file_keys_requiring_updating;
+}
+
+
+sub is_chunk_automatically_translated
+{
+    my ($chunk_key, $translation_file_type) = @_;
+    eval "return &is_${translation_file_type}_chunk_automatically_translated(\$chunk_key)";
+}
+
+
+sub make_text_xml_safe
+{
+    my $text = shift(@_);
+    $text =~ s/\&/\&amp\;/g;
+    $text =~ s/\&amp\;lt\;/\&amp\;amp\;lt\;/g;
+    $text =~ s/\&amp\;gt\;/\&amp\;amp\;gt\;/g;
+    $text =~ s/\&amp\;rarr\;/\&amp\;amp\;rarr\;/g;
+    $text =~ s/\&amp\;mdash\;/\&amp\;amp\;mdash\;/g;
+    $text =~ s/</\&lt\;/g;
+    $text =~ s/>/\&gt\;/g;
+    return $text;
+}
+
+
+sub unmake_text_xml_safe
+{
+    my $text = shift(@_);
+    $text =~ s/\&lt\;/</g;
+    $text =~ s/\&gt\;/>/g;
+    $text =~ s/\&amp\;/\&/g;
+    return $text;
+}
+
+
+# Returns 1 if $date1 is after $date2, 0 otherwise
+sub is_date_after
+{
+    my ($date1, $date2) = @_;
+    my %months = ("Jan", 1, "Feb", 2, "Mar", 3, "Apr",  4, "May",  5, "Jun",  6,
+		  "Jul", 7, "Aug", 8, "Sep", 9, "Oct", 10, "Nov", 11, "Dec", 12);
+
+    my @date1parts = split(/-/, $date1);
+    my @date2parts = split(/-/, $date2);
+
+    # Compare year - nasty because we have rolled over into a new century
+    my $year1 = $date1parts[2];
+    if ($year1 < 80) {
+	$year1 += 2000;
+    }
+    my $year2 = $date2parts[2];
+    if ($year2 < 80) {
+	$year2 += 2000;
+    }
+
+    # Compare year
+    if ($year1 > $year2) {
+	return 1;
+    }
+    elsif ($year1 == $year2) {
+	# Year is the same, so compare month
+	if ($months{$date1parts[1]} > $months{$date2parts[1]}) {
+	    return 1;
+	}
+	elsif ($months{$date1parts[1]} == $months{$date2parts[1]}) {
+	    # Month is the same, so compare day
+	    if ($date1parts[0] > $date2parts[0]) {
+		return 1;
+	    }
+	}
+    }
+
+    return 0;
+}
+
+
+# ==========================================================================================
+#   MACROFILE FUNCTIONS
+
+sub build_key_to_line_mapping_for_macrofile
+{
+    my (@file_lines) = @_;
+
+    my $macro_package;
+    my %chunk_key_to_line_mapping = ();
+    # Process the contents of the file, line by line
+    for (my $i = 0; $i < scalar(@file_lines); $i++) {
+	my $line = $file_lines[$i];
+	$line =~ s/(\s*)$//;  # Remove any nasty whitespace, carriage returns etc.
+
+	# Check if a new package is being defined
+	if ($line =~ m/^package\s+(.+)/) {
+	    $macro_package = $1;
+	}
+
+	# Line contains a macro name
+	elsif ($line =~ m/^(_\w+_)/) {
+	    my $macro_key = $1;
+	    $line =~ s/\s*([^\\]\#[^\}]+)?$//;  # Remove any comments and nasty whitespace
+
+	    # While there is still text of the macro to go...
+	    my $startline = $i;
+	    while ($line !~ /\}$/) {
+		$i++;
+		if ($i == scalar(@file_lines)) {
+		    &throw_fatal_error("Could not find end of macro $macro_key.");
+		}
+		$line = $file_lines[$i];
+		$line =~ s/\s*([^\\]\#[^\}]+)?$//;  # Remove any comments and nasty whitespace
+	    }
+
+	    # The chunk key consists of the package name and the macro key
+	    my $chunk_key = $macro_package . "." . $macro_key;
+	    # Map from chunk key to line
+	    $chunk_key_to_line_mapping{$chunk_key} = $startline . "-" . $i;
+	}
+
+	# Icon: line in format ## "image text" ## image_type ## macro_name ##
+	elsif ($line =~ m/^\#\# .* \#\# .* \#\# (.*) \#\#/) {
+	    # The chunk key consists of package name and macro key
+	    my $chunk_key = $macro_package . "." . $1;
+	    # Map from chunk key to line
+	    $chunk_key_to_line_mapping{$chunk_key} = $i . "-" . $i;
+	}
+    }
+
+    return %chunk_key_to_line_mapping;
+}
+
+
+sub import_chunk_from_macrofile
+{
+    my ($chunk_text) = @_;
+
+    # Is this an icon macro??
+    if ($chunk_text =~ /^\#\# (.*)/) {
+	# Extract image macro text
+	$chunk_text =~ /^\#\#\s+([^\#]+)\s+\#\#/;
+	$chunk_text = $1;
+
+	# Remove enclosing quotes
+	$chunk_text =~ s/^\"//;
+	$chunk_text =~ s/\"$//;
+    }
+
+    # No, so it must be a text macro
+    else {
+	# Remove macro key
+	$chunk_text =~ s/^_([^_]+)_(\s*)//;
+
+	# Remove language specifier
+	$chunk_text =~ s/^\[l=.*\](\s*)//;
+
+	# Remove braces enclosing text
+	$chunk_text =~ s/^{(\s*)((.|\n)*)}(\s*)(\#.+\s*)?/$2/;
+    }
+
+    return $chunk_text;
+}
+
+
+sub get_macrofile_chunk_gti_comment
+{
+    my ($chunk_text) = @_;
+
+    # Check for an "Updated DD-MMM-YYYY" comment at the end of the chunk
+    if ($chunk_text =~ /\#\s+(Updated\s+\d?\d-\D\D\D-\d\d\d\d.*)\s*$/i) {
+	return $1;
+    }
+
+    return undef;
+}
+
+
+sub is_macrofile_chunk_automatically_translated
+{
+    my ($chunk_key) = @_;
+
+    # The _httpiconX_, _widthX_ and _heightX_ image macros are automatically translated
+    if ($chunk_key =~ /\._(httpicon|width|height)/) {
+	return 1;
+    }
+
+    return 0;
+}
+
+
+# Use the source file to generate a target file that is formatted the same
+sub write_translated_macrofile
+{
+    my $source_file = shift(@_);  # Not used
+    my @source_file_lines = @{shift(@_)};
+    my $source_file_key_to_text_mapping = shift(@_);
+    my $target_file = shift(@_);
+    my @target_file_lines = @{shift(@_)};
+    my $target_file_key_to_text_mapping = shift(@_);
+    my $target_file_key_to_gti_comment_mapping = shift(@_);
+    my $target_language_code = shift(@_);
+
+    # Build a mapping from source file line to chunk key
+    my %source_file_key_to_line_mapping = &build_key_to_line_mapping_for_macrofile(@source_file_lines);
+    my %source_file_line_to_key_mapping = ();
+    foreach my $chunk_key (keys(%source_file_key_to_line_mapping)) {
+	$source_file_line_to_key_mapping{$source_file_key_to_line_mapping{$chunk_key}} = $chunk_key;
+    }
+    my @source_file_line_keys = (sort sort_by_line (keys(%source_file_line_to_key_mapping)));
+    my $source_file_line_number = 0;
+
+    # Build a mapping from target file line to chunk key
+    my %target_file_key_to_line_mapping = &build_key_to_line_mapping_for_macrofile(@target_file_lines);
+    my %target_file_line_to_key_mapping = ();
+    foreach my $chunk_key (keys(%target_file_key_to_line_mapping)) {
+	$target_file_line_to_key_mapping{$target_file_key_to_line_mapping{$chunk_key}} = $chunk_key;
+    }
+    my @target_file_line_keys = (sort sort_by_line (keys(%target_file_line_to_key_mapping)));
+
+    # Write the new target file
+    my $target_file_path = &util::filename_cat($gsdl_root_directory, $target_file);
+    if (!open(TARGET_FILE, ">$target_file_path")) {
+	&throw_fatal_error("Could not write target file $target_file_path.");
+    }
+
+    # Use the header from the target file, to keep language and author information
+    if (scalar(@target_file_line_keys) > 0) {
+	my $target_file_line_number = 0;
+ 	my $target_file_chunk_starting_line_number = (split(/-/, $target_file_line_keys[0]))[0];
+ 	while ($target_file_line_number < $target_file_chunk_starting_line_number) {
+	    my $target_file_line = $target_file_lines[$target_file_line_number];
+	    last if ($target_file_line =~ /^\# -- Missing translation: /);  # We don't want to get into the macros
+ 	    print TARGET_FILE $target_file_line;
+ 	    $target_file_line_number++;
+ 	}
+
+	$source_file_line_number = (split(/-/, $source_file_line_keys[0]))[0];
+    }
+
+    # Model the new target file on the source file, with the target file translations
+    foreach my $line_key (@source_file_line_keys) {
+ 	# Fill in the gaps before this chunk starts
+ 	my $source_file_chunk_starting_line_number = (split(/-/, $line_key))[0];
+ 	my $source_file_chunk_finishing_line_number = (split(/-/, $line_key))[1];
+ 	while ($source_file_line_number < $source_file_chunk_starting_line_number) {
+ 	    print TARGET_FILE $source_file_lines[$source_file_line_number];
+ 	    $source_file_line_number++;
+ 	}
+ 	$source_file_line_number = $source_file_chunk_finishing_line_number + 1;
+
+	my $chunk_key = $source_file_line_to_key_mapping{$line_key};
+	my $source_file_chunk_text = $source_file_key_to_text_mapping->{$chunk_key};
+	my $target_file_chunk_text = $target_file_key_to_text_mapping->{$chunk_key} || "";
+
+	my $macrofile_key = $chunk_key;
+	$macrofile_key =~ s/^(.+?)\.//;
+
+	# If no translation exists for this chunk, show this, and move on
+	if ($source_file_chunk_text ne "" && $target_file_chunk_text eq "") {
+	    print TARGET_FILE "# -- Missing translation: $macrofile_key\n";
+	    next;
+	}
+
+ 	# Grab the source chunk text
+ 	my $source_file_chunk = $source_file_lines[$source_file_chunk_starting_line_number];
+ 	for (my $l = ($source_file_chunk_starting_line_number + 1); $l <= $source_file_chunk_finishing_line_number; $l++) {
+ 	    $source_file_chunk .= $source_file_lines[$l];
+ 	}
+
+ 	# Is this an icon macro??
+ 	if ($source_file_chunk =~ /^\#\# (.*)/) {
+ 	    # Escape any newline and question mark characters so the source text is replaced correctly
+ 	    $source_file_chunk_text =~ s/\\/\\\\/g;
+	    $source_file_chunk_text =~ s/\?/\\\?/g;
+
+	    # Build the new target chunk from the source chunk
+	    my $target_file_chunk = $source_file_chunk;
+	    $target_file_chunk =~ s/$source_file_chunk_text/$target_file_chunk_text/;
+	    $target_file_chunk =~ s/(\s)*$//;
+	    print TARGET_FILE "$target_file_chunk";
+ 	}
+
+ 	# No, it is just a normal text macro
+ 	else {
+ 	    print TARGET_FILE "$macrofile_key [l=$target_language_code] {$target_file_chunk_text}";
+ 	}
+
+	# Add the "updated" comment, if one exists
+	if ($target_file_key_to_gti_comment_mapping->{$chunk_key}) {
+	    print TARGET_FILE "  # " . $target_file_key_to_gti_comment_mapping->{$chunk_key};
+	}
+	print TARGET_FILE "\n";
+    }
+
+    close(TARGET_FILE);
+}
+
+
+sub sort_by_line
+{
+    return ((split(/-/, $a))[0] <=> (split(/-/, $b))[0]);
+}
+
+
+# ==========================================================================================
+#   RESOURCE BUNDLE FUNCTIONS
+
+sub build_key_to_line_mapping_for_resource_bundle
+{
+    my (@file_lines) = @_;
+
+    my %chunk_key_to_line_mapping = ();
+    for (my $i = 0; $i < scalar(@file_lines); $i++) {
+	my $line = $file_lines[$i];
+	$line =~ s/(\s*)$//;  # Remove any nasty whitespace, carriage returns etc.
+
+	# Line contains a dictionary string
+	if ($line =~ /^(\S+?):(.*)$/) {
+	    my $chunk_key = $1;
+
+	    # Map from chunk key to line
+	    $chunk_key_to_line_mapping{$chunk_key} = $i . "-" . $i;
+	}
+    }
+
+    return %chunk_key_to_line_mapping;
+}
+
+
+sub import_chunk_from_resource_bundle
+{
+    my ($chunk_text) = @_;
+
+    # Simple: just remove string key
+    $chunk_text =~ s/^(\S+?):(\s*)//;
+    $chunk_text =~ s/(\s*)$//;  # Remove any nasty whitespace, carriage returns etc.
+    $chunk_text =~ s/(\s*)\#\s+Updated\s+(\d?\d-\D\D\D-\d\d\d\d.*)\s*$//i;
+
+    return $chunk_text;
+}
+
+
+sub get_resource_bundle_chunk_gti_comment
+{
+    my ($chunk_text) = @_;
+
+    # Check for an "Updated DD-MMM-YYYY" comment at the end of the chunk
+    if ($chunk_text =~ /\#\s+(Updated\s+\d?\d-\D\D\D-\d\d\d\d.*)\s*$/i) {
+	return $1;
+    }
+
+    return undef;
+}
+
+
+sub is_resource_bundle_chunk_automatically_translated
+{
+    # No resource bundle chunks are automatically translated
+    return 0;
+}
+
+
+sub write_translated_resource_bundle
+{
+    my $source_file = shift(@_);  # Not used
+    my @source_file_lines = @{shift(@_)};
+    my $source_file_key_to_text_mapping = shift(@_);
+    my $target_file = shift(@_);
+    my @target_file_lines = @{shift(@_)};  # Not used
+    my $target_file_key_to_text_mapping = shift(@_);
+    my $target_file_key_to_gti_comment_mapping = shift(@_);
+    my $target_language_code = shift(@_);  # Not used
+
+    # Build a mapping from chunk key to source file line, and from source file line to chunk key
+    my %source_file_key_to_line_mapping = &build_key_to_line_mapping_for_resource_bundle(@source_file_lines);
+    my %source_file_line_to_key_mapping = ();
+    foreach my $chunk_key (keys(%source_file_key_to_line_mapping)) {
+	$source_file_line_to_key_mapping{$source_file_key_to_line_mapping{$chunk_key}} = $chunk_key;
+    }
+
+    # Write the new target file
+    my $target_file_path = &util::filename_cat($gsdl_root_directory, $target_file);
+    if (!open(TARGET_FILE, ">$target_file_path")) {
+	&throw_fatal_error("Could not write target file $target_file_path.");
+    }
+
+    # Model the new target file on the source file, with the target file translations
+    my $source_file_line_number = 0;
+    foreach my $line_key (sort sort_by_line (keys(%source_file_line_to_key_mapping))) {
+ 	# Fill in the gaps before this chunk starts
+ 	my $source_file_chunk_starting_line_number = (split(/-/, $line_key))[0];
+ 	my $source_file_chunk_finishing_line_number = (split(/-/, $line_key))[1];
+ 	while ($source_file_line_number < $source_file_chunk_starting_line_number) {
+ 	    print TARGET_FILE $source_file_lines[$source_file_line_number];
+ 	    $source_file_line_number++;
+ 	}
+ 	$source_file_line_number = $source_file_chunk_finishing_line_number + 1;
+
+	my $chunk_key = $source_file_line_to_key_mapping{$line_key};
+	my $source_file_chunk_text = $source_file_key_to_text_mapping->{$chunk_key};
+	my $target_file_chunk_text = $target_file_key_to_text_mapping->{$chunk_key} || "";
+
+	# If no translation exists for this chunk, show this, and move on
+	if ($source_file_chunk_text ne "" && $target_file_chunk_text eq "") {
+	    print TARGET_FILE "# -- Missing translation: $chunk_key\n";
+	    next;
+	}
+
+	print TARGET_FILE "$chunk_key:$target_file_chunk_text";
+	if ($target_file_key_to_gti_comment_mapping->{$chunk_key}) {
+	    print TARGET_FILE "  # " . $target_file_key_to_gti_comment_mapping->{$chunk_key};
+	}
+	print TARGET_FILE "\n";
+    }
+
+    close(TARGET_FILE);
+}
+
+
+# ==========================================================================================
+#   GREENSTONE XML FUNCTIONS
+
+sub build_key_to_line_mapping_for_greenstone_xml
+{
+    my (@file_lines) = @_;
+
+    my %chunk_key_to_line_mapping = ();
+    for (my $i = 0; $i < scalar(@file_lines); $i++) {
+	my $line = $file_lines[$i];
+	$line =~ s/(\s*)$//;  # Remove any nasty whitespace, carriage returns etc.
+
+	# Line contains a string to translate
+	if ($line =~ /^\s*<Text id=\"(.*?)\">/) {
+	    my $chunk_key = $1;
+	    $line =~ s/\s*$//;  # Remove any nasty whitespace
+	    $line =~ s/<Updated date=\"\d?\d-\D\D\D-\d\d\d\d.*\"\/>$//;
+
+	    # While there is still text of the string to go...
+	    my $startline = $i;
+	    while ($line !~ /<\/Text>$/) {
+		$i++;
+		if ($i == scalar(@file_lines)) {
+		    &throw_fatal_error("Could not find end of string $chunk_key.");
+		}
+		$line = $file_lines[$i];
+		$line =~ s/\s*$//;  # Remove any nasty whitespace
+		$line =~ s/<Updated date=\"\d?\d-\D\D\D-\d\d\d\d.*\"\/>$//;
+	    }
+
+	    # Map from chunk key to line
+	    if (!defined($chunk_key_to_line_mapping{$chunk_key})) {
+		$chunk_key_to_line_mapping{$chunk_key} = $startline . "-" . $i;
+	    }
+	    else {
+		&throw_fatal_error("Duplicate key $chunk_key.");
+	    }
+	}
+    }
+
+    return %chunk_key_to_line_mapping;
+}
+
+
+sub import_chunk_from_greenstone_xml
+{
+    my ($chunk_text) = @_;
+
+    # Simple: just remove the Text tags
+    $chunk_text =~ s/^\s*<Text id=\"(.*?)\">(\s*)//;
+    $chunk_text =~ s/<Updated date=\"\d?\d-\D\D\D-\d\d\d\d.*\"\/>$//;
+    $chunk_text =~ s/<\/Text>$//;
+
+    return $chunk_text;
+}
+
+
+sub get_greenstone_xml_chunk_gti_comment
+{
+    my ($chunk_text) = @_;
+
+    # Check for an "Updated DD-MMM-YYYY" comment at the end of the chunk
+    if ($chunk_text =~ /<Updated date=\"(\d?\d-\D\D\D-\d\d\d\d.*)\"\/>$/i) {
+	return $1;
+    }
+
+    return undef;
+}
+
+
+sub is_greenstone_xml_chunk_automatically_translated
+{
+    # No greenstone XML chunks are automatically translated
+    return 0;
+}
+
+
+sub write_translated_greenstone_xml
+{
+    my $source_file = shift(@_);  # Not used
+    my @source_file_lines = @{shift(@_)};
+    my $source_file_key_to_text_mapping = shift(@_);
+    my $target_file = shift(@_);
+    my @target_file_lines = @{shift(@_)};  # Not used
+    my $target_file_key_to_text_mapping = shift(@_);
+    my $target_file_key_to_gti_comment_mapping = shift(@_);
+    my $target_language_code = shift(@_);  # Not used
+
+    # Build a mapping from chunk key to source file line, and from source file line to chunk key
+    my %source_file_key_to_line_mapping = &build_key_to_line_mapping_for_greenstone_xml(@source_file_lines);
+    my %source_file_line_to_key_mapping = ();
+    foreach my $chunk_key (keys(%source_file_key_to_line_mapping)) {
+	$source_file_line_to_key_mapping{$source_file_key_to_line_mapping{$chunk_key}} = $chunk_key;
+    }
+
+    # Write the new target file
+    my $target_file_path = &util::filename_cat($gsdl_root_directory, $target_file);
+    if (!open(TARGET_FILE, ">$target_file_path")) {
+	&throw_fatal_error("Could not write target file $target_file_path.");
+    }
+
+    # Model the new target file on the source file, with the target file translations
+    my $source_file_line_number = 0;
+    foreach my $line_key (sort sort_by_line (keys(%source_file_line_to_key_mapping))) {
+ 	# Fill in the gaps before this chunk starts
+ 	my $source_file_chunk_starting_line_number = (split(/-/, $line_key))[0];
+ 	my $source_file_chunk_finishing_line_number = (split(/-/, $line_key))[1];
+ 	while ($source_file_line_number < $source_file_chunk_starting_line_number) {
+ 	    print TARGET_FILE $source_file_lines[$source_file_line_number];
+ 	    $source_file_line_number++;
+ 	}
+ 	$source_file_line_number = $source_file_chunk_finishing_line_number + 1;
+
+	my $chunk_key = $source_file_line_to_key_mapping{$line_key};
+	my $source_file_chunk_text = $source_file_key_to_text_mapping->{$chunk_key};
+	my $target_file_chunk_text = $target_file_key_to_text_mapping->{$chunk_key} || "";
+	$target_file_chunk_text =~ s/(\n)*$//g;
+
+	# If no translation exists for this chunk, show this, and move on
+	if ($source_file_chunk_text ne "" && $target_file_chunk_text eq "") {
+	    print TARGET_FILE "<!-- Missing translation: $chunk_key -->\n";
+	    next;
+	}
+
+	print TARGET_FILE "<Text id=\"$chunk_key\">$target_file_chunk_text</Text>";
+	if ($target_file_key_to_gti_comment_mapping->{$chunk_key}) {
+	    my $chunk_gti_comment = $target_file_key_to_gti_comment_mapping->{$chunk_key};
+	    $chunk_gti_comment =~ s/^Updated //;
+	    print TARGET_FILE "<Updated date=\"" . $chunk_gti_comment . "\"\/>";
+	}
+	print TARGET_FILE "\n";
+    }
+
+    # Fill in the end of the file
+    while ($source_file_line_number < scalar(@source_file_lines)) {
+	print TARGET_FILE $source_file_lines[$source_file_line_number];
+	$source_file_line_number++;
+    }
+
+    close(TARGET_FILE);
+}
+
+
+&main(@ARGV);
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/import.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/import.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/import.pl	(revision 13928)
@@ -0,0 +1,567 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# import.pl --
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+# This program will import a number of files into a particular collection
+
+package import;
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/cpan");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/plugins");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/plugouts");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/classify");
+}
+
+use arcinfo;
+use colcfg;
+use plugin;
+use plugout;
+use manifest;
+use util;
+use scriptutil;
+use FileHandle;
+use gsprintf 'gsprintf';
+use printusage;
+use parse2;
+
+
+
+use strict;
+no strict 'refs'; # allow filehandles to be variables and vice versa
+no strict 'subs'; # allow barewords (eg STDERR) as function arguments
+
+my $oidtype_list = 
+    [ { 'name' => "hash",
+        'desc' => "{import.OIDtype.hash}" },
+      { 'name' => "assigned",
+        'desc' => "{import.OIDtype.assigned}" },
+      { 'name' => "incremental",
+        'desc' => "{import.OIDtype.incremental}" },
+      { 'name' => "dirname",
+        'desc' => "{import.OIDtype.dirname}" } ];
+
+#** define to use the original GA format or METS format
+my $saveas_list = 
+    [ { 'name' => "GA",
+        'desc' => "{import.saveas.GA}" },
+      { 'name' => "METS",
+        'desc' => "{import.saveas.METS}" } ];
+
+
+# Possible attributes for each argument
+# name: The name of the argument
+# desc: A description (or more likely a reference to a description) for this argument
+# type: The type of control used to represent the argument. Options include: string, int, flag, regexp, metadata, language, enum etc
+# reqd: Is this argument required?
+# hiddengli: Is this argument hidden in GLI?
+# modegli: The lowest detail mode this argument is visible at in GLI
+
+my $arguments = 
+    [ { 'name' => "archivedir",
+	'desc' => "{import.archivedir}",
+	'type' => "string",
+	'reqd' => "no",
+        'hiddengli' => "yes" },
+      { 'name' => "collectdir",
+	'desc' => "{import.collectdir}",
+	'type' => "string",
+	# parsearg left "" as default
+	#'deft' => &util::filename_cat ($ENV{'GSDLHOME'}, "collect"),
+	'deft' => "",
+	'reqd' => "no",
+        'hiddengli' => "yes" },
+      { 'name' => "manifest",
+	'desc' => "{import.manifest}",
+	'type' => "string",
+	'deft' => "",
+	'reqd' => "no",
+        'hiddengli' => "yes" },
+      { 'name' => "debug",
+	'desc' => "{import.debug}",
+	'type' => "flag",
+	'reqd' => "no",
+        'hiddengli' => "yes" },
+      { 'name' => "faillog",
+	'desc' => "{import.faillog}",
+	'type' => "string",
+	# parsearg left "" as default
+	#'deft' => &util::filename_cat("&lt;collectdir&gt;", "colname", "etc", "fail.log"),
+	'deft' => "",
+	'reqd' => "no",
+        'modegli' => "4" },
+      { 'name' => "importdir",
+	'desc' => "{import.importdir}",
+	'type' => "string",
+	'reqd' => "no",
+        'hiddengli' => "yes" },
+      { 'name' => "incremental",
+	'desc' => "{import.incremental}",
+	'type' => "flag",
+	'hiddengli' => "yes" },
+      { 'name' => "keepold",
+	'desc' => "{import.keepold}",
+	'type' => "flag",
+	'reqd' => "no",
+	'hiddengli' => "yes" },
+      { 'name' => "removeold",
+	'desc' => "{import.removeold}",
+	'type' => "flag",
+	'reqd' => "no",
+	'hiddengli' => "yes" },
+      { 'name' => "language",
+	'desc' => "{scripts.language}",
+	'type' => "string",
+	'reqd' => "no",
+	'hiddengli' => "yes" },
+      { 'name' => "maxdocs",
+	'desc' => "{import.maxdocs}",
+	'type' => "int",
+	'reqd' => "no",
+	# parsearg left "" as default
+	#'deft' => "-1",
+	'range' => "1,",
+	'modegli' => "1" },
+      { 'name' => "OIDtype",
+	'desc' => "{import.OIDtype}",
+	'type' => "enum",
+	'list' => $oidtype_list,
+	# parsearg left "" as default
+	#'deft' => "hash",
+	'reqd' => "no",
+	'modegli' => "2" },
+      { 'name' => "OIDmetadata",
+	'desc' => "{import.OIDmetadata}",
+	'type' => "metadata",
+	'deft' => "dc.Identifier",
+	'reqd' => "no",
+	'modegli' => "2" },
+      { 'name' => "out",
+	'desc' => "{import.out}",
+	'type' => "string",
+	'deft' => "STDERR",
+	'reqd' => "no",
+        'hiddengli' => "yes" },
+      { 'name' => "saveas",
+	'desc' => "{import.saveas}",
+	'type' => "enum",
+	'list' => $saveas_list,
+	'deft' => "GA",
+	'reqd' => "no",
+	'modegli' => "3" },      
+      { 'name' => "sortmeta",
+	'desc' => "{import.sortmeta}",
+	'type' => "metadata",
+#	'type' => "string",
+	'reqd' => "no",
+	'modegli' => "3" },
+      { 'name' => "removeprefix",
+	'desc' => "{BasClas.removeprefix}",
+	'type' => "regexp",
+	'deft' => "",
+	'reqd' => "no", 
+	'modegli' => "3" },
+      { 'name' => "removesuffix",
+	'desc' => "{BasClas.removesuffix}",
+	'type' => "regexp",
+	'deft' => "",
+	'reqd' => "no",
+	'modegli' => "3" }, 
+      { 'name' => "groupsize",
+	'desc' => "{import.groupsize}",
+	'type' => "int",
+	'deft' => "1",
+	'reqd' => "no",
+	'modegli' => "3" },
+      { 'name' => "gzip",
+	'desc' => "{import.gzip}",
+	'type' => "flag",
+	'reqd' => "no",
+	'modegli' => "4" },
+      { 'name' => "statsfile",
+	'desc' => "{import.statsfile}",
+	'type' => "string",
+	'deft' => "STDERR",
+	'reqd' => "no",
+        'hiddengli' => "yes" },
+      { 'name' => "verbosity",
+	'desc' => "{import.verbosity}",
+	'type' => "int",
+	'range' => "0,",
+	# parsearg left "" as default
+	#'deft' => "2",
+	'reqd' => "no",
+	'modegli' => "4" },
+      { 'name' => "gli",
+	'desc' => "",
+	'type' => "flag",
+	'reqd' => "no",
+	'hiddengli' => "yes" },
+      { 'name' => "xml",
+	'desc' => "{scripts.xml}",
+	'type' => "flag",
+	'reqd' => "no",
+	'hiddengli' => "yes" }];
+
+my $options = { 'name' => "import.pl",
+		'desc' => "{import.desc}",
+		'args' => $arguments };
+
+
+&main();
+
+sub main {
+    my ($verbosity, $importdir, $archivedir, $manifest, $incremental, $keepold, 
+	$removeold, $saveas, $version,
+	$gzip, $groupsize, $OIDtype, $OIDmetadata, $debug, 
+	$maxdocs, $collection, $configfilename, $collectcfg, 
+	$pluginfo, $sortmeta, $removeprefix, $removesuffix, 
+	$archive_info_filename, $statsfile,
+	$archive_info, $processor, $out, $faillog, $collectdir, $gli, $language);
+
+    my $xml = 0;
+
+    my $service = "import";
+
+    my $hashParsingResult = {};
+    # general options available to all plugins
+    my $intArgLeftinAfterParsing = parse2::parse(\@ARGV,$arguments,$hashParsingResult,"allow_extra_options");
+    # Parse returns -1 if something has gone wrong
+    if($intArgLeftinAfterParsing == -1)
+    {
+	&PrintUsage::print_txt_usage($options, "{import.params}");
+	die "\n";
+    }
+    
+    foreach my $strVariable (keys %$hashParsingResult)
+    {
+	eval "\$$strVariable = \$hashParsingResult->{\"\$strVariable\"}";
+    }
+
+    # If $language has been specified, load the appropriate resource bundle
+    # (Otherwise, the default resource bundle will be loaded automatically)
+    if ($language && $language =~ /\S/) {
+	&gsprintf::load_language_specific_resource_bundle($language);
+    }
+
+    if ($xml) {
+        &PrintUsage::print_xml_usage($options);
+	print "\n";
+	return;
+    }
+
+    if ($gli) { # the gli wants strings to be in UTF-8
+	&gsprintf::output_strings_in_UTF8; 
+    }
+    
+    # now check that we had exactly one leftover arg, which should be 
+    # the collection name. We don't want to do this earlier, cos 
+    # -xml arg doesn't need a collection name
+    # Or if the user specified -h, then we output the usage also
+    if ($intArgLeftinAfterParsing != 1 || (@ARGV && $ARGV[0] =~ /^\-+h/))
+    {
+	&PrintUsage::print_txt_usage($options, "{buildcol.params}");
+	die "\n";
+    }
+
+    my $close_out = 0;
+    if ($out !~ /^(STDERR|STDOUT)$/i) {
+	open (OUT, ">$out") ||
+	    (&gsprintf(STDERR, "{common.cannot_open_output_file}: $!\n", $out) && die);
+	$out = 'import::OUT';
+	$close_out = 1;
+    }
+    $out->autoflush(1);
+
+    # get and check the collection name
+    if (($collection = &util::use_collection(@ARGV, $collectdir)) eq "") {
+	&PrintUsage::print_txt_usage($options, "{import.params}");
+	die "\n";
+    }
+
+    # add collection's perllib dir  into include path in 
+    # case we have collection specific modules
+    unshift (@INC, "$ENV{'GSDLCOLLECTDIR'}/perllib");
+
+    # check that we can open the faillog
+    if ($faillog eq "") {
+	$faillog = &util::filename_cat($ENV{'GSDLCOLLECTDIR'}, "etc", "fail.log");
+    }
+    open (FAILLOG, ">$faillog") ||
+	(&gsprintf(STDERR, "{import.cannot_open_fail_log}\n", $faillog) && die);
+
+    
+    my $faillogname = $faillog;
+    $faillog = 'import::FAILLOG';
+    $faillog->autoflush(1);
+    
+    # check that there is a collect.cfg file
+    $configfilename = &util::filename_cat ($ENV{'GSDLCOLLECTDIR'}, "etc", "collect.cfg");
+    if (!-e $configfilename) {
+	(&gsprintf($out, "{common.cannot_find_cfg_file}\n", $configfilename) && die);
+    }
+    $collectcfg = &colcfg::read_collect_cfg ($configfilename);
+
+    
+    if (defined $collectcfg->{'importdir'} && $importdir eq "") {
+	$importdir = $collectcfg->{'importdir'};
+    }
+    if (defined $collectcfg->{'archivedir'} && $archivedir eq "") {
+	$archivedir = $collectcfg->{'archivedir'};
+    }
+    # fill in the default import and archives directories if none
+    # were supplied, turn all \ into / and remove trailing /
+    $importdir = &util::filename_cat ($ENV{'GSDLCOLLECTDIR'}, "import") if $importdir eq "";
+    $importdir =~ s/[\\\/]+/\//g;
+    $importdir =~ s/\/$//;
+    if (!-e $importdir) {
+	&gsprintf($out, "{import.no_import_dir}\n\n", $importdir);
+	die "\n";
+    }
+
+    $archivedir = &util::filename_cat ($ENV{'GSDLCOLLECTDIR'}, "archives") if $archivedir eq "";
+    $archivedir =~ s/[\\\/]+/\//g;
+    $archivedir =~ s/\/$//;
+
+    my $plugins = [];
+    if (defined $collectcfg->{'plugin'}) {
+	$plugins = $collectcfg->{'plugin'};
+    }
+    #some global options for the plugins
+    my @global_opts = ();
+
+    if ($verbosity !~ /\d+/) {
+	if (defined $collectcfg->{'verbosity'} && $collectcfg->{'verbosity'} =~ /\d+/) {
+	    $verbosity = $collectcfg->{'verbosity'};
+	} else {
+	    $verbosity = 2; # the default
+	}
+    }
+    if (defined $collectcfg->{'manifest'} && $manifest eq "") {
+	$manifest = $collectcfg->{'manifest'};
+    }
+
+    if (defined $collectcfg->{'gzip'} && !$gzip) {
+	if ($collectcfg->{'gzip'} =~ /^true$/i) {
+	    $gzip = 1;
+	}
+    }
+
+    if ($maxdocs !~ /\-?\d+/) {
+	if (defined $collectcfg->{'maxdocs'} && $collectcfg->{'maxdocs'} =~ /\-?\d+/) {
+	    $maxdocs = $collectcfg->{'maxdocs'};
+	} else {
+	    $maxdocs = -1; # the default
+	}
+    }
+    if ($groupsize == 1) {
+	if (defined $collectcfg->{'groupsize'} && $collectcfg->{'groupsize'} =~ /\d+/) {
+	    $groupsize = $collectcfg->{'groupsize'};
+	}
+    }
+
+    if ($OIDtype !~ /^(hash|incremental|assigned|dirname)$/) {
+	if (defined $collectcfg->{'OIDtype'} && $collectcfg->{'OIDtype'} =~ /^(hash|incremental|assigned|dirname)$/) {
+	    $OIDtype = $collectcfg->{'OIDtype'};
+	} else {
+	    $OIDtype = "hash"; # the default
+	}
+    }
+     
+    if ($saveas !~ /^(GA|METS)$/) {
+	if (defined $collectcfg->{'plugout'} && $collectcfg->{'plugout'}[0] =~ /^(GAPlugout|METSPlugout)$/) {
+	    $saveas = $collectcfg->{'plugout'}[0];
+	} else {
+	    $saveas ="GAPlugout";
+	}
+    }
+
+    if (defined $collectcfg->{'sortmeta'} && (!defined $sortmeta || $sortmeta eq "")) {
+	$sortmeta = $collectcfg->{'sortmeta'};
+    }
+    # sortmeta cannot be used with group size
+    $sortmeta = undef unless defined $sortmeta && $sortmeta =~ /\S/;
+    if (defined $sortmeta && $groupsize > 1) {
+	&gsprintf($out, "{import.cannot_sort}\n\n");
+	$sortmeta = undef;
+    }
+
+    if (defined $collectcfg->{'removeprefix'} && $removeprefix eq "") {
+	$removeprefix = $collectcfg->{'removeprefix'};
+    }
+    
+    if (defined $collectcfg->{'removesuffix'} && $removesuffix eq "") {
+	$removesuffix = $collectcfg->{'removesuffix'};
+    }
+    if (defined $collectcfg->{'debug'} && $collectcfg->{'debug'} =~ /^true$/i) {
+	$debug = 1;
+    }
+    if (defined $collectcfg->{'gli'} && $collectcfg->{'gli'} =~ /^true$/i) {
+	$gli = 1;
+    }
+    
+    
+    # global plugin stuff
+    if (defined $collectcfg->{'separate_cjk'} && $collectcfg->{'separate_cjk'} =~ /^true$/i) {
+	push @global_opts, "-separate_cjk";
+    }
+    
+    # check keepold and removeold
+    ($removeold, $keepold, $incremental) = &scriptutil::check_removeold_and_keepold($removeold, $keepold, $incremental, "archives", $collectcfg);
+ 
+    $gli = 0 unless defined $gli;
+
+    print STDERR "<Import>\n" if $gli;
+    
+    my $manifest_lookup = new manifest();
+    if ($manifest ne "") {	
+	my $manifest_filename = $manifest;
+
+	if ($manifest_filename !~ m/^[\\\/]/) {
+	    $manifest_filename = &util::filename_cat ($ENV{'GSDLCOLLECTDIR'}, $manifest_filename);
+	}
+
+	$manifest =~ s/[\\\/]+/\//g;
+	$manifest =~ s/\/$//;
+
+	$manifest_lookup->parse($manifest_filename);
+    }
+
+
+    # load all the plugins
+    $pluginfo = &plugin::load_plugins ($plugins, $verbosity, $out, $faillog, \@global_opts, $incremental);
+    if (scalar(@$pluginfo) == 0) {
+	&gsprintf($out, "{import.no_plugins_loaded}\n");
+	die "\n";
+    }
+
+    # remove the old contents of the archives directory (and tmp directory) if needed
+    if ($removeold) {
+	if (-e $archivedir) {
+	    &gsprintf($out, "{import.removing_archives}\n");
+	    &util::rm_r ($archivedir);
+	}
+	my $tmpdir = &util::filename_cat ($ENV{'GSDLCOLLECTDIR'}, "tmp");
+	$tmpdir =~ s/[\\\/]+/\//g;
+	$tmpdir =~ s/\/$//;
+	if (-e $tmpdir) {
+	    &gsprintf($out, "{import.removing_tmpdir}\n");
+	    &util::rm_r ($tmpdir);
+	}
+    }
+    # create the archives dir if needed
+    &util::mk_all_dir($archivedir);
+
+    # read the archive information file
+    $archive_info_filename = &util::filename_cat ($archivedir, "archives.inf");
+    $archive_info = new arcinfo ();
+    $archive_info->load_info ($archive_info_filename);
+    
+
+    ####Use Plugout####
+    my ($plugout_name); 
+    if ($saveas !~ /^(GA|METS)Plugout$/  ){      
+	$plugout_name = $saveas."Plugout";
+    }
+    else {
+	$plugout_name = $saveas;
+    } 
+    
+    my $opts=[];
+    push @$opts,("-output_info",$archive_info) if (defined $archive_info); 
+    
+    push @$opts,("-verbosity",$verbosity) if (defined $verbosity);
+    push @$opts,("-gzip_output") if ($gzip);
+    push @$opts,("-group_size",$groupsize) if (defined $groupsize);
+    push @$opts,("-output_handle",$out) if (defined $out);
+    
+    push @$opts,("-debug") if ($debug);
+    
+    $processor = &plugout::load_plugout($plugout_name,$opts);                        
+    $processor->setoutputdir ($archivedir);
+    $processor->set_sortmeta ($sortmeta, $removeprefix, $removesuffix) if defined $sortmeta;
+    $processor->set_OIDtype ($OIDtype, $OIDmetadata);
+    
+    &plugin::begin($pluginfo, $importdir, $processor, $maxdocs, $gli);
+
+    if ($manifest eq "") {
+	# process the import directory
+	&plugin::read ($pluginfo, $importdir, "", {}, $processor, $maxdocs, 0, $gli);
+    }
+    else {
+
+	# process any new files
+	foreach my $file (keys %{$manifest_lookup->{'index'}}) {
+	    &plugin::read ($pluginfo, $importdir, $file, {}, $processor, $maxdocs, 0, $gli);
+	}
+
+	# record files marked for deletion in arcinfo
+	foreach my $file (keys %{$manifest_lookup->{'delete'}}) {
+	    # consider finding it?
+	    # $archive_info->add_info($OID,$doc_xml_file,"D");
+	}
+    }
+
+    &plugin::end($pluginfo, $processor);
+
+    &plugin::deinit($pluginfo, $processor);
+
+    # write out the archive information file
+    $processor->close_file_output() if $groupsize > 1;
+    $processor->close_group_output() if $processor->is_group();
+    # should we still do this in debug mode??
+    $archive_info->save_info($archive_info_filename);
+    
+    # write out import stats
+    my $close_stats = 0;
+    if ($statsfile !~ /^(STDERR|STDOUT)$/i) {
+	if (open (STATS, ">$statsfile")) {
+	    $statsfile = 'import::STATS';
+	    $close_stats = 1;
+	} else {
+	    &gsprintf($out, "{import.cannot_open_stats_file}", $statsfile);
+	    &gsprintf($out, "{import.stats_backup}\n");
+	    $statsfile = 'STDERR';
+	}
+    }
+
+    &gsprintf($out, "\n");
+    &gsprintf($out, "*********************************************\n");
+    &gsprintf($out, "{import.complete}\n");
+    &gsprintf($out, "*********************************************\n");
+
+    &plugin::write_stats($pluginfo, $statsfile, $faillogname, $gli);
+    if ($close_stats) {
+	close STATS;
+    }
+
+    close OUT if $close_out;
+    close FAILLOG;
+}
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/importfrom.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/importfrom.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/importfrom.pl	(revision 13928)
@@ -0,0 +1,453 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# importfrom.pl --
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+# This program will contact the named DL server
+#  and export its metadata and (optionally) it documents.
+
+# Currently only designed for OAI exporting
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use colcfg;
+use util;
+use parsargv;
+use FileHandle;
+
+my $wgetopt = "";
+
+my $num_processed = 0;
+
+sub print_usage {
+    print STDERR "\n  usage: $0 [options] collection-name\n\n";
+    print STDERR "  options:\n";
+    print STDERR "   -verbosity number      0=none, 3=lots\n";
+    print STDERR "   -getdoc                Also download if source document if present\n";
+    print STDERR "   -importdir directory   Where the original material lives\n";
+    print STDERR "   -keepold               Will not destroy the current contents of the\n";
+    print STDERR "                          import directory (the default)\n";
+    print STDERR "   -removeold             Will remove the old contents of the import\n";
+    print STDERR "                          directory -- use with care\n";
+    print STDERR "   -gzip                  Use gzip to compress exported documents\n";
+    print STDERR "                          (don't forget to include ZIPPlug in your plugin\n";
+    print STDERR "   -maxdocs number        Maximum number of documents to import\n";
+    print STDERR "   -debug                 Print imported text to STDOUT\n";
+    print STDERR "   -collectdir directory  Collection directory (defaults to " .
+	&util::filename_cat ($ENV{'GSDLHOME'}, "collect") . ")\n";
+    print STDERR "   -out                   Filename or handle to print output status to.\n";
+    print STDERR "                          The default is STDERR\n\n";
+}
+
+
+
+sub xml_pretty_print
+{
+    my ($text,$out,$verbosity) = @_;
+
+    if (system("xmllint --version >/dev/null 2>&1")!=0) {
+	if ($verbosity>1) {
+	    print STDERR "Warning: Unable to find xmllint for pretty printing.\n";
+	    print STDERR "         XML will be shown verbatim.\n\n";
+	}
+	print $out $text;
+    }
+    else {
+
+	if (!open (PPOUT,"|xmllint --format -")) {
+	    print STDERR "Error running xmllint: $!\n\n";
+	    print $out $text;
+	    return;
+	}
+
+	print PPOUT $text;
+	close(PPOUT);
+    }
+}
+
+sub wget_oai_url 
+{
+    my ($wget_cmd,$out,$verbosity) = @_;
+
+    if ($verbosity>2) {
+	print $out "  $wget_cmd\n";
+    }
+
+    open (OAIIN,"$wget_cmd |")
+	|| die "wget request failed: $!\n";
+ 
+    my $li_record = "";
+
+    my $line;
+    while (defined($line=<OAIIN>))
+    {
+	$li_record .= $line;
+	# print $out $line;
+    }
+
+    close(OAIIN);
+
+    return $li_record;
+}
+
+sub oai_info
+{
+    my ($base_url,$out,$verbosity) = @_;
+
+    my $base_wget_cmd = "wget $wgetopt -q -O - \"$base_url?_OPTS_\"";
+ 
+    my $identify = "verb=Identify";
+    my $list_sets = "verb=ListSets";
+    my $list_md_formats = "ListMetadataFormats"; # not currently used
+
+    my $identify_cmd = $base_wget_cmd;
+    $identify_cmd =~ s/_OPTS_/$identify/;
+    print $out "-------------------\n";
+    print $out "General Information\n";
+    print $out "-------------------\n";
+    my $identify_text = wget_oai_url($identify_cmd,$out,$verbosity);
+    xml_pretty_print($identify_text,$out,$verbosity);
+
+    
+    my $list_sets_cmd = $base_wget_cmd;
+    $list_sets_cmd =~ s/_OPTS_/$list_sets/;
+    print $out "-------------------\n";
+    print $out "Set Information\n";
+    print $out "-------------------\n";
+    my $list_sets_text = wget_oai_url($list_sets_cmd,$out,$verbosity);
+    xml_pretty_print($list_sets_text,$out,$verbosity);
+}
+
+
+sub get_oai_ids
+{
+    my ($base_url, $set, $format, $out, $verbosity) = @_;
+
+    print $out "Requesting list of identifiers ...\n";
+    
+    my $base_wget_cmd = "wget $wgetopt -q -O - \"$base_url?_OPTS_\"";
+    my $identifiers_cmd = $base_wget_cmd;
+
+    my $identifiers_opts = "verb=ListIdentifiers&metadataPrefix=$format";
+
+    if (defined $set && ($set ne "")) {
+	$identifiers_opts .= "&set=$set";
+    }
+
+    $identifiers_cmd =~ s/_OPTS_/$identifiers_opts/;
+
+    my $li_record = wget_oai_url($identifiers_cmd,$out,$verbosity);
+
+    print $out "... Done.\n";
+
+    return $li_record;
+}
+
+sub parse_oai_ids
+{
+    my ($li_record, $out, $verbosity) = @_;
+
+    # extract identifier list
+    $li_record =~ s/^.*?<identifier>/<identifier>/s;
+    $li_record =~ s/^(.*<\/identifier>).*$/$1/s;
+
+    my @ids = ();
+
+    while ($li_record =~ m/<identifier>(.*?)<\/identifier>(.*)$/s)
+    {
+	$li_record = $2;
+	push(@ids,$1);
+    }
+
+    return \@ids;
+}
+
+
+sub dir_file_split
+{
+    my ($file) = @_;
+
+    my @dirs = split("/",$file);
+    my $local_file = pop(@dirs);
+    my $sub_dirs = join("/",@dirs);
+
+    return ($sub_dirs,$local_file);
+}
+
+sub get_oai_document
+{
+    my ($doc_url,$output_dir, $out) = @_;
+
+    my ($id_dir,$id_fname) = dir_file_split($doc_url);
+
+    print $out "Getting document $doc_url\n";
+
+    &util::mk_dir($output_dir)  if (!-e "$output_dir");
+
+    my $full_id_fname = &util::filename_cat($output_dir,$id_fname);
+
+    my $wget_cmd = "wget $wgetopt --quiet -O $full_id_fname \"$doc_url\"";
+
+    if (system($wget_cmd)!=0) {
+	print STDERR "Error: failed to execute $wget_cmd\n";
+	return 0;
+    }
+
+    return 1;    
+}
+
+sub get_oai_records
+{
+    my ($base_url,$format, $ids,$output_dir, $get_id, $maxdocs, $out) = @_;
+
+    my $doc_count = 0;
+
+    my $i;
+    foreach $i ( @$ids )
+    {
+	# wget it;
+	my $url = "$base_url?verb=GetRecord&metadataPrefix=$format";
+	$url .= "&identifier=$i";
+	print $out "Downloading metadata record for $i\n";
+
+        my $i_url = $i; #convert OAI set separators (:) to directory sep
+        $i_url =~ s/:/\//g;
+	my $file_i_url = "$output_dir/$i_url.oai";
+
+	my $ds = &util::get_dirsep();
+	my $i_os = $i; #convert OAI set separators (:) to OS dir sep
+	$i_os =~ s/:/$ds/g;
+	my $file_i = &util::filename_cat($output_dir,"$i_os.oai");
+
+	# obtain record
+	my $wget_cmd = "wget $wgetopt -q -O - \"$url\"";
+
+	open (OAIIN,"$wget_cmd|")
+	    || die "wget request failed: $!\n";
+	my $i_record = "";
+	
+	my $line;
+	while (defined($line=<OAIIN>))
+	{
+	    $i_record .= $line;
+	}
+
+	close(OAIIN);
+
+	$num_processed++;
+	
+	# prepare subdirectory for record (if needed)
+	my ($i_dir,$unused) = dir_file_split($file_i_url);
+
+	&util::mk_all_dir($i_dir);
+
+	# look out for identifier tag in metadata section
+	if ($i_record =~ m/<metadata>(.*)<\/metadata>/s)
+	{
+	    my $m_record = $1;
+
+	    if ($get_id)
+	    {
+		my $got_doc = 0;
+
+		my @url_matches = ($m_record =~ m/<(?:dc:)?identifier>(.*?)<\/(?:dc:)?identifier>/gs);
+		foreach my $doc_url (@url_matches) 
+		{
+		    if ($doc_url =~ m/^(http|ftp):/) {
+
+			my $revised_doc_url = $doc_url;
+##			$revised_doc_url =~ s/hdl\.handle\.net/mcgonagall.cs.waikato.ac.nz:8080\/dspace\/handle/;
+			
+			my $srcdocs_dir = &util::filename_cat($i_dir,"srcdocs");
+
+			if (get_oai_document($revised_doc_url,$srcdocs_dir, $out)) {			   
+
+			    $got_doc = 1;
+			    my ($id_dir,$id_fname) = dir_file_split($revised_doc_url);
+			    
+			    $i_record =~ s/<metadata>(.*?)<(dc:)?identifier>$doc_url<\/(dc:)?identifier>(.*?)<\/metadata>/<metadata>$1<OrigURL>$doc_url<\/OrigURL>\n   <identifier>srcdocs\/$id_fname<\/identifier>$4<\/metadata>/s;
+			    
+			}
+		    }
+
+		    if (!$got_doc) {
+			$i_record =~ s/<metadata>(.*?)<(dc:)?identifier>$doc_url<\/(dc:)?identifier>(.*?)<\/metadata>/<metadata>$1<OrigIdentifier>$doc_url<\/OrigIdentifier>$4<\/metadata>/s;
+		    }
+		}
+	    }
+	}
+
+	# save record 
+	open (OAIOUT,">$file_i")
+	    || die "Unable to save oai metadata record: $!\n";
+	print OAIOUT $i_record;
+	close(OAIOUT);
+
+	$doc_count++;
+	last if ($doc_count == $maxdocs);
+    }
+}
+
+
+sub main {
+    my ($verbosity, $importdir, $keepold, 
+	$getdoc, $acquire_info, $acquire_set,
+	$removeold, $gzip, $groupsize, $debug, $maxdocs, $collection,
+	$configfilename, $collectcfg,
+	$out, $collectdir);
+
+    if (!parsargv::parse(\@ARGV, 
+			 'verbosity/\d+/2', \$verbosity,
+			 'getdoc', \$getdoc,
+			 'info', \$acquire_info,
+			 'importdir/.*/', \$importdir,
+			 'keepold', \$keepold,
+			 'removeold', \$removeold,
+			 'gzip', \$gzip,
+			 'debug', \$debug,
+			 'maxdocs/^\-?\d+/-1', \$maxdocs,
+			 'collectdir/.*/', \$collectdir,
+			 'out/.*/STDERR', \$out)) {
+	&print_usage();
+	die "\n";
+    }
+
+    my $close_out = 0;
+    if ($out !~ /^(STDERR|STDOUT)$/i) {
+	open (OUT, ">$out") || die "Couldn't open output file $out\n";
+	$out = 'import::OUT';
+	$close_out = 1;
+    }
+    $out->autoflush(1);
+
+    # set removeold to false if it has been defined
+    $removeold = 0 if ($keepold);
+
+    # get and check the collection name
+    if (($collection = &util::use_collection(@ARGV, $collectdir)) eq "") {
+	&print_usage();
+	die "\n";
+    }
+
+
+    # get acquire list
+    my $acquire = [];
+    $configfilename = &util::filename_cat ($ENV{'GSDLCOLLECTDIR'}, "etc", "collect.cfg");
+    if (-e $configfilename) {
+	$collectcfg = &colcfg::read_collect_cfg ($configfilename);
+	if (defined $collectcfg->{'acquire'}) {
+	    $acquire = $collectcfg->{'acquire'};
+	}
+	if (defined $collectcfg->{'importdir'} && $importdir eq "") {
+	    $importdir = $collectcfg->{'importdir'};
+	}
+	if (defined $collectcfg->{'removeold'}) {
+	    if ($collectcfg->{'removeold'} =~ /^true$/i && !$keepold) {
+		$removeold = 1;
+	    }
+	    if ($collectcfg->{'removeold'} =~ /^false$/i && !$removeold) {
+		$removeold = 0;
+	    }
+	}
+    } else {
+	die "Couldn't find the configuration file $configfilename\n";
+    }
+    
+    # fill in the default import directory if none
+    # were supplied, turn all \ into / and remove trailing /
+    $importdir = &util::filename_cat ($ENV{'GSDLCOLLECTDIR'}, "import") if $importdir eq "";
+    $importdir =~ s/[\\\/]+/\//g;
+    $importdir =~ s/\/$//;
+
+    # remove the old contents of the import directory if needed
+    if ($removeold && -e $importdir) {
+	print $out "Warning - removing current contents of the import directory\n";
+	print $out "          in preparation for the acquire\n";
+	&util::rm_r ($importdir);
+    }
+
+    my $e;
+    foreach $e ( @$acquire )
+    {
+	my $acquire_type = shift @$e;
+	my $acquire_src = undef;
+
+	if ($acquire_type ne "OAI") {
+	    print STDERR "Warning: $acquire_type not currently supported. Skipping.\n";
+	    next;
+	}
+
+	my $store_getdoc = $getdoc;
+
+	if (!parsargv::parse($e, 
+			     'getdoc',  \$getdoc,
+			     'set/.*/', \$acquire_set,
+			     'format/.*/oai_dc', \$metadata_format,
+			     'src/.*/', \$acquire_src)) {
+	    &print_usage();
+	    die "\n";
+	}
+
+	if (!defined $acquire_src) {
+	    print STDERR "Warning: Not -src flag defined.  Skipping.\n";
+	    next;
+	}
+
+	if (defined $acquire_info && ($acquire_info)) {
+	    oai_info($acquire_src,$out,$verbosity);
+	    next;
+	}
+
+	print $out "$acquire_type Acquire: from $acquire_src\n";
+
+	my $li_record = get_oai_ids($acquire_src,$acquire_set,$metadata_format,
+				    $out,$verbosity);
+	my $ids = parse_oai_ids($li_record,$out,$verbosity);
+
+	get_oai_records($acquire_src,$metadata_format, $ids,$importdir, 
+			$getdoc, $maxdocs, $out);
+	$getdoc = $store_getdoc;
+    }
+
+    print "\nNumber of documents processed: $num_processed\n";
+
+    close OUT if $close_out;
+}
+
+
+&main();
+
+
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/indexes/Core.pm
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/indexes/Core.pm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/indexes/Core.pm	(revision 13928)
@@ -0,0 +1,895 @@
+#
+# PDF::Core.pm, version 1.11 February 2000 antro
+#
+# Copyright (c) 1998 - 2000 Antonio Rosella Italy antro@tiscalinet.it, Johannes Blach dw235@yahoo.com 
+#
+# Free usage under the same Perl Licence condition.
+#
+
+package PDF::Core;
+
+$PDF::Core::VERSION = "1.11";
+
+=pod
+
+=head1 NAME
+
+PDF::Core - Core Library for PDF library
+
+=head1 SYNOPSIS
+
+  use PDF::Core;
+
+  $pdf=PDF::Core->new ;
+  $pdf=PDF->new(filename);
+
+  $res= $pdf->GetObject($ref);
+
+  $name = UnQuoteName($pdfname);							  
+  $string = UnQuoteString($pdfstring);							  
+
+  $pdfname = QuoteName($name);							  
+  $pdfhexstring = QuoteHexString($string);
+  $pdfstring = QuoteString($string);
+
+  $obj = PDFGetPrimitive (filehandle, \$offset);
+  $line = PDFGetLine (filehandle, \$offset);
+  
+
+=head1 DESCRIPTION
+
+The main purpose of the PDF::Core library is to provide the data structure
+and the constructor for the more general PDF library.
+
+=cut
+
+require 5.005;
+use strict;
+use Carp;
+use Exporter ();
+
+use vars qw(@ISA @EXPORT_OK $UseObjectCache);
+
+@ISA = qw(Exporter);
+
+@EXPORT_OK = qw( GetObject );
+
+#
+# Object caching
+#
+# If this variable is true, all processed objects will be added to the
+# object cache. If only header information of a PDF are read or very
+# big PDF are processed, turning off the cache reduces the memory usage.
+#
+$UseObjectCache = 1;
+
+
+#################################################################
+#
+# Helper functions
+#
+#################################################################
+
+=pod
+
+=head1 Helper functions
+
+This functions are not part of the class, but perform useful services.
+
+=cut
+
+#
+# Modification by johi: 18.12.1999
+#
+
+#################################################################
+=pod
+
+=head2 UnQuoteName ( string )
+
+This function processes quoted characters in a PDF-name. PDF-names returned by
+B<GetObject> are already processed by this function.
+
+Returns a string.
+
+=cut
+
+sub UnQuoteName ($)
+	{
+	my $value = shift;
+	$value =~ s/#([\da-f]{2})/chr(hex($1))/ige;
+	return $value;
+	}
+
+#################################################################
+=pod
+
+=head2 UnQuoteString ( string )
+
+This function extracts the text from PDF-strings and PDF-hexstrings.
+It will process all quoted characters and remove the enclosing braces.
+
+WARNING: The current version doesn't handle unicode strings properly.
+
+Returns a string.
+
+=cut
+
+sub UnQuoteString ($)
+	{
+#
+# Translate quoted character. 
+#
+	my $param = shift;
+	my $value;
+	if (($value) = $param =~ m/^<(.*)>$/)
+		{
+		$value =~ tr/0-9A-Fa-f//cd;
+		$value .= "0" if (length ($value) % 2);
+		$value =~ s/([\da-f]{2})/chr(hex($1))/ige;
+		}
+	elsif (($value) = $param =~ m/^\((.*)\)$/)
+		{
+		my %quoted = ("n" => "\n", "r" => "\r",
+					  "t" => "\t", "b" => "\b",
+					  "f" => "\f", "\\" => "\\",
+					  "(" => "(", ")" => ")");
+		$value =~ s/\\([nrtbf\\()]|[0-7]{1,3})/
+		defined ($quoted{$1}) ? $quoted{$1} : chr(oct($1))/gex;
+		}
+	else
+		{
+		$value = $param;
+		}
+
+	return $value;
+	}
+
+#################################################################
+=pod
+
+=head2 QuoteName ( string )
+
+This function quotes problematic characters in a PDF-name. This
+function should be used before writing a PDF-name back to a PDF-file.
+
+Returns a string.
+
+=cut
+
+sub QuoteName ($)
+	{
+	my $value = shift;
+	$value =~ s/(?<!\A)([\x00-\x20\x7f-\xff%()\[\]<>\/{}#])/
+						 sprintf ("#%2.2X", ord($1))/gex;
+	return $value;
+	}
+
+#################################################################
+=pod
+
+=head2 QuoteHexString ( string )
+
+This function translates a string into a PDF-hexstring. 
+
+Returns a string.
+
+=cut
+
+sub QuoteHexString ($)
+	{
+	my $value = shift;
+
+	$value =~ s/(.)/sprintf ("%2.2X", ord($1))/ge;
+	return ("<" . $value . ">");
+	}
+
+#################################################################
+=pod
+
+=head2 QuoteString ( string )
+
+This function translates a string into a PDF-string. Problematic
+character will be quoted.
+
+WARNING: The current version doesn't handle unicode strings properly.
+
+Returns a string.
+
+=cut
+
+sub QuoteString ($)
+	{
+	#
+	# Only \character style quotes will be added. The really important
+	# characters to quote are: ()\
+	# 
+	my $value = shift;
+
+	my %quote = ("\n" => "\\n", "\r" => "\\r",
+				  "\t" => "\\t", "\b" => "\\b",
+				  "\f" => "\\f", "\\" => "\\\\",
+				  "(" => "\\(", ")" => "\\)");
+	$value =~ s/([\n\r\t\b\f\\()])/$quote{$1}/g;
+	return ("(" . $value . ")");
+	}
+
+#################################################################
+=pod
+
+=head2 PDFGetPrimitive ( filehandle, offset )
+
+This internal function is used while parsing a PDF-file. If you are
+not writing extentions for this library and are parsing some special
+parts of the PDF-file, stay away and use B<GetObject> instead.
+
+This function has many quirks and limitations. Check the source for details.
+
+=cut
+
+sub PDFGetPrimitive (*\$)
+	{
+	my $fd = shift;
+	my $offset = shift;
+
+	binmode $fd;
+	seek $fd, $$offset, 0;
+
+	my $state = 0;
+	my $buffer;
+	my @collector;
+	my $lastchar;
+
+	while ()
+		{
+		# File offset is positioned on start of stream.
+		last if ($state == -4);
+
+		$state = 0;
+
+		# Process last element
+		if ($#collector >= 0)
+			{
+			my $lastvalue = $collector[$#collector];
+			
+			if ($lastvalue eq "R")
+				{
+				# Process references
+				if ($#collector >= 2
+					&& $collector[$#collector - 1] =~ m/\d+/
+					&& $collector[$#collector - 2] =~ m/\d+/)
+					{
+					$collector[$#collector - 2] .= join (" ", 
+						"", @collector[$#collector - 1, $#collector]);
+					$#collector -= 2; 
+					}
+				else
+					{
+					carp "Bad reference at offset ", $$offset;
+					}
+				}
+			elsif ($lastvalue eq "endobj")
+				{
+				# End of object
+				last;
+				}
+			elsif ($lastvalue eq "stream")
+				{
+				# End of object
+				$state = -4;
+				}
+			}
+		
+		# Set state for next element
+		if ($buffer eq "[") 
+			{
+			# Read array
+			$buffer = "";
+			push @collector, [ PDFGetPrimitive ($fd, $offset) ];
+			}
+		elsif ($buffer eq "<<")
+			{
+			# Read dictionary
+			$buffer = "";
+			push @collector, { PDFGetPrimitive ($fd, $offset) };
+			}
+		elsif ($buffer eq "(") 
+			{
+			# Here comes a string
+			$state = 1;
+			$lastchar = "";
+			}
+		elsif ($buffer eq "<") 
+			{
+			# Here comes a hex string
+			$state = -1;
+			}
+		elsif ($buffer eq ">")
+			{
+			# Wait for next > to terminate dictionary
+			$state = -2;
+			}
+		elsif ($buffer eq "%")
+			{
+			# Skip comments
+			$state = -3;
+			$buffer = "";
+			}
+		elsif ($buffer eq "]")
+			{
+			last;
+			}
+		elsif ($buffer eq ">>")
+			{
+			last;
+			}
+
+		# Read next item
+		while (read ($fd, $_, 1))
+			{
+			$$offset++;
+
+			if ($state == 0)
+				{
+				# Normal mode
+				if (m/[^\x00-\x20\x7f-\xff%()\[\]<>\/]/)
+					{
+					# Normal character inside a name or number
+					$buffer .= $_;
+					}
+				elsif (m/[\/\(\[\]\<\>%]/)
+					{
+					if ($buffer ne "")
+						{
+						# A new item starts
+						if ($buffer =~ m/^\//)
+							{
+							push @collector, UnQuoteName ($buffer);
+							}
+						else
+							{
+							push @collector, $buffer;
+							}
+						}
+					$buffer = $_;
+					last;
+					}
+				elsif (m/\s/)
+					{
+					# All kind of whitespaces are ignored
+					if ($buffer ne "")
+						{
+						# The old item is done starts
+						if ($buffer =~ m/^\//)
+							{
+							push @collector, UnQuoteName ($buffer);
+							}
+						else
+							{
+							push @collector, $buffer;
+							}
+						$buffer = "";
+						last;
+						}
+					}
+				else
+					{
+					# Strange character. Should not exist.
+					# Complain and move on.
+					carp "Strange character '", $_, "' at offset ",
+					$$offset, " in mode ", $state, " detected";
+					$buffer .= $_;
+					}
+				}
+			elsif ($state > 0)
+				{
+				# We have a string
+
+				if ($lastchar =~ m/\\[\r\n]+/ && m/[^\r\n]/)
+					{
+					# Clean up after line continuation
+					$lastchar = "";
+					}
+
+				if ($lastchar =~ m/\\[\r\n]*/)
+					{
+					# Process character after backslash
+					if (m/[\r\n]/)
+						{
+						# end of line
+						$lastchar .= $_;
+						}
+					else
+						{
+						# Just a quote
+						$buffer .= $lastchar . $_;
+						$lastchar = "";
+						}
+					}
+				else
+					{
+					if ($_ eq "\\")
+						{
+						# Quoted string starts
+						$lastchar = $_;
+						}
+					elsif ($_ eq "(")
+						{
+						# Count braces
+						$buffer .= $_;
+						$state ++;
+						}
+					elsif ($_ eq ")")
+						{
+						# End of string
+						$buffer .= $_;
+						unless (-- $state)
+							{
+							push @collector, $buffer;
+							$buffer = "";
+							last;
+							}
+						}
+					else
+						{
+						$buffer .= $_;
+						}
+					}
+				}
+			elsif ($state == -1)
+				{
+				if (m/[0-9a-f\s]/i)
+					{
+					# Hex character
+					$buffer .= $_;
+					}
+				elsif ($_ eq ">")
+					{
+					# End of string
+					$buffer .= $_;
+					push @collector, $buffer;
+					$buffer = "";
+					last;
+					}
+				elsif ($_ eq "<" && $buffer eq "<")
+					{
+					# This is not a string, but a dictionary instead
+					$buffer .= $_;
+					last;
+					}
+				else
+					{
+					# Should not be there. Complain and add it to the $buffer
+					carp "Bad character '", $_ , "' in hex string";
+					$buffer .= $_;
+					}
+				}
+			elsif ($state == -2)
+				{
+				# Wait for second > to terminate dictionary
+
+				# Some sanity checks
+				carp "Character '", $_, "' appeared while waiting for '>'" 
+				if ($_ ne ">");
+				carp "Buffer contains '", $buffer, "' and not '>'" 
+				if ($buffer ne ">");
+
+				$buffer = ">>";
+				last;
+				}
+			elsif ($state == -3)
+				{
+				# Skip comments;
+				last if (m/[\r\n]/);
+				}
+			elsif ($state == -4)
+				{
+				# Wait for newline to start stream
+
+				if ($_ eq "\n")
+					{
+					# Some sanity checks
+					carp "Text '", $buffer, 
+					"' appeared while waiting for start of stream" 
+					if ($buffer ne "");
+
+					$buffer = "";
+					last;
+					}
+				elsif (m/\S/)
+					{
+					$buffer .= $_;
+					}
+				}
+			else
+				{
+				# Unhandled status. Complain and reset
+				carp "Unhandled status ", $state;
+				}
+			}
+		if ($_ eq "")
+			{
+			# Unhandled status. Complain and reset
+			carp "Premature end of file reached";
+			
+			if ($buffer ne "")
+				{
+				push @collector, $buffer;
+				$buffer = "";
+				}
+			last;
+			}
+		}
+
+	return @collector;
+	}
+
+#################################################################
+=pod
+
+=head2 PDFGetline ( filehandle, offset )
+
+This internal function was used to read a line from a PDF-file. It has
+many limitations and you should stay away from it, if you don't know
+what you are doing. Use B<GetObject> or B<PDFGetPrimitive> instead.
+
+=cut
+
+sub PDFGetline {
+#
+# BUG WARNING:
+#
+# This function returns only one line, which doesn't mean anything most of the
+# time. Except for the fileheader and the xref-table, linebreaks can (and will!)
+# occur everywhere in a PDF and are just whitespace. You may find only part of a
+# PDF-primitve on one line, or more than one of them.
+#
+# If you want to read PDF-Primitves, use the function PDFGetPrimitive instead.
+#
+    my $fd = shift;
+    my $offset=shift;
+
+    my $buffer;
+    my $endflag=1;
+
+    binmode $fd;
+    seek $fd, $$offset, 0;
+
+    read($fd,$buffer,2);
+    $buffer =~ s/^\r?\n?// ;
+
+    $$offset +=2;
+
+    while ($endflag) {
+      read($fd,$_,1);
+      $$offset++;
+      $endflag = 0 if ( $_ eq "\r" || $_ eq "\n");
+      $buffer = $buffer . $_ ;
+    }
+    return $buffer;
+	}
+
+#################################################################
+#
+# Constructors
+#
+#################################################################
+
+=pod
+
+=head1 Constructor
+
+=cut
+
+#################################################################
+=pod
+
+=head2 new ( [ filename ] )
+
+This is the constructor of a new PDF object. If the filename is
+missing, it returns an empty PDF descriptor ( can be filled with
+$pdf->TargetFile). Otherwise, It acts as the B<PDF::Parse::TargetFile>
+method.
+
+=cut
+
+sub new {
+
+	my %PDF_Fields = (
+		  File_Name => undef, # Name of file
+		  File_Handler => undef, # Open handle to file
+		  Header => undef, # Identification string
+
+		  Objects => [], # Offset of objects
+		  Gen_Num => [], # Genereation number of objects
+		  Object_Length => [],	# Length of processed objects
+		  Object_Cache => {}, # Cache for objects.
+		  Page => [], # Information about all pages. Useful.
+
+		  Updated => 0,	# Is the PDF updated 
+		  Last_XRef_Offset => undef, # File offset of active Xref table
+		  Trailer => {}, # Content of active trailer
+		  Info => {}, # Content of active info object
+		  Catalog => {}, # Content of catalog
+		  PageTree => {}, # Content of root page
+		  );
+my $that = shift;
+my $class=ref($that) || $that ;
+  my $self = \%PDF_Fields ;
+  my $buf2=bless $self, $class;
+  if ( @_ ) { 			# I have the filename
+    $buf2->TargetFile($_[0]) ; 
+  }
+  return bless $self, $class;
+};
+
+#################################################################
+sub DESTROY {
+#
+# Close the file if not empty
+#
+  my $self = shift;
+  close ( $self->{File_Handler} ) if $self->{File_Handler} ;
+}
+
+#################################################################
+#
+# Methods
+#
+#################################################################
+
+=pod
+
+=head1 Methods
+
+The available methods are:
+
+=cut
+
+#################################################################
+=pod
+
+=head2 GetObject (reference)
+
+This methods returns the PDF-object for B<reference>. The string
+B<reference> must match the regular expression /^\d+ \d+ R$/,
+where the first number is the object number, the second number the
+generation number.
+
+The return value is a PDF-primitive, the type depends on the content
+of the object:
+
+=over
+
+=item B<undef>
+
+The object could not be found or an error. Not all referenced objects
+need to be present in a PDF-file. This value can be ignored.
+
+=item B<Hash Reference>
+
+If (UNIVERSAL::isa ($retval, "HASH") is true, the object is a
+PDF-dictionary. The keys of the hash should be either a PDF name (eg:
+/MediaBox) or a generated value like Stream_Offset. Everything else is
+an error.
+
+The values of the hash can be any PDF-primitive, including PDF-arrays
+and other dictionaries.
+
+This is the most common value returned by GetObject. If the key
+Stream_Offset exists, the dictionary is followed by stream data,
+starting at the file offeset indicated by this value.
+
+=item B<Array Reference>
+
+If (UNIVERSAL::isa ($retval, "ARRAY") is true, the object is a
+PDF-array. Each element may be of a different type, and may contain
+further references to arrays or any other PDF-primitive.
+
+=item B<String matching /^\d+ \d+ R$/>
+
+This is a reference to another PDF-Object. This value can be passed to
+GetObject. This kind of value may appear instead of most other types.
+Some PDF-writing programs seem to have special fun writing references
+when a simple number is expected. If the final number is need, use
+code like this to resolve references:
+
+while ($len =~ m/^\d+ \d+ R$/) {$len = $self->GetObject ($len);	}
+
+Example: 22 0 R
+
+=item B<String matching /^\//>
+
+This is a Name in a PDF dictionary. This string is already processed
+by B<UnQuotName> and may differ from the value in the PDF-file. In
+some very old andstrange non-standard PDF-files, this may lead to
+confusion.
+
+Example: /MediaBox
+
+=item B<String matching /^\(.*\)$/>
+
+This is a string. It may contain newlines, quoted characters und other
+strange stuff. Use PDF::UnQuoteString to extract the text.
+
+Example: (This is\na string with two \(2\) lines.)
+
+=item B<String matching /^E<lt>.*E<gt>$/>
+
+This is a hex encoded string. Use PDF::UnQuoteString to extract the text.
+
+Example: E<lt>48 45 4c4C4 F1cE<gt>
+
+=item B<String matching /^[\d.\+\-]+$/>
+
+This is probably a number.
+
+Example: 611
+
+=item B<String matching none of the above>
+
+this is either a PDF bareword (eg. true, false, ...) or a value
+generated by this method like Stream_Offset.
+
+Example: true
+
+=back
+
+To improve performance GetObject uses an internal cache for objects.
+Repeated requests for the same objects are not read form the file but
+satisfied from the cache. With the Variable B<$PDF::Core::UseObjectCache>,
+the caching mechanism can be turned off.
+
+B<WARNING>
+
+Special care must be taken, when returned objects are modified. If the
+object contains sub-objects, the sub-objects are not duplicated and
+all changes affect all other copies of this object. Use your own copy,
+if you need to modify those values.
+
+=cut
+
+sub GetObject (\*$;$)
+	{
+	my $self = shift;
+	my $ref = shift;
+	my $force = shift;
+
+#
+# Is PDF file open?
+#
+	croak "PDF-file not open." unless ($self->{"File_Handler"});
+
+#
+# Check reference
+#
+	my ($ind, $gen);
+	unless (($ind,$gen) = $ref =~ m/^(\d+) (\d+) R$/)
+		{
+		carp "Bad object reference '", $_, "'";
+		return undef;
+		}
+	if ($ind > $#{$self->{"Gen_Num"}} || $self->{"Gen_Num"}[$ind] != $gen)
+		{
+		#
+		# The page does not exist. According to the PDF specification,
+		# this is not an error.
+		#
+		return undef;
+		}
+
+	# Remove leading zero for cache key.
+	$ind += 0;
+	# Check cache
+	if ($UseObjectCache && ! $force
+		&& defined($self->{"Object_Cache"}{$ind}))
+		{
+		return $self->{"Object_Cache"}{$ind};
+		}
+
+	my $offset = $self->{"Objects"}[$ind];
+	my @data = PDFGetPrimitive ($self->{"File_Handler"}, $offset);
+
+	unless ($#data == 4  && $data[0] == $ind 
+		&& $data[1] == $gen && $data[2] eq "obj")
+		{
+		carp "Object mismatch: Got '", join (" ", @data[0..2]),
+		"' instead of '", join (" ", $ind, $gen, "obj"), "'";
+		return;
+		}
+
+	#
+	# An object is not always a dictionary. In such cases,
+	# adding additional keys breaks the content.
+	#
+	if (UNIVERSAL::isa ($data[3], "HASH"))
+		{
+		if ($data[4] eq "stream")
+			{
+			#
+			# Find end of a stream object
+			#
+			$data[3]{"Stream_Offset"} = $offset;
+			my $len = $data[3]{"/Length"};
+
+			# Length can be a reference to another object. 
+			# Resolve references in this case till something else appears.
+			while ($len =~ m/^\d+ \d+ R$/)
+				{
+				$len = $self->GetObject ($len);
+				}
+
+			# Skip stream
+			if ($len =~ m/^\d+$/)
+				{
+				$offset += $len;
+				}
+			else
+				{
+				carp "Strange: /Length resolves to '", $len, "' in object ", 
+				join (" ", @data[0..2]);
+				}
+
+			my @enddata = PDFGetPrimitive ($self->{"File_Handler"}, $offset);
+			$data[4] = $enddata[$#enddata];
+			}
+		}
+
+	#
+	# Save length of object.
+	#
+	$self->{"Object_Length"}[$ind] = $offset - $self->{"Objects"}[$ind];
+
+	carp "Bad object termination '", $data[4], "' in object ", 
+	join (" ", @data[0..2]) if ($data[4] ne "endobj");
+	
+
+	# Update cache
+	$self->{"Object_Cache"}{$ind} = $data[3] if ($UseObjectCache);
+
+	return $data[3];
+	}
+
+#
+# End of Modification by johi: 18.12.1999
+#
+#################################################################
+
+
+1;
+__END__
+
+=pod
+
+=head1 Variables
+
+Available variables are:
+
+=over 4
+
+=item B<$PDF::Core::VERSION>
+
+Contains the version of the library installed
+
+=item B<$PDF::Core::UseObjectCache>
+
+If this variable is true, all processed objects will be added to the
+object cache. If only header information of a PDF are read or very big
+PDF are processed, turning off the cache reduces the memory usage.
+
+=back 4
+
+=head1 Copyright
+
+  Copyright (c) 1998 - 2000 Antonio Rosella Italy antro@tiscalinet.it, Johannes Blach dw235@yahoo.com 
+
+This library is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=head1 Availability
+
+The latest version of this library is likely to be available from:
+
+http://www.geocities.com/CapeCanaveral/Hangar/4794/
+
+=cut
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/indexes/PDF.pm
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/indexes/PDF.pm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/indexes/PDF.pm	(revision 13928)
@@ -0,0 +1,153 @@
+#
+# PDF.pm, version 1.11 February 2000 antro
+#
+# Copyright (c) 1998 - 2000 Antonio Rosella Italy antro@tiscalinet.it, Johannes Blach dw235@yahoo.com 
+#
+# Free usage under the same Perl Licence condition.
+#
+
+package PDF;
+
+$PDF::VERSION = "1.11";
+
+require 5.005;
+
+#require PDF::Core;  
+#require PDF::Parse; 
+require Core;  
+require Parse;
+ 
+use strict;
+use Carp;
+use Exporter ();
+
+use vars qw(@ISA $Verbose);
+
+#
+# Verbose off by default
+#
+$Verbose = 0;
+
+@ISA = qw(Exporter PDF::Core PDF::Parse);
+
+1;
+
+__END__
+
+=head1 NAME
+
+PDF - Library for PDF access and manipulation in Perl
+
+=head1 SYNOPSIS
+
+  use PDF;
+
+  $pdf=PDF->new ;
+  $pdf=PDF->new(filename);
+
+  $result=$pdf->TargetFile( filename );
+
+  print "is a pdf file\n" if ( $pdf->IsaPDF ) ;
+  print "Has ",$pdf->Pages," Pages \n";
+  print "Use a PDF Version  ",$pdf->Version ," \n";
+  print "and it is crypted  " if ( $pdf->IscryptedPDF) ;
+
+  print "filename with title",$pdf->GetInfo("Title"),"\n";
+  print "and with subject ",$pdf->GetInfo("Subject"),"\n";
+  print "was written by ",$pdf->GetInfo("Author"),"\n";
+  print "in date ",$pdf->GetInfo("CreationDate"),"\n";
+  print "using ",$pdf->GetInfo("Creator"),"\n";
+  print "and converted with ",$pdf->GetInfo("Producer"),"\n";
+  print "The last modification occurred ",$pdf->GetInfo("ModDate"),"\n";
+  print "The associated keywords are ",$pdf->GetInfo("Keywords"),"\n";
+
+  my (startx,starty, endx,endy) = $pdf->PageSize ($page) ;
+
+=head1 DESCRIPTION
+
+The main purpose of the PDF library is to provide classes and
+functions that allow to read and manipulate PDF files with perl. PDF
+stands for Portable Document Format and is a format proposed by Adobe.
+A full description of this format can be found in the B<Portable
+Document Reference Manual> by B<Adobe Systems Inc.>. For more details
+about PDF, refer to:
+
+B<http://www.adobe.com/>
+
+The main idea is to provide some "basic" modules for access 
+the information contained in a PDF file. Even if at this
+moment is in an early development stage, the scripts in the 
+example directory show that it is usable. 
+
+B<is_pdf> script test a list of files in order divide the PDF file
+from the non PDF using the info provided by the files 
+themselves. It doesn't use the I<.pdf> extension, it uses the information
+contained in the file.
+
+B<pdf_version> returns the PDF level used for writing a file.
+
+B<pdf_pages> gives the number of pages of a PDF file. 
+
+B<pagedump.pl> prints some information about individual pages in a
+PDF-file. Although the information as such are not very useful, it
+demontrates well some more complex aspects of the library. Check the
+function B<doprint> in this program on how to handle all possible data
+occuring in a PDF.
+
+The library is now splitted in 2 section :
+
+B<PDF::Core> that contains the data structure, the constructor and low
+level access fuctions;
+
+B<PDF::Parse> all kind of functions to parse the PDF-files and
+provide information about the content.
+
+Check the help-files of these modules for more details.
+
+=head1 Variables
+
+There are 2 variables that can be accessed:
+
+=over 4
+
+`=item B<$PDF::VERSION>
+
+Contain the version of the library installed.
+
+=item B<$PDF::Verbose>
+
+This variable is false by default. Change the value if you want 
+more verbose output messages from library.
+
+=back 4
+
+=head1 Copyright
+
+  Copyright (c) 1998 - 2000 Antonio Rosella Italy antro@tiscalinet.it, Johannes Blach dw235@yahoo.com 
+
+This library is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=head1 Availability
+
+The latest version of this library is likely to be available from:
+
+http://www.geocities.com/CapeCanaveral/Hangar/4794/
+
+and at any CPAN mirror
+
+=head1 Greetings
+
+Fabrizio Pivari ( pivari@geocities.com ) for all the suggestions about life, the universe and everything.
+Brad Appleton ( bradapp@enteract.com ) for his suggestions about the module organization.
+Thomas Drillich for the iso latin1 support 
+Ross Moore ( ross@ics.mq.edu.au ) for ReadInfo fix
+
+=cut
+
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/indexes/Parse.pm
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/indexes/Parse.pm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/indexes/Parse.pm	(revision 13928)
@@ -0,0 +1,513 @@
+#
+# PDF::Parse.pm, version 1.11 February 2000 antro
+#
+# Copyright (c) 1998 - 2000 Antonio Rosella Italy antro@tiscalinet.it, Johannes Blach dw235@yahoo.com 
+#
+# Free usage under the same Perl Licence condition.
+#
+
+package PDF::Parse;
+
+$PDF::Parse::VERSION = "1.11";
+
+=pod
+
+=head1 NAME
+
+PDF::Parse - Library with parsing functions for PDF library
+
+=head1 SYNOPSIS
+
+  use PDF::Parse;
+
+  $pdf->TargetFile($filename);
+  $pdf->LoadPageInfo;
+
+  $version = $pdf->Version;
+  $bool = $pdf->IsaPDF;
+  $bool = $pdf->IscryptPDF;
+
+  $info = $pdf->GetInfo ($key);
+  $pagenum = $pdf->Pages;
+
+  @size = $pdf->PageSize ($page);
+  # or
+  @size = $pdf->PageSize;
+
+  $rotation = $pdf->PageRotation ($page);
+  # or
+  $rotation = $pdf->PageRotation;
+
+=head1 DESCRIPTION
+
+The main purpose of the PDF::Parse library is to provide parsing functions
+for the more general PDF library.
+
+=head1 Methods
+
+The available methods are:
+
+=cut
+
+require 5.005;
+#require PDF::Core;
+require Core;
+
+use strict;
+use Carp;
+use Exporter ();
+
+use vars qw(@ISA @EXPORT_OK);
+
+@ISA = qw(Exporter PDF::Core);
+
+@EXPORT_OK = qw( LoadPageInfo GetInfo TargetFile
+				 Pages PageSize PageRotation IsaPDF
+				 Version IscryptPDF );
+
+#################################################################
+sub ReadCrossReference_pass1 {
+  my $fd = shift;
+  my $offset=shift;
+  my $self=shift;
+
+  my $initial_number;
+  my $obj_counter=0;
+  my $global_obj_counter=0;
+  my $buf;
+
+  binmode $fd;
+
+  $_=PDF::Core::PDFGetline ($fd,\$offset);
+
+  die "Can't read cross-reference section, according to trailer\n" if ! /xref\r?\n?/  ;
+
+  while () {
+    $_=PDF::Core::PDFGetline ($fd,\$offset);
+    s/^\n//;
+    s/^\r//;
+    last if (m/\btrailer\b/) ;
+#
+# An Object
+#
+    /^\d+\s+\d+\s+n\r?\n?/ && do { my $buf =$_;
+	       my $ind = $initial_number + ($obj_counter++);
+               ( not defined $self->{Objects}[$ind] )&& 
+		  do { $self->{Objects}[$ind] = int substr($buf,0,10);
+		       $self->{Gen_Num}[$ind] = int substr($buf,11,5);
+		     };
+	       $_=$buf;
+	       s/^.{18}//; 
+	       next ;
+   }; 
+#
+# A Freed Object
+#
+    /^\d+\s+\d+\s+f\r?\n?/ && do { my $buf =$_;
+   	       my $objects_generation_nr = substr($buf,11,5);
+	       my $Num=substr($buf,0,10);
+	       my $ind = $initial_number + ($obj_counter++);
+	       # $ind = $ind . "_" . $objects_generation_nr;
+		       $self->{Objects}[$ind] = - $Num;
+		       $self->{Gen_Num}[$ind] = $objects_generation_nr;
+		       $_=$buf;
+		       s/^.{18}//; 
+		       next ;
+     };
+#
+# A subsection
+#
+    /^\d+\s+\d+\r?\n?/  && do { 
+ 	my $buf = $_ ; 
+ 	 $initial_number = $buf; 
+ 	 $initial_number=~ s/^(\d+)\s+\d+\r?\n?.*/$1/; 
+	 $global_obj_counter += $obj_counter;
+ 	 $obj_counter=0; 
+	 next ;
+    };
+  }
+
+  $global_obj_counter +=$obj_counter;
+#
+# Now the trailer for updates 
+#
+
+#
+# Skip to start of dictionary.
+#
+    until (m/<</)
+		{
+		$_=PDF::Core::PDFGetline ($fd,\$offset);
+		}
+
+#
+# Read the dictionary
+#
+    my %trailer = ( PDF::Core::PDFGetPrimitive ($fd, $offset) );
+
+    if ($self->{"Trailer"}{"/Root"} eq "")
+		{
+		$self->{"Trailer"} = \%trailer;
+		#
+		# This code is here for backward compatibility only. If the content
+		# of the root trailer is needed, use $self->{"Trailer"} instead.
+		#
+		$self->{"Cross_Reference_Size"} = $trailer{"/Size"};
+		$self->{"Root_Object"} = $trailer{"/Root"};
+		$self->{"Crypt_Object"} = $trailer{"/Encrypt"};
+		}
+	if ($trailer{"/Prev"} =~ m/^\d+$/)
+		{  
+  		$self->{"Updated"} = 1;
+		my $old_seek = tell $fd;
+		$global_obj_counter += ReadCrossReference_pass1 ($fd,
+            $trailer{"/Prev"}, $self );
+		seek $fd, $old_seek, 0;
+		}
+
+
+  return $global_obj_counter;
+}
+
+#################################################################
+sub LoadPageSubtree (\*$;%)
+	{
+	my $self = shift;
+	my $ref = shift;
+	my %inheritance = @_ ;
+
+	my $data = $self->GetObject ($ref);
+
+	# Check which attributes are inherited. Adobe did not add any new
+	# inherited attributes in version 1.2 or later, so this list is
+	# complete.
+
+	# Do simple values.
+	foreach my $key ("/Rotate", "/Dur", "/Hid", "/Trans", 
+			 "/MediaBox", "/CropBox") {
+
+	    if (defined ($data->{$key})){
+
+		# Check if it is an indirect reference
+		if ($data->{$key} =~ m/^\d+ \d+ R$/) {
+		    
+		    my $dataref = $data->{$key};
+
+		    do {
+
+			$dataref = $self->GetObject ($dataref);
+
+		    } while ($dataref =~ m/^\d+ \d+ R$/);
+
+		    if (UNIVERSAL::isa ($data, "ARRAY")){
+
+			$inheritance{$key} = [];
+
+			foreach my $i (@{$data}){
+			    # Each element may be a reference.
+			    while ($i =~ m/^\d+ \d+ R$/){
+				$i = $self->GetObject ($i);
+			    }
+			    
+			    push @{$inheritance{$key}}, $i;
+			}
+		    } else {
+			$inheritance{$key} = $dataref;
+		    }
+		} else { #not an indirect reference
+		    $inheritance{$key} = $data->{$key};
+		}
+	    }
+	}
+	
+	# If this objects contains ressources, replace information in inheritance
+	$inheritance{"Resource_Object"} = $data->{"/Resources"}
+	    if (defined ($data->{"/Resources"}));
+
+	if ($data->{"/Type"} eq "/Pages")
+		{
+		# It's just an intermediate Node
+		foreach my $kid (@{$data->{"/Kids"}})
+			{
+			$self->LoadPageSubtree ($kid, %inheritance);
+			}
+		}
+	elsif ($data->{"/Type"} eq "/Page")
+		{
+		# We have a real page!
+		$inheritance{"Page_Object"} = $ref;
+		push @{$self->{"Page"}}, +{ %inheritance };
+		}
+	else
+		{
+		# Strange stuff. Complain and discard.
+		carp "While loading pages got object of type '", $data->{"/Type"}, "'";
+		}
+	}
+
+#################################################################
+=pod
+
+=head2 TargetFile ( filename )
+
+This method links the filename to the pdf descriptor and parses all
+kind of header information.
+
+=cut
+
+sub TargetFile {
+  my $self = shift;
+  my $file = shift;
+
+  croak "Already linked to the file ",$self->{File_Name},"\n" 
+      if $self->{File_Name} ;
+  
+  my $offset;
+
+  if ( $file ) {
+    open(FILE, "< $file") or croak "can't open $file: $!";
+    binmode FILE;
+    $self->{File_Name} = $file ;
+    $self->{File_Handler} = \*FILE;
+    my $buf;
+    read(FILE,$buf,4);
+    if ( $buf ne "%PDF" ) {
+     print "File $_[0] is not PDF compliant !\n" if $PDF::Verbose ;
+     return 0 ;
+    }
+    read(FILE,$buf,4);
+    $buf =~ s/-//;
+    $self->{Header}= $buf;
+    seek FILE,-50,2;
+    read( FILE, $offset, 50 );
+    $offset =~ s/[^s]*startxref\r?\n?(\d*)\r?\n?%%EOF\r?\n?/$1/;
+
+	$self->{"Last_XRef_Offset"} = $offset;
+    ReadCrossReference_pass1 (\*FILE, $offset, $self);
+	$self->{"Info"} = $self->GetObject ($self->{"Trailer"}{"/Info"});
+	$self->{"Catalog"} = $self->GetObject ($self->{"Trailer"}{"/Root"});
+	$self->{"PageTree"} = $self->GetObject ($self->{"Catalog"}{"/Pages"});
+    return 1;
+  } else {
+    croak "I need a file name (!)";
+	}
+}
+
+#################################################################
+=pod
+
+=head2 LoadPageInfo
+
+This function loads the information for all pages. This process can
+take some time for big PDF-files.
+
+=cut
+
+sub LoadPageInfo (\*)
+	{
+	my $self = shift;
+
+	# Reset Page Array
+	$#{$self->{"Page"}} = -1;
+
+	# Recurse
+	$self->LoadPageSubtree ($self->{"Catalog"}{"/Pages"});
+	}								
+
+
+
+#################################################################
+=pod
+
+=head2 Version
+
+Returns the PDF version used for writing the object file.
+
+=cut
+
+sub Version { 
+  return ($_[0]->{Header}); 
+}
+
+#################################################################
+=pod
+
+=head2 IsaPDF
+
+Returns true, if the file could be parsed and is a PDF-file.
+
+=cut
+
+sub IsaPDF { 
+  return ($_[0]->{Header} != undef) ; 
+}
+
+#################################################################
+=pod
+
+=head2 IscryptPDF
+
+Returns true if the PDF contains a crypt object. This indicates that
+the data of the PDF-File is encrypted. In this case, not all function
+work as expected.
+
+=cut
+
+sub IscryptPDF { 
+  return ($_[0]->{Crypt_Object} != undef) ; 
+}
+
+#################################################################
+=pod
+
+=head2 GetInfo ( key )
+
+Returns the various information contained in the info section of a PDF
+file (if present). A PDF file can have:
+
+  a title ==> GetInfo ("Title")
+  a subject ==> GetInfo ("Subject")
+  an author ==> GetInfo("Author")
+  a creation date ==> GetInfo("CreationDate")
+  a creator ==> GetInfo("Creator")
+  a producer ==> GetInfo("Producer")
+  a modification date ==> GetInfo("ModDate")
+  some keywords ==> GetInfo("Keywords")
+
+=cut
+
+sub GetInfo (\*$)
+	{
+	my $self = shift;
+	my $type = shift;
+
+	return PDF::Core::UnQuoteString ($self->{"Info"}{"/" . $type})
+	}
+
+#################################################################
+=pod
+
+=head2 Pages
+
+Returns the number of pages of the PDF-file.
+
+=cut
+
+sub Pages 
+	{
+	my $self = shift;
+
+	return $self->{"PageTree"}{"/Count"};
+	}
+
+
+
+#################################################################
+=pod
+
+=head2 PageSize ( [ page ] )
+
+Returns the size of a page in the PDF-file. If no parameter is given,
+the default size of the root page will be returned. This value may be
+overridden for any page.
+
+If the size of an individual page is requested and the page data is
+not already loaded, the method B<LoadPageInfo> will be executed. This
+may take some time for large PDF-files. The size of the root page is
+always available and will never execute B<LoadPageInfo>.
+
+=cut
+
+sub PageSize (;$)
+	{
+	my $self = shift;
+	my $page = shift;
+
+	if ($page > 0)
+		{
+		return undef if ($page > $self->{"PageTree"}{"/Count"});
+		$self->LoadPageInfo unless ($#{$self->{"Page"}} >= 0);
+		
+		return @{$self->{"Page"}[$page - 1]{"/MediaBox"}}
+		if (defined $self->{"Page"}[$page - 1]{"/MediaBox"});
+		}
+	else
+		{
+		return @{$self->{"PageTree"}{"/MediaBox"}}
+		if (defined $self->{"PageTree"}{"/MediaBox"});
+		}
+
+	return undef;
+	}
+
+
+#################################################################
+=pod
+
+=head2 PageRotation ( [ page ] )
+
+Returns the rotation of a page in the PDF-file. If no parameter is given,
+the default rotation of the root page will be returned. This value may be
+overridden for any page.
+
+If the rotation of an individual page is requested and the page data is
+not already loaded, the method B<LoadPageInfo> will be executed. This
+may take some time for large PDF-files. The rotation of the root page is
+always available and will never execute B<LoadPageInfo>.
+
+=cut
+sub PageRotation (;$)
+	{
+	my $self = shift;
+	my $page = shift;
+
+	my $rotate = 0;
+
+	if ($page > 0)
+		{
+		return undef if ($page > $self->{"PageTree"}{"/Count"});
+		$self->LoadPageInfo unless ($#{$self->{"Page"}} >= 0);
+		
+		$rotate = $self->{"Page"}[$page - 1]{"/Rotate"};
+		}
+	else
+		{
+		$rotate = $self->{"PageTree"}{"/Rotate"};
+		}
+
+	print "Rotation ", 0 + $rotate if ($PDF::Verbose);
+
+	return 0 + $rotate;
+	}
+#################################################################
+1;
+__END__
+
+=head1 Variables
+
+The only available variable is :
+
+=over
+
+=item B<$PDF::Parse::VERSION>
+
+Contains the version of the library installed
+
+=back
+
+
+=head1 Copyright
+
+  Copyright (c) 1998 - 2000 Antonio Rosella Italy antro@tiscalinet.it, Johannes Blach dw235@yahoo.com 
+
+This library is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=head1 Availability
+
+The latest version of this library is likely to be available from:
+
+http://www.geocities.com/CapeCanaveral/Hangar/4794/
+
+=cut
+
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/indexes/amend_pdf.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/indexes/amend_pdf.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/indexes/amend_pdf.pl	(revision 13928)
@@ -0,0 +1,682 @@
+#!/usr/bin/perl
+#Jessica Thurston
+#usage: perl amend_pdf.pl filename
+#This program takes a pdf file 'filename'
+#and modifys it to include outline entries
+#(bookmarks).  
+#This is achieved using a pdf library which
+#parses the pdf file into objects allowing 
+#this script to more easily manipulate the pdf
+#objects and then modify the file by means
+#of incremental updates. (modifys the necessary
+#pdf objects and appends them to the end of 
+#the file, then updates the xreference table and
+#trailer). This library can be downloaded at
+# http://www.sanface.com/PDF-lib/
+#A file url.txt stored in the same
+#directory is read containing two columns of data:
+#title of related pdf document     url of related pdf document
+#The pdf document is modified so that the title of the
+#related pdf documents are displayed as bookmarks and
+#when the user clicks on it the web browser opens at
+#the url stored in the same column of url.txt.
+#
+#This program was designed to be used with the Greenstone
+#digital library in the following ways:
+#-When a user has built a collection containing
+# pdf documents, they have a choice of either displaying
+# the page in the web browser in gml form or saving the
+# original pdf document to view in an acrobat pdf reader.
+#-The related document file url.txt can be downloaded
+# in the same way if the user has included in the format
+# string for that page (ie search list) in the collection 
+# configuration file [urllink] related documents [/urllink].  
+# This will create a html link 'related documents' which 
+# when clicked on will enable the user to save a file url.txt 
+# containing the related documents for that particular document. 
+#-This file has been written upon running the perl script
+# relationPDF.pl which will also amend the gml documents to 
+# include the 'urllink' information enabling the user to 
+# include the related document links in config file format 
+# strings.
+#-So once this related doc info has been included the user
+# can download both the pdf file (doc.pdf) and the related
+# document file for that particluar document (url.txt).
+#-perl amend_pdf.pl doc.pdf is then run in the command line
+# modifying the pdf document to the desired effect.  
+#bugs:
+#-cannot be run more than once on the same file
+#-doesn't make use of free objects (free objects
+# are quite unlikely though, I didn't come across
+# any while looking through pdfs)
+#-many other things I haven't bothered testing
+
+use Carp;
+use Getopt::Long;
+use PDF;
+
+$objects = 0;
+$offsets = 1;
+
+
+#for each command line argument add the outlines
+#contained in url.txt
+#foreach (@ARGV) {
+#    create_outlines($_); 
+#}
+
+if(defined $ARGV[0]){
+    $pdf_document = $ARGV[0];
+} else {
+    print STDERR "You must supply pdf document filename\n";
+    return;
+}
+if(defined $ARGV[1]){
+    $related_docs = $ARGV[1];
+} else {
+print STDERR "You must supply related document filename\n";
+return;
+}
+create_outlines($pdf_document); 
+
+exit(1);
+
+
+#this function first checks to see is the file is indeed
+#a pdf file - if not then exits. If it is a pdf then it
+#checks to see if it is encrypted. If it is then exits.
+#Next we check if the outlines dictionary exists in the
+#document catalog. 
+#-If the outline entry exists but there are no actual outlines
+# present then call add_outlines but pass on the existing
+# outline dictionary.
+#-otherwise call modify_outlines to modify the existing outline
+# structure to include new outlines.
+#If outlines dictionary doesn't exist call add_outlines.
+sub create_outlines {
+
+  my $filename = shift;
+
+  #parse pdf filename
+  my @filelist = split("/", $filename);
+  my $file = pop @filelist;
+
+  print STDERR "pdf file to be manipulated: $file\n";
+  print STDERR "pdf file to be saved: tmp_$file\n";
+
+  #make a copy of that file in this directory
+  print STDERR "cp $filename $file\n"; 
+  `cp $filename $file\n`; 
+  `cp $filename tmp_$file\n`; 
+
+  #create and parse a new 'pdf' object
+  my $PDFfile = PDF->new($file);  
+
+  #if it is a pdf file
+  if ($PDFfile->{"Header"}){
+
+      if($PDFfile->IscryptPDF){
+	  #an encrypted file so cannot continue with
+	  #adding the related doc outlines to it 
+	  print STDERR "file \"$file\" is encrypted \n"; 
+	  return;
+      }
+
+      #display some relevant information about the document
+      print STDERR "Author: ", $PDFfile->GetInfo ("Author"), "\n"; 
+      print STDERR "Title: ", $PDFfile->GetInfo ("Title"), "\n"; 
+      print STDERR "Subject: ", $PDFfile->GetInfo ("Subject"), "\n"; 
+      print STDERR "Updated: ", $PDFfile->{"Updated"}, "\n";
+     
+      #if the pdf document already includes an outline dictionary
+      if (defined $PDFfile->{"Catalog"}{"/Outlines"}) {
+
+	  #get the outline object from the indirect ref
+	  my $outline_data = $PDFfile->GetObject($PDFfile->{"Catalog"}{"/Outlines"});
+	  #obtain the number of existing outlines
+	  $PDFfile->{"Outlines"}{"/Count"} = $outline_data->{"/Count"};
+	  print STDERR "number of existing outlines: $PDFfile->{\"Outlines\"}{\"/Count\"}\n";
+
+	  #this means that the pdf file had an outline dictionary but
+	  #did not actually include any outlines.
+	  if($PDFfile->{"Outlines"}{"/Count"} == 0){
+	      #obtain object number of outline dictionary and pass to add_outlines
+	      my $dictionary = split(/\s/, $PDFfile->{"Catalog"}{"/Outlines"});
+	     
+	      add_outlines($PDFfile, $file, $dictionary);
+	  } else { 
+	      #collect other outline data to pass to modify_outlines
+	      $PDFfile->{"Outlines"}{"/First"} = $outline_data->{"/First"};
+	      $PDFfile->{"Outlines"}{"/Last"} = $outline_data->{"/Last"};
+
+	      #modify last outline entry
+	      modify_outlines($outline_data, $PDFfile, $file);
+	  }
+      } else { #there was no outline dictionary thus no outlines so add some
+	  print STDERR "no bookmarks in \"$file\" \n"; 
+	  add_outlines($PDFfile, $file, 0);
+      }
+  } else { #the file was not a pdf file
+      print STDERR "$file is not a pdf file!!\n"; 
+  }
+
+
+  #copy back the file we modified and the saved copy 
+  my $copypath = join("/", @filelist);
+  print STDERR "cp $file $filename\n"; 
+  print STDERR "cp tmp_$file $copypath/tmp_$file\n"; 
+  `cp $file $filename\n`; 
+  `cp tmp_$file $copypath/tmp_$file\n`; 
+
+  #remove the copy of that file in this directory
+  #print STDERR "rm $file\n"; 
+  `rm $file\n`;  
+  `rm tmp_$file\n`; 
+}
+
+
+#add_outlines function recieves following params
+#PDF file information, filename of pdf file, outline dictionary
+#(if outline dict. is 0 that means it must be created).
+#First the function decides if we are to create new dictionary
+#or not. Next read in the url file. Open up the pdf document.
+#Modify the catalog so that it includes the outline dictionary
+#(this is done even if the catalog doesn't need modifying 
+# so that the objects in the objects/offset table will not
+# be all mucked up when it comes time to write the xreference
+# table)
+#Then append outline dictionary to end of file (either modified
+#or created). Then append the top heirarchy related document
+#outline.  Then the new file url bookmarks. Call  xref_table
+#to write new xreference table. Call trailer to write new trailer.
+
+#table[0][0] - document catalog
+#table[0][1] - document catalog offset
+#table[1][0] - outline dictionary
+#table[1][1] - outline dictionary offset
+#table[2][0] - related document outline
+#table[2][1] - related document outline offset
+#table[3][0] etc - url outlines, read from file
+#table[3][1] etc - url outlines offset, read from file
+
+sub add_outlines (*\$){
+    
+ my $PDFfile = shift; 
+ my $file = shift; 
+
+ my @table;
+ $table[1][$objects] = shift;
+
+ #read in file of url's
+ my @urls = read_file(); 
+ my $url_num = $#urls + 1;
+ 
+ #if outline dictionary was not present in catalog
+ if ($table[1][$objects] == 0){ #get new object number for new dictionary
+     $table[1][$objects] = $PDFfile->{"Trailer"}{"/Size"}; #outline dictionary to be created
+     $table[2][$objects] = $table[1][$objects] + 1; #related document outline
+ } else { #else get object number for related doc outline to be appended
+     $table[2][$objects] = $PDFfile->{"Trailer"}{"/Size"}; #related document outline
+ }
+ 
+ #open up pdf file for appending
+ open(FILE, ">> $file") or croak "can't open $file: $!"; 
+ binmode \*FILE;
+ 
+ #obtain object number and offset for the document catalog
+ $table[0][$objects] = split(/\s/, $PDFfile->{"Trailer"}{"/Root"});
+ $table[0][$offsets] = tell \*FILE;
+
+ #print the modified or original catalog back to the file (appended)
+ print FILE "$table[0][$objects] 0 obj
+";
+ print FILE "<<
+";
+ print FILE "/Pages $PDFfile->{\"Catalog\"}{\"/Pages\"}
+";
+ print FILE "/Outlines $table[1][$objects] 0 R
+"; #only line actually added
+ print FILE "/Type /Catalog
+";
+ print FILE "/DefaultGray $PDFfile->{\"Catalog\"}{\"/DefaultGray\"}
+"
+     if (defined ($PDFfile->{"Catalog"}{"/DefaultGray"}));
+ print FILE "/DefaultRGB $PDFfile->{\"Catalog\"}{\"/DefaultRGB\"}
+"
+     if (defined ($PDFfile->{"Catalog"}{"/DefaultRGB"}));
+ print FILE "/PageLabels $PDFfile->{\"Catalog\"}{\"/PageLabels\"}
+"
+     if (defined ($PDFfile->{"Catalog"}{"/PageLabels"}));
+ print FILE "/Names $PDFfile->{\"Catalog\"}{\"/Names\"}
+" 
+     if (defined ($PDFfile->{"Catalog"}{"/Names"}));
+ print FILE "/Dests $PDFfile->{\"Catalog\"}{\"/Dests\"}
+"
+     if (defined ($PDFfile->{"Catalog"}{"/Dests"}));
+ print FILE "/ViewerPreferences $PDFfile->{\"Catalog\"}{\"/ViewerPreferences\"}
+"
+     if (defined ($PDFfile->{"Catalog"}{"/ViewerPreferences"}));
+ print FILE "/PageLayout $PDFfile->{\"Catalog\"}{\"/PageLayout\"}
+"
+     if (defined ($PDFfile->{"Catalog"}{"/PageLayout"}));
+ print FILE "/PageMode $PDFfile->{\"Catalog\"}{\"/PageMode\"}
+"
+     if (defined ($PDFfile->{"Catalog"}{"/PageMode"}));
+ print FILE "/Threads $PDFfile->{\"Catalog\"}{\"/Threads\"}
+"
+     if (defined ($PDFfile->{"Catalog"}{"/Threads"}));
+ print FILE "/OpenAction $PDFfile->{\"Catalog\"}{\"/OpenAction\"}
+"
+     if (defined ($PDFfile->{"Catalog"}{"/OpenAction"}));
+ print FILE "/URI $PDFfile->{\"Catalog\"}{\"/URI\"}
+"
+     if (defined ($PDFfile->{"Catalog"}{"/URI"}));
+ print FILE "/Acroform $PDFfile->{\"Catalog\"}{\"/Acroform\"}
+"
+     if (defined ($PDFfile->{"Catalog"}{"/Acroform"}));
+ print FILE "/StructTreeRoot $PDFfile->{\"Catalog\"}{\"/StructTreeRoot\"}
+"
+     if (defined ($PDFfile->{"Catalog"}{"/StructTreeRoot"}));
+ print FILE "/SpiderInfo $PDFfile->{\"Catalog\"}{\"/SpiderInfo\"}
+"
+     if (defined ($PDFfile->{"Catalog"}{"/SpiderInfo"}));
+ print FILE ">>
+";
+ print FILE "endobj
+";
+ 
+ #obtain offset for outline dictionary
+ $table[1][$offsets] = tell \*FILE;
+
+ #append newly created outline dictionary
+ print FILE "$table[1][$objects] 0 obj
+";
+ print FILE "<<
+";
+ print FILE "/Type /Outlines
+";
+ print FILE "/Count ", $url_num + 1, "
+";
+ print FILE "/First $table[2][$objects] 0 R
+";
+ print FILE "/Last $table[2][$objects] 0 R
+";
+ print FILE ">>
+";
+ print FILE "endobj
+";
+
+
+ #get the related document outline object num and offset
+ my $obj = $table[2][$objects]; 
+ $table[2][$offsets] = tell \*FILE;
+
+ #append the top heirarchy related document outline to file 
+ print FILE "$table[2][$objects] 0 obj
+";
+ print FILE "<<
+";
+ print FILE "/Title (Related Documents)
+";
+ print FILE "/Parent $table[1][$objects] 0 R
+";
+ print FILE "/Count ", $url_num, "
+";
+ print FILE "/First ", $obj + 1, " 0 R
+";
+ print FILE "/Last ", $table[2][$objects] + $url_num, " 0 R
+";
+ print FILE ">>
+";
+ print FILE "endobj
+";
+
+ my $ind = 3;
+ $obj++;
+
+ 
+ #store the object nums and offsets of the new related document
+ #outlines and write them to the file (must be outline with
+ #an action eg go to specific url)
+ for $i ( 0 .. $#urls ) {
+     $table[$ind][$offsets] = tell \*FILE; 
+     $table[$ind][$objects] = $obj; 
+     print FILE "$obj 0 obj
+";
+     print FILE "<<
+";
+     print FILE "/Title ($urls[$i][0])
+"; 
+     print FILE "/Parent $table[2][$objects] 0 R
+";
+     print FILE "/Next ", $obj + 1, " 0 R
+" if (($obj + 1) <= ($table[2][$objects] + $url_num)); 
+     print FILE "/Prev ", $obj - 1, " 0 R
+" if(($obj - 1) != ($table[2][$objects]));
+     print FILE "/A << /Type /Action
+";
+     print FILE "/S /URI
+"; 
+     print FILE "/URI ($urls[$i][1])
+"; 
+     print FILE ">>
+";
+     print FILE ">>
+";
+     print FILE "endobj
+";
+     $obj++;
+     $ind++; 
+ }
+
+
+ #append new X-reference table 
+ my $xref_offset = tell \*FILE;
+ xref_table(\*FILE, $url_num, @table);
+
+ #print trailer 
+ trailer(\*FILE, $PDFfile, $obj); 
+ print FILE "$xref_offset
+";
+ print FILE "%%EOF
+"; 
+
+ #close FILE;
+}
+
+#modify_outlines function recieves following params
+#PDF file information, outline data, pdf filename
+#First the function obtains the object data for the
+#last outline entry. Next read in the url file. 
+#Open up the pdf document.Then append the modified 
+#outline dictionary to end of file. Next append the
+#modified last outline.  Then append the 
+#top heirarchy related document outline.  Then the 
+#new file url bookmarks. Call  xref_table
+#to write new xreference table. 
+#Call trailer to write new trailer.
+
+#table[0][0] - outline dictionary
+#table[0][1] - outline dictionary offset
+#table[1][0] - last outline
+#table[1][1] - last outline offset
+#table[2][0] - related document outline
+#table[2][1] - related document outline offset
+#table[3][0] etc - url outlines, read from file
+#table[3][1] etc - url outlines offset, read from file
+
+sub modify_outlines (*\$){
+
+    my ($outline_data, $PDFfile, $file) = @_;
+
+    #collect the data for the last outline (which must be modified)
+    $PDFfile->{"Outlines"}{"/Last"} = $outline_data->{"/Last"};
+    my $last_data = $PDFfile->GetObject($PDFfile->{"Outlines"}{"/Last"});  
+
+    #read in file of url's
+    my @urls = read_file(); 
+    my $url_num = $#urls + 1;
+ 
+    my @table;
+
+    #This number is the number to use for the next created object
+    #eg the related doc heirarchy
+    $table[2][$objects] = $PDFfile->{"Trailer"}{"/Size"};
+  
+    #open up the pdf file for appending
+    open(FILE, ">> $file") or croak "can't open $file: $!"; 
+    binmode \*FILE;
+    
+    #store the object number and offset of the outline dictionary
+    $table[0][$objects] = split(/\s/, $PDFfile->{"Catalog"}{"/Outlines"});
+    $table[0][$offsets] = tell \*FILE;
+   
+    #write the outline dictionary back to the file (appending)
+    print FILE "$table[0][$objects] 0 obj
+";
+    print FILE "<<
+";
+    print FILE "/Type /Outlines
+";
+    print FILE "/Count ", $PDFfile->{"Outlines"}{"/Count"} + 1, "
+"
+	if (defined ($PDFfile->{"Outlines"}{"/Count"}));
+    print FILE "/First $PDFfile->{\"Outlines\"}{\"/First\"}
+"
+	if (defined ($PDFfile->{"Outlines"}{"/First"}));
+    print FILE "/Last $table[2][$objects] 0 R
+";
+    print FILE ">>
+";
+    print FILE "endobj
+";
+    
+    #store the last outline entry object num and file offset
+    my @last_entry = split(/\s/, $PDFfile->{"Outlines"}{"/Last"});
+    $table[1][$objects] = $last_entry[0]; 
+    $table[1][$offsets] = tell \*FILE; 
+
+    #append modified last outline entry
+    print FILE "$table[1][$objects] 0 obj
+";
+    print FILE "<<
+";
+    print FILE "/Title $last_data->{\"/Title\"}
+";
+    print FILE "/Dest $last_data->{\"/Dest\"}
+" if(defined $last_data->{"/Dest"});
+    print FILE "/Parent $last_data->{\"/Parent\"}
+";
+    print FILE "/Prev $last_data->{\"/Prev\"}
+";
+    print FILE "/Next $table[2][$objects] 0 R
+";
+    print FILE "/First $last_data->{\"/First\"}
+" if(defined $last_data->{"/First"});
+    print FILE "/Last $last_data->{\"/Last\"}
+" if(defined $last_data->{"/Last"});
+    print FILE "/Count $last_data->{\"/Count\"}
+"if(defined $last_data->{"/Count"});
+    print FILE "/A $last_data->{\"/A\"}
+" if(defined $last_data->{"/A"});
+    print FILE "/SE $last_data->{\"/SE\"}
+" if(defined $last_data->{"/SE"});
+    print FILE ">>
+";
+    print FILE "endobj
+";
+    
+    #store the object num and offset of the related
+    #document top level outline
+    my $obj = $table[2][$objects] + 1;
+    $table[2][$offsets] = tell \*FILE;
+
+    #append related document top level outline
+    print FILE "$table[2][$objects] 0 obj
+";
+    print FILE "<<
+";
+    print FILE "/Title (Related Documents)
+"; 
+    print FILE "/Parent $last_data->{\"/Parent\"}
+";
+    print FILE "/Count ", $url_num, "
+";
+    print FILE "/First $obj 0 R
+";
+    print FILE "/Last ", $table[2][$objects] + $url_num , " 0 R
+";
+    print FILE ">>
+";
+    print FILE "endobj
+";
+    
+   
+    my $ind = 3;
+
+    #store the object nums and offsets of the new related document
+    #outlines and write them to the file (must be outline with
+    #an action eg go to specific url)
+    for $i ( 0 .. $#urls ) { 
+	$table[$ind][$objects] = $obj;  
+	$table[$ind][$offsets] = tell \*FILE; 
+	print FILE "$obj 0 obj
+";
+	print FILE "<<
+";
+	print FILE "/Title ($urls[$i][0])
+"; 
+	print FILE "/Parent $table[2][$objects] 0 R
+";
+	print FILE "/Next ", $obj + 1, " 0 R
+" if (($obj + 1) <= ($table[2][$objects] + $url_num)); 
+	print FILE "/Prev ", $obj - 1, " 0 R
+" if (($obj - 1) != ($table[2][$objects]));
+	print FILE "/A << /Type /Action
+";
+	print FILE "/S /URI
+"; 
+	print FILE "/URI ($urls[$i][1])
+"; 
+	print FILE ">>
+";
+	print FILE ">>
+";
+	print FILE "endobj
+";
+	$obj++;
+	$ind++;
+    }
+    
+    #append new X-reference table
+    my $xref_offset = tell \*FILE;   
+    xref_table(\*FILE, $url_num, @table); 
+  
+    #print trailer  
+    trailer(\*FILE, $PDFfile, $obj);
+    print FILE "$xref_offset
+";
+    print FILE "%%EOF
+"; 
+
+    close FILE;
+
+}
+
+
+#This function reads a file 'url.txt' which contains
+#two columns of data in the following format:
+#related document title    related document url
+#each array of title, url is stored in an array
+#(to obtain the title of the first related  
+#document in the file)
+#eg table[1st related document][title] 
+#(to obtain the url of the second related 
+#document in the file)
+#eg table[2nd related document][url]
+#this table is then returned to the calling 
+#function.
+sub read_file {
+
+    #create two-dimensional array for urls
+    my @urls;
+
+    #open up url.txt to start reading
+    open(URL, "$related_docs") or croak "Can't open $related_docs: $!"; 
+
+    my $counter = 0;
+
+    #read in url.txt and store into the arry
+    while (<URL>){
+	chomp;
+	if(/([^\t]*)\t(.*)/){ 
+	    push @urls, [ split ]; #split on /s into arrays of arrays
+	}
+    }
+
+    close URL;
+
+    return (@urls);
+
+}
+
+ 
+#this function takes as parameters the filehandle
+#to the pdf document, the number of related documents
+#to this pdf doc and a table of object numbers and
+#their offsets. Using this information it writes
+#(appends) a new xreference table to the pdf 
+#document. 
+
+sub xref_table  (*\$) {
+    
+    my ($fd, $num, @table) = @_;
+    my $offset;
+
+    #print the new xref table (append to file)
+    print $fd "xref
+";
+    print $fd "0 1 
+";
+    print $fd "0000000000 65535 f 
+";
+    print $fd "$table[0][$objects] 1 
+";
+    $offset = '0'x(10-length($table[0][$offsets])).$table[0][$offsets];
+    print $fd "$offset 00000 n 
+";
+    print $fd "$table[1][$objects] 1 
+"; 
+    $offset = '0'x(10-length($table[1][$offsets])).$table[1][$offsets];
+    print $fd "$offset 00000 n 
+";
+    print $fd "$table[2][$objects] ", $num + 1, " 
+"; 
+    for $i ( 2 .. ($num + 2) ) { #add 2 on because already written 2 to file
+	$offset = '0'x(10-length($table[$i][$offsets])).$table[$i][$offsets];
+	print $fd "$offset 00000 n 
+";
+    }
+    
+}
+
+
+#This function recieves as parameters the filehandle
+#to the pdf document, parsed information about the
+#document and the new size (last object number + 1)
+#of the pdf file.  Using this information it appends
+#a new trailer to the end of the pdf document.
+
+sub trailer  (*\$) {
+
+    my ($fd, $PDFfile, $new_size) = @_;
+
+    #append the new trailer to the end of the file
+    print $fd "trailer
+";
+    print $fd "<<
+";
+    print $fd "/Size ", $new_size, "
+";
+    print $fd "/Root $PDFfile->{\"Trailer\"}{\"/Root\"}
+";
+    print $fd "/Info $PDFfile->{\"Trailer\"}{\"/Info\"}
+" 
+	if (defined ($PDFfile->{"Trailer"}{"/Info"}));
+    print $fd "/ID [$PDFfile->{\"Trailer\"}{\"/ID\"}[0]$PDFfile->{\"Trailer\"}{\"/ID\"}[1]]
+"
+	if (defined ($PDFfile->{"Trailer"}{"/ID"}));
+    print $fd "/Prev $PDFfile->{\"Last_XRef_Offset\"}
+";
+    print $fd "/Encrypt $PDFfile->{\"Trailer\"}{\"/Encrypt\"}
+"
+	if (defined ($PDFfile->{"Trailer"}{"/Encrypt"}));
+    print $fd ">>
+";
+    print $fd "startxref
+";
+   
+}
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/indexes/buildkpi.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/indexes/buildkpi.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/indexes/buildkpi.pl	(revision 13928)
@@ -0,0 +1,491 @@
+#! /user/bin/perl 
+
+#usage: perl buildkpi.pl [-R] [collection] [collection] etc
+#
+#-r or -R will remove previous index files so that you may build new ones
+#
+#The program performs the following tasks:
+#-gathers the specified collections on the command line OR
+#-gathers the directories of all the collections in the collect directory, this is all
+# the directories apart from CVS, modelcol, . and .. which are not collections.
+#-It then retrieves the archive.inf file from the archive directory of each collection
+# to obtain the unique file ID and filepath of every document in the collection
+#-Then parse through each doc.gml stored in filepath to gather information
+#-From each file collect kea phrases and/or stems
+#-Determine the number of kea phrases and stems for each document 
+#-Search for the kea phrases in the numbered phrase index. If a phrase is not there then 
+# the program will write the kea phrase to the phrase index . 
+#-Search for the kea phrases in the keyphrase to document index. If the phrase is there, 
+# it will increment the number of documents that the keyphrase appears in and replace that
+# then append the hash ID to the list of documents in the entry. If the phrase is not there 
+# then the program will write the kea phrase to the phrase index.
+#-Then write document ID, no of phrase, phrase number from index followed by number of times 
+# phrase appears into the document_keyphrase index
+
+$gsdlhome = $ENV{'GSDLHOME'};
+
+require "getopts.pl";
+&Getopts('R'); #process option arguments
+
+
+#collections may be specified in the command line
+#otherwise, all collections will be used to build
+#the indexes.  
+if(@ARGV){
+
+    @directories = @ARGV;
+
+} else { #open collect directory and get a list of all collections
+    opendir(DIR, "$gsdlhome/collect");
+    @directories = grep(!/(^\.|(CVS)|(modelcol))/, readdir(DIR));
+    closedir(DIR);
+}
+
+
+#directory to store indexes in using collection names
+$dirname = "";
+foreach $collection (sort @directories){
+    $dirname .= $collection."_";
+}
+$dirname .= "indexes";
+print STDERR "directory name: $dirname\n";
+
+#if option R remove all previous indexes
+if($opt_R == 1){ #remove indexes
+    print STDERR "\nremoving $gsdlhome/bin/script/indexes/$dirname/keyphrase_index.txt\n";
+    print STDERR "removing $gsdlhome/bin/script/indexes/$dirname/keyphrase_document.txt\n";
+    print STDERR "removing $gsdlhome/bin/script/indexes/$dirname/document_keyphrase.txt\n";
+    system("rm $gsdlhome/bin/script/indexes/$dirname/keyphrase_document.txt");   
+    system("rm $gsdlhome/bin/script/indexes/$dirname/document_keyphrase.txt"); 
+    system("rm $gsdlhome/bin/script/indexes/$dirname/keyphrase_index.txt");
+} 
+
+#create the new directory, display an error message if the directory
+#already exists.
+`mkdir --verbose $gsdlhome/bin/script/indexes/$dirname`;
+
+#for each collection specified to build indexes for
+foreach $collection (@directories){
+
+    print STDERR "\nBUILDING INDEXES FOR COLLECTION $collection\n\n";
+
+    my @filelist;
+
+    #archives.inf contains a list of unique hash ID's of each file and file paths
+    open(INFO, "$gsdlhome/collect/$collection/archives/archives.inf")
+	or die "$gsdlhome/collect/$collection/archives/archives.inf could not be opened.";
+
+    while(<INFO>){ #get each line of text from archives.inf (OID \t filepath)
+	chomp;
+	push(@filelist, $_);
+    }
+
+    foreach $file (@filelist){ #add each document to the indexes
+	build_index($file, $collection);
+    }
+}
+
+#This function opens the file in the filepath sent as an argument.  From this it obtains 
+#the kea and/or stem data, and then searches for these phrases in the file, counting and storing 
+#how many times each phrase appears. The data is then sent to function keyphrase_document 
+#with arguments hash ID, kea phrases and stem phrases to build the keyphrase_document index.
+#The function which builds the document_keyphrase index is then passed the hash ID, the kea 
+#phrases and/or the stemmed phrases and the array/s which hold the number of times each phrase
+#appears in the document so that the data it has collected can be written to document_ keyphrase
+#index.
+
+sub build_index {
+
+    my $args = shift(@_);
+    my $collection = shift(@_);
+    my ($ID, $filepath) = split(/\t/, $args);
+    my $keaS = "";
+    my $stemsS = "";
+    my @kea_phrase_counts = 0;
+    my @stem_phrase_counts = 0;
+    my $text = "";
+
+    print STDERR "\nID: $ID\n";
+    print STDERR "filepath: $filepath\n";
+
+    #open file to extract keyphrase information
+    open(FILE, "$gsdlhome/collect/$collection/archives/$filepath")
+	or die "$gsdlhome/collect/$collection/archives/$filepath could not be opened.";
+
+    #patterns to search for so that we can extract the kea information
+    my $kea_search = ".* kea=\"([^\"]*)\"";
+    my $stem_search = "stems=\"([^\"]*)\"";
+
+    while(<FILE>){ #get kea and stem data and store
+	chomp;
+	$keaS = $1 if (/$kea_search/);
+	$stemsS = $1 if (/$stem_search/);
+    }
+
+    close(FILE);
+    
+    print STDERR "Kea: $keaS\n";
+    print STDERR "stems: $stemsS\n";
+
+    my @kea = split(", ", $keaS);
+    my @stems = split(", ", $stemsS);
+
+    if(@kea && @stems){ #if the data exists
+	
+	#open the filepath to the current document
+	open(FILE, "$gsdlhome/collect/$collection/archives/$filepath")
+	    or die "$gsdlhome/collect/$collection/archives/$filepath could not be opened.";
+	
+	while(<FILE>){ #get the text
+	    chomp;
+	    $text .= $_;
+	}
+ 
+	#chop out all things in angled brackets
+	$text =~ s/(<[^>]*>)//g;
+
+	#initilise counts
+	for($i=0; $i<=$#kea; $i++){
+	    $kea_phrase_counts[$i] = 0;
+	}
+	
+	for($i=0; $i<=$#stems; $i++){
+	    $stem_phrase_counts[$i] = 0;
+	}
+
+	print STDERR "counting number of kea phrases in document...\n";
+
+	#using regular expressions generated from kea-reg and stem-reg
+	#count how many of each phrase appear in the document
+	$text_copy = $text;
+	for($i=0; $i<=$#kea; $i++){ #search for text with kea phrases
+	    my $phrase = $kea[$i];
+	    $reg = &kea_reg(split(/\s+/, $phrase));
+	    while($text_copy =~ s/$reg//i){
+		$kea_phrase_counts[$i]++; #count the number of kea phrases 
+	    } 
+	    $text_copy = $text;
+	}  
+
+	print STDERR "counting number of stemmed phrases in document...\n";
+
+	$text_copy = $text;
+	for($i=0; $i<=$#stems; $i++){ #search for text with stem phrases
+	    my $stem = $stems[$i];
+	    $reg = &stem_reg(split(/\s+/, $stem));
+	    while($text_copy =~ s/$reg//i){
+		$stem_phrase_counts[$i]++; #count the number of stem phrases
+	    } 
+	    $text_copy = $text;
+	}
+
+	
+	#write data to keyphrase_document index
+	&keyphrase_document($ID, $keaS, $stemsS); 
+	
+	#write data to document_keyphrase index
+	$kea_counts = join(", ", @kea_phrase_counts);
+	$stem_counts = join(", ", @stem_phrase_counts);
+	&document_keyphrase($ID, $keaS, $stemsS, $kea_counts, $stem_counts);
+	
+    } else { 
+	print STDERR "No kea data was found in file $filepath\n";
+    }
+
+}
+
+#returns a regular expression designed to 
+#search for stems in text
+#eg 'agri cari'
+#    agri followed by 0 or more non-whitespace characters
+#         followed by one or more whitespace OR 0 or 1 non-whitespace characters
+#    cari followed by 0 or more non-whitespace characters
+#modified from original by Stephen Lundy 
+
+sub stem_reg {
+   
+    $regexp = "";
+
+    $l = @_;
+
+    if ($l > 0) {
+        $s = shift;
+        $regexp = "$s\\S*";
+
+        if ($l-1 > 0) {
+            foreach $s (@_) {
+                $regexp .= "(\\s+|\\S?)$s\\S*";
+            }
+        }
+    }
+
+    return $regexp;
+}
+
+#returns a regular expression designed to 
+#search for phrases in text
+#eg 'agris caris'
+#    agris followed by 0 or 1 non-whitespace characters OR
+#          followed by one or more whitespace 
+#    caris followed by 0 or 1 non-whitespace characters
+#modified from original by Stephen Lundy 
+
+sub kea_reg {
+    $regexp = "";
+
+    $l = @_;
+
+    if ($l > 0) {
+        $s = shift;
+        #$regexp = "$s(\\S?)";
+	$regexp = "$s(\\s+|\\S?)";
+
+        if ($l-1 > 0) {
+            foreach $s (@_) {
+                $regexp .= "$s(\\s+|\\S?)";
+            }
+        }
+    }
+
+    return $regexp;
+}
+
+
+#This function is passed as arguments a list of kea phrases and/or stems. Its purpose is to 
+#check in the keyphrase index file for each phrase and determine whether or not an entry has
+#been made for that phrase and an index number assigned to it. If there has not been an entry
+#made then an index number is assigned to the phrase and it is written to the file.  This 
+#function is called by document_keyphrase and keyphrase_document.  Each line in the file has
+#this form:
+#-phrase index number:phrase
+#This function then returns a table of pairs of the phrases that were sent as arguments to it
+#{phrase => phrase index number}.
+ 
+sub keyphrase_index_search {
+
+    my $phrases = shift(@_); 
+    my @phrases = split(", ", $phrases);
+    my %table;
+    my $index = 1;
+    my $create_new_index = 0;
+
+    print STDERR "searching keyphrase index...\n";
+
+    #initilise table of phrases and index numbers
+    foreach $phrase (@phrases){
+	$table{"$phrase"} = "0";
+    }
+
+    #open keyphrase index for appending data and for reading
+    open(INDEX_OUT, ">>$gsdlhome/bin/script/indexes/$dirname/keyphrase_index.txt");
+    open(INDEX_IN, "$gsdlhome/bin/script/indexes/$dirname/keyphrase_index.txt")
+	or $create_new_index = 1;
+
+    if($create_new_index == 0){
+	#if the index already exists read in the phrases
+	while(<INDEX_IN>){
+	    chomp;
+	    foreach $phrase (@phrases){
+		if(/(\d+):$phrase/){
+		    $index = $1;
+		    $table{"$phrase"} = "$index";
+		}
+	    }
+	    $index++; #new starting index (one + the last index)
+	}
+
+	close(INDEX_IN);
+
+    }
+
+    #add new phrases to the phrase index
+    foreach $phrase (keys %table){
+	if($table{"$phrase"} eq "0"){
+	    print INDEX_OUT "$index:$phrase\n";
+	    $table{"$phrase"} = "$index"; 
+	    $index++;
+	}
+    }
+
+    close(INDEX_OUT);
+    return %table;
+}
+
+#This function is passed as arguments file hash ID and a list of kea phrases and/or stems
+#that exist for that particular file.  Its purpose is to write to the keyphrase_document
+#index a line for the document it has been sent:
+#-phrase index number:number of documents it appears in|ID
+sub keyphrase_document{
+
+    my ($ID, $kea, $stems) = @_;
+    my $text = ""; 
+    my @textlist;
+    my $create_new_index = 0;
+
+    print STDERR "writing to keyphrase_document.txt...\n";
+
+    #get table of phrases and phrase indexes 
+    my %table = keyphrase_index_search($kea.", ".$stems); 
+    
+  
+    #open index for reading
+    open(INDEX_IN, "$gsdlhome/bin/script/indexes/$dirname/keyphrase_document.txt")
+	or $create_new_index = 1;
+
+    #read in document if file exists
+    if($create_new_index == 0){
+
+	while(<INDEX_IN>){
+	    $text .= $_;
+	}
+
+	close(INDEX_IN);
+
+	#split text into lines
+	@textlist = split(/\n/, $text);
+
+    } 
+
+    #open index for output
+    open(INDEX_OUT, ">$gsdlhome/bin/script/indexes/$dirname/keyphrase_document.txt");
+
+    if($create_new_index == 0){ #amend existing index
+	
+	foreach $line (@textlist){
+	    foreach $phrase (keys %table){
+		if($line =~ /(\d+):(\d+)(.*)/){ #all lines of this form
+		    $index = $1;
+		    if($table{"$phrase"} eq "$index") { #if phrase exists in index
+			$ids = $3; #get all doc IDs for that keyphrase
+			if($ids !~ /$ID/){ #if doc ID not already included
+			    $num_docs = $2;
+			    $num_docs++; #increment number of docs
+			    $line = "$index:$num_docs$3|$ID"; #line to append to index
+			    $table{"$phrase"} = "0"; 
+			}
+		    }
+		}
+	    }
+	    print INDEX_OUT "$line\n";
+	}
+    }
+
+    #add new phrases to the index
+    foreach $phrase (keys %table){ #write 'phrase index:1:file ID
+	if($table{"$phrase"} ne "0"){
+	    my $line = "$table{$phrase}:1:$ID";
+	    print INDEX_OUT "$line\n"; 
+	}
+    }
+
+    close(INDEX_OUT);
+
+}
+
+#This function is passed as arguments file hash ID and a list of kea phrases and/or stems
+#that exist for that particular file and a list of the number of times each kea and/or stem
+#phrase appear in that document.  Its purpose is to write to the document_keyphrase
+#index a line for the document it has been sent:
+#-file ID:number of phrases and/or stems appear in the document
+#      |pairs of 'phrase index,number of times the phrase appears in the document' 
+sub document_keyphrase {
+
+    my ($ID, $keaS, $stemsS, $kea_c, $stem_c) = @_;
+    my $text = "";
+    my @textlist;
+    my %phrases;
+    my $create_new_index = 0;
+
+    print STDERR "writing to document_keyphrase.txt...\n";
+
+    #split phrase counts into arrays
+    my @kea_counts = split(", ", $kea_c);
+    my @stem_counts = split(", ", $stem_c);
+  
+    #get table of phrases and phrase indexes
+    my %table = keyphrase_index_search($keaS.", ".$stemsS);
+
+    #split phrases into arrays
+    my @kea = split(", ", $keaS);
+    my @stems = split(", ", $stemsS);
+
+    #build new phrases dictionary
+    for($i=0; $i<=$#kea; $i++){
+	my $phrase = $table{"$kea[$i]"};
+	if($kea_counts[$i] > 0){
+	    $phrases{"$phrase"} = "$kea_counts[$i]";
+	} else {
+	    $phrases{"$phrase"} = 1;
+	}
+    } 
+    for($i=0; $i<=$#stems; $i++){
+	my $phrase = $table{"$stems[$i]"};
+	if($stem_counts[$i] > 0){
+	    $phrases{"$phrase"} = "$stem_counts[$i]";
+	} else {
+	    $phrases{"$phrase"} = 1;
+	}
+    }   
+    my @num = keys %phrases;
+    my $phrasenum = $#num + 1; #number of phrases in doc
+
+    #open index for reading
+    open(INDEX_IN, "$gsdlhome/bin/script/indexes/$dirname/document_keyphrase.txt")
+	or $create_new_index = 1;
+
+     
+    if($create_new_index == 0){ #index doesn't need to be created
+
+	while(<INDEX_IN>){
+	    $text .= $_;
+	}
+
+	close(INDEX_IN);
+	
+	#split text into lines
+	@textlist = split(/\n/, $text);
+
+    }  
+
+
+    #must write this line to the file
+    #document ID:num of phrases|phrase index, number of times phrases appears
+    my $newline = "$ID:$phrasenum";
+    foreach $phrase (keys %phrases){
+	$newline .= "|$phrase,$phrases{$phrase}";
+    }
+
+    #open index for output
+    open(INDEX_OUT, ">$gsdlhome/bin/script/indexes/$dirname/document_keyphrase.txt");
+
+    if($create_new_index == 1){ #create a new index
+
+	print INDEX_OUT "$newline\n";
+
+    } else {
+
+	#if ID is already in the file write line overtop incase
+	#someone has modified the file.  Otherwise add the line
+	#to the end of the file
+	my $found = 0;
+
+	foreach $line (@textlist){
+	    if($line =~ /([^:]+):(.*)/){ #all lines should follow this pattern
+		$id = $1;
+		if($ID eq $id){ #id is already in the file
+		    print INDEX_OUT "$newline\n"; #print line overtop
+		    $found = 1;
+		} else {
+		    print INDEX_OUT "$line\n"; #print old line out
+		}
+	    }
+	}
+
+	print INDEX_OUT "$newline\n" if ($found == 0); #append new line to end of file 
+
+    }
+
+    close(INDEX_OUT);
+
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/indexes/buildkpiK.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/indexes/buildkpiK.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/indexes/buildkpiK.pl	(revision 13928)
@@ -0,0 +1,411 @@
+#! /user/bin/perl 
+
+#usage: perl buildkpiK.pl [-R] [collection] [collection] etc
+#
+#-r or -R will remove previous index files so that you may build new ones
+#
+#The program performs the following tasks:
+#-gathers the specified collections on the command line OR
+#-gathers the directories of all the collections in the collect directory, this is all
+# the directories apart from CVS, modelcol, . and .. which are not collections.
+#-It then retrieves the archive.inf file from the archive directory of each collection
+# to obtain the unique file ID and filepath of every document in the collection
+#-Then parse through each doc.gml stored in filepath to gather information
+#-From each file collect kea phrases. 
+#-Determine the number of kea phrases for each document 
+#-Search for the kea phrases in the numbered phrase index. If a phrase is not there then 
+# the program will write the kea phrase to the phrase index . 
+#-Search for the kea phrases in the keyphrase to document index. If the phrase is there, 
+# it will increment the number of documents that the keyphrase appears in and replace that
+# then append the hash ID to the list of documents in the entry. If the phrase is not there 
+# then the program will write the kea phrase to the phrase index.
+#-Then write document ID, no of phrase, phrase number from index followed by number of times 
+# phrase appears into the document_keyphrase index
+
+$gsdlhome = $ENV{'GSDLHOME'};
+$collection;
+
+require "getopts.pl";
+&Getopts('R'); #process option arguments
+
+#if option R remove all previous indexes
+if($opt_R == 1){ #remove indexes
+    print STDERR "\nremoving $gsdlhome/bin/script/indexes/keyphrase_index.txt\n";
+    print STDERR "removing $gsdlhome/bin/script/indexes/keyphrase_document.txt\n";
+    print STDERR "removing $gsdlhome/bin/script/indexes/document_keyphrase.txt\n";
+    system("rm $gsdlhome/bin/script/indexes/keyphrase_document.txt");   
+    system("rm $gsdlhome/bin/script/indexes/document_keyphrase.txt"); 
+    system("rm $gsdlhome/bin/script/indexes/keyphrase_index.txt");
+}
+
+#collections may be specified in the command line
+#otherwise, all collections will be used to build
+#the indexes.  
+if(@ARGV){
+
+    @directories = @ARGV;
+
+} else { #open collect directory and get a list of all collections
+    opendir(DIR, "$gsdlhome/collect");
+    @directories = grep(!/(^\.|(CVS)|(modelcol))/, readdir(DIR));
+    closedir(DIR);
+}
+
+#for each collection specified to build indexes for
+foreach $collection (@directories){
+
+    my @filelist;
+
+    #archives.inf contains a list of unique hash ID's of each file and file paths
+    open(INFO, "$gsdlhome/collect/$collection/archives/archives.inf")
+	or die "$gsdlhome/collect/$collection/archives/archives.inf could not be opened.";
+
+    while(<INFO>){ #get each line of text from archives.inf (OID \t filepath)
+	chomp;
+	push(@filelist, $_);
+    }
+
+    foreach $file (@filelist){ #add each document to the indexes
+	build_index($file, $collection);
+    }
+}
+
+#This function opens the file in the filepath sent as an argument.  From this it obtains 
+#the kea data, and then searches for these phrases in the file, counting and storing 
+#how many times each phrase appears. The data is then sent to function keyphrase_document 
+#with arguments hash ID, kea phrases to build the keyphrase_document index.
+#The function which builds the document_keyphrase index is then passed the hash ID, the kea 
+#phrases and the array/s which hold the number of times each phrase
+#appears in the document so that the data it has collected can be written to document_ keyphrase
+#index.
+
+sub build_index {
+
+    my $args = shift(@_);
+    my $collection = shift(@_);
+    my ($ID, $filepath) = split(/\t/, $args);
+    my $keaS = "";
+    my @kea_phrase_counts = 0;
+    my $text = "";
+
+    print STDERR "\nID: $ID\n";
+    print STDERR "filepath: $filepath\n";
+
+    #open file to extract keyphrase information
+    open(FILE, "$gsdlhome/collect/$collection/archives/$filepath")
+	or die "$gsdlhome/collect/$collection/archives/$filepath could not be opened.";
+
+    #patterns to search for so that we can extract the kea information
+    my $kea_search = ".* kea=\"([^\"]*)\"";
+
+    while(<FILE>){ #get kea and stem data and store
+	chomp;
+	$keaS = $1 if (/$kea_search/);
+    }
+
+    close(FILE);
+    
+    print STDERR "Kea: $keaS\n";
+
+    my @kea = split(", ", $keaS);
+
+    if(@kea){ #if the data exists
+	
+	#open the filepath to the current document
+	open(FILE, "$gsdlhome/collect/$collection/archives/$filepath")
+	    or die "$gsdlhome/collect/$collection/archives/$filepath could not be opened.";
+	
+	while(<FILE>){ #get the text
+	    chomp;
+	    $text .= $_;
+	}
+ 
+	#chop out all things in angled brackets
+	$text =~ s/(<[^>]*>)//g;
+
+	#initilise counts
+	for($i=0; $i<=$#kea; $i++){
+	    $kea_phrase_counts[$i] = 0;
+	}
+	
+	
+	#using regular expressions generated from kea-reg 
+	#count how many of each phrase appear in the document
+	$text_copy = $text;
+	for($i=0; $i<=$#kea; $i++){ #search for text with kea phrases
+	    my $phrase = $kea[$i];
+	    $reg = &kea_reg(split(/\s+/, $phrase));
+	    while($text_copy =~ s/$reg//i){
+		$kea_phrase_counts[$i]++; #count the number of kea phrases 
+	    } 
+	    $text_copy = $text;
+	}  
+	
+	#write data to keyphrase_document index
+	&keyphrase_document($ID, $keaS); 
+	
+	#write data to document_keyphrase index
+	$kea_counts = join(", ", @kea_phrase_counts);
+	&document_keyphrase($ID, $keaS, $kea_counts);
+	
+    } else { 
+	print STDERR "No kea data was found in file $filepath\n";
+    }
+
+}
+
+
+#returns a regular expression designed to 
+#search for phrases in text
+#eg 'agris caris'
+#    agris followed by 0 or 1 non-whitespace characters OR
+#          followed by one or more whitespace 
+#    caris followed by 0 or 1 non-whitespace characters
+#modified from original by Stephen Lundy 
+
+sub kea_reg {
+    $regexp = "";
+
+    $l = @_;
+
+    if ($l > 0) {
+        $s = shift;
+        #$regexp = "$s(\\S?)";
+	$regexp = "$s(\\s+|\\S?)";
+
+        if ($l-1 > 0) {
+            foreach $s (@_) {
+                $regexp .= "$s(\\s+|\\S?)";
+            }
+        }
+    }
+
+    return $regexp;
+}
+
+
+#This function is passed as arguments a list of kea phrases and/or stems. Its purpose is to 
+#check in the keyphrase index file for each phrase and determine whether or not an entry has
+#been made for that phrase and an index number assigned to it. If there has not been an entry
+#made then an index number is assigned to the phrase and it is written to the file.  This 
+#function is called by document_keyphrase and keyphrase_document.  Each line in the file has
+#this form:
+#-phrase index number:phrase
+#This function then returns a table of pairs of the phrases that were sent as arguments to it
+#{phrase => phrase index number}.
+ 
+sub keyphrase_index_search {
+
+    my $phrases = shift(@_);
+    my @phrases = split(", ", $phrases);
+    my %table;
+    my $index = 1;
+    my $create_new_index = 0;
+
+    print STDERR "searching keyphrase index...\n";
+
+    #initilise table of phrases and index numbers
+    foreach $phrase (@phrases){
+	$table{"$phrase"} = "0";
+    }
+
+    #open keyphrase index for appending data and for reading
+    open(INDEX_OUT, ">>$gsdlhome/bin/script/indexes/keyphrase_index.txt");
+    open(INDEX_IN, "$gsdlhome/bin/script/indexes/keyphrase_index.txt")
+	or $create_new_index = 1;
+
+    if($create_new_index == 0){
+	#if the index already exists read in the phrases
+	while(<INDEX_IN>){
+	    chomp;
+	    foreach $phrase (@phrases){
+		if(/(\d+):$phrase/){
+		    $index = $1;
+		    $table{"$phrase"} = "$index";
+		}
+	    }
+	    $index++; #new starting index (one + the last index)
+	}
+
+	close(INDEX_IN);
+
+    }
+
+    #add new phrases to the phrase index
+    foreach $phrase (keys %table){
+	if($table{"$phrase"} eq "0"){
+	    print INDEX_OUT "$index:$phrase\n";
+	    $table{"$phrase"} = "$index"; 
+	    $index++;
+	}
+    }
+
+    close(INDEX_OUT);
+    return %table;
+}
+
+#This function is passed as arguments file hash ID and a list of kea phrases
+#that exist for that particular file.  Its purpose is to write to the keyphrase_document
+#index a line for the document it has been sent:
+#-phrase index number:number of documents it appears in|ID
+sub keyphrase_document{
+
+    my ($ID, $kea) = @_;
+    my $text = ""; 
+    my @textlist;
+    my $create_new_index = 0;
+
+    print STDERR "writing to keyphrase_document.txt...\n";
+
+    #get table of phrases and phrase indexes 
+    my %table = keyphrase_index_search($kea); 
+    
+  
+    #open index for reading
+    open(INDEX_IN, "$gsdlhome/bin/script/indexes/keyphrase_document.txt")
+	or $create_new_index = 1;
+
+    #read in document if file exists
+    if($create_new_index == 0){
+
+	while(<INDEX_IN>){
+	    $text .= $_;
+	}
+
+	close(INDEX_IN);
+
+	#split text into lines
+	@textlist = split(/\n/, $text);
+
+    } 
+
+    #open index for output
+    open(INDEX_OUT, ">$gsdlhome/bin/script/indexes/keyphrase_document.txt");
+
+    if($create_new_index == 0){ #amend existing index
+	
+	foreach $line (@textlist){
+	    foreach $phrase (keys %table){
+		if($line =~ /(\d+):(\d+)(.*)/){ #all lines of this form
+		    $index = $1;
+		    if($table{"$phrase"} eq "$index") { #if phrase exists in index
+			$ids = $3; #get all doc IDs for that keyphrase
+			if($ids !~ /$ID/){ #if doc ID not already included
+			    $num_docs = $2;
+			    $num_docs++; #increment number of docs
+			    $line = "$index:$num_docs$3|$ID"; #line to append to index
+			    $table{"$phrase"} = "0"; 
+			}
+		    }
+		}
+	    }
+	    print INDEX_OUT "$line\n";
+	}
+    }
+
+    #add new phrases to the index
+    foreach $phrase (keys %table){ #write 'phrase index:1:file ID
+	if($table{"$phrase"} ne "0"){
+	    my $line = "$table{$phrase}:1:$ID";
+	    print INDEX_OUT "$line\n"; 
+	}
+    }
+
+    close(INDEX_OUT);
+
+}
+
+#This function is passed as arguments file hash ID and a list of kea phrases and/or stems
+#that exist for that particular file and a list of the number of times each kea and/or stem
+#phrase appear in that document.  Its purpose is to write to the document_keyphrase
+#index a line for the document it has been sent:
+#-file ID:number of phrases and/or stems appear in the document
+#      |pairs of 'phrase index,number of times the phrase appears in the document' 
+sub document_keyphrase {
+
+    my ($ID, $keaS, $kea_c) = @_;
+    my $text = "";
+    my @textlist;
+    my %phrases;
+    my $create_new_index = 0;
+
+    print STDERR "writing to document_keyphrase.txt...\n";
+
+    #split phrase counts into arrays
+    my @kea_counts = split(", ", $kea_c);
+  
+    #get table of phrases and phrase indexes
+    my %table = keyphrase_index_search($keaS);
+
+    #split phrases into arrays
+    my @kea = split(", ", $keaS);
+
+    #build new phrases dictionary
+    for($i=0; $i<=$#kea; $i++){
+	my $phrase = $table{"$kea[$i]"};
+	$phrases{"$phrase"} = "$kea_counts[$i]";
+    } 
+   
+    my @num = keys %phrases;
+    my $phrasenum = $#num + 1; #number of phrases in doc
+
+    #open index for reading
+    open(INDEX_IN, "$gsdlhome/bin/script/indexes/document_keyphrase.txt")
+	or $create_new_index = 1;
+
+     
+    if($create_new_index == 0){ #index doesn't need to be created
+
+	while(<INDEX_IN>){
+	    $text .= $_;
+	}
+
+	close(INDEX_IN);
+	
+	#split text into lines
+	@textlist = split(/\n/, $text);
+
+    }  
+
+
+    #must write this line to the file
+    #'document ID:num of phrases|phrase index, number of times phrases appears
+    my $newline = "$ID:$phrasenum";
+    foreach $phrase (keys %phrases){
+	$newline .= "|$phrase,$phrases{$phrase}";
+    }
+
+    #open index for output
+    open(INDEX_OUT, ">$gsdlhome/bin/script/indexes/document_keyphrase.txt");
+
+    if($create_new_index == 1){ #create a new index
+
+	print INDEX_OUT "$newline\n";
+
+    } else {
+
+	#if ID is already in the file write line overtop incase
+	#someone has modified the file.  Otherwise add the line
+	#to the end of the file
+	my $found = 0;
+
+	foreach $line (@textlist){
+	    if($line =~ /([^:]+):(.*)/){ #all lines should follow this pattern
+		$id = $1;
+		if($ID eq $id){ #id is already in the file
+		    print INDEX_OUT "$newline\n"; #print line overtop
+		    $found = 1;
+		} else {
+		    print INDEX_OUT "$line\n"; #print old line out
+		}
+	    }
+	}
+
+	print INDEX_OUT "$newline\n" if ($found == 0); #append new line to end of file 
+
+    }
+
+    close(INDEX_OUT);
+
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/indexes/buildkpiS.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/indexes/buildkpiS.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/indexes/buildkpiS.pl	(revision 13928)
@@ -0,0 +1,420 @@
+#! /user/bin/perl 
+
+#usage: perl buildkpiS.pl [-R] [collection] [collection] etc
+#
+#-r or -R will remove previous index files so that you may build new ones
+#
+#The program performs the following tasks:
+#-gathers the specified collections on the command line OR
+#-gathers the directories of all the collections in the collect directory, this is all
+# the directories apart from CVS, modelcol, . and .. which are not collections.
+#-It then retrieves the archive.inf file from the archive directory of each collection
+# to obtain the unique file ID and filepath of every document in the collection
+#-Then parse through each doc.gml stored in filepath to gather information
+#-From each file collect stems of kea keyphrases.
+#-Determine the number of keyphrase stems for each document 
+#-Search for the keyphrase stems in the numbered phrase index. If a phrase is not there then 
+# the program will write the keyphrase stem to the phrase index . 
+#-Search for the keyphrase stem in the keyphrase to document index. If the stem is there, 
+# it will increment the number of documents that the keyphrase stem appears in and replace that
+# then append the hash ID to the list of documents in the entry. If the stem is not there 
+# then the program will write the stem to the phrase index.
+#-Then write document ID, no of phrase, phrase number from index followed by number of times 
+# phrase appears into the document_keyphrase index
+
+$gsdlhome = $ENV{'GSDLHOME'};
+$collection;
+
+require "getopts.pl";
+&Getopts('R'); #process option arguments
+
+#if option R remove all previous indexes
+if($opt_R == 1){ #remove indexes
+    print STDERR "\nremoving $gsdlhome/bin/script/indexes/keyphrase_index.txt\n";
+    print STDERR "removing $gsdlhome/bin/script/indexes/keyphrase_document.txt\n";
+    print STDERR "removing $gsdlhome/bin/script/indexes/document_keyphrase.txt\n";
+    system("rm $gsdlhome/bin/script/indexes/keyphrase_document.txt");   
+    system("rm $gsdlhome/bin/script/indexes/document_keyphrase.txt"); 
+    system("rm $gsdlhome/bin/script/indexes/keyphrase_index.txt");
+}
+
+#collections may be specified in the command line
+#otherwise, all collections will be used to build
+#the indexes.  
+if(@ARGV){
+
+    @directories = @ARGV;
+
+} else { #open collect directory and get a list of all collections
+    opendir(DIR, "$gsdlhome/collect");
+    @directories = grep(!/(^\.|(CVS)|(modelcol))/, readdir(DIR));
+    closedir(DIR);
+}
+
+#for each collection specified to build indexes for
+foreach $collection (@directories){
+
+    my @filelist;
+
+    #archives.inf contains a list of unique hash ID's of each file and file paths
+    open(INFO, "$gsdlhome/collect/$collection/archives/archives.inf")
+	or die "$gsdlhome/collect/$collection/archives/archives.inf could not be opened.";
+
+    while(<INFO>){ #get each line of text from archives.inf (OID \t filepath)
+	chomp;
+	push(@filelist, $_);
+    }
+
+    foreach $file (@filelist){ #add each document to the indexes
+	build_index($file, $collection);
+    }
+}
+
+#This function opens the file in the filepath sent as an argument.  From this it obtains 
+#the kea and/or stem data, and then searches for these phrases in the file, counting and storing 
+#how many times each phrase appears. The data is then sent to function keyphrase_document 
+#with arguments hash ID, kea phrases and stem phrases to build the keyphrase_document index.
+#The function which builds the document_keyphrase index is then passed the hash ID, the kea 
+#phrases and/or the stemmed phrases and the array/s which hold the number of times each phrase
+#appears in the document so that the data it has collected can be written to document_ keyphrase
+#index.
+
+sub build_index {
+
+    my $args = shift(@_);
+    my $collection = shift(@_);
+    my ($ID, $filepath) = split(/\t/, $args);
+    my $stemsS = "";
+    my @stem_phrase_counts = 0;
+    my $text = "";
+
+    print STDERR "\nID: $ID\n";
+    print STDERR "filepath: $filepath\n";
+
+    #open file to extract keyphrase information
+    open(FILE, "$gsdlhome/collect/$collection/archives/$filepath")
+	or die "$gsdlhome/collect/$collection/archives/$filepath could not be opened.";
+
+    #patterns to search for so that we can extract the kea information
+    my $stem_search = "stems=\"([^\"]*)\"";
+
+    while(<FILE>){ #get kea and stem data and store
+	chomp;
+	$stemsS = $1 if (/$stem_search/);
+    }
+
+    close(FILE);
+    
+    print STDERR "stems: $stemsS\n";
+
+    my @stems = split(", ", $stemsS);
+
+    if(@stems){ #if the data exists
+	
+	#open the filepath to the current document
+	open(FILE, "$gsdlhome/collect/$collection/archives/$filepath")
+	    or die "$gsdlhome/collect/$collection/archives/$filepath could not be opened.";
+	
+	while(<FILE>){ #get the text
+	    chomp;
+	    $text .= $_;
+	}
+ 
+	#chop out all things in angled brackets
+	$text =~ s/(<[^>]*>)//g;
+
+	#initilise counts
+	for($i=0; $i<=$#stems; $i++){
+	    $stem_phrase_counts[$i] = 0;
+	}
+	
+	#using regular expressions generated from stem-reg
+	#count how many of each phrase appear in the document
+	
+	$text_copy = $text;
+	for($i=0; $i<=$#stems; $i++){ #search for text with stem phrases
+	    my $stem = $stems[$i];
+	    $reg = &stem_reg(split(/\s+/, $stem));
+	    while($text_copy =~ s/$reg//i){
+		$stem_phrase_counts[$i]++; #count the number of stem phrases
+	    } 
+	    $text_copy = $text;
+	}
+
+	
+	#write data to keyphrase_document index
+	&keyphrase_document($ID, $stemsS); 
+	
+	#write data to document_keyphrase index
+	$stem_counts = join(", ", @stem_phrase_counts);
+	&document_keyphrase($ID, $stemsS, $stem_counts);
+	
+    } else { 
+	print STDERR "No stem data was found in file $filepath\n";
+    }
+
+}
+
+#returns a regular expression designed to 
+#search for stems in text
+#eg 'agri cari'
+#    agri followed by 0 or more non-whitespace characters
+#         followed by one or more whitespace OR 0 or 1 non-whitespace characters
+#    cari followed by 0 or more non-whitespace characters
+#modified from original by Stephen Lundy 
+
+sub stem_reg {
+   
+    $regexp = "";
+
+    $l = @_;
+
+    if ($l > 0) {
+        $s = shift;
+        $regexp = "$s\\S*";
+
+        if ($l-1 > 0) {
+            foreach $s (@_) {
+                $regexp .= "(\\s+|\\S?)$s\\S*";
+            }
+        }
+    }
+
+    return $regexp;
+}
+
+
+
+#This function is passed as arguments a list of kea phrase stems. Its purpose is to 
+#check in the keyphrase index file for each phrase and determine whether or not an entry has
+#been made for that phrase and an index number assigned to it. If there has not been an entry
+#made then an index number is assigned to the phrase and it is written to the file.  This 
+#function is called by document_keyphrase and keyphrase_document.  Each line in the file has
+#this form:
+#-phrase index number:phrase
+#This function then returns a table of pairs of the phrases that were sent as arguments to it
+#{phrase => phrase index number}.
+ 
+sub keyphrase_index_search {
+
+    my $phrases = shift(@_);
+    my @phrases = split(", ", $phrases);
+    my %table;
+    my $index = 1;
+    my $create_new_index = 0;
+
+    print STDERR "searching keyphrase index...\n";
+
+    #initilise table of phrases and index numbers
+    foreach $phrase (@phrases){
+	$table{"$phrase"} = "0";
+    }
+
+    #open keyphrase index for appending data and for reading
+    open(INDEX_OUT, ">>$gsdlhome/bin/script/indexes/keyphrase_index.txt");
+    open(INDEX_IN, "$gsdlhome/bin/script/indexes/keyphrase_index.txt")
+	or $create_new_index = 1;
+
+    if($create_new_index == 0){
+	#if the index already exists read in the phrases
+	while(<INDEX_IN>){
+	    chomp;
+	    foreach $phrase (@phrases){
+		if(/(\d+):$phrase/){
+		    $index = $1;
+		    $table{"$phrase"} = "$index";
+		}
+	    }
+	    $index++; #new starting index (one + the last index)
+	}
+
+	close(INDEX_IN);
+
+    }
+
+    #add new phrases to the phrase index
+    foreach $phrase (keys %table){
+	if($table{"$phrase"} eq "0"){
+	    print INDEX_OUT "$index:$phrase\n";
+	    $table{"$phrase"} = "$index"; 
+	    $index++;
+	}
+    }
+
+    close(INDEX_OUT);
+    return %table;
+}
+
+#This function is passed as arguments file hash ID and a list of kea phrases and/or stems
+#that exist for that particular file.  Its purpose is to write to the keyphrase_document
+#index a line for the document it has been sent:
+#-phrase index number:number of documents it appears in|ID
+sub keyphrase_document{
+
+    my ($ID, $stems) = @_;
+    my $text = ""; 
+    my @textlist;
+    my $create_new_index = 0;
+
+    print STDERR "writing to keyphrase_document.txt...\n";
+
+    #get table of phrases and phrase indexes 
+    my %table = keyphrase_index_search($stems); 
+    
+  
+    #open index for reading
+    open(INDEX_IN, "$gsdlhome/bin/script/indexes/keyphrase_document.txt")
+	or $create_new_index = 1;
+
+    #read in document if file exists
+    if($create_new_index == 0){
+
+	while(<INDEX_IN>){
+	    $text .= $_;
+	}
+
+	close(INDEX_IN);
+
+	#split text into lines
+	@textlist = split(/\n/, $text);
+
+    } 
+
+    #open index for output
+    open(INDEX_OUT, ">$gsdlhome/bin/script/indexes/keyphrase_document.txt");
+
+    if($create_new_index == 0){ #amend existing index
+	
+	foreach $line (@textlist){
+	    foreach $phrase (keys %table){
+		if($line =~ /(\d+):(\d+)(.*)/){ #all lines of this form
+		    $index = $1;
+		    if($table{"$phrase"} eq "$index") { #if phrase exists in index
+			$ids = $3; #get all doc IDs for that keyphrase
+			if($ids !~ /$ID/){ #if doc ID not already included
+			    $num_docs = $2;
+			    $num_docs++; #increment number of docs
+			    $line = "$index:$num_docs$3|$ID"; #line to append to index
+			    $table{"$phrase"} = "0"; 
+			}
+		    }
+		}
+	    }
+	    print INDEX_OUT "$line\n";
+	}
+    }
+
+    #add new phrases to the index
+    foreach $phrase (keys %table){ #write 'phrase index:1:file ID
+	if($table{"$phrase"} ne "0"){
+	    my $line = "$table{$phrase}:1:$ID";
+	    print INDEX_OUT "$line\n"; 
+	}
+    }
+
+    close(INDEX_OUT);
+
+}
+
+#This function is passed as arguments file hash ID and a list of kea phrase stems
+#that exist for that particular file and a list of the number of times each stem
+#phrase appear in that document.  Its purpose is to write to the document_keyphrase
+#index a line for the document it has been sent:
+#-file ID:number of phrases and/or stems appear in the document
+#      |pairs of 'phrase index,number of times the phrase appears in the document' 
+sub document_keyphrase {
+
+    my ($ID, $stemsS, $stem_c) = @_;
+    my $text = "";
+    my @textlist;
+    my %phrases;
+    my $create_new_index = 0;
+
+    print STDERR "writing to document_keyphrase.txt...\n";
+
+    #split phrase counts into arrays
+    my @stem_counts = split(", ", $stem_c);
+  
+    #get table of phrases and phrase indexes
+    my %table = keyphrase_index_search($stemsS);
+
+    #split phrases into arrays
+    my @stems = split(", ", $stemsS);
+
+    #build new phrases dictionary
+    for($i=0; $i<=$#stems; $i++){
+	my $phrase = $table{"$stems[$i]"};
+	$phrases{"$phrase"} = "$stem_counts[$i]";
+    }   
+    my @num = keys %phrases;
+    my $phrasenum = $#num + 1; #number of phrases in doc
+
+    #open index for reading
+    open(INDEX_IN, "$gsdlhome/bin/script/indexes/document_keyphrase.txt")
+	or $create_new_index = 1;
+
+     
+    if($create_new_index == 0){ #index doesn't need to be created
+
+	while(<INDEX_IN>){
+	    $text .= $_;
+	}
+
+	close(INDEX_IN);
+	
+	#split text into lines
+	@textlist = split(/\n/, $text);
+
+    }  
+
+
+    #must write this line to the file
+    #'document ID:num of phrases|phrase index, number of times phrases appears
+    my $newline = "$ID:$phrasenum";
+    foreach $phrase (keys %phrases){
+	$newline .= "|$phrase,$phrases{$phrase}";
+    }
+
+    #open index for output
+    open(INDEX_OUT, ">$gsdlhome/bin/script/indexes/document_keyphrase.txt");
+
+    if($create_new_index == 1){ #create a new index
+
+	print INDEX_OUT "$newline\n";
+
+    } else {
+
+	#if ID is already in the file write line overtop incase
+	#someone has modified the file.  Otherwise add the line
+	#to the end of the file
+	my $found = 0;
+
+	foreach $line (@textlist){
+	    if($line =~ /([^:]+):(.*)/){ #all lines should follow this pattern
+		$id = $1;
+		if($ID eq $id){ #id is already in the file
+		    print INDEX_OUT "$newline\n"; #print line overtop
+		    $found = 1;
+		} else {
+		    print INDEX_OUT "$line\n"; #print old line out
+		}
+	    }
+	}
+
+	print INDEX_OUT "$newline\n" if ($found == 0); #append new line to end of file 
+
+    }
+
+    close(INDEX_OUT);
+
+}
+
+
+
+
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/indexes/relation.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/indexes/relation.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/indexes/relation.pl	(revision 13928)
@@ -0,0 +1,414 @@
+#!/usr/bin/perl
+
+#data structures used:
+#-document_keyphrase
+#%document_phrases = ("hashID" => {"phrase" => "number of occurrences"})
+#-keyphrase_document 
+#%phrases_document = ("phrase" => "no. of docs phrase occurs in")
+
+#after calculation relational data, it will amend gml files
+#to include this data while writing to a file ID_relatedlinks.txt
+#the html links of the related files
+#if option p is set then the user wishes to add the related documents
+#as bookmarks to the pdf file
+
+require "getopts.pl";
+&Getopts('N:P'); #process option arguments
+
+
+$gsdlhome = $ENV{'GSDLHOME'};
+@directories; #list of directories for the collections
+%phrases_document; #hash storing phrase index => no. of documents with phrase in it
+%document_phrases; #hash of hashes ID => {phrase number => no. of phrases in ID}
+$N = 0; #number of documents in the index (presumably in the collection)
+%cosine_matrix; #2-dimensional matrix, for each pair of documents stores a cosine measure
+$number_of_files = 1; #by default the top related file is returned
+$do_pdfs = 0;
+
+if($opt_N =~ /(\d)+/){ #if flag is set then return top N docs
+    $number_of_files = $opt_N;
+}
+
+#get server name and httpprefix
+$httpprefix;
+$servername = "nzdl2.cs.waikato.ac.nz"; #should be localhost
+
+if($opt_P == 1){ #if flag is set 
+    $do_pdfs = 1;
+    
+    #get the httpprefix from gsdlsite.cfg
+    open(CFG, "$gsdlhome/cgi-bin/gsdlsite.cfg") 
+	or die "$gsdlhome/cgi-bin/gsdlsite.cfg could not be opened";
+    
+    while(<CFG>){
+	chomp;
+	if(/httpprefix \/(.+)/){
+	    $httpprefix = $1; 
+	}
+    }
+    close CFG;
+}
+
+if(@ARGV){
+
+    @directories = @ARGV;
+
+} else { #open collect directory and get a list of all collections
+    opendir(DIR, "$gsdlhome/collect");
+    @directories = grep(!/(^\.|(CVS)|(modelcol))/, readdir(DIR));
+    closedir(DIR);
+}
+
+
+
+#get the name of the directory the index will be stored in
+$dirname = "";
+foreach $collection (sort @directories){
+    $dirname .= $collection."_";
+}
+$dirname .= "indexes";
+print STDERR "directory name: $dirname\n";
+
+#open keyphrases_document.txt
+open(KEY_FILE, "$gsdlhome/bin/script/indexes/$dirname/keyphrase_document.txt") 
+    or die "$gsdlhome/bin/script/indexes/$dirname/keyphrase_document.txt could not be opened";
+
+print STDERR "\nreading keyphrase_document.txt...\n";
+
+#read a list of phrase indexes and number of documents that phrase appears in 
+while(<KEY_FILE>){
+    chomp;
+    if(/(\d+)\:(\d+)(.*)/){ #all lines should be of this form
+	my $phrase_index = $1;
+	my $doc_num = $2;
+	$phrases_document{"$phrase_index"} = "$doc_num"; #build keyphrase hash
+    }
+}
+
+close(KEY_FILE); 
+
+print STDERR "\nreading document_keyphrase.txt...\n";
+
+#open document_keyphrases.txt
+open(DOC_FILE, "$gsdlhome/bin/script/indexes/$dirname/document_keyphrase.txt") 
+    or die "$gsdlhome/bin/script/indexes/$dirname/document_keyphrase.txt could not be opened";
+
+#read a list of documents and the phrases that appear in them (& how many times they appear)
+while(<DOC_FILE>){
+    chomp;
+    my %document;
+    if(/(\w+)\:(\d+)((\|\d+,\d+)+)/){ #every line in the index of this form
+	my $ID = $1;
+	my $pairs = $3;
+	while ($pairs =~ s/\|(\d+),(\d+)//) { #this is the list of keyphrases and numbers
+	    my $phrase_index = $1;
+	    my $num_phrase = $2;
+	    $document{"$phrase_index"} = "$num_phrase"; #table to be stored in another table
+	}
+	$document_phrases{"$ID"} = ({%document});	  
+	$N++; #number of documents in the collection (which have kea metadata)
+    }
+}
+
+close(DOC_FILE);
+ 
+#we do not want to recalculate measures ie if we have already calculated
+#doc1 & doc2 we do not then want to calculate doc2 & doc1
+#to achieve this we must first sort the list of ids so that both lists
+#of documents will be in the same order (otherwise hash tables return values in 
+#no particular order). We then compare each document in the left 
+#column below against the documents in the right column:
+
+#doc0 -> 
+#doc1 -> doc0 
+#doc2 -> doc0, doc 1 
+#doc3 -> doc0, doc 1, doc 2 
+#doc4 -> doc0, doc 1, doc 2, doc 3 
+#doc5 -> doc0, doc 1, doc 2, doc 3, doc 4 
+#etc
+
+#this way we are not recalculating the same value and also not
+#comparing each document to itself (which would result in the
+#value 1) thus more than halving the processing time.
+
+print STDERR "\ncalculating cosine measures for $N documents...\n";
+
+$count = 0;
+@ids = sort keys(%document_phrases);
+
+#repeat for all pairs of documents
+foreach $id1 (sort keys(%document_phrases)) { 
+    my %table;
+   
+    for($i=0; $i<$count; $i++){ #calculate the cosine measure and store
+	my $cosine_measure = &compare_docs($id1, $ids[$i]); 
+	$table{"$ids[$i]"} = "$cosine_measure";  	
+    }
+    $cosine_matrix{"$id1"} = ({%table});
+    $count++; #each iteration the number of documents to compare against expands by 1
+}
+
+&addtogml(); #add the relational data we have just gathered to the documents gml files
+
+   
+#this function takes as an argument two document IDs and uses these to extract the
+#keyphrases from the document_keyphrase data structure.  It then calculates a 
+#'measure of relativity' [0-1] with which we can establish how similar the two
+#documents are to each other. (0-not related, 1-same document).  The equation 
+#used to establish this similarity:
+#
+#                     for all phrases 
+#                     in both d1, d2 (fd1p * loge(N/fp) (fd2p * loge(N/fp) 
+#  cosine(d1, d2) = --------------------------------------------------------------
+#                     sqrt(sum of phrases in d1(fd1p * loge(N/fp))) * 
+#                     sqrt(sum of phrases in d2(fd2p * loge(N/fp))) 
+#
+#where d1 and d2 are lists of keyphrase and represent documents
+#fd1p is the frequency that phrase p occurs in document d1
+#fd2p is the frequency that phrase p occurs in document d2
+#fp is the number of documents that have p as a keyphrase
+#N is the number of documents in the collection 
+sub compare_docs {
+
+  
+    my $ID1 = shift(@_); #ID for document one 
+    my $ID2 = shift(@_); #ID for document two
+  
+    my @phrases; #a list of phrases in document 1 and document 2
+    my @phrases1; #a list of phrases in document 1
+    my @phrases2; #a list of phrases in document 2
+    
+    
+    foreach $phrase (keys %{ $document_phrases{$ID1}}) { #list of phrases in doc1
+	push(@phrases1, $phrase);
+    } 
+    foreach $phrase (keys %{ $document_phrases{$ID2}}) { #list of phrases in doc2
+	push(@phrases2, $phrase);
+    }
+    foreach $phrase1 (@phrases1) { #list holds intersection of doc1 and doc2
+	foreach $phrase2 (@phrases2) {
+	    push(@phrases, $phrase1) if ($phrase1 == $phrase2);
+	}
+    }
+ 
+#COSINE MEASURE
+    my $wqtwdt= 0; 
+   
+    foreach $phrase (@phrases){ #for all phrases ocurring in d1 and d2
+	#the frequency that phrase occurs in document d1
+	$fd1p = $document_phrases{$ID1}{$phrase}; 
+	
+	#log base e(N/the number of documents that have phrase as a keyphrase)
+	$log_freq = log($N/$phrases_document{$phrase});
+	
+	#the frequency that phrase occurs in document d2
+	$fd2p = $document_phrases{$ID2}{$phrase};
+	$sum = ($fd1p * $log_freq) * ($fd2p * $log_freq);
+	$wqtwdt += $sum;
+    }
+  
+   
+    my $wd = 0; #stores the calculation for wd
+
+    foreach $phrase (@phrases1){ #for all phrases ocurring in d1 and d2
+	#the frequency that phrase occurs in document d1
+	$fd1p = $document_phrases{$ID1}{$phrase};
+	
+	#log base e($N/the number of documents that have phrase as a keyphrase)
+	$log_freq = log($N/$phrases_document{$phrase});
+	$sum = $fd1p * $log_freq;
+	$wd += ($sum * $sum); #sum squared
+    }
+
+   
+    my $wq = 0; #stores the calculation for wq
+ 
+    foreach $phrase (@phrases2){ #for all phrases ocurring in d2
+	#the frequency that phrase occurs in document d2
+	$fd2p = $document_phrases{$ID2}{$phrase};
+
+	#log base e($N/the number of documents that have phrase as a keyphrase)
+	$log_freq = log($N/$phrases_document{$phrase});
+	$sum = $fd2p * $log_freq;
+	$wq += ($sum * $sum); #sum squared 
+    }
+   
+    my $wdwq = sqrt($wq)  * sqrt($wd);  
+    my $cosine = $wqtwdt / $wdwq;
+    
+    return $cosine;
+	
+}
+   
+#this function adds the relational data we have collected to the gml files
+sub addtogml {
+
+ print STDERR "\nadding relational data to $N gml documents...\n\n";
+ my @doclist;
+ my %filetable;
+ my $pattern = "kea="; #pattern to search for to find where to insert relation data
+
+ #open archive info for each collecticollection
+ foreach $collection (@directories){
+
+     open(INFO, "$gsdlhome/collect/$collection/archives/archives.inf") 
+	 or die "$gsdlhome/collect/$collection/archives/archives.inf could not be opened";
+     
+     #read a list of ID's and pathnames into a file table
+     while(<INFO>){
+	 chomp;
+	 my %idtable;
+	 my $ID;
+	 if(/(\w+)(\s+)([\w\.\/]+)/){ #format of the line
+	     $ID = $1;
+	     $path = $3;
+	     $idtable{"$path"} = "$collection";
+	 }
+	 $filetable{"$ID"} = ({%idtable});
+     } 
+  
+     close(INFO);
+ }
+
+ 
+
+ #for each id in the matrix calculate a list of related documents
+ foreach $id (keys %cosine_matrix){    
+    
+     @doclist = &calculate_list($id); #gets list of documents with most relevant scores
+
+     my @path = keys %{$filetable{$id}}; #get filepath for document
+     my $collection = $filetable{$id}{$path[0]};
+     
+     #open gml file to amend for each collection
+     open(FILE, "$gsdlhome/collect/$collection/archives/$path[0]") 
+	 or die "$gsdlhome/collect/$collection/archives/$path[0] could not be opened";
+     
+     #read the gml file into text
+     $text = ""; 
+     while(<FILE>){
+	 $text .= $_;
+     }
+     
+     close(FILE);
+     
+     #delete previous relational data and urllinks to files storing rel doc links
+     $text =~ s/(\s)+relation=\"([^\"]*)\"//g;
+     $text =~ s/(\s)+urllink=\"([^\"]*)\"//g;
+     $text =~ s/(\s)+\/urllink=\"([^\"]*)\"//g;
+     
+     #if we want to insert each relation item as 'relation1="id" relation2="id"'
+     #$count = 1; #insert each item in the list
+     #foreach $item (@doclist){ #insert list into text
+     #	 $text =~ s/(\s)($pattern)/ relation$count=\"$item\" $2/g;
+     #	 $count++;
+     #} 
+     
+     #or relation="id, id, id"
+     #my $relation = join(",", @doclist);
+
+     #if pdf flag is set then delete pdf url document
+     if($do_pdfs == 1){ 
+	 my $dirpath = $path[0];
+	 $dirpath =~ s/(^(\/doc\.gml))*\/doc\.(gml)/$1/;
+ 	 `rm $gsdlhome/collect/$collection/index/assoc/$dirpath/url.txt`; 
+     }
+
+     my $title = "related document";
+     $title = $2 if($text =~ /(\s)+Title=\"([^\"]*)\"/g);
+   
+     #relation="collection,id collection,id"
+     my @relationlist;
+     my $relation = "";
+     foreach $doc (@doclist){
+	 my @p = keys %{$filetable{$doc}};
+	 my $collect = $filetable{$doc}{$p[0]};
+	 push(@relationlist, "$collect,$doc");
+
+	 #write pdf docs to file
+	 if($do_pdfs == 1){
+	     my @rel_path = keys %{$filetable{$doc}};
+	     &write_related_urls($title, $collection, $path[0], $collect, $rel_path[0]);
+	 }
+     }
+  
+     #modify the text to include relation data
+     $relation = join(" ", @relationlist); 
+     $text =~ s/($pattern)/ relation=\"$relation\" $1/g;
+
+     #open gml file to write back new text
+     open(FILE, ">$gsdlhome/collect/$collection/archives/$path[0]") or print STDERR "NO!!!!\n";
+     print FILE "$text"; #write back text
+     close(FILE);
+
+     #amend the pdf file 
+     if($do_pdfs == 1){
+	 my $pdf_path = $path[0];
+	 $pdf_path =~ s/(^(\/doc\.gml))*\/doc\.(gml)/$1/;
+	 `perl amend_pdf.pl $gsdlhome/collect/$collection/index/assoc/$pdf_path/doc.pdf $gsdlhome/collect/$collection/index/assoc/$pdf_path/url.txt\n`;
+     }
+ } 
+}
+
+#this function builds a list of cosine measures for each
+#document and sorts the list of ids each measure belongs to
+#in reverse order (ie docs with greatest cosine measure first)
+#returns the list calculated
+sub calculate_list {
+   
+    my $document = shift(@_);
+    my %measures;
+    my @doclist;
+    
+    
+    #find the top $number_of_files for $document  
+    foreach $id (keys %{$cosine_matrix{$document}}){ 
+	    $measures{"$cosine_matrix{$document}{$id}"} = "$id";
+    }
+    
+    my @list = reverse sort {$a<=>$b} keys %measures;
+
+    #list is as big as specified in command line (default is 1)
+    for($i = 0; $i<$number_of_files; $i++){ 
+	my $id = $measures{$list[$i]};
+	push(@doclist, $id) if($id ne "");
+    }
+
+    return @doclist;
+}
+
+
+sub write_related_urls {
+
+    
+ #need server name eg nzdl2.cs.waikato.ac.nz
+ #localhost should work but doesn't on this computer?
+ #open up config file to read httpprefix
+ #get collection name of related document
+ #get hash directory of related document
+ #write http://nzdl2.cs.waikato.ac.nz/httpprefix/collectionname/index/assoc/directory/doc.pdf
+
+ my ($title, $collection, $path, $collect, $rel_path) = @_;
+
+ $rel_path =~ s/(^(\/doc\.gml))*\/doc\.(gml)/$1/;
+ $path =~ s/(^(\/doc\.gml))*\/doc\.(gml)/$1/;
+ 
+ print STDERR "writing related pdf urls to file ";
+ print STDERR "$gsdlhome/collect/$collection/index/assoc/$path/url.txt...\n";
+ 
+ open(URL, ">>$gsdlhome/collect/$collection/index/assoc/$path/url.txt") 
+     or open(URL, ">$gsdlhome/collect/$collection/index/assoc/$path/url.txt")
+	 or print STDERR "This file $title is not a pdf file\n";
+
+ print URL "$title\t"; 
+ print URL "http://$servername/$httpprefix/collect/$collect/index/assoc/$rel_path/doc.pdf\n";
+ close URL;
+
+}
+
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/lucene_passes.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/lucene_passes.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/lucene_passes.pl	(revision 13928)
@@ -0,0 +1,235 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# lucene_passes.pl -- perl wrapper, akin to mgpp_passes, for Lucene
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/cpan");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/plugins");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/classify");
+}
+
+use util;
+use ghtml;
+
+sub open_java_lucene
+{
+  my ($doc_tag_level,$full_builddir,$indexdir,$create,$verbosity) = @_;
+
+  my $bin_java = &util::filename_cat($ENV{'GSDLHOME'},"bin","java");
+  my $classpath = &util::filename_cat($bin_java,"LuceneWrapper.jar");
+
+  my $java_lucene = "java -classpath \"$classpath\" org.greenstone.LuceneWrapper.GS2LuceneIndexer";
+  my $cmd_options = "$create -verbosity $verbosity";
+  my $java_cmd = "$java_lucene $cmd_options $doc_tag_level \"$full_builddir\" $indexdir";
+
+  open (PIPEOUT, "| $java_cmd") or die "$PROGNAME - couldn't run $java_cmd\n";
+}
+
+sub close_java_lucene
+{
+  close(PIPEOUT);
+}
+
+sub save_xml_doc
+{
+    my ($full_textdir,$output_filename,$doc_xml) = @_;
+    $dir_sep = &util::get_os_dirsep();
+
+    my $full_output_filename = &util::filename_cat($full_textdir,$output_filename);
+    my ($full_output_dir) = ($full_output_filename =~ m/^(.*$dir_sep)/x);
+    &util::mk_all_dir($full_output_dir);
+
+    open(DOCOUT,">$full_output_filename")
+	|| die "Unable to open $full_output_filename";
+
+    print DOCOUT $doc_xml;
+    close(DOCOUT);
+
+    my @secs =  ($doc_xml =~ m/<Sec\s+gs2:id="\d+"\s*>.*?<\/Sec>/sg);
+}
+
+sub compress_xml_doc
+{
+    my ($full_textdir,$output_filename) = @_;
+
+    my $full_output_filename
+	= &util::filename_cat($full_textdir,$output_filename);
+
+    `gzip $full_output_filename`;
+}
+
+# This appears to be the callback that gets the xml stream during the
+# build process, so I need to intercept it here and call my XML RPC
+# to insert into the Lucene database.
+sub monitor_xml_stream
+{
+    my ($mode, $full_textdir) = @_;
+
+    my $doc_xml = "";
+    my $output_filename = "";
+
+    my $line;
+    while (defined ($line = <STDIN>)) {
+	$line =~ s/&nbsp;/&amp;nbsp;/g;
+	$doc_xml .= $line;
+	if ($line =~ m/^<Doc.+file=\"(.*?)\".*>$/) {
+	    $output_filename = $1;
+	    
+	}
+	
+	if ($line =~ m/^<\/Doc>$/) {
+	    if ($mode eq "text") {
+		save_xml_doc($full_textdir,$output_filename,$doc_xml);
+	    } elsif ($mode eq "index") {
+		# notify lucene indexer
+
+		# SAX parser seems to be sensitive to blank lines
+		# => remove them
+		$doc_xml =~ s/\n+/\n/g;
+
+#		 print STDERR $doc_xml;
+
+##	    print PIPEOUT "$output_filename\n";
+
+		print PIPEOUT "$doc_xml";
+
+
+		#save_xml_doc($full_textdir, "$output_filename.txt", $doc_xml);
+	    }
+	    # compress file
+###	    compress_xml_doc($full_textdir,$output_filename);
+
+	    $doc_xml = "";
+	    $output_filename = "";
+	}
+    }
+}
+
+
+# /** This checks the arguments on the command line, filters the
+#  *  unknown command line arguments and then calls the open_java_lucene
+#  *  function to begin processing. Most of the arguments are passed on
+#  *  the command line of the java wrapper.
+#  *
+#  *  Do not set -create and -remove at the same time, although -create is
+#  *  required for -remove, -remove will set it it's self, if you set -create
+#  *  after -remove the create will be ignored.
+#  *
+#  *  @version 2.0 Added support for removing documents from the index by John Rowe
+#  *
+#  *  @author John Rowe, DL Consulting
+#  */
+sub main
+{
+  my (@argv) = @_;
+  my $argc = scalar(@argv);
+
+  my $create = "";
+  my $verbosity = 1;
+
+  my @filtered_argv = ();
+
+  my $i = 0;
+  while ($i<$argc) {
+    if ($argv[$i] =~ m/^\-(.*)$/) {
+
+      my $option = $1;
+
+      # -create causes build to be incremental
+      if ($option eq ("create")) {
+        print STDERR "\n\n-create set\n";
+        $create = "-create";
+      }
+      # In a blinding flash of unintuitiveness -remove causes
+      # -create to be set (we don't want to remove the old indexes)
+      elsif($option eq "remove")
+      {
+        # Look at the next arg for the oid and if that doesn't exist then
+        $i++;
+        if(!defined $argv[$i])
+        {
+          print STDERR "Remove was specified but the OID was not specified";
+          die "\n\nCannot continue";
+        }
+        $removeoid = $argv[$i];
+        print STDERR "\n\nWe're removing the document with id: '$removeoid'\n";
+
+        # Now, to make sure this gets through to the Java executable
+        $create = "-create -remove '$removeoid'";
+      }
+
+      # -verbosity num
+      elsif ($option eq "verbosity") {
+        $i++;
+        if ($i<$argc) {
+          $verbosity = $argv[$i];
+        }
+      }
+      else {
+        print STDERR "Unrecognised minus option: -$option\n";
+      }
+    }
+    else {
+        push(@filtered_argv,$argv[$i]);
+    }
+    $i++;
+  }
+
+  my $filtered_argc = scalar(@filtered_argv);
+
+  if ($filtered_argc < 4) {
+    print STDERR "Usage: $PROGNAME [-create|-verbosity num] \"text\"|\"index\" doc-tag-level build-dir index-name\n";
+    exit 1;
+  }
+
+  my $mode = $filtered_argv[0];
+  my $doc_tag_level = $filtered_argv[1];
+  my $full_builddir = $filtered_argv[2];
+  my $indexdir      = $filtered_argv[3];
+###    print STDERR "**** ARGS = ", join(" ", @argv), "\n";
+
+  my $full_textdir = &util::filename_cat($full_builddir,"text");
+
+  if ($mode eq "index") {
+# don't need the lucene stuff if we are just storing the docs
+    open_java_lucene($doc_tag_level,$full_builddir,$indexdir,$create,$verbosity);
+  }
+  print STDERR "Monitoring for input!\n";
+  monitor_xml_stream($mode, $full_textdir);
+  if ($mode eq "index") {
+    close_java_lucene();
+  }
+}
+
+$PROGNAME = $0;
+$PROGNAME =~ s/^.*\/(.*)$/$1/;
+
+&main(@ARGV);
+
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/lucene_query.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/lucene_query.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/lucene_query.pl	(revision 13928)
@@ -0,0 +1,171 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# lucene_query.pl -- perl wrapper to initiate query using Lucene
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use strict;
+use util;
+
+my $PROGNAME = $0;
+$PROGNAME =~ s/^.*\/(.*)$/$1/;
+
+
+sub get_java_path()
+{
+    # Check the JAVA_HOME environment variable first
+    if (defined $ENV{'JAVA_HOME'}) {
+	my $java_home = $ENV{'JAVA_HOME'};
+	$java_home =~ s/\/$//;  # Remove trailing slash if present (Unix specific)
+	return &util::filename_cat($java_home, "bin", "java");
+    }
+
+    # Hope that Java is on the PATH
+    return "java";
+}
+
+sub open_java_lucene
+{
+    my $full_indexdir = shift(@_);
+    my $fuzziness = shift(@_);
+    my $filter_string = shift(@_);
+    my $sort_field = shift(@_);
+    my $dco = shift(@_);
+    my $start_results = shift(@_);
+    my $end_results = shift(@_);
+    my $out_file = shift(@_);
+
+    my $java = &get_java_path();
+    my $classpath = &util::filename_cat($ENV{'GSDLHOME'}, "bin", "java", "LuceneWrapper.jar");
+    my $java_lucene = "$java -classpath \"$classpath\" org.greenstone.LuceneWrapper.GS2LuceneQuery";
+
+    my $cmd = "| " . $java_lucene . " \"" . $full_indexdir . "\"";
+    if (defined($fuzziness)) {
+        $cmd .= " -fuzziness " . $fuzziness;
+    }
+    if (defined($filter_string)) {
+	$cmd .= " -filter \"" . $filter_string . "\"";
+    }
+    if (defined($sort_field)) {
+        $cmd .= " -sort " . $sort_field;
+    }
+    if (defined($dco)) {
+        $cmd .= " -dco " . $dco;
+    }
+    if (defined($start_results)) {
+        $cmd .= " -startresults " . $start_results;
+    }
+    if (defined($end_results)) {
+        $cmd .= " -endresults " . $end_results;
+    }
+    if (defined($out_file)) {
+	$cmd .= " > \"" . $out_file . "\"";
+    }
+    # print STDERR $cmd . "\n";
+
+    if (!open (PIPEOUT, $cmd)) {
+	die "$PROGNAME - couldn't run $cmd\n";
+    }
+}
+
+sub close_java_lucene
+{
+    close(PIPEOUT);
+}
+
+sub main
+{
+    my (@argv) = @_;
+    my $argc = scalar(@argv);
+    if ($argc == 0) {
+	print STDERR "Usage: $PROGNAME full-index-dir [query] [-fuzziness value] [-filter filter_string] [-sort sort_field] [-dco AND|OR] [-startresults number -endresults number] [-out out_file]\n";
+	exit 1;
+    }
+
+    my $full_indexdir = shift(@argv);
+    my $query = undef;
+    my $fuzziness = undef;
+    my $filter_string = undef;
+    my $sort_field = undef;
+    my $dco = undef;
+    my $start_results = undef;
+    my $end_results = undef;
+    my $out_file = undef;
+    for (my $i = 0; $i < scalar(@argv); $i++)
+    {
+	if ($argv[$i] eq "-fuzziness") {
+	    $i++;
+	    $fuzziness = $argv[$i];
+	}
+        elsif ($argv[$i] eq "-filter") {
+            $i++;
+            $filter_string = $argv[$i];
+	}
+        elsif ($argv[$i] eq "-sort") {
+            $i++;
+            $sort_field = $argv[$i];
+	}
+        elsif ($argv[$i] eq "-dco") {
+            $i++;
+            $dco = $argv[$i];
+	}
+        elsif ($argv[$i] eq "-startresults") {
+            $i++;
+            $start_results = $argv[$i];
+	}
+        elsif ($argv[$i] eq "-endresults") {
+            $i++;
+            $end_results = $argv[$i];
+	}
+        elsif ($argv[$i] eq "-out") {
+            $i++;
+            $out_file = $argv[$i];
+	}
+        else {
+            $query = $argv[$i];
+	}
+    }
+
+    open_java_lucene($full_indexdir, $fuzziness, $filter_string, $sort_field, $dco, $start_results, $end_results, $out_file);
+
+    if (defined $query) {
+	print PIPEOUT "$query\n";
+    }
+    else {
+	while (defined (my $line = <STDIN>)) {
+	    print PIPEOUT $line;
+	}
+    }
+
+    close_java_lucene();
+}
+
+&main(@ARGV);
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/makemapfile.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/makemapfile.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/makemapfile.pl	(revision 13928)
@@ -0,0 +1,188 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# makemapfile.pl --
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 2001 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use parsargv;
+use util;
+
+# %translations is of the form:
+#
+# encodings{encodingname-encodingname}->blocktranslation
+# blocktranslation->[[0-255],[256-511], ..., [65280-65535]]
+#
+# Any of the top translation blocks can point to an undefined
+# value. This data structure aims to allow fast translation and 
+# efficient storage.
+%translations = ();
+
+# @array256 is used for initialisation, there must be
+# a better way...
+@array256 = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+	     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+	     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+	     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+	     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+	     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+	     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+	     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+	     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+	     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+	     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+	     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+	     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+	     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+	     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+	     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
+
+&main();
+
+sub print_usage {
+    print STDERR "\n";
+    print STDERR "makemapfile.pl: Creates unicode map (.ump) files from plain\n";
+    print STDERR "                text code pages.\n\n";
+    print STDERR "  usage: $0 [options]\n\n";
+    print STDERR "  options:\n";
+    print STDERR "   -encoding name\n";
+    print STDERR "   -mapfile  text file from which to create binary ump file\n\n";
+}
+
+sub main {
+    if (!parsargv::parse(\@ARGV, 
+			 'encoding/.+', \$encoding,
+			 'mapfile/.+', \$mapfile)) {
+	&print_usage();
+	die "\n";
+    }
+
+    if (!&loadencoding ($encoding, $mapfile)) {
+	die "couldn't load encoding $encoding";
+    }
+
+    # write out map files
+    &writemapfile ("$encoding-unicode", $encoding, 1);
+    &writemapfile ("unicode-$encoding", $encoding, 0);
+}
+
+sub writemapfile {
+    my ($encoding, $filename, $tounicode) = @_;
+
+    $filename .= ".ump"; # unicode map file
+    if ($tounicode) {
+	$filename = &util::filename_cat ($ENV{'GSDLHOME'}, "mappings", "to_uc", $filename);
+    } else {
+	$filename = &util::filename_cat ($ENV{'GSDLHOME'}, "mappings", "from_uc", $filename);
+    }
+
+    die "translation not defined" if (!defined $translations{$encoding});
+    my $block = $translations{$encoding};
+
+    print "writing $filename\n";
+    open (MAPFILE, ">" . $filename) || die;
+    binmode (MAPFILE);
+
+    my ($i, $j);
+    for ($i=0; $i<256; $i++) {
+	if (ref ($block->[$i]) eq "ARRAY") {
+	    print MAPFILE pack ("C", $i);
+	    for ($j=0; $j<256; $j++) {
+		# unsigned short in network order
+		print MAPFILE pack ("CC", int($block->[$i]->[$j] / 256), 
+				    $block->[$i]->[$j] % 256);
+	    }
+	}
+    }
+    close (MAPFILE);
+}
+
+# loadencoding expects the mapfile to contain (at least) two
+# tab-separated fields. The first field is the mapped value
+# and the second field is the unicode value.
+#
+# It returns 1 if successful, 0 if unsuccessful
+sub loadencoding {
+    my ($encoding, $mapfile) = @_;
+    
+    my $to = "$encoding-unicode";
+    my $from = "unicode-$encoding";
+
+    # check to see if the encoding has already been loaded
+    if (defined $translations{$to} && defined $translations{$from}) {
+	return 1;
+    }
+
+    return 0 unless open (MAPFILE, $mapfile);
+
+    my ($line, @line);
+    $translations{$to} = [@array256];
+    $translations{$from} = [@array256];
+    while (defined ($line = <MAPFILE>)) {
+	chomp $line;
+	# remove comments
+	$line =~ s/\#.*$//;
+	next unless $line =~ /\S/;
+
+	# split the line into fields and do a few
+	# simple sanity checks
+	@line = split (/\t/, $line);
+	next unless (scalar(@line) >= 2 &&
+		     $line[0] =~ /^0x/ &&
+		     $line[1] =~ /^0x/);
+
+	my $char = hex($line[0]);
+	my $unic = hex($line[1]);
+
+	# might need this for some versions of gb but not gbk
+#	$char = $char | 0x8080 unless ($encoding =~ /gbk/i);
+
+	&addchartrans ($translations{$to}, $char, $unic);
+	&addchartrans ($translations{$from}, $unic, $char);
+    }
+
+    close (MAPFILE);
+
+    return 1;
+}
+
+# addchartrans adds one character translation to a translation block.
+# It also simplifies the translation block if possible.
+sub addchartrans {
+    my ($block, $from, $to) = @_;
+    my $i = 0;
+
+    my $high = ($from / 256) % 256;
+    my $low = $from % 256;
+
+    if (ref ($block->[$high]) ne "ARRAY") {
+	$block->[$high] = [@array256];
+    }
+    $block->[$high]->[$low] = $to;
+}
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/mirror.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/mirror.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/mirror.pl	(revision 13928)
@@ -0,0 +1,144 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# mirror.pl
+#
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+# This program uses w3mirror to mirror a web site.  It looks for a
+# mirror program configuration files in etc, and if it finds them then
+# it runs the mirroring software using this configuration file, and placing
+# the mirror in the import directory.
+#
+# mirror.pl can use the w3mirror program or the wget program if they are
+# installed.
+#
+# To use w3mirror, the configuration file must be in etc/w3mir.cfg.
+# To use GNU wget, the configuration file (i.e. a wgetrc file) must
+# be in etc/wget.cfg and a file of the URLs to read in etc/wget.url
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/plugins");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/classify");
+}
+
+use arcinfo;
+use colcfg;
+use util;
+use parsargv;
+
+sub print_usage {
+    print STDERR "\n";
+    print STDERR "mirror.pl: Uses w3mir or wget to sync a collections import data\n";
+    print STDERR "           with a website.\n\n";
+    print STDERR "  usage: $0 [options] collection-name\n\n";
+    print STDERR "  options:\n";
+    print STDERR "   -verbosity number      0=none, 3=lots\n";
+    print STDERR "   -importdir directory   Where to place the mirrored material\n";
+}
+
+
+&main ();
+
+sub main {
+    my ($verbosity, $importdir, $etcdir, 
+        $collection, $configfilename, $collectcfg);
+
+    if (!parsargv::parse(\@ARGV, 
+			 'verbosity/\d+/2', \$verbosity,
+			 'importdir/.*/', \$importdir )) {
+	&print_usage();
+	die "\n";
+    }
+
+    # get and check the collection name
+    if (($collection = &util::use_collection(@ARGV)) eq "") {
+	&print_usage();
+	die "\n";
+    }
+
+    # get the etc directory
+    $etcdir = &util::filename_cat ($ENV{'GSDLCOLLECTDIR'}, "etc");
+    
+    # check the collection configuration file for options
+    my $interval = 0;
+    $configfilename = &util::filename_cat ($ENV{'GSDLCOLLECTDIR'}, 
+					   "etc", "collect.cfg");
+    if (-e $configfilename) {
+	$collectcfg = &colcfg::read_collect_cfg ($configfilename);
+	if (defined $collectcfg->{'importdir'} && $importdir eq "") {
+	    $importdir = $collectcfg->{'importdir'};
+	}
+    } else {
+	die "Couldn't find the configuration file $configfilename\n";
+    }
+    
+    # fill in the default import directories if none
+    # were supplied, turn all \ into / and remove trailing /
+    $importdir = "$ENV{'GSDLCOLLECTDIR'}/import" if $importdir eq "";
+    $importdir =~ s/[\\\/]+/\//g;
+    $importdir =~ s/\/$//;
+
+    # make sure there is an import directory
+    if (! -e "$importdir") {
+	&util::mk_dir($importdir);
+    }
+
+    # if w3mir.cfg exists, 
+    # then we are using w3mirror to mirror the remote site
+    if (-e "$etcdir/w3mir.cfg") {
+
+	# run the mirror program from the import directory
+	my  $cmd = "cd $importdir; ";
+	$cmd .= "perl -S gsw3mir.pl -cfgfile $etcdir/w3mir.cfg";
+	# print "\n$cmd\n";
+	`$cmd`;
+
+    } 
+
+    # if wget.cfg and wget.url both exist, 
+    # then we are using GNU wget to mirror the remote site
+    elsif ((-e "$etcdir/wget.cfg") && (-e "$etcdir/wget.url")) {
+	$ENV{WGETRC} = "$etcdir/wget.cfg";
+	my $cmd = "perl -S gsWget.pl --input-file=$etcdir/wget.url --directory-prefix=$importdir";
+	system($cmd);
+    }
+
+    # otherwise, there are no mirror copnfiguration files
+    else {
+	die "Couldn't find the mirror configuration files in $etcdir\n";
+    }
+
+
+}
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/mkcol.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/mkcol.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/mkcol.pl	(revision 13928)
@@ -0,0 +1,346 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# mkcol.pl --
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+# This program will setup a new collection from a model one. It does this by
+# copying the model, moving files to have the correct names, and replacing
+# text within the files to match the parameters.
+
+package mkcol;
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use parse2;
+use util;
+use cfgread;
+use gsprintf 'gsprintf';
+use printusage;
+
+use strict;
+no strict 'subs'; # allow barewords (eg STDERR) as function arguments
+
+my $public_list = 
+    [ { 'name' => "true",
+	'desc' => "{mkcol.public.true}"},
+      { 'name' => "false",
+	'desc' => "{mkcol.public.false}"} 
+      ];
+
+my $win31compat_list = 
+    [ { 'name' => "true",
+	'desc' => "{mkcol.win31compat.true}"},
+      { 'name' => "false",
+	'desc' => "{mkcol.win31compat.false}"} 
+      ];
+
+my $arguments =
+    [ { 'name' => "creator",
+	'desc' => "{mkcol.creator}",
+	'type' => "string",
+	'reqd' => "no" },
+      { 'name' => "optionfile",
+	'desc' => "{mkcol.optionfile}",
+	'type' => "string",
+	'reqd' => "no" },
+      { 'name' => "maintainer",
+	'desc' => "{mkcol.maintainer}",
+	'type' => "string",
+	'reqd' => "no" },
+      { 'name' => "collectdir",
+	'desc' => "{mkcol.collectdir}",
+	'type' => "string",
+	'deft' => &util::filename_cat ($ENV{'GSDLHOME'}, "collect"),
+	'reqd' => "no" },
+      { 'name' => "public",
+	'desc' => "{mkcol.public}",
+	'type' => "enum",
+	'deft' => "true",
+	'list' => $public_list,
+	'reqd' => "no" },
+      { 'name' => "title",
+	'desc' => "{mkcol.title}",
+	'type' => "string",
+	'reqd' => "no" },
+      { 'name' => "about",
+	'desc' => "{mkcol.about}",
+	'type' => "string",
+	'reqd' => "no" },
+      { 'name' => "plugin",
+	'desc' => "{mkcol.plugin}",
+	'type' => "string",
+	'reqd' => "no" },
+      { 'name' => "quiet",
+	'desc' => "{mkcol.quiet}",
+	'type' => "flag",
+	'reqd' => "no" },
+      { 'name' => "language",
+	'desc' => "{scripts.language}",
+	'type' => "string",
+	'reqd' => "no" },
+      { 'name' => "win31compat",
+	'desc' => "{mkcol.win31compat}",
+	'type' => "enum",
+	'deft' => "true",
+	'list' => $win31compat_list,
+	'reqd' => "no" },
+      { 'name' => "gli",
+	'desc' => "",
+	'type' => "flag",
+	'reqd' => "no",
+	'hiddengli' => "yes" },
+      { 'name' => "xml",
+	'desc' => "{scripts.xml}",
+	'type' => "flag",
+	'reqd' => "no",
+	'hiddengli' => "yes" }
+      ];
+
+my $options = { 'name' => "mkcol.pl",
+		'desc' => "{mkcol.desc}",
+		'args' => $arguments };
+
+# options
+my ($creator, $optionfile, $maintainer, $collectdir, $public, 
+    $title, $about, $plugin, $quiet, $language, $win31compat, $gli);
+
+#other variables
+my ($collection, $capcollection, $pluginstring, @plugin);
+
+&main();
+
+
+sub traverse_dir
+{
+    my ($modeldir, $coldir) = @_;
+    my ($newfile, @filetext);
+
+    if (!(-e $coldir)) {
+
+	my $store_umask = umask(0002);
+	my $mkdir_ok = mkdir ($coldir, 0777);
+	umask($store_umask);
+
+	if (!$mkdir_ok) 
+	{
+	    die "$!";
+	}
+    }
+
+    opendir(DIR, $modeldir) ||
+	(&gsprintf(STDERR, "{common.cannot_read}\n", $modeldir) && die);
+    my @files = grep(!/^(\.\.?|CVS)$/, readdir(DIR));
+    closedir(DIR);
+
+    foreach my $file (@files)
+    {
+	my $thisfile = &util::filename_cat ($modeldir, $file);
+	if (-d $thisfile) {
+	    my $colfiledir = &util::filename_cat ($coldir, $file);
+	    traverse_dir ($thisfile, $colfiledir);
+
+	} else {
+	    my $destfile = $file;
+	    $destfile =~ s/^modelcol/$collection/;
+	    $destfile =~ s/^MODELCOL/$capcollection/;
+	    &gsprintf(STDOUT, "{mkcol.doing_replacements}\n", $destfile)
+		unless $quiet;
+	    $destfile = &util::filename_cat ($coldir, $destfile);
+
+	    open (INFILE, $thisfile) || 
+		(&gsprintf(STDERR, "{common.cannot_read_file}\n", $thisfile) && die);
+	    open (OUTFILE, ">$destfile") ||
+		(&gsprintf(STDERR, "{common.cannot_create_file}\n", $destfile) && die);
+
+	    while (defined (my $line = <INFILE>)) {
+		$line =~ s/\*\*collection\*\*/$collection/g;
+		$line =~ s/\*\*COLLECTION\*\*/$capcollection/g;
+		$line =~ s/\*\*creator\*\*/$creator/g;
+		$line =~ s/\*\*maintainer\*\*/$maintainer/g;
+		$line =~ s/\*\*public\*\*/$public/g;
+		$line =~ s/\*\*title\*\*/$title/g;
+		$line =~ s/\*\*about\*\*/$about/g;
+		$line =~ s/\*\*plugins\*\*/$pluginstring/g;
+
+		print OUTFILE $line;
+	    }
+	    
+	    close (OUTFILE);
+	    close (INFILE);
+	}
+    }
+}
+
+
+sub main {
+    
+    my $xml = 0;
+    
+    my $hashParsingResult = {};
+    my $intArgLeftinAfterParsing = parse2::parse(\@ARGV,$arguments,$hashParsingResult,"allow_extra_options");
+    
+    # If parse returns -1 then something has gone wrong
+    if ($intArgLeftinAfterParsing == -1)
+    {
+	&PrintUsage::print_txt_usage($options, "{mkcol.params}");
+	die "\n";
+    }
+    
+    foreach my $strVariable (keys %$hashParsingResult)
+    {
+	eval "\$$strVariable = \$hashParsingResult->{\"\$strVariable\"}";
+    }
+
+    # If $language has been specified, load the appropriate resource bundle
+    # (Otherwise, the default resource bundle will be loaded automatically)
+    if ($language && $language =~ /\S/) {
+	&gsprintf::load_language_specific_resource_bundle($language);
+    }
+
+    if ($xml) {
+	&PrintUsage::print_xml_usage($options);
+	print "\n";
+	return;
+    }
+
+    if ($gli) { # the gli wants strings to be in UTF-8
+	&gsprintf::output_strings_in_UTF8; 
+    }
+
+    # now check that we had exactly one leftover arg, which should be 
+    # the collection name. We don't want to do this earlier, cos 
+    # -xml arg doesn't need a collection name
+    # Or if the user specified -h, then we output the usage also
+    if ($intArgLeftinAfterParsing != 1 || (@ARGV && $ARGV[0] =~ /^\-+h/))
+    {
+	&PrintUsage::print_txt_usage($options, "{mkcol.params}");
+	die "\n";
+    }
+
+    if ($optionfile =~ /\w/) {
+	open (OPTIONS, $optionfile) ||
+	    (&gsprintf(STDERR, "{common.cannot_open}\n", $optionfile) && die);
+	my $line = [];
+	my $options = [];
+	while (defined ($line = &cfgread::read_cfg_line ('mkcol::OPTIONS'))) {
+	    push (@$options, @$line);
+	}
+	close OPTIONS;
+	my $optionsParsingResult = {};
+	if (parse2::parse($options,$arguments,$optionsParsingResult) == -1) {
+	    &PrintUsage::print_txt_usage($options, "{mkcol.params}");
+	    die "\n";
+	}
+	    
+	foreach my $strVariable (keys %$optionsParsingResult)
+	{
+	    eval "\$$strVariable = \$optionsParsingResult->{\"\$strVariable\"}";
+	}
+    }
+    
+    # load default plugins if none were on command line
+    if (!scalar(@plugin)) {
+	@plugin = (ZIPPlug,GAPlug,TEXTPlug,"HTMLPlug -smart_block","EMAILPlug",
+		   PDFPlug,RTFPlug,WordPlug,PSPlug,ImagePlug,ISISPlug,NULPlug,MetadataXMLPlug,ArcPlug,RecPlug);
+    }
+
+    # get and check the collection name
+    ($collection) = @ARGV;
+    if (!defined($collection)) {
+	&gsprintf(STDOUT, "{mkcol.no_colname}\n");
+	&PrintUsage::print_txt_usage($options, "{mkcol.params}");
+	die "\n";
+    }
+
+    if (($win31compat eq "true") && (length($collection)) > 8) {
+	&gsprintf(STDOUT, "{mkcol.long_colname}\n");
+	die "\n";
+    }
+
+    if ($collection eq "modelcol") {
+	&gsprintf(STDOUT, "{mkcol.bad_name_modelcol}\n");
+	die "\n";
+    }
+
+    if ($collection eq "CVS") {
+	&gsprintf(STDOUT, "{mkcol.bad_name_cvs}\n");
+	die "\n";
+    }
+
+    if (defined($creator) && (!defined($maintainer) || $maintainer eq "")) {
+	$maintainer = $creator;
+    }
+
+    $public = "true" unless defined $public;
+
+    if (!defined($title) || $title eq "") {
+	$title = $collection;
+    }
+
+    # get capitalised version of the collection
+    $capcollection = $collection;
+    $capcollection =~ tr/a-z/A-Z/;
+
+    # get the strings to include.
+    $pluginstring = "";
+    foreach my $plug (@plugin) {
+	$pluginstring .= "plugin         $plug\n";
+    }
+
+    my $mdir = &util::filename_cat ($ENV{'GSDLHOME'}, "collect", "modelcol");
+    my $cdir;
+    if (defined $collectdir && $collectdir =~ /\w/) {
+	if (!-d $collectdir) {
+	    &gsprintf(STDOUT, "{mkcol.no_collectdir}\n", $collectdir);
+	    die "\n";
+	}
+	$cdir = &util::filename_cat ($collectdir, $collection);
+    } else {
+	$cdir = &util::filename_cat ($ENV{'GSDLHOME'}, "collect", $collection);
+    }
+
+    # make sure the model collection exists
+    (&gsprintf(STDERR, "{mkcol.cannot_find_modelcol}\n", $mdir) && die) unless (-d $mdir);
+
+    # make sure this collection does not already exist
+    if (-e $cdir) {
+	&gsprintf(STDOUT, "{mkcol.col_already_exists}\n");
+	die "\n";
+    }
+
+    # start creating the collection
+    &gsprintf(STDOUT, "\n{mkcol.creating_col}...\n", $collection)
+	unless $quiet;
+    &traverse_dir ($mdir, $cdir);
+    &gsprintf(STDOUT, "\n{mkcol.success}\n", $cdir)
+	unless $quiet;
+}
+
+
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/nightly.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/nightly.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/nightly.pl	(revision 13928)
@@ -0,0 +1,102 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# nightly.pl
+#
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+# This program will find all the collections under $GSDLHOME/collect
+# and use the update.pl script to update them all.  It should be run
+# every night to keep mirror collections up-to-date.
+
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/plugins");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/classify");
+}
+
+use arcinfo;
+use colcfg;
+use util;
+use parsargv;
+
+sub print_usage {
+    print STDERR "\n";
+    print STDERR "nightly.pl: Attempts to update all Greenstone collections found on\n";
+    print STDERR "            the local filesystem by calling update.pl for each of\n";
+    print STDERR "            them.\n\n";
+    print STDERR "  usage: $0 [options]\n\n";
+    print STDERR "  options:\n";
+    print STDERR "   -verbosity number      0=none, 3=lots\n";
+    print STDERR "   -importdir directory   Where to place the mirrored material\n";
+    print STDERR "   -archivedir directory  Where the converted material ends up\n";
+}
+
+
+&main ();
+
+sub main {
+    my ($verbosity, $collectdir, $name, $collection);
+
+    if (!parsargv::parse(\@ARGV, 
+			 'verbosity/\d+/2', \$verbosity )) {
+	&print_usage();
+	die "\n";
+    }
+
+
+    # get the contents of the collect directory
+    $collectdir =  &util::filename_cat($ENV{'GSDLHOME'}, "collect");
+    opendir(CDIR, $collectdir) || die "Cannot open $collectdir: $!";
+    my @files = readdir(CDIR);
+    closedir CDIR;
+
+
+    # update each collection
+    foreach $name (@files) {
+
+	$collection = &util::filename_cat($collectdir, $name);
+
+	# igore entries for "." and ".."
+	next unless ($name =~ /[^\.]/);
+
+	# ignore modelcol
+	next if ($name eq "modelcol");
+
+	# ignore entries that are not directories
+	next unless (-d $collection);
+
+	# ignore directories that do not have a subdir called etc
+	next unless (-d &util::filename_cat($collection, "etc"));
+
+	print "Updating: $name\n";
+	print `update.pl $name`;
+	
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/pdftohtml.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/pdftohtml.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/pdftohtml.pl	(revision 13928)
@@ -0,0 +1,267 @@
+#!/usr/bin/perl -w
+
+
+###########################################################################
+#
+# pdftohtml.pl -- convert PDF documents to HTML format
+#
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 2001 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+# pdftohtml.pl is a wrapper for running pdftohtml utility which converts
+# PDF documents to HTML, and converts images to PNG format for display in
+# the HTML pages generated
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use parsargv;
+use util;
+use Cwd;
+use File::Basename;
+
+sub print_usage {
+# note - we don't actually ever use most of these options...
+print STDERR  
+    ("pdftohtml.pl wrapper for pdftohtml.\n",
+     "Usage: pdftohtml [options] <PDF-file> <html-file>\n",
+     "Options:\n",
+     "\t-i\tignore images (don't extract)\n",
+     "\t-a\tallow images only (continue even if no text is present)\n",
+     "\t-c\tproduce complex output (requires ghostscript)\n",
+     "\t-hidden\tExtract hidden text\n",
+     "\t-zoom\tfactor by which to zoom the PDF (only useful if -c is set)\n"
+     );
+exit (1);
+}
+
+sub main {
+    my (@ARGV) = @_;
+    my ($allow_no_text, $ignore_images, $complex, $zoom, $hidden);
+    
+    # read command-line arguments so that
+    # you can change the command in this script
+    if (!parsargv::parse(\@ARGV,
+			 'a', \$allow_no_text,
+			 'i', \$ignore_images,
+			 'c', \$complex,
+			 'hidden', \$hidden,
+			 'zoom/\d+/2', \$zoom,
+			 ))
+    {
+	print_usage();
+    }
+
+    # Make sure the input file exists and can be opened for reading
+    if (scalar(@ARGV) != 2) {
+	print_usage();
+    }
+
+    my $input_filename = $ARGV[0];
+    my $output_filestem = $ARGV[1];
+
+    $output_filestem =~ s/\.html$//i; # pdftohtml adds this suffix
+
+    # test that the directories exist to create the output file, or
+    # we should exit immediately. (File:: is included by util.pm)
+    my $output_dir =  File::Basename::dirname($output_filestem);
+    if (! -d $output_dir || ! -w $output_dir) {
+	die "pdftohtml.pl: cannot write to directory $output_dir\n";
+    }
+
+    my @dir = split (/(\/|\\)/, $input_filename);
+    my $input_basename = pop(@dir);
+    $input_basename =~ s/\.pdf//i;
+    my $dir = join ("", @dir);
+
+    if (!-r $input_filename) {
+	print STDERR "Error: unable to open $input_filename for reading\n";
+	exit(1);
+    }
+
+    # Heuristical code removed due to pdftohtml being "fixed" to not
+    # create bitmaps for each char in some pdfs. However, this means we
+    # now create .html files even if we can't extract any text. We should
+    # check for that now instead someday...
+
+
+    # formulate the command
+    my $cmd = &util::filename_cat($ENV{'GSDLHOME'}, "bin", $ENV{'GSDLOS'}, "pdftohtml");
+
+    # don't include path on windows (to avoid having to play about
+    # with quoting when GSDLHOME might contain spaces) but assume
+    # that the PATH is set up correctly.
+    $cmd = "pdftohtml" if ($ENV{'GSDLOS'} =~ /^windows$/);
+
+    $cmd .= " -i" if ($ignore_images);
+    $cmd .= " -c" if ($complex);
+    $cmd .= " -hidden" if ($hidden);
+    $cmd .= " -zoom $zoom";
+    $cmd .= " -noframes -p -enc UTF-8 \"$input_filename\" \"$output_filestem.html\"";
+
+# system() returns -1 if it can't run, otherwise it's $cmds ret val.
+    # note we return 0 if the file is "encrypted"
+    $!=0;
+    if (system($cmd)!=0) {
+	print STDERR "pdftohtml error for $input_filename $!\n";
+	# leave these for gsConvert.pl...
+	#&util::rm("$output_filestem.text") if (-e "$output_filestem.text");
+	#&util::rm("$output_filestem.err") if (-e "$output_filestem.err");
+	return 1;
+    }
+
+    if (! -e "$output_filestem.html") {
+	return 1;
+    }
+
+# post-process to remove </b><b> and </i><i>, as these break up
+# words, screwing up indexing and searching.
+# At the same time, check that our .html file has some textual content.
+    &util::mv("$output_filestem.html","$output_filestem.html.tmp");
+    $!=0;
+    open INFILE, "$output_filestem.html.tmp" ||
+	die "Couldn't open file: $!";
+    open OUTFILE, ">$output_filestem.html" ||
+	die "Couldn't open file for writing: $!";
+    my $line;
+    my $seen_textual_content=$allow_no_text;
+    # check for unicode byte-order marker at the start of the file
+    $line = <INFILE>;
+    $line =~ s#\376\377##g;
+    while ($line) {
+	$line =~ s#</b><b>##g;
+	$line =~ s#</i><i>##g;
+	$line =~ s#\\#\\\\#g; # until macro language parsing is fixed...
+# check for any extracted text
+	if ($seen_textual_content == 0) {
+	    my $tmp_line=$line;
+	    $tmp_line =~ s/<[^>]*>//g;
+	    $tmp_line =~ s/Page\s\d+//;
+	    $tmp_line =~ s/\s*//g;
+	    if ($tmp_line ne "") {
+		$seen_textual_content=1;
+	    }
+	    # special - added to remove the filename from the title
+	    # this should be in the header, before we see "textual content"
+	    if ($line =~ m@<title>(.*?)</title>@i) {
+		my $title=$1;
+		
+		# is this title the name of a filename?
+		if (-r "$title.pdf" || -r "$title.html") {
+		    # remove the title
+		    $line =~ s@<title>.*?</title>@<title></title>\n<META NAME=\"filename\" CONTENT=\"$title\">@i;
+		}
+	    }
+	}
+
+	# relative hrefs to own document...
+	$line =~ s@href=\"$input_basename\.html\#@href=\"\#@go;
+# escape underscores, but not if they're inside tags (eg img/href names)
+	my $inatag = 0; # allow multi-line tags
+	if ($line =~ /_/) {
+	    my @parts=split('_',$line);
+	    my $lastpart=pop @parts;
+	    foreach my $part (@parts) {
+		if ($part =~ /<[^>]*$/) { # if we're starting a tag...
+		    $inatag=1;
+		} elsif ($part =~ />[^<]*$/) { # closing a tag
+		    $inatag=0;
+		}
+		if ($inatag) {
+		    $part.='_';
+		} else {
+		    $part.="&#95;";
+		}
+	    }
+	    $line=join('',@parts,$lastpart);
+	}
+
+	print OUTFILE $line;
+	$line = <INFILE>;
+    }
+    close INFILE;
+    close OUTFILE;
+    &util::rm("$output_filestem.html.tmp");
+
+    # Need to convert images from PPM format to PNG format
+    my @images;
+
+    my $directory=$output_filestem;
+    $directory =~ s@[^\/]*$@@;    # assume filename has no embedded slashes...
+    # newer versions of pdftohtml don't seem to do images this way anymore?
+    if (open (IMAGES, "${directory}images.log") || 
+	open (IMAGES, "${directory}image.log")) {
+	while (<IMAGES>) {
+	    push (@images, $_);
+	}
+	close IMAGES;
+	&util::rm("${directory}image.log") if (-e "${directory}image.log");
+
+    }
+
+    # no need to go any further if there is no text extracted from pdf.
+    if ($seen_textual_content == 0) {
+	print STDERR "Error: PDF contains no extractable text\n";
+	# remove images...
+	for $image (@images) {
+	    chomp($image);
+	    &util::rm("${directory}$image");
+	}
+	return 1;
+    }
+
+
+
+    for $image (@images) {
+	chomp($image);
+	my $cmd = "";
+	if ($ENV{'GSDLOS'} =~ /^windows/i) {
+	    $cmd = "pnmtopng \"${directory}$image\"";
+	    if (system($cmd)!=0) {
+		print STDERR "Error executing $cmd\n";
+		#return 1; # not sure about whether to leave this one in or take it out
+		next;
+	    }
+	} else {
+	    my @nameparts = split(/\./, $image);
+	    my $image_base = shift(@nameparts);
+	    $cmd = "pnmtopng \"${directory}$image\" > \"${directory}$image_base.png\" 2>/dev/null";
+	    if (system($cmd)!=0) {
+		$cmd = "convert \"${directory}$image\" \"${directory}$image_base.png\" 2>/dev/null";
+		if (system($cmd)!=0) {
+		    print STDERR "Cannot convert $image into PNG format (tried `pnmtopng' and `convert')...\n";
+		    #return 1; # not sure about whether to leave this one in or take it out
+		    next;
+		}
+	    }
+	}
+	&util::rm($image);
+    }
+
+    return 0;
+}
+
+# indicate our error status, 0 = success
+exit (&main(@ARGV));
+
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/pdftoimg.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/pdftoimg.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/pdftoimg.pl	(revision 13928)
@@ -0,0 +1,156 @@
+#!/usr/bin/perl -w
+
+
+###########################################################################
+#
+# pdftoimg.pl -- convert PDF documents to various types of Image format
+#
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 2001 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+# pdftoimg.pl is a wrapper for running convert utility which converts
+# PDF documents to various types of image (e.g. PNG, GIF, JPEG format, 
+# Then use PagedImgPlug to deal with the the images
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use parsargv;
+use util;
+use Cwd;
+use File::Basename
+;
+sub print_usage {
+    # note - we don't actually ever use most of these options...
+    print STDERR  
+	("pdftoimg.pl wrapper for pdftoimg.\n",
+	 "Usage: pdftoimg [options] <PDF-file> <output>>\n",
+	 "Options:\n",
+	 "\t-convert_to\toutput image type for the PDF\n"
+	 );
+    exit (1);
+}
+
+sub main {
+    my (@ARGV) = @_;
+    my ($convert_to);
+    
+    # read command-line arguments so that
+    # you can change the command in this script
+    if (!parsargv::parse(\@ARGV,
+			 'convert_to/.*/^', \$convert_to,
+			 )) {
+    	print_usage();
+    }
+    
+    # Make sure the input file exists and can be opened for reading
+    if (scalar(@ARGV) != 2) {
+	print_usage();
+    }
+    
+    my $input_filename = $ARGV[0];
+    my $output_filestem = $ARGV[1];
+    
+    # test that the directories exist to create the output file, or
+    # we should exit immediately. (File:: is included by util.pm)
+    &util::mk_dir($output_filestem) if (!-e $output_filestem);
+	    
+    my @dir = split (/(\/|\\)/, $input_filename);
+    my $input_basename = pop(@dir);
+    $input_basename =~ s/\.pdf//i;
+    my $dir = join ("", @dir);
+
+    if (!-r $input_filename) {
+	print STDERR "Error: unable to open $input_filename for reading\n";
+	exit(1);
+    }
+    # don't include path on windows (to avoid having to play about
+    # with quoting when GSDLHOME might contain spaces) but assume
+    # that the PATH is set up correctly.
+    $cmd = "convert";
+    #if ($ENV{'GSDLOS'} =~ /^windows$/);
+    #Convert utility will convert the PDF to GIF Animation
+    my $output_filename = &util::filename_cat($output_filestem, $input_basename);
+    if ($convert_to eq "gif") {
+	$cmd .= " \"$input_filename\" \"$output_filename-%02d.$convert_to\"";
+    } else {
+	$cmd .= " \"$input_filename\" \"$output_filename.$convert_to\"";
+    }	
+ 
+    # system() returns -1 if it can't run, otherwise it's $cmds ret val.
+    # note we return 0 if the file is "encrypted"
+    $!=0;
+    if (system($cmd)!=0) {
+	print STDERR "Convert error for $input_filename $!\n";
+	# leave these for gsConvert.pl...
+	#&util::rm("$output_filestem.text") if (-e "$output_filestem.text");
+	#&util::rm("$output_filestem.err") if (-e "$output_filestem.err");
+	return 1;
+    } else {
+	# command execute successfully
+	create_itemfile($output_filestem, $input_basename, $convert_to);
+    }
+    return 0;
+}
+
+sub create_itemfile
+{
+    my ($output_dir, $convert_basename, $convert_to) = @_;
+    opendir(DIR, $output_dir) || die "can't opendir $output_dir: $!";  
+    my $item_file = $output_dir."/".$convert_basename.".item";
+    open(FILE,">$item_file");
+    
+    print FILE "<PagedDocument>\n";
+
+    my $page_num = "";
+    @dir_files = grep {-f "$output_dir/$_"} readdir(DIR);
+
+    # Sort files in the directory by page_num    
+    sub page_number {
+	my ($dir) = @_;
+	my ($pagenum) =($dir =~ m/^.*[-\.](\d+)(\.(jpg|gif|png))?$/i);
+	
+	$pagenum = 1 unless defined $pagenum;
+	return $pagenum;
+    }
+
+    # sort the files in the directory in the order of page_num rather than lexically. 
+    @dir_files = sort { page_number($a) <=> page_number($b) } @dir_files;
+
+    foreach my $file (@dir_files){
+	$page_num = page_number($file)+1; # image numbers start at 0, so add 1
+	if ($file !~ /\.item/i){
+	    print FILE "   <Page pagenum=\"$page_num\" imgfile=\"$file\" txtfile=\"\"/>\n";
+	} 
+    }
+
+    print FILE "</PagedDocument>\n";
+    closedir DIR;
+    return "";
+}
+
+# indicate our error status, 0 = success
+exit (&main(@ARGV));
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/ping.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/ping.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/ping.pl	(revision 13928)
@@ -0,0 +1,74 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# ping.pl --
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 2001 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/cpan/Ping");
+}
+
+
+require LWP::UserAgent;
+use parsargv;
+
+&main();
+
+sub print_usage {
+    print STDERR "\n";
+    print STDERR "ping.pl: Ping http or ftp URL to see if it's accessable.\n\n";
+    print STDERR "  usage: $0 [options] URL\n\n";
+    print STDERR "  options:\n";
+    print STDERR "   -quiet   Quiet operation\n\n";
+}
+
+sub main {
+
+    my ($quiet);
+    if (!parsargv::parse(\@ARGV, 'quiet', \$quiet)) {
+	&print_usage();
+	die "\n";
+    }
+
+    if (!scalar(@ARGV)) {
+	print STDERR "ERROR: no URL was provided\n";
+	die "\n";
+    }
+
+    $ua = new LWP::UserAgent;
+    $ua->timeout(60);
+    $request = new HTTP::Request('HEAD', $ARGV[0]);
+    $response = $ua->request($request);
+    
+    if ($response->is_success) {
+	print STDERR "$ARGV[0] ping succeeded\n" unless $quiet;
+	exit 0;
+    } else {
+	print STDERR "$ARGV[0] ping failed\n" unless $quiet;
+	exit 1;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/pluginfo.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/pluginfo.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/pluginfo.pl	(revision 13928)
@@ -0,0 +1,208 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# pluginfo.pl --
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+# This program will print info about a plugin
+
+use strict;
+no strict 'subs'; # allow barewords (eg STDERR) as function arguments
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/cpan");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/plugins");
+}
+
+use plugin;
+use util;
+use gsprintf;
+use printusage;
+use parse2;
+
+my $arguments =
+    [ { 'name' => "collection",
+	'desc' => "{pluginfo.collection}",
+	'type' => "string",
+	'reqd' => "no" },
+      { 'name' => "xml",
+	'desc' => "{scripts.xml}",
+	'type' => "flag",
+	'reqd' => "no" },
+      { 'name' => "listall",
+	'desc' => "{scripts.listall}",
+	'type' => "flag",
+	'reqd' => "no" },
+      { 'name' => "describeall",
+	'desc' => "{scripts.describeall}",
+	'type' => "flag",
+	'reqd' => "no" },
+      { 'name' => "language",
+	'desc' => "{scripts.language}",
+	'type' => "string",
+	'reqd' => "no" } ];
+
+my $options = { 'name' => "pluginfo.pl",
+		'desc' => "{pluginfo.desc}",
+		'args' => $arguments };
+
+sub gsprintf
+{
+    return &gsprintf::gsprintf(@_);
+}
+
+
+sub main {
+    my $collection = "";
+    my $xml = 0;
+    my $listall = 0;
+    my $describeall = 0;
+    my ($language, $encoding);
+
+    my $hashParsingResult = {};
+    # general options available to all plugins
+    my $unparsed_args = parse2::parse(\@ARGV,$arguments,$hashParsingResult,"allow_extra_options");
+    # parse returns -1 if an error occurred
+    if ($unparsed_args == -1) {
+	
+	PrintUsage::print_txt_usage($options, "{pluginfo.params}");
+ 	die "\n";
+    }
+    
+    foreach my $strVariable (keys %$hashParsingResult)
+    {
+	my $value = $hashParsingResult->{$strVariable};
+	# test to make sure the variable name is 'safe'
+	if ($strVariable !~ /^\w+$/) {
+ 	    die "variable name '$strVariable' isn't safe!";
+	}
+	eval "\$$strVariable = \$value";
+    }
+
+    # if language wasn't specified, see if it is set in the environment
+    # (LC_ALL or LANG)
+    if (!$language && ($_=$ENV{'LC_ALL'} or $_=$ENV{'LANG'})) {
+	m/^([^\.]+)\.?(.*)/;
+	$language=$1;
+	$encoding=$2; # might be undef...
+# gsprintf::load_language* thinks "fr" is completely different to "fr_FR"...
+	$language =~ s/_.*$//;
+    }
+
+    # If $language has been set, load the appropriate resource bundle
+    # (Otherwise, the default resource bundle will be loaded automatically)
+    if ($language) {
+	gsprintf::load_language_specific_resource_bundle($language);
+	if ($encoding) {
+	    $encoding =~ tr/-/_/;
+	    $encoding = lc($encoding);
+	    $encoding =~ s/utf_8/utf8/; # special
+	    $gsprintf::specialoutputencoding=$encoding;
+	}
+    }
+
+    # If there is not exactly 1 argument left (plugin name), then the arguments were wrong
+    # If the user specified -h, then we output the usage also
+    if((@ARGV && $ARGV[0] =~ /^\-+h/) )
+    {
+	PrintUsage::print_txt_usage($options, "{pluginfo.params}");  
+        die "\n";
+    }
+
+    # If there is not exactly 1 argument left (plugin name), then the arguments were wrong (apart from if we had listall or describeall set)
+    if ($listall == 0 && $describeall ==0 && $unparsed_args == 0) {
+	gsprintf(STDERR, "{pluginfo.no_plugin_name}\n\n");
+	PrintUsage::print_txt_usage($options, "{pluginfo.params}", 1);
+	die "\n";
+    }
+
+    # we had some arguments that we weren't expecting
+    if ($unparsed_args > 1) {
+	pop(@ARGV); # assume that the last arg is the plugin name
+	gsprintf(STDERR, "{common.invalid_options}\n\n", join (',', @ARGV));
+	PrintUsage::print_txt_usage($options, "{pluginfo.params}", 1);
+	die "\n";
+    }
+	
+    my $plugin = shift (@ARGV);
+    if (defined $plugin) {
+	$plugin =~ s/\.pm$//; # allow xxxPlug.pm as the argument
+    }
+
+    if ($collection ne "") {
+	$ENV{'GSDLCOLLECTDIR'} = &util::filename_cat ($ENV{'GSDLHOME'}, "collect", $collection);
+    } else {
+	$ENV{'GSDLCOLLECTDIR'} = $ENV{'GSDLHOME'};
+    }
+
+    if ($listall || $describeall) {
+	my $plugins_dir = &util::filename_cat($ENV{'GSDLCOLLECTDIR'}, "perllib", "plugins");
+	my @plugin_list = ();
+	if (opendir (INDIR, $plugins_dir)) {
+	    @plugin_list = grep (/Plug\.pm$/, readdir (INDIR));
+	    closedir (INDIR);
+	}
+
+	print STDERR "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+	print STDERR "<PluginList length=\"" . scalar(@plugin_list) . "\">\n";
+	foreach my $plugin (@plugin_list) {
+	    $plugin =~ s/\.pm$//;
+	    my $plugobj = &plugin::load_plugin_for_info ($plugin);
+	    if ($describeall) {
+		$plugobj->print_xml_usage(0);
+	    }
+	    else {
+		$plugobj->print_xml_usage(0, 1);
+	    }
+	}
+	print STDERR "</PluginList>\n";
+    }
+    else {
+	&print_single_plugin($plugin, $xml, 1);
+    }
+}
+
+
+sub print_single_plugin {
+    my ($plugin, $xml, $header) = @_;
+    my $plugobj = &plugin::load_plugin_for_info ($plugin);
+    if ($xml) {
+	$plugobj->print_xml_usage($header);
+    }
+    else {
+	gsprintf(STDERR, "\n{pluginfo.passing_options}\n\n");
+	gsprintf(STDERR, "{pluginfo.option_types}:\n\n");
+	gsprintf(STDERR, "{pluginfo.specific_options}\n\n");
+	gsprintf(STDERR, "{pluginfo.general_options}\n\n");
+	gsprintf(STDERR, "$plugin {pluginfo.info}:\n\n");
+	
+	$plugobj->print_txt_usage();
+    }
+    
+}
+
+&main ();
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/plugoutinfo.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/plugoutinfo.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/plugoutinfo.pl	(revision 13928)
@@ -0,0 +1,211 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# plugoutinfo.pl --
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+# This program will print info about a plugout
+
+use strict;
+no strict 'subs'; # allow barewords (eg STDERR) as function arguments
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/cpan");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/plugouts");
+}
+
+use plugout;
+use util;
+use gsprintf;
+use printusage;
+use parse2;
+
+my $arguments =
+    [ { 'name' => "collection",
+	'desc' => "{plugoutinfo.collection}",
+	'type' => "string",
+	'reqd' => "no" },
+      { 'name' => "xml",
+	'desc' => "{scripts.xml}",
+	'type' => "flag",
+	'reqd' => "no" },
+      { 'name' => "listall",
+	'desc' => "{scripts.listall}",
+	'type' => "flag",
+	'reqd' => "no" },
+      { 'name' => "describeall",
+	'desc' => "{scripts.describeall}",
+	'type' => "flag",
+	'reqd' => "no" },
+      { 'name' => "language",
+	'desc' => "{scripts.language}",
+	'type' => "string",
+	'reqd' => "no" } ];
+
+my $options = { 'name' => "plugoutinfo.pl",
+		'desc' => "{plugoutinfo.desc}",
+		'args' => $arguments };
+
+sub gsprintf
+{
+    return &gsprintf::gsprintf(@_);
+}
+
+
+sub main {
+    my $collection = "";
+    my $xml = 0;
+    my $listall = 0;
+    my $describeall = 0;
+    my ($language, $encoding);
+
+    my $hashParsingResult = {};
+    # general options available to all plugouts
+    my $unparsed_args = parse2::parse(\@ARGV,$arguments,$hashParsingResult,"allow_extra_options");
+
+    # parse returns -1 if an error occurred
+    if ($unparsed_args == -1) {
+	
+	PrintUsage::print_txt_usage($options, "{plugoutinfo.params}");
+ 	die "\n";
+    }
+    
+    foreach my $strVariable (keys %$hashParsingResult)
+    {
+	my $value = $hashParsingResult->{$strVariable};
+	# test to make sure the variable name is 'safe'
+	if ($strVariable !~ /^\w+$/) {
+ 	    die "variable name '$strVariable' isn't safe!";
+	}
+	eval "\$$strVariable = \$value";
+        
+    }
+ 
+    # if language wasn't specified, see if it is set in the environment
+    # (LC_ALL or LANG)
+    if (!$language && ($_=$ENV{'LC_ALL'} or $_=$ENV{'LANG'})) {
+	m/^([^\.]+)\.?(.*)/;
+	$language=$1;
+	$encoding=$2; # might be undef...
+# gsprintf::load_language* thinks "fr" is completely different to "fr_FR"...
+	$language =~ s/_.*$//;
+    }
+
+    # If $language has been set, load the appropriate resource bundle
+    # (Otherwise, the default resource bundle will be loaded automatically)
+    if ($language) {
+	gsprintf::load_language_specific_resource_bundle($language);
+	if ($encoding) {
+	    $encoding =~ tr/-/_/;
+	    $encoding = lc($encoding);
+	    $encoding =~ s/utf_8/utf8/; # special
+	    $gsprintf::specialoutputencoding=$encoding;
+	}
+    }
+
+    # If there is not exactly 1 argument left (plugout name), then the arguments were wrong
+    # Or if the user specified -h, then we output the usage also
+    if(@ARGV && $ARGV[0] =~ /^\-+h/ )
+    {
+	PrintUsage::print_txt_usage($options, "{plugoutinfo.params}");  
+        die "\n";
+    }
+
+    # If there is not exactly 1 argument left (plugout name), then the arguments were wrong (apart from if we had listall or describeall set)
+    if ($listall == 0 && $describeall ==0 && $unparsed_args == 0) {
+	gsprintf(STDERR, "{plugoutinfo.no_plugout_name}\n\n");
+	PrintUsage::print_txt_usage($options, "{plugoutinfo.params}", 1);
+	die "\n";
+    }
+
+    # we had some arguments that we weren't expecting
+    if ($unparsed_args > 1) {
+	pop(@ARGV); # assume that the last arg is the plugout name
+	gsprintf(STDERR, "{common.invalid_options}\n\n", join (',', @ARGV));
+	PrintUsage::print_txt_usage($options, "{plugoutinfo.params}", 1);
+	die "\n";
+    }
+
+    my $plugout = shift (@ARGV);
+    if (defined $plugout) {
+	$plugout =~ s/\.pm$//; # allow xxxPlugout.pm as the argument
+    }
+
+    if ($collection ne "") {
+	$ENV{'GSDLCOLLECTDIR'} = &util::filename_cat ($ENV{'GSDLHOME'}, "collect", $collection);
+    } else {
+	$ENV{'GSDLCOLLECTDIR'} = $ENV{'GSDLHOME'};
+    }
+
+    if ($listall || $describeall) {
+	my $plugouts_dir = &util::filename_cat($ENV{'GSDLCOLLECTDIR'}, "perllib", "plugouts");
+	my @plugout_list = ();
+	if (opendir (INDIR, $plugouts_dir)) {
+	    @plugout_list = grep (/Plugout\.pm$/, readdir (INDIR));
+	    closedir (INDIR);
+	}
+
+	print STDERR "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+	print STDERR "<PlugoutList length=\"" . scalar(@plugout_list) . "\">\n";
+	foreach my $plugout (@plugout_list) {
+	    $plugout =~ s/\.pm$//;
+	    my $plugoutobj = &plugout::load_plugout ($plugout);
+	    if ($describeall) {
+		$plugoutobj->print_xml_usage(0);
+	    }
+	    else {
+		$plugoutobj->print_xml_usage(0, 1);
+	    }
+	}
+	print STDERR "</PlugoutList>\n";
+    }
+    else {
+	&print_single_plugout($plugout, $xml, 1);
+    }
+}
+
+
+sub print_single_plugout {
+    my ($plugout, $xml, $header) = @_;
+    my $plugoutobj = &plugout::load_plugout($plugout,[]);
+
+    if ($xml) {
+	$plugoutobj->print_xml_usage($header);
+    }
+    else {
+	gsprintf(STDERR, "\n{plugoutinfo.passing_options}\n\n");
+	gsprintf(STDERR, "{plugoutinfo.option_types}:\n\n");
+	gsprintf(STDERR, "{plugoutinfo.specific_options}\n\n");
+	gsprintf(STDERR, "{plugoutinfo.general_options}\n\n");
+	gsprintf(STDERR, "$plugout {plugoutinfo.info}:\n\n");
+	
+	$plugoutobj->print_txt_usage();
+    }
+    
+}
+
+&main ();
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/ppttohtml.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/ppttohtml.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/ppttohtml.pl	(revision 13928)
@@ -0,0 +1,68 @@
+eval 'exec perl -x -- $0 $@'
+    if 0;
+#! perl
+# line 6
+
+sub usage() {
+    print "$0 <input.ppt> <output.html>\n";
+}
+
+
+if (@ARGV != 2) {
+    usage();
+    exit(1);
+}
+my $input_ppt=shift;
+my $output_html=shift;
+
+# try to find ppthtml binary in GSDLHOME
+my $ppthtml_binary="ppthtml";
+my $GSDLOS=$ENV{'GSDLOS'};
+my $GSDLHOME=$ENV{'GSDLHOME'};
+if ($GSDLOS =~ /^windows$/i) {
+    $ppthtml_binary.=".exe";
+}
+
+# assume it is on the path if running under windows, in case GSDLHOME
+# has a space
+if ($GSDLOS !~ /windows/i && -x "$GSDLHOME/bin/$GSDLOS/$ppthtml_binary") {
+    $ppthtml_binary="$GSDLHOME/bin/$GSDLOS/$ppthtml_binary";
+}
+
+if (! -r $input_ppt) {
+    print STDERR "Unable to read file `$input_ppt'\n";
+    exit (1);
+}
+
+my $return_value=
+    system("$ppthtml_binary \"$input_ppt\" > \"$output_html\"");
+
+if ($return_value != 0) {
+    exit (1);
+}
+
+# Ok, we made an html file. Check to see if it has any content, and remove
+# the little nag link at the the bottom.
+my $html="";
+open (HTML, "$output_html") || die "Can't read file:$!";
+$html=join('', <HTML>);
+close HTML;
+
+$html =~ s@<hr><FONT SIZE=-1>Created with.*\n</BODY></HTML>$@</BODY></HTML>@s;
+
+# if we are using the file name as the title, then get rid of it,
+# as HTMLPlug will use the first 100 chars instead if there's no title.
+$html =~ s@<title>.*?\.ppt</title>@<title></title>@i;
+
+my $tmp=$html;
+$tmp =~ s/^.*?<BODY>//ms;
+$tmp =~ s/(&nbsp;)|\s//gims;
+if ($tmp !~ m/(>[^<]+<)/) {
+    print STDERR "No text found in extracted html file!\n";
+    exit(1);
+}
+open (NEWHTML, ">$output_html") || die "Can't create file:$!";
+print NEWHTML $html;
+close NEWHTML;
+exit (0);
+
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/process_html.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/process_html.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/process_html.pl	(revision 13928)
@@ -0,0 +1,393 @@
+#!/usr/bin/perl -w
+
+
+# Both this script and its associated process_html.pl were written by
+# Marcel ?, while a student at Waikato University. Unfortunately he
+# was very new to perl at the time so the code is neither as clean nor
+# as fast as it could be (I've cleaned up a few of the more serious
+# bottlenecks -- it could do with alot more work though).  The code
+# does work though, if a little slowly. It's not ready for primetime
+# however and is included in the Greenstone source tree mostly so that
+# I don't lose it. -- Stefan - 24 Jul 2001
+
+
+# This script rebuilds the static collection by linking all the downloaded html files
+# back together. 
+# It searches through html files and replaces links it recognizes from the links.txt file 
+# with the apropriate html file name (eg 1.html, 2.html etc)
+# This script also updates the links for the pictures.
+
+# This is where all the dl-ed html files are located, eg. 'temp_html/'
+my $outputdir  = 'temp_html/';
+
+# This is where all the processed files end up (don't want to overwrite originals ;) eg. 'my_static_collection/'
+my $finaldir   = 'envl_collection/';
+
+# If any options where used (such as &u=1) when the html files where dl-ed then please specify them here.
+my $option = "&u=1";
+
+# Please ensure these two options match the settings used when downloading the collection :)
+my $dir_entries = 250;
+my $fix_empty_pages = '&cl=CL1';
+
+#-------------------------------------------------------------------------------------------------
+
+# global arrays used to store links, links-index & html-filenames
+my %filez;
+my %out_filez;
+my %linkz;
+my %short_linkz1;
+my %short_linkz2;
+my %short_linkz3;
+my %linkz_index;
+#my %remove_these;
+my $remove_these = "";
+
+sub processfiles
+{
+    local($start_here) = @_;
+
+    for my $file($start_here .. $#filez)
+    {
+	if((-e $filez[$file])&&(-s $filez[$file]))
+	{
+	    open (FILE, $filez[$file]) or die "can't open ", $filez[$file],": $! \n";
+	    
+	    print " $filez[$file] ";
+	    
+	    undef $/;
+	    my $content_of_file = <FILE>;
+	    $/ = "\n";
+	    close(FILE);
+	    
+	    #quick & nasty fix for the 'open book' link
+	    local $quick_fix1 = "&cl=\"";
+	    local $quick_fix2 = "&cl=\'";
+	    
+	    $content_of_file =~ s/$quick_fix1/$fix_empty_pages\"/g;
+	    $content_of_file =~ s/$quick_fix2/$fix_empty_pages\'/g;
+	    
+	    for my $link(0 .. $#linkz)
+	    {
+		my $new_link = $linkz_index[$link].".html";
+		
+		if($short_linkz3[$link] ne "")
+		{
+		    $content_of_file =~ s/$short_linkz1[$link].*?$short_linkz2[$link].*?${short_linkz3[$link]}[^\"\'\s\>]*/$new_link/g;
+		}
+		else
+		{
+			$content_of_file =~ s/$short_linkz1[$link].*${short_linkz2[$link]}[^\"\'\s\>]*/$new_link/g;
+		}
+	    }
+    
+            $content_of_file =~ s/(["'])$remove_these/$1..\//g;
+	    open (TEMP, ">temp.html") or die "can't open temp.html: $! \n";
+	    print TEMP $content_of_file;
+	    close(TEMP);
+	    rename("temp.html", $out_filez[$file]) or die "cannot create", $out_filez[$file],": $! \n";
+	    print " --> $out_filez[$file]";
+	    print "..done\n";
+	}
+	else
+	{
+	    last;    # bomb out of loop. Done.
+	}
+    }
+     print " *** Done, cannot find any more files to process ***\n";
+}
+
+# the switch variable there so that I can create a couple of additional arrays without having to write an entirely new function :-)
+# 0 = off, 1 = on (puts values into %linkz_index, %short_linkz1 and %short_linkz2)
+sub sort_array_by_length
+{
+    local (*foo, $switch) = @_;
+    my $total = $#foo;
+    my %temp_linkz;
+    my $shortest = 999999;
+    my $longest = 0;
+
+    if ($switch != 0)
+    {
+	print "Processing linkz (chopping, slicing, dicing and sorting :-)...";
+    }
+
+    for my $counter(0 .. $total)
+    {
+	if (length($foo[$counter]) < $shortest)
+	{
+	    $shortest = length($foo[$counter]);   
+	    $temp_linkz[$total] = $foo[$counter];
+	}
+	if (length($foo[$counter]) > $longest)
+	{
+	    $longest = length($foo[$counter]);   
+	}  
+    }        
+    
+    $backward = $total;
+    for my $l($shortest .. $longest)
+    {      
+	local $numberdir = 0;
+	for my $counter(0 .. $total)
+	{
+	    if ($counter % $dir_entries == 0)
+	    {
+		$numberdir = $counter;
+	    }
+
+	    if(length($foo[$counter]) == $l)
+	    {
+		$temp_linkz[$backward] = $foo[$counter];
+		if ($switch != 0)
+		{ 
+		    $linkz_index[$backward] = "../".$numberdir."/".$counter;
+		    my $d_offset = 0;
+		    for my $search(0 .. (length($foo[$counter]) - 3))
+		    {
+			if((substr($foo[$counter], $search, 3) eq '?e=')||(substr($foo[$counter], $search, 3) eq '&e='))
+			{
+			    $short_linkz1[$backward] = substr($foo[$counter], 0, $search);
+			}
+			
+			for my $second_search($search .. length($foo[$counter]))
+			{
+			    if((substr($foo[$counter], $second_search, 3) eq '?d=')||(substr($foo[$counter], $second_search, 3) eq '&d='))
+			    {
+				$short_linkz3[$backward] = substr($foo[$counter], $second_search);
+				$d_offset = $second_search;
+				last;
+			    }
+			}
+			
+			if(substr($foo[$counter], $search, 3) eq '?a=')
+			{
+			    $short_linkz1[$backward] = substr($foo[$counter], 0, $search);
+			    if($d_offset > 0)
+			    {
+				$short_linkz2[$backward] = substr($foo[$counter], $search, $d_offset - $search);
+			    }
+			    else
+			    {
+				$short_linkz2[$backward] = substr($foo[$counter], $search);
+			    }
+			}
+			
+			if(substr($foo[$counter], $search, 3) eq '&a=')
+			{
+			    if($d_offset > 0)
+			    {
+				$short_linkz2[$backward] = substr($foo[$counter], $search, $d_offset - $search);
+			    }
+			    else
+			    {
+				$short_linkz2[$backward] = substr($foo[$counter], $search);
+			    }
+			}
+		    } 
+		}
+		$backward--;
+	    }
+	}
+    }    
+    # copy the sorted temp_array over the original array (must be a better way of doing this :\ )
+    for my $counter(0 .. $total)
+    {    
+	$foo[$counter] = $temp_linkz[$counter];
+    }
+    if ($switch != 0)
+    {
+	print "done!\n";
+    }
+}
+
+sub how_much_to_chop
+{
+    local($link) = @_;
+    my $bracket_counter = 0;
+    my $chop_offset = 0;
+
+    for my $search(0 .. length($link))
+    {
+	if (substr($link, $search, 1) eq '/')
+	{
+	    $bracket_counter++;   
+	}
+	if ($bracket_counter == 2)
+	{
+	    $chop_offset = $search + 1;
+	} 
+    }
+    return $chop_offset;
+}
+
+my $start_time = (times)[0]; 
+
+#-----------------------------------------------------------------------------------------------
+# No need to start from scratch everytime, we can recover/continue from wherever we left off
+# simply by checking which html files have been created
+#-----------------------------------------------------------------------------------------------
+my $linknumber = 0;
+my $failed     = 0;
+my $check_file = "";
+my $numberdir = 0;
+
+if($outputdir ne $finaldir)
+{
+    while ($failed == 0)
+    {
+	if ($linknumber % $dir_entries == 0) 
+	{
+	    if (!((-e $finaldir.$linknumber)&&(-d $finaldir.$linknumber)))
+	    {
+		$failed++;
+		mkdir($finaldir.$linknumber, 0777) or die " ** Cannot create ",$finaldir.$linknumber, "!: $!\n";
+	    }
+	    $numberdir = $linknumber;
+	}
+	
+	$check_file = $finaldir.$numberdir."/".$linknumber.".html";
+	if ((-e $check_file)&&($failed == 0)) 
+	{ 
+	    $linknumber++;
+	} 
+	else
+	{
+	    $failed++;
+	    # I'm subtracting 1 from the starting link, 
+	    # just in case it only loaded half the page ;^)
+	    if($linknumber>0) 
+	    { 
+		$linknumber--; 
+	    }
+	    print " Will start processing at number $linknumber \n";
+	}
+    }
+}
+my $i = 0;
+my $that = "";
+my $offset = 0;
+
+#read in old links from links text file
+open (CHECK, "links.txt") || die " ** Cannot find/open links text file!: $!\n";
+while (defined ($that = <CHECK>)) {
+    
+    if ($i == 0)
+    {  
+	#chop off the first bit
+	$offset = &how_much_to_chop($that); 
+	print " Offset has been set to: ",$offset,"\n";
+	print " This next bit will be ignored for all links in the links.txt file:\n";
+	print "  -->",substr($that,0,$offset),"<--\n";
+    }
+    
+    $that = substr($that, $offset);
+    
+    #Wipe-out the EOL character
+#    if (substr($that, -1) eq "\n") { substr($that, -1) = ""; }
+    chomp $that;
+    
+    #this wipes the options
+#    if (length($option) != 0)
+#    {	    
+#	substr($that, (length($option)) * -1) = "";
+#    }
+    $that =~ s/$option//;
+    
+    $linkz[$i] = $that;
+    
+    $short_linkz1[$i] = "";
+    $short_linkz2[$i] = "";
+    $short_linkz3[$i] = "";
+    
+    for my $search(0 .. (length($that) - 3))
+    {
+	if((substr($that, $search, 3) eq '?e=')||(substr($that, $search, 3) eq '&e='))
+	{
+	    $short_linkz1[$i] = substr($that, 0, $search);
+	}
+	
+	if(substr($that, $search, 3) eq '?a=')
+	{
+	    $short_linkz1[$i] = substr($that, 0, $search);
+	    $short_linkz2[$i] = substr($that, $search);
+	}
+	if(substr($that, $search, 3) eq '&a=')
+	{
+	    $short_linkz2[$i] = substr($that, $search);
+	}
+    }
+    $i++;
+    
+    if ($i % $dir_entries == 0)
+    {
+	if (!((-e $finaldir.$i)&&(-d $finaldir.$i)))
+	{
+	    mkdir($finaldir.$i, 0777) or die " ** Cannot create ",$finaldir.$i, "!: $!\n";
+	}
+    }
+}
+close(CHECK);
+
+print " - I found ",$i, " links in the links text file -\n";
+
+&sort_array_by_length(*linkz, 1);
+
+$numberdir = 0;
+
+for my $z(0 .. ($i - 1))
+{
+    if($z % $dir_entries == 0)
+    {
+	$numberdir = $z;
+    }
+    $filez[$z] = $outputdir.$numberdir."/".$z.".html";
+    $out_filez[$z] = $finaldir.$numberdir."/".$z.".html";
+}
+
+# ..and last but not least, load any image_dirs from image_dirs.txt
+my $imd_that = "";
+#my $image_dirs_pointer = 0;
+
+my @tmp_arr = ();
+open (IMAGE_DIR, "image_dirs.txt") || die " ** HEY! Cannot find/open image_dirs.txt file! : $! **\n";
+while(defined ($imd_that = <IMAGE_DIR>))
+{
+    chomp $imd_that;
+    push(@tmp_array, $imd_that);
+}
+close IMAGE_DIR;
+
+$remove_these = "(" . join ("|", sort {length $b <=> length $a} @tmp_array) . ")"; 
+
+#print " - I found ",($#remove_these + 1)," picture directories in image_dirs.txt -\n";
+#&sort_array_by_length(*remove_these, 0);
+
+print "-" x 20, "\n";
+print "  Here we go...\n";
+print "-" x 20, "\n";
+
+&processfiles($linknumber);
+
+my $end_time = (times)[0];
+print "\n\n\n *----------------------------*\n";
+print " |  Whew! Task completed! :-D |\n";
+print " *----------------------------*\n";
+printf"  Script took %.2f CPU seconds to complete ;^)\n", $end_time - $start_time;
+print "\n\n"; 
+print " Now there's a few things left to do...load up ",$finaldir, "0/0.html in your webbrowser and\n";
+print " make sure everything works.\n"; 
+print " The grab_collection script will have generated 3 text files that can be removed, namely:\n";
+print " - links.txt \n";
+print " - images.txt \n";
+print " - image_dirs.txt \n\n";
+if ($outputdir ne $finaldir)
+{
+    print "And then finally you can also delete the ",$outputdir," directory.\n\n";
+}
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/pstoimg.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/pstoimg.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/pstoimg.pl	(revision 13928)
@@ -0,0 +1,168 @@
+#!/usr/bin/perl -w
+
+
+###########################################################################
+#
+# pstoimg.pl -- convert PS documents to various types of Image format
+#
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 2001 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+# 
+###########################################################################
+# pstoimg.pl is a wrapper for running convert utility which converts
+# PS documents to various types of image (e.g. PNG, GIF, JPEG format, 
+# Then use PagedImgPlug to deal with the the images
+# Chi-Yu Huang 08.2005
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use parsargv;
+use util;
+use Cwd;
+use File::Basename
+;
+sub print_usage {
+    # note - we don't actually ever use most of these options...
+    print STDERR  
+	("pstoimg.pl wrapper for pstoimg.\n",
+	 "Usage: pstoimg [options] <PS-file> <output>\n",
+	 "Options:\n",
+	 "\t-convert_to\toutput image type for the PS\n"
+	 );
+    exit (1);
+}
+
+sub main {
+    my (@ARGV) = @_;
+    my ($convert_to);
+     
+    # read command-line arguments so that
+    # you can change the command in this script
+    if (!parsargv::parse(\@ARGV,
+			 'convert_to/.*/^', \$convert_to,
+			 )) {
+    	print_usage();
+    }
+ 
+    # Make sure the input file exists and can be opened for reading
+    if (scalar(@ARGV) != 2) {
+	print_usage();
+    }
+
+    my $input_filename = $ARGV[0];
+    my $output_filestem = $ARGV[1];
+    
+    # test that the directories exist to create the output file, or
+    # we should exit immediately. (File:: is included by util.pm)
+    &util::mk_dir($output_filestem) if (!-e $output_filestem);
+	    
+    my @dir = split (/(\/|\\)/, $input_filename);
+    my $input_basename = pop(@dir);
+    $input_basename =~ s/\.ps//i;
+    my $dir = join ("", @dir);
+    
+    if (!-r $input_filename) {
+	print STDERR "Error: unable to open $input_filename for reading\n";
+	exit(1);
+    }
+    # don't include path on windows (to avoid having to play about
+    # with quoting when GSDLHOME might contain spaces) but assume
+    # that the PATH is set up correctly.
+    $cmd = "convert";
+    #if ($ENV{'GSDLOS'} =~ /^windows$/);
+    #Convert utility will convert the PS to GIF Animation
+    my $output_filename = &util::filename_cat($output_filestem, $input_basename);
+    if ($convert_to eq "gif") {
+	$cmd .= " \"$input_filename\" \"$output_filename-%02d.$convert_to\"";
+    } else {
+	$cmd .= " \"$input_filename\" \"$output_filename.$convert_to\"";
+    }	
+
+    # system() returns -1 if it can't run, otherwise it's $cmds ret val.
+    # note we return 0 if the file is "encrypted"
+    $!=0;
+    if (system($cmd)!=0) {
+	print STDERR "Convert error for $input_filename $!\n";
+	# leave these for gsConvert.pl...
+	#&util::rm("$output_filestem.text") if (-e "$output_filestem.text");
+	#&util::rm("$output_filestem.err") if (-e "$output_filestem.err");
+	return 1;
+    } else {
+	# command execute successfully
+	create_itemfile($output_filestem, $input_basename, $convert_to);
+    }
+    return 0;
+}
+
+sub create_itemfile
+{
+    my ($output_dir, $convert_basename, $convert_to) = @_;
+    opendir(DIR, $output_dir) || die "can't opendir $output_dir: $!";  
+    my $item_file = $output_dir."/".$convert_basename.".item";
+    open(FILE,">$item_file");
+    
+    print FILE "<PagedDocument>\n";
+
+    my $page_num = "";
+    @dir_files = grep {-f "$output_dir/$_"} readdir(DIR);
+
+    # Sort files in the directory by page_num    
+    sub page_num {
+	my ($dir) = @_;
+	my $pagenum = "";
+	if ($ENV{'GSDLOS'} =~ /^windows$/){
+	   ($pagenum) =($dir =~ m/^.*\.(\d+)$/i);   
+	} else {
+	   ($pagenum) =($dir =~ m/^.*-(\d+)\.(.*)$/i);
+	}
+	$pagenum = $pagenum || 1;
+	return $pagenum;
+    }
+
+    # sort the files in the directory in the order of page_num rather than lexically. 
+    @dir_files = sort { page_num($a) <=> page_num($b) } @dir_files;
+
+    foreach my $file (@dir_files){
+        if ($ENV{'GSDLOS'} =~ /^windows$/ && $convert_to ne "gif"){
+	  ($page_num) =($file =~ m/^.*\.(\d+)$/i); 
+	} else {
+	    ($page_num) =($file =~ m/^.*-(\d+)\.(.*)/i);   
+	}
+	# as the converter will convert the document to image files start from page 0
+	$page_num =$page_num + 1 if defined $page_num;
+	$page_num = 1 unless defined $page_num;
+	if ($file !~ /\.item/i){
+	    print FILE "   <Page pagenum=\"$page_num\" imgfile=\"$file\" txtfile=\"\"/>\n";
+	} 
+    }
+
+    print FILE "</PagedDocument>\n";
+    closedir DIR;
+    return "";
+}
+
+# indicate our error status, 0 = success
+exit (&main(@ARGV));
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/removedocument.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/removedocument.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/removedocument.pl	(revision 13928)
@@ -0,0 +1,32 @@
+#!/usr/bin/perl -w
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/bin/script");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/cpan");
+    unshift (@INC, "$ENV{'GSDLHOME'}/collect/lld/perllib");
+}
+
+use util;
+
+use IncrementalBuildUtils; # Include John's incremental building API
+
+# Ensure the collection specific binaries are on the search path
+my $path_separator = ":";
+$ENV{'PATH'} = &util::filename_cat($ENV{'GSDLHOME'}, "bin", $ENV{'GSDLOS'}) .
+$path_separator . &util::filename_cat($ENV{'GSDLHOME'}, "bin", "script") .
+$path_separator . $ENV{'PATH'};
+
+if(!$ARGV[0] || !$ARGV[1]) {
+  print STDERR "Usage: removedocument <collection> <oid>\n";
+  exit;
+}
+
+my $collection = $ARGV[0];
+my $oid = $ARGV[1];
+
+&IncrementalBuildUtils::deleteDocument($collection, $oid);
+
+exit;
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/sendmail.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/sendmail.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/sendmail.pl	(revision 13928)
@@ -0,0 +1,92 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# sendmail.pl --
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 2000 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+# sendmail.pl is a simple wrapper around the Sendmail perl module written
+# by Milivoj Ivkovic <mi@alma.ch>
+
+# Input is either read from STDIN or, if the -msgfile option is set, read
+# from the given file.
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use lib qq($ENV{'GSDLHOME'}/perllib/cpan);
+use Mail::Sendmail;
+use parsargv;
+
+if (!parsargv::parse(\@ARGV, 
+		     'to/@', \$to,
+		     'from/@', \$from,
+		     'subject/.*/', \$subject,
+		     'html', \$html,
+		     'smtp/.*', \$smtp,
+		     'msgfile/.*/', \$msgfile)) {
+    print STDERR "\n";
+    print STDERR "sendmail.pl: A simple platform independant mail sending program.\n\n";
+    print STDERR "  usage: $0 [options]\n\n";
+    print STDERR "  options:\n";
+    print STDERR "   -to addr      Comma separated list of mail recipients\n";
+    print STDERR "   -from addr    Address of message sender\n";
+    print STDERR "   -subject str  Optional subject line\n";   
+    print STDERR "   -html         Send message as HTML\n";
+    print STDERR "   -smtp server  The outgoing (SMTP) mail server\n";
+    print STDERR "   -msgfile file A file from which message to be sent is read.\n";
+    print STDERR "                 If not set message will be read in from STDIN\n";
+    die "\n";
+}
+
+my %mail = ('SMTP' => $smtp, 
+	    'To' => $to,
+	    'From' => $from,
+	    'Subject' => $subject,
+	    );
+
+my $msg = "";
+if ($msgfile ne "") {
+    if (!open (MSGFILE, $msgfile)) {
+	print STDERR "ERROR: Failed to open $msgfile. Message was not sent\n";
+	exit (-1);
+    }
+    undef $/;
+    $msg = <MSGFILE>;
+    $/ = "\n";
+    close MSGFILE;
+} else {
+    $msg = <STDIN>;
+}
+
+$mail{'Content-type'} = "text/html; charset=\"iso-8859-1\"" if ($html);
+$mail{'Message'} = $msg;
+	
+if (!sendmail %mail) {
+    print STDERR "ERROR: Failed to send message\n";
+    print STDERR "'$Mail::Sendmail::error'\n";
+    exit (-1);
+}
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/set_metadata.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/set_metadata.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/set_metadata.pl	(revision 13928)
@@ -0,0 +1,51 @@
+#!/usr/bin/perl -w
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/bin/script");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use doc;
+use strict;
+# Include John's incremental building API
+use IncrementalBuildUtils;
+use IncrementalDocument;
+
+if (!$ARGV[0] || !$ARGV[1] || !$ARGV[2] || !$ARGV[3] || !$ARGV[4] || ($ARGV[3] eq "REPLACE" && !$ARGV[5])) {
+  print STDERR "Usage: set_metadata <collection> <oid> <metadata_field> (REPLACE <old_value> <new_value> | (ADD|REMOVE) <value>)\n";
+  print STDERR "[you tried: set_metadata ";
+  foreach my $arg (@$ARGV) {
+    print STDERR $arg . " ";
+  }
+  print STDERR "]\n";
+  exit;
+}
+
+my $collection = $ARGV[0];
+my $oid        = $ARGV[1];
+my $field      = $ARGV[2];
+my $action     = $ARGV[3];
+my $a_value    = $ARGV[4];
+my $b_value    = "";
+if ($action eq "REPLACE")
+{
+  $b_value     = $ARGV[5];
+}
+
+# We pass a 1 to force the indexes to be updated too.
+if ($action eq "ADD")
+{
+  &IncrementalBuildUtils::setDocumentMetadata($collection, $oid, $field, "", $a_value, 1);
+}
+elsif ($action eq "REMOVE")
+{
+  &IncrementalBuildUtils::setDocumentMetadata($collection, $oid, $field, $a_value, "", 1);
+}
+elsif ($action eq "REPLACE")
+{
+  &IncrementalBuildUtils::setDocumentMetadata($collection, $oid, $field, $a_value, $b_value, 1);
+}
+
+exit;
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/translate.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/translate.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/translate.pl	(revision 13928)
@@ -0,0 +1,488 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# translate.pl 
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+# translate.pl takes a translated macro file (filename passed in on command
+# line) and generates any images required by it. Check out english.dm for
+# an example of the format translate.pl expects
+
+# translate.pl uses gimp to generate images so needs gimp installed and set
+# up for scripting with perl
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use Gimp qw/:auto :DEFAULT/;
+use parsargv;
+use util;
+use unicode;
+
+# these html entities will be translated correctly when occurring in 
+# images. Any entities not in this list will not.
+my %rmap = ('auml' => chr (228),
+	    'euml' => chr (235),
+	    'iuml' => chr (239),
+	    'ouml' => chr (246),
+	    'uuml' => chr (252),
+	    'Auml' => chr (196),
+	    'Euml' => chr (203),
+	    'Iuml' => chr (207),
+	    'Ouml' => chr (214),
+	    'Uuml' => chr (220),
+	    'szlig' => chr (223),
+	    'aacute' => chr (225),
+	    'eacute' => chr (233),
+	    'iacute' => chr (237),
+	    'oacute' => chr (243),
+	    'uacute' => chr (250),
+	    'Aacute' => chr (193),
+	    'Eacute' => chr (201),
+	    'Iacute' => chr (205),
+	    'Oacute' => chr (211),
+	    'Uacute' => chr (218),
+	    'agrave' => chr (224),
+	    'egrave' => chr (232),
+	    'igrave' => chr (236),
+	    'ograve' => chr (242),
+	    'ugrave' => chr (249),
+	    'Agrave' => chr (192),
+	    'Egrave' => chr (200),
+	    'Igrave' => chr (204),
+	    'Ograve' => chr (210),
+	    'Ugrave' => chr (217),
+	    'ntilde' => chr (241),
+	    'Ntilde' => chr (209),
+	    'atilde' => chr (227),
+	    'Atilde' => chr (195),
+	    'otilde' => chr (245),
+	    'Otilde' => chr (213),
+	    'ccedil' => chr (231),
+	    'Ccedil' => chr (199),
+	    'ecirc' => chr (234),
+	    'Ecirc' => chr (202),
+	    'acirc' => chr (226),
+	    'Acirc' => chr (194),
+	    );
+
+my $hand_made = 0;
+
+sub print_usage {
+    print STDERR "\n";
+    print STDERR "translate.pl: Uses gimp to generate any images required by a\n";
+    print STDERR "              Greenstone macro file.\n\n";
+    print STDERR "  usage: $0 [options] macrofile\n\n";
+    print STDERR "  options:\n";
+    print STDERR "   -save_orig_file       edited macrofile will be written to\n";
+    print STDERR "                         macrofile.new leaving macrofile unchanged\n";
+    print STDERR "   -language_symbol      ISO abbreviation of language (e.g. German=de,\n";
+    print STDERR "                         French=fr, Maori=mi)\n";
+    print STDERR "   -image_dir directory  full path to directory in which to create images\n";
+    print STDERR "                         (defaults to `pwd`/images)\n\n";
+}
+
+sub gsdl_translate {
+
+    if (!parsargv::parse(\@ARGV, 
+			 'save_orig_file', \$save_orig_file,
+			 'language_symbol/[A-Za-z]{2}', \$language_symbol,
+			 'image_dir/.*/images', \$image_dir)) {
+	&print_usage();
+	die "\n";
+    }
+
+    if ($image_dir eq "images") {
+	$image_dir = `pwd`;
+	chomp $image_dir;
+	$image_dir = &util::filename_cat ($image_dir, "images");
+    }
+
+    if (!defined $ARGV[0]) {
+	print STDERR "no macro file supplied\n\n";
+	&print_usage();
+	die "\n";
+    }
+    my $macrofile = $ARGV[0];
+    die "\nmacrofile $macrofile does not exist\n\n" unless -e $macrofile;
+
+    if (!-e $image_dir) {
+	mkdir ($image_dir, 511) || die "\ncouldn't create image_dir $image_dir\n\n";
+    }
+
+    open (INPUT, $macrofile) || die "\ncouldn't open $macrofile for reading\n\n";
+    open (OUTPUT, ">$macrofile.new") || die "\ncouldn't open temporary file $macrofile.new for writing\n\n";
+
+    &parse_file (INPUT, OUTPUT);
+
+    close OUTPUT;
+    close INPUT;
+
+    if (!$save_orig_file) {
+	`mv $macrofile.new $macrofile`;
+    }
+
+    print STDERR "\n\n";
+    print STDERR "translation of macro file $macrofile completed\n";
+    print STDERR "the translated macro file is $macrofile.new\n" if $save_orig_file;
+    print STDERR "\n";
+    if ($hand_made) {
+	print STDERR "$hand_made hand made images were found within $macrofile,\n";
+	print STDERR "these will need to be made by hand (grep $macrofile for 'hand_made'\n\n";
+    }
+    print STDERR "To add your new interface translation to Greenstone you'll need to:\n";
+    print STDERR "  1. Copy your new macro file to your GSDLHOME/macros directory\n";
+    print STDERR "  2. Add your new macro file to the macrofiles list in your\n";
+    print STDERR "     GSDLHOME/etc/main.cfg configuration file\n";
+    print STDERR "  3. Copy your newly created images from $image_dir to \n";
+    print STDERR "     GSDLHOME/images/$language_symbol/\n\n";
+    print STDERR "Access your new interface language by setting the language (l) cgi\n";
+    print STDERR "argument to '$language_symbol'\n\n";
+
+}
+
+sub parse_file {
+    my ($input, $output) = @_;
+
+    undef $/;
+    my $dmfile = <$input>;
+    $/ = "\n";
+
+    # process all the images
+
+    $dmfile =~ s/(?:^|\n)\#\#\s*\"([^\"]*)\"\s*\#\#\s*([^\s\#]*)\s*\#\#\s*([^\s\#]*)\s*\#\#(.*?)(?=(\n\#|\s*\Z))/&process_image ($1, $2, $3, $4)/esg;
+
+    # add language parameter to each macro
+    $dmfile =~ s/(\n\s*)(_[^_]*_)\s*(\[[^\]]*\])?\s*\{/$1 . &add_language_param ($2, $3)/esg;
+    
+    print $output $dmfile;
+}
+
+sub process_image {
+    my ($text, $image_type, $image_name, $image_macros) = @_;
+
+    my $origtext = $text;
+
+    $text =~ s/&(\d{3,4});/chr($1)/ge;
+    $text =~ s/&([^;]*);/$rmap{$1}/g;
+
+    # Default font is set by the individual scripts (flash_button-1.2.pl etc), usually lucida
+    my $fontchoice = "";
+
+    # special case for Kazakh images (can also handle Russian) - encode to match Kazakh font
+    if ($language_symbol eq "kz") {  # || $language_symbol eq "ru") {
+	$text = &unicode::unicode2singlebyte(&unicode::utf82unicode($text), "kazakh");
+	$fontchoice = " -foundry 2rebels -fontname \"helv kaz\"";
+    }
+    # special case for Russian images - font is koi8-r encoded
+    elsif ($language_symbol eq "ru") {
+	$text = &unicode::unicode2singlebyte(&unicode::utf82unicode($text), "koi8_r");
+	$fontchoice = " -foundry cronyx -fontname helvetica";
+    }
+    # special case for Thai images
+    elsif ($language_symbol eq "th") {
+	$text = &unicode::unicode2singlebyte(&unicode::utf82unicode($text), "windows_874");
+	$fontchoice = " -foundry monotype -fontname BrowalliaUPC -fontregistry tis620";
+    }
+    # special case for Ukrainian images - font is windows_1251 encoded 
+    elsif ($language_symbol eq "uk") {
+	$text = &unicode::unicode2singlebyte(&unicode::utf82unicode($text), "windows_1251");
+	$fontchoice = " -foundry rfx -fontname serene";
+    }
+
+    # edit image macros
+    $image_macros =~ s/(_httpimg_\/)(?:[^\/\}]*\/)?([^\}]*\.(?:gif|jpe?g|png))/$1$language_symbol\/$2/gs;
+
+    if ($image_type eq "top_nav_button") {
+
+	# generate images
+	my $options = "-text \"$text\" -filenamestem $image_name -image_dir $image_dir";
+	$options .= " -height 20 -whitespace";
+	$options .= $fontchoice;
+
+	# special case for Kazakh images (can also handle Russian)
+	if ($language_symbol eq "kz") {  # || $language_symbol eq "ru") {
+	    $options .= " -fontsize 10 -fontweight bold";
+	}
+	# special case for Russian images
+	elsif ($language_symbol eq "ru") {
+	    $options .= " -fontsize 10 -fontweight bold";
+	}
+	# special case for Thai images
+	elsif ($language_symbol eq "th") {
+	    $options .= " -fontsize 20 -fontweight bold";  # Browallia
+	}
+	# special case for Ukrainian images
+	elsif ($language_symbol eq "uk") {
+	    $options .= " -fontsize 10";
+	}
+	else {
+	    $options .= " -fontsize 12";
+	}
+	`$ENV{'GSDLHOME'}/bin/script/gimp/flash_button-1.2.pl $options`;
+
+	# get width of new images and edit width macro
+	# my $fullfilename = &util::filename_cat ($image_dir, "${image_name}on.gif");
+	# &process_width_macro ($fullfilename, $image_name, \$image_macros);
+
+    }
+    elsif ($image_type eq "nav_bar_button") {
+
+	# generate on and off images
+	my $options = "-text \"$text\" -filenamestem $image_name -image_dir $image_dir";
+	$options .= " -height 17 -fixed_width -width 87";
+	$options .= $fontchoice;
+
+	# special case for Thai images
+	if ($language_symbol eq "th") {
+	    $options .= " -fontsize 18 -fontweight bold";  # Browallia
+	}
+	else {
+	    $options .= " -fontsize 17";
+	}
+
+	`$ENV{'GSDLHOME'}/bin/script/gimp/flash_button-1.2.pl $options`;
+
+	# generate green image
+	$options = "-text \"$text\" -filenamestem ${image_name}gr -image_dir $image_dir";
+	$options .= " -height 17 -fixed_width -width 87";
+	$options .= " -bgcolor \"#96c19b\"";
+	$options .= $fontchoice;
+
+	# special case for Thai images
+	if ($language_symbol eq "th") {
+	    $options .= " -fontsize 18 -fontweight bold";  # Browallia
+	}
+	else {
+	    $options .= " -fontsize 17";
+	}
+
+	`$ENV{'GSDLHOME'}/bin/script/gimp/flash_button-1.2.pl $options`;
+
+	# delete the unused light image
+	unlink(util::filename_cat($image_dir, "${image_name}gr" . "of.gif"));
+
+	# rename the dark image
+	&util::mv(util::filename_cat($image_dir, "${image_name}gr" . "on.gif"),
+		util::filename_cat($image_dir, "$image_name" . "gr.gif"));
+
+	# get width of new images and edit width macro
+	my $fullfilename = &util::filename_cat ($image_dir, "${image_name}on.gif");
+	&process_width_macro ($fullfilename, $image_name, \$image_macros);
+
+    }
+    elsif ($image_type eq "document_button") {
+
+	# generate on and off images
+	my $options = "-text \"$text\" -filenamestem $image_name -image_dir $image_dir";
+	$options .= " -fixed_width -whitespace";
+	$options .= $fontchoice;
+
+	# special case for Kazakh images (can also handle Russian)
+	if ($language_symbol eq "kz") {  # || $language_symbol eq "ru") {
+	    $options .= " -fontsize 8";
+	}
+	# special case for Russian images
+	elsif ($language_symbol eq "ru") {
+	    $options .= " -fontsize 8";
+	}
+	# special case for Thai images
+	elsif ($language_symbol eq "th") {
+	    $options .= " -fontsize 22 -fontweight bold";  # Browallia
+	}
+	# special case for Ukrainian images
+	elsif ($language_symbol eq "uk") {
+	    $options .= " -fontsize 8";
+	}
+	`$ENV{'GSDLHOME'}/bin/script/gimp/flash_button-1.2.pl $options`;
+
+	# get width of new images and edit width macro
+	# my $fullfilename = &util::filename_cat ($image_dir, "${image_name}on.gif");
+	# &process_width_macro ($fullfilename, $image_name, \$image_macros);
+
+    }
+    elsif ($image_type eq "collector_bar_button") {
+
+	$text =~ s/\\n/\n/g;
+	if ($text !~ /\n/) {
+	    # Format the text so it is centered, one word per line
+	    local @textparts = split(/[ \t\n]+/, $text);
+	    local $maxlength = 0;
+	    for ($i = 0; $i < scalar(@textparts); $i++) {
+		if (length($textparts[$i]) > $maxlength) {
+		    $maxlength = length($textparts[$i]);
+		}
+	    }
+	    $text = "";
+	    for ($i = 0; $i < scalar(@textparts); $i++) {
+		if (length($textparts[$i]) < $maxlength) {
+		    $text .= ' ' x ((($maxlength - length($textparts[$i])) / 2) + 1);
+		}
+		$text .= $textparts[$i] . "\n";
+	    }
+	}
+
+	# generate on and off images (yellow)
+	my $options = "-text \"$text\" -filenamestem yc$image_name -image_dir $image_dir";
+	$options .= " -width 77 -height 26 -fixed_width -whitespace -fontsize 13";
+	$options .= $fontchoice;
+
+	`$ENV{'GSDLHOME'}/bin/script/gimp/flash_button-1.2.pl $options`;
+
+	# generate on and off images (green)
+	$options = "-text \"$text\" -filenamestem gc$image_name -image_dir $image_dir";
+	$options .= " -width 77 -height 26 -fixed_width -whitespace -fontsize 13";
+	$options .= " -bgcolor \"#96c19b\"";
+	$options .= $fontchoice;
+
+	`$ENV{'GSDLHOME'}/bin/script/gimp/flash_button-1.2.pl $options`;
+
+	# generate on and off images (grey) - only the light image (off) is used
+	$options = "-text \"$text\" -filenamestem nc$image_name -image_dir $image_dir";
+	$options .= " -width 77 -height 26 -fixed_width -whitespace -fontsize 13";
+	$options .= " -bgcolor \"#7E7E7E\" -fontcolor \"#a0a0a0\"";
+	$options .= $fontchoice;
+
+	`$ENV{'GSDLHOME'}/bin/script/gimp/flash_button-1.2.pl $options`;
+
+	# delete the unused dark image
+	unlink(util::filename_cat($image_dir, "nc$image_name" . "on.gif"));
+
+    }
+    elsif ($image_type eq "green_bar_left_aligned") {
+
+	# generate green bar image (we're assuming these bars are always 537
+	# pixels and are never stretched by excess text
+	my $options = "-text \"$text\" -filename ${image_name}.gif -image_dir $image_dir";
+	$options .= " -dont_center -width 537 -width_space 15";
+	$options .= $fontchoice;
+
+	# special case for Thai images
+	if ($language_symbol eq "th") {
+	    $options .= " -fontsize 18 -fontweight bold";  # Browallia
+	}
+
+	`$ENV{'GSDLHOME'}/bin/script/gimp/green_bar-1.2.pl $options`;
+
+    }
+    elsif ($image_type eq "green_title") {
+	
+	# read the width if it is specified in $image_macros
+        my ($width) = $image_macros =~ /_width${image_name}x?_\s*[^\{]*\{(\d+)\}/;
+        $width = 200 unless ($width);
+
+        # generate green title image
+	my $options = "-text \"$text\" -filename ${image_name}.gif -image_dir $image_dir";
+	$options .= " -width $width -height 57 -stripe_alignment right -text_alignment right";
+        $options .= $fontchoice;
+
+        # special case for Thai images
+        if ($language_symbol eq "th") {
+	    $options .= " -fontsize 50 -fontweight bold";  # Browallia
+	}
+        else {
+	    $options .= " -fontsize 26 -fontweight bold";
+	}
+
+	`$ENV{'GSDLHOME'}/bin/script/gimp/title_icon-1.2.pl $options`;
+
+	# get width of resulting image and edit _width..._ macro in $image_macros
+        # (no longer needed since we always resize to the width read from $image_macros.)
+        # my $fullfilename = &util::filename_cat ($image_dir, "${image_name}.gif");
+	# &process_width_macro ($fullfilename, $image_name, \$image_macros);
+
+    }
+    elsif ($image_type eq "hand_made") {
+
+	$hand_made ++;
+
+    }
+    else {
+	
+	print STDERR "WARNING (translate.pl): unknown image type found ($image_type)\n";
+
+    }
+
+    return "\n\#\# \"$origtext\" \#\# $image_type \#\# $image_name \#\#$image_macros";
+}
+
+sub process_width_macro {
+    my ($filename, $image_name, $image_macros) = @_;
+
+    my $img_info = &get_img_info ($filename);
+    $$image_macros =~ s/(_width${image_name}x?_\s*(?:\[[^\]]*\])?\s*\{)(\d+)(\})/$1$img_info->{'width'}$3/s;
+}
+
+sub add_language_param {
+    my ($macroname, $paramlist) = @_;
+
+    my $first = 1;
+    if (defined $paramlist) {
+	$paramlist =~ s/^\[//;
+	$paramlist =~ s/\]$//;
+	my @params = split /\,/, $paramlist;
+	$paramlist = "";
+	foreach $param (@params) {
+	    # remove any existing language parameter
+	    if ($param !~ /^l=/) {
+		$paramlist .= "," unless $first;
+		$paramlist .= $param;
+		$first = 0;
+	    }
+	}
+    }
+    $paramlist .= "," unless $first;
+    $paramlist .= "l=" . $language_symbol;
+    return "$macroname [$paramlist] {";
+}
+
+sub get_img_info {
+    my ($imagefile) = @_;
+    my %info = ();
+
+    if (!-r $imagefile) {
+	print STDERR "ERROR (translate.pl): couldn't open $imagefile to get dimensions\n";
+	$info{'width'} = 0;
+	$info{'height'} = 0;
+    } else {
+	my $image = gimp_file_load (RUN_NONINTERACTIVE, $imagefile, $imagefile);
+	$info{'width'} = gimp_image_width ($image);
+	$info{'height'} = gimp_image_height ($image);
+    }
+
+    return \%info;
+}
+
+sub query {
+
+  gimp_install_procedure("gsdl_translate", "translate macro files and create images",
+                        "", "Stefan Boddie", "Stefan Boddie", "2000-03-14",
+                        "<Toolbox>/Xtns/gsdl_translate", "*", &PROC_EXTENSION,
+                        [[PARAM_INT32, "run_mode", "Interactive, [non-interactive]"]], []);
+}
+
+Gimp::on_net {   gsdl_translate; };
+exit main;
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/unbuildv1.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/unbuildv1.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/unbuildv1.pl	(revision 13928)
@@ -0,0 +1,747 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# unbuildv1.pl --
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+# this program will decompress all the text from a built index
+# and return it to gml format - this version of the program is designed to
+# work on collections built with the first version of the greenstone software
+# it extracts the browse classifications from the gdbm file, and recreates 
+# them. It also creates a default collect.cfg file.
+
+# To run, this program needs the old archive directory (called archives),
+# the index directory with the text and one other index, not paragraphs!! -
+# use one of the section indexes. Also needs the build.cfg file (in the
+# index dir) - used in creating a collect.cfg file. If build.cfg is not
+# present, the parts of the collect.cfg file relating to indexes will not
+# be entered.
+
+# Stefan altered this script slightly August 2002 to use
+# $GSDLHOME/bin/$GSDLOS/mgquery_old instead of the old mgquery in
+# nzdl-1.2. mgquery_old is a statically linked binary compiled from
+# mg-1.3d. It was compiled with SHORT_SUFFIX set so doesn't need the index
+# file extensions to be altered. 
+# Also changed the command line options a little.
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+    $FileHandle = 'FH000';
+}
+
+use doc;
+use util;
+use parsargv;
+use FileHandle;
+use English;
+use cfgread;
+use unicode;
+use plugout;
+select STDERR; $| = 1;
+select STDOUT; $| = 1;
+
+
+# globals
+$collection = "";  # the collection name
+$index = "";  # the selected index (like stt/unu)
+$textdir = ""; # the textdir (like text/unu)
+$toplevelinfo = []; #list of document OIDs
+%infodb = (); #hash into GDBM file
+$classifyinfo = []; # list of classifications
+$doc_classif_info = {};  # hash of OIDs->classifications they belong to
+$collect_cfg = {}; #data for the configuration file
+$mgread = ++$FileHandle;
+$mgwrite = ++$FileHandle;
+
+sub print_usage {
+    print STDERR "\n  usage: $0 [options]\n\n";
+    print STDERR "  options:\n";
+    print STDERR "   -verbosity number      0=none, 3=lots\n";
+    print STDERR "   -old directory         The directory in which the old collection lives\n";
+    print STDERR "   -new directory         The directory in which to put the new collection\n";
+}
+
+&main ();
+
+sub main {
+    if (!parsargv::parse(\@ARGV, 
+			 'verbosity/\d+/2', \$verbosity,
+			 'old/.*/', \$old,
+			 'new/.*/', \$new)) {
+	&print_usage();
+	die "\n";
+    }
+
+    die "$old does not exist\n\n" unless (-d $old);
+    my $old_indexdir = &util::filename_cat($old, "index");
+    my $old_archivedir = &util::filename_cat($old, "archives");
+
+    my $new_archivedir = &util::filename_cat($new, "archives");
+    my $new_etcdir = &util::filename_cat($new, "etc");
+    if (!-e $new_archivedir) {
+	&util::mk_all_dir($new_archivedir);
+    }
+    if (!(-d $new_etcdir)) {
+	&util::mk_all_dir($new_etcdir);
+    }
+
+    my $gdbmfile = &get_gdbmfile($old_indexdir); # sets $collection and $textdir
+    &set_index($old_indexdir);  # sets $index (just chooses one index)
+
+    my $buildcfgfile = &util::filename_cat($old_indexdir, "build.cfg");
+    my $colcfgfile = &util::filename_cat($new_etcdir, "collect.cfg");
+
+    # don't need this but giving it a value stops an annoying undefined
+    # value warning
+    $ENV{'GSDLCOLLECTDIR'} = 'tmp';
+
+    &add_default_cfg();
+    &add_index_cfg($buildcfgfile);
+
+    # work out all the classifications from the gdbm file, info for each doc
+    # (ie which classifications they belong to, are kept in $doc_classif_info
+    &get_classifyinfo($gdbmfile); #puts a list of classifications into classifyinfo
+    &get_toplevel_OID($gdbmfile); # puts a list of the top level document OIDs into $toplevelinfo
+
+    # read ldb file into %infodb
+    &read_gdbm($gdbmfile);
+
+    #this makes the files specifying the hierarchy of subjects, titles etc
+    foreach my $classify (@$classifyinfo) {
+	&make_info_file($new_etcdir, $classify);
+    }
+    
+    # write out the collect.cfg
+    &output_cfg_file($colcfgfile);
+
+    &openmg($old_indexdir);
+
+    # read the archive information file
+    my $archive_info_filename = &util::filename_cat ($new_archivedir, "archives.inf");
+    my $archive_info = new arcinfo ();
+
+    my $opts = [];
+    push @$opts,("-output_info",$archive_info); 
+
+    $processor = &plugout::load_plugout("GAPlugout",$opts); 
+    $processor->setoutputdir ($new_archivedir);
+
+    my ($doc_obj, $hashref, $children);
+    print STDERR "processing documents now\n" if $verbosity >=2;
+    foreach $oid (@$toplevelinfo) {
+	$value = $infodb{$oid};
+	$hashref={};
+	$children = [];
+	&get_metadata($value, $hashref);
+	$doc_obj = new doc ();
+	$doc_obj->set_OID($oid);
+	my ($olddir) = $hashref->{'archivedir'}; # old dir for this doc, where images are stored
+	$top = $doc_obj->get_top_section();
+	&add_section_content ($doc_obj, $top, $hashref, $olddir);
+	&add_classification_metadata($oid, $doc_obj, $top);
+	&add_cover_image($doc_obj, $old_archivedir, $olddir);
+	&get_children($hashref, $children);
+	&recurse_sections($doc_obj, $children, $oid, $top, $olddir) if (defined ($children));
+
+	#change OID to new format
+	$doc_obj->delete_OID();
+	$doc_obj->set_OID();
+	$processor->process($doc_obj);
+#	last;
+    }
+    print STDERR "\n";
+   
+    &closemg();
+
+    # write out the archive information file
+    $archive_info->save_info($archive_info_filename);
+   
+    
+}
+
+# returns the path to the gdbm info database - also
+# sets the $collection and $textdir global variable
+sub get_gdbmfile {
+    my ($indexdir) = @_;
+    my ($gdbmfile);
+
+    opendir (DIR, $indexdir) || die "Couldn't open directory $indexdir\n\n";
+    my @conts = readdir DIR;
+    close DIR;
+
+    foreach $file (@conts) {
+	if ($file =~ /text$/) {
+	    $textdir = $file;
+	    last;
+	}
+    }
+    die "No text directory found in $indexdir\n\n" 
+	unless defined $textdir && $textdir =~ /text$/;
+
+    $gdbmfile = &util::filename_cat ($indexdir, $textdir);
+
+    opendir (DIR, $gdbmfile) || die "Couldn't open directory $gdbmfile\n\n";
+    @conts = readdir DIR;
+    close DIR;
+
+    foreach my $file (@conts) {
+	if ($file =~ /^(.*?)\.(?:ldb|bdb)$/) {
+	    $collection = $1;
+	    $gdbmfile = &util::filename_cat ($gdbmfile, $file);
+	    last;
+	}
+    }
+    
+    if (defined $collection && $collection =~ /\w/) {
+	$textdir = &util::filename_cat ($textdir, $collection);
+    } else {
+	die "collection global wasn't set\n";
+    }
+    return $gdbmfile if (-e $gdbmfile);
+    die "Couldn't find gdbm info database in $indexdir\n\n";
+}
+
+
+#this function will probably need to be changed for any different file formats
+sub get_toplevel_OID {
+    my ($gdbmfile) = @_;
+
+    open (DB2TXT, "db2txt $gdbmfile |") || die "couldn't open pipe to db2txt\n";
+    print STDERR "Finding all top level sections from $gdbmfile\n" if $verbosity >= 2;
+
+    $/ = '-' x 70;
+    my $entry = "";
+    while (defined ($entry = <DB2TXT>)) {
+	next unless $entry =~ /\w/;  #ignore blank entries
+	$entry =~ s/\n+/\\n/g;  # replace multiple \n with single \n
+	my ($key, $value) = $entry =~ /\[([^\]]*)\](.*)/;
+
+	next unless ($key =~ /B\.\d*$/); # assumes top level OID is like
+	                                 # B.12
+
+	push( @$toplevelinfo, $key);
+   
+    }
+
+    $/ = "\n";
+}
+    
+# gets all the metadata from a gdbm file entry, and puts it into a hashref
+#this has changed for old style formats
+sub get_metadata {
+
+    my ($gdb_str_ref, $hashref) = @_;
+#    print STDERR $gdb_str_ref;
+    my @entries = split(/\n/, $gdb_str_ref);
+
+    my $hastext = 1;
+    foreach $entry (@entries) {
+	
+	my($key, $value) = ($entry =~ /^<([^>]*)>(.*?)$/ );
+
+	next if ($key eq "p");
+	next if ($key eq "j");
+	
+	$key = "Title" if $key eq "t";
+	$key = "docnum" if $key eq "d";	
+	if ($key eq "o") {
+	    $key = "archivedir";
+	    $value =~ s/HASH/hash/;
+	}
+	if ($key eq "c") {
+	    $key = "contains";
+	    $hastext=0;}
+
+	$$hashref{$key} .= $value;
+						  
+    }
+    
+    $$hashref{'hastxt'} = $hastext;
+
+}					  
+
+# takes a hashref containing the metadata for a gdbmfile entry, and
+# extracts the childrens numbers (from the 'contains' entry).  assumes
+# format is like B.14.1:B.24.2:B.24.3 returns a list like 1 2 3 4
+sub get_children {	
+    my ($hashref, $children) = @_; 
+
+    my $childs = $hashref->{'contains'};
+    if (defined ($childs)) {
+	@xchildren = split /\:/, $childs;
+	foreach $kid (@xchildren) {
+	    my ($child)= $kid =~ /\.([^\.]*)(?:\\n|$)/;
+	    push (@$children, $child);
+	}
+#	print STDERR "children are: ", @$children;
+    }
+    else {
+	$children = [];
+    }
+}
+
+#takes a hashref containing the metadata for a gdbmfile entry, and extracts 
+#the childrens numbers (from the 'contains' entry).	
+#assumes format is like B.14.1:B.24.2:B.24.3
+#returns a list with the full child name ie B.14.1 B.14.2 etc
+#used for classification stuff
+sub get_whole_children {	
+
+    my ($hashref, $children) = @_; 
+
+    my $childs = $hashref->{'contains'};
+    if (defined ($childs)) {
+	@$children = split /\:/, $childs;
+	#print STDERR "children are: ", @$children;
+    }
+    else {
+	$children = [];
+    }
+}
+    
+sub recurse_sections {
+    my ($doc_obj, $children, $parentoid, $parentsection, $olddir) = @_;
+
+    foreach $child (sort numerically @$children) {
+	$doc_obj->create_named_section("$parentsection.$child");
+	my $value = $infodb{"$parentoid.$child"};
+	my $hashref={};
+	&get_metadata($value, $hashref); # get childs metadata
+	my $newchildren = [];
+	&get_children($hashref, $newchildren); # get childs children
+	#add content fo rcurrent section
+	&add_section_content($doc_obj, "$parentsection.$child", $hashref, $olddir);
+	# process all the children if there are any
+	&recurse_sections($doc_obj, $newchildren, "$parentoid.$child", "$parentsection.$child", $olddir)
+	    if (defined ($newchildren));
+    }
+}					     
+
+sub add_section_content {
+    my ($doc_obj, $cursection, $hashref, $olddir) = @_;
+    
+    foreach $key (keys %$hashref) {
+	#dont need to store these metadata
+	next if $key =~ /(contains|docnum|hastxt|doctype|archivedir|classifytype)/i;
+	my @items = split /@/, $hashref->{$key};
+	map {$doc_obj->add_metadata ($cursection, $key, $_); } @items;
+	
+    }
+
+    my ($hastext) = $hashref->{'hastxt'} =~ /(0|1)/;
+    if ($hastext) {
+	
+	my ($docnum)= $hashref->{'docnum'} =~ /(\d*)/;
+	my $text = &get_text($docnum);
+	$doc_obj->add_text ($cursection, $text);
+	
+	my (@images) = $text =~ /<img.*?src=\"([^\"]*)\"[^>]*>/g;
+	
+	if (scalar(@images)>0) {
+	    
+	    foreach $img (@images) {
+		my ($assoc_file) = $img =~ /([^\/\\]*\..*)$/; #the name of the image
+		$img =~ s/_httpcollection_/$old/; #replace _httpcollection_ with path to old collection
+		$olddir =~ s/HASH/hash/;
+		$img =~ s/_thisOID_/$olddir/; #replace _thisOID_ with old archivedir name   #the path to the image
+		$img = lc $img; # doc names and path upper case in file, lower
+		# case in directory
+		if (-e $img) {
+		    $doc_obj->associate_file($img, $assoc_file);
+		} else {
+		    print STDERR "WARNING: $img does not exist\n";
+		}
+	    }
+	    
+	}
+    }
+}
+
+
+sub add_classification_metadata {
+
+    my ($oid, $doc_obj, $cursection) = @_;
+    
+    if (defined $doc_classif_info->{$oid}) {
+
+	$hashref = $doc_classif_info->{$oid};
+	
+	foreach $key (keys %$hashref) {
+	    my @items = @{$hashref->{$key}};
+	    map {$doc_obj->add_metadata ($cursection, $key, $_); } @items;
+	}
+    }
+}
+# picks up the cover image "cover.jpg" from the old archives directory.
+sub add_cover_image {
+    my ($doc_obj, $archivedir, $olddir) =  @_;
+    $assoc_file = "cover.jpg";
+    $img = &util::filename_cat($archivedir, $olddir, $assoc_file);
+
+    if (-e $img) {
+	$doc_obj->associate_file($img, $assoc_file);
+    } else {
+	print STDERR "WARNING: couldn't find $img\n";
+    }
+}
+
+sub set_index {
+    my ($indexdir) = @_;
+
+    # check that $collection has been set
+    die "collection global was not set\n"
+	unless defined $collection && $collection =~ /\w/;
+
+    # find an index (just use first non-text and non-paragraph directory we
+    # come across in $indexdir)
+    opendir (INDEXDIR, $indexdir) || die "couldn't open directory $indexdir\n";
+    my @indexes = readdir INDEXDIR;
+    close INDEXDIR;
+    foreach $i (@indexes) {
+	next if $i =~ /text$/i || $i =~ /\./ || $i =~ /^p/i;
+	$index = &util::filename_cat ($i, $collection);
+	last;
+    }
+}
+
+
+#########################################################################
+
+################ functions involving mg ################################
+sub get_text {
+    my ($docnum) = @_;
+
+    print STDERR "." if $verbosity >= 2;
+    &mgcommand ($docnum);
+
+   <$mgread>;	# eat the document separator
+
+    my $text = "";
+    my $line = "";
+
+    while (defined ($line = <$mgread>))
+    {
+	last if $line =~ /^<\/mg>/;
+	$text .= $line;
+    }
+
+    # Read in the last statement, which should be:
+    #  "dd documents retrieved."
+    <$mgread>;
+
+    return $text;
+}
+
+
+sub numerically {$a <=> $b;}
+
+
+
+# mg stuff
+
+sub openmg {
+    my ($indexdir) = @_;
+
+    die "Unable to start mgquery." unless
+	&openpipe($mgread, $mgwrite, "mgquery_old -d $indexdir -f $index -t $textdir");
+
+    $mgwrite->autoflush();
+    &mgcommand('.set expert true');
+    &mgcommand('.set terminator "</mg>\n"');
+    &mgcommand('.set mode text');
+    &mgcommand('.set query docnums');
+    &mgcommand('.set term_freq off');
+}
+
+sub closemg {
+    &mgcommand (".quit");
+    close($mgread);
+    close($mgwrite);
+}
+
+sub mgcommand {
+    my ($command) = @_;
+
+    return if $command =~ /^\s*$/;  #whitespace
+    #print STDERR "command: $command\n";
+    print $mgwrite "$command\n";
+
+    # eat up the command executed which is echoed
+    <$mgread>;
+}
+
+# openpipe(READ, WRITE, CMD)
+# 
+# Like open2, except CMD's stderr is also redirected.
+# 
+sub openpipe
+{
+    my ($read, $write, $cmd) = @_;
+    my ($child_read, $child_write);
+
+    $child_read = ++$FileHandle;
+    $child_write = ++$FileHandle;
+
+    pipe($read, $child_write) || die "Failed pipe($read, $child_write): $!";
+    pipe($child_read, $write) || die "Failed pipe($child_read, $write): $!";
+    my $pid;
+
+    if (($pid = fork) < 0) {
+        die "Failed fork: $!";
+    } elsif ($pid == 0) {
+        close($read);
+        close($write);
+        open(STDIN, "<&$child_read");
+        open(STDOUT, ">&$child_write");
+        open(STDERR, ">&$child_write");
+        exec($cmd);
+        die "Failed exec $cmd: $!";
+    }
+
+    close($child_read);
+    close($child_write);
+
+    $write->autoflush();
+    $read->autoflush();
+
+    return 1;
+}
+
+
+######################################################################
+
+############# functions to do with the classificaiton stuff ##########
+sub get_classifyinfo {
+    my ($gdbmfile) = @_;
+
+    open (DB2TXT, "db2txt $gdbmfile |") || die "couldn't open pipe to db2txt\n";
+    print STDERR "Finding all classification sections from $gdbmfile\n" ;
+
+    $/ = '-' x 70;
+    my $entry = "";
+    while (defined ($entry = <DB2TXT>)) {
+	next unless $entry =~ /\w/;  #ignore blank entries
+	$entry =~ s/\n+/\\n/g;  # replace multiple \n with single \n
+	my ($key, $value) = $entry =~ /\[([^\]]*)\](.*)/;
+
+	next unless ($key =~/^[A-Z]$/); # assumes classification OID is like
+	                                 # C or T etc
+
+	push( @$classifyinfo, $key);
+   
+    }
+
+    $/ = "\n";
+}
+
+#this creates the classification files needed for the hierarchy classifier
+#used for subjects, titles, orgs etc
+#also adds in entries to the collect_cfg hash    
+sub make_info_file {
+    my ($etcdir, $classifier) = @_;
+    my $info_file = "";
+
+    $info_file = &util::filename_cat($etcdir, "CL.${classifier}.txt");
+    $classifier_name = "CL.$classifier";
+    print STDERR "classification $classifier will be called CL.$classifier\n";
+
+    open (OUTDOC, ">$info_file" ) || die  "couldn't open file $info_file\n";
+	
+    my $entry = $infodb{$classifier};
+    #print STDERR "entry = $entry\n";
+    my $hashref = {};
+    &get_metadata($entry, $hashref);
+    my $children=[];
+    &get_whole_children($hashref, $children);
+    foreach $child (@$children) {
+	&process_entry(OUTDOC, $classifier_name, $child);
+    }
+  
+    close OUTDOC;
+    
+    &add_classify_cfg($classifier, $classifier_name, $info_file);
+    
+}
+
+
+sub process_entry {
+    my ($handle, $classifier_name, $classify_id) = @_;
+
+    my $value = $infodb{$classify_id};
+    my $hashref={};
+    &get_metadata($value, $hashref);
+    my $title = $hashref->{'Title'};
+
+    &add_line($handle, $classify_id, $title);
+    
+    my $children = [];
+    &get_whole_children($hashref, $children);
+    foreach $child (@$children) {
+	if (&is_document($child)) {
+	    &add_doc_metadata($child, $classifier_name, $classify_id);
+	}
+	else {
+	    &process_entry($handle, $classifier_name, $child);
+	}
+    }
+}
+
+sub add_doc_metadata {
+    my ($doc_id, $classifier_name, $classifier_id) = @_;
+
+    #add entry to doc database
+    #print STDERR "at doc level, docnum=$classify_id\n";
+    $doc_classif_info->{$doc_id}={} unless defined $doc_classif_info->{$doc_id};
+    $doc_classif_info->{$doc_id}->{$classifier_name}=[] unless
+	defined $doc_classif_info->{$doc_id}->{$classifier_name};
+    push (@{$doc_classif_info->{$doc_id}->{$classifier_name}}, $classifier_id); 
+}
+
+sub add_line {
+    my ($handle, $classify_id, $title) = @_;
+    $title = &unicode::ascii2utf8(\$title);
+    my ($num) = $classify_id =~ /^[A-Z]\.(.*)$/; #remove the C. from the front
+    print $handle "$classify_id\t$num\t\"$title\"\n";
+}
+
+sub is_document {
+    my ($oid) = @_;
+    return 1 if $oid =~ /^B\.\d/;
+    return 0;
+}
+    
+########################################################################
+
+########## stuff for producing collect.cfg file ###########################
+
+sub add_default_cfg {
+
+    $username=`whoami`;
+    $username=`logname` unless defined $username;
+    $username="a_user" unless defined $username;
+    $username =~ s/\n//;
+    $collect_cfg->{'creator'}="$username\@cs.waikato.ac.nz";
+    $collect_cfg->{'maintainer'}="$username\@cs.waikato.ac.nz";
+    $collect_cfg->{'public'}="true";
+    
+    $collect_cfg->{'plugin'}=[];
+    push (@{$collect_cfg->{'plugin'}}, ["GAPlug"]);
+    push (@{$collect_cfg->{'plugin'}}, ["ArcPlug"]);
+    push (@{$collect_cfg->{'plugin'}}, ["RecPlug"]);
+
+    $collect_cfg->{'format'}={};
+    $collect_cfg->{'format'}->{'DocumentImages'}="true";
+    $collect_cfg->{'format'}->{'DocumentText'} = 
+	"\"<h3>[Title]</h3>\\\\n\\\\n<p>[Text]\"";
+    $collect_cfg->{'format'}->{'SearchVList'} =
+	"\"<td valign=top>[link][icon][/link]</td><td>{If}{[parent(All': '):Title],[parent(All': '):Title]:}[link][Title][/link]</td>\"";
+
+    $collect_cfg->{'collectionmeta'}={};
+    $collect_cfg->{'collectionmeta'}->{'collectionname'}="\"$collection\"";
+    $collect_cfg->{'collectionmeta'}->{'iconcollection'}="\"_httpprefix_/collect/$collection/images/$collection.gif\"";
+    $collect_cfg->{'collectionmeta'}->{'iconcollectionsmall'}="\"_httpprefix_/collect/$collection/images/${collection}sm.gif\"";
+    $collect_cfg->{'collectionmeta'}->{'collectionextra'} = "\"This is a collection rebuilt from CDROM.\"";
+
+}
+
+sub add_index_cfg {
+  my ($buildfile) = @_;
+
+  my $data={};
+  $collect_cfg->{'indexes'}=[];
+  if (-e $buildfile) {
+      $data=&cfgread::read_cfg_file($buildfile, '^(this)$', '^(indexmap)$'); 
+      foreach my $i (@{$data->{'indexmap'}}) {
+          my ($thisindex, $abbrev)= split (/\-\>/, $i);
+          push (@{$collect_cfg->{'indexes'}}, $thisindex);
+	  $collect_cfg->{'defaultindex'} = $thisindex unless defined 
+	      $collect_cfg->{'defaultindex'};
+          $name=&get_index_name($thisindex);
+	  $thisindex=".$thisindex";
+          $collect_cfg->{'collectionmeta'}->{$thisindex} = "\"$name\"";
+      } 
+  }
+  else {
+      print STDERR "Couldn't read $buildfile, could not add index data to configuration file\n";
+  }
+
+}
+
+sub get_index_name {
+    my ($thisindex) = @_;
+    return "paragraphs" if $thisindex =~ /paragraph/;
+    return "chapters" if $thisindex =~ /section.*text/;
+    return "titles" if $thisindex =~ /Title/;
+    return "other";
+}
+
+sub add_classify_cfg {
+
+    my ($classify, $metadata, $file) = @_;
+    $collect_cfg->{'classify'} = [] unless defined $collect_cfg->{'classify'};
+
+    my ($title);
+    $title = "Howto" if $classify eq 'H';
+    $title = "Subject" if $classify eq 'C';
+    $title = "Organization" if $classify eq 'O';
+    $title = "Title" if $classify eq 'T';
+    $title = "Other" unless defined $title;
+
+    my ($filename) = $file =~ /\/([^\/]*)$/;
+    my $entry = "Hierarchy -hfile $filename -metadata $metadata -buttonname $title -sort Title";
+    $entry .= " -hlist_at_top" if $title eq "Title";
+    push (@{$collect_cfg->{'classify'}},[$entry]);
+   
+
+}
+
+sub output_cfg_file {
+
+    my ($collfile) = @_;
+    &cfgread::write_cfg_file($collfile, $collect_cfg, 
+			     '^(creator|maintainer|public|beta|defaultindex)$',
+                            '^(indexes)$', '^(format|collectionmeta)$',
+                            '^(plugin|classify)$');
+}
+
+sub read_gdbm {
+    my ($filename) = @_;
+
+    open (PIPEIN, "db2txt \"$filename\" |") || die "couldn't open pipe from db2txt\n";
+    my $line = ""; my $key = ""; my $value = "";
+    while (defined ($line = <PIPEIN>)) {
+	if ($line =~ /^\[([^\]]+)\]$/) {
+	    $key = $1;
+	} elsif ($line =~ /^-{70}$/) {
+	    $infodb{$key} = $value;
+	    $value = "";
+	    $key = "";
+	} else {
+	    $value .= $line;
+	}
+    }
+    close PIPEIN;
+}
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/unbuildv2.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/unbuildv2.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/unbuildv2.pl	(revision 13928)
@@ -0,0 +1,788 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# unbuildv2.pl --
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+# this program will decompress all the text from a built index
+# and return it to gml format -
+#this is based on the format current in Nov 1999. (version two)
+
+# Stefan updated unbuildv1.pl in August 2002 but unbuildv2.pl was not
+# updated. It probably needs some work done before using.
+
+# Katherine updated this but apparently it still doesn't work.
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+    $FileHandle = 'FH000';
+}
+
+use unbuildutil;
+use doc;
+use util;
+use parsargv;
+use GDBM_File;
+use FileHandle;
+use English;
+use cfgread;
+use unicode;
+use plugout;
+
+select STDERR; $| = 1;
+select STDOUT; $| = 1;
+
+
+# globals
+$collection = "";  # the collection name
+$index = "";  # the selected index (like stt/unu)
+$textdir = ""; # the textdir (like text/unu)
+$toplevelinfo = []; #list of document OIDs
+%infodb = (); #hash into GDBM file
+$classifyinfo = []; # list of classifications
+$doc_classif_info = {};  # hash of OIDs->classifications they belong to
+$collect_cfg = {}; #data for the configuration file
+
+$mgread = ++$FileHandle;
+$mgwrite = ++$FileHandle;
+
+
+
+sub print_usage {
+    print STDERR "\n  usage: $0 [options]\n\n";
+    print STDERR "  options:\n";
+    print STDERR "   -verbosity number      0=none, 3=lots\n";
+    print STDERR "   -indexdir directory    The index to be decompressed (defaults to ./index)\n";
+    print STDERR "   -archivedir directory  Where the converted material ends up (defaults to ./archives.new\n";
+    print STDERR "   -removeold             Will remove the old contents of the archives\n";
+    print STDERR "                          directory -- use with care\n\n";
+}
+
+&main ();
+
+sub main {
+    if (!parsargv::parse(\@ARGV, 
+			 'verbosity/\d+/2', \$verbosity,
+			 'indexdir/.*/index', \$indexdir,
+			 'archivedir/.*/archives.new', \$archivedir,
+			 'removeold', \$removeold)) {
+	&print_usage();
+	die "\n";
+    }
+
+    die "indexdir $indexdir does not exist\n\n" unless (-d $indexdir);
+    $indexdir =~ s/\/$//;
+    if (-d $archivedir) {
+	if ($removeold) {
+	    print STDERR "Warning - removing current contents of the archives directory $archivedir\n";
+	    print STDERR "          in preparation for the import\n";
+	    sleep(5); # just in case...
+	    &util::rm_r ($archivedir);
+	}
+    } else {
+	&util::mk_all_dir ($archivedir);
+    }
+
+    $etcdir = "./etc";
+    if (!(-d $etcdir)) {
+	&util::mk_all_dir ($etcdir);
+    }
+
+
+    my $gdbmfile = &get_gdbmfile ($indexdir); #sets $collection and $textdir
+    &set_index ();  # sets $index (just chooses one index)
+
+
+    my $buildcfgfile = &util::filename_cat($indexdir, "build.cfg");
+    my $colcfgfile = &util::filename_cat($etcdir, "collect.cfg");
+
+    &add_default_cfg();
+    &add_index_cfg($buildcfgfile);
+
+
+    #work out all the classifications from the gdbm file, info for each doc
+#(ie which classifications they belong to, are kept in $doc_classif_info
+    &get_classifyinfo ($gdbmfile); #puts a list of classifications into classifyinfo
+
+    &get_toplevel_OID ($gdbmfile); # puts a list of the top level document OIDs into $toplevelinfo
+
+    #tie (%infodb, "GDBM_File", $gdbmfile, 1, 0);
+    
+    #read ldb file into %infodb
+    &unbuildutil::read_gdbm($gdbmfile, \%infodb);
+
+    #this makes the files specifying the hierarchy of subjects, titles etc
+    foreach $classify (@$classifyinfo) {
+	
+	&make_info_file($classify);
+
+    }
+
+    
+    #write out the collect.cfg
+    &output_cfg_file($colcfgfile);
+
+    &openmg ();
+
+    # read the archive information file
+    my $archive_info_filename = &util::filename_cat ($archivedir, "archives.inf");
+    my $archive_info = new arcinfo ();
+
+    my $opts = [];
+    push @$opts,("-output_info",$archive_info); 
+
+    $processor = &plugout::load_plugout("GAPlugout",$opts); 
+    $processor->setoutputdir ($new_archivedir);
+
+    my ($doc_obj, $hashref, $children);
+    print STDERR "processing documents now\n" if $verbosity >=2;
+    foreach $oid (@$toplevelinfo) {
+	$value = $infodb{$oid};
+	$hashref={};
+	$children = [];
+	&get_metadata($value, $hashref);
+	$doc_obj = new doc ();
+	$doc_obj->set_OID($oid);
+	my ($olddir) = $hashref->{'archivedir'}; # old dir for this doc, where images are stored
+	$top = $doc_obj->get_top_section();
+	&add_section_content ($doc_obj, $top, $hashref, $olddir);
+	&add_classification_metadata($oid, $doc_obj, $top);
+	&add_cover_image($doc_obj, $olddir);
+	&get_children($hashref, $children);
+	&recurse_sections($doc_obj, $children, $oid, $top, $olddir);
+	$processor->process($doc_obj);
+	
+    }
+    print STDERR "\n";
+   
+    &closemg();
+
+    # write out the archive information file
+    $archive_info->save_info($archive_info_filename);
+}
+
+# returns the path to the gdbm info database - also
+# sets the $collection and $textdir global variable
+sub get_gdbmfile {
+    my ($indexdir) = @_;
+    my ($gdbmfile);
+
+    opendir (DIR, $indexdir) || die "Couldn't open directory $indexdir\n\n";
+    my @conts = readdir DIR;
+    close DIR;
+
+    foreach $file (@conts) {
+	if ($file =~ /text$/) {
+	    $textdir = $file;
+	    last;
+	}
+    }
+    die "No text directory found in $indexdir\n\n" 
+	unless defined $textdir && $textdir =~ /text$/;
+
+    $gdbmfile = &util::filename_cat ($indexdir, $textdir);
+
+    opendir (DIR, $gdbmfile) || die "Couldn't open directory $gdbmfile\n\n";
+    @conts = readdir DIR;
+    close DIR;
+
+    foreach $file (@conts) {
+	if ($file =~ /^(.*?)\.(?:ldb|bdb)$/) {
+	    $collection = $1;
+	    $gdbmfile = &util::filename_cat ($gdbmfile, $file);
+	    last;
+	}
+    }
+    
+    if (defined $collection && $collection =~ /\w/) {
+	$textdir = &util::filename_cat ($textdir, $collection);
+    } else {
+	die "collection global wasn't set\n";
+    }
+    return $gdbmfile if (-e $gdbmfile);
+    die "Couldn't find gdbm info database in $indexdir\n\n";
+}
+
+
+sub get_toplevel_OID {
+    my ($gdbmfile) = @_;
+
+    open (DB2TXT, "db2txt $gdbmfile |") || die "couldn't open pipe to db2txt\n";
+    print STDERR "Finding all top level sections from $gdbmfile\n" if $verbosity >= 2;
+
+    $/ = '-' x 70;
+    my $entry = "";
+    while (defined ($entry = <DB2TXT>)) {
+	next unless $entry =~ /\w/;  #ignore blank entries
+	$entry =~ s/\n+/\\n/g;  # replace multiple \n with single \n
+	my ($key, $value) = $entry =~ /\[([^\]]*)\](.*)/;
+
+	next if ($key =~ /\./); #ignore any lower level entries
+	next if ($key =~ /^CL/); #ignore classification entries
+	next if ($value =~ /<section>/); #ignore docnum->OID entries
+	next if ($value =~ /<docoid>/); #ignore strange s133->OID entries
+	next if ($key !~ /\d/); #ignore collection, browse entries
+
+	push( @$toplevelinfo, $key);
+   
+    }
+
+    $/ = "\n";
+    #print STDERR "toplevel sections are: ", join ("\n", @$toplevelinfo);
+    #print STDERR "\n";
+}
+    
+# gets all the metadata from a gdbm file entry, and puts it into a hashref
+sub get_metadata {
+    
+    my ($gdb_str_ref, $hashref) = @_;
+    my @entries = split(/\n/, $gdb_str_ref);
+    foreach $entry (@entries) {
+	my($key, $value) = ($entry =~ /^<([^>]*)>(.*?)$/ );
+	$$hashref{$key} .= '@' if defined $$hashref{$key};
+	$$hashref{$key} .= $value;
+	
+    }
+   
+    
+}					  
+
+#takes a hashref containing the metadata for a gdbmfile entry, and extracts 
+#the childrens numbers (from the 'contains' entry).	
+#assumes format is ".1;".2;".3
+sub get_children {	
+    my ($hashref, $children) = @_; 
+
+    $childs = $hashref->{'contains'};
+    if (defined ($childs)) {
+	$childs =~ s/\@$//;  #remove trailing @
+	$childs =~ s/^\"\.//; #remove initial ".
+	@$children = split /\;\"\./, $childs;
+	
+    }
+    else {
+	  $children = [];
+      }
+}
+	
+#takes a hashref containing the metadata for a gdbmfile entry, and extracts 
+#the childrens numbers (from the 'contains' entry).	
+#assumes format is ".1;".2;".3
+#returns a list with the full child name ie HASH0123...ac.1 HASH0123...ac.2 
+#etc
+#used for classification stuff
+sub get_whole_children {	
+
+    my ($parentoid, $hashref, $children) = @_; 
+    
+    my $childs = $hashref->{'contains'};
+    my @items;
+    if (defined ($childs)) {
+	$childs =~ s/\@$//;  #remove trailing @
+	@items = split /\;/, $childs; #split on ;
+	foreach $item (@items) {
+	    $item =~ s/^\"/$parentoid/; # replace " with parentoid
+	    push (@$children, "$item");
+	}
+    }
+    else {
+	  $children = [];
+      }
+}
+
+    
+sub recurse_sections {
+    my ($doc_obj, $children, $parentoid, $parentsection, $olddir) = @_;
+
+    foreach $child (sort numerically @$children) {
+	$doc_obj->create_named_section("$parentsection.$child");
+	my $value = $infodb{"$parentoid.$child"};
+	my $hashref={};
+	&get_metadata($value, $hashref); # get childs metadata
+	my $newchildren = [];
+	&get_children($hashref, $newchildren); # get childs children
+	#add content fo rcurrent section
+	&add_section_content($doc_obj, "$parentsection.$child", $hashref, $olddir);
+	# process all the children if there are any
+	&recurse_sections($doc_obj, $newchildren, "$parentoid.$child", "$parentsection.$child", $olddir)
+	    if (defined ($newchildren));
+    }
+
+
+}					     
+
+sub add_section_content {
+    my ($doc_obj, $cursection, $hashref, $olddir) = @_;
+ 
+    foreach $key (keys %$hashref) {
+	#dont need to store these metadata
+	next if $key =~ /(contains|docnum|hastxt|doctype|archivedir|classifytype)/i;
+	my @items = split /@/, $hashref->{$key};
+	map {$doc_obj->add_metadata ($cursection, $key, $_); } @items;
+
+    }
+    my ($docnum)= $hashref->{'docnum'} =~ /(\d*)/;
+    my ($hastext) =$hashref->{'hastxt'} =~ /(0|1)/;
+
+    my $images=[];
+    if ($hastext) {
+	my $text = &get_text($docnum);
+    
+	#my (@images) = $text =~ /<img.*?src=\"([^\"]*)\"[^>]*>/g;
+    
+	# in text replace path to image with _httpdocimg_/blah.gif
+	#while ($text =~ s/(<img.*?src=\")([^\"]*)(\"[^>]*>)/
+	#   $1.&get_img($2, \@images).$3/sgei) {
+	$text =~ s/(<img.*?src=\")([^\"]*)(\"[^>]*>)/
+	    $1.&get_img($2,$images).$3/sgei;
+    
+	$doc_obj->add_text ($cursection, $text);
+	
+	if (scalar(@$images)>0) {
+	    
+	    foreach $img (@$images) {
+		my ($assoc_file) = $img =~ /([^\/\\]*\..*)$/; #the name of the image
+		$img =~ s/_httpcollection_/\./; #replace _httpcollection_ with .
+		$img =~ s/_thisOID_/$olddir/; #replace _thisOID_ with old archivedir name
+		
+		$doc_obj->associate_file($img, $assoc_file);
+	    }
+	}
+    }
+}
+
+
+
+sub get_img {
+    my ($path, $images) = @_;
+    my $img = "_httpdocimg_/";
+    my ($imgname) = $path =~ /([^\/\\]*\..*)$/;
+    push (@$images, $path);
+    $img .= $imgname;
+    return $img;
+}
+    
+
+sub add_classification_metadata {
+
+    my ($oid, $doc_obj, $cursection) = @_;
+    
+    if (defined $doc_classif_info->{$oid}) {
+
+	my $hashref = $doc_classif_info->{$oid};
+	
+	foreach $key (keys %$hashref) {
+	    my @items = @{$hashref->{$key}};
+	    map {$doc_obj->add_metadata ($cursection, $key, $_); } @items;
+	}
+    }
+}
+
+# picks up the cover image "cover.jpg" from the old archives directory.
+sub add_cover_image {
+
+    my ($doc_obj, $olddir) =  @_;
+    $assoc_file = "cover.jpg";
+    $img = "archives/$olddir/$assoc_file";
+
+
+    if (-e $img) {
+	$doc_obj->associate_file($img, $assoc_file);
+    }
+}
+
+
+
+sub set_index {
+    # check that $collection has been set
+    die "collection global was not set\n"
+	unless defined $collection && $collection =~ /\w/;
+
+    # find an index (just use first non-text directory we come across in $indexdir)
+    opendir (INDEXDIR, $indexdir) || die "couldn't open directory $indexdir\n";
+    my @indexes = readdir INDEXDIR;
+    close INDEXDIR;
+    foreach $i (@indexes) {
+	next if $i =~ /text$/i || $i =~ /\./ || $i =~ /assoc$/i;
+	$index = &util::filename_cat ($i, $collection);
+	last;
+    }
+}
+
+
+#########################################################################
+
+################ functions involving mg ################################
+
+sub get_text {
+    my ($docnum) = @_;
+
+    print STDERR "." if $verbosity >= 2;
+    &mgcommand ($docnum);
+
+   <$mgread>;	# eat the document separator
+
+    my $text = "";
+    my $line = "";
+
+    while (defined ($line = <$mgread>))
+    {
+	last if $line =~ /^<\/mg>/;
+	$text .= $line;
+    }
+
+    # Read in the last statement, which should be:
+    #  "dd documents retrieved."
+    <$mgread>;
+
+    return $text;
+}
+
+sub numerically {$a <=> $b;}
+
+
+
+sub openmg {
+
+    #print STDERR "index: $index\n";
+
+    die "Unable to start mgquery." unless
+	&openpipe($mgread, $mgwrite,
+		 "mgquery -d $indexdir -f $index -t $textdir");
+
+    $mgwrite->autoflush();
+
+    &mgcommand('.set expert true');
+    &mgcommand('.set terminator "</mg>\n"');
+    &mgcommand('.set mode text');
+    &mgcommand('.set query docnums');
+    &mgcommand('.set term_freq off');
+    &mgcommand('.set briefstats off');
+    &mgcommand('.set memstats off');
+    &mgcommand('.set sizestats off');
+    &mgcommand('.set timestats off');
+}
+
+sub closemg {
+    &mgcommand (".quit");
+    close($mgread);
+    close($mgwrite);
+}
+
+sub mgcommand {
+    my ($command) = @_;
+
+    return if $command =~ /^\s*$/;  #whitespace
+    #print STDERR "command: $command\n";
+    print $mgwrite "$command\n";
+
+    # eat up the command executed which is echoed
+    <$mgread>;
+}
+
+# openpipe(READ, WRITE, CMD)
+# 
+# Like open2, except CMD's stderr is also redirected.
+# 
+sub openpipe
+{
+    my ($read, $write, $cmd) = @_;
+    my ($child_read, $child_write);
+
+    $child_read = ++$FileHandle;
+    $child_write = ++$FileHandle;
+
+    pipe($read, $child_write) || die "Failed pipe($read, $child_write): $!";
+    pipe($child_read, $write) || die "Failed pipe($child_read, $write): $!";
+    my $pid;
+
+    if (($pid = fork) < 0) {
+        die "Failed fork: $!";
+    } elsif ($pid == 0) {
+        close($read);
+        close($write);
+        open(STDIN, "<&$child_read");
+        open(STDOUT, ">&$child_write");
+        open(STDERR, ">&$child_write");
+        exec($cmd);
+        die "Failed exec $cmd: $!";
+    }
+
+    close($child_read);
+    close($child_write);
+
+    $write->autoflush();
+    $read->autoflush();
+
+    return 1;
+}
+
+
+
+
+######################################################################
+
+############# functions to do with the classification stuff ##########
+
+#returns the top level classification oids
+sub get_classifyinfo {
+    my ($gdbmfile) = @_;
+
+    open (DB2TXT, "db2txt $gdbmfile |") || die "couldn't open pipe to db2txt\n";
+    print STDERR "Finding all classification sections from $gdbmfile\n" ;
+
+    $/ = '-' x 70;
+    my $entry = "";
+    while (defined ($entry = <DB2TXT>)) {
+	next unless $entry =~ /\w/;  #ignore blank entries
+	$entry =~ s/\n+/\\n/g;  # replace multiple \n with single \n
+	my ($key, $value) = $entry =~ /\[([^\]]*)\](.*)/;
+
+	next unless ($key =~/^CL\d$/); # assumes classification OID is like
+	                                 # CL1 or CL2 etc
+
+	push( @$classifyinfo, $key);
+   
+    }
+
+    $/ = "\n";
+    #print STDERR "classifications are: ", join(", ", @$classifyinfo);
+    #print STDERR "\n";
+    
+}
+
+#this creates the classification files needed for the hierarchy classifier
+#used for subjects, titles, orgs etc
+#also adds in entries to the collect_cfg hash    
+sub make_info_file {
+
+    my ($classifier) = @_;
+    my $info_file = "";
+    my $entry = $infodb{$classifier};
+
+    my $hashref = {};
+    &get_metadata($entry, $hashref);
+   
+    my $classifier_name = "CL".$hashref->{'Title'}; #like CLSubject
+    $classifier_name =~ s/\@$//; #remove trailing @
+   
+    # check children - if there is a classifier node at this level, 
+    # use a hierarchy, otherwise use an AZList.
+    
+    my $children=[];
+    my $hierarchy = 0;
+    &get_whole_children($classifier, $hashref, $children); #returns a list of the child ids
+    foreach $child(@$children) {
+	if(not &is_document($child)) {
+	    $hierarchy = 1;
+	    last;
+	}
+    }
+
+    if (!$hierarchy) {
+	&add_classify_cfg_list($classifier_name);
+    }else { #there is a hierarchy so create a file
+	$info_file = "./etc/$classifier_name.txt";
+
+	print STDERR "classification $classifier will be called $classifier_name\n";
+
+	open (OUTDOC, "> $info_file" ) || die  "couldn't open file $info_file\n";
+	
+	foreach $child (@$children) {
+	    &process_entry(OUTDOC, $classifier_name, $child);
+	}
+	
+	close OUTDOC;
+    
+	&add_classify_cfg($classifier, $classifier_name, $info_file);
+    }
+}
+
+
+sub process_entry {
+    my ($handle, $classifier_name, $classify_id) = @_;
+    my $value = $infodb{$classify_id};
+    
+    my $hashref={};
+    &get_metadata($value, $hashref);
+    my $title = $hashref->{'Title'};
+    $title =~ s/\@$//; #remove trailing @
+    &add_line($handle, $classify_id, $title);
+    
+    my $children = [];
+    &get_whole_children($classify_id, $hashref, $children);
+    foreach $child (@$children) {
+	if (&is_document($child)) {
+	    &add_doc_metadata($child, $classifier_name, $title);
+	}else {
+	    &process_entry($handle, $classifier_name, $child);
+	}
+    }
+    
+}
+    
+
+
+sub add_doc_metadata {
+
+    my ($doc_id, $classifier_name, $classifier_id) = @_;
+
+	#add entry to doc database
+	#print STDERR "at doc level, docnum=$classify_id\n";
+
+    $doc_classif_info->{$doc_id}={} unless defined $doc_classif_info->{$doc_id};
+    $doc_classif_info->{$doc_id}->{$classifier_name}=[] unless
+	defined $doc_classif_info->{$doc_id}->{$classifier_name};
+    push (@{$doc_classif_info->{$doc_id}->{$classifier_name}}, $classifier_id); 
+
+}
+
+
+
+
+sub add_line {
+
+    my ($handle, $classify_id, $title) = @_;
+    #print STDERR "classify id= $classify_id, title= $title\n";
+    $title = &unicode::ascii2utf8(\$title);
+    my ($num) = $classify_id =~ /^CL\d\.(.*)$/; #remove the CL1. from the front
+    
+    print $handle "\"$title\"\t$num\t\"$title\"\n";
+
+
+}
+
+sub is_document {
+    my ($oid) = @_;
+    return 1 if $oid =~ /^HASH/i;
+    return 0;
+}
+    
+########################################################################
+
+########## stuff for producing collect.cfg file ###########################
+
+sub add_default_cfg {
+
+    $username=`whoami`;
+    $username=`logname` unless defined $username;
+    $username="a_user" unless defined $username;
+    $username =~ s/\n//;
+    $collect_cfg->{'creator'}="$username\@cs.waikato.ac.nz";
+    $collect_cfg->{'maintainer'}="$username\@cs.waikato.ac.nz";
+    $collect_cfg->{'public'}="true";
+    $collect_cfg->{'beta'}="true";
+    
+    $collect_cfg->{'plugin'}=[];
+    push (@{$collect_cfg->{'plugin'}}, ["GAPlug"]);
+    push (@{$collect_cfg->{'plugin'}}, ["ArcPlug"]);
+    push (@{$collect_cfg->{'plugin'}}, ["RecPlug"]);
+
+    $collect_cfg->{'format'}={};
+    $collect_cfg->{'format'}->{'DocumentImages'}="true";
+    $collect_cfg->{'format'}->{'DocumentText'} = 
+	"\"<h3>[Title]</h3>\\\\n\\\\n<p>[Text]\"";
+    $collect_cfg->{'format'}->{'SearchVList'} =
+	"\"<td valign=top>[link][icon][/link]</td><td>{If}{[parent(All': '):Title],[parent(All': '):Title]:}[link][Title][/link]</td>\"";
+
+    $collect_cfg->{'collectionmeta'}={};
+    $collect_cfg->{'collectionmeta'}->{'collectionname'}="\"$collection\"";
+    $collect_cfg->{'collectionmeta'}->{'iconcollection'}="\"_httpprefix_/collect/$collection/images/$collection.gif\"";
+    $collect_cfg->{'collectionmeta'}->{'iconcollectionsmall'}="\"_httpprefix_/collect/$collection/images/${collection}sm.gif\"";
+    $collect_cfg->{'collectionmeta'}->{'collectionextra'} = "\"This is a collection rebuilt from CDROM.\"";
+
+}
+
+sub add_index_cfg {
+  my ($buildfile) = @_;
+
+  my $data={};
+  $collect_cfg->{'indexes'}=[];
+  if (-e $buildfile) {
+      $data=&cfgread::read_cfg_file($buildfile, '^(this)$', '^(indexmap)$'); 
+      foreach $i (@{$data->{'indexmap'}}) {
+          ($thisindex, $abbrev)= split ("\-\>", $i);
+          push (@{$collect_cfg->{'indexes'}}, $thisindex);
+	  $collect_cfg->{'defaultindex'} = $thisindex unless defined 
+	      $collect_cfg->{'defaultindex'};
+          $name=&get_index_name($thisindex);
+	  $thisindex=".$thisindex";
+          $collect_cfg->{'collectionmeta'}->{$thisindex} = "\"$name\"";
+      } 
+  }
+  else {
+      print STDERR "Couldn't read $buildfile, could not add index data to configuration file\n";
+  }
+
+}
+
+sub get_index_name {
+    my ($thisindex) = @_;
+    return "paragraphs" if $thisindex =~ /paragraph/;
+    return "chapters" if $thisindex =~ /section.*text/;
+    return "titles" if $thisindex =~ /Title/;
+    return "other";
+}
+
+sub add_classify_cfg {
+
+    my ($classify, $classifier_name, $file) = @_;
+    $collect_cfg->{'classify'} = [] unless defined $collect_cfg->{'classify'};
+
+    my ($title) = $classifier_name =~ /^CL(.*)$/;
+    my ($filename) = $file =~ /\/([^\/]*)$/;
+    my $entry = "Hierarchy -hfile $filename -metadata $classifier_name -buttonname $title -sort Title";
+    push (@{$collect_cfg->{'classify'}},[$entry]);
+   
+
+}
+
+sub add_classify_cfg_list {
+
+    my ($classifier) = @_;
+    $collect_cfg->{'classify'} = [] unless defined $collect_cfg->{'classify'};
+    my ($title) = $classifier =~ /^CL(.*)$/;
+    my $entry = "AZList -metadata $classifier -buttonname $title";
+    push (@{$collect_cfg->{'classify'}},[$entry]);
+}    
+
+sub output_cfg_file {
+
+    my ($collfile) = @_;
+    
+    if (-e $collfile) { #collect.cfg already exists
+	$collfile .= ".new";
+    }
+    &cfgread::write_cfg_file($collfile, $collect_cfg, 
+			     '^(creator|maintainer|public|beta|defaultindex)$',
+                            '^(indexes)$', '^(format|collectionmeta)$',
+                            '^(plugin|classify)$');
+
+
+
+}
+
+
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/update.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/update.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/update.pl	(revision 13928)
@@ -0,0 +1,196 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# update.pl
+#
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+# This program updates any collections that are based on mirrors of
+# web sites after a certain interval.  It first checks that the
+# collection is a mirrored collection and whether it is time to 
+# update the collection.  If so, it updates the mirror with 
+# mirror.pl; then imports the collection with import.pl; then 
+# builds the collection with buildcol.pl; then replaces the 
+# existing index directory with the new building directory.
+# The etc/mirror.log file stores the STDOUT output.
+
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/plugins");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/classify");
+}
+
+use arcinfo;
+use colcfg;
+use util;
+use parsargv;
+
+sub print_usage {
+    print STDERR "\n";
+    print STDERR "update.pl: Updates a collection if it has been set up to mirror\n";
+    print STDERR "           a website. Calls mirror.pl to do the mirroring.\n\n";
+    print STDERR "  usage: $0 [options] collection-name\n\n";
+    print STDERR "  options:\n";
+    print STDERR "   -verbosity number      0=none, 3=lots\n";
+    print STDERR "   -importdir directory   Where to place the mirrored material\n";
+    print STDERR "   -archivedir directory  Where the converted material ends up\n";
+}
+
+
+&main ();
+
+sub main {
+    my ($verbosity, $importdir, $archivedir, $builddir, $indexdir, $etcdir, 
+	$mirror, $interval, $logfile,
+        $collection, $configfilename, $collectcfg);
+
+    if (!parsargv::parse(\@ARGV, 
+			 'verbosity/\d+/2', \$verbosity,
+			 'importdir/.*/', \$importdir,
+			 'archivedir/.*/', \$archivedir )) {
+	&print_usage();
+	die "\n";
+    }
+
+    # get and check the collection name
+    if (($collection = &util::use_collection(@ARGV)) eq "") {
+	&print_usage();
+	die "\n";
+    }
+
+    # check the configuration file for options
+    $configfilename = &util::filename_cat ($ENV{'GSDLCOLLECTDIR'}, "etc/collect.cfg");
+    if (-e $configfilename) {
+	$collectcfg = &colcfg::read_collect_cfg ($configfilename);
+	if (defined $collectcfg->{'importdir'} && $importdir eq "") {
+	    $importdir = $collectcfg->{'importdir'};
+	}
+	if (defined $collectcfg->{'archivedir'} && $archivedir eq "") {
+	    $archivedir = $collectcfg->{'archivedir'};
+	}
+	if (defined $collectcfg->{'mirror'}) {
+	    $mirror = $collectcfg->{'mirror'};
+	}
+    } else {
+	die "Couldn't find the configuration file $configfilename\n";
+    }
+    
+    # fill in the default import and archives directories if none
+    # were supplied, turn all \ into / and remove trailing /
+    $importdir = "$ENV{'GSDLCOLLECTDIR'}/import" if $importdir eq "";
+    $importdir =~ s/[\\\/]+/\//g;
+    $importdir =~ s/\/$//;
+    $archivedir = "$ENV{'GSDLCOLLECTDIR'}/archives" if $archivedir eq "";
+    $archivedir =~ s/[\\\/]+/\//g;
+    $archivedir =~ s/\/$//;
+
+    $indexdir = "$ENV{'GSDLCOLLECTDIR'}/index";
+    $builddir = "$ENV{'GSDLCOLLECTDIR'}/building";
+    $etcdir = "$ENV{'GSDLCOLLECTDIR'}/etc";
+    $logfile = "$etcdir/mirror.log";
+
+    # if there is no mirror information, we're all done
+    if (!defined($mirror)) {
+	print "No mirror command in $configfilename\n";
+	exit;
+    }
+
+    # read the mirror interval
+    if (($#$mirror == 1) && ($$mirror[0] =~ /interval/)){
+	$interval = $$mirror[1];
+    } else {
+	die "Malformed mirror information: use \"mirror interval N\"\n" .
+	    "where N is the number of days between mirrors.\n";
+    }
+
+    # make sure there is an import directory
+    if (! -e "$importdir") {
+	&util::mk_dir($importdir);
+    }
+
+    print "archives directory: $archivedir\n";
+    print "  import directory: $importdir\n";
+    print "     etc directory: $etcdir\n";
+    print "          interval: $interval days\n";
+
+    # how many days is it since the last mirror
+    my $seconds = 0;
+    if (-e "$logfile") {
+	my $now = time;
+	my @stats = stat("$logfile");
+	my $then = $stats[9];
+	# calculate the number of days since the last mirror
+	$seconds = $now - $then;
+    }
+    my $days = (($seconds / 3600) / 24);
+
+    # Is it too soon to start mirroring?
+    if (($seconds > 0) && ($interval > $days)) {
+	printf "Mirror not started: only %.1f days have passed\n", $days;
+	exit;
+    }
+    
+    # Mirror the remote site
+    open(WLOG, ">$logfile");
+    print WLOG "Starting mirror at " . time . "\n\n";
+    
+    my $command = "mirror.pl $collection";
+    print WLOG "Executing: $command\n";
+    print WLOG `$command`;
+    
+    # Import the collection
+    print WLOG "\n\nStarting import at " . time . "\n\n";
+    $command = "import.pl -removeold $collection";
+    print WLOG "Executing: $command\n";
+    print WLOG `$command`;
+
+    # Build the collection
+    print WLOG "\n\nStarting buildcol.pl at " . time . "\n\n";
+    $command = "buildcol.pl $collection";
+    print WLOG "Executing: $command\n";
+    print WLOG `$command`;
+
+    # Renaming the building directory to index
+    print WLOG "\n\nRenaming building directory at " . time . "\n\n";
+    if (-e $indexdir) {
+	&util::mv($indexdir, "$indexdir.old");
+	&util::mv($builddir, $indexdir);
+	&util::rm_r ("$indexdir.old");
+    } else {
+	&util::mv($builddir, $indexdir);
+    }
+
+
+    close WLOG;
+    
+}
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl/bin/script/xlstohtml.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/bin/script/xlstohtml.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/bin/script/xlstohtml.pl	(revision 13928)
@@ -0,0 +1,69 @@
+eval 'exec perl -x -- $0 $@'
+    if 0;
+#! perl
+# line 6
+
+sub usage() {
+    print "$0 <input.xls> <output.html>\n";
+}
+
+
+if (@ARGV != 2) {
+    usage();
+    exit(1);
+}
+my $input_xls=shift;
+my $output_html=shift;
+
+# try to find xlhtml binary in GSDLHOME
+my $xlhtml_binary="xlhtml";
+my $GSDLOS=$ENV{'GSDLOS'};
+my $GSDLHOME=$ENV{'GSDLHOME'};
+if ($GSDLOS =~ /^windows/i) {
+    $xlhtml_binary.=".exe";
+}
+
+# Trouble happens if there are spaces in GSDLHOME. Assume that on windows
+# the program is found in the path.
+if ($GSDLOS !~ /windows/i && -x "$GSDLHOME/bin/$GSDLOS/$xlhtml_binary") {
+    $xlhtml_binary="$GSDLHOME/bin/$GSDLOS/$xlhtml_binary";
+}
+
+if (! -r $input_xls) {
+    print STDERR "Unable to read file `$input_xls'\n";
+    exit (1);
+}
+
+my $return_value=
+    system("$xlhtml_binary \"$input_xls\" > \"$output_html\"");
+
+if ($return_value != 0) {
+    exit (1);
+}
+
+# Ok, we made an html file. Check to see if it has any content, and remove
+# the little nag link at the the bottom.
+my $html="";
+open (HTML, "$output_html") || die "Can't read file:$!";
+$html=join('', <HTML>);
+close HTML;
+
+$html =~ s@<hr><FONT SIZE=-1>Created with.*\n</BODY></HTML>$@</BODY></HTML>@s;
+
+# xlHtml uses the filename as the title.
+# HTMLPlug will use the first 100 chars instead if there's no title.
+# Don't know if that's a good idea with a spreadsheet, though...
+$html =~ s@<title>.*?\.xls</title>@<title></title>@i;
+
+my $tmp=$html;
+$tmp =~ s/^.*?<BODY>//ms;
+$tmp =~ s/(&nbsp;)|\s//gims;
+if ($tmp !~ m/(>[^<]+<)/) {
+    print STDERR "No text found in extracted html file!\n";
+    exit(1);
+}
+open (NEWHTML, ">$output_html") || die "Can't create file:$!";
+print NEWHTML $html;
+close NEWHTML;
+exit (0);
+
Index: /tags/greenstone-3_02-distribution/gsdl/collect/modelcol/etc/collect.cfg
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/collect/modelcol/etc/collect.cfg	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/collect/modelcol/etc/collect.cfg	(revision 13928)
@@ -0,0 +1,26 @@
+creator       **creator**
+maintainer    **maintainer**
+public        **public**
+
+buildtype	mgpp
+
+#indexes        document:text document:Title document:Source
+indexes		text Title Source
+defaultindex	text
+
+levels		document
+
+**plugins**
+
+classify       AZList -metadata Title
+classify       AZList -metadata Source
+
+collectionmeta collectionname    "**title**"
+collectionmeta iconcollection    ""
+collectionmeta collectionextra   "**about**"
+collectionmeta .document:text    "text"
+collectionmeta .document:Title  "titles"
+collectionmeta .document:Source  "filenames"
+collectionmeta  .text "text"
+collectionmeta	.Title "titles"
+collectionmeta	.Source "filenames"
Index: /tags/greenstone-3_02-distribution/gsdl/collect/modelcol/macros/extra.dm
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/collect/modelcol/macros/extra.dm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/collect/modelcol/macros/extra.dm	(revision 13928)
@@ -0,0 +1,4 @@
+# extra.dm file
+# You can add collection specific macros in here
+# Lines starting with a '#' are comments.
+# Remember to include the package declaration
Index: /tags/greenstone-3_02-distribution/gsdl/config.guess
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/config.guess	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/config.guess	(revision 13928)
@@ -0,0 +1,1298 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+#   Free Software Foundation, Inc.
+
+timestamp='2001-07-12'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Written by Per Bothner <bothner@cygnus.com>.
+# Please send patches to <config-patches@gnu.org>.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+
+dummy=dummy-$$
+trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script.
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int dummy(){}" > $dummy.c ;
+	for c in cc gcc c89 ; do
+	  ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ;
+	  if test $? = 0 ; then
+	     CC_FOR_BUILD="$c"; break ;
+	  fi ;
+	done ;
+	rm -f $dummy.c $dummy.o $dummy.rel ;
+	if test x"$CC_FOR_BUILD" = x ; then
+	  CC_FOR_BUILD=no_compiler_found ;
+	fi
+	;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+	# Netbsd (nbsd) targets should (where applicable) match one or
+	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	# Determine the machine/vendor (is the vendor relevant).
+	case "${UNAME_MACHINE}" in
+	    amiga) machine=m68k-unknown ;;
+	    arm32) machine=arm-unknown ;;
+	    atari*) machine=m68k-atari ;;
+	    sun3*) machine=m68k-sun ;;
+	    mac68k) machine=m68k-apple ;;
+	    macppc) machine=powerpc-apple ;;
+	    hp3[0-9][05]) machine=m68k-hp ;;
+	    ibmrt|romp-ibm) machine=romp-ibm ;;
+	    *) machine=${UNAME_MACHINE}-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently, or will in the future.
+	case "${UNAME_MACHINE}" in
+	    i386|sparc|amiga|arm*|hp300|mvme68k|vax|atari|luna68k|mac68k|news68k|next68k|pc532|sun3*|x68k)
+		eval $set_cc_for_build
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep __ELF__ >/dev/null
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+	        os=netbsd
+		;;
+	esac
+	# The OS release
+	release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	echo "${machine}-${os}${release}"
+	exit 0 ;;
+    alpha:OSF1:*:*)
+	if test $UNAME_RELEASE = "V4.0"; then
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+	fi
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	cat <<EOF >$dummy.s
+	.data
+\$Lformat:
+	.byte 37,100,45,37,120,10,0	# "%d-%x\n"
+
+	.text
+	.globl main
+	.align 4
+	.ent main
+main:
+	.frame \$30,16,\$26,0
+	ldgp \$29,0(\$27)
+	.prologue 1
+	.long 0x47e03d80 # implver \$0
+	lda \$2,-1
+	.long 0x47e20c21 # amask \$2,\$1
+	lda \$16,\$Lformat
+	mov \$0,\$17
+	not \$1,\$18
+	jsr \$26,printf
+	ldgp \$29,0(\$26)
+	mov 0,\$16
+	jsr \$26,exit
+	.end main
+EOF
+	eval $set_cc_for_build
+	$CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
+	if test "$?" = 0 ; then
+		case `./$dummy` in
+			0-0)
+				UNAME_MACHINE="alpha"
+				;;
+			1-0)
+				UNAME_MACHINE="alphaev5"
+				;;
+			1-1)
+				UNAME_MACHINE="alphaev56"
+				;;
+			1-101)
+				UNAME_MACHINE="alphapca56"
+				;;
+			2-303)
+				UNAME_MACHINE="alphaev6"
+				;;
+			2-307)
+				UNAME_MACHINE="alphaev67"
+				;;
+		esac
+	fi
+	rm -f $dummy.s $dummy
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	exit 0 ;;
+    Alpha\ *:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# Should we change UNAME_MACHINE based on the output of uname instead
+	# of the specific Alpha model?
+	echo alpha-pc-interix
+	exit 0 ;;
+    21064:Windows_NT:50:3)
+	echo alpha-dec-winnt3.5
+	exit 0 ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit 0;;
+    amiga:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit 0 ;;
+    arc64:OpenBSD:*:*)
+	echo mips64el-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    arc:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    hkmips:OpenBSD:*:*)
+	echo mips-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    pmax:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    sgi:OpenBSD:*:*)
+	echo mips-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    wgrisc:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit 0 ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit 0;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit 0;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit 0 ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit 0 ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    i86pc:SunOS:5.*:*)
+	echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:*:*)
+	case "`/usr/bin/arch -k`" in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+	exit 0 ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit 0 ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit 0 ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos${UNAME_RELEASE}
+	exit 0 ;;
+    atari*:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit 0 ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit 0 ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit 0 ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit 0 ;;
+    sun3*:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mac68k:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mvme68k:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mvme88k:OpenBSD:*:*)
+	echo m88k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten${UNAME_RELEASE}
+	exit 0 ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit 0 ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit 0 ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit 0 ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit 0 ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	sed 's/^	//' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	eval $set_cc_for_build
+	$CC_FOR_BUILD $dummy.c -o $dummy \
+	  && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+	  && rm -f $dummy.c $dummy && exit 0
+	rm -f $dummy.c $dummy
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit 0 ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit 0 ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit 0 ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit 0 ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit 0 ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit 0 ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+	then
+	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+	       [ ${TARGET_BINARY_INTERFACE}x = x ]
+	    then
+		echo m88k-dg-dgux${UNAME_RELEASE}
+	    else
+		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+	    fi
+	else
+	    echo i586-dg-dgux${UNAME_RELEASE}
+	fi
+ 	exit 0 ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit 0 ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit 0 ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit 0 ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit 0 ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+	exit 0 ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	echo romp-ibm-aix      # uname -m gives an 8 hex-code CPU id
+	exit 0 ;;              # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit 0 ;;
+    ia64:AIX:*:*)
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+	exit 0 ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		sed 's/^		//' << EOF >$dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		eval $set_cc_for_build
+		$CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
+		rm -f $dummy.c $dummy
+		echo rs6000-ibm-aix3.2.5
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit 0 ;;
+    *:AIX:*:[45])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+	exit 0 ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit 0 ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+	echo romp-ibm-bsd4.4
+	exit 0 ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+	exit 0 ;;                           # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit 0 ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit 0 ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit 0 ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit 0 ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	case "${UNAME_MACHINE}" in
+	    9000/31? )            HP_ARCH=m68000 ;;
+	    9000/[34]?? )         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+              case "${HPUX_REV}" in
+                11.[0-9][0-9])
+                  if [ -x /usr/bin/getconf ]; then
+                    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+                        esac ;;
+                    esac
+                  fi ;;
+              esac
+              if [ "${HP_ARCH}" = "" ]; then
+              sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+              	{
+              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+              	case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+              	    switch (bits)
+              		{
+              		case 64: puts ("hppa2.0w"); break;
+              		case 32: puts ("hppa2.0n"); break;
+              		default: puts ("hppa2.0"); break;
+              		} break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+              	    puts ("hppa2.0"); break;
+              #endif
+              	default: puts ("hppa1.0"); break;
+              	}
+                  exit (0);
+              }
+EOF
+	eval $set_cc_for_build
+	(CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy`
+	if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi
+	rm -f $dummy.c $dummy
+	fi ;;
+	esac
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit 0 ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux${HPUX_REV}
+	exit 0 ;;
+    3050*:HI-UX:*:*)
+	sed 's/^	//' << EOF >$dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	eval $set_cc_for_build
+	$CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
+	rm -f $dummy.c $dummy
+	echo unknown-hitachi-hiuxwe2
+	exit 0 ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+	echo hppa1.1-hp-bsd
+	exit 0 ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit 0 ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit 0 ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+	echo hppa1.1-hp-osf
+	exit 0 ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit 0 ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo ${UNAME_MACHINE}-unknown-osf1mk
+	else
+	    echo ${UNAME_MACHINE}-unknown-osf1
+	fi
+	exit 0 ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit 0 ;;
+    hppa*:OpenBSD:*:*)
+	echo hppa-unknown-openbsd
+	exit 0 ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+        exit 0 ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+        exit 0 ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+        exit 0 ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+        exit 0 ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+        exit 0 ;;
+    CRAY*X-MP:*:*:*)
+	echo xmp-cray-unicos
+        exit 0 ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*[A-Z]90:*:*:*)
+	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+	      -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*T3D:*:*:*)
+	echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY-2:*:*:*)
+	echo cray2-cray-unicos
+        exit 0 ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit 0 ;;
+    hp300:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    *:BSD/OS:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    *:FreeBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	exit 0 ;;
+    *:OpenBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+	exit 0 ;;
+    i*:CYGWIN*:*)
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit 0 ;;
+    i*:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
+	exit 0 ;;
+    i*:PW*:*)
+	echo ${UNAME_MACHINE}-pc-pw32
+	exit 0 ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+	# UNAME_MACHINE based on the output of uname instead of i386?
+	echo i386-pc-interix
+	exit 0 ;;
+    i*:UWIN*:*)
+	echo ${UNAME_MACHINE}-pc-uwin
+	exit 0 ;;
+    p*:CYGWIN*:*)
+	echo powerpcle-unknown-cygwin
+	exit 0 ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    *:GNU:*:*)
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit 0 ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit 0 ;;
+    arm*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux
+	exit 0 ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    mips:Linux:*:*)
+	case `sed -n '/^byte/s/^.*: \(.*\) endian/\1/p' < /proc/cpuinfo` in
+	  big)    echo mips-unknown-linux-gnu && exit 0 ;;
+	  little) echo mipsel-unknown-linux-gnu && exit 0 ;;
+	esac
+	;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-gnu
+	exit 0 ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev67 ;;
+        esac
+	objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+	if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+	exit 0 ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) echo hppa1.1-unknown-linux-gnu ;;
+	  PA8*) echo hppa2.0-unknown-linux-gnu ;;
+	  *)    echo hppa-unknown-linux-gnu ;;
+	esac
+	exit 0 ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-gnu
+	exit 0 ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo ${UNAME_MACHINE}-ibm-linux
+	exit 0 ;;
+    sh*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    x86_64:Linux:*:*)
+	echo x86_64-unknown-linux-gnu
+	exit 0 ;;
+    i*86:Linux:*:*)
+	# The BFD linker knows what the default object file format is, so
+	# first see if it will tell us. cd to the root directory to prevent
+	# problems with other programs or directories called `ld' in the path.
+	ld_supported_targets=`cd /; ld --help 2>&1 \
+			 | sed -ne '/supported targets:/!d
+				    s/[ 	][ 	]*/ /g
+				    s/.*supported targets: *//
+				    s/ .*//
+				    p'`
+        case "$ld_supported_targets" in
+	  elf32-i386)
+		TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+		;;
+	  a.out-i386-linux)
+		echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+		exit 0 ;;		
+	  coff-i386)
+		echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+		exit 0 ;;
+	  "")
+		# Either a pre-BFD a.out linker (linux-gnuoldld) or
+		# one that does not give us useful --help.
+		echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+		exit 0 ;;
+	esac
+	# Determine whether the default compiler is a.out or elf
+	cat >$dummy.c <<EOF
+#include <features.h>
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+#ifdef __ELF__
+# ifdef __GLIBC__
+#  if __GLIBC__ >= 2
+    printf ("%s-pc-linux-gnu\n", argv[1]);
+#  else
+    printf ("%s-pc-linux-gnulibc1\n", argv[1]);
+#  endif
+# else
+   printf ("%s-pc-linux-gnulibc1\n", argv[1]);
+# endif
+#else
+  printf ("%s-pc-linux-gnuaout\n", argv[1]);
+#endif
+  return 0;
+}
+EOF
+	eval $set_cc_for_build
+	$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0
+	rm -f $dummy.c $dummy
+	test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+	;;
+    i*86:DYNIX/ptx:4*:*)
+	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+	# earlier versions are messed up and put the nodename in both
+	# sysname and nodename.
+	echo i386-sequent-sysv4
+	exit 0 ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+	exit 0 ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+	else
+		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+	fi
+	exit 0 ;;
+    i*86:*:5:[78]*)
+	case `/bin/uname -X | grep "^Machine"` in
+	    *486*)	     UNAME_MACHINE=i486 ;;
+	    *Pentium)	     UNAME_MACHINE=i586 ;;
+	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+	esac
+	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+	exit 0 ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	exit 0 ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit 0 ;;
+    pc:*:*:*)
+	# Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i386.
+	echo i386-pc-msdosdjgpp
+        exit 0 ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit 0 ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit 0 ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+	fi
+	exit 0 ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit 0 ;;
+    M68*:*:R3V[567]*:*)
+	test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+    3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && echo i486-ncr-sysv4 && exit 0 ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit 0 ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv${UNAME_RELEASE}
+	exit 0 ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit 0 ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit 0 ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo ${UNAME_MACHINE}-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit 0 ;;
+    PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                           # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit 0 ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes@openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit 0 ;;
+    *:*:*:FTX*)
+	# From seanf@swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit 0 ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux${UNAME_RELEASE}
+	exit 0 ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit 0 ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if [ -d /usr/nec ]; then
+	        echo mips-nec-sysv${UNAME_RELEASE}
+	else
+	        echo mips-unknown-sysv${UNAME_RELEASE}
+	fi
+        exit 0 ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit 0 ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit 0 ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit 0 ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux${UNAME_RELEASE}
+	exit 0 ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux${UNAME_RELEASE}
+	exit 0 ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+	exit 0 ;;
+    *:Rhapsody:*:*)
+	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+	exit 0 ;;
+    *:Darwin:*:*)
+	echo `uname -p`-apple-darwin${UNAME_RELEASE}
+	exit 0 ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	if test "${UNAME_MACHINE}" = "x86pc"; then
+		UNAME_MACHINE=pc
+	fi
+	echo `uname -p`-${UNAME_MACHINE}-nto-qnx
+	exit 0 ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit 0 ;;
+    NSR-[KW]:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk${UNAME_RELEASE}
+	exit 0 ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit 0 ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit 0 ;;
+    DS/*:UNIX_System_V:*:*)
+	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+	exit 0 ;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "$cputype" = "386"; then
+	    UNAME_MACHINE=i386
+	else
+	    UNAME_MACHINE="$cputype"
+	fi
+	echo ${UNAME_MACHINE}-unknown-plan9
+	exit 0 ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit 0 ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit 0 ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit 0 ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit 0 ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit 0 ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit 0 ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+	  ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+	printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+	printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+eval $set_cc_for_build
+$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0
+rm -f $dummy.c $dummy
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+	echo c1-convex-bsd
+	exit 0 ;;
+    c2*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit 0 ;;
+    c34*)
+	echo c34-convex-bsd
+	exit 0 ;;
+    c38*)
+	echo c38-convex-bsd
+	exit 0 ;;
+    c4*)
+	echo c4-convex-bsd
+	exit 0 ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+    ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
Index: /tags/greenstone-3_02-distribution/gsdl/config.h.in
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/config.h.in	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/config.h.in	(revision 13928)
@@ -0,0 +1,217 @@
+/* config.h.in.  Generated automatically from configure.in by autoheader.  */
+
+#ifndef _GSDL_CONFIG_H
+#define _GSDL_CONFIG_H
+
+/* Define if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+#undef _ALL_SOURCE
+#endif
+
+/* Define if using alloca.c.  */
+#undef C_ALLOCA
+
+/* Define if big endian */
+#undef WORDS_BIGENDIAN
+
+/* Define to empty if the keyword does not work.  */
+#undef const
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+   This function is required for alloca.c support on those systems.  */
+#undef CRAY_STACKSEG_END
+
+/* Define if you have alloca, as a function or macro.  */
+#undef HAVE_ALLOCA
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix).  */
+#undef HAVE_ALLOCA_H
+
+/* Define if you don't have vprintf but do have _doprnt.  */
+#undef HAVE_DOPRNT
+
+/* Define if you have the vprintf function.  */
+#undef HAVE_VPRINTF
+
+/* Define if on MINIX.  */
+#undef _MINIX
+
+/* Define to `long' if <sys/types.h> doesn't define.  */
+#undef off_t
+
+/* Define if the system does not provide POSIX.1 features except
+   with this defined.  */
+#undef _POSIX_1_SOURCE
+
+/* Define if you need to in order for stat and other things to work.  */
+#undef _POSIX_SOURCE
+
+/* Define as the return type of signal handlers (int or void).  */
+#undef RETSIGTYPE
+
+/* Define to `unsigned' if <sys/types.h> doesn't define.  */
+#undef size_t
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+#undef STACK_DIRECTION
+
+/* Define if you have the ANSI C header files.  */
+#undef STDC_HEADERS
+
+/* Define if you can safely include both <sys/time.h> and <time.h>.  */
+#undef TIME_WITH_SYS_TIME
+
+/* Define if your <sys/time.h> declares struct tm.  */
+#undef TM_IN_SYS_TIME
+
+/* Define to the name of the distribution.  */
+#undef PACKAGE
+
+/* Define to the version of the distribution.  */
+#undef VERSION
+
+/* Define to 1 if you have the valloc function.  */
+#undef HAVE_VALLOC
+
+/* Define to 1 if ANSI function prototypes are usable.  */
+#undef PROTOTYPES
+
+/* Define if you don't want to use long long's with GCC */
+#undef DISABLE_LONG_LONG
+ 
+/* Define to 1 for better use of the debugging malloc library.  See
+   site ftp.antaire.com in antaire/src, file dmalloc/dmalloc.tar.gz.  */
+#undef WITH_DMALLOC
+
+ 
+/* Define to 1 if GNU regex should be used instead of GNU rx.  */
+#undef WITH_REGEX
+
+/* Some braindead header files do not have the requ'd function declarations */
+#undef HAVE_FGETC_DECL
+#undef HAVE_FREAD_DECL
+
+/* See if have this field in the prstatus_t structure */
+/* It stores the size of the process heap */
+#undef HAVE_PR_BRKSIZE
+
+/* Define FASTCGI if needsbe */
+#undef USE_FASTCGI
+
+/* Define USE_CORBA if needsbe */
+#undef USE_CORBA
+
+/* Define MICO_DIR if needsbe */
+#undef MICO_DIR
+
+/* Define MICO_VERSION if required */
+#undef MICO_VERSION
+
+/* Define if you have the ftime function.  */
+#undef HAVE_FTIME
+
+/* Define if you have the ftruncate function.  */
+#undef HAVE_FTRUNCATE
+
+/* Define if you have the getpagesize function.  */
+#undef HAVE_GETPAGESIZE
+
+/* Define if you have the getrusage function.  */
+#undef HAVE_GETRUSAGE
+
+/* Define if you have the mallinfo function.  */
+#undef HAVE_MALLINFO
+
+/* Define if you have the select function.  */
+#undef HAVE_SELECT
+
+/* Define if you have the setbuffer function.  */
+#undef HAVE_SETBUFFER
+
+/* Define if you have the strcasecmp function.  */
+#undef HAVE_STRCASECMP
+
+/* Define if you have the strerror function.  */
+#undef HAVE_STRERROR
+
+/* Define if you have the strftime function.  */
+#undef HAVE_STRFTIME
+
+/* Define if you have the strstr function.  */
+#undef HAVE_STRSTR
+
+/* Define if you have the strtol function.  */
+#undef HAVE_STRTOL
+
+/* Define if you have the times function.  */
+#undef HAVE_TIMES
+
+/* Define if you have the valloc function.  */
+#undef HAVE_VALLOC
+
+/* Define if you have the <crypt.h> header file.  */
+#undef HAVE_CRYPT_H
+
+/* Define if you have the <dirent.h> header file.  */
+#undef HAVE_DIRENT_H
+
+/* Define if you have the <fcntl.h> header file.  */
+#undef HAVE_FCNTL_H
+
+/* Define if you have the <limits.h> header file.  */
+#undef HAVE_LIMITS_H
+
+/* Define if you have the <memory.h> header file.  */
+#undef HAVE_MEMORY_H
+
+/* Define if you have the <ndir.h> header file.  */
+#undef HAVE_NDIR_H
+
+/* Define if you have the <string.h> header file.  */
+#undef HAVE_STRING_H
+
+/* Define if you have the <sys/dir.h> header file.  */
+#undef HAVE_SYS_DIR_H
+
+/* Define if you have the <sys/ndir.h> header file.  */
+#undef HAVE_SYS_NDIR_H
+
+/* Define if you have the <sys/procfs.h> header file.  */
+#undef HAVE_SYS_PROCFS_H
+
+/* Define if you have the <sys/time.h> header file.  */
+#undef HAVE_SYS_TIME_H
+
+/* Define if you have the <unistd.h> header file.  */
+#undef HAVE_UNISTD_H
+
+/* Define if you have the crypt library (-lcrypt).  */
+#undef HAVE_LIBCRYPT
+
+/* Define if you have the g library (-lg).  */
+#undef HAVE_LIBG
+
+/* Define if you have the gdbm library (-lgdbm).  */
+#undef HAVE_LIBGDBM
+
+/* Define if you have the m library (-lm).  */
+#undef HAVE_LIBM
+
+/* Define if you have the stdc++ library (-lstdc++).  */
+#undef HAVE_LIBSTDC__
+
+/* Define if you have gettext (eg glibc) */
+#undef ENABLE_NLS
+
+/* Define if big endian */
+#undef WORDS_BIGENDIAN
+
+#endif /* _GSDL_CONFIG_H */
Index: /tags/greenstone-3_02-distribution/gsdl/config.sub
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/config.sub	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/config.sub	(revision 13928)
@@ -0,0 +1,1375 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+#   Free Software Foundation, Inc.
+
+timestamp='2001-06-08'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Please send patches to <config-patches@gnu.org>.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit 0;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+	-sun*os*)
+		# Prevent following clause from handling this invalid input.
+		;;
+	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+	-apple | -axis)
+		os=
+		basic_machine=$1
+		;;
+	-sim | -cisco | -oki | -wec | -winbond)
+		os=
+		basic_machine=$1
+		;;
+	-scout)
+		;;
+	-wrs)
+		os=-vxworks
+		basic_machine=$1
+		;;
+	-chorusos*)
+		os=-chorusos
+		basic_machine=$1
+		;;
+ 	-chorusrdb)
+ 		os=-chorusrdb
+		basic_machine=$1
+ 		;;
+	-hiux*)
+		os=-hiuxwe2
+		;;
+	-sco5)
+		os=-sco3.2v5
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco4)
+		os=-sco3.2v4
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2.[4-9]*)
+		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2v[4-9]*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco*)
+		os=-sco3.2v2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-udk*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-isc)
+		os=-isc2.2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-clix*)
+		basic_machine=clipper-intergraph
+		;;
+	-isc*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-lynx*)
+		os=-lynxos
+		;;
+	-ptx*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+		;;
+	-windowsnt*)
+		os=`echo $os | sed -e 's/windowsnt/winnt/'`
+		;;
+	-psos*)
+		os=-psos
+		;;
+	-mint | -mint[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+	# Recognize the basic CPU types without company name.
+	# Some are omitted here because they have special meanings below.
+	tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc \
+	        | arm | arme[lb] | arm[bl]e | armv[2345] | armv[345][lb] | strongarm | xscale \
+		| pyramid | mn10200 | mn10300 | tron | a29k \
+		| 580 | i960 | h8300 \
+		| x86 | ppcbe | mipsbe | mipsle | shbe | shle \
+		| hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \
+		| hppa64 \
+		| alpha | alphaev[4-8] | alphaev56 | alphapca5[67] \
+		| alphaev6[78] \
+		| we32k | ns16k | clipper | i370 | sh | sh[34] \
+		| powerpc | powerpcle \
+		| 1750a | dsp16xx | pdp10 | pdp11 \
+		| mips16 | mips64 | mipsel | mips64el \
+		| mips64orion | mips64orionel | mipstx39 | mipstx39el \
+		| mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \
+		| mips64vr5000 | mips64vr5000el | mcore | s390 | s390x \
+		| sparc | sparclet | sparclite | sparc64 | sparcv9 | sparcv9b \
+		| v850 | c4x \
+		| thumb | d10v | d30v | fr30 | avr | openrisc | tic80 \
+		| pj | pjl | h8500 | z8k)
+		basic_machine=$basic_machine-unknown
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12)
+		# Motorola 68HC11/12.
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+		;;
+
+	# We use `pc' rather than `unknown'
+	# because (1) that's what they normally are, and
+	# (2) the word "unknown" tends to confuse beginning users.
+	i*86 | x86_64)
+	  basic_machine=$basic_machine-pc
+	  ;;
+	# Object if more than one company name word.
+	*-*-*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+	# Recognize the basic CPU types with company name.
+	# FIXME: clean up the formatting here.
+	vax-* | tahoe-* | i*86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \
+	      | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | c[123]* \
+	      | arm-*  | armbe-* | armle-* | armv*-* | strongarm-* | xscale-* \
+	      | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
+	      | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \
+	      | xmp-* | ymp-* \
+	      | x86-* | ppcbe-* | mipsbe-* | mipsle-* | shbe-* | shle-* \
+	      | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \
+	      | hppa2.0n-* | hppa64-* \
+	      | alpha-* | alphaev[4-8]-* | alphaev56-* | alphapca5[67]-* \
+	      | alphaev6[78]-* \
+	      | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \
+	      | clipper-* | orion-* \
+	      | sparclite-* | pdp10-* | pdp11-* | sh-* | sh[34]-* | sh[34]eb-* \
+	      | powerpc-* | powerpcle-* | sparc64-* | sparcv9-* | sparcv9b-* | sparc86x-* \
+	      | mips16-* | mips64-* | mipsel-* \
+	      | mips64el-* | mips64orion-* | mips64orionel-* \
+	      | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \
+	      | mipstx39-* | mipstx39el-* | mcore-* \
+	      | f30[01]-* | f700-* | s390-* | s390x-* | sv1-* | t3e-* \
+	      | [cjt]90-* \
+	      | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \
+	      | thumb-* | v850-* | d30v-* | tic30-* | tic80-* | c30-* | fr30-* \
+	      | bs2000-* | tic54x-* | c54x-* | x86_64-* | pj-* | pjl-*)
+		;;
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	386bsd)
+		basic_machine=i386-unknown
+		os=-bsd
+		;;
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		basic_machine=m68000-att
+		;;
+	3b*)
+		basic_machine=we32k-att
+		;;
+	a29khif)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	adobe68k)
+		basic_machine=m68010-adobe
+		os=-scout
+		;;
+	alliant | fx80)
+		basic_machine=fx80-alliant
+		;;
+	altos | altos3068)
+		basic_machine=m68k-altos
+		;;
+	am29k)
+		basic_machine=a29k-none
+		os=-bsd
+		;;
+	amdahl)
+		basic_machine=580-amdahl
+		os=-sysv
+		;;
+	amiga | amiga-*)
+		basic_machine=m68k-unknown
+		;;
+	amigaos | amigados)
+		basic_machine=m68k-unknown
+		os=-amigaos
+		;;
+	amigaunix | amix)
+		basic_machine=m68k-unknown
+		os=-sysv4
+		;;
+	apollo68)
+		basic_machine=m68k-apollo
+		os=-sysv
+		;;
+	apollo68bsd)
+		basic_machine=m68k-apollo
+		os=-bsd
+		;;
+	aux)
+		basic_machine=m68k-apple
+		os=-aux
+		;;
+	balance)
+		basic_machine=ns32k-sequent
+		os=-dynix
+		;;
+	convex-c1)
+		basic_machine=c1-convex
+		os=-bsd
+		;;
+	convex-c2)
+		basic_machine=c2-convex
+		os=-bsd
+		;;
+	convex-c32)
+		basic_machine=c32-convex
+		os=-bsd
+		;;
+	convex-c34)
+		basic_machine=c34-convex
+		os=-bsd
+		;;
+	convex-c38)
+		basic_machine=c38-convex
+		os=-bsd
+		;;
+	cray | ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
+	cray2)
+		basic_machine=cray2-cray
+		os=-unicos
+		;;
+	[cjt]90)
+		basic_machine=${basic_machine}-cray
+		os=-unicos
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	da30 | da30-*)
+		basic_machine=m68k-da30
+		;;
+	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+		basic_machine=mips-dec
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		basic_machine=m68k-motorola
+		;;
+	delta88)
+		basic_machine=m88k-motorola
+		os=-sysv3
+		;;
+	dpx20 | dpx20-*)
+		basic_machine=rs6000-bull
+		os=-bosx
+		;;
+	dpx2* | dpx2*-bull)
+		basic_machine=m68k-bull
+		os=-sysv3
+		;;
+	ebmon29k)
+		basic_machine=a29k-amd
+		os=-ebmon
+		;;
+	elxsi)
+		basic_machine=elxsi-elxsi
+		os=-bsd
+		;;
+	encore | umax | mmax)
+		basic_machine=ns32k-encore
+		;;
+	es1800 | OSE68k | ose68k | ose | OSE)
+		basic_machine=m68k-ericsson
+		os=-ose
+		;;
+	fx2800)
+		basic_machine=i860-alliant
+		;;
+	genix)
+		basic_machine=ns32k-ns
+		;;
+	gmicro)
+		basic_machine=tron-gmicro
+		os=-sysv
+		;;
+	go32)
+		basic_machine=i386-pc
+		os=-go32
+		;;
+	h3050r* | hiux*)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	h8300hms)
+		basic_machine=h8300-hitachi
+		os=-hms
+		;;
+	h8300xray)
+		basic_machine=h8300-hitachi
+		os=-xray
+		;;
+	h8500hms)
+		basic_machine=h8500-hitachi
+		os=-hms
+		;;
+	harris)
+		basic_machine=m88k-harris
+		os=-sysv3
+		;;
+	hp300-*)
+		basic_machine=m68k-hp
+		;;
+	hp300bsd)
+		basic_machine=m68k-hp
+		os=-bsd
+		;;
+	hp300hpux)
+		basic_machine=m68k-hp
+		os=-hpux
+		;;
+	hp3k9[0-9][0-9] | hp9[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		basic_machine=m68000-hp
+		;;
+	hp9k3[2-9][0-9])
+		basic_machine=m68k-hp
+		;;
+	hp9k6[0-9][0-9] | hp6[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k7[0-79][0-9] | hp7[0-79][0-9])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k78[0-9] | hp78[0-9])
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][13679] | hp8[0-9][13679])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hppa-next)
+		os=-nextstep3
+		;;
+	hppaosf)
+		basic_machine=hppa1.1-hp
+		os=-osf
+		;;
+	hppro)
+		basic_machine=hppa1.1-hp
+		os=-proelf
+		;;
+	i370-ibm* | ibm*)
+		basic_machine=i370-ibm
+		;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+	i*86v32)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv32
+		;;
+	i*86v4*)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv4
+		;;
+	i*86v)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv
+		;;
+	i*86sol2)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-solaris2
+		;;
+	i386mach)
+		basic_machine=i386-mach
+		os=-mach
+		;;
+	i386-vsta | vsta)
+		basic_machine=i386-unknown
+		os=-vsta
+		;;
+	iris | iris4d)
+		basic_machine=mips-sgi
+		case $os in
+		    -irix*)
+			;;
+		    *)
+			os=-irix4
+			;;
+		esac
+		;;
+	isi68 | isi)
+		basic_machine=m68k-isi
+		os=-sysv
+		;;
+	m88k-omron*)
+		basic_machine=m88k-omron
+		;;
+	magnum | m3230)
+		basic_machine=mips-mips
+		os=-sysv
+		;;
+	merlin)
+		basic_machine=ns32k-utek
+		os=-sysv
+		;;
+	mingw32)
+		basic_machine=i386-pc
+		os=-mingw32
+		;;
+	miniframe)
+		basic_machine=m68000-convergent
+		;;
+	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+	mipsel*-linux*)
+		basic_machine=mipsel-unknown
+		os=-linux-gnu
+		;;
+	mips*-linux*)
+		basic_machine=mips-unknown
+		os=-linux-gnu
+		;;
+	mips3*-*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+		;;
+	mips3*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+		;;
+	mmix*)
+		basic_machine=mmix-knuth
+		os=-mmixware
+		;;
+	monitor)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	msdos)
+		basic_machine=i386-pc
+		os=-msdos
+		;;
+	mvs)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+	ncr3000)
+		basic_machine=i486-ncr
+		os=-sysv4
+		;;
+	netbsd386)
+		basic_machine=i386-unknown
+		os=-netbsd
+		;;
+	netwinder)
+		basic_machine=armv4l-rebel
+		os=-linux
+		;;
+	news | news700 | news800 | news900)
+		basic_machine=m68k-sony
+		os=-newsos
+		;;
+	news1000)
+		basic_machine=m68030-sony
+		os=-newsos
+		;;
+	news-3600 | risc-news)
+		basic_machine=mips-sony
+		os=-newsos
+		;;
+	necv70)
+		basic_machine=v70-nec
+		os=-sysv
+		;;
+	next | m*-next )
+		basic_machine=m68k-next
+		case $os in
+		    -nextstep* )
+			;;
+		    -ns2*)
+		      os=-nextstep2
+			;;
+		    *)
+		      os=-nextstep3
+			;;
+		esac
+		;;
+	nh3000)
+		basic_machine=m68k-harris
+		os=-cxux
+		;;
+	nh[45]000)
+		basic_machine=m88k-harris
+		os=-cxux
+		;;
+	nindy960)
+		basic_machine=i960-intel
+		os=-nindy
+		;;
+	mon960)
+		basic_machine=i960-intel
+		os=-mon960
+		;;
+	nonstopux)
+		basic_machine=mips-compaq
+		os=-nonstopux
+		;;
+	np1)
+		basic_machine=np1-gould
+		;;
+	nsr-tandem)
+		basic_machine=nsr-tandem
+		;;
+	op50n-* | op60c-*)
+		basic_machine=hppa1.1-oki
+		os=-proelf
+		;;
+	OSE68000 | ose68000)
+		basic_machine=m68000-ericsson
+		os=-ose
+		;;
+	os68k)
+		basic_machine=m68k-none
+		os=-os68k
+		;;
+	pa-hitachi)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	paragon)
+		basic_machine=i860-intel
+		os=-osf
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+        pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	pentium | p5 | k5 | k6 | nexgen)
+		basic_machine=i586-pc
+		;;
+	pentiumpro | p6 | 6x86 | athlon)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2)
+		basic_machine=i686-pc
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-*)
+		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumii-* | pentium2-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pn)
+		basic_machine=pn-gould
+		;;
+	power)	basic_machine=power-ibm
+		;;
+	ppc)	basic_machine=powerpc-unknown
+	        ;;
+	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppcle | powerpclittle | ppc-le | powerpc-little)
+		basic_machine=powerpcle-unknown
+	        ;;
+	ppcle-* | powerpclittle-*)
+		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ps2)
+		basic_machine=i386-ibm
+		;;
+	pw32)
+		basic_machine=i586-unknown
+		os=-pw32
+		;;
+	rom68k)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	rm[46]00)
+		basic_machine=mips-siemens
+		;;
+	rtpc | rtpc-*)
+		basic_machine=romp-ibm
+		;;
+	sa29200)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	sparclite-wrs)
+		basic_machine=sparclite-wrs
+		os=-vxworks
+		;;
+	sps7)
+		basic_machine=m68k-bull
+		os=-sysv2
+		;;
+	spur)
+		basic_machine=spur-unknown
+		;;
+	st2000)
+		basic_machine=m68k-tandem
+		;;
+	stratus)
+		basic_machine=i860-stratus
+		os=-sysv4
+		;;
+	sun2)
+		basic_machine=m68000-sun
+		;;
+	sun2os3)
+		basic_machine=m68000-sun
+		os=-sunos3
+		;;
+	sun2os4)
+		basic_machine=m68000-sun
+		os=-sunos4
+		;;
+	sun3os3)
+		basic_machine=m68k-sun
+		os=-sunos3
+		;;
+	sun3os4)
+		basic_machine=m68k-sun
+		os=-sunos4
+		;;
+	sun4os3)
+		basic_machine=sparc-sun
+		os=-sunos3
+		;;
+	sun4os4)
+		basic_machine=sparc-sun
+		os=-sunos4
+		;;
+	sun4sol2)
+		basic_machine=sparc-sun
+		os=-solaris2
+		;;
+	sun3 | sun3-*)
+		basic_machine=m68k-sun
+		;;
+	sun4)
+		basic_machine=sparc-sun
+		;;
+	sun386 | sun386i | roadrunner)
+		basic_machine=i386-sun
+		;;
+	sv1)
+		basic_machine=sv1-cray
+		os=-unicos
+		;;
+	symmetry)
+		basic_machine=i386-sequent
+		os=-dynix
+		;;
+	t3e)
+		basic_machine=t3e-cray
+		os=-unicos
+		;;
+	tic54x | c54x*)
+		basic_machine=tic54x-unknown
+		os=-coff
+		;;
+	tx39)
+		basic_machine=mipstx39-unknown
+		;;
+	tx39el)
+		basic_machine=mipstx39el-unknown
+		;;
+	tower | tower-32)
+		basic_machine=m68k-ncr
+		;;
+	udi29k)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	ultra3)
+		basic_machine=a29k-nyu
+		os=-sym1
+		;;
+	v810 | necv810)
+		basic_machine=v810-nec
+		os=-none
+		;;
+	vaxv)
+		basic_machine=vax-dec
+		os=-sysv
+		;;
+	vms)
+		basic_machine=vax-dec
+		os=-vms
+		;;
+	vpp*|vx|vx-*)
+               basic_machine=f301-fujitsu
+               ;;
+	vxworks960)
+		basic_machine=i960-wrs
+		os=-vxworks
+		;;
+	vxworks68)
+		basic_machine=m68k-wrs
+		os=-vxworks
+		;;
+	vxworks29k)
+		basic_machine=a29k-wrs
+		os=-vxworks
+		;;
+	w65*)
+		basic_machine=w65-wdc
+		os=-none
+		;;
+	w89k-*)
+		basic_machine=hppa1.1-winbond
+		os=-proelf
+		;;
+	windows32)
+		basic_machine=i386-pc
+		os=-windows32-msvcrt
+		;;
+	xmp)
+		basic_machine=xmp-cray
+		os=-unicos
+		;;
+        xps | xps100)
+		basic_machine=xps100-honeywell
+		;;
+	z8k-*-coff)
+		basic_machine=z8k-unknown
+		os=-sim
+		;;
+	none)
+		basic_machine=none-none
+		os=-none
+		;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		basic_machine=hppa1.1-winbond
+		;;
+	op50n)
+		basic_machine=hppa1.1-oki
+		;;
+	op60c)
+		basic_machine=hppa1.1-oki
+		;;
+	mips)
+		if [ x$os = x-linux-gnu ]; then
+			basic_machine=mips-unknown
+		else
+			basic_machine=mips-mips
+		fi
+		;;
+	romp)
+		basic_machine=romp-ibm
+		;;
+	rs6000)
+		basic_machine=rs6000-ibm
+		;;
+	vax)
+		basic_machine=vax-dec
+		;;
+	pdp10)
+		# there are many clones, so DEC is not a safe bet
+		basic_machine=pdp10-unknown
+		;;
+	pdp11)
+		basic_machine=pdp11-dec
+		;;
+	we32k)
+		basic_machine=we32k-att
+		;;
+	sh3 | sh4)
+		basic_machine=sh-unknown
+		;;
+	sparc | sparcv9 | sparcv9b)
+		basic_machine=sparc-sun
+		;;
+        cydra)
+		basic_machine=cydra-cydrome
+		;;
+	orion)
+		basic_machine=orion-highlevel
+		;;
+	orion105)
+		basic_machine=clipper-highlevel
+		;;
+	mac | mpw | mac-mpw)
+		basic_machine=m68k-apple
+		;;
+	pmac | pmac-mpw)
+		basic_machine=powerpc-apple
+		;;
+	c4x*)
+		basic_machine=c4x-none
+		os=-coff
+		;;
+	*-unknown)
+		# Make sure to match an already-canonicalized machine name.
+		;;
+	*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+	*-digital*)
+		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+		;;
+	*-commodore*)
+		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+	# -solaris* is a basic system type, with this one exception.
+	-solaris1 | -solaris1.*)
+		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		;;
+	-solaris)
+		os=-solaris2
+		;;
+	-svr4*)
+		os=-sysv4
+		;;
+	-unixware*)
+		os=-sysv4.2uw
+		;;
+	-gnu/linux*)
+		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+		;;
+	# First accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST END IN A *, to match a version number.
+	# -sysv* is not here because it comes later, after sysvr4.
+	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+	      | -aos* \
+	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+	      | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+	      | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+	      | -chorusos* | -chorusrdb* \
+	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
+	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* | -os2*)
+	# Remember, each alternative MUST END IN *, to match a version number.
+		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto*)
+		os=-nto-qnx
+		;;
+	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+		;;
+	-mac*)
+		os=`echo $os | sed -e 's|mac|macos|'`
+		;;
+	-linux*)
+		os=`echo $os | sed -e 's|linux|linux-gnu|'`
+		;;
+	-sunos5*)
+		os=`echo $os | sed -e 's|sunos5|solaris2|'`
+		;;
+	-sunos6*)
+		os=`echo $os | sed -e 's|sunos6|solaris3|'`
+		;;
+	-opened*)
+		os=-openedition
+		;;
+	-wince*)
+		os=-wince
+		;;
+	-osfrose*)
+		os=-osfrose
+		;;
+	-osf*)
+		os=-osf
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-386bsd)
+		os=-bsd
+		;;
+	-ctix* | -uts*)
+		os=-sysv
+		;;
+	-ns2 )
+	        os=-nextstep2
+		;;
+	-nsk*)
+		os=-nsk
+		;;
+	# Preserve the version number of sinix5.
+	-sinix5.*)
+		os=`echo $os | sed -e 's|sinix|sysv|'`
+		;;
+	-sinix*)
+		os=-sysv4
+		;;
+	-triton*)
+		os=-sysv3
+		;;
+	-oss*)
+		os=-sysv3
+		;;
+	-svr4)
+		os=-sysv4
+		;;
+	-svr3)
+		os=-sysv3
+		;;
+	-sysvr4)
+		os=-sysv4
+		;;
+	# This must come after -sysvr4.
+	-sysv*)
+		;;
+	-ose*)
+		os=-ose
+		;;
+	-es1800*)
+		os=-ose
+		;;
+	-xenix)
+		os=-xenix
+		;;
+        -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+	        os=-mint
+		;;
+	-none)
+		;;
+	*)
+		# Get rid of the `-' at the beginning of $os.
+		os=`echo $os | sed 's/[^-]*-//'`
+		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+		exit 1
+		;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+	*-acorn)
+		os=-riscix1.2
+		;;
+	arm*-rebel)
+		os=-linux
+		;;
+	arm*-semi)
+		os=-aout
+		;;
+	pdp10-*)
+		os=-tops20
+		;;
+        pdp11-*)
+		os=-none
+		;;
+	*-dec | vax-*)
+		os=-ultrix4.2
+		;;
+	m68*-apollo)
+		os=-domain
+		;;
+	i386-sun)
+		os=-sunos4.0.2
+		;;
+	m68000-sun)
+		os=-sunos3
+		# This also exists in the configure program, but was not the
+		# default.
+		# os=-sunos4
+		;;
+	m68*-cisco)
+		os=-aout
+		;;
+	mips*-cisco)
+		os=-elf
+		;;
+	mips*-*)
+		os=-elf
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=-sysv3
+		;;
+	sparc-* | *-sun)
+		os=-sunos4.1.1
+		;;
+	*-be)
+		os=-beos
+		;;
+	*-ibm)
+		os=-aix
+		;;
+	*-wec)
+		os=-proelf
+		;;
+	*-winbond)
+		os=-proelf
+		;;
+	*-oki)
+		os=-proelf
+		;;
+	*-hp)
+		os=-hpux
+		;;
+	*-hitachi)
+		os=-hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=-sysv
+		;;
+	*-cbm)
+		os=-amigaos
+		;;
+	*-dg)
+		os=-dgux
+		;;
+	*-dolphin)
+		os=-sysv3
+		;;
+	m68k-ccur)
+		os=-rtu
+		;;
+	m88k-omron*)
+		os=-luna
+		;;
+	*-next )
+		os=-nextstep
+		;;
+	*-sequent)
+		os=-ptx
+		;;
+	*-crds)
+		os=-unos
+		;;
+	*-ns)
+		os=-genix
+		;;
+	i370-*)
+		os=-mvs
+		;;
+	*-next)
+		os=-nextstep3
+		;;
+        *-gould)
+		os=-sysv
+		;;
+        *-highlevel)
+		os=-bsd
+		;;
+	*-encore)
+		os=-bsd
+		;;
+        *-sgi)
+		os=-irix
+		;;
+        *-siemens)
+		os=-sysv4
+		;;
+	*-masscomp)
+		os=-rtu
+		;;
+	f30[01]-fujitsu | f700-fujitsu)
+		os=-uxpv
+		;;
+	*-rom68k)
+		os=-coff
+		;;
+	*-*bug)
+		os=-coff
+		;;
+	*-apple)
+		os=-macos
+		;;
+	*-atari*)
+		os=-mint
+		;;
+	*)
+		os=-none
+		;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+	*-unknown)
+		case $os in
+			-riscix*)
+				vendor=acorn
+				;;
+			-sunos*)
+				vendor=sun
+				;;
+			-aix*)
+				vendor=ibm
+				;;
+			-beos*)
+				vendor=be
+				;;
+			-hpux*)
+				vendor=hp
+				;;
+			-mpeix*)
+				vendor=hp
+				;;
+			-hiux*)
+				vendor=hitachi
+				;;
+			-unos*)
+				vendor=crds
+				;;
+			-dgux*)
+				vendor=dg
+				;;
+			-luna*)
+				vendor=omron
+				;;
+			-genix*)
+				vendor=ns
+				;;
+			-mvs* | -opened*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+			-vxsim* | -vxworks*)
+				vendor=wrs
+				;;
+			-aux*)
+				vendor=apple
+				;;
+			-hms*)
+				vendor=hitachi
+				;;
+			-mpw* | -macos*)
+				vendor=apple
+				;;
+			-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+				vendor=atari
+				;;
+		esac
+		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+		;;
+esac
+
+echo $basic_machine$os
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
Index: /tags/greenstone-3_02-distribution/gsdl/configtest.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/configtest.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/configtest.pl	(revision 13928)
@@ -0,0 +1,1 @@
+print $]
Index: /tags/greenstone-3_02-distribution/gsdl/etc/dc2marc-mapping.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/etc/dc2marc-mapping.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/etc/dc2marc-mapping.xml	(revision 13928)
@@ -0,0 +1,238 @@
+<Mapping>
+    <!-- English-->
+    <stopwords lang="en" >
+      <item  name="a " length="2"/>
+      <item  name="an " length="3"/>
+      <item  name="the " length="4"/>
+      <item  name="A " length="2"/>
+      <item  name="An " length="3"/>
+      <item  name="The " length="4"/>
+      <item  name="AN " length="3"/>
+      <item  name="THE " length="4"/>      
+    </stopwords>
+
+    <!--Spain-->
+    <stopwords lang="es">
+      <item  name="uno " length="4"/>
+      <item  name="una " length="4"/>
+      <item  name="el " length="3"/>
+      <item  name="la " length="3"/>
+      <item  name="las " length="4"/>
+      <item  name="los " length="4"/>
+      <item  name="un " length="3"/>
+      <item  name="unos " length="5"/>
+      <item  name="unas " length="5"/>
+    </stopwords>
+
+  <!--Catalan-->
+  <stopwords lang="ca">
+     <item  name="el " length="3"/>
+     <item  name="la " length="3"/>
+     <item  name="les " length="4"/>
+     <item  name="l'" length="2"/>
+     <item  name="un " length="3"/>
+     <item  name="una " length="4"/>
+     <item  name="uns " length="4"/>
+     <item  name="unes " length="5"/>
+     <item  name="es " length="3"/>
+     <item  name="sa " length="3"/>
+     <item  name="ses " length="4"/>
+     <item  name="sos " length="4"/>
+     <item  name="so " length="3"/>
+     <item  name="s'" length="2"/>
+   </stopwords>
+ 
+  <!--German-->  
+  <stopwords lang="de">
+     <item  name="der " length="4"/>
+     <item  name="ein " length="4"/>
+     <item  name="die " length="4"/>
+     <item  name="eine " length="5"/>
+     <item  name="das " length="4"/>
+   </stopwords>
+
+  <!--French-->
+  <stopwords lang="fr">
+     <item  name="le " length="3"/>
+     <item  name="la " length="3"/>
+     <item  name="les " length="4"/>
+     <item  name="un " length="3"/>
+     <item  name="une " length="4"/>
+     <item  name="l'" length="2"/>    
+  </stopwords>
+
+  <!--Italian-->  
+  <stopwords lang="it">
+     <item  name="il " length="3"/>
+     <item  name="lo " length="3"/>
+     <item  name="la " length="3"/>
+     <item  name="gli " length="4"/>
+     <item  name="le " length="3"/>
+     <item  name="un " length="3"/>
+     <item  name="uno " length="4"/>
+     <item  name="una " length="4"/>
+     <item  name="l'" length="2"/>
+     <item  name="un'" length="3"/>
+  </stopwords>
+
+   <!--Galician-->  
+  <stopwords lang="gl">
+     <item  name="o " length="2"/>
+     <item  name="os " length="3"/>
+     <item  name="a " length="2"/>
+     <item  name="as " length="3"/>
+     <item  name="un " length="3"/>
+     <item  name="uns " length="4"/>
+     <item  name="unha " length="5"/>
+     <item  name="unhas " length="6"/>
+   </stopwords> 
+    
+   <recordTypeMapping>
+       <type name="collection" mapping="p"/>
+       <type name="dataset" mapping="m"/>
+       <type name="event" mapping="r"/>
+       <type name="image" mapping="k"/>
+       <type name="interactive resource" mapping="m"/> 
+       <type name="service" mapping="m"/>
+       <type name="software" mapping="m"/>
+       <type name="sound" mapping="i"/>
+       <type name="text" mapping="a"/>      
+    </recordTypeMapping>
+
+    <leader> 
+       <recordLength pos="1" value="00000" />
+       <recordStatus pos="5" value="n" />
+       <recordType pos="6" value="a" />
+       <bibliographiclevel pos="7" value="m" />
+       <controlType pos="8" value=" " />
+       <codingScheme pos="9" value=" " />
+       <indicatorCount pos="10" value="2" />
+       <subfieldCodeCount pos="11" value="2" />
+       <dataBaseAddress pos="12" value="     " />
+       <encodingLevel pos="17" value="3" />
+       <descriptiveCatalogForm pos="18" value="u" />
+       <linkedRecordRequirement pos="19" value=" " />
+       <lpLength pos="20" value="4" />
+       <scpLength pos="21" value="5" />
+       <idLength pos="22" value="0" />
+       <emcpLength pos="23" value="0" /> 
+    </leader>
+        
+    <controlfield tag="001" value="the value of code 001" required="true" />
+    <controlfield tag="002" value="the value of code 002" required="false"/>
+    <controlfield tag="003" value="the value of code 003" required="true"/>
+    <controlfield tag="004" value="the value of code 004" required="false"/>
+    <controlfield tag="005" value="the value of code 005" required="false"/>
+    <controlfield tag="006" value="the value of code 006" required="false"/>
+    <controlfield tag="008" value="the value of code 008" required="true"/>    
+
+<!--this mapping provides duclin core to the following Marc fields mapping:   
+    024 |a[dc.Identifier]
+    245 |a[dc.Title]
+    246 |a[dc.Title] (repeated dc.Title)
+    260 |b[dc.Publisher] |c[dc.Date]
+    500 |a[dc.Coverage] 
+    520 |a[dc.Description]
+    540 |a[dc.Rights]
+    546 |a[dc.Language]
+    653 |a[dc.Subject]
+    655 |s[dc.Type]
+    720 |a[dc.Contributor] |a[dc.Creator]
+    787 |n[dc.Relation]
+    786 |n[dc.Source]
+    856 |q[dc.Format]
+-->
+
+ <!--if the first or second indicator is "nonfiling characters", 
+     one of subfields must have a "nonfiling" attribute with the "true" value
+     to indicate that the begining of this subfield is to be disregarded. 
+     see MarcField 245. 
+-->
+
+<!--If the marc field is same for the repeated metadata (the metadata for the first subfield),
+     set the "multiple" attibute to "true"     
+ -->
+
+<!--If the marc field is different for the repeated metadata (the metadata for the first subfield),
+     set the "repeat" attibute to "true"     
+ -->
+
+<!-- Title  --> 
+ <MarcField multiple="false" datafield="245" ind1="0" ind2="nonfiling">
+     <subfield code="a" nonfiling="true"  meta="dc.Title" punc=""/>
+ </MarcField>
+
+ <MarcField repeat="true" datafield="246" ind1="3" ind2="3" >
+     <subfield code="a" meta="dc.Title" punc=""/>
+  </MarcField>
+  
+<!--Coverage -->
+  <MarcField multiple="true" datafield="500" ind1=" " ind2=" ">
+     <subfield code="a" meta="dc.Coverage" punc=""/>
+  </MarcField>
+    
+
+<!--Contributor-->
+   <MarcField multiple="true" datafield="720" ind1=" " ind2=" ">
+     <subfield code="a" meta="dc.Contributor" punc=","/>
+   </MarcField>
+
+<!--Creator-->
+ <MarcField  multiple="true"  datafield="720" ind1=" " ind2=" ">
+     <subfield code="a" meta="dc.Creator" punc=","/>
+ </MarcField>
+
+ <!--Publisher and  Date-->
+   <MarcField  multiple="false" datafield="260" ind1=" " ind2=" ">
+     <subfield code="b" meta="dc.Publisher" punc=","/>
+     <subfield code="c" meta="dc.Date" punc=""/> 
+   </MarcField>
+
+ <!-- Descrption -->
+    <MarcField multiple="true" datafield="520" ind1=" " ind2=" ">
+       <subfield code="a" meta="dc.Description" punc=""/> 
+    </MarcField>
+   
+  <!--Format -->
+     <MarcField multiple="true" datafield="856" ind1=" " ind2=" ">
+       <subfield code="q" meta="dc.Format" punc=""/> 
+    </MarcField>
+   
+
+ <!--Identifier -->
+     <MarcField multiple="true" datafield="024" ind1="8" ind2=" ">
+        <subfield code="b" meta="dc.Identifier" punc=""/>
+     </MarcField>
+
+ <!--Language-->
+ <MarcField  multiple="false" datafield="546" ind1=" " ind2=" ">
+     <subfield code="a" meta="dc.Language" punc=""/>
+  </MarcField>
+        
+
+  <!-- relation -->
+   <MarcField  multiple="true" datafield="787" ind1="0" ind2=" " >
+      <subfield code="n" meta="dc.Relation" punc=""/>
+   </MarcField>
+     
+  <!-- Right -->
+  <MarcField multiple="true" datafield="540" ind1=" " ind2=" ">
+      <subfield code="a" meta="dc.Rights" punc=""/>
+  </MarcField>
+
+ <!-- subject --> 
+  <MarcField multiple="true" datafield="653" ind1=" " ind2=" ">
+    <subfield code="a" meta="dc.Subject" punc=","/>
+  </MarcField>
+
+<!-- source -->
+ <MarcField multiple="true" datafield="786" ind1="0" ind2=" ">
+     <subfield code="n" meta="dc.Source" punc=""/>
+ </MarcField>
+  
+
+ <!-- type -->
+  <MarcField multiple="true" datafield="655" ind1=" " ind2="7">
+     <subfield code="a" meta="dc.Type" punc=","/>
+  </MarcField>
+</Mapping>
Index: /tags/greenstone-3_02-distribution/gsdl/etc/dc2marc.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/etc/dc2marc.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/etc/dc2marc.xsl	(revision 13928)
@@ -0,0 +1,285 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+      	 xmlns:xsltutil="xalan://org.nzdl.gsdl.ApplyXSLTUtil"
+         exclude-result-prefixes="xsltutil">
+
+  <xsl:output method="xml" indent="yes"/>
+
+  <xsl:param name="mapping" />	
+
+  <xsl:template match="/">
+     <collection>
+           <xsl:apply-templates select="/MARCXML/MetadataList"/>
+      </collection>
+ </xsl:template>
+ 
+  <xsl:template match="MetadataList">
+       <xsl:variable name="lang" >
+       	<xsl:choose>      
+           <xsl:when test="Metadata[@name='dc.Language']">
+                <xsl:value-of select="Metadata[@name='dc.Language']"/>                    
+            </xsl:when>            
+            <!-- comment out this if you want to test dls.Language as well
+             <xsl:when test="Metadata[@name='dls.Language']">
+                <xsl:value-of select="Metadata[@name='dls.Language']"/>                    
+             </xsl:when>
+            -->
+            <xsl:when test="Metadata[@name='Language']">
+                  <xsl:value-of select="Metadata[@name='Language']"/>
+            </xsl:when>           
+           <!-- the defualt language is english --> 
+            <xsl:otherwise>
+                 <xsl:value-of select="en"/>	
+             </xsl:otherwise>
+           </xsl:choose>   
+       </xsl:variable>	
+      <xsl:variable name="item" select="$mapping/stopwords[@lang=$lang]/item"/>
+      <record>
+	  <xsl:apply-templates select="$mapping/leader">
+	     <xsl:with-param name="source" select="." />   
+	  </xsl:apply-templates>                 
+          <xsl:apply-templates select="$mapping/controlfield[@required='true']" /> 
+      	  <xsl:apply-templates select="$mapping/MarcField" >
+	      <xsl:with-param name="source" select="." /> 
+              <xsl:with-param name="item" select="$item" />   
+	  </xsl:apply-templates>                       
+      </record>   
+  </xsl:template>
+
+  <xsl:template match="leader">
+     <xsl:param  name="source" />	
+      <leader>
+         <xsl:for-each select="*">
+           <xsl:choose>
+             <xsl:when test="@pos='3' and count($source/Metadata[@name='dc.Type'])=1">
+                <xsl:apply-templates select="$mapping/recordTypeMapping/type[1]" mode="mapping-type" >
+                  <xsl:with-param name="dctype" select="$source/Metadata[@name='dc.Type'][1]/text()"/>     
+                </xsl:apply-templates>
+            </xsl:when> 
+            <xsl:when test="@pos='3' and count($source/Metadata[@name='dc.Type'])=2
+                                     and $source/Metadata[@name='dc.Type' and text()='collection']">
+                <xsl:apply-templates select="$mapping/recordTypeMapping/type[1]" mode="mapping-type" >
+                  <xsl:with-param name="dctype" select="$source/Metadata[@name='dc.Type' and text()!='collection']/text()"/>
+                </xsl:apply-templates>                     
+            </xsl:when> 
+             <xsl:when test="@pos='3' and count($source/Metadata[@name='dc.Type'])=2" >
+                <xsl:apply-templates select="$mapping/recordTypeMapping/type[1]" mode="mapping-type" >
+                  <xsl:with-param name="dctype" select="$source/Metadata[@name='dc.Type'][1]"/>
+                </xsl:apply-templates>                     
+            </xsl:when>   
+            <xsl:when test="@pos='3' and count($source/Metadata[@name='dc.Type'])>2 ">
+                  <xsl:value-of select="'m'"/>
+            </xsl:when> 
+            <xsl:when test="@pos='4' and $source/Metadata[@name='dc.Type' and text()='collection']">
+                <xsl:value-of select="'c'"/>
+            </xsl:when>
+            <xsl:otherwise>
+                 <xsl:value-of select="@value"/>	
+             </xsl:otherwise>
+           </xsl:choose>      
+         </xsl:for-each>
+       </leader>  
+  </xsl:template>
+
+    
+  <xsl:template match="type" mode="mapping-type">
+   <xsl:param name="dctype" />  
+     <xsl:variable name="typename" select="@name"/>    
+      <xsl:choose>     
+           <xsl:when test="$dctype=$typename or count(following-sibling::*)=0">
+               <xsl:choose>
+                 <xsl:when test="count(following-sibling::*) !=0 ">
+                     <xsl:value-of select="@mapping"/>                                      
+                 </xsl:when>                                      
+                 <xsl:otherwise>
+                       <xsl:value-of select="'a'"/>  
+                 </xsl:otherwise>               
+               </xsl:choose> 
+           </xsl:when>
+         <xsl:otherwise>
+             <xsl:apply-templates select="following-sibling::*[1]" mode="mapping-type" >
+                <xsl:with-param name="dctype" select="$dctype" />                   
+             </xsl:apply-templates>
+         </xsl:otherwise>
+      </xsl:choose>
+  </xsl:template>
+ 
+  <xsl:template match="controlfield">
+     <controlfield tag="{@tag}"><xsl:value-of select="@value"/></controlfield>  
+  </xsl:template>
+ 
+ 
+  <xsl:template match="MarcField">
+   <xsl:param  name="source" />  
+   <xsl:param  name="item" /> 
+   <xsl:variable name="this" select="."/> 
+   <xsl:choose>
+      <xsl:when test="@multiple='true'">
+        <xsl:variable name="meta" select="subfield[1]/@meta"/>       
+        <xsl:for-each select="$source/Metadata[@name=$meta]">
+         <xsl:apply-templates select="$this/subfield[1]" mode="testing"> 
+                <xsl:with-param name="pos" select="position()"/> 
+	        <xsl:with-param name="source" select="$source"/>
+                <xsl:with-param name="item" select="$item"/> 
+            </xsl:apply-templates>
+        </xsl:for-each>
+      </xsl:when>
+      <xsl:when test="@repeat='true'">
+        <xsl:variable name="meta" select="subfield[1]/@meta"/>
+        <xsl:for-each select="$source/Metadata[@name=$meta][position()!=1]">
+           <xsl:apply-templates select="$this/subfield[1]" mode="testing"> 
+               <xsl:with-param name="pos" select="position()+1"/> 
+	       <xsl:with-param name="source" select="$source"/>
+               <xsl:with-param name="item" select="$item"/>  
+            </xsl:apply-templates>
+        </xsl:for-each>
+      </xsl:when>
+       <xsl:otherwise>
+         <xsl:apply-templates select="subfield[1]" mode="testing">
+           <xsl:with-param name="pos" select="'0'"/> 
+	   <xsl:with-param name="source" select="$source"/> 
+           <xsl:with-param name="item" select="$item"/>  
+         </xsl:apply-templates>
+       </xsl:otherwise> 
+    </xsl:choose>        
+  </xsl:template>
+  
+  <xsl:template match="subfield" mode="testing">
+     <xsl:param name="pos"/>
+     <xsl:param  name="source" /> 
+     <xsl:param  name="item" />
+     <xsl:variable name="meta" select="@meta"/>
+     <xsl:choose>     
+       <xsl:when test="count($source/Metadata[@name=$meta]) >0">
+          <datafield>
+             <xsl:apply-templates select="../@*" mode="mapping-attribute">
+               <xsl:with-param name="source" select="$source"/>
+                <xsl:with-param name="item" select="$item"/>
+             </xsl:apply-templates>                                      
+             <xsl:apply-templates select="../subfield[not(@nonfiling)]" >                       
+               <xsl:with-param name="pos" select="$pos"/> 
+               <xsl:with-param name="source" select="$source"/>
+             </xsl:apply-templates>   
+         </datafield>
+       </xsl:when>
+       <xsl:otherwise>
+             <xsl:apply-templates select="following-sibling::*[1]" mode="testing" >
+                    <xsl:with-param name="pos" select="$pos"/> 
+            	    <xsl:with-param name="source" select="$source"/>
+                    <xsl:with-param name="item" select="$item"/>
+             </xsl:apply-templates> 
+         </xsl:otherwise>
+      </xsl:choose>       
+  </xsl:template>
+  
+
+  <xsl:template match="@*" mode="mapping-attribute" >
+     <xsl:param name="source" />
+     <xsl:param name="item" /> 	
+     <xsl:variable name="name" select="name()"/>
+     <xsl:variable name="value" select="."/>
+     <xsl:choose> 
+     <xsl:when test="starts-with($name,'ind') and $value='nonfiling'">
+         <xsl:variable name="meta" select="../subfield[@nonfiling='true']/@meta"/>
+         <xsl:variable name="content" select="$source/Metadata[@name=$meta]/text()"/>  
+         <xsl:apply-templates select="$item[1]" mode="mapping-item">
+             <xsl:with-param name='name' select="$name"/>
+             <xsl:with-param name='content' select="$content"/>
+             <xsl:with-param name='subfield' select="../subfield[@nonfiling='true']"/>
+	     <xsl:with-param name='source' select="$source"/>
+         </xsl:apply-templates>     
+      </xsl:when>
+      <xsl:otherwise>      
+        <xsl:if test="starts-with($name,'ind') or starts-with($name,'datafield') ">
+          <xsl:call-template name="addAttribute" >
+             <xsl:with-param name='name' select="$name"/>
+             <xsl:with-param name='value' select="$value"/>         
+          </xsl:call-template>    
+        </xsl:if>
+      </xsl:otherwise>   
+    </xsl:choose> 
+ </xsl:template>
+
+  
+ <xsl:template match="item" mode="mapping-item">
+     <xsl:param name="name" />
+     <xsl:param name="content" />
+     <xsl:param name="subfield" />
+     <xsl:param name="source" />
+
+  <xsl:variable name="itemname" select="@name"/>
+  <xsl:variable name="lowercasecontent" select="xsltutil:toLowerCase($content)"/>		
+      <xsl:choose>     
+           <xsl:when test="starts-with($lowercasecontent,$itemname) or count(following-sibling::*)=0">
+               <xsl:choose>
+                 <xsl:when test="starts-with($lowercasecontent,$itemname)" >              
+                      <xsl:call-template name="addAttribute" >
+                         <xsl:with-param name="name" select="$name"/>
+                         <xsl:with-param name="value" select="@length"/>         
+                      </xsl:call-template>          
+                      <xsl:apply-templates select="$subfield" >
+                         <xsl:with-param name="length" select="@length" />
+                         <xsl:with-param name="content" select="$content" />
+	                 <xsl:with-param name="source" select="$source" />                  
+                      </xsl:apply-templates>
+                 </xsl:when>                                      
+                 <xsl:otherwise>
+                      <xsl:call-template name="addAttribute" >
+                          <xsl:with-param name="name" select="$name"/>
+                          <xsl:with-param name="value" select="'0'"/>         
+                      </xsl:call-template>          
+                      <xsl:apply-templates select="$subfield" >
+                          <xsl:with-param name="length" select="'0'" />
+                          <xsl:with-param name="content" select="$content" />
+                          <xsl:with-param name="source" select="$source" />                   
+                      </xsl:apply-templates>  
+                 </xsl:otherwise>               
+               </xsl:choose> 
+           </xsl:when>
+         <xsl:otherwise>
+             <xsl:apply-templates select="following-sibling::*[1]" mode="mapping-item" >
+                <xsl:with-param name="name" select="$name" />
+                <xsl:with-param name="content" select="$content" />
+                <xsl:with-param name="subfield" select="$subfield" />
+	        <xsl:with-param name="source" select="$source" />     
+             </xsl:apply-templates>
+         </xsl:otherwise>
+      </xsl:choose>
+  </xsl:template>
+
+  
+  <xsl:template name="addAttribute">
+      <xsl:param name="value" />
+      <xsl:param name="name" />
+      <xsl:attribute name="{$name}"><xsl:value-of select="$value"/></xsl:attribute>
+  </xsl:template>
+
+ 
+
+  <xsl:template match="subfield">
+     <xsl:param name="length" />
+     <xsl:param name="content" />
+     <xsl:param name="pos" />         
+     <xsl:param name="source" />
+     <xsl:variable name="meta" select="@meta" />
+     <xsl:variable name="punc" select="@punc" /> 
+     <xsl:if test="$source/Metadata[@name=$meta]">
+      <xsl:choose>
+        <xsl:when test="@nonfiling='true'">
+          <subfield code="{@code}"><xsl:value-of select="$content"/><xsl:value-of select="@punc"/></subfield>
+        </xsl:when>
+        <xsl:when test="$pos >0">
+           <subfield code="{@code}">
+                <xsl:value-of select="$source/Metadata[@name=$meta][$pos]"/><xsl:value-of select="$punc"/>
+           </subfield>
+        </xsl:when>
+        <xsl:otherwise>
+           <subfield code="{@code}">
+                <xsl:value-of select="$source/Metadata[@name=$meta]"/><xsl:value-of select="$punc"/>
+           </subfield> 
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:if>         
+  </xsl:template>
+  
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gsdl/etc/marctodc.txt
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/etc/marctodc.txt	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/etc/marctodc.txt	(revision 13928)
@@ -0,0 +1,86 @@
+#
+# This file is used by MARCPlug for mapping MARC field numbers to
+# Greenstone-style metadata.
+#
+# The field numbers listed in this file are for USMARC / MARC21.
+#
+# Lines beginning with "#" are comments.
+# The format for these files are:
+#  <number> -> GreenstoneMetadataName
+#
+# This is loosely based on the MARC -> Dublin Core mapping as found at
+#   http://lcweb.loc.gov/marc/dccross.html
+#
+# The problem with that is that some mappings are conditional on
+# subfield values...
+
+### Contributor	###
+# 720 = "Uncontrolled Name", with $e=collaborator
+
+### Coverage	###
+#500 -> Coverage
+
+### Creator	###
+# 720 = "Uncontrolled Name" with $e=author
+720 -> Creator
+# 100 = "Personal Name"
+100	-> Creator
+# 110 = "Corporate Name" 
+110	-> Creator
+# 111 = "Meeting Name"
+111	-> Creator
+
+### Date	###
+# Don't do this yet, as greenstone expects dates in YYYYMMDD format...
+# 260, $c (but also see Publisher below)
+# 260 -> Date
+
+### Description	###
+# 520 = "Summary, Note"
+520 -> Description
+
+### Identifier	###
+# 024 = "Standard Identifier/number"
+# greenstone uses its own Identifier metadata
+024 -> MarcIdentifier
+
+# 856 = "Electronic Location"
+856 -> URL
+
+### Language	###
+# Greenstone has its own Language metadata...
+546 -> MarcLanguage
+
+### Publisher	###
+# 260 = "Publication, etc"
+# 260 $b if $e=publisher... (but see Date)
+260 -> Publisher
+
+### Relation	###
+# 787 = "Nonspecific Relationship Note"
+787 -> Relation
+
+### Rights	###
+# 540 = "Reproduction Note"
+540 -> Rights
+
+### Source	###
+# greenstone has its own Source metadata...
+# 786 = "Data Source Entry"
+786 -> MarcSource
+
+### Subject	###
+# 650 = "Subject: Topical Term"
+650 -> Subject
+# 653 = "Index Term: Uncontrolled"
+653 -> Subject
+
+### Title	###
+# 245 = "Title Statement"
+245	-> Title
+# 246 = "Varying Form of Title"
+
+### Type	###
+# 655 = "Index Term - Genre/Form"
+655 -> Type
+
Index: /tags/greenstone-3_02-distribution/gsdl/etc/packages/example.dbi
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/etc/packages/example.dbi	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/etc/packages/example.dbi	(revision 13928)
@@ -0,0 +1,109 @@
+# -*- perl -*-
+# This is an example configuration file for greenstone's DBPlug
+# (DataBase plugin).
+#
+# This config file should be a fragment of perl, specifying how to
+# get records out of a database. This uses perl's DBI module, which
+# includes back-ends for mysql, postgresql, comma separated values (CSV),
+# MS Excel, ODBC, sybase, etc...
+#
+# You need to install the separate backends - For example, on debian you
+# need the libdbi-perl base package and then the libdbd-mysql-perl,
+# libdbd-csv-perl, libdbd-pg-perl and/or libdbd-sybase-perl (etc) packages.
+
+
+# debugging. Set to 0 if you don't want extra information printed
+# out during greenstone's import process.
+#
+$dbplug_debug=1;
+
+
+# If these are commented out, then we will use the plugin's defaults.
+# However, you might want to override them here if you know what they
+# are for this particular database
+# run "$ pluginfo.pl DBPlug | less" to see a list of valid encodings
+# Language metadata isn't really necessary unless you want indexes by language
+# However, Encoding is important, for converting data to utf8
+#
+
+$language = "en";
+$encoding = "iso_8859_1";
+
+
+# Data Source.
+# This is going to be dependent on which back-end you use. Note that these
+# strings are case-sensitive.
+# Eg, for postgres, it is "DBI:Pg:dbname=<database>".
+# For mysql, it might look like "DBI:mysql:database=<database>;host=localhost"
+# For the CSV (comma-separated values text-file) backend, try something like
+#   'DBI:CSV:f_dir=/path/to/directory/containing/csvfile;csv_quote_char=\";csv_sep_char=	'
+# with an embedded tab character for tab-separated instead of the
+# default comma-separated.
+
+$db='';
+
+# If you need a username and password to connect to this database,
+# uncomment these lines and fill in the details
+#
+#$username='';
+#$password='';
+
+# DBI does not allow you to use multiple SQL statements at once. So if
+# you want to execute two statements (for example, to prep the data by
+# creating a temporary table), uncomment and use this as the first statement.
+ 
+#$sql_query_prime = 'CREATE TEMP TABLE foo AS
+# SELECT t1.ID, t2.name
+# FROM table1 AS t1 JOIN table2 AS t2
+# ON t1.ID = t2.ID ';
+
+# sql query required to get your rows out of the database. Each row will
+# become a separate greenstone document.
+#
+#$sql_query = 'SELECT id, name, data FROM foo JOIN table2 WHERE something';
+# For CSV, the table name is the file name. Eg:
+#$sql_query = 'SELECT * FROM values.txt'
+# CSV may also require DOS '\r\n'-style line endings instead of unix '\n'.
+# It is easier if your data file does not have a dot '.' in it, as that is
+# not a valid character in an SQL table name (although it works for simple
+# SELECTS but not joins).
+
+$sql_query='';
+
+# a map of database field names to Greenstone metadata field names.
+# You should have a "Title" field and a "text" field, at a minimum.
+# If you want to give records a unique identifier from a database field
+# rather than have greenstone perform a hash on the document, also provide
+# an "Identifier" metadata field.
+# If you do map something to Identifier, make sure that the field is unique
+# for each record, and also note that because greenstone does special things
+# if this field is only numeric, DBPlug will add some letters to the front
+# if this is the case.
+#
+#%db_to_greenstone_fields=(
+#			  "name" => "Title",
+#			  "data" => "text",
+#			  "id" => "Identifier"
+#			  );
+
+%db_to_greenstone_fields=(
+
+			  );
+
+# finally, you can declare subroutines here to post-process the fields
+# in case you want to do any mark up or processing of it. 
+# For example, you might want to do HTML formatting.
+# The subroutine's name should be the greenstone metadata field name,
+# followed by "_callback", and must end with "}" in the first column.
+#
+#sub text_callback {
+#    my $text=shift;
+#    # do markup stuff...
+#    return $text;
+#}
+#
+#sub Title_callback {
+#    my $title=shift;
+#    return ucfirst($title); # uppercase first letter
+#}
+
Index: /tags/greenstone-3_02-distribution/gsdl/etc/packages/phind/stopword/en/brown.sw
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/etc/packages/phind/stopword/en/brown.sw	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/etc/packages/phind/stopword/en/brown.sw	(revision 13928)
@@ -0,0 +1,2009 @@
+a
+aah
+aback
+abed
+abjectly
+ablaze
+ably
+abnormally
+aboard
+about
+abreast
+abroad
+abroade
+abruptly
+absently
+absentmindedly
+absolutely
+abstractly
+absurdly
+abundantly
+academically
+accidentally
+according
+accordingly
+accurately
+accusingly
+acourse
+acoustically
+across
+actively
+actually
+actuarially
+acutely
+adamantly
+additionally
+adequately
+administratively
+admirably
+admiringly
+admittedly
+adrift
+advantageously
+adversely
+advisedly
+afar
+affectingly
+affectionately
+affirmatively
+afield
+afloat
+afoot
+aforethought
+afresh
+after
+afterward
+afterwards
+aftuh
+again
+against
+agayne
+aggressively
+agilely
+agin
+ago
+agreeably
+agriculturally
+ah
+ahah
+ahead
+ahem
+ahn
+ai
+aimlessly
+airily
+ajar
+alarmingly
+alas
+albeit
+alertly
+algebraically
+alike
+all
+allegedly
+allso
+almost
+aloft
+alone
+along
+alongside
+aloud
+alreadeh
+already
+also
+alternately
+alternatively
+altho
+although
+altogether
+altruistically
+always
+am
+amazingly
+ambitiously
+ame
+amen
+amicably
+amid
+amidst
+among
+amongst
+amorphously
+amply
+amusedly
+amusingly
+an
+analogously
+analytically
+anatomically
+anciently
+and
+anesthetically
+anew
+angrily
+anhydrously
+ani
+annually
+another
+anti
+anxiously
+any
+anybody
+anye
+anyhow
+anymore
+anyone
+anyplace
+anythin
+anything
+anyway
+anyways
+anywhere
+apart
+apiece
+apologetically
+appallingly
+apparently
+appraisingly
+appreciably
+appreciatively
+apprehensively
+appropriately
+approvingly
+approximately
+aptly
+arbitrarily
+are
+aristocratically
+around
+arrogantly
+artfully
+artificially
+artistically
+as
+asham
+ashore
+aside
+askance
+askew
+asleep
+associatively
+assuredly
+astonishingly
+astray
+astride
+astronomically
+asunder
+asymmetrically
+asymptotically
+at
+atonally
+atop
+atrociously
+att
+atta
+attentively
+attractively
+audibly
+aurally
+auspiciously
+austerely
+authentically
+authoritatively
+automatically
+avidly
+aw
+away
+awaye
+awfully
+awhile
+awkwardly
+axially
+aye
+backstage
+backstairs
+backward
+backwards
+badly
+bah
+bannnnnng
+barely
+basically
+be
+beautifully
+because
+beefore
+been
+befoh
+before
+beforehand
+behahn
+behaviorally
+behind
+bein
+being
+beinge
+belatedly
+believably
+belligerently
+below
+beneath
+beside
+besides
+between
+bewilderedly
+bewilderingly
+beyond
+bi
+billion
+biologically
+bitterly
+blandly
+bleakly
+blindly
+blissfully
+blithely
+bluntly
+boastfully
+bodily
+boldly
+bong
+both
+bravely
+brazenly
+breathlessly
+briefly
+brightly
+brilliantly
+briskly
+broadly
+brokenly
+brusquely
+brutally
+busily
+but
+by
+callously
+calmly
+can
+candidly
+cannot
+capably
+carefully
+carelessly
+casually
+catastrophically
+categorically
+causally
+cautiously
+ceaselessly
+centrally
+ceremonially
+ceremoniously
+certainly
+characteristically
+charmingly
+cheaply
+cheerfully
+chemically
+chiefly
+childishly
+chronically
+chronologically
+circa
+circumspectly
+clairaudiently
+classically
+cleanly
+clearly
+cleverly
+clinically
+clockwise
+closely
+clumsily
+coarsely
+cogently
+cohesively
+colde
+coldly
+collectively
+comfortably
+comically
+commercially
+commonly
+compactly
+comparatively
+compassionately
+competently
+competitively
+completely
+comprehensively
+compulsively
+concededly
+conceivably
+conceptually
+concerning
+conclusively
+concretely
+concurrently
+confidentially
+confidently
+consanguineously
+consciously
+consequently
+considerably
+considerately
+consisently
+consistently
+conspicuously
+constantly
+constructively
+consummately
+contemptuously
+contentedly
+continentally
+continually
+continuously
+contradictorily
+contrarily
+conveniently
+conventionally
+conversely
+convincingly
+convulsively
+coolly
+copiously
+correctly
+correlatively
+correspondingly
+cortically
+cosily
+coud
+coudn
+could
+courageously
+courteously
+covertly
+coyly
+crazily
+creatively
+credibly
+crisply
+critically
+crossways
+crosswise
+crucially
+crudely
+cruelly
+culturally
+cunningly
+curiously
+currently
+curtly
+curvaceously
+customarily
+cynically
+d
+da
+daintily
+dammit
+damnit
+dandily
+dangerously
+darkly
+dearly
+deathly
+decently
+deceptively
+decidedly
+decisively
+deeply
+defiantly
+definitely
+dejectedly
+deliberately
+delicately
+deliciously
+delightfully
+demandingly
+demonstrably
+denominationally
+depending
+deplorably
+depressingly
+dere
+derisively
+despairingly
+desperately
+despite
+determinedly
+devastatingly
+devotedly
+devoutly
+dey
+diagonally
+dialectically
+diametrically
+did
+diddle
+didn
+differently
+diffusely
+diligently
+dimensionally
+dimly
+directionally
+directly
+disapprovingly
+disconcertingly
+discordantly
+discreetly
+dismally
+dispassionately
+disproportionately
+distally
+distantly
+distastefully
+distinctively
+distinctly
+distractedly
+disturbingly
+divinely
+dizzily
+do
+doan
+docilely
+doctrinally
+does
+doggedly
+doggone
+dogmatically
+domestically
+dominantly
+doo
+dost
+doubly
+doubtfully
+doubtingly
+doubtless
+dourly
+down
+downright
+downstairs
+downwind
+dramatically
+drastically
+dreadfully
+dreamlessly
+drowsily
+drunkenly
+druther
+dryly
+dully
+duly
+during
+dutifully
+dynamically
+each
+eagerly
+earnestly
+easily
+eastward
+eclectically
+economically
+edgewise
+editorially
+eerily
+effectively
+efficaciously
+efficiently
+effortlessly
+egregiously
+eh
+eight
+eighteen
+eighteenth
+eighth
+eighty
+either
+elaborately
+electrically
+elegantly
+eleven
+eleventh
+eloquently
+else
+elsewhere
+em
+embarrassingly
+eminently
+emotionally
+emphatically
+empirically
+enchantingly
+encouragingly
+endlessly
+enduringly
+energetically
+engagingly
+enny
+enormously
+enough
+enterprisingly
+enthusiastically
+entirely
+enviably
+enviously
+epicyclically
+equally
+equidistantly
+equitably
+ere
+erotically
+erratically
+erroneously
+especially
+essentially
+etcetera
+ether
+ethically
+evenly
+eventfully
+eventshahleh
+eventually
+evenutally
+ever
+everlastingly
+every
+everybody
+everyone
+everything
+everywhere
+evidently
+exactly
+exasperatingly
+exceedingly
+excellently
+except
+excepting
+exceptionally
+excessively
+excitedly
+excluding
+exclusively
+exhaustingly
+exhaustively
+expansively
+expectantly
+expectedly
+expeditiously
+experientially
+experimentally
+expertly
+explicitly
+explosively
+expressly
+exquisitely
+extempore
+extensively
+externally
+extraordinarily
+extremely
+exuberantly
+exultantly
+facetiously
+faintly
+fairly
+faithfully
+familiarly
+fantastically
+farther
+fascinatingly
+fatally
+favorably
+fearfully
+fearlessly
+feebly
+fer
+ferociously
+fervently
+feverishly
+few
+fewer
+fiercely
+fifteen
+fifteenth
+fifth
+fiftieth
+fifty
+finally
+financially
+finely
+firmly
+first
+fitfully
+five
+flagrantly
+flamboyantly
+flatly
+flatteringly
+fluently
+focally
+foh
+fondly
+foolishly
+for
+forcibly
+foremost
+forever
+formally
+former
+formerly
+formidably
+forth
+forthrightly
+fortunately
+forty
+foully
+four
+fourteen
+fourteenth
+fourth
+fragmentarily
+frankly
+frantically
+freely
+frenziedly
+frequently
+freshly
+friendlily
+frighteningly
+frightfully
+from
+frowningly
+frugally
+fruitfully
+fruitlessly
+fully
+functionally
+fundamentally
+furiously
+furthermore
+furtively
+fussily
+futhermore
+gaily
+gaspingly
+gawdamighty
+generally
+generously
+gently
+genuinely
+geographically
+geometrically
+girlishly
+gladly
+glaringly
+gleefully
+glibly
+globally
+gloomily
+gloriously
+glumly
+godamit
+goddamit
+goddammit
+golly
+goodbye
+goodnight
+goody
+goolick
+goooolick
+gorgeously
+gosh
+governmentally
+gracefully
+graciously
+gradually
+grammatically
+grandly
+graphically
+gratefully
+gratifyingly
+gratingly
+gratis
+gratuitously
+gravely
+greatly
+greedily
+greenly
+grevouselye
+grimly
+grossly
+grotesquely
+grudgingly
+ha
+habitually
+had
+hadd
+haf
+haggardly
+haint
+half
+halfways
+haltingly
+handsomely
+haphazardly
+happily
+harder
+hardly
+harmlessly
+harmoniously
+harro
+harshly
+has
+hast
+hastily
+hath
+haughtily
+have
+having
+he
+healthily
+heartily
+heatedly
+heavily
+hello
+helpfully
+helplessly
+hence
+henceforth
+henh
+her
+here
+hereabouts
+hereafter
+hereby
+herein
+hereinafter
+heretofore
+hereunto
+herewith
+heroically
+hers
+herself
+hesitantly
+hesitatingly
+hev
+hevin
+hey
+hi
+hideously
+highly
+hilariously
+him
+himself
+himselfe
+hir
+his
+hisself
+historically
+hither
+hitherto
+hmpf
+hoarsely
+homeward
+homewards
+homogeneously
+honestly
+honorably
+hopefully
+hopelessly
+horizontally
+horribly
+horrifyingly
+hotly
+how
+howe
+however
+howsomever
+hubba
+huh
+humanely
+humanly
+humbly
+humiliatingly
+hundred
+hundredth
+hurriedly
+huskily
+hydraulically
+hym
+hyperbolically
+hypnotically
+hypothalamically
+hys
+hytt
+ideally
+identically
+idiotically
+idly
+if
+illegally
+imaginatively
+immeasurably
+immediately
+immensely
+impassively
+impatiently
+impeccably
+imperceptibly
+imperfectly
+imperiously
+impersonally
+implausibly
+implicitly
+importantly
+importunately
+impossibly
+imprecisely
+improbably
+improperly
+imprudently
+impudently
+in
+inadequately
+inadvertently
+inasmuch
+incessantly
+incidentally
+including
+incoherently
+incomparably
+incompletely
+inconspicuously
+inconveniently
+increasingly
+incredibly
+incredulously
+incurably
+indecisively
+indeed
+indefinitely
+indelibly
+independently
+indignantly
+indirectly
+indiscriminantly
+indisputably
+individually
+indolently
+indoors
+industrially
+industriously
+ineffectively
+ineptly
+inescapably
+inevitably
+inexorably
+inexplicably
+inexpressibly
+infernally
+infinitely
+infinitesimally
+informally
+infra
+infrequently
+ingeniously
+inherently
+initially
+inland
+innocently
+inordinately
+insanely
+insidiously
+insofar
+insolently
+insomma
+instantaneously
+instantly
+instead
+instinctively
+instrumentally
+insufficiently
+insuperably
+intellectually
+intelligently
+intensely
+intensively
+intentionally
+intently
+interestingly
+intermittently
+internally
+internationally
+intimately
+into
+intramuscularly
+intricately
+intriguingly
+intrinsically
+intuitively
+invariably
+inversely
+invisibly
+involuntarily
+inwardly
+ironically
+irrationally
+irredeemably
+irregularly
+irreparably
+irresistibly
+irreversibly
+irrevocably
+irritably
+is
+isothermally
+it
+its
+itself
+jaggedly
+jealously
+jist
+jocularly
+jointly
+joyfully
+joyously
+jubilantly
+judiciously
+july
+jurisprudentially
+justifiably
+justly
+kaboom
+keenly
+kin
+kinda
+kinesthetically
+knowingly
+laboriously
+lahk
+lak
+largely
+last
+lastly
+lately
+latter
+laudably
+laughingly
+lavishly
+lazily
+least
+legally
+legitimately
+lengthily
+less
+lest
+lewdly
+liberally
+lightly
+likewise
+limply
+linearly
+linguistically
+listlessly
+literally
+litle
+lo
+locally
+logically
+loosely
+lopsidedly
+loudly
+lovingly
+luckily
+lustily
+m
+macroscopically
+madly
+magically
+magnetically
+magnificently
+mah
+maht
+mai
+mainly
+majestically
+maliciously
+manifestly
+manually
+many
+manye
+marginally
+markedly
+marketwise
+marvelously
+masterfully
+materially
+mathematically
+may
+maybe
+maye
+mayst
+me
+meaningfully
+meanwhile
+measurably
+mechanically
+mechanochemically
+medically
+mee
+meekly
+melodically
+mentally
+mercifully
+mercilessly
+merely
+merrily
+methodically
+meticulously
+metrically
+microscopically
+midway
+might
+mightily
+mildly
+militantly
+militarily
+million
+mimetically
+mine
+minimally
+minus
+minutely
+miraculously
+miserably
+mistakenly
+mmm
+mmmm
+mockingly
+moderately
+modestly
+momentarily
+monolithically
+monumentally
+moodily
+mor
+morally
+more
+moreover
+morosely
+mortally
+most
+mostly
+mountainously
+mournfully
+movingly
+much
+municipally
+musically
+must
+mutely
+mutually
+my
+myn
+myne
+myself
+mysteriously
+n
+na
+nae
+naively
+nakedly
+namely
+narrowly
+nary
+natch
+nationally
+naturally
+naught
+naw
+nawt
+nay
+nearly
+nearsightedly
+neatly
+necessarily
+needlessly
+negatively
+neither
+nervously
+nether
+never
+nevertheless
+next
+nicely
+nigh
+nightly
+nilly
+nimbly
+nine
+nineteen
+nineteenth
+ninetieth
+ninety
+ninth
+no
+nobody
+noisily
+nominally
+noncommittally
+nondescriptly
+none
+nonetheless
+nonspecifically
+nope
+nor
+normally
+northward
+nostalgically
+not
+notably
+noth
+nothin
+nothing
+noticeably
+notoriously
+nott
+notwithstanding
+now
+nowadays
+nowhere
+nuf
+numbingly
+numerically
+o
+objectively
+obligingly
+obliquely
+obscurely
+obviously
+occasionally
+octillion
+oddly
+of
+off
+offensively
+officially
+offstage
+oft
+often
+oftener
+oftentimes
+oh
+okay
+ominously
+on
+once
+onct
+one
+oneself
+onleh
+only
+onto
+ontologically
+onward
+onwards
+oooo
+oops
+openly
+operationally
+optically
+or
+orally
+ordinarily
+organically
+organizationally
+originally
+ornately
+ostensibly
+other
+otherwise
+ought
+our
+ours
+ourselves
+out
+outdoors
+outstandingly
+outwardly
+over
+overboard
+overland
+overly
+overtly
+overwhelmingly
+ovuh
+owly
+ownself
+painfully
+painlessly
+painstakingly
+palely
+palpably
+paradoxically
+parenthetically
+partially
+particularly
+partly
+passionately
+passively
+paternally
+patiently
+peacefully
+peculiarly
+per
+perchance
+perennially
+perfectly
+perforce
+perfunctorily
+perhaps
+perilously
+periodically
+peripherally
+permanently
+perpendicularly
+perpetually
+persistently
+personally
+persuasively
+pervasively
+perversely
+philosophically
+photographically
+physically
+physiologically
+pictorially
+piecewise
+pinkly
+piously
+pip
+pitifully
+pitilessly
+pityingly
+plainly
+plastically
+pleasantly
+pleasingly
+plumb
+plus
+poetically
+poignantly
+pointedly
+politely
+politically
+pompously
+poorly
+popularly
+positively
+possibly
+potentially
+powerfully
+practically
+prayerfully
+precariously
+precisely
+precociously
+predictably
+predominantly
+predominately
+preferably
+preferentially
+prematurely
+preponderantly
+presente
+presently
+presentlye
+presumably
+prettily
+pretty
+previously
+primarily
+primly
+principally
+privately
+probably
+probly
+prodigally
+professedly
+professionally
+profitably
+profoundly
+profusely
+progressively
+prominently
+promptly
+pronto
+properly
+prophetically
+proportionally
+proportionately
+protectively
+proudly
+provocatively
+prudentially
+prudently
+psychically
+psychologically
+publically
+publicly
+pugh
+punctually
+pungently
+purely
+purportedly
+purposefully
+purposely
+purposively
+pursuant
+quadrillion
+qualitatively
+quantitatively
+querulously
+questioningly
+quickly
+quietly
+quintillion
+quite
+quitely
+racially
+radically
+rakishly
+randomly
+rapidly
+rarely
+rather
+rationally
+raucously
+readily
+realistically
+really
+reasonably
+reassuringly
+rebelliously
+recently
+recklessly
+rectlinearly
+recurrently
+reflexly
+refreshingly
+regarding
+regardless
+regionally
+regretfully
+regrettably
+regularly
+relatively
+relentlessly
+reliably
+religiously
+reluctantly
+remarkably
+remotely
+repeatedly
+reportedly
+reproducibly
+reprovingly
+reputedly
+residentially
+resignedly
+resolutely
+resourcefully
+respectfully
+respectively
+responsibly
+responsively
+restively
+restlessly
+reverently
+rhythmically
+richly
+ridiculously
+rightfully
+rightly
+rigidly
+rigorously
+rollickingly
+romantically
+rotationally
+roughly
+roughtly
+roundly
+routinely
+rudely
+ruefully
+ruggedly
+ruthlessly
+sadly
+safely
+same
+sarcastically
+satirically
+satisfactorily
+savagely
+scarcely
+scathingly
+schematically
+scholastically
+scientifically
+scornfully
+scrupulously
+searchingly
+seasonally
+second
+secondarily
+secondly
+secretly
+securely
+sedately
+sedulously
+seekingly
+seemingly
+seldom
+selectively
+semantically
+senselessly
+sensibly
+sensitively
+separately
+septillion
+serenely
+seriously
+seven
+seventeen
+seventeenth
+seventh
+seventy
+several
+severally
+severely
+severly
+sextillion
+sexually
+sha
+shabbily
+shakily
+shall
+shamefacedly
+sharply
+shatteringly
+she
+shh
+shiningly
+shockingly
+shortly
+should
+shrewdly
+shrilly
+shucks
+shuld
+shulde
+shyly
+sidewise
+signally
+significantly
+silently
+similarly
+simply
+simultaneously
+since
+sincerely
+single
+singlehandedly
+singly
+singularly
+sinuously
+six
+sixteen
+sixteenth
+sixth
+sixty
+skeptically
+skilfully
+skillfully
+sleepily
+sleeplessly
+slightly
+slimly
+sloppily
+slowly
+sluggishly
+slyly
+smartly
+smilingly
+smolderingly
+smoothly
+snobbishly
+snugly
+so
+sobbingly
+soberly
+socially
+sociologically
+soddenly
+soe
+sofar
+softly
+solely
+solemnly
+solidly
+some
+somebody
+someday
+somehow
+someone
+someplace
+somethin
+something
+sometime
+sometimes
+somewhat
+somewhere
+somewheres
+sompin
+sonuvabitch
+soon
+sooner
+soothingly
+sorely
+soulfully
+soundly
+sourly
+sparsely
+spatially
+specially
+specifically
+spectacularly
+spectrally
+speculatively
+speedily
+spiritually
+splendidly
+spontaneously
+squarely
+sssshoo
+staggeringly
+starkly
+startlingly
+statistically
+steadfastly
+steadily
+stealthily
+steamily
+steeply
+sternly
+stiffly
+stirringly
+stolidly
+stonily
+stoutly
+straightway
+strangely
+strategically
+strenuously
+strictly
+strikingly
+stringently
+strongly
+structurally
+stubbornly
+studiously
+stunningly
+stupidly
+subconsciously
+subjectively
+subsequently
+substantially
+substantively
+subtly
+successfully
+successively
+succinctly
+suddenly
+sufficiently
+suitably
+sulkily
+sullenly
+superbly
+superficially
+supinely
+supposedly
+supposing
+supra
+supremely
+surely
+surprisingly
+surreptitiously
+suspiciously
+sweepingly
+sweetly
+swiftly
+sycophantically
+symbolically
+symmetrically
+sympathetically
+synce
+syntactically
+systematically
+ta
+tacitly
+tactically
+tactually
+tangibly
+tantalizingly
+tarantara
+tardily
+tartly
+tauntingly
+tearfully
+technically
+technologically
+tediously
+telepathically
+temperately
+temporally
+temporarily
+temptingly
+ten
+tenaciously
+tenderly
+tenfold
+tensely
+tentatively
+tenth
+tenuously
+terribly
+tersely
+testily
+than
+thar
+that
+thatt
+thay
+the
+theare
+thease
+theatrically
+thee
+thees
+thei
+their
+theirs
+them
+themselves
+thence
+thenceforth
+theoretically
+ther
+there
+thereabouts
+thereafter
+thereby
+therefor
+therefore
+therefrom
+therein
+thereof
+thereon
+thereto
+theretofore
+thereunder
+thereupon
+therewith
+thermally
+thermodynamically
+these
+thet
+they
+thickly
+thine
+thinly
+third
+thirdly
+thirteen
+thirteenth
+thirtieth
+thirty
+this
+thither
+thoroughly
+those
+thou
+though
+thoughtfully
+thoughtlessly
+thousand
+thousandth
+threateningly
+three
+thrice
+through
+throughout
+thru
+thum
+thus
+thy
+tighter
+tightly
+till
+timidly
+tiredly
+tirelessly
+to
+together
+tonally
+too
+totally
+toward
+towardes
+towards
+traditionally
+tragically
+transversally
+transversely
+tremendously
+tremulously
+trillion
+triumphantly
+truly
+trustfully
+trustingly
+truthfully
+tunelessly
+twelfth
+twelve
+twentieth
+twenty
+twice
+twirlingly
+twise
+two
+typically
+u
+ugh
+uh
+uhhu
+ultimately
+ultracentrifugally
+ultrasonically
+um
+umm
+unaccountably
+unambiguously
+unanimously
+unappeasably
+unashamedly
+unavoidably
+unbearably
+unbelievably
+unblinkingly
+unceasingly
+uncertainly
+uncomfortably
+uncommonly
+uncomplainingly
+unconcernedly
+unconditionally
+unconsciously
+uncritically
+undeniably
+underfoot
+underneath
+understandably
+understandingly
+underway
+undoubtedly
+unduly
+uneasily
+unequally
+unequivocally
+unerringly
+unexpectedly
+unfailingly
+unfairly
+unfalteringly
+unfortunately
+unfunnily
+unhappily
+unhesitatingly
+unhurriedly
+uniformly
+unilaterally
+unimpeachably
+unintentionally
+uninterruptedly
+uniquely
+universally
+unknowingly
+unless
+unlike
+unluckily
+unmanageably
+unmistakably
+unnaturally
+unnecessarily
+unnnt
+unobtrusively
+unofficially
+unpleasantly
+unpredictably
+unqualifiedly
+unquestionably
+unquestioningly
+unrealistically
+unreasonably
+unreassuringly
+unreservedly
+unrestrictedly
+unselfishly
+unsmilingly
+unsteadily
+unsuccessfully
+unsuitably
+until
+unto
+unusually
+unutterably
+unwaveringly
+unwillingly
+unwisely
+unwittingly
+up
+upon
+uppermost
+uppon
+uproariously
+upside
+upstate
+upwards
+urgently
+us
+usefully
+uselessly
+usually
+utterly
+vaguely
+vainly
+valiantly
+validly
+variously
+vastly
+vehemently
+verbally
+verbatim
+verie
+versa
+versus
+vertically
+very
+via
+victoriously
+vigorously
+violently
+virtually
+visibly
+visually
+vitally
+vividly
+vocally
+vocationally
+vociferously
+volumetrically
+voluntarily
+voraciously
+warily
+warmly
+warningly
+was
+waspishly
+we
+weakly
+wearily
+wee
+weirdly
+were
+westward
+westwards
+wetly
+whad
+what
+whatever
+whatsoever
+wheare
+when
+whence
+whenever
+wher
+where
+whereas
+whereby
+whereever
+wherefore
+wherein
+whereon
+whereupon
+wherever
+wherewith
+whether
+which
+whichever
+whitely
+who
+whoe
+whoever
+wholeheartedly
+wholly
+whom
+whoosh
+whose
+whosoever
+why
+wickedly
+widely
+wil
+wildly
+wilfully
+will
+willfully
+willingly
+willy
+wilt
+wisely
+wistfully
+with
+withal
+within
+without
+wittingly
+wod
+woefully
+wold
+wolde
+wolfishly
+wonderfully
+wonderingly
+wondrously
+wordlessly
+worriedly
+would
+wow
+wrongly
+wryly
+wuh
+ya
+ye
+yea
+yeah
+yearningly
+yehhh
+yes
+yesiree
+yet
+yff
+yon
+yonder
+yooee
+you
+your
+yours
+yourself
+yourselves
+yow
+ys
+yuh
+zealously
+zero
+zoooop
+zounds
Index: /tags/greenstone-3_02-distribution/gsdl/etc/packages/phind/stopword/fr/JASIS.sw
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/etc/packages/phind/stopword/fr/JASIS.sw	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/etc/packages/phind/stopword/fr/JASIS.sw	(revision 13928)
@@ -0,0 +1,215 @@
+a
+afin
+ai
+ainsi
+aprÃšs
+attendu
+au
+aujourd
+auquel
+aussi
+autre
+autres
+aux
+auxquelles
+auxquels
+avait
+avant
+avec
+avoir
+c
+car
+ce
+ceci
+cela
+celle
+celles
+celui
+cependant
+certain
+certaine
+certaines
+certains
+ces
+cet
+cette
+ceux
+chez
+ci
+combien
+comme
+comment
+concernant
+contre
+d
+dans
+de
+debout
+dedans
+dehors
+delÃ 
+depuis
+derriÃšre
+des
+desquelles
+desquels
+dessous
+dessus
+devant
+devers
+devra
+divers
+diverse
+diverses
+doit
+donc
+dont
+du
+duquel
+durant
+dÃšs
+elle
+elles
+en
+entre
+environ
+est
+et
+etc
+etre
+eux
+exceptÃ©
+hormis
+hors
+hui
+hÃ©las
+il
+ils
+j
+je
+jusqu
+jusque
+l
+la
+laquelle
+le
+lequel
+les
+lesquelles
+lesquels
+leur
+leurs
+lorsque
+lui
+lÃ 
+ma
+mais
+malgrÃ©
+me
+merci
+mes
+mien
+mienne
+miennes
+miens
+moi
+moins
+mon
+moyennant
+mÃªme
+mÃªmes
+n
+ne
+ni
+non
+nos
+notre
+nous
+nÃ©anmoins
+nÃŽtre
+nÃŽtres
+on
+ou
+out
+outre
+oÃ¹
+par
+parmi
+partant
+pas
+passÃ©
+pendant
+plein
+plus
+plusieurs
+pour
+pourquoi
+proche
+prÃšs
+puisque
+qu
+quand
+que
+quel
+quelle
+quelles
+quels
+qui
+quoi
+quoique
+revoici
+revoilÃ 
+s
+sa
+sans
+sauf
+se
+selon
+seront
+ses
+si
+sien
+sienne
+siennes
+siens
+sinon
+soi
+soit
+son
+sont
+sous
+suivant
+sur
+ta
+te
+tes
+tien
+tienne
+tiennes
+tiens
+toi
+ton
+tous
+tout
+toute
+toutes
+tu
+un
+une
+va
+vers
+voici
+voilÃ 
+vos
+votre
+vous
+vu
+vÃŽtre
+vÃŽtres
+y
+Ã 
+Ã§a
+Ãšs
+Ã©tÃ©
+Ãªtre
+ÃŽ
Index: /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/ansi.gen
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/ansi.gen	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/ansi.gen	(revision 13928)
@@ -0,0 +1,215 @@
+# RTF ANSI character set (\ansi) general map
+# These are taken from the ISO-Latin-1 (ISO-8859-1) encodings, with
+# a few additions
+
+# Field 1 is the standard character name which the character value in
+# field 2 maps onto.  (It doesn't mean "to produce the character in field 1,
+# use the value in field 2.)
+# jrm21 - ie, given the input in field 2, what name do we use for it?
+
+# The character value may be given either as a single character (which will be
+# converted to the ASCII value of the character), or in numeric format, either
+# in decimal or 0xyy as hex yy.  Single or double quotes may be used to quote
+# characters.
+
+# characters in ASCII range (00-127)
+
+formula		0x06
+nobrkhyphen	0x1e
+opthyphen	0x1f
+
+space		" "
+exclam		!
+quotedbl	'"'
+numbersign	#
+dollar		$
+percent		%
+ampersand	&
+quoteright	"'"
+parenleft	(
+parenright	)
+asterisk	*
+plus		+
+comma		,
+hyphen		-
+period		.
+slash		/
+zero		0
+one		1
+two		2
+three		3
+four		4
+five		5
+six		6
+seven		7
+eight		8
+nine		9
+colon		:
+semicolon	;
+less		<
+equal		=
+greater		>
+question	?
+at		@
+A		A
+B		B
+C		C
+D		D
+E		E
+F		F
+G		G
+H		H
+I		I
+J		J
+K		K
+L		L
+M		M
+N		N
+O		O
+P		P
+Q		Q
+R		R
+S		S
+T		T
+U		U
+V		V
+W		W
+X		X
+Y		Y
+Z		Z
+bracketleft	[
+backslash	\
+bracketright	]
+asciicircum	^
+underscore	_
+quoteleft	"`"
+a		a
+b		b
+c		c
+d		d
+e		e
+f		f
+g		g
+h		h
+i		i
+j		j
+k		k
+l		l
+m		m
+n		n
+o		o
+p		p
+q		q
+r		r
+s		s
+t		t
+u		u
+v		v
+w		w
+x		x
+y		y
+z		z
+braceleft	{
+bar		|
+braceright	}
+asciitilde	~
+
+# non-ASCII characters (128-255)
+null		0x80
+
+nobrkspace	0xa0
+exclamdown	0xa1
+cent		0xa2
+sterling	0xa3
+currency	0xa4
+yen		0xa5
+brokenbar	0xa6
+section		0xa7
+dieresis	0xa8
+copyright	0xa9
+ordfeminine	0xaa
+guillemotleft	0xab
+logicalnot	0xac
+opthyphen	0xad
+registered	0xae
+macron		0xaf
+degree		0xb0
+plusminus	0xb1
+twosuperior	0xb2
+threesuperior	0xb3
+acute		0xb4
+mu		0xb5
+paragraph	0xb6
+periodcentered	0xb7
+cedilla		0xb8
+onesuperior	0xb9
+ordmasculine	0xba
+guillemotright	0xbb
+onequarter	0xbc
+onehalf		0xbd
+threequarters	0xbe
+questiondown	0xbf
+Agrave		0xc0
+Aacute		0xc1
+Acircumflex	0xc2
+Atilde		0xc3
+Adieresis	0xc4
+Aring		0xc5
+AE		0xc6
+Ccedilla	0xc7
+Egrave		0xc8
+Eacute		0xc9
+Ecircumflex	0xca
+Edieresis	0xcb
+Igrave		0xcc
+Iacute		0xcd
+Icircumflex	0xce
+Idieresis	0xcf
+Eth		0xd0
+Ntilde		0xd1
+Ograve		0xd2
+Oacute		0xd3
+Ocircumflex	0xd4
+Otilde		0xd5
+Odieresis	0xd6
+multiply	0xd7
+Oslash		0xd8
+Ugrave		0xd9
+Uacute		0xda
+Ucircumflex	0xdb
+Udieresis	0xdc
+Yacute		0xdd
+Thorn		0xde
+germandbls	0xdf
+agrave		0xe0
+aacute		0xe1
+acircumflex	0xe2
+atilde		0xe3
+adieresis	0xe4
+aring		0xe5
+ae		0xe6
+ccedilla	0xe7
+egrave		0xe8
+eacute		0xe9
+ecircumflex	0xea
+edieresis	0xeb
+igrave		0xec
+iacute		0xed
+icircumflex	0xee
+idieresis	0xef
+eth		0xf0
+ntilde		0xf1
+ograve		0xf2
+oacute		0xf3
+ocircumflex	0xf4
+otilde		0xf5
+odieresis	0xf6
+divide		0xf7
+oslash		0xf8
+ugrave		0xf9
+uacute		0xfa
+ucircumflex	0xfb
+udieresis	0xfc
+yacute		0xfd
+thorn		0xfe
+ydieresis	0xff
Index: /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/ansi.sym
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/ansi.sym	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/ansi.sym	(revision 13928)
@@ -0,0 +1,114 @@
+# RTF ANSI character set (\ansi) Symbol font map
+
+# Field 1 is the standard character name which the character value in
+# field 2 maps onto.  (It doesn't mean "to produce the character in field 1,
+# use the value in field 2.)
+
+# The character value may be given either as a single character (which will be
+# converted to the ASCII value of the character), or in numeric format, either
+# in decimal or 0xyy as hex yy.  Single or double quotes may be used to quote
+# characters.
+
+# characters in ASCII range (00-127)
+
+formula		0x06
+nobrkhyphen	0x1e
+opthyphen	0x1f
+
+space		" "
+exclam		!
+universal	'"'
+mathnumbersign	#
+existential	$
+percent		%
+ampersand	&
+suchthat	"'"
+parenleft	(
+parenright	)
+mathasterisk	*
+mathplus	+
+comma		,
+mathminus	-
+period		.
+slash		/
+zero		0
+one		1
+two		2
+three		3
+four		4
+five		5
+six		6
+seven		7
+eight		8
+nine		9
+colon		:
+semicolon	;
+less		<
+mathequal	=
+greater		>
+question	?
+congruent	@
+Alpha		A
+Beta		B
+Chi		C
+Delta		D
+Epsilon		E
+Phi		F
+Gamma		G
+Eta		H
+Iota		I
+# J		J
+Kappa		K
+Lambda		L
+Mu		M
+Nu		N
+Omicron		O
+Pi		P
+Theta		Q
+Rho		R
+Sigma		S
+Tau		T
+Upsilon		U
+varsigma	V
+Omega		W
+Xi		X
+Psi		Y
+Zeta		Z
+bracketleft	[
+backslash	\
+bracketright	]
+asciicircum	^
+underscore	_
+quoteleft	"`"
+alpha		a
+beta		b
+chi		c
+delta		d
+epsilon		e
+phi		f
+gamma		g
+eta		h
+iota		i
+# j		j
+kappa		k
+lambda		l
+mu		m
+nu		n
+omicron		o
+pi		p
+theta		q
+rho		r
+sigma		s
+tau		t
+upsilon		u
+# xxx		v
+omega		w
+xi		x
+psi		y
+zeta		z
+braceleft	{
+bar		|
+braceright	}
+mathtilde	~
+
+# non-ASCII characters (128-255)
Index: /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/cpg1252.gen
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/cpg1252.gen	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/cpg1252.gen	(revision 13928)
@@ -0,0 +1,244 @@
+# RTF Windows Codepage-1252 character set (\ansi) general map
+# Note (jrm21) - this is basically a modified version of the ANSI map.
+
+# Field 1 is the standard character name which the character value in
+# field 2 maps onto.  (It doesn't mean "to produce the character in field 1,
+# use the value in field 2.)
+
+# The character value may be given either as a single character (which will be
+# converted to the ASCII value of the character), or in numeric format, either
+# in decimal or 0xyy as hex yy.  Single or double quotes may be used to quote
+# characters.
+
+# printable characters in ASCII range (00-127)
+
+formula		0x06
+nobrkhyphen	0x1e
+opthyphen	0x1f
+
+space		" "	# 0x20
+exclam		!	# 0x21
+quotedbl	'"'	# 0x22
+numbersign	#	# 0x23
+dollar		$	# 0x24
+percent		%	# 0x25
+ampersand	&	# 0x26
+quoteright	"'"	# 0x27
+parenleft	(	# 0x28
+parenright	)	# 0x29
+asterisk	*	# 0x2a
+plus		+	# 0x2b
+comma		,	# 0x2c
+hyphen		-	# 0x2d
+period		.	# 0x2e
+slash		/	# 0x2f
+zero		0	# 0x30
+one		1	# 0x31
+two		2	# 0x32
+three		3	# 0x33
+four		4	# 0x34
+five		5	# 0x35
+six		6	# 0x36
+seven		7	# 0x37
+eight		8	# 0x38
+nine		9	# 0x39
+colon		:	# 0x3a
+semicolon	;	# 0x3b
+less		<	# 0x3c
+equal		=	# 0x3d
+greater		>	# 0x3e
+question	?	# 0x3f
+at		@	# 0x40
+A		A	# 0x41
+B		B	# 0x42
+C		C	# 0x43
+D		D	# 0x44
+E		E	# 0x45
+F		F	# 0x46
+G		G	# 0x47
+H		H	# 0x48
+I		I	# 0x49
+J		J	# 0x4a
+K		K	# 0x4b
+L		L	# 0x4c
+M		M	# 0x4d
+N		N	# 0x4e
+O		O	# 0x4f
+P		P	# 0x50
+Q		Q	# 0x51
+R		R	# 0x52
+S		S	# 0x53
+T		T	# 0x54
+U		U	# 0x55
+V		V	# 0x56
+W		W	# 0x57
+X		X	# 0x58
+Y		Y	# 0x59
+Z		Z	# 0x5a
+bracketleft	[	# 0x5b
+backslash	\	# 0x5c
+bracketright	]	# 0x5d
+asciicircum	^	# 0x5e
+underscore	_	# 0x5f
+quoteleft	"`"	# 0x60
+a		a	# 0x61
+b		b	# 0x62
+c		c	# 0x63
+d		d	# 0x64
+e		e	# 0x65
+f		f	# 0x66
+g		g	# 0x67
+h		h	# 0x68
+i		i	# 0x69
+j		j	# 0x6a
+k		k	# 0x6b
+l		l	# 0x6c
+m		m	# 0x6d
+n		n	# 0x6e
+o		o	# 0x6f
+p		p	# 0x70
+q		q	# 0x71
+r		r	# 0x72
+s		s	# 0x73
+t		t	# 0x74
+u		u	# 0x75
+v		v	# 0x76
+w		w	# 0x77
+x		x	# 0x78
+y		y	# 0x79
+z		z	# 0x7a
+braceleft	{	# 0x7b
+bar		|	# 0x7c
+braceright	}	# 0x7d
+asciitilde	~	# 0x7e
+# undefined (delete)	# 0x7f
+
+# non-ASCII characters (128-255)
+euro		0x80
+# undefined	0x81
+quotesinglbase	0x82 # single low-9 quotation mark
+florin		0x83 # f with hook (fnof) ## not sure if florin is right...
+quotedblbase	0x84 # double low-9 quotation mark
+ellipsis	0x85
+dagger		0x86
+daggerdbl	0x87
+circumflex	0x88 # modifier
+perthousand	0x89
+Scaron		0x8a
+guilsinglleft	0x8b
+OE		0x8c # OE ligature
+# undefined	0x8d
+Zcaron		0x8e
+# undefined	0x8f
+# undefined	0x90
+quoteleft	0x91 # single quote left - use ascii for now
+quoteright	0x92 # single quote right - use ascii for now
+quotedblleft	0x93
+quotedblright	0x94
+bullet		0x95
+endash		0x96
+emdash		0x97
+asciitilde	0x98 # use ascii tilde
+trademark	0x99
+scaron		0x9a
+guilsinglright	0x9b # single rightpointing quotemark
+oe		0x9c
+# undefined	0x9d
+zcaron		0x9e
+Ydieresis	0x9f # Y with diaeresis
+nobrkspace	0xa0
+exclamdown	0xa1
+cent		0xa2
+sterling	0xa3
+currency	0xa4
+yen		0xa5
+brokenbar	0xa6
+section		0xa7
+dieresis	0xa8
+copyright	0xa9
+ordfeminine	0xaa
+guillemotleft	0xab
+logicalnot	0xac
+opthyphen	0xad
+registered	0xae
+macron		0xaf
+degree		0xb0
+plusminus	0xb1
+twosuperior	0xb2
+threesuperior	0xb3
+acute		0xb4
+mu		0xb5
+paragraph	0xb6
+periodcentered	0xb7
+cedilla		0xb8
+onesuperior	0xb9
+ordmasculine	0xba
+guillemotright	0xbb
+onequarter	0xbc
+onehalf		0xbd
+threequarters	0xbe
+questiondown	0xbf
+Agrave		0xc0
+Aacute		0xc1
+Acircumflex	0xc2
+Atilde		0xc3
+Adieresis	0xc4
+Aring		0xc5
+AE		0xc6
+Ccedilla	0xc7
+Egrave		0xc8
+Eacute		0xc9
+Ecircumflex	0xca
+Edieresis	0xcb
+Igrave		0xcc
+Iacute		0xcd
+Icircumflex	0xce
+Idieresis	0xcf
+Eth		0xd0
+Ntilde		0xd1
+Ograve		0xd2
+Oacute		0xd3
+Ocircumflex	0xd4
+Otilde		0xd5
+Odieresis	0xd6
+multiply	0xd7
+Oslash		0xd8
+Ugrave		0xd9
+Uacute		0xda
+Ucircumflex	0xdb
+Udieresis	0xdc
+Yacute		0xdd
+Thorn		0xde
+germandbls	0xdf
+agrave		0xe0
+aacute		0xe1
+acircumflex	0xe2
+atilde		0xe3
+adieresis	0xe4
+aring		0xe5
+ae		0xe6
+ccedilla	0xe7
+egrave		0xe8
+eacute		0xe9
+ecircumflex	0xea
+edieresis	0xeb
+igrave		0xec
+iacute		0xed
+icircumflex	0xee
+idieresis	0xef
+eth		0xf0
+ntilde		0xf1
+ograve		0xf2
+oacute		0xf3
+ocircumflex	0xf4
+otilde		0xf5
+odieresis	0xf6
+divide		0xf7
+oslash		0xf8
+ugrave		0xf9
+uacute		0xfa
+ucircumflex	0xfb
+udieresis	0xfc
+yacute		0xfd
+thorn		0xfe
+ydieresis	0xff
Index: /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/cpg1252.sym
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/cpg1252.sym	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/cpg1252.sym	(revision 13928)
@@ -0,0 +1,221 @@
+# RTF ANSI character set (\ansi) general map
+# These are taken from the ISO-Latin-1 (ISO-8859-1) encodings, with
+# a few additions
+
+# Field 1 is the standard character name which the character value in
+# field 2 maps onto.  (It doesn't mean "to produce the character in field 1,
+# use the value in field 2.)
+
+# The character value may be given either as a single character (which will be
+# converted to the ASCII value of the character), or in numeric format, either
+# in decimal or 0xyy as hex yy.  Single or double quotes may be used to quote
+# characters.
+
+# jrm21 - the character name is used when outputting a particular character
+# code. This name is then looked up in the *-gen file to see what to output
+# for that symbol name. It's a bit round-about...
+
+# characters in ASCII range (00-127)
+
+formula		0x06
+nobrkhyphen	0x1e
+opthyphen	0x1f
+
+space		" "
+exclam		!
+quotedbl	'"'
+numbersign	#
+dollar		$
+percent		%
+ampersand	&
+quoteright	"'"
+parenleft	(
+parenright	)
+asterisk	*
+plus		+
+comma		,
+hyphen		-
+period		.
+slash		/
+zero		0
+one		1
+two		2
+three		3
+four		4
+five		5
+six		6
+seven		7
+eight		8
+nine		9
+colon		:
+semicolon	;
+less		<
+equal		=
+greater		>
+question	?
+at		@
+A		A
+B		B
+C		C
+D		D
+E		E
+F		F
+G		G
+H		H
+I		I
+J		J
+K		K
+L		L
+M		M
+N		N
+O		O
+P		P
+Q		Q
+R		R
+S		S
+T		T
+U		U
+V		V
+W		W
+X		X
+Y		Y
+Z		Z
+bracketleft	[
+backslash	\
+bracketright	]
+asciicircum	^
+underscore	_
+quoteleft	"`"
+a		a
+b		b
+c		c
+d		d
+e		e
+f		f
+g		g
+h		h
+i		i
+j		j
+k		k
+l		l
+m		m
+n		n
+o		o
+p		p
+q		q
+r		r
+s		s
+t		t
+u		u
+v		v
+w		w
+x		x
+y		y
+z		z
+braceleft	{
+bar		|
+braceright	}
+asciitilde	~
+
+# non-ASCII characters (128-255)
+#ellipsis		0x85
+#dagger		0x86
+#daggerdbl	0x87
+
+nobrkspace	0xa0
+exclamdown	0xa1
+cent		0xa2
+sterling	0xa3
+currency	0xa4
+yen		0xa5
+brokenbar	0xa6
+section		0xa7
+dieresis	0xa8
+copyright	0xa9
+ordfeminine	0xaa
+guillemotleft	0xab
+logicalnot	0xac
+opthyphen	0xad
+registered	0xae
+macron		0xaf
+degree		0xb0
+plusminus	0xb1
+twosuperior	0xb2
+threesuperior	0xb3
+acute		0xb4
+mu		0xb5
+paragraph	0xb6
+periodcentered	0xb7
+#asterisk	0xb7
+cedilla		0xb8
+onesuperior	0xb9
+ordmasculine	0xba
+guillemotright	0xbb
+onequarter	0xbc
+onehalf		0xbd
+threequarters	0xbe
+questiondown	0xbf
+Agrave		0xc0
+Aacute		0xc1
+Acircumflex	0xc2
+Atilde		0xc3
+Adieresis	0xc4
+Aring		0xc5
+AE		0xc6
+Ccedilla	0xc7
+Egrave		0xc8
+Eacute		0xc9
+Ecircumflex	0xca
+Edieresis	0xcb
+Igrave		0xcc
+Iacute		0xcd
+Icircumflex	0xce
+Idieresis	0xcf
+Eth		0xd0
+Ntilde		0xd1
+Ograve		0xd2
+Oacute		0xd3
+Ocircumflex	0xd4
+Otilde		0xd5
+Odieresis	0xd6
+multiply	0xd7
+Oslash		0xd8
+Ugrave		0xd9
+Uacute		0xda
+Ucircumflex	0xdb
+Udieresis	0xdc
+Yacute		0xdd
+Thorn		0xde
+germandbls	0xdf
+agrave		0xe0
+aacute		0xe1
+acircumflex	0xe2
+atilde		0xe3
+adieresis	0xe4
+aring		0xe5
+ae		0xe6
+ccedilla	0xe7
+egrave		0xe8
+eacute		0xe9
+ecircumflex	0xea
+edieresis	0xeb
+igrave		0xec
+iacute		0xed
+icircumflex	0xee
+idieresis	0xef
+eth		0xf0
+ntilde		0xf1
+ograve		0xf2
+oacute		0xf3
+ocircumflex	0xf4
+otilde		0xf5
+odieresis	0xf6
+divide		0xf7
+oslash		0xf8
+ugrave		0xf9
+uacute		0xfa
+ucircumflex	0xfb
+udieresis	0xfc
+yacute		0xfd
+thorn		0xfe
+ydieresis	0xff
Index: /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/html-map
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/html-map	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/html-map	(revision 13928)
@@ -0,0 +1,265 @@
+# Output sequence map for rtftohtml
+
+# Field 1 is the standard character name.  Field 2 is the output sequence
+# to produce for that character.
+
+# The output sequence is simply a string of characters.  If it contains
+# whitespace, it may be quoted.  If it contains quotes, it may be quoted
+# with a different quote character.
+
+null		''
+# characters in ASCII range (32-127)
+
+space		" "
+exclam		!
+quotedbl	'"'
+numbersign	#
+dollar		$
+percent		%
+ampersand	&amp;
+quoteright	"'"
+parenleft	(
+parenright	)
+asterisk	*
+plus		+
+comma		,
+hyphen		-
+period		.
+slash		/
+zero		0
+one		1
+onesuperior	&sup1;
+two		2
+twosuperior	&sup2;
+three		3
+threesuperior	&sup3;
+four		4
+five		5
+six		6
+seven		7
+eight		8
+nine		9
+colon		:
+semicolon	;
+less		&lt;
+equal		=
+greater		&gt;
+question	?
+at		@
+A		A
+B		B
+C		C
+D		D
+E		E
+F		F
+G		G
+H		H
+I		I
+J		J
+K		K
+L		L
+M		M
+N		N
+O		O
+P		P
+Q		Q
+R		R
+S		S
+T		T
+U		U
+V		V
+W		W
+X		X
+Y		Y
+Z		Z
+bracketleft	[
+backslash	\
+bracketright	]
+asciicircum	^
+underscore	_
+quoteleft	"`"
+a		a
+b		b
+c		c
+d		d
+e		e
+f		f
+g		g
+h		h
+i		i
+j		j
+k		k
+l		l
+m		m
+n		n
+o		o
+p		p
+q		q
+r		r
+s		s
+t		t
+u		u
+v		v
+w		w
+x		x
+y		y
+z		z
+braceleft	{
+bar		|
+braceright	}
+asciitilde	~
+
+# non-ASCII
+# use HTML 4.0 entity names where practical
+# starting at decimal code 160
+nobrkspace	&nbsp;
+# inverted exclamation mark 161
+cent		&cent;
+sterling	&pound;
+currency	&curren;
+yen		&yen;
+#netscape will only do this in utf-8: brokenbar	&brvbar;
+brokenbar	|
+section		&sect;
+# uml / diaeresis = 168
+copyright	&copy;
+copyrightsans	&copy;
+
+
+# Latin Extended-A
+OE		&OElig;
+oe		&oelig;
+Scaron		&Scaron;
+scaron		&scaron;
+Ydieresis	&Yuml;
+
+acute		"'"
+angleleft	[
+angleright	&gt;
+approxequal	~
+arrowboth	&lt;-&gt;
+arrowdblboth	&lt;=&gt;
+arrowdblleft	&lt;=
+arrowdblright	=&gt;
+arrowleft	&lt;-
+arrowright	-&gt;
+#bullet		*
+bullet		&middot;
+circumflex	^
+# next 2 have named entities, which netscape 4 doesn't use...
+# unicode &#8224; and &#8225;
+dagger		&#134;
+daggerdbl	&#135;
+
+degree		&deg;
+delta		d
+divide		&divide;
+dotlessi	i
+ellipsis	...
+# next 2 have named entities, which netscape 4 doesn't use...
+endash		&#150;
+emdash		&#151;
+euro		&euro;
+fi		fi
+fl		fl
+fraction	/
+grave		"`"
+greaterequal	&gt;=
+# &#171; # was &lt;&lt;
+guillemotleft	&laquo;
+# &#187; # was &gt;&gt;
+guillemotright	&raquo;
+# netscape 4.7 doesn't do this? - unicode: &#2039; or &lsaquo;
+guilsinglleft	&lt;
+# ditto? unicode: &#203A; or &rsaquo;
+guilsinglright	&gt;
+lessequal	&lt;=
+logicalnot	&not;
+mathasterisk	*
+mathequal	=
+mathminus	-
+mathnumbersign	'#'
+mathplus	+
+mathtilde	~
+minus		-
+mu		&micro;
+multiply	&times;
+nobrkhyphen	-
+
+notequal	!=
+onehalf		&frac12;
+onequarter	&frac14;
+periodcentered	&middot;
+plusminus	&plusmn;
+quotedblbase	,,
+quotedblleft	'"'
+quotedblright	'"'
+quotesinglbase	,
+registered	&reg;
+registersans	&reg;
+threequarters	&frac34;
+tilde		~
+trademark	&trade;
+AE		&AElig;
+Aacute      &Aacute;
+Acircumflex &Acirc;
+Agrave      &Agrave;
+Aring       &Aring;
+Atilde		&Atilde;
+Adieresis	&Auml;
+Ccedilla	&Ccedil;
+#ETH		&ETH;
+Eacute	&Eacute;
+Ecircumflex	&Ecirc;
+Egrave	&Egrave;
+Edieresis	&Euml;
+Iacute	&Iacute;
+Icircumflex	&Icirc;
+Igrave	&Igrave;
+Idieresis	&Iuml;
+Ntilde	&Ntilde;
+Oacute	&Oacute;
+Ocircumflex	&Ocirc;
+Ograve	&Ograve;
+Oslash	&Oslash;
+#Otilde	&Otilde;
+Odieresis	&Ouml;
+#THORN	&THORN;
+Uacute	&Uacute;
+Ucircumflex	&Ucirc;
+Ugrave	&Ugrave;
+Udieresis	&Uuml;
+#Yacute	&Yacute;
+ae		&aelig;
+aacute	&aacute;
+acircumflex	&acirc;
+agrave	&agrave;
+aring	&aring;
+atilde	&atilde;
+adieresis	&auml;
+ccedilla	&ccedil;
+eacute	&eacute;
+ecircumflex	&ecirc;
+egrave	&egrave;
+#eth	&eth;
+edieresis	&euml;
+iacute	&iacute;
+icircumflex	&icirc;
+igrave	&igrave;
+idieresis	&iuml;
+ntilde	&ntilde;
+oacute	&oacute;
+ocircumflex	&ocirc;
+ograve	&ograve;
+oslash	&oslash;
+otilde	&otilde;
+odieresis	&ouml;
+germandbls	&szlig;
+#thorn	&thorn;
+uacute	&uacute;
+ucircumflex	&ucirc;
+ugrave	&ugrave;
+udieresis	&uuml;
+yacute	&yacute;
+ydieresis	&yuml;
+newline	<br>
Index: /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/html-trn
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/html-trn	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/html-trn	(revision 13928)
@@ -0,0 +1,214 @@
+# Starting with rtftohtml 2.7, all html-trans files have a version number
+# The version number must appear before any other tables.
+.Version,3
+
+# Paragraph Style Tags table
+# Format:
+#"name","starttag","endtag","col2mark","tabmark","parmark",allowtext,cannest,DeleteCol1,fold,TocStyl
+.PTag
+"Normal","","\n","\t","\t","<p>\n",1,0,0,1,0
+"h1","<h1>\n","</h1>\n","\t","\t","<br>\n",0,0,0,1,1
+"h2","<h2>\n","</h2>\n","\t","\t","<br>\n",0,0,0,1,2
+"h3","<h3>\n","</h3>\n","\t","\t","<br>\n",0,0,0,1,3
+"h4","<h4>\n","</h4>\n","\t","\t","<br>\n",0,0,0,1,4
+"h5","<h5>\n","</h5>\n","\t","\t","<br>\n",0,0,0,1,5
+"h6","<h6>\n","</h6>\n","\t","\t","<br>\n",0,0,0,1,6
+"ul","<ul>\n<li>","</ul>","\t","\t","\n<li>",1,1,0,1,0
+"ul-d","<ul>\n<li>","</ul>","\t","\t","\n<li>",1,1,1,1,0
+"ol","<ol>\n<li>","</ol>","\t","\t","\n<li>",1,1,0,1,0
+"ol-d","<ol>\n<li>","</ol>","\t","\t","\n<li>",1,1,1,1,0
+"dl","<dl>\n<dt>","</dl>","\n<dd>","\t","\n<dt>",1,1,0,1,0
+"TERM","<dl>\n<dt>","</dl>","\t","\t","\n<dt>",1,1,0,1,0
+"DEF","<dd>","","\t","\t","\n<br>",1,1,0,1,0
+"dir","<dir>\n<li>","</dir>","\n<li>","\n<li>","\n<li>",0,1,0,1,0
+"menu","<menu>\n<li>","</menu>\n","\n<li>","\n<li>","\n<li>",0,1,0,1,0
+"address","<address>","</address>\n","\t","\t","<br>\n",1,0,0,1,0
+"pre","\n<pre>\n","\n</pre>\n","\t","\t","\n",0,0,0,0,0
+"blockquote","<blockquote>","</blockquote>","\t","\t","\n",1,0,0,1,0
+"hr","<hr>","","","","",1,0,0,1,0
+# This is a required entry; tables will be formatted with this entry
+"_Table","\n<pre>\n","\n</pre>\n","\t","\t","\n",0,0,0,0,0
+
+# Text STyle Tags table
+# Format
+# "name","Starttag","Endtag"
+.TTag
+"b","<b>","</b>"
+"i","<i>","</i>"
+"u","<u>","</u>"
+"em","<em>","</em>"
+"cite","<cite>","</cite>"
+"tt","<tt>","</tt>"
+"strong","<strong>","</strong>"
+"code","<code>","</code>"
+"samp","<samp>","</samp>"
+"kbd","<kbd>","</kbd>"
+"var","<var>","</var>"
+"dfn","<dfn>","</dfn>"
+"sup","<sup>","</sup>"
+
+# Text Match Table
+# Format:
+# "Font",FontSize,Match,Mask,"TextStyleName"
+# "" is don't care for fonts
+# 0 is don't care for font size
+# Special names for TextStyleName
+# _Discard - text will not be output
+# _Name    - text will be used for an named anchor
+# _HRef    - text is an href
+# _Hot     - end of this text marks the end of hot text
+# _Literal - text is sent thorough without any translation
+# The order of bits for match and mask is:
+#    v^bDWUHACSOTIB - Bold
+#    v^bDWUHACSOTI - Italic
+#    v^bDWUHACSOT - StrikeThrough
+#    v^bDWUHACSO - Outline
+#    v^bDWUHACS - Shadow
+#    v^bDWUHAC - SmallCaps
+#    v^bDWUHA - AllCaps
+#    v^bDWUH - Hidden
+#    v^bDWU - Underline
+#    v^bDW - Word Underline
+#    v^bD - Dotted Underline
+#    v^b - Double Underline
+#    v^ - SuperScript
+#    v - SubScript
+#    v^bDWUIACSOTIB
+.TMatch
+#
+# First do specials, because they are higher priority than other matches
+# 
+# double-underline/not hidden -> hot text
+# double-underline/hidden -> href
+#    v^bDWUHACSOTIB,v^bDWUHACSOTIB
+"",0,00100000000000,00100010000000,"_Hot"
+"",0,00100010000000,00100010000000,"_HRef"
+
+# hidden/shadow -> literal
+#    v^bDWUHACSOTIB,v^bDWUHACSOTIB
+"",0,00000010010000,00000010010000,"_Literal"
+
+# hidden/outline -> Name
+#    v^bDWUHACSOTIB,v^bDWUHACSOTIB
+"",0,00000010001000,00000010001000,"_Name"
+
+# hidden/all other hiddens are discarded
+"",0,00000010000000,00000010000000,"_Discard"
+
+# All other Superscripts just superscripts
+#    v^bDWUHACSOTIB,v^bDWUHACSOTIB
+"",0,01000000000000,01000000000000,"sup"
+
+# Regular matches - You can have multiple of these active
+
+# monospace fonts -> tt
+"Courier",0,00000000000000,00000000000000,"tt"
+"Monoco",0,00000000000000,00000000000000,"tt"
+
+# bold -> bold
+#    v^bDWUHACSOTIB,v^bDWUHACSOTIB
+"",0,00000000000001,00000000000001,"b"
+
+# italic/underline -> cite, italic/nounderline -> italic
+#    v^bDWUHACSOTIB,v^bDWUHACSOTIB
+"",0,00000000000010,00000100000010,"i"
+"",0,00000100000010,00000100000010,"cite"
+
+# any underline without italic -> underline
+#    v^bDWUHACSOTIB,v^bDWUHACSOTIB
+"",0,00010000000000,00111100000010,"u"
+"",0,00001000000000,00111100000010,"u"
+"",0,00000100000000,00111100000010,"u"
+"",0,00100000000000,00111100000010,"u"
+
+# outline,shadow -> em
+#    v^bDWUHACSOTIB,v^bDWUHACSOTIB
+"",0,00000000001000,00000000001000,"em"
+"",0,00000000010000,00000000010000,"em"
+
+
+# Format:
+# "Paragraph Style",NestLevel,"ParagraphStyleName"
+# First Entry is the default if no style match. Should be level 0 
+# point to a Paragraph style with no markup
+.PMatch
+"Normal",0,"Normal"
+# This is a required entry; tables will be formatted with this entry
+"_Table",0,"_Table"
+"heading 1",0,"h1"
+"heading 2",0,"h2"
+"heading 3",0,"h3"
+"heading 4",0,"h4"
+"heading 5",0,"h5"
+"heading 6",0,"h6"
+"ol",0,"ol"
+"ol 1",1,"ol"
+"ol 2",2,"ol"
+"ol 3",3,"ol"
+"ol 4",4,"ol"
+"ol 5",5,"ol"
+"ul",0,"ul"
+"ul 1",1,"ul"
+"ul 2",2,"ul"
+"ul 3",3,"ul"
+"ul 4",4,"ul"
+"ul 5",5,"ul"
+"numbered list",0,"ol-d"
+"numbered list 1",1,"ol-d"
+"numbered list 2",2,"ol-d"
+"numbered list 3",3,"ol-d"
+"numbered list 4",4,"ol-d"
+"numbered list 5",5,"ol-d"
+"bullet list",0,"ul-d"
+"bullet list 1",1,"ul-d"
+"bullet list 2",2,"ul-d"
+"bullet list 3",3,"ul-d"
+"bullet list 4",4,"ul-d"
+"bullet list 5",5,"ul-d"
+"dir",0,"dir"
+"dir 1",1,"dir"
+"dir 2",2,"dir"
+"dir 3",3,"dir"
+"dir 4",4,"dir"
+"dir 5",5,"dir"
+"small gloss",0,"dl"
+"small gloss 1",1,"dl"
+"small gloss 2",2,"dl"
+"small gloss 3",3,"dl"
+"small gloss 4",4,"dl"
+"small gloss 5",5,"dl"
+"glossary",0,"dl"
+"glossary 1",1,"dl"
+"glossary 2",2,"dl"
+"glossary 3",3,"dl"
+"glossary 4",4,"dl"
+"glossary 5",5,"dl"
+"menu",0,"menu"
+"menu 1",1,"menu"
+"menu 2",2,"menu"
+"menu 3",3,"menu"
+"menu 4",4,"menu"
+"menu 5",5,"menu"
+"pre",0,"pre"
+"blockquote",0,"blockquote"
+"address",0,"address"
+"hr",0,"hr"
+# the following paragraph styles will be discarded
+"toc 1",0,"_Discard"
+"toc 2",0,"_Discard"
+"toc 3",0,"_Discard"
+"toc 4",0,"_Discard"
+"toc 5",0,"_Discard"
+"index 1",0,"_Discard"
+"index 2",0,"_Discard"
+"index 3",0,"_Discard"
+"index 4",0,"_Discard"
+"index 5",0,"_Discard"
+"TERM",0,"TERM"
+"DEF",1,"DEF"
+"TERM 1",1,"TERM"
+"DEF 1",2,"DEF"
+"TERM 2",2,"TERM"
+"DEF 2",3,"DEF"
+"HTML",0,"_Literal"
+"footnote text",0,"Normal"
Index: /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/mac.gen
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/mac.gen	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/mac.gen	(revision 13928)
@@ -0,0 +1,243 @@
+# RTF Macintosh character set (\mac) general map
+
+# Field 1 is the standard character name which the character value in
+# field 2 maps onto.  (It doesn't mean "to produce the character in field 1,
+# use the value in field 2.)
+
+# The character value may be given either as a single character (which will be
+# converted to the ASCII value of the character), or in numeric format, either
+# in decimal or 0xyy as hex yy.  Single or double quotes may be used to quote
+# characters.
+
+# characters in ASCII range (00-127)
+
+formula		0x06
+nobrkhyphen	0x1e
+opthyphen	0x1f
+
+space		" "
+exclam		!
+quotedbl	'"'
+numbersign	#
+dollar		$
+percent		%
+ampersand	&
+quoteright	"'"
+parenleft	(
+parenright	)
+asterisk	*
+plus		+
+comma		,
+hyphen		-
+period		.
+slash		/
+zero		0
+one		1
+two		2
+three		3
+four		4
+five		5
+six		6
+seven		7
+eight		8
+nine		9
+colon		:
+semicolon	;
+less		<
+equal		=
+greater		>
+question	?
+at		@
+A		A
+B		B
+C		C
+D		D
+E		E
+F		F
+G		G
+H		H
+I		I
+J		J
+K		K
+L		L
+M		M
+N		N
+O		O
+P		P
+Q		Q
+R		R
+S		S
+T		T
+U		U
+V		V
+W		W
+X		X
+Y		Y
+Z		Z
+bracketleft	[
+backslash	\
+bracketright	]
+asciicircum	^
+underscore	_
+quoteleft	"`"
+a		a
+b		b
+c		c
+d		d
+e		e
+f		f
+g		g
+h		h
+i		i
+j		j
+k		k
+l		l
+m		m
+n		n
+o		o
+p		p
+q		q
+r		r
+s		s
+t		t
+u		u
+v		v
+w		w
+x		x
+y		y
+z		z
+braceleft	{
+bar		|
+braceright	}
+asciitilde	~
+
+# non-ASCII characters (128-255)
+
+# ?? Ygrave		0x07
+# ?? yacute		0x08
+Adieresis	0x80
+Aring		0x81
+Ccedilla	0x82
+Eacute		0x83
+Ntilde		0x84
+Odieresis	0x85
+Udieresis	0x86
+aacute		0x87
+agrave		0x88
+acircumflex	0x89
+adieresis	0x8a
+atilde		0x8b
+aring		0x8c
+ccedilla	0x8d
+eacute		0x8e
+egrave		0x8f
+ecircumflex	0x90
+edieresis	0x91
+iacute		0x92
+igrave		0x93
+icircumflex	0x94
+idieresis	0x95
+ntilde		0x96
+oacute		0x97
+ograve		0x98
+ocircumflex	0x99
+odieresis	0x9a
+otilde		0x9b
+uacute		0x9c
+ugrave		0x9d
+ucircumflex	0x9e
+udieresis	0x9f
+dagger		0xa0
+degree		0xa1
+cent		0xa2
+sterling	0xa3
+section		0xa4
+bullet		0xa5
+paragraph	0xa6
+germandbls	0xa7
+registered	0xa8
+copyright	0xa9
+trademark	0xaa
+acute		0xab
+dieresis	0xac
+notequal	0xad
+AE		0xae
+Oslash		0xaf
+infinity	0xb0
+plusminus	0xb1
+lessequal	0xb2
+greaterequal	0xb3
+yen		0xb4
+mu		0xb5
+partialdiff	0xb6
+Sigma		0xb7
+Pi		0xb8
+pi		0xb9
+integral	0xba
+ordfeminine	0xbb
+ordmasculine	0xbc
+Omega		0xbd
+ae		0xbe
+oslash		0xbf
+questiondown	0xc0
+exclamdown	0xc1
+logicalnot	0xc2
+radical		0xc3
+florin		0xc4
+approxequal	0xc5
+Delta		0xc6
+guillemotleft	0xc7
+guillemotright	0xc8
+ellipsis	0xc9
+nobrkspace	0xca
+Agrave		0xcb
+OE		0xce
+oe		0xcf
+endash		0xd0
+emdash		0xd1
+quotedblleft	0xd2
+quotedblright	0xd3
+quoteleft	0xd4
+quoteright	0xd5
+divide		0xd6
+lozenge		0xd7
+ydieresis	0xd8
+Ydieresis	0xd9
+fraction	0xda
+currency	0xdb
+guilsinglleft	0xdc
+guilsinglright	0xdd
+fi		0xde
+fl		0xdf
+daggerdbl	0xe0
+periodcentered	0xe1
+quotesinglbase	0xe2
+quotedblbase	0xe3
+perthousand	0xe4
+Acircumflex	0xe5
+Ecircumflex	0xe6
+Aacute		0xe7
+Edieresis	0xe8
+Egrave		0xe9
+Iacute		0xea
+Icircumflex	0xeb
+Idieresis	0xec
+Igrave		0xed
+Oacute		0xee
+Ocircumflex	0xef
+apple		0xf0
+Ograve		0xf1
+Uacute		0xf2
+Ucircumflex	0xf3
+Ugrave		0xf4
+dotlessi	0xf5
+circumflex	0xf6
+tilde		0xf7
+macron		0xf8
+breve		0xf9
+dotaccent	0xfa
+ring		0xfb
+cedilla		0xfc
+hungarumlaut	0xfd
+ogonek		0xfe
+caron		0xff
Index: /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/mac.sym
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/mac.sym	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/mac.sym	(revision 13928)
@@ -0,0 +1,241 @@
+# RTF Macintosh character set (\mac) Symbol font map
+
+# Field 1 is the standard character name which the character value in
+# field 2 maps onto.  (It doesn't mean "to produce the character in field 1,
+# use the value in field 2.)
+
+# The character value may be given either as a single character (which will be
+# converted to the ASCII value of the character), or in numeric format, either
+# in decimal or 0xyy as hex yy.  Single or double quotes may be used to quote
+# characters.
+
+# characters in ASCII range (00-127)
+
+formula		0x06
+nobrkhyphen	0x1e
+opthyphen	0x1f
+
+space		" "
+exclam		!
+universal	'"'
+mathnumbersign	#
+existential	$
+percent		%
+ampersand	&
+suchthat	"'"
+parenleft	(
+parenright	)
+mathasterisk	*
+mathplus	+
+comma		,
+mathminus	-
+period		.
+slash		/
+zero		0
+one		1
+two		2
+three		3
+four		4
+five		5
+six		6
+seven		7
+eight		8
+nine		9
+colon		:
+semicolon	;
+less		<
+mathequal	=
+greater		>
+question	?
+congruent	@
+Alpha		A
+Beta		B
+Chi		C
+Delta		D
+Epsilon		E
+Phi		F
+Gamma		G
+Eta		H
+Iota		I
+# J		J
+Kappa		K
+Lambda		L
+Mu		M
+Nu		N
+Omicron		O
+Pi		P
+Theta		Q
+Rho		R
+Sigma		S
+Tau		T
+Upsilon		U
+varsigma	V
+Omega		W
+Xi		X
+Psi		Y
+Zeta		Z
+bracketleft	[
+backslash	\
+bracketright	]
+asciicircum	^
+underscore	_
+quoteleft	"`"
+alpha		a
+beta		b
+chi		c
+delta		d
+epsilon		e
+phi		f
+gamma		g
+eta		h
+iota		i
+# j		j
+kappa		k
+lambda		l
+mu		m
+nu		n
+omicron		o
+pi		p
+theta		q
+rho		r
+sigma		s
+tau		t
+upsilon		u
+# xxx		v
+omega		w
+xi		x
+psi		y
+zeta		z
+braceleft	{
+bar		|
+braceright	}
+mathtilde	~
+
+# non-ASCII characters (128-255)
+
+# Adieresis	0x80
+# Aring		0x81
+# Ccedilla	0x82
+# Eacute	0x83
+# Ntilde	0x84
+# Odieresis	0x85
+# Udieresis	0x86
+# aacute	0x87
+# agrave	0x88
+# acircumflex	0x89
+# adieresis	0x8a
+# atilde	0x8b
+# aring		0x8c
+# ccedilla	0x8d
+# eacute	0x8e
+# egrave	0x8f
+# ecircumflex	0x90
+# edieresis	0x91
+# iacute	0x92
+# igrave	0x93
+# icircumflex	0x94
+# idieresis	0x95
+# ntilde	0x96
+# oacute	0x97
+# ograve	0x98
+# ocircumflex	0x99
+# odieresis	0x9a
+# otilde	0x9b
+# uacute	0x9c
+# ugrave	0x9d
+# ucircumflex	0x9e
+# udieresis	0x9f
+# dagger	0xa0
+# degree	0xa1
+minute		0xa2
+lessequal	0xa3
+fraction	0xa4
+infinity	0xa5
+florin		0xa6
+club		0xa7
+diamond		0xa8
+heart		0xa9
+spade		0xaa
+arrowboth	0xab
+arrowleft	0xac
+arrowup		0xad
+arrowright	0xae
+arrowdown	0xaf
+degree		0xb0
+plusminus	0xb1
+second		0xb2
+greaterequal	0xb3
+multiply	0xb4
+proportional	0xb5
+partialdiff	0xb6
+bullet		0xb7
+divide		0xb8
+notequal	0xb9
+equivalence	0xba
+approxequal	0xbb
+ellipsis	0xbc
+arrowvertex	0xbd
+arrowhorizex	0xbe
+carriagereturn	0xbf
+aleph		0xc0
+Ifraktur	0xc1
+Rfraktur	0xc2
+weierstrass	0xc3
+circlemultiply	0xc4
+circleplus	0xc5
+emptyset	0xc6
+intersection	0xc7
+union		0xc8
+propersuperset	0xc9
+reflexsuperset	0xca
+notsubset	0xcb
+propersubset	0xce
+reflexsubset	0xcf
+angle		0xd0
+gradient	0xd1
+registered	0xd2
+copyright	0xd3
+trademark	0xd4
+product		0xd5
+radical		0xd6
+periodcentered	0xd7
+logicalnot	0xd8
+logicaland	0xd9
+logicalor	0xda
+arrowdblboth	0xdb
+arrowdblleft	0xdc
+arrowdblup	0xdd
+arrowdblright	0xde
+arrowdbldown	0xdf
+lozenge		0xe0
+angleleft	0xe1
+registersans	0xe2
+copyrightsans	0xe3
+trademarksans	0xe4
+Sigma		0xe5
+# Ecircumflex	0xe6
+# Aacute	0xe7
+# Edieresis	0xe8
+# Egrave	0xe9
+# Iacute	0xea
+# Icircumflex	0xeb
+# Idieresis	0xec
+# Igrave	0xed
+# Oacute	0xee
+# Ocircumflex	0xef
+apple		0xf0
+angleright	0xf1
+# Uacute	0xf2
+# Ucircumflex	0xf3
+# Ugrave	0xf4
+# dotlessi	0xf5
+# circumflex	0xf6
+# tilde		0xf7
+# macron	0xf8
+# breve		0xf9
+# dotaccent	0xfa
+# ring		0xfb
+# cedilla	0xfc
+# hungarumlaut	0xfd
+# ogonek	0xfe
+# caron		0xff
Index: /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/pc.gen
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/pc.gen	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/pc.gen	(revision 13928)
@@ -0,0 +1,243 @@
+# RTF PC character set (\pc) general map
+
+# Field 1 is the standard character name which the character value in
+# field 2 maps onto.  (It doesn't mean "to produce the character in field 1,
+# use the value in field 2.)
+
+# The character value may be given either as a single character (which will be
+# converted to the ASCII value of the character), or in numeric format, either
+# in decimal or 0xyy as hex yy.  Single or double quotes may be used to quote
+# characters.
+
+# characters in ASCII range (32-127)
+
+formula		0x06
+nobrkhyphen	0x1e
+opthyphen	0x1f
+
+space		" "
+exclam		!
+quotedbl	'"'
+numbersign	#
+dollar		$
+percent		%
+ampersand	&
+quoteright	"'"
+parenleft	(
+parenright	)
+asterisk	*
+plus		+
+comma		,
+hyphen		-
+period		.
+slash		/
+zero		0
+one		1
+two		2
+three		3
+four		4
+five		5
+six		6
+seven		7
+eight		8
+nine		9
+colon		:
+semicolon	;
+less		<
+equal		=
+greater		>
+question	?
+at		@
+A		A
+B		B
+C		C
+D		D
+E		E
+F		F
+G		G
+H		H
+I		I
+J		J
+K		K
+L		L
+M		M
+N		N
+O		O
+P		P
+Q		Q
+R		R
+S		S
+T		T
+U		U
+V		V
+W		W
+X		X
+Y		Y
+Z		Z
+bracketleft	[
+backslash	\
+bracketright	]
+asciicircum	^
+underscore	_
+quoteleft	"`"
+a		a
+b		b
+c		c
+d		d
+e		e
+f		f
+g		g
+h		h
+i		i
+j		j
+k		k
+l		l
+m		m
+n		n
+o		o
+p		p
+q		q
+r		r
+s		s
+t		t
+u		u
+v		v
+w		w
+x		x
+y		y
+z		z
+braceleft	{
+bar		|
+braceright	}
+asciitilde	~
+
+# non-ASCII characters (128-255)
+
+Ccedilla	0x80
+udieresis	0x81
+eacute		0x82
+acircumflex	0x83
+adieresis	0x84
+agrave		0x85
+aring		0x86
+ccedilla	0x87
+ecircumflex	0x88
+edieresis	0x89
+egrave		0x8a
+idieresis	0x8b
+icircumflex	0x8c
+igrave		0x8d
+Adieresis	0x8e
+Aring		0x8f
+Eacute		0x90
+ae		0x91
+AE		0x92
+ocircumflex	0x93
+odieresis	0x94
+ograve		0x95
+ucircumflex	0x96
+ugrave		0x97
+ydieresis	0x98
+Odieresis	0x99
+Udieresis	0x9a
+cent		0x9b
+sterling	0x9c
+yen		0x9d
+ucircumflex	0x9e
+florin		0x9f
+aacute		0xa0
+iacute		0xa1
+oacute		0xa2
+uacute		0xa3
+ntilde		0xa4
+Ntilde		0xa5
+ordfeminine	0xa6
+ordmasculine	0xa7
+questiondown	0xa8
+copyright	0xa9
+trademark	0xaa
+acute		0xab
+dieresis	0xac
+exclamdown	0xad
+guillemotleft	0xae
+guillemotright	0xaf
+space		0xb0
+plusminus	0xb1
+lessequal	0xb2
+bar		0xb3
+yen		0xb4
+mu		0xb5
+partialdiff	0xb6
+Sigma		0xb7
+Pi		0xb8
+pi		0xb9
+integral	0xba
+ordfeminine	0xbb
+ordmasculine	0xbc
+Omega		0xbd
+ae		0xbe
+logicalnot	0xbf
+questiondown	0xc0
+exclamdown	0xc1
+logicalnot	0xc2
+radical		0xc3
+emdash		0xc4
+approxequal	0xc5
+delta		0xc6
+guillemotleft	0xc7
+guillemotright	0xc8
+ellipsis	0xc9
+nobrkspace	0xca
+Agrave		0xcb
+Atilde		0xcc
+Otilde		0xcd
+OE		0xce
+oe		0xcf
+endash		0xd0
+emdash		0xd1
+quotedblleft	0xd2
+quotedblright	0xd3
+quoteleft	0xd4
+quoteright	0xd5
+divide		0xd6
+lozenge		0xd7
+ydieresis	0xd8
+Ydieresis	0xd9
+fraction	0xda
+Ydieresis	0xdb
+guilsinglleft	0xdc
+greater		0xdd
+less		0xde
+fl		0xdf
+a		0xe0
+germandbls	0xe1
+quotesinglbase	0xe2
+pi		0xe3
+Sigma		0xe4
+Acircumflex	0xe5
+mu		0xe6
+Aacute		0xe7
+Edieresis	0xe8
+Egrave		0xe9
+Omega		0xea
+partialdiff	0xeb
+infinity	0xec
+oslash		0xed
+e		0xee
+Ocircumflex	0xef
+equal		0xf0
+plusminus	0xf1
+greaterequal	0xf2
+lessequal	0xf3
+integral	0xf4
+integral	0xf5
+divide		0xf6
+approxequal	0xf7
+degree		0xf8
+bullet		0xf9
+bullet		0xfa
+radical		0xfb
+cedilla		0xfc
+hungarumlaut	0xfd
+ogonek		0xfe
+nobrkspace	0xff
Index: /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/pc.sym
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/pc.sym	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/pc.sym	(revision 13928)
@@ -0,0 +1,115 @@
+# RTF PC character set (\pc) Symbol font map
+
+# Field 1 is the standard character name which the character value in
+# field 2 maps onto.  (It doesn't mean "to produce the character in field 1,
+# use the value in field 2.)
+
+# The character value may be given either as a single character (which will be
+# converted to the ASCII value of the character), or in numeric format, either
+# in decimal or 0xyy as hex yy.  Single or double quotes may be used to quote
+# characters.
+
+# characters in ASCII range (00-127)
+
+formula		0x06
+nobrkhyphen	0x1e
+opthyphen	0x1f
+
+space		" "
+exclam		!
+universal	'"'
+mathnumbersign	#
+existential	$
+percent		%
+ampersand	&
+suchthat	"'"
+parenleft	(
+parenright	)
+mathasterisk	*
+mathplus	+
+comma		,
+mathminus	-
+period		.
+slash		/
+zero		0
+one		1
+two		2
+three		3
+four		4
+five		5
+six		6
+seven		7
+eight		8
+nine		9
+colon		:
+semicolon	;
+less		<
+mathequal	=
+greater		>
+question	?
+congruent	@
+Alpha		A
+Beta		B
+Chi		C
+Delta		D
+Epsilon		E
+Phi		F
+Gamma		G
+Eta		H
+Iota		I
+# J		J
+Kappa		K
+Lambda		L
+Mu		M
+Nu		N
+Omicron		O
+Pi		P
+Theta		Q
+Rho		R
+Sigma		S
+Tau		T
+Upsilon		U
+varsigma	V
+Omega		W
+Xi		X
+Psi		Y
+Zeta		Z
+bracketleft	[
+backslash	\
+bracketright	]
+asciicircum	^
+underscore	_
+quoteleft	"`"
+alpha		a
+beta		b
+chi		c
+delta		d
+epsilon		e
+phi		f
+gamma		g
+eta		h
+iota		i
+# j		j
+kappa		k
+lambda		l
+mu		m
+nu		n
+omicron		o
+pi		p
+theta		q
+rho		r
+sigma		s
+tau		t
+upsilon		u
+# xxx		v
+omega		w
+xi		x
+psi		y
+zeta		z
+braceleft	{
+bar		|
+braceright	}
+mathtilde	~
+
+# non-ASCII characters (128-255)
+
Index: /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/pca.gen
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/pca.gen	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/pca.gen	(revision 13928)
@@ -0,0 +1,244 @@
+# RTF PC-A character set (\pca) general map
+
+# Field 1 is the standard character name which the character value in
+# field 2 maps onto.  (It doesn't mean "to produce the character in field 1,
+# use the value in field 2.)
+
+# The character value may be given either as a single character (which will be
+# converted to the ASCII value of the character), or in numeric format, either
+# in decimal or 0xyy as hex yy.  Single or double quotes may be used to quote
+# characters.
+
+# characters in ASCII range (32-127)
+
+formula		0x06
+nobrkhyphen	0x1e
+opthyphen	0x1f
+
+space		" "
+exclam		!
+quotedbl	'"'
+numbersign	#
+dollar		$
+percent		%
+ampersand	&
+quoteright	"'"
+parenleft	(
+parenright	)
+asterisk	*
+plus		+
+comma		,
+hyphen		-
+period		.
+slash		/
+zero		0
+one		1
+two		2
+three		3
+four		4
+five		5
+six		6
+seven		7
+eight		8
+nine		9
+colon		:
+semicolon	;
+less		<
+equal		=
+greater		>
+question	?
+at		@
+A		A
+B		B
+C		C
+D		D
+E		E
+F		F
+G		G
+H		H
+I		I
+J		J
+K		K
+L		L
+M		M
+N		N
+O		O
+P		P
+Q		Q
+R		R
+S		S
+T		T
+U		U
+V		V
+W		W
+X		X
+Y		Y
+Z		Z
+bracketleft	[
+backslash	\
+bracketright	]
+asciicircum	^
+underscore	_
+quoteleft	"`"
+a		a
+b		b
+c		c
+d		d
+e		e
+f		f
+g		g
+h		h
+i		i
+j		j
+k		k
+l		l
+m		m
+n		n
+o		o
+p		p
+q		q
+r		r
+s		s
+t		t
+u		u
+v		v
+w		w
+x		x
+y		y
+z		z
+braceleft	{
+bar		|
+braceright	}
+asciitilde	~
+
+# non-ASCII characters (128-255)
+
+
+Ccedilla	0x80
+udieresis	0x81
+eacute		0x82
+acircumflex	0x83
+adieresis	0x84
+agrave		0x85
+aring		0x86
+ccedilla	0x87
+ecircumflex	0x88
+edieresis	0x89
+egrave		0x8a
+idieresis	0x8b
+icircumflex	0x8c
+igrave		0x8d
+Adieresis	0x8e
+Aring		0x8f
+Eacute		0x90
+ae		0x91
+AE		0x92
+ocircumflex	0x93
+odieresis	0x94
+ograve		0x95
+ucircumflex	0x96
+ugrave		0x97
+ydieresis	0x98
+Odieresis	0x99
+Udieresis	0x9a
+oslash		0x9b
+sterling	0x9c
+Oslash		0x9d
+# ???		0x9e
+florin		0x9f
+aacute		0xa0
+iacute		0xa1
+oacute		0xa2
+uacute		0xa3
+ntilde		0xa4
+Ntilde		0xa5
+ordfeminine	0xa6
+ordmasculine	0xa7
+questiondown	0xa8
+registered	0xa9
+logicalnot	0xaa
+# ???		0xab
+# ???		0xac
+exclamdown	0xad
+guillemotleft	0xae
+guillemotright	0xaf
+# ???		0xb0
+# ???		0xb1
+# ???		0xb2
+# ???		0xb3
+# ???		0xb4
+# ???		0xb5
+# ???		0xb6
+Agrave		0xb7
+copyright	0xb8
+# ???		0xb9
+# ???		0xba
+# ???		0xbb
+# ???		0xbc
+cent		0xbd
+yen		0xbe
+# ???		0xbf
+# ???		0xc0
+# ???		0xc1
+# ???		0xc2
+# ???		0xc3
+# ???		0xc4
+# ???		0xc5
+atilde		0xc6
+Atilde		0xc7
+# ???		0xc8
+# ???		0xc9
+# ???		0xca
+# ???		0xcb
+# ???		0xcc
+# ???		0xcd
+# ???		0xce
+# ???		0xcf
+partialdiff	0xd0
+# ???		0xd1
+# ???		0xd2
+# ???		0xd3
+# ???		0xd4
+# ???		0xd5
+# ???		0xd6
+# ???		0xd7
+# ???		0xd8
+# ???		0xd9
+# ???		0xda
+# ???		0xdb
+# ???		0xdc
+# ???		0xdd
+# ???		0xde
+# ???		0xdf
+# ???		0xe0
+germandbls	0xe1
+# ???		0xe2
+# ???		0xe3
+otilde		0xe4
+Otilde		0xe5
+mu		0xe6
+# ???		0xe7
+# ???		0xe8
+# ???		0xe9
+# ???		0xea
+# ???		0xeb
+# ???		0xec
+# ???		0xed
+# ???		0xee
+acute		0xef
+endash		0xf0
+plusminus	0xf1
+equal		0xf2
+# ???		0xf3
+paragraph	0xf4
+section		0xf5
+divide		0xf6
+# ???		0xf7
+degree		0xf8
+dieresis	0xf9
+bullet		0xfa
+# ???		0xfb
+# ???		0xfc
+# ???		0xfd
+# ???		0xfe
+nobrkspace	0xff
Index: /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/pca.sym
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/pca.sym	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/pca.sym	(revision 13928)
@@ -0,0 +1,115 @@
+# RTF PC-A character set (\pca) Symbol font map
+
+# Field 1 is the standard character name which the character value in
+# field 2 maps onto.  (It doesn't mean "to produce the character in field 1,
+# use the value in field 2.)
+
+# The character value may be given either as a single character (which will be
+# converted to the ASCII value of the character), or in numeric format, either
+# in decimal or 0xyy as hex yy.  Single or double quotes may be used to quote
+# characters.
+
+# characters in ASCII range (00-127)
+
+formula		0x06
+nobrkhyphen	0x1e
+opthyphen	0x1f
+
+space		" "
+exclam		!
+universal	'"'
+mathnumbersign	#
+existential	$
+percent		%
+ampersand	&
+suchthat	"'"
+parenleft	(
+parenright	)
+mathasterisk	*
+mathplus	+
+comma		,
+mathminus	-
+period		.
+slash		/
+zero		0
+one		1
+two		2
+three		3
+four		4
+five		5
+six		6
+seven		7
+eight		8
+nine		9
+colon		:
+semicolon	;
+less		<
+mathequal	=
+greater		>
+question	?
+congruent	@
+Alpha		A
+Beta		B
+Chi		C
+Delta		D
+Epsilon		E
+Phi		F
+Gamma		G
+Eta		H
+Iota		I
+# J		J
+Kappa		K
+Lambda		L
+Mu		M
+Nu		N
+Omicron		O
+Pi		P
+Theta		Q
+Rho		R
+Sigma		S
+Tau		T
+Upsilon		U
+varsigma	V
+Omega		W
+Xi		X
+Psi		Y
+Zeta		Z
+bracketleft	[
+backslash	\
+bracketright	]
+asciicircum	^
+underscore	_
+quoteleft	"`"
+alpha		a
+beta		b
+chi		c
+delta		d
+epsilon		e
+phi		f
+gamma		g
+eta		h
+iota		i
+# j		j
+kappa		k
+lambda		l
+mu		m
+nu		n
+omicron		o
+pi		p
+theta		q
+rho		r
+sigma		s
+tau		t
+upsilon		u
+# xxx		v
+omega		w
+xi		x
+psi		y
+zeta		z
+braceleft	{
+bar		|
+braceright	}
+mathtilde	~
+
+# non-ASCII characters (128-255)
+
Index: /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/rtf-ctrl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/rtf-ctrl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/etc/packages/rtftohtm/rtf-ctrl	(revision 13928)
@@ -0,0 +1,769 @@
+# number of control words
+766
+# control word table
+6 0 "vern"
+6 5 "edmins"
+6 6 "yr"
+6 7 "mo"
+6 8 "dy"
+6 9 "hr"
+6 10 "min"
+6 11 "sec"
+6 12 "nofpages"
+6 13 "nofwords"
+6 14 "nofchars"
+6 15 "id"
+6 16 "chdate"
+6 17 "chdpl"
+6 18 "chdpa"
+6 19 "chtime"
+6 20 "chpgn"
+6 21 "sectnum"
+6 22 "chftn"
+6 23 "chatn"
+6 24 "chftnsep"
+6 25 "chftnsepc"
+6 26 "cell"
+6 27 "row"
+6 28 "par"
+6 28 "\n"
+6 28 "\r"
+6 29 "sect"
+6 30 "page"
+6 31 "column"
+6 32 "line"
+6 33 "softpage"
+6 34 "softcol"
+6 35 "softline"
+6 36 "softlheight"
+6 37 "tab"
+6 38 "emdash"
+6 39 "endash"
+6 40 "emspace"
+6 41 "enspace"
+6 42 "bullet"
+6 43 "lquote"
+6 44 "rquote"
+6 45 "ldblquote"
+6 46 "rdblquote"
+6 47 "|"
+6 49 "~"
+6 50 "-"
+6 51 "_"
+6 52 "*"
+6 53 "ltrmark"
+6 54 "rtlmark"
+6 55 "zwj"
+6 56 "zwnj"
+6 57 "chpict"
+6 59 "version"
+12 0 "plain"
+12 1 "b"
+12 2 "caps"
+12 37 "cgrid"
+12 3 "deleted"
+12 4 "dn"
+12 5 "sub"
+12 6 "nosupersub"
+12 7 "expnd"
+12 8 "expndtw"
+12 9 "kerning"
+12 38 "langfe"
+12 39 "langfenp"
+12 35 "lang"
+12 40 "langnp"
+12 10 "f"
+12 11 "fs"
+12 12 "i"
+12 13 "outl"
+12 14 "revised"
+12 15 "revauth"
+12 16 "revdttm"
+12 17 "scaps"
+12 18 "shad"
+12 19 "strike"
+12 20 "ul"
+12 21 "uld"
+12 22 "uldb"
+12 23 "ulnone"
+12 24 "ulw"
+12 25 "up"
+12 26 "super"
+12 27 "v"
+12 28 "cf"
+12 29 "cb"
+12 30 "rtlch"
+12 31 "ltrch"
+12 32 "noproof"
+12 33 "cs"
+12 34 "cchs"
+12 36 "gray"
+11 0 "pard"
+11 1 "s"
+11 2 "hyphpar"
+11 3 "intbl"
+11 104 "itap"
+11 4 "keep"
+11 6 "keepn"
+11 7 "level"
+11 8 "noline"
+11 5 "nowidctlpar"
+11 105 "widctlpar"
+11 7 "outlinelevel"
+11 9 "pagebb"
+11 10 "sbys"
+11 11 "ql"
+11 12 "qr"
+11 13 "qj"
+11 14 "qc"
+11 15 "fi"
+11 16 "li"
+11 16 "lin"
+11 17 "ri"
+11 17 "rin"
+11 17 "curi"
+11 106 "adjustright"
+11 18 "sb"
+11 19 "sa"
+11 20 "sl"
+11 21 "slmult"
+11 22 "subdocument"
+11 23 "rtlpar"
+11 24 "ltrpar"
+11 25 "tx"
+11 26 "tql"
+11 27 "tqr"
+11 28 "tqc"
+11 29 "tqdec"
+11 30 "tb"
+11 31 "tldot"
+11 32 "tlhyph"
+11 33 "tlul"
+11 34 "tlth"
+11 35 "tleq"
+11 36 "pnlvl"
+11 37 "pnlvlblt"
+11 38 "pnlvlbody"
+11 39 "pnlvlcont"
+11 40 "pnnumonce"
+11 41 "pnacross"
+11 42 "pnhang"
+11 43 "pnrestart"
+11 44 "pncard"
+11 45 "pndec"
+11 46 "pnucltr"
+11 47 "pnucrm"
+11 48 "pnlcltr"
+11 49 "pnlcrm"
+11 50 "pnord"
+11 51 "pnordt"
+11 52 "pnb"
+11 53 "pni"
+11 54 "pncaps"
+11 55 "pnscaps"
+11 56 "pnul"
+11 57 "pnuld"
+11 58 "pnuldb"
+11 59 "pnulnone"
+11 60 "pnulw"
+11 61 "pnstrike"
+11 62 "pncf"
+11 63 "pnf"
+11 64 "pnfs"
+11 65 "pnindent"
+11 66 "pnsp"
+11 67 "pnprev"
+11 68 "pnqc"
+11 69 "pnql"
+11 70 "pnqr"
+11 71 "pnstart"
+11 72 "brdrt"
+11 73 "brdrb"
+11 74 "brdrl"
+11 75 "brdrr"
+11 76 "brdrbtw"
+11 77 "brdrbar"
+11 78 "box"
+11 79 "brdrs"
+11 80 "brdrth"
+11 81 "brdrsh"
+11 82 "brdrdb"
+11 83 "brdrdot"
+11 83 "brdrdash"
+11 85 "brdrhair"
+11 86 "brdrw"
+11 87 "brdrcf"
+11 88 "brsp"
+11 89 "shading"
+11 90 "bghoriz"
+11 91 "bgvert"
+11 92 "bgfdiag"
+11 93 "bgbdiag"
+11 94 "bgcross"
+11 95 "bgdcross"
+11 96 "bgdkhoriz"
+11 97 "bgdkvert"
+11 98 "bgdkfdiag"
+11 99 "bgdkbdiag"
+11 100 "bgdkcross"
+11 101 "bgdkdcross"
+11 102 "cfpat"
+11 103 "cbpat"
+11 39 "ls"
+11 40 "ilvl"
+9 0 "sectd"
+9 1 "endnhere"
+9 2 "binfsxn"
+9 3 "binsxn"
+9 4 "ds"
+9 5 "sbknone"
+9 6 "sbkcol"
+9 7 "sbkpage"
+9 8 "sbkeven"
+9 9 "sbkodd"
+9 10 "cols"
+9 11 "colsx"
+9 12 "colno"
+9 13 "colsr"
+9 14 "colw"
+9 15 "linebetcol"
+9 16 "linemod"
+9 17 "linex"
+9 18 "linestarts"
+9 19 "linerestart"
+9 20 "lineppage"
+9 21 "linecont"
+9 22 "pgwsxn"
+9 23 "pghsxn"
+9 24 "marglsxn"
+9 25 "margrsxn"
+9 26 "margtsxn"
+9 27 "margbsxn"
+9 28 "guttersxn"
+9 29 "lndscpsxn"
+9 30 "titlepg"
+9 31 "headery"
+9 32 "footery"
+9 33 "pgnstarts"
+9 34 "pgncont"
+9 35 "pgnrestart"
+9 36 "pgnx"
+9 37 "pgny"
+9 38 "pgndec"
+9 39 "pgnucrm"
+9 40 "pgnlcrm"
+9 41 "pgnucltr"
+9 42 "pgnlcltr"
+9 43 "pgnhnsh"
+9 44 "pgnhnsp"
+9 45 "pgnhnsc"
+9 46 "pgnhnsm"
+9 47 "pgnhnsn"
+9 48 "vertalt"
+9 49 "vertalb"
+9 50 "vertalc"
+9 51 "vertalj"
+9 52 "rtlsect"
+9 53 "ltrsect"
+9 54 "horzsect"
+9 55 "vertsect"
+9 100 "sectexpand"
+9 100 "sectlinegrid"
+9 100 "sectdefaultcl"
+9 100 "sectspecifycl"
+9 100 "sectspecifyl"
+9 100 "sectspecifygen"
+9 56 "pgnhn"
+9 57 "sectunlocked"
+8 160 "uc"
+8 0 "deftab"
+8 1 "hyphhotz"
+8 2 "hyphconsec"
+8 3 "hyphcaps"
+8 4 "hyphauto"
+8 5 "linestart"
+8 6 "fracwidth"
+8 7 "makeback"
+8 7 "makebackup"
+8 8 "defformat"
+8 9 "psover"
+8 10 "doctemp"
+8 11 "deflang"
+8 150 "deflangfe"
+8 151 "windowcaption"
+8 152 "doctype"
+8 153 "fromtext"
+8 154 "fromhtml"
+8 155 "horzdoc"
+8 156 "vertdoc"
+8 157 "jcompress"
+8 158 "jexpand"
+8 159 "lnongrid"
+8 78 "viewkind"
+8 79 "viewscale"
+8 79 "viewzk"
+8 12 "fet"
+8 13 "endnotes"
+8 14 "enddoc"
+8 15 "ftntj"
+8 16 "ftnbj"
+8 17 "aendnotes"
+8 18 "aenddoc"
+8 19 "aftntj"
+8 20 "aftnbj"
+8 21 "ftnstart"
+8 22 "aftnstart"
+8 23 "ftnrstpg"
+8 24 "ftnrestart"
+8 25 "ftnrstcont"
+8 26 "aftnrestart"
+8 27 "aftnrstcont"
+8 28 "ftnnar"
+8 29 "ftnnalc"
+8 30 "ftnnauc"
+8 31 "ftnnrlc"
+8 32 "ftnnruc"
+8 33 "ftnnchi"
+8 34 "aftnnar"
+8 35 "aftnnalc"
+8 36 "aftnnauc"
+8 37 "aftnnrlc"
+8 38 "aftnnruc"
+8 39 "aftnnchi"
+8 40 "paperw"
+8 41 "paperh"
+8 42 "psz"
+8 43 "margl"
+8 44 "margr"
+8 45 "margt"
+8 46 "margb"
+8 47 "facingp"
+8 48 "gutter"
+8 49 "margmirror"
+8 50 "landscape"
+8 51 "pgnstart"
+8 52 "widowctrl"
+8 53 "linkstyles"
+8 54 "notabind"
+8 55 "wraptrsp"
+8 56 "prcolbl"
+8 57 "noextrasprl"
+8 58 "nocolbal"
+8 59 "cvmme"
+8 60 "sprstsp"
+8 61 "sprsspbf"
+8 62 "otblrul"
+8 63 "transmf"
+8 64 "swpbdr"
+8 65 "brkfrm"
+8 82 "formprot"
+8 83 "allprot"
+8 84 "formshade"
+8 85 "formdisp"
+8 86 "printdata"
+8 87 "revprot"
+8 88 "revisions"
+8 89 "revprop"
+8 90 "revbar"
+8 91 "annotprot"
+8 92 "rtldoc"
+8 93 "ltrdoc"
+8 94 "cts"
+8 95 "dghspace"
+8 96 "dgvspace"
+8 97 "dghorigin"
+8 98 "dgvorigin"
+8 99 "dghshow"
+8 100 "dgvshow"
+8 101 "dgsnap"
+8 102 "dgmargin"
+8 103 "pgbrdrhead"
+8 104 "pgbrdrfoot"
+8 105 "aspalpha"
+8 106 "aspnum"
+8 107 "faauto"
+8 66 "truncex"
+8 67 "bdbfhdr"
+8 68 "dntblnsbdb"
+8 69 "expshrtn"
+8 70 "lytexcttp"
+8 71 "lytprtmet"
+8 72 "msmcap"
+8 73 "nolead"
+8 74 "nospaceforul"
+8 75 "noultrlspc"
+8 76 "noxlattoyen"
+8 77 "oldas"
+8 78 "lnbrkrule"
+8 79 "bdrrlswsix"
+8 81 "sprstsm"
+8 80 "nolnhtadjtbl"
+7 0 "additive"
+7 1 "sbasedon"
+7 2 "snext"
+7 3 "sautoupd"
+13 32 "emfblip"
+13 33 "pngblip"
+13 34 "jpegblip"
+13 36 "nonshppict"
+13 0 "macpict"
+13 1 "pmmetafile"
+13 2 "wmetafile"
+13 3 "dibitmap"
+13 4 "wbitmap"
+13 5 "wbmbitspixel"
+13 6 "wbmplanes"
+13 7 "wbmwidthbytes"
+13 8 "picw"
+13 9 "pich"
+13 10 "picwgoal"
+13 11 "pichgoal"
+13 10 "picwGoal"
+13 11 "pichGoal"
+13 12 "picscalex"
+13 13 "picscaley"
+13 14 "picscaled"
+13 15 "piccropt"
+13 16 "piccropb"
+13 17 "piccropl"
+13 18 "piccropr"
+13 19 "picbmp"
+13 20 "picbpp"
+13 21 "bin"
+13 22 "blipupi"
+13 24 "bliptag"
+15 0 "width"
+15 1 "height"
+3 0 "fonttbl"
+3 1 "falt"
+3 2 "fonteb"
+3 3 "fontfile"
+3 4 "filetbl"
+3 5 "file"
+3 6 "colortbl"
+3 7 "stylesheet"
+3 8 "keycode"
+3 9 "revtbl"
+3 10 "info"
+3 11 "title"
+3 12 "subject"
+3 13 "author"
+3 14 "operator"
+3 15 "keywords"
+3 16 "comment"
+3 18 "doccomm"
+3 19 "verscomm"
+3 20 "nextfile"
+3 21 "template"
+3 22 "ftnsep"
+3 23 "ftnsepc"
+3 24 "ftncn"
+3 25 "aftnsep"
+3 26 "aftnsepc"
+3 27 "aftncn"
+3 29 "pnseclvl"
+3 30 "header"
+3 31 "footer"
+3 32 "headerl"
+3 33 "headerr"
+3 34 "headerf"
+3 35 "footerl"
+3 36 "footerr"
+3 37 "footerf"
+3 38 "pntext"
+3 39 "pn"
+3 40 "pntxta"
+3 41 "pntxtb"
+3 42 "bkmkstart"
+3 43 "bkmkend"
+3 44 "pict"
+3 45 "object"
+3 46 "objclass"
+3 47 "objname"
+3 48 "objtime"
+3 49 "objdata"
+3 50 "objalias"
+3 51 "objsect"
+3 53 "objitem"
+3 54 "objtopic"
+3 52 "result"
+3 55 "do"
+3 56 "footnote"
+3 57 "atrfstart"
+3 58 "atrfend"
+3 59 "atnid"
+3 60 "atnauthor"
+3 61 "annotation"
+3 62 "atnref"
+3 63 "atntime"
+3 64 "atnicn"
+3 65 "field"
+3 66 "fldinst"
+3 67 "fldrslt"
+3 68 "datafield"
+3 69 "xe"
+3 70 "txe"
+3 71 "rxe"
+3 72 "tc"
+3 73 "NeXTGraphic"
+3 74 "NeXTHelpMarker"
+3 28 "NeXTHelpLink"
+3 75 "buptim"
+3 76 "creatim"
+3 77 "printim"
+3 78 "revtim"
+3 79 "dptxbxtext"
+3 80 "fontemb"
+3 81 "tcn"
+3 35 "shppict"
+3 41 "listtext"
+3 79 "private"
+3 82 "shpgrp"
+4 0 "fnil"
+4 1 "froman"
+4 2 "fswiss"
+4 3 "fmodern"
+4 4 "fscript"
+4 5 "fdecor"
+4 6 "ftech"
+4 7 "fbidi"
+23 0 "fcharset"
+23 1 "fprq"
+23 2 "cpg"
+23 3 "ftnil"
+23 4 "fttruetype"
+24 0 "fid"
+24 1 "frelative"
+24 2 "fosnum"
+25 0 "fvalidmac"
+25 1 "fvaliddos"
+25 2 "fvalidntfs"
+25 3 "fvalidhpfs"
+25 4 "fnetwork"
+5 0 "red"
+5 1 "green"
+5 2 "blue"
+2 2 "mac"
+2 0 "ansi"
+2 3 "pc"
+2 4 "pca"
+2 1 "ansicpg"
+10 0 "trowd"
+10 1 "trgaph"
+10 2 "cellx"
+10 3 "clmgf"
+10 4 "clmrg"
+10 5 "trql"
+10 6 "trqr"
+10 7 "trqc"
+10 8 "trleft"
+10 9 "trrh"
+10 10 "trhdr"
+10 11 "trkeep"
+10 12 "rtlrow"
+10 13 "ltrrow"
+10 14 "trbrdrt"
+10 15 "trbrdrl"
+10 16 "trbrdrb"
+10 17 "trbrdrr"
+10 18 "trbrdrh"
+10 19 "trbrdrv"
+10 20 "clbrdrb"
+10 21 "clbrdrt"
+10 22 "clbrdrl"
+10 23 "clbrdrr"
+10 42 "clvertalt"
+10 43 "clvertalc"
+10 44 "clvertalb"
+10 45 "cltxlrtb"
+10 46 "cltxlbrl"
+10 24 "clshdng"
+10 25 "clbghoriz"
+10 26 "clbgvert"
+10 27 "clbgfdiag"
+10 28 "clbgbdiag"
+10 29 "clbgcross"
+10 30 "clbgdcross"
+10 31 "clbgdkhoriz"
+10 31 "clbgdkhor"
+10 32 "clbgdkvert"
+10 33 "clbgdkfdiag"
+10 34 "clbgdkbdiag"
+10 35 "clbgdkcross"
+10 36 "clbgdkdcross"
+10 37 "clcfpat"
+10 38 "clcbpat"
+16 0 "flddirty"
+16 1 "fldedit"
+16 2 "fldlock"
+16 3 "fldpriv"
+16 4 "fldalt"
+18 0 "absw"
+18 1 "absh"
+18 2 "phmrg"
+18 3 "phpg"
+18 4 "phcol"
+18 5 "posx"
+18 6 "posnegx"
+18 7 "posxc"
+18 8 "posxi"
+18 9 "posxo"
+18 10 "posxr"
+18 11 "posxl"
+18 12 "pvmrg"
+18 13 "pvpg"
+18 14 "pvpara"
+18 15 "posy"
+18 16 "posnegy"
+18 17 "posyil"
+18 18 "posyt"
+18 19 "posyc"
+18 20 "posyb"
+18 21 "nowrap"
+18 22 "dxfrtext"
+18 23 "dfrmtxtx"
+18 24 "dfrmtxty"
+18 25 "dyfrtext"
+18 26 "dropcapli"
+18 27 "dropcapt"
+19 0 "objemb"
+19 1 "objlink"
+19 2 "objautlink"
+19 3 "objsub"
+19 4 "objpub"
+19 5 "objicemb"
+19 6 "linkself"
+19 7 "objupdate"
+19 8 "objlock"
+19 9 "objh"
+19 10 "objw"
+19 11 "objsetsize"
+19 12 "objalign"
+19 13 "objtransy"
+19 14 "objcropt"
+19 15 "objcropb"
+19 16 "objcropl"
+19 17 "objcropr"
+19 18 "objscalex"
+19 19 "objscaley"
+19 20 "rsltrtf"
+19 21 "rsltpict"
+19 22 "rsltbmp"
+19 23 "rslttxt"
+19 24 "rsltmerge"
+19 25 "bkmkpub"
+19 26 "pubauto"
+22 0 "ab"
+22 1 "acaps"
+22 2 "acf"
+22 3 "adn"
+22 4 "aexpnd"
+22 5 "af"
+22 6 "afs"
+22 7 "ai"
+22 8 "alang"
+22 9 "aoutl"
+22 10 "ascaps"
+22 11 "ashad"
+22 12 "astrike"
+22 13 "aul"
+22 14 "auld"
+22 15 "auldb"
+22 16 "aulnone"
+22 17 "aulw"
+22 18 "aup"
+20 0 "ftnalt"
+21 0 "alt"
+21 1 "shift"
+21 2 "ctrl"
+21 3 "fn"
+14 0 "bkmkcolf"
+14 1 "bkmkcoll"
+27 0 "xef"
+27 1 "bxe"
+27 2 "ixe"
+17 0 "tcf"
+17 1 "tcl"
+26 0 "dolock"
+26 1 "dobxpage"
+26 2 "dobxcolumn"
+26 3 "dobxmargin"
+26 4 "dobypage"
+26 6 "dobymargin"
+26 7 "dodhgt"
+26 8 "dpgroup"
+26 9 "dpcount"
+26 10 "dpendgroup"
+26 11 "dparc"
+26 12 "dpcallout"
+26 13 "dpellipse"
+26 14 "dpline"
+26 15 "dppolygon"
+26 16 "dppolyline"
+26 17 "dprect"
+26 18 "dptxbx"
+26 19 "dpx"
+26 20 "dpxsize"
+26 21 "dpy"
+26 22 "dpysize"
+26 23 "dpcoa"
+26 24 "dpcoaccent"
+26 25 "dpcobestfit"
+26 26 "dpcoborder"
+26 27 "dpcodabs"
+26 28 "dpcodbottom"
+26 29 "dpcodcenter"
+26 30 "dpcodtop"
+26 31 "dpcolength"
+26 32 "dpcominusx"
+26 33 "dpcominusy"
+26 34 "dpcooffset"
+26 35 "dpcosmarta"
+26 36 "dpcotdouble"
+26 37 "dpcotright"
+26 38 "dpcotsingle"
+26 39 "dpcottriple"
+26 40 "dptxbxmar"
+26 42 "dproundr"
+26 43 "dpptx"
+26 44 "dppty"
+26 45 "dppolycount"
+26 46 "dparcflipx"
+26 47 "dparcflipy"
+26 48 "dplinecob"
+26 49 "dplinecog"
+26 50 "dplinecor"
+26 51 "dplinepal"
+26 52 "dplinedado"
+26 53 "dplinedadodo"
+26 54 "dplinedash"
+26 55 "dplinedot"
+26 56 "dplinegray"
+26 57 "dplinehollow"
+26 58 "dplinesolid"
+26 59 "dplinew"
+26 60 "dpaendhol"
+26 61 "dpaendl"
+26 62 "dpaendsol"
+26 63 "dpaendw"
+26 64 "dpastarthol"
+26 65 "dpastartl"
+26 66 "dpastartsol"
+26 67 "dpastartw"
+26 68 "dpfillbgcb"
+26 69 "dpfillbgcg"
+26 70 "dpfillbgcr"
+26 71 "dpfillbgpal"
+26 72 "dpfillbggray"
+26 73 "dpfillfgcb"
+26 74 "dpfillfgcg"
+26 75 "dpfillfgcr"
+26 76 "dpfillfgpal"
+26 77 "dpfillfggray"
+26 78 "dpfillpat"
+26 79 "dpshadow"
+26 80 "dpshadx"
+26 81 "dpshady"
+26 82 "dobypara"
+0 -1 "rtf"
+1 -1 "deff"
Index: /tags/greenstone-3_02-distribution/gsdl/etc/packages/wv/wvHtml.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/etc/packages/wv/wvHtml.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/etc/packages/wv/wvHtml.xml	(revision 13928)
@@ -0,0 +1,397 @@
+<main>
+<charentity>
+<begin>HTML</begin>
+</charentity>
+
+<document>
+<begin>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/REC-html40/loose.dtd&quot;&gt;
+&lt;html&gt; 
+&lt;head&gt; 
+&lt;META HTTP-EQUIV=&quot;Content-Type&quot; CONTENT=&quot;text/html; charset=<charset/>&quot;&gt;
+&lt;META NAME=&quot;GENERATOR&quot; CONTENT=&quot;wvWare/<version/>&quot;&gt;
+&lt;title&gt; 
+<title/>
+&lt;/title&gt; 
+&lt;/head&gt; 
+&lt;body bgcolor=&quot;#FFFFFF&quot; text=&quot;#000000&quot; link=&quot;#0000ee&quot; vlink=&quot;#551a8b&quot;&gt;
+</begin>
+<end>
+&lt;/body&gt;
+&lt;/html&gt;
+</end>
+</document>
+
+<section>
+<begin>
+&lt;!--Section Begins--&gt;&lt;br&gt;
+</begin>
+<end>
+&lt;!--Section Ends--&gt;
+</end>
+</section>
+
+<justification>
+<left>left</left>
+<right>right</right>
+<center>center</center>
+<block>justify</block>
+<asian>&lt;!--Could Someone who sees this tag tell me what was is this type of justification, asian languages only i thing--&gt;</asian>
+</justification>
+
+<numbering>
+<Arabic>type=&quot;1&quot;</Arabic>
+<UpperRoman>type=&quot;I&quot;</UpperRoman>
+<LowerRoman>type=&quot;i&quot;</LowerRoman>
+<UpperCaseN>type=&quot;A&quot;</UpperCaseN>
+<LowerCaseN>type=&quot;a&quot;</LowerCaseN>
+</numbering>
+
+<border>
+<noned>none</noned>
+<singled>solid</singled>
+<thickd>solid</thickd>
+<doubled>double</doubled>
+<number4d>double</number4d>
+<hairlined>solid</hairlined>
+<dotd>dotted</dotd>
+<dashlargegapd>dashed</dashlargegapd>
+<dotdashd>dotted</dotdashd>
+<dotdotdashd>dotted</dotdotdashd>
+<tripled>double</tripled>
+<thin-thicksmallgapd>dashed</thin-thicksmallgapd>
+<thick-thinsmallgapd>dashed</thick-thinsmallgapd>
+<thin-thick-thinsmallgapd>dashed</thin-thick-thinsmallgapd>
+<thin-thickmediumgapd>dashed</thin-thickmediumgapd>
+<thick-thinmediumgapd>dashed</thick-thinmediumgapd>
+<thin-thick-thinmediumgapd>dashed</thin-thick-thinmediumgapd>
+<thin-thicklargegapd>dashed</thin-thicklargegapd>
+<thick-thinlargegapd>dashed</thick-thinlargegapd>
+<thin-thick-thinlargegapd>dashed</thin-thick-thinlargegapd>
+<waved>solid</waved>
+<doublewaved>double</doublewaved>
+<dashsmallgapd>sashed</dashsmallgapd>
+<dashdotstrokedd>dashed</dashdotstrokedd>
+<emboss3Dd>ridge</emboss3Dd>
+<engrave3Dd>groove</engrave3Dd>
+<defaultd>ridge</defaultd>
+</border>
+
+<olist>
+<begin>&lt;ol <nfc/> start=&quot;<start/>&quot;&gt;
+</begin>
+<end>&lt;/ol&gt;</end>
+</olist>
+
+<ulist>
+<begin>&lt;ul&gt;
+</begin>
+<end>&lt;/ul&gt;</end>
+</ulist>
+
+<entry>
+<begin>&lt;li&gt;</begin>
+<end></end>
+</entry>
+
+
+<!-- 
+this tableoverride option can be used to turn off handling of
+these tags in tables, which I find is necessary for at least netscape
+-->
+<tableoverrides>
+<ParaBefore>0</ParaBefore>
+<ParaRight>0</ParaRight>
+<ParaAfter>0</ParaAfter>
+<ParaLeft>0</ParaLeft>
+<ParaLeft1>0</ParaLeft1>
+<VertMergedCells>0</VertMergedCells>
+</tableoverrides>
+
+<table>
+<begin>&lt;table width=&quot;<tablerelwidth/>%&quot; border=&quot;1&quot; cols=&quot;<no_cols/>&quot; rows=&quot;<no_rows/>&quot;&gt;</begin>
+<end>&lt;/table&gt;</end>
+</table>
+
+<row>
+<begin>&lt;tr&gt;</begin>
+<end>&lt;/tr&gt;</end>
+</row>
+
+<cell>
+<begin>&lt;td bgcolor=&quot;<cellbgcolor/>&quot; width=&quot;<cellrelwidth/>%&quot; rowspan=&quot;<rowspan/>&quot; colspan=&quot;<colspan/>&quot;&gt;</begin>
+<end>&lt;/td&gt;</end>
+</cell>
+
+<paragraph>
+<begin>
+<table.end/>
+<table.begin/>
+<row.begin/>
+<cell.begin/><olist.end/><olist.begin/><ulist.end/><ulist.begin/><entry.begin/>
+<text.begin/>
+</begin>
+<end>
+<text.end/>
+<entry.end/>
+<olist.end/>
+<ulist.end/>
+<cell.end/>
+<row.end/>
+</end>
+</paragraph>
+
+<!-- these are all the character properties that can show up in word -->
+<bold><begin>&lt;b&gt;</begin><end>&lt;/b&gt;</end></bold>
+<italic><begin>&lt;i&gt;</begin><end>&lt;/i&gt;</end></italic>
+
+<!--
+text that has been deleted and will be displayed with strikethrough when
+revision marked text is to be displayed
+
+use either this line...
+--> 
+<RMarkDel><begin>&lt;s&gt;</begin><end>&lt;/s&gt;&lt;a href=&quot;#author<ibstRMarkDel/>&quot;&gt;[Author ID<ibstRMarkDel/>: at <dttmRMarkDel/> ]&lt;/a&gt;</end></RMarkDel>
+
+<!--
+or uncomment below to make deleted text dissappear (well, become commented out)
+-->
+<!--
+<RMarkDel><begin>&lt;!-&#45;</begin><end>-&#45;&gt;</end></RMarkDel>
+-->
+
+<!-- I don't even know what outline means -->
+<outline><begin></begin><end></end></outline>
+<smallcaps><begin></begin><end></end></smallcaps>
+<caps><begin></begin><end></end></caps>
+<vanish><begin></begin><end></end></vanish>
+
+<!--If you uncomment this then the annotation text links will become commented out by html tags-->
+<!--
+<vanish><begin>&lt;!-&#45;</begin><end>-&#45;&gt;</end></vanish>
+-->
+
+<!--
+text that has been newly typed since the last time revision marks have been accepted
+and will be displayed with underline when revision marked text is to be displayed
+
+use either this line...
+-->
+<RMark><begin>&lt;u&gt;</begin><end>&lt;/u&gt;&lt;a href=&quot;#author<ibstRMark/>&quot;&gt;[Author ID<ibstRMark/>: at <dttmRMark/>]&lt;/a&gt;</end></RMark>
+
+<!--
+or uncomment below to make the underline dissappear
+-->
+<!--
+<RMark><begin></begin><end></end></RMark>
+-->
+
+
+<strike><begin>&lt;s&gt;</begin><end>&lt;/s&gt;</end></strike>
+<shadow><begin></begin><end></end></shadow>
+<lowercase><begin></begin><end></end></lowercase>
+<emboss><begin></begin><end></end></emboss>
+<imprint><begin></begin><end></end></imprint>
+<!--double strike-->
+<dstrike><begin>&lt;s&gt;</begin><end>&lt;/s&gt;</end></dstrike>
+
+<!--
+ftc's
+&
+hps
+
+keep them for font face and do that later.
+-->
+
+<super><begin>&lt;sup&gt;</begin><end>&lt;/sup&gt;</end></super>
+<sub><begin>&lt;sub&gt;</begin><end>&lt;/sub&gt;</end></sub>
+
+<singleu><begin>&lt;u&gt;</begin><end>&lt;/u&gt;</end></singleu>
+<wordu><begin>&lt;u&gt;</begin><end>&lt;/u&gt;</end></wordu>
+<doubleu><begin>&lt;u&gt;</begin><end>&lt;/u&gt;</end></doubleu>
+<dottedu><begin>&lt;u&gt;</begin><end>&lt;/u&gt;</end></dottedu>
+<hiddenu><begin>&lt;u&gt;</begin><end>&lt;/u&gt;</end></hiddenu>
+<thicku><begin>&lt;u&gt;</begin><end>&lt;/u&gt;</end></thicku>
+<dashu><begin>&lt;u&gt;</begin><end>&lt;/u&gt;</end></dashu>
+<dotu><begin>&lt;u&gt;</begin><end>&lt;/u&gt;</end></dotu>
+<dotdashu><begin>&lt;u&gt;</begin><end>&lt;/u&gt;</end></dotdashu>
+<dotdotdashu><begin>&lt;u&gt;</begin><end>&lt;/u&gt;</end></dotdotdashu>
+<waveu><begin>&lt;u&gt;</begin><end>&lt;/u&gt;</end></waveu>
+
+<!--
+text whose properties have been changed since the last time revision marks have been accepted
+and will be displayed with a note showing the change points.
+
+use either this line (which admit it a bit scary looking, but harmless)...
+--> 
+<PropRMark><begin>&lt;a href=&quot;#author<ibstPropRMark/>&quot;&gt;-&#45;&amp;gt;&lt;/a&gt;</begin><end>&lt;a href=&quot;#author<ibstPropRMark/>&quot;&gt;[Author ID<ibstPropRMark/>: at <dttmPropRMark/>]&lt;/a&gt;</end></PropRMark>
+
+<!--
+or uncomment below to make the notes dissappear
+-->
+<!--
+<PropRMark><begin></begin><end></end></PropRMark>
+-->
+
+<!--
+<color>
+-->
+<Black><begin>Black</begin><end></end></Black>
+<Blue><begin>Blue</begin><end></end></Blue>
+<Cyan><begin>Cyan</begin><end></end></Cyan>
+<Green><begin>Green</begin><end></end></Green>
+<Magenta><begin>Magenta</begin><end></end></Magenta>
+<Red><begin>Red</begin><end></end></Red>
+<Yellow><begin>Yellow</begin><end></end></Yellow>
+<White><begin>White</begin><end></end></White>
+<DkBlue><begin>DarkBlue</begin><end></end></DkBlue>
+<DkCyan><begin>DarkCyan</begin><end></end></DkCyan>
+<DkGreen><begin>DarkGreen</begin><end></end></DkGreen>
+<DkMagenta><begin>DarkMagenta</begin><end></end></DkMagenta>
+<DkRed><begin>DarkRed</begin><end></end></DkRed>
+<DkYellow><begin>#8b8b00</begin><end></end></DkYellow>
+<DkGray><begin>DarkGray</begin><end></end></DkGray>
+<LtGray><begin>LightGrey</begin><end></end></LtGray>
+<!--
+</color>
+-->
+
+<!--
+<animation>
+-->
+<LasVegas><begin>&lt;blink&gt;</begin><end>&lt;/blink&gt;</end></LasVegas>
+<BackgroundBlink><begin>&lt;blink&gt;</begin><end>&lt;/blink&gt;</end></BackgroundBlink>
+<SparkleText><begin>&lt;blink&gt;</begin><end>&lt;/blink&gt;</end></SparkleText>
+<MarchingAnts><begin>&lt;blink&gt;</begin><end>&lt;/blink&gt;</end></MarchingAnts>
+<MarchingRedAnts><begin>&lt;blink&gt;</begin><end>&lt;/blink&gt;</end></MarchingRedAnts>
+<Shimmer><begin>&lt;blink&gt;</begin><end>&lt;/blink&gt;</end></Shimmer>
+<!--
+</animation>
+-->
+
+<!--
+I dont understand what this one is, and ive never come across it
+
+use this sample line (which admit it a bit scary looking, but harmless)...
+-->
+<DispFldRMark><begin>&lt;a href=&quot;#author<ibstDispFldRMark/>&quot;&gt;--&amp;gt;&lt;/a&gt;</begin><end>&lt;a href=&quot;#author<ibstDispFldRMark/>&quot;&gt;[Author ID<ibstDispFldRMark/>: at <dttmDispFldRMark/> (<xstDispFldRMark/>)]&lt;/a&gt;</end></DispFldRMark>
+
+<!--
+or uncomment below to ignore it, the previous might even crash wv ?
+-->
+<!--
+<DispFldRMark><begin></begin><end></end></DispFldRMark>
+-->
+
+<animation>
+<begin><LasVegas.begin/><BackgroundBlink.begin/><SparkleText.begin/><MarchingAnts.begin/><MarchingRedAnts.begin/><Shimmer.begin/></begin>
+<end><Shimmer.end/><MarchingRedAnts.end/><MarchingAnts.end/><SparkleText.end/><BackgroundBlink.end/><LasVegas.end/></end>
+</animation>
+
+<fontstr>
+<begin>&lt;font color=&quot;<black.begin/><blue.begin/><cyan.begin/><green.begin/><magenta.begin/><red.begin/><yellow.begin/><white.begin/><dkblue.begin/><dkcyan.begin/><dkgreen.begin/><dkmagenta.begin/><dkred.begin/><dkyellow.begin/><dkgray.begin/><ltgray.begin/>&quot;&gt;</begin>
+<end><ltgray.end/><dkgray.end/><dkyellow.end/><dkred.end/><dkmagenta.end/><dkgreen.end/><dkcyan.end/><dkblue.end/><white.end/><yellow.end/><red.end/><magenta.end/><green.end/><cyan.end/><blue.end/><black.end/>&lt;/font&gt;</end>
+</fontstr>
+
+<comment>
+<begin>
+&lt;a href=&quot;#comment<ibstAnno/> &quot;&gt;-&#45;&amp;gt;&lt;/a&gt;
+</begin>
+<end>&lt;a href=&quot;#comment<ibstAnno/> &quot;&gt;[Author:<xstUsrInitl/>]&lt;/a&gt;
+</end>
+</comment>
+
+<style name="Normal">
+<character>
+<begin><PropRMark.begin/><DispFldRMark.begin/><animation.begin/><fontstr.begin/><bold.begin/><italic.begin/><strike.begin/><RMarkDel.begin/><outline.begin/><smallcaps.begin/><caps.begin/><vanish.begin/><RMark.begin/><shadow.begin/><lowercase.begin/><emboss.begin/><imprint.begin/><dstrike.begin/><super.begin/><sub.begin/><singleu.begin/><wordu.begin/><doubleu.begin/><dottedu.begin/><hiddenu.begin/><thicku.begin/><dashu.begin/><dotu.begin/><dotdashu.begin/><dotdotdashu.begin/><waveu.begin/></begin>
+<end><waveu.end/><dotdotdashu.end/><dotdashu.end/><dotu.end/><dashu.end/><thicku.end/><hiddenu.end/><dottedu.end/><doubleu.end/><wordu.end/><singleu.end/><sub.end/><super.end/><dstrike.end/><imprint.end/><emboss.end/><lowercase.end/><shadow.end/><RMark.end/><vanish.end/><caps.end/><smallcaps.end/><outline.end/><RMarkDel.end/><strike.end/><italic.end/><bold.end/><fontstr.end/><animation.end/><DispFldRMark.end/><PropRMark.end/></end>
+</character>
+
+<!-- Netscape does handle this correctly yet, here is how each different side of the border should work.
+border-top: thin <bordertopstyle/> <bordertopcolor/>;
+border-left: thin <borderleftstyle/> <borderleftcolor/>;
+border-right: thin <borderrightstyle/> <borderrightcolor/>;
+border-bottom: thin <borderbottomstyle/> <borderbottomcolor/>
+-->
+
+
+<pmargin>
+<begin>margin: <mmParaBefore/> <mmParaRight/> <mmParaAfter/> <mmParaLeft/>;</begin>
+</pmargin>
+
+<pborder>
+<begin>
+border: thin <borderleftstyle/> <borderleftcolor/>;
+<!--
+border-top: thin <bordertopstyle/> <bordertopcolor/>;
+border-left: thin <borderleftstyle/> <borderleftcolor/>;
+border-right: thin <borderrightstyle/> <borderrightcolor/>;
+border-bottom: thin <borderbottomstyle/> <borderbottomcolor/>
+-->
+</begin>
+</pborder>
+
+<text>	
+<begin>
+&lt;div align=&quot;<just/>&quot; style=&quot;<paramargin/> <paraborder/>
+padding: <mmPadTop/> <mmPadRight/> <mmPadBottom/> <mmPadLeft/>; &quot;&gt;
+&lt;p style=&quot;text-indent: <mmParaLeft1/>; text-align: <just/>; color: <parafgcolor/>; background-color: <parabgcolor/>; &quot;&gt;
+</begin>
+<end>
+&lt;/p&gt;
+&lt;/div&gt;
+</end>
+</text>
+
+<picture>
+<begin>
+&lt;img <htmlAlignGuess/> width=&quot;<pixPicWidth/>&quot; height=&quot;<pixPicHeight/>&quot; alt=&quot;0x01 graphic&quot; src=&quot;placeholder.png&quot;&gt;<htmlNextLineGuess/>
+</begin>
+</picture>
+
+</style>
+
+<!--we need to be override the character properties-->
+<!--
+<style name="Normal">
+<character>
+<begin><PropRMark.begin/><DispFldRMark.begin/><animation.begin/><fontstr.begin/><bold.begin/><italic.begin/><strike.begin/><RMarkDel.begin/><outline.begin/><smallcaps.begin/><caps.begin/><vanish.begin/><RMark.begin/><shadow.begin/><lowercase.begin/><emboss.begin/><imprint.begin/><dstrike.begin/><super.begin/><sub.begin/><singleu.begin/><wordu.begin/><doubleu.begin/><dottedu.begin/><hiddenu.begin/><thicku.begin/><dashu.begin/><dotu.begin/><dotdashu.begin/><dotdotdashu.begin/><waveu.begin/></begin>
+<end><waveu.end/><dotdotdashu.end/><dotdashu.end/><dotu.end/><dashu.end/><thicku.end/><hiddenu.end/><dottedu.end/><doubleu.end/><wordu.end/><singleu.end/><sub.end/><super.end/><dstrike.end/><imprint.end/><emboss.end/><lowercase.end/><shadow.end/><RMark.end/><vanish.end/><caps.end/><smallcaps.end/><outline.end/><RMarkDel.end/><strike.end/><italic.end/><bold.end/><fontstr.end/><animation.end/><DispFldRMark.end/><PropRMark.end/></end>
+</character>
+
+<text>	
+<begin>
+&lt;div align=&quot;<just/>&quot;&gt;
+&lt;p&gt;
+</begin>
+<end>
+&lt;/p&gt;
+&lt;/div&gt;
+</end>
+</text>
+
+</style>
+
+<style name="Heading 1">
+
+<character>
+<begin></begin>
+<end></end>
+</character>
+
+<text>	
+<begin>
+&lt;div align=&quot;<just/>&quot;&gt;
+&lt;H1&gt;
+</begin>
+<end>
+&lt;/H1&gt;
+&lt;/div&gt;
+</end>
+</text>
+
+
+
+</style>
+-->
+
+</main>
Index: /tags/greenstone-3_02-distribution/gsdl/etc/packages/z3950.cfg
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/etc/packages/z3950.cfg	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/etc/packages/z3950.cfg	(revision 13928)
@@ -0,0 +1,43 @@
+[GSDL2.1] # config file version
+#
+# This file specifies a list of z39.50 servers to use.
+# Each field is separated by white-space.
+# If you want a " character inside a string, escape it - ie \" or ""
+
+#
+# Each server configuration consists of a stanza. The items are described here:
+#	Item				Description
+#	###############			########################
+#	collectname			<GSDL internal name (alphanumeric) >
+#	servername:port			<Internet address (def. port is 210) >
+#	dbname				<z39.50 server database name>
+#	"humanname"			<Brief description>
+#	icon "url to icon"		<optional GSDL icon (eg collection) >
+#	smallicon "url to small icon"	<optional GSDL icon (eg homepage) >
+#	About "about text"		<optional>
+
+
+# For an exhaustive list of servers to try, have a look at
+#  http://www.indexdata.dk/targettest/
+
+
+#LOCtest
+#       ilssun2.loc.gov:7090
+#       Voyager
+#       "Library of Congress TEST z39.50 server"
+#       About "This database/server is provided by the US LoC for the testing
+#           of z39.50 clients. For server capabilities, look at
+#           <a href=\"http://lcweb.loc.gov/z3950/lcserver.html\">their web 
+#           pages</a>. Note that <b>no records will ever be returned</b> -
+#           this server is for testing the protocols only."
+
+
+#LOC
+#        z3950.loc.gov:7090
+#        Voyager
+#        "Library of Congress z39.50 server"
+#        About   "This is the z39.50 interface to the US LoC catalogue
+#           system. It contains approximately 12 million bibliographic records.
+#           For server capabilities, look at
+#           <a href=\"http://lcweb.loc.gov/z3950/lcserver.html\">their web 
+#           pages</a>."
Index: /tags/greenstone-3_02-distribution/gsdl/etc/qdc2marc-mapping.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/etc/qdc2marc-mapping.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/etc/qdc2marc-mapping.xml	(revision 13928)
@@ -0,0 +1,354 @@
+<Mapping>
+    <!-- English-->
+    <stopwords lang="en" >
+      <item  name="a " length="2"/>
+      <item  name="an " length="3"/>
+      <item  name="the " length="4"/>   
+    </stopwords>
+
+    <!--Spain-->
+    <stopwords lang="es">
+      <item  name="uno " length="4"/>
+      <item  name="una " length="4"/>
+      <item  name="el " length="3"/>
+      <item  name="la " length="3"/>
+      <item  name="las " length="4"/>
+      <item  name="los " length="4"/>
+      <item  name="un " length="3"/>
+      <item  name="unos " length="5"/>
+      <item  name="unas " length="5"/>
+    </stopwords>
+
+  <!--Catalan-->
+  <stopwords lang="ca">
+     <item  name="el " length="3"/>
+     <item  name="la " length="3"/>
+     <item  name="les " length="4"/>
+     <item  name="l'" length="2"/>
+     <item  name="un " length="3"/>
+     <item  name="una " length="4"/>
+     <item  name="uns " length="4"/>
+     <item  name="unes " length="5"/>
+     <item  name="es " length="3"/>
+     <item  name="sa " length="3"/>
+     <item  name="ses " length="4"/>
+     <item  name="sos " length="4"/>
+     <item  name="so " length="3"/>
+     <item  name="s'" length="2"/>
+   </stopwords>
+ 
+  <!--German-->  
+  <stopwords lang="de">
+     <item  name="der " length="4"/>
+     <item  name="ein " length="4"/>
+     <item  name="die " length="4"/>
+     <item  name="eine " length="5"/>
+     <item  name="das " length="4"/>
+   </stopwords>
+
+  <!--French-->
+  <stopwords lang="fr">
+     <item  name="le " length="3"/>
+     <item  name="la " length="3"/>
+     <item  name="les " length="4"/>
+     <item  name="un " length="3"/>
+     <item  name="une " length="4"/>
+     <item  name="l'" length="2"/>    
+  </stopwords>
+
+  <!--Italian-->  
+  <stopwords lang="it">
+     <item  name="il " length="3"/>
+     <item  name="lo " length="3"/>
+     <item  name="la " length="3"/>
+     <item  name="gli " length="4"/>
+     <item  name="le " length="3"/>
+     <item  name="un " length="3"/>
+     <item  name="uno " length="4"/>
+     <item  name="una " length="4"/>
+     <item  name="l'" length="2"/>
+     <item  name="un'" length="3"/>
+  </stopwords>
+
+   <!--Galician-->  
+  <stopwords lang="gl">
+     <item  name="o " length="2"/>
+     <item  name="os " length="3"/>
+     <item  name="a " length="2"/>
+     <item  name="as " length="3"/>
+     <item  name="un " length="3"/>
+     <item  name="uns " length="4"/>
+     <item  name="unha " length="5"/>
+     <item  name="unhas " length="6"/>
+   </stopwords> 
+    
+   <recordTypeMapping>
+       <type name="collection" mapping="p"/>
+       <type name="dataset" mapping="m"/>
+       <type name="event" mapping="r"/>
+       <type name="image" mapping="k"/>
+       <type name="interactive resource" mapping="m"/> 
+       <type name="service" mapping="m"/>
+       <type name="software" mapping="m"/>
+       <type name="sound" mapping="i"/>
+       <type name="text" mapping="a"/>      
+    </recordTypeMapping>
+
+    <leader> 
+        <recordLength pos="1" value="00000" />
+       <recordStatus pos="5" value="n" />
+       <recordType pos="6" value="a" />
+       <bibliographiclevel pos="7" value="m" />
+       <controlType pos="8" value=" " />
+       <codingScheme pos="9" value=" " />
+       <indicatorCount pos="10" value="2" />
+       <subfieldCodeCount pos="11" value="2" />
+       <dataBaseAddress pos="12" value="     " />
+       <encodingLevel pos="17" value="3" />
+       <descriptiveCatalogForm pos="18" value="u" />
+       <linkedRecordRequirement pos="19" value=" " />
+       <lpLength pos="20" value="4" />
+       <scpLength pos="21" value="5" />
+       <idLength pos="22" value="0" />
+       <emcpLength pos="23" value="0" />
+    </leader>
+        
+    <controlfield tag="001" value="the value of code 001" required="true" />
+    <controlfield tag="002" value="the value of code 002" required="false"/>
+    <controlfield tag="003" value="the value of code 003" required="true"/>
+    <controlfield tag="004" value="the value of code 004" required="false"/>
+    <controlfield tag="005" value="the value of code 005" required="false"/>
+    <controlfield tag="006" value="the value of code 006" required="false"/>
+    <controlfield tag="008" value="the value of code 008" required="true"/>    
+
+<!--this mapping provides qualified duclin core to the following Marc fields mapping:   
+    024 |a[dc.Identifier]
+    041 |a[dc.Language]   
+ 
+    245 |a[dc.Title]
+    246 |a[dc.Title^alternative]    
+    260 |b[dc.Publisher] |c[dc.Date^issued] |g[dc.Date^created]
+    
+    300 |a[dc.Format^extent] 
+    307 |a[dc.Date^available]     
+    340 |a[dc.Format^medium]
+
+    500 |a[dc.Coverage] 
+    505 |a[dc.Description^tableOfContents]
+    510 |a[dc.Relation^isReferencedBy]
+    513 |b[dc.Coverage^spatial]           
+    518 |a[dc.Date^valid]
+    520 |a[dc.Description]
+    520 |a[dc.Description^abstract]
+    522 |a[dc.Coverage^temporal]
+    538 |a[dc.Relation^requires]
+    540 |a[dc.Rights^accessRights] |b[dc.RightsHolder]
+    540 |a[dc.Rights^license] |b[dc.RightsHolder]
+    540 |a[dc.Rights] |b[dc.RightsHolder]
+    546 |a[dc.Language]
+    583 |d[dc.Date^modified] 
+
+
+    650 |a[dc.Subject]
+    655 |a[dc.Type]
+    
+    720 |a[dc.Contributor] |a[dc.Creator]
+    774 |n[dc.Relation^hasPart]
+    774 |n[dc.Relation^^isPartOf]
+    775 |n[dc.Relation^hasVersion]
+    775 |n[dc.Relation^isVersionOf]
+    776 |n[dc.Relation^hasFormat]
+    776 |n[dc.Relation^isFormatOf]
+    780 |t[dc.Relation^replaces]
+    785 |t[dc.Relation^isReplacedBy]
+    786 |o[dc.Source]
+    787 |o[dc.Relation]    
+
+    856 |q[dc.Format]
+
+ 
+-->
+
+<!-- Contributor -->
+ <MarcField multiple="true" datafield="720" ind1=" " ind2=" ">
+   <subfield code="a" meta="dc.Contributor" punc=","/>
+ </MarcField>
+
+<!--Coverage -->
+  <MarcField multiple="true" datafield="500" ind1=" " ind2=" ">
+     <subfield code="a" meta="dc.Coverage" punc=""/>
+  </MarcField>
+  <MarcField multiple="true" datafield="522" ind1=" " ind2=" ">
+     <subfield code="a" meta="dc.Coverage^temporal" punc=""/>
+  </MarcField>
+  <MarcField multiple="true" datafield="513" ind1=" " ind2=" ">
+     <subfield code="b" meta="dc.Coverage^spatial" punc=""/>
+  </MarcField>
+
+ <!--Creator-->
+ <MarcField  multiple="true"  datafield="720" ind1=" " ind2=" ">
+     <subfield code="a" meta="dc.Creator" punc=","/>
+ </MarcField>   
+
+  <!--Publisher and  Date-->
+   <MarcField  multiple="false" datafield="260" ind1=" " ind2=" ">
+     <subfield code="b" meta="dc.Publisher" punc=","/>
+     <subfield code="c" meta="dc.Date^issued" punc=""/> 
+     <subfield code="g" meta="dc.Date^created" punc=""/>
+   </MarcField>
+
+ <!--Date-->
+    <MarcField  multiple="true"   datafield="307" ind1=" " ind2=" ">
+       <subfield code="a" meta="dc.Date^available" punc=""/> 
+   </MarcField>         
+     
+   <MarcField  multiple="true"   datafield="583" ind1=" " ind2=" ">
+       <subfield code="d" meta="dc.Date^modified" punc=""/> 
+   </MarcField>
+  
+   <MarcField  multiple="true"   datafield="518" ind1=" " ind2=" ">
+       <subfield code="a" meta="dc.Date^valid" punc=""/> 
+   </MarcField>
+
+<!-- Descrption -->
+    <MarcField  multiple="true" datafield="520" ind1=" " ind2=" ">
+       <subfield code="a" meta="dc.Description" punc=""/> 
+    </MarcField>
+
+    <MarcField  multiple="true"  datafield="520" ind1=" " ind2=" ">
+        <subfield code="a" meta="dc.Description^abstract" punc=""/> 
+    </MarcField>
+
+    <MarcField  multiple="true"  datafield="505" ind1="0" ind2=" ">
+       <subfield code="a" meta="dc.Description^tableOfContents" punc=""/>
+    </MarcField>
+
+
+<!--Format -->
+     <MarcField  multiple="true"  datafield="856" ind1=" " ind2=" ">
+       <subfield code="q" meta="dc.Format" punc=""/> 
+    </MarcField>
+    <MarcField  multiple="true"  datafield="300" ind1=" " ind2=" ">
+        <subfield code="a" meta="dc.Format^extent" punc=""/> 
+    </MarcField>
+    <MarcField  multiple="true"  datafield="340" ind1="0" ind2=" ">
+       <subfield code="a" meta="dc.Format^medium" punc=""/>
+    </MarcField>
+
+ <!--Identifier -->
+     <MarcField multiple="true" datafield="024" ind1="8" ind2=" ">
+        <subfield code="b" meta="dc.Identifier" punc=""/>
+     </MarcField>
+
+
+ <!--Language-->
+ <MarcField  multiple="false" datafield="041" ind1=" " ind2=" ">
+     <subfield code="a" meta="dc.Language" punc=""/>
+  </MarcField>
+
+<!-- relation -->
+  <MarcField multiple="true"  datafield="787" ind1="0" ind2=" " >
+      <subfield code="o" meta="dc.Relation" punc=""/>
+  </MarcField>
+
+  <MarcField multiple="true"  datafield="538" ind1=" " ind2=" ">
+        <subfield code="a" meta="dc.Relation^requires" punc=""/>
+  </MarcField>
+
+  <MarcField multiple="true" datafield="510" ind1="0" ind2=" ">
+     <subfield code="a" meta="dc.Relation^isReferencedBy" punc=""/>
+  </MarcField>
+ 
+  <!--no entry in the crosstalk spec
+  <MarcField name="dc.Relation^conformsTo" />
+ -->
+  
+  <MarcField multiple="true" datafield="776" ind1="0" ind2=" ">
+     <subfield code="n" meta="dc.Relation^hasFormat" punc=""/>
+  </MarcField>
+
+  <MarcField multiple="true" datafield="774" ind1="0" ind2=" ">
+     <subfield code="n" meta="dc.Relation^hasPart" punc=""/>
+  </MarcField>
+
+  <MarcField multiple="true" datafield="775" ind1="0" ind2=" ">
+      <subfield code="n" meta="dc.Relation^hasVersion" punc=""/>
+  </MarcField>
+
+ <MarcField multiple="true" datafield="776" ind1="0" ind2=" ">
+     <subfield code="n" meta="dc.Relation^isFormatOf" punc=""/>
+  </MarcField>
+
+  <MarcField multiple="true" datafield="774" ind1="0" ind2=" ">
+     <subfield code="n" meta="dc.Relation^isPartOf" punc=""/>
+  </MarcField>
+
+  <MarcField multiple="true"  datafield="785" ind1="0" ind2="0">
+     <subfield code="t" meta="dc.Relation^isReplacedBy" punc=""/>
+  </MarcField>
+
+ <!--has no entry in crosstalk spec
+   <MarcField name="dc.Relation^isRequiredBy"/>
+ -->
+
+ <MarcField multiple="true" datafield="775" ind1="0" ind2=" ">
+       <subfield code="n" meta="dc.Relation^isVersionOf" punc=""/>
+ </MarcField>
+
+<!--has no entry in crosstalk spec
+      <MarcField name="dc.Relation^references" >
+      </MarcField>
+-->
+
+ <MarcField multiple="true" datafield="780" ind1="0" ind2="0">
+    <subfield code="t" meta="dc.Relation^replaces" punc=""/>
+ </MarcField>
+
+ <!--Rights: additional qualified entries ???-->
+  <MarcField multiple="false"  datafield="540" ind1=" " ind2=" ">
+    <subfield code="a" meta="dc.Rights" punc=""/>
+    <subfield code="b" meta="dc.RightsHolder" punc=""/>
+  </MarcField>
+
+  <MarcField   multiple="false"  datafield="540" ind1=" " ind2=" ">
+    <subfield code="a" meta="dc.Rights^accessRights" punc=""/>
+    <subfield code="b" meta="dc.RightsHolder" punc=""/>
+  </MarcField>
+
+  <MarcField multiple="false" datafield="540" ind1=" " ind2=" ">
+     <subfield code="a" meta="dc.Rights^license" punc=""/>
+     <subfield code="b" meta="dc.RightsHolder" punc=""/>
+  </MarcField>
+
+   <!-- Source -->
+  <MarcField  multiple="true" datafield="786" ind1="0" ind2=" ">
+     <subfield code="o" meta="dc.Source" punc=""/>
+  </MarcField>
+  
+
+ <!--subject-->
+  <MarcField  multiple="true"  datafield="650" ind1=" " ind2="0">
+    <subfield code="a" meta="dc.Subject" punc=" :"/>
+  </MarcField>
+
+<!--Title-->
+  <MarcField  multiple="false" datafield="245" ind1="1" ind2="nonfiling">
+     <subfield code="a" meta="dc.Title" punc=""/>
+  </MarcField>
+ 
+  <MarcField multiple="true" datafield="246" ind1="3" ind2="3">
+    <subfield code="a" meta="dc.Title" punc=""/>
+  </MarcField>
+
+
+  <MarcField multiple="true" datafield="246" ind1="3" ind2="3">
+    <subfield code="a" meta="dc.Title^alternative" punc=""/>
+  </MarcField>
+
+
+ <!-- type -->
+  <MarcField multiple="true" datafield="655" ind1=" " ind2="7">
+     <subfield code="a" meta="dc.Type" punc=""/>
+  </MarcField>
+  
+</Mapping>
Index: /tags/greenstone-3_02-distribution/gsdl/install-sh
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/install-sh	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/install-sh	(revision 13928)
@@ -0,0 +1,238 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+tranformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+	-c) instcmd="$cpprog"
+	    shift
+	    continue;;
+
+	-d) dir_arg=true
+	    shift
+	    continue;;
+
+	-m) chmodcmd="$chmodprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-o) chowncmd="$chownprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-g) chgrpcmd="$chgrpprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-s) stripcmd="$stripprog"
+	    shift
+	    continue;;
+
+	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
+	    shift
+	    continue;;
+
+	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+	    shift
+	    continue;;
+
+	*)  if [ x"$src" = x ]
+	    then
+		src=$1
+	    else
+		# this colon is to work around a 386BSD /bin/sh bug
+		:
+		dst=$1
+	    fi
+	    shift
+	    continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+	echo "install:	no input file specified"
+	exit 1
+else
+	true
+fi
+
+if [ x"$dir_arg" != x ]; then
+	dst=$src
+	src=""
+	
+	if [ -d $dst ]; then
+		instcmd=:
+	else
+		instcmd=mkdir
+	fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+	if [ -f $src -o -d $src ]
+	then
+		true
+	else
+		echo "install:  $src does not exist"
+		exit 1
+	fi
+	
+	if [ x"$dst" = x ]
+	then
+		echo "install:	no destination specified"
+		exit 1
+	else
+		true
+	fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+	if [ -d $dst ]
+	then
+		dst="$dst"/`basename $src`
+	else
+		true
+	fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='	
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+	pathcomp="${pathcomp}${1}"
+	shift
+
+	if [ ! -d "${pathcomp}" ] ;
+        then
+		$mkdirprog "${pathcomp}"
+	else
+		true
+	fi
+
+	pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+	$doit $instcmd $dst &&
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+	if [ x"$transformarg" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		dstfile=`basename $dst $transformbasename | 
+			sed $transformarg`$transformbasename
+	fi
+
+# don't allow the sed command to completely eliminate the filename
+
+	if [ x"$dstfile" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		true
+	fi
+
+# Make a temp file name in the proper directory.
+
+	dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+	$doit $instcmd $src $dsttmp &&
+
+	trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+	$doit $rmcmd -f $dstdir/$dstfile &&
+	$doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
Index: /tags/greenstone-3_02-distribution/gsdl/setup.bash
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl/setup.bash	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl/setup.bash	(revision 13928)
@@ -0,0 +1,183 @@
+# if this file is executed, /bin/sh is used, as we don't start with #!
+# this should work under ash, bash, zsh, ksh, sh style shells.
+gsdllang=""
+# encoding inputs and outputs
+gsdltoenc=""
+gsdlfromenc=""
+
+# see if the shell has any language environment variables set
+# see locale(7) manpage for this ordering.
+if test ! -z "$LC_ALL" ; then
+  gsdllang="$LC_ALL"
+elif test ! -z "$LANG"; then
+  gsdllang="$LANG"
+fi
+
+
+# note... all our output strings have the charset hard-coded, but
+# people may be using a different encoding in their terminal. LANG
+# strings look like "en_NZ.UTF-8".
+
+# Determine the requested output encoding
+case $gsdllang in
+  *.*)
+    gsdltoenc=`echo $gsdllang | sed 's/.*\.//'`
+    ;;
+esac
+
+# Our french and spanish strings are currently in iso-8859-1 encoding.
+case $gsdllang in
+  fr*|FR*)
+    gsdllang=fr
+    gsdlfromenc="iso-8859-1"
+  ;;
+  es*|ES*)
+    gsdllang=es
+    gsdlfromenc="iso-8859-1"
+  ;;
+  ru*|RU*)
+    gsdllang=ru
+    gsdlfromenc="koi8r"
+  ;;
+  *) # default
+    gsdllang=en
+    gsdlfromenc="iso-8859-1"
+  ;;
+esac  
+
+# "iconv" is the program for converting text between encodings.
+gsdliconv=`which iconv 2>/dev/null`
+if test $? -ne 0 || test ! -x "$gsdliconv" || test -z "$gsdlfromenc" || test -z "$gsdltoenc"; then
+# we can't convert encodings from some reason
+  gsdliconv="cat"
+else
+# add the encodings
+  gsdliconv="$gsdliconv -f $gsdlfromenc -t $gsdltoenc"
+fi
+
+# make sure we are sourced, and not run
+
+if test "$0" != "`echo $0 | sed s/setup\.bash//`" ; then
+# if $0 contains "setup.bash" we've been run... $0 is shellname if sourced.
+# One exception is zsh has an option to set it temporarily to the script name
+  if test -z "$ZSH_NAME" ; then
+  # we aren't using zsh
+  gsdl_not_sourced=true
+  fi
+fi
+
+if test -n "$gsdl_not_sourced" ; then
+  case "$gsdllang" in
+ "es")
+eval $gsdliconv <<EOF
+      Error: Asegúrese de compilar este guión, no de ejecutarlo. P. ej.:
+         $ source setup.bash
+      o
+         $ . ./setup.bash
+      no
+         $ ./setup.bash
+EOF
+  ;;
+  "fr")
+eval $gsdliconv <<EOF
+      Erreur: Assurez-vous de "sourcer" le script, plutôt que de l'exécuter. Ex:
+         $ source setup.bash
+      ou
+         $ . ./setup.bash
+      pas
+         $ ./setup.bash
+EOF
+  ;;
+  "ru")
+eval $gsdliconv <<EOF
+      ïÛÉÂËÁ: õÄÏÓÔÏ×ÅÒØÔÅÓØ × ÉÓÔÏÞÎÉËÅ ÜÔÏÇÏ ÓËÒÉÐÔÁ. îÅ ÉÓÐÏÌÎÑÊÔÅ ÅÇÏ.
+      îÁÐÒÉÍÅÒ:
+         $ source setup.bash
+      ÉÌÉ
+         $ . ./setup.bash
+      ÎÅÔ
+         $ ./setup.bash
+EOF
+  ;;
+  *)
+eval $gsdliconv <<EOF
+	Error: Make sure you source this script, not execute it. Eg:
+		$ source setup.bash
+	or
+		$ . ./setup.bash
+	not
+		$ ./setup.bash
+EOF
+  ;;
+  esac
+elif test -n "$GSDLHOME" ; then
+  case "$gsdllang" in
+  "es")
+    echo '¡Su ambiente ya está listo para Greenstone!' | eval $gsdliconv
+  ;;
+  "fr")
+    echo 'Votre environnement est déjà préparé pour Greenstone!' | eval $gsdliconv
+ ;;
+  "ru")
+    echo '÷ÁÛÅ ÏËÒÕÖÅÎÉÅ ÕÖÅ ÎÁÓÔÒÏÅÎÏ ÄÌÑ Greenstone!' | eval $gsdliconv
+  ;;
+  *)
+    echo 'Your environment is already set up for Greenstone!'
+  ;;
+  esac
+elif test ! -f setup.bash ; then
+  case "$gsdllang" in
+    "es")
+eval $gsdliconv <<EOF
+Usted debe compilar el guión desde el interior del directorio de inicio
+de Greenstone.
+EOF
+  ;;
+  "fr")
+echo 'Vous devez trouver la source du script dans le répertoire de base de Greenstone' | eval $gsdliconv
+  ;;
+  "ru")
+eval $gsdliconv <<EOF
+÷ÁÍ ÎÅÏÂÈÏÄÉÍ ÉÓÔÏÞÎÉË ÓËÒÉÐÔÁ ÉÚ ÂÁÚÏ×ÏÊ ÄÉÒÅËÔÏÒÉÉ Greenstone
+EOF
+  ;;
+  *)
+    echo 'You must source the script from within the Greenstone home directory'
+  ;;
+  esac
+else
+  GSDLHOME=`pwd`
+  export GSDLHOME
+  GSDLOS=`uname -s | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+  # check for running bash under cygwin
+  if test "`echo $GSDLOS | sed 's/cygwin//'`" != "$GSDLOS" ;
+  then
+    GSDLOS=windows
+  fi
+  export GSDLOS
+
+  PATH=$PATH:$GSDLHOME/bin/script:$GSDLHOME/bin/$GSDLOS
+  export PATH
+  MANPATH=$MANPATH:$GSDLHOME/packages/mg/man
+  export MANPATH
+  case "$gsdllang" in
+    "es")
+      echo 'Su ambiente ha sido configurado para correr los programas Greenstone.' | eval $gsdliconv
+    ;;
+    "fr")
+      echo 'Votre environnement a été configuére avec succès pour exécuter Greenstone' | eval $gsdliconv
+    ;;
+    "ru")
+eval $gsdliconv <<EOF
+÷ÁÛÅ ÏËÒÕÖÅÎÉÅ ÂÙÌÏ ÕÓÐÅÛÎÏ ÎÁÓÔÒÏÅÎÏ, ÞÔÏÂÙ ÕÓÔÁÎÏ×ÉÔØ Greenstone
+EOF
+    ;;
+    *)
+      echo 'Your environment has successfully been set up to run Greenstone'
+    ;;
+  esac
+fi
+unset gsdl_not_sourced
+unset gsdliconv
+unset gsdlfromenc
+unset gsdltoenc
Index: /tags/greenstone-3_02-distribution/gsdl3/LICENSE.txt
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/LICENSE.txt	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/LICENSE.txt	(revision 13928)
@@ -0,0 +1,350 @@
+Copyright (c) 2003 New Zealand Digital Library Project, University of Waikato
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, and distribute copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the GPL and the following conditions (where not in conflict with the GPL):
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software, as will all other notices contained in the copyrights directory.
+
+THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDER (Greenstone Digital Libraries, University of Waikato), OR THEIR STAFF BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of New Zealand Digital Library Project, University of Waikato shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the New Zealand Digital Library Project, University of Waikato. Distributed under GPL, as follows: 
+
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program 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 for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: /tags/greenstone-3_02-distribution/gsdl3/README-CVS.txt
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/README-CVS.txt	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/README-CVS.txt	(revision 13928)
@@ -0,0 +1,94 @@
+Greenstone 3 (GSDL3)
+Copyright (C) 2003 New Zealand Digital Libraries, University Of Waikato
+Greenstone3 comes with ABSOLUTELY NO WARRANTY; for details see LICENSE.txt
+This is free software, and you are welcome to redistribute it
+
+These are some extra notes for installing Greenstone from CVS. Please also read the README.txt file for general information as almost all of that applies here too.
+
+Installing Greenstone from a CVS checkout:
+---------------------------------------------------------------------
+
+Make sure the CVS executable is on your PATH.
+
+Checkout the code:
+
+cvs -d :pserver:cvs_anon@cvs.scms.waikato.ac.nz:2402/usr/local/global-cvs/gsdl-src co greenstone3
+
+Build and install:
+
+In the greenstone3 directory, edit the build.properties file (see 'Configuring your installation' in README.txt), and run 'ant prepare install'. The two targets can be run separately if you like.
+
+The 'prepare' target will download additional code (using CVS and http), so you need to be online to run it. The 'install' target can be run offline.
+
+The prepare/install targets will ask you if you accept the properties before starting.
+To suppress this prompt, use the -Dproperties.accepted=yes flag. E.g.
+ant -Dproperties.accepted=yes prepare install (from CVS), or
+To log the output, run
+ant -Dproperties.accepted=yes -logfile build.log prepare install (from CVS), or
+
+Extra Configuration notes:
+--------------------------------------------------------------
+
+Greenstone 3 uses some parts of Greenstone 2 for collection building, 
+including external packages and the Librarian Interface. These will be 
+installed during the Greenstone 3 installation process. If you do not want 
+collection building capability, please set the disable.collection.building property to true in build.properties. 
+
+
+Common install/update targets:
+---------------------------------------------------------------------
+1. Install for the first time from CVS:
+cvs co greenstone3
+cd greenstone3
+ant prepare install
+
+2. Install for the first time from CVS, mostly offline:
+[online]
+cvs co greenstone3
+cd greenstone3
+ant prepare
+[offline]
+ant install
+
+3. Install for the first time, with CVS done outside of Ant (if you have problems running CVS commands from Ant):
+cvs co -P greenstone3
+cd greenstone3
+[if you want collection building:
+cvs co -P gli
+cvs co -P gs2build
+]
+[if you didn't want collection building
+cd src/packages
+cvs co indexers
+cd ../../
+]
+[if you are on windows
+cvs co winbin
+]
+ant -Dnocvs.mode=yes prepare install (prepare needs to be online, install can be done offline)
+
+4. Updating your Greenstone installation from CVS (and reconfigure/recompile):
+cd greenstone3
+ant update
+
+5. Updating your Greenstone installation from CVS, offline:
+cd greenstone3
+[online]
+ant cvsupdate
+[offline]
+ant -Dnocvs.mode=yes update
+
+6. Updating your Greenstone installation, with CVS done outside of Ant:
+cd greenstone3
+cvs update -l
+cvs update -dP bin docs lib resources src winutil packages 
+cd web (or the path-to-tomcat/webapps/greenstone3 if have installed greenstone as a webapp in Tomcat, see Using External Tomcat section)
+cvs update -dP 
+cd ../
+[ if you have greenstone 2 building:
+cvs update -dP gli
+cvs checkout -P gs2build
+Note that the gs2build one uses checkout not update.
+]
+ant -Dnocvs.mode=yes update
+
Index: /tags/greenstone-3_02-distribution/gsdl3/README.txt
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/README.txt	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/README.txt	(revision 13928)
@@ -0,0 +1,227 @@
+Greenstone 3 (GSDL3)
+Copyright (C) 2003 New Zealand Digital Libraries, University Of Waikato
+Greenstone3 comes with ABSOLUTELY NO WARRANTY; for details see LICENSE.txt
+This is free software, and you are welcome to redistribute it
+
+You will need Java and Ant to run Greenstone 3. 
+
+Your Java version should be 1.4 or higher. We recommend Sun Java. You need the SDK (development environment). Set the environment variable JAVA_HOME to be the root of your Java installation.
+
+Ant (Apache's Java based build tool) can be downloaded from http://ant.apache.org/bindownload.cgi. Set the environment variable ANT_HOME to be the root of your Ant installation, and make sure the Ant executables are on your PATH. You may have problems with earlier versions. This has been tested with version 1.6.2
+
+In the greenstone3 directory, you can run 'ant' which will give you a help message.
+Running 'ant -projecthelp' gives a list of the targets that you can run - these
+do various things like compile the source code, start up the server etc.
+
+Installing Greenstone
+---------------------------------------------------------
+
+Download the appropriate installer from sourceforge.net/projects/greenstone3 and run it. 
+
+See 'Installing from a Source Distribution' section below for extra notes about installing from Source.
+
+See the README-CVS.txt file for extra notes about installing from CVS.
+
+Running Greenstone:
+---------------------------------------------------------
+
+To start up Greenstone, select Greenstone 2 Digital Library from the Start menu (Windows), or run gs3-server.sh/bat. This launches a small server program, which starts up Tomcat and launches a browser. A small window pops up which allows you to chnage some settings for your library and restart the Tomcat server. Closing this program will stop Tomcat running.
+
+Alternatively, you can start Tomcat directly through using Ant. 'ant start', 'ant restart' and 'ant stop' starts, restarts and shuts down Tomcat, respectively. This will only start/stop a local server (one installed by Greenstone). You will need to manually start/stop an external Tomcat (see below for notes about using a version of Tomcat external to Greenstone).
+
+Once the Tomcat server is running, Greenstone will be available in a browser at "http://localhost:8080/greenstone3" (or whatever port you specified during the 
+installation process).
+You can change the port number using File->Settings in the server program, or by changing the 'tomcat.port' property in build.properties, then running 'ant configure'.
+
+Building Collections:
+----------------------------------------------------------
+
+You need to have Perl installed and on your PATH. Perl is included as part of 
+the Windows binary distribution.
+run  'ant gli", or cd to greenstone3/gli and run gli4gs3.sh/bat. This is a 
+graphical tool for building collections. Once you have created and built a 
+collection, you can see it by clicking 'Preview collection' on the Build panel.
+
+Note that GLI doesn't start up the Greenstone Tomcat server so you should 
+run 'ant start' before previewing your collection.
+
+
+Greenstone Admin
+------------------------------------------------------
+
+The Greenstone admin tool is currently under development.
+
+Using SOAP:
+-------------------------------------------------------
+
+Greenstone comes with Apache Axis installed as part of the Greenstone web application. However, no SOAP services are deployed by default.
+
+To deploy a SOAP server for localsite, run 'ant deploy-localsite'. You should now be able to see all localsite's collections through the gateway servlet. (http://localhost:8080/greenstone3/gateway)
+
+To set up a SOAP server on a new site, run
+ant soap-deploy-site
+This will prompt you for the sitename (the directory name), and the site uri - this should be a unique identifier for the site's web service. 
+
+For a non-interactive version, run
+ant -Daxis.sitename=xxx -Daxis.siteuri=yyy soap-deploy-site
+
+The service is accessible at http://localhost:8080/greenstone3/services/<siteuri>
+(or http://<computer-web-address>:<port>/greenstone3/services/<siteuri>)
+
+Note: Deploying a SOAP service for any site other than localsite requires the Greenstone source code to be installed. This is not installed by default for a binary distribution. To get the source code, re-run the installer, select custom install and deselect everything except the source code.
+
+Using External Tomcat:
+---------------------------------------------------
+
+If you want to use an existing Tomcat, set the path to its base directory
+in build.properties (tomcat.installed.path). Also set the tomcat.port property to be the port you are running Tomcat on, and change tomcat.server if the web address is not localhost. Then run 'ant configure'.
+
+ You will need to modify the Tomcat setup slightly.
+
+1. Tell Tomcat about the Greenstone web app. There are two ways to do this.
+
+A. Copy the file greenstone3/resources/tomcat/greenstone3.xml into Tomcat's conf/Catalina/localhost directory. You'll need to edit the file and replace @gsdl3webhome@ with the full path to the web directory of your greenstone 3 installation. Any path separator is fine here ('/', '\\', '\').
+
+B. Alternatively, you can move (and rename) the greenstone3/web directory to tomcat/webapps/greenstone3 (i.e. the resulting directories will be like
+tomcat/webapps/greenstone3/WEB-INF, no web directory). This should be done after running the initial 'ant install'.
+
+You will need to set the web.home property in the build.properties file
+i.e.
+web.home=${tomcat.installed.path}/webapps/greenstone3
+And then run 'ant configure' to reset gsdl3home.
+
+2. Set up the JNI libraries and Java wrappers.
+JNI libraries and their Java wrappers cannot go into the web app. The libraries need to be loaded by the same class loader as their wrappers. The libraries need to be in java.library.path, and I think get loaded by the system class loader.
+The wrappers need to be loaded by this too. 
+
+These JNI bits are located by default in the lib/jni directory. There are two ways to get them into Tomcat:
+A: Keep all the Greenstone stuff inside the greenstone3 directory, and just modify the environment that Tomcat runs in
+
+Set LD_LIBRARY_PATH (GNU/Linux), DYLD_LIBRARY_PATH (Mac OS X) or PATH/Path (windows) to include the  greenstone3/lib/jni directory.
+Add all the jar files in greenstone3/lib/jni directory to the CLASSPATH, then edit tomcats setclasspath.sh/bat to use the system CLASSPATH.
+(in setclasspath.bat, change 
+set CLASSPATH=%JAVA_HOME%\lib\tools.jar
+to 
+set CLASSPATH=%JAVA_HOME%\lib\tools.jar;%CLASSPATH%
+
+in setclasspath.sh, change
+# Set standard CLASSPATH
+if [ "$1" = "debug" -o "$1" = "javac" ] ; then
+  CLASSPATH="$JAVA_HOME"/lib/tools.jar
+fi
+
+to
+# Set standard CLASSPATH
+if [ "$1" = "debug" -o "$1" = "javac" ] ; then
+  CLASSPATH="$JAVA_HOME"/lib/tools.jar:"$CLASSPATH"
+fi
+
+
+B: Copy the files into Tomcat installation:
+Move the greenstone3/lib/jni jar files into tomcat's shared/lib directory.
+Move the greenstone3/lib/jni library files (.so for GNU/Linux, .jnilib for Mac OS X .dll for Windows) into shared/classes, and set LD_LIBARARY_PATH (GNU/Linux), DYLD_LIBRARY_PATH (Mac OS X) or PATH/Path (Windows) to include this directory.
+ This has the advantage that you can use this for other webapps without modifying the Tomcat environment.
+
+Once all these changes have been made, you will need to restart the Tomcat server for them to take effect.
+
+
+Notes for Mac OS
+------------------------------------------------
+
+Set JAVA_HOME to be /Library/Java/Home
+
+Notes for Windows
+-----------------------------------------------
+
+You can set environment variables by going to Control Panel->System->Advanced->Environment Variables. 
+
+Installing from a Source Distribution
+----------------------------------------------
+
+Download the greenstone-3.xx-src.tar.gz package from sourceforge.net/projects/greenstone3, and unpack it.
+In the greenstone3 directory, edit the build.properties file and run 
+ant prepare install
+
+Tomcat will be installed as part of the prepare process. To stop this set the tomcat.installed.path to be the root of an existing Tomcat installation. 
+
+* Solaris notes:
+** Make sure /usr/local/bin is in your PATH ahead of /usr/bin etc.
+** Add /usr/local/lib to LD_LIBARY_PATH
+** The gdbm database files (gs2mgdemo and gs2mgppdemo collections) were generated on a Mac, and don't seem to be compatible with Solaris. A text version of the file (database.txt) is included in the index/text directory. After installing Greenstone, and before running it, you'll need to:
+in greenstone3/gs2build directory: run 'source setup.bash' (Or if you have greenstone 2 already installed, run 'source setup.bash' in your greenstone 2 installation)
+in greenstone3/web/sites/localsite/collect/gs2mgdemo/index/text directories, run 'txt2db gs2mgdemo.bdb < database.txt'
+in greenstone3/web/sites/localsite/collect/gs2mgppdemo/index/text directories, run 'txt2db gs2mgppdemo.bdb < database.txt'
+** GLI shell scripts may not work like "./gli4gs3.sh". In this case, run "bash ./gli4gs3.sh" etc. You will need to compile GLI by hand (run "bash ./makegli.sh" in greenstone3/gli directory).
+** Set CC=gcc environment variable if you don't have cc, before running ant install.
+
+* Windows notes:
+** You need to have Visual Studio installed to compile the C/C++ code. Set the path to the setup file in build.properties (compile.windows.c++.setup).
+
+Configuring your installation:
+--------------------------------------------------------
+
+The file build.properties contains various parameters that can be set by the user. Please check these settings before running the install.
+Note, either forward slash '/' or double backslash '\\' can be used as path separators in the build.properties file, but not single backslash '\'. 
+
+Greenstone 3 comes with Tomcat bundled in.  
+
+If you already have Tomcat running, you can set the 'tomcat.installed.path' property (in build.properties) to the base directory of your Tomcat installation, and Greenstone will not use its own Tomcat. (You can delete the packages/tomcat directory if you like.) Please read the section "Using External Tomcat" for details about how to configure Tomcat for Greenstone.
+
+Mac OS X: You need to have GDBM installed (http://www.gnu.org/software/gdbm/gdbm.html). Please set the gdbm.installed.path property (in build.properties) to the root of your gdbm installation if it is not installed in a default place. If you run GLI or GS2 collection building from the command line, you will need to set the DYLD_LIBRARY_PATH environment variable to include <path-to-gdbm>/lib.
+
+The install target will ask you if you accept the properties before starting.
+To suppress this prompt, use the -Dproperties.accepted=yes flag. E.g.
+ant -Dproperties.accepted=yes install 
+
+To log the output in build.log, run
+ant -Dproperties.accepted=yes -logfile build.log  install 
+
+Recompiling
+-------------------------------------------------------
+To recompile your Greenstone3 installation, in the top level greenstone3 directory, run:
+
+ant configure
+ant configure-c++
+ant clean
+ant compile
+
+The compile target does Java and C/C++ compilation. On Windows, you need to set the compile.windows.c++.setup property to be your Visual Studio setup batch file. 
+
+Any sub targets can be run by themselves. Run 'ant -projecthelp' for a list of public targets, otherwise you can look at the build.xml file to see which targets depend on other ones.
+
+
+Notes on Versions of Third Party packages
+-----------------------------------------------
+
+Tomcat:
+
+apache-tomcat-5.5.12.zip: latest production quality release as of October, 2005.
+apache-tomcat-5.5.12-compat.zip: Tomcat 5 requires Java 1.5. If using Java 1.4, need to use this compatibility module.
+
+website: http://tomcat.apache.org/
+download: http://tomcat.apache.org/download-55.cgi
+
+Axis:
+
+Apache Web Services Project, SOAP implementation. Axis is a follow on project to Apache SOAP
+
+axis-bin-1_2_1.zip: latest stable release as of October, 2005
+website: http://ws.apache.org/axis/
+download: http://www.apache.org/dyn/closer.cgi/ws/axis/1_2_1
+
+All available from www.greenstone.org/gs3files if not available at their respective websites.
+
+Other Notes:
+-------------------------------------------------
+
+See greenstone3/docs/manual/manual.pdf for more details about the software and installation etc.
+
+Output is logged to web/logs. usage.log is a usage log, while greenstone.log is the error/message log. To change the level of logging, edit the web/WEB-INF/classes/log4j.properties file, and change the log4j.disable property. Valid values are TRACE, DEBUG, INFO, WARN, ERROR and FATAL.
+
+To prevent Tomcat showing directory listings, edit Tomcat's conf/web.xml file and set the value of the "listings" servlet parameter to false.
+
+To enable symlinks to files outside the webapp root directory, edit Tomcat's conf/Catalina/localhost/greenstone3.xml file, and set the allowLinking attribute in the Context element to true.
+(Note from Tomcat website: This flag MUST NOT be set to true on the Windows platform (or any other OS which does not have a case sensitive filesystem), as it will disable case sensitivity checks, allowing JSP source code disclosure, among other security problems.)
+
+The file web/WEB-INF/classes/global.properties is generated on install and contains some properties for the run time system.
+
Index: /tags/greenstone-3_02-distribution/gsdl3/TODO.txt
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/TODO.txt	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/TODO.txt	(revision 13928)
@@ -0,0 +1,306 @@
+my specific todo list. in no particular order. smallish  jobs.
+
+* nzdl.org mirror presentation - from ian
+ replace macros
+ horizontal list -> first item should be selected
+ expand text, detach page buttons
+ remove unneccesary blank lines
+ how to in hdl - the entries are double spaced and also vertical lists
+ remove \n in config files
+ the image under the about/search etc titles is funny under macs
+ change font if language english/european??
+ rollover background for buttons and nav bar
+
+* get computer ggraphic design people to give input?? dave N matt J, polly cantlon ??
+
+* self documenting collections?? eg provides links to the source of the  class files , the xslt , the config file etc everything needed to generate teh coll/page 
+ 
+* UPDATE DOCUMENTATION!!!!
+
+* text on nzdl query page to resource bundle
+
+* collection getMetadata service
+
+* rethink how we determine docType - current method doesn't work for phind cos it only gets doc ids - it should come from the document if not specified.
+
+* niupepa display - abstract and commentary links. new action? or just new xslt?
+
+* is the 'to' att compulsory? do we have to have to=""?
+
+* query info - eg num docs found from a search, query term info - 
+is this called metadata for the query and returned in a metadataList? or 
+should it have another name?
+
+<response>
+<metadataList>
+<metadata name="numDocs">55</metadata>
+<content>
+<document name="HASHxxx"/>
+...
+</content>
+</response>
+
+????
+
+* format statements - need to add If and Or. do we test only on metadata? <gsf:if test="Title"> and <gsf:if test="Title='snail farming'> or more sophisticated?
+also need to fix the bit where <a href='[URL]'> gets turned into <a href='<gsf:metadata name='URL'/> - needs to be added as an attribute.
+
+* format statements for doc display
+
+* including named templates - need to replace the ones they overwrite - not allowed two templates with teh same name. eg docHeading, docContent. or should they be match=document mode=heading/content ??
+
+* coll specific xslt/actions?? how get these for remote colls?
+
+* process messages - do we still have pid and handle atts? make them the same, and both atts instead of params??
+
+* equivTermList contains terms
+
+* page link style paging eg 1, 2, 3, .... can have links to all, links to same eg 5 either side of current page. 1,2,3...24,25,26,27,28...231
+
+* multi query - finish.
+ 1. check if coll specified.
+ 2. check if ccs coll specified.
+ 3. get background info (description and format) for current coll - or all colls?? will we format stuff differently for different colls? have templates based on collection??
+ 4. do the query over all colls.
+ 5. get metadata for each result from appropriate coll.
+ 6. merge the results - append initially. sort by rank? this means we need to return the rank.
+
+* metadata retrieve determination - use an action helper? separate class? should look at xslt as well as format statements? 
+
+* what if have two services with teh same name eg two phind applets
+
+* phind applet not working at the moment. why??
+
+* tei building stuff into gsdl3 build code.
+
+* subcollection/language handling for gs2 collections
+
+* datelists formatted nicely with years at top and months down the side.
+
+* on/off format stuff in config file eg query term highlighting, display cover image and toc, offer enriching services to user, buttons, 
+
+* different templates for different positions in the hierarchy??
+X
+ ---
+   ~~~~
+   ~~~~
+ ---
+   ~~~~
+   ~~~~
+X
+ ---
+
+etc can we test for that? gs2 tests for [parent:Title]
+
+* global resource bundles, not class named ones. getGlobalText? getTExt(key, bundle name)?
+
+* fix errors in javadoc make
+
+* send back error messages to user? rather than getting null pointer exceptions. eg if ask for non-existant metadata. also invalid syntax info?
+
+* tidy up phind error messages
+
+* check text strings in code and xslt - put all into resource bundles
+
+* finalise the nzdl interface, and write script to do teh translations from the macro files.
+
+* query results: 7 out of 10 matches
+
+* bibliographic display??
+
+* look at what assumptions OID makes about ids - need it to be general not just working for hash ids.
+
+* specific tool tips for images. alt/title. eg this file is 380Mb.
+
+* nzdl prefs page - where do the defaults come from? do we need a full cgiargs class? with default value? nzdl, we already know what query options there are so dont need to get them from the service, so dont have displayinfo or default.
+
+* proper query term highlighting. phrases. fast.
+
+* system requests shouls also return status id not just a message. like the build stuff. 
+
+* should preferences be carried over between collections? currently they are.
+
+* xslt assumes that something is saving the query args. is this ok?
+
+* nzdl query mode - some/all, boolean/ranked, ranked/natural. result in different query parsing. new queryaction??
+
+* should actions have access to config? currently only applet actionactually uses it. - used for filling in library  - should receptionist do this instead?
+
+* should actions tell recepitonist if they need metadata? should receptionist pass in a list of metadata that the xslt requires?
+
+* polling for collections? delete and start again? check dates and only reload new ones?
+
+* caching. LInkedHashMap. overwrite the removeEldestEntry bits.
+
+* macros in coll description and titles. eg this collection was built _date_ days ago and contains _numdocs_ documents. 
+niupepa titles "_vol_1, _num_ 2" _commentary_
+
+*dynamic query content as well as dynamic query params?
+
+*communicators: 2 modes. 1 relays messages eg to a remote service
+2. site to site - needs to modify addresses and names.
+
+* make sure mgpp colls work with new config file stuff
+
+* presentation prefs - how do we decide on the list of langs? from interface config file? how do we use encoding?
+
+* mg/mgpp errors should not crash the servlet. 
+
+* some stuff for actions can go in config files. metadata determination, query term highlighting, enrich services. result pre or post processing. is there a generic way?
+
+* do we want a 'link to external page' action that displays the page but with teh greenstone header? a=p&sa=external?? also what about displaying whole cached html pages as frames??  gsdl uses a nav frame (a=p&p=nav) and then a second frame which is the html page.
+
+* doc ranking
+
+* generic multi query. a=q&c=demo&ccs=fao,... use a base coll??
+
+* what to do when config file says : {If}{[parent:Title],[parent:Title],[Title]}. maybe we need to do root_or_self type thing?? or have some way of testing.
+
+* stuff from talking to ian - I am sure that I have typed this in already - where is it????
+
+ macros in gdbm db - turn them into real text.
+horizontal list - first item should be selected
+expand text, detach page etc buttons.
+remove extraneous blank lines eg under nav bar
+how to in hdl is double spaced - shouldn't be
+and vertical lists appear to have more space
+remove \n from config files
+on the mac, about image looks weird - the green bar is on teh wrong side
+change font if language is english or european?? san serif font
+rollover background or colour on nav bar and buttons
+
+get meeting with computer design person, dave N, matt J? Polly cantlon?? colours, any quick hints?
+
+self documenting collections: eg links to config file, service code, xslt files,automatically generate but also can provide manually if wish.
+
+cstr browse format statement.
+turn off cover images
+
+Release: present existing gs2 colls
+ skeleton build for eg text and html.
+documentation
+scrap the collector?? ask the group
+release README: how to build a collection - gs2+convert? basic gs3?
+EASY installation
+consolidate and document
+adhoc testing
+translation of resource bundles
+
+help page: type in gsf:format statemenets and it shows you xslt? or html?
+
+test protocol - sample thing that could generate every message?? 
+
+
+
+General todo list. in no particular order. large  jobs.
+
+* gs3 release - basic stuff, translations, installation, documentation. oct 31? gs2 building only, both default and nzdl interfaces? gatherer?
+
+* generic resource retrieval - associated documents, src docs eg pdf/word, niupepa image files etc. if http accessible, put a link otherwise use a general resource retrieve?
+
+* collector collection building - do we want to finish this? needs addDocument and configureCollection services.
+
+The addDocument service (in GS2Construct) has not been implemented. It should take a file name and add the document to the import directory of teh collection.
+there are problems with just transmitting a file name - the service may live remotely and therefore the document is not there. You should probably send it attached to the html - therefore need to work out:
+how to get the document attached to the form (theres something to do with post and encoding = multipart ?? otherwise the browser just sends the filename),
+and then where to get it in the servlet - is it a parameter? or something else?
+
+and then it needs to be added into the xml request to be passed to the service.
+
+If the program is running locally its much simpler just to send a filename - can we somehow check for this?
+
+* configure Collection for building
+
+also to do with building, a little harder, is the ConfigureCollection service. There is no stub for it yet, but easy enough to add one. - need to add this service to the service description xml stuff, and write a processConfigureColleciton() method.  It would be easy enough to display the config file in a big text box, and have the user edit it like the collector does.
+
+the hard bit is that when you click ConfigureCollection, you dont know what collection you are going to be dealing with - all the building services, you select the collection on the service page. with the configure stuff, you need to select the collection, and then the config file needs to be retrieved. so its really a two step process to configure the coll - first select the coll, submit that, then edit the config file, and submit that.
+
+All the services currently are one step - need to think about how this type of service fits into the model.
+
+maybe it needs a hidden arg? - to tell teh service if you're at stage 1 or 2?
+when teh action does the request, it then asks for the service description again to redisplay it for the user. maybe if the service knows that it has done the first half, it sends the second type of description?
+
+also do we use the collect.cfg file or the collectionConfig.xml file to show the user?
+
+* sequence of services
+
+some service clusters  have services that you are supposed to carry out in sequence such as building, but there may be others.
+
+can we do a generic action or xslt or something that sends teh user to teh next service once they've completed the first one? 
+
+Maybe the service cluster/serviceRack class specifies teh sequence of services, and they are all handled individually like present except that some xslt puts a next button on each page with a link to teh next service in the list.
+
+* proper install package
+
+* currently nothing is cached - service decriptions, text strings etc could all be cached. (cgi args are cached by tomcat)
+
+* document structure - new greenstone archive format? TEI, XHTML, OO, GML compatible? parallel document structures?
+  - associated resources/documents - xlinks
+
+* greenstone 3 building - is building going to change for gs3, or will we continue to use the perl scripts? 
+  - import, build, activate
+  - info extraction, augmentation
+  - incremental update?
+  - modular? xml pipeline?
+
+* additional services - music search
+		      - keyphrase stuff
+		      - search history
+
+* all the gs2 admin/security stuff - user management, authentication
+
+* server side threading issues - is it thread safe?
+
+* usage logs
+
+* better error handling
+
+* document version control
+
+* combining requests to MR - results from first one becoming content for second one??
+
+* language translation stuff - when translating, we want to click on a text piece or macro and go to a sample page with that text string in it. can we do this?
+
+can we tell in gs3 where bits will be in pages?
+I think we could have a new type of request, that provides a page containing all teh text strings used by a service/agent. - would it be class specific or service specific?
+eg it would contain the service form, some sample results, and if its a process type of thing, all teh possible error and success messages.
+
+what about the interface bits?
+
+* are message formats fixed? can we create a DTD? or will they evolve too much over time?
+
+* sitewide service agents - may want to specify that only some of the services that could potentially be provided by an agent are actually provided.
+
+* should actions respond to describe requests? and what would they say if they did? are they agents and part of teh system, or somehow outside the system? 
+
+*  what about soap? is there a new version of that?
+
+* combined query services - eg one page with two service forms on there eg text query and music query - need to combine the results. eg teh action could carry out both queries then use xslt to combine the results.
+
+or do the same thing across title and creator indexes in mg to approximate fielded searching?
+
+true cross collection search would probably need a new service??
+
+* more generally, combining services in general, action and service level
+
+* action helpers: query term highlighting, page transformation and metadata determination (remove from receptionist?)
+* if leave an applet page you lose all teh previous info eg for the status display for importing. need a function to retrieve again all the previous messages to redisplay them.
+
+* can the xslt dynamically retrieve the metadata it needs for say query results??
+
+* CSS instead of tables? - use html lists than use css to format them.
+
+* cross coll search - if colls are built the same, just present the form and search both. need to think about ranking.
+if colls are not built the same, and have indexes, subcolls, langs - do we merge the lists? and only search those that have the right ones? what if two indexes have different meanings and display text but the same id? are they treated as same index? which name do you display?
+what about colls with different levels eg oneonly has document, the other doc and section. what do you display? field lists? just combine?
+
+* search history
+
+* use objects instead of applets? java provides a conversion tool. NPX_PLUGIN_PATH=
+
+* danas combined search and browse stuff
+
+* can xslt be used to generate requests as well as transform teh output?
+
+* kea.
+
Index: /tags/greenstone-3_02-distribution/gsdl3/bin/script/ConstructCollection
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/bin/script/ConstructCollection	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/bin/script/ConstructCollection	(revision 13928)
@@ -0,0 +1,30 @@
+#!/bin/sh
+echo "Constructing collections ..."
+ 
+if [ "x$GSDLHOME" = "x" ] ; then
+  echo "You must have GSDLHOME set for building to work"
+  exit
+fi
+ 
+if [ "x$GSDL3HOME" = "x" ] ; then
+  echo "You must have GSDL3HOME set for building to work"
+  exit
+fi
+ 
+if [ "x$GSDLOS" = "x" ] ; then
+  echo "You must have GSDLOS set for building to work"
+  exit
+fi
+ 
+
+# -Xms32M          To set minimum memory
+# -Xmx32M          To set maximum memory
+# -verbose:gc      To set garbage collection messages
+# -Xincgc          For incremental garbage collection
+# -Xprof           Function call profiling
+# -Xloggc:<file>   Write garbage collection log
+ 
+echo "running java -DGSDLHOME=$GSDLHOME -DGSDLOS=$GSDLOS -DGSDL3HOME=$GSDL3HOME -DPATH=$PATH org.greenstone.gsdl3.build.ConstructCollection  $*"
+java -DGSDLHOME=$GSDLHOME -DGSDLOS=$GSDLOS -DGSDL3HOME=$GSDL3HOME -DPATH=$PATH org.greenstone.gsdl3.build.ConstructCollection  $*
+ 
+echo "Done!"
Index: /tags/greenstone-3_02-distribution/gsdl3/bin/script/convert_coll_from_gs2.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/bin/script/convert_coll_from_gs2.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/bin/script/convert_coll_from_gs2.pl	(revision 13928)
@@ -0,0 +1,758 @@
+#!/usr/bin/perl -w
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDL3HOME not set\n" unless defined $ENV{'GSDL3HOME'};
+    die "GSDL3SRCHOME not set\n" unless defined $ENV{'GSDL3SRCHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+    unshift (@INC, "$ENV{'GSDL3SRCHOME'}/lib/perl/cpan");
+}
+
+use colcfg;
+use util;
+use parsargv;
+use FileHandle;
+use XML::Writer;
+#can't get this to work on windows
+#use GDBM_File;
+
+use strict;
+
+&main();
+sub print_usage() {
+    print STDOUT "Usage: convert_coll_from_gs2.pl [options] coll-name\n";
+    print STDOUT "options:\n";
+    
+    print STDOUT "   -collectdir         Directory where collection lives.\n";
+    print STDOUT "   -verbosity          Controls the amount of output.\n";
+    print STDOUT "   -defaultlang        The language that is considered the default (for display text etc). defaults to 'en'\n\n";
+}
+
+
+sub main {
+
+    my ($defaultlang, $verbosity, $collectdir);
+    # note that no defaults are passed for most options as they're set
+    # later (after we check the collect.cfg file)
+    if (!&parsargv::parse(\@ARGV,
+			  'verbosity/\d+/', \$verbosity,
+			  'collectdir/.*/', \$collectdir,
+			  'defaultlang/.*/', \$defaultlang)) {
+	&print_usage();
+	die "\n";
+    }
+
+    # get and check the collection name
+    my ($collection) = @ARGV;
+    if (!defined($collection) || $collection eq "") {
+	die "No collection specified\n";
+    }
+    if ($collection eq "gs2model") {
+	die "You cant convert the model collection\n";
+    }
+    
+    if (!defined $collectdir || $collectdir eq "") {
+	$collectdir = &util::filename_cat ($ENV{'GSDLHOME'}, "collect");
+    }
+
+    if (!defined $defaultlang || $defaultlang eq "") {
+	$defaultlang = 'en';
+    }
+    # add on the coll name
+    $collectdir = &util::filename_cat ($collectdir, $collection);
+    
+    my $collconfigfilename = &util::filename_cat ($collectdir, "etc", "collect.cfg");
+    print STDOUT "coll config=$collconfigfilename\n";
+    my $collectcfg;
+    if (-e $collconfigfilename) {
+	$collectcfg = &colcfg::read_collect_cfg ($collconfigfilename);
+
+    } else {
+	print STDERR "collect.cfg not found!!";
+	die "\n";
+    }
+    
+
+    my $buildconfigfilename = &util::filename_cat ($collectdir, "index", "build.cfg");
+    my $buildcfg;
+    if (-e $buildconfigfilename) {
+	$buildcfg = &colcfg::read_build_cfg ($buildconfigfilename);
+
+    } else {
+	print STDERR "build.cfg not found!!";
+	die "\n";
+    }
+    
+
+     
+    my $colloutfile = &util::filename_cat ($collectdir, "etc", "collectionConfig.xml");
+    if (-e $colloutfile) {
+	print STDOUT "collectionConfig file already exists! overwriting it!\n";
+	
+    }
+   
+    my $buildoutfile = &util::filename_cat ($collectdir, "index", "buildConfig.xml");
+    if (-e $buildoutfile) {
+	print STDOUT "buildConfig file already exists! overwriting it!\n";
+	
+    }
+
+#    my $db_file = &util::filename_cat ($collectdir, "index", "text", "$collection.ldb");
+    my $database;
+#    if (-e $db_file) {
+#	$database = &open_database($db_file);
+#    } else {
+#	print STDERR "gdbm database file $db_file not found!!";
+#	die "\n";
+#    }
+    
+    my $buildtype;
+    if (defined $buildcfg->{'buildtype'}) {
+	$buildtype = $buildcfg->{'buildtype'};
+    } else {
+	$buildtype = 'mg';
+    }
+    
+    my $indexstem = undef;
+    if (defined $buildcfg->{'indexstem'}) {
+	$indexstem = $buildcfg->{'indexstem'};
+    }
+
+    my $buildoutput = new IO::File(">$buildoutfile");
+    my $buildwriter = new XML::Writer(OUTPUT => $buildoutput, NEWLINES => 1);
+    
+    $buildwriter->startTag('buildConfig', 'xmlns:gsf'=>"http://www.greenstone.org/greenstone3/schema/ConfigFormat");
+    
+    my $colloutput = new IO::File(">$colloutfile");
+    my $collwriter = new XML::Writer(OUTPUT => $colloutput, NEWLINES => 1);
+    
+    $collwriter->startTag('collectionConfig', 'xmlns:gsf'=>"http://www.greenstone.org/greenstone3/schema/ConfigFormat", 'xmlns:xsl'=>'http://www.w3.org/1999/XSL/Transform');
+    
+    #output the collection metadata to the collectionConfig file
+    $collwriter->startTag('metadataList');
+    
+    my $creator = $collectcfg->{'creator'};
+    &output_metadata($collwriter, 'creator', $creator);
+    my $public =$collectcfg->{'public'};
+    &output_metadata($collwriter, 'public', $public);
+    $collwriter->endTag('metadataList');
+
+    #output the display collectionmeta to collectionConfig.xml
+    
+    my $collectionmeta = $collectcfg->{'collectionmeta'};
+    if (defined $collectionmeta) {
+	my %name_map = ('collectionname', 'name',
+		     'collectionextra', 'description',
+		     'iconcollection', 'icon',
+		     'iconcollectionsmall', 'smallicon');
+	
+	$collwriter->startTag('displayItemList');
+	foreach my $entry ( keys %$collectionmeta) {
+	    if (defined $name_map{$entry}) {
+		my $name= $name_map{$entry};
+		foreach my $lang (keys %{$collectionmeta->{$entry}}) {
+		    my $value = $collectionmeta->{$entry}->{$lang};
+		    if ($entry =~ /^icon/) {
+			$value = format_icon_value($value);
+		    } else {
+			$value = tidy_up_display_item($value);
+		    }
+		    &output_display($collwriter, $name, $lang, $value);
+		}
+	    }
+	}
+	$collwriter->endTag('displayItemList');
+    } 
+    
+    # output building metadata to build config file 
+    my $numdocs = $buildcfg->{'numdocs'};
+    $buildwriter->startTag('metadataList');
+    &output_metadata($buildwriter, 'numDocs', $numdocs);
+    &output_metadata($buildwriter, 'buildType', $buildtype);
+    $buildwriter->endTag('metadataList');
+    
+    
+    #indexes
+    # maps index name to shortname
+    my $indexmap = {};
+    # keeps the order for indexes
+    my @indexlist = ();
+    my $defaultindex = "";
+    my $first = 1;
+    my $maptype = "indexfieldmap";
+    if ($buildtype eq "mg") {
+	$maptype = "indexmap";
+    }
+    if (defined $buildcfg->{$maptype}) {
+	my $indexmap_t = $buildcfg->{$maptype};
+	foreach my $i (@$indexmap_t) {
+	    my ($k, $v) = $i =~ /^(.*)\-\>(.*)$/;
+	    $indexmap->{$k} = $v;
+	    push @indexlist, $k;
+	    if ($first) {
+		$defaultindex = $v;
+		$first = 0;
+	    }	
+	}
+    } else {
+	print STDERR "$maptype not defined";
+    }
+    # we use the shortname for default index
+    if (defined $collectcfg->{'defaultindex'}) {
+	$defaultindex = $collectcfg->{'defaultindex'};
+	$defaultindex = $indexmap->{$defaultindex};
+    }
+    
+    #  levels
+    my $levelmap = {};
+    my @levellist = ();
+    my $default_search_level = "";
+    my $default_retrieve_level = "Sec";
+    $first = 1;
+    if ($buildtype eq "mgpp" || $buildtype eq "lucene") {
+	if (defined $buildcfg->{'levelmap'}) {
+	    my $levelmap_t = $buildcfg->{'levelmap'};
+	    foreach my $l (@$levelmap_t) {
+		my ($k, $v) = $l =~ /^(.*)\-\>(.*)$/;
+		$levelmap->{$k} = $v;
+		push @levellist, $k;
+		if ($first) {
+		    $default_search_level = $v;
+		    $first = 0;
+		}
+	    }
+	}
+
+	if (defined $collectcfg->{'defaultlevel'}) {
+	    $default_search_level = $collectcfg->{'defaultlevel'};
+	    $default_search_level = $levelmap->{$default_search_level};
+	}
+	if (defined $buildcfg->{'textlevel'}) {
+	    $default_retrieve_level = $buildcfg->{'textlevel'};
+	}
+    }
+    # format stuff
+    my $format = $collectcfg->{'format'};
+
+    #output the search stuff to coll cfg
+    $collwriter->startTag('search');
+    foreach my $i (keys %$indexmap) {
+	$collwriter->startTag('index', 'name'=>$i);
+	#find the coll meta stuff
+	my $indexdisplay = ".$i";
+	foreach my $lang (keys %{$collectionmeta->{$indexdisplay}}) {
+	    my $value = $collectionmeta->{$indexdisplay}->{$lang};
+	    output_display($collwriter, 'name', $lang, $value);
+	}
+	$collwriter->endTag('index');
+    }
+
+    #  level stuff for mgpp/lucene
+    if ($buildtype eq 'mgpp' || $buildtype eq 'lucene'){
+	foreach my $l (keys %$levelmap) {
+	    $collwriter->startTag('level', 'name'=>$l);
+	    #find the coll meta stuff
+	    my $leveldisplay = ".$l";
+	    foreach my $lang (keys %{$collectionmeta->{$leveldisplay}}) {
+		my $value = $collectionmeta->{$leveldisplay}->{$lang};
+		output_display($collwriter, 'name', $lang, $value);
+	    }
+	    $collwriter->endTag('level');
+	}
+    }
+    # add in the format stuff
+    if (defined $format->{'SearchVList'}) {
+	
+	$collwriter->startTag('format');
+	write_format($collwriter, $format->{'SearchVList'}, "document");
+	$collwriter->endTag('format');
+    }
+    elsif (defined $format->{'VList'}) {
+	$collwriter->startTag('format');
+	write_format($collwriter, $format->{'VList'}, "document");
+	$collwriter->endTag('format');
+    }	
+    
+    $collwriter->endTag('search');
+    
+    $buildwriter->startTag('serviceRackList');
+    
+    my @levels = ();
+    my $defaultlevel;
+    my $service_type = "MG";
+    if ($buildtype eq 'mgpp') {
+	$service_type = "MGPP";
+    } elsif ($buildtype eq "lucene") {
+	$service_type = "Lucene";
+    }
+
+    #do the retrieve service
+    $buildwriter->startTag('serviceRack', 'name'=>"GS2".$service_type."Retrieve");
+    if ($buildtype eq 'mgpp' || $buildtype eq 'lucene') {
+	$buildwriter->emptyTag('defaultLevel', 'shortname'=>$default_retrieve_level);
+    } elsif ($buildtype eq "mg") {
+	$buildwriter->emptyTag('defaultIndex', 'shortname'=>$defaultindex);
+	
+    }
+    if (defined $indexstem) {
+	$buildwriter->emptyTag('indexStem', 'name'=>$indexstem);
+    } 
+    # close off the Retrieve service
+    $buildwriter->endTag('serviceRack');
+
+    # add in the classifiers if needed
+
+    my $count = 1;
+    my $phind = 0;
+    my $started_classifiers = 0;
+    if (defined $collectcfg->{'classify'}) { 
+	$collwriter->startTag('browse');
+	# add in default format if necessary
+	if (defined $format->{"VList"} || defined $format->{"HList"}) {
+	    # global formats
+	    $collwriter->startTag('format');
+	    if (defined $format->{"VList"}) {
+		# VLIst applies to both classifier and doc nodes
+		write_format($collwriter, $format->{"VList"}, "document");
+		write_format($collwriter, $format->{"VList"}, "classifier");
+	    }
+	    if (defined $format->{"HList"}) {
+		# hlist is only for classifier nodes
+		write_format($collwriter, $format->{"HList"}, "horizontal");
+	    }
+	    $collwriter->endTag('format');
+	}
+	my $classifiers = $collectcfg->{'classify'};
+	foreach my $cl (@$classifiers) {
+	    my $name = "CL$count";
+	    $count++;
+	    my ($classname) = @$cl[0];
+	    if ($classname =~ /^phind$/i) {
+		$phind=1;
+		#should add it into coll config classifiers
+		next;
+	    }
+	    
+	    my $horizontalAtTop = &isHorizontalClassifier($database, $name);
+	    if (not $started_classifiers) {
+		$buildwriter->startTag('serviceRack', 'name'=>'GS2Browse');
+		if (defined $indexstem) {
+		    $buildwriter->emptyTag('indexStem', 'name'=>$indexstem);
+		} 
+
+		$buildwriter->startTag('classifierList');		
+		$started_classifiers = 1;
+	    }
+	    my $content = ''; #use buttonname first, then metadata
+	    if ($classname eq "DateList") {
+		$content = "Date";
+	    } else {
+		for (my $i=0; $i<scalar(@$cl); $i++) {
+		    my $arg = @$cl[$i];
+		    if ($arg eq "-buttonname"){
+			$content = @$cl[$i+1];
+			last;
+		    } elsif ($arg eq "-metadata") {
+			$content = @$cl[$i+1];
+		    }
+		    
+		}
+	    }
+	    if ($horizontalAtTop) {
+		$buildwriter->emptyTag('classifier', 'name'=>$name, 'content'=>$content, 'horizontalAtTop'=>'true');
+	    } else {
+		$buildwriter->emptyTag('classifier', 'name'=>$name, 'content'=>$content);
+	    } 
+	    
+	    
+	    $collwriter->startTag('classifier', 'name'=>$name);
+	    my $vlist = $name."VList";
+	    my $hlist = $name."HList";
+	    my $dlist = "";
+	    if ($classname eq "DateList") {
+		$dlist = "DateList";
+	    }
+	    # need to work out how to split into classifier and document
+	    if (defined $format->{$vlist} || defined $format->{$hlist} || defined $format->{$dlist}) {
+		$collwriter->startTag('format');
+		if (defined $format->{$vlist}) {
+		    write_format($collwriter, $format->{$vlist}, "document");
+		    write_format($collwriter, $format->{$vlist}, "classifier");
+		} 
+		if (defined $format->{$hlist}) {
+		    write_format($collwriter, $format->{$hlist}, "horizontal");
+		} 
+		
+		if (defined $format->{$dlist}) {
+		    write_format($collwriter, $format->{$dlist}, "document");
+		}
+		$collwriter->endTag('format');
+	    }
+	    $collwriter->endTag('classifier');
+	} #foreach classifier
+	if ($started_classifiers) {
+	    # end the classifiers
+	    $buildwriter->endTag('classifierList');
+	    # close off the Browse service
+	    $buildwriter->endTag('serviceRack');
+	}
+	
+	$collwriter->endTag('browse');
+    }
+    
+    
+    # the phind classifier is a separate service
+    if ($phind) {
+	# if phind classifier
+	$buildwriter->emptyTag('serviceRack', 'name'=>'PhindPhraseBrowse');
+    }
+   
+    # do the search service
+    $buildwriter->startTag('serviceRack', 'name'=>'GS2'.$service_type.'Search');
+    $buildwriter->emptyTag('defaultIndex', 'shortname'=>$defaultindex);
+    $buildwriter->startTag('indexList');
+    #for each index
+    foreach my $i (@indexlist) {
+	my $index = $indexmap->{$i};
+	$buildwriter->emptyTag('index', 'name'=>$i, 'shortname'=>$index);
+    }	
+    $buildwriter->endTag('indexList');
+    if (defined $indexstem) {
+	$buildwriter->emptyTag('indexStem', 'name'=>$indexstem);
+    } 
+    
+    # index options
+    if ($buildtype eq 'mg' || $buildtype eq 'mgpp') {
+	$buildwriter->startTag('indexOptionList');
+	my $stemindexes = 3; # default is stem and casefold
+	if (defined $buildcfg->{'stemindexes'} && $buildcfg->{'stemindexes'} =~ /^\d+$/ ) {
+	    $stemindexes = $buildcfg->{'stemindexes'};
+	}
+	$buildwriter->emptyTag('indexOption', 'name'=>'stemIndexes', 'value'=>$stemindexes);
+	
+	my $maxnumeric = 4; # default
+	if (defined $buildcfg->{'maxnumeric'} && $buildcfg->{'maxnumeric'} =~ /^\d+$/) {
+	    $maxnumeric = $buildcfg->{'maxnumeric'};
+	}
+	$buildwriter->emptyTag('indexOption', 'name'=>'maxnumeric', 'value'=>$maxnumeric);
+	
+	$buildwriter->endTag('indexOptionList');
+    }
+
+    if ($buildtype eq 'mgpp' || $buildtype eq 'lucene') {
+		
+	# level info
+	$buildwriter->emptyTag('defaultLevel', 'shortname'=>$default_search_level);
+	$buildwriter->emptyTag('defaultGDBMLevel', 'shortname'=>$default_retrieve_level);
+	$buildwriter->startTag('levelList');
+	foreach my $l (@levellist) {
+	    my $level = $levelmap->{$l};
+	    $buildwriter->emptyTag('level', 'name'=>$l, 'shortname'=>$level);
+	}	
+	$buildwriter->endTag('levelList');
+	
+	# do the search types if there
+	if (defined $collectcfg->{'searchtype'}) {
+	    $buildwriter->startTag('searchTypeList');
+	    foreach my $st (@{$collectcfg->{'searchtype'}}) {
+		$buildwriter->emptyTag('searchType', 'name'=>$st);
+	    }
+	    $buildwriter->endTag('searchTypeList');
+	} elsif (defined $format->{'SearchTypes'}) {
+	    #check format statement 
+	    my $searchtype = $format->{'SearchTypes'};
+	    $buildwriter->startTag('searchTypeList');
+	    if ($searchtype =~ /form/) {
+		$buildwriter->emptyTag('searchType', 'name'=>'form');
+	    }
+	    if ($searchtype =~ /plain/) {
+		$buildwriter->emptyTag('searchType', 'name'=>'plain');
+	    }
+	    $buildwriter->endTag('searchTypeList');
+	}
+    } 
+    
+
+    
+    $buildwriter->endTag('serviceRack');
+    
+    $buildwriter->endTag('serviceRackList');
+    $buildwriter->endTag('buildConfig');
+
+    # we add in the default replace list just in case we have macros in the 
+    # collection
+    $collwriter->emptyTag('replaceListRef', 'id'=>'gs2-standard');
+    $collwriter->endTag('collectionConfig');
+    $collwriter->end();
+    $buildwriter->end();
+    $buildoutput->close();
+    $colloutput->close();
+    &close_database($database);
+}
+
+
+sub output_metadata {
+    my ($writer, $metaname,  $metavalue) = @_;
+    $writer->startTag('metadata',  'name'=>$metaname);
+    $writer->characters($metavalue);
+    $writer->endTag('metadata');
+}
+
+sub output_display {
+    my ($writer, $name, $lang, $value) = @_;
+    $lang = 'en' if $lang eq 'default';
+    if ($lang =~ /^\[/) {
+	($lang) = $lang =~ /\[l=(.*)\]/;
+    }
+    $writer->startTag('displayItem', 'name'=>$name, 'lang'=>$lang);
+    $writer->characters($value);
+    $writer->endTag('displayItem');
+}
+sub format_icon_value {
+    my ($value) = @_;
+    if ($value =~ /^_/) {
+	my ($newvalue) = $value =~ /images\/(.*)$/;
+	if ($newvalue) {
+	    return $newvalue;
+	}
+    }
+    return $value;
+}
+
+sub tidy_up_display_item {
+    my ($value) = @_;
+    # remove \n
+    $value =~ s/\\n//g;
+    # replace \' with '
+    $value =~ s/\\\'/\'/g;
+    # replace \" with "
+    $value =~ s/\\\"/\"/g;
+    # replace _httpprefix_ with _httpsite_
+    $value =~ s/_httpprefix_/_httpsite_/g;
+    $value =~ s/_gwcgi_//g;
+    $value =~ s/[a-z][a-z]?=_cgiarg[a-z][a-z]?_&?//g;
+    $value =~ s/&p=/&sa=/g;
+    return $value;
+}
+
+sub write_format {
+    my ($writer, $old_format, $node_type) = @_;
+    # replace \' with '
+    $old_format =~ s/\\\'/\'/g;
+    # replace \" with "
+    $old_format =~ s/\\\"/\"/g;
+    #convert [] to <gsf:...>
+    # assume no nesting {If} or {Or} for now
+    $old_format =~ s/\{If\}\{([^\}]*)\}/&format_if($1, $node_type)/eg;
+    $old_format =~ s/\{Or\}\{([^\}]*)\}/&format_or($1)/eg;
+    $old_format =~ s/\[Text\]/\<gsf:text\/\>/g;
+    $old_format =~ s/\[num\]/\<gsf:num\/\>/g;
+    $old_format =~ s/\[link\]/\<gsf:link type=\'$node_type\'\>/g;
+    $old_format =~ s/\[\/link\]/\<\/gsf:link\>/g;
+    $old_format =~ s/\[srclink\]/\<gsf:link type=\'source\'\>/g;
+    $old_format =~ s/\[\/srclink\]/\<\/gsf:link\>/g;
+    $old_format =~ s/\[icon\]/\<gsf:icon type=\'$node_type\'\/\>/g;
+    $old_format =~ s/\[srcicon\]/\<gsf:icon type=\'source\'\/\>/g;
+		  
+    # what to do with hightlight??
+    $old_format =~ s/\[\/?highlight\]//g;
+
+    #now do the rest of the [] which are assumed to be metadata
+    $old_format =~ s/\[([^\]]*)\]/&format_metadata($1)/eg;
+  
+    # some html tidy
+    #turn <br> into <br />
+    $old_format =~ s/\<br\>/\<br \/\>/g;
+    #turn <p> into <p />
+    $old_format =~ s/\<p\>/\<p \/\>/g;
+    
+    #put quotes around any atts
+    $old_format =~ s/=([a-z]+)([> ])/=\'$1\'$2/g;
+
+    if ($node_type eq "document") {
+	$writer->startTag('gsf:template', 'match'=>'documentNode');
+	$writer->charactersXML($old_format);
+	$writer->endTag('gsf:template');
+    } elsif ($node_type eq "classifier") {
+	$writer->startTag('gsf:template', 'match'=>'classifierNode');
+	$writer->charactersXML($old_format);
+	$writer->endTag('gsf:template');
+    } elsif ($node_type eq "horizontal") {	
+	$writer->startTag('gsf:template', 'match'=>'classifierNode', 'mode'=>'horizontal');
+	$writer->charactersXML($old_format);
+	$writer->endTag('gsf:template');
+
+    }
+}
+
+sub format_metadata {
+    my ($metadata_string) = @_;
+
+    #print STDERR "original meta = $metadata_string\n"; 
+    
+    # what shall we do with cgisafe??
+    my $cgisafe = $metadata_string =~ s/^cgisafe://;
+
+    my ($select) = $metadata_string =~ /^(parent|sibling)/;
+    $metadata_string =~ s/^(parent|sibling)//;
+    my ($scope, $delim);
+    
+    if ($select) {
+	($scope) = $metadata_string =~ /^\((Top|All)/;
+	$metadata_string =~ s/^\((Top|All)\)?//;
+	if ($scope) {
+	    ($delim) = $metadata_string =~ /^\'([^\']*)\'\)/;
+	    $metadata_string =~ s/^\'([^\']*)\'\)//;
+	} 
+    }
+    $metadata_string =~ s/^://;
+    # remove ex.
+    $metadata_string =~ s/^ex\.//;
+    
+    #print STDERR "select=$select, scope=$scope, delim=|$delim|, meta = $metadata_string\n";
+    
+    my $new_format = "<gsf:metadata name='$metadata_string' ";
+    if (defined $select) {
+	if ($select eq "sibling") {
+	    $new_format .= "multiple='true' ";
+	    if (defined $delim) {
+		$new_format .= "separator='$delim' ";
+	    }
+	} elsif ($select eq "parent"){
+	    if (defined $scope) {
+		if ($scope eq "Top") {
+		    $new_format .= "select='root' ";
+		} elsif ($scope eq "All") {
+		    $new_format .= "select='ancestors' ";
+		    if (defined $delim) {
+			$new_format .= "separator='$delim' ";
+		    }
+		}
+	    } else {
+		$new_format .= "select='parent' ";
+	    }	
+	}
+    }
+    $new_format .= "/>";
+    #print STDERR "$new_format\n";
+    return $new_format;
+    
+}
+
+sub format_if {
+
+    my ($if_string, $node_type) = @_;
+    #print STDERR "if string = $if_string\n";
+
+    my @parts = split /,/, $if_string; 
+    my $test = $parts[0];
+    my $true_option = $parts[1];
+    my $false_option;
+    if (scalar (@parts) == 3) {
+	$false_option = $parts[2];
+    }
+    $test =~ s/^\s*//;
+    $test =~ s/\s*$//;
+    my ($test_meta, $test_type, $test_value);
+    if ($test =~ /^(\[.+\])$/) {
+	$test_meta = $1;
+	$test_type = 'exists';
+    } else {
+	my ($lhs, $exp, $rhs) = $test =~ /^(.+)\s+(eq|ne|lt|gt|le|ge|sw|ew)\s+(.+)$/;
+	#print STDERR "lhs, exp, rhs = $lhs, $exp, $rhs\n";
+	if ($exp eq "eq") {
+	    $test_type = "equals";
+	} elsif ($exp eq "sw") {
+	    $test_type = "startsWith";
+	} elsif ($exp eq "ew") {
+	    $test_type = "endsWith";
+	} elsif ($exp eq "ne") {
+	    $test_type = "notEquals";
+	} elsif ($exp eq "lt") {
+	    $test_type = "lessThan";
+	}elsif ($exp eq "gt") {
+	    $test_type = "greaterThan";
+	}elsif ($exp eq "le") {
+	    $test_type = "lessThanOrEquals";
+	}elsif ($exp eq "ge") {
+	    $test_type = "greaterThanOrEquals";
+	}
+	if ($lhs =~ /^\[.+\]$/) {
+	    $test_meta = $lhs;
+	    $test_value = $rhs;
+	} else {
+	    # assume rhs has meta
+	    $test_meta = $rhs;
+	    $test_value = $lhs;
+	}
+	
+	#remove beginning and end quotes
+	$test_value =~ s/^[\'\"]//;
+	$test_value =~ s/[\'\"]$//;
+    }
+    my $test_atts = "test='$test_type' ";
+    if (defined $test_value) {
+	$test_atts .= "test-value='$test_value' ";
+    }
+    #print STDERR "test, true, false = $test, $true_option, $false_option\n";
+    my $new_format = "<gsf:switch>$test_meta";
+    $new_format .= "<gsf:when $test_atts>$true_option</gsf:when>";
+    if (defined $false_option) {
+	$new_format .="<gsf:otherwise>$false_option</gsf:otherwise>";
+    }
+    $new_format .= "</gsf:switch>";
+	
+    #print STDERR "new format = $new_format\n";
+    return $new_format;
+}
+
+sub format_or {
+    my ($or_string) = @_;
+    my @meta_list = split (',', $or_string);
+    return "" unless scalar (@meta_list);
+    my $new_format = "<gsf:choose-metadata>";
+    foreach my $m (@meta_list) {
+	if ($m =~ /^\[(.*)\]$/) {
+	    $new_format .= &format_metadata($1);
+	} else {
+	    # a default value
+	    $new_format .= "<gsf:default>$m</gsf:default>";
+	    last;
+	}
+    }
+    $new_format .= "</gsf:choose-metadata>";
+    return $new_format;
+}
+
+sub open_database {
+    my ($db_file) = @_;
+    
+    my $database = ();
+#    tie (%$database, 'GDBM_File', $db_file, GDBM_READER, 0400) ||
+#	die "Couldn't open database $db_file\n";
+
+    return $database;
+}
+
+sub close_database {
+    my ($database) = @_;
+    untie %$database;
+}
+sub isHorizontalClassifier {
+    my ($database, $name) = @_;
+
+    return 0; # can't get this to work for windows
+    my $record = $database->{$name};
+    my ($childtype) = $record =~ /<childtype>(\w*)/;
+    if ($childtype eq "HList") {
+	return 1;
+    }
+    return 0;
+}
+#$writer->startTag('');
+#$writer->endTag('');
+#$writer->characters();
+#$writer->emptyTag('');
+
+1;
Index: /tags/greenstone-3_02-distribution/gsdl3/bin/script/gs2_mkcol.pl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/bin/script/gs2_mkcol.pl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/bin/script/gs2_mkcol.pl	(revision 13928)
@@ -0,0 +1,297 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# gs2_mkcol.pl -- create the framework for a gs2 compatible collection in 
+# gs3
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+# This program will setup a new collection from a model one. It does this by
+# copying the model, moving files to have the correct names, and replacing
+# text within the files to match the parameters.
+
+package gs2_mkcol;
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+use parsargv;
+use util;
+use cfgread;
+
+sub print_usage {
+    print STDOUT "\n";
+    print STDOUT "gs2_mkcol.pl: Creates the directory structure for a new\n";
+    print STDOUT "          Greenstone2 compatible collection in Greenstone3.\n\n";
+    print STDOUT "  usage: $0 -site site-home -creator email [options] collection-name\n\n";
+    print STDOUT "  options:\n";
+    print STDOUT "   -optionfile file    Get options from file, useful on systems where\n";
+    print STDOUT "                       long command lines may cause problems\n";
+    print STDOUT "   -collectdir         Directory where new collection will be created.\n";
+    print STDOUT "                       Default is " . 
+	&util::filename_cat("site-home", "collect") . "\n";
+    print STDOUT "   -maintainer email   The collection maintainer's email address (if\n";
+    print STDOUT "                       different from the creator)\n";
+    print STDOUT "   -public true|false  If this collection has anonymous access\n";
+    print STDOUT "   -buildtype mg|mgpp  Whether to use mg or mgpp to build the collection\n";
+    print STDOUT "                       Default is mgpp.\n";
+    print STDOUT "   -title text         The title for the collection\n";
+    print STDOUT "   -about text         The about text for the collection\n";
+    print STDOUT "   -plugin text        perl plugin module to use (there may be multiple\n";
+    print STDOUT "                       plugin entries)\n";
+    print STDOUT "   -quiet              Operate quietly\n";
+    print STDOUT "  Note that -creator and -site must be specified. You can make changes to all\n";
+    print STDOUT "  options later by editing the collect.cfg configuration file for your\n";
+    print STDOUT "  new collection (it'll be in the \"etc\" directory).\n\n";
+    print STDOUT "  [Type \"perl -S mkcol.pl | more\" if this help text scrolled off your screen]";
+    print STDOUT "\n" unless $ENV{'GSDLOS'} =~ /^windows$/i;
+}
+
+sub traverse_dir
+{
+    my ($modeldir, $coldir) = @_;
+    my ($newfile, @filetext);
+
+    if (!(-e $coldir)) {
+
+	my $store_umask = umask(0002);
+	my $mkdir_ok = mkdir ($coldir, 0777);
+	umask($store_umask);
+
+	if (!$mkdir_ok) 
+	{
+	    die "$!";
+	}
+    }
+
+    opendir(DIR, $modeldir) || die "Can't read $modeldir";
+    my @files = grep(!/^(\.\.?|CVS)$/, readdir(DIR));
+    closedir(DIR);
+
+    foreach $file (@files)
+    {
+	my $thisfile = &util::filename_cat ($modeldir, $file);
+	if (-d $thisfile) {
+	    my $colfiledir = &util::filename_cat ($coldir, $file);
+	    traverse_dir ($thisfile, $colfiledir);
+
+	} else {
+	    my $destfile = $file;
+	    $destfile =~ s/^modelcol/$collection/;
+	    $destfile =~ s/^MODELCOL/$capcollection/;
+	    print STDOUT "  doing replacements for $destfile\n" unless $quiet;
+	    $destfile = &util::filename_cat ($coldir, $destfile);
+	    
+	    open (INFILE, $thisfile) || 
+		die "ERROR: Can't read file $thisfile";
+	    open (OUTFILE, ">$destfile") ||
+		die "ERROR: Can't create file $destfile";
+
+	    while (defined ($line = <INFILE>)) {
+		$line =~ s/\*\*collection\*\*/$collection/g;
+		$line =~ s/\*\*COLLECTION\*\*/$capcollection/g;
+		$line =~ s/\*\*creator\*\*/$creator/g;
+		$line =~ s/\*\*maintainer\*\*/$maintainer/g;
+		$line =~ s/\*\*public\*\*/$public/g;
+		$line =~ s/\*\*title\*\*/$title/g;
+		$line =~ s/\*\*about\*\*/$about/g;
+		$line =~ s/\*\*plugins\*\*/$pluginstring/g;
+		$line =~ s/\*\*buildtype\*\*/$buildtype/g;
+		$line =~ s/\*\*searchtype\*\*/$searchtype/g;
+		$line =~ s/\*\*indexes\*\*/$indexes/g;
+		$line =~ s/\*\*defaultindex\*\*/$defaultindex/g;
+		$line =~ s/\*\*indexmeta\*\*/$indexmeta/g;
+		$line =~ s/\*\*xmlindexes\*\*/$xmlindexes/g;
+		#$line =~ s/\*\*xmlplugins\*\*/$xmlpluginstring/g;
+		
+		print OUTFILE $line;
+	    }
+	    
+	    close (OUTFILE);
+	    close (INFILE);
+	}
+    }
+}
+
+# get and check options
+sub parse_args {
+    my ($argref) = @_;
+    if (!&parsargv::parse($argref,
+			  'optionfile/.*/', \$optionfile,
+			  'collectdir/.*/', \$collectdir,
+			  'site/.*/', \$sitehome,
+			  'creator/\w+\@[\w\.]+/', \$creator,
+			  'maintainer/\w+\@[\w\.]+/', \$maintainer,
+			  'public/true|false/true', \$public,
+			  'buildtype/mg|mgpp/mgpp', \$buildtype,
+			  'title/.+/', \$title,
+			  'about/.+/', \$about,
+			  'plugin/.+', \@plugin,
+			  'quiet', \$quiet,
+			  )) {
+	&print_usage();
+	die "\n";
+    }
+}
+
+sub main {
+
+    &parse_args (\@ARGV);
+    if ($optionfile =~ /\w/) {
+	open (OPTIONS, $optionfile) || die "Couldn't open $optionfile\n";
+	my $line = [];
+	my $options = [];
+	while (defined ($line = &cfgread::read_cfg_line ('mkcol::OPTIONS'))) {
+	    push (@$options, @$line);
+	}
+	close OPTIONS;
+	&parse_args ($options);
+
+    }
+
+    # load default plugins if none were on command line    
+    if (!scalar(@plugin)) {
+	@plugin = (ZIPPlug,GAPlug,TEXTPlug,HTMLPlug,EMAILPlug,
+		   PDFPlug,RTFPlug,WordPlug,PSPlug,ArcPlug,RecPlug);
+    }
+
+    # get and check the collection name
+    ($collection) = @ARGV;
+    if (!defined($collection)) {
+	print STDOUT "ERROR: no collection name was specified\n";
+	&print_usage();
+	die "\n";
+    }
+
+    if (length($collection) > 8) {
+	print STDOUT "ERROR: The collection name must be less than 8 characters\n";
+	print STDOUT "       so compatibility with earlier filesystems can be\n";
+	print STDOUT "       maintained.\n";
+	die "\n";
+    }
+
+    if ($collection eq "gs2model" || $collection eq "gs3model") {
+	print STDOUT "ERROR: No collection can be named gs2model or gs3model as these are  the\n";
+	print STDOUT "       names of the model collections.\n";
+	die "\n";
+    }
+
+    if ($collection eq "CVS") {
+	print STDOUT "ERROR: No collection can be named CVS as this may interfere\n";
+	print STDOUT "       with directories created by the CVS versioning system\n";
+	die "\n";
+    }
+
+    #check that -site has been specified
+    if (!defined($sitehome) || $sitehome eq "") {
+	print STDOUT "ERROR: The site was not defined. This variable is\n";
+	print STDOUT "       needed to locate the collect directory.\n";
+	die "\n";
+    }
+    #check that its a valid directory
+    if (!-d $sitehome) {
+	print STDOUT "ERROR: $sitehome doesn't exist\n";
+	die "\n";
+    }
+    if (!defined($creator) || $creator eq "") {
+	print STDOUT "ERROR: The creator was not defined. This variable is\n";
+	print STDOUT "       needed to recognise duplicate collection names.\n";
+	die "\n";
+    }
+
+    if (!defined($maintainer) || $maintainer eq "") {
+	$maintainer = $creator;
+    }
+
+    $public = "true" unless defined $public;
+    $buildtype = "mgpp" unless defined $buildtype;
+
+    $searchtype = "";
+    if ($buildtype eq "mgpp") {
+	$searchtype = "searchtype  plain form";
+    }
+    
+    if (!defined($title) || $title eq "") {
+	$title = $collection;
+    }
+
+    # get capitalised version of the collection
+    $capcollection = $collection;
+    $capcollection =~ tr/a-z/A-Z/;
+
+    # get the strings to include.
+    $pluginstring = "";
+    foreach $plugin (@plugin) {
+	if ($plugin eq RecPlug) {
+	    $pluginstring .= "plugin         $plugin -use_metadata_files\n";
+	} else {
+	    $pluginstring .= "plugin         $plugin\n";
+	}
+    }
+
+    $mdir = &util::filename_cat ($sitehome, "collect", "gs2model");
+    
+    if (defined $collectdir && $collectdir =~ /\w/) {
+	if (!-d $collectdir) {
+	    print STDOUT "ERROR: $collectdir doesn't exist\n";
+	    die "\n";
+	}
+	$cdir = &util::filename_cat ($collectdir, $collection);
+    } else {
+	$cdir = &util::filename_cat ($sitehome, "collect", $collection);
+    }
+
+    # make sure the model collection exists
+    die "ERROR: Cannot find the model collection $mdir" unless (-d $mdir);
+
+    # make sure this collection does not already exist
+    if (-e $cdir) {
+	print STDOUT "ERROR: This collection already exists\n";
+	die "\n";
+    }
+
+    # set up the default indexes - this could be a command line option at some stage
+    # the names are added in here for the xml ones, but they should be added after building once the names are known.
+    if ($buildtype eq "mg") {
+	$indexes = "document:text document:Title document:Source";
+	$defaultindex = "defaultindex document:text";
+	$indexmeta = "collectionmeta .document:text    \"text\"\ncollectionmeta .document:Title  \"titles\"\ncollectionmeta .document:Source  \"filenames\"\n";
+    } elsif ($buildtype eq "mgpp") {
+	$indexes = "allfields text metadata";
+	$defaultindex = "";
+	$indexmeta = "collectionmeta .text    \"text\"\ncollectionmeta .allfields \"entire documents\"\n";
+    } else {
+	print STDOUT "Error: buildtype should be mg or mgpp, but its $buildtype\n";
+    }
+    # start creating the collection
+    print STDOUT "\nCreating the collection $collection...\n" unless $quiet;
+    &traverse_dir ($mdir, $cdir);
+    print STDOUT "\nThe new collection was created successfully at\n" unless $quiet;
+    print STDOUT "$cdir\n" unless $quiet;
+}
+
+&main ();
Index: /tags/greenstone-3_02-distribution/gsdl3/bin/script/gs3-build.bat
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/bin/script/gs3-build.bat	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/bin/script/gs3-build.bat	(revision 13928)
@@ -0,0 +1,23 @@
+@echo off
+
+:: ---- Check that %GSDL3HOME% is set ----
+if not "%GSDL3HOME%" == "" goto start
+    echo "You need to run 'gs3-setup' in the greenstone3 directory before running this script"
+    goto exit
+
+:start
+
+if not "%1" == "" goto start2
+    echo Usage: gs3-build sitename collname
+    goto exit
+
+:start2
+if not "%2" == "" goto run
+    echo Usage: gs3-build sitename collname
+    goto exit
+
+:run
+
+java -cp "%CLASSPATH%" -DGSDL3HOME="%GSDL3HOME%"  -DGSDL3SRCHOME="%GSDL3SRCHOME%" -Dorg.xml.sax.driver=org.apache.xerces.parsers.SAXParser  org.greenstone.gsdl3.gs3build.Build -site %1 -collect %2
+
+:exit
Index: /tags/greenstone-3_02-distribution/gsdl3/bin/script/gs3-build.sh
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/bin/script/gs3-build.sh	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/bin/script/gs3-build.sh	(revision 13928)
@@ -0,0 +1,20 @@
+#!/bin/sh 
+
+#check that GSDL3HOME is set
+if test -z "$GSDL3HOME" ; then
+  echo "You need to 'source gs3-setup.sh' in the greenstone3 directory before running this script"
+ exit;
+fi
+
+if test $# != 2; then
+  echo "Usage: gs3-build.sh <site name> <collection name>"
+  exit;
+fi
+
+sitename=$1
+collectionname=$2
+
+# we need to stop here if the database isn't running - how can we tell??
+java -DGSDL3HOME=$GSDL3HOME -DGSDL3SRCHOME=$GSDL3SRCHOME -Dorg.xml.sax.driver=org.apache.xerces.parsers.SAXParser org.greenstone.gsdl3.gs3build.Build -site $sitename -collect $collectionname
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/bin/script/gs3-mkcol.bat
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/bin/script/gs3-mkcol.bat	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/bin/script/gs3-mkcol.bat	(revision 13928)
@@ -0,0 +1,23 @@
+@echo off
+
+:: ---- Check that %GSDL3HOME% is set ----
+if not "%GSDL3HOME%" == "" goto start
+    echo "You need to run 'gs3-setup' in the greenstone3 directory before running this script"
+    goto exit
+
+:start
+
+if not "%1" == "" goto start2
+    echo Usage: gs3-mkcol sitename collname
+    goto exit
+
+:start2
+if not "%2" == "" goto run
+    echo Usage: gs3-mkcol sitename collname
+    goto exit
+
+:run
+
+java -cp "%CLASSPATH%" -DGSDL3HOME="%GSDL3HOME%" -DGSDL3SRCHOME="%GSDL3SRCHOME%" -Dorg.xml.sax.driver=org.apache.xerces.parsers.SAXParser  org.greenstone.gsdl3.gs3build.Create -site %1 -collect %2
+
+:exit
Index: /tags/greenstone-3_02-distribution/gsdl3/bin/script/gs3-mkcol.sh
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/bin/script/gs3-mkcol.sh	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/bin/script/gs3-mkcol.sh	(revision 13928)
@@ -0,0 +1,23 @@
+#!/bin/sh 
+
+#check that GSDL3HOME is set
+if test -z "$GSDL3HOME" ; then
+  echo "You need to 'source gs3-setup.sh' in the greenstone3 directory before running this script"
+ exit;
+fi
+
+if test $# != 2; then
+  echo "Usage: gs3-mkcol.sh <site name> <collection name>"
+  exit;
+fi
+
+sitename=$1
+collectionname=$2
+
+java -DGSDL3HOME=$GSDL3HOME -DGSDL3SRCHOME=$GSDL3SRCHOME -Dorg.xml.sax.driver=org.apache.xerces.parsers.SAXParser org.greenstone.gsdl3.gs3build.Create -site $sitename -collect $collectionname
+
+#/opt/sun-jdk-1.4.2.03/bin/java -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y -DGSDL3HOME=$GSDL3HOME -Dorg.xml.sax.driver=org.apache.xerces.parsers.SAXParser org.greenstone.gsdl3.gs3build.Build -site $sitename -collect $collectionname
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/build.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/build.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/build.properties	(revision 13928)
@@ -0,0 +1,52 @@
+#### properties file for Greenstone3 building using ANT. See the README for more 
+#### information
+
+## java compilation properties - for javac
+#Should compilation include the debug option?
+compile.debug=true
+#Should compilation include the deprecation option?
+compile.deprecation=true
+#Should compilation include the optimize option?
+compile.optimize=true
+
+## windows c++ compilation
+compile.windows.c++.setup=C:/Program Files/Microsoft Visual Studio/VC98/Bin/VCVARS32.BAT
+
+## Tomcat installation
+#Set this to the internet/intranet name of the machine that Tomcat is/will be run on. localhost is fine for accessing the server from the local machine, but not remotely
+tomcat.server=localhost
+# The port number that tomcat is/will be run on
+tomcat.port=8080
+# Tomcat's shutdown port - this may need to be changed if you are running two or more Tomcats
+tomcat.shutdown.port=8005
+# If tomcat is already running, enter the path to the base directory here
+tomcat.installed.path=
+#uncomment the following if you have moved the greenstone3 web directory to tomcats webapps dir 
+#web.home=${tomcat.installed.path}/webapps/greenstone3
+
+## Collection building options
+# uncomment if you don't want to have collection building enabled
+#disable.collection.building=true
+
+## Greenstone 3 server program options
+# does running the server automatically start up Tomcat and a browser
+server.auto.start=false
+# default servlet to start with
+server.default.servlet=/library
+
+##Browser setup
+browser.path=
+
+## Proxy setup - Greenstone installation will attempt to download extra packages. Set the proxy information here if you are behind a firewall.
+# The proxy server name 
+proxy.host=
+# The proxy server port
+proxy.port=
+# A user name to use when talking to the proxy server (optional, will prompt if not entered here)
+proxy.user=
+# A password to use when talking to the proxy server (optional, will prompt if not entered here)
+proxy.password=
+
+## Mac OS X specific stuff
+# set the path to your GDBM here
+gdbm.installed.path=
Index: /tags/greenstone-3_02-distribution/gsdl3/build.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/build.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/build.xml	(revision 13928)
@@ -0,0 +1,1294 @@
+<?xml version="1.0"?>
+
+<!-- ====================================================================== 
+     March 2005                                                    
+
+     Greenstone3 build and install script
+                   
+     kjdon                                                                
+     ====================================================================== -->
+<project name="greenstone3" default="usage" basedir=".">
+
+ <!-- ============ self defined tasks =================== -->
+
+  <taskdef name="mysetproxy" classname="org.greenstone.anttasks.MySetProxy" classpath="${basedir}/lib/java/anttasks.jar"/>
+  <taskdef name="getuserandpassword" classname="org.greenstone.anttasks.MyGetUserAndPassword" classpath="${basedir}/lib/java/anttasks.jar"/>
+
+
+
+<!-- ===================== Property Definitions =========================== -->
+
+<!--
+
+  Each of the following properties are used in the build script.
+  Values for these properties are set by the first place they are
+  defined, from the following list:
+
+  * Definitions on the "ant" command line (ant -Dfoo=bar compile).
+
+  * Definitions from a "build.properties" file in the top level
+    source directory of this application.
+
+  * Definitions from a "build.properties" file in the user's
+    home directory.
+
+  * Default definitions in this build.xml file.
+
+  You will note below that property values can be composed based on the
+  contents of previously defined properties.  This is a powerful technique
+  that helps you minimize the number of changes required when your development
+  environment is modified.  Note that property composition is allowed within
+  "build.properties" files as well as in the "build.xml" script.
+
+-->
+
+  <property file="build.properties"/>
+  <property file="${user.home}/build.properties"/>
+
+  <!-- get properties from the environment -->
+  <property environment="env"/>
+  <property name="build.home" value="${basedir}/build"/>
+  <property name="src.home" value="${basedir}/src/java"/>
+  <property name="src.packages.home" value="${basedir}/src/packages"/>
+  <property name="packages.home" value="${basedir}/packages"/>
+  <!-- this may be set in build.properties, eg if you move the web dir to 
+  tomcats webapps directory -->
+  <property name="web.home" value="${basedir}/web"/>
+  <!-- jar files needed by applets go here -->
+  <property name="web.applet" value="${web.home}/applet"/>
+  <!-- jar files needed by the servlet (and extra ones) go here -->
+  <property name="web.lib" value="${web.home}/WEB-INF/lib"/>
+  <!-- other files needed by the servlet go here -->
+  <property name="web.classes" value="${web.home}/WEB-INF/classes"/>
+  <!-- jni libraries and java wrappers go here -->
+  <property name="lib.jni" value="${basedir}/lib/jni"/>
+    
+  <property name="javadocs" value="${basedir}/docs/javadoc"/>
+
+  <property name="app.name"      value="greenstone3"/>
+  <property name="app.path"      value="/${app.name}"/>
+  <property name="app.version"   value="3.02"/>
+
+  <property name="cvs.root" value=":pserver:cvs_anon@cvs.scms.waikato.ac.nz:2402/usr/local/global-cvs/gsdl-src"/>
+  <!-- catalina home is set to tomcat basedir is already installed, otherwise
+  use greenstone's tomcat -->
+  <condition property="catalina.home" value="${tomcat.installed.path}"> 
+    <and>
+      <isset property="tomcat.installed.path"/>
+      <not>
+	<equals arg1="" arg2="${tomcat.installed.path}"/>
+      </not>
+    </and>
+  </condition>
+  <property name="catalina.home" value="${packages.home}/tomcat"/>
+
+  <property name="os.linux" value="Linux"/> 
+  <property name="os.mac" value="Mac OS X"/>
+  <property name="os.solaris" value="SunOS"/>
+  <property name="os.unix" value="${os.linux},${os.mac},${os.solaris}"/>
+  <property name="os.windows" value="Windows 95,Windows 98,Windows 2000,Windows XP,Windows NT,Windows ME"/> <!-- check this!!!-->
+
+  <!-- this is true for linux and macs -->
+  <condition property="current.os.isunix">
+    <os family="unix"/>
+  </condition>
+  
+  <condition property="current.os.isunixnotmac">
+    <and>
+      <os family="unix"/>
+      <not>
+	<os family="mac"/>
+      </not>
+    </and>
+  </condition>
+  <condition property="current.os.ismac">
+    <os family="mac"/>
+  </condition>
+  
+  <condition property="current.os.iswindows">
+    <os family="windows"/>
+  </condition>
+
+  <condition property="collection.building.enabled">
+    <not>
+      <isset property="disable.collection.building"/>
+    </not>
+  </condition>
+
+  <condition property="collection.building.enabled.windows">
+    <and>
+      <isset property="collection.building.enabled"/>
+      <isset property="current.os.iswindows"/>
+    </and>
+  </condition>
+  
+  <condition property="collection.building.enabled.unix">
+    <and>
+      <isset property="collection.building.enabled"/>
+      <isset property="current.os.isunix"/>
+    </and>
+  </condition>
+  
+  <condition property="independent-indexers">
+    <isset property="disable.collection.building"/>
+  </condition>
+    
+  <!-- ============= Base dirs for each package and component ============ -->
+  <property name="src.applet.home" value="${src.home}/org/greenstone/applet"/>
+  <property name="src.gsdl3.home" value="${src.home}/org/greenstone/gsdl3"/>
+  <property name="anttasks.home" value="${src.home}/org/greenstone/anttasks"/>
+  <property name="gs2build.home" value="${basedir}/gs2build"/>
+  <property name="gli.home" value="${basedir}/gli"/>
+  <property name="javagdbm.home" value="${src.packages.home}/javagdbm"/>
+
+  <!--<property name="indexers.home" value="${basedir}/src/packages/indexers">-->
+  <condition property="indexers.home" value="${basedir}/src/packages/indexers">
+    <isset property="disable.collection.building"/>
+  </condition>
+  <condition property="indexers.home" value="${gs2build.home}/indexers">
+    <not>
+      <isset property="disable.collection.building"/>
+    </not>
+  </condition>
+
+  <property name="mg.home" value="${indexers.home}/mg"/>
+  <property name="mgpp.home" value="${indexers.home}/mgpp"/>
+  <property name="lucene.home" value="${indexers.home}/lucene-gs"/>
+
+
+<!--  ==================== Compilation Control Options ==================== -->
+
+<!--
+
+  These properties control option settings on the Javac compiler when it
+  is invoked using the <javac> task.
+
+  compile.debug        Should compilation include the debug option?
+
+  compile.deprecation  Should compilation include the deprecation option?
+
+  compile.optimize     Should compilation include the optimize option?
+
+-->
+
+  <property name="compile.debug"       value="true"/>
+  <property name="compile.deprecation" value="true"/>
+  <property name="compile.optimize"    value="true"/>
+
+<!--
+
+  Rather than relying on the CLASSPATH environment variable, Ant includes
+  features that makes it easy to dynamically construct the classpath you
+  need for each compilation.  The example below constructs the compile
+  classpath to include the servlet.jar file, as well as the other components
+  that Tomcat makes available to web applications automatically, plus anything
+  that you explicitly added.
+
+-->
+
+  <path id="compile.classpath">
+    <!-- Include all jar files and libraries in our jni lib directory -->
+    <pathelement location="${lib.jni}"/>
+    <fileset dir="${lib.jni}">
+      <include name="*.jar"/>
+    </fileset>
+    <!-- Include all jar files in our web lib directory -->
+    <pathelement location="${web.lib}"/>
+    <fileset dir="${web.lib}">
+      <include name="*.jar"/>
+    </fileset>
+    
+    <!-- Include the axis jar files -->
+    <!--<fileset dir="${basedir}/comms/soap/axis/lib">
+      <include name="*.jar"/>
+    </fileset>-->
+    
+    <!-- include the jar files from the source packages -->
+    <!-- mg and mgpp get installed into lib/jni but they may not be there yet
+    so we add them in by name -->
+    <pathelement location="${lib.jni}/mg.jar"/>
+    <pathelement location="${lib.jni}/mgpp.jar"/>
+    
+    <!-- Include all elements that Tomcat exposes to applications -->
+    <pathelement location="${catalina.home}/common/classes"/>
+    <fileset dir="${catalina.home}/common/endorsed">
+      <include name="*.jar"/>
+    </fileset>
+    <fileset dir="${catalina.home}/common/lib">
+      <include name="*.jar"/>
+    </fileset>
+    <pathelement location="${catalina.home}/shared/classes"/>
+    <fileset dir="${catalina.home}/shared/lib">
+      <include name="*.jar"/>
+    </fileset>
+  </path>
+
+  <path id="local.tomcat.classpath">
+    <!-- explicitly include the jni java wrappers in the classpath -->
+    <pathelement location="${lib.jni}"/>
+    <fileset dir="${lib.jni}">
+      <include name="*.jar"/>
+    </fileset>
+  </path>
+  
+  <path id="local.tomcat.path">
+    <pathelement location="${basedir}/bin/script"/>
+    <pathelement location="${basedir}/bin"/>
+    <pathelement location="${lib.jni}"/>
+    <pathelement path="${env.PATH}"/>
+    <pathelement path="${env.Path}"/>
+  </path>
+
+  <target name="test-setup">
+    <echo>ant java version=${ant.java.version}</echo>
+    <echo>is unix : ${current.os.isunix}</echo>
+    <echo>is mac : ${current.os.ismac}</echo>
+    <echo>is unixnotmac : ${current.os.isunixnotmac}</echo>
+    <echo>is windows : ${current.os.iswindows}</echo>
+    <echo>os.unix: ${os.unix}</echo>
+  </target>
+<!-- ==================== Primary and Global Targets ============================= -->
+
+  <!-- add comments about using xxx-core, xxx-packages if only want certain parts?? -->
+
+  <target name="prepare" depends="accept-properties,init,prepare-core,prepare-packages,prepare-gs2building,prepare-tomcat,prepare-axis,prepare-web,prepare-collections"
+    description="Use this when you first checkout the code: 'ant prepare install'. This will do some additional cvs checkouts and downloads, so you need to be online to run this.">
+    <!-- make sure .sh files are executable -->
+    <chmod dir="${basedir}" perm="ugo+rx" 
+      includes="*.sh"/>
+    <chmod dir="${basedir}/bin/script" perm="ugo+rx" 
+      includes="*.sh,*.pl"/>
+  </target>
+  <target name="install" depends="init,install-indexer-files,configure,configure-c++,compile" 
+    description="Install Greenstone 3. Use this when you first checkout the code: 'ant prepare install'."/>
+  
+  <target name="cvsupdate" depends="init,cvsupdate-packages,cvsupdate-core,cvsupdate-gs2building,cvsupdate-web"
+    description="Do a cvs update for all sources. Doesn't recompile the code. You need to be online to run this."/>
+
+  <target name="configure-c++" depends="init,configure-packages,configure-core,configure-gs2building"
+    description="Configure any C/C++ package code and gs2building code if necessary"/>
+  
+  <target name="configure" depends="init,configure-tomcat,configure-web"
+    description="Configure the installation. Includes setting up config files. Should be re-run if you change the build.properties file."/>
+
+  <target name="clean" depends="init,clean-packages,clean-core,clean-gs2building"
+    description="Remove all old compiled code. Includes core, packages and gs2building if necessary"/>
+  
+  <target name="compile" depends="init,compile-web,compile-packages,compile-core,compile-gs2building"
+    description="Compile all the source code, includes core, packages and gs2building if necessary. Copy jar files and executables to their correct places."/>
+    
+  <target name="update" depends="init,cvsupdate,clean,configure,configure-c++,compile" 
+    description="Update (thru CVS) all the source (including core, packages and gs2building), then clean, configure and recompile."/>
+
+  <target name="start" depends="init,start-tomcat"
+    description="Startup the Tomcat server." />
+
+  <target name="stop" depends="init,stop-tomcat" 
+    description="Shutdown the Tomcat server."/>
+  
+  <target name="restart" description="Shutdown and restart Tomcat"  depends="init,stop,start"/>
+
+
+<!-- =========== Help targets ===================================  -->
+  
+  <property name="install-command" value="ant [options] prepare install"/>
+  
+  <target name="usage" description="Print a help message">
+    <echo message="  Execute 'ant -projecthelp' for a list of targets."/>
+    <echo message="  Execute 'ant -help' for Ant help."/>
+    <echo>To install Greenstone3, run '${install-command}'. 
+There are properties defined in build.properties. The install process will ask you if these properties are set correctly. To avoid this prompt, use the '-Dproperties.accepted=yes' option.
+To log the output, use the '-logfile build.log' option.
+The README.txt file has more information about the ant targets and install process.
+    </echo>
+  </target>
+  
+  <target name="help" depends="usage" description="Print a help message"/>
+  
+  <target name="debug" depends="init" description="Display all the currently used properties">
+    <echoproperties/>
+  </target>
+
+<!-- ====== initialization and setup targets ================== -->
+
+  <target name="accept-properties" unless="properties.accepted">
+    <input addproperty="properties.ok" validargs="y,n">The following properties (among others) are being used from a build.properties file found in this directory:
+tomcat.server=${tomcat.server}
+tomcat.port=${tomcat.port} 
+tomcat.installed.path=${tomcat.installed.path} (this is the location of Tomcat's base dir if it is already installed)
+proxy.host=${proxy.host}
+proxy.port=${proxy.port}
+If these are not acceptable, please change them and rerun this target. Continue [y/n]? />
+    </input>
+    <condition property="do.abort"> 
+      <equals arg1="n" arg2="${properties.ok}"/>
+    </condition>
+    <fail if="do.abort">Build aborted by user. Please change your properties settings and re-run the target</fail>
+  </target>
+
+  <target name="check-cvsroot">
+    <condition property="cvsroot.notset">
+      <or>
+	<not>
+	  <isset property="env.CVSROOT"/>
+	</not>
+	<equals arg1="" arg2="${env.CVSROOT}"/>
+      </or>
+    </condition>
+    <fail if="cvsroot.notset" message="You need to set the CVSROOT variable"/>
+  </target>
+
+  <!-- this sets up some initial properties -->
+  <target name="init">
+
+    <condition property="java.too.old">
+      <or>
+	<equals arg1="1.1" arg2="${ant.java.version}"/>
+	<equals arg1="1.2" arg2="${ant.java.version}"/>
+	<equals arg1="1.3" arg2="${ant.java.version}"/>
+      </or>
+    </condition>
+    <fail if="java.too.old" message="You need Java 1.4 or greater to run Greenstone 3"/>
+    
+    <available file="${indexers.home}" property="indexers.present"/>
+    <available file="${basedir}/gli" property="gli.present"/>
+    <available file="${basedir}/gs2build" property="gs2build.present"/>
+
+    <condition property="tomcat.islocal">
+      <or>
+	<not>
+	  <isset property="tomcat.installed.path"/>
+	</not>
+	<equals arg1="" arg2="${tomcat.installed.path}"/>
+      </or>
+    </condition>
+    
+      <echo>tomcat.port:${tomcat.port}, gli.present:${gli.present} gs2build.present=${gs2build.present} gsdl2.installed.path = ${gsdl2.installed.path}</echo>
+    <condition property="proxy.present">
+      <and>
+	<isset property="proxy.host"/>
+	<not>
+	  <equals arg1="" arg2="${proxy.host}"/>
+	</not>
+      </and>
+    </condition>
+
+    <condition property="need.macos.extra">
+      <and>
+	<isset property="current.os.ismac"/>
+	<not>
+	  <isset property="disable.collection.building"/>
+	</not>
+      </and>
+    </condition>
+  </target>
+
+  <target name="setup-proxy" depends="init" if="proxy.present">
+    <condition property="ask.user">
+      <or>
+	<equals arg1="" arg2="${proxy.user}"/>
+	<equals arg1="" arg2="${proxy.password}"/>
+      </or>
+    </condition>
+    <getuserandpassword message="Using proxy: ${proxy.host}:${proxy.port}" if="ask.user" username="${proxy.user}" userproperty="proxy.username" pwordproperty="proxy.password"/>
+    <mysetproxy proxyhost="${proxy.host}" proxyport="${proxy.port}" proxyuser="${proxy.username}" proxypassword="${proxy.password}"/>
+  </target>
+     
+ <!-- ========== Web app Targets ================================ -->
+  
+  <target name="prepare-web" depends="init">
+    <mkdir dir="${web.home}/applet"/>
+    <mkdir dir="${web.home}/logs"/>
+    <condition property="need.xml.jars">
+      <equals arg1="1.5" arg2="${ant.java.version}"/>
+    </condition>
+    <antcall target="activate-xml-jars"/>
+    <antcall target="deactivate-xml-jars"/>
+  </target>
+  
+  <target name="configure-java-version" depends="init"
+    description="Run this target if you have changed the default version of java since installing greenstone3">
+    <condition property="need.xml.jars">
+      <equals arg1="1.5" arg2="${ant.java.version}"/>
+    </condition>
+    <antcall target="activate-xml-jars"/>
+    <antcall target="deactivate-xml-jars"/>
+    <condition property="need.tomcat.compat">
+      <equals arg1="1.5" arg2="${ant.java.version}"/>
+    </condition>
+    <antcall target="install-tomcat-compat"/>
+    <antcall target="uninstall-tomcat-compat"/>
+  </target>
+  
+  <target name="activate-xml-jars" if="need.xml.jars">
+    <copy file="${web.lib}/xalan.jar.tmp" tofile="${web.lib}/xalan.jar"/>
+    <copy file="${web.lib}/xercesImpl.jar.tmp" tofile="${web.lib}/xercesImpl.jar"/>
+  </target>
+  
+  <target name="deactivate-xml-jars" unless="need.xml.jars">
+    <delete file="${web.lib}/xalan.jar"/>
+    <delete file="${web.lib}/xercesImpl.jar"/>
+  </target>
+
+  <target name="prepare-collections" depends="init">
+    <property name="collect.dir" value="${web.home}/sites/localsite/collect"/>
+    <!-- gs2mgdemo -->
+    <unzip src="${collect.dir}/gs2mgdemo/import.zip" 
+      dest="${collect.dir}/gs2mgdemo"/>
+    <unzip src="${collect.dir}/gs2mgdemo/metadata.zip" 
+      dest="${collect.dir}/gs2mgdemo"/>
+    <unzip src="${collect.dir}/gs2mgdemo/index/index.zip" 
+      dest="${collect.dir}/gs2mgdemo/index"/>
+    <delete file="${collect.dir}/gs2mgdemo/import.zip"/>
+    <delete file="${collect.dir}/gs2mgdemo/metadata.zip"/>
+    <delete file="${collect.dir}/gs2mgdemo/index/index.zip"/>
+    <!-- gs2mgppdemo -->
+    <unzip src="${collect.dir}/gs2mgppdemo/import.zip" 
+      dest="${collect.dir}/gs2mgppdemo"/>
+    <unzip src="${collect.dir}/gs2mgppdemo/metadata.zip" 
+      dest="${collect.dir}/gs2mgppdemo"/>
+    <unzip src="${collect.dir}/gs2mgppdemo/index/index.zip" 
+      dest="${collect.dir}/gs2mgppdemo/index"/>
+    <delete file="${collect.dir}/gs2mgppdemo/import.zip"/>
+    <delete file="${collect.dir}/gs2mgppdemo/metadata.zip"/>
+    <delete file="${collect.dir}/gs2mgppdemo/index/index.zip"/>
+    <!-- gberg -->
+    <unzip src="${collect.dir}/gberg/index/index.zip" 
+      dest="${collect.dir}/gberg/index"/>
+    <delete file="${collect.dir}/gberg/index/index.zip"/>
+  </target>
+
+  
+  <target name="configure-web" depends="init"
+    description="Configure only the web app config files">
+    <!-- we want a unix path in the global.properties file -->
+    <pathconvert targetos="unix" property="src.gsdl3.home.unix">
+      <path path="${web.home}"/>
+    </pathconvert>
+    <filter token="gsdl3home" value="${src.gsdl3.home.unix}"/>
+    <filter token="gsdl3version" value="${app.version}"/>
+    <filter token="tomcat.server" value="${tomcat.server}"/>
+    <filter token="tomcat.port" value="${tomcat.port}"/>
+    <copy file="${basedir}/resources/java/global.properties.in" tofile="${web.classes}/global.properties" filtering="true" overwrite="true"/> 
+    <copy file="${basedir}/resources/java/log4j.properties.in" tofile="${web.classes}/log4j.properties" filtering="true" overwrite="true"/> 
+    <chmod file="${web.classes}/global.properties" perm="600"/>
+    <chmod file="${web.classes}/log4j.properties" perm="600"/>
+  </target>
+
+  <target name="compile-web" depends="init">
+    <javac srcdir="${web.classes}"
+      destdir="${web.classes}"
+      debug="${compile.debug}"
+      deprecation="${compile.deprecation}"
+      optimize="${compile.optimize}">
+      <classpath>
+	<path refid="compile.classpath"/>
+      </classpath>
+    </javac>
+  </target>
+
+  <target name="cvsupdate-web" unless="nocvs.mode">
+    <cvs command="update -dP" dest="${web.home}"/>
+  </target>
+
+  <target name="update-web" depends="init,cvsupdate-web,configure-web"
+    description="update only the web stuff (config files)"/>
+
+
+<!-- ======================= Tomcat Targets ========================== -->
+  
+  <!-- this target sets up tomcat for the first time, or resets it any subsequent times -->
+  <target name="prepare-tomcat" depends="init,download-tomcat" if="tomcat.islocal">
+    <condition property="need.tomcat.compat">
+      <equals arg1="1.4" arg2="${ant.java.version}"/>
+    </condition>
+    <antcall target="install-tomcat-compat"/>
+  </target>
+
+  <target name="download-tomcat" depends="init,setup-proxy" if="tomcat.islocal">
+    <!-- check that packages dir is there -->
+    <mkdir dir="${packages.home}"/>
+    <get src="http://www.greenstone.org/gs3files/apache-tomcat-5.5.12.zip"
+      dest="${packages.home}/apache-tomcat-5.5.12.zip"
+      usetimestamp="true"/>
+    <delete dir="${packages.home}/tomcat.bak"/>
+    <move todir="${packages.home}/tomcat.bak" failonerror="false">
+      <fileset dir="${packages.home}/tomcat"/>
+    </move>
+    <unzip src="${packages.home}/apache-tomcat-5.5.12.zip" 
+      dest="${packages.home}"/>
+    <move todir="${packages.home}/tomcat">
+      <fileset dir="${packages.home}/apache-tomcat-5.5.12"/>
+    </move>
+    <copy file="${basedir}/resources/tomcat/setclasspath.bat"
+      tofile="${packages.home}/tomcat/bin/setclasspath.bat"
+      overwrite="true"/>
+    <copy file="${basedir}/resources/tomcat/setclasspath.sh"
+      tofile="${packages.home}/tomcat/bin/setclasspath.sh"
+      overwrite="true"/>
+    <!-- make sure we have execute permission for the .sh files -->
+    <chmod dir="${packages.home}/tomcat/bin" perm="ugo+rx" 
+      includes="*.sh"/>
+    
+    <!-- download the compat module but don't install it unless necessary -->
+    <get src="http://www.greenstone.org/gs3files/apache-tomcat-5.5.12-compat.zip"
+      dest="${packages.home}/apache-tomcat-5.5.12-compat.zip"
+      usetimestamp="true"/>
+    <unzip src="${packages.home}/apache-tomcat-5.5.12-compat.zip" 
+      dest="${packages.home}"/>
+    <move todir="${packages.home}/tomcat-compat">
+      <fileset dir="${packages.home}/apache-tomcat-5.5.12"/>
+    </move>
+  </target>
+
+  
+  <target name="install-tomcat-compat" if="need.tomcat.compat">
+    <copy file="${packages.home}/tomcat-compat/common/endorsed/xml-apis.jar"
+      tofile="${web.applet}/xml-apis.jar"/>
+    <copy file="${packages.home}/tomcat-compat/common/endorsed/xml-apis.jar"
+      tofile="${packages.home}/tomcat/common/endorsed/xml-apis.jar"/>    
+    <copy file="${packages.home}/tomcat-compat/common/endorsed/xercesImpl.jar"
+      tofile="${web.applet}/xercesImpl.jar"/>
+    <copy file="${packages.home}/tomcat-compat/common/endorsed/xercesImpl.jar"
+      tofile="${packages.home}/tomcat/common/endorsed/xercesImpl.jar"/>
+    <copy file="${packages.home}/tomcat-compat/bin/jmx.jar"
+      tofile="${packages.home}/tomcat/bin/jmx.jar"/>
+  </target>
+  <target name="uninstall-tomcat-compat" unless="need.tomcat.compat">
+    <delete file="${web.applet}/xml-apis.jar"/>
+    <delete file="${packages.home}/tomcat/common/endorsed/xml-apis.jar"/>    
+    <delete file="${web.applet}/xercesImpl.jar"/>
+    <delete file="${packages.home}/tomcat/common/endorsed/xercesImpl.jar"/>
+    <delete file="${packages.home}/tomcat/bin/jmx.jar"/>
+  </target>
+  
+  <target name="configure-tomcat" depends="init,configure-tomcat-local,configure-tomcat-external"/>
+  
+  <target name="configure-tomcat-local" depends="init" if="tomcat.islocal">
+    <!-- re-setup the server.xml file -->
+    <copy file="${basedir}/resources/tomcat/server.xml" tofile="${packages.home}/tomcat/conf/server.xml" overwrite="true">
+      <filterset>
+	<filter token="port" value="${tomcat.port}"/>
+	<filter token="shutdown-port" value="${tomcat.shutdown.port}"/>
+      </filterset>
+    </copy>
+    <!-- set up the greenstone3 context -->
+    <copy file="${basedir}/resources/tomcat/greenstone3.xml" tofile="${packages.home}/tomcat/conf/Catalina/localhost/greenstone3.xml" overwrite="true">
+      <filterset>
+	<filter token="gsdl3webhome" value="${basedir}/web"/>
+      </filterset>
+    </copy>
+  </target>
+
+  <target name="configure-tomcat-external" depends="init" unless="tomcat.islocal">
+    <!-- re-setup the server.xml file -->
+    <!-- need to edit the config file, or do we get the user to do this???-->
+  </target>
+  
+  <target name="reload" description="Reload web application"
+          depends="init,setup-catalina-ant-tasks">
+    <reload  url="http://${tomcat.server}:${tomcat.port}/manager" username="admin" password="admin"
+            path="${app.path}"/>
+  </target>
+  
+  <target name="start-tomcat" description="Startup only Tomcat" depends="init" if="tomcat.islocal">
+   <property name="tomcat.classpath" refid="local.tomcat.classpath"/>
+    <property name="tomcat.path" refid="local.tomcat.path"/>
+    <property name="catalina.opts" value="-Djava.util.prefs.syncInterval=2000000 -DGSDL3HOME=$GSDL3HOME -DGSDLOS=$GSDLOS -DPATH=$PATH -Xmx400M"/>
+    <exec executable="${catalina.home}/bin/startup.sh" os="${os.unix}" dir="${catalina.home}/bin" spawn="false">
+      <!--<env key="GSDLOS" value="linux"/> do we need this?? -->
+      <env key="GSDL3HOME" value="${basedir}"/>
+      <env key="PATH" path="${tomcat.path}"/>
+      <env key="CATALINA_OPTS" value="${catalina.opts}"/>
+      <env key="CATALINA_HOME" value="${catalina.home}"/>
+      <env key="CLASSPATH" path="${tomcat.classpath}"/>
+      <env key="LD_LIBRARY_PATH" path="${env.LD_LIBRARY_PATH}:${lib.jni}"/>
+      <env key="DYLD_LIBRARY_PATH" path="${env.DYLD_LIBRARY_PATH}:${lib.jni}:${gdbm.installed.path}/lib"/> <!-- for mac os -->
+    </exec>
+    <exec executable="${catalina.home}/bin/startup.bat" os="${os.windows}" dir="${catalina.home}/bin" spawn="true">
+      <env key="GSDLOS" value="windows"/>
+      <env key="GSDL3HOME" value="${basedir}"/>
+      <env key="Path" path="${tomcat.path}"/>
+      <env key="PATH" path="${tomcat.path}"/>
+      <env key="CATALINA_OPTS" value="${catalina.opts}"/>
+      <env key="CLASSPATH" path="${tomcat.classpath}"/>
+    </exec>
+    <!-- wait for the server to startup in case other targets need it running -->
+    <waitfor maxwait="5" maxwaitunit="second">
+      <and>
+	<socket server="${tomcat.server}" port="${tomcat.port}"/>
+	<http url="http://${tomcat.server}:${tomcat.port}${app.path}/index.html"/>
+      </and>
+    </waitfor>
+  </target>
+  <!-- windows: do we want to launch a webrowser?? -->
+  <target name="stop-tomcat" description="Shutdown only Tomcat" depends="init" if="tomcat.islocal">
+    <exec executable="${catalina.home}/bin/shutdown.sh" os="${os.unix}" dir="${catalina.home}/bin" spawn="false">
+      <env key="CATALINA_HOME" value="${catalina.home}"/>
+    </exec>
+    <exec executable="${catalina.home}/bin/shutdown.bat" os="${os.windows}" dir="${catalina.home}/bin" spawn="false"/>
+  </target>
+
+  <target name="restart-tomcat" description="Shutdown and restart only Tomcat" depends="init,stop-tomcat,start-tomcat"/>
+
+  <target name="setup-catalina-ant-tasks">
+    <!-- Configure the custom Ant tasks for the Tomcat Manager application -->
+    <taskdef name="deploy"    classname="org.apache.catalina.ant.DeployTask"
+      classpath="${catalina.home}/server/lib/catalina-ant.jar"/>
+    <taskdef name="list"      classname="org.apache.catalina.ant.ListTask"
+      classpath="${catalina.home}/server/lib/catalina-ant.jar"/>
+    <taskdef name="reload"    classname="org.apache.catalina.ant.ReloadTask"
+      classpath="${catalina.home}/server/lib/catalina-ant.jar"/>
+    <taskdef name="resources" classname="org.apache.catalina.ant.ResourcesTask"
+      classpath="${catalina.home}/server/lib/catalina-ant.jar"/>
+    <taskdef name="roles"     classname="org.apache.catalina.ant.RolesTask"
+      classpath="${catalina.home}/server/lib/catalina-ant.jar"/>
+    <taskdef name="start"     classname="org.apache.catalina.ant.StartTask"
+      classpath="${catalina.home}/server/lib/catalina-ant.jar"/>
+    <taskdef name="stop"      classname="org.apache.catalina.ant.StopTask"
+      classpath="${catalina.home}/server/lib/catalina-ant.jar"/>
+    <taskdef name="undeploy"  classname="org.apache.catalina.ant.UndeployTask"
+      classpath="${catalina.home}/server/lib/catalina-ant.jar"/>
+  </target>
+
+
+
+
+
+
+<!-- ======================= ant Targets ============================ --> 
+  <target name="prepare-ant" depends="init">
+    <get src="http://www.greenstone.org/gs3files/apache-ant-1.7.0-bin.zip"
+      dest="${packages.home}/apache-ant-1.7.0-bin.zip"
+      usetimestamp="true"/>
+    <unzip src="${packages.home}/apache-ant-1.7.0-bin.zip"
+      dest="${packages.home}"/>
+    <move todir="${packages.home}/ant">
+      <fileset dir="${packages.home}/apache-ant-1.7.0"/>
+    </move>
+  </target>
+
+<!-- ======================= Axis Targets ============================ --> 
+
+  <target name="prepare-axis" depends="init">
+    <get src="http://www.greenstone.org/gs3files/axis-bin-1_2_1.zip"
+      dest="${packages.home}/axis-bin-1_2_1.zip"
+      usetimestamp="true"/>
+    <unzip src="${packages.home}/axis-bin-1_2_1.zip"
+      dest="${packages.home}"/>
+    <move todir="${packages.home}/axis">
+      <fileset dir="${packages.home}/axis-1_2_1"/>
+    </move>
+    <!-- install axis into greenstone web app -->
+    <copy todir="${web.lib}">
+      <fileset dir="${packages.home}/axis/webapps/axis/WEB-INF/lib">
+	<include name="*.jar"/>
+      </fileset>
+    </copy>
+    <copy todir="${web.home}">
+      <fileset dir="${packages.home}/axis/webapps/axis/">
+	<include name="*.jsp"/>
+	<include name="*.jws"/>
+      </fileset>
+    </copy>
+    <copy tofile="${web.home}/axis.html" file="${packages.home}/axis/webapps/axis/index.html"/>
+    <copy todir="${web.classes}">
+      <fileset dir="${packages.home}/axis/webapps/axis/WEB-INF/classes">
+	<include name="*.properties"/>
+      </fileset>
+    </copy>
+  </target>
+
+  <target name="soap-deploy-site" depends="init,get-sitename,get-siteuri,create-deployment-files,deploy-site"
+    description="Deploy a SOAP web service for a local Greenstone site. Tomcat must be running for this to work."/>
+  
+  <target name="deploy-site">
+    <java classname="org.apache.axis.client.AdminClient">
+      <classpath refid="compile.classpath"/>
+      <arg value="-l"/>
+      <arg value="http://${tomcat.server}:${tomcat.port}${app.path}/servlet/AxisServlet"/>
+      <arg file="${basedir}/resources/soap/${axis.sitename}.wsdd"/>
+    </java>    
+  </target>
+  
+  <target name="soap-undeploy-site" depends="get-sitename"
+    description="Undeploy a SOAP web service for a local Greenstone site. Tomcat must be running for this to work.">
+    <java classname="org.apache.axis.client.AdminClient">
+      <classpath refid="compile.classpath"/>
+      <arg value="-l"/>
+      <arg value="http://${tomcat.server}:${tomcat.port}${app.path}/servlet/AxisServlet"/>
+      <arg file="${basedir}/resources/soap/undeploy-${axis.sitename}.wsdd"/>
+    </java>
+  </target>
+
+  <!-- this target used to deploy the preprepared localsite server  -->
+  <target name="deploy-localsite" depends="init" 
+    description="Deploy the SOAP server for localsite. Will start and stop Tomcat.">
+    <antcall target="start-tomcat"/>
+    <antcall target="deploy-site">
+      <param name="axis.sitename" value="localsite"/>
+    </antcall>
+    <antcall target="stop-tomcat"/>
+  </target>
+  
+  <target name="get-sitename" unless="axis.sitename">
+    <input addproperty="axis.sitename" message="What site? (press enter for default:localsite)" defaultvalue="localsite"/>
+  </target>
+
+  <target name="get-siteuri" depends="get-sitename" unless="axis.siteuri">
+    <input addproperty="axis.siteuri" message="What name do you want the service to have? (press enter for default:${axis.sitename})" defaultvalue="${axis.sitename}"/>
+    <echo>${axis.sitename}, ${axis.siteuri}</echo>
+  </target>
+
+  <target name="check-deployment-files" depends="get-sitename">
+    <condition property="deploy.exists">
+      <and>
+	<available file="${basedir}/resources/soap/${axis.sitename}.wsdd"/>
+	<available file="${basedir}/resources/soap/undeploy-${axis.sitename}.wsdd"/>
+	<available file="${web.classes}/org/greenstone/gsdl3/SOAPServer${axis.sitename}.class"/>
+      </and>
+    </condition>
+   </target> 
+
+  <target name="create-deployment-files" depends="get-sitename,get-siteuri,check-deployment-files" 
+    if="axis.sitename" unless="deploy.exists">
+    <filter token="sitename" value="${axis.sitename}"/>
+    <filter token="siteuri" value="${axis.siteuri}"/>
+    <copy file="${basedir}/resources/soap/site.wsdd.template"
+      tofile="${basedir}/resources/soap/${axis.sitename}.wsdd"
+      filtering="true"/>
+     <copy file="${basedir}/resources/soap/undeploy-site.wsdd.template"
+      tofile="${basedir}/resources/soap/undeploy-${axis.sitename}.wsdd"
+      filtering="true"/>
+    <!-- create the java files and compile them -->
+    <copy file="${basedir}/resources/java/SOAPServer.java.in"
+      tofile="${src.gsdl3.home}/SOAPServer${axis.sitename}.java"
+      filtering="true"/>
+    <mkdir dir="${build.home}"/>
+    <javac srcdir="${src.home}"
+      destdir="${build.home}" 
+      debug="${compile.debug}"
+      deprecation="${compile.deprecation}"
+      optimize="${compile.optimize}">
+      <classpath refid="compile.classpath"/>
+      <include name="org/greenstone/gsdl3/SOAPServer${axis.sitename}.java" />
+    </javac>
+    <mkdir dir="${web.classes}/org/greenstone/gsdl3"/>
+    <copy file="${build.home}/org/greenstone/gsdl3/SOAPServer${axis.sitename}.class" tofile="${web.classes}/org/greenstone/gsdl3/SOAPServer${axis.sitename}.class" />
+  </target>
+    
+
+<!-- ====================== Core targets ============================== -->
+<!-- core targets refer to the core gsdl3 java src -->
+  
+  <target name="prepare-core" unless="nocvs.mode">
+    <!-- just get rid of empty directories-->
+    <cvs command="update -P"/>
+  </target>
+  
+  <target name="configure-core"/>
+
+  <target name="update-core" depends="init,cvsupdate-core,clean-core,compile-core"
+    description="Update only the Greenstone core" />
+  
+  <target name="cvsupdate-core" unless="nocvs.mode">
+    <cvs command="update -l"/>
+    <cvs command="update -dP bin comms dist-resources docs lib resources src winutil"/>
+  </target>
+
+  <target name="clean-core"
+    description="Clean only the Greenstone core">
+    <delete dir="${build.home}"/>
+  </target>
+
+   <target name="compile-core" depends="init" 
+    description="Compile only the Greenstone core">
+    <mkdir dir="${build.home}"/>
+    <javac srcdir="${src.home}"
+      destdir="${build.home}"
+      debug="${compile.debug}"
+      deprecation="${compile.deprecation}"
+      optimize="${compile.optimize}">
+      <classpath>
+	<path refid="compile.classpath"/>
+      </classpath>
+    </javac>
+    <jar destfile="${build.home}/gsdl3.jar">
+      <fileset dir="${build.home}">
+	<include name="org/greenstone/gsdl3/**"/>
+	<exclude name="**/Test.class"/>
+      </fileset>
+      <manifest>
+	<attribute name="Built-By" value="${user.name}" />
+      </manifest>
+    </jar>
+    <copy file="${build.home}/gsdl3.jar" todir="${web.lib}"/>
+    <!-- copy the localsite server in case we need it -->
+    <copy file="${build.home}/org/greenstone/gsdl3/SOAPServerlocalsite.class" tofile="${web.classes}/org/greenstone/gsdl3/SOAPServerlocalsite.class" />
+
+    <jar destfile="${build.home}/GAI.jar">
+      <fileset dir="${build.home}">
+	<include name="org/greenstone/admin/**"/>
+      </fileset>
+      <manifest>
+	<attribute name="Built-By" value="${user.name}" />
+      </manifest>
+    </jar>
+      
+    <jar destfile="${build.home}/phind.jar">
+      <fileset dir="${build.home}">
+	<include name="org/greenstone/applet/phind/**"/>
+      </fileset>
+      <manifest>
+	<attribute name="Built-By" value="${user.name}" />
+      </manifest>
+    </jar>
+    <copy file="${build.home}/phind.jar" todir="${web.applet}"/>
+    <jar destfile="${build.home}/anttasks.jar">
+      <fileset dir="${build.home}">
+	<include name="org/greenstone/anttasks/**"/>
+      </fileset>
+      <manifest>
+	<attribute name="Built-By" value="${user.name}" />
+      </manifest>
+    </jar>
+    <copy file="${build.home}/anttasks.jar" todir="${basedir}/lib/java"/>
+    <jar destfile="${build.home}/gsdl3test.jar">
+      <fileset dir="${build.home}">
+	<include name="org/greenstone/gsdl3/**/*Test.class"/>
+	<include name="org/greenstone/testing/**"/>
+      </fileset>
+      <manifest>
+	<attribute name="Built-By" value="${user.name}" />
+      </manifest>
+    </jar>
+    <jar destfile="${build.home}/server.jar">
+      <fileset dir="${build.home}">
+	<include name="org/greenstone/server/**"/>
+      </fileset>
+      <fileset file="${basedir}/resources/java/server.properties"/>
+      <manifest>
+	<attribute name="Built-By" value="${user.name}"/>
+      </manifest>
+    </jar>
+    <copy file="${build.home}/server.jar" todir="${basedir}"/>
+  </target>
+ 
+<!-- ================== Packages targets ================================ -->
+  <!-- these targets refer to the greenstone source packages - these need 
+  updating less often, so are in  separate targets to the core -->
+  <target name="prepare-packages" depends="init,prepare-indexers"/>
+  
+  <target name="checkout-indexers" depends="check-cvsroot,init" if="independent-indexers" unless="nocvs.mode">
+    <cvs command="checkout -P" package="indexers" dest="${src.packages.home}"/>
+  </target>
+  
+  <target name="prepare-indexers" depends="init" if="independent-indexers" unless="indexers.present">
+    <antcall target="checkout-indexers"/>
+  </target>
+
+  <target name="update-packages" depends="init,cvsupdate-packages,configure-packages,clean-packages,compile-packages"
+    description="Update only the source packages"/>
+
+  <target name="cvsupdate-packages" unless="nocvs.mode"> 
+    <cvs command="update -dP" dest="${src.packages.home}"/>
+  </target>
+  
+  <target name="configure-packages" depends="init,configure-javagdbm,configure-indexers" 
+    description="Configure only the packages."/>
+  
+  <target name="configure-javagdbm">
+    <echo>
+      Configuring JavaGDBM
+    </echo>
+    <exec executable="${javagdbm.home}/configure" os="${os.linux},${os.solaris}"
+      dir="${javagdbm.home}">
+      <arg value="--prefix=${basedir}"/>
+      <arg value="--libdir=${lib.jni}"/>
+    </exec>    
+    <exec executable="${javagdbm.home}/configure" os="${os.mac}"
+      dir="${javagdbm.home}">
+      <arg value="--prefix=${basedir}"/>
+      <arg value="--libdir=${lib.jni}"/>
+     <arg value="--with-gdbm=${gdbm.installed.path}"/>
+    </exec>    
+    
+  </target>
+  <target name="configure-indexers" depends="init" if="independent-indexers">
+    <echo>
+      Configuring Indexers
+    </echo>
+    <exec executable="${indexers.home}/configure" os="${os.unix}"
+      dir="${indexers.home}">
+      <arg value="--prefix=${basedir}"/>
+      <arg value="--libdir=${lib.jni}"/>
+    </exec>          
+  </target>
+
+  <target name="clean-packages" depends="init,clean-javagdbm,clean-indexers" description="Clean only the packages"/>
+
+  <target name="clean-javagdbm" depends="init">
+    <exec executable="make" os="${os.unix}"
+      dir="${javagdbm.home}">
+      <arg value="clean"/>
+    </exec>
+  </target>
+  
+  <target name="clean-indexers" depends="init" if="independent-indexers">
+    <exec executable="make" os="${os.unix}"
+      dir="${indexers.home}">
+      <arg value="clean"/>
+    </exec>
+    <exec executable="${indexers.home}/winMake.bat" os="${os.windows}"
+       dir="${indexers.home}">
+       <arg value="clean"/>
+    </exec>
+
+  </target>
+   
+  <target name="compile-packages"
+    description="Compile only the source packages">    
+    <!-- javagdbm -->
+    <exec executable="make" os="${os.unix}"
+      dir="${javagdbm.home}">
+    </exec>
+    <exec executable="make" os="${os.unix}"
+      dir="${javagdbm.home}">
+      <arg value="install"/>
+    </exec>
+    <!-- windows: just the java stuff. -->
+    <exec executable="${javagdbm.home}/winMake.bat" os="${os.windows}"
+      dir="${javagdbm.home}">
+      <arg value="compile"/>
+      <arg value="javaonly"/>
+    </exec>
+    <!-- install the jar file -->
+    <copy file="${javagdbm.home}/javagdbm.jar" todir="${lib.jni}"/>
+    
+    <!-- Indexers -->
+    <!-- this may be in gs2build - we will be recompiling, but never mind -->
+    <exec executable="make" os="${os.unix}"
+      dir="${indexers.home}">
+    </exec>
+    <exec executable="make" os="${os.unix}"
+      dir="${indexers.home}">
+      <arg value="install"/>
+    </exec>
+    <exec executable="${indexers.home}/winMake.bat" os="${os.windows}"
+       dir="${indexers.home}">
+       <arg value="all"/>
+    </exec>
+    <exec executable="${indexers.home}/winMake.bat" os="${os.windows}"
+       dir="${indexers.home}">
+       <arg value="install"/>
+    </exec>
+    <!-- install the jar and jni files -->
+    <copy file="${mg.home}/mg.jar" todir="${lib.jni}"/>
+    <copy file="${mgpp.home}/mgpp.jar" todir="${lib.jni}"/>
+    <copy file="${lucene.home}/LuceneWrapper.jar" todir="${web.lib}"/>
+    <antcall target="install-jni-files"/>
+  </target>
+
+  <target name="install-jni-files" depends="init,install-jni-files-linux,install-jni-files-windows,install-jni-files-macos"/>
+
+  <target name="install-jni-files-linux" depends="init" if="current.os.isunixnotmac">
+    <copy file="${mg.home}/jni/libmgjni.so" todir="${lib.jni}"/>
+    <copy file="${mg.home}/jni/libmgpassjni.so" todir="${lib.jni}"/>
+    <copy file="${mgpp.home}/jni/libmgppjni.so" todir="${lib.jni}"/>
+    <copy file="${mgpp.home}/jni/libmgpppassjni.so" todir="${lib.jni}"/>
+  </target>
+  <target name="install-jni-files-windows" depends="init" if="current.os.iswindows">
+    <copy file="${mg.home}/jni/mgjni.dll" todir="${lib.jni}"/>
+    <copy file="${mg.home}/jni/mgpassjni.dll" todir="${lib.jni}"/>
+    <copy file="${mgpp.home}/jni/mgppjni.dll" todir="${lib.jni}"/>
+    <copy file="${mgpp.home}/jni/mgpppassjni.dll" todir="${lib.jni}"/>
+  </target>
+  <target name="install-jni-files-macos" depends="init" if="current.os.ismac">
+    <copy file="${mg.home}/jni/libmgjni.jnilib" todir="${lib.jni}"/>
+    <copy file="${mg.home}/jni/libmgpassjni.jnilib" todir="${lib.jni}"/>
+    <copy file="${mgpp.home}/jni/libmgppjni.jnilib" todir="${lib.jni}"/>
+    <copy file="${mgpp.home}/jni/libmgpppassjni.jnilib" todir="${lib.jni}"/>
+  </target>
+ 
+  <!-- ================== gs2building targets ===============-->
+
+
+  <target name="update-gs2building" if="collection.building.enabled" 
+    depends="init,cvsupdate-gs2building,rename-gs2build-files,configure-gs2building,clean-gs2building,compile-gs2building"
+    description="Update only the Greenstone 2 building components"/>
+
+  <target name="cvsupdate-gs2building" if="collection.building.enabled" depends="init,cvsupdate-gs2build,cvsupdate-gli" unless="nocvs.mode">
+  </target>
+  <target name="cvsupdate-gs2build" if="collection.building.enabled" depends="init" unless="nocvs.mode">
+    <!-- Note: can't do a -d update here cos it will get all of gsdl 
+     also, an update doesn't get new files, so we do a checkout instead. -->
+    <cvs command="checkout -P" package="gs2build" dest="${basedir}"/>
+  </target>
+  
+  <target name="cvsupdate-gli" if="collection.building.enabled" depends="init" unless="nocvs.mode">
+    <cvs command="update -dP" dest="${gli.home}"/>
+  </target>
+
+  <target name="prepare-gs2building" depends="init,prepare-gs2build,prepare-gli" if="collection.building.enabled">
+  </target>
+
+  <target name="checkout-gs2build" depends="check-cvsroot,init" if="collection.building.enabled" unless="nocvs.mode">
+    <echo>checking out gs2build</echo>
+    <cvs command="checkout -P" package="gs2build"/>
+  </target>
+
+  <target name="prepare-gs2build" depends="init" if="collection.building.enabled" unless="gs2build.present">
+    <antcall target="checkout-gs2build"/>
+    <antcall target="rename-gs2build-files"/>
+    <antcall target="unzip-windows-packages"/>
+    <antcall target="checkout-winbin"/>
+    <antcall target="get-windows-binaries"/>
+    <antcall target="delete-winbin"/>
+    <antcall target="get-macos-extra"/>
+  </target>
+
+  <target name="checkout-winbin" depends="init" if="current.os.iswindows" 
+    unless="nocvs.mode">
+    <cvs command="checkout -P" package="winbin"/>
+  </target>
+  
+  <target name="get-windows-binaries" depends="init" if="collection.building.enabled.windows">
+    <move todir="${gs2build.home}/bin/windows" failonerror="false">
+      <fileset dir="${basedir}/winbin/bin"/>
+    </move>
+  </target>
+  <target name="delete-winbin" depends="init" if="collection.building.enabled.windows">
+    <delete dir="${basedir}/winbin"/>
+  </target>
+  
+  <target name="unzip-windows-packages" depends="init" if="collection.building.enabled.windows">  
+    <unzip src="${gs2build.home}/packages/windows/gdbm/gdbm.zip"
+    dest="${gs2build.home}/packages/windows/gdbm"/>
+   <unzip src="${gs2build.home}/packages/windows/crypt/crypt.zip"
+    dest="${gs2build.home}/packages/windows/crypt"/>
+       <unzip src="${gs2build.home}/packages/windows/expat/expat.zip"
+    dest="${gs2build.home}/packages/windows/expat"/>
+   </target>
+  
+  <!-- downloads a good XML-Parser -->
+  <target name="get-macos-extra" depends="init" if="need.macos.extra">	
+      <get src="http://www.greenstone.org/gs3files/XML-Parser.tar.gz"
+      dest="${gs2build.home}/perllib/cpan/XML-Parser.tar.gz"
+      usetimestamp="true"/>
+  </target>  
+
+  <!-- untars the XML-Parser. need to do this after compiling in gs2build-->
+  <target name="install-macos-extra" depends="init" if="need.macos.extra">
+    <!-- make sure these directories are present, otherwise chmod craps out 
+    this chmod is needed in case we are unpacking for a second time -->
+    <mkdir dir="${gs2build.home}/perllib/cpan/perl-5.8"/>
+    <mkdir dir="${gs2build.home}/perllib/cpan/perl-5.6"/>
+    <chmod dir="${gs2build.home}/perllib/cpan/perl-5.8" perm="ug+w" includes="**"/>
+    <chmod dir="${gs2build.home}/perllib/cpan/perl-5.6" perm="ug+w" includes="**"/>
+    <untar src="${gs2build.home}/perllib/cpan/XML-Parser.tar.gz"
+      dest="${gs2build.home}/perllib/cpan/"
+      compression="gzip"/>
+  </target>
+
+  <target name="install-indexer-files" depends="init" unless="indexers.present">
+    <copy todir="${indexers.home}">
+      <fileset dir="${gs2build.home}/indexers" />
+    </copy>
+    <chmod file="${indexers.home}/configure" perm="a+x"/>
+  </target>
+
+  <target name="rename-gs2build-files" depends="rename-gs2build-files-unix,rename-gs2build-files-windows,gs2build-edit-setup-bat" if="collection.building.enabled"/>
+  
+  <target name="gs2build-edit-setup-bat" if="collection.building.enabled.windows">
+    <!-- we want a windows path in the setup.bat file -->
+    <pathconvert targetos="windows" property="gs2build.home.windows">
+      <path path="${gs2build.home}"/>
+    </pathconvert>
+    <move file="${gs2build.home}/setup.bat" tofile="${gs2build.home}/setup-tmp.bat">
+      <filterset>
+	<filter token="gsdlhome" value="${gs2build.home.windows}"/>
+     </filterset>
+    </move>  
+    <move file="${gs2build.home}/setup-tmp.bat" tofile="${gs2build.home}/setup.bat" />
+  </target>
+  
+  <target name="rename-gs2build-files-windows" if="collection.building.enabled.windows">
+    <property name="gs2build-extra.home" value="${gs2build.home}/gs2build-extra"/>
+    <copy file="${gs2build-extra.home}/lib.win32.mak" tofile="${gs2build.home}/lib/win32.mak"/>
+    <copy file="${gs2build-extra.home}/win32.mak" tofile="${gs2build.home}/win32.mak"/>
+    <copy file="${gs2build-extra.home}/setup.bat" tofile="${gs2build.home}/setup.bat"/>
+  </target> 
+  
+  <target name="rename-gs2build-files-unix" if="collection.building.enabled.unix">
+    <property name="gs2build-extra.home" value="${gs2build.home}/gs2build-extra"/>
+    <copy file="${gs2build-extra.home}/configure" tofile="${gs2build.home}/configure"/>    
+    <chmod file="${gs2build.home}/configure" perm="a+x"/>
+    <copy file="${gs2build-extra.home}/configure.in" tofile="${gs2build.home}/configure.in"/>
+    <copy file="${gs2build-extra.home}/Makefile.in" tofile="${gs2build.home}/Makefile.in"/>  
+    <copy file="${gs2build-extra.home}/packages.configure" tofile="${gs2build.home}/packages/configure"/>
+    <chmod file="${gs2build.home}/packages/configure" perm="a+x"/>
+    <copy file="${gs2build-extra.home}/packages.Makefile.in" tofile="${gs2build.home}/packages/Makefile.in"/>
+    <copy file="${gs2build-extra.home}/lib.Makefile.in" tofile="${gs2build.home}/lib/Makefile.in"/>  
+  </target>
+  
+  <target name="prepare-gli" depends="init" if="collection.building.enabled" unless="gli.present">
+    <antcall target="checkout-gli"/>
+  </target>
+  
+  <target name="checkout-gli" depends="check-cvsroot,init" if="collection.building.enabled" unless="nocvs.mode">
+    <echo>checking out gli</echo>
+    <cvs command="checkout -P" package="gli"/>
+  </target>
+    
+  <target name="configure-gs2building" depends="init" if="collection.building.enabled"
+    description="Configure only the Greenstone 2 building components">
+    <exec executable="${gs2build.home}/configure" os="${os.linux},${os.solaris}"
+      dir="${gs2build.home}">
+      <arg value="--prefix=${gs2build.home}"/>
+    </exec>
+    <exec executable="${gs2build.home}/configure" os="${os.mac}"
+      dir="${gs2build.home}">
+      <arg value="--prefix=${gs2build.home}"/>
+      <arg value="--with-gdbm=${gdbm.installed.path}"/>
+    </exec>
+  </target>
+
+  <target name="clean-gs2building" depends="init,clean-gli,clean-gs2build" 
+    description="Clean only the Greenstone 2 building components" 
+    if="collection.building.enabled"/>
+  
+  <target name="clean-gli" depends="init" if="collection.building.enabled">
+    <!-- gli -->
+    <property name="gli.home" value="${basedir}/gli"/>
+    <!-- linux -->
+    <exec executable="clean.sh" os="${os.unix}" dir="${gli.home}"
+      resolveExecutable="true"/>
+    <!-- windows -->
+    <exec executable="clean.bat" os="${os.windows}" dir="${gli.home}"
+      resolveExecutable="true"/>
+  </target>
+  
+  <target name="clean-gs2build" depends="init" if="collection.building.enabled">
+    <!-- gs2build -->
+    <!--linux:  -->
+    <exec executable="make" os="${os.unix}" dir="${gs2build.home}">
+      <arg value="clean"/>
+    </exec>
+    <!-- windows: -->    
+    <!-- run the setup script -->
+    <exec executable="${compile.windows.c++.setup}"/>
+    <exec executable="nmake" dir="${gs2build.home}">
+     <arg value="/f"/>
+     <arg value="win32.mak"/>
+     <arg value="clean"/>
+    </exec>
+  </target>
+  
+  <target name="distclean-gs2build" depends="init" if="collection.building.enabled">
+    <!-- gs2build -->
+    <!--linux:  -->
+    <exec executable="make" os="${os.unix}" dir="${gs2build.home}">
+      <arg value="distclean"/>
+    </exec>
+    <!-- windows: -->    
+  </target>
+  
+  <target name="compile-gs2building" depends="init,compile-gs2build,compile-gli" if="collection.building.enabled"
+    description="Compile only the Greenstone 2 building components">
+  </target>
+  
+  <target name="compile-gli" depends="init" if="collection.building.enabled">
+    <!-- gli -->
+    <property name="gli.home" value="${basedir}/gli"/>
+    <!-- linux -->
+    <exec executable="makegli.sh" os="${os.unix}" dir="${gli.home}"
+      resolveExecutable="true"/>
+    <!-- windows -->
+    <exec executable="makegli.bat" os="${os.windows}" dir="${gli.home}"
+      resolveExecutable="true"/>
+  </target>
+  
+  <target name="compile-gs2build" depends="init" if="collection.building.enabled">
+    <!-- gs2build -->
+    <!--linux: make, make install -->
+    <exec executable="make" os="${os.unix}" dir="${gs2build.home}">
+    </exec>
+    <exec executable="make" os="${os.unix}" dir="${gs2build.home}">
+      <arg value="install"/>
+    </exec>
+    <!-- run the setup script -->
+    <exec executable="${compile.windows.c++.setup}" os="${os.windows}"/>
+    <exec executable="nmake" dir="${gs2build.home}" os="${os.windows}">
+     <arg value="/f"/>
+     <arg value="win32.mak"/>
+    </exec>
+    <exec executable="nmake" dir="${gs2build.home}" os="${os.windows}">
+     <arg value="/f"/>
+     <arg value="win32.mak"/>
+     <arg value="install"/>
+    </exec>
+    <!-- LuceneWrapper jar file not installed by default -->
+    <mkdir dir="${gs2build.home}/bin/java"/>
+    <copy file="${lucene.home}/LuceneWrapper.jar" todir="${gs2build.home}/bin/java"/>
+    <antcall target="install-gs2build-indexers-windows"/>
+    <antcall target="install-macos-extra"/>
+  </target>
+  
+  <target name="install-gs2build-indexers-windows" depends="init" if="collection.building.enabled.windows">
+    <copy todir="${gs2build.home}/bin/windows">
+      <fileset dir="${gs2build.home}/indexers/bin">
+	<include name="*.*"/>
+      </fileset>
+    </copy>
+  </target>
+
+  <target name="gli" description="Run the Greenstone Librarian Interface" depends="init" if="collection.building.enabled">
+    <exec executable="${basedir}/gli/gli4gs3.sh" os="${os.linux},${os.solaris}" dir="${basedir}/gli" spawn="true">
+      <env key="gsdl3path" path="${basedir}"/>
+      <env key="gsdlpath" path="${basedir}/gs2build"/>
+    </exec>
+    <exec executable="${basedir}/gli/gli4gs3.sh" os="${os.mac}" dir="${basedir}/gli" spawn="true">
+      <env key="gsdl3path" path="${basedir}"/>
+      <env key="gsdlpath" path="${basedir}/gs2build"/>
+      <env key="DYLD_LIBRARY_PATH" path="${env.DYLD_LIBRARY_PATH}:${gdbm.installed.path}/lib"/>
+    </exec>
+    <exec executable="${basedir}/gli/gli4gs3.bat" os="${os.windows}" dir="${basedir}/gli" spawn="true">
+      <env key="GSDL3PATH" path="${basedir}"/>
+      <env key="GSDLPATH" path="${basedir}/gs2build"/>
+    </exec>
+    <echo>Running GLI from Ant means that you don't get to see any of the terminal output. If you have problems with GLI and want to see the output, please run the script gli4gs3.sh/bat from the greenstone3/gli directory.
+    </echo>
+  </target>
+ 
+
+<!-- ======================== TESTING Targets ========================= -->
+  
+  <target name="test" description="Run the (incomplete) JUnit test suite "
+    depends="init">
+    <mkdir dir="${basedir}/test"/>
+    <junit printsummary="withOutAndErr"
+      errorproperty="test.failed"
+      failureproperty="test.failed"
+      fork="${junit.fork}">
+      <formatter type="plain"/>
+      <classpath>
+	<pathelement location="${build.home}/gsdl3test.jar"/>
+	<path refid="compile.classpath"/>
+      </classpath>
+      <test name="${testcase}" if="testcase"/>
+      <batchtest todir="${basedir}/test" unless="testcase">
+	<fileset dir="${build.home}"
+	  includes="**/*Test.class"
+	  />
+      </batchtest>
+    </junit>
+    <echo>
+      *********************************************
+       Test output can be found in directory 'test'
+      *********************************************
+    </echo>
+  </target>
+
+</project>
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/dist-resources/convert-build-xml-source.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/dist-resources/convert-build-xml-source.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/dist-resources/convert-build-xml-source.xsl	(revision 13928)
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+ <!-- we basically want to copy everything except for a few targets that no longer apply -->
+  <xsl:output method="xml"/>
+
+  <!-- for some reason, the default copy-of doesn't copy empty attributes, so have this to get the empty arg1 in equals-->
+  <xsl:template match="project|condition|and|isset|equals|not|or">
+    <xsl:copy>
+      <xsl:copy-of select="@*"/>
+      <xsl:apply-templates/>
+    </xsl:copy>
+  </xsl:template>
+      
+  <!-- delete the unnecessary targets -->
+  <xsl:template match="target[starts-with(@name, 'prepare')]"></xsl:template>
+  <xsl:template match="target[starts-with(@name, 'cvsupdate')]"></xsl:template>
+  <xsl:template match="target[starts-with(@name, 'update')]"></xsl:template>
+  <xsl:template match="target[starts-with(@name, 'checkout')]"></xsl:template>
+  <xsl:template match="target[starts-with(@name, 'rename-gs2build')]"></xsl:template>
+  <xsl:template match="target[@name='test']"></xsl:template>
+  <xsl:template match="target[@name='get-macos-extra']"></xsl:template>
+  <xsl:template match="target[@name='get-windows-binaries']"></xsl:template>
+  
+  <xsl:template match="property[@name='install-command']">
+    <property name="install-command" value="ant [options] install"/>
+  </xsl:template>
+
+  <xsl:variable name="install-for-dist" select="document('dist-build.xml')/project/target[@name='install-for-source-dist']"/>
+  
+  <!-- copy in our new install target -->
+  <xsl:template match="target[@name='install']">
+    <target name="install">
+      <xsl:copy-of select="$install-for-dist/@depends|$install-for-dist/@description|$install-for-dist/@if|$install-for-dist/@unless|$install-for-dist/node()"/>
+    </target>
+  </xsl:template>
+
+  <xsl:template match="*">
+    <xsl:copy-of select="."/>
+  </xsl:template>
+
+  <xsl:template match="comment()">
+    <xsl:copy-of select="."/>
+    <xsl:text>
+</xsl:text>
+  </xsl:template>
+    
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gsdl3/dist-resources/convert-build-xml.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/dist-resources/convert-build-xml.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/dist-resources/convert-build-xml.xsl	(revision 13928)
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+ <!-- we basically want to copy everything except for a few targets that no longer apply -->
+  <xsl:output method="xml"/>
+
+  <!-- for some reason, the default copy-of doesn't copy empty attributes, so have this to get the empty arg1 in equals-->
+  <xsl:template match="project|condition|and|isset|equals|not|or">
+    <xsl:copy>
+      <xsl:copy-of select="@*"/>
+      <xsl:apply-templates/>
+    </xsl:copy>
+  </xsl:template>
+  
+  <!-- delete the old install target-->
+  <xsl:template match="target[@name='install']"></xsl:template>
+
+  <!-- delete the unnecessary targets -->
+  <xsl:template match="target[starts-with(@name, 'prepare')]"></xsl:template>
+  <xsl:template match="target[starts-with(@name, 'cvsupdate')]"></xsl:template>
+  <xsl:template match="target[starts-with(@name, 'update')]"></xsl:template>
+  <xsl:template match="target[starts-with(@name, 'checkout')]"></xsl:template>
+  <xsl:template match="target[starts-with(@name, 'rename-gs2build')]"></xsl:template>
+  <xsl:template match="target[@name='test']"></xsl:template>
+  <xsl:template match="target[@name='get-macos-extra']"></xsl:template>
+  <xsl:template match="target[@name='get-windows-binaries']"></xsl:template>
+
+  <xsl:variable name="usage-for-dist" select="document('dist-build.xml')/project/target[@name='usage-for-binary-dist']"/>
+  
+  <!-- copy in our new usage target -->
+  <xsl:template match="target[@name='usage']">
+    <target name="usage">
+      <xsl:copy-of select="$usage-for-dist/@description|$usage-for-dist/node()"/>
+    </target>
+  </xsl:template>
+  
+  <xsl:template match="*">
+    <xsl:copy-of select="."/>
+  </xsl:template>
+
+  <xsl:template match="comment()">
+    <xsl:copy-of select="."/>
+    <xsl:text>
+</xsl:text>
+  </xsl:template>
+    
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gsdl3/dist-resources/dist-build.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/dist-resources/dist-build.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/dist-resources/dist-build.xml	(revision 13928)
@@ -0,0 +1,403 @@
+<?xml version="1.0"?>
+
+<!-- ====================================================================== 
+     March 2005                                                    
+
+     Greenstone3 build and install script
+                   
+     kjdon                                                                
+     ====================================================================== -->
+<project name="greenstone3-distribution" default="usage" basedir="..">
+  
+  <!-- include standard build file -->
+  <import file="../build.xml"/>
+  
+  <property name="documented.collections.home" value="/home/nzdl/for-distributions/collect"/>
+  <property name="greenstone3-change-date" value="2005/11/14 03:13:14"/>
+  <property name="gs2build-change-date" value="Wed Dec 13 10:35:57 NZDT 2006"/>
+
+  <!-- ====================== DISTRIBUTION Targets ========================= -->
+  
+  <!-- these two, do we need tomcat and axis for compilation??-->
+  <!-- Create the binaries for windows distribution -->
+  <target name="prepare-windows" depends="init">
+    <cvs command="checkout -P" package="gs2build" /> 
+    <antcall target="unzip-windows-packages"/>
+    <antcall target="checkout-winbin"/>
+    <antcall target="get-perl-for-windows"/>
+  </target>
+  
+  <target name="build-windows" depends="init">
+    <antcall target="cvsupdate-distribution"/>
+    <cvs command="update -dP" package="winbin" />
+    <antcall target="get-windows-binaries"/>
+    <antcall target="rename-gs2build-files-windows"/>
+    <antcall target="compile-gs2build"/>
+    <antcall target="compile-packages"/>
+   </target>
+  
+  <!-- Create the binaries for Unix/Mac distributions -->
+  <target name="prepare-unix" depends="init">
+    <cvs command="checkout -P" package="gs2build"/>
+    <cvs command="checkout -P" packages="gli"/>
+  </target>
+
+  <target name="update-unix" depends="init">
+    <antcall target="cvsupdate-distribution"/>
+    <antcall target="rename-gs2build-files-unix"/>
+    <antcall target="delete-windows-files"/>
+  </target>
+  
+  <target name="configure-unix" depends="init">
+    <antcall target="configure-c++"/>
+  </target>    
+  <target name="build-unix" depends="init">
+    <antcall target="compile-packages"/>
+    <antcall target="compile-gs2build"/>
+  </target>
+    
+  <!-- creates the base distribution. Needs binaries copied in to it from other
+    greenstones (prepare-os targets) -->
+  <target name="create-distribution-1" depends="init" description="do all the initial downloading and setting up">
+    <cvs command="export -D '1 second ago'" package="gs2build"/>
+    <cvs command="export -D '1 second ago'" package="gli"/>
+    <delete file="${gli.home}/gli.bat"/>
+    <delete file="${gli.home}/gli.sh"/>
+    <delete file="${gli.home}/gems.bat"/>
+    <delete file="${gli.home}/gems.sh"/>
+    <antcall target="rename-gs2build-files-dist"/>    
+    <delete dir="${gs2build-extra.home}"/>
+    
+    <!--<antcall target="unzip-windows-packages"/> do we need this?-->
+    <antcall target="download-tomcat"/>
+    <delete file="${packages.home}/apache-tomcat-5.5.12.zip"/>
+    <delete file="${packages.home}/apache-tomcat-5.5.12-compat.zip"/>
+    <antcall target="prepare-axis"/>
+    <delete file="${packages.home}/axis-bin-1_2_1.zip"/>
+    <!-- delete old axis dir -->
+    <delete dir="${packages.home}/axis"/>
+    <mkdir dir="${web.home}/applet"/>
+    <mkdir dir="${web.home}/logs"/>
+    <antcall target="prepare-ant"/>
+    <delete file="${packages.home}/apache-ant-1.7.0-bin.zip"/>
+    <antcall target="prepare-collections"/>
+
+    <!-- get good XML-Parser - does this work? -->
+    <antcall target="get-xml-parser"/>
+    <!-- documented collections -->
+    <antcall target="get-documented-collections"/>
+
+    <delete file="${basedir}/README-CVS.txt"/>
+    <delete file="${basedir}/TODO.txt"/>
+
+    <!-- make the extra directories needed for a release -->
+    <mkdir dir="${basedir}/Linux/lib/jni"/>
+    <mkdir dir="${basedir}/Darwin/lib/jni"/>
+    <mkdir dir="${basedir}/Windows/lib/jni"/>
+    <mkdir dir="${gs2build.home}/Unix/bin/linux"/>
+    <mkdir dir="${gs2build.home}/Unix/bin/darwin"/>
+    <mkdir dir="${gs2build.home}/Windows/bin/windows"/>
+    <mkdir dir="${gs2build.home}/source/Windows"/>
+    <mkdir dir="${gs2build.home}/source/Unix"/>
+
+  </target>
+
+  <target name="create-distribution-2" description="do all the compilation">
+    <!-- compile the java stuff -->
+    <antcall target="compile-web"/>
+    <antcall target="configure-packages-and-indexers"/>
+    <antcall target="compile-packages-and-indexers-javaonly"/>
+    <antcall target="distclean-packages"/>
+    <antcall target="compile-core"/>
+    <antcall target="compile-gli"/>
+  </target>
+
+  <target name="create-distribution-3" depends="init" description="Do the rearranging of source code etc">
+
+    <!-- move top-level os dependent files -->
+    <copy todir="${basedir}/Linux">
+      <fileset dir="${basedir}">
+	<include name="*.sh"/>
+      </fileset>
+    </copy>
+    <chmod dir="${basedir}/Linux" perm="ugo+rx" 
+      includes="*.sh"/>
+    <move todir="${basedir}/Darwin">
+      <fileset dir="${basedir}">
+	<include name="*.sh"/>
+      </fileset>
+    </move>
+    <chmod dir="${basedir}/Darwin" perm="ugo+rx" 
+      includes="*.sh"/>
+    <move todir="${basedir}/Windows">
+      <fileset dir="${basedir}">
+	<include name="*.bat"/>
+      </fileset>
+    </move>
+
+    <!-- rearrange collection building stuff -->
+    <move file="${gs2build.home}/win32.mak" tofile="${gs2build.home}/source/Windows/win32.mak"/>
+    <move file="${gs2build.home}/setup.bat" tofile="${gs2build.home}/source/Windows/setup.bat"/>
+    <move file="${gs2build.home}/WIN32cfg.h" tofile="${gs2build.home}/source/Windows/WIN32cfg.h"/>
+    <move todir="${gs2build.home}/source/Unix/">
+      <fileset dir="${gs2build.home}">
+	<include name="config*"/>
+	<include name="ac*"/>
+	<include name="install-sh"/>
+	<include name="setup.bash"/>
+	<include name="Makefile.in"/>
+      </fileset>
+    </move>
+    <!-- general source files -->
+    <move todir="${gs2build.home}/source/src" failonerror="false">
+      <fileset dir="${gs2build.home}/src" defaultexcludes="no"/>
+    </move>
+    <move todir="${gs2build.home}/source/lib" failonerror="false">
+      <fileset dir="${gs2build.home}/lib" defaultexcludes="no"/>
+    </move>
+    <move todir="${gs2build.home}/source/packages" failonerror="false">
+      <fileset dir="${gs2build.home}/packages" defaultexcludes="no"/>
+    </move>
+    <move todir="${gs2build.home}/source/indexers" failonerror="false">
+      <fileset dir="${gs2build.home}/indexers" defaultexcludes="no"/>
+    </move>
+
+    <!-- generate modified build.xml file -->
+    <antcall target="run-xslt-binary"/>
+
+    <!-- clean up -->
+    <delete dir="${basedir}/build"/>
+    <delete dir="${basedir}/lib/jni"/>
+  </target>
+  
+
+  <target name="create-source-distribution" depends="init">
+    <cvs command="export -D '1 second ago'" package="gs2build"/>
+    <cvs command="export -D '1 second ago'" package="gli"/>
+    <delete file="${gli.home}/gli.bat"/>
+    <delete file="${gli.home}/gli.sh"/>
+    <antcall target="rename-gs2build-files-dist"/>
+    <delete dir="${gs2build-extra.home}"/>
+    <antcall target="download-tomcat"/>
+    <delete file="${packages.home}/apache-tomcat-5.5.12.zip"/>
+    <delete file="${packages.home}/apache-tomcat-5.5.12-compat.zip"/>
+    <antcall target="prepare-ant"/>
+    <delete file="${packages.home}/apache-ant-1.7.0-bin.zip"/>
+    <antcall target="prepare-collections"/>
+    <antcall target="prepare-axis"/>
+    <delete file="${packages.home}/axis-bin-1_2_1.zip"/>
+    <!-- delete old axis dir -->
+    <delete dir="${packages.home}/axis"/>
+    <mkdir dir="${web.home}/applet"/>
+    <mkdir dir="${web.home}/logs"/>
+
+    <!-- download the mac XML parser just in case: it will only be unpacked if on a mac  -->
+    <get src="http://www.greenstone.org/gs3files/XML-Parser.tar.gz"
+      dest="${gs2build.home}/perllib/cpan/XML-Parser.tar.gz"
+      usetimestamp="true"/>
+
+    <!-- generate modified build.xml file -->
+    <antcall target="run-xslt-source"/>
+    <!--<delete dir="${basedir}/dist-resources"/>-->
+
+  </target>
+
+  <!-- Supplementary targets -->
+
+  <target name="cvsupdate-distribution" depends="init">
+    <antcall target="cvsupdate-packages"/>
+    <antcall target="cvsupdate-core"/>
+    <antcall target="cvsupdate-gs2build"/>
+    <antcall target="cvsupdate-web"/>
+  </target>
+
+  <target name="run-xslt-source" depends="init">
+    <xslt in="${basedir}/build.xml" out="${basedir}/dist-build.xml" style="${basedir}/dist-resources/convert-build-xml-source.xsl"/>
+  </target>
+  
+  <target name="run-xslt-binary" depends="init">
+    <xslt in="${basedir}/build.xml" out="${basedir}/dist-build.xml" style="${basedir}/dist-resources/convert-build-xml.xsl"/>
+  </target>
+  
+  <target name="rename-gs2build-files-dist" depends="init,rename-gs2build-files-unix">
+    <copy file="${gs2build-extra.home}/lib.win32.mak" tofile="${gs2build.home}/lib/win32.mak"/>
+   <copy file="${gs2build-extra.home}/win32.mak" tofile="${gs2build.home}/win32.mak"/>
+   <copy file="${gs2build-extra.home}/setup.bat" tofile="${gs2build.home}/setup.bat"/>
+  </target>   
+
+  <target name="configure-packages-and-indexers" depends="init">
+    <exec executable="${indexers.home}/configure"
+      dir="${indexers.home}">
+      <arg value="--prefix=${basedir}"/>
+      <arg value="--libdir=${lib.jni}"/>
+    </exec>          
+    <exec executable="${javagdbm.home}/configure"
+      dir="${javagdbm.home}">
+      <arg value="--prefix=${basedir}"/>
+      <arg value="--libdir=${lib.jni}"/>
+    </exec>    
+
+  </target>
+  <target name="compile-packages-and-indexers-javaonly" depends="init">
+    <echo>Compiling Indexers</echo>
+    <exec executable="make" os="${os.unix}"
+       dir="${indexers.home}">
+      <arg value="javaonly"/>
+    </exec>
+    <exec executable="make" os="${os.unix}"
+      dir="${indexers.home}">
+      <arg value="install-javaonly"/>
+    </exec>
+    <!-- install the jar files -->
+    <copy file="${mg.home}/mg.jar" todir="${lib.jni}"/>
+    <copy file="${mgpp.home}/mgpp.jar" todir="${lib.jni}"/>
+    <copy file="${lucene.home}/LuceneWrapper.jar" todir="${web.lib}"/>
+    
+    <!-- javagdbm -->
+    <exec executable="make" os="${os.unix}"
+      dir="${javagdbm.home}">
+      <arg value="javaonly"/>
+    </exec>
+    <exec executable="make" os="${os.unix}"
+      dir="${javagdbm.home}">
+      <arg value="installjava"/>
+    </exec>
+    <!-- install the jar file -->
+    <copy file="${javagdbm.home}/javagdbm.jar" todir="${lib.jni}"/>
+
+  </target>
+
+  <target name="delete-windows-files" depends="init" unless="current.os.iswindows">
+    <delete dir="${basedir}/winutil"/>
+    <delete>
+      <fileset dir="${lib.jni}" includes="*.dll"/>
+    </delete>
+  </target>
+
+  <target name="get-perl-for-windows" depends="init" if="current.os.iswindows">
+    <mkdir dir="${gs2build.home}/bin/windows"/>
+    <get src="http://www.greenstone.org/gs3files/perl-for-windows.zip"
+      dest="${gs2build.home}/bin/windows/perl-for-windows.zip"
+      usetimestamp="true"/>
+    <unzip src="${gs2build.home}/bin/windows/perl-for-windows.zip" 
+      dest="${gs2build.home}/bin/windows"/>
+    <delete file="${gs2build.home}/bin/windows/perl-for-windows.zip"/>
+  </target>
+
+  <target name="distclean-packages" depends="init">
+    <!-- indexers : just call the make target -->
+    <exec executable="make" os="${os.unix}"
+      dir="${indexers.home}">
+      <arg value="distclean"/>
+    </exec>
+    <!-- javagdbm -->
+    <exec executable="make" os="${os.unix}"
+      dir="${javagdbm.home}">
+      <arg value="distclean"/>
+    </exec>
+  </target>
+
+  <!-- copy the doc eg colls from /home/nzdl - note we don't include the formatting ones -->
+  <target name="get-documented-collections" depends="init">
+    <property name="collect.home" value="${basedir}/web/sites/localsite/collect"/>
+    <copy todir="${collect.home}/MARC-e">
+      <fileset dir="${documented.collections.home}/MARC-e"/>
+    </copy>
+    <copy todir="${collect.home}/cltbib-e">
+      <fileset dir="${documented.collections.home}/cltbib-e"/>
+    </copy>
+    <copy todir="${collect.home}/dls-e">
+      <fileset dir="${documented.collections.home}/dls-e"/>
+    </copy>
+    <copy todir="${collect.home}/dspace-e">
+      <fileset dir="${documented.collections.home}/dspace-e"/>
+    </copy>
+    <copy todir="${collect.home}/gsarch-e">
+      <fileset dir="${documented.collections.home}/gsarch-e"/>
+    </copy>
+    <copy todir="${collect.home}/isis-e">
+      <fileset dir="${documented.collections.home}/isis-e"/>
+    </copy>
+    <copy todir="${collect.home}/oai-e">
+      <fileset dir="${documented.collections.home}/oai-e"/>
+    </copy>
+    <copy todir="${collect.home}/pagedimg-e">
+      <fileset dir="${documented.collections.home}/pagedimg-e"/>
+    </copy>
+    <copy todir="${collect.home}/wrdpdf-e">
+      <fileset dir="${documented.collections.home}/wrdpdf-e"/>
+    </copy>
+  </target>
+
+  <target name="get-xml-parser" depends="init">
+    <get src="http://www.greenstone.org/gs3files/XML-Parser.tar.gz"
+      dest="${gs2build.home}/perllib/cpan/XML-Parser.tar.gz"
+      usetimestamp="true"/>
+    <untar src="${gs2build.home}/perllib/cpan/XML-Parser.tar.gz"
+      dest="${gs2build.home}/perllib/cpan/"
+      compression="gzip"/>
+    <delete file="${gs2build.home}/perllib/cpan/XML-Parser.tar.gz"/>
+  </target>
+
+  <target name="create-changelog">
+    <!-- generate greenstone 3 changelog -->
+    <exec executable="/home/nzdl/for-distributions/bin/script/cvs2cl.pl"
+      dir="${basedir}">
+      <arg value="-P"/>
+      <arg value="-F"/>
+      <arg value="trunk"/>
+      <arg value="-r"/>
+      <arg value="-S"/>
+      <arg value="-l"/>
+      <arg value="-d'${greenstone3-change-date}&lt;tomorrow'"/>
+      <arg value="-f"/>
+      <arg value="greenstone-${app.version}-ChangeLog.txt"/>
+      <arg value="-I"/>
+      <arg value="gli/.*|gs2build/.*"/>
+    </exec> 
+    <!-- generate coll building change log -->
+    <exec executable="/home/nzdl/for-distributions/bin/script/cvs2cl.pl"
+      dir="${basedir}">
+      <arg value="-P"/>
+      <arg value="-F"/>
+      <arg value="trunk"/>
+      <arg value="-r"/>
+      <arg value="-S"/>
+      <arg value="-l"/>
+      <arg value="-d'${gs2build-change-date}&lt;tomorrow'"/>
+      <arg value="-f"/>
+      <arg value="greenstone-${app.version}-ChangeLog-collbuilding.txt"/>
+      <arg value="gli"/>
+      <arg value="gs2build"/>
+    </exec> 
+  </target>
+  <!-- new targets to go in distribution build.xml files -->
+
+  <!-- new usage target for binary release -->
+  <target name="usage-for-binary-dist" description="Print a help message">
+    <echo message="  Execute 'ant -projecthelp' for a list of targets."/>
+    <echo message="  Execute 'ant -help' for Ant help."/>
+  </target>
+    
+
+  <!-- new install target for source distribution -->
+  <target name="install-for-source-dist" depends="init" description="install the source distribution. Includes configuring and compiling">
+    <antcall target="unzip-windows-packages"/>
+    <!-- do the java version dependent stuff -->
+    <antcall target="configure-java-version"/>
+    <antcall target="install-macos-extra"/>
+    <!-- set gsdlhome in setup.bat -->
+    <antcall target="gs2build-edit-setup-bat"/>
+    <antcall target="install-indexer-files"/>
+    <antcall target="configure"/>
+    <antcall target="configure-c++"/>
+    <antcall target="compile"/>
+    <!-- make sure we have execute permission for the .sh files -->
+    <chmod dir="${basedir}" perm="ugo+rx" 
+      includes="*.sh"/>
+
+  </target>
+
+</project>
+  
+
Index: /tags/greenstone-3_02-distribution/gsdl3/dist-resources/tomcat-server.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/dist-resources/tomcat-server.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/dist-resources/tomcat-server.xsl	(revision 13928)
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+ <!-- we basically want to copy everything, but add in a few bits for gs3 -->
+  <xsl:output method="xml"/>
+  
+  <xsl:template match="Server">
+    <xsl:copy>
+      <xsl:copy-of select="@*"/>
+      <xsl:apply-templates/>
+    </xsl:copy>
+    <xsl:text>
+    </xsl:text>
+  </xsl:template>
+  
+  <xsl:template match="Service | Engine ">
+    <xsl:copy>
+      <xsl:copy-of select="@*"/>
+      <xsl:apply-templates/>
+    </xsl:copy>
+  </xsl:template>
+  
+  <xsl:template match="Connector[@port='8080']">
+    <xsl:copy>
+    <xsl:for-each select="@*">
+      <xsl:choose>
+	<xsl:when test="name()='port'">
+	  <xsl:attribute name="port">@port@</xsl:attribute>
+	</xsl:when>
+	<xsl:otherwise>
+	  <xsl:copy-of select="."/>
+	</xsl:otherwise>
+      </xsl:choose>
+    </xsl:for-each>
+      <xsl:apply-templates/>
+    </xsl:copy>
+  </xsl:template>
+	  
+  <xsl:template match="Host">
+    <xsl:copy>
+      <xsl:copy-of select="@*"/>
+      <xsl:apply-templates/>
+      <Context path="/gsdl3" docBase="@gsdl3home@/web" debug="1" 
+	reloadable="true">
+	<Resources allowLinking='true'/>
+      </Context>
+    </xsl:copy>
+  </xsl:template>
+      
+  <xsl:template match="*">
+    <xsl:copy-of select="."/>
+  </xsl:template>
+
+  <xsl:template match="comment()">
+    <xsl:copy-of select="."/>
+    <xsl:text>
+</xsl:text>
+  </xsl:template>
+    
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gsdl3/docs/Makefile.in
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/docs/Makefile.in	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/docs/Makefile.in	(revision 13928)
@@ -0,0 +1,42 @@
+###########################################################################
+#
+# Makefile -- Makefile for documentation included with Greenstone
+#
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 2000 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+GSDL3HOME=..
+
+JAVADOC=$(JAVA_HOME)/bin/javadoc
+JAVADOCDIR=$(GSDL3HOME)/docs/javadoc
+SRCDIR=$(GSDL3HOME)/src/java
+PACKAGEDIR=$(GSDL3HOME)/packages
+
+docs:
+	$(JAVADOC) -d $(JAVADOCDIR) -private -link http://java.sun.com/j2se/1.4.2/docs/api/ `find $(SRCDIR) -name '*.java'` `find $(PACKAGEDIR) -name '*.java'` > $(JAVADOCDIR)/javadoc_log
+
+# what about the CVS dir??
+clean:
+	rm -rf $(JAVADOCDIR)/*
+
+distclean: clean
+	rm -f Makefile
Index: /tags/greenstone-3_02-distribution/gsdl3/docs/javadoc/.keepme
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/docs/javadoc/.keepme	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/docs/javadoc/.keepme	(revision 13928)
@@ -0,0 +1,1 @@
+a file to ensure cvs keeps the directory
Index: /tags/greenstone-3_02-distribution/gsdl3/docs/manual/hints.tex
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/docs/manual/hints.tex	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/docs/manual/hints.tex	(revision 13928)
@@ -0,0 +1,228 @@
+\documentclass[a4paper,11pt]{article}
+\usepackage{times,epsfig}
+
+\newenvironment{bulletedlist}%
+{\begin{list}{$\bullet$}{\setlength{\itemsep}{0pt}\setlength{\parsep}{0pt}}}%
+{\end{list}}
+
+
+\begin{document}
+
+\title{Some hints for developers}
+
+\maketitle
+
+\section{Java code}
+
+the java code is found in gsdl3/src/java/org/greenstone/gsdl3
+util has various utility classes, service has the services, action has the actions, build has the building code, etc.
+
+\section{Working with XML}
+
+We use the DOM model for handling XML. This involves Documents, Nodes, Elements etc. Node is the basic thing in the tree, all others inherit from this. A Document represents a whole document, and is a kind of container for all the nodes. Elements and Nodes are not supposed to exist outside of the context of a document, so you have to have a document to create them. The document is not the top level node in the tree, to get this, use Document.getDocumentElement(). If you create nodes etc but dont append them to something already in the document tree, they will be separate - but they still know who their owner document is.
+
+There is a utility class called XMLConverter - this creates new Documents, and converts Strings or files to Documents.
+eg:
+XMLConverter converter = new XMLConverter();
+Document doc = converter.newDOM();
+
+File stylesheet = new File(``query.xsl'');
+Document style = converter.getDOM(stylesheet);
+
+String message = ``<message><request type='cgi'/></message>'';
+Document m = converter.getDOM(message);
+
+To output a document as a String, use converter.getString(doc);
+
+
+To add nodes and stuff to an empty document - create them, then append to the tree
+
+Document doc = converter.newDOM();
+Element e = doc.createElement(``message'');
+doc.appendChild(e);
+
+Note, you can only append one node to a document - this will become the toplevel node. After that, you can append nodes to child nodes as you like, but a document is only allowed one top level node.
+
+DOM006 Hierarchy request error: happens if you have more than one root node in your document
+
+\section{Working with XSLT}
+
+* adding html to an xml doc:
+
+eg I have a text node with html inside it inside a resource element
+to add that to a new XML doc, I use
+{\em <xsl:value-of select='resource'>\/}
+
+if the output mode is xml or html, this will escape any special characters
+ie $<$ and $>$ etc
+
+use
+{\em <xsl:value-of disable-output-escaping="yes" select='resource'>\/}
+instead.
+
+* including an xml doc into a stylesheet:
+
+{\em <xsl:variable name='import' select='document(``newdoc.xml'')'/>\/}
+
+then can use the info:
+
+{\em <xsl:value-of select='\$import/element'/>\/}
+
+* selecting an ancestor:
+
+ the ancestor axis contains the parent of the context node, and its
+ parent and so on. to pick one node among these:
+ ancestor::elem-name. I dont know how this works if there are two
+ nodes with the same name in the axis.
+
+* basic XSLT elements
+\begin{quote}\begin{footnotesize}\begin{verbatim}
+<xsl:template match='xxx' name='yyy'/>
+
+<xsl:apply-templates select='xxx'/>
+<xsl:call-templates name='yyy'/>
+
+<xsl:variable name='doc' select='document("layout.xml")'/>
+
+<xsl:value-of select='$doc/chapter1'/> $
+\end{verbatim}\end{footnotesize}\end{quote}
+
+* using namespaces
+If you are using the same namespace in more than one file, eg in the source xml and in the stylesheet, make sure that the URI for the xmlns:xxx thingy is the same in both cases---otherwise the names dont match. This includes http:// on the front.
+
+\subsection{What can I do to speed up XSL transformations?}
+
+This information taken from the Xalan FAQS page.
+
+\begin{bulletedlist}
+
+\item Use a Templates object (with a different Transformers for each
+transformation) to perform multiple transformations with the same set
+of stylesheet instructions (see Multithreading).
+
+\item Set up your stylesheets to function efficiently.
+
+\item Don't use "//" (descendant axes) patterns near the root of a
+large document.
+
+\item Use xsl:key elements and the key() function as an efficient way
+to retrieve node sets.
+
+\item Where possible, use pattern matching rather than xsl:if or
+xsl:when statements.
+
+\item xsl:for-each is fast because it does not require pattern matching.
+
+\item Keep in mind that xsl:sort prevents incremental processing.
+
+\item When you create variables,
+{\em <xsl:variable name="fooElem" select="foo"/>\/} is usually faster
+than \\
+{\em <xsl:variable name="fooElem"><xsl:value-of-select="foo"/></xsl:variable>\/}.
+
+\item Be careful using the last() function.
+
+\item The use of index predicates within match patterns can be expensive.
+
+\item Decoding and encoding is expensive.
+
+\item For the ultimate in server-side scalability, perform transform
+operations on the client. For examples, see appletXMLtoHTML and
+get-todo-list.
+
+\end{bulletedlist}
+
+\section{Java gdbm}
+
+To talk to gdbm, a jni wrapper called java-gdbm is used. It was
+obtained from:\\ {\tt
+http://aurora.rg.iupui.edu/~schadow/dbm-java/pip/gdbm/}
+
+It uses packing objects to convert to and from an array of bytes (in
+gdbm file) from and to java objects. In my GDBMWrapper class I use
+StringPacking - uese UTF-8 encoding. but some stuff came out funny. so
+I had to changes the from\_bytes method in StringPacking.java to use
+new String(raw, "UTF-8") instead of new String(raw). this seems to
+work.
+
+Note---if we use this gdbm stuff to create the file too, may need to
+alter the to-bytes method.
+
+The makefile in j-gdbm is crap---it tries to get stuff from its
+original CVS tree.  I have created a new Makefile---in my-j-gdbm
+directory.  this stuff needs to go into cvs probably.
+
+* I dont think {\em <xsl:with-param name='xxx' select='true'/>\/} is
+the same as {\em <xsl:with-param name='xxx'>true</xsl:with-param>\/}
+use the second one.
+
+
+\section{Resources}
+
+Contents for 'The Java Native Interface Programmer's Guide and
+Specification' on-line\\ {\tt
+http://java.sun.com/docs/books/jni/html/jniTOC.html}
+
+Java Native Interface Specification\\
+{\tt http://java.sun.com/j2se/1.4/docs/guide/jni/spec/jniTOC.doc.html}
+
+JNI Documentation Contents\\
+{\tt http://java.sun.com/j2se/1.4/docs/guide/jni/index.html}
+
+another JNI page\\
+{\tt http://mindprod.com/jni.html}
+
+Java 1.4 api index\\
+{\tt http://java.sun.com/j2se/1.4/docs/api/index.html}
+
+Java tutorial index\\
+{\tt http://java.sun.com/docs/books/tutorial/index.html}
+
+Safari books online - has java, XML, XSLT, etc books\\
+{\tt http://proquest.safaribooksonline.com/mainhom.asp?home}
+
+Java 1.4 i18n FAQ\\
+{\tt http://www.sun.com/developers/gadc/faq/java/java1.4.html}
+
+Java and XSLT page\\
+{\tt http://www.javaolympus.com/java/Java\%20and\%20XSLT.html}
+
+Xalan-Java overview\\
+{\tt http://xml.apache.org/xalan-j/overview.html}
+
+Tomcat documentation index\\
+{\tt http://jakarta.apache.org/tomcat/tomcat-4.0-doc/index.html}
+
+Servlet and JSP tutorial\\
+{\em http://www.apl.jhu.edu/~hall/java/Servlet-Tutorial/\/}
+
+Core Servlets and JavaServer Pages, book by Marty Hall. download the
+pdf from here (try before you buy link)\\ {\tt
+http://www.coreservlets.com/}
+
+J-gdbm page\\
+{\em http://aurora.rg.iupui.edu/~schadow/dbm-java/pip/gdbm/\/}
+
+Stuarts page of links\\
+{\em http://www.cs.waikato.ac.nz/~nzdl/gsdl3/\/}
+
+a good basic xslt tutorial\\
+{\tt http://www.zvon.org/xxl/XSLTutorial/Books/Output/contents.html}
+
+JAXP (java api for xml processing) package overview\\
+{\tt http://java.sun.com/xml/jaxp/dist/1.1/docs/api/overview-summary.html}
+
+DeveloperWorks, xml zone\\
+{\tt http://www-106.ibm.com/developerworks/xml/}
+
+xslt.com\\
+{\tt http://www.xslt.com/}
+
+jeni tennison's xslt pages\\
+{\tt http://www.jenitennison.com/xslt/}
+
+apaches xml tools\\
+{\tt http://xml.apache.org/}
+
+
+\end{document}
Index: /tags/greenstone-3_02-distribution/gsdl3/docs/manual/manual.tex
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/docs/manual/manual.tex	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/docs/manual/manual.tex	(revision 13928)
@@ -0,0 +1,2388 @@
+\documentclass[a4paper,11pt]{article}
+\usepackage{isolatin1,times,epsfig}
+\hyphenation{Message-Router Text-Query}
+
+\newenvironment{gsc}% Greenstone text bits
+{\begin{footnotesize}\begin{tt}}%
+{\end{tt}\end{footnotesize}}
+ 
+\newcommand{\gst}[1]{{\footnotesize \tt #1}}
+
+\newcommand{\gsii}{Greenstone2}
+\newcommand{\gsiii}{Greenstone3}
+\newcommand{\gs}{Greenstone}
+
+\begin{document}
+
+\title{\gsiii\ : A modular digital library.}
+
+% if you work on this manual, add your name here
+\author{Katherine Don \\[1ex]
+        Department of Computer Science \\
+        University of Waikato \\ Hamilton, New Zealand \\ }
+
+\date{}
+
+\maketitle
+
+\newenvironment{bulletedlist}%
+{\begin{list}{$\bullet$}{\setlength{\itemsep}{0pt}\setlength{\parsep}{0pt}}}%
+{\end{list}}
+
+\noindent
+Greenstone Digital Library Version 3 is a complete redesign and
+reimplementation of the \gs\  digital library software.  The current
+version (\gsii) enjoys considerable success and is being widely used.
+\gsiii \  will capitalize on this success, and in addition it will
+\begin{bulletedlist}
+\item improve flexibility, modularity, and extensibility
+\item lower the bar for ``getting into'' the \gs\  code with a view to
+   understanding and extending it
+\item use XML where possible internally to improve the amount of
+   self-documentation
+\item make full use of existing XML-related standards and software
+\item provide improved internationalization, particularly in terms of sort order,
+   information browsing, etc.
+\item include new features that facilitate additional ``content management''
+   operations
+\item operate on a scale ranging from personal desktop to corporate library
+\item easily permit the incorporation of text mining operations
+\item use Java, to encourage multilinguality, X-compatibility, and to permit
+   easier inclusion of existing Java code (such as for text mining).
+\end{bulletedlist}
+Parts of \gs\  will remain in other languages (e.g. MG, MGPP); JNI (Java
+Native Interface) will be used to communicate with these.
+
+A description of the general design and architecture of \gsiii\  is covered by the document {\em The design of Greenstone3: An agent based dynamic digital library} (design-2002.ps, in the docs/manual directory).
+
+This documentation consists of several parts. Section~\ref{sec:install} is for administrators, and covers \gsiii\  installation, how to access the library, and some administration issues. Section~\ref{sec:user} is for users of the software, and looks at using the sample collections, creating new collections, and how to make small customizations to the interface. The remaining sections are aimed towards  the \gs\  developer. Section~\ref{sec:develop-runtime} describes the run-time system, including the structure of the software, and the message format. Section~\ref{sec:new-features} describes how to add new features to \gs, such as how to add new services, new page types, new plugins for different document formats.  Section~\ref{sec:distributed} describes how to make \gs\  run in a distributed fashion, using SOAP as an example communications protocol. Finally, there are several appendices, including how to install \gs\  from CVS, some notes on Tomcat and SOAP, and a comparison of \gsii\  and \gsiii\  format statements.
+\newpage
+\tableofcontents
+\newpage
+\section{\gs\  installation and administration}\label{sec:install}
+
+This section covers where to get \gsiii\  from, how to install it and how to run it. The standard method of running \gsiii\  is as a Java servlet. We provide the Tomcat servlet container to run the servlet. Standard web servers may  be able to be configured to provide servlet support, and thereby remove the need to use Tomcat. Please see your web server documentation for this. This documentation assumes that you are using Tomcat. To access \gsiii, Tomcat must be started up, and then it can be accessed via a web browser. 
+
+Ant (Java's XML based build tool) is used for compilation, installation and running Greenstone. The \gst{build.xml} file is the configuration file for the Greenstone project, and \gst{build.properties} contains parameters that can be altered by the user.
+
+\subsection{Get and install \gs\ }\label{sec:getandinstall}
+
+\gsiii\  is available for download from Sourceforge:\\
+ \gst{https://sourceforge.net/projects/greenstone3}. There are Windows, Linux, and source releases. The binary releases are self-installing executables: download and run the file to install. A series of prompts will guide you through the installation process. The source release is a gzip'd tar file. Unzip and untar this, check build.properties, then run \gst{'ant install'} to configure and compile the code.
+
+The \gsiii\  library can be launched by running the server program. This is accessible from the Start menu on Windows, or by running the \gst{gs3-server.sh/bat} script in the top level \gst{greenstone3} directory. This program will start up the Tomcat web server and launch a browser.
+
+Alternatively, you can start it up using Ant: run \gst{'ant start'}, which starts up Tomcat, then in a browser go to \gst{http://localhost:8080/greenstone3}\\
+(or \gst{http://your-computer-name:your-chosen-port/greenstone3}). \\
+This gets you to a welcome page containing links to four servlets: the \gst{test} servlet (this allows you to check that Tomcat is running properly); the standard \gst{library} servlet which serves \gst{localsite} site with the \gst{default} interface; the \gst{classic} servlet which serves \gst{localsite} using the \gst{classic} or \gsii-style interface; and the \gst{gateway} servlet, which serves \gst{gateway} site with the \gst{default} interface. The \gst{gateway} site uses a SOAP connection to communicate with \gst{localsite}, and demonstrates the library working in a distributed fashion. The SOAP connection is not enabled by default - to enable it, run \gst{'ant deploy-localsite'}.
+
+\gsiii\  is also available through CVS (Concurrent Versioning System). This provides the latest development version, and is not guaranteed to be stable. Appendix~\ref{app:cvs} describes how to download and install \gsiii\  from CVS.
+
+\subsection{How the library works}
+
+The standard library program is a Java servlet. We use the Tomcat servlet container to present the servlets over the web. Tomcat takes CGI-style URLs and passes the arguments to the servlet, which processes these and returns a page of HTML. As far as an end-user is concerned, a servlet is a Java version of a CGI program. The interaction is similar: access is via a web browser, using arguments in a URL.
+
+Other types of interfaces can be used, such as Java GUI programs. See Section~\ref{sec:new-interfaces} for details about how to make these.
+
+\subsubsection{Restarting the library}
+
+You can restart Tomcat by clicking 'Restart Server' on the little server program. You should restart the server any time you make changes in the following for those changes to take effect:\\
+\begin{bulletedlist}
+\begin{gsc}
+\item \$GSDL3HOME/WEB-INF/web.xml
+\item \$GSDL3SRCHOME/packages/tomcat/conf/server.xml
+\end{gsc}
+\item any classes or jar files used by the servlets
+\end{bulletedlist}
+
+
+\subsection{Directory structure}
+
+Table~\ref{tab:dirs} shows the file hierarchy for \gsiii.
+The first part  shows the common stuff which can be shared between
+\gs\  users---the source, libraries etc. The second part shows the file hierarchy for the web directory, which comprises the greenstone3 context for Tomcat, and is accessible via Tomcat. The main directories are for sites and interfaces: there can be several sites and interfaces per installation, and they are described in the following section.
+
+Two environment variables used by \gsiii\ are often mentioned in this manual: \gst{\$GSDL3SRCHOME} and \gst{\$GSDL3HOME}. \gst{\$GSDL3SRCHOME} refers to the top-level \gst{greenstone3} directory, while \gst{\$GSDL3HOME} refers to the \gst{web} directory. The web directory contains everything needed to serve the \gsiii\ library using Tomcat, and doesn't necessarily need to live with the rest of the \gsiii\ source.
+
+\begin{table}
+\caption{The \gs\  directory structure}
+\label{tab:dirs}
+{\footnotesize
+\begin{tabular}{l p{8cm}}
+\hline
+\bf directory & \bf description \\
+\hline
+greenstone3 
+  & The main installation directory---\$GSDL3SRCHOME is set to this directory \\
+greenstone3/src 
+  & Source code lives here \\
+greenstone3/src/java/
+  & main \gsiii\  java source code \\
+greenstone3/src/packages 
+  & Imported source packages from other systems e.g. indexing packages may go here \\
+greenstone3/lib
+  & Shared library files\\
+greenstone3/lib/java
+  & Java jar files not needed in the \gsiii\  runtime\\
+greenstone3/lib/jni
+  & Jar files and shared library files (.so, .jnilib, .dll) needed for JNI components \\
+greenstone3/resources 
+ & any resources that may be needed\\
+greenstone3/resources/soap
+ & soap service description files \\
+greenstone3/bin
+  & executable stuff lives here\\
+greenstone3/bin/script
+  & some Perl and/or shell scripts\\
+greenstone3/packages
+  & External packages that may be installed as part of greenstone, e.g. Tomcat \\
+greenstone3/docs
+  & Documentation\\
+greenstone3/gli
+  & \gs\ Librarian Interface code \\
+greenstone3/gs2build
+  & collection building code\\
+\hline
+greenstone3/web
+  & This is where the web site is defined. Any static HTML files can go here. This directory is the root directory used by Tomcat when serving \gsiii. \$GSDL3HOME is set to this directory. \\
+greenstone3/web/WEB-INF
+  & The web.xml file lives here (servlet configuration information for Tomcat)\\
+greenstone3/web/WEB-INF/classes
+  & Individual class files needed by the servlet go in here, also properties files for java resource bundles - used to handle all the language specific text. This directory is on the servlet classpath\\
+greenstone3/web/WEB-INF/lib
+  & jar files needed by the servlets go here \\
+greenstone3/web/sites
+  & Contains directories for different sites---a site is a set of collections and services served by a single MessageRouter (MR). The MR may have connections (e.g. soap) to other sites\\
+greenstone3/web/sites/localsite 
+  & An example site - the site configuration file lives here\\
+greenstone3/web/sites/localsite/collect 
+  & The collections directory \\
+greenstone3/web/sites/localsite/images 
+  & Site specific images \\
+greenstone3/web/sites/localsite/transforms 
+  & Site specific transforms \\
+greenstone3/web/interfaces
+  & Contains directories for different interfaces - an interface is defined by its images and XSLT files \\
+greenstone3/web/interfaces/default
+  & The default interface\\
+greenstone3/web/interfaces/default/images
+  & The images for the default interface\\
+greenstone3/web/interfaces/default/js
+  & The javascript libraries for the default interface\\
+greenstone3/web/interfaces/default/style
+  & The CSS stylesheets for the default interface\\
+greenstone3/web/interfaces/default/transforms
+  & The XSLT files for the default interface\\
+greenstone3/web/applet 
+  & jar files needed by applets can go here \\
+\hline
+\end{tabular}}
+\end{table}
+
+
+\subsection{Sites and interfaces}\label{sec:sites-and-ints}
+
+Sites and interfaces contain the content and presentation information, respectively, for the digital library.
+A site is comprised of a set of collections and possibly some site-wide services. An interface (in this web-based servlet context) is a set of images along with a set of XSLT files used for translating xml output from the library into an appropriate form---HTML in general.
+
+One \gsiii\  installation can have many sites and interfaces, and these can be paired in different combinations.  One instantiation of a servlet uses one site and one interface, so every specified pairing results in a new servlet instance.  For example, a single site might be served with two different interfaces. This provides different modes of access to the same content. e.g. HTML vs WML, or perhaps providing a completely different look and feel for different audiences. Alternatively, a standard interface may be used with many different sites---providing a consistent mode of access to a lot of different content.
+
+Collections live in the \gst{collect} directory of a site. Any collections that are found in this directory when the servlet is initialized will be loaded up. Public collections will appear on the library home page, while private collections will be hidden. These can still be accessed by typing in cgi arguments. Collections require valid configuration files, but apart from this, nothing needs to be done to the site to use new collections. Collections added while Tomcat is running will not be noticed automatically. Either the server needs to be restarted, or a configuration request may be sent to the library, triggering a (re)load of the collection (this is described in Section~\ref{sec:runtime-config}).
+
+There are two  sites that come with the distribution: \gst{localsite}, and \gst{gateway}. \gst{localsite} has several demo  collections, while \gst{gateway} has none. \gst{gateway} specifies that a SOAP connection should be made to \gst{localsite}. Getting this to work involves setting up a soap server for localsite: see Section~\ref{sec:distributed} for details. 
+There are also two interfaces provided in the distribution: \gst{default} and \gst{classic}. The default interface is a generic \gsiii\ interface, while the \gst{classic} interface aims to look like the old \gsii\ interface.
+
+Each site and interface has a configuration file which specifies parameters for the site or interface---these are described in Section~\ref{sec:config}.
+
+\subsection{Configuring Tomcat}\label{sec:tomcat-config}
+
+The file \gst{\$GSDL3HOME/WEB-INF/web.xml} contains the configuration information for Tomcat. It tells Tomcat what servlets to load, what initial parameters to pass them, and what web names map to the servlets.
+There are four servlets specified in web.xml (these correspond to the four servlet links in the welcome page for \gsiii): one is a test servlet that just prints ``hello greenstone'' to a web page. This is useful if you are having trouble getting Tomcat set up. The other three are the \gs\  library servlets described in Section~\ref{sec:getandinstall}, \gst{library}, \gst{classic} and \gst{gateway}. Each servlet must specify which site and which interface to use. Having multiple servlets provides a way of serving different sites, or the same site with a different style of presentation. \gst{site\_name} and \gst{interface\_name} are just two examples of initialization parameters used by the library servlets. The full list is shown in Table~\ref{tab:serv-init}. 
+
+For more details about Tomcat see Appendix~\ref{app:tomcat}.
+
+\begin{table}
+\caption{\gs\  servlet initialization parameters}
+\label{tab:serv-init}
+{\footnotesize
+\begin{tabular}{lp{3.5cm}p{6cm}}
+\hline
+\bf name & \bf sample value & \bf description \\
+\hline
+library\_name & library & the web name of the servlet \\
+interface\_name & default & the name of the interface to use\\
+site\_name & localsite & the name of the local site to use (use either site\_name or the three remote\_site parameters)\\
+remote\_site\_name & org.greenstone.site1 & the name of a remote site (can be anything??) \\
+remote\_site\_type & soap & the type of server running on the site \\
+remote\_site\_address & http://www.greenstone.org/ greenstone3/services/ localsite & The address of the server \\
+default\_lang & en & the default language for the interface\\
+receptionist\_class & NZDLReceptionist & (optional) specifies an alternative Receptionist to use\\
+messagerouter\_class & NewMessageRouter & (optional) specifies an alternative MessageRouter to use\\
+params\_class & NZDLParams & (optional) specifies an alternative GSParams class to use \\
+\hline
+\end{tabular}}
+\end{table}
+
+\subsection{Configuring a \gs\ library}\label{sec:config}
+
+Initial \gsiii\  system configuration is determined by a set of XML configuration files. Each site has a configuration file that binds parameters for the site, \gst{siteConfig.xml}. Each interface has a configuration file, \gst{interfaceConfig.xml}, that specifies parameters for the interface. Collections also have several configuration files; these are discussed in Section~\ref{sec:collconfig}. 
+The configuration files are read in when the system is initialized, and their contents are cached in memory. This means that changes made to these files once the system is running will not take immediate effect. Tomcat needs to be restarted for changes to the interface configuration file to take effect. However, changes to the site configuration file can be incorporated sending a system command to the library.  There are a series of system commands that can be sent to the library to induce reconfiguration of different modules, including reloading the whole site. This removes the need to restart the system to reflect these changes. These commands are described in Section~\ref{sec:runtime-config}.
+
+\subsubsection{Site configuration file}\label{sec:siteconfig}
+
+The file \gst{siteConfig.xml} specifies the URI for the site (\gst{localSiteName}), the HTTP address for site resources (\gst{httpAddress}), any \gst{ServiceClusters} that the site provides (for example, collection building), any \gst{ServiceRacks} that do not belong to a cluster or collection, and a list of
+known external sites to connect to.  Collections are not specified in the site
+configuration file, but are determined by the contents of the site's
+collect directory.
+
+The HTTP address is used for retrieving resources from a site outside the XML protocol. Because a site is HTTP accessible through Tomcat, any files (e.g. images) belonging to that site or to its collections can be specified in the HTML of a page by a URL. This avoids having to retrieve these files from a remote site via the XML protocol\footnote{Currently, sites live inside the Tomcat greenstone3 root context, and therefore all their content is accessible over HTTP via the Tomcat address. We need to see if parts can be restricted. Also, if we use a different protocol, then resources from remote sites may need to come through the XML. Also, if we are running locally without using Tomcat, we may want to get them via file:// rather than http://.}.
+ 
+Figure~\ref{fig:siteconfig} shows two example site configuration files. The first example is for a rudimentary site with no site-wide services,
+which does not connect to any external sites. The second example is for a site with one site-wide service cluster - a collection building cluster.  It also connects to the first site using SOAP.
+These two sites happen to be running on the same machine, which is why they can use \gst{localhost} in the address. For site \gst{gsdl1} to talk to site \gst{localsite}, a SOAP server must be run for \gst{localsite}. The address of the SOAP server, in this case, is \gst{http://localhost:8080/greenstone3/services/localsite}.
+
+
+\begin{figure}
+\begin{gsc}\begin{verbatim}
+<siteConfig>
+  <localSiteName value="org.greenstone.localsite"/>
+  <httpAddress value="http://localhost:8080/greenstone3/sites/localsite"/>
+  <serviceClusterList/>
+  <serviceRackList/>
+  <siteList/>
+</siteConfig>
+\end{verbatim}\end{gsc}
+
+\begin{gsc}\begin{verbatim}
+<siteConfig>
+  <localSiteName value="org.greenstone.gsdl1"/>
+  <httpAddress value="http://localhost:8080/greenstone3/sites/gsdl1"/>
+  <serviceClusterList>	
+    <serviceCluster name="build">
+      <metadataList>
+        <metadata name="Title">Collection builder</metadata>
+        <metadata name="Description">Builds collections in a 
+           gsdl2-style manner</metadata>
+      </metadataList>
+      <serviceRackList>
+        <serviceRack name="GS2Construct"/>
+      </serviceRackList>
+    </serviceCluster>
+  </serviceClusterList>
+  <siteList>
+    <site name="org.greenstone.localsite"
+      address="http://localhost:8080/greenstone3/services/localsite"
+      type="soap"/>
+  </siteList>
+</siteConfig>
+\end{verbatim}\end{gsc}
+\caption{Two sample site configuration files}
+\label{fig:siteconfig}
+\end{figure}
+
+Another element that can appear in a site configuration file is \gst{replaceList}. This must have an \gst{id} attribute, and may contain one or more \gst{replace} elements. Replace elements are discussed in Section \ref{sec:collconfig}. The list found in a \gst{siteConfig.xml} file can be applied to any collection by adding a \gst{replaceListRef} element (with the appropriate \gst{id} attribute) to its \gst{collectionConfig.xml} file.
+
+\subsubsection{Interface configuration file}\label{sec:interfaceconfig}
+
+The interface configuration file \gst{interfaceConfig.xml} lists all the actions that the interface knows about at the start (other ones can be loaded dynamically). Actions create the web pages for the library: there is generally one Action per type of page. For example, a query action produces the pages for searching, while a document action displays the documents. The configuration file specifies what short name each action maps to (this is used in library URLs for the a (action) parameter) e.g. QueryAction should use \gst{a=q}. If the interface uses XSLT, it specifies what XSLT file should be used for each action and possibly each subaction. This makes it easy for developers to implement and use different actions and/or XSLT files without recompilation. The server must be restarted, however.
+
+It also lists all the languages that the interface text files have been translated into. These have a \gst{name} attribute, which is the ISO code for the language, and a \gst{displayElement} which gives the language name in that language (note that this file should be encoded in UTF-8). This language list is used on the Preferences page to allow the user to change the interface language. Details on how to add a new language to a \gsiii\  library are shown in Section~\ref{sec:interface-language}.
+
+An \gst{optionList} element can be used to disable or enable some optional functionality for the interface. Currently there are three options that can be enabled:
+
+\begin{tabular}{lp{7cm}}
+highlightQueryTerms & Whether search term highlighting is available or not\\
+berryBaskets & Whether berry basket functionality is available or not\\
+displayAnnotationService & Whether any annotation services (specified in the site config file) should be displayed with a document or not. \\
+\end{tabular}
+
+An interface may be based on an existing one, for example, the classic interface is based on the default interface. This means that it will use any images or templates from the base one unless overridden in the current one. The \gst{baseInterface} attribute of the \gst{<interfaceConfig>} element is used to specify the base interface.
+ 
+\begin{figure}
+\begin{gsc}\begin{verbatim}
+<interfaceConfig>
+  <actionList>
+    <action name='p' class='PageAction'>
+      <subaction name='home' xslt='home.xsl'/>
+      <subaction name='about' xslt='about.xsl'/>
+      <subaction name='help' xslt='help.xsl'/>
+      <subaction name='pref' xslt='pref.xsl'/>
+      <subaction name='nav' xslt='nav.xsl'/><!-- used for the 
+            collection header frame -->
+      <subaction name="html" xslt="html.xsl"/> <!-- used to put an 
+            external page into a frame with a collection header-->
+    </action>
+    <action name='q' class='QueryAction' xslt='basicquery.xsl'/>
+    <action name='b' class='GS2BrowseAction' xslt='classifier.xsl'/>
+    <action name='a' class='AppletAction' xslt='applet.xsl'/>
+    <action name='d' class='DocumentAction' xslt='document.xsl'/>
+    <action name='xd' class='XMLDocumentAction'>
+      <subaction name='toc' xslt='document-toc.xsl'/>
+      <subaction name='text' xslt='document-content.xsl'/>
+    </action>
+    <action name='pr' class='ProcessAction' xslt='process.xsl'/>
+    <action name='s' class='SystemAction' xslt='system.xsl'/>
+    <action name='g' class='GeneralAction'>
+      <subaction name="berry" xslt='berry.xsl'/>
+    </action>
+  </actionList>
+  <languageList>
+    <language name="en">
+      <displayItem name='name'>English</displayItem>
+    </language>
+    <language name="fr">
+      <displayItem name='name'>Français</displayItem>
+    </language>
+    <language name='es'>
+      <displayItem name='name'>Español</displayItem>
+    </language>
+  </languageList>
+  <optionList>
+    <option name="highlightQueryTerms" value="true"/>
+    <option name="berryBaskets" value="true"/>
+  </optionList>
+</interfaceConfig>
+\end{verbatim}\end{gsc}
+\caption{Default interface configuration file}
+\label{fig:ifaceconfig}
+\end{figure}
+
+
+\subsection{Run-time re-initialization}\label{sec:runtime-config}
+
+When Tomcat is started up, the site and interface configuration files are read in, and actions/services/collections loaded as necessary. The configuration is then static unless Tomcat is restarted, or re-configuration commands issued. 
+
+There are several commands that can be issued to Tomcat to avoid having to restart the server. These can reload the entire site, or just individual collections. Unfortunately at present there are no commands to reconfigure the interface, so if the interface configuration file has changed, Tomcat must be restarted for those changes to take effect. Similarly, if the Java classes are modified, Tomcat must be restarted then too.
+
+Currently, the runtime configuration commands can only be accessed by typing arguments into the URL; there is no nice web form yet to do this. 
+
+The arguments are entered after the \gst{library?} part of the URL. There are three types of commands: configure, activate, deactivate. These are specified by \gst{a=s\&sa=c}, \gst{a=s\&sa=a}, and \gst{a=s\&sa=d}, respectively (\gst{a} is action, \gst{sa} is subaction). By default, the requests are sent to the MessageRouter, but they can be sent to a collection/cluster by the addition of \gst{sc=xxx}, where \gst{xxx} is the name of the collection or cluster. Table~\ref{tab:run-time config} describes the commands and arguments in a bit more detail.
+
+\begin{table}
+\caption{Example run-time configuration arguments.}
+\label{tab:run-time config}
+{\footnotesize
+\begin{tabular}{lp{9cm}}
+\hline
+\gst{a=s\&sa=c} & reconfigures the whole site. Reads in siteConfig.xml, reloads all the collections. Just part of this can be specified with another argument \gst{ss} (system subset). The valid values are \gst{collectionList}, \gst{siteList}, \gst{serviceList}, \gst{clusterList}. \\
+\gst{a=s\&sa=c\&sc=XXX} & reconfigures the XXX collection or cluster. \gst{ss} can also be used here, valid values are \gst{metadataList} and \gst{serviceList}. \\
+\gst{a=s\&sa=a} & (re)activate a specific module. Modules are specified using two arguments, \gst{st} (system module type) and \gst{sn} (system module name). Valid types are \gst{collection}, \gst{cluster} \gst{site}.\\
+\gst{a=s\&sa=d} & deactivate a module. \gst{st} and \gst{sn} can be used here too. Valid types are \gst{collection}, \gst{cluster}, \gst{site}, \gst{service}. Modules are removed from the current configuration, but will reappear if Tomcat is restarted.\\
+\gst{a=s\&sa=d\&sc=XXX} & deactivate a module belonging to the XXX collection or cluster. \gst{st} and \gst{sn} can be used here too. Valid types are \gst{service}. \\
+\hline
+\end{tabular}}
+\end{table}
+\newpage
+\section{Using \gsiii\ }\label{sec:user}
+
+Once \gsiii\ is installed, the sample collections can be accessed. The installation comes with several example collections, and Section~\ref{sec:usecolls} describes these collections and how to use them. Section~\ref{sec:buildcol} describes how to build new collections.
+
+\subsection{Using a collection}\label{sec:usecolls} 
+
+A collection typically consists of a set of documents, which could be text, HTML, word, PDF, images, bibliographic records etc, along with some access methods, or ``services''. Typical access methods include searching or browsing for document identifiers, and retrieval of content or metadata for those identifiers.
+Searching involves entering words or phrases and getting back lists of documents that contain those words. The search terms may be restricted to particular fields of the document. 
+
+Browsing involves navigating pre-defined hierarchies of documents, following links of interest to find documents. The hierarchies may be constructed on different metadata fields, for example, alphabetical lists of Titles, or a hierarchy of Subject classifications. Clicking on a bookshelf icon takes you to a lower level in the hierarchy, while clicking on a book or page icon takes you to a document.
+
+In the standard interface that comes with \gsiii\ \footnote{of course, this is all customizable}, collections in a digital library are presented in the following manner. The 'home' page of the library shows a list of all the public collections in that library. Clicking on a collection link takes you to the home page for the collection, which we call the collection's 'about' page. The standard page banner for a collection looks something like that shown in Figure~\ref{fig:page-banner}.
+
+\begin{figure}[h]
+  \centering
+  \includegraphics[width=4in]{pagebanner.ps} %5.8
+  \caption{A sample collection page banner}
+  \label{fig:page-banner}
+\end{figure}
+
+The image at the top left is a link to the collection's home page. The top right has buttons to link to the library home page, help and preferences pages. All the available services are arrayed along a navigation bar, along the bottom of the banner. Clicking on a name accesses that service. 
+
+Search type services generally provide a form to fill in, with parameters including what field or granularity to search, and the query itself. Clicking the search button carries out the search, and a list of matching documents will be displayed. Clicking on the icons in the result list takes you to the document itself. 
+
+Once you are looking at a document, clicking the open book icon at the top of the document, underneath the navigation bar, will take you back to the service page that you accessed the document from.
+
+\subsection{Building a collection}\label{sec:buildcol}
+
+There are three ways to get a new collection into \gsiii. The most common way is to use the Greenstone Librarian Interface to create a collection. If you have existing collections in a \gsii\ installation, these can be imported into \gsiii. Thirdly, you can use the Perl command line building scripts directly.
+
+Collections live in the \gst{collect} directory of a site. As described in Section~\ref{sec:sites-and-ints}, there can be several sites per \gsiii\  installation. The collect directory is at \gst{\$GSDL3HOME/sites/site-name/collect}, where site-name is the name of the site you want your new collection to belong to.
+
+The following three sections briefly  describe how to create a collection using GLI, how to import a collection from \gsii, and how to use command line building.  Once a collection has been built (and is located in the collect directory), the library server needs to be notified that there is a new collection. This can be accomplished in two ways\footnote{and eventually there will also probably be automatic polling for new collections}. If you are the library administrator, you can restart Tomcat. The library servlet will then be created afresh, and will discover the new collection when it scans the collect directory for the collection list. Alternatively, an activate collection command can be issued to the servlet, using the arguments \gst{a=s\&sa=a\&st=collection\&sn=collname}, where \gst{collname} should be replaced with the collection name---this tells the library program to (re)load the \gst{collname} collection.
+
+\subsubsection{Using the Librarian Interface}
+
+The Greenstone Librarian Interface (GLI) can be used to create collections. The procedure is the same as for \gsii, but it works in a \gsiii\  context. It can be started under Windows by selecting Greenstone Librarian Interface from the Greenstone 3 Digital Library menu in the Program Files section of the Start menu. On Linux, run \gst{ant gli} from the \gst{greenstone3} directory, or run \gst{./gli4gs3.sh} from the \gst{\$GSDL3SRCHOME/gli} directory.
+
+Currently, the GLI works almost exactly the same as for \gsii\footnote{Eventually the GLI will be modified to use \gsiii\ XML  configuration files.}. Collection configuration is done in a \gsii\ manner. The main difference is that \gsiii\ has different sites and interfaces and servlets, whereas \gsii\ has a single collect directory, and a single runtime cgi program.
+
+The GLI for \gsiii\ has a couple of new configuration parameters: site and servlet. It operates within a single site---you can edit, delete, and create new collections within this site. A servlet is also specified for that site---this is used when previewing a collection. While you are working in one site, you cannot edit collections from another site. However, you can base a collection on one from another site. To change the working site and/or servlet, go to Preferences-$>$Connection in the File menu. By default, the GLI will use site \gst{localsite}, and servlet \gst{library}.
+
+Collection building using the GLI will use the \gsii\ Perl scripts and plugins. At the conclusion of the \gsii\ build process, a conversion script will be run to create the \gsiii\  configuration files. This means that format statements are no longer 'live'---changing these will require changes to the \gsiii\ configuration files. Clicking the Preview Collection button will re-run the configuration file conversion script. If you change anything on the Format panel, you will need to click Preview Collection. Just reloading the collection via a browser will not be enough. 
+ 
+Detailed instructions about using the GLI can be found in Sections 3.1 and 3.2 of the \gsii\  User's Guide (\gst{GS2-User-en.pdf}). This can be found in  your \gsii\ installation, or in the \gst{\$GSDL3SRCHOME/docs/manual} directory if you have installed \gsiii\ from a distribution.
+
+
+\subsubsection{Importing from \gsii}
+
+Pre-built \gsii\ collections can also be used in \gsiii. The collection folder should be copied to the collect directory of the site it is to appear in (or a symbolic link may be used if possible).
+The \gsiii\  run time system requires different configuration files for a collection, so you need to run a conversion script. All this does is create the new \gst{collectionConfig.xml} and \gst{buildConfig.xml} from the old \gst{collect.cfg} and \gst{build.cfg} files. It does not change the collection in any way, so it can still be used by \gsii\  software.
+
+The conversion script is \gst{convert\_coll\_from\_gs2.pl}. To run it, make sure you have run \gst{source setup.bash} (or \gst{setup} in Windows) in the \gst{\$GSDL3SRCHOME/gs2build} directory (as well as running the standard \gst{gs3-setup} command). Then you need to specify the path to the collect directory and the collection name as parameters to the conversion script. For example, 
+
+\begin{gsc}
+\begin{verbatim}
+convert_coll_from_gs2.pl -collectdir 
+   $GSDL3HOME/sites/localsite/collect gs2mgdemo
+\end{verbatim}
+\end{gsc}
+%$
+The script attempts to create \gsiii\  format statements from the old \gsii\  ones. The conversion may not always work properly, so if the collection looks a bit strange under \gsiii, you should check the format statements. Format statements are described in Section~\ref{sec:formatstmt}.
+
+Once again, to have the collection recognized by the library servlet, you can either restart Tomcat, or load it dynamically.
+
+\subsubsection{Using command line building}
+
+This is the same procedure as for \gsii\ command line building, with the addition of a final step to create the \gsiii\ configuration files. The basic steps are (for a new collection called testcol):
+
+Linux:
+
+\begin{gsc}
+\begin{verbatim}
+cd greenstone3
+source gs3-setup.sh
+cd gs2build
+source setup.bash
+cd ../
+mkcol.pl -collectdir $GSDL3HOME/sites/localsite/collect testcol
+put source documents and metadata into 
+            $GSDL3HOME/sites/localsite/collect/testcol/import
+edit $GSDL3HOME/sites/localsite/collect/testcol/etc/collect.cfg as 
+            appropriate
+import.pl -collectdir $GSDL3HOME/sites/localsite/collect testcol
+buildcol.pl -collectdir $GSDL3HOME/sites/localsite/collect testcol
+rename the $GSDL3HOME/sites/localsite/collect/testcol/building 
+            directory to index
+convert_coll_from_gs2.pl -collectdir $GSDL3HOME/sites/localsite/collect 
+            testcol
+%$
+\end{verbatim}
+\end{gsc}
+
+Windows:
+\begin{gsc}
+\begin{verbatim}
+cd greenstone3
+gs3-setup
+cd gs2build
+setup
+cd ..
+perl -S mkcol.pl -collectdir %GSDL3HOME%\sites\localsite\collect testcol
+put source documents and metadata into 
+            %GSDL3HOME%\sites\localsite\collect\testcol\import
+edit %GSDL3HOME%\sites\localsite\collect\testcol\etc\collect.cfg as 
+            appropriate
+perl -S import.pl -collectdir %GSDL3HOME%\sites\localsite\collect testcol
+perl -S buildcol.pl -collectdir %GSDL3HOME%\sites\localsite\collect testcol
+rename the %GSDL3HOME%\sites\localsite\collect\testcol\building directory 
+            to index
+perl -S convert_coll_from_gs2.pl -collectdir 
+            %GSDL3HOME%\sites\localsite\collect testcol
+\end{verbatim}
+\end{gsc}
+
+Once the build process is complete, Tomcat should be prompted to reload the collection---either by restarting the server, or by sending an activate collection command to the library servlet.
+
+Metadata for documents can be added using \gst{metadata.xml} files.  A \gst{metadata.xml} file has a root element of \gst{<DirectoryMetadata>}.  This encloses a series of \gst{<FileSet>} items.  Neither of these tags has any attributes.  Each \gst{<FileSet>} item includes two parts: firstly, one or more \gst{<FileName>} tags, each of which encloses a regular expression to identify the files which are to be assigned the metadata.  Only files in the same directory as the \gst{metadata.xml} file, or in one of its child directories, will be selected.  The filename tag encloses the regular expression as text, e.g.:
+
+\begin{gsc}\begin{verbatim}
+<FileName>example</FileName>
+\end{verbatim}\end{gsc}
+
+This would match any file containing the text 'example' in its name.  The second part of the \gst{<FileSet>} item is a \gst{<Description>} item.  The \gst{<Description>} tag has no attributes, but encloses one or more \gst{<Metadata>} tags.  Each \gst{<Metadata>} tag contains one metadata item, i.e. a label to describe the metadata and a corresponding value.  The \gst{<Metadata>} tag has one compulsory attribute: \gst{'name'}.  This attribute gives the metadata label to add to the document.  Each \gst{<Metadata>} tag also has an optional attribute: \gst{'mode'}.  If this attribute is set to \gst{'accumulate'} then the value is added to the document, and any existing values for that metadata item are retained.  If the attribute is set to \gst{'set'} or is omitted, then any existing value of the metadata item will be deleted.
+
+\begin{figure}
+\begin{gsc}\begin{verbatim}
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE DirectoryMetadata SYSTEM "http://greenstone.org/dtd/DirectoryMetadata
+         /1.0/DirectoryMetadata.dtd">
+<DirectoryMetadata>
+  <FileSet>
+    <FileName>ec160e</FileName>
+    <Description>
+      <Metadata name="Title">The Courier - No.160 - Nov - Dec 1996 - 
+         Dossier Habitat - Country reports: Fiji , Tonga (ec160e)</Metadata>
+      <Metadata mode="accumulate" name="Language">English</Metadata>
+      <Metadata mode="accumulate" name="Subject">Settlements and housing: 
+        general works incl. low- cost housing, planning techniques, surveying, 
+        etc.</Metadata>
+      <Metadata mode="accumulate" name="Subject">The Courier ACP 1990 - 1996 
+        Africa-Caribbean-Pacific - European Union</Metadata>
+      <Metadata mode="accumulate" name="Organization">EC Courier</Metadata>
+      <Metadata mode="accumulate" name="AZList">T.1</Metadata>
+    </Description>
+  </FileSet>
+  <FileSet>
+    <FileName>b22bue</FileName>
+    <Description>
+      <Metadata name="Title">Butterfly Farming in Papua New Guinea 
+        (b22bue)</Metadata>
+      <Metadata mode="accumulate" name="Language">English</Metadata>
+      <Metadata mode="accumulate" name="Subject">Other animals (micro-
+        livestock, little known animals, silkworms, reptiles, frogs, 
+        snails, game, etc.)</Metadata>
+      <Metadata mode="accumulate" name="Organization">BOSTID</Metadata>
+      <Metadata mode="accumulate" name="AZList">T.1</Metadata>
+      <Metadata mode="accumulate" name="Keyword">start a butterfly farm
+        </Metadata>
+    </Description>
+  </FileSet>
+</DirectoryMetadata>
+\end{verbatim}\end{gsc}
+\caption{Sample metadata.xml file}
+\label{fig:metadatafile}
+\end{figure}
+
+Figure~\ref{fig:metadatafile} shows an example metadata.xml file.
+Here, only one file pattern is found in each file set.  However, the \gst{Description} tag contains a number of separate metadata items.  Note that the \gst{Title} metadata does not have the \gst{mode=accumulate} attribute.  This means that when this title is assigned to a document, any existing \gst{Title} information will be lost.
+
+
+\subsection{Collection configuration files}\label{sec:collconfig}
+
+Each collection has two, or possibly three, \gsiii\ configuration files, \\
+\gst{collectionConfig.xml}, \gst{buildConfig.xml}, and optionally \gst{collectionInit.xml}, that give metadata, display and other information for the
+collection. Currently, \gst{collectionConfig.xml} and \gst{buildConfig.xml} are generated from \gst{collect.cfg} and \gst{build.cfg}. At some stage, the collection building process and the Librarian Interface will be modified to use these files directly. 
+\gst{collect.cfg} and/or \gst{collectionConfig.xml} includes user-defined presentation metadata for the collection, such as its name and the {\em About this collection} text; gives formatting information for the collection display; and also gives instructions on how the collection is to be built. \gst{build.cfg} and/or \gst{buildConfig.xml} are produced by the build-time process and include any metadata that can be determined automatically. It also includes configuration information for any ServiceRacks needed by the collection.
+
+All the configuration files should be encoded using UTF-8.
+
+The format of \gst{collect.cfg} and \gst{build.cfg} are not discussed here. Please see the \gsii\ manuals for more information regarding these files.
+
+\subsubsection{collectionInit.xml}
+
+This optional file is only used for non-standard, customized collections. It specifies the class name of the non-standard collection class.  The only syntax so far is the class name:
+
+\begin{gsc}\begin{verbatim}
+<collectionInit class="XMLCollection"/>
+\end{verbatim}\end{gsc}
+
+Section~\ref{sec:new-coll-types} describes an example collection where this file is used. Depending on the type of collection that this is used for, one or both of the other configuration files may not be needed.
+
+\subsubsection{collectionConfig.xml}
+
+The collection configuration file is where the collection designer (e.g. a librarian) decides what form the collection should take. So far this file only includes the presentation aspects needed by the run-time system. Instructions for collection building have yet to be defined. Presentation aspects include collection metadata such as title and description, display text for indexes, and format statements for search results, classifiers etc. The format of \gst{collectionConfig.xml} is still under consideration. However, Figure~\ref{fig:collconfig} shows the parts of it that have been defined so far. 
+
+Display elements for a collection can be entered in any language---use \gst{lang='en'} attributes to specify which language they are in.
+
+\begin{figure}
+\begin{gsc}\begin{verbatim}
+<collectionConfig xmlns:gsf="http://www.greenstone.org/greenstone3/
+  schema/ConfigFormat" xmlns:xslt="http://www.w3.org/1999/XSL/Transform">
+  <metadataList>
+    <metadata name="creator">greenstone@cs.waikato.ac.nz</metadata>
+    <metadata name="public">true</metadata>
+  </metadataList>
+  <displayItemList>
+    <displayItem name='name' lang='en'>Greenstone3 MG demo collection</displayItem>
+    <displayItem name='description' lang='en'>This is a demonstration 
+      collection for the Greenstone3 digital library software.</displayItem>
+    <displayItem name='icon' lang='en'>gs3mgdemo.gif</displayItem>
+    <displayItem name='smallicon' lang='en'>gs3mgdemo_sm.gif</displayItem>
+  </displayItemList>
+  <search>
+    <index name="ste">
+      <displayItem name='name' lang="en">chapters</displayItem>
+      <displayItem name='name' lang="fr">chapitres</displayItem>
+      <displayItem name='name' lang="es">capÃ­tulos</displayItem>
+    </index>
+    [ ... more indexes ...]
+    <format>
+      <gsf:template match="documentNode"><td valign='top'>
+       <gsf:link><gsf:icon/></gsf:link></td><td><gsf:metadata name='Title'/>
+      </td></gsf:template>
+    </format>
+  </search>
+  <browse>
+    <classifier name="CL1" horizontalAtTop='true'>
+      <displayItem name='name' lang='en'>Titles</displayItem>
+    </classifier>
+    [... more classifiers ...]
+    <classifier name="CL4">
+      <displayItem name='name' lang='en'>HowTo</displayItem>
+      <format>
+        <gsf:template match="documentNode">
+          <br /><gsf:link><gsf:metadata name='Keyword' />
+            </gsf:link></gsf:template>
+      </format>
+    </classifier>
+  </browse>
+  <display>
+    <format>
+      <gsf:option name="coverImages" value="false"/>
+      <gsf:option name="documentTOC" value="false"/>
+    </format>
+  </display>
+</collectionConfig>
+\end{verbatim}\end{gsc}
+\caption{Sample collectionConfig.xml file}
+\label{fig:collconfig}
+\end{figure}
+
+The \gst{<metadataList>} element specifies some collection metadata, such as creator. The \gst{<displayItemList>} specifies some language dependent information that is used for collection display, such as collection name and short description. These \gst{displayItem} elements can be specified in different languages. 
+ 
+The \gst{<search>} element provides some display and formatting information for the search indexes, while the \gst{<browse>} element concerns classifiers, and   the \gst{<display>} element looks at document display. 
+
+Inside the \gst{<search>} and \gst{<browse>} elements, \gst{<displayItem>} elements are used to provide titles for the indexes or classifiers, while \gst{<format>} elements provide formatting instructions, typically for a document or classifier node in a list of results. Placing the \gst{<format>} instructions at the top level in the \gst{search} or \gst{browse} element will apply the format to all the indexes or classifiers, while placing it inside an individual \gst{index} or \gst{classifier} element will restrict that formatting instruction to that item.
+
+The \gst{<display>} element contains optional formatting information for the display of documents. Templates that can be specified here include \gst{documentHeading} and \gst{DocumentContent}. Other formatting options may also be specified here, such as whether to display a table of contents and/or cover image for the documents.
+
+Format elements are described in Section~\ref{sec:formatstmt}.
+
+An optional \gst{<replaceList>} element can be included at the top level. This contains a list of strings and their replacements. This is particularly useful for \gsii\  collections that use macros. 
+
+The format is like the following:
+\begin{gsc}\begin{verbatim}
+<replaceList>
+<replace scope='text' macro="xxx" text="yyy"/>
+<replace scope='metadata' macro="xxx" bundle="yyy" key="zzz"/>
+<replace scope='all' macro='xxx' metadata='yyy'/>
+</replaceList>
+\end{verbatim}\end{gsc}
+
+Scope determines on what text the replacements are carried out: \gst{text}, \gst{metadata}, and \gst{all} (both text and metadata). An empty scope attribute is equivalent to scope=all. Each replace type can be used with all scope values. Replacing uses Java's 'String.replaceAll' functionality, so macro and replacement text are actually regular expressions. The first example is a straight textual replacement. The second example uses dictionary lookups. xxx will be replaced with the (language-dependent) value for key zzz in resource bundle yyy. The third example uses metadata: xxx will be replaced by the value of the yyy metadata for that document.
+
+Appendix~\ref{app:gs2replace} gives some examples that have been used for \gsii\  collections.
+
+\subsubsection{buildConfig.xml}\label{sec:buildconfig}
+
+The file \gst{buildConfig.xml} is produced by the collection building process. Generally it is not necessary to look at this file, but it can be useful in determining what went wrong if the collection doesn't appear quite the way it was planned.
+
+It contains metadata and other information about the collection that can
+be determined automatically, such as the number of
+documents in the collection.  It also includes a list of \gst{ServiceRack} classes that are
+required to provide the services that have been built into the
+collection.  The serviceRack names are Java classes that are loaded
+dynamically at runtime. Any information inside the serviceRack element is
+specific to that service---there is no set format. Figure~\ref{fig:buildconfig} shows an example. This configuration file specifies that the collection should load up 3 ServiceRacks: \gst{GS2Browse}, \gst{GS2MGPPRetrieve} and \gst{GS2MGPPSearch}. The contents of each \gst{<serviceRack>} element are passed to the appropriate ServiceRack objects for configuration. The \gst{collectionConfig.xml} file content is also passed to the ServiceRack objects at configure time---the \gst{format} and \gst{displayItem} information is used directly from the \gst{collectionConfig.xml} file rather than added into \gst{buildConfig.xml} during building. This enables formatting and metadata changes in \gst{collectionConfig.xml} to take effect in the collection without rebuilding being necessary. However, as these files are cached, the collection needs to be reloaded for the changes to appear in the library.
+
+
+\begin{figure}
+\begin{gsc}\begin{verbatim}
+<buildConfig>
+  <metadataList>
+    <metadata name="numDocs">11</metadata>
+    <metadata name="buildType">mgpp</metadata>
+  </metadataList>
+  <serviceRackList>
+    <serviceRack name="GS2Browse">
+      <indexStem name="gs2mgppdemo"/>
+      <classifierList>
+        <classifier name="CL1" content="Title"/>
+        <classifier name="CL2" content="Subject" />
+        <classifier name="CL3" content="Organization" />
+        <classifier name="CL4" content="Howto" />
+      </classifierList>
+    </serviceRack>
+    <serviceRack name="GS2MGPPRetrieve">
+      <indexStem name="gs2mgppdemo"/>
+      <defaultLevel name="Sec" />
+    </serviceRack>
+    <serviceRack name="GS2MGPPSearch">
+      <indexStem name="gs2mgppdemo"/>
+      <defaultLevel name="Sec" />
+      <levelList>
+        <level name="Sec" />
+        <level name="Doc" />
+      </levelList>
+      <fieldList>
+        <field shortname="ZZ" name="allfields" />
+        <field shortname="TX" name="text" />
+        <field shortname="DL" name="dls.Title" />
+        <field shortname="DS" name="dls.Subject" />
+        <field shortname="DO" name="dls.Organization" />
+      </fieldList>
+      <searchTypeList>
+        <searchType name="form" />
+        <searchType name="plain" />
+      </searchTypeList>
+      <indexOptionList>
+        <indexOption name="stemIndexes" value="3"/>
+	<indexOption name="maxnumeric" value="4"/>
+      </indexOptionList>
+      <defaultIndex name="idx" />
+      <indexList>
+        <index name="idx" />
+      </indexList>
+    </serviceRack>
+  </serviceRackList>
+</buildConfig>
+\end{verbatim}\end{gsc}
+\caption{Sample buildConfig.xml file (gs2mgppdemo collection)}
+\label{fig:buildconfig}
+\end{figure}
+
+\subsection{Formatting the collection}\label{sec:formatstmt}
+
+Part of collection design involves deciding how the collection should look. \gsiii\  has a default 'look' for a collection, so this is optional. However, the default may not suit the purposes of some collections, so many parts to the look of a collection can be determined by the collection designer.
+
+In standard \gsiii, the library is served to a web browser by a servlet, and the HTML is generated using XSLT. XSLT templates are used to format all the parts of the pages. These templates can be overridden by including them in the \gst{collectionConfig.xml} file. Some commonly overridden templates are those for formatting lists: search results list, classifier browsing hierarchies, and for parts of the document display. 
+
+Real XSLT templates for formatting search results or classifier lists are quite complicated, and not at all easy for a new user to write. For example, the following is a sample template for formatting a classifier list, to show Keyword metadata as a link to the document.
+ 
+\begin{gsc}\begin{verbatim}
+<xsl:template match="documentNode" priority="2"
+     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+  <xsl:param name="collName"/>
+    <td><a href="{$library_name}?a=d&amp;c={$collName}&amp;
+           d={@nodeID}&amp;dt={@docType}"><xsl:value-of 
+           select="metadataList/metadata[@name='Keyword']"/></a>
+    </td>
+</xsl:template>
+ \end{verbatim}\end{gsc}
+ 
+To write this, the user would need to know that:
+\begin{bulletedlist}
+\item the variable \gst{\$library\_name} exists,
+\item the collection name is passed in as a parameter called \gst{collName}
+\item metadata for a document is found in a \gst{<metadataList>} and that its form is \gst{<metadata name="Keyword">the value</metadata>}
+\item the arguments needed for the link to the document are \gst{a, sa, c, d, a, dt}.
+\end{bulletedlist}
+ 
+We can use XSLT to transform XML into XSLT. \gsiii\  provides a simplified set of formatting commands, written in XML, which will be transformed into proper XSLT. The user specifies a \gst{<gsf:template>} for what they want to format---these typically match \gst{documentNode} or \gst{classifierNode} (for a node in a classification hierarchy).
+ 
+The template above can be represented as:
+ 
+\begin{gsc}\begin{verbatim}
+<gsf:template match='documentNode'>
+  <td><gsf:link><gsf:metadata name='Keyword'/></gsf:link></td>
+</gsf:template>
+\end{verbatim}\end{gsc}
+
+Table~\ref{tab:gsf-format} shows the set of \gst{'gsf'} (Greenstone Format) elements. If you have come from a \gsii\  background, Appendix~\ref{app:gs2format} shows \gsii\  format elements and their equivalents in \gsiii\ .
+ 
+\begin{table}
+\caption{Format elements for GSF format language}
+\label{tab:gsf-format}
+{\footnotesize
+\begin{tabular}{p{6.5cm}p{6.5cm}}
+\hline
+\bf Element       & \bf Description \\
+\hline
+\gst{<gsf:text/>} & The document's text\\
+\hline
+\gst{<gsf:link>...</gsf:link>} & The HTML link to the document itself \\
+\gst{<gsf:link type='document'>...
+</gsf:link>} & Same as above\\
+\gst{<gsf:link type='classifier'>...
+</gsf:link>} & A link to a classification node (use in classifierNode templates)\\
+\gst{<gsf:link type='source'>...
+</gsf:link>} & The HTML link to the original file---set for documents that have been converted from e.g. Word, PDF, PS \\
+\hline
+\gst{<gsf:icon/>}  & An appropriate icon\\
+\gst{<gsf:icon type='document'/>} & same as above\\
+\gst{<gsf:icon type='classifier'/>} & bookshelf icon for classification nodes\\
+\gst{<gsf:icon type='source'/>} & An appropriate icon for the original file e.g. Word, PDF icon\\
+\hline
+\gst{<gsf:metadata name='Title'/>} & The value of a metadata element for the current document or section, in this case, Title\\
+\gst{<gsf:metadata name='Title' select='select-type' [separator='y' multiple='true']/>} & A more extended selection of metadata values. The select field can be one of those shown in Table~\ref{tab:gsf-select-types}. There are two optional attributes: separator gives a String that will be used to separate the fields, default is ``, ``, and if multiple is set to true, looks for multiple values at each section.\\
+\gst{<gsf:metadata name='Date' format='formatDate'/>} & The value of a metadata element for the current document, formatted in some way. Current formatting options available are formatDate: turns '20040201' into '01 February 2004', and formatLanguage: turns 'en' into 'English', both in a language dependent manner. \\
+\hline
+\gst{<gsf:choose-metadata>
+  <gsf:metadata name='metaA'/>
+  <gsf:metadata name='metaB'/>
+  <gsf:metadata name='metaC'/>
+</gsf:choose-metadata>}
+ & A choice of metadata. Will select the first existing one. the metadata elements can have the select, separator and multiple attributes like normal.\\
+\hline
+\gst{<gsf:switch preprocess=
+'preprocess-type'>
+<gsf:metadata name='Title'/> 
+<gsf:when test='test-type'
+test-value='xxx'>...</gsf:when>
+<gsf:when test='test-type' 
+test-value='yyy'>...</gsf:when>
+<gsf:otherwise>...</gsf:otherwise>
+</gsf:switch>} & switch on the value of a particular metadata - the metadata is specified in gsf:metadata, has the same attributes as normal.\\
+\hline
+\end{tabular}}
+\end{table}
+
+The \gst{<gsf:metadata>} elements are used to output metadata values. The simplest case is \gst{<gsf:metadata name='Title'/>}---this outputs the Title metadata for the current document or section. Namespaces are important here: if the Title metadata is in the Dublin Core (dc) namespace, then the element should look like \gst{<gsf:metadata name='dc.Title'/>}. There are three other attributes for this element. The attribute \gst{multiple} is used when there may be more than one value for the selected metadata. 
+For instance, one document may fall into several classification categories, and therefore may have multiple Subject metadata values. Adding \gst{multiple='true'} to the \gst{<gsf:metadata>} element will retrieve all values, not just the first one. Multiple values are separated by commas by default. The \gst{separator} attribute is used to change the separating string. For example, adding \gst{separator=':~'} to the element will separate all values by a colon and a space.
+
+Sometimes you may want to display metadata values for sections other than the current one. For example, in the mgppdemo collection, in a search list we display the Titles of all the enclosing sections, followed by the Title of the current section, all separated by semi-colons. The display ends up looking something like:
+\emph{Farming snails 2; Starting out; Selecting your snails}
+where \emph{Selecting your snails} is the Title of the section in the results list, and \emph{Farming snails 2} and \emph{Starting out} are the Titles of the enclosing sections. The \gst{select} attribute is used to display metadata for sections other than the current one. Table~\ref{tab:gsf-select-types} shows the options available for this attribute. The \gst{separator} attribute is used here also, to specify the separating text.
+
+To get the previous metadata, the format statement would have the following in it:
+
+\begin{gsc}
+\begin{verbatim}
+<gsf:metadata name='Title' select='ancestors' separator='; '/>; 
+    <gsf:metadata name='Title'/>
+\end{verbatim}
+\end{gsc}
+
+\begin{table}
+\caption{Select types for metadata format elements}
+\label{tab:gsf-select-types}
+{\footnotesize
+\begin{tabular}{ll}
+\hline
+\bf Select Type & \bf Description\\
+\hline
+current & The current section \\
+parent & The immediate parent section\\
+ancestors & All the parents back to the root (topmost) section\\
+root & The root or topmost section \\
+siblings & All the sibling sections\\
+children & The immediate child sections of the current section\\
+descendents & All the descendent sections\\
+\hline
+\end{tabular}}
+\end{table}
+
+The \gst{<gsf:choose-metadata>} element selects the first available metadata value from the list of options. 
+\begin{gsc}
+\begin{verbatim}
+<gsf:choose-metadata>
+  <gsf:metadata name='dc.Title'/>
+  <gsf:metadata name='dls.Title'/>
+  <gsf:metadata name='Title'/>
+</gsf:choose-metadata>
+\end{verbatim}
+\end{gsc}
+
+This will display dls.Title if available, otherwise it will use dc.Title if available, otherwise it will use the Title metadata. If there are no values for any of these metadata elements, then nothing will be displayed.
+
+The \gst{<gsf:switch>} element allows different formatting depending on the value of a specified metadata element. For example, the following switch statement could be used to display a different icon for each document in a list depending on which organization it came from. 
+
+\begin{gsc}
+\begin{verbatim}
+<gsf:switch  preprocess='toLower;stripSpace'>
+  <gsf:metadata name='Organization'/>
+  <gsf:when test='equals' test-value='bostid'>
+     <!-- output BOSTID image --></gsf:when>
+  <gsf:when test='equals' test-value='worldbank'>
+     <!-- output world bank image --></gsf:when>
+  <gsf:otherwise><!-- output default image--></gsf:otherwise>
+</gsf:switch>
+\end{verbatim}
+\end{gsc}
+
+Preprocessing of the metadata value is optional. The preprocess types are \gst{toLower} (make the value lowercase), \gst{toUpper} (make the value uppercase), \gst{stripSpace} (removes any whitespace from the value). These operations are carried out on the value of the selected metadata before the test is carried out. Multiple processing types can be specified, separated by ; and they will be applied in the order specified (from left to right).
+
+Each option specifies a test and a test value. Test values are just text. Tests include \gst{startsWith}, \gst{contains}, \gst{exists}, \gst{equals}, \gst{endsWith}. Exists doesn't need a test value. Having an otherwise option ensures that something will be displayed even when none of the tests match.
+
+If none of the gsf elements meets your needs for formatting, XSLT can be entered directly into the format element, giving the collection designer full flexibility over how the collection appears. 
+
+The collection specific templates are added into the configuration file \gst{collectionConfig.xml}. Any templates found in the XSLT files can be overridden.
+The important part to adding templates into the configuration file is determining where to put them. Formatting templates cannot go just anywhere---there are standard places for them. Figure~\ref{fig:format-places} shows the positions that templates can occur.
+
+\begin{figure}
+\begin{gsc}\begin{verbatim}
+<collectionConfig>
+  <metadataList/>
+  <displayItemList/>
+  <search>
+    <format> <!--Put here templates related to searching and 
+        the query page. The common one is the documentNode 
+        template -->
+      <gsf:template match='documentNode'>...</gsf:template>
+    </format>
+  </search>
+  <browse>
+    <classifier name='xx'>
+      <format><!-- put here templates related to formating a 
+        particular classifier page. Common ones are documentNode 
+        and classifierNode templates-->
+        <gsf:template match='documentNode'>...</gsf:template>
+        <gsf:template match='classifierNode'>...</gsf:template>
+        <gsf:template match='classifierNode' mode='horizontal'>...
+          </gsf:template>
+      </format>
+    </classifier>
+    <classifier>...</classifier>
+    <format><!-- formatting for all the classifiers. these will
+      be overridden by any classifier specific formatting 
+      instructions --></format>
+  </browse>
+  <display>
+    <format><!-- here goes any formatting relating to the display 
+        of the documents. These are generally named templates, 
+        and format options -->
+      <gsf:template name='documentContent'>...</gsf:template>
+      <gsf:option name='TOC' value='true'/>
+    </format>
+  </display>
+</collectionConfig>
+\end{verbatim}\end{gsc}
+\caption{Places for format statements}
+\label{fig:format-places}
+\end{figure} 
+
+ 
+There are also formatting instructions that are not templates but are options. 
+These are described in Table~\ref{tab:format_options}. They are entered into the configuration file like \gst{<gsf:option name='coverImages' value='false'/>}
+
+\begin{table}
+\caption{Formatting options}
+\label{tab:format_options}
+{\footnotesize
+\begin{tabular}{llp{5cm}}
+\hline
+\bf option name & \bf values & \bf description \\
+\hline
+coverImages & true, false & whether or not to display cover images for documents \\
+documentTOC & true, false & whether or not to display the table of contents for the document\\
+\hline
+\end{tabular}}
+\end{table}
+
+Note, format templates are added into the XSLT files before transforming, while the options are added into the page source, and used in tests in the XSLT.
+
+\subsubsection{Changing the service text strings}
+
+Each collection has a set of services which are the access points for the information in the collection. Each service has a set of text strings which are used to display it. These include name, description, the text on the submit button, and names and descriptions of all the parameters to the service.
+
+These text strings are found in \gst{.properties} files, in \gst{\$GSDL3HOME/WEB-INF/classes}. The names of the files are based on class names. Subclasses can define their own properties, or can use their parent class ones. For example, \gst{AbstractSearch} defines strings for the \gst{TextQuery} service, in \gst{AbstractSearch.properties}. \gst{GS2MGSearch} just uses these default ones, so doesn't need its own properties file.
+
+A particular collection can override the properties for any service. For example, if a collection uses the \gst{GS2MGSearch} service rack (look in the \gst{buildConfig.xml} file for a list of service racks used), and the collection builder wants to change the text associated with this service, they can put a \gst{GS2MGSearch.properties} file in the resources directory of the collection. After a reconfigure of the collection, this will be used in preference to the one in the default resources directory.
+
+\subsection{Customizing the interface}\label{sec:interface-customise}
+
+Format statements in the collection configuration files provide a way to change small parts of the collection display. For large scale customizations to a collection, or ones that apply to a site as a whole, a second mechanism is available. The interface is defined by a set of XSLT files that transform the page data into HTML. Any of these files can be overridden to provide specialized display, on a site or collection basis. 
+
+The first section looks at customizing the existing interface, while the second section looks at defining a whole new interface. The last section describes how to add a new language translation of an interface.
+
+\subsubsection{Modifying an existing interface}
+
+Most of an interface is defined by XSLT files, which are stored in \gst{\$GSDL3HOME/\-interfaces/\-interface-name/\-transform}. These can be changed and the changes will take effect straight away. If changes only apply to certain collections or sites, not everything that uses the interface, you can override some of the files by putting new ones in a different place. XSLT files are looked for in the following  order: collection, site, interface, default interface. (This currently only apples to sites, and therefore collections, that reside in the same \gs\  installation as the interface.) 
+
+Sites and collections can have a transform directory, which is where customized XSLT files should go. Any XSLT files in here will be used in preference to the interface files when using this collection. For example, if you want to have a completely different layout for the about page of a collection, you can put a new \gst{about.xsl} file into the collection's \gst{transform} directory, and this will be used instead. This is what we do for the Gutenberg sample collection.
+
+This also applies to files that are included from other XSLT files. For example the \gst{query.xsl} for the query pages includes a file called \gst{querytools.xsl}. To have a particular site show a different query interface either of these files may need to be modified. Creating a new version of either of these and putting it in the site \gst{transform} directory will work. Either the new \gst{query.xsl} will include the default \gst{querytools.xsl}, or the default \gst{query.xsl} will include the new \gst{querytools.xsl}. The \gst{xsl:include} directives are preprocessed by the Java code and full paths added based on availability of the files, so that the correct one is used.
+
+Note that you cannot include a file with the same name as the including file. For example \gst{query.xsl} cannot include \gst{query.xsl} (it is tempting to want to do this if you just want to change one template for a particular file, and then include the default. but you cant).
+
+You can add the argument \gst{o=xml} to any URL and you wil be returned the XML before transformation by a stylesheet. This shows you the XML page source. It can be useful when you are trying to write some new XSLT statements.
+
+\subsubsection{Defining a new interface}
+
+A new interface may be needed if different instantiations of the library require different interfaces, or different developers want their own look and feel. Creating a new interface will allow modifications to be made while leaving the original one intact. 
+
+A new interface needs a directory in \gst{\$GSDL3HOME/interfaces}, the name of this directory becomes the interface name. Inside, it needs \gst{images} and \gst{transform} directories,  and an \gst{interfaceConfig.xml} file. The \gst{interfaceConfig.xml} file may specify a base interface, in which case the new interface only needs to define XSLT for the parts that are different. Otherwise, it will need a full set of XSLT files. 
+
+To use a new interface, the \gst{\$GSDL3HOME/WEB-INF/web.xml} file must be edited: either change the interface that a current servlet instance is using, or add another servlet instantiation to the file (see Section~\ref{sec:sites-and-ints} or Appendix~\ref{app:tomcat}). The Tomcat server must be restarted for this to take effect.
+
+\subsubsection{Changing the interface language}\label{sec:interface-language}
+
+The interface language can be changed by going to the preferences page, and choosing a language from the list, which includes all languages into which the interface has been translated.
+
+It is easy to add a new interface language to \gs\ .  Language specific text strings are separated out from the rest of the system to allow for easy incorporation of new languages. These text strings are contained in Java resource bundle properties files. These are plain text files consisting of key-value pairs, located in \gst{\$GSDL3HOME/WEB-INF/classes}. Each interface has one named \gst{interface\_name.properties} (where \gst{'name'} is the interface name, for example, \gst{interface\_default.properties}, or \gst{interface\_classic.properties}). Each service class has one with the same name as the class (e.g. \gst{GS2Search.properties}). To add another language all of the base \gst{.properties}  files must be translated. The translated files keep the same names, but with a language extension added. For example, a French version of \gst{interface\_default.properties} would be named \gst{interface\_default\_fr.properties}.
+
+Keys will be looked up in the properties file closest to the specified language. For example, if language \gst{fr\_CA} was specified (French language, country Canada), and the default locale was \gst{en\_GB},  Java would look at properties files in the following order, until it found the key: \gst{XXX\_fr\_CA.properties}, \gst{XXX\_fr.properties},  \gst{XXX\_en\_GB.properties}, then \gst{XXX\_en.properties}, and finally the default \gst{XXX.properties}.
+
+These new files are available straight away---to use the new language, add e.g. \gst{l=fr} to the arguments in the URL. To get \gs\ to add it in to the list of languages on the preferences page, an entry needs to be added into the languages list in the \gst{interfaceConfig.xml} file (see Section~\ref{sec:interfaceconfig}). Modification of this file requires a restart of the Tomcat server for the changes to be recognized.
+
+\newpage 
+\section{Developing \gsiii : Run-time system}\label{sec:develop-runtime}
+
+[TODO: rewrite this section\\
+runtime object structure diagram. describe the modules.\\ 
+class hierarchy,\\
+directory structure and where everything lives\\
+message format.\\
+overall description of message passing sequence.\\
+configuration process - start up and runtime\\
+\\
+page generation\\
+]
+\subsection{Overview of modules??}
+
+A \gsiii\  'library' system consists of many components: MessageRouter, Receptionist, Actions, Collections, ServiceRacks etc.  Figure~\ref{fig:local} shows how they fit together in a stand-alone system. The top left part is concerned with displaying the data, while the bottom right part is the collection data serving part. The two sides communicate through the MessageRouter. There is a one-to-one correspondence between modules and Java classes, with the exception of services: for coding and/or run-time efficiency reasons, several Service modules may be grouped together into one ServiceRack class.
+
+\begin{figure}[t]
+  \centering
+  \includegraphics[width=4in]{local} %5.8
+  \caption{A simple stand-alone site.}
+  \label{fig:local}
+\end{figure}
+
+
+{\em MessageRouter}: this is the central module for a site. It controls the site, loading up all the collections, clusters, communicators needed. All messages pass through the MessageRouter. Communication between remote sites is always done between MessageRouters, one for each site.
+
+{\em Collection and ServiceCluster}: these are very similar, and group a set of services into a conceptual group.. They both provide some metadata about the collection/cluster, and a list of services. The services are provided by ServiceRack objects that the collection/cluster loads up. A Collection is a specific type of ServiceCluster. A ServiceCluster groups services that are related conceptually, e.g. all the building services may be part of a cluster. What is part of a cluster is specified by the site configuration file. A Collection's services are grouped by the fact that they all operate on some common data---the documents in the collection.
+Functionally Collection and ServiceCluster are very similar, but conceptually, and to the user, they are quite different.
+
+{\em Service}: these provide the core functionality of the system e.g. searching, retrieving documents, building collections etc. One or more may be grouped into a single Java class (ServiceRack) for code reuse, or to avoid instantiating the same objects several times. For example, MGPP searching services all need to have the index loaded into memory. 
+
+{\em Communicator/Server}: these facilitate communication between remote modules. For example, if you want MR1 to talk to MR2, you need a Communicator-Server pair. The Server sits on top of MR2, and MR1 talks to the Communicator. Each communication type needs a new pair. So far we have only been using SOAP, so we have a SOAPCommunicator and a SOAPServer.
+
+{\em Receptionist}: this is the point of contact for the 'front end'. Its core functionality involves routing requests to the Actions, but it may do more than that. For example, a Receptionist may: modify the request in some way before sending it to the appropriate Action; add some data to the page responses that is common to all pages; transform the response into another form using XSLT. There is a hierarchy of different Receptionist types, which is described in Section~\ref{sec:recepts}.
+
+{\em Actions}: these do the job of creating the 'pages'. There is a different action for each type of page, for example PageAction handles semi-static pages, QueryAction handles queries, DocumentAction displays documents. They know a little bit about specific service types. Based on the 'CGI' arguments passed in to them, they construct requests for the system, and put together the responses into data for the page. This data is returned to the Receptionist, which may transform it to HTML. The various actions are described in  more detail in Section~\ref{sec:pagegen}.
+
+
+\subsection{Start up configuration}\label{sec:startup-config}
+
+We use the Tomcat web server, which operates either stand-alone in a test mode
+or in conjunction with the Apache web server.  The \gs\  LibraryServlet
+class is loaded by Tomcat  and the servlet's \gst{init()} method is called.  Each time a
+\gst{get/put/post} (etc.) is used, a new thread is started and
+\gst{doGet()/doPut()/doPost()} (etc.) is called.
+
+The \gst{init()} method creates a new Receptionist and a new 
+MessageRouter. Default classes (DefaultReceptionist, MessageRouter) are used unless subclasses have been specified  in the servlet initiation parameters (see Section~\ref{sec:sites-and-ints}). The appropriate system variables are set for each object (interface
+name, site name, etc.) and then \gst{configure()} is called on both. The MessageRouter handle 
+is passed to the Receptionist. The servlet then communicates only with
+the Receptionist, not with the MessageRouter.
+
+The Receptionist reads in the \gst{interfaceConfig.xml} file (see Section~\ref{sec:interfaceconfig}), and loads up all the different Action classes. Other Actions may be loaded on the fly as needed. Actions are added to a map, with shortnames for keys. Eg the QueryAction is added with key 'q'. The Actions are passed the MessageRouter reference too.
+If the Receptionist is a TransformingReceptionist, a mapping between shortnames  and XSLT file names is also created. 
+
+The MessageRouter reads in its site configuration file \gst{siteConfig.xml} (see Section~\ref{sec:siteconfig}). It creates a module map that maps names to objects. This is used for routing the messages. It also keeps small chunks of XML---serviceList, collectionList, clusterList and siteList. These are part of what get returned in response to a describe request (see Section~\ref{sec:describe}.).
+
+Each ServiceRack specified in the configuration file is created, then queried for its list of services. Each service name is added to the map, pointing to the ServiceRack object. Each service is also added to the serviceList. After this stage, ServiceRacks are transparent to the system, and each service is treated as a separate module.
+
+ServiceClusters are created and passed the \gst{<serviceCluster>} element for configuration. They are added to the map as is, with the cluster name as a key. A serviceCluster is also added to the serviceClusterList.
+
+For each site specified, the MessageRouter creates an appropriate type of Communicator object. Then it tries to get the site description. If the server for the remote site is up and running, this should  be successful. The site will be added to the mapping with its site name as a key. The site's collections, services and clusters will also be added into the static xml lists. If the server for the remote site is not running, the site will not be included in the siteList or module map. To try again to access the site, either Tomcat must be restarted, or a run-time reconfigure-site command must be sent (see Section~\ref{sec:runtime-config}).
+
+The MessageRouter also looks inside the site's \gst{collect} directory, and  loads up a Collection object for each valid collection found. If a \gst{collectionInit.xml} file is present, a subclass of Collection may be used.
+The Collection object reads its \gst{buildConfig.xml} and \gst{collectionConfig.xml}
+files, determines the metadata, and loads ServiceRack classes based on the 
+names specified in \gst{buildConfig.xml\/}. The \gst{<serviceRack>} XML element is passed to the object to be used in configuration. The \gst{collectionConfig.xml} contents are also passed in to the ServiceRacks. Any format or display information that the services need must be extracted from the collection configuration file.
+Collection objects are added to the module map with their name as a key, and also a collection element is added into the collectionList XML.
+
+\subsection{Message passing}
+
+There are two types of messages used by the system: external and internal messages. All messages have an enclosing \gst{<message>} element, which contains either one or more requests, or one or more responses. In the following descriptions, the message element is not shown, but is assumed to be present.  
+Action in \gsiii\  is originated by a request coming in from the outside. In the standard web-based \gs, this comes from a servlet and is passed into the Receptionist. This ``external'' type request is a request for a page of data, and contains a representation of the CGI style arguments. A page of XML is returned, which can be in HTML format or other depending on the output parameter of the request. 
+
+Messages inside the system (``internal'' messages) all follow the same basic format: message elements contain multiple request elements, or multiple response elements. Messaging is all synchronous. The same number of responses as requests will be returned. Currently all requests are independent, so any requests can be combined into the same message, and they will be answered separately, with their responses being sent back in a single message.
+
+When a page request (external request) comes in to the Receptionist, it looks at the action attribute and passes the request to the appropriate Action module. The Action will fire one or more internal requests to the MessageRouter, based on the arguments. The data is gathered into a  response, which is returned to the Receptionist.  The page that the receptionist returns contains the original request, the response from the action and other info as needed (depends on the type of Receptionist). The data may be transformed in some way --- for the \gs\ servlet  we transform using XSLT to generate HTML pages.
+
+Actions send internal style messages to the MessageRouter. Some can be answered by it, others are passed on to collections, and maybe on to services. Internal requests are for simple actions, such as search, retrieve metadata, retrieve document text
+There are different internal request types: describe, process, system, format, status. Process requests do the actual work of the system, while the other types get auxiliary information. The format of the requests and responses for each internal request type are described in the following sections. External style requests, and their page responses are described in the Section about page generation (Section~\ref{sec:pagegen}).
+
+\subsection{'describe'-type messages}\label{sec:describe}
+
+The most basic of the internal standard requests is ``describe-yourself'', which can be sent to any module in the system. The module responds with a semi-predefined piece of XML, making these requests very efficient. The response is predefined apart from any language-specific text strings, which are put together as each request comes in, based on the language attribute of the request.
+\begin{quote}\begin{gsc}\begin{verbatim}
+<request lang='en' type='describe' to=''/>
+\end{verbatim}\end{gsc}\end{quote}
+If the \gst{to} field is empty, a request is answered by the MessageRouter. 
+An example response from a MessageRouter might look like this:
+\begin{quote}\begin{gsc}\begin{verbatim}
+<response lang='en' type='describe'>
+  <serviceList/>
+  <siteList>
+    <site name='org.greenstone.gsdl1'
+            address='http://localhost:8080/greenstone3/services/localsite'
+            type='soap' />
+  </siteList>
+  <serviceClusterList>
+    <serviceCluster name="build" />
+  </serviceClusterList>
+  <collectionList>
+    <collection name='org.greenstone.gsdl1/
+  	              org.greenstone.gsdl2/fao' />
+    <collection name='org.greenstone.gsdl1/demo' />
+    <collection name='org.greenstone.gsdl1/fao' />
+    <collection name='myfiles' />
+  </collectionList>
+</response>
+\end{verbatim}\end{gsc}\end{quote}
+This MessageRouter has no individual site-wide services (an empty \gst{<serviceList>}), but has a service cluster called build (which provides collection importing and building functionality).  It
+communicates with one site, \gst{org.greenstone.gsdl1}.  It is aware of four
+collections.  One of these, \gst{myfiles}, belongs to it; the other three are
+available through the external site.  One of those collections is actually from
+a further external site.
+
+It is possible to ask just for a specific part of the information provided by a
+describe request, rather than the whole thing. For example, these two
+messages get the \gst{collectionList} and the \gst{siteList} respectively: 
+\begin{quote}\begin{gsc}\begin{verbatim}
+<request lang='en' type='describe' to=''>
+  <paramList>
+    <param name='subset' value='collectionList'/>
+  </paramList>
+</request>
+
+<request lang='en' type='describe' to=''>
+  <paramList>
+    <param name='subset' value='siteList'/>
+  </paramList>
+</request>
+\end{verbatim}\end{gsc}\end{quote}
+
+Subset options for the MessageRouter include \gst{collectionList}, \gst{serviceClusterList}, \gst{serviceList}, \gst{siteList}.
+
+When a collection or service cluster is asked to describe itself, what is returned is a list of metadata, some display elements, and  a list of services.  For example, here is such a message, along with a sample response.
+
+\begin{quote}\begin{gsc}\begin{verbatim}
+<request lang='en' type='describe' to='mgppdemo'/>
+
+<response from="mgppdemo" type="describe">
+  <collection name="mgppdemo">
+    <displayItem lang="en" name="name">greenstone mgpp demo
+    </displayItem>
+    <displayItem lang="en" name="description">This is a 
+      demonstration collection for the Greenstone digital 
+      library software. It contains a small subset (11 books) 
+      of the Humanity Development Library. It is built with 
+      mgpp.</displayItem>
+    <displayItem lang="en" name="icon">mgppdemo.gif</displayItem>
+    <serviceList>
+      <service name="DocumentStructureRetrieve" type="retrieve" />
+      <service name="DocumentMetadataRetrieve" type="retrieve" />
+      <service name="DocumentContentRetrieve" type="retrieve" />
+      <service name="ClassifierBrowse" type="browse" />
+      <service name="ClassifierBrowseMetadataRetrieve" 
+            type="retrieve" />
+      <service name="TextQuery" type="query" />
+      <service name="FieldQuery" type="query" />
+      <service name="AdvancedFieldQuery" type="query" />
+      <service name="PhindApplet" type="applet" />
+    </serviceList>
+    <metadataList>
+      <metadata name="creator">greenstone@cs.waikato.ac.nz</metadata>
+      <metadata name="numDocs">11</metadata>  
+      <metadata name="buildType">mgpp</metadata>
+      <metadata name="httpPath">http://kanuka:8090/greenstone3/sites/
+                                localsite/collect/mgppdemo</metadata>
+    </metadataList>
+  </collection>
+</response>
+\end{verbatim}\end{gsc}\end{quote}
+
+Subset options for a collection or serviceCluster include \gst{metadataList}, \gst{serviceList}, and \gst{displayItemList}.
+
+This collection provides many typical services. Notice how this response lists the services available, while the collection configuration file for this collection (Figure~\ref{fig:collconfig}) described serviceRacks. Once the service racks have been configured, they become transparent in the system, and only services are referred to.
+There are three document retrieval services, for structural information, metadata, and content. The Classifier services retrieve classification structure and metadata. These five services were all provided by the GS2MGPPRetrieve ServiceRack. The three query services were provided by GS2MGPPSearch serviceRack, and provide different kinds of query interface. The last service, PhindApplet, is provided by the PhindPhraseBrowse serviceRack and is an applet service.
+
+A \gst{describe} request sent to a service returns a list of parameters that
+the service accepts and some display information, (and in future may describe the content type for the request and response). Subset options for the request include \gst{paramList} and \gst{displayItemList}.
+
+Parameters can be in the following formats:
+\begin{quote}\begin{gsc}\begin{verbatim}
+<param name='xxx' type='integer|boolean|string|invisible' default='yyy'/>
+<param name='xxx' type='enum_single|enum_multi' default='aa'/>
+  <option name='aa'/><option name='bb'/>...
+</param>
+<param name='xxx' type='multi' occurs='4'>
+ <param .../>
+ <param .../>
+</param>
+\end{verbatim}\end{gsc}\end{quote}
+
+If no default is specified, the parameter is assumed to be mandatory.
+Here are some examples of parameters:
+\begin{quote}\begin{gsc}\begin{verbatim}
+<param name='case' type='boolean' default='0'/>
+
+<param name='maxDocs' type='integer' default='50'/>
+
+<param name='index' type='enum' default='dtx'>
+  <option name='dtx'/>
+  <option name='stt'/>
+  <option name='stx'/>
+<param>
+
+<!-- this one is for the text box and field list for the 
+simple field query-->
+<param name='simpleField' type='multi' occurs='4'>
+  <param name='fqv' type='string'/>
+  <param name='fqf' type='enum_single'>
+    <option name='TI'/><option name='AU'/><option name='OR'/>
+  </param>
+</param>
+
+\end{verbatim}\end{gsc}\end{quote}
+The type attribute is used to determine how to display the parameters on a web page or interface. For example, a string parameter may result in a text entry box, a boolean an on/off button, enum\_single/enum\_multi a drop-down menu, where one or many items, respectively, can be selected.
+A multi-type parameter indicates that two or more parameters are associated, and should be displayed appropriately. For example, in a field query, the text box and field list should be associated. The occurs attribute specifies how many times the parameter should be displayed on the page.
+Parameters also come with display information: all the text strings needed to present them to the user. These include the name of the parameter and the display values for any options. These are included in the above parameter descriptions in the form of \gst{<displayItem>} elements.
+
+A service description also contains some display information---this includes the name of the service, and the text  for the submit button. 
+
+Here is a sample describe request to the FieldQuery service of collection mgppdemo, along with its response. The parameters in this example include their display information. Figure~\ref{fig:query-display} shows an example HTML search form that may be generated from this describe response. 
+
+\begin{quote}\begin{gsc}\begin{verbatim}
+<request lang="en" to="mgppdemo/FieldQuery" type="describe" />
+
+<response from="mgppdemo/FieldQuery" type="describe">
+  <service name="FieldQuery" type="query">
+    <displayItem name="name">Form Query</displayItem>
+    <displayItem name="submit">Search</displayItem>
+    <paramList>
+      <param default="Doc" name="level" type="enum_single">
+        <displayItem name="name">Granularity to search at</displayItem>
+        <option name="Doc">
+          <displayItem name="name">Document</displayItem>
+        </option>
+        <option name="Sec">
+          <displayItem name="name">Section</displayItem>
+        </option>
+        <option name="Para">
+          <displayItem name="name">Paragraph</displayItem>
+        </option>
+      </param>
+      <param default="1" name="case" type="boolean">
+        <displayItem name="name">Turn casefolding </displayItem>
+        <option name="0">
+          <displayItem name="name">off</displayItem>
+        </option>
+        <option name="1">
+          <displayItem name="name">on</displayItem>
+        </option>
+      </param>
+      <param default="1" name="stem" type="boolean">
+        <displayItem name="name">Turn stemming </displayItem>
+        <option name="0">
+          <displayItem name="name">off</displayItem>
+        </option>
+        <option name="1">
+          <displayItem name="name">on</displayItem>
+        </option>
+      </param>
+      <param default="10" name="maxDocs" type="integer">
+        <displayItem name="name">Maximum documents to return
+        </displayItem>
+      </param>
+      <param name="simpleField" occurs="4" type="multi">
+        <displayItem name="name"></displayItem>
+        <param name="fqv" type="string">
+          <displayItem name="name">Word or phrase </displayItem>
+        </param>
+        <param default="ZZ" name="fqf" type="enum_single">
+          <displayItem name="name">in field</displayItem>
+          <option name="ZZ">
+            <displayItem name="name">allfields</displayItem>
+          </option>	  
+          <option name="TX">
+            <displayItem name="name">text</displayItem>
+          </option>
+          <option name="TI">
+            <displayItem name="name">Title</displayItem>
+          </option>
+          <option name="SU">
+            <displayItem name="name">Subject</displayItem>
+          </option>
+          <option name="ORG">
+            <displayItem name="name">Organization</displayItem>
+          </option>
+          <option name="SO">
+            <displayItem name="name">Source</displayItem>
+          </option>
+        </param>
+      </param>
+    </paramList>
+  </service>
+</response>
+\end{verbatim}\end{gsc}\end{quote}
+
+\begin{figure}[t]
+  \centering
+  \includegraphics[width=3.5in]{query2.ps}
+  \caption{The previous query service describe response as displayed on the search page.}
+  \label{fig:query-display}
+\end{figure}
+
+A describe request to an applet type service returns the applet HTML element: this will be embedded into a web page to run the applet. 
+\begin{quote}\begin{gsc}\begin{verbatim}
+<request type='describe' to='mgppdemo/PhindApplet'/>
+
+<response type='describe'>
+  <service name='PhindApplet' type='query'>
+    <applet ARCHIVE='phind.jar, xercesImpl.jar, gsdl3.jar, 
+			jaxp.jar, xml-apis.jar'
+            CODE='org.greenstone.applet.phind.Phind.class'
+            CODEBASE='lib/java'
+            HEIGHT='400' WIDTH='500'>
+      <PARAM NAME='library' VALUE=''/>
+      <PARAM NAME='phindcgi' VALUE='?a=a&amp;sa=r&amp;sn=Phind'/>
+      <PARAM NAME='collection' VALUE='mgppdemo' />
+      <PARAM NAME='classifier' VALUE='1' />
+      <PARAM NAME='orientation' VALUE='vertical' />
+      <PARAM NAME='depth' VALUE='2' />
+      <PARAM NAME='resultorder' VALUE='L,l,E,e,D,d' />
+      <PARAM NAME='backdrop' VALUE='interfaces/default/>
+				      images/phindbg1.jpg'/>
+      <PARAM NAME='fontsize' VALUE='10' />
+      <PARAM NAME='blocksize' VALUE='10' />
+      The Phind java applet.
+    </applet>
+    <displayItem name="name">Browse phrase hierarchies</displayItem>
+  </service>
+</response>
+\end{verbatim}\end{gsc}\end{quote}
+
+Note that the library parameter has been left blank. This is because library refers to the current servlet that is running and the name is not necessarily known in advance. So either the applet action or the Receptionist must fill in this parameter before displaying the HTML.
+
+\subsection{'system'-type messages}\label{sec:system}
+
+``System'' requests are used to tell a MessageRouter, Collection or ServiceCluster to update its cached information and activate or deactivate other modules. For example, the MessageRouter has a set of Collection modules that it can talk to. It also holds some XML information about those collections---this is returned when a request for a collection list comes in. If a collection is deleted or modified, or a new one created, this information may need to change, and the list of available modules may also change. Currently these requests are initiated by particular CGI requests (see Section~\ref{sec:runtime-config}).
+
+The basic format of a system request is as follows:
+
+\begin{quote}\begin{gsc}\begin{verbatim}
+<request type='system' to=''>
+  <system .../>
+</request>
+\end{verbatim}\end{gsc}\end{quote}
+
+One or more actual requests are specified in  system elements. The following are examples:
+\begin{quote}\begin{gsc}\begin{verbatim}
+<system type='configure' subset=''/>
+<system type='configure' subset='collectionList'/>
+<system type='activate' moduleType='collection' moduleName='demo'/>
+<system type='deactivate' moduleType='site' moduleName='site1'/>
+\end{verbatim}\end{gsc}\end{quote}
+
+The first request reconfigures the whole site---the MessageRouter goes through its whole configure process again. The second request just reconfigures the collectionList---the MessageRouter will delete all its collection information, and re-look through the collect directory and reload all the collections again.
+The third request is to activate collection demo. This could be a new collection, or a reactivation of an old one. If a collection module already exists, it will be deleted, and a new one loaded. The final request deactivates the site site1---this removes the site from the siteList and module map, and also removes any of that sites collections/services from the static lists.
+
+A response just contains a status message\footnote{TODO: add in error/status codes}, for example:
+\begin{quote}\begin{gsc}\begin{verbatim}
+<status>MessageRouter reconfigured successfully</status>
+<status>Error on reconfiguring collectionList</status>
+<status>collection:demo activated</status>
+<status>site:site1 deactivated</status>
+\end{verbatim}\end{gsc}\end{quote}
+
+System requests are mainly answered by the MessageRouter. However, Collections and ServiceClusters will respond to a subset of these requests. 
+
+\subsection{'format'-type messages}\label{sec:format}
+
+Collection designers are able to specify how their collection looks to a certain degree. They can specify format statements for display that will apply to the results of a search, the display of a document, entries in a classification hierarchy, for example. This info is generally service specific. All services respond to a format request, where they return any service specific formatting information. A typical request and response looks like this:
+\begin{quote}\begin{gsc}\begin{verbatim}
+<request lang="en" to="mgppdemo/FieldQuery" type="format" />
+
+<response from="mgppdemo/FieldQuery" type="format">
+  <format>
+    <gsf:template match="documentNode"><td><gsf:link>
+      <gsf:metadata name="Title" />(<gsf:metadata name="Source" />)
+      </gsf:link></td>
+    </gsf:template>
+  </format>
+</response>
+\end{verbatim}\end{gsc}\end{quote}
+
+The actual format statements are described in Section~\ref{sec:formatstmt}. They are templates written directly in XSLT, or in GSF (GreenStone Format) which is a simple XML representation of the more complicated XSLT templates. 
+GSF-style format statements need to be converted to proper XSLT. This is currently done by the Receptionist (but may be moved to an ActionHelper): the format XML is transformed to XSLT using XSLT with the config\_format.xsl stylesheet.
+
+\subsection{'status'-type messages}\label{sec:status}
+
+These are only used with process-type services, which are those where a request is sent to start some type of process (see Section~\ref{sec:process}). An initial 'process' request to a 'process' service generates a response which states whether the process had successfully started, and whether its still continuing. If the process is not finished, status requests can be sent repeatedly to the service to poll the status, using the pid to identify the  process.  Status codes are used to identify the state of a process. The values used at the moment are listed in Table~\ref{tab:status codes}\footnote{A more standard set of codes should probably be used, for example, the HTTP codes}.
+
+\begin{table}
+\caption{Status codes currently used in \gsiii\ }
+\label{tab:status codes}
+{\footnotesize
+\begin{tabular}{llp{8cm}}
+\hline
+\bf code name & \bf code  & \bf meaning \\
+& \bf value & \\
+\hline
+SUCCESS &  1 & the request was accepted, and the process was  completed \\
+ACCEPTED & 2 & the request was accepted, and the process has been started, but it is not completed yet \\
+ERROR & 3 & there was an error and the process was stopped \\
+CONTINUING & 10 & the process is still continuing \\
+COMPLETED & 11 & the process has  finished \\
+HALTED & 12 & the process has stopped  \\
+INFO & 20 & just an info message that doesn't imply anything \\
+\hline
+\end{tabular}}
+\end{table}
+
+ The following shows an example status request, along with two responses, the first a 'OK but continuing' response, and the second a 'successfully completed' response. The content of the status elements in the two responses is the output from the process since the last status update was sent back.
+
+\begin{quote}\begin{gsc}\begin{verbatim}
+<request lang="en" to="build/ImportCollection" type="status">
+  <paramList>
+    <param name="pid" value="2" />
+  </paramList>
+</request>
+
+<response from="build/ImportCollection">
+  <status code="2" pid="2">Collection construction: import collection.
+command = import.pl -collectdir /research/kjdon/home/greenstone3/web/sites/
+    localsite/collect test1
+starting
+  </status>
+</response>
+
+<response from="build/ImportCollection">
+  <status code="11" pid="2">RecPlug: getting directory 
+/research/kjdon/home/greenstone3/web/sites/localsite/collect/test1/import
+WARNING - no plugin could process /.keepme
+ 
+*********************************************
+Import Complete
+*********************************************
+* 1 document was considered for processing
+* 0 were processed and included in the collection
+* 1 was rejected. See /research/kjdon/home/greenstone3/web/sites/
+    localsite/collect/test1/etc/fail.log for a list of rejected documents
+Success
+  </status>
+</response>
+\end{verbatim}\end{gsc}\end{quote}
+
+\subsection{'process'-type messages}
+
+Process requests and responses  provide  the major functionality of the system---these are the ones that do the actual work. The format depends on the service they are for, so I'll describe these by service.
+
+Query type services TextQuery, FieldQuery, AdvancedFieldQuery (GS2MGSearch, GS2MGPPSearch), TextQuery (LuceneSearch)
+The main type of requests in the system are for services. There are different types of services, currently: \gst{query}, \gst{browse}, \gst{retrieve}, \gst{process}, \gst{applet}, \gst{enrich}. Query services do some kind of search and return a list of document identifiers. Retrieve services can return the content of those documents, metadata about the documents, or other resources. Browse is for browsing lists or hierarchies of documents. Process type services are those where the request is for a command to be run. A status code will be returned immediately, and then if the command has not finished, an update of the status can be requested. Applet services are those that run an applet. Enrich services take a document and return the document with some extra markup added.
+
+  Other possibilities include transform, extract, accrete. These types of service generally enhance the functionality of the first set. They may be used during collection formation: 'accrete' documents by adding them to a collection, 'transform' the documents into a different format, 'extract' information or acronyms from the documents, 'enrich' those documents with the information extracted or by adding new information. They may also be used during querying: 'transform' a query before using it to query a collection, or 'transform' the documents you get back into an appropriate form.
+
+The basic structure of a service 'process' request is as follows:
+\begin{quote}\begin{gsc}\begin{verbatim}
+
+<request lang='en'  type='process' to='demo/TextQuery'>
+  <paramList/>
+  other elements...
+</request>
+
+\end{verbatim}\end{gsc}\end{quote}
+
+The parameters are name-value pairs corresponding to parameters that were specified in the service description sent in response to a describe request. 
+
+\begin{quote}\begin{gsc}\begin{verbatim}
+<param name='case' value='1'/>
+<param name='maxDocs' value='34'/>
+<param name='index' value='dtx'/>
+\end{verbatim}\end{gsc}\end{quote}
+
+Some requests have other content---for document retrieval, this would be a list of document identifiers to retrieve. For metadata retrieval, the content is the list of documents to retrieve metadata for. 
+
+Responses vary depending on the type of request. The following sections look at the process type requests and responses for each type of service.
+
+\subsubsection{'query'-type services}
+Responses to query requests contain a list of document identifiers, along with some other information, dependent on the query type. For a text query, this includes term frequency information, and some metadata about the result. For instance, a text query on 'snail farming', with the parameter 'maxDocs=10' might return the first 10 documents, and one of the query metadata items would be the total number of documents that matched the query.\footnote{no metadata about the query result is returned yet.}
+
+The following shows an example query request and its response.
+
+Find at most 10 Sections in the mgppdemo collection, containing the word snail (stemmed), returning the results in ranked order:
+\begin{quote}\begin{gsc}\begin{verbatim}
+<request lang='en'  to="mgppdemo/TextQuery" type="process">
+  <paramList>
+    <param name="maxDocs" value="10"/>
+    <param name="queryLevel" value="Section"/>
+    <param name="stem" value="1"/>
+    <param name="matchMode" value="some"/>
+    <param name="sortBy" value="1"/>
+    <param name="index" value="t0"/>
+    <param name="case" value="0"/>
+    <param name="query" value="snail"/>
+  </paramList>
+</request>
+
+<response from="mgppdemo/TextQuery" type="process">
+  <metadataList>
+    <metadata name="numDocsMatched" value="59" />
+  </metadataList>
+  <documentNodeList>
+    <documentNode nodeID="HASHac0a04dd14571c60d7fbfd.4.2" 
+	docType='hierarchy' nodeType="leaf" />
+    <documentNode nodeID="HASH010f073f22033181e206d3b7.2.12" 
+	docType='hierarchy' nodeType="leaf" />
+    <documentNode nodeID="HASH010f073f22033181e206d3b7.1" 
+	docType='hierarchy' nodeType="interior" />
+    <documentNode nodeID="HASHac0a04dd14571c60d7fbfd.2.2" 
+	docType='hierarchy' nodeType="leaf" />
+    ...
+  </documentNodeList>
+  <termList>
+    <term field="" freq="454" name="snail" numDocsMatch="58" stem="3">
+      <equivTermList>
+        <term freq="" name="Snail" numDocsMatch="" />
+        <term freq="" name="snail" numDocsMatch="" />
+        <term freq="" name="Snails" numDocsMatch="" />
+        <term freq="" name="snails" numDocsMatch="" />
+      </equivTermList>
+    </term>
+  </termList>
+</response>
+\end{verbatim}\end{gsc}\end{quote}
+
+The list of document identifiers includes some information about document type and node type. Currently, document types include \gst{simple}, \gst{paged} and \gst{hierarchy}. \gst{simple} is for single section documents, i.e. ones with no sub-structure. \gst{paged} is documents that have a single list of sections, while \gst{hierarchy} type documents have a hierarchy of nested sections. For \gst{paged} and \gst{hierarchy} type documents, the node type identifies whether a section is the root of the document, an internal section, or a leaf.
+
+The term list identifies, for each term in the query, what its frequency in the collection is, how many documents contained that term, and a list of its equivalent terms (if stemming or casefolding was used).
+
+\subsubsection{'browse'-type services}
+
+Browse type services are used for classification browsing. The request consists of a list of classifier identifiers, and some structure parameters listing what structure to retrieve.
+
+\begin{quote}\begin{gsc}\begin{verbatim}
+<request lang="en" to="mgppdemo/ClassifierBrowse" type="process">
+  <paramList>
+    <param name="structure" value="ancestors" />
+    <param name="structure" value="children" />
+  </paramList>
+  <classifierNodeList>
+    <classifierNode nodeID="CL1.2" />
+  </classifierNodeList>
+</request>
+
+<response from="mgppdemo/ClassifierBrowse" type="process">
+  <classifierNodeList>
+    <classifierNode nodeID="CL1">
+      <nodeStructure>
+	<classifierNode nodeID="CL1">
+          <classifierNode nodeID="CL1.2">
+	    <classifierNode nodeID="CL1.2.1" />
+	    <classifierNode nodeID="CL1.2.2" />
+	    <classifierNode nodeID="CL1.2.3" />
+	    <classifierNode nodeID="CL1.2.4" />
+	    <classifierNode nodeID="CL1.2.5" />
+          </classifierNode>	
+	</classifierNode>
+      </nodeStructure>
+    </classifierNode>
+  </classifierNodeList>
+</response>
+\end{verbatim}\end{gsc}\end{quote}
+
+Possible values for structure parameters are \gst{ancestors}, \gst{parent}, \gst{siblings}, \gst{children}, \gst{descendents}. The response gives, for each identifier in the request, a \gst{<nodeStructure>} element with all the requested structure put together into a hierarchy. The structure may include classifier and document nodes. 
+
+
+\subsubsection{'retrieve'-type services}
+
+Retrieval services are special in that requests are not explicitly initiated by a user from a form on a web page, but are called from actions in response to other things. This means that their names are hard-coded into the Actions. DocumentContentRetrieve, DocumentStructureRetrieve and DocumentMetadataRetrieve are the standard names for retrieval services for content, structure, and metadata of documents. Requests to each of these include a list of document identifiers. Because these generally refer to parts of documents, the elements are called \gst{<documentNode>}. For the content, that is all that is required. For the metadata retrieval service, the request also needs parameters specifying what metadata is required. For structure retrieval services, requests need parameters specifying what structure or structural info is required.
+
+Some example requests and responses follow.
+
+Give me the Title metadata for these documents:
+\begin{quote}\begin{gsc}\begin{verbatim}
+
+<request lang="en" to="mgppdemo/DocumentMetadataRetrieve" type="process">
+  <paramList>
+    <param name="metadata" value="Title" />
+  </paramList>
+  <documentNodeList>
+    <documentNode nodeID="HASHac0a04dd14571c60d7fbfd.4.2"/>
+    <documentNode nodeID="HASH010f073f22033181e206d3b7.2.12"/>
+    <documentNode nodeID="HASH010f073f22033181e206d3b7.1"/>
+    ...
+  </documentNodeList>
+</request>
+
+<response from="mgppdemo/DocumentMetadataRetrieve" type="process">
+  <documentNodeList>
+    <documentNode nodeID="HASHac0a04dd14571c60d7fbfd.4.2">
+      <metadataList>
+        <metadata name="Title">Putting snails in your second pen</metadata>
+      </metadataList>
+    </documentNode>
+    <documentNode nodeID="HASH010f073f22033181e206d3b7.2.12">
+      <metadataList>
+        <metadata name="Title">Now you must decide</metadata>
+      </metadataList>
+    </documentNode>
+    <documentNode nodeID="HASH010f073f22033181e206d3b7.1">
+      <metadataList>
+        <metadata name="Title">Introduction</metadata>
+      </metadataList>
+    </documentNode>
+  </documentNodeList>
+</response>
+\end{verbatim}\end{gsc}\end{quote}
+
+One or more parameters specifying metadata may be included in a request. Also, a metadata  value of \gst{all} will retrieve all the metadata for each document.
+
+Any browse-type service must also implement a metadata retrieval service to provide metadata for the nodes in the classification hierarchy. The name of it is the browse service name plus \gst{MetadataRetrieve}. For example, the ClassifierBrowse service described in the previous section should also have a ClassifierBrowseMetadataRetrieve service. The request and response format is exactly the same as for the DocumentMetadataRetrieve service, except that \gst{<documentNode>} elements are replaced by \gst{<classifierNode>} elements (and the corresponding list element is also changed).
+
+Give me the text (content) of this document:
+\begin{quote}\begin{gsc}\begin{verbatim}
+<request lang="en" to="mgppdemo/DocumentContentRetrieve" type="process">
+  <paramList />
+  <documentNodeList>
+    <documentNode nodeID="HASHac0a04dd14571c60d7fbfd.4.2" />
+  </documentNodeList>
+</request>
+
+<response from="mgppdemo/DocumentContentRetrieve" type="process">
+  <documentNodeList>
+    <documentNode nodeID="HASHac0a04dd14571c60d7fbfd.4.2">
+      <nodeContent>&lt;Section&gt; 
+       &lt;/B&gt;&lt;P ALIGN=&quot;JUSTIFY&quot;&gt;&lt;/P&gt;
+       &lt;P ALIGN=&quot;JUSTIFY&quot;&gt;190. When the plants in 
+       your second pen have grown big enough to provide food and 
+       shelter, you can put in the snails.&lt;/P&gt;
+      </nodeContent>
+    </documentNode>
+  </documentNodeList>
+</response>
+\end{verbatim}\end{gsc}\end{quote}
+
+The content of a node is returned in a \gst{<nodeContent>} element. In this case it is escaped HTML.
+
+Give me the ancestors and children of the specified node, along with the number of siblings it has:
+\begin{quote}\begin{gsc}\begin{verbatim}
+<request lang="en" to="mgppdemo/DocumentStructureRetrieve" type="process">
+  <paramList>
+    <param name="structure" value="ancestors" />
+    <param name="structure" value="children" />
+    <param name="info" value="numSiblings" />
+  </paramList>
+  <documentNodeList>
+    <documentNode nodeID="HASHac0a04dd14571c60d7fbfd.4.2" />
+  </documentNodeList>
+</request>
+
+<response from="mgppdemo/DocumentStructureRetrieve" type="process">
+  <documentNodeList>
+    <documentNode nodeID="HASHac0a04dd14571c60d7fbfd.4.2">
+      <nodeStructureInfo>
+        <info name="numSiblings" value="2" />
+      </nodeStructureInfo>
+      <nodeStructure>
+        <documentNode nodeID="HASHac0a04dd14571c60d7fbfd" 
+                docType='hierarchy' nodeType="root">
+          <documentNode nodeID="HASHac0a04dd14571c60d7fbfd.4" 
+                  docType='hierarchy' nodeType="interior">
+            <documentNode nodeID="HASHac0a04dd14571c60d7fbfd.4.2" 
+                   docType='hierarchy' nodeType="leaf" />
+          </documentNode>
+        </documentNode>
+      </nodeStructure>
+    </documentNode>
+  </documentNodeList>
+</response>
+\end{verbatim}\end{gsc}\end{quote}
+
+Structure is returned inside a \gst{<nodeStructure>} element, while structural info is returned in a \gst{<nodeStructureInfo>} element. Possible values for structure parameters are as for browse services: \gst{ancestors}, \gst{parent}, \gst{siblings}, \gst{children}, \gst{descendents}, \gst{entire}. Possible values for info parameters are \gst{numSiblings}, \gst{siblingPosition}, \gst{numChildren}. 
+
+\subsubsection{'process'-type services}\label{sec:process}
+Requests to process-type services are not requests for data---they request some action to be carried out, for example, create a new collection, or import a collection. The response is a status or an error message. The import and build commands may take a long time to complete, so a response is sent back after a successful start to the command. The status may be polled by the requester to see how the process is going. 
+
+Process requests generally contain just a parameter list. Like for any service, the parameters used by a process-type service can be obtained by a describe request to that service.
+
+Here are two example requests for process-services that are part of the build service cluster (hence the addresses all begin with 'build/'), followed by an example response:
+
+\begin{quote}\begin{gsc}\begin{verbatim}
+<request lang='en'  type='process' to='build/NewCollection'>
+  <paramList>
+    <param name='creator' value='me@home.com'/>
+    <param name='collName' value='the demo collection'/>
+    <param name='collShortName' value='demo'/>
+  </paramlist>
+</request>
+
+<request lang='en'  type='process' to='build/ImportCollection'>
+  <paramList>
+    <param name='collection' value='demo'/>
+  </paramlist>
+</request>
+
+<response from="build/ImportCollection">
+  <status code="2" pid="2">Starting process...</status>
+</response>
+\end{verbatim}\end{gsc}\end{quote}
+
+The \gst{code} attribute in the response specifies whether the command has been successfully stated, whether its still going, etc (see Table~\ref{tab:status codes} for a list of currently used codes). The pid attribute specifies a process id number that can be used when querying the status of this process. The content of the status element is (currently) just the output from the process so far. Status messages, which were described in Section~\ref{sec:status}, are used to find out how the process is going, and whether it has finished or not.
+
+\subsubsection{'applet'-type services}
+
+Applet-type services are those that process the data for an applet. A request consists only of a list of parameters, and the response contains an \gst{<appletData>} element that contains the XML data to be returned to the applet. The format of this is entirely specific to the applet---there is no set format to the applet data.
+
+Here is an example request and response, used by the Phind applet:
+\begin{quote}\begin{gsc}\begin{verbatim}
+  <request type='query' to='mgppdemo/PhindApplet'>
+    <paramList>
+      <param name='pc' value='1'/>
+      <param name='pptext' value='health'/>
+      <param name='pfe' value='0'/>
+      <param name='ple' value='10'/>
+      <param name='pfd' value='0'/>
+      <param name='pld' value='10'/>
+      <param name='pfl' value='0'/>
+      <param name='pll' value='10'/>
+    </paramList>
+  </request>
+
+  <response type='query' from='mgppdemo/PhindApplet'>
+    <appletData>
+      <phindData df='9' ef='46' id='933' lf='15' tf='296'>
+        <expansionList end='10' length='46' start='0'>
+          <expansion df='4' id='8880' num='0' tf='59'>
+            <suffix> CARE</suffix>
+          </expansion>
+          ...
+        </expansionList>
+        <documentList end='10' length='9' start='0'>
+          <document freq='78' hash='HASH4632a8a51d33c47a75c559' num='0'>
+            <title>The Courier - N??159 - Sept- Oct 1996 Dossier Investing 
+                   in People Country Reports: Mali ; Western Samoa
+            </title>
+          </document>
+          ...
+        </documentList>
+        <thesaurusList end='10' length='15' start='0'>
+          <thesaurus df='7' id='12387' tf='15' type='RT'>
+            <phrase>PUBLIC HEALTH</phrase>
+          </thesaurus>...
+        </thesaurusList>
+      </phindData>
+    </appletData>
+  </response>
+
+\end{verbatim}\end{gsc}\end{quote}
+
+\subsubsection{'enrich'-type services}
+
+Enrich services typically take some text of documents (inside \gst{<nodeContent>} tags) and returns the text marked up in some way. One example of this is the GatePOSTag service: this identifies Dates, Locations, People and Organizations in the text, and annotates the text with the labels. In the following example, the request is for Location and Dates to be identified.
+
+\begin{quote}\begin{gsc}\begin{verbatim}
+<request lang="en" to="GatePOSTag" type="process">
+  <paramList>
+    <param name="annotationType" value="Date,Location" />
+  </paramList>
+  <documentNodeList>
+    <documentNode nodeID="HASHac0a04dd14571c60d7fbfd">
+      <nodeContent>
+        FOOD AND AGRICULTURE ORGANIZATION OF THE UNITED NATIONS
+        Rome 1986
+        P-69
+        ISBN 92-5-102397-2
+        FAO 1986
+      </nodeContent>
+    </documentNode>
+  </documentNodeList>
+</request>
+
+<response from="GatePOSTag" type="process">
+  <documentNodeList>
+    <documentNode nodeID="HASHac0a04dd14571c60d7fbfd">
+      <nodeContent>
+	FOOD AND AGRICULTURE ORGANIZATION OF THE UNITED NATIONS
+	<annotation type="Location">Rome</annotation> 
+        <annotation type="Date">1986</annotation>
+        P-69
+        ISBN 92-5-102397-2
+        FAO <annotation type="Date">1986</annotation>
+      </nodeContent>
+    </documentNode>
+  </documentNodeList>
+</response>
+\end{verbatim}\end{gsc}\end{quote}
+
+\subsection{Page generation}\label{sec:pagegen} 
+
+A 'page' is some XML or HTML (or other?) data returned in response to an 
+external 'page'-type request. These requests originate from outside \gs\ , for example from a servlet, or Java application, and are received by the Receptionist. As described below in Section~\ref{sec:page-requests}, the requests are XML representations of \gs\  URLs. One of the arguments is action (a). This tells the Receptionist which Action module to pass the request to. 
+
+Action modules decode the rest of the arguments to determine what requests need to be made to the system. One or more internal requests may be made to the MessageRouter. A request for format information from the Collection/Service may also be made. The resulting data is gathered together into a single XML response, \gst{<page>}, and returned to the Receptionist. 
+
+The page format is described in Section~\ref{sec:page-format}. The XML may be returned as is, or may be modified by the Receptionist. The various Receptionists are described in Section~\ref{sec:recepts}. The default receptionist used by a servlet transforms the XML into HTML using XSL stylesheets. Section~\ref{sec:collformat} looks at collection specific formatting, in particular for HTML output.
+Sections~\ref{sec:pageaction} to \ref{sec:systemaction} look at the various actions and what kind of data they gather.
+
+\subsubsection{'page'-type requests and their arguments}\label{sec:page-requests}
+
+These are requests for a 'page' of data---for example, the home page for a site; the query page for a collection; the text of a document. They contain, in XML, a list of arguments specifying what type of page is required. If the external context is a servlet, the arguments represent the 'CGI' arguments in a \gs\  URL.  The two main arguments are \gst{a} (action) and \gst{sa} (subaction). All other arguments are encoded as parameters.
+
+Here are some examples of  requests\footnote{In a servlet context, these correspond to the arguments \gst{a=p\&sa=about\&c=demo\&l=fr}, and \gst{a=q\&l=en\&s=TextQuery\&c=demo\&rt=r\&ca=0\&st=1\&m=10\&q=snail}.}:
+
+\begin{quote}\begin{gsc}\begin{verbatim}
+<request type='page' action='p' subaction='about'
+         lang='fr' output='html'>
+  <paramList>
+    <param name='c' value='demo'/>
+  </paramList>
+</request>
+\end{verbatim}\end{gsc}\end{quote}
+
+\begin{quote}\begin{gsc}\begin{verbatim}
+<request type='page' action='q' lang='en' output='html'>
+  <paramList>
+    <param name='s' value='TextQuery'/>
+    <param name='c' value='demo'/>
+    <param name='rt' value='r'/>
+    <!-- the rest are the service specific params -->
+    <param name='ca' value='0'/> <!-- casefold -->
+    <param name='st' value='1'/> <!-- stem -->
+    <param name='m' value='10'/> <!-- maxdocs -->
+    <param name='q' value='snail'/> <!-- query string -->
+  </paramList>
+</request>
+\end{verbatim}\end{gsc}\end{quote}
+
+There are some standard arguments used in Greenstone, and they are described in Table~\ref{tab:args}. These are used by Receptionists and Actions. The GSParams class specifies all the general basic arguments, and whether they should be saved or not (Some arguments need to be saved during a session, and this needs to be implemented outside \gs\  proper --- currently we do this in the servlet, using servlet session handling). The servlet has an init parameter \gst{params\_class} which specifies which params class to use: GSParams can be subclassed if necessary. The Receptionist and Actions must not have conflicting argument names.
+
+Other arguments are used dynamically and come from the Services. Service arguments must always be saved during a session. Services may be created by different people, and may reside on a different site. There is no guarantee that there is no conflict with argument names between services and actions. Therefore service parameters are namespaced when they are put on the page, whereas interface (receptionist and action) parameters have no namespace. The default namespace is s1 (service1) --- any parameters that are for the service will be prefixed by this. For example, the case parameter for a search will be put in the page as s1.case, and the resulting argument in a search URL will be s1.case. When actions are deciding which parameters need to be sent in a request to a service, they can use the namespace information.
+
+If there are  two or more services combined on a page with a single submit button, they will use namespaces s1, s2, s3 etc as needed. The s  (service) parameter will end up with a list of services. For example, \gst{s=TextQuery,MusicQuery,} and the order of these determines the mapping order of the namespaces, i.e. s1 will map to TextQuery, s2 to MusicQuery.
+
+\begin{table}
+{\footnotesize
+\begin{tabular}{lll}
+\hline
+\bf Argument & \bf Meaning &\bf Typical values \\
+\hline
+a & action & a (applet), q (query), b (browse), p (page), pr (process) \\
+& & s (system)\\
+sa & subaction & home, about (page action)\\
+c & collection or  & demo, build \\
+& service cluster \\
+s & service name & TextQuery, ImportCollection \\
+rt & request type & d (display), r (request), s (status) \\
+ro & response only & 0 or 1 - if set to one, the request is carried out \\
+& & but no processing of the results is done \\
+& & currently only used in process actions \\
+o & output type & XML, HTML, WML \\
+l & language & en, fr, zh ...\\
+d & document id & HASHxxx \\
+r & resource id & ???\\
+pid & process handle & an integer identifying a particular process request \\
+\hline
+\end{tabular}}
+\caption{Generic arguments that can appear in a \gs\  URL}
+\label{tab:args}
+\end{table}
+
+\subsubsection{page format}\label{sec:page-format}
+
+The basic  page format  is:
+\begin{quote}\begin{gsc}\begin{verbatim}
+<page lang='en'>
+  <pageRequest/>
+  <pageResponse/>
+</page>
+\end{verbatim}\end{gsc}\end{quote}
+
+* show configuration and describe whats its used for
+
+There are two main elements in the page: pageRequest, pageResponse. The pageRequest is the original request that came into the Receptionist---this is included so that any parameters  can be preset to their previous values, for example, the query options on the query form. The pageResponse contains all the data that has been gathered from the system by the action. The other two elements contain extra information needed by XSLT. Config contains run-time variables such as the location of the gsdl home directory, the current site name, the name of the executable that is running (e.g. library)---these are needed to allow the XSLT to generate correct HTML URLs. Display contains some of the text strings needed in the interface---these are separate from the XSLT to allow for internationalization.
+
+The following subsections outline, for each action, what data is needed and what requests are generated to send to the system. 
+
+
+Once the XML page has been put together, the page to return to the user is created by transforming the XML using XSLT. The output is HTML at this stage, but it will be possible to generate alternative outputs, such as XML, WML etc. A set of XSLT files defines an 'interface'. Different users can change the look of their web pages by creating new XSLT files for a new 'interface'. Just as we have a sites directory where different sites 'live' (ie where their configuration file and collections are located), we have an interfaces directory where the different interfaces 'live' (ie their transforms and images are located there). The default XSLT files are
+located in interfaces/default/transforms. Collections, sites and other interfaces
+can override these files by having their own copy of the appropriate
+files. New interfaces have their own directory inside interfaces/. Sites and collections can have a transform directory containing XSLT files. The order in which the XSLT files are looked for is collection, site, current
+interface, default interface.\footnote{this currently breaks down for remote sites - need to rethink it a bit.}
+[TODO: describe a bit more?? currently only can get this locally]
+
+\subsubsection{Receptionists}\label{sec:recepts}
+
+The receptionist is the controlling module for the page generation part of \gs\ . It has the job of loading up all the actions, and it knows about the message router it and the actions are supposed to talk to. It routes messages received to the appropriate action (page-type messages) or directly to the message router (all other types). Receptionists also do other things, for example, adding to the page received back from the action any information that is common to all pages.
+
+There are different ways of providing an interface to \gs\ , from web based CGI style (using servlets) to Java GUI applications. These different interfaces require slightly different responses from a receptionist, so we provide several standard types of receptionist.
+
+Receptionist: This is the most basic receptionist. The page it returns consists of the original request, and the response from the action it was sent to. Methods preProcessRequest, and postProcessPage are called on the request and page, respectively, but in this basic receptionist, they don't do anything.
+
+TransformingReceptionist: This extends Receptionist, and overwrites postProcessPage to transform the page using XSLT. An XSLT is listed for each action in the receptionists configuration file, and this is used to transform the page. First, some display information, and configuration information is added to the page. Then it is transformed using the specified XSLT for the action, and returned.
+
+WebReceptionist: The WebReceptionist extends TransformingReceptionist. It doesn't do much else except some argument conversion. To keep the URLs short, parameters from the services are given shortnames, and these are used in the web pages. 
+
+DefaultReceptionist: This extends WebReceptionist, and is the default one for \gsiii\  servlets. Due to the page design, some extra information is needed for each page: some metadata about the current collection. The receptionist sends a describe request to the collection to get this, and appends it to the page before transformation using XSLT.
+
+NZDLReceptionist: (do we want to talk about this?) This is an example of a custom receptionist. For a look-alike nzdl.org system, even more information is needed for each page, namely the list of classifiers available from the ClassifierBrowse service. 
+
+By default, the LibraryServlet uses DefaultReceptionist. However, there is a servlet init-param called \gst{receptionist} which can be set to make the servlet use a different one.
+
+\subsubsection{Collection specific formatting}\label{sec:collformat}
+get format info, transform gsf->xsl. transform xml->html
+
+configuration params are passed in to the transformation
+\subsubsection{CGI arguments}
+
+
+\subsubsection{Page action}\label{sec:pageaction}
+
+PageAction is responsible for displaying kinds of information pages, such as the home page of the library, or the home page of a collection, or the help and preferences pages. These pages are not associated with specific services like the other page types. In general, the data comes from describe requests to various modules.
+The different pages are requested using the subaction argument. For the 'home' page, a 'describe' request is sent to the MessageRouter---this returns a list of all the collections, services, serviceClusters and sites known about. For each collection, its metadata is retrieved via a 'describe' request. This metadata is added into the previous result, which is then added into the page.    For the 'about' page, a \gst{describe} request is sent to the module that the about page is about: this may be a collection or a service cluster.  This returns a list of metadata
+and a list of services.
+
+To get an external html page embedded into a greenstone collection, i.e. a two frame page, with the top frame containing the collection header and navigation bar, and the second frame containg the external page, use subaction html.
+A url would look like
+a=p\&amp;sa=html\&amp;c=collname\&amp;url=externalurl
+
+\subsubsection{Query action}\label{sec:queryaction}
+
+The basic URL is \gst{a=q\&s=TextQuery\&c=demo\&rt=d/r}.
+There are three query services which have been implemented: TextQuery, FieldQuery, and AdvancedFieldQuery. These are all handled in the same way by query action.
+For each page, the service description is requested from the  service  of the current collection (via a describe request).  This is currently done every time the query page is
+displayed, but should be cached. The description includes a list of the parameters available for the query, such as case/stem, max num docs to return, etc. If the request type (rt) parameter is set to d for display, the action only needs to display the form, and this is the only request to the service. Otherwise, the submit button has been pressed, and a query request to the TextQuery service is sent. This has  all the parameters from the URL put into the parameter list. A list of document identifiers
+is returned. A followup query is sent to the MetadataRetrieve service of the collection: the content includes the list of
+documents, with a request for some of their metadata. Which metadata to retrieve is determined by looking through the XSLT that will be used to transform the page. The service description and query result are combined into a page of XML, which is returned to the Receptionist.
+
+\subsubsection{Applet action}\label{sec:appletaction}
+
+There are two types of request to the applet action: \gst{a=a \& rt=d\/} and
+\gst{a=a \& rt=r\/}.  The value \gst{rt=d\/} means ``display the applet.'' A
+\gst{describe} request is sent to the service, which returns the \gst{<applet>} HTML element.  The transformation file \gst{applet.xsl} embeds this
+into the page, and the servlet returns the HTML.
+
+The value \gst{rt=r} signals a request from the applet. A process request containing all the parameters is sent to the applet service. The result contains an appletData element, which contains a single  element - this element is returned
+directly to the applet, in XML. No transformation is done. 
+Because the AppletAction doesn't know or care anything about the applet data, it can work with any applet-service pair.
+
+Note that the applet HTML may need to know the name of the \gst{library}
+program.  However, that name is chosen by the person who installed the software
+and will not necessarily be ``library''.  To get around this, the applet can
+put a parameter called ``library'' into the applet data with a null value:
+\begin{quote}\begin{gsc}\begin{verbatim}
+<PARAM NAME='library' VALUE=''/>
+\end{verbatim}\end{gsc}\end{quote}
+When the AppletAction encounters this parameter it inserts the name of the
+current library servlet as its value.
+
+\subsubsection{Document action}\label{sec:documentaction}
+
+DocumentAction is responsible for displaying a document to the user. The display might involve some metadata and/or text for a document or part of a document. For hierarchical documents, a table of contents may be shown, while for paged documents (those with a single linear list of sections), next and previous page buttons may be shown. These different display types require different information about the document. Depending on the arguments, DocumentAction will send requests to several services: DocumentMetadataRetrieve, DocumentStructureRetrieve and DocumentContentRetrieve.
+
+A basic display, for example, Title and text, involves a metadata request to get the Title, and a content request to get the text. Hierarchical table of contents display requires a structure request. If the entire contents is to be displayed, the parameter \gst{structure=entire} would be sent in the request. Otherwise, parameters \gst{structure=ancestors}, \gst{structure=children} and possibly \gst{structure=siblings} may be used, depending in the position of the current node in the document. These return a hierarchical structure of nodes, containing ancestor nodes, child nodes and sibling nodes, respectively.
+For paged display, the structure is not actually needed. A structure request is still sent, but this time it requests some information, rather the structure itself. The information requested includes the number of siblings and the current position of the current node, or the number of children (if the current node is the root of the document).
+
+Metadata may be requested for the current node, or for any nodes in the structure, and content also. The metadata and content are added into the appropriate nodes in the structure hierarchy, and this is returned as the page data.
+
+\subsubsection{XML Document action}\label{sec:xmldocumentaction}
+
+XMLDocumentAction is a little different to the standard DocumentAction. It operates in two modes, \gst{text} and \gst{toc}. In \gst{text} mode, it will retrieve the content of the current document node using a DocumentContentRetrieve request. In \gst{toc} mode, it retrieves the entire table of contents for the document using a DocumentStructureRetrieve request. Either mode may also retrieve metadata for the current section or each section in the table of contents.
+
+\subsubsection{GS2Browse action}\label{sec:browseaction}
+
+GS2BrowseAction is for displaying \gsii\  style classifiers. 
+\subsubsection{System action}\label{sec:systemaction}
+
+SystemAction allows for manual reconfiguration of various components at run-time. There is no interactive web-page displaying the options, it merely turns a set of CGI arguments into an XML system request. The response from a system request is a message which is displayed to the user.
+
+\begin{table}
+\caption{Configure CGI arguments}
+\label{tab:system-cgi}
+{\footnotesize
+\begin{tabular}{ll}
+\hline
+\bf arg & \bf description\\
+\hline
+a=s & system action\\
+sa=c$|$a$|$d & type of system request: c (configure), a (add/activate), \\
+& d (delete/deactivate) \\
+c=demo &  the request will go to this collection/servicecluster \\
+& instead of the message router\\
+ss=collectionList & subset for configure: only reconfigure this part.\\
+&  For the MessageRouter,  can be serviceClusterList, serviceList, \\
+& collectionList, siteList.\\
+&  For a collection/cluster, can be metadataList or serviceList.\\
+sn=demo & \\
+st=collection& \\
+\hline
+\end{tabular}}
+\end{table}
+
+
+\subsection{Other code information}
+
+Greenstone has a set of Utility classes, which are briefly described in Table~\ref{tab:utils}.
+
+\begin{table}[h]
+\caption{The utility classes in org.greenstone.gsdl3.util}
+\label{tab:utils}
+{\footnotesize
+\begin{tabular}{lp{3.75in}}
+\hline
+\bf Utility class & \bf Description\\
+\hline
+CollectionClassLoader & ClassLoader that knows about a collection's resource directory \\
+DBInfo & Class to hold info from GDBM database entry \\
+Dictionary & wrapper around a Resource Bundle, providing strings with parameters\\
+GDBMWrapper & Wrapper for GDBM database. Uses JavaGDBM\\
+GSConstants & holds some constants used for servlet arguments and configuration variables\\
+GSEntityResolver & an EntityResolver which can be used to find resources such as DTDs\\
+GSFile & class to create all \gs\  file paths e.g. used to locate configuration files, XSLT files and collection data. \\
+GSHTML & provides convenience methods for dealing with HTML, e.g. making strings HTML safe\\
+GSParams & contains names and default values for interface parameters\\
+NZDLParams & a subclass of GSParams which holds default service parameters too, necessary for the classic style interface.\\
+GSPath & used to create, examine and modify message address paths\\
+GSStatus & some static codes for status messages\\ 
+GSXML & lots of methods for extracting information out of \gs\  XML, and creating some common types of elements. Also has static Strings for element and attribute names used by \gs\ .\\
+GSXSLT & some manipulation functions for \gs\  XSLT\\
+GlobalProperties & Holds the global properties (from global.properties) \\
+MacroResolver & Used with replace elements in collection configuration files, replaces a macro or string with another string, metadata or text from a dictionary\\
+GS2MacroResolver & MacroResolver for GS2 collections, that uses the GDBM database\\
+Misc & miscellaneous functions\\
+MyNodeList & A simple implementation of an XML NodeList\\
+OID & class to handle \gs\  (2) OIDs\\
+Processing & Runs an external process and prints the output from the process \\
+SQLQuery & contains a connection to a SQL database, along with some methods for accessing the data, such as converting MG numbers to and from Greenstone OIDs.\\
+XMLConverter & provides methods to create new Documents, parse Strings or Files into Documents, and convert Nodes to Strings\\
+XMLTransformer & methods to transform XML using XSLT \\
+XSLTUtil & contains static methods to be called from within XSLT \\
+\hline
+\end{tabular}}
+\end{table}
+
+
+\newpage
+\section{Developing \gsiii\ : Adding new features}\label{sec:new-features}
+
+[TODO: finish this section ]
+
+\subsection{Creating new services}\label{sec:new-services}
+
+*inherit from ServiceRack - abstract base class. this handles the main process method, determines the service name and request type. if request type is describe, and to is empty, it returns a list of services (short\_service\_info) which is initialized in the configure method. a describe request to a particular service results in getServiceDescription being called, which must be supplied by the subclass.
+other request types (process) get sent to processXXX methods, where XXX is the service name.
+
+* what methods are expected
+
+*service type responses expected
+
+*a browse type service must also implement servicenameMetadataRetrieve service.
+
+* should a metadata retrieval service advertise what metadata is available??
+
+standard service type vs new service type - standard needs some xml response syntax.
+
+\subsection{creating new actions/pages}\label{sec:new-pages}
+
+\subsection{new interfaces}\label{sec:new-interfaces}
+
+It is easy to create new interfaces to \gsiii. Here we are talking about interfaces other than those to display in typical browser.
+
+Handheld devices: Use the standard servlet setup, but with a different set of XSLT files to format the pages for small screens, or use WML.
+
+Java GUI Interface: There are couple of alternatives. Depending on what you want to display in the GUI, you could talk to either a Receptionist or a MessageRouter. The library classes can be set up and compiled into the GUI program.
+Talking to a Receptionist will give you access to pages of XML. It is likely that the standard Receptionist class would be used - this doesn't transform the data to HTML. Queries such as ``give me the home page of a collection'' and ``do the following search'' can be issued. All the data needed for the result view is returned. Queries are quite simple, but are limited to what kinds of Actions are available in the library. 
+Talking to a MessageRouter requires a bit more effort on the part of the GUI program, but results in greater flexibility. The kinds of queries that can be issued are individual units of action, such as ``describe yourself'', ``search'', ``retrieve the content for this document''. More than one request may need to be made for a particular feature of the GUI. However you can ask for any combination of data available in the system, you are not relying on Actions. What you will implement though, may be a lot like the Action code in terms of request sequences.
+
+Interfaces in other programming languages: Because the communication is all XML based, other interfaces can talk to the Java library if a communication protocol is set up. This could be done using SOAP for example. Like for Java GUI interfaces, the program could talk to a Receptionist or to a MessageRouter. 
+e.g. Java interface. where you can interface to. MR vs Receptionist. different receptionists. e.g., handheld - using servlet, transforming recpt, but new set of XSLT Java program other program - talk to recpt but just get back XML data for pages. Java gui - just talk to MR, do all processing itself.
+
+Remote interfaces: remote interfaces can be set up in the same way as above, using a communication protocol between the interface, and the library program.
+
+
+\subsection{New types of collections}\label{sec:new-coll-types}
+
+The standard type of collection is built with the \gsii\ Perl collection building system. There are many options to this, but it is conceivable that these options don't meet the needs of all collection builders. \gsiii\  has an ability to use any type of collection you can come up with, assuming some Java code is provided. 
+
+There are four levels of customization that may be needed with new collections: service, collection, interface XSLT, and action levels. We will use the example collections that come with \gs\  to describe these different levels.
+
+Firstly, new service classes need to be written to provide the functionality to search/browse/whatever the collection. If the services have similar interfaces and functionality to the standard services, this may be all that is needed. For example, MGPP collections were the first to be served in \gsiii\ . When we came to do MG collections, all we had to do was write some new service classes that interacted with MG instead of MGPP. Because these collections used the same type of services, this was all we had to do. The format of the configuration files was similar, they just specified MG serviceRack classes rather than MGPP ones.
+
+The XML Sample Texts (gberg) collection, however, was done quite differently to the standard collections. New services were provided to search the database (built with Lucene) and to provide the documents and parts of documents (using XSLT to transform the raw XML files). The collectionConfig file had some extra information in it: a list of the documents in the collection along with their Titles. Because the standard collection class has no notion of document lists, a new class was created (org.greenstone.gsdl3.collection.XMLCollection). This class is basically the same as a standard collection class except that it looks for and stores in memory the documentList from the collectionConfig file.
+
+To tell \gs\  to load up a different type of collection class, we use another configuration file: \gst{etc/collectionInit.xml}. This specifies the name of the collection class to use.
+Currently, this is all that is specified in that file, but you may want to add parameters for the class etc.
+
+\gst{<collectionInit class="XMLCollection"/>}
+
+The display for the collection is also quite different. The home page for the collection  displays the list of documents. To achieve this, the describe response from the collection had to include the list, and a new XSLT was written for the collection that displayed this. Collection XSLT should be put in the transform directory of the collection\footnote{These are currently only used when running \gs\  in a non-distributed fashion, but it will be added in properly at some stage}.
+
+Document display is  significantly different to standard \gs\ . There are two modes of display: table of contents mode, and content mode. Clicking on a document link from the collection home page takes the user to the table of contents for the collection. Clicking on one of the sections in the table of contents takes them to a display of that section. To facilitate this, not only do we need new XSLT files , we also needed a new action. XMLDocumentAction was created, that used two subactions, toc and text, for the different modes of display.
+
+The Receptionist was told about this new action by the addition of the following element to the interfaceConfig.xml file: 
+
+\begin{gsc}\begin{verbatim}
+<action name='xd' class='XMLDocumentAction'>
+  <subaction name='toc' xslt='document-toc.xsl'/>
+  <subaction name='text' xslt='document-content.xsl'/>
+</action>
+\end{verbatim}\end{gsc}
+
+XSLT files are linked to subactions rather than the action as a whole. The collection supplies the two XSLT files written appropriately for the data it contains.
+
+All links that link to the documents have to be changed to use the xd action rather than the standard d action. These include the links from the home page, and the links from query results.
+
+Querying of the collection is almost the same as usual. The query service provides a list of parameters, does the query and then sends back a list of document identifiers. The standard query action was fine for this collection. The change occurs in the way that the results are displayed---this is accomplished using a format statement supplied in the collectionConfig file inside the search node.
+
+\begin{gsc}\begin{verbatim}
+<search>
+  <format>
+    <gsf:template match="documentNode">
+      <xsl:param name="collName"/>
+      <xsl:param name="serviceName"/>
+      <td>
+        <b><a href="{$library_name}?a=xd&amp;sa=text&amp;c={$collName}&
+            amp;d={@nodeID}&amp;p.a=q&amp;p.s={$serviceName}">
+             <xsl:choose>
+               <xsl:when test="metadataList/metadata[@name='Title']">
+                 <gsf:metadata name="Title"/>
+               </xsl:when>
+               <xsl:otherwise>(section)</xsl:otherwise>
+             </xsl:choose>
+           </a>
+         </b> from <b><a href="{$library_name}?a=xd&amp;sa=toc&amp;
+           c={$collName}&amp;d={@nodeID}.rt&amp;p.a=q&amp;p.s={$serviceName}">
+         <gsf:metadata name="Title" select="root"/></a></b>
+      </td>
+    </gsf:template>
+  </format>
+</search>
+\end{verbatim}\end{gsc}
+
+Instead of displaying an icon and the Title, it displays the Title of the section and the title of the document. Both of these are linked to the document: the section title to the content of that section, the document title to the table of contents for the document. Because these require non-standard arguments to the library, these parts of the template are written in XSLT not \gs\  format language. As is shown here it is perfectly feasible to write a format statement that includes XSLT mixed in with \gs\  format elements.
+
+The document display uses CSS to format the output---these are kept in the collection and specified in the collections XSLT files. The documents also specify DTD files. Due to the way we read in the XML files, Tomcat sometimes has trouble locating the DTDs. One option is to make all the links absolute links to files in the collection folder, the other option is to put them in \gs\ 's DTD folder \gst{\$GSDL3SRCHOME/resources/dtd}. 
+
+\subsection{The Classic Interface}
+
+The library seen at \gst{http://www.greenstone.org/greenstone3/nzdl} is like a mirror to \gst{http://www.nzdl.org}---it aims to present the same collections, in the same way but using \gsiii\  instead of \gsii\ . It uses a new site (nzdl) with a new interface (nzdl) which is based on the classic interface. The web.xml file had a new servlet entry in it to specify the combination of nzdl site and nzdl interface.
+
+The site was created by making a directory called nzdl in the sites folder. A siteConfig file was created. Because it is running on Linux, we were able to link to all the collections in the old \gs\  installation. The convert\_coll\_from\_gs2.pl script was run over all the collections to produce the new XML configuration files.
+
+The classic interface was created to be used by this site (and is now a standard part of Greenstone).
+In many cases, creating a new interface just requires the new images and XSLT  to be added to the new directory(see Sections~\ref{sec:sites-and-ints} and \ref{sec:interface-customise}). This classic interface required a bit more customization.
+
+The standard \gsiii\  navigation bar lists all the services available for the collection. In \gsii\ , the navigation bar provides the search option, and the different classifiers. This is not service specific, but hard coded to the search and classifiers. The XSLT that produces the navigation bar needed to be altered to produce this. But also, a new Receptionist was needed. 
+The standard receptionist (DefaultReceptionist) gathers a little bit of extra information for each page of XML before transforming it: this is the list of services for the collection and their display information, allowing the services to be listed along the navigation bar. This is information that is needed by every page (except for the library home page) and therefore is obtained by the receptionist instead of by each action. The nzdl interface needed a bit more information than this: for the ClassifierBrowse service, if there was one, the list of classifiers and their display elements must be obtained. So a new Receptionist (NZDLReceptionist) was written that inherited from DefaultReceptionist, and added this new info into the page.
+
+One of the servlet initialization parameters is the receptionist class: this was added to the servlet definition in the web.xml file so that the LibraryServlet would load up the right receptionist class.
+
+
+\newpage
+\section{Distributed \gs\ }\label{sec:distributed}
+
+\gs\  is designed to run in a distributed fashion. One \gs\  installation can talk to several sites on different computers. This requires some sort of communication protocol. Any protocol can be used, currently we have a simple SOAP protocol.
+
+more explanation..
+
+\begin{figure}[h]
+  \centering
+  \includegraphics[width=4in]{remote} %5.8
+  \caption{A distributed digital library configuration running over several servers}
+  \label{fig:remote}
+\end{figure}
+
+We have used Apache Axis SOAP implementation. This is run as a servlet in Tomcat. Axis is set up during installation of Greenstone. For more details about SOAP in Greenstone, see Appendix~\ref{app:soap}. Debugging soap is described in Appendix~\ref{app:soap-debug}.
+
+\subsection{Serving a site using soap}
+
+A web service for localsite comes with \gs. However, it is not deployed by default. To deploy it, run run \gst{ant deploy-localsite}. If you want to set up web services for other sites, run \gst{ant soap-deploy-site}. This will prompt you for the sitename (its directory name), and a siteuri - a unique identifier for the web service. Tomcat needs to be running for this to work, and you need to have installed the \gs source code.
+
+The ant target deploys the service for the site specified. A resource file (\gst{<sitename>.wsdd}) is created which is used to specify the service. It can be found in \gst{\$GSDL3HOME/resources/soap}, and is generated from \gst{site.wsdd.template}.
+
+The address of the new SOAP service will be tomcatserver-address/greenstone3/services/sitename, for example, www.greenstone.org/greenstone3/services/localsite.
+
+\subsection{Connecting to a site web service}
+
+There are two ways to use a remote site. First, if you have a local site running, then the site can also connect to other remote sites. In the siteConfig.xml file, you need to add a site element into the siteList element.
+
+For example, to get siteA to talk to siteB, you need to deploy a SOAP server on siteB, then add a \gst{<site>} element to the \gst{<siteList>} of siteA's \gst{siteConfig.xml} file (in \gst{\$GSDL3HOME/sites/siteA/siteConfig.xml}).
+
+In the \gst{<siteList>} element, add the following (substituting the chosen site uri for siteBuri):
+
+\begin{gsc}\begin{verbatim}
+<site name="siteBuri"
+  address="http://localhost:8080/greenstone3/services/siteBuri"
+  type="soap"/>
+\end{verbatim}\end{gsc}
+
+(Note that localhost and 8080 should be changed to the values you entered when installing \gsiii. Localhost will only work for servers on the smae machine.).
+
+If you have changed the siteConfig.xml file for a site that is running, it will need to be reconfigured. Either restart Tomcat, or reconfigure through a URL:
+e.g. \gst{http://localhost:8080/greenstone3/library?a=s\&sa=c}.
+Several sites can be connected to in this manner.
+
+The second option is if you have a receptionist set up on a machine where you have no site, and you only want to connect to a single remote site. Instead of using site\_name in the servlet initialisation parameters (in \$GSDL3HOME/WEB-INF/web.xml), you can specify remote\_site\_name, remote\_site\_type and remote\_site\_address. A communicator object will be set up instead of a MessageRouter and the receptionist will talk to the communicator.
+
+\appendix
+
+\newpage
+\section{Using \gsiii\  from CVS}\label{app:cvs}
+
+\gsiii\  is also available via CVS. You can download the latest version of the code. This is not guaranteed to be stable, in fact it is likely to be unstable. The advantage of using CVS is that you can update the code and get the latest fixes. 
+
+Note that you will need the Java 2 SDK, version 1.4.0 or higher, and Ant (Apache's Java based build tool, http://ant.apache.org) installed.
+
+To check out the \gs\  code, use:
+
+\begin{quote}\begin{gsc}\begin{verbatim}
+cvs -d :pserver:cvs\_anon@cvs.scms.waikato.ac.nz:2402/usr/local/
+           global-cvs/gsdl-src co -P greenstone3
+\end{verbatim}\end{gsc}\end{quote}
+
+If you need it, the password for anonymous CVS access is \gst{anonymous}. Note that some older versions of CVS have trouble accessing this repository due to the port number being present. We are using version 1.11.1p1. 
+
+Greenstone is built and installed using Ant (Apache's Java based build tool, 
+http://ant.apache.org). You will need a Java Development 
+Environment (1.4 or higher), and Ant installed to use Greenstone. You can download Ant from \\\gst{http://ant.apache.org/bindownload.cgi}. Make sure that the environment variables JAVA\_HOME and ANT\_HOME are set.
+
+In the \gst{greenstone3} directory, you can run \gst{'ant'} which will give you a help message.
+Running \gst{'ant -projecthelp'} gives a list of the targets that you can run --- these
+do various things like compile the source code, startup the server etc.
+
+The \gst{README.txt} file has up-to-date instructions for installing from CVS. Briefly, for a first time install, run \gst{'ant prepare install'}.
+
+The file \gst{build.properties} contains various parameters that can be set by the user. Please check these settings before running the installation process. The install process will ask you if you accept the properties before starting.
+For a  non-interactive version of the install, run
+\gst{'ant -Dproperties.accepted=yes install'}
+
+To log the output in build.log, run
+\gst{'ant -Dproperties.accepted=yes -logfile build.log install'}
+
+Compilation includes Java and C/C++. On Windows, you will need to have Visual Studio or equivalent installed. Please check the \gst{compile.windows.c++.setup} property in build.properties --- make sure it is set to the setup script of Visual Studio.
+
+Note: \gst{gs3-setup} sets the environment variables \gst{GSDL3HOME, GSDL3SRCHOME, CLASSPATH, PATH, JAVA\_HOME} and needs to be done in a shell before doing collection building etc. 
+
+To run the library, use the \gst{gs3-server.sh/bat} shell scripts.
+
+\newpage
+\section{Tomcat}\label{app:tomcat}
+
+Tomcat is a servlet container, and \gsiii\  runs as a servlet inside it. 
+
+The file \gst{\$GSDL3SRCHOME/packages/tomcat/conf/server.xml} is the Tomcat configuration file. A context for \gsiii\  is given by the file\\ \gst{\$GSDL3SRCHOME/packages/tomcat/conf/Catalina/localhost/greenstone3.xml}. This tells Tomcat where to find the web.xml file, and what URL (\gst{/greenstone3}) to give it. Anything inside the context directory is accessible via Tomcat\footnote{can we use .htaccess files to restrict access??}. For example, the index.html file that lives in \gst{\$GSDL3HOME} can be accessed through the URL \gst{localhost:8080/greenstone3/index.html}. The gs2mgdemo collection's images can be accessed through \\
+\gst{localhost:8080/greenstone3/sites/localsite/collect/gs2mgdemo/images/}.
+
+
+Greenstone sets up Tomcat to run on port 8080 by default. To change this, you can edit the tomcat.port property in build.properties. If you do this before installing Greenstone, then running 'ant install' will use the new port number. If you want to change it later on, shutdown tomcat, run 'ant configure', then when you restart tomcat it will use the new port.
+
+Note: Tomcat must be shutdown and restarted any time you make changes in the following for those changes to take effect:
+\begin{bulletedlist}
+\begin{gsc}
+\item \$GSDL3HOME/WEB-INF/web.xml
+\item \$GSDL3SRCHOME/packages/tomcat/conf/server.xml
+\end{gsc}
+\item any classes or jar files used by the servlets
+\end{bulletedlist}
+
+On startup, the servlet loads in its collections and services. If the site or collection configuration files are changed, these changes will not take effect until the site/collection is reloaded. This can be done through the reconfiguration messages (see Section~\ref{sec:runtime-config}), or by restarting Tomcat.
+
+We have disabled following symlinks for the greenstone servlet. To enable it, edit \gst{\$GSDL3SRCHOME/packages/tomcat/conf/Catalina/localhost/greenstone3.xml} and set 'allowLinking' to true. 
+
+By default, Tomcat allows directory listings. To disable this, change the 'listings' parameter to false in the default servlet definition, in Tomcat's web.xml file (\gst{\$GSDL3SRCHOME/packages/tomcat/conf/web.xml}):
+
+We have set the greenstone context to be reloadable. This means that if a class or resource file in web/WEB-INF/lib or web/WEB-INF/classes changes, the servlet will be reloaded. This is useful for development, but should be turned off for production mode (set the 'reloadable' attribute to false).
+
+Tomcat uses a Manager to handle HTTP session information. This may be stored between restarts if possible. To use a persistent session handling manager, uncomment the \gst{<Manager>} element in \\
+\gst{\$GSDL3SRCHOME/packages/tomcat/conf/server.xml}. For the default manager, session information is stored in the work directory:\\
+\gst{\$GSDL3SRCHOME/packages/tomcat/work/Catalina/localhost/greenstone3/SESSIONS.ser}. Delete this file to clear the cached session info. Note that Tomcat needs to be shutdown to delete this file.
+
+\subsection{Proxying Tomcat with apache}
+
+Instead of incorporating servlet support into your existing web server, an easy alternative is to proxy Tomcat. The \gst{http://www.greenstone.org/greenstone3} site uses apache to proxy Tomcat. ProxyPass and ProxyPassReverse directives need to be added to the Virtualhost description for the www.greenstone.org server.
+
+\begin{quote}\begin{gsc}
+<VirtualHost xx.xx.xx.xx>\\
+ServerName www.greenstone.org\\
+...\\
+ProxyPass /greenstone3 http://puka.cs.waikato.ac.nz:8080/greenstone3\\
+ProxyPassReverse /greenstone3 http://puka.cs.waikato.ac.nz:8080/greenstone3\\
+</VirtualHost>\\
+\end{gsc}\end{quote}
+
+In our example, the \gsiii\  servlet can be accessed at \\
+\gst{http://www.greenstone.org/greenstone3/library}, instead of at \\
+\gst{http://puka.cs.waikato.ac.nz:8080/greenstone3/library}, which is not publically accessible.
+
+\subsection{Running Tomcat behind a proxy}
+
+Almost everything works fine when Tomcat is running behind a proxy. The only time this causes trouble is if the servlet itself needs to make external HTTP connections. We do this in the infomine demo collection for example. One of the service classes sends HTTP requests to the infomine database at riverside. Since this is going through the proxy, a username and password is needed. It is not sufficient to prompt the user for a password because they are unlikely to have a password for the particular proxy that Tomcat is using. What we have done at present is to put a proxy element in the siteConfig.xml file. Here you have to enter a suitable username and password for the proxy server. Unfortunately these are entered in plain text. And the file is viewable via the servlet. So we need a better solution.
+
+\newpage
+\section{SOAP}\label{app:soap}
+
+Greenstone uses the Apache Axis SOAP implementation for distributed communications. Axis runs as a servlet inside Tomcat, and SOAP web services can be deployed by this Axis servlet. The Greenstone installation process sets up Axis for Tomcat, but does not deploy any services. 
+
+To deploy the SOAP service for localsite, run \gst{ant deploy-localsite}.
+
+To deploy a SOAP service for other sites, run \gst{ant soap-deploy-site}
+
+This will prompt you for the sitename (the site's directory name), and a unique URI for the site. It creates a new SOAPServer class for the site \\(\gst{\$GSDL3SRCHOME/src/java/org/greenstone/gsdl3/SOAPServer<sitename>.java}), creates a resource file for deployment (\gst{\$GSDL3SRCHOME/resources/soap/<sitename>.wsdd}), and then tries to deploy the service.
+
+Information about deployed services is maintained between Tomcat sessions---you only need to deploy something once. To undeploy a site, use \gst{ant undeploy-soap-site}.
+
+The axis services can be accessed at \gst{localhost:8080/greenstone3/index.jsp}.
+
+\subsection{Debugging SOAP}\label{app:soap-debug}
+
+If you need to debug the SOAP stuff for some reason, or just want to look at the SOAP messages that are being passed back and forth, you can use the TCP monitor. This intercepts messages coming in to one port, displays them, and passes them to another port.
+To run it, type:
+
+\begin{quote}\gst{java -cp \$GSDL3HOME/WEB-INF/lib/axis.jar \\
+org.apache.axis.utils.tcpmon}
+\end{quote}
+
+The listen port is the port that you want the monitor to be listening on. It should 'act as' a Listener, with target hostname 127.0.0.1 (localhost), and target port the port that Tomcat is running on (8080). You need to modify the address used to talk to the SOAP service. For example, if you want to monitor traffic between the gateway site and the localsite SOAP server, you will need to edit gateway's siteConfig.xml file and change the port number (in the site element) to whatever you have chosen as the listen port.
+
+For example, in the Admin panel of TCPMonitor the Target Hostname might be 127.0.0.1, and the Target Port \# 8080. Set the Listen Port \# to be a different port, such as 8070 and click Add. This produces a new tab panel where you can see the messages arriving at port 8070 before being forwarded to port 8080. You then need to set your test request from your SOAP application to arrive at port 8070 and you will see copies of the messages in the new tab panel.
+
+
+\newpage
+\section{Tidying up the formatting for imported \gsii\  collections}\label{app:gs2tidy}
+
+\subsection{Format statements: \gsii\  vs \gsiii\ }\label{app:gs2format}
+The following table shows the \gsii\  format elements, and their equivalents in \gsiii\ 
+\begin{table}[h]
+\caption{\gsiii\  equivalents of \gsii\  format statements}
+{\footnotesize
+\begin{tabular}{ll}
+\hline
+\bf \gsii\         & \bf \gsiii\  \\
+\hline
+\gst{[Text]} & \gst{<gsf:text/>} \\
+\gst{[num]} & \gst{<gsf:metadata name='docnum'/>}\\
+\gst{[link][/link]} & \gst{<gsf:link></gsf:link>} or \\
+& \gst{<gsf:link type='document'></gsf:link>}\\
+\gst{[srclink][/srclink]} & \gst{<gsf:link type='source'></gsf:link>}\\
+\gst{[icon]} & \gst{<gsf:icon/>} or \\
+& \gst{<gsf:icon type='document'/>}\\
+\gst{[srcicon]} & \gst{<gsf:icon type='source'/>}\\
+\gst{[Title]} (metadata) & \gst{<gsf:metadata name='Title'/>} or \\
+& \gst{<gsf:metadata name='Title' select='current'/>}\\
+\gst{[parent:Title]} & \gst{<gsf:metadata name='Title' select='parent' />}\\
+\gst{[parent(All):Title]} & \gst{<gsf:metadata name='Title' select='ancestors'/>}\\
+\gst{[parent(Top):Title]} & \gst{<gsf:metadata name='Title' select='root' />}\\
+\gst{[parent(All': '):Title]} & \gst{<gsf:metadata name='Title' select='ancestors'}\\ 
+& \gst{  separator=': ' />}\\
+\gst{[sibling(All': '):Title]} & \gst{<gsf:metadata name='Title' multiple='true'} \\
+& \gst{  separator=': ' />}\\
+\gst{\{Or\}\{[dc.Title],}  & \gst{<gsf:choose-metadata>}\\
+\gst{  [dls.Title], [Title]\}}& \gst{  <gsf:metadata name='dc.Title'/>}\\
+& \gst{  <gsf:metadata name='dls.Title'/>}\\
+& \gst{  <gsf:metadata name='Title'/>}\\
+& \gst{</gsf:choose-metadata>}\\
+\gst{\{If\}\{[parent:Title],} & \gst{<gsf:choose-metadata>}\\
+\gst{  [parent:Title], [Title]\}}& \gst{  <gsf:metadata name='Title' select='parent'/>}\\
+& \gst{  <gsf:metadata name='Title'/>}\\
+& \gst{</gsf:choose-metadata>}\\
+\gst{\{If\}\{[Subject],} & \gst{<gsf:switch>}\\
+\gst{  <td>[Subject]</td>\}}& \gst{  <gsf:metadata name='Subject'/>}\\
+& \gst{  <gsf:when test='exists'>} \\
+& \gst{     <td><gsf:metadata name='Subject'/></td>}\\
+& \gst{  </gsf:when></gsf:switch>}\\
+\hline
+\end{tabular}}
+\end{table}
+\subsection{Cleaning up macros}\label{app:gs2replace}
+
+Here we show some of the replace items that have been used for \gsii\  collections.
+
+Getting rid of silly backslashes:
+\begin{gsc}\begin{verbatim}
+<replace scope='text' macro="\\?\\\(" text="\("/>
+\end{verbatim}\end{gsc}
+
+Macro resolving using resource bundles and metadata:
+\begin{gsc}\begin{verbatim}
+<replace scope='metadata' macro="_magazines_" bundle="NZDLMacros" 
+   key="Magazines"/>
+<replace scope='all' macro='_thisOID_' metadata='archivedir'/>
+<replace macro="_httpcollimg_" 
+   text="sites/localsite/collect/folktale/index/assoc"/>
+\end{verbatim}\end{gsc}
+
+Fixing up broken external links:
+\begin{gsc}\begin{verbatim}
+<replace macro="_httpextlink_&amp;rl=1&amp;href=" 
+   text="?a=d&amp;c=folktale&amp;s0.ext=1&amp;d="/>
+<replace macro="_httpextlink_&amp;rl=0&amp;href=" 
+   text="?a=p&amp;sa=html&amp;c=folktale&amp;url="/>
+\end{verbatim}\end{gsc}
+
+These two examples show how to deal with \gsii's external link macros. The first one is for a 'relative' external link. In this case, the links are like URL's but they actually refer to Greenstone internal documents. So the \gsiii\  link is to the document, but with parameter s0.ext signifying that the d argument will need translating before retrieving the content.
+The second example is a truly external link. This is translated into a HTML type page action, where the URL is presented as a frame along with the collection header in a separate frame.
+
+Sometimes we need to add in macros to be resolved in a second step:
+\begin{gsc}\begin{verbatim}
+<replace macro="_iconpdf_" scope="metadata" 
+   text="&lt;img title='_texticonpdf_' src='interfaces/default/images/ipdf.gif'/&gt;"/>
+<replace macro="_texticonpdf_" scope="metadata" bundle="interface_classic" 
+   key="texticonpdf"/>
+\end{verbatim}\end{gsc}
+
+\end{document}
Index: /tags/greenstone-3_02-distribution/gsdl3/gs3-admin.sh
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/gs3-admin.sh	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/gs3-admin.sh	(revision 13928)
@@ -0,0 +1,63 @@
+#!/bin/sh
+gailang=en
+
+echo
+    echo "Greenstone Administrator Interface (GAI)"
+    echo "Copyright (C) 2005, New Zealand Digital Library Project, University Of Waikato"
+    echo "GAI comes with ABSOLUTELY NO WARRANTY; for details see LICENSE.txt"
+    echo "This is free software, and you are welcome to redistribute it"
+echo
+
+##  -------- Run the Greenstone Administrator Interface --------
+
+# This script must be run from within the directory in which it lives
+thisdir=`pwd`
+if [ ! -f "${thisdir}/gs3-admin.sh" ]; then
+    if [ "$gailang" == "es" ]; then
+        echo "Este guión deberá ejecutarse desde el directorio en el que reside."
+    elif [ "$gailang" == "fr" ]; then
+	echo "Ce script doit être exécuté à partir du répertoire dans lequel il se trouve."
+    elif [ "$gailang" == "ru" ]; then
+	echo "üÔÏÔ ÓËÒÉÐÔ ÄÏÌÖÅÎ ÂÙÔØ ×ÚÑÔ ÉÚ ÄÉÒÅËÔÏÒÉÉ, × ËÏÔÏÒÏÊ ÏÎ ÒÁÓÐÏÌÏÖÅÎ"
+    else
+	echo "This script must be run from the directory in which it resides."
+    fi
+    exit 1
+fi
+
+
+##  ---- Determine GSDL3HOME ----
+gsdl3path=
+
+# Some users may set the above line manually
+if [ "$gsdl3path" == "" ]; then
+    # Check the environment variable first
+    if [ "$GSDL3SRCHOME" != "" ]; then
+	gsdl3path=$GSDL3SRCHOME
+
+    # If it is not set, assume that the GAI is installed as a subdirectory of Greenstone
+    else
+#	pushd .. > /dev/null
+	gsdl3path=`pwd`
+#	popd > /dev/null
+    fi
+fi
+
+# Setup Greenstone3, unless it has already been done
+if [ "$GSDL3HOME" == "" ]; then
+    pushd $gsdl3path > /dev/null
+    source gs3-setup.sh
+    popd > /dev/null
+fi
+
+# Other arguments you can provide to GLI to work around memory limitations, or debug
+# -Xms<number>M    To set minimum memory (by default 32MB)
+# -Xmx<number>M    To set maximum memory (by default the nearest 2^n to the total remaining physical memory)
+# -verbose:gc      To set garbage collection messages
+# -Xincgc          For incremental garbage collection (significantly slows performance)
+# -Xprof           Function call profiling
+# -Xloggc:<file>   Write garbage collection log
+
+# $javapath -classpath classes/:GLI.jar:lib/apache.jar:lib/qfslib.jar:lib/mail.jar:lib/activation.jar org.greenstone.gatherer.GathererProg -gsdl $GSDLHOME -wget $wgetpath $*
+
+java -cp $CLASSPATH org.greenstone.admin.GAI $GSDL3SRCHOME $GSDL3HOME
Index: /tags/greenstone-3_02-distribution/gsdl3/gs3-server.bat
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/gs3-server.bat	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/gs3-server.bat	(revision 13928)
@@ -0,0 +1,132 @@
+@echo off
+set SERVERLANG=en
+
+:: -------- Run the Greenstone 3 Server --------
+
+:: This script must be run from within the directory in which it lives
+if exist gs3-server.bat goto start
+    if "%SERVERLANG%" == "en" echo This script must be run from the directory in which it resides.
+    if "%SERVERLANG%" == "es" echo Este guiÂ¢n deberÂ  ejecutarse desde el directorio en el que reside.
+    if "%SERVERLANG%" == "fr" echo Ce script doit Ëtre exâcutâ âŠ partir du râpertoire dans lequel il se trouve.
+    if "%SERVERLANG%" == "ru" echo ÂÃ¢Â®Ã¢ Ã¡ÂªÃ ÂšÂ¯Ã¢ Â€Â®Â«ÂŠÂ¥Â­ Â¡Ã«Ã¢Ã¬ Â¢Â§Ã¯Ã¢ ÂšÂ§ Â€ÂšÃ Â¥ÂªÃ¢Â®Ã ÂšÂš, Â¢ ÂªÂ®Ã¢Â®Ã Â®Â© Â®Â­ Ã Â Ã¡Â¯Â®Â«Â®ÂŠÂ¥Â­
+    goto exit
+
+:start
+if "%OS%" == "Windows_NT" goto findGSDL
+    :: Invoke a new command processor to ensure there's enough environment space
+    if "%1" == "Second" goto findGSDL
+        command /E:2048 /C %0 Second %1 %2 %3 %4 %5 %6 %7 %8 %9
+        goto done
+
+:findGSDL
+echo.
+if "%SERVERLANG%" == "en" echo Greenstone3 Server
+if "%SERVERLANG%" == "en" echo Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato
+if "%SERVERLANG%" == "en" echo This program comes with ABSOLUTELY NO WARRANTY; for details see LICENSE.txt
+if "%SERVERLANG%" == "en" echo This is free software, and you are welcome to redistribute it
+
+echo.
+::  ---- Determine GSDL3HOME ----
+set GSDL3PATH=
+
+:: Some users may set the above line manually
+ if not "%GSDL3PATH%" == "" goto prepGSDL
+
+ :: The default location is the current directory
+ set GSDL3PATH=.
+
+ :: If it is set, use the GSDLHOME environment variable
+  if "%GSDL3SRCHOME%" == "" goto prepGSDL
+  set GSDL3PATH=%GSDL3SRCHOME%
+
+:prepGSDL
+:: Setup Greenstone, unless it has already been done
+if not "%GSDL3SRCHOME%" == "" goto doneGSDL
+    call "%GSDL3PATH%\gs3-setup.bat" SetEnv > nul
+
+:doneGSDL
+:: GSDL3PATH is no longer needed, since GSDL3SRCHOME should now be set
+set GSDL3PATH=
+
+:findJava
+:: ---- Check Java exists ----
+set JAVAPATH=
+
+:: Some users may set the above line manually
+if not "%JAVAPATH%" == "" goto testJava
+
+:: If it is set, use the JAVA_HOME environment variable
+ if not "%JAVA_HOME%" == "" goto javahome
+
+:: Check if Java is on the search path
+ echo %PATH%| winutil\which.exe java.exe | winutil\setvar.exe JAVAPATH > setjava.bat
+ call setjava.bat
+ del setjava.bat
+ if not "%JAVAPATH%" == "" goto testJava
+
+    :: Still haven't found anything, so try looking in the registry (gulp!)
+    type nul > jdk.reg
+    regedit /E jdk.reg "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit"
+    type jdk.reg > jdk.txt
+    del jdk.reg
+    type nul > jre.reg
+    regedit /E jre.reg "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment"
+    type jre.reg > jre.txt
+    del jre.reg
+
+    winutil\findjava.exe jdk.txt jre.txt | winutil\setvar.exe JAVAPATH > setjava.bat
+    del jdk.txt
+    del jre.txt
+    call setjava.bat
+    del setjava.bat
+
+   :: If nothing was found in the registry, we're stuck
+    if "%JAVAPATH%" == "" goto noJava
+
+    set JAVAPATH=%JAVAPATH%\bin
+    goto testJava
+
+:javahome
+    set JAVAPATH=%JAVA_HOME%\bin
+
+:testJava
+:: Check that a Java executable has been found
+  if "%SERVERLANG%" == "en" echo Checking Java: %JAVAPATH%
+  if "%SERVERLANG%" == "es" echo Revisando Java: %JAVAPATH%
+  if "%SERVERLANG%" == "fr" echo Vârification de Java: %JAVAPATH%
+  if "%SERVERLANG%" == "ru" echo ÂÃ Â®Â¢Â¥Ã ÂªÂ  Java: %JAVAPATH%
+  if exist "%JAVAPATH%\java.exe" goto checkServer
+
+:noJava
+ echo.
+    if "%SERVERLANG%" == "en" echo Failed to locate an appropriate version of Java. You must install a
+    if "%SERVERLANG%" == "en" echo Java Runtime Environment (version 1.4 or greater) before running the
+    if "%SERVERLANG%" == "en" echo Greenstone3 Server.
+    goto exit
+
+:checkServer
+::---- Check that the server program has been compiled ----
+if exist "server.jar" goto runServer
+if "%SERVERLANG%" == "en" echo "You need to compile the code before running the server"
+goto exit
+
+:runServer
+echo Running the Greenstone Server
+:: -Xms32M          To set minimum memory
+:: -Xmx32M          To set maximum memory
+:: -verbose:gc      To set garbage collection messages
+:: -Xincgc          For incremental garbage collection
+:: -Xprof           Function call profiling
+:: -Xloggc:<file>   Write garbage collection log
+
+"%JAVAPATH%\java" -cp "%CLASSPATH%" org.greenstone.server.Server "%GSDL3SRCHOME%"
+
+:exit
+
+:done
+:: ---- Clean up ----
+set JAVAPATH=
+
+
+
+ 
Index: /tags/greenstone-3_02-distribution/gsdl3/gs3-server.sh
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/gs3-server.sh	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/gs3-server.sh	(revision 13928)
@@ -0,0 +1,107 @@
+#!/bin/sh
+serverlang=en
+
+echo
+echo "Greenstone 3 Server"
+echo "Copyright (C) 2006, New Zealand Digital Library Project, University Of Waikato"
+echo "This software comes with ABSOLUTELY NO WARRANTY; for details see LICENSE.txt"
+echo "This is free software, and you are welcome to redistribute it"
+echo
+
+##  -------- Run the Greenstone 3 Server --------
+
+# This script must be run from within the directory in which it lives
+thisdir=`pwd`
+if [ ! -f "${thisdir}/gs3-server.sh" ]; then
+    if [ "$serverlang" == "es" ]; then
+        echo "Este guión deberá ejecutarse desde el directorio en el que reside."
+    elif [ "$serverlang" == "fr" ]; then
+	echo "Ce script doit être exécuté à partir du répertoire dans lequel il se trouve."
+    elif [ "$serverlang" == "ru" ]; then
+	echo "üÔÏÔ ÓËÒÉÐÔ ÄÏÌÖÅÎ ÂÙÔØ ×ÚÑÔ ÉÚ ÄÉÒÅËÔÏÒÉÉ, × ËÏÔÏÒÏÊ ÏÎ ÒÁÓÐÏÌÏÖÅÎ"
+    else
+	echo "This script must be run from the directory in which it resides."
+    fi
+    exit 1
+fi
+
+
+##  ---- Determine GSDL3SRCHOME ----
+gsdl3path=
+
+# Some users may set the above line manually
+if [ "x$gsdl3path" == "x" ]; then
+    # Check the environment variable first
+    if [ "x$GSDL3SRCHOME" != "x" ]; then
+	gsdl3path=$GSDL3SRCHOME
+    else
+	gsdl3path=`pwd`
+    fi
+fi
+
+# Setup Greenstone3, unless it has already been done
+if [ "x$GSDL3SRCHOME" == "x" ]; then
+    pushd $gsdl3path > /dev/null
+    source gs3-setup.sh
+    popd > /dev/null
+fi
+
+## ---- Check Java exists ----
+javapath=
+
+# Some users may set the above line manually
+if [ "x$javapath" = "x" ]; then
+
+    # If it is set, use the JAVA_HOME environment variable
+    if [ "x$JAVA_HOME" != "x" ]; then
+        javapath="$JAVA_HOME/bin/java"
+
+    # Check if Java is on the search path
+    else
+        javapath=`which java 2> /dev/null`
+    fi
+fi
+
+# Check that a Java executable has been found
+if [ "$glilang" = "es" ]; then
+    echo "Revisando Java: $javapath"
+elif [ "$glilang" = "fr" ]; then
+    echo "V<E9>rification de Java: $javapath"
+elif [ "$glilang" = "ru" ]; then
+    echo "<F0><D2><CF><D7><C5><D2><CB><C1> Java: $javapath"
+else
+    echo "Checking Java: $javapath"
+fi
+if [ ! -x "$javapath" ]; then
+    echo
+    echo "Failed to locate an appropriate version of Java. You must installa"
+    echo "Java Runtime Environment (version 1.4 or greater) before running the"
+    echo "Greenstone Server."
+exit 1
+fi
+
+## -- Check the version of Java is new enough (1.4.0 or higher) to run the Server -- do we need this?
+#`$javapath -classpath . CheckJavaVersion > /dev/null`
+#if [ $? -ne 2 ] ; then
+#   echo "The version of the Java Runtime Environment you have installed is too"
+#   echo "old to run the Greenstone Librarian Interface. Please install a new"
+#   echo "version of the JRE (version 1.4 or newer) and rerun this script."
+#exit 1
+#fi
+
+## ---- Check that the server has been compiled ----
+if [ ! -f server.jar ]; then
+  echo "You need to compile the server before running this script"
+  exit 1
+fi
+
+
+# Other arguments you can provide to java 
+# -Xms<number>M    To set minimum memory (by default 32MB)
+# -Xmx<number>M    To set maximum memory (by default the nearest 2^n to the total remaining physical memory)
+# -verbose:gc      To set garbage collection messages
+# -Xincgc          For incremental garbage collection (significantly slows performance)
+# -Xprof           Function call profiling
+# -Xloggc:<file>   Write garbage collection log
+
+java -cp $CLASSPATH org.greenstone.server.Server $GSDL3SRCHOME 
Index: /tags/greenstone-3_02-distribution/gsdl3/gs3-setup.bat
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/gs3-setup.bat	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/gs3-setup.bat	(revision 13928)
@@ -0,0 +1,74 @@
+@echo off
+
+if exist gs3-setup.bat goto start
+  echo This script must be run from within the Greenstone 3 home directory
+  goto exit
+
+:start
+:: ---- Set the GSDL3HOME variable to the current directory ----
+cd | winutil\setvar.exe GSDL3SRCHOME > setgsdl3.bat
+call setgsdl3.bat
+del setgsdl3.bat
+echo GSDL3SRCHOME: %GSDL3SRCHOME%
+set GSDL3HOME=%GSDL3SRCHOME%\web
+echo GSDL3HOME: %GSDL3HOME%
+
+:: change if using external tomcat
+set TOMCAT_HOME=%GSDL3SRCHOME%\packages\tomcat
+
+:: ---- Set other important environment variables ----
+set GSDLOS=windows
+set PATH=%PATH%;%GSDL3SRCHOME%\bin;%GSDL3SRCHOME%\bin\script;%GSDL3SRCHOME%\lib\jni;
+
+:: ---- Set the CLASSPATH environment variable ----
+set CLASSPATH=.;%GSDL3HOME%\WEB-INF\classes;%GSDL3SRCHOME%\resources\java;%CLASSPATH%
+if exist setcp.bat del setcp.bat
+for %%j in ("%GSDL3SRCHOME%"\*.jar) do echo set CLASSPATH=%%CLASSPATH%%;%%j>> setcp.bat
+for %%j in ("%GSDL3HOME%"\WEB-INF\lib\*.jar) do echo set CLASSPATH=%%CLASSPATH%%;%%j>> setcp.bat
+for %%j in ("%GSDL3SRCHOME%"\lib\jni\*.jar) do echo set CLASSPATH=%%CLASSPATH%%;%%j>> setcp.bat
+for %%j in ("%TOMCAT_HOME%"\common\endorsed\*.jar) do echo set CLASSPATH=%%CLASSPATH%%;%%j>> setcp.bat
+for %%j in ("%GSDL3SRCHOME%"\build\*.jar) do echo set CLASSPATH=%%CLASSPATH%%;%%j>> setcp.bat
+
+call setcp.bat
+del setcp.bat
+
+echo CLASSPATH: %CLASSPATH%
+
+::cd %GSDL3HOME%
+
+:findJava
+:: ---- Check Java SDK exists ----
+set JAVAPATH=
+
+:: Some users may set the above line manually
+if not "%JAVAPATH%" == "" goto testJava
+
+    :: If it is set, use the JAVA_HOME environment variable
+    if not "%JAVA_HOME%" == "" goto exit
+
+    :: Look in the registry for Java SDK installations
+    type nul > jdk.reg
+    regedit /E jdk.reg "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit"
+    type jdk.reg > jdk.txt
+    del jdk.reg
+
+    winutil\findjava.exe jdk.txt | winutil\setvar.exe JAVAPATH > setjava.bat
+    del jdk.txt
+    call setjava.bat
+    del setjava.bat
+
+    :: If a suitable installation was found in the registry, check it
+    if not "%JAVAPATH%" == "" goto testJava
+
+:noJava
+    echo.
+    echo Failed to locate an appropriate version of Java. You must install a
+    echo Java Development Kit (version 1.4 or greater) before running the
+    echo Greenstone 3 Digital Library Software.
+    pause
+    goto exit
+
+:testJava
+set JAVA_HOME=%JAVAPATH%
+
+:exit
Index: /tags/greenstone-3_02-distribution/gsdl3/gs3-setup.sh
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/gs3-setup.sh	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/gs3-setup.sh	(revision 13928)
@@ -0,0 +1,132 @@
+# if this file is executed, /bin/sh is used, as we don't start with #!
+# this should work under ash, bash, zsh, ksh, sh style shells.
+
+# make sure we are sourced, and not run
+
+if test "$0" != "`echo $0 | sed s/gs3-setup\.sh//`" ; then
+# if $0 contains "gs3-setup.sh" we've been run... $0 is shellname if sourced.
+# One exception is zsh has an option to set it temporarily to the script name
+  if test -z "$ZSH_NAME" ; then
+  # we aren't using zsh
+  gsdl_not_sourced=true
+  fi
+fi
+
+if test -n "$gsdl_not_sourced" ; then
+  echo "	Error: Make sure you source this script, not execute it. Eg:"
+  echo "		$ source gs3-setup.sh"
+  echo "	or"
+  echo "		$ . ./gs3-setup.sh"
+  echo "	not"
+  echo "		$ ./gs3-setup.sh"
+  unset gsdl_not_sourced
+  exit 1
+fi
+
+if test ! -f gs3-setup.sh ; then
+  echo "You must source the script from within the Greenstone home directory"
+  exit 1
+fi
+
+GSDL3SRCHOME=`pwd`
+GSDL3HOME=$GSDL3SRCHOME/web
+export GSDL3HOME
+export GSDL3SRCHOME
+GSDLOS=`uname -s | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+# check for running bash under cygwin
+if test "`echo $GSDLOS | sed 's/cygwin//'`" != "$GSDLOS" ; then
+    GSDLOS=windows
+fi
+export GSDLOS
+
+#change this if external tomcat
+TOMCAT_HOME=$GSDL3SRCHOME/packages/tomcat
+
+PATH=$GSDL3SRCHOME/bin/script:$GSDL3SRCHOME/bin:$PATH
+export PATH
+MANPATH=$MANPATH:$GSDL3SRCHOME/doc/man
+export MANPATH
+
+CLASSPATH=$GSDL3HOME/WEB-INF/classes:$GSDL3SRCHOME/resources/java:$CLASSPATH
+for JARFILE in $GSDL3SRCHOME/*.jar; do
+    CLASSPATH=$CLASSPATH:$JARFILE
+done
+for JARFILE in $GSDL3SRCHOME/lib/jni/*.jar; do
+    CLASSPATH=$CLASSPATH:$JARFILE
+done
+for JARFILE in $GSDL3HOME/WEB-INF/lib/*.jar; do
+    CLASSPATH=$CLASSPATH:$JARFILE
+done
+for JARFILE in $TOMCAT_HOME/common/endorsed/*.jar; do
+    CLASSPATH=$CLASSPATH:$JARFILE
+done    
+for JARFILE in $GSDL3SRCHOME/build/*.jar; do
+    CLASSPATH=$CLASSPATH:$JARFILE
+done
+
+export CLASSPATH
+
+LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$GSDL3SRCHOME/lib/jni
+export LD_LIBRARY_PATH
+## for mac
+DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:$GSDL3SRCHOME/lib/jni
+export DYLD_LIBRARY_PATH
+
+
+# see if we can find java
+java="java"
+jfound=1
+jok=1
+# if JAVAHOME or JAVA_HOME is set we'll use it to determine where java lives, otherwise
+#  we just hope it's on the search path
+if [ "$JAVA_HOME" != "" ] ; then
+    java="$JAVA_HOME/bin/java"
+elif [ "$JAVAHOME" != "" ] ; then
+    java="$JAVAHOME/bin/java"
+    export JAVA_HOME=$JAVAHOME
+else
+    java=`which java 2> /dev/null`
+    if [ ! -x "$java" ]; then
+	echo "Failed to locate Java. You must install a java runtime environment"
+	echo "(version 1.4 or greater) before installing Greenstone 3."
+	jfound=0
+	jok=0
+    else
+	export JAVA_HOME=`echo $java | sed -n 's/[\\\/]bin[\\\/]java$//p'`
+    fi
+fi
+if [ $jfound -eq 1 ]; then
+    javaversion=`$java -version 2>&1 | sed -n 's/^java version \"\(.*\)\"/\1/p'`
+    jvmajor=`echo $javaversion | sed -n 's/^\([0-9]*\).*$/\1/p'`
+    jvminor=`echo $javaversion | sed -n 's/^[0-9]*\.\([0-9]*\).*$/\1/p'`
+    
+    if [ $jvmajor -lt 1 ] ; then
+	jok=0
+    fi
+    if [ $jvmajor -eq 1 ] && [ $jvminor -lt 4 ] ; then
+	jok=0
+    fi
+fi
+
+if [ $jfound -eq 1 ] && [ $jok -eq 0 ] ; then
+    echo "The version of the java runtime environment you have installed is too"
+    echo "old to run Greenstone 3. Please install a new version of the JRE (version"
+    echo "1.4 or newer) and rerun this installation."
+else
+    echo "Your environment has successfully been set up to run Greenstone3"
+fi
+
+#do we need to check for perl???
+# make sure perl is ok
+#perl=`which perl 2> /dev/null`
+# echo "perl: $perl"
+#if [ ! -x "$perl" ] ; then
+#    echo "Greenstone 3 requires perl in order to operate but this installation"
+#    echo "could not detect perl on your system. Please ensure that perl is installed"
+#    echo "and is on your search path then rerun this installation script."
+#    exit 1
+#fi
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/lib/perl/cpan/XML/Writer.pm
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/lib/perl/cpan/XML/Writer.pm	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/lib/perl/cpan/XML/Writer.pm	(revision 13928)
@@ -0,0 +1,1407 @@
+########################################################################
+# Writer.pm - write an XML document.
+# Copyright (c) 1999 by Megginson Technologies.
+# No warranty.  Commercial and non-commercial use freely permitted.
+#
+# $Id$
+########################################################################
+
+package XML::Writer;
+
+require 5.004;
+
+use strict;
+use vars qw($VERSION);
+use Carp;
+use IO;
+
+$VERSION = "0.4";
+
+
+
+
+########################################################################
+# Constructor.
+########################################################################
+
+#
+# Public constructor.
+#
+# This actually does most of the work of the module: it defines closures
+# for all of the real processing, and selects the appropriate closures
+# to use based on the value of the UNSAFE parameter.  The actual methods
+# are just stubs.
+#
+sub new {
+  my ($class, %params) = (@_);
+
+				# If the user wants namespaces,
+				# intercept the request here; it will
+				# come back to this constructor
+				# from within XML::Writer::Namespaces::new()
+  if ($params{NAMESPACES}) {
+    delete $params{NAMESPACES};
+    return new XML::Writer::Namespaces(%params);
+  }
+
+				# Set up $self and basic parameters
+  my $self;
+  my $output;
+  my $unsafe = $params{UNSAFE};
+  my $newlines = $params{NEWLINES};
+  my $dataMode = $params{DATA_MODE};
+  my $dataIndent = $params{DATA_INDENT};
+
+				# If the NEWLINES parameter is specified,
+				# set the $nl variable appropriately
+  my $nl = '';
+  if ($newlines) {
+    $nl = "\n";
+  }
+
+
+				# Parse variables
+  my @elementStack = ();
+  my $elementLevel = 0;
+  my %seen = ();
+
+  my $hasData = 0;
+  my @hasDataStack = ();
+  my $hasElement = 0;
+  my @hasElementStack = ();
+
+  #
+  # Private method to show attributes.
+  #
+  my $showAttributes = sub {
+    my $atts = $_[0];
+    my $i = 1;
+    while ($atts->[$i]) {
+      my $aname = $atts->[$i++];
+      my $value = _escapeLiteral($atts->[$i++]);
+      $output->print(" $aname=\"$value\"");
+    }
+  };
+
+				# Method implementations: the SAFE_
+				# versions perform error checking
+				# and then call the regular ones.
+  my $end = sub {
+    $output->print("\n");
+  };
+
+  my $SAFE_end = sub {
+    if (!$seen{ELEMENT}) {
+      croak("Document cannot end without a document element");
+    } elsif ($elementLevel > 0) {
+      croak("Document ended with unmatched start tag(s): @elementStack");
+    } else {
+      @elementStack = ();
+      $elementLevel = 0;
+      %seen = ();
+      &{$end};
+    }
+  };
+
+  my $xmlDecl = sub {
+    my ($encoding, $standalone) = (@_);
+    if ($standalone && $standalone ne 'no') {
+      $standalone = 'yes';
+    }
+    $encoding = "UTF-8" unless $encoding;
+    $output->print("<?xml version=\"1.0\"");
+    if ($encoding) {
+      $output->print(" encoding=\"$encoding\"");
+    }
+    if ($standalone) {
+      $output->print(" standalone=\"$standalone\"");
+    }
+    $output->print("?>\n");
+  };
+
+  my $SAFE_xmlDecl = sub {
+    if ($seen{ANYTHING}) {
+      croak("The XML declaration is not the first thing in the document");
+    } else {
+      $seen{ANYTHING} = 1;
+      $seen{XMLDECL} = 1;
+      &{$xmlDecl};
+    }
+  };
+
+  my $pi = sub {
+    my ($target, $data) = (@_);
+    if ($data) {
+      $output->print("<?$target $data?>");
+    } else {
+      $output->print("<?$target?>");
+    }
+    if ($elementLevel == 0) {
+      $output->print("\n");
+    }
+  };
+
+  my $SAFE_pi = sub {
+    my ($name, $data) = (@_);
+    $seen{ANYTHING} = 1;
+    if ($name =~ /xml/i) {
+      carp("Processing instruction target begins with 'xml'");
+    } 
+
+    if ($name =~ /\?\>/ || $data =~ /\?\>/) {
+      croak("Processing instruction may not contain '?>'");
+    } else {
+      &{$pi};
+    }
+  };
+
+  my $comment = sub {
+    my $data = $_[0];
+    $output->print("<!-- $data -->");
+    if ($elementLevel == 0) {
+      $output->print("\n");
+    }
+  };
+
+  my $SAFE_comment = sub {
+    my $data = $_[0];
+    if ($data =~ /--/) {
+      carp("Interoperability problem: \"--\" in comment text");
+    }
+
+    if ($data =~ /-->/) {
+      croak("Comment may not contain '-->'");
+    } else {
+      $seen{ANYTHING} = 1;
+      &{$comment};
+    }
+  };
+
+  my $doctype = sub {
+    my ($name, $publicId, $systemId) = (@_);
+    $output->print("<!DOCTYPE $name");
+    if ($publicId) {
+      $output->print(" PUBLIC \"$publicId\" \"$systemId\"");
+    } elsif ($systemId) {
+      $output->print(" SYSTEM \"$systemId\"");
+    }
+    $output->print(">\n");
+  };
+
+  my $SAFE_doctype = sub {
+    my $name = $_[0];
+    if ($seen{DOCTYPE}) {
+      croak("Attempt to insert second DOCTYPE declaration");
+    } elsif ($seen{ELEMENT}) {
+      croak("The DOCTYPE declaration must come before the first start tag");
+    } else {
+      $seen{ANYTHING} = 1;
+      $seen{DOCTYPE} = $name;
+      &{$doctype};
+    }
+  };
+
+  my $startTag = sub {
+    my $name = $_[0];
+    if ($dataMode) {
+      $output->print("\n");
+      $output->print(" " x ($elementLevel * $dataIndent));
+    }
+    $elementLevel++;
+    push @elementStack, $name;
+    $output->print("<$name");
+    &{$showAttributes}(\@_);
+    $output->print("$nl>");
+    if ($dataMode) {
+      $hasElement = 1;
+      push @hasDataStack, $hasData;
+      $hasData = 0;
+      push @hasElementStack, $hasElement;
+      $hasElement = 0;
+    }
+  };
+
+  my $SAFE_startTag = sub {
+    my $name = $_[0];
+
+    _checkAttributes(\@_);
+
+    if ($seen{ELEMENT} && $elementLevel == 0) {
+      croak("Attempt to insert start tag after close of document element");
+    } elsif ($elementLevel == 0 && $seen{DOCTYPE} && $name ne $seen{DOCTYPE}) {
+      croak("Document element is \"$name\", but DOCTYPE is \""
+	    . $seen{DOCTYPE}
+	    . "\"");
+    } elsif ($dataMode && $hasData) {
+      croak("Mixed content not allowed in data mode: element $name");
+    } else {
+      $seen{ANYTHING} = 1;
+      $seen{ELEMENT} = 1;
+      &{$startTag};
+    }
+  };
+
+  my $emptyTag = sub {
+    my $name = $_[0];
+    if ($dataMode) {
+      $output->print("\n");
+      $output->print(" " x ($elementLevel * $dataIndent));
+    }
+    $output->print("<$name");
+    &{$showAttributes}(\@_);
+    $output->print("$nl />");
+    if ($dataMode) {
+      $hasElement = 1;
+    }
+  };
+
+  my $SAFE_emptyTag = sub {
+    my $name = $_[0];
+
+    _checkAttributes(\@_);
+
+    if ($seen{ELEMENT} && $elementLevel == 0) {
+      croak("Attempt to insert empty tag after close of document element");
+    } elsif ($elementLevel == 0 && $seen{DOCTYPE} && $name ne $seen{DOCTYPE}) {
+      croak("Document element is \"$name\", but DOCTYPE is \""
+	    . $seen{DOCTYPE}
+	    . "\"");
+    } elsif ($dataMode && $hasData) {
+      croak("Mixed content not allowed in data mode: element $name");
+    } else {
+      $seen{ANYTHING} = 1;
+      $seen{ELEMENT} = 1;
+      &{$emptyTag};
+    }
+  };
+
+  my $endTag = sub {
+    my $name = $_[0];
+    my $currentName = pop @elementStack;
+    $name = $currentName unless $name;
+    $elementLevel--;
+    if ($dataMode && $hasElement) {
+      $output->print("\n");
+      $output->print(" " x ($elementLevel * $dataIndent));
+    }
+    $output->print("</$name$nl>");
+    if ($dataMode) {
+      $hasData = pop @hasDataStack;
+      $hasElement = pop @hasElementStack;
+    }
+  };
+
+  my $SAFE_endTag = sub {
+    my $name = $_[0];
+    my $oldName = $elementStack[$#elementStack];
+    if ($elementLevel <= 0) {
+      croak("End tag \"$name\" does not close any open element");
+    } elsif ($name && ($name ne $oldName)) {
+      croak("Attempt to end element \"$oldName\" with \"$name\" tag");
+    } else {
+      &{$endTag};
+    }
+  };
+
+  my $characters = sub {
+    my $data = $_[0];
+    if ($data =~ /[\&\<\>]/) {
+      $data =~ s/\&/\&amp\;/g;
+      $data =~ s/\</\&lt\;/g;
+      $data =~ s/\>/\&gt\;/g;
+    }
+    $output->print($data);
+    $hasData = 1;
+  };
+
+  my $SAFE_characters = sub {
+    if ($elementLevel < 1) {
+      croak("Attempt to insert characters outside of document element");
+    } elsif ($dataMode && $hasElement) {
+      croak("Mixed content not allowed in data mode: characters");
+    } else {
+      &{$characters};
+    }
+  };
+
+   my $charactersXML = sub {
+    my $data = $_[0];
+  #  if ($data =~ /[\&\<\>]/) {
+  #    $data =~ s/\&/\&amp\;/g;
+  #    $data =~ s/\</\&lt\;/g;
+  #    $data =~ s/\>/\&gt\;/g;
+  #  }
+    $output->print($data);
+    $hasData = 1;
+  };
+
+  my $SAFE_charactersXML = sub {
+    if ($elementLevel < 1) {
+      croak("Attempt to insert characters outside of document element");
+    } elsif ($dataMode && $hasElement) {
+      croak("Mixed content not allowed in data mode: characters");
+    } else {
+      &{$charactersXML};
+    }
+  };
+
+  
+				# Assign the correct closures based on
+				# the UNSAFE parameter
+  if ($unsafe) {
+    $self = {'END' => $end,
+	     'XMLDECL' => $xmlDecl,
+	     'PI' => $pi,
+	     'COMMENT' => $comment,
+	     'DOCTYPE' => $doctype,
+	     'STARTTAG' => $startTag,
+	     'EMPTYTAG' => $emptyTag,
+	     'ENDTAG' => $endTag,
+	     'CHARACTERS' => $characters,
+	     'CHARACTERSXML' => $charactersXML};
+  } else {
+    $self = {'END' => $SAFE_end,
+	     'XMLDECL' => $SAFE_xmlDecl,
+	     'PI' => $SAFE_pi,
+	     'COMMENT' => $SAFE_comment,
+	     'DOCTYPE' => $SAFE_doctype,
+	     'STARTTAG' => $SAFE_startTag,
+	     'EMPTYTAG' => $SAFE_emptyTag,
+	     'ENDTAG' => $SAFE_endTag,
+	     'CHARACTERS' => $SAFE_characters,
+	     'CHARACTERSXML' => $SAFE_charactersXML};
+  }
+
+				# Query methods
+  $self->{'IN_ELEMENT'} = sub {
+    my ($ancestor) = (@_);
+    return $elementStack[$#elementStack] eq $ancestor;
+  };
+
+  $self->{'WITHIN_ELEMENT'} = sub {
+    my ($ancestor) = (@_);
+    my $el;
+    foreach $el (@elementStack) {
+      return 1 if $el eq $ancestor;
+    }
+    return 0;
+  };
+
+  $self->{'CURRENT_ELEMENT'} = sub {
+    return $elementStack[$#elementStack];
+  };
+
+  $self->{'ANCESTOR'} = sub {
+    my ($n) = (@_);
+    return $elementStack[$#elementStack-$n];
+  };
+
+				# Set and get the output destination.
+  $self->{'GETOUTPUT'} = sub {
+    return $output;
+  };
+
+  $self->{'SETOUTPUT'} = sub {
+    my $newOutput = $_[0];
+				# If there is no OUTPUT parameter,
+				# use standard output
+    unless ($newOutput) {
+      $newOutput = new IO::Handle();
+      $newOutput->fdopen(fileno(STDOUT), "w") ||
+	croak("Cannot write to standard output");
+    }
+    $output = $newOutput;
+  };
+
+  $self->{'SETDATAMODE'} = sub {
+    $dataMode = $_[0];
+  };
+
+  $self->{'GETDATAMODE'} = sub {
+    return $dataMode;
+  };
+
+  $self->{'SETDATAINDENT'} = sub {
+    $dataIndent = $_[0];
+  };
+
+  $self->{'GETDATAINDENT'} = sub {
+    return $dataIndent;
+  };
+
+				# Set the output.
+  &{$self->{'SETOUTPUT'}}($params{'OUTPUT'});
+
+				# Return the blessed object.
+  return bless $self, $class;
+}
+
+
+
+
+########################################################################
+# Public methods
+########################################################################
+
+#
+# Finish writing the document.
+#
+sub end {
+  my $self = shift;
+  &{$self->{END}};
+}
+
+#
+# Write an XML declaration.
+#
+sub xmlDecl {
+  my $self = shift;
+  &{$self->{XMLDECL}};
+}
+
+#
+# Write a processing instruction.
+#
+sub pi {
+  my $self = shift;
+  &{$self->{PI}};
+}
+
+#
+# Write a comment.
+#
+sub comment {
+  my $self = shift;
+  &{$self->{COMMENT}};
+}
+
+#
+# Write a DOCTYPE declaration.
+#
+sub doctype {
+  my $self = shift;
+  &{$self->{DOCTYPE}};
+}
+
+#
+# Write a start tag.
+#
+sub startTag {
+  my $self = shift;
+  &{$self->{STARTTAG}};
+}
+
+#
+# Write an empty tag.
+#
+sub emptyTag {
+  my $self = shift;
+  &{$self->{EMPTYTAG}};
+}
+
+#
+# Write an end tag.
+#
+sub endTag {
+  my $self = shift;
+  &{$self->{ENDTAG}};
+}
+
+#
+# Write a simple data element.
+#
+sub dataElement {
+  my ($self, $name, $data, %atts) = (@_);
+  $self->startTag($name, %atts);
+  $self->characters($data);
+  $self->endTag($name);
+}
+
+#
+# Write character data.
+#
+sub characters {
+  my $self = shift;
+  &{$self->{CHARACTERS}};
+}
+
+sub charactersXML {
+  my $self = shift;
+  &{$self->{CHARACTERSXML}};
+}
+    
+#
+# Query the current element.
+#
+sub in_element {
+  my $self = shift;
+  return &{$self->{IN_ELEMENT}};
+}
+
+#
+# Query the ancestors.
+#
+sub within_element {
+  my $self = shift;
+  return &{$self->{WITHIN_ELEMENT}};
+}
+
+#
+# Get the name of the current element.
+#
+sub current_element {
+  my $self = shift;
+  return &{$self->{CURRENT_ELEMENT}};
+}
+
+#
+# Get the name of the numbered ancestor (zero-based).
+#
+sub ancestor {
+  my $self = shift;
+  return &{$self->{ANCESTOR}};
+}
+
+#
+# Get the current output destination.
+#
+sub getOutput {
+  my $self = shift;
+  return &{$self->{GETOUTPUT}};
+}
+
+
+#
+# Set the current output destination.
+#
+sub setOutput {
+  my $self = shift;
+  return &{$self->{SETOUTPUT}};
+}
+
+#
+# Set the current data mode (true or false).
+#
+sub setDataMode {
+  my $self = shift;
+  return &{$self->{SETDATAMODE}};
+}
+
+
+#
+# Get the current data mode (true or false).
+#
+sub getDataMode {
+  my $self = shift;
+  return &{$self->{GETDATAMODE}};
+}
+
+
+#
+# Set the current data indent step.
+#
+sub setDataIndent {
+  my $self = shift;
+  return &{$self->{SETDATAINDENT}};
+}
+
+
+#
+# Get the current data indent step.
+#
+sub getDataIndent {
+  my $self = shift;
+  return &{$self->{GETDATAINDENT}};
+}
+
+
+#
+# Empty stub.
+#
+sub addPrefix {
+}
+
+
+#
+# Empty stub.
+#
+sub removePrefix {
+}
+
+
+
+
+########################################################################
+# Private functions.
+########################################################################
+
+#
+# Private: check for duplicate attributes.
+# Note - this starts at $_[1], because $_[0] is assumed to be an
+# element name.
+#
+sub _checkAttributes {
+  my %anames;
+  my $i = 1;
+  while ($_[$i]) {
+    my $name = $_[$i];
+    $i += 2;
+    if ($anames{$name}) {
+      croak("Two attributes named \"$name\"");
+    } else {
+      $anames{$name} = 1;
+    }
+  }
+}
+
+#
+# Private: escape an attribute value literal.
+#
+sub _escapeLiteral {
+  my $data = $_[0];
+  if ($data =~ /[\&\<\>\"]/) {
+    $data =~ s/\&/\&amp\;/g;
+    $data =~ s/\</\&lt\;/g;
+    $data =~ s/\>/\&gt\;/g;
+    $data =~ s/\"/\&quot\;/g;
+  }
+  return $data;
+}
+
+
+
+
+########################################################################
+# XML::Writer::Namespaces - subclass for Namespace processing.
+########################################################################
+
+package XML::Writer::Namespaces;
+use strict;
+use vars qw(@ISA);
+use Carp;
+
+@ISA = qw(XML::Writer);
+
+#
+# Constructor
+#
+sub new {
+  my ($class, %params) = (@_);
+
+  my $unsafe = $params{UNSAFE};
+
+				# Snarf the prefix map, if any, and
+				# note the default prefix.
+  my %prefixMap = ();
+  if ($params{PREFIX_MAP}) {
+    %prefixMap = (%{$params{PREFIX_MAP}});
+    delete $params{PREFIX_MAP};
+  }
+  my $defaultPrefix = $prefixMap{''};
+  delete $prefixMap{''};
+
+				# Generate the reverse map for URIs
+  my %uriMap = ();
+  my $key;
+  foreach $key (keys(%prefixMap)) {
+    $uriMap{$prefixMap{$key}} = $key;
+  }
+
+				# Create an instance of the parent.
+  my $self = new XML::Writer(%params);
+
+				# Snarf the parent's methods that we're
+				# going to override.
+  my $OLD_startTag = $self->{STARTTAG};
+  my $OLD_emptyTag = $self->{EMPTYTAG};
+  my $OLD_endTag = $self->{ENDTAG};
+
+				# State variables
+  my $prefixCounter = 1;
+  my @nsDecls = ();
+  my $nsDecls = {};
+  my @nsDefaultDecl = ();
+  my $nsDefaultDecl = undef;
+  my @nsCopyFlag = ();
+  my $nsCopyFlag = 0;
+
+  #
+  # Push the current declaration state.
+  #
+  my $pushState = sub {
+    push @nsDecls, $nsDecls;
+    push @nsDefaultDecl, $nsDefaultDecl;
+    push @nsCopyFlag, $nsCopyFlag;
+    $nsCopyFlag = 0;
+  };
+
+
+  #
+  # Pop the current declaration state.
+  #
+  my $popState = sub {
+    $nsDecls = pop @nsDecls;
+    $nsDefaultDecl = pop @nsDefaultDecl;
+    $nsCopyFlag = pop @nsCopyFlag;
+  };
+
+  #
+  # Generate a new prefix.
+  #
+  my $genPrefix = sub {
+    my $prefix;
+    do {
+      $prefix = "__NS$prefixCounter";
+      $prefixCounter++;
+    } while ($uriMap{$prefix});
+    return $prefix;
+  };
+
+  #
+  # Perform namespace processing on a single name.
+  #
+  my $processName = sub {
+    my ($nameref, $atts, $attFlag) = (@_);
+    my ($uri, $local) = @{$$nameref};
+    my $prefix = $prefixMap{$uri};
+
+				# Is this an element name that matches
+				# the default NS?
+    if (!$attFlag && ($uri eq $defaultPrefix)) {
+      unless ($nsDefaultDecl) {
+	push @{$atts}, 'xmlns';
+	push @{$atts}, $uri;
+	$nsDefaultDecl = 1;
+      }
+      $$nameref = $local;
+      
+				# Is there a straight-forward prefix?
+    } elsif ($prefix) {
+      unless ($nsDecls->{$uri}) {
+				# Copy on write (FIXME: duplicated)
+	unless ($nsCopyFlag) {
+	  $nsCopyFlag = 1;
+	  my %decls = (%{$nsDecls});
+	  $nsDecls = \%decls;
+	}
+	$nsDecls->{$uri} = $prefix;
+	push @{$atts}, "xmlns:$prefix";
+	push @{$atts}, $uri;
+      }
+      $$nameref = "$prefix:$local";
+
+    } else {
+      $prefix = &{$genPrefix}();
+      $prefixMap{$uri} = $prefix;
+      $uriMap{$prefix} = $uri;
+      unless ($nsCopyFlag) {
+	$nsCopyFlag = 1;
+	my %decls = (%{$nsDecls});
+	$nsDecls = \%decls;
+      }
+      $nsDecls->{$uri} = $prefix;
+      push @{$atts}, "xmlns:$prefix";
+      push @{$atts}, $uri;
+      $$nameref = "$prefix:$local";
+    }
+  };
+
+
+  #
+  # Perform namespace processing on element and attribute names.
+  #
+  my $nsProcess = sub {
+    if (ref($_[0]->[0]) eq 'ARRAY') {
+      &{$processName}(\$_[0]->[0], $_[0], 0);
+    }
+    my $i = 1;
+    while ($_[0]->[$i]) {
+      if (ref($_[0]->[$i]) eq 'ARRAY') {
+	&{$processName}(\$_[0]->[$i], $_[0], 1);
+      }
+      $i += 2;
+    }
+  };
+
+  #
+  # Start tag, with NS processing
+  #
+  $self->{STARTTAG} = sub {
+    my $name = $_[0];
+    unless ($unsafe) {
+      _checkNSNames(\@_);
+    }
+    &{$pushState}();
+    &{$nsProcess}(\@_);
+    &{$OLD_startTag};
+  };
+
+
+  #
+  # Empty tag, with NS processing
+  #
+  $self->{EMPTYTAG} = sub {
+    unless ($unsafe) {
+      _checkNSNames(\@_);
+    }
+    &{$pushState}();
+    &{$nsProcess}(\@_);
+    &{$OLD_emptyTag};
+    &{$popState}();
+  };
+
+
+  #
+  # End tag, with NS processing
+  #
+  $self->{ENDTAG} = sub {
+    my $name = $_[0];
+    &{$nsProcess}(\@_);
+    &{$OLD_endTag};
+    &{$popState}();
+  };
+
+
+  #
+  # Processing instruction, but only if not UNSAFE.
+  #
+  unless ($unsafe) {
+    my $OLD_pi = $self->{PI};
+    $self->{PI} = sub {
+      my $target = $_[0];
+      if ($target =~ /:/) {
+	croak "PI target '$target' contains a colon.";
+      }
+      &{$OLD_pi};
+    }
+  };
+
+
+  #
+  # Add a prefix to the prefix map.
+  #
+  $self->{ADDPREFIX} = sub {
+    my ($uri, $prefix) = (@_);
+    if ($prefix) {
+      $prefixMap{$uri} = $prefix;
+      $uriMap{$prefix} = $uri;
+    } else {
+      $defaultPrefix = $uri;
+    }
+  };
+
+
+  #
+  # Remove a prefix from the prefix map.
+  #
+  $self->{REMOVEPREFIX} = sub {
+    my ($uri) = (@_);
+    if ($defaultPrefix eq $uri) {
+      $defaultPrefix = undef;
+    }
+    delete $prefixMap{$uri};
+  };
+
+
+  #
+  # Bless and return the object.
+  #
+  return bless $self, $class;
+}
+
+
+#
+# Add a preferred prefix for a namespace URI.
+#
+sub addPrefix {
+  my $self = shift;
+  return &{$self->{ADDPREFIX}};
+}
+
+
+#
+# Remove a preferred prefix for a namespace URI.
+#
+sub removePrefix {
+  my $self = shift;
+  return &{$self->{REMOVEPREFIX}};
+}
+
+
+#
+# Check names.
+#
+sub _checkNSNames {
+  my $names = $_[0];
+  my $i = 1;
+  my $name = $names->[0];
+
+				# Check the element name.
+  if (ref($name) eq 'ARRAY') {
+    if ($name->[1] =~ /:/) {
+      croak("Local part of element name '" .
+	    $name->[1] .
+	    "' contains a colon.");
+    }
+  } elsif ($name =~ /:/) {
+    croak("Element name '$name' contains a colon.");
+  }
+
+				# Check the attribute names.
+  while ($names->[$i]) {
+    my $name = $names->[$i];
+    if (ref($name) eq 'ARRAY') {
+      my $local = $name->[1];
+      if ($local =~ /:/) {
+	croak "Local part of attribute name '$local' contains a colon.";
+      }
+    } else {
+      if ($name =~ /^(xmlns|.*:)/) {
+	if ($name =~ /^xmlns/) {
+	  croak "Attribute name '$name' begins with 'xmlns'";
+	} elsif ($name =~ /:/) {
+	  croak "Attribute name '$name' contains ':'";
+	}
+      }
+    }
+    $i += 2;
+  }
+}
+
+
+1;
+__END__
+
+
+########################################################################
+# POD Documentation
+########################################################################
+
+=head1 NAME
+
+XML::Writer - Perl extension for writing XML documents.
+
+=head1 SYNOPSIS
+
+  use XML::Writer;
+  use IO;
+
+  my $output = new IO::File(">output.xml");
+
+  my $writer = new XML::Writer(OUTPUT => $output);
+  $writer->startTag("greeting", 
+                    "class" => "simple");
+  $writer->characters("Hello, world!");
+  $writer->endTag("greeting");
+  $writer->end();
+  $output->close();
+
+
+=head1 DESCRIPTION
+
+XML::Writer is a helper module for Perl programs that write an XML
+document.  The module handles all escaping for attribute values and
+character data and constructs different types of markup, such as tags,
+comments, and processing instructions.
+
+By default, the module performs several well-formedness checks to
+catch errors during output.  This behaviour can be extremely useful
+during development and debugging, but it can be turned off for
+production-grade code.
+
+The module can operate either in regular mode in or Namespace
+processing mode.  In Namespace mode, the module will generate
+Namespace Declarations itself, and will perform additional checks on
+the output.
+
+Additional support is available for a simplified data mode with no
+mixed content: newlines are automatically inserted around elements and
+elements can optionally be indented based as their nesting level.
+
+
+=head1 METHODS
+
+=head2 Writing XML
+
+=over 4
+
+=item new([$params])
+
+Create a new XML::Writer object:
+
+  my $writer = new XML::Writer(OUTPUT => $output, NEWLINES => 1);
+
+Arguments are an anonymous hash array of parameters:
+
+=over 4
+
+=item OUTPUT
+
+An object blessed into IO::Handle or one of its subclasses (such as
+IO::File); if this parameter is not present, the module will write to
+standard output.
+
+=item NAMESPACES
+
+A true (1) or false (0, undef) value; if this parameter is present and
+its value is true, then the module will accept two-member array
+reference in the place of element and attribute names, as in the
+following example:
+
+  my $rdfns = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+  my $writer = new XML::Writer(NAMESPACES => 1);
+  $writer->startTag([$rdfns, "Description"]);
+
+The first member of the array is a namespace URI, and the second part
+is the local part of a qualified name.  The module will automatically
+generate appropriate namespace declarations and will replace the URI
+part with a prefix.
+
+=item PREFIX_MAP
+
+A hash reference; if this parameter is present and the module is
+performing namespace processing (see the NAMESPACES parameter), then
+the module will use this hash to look up preferred prefixes for
+namespace URIs:
+
+
+  my $rdfns = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+  my $writer = new XML::Writer(NAMESPACES => 1,
+                               PREFIX_MAP => {$rdfns => 'rdf'});
+
+The keys in the hash table are namespace URIs, and the values are the
+associated prefixes.  If there is not a preferred prefix for the
+namespace URI in this hash, then the module will automatically
+generate prefixes of the form "__NS1", "__NS2", etc.
+
+To set the default namespace, use '' for the prefix.
+
+=item NEWLINES
+
+A true or false value; if this parameter is present and its value is
+true, then the module will insert an extra newline before the closing
+delimiter of start, end, and empty tags to guarantee that the document
+does not end up as a single, long line.  If the paramter is not
+present, the module will not insert the newlines.
+
+=item UNSAFE
+
+A true or false value; if this parameter is present and its value is
+true, then the module will skip most well-formedness error checking.
+If the parameter is not present, the module will perform the
+well-formedness error checking by default.  Turn off error checking at
+your own risk!
+
+=item DATA_MODE
+
+A true or false value; if this parameter is present and its value is
+true, then the module will enter a special data mode, inserting
+newlines automatically around elements and (unless UNSAFE is also
+specified) reporting an error if any element has both characters and
+elements as content.
+
+=item DATA_INDENT
+
+A numeric value; if this parameter is present, it represents the
+indent step for elements in data mode (it will be ignored when not in
+data mode).
+
+=back
+
+=item end()
+
+Finish creating an XML document.  This method will check that the
+document has exactly one document element, and that all start tags are
+closed:
+
+  $writer->end();
+
+=item xmlDecl([$encoding, $standalone])
+
+Add an XML declaration to the beginning of an XML document.  The
+version will always be "1.0".  If you provide a non-null encoding or
+standalone argument, its value will appear in the declaration (and
+non-null value for standalone except 'no' will automatically be
+converted to 'yes').
+
+  $writer->xmlDecl("UTF-8");
+
+=item doctype($name, [$publicId, $systemId])
+
+Add a DOCTYPE declaration to an XML document.  The declaration must
+appear before the beginning of the root element.  If you provide a
+publicId, you must provide a systemId as well, but you may provide
+just a system ID.
+
+  $writer->doctype("html");
+
+=item comment($text)
+
+Add a comment to an XML document.  If the comment appears outside the
+document element (either before the first start tag or after the last
+end tag), the module will add a carriage return after it to improve
+readability:
+
+  $writer->comment("This is a comment");
+
+=item pi($target [, $data])
+
+Add a processing instruction to an XML document:
+
+  $writer->pi('xml-stylesheet', 'href="style.css" type="text/css"');
+
+If the processing instruction appears outside the document element
+(either before the first start tag or after the last end tag), the
+module will add a carriage return after it to improve readability.
+
+The $target argument must be a single XML name.  If you provide the
+$data argument, the module will insert its contents following the
+$target argument, separated by a single space.
+
+=item startTag($name [, $aname1 => $value1, ...])
+
+Add a start tag to an XML document.  Any arguments after the element
+name are assumed to be name/value pairs for attributes: the module
+will escape all '&', '<', '>', and '"' characters in the attribute
+values using the predefined XML entities:
+
+  $writer->startTag('doc', 'version' => '1.0',
+                           'status' => 'draft',
+                           'topic' => 'AT&T');
+
+All start tags must eventually have matching end tags.
+
+=item emptyTag($name [, $aname1 => $value1, ...])
+
+Add an empty tag to an XML document.  Any arguments after the element
+name are assumed to be name/value pairs for attributes (see startTag()
+for details):
+
+  $writer->emptyTag('img', 'src' => 'portrait.jpg',
+                           'alt' => 'Portrait of Emma.');
+
+=item endTag([$name])
+
+Add an end tag to an XML document.  The end tag must match the closest
+open start tag, and there must be a matching and properly-nested end
+tag for every start tag:
+
+  $writer->endTag('doc');
+
+If the $name argument is omitted, then the module will automatically
+supply the name of the currently open element:
+
+  $writer->startTag('p');
+  $writer->endTag();
+
+=item dataElement($name, $data [, $aname1 => $value1, ...])
+
+Print an entire element containing only character data.  This is
+equivalent to
+
+  $writer->startTag($name [, $aname1 => $value1, ...]);
+  $writer->characters($data);
+  $writer->endTag($name);
+
+=item characters($data)
+
+Add character data to an XML document.  All '<', '>', and '&'
+characters in the $data argument will automatically be escaped using
+the predefined XML entities:
+
+  $writer->characters("Here is the formula: ");
+  $writer->characters("a < 100 && a > 5");
+
+You may invoke this method only within the document element
+(i.e. after the first start tag and before the last end tag).
+
+In data mode, you must not use this method to add whitespace between
+elements.
+
+=item setOutput($output)
+
+Set the current output destination, as in the OUTPUT parameter for the
+constructor.
+
+=item getOutput()
+
+Return the current output destination, as in the OUTPUT parameter for
+the constructor.
+
+=item setDataMode($mode)
+
+Enable or disable data mode, as in the DATA_MODE parameter for the
+constructor.
+
+=item getDataMode()
+
+Return the current data mode, as in the DATA_MODE parameter for the
+constructor.
+
+=item setDataIndent($step)
+
+Set the indent step for data mode, as in the DATA_INDENT parameter for
+the constructor.
+
+=item getDataIndent()
+
+Return the indent step for data mode, as in the DATA_INDENT parameter
+for the constructor.
+
+
+=back
+
+=head2 Querying XML
+
+=over 4
+
+=item in_element($name)
+
+Return a true value if the most recent open element matches $name:
+
+  if ($writer->in_element('dl')) {
+    $writer->startTag('dt');
+  } else {
+    $writer->startTag('li');
+  }
+
+=item within_element($name)
+
+Return a true value if any open elemnet matches $name:
+
+  if ($writer->within_element('body')) {
+    $writer->startTag('h1');
+  } else {
+    $writer->startTag('title');
+  }
+
+=item current_element()
+
+Return the name of the currently open element:
+
+  my $name = $writer->current_element();
+
+This is the equivalent of
+
+  my $name = $writer->ancestor(0);
+
+=item ancestor($n)
+
+Return the name of the nth ancestor, where $n=0 for the current open
+element.
+
+=back
+
+
+=head2 Additional Namespace Support
+
+WARNING: you must not use these methods while you are writing a
+document, or the results will be unpredictable.
+
+=over 4
+
+=item addPrefix($uri, $prefix)
+
+Add a preferred mapping between a Namespace URI and a prefix.  See
+also the PREFIX_MAP constructor parameter.
+
+To set the default namespace, omit the $prefix parameter or set it to
+''.
+
+=item removePrefix($uri)
+
+Remove a preferred mapping between a Namespace URI and a prefix.
+
+To set the default namespace, omit the $prefix parameter or set it to
+''.
+
+=back
+
+
+=head1 ERROR REPORTING
+
+With the default settings, the XML::Writer module can detect several
+basic XML well-formedness errors:
+
+=over 4
+
+=item *
+
+Lack of a (top-level) document element, or multiple document elements.
+
+=item *
+
+Unclosed start tags.
+
+=item *
+
+Misplaced delimiters in the contents of processing instructions or
+comments.
+
+=item *
+
+Misplaced or duplicate XML declaration(s).
+
+=item *
+
+Misplaced or duplicate DOCTYPE declaration(s).
+
+=item *
+
+Mismatch between the document type name in the DOCTYPE declaration and
+the name of the document element.
+
+=item *
+
+Mismatched start and end tags.
+
+=item *
+
+Attempts to insert character data outside the document element.
+
+=item *
+
+Duplicate attributes with the same name.
+
+=back
+
+During Namespace processing, the module can detect the following
+additional errors:
+
+=over 4
+
+=item *
+
+Attempts to use PI targets or element or attribute names containing a
+colon.
+
+=item *
+
+Attempts to use attributes with names beginning "xmlns".
+
+=back
+
+To ensure full error detection, a program must also invoke the end
+method when it has finished writing a document:
+
+  $writer->startTag('greeting');
+  $writer->characters("Hello, world!");
+  $writer->endTag('greeting');
+  $writer->end();
+
+This error reporting can catch many hidden bugs in Perl programs that
+create XML documents; however, if necessary, it can be turned off by
+providing an UNSAFE parameter:
+
+  my $writer = new XML::Writer(OUTPUT => $output, UNSAFE => 1);
+
+
+=head1 AUTHOR
+
+David Megginson, david@megginson.com
+
+=head1 SEE ALSO
+
+XML::Parser
+
+=cut
Index: /tags/greenstone-3_02-distribution/gsdl3/resources/dtd/bookfrag.dtd
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/resources/dtd/bookfrag.dtd	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/resources/dtd/bookfrag.dtd	(revision 13928)
@@ -0,0 +1,529 @@
+<!--This is bookfrag DTD-->
+
+<!--entity declarations-->
+<!--#############################################-->
+
+<!ENTITY % stdatts 
+"ref   IDREF  #IMPLIED
+ id    ID     #IMPLIED
+ type  CDATA  #IMPLIED
+ role  CDATA  #IMPLIED
+ class CDATA  #IMPLIED"
+>
+
+<!ENTITY % inline.class "|quote|emph|ital|reference|date|place|name|graphic|txterr|mkuperr|misc ">
+
+<!ENTITY % block.class "|letter|blockquote|footnote|note|list|deflist|table|blockgraphic">
+
+
+<!-- the top level element-->
+<!--##############################################-->
+
+<!ELEMENT book (acknowledge?,meta*,frontmatter?,bookbody,backmatter?,endmeta*)>
+
+<!--begin top level element declarations-->
+<!--##############################################-->
+
+
+<!--the acknowledge element is for a simple statement 
+designed to be placed at the beginning of the visible document.
+Suggested content:
+  Name of Book
+  Author
+  PG and HWG blurb
+  Original Transcriber + date
+  Marker 
+  e.g.
+  "Origin of the Species by Charles Darwin
+  A project of Project Gutenberg and the HTML Writers Guild.
+  Transcribed by  
+  Markup by Frank Boumphrey. Jan 22 2000"
+  -->
+
+<!ELEMENT acknowledge (#PCDATA %inline.class;)*>
+<!ATTLIST acknowledge
+  %stdatts;
+>
+
+<!--the meta tags are here to provide a means for comment 
+at either the very beginning or end of the document-->
+<!ELEMENT meta EMPTY>
+<!ATTLIST meta
+   content  CDATA  #REQUIRED
+   id       ID     #IMPLIED
+>
+
+<!ELEMENT endmeta EMPTY >
+<!ATTLIST endmeta
+   content  CDATA  #REQUIRED
+   id       ID     #IMPLIED
+>
+
+
+
+<!--the bookbody element contains the body of the book it can 
+consist of either part or chapter divisions-->
+
+<!ELEMENT bookbody (part*|chapter*)>
+
+<!--
+the backmatter element contains the backmatter of the book -->
+
+<!ELEMENT backmatter ((appendix|index|glossary|biblio|note)*,colophon?)>
+
+<!--The endmeta tag is groupedwith its twin meta-->
+
+
+<!--end top level element declarations-->
+
+<!--begin frontmatter element declarations-->
+<!--##############################################-->
+
+<!ELEMENT frontmatter (htitlepage|copypage|epigraph|titlepage|
+                toc|acksect|dedication|preface|introduction|miscfm)*>
+
+<!ELEMENT htitlepage (#PCDATA|title|subtitle|author|para|poem|song %inline.class;)*>
+<!ATTLIST htitlepage
+  %stdatts;
+>
+
+<!ELEMENT copypage (#PCDATA|para|poem|song|note %inline.class;)*>
+<!ATTLIST copypage
+  %stdatts;
+>
+
+<!ELEMENT epigraph (#PCDATA|para|poem|song|note|blockquote %inline.class;)*>
+<!ATTLIST epigraph
+  %stdatts;
+>
+
+
+<!ELEMENT titlepage (#PCDATA|partnum|title|subtitle|author|pubinfo|para|poem|song|note|line %inline.class;)*>
+<!ATTLIST titlepage
+  %stdatts;
+>
+
+<!ELEMENT pubinfo (#PCDATA|para|line %inline.class;)*>
+<!ATTLIST pubinfo
+  %stdatts;
+>
+
+
+<!ELEMENT toc (#PCDATA|title|subtitle|subsubtitle|item|list|deflist %inline.class;)*>
+<!--use type or role to describe toctype="other"-->
+<!ATTLIST toc
+  toctype (contents|maps|graphics|tables|other) "contents" 
+  %stdatts;
+>
+
+<!ELEMENT acksect (#PCDATA|para|poem|song|note %inline.class;)*>
+<!ATTLIST acksect
+  %stdatts;
+>
+
+<!ELEMENT dedication (#PCDATA|title|para|poem|song|note %inline.class;)*>
+<!ATTLIST dedication
+  %stdatts;
+>
+
+
+<!ELEMENT preface ((title|chapheader)?,(para|poem|song|sect1|simplesect %block.class;)*,endchap?,preauthor?)>
+<!ATTLIST preface  %stdatts;
+>
+
+<!ELEMENT introduction ((title|chapheader)?,(para|poem|song|sect1|simplesect %block.class;)*,endchap?)>
+<!ATTLIST introduction  %stdatts;
+>
+
+<!ELEMENT miscfm (#PCDATA|para|poem|song|note %inline.class;)*>
+<!ATTLIST miscfm
+  %stdatts;
+>
+
+<!ELEMENT preauthor (#PCDATA|author %inline.class;)*>
+<!ATTLIST preauthor
+  %stdatts;
+>
+
+
+
+<!--end frontmatter element declarations-->
+
+<!--begin bookbody element declarations-->
+<!--##############################################-->
+
+
+<!ELEMENT part (acknowledge?,(titlepage|toc|htitlepage)*,chapter*)>
+<!ATTLIST part
+  %stdatts;
+>
+
+<!ELEMENT chapter ((title|chapheader)?,(para|poem|song|sect1|simplesect|page %block.class;)*,endchap?)>
+<!ATTLIST chapter  %stdatts;
+>
+
+<!--end bookbody element declarations-->
+
+<!--the lowerlevel bookbody elements-->
+<!--##############################################-->
+
+<!--the chapter heading elements-->
+<!--##############################################-->
+
+
+
+
+<!ELEMENT title (#PCDATA %inline.class;)*>
+<!ATTLIST title
+  %stdatts;
+>
+
+<!ELEMENT subtitle (#PCDATA %inline.class;)*>
+<!ATTLIST subtitle
+  %stdatts;
+>
+
+<!ELEMENT subsubtitle (#PCDATA %inline.class;)*>
+<!ATTLIST subsubtitle
+  %stdatts;
+>
+
+
+
+<!--validity constraint. Only one title,chapnum and chapsummary -->
+<!ELEMENT chapheader (title|subtitle|chapnum|chapsummary|blockquote|para|note)*>
+<!ATTLIST chapheader
+  %stdatts;
+>
+
+
+<!ELEMENT chapnum (#PCDATA %inline.class;)*>
+<!ATTLIST chapnum
+  %stdatts;
+>
+
+<!ELEMENT chapsummary (#PCDATA %inline.class;)*>
+<!ATTLIST chapsummary
+  %stdatts;
+>
+
+
+<!--begin backmatter element declarations-->
+<!--##############################################-->
+
+<!--end backmatter element declarations-->
+
+<!ELEMENT index (title|item|list|deflist|note)*>
+<!ATTLIST index
+  indtype (contents|authors|firstlines|tables|other) "contents" 
+  %stdatts;
+>
+
+<!ELEMENT glossary (title|item|list|deflist|note)*>
+<!ATTLIST glossary  
+  %stdatts;
+>
+
+<!ELEMENT biblio (title|item|list|deflist|note)*>
+<!ATTLIST biblio  
+  %stdatts;
+>
+
+
+<!ELEMENT appendix ((title|chapheader)?,(para|poem|song|sect1|simplesect %block.class;)*,endchap?)>
+<!ATTLIST appendix  %stdatts;
+>
+
+<!ELEMENT colophon (#PCDATA|para|poem|song %inline.class;)*>
+<!ATTLIST colophon
+  %stdatts;
+>
+
+<!--the block elements-->
+<!--##############################################-->
+
+
+<!--validity constraint. Only one title per paragraph-->
+<!ELEMENT para (#PCDATA|title %inline.class;)*>
+<!ATTLIST para
+  %stdatts;
+>
+
+<!ELEMENT simplesect (title,(subtitle|para|poem|song %block.class;)*)>
+<!ATTLIST simplesect
+  %stdatts;
+>
+
+<!ELEMENT sect1 (title,(sect2|simplesect|para|poem|song %block.class;)*)>
+<!ATTLIST sect1
+  %stdatts;
+>
+
+<!ELEMENT sect2 (title,(sect3|simplesect|subtitle|para|poem|song  %block.class;)*)>
+<!ATTLIST sect2
+  %stdatts;
+>
+
+<!ELEMENT sect3 (title,(sect4|simplesect|subtitle|para|poem|song  %block.class;)*)>
+<!ATTLIST sect3
+  %stdatts;
+>
+
+<!ELEMENT sect4 (title,(simplesect|subtitle|para|poem|song  %block.class;)*)>
+<!ATTLIST sect4
+  %stdatts;
+>
+
+<!ELEMENT page (#PCDATA %inline.class;)*>
+<!ATTLIST page
+  %stdatts;
+>
+
+<!ELEMENT misc (#PCDATA %inline.class;)*>
+<!ATTLIST misc
+  %stdatts;
+>
+
+
+
+<!ELEMENT blockquote (title?,(para|poem|song)*,attrib?)>
+<!ATTLIST blockquote
+  %stdatts;
+>
+
+<!ELEMENT attrib (#PCDATA %inline.class;)*>
+<!ATTLIST attrib
+  %stdatts;
+>
+
+<!ELEMENT caption (#PCDATA %inline.class;)*>
+<!ATTLIST caption
+  %stdatts;
+>
+<!--##############################################-->
+<!--poetry and songs in the text-->
+<!ELEMENT poem (#PCDATA|title|subtitle|verse|line|note|footnote %inline.class;)*>
+<!ATTLIST poem
+  %stdatts;
+>
+
+<!ELEMENT song (#PCDATA|title|subtitle|verse|line|note|footnote %inline.class;)*>
+<!ATTLIST song
+  %stdatts;
+>
+
+
+<!ELEMENT verse (title|subtitle|line|note)*>
+<!ATTLIST verse
+  %stdatts;
+>
+
+<!ELEMENT line (#PCDATA %inline.class;)*>
+<!ATTLIST line
+  %stdatts;
+>
+
+
+<!--validity constraint: Only one title per poem or per verse-->
+
+<!--end of poetry in the text-->
+
+<!--letter module-->
+
+<!ELEMENT letter (address|to|from|salut|sig|title|subtitle|para|poem|song|line|note)*>
+<!ATTLIST letter
+  %stdatts;
+>
+
+<!ELEMENT address (#PCDATA|para|line %inline.class;)*>
+<!ATTLIST address
+  %stdatts;
+>
+
+<!ELEMENT to (#PCDATA|para|line %inline.class;)*>
+<!ATTLIST to
+  %stdatts;
+>
+
+
+<!ELEMENT from (#PCDATA|para|line %inline.class;)*>
+<!ATTLIST from
+  %stdatts;
+>
+
+
+<!ELEMENT salut (#PCDATA|para|line %inline.class;)*>
+<!ATTLIST salut
+  %stdatts;
+>
+
+
+<!ELEMENT sig (#PCDATA|para|line %inline.class;)*>
+<!ATTLIST sig
+  %stdatts;
+>
+
+
+<!--end letters module-->
+<!--endchap-->
+<!--##############################################-->
+<!--
+  Endchap should only be used when there is a 
+  considerable ammount of material to be organized.
+  For the occasional note footnote and note will suffice
+-->
+
+<!ELEMENT endchap (para %block.class;)*>
+<!ATTLIST endchap  %stdatts;
+>
+
+<!--lists-->
+<!--##############################################-->
+
+
+<!ELEMENT list (title?,(list|item)*)>
+<!ATTLIST list
+  %stdatts;
+>
+
+<!ELEMENT item (#PCDATA|para|poem|song|simplesect %block.class; %inline.class;)*>
+<!ATTLIST item
+  %stdatts;
+>
+
+<!ELEMENT deflist (title?,(item,desc?,def*)*)>
+<!ATTLIST deflist
+  %stdatts;
+>
+
+<!ELEMENT desc (#PCDATA %inline.class;)*>
+<!ATTLIST desc
+  %stdatts;
+>
+
+<!ELEMENT def (#PCDATA %inline.class;)*>
+<!ATTLIST def
+  %stdatts;
+>
+<!--end lists-->
+<!--table element-->
+<!--##############################################-->
+
+
+<!ELEMENT table (title?,row*,caption?)>
+<!ATTLIST table
+  %stdatts;
+>
+
+<!ELEMENT row (cell)*>
+<!ATTLIST row
+  %stdatts;
+>
+
+<!ELEMENT cell (#PCDATA %block.class; %inline.class;)*>
+<!ATTLIST cell
+  %stdatts;
+>
+
+<!--end table-->
+
+<!--graphics-->
+<!--##############################################-->
+
+<!--
+  Note that the required desc attribute is added 
+  text composed by the marker.
+-->
+
+<!ELEMENT graphic EMPTY >
+<!ATTLIST graphic
+  desc CDATA #REQUIRED
+  href CDATA #REQUIRED
+  %stdatts;
+>
+
+<!ELEMENT blockgraphic (title?,graphic,caption?)>
+<!ATTLIST blockgraphic
+  %stdatts;
+>
+
+
+<!--the inline elements-->
+<!--##############################################-->
+
+
+
+<!ELEMENT footnote (#PCDATA %inline.class;)*>
+<!ATTLIST footnote
+  %stdatts;
+>
+
+<!ELEMENT note (#PCDATA %inline.class;)*>
+<!ATTLIST note
+  %stdatts;
+>
+
+
+<!ELEMENT quote (#PCDATA %inline.class;)*>
+<!ATTLIST quote
+  %stdatts;
+>
+
+<!ELEMENT emph (#PCDATA %inline.class;)*>
+<!ATTLIST emph
+  %stdatts;
+>
+
+<!ELEMENT ital (#PCDATA %inline.class;)*>
+<!ATTLIST ital
+  %stdatts;
+>
+
+<!ELEMENT reference (#PCDATA %inline.class;)*>
+<!ATTLIST reference
+  %stdatts;
+>
+
+<!ELEMENT author (#PCDATA %inline.class;)*>
+<!ATTLIST author
+  %stdatts;
+>
+
+<!ELEMENT date (#PCDATA %inline.class;)*>
+<!ATTLIST date
+  %stdatts;
+>
+
+<!ELEMENT place (#PCDATA %inline.class;)*>
+<!ATTLIST place
+  %stdatts;
+>
+
+<!ELEMENT name (#PCDATA %inline.class;)*>
+<!ATTLIST name
+  %stdatts;
+>
+
+
+<!--use to enclose the text you think is in error
+optional explanation if error is not obvious-->
+<!ELEMENT txterr (#PCDATA)*>
+<!ATTLIST txterr
+  explain  CDATA  #IMPLIED
+  %stdatts;
+>
+
+<!--an explanation is required-->
+<!ELEMENT mkuperr EMPTY>
+<!ATTLIST mkuperr
+  explain  CDATA  #REQUIRED
+  %stdatts;
+>
+
+<!--added as titlepage content  Feb/6/00-->
+<!ELEMENT partnum (#PCDATA %inline.class;)*>
+<!ATTLIST partnum
+  %stdatts;
+>
+
+<!--End of bookfrag dtd-->
Index: /tags/greenstone-3_02-distribution/gsdl3/resources/dtd/entities.dtd
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/resources/dtd/entities.dtd	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/resources/dtd/entities.dtd	(revision 13928)
@@ -0,0 +1,50 @@
+<!ENTITY nbsp "&#160;">
+<!ENTITY copy "&#169;">
+<!ENTITY mdash "&#151;">
+<!ENTITY ouml "&#214;">
+<!ENTITY dollar "&#36;" >
+<!ENTITY Eacute "&#201;" >
+<!ENTITY eacute "&#233;" >
+<!ENTITY uacute "&#250;">
+<!ENTITY aacute "&#225;">
+<!ENTITY oacute "&#243;">
+<!ENTITY Eacute "&#201;">
+<!ENTITY iacute "&#237;">
+<!ENTITY agrave "&#224;">
+<!ENTITY egrave "&#232;">
+<!ENTITY igrave "&#236;">
+<!ENTITY ograve "&#242;">
+<!ENTITY ugrave "&#249;">
+<!ENTITY aelig "&#230;">
+<!ENTITY acirc "&#226;">
+<!ENTITY ecirc "&#234;">
+<!ENTITY icirc "&#238;">
+<!ENTITY ocirc "&#244;">
+<!ENTITY ucirc "&#251;">
+<!ENTITY ntilde "&#241;">
+<!ENTITY ccedil "&#231;">
+<!ENTITY shy "&#173;">
+<!ENTITY pound "&#163;">
+<!ENTITY percnt "&#37;">
+<!ENTITY percent "&#37;">
+<!ENTITY iuml "&#239;">
+<!ENTITY Iuml "&#207;">
+<!ENTITY amacr "&#257;">
+<!ENTITY Amacr "&#256;">
+<!ENTITY emacr "&#275;">
+<!ENTITY Emacr "&#274;">
+<!ENTITY omacr "&#333;">
+<!ENTITY imacr "&#299;">
+<!ENTITY Imacr "&#298;">
+<!ENTITY Omacr "&#332;">
+<!ENTITY umacr "&#363;">
+<!ENTITY Umacr "&#362;">
+<!ENTITY oslash "&#248;">
+<!ENTITY euml "&#235;">
+<!ENTITY Euml "&#203;">
+<!ENTITY uuml "&#252;">
+<!ENTITY frac14 "&#188;">
+<!ENTITY frac34 "&#190;">
+<!ENTITY half "&#189;">
+<!ENTITY frac12 "&#189;">
+
Index: /tags/greenstone-3_02-distribution/gsdl3/resources/dtd/gutbook1.dtd
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/resources/dtd/gutbook1.dtd	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/resources/dtd/gutbook1.dtd	(revision 13928)
@@ -0,0 +1,40 @@
+<!--
+GUTBOOK DTD V 1.0
+==================
+
+GENERAL NOTES
++++++++++++++
+This is gutbook dtd version 1.0
+file name is gutpoems1.dtd
+This dtd is a first pass at a dtd for marking up 
+books for project gutenberg.
+It was originally developed for marking up the Darwins books.
+
+REVISION HISTORY
+++++++++++++++++
+Original Author
+Frank Boumphrey  1/19/2000
+
+COPYRIGHT NOTICE
+++++++++++++++++
+This DTD is the copyright of the HTML writers guild.
+Permission is given in perpetuity for any one to use 
+this DTD provided that these notes and this  copyright 
+notice is included.
+
+
+-->
+
+<!--Begin gutbook DTD-->
+<!ELEMENT gutbook (gutblurb,markupblurb,book*,endmarkupblurb?,endgutblurb?)>
+
+<!ELEMENT gutblurb (#PCDATA|para|simplesect|title)*>
+<!ELEMENT markupblurb (#PCDATA|para|simplesect|title)*>
+<!ELEMENT endmarkupblurb (#PCDATA|para|simplesect|title)*>
+<!ELEMENT endgutblurb (#PCDATA|para|simplesect|title)*>
+
+<!--Include bookfrag.dtd-->
+
+<!ENTITY % bookfrag SYSTEM "bookfrag.dtd">
+%bookfrag;
+<!--end of file-->
Index: /tags/greenstone-3_02-distribution/gsdl3/resources/java/SOAPServer.java.in
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/resources/java/SOAPServer.java.in	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/resources/java/SOAPServer.java.in	(revision 13928)
@@ -0,0 +1,87 @@
+/*
+ *    SOAPServer.java.in: a template for a new SOAPServer
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.greenstone.gsdl3;
+
+import org.greenstone.gsdl3.core.MessageRouter;
+import org.greenstone.gsdl3.util.GlobalProperties;
+import org.greenstone.gsdl3.util.GSFile;
+import org.greenstone.gsdl3.util.GSXML;
+import org.w3c.dom.Element;
+import java.io.File;
+
+/**
+ * The server side of a SOAP connection
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ * @see <a href="http://www.w3.org/TR/SOAP/">Simple Object Access Protocol (SOAP) 1.1 </a>
+ */
+
+public class SOAPServer@sitename@
+{
+    
+    /** The message router we're talking to */
+    protected MessageRouter mr=null;
+    /** the name of the site we are serving */
+    protected String site_name = "@sitename@";
+  
+    /** The no-args constructor */
+    public SOAPServer@sitename@() {
+	String gsdl3_home = GlobalProperties.getGSDL3Home();
+	if (gsdl3_home == null || gsdl3_home.equals("")) {
+	    System.err.println("Couldn't access GSDL3Home from GlobalProerties.getGSDL3HOME, can't initialize the SOAP Server.");
+	    return;
+	}
+	String site_home = GSFile.siteHome(gsdl3_home, this.site_name);
+	
+	File site_file = new File(site_home);
+	if (!site_file.isDirectory()) {
+	    System.err.println("The site directory "+site_file.getPath()+" doesn't exist. Can't initialize the SOAP Server.");
+	    return;
+	}   	
+	mr = new MessageRouter();
+	mr.setSiteName(this.site_name);
+	mr.configure();
+    }
+    
+    
+    public Element [] process (Element [] xml_in) {
+	Element [] result = new Element[xml_in.length];
+	for (int i=0; i<xml_in.length; i++) {
+	    Element req = xml_in[i];
+	    // get rid of the obligatory namespace that axis needs
+	    String tag_name = req.getTagName();
+	    String namespace="";
+	    if (tag_name.indexOf(':')!= -1) {
+		namespace = tag_name.substring(0, tag_name.indexOf(':'));
+		tag_name = tag_name.substring(tag_name.indexOf(':')+1);	
+	    }
+	    Element new_req = GSXML.duplicateWithNewName(req.getOwnerDocument(), req, tag_name, true);
+	    Element r = mr.process(new_req);
+	    // add the namespace back on
+	    //Element new_res = r;
+	    //if (!namespace.equals("")) {
+	    //	new_res = GSXML.duplicateWithNewName(r.getOwnerDocument(), r, namespace+r.getTagName(), true);
+	    //}
+	    result[i] = r;
+	}
+	return result;
+    }   
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl3/resources/java/gai.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/resources/java/gai.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/resources/java/gai.properties	(revision 13928)
@@ -0,0 +1,49 @@
+#***** GAI *****
+# Currently Enabled and Disabled display the same text but in different
+# colours. If necessary this can be changed.
+GAI.Configuration:Configuration
+GAI.Conf_Tooltip: Maintains the configuration setting
+GAI.Ext:Ext
+GAI.Ext_Tooltip:Fedora & DSpace Search
+GAI.Monitor:Monitor
+GAI.Monitor_Tooltip:XXXXXXXXXXXXXXXX
+GAI.Log:Log
+GAI.Log_Tooltip:Examine the relevant log files
+
+Menu.Edit:Edit
+Menu.File:File
+Menu.File_Exit:Exit
+Menu.File_Save:Save
+Menu.Help:Help
+Menu.Help_About:About...
+
+#***** ConfPane *****
+ConfPane.Conf_Content:Configuration file content
+ConfPane.Conf_List:Configuration settings
+ConfPane.Tomcat_Startup:Start Tomcat
+ConfPane.Tomcat_Startup_Tooltip:Click this buttone to startup the Tomcat server
+ConfPane.Tomcat_Shutdown:Stop Tomcat
+ConfPane.Tomcat_Shutdown_Tooltip:Click this buttone to shutdown the Tomcat serve
+r
+ConfPane.Tomcat_Restart:Restart Tomcat
+ConfPane.Tomcat_Restart_Tooltip:Click this button to restart the Tomcat server
+(which will shutdown Tomcat server and restart it again)
+ConfPane.MySQL_Startup:Start MySQL
+ConfPane.MySQL_Startup_Tooltip:Click this button to startup the MYSQL Server
+ConfPane.MySQL_Shutdown:Stop MySQL
+ConfPane.MySQL_Shutdown_Tooltip:Click this button to shutdown the MYSQL Server
+ConfPane.MySQL_Restart:Restart MySQL
+ConfPane.MySQL_Restart_Tooltip:Click this button to restart the MYSQL server(which will shutdown MYSQL server and restart it again
+#***** ExtPane *****
+#***** MonitorPane *****
+#***** LogPane *****
+LogPane.Clear_Log:Clear Log
+LogPane.Clear_Log_Tooltip:Clear the log file
+LogPane.Log_List:Log List
+LogPane.Log_Content:Log Content
+LogPane.Reload_Log:Reload Log
+LogPane.Reload_Log_Tooltip:Reload the contents of this log file
+#**********************
+#***** Sources *****
+Source.General:General
+#*******************
Index: /tags/greenstone-3_02-distribution/gsdl3/resources/java/global.properties.in
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/resources/java/global.properties.in	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/resources/java/global.properties.in	(revision 13928)
@@ -0,0 +1,19 @@
+## greenstone home
+gsdl3.home=@gsdl3home@
+gsdl3.version=@gsdl3version@
+
+# tomcat info
+tomcat.server=@tomcat.server@
+tomcat.port=@tomcat.port@
+tomcat.context=greenstone3
+
+## Proxy setup - set these if you are behind a firewall and you want services that access the internet
+# The proxy server name 
+proxy.host=
+# The proxy server port
+proxy.port=
+# A user name to use when talking to the proxy server 
+proxy.user=
+# A password to use when talking to the proxy server 
+proxy.password=
+
Index: /tags/greenstone-3_02-distribution/gsdl3/resources/java/log4j.properties.in
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/resources/java/log4j.properties.in	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/resources/java/log4j.properties.in	(revision 13928)
@@ -0,0 +1,60 @@
+## greenstone home 
+gsdl3.home=@gsdl3home@
+
+##Configure log4j's operation at the meta level                              
+##Observe log4j parsing this file
+#log4j.debug=true
+##Set this to false for log4j to actually obey the log4j.disable property(next)
+log4j.disableOverride=false
+##Disable all logging in all categories for messages with priority equal to
+##or lower than the one given here
+log4j.disable=DEBUG
+
+#####configure the loggers####
+##general logger                                                   
+log4j.rootCategory=INFO, infolog
+
+##usage logger
+log4j.category.org.greenstone.gsdl3.LibraryServlet=INFO, usagelog
+log4j.additivity.org.greenstone.gsdl3.LibraryServlet=false
+
+##server logger
+log4j.category.org.greenstone.server=INFO, serverlog
+log4j.additivity.org.greenstone.server=false
+
+#####configure appenders and their oprions####                                  
+##general logger
+log4j.appender.infolog=org.apache.log4j.RollingFileAppender
+log4j.appender.infolog.File=${gsdl3.home}/logs/greenstone.log
+#Control the maximum log file size
+log4j.appender.infolog.MaxFileSize=100KB
+#Keep backup file(s) (backups will be in filename.1, .2, .3 etc.)
+log4j.appender.infolog.MaxBackupIndex=3
+
+##usage logger
+log4j.appender.usagelog=org.apache.log4j.RollingFileAppender
+log4j.appender.usagelog.File=${gsdl3.home}/logs/usage.log
+#Control the maximum log file size
+log4j.appender.usagelog.MaxFileSize=1000KB
+
+##Server's logger
+log4j.appender.serverlog=org.apache.log4j.RollingFileAppender
+log4j.appender.serverlog.File=${gsdl3.home}/logs/server.log
+
+
+#####Configure appender layouts and their options#### 
+## general logger layout
+log4j.appender.infolog.layout=org.apache.log4j.PatternLayout
+log4j.appender.infolog.layout.ConversionPattern=%-5p: [%d{yyyy-MM-dd hh:mm:ss}] %C{1}.%M()%n %m%n
+
+##usage logger layout
+# Usage log contains:                                                        
+#      loggingTime + servletName + args (in URL plus saved in a session) +  
+#      remoteAddress + sessionID + browerInfo                               
+log4j.appender.usagelog.layout=org.apache.log4j.PatternLayout
+log4j.appender.usagelog.layout.ConversionPattern=[%d{yyyy-MM-dd hh:mm:ss}] %m%n
+
+##server logger layout
+log4j.appender.serverlog.layout=org.apache.log4j.PatternLayout
+log4j.appender.serverlog.layout.ConversionPattern=%-5p: [%d{yyyy-MM-dd hh:mm:ss}] %C{1}.%M()%n %m%n
+
Index: /tags/greenstone-3_02-distribution/gsdl3/resources/java/server.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/resources/java/server.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/resources/java/server.properties	(revision 13928)
@@ -0,0 +1,32 @@
+ServerSettings.Title=Server settings
+ServerSettings.Tomcat_Port=Tomcat port:
+ServerSettings.Servlet=Servlet:
+ServerSettings.Auto_Start=Enter the library automatically
+ServerSettings.OK=OK
+ServerSettings.Cancel=Cancel
+ServerSettings.DefaultBrowser=Default browser
+ServerSettings.OtherBrowser=Other browser
+ServerSettings.ChooseBrowser=Enter library using:
+ServerSettings.Browse=Browse
+
+ServerControl.EnterLibrary=Enter Library
+ServerControl.RestartLibrary=Restart Library
+ServerControl.StartServer=Start Server
+ServerControl.Version=Version {0}
+ServerControl.Frame_Title=Greenstone Server
+ServerControl.Title=Greenstone3 Digital Library
+ServerControl.Help_RestartLibrary=Press the 'Restart Library' button to restart the server, launch a browser and enter the library
+ServerControl.Help_EnterLibrary=Press the 'Enter Library' button to launch a browser and enter the library
+ServerControl.Starting=Starting server...
+ServerControl.Configuring=Configuring server...
+ServerControl.Stopping=Stopping server...
+ServerControl.LaunchingBrowser=Launching browser...
+ServerControl.LaunchBrowser=Launch browser
+ServerControl.Menu.File=File
+ServerControl.Menu.Settings=Settings...
+ServerControl.Menu.Exit=Exit
+ServerControl.Error={0} failed, please check server.log in {1}/logs for details. 
+ServerControl.Falied={0} failed
+ServerControl.Success={0} success
+greenstone.version=Version 3.2
+ServerSetting.SettingChanged=The new settings will be avaliable after the server restarted
Index: /tags/greenstone-3_02-distribution/gsdl3/resources/soap/localsite.wsdd
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/resources/soap/localsite.wsdd	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/resources/soap/localsite.wsdd	(revision 13928)
@@ -0,0 +1,10 @@
+<deployment xmlns="http://xml.apache.org/axis/wsdd/"
+    xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"
+    xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance">
+  <service name="localsite" style="message">
+    <parameter name="className" value="org.greenstone.gsdl3.SOAPServerlocalsite"/>
+    <parameter name="allowedMethods" value="process"/>
+    <parameter name="scope" value="application"/>
+  </service>
+</deployment>
+
Index: /tags/greenstone-3_02-distribution/gsdl3/resources/soap/site.wsdd.template
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/resources/soap/site.wsdd.template	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/resources/soap/site.wsdd.template	(revision 13928)
@@ -0,0 +1,10 @@
+<deployment xmlns="http://xml.apache.org/axis/wsdd/"
+    xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"
+    xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance">
+  <service name="@siteuri@" style="message">
+    <parameter name="className" value="org.greenstone.gsdl3.SOAPServer@sitename@"/>
+    <parameter name="allowedMethods" value="process"/>
+    <parameter name="scope" value="application"/>
+  </service>
+</deployment>
+
Index: /tags/greenstone-3_02-distribution/gsdl3/resources/soap/undeploy-localsite.wsdd
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/resources/soap/undeploy-localsite.wsdd	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/resources/soap/undeploy-localsite.wsdd	(revision 13928)
@@ -0,0 +1,3 @@
+<undeployment xmlns="http://xml.apache.org/axis/wsdd/">
+  <service name="localsite"/>
+</undeployment>
Index: /tags/greenstone-3_02-distribution/gsdl3/resources/soap/undeploy-site.wsdd.template
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/resources/soap/undeploy-site.wsdd.template	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/resources/soap/undeploy-site.wsdd.template	(revision 13928)
@@ -0,0 +1,3 @@
+<undeployment xmlns="http://xml.apache.org/axis/wsdd/">
+  <service name="@siteuri@"/>
+</undeployment>
Index: /tags/greenstone-3_02-distribution/gsdl3/resources/tomcat/greenstone3.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/resources/tomcat/greenstone3.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/resources/tomcat/greenstone3.xml	(revision 13928)
@@ -0,0 +1,8 @@
+<!-- set allowLinking to true if you want to use symlinks to files or directories outside the docBase directory -->
+<!-- set reloadable to false for a production version. if true, automatically reloads the webapp if it detects changes in classes or lib directories -->
+<!-- see http://tomcat.apache.org/tomcat-5.5-doc/config/context.html for more Context attributes -->
+<Context path="/greenstone3" 
+  docBase="@gsdl3webhome@" 
+  debug="1" reloadable="true" 
+  allowLinking="false">
+</Context>
Index: /tags/greenstone-3_02-distribution/gsdl3/resources/tomcat/server.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/resources/tomcat/server.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/resources/tomcat/server.xml	(revision 13928)
@@ -0,0 +1,381 @@
+<!-- Example Server Configuration File -->
+<!-- Note that component elements are nested corresponding to their
+     parent-child relationships with each other -->
+
+<!-- A "Server" is a singleton element that represents the entire JVM,
+     which may contain one or more "Service" instances.  The Server
+     listens for a shutdown command on the indicated port.
+
+     Note:  A "Server" is not itself a "Container", so you may not
+     define subcomponents such as "Valves" or "Loggers" at this level.
+ -->
+
+<Server port="@shutdown-port@" shutdown="SHUTDOWN">
+
+  <!-- Comment these entries out to disable JMX MBeans support used for the 
+       administration web application -->
+  <Listener className="org.apache.catalina.core.AprLifecycleListener" />
+  <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />
+  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
+  <Listener className="org.apache.catalina.storeconfig.StoreConfigLifecycleListener"/>
+
+  <!-- Global JNDI resources -->
+  <GlobalNamingResources>
+
+    <!-- Test entry for demonstration purposes -->
+    <Environment name="simpleValue" type="java.lang.Integer" value="30"/>
+
+    <!-- Editable user database that can also be used by
+         UserDatabaseRealm to authenticate users -->
+    <Resource name="UserDatabase" auth="Container"
+              type="org.apache.catalina.UserDatabase"
+       description="User database that can be updated and saved"
+           factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
+          pathname="conf/tomcat-users.xml" />
+
+  </GlobalNamingResources>
+
+  <!-- A "Service" is a collection of one or more "Connectors" that share
+       a single "Container" (and therefore the web applications visible
+       within that Container).  Normally, that Container is an "Engine",
+       but this is not required.
+
+       Note:  A "Service" is not itself a "Container", so you may not
+       define subcomponents such as "Valves" or "Loggers" at this level.
+   -->
+
+  <!-- Define the Tomcat Stand-Alone Service -->
+  <Service name="Catalina">
+
+    <!-- A "Connector" represents an endpoint by which requests are received
+         and responses are returned.  Each Connector passes requests on to the
+         associated "Container" (normally an Engine) for processing.
+
+         By default, a non-SSL HTTP/1.1 Connector is established on port 8080.
+         You can also enable an SSL HTTP/1.1 Connector on port 8443 by
+         following the instructions below and uncommenting the second Connector
+         entry.  SSL support requires the following steps (see the SSL Config
+         HOWTO in the Tomcat 5 documentation bundle for more detailed
+         instructions):
+         * If your JDK version 1.3 or prior, download and install JSSE 1.0.2 or
+           later, and put the JAR files into "$JAVA_HOME/jre/lib/ext".
+         * Execute:
+             %JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA (Windows)
+             $JAVA_HOME/bin/keytool -genkey -alias tomcat -keyalg RSA  (Unix)
+           with a password value of "changeit" for both the certificate and
+           the keystore itself.
+
+         By default, DNS lookups are enabled when a web application calls
+         request.getRemoteHost().  This can have an adverse impact on
+         performance, so you can disable it by setting the
+         "enableLookups" attribute to "false".  When DNS lookups are disabled,
+         request.getRemoteHost() will return the String version of the
+         IP address of the remote client.
+    -->
+
+    <!-- Define a non-SSL HTTP/1.1 Connector on port 8080 -->
+    <Connector port="@port@" maxHttpHeaderSize="8192"
+               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
+               enableLookups="false" redirectPort="8443" acceptCount="100"
+               connectionTimeout="20000" disableUploadTimeout="true" URIEncoding="UTF-8"/>
+    <!-- Note : To disable connection timeouts, set connectionTimeout value
+     to 0 -->
+	
+	<!-- Note : To use gzip compression you could set the following properties :
+	
+			   compression="on" 
+			   compressionMinSize="2048" 
+			   noCompressionUserAgents="gozilla, traviata" 
+			   compressableMimeType="text/html,text/xml"
+	-->
+
+    <!-- Define a SSL HTTP/1.1 Connector on port 8443 -->
+    <!--
+    <Connector port="8443" maxHttpHeaderSize="8192"
+               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
+               enableLookups="false" disableUploadTimeout="true"
+               acceptCount="100" scheme="https" secure="true"
+               clientAuth="false" sslProtocol="TLS" />
+    -->
+
+    <!-- Define an AJP 1.3 Connector on port 8009 -->
+    <Connector port="8009" 
+               enableLookups="false" redirectPort="8443" protocol="AJP/1.3" />
+
+    <!-- Define a Proxied HTTP/1.1 Connector on port 8082 -->
+    <!-- See proxy documentation for more information about using this. -->
+    <!--
+    <Connector port="8082" 
+               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
+               enableLookups="false" acceptCount="100" connectionTimeout="20000"
+               proxyPort="80" disableUploadTimeout="true" />
+    -->
+
+    <!-- An Engine represents the entry point (within Catalina) that processes
+         every request.  The Engine implementation for Tomcat stand alone
+         analyzes the HTTP headers included with the request, and passes them
+         on to the appropriate Host (virtual host). -->
+
+    <!-- You should set jvmRoute to support load-balancing via AJP ie :
+    <Engine name="Standalone" defaultHost="localhost" jvmRoute="jvm1">         
+    --> 
+         
+    <!-- Define the top level container in our container hierarchy -->
+    <Engine name="Catalina" defaultHost="localhost">
+
+      <!-- The request dumper valve dumps useful debugging information about
+           the request headers and cookies that were received, and the response
+           headers and cookies that were sent, for all requests received by
+           this instance of Tomcat.  If you care only about requests to a
+           particular virtual host, or a particular application, nest this
+           element inside the corresponding <Host> or <Context> entry instead.
+
+           For a similar mechanism that is portable to all Servlet 2.4
+           containers, check out the "RequestDumperFilter" Filter in the
+           example application (the source for this filter may be found in
+           "$CATALINA_HOME/webapps/examples/WEB-INF/classes/filters").
+
+           Request dumping is disabled by default.  Uncomment the following
+           element to enable it. -->
+      <!--
+      <Valve className="org.apache.catalina.valves.RequestDumperValve"/>
+      -->
+
+      <!-- Because this Realm is here, an instance will be shared globally -->
+
+      <!-- This Realm uses the UserDatabase configured in the global JNDI
+           resources under the key "UserDatabase".  Any edits
+           that are performed against this UserDatabase are immediately
+           available for use by the Realm.  -->
+      <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
+             resourceName="UserDatabase"/>
+
+      <!-- Comment out the old realm but leave here for now in case we
+           need to go back quickly -->
+      <!--
+      <Realm className="org.apache.catalina.realm.MemoryRealm" />
+      -->
+
+      <!-- Replace the above Realm with one of the following to get a Realm
+           stored in a database and accessed via JDBC -->
+
+      <!--
+      <Realm  className="org.apache.catalina.realm.JDBCRealm"
+             driverName="org.gjt.mm.mysql.Driver"
+          connectionURL="jdbc:mysql://localhost/authority"
+         connectionName="test" connectionPassword="test"
+              userTable="users" userNameCol="user_name" userCredCol="user_pass"
+          userRoleTable="user_roles" roleNameCol="role_name" />
+      -->
+
+      <!--
+      <Realm  className="org.apache.catalina.realm.JDBCRealm"
+             driverName="oracle.jdbc.driver.OracleDriver"
+          connectionURL="jdbc:oracle:thin:@ntserver:1521:ORCL"
+         connectionName="scott" connectionPassword="tiger"
+              userTable="users" userNameCol="user_name" userCredCol="user_pass"
+          userRoleTable="user_roles" roleNameCol="role_name" />
+      -->
+
+      <!--
+      <Realm  className="org.apache.catalina.realm.JDBCRealm"
+             driverName="sun.jdbc.odbc.JdbcOdbcDriver"
+          connectionURL="jdbc:odbc:CATALINA"
+              userTable="users" userNameCol="user_name" userCredCol="user_pass"
+          userRoleTable="user_roles" roleNameCol="role_name" />
+      -->
+
+      <!-- Define the default virtual host
+           Note: XML Schema validation will not work with Xerces 2.2.
+       -->
+      <Host name="localhost" appBase="webapps"
+       unpackWARs="true" autoDeploy="true"
+       xmlValidation="false" xmlNamespaceAware="false">
+	
+        <!-- Defines a cluster for this node,
+             By defining this element, means that every manager will be changed.
+             So when running a cluster, only make sure that you have webapps in there
+             that need to be clustered and remove the other ones.
+             A cluster has the following parameters:
+
+             className = the fully qualified name of the cluster class
+
+             name = a descriptive name for your cluster, can be anything
+
+             mcastAddr = the multicast address, has to be the same for all the nodes
+
+             mcastPort = the multicast port, has to be the same for all the nodes
+             
+             mcastBindAddr = bind the multicast socket to a specific address
+             
+             mcastTTL = the multicast TTL if you want to limit your broadcast
+             
+             mcastSoTimeout = the multicast readtimeout 
+
+             mcastFrequency = the number of milliseconds in between sending a "I'm alive" heartbeat
+
+             mcastDropTime = the number a milliseconds before a node is considered "dead" if no heartbeat is received
+
+             tcpThreadCount = the number of threads to handle incoming replication requests, optimal would be the same amount of threads as nodes 
+
+             tcpListenAddress = the listen address (bind address) for TCP cluster request on this host, 
+                                in case of multiple ethernet cards.
+                                auto means that address becomes
+                                InetAddress.getLocalHost().getHostAddress()
+
+             tcpListenPort = the tcp listen port
+
+             tcpSelectorTimeout = the timeout (ms) for the Selector.select() method in case the OS
+                                  has a wakup bug in java.nio. Set to 0 for no timeout
+
+             printToScreen = true means that managers will also print to std.out
+
+             expireSessionsOnShutdown = true means that 
+
+             useDirtyFlag = true means that we only replicate a session after setAttribute,removeAttribute has been called.
+                            false means to replicate the session after each request.
+                            false means that replication would work for the following piece of code: (only for SimpleTcpReplicationManager)
+                            <%
+                            HashMap map = (HashMap)session.getAttribute("map");
+                            map.put("key","value");
+                            %>
+             replicationMode = can be either 'pooled', 'synchronous' or 'asynchronous'.
+                               * Pooled means that the replication happens using several sockets in a synchronous way. Ie, the data gets replicated, then the request return. This is the same as the 'synchronous' setting except it uses a pool of sockets, hence it is multithreaded. This is the fastest and safest configuration. To use this, also increase the nr of tcp threads that you have dealing with replication.
+                               * Synchronous means that the thread that executes the request, is also the
+                               thread the replicates the data to the other nodes, and will not return until all
+                               nodes have received the information.
+                               * Asynchronous means that there is a specific 'sender' thread for each cluster node,
+                               so the request thread will queue the replication request into a "smart" queue,
+                               and then return to the client.
+                               The "smart" queue is a queue where when a session is added to the queue, and the same session
+                               already exists in the queue from a previous request, that session will be replaced
+                               in the queue instead of replicating two requests. This almost never happens, unless there is a 
+                               large network delay.
+        -->             
+        <!--
+            When configuring for clustering, you also add in a valve to catch all the requests
+            coming in, at the end of the request, the session may or may not be replicated.
+            A session is replicated if and only if all the conditions are met:
+            1. useDirtyFlag is true or setAttribute or removeAttribute has been called AND
+            2. a session exists (has been created)
+            3. the request is not trapped by the "filter" attribute
+
+            The filter attribute is to filter out requests that could not modify the session,
+            hence we don't replicate the session after the end of this request.
+            The filter is negative, ie, anything you put in the filter, you mean to filter out,
+            ie, no replication will be done on requests that match one of the filters.
+            The filter attribute is delimited by ;, so you can't escape out ; even if you wanted to.
+
+            filter=".*\.gif;.*\.js;" means that we will not replicate the session after requests with the URI
+            ending with .gif and .js are intercepted.
+            
+            The deployer element can be used to deploy apps cluster wide.
+            Currently the deployment only deploys/undeploys to working members in the cluster
+            so no WARs are copied upons startup of a broken node.
+            The deployer watches a directory (watchDir) for WAR files when watchEnabled="true"
+            When a new war file is added the war gets deployed to the local instance,
+            and then deployed to the other instances in the cluster.
+            When a war file is deleted from the watchDir the war is undeployed locally 
+            and cluster wide
+        -->
+        
+        <!--
+        <Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster"
+                 managerClassName="org.apache.catalina.cluster.session.DeltaManager"
+                 expireSessionsOnShutdown="false"
+                 useDirtyFlag="true"
+                 notifyListenersOnReplication="true">
+
+            <Membership 
+                className="org.apache.catalina.cluster.mcast.McastService"
+                mcastAddr="228.0.0.4"
+                mcastPort="45564"
+                mcastFrequency="500"
+                mcastDropTime="3000"/>
+
+            <Receiver 
+                className="org.apache.catalina.cluster.tcp.ReplicationListener"
+                tcpListenAddress="auto"
+                tcpListenPort="4001"
+                tcpSelectorTimeout="100"
+                tcpThreadCount="6"/>
+
+            <Sender
+                className="org.apache.catalina.cluster.tcp.ReplicationTransmitter"
+                replicationMode="pooled"
+                ackTimeout="15000"/>
+
+            <Valve className="org.apache.catalina.cluster.tcp.ReplicationValve"
+                   filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/>
+                   
+            <Deployer className="org.apache.catalina.cluster.deploy.FarmWarDeployer"
+                      tempDir="/tmp/war-temp/"
+                      deployDir="/tmp/war-deploy/"
+                      watchDir="/tmp/war-listen/"
+                      watchEnabled="false"/>
+                      
+            <ClusterListener className="org.apache.catalina.cluster.session.ClusterSessionListener"/>
+        </Cluster>
+        -->        
+
+
+
+        <!-- Normally, users must authenticate themselves to each web app
+             individually.  Uncomment the following entry if you would like
+             a user to be authenticated the first time they encounter a
+             resource protected by a security constraint, and then have that
+             user identity maintained across *all* web applications contained
+             in this virtual host. -->
+        <!--
+        <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
+        -->
+
+        <!-- Access log processes all requests for this virtual host.  By
+             default, log files are created in the "logs" directory relative to
+             $CATALINA_HOME.  If you wish, you can specify a different
+             directory with the "directory" attribute.  Specify either a relative
+             (to $CATALINA_HOME) or absolute path to the desired directory.
+        -->
+        <!--
+        <Valve className="org.apache.catalina.valves.AccessLogValve"
+                 directory="logs"  prefix="localhost_access_log." suffix=".txt"
+                 pattern="common" resolveHosts="false"/>
+        -->
+
+        <!-- Access log processes all requests for this virtual host.  By
+             default, log files are created in the "logs" directory relative to
+             $CATALINA_HOME.  If you wish, you can specify a different
+             directory with the "directory" attribute.  Specify either a relative
+             (to $CATALINA_HOME) or absolute path to the desired directory.
+             This access log implementation is optimized for maximum performance,
+             but is hardcoded to support only the "common" and "combined" patterns.
+        -->
+        <!--
+        <Valve className="org.apache.catalina.valves.FastCommonAccessLogValve"
+                 directory="logs"  prefix="localhost_access_log." suffix=".txt"
+                 pattern="common" resolveHosts="false"/>
+        -->
+        <!-- Access log processes all requests for this virtual host.  By
+             default, log files are created in the "logs" directory relative to
+             $CATALINA_HOME.  If you wish, you can specify a different
+             directory with the "directory" attribute.  Specify either a relative
+             (to $CATALINA_HOME) or absolute path to the desired directory.
+             This access log implementation is optimized for maximum performance,
+             but is hardcoded to support only the "common" and "combined" patterns.
+
+             This valve use NIO direct Byte Buffer to asynchornously store the
+             log.
+        -->
+        <!--
+        <Valve className="org.apache.catalina.valves.ByteBufferAccessLogValve"
+                 directory="logs"  prefix="localhost_access_log." suffix=".txt"
+                 pattern="common" resolveHosts="false"/>
+        -->
+
+      </Host>
+
+    </Engine>
+
+  </Service>
+
+</Server>
Index: /tags/greenstone-3_02-distribution/gsdl3/resources/tomcat/setclasspath.bat
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/resources/tomcat/setclasspath.bat	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/resources/tomcat/setclasspath.bat	(revision 13928)
@@ -0,0 +1,57 @@
+rem ---------------------------------------------------------------------------
+rem Set CLASSPATH and Java options
+rem
+rem $Id$
+rem ---------------------------------------------------------------------------
+
+rem Make sure prerequisite environment variables are set
+if not "%JAVA_HOME%" == "" goto gotJavaHome
+echo The JAVA_HOME environment variable is not defined
+echo This environment variable is needed to run this program
+goto exit
+:gotJavaHome
+if not exist "%JAVA_HOME%\bin\java.exe" goto noJavaHome
+if not exist "%JAVA_HOME%\bin\javaw.exe" goto noJavaHome
+if not exist "%JAVA_HOME%\bin\jdb.exe" goto noJavaHome
+if not exist "%JAVA_HOME%\bin\javac.exe" goto noJavaHome
+goto okJavaHome
+:noJavaHome
+echo The JAVA_HOME environment variable is not defined correctly
+echo This environment variable is needed to run this program
+echo NB: JAVA_HOME should point to a JDK not a JRE
+goto exit
+:okJavaHome
+
+if not "%BASEDIR%" == "" goto gotBasedir
+echo The BASEDIR environment variable is not defined
+echo This environment variable is needed to run this program
+goto exit
+:gotBasedir
+if exist "%BASEDIR%\bin\setclasspath.bat" goto okBasedir
+echo The BASEDIR environment variable is not defined correctly
+echo This environment variable is needed to run this program
+goto exit
+:okBasedir
+
+rem Set the default -Djava.endorsed.dirs argument
+set JAVA_ENDORSED_DIRS=%BASEDIR%\common\endorsed
+
+rem Set standard CLASSPATH
+rem Note that there are no quotes as we do not want to introduce random
+rem quotes into the CLASSPATH
+set CLASSPATH=%JAVA_HOME%\lib\tools.jar;%CLASSPATH%
+
+rem Set standard command for invoking Java.
+rem Note that NT requires a window name argument when using start.
+rem Also note the quoting as JAVA_HOME may contain spaces.
+set _RUNJAVA="%JAVA_HOME%\bin\java"
+set _RUNJAVAW="%JAVA_HOME%\bin\javaw"
+set _RUNJDB="%JAVA_HOME%\bin\jdb"
+set _RUNJAVAC="%JAVA_HOME%\bin\javac"
+
+goto end
+
+:exit
+exit /b 1
+
+:end
Index: /tags/greenstone-3_02-distribution/gsdl3/resources/tomcat/setclasspath.sh
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/resources/tomcat/setclasspath.sh	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/resources/tomcat/setclasspath.sh	(revision 13928)
@@ -0,0 +1,87 @@
+#!/bin/sh
+# -----------------------------------------------------------------------------
+#  Set CLASSPATH and Java options
+#
+#  $Id$
+# -----------------------------------------------------------------------------
+
+# First clear out the user classpath
+# gs3 - we need to set classpath
+CLASSPATH=$CLASSPATH
+
+# Make sure prerequisite environment variables are set
+if [ -z "$JAVA_HOME" -a -z "$JRE_HOME" ]; then
+  echo "Neither the JAVA_HOME nor the JRE_HOME environment variable is defined"
+  echo "At least one of these environment variable is needed to run this program"
+  exit 1
+fi
+if [ -z "$JAVA_HOME" -a "$1" = "debug" ]; then
+  echo "JAVA_HOME should point to a JDK in order to run in debug mode."
+  exit 1
+fi
+if [ -z "$JRE_HOME" ]; then
+  JRE_HOME="$JAVA_HOME"
+fi
+
+# If we're running under jdb, we need a full jdk.
+if [ "$1" = "debug" -o "$1" = "javac" ] ; then
+  if [ "$os400" = "true" ]; then
+    if [ ! -x "$JAVA_HOME"/bin/java -o ! -x "$JAVA_HOME"/bin/javac ]; then
+      echo "The JAVA_HOME environment variable is not defined correctly"
+      echo "This environment variable is needed to run this program"
+      echo "NB: JAVA_HOME should point to a JDK not a JRE"
+      exit 1
+    fi
+  else
+    if [ ! -x "$JAVA_HOME"/bin/java -o ! -x "$JAVA_HOME"/bin/jdb -o ! -x "$JAVA_HOME"/bin/javac ]; then
+      echo "The JAVA_HOME environment variable is not defined correctly"
+      echo "This environment variable is needed to run this program"
+      echo "NB: JAVA_HOME should point to a JDK not a JRE"
+      exit 1
+    fi
+  fi
+fi
+if [ -z "$BASEDIR" ]; then
+  echo "The BASEDIR environment variable is not defined"
+  echo "This environment variable is needed to run this program"
+  exit 1
+fi
+if [ ! -x "$BASEDIR"/bin/setclasspath.sh ]; then
+  if $os400; then
+    # -x will Only work on the os400 if the files are:
+    # 1. owned by the user
+    # 2. owned by the PRIMARY group of the user
+    # this will not work if the user belongs in secondary groups
+    eval
+  else
+    echo "The BASEDIR environment variable is not defined correctly"
+    echo "This environment variable is needed to run this program"
+    exit 1
+  fi
+fi
+
+# Set the default -Djava.endorsed.dirs argument
+JAVA_ENDORSED_DIRS="$BASEDIR"/common/endorsed
+
+# Set standard CLASSPATH
+if [ "$1" = "debug" -o "$1" = "javac" ] ; then
+  CLASSPATH="$JAVA_HOME"/lib/tools.jar:$CLASSPATH
+fi
+
+# OSX hack to CLASSPATH
+JIKESPATH=
+if [ `uname -s` = "Darwin" ]; then
+  OSXHACK="/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Classes"
+  if [ -d "$OSXHACK" ]; then
+    for i in "$OSXHACK"/*.jar; do
+      JIKESPATH="$JIKESPATH":"$i"
+    done
+  fi
+fi
+
+# Set standard commands for invoking Java.
+  _RUNJAVA="$JRE_HOME"/bin/java
+if [ "$os400" != "true" ]; then
+  _RUNJDB="$JAVA_HOME"/bin/jdb
+fi
+_RUNJAVAC="$JAVA_HOME"/bin/javac
Index: /tags/greenstone-3_02-distribution/gsdl3/resources/xml/collectionConfig.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/resources/xml/collectionConfig.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/resources/xml/collectionConfig.xml	(revision 13928)
@@ -0,0 +1,67 @@
+<collectionConfig xmlns:gsf="http://www.greenstone.org/greenstone3/schema/ConfigFormat" xmlns:xslt="http://www.w3.org/1999/XSL/Transform">>
+  <metadataList>
+    <!-- email address of collection creator -->
+    <metadata name="creator"></metadata>
+  </metadataList>
+  <displayItemList>
+    <!-- Display name of collection -->
+    <displayItem name='name' lang='en'></displayItem>
+    <!-- Display description of collection -->
+    <displayItem name='description' lang='en'></displayItem>
+    <!-- Icon name for collection home page -->
+    <displayItem name='icon' lang='en'></displayItem>
+    <!-- Icon name for library home page -->
+    <displayItem name='smallicon' lang='en'></displayItem>
+  </displayItemList>
+  <recognise>
+    <docType name="HTML"/>
+    <docType name="Text"/>
+    <docType name="Metadata"/>
+    <docType name="JPEG"/>
+  </recognise>
+  <search type="mg" name="mgsearch">
+    <index name="doctext">
+      <field>text</field>
+      <level>document</level>
+      <displayItem name='name' lang="en">entire documents</displayItem>
+      <displayItem name='name' lang="fr">documents entiers</displayItem>
+      <displayItem name='name' lang="es">documentos enteros</displayItem>
+    </index>
+    <!-- section level text index -->
+    <!-- <index name="sectext">
+    <field>text</field>
+    <level>section</level>
+      <displayItem name='name' lang="en">chapters</displayItem>
+      <displayItem name='name' lang="fr">chapitres</displayItem>
+      <displayItem name='name' lang="es">capÃ­tulos</displayItem>
+    </index>-->
+    <!-- section level title index -->
+    <!--<index name="sectitle">
+      <field>Title</field>
+      <level>section</level>
+      <displayItem name='name' lang="en">section titles</displayItem>
+      <displayItem name='name' lang="fr">titres des sections</displayItem>
+      <displayItem name='name' lang="es">tÃ­tulos de las secciones</displayItem>
+    </index>-->
+    <!-- default format -->
+    <format>
+      <gsf:template match="documentNode"><td valign='top'><gsf:link><gsf:icon/></gsf:link></td><td><gsf:metadata name='Title'/></td></gsf:template>
+    </format>
+  </search>
+  <browse>
+    <classifier name="CLTit" type="AZList" horizontalAtTop='true'>
+      <field>Title</field>
+      <sort>Title</sort>
+      <displayItem name='name' lang='en'>Titles</displayItem>
+    </classifier>
+  </browse>
+  <display>
+    <format>
+      <!-- set to true if have cover images -->
+      <gsf:option name="coverImages" value="false"/>
+      <!-- set to true if have sectioned documents -->
+      <gsf:option name="documentTOC" value="false"/>
+    </format>
+  </display>
+</collectionConfig>
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/Configuration.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/Configuration.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/Configuration.java	(revision 13928)
@@ -0,0 +1,132 @@
+/**
+ *#########################################################################
+ * Configuration
+ * A component of the GAI application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.admin;
+
+import java.awt.Color;
+import java.util.Locale;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+
+// eventually this class will hold configuration settings from a config file. For now, lets use static info
+// loosely copied from Gatherer Configuration
+public class Configuration {
+    
+    static private Hashtable hash = null;
+
+    /** The first of three patterns used during tokenization, this pattern handles a comma separated list. */
+    static final private String TOKENIZER_PATTERN1 = " ,\n\t";
+    /** The second of three patterns used during tokenization, this pattern handles an underscore separated list. */
+    static final private String TOKENIZER_PATTERN2 = "_\n\t";
+    /** The last of three patterns used during tokenization, this pattern handles an comma separated list containing spaces. */
+    static final private String TOKENIZER_PATTERN3 = ",\n\t";
+
+    public Configuration() {
+	
+	hash = new Hashtable();
+	
+	
+	// load up all the initial stuff
+	hash.put("admin.log", "true");
+	hash.put("admin.conf", "true");
+	hash.put("admin.ext", "true");
+	hash.put("admin.monitor", "true");
+	hash.put("coloring.workspace_selection_foreground", "0, 0, 0");
+	hash.put("coloring.workspace_selection_background", "176, 208, 176");
+	hash.put("coloring.table_noneditable_background", "255, 255, 255");
+	hash.put("coloring.table_editable_background", "255, 255, 255");
+	hash.put("coloring.collection_tree_background", "224, 240, 224");
+	hash.put("coloring.collection_tree_foreground", "0, 0, 0");
+	hash.put("coloring.workspace_tree_foreground", "0, 0, 0");
+	hash.put("coloring.workspace_tree_background", "218, 237, 252");
+	hash.put("coloring.workspace_heading_background", "128, 180, 216");
+	hash.put("coloring.workspace_heading_foreground", "0, 0, 0");
+	
+    }
+
+    /** Retrieve whether the named property is set or not */
+    static public boolean get(String property) {
+	String value = (String)hash.get(property);
+	return (value != null && value.equalsIgnoreCase("true"));
+    }
+    
+    /** Retrieve the value of the named property as a String */
+    static public String getString(String property) {
+	return (String)hash.get(property);
+    }
+
+    /** Retrieve the value of the named property as a Locale. */
+    static public Locale getLocale(String property) {
+	Locale result = Locale.getDefault();
+	try {
+	    String raw = (String) hash.get(property);
+	    if (raw==null) {
+		return result;
+	    }
+	    // Locale is a underscore separated code.
+	    StringTokenizer tokenizer = new StringTokenizer(raw, TOKENIZER_PATTERN2);
+	    String language = tokenizer.nextToken();
+	    if(tokenizer.hasMoreTokens()) {
+		String country = tokenizer.nextToken();
+		result = new Locale(language, country);
+	    }
+	    else {
+		result = new Locale(language);
+	    }
+	}
+	catch(Exception error) {
+	    error.printStackTrace();
+	}
+	return result;
+    }
+    
+    /** Retrieve the value of the named property as a Color. */
+    static public Color getColor(String property) {
+	Color result = Color.white; // Default
+	String raw = (String)hash.get(property);
+	if (raw == null || raw.equals("")) {
+	    return result;
+	}
+	try {
+	    // Color is a RGB triplet list, comma separated (also remove whitespace)
+	    StringTokenizer tokenizer = new StringTokenizer(raw, TOKENIZER_PATTERN1);
+	    int red = Integer.parseInt(tokenizer.nextToken());
+	    int green = Integer.parseInt(tokenizer.nextToken());
+	    int blue = Integer.parseInt(tokenizer.nextToken());
+	    result = new Color(red, green, blue);
+	}
+	catch(Exception error) {
+	    error.printStackTrace();
+	}
+	return result;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/GAI.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/GAI.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/GAI.java	(revision 13928)
@@ -0,0 +1,115 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Greenstone Administrator Interface, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Chi-Yu Huang, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+
+package org.greenstone.admin;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.lang.*;
+import java.net.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.plaf.*;
+import javax.swing.text.*;
+
+import org.greenstone.gsdl3.util.Dictionary;
+import org.greenstone.admin.gui.SetServerPane;
+
+/** Containing the top-level "core" for the GAI(Greenstone Administrator
+ * Interface) this class is the common core for the GAI application and 
+ * applet. It first parses the command line arguments, preparing to update 
+ * the configuration as required. Next it loads several important support 
+ * classes such as the Configuration and Dictionary. Finally it creates the 
+ * other important managers and sends them on their way.
+ * @author Chi-Yu Huang, Greenstone Digital Library, University of Waikato
+ * @version ###
+ */
+public class GAI
+{
+    public static Dimension screen_size = Toolkit.getDefaultToolkit().getScreenSize();
+    public static String gsdl3_src_home;
+    public static String gsdl3_web_home;
+    public static String tomcat_home;
+    
+    public static File build_properties_file;
+
+    public static String images_path;
+    /** A public reference to the GAIManager. */
+    static public GAIManager ga_man;
+
+    /** a public reference to the Dictionary */
+    static public Dictionary dictionary = null;
+    
+    public GAI(String gsdl3_src_home, String gsdl3_web_home)
+    {
+	this.gsdl3_src_home = gsdl3_src_home;
+	this.gsdl3_web_home = gsdl3_web_home;
+	
+	// set up the Configuration
+	new Configuration();
+	
+	// Read Dictionary
+	this.dictionary = new Dictionary("gai", Configuration.getLocale("general.locale"));
+	this.build_properties_file = new File(this.gsdl3_src_home, "build.properties");
+	// this may change if using preinstalled tomcat
+	this.tomcat_home = this.gsdl3_src_home+File.separatorChar+"packages"+File.separatorChar+"tomcat";
+	
+	// should come from classpath ??
+	this.images_path = this.gsdl3_src_home+File.separatorChar+"resources"+File.separatorChar+"images"+File.separatorChar;
+	// start the GAIManager
+	ga_man  = new GAIManager(screen_size);
+	ga_man.display();
+
+    }
+    
+    public static void main (String[] args){
+	// A serious hack, but its good enough to stop crappy 'Could not
+        // lock user prefs' error messages.  Thanks to Walter Schatz from
+        // the java forums.
+        System.setProperty("java.util.prefs.syncInterval","2000000");
+
+	if (args.length != 2) {
+	    System.err.println("Usage: java org.greenstone.admin.GAI <gsdl3 src home> <gsdl3 web home>");
+	    System.exit(1);
+	}
+	
+	File gsdl3_src_dir = new File(args[0]);
+	File gsdl3_web_dir = new File(args[1]);
+	if (!gsdl3_src_dir.isDirectory() || !gsdl3_web_dir.isDirectory()) {
+	    System.err.println("Usage: java org.greenstone.admin.GAI <gsdl3 src home> <gsdl3 web home>");
+	    System.err.println("src or web directory does not exist!");
+	    System.exit(1);
+	}
+	
+	GAI gai = new GAI(args[0], args[1]);
+
+    }
+
+}
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/GAIFirstSettingFrame.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/GAIFirstSettingFrame.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/GAIFirstSettingFrame.java	(revision 13928)
@@ -0,0 +1,218 @@
+/**
+ *#########################################################################
+ *
+ * A component of the GAI application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Chi-Yu Huang, Greenstone Digital Library, University of Waikato
+ * Date: 03.2005
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+/* This program is intended to confirm the initial user's setting about
+ * the Tomcat server and MySQL server they would like to run GSDL3 with
+ */
+package org.greenstone.admin;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.lang.Object;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.tree.*;
+
+import org.greenstone.core.ParsingProgress;
+import org.greenstone.admin.gui.SetServerPane;
+import org.greenstone.admin.GAI;
+
+/** The initial setting pane is to request the user to input the preferred 
+ *  Tomcat and Mysql server,they would like to run GSDL3 with
+ *  @author Chi-Yu Huang, Greenstone Digital Library, University of Waikato
+ *  @version
+ */
+public class GAIFirstSettingFrame
+    extends JFrame
+    implements ActionListener {
+
+    public static Dimension screen_size = Toolkit.getDefaultToolkit().getScreenSize();
+   
+    /* This pane is to inform the user to set up the tomcat and mysql server 
+     * if they are the first time run GAI, if the user doen't want to set up
+     * the installation will be based on the gsdl3 default value*/
+    protected JScrollPane setting_message_pane = null;
+    protected JPanel first_setting_pane = null;
+    protected JPanel main_pane = null;
+    protected JTextArea first_setting_message = null;
+    protected JButton fset_yes_button = null;
+    protected JButton fset_no_button = null;
+    protected JPanel button_pane = null;
+    protected JPanel control_pane = null;
+    
+    public boolean setting_confirm = false;
+    
+    /** The various sizes for the screen layout*/
+    static private Dimension MIN_SIZE = new Dimension( 90,  90);
+    static private Dimension LIST_SIZE  = new Dimension(200, 450);
+    static private Dimension DIALOG_SIZE = new Dimension (400,300);
+    static private Dimension TABLE_SIZE = new Dimension(500,200);
+    static final Dimension SIZE = new Dimension(400,75);						   
+    
+    //Constructor
+    public GAIFirstSettingFrame() {
+	super();
+
+	this.setDefaultCloseOperation(EXIT_ON_CLOSE);
+	this.setSize(DIALOG_SIZE);
+	this.setTitle("First time setting Tomcat/MYSQL Server");
+
+	// create all the control button panes
+	button_pane  = new JPanel();
+
+	//First time running button
+	FirstSetYesButtonListener fsybl = new FirstSetYesButtonListener();
+	FirstSetNoButtonListener fsnbl = new FirstSetNoButtonListener();
+	
+	// ImagesIcon for the buttons
+	ImageIcon setYesButtonIcon = new ImageIcon(GAI.images_path + "refresh.gif");
+	ImageIcon setNoButtonIcon = new ImageIcon(GAI.images_path + "exit.gif");
+	
+	fset_yes_button = new JButton("Yes", setYesButtonIcon);
+	fset_yes_button.addActionListener(fsybl);
+	fset_yes_button.setMnemonic(KeyEvent.VK_S);
+	fset_yes_button.setToolTipText("Click this button to Set up the Tomcat/MYSQL server");
+	fset_yes_button.setEnabled(false);
+	fset_no_button = new JButton("No", setNoButtonIcon);
+	fset_no_button.addActionListener(fsnbl);
+	fset_no_button.setEnabled(false);
+	fset_no_button.setMnemonic(KeyEvent.VK_N);
+	fset_no_button.setToolTipText("Click this button to skip the First time Tomcat/MYSQL server setting");
+	
+	//First time running setting buttons
+	fsybl = null;
+	fsnbl = null;
+	display();
+    }
+
+    /** Any implementation of ActionListener requires this method so that when an 
+     **action is performed the appropriate effect can occur.*/
+    public void actionPerformed(ActionEvent event) {
+    }
+
+    /** This method is callsed to actually layout the components.*/
+    public void display() {
+	//KeyListenerImpl key_listener = new KeyListenerImpl();
+	//MouseListenerImpl mouse_listener = new MouseListenerImpl();
+	//this.addKeyListener(key_listener);
+
+	first_setting_message = new JTextArea();
+	first_setting_message.setEditable(false);
+	first_setting_message.setLineWrap(true);
+	
+	first_setting_message.setText("If you are about the first time to run GAI, you can set up " +
+				      "your own TOMCAT/MYSQL server. Otherwise, your GSDL3 " +
+				      "will be installed with the TOMCAT/MYSQL setting come " +
+				      "with the package. You may change the setting later on.");
+
+	first_setting_message.setFont(new Font("Arial", Font.BOLD, 14));
+	
+	setting_message_pane = new JScrollPane(first_setting_message);
+	
+	// The pane to store setting_message_pane
+	first_setting_pane = new JPanel();
+	first_setting_pane.setBorder(BorderFactory.createEmptyBorder(5,5,20,5));
+	first_setting_pane.setLayout (new BorderLayout());
+	first_setting_pane.add(setting_message_pane, BorderLayout.CENTER);
+
+	// Button Control Layout 
+	fset_yes_button.setEnabled(true);
+	fset_no_button.setEnabled(true);
+
+	button_pane.setLayout (new GridLayout(1,2));
+	button_pane.add(fset_yes_button);
+	button_pane.add(fset_no_button);
+
+	control_pane = new JPanel();
+	control_pane.setBorder(BorderFactory.createLoweredBevelBorder());
+	control_pane.setLayout(new BorderLayout());
+	control_pane.add(new JLabel("Do you want to set up your own running Tomcat/Mysql Servers?"), BorderLayout.CENTER);
+	control_pane.add(button_pane, BorderLayout.SOUTH);
+			 
+	main_pane = (JPanel) getContentPane();
+	//main_pane.setBorder(BorderFactory.createLoweredBevelBorder());
+	main_pane.setLayout (new BorderLayout());
+	main_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	main_pane.add(first_setting_pane,BorderLayout.CENTER);
+	main_pane.add(control_pane, BorderLayout.SOUTH);
+	main_pane.setBackground(Configuration.getColor("coloring.workspace_selection_background"));
+	main_pane.setForeground(Configuration.getColor("coloring.workspace_selection_foreground"));
+
+	// Center and display
+	Dimension screen_size = Toolkit.getDefaultToolkit().getScreenSize();
+	setLocation((screen_size.width - SIZE.width) / 2,
+		    (screen_size.height - SIZE.height) / 2);
+	setVisible(true);
+    }
+    
+    public boolean checkSettingConfirm(){
+	return setting_confirm;
+    }
+
+    public void destroy() {
+    }
+        
+    /** This class serves as the listener for actions on the build button.*/
+    private class FirstSetYesButtonListener
+	implements ActionListener {
+	/** If you want to give up the change you have made to the build properties 
+	 *  file before you save the change,  This button is to reload the log file 
+	 *  whenever user want to */
+	public void actionPerformed(ActionEvent event) {
+	    SetServerPane set_server_pane = new SetServerPane ();
+	    set_server_pane.display();
+	    //disable the GAIFirstSettingFrame
+	    setVisible (false);
+	    setting_confirm = true;
+	}
+    }
+    private class FirstSetNoButtonListener
+	implements ActionListener {
+	// Exit the Adminstration tool 
+	public void actionPerformed(ActionEvent event) {
+	    setting_confirm = false;
+	    setVisible (false);
+	    //return setting_confirm;
+	    if (!setting_confirm) {
+		GAIManager gai = new GAIManager(screen_size);
+	    }
+	}
+    }
+}
+       
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/GAIManager.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/GAIManager.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/GAIManager.java	(revision 13928)
@@ -0,0 +1,353 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Administration Tool (GAI) application, part of the 
+ * Greenstone digital library suite from the New Zealand Digital Library 
+ * Project at the University of Waikato, New Zealand.
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Chi-Yu Huang, Greenstone Digital Library, University of Waikato
+ *
+ *########################################################################
+ */
+
+package org.greenstone.admin;
+
+import org.greenstone.admin.GAI;
+import org.greenstone.admin.gui.TabbedPane;
+import org.greenstone.admin.gui.MenuBar;
+import org.greenstone.admin.gui.LogPane;
+import org.greenstone.admin.gui.ConfPane;
+
+//import java AWT classes
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.plaf.*;
+
+public class GAIManager 
+    extends JFrame 
+    implements ActionListener, ChangeListener{
+    
+    private Dimension size = null;
+    // The ConfPane contains the configuration details of Greenstone III build and installation
+    public ConfPane conf_pane = null;
+    // The LogPane contains the log details for Tomcat Server used by gsdl3
+    public LogPane log_pane = null;
+    // Not designed yet
+    public JPanel ext_pane = null;
+    // Not designed yet
+    public JPanel monitor_pane = null;
+       
+    static public ImageIcon CONF_ICON = null; 
+    static public ImageIcon EXT_ICON = null; 
+    static public ImageIcon MONITOR_ICON = null; 
+    static public ImageIcon LOG_ICON = null; 
+    
+    // Create a menu bar in the main Pane
+    public MenuBar menu_bar = null;
+
+    // HelpFrame
+    
+    private JPanel previous_pane = null;
+    private JPanel content_pane = null;
+    private JTabbedPane tab_pane = null;
+
+    /** A threaded tab changer to try and avoid NPE on exit. */
+    private TabUpdater tab_updater = null;
+    
+    //Contructor
+    public GAIManager(Dimension size){
+	super();
+	this.size = size;
+	this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
+	this.setTitle("GreenStone 3 Administration Tool");
+	/* Add a focus listener to ourselves. Thus if we gain focus when a Modal Dialog should 
+	 * instead have it, we can try to bring the modal dialog to the front*/
+	//this.addFocusListener(new GAIGUIFocusListener());	
+	//display();
+    }
+
+    private class GAIGUIFocusListener
+	extends FocusAdapter {
+	public void focusGained(FocusEvent e) {
+	    /*  if (ModalDialog.current_modal != null) {
+		ModalDialog.current_modal.makeVisible();
+		ModalDialog.current_modal.toFront();
+		}*/
+	}
+    }
+
+   public void display(){
+	CONF_ICON = new ImageIcon (GAI.images_path + "create.gif");
+	EXT_ICON = new ImageIcon (GAI.images_path + "information.gif");	
+	MONITOR_ICON = new ImageIcon (GAI.images_path + "zoom.gif");
+	LOG_ICON = new ImageIcon (GAI.images_path + "history.gif");
+	content_pane = (JPanel) this.getContentPane();
+
+	try {
+	    this.setSize(size);
+	    //create a menuBar
+	    menu_bar = new MenuBar(new MenuListenerImpl());
+	    this.setJMenuBar(menu_bar);
+	    
+	    //Create the tabbed pane and put it in the center
+	    tab_pane = new JTabbedPane();
+	    tab_pane.addChangeListener(this);
+	    
+	    //set up the Configuration Pane
+	    if (Configuration.get("admin.conf")){
+		conf_pane = new ConfPane();
+		conf_pane.display();
+		tab_pane.addTab("Configuration", CONF_ICON, conf_pane);
+		tab_pane.setEnabledAt(tab_pane.indexOfComponent(conf_pane),Configuration.get("admin.conf"));
+	    }
+	    	    
+	    //set up the ext Pane
+	    if (Configuration.get("admin.ext")){
+		ext_pane = new JPanel();
+		//ext_pane.display();
+		tab_pane.addTab("Exts", EXT_ICON, ext_pane);
+		tab_pane.setEnabledAt(tab_pane.indexOfComponent(ext_pane),Configuration.get("admin.ext"));
+	    }
+	    	    
+	    //set up the Monitor Pane
+	    if (Configuration.get("admin.monitor")){
+		monitor_pane = new JPanel();
+		//monitor_pane.display();
+		tab_pane.addTab("Monitor", MONITOR_ICON, monitor_pane);
+		tab_pane.setEnabledAt(tab_pane.indexOfComponent(monitor_pane),Configuration.get("admin.monitor"));
+	    }
+
+	    //set up the Log Pane
+	    if (Configuration.get("admin.log")){
+		log_pane = new LogPane();
+		log_pane.display();
+		tab_pane.addTab("Log", LOG_ICON, log_pane);
+		tab_pane.setEnabledAt(tab_pane.indexOfComponent(log_pane),Configuration.get("admin.log"));
+	    }   
+	    content_pane.setLayout(new BorderLayout());
+	    content_pane.add(tab_pane, BorderLayout.CENTER);
+	    pack();
+	    setVisible(true);
+	} catch (Exception e){
+	    e.printStackTrace();
+	    System.exit(1);
+	}
+    }
+
+    /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed 
+     *  when an action has occured. In this case we are listening to actions from the menu-bar, and should 
+     *  react appropriately.
+     * @param event An <strong>ActionEvent</strong> containing information about the action that has occured.
+     */
+    
+    public void actionPerformed (ActionEvent event){
+	Object esrc = event.getSource();
+	if (esrc == menu_bar.file_exit){
+	    if (conf_pane.configurationChanged()) {
+		// prompt users for save
+		int result = JOptionPane.showConfirmDialog((Component) null, "The Configuration files have been changed, do you want to save the change", "Save Confirmation", JOptionPane.YES_NO_OPTION);
+		if ( result == JOptionPane.YES_OPTION) {
+		    conf_pane.save();	
+		} 
+	    }
+	    exit();
+	}
+	else if (esrc == menu_bar.file_save){
+	    /* sliently and Globally save Project and Site configuration*/
+	    conf_pane.save();
+	}
+	else if (esrc == menu_bar.help_conf){
+	}
+	else if (esrc == menu_bar.help_ext){
+	} 
+	else if (esrc == menu_bar.help_monitor){
+	}
+	else if (esrc == menu_bar.help_log){
+	}
+	else if (esrc == menu_bar.help_about) {
+	}
+    }
+    
+    
+    public void destory (){
+	// Destroying create pane ensures the latest log has been closed
+	//if (status_pane != null) {
+	//}
+    }
+    /**Overridden from JFrame so we can exit safely when window is closed 
+     *(or destroyed). @param event A <strong>WindowEvent</strong> containing 
+     *information about the event that fired this call.
+     */
+    protected void processWindowEvent(WindowEvent event) {
+	if(event.getID() == WindowEvent.WINDOW_CLOSING) {
+	    exit();
+	}
+    }
+
+
+    /** Listens to actions upon the menu bar, and if it detects a click over 
+     *the help menu brings the help window to the front if it has become hidden.
+     */
+    private class MenuListenerImpl
+	implements MenuListener {
+	public void menuCanceled (MenuEvent e) {
+	}
+	
+	public void menuDeselected (MenuEvent e){
+	}
+	
+	public void menuSelected (MenuEvent e){
+	    if (e.getSource() == menu_bar.file_exit) {
+		exit();
+	    }
+	  
+	    if (e.getSource() == menu_bar.help){
+		if (menu_bar.help.isSelected()){
+		    menu_bar.help.doClick(10);
+		}
+	    }
+	}
+    }
+
+
+    /** This method ensures that all the things needing saving 
+     *  are saved before GAIManager.exit() is called.
+     */
+    public void exit() {
+	System.exit(0);
+    }
+
+
+    /** Any implementation of ChangeListener must include this method 
+     **so we can be informed when the state of one of the registered 
+     **objects changes. In this case we are listening to view changes 
+     **within the tabbed pane.
+     * @param event A ChangeEvent containing information about the event that fired this call.
+     */
+    public void stateChanged(ChangeEvent event) {
+	if(previous_pane != null) {
+	}
+	
+	//menu_bar.tabSelected(tab_pane.getSelectedIndex());
+	int selected_index = tab_pane.getSelectedIndex();
+	if (selected_index == tab_pane.indexOfComponent(log_pane)) {
+	    log_pane.gainFocus();
+	}
+	else if (selected_index == tab_pane.indexOfComponent(conf_pane)) {
+	    conf_pane.gainFocus();
+	}
+	previous_pane = (JPanel) tab_pane.getSelectedComponent();
+    }
+    
+    public void modeChanged (int mode){
+	if (log_pane != null){
+	    log_pane.modeChanged(mode);
+	}
+	if (conf_pane !=null) {
+	    conf_pane.modeChanged(mode);
+	}
+    }
+
+    //   public void refresh (int refresh_reason, boolean collection_loaded)
+    public void refresh () {
+	if (log_pane != null ){
+	}
+    }
+
+    public void returnToInitialPane(){
+	if (log_pane != null) {
+	    tab_pane.setSelectedComponent(log_pane);
+	}
+    }
+    public void wait(boolean waiting) {
+	Component glass_pane = getGlassPane();
+	if(waiting) {
+	    // Show wait cursor.
+	    //glass_pane.addMouseListener(mouse_blocker_listener);
+	    glass_pane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+	    glass_pane.setVisible(true);
+	}
+	else {
+	    // Hide wait cursor.
+	    glass_pane.setVisible(false);
+	    glass_pane.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+	    //glass_pane.removeMouseListener(mouse_blocker_listener);
+	}
+	glass_pane = null;
+    }
+
+    private class TabUpdater
+	implements Runnable {
+	private boolean ready = false;
+	private int conf_pos = -1;
+	private int ext_pos = -1;
+	private int monitor_pos = -1;
+	private int log_pos = -1;
+	private JTabbedPane tab_pane = null;
+	
+	public TabUpdater (JTabbedPane tab_pane, boolean ready){
+	    this.ready = ready;
+	    this.tab_pane = tab_pane;
+	    conf_pos = tab_pane.indexOfComponent(conf_pane);
+	    ext_pos = tab_pane.indexOfComponent(ext_pane);
+	    monitor_pos = tab_pane.indexOfComponent(monitor_pane);  
+	    log_pos = tab_pane.indexOfComponent(log_pane);
+	}
+	
+	public void run() {
+	    if (conf_pos != -1){
+		if (ready) {
+		    tab_pane.setEnabledAt (conf_pos,Configuration.get("admin.conf"));
+		} else {
+		    tab_pane.setEnabledAt (conf_pos,false);
+		}
+	    }
+	    if (ext_pos != -1){
+		if (ready) {
+		    tab_pane.setEnabledAt (ext_pos,Configuration.get("admin.ext"));
+		} else {
+		    tab_pane.setEnabledAt (ext_pos,false);
+		}
+	    }
+	    if (monitor_pos != -1){
+		if (ready) {
+		    tab_pane.setEnabledAt (monitor_pos,Configuration.get("admin.monitor"));
+		} else {
+		    tab_pane.setEnabledAt (monitor_pos,false);
+		}
+	    }
+	    if (log_pos != -1){
+		if (ready) {
+		    tab_pane.setEnabledAt (log_pos,Configuration.get("admin.log"));
+		} else {
+		    tab_pane.setEnabledAt (log_pos,false);
+		}
+	    }
+	}
+	public void setReady (boolean ready){
+
+	    this.ready = ready;
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/config.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/config.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/config.xml	(revision 13928)
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE Configuration [
+  <!ELEMENT Configuration  (GathererConfig, Other, DirectoryMappings, Associations)>
+  <!ELEMENT GathererConfig (Argument*)>
+  <!ELEMENT Argument       (#PCDATA)>
+  <!ATTLIST Argument
+            name           CDATA #REQUIRED>
+  <!ELEMENT Other          (Info*)>
+  <!ELEMENT Info           (Name, Desc, Arguments)>
+  <!ELEMENT Arguments      (Option*)>
+  <!ELEMENT Option         (Name, Desc, Type, Required, Default?, List?)>
+  <!ELEMENT Type           (#PCDATA)>
+  <!ELEMENT Required       (#PCDATA)>
+  <!ELEMENT Default        (#PCDATA)>
+  <!ELEMENT List           (Value*)>
+  <!ELEMENT Value          (Name, Desc?)>
+  <!ELEMENT Name           (#PCDATA)>
+  <!ELEMENT Desc           (#PCDATA)>
+  <!ELEMENT DirectoryMappings (Mapping*)>
+  <!ELEMENT Mapping           (#PCDATA)>
+  <!ATTLIST Mapping 
+            name              CDATA #REQUIRED
+	    file              CDATA #REQUIRED>
+  <!ELEMENT Associations (Entry*)>
+  <!ELEMENT Entry (#PCDATA)>
+  <!ATTLIST Entry
+            extension CDATA #REQUIRED>
+]>
+
+<Configuration version="2.53a">
+  <GathererConfig>
+    <!-- ***** General Options: apply globally to the GAI execution. ***** -->
+    <!-- The location and size of the main Gatherer window. -->
+    <Argument name="general.bounds">0, 0, 800, 600</Argument>
+    <!-- Are we expected to produce a debug file. Can be overidden at start up. default = [false] -->
+    <Argument name="general.debug">false</Argument>
+    <!-- The standard font used in the Gatherer. [Verdana, BOLD, 12] -->
+    <Argument name="general.font">Verdana, BOLD, 12</Argument>
+    <Argument name="general.library_url"/>
+    <Argument name="general.locale">en_NZ</Argument>
+    <!-- How many folders deep should we recurse before suspecting a cyclic path? [40] -->
+    <Argument name="general.max_folder_depth">40</Argument>
+    <!-- The mode controls what level a detail is presented to the user - ranging from a basic, no regex, no perl experience up to complete details for all processes. The values, ranging from lowest to highest detail, are: 1 = Assistant, 2 = Librarian, 3 = Systems, 4 = Expert [default 2]-->
+    <Argument name="general.mode">2</Argument>
+    <Argument name="general.open_collection"></Argument>
+    <!-- The application launching command used when previewing the collection. [default -blank-] -->
+    <Argument name="general.preview_program"></Argument>
+    <Argument name="general.proxy_host"></Argument>
+    <Argument name="general.proxy_port"></Argument>
+    <Argument name="general.show_file_size">false</Argument>
+    <!-- Do we expect to connect to the internet via a proxy server. [false] -->
+    <Argument name="general.use_proxy">false</Argument>
+    <Argument name="general.view_extracted_metadata">true</Argument>
+
+    <!-- Colouring -->
+    <Argument name="coloring.button_background">218, 237, 252</Argument>
+    <Argument name="coloring.button_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.button_selected_background">128, 180, 216</Argument>
+    <Argument name="coloring.button_selected_foreground">255, 255, 255</Argument>
+    <Argument name="coloring.collection_heading_background">176, 208, 176</Argument>  
+    <Argument name="coloring.collection_heading_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.collection_selection_background">128, 180, 216</Argument>
+    <Argument name="coloring.collection_selection_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.collection_tree_background">224, 240, 224</Argument>
+    <Argument name="coloring.collection_tree_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.collection_noneditable_background">192, 192, 192</Argument>
+    <Argument name="coloring.collection_noneditable_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.disabled">206, 206, 206</Argument>
+    <Argument name="coloring.editable_background">255, 255, 255</Argument>
+    <Argument name="coloring.editable_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.error_background">255, 0, 0</Argument>
+    <Argument name="coloring.error_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.scrollbar_background">192, 192, 192</Argument>
+    <Argument name="coloring.scrollbar_foreground">255, 255, 255</Argument>
+    <Argument name="coloring.workspace_heading_background">128, 180, 216</Argument>
+    <Argument name="coloring.workspace_heading_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.workspace_selection_background">176, 208, 176</Argument>
+    <Argument name="coloring.workspace_selection_foreground">0, 0, 0</Argument>
+    <Argument name="coloring.workspace_tree_background">218, 237, 252</Argument>
+    <Argument name="coloring.workspace_tree_foreground">0, 0, 0</Argument>
+
+    <!-- Mirroring -->
+    <!-- Mirroring has many particular options. These show the default settings. -->
+   <!-- <Argument name="mirroring.depth">0</Argument>
+    <Argument name="mirroring.no_parents">true</Argument>
+    <Argument name="mirroring.other_hosts">false</Argument>
+    <Argument name="mirroring.overwrite">false</Argument>
+    <Argument name="mirroring.page_requisites">true</Argument>
+    <Argument name="mirroring.quiet">true</Argument>
+    <Argument name="mirroring.remove_failed">false</Argument>-->
+
+    <!-- Warnings -->
+    <!-- Warnings can be disabled by the user. -->
+    <Argument name="warning.CollectionBuilt">true</Argument>
+    <Argument name="warning.DirectoryLevelMetadata">true</Argument>
+    <Argument name="warning.ExtractedMetadata">true</Argument>
+    <Argument name="warning.InheritedMetadata">true</Argument>
+    <Argument name="warning.MissingEXEC">true</Argument>
+    <Argument name="warning.MissingGSDL">true</Argument>
+    <Argument name="warning.MissingPERL">true</Argument>
+    <Argument name="warning.MissingWGET">true</Argument>
+    <Argument name="warning.NoMetadataSetsSelected">true</Argument>
+    <Argument name="warning.NoPluginExpectedToProcessFile">true</Argument>
+    <Argument name="warning.OldWGET">true</Argument>
+    <Argument name="warning.TitleClashes">true</Argument>
+
+    <!-- Workflow -->
+    <!-- Disabling a view here will cause it to be hidden from the Gatherer display. -->
+    <Argument name="admin.conf">true</Argument>
+    <Argument name="admin.ext">true</Argument> 
+    <Argument name="admin.monitor">true</Argument>
+    <Argument name="admin.log">true</Argument> 
+
+    <Argument name="GEMS.Preferences.Selected_Languages">en</Argument>
+  </GathererConfig>
+
+  <Other/>
+  <DirectoryMappings/>
+  <Associations>
+    <Entry extension="doc"/>
+    <Entry extension="gif"/>
+    <Entry extension="htm"/>
+    <Entry extension="html"/>
+    <Entry extension="jpg"/>
+    <Entry extension="jpeg"/>
+    <Entry extension="pdf"/>
+    <Entry extension="png"/>
+    <Entry extension="ps"/>
+    <Entry extension="rtf"/>
+    <Entry extension="txt"/>
+    <Entry extension="text"/>
+  </Associations>
+</Configuration>
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/ClearLogFilePrompt.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/ClearLogFilePrompt.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/ClearLogFilePrompt.java	(revision 13928)
@@ -0,0 +1,124 @@
+/**
+ *#########################################################################
+ *
+ * A component of the GAI application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ * Modified by: Chi-Yu Huang
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.admin.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.net.*;
+import javax.swing.*;
+import javax.swing.event.*;
+
+/*import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.LocalLibraryServer;
+import org.greenstone.gatherer.collection.BasicCollectionConfiguration;
+import org.greenstone.gatherer.file.WorkspaceTree;  // !!! Don't like this here
+import org.greenstone.gatherer.util.ArrayTools;
+import org.greenstone.gatherer.util.StaticStrings;*/
+
+
+/** This class provides the functionality to delete current collections from the 
+ ** GSDLHOME/collect/ directory. The user chooses the collection from a list, where 
+ ** each entry also displays details about itself, confirms the delete of a collection 
+ ** by checking a checkbox then presses the ok button to actually delete the collection.
+ * @author Chi-Yu Huang, Greenstone Digital Library, University of Waikato
+ * @version 1.0
+ */
+public class ClearLogFilePrompt 
+	extends JDialog {
+    
+    /** A reference to ourself so any inner-classes can dispose of us. */
+    private ClearLogFilePrompt prompt = null;
+    private File log_file = null;
+
+    //A flag showing the deleting status
+    private boolean current_logfile_cleared = false;
+
+    /** The size of the delete prompt screen. */
+    static final Dimension SIZE = new Dimension(500, 500);
+
+    // Constructor.
+    public ClearLogFilePrompt() {
+	super();
+	prompt = this;
+    }
+    
+    /** Destructor. */
+    public void destroy() {
+	prompt = null;
+    }
+
+    /** This method causes the Clear Confirmation Dialog to be displayed. 
+     * returns true if it has deleted the log file that is currently open */
+    public boolean display(File log_file) {
+	int result = JOptionPane.showConfirmDialog((Component) null, "Do you really want to clear this log file", "Clear Confirmation", JOptionPane.YES_NO_OPTION);
+	if ( result == JOptionPane.YES_OPTION) {
+	    log_file.delete();
+	    try {
+		log_file.createNewFile();
+	    } catch (Exception e) {
+		e.printStackTrace();
+	    }	     
+	    current_logfile_cleared = true;
+	} else if (result == JOptionPane.NO_OPTION) {
+	    current_logfile_cleared = false;
+	    JOptionPane.showMessageDialog(prompt, "Cancel clearing the " + log_file.getPath() +" log file");
+	    prompt.dispose();
+	}
+	return current_logfile_cleared;
+    }
+    
+    
+    /** Shows a delete complete prompt. 
+     * @param success A <strong>boolean</strong> indicating if the collection was successfully deleted.
+     * @see org.greenstone.gatherer.collection.Collection
+     */
+    /*public void resultPrompt(boolean success) {
+	if (success) {
+	    JOptionPane.showMessageDialog(prompt,"Selected log file has been deleted. You have to restart the action to create the log file");
+	} else {
+	    JOptionPane.showMessageDialog(prompt, "Cancel deleting the log file");
+	}
+	}*/
+    
+    /** Any implementation of ActionListener requires this method so that when an 
+     **action is performed the appropriate effect can occur.*/
+    public void actionPerformed(ActionEvent event) {
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/ConfPane.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/ConfPane.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/ConfPane.java	(revision 13928)
@@ -0,0 +1,940 @@
+/**
+ *#########################################################################
+ *
+ * A component of the GAI application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Chi-Yu Huang, Greenstone Digital Library, University of Waikato
+ * Modified: 03.2005
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.admin.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Enumeration;
+import java.lang.Object;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.tree.*;
+import javax.swing.table.*;
+import java.awt.event.MouseEvent;
+import java.net.*;
+import java.sql.*;
+
+import org.greenstone.admin.GAI;
+import org.greenstone.admin.GAIManager;
+import org.greenstone.admin.Configuration;
+import org.greenstone.admin.gui.ThreadControl;
+//import org.greenstone.admin.gui.ConfSettingTableModel;
+import org.greenstone.admin.gui.SiteConfSetting;
+import org.greenstone.core.ParsingProgress;
+import org.greenstone.gsdl3.util.GSFile;
+
+/** The Configuration pane is to view the status of relevant configure files in GSIII
+ * @author Chi-Yu Huang, Greenstone Digital Library, University of Waikato
+ * @version
+ */
+public class ConfPane
+    extends JPanel
+    implements ActionListener {
+
+    /* The pane to demonstrate Configuration information, including the build property file
+     * being monitored and their content, and control functions */
+    protected JSplitPane main_conf_pane = null;
+    
+    protected JPanel main_contentPane = null;
+    public Hashtable conf_table;
+    
+    /** The panel that contains a Conf_list */
+    private JPanel confList_pane =  null;
+    
+    /** The panel that contains the conf content. */
+    private JPanel confContent_pane =  null;
+    private JScrollPane conf_table_pane = null;
+    
+    /** The List showing all the Configuration files concerned. */
+    private JList conf_list=null;
+    private JTree conf_tree = null;
+
+    /** The label at the top of the confList_pane. */
+    private JLabel confList_label =  null;
+    /** The label shown at the top of the confContent Pane. */
+    private JLabel confContent_label  =  null;
+
+    // The control buttons used to manipulate Configuration Pane
+    protected JPanel inner_button_pane = null;
+    protected JPanel inner_control_pane = null;
+    protected JPanel tomcat_button_pane = null;
+    protected JPanel mysql_button_pane = null;
+    protected JPanel setting_shown_pane = null;
+    
+    /**Buttons in inner button pane */
+    private JButton startup_tomcat_button = null;
+    private JButton shutdown_tomcat_button = null;
+    private JButton restart_tomcat_button = null;
+    private JButton startup_mysql_button = null;
+    private JButton shutdown_mysql_button = null;
+    private JButton restart_mysql_button = null;
+
+    private JButton save_button = null;
+
+    private JLabel conf_label = null;
+    private JLabel conf_setting_label = null;
+    
+    /* ConfPane empty AREA to show XML configuration file*/
+    //private JTextArea conf_xml_area = null;
+
+    //control tomcat and mysql server running status
+    private String tomcat_server;
+    private String tomcat_port;
+    private String mysql_adminuser;
+    private String mysql_server;
+    private String mysql_port;
+    private String conf_pane_name;
+  
+    private boolean tomcat_server_up = false;
+    private boolean mysql_server_up = false;
+
+    /** The scrollable area into which the configuration content is placed. */
+    //private JScrollPane conf_xml_content = null;
+    
+    public SiteConfSetting site_conf = null;
+    public SiteConfSetting interface_conf = null;
+
+    /** The various sizes for the screen layout*/
+    static private Dimension MIN_SIZE = new Dimension( 90,  90);
+    static private Dimension LIST_SIZE  = new Dimension(200, 450);
+    static private Dimension CONTENT_SIZE = new Dimension (600,450);
+    static private Dimension TABLE_SIZE = new Dimension(500,200);
+    static private int MINIMUM_TABLE_HEADER_SIZE = 15;
+    
+    private JTable conf_setting_table = null;
+
+    private int num_of_setting;
+
+    //The details display in the table
+    int display_row_count = 5;
+    int rowLength = 20;
+    int colLength = 3;
+    private Object[][] conf_display = new Object [rowLength][colLength];
+    private Object[][] conf_setting;
+    
+    //An array to store all the details in the build.properties file
+    private ArrayList conf_array;
+    
+    //Site configuration
+    // TODO!! there are more than one site and interface - need to extend this
+    public File site_conf_file = new File(GSFile.siteConfigFile(GSFile.siteHome(GAI.gsdl3_web_home, "localsite")));
+    public File interface_conf_file = new File(GSFile.interfaceConfigFile(GSFile.interfaceHome(GAI.gsdl3_web_home, "default")));
+    public boolean  project_conf_changed = false;
+
+    ConfSettingTableModel conf_table_model = null;
+    DefaultMutableTreeNode top = new DefaultMutableTreeNode("Configuration Files");
+    //Constructor
+    public ConfPane() {
+	conf_table = new Hashtable();
+	// create all the control button panes
+	inner_control_pane = new JPanel();
+	inner_button_pane = new JPanel();
+	tomcat_button_pane = new JPanel();
+	mysql_button_pane = new JPanel();
+	
+	/*the class for showing the site configurations including
+	 * siteConfig.xml and interfaceConfig.xml
+	 */
+	site_conf = new SiteConfSetting("siteConfig", site_conf_file);
+	interface_conf =  new SiteConfSetting("interfaceConfig", interface_conf_file);
+	
+	// Main Configuration Pane
+	main_conf_pane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
+       	// Main pane for Configuration Content Pane
+	main_contentPane = new JPanel();
+	
+	//Create a tree for a list Configuration files we are interested
+	//DefaultMutableTreeNode child1 = new DefaultMutableTreeNode();
+	DefaultMutableTreeNode child1 = new DefaultMutableTreeNode("Project Configuration");
+
+	DefaultMutableTreeNode compile = new DefaultMutableTreeNode("Compile");
+	DefaultMutableTreeNode tomcat = new DefaultMutableTreeNode("Tomcat");
+	DefaultMutableTreeNode proxy = new DefaultMutableTreeNode("Proxy");
+	DefaultMutableTreeNode mysql = new DefaultMutableTreeNode("MySQL");	
+	DefaultMutableTreeNode gsdl = new DefaultMutableTreeNode("GSDL");
+	child1.add(compile);
+	child1.add(tomcat);
+	child1.add(proxy);
+	child1.add(mysql);
+	child1.add(gsdl);
+
+	DefaultMutableTreeNode child2 = new DefaultMutableTreeNode("Site Configuration");
+	//DefaultMutableTreeNode child2 = new DefaultMutableTreeNode();	
+	DefaultMutableTreeNode siteConf = new DefaultMutableTreeNode("SiteConfig");
+	DefaultMutableTreeNode interfaceConf = new DefaultMutableTreeNode("InterfaceConfig");
+	child2.add(siteConf);
+	child2.add(interfaceConf);
+
+	//DefaultMutableTreeNode child3 = new DefaultMutableTreeNode("Conf 3");
+	top.add(child1);
+	top.add(child2);
+	//top.add(child3);
+	conf_tree = new JTree(top);
+	conf_tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+	conf_tree.addTreeSelectionListener(new ConfTreeListener());
+
+	// inner button_pane Buttons
+	StartupTomcatButtonListener stbl = new StartupTomcatButtonListener();
+	ShutdownTomcatButtonListener stdbl = new ShutdownTomcatButtonListener();
+	RestartTomcatButtonListener rtbl = new RestartTomcatButtonListener();
+
+	StartupMysqlButtonListener smbl = new StartupMysqlButtonListener();
+	ShutdownMysqlButtonListener smdbl = new ShutdownMysqlButtonListener();
+	RestartMysqlButtonListener rmbl = new RestartMysqlButtonListener();
+		
+	ImageIcon startupTomcatButtonIcon = new ImageIcon(GAI.images_path + "redo.gif");
+	ImageIcon shutdownTomcatButtonIcon = new ImageIcon(GAI.images_path + "stop.gif");
+	ImageIcon restartTomcatButtonIcon = new ImageIcon(GAI.images_path + "stop.gif");
+	
+	ImageIcon startupMysqlButtonIcon = new ImageIcon(GAI.images_path + "redo.gif");
+	ImageIcon shutdownMysqlButtonIcon = new ImageIcon(GAI.images_path + "stop.gif");
+	ImageIcon restartMysqlButtonIcon = new ImageIcon(GAI.images_path + "stop.gif");
+	ImageIcon saveButtonIcon = new ImageIcon(GAI.images_path  + "save.gif");
+
+	startup_tomcat_button = new JButton();	
+	startup_tomcat_button.addActionListener(stbl);
+	startup_tomcat_button.setMnemonic(KeyEvent.VK_S);
+	startup_tomcat_button.setEnabled(false);
+	startup_tomcat_button.setText(GAI.dictionary.get("ConfPane.Tomcat_Startup"));
+	startup_tomcat_button.setToolTipText(GAI.dictionary.get("ConfPane.Tomcat_Startup_Tooltip"));
+
+	shutdown_tomcat_button = new JButton();
+	shutdown_tomcat_button.addActionListener(stdbl);
+	shutdown_tomcat_button.setEnabled(false);
+	shutdown_tomcat_button.setText(GAI.dictionary.get("ConfPane.Tomcat_Shutdown"));
+	shutdown_tomcat_button.setToolTipText(GAI.dictionary.get("ConfPane.Tomcat_Shutdown_Tooltip"));
+
+	restart_tomcat_button = new JButton();
+	restart_tomcat_button.addActionListener(rtbl);
+	restart_tomcat_button.setEnabled(false);
+	restart_tomcat_button.setText(GAI.dictionary.get("ConfPane.Tomcat_Restart"));
+	restart_tomcat_button.setToolTipText(GAI.dictionary.get("ConfPane.Tomcat_Restart_Tooltip"));
+
+	startup_mysql_button = new JButton();
+	startup_mysql_button.addActionListener(smbl);
+	startup_mysql_button.setMnemonic(KeyEvent.VK_S);
+	startup_mysql_button.setEnabled(false);
+	startup_mysql_button.setText(GAI.dictionary.get("ConfPane.MySQL_Startup"));
+	startup_mysql_button.setToolTipText(GAI.dictionary.get("ConfPane.MySQL_Startup_Tooltip"));
+
+	shutdown_mysql_button = new JButton();
+	shutdown_mysql_button.addActionListener(smdbl);
+	shutdown_mysql_button.setEnabled(false);
+	shutdown_mysql_button.setText(GAI.dictionary.get("ConfPane.MySQL_Shutdown"));
+	shutdown_mysql_button.setToolTipText(GAI.dictionary.get("ConfPane.MySQL_Shutdown_Tooltip"));
+	
+	restart_mysql_button = new JButton();
+	restart_mysql_button.addActionListener(rmbl);
+	restart_mysql_button.setEnabled(false);
+	restart_mysql_button.setText(GAI.dictionary.get("ConfPane.MySQL_Restart"));
+	restart_mysql_button.setToolTipText(GAI.dictionary.get("ConfPane.MySQL_Restart_Tooltip"));
+
+	//tomcat control buttons
+	stbl = null;
+	stdbl = null;
+	rtbl = null;
+	
+	//mysql control button
+	smbl = null;
+	smdbl = null;
+	rmbl = null;
+	
+	//read in build properties
+	getConfContent();
+    }
+
+    /** Any implementation of ActionListener requires this method so that when an 
+     **action is performed the appropriate effect can occur.*/
+    public void actionPerformed(ActionEvent event) {
+    }
+    
+    
+    /** This method is called to actually layout the components.*/
+    public void display() {
+	//Create Components.
+	//KeyListenerImpl key_listener = new KeyListenerImpl();
+	//MouseListenerImpl mouse_listener = new MouseListenerImpl();
+	//this.addKeyListener(key_listener);
+	
+	//confList_Pane
+	confList_pane = new JPanel();
+	confList_pane.setBorder(BorderFactory.createLoweredBevelBorder());
+	confList_pane.setPreferredSize(LIST_SIZE);
+	confList_pane.setSize(LIST_SIZE);
+	confList_pane.setBackground(Configuration.getColor("coloring.workspace_selection_background"));
+	confList_pane.setForeground(Configuration.getColor("coloring.workspace_selection_foreground"));
+	
+	confList_label = new JLabel();
+	confList_label.setOpaque(true);
+	confList_label.setBackground(Configuration.getColor("coloring.workspace_selection_background"));
+	confList_label.setForeground(Configuration.getColor("coloring.workspace_selection_foreground"));
+	confList_label.setText(GAI.dictionary.get("ConfPane.Conf_List"));
+
+	// confContent_Pane
+	confContent_pane = new JPanel();
+	confContent_pane.setBorder(BorderFactory.createEmptyBorder(10,20,10,20));
+	confContent_pane.setBackground(Configuration.getColor("coloring.workspace_selection_background"));
+	confContent_pane.setForeground(Configuration.getColor("coloring.workspace_selection_foreground"));
+
+	confContent_label = new JLabel();
+	confContent_label.setOpaque(true);
+	confContent_label.setBackground(Configuration.getColor("coloring.workspace_selection_background"));
+	confContent_label.setForeground(Configuration.getColor("coloring.workspace_selection_foreground"));
+	confContent_label.setText(GAI.dictionary.get("ConfPane.Conf_Content"));
+		
+	conf_table_model = new ConfSettingTableModel();
+	conf_setting_table = new JTable(conf_table_model){
+		public String getToolTipText(MouseEvent e){
+		    String tip = null;
+		    Point p = e.getPoint();
+		    int rowIndex = rowAtPoint(p);
+		    int colIndex = columnAtPoint(p);
+		    int realColumnIndex = convertColumnIndexToModel(colIndex);
+		    if (realColumnIndex == 0){
+			tip = conf_display[rowIndex][realColumnIndex].toString();
+		    } else {
+			tip = super.getToolTipText(e);
+		    }
+		    return tip;
+		}
+		public Component prepareRenderer (TableCellRenderer renderer, 
+						  int rowIndex, int colIndex){
+		    Component c = super.prepareRenderer(renderer, rowIndex, colIndex);
+		    if (colIndex == 0) {
+			c.setBackground(Configuration.getColor("coloring.table_noneditable_background"));
+		    } else {
+			c.setBackground(Configuration.getColor("coloring.table_editable_background"));
+		    }
+		    return c;
+		}
+	    };
+	
+	//When the MySQL and TOMCAT servers are still running and detect double-clicking occuring (editing mode)
+	conf_setting_table.addMouseListener(new MouseAdapter(){
+		public void mouseClicked(MouseEvent e){
+		    if (e.getClickCount() == 2){ 
+			if (conf_pane_name.matches("MYSQL")){
+			    mysql_server_up = false;
+			    mysql_server_up = checkMysqlServer();
+			    if (mysql_server_up) {
+				JOptionPane.showMessageDialog((Component) null,"MySQL is running, shutdown the MySQL server before making any changes");
+			    }
+			}
+			if (conf_pane_name.matches("TOMCAT")){
+			    tomcat_server_up = false;
+			    tomcat_server_up = checkTomcatServer();
+			    if (tomcat_server_up) {
+				JOptionPane.showMessageDialog((Component) null,"TOMCAT is running, shutdown the TOMCAT server before making any changes");
+			    }
+			}	
+		    }
+		}
+	    });
+	conf_setting_table.addKeyListener(new KeyAdapter(){
+		public void keyPressed(KeyEvent ke){
+		    if (ke.getKeyCode() == KeyEvent.VK_F2){ 
+			if (conf_pane_name.matches("MYSQL")){
+			    mysql_server_up = checkMysqlServer();
+			    if (mysql_server_up) {
+				JOptionPane.showMessageDialog((Component) null,"MySQL is running, shutdown the MySQL server before making any changes");
+			    }
+			}
+			if (conf_pane_name.matches("TOMCAT")){
+			    tomcat_server_up = checkTomcatServer();
+			    if (tomcat_server_up) {
+				JOptionPane.showMessageDialog((Component) null,"TOMCAT is running, shutdown the TOMCAT server before making any changes");
+			    }
+			}
+		    }
+		}
+	    });
+	
+	//Set up tableHeader
+	JTableHeader table_header = conf_setting_table.getTableHeader();
+	Dimension table_header_preferred_size = table_header.getPreferredSize();
+	if (table_header_preferred_size.height < MINIMUM_TABLE_HEADER_SIZE) {
+	    table_header_preferred_size.setSize(table_header_preferred_size.width, MINIMUM_TABLE_HEADER_SIZE);
+	    table_header.setPreferredSize(table_header_preferred_size);
+	}
+
+	table_header.setFont(new Font("Arial", Font.BOLD, 13));
+	conf_setting_table.setRowHeight(30);
+	conf_table_pane = new JScrollPane(conf_setting_table);
+	conf_table_pane.setVisible(false);
+	conf_table_pane.getViewport().setBackground(Configuration.getColor("coloring.collection_tree_background"));
+	
+	// Layout Components
+	confList_pane.setLayout(new BorderLayout());
+	JScrollPane conf_treeView = new JScrollPane(conf_tree);
+	confList_pane.add(conf_treeView, BorderLayout.CENTER);
+	confList_pane.add(confList_label, BorderLayout.NORTH);
+	confContent_pane.setLayout(new BorderLayout());
+	confContent_pane.add(conf_table_pane, BorderLayout.CENTER);
+	
+	inner_button_pane.setLayout(new GridLayout(1,2));
+	inner_control_pane.setLayout (new BorderLayout());
+	inner_control_pane.setBorder(BorderFactory.createEmptyBorder(5,10,5,10));
+	inner_control_pane.setPreferredSize(new Dimension(50,50));
+	inner_control_pane.setSize(new Dimension(50,50));
+	inner_control_pane.add (inner_button_pane, BorderLayout.CENTER);
+	
+	main_contentPane.setLayout (new BorderLayout());
+	main_contentPane.add(confContent_label, BorderLayout.NORTH);
+	main_contentPane.add(confContent_pane, BorderLayout.CENTER);
+	main_contentPane.add(inner_control_pane, BorderLayout.SOUTH);
+	main_conf_pane.add(confList_pane, JSplitPane.LEFT);
+	main_conf_pane.add(main_contentPane, JSplitPane.RIGHT);
+	main_conf_pane.setDividerLocation(LIST_SIZE.width - 10);
+	
+	this.setLayout(new BorderLayout());
+	this.add(main_conf_pane, BorderLayout.CENTER);
+    }
+
+    public void save() {
+	if (project_conf_changed) {
+	    saveProjectConf(GAI.build_properties_file);
+	}
+	if (site_conf.confChanged()){
+	    site_conf.saveFile(site_conf_file);
+	}
+	if (interface_conf.confChanged()) {
+	    interface_conf.saveFile(interface_conf_file);
+	}
+	
+
+    }
+    
+    public boolean configurationChanged() {
+	return (project_conf_changed || site_conf.confChanged() ||
+		interface_conf.confChanged());
+
+    }
+
+    private class StartupTomcatButtonListener
+	implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    /*before startup Tomcat server, we want to make sure project and Site configuration 
+	     * files are saved*/
+	    if (project_conf_changed) {
+		saveProjectConf(GAI.build_properties_file);
+	    }
+	    /*boolean site_conf_changed = site_conf.confChanged();
+	    boolean interface_conf_changed=interface_conf.confChanged();
+	    if (site_conf_changed) {
+		site_conf.saveFile(site_conf_file);
+	    }
+	    if (interface_conf_changed) {
+		interface_conf.saveFile(interface_conf_file);
+		}*/
+	    tomcat_server_up = checkTomcatServer();
+	    if (!tomcat_server_up) {
+		ThreadControl threadControl = new ThreadControl();
+		Runnable startupTomcatThread = threadControl.new startupTomcatServer("start-tomcat");
+		new Thread(startupTomcatThread).start();
+		threadControl.destroy();
+		tomcat_server_up = true;
+		JOptionPane.showMessageDialog((Component) null,"Tomcat server has been Startup successfully!");  
+	    } else {
+		JOptionPane.showMessageDialog((Component) null,"Tomcat server is running");
+	    }
+	    changeTomcatButtonPane1();
+	}
+    }
+    
+    private class ShutdownTomcatButtonListener
+	implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    tomcat_server_up = checkTomcatServer();
+	    if (tomcat_server_up){
+		ThreadControl threadControl = new ThreadControl();
+		Runnable shutdownTomcatThread = threadControl.new shutdownTomcatServer("stop-tomcat");
+		new Thread(shutdownTomcatThread).start();
+		threadControl.destroy();
+		tomcat_server_up = false;
+		JOptionPane.showMessageDialog((Component) null, "Tomcat server has been shutted down !");
+	    } else {
+		JOptionPane.showMessageDialog((Component) null,"Tomcat server was not running!");
+	    }
+	    changeTomcatButtonPane2();
+	}
+    }
+    
+    private class RestartTomcatButtonListener
+	implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    //before we restart Tomcat server, we want to make sure the conf_pane settings are saved
+	    if (project_conf_changed) {
+		saveProjectConf(GAI.build_properties_file);
+	    }
+	    /*boolean site_conf_changed = site_conf.confChanged();
+	    boolean interface_conf_changed=interface_conf.confChanged();
+	    if (site_conf_changed) {
+		site_conf.saveFile(site_conf_file);
+	    }
+	    if (interface_conf_changed) {
+		interface_conf.saveFile(interface_conf_file);
+		}*/
+	    tomcat_server_up = checkTomcatServer();
+	    if (tomcat_server_up) {
+		ThreadControl threadControl = new ThreadControl();
+		Runnable restartTomcatThread = threadControl.new restartTomcatServer("restart-tomcat");
+ 		new Thread(restartTomcatThread).start();
+		threadControl.destroy();
+		tomcat_server_up = true;
+		JOptionPane.showMessageDialog((Component) null,"Tomcat server has been Restarted successfully!"); 
+	    } else {
+		JOptionPane.showMessageDialog((Component) null,"Tomcat server was not running!"); 
+	    }
+	}
+    }
+    
+    private class StartupMysqlButtonListener
+	implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    //before we startup the MySQL server, we want to make sure the Conf_pane settings are saved
+	    saveProjectConf(GAI.build_properties_file);
+	    mysql_server_up = checkMysqlServer();
+	    if (!mysql_server_up) {
+		ThreadControl threadControl = new ThreadControl();
+		Runnable startupMysqlThread = threadControl.new startupMysqlServer("start-mysql");
+		new Thread(startupMysqlThread).start();
+		threadControl.destroy();
+		mysql_server_up = true;
+		JOptionPane.showMessageDialog((Component) null,"MYSQL server has been Startup successfully!");  
+	    } else {
+		JOptionPane.showMessageDialog((Component) null,"MYSQL server has been running");  	
+	    }
+	    changeMysqlButtonPane1();
+	}
+    }  
+    
+    private class ShutdownMysqlButtonListener
+	implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    mysql_server_up = checkMysqlServer();
+	    if (mysql_server_up){
+		ThreadControl threadControl = new ThreadControl();
+		Runnable shutdownMysqlThread = threadControl.new shutdownMysqlServer("stop-mysql");
+		new Thread(shutdownMysqlThread).start();
+		threadControl.destroy();
+		JOptionPane.showMessageDialog((Component) null,"MYSQL server has been Shutdown successfully !");
+		mysql_server_up = false;
+	    } else {
+		JOptionPane.showMessageDialog((Component) null,"MYSQL server was not running!");
+	    }
+	    changeMysqlButtonPane2();
+	}
+    }
+    
+    private class RestartMysqlButtonListener
+	implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    saveProjectConf(GAI.build_properties_file);
+	    mysql_server_up = checkMysqlServer();
+	    if (mysql_server_up) {
+		ThreadControl threadControl = new ThreadControl();
+		Runnable restartMysqlThread = threadControl.new restartMysqlServer("restart-mysql");
+		new Thread(restartMysqlThread).start();
+		threadControl.destroy();
+		JOptionPane.showMessageDialog((Component) null,"MYSQL server has been Restarted successfully!");  
+		mysql_server_up = true;
+	    } else { 
+		JOptionPane.showMessageDialog((Component) null,"MYSQL server was not running!"); 
+	    }
+	}
+    }
+
+    // Save the configuration file globally,when click File->Save or restart (or startup) Tomcat and MySQl server
+    public void saveProjectConf(File file){
+    	String new_string;
+	Enumeration keys = conf_table.keys();
+	String key;
+	String value;
+	String filename = file.getPath();
+	while (keys.hasMoreElements()) {
+	    key = (String) keys.nextElement();
+	    value = (String) conf_table.get(key);
+	    for (int j=0 ; j < conf_array.size(); j++){
+		if (((String)conf_array.get(j)).startsWith(key.toLowerCase())){
+		    new_string = key+"="+value; 
+		    conf_array.set(j, new_string.toLowerCase());
+		}
+	    }
+	}
+
+	try {
+	    BufferedWriter conf_out = new BufferedWriter(new FileWriter(filename));
+	    for (int j=0 ; j < conf_array.size(); j++){
+		conf_out.write(conf_array.get(j).toString());
+		conf_out.newLine();
+	    }
+	    conf_out.close();
+	    getConfContent();
+	    project_conf_changed = false;
+	} catch (Exception e) {
+	    e.printStackTrace();
+	}
+    }
+
+    public boolean projectConfChanged() {
+	return project_conf_changed;
+    }
+
+    public void getConfContent(){
+	String filename = GAI.build_properties_file.getPath();
+	if (!GAI.build_properties_file.exists()){ 
+	    JOptionPane.showMessageDialog((Component) null,"Build property file does not exist");  
+	} else {
+	    readProjectConf(filename);
+	}
+    }
+    
+    /* Read build.properties file 
+     * @param
+     */
+    public void readProjectConf (String filename) {
+	String fileLine;
+	/*inside the array will store, the conf_setting[i][0]:Comment, 
+	 * conf_setting[i][1]:Para and conf_setting[i][2]:Value
+	 * conf_array[] store all the details from the build.properties*/
+	conf_array = new ArrayList();
+	conf_setting = new Object [rowLength][colLength];
+	try {
+	    BufferedReader conf_in = new BufferedReader(new FileReader(filename));
+	    int i = 0;
+	    while ((fileLine = conf_in.readLine()) != null) {
+		// This is an empty line
+		if (fileLine.matches("^\\s*$")) {
+		    // Do Nothing
+		} else if (fileLine.matches("##.+")){
+		    //This line shows the specific service for these conf setting
+		    conf_array.add(fileLine);
+		} else 	if (fileLine.matches("#.+")){
+		    //This line is Configuration Comment line
+		    conf_array.add(fileLine);
+		    conf_setting[i][0] = fileLine.substring(1); // use 1 to get rid of the # symbol.
+		} else if (!fileLine.matches("#.+") && !fileLine.matches("^\\s*$") ){
+		    //This line is Setting line
+		    int end_index = fileLine.indexOf("=");
+		    conf_setting[i][1] = fileLine.substring(0,end_index).toUpperCase();
+		    conf_setting[i][2] = fileLine.substring(end_index+1);
+		    conf_table.put(conf_setting[i][1], conf_setting[i][2]);
+		    i++; //calculat the number of settings
+		    conf_array.add(fileLine);
+		} else {
+		    // Wrong character in the line
+		}
+	    }
+	    num_of_setting = i;
+	    for (int j=0; j<num_of_setting; j++){
+		if (conf_setting[j][1].toString().matches("TOMCAT.SERVER")){
+		    tomcat_server = conf_setting[j][2].toString();
+		}
+		if (conf_setting[j][1].toString().matches("TOMCAT.PORT")){
+		    tomcat_port = conf_setting[j][2].toString();
+		}
+		if (conf_setting[j][1].toString().matches("MYSQL.ADMIN.USER")){
+		    mysql_adminuser = conf_setting[j][2].toString();
+		}
+		if (conf_setting[j][1].toString().matches("MYSQL.SERVER")){
+		    mysql_server = conf_setting[j][2].toString();
+		}
+		if (conf_setting[j][1].toString().matches("MYSQL.PORT")){
+		    mysql_port = conf_setting[j][2].toString();
+		}	
+	    }
+	    conf_in.close();
+	} catch (Exception e) {
+	    e.printStackTrace();
+	}
+    }
+    
+
+    public void clearTable (){
+	for (int i=0; i< rowLength; i++){
+	    conf_display[i][0] = "";
+	    conf_display[i][1] = "";
+	    conf_display[i][2] = "";
+	}
+    }
+
+    private boolean checkTomcatServer (){
+	try {
+	    if (tomcat_server != "" && tomcat_port != ""){
+		String http_string = "http://" + tomcat_server+":"+tomcat_port+"/";
+		URL tomcatURL = new URL(http_string);
+		HttpURLConnection tomcatConn = (HttpURLConnection) tomcatURL.openConnection();
+		tomcatConn.connect();
+		//necessary to get a Response, even if you don't care about contents
+		InputStream connIn = tomcatConn.getInputStream(); 
+		int pageStatus = tomcatConn.getResponseCode();
+		if (pageStatus == HttpURLConnection.HTTP_NOT_FOUND) {//404 error
+		    //Tomcat is not running
+		    tomcat_server_up = false;
+		} else {
+		    tomcat_server_up = true;
+		}  
+	    } else {
+		System.err.println("Either Tomcat server or Tomcat port was not set properly");
+	    }
+	} catch (Exception ex) {
+	    tomcat_server_up = false;
+	    System.err.println(ex.getMessage());
+	}
+	return tomcat_server_up;
+    }
+    
+    private boolean checkMysqlServer(){
+	Connection conn = null;
+	try {
+	    String mysql_userName ="gsdl3reader";
+	    String mysql_password = ""; 
+	    String mysql_url ="jdbc:mysql://"+mysql_server+":"+mysql_port+"/localsite_gs3mgdemo";
+	    //System.err.println("what is Mysql_URL:" + mysql_url);
+	    Class.forName("com.mysql.jdbc.Driver").newInstance();
+	    conn = DriverManager.getConnection(mysql_url, mysql_userName, mysql_password);
+	    if (conn == null) {
+		mysql_server_up =false;
+	    } else {
+		mysql_server_up = true;
+	    }
+	} catch (Exception e) {
+	    mysql_server_up = false;
+	    System.err.println("Cannot connect to database server");
+	}
+	return mysql_server_up;
+    }
+    
+    public class ConfSettingTableModel 
+	extends AbstractTableModel
+	{
+	String[] columnNames = {"Configuration Parameter",
+	"Configuration Value"};
+	
+	public int getColumnCount(){
+	return columnNames.length;
+	}
+	
+	public int getRowCount() {
+	return display_row_count;
+	}
+	
+	public String getColumnName(int col){
+	    
+	    return columnNames[col];
+	}
+	
+	public Object getValueAt(int row,int col){
+	    return conf_display[row][col+1];
+	}
+	
+	public boolean isCellEditable(int row, int col){
+	    if (col==0){
+		return false;
+	    } else if (conf_display[row][col].toString().matches("MYSQL.+")){
+		mysql_server_up = checkMysqlServer();
+		if (mysql_server_up) {
+		    return false;
+		}
+	    } else if (conf_display[row][col].toString().matches("TOMCAT.+")){
+	   	tomcat_server_up = checkTomcatServer();
+		if (tomcat_server_up) {
+		   return false;
+		}
+	    }
+	    return true;
+	}
+	
+	public void setValueAt(Object value, int row, int col){
+	    if (!isCellEditable(row, col))
+		return;
+	    conf_display[row][col+1] = value;
+	    project_conf_changed = true;
+	    //System.err.println("**ConfDisplay:" + conf_display[row][col].toString());
+	    conf_table.put(conf_display[row][col].toString(), value);
+	    fireTableCellUpdated(row,col+1);
+	    updateUI();
+	}
+    }
+
+    public int showProjectConf(String conf_param) {
+	conf_table_pane.setVisible(true);
+	clearPrevConfPane();
+	confContent_pane.add(conf_table_pane, BorderLayout.CENTER);
+	confContent_pane.revalidate();	
+	clearTable();
+	int j=0;
+	int row_count = 0;
+	for (int i=0; i< num_of_setting; i++){
+	    if (conf_setting[i][1].toString().matches("^("+ conf_param +").+")) {
+		row_count = row_count +1;
+		conf_display[j][0] = conf_setting[i][0];
+	    	conf_display[j][1] = conf_setting[i][1];
+	   	conf_display[j][2] = conf_table.get(conf_setting[i][1]);
+		j++;
+	    }
+	}
+	return row_count;
+    }
+      
+    public void displaySiteConf(SiteConfSetting site_conf_tmp){
+	clearPrevConfPane();
+	confContent_pane.add(site_conf_tmp, BorderLayout.CENTER);
+	try {
+	    site_conf_tmp.showText();
+	    site_conf_tmp.goTop();
+	    confContent_pane.revalidate();
+	} catch (Exception e) {
+	    e.printStackTrace();
+	}    
+     }
+    
+    public void clearPrevConfPane() {
+	confContent_pane.remove(conf_table_pane);
+	confContent_pane.remove(site_conf);
+	confContent_pane.remove(interface_conf);
+    }
+	
+   
+    private class ConfTreeListener implements TreeSelectionListener{
+	public void valueChanged (TreeSelectionEvent e){
+	    String option = conf_tree.getLastSelectedPathComponent().toString();
+	    conf_table_pane.setVisible(true);
+	    if (option == "Compile"){
+		conf_pane_name = "COMPILE";
+		display_row_count = showProjectConf(conf_pane_name);
+		inner_button_pane.removeAll();
+		inner_button_pane.setLayout(new GridLayout(1,3));
+	    } else if (option == "Tomcat"){
+		conf_pane_name ="TOMCAT";
+		display_row_count = showProjectConf(conf_pane_name);
+		//Setup Tomcat button control pane
+		inner_button_pane.removeAll();
+		inner_button_pane.setLayout(new GridLayout(1,3));
+		if (checkTomcatServer()) {
+		    changeTomcatButtonPane1();
+		} else {
+		    changeTomcatButtonPane2();
+		}
+	    } else if (option =="Proxy"){
+		conf_pane_name="PROXY";
+		display_row_count = showProjectConf(conf_pane_name);
+		//Setup Proxy button control pane
+		inner_button_pane.removeAll();
+		inner_button_pane.setLayout(new GridLayout(1,3));
+	    } else if (option == "MySQL"){
+		conf_pane_name="MYSQL";
+		display_row_count = showProjectConf(conf_pane_name);
+		// Setup MySQL button control pane
+		inner_button_pane.removeAll();
+		inner_button_pane.setLayout(new GridLayout(1,3));
+		if (checkMysqlServer()) {
+		    changeMysqlButtonPane1();
+		} else {
+		    changeMysqlButtonPane2();
+		}
+	    } else if (option == "GSDL"){
+		conf_pane_name ="GSDL";
+		display_row_count = showProjectConf(conf_pane_name);
+		inner_button_pane.removeAll();
+	    } else if (option == "SiteConfig"){
+		conf_pane_name = "SiteConfig";
+		inner_button_pane.removeAll();
+		displaySiteConf(site_conf);
+	    } else if (option == "InterfaceConfig") {
+		conf_pane_name = "InterfaceConfig";
+		inner_button_pane.removeAll();
+		displaySiteConf(interface_conf);
+	    }
+	    updateUI();
+	}
+    }
+
+    public void modeChanged (int mode){
+	return;
+    }
+
+    public void gainFocus() {
+	return;
+    }
+
+    public void changeTomcatButtonPane1 (){
+	inner_button_pane.removeAll();
+	inner_button_pane.setLayout(new GridLayout(1,2));
+	inner_button_pane.add(restart_tomcat_button);
+	inner_button_pane.add(shutdown_tomcat_button);
+	restart_tomcat_button.setEnabled (true);
+	shutdown_tomcat_button.setEnabled (true);
+	updateUI();
+    }
+    public void changeTomcatButtonPane2 (){
+	inner_button_pane.removeAll();
+	inner_button_pane.setLayout(new GridLayout(1,2));
+	inner_button_pane.add(startup_tomcat_button);
+	inner_button_pane.add(shutdown_tomcat_button);
+	startup_tomcat_button.setEnabled (true);
+	shutdown_tomcat_button.setEnabled (false);
+	updateUI();
+    }	
+    public void changeMysqlButtonPane1 (){
+	inner_button_pane.removeAll();
+	inner_button_pane.setLayout(new GridLayout(1,2));
+	inner_button_pane.add(restart_mysql_button);
+	inner_button_pane.add(shutdown_mysql_button);
+	restart_mysql_button.setEnabled (true);
+	shutdown_mysql_button.setEnabled (true);
+	updateUI();
+    }
+    public void changeMysqlButtonPane2 (){
+	inner_button_pane.removeAll();
+	inner_button_pane.setLayout(new GridLayout(1,2));
+	inner_button_pane.add(startup_mysql_button);
+	inner_button_pane.add(shutdown_mysql_button);
+	startup_mysql_button.setEnabled (true);
+	shutdown_mysql_button.setEnabled (false);
+	updateUI();
+    }	
+    public void afterDisplay(){
+	return;
+    }
+} 
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/DeleteLogFilePrompt.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/DeleteLogFilePrompt.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/DeleteLogFilePrompt.java	(revision 13928)
@@ -0,0 +1,120 @@
+/**
+ *#########################################################################
+ *
+ * A component of the GAI application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ * Modified by: Chi-Yu Huang
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.admin.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.net.*;
+import javax.swing.*;
+import javax.swing.event.*;
+
+/*
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.LocalLibraryServer;
+import org.greenstone.gatherer.collection.BasicCollectionConfiguration;
+import org.greenstone.gatherer.file.WorkspaceTree;  // !!! Don't like this here
+import org.greenstone.gatherer.util.ArrayTools;
+import org.greenstone.gatherer.util.StaticStrings;*/
+
+
+/** This class provides the functionality to delete current collections from the 
+ ** GSDLHOME/collect/ directory. The user chooses the collection from a list, where 
+ ** each entry also displays details about itself, confirms the delete of a collection 
+ ** by checking a checkbox then presses the ok button to actually delete the collection.
+ * @author Chi-Yu Huang, Greenstone Digital Library, University of Waikato
+ * @version 1.0
+ */
+public class DeleteLogFilePrompt 
+	extends JDialog {
+    
+    /** A reference to ourself so any inner-classes can dispose of us. */
+    private DeleteLogFilePrompt prompt = null;
+    private File log_file = null;
+
+    //A flag showing the deleting status
+    private boolean current_logfile_deleted = false;
+
+    /** The size of the delete prompt screen. */
+    static final Dimension SIZE = new Dimension(500, 500);
+
+    // Constructor.
+    public DeleteLogFilePrompt() {
+	super();
+	prompt = this;
+    }
+    
+    /** Destructor. */
+    public void destroy() {
+	prompt = null;
+    }
+
+    /** This method causes the Delete Confirmation Dialog to be displayed. 
+     * returns true if it has deleted the log file that is currently open */
+    public boolean display(File log_file) {
+	int result = JOptionPane.showConfirmDialog((Component) null, "Do you really want to delete this log file", "Delete Confirmation", JOptionPane.YES_NO_OPTION);
+	if ( result == JOptionPane.YES_OPTION) {
+	    log_file.delete();
+	    current_logfile_deleted = true;
+	    JOptionPane.showMessageDialog(prompt,log_file.getPath() + " log file has been deleted. You have to restart the action to create the log file");
+	} else if (result == JOptionPane.NO_OPTION) {
+	    current_logfile_deleted = false;
+	    JOptionPane.showMessageDialog(prompt, "Cancel deleting the " + log_file.getPath() +" log file");
+	    prompt.dispose();
+	}
+	return current_logfile_deleted;
+    }
+    
+    
+    /** Shows a delete complete prompt. 
+     * @param success A <strong>boolean</strong> indicating if the collection was successfully deleted.
+     * @see org.greenstone.gatherer.collection.Collection
+     */
+    /*public void resultPrompt(boolean success) {
+	if (success) {
+	    JOptionPane.showMessageDialog(prompt,"Selected log file has been deleted. You have to restart the action to create the log file");
+	} else {
+	    JOptionPane.showMessageDialog(prompt, "Cancel deleting the log file");
+	}
+	}*/
+    
+    /** Any implementation of ActionListener requires this method so that when an 
+     **action is performed the appropriate effect can occur.*/
+    public void actionPerformed(ActionEvent event) {
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/LogPane.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/LogPane.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/LogPane.java	(revision 13928)
@@ -0,0 +1,378 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Chi-Yu Huang, Greenstone Digital Library, University of Waikato
+ * Modified: 03.2005
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.admin.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.tree.*;
+
+import org.greenstone.admin.GAIManager;
+import org.greenstone.admin.GAI;
+import org.greenstone.admin.Configuration;
+
+/** The Log pane is to view the status of relevant log files in GSIII
+ * @author Chi-Yu Huang, Greenstone Digital Library, University of Waikato
+ * @version
+ */
+public class LogPane
+    extends JPanel
+    implements ActionListener {
+
+    /* The pane to demonstrate log information, including  the log files being 
+     *monitored and their content*/
+    protected JSplitPane main_log_pane = null;
+
+    /** The panel that contains a log_list */
+    private JPanel logList_pane =  null;
+
+    /** The panel that contains the log content. */
+    private JPanel logContent_pane =  null;
+
+    /** The List showing all the log files concerned. */
+    private JList log_list=null;
+
+    /** The scrollable area into which the log content is placed. */
+    private JScrollPane log_content = null;
+
+    /** The label at the top of the logList_pane. */
+    private JLabel logList_label =  null;
+
+    /** The label shown at the top of the logContent Pane. */
+    private JLabel logContent_label  =  null;
+
+    /* Log TEXT AREA*/
+    private JTextArea log_textarea = null;
+
+    // The control buttons used to manipulate log Pane
+    protected JPanel button_pane = null;
+    
+    /** Buttons */
+    private JButton reload_button = null;
+    private JButton clear_button = null;
+
+    /*The pane which contains the controls for log files */
+    private JPanel control_pane = null;
+
+    private File log_file = null;
+      
+    /** The various sizes for the screen layout*/
+    static private Dimension MIN_SIZE = new Dimension( 90,  90);
+    static private Dimension LIST_SIZE  = new Dimension(200, 450);
+    static private Dimension LOGPANE_SIZE = new Dimension (800,450);
+
+    //Constructor
+    public LogPane() {
+	
+	// create all the necessary panes
+	control_pane = new JPanel();
+	button_pane = new JPanel();
+
+	// Log_Pane
+	main_log_pane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
+	main_log_pane.setPreferredSize(LOGPANE_SIZE);
+	//log_pane.setSize(LOGPANE_SIZE);
+	
+	// Log_list
+	String[] log_files = { "Tomcat log file", "Log file 2", "Log file 3"};
+	log_list = new JList(log_files);
+	log_list.setBorder(BorderFactory.createLoweredBevelBorder());
+	log_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+	log_list.setVisibleRowCount(4);
+	log_list.setBackground (Configuration.getColor("coloring.workspace_tree_background"));
+	log_list.setForeground (Configuration.getColor("coloring.workspace_tree_foreground"));
+	log_list.addListSelectionListener(new LogListListener());
+	
+	// Log_TextArea
+	log_textarea = new JTextArea();
+	log_textarea.setEditable(false);
+		
+	// Buttons
+	ReloadButtonListener rbl = new ReloadButtonListener();
+	ClearButtonListener dbl = new ClearButtonListener();
+	ImageIcon reloadButtonIcon = new ImageIcon(GAI.images_path + "toolbarButtonGraphics/general/Refresh16.gif");
+	ImageIcon clearButtonIcon = new ImageIcon(GAI.images_path + "toolbarButtonGraphics/general/Delete16.gif");
+
+	//reload_button = new JButton("Reload", reloadButtonIcon);
+	reload_button = new JButton();
+	reload_button.addActionListener(rbl);
+	reload_button.setEnabled(false);
+	reload_button.setMnemonic(KeyEvent.VK_R);
+	reload_button.setText(GAI.dictionary.get("LogPane.Reload_Log"));
+	reload_button.setToolTipText(GAI.dictionary.get("LogPane.Reload_Log_Tooltip"));
+
+	clear_button = new JButton();
+	clear_button.addActionListener(dbl);
+	clear_button.setEnabled(false);
+	clear_button.setMnemonic(KeyEvent.VK_C);
+	clear_button.setText(GAI.dictionary.get("LogPane.Clear_Log"));
+	clear_button.setToolTipText(GAI.dictionary.get("LogPane.Clear_Log_Tooltip"));
+
+	rbl = null;
+	dbl = null;
+    }
+
+    /** Any implementation of ActionListener requires this method so that when an 
+     **action is performed the appropriate effect can occur.*/
+
+    public void actionPerformed(ActionEvent event) {
+    }
+
+
+    /** This method is callsed to actually layout the components.*/
+    public void display() {
+	// Create Components.
+	//KeyListenerImpl key_listener = new KeyListenerImpl();
+	//MouseListenerImpl mouse_listener = new MouseListenerImpl();
+	//this.addKeyListener(key_listener);
+
+	// logList_Pane
+	logList_pane = new JPanel();
+	logList_pane.setBorder(BorderFactory.createLoweredBevelBorder());
+	logList_label = new JLabel();
+	logList_label.setOpaque(true);
+	logList_label.setBackground(Configuration.getColor("coloring.workspace_heading_background"));
+	logList_label.setForeground(Configuration.getColor("coloring.workspace_heading_foreground"));
+	logList_label.setText(GAI.dictionary.get("LogPane.Log_List"));
+
+	// logContent_Pane
+	logContent_pane = new JPanel();
+	logContent_pane.setBorder(BorderFactory.createLoweredBevelBorder());
+	logContent_pane.setBackground(Configuration.getColor("coloring.workspace_selection_background"));
+	logContent_pane.setForeground(Configuration.getColor("coloring.workspace_selection_foreground"));
+	logContent_label = new JLabel();
+	logContent_label.setOpaque(true);
+	logContent_label.setBackground(Configuration.getColor("coloring.workspace_selection_background"));
+	logContent_label.setForeground(Configuration.getColor("coloring.workspace_selection_foreground"));
+	logContent_label.setText(GAI.dictionary.get("LogPane.Log_Content"));
+	
+	// TEXTAREA Layout
+	log_content = new JScrollPane(log_textarea);
+
+	// Button Layout 
+	button_pane.setLayout (new GridLayout(1,3));
+	button_pane.add(reload_button);
+	button_pane.add(clear_button);
+	
+	control_pane.setLayout (new BorderLayout());
+	//control_pane.setBorder(BorderFactory.createLoweredBevelBorder());
+	control_pane.setBorder(BorderFactory.createEmptyBorder(05,10,5,10));
+	control_pane.setPreferredSize(new Dimension(50,50));
+	control_pane.setSize(new Dimension(50,50));
+	control_pane.add (button_pane, BorderLayout.CENTER);
+
+	// Layout Components
+	logList_pane.setLayout(new BorderLayout());
+	logList_pane.add(log_list, BorderLayout.CENTER);
+	logList_pane.add(logList_label, BorderLayout.NORTH);
+		
+	logContent_pane.setLayout(new BorderLayout());
+	logContent_pane.add(log_content,BorderLayout.CENTER);
+	logContent_pane.add(logContent_label, BorderLayout.NORTH);
+	logContent_pane.add(control_pane, BorderLayout.SOUTH);
+	
+	main_log_pane.add(logList_pane, JSplitPane.LEFT);
+	main_log_pane.add(logContent_pane, JSplitPane.RIGHT);
+	main_log_pane.setDividerLocation(LIST_SIZE.width - 10);
+	
+	this.setLayout(new BorderLayout());
+	this.add(main_log_pane, BorderLayout.CENTER);
+	//this.add(control_pane, BorderLayout.SOUTH);
+    }
+
+    /** Called whenever this pane gains focus, this method ensures that the various 
+     **tree renderers are correctly colouring the tree (as these settings sometimes get lost).
+     * @param event A <strong>FocusEvent</strong> containing details about the focus action performed.
+     */
+    /*public void focusGained(FocusEvent event) {
+	DefaultTreeCellRenderer def = new DefaultTreeCellRenderer();
+	DefaultTreeCellRenderer w = (DefaultTreeCellRenderer)workspace_tree.getCellRenderer();
+	DefaultTreeCellRenderer c = (DefaultTreeCellRenderer)collection_tree.getCellRenderer();
+	if(event.getSource() == workspace_tree) {
+	    w.setBackgroundSelectionColor(def.getBackgroundSelectionColor());
+	    c.setBackgroundSelectionColor(Color.lightGray);
+	}
+	else if(event.getSource() == collection_tree) {
+	    c.setBackgroundSelectionColor(def.getBackgroundSelectionColor());
+	    w.setBackgroundSelectionColor(Color.lightGray);
+	}
+	repaint();
+	}*/
+    
+    /** Implementation side-effect, not used in any way.
+     * @param event A <strong>FocusEvent</strong> containing details about the focus action performed.
+     */
+    /*public void focusLost(FocusEvent event) {
+      }*/
+    
+    /** Called to inform this control panel that it has just gained focus as an effect of the user clicking on its tab.
+     */
+    public void gainFocus() {
+	// Update the meta-audit view to show the current selection, if any.
+	//Gatherer.g_man.meta_audit.setRecords(getCollectionTreeSelection());
+    }
+    
+    /** Called whenever the detail mode changes to ensure the filters are at an appropriate 
+     **level (ie only editable by those that understand regular expression matching)
+     * @param mode the mode level as an int
+     */
+    /*  public void modeChanged(int mode) {
+	collection_filter.setEditable(mode > Configuration.LIBRARIAN_MODE);
+	workspace_filter.setEditable(mode > Configuration.LIBRARIAN_MODE);
+	}*/
+    
+    private class KeyListenerImpl
+	extends KeyAdapter {
+	private boolean vk_left_pressed = false;
+	public void keyReleased(KeyEvent event) {
+	}
+	// we need to watch for left clicks on an unopened folder - should shift the focus to the
+	//parent folder. But because there is some other mysterious key listener that does opening and 
+	//closing folders on right and left clicks, we must detect the situation before the other handler 
+	//has done its job, and process it after.*/
+	public void keyPressed(KeyEvent event) {
+	    if (event.getKeyCode() == KeyEvent.VK_LEFT) {
+		
+	    }
+	}     
+    }
+
+    /** This class listens for mouse clicks and responds right mouse button clicks (popup menu)., left
+     **  mouse button:log file selected */
+    private class MouseListenerImpl
+	extends MouseAdapter {
+	/* Any subclass of MouseAdapter can override this method to respond to mouse click events. 
+	 *In this case we want to open a pop-up menu if we detect a right mouse click over one of our 
+	 *registered components, and start an external application if someone double clicks on a certain 
+	 *file record. */
+	public void mouseReleased(MouseEvent e) {}
+	public void mouseExited(MouseEvent e) {}
+	public void mousePressed(MouseEvent e) {}
+	public void mouseEntered(MouseEvent e) {}
+	
+    }
+    
+    /** This class serves as the listener for actions on the build button. */
+    private class ReloadButtonListener
+	implements ActionListener {
+	/** As the log files could be modified in the runtime environment
+	 *  This button is to reload the log file whenever user want to */
+	public void actionPerformed(ActionEvent event) {
+	    // Remember that for lower thresholds the above doesn't work, so try this instead
+	    reload_button.setEnabled(true);
+	    clear_button.setEnabled(true);
+	    updateLogsContent(log_file.getPath());
+	}
+    }
+    
+    private class ClearButtonListener
+	implements ActionListener {
+	public void actionPerformed(ActionEvent event) {
+	    if (!log_file.exists()){
+		JOptionPane.showMessageDialog((Component) null,log_file.getPath() + " log file does not exist");
+		return;
+	    } else {
+		ClearLogFilePrompt cfp  = new ClearLogFilePrompt();
+		boolean file_cleared = cfp.display(log_file);
+		if (file_cleared) {
+		    log_textarea.setText("");
+		}
+	    }
+	    clear_button.setEnabled(false);
+	}
+    }
+    
+    public void updateLogsContent(String filename){
+	if (!log_file.exists()){ 
+	    log_textarea.setText("");
+	    JOptionPane.showMessageDialog((Component) null, filename+" log file does not exist");  
+	    clear_button.setEnabled(false);
+	} else {
+	    readFile(filename);
+	}
+    }
+
+    public void readFile (String filename) {
+	log_textarea.setText("");
+	String fileLine;
+	try {
+	    BufferedReader in = new BufferedReader(new FileReader(filename));
+	    while ((fileLine = in.readLine()) != null) {
+		log_textarea.append(fileLine);
+		log_textarea.append("\n");
+	    }
+	} catch (Exception e) {
+	    e.printStackTrace();
+	}	    
+    }
+   
+    private class LogListListener implements ListSelectionListener {
+	public void valueChanged (ListSelectionEvent e){
+	    if (e.getValueIsAdjusting() == false){
+		if (log_list.getSelectedIndex() == -1){
+		    //no selection
+		} else if (log_list.getSelectedIndex () == 0 ) {
+		    log_file = new File (GAI.tomcat_home+File.separatorChar+"logs"+File.separatorChar+"catalina.out");
+		    String filename = log_file.getPath();
+		    updateLogsContent(filename);
+		    reload_button.setEnabled(true);
+		    clear_button.setEnabled(true);
+		} else if (log_list.getSelectedIndex () == 1) {
+		    log_textarea.setText("");
+		    JOptionPane.showMessageDialog((Component) null,"This file has not been defined yet");	
+		    clear_button.setEnabled(false);
+		    reload_button.setEnabled(false);
+		} else if (log_list.getSelectedIndex () == 2) {
+		    log_textarea.setText("");
+		    JOptionPane.showMessageDialog((Component) null,"This file has not been defined yet");	
+		    clear_button.setEnabled(false);
+		    reload_button.setEnabled(false);
+		}
+	    }
+	}
+    }
+    public void modeChanged (int mode){
+	return;
+    }
+    public void afterDisplay() {
+	return;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/MenuBar.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/MenuBar.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/MenuBar.java	(revision 13928)
@@ -0,0 +1,203 @@
+/**
+ *#########################################################################
+ *
+ * A component of the GAI application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ * Author: Chi-Yu Huang, Greenstone Digital Library, University of Waikato
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.admin.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+
+import org.greenstone.admin.GAI;
+import org.greenstone.admin.Configuration;
+
+/** The menu bar for the Administration tools main GUI. 
+ * @author Chi-Yu Huang, Greenstone Digital Library, University of Waikato
+ * @version
+ */
+public class MenuBar
+    extends JMenuBar {
+    /** The icon to be displayed alongside the context choosen help file. */
+    private int current_tab = -1;
+    
+    private JMenu file = null;
+    private JMenu edit = null;
+    public JMenu help  = null;
+    // public JMenuItem file_cdimage    = null;
+    // public JMenuItem file_close      = null;
+    //public JMenuItem file_delete     = null;
+    public JMenuItem file_exit = null;
+    public JMenuItem file_save = null;
+    public JMenuItem help_general;
+    public JMenuItem help_conf;
+    public JMenuItem help_ext;
+    public JMenuItem help_monitor;
+    public JMenuItem help_log;
+    public JMenuItem help_about;
+
+    static public ImageIcon HELP_ICON = null; 
+    static public ImageIcon BLANK_ICON = null;
+    
+    //    public MenuBar(MenuListener Menu_listener)
+    public MenuBar(MenuListener menu_listener)
+    {
+	HELP_ICON = new ImageIcon(GAI.images_path +"help.gif");
+	BLANK_ICON = new ImageIcon(GAI.images_path+"blank.gif");
+
+	//file = new JMenu("File");
+	file = new JMenu();
+	file.setMnemonic(KeyEvent.VK_F);
+	file.setText(GAI.dictionary.get("Menu.File"));
+	
+	//file_save = new JMenuItem("Save");
+	file_save = new JMenuItem();
+	file_save.addActionListener(GAI.ga_man);
+	file_save.setMnemonic(KeyEvent.VK_S);
+	file_save.setText(GAI.dictionary.get("Menu.File_Save"));
+	
+	//file_exit = new JMenuItem("Exit");
+	file_exit = new JMenuItem();
+	file_exit.addActionListener(GAI.ga_man);
+	file_exit.setMnemonic(KeyEvent.VK_X);
+	file_exit.setText(GAI.dictionary.get("Menu.File_Exit"));
+
+	//Layout (File menu)
+	file.add(file_save);
+	file.add(new JSeparator());
+	file.add(file_exit);
+
+	// Edit menu
+	//edit = new JMenu("Edit");
+	edit = new JMenu();
+	edit.setMnemonic(KeyEvent.VK_E);
+	edit.setText(GAI.dictionary.get("Menu.Edit"));
+			  
+	// Help menu
+	//help = new JMenu("Help");
+	help = new JMenu();
+	help.setMnemonic(KeyEvent.VK_H);
+	help.setIcon(HELP_ICON);
+	help.setText(GAI.dictionary.get("Menu.Help"));
+	
+	help_general = new JMenuItem();
+	help_general.addActionListener(GAI.ga_man);
+	help_general.setText(GAI.dictionary.get("Source.General"));
+		
+	help_conf = new JMenuItem();
+	help_conf.addActionListener(GAI.ga_man);
+	help_conf.setText(GAI.dictionary.get("GAI.Configuration"));
+		
+	help_ext = new JMenuItem();
+	help_ext.addActionListener(GAI.ga_man);
+	help_ext.setText(GAI.dictionary.get("GAI.Ext"));
+	
+	help_monitor = new JMenuItem();
+	help_monitor.addActionListener(GAI.ga_man);
+	help_monitor.setText(GAI.dictionary.get("GAI.Monitor"));
+	
+	help_log = new JMenuItem();
+	help_log.addActionListener(GAI.ga_man);
+	help_log.setText(GAI.dictionary.get("GAI.Log"));
+	
+	help_about = new JMenuItem();
+	help_about.addActionListener(GAI.ga_man);
+	help_about.setText(GAI.dictionary.get("Menu.Help_About"));
+			
+	
+	// Layout (help menu)
+	help.add(help_general);
+	help.add(new JSeparator());
+	if (Configuration.get("admin.conf")) {
+	    help.add(help_conf);
+	}
+	if (Configuration.get("admin.ext")) {
+	    help.add(help_ext);
+	}
+	if (Configuration.get("admin.monitor")) {
+	    help.add(help_monitor);
+	}
+	if (Configuration.get("admin.log")) {
+	    help.add(help_log);
+	}
+	
+	help.add(new JSeparator());
+	help.add(help_about);
+
+	// Layout (menu bar)
+	add(file);
+	add(Box.createHorizontalStrut(15));
+	add(edit);
+	add(Box.createHorizontalGlue());
+	add(help);
+    }
+
+    /** Once a quit has been requested by the user, prevent any further menu selections. */
+    public void exit() {
+	file.setEnabled(false);
+	edit.setEnabled(false);
+	help.setEnabled(false);
+    }
+
+    /*public void refresh(int refresh_reason, boolean ready)
+    {
+	file_close.setEnabled(ready);
+	file_save.setEnabled(ready);
+	}*/
+
+
+    /** In order to provide context aware help advice we keep track of which
+     *  tab the user has open, and then highlight that help menu item with
+     *  separators.
+     *  @param tab_index The index of the selected tab (0-7).
+     */
+    public void tabSelected(int tab_index) {
+	JMenuItem selected;
+	if(current_tab != -1) {
+	    // Remove the image
+	    selected = help.getItem(current_tab);
+	    if(selected != null) {
+		selected.setIcon(BLANK_ICON);
+	    }
+	}
+	current_tab = tab_index + 2;
+	selected = help.getItem(current_tab);
+	if(selected != null) {
+	    selected.setIcon(HELP_ICON);
+	    
+	}
+	selected = null;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/ParsingProgress.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/ParsingProgress.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/ParsingProgress.java	(revision 13928)
@@ -0,0 +1,123 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Core GUI application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: John Thompson, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.core;
+
+import java.awt.*;
+import java.lang.Object;
+import javax.swing.*;
+
+/** This class provides a progress bar to be displayed whenever the module 
+ * is running some background tasks
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class ParsingProgress
+    extends JDialog {
+    //implements ActionListener {
+    
+    public final static int ONE_SECOND = 1000;
+
+    /** The content pane within the dialog box. */
+    private JPanel content_pane = null;
+    private Timer timer;
+    /** The progress bar itself. */
+    private JProgressBar progressBar = null;
+    
+    /** The default size of the progress dialog. */
+    static final Dimension SIZE = new Dimension(400,75);
+    
+    
+    /** Constructor.
+     * @param title The title to show on the dialog, as a <strong>String</strong>.
+     * @param message The message to show on the dialog, as a <strong>String</strong>.
+     * @param max The total amount of the time the process is running before 
+     * the progress bar can be disposed of, as an <i>int</i>.
+     */
+    public ParsingProgress(String title, String message, int max) {
+	super();
+	this.setSize(SIZE);
+	this.setTitle(title);
+	//updateUI();
+
+	// Creation
+	this.content_pane = (JPanel) getContentPane();
+	this.content_pane = new JPanel();
+	
+	this.progressBar = new JProgressBar();
+	this.progressBar.setMaximum(max);
+	this.progressBar.setIndeterminate(true);
+       
+
+	// Layout
+	this.content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	this.content_pane.setLayout(new BorderLayout());
+	this.content_pane.add(new JLabel(message), BorderLayout.NORTH);
+	this.content_pane.add(progressBar, BorderLayout.CENTER);
+	
+	//Create a timer
+	//timer = new Timer (ONE_SECOND, new ActionListener() {
+	//	public void actionPerformed (ActionEvent evt) {
+		    progressBar.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+		    
+		    //container.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+		    /*  progressBar.setValue(max);
+			Toolkit.getDefaultToolkit().beep();
+			timer.stop();
+			startButton.setEnabled(true);
+			setCursor(null); //turn off the wait cursor
+			progressBar.setValue(progressBar.getMinimum());*/
+		    //}
+		    //});
+	
+	// Center and display
+	Dimension screen_size = Toolkit.getDefaultToolkit().getScreenSize();
+	setLocation((screen_size.width - SIZE.width) / 2,
+		    (screen_size.height - SIZE.height) / 2);
+	
+	setVisible(true);
+    }
+    
+    public void destroy() {
+    }
+    
+    /** Method which increments the progress count by one, which should be called 
+     ** after every successful parsing of a classifier or plugin.
+     */
+    public void inc() {
+	this.progressBar.setValue(progressBar.getValue() + 1);
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/SaveChangePrompt.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/SaveChangePrompt.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/SaveChangePrompt.java	(revision 13928)
@@ -0,0 +1,108 @@
+/**
+ *#########################################################################
+ *
+ * A component of the GAI application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Chi-Yu Huang, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.admin.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.net.*;
+import javax.swing.*;
+import javax.swing.event.*;
+
+import org.greenstone.admin.gui.ConfPane;
+
+/** This class provides the functionality to show a prompt to save changed file  
+ * @author Chi-Yu Huang, Greenstone Digital Library, University of Waikato
+ * @version 1.0
+ */
+public class SaveChangePrompt
+    extends JDialog {
+    
+    /** A reference to ourself so any inner-classes can dispose of us. */
+    private SaveChangePrompt prompt = null;
+    private File file = null;
+        
+    //A flag showing the saving change status
+    private boolean current_change_saved = false;
+    
+    /** The size of the save prompt screen. */
+    static final Dimension SIZE = new Dimension(500, 500);
+    
+    // Constructor.
+    public SaveChangePrompt() {
+	super();
+	prompt = this;
+    }
+    
+    /** Destructor. */
+    public void destroy() {
+	prompt = null;
+    }
+    
+    /** This method causes the Save Change Confirmation Dialog to be displayed.
+     * returns true if it has save the change file that is currently open */
+    // public boolean display(File file) {
+	/*int result = JOptionPane.showConfirmDialog((Component) null, "Do you really want to save the change", "Save Confirmation", JOptionPane.YES_NO_OPTION);
+	  if ( result == JOptionPane.YES_OPTION) {
+	  ConfPane confPane = new ConfPane();
+	  confPane.saveNewConfSetting();
+	  confPane.writeConfFile(file);
+	  current_change_saved = true;
+	  } else if (result == JOptionPane.NO_OPTION) {
+	    current_change_saved = false;
+	    prompt.dispose();
+	    }
+	    resultPrompt(current_change_saved);
+	    return current_change_saved;*/
+    //}
+    
+    /** Shows a save complete prompt. 
+     * @param success A <strong>boolean</strong> indicating if the collection was successfully saved
+     */
+    public void resultPrompt(boolean success) {
+	if (success) {
+	    JOptionPane.showMessageDialog(prompt,"The build property file has been saved.");
+	} else {
+	    JOptionPane.showMessageDialog(prompt, "Cancel saving the change to build property file");
+	}
+    }
+    
+    /** Any implementation of ActionListener requires this method so that when an 
+     **action is performed the appropriate effect can occur.*/
+    public void actionPerformed(ActionEvent event) {
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/SetServerPane.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/SetServerPane.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/SetServerPane.java	(revision 13928)
@@ -0,0 +1,371 @@
+/**
+ *#########################################################################
+ *
+ * A component of the GAI application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Chi-Yu Huang, Greenstone Digital Library, University of Waikato
+ * Date: 05.2005
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+/* This program is intended to confirm the initial user's setting about
+ * the Tomcat server and MySQL server they would like to run GSDL3 with
+ */
+package org.greenstone.admin.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.List;
+import java.util.ArrayList;
+import java.lang.Object;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.tree.*;
+import javax.swing.table.*;
+import java.awt.event.MouseEvent;
+import java.net.*;
+import java.sql.*;
+
+import org.greenstone.admin.Configuration;
+import org.greenstone.core.ParsingProgress;
+import org.greenstone.admin.GAI;
+
+
+/** The initial setting pane is to request the user to input the preferred 
+ * Tomcat and Mysql server,they would like to run GSDL3 with
+ *  @author Chi-Yu Huang, Greenstone Digital Library, University of Waikato
+ *  @version
+ */
+public class SetServerPane
+    extends JFrame
+    implements ActionListener {
+
+    /* This pane is to allow the user to set up their own running Tomcat/Mysql server 
+     * before the installation of the GSDL3*/
+    // protected JScrollPane setting_message_pane = null;
+    protected JPanel main_pane = null;
+    protected JPanel button_pane = null;
+    protected JPanel outter_control_pane = null;
+    protected JScrollPane setting_table_pane = null;
+    protected JTable server_setting_table = null;
+    
+    private JButton save_button = null;
+    private JButton install_button = null;
+    private JButton exit_button = null;
+
+    ServerSettingTableModel server_setting_table_model = null;
+    private boolean setting_confirm = false;
+    private ArrayList conf_array;
+    private boolean success = false;
+    private boolean file_saved = true;
+    
+    /** The various sizes for the screen layout*/
+    static private Dimension MIN_SIZE = new Dimension( 90,  90);
+    static private Dimension LIST_SIZE  = new Dimension(200, 450);
+    static private Dimension DIALOG_SIZE = new Dimension (400,300);
+    static private Dimension FRAME_SIZE = new Dimension (500, 450);
+    static private Dimension TABLE_SIZE = new Dimension(500,200);
+    static final Dimension SIZE = new Dimension(400,400);
+    
+    //Constructor
+    public SetServerPane() {
+	super();
+	this.setDefaultCloseOperation(EXIT_ON_CLOSE);
+	this.setSize(FRAME_SIZE);
+	this.setTitle("Setting Tomcat/MYSQL Servers");
+	
+	// create all the control button panes
+	button_pane  = new JPanel();
+
+	//First time running button
+	SaveButtonListener ybl = new SaveButtonListener();
+	InstallButtonListener nbl = new InstallButtonListener();
+	ExitButtonListener ebl = new ExitButtonListener();
+	
+	// ImagesIcon for the buttons
+	ImageIcon SaveButtonIcon = new ImageIcon(GAI.images_path + "refresh.gif");
+	ImageIcon InstallButtonIcon = new ImageIcon(GAI.images_path + "exit.gif");
+	ImageIcon ExitButtonIcon = new ImageIcon(GAI.images_path + "exit.gif");
+
+	save_button = new JButton("Save Setting", SaveButtonIcon);
+	save_button.addActionListener(ybl);
+	save_button.setMnemonic(KeyEvent.VK_S);
+	save_button.setToolTipText("Click this button to save up the setting");
+	save_button.setEnabled(false);
+
+	install_button = new JButton("Install GSDL3", InstallButtonIcon);
+	install_button.addActionListener(nbl);
+	install_button.setEnabled(false);
+	install_button.setMnemonic(KeyEvent.VK_I);
+	install_button.setToolTipText("Click this button to Install Greenstone III");
+
+	exit_button = new JButton("Exit Setting and Installation", ExitButtonIcon);
+	exit_button.addActionListener(ebl);
+	exit_button.setEnabled(false);
+	install_button.setMnemonic(KeyEvent.VK_I);
+	install_button.setToolTipText("Click this button to Exit the Setting and Installation of Greenstone III");
+
+	//Setting&Installation buttons
+	ybl = null;
+	nbl = null;
+	ebl = null;
+    }
+
+    /** Any implementation of ActionListener requires this method so that when an 
+     **action is performed the appropriate effect can occur.*/
+    public void actionPerformed(ActionEvent event) {
+    }
+
+    /** This method is callsed to actually layout the components.*/
+    public void display() {
+	//KeyListenerImpl key_listener = new KeyListenerImpl();
+	//MouseListenerImpl mouse_listener = new MouseListenerImpl();
+	//this.addKeyListener(key_listener);
+	
+	server_setting_table_model = new ServerSettingTableModel();
+	server_setting_table = new JTable(server_setting_table_model) {
+		protected String[] rowToolTips = {
+		    "The name of the machine that Tomcat is/will be run on",
+		    "The port number that Tomcat is/will be run on",
+		    "The base directory for the existing Tomcat installation",
+		    "The name of the machine that Mysql is/will be run on",
+		    "The port number that Mysql is/will be run on",
+		    "The base directory for the existing MYSQL installations",
+		    "The user name for the administrator of using MySQL",
+		    "The socket that Mysql is/will be run on"};
+		
+		public String getToolTipText(MouseEvent e){
+		    String tip = null;
+		    Point p = e.getPoint();
+		    int rowIndex = rowAtPoint(p);
+		    int colIndex = columnAtPoint(p);
+		    int realColumnIndex = convertColumnIndexToModel(colIndex);
+		    if (realColumnIndex == 0){
+			tip = rowToolTips[rowIndex];
+		    } else {
+			tip = super.getToolTipText(e);
+		    }
+		    return tip;
+		}
+	    };
+	
+	//Set up tableHeader
+	JTableHeader header = server_setting_table.getTableHeader();
+	header.setFont(new Font("Arial", Font.BOLD, 14));
+	
+	server_setting_table.setRowHeight(30);
+	setting_table_pane = new JScrollPane(server_setting_table);
+	
+	// Button Control Layout 
+	save_button.setEnabled(true);
+	install_button.setEnabled(true);
+	exit_button.setEnabled(true);
+	
+	button_pane.setLayout (new GridLayout(1,3));
+	button_pane.add(save_button);
+	button_pane.add(install_button);
+	button_pane.add(exit_button);
+
+	outter_control_pane = new JPanel();
+	outter_control_pane.setLayout (new BorderLayout());
+	outter_control_pane.setBorder(BorderFactory.createLoweredBevelBorder());
+	outter_control_pane.setPreferredSize(new Dimension(50,50));
+	outter_control_pane.setSize(new Dimension(50,50));
+	outter_control_pane.add (button_pane, BorderLayout.CENTER);
+	
+	main_pane = (JPanel) getContentPane();
+	main_pane.setLayout (new BorderLayout());
+	main_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	main_pane.add(setting_table_pane, BorderLayout.CENTER);
+	main_pane.add(outter_control_pane, BorderLayout.SOUTH);
+	main_pane.setBackground(Configuration.getColor("coloring.workspace_selection_background"));
+	main_pane.setForeground(Configuration.getColor("coloring.workspace_selection_foreground"));
+	
+	// Center and display
+	Dimension screen_size = Toolkit.getDefaultToolkit().getScreenSize();
+	setLocation((screen_size.width - SIZE.width) / 2,
+		    (screen_size.height - SIZE.height) / 2);
+	setVisible(true);
+    }
+    
+    public void destroy() {
+    }
+        
+    /** This class serves as the listener for actions on the build button.*/
+    private class SaveButtonListener
+	implements ActionListener {
+	/** This button is to save any change you have added
+	 ** to the Tomcat/Mysql servers setting*/
+	public void actionPerformed(ActionEvent event) {
+	    setting_confirm = true;
+	    int result = JOptionPane.showConfirmDialog((Component) null, "Do you really want to save the setting?", "Save Confirmation", JOptionPane.YES_NO_OPTION);
+	    if ( result == JOptionPane.YES_OPTION) {
+		updateSetting (GAI.build_properties_file);
+		file_saved = writeFile (GAI.build_properties_file);
+		if (file_saved) {
+		    JOptionPane.showMessageDialog((Component) null,"Change has been saved succefully!");
+		} else {
+		    JOptionPane.showMessageDialog((Component) null,"Change has not been saved succefully!");
+		    file_saved = false;
+		} 
+	    } else if (result == JOptionPane.NO_OPTION) {
+		JOptionPane.showMessageDialog((Component) null,"Change has not been saved!");
+		file_saved = false;
+	    }
+	}
+    }
+
+    public void updateSetting(File build_properties_file) {
+	readFile (GAI.build_properties_file);
+	String new_string;
+	for (int i=0; i < server_setting_table_model.getRowCount(); i++){
+	    //System.err.println("What is the value here:" + server_setting_table_model.getValueAt(i,0).toString());
+	    if (!server_setting_table_model.getValueAt(i,1).toString().matches("^\\s*$")){
+		for (int j=0; j < conf_array.size(); j++){
+		    if (((String)conf_array.get(j)).startsWith(server_setting_table_model.getValueAt(i,0).toString().toLowerCase())){
+			//System.err.println("What is the value in conf_array:" + conf_array.get(j));
+			new_string = server_setting_table_model.getValueAt(i,0).toString()+"="+server_setting_table_model.getValueAt(i,1).toString();
+			conf_array.set(j, new_string.toLowerCase());
+		    }
+		}
+	    }
+	}
+	
+    }
+    public void readFile (File build_properties_file) {
+	String filename = build_properties_file.getPath();
+	String fileLine;
+	/*conf_array[] store all the details from the build.properties*/
+	conf_array = new ArrayList();
+	try {
+	    BufferedReader conf_in = new BufferedReader(new FileReader(filename));
+	    while ((fileLine = conf_in.readLine()) != null) {
+		// Besides an empty line, all the other lines will be stored in the conf_array
+		if (!fileLine.matches("^\\s*$")) {
+		    conf_array.add(fileLine);
+		} 
+	    }
+	    conf_in.close();
+	} catch (Exception e) {
+	    e.printStackTrace();
+	}
+    }
+    
+    public boolean writeFile(File build_properties_file){
+	String filename = build_properties_file.getPath();
+	try {
+	    BufferedWriter conf_out = new BufferedWriter(new FileWriter(filename));
+	    for (int j=0 ; j < conf_array.size(); j++){
+		conf_out.write(conf_array.get(j).toString());
+		conf_out.newLine();
+	    }
+	    success = true;
+	    conf_out.close();
+	} catch (Exception e) {
+	    e.printStackTrace();
+	    success = false;
+	}
+	return success;
+    }
+
+    private class InstallButtonListener
+	implements ActionListener {
+	// Exit the Adminstration tool 
+	public void actionPerformed(ActionEvent event) {
+	    setting_confirm = false;
+	    /*if (!setting_confirm) {
+	      GAIManager gai = new GAIManager("/research/chi/gsdl3-test/gsdl3", screen_size);
+	      }*/
+	}
+    }
+    
+    private class ExitButtonListener
+	implements ActionListener {
+	// Exit the Adminstration tool 
+	public void actionPerformed(ActionEvent event) {
+	    if (!file_saved) {
+		int result = JOptionPane.showConfirmDialog((Component) null, "The value of configuration has been changed,do you really want to exit?", "Exit Confirmation", JOptionPane.YES_NO_OPTION);
+		if ( result == JOptionPane.YES_OPTION) {
+		    System.exit(1);
+		} else if (result == JOptionPane.NO_OPTION) {
+		    JOptionPane.showMessageDialog((Component) null,"Press Save button to save the change!");
+		}
+	    } else {
+		System.exit(1);
+	    }	    
+	}
+    }
+    
+    class ServerSettingTableModel extends AbstractTableModel {
+	String[] columnNames = {"Configuration Parameter",
+				"Configuration Value"};
+	Object [][] conf_display = {{"TOMCAT.SERVER", ""},
+				    {"TOMCAT.PORT", ""},
+				    {"TOMCAT.INSTALLED.PATH",""},
+				    {"MYSQL.SERVER",""},
+				    {"MYSQL.PORT",""},
+				    {"MYSQL.INSTALLED.PATH",""},
+				    {"MYSQL.ADMIN.USER",""},
+				    {"MYSQL.SOCKET",""}};
+	
+	public int getColumnCount(){
+	    return columnNames.length;
+	}
+	
+	public int getRowCount() {
+	    return conf_display.length;
+	}
+	
+	public String getColumnName(int col){
+	    return columnNames[col];
+	}
+	
+	public Object getValueAt(int row,int col){
+	    return conf_display[row][col];
+	}
+	
+	public boolean isCellEditable(int row, int col){
+	    if (col == 0){
+		return false;
+	    } else {
+		return true;
+	    }
+	}
+
+	public void setValueAt(Object value, int row, int col){
+	    conf_display[row][col] = value;
+	    fireTableCellUpdated(row,col);
+	}
+    }
+
+}
+       
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/SiteConfSetting.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/SiteConfSetting.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/SiteConfSetting.java	(revision 13928)
@@ -0,0 +1,151 @@
+/**
+ *#########################################################################
+ *
+ * A component of the GAI application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Chi-Yu Huang, Greenstone Digital Library, University of Waikato
+ * Modified: 03.2005
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.admin.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.*;
+import java.lang.Object;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.tree.*;
+import javax.swing.table.*;
+
+import org.greenstone.admin.GAI;
+
+/*Site configuration demonstrated in XML format
+ *@author: Chi-Yu Huang, Greenstone Digital Library, University of Waikato
+ *@version:
+ */
+public class SiteConfSetting
+    extends JPanel {
+    // implements TextListener {
+
+    //The Text area to demonstarte configuration content
+    private JTextArea site_conf_content = null;
+
+    //The scrollable area into which the configuration content is placed
+    private JScrollPane site_conf_area = null;
+    
+    private String site_conf_name;
+    private boolean conf_changed = false;
+    private StringBuffer site_conf_in;
+    
+    public SiteConfSetting(String conf_name, File conf_file) {
+	super();
+	this.site_conf_name = conf_name;
+	/*A StringBuffer to store the content of Site Configuration files such as 
+	 *SiteConfig.xml and InterfaceConfig.xml files*/
+	this.site_conf_in = new StringBuffer();
+	this.site_conf_in = readConfFile(conf_file);
+	this.site_conf_content = new JTextArea();
+	this.site_conf_content.setEditable(true);
+	this.site_conf_content.append(this.site_conf_in.toString());
+	this.site_conf_area = new JScrollPane(site_conf_content);  
+	this.site_conf_content.getDocument().addDocumentListener(new ConfDocumentListener());
+	setLayout(new BorderLayout());
+	add(site_conf_area,BorderLayout.CENTER);
+    }
+    
+    private class ConfDocumentListener implements DocumentListener {
+        final String newline = "\n";
+	
+        public void insertUpdate(DocumentEvent e) {
+	    conf_changed = true;
+        }
+        
+	public void removeUpdate(DocumentEvent e) {
+	    conf_changed = true;
+	}
+	
+        public void changedUpdate(DocumentEvent e) {
+	    conf_changed = true;
+	}
+	
+        public void updateLog(DocumentEvent e, String action) {
+	}
+    }
+    
+    public boolean confChanged ()
+    {
+	return this.conf_changed;
+    }
+    
+    public void showText()
+    {
+	site_conf_content.getText();
+    }
+    
+    public void goTop()
+    {
+	//Go to the top of ScrollPane
+	site_conf_content.setCaretPosition(0);
+    }
+    
+    public void saveFile(File filename) 
+    {
+	try {
+	    BufferedWriter site_out = new BufferedWriter(new FileWriter(filename.getPath()));
+	    String text = site_conf_content.getText();
+	    site_out.write(text);
+	    site_out.close();
+	    conf_changed = false;
+	} catch (Exception e) {
+	    e.printStackTrace();
+	}
+    }
+    
+    private StringBuffer readConfFile(File filename)
+    {
+	StringBuffer file_buffer = new StringBuffer();
+	String fileLine;
+	try {
+	    BufferedReader in = new BufferedReader(new FileReader(filename));
+	    while ((fileLine = in.readLine())!= null) {
+		file_buffer.append(fileLine);
+		file_buffer.append("\n");
+	    }
+   	} catch (Exception e) {
+	    e.printStackTrace();
+	}	    
+	return file_buffer;
+    }
+
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/TabbedPane.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/TabbedPane.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/TabbedPane.java	(revision 13928)
@@ -0,0 +1,90 @@
+/**
+ *#########################################################################
+ *
+ * A component of the Gatherer application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: Chi-Yu Huang, Greenstone Digital Library, University of Waikato
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+
+package org.greenstone.admin.gui;
+
+
+import javax.swing.JTabbedPane;
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JFrame;
+import javax.swing.JComponent;
+import java.awt.*;
+import java.awt.event.KeyEvent;
+
+public class TabbedPane extends JPanel {
+
+    private static final Dimension SIZE = new Dimension(800, 540);
+
+    public TabbedPane() {
+	super(new GridLayout(1, 1));
+	setBackground(new Color(176,208,176));
+	
+        JTabbedPane tabbedPane = new JTabbedPane();
+        JComponent panel1 = makeTextPanel("Log information Pane");
+	/*   tabbedPane.addTab("Log Pane", icon, panel1,
+	     "Log Pane");*/
+	panel1.setPreferredSize(SIZE);
+	panel1.setBackground(new Color(176,208,176));
+	tabbedPane.addTab("Log Pane", panel1);
+	tabbedPane.setMnemonicAt(0, KeyEvent.VK_L);
+      
+
+        JComponent panel2 = makeTextPanel("Runtime Status");
+        /*tabbedPane.addTab("Status Pane", icon, panel2,
+	  "Status Pane");*/
+
+	panel2.setPreferredSize(SIZE);
+	panel2.setBackground(new Color(176,208,176));
+	tabbedPane.addTab("Status Pane", panel2);
+        tabbedPane.setMnemonicAt(1, KeyEvent.VK_R);
+
+        //Add the tabbed pane to this panel.
+        add(tabbedPane);
+    }
+
+    protected JComponent makeTextPanel(String text) {
+        JPanel panel = new JPanel(false);
+        JLabel filler = new JLabel(text);
+        filler.setHorizontalAlignment(JLabel.CENTER);
+        panel.setLayout(new GridLayout(1, 1));
+        panel.add(filler);
+        return panel;
+    }
+
+    /** Returns an ImageIcon, or null if the path was invalid. */
+    protected static ImageIcon createImageIcon(String path) {
+        java.net.URL imgURL = TabbedPane.class.getResource(path);
+        if (imgURL != null) {
+            return new ImageIcon(imgURL);
+        } else {
+            System.err.println("Couldn't find file: " + path);
+            return null;
+        }
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/ThreadControl.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/ThreadControl.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/admin/gui/ThreadControl.java	(revision 13928)
@@ -0,0 +1,390 @@
+/**
+ *#########################################################################
+ *
+ * A component of the GAI application, part of the Greenstone digital
+ * library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * <BR><BR>
+ *
+ * Author: Chi-Yu Huang, Greenstone Digital Library, University of Waikato
+ *
+ * <BR><BR>
+ *
+ * Copyright (C) 1999 New Zealand Digital Library Project
+ *
+ * <BR><BR>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * <BR><BR>
+ *
+ * This program 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 for more details.
+ *
+ * <BR><BR>
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *########################################################################
+ */
+package org.greenstone.admin.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.net.*;
+import javax.swing.*;
+import javax.swing.event.*;
+
+import org.greenstone.admin.GAI;
+import org.greenstone.admin.GAIManager;
+import org.greenstone.admin.gui.LogPane;
+import org.greenstone.core.ParsingProgress;
+import org.apache.tools.ant.*;
+import org.apache.tools.ant.helper.ProjectHelperImpl;
+
+
+
+public class ThreadControl 
+    extends Thread {
+    
+    private GAIManager gai_man;
+
+    public ThreadControl(){
+    }
+
+    public void run(){
+    }   
+
+    
+    public void executeAntTarget(String command_string) throws IOException  {
+	Project ant = new Project();
+	File buildFile = new File (GAI.gsdl3_src_home + File.separator + "build.xml");
+	
+	//Set up a PrintStream pointing at a file
+	//FileOutputStream ant_out =
+	//   new FileOutputStream(GAI.gsdl3_src_home + File.separator + "ant_out.log");
+	//FileOutputStream ant_err = 
+	//   new FileOutputStream(GAI.gsdl3_src_home + File.separator + "ant_err.log");
+	
+	//	BufferedOutputStream ant_out_buffer = 
+	//   new BufferedOutputStream(ant_out, 1024);
+	//BufferedOutputStream ant_err_buffer = 
+	///   new BufferedOutputStream(ant_err, 1024);
+	
+	//PrintStream ant_out_ps =
+	//   new PrintStream(ant_out_buffer, false);
+	//PrintStream ant_err_ps =
+	//   new PrintStream(ant_err_buffer, false);
+	
+	DefaultLogger log = new DefaultLogger();
+        //log.setErrorPrintStream(ant_err_ps);
+	//log.setOutputPrintStream(ant_out_ps);
+
+	log.setErrorPrintStream(System.err);
+	log.setOutputPrintStream(System.out);
+        log.setMessageOutputLevel(Project.MSG_INFO);
+	ant.addBuildListener(log);
+	try {
+	    ant.init();
+	    ant.fireBuildStarted();
+	    ProjectHelper helper = ProjectHelper.getProjectHelper();
+	    helper.parse(ant, buildFile);
+	    ant.executeTarget(command_string);
+	    ant.fireBuildFinished(null);
+	}
+	catch (BuildException e) {
+	    e.printStackTrace(System.err); 
+	    ant.fireBuildFinished(e);
+	}
+	/*finally {
+	    System.setOut(ant_out_ps);
+	    System.setErr(ant_err_ps);
+	    }*/
+
+	//boolean ant_success = checkAntResult();
+	//ant_out_ps.close();
+	//ant_err_ps.close();
+	/*if (!ant_success){
+	    int result = JOptionPane.showConfirmDialog((Component) null, "Ant building call was failed, do you want to see the log file?", "Exit Confirmation", JOptionPane.YES_NO_OPTION);
+	    if ( result == JOptionPane.YES_OPTION) {
+		//System.exit(1);
+		// Showing ant_out.log content
+	    } else if (result == JOptionPane.NO_OPTION) {
+		JOptionPane.showMessageDialog((Component) null,"You can see the log file from Log Pane!");
+	    } 
+	} else {
+	    //System.err.println("****Ant build successed");
+	    //JOptionPane.showMessageDialog((Component) null,"You can see the log file from Log Pane!");
+	    
+	    }*/
+    }
+
+    /*public boolean checkAntResult(){
+	try {
+	    String filename = GAI.gsdl3_src_home + File.separator +"ant_out.log";
+	    String fileLine;
+	    
+	    BufferedReader ant_result = new BufferedReader(new FileReader(filename));
+	    
+	    while ((fileLine = ant_result.readLine()) != null) {
+		if (fileLine.matches("BUILD SUCCESSFUL")){
+		    //return true;
+		    return false;
+		} else if (fileLine.matches("BUILD FAILED")){
+		    //System.err.println("***Ant result"+fileLine);
+		    return false;
+		}
+	    }
+	} catch (Exception e) {
+	    e.printStackTrace();
+	   
+	}	
+	return false;
+	}*/
+    
+
+    public class restartTomcatServer 
+	implements Runnable {
+	private String command_string = null;
+	/* Construct a restartTomcatServer Object*/
+	public restartTomcatServer(String command_string) {
+	    this.command_string = command_string;
+	}
+	
+	public void run() {
+	    try {
+		executeAntTarget(this.command_string);
+	    } catch(Exception e) { 
+		System.out.println(e.getMessage()); 
+	    }
+	}
+    }
+
+    public class startupTomcatServer 
+	implements Runnable {
+	private String command_string = null;
+	/* Construct a startupTomcatServer Object*/
+	public startupTomcatServer(String command_string) {
+	    this.command_string = command_string;
+	}
+	public void run() {
+	    try { 
+		executeAntTarget(this.command_string);
+	    } catch(Exception e) { 
+		System.out.println(e.getMessage()); 
+	    }
+	}
+    }
+
+    public class shutdownTomcatServer 
+	implements Runnable {
+	private String command_string = null;
+	/* Construct a shutdownTomcatServer Object*/
+	public shutdownTomcatServer(String command_string) {
+	    this.command_string = command_string;
+	}
+	public void run() {
+	    try { 
+		executeAntTarget(this.command_string);
+	    } catch(Exception e) { 
+		System.out.println(e.getMessage()); 
+	    }
+	}
+    }
+
+    public class startupMysqlServer 
+	implements Runnable {
+	private String command_string = null;
+
+	/* Construct a startupMysqlServer Object*/
+	public startupMysqlServer(String command_string) {
+	    this.command_string = command_string;
+	}
+	public void run() {
+	    try { 
+		executeAntTarget(this.command_string);
+	    } catch(Exception e) { 
+		System.out.println(e.getMessage()); 
+	    }
+	}
+    }
+
+    public class shutdownMysqlServer 
+	implements Runnable {
+	private String command_string = null;
+	/* Construct a shutdownMysqlServer Object*/
+	public shutdownMysqlServer(String command_string) {
+	    this.command_string = command_string;
+	}
+	public void run() {
+	    try { 
+		executeAntTarget(this.command_string);
+	    } catch(Exception e) { 
+		System.out.println(e.getMessage()); 
+	    }
+	}
+    }
+
+    public class restartMysqlServer 
+	implements Runnable {
+	private String command_string = null;
+	/* Construct a restartMysqlServer Object*/
+	public restartMysqlServer(String command_string) {
+	    this.command_string = command_string;
+	}
+	public void run() {
+	    try { 
+		executeAntTarget(this.command_string);
+	    } catch(Exception e) { 
+		System.out.println(e.getMessage()); 
+	    }
+	}
+    }
+
+    public class installGS3 
+	implements Runnable {
+	private String command_string = null;
+
+	/* Install GSDL3 through ant program*/
+	public installGS3(String command_string) {
+	    this.command_string = command_string;
+	}
+	public void run() {
+	    try {
+     
+		executeAntTarget(this.command_string);
+		// ant_success;
+	    } catch(Exception e) { 
+		System.out.println(e.getMessage()); 
+	    }
+	}
+    }
+
+    
+    public void destroy(){
+    }
+}
+
+
+/***
+ * This program shows how you can time a set of threads.  The main()
+ * program demonstrates the timing classes by spawning and timing a
+ * set of threads that just execute a dummy loop.
+ ***/
+/*public class ThreadTiming {
+
+    /** Times a group of threads.  Works with TimingWrapper. */
+//    public static class ThreadTimer {
+//	private boolean __resultReady;
+//	private int __monitor[], __numThreads;
+//	private long __begin, __end;
+	
+	/** Creates a ThreadTimer that can time a given number of threads. */
+//	public ThreadTimer(int numThreads) {
+//	    __monitor     = new int[1];
+//	    __monitor[0]  = 0;
+//	    __numThreads  = numThreads;
+//	    __resultReady = false;
+//	}
+	
+	/** Starts the timer when all the threads are ready to start. */
+//	public void start() {
+//    synchronized(__monitor) {
+//		if(++__monitor[0] >= __numThreads) {
+//		    __begin = System.currentTimeMillis();
+//		    __monitor.notifyAll();
+//		} else {
+//		    while(true) {
+//			try {
+//			    __monitor.wait();
+//			} catch(InterruptedException e) {
+//			    continue;
+//			}
+//			break;
+//		    }
+//		}
+//	    }
+//	}
+	
+	/** Stops the timer when the last thread is done. */
+//	public void stop() {
+//	    synchronized(__monitor) {
+//	if(--__monitor[0] <= 0) {
+//		    __end   = System.currentTimeMillis();
+//		    synchronized(this) {
+//		__resultReady = true;
+//		notify();
+//	    }
+//	}
+//   }
+//}/
+	
+	/** Calling thread waits until timing result is ready. */
+//	public synchronized void waitForResult() {
+//	    while(!__resultReady) {
+//		try {
+///	    wait();
+//	} catch(InterruptedException e) {
+//	}
+//    }
+//    __resultReady = false;
+//}
+//
+///** Returns elapsed time in milliseconds. */
+//public long getElapsedTime() {
+//	    return (__end - __begin);
+//}
+//  }
+//  
+    /** Wraps a thread so it can be timed with a group. */
+//    public static class TimingWrapper implements Runnable {
+//	private Runnable __runMe;
+//private ThreadTimer __timer;
+
+//	public TimingWrapper(Runnable runMe, ThreadTimer timer) {
+//    __runMe   = runMe;
+//    __timer   = timer;
+//}
+	
+//public void run() {
+//    // Note, this timing approach does not measure thread creation
+//    // and thread joining overhead.
+//    __timer.start();
+//    __runMe.run();
+//    __timer.stop();
+//}
+//  }
+
+
+//public static final int NUM_THREADS = 10;
+//public static final int NUM_LOOPS   = 10000000;
+    
+//   public static void main(String[] args) {
+//int thread;
+//ThreadTimer timer;
+//
+//	timer = new ThreadTimer(NUM_THREADS);
+
+	// Start a number of threads that iterate a dummy loop
+//	for(thread = 0; thread < NUM_THREADS; thread++)
+//    new Thread(new TimingWrapper(new Runnable() {
+//	    public void run() {
+//		for(int i=0; i < NUM_LOOPS; i++);
+//	    }
+//	}, timer)).start();
+//
+//timer.waitForResult();
+	
+//	System.out.println("Elapsed Seconds: " +
+//			   ((double)timer.getElapsedTime())/1000.0);
+//   }
+    
+//}*/
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/anttasks/MyGetUserAndPassword.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/anttasks/MyGetUserAndPassword.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/anttasks/MyGetUserAndPassword.java	(revision 13928)
@@ -0,0 +1,235 @@
+/*
+ *    MyGetUserAndPassword.java
+ *    Copyright (C) 2005 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.anttasks;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+
+/** A new ant task to prompt the user for username and password.
+ * To use this task, the compiled class must be put in the classpath. add a taskdef line to the build.xml:
+ * <taskdef name="getuserandpassword" classname="org.greenstone.anttasks.MyGetUserAndPassword" />
+ * and call it like the following:
+ *  <getuserandpassword 
+ *       message="a message to display at the top of the dialog" 
+ *       userproperty="the name of the username property to set (optional)" 
+ *       pwordproperty="the name of the password property to set" 
+ *       username="default value for username (optional)" 
+ *       if="property name (optional)" 
+ *       unless="property name (optional)"/>
+ * the if and unless attributes are used to control whether this task runs or not. If the 'if' attribute is set, the task will only run if the specified property is defined. If the unless attribute is set, the task will only run if the property is not defined.
+*/
+
+public class MyGetUserAndPassword
+    extends org.apache.tools.ant.Task {
+    
+    private String message = null;
+    private String user_property = null;
+    private String pword_property = null;
+    private String username = null;
+    private String password = null;
+    private boolean cancelled = false;
+
+    private Dimension SIZE = new Dimension(300, 150);
+    private JButton ok_button = null;
+    private JTextField name_field = null;
+    private JPasswordField pass_field = null;
+    
+    private boolean do_the_task = true;
+    public void setMessage(String m) {
+	message = m;
+    }
+
+    /** specify a property name - the task will only execute if this property is set */
+    public void setIf(String property) {
+	String value = getProject().getProperty(property);
+	if (value== null) {
+	    do_the_task = false;
+	}
+    }
+
+    public void setPwordproperty(String p_prop) {
+	pword_property = p_prop;
+    }
+    
+    /** specify a property name - the task will only execute if this property is not set */
+    public void setUnless(String property) {
+	String value = getProject().getProperty(property);
+	if (value != null) {
+	    do_the_task = false;
+	}
+    }
+    
+    public void setUsername(String user) {
+	username = user;
+    }
+
+    public void setUserproperty(String u_prop) {
+	user_property = u_prop;
+    }
+    public void execute() throws org.apache.tools.ant.BuildException {
+	
+	if (!do_the_task) {
+	    return;
+	}
+	if (pword_property == null) {
+	    throw new org.apache.tools.ant.BuildException("pwordproperty attribute must be specified");
+	}
+	
+	JFrame hiddenFrame = new JFrame("Username and Password Hidden Frame");
+	final JDialog dialog = new JDialog(hiddenFrame, "Username and Password", true);
+	JPanel content_pane = (JPanel)dialog.getContentPane();
+	content_pane.setLayout(new BorderLayout(5,5));
+	content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+	dialog.setLocation(200, 300);
+	dialog.setSize(SIZE);
+	dialog.addWindowListener(new WindowAdapter() {
+		public void windowClosing(WindowEvent windowEvent) {
+		    cancelled = true;
+		    dialog.dispose();
+		} 
+	    });
+	
+	JPanel button_pane = new JPanel();
+	button_pane.setLayout(new GridLayout(1,2));
+	JPanel details_pane = new JPanel();
+	details_pane.setLayout(new BorderLayout(5,5));
+	JPanel labels_pane = new JPanel();
+	labels_pane.setLayout(new GridLayout(2,1));
+	JPanel fields_pane = new JPanel();
+	fields_pane.setLayout(new GridLayout(2,1));
+	
+        JTextArea instruction_textarea = new JTextArea();
+	instruction_textarea.setEditable(false);
+	instruction_textarea.setLineWrap(true);
+	instruction_textarea.setRows(2);
+	instruction_textarea.setWrapStyleWord(true);
+	if (message == null) {
+	    message = "Please enter your username and password";
+	}
+	instruction_textarea.setText(message);
+		
+	JLabel name_label = new JLabel("User name:");
+	name_field = new JTextField(16);
+	if (username != null) {
+	    name_field.setText(username);
+	}
+	if (user_property == null ) {
+	    name_field.setEditable(false);
+	} 
+	JLabel pass_label = new JLabel("Password:");
+	pass_field = new JPasswordField(16);
+	
+	FieldListener field_listener = new FieldListener();
+	name_field.addActionListener(field_listener);
+	name_field.getDocument().addDocumentListener(field_listener);
+	pass_field.addActionListener(field_listener);
+	pass_field.getDocument().addDocumentListener(field_listener);
+
+	ok_button = new JButton("Ok");
+	ok_button.setEnabled(false);
+	ok_button.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent actionEvent) {
+		    username = name_field.getText();
+		    password = new String(pass_field.getPassword());
+		    dialog.dispose();
+		}
+	    });
+		
+	JButton cancel_button = new JButton("Cancel");
+	cancel_button.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent actionEvent) {
+		    cancelled = true;
+		    dialog.dispose();
+		}
+	    });
+	
+	button_pane.add(ok_button);
+	button_pane.add(cancel_button);
+		
+	labels_pane.add(name_label);
+	labels_pane.add(pass_label);
+
+	fields_pane.add(name_field);
+	fields_pane.add(pass_field);
+
+	details_pane.add(labels_pane, BorderLayout.WEST);
+	details_pane.add(fields_pane, BorderLayout.CENTER);
+	
+	content_pane.add(instruction_textarea, BorderLayout.NORTH);
+	content_pane.add(details_pane, BorderLayout.CENTER);
+	content_pane.add(button_pane, BorderLayout.SOUTH);
+		
+	dialog.show();
+	hiddenFrame.dispose();
+
+	if (cancelled) {
+	    throw new org.apache.tools.ant.BuildException("Cancelled by user.");
+	}
+	
+	if (user_property != null) {
+	    getProject().setProperty(user_property, username);
+	}
+	getProject().setProperty(pword_property, password);
+	
+	
+	
+    }
+    private class FieldListener
+	implements ActionListener, DocumentListener {
+	
+	public void actionPerformed(ActionEvent actionEvent) {
+	    validateOkButton();
+	}
+	public void changedUpdate(DocumentEvent e) {
+	    
+	    validateOkButton();
+	}
+
+	public void insertUpdate(DocumentEvent e) {
+            
+	    validateOkButton();
+	}
+	
+	public void removeUpdate(DocumentEvent e) {
+            
+	    validateOkButton();
+	}
+	
+	private void validateOkButton() {
+	    if (name_field.getText().length()!=0 && 
+		pass_field.getPassword().length!=0) {		
+		ok_button.setEnabled(true);
+	    } else {
+		ok_button.setEnabled(false);
+	    }
+	}
+    }
+    
+
+    public static void main(String [] args) {
+	MyGetUserAndPassword task = new MyGetUserAndPassword();
+	task.setMessage("hi there kath");
+	task.setUserproperty("username");
+	task.setPwordproperty("password");
+	task.execute();
+
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/anttasks/MySetProxy.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/anttasks/MySetProxy.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/anttasks/MySetProxy.java	(revision 13928)
@@ -0,0 +1,70 @@
+/*
+ *    MyGetUserAndPassword.java
+ *    Copyright (C) 2005 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.anttasks;
+
+import java.net.Authenticator;
+import java.net.PasswordAuthentication;      
+
+/** A new ant task for as the setproxy task has a bug in it.
+ * To use this task, the compiled class must be put in the classpath. add a taskdef line to the build.xml:
+ * <taskdef name="mysetproxy" classname="MySetProxy" />
+ * and call it like the following:
+ *  <mysetproxy proxyhost="" proxyport="" proxyuser="" proxypassword=""/>
+*/
+public class MySetProxy 
+    extends org.apache.tools.ant.Task {
+
+    String host = null;
+    String port = null;
+    String user = null;
+    String password = null;
+
+    public void setProxyhost(String proxy_host) {
+	host = proxy_host;
+    }
+
+    public void setProxyPort(int proxy_port) {
+	port = Integer.toString(proxy_port);
+    }
+
+    public void setProxyuser(String proxy_user) {
+	user = proxy_user;
+    }
+    
+    public void setProxypassword(String proxy_password) {
+	password = proxy_password;
+    }
+
+    public void execute() {
+
+	try {
+	    System.setProperty("http.proxyType", "4");
+	    System.setProperty("http.proxyHost", host);
+	    System.setProperty("http.proxyPort", port);
+	    System.setProperty("http.proxySet", "true");
+	    Authenticator.setDefault(new Authenticator(){ 
+		    protected PasswordAuthentication getPasswordAuthentication(){ 
+			return new PasswordAuthentication(user, new String(password).toCharArray()); 
+		    } 
+		}); 
+	} catch (Exception e) {
+	    System.err.println("MySetProxy Error: couldn't set up the proxy");    
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/Phind.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/Phind.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/Phind.java	(revision 13928)
@@ -0,0 +1,945 @@
+/**********************************************************************
+ *
+ * Phind.java -- the Phind java applet - modified to work with gsdl3 kjdon
+ *
+ * Copyright 1997-2000 Gordon W. Paynter
+ * Copyright 2000 The New Zealand Digital Library Project
+ *
+ * A component of the Greenstone digital library software
+ * from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *********************************************************************/
+
+
+/*********************************************************************
+
+To use the applet, you'll need to embed it in a web page like this:
+
+<APPLET CODE="Phind.class" WIDTH=500 HEIGHT=500>
+
+  <PARAM NAME=collection  VALUE="fao.org">
+  <PARAM NAME=classifier  VALUE="1">
+  <PARAM NAME=phindcgi    VALUE="http://kowhai/cgi-bin/phindcgi">
+  <PARAM NAME=library     VALUE="http://kowhai/cgi-bin/library">
+  <PARAM NAME=backdrop    VALUE="http://kowhai/~paynter/transfer/phindtest/green1.jpg">
+  The Phind java applet.
+</APPLET>
+
+There are a bunch of other parameters; these are described in the 
+getParameters method below.  It is all done for you in Greenstone
+in the document.dm macro file (the _phindapplet_ macro).
+
+You may have problems with Java applet security.  Java applet's can only
+open socket connections (including the HTTP connections the applet uses 
+to get data) to the same server the applet was loaded from.  This means
+that your phindcgi, library, and (optional) backdrop URLs must be on the
+same machine that your web page was loaded from.
+
+**********************************************************************
+
+The applet comprises several classes:
+
+1. Phind (this file) is the applet class, loaded by the browser.
+   It also handles network connections.
+2. ResultDisplay is a Panel that sits in the applet and displays 
+   things; displays are connected in a doubly-linked list.
+3. ResultBox holds the results of a query.  Result boxes are shown
+   to the user through ResultDisplays.  Another doubly-linked list.
+4. ResultTitle acts as a caption to a ResultBox describing its contents.
+5. ResultCanvas is what the ResultBox data is drawn on.  It draws the
+   words on the screen, and handles user input from the mouse.
+6. ResultItem represents a single result object (a phrase or document).
+7. PhindTitle is for drawing backdrops in ResultDisplays.
+
+**********************************************************************/
+
+package org.greenstone.applet.phind;
+
+import java.awt.BorderLayout;
+import java.awt.Button;
+import java.awt.Choice;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.GridLayout;
+import java.awt.Image;
+import java.awt.Label;
+import java.awt.Panel;
+import java.awt.TextField;
+import java.awt.event.ActionListener;
+import java.net.URL;
+import java.io.DataInputStream;
+
+import java.net.Socket;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.io.IOException;
+
+import java.util.Vector;
+import java.util.Date;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+//import javax.xml.parsers.*;
+import org.xml.sax.InputSource;
+import org.apache.xerces.parsers.DOMParser;
+
+
+public class Phind extends java.applet.Applet 
+    implements ActionListener {
+    
+    // What is the collection called?
+    public String collection;
+
+    // Which phind classifier are we using? (There may be more than one.)
+    public String classifier;
+
+    // Internet address of phind resources
+    public String library_address, phindcgi_address;
+
+    // Initial search term
+    public String initialSearch;
+
+    // Number of phrases to retrieve at any one time
+    public int phraseBlockSize;
+
+    // Appearance parameters
+    public boolean vertical;
+    public int depth;
+
+    // Font
+    public int fontSize;
+    public String fontName;
+    public Font plainFont, boldFont;
+
+    // Do we want a background image in the applet?
+    public boolean showImage;
+    public String backdrop_address;
+    public Image backgroundImage;
+    public boolean showBorder;
+
+    // Colours
+    public Color panel_fg, panel_bg,
+	column_1_fg, column_1_bg, 
+	column_2_fg, column_2_bg,
+	highlight_fg, highlight_bg,
+	thesaurus_fg, thesaurus_bg, thesaurus_bar_fg, thesaurus_bar_bg,
+	expansion_fg, expansion_bg, expansion_bar_fg, expansion_bar_bg,
+	document_fg, document_bg, document_bar_fg, document_bar_bg,
+	message_fg, message_bg;
+    
+    // Column dimensions
+    int column_1_width, column_2_width;
+
+    // Where do we open new windows
+    String searchWindowName, documentWindowName;
+
+    // the mode of operation
+    int mode;
+    final int initMode = 0;
+    final int idleMode = 1;
+    final int searchMode = 2;
+
+    // Elements of the control panel
+    boolean showControlPanel;
+    Label titleLabel;
+    TextField wordField;
+    Button searchButton, prevButton, nextButton;
+
+    // Holders for the downloaded data
+    Panel resultPanel;
+    ResultDisplay firstDisplay, lastDisplay;
+
+    // The time at which the last query finished
+    Date lastQueryEndTime;
+
+    // lastQueryEndTime is stored to ensure a 1 second gap between a query
+    // returning and a new one beginning.  It is needed because the FAO
+    // folks in Rome have a huge lag, and frquently click several times
+    // while they wait; these clicks are turned into new queries, which
+    // they await again.  It is no elegant solution, but it seems like the
+    // easiest, given that I don't know threads.
+    // 1. The search button is easy to disable, and is disabled when a
+    //    socket connection is in progress.
+    // 2. ResutCanvas widgets can'r be similarly disabled because the
+    //    browser hides or wipes them, which looks very bad.
+    // 3. I cannot just ignore clicks on canvasses because the browser
+    //    caches the clicks while the socket connection is going on, and then
+    //    sends them through afterwards, when the canvas is accepting clicks
+    //    again.
+    // 4. Current sequence of events is to record the time the last query
+    //    ends, then whenever a click happens make sure a second has past.  if
+    //    you double-click the the first query is sent, returns, end-tie is
+    //    set, and the second (and any others made during query time) is
+    //    *immediately* processed, but since 1 second hasn't past it is
+    //    ignored.
+
+  
+    public String getAppletInfo() {
+	return "Phind by Gordon Paynter (paynter@cs.waikato.ac.nz). Copyright 1997-2000.";
+    }
+
+
+    public void init() {
+
+	mode = initMode;
+	
+	// Read applet parameters
+	getParameters();
+
+	// Initialise the user interface
+	setBackground(panel_bg);
+	lastQueryEndTime = new Date();
+
+	// fonts used to output text
+	plainFont = new Font(fontName, Font.PLAIN, fontSize);
+	boldFont  = new Font(fontName, Font.BOLD, fontSize);
+
+	// The phind applet layout manager
+	setLayout(new BorderLayout());
+
+	// Panel containing the displays is in the center of the display
+	resultPanel = new Panel();
+	if (vertical) {
+	    resultPanel.setLayout(new GridLayout(depth,1,0,2));
+	} else {
+	    System.out.println("horizontal");
+	    resultPanel.setLayout(new GridLayout(1,depth,2,0));
+	}
+	add("Center", resultPanel);
+
+	// Create ResultDisplays and place into the interface
+	ResultDisplay d1, d2 = null;
+	firstDisplay = new ResultDisplay(this, null);
+	resultPanel.add(firstDisplay);
+
+	if (depth == 1) {
+	    lastDisplay = firstDisplay;
+	} else {
+	    d1 = firstDisplay;
+	    for (int i = 2; i <= depth; i++) {
+		d2 = new ResultDisplay(this, d1);
+		resultPanel.add(d2);
+		d1 = d2;
+	    }
+	    lastDisplay = d2;
+	}
+
+	// The control panel
+	initialiseControlPanel();
+
+	// lets get started then
+	setStatus("Welcome to Phind.");
+	mode = idleMode;
+
+	// Perform initial search, if requested
+	if (initialSearch.length() > 0) {
+	    searchForWord(initialSearch);
+	}
+    }
+
+
+    // Display a message in the status bar
+    void setStatus(String status) {
+	showStatus(status);
+    }
+
+    // The user performs an action in the interface
+    /*   public boolean action(Event evt, Object arg) {
+
+	if (evt.target == searchButton) {
+	    System.out.println("evt.target==searchButton");
+	    searchForWord(getSearchTerm());
+	} else if (evt.target == wordField) {
+	    System.out.println("evt.target==wordField");
+	    searchForWord(getSearchTerm());
+	} else if (evt.target == prevButton) {
+	    shiftPrevious();
+	} else if (evt.target == nextButton) {
+	    shiftNext();
+	} else {
+	    System.out.println("unknown action: " + evt.toString() 
+			       + ", object: " + arg.toString());
+	}
+	return true;
+    }
+
+    */
+
+    public void actionPerformed(ActionEvent evt) {
+	
+	Component target = (Component)evt.getSource();
+	if (target==searchButton) {
+	    System.out.println("search button pressed");
+	    searchForWord(getSearchTerm());
+	} else if (target == wordField)  {
+	    System.out.println("word field entered");
+	    searchForWord(getSearchTerm());
+	} else if (target == prevButton) {
+	    System.out.println("prev button pressed");
+	    shiftPrevious();
+	}else if (target == nextButton) {
+	    System.out.println("prev button pressed");
+	    shiftNext();
+	} else {
+	    System.out.println("unknown action: " + evt.toString() );
+	    
+	}
+    }
+
+    // Search for a word 
+    //
+    // Called on two occasions:
+    //   when the "Search" Button is pressed, or
+    //   to perform an "initial search"
+    void searchForWord(String searchWord) {
+
+	System.err.println("in searchforword!!");
+	if (mode == idleMode) {
+	    
+	    setSearchTerm(searchWord);
+
+	    // Convert the String from UTF8 charaters into 
+	    // an encoding that is okay for a URL.
+	    searchWord = URLUTF8Encoder.encode(searchWord);
+
+	    // Look up the word
+	    if (searchWord.length() > 1) {
+		setStatus("searching for \"" + searchWord + "\""); 
+		firstDisplay.emptyContents();
+		ResultBox result = lookupPhraseOnServer(null, false, searchWord, searchWord, 2);
+
+		// if there is an error, return
+		if (result == null) {
+		    setStatus("No results for \"" + searchWord + "\""); 
+		    return;
+		}
+
+		// display the result
+		result.display = firstDisplay.display(result);
+		result.setSize(result.display.getSize());
+		result.paintAll(result.getGraphics());
+	    }
+
+	    enablePreviousAndNext();
+	}
+    }
+  
+
+    // Search for a phrase
+    //
+    // If querymode is 2, the user has clicked on a phrase.
+    // If querymode is 3, the user has requested more phrases.
+    // If querymode is 4, the user has requested more documents.
+    void searchForPhrase(ResultBox source, String key, String phrase, int queryMode) {
+
+	// System.out.println("searchForPhrase: " + key + " " + phrase + " " + queryMode);
+
+	if (mode == idleMode) {
+
+	    // If we are going to replace the first ResultDisplay, then empty it
+	    if (queryMode <= 2) {
+		if (source.display.next != null) source.display.next.emptyContents();
+	    }
+
+	    // look up the word
+	    setStatus("Searching for \"" + phrase + "\""); 
+	    ResultBox result = lookupPhraseOnServer(source, true, key, phrase, queryMode);
+	    if (result == null) {
+		setStatus("No result for \"" + phrase + "\""); 
+		return;
+	    }
+
+	    // If this is not already displayed, display it in the last free spot
+	    if (queryMode <= 2) {
+		result.display = lastDisplay.display(result);
+		result.setSize(result.display.getSize());
+		result.paintAll(result.getGraphics());
+	    }
+
+	    enablePreviousAndNext();
+	}
+    }
+
+
+    // Look up a phrase (or symbol) on the server
+    //
+    // Arguments are the source of the query (a ResultBox, or null if the
+    // query comes from hitting the search button), the key to search for
+    // (the text of a phrase or a symbol number), the phrase as a string, 
+    // and the query mode.
+    // Query modes are: 
+    //   0 = obsolete
+    //   1 = obsolete
+    //   2 = get first N phrases and URLs,
+    //   3 = get another N phrases into same window
+    //   4 = get another N documents into same window
+    //   5 = get another N thesaurus links into same window
+
+    ResultBox lookupPhraseOnServer(ResultBox source, 
+				   boolean keyKnown, String key, String phrase, 
+				   int queryMode) { 
+    	disableSearchButton();
+	mode = searchMode;
+	ResultBox r = null;
+
+	if (queryMode <= 2) {
+	    r = new ResultBox(this, collection, key, phrase, source);
+	} else if ((queryMode == 3) || (queryMode == 4) || (queryMode == 5)) {
+	    r = source;
+	}
+
+	try { 
+	    queryServer(keyKnown, key, queryMode, r);
+	} catch (Exception e) { 
+	    System.out.println("Phind query error: " + e.toString());
+	    setStatus("Query error: " + e.toString());
+	    mode = idleMode;
+	    enableSearchButton();
+	    return null;
+	}
+      
+	// The query is finished
+	setStatus(r.c.numberOfItems + " results for \"" + phrase + "\""); 
+	mode = idleMode;
+	enableSearchButton();
+	lastQueryEndTime = new Date();
+
+	return r;
+    }
+
+
+    // Query the phindcgi program
+    //
+    // Send a query (a word or symbol number) to the server
+    // and pass the response to a ResultBox.
+
+    void queryServer(boolean keyKnown, String word, int queryMode, ResultBox area) 
+	throws IOException {
+
+	// Build the query
+	String query = phindcgi_address + "c=" + collection + "&pc=" + classifier;
+
+	if (keyKnown) {
+	  query = query + "&ppnum=" + word;
+	} else {
+	  query = query + "&ppnum=0" + "&pptext=" + word;
+	}
+
+	
+	// Specify the set of results to return 
+	int first_e = 0;
+	int last_e = 0;
+	int first_d = 0;
+	int last_d = 0;
+	int first_l = 0;
+	int last_l = 0;
+
+	// the initial query
+	if (queryMode <= 2) {
+	  last_e = phraseBlockSize;
+	  last_d = phraseBlockSize;
+	  last_l = phraseBlockSize;
+	}
+
+	// add phrases to an existing result set
+	else if (queryMode == 3) {
+	  first_e = area.nextPhraseBlock * phraseBlockSize;
+	  area.nextPhraseBlock++;
+	  last_e = area.nextPhraseBlock * phraseBlockSize;
+	} 
+	
+	// add documents to existing result set
+	else if (queryMode == 4) {
+	  first_d = area.nextDocumentBlock * phraseBlockSize;
+	  area.nextDocumentBlock++;
+	  last_d = area.nextDocumentBlock * phraseBlockSize;
+	}
+
+	// add thesaurus links to existing result set
+	else if (queryMode == 5) {
+	  first_l = area.nextThesaurusLinkBlock * phraseBlockSize;
+	  area.nextThesaurusLinkBlock++;
+	  last_l = area.nextThesaurusLinkBlock * phraseBlockSize;
+	}
+
+	query = query + "&pfe=" + first_e + "&ple=" + last_e
+                      + "&pfd=" + first_d + "&pld=" + last_d
+                      + "&pfl=" + first_l + "&pll=" + last_l;
+
+	// Send the query to the phindcgi program 
+	System.out.println("1:sending query: " + query);
+	try {
+	    URL phindcgi = new URL(query);
+	    DataInputStream in = new DataInputStream(phindcgi.openStream());
+	    DOMParser parser = new DOMParser();
+	    parser.parse(new InputSource(in));
+	    Document data_doc = parser.getDocument();
+	    Element data_elem = data_doc.getDocumentElement();
+	    area.parseXML(data_elem);
+	    in.close();
+	} catch (Exception e) {
+	    System.err.println( "Error sending query to phindcgi: " + e);
+	    e.printStackTrace();
+	}
+	area.repaint();
+    }
+    
+
+    // Tidy up URLs
+    //
+    // Ensure a URL address (as string) has a protocol, host, and file.
+    //
+    // If the URL is a CGI script URL, it should be tidied up so that it is
+    // appropriate to tage attrib=value pairs on the end.  This means it
+    // must either end with a "?" or (if it contains a question-mark
+    // internally) end with a "&".
+    String tidy_URL(String address, boolean isCGI) {
+
+	// System.err.println("tidy URL: " + address);
+	
+	// make sure the URL has protocol, host, and file
+	if (address.startsWith("http")) {
+	    // the address has all the necessary components
+	} else if (address.startsWith("/")) {
+	    // there is not protocol and host
+	    URL document = getDocumentBase();
+	    String port = "";
+	    if (document.getPort()!=-1) {
+		port = ":" + document.getPort();
+	    }
+	    address = "http://" + document.getHost() + port  + address;
+	} else {
+	    // this URL is relative to the directory the document is in
+	    URL document = getDocumentBase();
+	    String directory = document.getFile();
+	    int end = directory.lastIndexOf('/');
+	    String port = "";
+	    if (document.getPort()!=-1) {
+		port = ":" + document.getPort();
+	    }
+	    directory = directory.substring(0,end + 1);
+	    address = "http://" + document.getHost() + port + directory + address;
+
+	}
+
+	// if the URL is a cgi script, make sure it has a "?" in ti,
+	// and that it ends with a "?" or "&"
+	if (isCGI) {
+	    if (address.indexOf((int) '?') == -1) { 
+		address = address + "?";
+	    } else if (!address.endsWith("?")) {
+		address = address + "&";
+	    }
+	}
+
+	return address;
+    }
+
+
+
+    // Open an arbitrary web page
+    void displayWebPage(String address, String window) {
+	try { 
+	    URL url= new URL(address);
+	    if (window.length() > 0) {
+		getAppletContext().showDocument(url, window);
+	    } else {
+		getAppletContext().showDocument(url);
+	    }
+	} catch (Exception e) { 
+	    System.out.println("Cannot open web page: " + e.toString());
+	}
+    }
+
+
+    // Get the applet parameters
+    void getParameters() {
+
+	// What is this collection called?
+	collection = parameterValue("collection");
+	System.out.println("Phind collection: " + collection);
+
+	// Which of the collection's classifiers are we using?
+	classifier = parameterValue("classifier", "1");
+	System.out.println("Phind classifier: " + classifier);
+
+	// Where is the Greenstone library
+	library_address = parameterValue("library");
+	library_address = tidy_URL(library_address, true);
+	System.out.println("Phind library: " + library_address);
+
+	// Where is the phind CGI script
+	// we assume this is relative to the greenstone library
+	phindcgi_address = parameterValue("library")+parameterValue("phindcgi");
+	phindcgi_address = tidy_URL(phindcgi_address, true);
+	System.out.println("Phind phindcgi: " + phindcgi_address);
+
+	
+	// Is there a default search term?
+	initialSearch = parameterValue("initial_search", "");
+
+	// Should we display the control panel
+	showControlPanel = true;
+	if (parameterValue("control_panel", "show").toLowerCase().equals("hide")) {
+	    showControlPanel = false;
+	}
+	
+	// Should we show a background image?
+	backdrop_address = parameterValue("backdrop", "");
+	if (backdrop_address.length() > 0) {
+	    backdrop_address = tidy_URL(backdrop_address, false);
+	    System.out.println("Phind backdrop URL: " + backdrop_address);
+
+	    try {
+		URL backdrop_url = new URL(backdrop_address);
+		backgroundImage = getImage(backdrop_url);
+		showImage = true;
+	    } catch (Exception e) { 
+		System.out.println("Phind could not load " + backdrop_address);
+		showImage = false;
+	    }
+	}
+
+	// Should we draw a border?
+	showBorder = parameterValue("border", "on").equals("off");
+
+	// Are the windows arranged vertically or horizontally
+	if (parameterValue("orientation", "vertical").toLowerCase().startsWith("hori")) {
+	    vertical = false;
+	} else {
+	    vertical = true;
+	}
+	
+	// How many phind windows are there?
+	depth = parameterValue("depth", 3);
+
+	// Result sort order
+	// Standard is "LlEeDd", expansion-first is "EeLlDd"
+	String order = parameterValue("resultorder", "standard");
+	if (!order.equals("standard")) {
+	    int next = 20;
+	    ResultItem.sortMessage = next;
+	    for (int x = 0; x < order.length(); x++) {
+		if (order.charAt(x) == ',') {
+		    next--;
+		} else if (order.charAt(x) == 'L') {
+		    ResultItem.sortLinkItem = next;
+		} else if (order.charAt(x) == 'l') {
+		    ResultItem.sortMoreLinks = next;
+		} else if (order.charAt(x) == 'E') {
+		    ResultItem.sortPhraseItem = next;
+		} else if (order.charAt(x) == 'e') {
+		    ResultItem.sortMorePhrases = next;
+		} else if (order.charAt(x) == 'D') {
+		    ResultItem.sortDocumentItem = next;
+		} else if (order.charAt(x) == 'd') {
+		    ResultItem.sortMoreDocuments = next;
+		}
+	    }
+	    System.out.println("link: " + ResultItem.sortLinkItem);
+	    System.out.println("exps: " + ResultItem.sortPhraseItem);
+	    System.out.println("docs: " + ResultItem.sortDocumentItem);
+
+	}
+
+	// How many phrases should we fetch at any given time?
+	phraseBlockSize = parameterValue("blocksize", 10);
+
+	// What font should we use?
+	fontSize = parameterValue("fontsize", 10);
+	fontName = parameterValue("fontname", "Helvetica");
+
+	// Column dimensions
+	column_1_width = parameterValue("first_column_width", 6);
+	column_2_width = parameterValue("second_column_width", column_1_width);
+	
+	// Where do we open new windows
+	searchWindowName = parameterValue("search_window", "phindsearch");
+	documentWindowName = parameterValue("document_window", "phinddoc");
+
+	// Colours
+	panel_fg = parameterValue("panel_fg", Color.black);
+	panel_bg = parameterValue("panel_bg", Color.white);
+
+	highlight_bg = parameterValue("highlight_bg", Color.yellow);
+
+	expansion_fg = parameterValue("expansion_fg", Color.black);
+	thesaurus_fg = parameterValue("thesaurus_fg", new Color(0, 100, 0));
+	document_fg = parameterValue("document_fg", Color.blue);
+
+	thesaurus_bar_fg = parameterValue("thesaurus_bar_fg", Color.black);
+	expansion_bar_fg = parameterValue("expansion_bar_fg", Color.black);
+	document_bar_fg = parameterValue("document_bar_fg", Color.black);
+
+	thesaurus_bar_bg = parameterValue("thesaurus_bar_bg", new Color(160, 160, 190));
+	expansion_bar_bg = parameterValue("expansion_bar_bg", new Color(255, 200, 200));
+	document_bar_bg = parameterValue("document_bar_bg", new Color(150, 193, 156));
+
+	column_1_fg = parameterValue("first_column_fg", Color.black);
+	column_1_bg = parameterValue("first_column_bg", new Color(235, 245, 235));
+	column_2_fg = parameterValue("second_column_fg", Color.black);
+	column_2_bg = parameterValue("second_column_bg", new Color(200, 220, 200));
+
+	message_fg = parameterValue("message_fg", Color.black);
+	message_bg = parameterValue("message_bg", Color.white);
+
+	// Colours I don't use, yet
+	// thesaurus_bg = parameterValue("thesaurus_bg", Color.white);
+	// expansion_bg = parameterValue("expansion_bg", Color.white);
+	// document_bg = parameterValue("document_bg", Color.white);
+    }
+
+    // Get the value of a parameter given its name.
+    // There are many types of parameters, hence the variety of functions.
+
+    // Get a REQUIRED string.  Stop the applet if we cannot.
+    String parameterValue(String name) {
+	try { 
+	    return getParameter(name);
+	} catch (Exception e) {
+	    System.err.println("Phind: you must give a parameter for \"" 
+			       + name + "\".  Stopping.");
+	    stop();
+	}
+	return "";
+    }
+
+    // Get an optional parameter.  Return a default if we cannot.
+    String parameterValue(String name, String defaultValue) {
+	String text = getParameter(name);
+	if (text == null) {
+	    return defaultValue;
+	}
+	System.out.println("Phind " + name + ": " + text);
+	return text;
+    }
+
+    int parameterValue(String name, int defaultValue) {
+	int value;
+	try { 
+	    value = Integer.parseInt(getParameter(name));
+	} catch (Exception e) {
+	    return defaultValue;
+	}
+	System.out.println("Phind " + name + ": " + value);
+	return value;
+    }
+
+    Color parameterValue(String name, Color defaultValue) {
+
+	String text = getParameter(name);
+	if (text == null) {
+	    return defaultValue;
+	}
+	text = text.toLowerCase();
+
+	// a number of the form "#ddffee" 
+	if (text.startsWith("#") && (text.length() == 7)) {
+	    text = text.substring(1);
+	    int r, g, b;
+	    try {
+		r = Integer.parseInt(text.substring(0,2), 16);
+		g = Integer.parseInt(text.substring(2,4), 16);
+		b = Integer.parseInt(text.substring(4), 16);
+		return new Color(r, g, b);
+	    }  catch (Exception e) {
+		return defaultValue;
+	    }
+	}
+
+	// a known Java colour string
+	else if (text.equals("black")) { return Color.black; }
+	else if (text.equals("blue")) { return Color.blue; }
+	else if (text.equals("cyan")) { return Color.cyan; }
+	else if (text.equals("darkgray")) { return Color.darkGray; }
+	else if (text.equals("gray")) { return Color.gray; }
+	else if (text.equals("green")) { return Color.green; }
+	else if (text.equals("lightgray")) { return Color.lightGray; }
+	else if (text.equals("magenta")) { return Color.magenta; }
+	else if (text.equals("orange")) { return Color.orange; }
+	else if (text.equals("pink")) { return Color.pink; }
+	else if (text.equals("red")) { return Color.red; }
+	else if (text.equals("white")) { return Color.white; }
+	else if (text.equals("yellow")) { return Color.yellow; }
+
+	return defaultValue;
+    }
+
+
+    // Control panel operations
+
+    // Initialise the control panel
+    void initialiseControlPanel() {
+	
+	if (showControlPanel) {
+	    Panel p1 = new Panel();
+	    add("North", p1);
+	    p1.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
+	    
+	    searchButton = new Button("Search");
+	    searchButton.setFont(boldFont);
+	    //searchButton.setEnabled(true);
+	    searchButton.addActionListener(this);
+	    p1.add(searchButton);
+	    
+	    Label tempLabel = new Label("  for");
+	    tempLabel.setFont(boldFont);
+	    p1.add(tempLabel);
+	    
+	    wordField = new TextField(12);
+	    wordField.setFont(boldFont);
+	    wordField.addActionListener(this);
+	    p1.add(wordField);
+	    
+	    Label temp2 = new Label("          ");
+	    p1.add(temp2);
+	    
+	    prevButton = new Button("Previous");
+	    prevButton.setFont(boldFont);
+	    prevButton.addActionListener(this);
+	    prevButton.setEnabled(false);
+	    
+	    p1.add(prevButton);
+	    
+	    nextButton = new Button("  Next  ");
+	    nextButton.setFont(boldFont);
+	    nextButton.addActionListener(this);
+	    nextButton.setEnabled(false);
+	    p1.add(nextButton);
+	    
+	}
+    }
+    
+    // Button and field functionality
+    
+    // Enable and disable the word field
+    void enableSearchButton() {
+	if (showControlPanel) {
+	    searchButton.setEnabled(true);
+	}
+    }
+    void disableSearchButton() {
+	if (showControlPanel) {
+	    searchButton.setEnabled(false);
+	}
+    }
+
+    // Get and set the search text in the wordField
+    String getSearchTerm() {
+	if (showControlPanel) {
+	    return wordField.getText();
+	} else {
+	    return initialSearch;
+	}
+    }
+    void setSearchTerm(String word) {
+	if (showControlPanel) {
+	    wordField.setText(word);
+	} 
+    }
+
+    // Enable or disable the "Previous" and "Next" buttons
+    void enablePreviousAndNext() {
+	if (showControlPanel) {
+	    Component c = firstDisplay.current;
+	    if (c.getClass().getName().endsWith("ResultBox")) {
+		if (((ResultBox) c).prevBoxExists()) {
+		    prevButton.setEnabled(true);
+		} else {
+		    prevButton.setEnabled(false);
+		}
+	    }
+	    
+	    c = lastDisplay.current;
+	    if (c.getClass().getName().endsWith("ResultBox")) {
+		if (((ResultBox) c).nextBoxExists()) {
+		    nextButton.setEnabled(true);
+		} else {
+		    nextButton.setEnabled(false);
+		}
+	    }
+	}
+    }
+
+    // Shift to previous box
+    //
+    // If the user clicks "Previous" then scroll up.
+    void shiftPrevious() {
+
+	Component c = firstDisplay.current;
+	if (c.getClass().getName().endsWith("ResultBox")) {
+
+	    ResultBox b = (ResultBox) c;
+	    if (b.prevBoxExists()) {
+		b = b.prev;
+
+		// empty all the displays
+		firstDisplay.emptyContents();
+
+		// add as many result boxes as there are displays
+		for (int i = 1 ; ((i <= depth) && (b != null)); i++) {
+		    lastDisplay.display(b);
+		    b.setSize(b.display.getSize());
+		    b.paintAll(b.getGraphics());
+		    b = b.next;
+		}
+	    }
+	}
+	enablePreviousAndNext();
+    }
+
+    // Shift to next box
+    //
+    // If the user clicks "Next" then scroll down if possible
+    void shiftNext() {
+
+	Component c = lastDisplay.current;
+	if (c.getClass().getName().endsWith("ResultBox")) {
+
+	    ResultBox b = (ResultBox) c;
+	    if (b.nextBoxExists()) {
+
+		// find the new "first" displayed box
+		c = firstDisplay.current;
+		b = (ResultBox) c;
+		b = b.next;
+
+		// empty all the displays
+		firstDisplay.emptyContents();
+
+		// add as many result boxes as there are displays
+		for (int i = 1 ; ((i <= depth) && (b != null)); i++) {
+		    lastDisplay.display(b);
+		    b.setSize(b.display.getSize());
+		    b.paintAll(b.getGraphics());
+		    b = b.next;
+		}
+	    }
+	}
+	enablePreviousAndNext();
+    }
+
+
+
+
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/PhindTitle.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/PhindTitle.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/PhindTitle.java	(revision 13928)
@@ -0,0 +1,84 @@
+/**********************************************************************
+ *
+ * PhindTitle.java -- backdrops to empty ResultDisplay panels.
+ *
+ * Copyright 1997-2000 Gordon W. Paynter
+ * Copyright 2000 The New Zealand Digital Library Project
+ *
+ * A component of the Greenstone digital library software
+ * from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *********************************************************************/
+
+
+/*********************************************************************
+
+PhindTitle is for drawing backdrops in empty ResultDisplay panels.
+
+**********************************************************************/
+package org.greenstone.applet.phind;
+//package org.nzdl.gsdl.Phind;
+
+import java.applet.Applet;
+import java.awt.Canvas;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Image;
+
+public class PhindTitle extends Canvas {
+
+    Phind phind;
+    static Image backgroundImage;
+    boolean displayInfo;
+    
+    PhindTitle(Phind p) {
+	phind = p;
+    }
+
+    public void update(Graphics g) {
+	paint(g);
+    }
+
+    public void paint(Graphics g) {
+	Dimension canvasSize = getSize();
+
+	Color fore = phind.panel_fg;
+	Color back = phind.panel_bg;
+
+	// set the screen background
+	if (phind.showImage)
+	    try {
+		g.drawImage(phind.backgroundImage, 
+			    0, 0, canvasSize.width, canvasSize.height, back, null);
+	    } catch (Exception e) {
+		System.err.println("PhindTitle paint: "  + e);
+	    }
+	else {
+	    g.setColor(back);
+	    g.fillRect(0,0, canvasSize.width, canvasSize.height);
+	}
+    }
+}
+
+ 
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/ResultBox.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/ResultBox.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/ResultBox.java	(revision 13928)
@@ -0,0 +1,423 @@
+/**********************************************************************
+ *
+ * ResultBox.java -- a list of phrases in the Phind java interface
+ *
+ * Copyright 1997-2000 Gordon W. Paynter
+ * Copyright 2000 The New Zealand Digital Library Project
+ *
+ * A component of the Greenstone digital library software
+ * from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *********************************************************************/
+
+/*********************************************************************
+
+This class is used in the Phind java applet (Phind.java).
+
+A ResultBox holds the results of a query to phindcgi.  They deal mostly
+with the information content of the query, and have methods for parsing the
+input into phrase and document items.  They have little do with display:
+ResultBoxes are shown to the user through "ResultDisplay" panels, and are
+drawn using "ResultCanvas" objects.
+
+**********************************************************************/
+package org.greenstone.applet.phind;
+//package org.nzdl.gsdl.Phind;
+
+import java.awt.Panel;
+import java.awt.BorderLayout;
+import java.awt.Scrollbar;
+
+import java.awt.Label;
+import java.awt.AWTEvent;
+import java.awt.event.AdjustmentListener;
+import java.awt.event.AdjustmentEvent;
+import java.net.*;
+import java.applet.*;
+
+import java.util.Vector;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class ResultBox extends Panel 
+    implements AdjustmentListener {
+    
+    // Objects at a "higher" level than this one
+    Phind phind;
+    ResultDisplay display;
+
+    // Surroundig objects
+    ResultBox prev, next;
+
+    // The components contained by this one.
+    ResultCanvas c;
+    ResultTitle t;
+    Scrollbar s;
+    Panel label;
+
+    // The key identifying the phrase displayed, with its text and the
+    // collection from which it is drawn
+    String searchKey, searchPhrase, searchCollection;
+    
+    // The total frequency, expansion frequency, and document frequency
+    // of the phrase
+    int numberOfOccurances;
+    int numberOfExpansions;
+    int numberOfDocuments;
+    int numberOfThesaurusLinks;
+
+    // The number of phrases and documents retrieved, and the number of
+    // times the user has requested more phrases or documents.
+    int expansionsRetrieved;
+    int documentsRetrieved;
+    int thesaurusLinksRetrieved;
+    int nextPhraseBlock;
+    int nextDocumentBlock;
+    int nextThesaurusLinkBlock;
+    
+    int mode;
+    final int initMode = 0;
+    public final int emptyMode = 1;
+    final int loadingMode = 2;
+    final int finishedMode = 3;
+
+    String buffer;
+    boolean finished;
+
+
+    // Create a ResultBox
+    // given details of the search that generated it.
+    ResultBox(Phind p, String collect, String key, String phrase, ResultBox rb) {
+
+	super();
+	mode = initMode;
+
+	phind = p;
+	display = null;
+	next = null;
+	prev = rb;
+	if (prev != null) prev.next = this;
+
+	searchKey = key;
+	searchPhrase = phrase;
+	searchCollection = collect;
+
+	numberOfOccurances = -1;
+	numberOfExpansions = -1;
+	numberOfDocuments = -1;
+	numberOfThesaurusLinks = -1;
+
+	expansionsRetrieved = 0;
+	documentsRetrieved = 0;
+	thesaurusLinksRetrieved = 0;
+
+	nextPhraseBlock = 1;
+	nextDocumentBlock = 1;
+	nextThesaurusLinkBlock = 1;
+
+
+	setLayout(new BorderLayout());
+
+	s = new Scrollbar(Scrollbar.VERTICAL);
+	disableScrollbar();
+	s.addAdjustmentListener(this);
+	add("East", s);
+
+	c = new ResultCanvas(this);
+	add("Center", c);
+
+	t = new ResultTitle(this);
+	add("North", t);
+
+	buffer = "";
+	finished = false;
+	mode = emptyMode;
+    }
+
+    static String describeContents(String phrase, String c) {
+	return( "\"" + phrase + "\" in " + c + ".");
+    }
+
+    String describeContents() {
+	return( describeContents(searchPhrase, searchCollection) );
+    }
+
+
+    // Reset the contents of the box
+    void resetBox( ) {
+	buffer = "";
+	finished = false;
+	c.resetCanvas();
+	disableScrollbar();
+	mode = emptyMode;
+    
+	numberOfExpansions = -1;
+	numberOfDocuments = -1;
+	numberOfThesaurusLinks = -1;
+
+	expansionsRetrieved = 0;
+	documentsRetrieved = 0;
+	thesaurusLinksRetrieved = 0;
+    }
+
+    void setStatus( String status ) {
+	phind.setStatus(status);
+    }
+
+    void disableScrollbar() {
+	if (s.isEnabled()) {
+	    s.setValues(0, 1, 0, 1);
+	    s.setUnitIncrement(1);
+	    s.setBlockIncrement(1);
+	    s.setEnabled(false);
+	}
+    }
+
+    // Are there displays previous to and after this?
+    public boolean prevBoxExists () {
+	return (prev != null);
+    }
+    public boolean nextBoxExists () {
+	return (next != null);
+    }
+
+    
+    // Look up a phrase
+    // Phrase lookups are passed on to the Phind applet itself.
+    void lookupPhrase(String key, String phrase, int queryMode) {
+	buffer = "";
+	finished = false;
+	phind.searchForPhrase(this, key, phrase, queryMode);
+	t.repaint();
+    }
+
+    /*   public void processEvent(AWTEvent event) {
+	//    System.out.println("event: " + event.toString());
+	if ( (event.target == s) && 
+	     ( (event.id == Event.SCROLL_ABSOLUTE) ||
+	       (event.id == Event.SCROLL_LINE_DOWN) ||
+	       (event.id == Event.SCROLL_LINE_UP) ||
+	       (event.id == Event.SCROLL_PAGE_DOWN) ||
+	       (event.id == Event.SCROLL_PAGE_UP) ) ) {
+	    c.repaint();
+	    
+	} else {
+	    super.processEvent(event);
+	}
+	} */  
+
+    public void adjustmentValueChanged(AdjustmentEvent evt) {
+	c.repaint();
+    }
+
+    void parseXML(Element data) {
+
+	//System.out.println("phinddata:"+data.toString());
+
+	//String id="", phrase="";
+	//int df=0, ef=0, lf=0, tf=0;
+	
+	searchKey = data.getAttribute("id");
+	
+	numberOfDocuments = Integer.valueOf(data.getAttribute("df")).intValue();
+	numberOfExpansions = Integer.valueOf(data.getAttribute("ef")).intValue();
+	numberOfThesaurusLinks = Integer.valueOf(data.getAttribute("lf")).intValue();
+	numberOfOccurances = Integer.valueOf(data.getAttribute("tf")).intValue();
+
+	//searchPhrase = "cat"; // for now
+
+	// go through children
+	Node e = data.getFirstChild();
+	while (e!=null) {
+	    String node_name = e.getNodeName();
+	    if (node_name.equals("phrase")) {
+		// the value of the phrase
+		searchPhrase = getNodeText(e);
+	    } else if (node_name.equals("expansionList")) {
+		
+		NodeList expansions = ((Element)e).getElementsByTagName("expansion");
+		for (int i=0; i<expansions.getLength(); i++) {
+		    processExpansionElement((Element)expansions.item(i));
+		}
+	    } else if (node_name.equals("documentList")) {
+			
+		NodeList documents = ((Element)e).getElementsByTagName("document");
+		for (int i=0; i<documents.getLength(); i++) {
+		    processDocumentElement((Element)documents.item(i));
+		}
+	
+	
+	    } else if (node_name.equals("thesaurusList")) {
+				
+		NodeList thesaurai = ((Element)e).getElementsByTagName("thesaurus");
+		for (int i=0; i<thesaurai.getLength(); i++) {
+		    processThesaurusElement((Element)thesaurai.item(i));
+		}
+		
+	    } else {
+		System.out.println("error in phinddata format, have unwanted node, "+node_name);
+	    }
+	    e = e.getNextSibling();
+	}
+	// finished parsing, update the getMoreDocs markers
+	c.updateMarkers();
+    }
+
+
+    /** Add an expansion tag
+     *
+     * Given a string containing an XML expansion element of the form:
+     *   <expansion num="3" id="8421" prefix="PEOPLE and" suffix="" tf="3" df="3"><suffix></suffix><prefix>PEOPLE</prefix></expansion>
+     *
+     * Create a new ResultItemPhrase for display
+     *
+     *  Return true if successful, otherwise false. */
+    boolean processExpansionElement(Element e) {
+
+	String num = "", id = "", tf = "", df = "", 
+	    prefix = "", body = "", suffix = "";
+
+	body = searchPhrase;
+
+	id = e.getAttribute("id");
+	tf = e.getAttribute("tf");
+	df = e.getAttribute("df");
+	num = e.getAttribute("num");
+
+	// get prefix child
+	Node prefix_node = getChildByTagName(e, "prefix");
+	if (prefix_node!=null) {
+	    prefix = getNodeText(prefix_node);
+	}
+	Node suffix_node = getChildByTagName(e, "suffix");
+	if (suffix_node !=null) {
+	    suffix = getNodeText(suffix_node);
+	}
+
+	ResultItemPhrase ri = new ResultItemPhrase(id, tf, df, prefix, body, suffix);
+	
+	if (c.addResultItem(ri)) {
+	    expansionsRetrieved++;
+	    return true;
+	}
+	
+	return false;
+    }
+
+    /** Add a document tag
+     *
+     * Given an XML Element of the form:
+     *   <document num="2" hash="HASH424e64b811fdad933be69c" freq="1"><title>CONTENTS</title></document>
+     *
+     * Create a new ResultItemDocument for display
+     *
+     * Return true if successful, otherwise false. */
+
+    boolean processDocumentElement(Element d ) {
+	// why do we have num??
+	String num = "", hash = "", freq = "", title = "";
+
+	num = d.getAttribute("num");
+	freq = d.getAttribute("freq");
+	hash = d.getAttribute("hash");
+
+	Node title_node = getChildByTagName(d, "title");
+	if (title_node != null) {
+	    title = getNodeText(title_node);
+	}
+	// Create a new ResultItem and add it to the display
+	ResultItemDocument ri = new ResultItemDocument(hash, title, freq);
+	
+	if (c.addResultItem(ri)) {
+	    documentsRetrieved++;
+	    return true;
+	}
+	
+	return false;
+    }
+
+    /** Add a thesaurus tag
+     *
+     * Given an  XML element  of the form:
+     *
+     * <thesaurus num="3" id="36506" tf="0" df="0" type="RT"><phrase>ANGLOPHONE AFRICA</phrase></thesaurus>
+     *
+     * Create a new ResultItemLink for display
+     *
+     * Return true if successful, otherwise false. */
+
+    boolean processThesaurusElement(Element t ) {
+	
+	// why do we have num??? - not used anywhere
+	String num = "", id = "", tf = "", df = "", type = "", phrase = "";
+
+	id = t.getAttribute("id");
+	tf = t.getAttribute("tf");
+	df = t.getAttribute("df");
+	type = t.getAttribute("type");
+	num = t.getAttribute("num");
+
+	Node phrase_node = getChildByTagName(t, "phrase");
+	if (phrase_node !=null) {
+	    phrase = getNodeText(phrase_node);
+	}
+	// Create a new ResultItem and add it to the display
+	ResultItemLink ri = new ResultItemLink(id, phrase, type, tf, df);
+
+	if (c.addResultItem(ri)) {
+	    thesaurusLinksRetrieved++;
+	    return true;
+	}
+	
+	return false;
+    }
+
+    /** extracts the text out of a node */
+    protected String getNodeText(Node elem) {
+	elem.normalize();
+	Node n = elem.getFirstChild();
+	while (n!=null && n.getNodeType() !=Node.TEXT_NODE) {
+	    n=n.getNextSibling();
+	}
+	if (n==null) { // no text node
+	    return "";
+	}
+	return n.getNodeValue();
+    }
+
+    /** returns the (first) child element with the given name */
+    protected Node getChildByTagName(Node n, String name) {
+
+	Node child = n.getFirstChild();
+	while (child!=null) {
+	    if (child.getNodeName().equals(name)) {
+		return child;
+	    }
+	    child = child.getNextSibling();
+	}
+	return null; //not found
+    }
+
+
+}
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/ResultCanvas.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/ResultCanvas.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/ResultCanvas.java	(revision 13928)
@@ -0,0 +1,647 @@
+/**********************************************************************
+ *
+ * ResultCanvas.java -- a Canvas onto which a phrase list is drawn
+ *
+ * Copyright 1997-2000 Gordon W. Paynter
+ * Copyright 2000 The New Zealand Digital Library Project
+ *
+ * A component of the Greenstone digital library software
+ * from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *********************************************************************/
+
+/*********************************************************************
+
+This class is used in the Phind java applet (Phind.java).
+
+The results of a query are displayed on a ResultCanvas object.  Each 
+entry in the result list is stored in a ResultItem, and the ResultCanvas 
+contains a Vector of ResultItems.
+
+Each ResultCanvas is embedded in a ResultBox alongside a Scrollbar.  
+When the ResultCanvas is drawn, it looks at the scrollbar, calculates 
+which ResultItems are visible, then draws them on the screen.
+
+**********************************************************************/
+
+package org.greenstone.applet.phind;
+//package org.nzdl.gsdl.Phind;
+
+import java.awt.Canvas;
+import java.awt.Scrollbar;
+import java.awt.Graphics;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Dimension;
+import java.awt.Color;
+import java.util.Vector;
+import java.awt.Image;
+//import java.awt.Event;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseAdapter;
+import java.net.URL;
+import java.applet.Applet;
+import java.util.Date;
+
+public class ResultCanvas extends Canvas {
+    
+
+    // Other objects associated with this 
+    Phind phind;
+    ResultBox parent;
+    Scrollbar scrollbar;
+    
+    // fonts and font spacings to use
+    Font areaPlain, areaBold;
+    int lineSpacing;
+    
+    // The items to display on this canvas
+    int numberOfItems;
+    int firstItemDisplayed;
+    int itemSelected;
+    Vector items;
+    
+    // the background image
+    public static Image backgroundImage;
+    
+    
+    // Create a ResultCanvas from the ResultBox which is its parent.
+    ResultCanvas(ResultBox p) {
+	
+	parent = p;
+	phind = p.phind;
+	scrollbar = p.s;
+	parent.disableScrollbar();
+
+	areaPlain = phind.plainFont;
+	areaBold  = phind.boldFont;
+
+	lineSpacing = phind.fontSize + 2;
+
+	items = new Vector();
+	numberOfItems = 0;
+	firstItemDisplayed = 0;
+	itemSelected = -1;
+    
+	if (backgroundImage == null) {
+	    backgroundImage = p.phind.backgroundImage;
+	}
+
+	// add a mouse listener for the mouse clicks. we only want to override
+	// one method, so we use the adaptor class
+	addMouseListener(new MouseAdapter() {
+		public void mouseClicked(MouseEvent evt) {
+		    ResultCanvas.this.mouseClicked(evt);
+		}
+	    });
+	
+
+    }
+
+    void resetCanvas( ) {
+	items.removeAllElements();
+	numberOfItems = 0;
+	repaint();
+    }
+
+
+    // Add a new search result.
+    // Return true if successful, otherwise false.
+    boolean addResultItem( ResultItem item ) {
+ 
+	// Add a new result, in sorted order.
+	// First sort key is item kind (lowest first),
+	// second is frequency (highest first).
+	// This is not efficient, but I don't care right now.
+	int index = 0;
+	while ((index < numberOfItems) &&
+	       ((item.sort < ((ResultItem) items.elementAt(index)).sort) ||
+		((item.sort == ((ResultItem) items.elementAt(index)).sort) &&
+		 (item.frequency <= ((ResultItem) items.elementAt(index)).frequency)))) {
+	    index++;
+	}
+	items.insertElementAt(item,index);
+	numberOfItems++;
+	return true;
+    }
+
+
+    // Update more phrases/documents/links markers
+    void updateMarkers() {
+	updateMorePhrasesMarker();
+	updateMoreDocumentsMarker();
+	updateMoreLinksMarker();
+    }
+
+    // Make sure the more Phrases item only appears in the list
+    // if it is meant to.
+    void updateMorePhrasesMarker() {
+    
+	 System.out.println("updateMorePhrasesMarker() ");
+	 System.out.println("expansions retrieved = "+parent.expansionsRetrieved +" num expansions = "+parent.numberOfExpansions);
+	// look for a marker
+	boolean found = false;
+	int index = 0;
+	while (!found && (index < numberOfItems)) {
+	    if (((ResultItem) items.elementAt(index)).isMorePhrases()) {
+		found = true;
+	    } else {
+		index++;
+	    }
+	}
+
+	if (parent.expansionsRetrieved == parent.numberOfExpansions) {
+	    // there should be no marker
+	    if (found) {
+		items.removeElementAt(index);
+		numberOfItems--;
+	    }
+
+	} else if (parent.expansionsRetrieved < parent.numberOfExpansions) {
+	    if (!found) {
+		ResultItem ri = new ResultItem(ResultItem.morePhrases);
+		addResultItem(ri);
+	    }
+	}
+    }
+
+
+    // Make sure the more documents marker appears when required
+    void updateMoreDocumentsMarker() {
+    
+	// System.out.println("updateMoreDocumentsMarker() ");
+
+	// look for a marker
+	boolean found = false;
+	int index = 0;
+	while (!found && (index < numberOfItems)) {
+	    if (((ResultItem) items.elementAt(index)).isMoreDocuments()) {
+		found = true;
+	    } else {
+		index++;
+	    }
+	}
+
+	if (parent.documentsRetrieved == parent.numberOfDocuments) {
+	    // there should be no marker
+	    if (found) {
+		items.removeElementAt(index);
+		numberOfItems--;
+	    }
+
+	} else if (parent.documentsRetrieved < parent.numberOfDocuments) {
+	    // there should be a marker
+	    if (!found) {
+		ResultItem ri = new ResultItem(ResultItem.moreDocuments);
+		addResultItem(ri);
+	    }
+	}
+    }
+
+      
+    // Make sure the more links marker appears when required
+    void updateMoreLinksMarker() {
+    
+	// System.out.println("updateMoreLinksMarker() ");
+
+	// look for a marker
+	boolean found = false;
+	int index = 0;
+	while (!found && (index < numberOfItems)) {
+	    if (((ResultItem) items.elementAt(index)).isMoreLinks()) {
+		found = true;
+	    } else {
+		index++;
+	    }
+	}
+
+	if (parent.thesaurusLinksRetrieved == parent.numberOfThesaurusLinks) {
+	    // there should be no marker
+	    if (found) {
+		items.removeElementAt(index);
+		numberOfItems--;
+	    }
+
+	} else if (parent.thesaurusLinksRetrieved < parent.numberOfThesaurusLinks) {
+	    // there should be a marker
+	    if (!found) {
+		ResultItem ri = new ResultItem(ResultItem.moreLinks);
+		addResultItem(ri);
+	    }
+	}
+    }
+
+      
+
+ 
+
+
+    public void update(Graphics g) {
+	paint(g);
+    }
+
+    public void paint(Graphics g) {
+
+	// calculate the canvas size, margins, and spacing
+	
+	// Note: the size() method is deprecated, but getSize fails in NetScape 4
+	Dimension canvasSize = getSize();
+	
+	g.setFont(areaPlain);
+	int space = g.getFontMetrics().stringWidth(" ");
+	int nought = g.getFontMetrics().stringWidth("0");
+
+	int firstColumnWidth = phind.column_1_width * nought;
+	int secondColumnWidth = phind.column_2_width * nought;
+	int columnWidth = firstColumnWidth + secondColumnWidth;
+
+	int firstColumnLeft = canvasSize.width - columnWidth;
+	int secondColumnLeft = firstColumnLeft + firstColumnWidth;
+
+	int mainLeftMargin = 0;
+	int mainRightMargin = firstColumnLeft;
+
+	// the number of items that will fit on the canvas
+	int visible = canvasSize.height / lineSpacing;
+
+	// calculate the first item to output
+	int scrollValue = scrollbar.getValue();
+	if (numberOfItems <= visible) {
+	    scrollValue = 0;
+	} else if (scrollValue > (numberOfItems - visible)) {
+	    scrollValue = numberOfItems - visible;
+	} 
+	firstItemDisplayed = scrollValue;
+
+	// Draw the phrase area
+	Color fore = phind.panel_fg;
+	Color back = phind.panel_bg;
+
+
+	// draw the background
+	if (phind.showImage) {
+	    try {
+		g.drawImage(backgroundImage, 
+			    mainLeftMargin, 0, mainRightMargin, canvasSize.height, 
+			    back, null);
+	    } catch (Exception e) {
+		phind.showImage = false;
+		System.err.println("ResultCanvas paint error: " + e); 
+		g.setColor(back);
+		g.fillRect(0, 0, canvasSize.width, canvasSize.height);
+	    }
+	} else {
+	    g.setColor(back);
+	    g.fillRect(0, 0, canvasSize.width, canvasSize.height);
+	}
+    
+	// If there are no phrases, output a brief explanation.
+	if (numberOfItems == 0) {
+	    g.drawString("No phrases match this query.", mainLeftMargin + 10, lineSpacing);
+	}
+
+	// Output each of the visible ResultItems
+	ResultItem result;
+	int tab, i, y = 0;
+	int center = mainLeftMargin 
+	    + ((mainRightMargin - mainLeftMargin 
+		- g.getFontMetrics().stringWidth(parent.searchPhrase)) / 2);
+	int thesColumn = mainLeftMargin + firstColumnWidth 
+	    + g.getFontMetrics().stringWidth("Narrower term");
+
+	String body, prefix, suffix;
+	
+	for (i = scrollValue; 
+	     (i < numberOfItems) && (y + lineSpacing < canvasSize.height); i++) {
+
+	    // Get the resultItem to output
+	    result = (ResultItem) items.elementAt(i);
+	    
+	    // Graphics settings for drawing this line
+	    y += lineSpacing;
+	    g.setFont(areaPlain);
+
+	    // Highlight the selected phrase.
+	    if (i == itemSelected) {
+		g.setColor(phind.highlight_bg);
+		g.fillRect(mainLeftMargin, y-lineSpacing+2, mainRightMargin, lineSpacing);
+	    }
+
+	    // Draw the item
+
+	    // Draw a phrase item
+	    if (result.isPhrase()) {
+		prefix = result.prefixText();
+		body = result.mainText();
+		suffix = result.suffixText();
+		
+		g.setColor(phind.expansion_fg);
+		g.setFont(areaPlain);
+		tab = center - g.getFontMetrics().stringWidth(prefix) - space;
+		g.drawString(prefix, tab, y);
+		
+		g.setFont(areaBold);
+		g.drawString(body, center, y);
+		
+		tab = center + space + g.getFontMetrics().stringWidth(body);
+		g.setFont(areaPlain);
+		g.drawString(suffix, tab, y);
+	
+	    } 
+
+	    // Draw a document item
+	    else if (result.isDocument()){
+		body = result.mainText();
+
+		g.setColor(phind.document_fg);
+		g.setFont(areaPlain);
+		tab = (mainRightMargin - g.getFontMetrics().stringWidth(body)) / 2;
+		g.drawString(body, tab, y);
+      
+	    } 
+	
+	    // Draw a thesaurus link item
+	    else if (result.isLink()){
+		prefix = result.prefixText() + ":";
+		body = result.mainText();
+		tab = thesColumn - g.getFontMetrics().stringWidth(prefix) - space;
+
+		g.setColor(phind.thesaurus_fg);
+		g.setFont(areaPlain);
+		g.drawString(prefix, tab, y);
+		g.setFont(areaBold);
+		g.drawString(body, thesColumn, y);
+	    } 
+	    
+	    // Draw a "more phrases/documents/links" marker
+	    else if (result.isMorePhrases() 
+		     || result.isMoreDocuments() 
+		     || result.isMoreLinks()){
+		body = result.mainText();
+		
+		if (result.isMorePhrases()) {
+		    g.setColor(phind.expansion_bar_bg);
+		} else if (result.isMoreDocuments()) {
+		    g.setColor(phind.document_bar_bg);
+		} else {
+		    g.setColor(phind.thesaurus_bar_bg);		    
+		}
+		g.fillRect(mainLeftMargin, y-lineSpacing+2, mainRightMargin, lineSpacing);
+
+		if (result.isMorePhrases()) {
+		    g.setColor(phind.expansion_bar_fg);
+		} else if (result.isMoreDocuments()) {
+		    g.setColor(phind.document_bar_fg);
+		} else {
+		    g.setColor(phind.thesaurus_bar_fg);		    
+		}
+		g.setFont(areaPlain);
+		tab = (mainRightMargin - g.getFontMetrics().stringWidth(body)) / 2;
+		g.drawString(body, tab, y);
+	    } 
+	}
+
+	// Draw the frequecy columns
+
+	// column backgrounds
+	g.setColor(phind.column_1_bg);
+	g.fillRect(firstColumnLeft, 0, firstColumnWidth, canvasSize.height);
+	g.setColor(phind.column_2_bg);
+	g.fillRect(secondColumnLeft, 0, secondColumnWidth, canvasSize.height);
+
+	// fill in the numbers
+	g.setColor(phind.column_1_fg);
+	g.setFont(areaPlain);
+	y = 0;
+	String docsText, freqText;
+
+	for (i = scrollValue; 
+	     (i < numberOfItems) && (y + lineSpacing < canvasSize.height); i++) {
+	    
+	    // Get the resultItem to output
+	    result = (ResultItem) items.elementAt(i);
+	    docsText = result.docsText();
+	    freqText = result.freqText();
+	    
+	    // Graphics settings for drawing this line
+	    y += lineSpacing;
+
+	    // Write the document frequency
+	    if (docsText.length() > 0) {
+		tab = secondColumnLeft - space - g.getFontMetrics().stringWidth(docsText);
+		g.drawString(docsText, tab, y);
+	    }
+
+	    // Write the term frequency
+	    if (freqText.length() > 0) {
+		tab = secondColumnLeft + secondColumnWidth 
+		    - space - g.getFontMetrics().stringWidth(freqText);
+		g.drawString(freqText, tab, y);
+	    }
+	}
+
+	// Adjust the scrollbar
+	if (visible >= numberOfItems) {
+	    parent.disableScrollbar();
+	} else {
+	    scrollbar.setValues(scrollValue, visible, 0, numberOfItems);
+	    // Deprecated - setPageIncrement() has been replaced by
+	    // setBlockIncrement(), but the latter doesn't work on some
+	    // browsers.  Damn.
+	    scrollbar.setBlockIncrement(visible - 1);
+	    //scrollbar.setPageIncrement(visible - 1);
+	    // Deprecated - more nonsense: enable() has been replaced by
+	    // setEnabled(true), but this doesn't work on some browsers.
+	    scrollbar.setEnabled(true);
+	    //scrollbar.enable();
+	}
+
+	
+	// draw the border
+	if (phind.showBorder) {
+	    g.setColor(phind.panel_fg);
+	    g.drawRect(0,0, canvasSize.width - 1, canvasSize.height - 1);
+	}
+    }
+
+    // handle mouse clicks in the new way. just copy gordons thing for now
+    public void mouseClicked(MouseEvent event) {
+
+	// ignore actions that occur within 1 second of the last
+	Date now = new Date();
+	// System.out.println("Click time: " + now.toString());
+	if (now.getTime() < (phind.lastQueryEndTime.getTime() + 1000)) {
+	    System.out.println("Ignoring click - too close to last query.");
+	    return;
+	}
+
+	// which Item is selected?
+	int rowSelected = event.getY() / lineSpacing;
+	itemSelected = rowSelected + firstItemDisplayed;
+	ResultItem item = (ResultItem) items.elementAt(itemSelected);
+
+	if (itemSelected <= numberOfItems) {
+	    
+	    //User clicks on a phrase
+	    if (item.isPhrase()) {
+		itemSelected = itemSelected;
+		update(getGraphics());
+		parent.lookupPhrase(item.hiddenText(), item.toString(), 2);
+		
+		// If meta key is held down, send query to search engine
+		/*if (event.metaDown() && !phind.library_address.equals("")) {
+		    String address = phind.library_address  
+			+ "a=q&sa=text&c=" + phind.collection
+			+ "&q=%22" + item.toString().replace(' ', '+') + "%22";
+		    phind.displayWebPage(address, phind.searchWindowName);
+		    }*/
+	    } 
+	    
+	    // Click on a thesaurus link
+	    else if (item.isLink()) {
+		itemSelected = itemSelected;
+		update(getGraphics());
+		parent.lookupPhrase(item.hiddenText(), item.toString(), 2);
+		
+		// If meta key is held down, send query to search engine
+		/*if (event.metaDown() && !phind.library_address.equals("")) {
+		    String address = phind.library_address  
+			+ "a=q&sa=text&c=" + phind.collection
+			+ "&q=%22" + item.toString().replace(' ', '+') + "%22";
+		    phind.displayWebPage(address, phind.searchWindowName);
+		    }*/
+	    } 
+	    
+	    // The user clicks on a URL; display it.
+	    else if (item.isDocument()) {
+		itemSelected = itemSelected;
+		update(getGraphics());
+		
+		String address = phind.library_address 
+		    + "a=d&c=" + phind.collection 
+		    + "&d=" + item.hiddenText()
+		    + "&q=" + parent.searchPhrase.replace(' ', '+');
+		
+		phind.displayWebPage(address, phind.documentWindowName);
+	    }
+	    
+	    // When the user clicks on "get more phrases" or other marker,
+	    // we have to send a new query to the host
+	    else if (item.isMorePhrases()){
+		parent.lookupPhrase(parent.searchKey, parent.searchPhrase, 3);
+	    } else if (item.isMoreDocuments()){
+		parent.lookupPhrase(parent.searchKey, parent.searchPhrase, 4);
+	    } else if (item.isMoreLinks()){
+		parent.lookupPhrase(parent.searchKey, parent.searchPhrase, 5);
+		
+		
+	    }
+	    repaint();
+	}
+    }
+    
+
+    // User interaction
+    //
+    // All interaction with the ResultCanvas is therough mouse clicks, and
+    // is handles in this method.  Note we ignore clicks that follow
+    // another too closely to avoid problems with slow connections.
+    /*  public boolean processEvent(Event event) {
+    
+	if (event.id == Event.MOUSE_UP) {
+
+	    // ignore actions that occur within 1 second of the last
+	    Date now = new Date();
+	    // System.out.println("Click time: " + now.toString());
+	    if (now.getTime() < (phind.lastQueryEndTime.getTime() + 1000)) {
+		System.out.println("Ignoring click - too close to last query.");
+		return true;
+	    }
+
+	    // which Item is selected?
+	    int rowSelected = event.y / lineSpacing;
+	    itemSelected = rowSelected + firstItemDisplayed;
+	    ResultItem item = (ResultItem) items.elementAt(itemSelected);
+
+	    if (itemSelected <= numberOfItems) {
+	
+		//User clicks on a phrase
+		if (item.isPhrase()) {
+		    itemSelected = itemSelected;
+		    update(getGraphics());
+		    parent.lookupPhrase(item.hiddenText(), item.toString(), 2);
+
+		    // If meta key is held down, send query to search engine
+		    if (event.metaDown() && !phind.library_address.equals("")) {
+			String address = phind.library_address  
+			    + "a=q&sa=text&c=" + phind.collection
+			    + "&q=%22" + item.toString().replace(' ', '+') + "%22";
+			phind.displayWebPage(address, phind.searchWindowName);
+		    }
+		} 
+
+		// Click on a thesaurus link
+		else if (item.isLink()) {
+		    itemSelected = itemSelected;
+		    update(getGraphics());
+		    parent.lookupPhrase(item.hiddenText(), item.toString(), 2);
+
+		    // If meta key is held down, send query to search engine
+		    if (event.metaDown() && !phind.library_address.equals("")) {
+			String address = phind.library_address  
+			    + "a=q&sa=text&c=" + phind.collection
+			    + "&q=%22" + item.toString().replace(' ', '+') + "%22";
+			phind.displayWebPage(address, phind.searchWindowName);
+		    }
+		} 
+
+		// The user clicks on a URL; display it.
+		else if (item.isDocument()) {
+		    itemSelected = itemSelected;
+		    update(getGraphics());
+
+		    String address = phind.library_address 
+			+ "a=r&c=" + phind.collection 
+			+ "&r=" + item.hiddenText()
+			+ "&q=" + parent.searchPhrase.replace(' ', '+');
+
+		    phind.displayWebPage(address, phind.documentWindowName);
+		}
+		 
+		// When the user clicks on "get more phrases" or other marker,
+		// we have to send a new query to the host
+		else if (item.isMorePhrases()){
+		    parent.lookupPhrase(parent.searchKey, parent.searchPhrase, 3);
+		} else if (item.isMoreDocuments()){
+		    parent.lookupPhrase(parent.searchKey, parent.searchPhrase, 4);
+		} else if (item.isMoreLinks()){
+		    parent.lookupPhrase(parent.searchKey, parent.searchPhrase, 5);
+
+
+		}
+		repaint();
+	    }
+	}
+	return true;
+	} */   
+  
+}
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/ResultDisplay.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/ResultDisplay.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/ResultDisplay.java	(revision 13928)
@@ -0,0 +1,126 @@
+/**********************************************************************
+ *
+ * ResultDisplay.java -- Phrase list holder for Phind java applet
+ *
+ * Copyright 1997-2000 Gordon W. Paynter
+ * Copyright 2000 The New Zealand Digital Library Project
+ *
+ * A component of the Greenstone digital library software
+ * from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *********************************************************************/
+
+/*********************************************************************
+
+This class is used in the Phind java applet (Phind.java).
+
+A ResultDisplay is a Panel that can display a single Component, which will
+be a ResultBox or PhindTitle object.
+
+ResultBoxes can be "chained" together with their "prev" and "next" fields,
+allowing us to have an arbitrary number of "displays" in which to show
+phrase lists.
+
+Main methods:
+* emptyContents will remove the component and emptyAll the "next" display
+* display will add an item to the first (ie: most "prev") available box
+
+**********************************************************************/
+package org.greenstone.applet.phind;
+//package org.nzdl.gsdl.Phind;
+
+import java.awt.Panel;
+import java.awt.BorderLayout;
+import java.awt.Component;
+
+class ResultDisplay extends Panel {
+
+  Phind phind;
+  ResultDisplay prev, next;
+  Component current;
+  boolean empty;
+
+  // Create a new Display
+  ResultDisplay(Phind ph, ResultDisplay pr) {
+    phind = ph;
+    prev = pr;
+    next = null;
+    if (prev != null) prev.next = this;
+    setLayout(new BorderLayout());
+
+    empty = true;
+    current = new PhindTitle(ph);
+    add(current);
+  }
+
+  // Empty the contents of the display,
+  // and all the next displays
+  void emptyContents() {
+    if (empty == false) {
+      empty = true;
+      current = new PhindTitle(phind);
+      removeAll();
+      add(current);
+    }
+    if (next != null) next.emptyContents();
+  }
+
+  // Set the contents of this display
+  Component setContents( Component r ) {
+    removeAll();
+    add("Center", r);
+    current = r;
+    empty = false;
+    if (r.getClass().getName().equals("ResultBox")) {
+      ((ResultBox) r).display = this;
+    }
+    return r;
+  }
+
+
+  
+  // Display a component in the "most previous" display
+  ResultDisplay display( Component r ) {
+
+    if (prev == null) {
+      // if there is no previous box, add the component here
+      setContents(r);
+      return this;
+
+    } else if (prev.empty == true) {
+      // if the previous box is empty, add the component to it instead
+      return prev.display(r);
+
+    } else if (empty == true) {
+      // if this box is empty, add the compnent to it
+      setContents(r);
+      return this;
+
+    } else {
+      // if this box is occupied,
+      // shift it's contents prev-wards and add here.
+      prev.display(current);
+      setContents(r);
+      return this;
+    }
+  }
+
+}
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/ResultItem.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/ResultItem.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/ResultItem.java	(revision 13928)
@@ -0,0 +1,128 @@
+/**********************************************************************
+ *
+ * ResultItemDocument.java -- a result in the Phind applet
+ *
+ * Copyright 2000 Gordon W. Paynter
+ * Copyright 2000 The New Zealand Digital Library Project
+ *
+ * A component of the Greenstone digital library software
+ * from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *********************************************************************/
+
+/*********************************************************************
+
+This class is used in the Phind java applet (Phind.java).
+
+A result item holds the data describing a single line returned from a phind
+query.  The complex functionality of phrase and URL items is implemented in
+subclasses; the base class handles simpler cases like the "get more phrases" 
+marker.
+
+**********************************************************************/
+package org.greenstone.applet.phind;
+//package org.nzdl.gsdl.Phind;
+
+public class ResultItem {
+
+    // A text string describing the item
+    String text = "Generic ResultItem";
+
+    // There are several kinds of ResultItem, identified by their
+    // "kind" field, which has an integer value from the list below.
+    final static int message = 8;
+    final static int linkItem = 7;
+    final static int moreLinks = 6;
+    final static int phraseItem = 5;
+    final static int morePhrases = 4;
+    final static int documentItem = 3;
+    final static int moreDocuments = 2;
+    final static int unknownResultItem = 1;
+
+    // The kind of the item
+    int kind = unknownResultItem;
+
+    // When results are displayed, they are loosely sorted by their
+    // kind.  The user can change the sort order numbers with the 
+    // ResultOrder parameter in Phind.java.
+    static int sortMessage = 8;
+    static int sortLinkItem = 7;
+    static int sortMoreLinks = 6;
+    static int sortPhraseItem = 5;
+    static int sortMorePhrases = 4;
+    static int sortDocumentItem = 3;
+    static int sortMoreDocuments = 2;
+    static int sortUnknownResultItem = 1;
+
+    // the primary sort key
+    int sort = 0;
+    
+    // The frequency of the item (secondary sort key)
+    int frequency = 0;
+
+
+    // Create a blank ResultItem
+    ResultItem() {
+	text = "Unknown result type";
+	kind = unknownResultItem;
+	frequency = 0;
+    }
+
+    // Create a new ResultItem of some given kind
+    ResultItem(int newKind) {
+	kind = newKind;
+	frequency = 0;
+
+	if (kind == moreLinks) {
+	    text = "get more thesaurus links";
+	    sort = sortMoreLinks;
+	} else if (kind == morePhrases) {
+	    text = "get more phrases";
+	    sort = sortMorePhrases;
+	} else if (kind == moreDocuments) {
+	    text = "get more documents";
+	    sort = sortMoreDocuments;
+	} else {
+	    text = "Unknown result type";
+	    sort = sortUnknownResultItem;
+	}
+    }
+
+    // Test the type of a ResultItem
+    public boolean isLink() { return false; }
+    public boolean isMoreLinks() { return (kind == moreLinks); }
+    public boolean isPhrase() { return false; }
+    public boolean isMorePhrases() { return (kind == morePhrases); }
+    public boolean isDocument() { return false; }
+    public boolean isMoreDocuments() { return (kind == moreDocuments); }
+
+    // Return the bare text of the item
+    public String toString() { return(text.trim()); }
+
+    // Return the text of the item components
+    public String mainText() { return text; }
+    public String freqText() { 
+	if (frequency > 0) { return Integer.toString(frequency); } 
+	else { return ""; }
+    }
+    public String docsText() { return ""; }
+    public String prefixText() { return ""; }
+    public String suffixText() { return ""; }
+    public String hiddenText() { return ""; }
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/ResultItemDocument.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/ResultItemDocument.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/ResultItemDocument.java	(revision 13928)
@@ -0,0 +1,70 @@
+/**********************************************************************
+ *
+ * ResultItemDocument.java -- a document result in the Phind applet
+ *
+ * Copyright 1997-2000 Gordon W. Paynter
+ * Copyright 2000 The New Zealand Digital Library Project
+ *
+ * A component of the Greenstone digital library software
+ * from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *********************************************************************/
+
+/*********************************************************************
+
+This class is used in the Phind java applet (Phind.java).
+
+It contains information describing a document in which a search term 
+occurs.
+
+**********************************************************************/
+package org.greenstone.applet.phind;
+//package org.nzdl.gsdl.Phind;
+
+public class ResultItemDocument extends ResultItem {
+
+    // The document's title is stored in the superclasses 
+    // text variable, and the number of times the phrase occurs
+    // in the frequency variable. 
+
+    // The document's unique object identifier (hash value).
+    String hash;
+
+    // Create a ResultItem for a document
+    ResultItemDocument(String newHash, String newTitle, String newFrequency) {
+	
+	kind = documentItem;
+	text = newTitle;
+
+	sort = sortDocumentItem;
+	frequency = Integer.valueOf(newFrequency).intValue();
+	hash = newHash;
+    }
+
+    // Is this item a document?
+    public boolean isDocument() { return true; }
+
+    // Return the bare text of the item
+    public String toString() { return(text); }
+
+    // Return the text of the item components
+    public String hiddenText() { return hash; }
+ 
+
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/ResultItemLink.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/ResultItemLink.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/ResultItemLink.java	(revision 13928)
@@ -0,0 +1,88 @@
+/**********************************************************************
+ *
+ * ResultItemLink.java -- a thesaurus link in the Phind applet
+ *
+ * Copyright 2000 Gordon W. Paynter
+ * Copyright 2000 The New Zealand Digital Library Project
+ *
+ * A component of the Greenstone digital library software
+ * from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *********************************************************************/
+
+/*********************************************************************
+
+This class is used in the Phind java applet (Phind.java).
+
+It contains information describing a thesaurus link.
+
+**********************************************************************/
+package org.greenstone.applet.phind;
+//package org.nzdl.gsdl.Phind;
+
+public class ResultItemLink extends ResultItem {
+
+    // The phrase number, stored as a string and as a number
+    String id;
+    int symbol;
+
+    // The text of the link is stored in the inherited text field.
+
+    // The type of thesaurus link
+    String linkType;
+
+    // The total frequency is stored in the inherited frequency field.
+
+    // The document frequency of the thesaurus item
+    int documentFrequency;
+
+    // Create a ResultItem for a thesaurus link
+    ResultItemLink(String newId, String newText, String newLinkType, 
+		   String tf, String df) { 
+
+	kind = linkItem;
+	id = newId;
+	symbol = Integer.valueOf(newId).intValue();
+	text = newText.trim();
+	sort = sortLinkItem;
+	linkType = newLinkType;
+	frequency = Integer.valueOf(tf).intValue();
+	documentFrequency = Integer.valueOf(df).intValue();
+    }
+
+    // Is this item a phrase?
+    public boolean isLink() { return true; }
+
+    // Return the text of the item components
+    public String hiddenText() { return id; }
+    public String docsText() { 
+	if (documentFrequency <= 0) { return ""; }
+	else { return Integer.toString(documentFrequency); }
+    }
+    public String prefixText() { 
+	if (linkType.equals("RT")) { return "Related term"; }
+	else if (linkType.equals("BT")) { return "Broader term"; }
+	else if (linkType.equals("NT")) { return "Narrower term"; }
+	else if (linkType.equals("USE")) { return "Use"; }
+	else if (linkType.startsWith("UF")) { return "Used for"; }
+	else { return linkType; }
+    }
+}
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/ResultItemPhrase.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/ResultItemPhrase.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/ResultItemPhrase.java	(revision 13928)
@@ -0,0 +1,85 @@
+/**********************************************************************
+ *
+ * ResultItemPhrase.java -- a phrase result in the Phind applet
+ *
+ * Copyright 2000 Gordon W. Paynter
+ * Copyright 2000 The New Zealand Digital Library Project
+ *
+ * A component of the Greenstone digital library software
+ * from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *********************************************************************/
+
+/*********************************************************************
+
+This class is used in the Phind java applet (Phind.java).
+
+It contains information describing a phrase.
+
+**********************************************************************/
+
+//package org.nzdl.gsdl.Phind;
+package org.greenstone.applet.phind;
+public class ResultItemPhrase extends ResultItem {
+
+    // The phrase number, stored as a string and as a number
+    String id;
+    int symbol;
+
+    // The text of the phrase is split into a prefix, body, and suffix.
+    // The body is the same as the parent phrase (or search term) and 
+    // the prefix and suffix are the surrounding text.
+    String prefix;
+    String body;
+    String suffix;
+
+    // The document frequency of the phrase
+    int documentFrequency;
+
+    // Create a ResultItem for a phrase
+    ResultItemPhrase(String newId, String tf, String df, 
+		     String p, String b, String s) {
+
+	kind = phraseItem;
+
+	id = newId;
+	symbol = Integer.valueOf(newId).intValue();
+
+	sort = sortPhraseItem;
+	frequency = Integer.valueOf(tf).intValue();
+	documentFrequency = Integer.valueOf(df).intValue();
+
+	prefix = p;
+	body = b;
+	suffix = s;
+	text = (prefix + " " + body + " " + suffix);
+
+    }
+
+    // Is this item a phrase?
+    public boolean isPhrase() { return true; }
+
+    // Return the text of the item components
+    public String mainText() { return body; }
+    public String docsText() { return Integer.toString(documentFrequency); }
+    public String prefixText() { return prefix; }
+    public String suffixText() { return suffix; }
+    public String hiddenText() { return id; }
+
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/ResultTitle.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/ResultTitle.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/ResultTitle.java	(revision 13928)
@@ -0,0 +1,162 @@
+/**********************************************************************
+ *
+ * ResultTitle.java -- describe the contents of a ResultBox
+ *
+ * Copyright 1997-2000 Gordon W. Paynter
+ * Copyright 2000 The New Zealand Digital Library Project
+ *
+ * A component of the Greenstone digital library software
+ * from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *********************************************************************/
+
+/*********************************************************************
+
+This class is used in the Phind java applet (Phind.java).
+
+ResultTitle is part of the result list displayed to the user.  It lists the
+phrase in the Result box, the number of expansions it occurs in, and the
+number of documents it occurs in.
+
+**********************************************************************/
+
+//package org.nzdl.gsdl.Phind;
+package org.greenstone.applet.phind;
+import java.awt.Canvas;
+import java.awt.Graphics;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Dimension;
+import java.awt.Color;
+
+
+public class ResultTitle extends Canvas {
+    
+    // Other objects associated with this 
+    Phind phind;
+    ResultBox parent;
+    ResultCanvas canvas;
+
+    // fonts and font spacings to use
+    Font plain, bold;
+    Graphics g;
+    
+    // Create a ResultTitle from the ResultBox which is its parent.
+    ResultTitle(ResultBox p) {
+	
+	parent = p;
+	phind = p.phind;
+	canvas = p.c;
+	g = getGraphics();
+	
+	plain = phind.plainFont;
+	bold  = phind.boldFont;
+	
+	// Note: the size() and resize() methods are deprecated, but the newer
+	// getSize() and setSize() methods fail in NetScape 4
+	Dimension d = getSize();
+	d.height = phind.fontSize + 10;
+	setSize(d);
+	
+	
+    }
+    
+    public void update(Graphics g) {
+	paint(g);
+    }
+    
+    public void paint(Graphics g) {
+	
+	// calculate the canvas size, margins, and spacing
+	Dimension canvasSize = getSize();
+	
+	g.setFont(plain);
+	int margin = g.getFontMetrics().stringWidth(" 8888 ");
+	int y = phind.fontSize + 5;
+	
+	int rightMargin = canvas.getSize().width;
+	int secondColumn = rightMargin - margin;
+	int firstColumn = secondColumn - margin;
+	
+	g.setColor(Color.white);
+	g.fillRect(0, 0, canvasSize.width, canvasSize.height);
+	g.setColor(Color.black);
+    
+    
+	// What is the phrase we are searching for?
+	String phrase = parent.searchPhrase.replace('+', ' ');
+	
+	// Construct the description phrase
+	String links = "";
+	if (parent.numberOfThesaurusLinks <= 0) {
+	    links = "";
+	} else if (parent.numberOfThesaurusLinks == 1) { 
+	    links = "1 link";
+	} else if (parent.thesaurusLinksRetrieved == parent.numberOfThesaurusLinks) {
+	    links = parent.numberOfThesaurusLinks + " links";
+	} else {
+	    links = parent.thesaurusLinksRetrieved + " of " 
+		+ parent.numberOfThesaurusLinks + " links";
+	}
+	
+	String expansions = "";
+	if (parent.numberOfExpansions <= 0) {
+	    expansions = "no phrases";
+	} else if (parent.numberOfExpansions == 1) { 
+	    expansions = "1 phrase";
+	} else if (parent.expansionsRetrieved == parent.numberOfExpansions) {
+	    expansions = parent.numberOfExpansions + " phrases";
+	} else {
+	    expansions = parent.expansionsRetrieved + " of " 
+		+ parent.numberOfExpansions + " phrases";
+	}
+	
+	String documents = "";
+	if (parent.numberOfDocuments <= 0) { 
+	    documents = "no documents";
+	} else if (parent.documentsRetrieved == 1) {
+	    documents = "1 document";
+	} else if (parent.documentsRetrieved == parent.numberOfDocuments) {
+	    documents = parent.numberOfDocuments + " documents";
+	} else {
+	    documents = parent.documentsRetrieved + " of " 
+		+ parent.numberOfDocuments + " documents";
+	}
+	
+	String status = "(";
+	if (parent.numberOfThesaurusLinks > 0) {
+	    status = status + links + ", ";
+	} 
+	status = status + expansions + ", " + documents + ")";
+	
+	
+	// Draw the text 
+	g.setFont(bold);
+	g.drawString(phrase, 0, y);
+	int tab = g.getFontMetrics().stringWidth(phrase + "  ");
+	
+	g.setFont(plain);
+	g.drawString(status, tab, y);
+	tab = tab + g.getFontMetrics().stringWidth(status);
+	
+	if (tab < firstColumn) {
+	    g.drawString("docs", firstColumn, y);
+	    g.drawString("freq", secondColumn, y);
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/URLUTF8Encoder.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/URLUTF8Encoder.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/applet/phind/URLUTF8Encoder.java	(revision 13928)
@@ -0,0 +1,159 @@
+/**********************************************************************
+ *
+ *
+ * URLUTF8Encoder.java -- encode UTF8 String into a URL form
+ *
+ * W3C SOFTWARE NOTICE AND LICENSE
+ *
+ * Copyright (C) 1994-2000 World Wide Web Consortium, 
+ * (Massachusetts Institute of Technology, Institut National de 
+ * Recherche en Informatique et en Automatique, Keio University). 
+ * All Rights Reserved.  http://www.w3.org/Consortium/Legal/
+ * 
+ * This W3C work (including software, documents, or other related items) is
+ * being provided by the copyright holders under the following license. By
+ * obtaining, using and/or copying this work, you (the licensee) agree that
+ * you have read, understood, and will comply with the following terms and
+ * conditions:
+ * 
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation, with or without modification, for any purpose and without
+ * fee or royalty is hereby granted, provided that you include the following
+ * on ALL copies of the software and documentation or portions thereof,
+ * including modifications, that you make:
+ * 
+ *   1. The full text of this NOTICE in a location viewable to users of the
+ *      redistributed or derivative work.
+ * 
+ *   2. Any pre-existing intellectual property disclaimers, notices, or terms
+ *      and conditions. If none exist, a short notice of the following form
+ *      (hypertext is preferred, text is permitted) should be used within the
+ *      body of any redistributed or derivative code: "Copyright (C)
+ *      [$date-of-software] World Wide Web Consortium, (Massachusetts
+ *      Institute of Technology, Institut National de Recherche en
+ *      Informatique et en Automatique, Keio University). All Rights
+ *      Reserved. http://www.w3.org/Consortium/Legal/"
+ * 
+ *   3. Notice of any changes or modifications to the W3C files, including the
+ *      date changes were made. (We recommend you provide URIs to the location
+ *      from which the code is derived.)
+ * 
+ * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS
+ * MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT
+ * NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR
+ * PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE
+ * ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
+ * 
+ * COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR
+ * CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR
+ * DOCUMENTATION.
+ * 
+ * The name and trademarks of copyright holders may NOT be used in advertising
+ * or publicity pertaining to the software without specific, written prior
+ * permission. Title to copyright in this software and any associated
+ * documentation will at all times remain with copyright holders.
+ *
+ *********************************************************************/
+
+/**
+ * Provides a method to encode any string into a URL-safe
+ * form, the so-called "x-www-form-urlencoded" form.
+ * Non-ASCII characters are first encoded as sequences of
+ * two or three bytes, using the UTF-8 algorithm, before being
+ * encoded in "x-www-form-urlencoded".
+ */
+
+//package org.nzdl.gsdl.Phind;
+package org.greenstone.applet.phind;
+public class URLUTF8Encoder
+{
+
+  final static String[] hex = {
+    "%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07",
+    "%08", "%09", "%0a", "%0b", "%0c", "%0d", "%0e", "%0f",
+    "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17",
+    "%18", "%19", "%1a", "%1b", "%1c", "%1d", "%1e", "%1f",
+    "%20", "%21", "%22", "%23", "%24", "%25", "%26", "%27",
+    "%28", "%29", "%2a", "%2b", "%2c", "%2d", "%2e", "%2f",
+    "%30", "%31", "%32", "%33", "%34", "%35", "%36", "%37",
+    "%38", "%39", "%3a", "%3b", "%3c", "%3d", "%3e", "%3f",
+    "%40", "%41", "%42", "%43", "%44", "%45", "%46", "%47",
+    "%48", "%49", "%4a", "%4b", "%4c", "%4d", "%4e", "%4f",
+    "%50", "%51", "%52", "%53", "%54", "%55", "%56", "%57",
+    "%58", "%59", "%5a", "%5b", "%5c", "%5d", "%5e", "%5f",
+    "%60", "%61", "%62", "%63", "%64", "%65", "%66", "%67",
+    "%68", "%69", "%6a", "%6b", "%6c", "%6d", "%6e", "%6f",
+    "%70", "%71", "%72", "%73", "%74", "%75", "%76", "%77",
+    "%78", "%79", "%7a", "%7b", "%7c", "%7d", "%7e", "%7f",
+    "%80", "%81", "%82", "%83", "%84", "%85", "%86", "%87",
+    "%88", "%89", "%8a", "%8b", "%8c", "%8d", "%8e", "%8f",
+    "%90", "%91", "%92", "%93", "%94", "%95", "%96", "%97",
+    "%98", "%99", "%9a", "%9b", "%9c", "%9d", "%9e", "%9f",
+    "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%a7",
+    "%a8", "%a9", "%aa", "%ab", "%ac", "%ad", "%ae", "%af",
+    "%b0", "%b1", "%b2", "%b3", "%b4", "%b5", "%b6", "%b7",
+    "%b8", "%b9", "%ba", "%bb", "%bc", "%bd", "%be", "%bf",
+    "%c0", "%c1", "%c2", "%c3", "%c4", "%c5", "%c6", "%c7",
+    "%c8", "%c9", "%ca", "%cb", "%cc", "%cd", "%ce", "%cf",
+    "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7",
+    "%d8", "%d9", "%da", "%db", "%dc", "%dd", "%de", "%df",
+    "%e0", "%e1", "%e2", "%e3", "%e4", "%e5", "%e6", "%e7",
+    "%e8", "%e9", "%ea", "%eb", "%ec", "%ed", "%ee", "%ef",
+    "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
+    "%f8", "%f9", "%fa", "%fb", "%fc", "%fd", "%fe", "%ff"
+  };
+
+  /**
+   * Encode a string to the "x-www-form-urlencoded" form, enhanced
+   * with the UTF-8-in-URL proposal. This is what happens:
+   *
+   * <ul>
+   * <li><p>The ASCII characters 'a' through 'z', 'A' through 'Z',
+   *        and '0' through '9' remain the same.
+   *
+   * <li><p>The space character ' ' is converted into a plus sign '+'.
+   *
+   * <li><p>All other ASCII characters are converted into the
+   *        3-character string "%xy", where xy is
+   *        the two-digit hexadecimal representation of the character
+   *        code
+   *
+   * <li><p>All non-ASCII characters are encoded in two steps: first
+   *        to a sequence of 2 or 3 bytes, using the UTF-8 algorithm;
+   *        secondly each of these bytes is encoded as "%xx".
+   * </ul>
+   *
+   * @param s The string to be encoded
+   * @return The encoded string
+   */
+  public static String encode(String s)
+  {
+    StringBuffer sbuf = new StringBuffer();
+    int len = s.length();
+    for (int i = 0; i < len; i++) {
+      int ch = s.charAt(i);
+      if ('A' <= ch && ch <= 'Z') {		// 'A'..'Z'
+	sbuf.append((char)ch);
+      } else if ('a' <= ch && ch <= 'z') {	// 'a'..'z'
+	sbuf.append((char)ch);
+      } else if ('0' <= ch && ch <= '9') {	// '0'..'9'
+	sbuf.append((char)ch);
+      } else if (ch == ' ') {			// space
+	sbuf.append('+');
+      } else if (ch <= 0x007f) {		// other ASCII
+	sbuf.append(hex[ch]);
+      } else if (ch <= 0x07FF) {		// non-ASCII <= 0x7FF
+	sbuf.append(hex[0xc0 | (ch >> 6)]);
+	sbuf.append(hex[0x80 | (ch & 0x3F)]);
+      } else {					// 0x7FF < ch <= 0xFFFF
+	sbuf.append(hex[0xe0 | (ch >> 12)]);
+	sbuf.append(hex[0x80 | ((ch >> 6) & 0x3F)]);
+	sbuf.append(hex[0x80 | (ch & 0x3F)]);
+      }
+    }
+    return sbuf.toString();
+  }
+
+}
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/Library1.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/Library1.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/Library1.java	(revision 13928)
@@ -0,0 +1,69 @@
+/*
+ *    Library1.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3;
+
+import org.greenstone.gsdl3.core.*;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+/** sample command line interface to gsdl3 site
+ *
+ * enter XML queries at the prompt
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ * @version $Revision$
+ */
+final public class Library1 {
+
+    public static void main(String args[]) {
+
+	if (args.length != 1) {
+	    System.out.println("Usage: Library1 <sitename>");
+	    System.exit(1);
+	}
+	String site_name = args[0];
+
+	MessageRouter mr = new MessageRouter();
+	mr.setSiteName(site_name);
+	mr.configure();
+	
+	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
+	String query=null;
+	String result=null;
+	while (true) {
+	    System.out.println("Please enter an XML query all on one line, or 'exit' to quit");
+	    try {
+		query = br.readLine();
+	    } catch (Exception e) {
+		System.err.println("Library1 exception:"+e.getMessage());
+	    }
+	    if (query.startsWith("exit")) {
+		System.exit(1);
+	    }
+	    System.out.println("\nProcessing query");
+	    
+	    result = mr.process(query);
+
+	    System.out.println("Result:\n"+result+"\n");
+
+
+	}
+       
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/Library2.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/Library2.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/Library2.java	(revision 13928)
@@ -0,0 +1,183 @@
+/*
+ *    Library2.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3;
+
+import org.greenstone.gsdl3.core.*;
+import org.greenstone.gsdl3.util.*;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.Iterator;
+/**
+ * A program to take cgi args from the command line and return html
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ * @version $Revision$
+ */
+
+final public class Library2 {
+ 
+    protected XMLConverter converter = null;
+    protected Document doc = null;
+    
+    protected HashMap saved_args = null;
+    protected GSParams params = null;
+    protected DefaultReceptionist recept = null;
+    
+    public Library2 (){
+	this.converter = new XMLConverter();
+	this.doc = converter.newDOM();
+	this.saved_args = new HashMap();
+	this.params = new GSParams();
+	this.recept = new DefaultReceptionist();
+    }
+    
+    public void configure(String site_name, String interface_name) {
+
+	HashMap config_params = new HashMap();
+	//config_params.put(GSConstants.GSDL3_HOME, gsdl_home);
+	config_params.put(GSConstants.SITE_NAME, site_name);
+	config_params.put(GSConstants.INTERFACE_NAME, interface_name);
+	// new message router - create it and pass a handle to recept.
+	// the servlet wont use this directly
+	MessageRouter message_router = new MessageRouter();
+	
+	message_router.setSiteName(site_name);
+	message_router.configure();
+	// new receptionist
+	recept.setConfigParams(config_params);
+	recept.setMessageRouter(message_router);
+	recept.setParams(params);
+	recept.configure();
+    }
+    public static void main(String args[]) {
+
+	if (args.length != 2) {
+	    System.out.println("Usage: Library2 <site name> <interface name>");
+	    System.exit(1);
+	}
+	
+	Library2 library = new Library2();
+	library.configure(args[0], args[1]);
+	
+
+	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
+	String query=null;
+	String result=null;
+	while (true) {
+	    System.out.println("Please enter the  cgi args (all on one line), or 'exit' to quit (default a=p&sa=home)");
+	    try {
+		query = br.readLine();
+	    } catch (Exception e) {
+		System.err.println("Library2 exception:"+e.getMessage());
+	    }
+	    if (query.startsWith("exit")) {
+		System.exit(1);
+	    }
+
+	    result = library.process(query);
+	    
+	    System.out.println(result);
+
+
+	}
+
+    } 
+
+    protected String process(String query) {
+	Element xml_message  = generateRequest(query);
+	System.out.println("*********************");
+	System.out.println(converter.getPrettyString(xml_message));
+	Element xml_result = recept.process(xml_message);
+	return this.converter.getPrettyString(xml_result);
+    }
+    protected Element generateRequest(String cgiargs) {
+
+	Element xml_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element xml_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PAGE, "", "", "");
+	xml_message.appendChild(xml_request);
+	Element xml_param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	xml_request.appendChild(xml_param_list);
+
+	// the defaults
+	String action = "p";
+	String subaction = "home";
+	String lang = (String)saved_args.get(GSParams.LANGUAGE);
+	if (lang == null) {
+	    lang = "en";
+	}
+	String output = "html";
+	
+	String args [] = cgiargs.split("&");
+	for (int i=0; i<args.length; i++) {
+	    String arg = args[i];
+	    int pos = arg.indexOf('=');
+	    if (pos == -1) continue;
+	    String name = arg.substring(0, pos);
+	    String value = arg.substring(pos+1);
+	    if (name.equals(GSParams.ACTION)) {
+		action = value;
+	    } else if (name.equals(GSParams.SUBACTION)) {
+		subaction = (value);
+	    } else if (name.equals(GSParams.LANGUAGE)) {
+		lang = value;
+		saved_args.put(name, value);
+	    } else if (name.equals(GSParams.OUTPUT)) {
+		output = value;
+	    } else if (params.shouldSave(name)) {
+		saved_args.put(name, value);
+	    } else {
+		// make a param now
+		Element param = doc.createElement(GSXML.PARAM_ELEM);
+		param.setAttribute(GSXML.NAME_ATT, name);
+		param.setAttribute(GSXML.VALUE_ATT, GSXML.xmlSafe(value));
+		xml_param_list.appendChild(param);
+	    }
+	}
+
+	xml_request.setAttribute(GSXML.OUTPUT_ATT, output);
+	xml_request.setAttribute(GSXML.ACTION_ATT, action);
+	xml_request.setAttribute(GSXML.SUBACTION_ATT, subaction);
+	xml_request.setAttribute(GSXML.LANG_ATT, lang);
+
+
+	// put in all the params from the session cache
+	Set params = saved_args.keySet();
+	Iterator i = params.iterator();
+	while (i.hasNext()) {
+	    String name = (String)i.next();
+	    if (name.equals(GSParams.LANGUAGE)) continue;
+	    Element param = this.doc.createElement(GSXML.PARAM_ELEM);
+	    param.setAttribute(GSXML.NAME_ATT, name);
+	    param.setAttribute(GSXML.VALUE_ATT, GSXML.xmlSafe((String)saved_args.get(name)));
+	    xml_param_list.appendChild(param);
+	}
+
+	return xml_message;
+    }
+}
+
+    
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/LibraryServlet.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/LibraryServlet.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/LibraryServlet.java	(revision 13928)
@@ -0,0 +1,375 @@
+package org.greenstone.gsdl3;
+
+import org.greenstone.gsdl3.comms.*;
+import org.greenstone.gsdl3.core.*;
+import org.greenstone.gsdl3.util.*;
+import org.greenstone.gsdl3.action.PageAction; // used to get the default action
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import java.io.*;
+import javax.servlet.*;
+import javax.servlet.http.*;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.io.File;
+
+import org.apache.log4j.*;
+
+/** a servlet to serve the greenstone library - we are using servlets instead
+ * of cgi
+ * the init method is called only once - the first time the servlet classes
+ * are loaded. Each time a request comes in to the servlet, the session()
+ * method is called in a new thread (calls doGet/doPut etc)
+ * takes the a=p&p=home type args and builds a simple request to send to 
+ * its receptionist, which returns a result in html, cos output=html
+ * is set in the request
+ * @see Receptionist
+ */
+public class LibraryServlet extends HttpServlet {
+    
+    /** the receptionist to send messages to */
+    protected Receptionist recept=null;
+    /** the default language - is specified by setting a servlet param,
+     * otherwise DEFAULT_LANG is used*/
+    protected String default_lang= null;
+    /** The default default - used if a default lang is not specified 
+     * in the servlet params */
+    protected final String DEFAULT_LANG = "en";
+    /** container Document to create XML Nodes */
+    protected Document doc=null;    
+    /** a converter class to parse XML and create Docs */
+    protected XMLConverter converter=null;
+    /** the cgi stuff - the Receptionist can add new args to this
+     * its used by the servlet to determine what args to save */
+    protected GSParams params = null;
+
+    /** user id - new one per session. This doesn't work if session state is saved between restarts - this requires this value to be saved too. */
+    protected int next_user_id = 0;
+
+    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.LibraryServlet.class.getName());
+
+    /** initialise the servlet
+     */
+    public void init(ServletConfig config) throws ServletException {
+	// always call super.init;
+	super.init(config);
+	// disable preferences - does this work anyway??
+	//System.setProperty("java.util.prefs.PreferencesFactory", "org.greenstone.gsdl3.util.DisabledPreferencesFactory");
+
+    
+	String library_name = config.getInitParameter(GSConstants.LIBRARY_NAME);
+	String gsdl3_home = config.getInitParameter(GSConstants.GSDL3_HOME);
+	String interface_name = config.getInitParameter(GSConstants.INTERFACE_NAME);
+	this.default_lang = config.getInitParameter(GSConstants.DEFAULT_LANG);
+
+	if (library_name == null || interface_name ==null) {
+	    // must have this
+	    System.err.println("initialisation parameters not all set!");
+	    System.err.println(" you must have libraryname and interfacename");
+	    System.exit(1);
+	}
+
+	String site_name = config.getInitParameter(GSConstants.SITE_NAME);
+	String remote_site_name = null;
+	String remote_site_type = null;
+	String remote_site_address = null;
+	
+	if (site_name == null) {
+	    // no site, try for communicator
+	    remote_site_name = config.getInitParameter("remote_site_name");
+	    remote_site_type = config.getInitParameter("remote_site_type");
+	    remote_site_address = config.getInitParameter("remote_site_address");
+	    if (remote_site_name == null || remote_site_type == null || remote_site_address == null) {
+		System.err.println("initialisation paramters not all set!");
+		System.err.println("if site_name is not set, then you must have remote_site_name, remote_site_type and remote_site_address set");
+		System.exit(1); 
+	    }
+	}
+	
+	if (this.default_lang == null) {
+	    // choose english
+	    this.default_lang = DEFAULT_LANG;
+	}
+	
+	HashMap config_params = new HashMap();
+	
+	config_params.put(GSConstants.LIBRARY_NAME, library_name);
+	config_params.put(GSConstants.INTERFACE_NAME, interface_name);
+	if (site_name != null) {
+	    config_params.put(GSConstants.SITE_NAME, site_name);
+	}
+	this.converter = new XMLConverter();
+	this.doc = this.converter.newDOM();
+	
+	// the receptionist -the servlet will talk to this
+	String recept_name = (String)config.getInitParameter("receptionist_class");
+	if (recept_name == null) {
+	    this.recept = new DefaultReceptionist();
+	} else {
+	    try {
+		this.recept = (Receptionist)Class.forName("org.greenstone.gsdl3.core."+recept_name).newInstance();
+	    } catch (Exception e) { // cant use this new one, so use normal one
+		System.err.println("LibraryServlet configure exception when trying to use a new Receptionist "+recept_name+": "+e.getMessage());
+		e.printStackTrace();
+		this.recept = new DefaultReceptionist();
+	    }
+	}
+	this.recept.setConfigParams(config_params);
+
+	// the receptionist uses a MessageRouter or Communicator to send its requests to. We either create a MessageRouter here for the designated site (if site_name set), or we create a Communicator for a remote site. The is given to teh Receptionist, and the servlet never talks to it again.directly.
+	if (site_name != null) {
+	    String mr_name = (String)config.getInitParameter("messagerouter_class");
+	    MessageRouter message_router = null;
+	    if (mr_name == null) { // just use the normal MR
+		message_router = new MessageRouter();
+	    } else { // try the specified one
+		try {
+		    message_router = (MessageRouter)Class.forName("org.greenstone.gsdl3.core."+mr_name).newInstance();
+		} catch (Exception e) { // cant use this new one, so use normal one
+		    System.err.println("LibraryServlet configure exception when trying to use a new MessageRouter "+mr_name+": "+e.getMessage());
+		    e.printStackTrace();
+		    message_router = new MessageRouter();
+		}   
+	    }
+	    
+	    message_router.setSiteName(site_name);
+	    message_router.configure();
+	    this.recept.setMessageRouter(message_router);
+	} else {
+	    // talking to a remote site, create a communicator
+	    Communicator communicator = null;
+	    // we need to create the XML to configure the communicator
+	    Element site_elem = this.doc.createElement(GSXML.SITE_ELEM);
+	    site_elem.setAttribute(GSXML.TYPE_ATT, remote_site_type);
+	    site_elem.setAttribute(GSXML.NAME_ATT, remote_site_name);
+	    site_elem.setAttribute(GSXML.ADDRESS_ATT, remote_site_address);
+
+	    if (remote_site_type.equals(GSXML.COMM_TYPE_SOAP_JAVA)) {
+		communicator = new SOAPCommunicator();
+	    } else {
+		System.err.println("LibraryServlet.init Error: invalid Communicator type: "+remote_site_type);
+		System.exit(1);
+	    }
+	    
+	    if (!communicator.configure(site_elem)) {
+		System.err.println("LibraryServlet.init Error: Couldn't configure communicator");
+		System.exit(1);
+	    }
+	    this.recept.setMessageRouter(communicator);
+	}
+	
+	// the params arg thingy
+	
+	String params_name = (String)config.getInitParameter("params_class");
+	if (params_name == null) {
+	    this.params = new GSParams();
+	} else {
+	    try {
+		this.params = (GSParams)Class.forName("org.greenstone.gsdl3.util."+params_name).newInstance();
+	    } catch (Exception e) {
+		System.err.println("LibraryServlet configure exception when trying to use a new params thing "+params_name+": "+e.getMessage());
+		e.printStackTrace();
+		this.params = new GSParams();
+	    }
+	}
+	// pass it to the receptionist
+	this.recept.setParams(this.params);
+	this.recept.configure();
+	
+    }
+
+
+    private void logUsageInfo(HttpServletRequest request){
+	String usageInfo = "";
+
+	//session-info: get params stored in the session
+	HttpSession session = request.getSession(true);
+        Enumeration attributeNames = session.getAttributeNames();
+	while(attributeNames.hasMoreElements()) {
+	    String name = (String)attributeNames.nextElement();
+	    usageInfo +=name+"="+session.getAttribute(name)+" ";
+	}
+	
+	//logged info = general-info + session-info
+	usageInfo = 
+	    request.getServletPath()+" "+ //serlvet
+	    "["+request.getQueryString()+"]" +" "+ //the query string
+	    "["+usageInfo.trim()+"]" +" "+ // params stored in a session
+	    request.getRemoteAddr()+" "+   //remote address                  
+	    request.getRequestedSessionId()+" "+ //session id
+	    request.getHeader("user-agent")+" "; //the remote brower info                      
+                         
+	logger.info(usageInfo);
+
+    }
+
+       
+    public void doGet(HttpServletRequest request,
+		      HttpServletResponse response)
+	throws ServletException, IOException {
+
+	logUsageInfo(request);
+          
+	// Nested Diagnostic Configurator to identify the client for
+       
+	HttpSession session = request.getSession(true);
+        String uid = (String)session.getAttribute(GSXML.USER_ID_ATT);
+	if (uid ==null) {
+	    uid = ""+getNextUserId();
+	    session.setAttribute(GSXML.USER_ID_ATT, uid);
+	}
+	request.setCharacterEncoding("UTF-8");
+	response.setContentType("text/html;charset=UTF-8");
+	PrintWriter out = response.getWriter();
+
+	String lang = request.getParameter(GSParams.LANGUAGE);
+	if (lang==null || lang.equals("")) {
+	    // try the session cached lang
+	    lang = (String)session.getAttribute(GSParams.LANGUAGE);
+	    if (lang==null || lang.equals("")) {
+		// still not set, use the default
+		lang = this.default_lang;
+	    }
+	}
+	
+	// set the lang in the session
+	session.setAttribute(GSParams.LANGUAGE, lang);
+
+	String output = request.getParameter(GSParams.OUTPUT);
+	if (output==null || output.equals("")) {
+	    output = "html"; // uses html by default
+	}
+
+	// the request to the receptionist	
+	Element xml_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element xml_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PAGE, "", lang, uid);
+	xml_request.setAttribute(GSXML.OUTPUT_ATT, output);
+	xml_message.appendChild(xml_request);
+	
+	
+	String action = request.getParameter(GSParams.ACTION);
+	String subaction = request.getParameter(GSParams.SUBACTION);
+	if (action==null || action.equals("")) {
+	    // should we do all the following stuff if using default page?
+	    // display the home page  - the default page
+	    action = "p";
+	    subaction = PageAction.HOME_PAGE;
+	    xml_request.setAttribute(GSXML.ACTION_ATT, action);
+	    xml_request.setAttribute(GSXML.SUBACTION_ATT, subaction);
+	    
+	} else {
+	
+	    xml_request.setAttribute(GSXML.ACTION_ATT, action);
+	    if (subaction != null) {
+		xml_request.setAttribute(GSXML.SUBACTION_ATT, subaction);
+	    }
+
+	    //  create the param list for the greenstone request - includes
+	    // the params from the current request and any others from the saved session
+	    Element xml_param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	    xml_request.appendChild(xml_param_list);
+	    
+	    Enumeration params = request.getParameterNames();
+	    while(params.hasMoreElements()) {
+		String name = (String)params.nextElement();
+		if (!name.equals(GSParams.ACTION) && !name.equals(GSParams.SUBACTION) && !name.equals(GSParams.LANGUAGE) && !name.equals(GSParams.OUTPUT)) {// we have already dealt with these 
+		    String value="";
+		    String [] values = request.getParameterValues(name);
+		    value = values[0];
+		    if (values.length > 1) {
+			for (int i=1; i< values.length; i++) {
+			    value += ","+values[i];
+			}
+		    }
+		    // either add it to the param list straight away, or save it to the session and add it later
+		    if (this.params.shouldSave(name)) {			
+			session.setAttribute(name, value);
+		    } else { 
+			Element param = this.doc.createElement(GSXML.PARAM_ELEM);
+			param.setAttribute(GSXML.NAME_ATT, name);
+			param.setAttribute(GSXML.VALUE_ATT, GSXML.xmlSafe(value));
+			xml_param_list.appendChild(param);
+		    }
+		}
+	    }
+	    
+	    // put in all the params from the session cache
+	    params = session.getAttributeNames();
+	    while(params.hasMoreElements()) {
+		String name = (String)params.nextElement();
+		
+		if ( !name.equals(GSParams.LANGUAGE) && !name.equals(GSXML.USER_ID_ATT)) { // lang and uid are stored but we dont want it in the param list cos its already in the request
+		    
+		    Element param = this.doc.createElement(GSXML.PARAM_ELEM);
+		    param.setAttribute(GSXML.NAME_ATT, name);
+		    String value =  GSXML.xmlSafe((String)session.getAttribute(name));
+		    // ugly hack to undo : escaping
+		    value = value.replaceAll("%3A", "\\:");
+		    param.setAttribute(GSXML.VALUE_ATT,value);
+		    xml_param_list.appendChild(param);
+		}
+	    }
+
+	
+	}
+	
+	if (!output.equals("html")) {
+	    response.setContentType("text/xml"); // for now use text
+	}
+
+	//GSXML.printXMLNode(xml_message);	
+
+	Element xml_result = this.recept.process(xml_message);
+	encodeURLs(xml_result, response);
+	out.println(this.converter.getPrettyString(xml_result));
+    }
+
+    /** this goes through each URL and adds in a session id if needed--
+     * its needed if the browser doesn't accept cookies
+     * also escapes things if needed
+     */
+    protected void encodeURLs(Element data, HttpServletResponse response) {
+	
+	if (data == null) {
+	    return;
+	}
+	// get all the <a> elements
+	NodeList hrefs = data.getElementsByTagName("a");
+	for (int i=0; i<hrefs.getLength(); i++) {
+	    Element a = (Element)hrefs.item(i);
+	    // ugly hack to get rid of : in the args - interferes with session handling
+	    String href = a.getAttribute("href");
+	    if (!href.equals("")) {
+		if (href.indexOf("?")!=-1) {
+		    String[] parts = href.split("\\?", -1);
+		    parts[1]=parts[1].replaceAll(":", "%3A");
+		    href = parts[0]+"?"+parts[1];
+		}
+		a.setAttribute("href", response.encodeURL(href));
+	    }
+	}
+	
+	// now find any submit bits - get all the <form> elements
+	NodeList forms = data.getElementsByTagName("form");
+	for (int i=0; i<forms.getLength(); i++) {
+	    Element form = (Element)forms.item(i);
+	    form.setAttribute("action", response.encodeURL(form.getAttribute("action")));
+	}
+	// are these the only cases where URLs occur??
+	// we should only do this for greenstone urls?
+	
+    }
+
+    synchronized protected int getNextUserId() {
+	next_user_id++;
+	return next_user_id;
+    }
+
+    public void doPost(HttpServletRequest request,
+		      HttpServletResponse response)
+	throws ServletException, IOException {
+	doGet(request,response);
+
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/SOAPServerlocalsite.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/SOAPServerlocalsite.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/SOAPServerlocalsite.java	(revision 13928)
@@ -0,0 +1,87 @@
+/*
+ *    SOAPServer.java.in: a template for a new SOAPServer
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.greenstone.gsdl3;
+
+import org.greenstone.gsdl3.core.MessageRouter;
+import org.greenstone.gsdl3.util.GlobalProperties;
+import org.greenstone.gsdl3.util.GSFile;
+import org.greenstone.gsdl3.util.GSXML;
+import org.w3c.dom.Element;
+import java.io.File;
+
+/**
+ * The server side of a SOAP connection
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ * @see <a href="http://www.w3.org/TR/SOAP/">Simple Object Access Protocol (SOAP) 1.1 </a>
+ */
+
+public class SOAPServerlocalsite
+{
+    
+    /** The message router we're talking to */
+    protected MessageRouter mr=null;
+    /** the name of the site we are serving */
+    protected String site_name = "localsite";
+  
+    /** The no-args constructor */
+    public SOAPServerlocalsite() {
+	String gsdl3_home = GlobalProperties.getGSDL3Home();
+	if (gsdl3_home == null || gsdl3_home.equals("")) {
+	    System.err.println("Couldn't access GSDL3Home from GlobalProerties.getGSDL3HOME, can't initialize the SOAP Server.");
+	    return;
+	}
+	String site_home = GSFile.siteHome(gsdl3_home, this.site_name);
+	
+	File site_file = new File(site_home);
+	if (!site_file.isDirectory()) {
+	    System.err.println("The site directory "+site_file.getPath()+" doesn't exist. Can't initialize the SOAP Server.");
+	    return;
+	}   	
+	mr = new MessageRouter();
+	mr.setSiteName(this.site_name);
+	mr.configure();
+    }
+    
+    
+    public Element [] process (Element [] xml_in) {
+	Element [] result = new Element[xml_in.length];
+	for (int i=0; i<xml_in.length; i++) {
+	    Element req = xml_in[i];
+	    // get rid of the obligatory namespace that axis needs
+	    String tag_name = req.getTagName();
+	    String namespace="";
+	    if (tag_name.indexOf(':')!= -1) {
+		namespace = tag_name.substring(0, tag_name.indexOf(':'));
+		tag_name = tag_name.substring(tag_name.indexOf(':')+1);	
+	    }
+	    Element new_req = GSXML.duplicateWithNewName(req.getOwnerDocument(), req, tag_name, true);
+	    Element r = mr.process(new_req);
+	    // add the namespace back on
+	    //Element new_res = r;
+	    //if (!namespace.equals("")) {
+	    //	new_res = GSXML.duplicateWithNewName(r.getOwnerDocument(), r, namespace+r.getTagName(), true);
+	    //}
+	    result[i] = r;
+	}
+	return result;
+    }   
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/Action.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/Action.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/Action.java	(revision 13928)
@@ -0,0 +1,140 @@
+package org.greenstone.gsdl3.action;
+
+import org.greenstone.gsdl3.core.ModuleInterface;
+import org.greenstone.gsdl3.util.*;
+// XML classes
+import org.w3c.dom.Node; 
+import org.w3c.dom.NodeList; 
+import org.w3c.dom.Element; 
+import org.w3c.dom.Document; 
+
+// other java stuff
+import java.io.File;
+import java.util.Vector;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+
+import org.apache.log4j.*;
+
+/** base class for Actions */
+abstract public class Action {
+
+    /** the system set up variables */
+    protected HashMap config_params = null;
+    /** container Document to create XML Nodes */
+    protected Document doc=null; 
+    /** a converter class to parse XML and create Docs */
+    protected XMLConverter converter=null;
+    /** a reference to the message router that it must talk to to
+     * get info. it may be a communicator acting as a proxy, but it 
+     doesn't care about that */
+    protected ModuleInterface mr=null;
+
+    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.action.Action.class.getName());
+
+    public Action() {
+	this.converter = new XMLConverter();
+	this.doc = this.converter.newDOM();
+    }
+    /** the config variables must be set before configure is called */
+    public void setConfigParams(HashMap params) {
+	this.config_params = params;
+    }
+    /** sets the message router */
+    public void setMessageRouter(ModuleInterface m) {
+       this.mr = m;
+    }
+    public boolean configure() {
+	// does nothing yet
+	return true;
+    }
+    
+    /** process takes an xml representation of cgi args
+     * and returns the page of results - may be in html/xml/other
+     * depending on the output att of the request */
+    public String process(String xml_in) {
+       
+	Document message_doc = this.converter.getDOM(xml_in);
+	if (message_doc == null) {
+	    logger.error("Couldn't parse request");
+	    logger.error(xml_in);
+	    return null;
+	}
+	Element result = process(message_doc.getDocumentElement());
+	return this.converter.getString(result);
+    }
+    
+    /** the main process method - must be implemented in subclass */
+    abstract public Element process(Element xml_in);
+
+    /** tell the param class what its arguments are 
+     * if an action has its own arguments, this should add them to the params
+     * object - particularly important for args that should not be saved */
+    public boolean getActionParameters(GSParams params) {
+	return true;
+    }
+
+    protected void extractMetadataNames(Element format, HashSet meta_names) {
+	//NodeList nodes = format.getElementsByTagNameNS("metadata", "http://www.greenstone.org/configformat");
+	NodeList nodes = format.getElementsByTagName("gsf:metadata");
+        for (int i=0; i<nodes.getLength(); i++) {
+	    Element elem = (Element)nodes.item(i);
+	    StringBuffer metadata = new StringBuffer();
+	    String all = elem.getAttribute("multiple");
+	    String name = elem.getAttribute("name");
+	    String select = elem.getAttribute("select");
+	    String sep = elem.getAttribute("separator");
+	    if (all.equals("true")) {
+		metadata.append("all");
+		metadata.append(GSConstants.META_RELATION_SEP);
+	    }
+	    if (!select.equals("")) {
+		metadata.append(select);
+		metadata.append(GSConstants.META_RELATION_SEP);
+	    }
+	    if (!sep.equals("")) {
+		metadata.append(GSConstants.META_SEPARATOR_SEP);
+		metadata.append(sep);
+		metadata.append(GSConstants.META_SEPARATOR_SEP);
+		metadata.append(GSConstants.META_RELATION_SEP);
+	    }
+
+	    metadata.append(name);
+	    meta_names.add(metadata.toString());
+	}
+		
+    }
+
+    protected Element createMetadataParamList(HashSet metadata_names) {
+	Element param_list  = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	
+	Element param = null;
+	Iterator i = metadata_names.iterator();
+	while (i.hasNext()) {
+	    String name = (String)i.next();
+	    param = this.doc.createElement(GSXML.PARAM_ELEM);
+	    param_list.appendChild(param);
+	    param.setAttribute(GSXML.NAME_ATT, "metadata");
+	    param.setAttribute(GSXML.VALUE_ATT, name);
+	
+	}
+	return param_list;
+    }
+
+    protected boolean processErrorElements(Element message, Element page) {
+	NodeList error_nodes = message.getElementsByTagName(GSXML.ERROR_ELEM);
+	if (error_nodes.getLength()==0) {
+	    return false;
+	}
+	Document owner = page.getOwnerDocument();
+	for (int i=0; i<error_nodes.getLength(); i++) {
+	    page.appendChild(owner.importNode(error_nodes.item(i), true));
+	}
+	return true;
+    }
+}
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/AppletAction.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/AppletAction.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/AppletAction.java	(revision 13928)
@@ -0,0 +1,124 @@
+package org.greenstone.gsdl3.action;
+
+import org.greenstone.gsdl3.core.ModuleInterface;
+import org.greenstone.gsdl3.util.*;
+// XML classes
+import org.w3c.dom.Node; 
+import org.w3c.dom.NodeList; 
+import org.w3c.dom.Document; 
+import org.w3c.dom.Element; 
+
+import java.util.HashMap;
+import java.io.File;
+
+import org.apache.log4j.*;
+
+/** action class for handling applets */
+public class AppletAction extends Action {
+
+      static Logger logger = Logger.getLogger(org.greenstone.gsdl3.action.AppletAction.class.getName());   
+
+    public Element process (Element message) {
+	
+	Element request = (Element)GSXML.getChildByTagName(message, GSXML.REQUEST_ELEM);
+	Element result = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element page_response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	result.appendChild(page_response);
+
+	// get the collection and service params
+	Element cgi_param_list = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	HashMap params = GSXML.extractParams(cgi_param_list, false);
+
+	// request_type is display (d) or request (r)
+	String request_type = (String)params.get(GSParams.REQUEST_TYPE);
+	if (!request_type.equals("d")&&!request_type.equals("r")) {
+	    logger.error("AppletAction Error: the rt arg should be either d or r, instead it was "+request_type+"!");
+	    return result;
+	}
+	
+	String collection = (String)params.get(GSParams.COLLECTION);
+	boolean coll_specified = true;
+	String service_name=(String)params.get(GSParams.SERVICE);
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	String uid = request.getAttribute(GSXML.USER_ID_ATT);
+	String to=null;
+	if (collection==null||collection.equals("") ) {
+	    coll_specified = false;
+	    to = service_name;
+	} else {
+	    to = GSPath.appendLink(collection, service_name);
+	}
+
+	if (request_type.equals("r")) {
+	    // we are processing stuff for the applet send a message to the service, type="query", and take out the something element, and return that as our result - the applet must take xml
+
+	    Element mr_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	    Element mr_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, to, lang, uid); 
+	    mr_message.appendChild(mr_request);
+	    // just append all the params for now - should filter out unneeded ones
+	    mr_request.appendChild(this.doc.importNode(cgi_param_list, true));
+       
+	    // process the request
+	    Element mr_response = (Element)this.mr.process(mr_message);
+	    // get the applet data out and pass it back as is. 
+	    String path = GSPath.appendLink(GSXML.RESPONSE_ELEM, GSXML.APPLET_DATA_ELEM);
+	    Element applet_info = (Element)GSXML.getNodeByPath(mr_response, path).getFirstChild();
+	    return applet_info;
+	    
+	}
+	
+
+	// get the applet description, and the collection info if a collection is specified
+	
+	Element mr_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element applet_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_DESCRIBE, to, lang, uid); 
+	mr_message.appendChild(applet_request);
+
+	
+	Element mr_response = (Element)this.mr.process(mr_message);
+
+	// add in the applet info
+	String path = GSPath.appendLink(GSXML.RESPONSE_ELEM, GSXML.SERVICE_ELEM);
+	//path = GSPath.appendLink(path, GSXML.APPLET_ELEM);
+	Element service_elem = (Element)this.doc.importNode(GSXML.getNodeByPath(mr_response, path), true);
+	Element applet_elem = (Element)GSXML.getChildByTagName(service_elem, GSXML.APPLET_ELEM);
+	// must handle any params that have values that are not 
+	// necessarily known by the service
+	// should this be done here or by web receptionist??
+	// cant really have an applet without web?
+	editLocalParams(applet_elem, (String)config_params.get(GSConstants.LIBRARY_NAME), collection);
+	page_response.appendChild(service_elem);
+	
+	return result;
+	
+    }
+
+    /** this method looks through the PARAMs of the applet description for 
+     * 'library' or 'collection'. If found, the params are set to  
+     * the appropriate values 
+     * should this be done here or in the receptionist? 
+     */
+    protected void editLocalParams(Element description, String library_name,
+				   String full_collection_name) {
+
+	Node child = description.getFirstChild();
+	while (child != null) {
+	    if (child.getNodeType() == Node.ELEMENT_NODE) {
+		String param = child.getNodeName();
+		if (param.equals("PARAM")||param.equals("param")) {
+		    String name = ((Element)child).getAttribute("NAME");
+		    if (name == null || name.equals("")) {
+			// somethings wrong!!
+		    } else if (name.equals("library")) {
+			((Element)child).setAttribute("VALUE", library_name);
+		    } else if (name.equals("collection")) {
+			((Element)child).setAttribute("VALUE", full_collection_name);
+		    }
+		    
+		}
+	    }
+	    child = child.getNextSibling();
+	}
+    }
+	
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/BrowseAction.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/BrowseAction.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/BrowseAction.java	(revision 13928)
@@ -0,0 +1,297 @@
+package org.greenstone.gsdl3.action;
+
+import org.greenstone.gsdl3.core.ModuleInterface;
+import org.greenstone.gsdl3.util.*;
+// XML classes
+import org.w3c.dom.Node; 
+import org.w3c.dom.NodeList; 
+import org.w3c.dom.Document; 
+import org.w3c.dom.Element; 
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Vector;
+import java.io.File;
+
+import org.apache.log4j.*;
+
+//NOTE: this class not used at present!!!!!
+/** action for classifier browsing */
+public class BrowseAction extends Action {
+
+    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.action.BrowseAction.class.getName());
+
+    public static final String CLASSIFIER_ARG = "cl";
+    public static final String SIBLING_ARG = "sib";
+
+    /** process the request */
+    public Element process (Element message) {
+
+	// get the request - assume only one
+	Element request = (Element)GSXML.getChildByTagName(message, GSXML.REQUEST_ELEM);
+
+	// the result
+	Element result = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element response = classifierBrowse(request);
+	result.appendChild(response);
+	return result;
+    }
+    
+
+    protected Element classifierBrowse(Element request) {
+
+	Element page_response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+
+	// extract the params from the cgi-request, and check that we have a coll specified
+	Element cgi_paramList = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	HashMap params = GSXML.extractParams(cgi_paramList, false);
+
+	String service_name = (String)params.get(GSParams.SERVICE);
+	String collection = (String)params.get(GSParams.COLLECTION);
+	if (collection == null || collection.equals("")) {
+	    logger.error("classifierBrowse, need to specify a collection!");
+	    return page_response;
+	   
+	}
+	
+	//whether to retrieve siblings or not
+	boolean get_siblings = false;
+	String sibs = (String) params.get(SIBLING_ARG);
+	if (sibs != null && sibs.equals("1")) {
+	    get_siblings = true;
+	}
+
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	String uid = request.getAttribute(GSXML.USER_ID_ATT);	
+	String to = GSPath.appendLink(collection, service_name);
+	
+	// the first part of the response is the service description 
+	// for now get this again from the service. 
+	// this should be cached somehow later on. 
+	
+	Element info_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element info_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_DESCRIBE, to, lang, uid); 
+	info_message.appendChild(info_request);
+	
+	// also get the format stuff now if there is some
+	Element format_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_FORMAT, to, lang, uid);
+	info_message.appendChild(format_request);
+	// process the requests
+
+	Element info_response = (Element) this.mr.process(info_message);
+
+	// the two responses
+	NodeList responses = info_response.getElementsByTagName(GSXML.RESPONSE_ELEM);
+	Element service_response = (Element)responses.item(0);
+	Element format_response = (Element)responses.item(1);
+
+	Element service_description = (Element)GSXML.getChildByTagName(service_response, GSXML.SERVICE_ELEM);
+	page_response.appendChild(this.doc.importNode(service_description, true));
+	
+	// if rt=d, then we are just displaying the service
+	String request_type = (String)params.get(GSParams.REQUEST_TYPE);
+	if (request_type.equals("d")) {
+	    //return the page that we have so far
+	    return page_response;
+	}
+    
+	// get the node that the user has clicked on
+	String classifier_node = (String)params.get(CLASSIFIER_ARG);
+	
+	// if the node is not defined, return the page that we have so far
+	if (classifier_node ==null || classifier_node.equals("")) {
+	    return page_response;
+	}
+	
+	// the id of the classifier is the top id of the selected node
+	String top_id = OID.getTop(classifier_node);
+	
+	HashSet metadata_names = new HashSet();
+
+	// add the format info into the response
+	Element format_elem = (Element)GSXML.getChildByTagName(format_response, GSXML.FORMAT_ELEM);
+	if (format_elem != null) {
+	    // find the one for the classifier we are in
+	    Element this_format = GSXML.getNamedElement(format_elem, GSXML.CLASSIFIER_ELEM, GSXML.NAME_ATT, top_id);
+	    if (this_format == null) {
+		this_format = (Element)GSXML.getChildByTagName(format_elem, GSXML.DEFAULT_ELEM);
+	    }
+	    if (this_format != null) {
+		Element new_format = GSXML.duplicateWithNewName(this.doc, this_format, GSXML.FORMAT_ELEM, false);
+		// set teh format type
+		new_format.setAttribute(GSXML.TYPE_ATT, "browse");
+
+		page_response.appendChild(new_format);
+		extractMetadataNames(new_format, metadata_names);
+	    }
+	}
+	
+	logger.info("extracted meta names, "+metadata_names.toString());
+	// get the browse structure for the selected node
+	Element classify_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element classify_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, to, lang, uid);
+	classify_message.appendChild(classify_request);
+	    
+	//Create a parameter list to specify the required structure information
+	// for now, always get ancestors and children
+	Element param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	classify_request.appendChild(param_list);
+	Element param = this.doc.createElement(GSXML.PARAM_ELEM);
+	param_list.appendChild(param);
+	param.setAttribute(GSXML.NAME_ATT, "structure");
+	param.setAttribute(GSXML.VALUE_ATT, "ancestors");
+	param = this.doc.createElement(GSXML.PARAM_ELEM);
+	param_list.appendChild(param);
+	param.setAttribute(GSXML.NAME_ATT, "structure");
+	param.setAttribute(GSXML.VALUE_ATT, "children");
+	if (get_siblings) {
+	    param = this.doc.createElement(GSXML.PARAM_ELEM);
+	    param_list.appendChild(param);
+	    param.setAttribute(GSXML.NAME_ATT, "structure");
+	    param.setAttribute(GSXML.VALUE_ATT, "siblings");
+	}
+
+	// put the classifier node into a classifier node list
+	Element classifier_list = this.doc.createElement(GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
+	Element classifier = this.doc.createElement(GSXML.CLASS_NODE_ELEM);
+	classifier.setAttribute(GSXML.NODE_ID_ATT, classifier_node);
+	classifier_list.appendChild(classifier);
+	classify_request.appendChild(classifier_list);
+	    
+	// process the request
+	Element classify_response = (Element)this.mr.process(classify_message);
+	// get the structure element
+	String path = GSPath.appendLink(GSXML.RESPONSE_ELEM, GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
+	path = GSPath.appendLink(path, GSXML.CLASS_NODE_ELEM);
+	path = GSPath.appendLink(path, GSXML.NODE_STRUCTURE_ELEM);
+	// assume that we always get back the top level CL1 node - this becomes the page_classifier node
+	path = GSPath.appendLink(path, GSXML.CLASS_NODE_ELEM);
+	Element cl_structure = (Element)GSXML.getNodeByPath(classify_response,
+							    path);
+	if (cl_structure ==null) {
+	    logger.error("classifier structure request returned no structure");
+	    return page_response;
+	}   
+    
+	// add the classifier node as the page classifier 
+	Element page_classifier = GSXML.duplicateWithNewName(this.doc, cl_structure,  GSXML.CLASSIFIER_ELEM, true);
+	page_response.appendChild(page_classifier);
+	page_classifier.setAttribute(GSXML.NAME_ATT, top_id);
+	
+	// get the metadata for each classifier node, 
+	// then for each document node
+
+	Element metadata_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+
+	boolean did_classifier = false;
+	boolean did_documents = false;
+	
+    
+	// if there are classifier nodes 
+	// create a metadata request for the classifier, and add it to 
+	// the the message
+	NodeList cl_nodes = page_classifier.getElementsByTagName(GSXML.CLASS_NODE_ELEM);
+	
+	if (cl_nodes.getLength() > 0) {
+	    did_classifier = true;
+	    Element cl_meta_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, to+"MetadataRetrieve", lang, uid);
+	    metadata_message.appendChild(cl_meta_request);
+	    
+	    Element new_cl_nodes_list = this.doc.createElement(GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
+	    cl_meta_request.appendChild(new_cl_nodes_list);
+	    
+	    for (int c=0; c<cl_nodes.getLength(); c++) {
+
+		Element cl = this.doc.createElement(GSXML.CLASS_NODE_ELEM);
+		cl.setAttribute(GSXML.NODE_ID_ATT, ((Element)cl_nodes.item(c)).getAttribute(GSXML.NODE_ID_ATT));
+		new_cl_nodes_list.appendChild(cl);
+	    }
+
+	    // create and add in the param list - for now get all the metadata
+	    // should be based on info sent in from the recept, and the 
+	    // format stuff
+	    Element cl_param_list = null;
+	    if (metadata_names.isEmpty()) {
+		cl_param_list  = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+		Element p = this.doc.createElement(GSXML.PARAM_ELEM);
+		cl_param_list.appendChild(p);
+		p.setAttribute(GSXML.NAME_ATT, "metadata");
+		p.setAttribute(GSXML.VALUE_ATT, "Title");
+	    } else {
+		cl_param_list  = createMetadataParamList(metadata_names);
+	    }
+
+	    cl_meta_request.appendChild(cl_param_list);
+	    
+	}
+
+	// if there are document nodes in the classification (happens 
+	// sometimes), create a second request for document metadata and 
+	// append to the message
+	NodeList doc_nodes = page_classifier.getElementsByTagName(GSXML.DOC_NODE_ELEM);
+	if (doc_nodes.getLength() > 0) {
+	    did_documents = true;
+	    Element doc_meta_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, GSPath.appendLink(collection, "DocumentMetadataRetrieve"), lang, uid);
+	    metadata_message.appendChild(doc_meta_request);
+	    
+	    Element doc_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	    doc_meta_request.appendChild(doc_list);
+	    
+	    for (int c=0; c<doc_nodes.getLength(); c++) {
+		
+		Element d = this.doc.createElement(GSXML.DOC_NODE_ELEM);
+		d.setAttribute(GSXML.NODE_ID_ATT, ((Element)doc_nodes.item(c)).getAttribute(GSXML.NODE_ID_ATT));
+		doc_list.appendChild(d);
+	    }
+
+	    // create and add in the param list - add all for now
+	    Element doc_param_list  = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	    Element p = this.doc.createElement(GSXML.PARAM_ELEM);
+	    doc_param_list.appendChild(p);
+	    p.setAttribute(GSXML.NAME_ATT, "metadata");
+	    p.setAttribute(GSXML.VALUE_ATT, "all");
+	    doc_meta_request.appendChild(doc_param_list);
+
+	}
+	
+	// process the metadata requests
+	Element metadata_response = (Element)this.mr.process(metadata_message);
+	if (did_classifier) {
+	    // the classifier one will be the first response
+	    // add the metadata lists for each node back into the 
+	    // page_classifier nodes
+	    path = GSPath.appendLink(GSXML.RESPONSE_ELEM, 
+				   GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
+	    NodeList meta_response_cls = GSXML.getNodeByPath(metadata_response, path).getChildNodes();
+	    for (int i = 0; i < cl_nodes.getLength(); i++) {
+		GSXML.mergeMetadataLists(cl_nodes.item(i), meta_response_cls.item(i));
+	    }
+	}
+	if (did_documents) {
+	    NodeList meta_response_docs = null;
+	    if (!did_classifier) {
+		// its the first response
+		path = GSPath.appendLink(GSXML.RESPONSE_ELEM, 
+					 GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+		meta_response_docs = GSXML.getNodeByPath(metadata_response, path).getChildNodes();
+	    } else { // its the second response
+		meta_response_docs = GSXML.getChildByTagName(metadata_response.getElementsByTagName(GSXML.RESPONSE_ELEM).item(1), GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER).getChildNodes();
+	    }
+	    
+	    for (int i = 0; i < doc_nodes.getLength(); i++) {
+		GSXML.mergeMetadataLists(doc_nodes.item(i), meta_response_docs.item(i));
+	    }
+	}
+	    
+
+	logger.debug("(BrowseAction) Page:\n" + this.converter.getPrettyString(page_response));
+	return page_response;
+    }
+
+    protected Element unknownBrowse(Element page, Element request, String browse_type) {
+	logger.error("unknown browse subtype: "+browse_type);
+	return null;
+    }
+}
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/DocumentAction.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/DocumentAction.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/DocumentAction.java	(revision 13928)
@@ -0,0 +1,847 @@
+/*
+ *    DocumentAction.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.action;
+
+// Greenstone classes
+import org.greenstone.gsdl3.core.ModuleInterface;
+import org.greenstone.gsdl3.util.*;
+
+// XML classes
+import org.w3c.dom.Document; 
+import org.w3c.dom.Element; 
+import org.w3c.dom.Node; 
+import org.w3c.dom.Text;
+import org.w3c.dom.NodeList;
+
+// General Java classes
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.io.File;
+
+import org.apache.log4j.*;
+
+/** Action class for retrieving Documents  via the message router
+ */
+public class DocumentAction extends Action {
+
+   static Logger logger = Logger.getLogger(org.greenstone.gsdl3.action.DocumentAction.class.getName());
+
+    // this is used to specify that the sibling nodes of a selected one should be obtained
+    public static final String SIBLING_ARG = "sib";
+    public static final String GOTO_PAGE_ARG = "gp";
+    public static final String ENRICH_DOC_ARG = "end";
+    
+    /** if this is set to true, when a document is displayed, any annotation
+     * type services (enrich) will be offered to the user as well */
+    protected boolean provide_annotations = false; 
+    
+    protected boolean highlight_query_terms = false;
+
+    public boolean configure() {
+	super.configure();
+	String highlight = (String)config_params.get("highlightQueryTerms");
+	if (highlight != null && highlight.equals("true")) {
+	    highlight_query_terms = true;
+	}
+	String annotate = (String)config_params.get("displayAnnotationService");
+	if (annotate != null && annotate.equals("true")) {
+	    provide_annotations = true;
+	}
+	return true;
+    }
+    public Element process (Element message)
+    {
+	// for now, no subaction eventually we may want to have subactions such as text assoc or something ?
+	
+	// the response
+	Element result = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element page_response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	result.appendChild(page_response);
+
+	// get the request - assume only one
+	Element request = (Element)GSXML.getChildByTagName(message, GSXML.REQUEST_ELEM);
+	Element cgi_paramList = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	HashMap params = GSXML.extractParams(cgi_paramList, false);
+
+	// just in case there are some that need to get passed to the services
+	HashMap service_params = (HashMap)params.get("s0"); 
+
+	String collection = (String) params.get(GSParams.COLLECTION);
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	String uid = request.getAttribute(GSXML.USER_ID_ATT);
+	String document_name = (String) params.get(GSParams.DOCUMENT);
+	if (document_name == null || document_name.equals("")) {
+	    logger.error("no document specified!");
+	    return result;
+	}
+	String document_type = (String) params.get(GSParams.DOCUMENT_TYPE);
+	if (document_type == null) {
+	    document_type = "simple";
+	}
+	//whether to retrieve siblings or not
+	boolean get_siblings = false;
+	String sibs = (String) params.get(SIBLING_ARG);
+	if (sibs != null && sibs.equals("1")) {
+	    get_siblings = true;
+	}
+	
+	String sibling_num = (String) params.get(GOTO_PAGE_ARG);
+	if (sibling_num != null && !sibling_num.equals("")) {
+	    // we have to modify the doc name
+	    document_name = document_name+"."+sibling_num+".ss";
+	}
+	
+	boolean expand_document = false;
+	String ed_arg = (String) params.get(GSParams.EXPAND_DOCUMENT);
+	if (ed_arg != null && ed_arg.equals("1")) {
+	    expand_document = true;
+	}
+       
+
+	boolean expand_contents = false;
+	if (expand_document) { // we always expand the contents with the text
+	    expand_contents = true;
+	} else {
+	    String ec_arg = (String) params.get(GSParams.EXPAND_CONTENTS);
+	    if (ec_arg != null && ec_arg.equals("1")) {
+		expand_contents = true;
+	    }
+	}
+	// get the additional data needed for the page
+	getBackgroundData(page_response, collection, lang, uid);
+	Element format_elem = (Element)GSXML.getChildByTagName(page_response, GSXML.FORMAT_ELEM);
+	
+	// the_document is where all the doc info - structure and metadata etc
+	// is added into, to be returned in the page
+	Element the_document = this.doc.createElement(GSXML.DOCUMENT_ELEM);
+	page_response.appendChild(the_document);
+
+	// set the doctype from the cgi arg as an attribute
+	the_document.setAttribute(GSXML.DOC_TYPE_ATT, document_type);
+
+	// create a basic doc list containing the current node
+	Element basic_doc_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	Element current_doc = this.doc.createElement(GSXML.DOC_NODE_ELEM);
+	basic_doc_list.appendChild(current_doc);
+	current_doc.setAttribute(GSXML.NODE_ID_ATT, document_name);
+	
+	// Create a parameter list to specify the required structure information
+	Element ds_param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	
+	if (service_params != null) {
+	    GSXML.addParametersToList(this.doc, ds_param_list, service_params);
+	}
+
+	Element ds_param = null; 
+	boolean get_structure = false;
+	boolean get_structure_info = false;
+	if (document_type.equals("paged")) {
+	    get_structure_info = true;
+	    // get teh info needed for paged naviagtion
+	    ds_param = this.doc.createElement(GSXML.PARAM_ELEM);
+	    ds_param_list.appendChild(ds_param);
+	    ds_param.setAttribute(GSXML.NAME_ATT, "info");
+	    ds_param.setAttribute(GSXML.VALUE_ATT, "numSiblings");
+	    ds_param = this.doc.createElement(GSXML.PARAM_ELEM);
+	    ds_param_list.appendChild(ds_param);
+	    ds_param.setAttribute(GSXML.NAME_ATT, "info");
+	    ds_param.setAttribute(GSXML.VALUE_ATT, "numChildren");
+	    ds_param = this.doc.createElement(GSXML.PARAM_ELEM);
+	    ds_param_list.appendChild(ds_param);
+	    ds_param.setAttribute(GSXML.NAME_ATT, "info");
+	    ds_param.setAttribute(GSXML.VALUE_ATT, "siblingPosition");
+	    
+	} else if (document_type.equals("hierarchy")){
+	    get_structure = true;
+	    if (expand_contents) {
+		ds_param = this.doc.createElement(GSXML.PARAM_ELEM);
+		ds_param_list.appendChild(ds_param);
+		ds_param.setAttribute(GSXML.NAME_ATT, "structure");
+		ds_param.setAttribute(GSXML.VALUE_ATT, "entire");
+	    } else {
+		// get the info needed for table of contents
+		ds_param = this.doc.createElement(GSXML.PARAM_ELEM);
+		ds_param_list.appendChild(ds_param);
+		ds_param.setAttribute(GSXML.NAME_ATT, "structure");
+		ds_param.setAttribute(GSXML.VALUE_ATT, "ancestors");
+		ds_param = this.doc.createElement(GSXML.PARAM_ELEM);
+		ds_param_list.appendChild(ds_param);
+		ds_param.setAttribute(GSXML.NAME_ATT, "structure");
+		ds_param.setAttribute(GSXML.VALUE_ATT, "children");
+		if (get_siblings) {
+		    ds_param = this.doc.createElement(GSXML.PARAM_ELEM);
+		    ds_param_list.appendChild(ds_param);
+		    ds_param.setAttribute(GSXML.NAME_ATT, "structure");
+		    ds_param.setAttribute(GSXML.VALUE_ATT, "siblings");
+		}
+	    }
+	} else {
+	    // we dont need any structure
+	}
+
+	boolean has_dummy = false;
+	if (get_structure || get_structure_info) {
+
+	    // Build a request to obtain the document structure
+	    Element ds_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	    String to = GSPath.appendLink(collection, "DocumentStructureRetrieve");// Hard-wired?
+	    Element ds_request = GSXML.createBasicRequest(this.doc,GSXML.REQUEST_TYPE_PROCESS, to, lang, uid); 
+	    ds_message.appendChild(ds_request);
+	    ds_request.appendChild(ds_param_list);
+	    
+	    // create a doc_node_list and put in the doc_node that we are interested in
+	    ds_request.appendChild(basic_doc_list);
+	    
+	    // Process the document structure retrieve message
+	    Element ds_response_message = (Element) this.mr.process(ds_message);
+	    if (processErrorElements(ds_response_message, page_response)) {
+		return result;
+	    }
+
+	    // get the info and print out
+	    String path = GSPath.appendLink(GSXML.RESPONSE_ELEM, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	    path = GSPath.appendLink(path, GSXML.DOC_NODE_ELEM);
+	    path = GSPath.appendLink(path, "nodeStructureInfo");
+	    Element ds_response_struct_info = (Element) GSXML.getNodeByPath(ds_response_message, path);
+	    // get the doc_node bit 
+	    if (ds_response_struct_info != null) {
+		the_document.appendChild(this.doc.importNode(ds_response_struct_info, true)); 
+	    }
+	    path = GSPath.appendLink(GSXML.RESPONSE_ELEM, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	    path = GSPath.appendLink(path, GSXML.DOC_NODE_ELEM);
+	    path = GSPath.appendLink(path, GSXML.NODE_STRUCTURE_ELEM);
+	    Element ds_response_structure = (Element) GSXML.getNodeByPath(ds_response_message, path);
+	    
+	    if (ds_response_structure != null) {
+		// add the contents of the structure bit into the_document
+		NodeList structs = ds_response_structure.getChildNodes();
+		for (int i=0; i<structs.getLength();i++) {
+		    the_document.appendChild(this.doc.importNode(structs.item(i), true));
+		}
+	    } else {
+		// no structure nodes, so put in a dummy doc node
+		Element doc_node = this.doc.createElement(GSXML.DOC_NODE_ELEM);
+		doc_node.setAttribute(GSXML.NODE_ID_ATT, document_name);
+		the_document.appendChild(doc_node);
+		has_dummy = true;
+	    }
+	} else { // a simple type - we dont have a dummy node for simple
+	    // should think about this more
+	    // no structure request, so just put in a dummy doc node
+	    Element doc_node = this.doc.createElement(GSXML.DOC_NODE_ELEM);
+	    doc_node.setAttribute(GSXML.NODE_ID_ATT, document_name);
+	    the_document.appendChild(doc_node);
+	    has_dummy = true;
+	}
+	
+	// Build a request to obtain some document metadata
+	Element dm_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	String to = GSPath.appendLink(collection, "DocumentMetadataRetrieve");  // Hard-wired?
+	Element dm_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, to, lang, uid);
+	dm_message.appendChild(dm_request);
+	// Create a parameter list to specify the required metadata information
+	
+	HashSet meta_names = new HashSet();
+	meta_names.add("Title"); // the default
+	if (format_elem != null) {
+	    extractMetadataNames(format_elem, meta_names);
+	}
+	
+	Element dm_param_list = createMetadataParamList(meta_names);
+	if (service_params != null) {
+	    GSXML.addParametersToList(this.doc, dm_param_list, service_params);
+	}
+	
+	dm_request.appendChild(dm_param_list);
+	
+	
+	// create the doc node list for the metadata request
+	Element dm_doc_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	dm_request.appendChild(dm_doc_list);
+
+	// Add each node from the structure response into the metadata request
+	NodeList doc_nodes = the_document.getElementsByTagName(GSXML.DOC_NODE_ELEM);
+	for (int i = 0; i < doc_nodes.getLength(); i++) {
+	    Element doc_node = (Element) doc_nodes.item(i);
+	    String doc_node_id = doc_node.getAttribute(GSXML.NODE_ID_ATT);
+
+	    // Add the documentNode to the list
+	    Element dm_doc_node = this.doc.createElement(GSXML.DOC_NODE_ELEM);
+	    dm_doc_list.appendChild(dm_doc_node);
+	    dm_doc_node.setAttribute(GSXML.NODE_ID_ATT, doc_node_id);
+	    dm_doc_node.setAttribute(GSXML.NODE_TYPE_ATT,
+				     doc_node.getAttribute(GSXML.NODE_TYPE_ATT));
+	}
+
+	// we also want a metadata request to the top level document to get
+	// assocfilepath - this could be cached too
+	Element doc_meta_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, to, lang, uid);
+	dm_message.appendChild(doc_meta_request);
+	Element doc_meta_param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	if (service_params != null) {
+	    GSXML.addParametersToList(this.doc, doc_meta_param_list, service_params);
+	}
+
+	doc_meta_request.appendChild(doc_meta_param_list);
+	Element doc_param = this.doc.createElement(GSXML.PARAM_ELEM);
+	doc_meta_param_list.appendChild(doc_param);
+	doc_param.setAttribute(GSXML.NAME_ATT, "metadata");
+	doc_param.setAttribute(GSXML.VALUE_ATT, "archivedir");
+
+	// create the doc node list for the metadata request
+	Element doc_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	doc_meta_request.appendChild(doc_list);
+
+	Element doc_node = this.doc.createElement(GSXML.DOC_NODE_ELEM);
+	// the node we want is the root document node
+	doc_node.setAttribute(GSXML.NODE_ID_ATT, document_name+".rt");
+	doc_list.appendChild(doc_node);
+	Element dm_response_message = (Element) this.mr.process(dm_message);
+	if (processErrorElements(dm_response_message, page_response)) {
+	    return result;
+	}
+
+	String path = GSPath.appendLink(GSXML.RESPONSE_ELEM, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	Element dm_response_doc_list = (Element) GSXML.getNodeByPath(dm_response_message, path);
+
+	// Merge the metadata with the structure information
+	NodeList dm_response_docs = dm_response_doc_list.getChildNodes();
+	for (int i = 0; i < doc_nodes.getLength(); i++) {
+	    GSXML.mergeMetadataLists(doc_nodes.item(i), dm_response_docs.item(i));
+	}
+	// get teh top level doc metadata out
+	Element doc_meta_response = (Element)dm_response_message.getElementsByTagName(GSXML.RESPONSE_ELEM).item(1);
+	Element doc_meta_list = (Element)GSXML.getNodeByPath(doc_meta_response, "documentNodeList/documentNode/metadataList");
+	if (doc_meta_list != null) {
+	    the_document.appendChild(this.doc.importNode(doc_meta_list, true));
+	}
+	// Build a request to obtain some document content
+	Element dc_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	to = GSPath.appendLink(collection, "DocumentContentRetrieve");  // Hard-wired?
+	Element dc_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, to, lang, uid);
+	dc_message.appendChild(dc_request);
+	
+
+	// Create a parameter list to specify the request parameters - empty for now
+	Element dc_param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	if (service_params != null) {
+	    GSXML.addParametersToList(this.doc, dc_param_list, service_params);
+	}
+
+	dc_request.appendChild(dc_param_list);
+
+	// get the content
+	// the doc list for the content request is the same as the one for the structure request unless we want the whole document, in which case its the same as for the metadata request.
+	if (expand_document) {
+	    dc_request.appendChild(dm_doc_list);
+	} else {
+	    dc_request.appendChild(basic_doc_list);
+	}
+	logger.debug("request = "+converter.getString(dc_message));
+	Element dc_response_message = (Element) this.mr.process(dc_message);
+	if (processErrorElements(dc_response_message, page_response)) {
+	    return result;
+	}
+
+	Element dc_response_doc_list = (Element) GSXML.getNodeByPath(dc_response_message, path);
+
+	if (expand_document) {
+	    // Merge the content with the structure information
+	    NodeList dc_response_docs = dc_response_doc_list.getChildNodes();
+	    for (int i = 0; i < doc_nodes.getLength(); i++) {
+		Node content = GSXML.getChildByTagName((Element)dc_response_docs.item(i), "nodeContent");
+		if (content != null) {
+		    doc_nodes.item(i).appendChild(this.doc.importNode(content, true));
+		}
+		//GSXML.mergeMetadataLists(doc_nodes.item(i), dm_response_docs.item(i));
+	    }
+	} else {
+	    
+	    //path = GSPath.appendLink(path, GSXML.DOC_NODE_ELEM);
+	    Element dc_response_doc = (Element) GSXML.getChildByTagName(dc_response_doc_list, GSXML.DOC_NODE_ELEM);
+	    Element dc_response_doc_content = (Element) GSXML.getChildByTagName(dc_response_doc, GSXML.NODE_CONTENT_ELEM);
+	    
+	    if (dc_response_doc_content == null) {
+		// no content to add
+		return result;
+	    }
+	    if (highlight_query_terms) {
+		dc_response_doc.removeChild(dc_response_doc_content);
+		
+		dc_response_doc_content = highlightQueryTerms(request, dc_response_doc_content);
+		dc_response_doc.appendChild(dc_response_doc.getOwnerDocument().importNode(dc_response_doc_content, true));
+	    }
+	    
+	
+	if (provide_annotations) {
+	    String service_selected = (String)params.get(ENRICH_DOC_ARG);
+	    if (service_selected != null && service_selected.equals("1")) {
+		// now we can modifiy the response doc if needed
+		String enrich_service = (String)params.get(GSParams.SERVICE);
+		// send a message to the service
+		Element enrich_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+		Element enrich_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, enrich_service, lang, uid);
+		enrich_message.appendChild(enrich_request);
+		// check for parameters
+		HashMap e_service_params = (HashMap)params.get("s1");
+		if (e_service_params != null) { 
+		    Element enrich_pl = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+		    GSXML.addParametersToList(this.doc, enrich_pl, e_service_params); 
+		    enrich_request.appendChild(enrich_pl);
+		}
+		Element e_doc_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+		enrich_request.appendChild(e_doc_list);
+		e_doc_list.appendChild(this.doc.importNode(dc_response_doc, true));
+		
+		Element enrich_response = this.mr.process(enrich_message);
+		
+		String [] links = {GSXML.RESPONSE_ELEM, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER, GSXML.DOC_NODE_ELEM, GSXML.NODE_CONTENT_ELEM};
+		path = GSPath.createPath(links);
+		dc_response_doc_content = (Element)GSXML.getNodeByPath(enrich_response, path);
+		
+	    } 
+	} // if provide_annotations
+
+	
+	// use the returned id rather than the sent one cos there may have
+	// been modifiers such as .pr that are removed.
+	String modified_doc_id = dc_response_doc.getAttribute(GSXML.NODE_ID_ATT);
+	the_document.setAttribute("selectedNode", modified_doc_id);
+	if (has_dummy) {
+	    // change the id if necessary and add the content
+	    Element dummy_node = (Element)doc_nodes.item(0);
+	    
+	    dummy_node.setAttribute(GSXML.NODE_ID_ATT, modified_doc_id);
+	    dummy_node.appendChild(this.doc.importNode(dc_response_doc_content, true));
+	    // hack for simple type
+	    if (document_type.equals("simple")) {
+		// we dont want the internal docNode, just want the content and metadata in the document
+		// rethink this!!
+		the_document.removeChild(dummy_node);
+
+		NodeList dummy_children = dummy_node.getChildNodes();
+		//for (int i=0; i<dummy_children.getLength(); i++) {
+		for (int i=dummy_children.getLength()-1; i>=0; i--) {
+		    the_document.appendChild(dummy_children.item(i));
+		    
+		}
+	    }
+	} else {
+	    // Merge the document content with the metadata and structure information
+	    for (int i = 0; i < doc_nodes.getLength(); i++) {
+		Node dn = doc_nodes.item(i);
+		String dn_id = ((Element)dn).getAttribute(GSXML.NODE_ID_ATT);
+		if (dn_id.equals(modified_doc_id)) {
+		    dn.appendChild(this.doc.importNode(dc_response_doc_content, true));
+		    break;
+		}
+	    }
+	}
+	}
+	logger.debug("(DocumentAction) Page:\n" + this.converter.getPrettyString(result));
+	return result;
+    }
+    
+    /** tell the param class what its arguments are 
+     * if an action has its own arguments, this should add them to the params
+     * object - particularly important for args that should not be saved */
+    public boolean getActionParameters(GSParams params) {
+	params.addParameter(GOTO_PAGE_ARG, false);
+	params.addParameter(ENRICH_DOC_ARG, false);
+ 	return true;
+    }
+
+
+    /** this method gets the collection description, the format info, the
+     * list of enrich services, etc - stuff that is needed for the page,
+     * but is the same whatever the query is - should be cached */
+    protected  boolean getBackgroundData(Element page_response, 
+					 String collection, String lang,
+					 String uid) {
+
+	// create a message to process - contains requests for the collection 
+	// description, the format element, the enrich services on offer
+	// these could all be cached
+	Element info_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	String path = GSPath.appendLink(collection, "DocumentContentRetrieve");
+	// the format request - ignore for now, where does this request go to??
+	Element format_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_FORMAT, path, lang, uid);
+	info_message.appendChild(format_request);
+
+	// the enrich_services request - only do this if provide_annotations is true
+
+	if (provide_annotations) {
+	    Element enrich_services_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_DESCRIBE, "", lang, uid);
+	    enrich_services_request.setAttribute(GSXML.INFO_ATT, "serviceList");
+	    info_message.appendChild(enrich_services_request);
+	}
+	
+	Element info_response = (Element)this.mr.process(info_message);
+
+	// the collection is the first response
+	NodeList responses = info_response.getElementsByTagName(GSXML.RESPONSE_ELEM);
+	Element format_resp = (Element) responses.item(0);
+	
+	Element format_elem = (Element)GSXML.getChildByTagName(format_resp, GSXML.FORMAT_ELEM);
+	if (format_elem != null) {
+	    logger.debug("doc action found a format statement");
+	    // set teh format type
+	    format_elem.setAttribute(GSXML.TYPE_ATT, "display");  
+	    page_response.appendChild(this.doc.importNode(format_elem, true));
+	}
+
+	if (provide_annotations) {
+	    Element services_resp = (Element)responses.item(1); 
+
+	    // a new message for the mr
+	    Element enrich_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	    
+	    NodeList e_services = services_resp.getElementsByTagName(GSXML.SERVICE_ELEM);
+	    boolean service_found = false;
+	    for (int j=0; j<e_services.getLength(); j++) {
+		if (((Element)e_services.item(j)).getAttribute(GSXML.TYPE_ATT).equals("enrich")) {
+		    Element s = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_DESCRIBE, ((Element)e_services.item(j)).getAttribute(GSXML.NAME_ATT), lang, uid);
+		    enrich_message.appendChild(s);
+		    service_found = true;
+		}
+	    }
+	    if (service_found) {
+		Element enrich_response = this.mr.process(enrich_message);
+
+		NodeList e_responses = enrich_response.getElementsByTagName(GSXML.RESPONSE_ELEM);
+		Element service_list = this.doc.createElement(GSXML.SERVICE_ELEM + GSXML.LIST_MODIFIER);
+		for (int i=0; i<e_responses.getLength(); i++) {
+		    Element e_resp = (Element)e_responses.item(i);
+		    Element e_service = (Element)this.doc.importNode(GSXML.getChildByTagName(e_resp, GSXML.SERVICE_ELEM), true); 
+		    e_service.setAttribute(GSXML.NAME_ATT, e_resp.getAttribute(GSXML.FROM_ATT));
+		    service_list.appendChild(e_service);
+		}
+		page_response.appendChild(service_list);
+	    }
+	} // if provide_annotations
+	return true;
+	    
+    }
+
+    /** this involves a bit of a hack to get the equivalent query terms - has to requery the query service - uses the last selected service name. (if it ends in query). should this action do the query or should it send a message to the query action? but that will involve lots of extra stuff. also doesn't handle phrases properly - just highlights all the terms found in the text.
+     */
+    protected Element highlightQueryTerms(Element request, Element dc_response_doc_content) {
+
+	// do the query again to get term info 
+	Element cgi_param_list = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	HashMap params = GSXML.extractParams(cgi_param_list, false);
+	
+	HashMap previous_params = (HashMap)params.get("p");
+	if (previous_params == null) {
+	    return dc_response_doc_content;
+	}
+       	String service_name = (String)previous_params.get(GSParams.SERVICE);
+	if (service_name == null || !service_name.endsWith("Query")) { // hack for now - we only do highlighting if we were in a query last - ie not if we were in a browse thingy
+	    logger.error("invalid service, not doing highlighting");
+	    return dc_response_doc_content;
+	}
+	String collection = (String)params.get(GSParams.COLLECTION);
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	String uid = request.getAttribute(GSXML.USER_ID_ATT);
+	String to = GSPath.appendLink(collection, service_name);
+	
+	Element mr_query_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element mr_query_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, to, lang, uid);
+	mr_query_message.appendChild(mr_query_request);
+	
+	// paramList
+	HashMap service_params = (HashMap)params.get("s1");
+	
+	Element query_param_list = this.doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
+	GSXML.addParametersToList(this.doc, query_param_list, service_params);
+	mr_query_request.appendChild(query_param_list);
+
+	// do the query
+       	Element mr_query_response = (Element)this.mr.process(mr_query_message);
+	
+	String path = GSPath.appendLink(GSXML.RESPONSE_ELEM, GSXML.TERM_ELEM+GSXML.LIST_MODIFIER);
+	Element query_term_list_element = (Element) GSXML.getNodeByPath(mr_query_response, path);
+	if (query_term_list_element == null) {
+	    // no term info
+	    logger.error("No query term information.\n");
+	    return dc_response_doc_content;
+	} 
+
+	String content = GSXML.getNodeText(dc_response_doc_content);
+
+	String metadata_path = GSPath.appendLink(GSXML.RESPONSE_ELEM, GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
+	Element metadata_list = (Element) GSXML.getNodeByPath(mr_query_response, metadata_path);
+
+	HashSet query_term_variants = new HashSet();
+	NodeList equivalent_terms_nodelist = query_term_list_element.getElementsByTagName("equivTermList");
+	for (int i = 0; i < equivalent_terms_nodelist.getLength(); i++) {
+	    Element equivalent_terms_element = (Element) equivalent_terms_nodelist.item(i);
+	    String[] equivalent_terms = GSXML.getAttributeValuesFromList(equivalent_terms_element, GSXML.NAME_ATT);
+	    for (int j = 0; j < equivalent_terms.length; j++) {
+		query_term_variants.add(equivalent_terms[j]);
+	    }
+	}
+
+	ArrayList phrase_query_term_variants_hierarchy = new ArrayList();
+
+	Element query_element = GSXML.getNamedElement(metadata_list, GSXML.METADATA_ELEM, GSXML.NAME_ATT, "query");
+	String performed_query = GSXML.getNodeText(query_element) + " ";
+
+	ArrayList phrase_query_p_term_variants_list = new ArrayList();
+	int term_start = 0;
+	boolean in_term = false;
+	boolean in_phrase = false;
+	for (int i = 0; i < performed_query.length(); i++) {
+	    char character = performed_query.charAt(i);
+	    boolean is_character_letter_or_digit = Character.isLetterOrDigit(character);
+
+	    // Has a query term just started?
+	    if (in_term == false && is_character_letter_or_digit == true) {
+		in_term = true;
+		term_start = i;
+	    }
+
+	    // Or has a term just finished?
+	    else if (in_term == true && is_character_letter_or_digit == false) {
+		in_term = false;
+		String term = performed_query.substring(term_start, i);
+				
+		Element term_element = GSXML.getNamedElement(query_term_list_element, GSXML.TERM_ELEM, GSXML.NAME_ATT, term);
+		if (term_element != null) {
+		    
+		    HashSet phrase_query_p_term_x_variants = new HashSet();
+		    
+		    NodeList term_equivalent_terms_nodelist = term_element.getElementsByTagName("equivTermList");
+		    for (int j = 0; j < term_equivalent_terms_nodelist.getLength(); j++) {
+			Element term_equivalent_terms_element = (Element) term_equivalent_terms_nodelist.item(j);
+			String[] term_equivalent_terms = GSXML.getAttributeValuesFromList(term_equivalent_terms_element, GSXML.NAME_ATT);
+			for (int k = 0; k < term_equivalent_terms.length; k++) {
+			    phrase_query_p_term_x_variants.add(term_equivalent_terms[k]);
+			}
+		    }
+		    phrase_query_p_term_variants_list.add(phrase_query_p_term_x_variants);
+		    
+		    if (in_phrase == false) {
+			phrase_query_term_variants_hierarchy.add(phrase_query_p_term_variants_list);
+			phrase_query_p_term_variants_list = new ArrayList();
+		    }
+		}
+	    }
+	    // Watch for phrases (surrounded by quotes)
+	    if (character == '\"') {
+		// Has a phrase just started?
+		if (in_phrase == false) {
+		    in_phrase = true;
+		}
+		// Or has a phrase just finished?
+		else if (in_phrase == true) {
+		    in_phrase = false;
+		    phrase_query_term_variants_hierarchy.add(phrase_query_p_term_variants_list);
+		}
+
+		phrase_query_p_term_variants_list = new ArrayList();
+	    }
+	}
+
+	return highlightQueryTermsInternal(content, query_term_variants, phrase_query_term_variants_hierarchy);
+    }
+
+
+    /**
+     * Highlights query terms in a piece of text.
+     */
+    private Element highlightQueryTermsInternal(String content, HashSet query_term_variants, ArrayList phrase_query_term_variants_hierarchy)
+    {
+	// Convert the content string to an array of characters for speed
+	char[] content_characters = new char[content.length()];
+	content.getChars(0, content.length(), content_characters, 0);
+
+	// Now skim through the content, identifying word matches
+	ArrayList word_matches = new ArrayList();
+	int word_start = 0;
+	boolean in_word = false;
+	boolean preceding_word_matched = false;
+	for (int i = 0; i < content_characters.length; i++) {
+	    boolean is_character_letter_or_digit = Character.isLetterOrDigit(content_characters[i]);
+
+	    // Has a word just started?
+	    if (in_word == false && is_character_letter_or_digit == true) {
+		in_word = true;
+		word_start = i;
+	    }
+
+	    // Or has a word just finished?
+	    else if (in_word == true && is_character_letter_or_digit == false) {
+		in_word = false;
+
+		// Check if the word matches any of the query term equivalents
+		String word = new String(content_characters, word_start, (i - word_start));
+		if (query_term_variants.contains(word)) {
+		    // We have found a matching word, so remember its location
+		    word_matches.add(new WordMatch(word, word_start, i, preceding_word_matched));
+		    preceding_word_matched = true;
+ 		}
+		else {
+		    preceding_word_matched = false;
+		}
+	    }
+	}
+
+	// Don't forget the last word...
+	if (in_word == true) {
+	    // Check if the word matches any of the query term equivalents
+	    String word = new String(content_characters, word_start, (content_characters.length - word_start));
+	    if (query_term_variants.contains(word)) {
+		// We have found a matching word, so remember its location
+		word_matches.add(new WordMatch(word, word_start, content_characters.length, preceding_word_matched));
+	    }
+	}
+
+	ArrayList highlight_start_positions = new ArrayList();
+	ArrayList highlight_end_positions = new ArrayList();
+
+	// Deal with phrases now
+	ArrayList partial_phrase_matches = new ArrayList();
+	for (int i = 0; i < word_matches.size(); i++) {
+	    WordMatch word_match = (WordMatch) word_matches.get(i);
+
+ 	    // See if any partial phrase matches are extended by this word
+ 	    if (word_match.preceding_word_matched) {
+ 		for (int j = partial_phrase_matches.size() - 1; j >= 0; j--) {
+ 		    PartialPhraseMatch partial_phrase_match = (PartialPhraseMatch) partial_phrase_matches.remove(j);
+		    ArrayList phrase_query_p_term_variants_list = (ArrayList) phrase_query_term_variants_hierarchy.get(partial_phrase_match.query_phrase_number);
+ 		    HashSet phrase_query_p_term_x_variants = (HashSet) phrase_query_p_term_variants_list.get(partial_phrase_match.num_words_matched);
+ 		    if (phrase_query_p_term_x_variants.contains(word_match.word)) {
+ 			partial_phrase_match.num_words_matched++;
+
+ 			// Has a complete phrase match occurred?
+ 			if (partial_phrase_match.num_words_matched == phrase_query_p_term_variants_list.size()) {
+ 			    // Check for overlaps by looking at the previous highlight range
+ 			    if (!highlight_end_positions.isEmpty()) {
+ 				int last_highlight_index = highlight_end_positions.size() - 1;
+ 				int last_highlight_end = ((Integer) highlight_end_positions.get(last_highlight_index)).intValue();
+ 				if (last_highlight_end > partial_phrase_match.start_position) {
+ 				    // There is an overlap, so remove the previous phrase match
+ 				    int last_highlight_start = ((Integer) highlight_start_positions.remove(last_highlight_index)).intValue();
+ 				    highlight_end_positions.remove(last_highlight_index);
+ 				    partial_phrase_match.start_position = last_highlight_start;
+ 				}
+ 			    }
+
+ 			    highlight_start_positions.add(new Integer(partial_phrase_match.start_position));
+ 			    highlight_end_positions.add(new Integer(word_match.end_position));
+ 			}
+ 			// No, but add the partial match back into the list for next time
+ 			else {
+ 			    partial_phrase_matches.add(partial_phrase_match);
+ 			}
+ 		    }
+ 		}
+ 	    }
+ 	    else {
+ 		partial_phrase_matches.clear();
+ 	    }
+
+	    // See if this word is at the start of any of the phrases
+	    for (int p = 0; p < phrase_query_term_variants_hierarchy.size(); p++) {
+		ArrayList phrase_query_p_term_variants_list = (ArrayList) phrase_query_term_variants_hierarchy.get(p);
+		HashSet phrase_query_p_term_1_variants = (HashSet) phrase_query_p_term_variants_list.get(0);
+		if (phrase_query_p_term_1_variants.contains(word_match.word)) {
+		    // If this phrase is just one word long, we have a complete match
+		    if (phrase_query_p_term_variants_list.size() == 1) {
+			highlight_start_positions.add(new Integer(word_match.start_position));
+			highlight_end_positions.add(new Integer(word_match.end_position));
+		    }
+		    // Otherwise we have the start of a potential phrase match
+		    else {
+			partial_phrase_matches.add(new PartialPhraseMatch(word_match.start_position, p));
+		    }
+		}
+	    }
+	}
+
+	// Now add the annotation tags into the document at the correct points
+	Element content_element = this.doc.createElement(GSXML.NODE_CONTENT_ELEM);
+
+ 	int last_wrote = 0;
+	for (int i = 0; i < highlight_start_positions.size(); i++) {
+	    int highlight_start = ((Integer) highlight_start_positions.get(i)).intValue();
+	    int highlight_end = ((Integer) highlight_end_positions.get(i)).intValue();
+
+	    // Print anything before the highlight range
+	    if (last_wrote < highlight_start) {
+		String preceding_text = new String(content_characters, last_wrote, (highlight_start - last_wrote));
+		// System.err.print(preceding_text);
+		content_element.appendChild(this.doc.createTextNode(preceding_text));
+	    }
+
+	    // Print the highlight text, annotated
+	    if (highlight_end > last_wrote) {
+		String highlight_text = new String(content_characters, highlight_start, (highlight_end - highlight_start));
+		// System.err.print("|" + highlight_text + "|");
+		Element annotation_element = GSXML.createTextElement(this.doc, "annotation", highlight_text);
+		annotation_element.setAttribute("type", "query_term");
+		content_element.appendChild(annotation_element);
+		last_wrote = highlight_end;
+	    }
+	}
+
+	// Finish off any unwritten text
+	if (last_wrote < content_characters.length) {
+	    String remaining_text = new String(content_characters, last_wrote, (content_characters.length - last_wrote));
+	    // System.err.print(remaining_text);
+	    content_element.appendChild(this.doc.createTextNode(remaining_text));
+	}
+
+	return content_element;
+    }
+
+
+    static private class WordMatch
+    {
+	public String word;
+	public int start_position;
+	public int end_position;
+	public boolean preceding_word_matched;
+
+	public WordMatch(String word, int start_position, int end_position, boolean preceding_word_matched)
+	{
+	    this.word = word;
+	    this.start_position = start_position;
+	    this.end_position = end_position;
+	    this.preceding_word_matched = preceding_word_matched;
+	}
+    }
+
+
+    static private class PartialPhraseMatch
+    {
+	public int start_position;
+	public int query_phrase_number;
+	public int num_words_matched;
+
+	public PartialPhraseMatch(int start_position, int query_phrase_number)
+	{
+	    this.start_position = start_position;
+	    this.query_phrase_number = query_phrase_number;
+	    this.num_words_matched = 1;
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/GS2BrowseAction.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/GS2BrowseAction.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/GS2BrowseAction.java	(revision 13928)
@@ -0,0 +1,346 @@
+package org.greenstone.gsdl3.action;
+
+import org.greenstone.gsdl3.core.ModuleInterface;
+import org.greenstone.gsdl3.util.*;
+// XML classes
+import org.w3c.dom.Node; 
+import org.w3c.dom.NodeList; 
+import org.w3c.dom.Document; 
+import org.w3c.dom.Element; 
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Vector;
+import java.io.File;
+
+import org.apache.log4j.*;
+
+/** action for GS2 style classifier browsing */
+public class GS2BrowseAction extends Action {
+    
+    public static final String CLASSIFIER_ARG = "cl";
+
+    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.action.GS2BrowseAction.class.getName());    
+
+    /** process the request */
+    public Element process (Element message) {
+
+	// get the request - assume only one
+	Element request = (Element)GSXML.getChildByTagName(message, GSXML.REQUEST_ELEM);
+
+	// the result
+	Element result = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element response = classifierBrowse(request);
+	result.appendChild(response);
+	return result;
+    }
+    
+
+    protected Element classifierBrowse(Element request) {
+
+	Element page_response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+
+	// extract the params from the cgi-request, and check that we have a coll specified
+	Element cgi_paramList = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	HashMap params = GSXML.extractParams(cgi_paramList, false);
+	
+	String service_name = (String)params.get(GSParams.SERVICE);
+	String collection = (String)params.get(GSParams.COLLECTION);
+	if (collection == null || collection.equals("")) {
+	    logger.error("classifierBrowse, need to specify a collection!");
+	    return page_response;
+	   
+	}
+	
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	String uid = request.getAttribute(GSXML.USER_ID_ATT);
+	String to = GSPath.appendLink(collection, service_name);
+	
+	// the first part of the response is the service description 
+	// for now get this again from the service. 
+	// this should be cached somehow later on. 
+	
+	Element info_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element info_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_DESCRIBE, to, lang, uid); 
+	info_message.appendChild(info_request);
+	
+	// also get the format stuff now if there is some
+	Element format_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_FORMAT, to, lang, uid);
+	info_message.appendChild(format_request);
+	// process the requests
+
+	Element info_response = (Element) this.mr.process(info_message);
+
+	// the two responses
+	NodeList responses = info_response.getElementsByTagName(GSXML.RESPONSE_ELEM);
+	Element service_response = (Element)responses.item(0);
+	Element format_response = (Element)responses.item(1);
+
+	Element service_description = (Element)GSXML.getChildByTagName(service_response, GSXML.SERVICE_ELEM);
+	page_response.appendChild(this.doc.importNode(service_description, true));
+	
+	// if rt=d, then we are just displaying the service
+	String request_type = (String)params.get(GSParams.REQUEST_TYPE);
+	if (request_type.equals("d")) {
+	    //return the page that we have so far
+	    return page_response;
+	}
+    
+	// get the node that the user has clicked on
+	String classifier_node = (String)params.get(CLASSIFIER_ARG);
+	
+	// if the node is not defined, return the page that we have so far
+	if (classifier_node ==null || classifier_node.equals("")) {
+	    return page_response;
+	}
+	
+	// the id of the classifier is the top id of the selected node
+	String top_id = OID.getTop(classifier_node);
+	HashSet doc_meta_names = new HashSet();
+	HashSet class_meta_names = new HashSet();
+	// add in the defaults
+	doc_meta_names.add("Title");
+	class_meta_names.add("Title");
+	
+	// add the format info into the response
+	Element format_elem = (Element)GSXML.getChildByTagName(format_response, GSXML.FORMAT_ELEM);
+	if (format_elem != null) {
+	    
+	    // find the one for the classifier we are in
+	    Element this_format = GSXML.getNamedElement(format_elem, GSXML.CLASSIFIER_ELEM, GSXML.NAME_ATT, top_id);
+	    if (this_format == null) {
+		this_format = (Element)GSXML.getChildByTagName(format_elem, GSXML.DEFAULT_ELEM);
+	    }
+
+	    if (this_format != null) {
+		Element new_format = GSXML.duplicateWithNewName(this.doc, this_format, GSXML.FORMAT_ELEM, false);
+		extractMetadataNames(new_format, doc_meta_names, class_meta_names);
+		// set the format type
+		new_format.setAttribute(GSXML.TYPE_ATT, "browse");
+
+		page_response.appendChild(new_format);
+	    }
+	}
+	
+	// find out if this classifier is horizontal at top
+	Element class_list = (Element)GSXML.getChildByTagName(service_description, GSXML.CLASSIFIER_ELEM+GSXML.LIST_MODIFIER);
+	Element this_classifier = GSXML.getNamedElement(class_list, GSXML.CLASSIFIER_ELEM, GSXML.NAME_ATT, top_id);
+	boolean horizontal_at_top = false;
+	if (!this_classifier.getAttribute("horizontalAtTop").equals("")) {
+	    horizontal_at_top = true;
+	}
+	if (top_id.equals(classifier_node) && horizontal_at_top) {
+	    // we have asked for a top node - if the first list is horizontal, we will select the first element of that list
+	    // this is a hack. also it craps out if the classifier really isn't horizontalAtTop. - 
+	    classifier_node = classifier_node+".1";
+		    
+	}
+
+	// get the browse structure for the selected node
+	Element classify_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element classify_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, to, lang, uid);
+	classify_message.appendChild(classify_request);
+	    
+	//Create a parameter list to specify the required structure information
+	// for now, always get ancestors and children
+	Element param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	classify_request.appendChild(param_list);
+	Element param = this.doc.createElement(GSXML.PARAM_ELEM);
+	param_list.appendChild(param);
+	param.setAttribute(GSXML.NAME_ATT, "structure");
+	param.setAttribute(GSXML.VALUE_ATT, "ancestors");
+	param = this.doc.createElement(GSXML.PARAM_ELEM);
+	param_list.appendChild(param);
+	param.setAttribute(GSXML.NAME_ATT, "structure");
+	param.setAttribute(GSXML.VALUE_ATT, "children");
+
+	// put the classifier node into a classifier node list
+	Element classifier_list = this.doc.createElement(GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
+	Element classifier = this.doc.createElement(GSXML.CLASS_NODE_ELEM);
+	classifier.setAttribute(GSXML.NODE_ID_ATT, classifier_node);
+	classifier_list.appendChild(classifier);
+	classify_request.appendChild(classifier_list);
+	    
+	if (horizontal_at_top && !classifier_node.equals(top_id)) {
+	    // also put the top id in, to get the persistant horizontal info
+	    classifier = this.doc.createElement(GSXML.CLASS_NODE_ELEM);
+	    classifier.setAttribute(GSXML.NODE_ID_ATT, top_id);
+	    classifier_list.appendChild(classifier);
+	}
+	// process the request
+	Element classify_response = (Element)this.mr.process(classify_message);
+	String path = GSPath.appendLink(GSXML.RESPONSE_ELEM, GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
+	Element class_node_list = (Element)GSXML.getNodeByPath(classify_response, path);
+	
+	path = GSPath.appendLink(GSXML.CLASS_NODE_ELEM, GSXML.NODE_STRUCTURE_ELEM);
+	// assume that we always get back the top level CL1 node - this becomes the page_classifier node
+	path = GSPath.appendLink(path, GSXML.CLASS_NODE_ELEM);
+	Element cl_structure = (Element)GSXML.getNodeByPath(class_node_list,
+							    path);
+	if (cl_structure ==null) {
+	    logger.error("classifier structure request returned no structure");
+	    return page_response;
+	}   
+    
+	Element page_classifier = null;
+	if (horizontal_at_top && !classifier_node.equals(top_id)) {
+	    // get the info for the top node
+	    Element top_node = GSXML.getNamedElement(class_node_list, GSXML.CLASS_NODE_ELEM, GSXML.NODE_ID_ATT, top_id);
+	    if (top_node !=null) {
+		path = GSPath.appendLink(GSXML.NODE_STRUCTURE_ELEM, GSXML.CLASS_NODE_ELEM);
+		Element top_structure = (Element)GSXML.getNodeByPath(top_node, path);	    
+		// add this as the classifier elem
+		page_classifier = GSXML.duplicateWithNewName(this.doc, top_structure,  GSXML.CLASSIFIER_ELEM, true);
+		page_response.appendChild(page_classifier);
+		// now replace the child with the structure from the other request
+		Element new_classifier = (Element)GSXML.getChildByTagName(cl_structure, GSXML.CLASS_NODE_ELEM);
+		String replace_name = new_classifier.getAttribute(GSXML.NODE_ID_ATT);
+		
+		// find the appropriate child
+		Element old_classifier = GSXML.getNamedElement(page_classifier, GSXML.CLASS_NODE_ELEM, GSXML.NODE_ID_ATT, replace_name);
+		page_classifier.replaceChild(this.doc.importNode(new_classifier, true), old_classifier);
+		page_classifier.setAttribute(GSXML.NAME_ATT, top_id);
+	    } else {
+		// add the single classifier node as the page classifier 
+		page_classifier = GSXML.duplicateWithNewName(this.doc, cl_structure,  GSXML.CLASSIFIER_ELEM, true);
+		page_response.appendChild(page_classifier);
+		page_classifier.setAttribute(GSXML.NAME_ATT, top_id);
+	    }
+	    
+	} else {
+	    // add the single classifier node as the page classifier 
+	    page_classifier = GSXML.duplicateWithNewName(this.doc, cl_structure,  GSXML.CLASSIFIER_ELEM, true);
+	    page_response.appendChild(page_classifier);
+	    page_classifier.setAttribute(GSXML.NAME_ATT, top_id);
+	}
+	// get the metadata for each classifier node, 
+	// then for each document node
+
+	Element metadata_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+
+	boolean did_classifier = false;
+	boolean did_documents = false;
+	
+    
+	// if there are classifier nodes 
+	// create a metadata request for the classifier, and add it to 
+	// the the message
+	NodeList cl_nodes = page_classifier.getElementsByTagName(GSXML.CLASS_NODE_ELEM);
+	
+	if (cl_nodes.getLength() > 0) {
+	    did_classifier = true;
+	    Element cl_meta_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, to+"MetadataRetrieve", lang, uid);
+	    metadata_message.appendChild(cl_meta_request);
+	    
+	    Element new_cl_nodes_list = this.doc.createElement(GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
+	    cl_meta_request.appendChild(new_cl_nodes_list);
+	    
+	    for (int c=0; c<cl_nodes.getLength(); c++) {
+
+		Element cl = this.doc.createElement(GSXML.CLASS_NODE_ELEM);
+		cl.setAttribute(GSXML.NODE_ID_ATT, ((Element)cl_nodes.item(c)).getAttribute(GSXML.NODE_ID_ATT));
+		new_cl_nodes_list.appendChild(cl);
+	    }
+
+	    // create and add in the param list - for now get all the metadata
+	    // should be based on info sent in from the recept, and the 
+	    // format stuff
+	    Element cl_param_list  = createMetadataParamList(class_meta_names);
+	    cl_meta_request.appendChild(cl_param_list);
+	    
+	}
+
+	// if there are document nodes in the classification (happens 
+	// sometimes), create a second request for document metadata and 
+	// append to the message
+	NodeList doc_nodes = page_classifier.getElementsByTagName(GSXML.DOC_NODE_ELEM);
+	if (doc_nodes.getLength() > 0) {
+	    did_documents = true;
+	    Element doc_meta_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, GSPath.appendLink(collection, "DocumentMetadataRetrieve"), lang, uid);
+	    metadata_message.appendChild(doc_meta_request);
+	    
+	    Element doc_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	    doc_meta_request.appendChild(doc_list);
+	    
+	    for (int c=0; c<doc_nodes.getLength(); c++) {
+		
+		Element d = this.doc.createElement(GSXML.DOC_NODE_ELEM);
+		d.setAttribute(GSXML.NODE_ID_ATT, ((Element)doc_nodes.item(c)).getAttribute(GSXML.NODE_ID_ATT));
+		doc_list.appendChild(d);
+	    }
+
+	    // create and add in the param list - add all for now
+	    Element doc_param_list  = createMetadataParamList(doc_meta_names);
+	    doc_meta_request.appendChild(doc_param_list);
+
+	}
+	
+	// process the metadata requests
+	Element metadata_response = (Element)this.mr.process(metadata_message);
+        if (did_classifier) {
+	    // the classifier one will be the first response
+	    // add the metadata lists for each node back into the 
+	    // page_classifier nodes
+	    path = GSPath.appendLink(GSXML.RESPONSE_ELEM, 
+				   GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
+            Node pathNode = GSXML.getNodeByPath(metadata_response, path);
+            if (pathNode ==null){
+	        return page_response; 
+	    }
+	    NodeList meta_response_cls = pathNode.getChildNodes();
+	    for (int i = 0; i < cl_nodes.getLength(); i++) {
+		GSXML.mergeMetadataLists(cl_nodes.item(i), meta_response_cls.item(i));
+		
+	    }
+	}
+
+	if (did_documents) {
+	    NodeList meta_response_docs = null;
+	    if (!did_classifier) {
+		// its the first response
+		path = GSPath.appendLink(GSXML.RESPONSE_ELEM, 
+					 GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+		Node pathNode = GSXML.getNodeByPath(metadata_response, path);
+		if (pathNode ==null){
+		    return page_response;
+                 }
+
+		meta_response_docs = pathNode.getChildNodes();
+		
+
+	    } else { // its the second response
+                Node nodes = GSXML.getChildByTagName(metadata_response.getElementsByTagName(GSXML.RESPONSE_ELEM).item(1), GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+		if (nodes ==null){
+		    return page_response;
+                 }
+		meta_response_docs = nodes.getChildNodes();
+	    }
+	    
+	    for (int i = 0; i < doc_nodes.getLength(); i++) {
+		GSXML.mergeMetadataLists(doc_nodes.item(i), meta_response_docs.item(i));
+	    }
+	}
+	    
+
+	logger.debug("(GS2BrowseAction) Page:\n" + this.converter.getPrettyString(page_response));
+	return page_response;
+    }
+
+   
+    protected void extractMetadataNames(Element new_format, HashSet doc_meta_names, HashSet class_meta_names) {
+
+	NodeList templates = new_format.getElementsByTagName("gsf:template");
+	for (int i=0; i<templates.getLength(); i++) {
+	    Element template = (Element)templates.item(i);
+	    String match = template.getAttribute("match");
+	    if (match.equals("documentNode")) {
+		extractMetadataNames(template, doc_meta_names);
+	    } else if (match.equals("classifierNode")) {
+		extractMetadataNames(template, class_meta_names);
+	    }
+	}
+    }
+
+}
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/GeneralAction.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/GeneralAction.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/GeneralAction.java	(revision 13928)
@@ -0,0 +1,108 @@
+package org.greenstone.gsdl3.action;
+
+import org.greenstone.gsdl3.core.ModuleInterface;
+import org.greenstone.gsdl3.util.*;
+// XML classes
+import org.w3c.dom.Node; 
+import org.w3c.dom.NodeList; 
+import org.w3c.dom.Document; 
+import org.w3c.dom.Element; 
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Iterator;
+import java.io.File;
+
+
+public class GeneralAction extends Action {
+    
+    /** process a request */
+    public Element process (Element message) {
+
+	// the result
+	Element result = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element page_response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	result.appendChild(page_response);
+
+	// assume only one request
+	Element request = (Element)GSXML.getChildByTagName(message, GSXML.REQUEST_ELEM);
+
+	// get the param list
+	Element cgi_param_list = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	HashMap params = GSXML.extractParams(cgi_param_list, false);
+	String service_name = (String) params.get(GSParams.SERVICE);
+	String cluster_name = (String) params.get(GSParams.CLUSTER);
+	String response_only_p = (String)params.get(GSParams.RESPONSE_ONLY);
+	boolean response_only = false;
+	if (response_only_p!=null) {
+	    response_only = (response_only_p.equals("1")?true:false);
+	}
+	String request_type = (String) params.get(GSParams.REQUEST_TYPE);
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	String uid = request.getAttribute(GSXML.USER_ID_ATT);
+	// what is carried out depends on the request_type
+	// if rt=d, then a describe request is done,
+	// is rt=r, a request and then a describe request is done
+	// if rt=s, a status request is done.
+
+	// if ro=1, then this calls for a process only page - we do the request
+	// (rt should be r or s) and just give the response straight back
+	// without any page processing
+
+
+	// where to send requests
+	String to;
+	if (cluster_name != null) {
+	    to = GSPath.appendLink(cluster_name, service_name);
+	} else {
+	    to = service_name;
+	}
+
+	if (request_type.equals("r")) {
+	    //do the request
+	    
+	    Element mr_query_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	    Element mr_query_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, to, lang, uid);
+	    
+	    mr_query_message.appendChild(mr_query_request);
+	    
+	    Element param_list = null;
+	    // add in the service params - except the ones only used by the action
+	    HashMap service_params = (HashMap)params.get("s1");
+	    if (service_params != null) { 
+		param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+		GSXML.addParametersToList(this.doc, param_list, service_params);
+		mr_query_request.appendChild(param_list);
+	    }
+	    
+	    Element mr_query_response = (Element)this.mr.process(mr_query_message);
+	    Element result_response = (Element)GSXML.getChildByTagName(mr_query_response, GSXML.RESPONSE_ELEM);
+	    
+	    if (response_only) {
+		// just send the reponse as is
+		return result_response;
+	    }
+	    
+	    // else append the contents of the response to the page 
+	    GSXML.copyAllChildren(page_response, result_response);
+	}
+	
+
+	// another part of the page is the service description
+
+	// request the service info for the selected service - should be cached
+	Element mr_info_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element mr_info_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_DESCRIBE, to, lang, uid);
+	mr_info_message.appendChild(mr_info_request);
+	Element mr_info_response = (Element) this.mr.process(mr_info_message);
+
+	String path = GSXML.RESPONSE_ELEM;
+	path = GSPath.appendLink(path, GSXML.SERVICE_ELEM);
+	Element description = (Element)this.doc.importNode(GSXML.getNodeByPath(mr_info_response, path), true);
+
+	page_response.appendChild(description);
+
+	return result;
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/NoCollQueryAction.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/NoCollQueryAction.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/NoCollQueryAction.java	(revision 13928)
@@ -0,0 +1,219 @@
+package org.greenstone.gsdl3.action;
+
+import org.greenstone.gsdl3.core.ModuleInterface;
+import org.greenstone.gsdl3.util.*;
+// XML classes
+import org.w3c.dom.Node; 
+import org.w3c.dom.NodeList; 
+import org.w3c.dom.Text; 
+import org.w3c.dom.Document; 
+import org.w3c.dom.Element; 
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Vector;
+import java.util.Map;
+import java.util.Iterator;
+import java.io.File;
+
+import org.apache.log4j.*;
+
+/** action class for queries 
+ * this is used when querying isn't collection specific, but it occurs across all collections in the site. The service description is assumed to be known by the xslt so we dont ask for it. we just pass all the service params to the TextQuery service of all the collections */
+public class NoCollQueryAction extends Action {
+    
+    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.action.NoCollQueryAction.class.getName());
+    /** process - processes a request.
+     */ 
+    public Element process (Element message) {
+
+	// get the request - assume there is only one
+	Element request = (Element)GSXML.getChildByTagName(message, GSXML.REQUEST_ELEM);
+
+	// create the return message
+	Element result = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	// for now we only have one type of query - subaction not used
+	Element response = basicQuery(request);
+	result.appendChild(this.doc.importNode(response, true));
+	return result;
+    }
+    
+    /** a generic query handler 
+     * this gets the service description, does the query (just passes all teh 
+     * params to the service, then gets the titles for any results 
+     */
+    protected Element basicQuery(Element request) {
+	
+	// the result
+	Element page_response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	
+	// extract the params from the cgi-request, and check that we have a coll specified
+	Element cgi_param_list = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	HashMap params = GSXML.extractParams(cgi_param_list, false);
+	
+	String request_type = (String)params.get(GSParams.REQUEST_TYPE);
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	String uid = request.getAttribute(GSXML.USER_ID_ATT);
+	if (request_type.equals("d")) {
+	    // display the query page
+	    // the only info we need to return is the collection list cos the xslt does teh rest
+	    
+	    Element coll_list = getCollectionList(lang, uid);
+	    page_response.appendChild(this.doc.importNode(coll_list, true));
+	    return page_response;
+	    
+	}
+	
+	// else we have a query
+	String service_name = (String)params.get(GSParams.SERVICE);
+	if (service_name == null || service_name.equals("")) {
+	    service_name = "TextQuery";
+	}
+  	String query_coll_list = (String)params.get(GSParams.COLLECTION);
+	
+  	if (query_coll_list == null || query_coll_list.equals("")) {
+  	    logger.error("no collections were specified!");
+  	    Element coll_list = getCollectionList(lang, uid);
+  	    page_response.appendChild(this.doc.importNode(coll_list, true));
+  	    return page_response; 
+  	}
+
+	// service paramList
+	HashMap service_params = (HashMap)params.get("s1");
+	if (service_params == null) { // no query
+	    return page_response;
+	}
+	Element query_param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	GSXML.addParametersToList(this.doc, query_param_list, service_params);
+	
+	// we will do a query for each coll
+	String [] colls = query_coll_list.split(",");
+	
+	Element mr_query_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	
+	for (int i=0; i< colls.length; i++) {
+	    String to = GSPath.appendLink(colls[i], service_name);
+	    Element mr_query_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, to, lang, uid);
+	    mr_query_message.appendChild(mr_query_request);
+	    mr_query_request.appendChild(query_param_list.cloneNode(true));
+	    
+	}
+	
+	// do the query
+       	Element mr_query_response = (Element)this.mr.process(mr_query_message);
+
+	
+	// get the Title metadata for each node - need Node title and root title
+	Element mr_meta_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	NodeList responses = mr_query_response.getElementsByTagName(GSXML.RESPONSE_ELEM);
+	for (int j=0; j<responses.getLength(); j++) {
+	    Element document_list = (Element)GSXML.getChildByTagName((Element)responses.item(j), GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	    if (document_list != null) {
+		String coll_name = extractCollName(((Element)responses.item(j)).getAttribute(GSXML.FROM_ATT));
+		String path = GSPath.appendLink(coll_name, "DocumentMetadataRetrieve");
+		Element mr_meta_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, path, lang, uid);
+		mr_meta_message.appendChild(mr_meta_request);
+		mr_meta_request.appendChild(this.doc.importNode(document_list, true));
+		// metadata params 
+		Element param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+		Element param = GSXML.createParameter(this.doc, "metadata", "Title");
+		param_list.appendChild(param);
+		param = GSXML.createParameter(this.doc, "metadata", "root_Title");
+		param_list.appendChild(param);
+		mr_meta_request.appendChild(param_list);
+		
+	    }
+	}
+	
+	// do the request
+	Element mr_meta_response = (Element)this.mr.process(mr_meta_message);
+
+	// the result 
+	Element result_doc_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	page_response.appendChild(result_doc_list);
+
+	responses = mr_meta_response.getElementsByTagName(GSXML.RESPONSE_ELEM);
+	for (int j=0; j<responses.getLength(); j++) {
+	    Element document_list = (Element)GSXML.getChildByTagName((Element)responses.item(j), GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	    String coll_name = extractCollName(((Element)responses.item(j)).getAttribute(GSXML.FROM_ATT));
+	    
+	    mergeDocLists(result_doc_list, document_list, coll_name );
+	}
+	
+	
+	return page_response;
+    }
+
+    protected String extractCollName(String path) {
+	return GSPath.removeLastLink(path);
+    }
+
+    protected void mergeDocLists(Element result_list, Element from_list, String collection) {
+
+	Document owner = result_list.getOwnerDocument();
+	Node child = from_list.getFirstChild();
+	while (child != null) {
+	    ((Element)child).setAttribute("collection", collection);
+	    result_list.appendChild(owner.importNode(child, true));
+	    child = child.getNextSibling();
+	}
+	
+    }
+
+
+    protected Element getCollectionList(String lang, String uid) {
+	
+	// first, get the message router info
+	Element coll_list_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element coll_list_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_DESCRIBE, "", lang, uid);
+	coll_list_message.appendChild(coll_list_request);
+	Element coll_list_response = (Element)this.mr.process(coll_list_message);
+	if (coll_list_response==null) {
+	    logger.error("couldn't query the message router!");
+	    return null;
+	}
+	
+	// second, get the display info for each collection 
+	NodeList colls = coll_list_response.getElementsByTagName(GSXML.COLLECTION_ELEM);
+
+	Element coll_param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	Element param = GSXML.createParameter(this.doc, GSXML.SUBSET_PARAM, GSXML.DISPLAY_TEXT_ELEM+GSXML.LIST_MODIFIER); 
+	coll_param_list.appendChild(param);
+	// we will send all the requests in a single message
+	Element metadata_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	for (int i=0; i<colls.getLength(); i++) {
+	    Element c = (Element)colls.item(i);
+	    String name = c.getAttribute(GSXML.NAME_ATT);	    
+	    
+	    Element metadata_request = GSXML.createBasicRequest(this.doc,  GSXML.REQUEST_TYPE_DESCRIBE, name, lang, uid);
+	    metadata_request.appendChild(coll_param_list.cloneNode(true));
+	    metadata_message.appendChild(metadata_request);
+	}
+	
+	Element metadata_response = (Element)this.mr.process(metadata_message);
+	
+	NodeList coll_responses = metadata_response.getElementsByTagName(GSXML.RESPONSE_ELEM);
+	// check that have same number of responses as collections
+	if (colls.getLength() != coll_responses.getLength()) {
+	    logger.error("didn't get a response for each collection - somethings gone wrong!");
+	    // for now, dont use the metadata
+	} else {
+	    for (int i=0; i<colls.getLength(); i++) {
+		Element c1 = (Element)colls.item(i);
+		Element c2 = (Element)coll_responses.item(i);
+		if (c1.getAttribute(GSXML.NAME_ATT).equals(c2.getAttribute(GSXML.FROM_ATT))) {
+		    //add the collection data into the original response
+		    GSXML.mergeElements(c1, (Element)GSXML.getChildByTagName(c2, GSXML.COLLECTION_ELEM));
+		} else {
+		    logger.error("response does not correspond to request!");
+		} 
+		
+	    }
+	}
+
+	String path = GSPath.appendLink(GSXML.RESPONSE_ELEM, GSXML.COLLECTION_ELEM+GSXML.LIST_MODIFIER);
+	Element response = (Element) GSXML.getNodeByPath(coll_list_response, path);
+	return response;
+
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/PageAction.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/PageAction.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/PageAction.java	(revision 13928)
@@ -0,0 +1,220 @@
+package org.greenstone.gsdl3.action;
+
+import org.greenstone.gsdl3.core.ModuleInterface;
+import org.greenstone.gsdl3.util.*;
+// XML classes
+import org.w3c.dom.Node; 
+import org.w3c.dom.NodeList; 
+import org.w3c.dom.Document; 
+import org.w3c.dom.Element;
+
+import java.util.HashMap;
+import java.io.File;
+
+import org.apache.log4j.*;
+
+public class PageAction extends Action {
+   
+     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.action.PageAction.class.getName());
+
+    public static final String HOME_PAGE = "home";
+    public static final String ABOUT_PAGE = "about";
+    public static final String PREFS_PAGE = "pref";
+    public Element process (Element message) {
+	
+	Element request = (Element) GSXML.getChildByTagName(message, GSXML.REQUEST_ELEM);
+	// the page name is the subaction
+	String page_name = request.getAttribute(GSXML.SUBACTION_ATT);
+	if (page_name.equals("")) { // if no page specified, assume home page
+	    page_name = HOME_PAGE;
+	}
+	Element result = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element response;
+	if (page_name.equals(HOME_PAGE)) {
+	    response = homePage(request);
+	} else if (page_name.equals(ABOUT_PAGE)) {
+	    response = aboutPage(request);
+//  	} else if (page_name.equals(PREFS_PAGE)) {
+//  	    response = prefsPage(request);
+	} else { // unknown page
+	    
+	    logger.error("unknown page specified!");
+	    response =  unknownPage(request);
+	}
+	
+	result.appendChild(this.doc.importNode(response, true));
+	logger.debug("page action result: "+this.converter.getPrettyString(result));
+	return result;
+    }
+
+
+    protected Element homePage(Element request) {
+	
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	String uid = request.getAttribute(GSXML.USER_ID_ATT);
+	// first, get the message router info
+	Element info_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element coll_list_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_DESCRIBE, "", lang, uid);
+	info_message.appendChild(coll_list_request);
+	Element info_response_message = (Element)this.mr.process(info_message);
+	if (info_response_message==null) {
+	    logger.error(" couldn't query the message router!");
+	    return null;
+	}
+	Element info_response = (Element)GSXML.getChildByTagName(info_response_message, GSXML.RESPONSE_ELEM);
+	if (info_response==null) {
+	    logger.error("couldn't query the message router!");
+	    return null;
+	}
+	    
+	// second, get the metadata for each collection - we only want specific
+	// elements but for now, we'll just get it all
+	Element collection_list = (Element)GSXML.getChildByTagName(info_response, GSXML.COLLECTION_ELEM+GSXML.LIST_MODIFIER);
+	logger.info(GSXML.xmlNodeToString(collection_list));
+        if (collection_list != null) {
+	    NodeList colls = GSXML.getChildrenByTagName(collection_list, GSXML.COLLECTION_ELEM);
+	    if (colls.getLength()>0) {
+		sendMultipleRequests(colls, null, GSXML.REQUEST_TYPE_DESCRIBE, lang, uid);
+	    }
+	}
+
+	// get metadata for any services
+	Element service_list = (Element)GSXML.getChildByTagName(info_response, GSXML.SERVICE_ELEM+GSXML.LIST_MODIFIER);
+	if (service_list != null) {
+	    NodeList services = GSXML.getChildrenByTagName(service_list, GSXML.SERVICE_ELEM);
+	    if (services.getLength() > 0) {
+		sendMultipleRequests(services, null, GSXML.REQUEST_TYPE_DESCRIBE, lang, uid);
+	    }
+	}
+
+	// get metadata for service clusters
+	Element cluster_list = (Element)GSXML.getChildByTagName(info_response, GSXML.CLUSTER_ELEM+GSXML.LIST_MODIFIER);
+	if (cluster_list != null) {
+	    NodeList clusters = GSXML.getChildrenByTagName(cluster_list, GSXML.CLUSTER_ELEM);
+	    if (clusters.getLength() > 0) {
+		sendMultipleRequests(clusters, null, GSXML.REQUEST_TYPE_DESCRIBE, lang, uid);
+		
+	    }
+	}
+	
+	// all the components have been merged into info_response
+	return info_response;
+	
+    } // homePage
+
+    protected Element aboutPage(Element request) {
+
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	String uid = request.getAttribute(GSXML.USER_ID_ATT);
+	// extract the params from the cgi-request, 
+	Element cgi_paramList = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	HashMap params = GSXML.extractParams(cgi_paramList, false);
+	
+	String coll_name = (String)params.get(GSParams.COLLECTION);
+	if (coll_name == null || coll_name.equals("")) {
+	    logger.error("about page requested with no collection or cluster specified!");
+	    // return an empty response
+	    return this.doc.createElement(GSXML.RESPONSE_ELEM);
+	}
+	
+	// get the collection or cluster description
+	Element coll_about_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	
+	Element coll_about_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_DESCRIBE,  coll_name, lang, uid);
+	coll_about_message.appendChild(coll_about_request);
+	
+	Element coll_about_response = (Element)this.mr.process(coll_about_message);
+
+	if (coll_about_response == null) {
+	    return null;
+	}
+	
+	// second, get the info for each service - we only want display items 
+	// but for now, we'll just get it all
+	NodeList services = coll_about_response.getElementsByTagName(GSXML.SERVICE_ELEM);
+	if (services.getLength() > 0) {
+	    sendMultipleRequests(services, coll_name, GSXML.REQUEST_TYPE_DESCRIBE, lang, uid);
+	}
+	
+	Element response = (Element) GSXML.getChildByTagName(coll_about_response, GSXML.RESPONSE_ELEM);
+	return response;
+    }
+
+//      protected Element prefsPage(Element request) {
+
+//  	return null;
+//      }
+
+    /** if we dont know the page type, use this method */
+    protected Element unknownPage(Element request) {
+	
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	String uid = request.getAttribute(GSXML.USER_ID_ATT);
+	String page_name = request.getAttribute(GSXML.SUBACTION_ATT);
+
+	// extract the params from the cgi-request, 
+	Element cgi_paramList = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	HashMap params = GSXML.extractParams(cgi_paramList, false);
+	
+	String coll_name = (String)params.get(GSParams.COLLECTION);
+	if (coll_name == null || coll_name.equals("")) {
+	    // just return an empty response
+	    return this.doc.createElement(GSXML.RESPONSE_ELEM);
+	}
+	
+	// else get the coll description - actually this is the same as for the about page - should we merge these two methods??
+	
+	// if there is a service specified should we get the service description instead??
+	// get the collection or cluster description
+	Element coll_about_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	
+	Element coll_about_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_DESCRIBE,  coll_name, lang, uid);
+	coll_about_message.appendChild(coll_about_request);
+	
+	Element coll_about_response = (Element)this.mr.process(coll_about_message);
+
+	Element response = (Element) GSXML.getChildByTagName(coll_about_response, GSXML.RESPONSE_ELEM);
+	return response;
+	
+    }
+
+
+    protected boolean sendMultipleRequests(NodeList items, String path_prefix, String request_type, String lang, String uid) {
+
+	// we will send all the requests in a single message
+	Element message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	for (int i=0; i<items.getLength(); i++) {
+	    Element c = (Element)items.item(i);
+	    String path = c.getAttribute(GSXML.NAME_ATT);	    
+	    if (path_prefix != null) {
+		path = GSPath.appendLink(path_prefix, path);
+	    }
+	    Element request = GSXML.createBasicRequest(this.doc, request_type, path, lang, uid);
+	    message.appendChild(request);
+	}
+	
+	Element response_message = (Element)this.mr.process(message);
+	    
+	NodeList responses = response_message.getElementsByTagName(GSXML.RESPONSE_ELEM);
+	// check that have same number of responses as requests
+	if (items.getLength() != responses.getLength()) {
+	    logger.error("didn't get a response for each request - somethings gone wrong!");
+	    return false;
+	} 
+	
+	for (int i=0; i<items.getLength(); i++) {
+	    Element c1 = (Element)items.item(i);
+	    Element c2 = (Element)GSXML.getChildByTagName((Element)responses.item(i), c1.getTagName());
+    	    if (c1.getAttribute(GSXML.NAME_ATT).endsWith(c2.getAttribute(GSXML.NAME_ATT))) {
+		//add the new data into the original element
+		GSXML.mergeElements(c1, c2);
+	    } else {
+		logger.error(" response does not correspond to request!");
+	    } 
+	    
+	}
+	
+	return true;
+    
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/ProcessAction.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/ProcessAction.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/ProcessAction.java	(revision 13928)
@@ -0,0 +1,137 @@
+package org.greenstone.gsdl3.action;
+
+import org.greenstone.gsdl3.core.ModuleInterface;
+import org.greenstone.gsdl3.util.*;
+// XML classes
+import org.w3c.dom.Node; 
+import org.w3c.dom.NodeList; 
+import org.w3c.dom.Document; 
+import org.w3c.dom.Element; 
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Iterator;
+import java.io.File;
+
+public class ProcessAction extends Action {
+    
+    /** process a request */
+    public Element process (Element message) {
+
+	// the result
+	Element result = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element page_response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	result.appendChild(page_response);
+
+	// assume only one request
+	Element request = (Element)GSXML.getChildByTagName(message, GSXML.REQUEST_ELEM);
+
+	// get the param list
+	Element cgi_param_list = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	HashMap params = GSXML.extractParams(cgi_param_list, false);
+	String service_name = (String) params.get(GSParams.SERVICE);
+	String cluster_name = (String) params.get(GSParams.CLUSTER);
+	String response_only_p = (String)params.get(GSParams.RESPONSE_ONLY);
+	boolean response_only = false;
+	if (response_only_p!=null) {
+	    response_only = (response_only_p.equals("1")?true:false);
+	}
+	String request_type = (String) params.get(GSParams.REQUEST_TYPE);
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	String uid = request.getAttribute(GSXML.USER_ID_ATT);
+	// what is carried out depends on the request_type
+	// if rt=d, then a describe request is done,
+	// is rt=r, a request and then a describe request is done
+	// if rt=s, a status request is done.
+
+	// if ro=1, then this calls for a process only page - we do the request
+	// (rt should be r or s) and just give the response straight back
+	// without any page processing
+
+
+	// where to send requests
+	String to;
+	if (cluster_name != null) {
+	    
+	    to = GSPath.appendLink(cluster_name, service_name);
+	} else {
+	    to = service_name;
+	}
+
+	if (!request_type.equals("d")) {
+	    // if rt=s or rt=r, do the request
+	    
+	    Element mr_query_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	    String request_type_att;
+	    Element param_list = null;
+	    if (request_type.equals("s")) { // status
+		request_type_att = GSXML.REQUEST_TYPE_STATUS;
+		param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+		Element param = this.doc.createElement(GSXML.PARAM_ELEM);
+		param.setAttribute(GSXML.NAME_ATT, GSParams.PROCESS_ID);
+		param.setAttribute(GSXML.VALUE_ATT, (String)params.get(GSParams.PROCESS_ID));
+		param_list.appendChild(param);
+	    } else {
+		request_type_att = GSXML.REQUEST_TYPE_PROCESS;
+		// add in the service params - except the ones only used by the action
+		HashMap service_params = (HashMap)params.get("s1");
+		if (service_params != null) { 
+		    param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+		    GSXML.addParametersToList(this.doc, param_list, service_params);
+		}
+		
+	    }
+	    Element mr_query_request = GSXML.createBasicRequest(this.doc, request_type_att, to, lang, uid);
+	    if (param_list != null) {
+		mr_query_request.appendChild(param_list);
+	    }
+	    mr_query_message.appendChild(mr_query_request);
+	    
+	    Element mr_query_response = (Element)this.mr.process(mr_query_message);
+	    Element result_response = (Element)GSXML.getChildByTagName(mr_query_response, GSXML.RESPONSE_ELEM);
+	    
+	    if (response_only) {
+		// just send the reponse as is
+		return result_response;
+	    }
+	    
+	    // else append the contents of the response to the page - just the status elem for now
+	    Element status = (Element)GSXML.getChildByTagName(result_response, GSXML.STATUS_ELEM);
+	    page_response.appendChild(this.doc.importNode(status, true));
+	}
+	
+
+	// another part of the page is the service description
+
+	// request the service info for the selected service - should be cached
+	Element mr_info_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element mr_info_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_DESCRIBE, to, lang, uid);
+	mr_info_message.appendChild(mr_info_request);
+	Element mr_info_response = (Element) this.mr.process(mr_info_message);
+
+	String path = GSXML.RESPONSE_ELEM;
+	path = GSPath.appendLink(path, GSXML.SERVICE_ELEM);
+	Element description = (Element)this.doc.importNode(GSXML.getNodeByPath(mr_info_response, path), true);
+
+	page_response.appendChild(description);
+
+	return result;
+    }
+
+    protected Element getServiceParamList(Element cgi_param_list) {
+
+	Element new_param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	Element param;
+	NodeList cgi_params = cgi_param_list.getChildNodes();
+	for (int i=0; i<cgi_params.getLength(); i++) {
+	    Element p = (Element) cgi_params.item(i);
+	    String name = p.getAttribute(GSXML.NAME_ATT);
+	    if (name.equals(GSParams.SERVICE) || name.equals(GSParams.REQUEST_TYPE) || name.equals(GSParams.CLUSTER)) {
+		continue;
+	    }
+	    // else add it in to the list
+	    new_param_list.appendChild(this.doc.importNode(p, true));
+	}
+	return new_param_list;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/QueryAction.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/QueryAction.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/QueryAction.java	(revision 13928)
@@ -0,0 +1,267 @@
+package org.greenstone.gsdl3.action;
+
+import org.greenstone.gsdl3.core.ModuleInterface;
+import org.greenstone.gsdl3.util.*;
+// XML classes
+import org.w3c.dom.Node; 
+import org.w3c.dom.NodeList; 
+import org.w3c.dom.Text; 
+import org.w3c.dom.Document; 
+import org.w3c.dom.Element; 
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Vector;
+import java.util.Map;
+import java.util.Iterator;
+import java.io.File;
+
+import org.apache.log4j.*;
+
+/** action class for queries */
+public class QueryAction extends Action {
+
+
+     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.action.QueryAction.class.getName());
+    
+    /** process - processes a request.
+     */ 
+    public Element process (Element message) {
+
+	// get the request - assume there is only one
+	Element request = (Element)GSXML.getChildByTagName(message, GSXML.REQUEST_ELEM);
+
+	// create the return message
+	Element result = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element response = basicQuery(request);
+	result.appendChild(this.doc.importNode(response, true));
+	return result;
+    }
+    
+    /** a generic query handler 
+     * this gets the service description, does the query (just passes all the 
+     * params to the service, then gets the titles for any results 
+     */
+    protected Element basicQuery(Element request) {
+	
+	// the result
+	Element page_response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	
+	// extract the params from the cgi-request, and check that we have a coll specified
+	Element cgi_param_list = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	HashMap params = GSXML.extractParams(cgi_param_list, false);
+	
+	String request_type = (String)params.get(GSParams.REQUEST_TYPE);
+	String service_name = (String)params.get(GSParams.SERVICE);
+	String collection = (String)params.get(GSParams.COLLECTION);
+
+	// collection may be null or empty when we are doing cross coll services
+	if (collection == null || collection.equals("")) {
+	    collection = null;
+	}
+	
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	String uid = request.getAttribute(GSXML.USER_ID_ATT);
+	String to = service_name;
+	if (collection != null) {
+	    to = GSPath.prependLink(to, collection);
+	}
+	
+	if (request_type.indexOf("d")!=-1) {
+	    // we have been asked for the service description
+	    Element mr_info_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	    Element mr_info_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_DESCRIBE,  to, lang, uid);
+	    mr_info_message.appendChild(mr_info_request);
+	    
+	    // process the message
+	    Element mr_info_response = (Element) this.mr.process(mr_info_message);
+	    // the response
+	    Element service_response = (Element)GSXML.getChildByTagName(mr_info_response, GSXML.RESPONSE_ELEM);
+	    
+	    Element service_description = (Element)this.doc.importNode(GSXML.getChildByTagName(service_response, GSXML.SERVICE_ELEM), true);
+	    page_response.appendChild(service_description);
+	}
+	
+	if (request_type.indexOf("r") == -1) {
+	    // just a display request, no actual processing to do
+	    return page_response;
+	}
+	
+	// check that we have some service params
+	HashMap service_params = (HashMap)params.get("s1");
+	if (service_params == null) { // no query
+	    return page_response;
+	}
+
+	// create the query request
+	Element mr_query_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element mr_query_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, to, lang, uid);
+	mr_query_message.appendChild(mr_query_request);
+	
+	Element query_param_list = this.doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
+	GSXML.addParametersToList(this.doc, query_param_list, service_params);
+	mr_query_request.appendChild(query_param_list);
+	
+	// also get the format stuff now if there is some
+	Element format_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_FORMAT, to, lang, uid);
+	mr_query_message.appendChild(format_request);
+
+	// do the query
+       	Element mr_query_response = (Element)this.mr.process(mr_query_message);
+
+	// check for errors
+	if (processErrorElements(mr_query_response, page_response)) {
+	    return page_response;
+	}
+	
+	NodeList responses = mr_query_response.getElementsByTagName(GSXML.RESPONSE_ELEM);
+	Element query_response = (Element) responses.item(0);
+	Element format_response = (Element) responses.item(1);
+	
+	Element query_result_metadata_list = (Element) GSXML.getChildByTagName(query_response, GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
+	if (query_result_metadata_list == null) {
+	    logger.error("No query result metadata.\n");
+	} else { // add it into the page response
+	    page_response.appendChild(this.doc.importNode(query_result_metadata_list, true)); 
+	}
+	
+	Element query_term_info_list = (Element) GSXML.getChildByTagName(query_response, GSXML.TERM_ELEM+GSXML.LIST_MODIFIER);
+	if (query_term_info_list == null) {
+	    logger.error("No query term information.\n");
+	} else { // add it into the page response
+	    page_response.appendChild(this.doc.importNode(query_term_info_list, true));
+	}
+	
+	// check that there are some documents - for now check the list, but later should use a numdocs metadata elem	
+	Element document_list = (Element)GSXML.getChildByTagName(query_response, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	// documentList not present if no docs found
+	if (document_list == null) {
+	    // add in a dummy doc node list - used by the display. need to think about this
+	    page_response.appendChild(this.doc.createElement(GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER));
+	    return page_response;
+	}
+
+	// now we check to see if there is metadata already - some search services return predefined metadata. if there is some, don't do a metadata request
+	NodeList doc_metadata = document_list.getElementsByTagName(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
+	if (doc_metadata.getLength()>0) {
+	    logger.error("have already found metadata!");
+	    // append the doc list to the result
+	    page_response.appendChild(this.doc.importNode(document_list, true));
+	    return page_response;
+	}
+	
+	// get the metadata elements needed from the format statement if any
+	HashSet metadata_names = new HashSet();
+	metadata_names.add("Title");
+	// add in the format info to the stylesheet if there is any
+	Element format_elem = (Element)GSXML.getChildByTagName(format_response, GSXML.FORMAT_ELEM);
+	if (format_elem != null) {
+	    // set the format type
+	    format_elem.setAttribute(GSXML.TYPE_ATT, "search");
+	    // for now just add to the response
+	    page_response.appendChild(this.doc.importNode(format_elem, true));
+	    extractMetadataNames(format_elem, metadata_names);
+	} 
+	
+	// paging of the results is done here - we filter the list to remove unwanted entries before retrieving metadata
+	Element filtered_doc_list = filterDocList(params, service_params, document_list);
+	
+	// do the metadata request on the filtered list
+	Element mr_metadata_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	to = "DocumentMetadataRetrieve";
+	if (collection != null) {
+	    to = GSPath.prependLink(to, collection);
+	}
+	Element mr_metadata_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, to, lang, uid);
+	mr_metadata_message.appendChild(mr_metadata_request);
+	
+	// just get all for now - the receptionist should perhaps pass in some
+	// metadata that it wants, and QueryAction should look through the format stuff to see if there is any other?
+	
+	Element dm_param_list  = createMetadataParamList(metadata_names);
+	
+	mr_metadata_request.appendChild(dm_param_list);
+	
+	// add in the doc node list too
+	mr_metadata_request.appendChild(filtered_doc_list);
+
+	Element mr_metadata_response = (Element) this.mr.process(mr_metadata_message);	
+	// check for errors
+	processErrorElements(mr_metadata_response, page_response);
+	
+	Element metadata_response = (Element) GSXML.getChildByTagName(mr_metadata_response, GSXML.RESPONSE_ELEM);
+
+	Element query_result_document_list = (Element) GSXML.getChildByTagName(metadata_response, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	
+	if (query_result_document_list != null) {
+	    page_response.appendChild(this.doc.importNode(query_result_document_list, true));
+	}
+	
+	logger.debug("Query page:\n" + this.converter.getPrettyString(page_response));
+	return page_response;
+    }
+
+    /** this filters out some of the doc results for result paging */
+    protected Element filterDocList(HashMap params, HashMap service_params, Element orig_doc_list) {
+	
+	// check the hits_per_page param - is it a service param??
+	String hits_pp = (String) service_params.get("hitsPerPage");
+	if (hits_pp != null) {
+	    // the service is doing the paging, so we want to display all of the returned docs
+	    return (Element)this.doc.importNode(orig_doc_list, true);
+	}
+	
+	hits_pp = (String)params.get("hitsPerPage");
+	int hits = 20;
+	if (hits_pp != null && !hits_pp.equals("")) {
+	    try {
+		hits = Integer.parseInt(hits_pp);
+	    } catch (Exception e) {
+		hits=20;
+	    }
+	}
+
+	if (hits == -1) { // all
+	    return (Element)this.doc.importNode(orig_doc_list, true);
+	}
+	NodeList result_docs = orig_doc_list.getElementsByTagName(GSXML.DOC_NODE_ELEM);
+	
+	int num_docs = result_docs.getLength();
+	if (num_docs <= hits) {
+	    // too few docs to do paging
+	    return (Element)this.doc.importNode(orig_doc_list, true);
+	}
+
+	// now we need our own doc list
+	Element result_list = this.doc.createElement(GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER);
+	String start_p = (String)params.get("startPage");
+	int start = 1;
+	if (start_p != null && !start_p.equals("")) {
+	    try {
+		start = Integer.parseInt(start_p);
+	    } catch (Exception e) {
+		start = 1;
+	    }
+	}
+
+	int start_from = (start-1)*hits;
+	int end_at = (start*hits)-1;
+
+	if (start_from > num_docs) {
+	    // something has gone wrong
+	    return result_list;
+	}
+	
+	if (end_at > num_docs) {
+	    end_at = num_docs-1;
+	}
+
+	// now we finally have the docs numbers to use
+	for (int i=start_from; i<=end_at; i++) {
+	    result_list.appendChild(this.doc.importNode(result_docs.item(i), true));
+	}
+
+	return result_list;
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/SystemAction.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/SystemAction.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/SystemAction.java	(revision 13928)
@@ -0,0 +1,86 @@
+package org.greenstone.gsdl3.action;
+
+import org.greenstone.gsdl3.core.ModuleInterface;
+import org.greenstone.gsdl3.util.*;
+
+// XML classes
+import org.w3c.dom.Node; 
+import org.w3c.dom.Element; 
+import org.w3c.dom.Document; 
+
+// other java stuff
+import java.io.File;
+import java.util.HashMap;
+
+import org.apache.log4j.*;
+
+public class SystemAction extends Action {
+    
+      static Logger logger = Logger.getLogger(org.greenstone.gsdl3.action.SystemAction.class.getName());
+
+    /** process a request */
+    public Element process (Element message) {
+	
+	// assume only one request
+	Element request = (Element)GSXML.getChildByTagName(message, GSXML.REQUEST_ELEM);
+	
+	String subaction = request.getAttribute(GSXML.SUBACTION_ATT);
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	String uid = request.getAttribute(GSXML.USER_ID_ATT);
+	// get the param list
+	Element cgi_param_list = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	HashMap params = GSXML.extractParams(cgi_param_list, false);
+
+	Element result = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	
+	String coll = (String)params.get(GSParams.SYSTEM_CLUSTER);
+
+	String to = "";
+	if (coll!=null && !coll.equals("")) {
+	    to = coll;
+	}
+
+	Element mr_request_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element mr_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_SYSTEM, to, lang, uid);
+	mr_request_message.appendChild(mr_request);
+	
+	Element system = this.doc.createElement(GSXML.SYSTEM_ELEM);
+	mr_request.appendChild(system);
+	
+	// will need to change the following if can do more than one system request at once
+	if (subaction.equals("c")) { // configure
+	    system.setAttribute(GSXML.TYPE_ATT, GSXML.SYSTEM_TYPE_CONFIGURE);
+	    String info = (String)params.get(GSParams.SYSTEM_SUBSET);
+	    system.setAttribute(GSXML.SYSTEM_SUBSET_ATT, info);
+	
+	} else {
+	    String name = (String)params.get(GSParams.SYSTEM_MODULE_NAME);
+	    String type = (String)params.get(GSParams.SYSTEM_MODULE_TYPE);
+
+	    system.setAttribute(GSXML.SYSTEM_MODULE_NAME_ATT, name);
+	    system.setAttribute(GSXML.SYSTEM_MODULE_TYPE_ATT, type);
+	    
+	    if (subaction.equals("d")) { // delete
+		system.setAttribute(GSXML.TYPE_ATT, GSXML.SYSTEM_TYPE_DEACTIVATE);
+
+	    } else if (subaction.equals("a")) { // add
+		system.setAttribute(GSXML.TYPE_ATT, GSXML.SYSTEM_TYPE_ACTIVATE);
+	    } else {
+	    // create the default response
+	    // for now just have an error
+	    logger.error("bad subaction type");
+	    Element page_response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	    result.appendChild(page_response);
+	
+	    return result;
+	    }
+	}
+
+	Element response_message = this.mr.process(mr_request_message);
+	
+	result.appendChild(GSXML.duplicateWithNewName(this.doc, (Element)GSXML.getChildByTagName(response_message, GSXML.RESPONSE_ELEM), GSXML.RESPONSE_ELEM, true));
+	return result;
+	
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/XMLDocumentAction.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/XMLDocumentAction.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/action/XMLDocumentAction.java	(revision 13928)
@@ -0,0 +1,106 @@
+package org.greenstone.gsdl3.action;
+
+import org.greenstone.gsdl3.core.ModuleInterface;
+import org.greenstone.gsdl3.util.*;
+import org.greenstone.gsdl3.service.TEIRetrieve;
+// XML classes
+import org.w3c.dom.Node; 
+import org.w3c.dom.NodeList; 
+import org.w3c.dom.Text; 
+import org.w3c.dom.Document; 
+import org.w3c.dom.Element; 
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Vector;
+import java.util.Map;
+import java.util.Iterator;
+import java.io.File;
+
+/** action class for retrieving parts of XML documents */
+public class XMLDocumentAction extends Action {
+    
+   
+    /** process - processes a request.
+     */ 
+    public Element process (Element message) {
+	
+	// get the request - assume there is only one
+	Element request = (Element)GSXML.getChildByTagName(message, GSXML.REQUEST_ELEM);
+
+	// create the return message
+	Element result = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element page_response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	result.appendChild(page_response);
+	
+	// extract the params from the cgi-request, and check that we have a coll specified
+	Element cgi_param_list = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	HashMap params = GSXML.extractParams(cgi_param_list, false);
+
+	String collection = (String)params.get(GSParams.COLLECTION);
+	if (collection == null || collection.equals("")) {
+	    return result;
+	}
+	String doc_name = (String) params.get(GSParams.DOCUMENT);
+	if (doc_name == null || doc_name.equals("")) {
+	    return result;
+	}
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	String uid = request.getAttribute(GSXML.USER_ID_ATT);
+	
+	// subaction used to decide if we are returning content or structure
+	String document_mode = request.getAttribute(GSXML.SUBACTION_ATT);
+	String to = null;
+	if (document_mode.equals("text")) {
+	    to = GSPath.appendLink(collection, "DocumentContentRetrieve");
+	} else if (document_mode.equals("toc")) {
+	    to = GSPath.appendLink(collection, "DocumentStructureRetrieve");
+	} else { // the default is text
+	    to = GSPath.appendLink(collection, "DocumentContentRetrieve");
+	}
+	
+	// make the request to the collection
+	Element mr_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	
+	Element ret_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, to, lang, uid);
+	mr_message.appendChild(ret_request);
+
+	Element doc_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	ret_request.appendChild(doc_list);
+	Element doc = this.doc.createElement(GSXML.DOC_NODE_ELEM);
+	doc.setAttribute(GSXML.NODE_ID_ATT, doc_name);
+	doc_list.appendChild(doc);
+	
+	// also add in a request for the Title metadata
+	to = GSPath.appendLink(collection, "DocumentMetadataRetrieve");
+	Element meta_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, to, lang, uid);
+	// copy the doc list
+	meta_request.appendChild(doc_list.cloneNode(true));
+	// add in a metadata param
+	Element param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	meta_request.appendChild(param_list);
+	Element param = GSXML.createParameter(this.doc, "metadata", "root_Title");
+	param_list.appendChild(param);
+	
+	// add the request to the message
+	mr_message.appendChild(meta_request);
+	
+	Element ret_response = this.mr.process(mr_message);
+	String [] links = {GSXML.RESPONSE_ELEM, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER, GSXML.DOC_NODE_ELEM};
+	String path = GSPath.createPath(links);
+	Element doc_node = (Element)this.doc.importNode(GSXML.getNodeByPath(ret_response, path), true);
+	page_response.appendChild(doc_node);
+
+	// get the metadata list
+	Element meta_response = (Element)ret_response.getElementsByTagName(GSXML.RESPONSE_ELEM).item(1);
+	String [] mlinks  = {GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER, GSXML.DOC_NODE_ELEM, GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER};
+	path = GSPath.createPath(mlinks);
+	
+	Element meta_list = (Element)GSXML.getNodeByPath(meta_response, path);
+	if (meta_list != null) {
+	    doc_node.appendChild(this.doc.importNode(meta_list, true));
+	}
+	return result;
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/build/CollectionConstructor.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/build/CollectionConstructor.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/build/CollectionConstructor.java	(revision 13928)
@@ -0,0 +1,97 @@
+package org.greenstone.gsdl3.build;
+
+import org.greenstone.gsdl3.util.*;
+//import java.util.Thread
+import javax.swing.event.EventListenerList;
+import org.w3c.dom.Element;
+
+/** base class for collection construction */
+public abstract class CollectionConstructor 
+    extends Thread {
+
+    /** the site in which building is to take place */
+    protected String site_home = null;
+    /** the name of the collection */
+    protected String collection_name = null;
+    /** the stage of construction */
+    protected int process_type = -1;
+    /** other arguments/parameters for the construction process - in a paramList */
+    protected Element process_params = null;
+    /** the list of listeners for the process */
+    protected EventListenerList listeners = null;
+    /** A flag used to determine if this process has been asked to cancel. */
+    protected boolean cancel = false;
+    
+    public CollectionConstructor(String name) {
+	super(name);
+	this.listeners = new EventListenerList();
+    }
+	
+    /** carry out any set up stuff - returns false if couldn't set up properly
+     */
+    public boolean configure() {
+	return true;
+    }
+    public void stopAction() {
+	this.cancel = true;
+    }
+    
+    public void setActionType(int type) {
+	this.process_type = type;
+    }
+    public void setSiteHome(String site_home) {
+	this.site_home = site_home;
+    }
+    public void setCollectionName(String coll_name) {
+	this.collection_name = coll_name;
+    }
+    public void setProcessParams(Element params) {
+	this.process_params = params;
+    }
+    public boolean addListener(ConstructionListener listener) {
+	this.listeners.add(ConstructionListener.class, listener);
+	return true;
+    }
+    public boolean removeListener(ConstructionListener listener) {
+	this.listeners.remove(ConstructionListener.class, listener);
+	return true;
+    }
+
+    protected void sendProcessBegun(ConstructionEvent evt) {
+	Object[] concerned = this.listeners.getListenerList();
+	for(int i = 0; i < concerned.length ; i+=2) {
+	    if(concerned[i] == ConstructionListener.class) {
+		((ConstructionListener)concerned[i+1]).processBegun(evt);
+	    }
+	}
+    }
+    protected void sendProcessComplete(ConstructionEvent evt) {
+	Object[] concerned = this.listeners.getListenerList();
+	for(int i = 0; i < concerned.length ; i+=2) {
+	    if(concerned[i] == ConstructionListener.class) {
+		((ConstructionListener)concerned[i+1]).processComplete(evt);
+	    }
+	}
+    }
+    
+    protected void sendProcessStatus(ConstructionEvent evt) {
+
+	Object[] concerned = this.listeners.getListenerList();
+	for(int i = 0; i < concerned.length ; i+=2) {
+	    if(concerned[i] == ConstructionListener.class) {
+		((ConstructionListener)concerned[i+1]).processStatus(evt);
+	    }
+	}
+    }
+    protected void sendMessage(ConstructionEvent evt) {
+
+	Object[] concerned = this.listeners.getListenerList();
+	for(int i = 0; i < concerned.length ; i+=2) {
+	    if(concerned[i] == ConstructionListener.class) {
+		((ConstructionListener)concerned[i+1]).message(evt);
+	    }
+	}
+    }
+    
+    abstract public void run();
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/build/ConstructCollection.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/build/ConstructCollection.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/build/ConstructCollection.java	(revision 13928)
@@ -0,0 +1,140 @@
+package org.greenstone.gsdl3.build;
+import org.greenstone.gsdl3.util.*;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+import java.io.File;
+
+/** the class containing the main program for collection building - is essentially a wrapper around a CollectionConstructor
+ * @see CollectionConstructor
+ */
+public class ConstructCollection 
+    implements ConstructionListener {
+    
+    static public void main(String [] args) {
+
+	String site_home = null;
+	String coll_name = null;
+	int process_mode = -1;
+	if (args.length < 4) {
+	    printUsage();
+	    return;
+	}
+
+	// parse the args
+
+	XMLConverter converter = new XMLConverter();
+	Document doc = converter.newDOM();
+	Element option_list = doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	Element option;
+
+	for (int i=0; i<args.length-1; i++) {
+	    String key = args[i];
+	    if (!key.startsWith("-")) {
+		continue; // ignore options that dont start with '-'
+	    }
+	    key = key.substring(1);
+	    String val = args[i+1];
+	    if (val.startsWith("-")) {
+		val=null;
+	    } else {
+		i++;
+	    }
+	    
+	    if (key.equals("site")) {
+		site_home = val;
+	    } else if (key.equals("mode")) {
+		if (val==null) {
+		    continue;
+		}
+		if (val.equals("new")) {
+		    process_mode = GS2PerlConstructor.NEW;
+		} else if (val.equals("import")) {
+		    process_mode = GS2PerlConstructor.IMPORT;
+		} else if (val.equals("build")) {
+		    process_mode = GS2PerlConstructor.BUILD;
+		} else if (val.equals("activate")) {
+		    process_mode = GS2PerlConstructor.ACTIVATE;
+		}
+
+	    } else { // an option to pass to the builder
+ 		option = doc.createElement(GSXML.PARAM_ELEM);
+		option.setAttribute(GSXML.NAME_ATT, key);
+		if (val!=null) {
+		    option.setAttribute(GSXML.VALUE_ATT, val);
+		}
+		option_list.appendChild(option);
+	    }
+	}
+	String last_arg = args[args.length-1];
+	if (last_arg.startsWith("-")) { // should be coll name
+	    System.out.println("ERROR: the last arg should be the collection name!");
+	    printUsage();
+	    return;
+	}
+	
+	coll_name = last_arg;
+	
+	// check that we have the required fields
+	if (site_home==null || process_mode == -1 || coll_name==null) {
+	    System.out.println("ERROR: you have not specified all the necessary args!");
+	    printUsage();
+	    return;
+	}
+
+	// check that the collection name is valid - ie the directory exists if this is not a new one, or doesn't exist if we are creating a new one
+	File coll_dir = new File(GSFile.collectionBaseDir(site_home, coll_name));
+	if (process_mode != GS2PerlConstructor.NEW && !coll_dir.exists()) {
+	    System.out.println("ERROR: Invalid collection ("+coll_name+").");
+	    printUsage();
+	    return;
+	} else if (process_mode == GS2PerlConstructor.NEW && 
+		   coll_dir.exists()) {
+	    System.out.println("ERROR: there is already a collection named "+coll_name);
+	    printUsage();
+	    return;
+	}
+	
+   
+	ConstructCollection processor = new ConstructCollection();
+	GS2PerlConstructor constructor = new GS2PerlConstructor("perl_build");
+	if (!constructor.configure()) {
+	    System.out.println("couldn't configure the constructor!!");
+	    return;
+	}
+	constructor.setCollectionName(coll_name);
+	constructor.setSiteHome(site_home);
+	constructor.setProcessParams(option_list);
+	constructor.setActionType(process_mode);
+	constructor.addListener(processor);
+	constructor.start();
+    }
+    
+    static protected void printUsage() {
+	System.out.println("Usage: the following arguments need to be supplied:\n -site <site-home> -mode new|import|build|activate [options] <coll-name>");
+	System.out.println("Options available are:");
+	System.out.println("-maxdocs N\t process at most N documents\n"+
+			   "-gs2\t use greenstone 2 style building");
+    }
+
+    /** This event handler used to signify that a task has been started */
+    public void processBegun(ConstructionEvent evt) {
+	System.out.println("begun: "+evt.getMessage());
+    }
+    /** This event handler used to signify that a task has been completed */
+    public void processComplete(ConstructionEvent evt){
+	System.out.println("complete: "+evt.getMessage());
+    }
+    /** This event handler used to send status updates as the task is progressing */
+    public void processStatus(ConstructionEvent evt){
+	System.out.println(evt.getMessage());
+    }
+    /**  This event handler used to send any other messages to the listeners */
+    public void message(ConstructionEvent evt){
+	System.out.println(evt.getMessage());
+    }
+
+
+
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/build/ConstructionEvent.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/build/ConstructionEvent.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/build/ConstructionEvent.java	(revision 13928)
@@ -0,0 +1,42 @@
+package org.greenstone.gsdl3.build;
+
+import java.awt.AWTEvent;     
+
+public class ConstructionEvent 
+    extends AWTEvent {
+    
+    /** the event id for these events - use a random number thats
+	not reserved*/
+    private static final int EVENT_ID = RESERVED_ID_MAX+77;
+    /** The status associated with the event. */
+    private int status = -1;
+    /** Any message associated with this event. */
+    private String message = null;
+    /* Constructor.
+     * @param source The <strong>CollectionConstructor</strong> that fired this message.
+     * @param status The status code for this event          
+     * @param message A <strong>String</strong> representing any message attatched with this event.
+     */
+    public ConstructionEvent(Object source, int status, String message) {
+	super(source, EVENT_ID);
+	this.message = message;
+	this.status = status;
+    }
+    /** Gets the message associated with this event.
+     * @return The message as a <strong>String</strong> or <i>null</i>. 
+     */
+    public String getMessage() {
+	return this.message;
+    }
+    /** Gets the status associated with this event. This status can then be matched back to the constants in <strong>GShell</strong>.
+     * @return An <strong>int</strong> signifying the process status.
+     */
+    public int getStatus() {
+	return this.status;
+    }
+    /** returns a String representation of the event */
+    public String toString() {
+	return "org.greenstone.gsdl3.build.ConstructionEvent[" + this.message
++ "," + this.status + "]";
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/build/ConstructionListener.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/build/ConstructionListener.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/build/ConstructionListener.java	(revision 13928)
@@ -0,0 +1,16 @@
+package org.greenstone.gsdl3.build;
+
+import java.util.EventListener;
+
+public interface ConstructionListener 
+    extends EventListener {
+
+    /** This event handler used to signify that a task has been started */
+    public void processBegun(ConstructionEvent evt);
+    /** This event handler used to signify that a task has been completed */
+    public void processComplete(ConstructionEvent evt);
+    /** This event handler used to send status updates as the task is progressing */
+    public void processStatus(ConstructionEvent evt);
+    /**  This event handler used to send any other messages to the listeners */
+    public void message(ConstructionEvent evt);
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/build/GS2PerlConstructor.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/build/GS2PerlConstructor.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/build/GS2PerlConstructor.java	(revision 13928)
@@ -0,0 +1,297 @@
+package org.greenstone.gsdl3.build;
+
+// greenstome classes
+import org.greenstone.gsdl3.util.*;
+
+
+// xml classes
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+//general java classes
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.File;
+import java.util.Vector;
+
+/** CollectionConstructor class for greenstone 2 compatible building
+ * it uses the perl scripts to do the building stuff */
+public class GS2PerlConstructor 
+    extends CollectionConstructor {
+
+    public static final int NEW = 0;
+    public static final int IMPORT = 1;
+    public static final int BUILD = 2;
+    public static final int ACTIVATE = 3;
+
+    /** gsdlhome for greenstone 2 - we use the perl modules and building 
+     * scripts from there */
+    protected String gsdl2home = null; 
+    /** gsdlhome for gsdl3 - shouldn't need this eventually ??*/
+    protected String gsdl3home = null; 
+    /** gsdlos for greenstone 2 */
+    protected String gsdlos = null; 
+    /** the path environment variable */
+    protected String path = null;
+
+    public GS2PerlConstructor(String name) {
+	super(name);
+    }
+
+    /** retrieves the necessary environment variables */
+    public boolean configure() {
+	// try to get the environment variables
+	this.gsdl2home = System.getProperty("GSDLHOME");
+	this.gsdl3home = System.getProperty("GSDL3HOME");
+	this.gsdlos = System.getProperty("GSDLOS");
+	this.path = System.getProperty("PATH");
+	if (this.gsdl2home ==null ) {
+	    System.err.println("You must have greenstone2 installed, and GSDLHOME set for GS2Perl building to work!!");
+	    return false;
+	} 
+	if (this.gsdl3home == null|| this.gsdlos == null) {
+	   System.err.println("You must have GSDL3HOME and GSDLOS set for GS2Perl building to work!!");
+	    return false;
+	}  
+	if (this.path==null) {
+	    System.err.println("You must have the PATH set for GS2Perl building to work!!");
+	    return false;
+	}
+	return true;
+    }
+
+    public void run() {
+	String msg;
+	ConstructionEvent evt;
+	if (this.process_type == -1) {
+	    msg = "Error: you must set the action type";
+	    evt = new ConstructionEvent(this, GSStatus.ERROR, msg);
+	    sendMessage(evt);
+	    return;
+	}
+	if (this.site_home==null) { 
+	    msg = "Error: you must set site_home";
+	    evt = new ConstructionEvent(this, GSStatus.ERROR, msg);
+	    sendMessage(evt);
+	    return;
+	}
+	if (this.process_type != NEW && this.collection_name ==null) {
+	    msg = "Error: you must set collection_name";
+	    evt = new ConstructionEvent(this, GSStatus.ERROR, msg);
+	    sendMessage(evt);
+	    return;
+	}
+	
+	switch (this.process_type) {
+	case NEW:
+	    newCollection();
+	    break;
+	case IMPORT:
+	    importCollection();
+	    break;
+	case BUILD:
+	    buildCollection();
+	    break;
+	case ACTIVATE:
+	    activateCollection();
+	    break;
+	default:
+	    msg = "wrong type of action specified!";
+	    evt = new ConstructionEvent(this, GSStatus.ERROR, msg);
+	    sendMessage(evt);
+	    break;
+	}
+
+    }
+
+    protected void newCollection() {
+	sendMessage(new ConstructionEvent(this, GSStatus.INFO, "Collection construction: new collection."));
+	Vector command = new Vector();
+	command.add("gs2_mkcol.pl");
+	command.add("-site");
+	command.add(this.site_home);
+	command.add("-collectdir");
+	command.add(GSFile.collectDir(this.site_home));
+	command.addAll(extractParameters(this.process_params));
+	command.add(this.collection_name);
+	String [] command_str = {};
+	command_str = (String [])command.toArray(command_str); 
+	if (runPerlCommand(command_str)) {
+	    // success!! - need to send the final completed message
+	    sendProcessComplete(new ConstructionEvent(this, GSStatus.COMPLETED, ""));
+	} // else an error message has already been sent, do nothing
+	
+    }
+
+    protected void importCollection() {
+	sendMessage(new ConstructionEvent(this, GSStatus.INFO, "Collection construction: import collection."));
+	Vector command = new Vector();
+	command.add("import.pl");
+	command.add("-collectdir");
+	command.add(GSFile.collectDir(this.site_home));
+	command.addAll(extractParameters(this.process_params));
+	command.add(this.collection_name);
+	String [] command_str = {};
+	command_str = (String [])command.toArray(command_str); 
+
+	if (runPerlCommand(command_str)) {
+	    // success!! - need to send the final completed message
+	    sendProcessComplete(new ConstructionEvent(this, GSStatus.COMPLETED, ""));
+	} // else an error message has already been sent, do nothing
+    }
+
+     protected void buildCollection() {
+	sendMessage(new ConstructionEvent(this, GSStatus.INFO, "Collection construction: build collection."));
+	Vector command = new Vector();
+	command.add("buildcol.pl");
+	command.add("-collectdir");
+	command.add(GSFile.collectDir(this.site_home));
+	command.addAll(extractParameters(this.process_params));
+	command.add(this.collection_name);
+	String [] command_str = {};
+	command_str = (String [])command.toArray(command_str); 
+	
+	if (runPerlCommand(command_str)) {
+	    // success!! - need to send the final completed message
+	    sendProcessComplete(new ConstructionEvent(this, GSStatus.COMPLETED, ""));
+	}// else an error message has already been sent, do nothing
+//  	    
+
+     }
+    protected void activateCollection() {
+	sendMessage(new ConstructionEvent(this, GSStatus.INFO, "Collection construction: activate collection."));
+
+	// first check that we have a building directory
+	File build_dir = new File(GSFile.collectionBuildDir(this.site_home, this.collection_name));
+	if (!build_dir.exists()) {
+	    sendMessage(new ConstructionEvent(this, GSStatus.ERROR, "build dir doesn't exist!"));
+	    return;
+	}
+
+	// move building to index
+	File index_dir = new File(GSFile.collectionIndexDir(this.site_home, this.collection_name));
+	if (index_dir.exists()) {
+	    sendMessage(new ConstructionEvent(this, GSStatus.INFO, "deleting index directory"));
+	    index_dir.delete();
+	    if (index_dir.exists()) {
+		sendMessage(new ConstructionEvent(this, GSStatus.INFO, "index directory still exists!"));
+	    }
+	}
+
+	GSFile.moveDirectory(build_dir, index_dir);
+	if (!index_dir.exists()) {
+	    sendMessage(new ConstructionEvent(this, GSStatus.ERROR, "index dir wasn't created!"));
+	}
+
+	// run the convert coll script to convert the gs2 coll to gs3
+	Vector command = new Vector();
+	command.add("convert_coll_from_gs2.pl");
+	command.add("-collectdir");
+	command.add(GSFile.collectDir(this.site_home));
+	command.addAll(extractParameters(this.process_params));
+	command.add(this.collection_name);
+	String [] command_str = {};
+	command_str = (String [])command.toArray(command_str); 
+	
+	if (!runPerlCommand(command_str)) {
+	    // an error has occurred, dont carry on
+	    return;
+	}
+
+	// success!!  - need to send the final completed message
+	sendProcessComplete(new ConstructionEvent(this, GSStatus.COMPLETED, ""));
+    }
+
+    /** extracts all the args from the xml and returns them in a Vector */
+    protected Vector extractParameters(Element param_list) {
+
+	Vector args = new Vector();
+	if (param_list==null) {
+	    return args; // return an empty vector
+	}
+	NodeList params = param_list.getElementsByTagName(GSXML.PARAM_ELEM);
+	
+	for (int i=0; i<params.getLength(); i++) {
+	    Element p = (Element)params.item(i);
+	    String name = p.getAttribute(GSXML.NAME_ATT);
+	    String value=p.getAttribute(GSXML.VALUE_ATT);
+	    if (!name.equals("")) {
+		args.add("-"+name);
+		if (!value.equals("")) {
+		    args.add(value);
+		}
+	    }
+	}
+	    
+	return args;
+    }
+    /** returns true if completed correctly, false otherwise */
+    protected boolean runPerlCommand(String[] command) {
+	String msg;
+	ConstructionEvent evt;
+	
+	String args[] = {"GSDLHOME="+this.gsdl2home, "GSDL3HOME="+this.gsdl3home, "GSDLOS="+this.gsdlos, "PATH="+this.path};
+	String command_str = "";
+	for(int i = 0; i < command.length; i++) {
+	    command_str = command_str + command[i] + " ";
+	}
+	sendMessage(new ConstructionEvent(this, GSStatus.INFO, "command = "+command_str));
+	try {
+	    Runtime rt = Runtime.getRuntime();
+	    sendProcessBegun(new ConstructionEvent(this, GSStatus.ACCEPTED, "starting"));
+	    Process prcs = rt.exec(command, args);
+
+	    InputStreamReader eisr = new InputStreamReader( prcs.getErrorStream() );
+	    InputStreamReader stdinisr = new InputStreamReader( prcs.getInputStream() );
+	    BufferedReader ebr = new BufferedReader( eisr );
+	    BufferedReader stdinbr = new BufferedReader( stdinisr );
+	    // Captures the std err of a program and pipes it into
+	    // std in of java
+	    String eline = null;
+	    String stdinline = null;
+	    while (((eline = ebr.readLine()) != null || (stdinline = stdinbr.readLine()) != null) && !this.cancel) {
+		if(eline != null) {
+		    sendProcessStatus(new ConstructionEvent(this, GSStatus.CONTINUING, eline));
+		}
+		if(stdinline != null) {
+		    sendProcessStatus(new ConstructionEvent(this, GSStatus.CONTINUING, stdinline));
+		}
+	    }
+	    if(!this.cancel) {
+		// Now display final message based on exit value
+		prcs.waitFor();
+		
+		if(prcs.exitValue() == 0) {
+		    //status = OK;
+		    sendProcessStatus(new ConstructionEvent(this, GSStatus.CONTINUING, "Success"));
+		    
+		} else {
+		    //status = ERROR;
+		    sendProcessStatus(new ConstructionEvent(this, GSStatus.ERROR, "Failure"));
+		   
+		    return false;
+		    
+		}
+	    }
+	    else {
+		// I need to somehow kill the child process. Unfortunately Thread.stop() and Process.destroy() both fail to do this. But now, thankx to the magic of Michaels 'close the stream suggestion', it works fine.
+		sendProcessStatus(new ConstructionEvent(this, GSStatus.HALTED, "killing the process"));
+		prcs.getOutputStream().close();
+		prcs.destroy();
+		//status = ERROR;
+		return false;
+	    }
+	    
+	} catch (Exception e) {
+	    sendProcessStatus(new ConstructionEvent(this, GSStatus.ERROR, "Exception occurred "+e.toString()));
+	}
+
+	// we're done, but we dont send a process complete message here cos there ight be stuff to do after this has finished.
+	return true;
+
+    }
+   
+
+
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/build/GS2PerlListener.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/build/GS2PerlListener.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/build/GS2PerlListener.java	(revision 13928)
@@ -0,0 +1,62 @@
+package org.greenstone.gsdl3.build;
+
+public class GS2PerlListener 
+    implements ConstructionListener {
+
+    /** a buffer holding all the messages */
+    protected StringBuffer log=null;
+    /** a buffer holding only the latest update */
+    protected StringBuffer update = null;
+
+    /** a status code */
+    protected int status = -1;
+    /** whether the process this is listeneing to is finshed */
+    protected boolean finished = false;
+
+    public GS2PerlListener() {
+	this.log = new StringBuffer();
+	this.update = new StringBuffer();
+    }
+
+    public boolean isFinished() {
+	return this.finished;
+    }
+    public String getLog() {
+	return this.log.toString();
+    }
+    public int getStatus() {
+	return this.status;
+    }
+    synchronized public String getUpdate() {
+	this.log.append(this.update);
+	String tmp = this.update.toString();
+	this.update.delete(0, this.update.length());
+	return tmp;
+    }
+
+    // do we need to synchronize the methods below?
+
+    /** This event handler used to signify that a task has been started */
+    synchronized public void processBegun(ConstructionEvent evt) {
+	this.status = evt.getStatus();
+	this.update.append(evt.getMessage()+"\n");
+	
+    }
+    /** This event handler used to signify that a task has been completed */
+    synchronized public void processComplete(ConstructionEvent evt){
+	this.status = evt.getStatus();
+	this.update.append(evt.getMessage()+"\n");
+    }
+    /** This event handler used to send status updates as the task is progressing */
+    synchronized public void processStatus(ConstructionEvent evt){
+	this.status = evt.getStatus();
+	this.update.append(evt.getMessage()+"\n");
+    }
+    /**  This event handler used to send any other messages to the listeners */
+    synchronized public void message(ConstructionEvent evt){
+	this.status = evt.getStatus();
+	this.update.append(evt.getMessage()+"\n");
+    }
+
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/build/StatusDisplay.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/build/StatusDisplay.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/build/StatusDisplay.java	(revision 13928)
@@ -0,0 +1,188 @@
+package org.greenstone.gsdl3.build;
+
+import java.applet.Applet;
+import java.awt.*;
+import java.awt.event.*;
+
+import org.greenstone.gsdl3.util.*;
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+import org.apache.xerces.parsers.DOMParser;
+import java.net.URL;
+import java.io.DataInputStream;
+
+
+/** StatusDisplay - a java applet thats sends a message at regular intervals 
+ * to a pre specified address (the library param) and then displays the 
+ * status messages received.
+ * to use, embed in a web page using something like: (note the cgi args may differ - see process.xsl for details )
+ * <applet code="org.greenstone.gsdl3.build.StatusDisplay.class" codebase='lib/java' archive='gsdl3.jar, xercesImpl.jar, jaxp.jar, xml-apis.jar' width='537' height='100'>The status display applet.<param name='library' value='mylibrary?a=pr&rt=s&c=build&o=xml&ro=1&s=ImportCollection&l=en&coll=demo'/></applet>
+ * the cgi params for the library param are dependent on what action/service 
+ *  is using the applet
+ */
+public class StatusDisplay extends Applet 
+    implements Runnable {
+
+    /** the display area for the status messages */
+    protected TextArea display;
+    /** how long to delay between requests */
+    protected int delay=3000; // 3 secs
+    /** the thread used */
+    protected Thread updator_thread;
+    /** the url for the requests */ 
+    protected URL status_cgi = null;
+    /** if true, stops sending requests, and cant be unset */
+    protected boolean completed = false;
+    // init is called if you leave the page and go back - need to somehow retrieve all the previous messages that have been obtained cos we may have left the page and gone back to it during an import or something. dont want to lose all the info.
+    public void init() {
+	//Create the text field and make it uneditable.
+	this.display = new TextArea();
+	this.display.setEditable(false);
+	this.display.setBackground(Color.white);
+	//Set the layout manager so that the text field will be
+	//as wide as possible.
+	setLayout(new java.awt.GridLayout(1,0));
+
+	//Add the text field to the applet.
+	add(this.display);
+	validate();
+
+	// add the initial status text
+	String initial_text = parameterValue("initial_text");
+	addItem(initial_text);
+
+	// check the initial error state - there may be no more messages to come
+	this.completed = GSStatus.isCompleted(Integer.parseInt(parameterValue("initial_code")));
+		
+	// we always do the same query
+	String library = parameterValue("library");
+	library = tidy_URL(library);
+	try {
+	    this.status_cgi = new URL(library);
+	} catch (Exception e) {
+	    System.out.println("Error creating URL for "+library+": "+e.getMessage());
+	}
+    }
+    
+    public void start() {
+	if (this.completed) {
+	    // do nothing
+	} else {
+	    if (this.updator_thread == null) {
+		this.updator_thread = new Thread(this);
+	    }
+	    this.updator_thread.start();
+	}
+    }
+    public void stop() {
+	this.updator_thread = null;
+    }
+    public void run() {
+	
+	if (this.completed) { // do nothing. dont know if we need this here
+	    return;
+	}
+        //Just to be nice, lower this thread's priority
+        //so it can't interfere with other processing going on.
+        Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
+
+        //Remember which thread we are.
+        Thread current_thread = Thread.currentThread();
+
+        //This is the  loop.
+        while (current_thread == this.updator_thread && !this.completed) {
+	    queryServer();
+            this.display.repaint();
+	    
+            //Delay for the specified time
+            try {
+		Thread.sleep(this.delay);
+            } catch (InterruptedException e) {
+                break;
+            }
+        }
+    }
+
+    /** add some more text to the display    */
+    void addItem(String new_text) {
+	String t = this.display.getText()+"\n"+new_text;
+	this.display.setText(t);
+	this.display.setCaretPosition(t.length()); // so that you always see the 
+	// most recent entries - ie so that it scrolls down automatically
+	repaint();
+    }
+    
+    void queryServer() {
+
+	// Send the query 
+	System.out.println("sending query: " + this.status_cgi); // this appears in the java console
+	try {
+	    DataInputStream in = new DataInputStream(this.status_cgi.openStream());
+	    DOMParser parser = new DOMParser();
+	    parser.parse(new InputSource(in));
+	    Document data_doc = parser.getDocument();
+	    Element data_elem = data_doc.getDocumentElement();
+	    Element status_elem = (Element)GSXML.getChildByTagName(data_elem, GSXML.STATUS_ELEM);
+	    if (status_elem != null) {
+		String status = status_elem.getAttribute(GSXML.STATUS_ERROR_CODE_ATT);
+		System.out.println("received status "+status);
+		this.completed = GSStatus.isCompleted(Integer.parseInt(status));
+		addItem(GSXML.getNodeText(status_elem));
+	    } else {
+		System.out.println("Error - no status receieved");
+		this.completed=true;
+	    }
+	    in.close();
+	} catch (Exception e) {
+	    System.err.println( "Error sending query ("+this.status_cgi+"): " + e);
+	}
+
+    }
+  
+    // Get a REQUIRED string.  Stop the applet if we cannot.
+    String parameterValue(String name) {
+	try { 
+	    return getParameter(name);
+	} catch (Exception e) {
+	    System.err.println("StatusDisplay: you must give a parameter for \""+ name + "\".  Stopping.");
+	    stop();
+	}
+	return "";
+    }
+
+    /**Tidy up URLs
+     *
+     * Ensure a URL address (as string) has a protocol, host, and file.
+     */
+    String tidy_URL(String address) {
+
+	// make sure the URL has protocol, host, and file
+	if (address.startsWith("http")) {
+	    // the address has all the necessary components
+	} else if (address.startsWith("/")) {
+	    // there is not protocol and host
+	    URL document = getDocumentBase();
+	    String port = "";
+	    if (document.getPort()!=-1) {
+		port = ":" + document.getPort();
+	    }
+	    address = "http://" + document.getHost() + port  + address;
+	} else {
+	    // this URL is relative to the directory the document is in
+	    URL document = getDocumentBase();
+	    String directory = document.getFile();
+	    int end = directory.lastIndexOf('/');
+	    String port = "";
+	    if (document.getPort()!=-1) {
+		port = ":" + document.getPort();
+	    }
+	    directory = directory.substring(0,end + 1);
+	    address = "http://" + document.getHost() + port + directory + address;
+
+	}
+
+	return address;
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/collection/Collection.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/collection/Collection.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/collection/Collection.java	(revision 13928)
@@ -0,0 +1,225 @@
+/*
+ *    Collection.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.collection;
+
+import org.greenstone.gsdl3.util.*;
+import org.greenstone.gsdl3.core.*;
+import org.greenstone.gsdl3.service.*;
+
+
+// java XML classes we're using
+import org.w3c.dom.Document; 
+import org.w3c.dom.Node; 
+import org.w3c.dom.Element; 
+import org.w3c.dom.NodeList; 
+
+import java.io.File;
+import java.util.HashMap;
+
+import org.apache.log4j.*;
+
+/**
+ * Represents a collection in Greenstone. A collection is an extension of
+ * a ServiceCluster - it has local data that the services use.
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ * @version $Revision$
+ * @see ModuleInterface
+ */
+public class Collection 
+    extends ServiceCluster {
+
+    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.collection.Collection.class.getName());
+
+    /** is this collection public or private */
+    protected boolean is_public = true;
+    protected XMLTransformer transformer = null;
+    /** same as setClusterName */
+    public void setCollectionName(String name) {
+	setClusterName(name);
+    }
+
+    public Collection() {
+	super();
+	this.description = this.doc.createElement(GSXML.COLLECTION_ELEM);
+	
+    }
+	
+    /**
+     * Configures the collection.
+     *
+     * gsdlHome and collectionName must be set before configure is called.
+     *
+     * the file buildcfg.xml is located in gsdlHome/collect/collectionName
+     * collection metadata is obtained, and services loaded.
+     *
+     * @return true/false on success/fail
+     */
+    public boolean configure() {
+	
+	if (this.site_home == null || this.cluster_name== null) {
+	    logger.error("Collection: site_home and collection_name must be set before configure called!");
+	    return false;
+	}
+	
+	Element coll_config_xml = loadCollConfigFile();
+	Element build_config_xml = loadBuildConfigFile();
+	
+	if (coll_config_xml==null||build_config_xml==null) {
+	    return false;
+	}
+	// process the metadata and display items
+	findAndLoadInfo(coll_config_xml, build_config_xml);
+	
+	// now do the services	
+	Element service_list = (Element)GSXML.getChildByTagName(build_config_xml, GSXML.SERVICE_CLASS_ELEM+GSXML.LIST_MODIFIER);
+	configureServiceRack(service_list, coll_config_xml);
+	
+	return true;
+	
+    }
+
+    public boolean isPublic() {
+	return is_public;
+    }
+    /** 
+     * load in the collection config file into a DOM Element 
+     */    
+    protected Element loadCollConfigFile() {
+
+	File coll_config_file = new File(GSFile.collectionConfigFile(this.site_home, this.cluster_name));
+	
+	if (!coll_config_file.exists()) {
+	    logger.error("Collection: couldn't configure collection: "+this.cluster_name+", "+coll_config_file+" does not exist");
+	    return null;
+	}
+	// get the xml for both files
+	Document coll_config_doc = this.converter.getDOM(coll_config_file, CONFIG_ENCODING);
+	Element coll_config_elem = null;
+	if (coll_config_doc != null) {
+	    coll_config_elem = coll_config_doc.getDocumentElement();
+	}
+	return coll_config_elem;
+
+    }
+    
+    /** 
+     * load in the collection build config file into a DOM Element 
+     */        
+    protected Element loadBuildConfigFile() {
+	
+	File build_config_file = new File(GSFile.collectionBuildConfigFile(this.site_home, this.cluster_name));
+	if (!build_config_file.exists()) {
+	    logger.error("Collection: couldn't configure collection: "+this.cluster_name+", "+build_config_file+" does not exist");
+	    return null;
+	}
+	Document build_config_doc = this.converter.getDOM(build_config_file, CONFIG_ENCODING);
+	Element build_config_elem = null;
+	if (build_config_doc != null) {
+	    build_config_elem = build_config_doc.getDocumentElement();
+	}
+	return build_config_elem;
+    }
+
+    /**
+     * find the metadata and display elems from the two config files and add it to the appropriate lists
+     */
+    protected boolean findAndLoadInfo(Element coll_config_xml, 
+				      Element build_config_xml){
+
+	// metadata
+	Element meta_list = (Element)GSXML.getChildByTagName(coll_config_xml, GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
+	addMetadata(meta_list);
+	meta_list = (Element)GSXML.getChildByTagName(build_config_xml, GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
+	addMetadata(meta_list);
+
+	meta_list = this.doc.createElement(GSXML.METADATA_ELEM + GSXML.LIST_MODIFIER);
+	GSXML.addMetadata(this.doc, meta_list, "httpPath", this.site_http_address+"/collect/"+this.cluster_name);
+	addMetadata(meta_list);
+
+	// display stuff
+	Element display_list = (Element)GSXML.getChildByTagName(coll_config_xml, GSXML.DISPLAY_TEXT_ELEM+GSXML.LIST_MODIFIER);
+	if (display_list != null) {
+	    resolveMacros(display_list);
+	    addDisplayItems(display_list);
+	}
+
+	// check whether we are public or not
+	if (meta_list != null) {
+	    Element meta_elem = (Element) GSXML.getNamedElement(metadata_list, GSXML.METADATA_ELEM, GSXML.NAME_ATT, "public");
+	    if (meta_elem != null) {
+		String value = GSXML.getValue(meta_elem).toLowerCase().trim();
+		if (value.equals("false")) {
+		    is_public = false;
+		}
+	    }
+	}
+	return true;
+
+    }
+
+    protected boolean resolveMacros(Element display_list) {
+	if (display_list==null) return false;
+	NodeList displaynodes = display_list.getElementsByTagName(GSXML.DISPLAY_TEXT_ELEM);
+	if (displaynodes.getLength()>0) { 
+	    String http_site = this.site_http_address;
+	    String http_collection = this.site_http_address +"/collect/"+this.cluster_name;
+	    for(int k=0; k<displaynodes.getLength(); k++) {
+		Element d = (Element) displaynodes.item(k);
+		String text = GSXML.getNodeText(d);
+		text = text.replaceAll("_httpsite_", http_site);
+		text = text.replaceAll("_httpcollection_", http_collection);
+		GSXML.setNodeText(d, text);
+	    }
+	}
+	return true;
+    }
+    /** 
+     * do a configure on only part of the collection
+     */
+    protected boolean configureSubset(String subset) {
+
+	// need the coll config files
+	Element coll_config_elem = loadCollConfigFile();
+	Element build_config_elem = loadBuildConfigFile();
+	if (coll_config_elem == null||build_config_elem == null) {
+	    // wont be able to do any of teh requests
+	    return false;
+	}    
+	
+	if (subset.equals(GSXML.SERVICE_ELEM+GSXML.LIST_MODIFIER)) {
+	    Element service_rack_list = (Element)GSXML.getChildByTagName(build_config_elem, GSXML.SERVICE_CLASS_ELEM+GSXML.LIST_MODIFIER);
+	    
+	    return configureServiceRack(service_rack_list, coll_config_elem);
+	} 
+
+	if (subset.equals(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER) || subset.equals(GSXML.DISPLAY_TEXT_ELEM+GSXML.LIST_MODIFIER)) {
+	    return findAndLoadInfo(coll_config_elem, build_config_elem);
+	    
+	}
+	
+	logger.error("Collection: cant process system request, configure "+subset);
+	return false;
+    } 
+
+}
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/collection/ServiceCluster.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/collection/ServiceCluster.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/collection/ServiceCluster.java	(revision 13928)
@@ -0,0 +1,623 @@
+/*
+ *    ServiceCluster.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+// leave the package name as is for now - should be changed to something better
+// cluster? groups?
+package org.greenstone.gsdl3.collection;
+
+
+import org.greenstone.gsdl3.util.*;
+import org.greenstone.gsdl3.core.*;
+import org.greenstone.gsdl3.service.*;
+
+// java XML classes we're using
+import org.w3c.dom.Document; 
+import org.w3c.dom.Node; 
+import org.w3c.dom.Element; 
+import org.w3c.dom.NodeList; 
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.apache.log4j.*;
+
+/* ServiceCluster - a groups of services that are related in some way
+ * Implements ModuleInterface. Contains a list of services provided by the cluster, along with metadata about the cluster itself.
+ * a collection is a special type of cluster
+ *  @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ *  @version $Revision$
+ *  @see ModuleInterface
+ */
+public class ServiceCluster  
+    implements ModuleInterface {
+
+    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.collection.ServiceCluster.class.getName()); 
+
+    protected static final String CONFIG_ENCODING = "utf-8";
+
+    protected static final String DEFAULT_LANG = "en"; // hack for now, should be read from the coll cfg file? or site cfg file for cluster
+    
+    /** base directory for the site that this cluster belongs to*/
+    protected String site_home = null;
+    /** http address of the site that this cluster belongs to */
+    protected String site_http_address = null;
+    /** The name of the cluster - for a collection, this is the collection name*/
+    protected String cluster_name = null;
+
+    /** a reference to the message router */
+    protected MessageRouter router = null;
+    /** The map of services.
+     *
+     * Maps Services to ServiceRack objects
+     * @see ServiceRack
+     *
+     */
+    protected HashMap service_map=null;
+    /** maps pseudo service names to real service names - needed if we have two services with the same name for one collection */
+    protected HashMap service_name_map=null;
+    
+    /** XML converter for String to DOM and vice versa */
+    protected XMLConverter converter=null;
+
+    /** container doc for description elements */
+    protected Document doc = null;
+    /** list of services */
+    protected Element service_list = null;
+    /** list of metadata - all metadata, regardless of language goes in here */
+    protected Element metadata_list = null;
+    /** language specific stuff */
+    //protected Element lang_specific_metadata_list = null;
+    protected Element display_item_list = null;
+    /** the element that will have any descriptions passed back in */
+    protected Element description = null;
+
+    public void setSiteHome(String home) {
+	this.site_home = home;
+    }
+
+    public void setSiteAddress(String address) {
+	this.site_http_address = address;
+    }
+
+    public void cleanUp() {
+	Iterator i = this.service_map.values().iterator();
+	while (i.hasNext()) {
+	    ServiceRack s = (ServiceRack)i.next();
+	    s.cleanUp();
+	}
+    }
+    public void setClusterName(String name) {
+	this.cluster_name = name;	
+	this.description.setAttribute(GSXML.NAME_ATT, name);
+    }  
+
+    public void setMessageRouter(MessageRouter m) {
+	this.router = m;
+    }
+
+    public ServiceCluster() {
+	this.service_map = new HashMap();
+	this.service_name_map = new HashMap();
+	this.converter = new XMLConverter();
+	this.doc = this.converter.newDOM();
+	this.description = this.doc.createElement(GSXML.CLUSTER_ELEM);
+	this.display_item_list = this.doc.createElement(GSXML.DISPLAY_TEXT_ELEM+GSXML.LIST_MODIFIER);
+	this.metadata_list = this.doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
+    }
+
+    /**
+     * Configures the cluster.
+     *
+     * gsdlHome and clusterName must be set before configure is called.
+     *
+     * reads the site configuration file, and configures itself
+     * this calls configure(Element) with the XML element node from the config
+     * file.
+     * configure(Element) should be used if the config file has already been 
+     * parsed.  This method will work with any subclass.
+     * 
+     * @return true if configure successful, false otherwise.
+     */
+    public boolean configure() {
+
+	if (this.site_home == null || this.cluster_name== null) {
+	    logger.error("site_home and cluster_name must be set before configure called!");
+	    return false;
+	}
+	logger.info("configuring service cluster");
+	// read the site configuration file
+	File config_file = new File(GSFile.siteConfigFile(this.site_home));
+
+	if (!config_file.exists()) {
+	    logger.error("couldn't configure cluster: "+this.cluster_name +", "+config_file+" does not exist");
+	    return false;
+	}
+
+	Document doc = this.converter.getDOM(config_file, CONFIG_ENCODING);
+	if (doc == null) {
+	    logger.error("couldn't parse config file "+config_file.getPath());
+	    return false;
+	}
+	
+	// get the appropriate service cluster element
+	Element cluster_list = (Element)GSXML.getChildByTagName(doc.getDocumentElement(), GSXML.CLUSTER_ELEM+GSXML.LIST_MODIFIER);
+	Element sc = GSXML.getNamedElement(cluster_list, GSXML.CLUSTER_ELEM,
+					   GSXML.NAME_ATT, this.cluster_name);
+	
+	return this.configure(sc);
+    }
+    
+    
+    public boolean configure(Element service_cluster_info) {
+	
+	// get the metadata - for now just add it to the list
+	Element meta_list = (Element) GSXML.getChildByTagName(service_cluster_info, GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
+	if (meta_list !=null) {
+	    if (!addMetadata(meta_list)) {
+		
+		logger.error(" couldn't configure the metadata");
+	    }
+	}
+	
+	// get the display info
+	Element display_list = (Element) GSXML.getChildByTagName(service_cluster_info, GSXML.DISPLAY_TEXT_ELEM+GSXML.LIST_MODIFIER);
+	if (display_list !=null) {
+	    if (!addDisplayItems(display_list)) {
+		
+		logger.error("couldn't configure the display items");
+	    }
+	}
+	
+
+	// do the service racks
+	Element service_rack_list = (Element)GSXML.getChildByTagName(service_cluster_info, GSXML.SERVICE_CLASS_ELEM+GSXML.LIST_MODIFIER);
+	if (service_rack_list == null) {
+	    // is this an error? could you ever have a service cluster
+	    // without service racks???
+	    logger.error("cluster has no service racks!!");
+	} else {
+	    
+	    if (!configureServiceRack(service_rack_list, null)) {
+		logger.error("couldn't configure the  service racks!!");
+		return false;
+	    }
+	}
+
+	return true;
+    }
+    
+    /** adds metadata from a metadataList into the metadata_list xml 
+     */
+    protected boolean addMetadata(Element metadata_list) {
+	if (metadata_list == null) return false;
+	NodeList metanodes = metadata_list.getElementsByTagName(GSXML.METADATA_ELEM);
+	if (metanodes.getLength()>0) { 	
+	    for(int k=0; k<metanodes.getLength(); k++) {
+		this.metadata_list.appendChild(this.doc.importNode(metanodes.item(k), true));
+	    }
+	}
+	
+	return true;
+    }
+
+    protected boolean addDisplayItems(Element display_list) {
+	
+	if (display_list==null) return false;
+	NodeList displaynodes = display_list.getElementsByTagName(GSXML.DISPLAY_TEXT_ELEM);
+	if (displaynodes.getLength()>0) { 	
+	    for(int k=0; k<displaynodes.getLength(); k++) {
+		Element d = (Element) displaynodes.item(k);
+		String lang = d.getAttribute(GSXML.LANG_ATT);
+		if (lang==null||lang.equals("")) {
+		    //set the lang to teh default
+		    d.setAttribute(GSXML.LANG_ATT, DEFAULT_LANG);
+		}
+		String name = d.getAttribute(GSXML.NAME_ATT);
+		Element this_item = GSXML.getNamedElement(this.display_item_list, GSXML.DISPLAY_TEXT_ELEM, GSXML.NAME_ATT, name);
+		if (this_item==null) {
+		    this_item = this.doc.createElement(GSXML.DISPLAY_TEXT_ELEM);
+		    this_item.setAttribute(GSXML.NAME_ATT, name);
+		    this.display_item_list.appendChild(this_item);
+		}
+		
+		this_item.appendChild(this.doc.importNode(d, true));
+		    
+		
+	    }
+	}
+	
+	return true;
+    }
+    
+    /** creates and configures all the services - extra_info is some more xml 
+that is passed to teh service  - eg used for coll config files for Collection
+    */
+    protected boolean configureServiceRack(Element service_rack_list, 
+					   Element extra_info) {
+
+	// empty the service map in case this is a reconfigure
+	service_map.clear();
+	this.service_list = this.doc.createElement(GSXML.SERVICE_ELEM+GSXML.LIST_MODIFIER);
+
+	// create all the services
+	NodeList nodes = service_rack_list.getElementsByTagName(GSXML.SERVICE_CLASS_ELEM);
+	if (nodes.getLength()==0) {
+	    logger.error("ServiceCluster configuration error: cluster "+this.cluster_name+" has no service modules!");
+	    return false;
+	}
+
+	for(int i=0; i<nodes.getLength(); i++) {
+	
+	    // the xml request to send to the serviceRack to query what
+	    // services it provides
+	    Element message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	    Element request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_DESCRIBE, "", "", "");
+	    message.appendChild(request);
+
+	    Element n = (Element)nodes.item(i);
+	    String servicetype = n.getAttribute(GSXML.NAME_ATT);
+	    
+	    try {
+		ServiceRack s = (ServiceRack)Class.forName("org.greenstone.gsdl3.service."+servicetype).newInstance();
+
+		s.setSiteHome(this.site_home);
+		s.setSiteAddress(this.site_http_address);
+		s.setClusterName(this.cluster_name);
+		s.setMessageRouter(this.router);
+		// pass the xml node to the service for configuration
+		if (s.configure(n, extra_info)) {
+		    
+		    // find out the supported service types for this service module
+		    Node types = s.process(message);
+		    NodeList typenodes = ((Element)types).getElementsByTagName(GSXML.SERVICE_ELEM);	   
+		    
+		    for (int j=0; j<typenodes.getLength();j++) {
+			String service = ((Element) typenodes.item(j)).getAttribute(GSXML.NAME_ATT);	   
+			if (service_map.get(service)!=null) {
+			    char extra = '0';
+			    String new_service = service+extra;	   
+
+			    while (service_map.get(new_service)!=null) {
+				extra++;
+				new_service = service+extra;
+			    }
+			    this.service_name_map.put(new_service, service);
+			    service=new_service;
+			    ((Element) typenodes.item(j)).setAttribute(GSXML.NAME_ATT, service);
+			}
+			this.service_map.put(service, s);
+			// also add info to the ServiceInfo XML element
+			this.service_list.appendChild(this.doc.importNode(typenodes.item(j), true));
+		    }
+		}
+	    } catch (Exception e) {
+		logger.error("configure exception: couldn't create service module:org.greenstone.gsdl3.service."+servicetype+"\n"+e.getMessage() + e.getClass() );
+		e.printStackTrace();
+		//return false;
+	    }
+	    
+	}
+	return true;
+	
+	
+    }
+
+
+    /**
+     * Process an XML document - uses Strings 
+     *  just calls process(Node).
+     *
+     * @param in the Document to process - a string
+     * @return the resultant document as a string - contains any error messages
+     * @see String
+     */
+    public String process(String in) {
+
+	Document doc = this.converter.getDOM(in);
+	Element e = doc.getDocumentElement();
+	
+	Element res = process(e);
+	return this.converter.getString(res);
+	
+    }
+    
+    /** process XML as Node
+     *
+     */
+    public Element process(Element message) {
+
+	NodeList requests = message.getElementsByTagName(GSXML.REQUEST_ELEM);
+	Document mess_doc = message.getOwnerDocument();
+	Element mainResult = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	if (requests.getLength()==0) {
+	    logger.error("no requests for cluster:"+this.cluster_name);
+	    // no requests
+	    return mainResult; // for now
+	}
+	for (int i=0; i<requests.getLength(); i++) {
+	    Element request = (Element)requests.item(i);
+	    String to = request.getAttribute(GSXML.TO_ATT);
+
+	    // the cluster name should be first, check, then remove
+	    String clustername = GSPath.getFirstLink(to);
+	    if (!clustername.equals(this.cluster_name)){ 
+		logger.error("cluster name wrong! was "+clustername+" should have been "+this.cluster_name);
+		continue; // ignore this request
+	    }
+	    to = GSPath.removeFirstLink(to);
+	    request.setAttribute(GSXML.TO_ATT, to);
+	   
+	    if (to.equals("")) { // this command is for me
+		Element response = processMessage(request);
+		mainResult.appendChild(response);
+		
+	    } else { // the request is for one of my services
+		String service = GSPath.getFirstLink(to);
+		
+		if (!this.service_map.containsKey(service)) {
+		    logger.error("non-existant service, "+service+", specified!");
+		    continue;
+		}
+		String real_service = service;
+		if (this.service_name_map.containsKey(service)) {
+		    real_service = (String)this.service_name_map.get(service);
+		    // need to change the to att in the request - give the real service name
+		    to = request.getAttribute(GSXML.TO_ATT);
+		    String old_to = to;
+		    to = GSPath.replaceFirstLink(to, real_service);
+		    request.setAttribute(GSXML.TO_ATT, to);
+		}
+		// have to pass the request to the service
+		Element single_message = mess_doc.createElement(GSXML.MESSAGE_ELEM);
+		single_message.appendChild(request);
+		Element response_message = ((ModuleInterface)this.service_map.get(service)).process(single_message);
+		if (response_message != null) {
+		    Element response = (Element) GSXML.getChildByTagName(response_message, GSXML.RESPONSE_ELEM);
+		    String from = response.getAttribute(GSXML.FROM_ATT);
+		    if (!real_service.equals(service)) {
+			// replace the real service name with the pseudo service name
+			from = GSPath.replaceFirstLink(from, service);
+			// also need to do it in the service itself
+			// shoudl this be done here??
+			Element service_elem = (Element) GSXML.getChildByTagName(response, GSXML.SERVICE_ELEM);
+			if (service_elem!= null) {
+			    service_elem.setAttribute(GSXML.NAME_ATT, service);
+			}
+		    }
+		    from = GSPath.prependLink(from, this.cluster_name);
+		    response.setAttribute(GSXML.FROM_ATT, from);
+		    mainResult.appendChild(this.doc.importNode(response, true));
+		}
+		  
+	    } // else
+		
+	   
+	} // for each request
+	return mainResult;
+    }
+
+    /** handles requests made to the ServiceCluster itself 
+     *
+     * @param req - the request Element- <request>
+     * @return the result Element - should be <response>
+     */
+    protected Element processMessage(Element request) {
+
+	Element response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	response.setAttribute(GSXML.FROM_ATT, this.cluster_name);
+	String type = request.getAttribute(GSXML.TYPE_ATT);
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	response.setAttribute(GSXML.TYPE_ATT, type);
+	
+	if (type.equals(GSXML.REQUEST_TYPE_DESCRIBE)) {
+	    // create the collection element
+	    Element description = (Element)this.description.cloneNode(false);
+	    response.appendChild(description);
+	    // check the param list
+	    Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	    if (param_list == null) {
+		addAllDisplayInfo(description, lang);
+		description.appendChild(this.service_list);
+		description.appendChild(this.metadata_list);
+		return response;
+	    }
+	    
+	    // go through the param list and see what components are wanted
+	    NodeList params = param_list.getElementsByTagName(GSXML.PARAM_ELEM);
+	    for (int i=0; i<params.getLength(); i++) {
+		
+		Element param = (Element)params.item(i);
+		// Identify the structure information desired
+		if (param.getAttribute(GSXML.NAME_ATT).equals(GSXML.SUBSET_PARAM)) {
+		    String info = param.getAttribute(GSXML.VALUE_ATT);
+		    if (info.equals(GSXML.SERVICE_ELEM+GSXML.LIST_MODIFIER)) {
+			description.appendChild(this.service_list);
+		    } else if (info.equals(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER)) {
+			description.appendChild(metadata_list);
+		    } else if (info.equals(GSXML.DISPLAY_TEXT_ELEM+GSXML.LIST_MODIFIER)) {
+			addAllDisplayInfo(description, lang);
+			
+		    }
+		}
+	    }
+	    return response;
+	}
+	
+	if (type.equals(GSXML.REQUEST_TYPE_SYSTEM)) {
+	    response = processSystemRequest(request);
+	} else { // unknown type
+	    logger.error("cant handle request of type "+ type);
+	    
+	}
+	return response;
+    }
+
+    protected Element processSystemRequest(Element request) {
+
+	Element response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	response.setAttribute(GSXML.FROM_ATT, this.cluster_name);
+	response.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_SYSTEM);
+
+	// a list of system requests - should put any error messages
+	// or success messages into response
+	NodeList commands = request.getElementsByTagName(GSXML.SYSTEM_ELEM);
+	String message=null;	
+	for (int i=0; i<commands.getLength(); i++) {
+	    // all the commands should be Elements
+	    Element elem = (Element)commands.item(i);
+	    String action = elem.getAttribute(GSXML.TYPE_ATT);
+	    if (action.equals(GSXML.SYSTEM_TYPE_CONFIGURE)) {
+		String subset = elem.getAttribute(GSXML.SYSTEM_SUBSET_ATT);
+		if (subset.equals("")) {
+		    // need to reconfigure the service cluster
+		    
+		    if (this.configure()) {
+			Element s = GSXML.createTextElement(this.doc, GSXML.STATUS_ELEM, this.cluster_name + " reconfigured");
+			response.appendChild(s);
+			
+		    } else {
+			Element s = GSXML.createTextElement(this.doc, GSXML.STATUS_ELEM, this.cluster_name + " could not be reconfigured");
+			response.appendChild(s); 
+		    }
+		} else if (this.configureSubset(subset)) {
+		    Element s = GSXML.createTextElement(this.doc, GSXML.STATUS_ELEM, this.cluster_name + " "+subset+" reconfigured");
+		    response.appendChild(s);
+		} else {
+		    Element s = GSXML.createTextElement(this.doc, GSXML.STATUS_ELEM, this.cluster_name + " "+subset + " could not be reconfigured");
+		    response.appendChild(s); 
+		}
+		continue;
+	    } // configure action
+	    
+	    String module_name = elem.getAttribute(GSXML.SYSTEM_MODULE_NAME_ATT);
+	    String module_type = elem.getAttribute(GSXML.SYSTEM_MODULE_TYPE_ATT);
+	    if (action.equals(GSXML.SYSTEM_TYPE_ACTIVATE)) {
+		Element s = GSXML.createTextElement(this.doc, GSXML.STATUS_ELEM, "activate action not yet implemented - does it even make sense in this context??");
+		response.appendChild(s);
+	    } else if (action.equals(GSXML.SYSTEM_TYPE_DEACTIVATE)) {
+		if (module_type.equals(GSXML.SERVICE_ELEM)) {
+		    // deactivate the service
+		    // remove from service_map
+		    this.service_map.remove(module_name);
+		    Element service_elem = GSXML.getNamedElement(this.service_list, GSXML.SERVICE_ELEM, GSXML.NAME_ATT, module_name);
+		    service_list.removeChild(service_elem);		    
+		    message = module_type+": "+module_name+" deactivated";
+		} else {
+		    message = "can't deactivate "+module_type+" type modules!";}
+		Element s = GSXML.createTextElement(this.doc, GSXML.STATUS_ELEM, message);
+		response.appendChild(s);
+	    } else {
+		logger.error("cant process system request, action "+action);
+		continue;
+	    }
+	} // for each command
+	return response;
+    }
+
+    /** 
+     * do a configure on only part of the collection
+     */
+    protected boolean configureSubset(String subset) {
+	
+	File configFile = new File(GSFile.siteConfigFile(this.site_home));
+	if (!configFile.exists() ) {
+	    logger.error("site config file: "+configFile.getPath()+" not found!");
+	    // wont be able to do any of the requests
+	    return false;
+	    
+	}
+	
+	Document site_config_doc  = this.converter.getDOM(configFile);
+	if (site_config_doc == null) {
+	    logger.error("could not read in site config file: "+configFile.getPath());
+	    return false;
+	}
+	
+	Element site_config_elem = site_config_doc.getDocumentElement();
+	Element cluster_config_elem = GSXML.getNamedElement((Element)GSXML.getChildByTagName(site_config_elem, GSXML.CLUSTER_ELEM+GSXML.LIST_MODIFIER), GSXML.CLUSTER_ELEM, GSXML.NAME_ATT, this.cluster_name);
+	if (cluster_config_elem == null) {
+	    logger.error("site config file: "+configFile.getPath()+" has no element for cluster "+this.cluster_name);
+	    // wont be able to do any of teh requests
+	    return false;
+	    
+	}
+	if (subset.equals(GSXML.SERVICE_ELEM+GSXML.LIST_MODIFIER)) {
+	    Element service_rack_list = (Element)GSXML.getChildByTagName(cluster_config_elem, GSXML.SERVICE_CLASS_ELEM+GSXML.LIST_MODIFIER);
+	    
+	    return configureServiceRack(service_rack_list, null);
+	} else if (subset.equals(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER)) {
+	    this.metadata_list = this.doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
+	    Element metadata_list = (Element)GSXML.getChildByTagName(cluster_config_elem, GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
+	    return addMetadata(metadata_list);
+	} else {
+	    logger.error("cannot process system request, configure "+subset);
+	    return false;
+	} 
+
+    } 
+
+
+    protected boolean addAllDisplayInfo(Element description, String lang) {
+	
+	NodeList items = this.display_item_list.getChildNodes();
+	for (int i=0; i<items.getLength(); i++) { // for each key
+	    Element m = (Element) items.item(i);
+	    // find the child with the correct language
+	    Element new_m = GSXML.getNamedElement(m, GSXML.DISPLAY_TEXT_ELEM, GSXML.LANG_ATT, lang);
+	    if (new_m==null && lang != DEFAULT_LANG) {
+		// use the default lang
+		new_m = GSXML.getNamedElement(m, GSXML.DISPLAY_TEXT_ELEM, GSXML.LANG_ATT, DEFAULT_LANG);
+	    }
+	    if (new_m==null) {
+		// just get the first one
+		new_m = (Element)GSXML.getChildByTagName(m, GSXML.DISPLAY_TEXT_ELEM);
+	    }
+	    description.appendChild(new_m.cloneNode(true));
+	}
+	return true;
+	
+    }
+
+    
+    protected Element getDisplayTextElement(String key, String lang) {
+	
+	Element this_item = GSXML.getNamedElement(this.display_item_list, GSXML.DISPLAY_TEXT_ELEM, GSXML.NAME_ATT, key);
+	if (this_item == null) {
+	    return null;
+	}
+
+	Element this_lang = GSXML.getNamedElement(this_item, GSXML.DISPLAY_TEXT_ELEM, GSXML.LANG_ATT, lang);
+	if (this_lang == null && lang != DEFAULT_LANG) {
+	    // try the default
+	    this_lang = GSXML.getNamedElement(this_item, GSXML.DISPLAY_TEXT_ELEM, GSXML.LANG_ATT, DEFAULT_LANG);
+	}
+	if (this_lang == null) {
+	    // just return the first one
+	    return (Element)this_item.getFirstChild().cloneNode(true);
+	}
+	return (Element)this_lang.cloneNode(true);
+	
+    }
+}
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/collection/XMLCollection.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/collection/XMLCollection.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/collection/XMLCollection.java	(revision 13928)
@@ -0,0 +1,118 @@
+package org.greenstone.gsdl3.collection;
+
+import org.greenstone.gsdl3.util.*;
+import org.greenstone.gsdl3.core.*;
+import org.greenstone.gsdl3.service.*;
+
+
+// java XML classes we're using
+import org.w3c.dom.Document; 
+import org.w3c.dom.Node; 
+import org.w3c.dom.Element; 
+import org.w3c.dom.NodeList; 
+
+import java.io.File;
+import java.util.HashMap;
+
+import org.apache.log4j.*;
+
+/* for a collection that hasn't been built with greenstone build stuff. expects a documentList in the collectionConfig file, and it stores this. this is where doc level metadata comes from */
+public class XMLCollection 
+    extends Collection {
+
+     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.collection.XMLCollection.class.getName());
+
+    protected Element document_list = null;
+    /** overwrite this to keep the document list
+     * find the metadata and display elems from the two config files and add it to the appropriate lists
+     */
+    protected boolean findAndLoadInfo(Element coll_config_xml, 
+				      Element build_config_xml){
+
+	// metadata
+	Element meta_list = (Element)GSXML.getChildByTagName(coll_config_xml, GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
+	addMetadata(meta_list);
+	meta_list = (Element)GSXML.getChildByTagName(build_config_xml, GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
+	addMetadata(meta_list);
+
+	meta_list = this.doc.createElement(GSXML.METADATA_ELEM + GSXML.LIST_MODIFIER);
+	GSXML.addMetadata(this.doc, meta_list, "httpPath", this.site_http_address+"/collect/"+this.cluster_name);
+	addMetadata(meta_list);
+
+	// display stuff
+	Element display_list = (Element)GSXML.getChildByTagName(coll_config_xml, GSXML.DISPLAY_TEXT_ELEM+GSXML.LIST_MODIFIER);
+	if (display_list != null) {
+	    addDisplayItems(display_list);
+	}
+
+	Element config_doc_list = (Element)GSXML.getChildByTagName(coll_config_xml, GSXML.DOCUMENT_ELEM+GSXML.LIST_MODIFIER);
+	if (config_doc_list != null) {
+	    document_list = (Element)this.doc.importNode(config_doc_list, true);
+	} else {
+	    document_list = this.doc.createElement(GSXML.DOCUMENT_ELEM+GSXML.LIST_MODIFIER);
+	}
+	return true;
+
+    }
+
+    /** handles requests made to the ServiceCluster itself 
+     *
+     * @param req - the request Element- <request>
+     * @return the result Element - should be <response>
+     */
+    protected Element processMessage(Element request) {
+
+	Element response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	response.setAttribute(GSXML.FROM_ATT, this.cluster_name);
+	String type = request.getAttribute(GSXML.TYPE_ATT);
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	response.setAttribute(GSXML.TYPE_ATT, type);
+	
+	if (type.equals(GSXML.REQUEST_TYPE_DESCRIBE)) {
+	    // create the collection element
+	    Element description = (Element)this.description.cloneNode(false);
+	    response.appendChild(description);
+	    // check the param list
+	    Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	    if (param_list == null) {
+		addAllDisplayInfo(description, lang);
+		description.appendChild(this.service_list);
+		description.appendChild(this.metadata_list);
+		description.appendChild(this.document_list);
+		return response;
+	    }
+	    
+	    // go through the param list and see what components are wanted
+	    NodeList params = param_list.getElementsByTagName(GSXML.PARAM_ELEM);
+	    for (int i=0; i<params.getLength(); i++) {
+		
+		Element param = (Element)params.item(i);
+		// Identify the structure information desired
+		if (param.getAttribute(GSXML.NAME_ATT) == GSXML.SUBSET_PARAM ) {
+		    String info = param.getAttribute(GSXML.VALUE_ATT);
+		    if (info.equals(GSXML.SERVICE_ELEM+GSXML.LIST_MODIFIER)) {
+			description.appendChild(this.service_list);
+		    } else if (info.equals(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER)) {
+			description.appendChild(metadata_list);
+		    } else if (info.equals(GSXML.DISPLAY_TEXT_ELEM+GSXML.LIST_MODIFIER)) {
+			addAllDisplayInfo(description, lang);
+			
+		    } else if (info.equals(GSXML.DOCUMENT_ELEM+GSXML.LIST_MODIFIER)) {
+			description.appendChild(this.document_list);
+		    }
+		    
+		}
+	    }
+	    return response;
+	}
+	
+	if (type.equals(GSXML.REQUEST_TYPE_SYSTEM)) {
+	    response = processSystemRequest(request);
+	} else { // unknown type
+	    logger.error("cant handle request of type "+ type);
+	    
+	}
+	return response;
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/comms/Communicator.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/comms/Communicator.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/comms/Communicator.java	(revision 13928)
@@ -0,0 +1,69 @@
+/*
+ *    Communicator.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.comms;
+
+import org.greenstone.gsdl3.core.ModuleInterface;
+import org.greenstone.gsdl3.util.*;
+
+//XML packages
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/** Communicator - base class for Modules that talk via some protocol to other modules
+ *
+ * can be used by a MessageRouter - in this case set localSiteName
+ * can be used by any other module - in this case it has no local site - dont set localsiteName. the setting of localSiteName affects the handling of teh to and from fields in the message. 
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ * @version $Revision$
+ */
+abstract public class Communicator
+    implements ModuleInterface {
+
+    /** name of local site */
+    protected String local_site_name_ = null;
+
+    /** name of site to connect to */
+    protected String remote_site_name_=null;
+
+    /** converter for String to DOM and vice versa */
+    protected XMLConverter converter_= null;
+
+    public Communicator() {
+	converter_ = new XMLConverter();
+    }
+    public void cleanUp() {}
+
+    public void setLocalSiteName(String name) {
+	local_site_name_ = name;
+    }
+    /** this should be done as part of configure */
+    public void setRemoteSiteName(String name) {
+	remote_site_name_ = name;
+    }
+    /** configures the Communicator using the <site> element */
+    abstract public boolean configure(Element site_elem); 
+
+    public String process(String xml_in) {
+	Element e = converter_.getDOM(xml_in).getDocumentElement();
+	Node result = process(e);
+	return converter_.getString(result);	
+    }
+
+    abstract public Element process(Element xml_in);
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/comms/SOAPCommunicator.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/comms/SOAPCommunicator.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/comms/SOAPCommunicator.java	(revision 13928)
@@ -0,0 +1,173 @@
+/*
+ *    SOAPCommunicator.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.comms;
+
+import org.greenstone.gsdl3.util.*;
+import org.greenstone.gsdl3.core.*;
+
+// classes needed for SOAP stuff
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.util.Vector;
+import org.apache.axis.client.Call;
+import org.apache.axis.client.Service;
+import org.apache.axis.message.SOAPBodyElement;
+import javax.xml.namespace.QName;
+
+import org.w3c.dom.Node; 
+import org.w3c.dom.NodeList; 
+import org.w3c.dom.Document; 
+import org.w3c.dom.Element; 
+
+import org.apache.log4j.*;
+
+/*
+ * The Client side of a SOAP Connection
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ * @version $Revision$
+ * @see <a href="http://www.w3.org/TR/SOAP/">Simple Object Access Protocol (SOAP) 1.1 </a>
+ */
+public class SOAPCommunicator
+    extends Communicator {
+
+      static Logger logger = Logger.getLogger(org.greenstone.gsdl3.comms.SOAPCommunicator.class.getName());
+
+    /** address of site to connect to */
+    protected String remote_site_address_=null;
+
+    /** the call object that does the SOAP talking */
+    private Call call_ = null;
+
+  /** The no-args constructor */
+    public SOAPCommunicator() {
+	
+    }
+        
+    public boolean configure(Element site_elem) {
+	
+	String type = site_elem.getAttribute(GSXML.TYPE_ATT);
+	if (!type.equals(GSXML.COMM_TYPE_SOAP_JAVA)) {
+	    logger.error("wrong type of site");
+	    return false;
+	}
+	remote_site_name_ = site_elem.getAttribute(GSXML.NAME_ATT);
+	if (remote_site_name_.equals("")) {
+	    logger.error("must have name attribute in site element");
+	    return false;
+	}
+	remote_site_address_ = site_elem.getAttribute(GSXML.ADDRESS_ATT);
+	String local_site_name = site_elem.getAttribute(GSXML.LOCAL_SITE_ATT);
+	if (remote_site_address_.equals("") && local_site_name.equals("")) {
+	    logger.error("must have address or localSite attributes in site element");
+	    return false;
+	}
+	if (remote_site_address_.equals("")) {
+	    remote_site_address_ = GlobalProperties.getGSDL3WebAddress()+"/services/"+local_site_name;
+	}
+
+	try {
+	    Service service = new Service();
+	    call_ = (Call) service.createCall();
+	    call_.setTargetEndpointAddress( new java.net.URL(remote_site_address_) );
+	} catch (Exception e) {
+	    logger.error("SOAPCommunicator.configure() Error: Exception occurred "+e);
+	    return false;
+	}
+	return true;
+    }
+
+    public Element process(Element message) {
+	
+	NodeList requests = message.getElementsByTagName(GSXML.REQUEST_ELEM);
+	if (requests.getLength()==0) {
+	    // no requests
+	    return null;
+	}
+
+	// if the communicator is part of a site, it needs to edit the to and from fields, otherwise it just passes the message on, as is
+	// for now, use local_site_name_ as the flag.
+	if (local_site_name_!=null) { // no local site
+	    
+	    for (int i=0;i<requests.getLength(); i++) {
+		Element e = (Element)requests.item(i);
+		String to = e.getAttribute(GSXML.TO_ATT);
+		to = GSPath.removeFirstLink(to); // remove the server name, should check that it is present
+		e.setAttribute(GSXML.TO_ATT, to);
+		String from = e.getAttribute(GSXML.FROM_ATT);
+		from = GSPath.appendLink(from, local_site_name_);
+		e.setAttribute(GSXML.FROM_ATT, from);
+	    }
+	}
+	// else do nothing to the requests, just pass it on
+
+	// the soap impl needs a namespace for the top level element
+	Element message_to_send = message;
+	if (message.getNamespaceURI() == null) {
+	    message_to_send = GSXML.duplicateWithNewNameNS(message.getOwnerDocument(), message, "gs3:"+message.getTagName(), "urn:foo", true);
+	}
+	
+	// do the soap query
+	Element result = null;
+	try {
+	    SOAPBodyElement[] input = new SOAPBodyElement[1];
+	    input[0] = new SOAPBodyElement(message_to_send);
+	    Vector output = (Vector) call_.invoke( input );
+	    SOAPBodyElement elem = (SOAPBodyElement) output.get(0);
+	    result = elem.getAsDOM();
+	} catch (Exception e) {
+	    e.printStackTrace();
+	    return null;
+	}
+	
+	if (local_site_name_ != null) {// have to modify the from field
+	    
+	    NodeList responses = result.getElementsByTagName(GSXML.RESPONSE_ELEM);
+	    for (int i=0;i<responses.getLength(); i++) {
+		Element e = (Element)responses.item(i);
+		String from = e.getAttribute(GSXML.FROM_ATT);
+		from = GSPath.prependLink(from, remote_site_name_);
+		e.setAttribute(GSXML.FROM_ATT, from);
+	    }
+	} // else return as is
+	
+	return result;
+    }
+
+    public static void main (String [] args) {
+	SOAPCommunicator comm = new SOAPCommunicator();
+	XMLConverter converter = new XMLConverter();
+	String message = "<site name=\"localsite\" address=\"http://kanuka.cs.waikato.ac.nz:7070/axis/services/localsite\" type=\"soap\"/>";
+	Element site_elem = converter.getDOM(message).getDocumentElement();
+	comm.configure(site_elem);
+	message = "<message><request type=\"describe\" to=\"\" lang=\"en\"/></message>";
+	Element request_elem = converter.getDOM(message).getDocumentElement();
+	Element response = comm.process(request_elem);
+	
+	logger.error("response was "+converter.getPrettyString(response));
+    }
+}
+
+
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/core/DefaultReceptionist.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/core/DefaultReceptionist.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/core/DefaultReceptionist.java	(revision 13928)
@@ -0,0 +1,163 @@
+package org.greenstone.gsdl3.core;
+
+import org.greenstone.gsdl3.util.*;
+import org.greenstone.gsdl3.action.*;
+// XML classes
+import org.w3c.dom.Node; 
+import org.w3c.dom.NodeList; 
+import org.w3c.dom.Document; 
+import org.w3c.dom.Element; 
+
+// other java classes
+import java.io.File;
+import java.util.HashMap;
+import java.util.Enumeration;
+
+import org.apache.log4j.*;
+
+/** The default greenstone receptionist - needs some extra info for each page
+ */
+public class DefaultReceptionist extends TransformingReceptionist {
+
+     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.core.DefaultReceptionist.class.getName());
+    
+    protected void addExtraInfo(Element page) {
+	// we want to add in the collection description for each page - cos
+	// our default xslt needs this.
+	super.addExtraInfo(page);
+	
+	Element page_request = (Element)GSXML.getChildByTagName(page, GSXML.PAGE_REQUEST_ELEM);
+	// if it is a system request, then we don't bother with this.
+	String action = page_request.getAttribute(GSXML.ACTION_ATT);
+	if (action.equals("s")) {
+	    logger.error("HACK: don't ask for coll info if system action");
+	    return;
+	}
+	logger.debug("add extra info, page request="+this.converter.getString(page_request));
+	// is a collection defined?
+	Element param_list = (Element)GSXML.getChildByTagName(page_request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	if (param_list==null) { // must be the original home page
+	    logger.debug(" no param list, assuming home page");
+	    return;
+	}
+	Element coll_param = GSXML.getNamedElement(param_list, GSXML.PARAM_ELEM, GSXML.NAME_ATT, GSParams.COLLECTION);
+	if (coll_param == null) {
+	    logger.debug(" coll param is null, returning");
+	    return;
+	}
+
+	// see if the collection/cluster element is already there
+	String coll_name = coll_param.getAttribute(GSXML.VALUE_ATT);
+	String lang = page_request.getAttribute(GSXML.LANG_ATT);
+	String uid = page_request.getAttribute(GSXML.USER_ID_ATT);
+	
+	boolean get_service_description = false;
+	Element page_response = (Element)GSXML.getChildByTagName(page, GSXML.PAGE_RESPONSE_ELEM);
+	if (this.language_list != null) {
+	    page_response.appendChild(this.language_list);
+	}
+	Element coll_description = (Element)GSXML.getChildByTagName(page_response, GSXML.COLLECTION_ELEM);
+	if (coll_description == null) {
+	    // try cluster
+	    coll_description = (Element)GSXML.getChildByTagName(page_response, GSXML.CLUSTER_ELEM);
+	}
+	if (coll_description == null) { 
+	    // we dont have one yet - get it
+	    Element coll_about_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	    Element coll_about_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_DESCRIBE,  coll_name, lang, uid);
+	    coll_about_message.appendChild(coll_about_request);
+	    
+	    Element coll_about_response_message = this.mr.process(coll_about_message);
+	    Element coll_about_response = (Element)GSXML.getChildByTagName(coll_about_response_message, GSXML.RESPONSE_ELEM);
+	    if (coll_about_response == null) {
+		return;
+	    }
+	    coll_description = (Element)GSXML.getChildByTagName(coll_about_response, GSXML.COLLECTION_ELEM);
+	    if (coll_description==null) { // may be a cluster
+		coll_description = (Element)GSXML.getChildByTagName(coll_about_response, GSXML.CLUSTER_ELEM);
+	    }
+	    
+	    if (coll_description == null) {
+		logger.error(" no collection description, returning");
+		return;
+	    }
+	    // have found one, append it to the page response
+	    coll_description = (Element)this.doc.importNode(coll_description, true);
+	    page_response.appendChild(coll_description);
+	    get_service_description = true;
+	}
+
+	// have got a coll description
+	
+	// now get the dispay info for the services
+	Element service_list = (Element)GSXML.getChildByTagName(coll_description, GSXML.SERVICE_ELEM+GSXML.LIST_MODIFIER);
+	if (service_list == null) {
+	    logger.error(" no service list, returning");
+	    // something weird has gone wrong
+	    return;
+	}
+
+	NodeList services = service_list.getElementsByTagName(GSXML.SERVICE_ELEM);
+	if (services.getLength()==0) {
+	    logger.error("DefaultReceoptionist: no services found for colllection/cluster "+ coll_name);
+	    return;
+	}
+	// check one service for display items
+	if (!get_service_description) {
+	    // we dont know yet if we need to get these
+	    int i=1;
+	    Element test_s = (Element)services.item(0);
+	    while (i<services.getLength() && test_s.getAttribute(GSXML.TYPE_ATT).equals(GSXML.SERVICE_TYPE_RETRIEVE)) {
+		test_s = (Element)services.item(i); i++;
+	    }
+	    if (i==services.getLength()) {
+		// we have only found retrieve services, so dont need descripitons anyway
+		return;
+	    }
+	    if (GSXML.getChildByTagName(test_s, GSXML.DISPLAY_TEXT_ELEM) !=null) {
+		// have got descriptions already, 
+		return;
+	    }
+	}
+
+	// if get here, we need to get the service descriptions
+	logger.debug("getting services description");
+	    
+	// we will send all the requests in a single message
+	Element info_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	for (int i=0; i<services.getLength(); i++) {
+	    Element c = (Element)services.item(i);
+	    String name = c.getAttribute(GSXML.NAME_ATT);
+	    String address = GSPath.appendLink(coll_name, name);
+	    Element info_request = GSXML.createBasicRequest(this.doc,  GSXML.REQUEST_TYPE_DESCRIBE, address, lang, uid);
+	    Element req_param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	    req_param_list.appendChild(GSXML.createParameter(this.doc, GSXML.SUBSET_PARAM, GSXML.DISPLAY_TEXT_ELEM+GSXML.LIST_MODIFIER));
+	    info_request.appendChild(req_param_list);
+	    info_message.appendChild(info_request);
+	    
+	}
+
+	Element info_response = (Element)this.mr.process(info_message);
+
+	NodeList service_responses = info_response.getElementsByTagName(GSXML.RESPONSE_ELEM);
+	// check that have same number of responses as collections
+	if (services.getLength() != service_responses.getLength()) {
+	    logger.error(" didn't get a response for each service - somethings gone wrong!");
+	    // for now, dont use the metadata
+	} else {
+	    for (int i=0; i<services.getLength(); i++) {
+		Element c1 = (Element)services.item(i);
+		Element c2 = (Element)GSXML.getChildByTagName((Element)service_responses.item(i), GSXML.SERVICE_ELEM);
+		if (c1.getAttribute(GSXML.NAME_ATT).equals(c2.getAttribute(GSXML.NAME_ATT))) {
+		    //add the service data into the original response
+		    GSXML.mergeElements(c1, c2);
+		} else {
+		    logger.error(" response does not correspond to request!");
+		} 
+		
+	    }
+	}
+	
+    }
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/core/GSException.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/core/GSException.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/core/GSException.java	(revision 13928)
@@ -0,0 +1,50 @@
+/*
+ *    GSException.java
+ *    a new exception for Greenstone
+
+ *    Copyright (C) 2005 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.core;
+
+import org.greenstone.gsdl3.util.GSXML;
+
+public class GSException
+    extends Exception {
+
+    private String exception_type = null;
+    // need some better names for these
+    //public static int PERMANENT = 0;
+    //public static int TEMPORARY = 1;
+    //public static int OTHER = 2;
+
+    public GSException(String message) {
+	
+	super(message);
+	this.exception_type = GSXML.ERROR_TYPE_OTHER;
+    }
+    public GSException(String message, String type) {
+
+	super(message);
+	this.exception_type = type;
+    }
+
+    public String getType() {
+	return exception_type;
+    }
+	
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/core/MessageRouter.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/core/MessageRouter.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/core/MessageRouter.java	(revision 13928)
@@ -0,0 +1,940 @@
+/*
+ *    MessageRouter.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.core;
+
+import org.greenstone.gsdl3.util.*;
+import org.greenstone.gsdl3.service.*;
+import org.greenstone.gsdl3.comms.*;
+import org.greenstone.gsdl3.collection.*;
+
+// XML classes
+import org.w3c.dom.Node; 
+import org.w3c.dom.NodeList; 
+import org.w3c.dom.Document; 
+import org.w3c.dom.Element; 
+import org.xml.sax.InputSource;
+import javax.xml.parsers.*;
+
+// other java classes
+import java.io.File;
+import java.io.Reader;
+import java.io.StringReader;
+import java.net.Authenticator;
+import java.net.PasswordAuthentication;      
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Properties;
+
+import org.apache.log4j.*;
+
+/**
+ * The hub of a Greenstone system. 
+ *
+ * Accepts  XML requests (via process method of ModuleInterface) and routes them to the appropriate collection or 
+ * service or external entity.
+ *
+ * contains a map of module objects - may be services, collections, comms 
+ * objects talking to other MessageRouters etc.
+ *
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ * @version $Revision$
+ * @see ModuleInterface
+ * @see Collection
+ * @see ServiceRack
+ * @see Communicator
+ *
+ */
+public class MessageRouter implements  ModuleInterface {
+
+     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.core.MessageRouter.class.getName());
+
+    /** the (directory) name of the site */
+    protected String site_name = null;
+    /** site home - the home directory for the site */
+    protected String site_home=null;
+    /** the http address for this site */
+    protected String site_http_address=null;
+    
+    /** map of names to Module objects */
+    protected HashMap module_map=null;
+
+    /** container Document to create XML Nodes */
+    protected Document doc=null; 
+    /** the full description of this site */
+
+    // should these things be separated into local and remote??
+
+    /** the original xml config element */
+    public Element config_info = null;
+
+    /** list of collections that can be reached */
+    protected Element collection_list = null; 
+    /** list of service clusters that can be reached */
+    protected Element cluster_list = null; 
+    /** list of single services that can be reached */
+    protected Element service_list = null; 
+    /** list of sites that can be reached */
+    protected Element site_list = null; 
+    
+   
+    /** a converter class to parse XML and create Docs */
+    protected XMLConverter converter=null;
+
+    //***************************************************************
+    // public methods
+    //***************************************************************
+
+    /** constructor */
+    public MessageRouter() {
+	this.converter = new XMLConverter();
+	this.doc = this.converter.newDOM();
+    }
+
+    public void cleanUp() {
+	if (this.module_map != null) {
+	    Iterator i = this.module_map.values().iterator();
+	    while (i.hasNext()) {
+		((ModuleInterface)i.next()).cleanUp();
+	    }
+	}
+    }
+
+    /** site_name must be set before configure is called */
+    public void setSiteName(String site_name) {
+	this.site_name = site_name;
+    }
+    /**
+     * configures the system
+     *
+     * looks in site_home/collect for collections, reads config file
+     * site_home/siteConfig.xml
+     *
+     */
+    public boolean configure() { 
+
+	logger.info("configuring site");
+
+	if (this.site_name==null) {
+	    logger.error(" You must set site_name before calling configure");
+	    return false;
+	}
+	this.site_home = GSFile.siteHome(GlobalProperties.getGSDL3Home(), this.site_name);
+	this.site_http_address = GlobalProperties.getGSDL3WebAddress()+"/sites/"+this.site_name;
+	
+	// are we behind a firewall?? - is there a better place to set up the proxy?
+	String host = GlobalProperties.getProperty("proxy.host");
+	String port = GlobalProperties.getProperty("proxy.port");
+	final String user = GlobalProperties.getProperty("proxy.user");
+	final String passwd = GlobalProperties.getProperty("proxy.password");
+	  
+	if (host != null && !host.equals("") && port !=null && !port.equals("")) {
+	    System.setProperty("http.proxyType", "4");
+	    System.setProperty("http.proxyHost", host);
+	    System.setProperty("http.proxyPort", port);
+	    System.setProperty("http.proxySet", "true");
+	    // have we got a user/password?
+	    if (user != null && !user.equals("") && passwd != null && !passwd.equals("")) {
+		try {
+		    // set up the authenticator
+		    Authenticator.setDefault(new Authenticator(){ 
+			    protected PasswordAuthentication getPasswordAuthentication(){ 
+				return new PasswordAuthentication(user, new String(passwd).toCharArray()); 
+			    } 
+			}); 
+		    
+		} catch (Exception e) {
+		    logger.error("MessageRouter Error: couldn't set up an authenticator the proxy");
+		    
+		}
+	    }
+	}
+
+	// read thru own config file - create services and connect to sites
+	File configFile = new File(GSFile.siteConfigFile(this.site_home));
+
+	if (!configFile.exists() ) {
+	    logger.error(" site config file: "+configFile.getPath()+" not found!");
+	    return false;
+	}
+	
+	Document config_doc = this.converter.getDOM(configFile);
+	if (config_doc == null) {
+logger.error(" couldn't parse site config file: "+configFile.getPath());
+	    return false;
+	}
+	
+	config_info = config_doc.getDocumentElement();
+	
+	this.module_map = new HashMap();
+	
+	// load up the services
+	Element service_rack_list = (Element)GSXML.getChildByTagName(config_info, GSXML.SERVICE_CLASS_ELEM+GSXML.LIST_MODIFIER);
+	configureServices(service_rack_list);
+	
+	// load up the service clusters
+	Element cluster_list = (Element)GSXML.getChildByTagName(config_info, GSXML.CLUSTER_ELEM+GSXML.LIST_MODIFIER);	
+	configureClusters(cluster_list);
+
+	// load up the collections
+	configureCollections();
+
+	// load up the external sites - this also adds their services/clusters/collections to the other lists - so must be done last
+	Element site_list = (Element)GSXML.getChildByTagName(config_info, GSXML.SITE_ELEM+GSXML.LIST_MODIFIER);
+	configureSites(site_list);
+	
+		
+	return true;
+	
+    }
+ 	
+   
+    /**
+     * Process an XML request - as a String
+     *
+     * @param xml_in the request to process
+     * @return the response - contains any error messages
+     * @see String
+     */
+    public String process(String xml_in) {
+	
+	Document doc = this.converter.getDOM(xml_in);
+	
+	Element result = process(doc.getDocumentElement());
+	return this.converter.getString(result);
+    }
+    
+    /**
+     * Process an XML request - as a DOM Element
+     *
+     * @param xml_in the message to process - should be <message>
+     * @return the response - contains any error messages
+     * @see Element
+     */
+    public Element process(Element message) {
+     
+	logger.debug("MR received request");
+	logger.debug(this.converter.getString(message));
+	// check that its a correct message tag
+	if (!message.getTagName().equals(GSXML.MESSAGE_ELEM)) {
+	    logger.error(" Invalid message. GSDL message should start with <"+GSXML.MESSAGE_ELEM+">, instead it starts with:"+message.getTagName()+".");
+	    return null;
+	}
+
+	NodeList requests = message.getElementsByTagName(GSXML.REQUEST_ELEM);
+
+	Element mainResult = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	
+	// empty request
+	if (requests.getLength()==0) {
+	    return mainResult;
+	}
+
+	Document message_doc = message.getOwnerDocument();
+
+	// for now, just process each request one by one, and append the results to mainResult
+	// Note: if you add an element to another node in the same document, it
+	// gets removed from where it was. This changes the node list - you cant iterate over the node list in a normal manner if you are moving elements out of it
+	int num_requests = requests.getLength();
+	for (int i=0; i< num_requests; i++) {
+	    Node result=null;
+	    Element req = (Element)requests.item(i);
+	    if (req == null) {
+		logger.error("request "+i+" is null");
+		continue;
+	    }
+	    String path = req.getAttribute(GSXML.TO_ATT); // returns "" if no att of this name
+	    if (path.equals("")) {
+		// its a message for the message router
+		if (req.getAttribute(GSXML.TYPE_ATT).equals(GSXML.REQUEST_TYPE_MESSAGING)) {
+		    // its a messaging request - modifies the requests/responses
+		    result = modifyMessages(req, message, mainResult);
+		    mainResult.appendChild(this.doc.importNode(result, true));
+		} else {
+		    // standard request
+		    result = processMessage(req);
+		    mainResult.appendChild(this.doc.importNode(result, true));
+		}
+	    } else {
+		String [] modules = path.split(",");
+		
+		for (int j=0; j<modules.length; j++) {
+		    // why can't we do this outside the loop??
+		    Element mess = this.doc.createElement(GSXML.MESSAGE_ELEM);
+		    Element copied_request = (Element)this.doc.importNode(req, true);
+		    mess.appendChild(copied_request);
+
+		    String this_mod = modules[j];
+		    // find the module to pass it on to
+		    // need to put the request into a message element
+		    String obj = GSPath.getFirstLink(this_mod);
+		    
+		    if (this.module_map.containsKey(obj)) {
+			copied_request.setAttribute(GSXML.TO_ATT, this_mod);
+			result = ((ModuleInterface)this.module_map.get(obj)).process(mess);
+			if (result !=null ) {
+			    // append the contents of the message to the mainResult - there will only be one response at this stage
+			    mainResult.appendChild(this.doc.importNode(GSXML.getChildByTagName(result, GSXML.RESPONSE_ELEM), true));
+			} else {
+			    // add in a place holder response
+			    Element response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+			    response.setAttribute(GSXML.FROM_ATT, this_mod);
+			    mainResult.appendChild(response);
+			    logger.error("MessageRouter Error: request had null result!");
+			}
+			
+		    } else {    
+			logger.error("MessageRouter Error: request has illegal module name in:\n"+this.converter.getString(req));
+		    }
+		}
+	    }
+	    
+	} // for each request
+	
+	logger.debug("MR returned response");
+	logger.debug(this.converter.getString(mainResult));
+
+	return mainResult;
+	
+    }
+	
+    // ********************************************************************
+    // auxiliary configure methods
+    // *******************************************************************
+
+
+    protected boolean configureServices(Element service_rack_list) {
+
+	this.service_list = this.doc.createElement(GSXML.SERVICE_ELEM+GSXML.LIST_MODIFIER);
+
+	// load up the individual services
+	logger.info("loading service modules...");
+	
+	if (service_rack_list == null) {
+	    logger.info("... none to be loaded");
+	    return true;
+	} 
+	
+	NodeList service_racks = service_rack_list.getElementsByTagName(GSXML.SERVICE_CLASS_ELEM);
+	if (service_racks.getLength()==0) {
+	    logger.info("... none to be loaded");
+	    return true;
+	} 
+		
+	Element service_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element service_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_DESCRIBE, "", "", "");
+	service_message.appendChild(service_request);
+		
+	for(int i=0; i<service_racks.getLength(); i++) {
+	    Element n = (Element)service_racks.item(i);
+	    String service_name = n.getAttribute(GSXML.NAME_ATT);
+	    logger.info("..."+service_name);
+	    try {
+		ServiceRack s = (ServiceRack)Class.forName("org.greenstone.gsdl3.service."+service_name).newInstance();
+		s.setSiteHome(this.site_home);
+		s.setSiteAddress(this.site_http_address);
+		s.setMessageRouter(this);
+		// pass the XML node to the service for service configuration
+		s.configure(n, null);
+
+		// find out the supported services for this service module
+		Element service_response = (Element) s.process(service_message);
+		NodeList services = service_response.getElementsByTagName(GSXML.SERVICE_ELEM);
+		if (services.getLength()==0) {
+		    logger.error("MessageRouter configure error: serviceRack "+service_name+" has no services!");
+		} else {
+		    for (int j=0; j<services.getLength();j++) {
+			String service = ((Element)services.item(j)).getAttribute(GSXML.NAME_ATT);
+			this.module_map.put(service, s);
+			
+				// add short info to service_list_ XML
+			this.service_list.appendChild(this.doc.importNode(services.item(j), true));
+		    }
+		}
+	    } catch (Exception e ) {
+		logger.error("MessageRouter configure exception:  in ServiceRack class specification:  "+ e.getMessage());
+		e.printStackTrace();
+	    } 
+	} // for each service module
+	return true;
+    }
+    
+    protected boolean configureClusters(Element config_cluster_list) {
+
+	this.cluster_list = this.doc.createElement(GSXML.CLUSTER_ELEM+GSXML.LIST_MODIFIER);
+	// load up the service clusters
+	logger.info("loading service clusters ...");
+	if (config_cluster_list == null) {
+	    logger.info("... none to be loaded");
+	    return true;
+	} 
+	NodeList service_clusters = config_cluster_list.getElementsByTagName(GSXML.CLUSTER_ELEM);
+	if (service_clusters.getLength()==0) {
+	    logger.info("... none to be loaded");
+	    return true;
+	}
+	
+	for (int i=0; i<service_clusters.getLength(); i++) {
+	    Element cluster = (Element)service_clusters.item(i);
+	    String name = cluster.getAttribute(GSXML.NAME_ATT);
+	    logger.info("..."+name);
+	    ServiceCluster sc = new ServiceCluster();
+	    sc.setSiteHome(this.site_home);
+	    sc.setSiteAddress(this.site_http_address);
+	    sc.setClusterName(name);
+	    sc.setMessageRouter(this);
+	    sc.configure(cluster);
+	    this.module_map.put(name, sc); // this replaces the old one if there was one already present
+	    //add short info to cluster list
+	    Element e = this.doc.createElement(GSXML.CLUSTER_ELEM);
+	    e.setAttribute(GSXML.NAME_ATT, name);
+	    this.cluster_list.appendChild(e);
+	    
+	}
+	return true;
+    }
+    
+    protected boolean configureCollections() {
+
+	this.collection_list = this.doc.createElement(GSXML.COLLECTION_ELEM+GSXML.LIST_MODIFIER);
+
+	// read thru the collect directory and activate all the valid collections
+	File collectDir = new File(GSFile.collectDir(this.site_home));
+	if (collectDir.exists()) {
+	    logger.info("Reading thru directory "+collectDir.getPath()+" to find collections.");
+	    File[] contents = collectDir.listFiles();
+	    for (int i=0; i<contents.length;i++) {
+		if(contents[i].isDirectory()) {
+		    
+		    String colName = contents[i].getName();
+		    if (!colName.startsWith("CVS")) {
+			activateCollectionByName(colName);
+		    }
+		}
+	    }
+	} // collectDir
+	return true;
+    }
+
+    protected boolean configureSites(Element config_site_list) {
+
+	this.site_list = this.doc.createElement(GSXML.SITE_ELEM+GSXML.LIST_MODIFIER);
+	// load up the sites
+	logger.info("loading external sites...");
+	if (config_site_list ==null ) {
+	    logger.info("...none found");
+	    return true;
+	}
+
+	NodeList sites = config_site_list.getElementsByTagName(GSXML.SITE_ELEM);
+	if (sites.getLength()==0) {
+	    logger.info("...none found");
+	    return true;
+	}
+
+	// this is a name to identify the current site in the Communicator 
+	String local_site_name = config_site_list.getAttribute(GSXML.LOCAL_SITE_NAME_ATT);
+	if (local_site_name.equals("")) {
+	    local_site_name = site_name;
+	}
+
+	for (int i=0; i<sites.getLength(); i++) {
+	    Element s = (Element)sites.item(i);
+	    activateSite(s, local_site_name);	    
+	}
+	return true;
+    }
+    
+    protected boolean activateSite(Element site_elem, String local_site_name) {
+	Communicator comm=null;
+	String type = site_elem.getAttribute(GSXML.TYPE_ATT);
+	String name = site_elem.getAttribute(GSXML.NAME_ATT);
+	if (type.equals(GSXML.COMM_TYPE_SOAP_JAVA)) {
+	    comm = new SOAPCommunicator();
+	    if (comm.configure(site_elem)) {
+		comm.setLocalSiteName(local_site_name);
+		
+		// add to map of modules
+		this.module_map.put(name, comm);
+		this.site_list.appendChild(this.doc.importNode(site_elem, true));
+		// need to get collection list and service 
+		// list from here- if the site isn't up yet, the site will
+		// have to be added later 
+		if (!getRemoteSiteInfo(comm, name)) {
+		    logger.error(" couldn't get info from site "+name);
+		}
+	    } else {
+		logger.error(" couldn't configure soap site:"+name);
+		return false;
+	    }
+	    
+	} else {
+	    System.err.print(" cant talk to server of type:"+type + ", so not making a connection to "+name);
+	    return false;
+	}
+	return true;
+    }
+    
+    /** get site info from external site
+     *
+     * @param comm - the communicator object for the external site
+     * @param site_name - the name of the external site
+     * @return true if successful
+     */
+    protected boolean getRemoteSiteInfo(Communicator comm, String site_name) {
+    
+	logger.info(" getting info from site:"+site_name);
+
+	Element info_request = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element req = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_DESCRIBE, "", "", "");
+	info_request.appendChild(req);
+
+	// process the message
+	Element info_response = comm.process(info_request);
+	if (info_response == null) {
+	    return false;
+	}
+	// collection info
+	NodeList colls = info_response.getElementsByTagName(GSXML.COLLECTION_ELEM);
+	if (colls.getLength()>0) {
+	    for (int i=0; i<colls.getLength(); i++) {
+		Element e = (Element)colls.item(i);
+		String col_name = e.getAttribute(GSXML.NAME_ATT);
+		// add the info to own coll list - may want to keep 
+		// this separate in future - so can distinguish own and 
+		// other collections ??
+		e.setAttribute(GSXML.NAME_ATT, GSPath.prependLink(col_name, site_name));
+		this.collection_list.appendChild(this.doc.importNode(e, true));
+	    }
+	}
+
+	// service info
+	NodeList services = info_response.getElementsByTagName(GSXML.SERVICE_ELEM);
+	if (services.getLength()>0) {
+	    for (int i=0; i<services.getLength(); i++) {
+		Element e = (Element)services.item(i);
+		String serv_name = e.getAttribute(GSXML.NAME_ATT);
+		e.setAttribute(GSXML.NAME_ATT, GSPath.prependLink(serv_name, site_name));
+		this.service_list.appendChild(this.doc.importNode(e, true));
+	    }
+	}
+	
+	// serviceCluster info
+	NodeList clusters = info_response.getElementsByTagName(GSXML.CLUSTER_ELEM);
+	if (clusters.getLength()>0) {
+	    for (int i=0; i<clusters.getLength(); i++) {
+		Element e = (Element)clusters.item(i);
+		String clus_name = e.getAttribute(GSXML.NAME_ATT);
+		e.setAttribute(GSXML.NAME_ATT, GSPath.prependLink(clus_name, site_name));
+		this.cluster_list.appendChild(this.doc.importNode(e, true));
+	    }
+	}
+	return true;
+    }
+
+
+    //*****************************************************************
+    // auxiliary process methods
+    //*****************************************************************
+
+    /** handles requests made to the MessageRouter itself 
+     *
+     * @param req - the request Element- <request>
+     * @return the result Element - should be <response>
+     */
+    protected Element processMessage(Element req) {
+
+	// message for self, should be type=describe/configure at this stage
+	String type = req.getAttribute(GSXML.TYPE_ATT);
+	Element response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	response.setAttribute(GSXML.FROM_ATT, "");
+	if (type.equals(GSXML.REQUEST_TYPE_DESCRIBE)) {
+	    response.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_DESCRIBE);
+	    // check the param list
+	    Element param_list = (Element) GSXML.getChildByTagName(req, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	    if (param_list == null) {
+		response.appendChild(this.collection_list);
+		response.appendChild(this.cluster_list);
+		response.appendChild(this.site_list);
+		response.appendChild(this.service_list);
+		return response;
+	    }
+	    NodeList params = param_list.getElementsByTagName(GSXML.PARAM_ELEM);
+	    
+	    // go through the param list and see what components are wanted
+	    for (int i=0; i<params.getLength(); i++) {
+		
+		Element param = (Element)params.item(i);
+		// Identify the structure information desired
+		if (param.getAttribute(GSXML.NAME_ATT).equals(GSXML.SUBSET_PARAM)) {
+		    String info = param.getAttribute(GSXML.VALUE_ATT);
+		    if (info.equals(GSXML.COLLECTION_ELEM+GSXML.LIST_MODIFIER)) {
+			response.appendChild(this.collection_list);
+			
+		    } else if (info.equals(GSXML.CLUSTER_ELEM+GSXML.LIST_MODIFIER)) {
+			response.appendChild(this.cluster_list);
+			
+		    } else if (info.equals(GSXML.SERVICE_ELEM+GSXML.LIST_MODIFIER)) {
+			response.appendChild(this.service_list);
+		    } else if (info.equals(GSXML.SITE_ELEM+GSXML.LIST_MODIFIER)) {
+			response.appendChild(this.site_list);
+		    } 
+		}
+	    }
+	    return response;
+	    
+	} 
+	
+	if (type.equals(GSXML.REQUEST_TYPE_SYSTEM)) {
+	    
+	    // a list of system requests - should put any error messages
+	    // or success messages into response
+	    NodeList commands = req.getElementsByTagName(GSXML.SYSTEM_ELEM);
+	    Element site_config_elem = null;
+	    boolean success = false;
+			
+	    for (int i=0; i<commands.getLength(); i++) {
+		// all the commands should be Elements
+		Element elem = (Element)commands.item(i);
+		String action = elem.getAttribute(GSXML.TYPE_ATT);
+		if (action.equals(GSXML.SYSTEM_TYPE_CONFIGURE)) {
+		    String subset = elem.getAttribute(GSXML.SYSTEM_SUBSET_ATT);
+		    if (subset.equals("")) {
+			// need to reconfigure the MR
+			this.configure();
+			Element s = GSXML.createTextElement(this.doc, GSXML.STATUS_ELEM,  "MessageRouter reconfigured successfully");
+			response.appendChild(s);
+			
+		    } else {
+			// else it a specific request
+			if (subset.equals(GSXML.COLLECTION_ELEM+GSXML.LIST_MODIFIER)) {
+			    success = configureCollections();
+			} else {
+
+			    // need the site config file
+			    if (site_config_elem==null) {
+				
+				File configFile = new File(GSFile.siteConfigFile(this.site_home));
+				if (!configFile.exists() ) {
+				    logger.error(" site config file: "+configFile.getPath()+" not found!");
+				    continue;
+				}
+				Document site_config_doc = this.converter.getDOM(configFile);
+				if (site_config_doc == null) {
+				    logger.error(" couldn't parse site config file: "+configFile.getPath());
+				    continue;
+				}
+				site_config_elem  = site_config_doc.getDocumentElement();
+			    }
+			    if (subset.equals(GSXML.SERVICE_ELEM+GSXML.LIST_MODIFIER)) {
+				Element service_rack_list = (Element)GSXML.getChildByTagName(site_config_elem, GSXML.SERVICE_CLASS_ELEM+GSXML.LIST_MODIFIER);
+				
+				success = configureServices(service_rack_list);
+			    } else if (subset.equals(GSXML.CLUSTER_ELEM+GSXML.LIST_MODIFIER)) {
+				Element cluster_list = (Element)GSXML.getChildByTagName(site_config_elem, GSXML.CLUSTER_ELEM+GSXML.LIST_MODIFIER);	
+				
+				success = configureClusters(cluster_list);
+			    } else if (subset.equals(GSXML.SITE_ELEM+GSXML.LIST_MODIFIER)) {
+				Element site_list = (Element)GSXML.getChildByTagName(site_config_elem, GSXML.SITE_ELEM+GSXML.LIST_MODIFIER);
+				success = configureSites(site_list);
+			    }
+			}
+			String message=null;
+			if (success) {
+			    message = subset + "reconfigured successfully";
+			} else {
+			    message = "Error in reconfiguring "+subset;
+			}
+			Element s = GSXML.createTextElement(this.doc, GSXML.STATUS_ELEM, message);
+			response.appendChild(s);
+		    }
+		    
+		    
+		} else {
+		    String module_name = elem.getAttribute(GSXML.SYSTEM_MODULE_NAME_ATT);
+		    String module_type = elem.getAttribute(GSXML.SYSTEM_MODULE_TYPE_ATT);
+
+		    if (action.equals(GSXML.SYSTEM_TYPE_DEACTIVATE)) {
+			deactivateModule(module_type, module_name);
+			Element s = GSXML.createTextElement(this.doc, GSXML.STATUS_ELEM, module_type+": "+module_name+" deactivated");
+			response.appendChild(s);
+		    } else if (action.equals(GSXML.SYSTEM_TYPE_ACTIVATE)) {
+			if (module_type.equals(GSXML.COLLECTION_ELEM)) {
+			    success = activateCollectionByName(module_name);
+			} else if (module_type.equals(GSXML.SITE_ELEM)) {
+			    success = activateSiteByName(module_name);
+			} else if (module_type.equals(GSXML.CLUSTER_ELEM)) {
+			    success = activateServiceClusterByName(module_name);
+			}
+			if (success) {
+			    Element s = GSXML.createTextElement(this.doc, GSXML.STATUS_ELEM, module_type+": "+module_name+" activated");
+			    response.appendChild(s);
+			} else {
+			    Element s = GSXML.createTextElement(this.doc, GSXML.STATUS_ELEM, module_type+": "+module_name+" could not be activated");
+			    response.appendChild(s);
+			}
+		    }
+		} // else not a configure action
+	    } // for all commands
+	    return response;
+			
+
+	} // system type request
+	
+	// if get here something has gone wrong
+	logger.error(" cant process request:");
+	logger.error(this.converter.getString(req));
+	return null;
+       
+    }
+    protected Element modifyMessages(Element request, Element message, Element result) {
+	Element response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	response.setAttribute(GSXML.FROM_ATT, "");
+	response.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_MESSAGING);
+
+	NodeList commands = request.getElementsByTagName("command");
+	if (commands == null) {
+	    logger.error("no commands, "+converter.getPrettyString(request));
+	    return response;
+	}
+	for (int i=0; i<commands.getLength(); i++) {
+	    Element action = (Element)commands.item(i);
+	    String type = action.getAttribute(GSXML.TYPE_ATT);
+	    if (type.equals("copyNode")) {
+		// copies the from node as a child of to node
+		String from_path = action.getAttribute("from");
+		String to_path = action.getAttribute("to");
+		Element from_node = null;
+		String from_node_root = GSPath.getFirstLink(from_path);
+		if (from_node_root.startsWith(GSXML.REQUEST_ELEM)) {
+		    from_node = message;
+		} else if (from_node_root.startsWith(GSXML.RESPONSE_ELEM)) {
+		    from_node = result;
+		}
+		if (from_node == null) {
+		    continue;
+		}
+		Element to_node = null;
+		String to_node_root = GSPath.getFirstLink(to_path);
+		if (to_node_root.startsWith(GSXML.REQUEST_ELEM)) {
+		    to_node = message;
+		} else if (to_node_root.startsWith(GSXML.RESPONSE_ELEM)) {
+		    to_node = result;
+		}
+		if (to_node == null) {
+		    continue;
+		}
+		// now we know what node to copy where
+		Node orig_node = GSXML.getNodeByPathIndexed(from_node, from_path);
+		if (orig_node == null) {
+		    continue;
+		}
+		Node new_parent = GSXML.getNodeByPathIndexed(to_node, to_path);
+		if (new_parent == null) {
+		    continue;
+		    
+		}
+		new_parent.appendChild(to_node.getOwnerDocument().importNode(orig_node, true));
+	    }
+	    
+	    else if (type.equals("copyChildren")) {
+
+	    }
+	} // for each command
+	return response;
+    }
+    
+    // ****************************************************
+    // other methods
+    // ****************************************************
+
+    /** creates and configures a new collection
+     *
+     *@param col_name the name of the collection
+     *@return true if collection created ok
+     */
+    protected boolean activateCollectionByName(String col_name) {
+
+	logger.info("Activating collection: "+col_name+".");
+
+	// Look for the etc/collectionInit.xml file, and see what sort of Collection to load
+	Collection c = null;
+	File init_file = new File(GSFile.collectionInitFile(this.site_home, col_name));
+
+	if (init_file.exists()) {
+	    Document init_doc = this.converter.getDOM(init_file);
+	    if (init_doc != null) {
+		Element init_elem = init_doc.getDocumentElement();
+		if (init_elem != null) {
+		    String coll_class_name = init_elem.getAttribute("class");
+		    if (!coll_class_name.equals("")) {
+			try {
+			    c = (Collection)Class.forName("org.greenstone.gsdl3.collection."+coll_class_name).newInstance();
+			} catch (Exception e) {
+			    logger.info(" couldn't create a new collection, type "+coll_class_name+", defaulting to class Collection");
+			}
+		    }
+		}
+	    }
+	}
+	if (c==null) { // we haven't found another classname to use
+	    c = new Collection();
+	}
+	
+	c.setCollectionName(col_name);
+	c.setSiteHome(this.site_home);
+	c.setSiteAddress(this.site_http_address);
+	c.setMessageRouter(this);
+	if (c.configure()) {
+	    // this could be a reactivation, so delete the old version
+	    deactivateModule(GSXML.COLLECTION_ELEM, col_name);
+	    // add to list of collections
+	    this.module_map.put(col_name, c);
+	    
+	    if(c.isPublic()) {
+		// only public collections will appear on the home page
+		// add short description_ to collection_list_
+		Element e = this.doc.createElement(GSXML.COLLECTION_ELEM);
+		e.setAttribute(GSXML.NAME_ATT, col_name);
+		this.collection_list.appendChild(e);
+	    } 
+	    return true;
+	} else {
+	    logger.error("Couldn't configure collection: "+
+			       col_name+".");
+	    return false;
+	}
+    }
+    
+    protected boolean activateSiteByName(String site_name) {
+	logger.info("Activating site: "+site_name+".");
+	
+	// just in case this is a reactivation, deactivate this site first
+	deactivateModule(GSXML.SITE_ELEM, site_name);
+	File configFile = new File(GSFile.siteConfigFile(this.site_home));
+
+	if (!configFile.exists() ) {
+	    logger.error(" site config file: "+configFile.getPath()+" not found!");
+	    return false;
+	}
+	Document config_doc = this.converter.getDOM(configFile);
+	if (config_doc == null) {
+	    logger.error(" couldn't parse site config file: "+configFile.getPath());
+	    return false;
+	}
+	Element config_elem = config_doc.getDocumentElement();
+	
+	Element config_site_list = (Element)GSXML.getChildByTagName(config_elem, GSXML.SITE_ELEM+GSXML.LIST_MODIFIER);
+	if (config_site_list ==null ) {
+	    logger.error("activateSite, no sites found");
+	    return false;
+	}
+	// this is a name to identify the current site in the Communicator 
+	String local_site_name = config_site_list.getAttribute("localSiteName");
+	if (local_site_name.equals("")) {
+	    local_site_name = site_name;
+	}
+
+	Element this_site_elem = GSXML.getNamedElement(config_site_list, GSXML.SITE_ELEM, GSXML.NAME_ATT, site_name);
+	if (this_site_elem == null) {
+	    logger.error("activateSite, site "+site_name+" not found");
+	    return false;
+	}
+	
+	return activateSite(this_site_elem, local_site_name);
+    }
+    
+    protected boolean activateServiceClusterByName(String cluster_name) {
+	return false;
+
+    }
+
+    protected boolean activateServiceRackByName(String module_name) {
+	return false;
+    }
+
+    protected boolean deactivateModule(String type, String name) {
+	
+	if (this.module_map.containsKey(name)) {
+
+	    logger.info(" deactivating "+name);
+	    ModuleInterface m = (ModuleInterface)this.module_map.remove(name);
+	    m.cleanUp(); // clean up any open files/connections etc - can cause trouble on windows
+	    // also remove the xml bit from description list
+	    if (type.equals(GSXML.COLLECTION_ELEM)) {
+		Element this_col = GSXML.getNamedElement(this.collection_list, GSXML.COLLECTION_ELEM, GSXML.NAME_ATT, name);
+		if (this_col != null) {
+		    this.collection_list.removeChild(this_col);
+		}
+		return true;
+	    } else if (type.equals(GSXML.SERVICE_ELEM)) {
+		Element this_service = GSXML.getNamedElement(this.service_list, GSXML.SERVICE_ELEM, GSXML.NAME_ATT, name);
+		if (this_service != null) {
+		    this.service_list.removeChild(this_service);
+		}
+		return true;
+	    } else if (type.equals(GSXML.CLUSTER_ELEM)) {
+		Element this_cluster = GSXML.getNamedElement(this.cluster_list, GSXML.CLUSTER_ELEM, GSXML.NAME_ATT, name);
+		if (this_cluster != null) {
+		    this.cluster_list.removeChild(this_cluster);
+		}
+		return true;
+	    } else if (type.equals(GSXML.SITE_ELEM)) {
+		Element this_site = GSXML.getNamedElement(this.site_list, GSXML.SITE_ELEM, GSXML.NAME_ATT, name);
+		if (this_site != null) {
+		    this.site_list.removeChild(this_site);
+		    
+		    // also remove this sites colls, services, clusters etc
+		    removeRemoteSiteInfo(this.collection_list, GSXML.COLLECTION_ELEM, name);
+		    removeRemoteSiteInfo(this.cluster_list, GSXML.CLUSTER_ELEM, name);
+		    removeRemoteSiteInfo(this.service_list, GSXML.SERVICE_ELEM, name);
+		}
+	    } else {
+		logger.error(" couldn't deactivate coll");
+		// couldn't do it
+		return false;
+	    }
+	}
+	// else not deactivated 
+	return false;
+
+    }
+
+    /**
+     * this looks through a list (module_list) of elements named module_name, 
+     * and removes any whose names start with site_name
+     */
+    protected void removeRemoteSiteInfo(Element module_list, 
+					String module_name, 
+					String site_name) {
+
+	NodeList modules = module_list.getElementsByTagName(module_name);
+	// will this work??
+	for (int i=modules.getLength()-1; i>=0; i--) {
+	    
+	    String name = ((Element)modules.item(i)).getAttribute(GSXML.NAME_ATT);
+	    if (GSPath.getFirstLink(name).equals(site_name)) {
+		module_list.removeChild(modules.item(i));
+	    }
+	}
+    }
+	
+}
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/core/ModuleInterface.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/core/ModuleInterface.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/core/ModuleInterface.java	(revision 13928)
@@ -0,0 +1,62 @@
+/*
+ *    ModuleInterface.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.core;
+   
+import org.w3c.dom.Element;                                                
+
+/**
+ * interface for all modules in greenstone.
+ *
+ * all components talk via a process method - in its simplest form,
+ * it takes a String of XML, and returns a String of XML
+ *
+ * the more efficient process method uses DOM Element Nodes instead 
+ * of Strings - this avoids parsing the XML at each module
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ * @version $Revision$
+ */
+public interface ModuleInterface {
+ 
+  /**
+   * Process an XML request - as a String
+   *
+   * @param xml_in the request to process
+   * @return the response - contains any error messages
+   * @see java.lang.String
+   */
+    abstract public String process(String xml_in);
+
+  /**
+   * Process an XML request - as a DOM model Element
+   *
+   * @param xml_in the request to process
+   * @return the response - contains any error messages
+   * @see org.w3c.dom.Element
+   */
+    abstract public Element process(Element xml_in);
+
+    /** 
+     * Do any clean up necessary for deactivating the module, eg
+     * close any open file handles (gdbm in particular) or windows
+     * holds locks on them.
+     */
+    abstract public void cleanUp();
+}    
+                                                                           
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/core/NZDLReceptionist.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/core/NZDLReceptionist.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/core/NZDLReceptionist.java	(revision 13928)
@@ -0,0 +1,99 @@
+package org.greenstone.gsdl3.core;
+
+import org.greenstone.gsdl3.util.*;
+import org.greenstone.gsdl3.action.*;
+// XML classes
+import org.w3c.dom.Node; 
+import org.w3c.dom.NodeList; 
+import org.w3c.dom.Document; 
+import org.w3c.dom.Element; 
+
+// other java classes
+import java.io.File;
+import java.util.HashMap;
+import java.util.Enumeration;
+
+import org.apache.log4j.*;
+
+/** 
+ * This is a new version of the Receptionist for the NZDL interface
+ * the interface requires a lot more info for each page
+ * @see DefaultReceptionist
+ */
+public class NZDLReceptionist extends DefaultReceptionist {
+
+     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.core. NZDLReceptionist.class.getName());
+
+    protected void addExtraInfo(Element page) {
+	logger.debug("the  page before adding extra info is");
+	logger.debug(this.converter.getPrettyString(page));
+
+	super.addExtraInfo(page);
+
+	// this gets the collection info
+	Element page_response = (Element)GSXML.getChildByTagName(page, GSXML.PAGE_RESPONSE_ELEM);
+	Element page_request = (Element)GSXML.getChildByTagName(page, GSXML.PAGE_REQUEST_ELEM);
+	Element collection_info = (Element)GSXML.getChildByTagName(page_response, GSXML.COLLECTION_ELEM);
+	if (collection_info== null) {
+	    return;
+	}
+
+	String collection = collection_info.getAttribute("name"); // should we take this from the request instead??
+	// look through services and see if classifier one is present - need to
+	// get the list of classifiers
+	Element service_list = (Element)GSXML.getChildByTagName(collection_info, GSXML.SERVICE_ELEM+GSXML.LIST_MODIFIER);
+	if (service_list == null) {
+	    // something weird has gone wrong
+	    return;
+	}
+	
+	Element info_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	String lang = page.getAttribute(GSXML.LANG_ATT);
+	
+	boolean do_classifier = false;
+	boolean do_query = false;
+	Element classifier_service = GSXML.getNamedElement(service_list, GSXML.SERVICE_ELEM, GSXML.NAME_ATT, "ClassifierBrowse");
+	Element query_service = GSXML.getNamedElement(service_list, GSXML.SERVICE_ELEM, GSXML.NAME_ATT, "TextQuery");
+	if (classifier_service != null) {
+	    do_classifier = true;
+	    // find the list of classifiers
+	
+	    String to = GSPath.appendLink(collection, "ClassifierBrowse");
+	    Element info_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_DESCRIBE, to, lang, ""); 
+	    info_message.appendChild(info_request);
+	}
+	
+	String action = page_request.getAttribute(GSXML.ACTION_ATT);
+	String subaction = page_request.getAttribute(GSXML.SUBACTION_ATT);
+	
+	if (query_service != null && action.equals("p") && subaction.equals("about")) {
+	    do_query = true;
+	    // get the full description
+	    String to = GSPath.appendLink(collection, "TextQuery");
+	    Element query_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_DESCRIBE, to, lang, "");
+	    info_message.appendChild(query_request);
+	    
+	}
+	
+	Element info_resp_message = (Element) this.mr.process(info_message);
+	Element info_response = (Element) GSXML.getChildByTagName(info_resp_message, GSXML.RESPONSE_ELEM); 
+	//	String path = GSPath.appendLink(GSXML.RESPONSE_ELEM, GSXML.SERVICE_ELEM);
+	if (do_classifier) {
+	    Element classifier_service_info = (Element)GSXML.getNamedElement(info_response, GSXML.SERVICE_ELEM, GSXML.NAME_ATT, "CLassifierBrowse");
+	    if (classifier_service_info != null) {
+		service_list.replaceChild(this.doc.importNode(classifier_service_info, true), classifier_service);
+	    }
+	}
+	if (do_query) {
+	    Element query_service_info = (Element)GSXML.getNamedElement(info_response, GSXML.SERVICE_ELEM, GSXML.NAME_ATT, "TextQuery");
+	    if (query_service_info != null) {
+		service_list.replaceChild(this.doc.importNode(query_service_info, true), query_service);
+	    }
+	}
+	logger.debug("the final page before transforming is");
+	logger.debug(this.converter.getPrettyString(page));
+	return;
+    }
+	
+}
+    
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/core/Receptionist.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/core/Receptionist.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/core/Receptionist.java	(revision 13928)
@@ -0,0 +1,281 @@
+package org.greenstone.gsdl3.core;
+
+import org.greenstone.gsdl3.util.*;
+import org.greenstone.gsdl3.action.*;
+// XML classes
+import org.w3c.dom.Node; 
+import org.w3c.dom.NodeList; 
+import org.w3c.dom.Document; 
+import org.w3c.dom.Element; 
+
+// other java classes
+import java.io.File;
+import java.util.HashMap;
+import java.util.Enumeration;
+import java.util.ArrayList;
+
+import org.apache.log4j.*;
+
+/** the most basic Receptionist, used for interface generation. 
+ * Receives requests consisting
+ * of an xml representation of cgi args, and returns the page of data. The requests are processed by the appropriate action class
+ *
+ * @see Action
+ */
+public class Receptionist implements ModuleInterface {
+
+     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.core.Receptionist.class.getName());
+
+    /** the set up variables */
+    protected HashMap config_params = null;
+    /** container Document to create XML Nodes */
+    protected Document doc=null; 
+   
+    /** a converter class to parse XML and create Docs */
+    protected XMLConverter converter=null;
+
+    /** the message router that the Receptionist and Actions will talk to */
+    protected ModuleInterface mr=null;
+
+    /** the list of actions */
+    protected HashMap action_map=null;
+    
+    /** the list of params */
+    protected GSParams params=null;
+    protected Element language_list = null;
+
+    /** the list of interfaces this is based on */
+    protected ArrayList base_interfaces = null;
+    
+    public Receptionist() {
+	this.converter = new XMLConverter();
+	this.doc = this.converter.newDOM();
+	this.action_map= new HashMap();
+    }
+    
+    public void cleanUp() {}
+    public void setParams(GSParams params) {
+	this.params = params;
+    }
+    public void setConfigParams(HashMap params) {
+	this.config_params = params;
+    }
+    /** sets the message router  - it should already be created and 
+     * configured before  being passed to the receptionist*/
+    public void setMessageRouter(ModuleInterface m) {
+       this.mr = m;
+    }
+
+    /** configures the receptionist */
+    public boolean configure() {
+
+	if (this.config_params==null) {
+	    logger.error(" config variables must be set before calling configure");
+	    return false;
+	}
+	if (this.mr==null) {	   
+	    logger.error(" message router must be set  before calling configure");
+	    return false;
+	}
+
+	// find the config file containing a list of actions
+	File interface_config_file = new File(GSFile.interfaceConfigFile(GSFile.interfaceHome(GlobalProperties.getGSDL3Home(), (String)this.config_params.get(GSConstants.INTERFACE_NAME))));
+	if (!interface_config_file.exists()) {
+	    logger.error(" interface config file: "+interface_config_file.getPath()+" not found!");
+	    return false;
+	}
+	
+	Document config_doc = this.converter.getDOM(interface_config_file);
+	if (config_doc == null) {
+	    logger.error(" could not parse interface config file: "+interface_config_file.getPath());
+	    return false;
+	}
+	Element config_elem = config_doc.getDocumentElement();
+	String base_interface = config_elem.getAttribute("baseInterface");
+	setUpBaseInterface(base_interface);
+	setUpInterfaceOptions(config_elem);
+
+	// load up the actions
+	Element action_list = (Element)GSXML.getChildByTagName(config_elem, GSXML.ACTION_ELEM+GSXML.LIST_MODIFIER);
+	NodeList actions = action_list.getElementsByTagName(GSXML.ACTION_ELEM);
+
+	for (int i=0; i<actions.getLength(); i++) {
+	    Element action = (Element) actions.item(i);
+	    String class_name = action.getAttribute("class");
+	    String action_name = action.getAttribute("name");
+	    Action ac = null;
+	    try {
+		ac = (Action)Class.forName("org.greenstone.gsdl3.action."+class_name).newInstance();
+	    } catch (Exception e) {
+		logger.error(" couldn't load in action "+class_name);
+		e.printStackTrace();
+		continue;
+	    }
+	    ac.setConfigParams(this.config_params);
+	    ac.setMessageRouter(this.mr);
+	    ac.configure();
+	    ac.getActionParameters(this.params);
+	    this.action_map.put(action_name, ac);
+	}
+
+	this.language_list = (Element)GSXML.getChildByTagName(config_elem, "languageList");
+	if (language_list == null) {
+	    logger.error(" didn't find a language list in the config file!!");
+	}
+
+	return true;
+    }
+    /** process using strings - just calls process using Elements */
+    public String process(String xml_in) {
+
+	Element message = this.converter.getDOM(xml_in).getDocumentElement();
+	Element page = process(message);
+	return this.converter.getString(page);
+    }
+
+    /** process - produce a page of data in response to a request 
+     * if something goes wrong, it returns null - 
+     * TODO:  return a suitable message to the user */
+    public Element process(Element message) {
+
+	// get the request out of the message - assume that there is only one
+	Element request = (Element)GSXML.getChildByTagName(message, GSXML.REQUEST_ELEM);
+	if (request == null) {
+	    logger.error(" message had no request!");
+	    return null; 
+	}
+	// check the request type 
+	String type = request.getAttribute(GSXML.TYPE_ATT); // returns "" if no att of this name
+	if (!type.equals(GSXML.REQUEST_TYPE_PAGE)) { 
+	    // now Receptionist forwards non-page requests straight to the MR, and returns the responses
+	    logger.error(" request type is not '"+GSXML.REQUEST_TYPE_PAGE+"', but it is '"+type+"', so forwarding the message to the MR!");
+	    // process the whole message - mr needs <message> tags, and 
+	    // in this case, there may be more than one request in the message
+	    return this.mr.process(message);
+	}	
+	// work out which action to pass to
+	String action = request.getAttribute(GSXML.ACTION_ATT);
+	if (action.equals("")) {
+	    logger.error(" no action specified in the request!");
+	    return null;
+	}
+	
+	// find the  appropriate action	
+	Action a = (Action)this.action_map.get(action);
+	String action_name=null;
+	if (a==null) { // not in the map yet
+	    // try to load a new action
+	    try {
+		action_name = action.substring(0,1).toUpperCase()+action.substring(1)+"Action";
+		Action ac = (Action)Class.forName("org.greenstone.gsdl3.action."+action_name).newInstance();
+		ac.setConfigParams(this.config_params);
+		ac.setMessageRouter(this.mr);
+		ac.configure();
+		ac.getActionParameters(this.params);
+		this.action_map.put(action, ac);
+		a = ac;
+	    } catch (Exception e) {
+		
+		logger.error(" a new action ("+action_name+") was specified and it couldn't be created. Error message:"+e.getMessage());
+		return null;
+	    }
+	}
+
+	// transform the request in some way
+	preProcessRequest(request);
+	// set up the page
+	Element page = this.doc.createElement(GSXML.PAGE_ELEM);
+	page.setAttribute(GSXML.LANG_ATT, request.getAttribute(GSXML.LANG_ATT));
+	
+	// get the page data from the action
+	Element action_response = a.process(message);
+
+	boolean response_only=false;
+	Element param_list = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	if (param_list != null) {
+	    Element param = GSXML.getNamedElement(param_list, GSXML.PARAM_ELEM, GSXML.NAME_ATT, "ro");
+	    if (param != null) {
+		String value = param.getAttribute("value");
+		if (value.equals("1")) {
+		    response_only = true;
+		}
+	    }
+	}
+	if (response_only) {
+	    // only the response from the action is sent back
+	    return action_response;
+	}
+	
+	// the request is part of the page
+	page.appendChild(GSXML.duplicateWithNewName(this.doc, request, GSXML.PAGE_REQUEST_ELEM, true));
+	// add the response too
+	Element page_response = GSXML.duplicateWithNewName(this.doc, (Element)GSXML.getChildByTagName(action_response, GSXML.RESPONSE_ELEM), GSXML.PAGE_RESPONSE_ELEM, true);
+	page.appendChild(page_response);
+
+	logger.debug(" raw page="+this.converter.getString(page));
+	// transform the result in some way
+	Element resulting_page = postProcessPage(page);
+	return resulting_page;
+	
+    }
+
+    protected boolean setUpBaseInterface(String base_interface) {
+	if (base_interface== null || base_interface.equals("")) {
+	    // there was no base interface, the list remains null
+	    return true;
+	}
+	// foreach base interface
+	while (!base_interface.equals("")) {
+	    // find the base interface config file
+	    File base_interface_config_file = new File(GSFile.interfaceConfigFile(GSFile.interfaceHome(GlobalProperties.getGSDL3Home(), base_interface)));
+	    if (!base_interface_config_file.exists()) {
+		logger.error(" base interface config file: "+base_interface_config_file.getPath()+" not found!");
+		return false;
+	    }
+	    // the interface name is valid, add it to the list
+	    if (base_interfaces == null) {
+		base_interfaces = new ArrayList();
+	    }
+	    base_interfaces.add(base_interface);
+	    // now see if this has a base interface
+	    Document config_doc = this.converter.getDOM(base_interface_config_file);
+	    if (config_doc == null) {
+		logger.error(" could not parse base interface config file: "+base_interface_config_file.getPath());
+		return false;
+	    }
+	    Element config_elem = config_doc.getDocumentElement();
+	    base_interface = config_elem.getAttribute("baseInterface");
+	}
+	return true;
+    }
+
+    protected boolean setUpInterfaceOptions(Element config_elem) {
+	Element option_list = (Element)GSXML.getChildByTagName(config_elem, "optionList");
+	if (option_list != null) {
+	    logger.error("found an option list");
+	    // we set any options in the config params
+	    NodeList options = option_list.getElementsByTagName("option");
+	    for (int i=0; i<options.getLength(); i++) {
+		Element option = (Element)options.item(i);
+		String name = option.getAttribute(GSXML.NAME_ATT);
+		String value = option.getAttribute(GSXML.VALUE_ATT);
+		logger.error("option: "+name+", "+value);
+		if (!name.equals("") && !value.equals("")) {
+		    this.config_params.put(name, value);
+		}
+	    }
+	}
+
+	return true;
+    }
+
+    protected void preProcessRequest(Element request) {
+	return;
+    }
+
+    protected Element postProcessPage(Element page) {
+	return page;
+    }
+    
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/core/TransformingReceptionist.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/core/TransformingReceptionist.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/core/TransformingReceptionist.java	(revision 13928)
@@ -0,0 +1,226 @@
+package org.greenstone.gsdl3.core;
+
+import org.greenstone.gsdl3.util.*;
+import org.greenstone.gsdl3.action.*;
+// XML classes
+import org.w3c.dom.Node; 
+import org.w3c.dom.NodeList; 
+import org.w3c.dom.Document; 
+import org.w3c.dom.Element; 
+
+// other java classes
+import java.io.File;
+import java.util.HashMap;
+import java.util.Enumeration;
+
+import org.apache.log4j.*;
+
+/** A receptionist that uses xslt to transform the page_data before returning it. . Receives requests consisting
+ * of an xml representation of cgi args, and returns the page of data - in 
+ * html by default. The requests are processed by the appropriate action class
+ *
+ * @see Action
+ */
+public class TransformingReceptionist extends Receptionist{
+    
+     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.core.TransformingReceptionist.class.getName());
+
+    /** the list of xslt to use for actions */
+    protected HashMap xslt_map = null;
+    
+    /** a transformer class to transform xml using xslt */
+    protected XMLTransformer transformer=null;
+
+    public TransformingReceptionist() {
+	super();
+	this.xslt_map = new HashMap();
+	this.transformer = new XMLTransformer();
+    }
+    
+    /** configures the receptionist - overwrite this to set up the xslt map*/
+    public boolean configure() {
+	
+	if (this.config_params==null) {
+	    logger.error(" config variables must be set before calling configure");
+	    return false;
+	}
+	if (this.mr==null) {	   
+	    logger.error(" message router must be set  before calling configure");
+	    return false;
+	}
+	
+	// find the config file containing a list of actions
+	File interface_config_file = new File(GSFile.interfaceConfigFile(GSFile.interfaceHome(GlobalProperties.getGSDL3Home(), (String)this.config_params.get(GSConstants.INTERFACE_NAME))));
+	if (!interface_config_file.exists()) {
+	    logger.error(" interface config file: "+interface_config_file.getPath()+" not found!");
+	    return false;
+	}
+	Document config_doc = this.converter.getDOM(interface_config_file, "utf-8");
+	if (config_doc == null) {
+	    logger.error(" could not parse interface config file: "+interface_config_file.getPath());
+	    return false;
+	}
+	Element config_elem = config_doc.getDocumentElement();
+	String base_interface = config_elem.getAttribute("baseInterface");
+	setUpBaseInterface(base_interface);
+	setUpInterfaceOptions(config_elem);
+
+	Element action_list = (Element)GSXML.getChildByTagName(config_elem, GSXML.ACTION_ELEM+GSXML.LIST_MODIFIER);
+	NodeList actions = action_list.getElementsByTagName(GSXML.ACTION_ELEM);
+
+	for (int i=0; i<actions.getLength(); i++) {
+	    Element action = (Element) actions.item(i);
+	    String class_name = action.getAttribute("class");
+	    String action_name = action.getAttribute("name");
+	    Action ac = null;
+	    try {
+		ac = (Action)Class.forName("org.greenstone.gsdl3.action."+class_name).newInstance();
+	    } catch (Exception e) {
+		logger.error(" couldn't load in action "+class_name);
+		e.printStackTrace();
+		continue;
+	    }
+	    ac.setConfigParams(this.config_params);
+	    ac.setMessageRouter(this.mr);
+	    ac.configure();
+	    ac.getActionParameters(this.params);
+	    this.action_map.put(action_name, ac);
+
+	    // now do the xslt map
+	    String xslt = action.getAttribute("xslt");
+	    if (!xslt.equals("")) {
+		this.xslt_map.put(action_name, xslt);
+	    }
+	    NodeList subactions = action.getElementsByTagName(GSXML.SUBACTION_ELEM);
+	    for (int j=0; j<subactions.getLength(); j++) {
+		Element subaction = (Element)subactions.item(j);
+		String subname = subaction.getAttribute(GSXML.NAME_ATT);
+		String subxslt = subaction.getAttribute("xslt");
+		
+		String map_key = action_name+":"+subname;
+		logger.debug("adding in to xslt map, "+map_key+"->"+subxslt);
+		this.xslt_map.put(map_key, subxslt);
+	    }
+	    
+	   
+	}
+	Element lang_list = (Element)GSXML.getChildByTagName(config_elem, "languageList");
+	if (lang_list == null) {
+	    logger.error(" didn't find a language list in the config file!!");
+	} else {
+	    this.language_list = (Element) this.doc.importNode(lang_list, true);
+	}
+
+	return true;
+    }
+
+
+    protected Element postProcessPage(Element page) {
+	
+	// might need to add some data to the page
+	addExtraInfo(page);
+	// transform the page using xslt
+	Element transformed_page = transformPage(page);
+	
+	return transformed_page;
+    }
+    
+    /** overwrite this to add any extra info that might be needed in the page before transformation */
+    protected void addExtraInfo(Element page) {}
+
+    /** transform the page using xslt
+     * we need to get any format element out of the page and add it to the xslt
+     * before transforming */
+    protected Element transformPage(Element page) {
+
+	logger.debug("page before transfomring:");
+	logger.debug(this.converter.getPrettyString(page));
+
+	Element request = (Element)GSXML.getChildByTagName(page, GSXML.PAGE_REQUEST_ELEM);
+	String action = request.getAttribute(GSXML.ACTION_ATT);
+	String subaction = request.getAttribute(GSXML.SUBACTION_ATT);
+	
+	String output = request.getAttribute(GSXML.OUTPUT_ATT);
+	// we should choose how to transform the data based on output, eg diff
+	// choice for html, and wml??
+	// for now, if output=xml, we don't transform the page, we just return 
+	// the page xml
+	if (output.equals("xml")) {
+	    return page;
+	}
+
+	Element cgi_param_list = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	String collection = "";
+	if (cgi_param_list != null) {
+	    HashMap params = GSXML.extractParams(cgi_param_list, false);
+	    collection = (String)params.get(GSParams.COLLECTION);
+	    if (collection == null) collection = "";
+	}
+	
+	String xslt_file = getXSLTFileName(action, subaction, collection);
+	if (xslt_file==null) {
+	    // cant transform the page - return null or the original?
+	    logger.error(" cant find the xslt file needed, so returning the original page!");
+	    return page;
+	}
+	Document style_doc = this.converter.getDOM(new File(xslt_file), "UTF-8");
+	if (style_doc == null) {
+	    logger.error(" cant parse the xslt file needed, so returning the original page!");
+	    return page;
+	    
+	}
+
+	// look for the format element in the page response
+	Element page_response = (Element)GSXML.getChildByTagName(page, GSXML.PAGE_RESPONSE_ELEM);
+	Element format_elem = (Element)GSXML.getChildByTagName(page_response, GSXML.FORMAT_ELEM);
+	if (format_elem != null) {
+	    //page_response.removeChild(format_elem);
+	    logger.debug("format elem="+this.converter.getPrettyString(format_elem));
+	    // need to transform the format info
+	    String stylesheet_file = GSFile.stylesheetFile(GlobalProperties.getGSDL3Home(), (String)this.config_params.get(GSConstants.SITE_NAME), collection, (String)this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces,   "config_format.xsl");
+	    Document stylesheet_doc = this.converter.getDOM(new File(stylesheet_file));
+	    if (stylesheet_doc != null) {
+		Document format_doc = this.converter.newDOM();
+		format_doc.appendChild(format_doc.importNode(format_elem, true));
+		Element new_format = (Element)this.transformer.transform(stylesheet_doc, format_doc);
+	    logger.debug("new format elem="+this.converter.getPrettyString(new_format));
+	    
+	    // add it in to the main stylesheet
+		GSXSLT.mergeStylesheets(style_doc, new_format);
+	    } else {
+		logger.error(" couldn't parse the config_format stylesheet, adding the format info as is");
+		GSXSLT.mergeStylesheets(style_doc, format_elem);
+	    }
+	    logger.debug("the converted stylesheet is:");
+	    logger.debug(this.converter.getPrettyString(style_doc.getDocumentElement()));
+	}
+	
+	// there is a thing called a URIResolver which you can set for a transformer or transformer factory. may be able to use this instead of this absoluteIncludepaths hack
+	GSXSLT.absoluteIncludePaths(style_doc, GlobalProperties.getGSDL3Home(), (String)this.config_params.get(GSConstants.SITE_NAME), collection, (String)this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces);
+	// put the page into a document - this is necessary for xslt to get the paths right if you have paths relative to the document root eg /page.
+	Document doc = this.converter.newDOM();
+	doc.appendChild(doc.importNode(page, true));
+	return (Element)this.transformer.transform(style_doc, doc, config_params);          
+    }
+
+    protected String getXSLTFileName(String action, String subaction,
+				     String collection) {
+
+	String name = null;
+	if (!subaction.equals("")) {
+	    String key = action+":"+subaction;
+	    name = (String) this.xslt_map.get(key);
+	}
+	// try the action by itself
+	if (name==null) {
+	    name = (String) this.xslt_map.get(action);
+	}
+	// now find the absolute path
+	String stylesheet = GSFile.stylesheetFile(GlobalProperties.getGSDL3Home(), (String)this.config_params.get(GSConstants.SITE_NAME), collection, (String)this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces, name);
+	if (stylesheet==null) {
+	    logger.info(" cant find stylesheet for "+name);
+	}
+	return stylesheet;
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/selfContained/DocumentStream.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/selfContained/DocumentStream.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/selfContained/DocumentStream.java	(revision 13928)
@@ -0,0 +1,55 @@
+/*
+ *    DocumentStream.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.selfContained;
+
+// XML classes
+import org.w3c.dom.Document; 
+
+// other java classes
+import java.io.Serializable;
+
+
+/**
+ * Document Stream represents a stream of XML documents
+ *
+ * Based on algorithms in ...
+ *
+ * @author <a href="http://www.cs.waikato.ac.nz/~say1/">stuart yeates</a> (<a href="mailto:s.yeates@cs.waikato.ac.nz">s
+.yeates@cs.waikato.ac.nz</a>) at the <a href="http://www.nzdl.org">New Zealand Digital Library</a>
+ * @version $Revision$
+ * 
+ */
+public interface DocumentStream extends Cloneable, Serializable {
+  
+  /**
+   * Get the next document
+   * 
+   * @exception java.io.Exception when something goes wrong
+   * @return the next document
+   */
+  public Document nextDocument() throws Exception ;
+  /**
+   * Is there a next document?
+   * 
+   * @exception java.io.Exception when something goes wrong
+   * @return true if there is a next document
+   */
+  public boolean hasNextDocument() throws Exception ;
+  
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/selfContained/FilesDocumentStream.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/selfContained/FilesDocumentStream.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/selfContained/FilesDocumentStream.java	(revision 13928)
@@ -0,0 +1,196 @@
+/*
+ *    DocumentStreamFromFiles.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.selfContained;
+
+// XML classes
+import org.w3c.dom.Document; 
+import org.xml.sax.InputSource;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import org.apache.xerces.dom.DocumentImpl;
+import org.apache.xerces.dom.ElementImpl;
+import org.apache.xerces.dom.TextImpl;
+import org.w3c.dom.Document; 
+
+// other java classes
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.Vector;
+
+
+  
+/**
+ * DocumentStreamFromFiles creates a stream of documents from a directory or directories.
+ *
+ * @author <a href="http://www.cs.waikato.ac.nz/~say1/">stuart yeates</a> (<a href="mailto:s.yeates@cs.waikato.ac.nz">s
+.yeates@cs.waikato.ac.nz</a>) at the <a href="http://www.nzdl.org">New Zealand Digital Library</a>
+ * @version $Revision$
+ * @see java.io.File
+ * @see DocumentStream
+ */
+public class FilesDocumentStream 
+  implements DocumentStream {
+  /** the files we've found so far */
+  Vector files = new Vector();
+  /** the directories we've found so far */
+  Vector directories = new Vector();
+
+  /**
+   * Filename constructor
+   * 
+   * @exception java.io.IOException file access do
+   * @param filename the filename of the file or directory
+   */
+  public FilesDocumentStream(String filename)  {
+    File file = new File(filename);
+    if (file.exists() && file.isDirectory())
+      directories.add(file.getAbsolutePath());
+    else
+      files.add(file.getAbsolutePath());
+  }
+  /**
+   * File constructor
+   * 
+   * @exception java.io.IOException file access do
+   * @param file a handle to the file
+   */
+  public FilesDocumentStream(File file) {
+    if (file.exists() && file.isDirectory())
+      directories.add(file.getAbsolutePath());
+    else
+      files.add(file.getAbsolutePath());
+  }
+
+  /** 
+   * A small inner class to filter out those files that don't 
+   * end in ".xml" or ".XML"
+   */
+  class XMLFilenameFilter implements FilenameFilter {
+    /** Tests if a specified file should be included in a file list. */
+    public boolean accept(File dir, String name) {
+      String target = ".xml";
+      if (name.length() < target.length())
+	return false;
+      String extension = name.substring(name.length() - 4, name.length());
+      //System.out.println(name + " ==>> " +  extension);
+      if (extension.equalsIgnoreCase(target)) {
+	return true;
+      } else {
+	return false;
+      }
+    }    
+  }
+
+  /**
+   * Opens a new directory if there are no files are queued
+   * 
+   * @exception java.io.IOException when the underlying file access does
+   */
+  protected void expandIfNecessary() {
+    while (directories.size() > 0) {
+      String dirname = (String) directories.elementAt(0);
+      directories.removeElement(dirname);
+      File dir = new File(dirname);
+      if (!dir.exists()) throw new Error ("error in expand: expecting a directory " + dirname);
+      String[] fileArray = dir.list();
+      for (int i=0;i<fileArray.length;i++){
+	File file = new File(dir, fileArray[i]);
+	if (file.exists() && file.isDirectory()) 
+	  directories.add(file.getPath());
+      }
+      
+      fileArray = dir.list(new XMLFilenameFilter());
+      for (int i=0;i<fileArray.length;i++){
+	File file = new File(dir, fileArray[i]);
+	if (file.exists() && !file.isDirectory())
+	  files.add(file.getPath());
+      }
+      if (files.size() > 0)
+	return;
+    }
+  }
+  
+  /**
+   * Returns the next document
+   * 
+   * @exception java.io.IOException when the underlying file access does
+   * @return the next document
+   */
+  public Document nextDocument()
+    throws Exception {
+    
+    if (!hasNextDocument()) throw new Error("Doesn't have another Document");
+
+    String filename = (String) files.elementAt(files.size() - 1);
+    files.removeElementAt(files.size() - 1);
+    File file = new File(filename);
+    
+    Reader reader = new FileReader(file);
+    InputSource xml_source = new InputSource(reader);
+
+    XMLUtil.getDOMParser().parse(xml_source);
+    Document doc = XMLUtil.getDOMParser().getDocument();
+    
+    return doc;
+  }
+    
+  /**
+   * Is there another document ?
+   * 
+   * @exception java.io.IOException when the underlying file access does
+   * @return the next document
+   */
+
+  public boolean hasNextDocument()  throws Exception {
+    expandIfNecessary();
+    return (files.size() > 0);
+  }
+  /**
+   * Tests...
+   *
+   * 
+   * @exception java.io.IOException when ...
+   * @param args the arguments ...
+   */
+
+  public static void main(String args[]) throws Exception
+  {
+   
+    StreamResult result = new StreamResult(System.out);
+    TransformerFactory transformerFactory = TransformerFactory.newInstance();
+    
+    FilesDocumentStream stream = new FilesDocumentStream(".");
+    while (stream.hasNextDocument()) {
+      Document document = stream.nextDocument();
+      Transformer transformer = transformerFactory.newTransformer();
+      Source source = new DOMSource(document);
+      transformer.transform(source,result);
+      System.out.println();
+      System.out.println();
+    }
+
+  } 
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/selfContained/GeneratedDocumentStream.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/selfContained/GeneratedDocumentStream.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/selfContained/GeneratedDocumentStream.java	(revision 13928)
@@ -0,0 +1,148 @@
+/*
+ *    GenerateDocumentStream.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.selfContained;
+
+// XML classes
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import org.apache.xerces.dom.DocumentImpl;
+import org.apache.xerces.dom.ElementImpl;
+import org.apache.xerces.dom.TextImpl;
+import org.w3c.dom.Document; 
+
+
+// other java classes
+
+/**
+ * GeneratedDocumentStream generates an unbounded stream of XML documents
+ * Each containing a single string.
+ *
+ * Based as a wrapper around an Increment object
+ *
+ * @author <a href="http://www.cs.waikato.ac.nz/~say1/">stuart yeates</a> (<a href="mailto:s.yeates@cs.waikato.ac.nz">s
+.yeates@cs.waikato.ac.nz</a>) at the <a href="http://www.nzdl.org">New Zealand Digital Library</a>
+ * @version $Revision$
+ * @see DocumentStream
+ * @see Increment
+ * 
+ */
+public class GeneratedDocumentStream implements DocumentStream {
+  
+  /** The next string */
+  protected String next = "";
+  /** The underlying Increment object */
+  protected Increment incrementer = new IncrementRange();
+
+  /** The default constructor. Generates ASCII-only documents */
+  public GeneratedDocumentStream() {
+
+  }
+  
+  /** 
+   * Custom constructor 
+   *
+   * @param incrementer the incrementer to use (controls the character set to use)
+   */
+  public GeneratedDocumentStream(Increment incrementer) {
+    this.incrementer = incrementer;
+  }
+  
+  /** 
+   * Custom constructor 
+   *
+   * @param next the string for the first document (must suit the incrementor)
+   */
+  public GeneratedDocumentStream(String next) {
+    this.next = next;
+  }
+  
+  /** 
+   * Custom constructor 
+   *
+   * @param incrementer the incrementer to use (controls the character set to use)
+   * @param next the string for the first document (must suit the incrementor)
+   */
+  public GeneratedDocumentStream(Increment incrementer, String next) {
+    this.incrementer = incrementer;
+    this.next = next;
+  }
+  /** 
+   * Custom constructor 
+   *
+   * @param first the first letter in the alphabet
+   * @param last the last letter in the alphabet
+   */
+  public GeneratedDocumentStream(char first, char last) {
+    this.incrementer = new IncrementRange(first,last);
+  }
+
+
+  /**
+   * Generates the nest document in the sequence
+   * 
+   * @exception java.io.Exception when something goes wrong in the XML stuff
+   * @return the next Document
+   * @see org.w3c.dom.Document
+   */
+  public Document nextDocument() {
+
+
+   DocumentImpl doc = new DocumentImpl(true);
+    
+   ElementImpl root = new ElementImpl(doc,"document");
+   TextImpl text = new TextImpl(doc,next);
+    
+   doc.appendChild(root);
+   root.appendChild(text);
+ 
+   next = incrementer.incrementString(next);
+   return doc;
+   
+  }
+  /**
+   * Are there more documents ?
+   * 
+   * @return yes
+   */
+  public boolean hasNextDocument(){
+    return true;
+  }
+  /**
+   * Generates an unbounded stream of documents
+   */
+  public static void main(String args[]) throws Exception
+  {
+    
+    StreamResult result = new StreamResult(System.out);
+    TransformerFactory transformerFactory = TransformerFactory.newInstance();
+    
+    GeneratedDocumentStream stream = new GeneratedDocumentStream();
+    while (stream.hasNextDocument()) {
+      Document document = stream.nextDocument();
+      Transformer transformer = transformerFactory.newTransformer();
+      Source source = new DOMSource(document);
+      transformer.transform(source,result);
+    }
+  }
+  
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/selfContained/Increment.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/selfContained/Increment.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/selfContained/Increment.java	(revision 13928)
@@ -0,0 +1,111 @@
+/*
+ *    Increment.java
+ *    Copyright (C) 2000-2001 Stuart Yeates 
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+// the package we're in
+package org.greenstone.gsdl3.selfContained;
+
+// java standard library classes used
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Serializable;
+import java.io.Writer;
+
+
+/**
+ * Class Increment is an abstract class for incrementing streams and strings
+ *
+ *
+ * @author <a href="http://www.cs.waikato.ac.nz/~say1/">stuart yeates</a> (<a href="mailto:s.yeates@cs.waikato.ac.nz">s.yeates@cs.waikato.ac.nz</a>) at the <a href="http://www.nzdl.org">New Zealand Digital Library</a>
+ * @version $Revision$
+ */
+
+abstract public class Increment implements Cloneable, Serializable
+{
+  /**
+   * Increment a string of characters
+   * 
+   * @exception java.io.Exception if any of the characters in the string are outside the range of first-last
+   * @param str the string to be incremented
+   * @return the incremented string
+   * @see Increment
+   */
+  abstract String incrementString(String str);
+
+  /**
+   * Increment a stream of characters, reading from the reader and writing the incremented characters to the writer
+   * 
+   * @exception java.io.Exception if any of the characters in the string are outside the range of first-last
+   * @param str the string to be incremented
+   * @return the incremented string
+   * @see Increment
+   */
+  abstract long incrementStream(Reader rdr, Writer wtr);
+
+  /**
+   * Print to standard out a verbose message about the 
+   * results of incrementing this string
+   * 
+   * @param s the string to increment
+   * @see #incrementString(String)
+   */
+  final void checkStr(String s) {
+    try {
+      System.out.println("incrementing: \"" + s +
+			 "\" to \"" + incrementString(s) +
+			 "\"  " + stringToOctal(s) +
+			 " ===> " + stringToHex(incrementString(s)));
+    } catch (Exception e) {
+      System.out.println("Caught exception: " + e);
+    }
+  }
+
+  /**
+   * Converts a unicode string to Hex
+   * 
+   * @exception java.io.IOException when ...
+   * @param s the string to convert
+   * @return a string in hex
+   * @see Integer#toHexString(int)
+   */
+  static final String stringToHex(String s) {
+    StringBuffer buffer = new StringBuffer();
+    for (int i=0;i<s.length();i++) {
+      buffer.append(" 0x");
+      buffer.append(Integer.toHexString(s.charAt(i)));
+    } 
+    return buffer.toString();
+  }
+
+  /**
+   * Converts a unicode string to Octal
+   * 
+   * @param s the string
+   * @return the string in octal
+   * @see Integer#toOctalString(int)
+   */
+  static final String stringToOctal(String s) {
+    StringBuffer buffer = new StringBuffer();
+    for (int i=0;i<s.length();i++) {
+      buffer.append(" 0x");
+      buffer.append(Integer.toOctalString(s.charAt(i)));
+    } 
+    return buffer.toString();
+  }
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/selfContained/IncrementRange.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/selfContained/IncrementRange.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/selfContained/IncrementRange.java	(revision 13928)
@@ -0,0 +1,240 @@
+/*
+ *    IncrementRange.java
+ *    Copyright (C) 2000-2001 Stuart Yeates 
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+// the package we're in
+package org.greenstone.gsdl3.selfContained;
+
+// java standard library classes used
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Serializable;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+
+/**
+ * Class IncrementRange increments strings and streams over a limited range of Characters.
+ *
+ *
+ * @author <a href="http://www.cs.waikato.ac.nz/~say1/">stuart yeates</a> (<a href="mailto:s.yeates@cs.waikato.ac.nz">s.yeates@cs.waikato.ac.nz</a>) at the <a href="http://www.nzdl.org">New Zealand Digital Library</a>
+ * @version $Revision$
+ * @see Increment
+ * 
+ */
+final public class IncrementRange
+  extends Increment 
+  implements Cloneable, Serializable
+{
+  /**
+   * Create an IncrementRange which counts between first and last inclusive
+   * 
+   * @param first the first character in the range
+   * @param last the last character in the range
+   * @see Increment
+   */
+  IncrementRange(char first, char last){
+    this.first = first;
+    this.last = last;
+  }
+  /**
+   * Create a default IncrementRange
+   * 
+   * @see Increment
+   */
+  IncrementRange(){
+  }
+
+  /**
+   * Create a IncrementRange over all Unicode characters
+   * 
+   * @see Increment
+   */
+  IncrementRange(boolean b){
+    if (true) {
+      this.first = Character.MIN_VALUE;
+      this.last = Character.MAX_VALUE;
+    }
+  }  
+  /** the last character in out range */
+  private char first = ' ';
+  /** the last character in out range */
+  private char last = 'z';
+
+  /**
+   * Increment a stream of characters, reading from the reader and writing the incremented characters to the writer
+   * 
+   * @exception java.io.Error if any of the characters in the string are outside the range of first-last
+   * @param str the string to be incremented
+   * @return the incremented string
+   * @see Increment
+   */
+  long incrementStream(Reader rdr, Writer wtr) {
+    try {
+      long count = 0; // the return value
+    
+      int i = rdr.read();
+      boolean carry = true;
+    
+      while (i != -1) {
+	char c = (char) i;
+      
+	// check the validity of the character we're about to increment
+	if (c < first || c > last) 
+	  throw new Error("Character '" + c + "' is ouside range");
+      
+	if (c == last) {
+	  if (carry == true) {
+	    wtr.write(first);
+	    carry = true;
+	  } else {
+	    wtr.write(c);
+	    carry = false;
+	  }
+	} else {
+	  if (carry == true) {
+	    wtr.write(++c);
+	    carry = false;
+	  } else {
+	    wtr.write(c);
+	    carry = false;
+	  } 
+	}
+	count++;
+
+	// read the next character
+	i = rdr.read();
+      }
+      if (carry == true) {
+	wtr.write(first);
+	count++;
+      }
+      return count;
+    } catch (IOException e) {
+      System.err.println("IOException in incrementStream()");
+      throw new Error(e.toString());
+    }
+  }
+
+  /**
+   * Increment a string of characters
+   * 
+   * @exception java.lang.Error if any of the characters in the string are outside the range of first-last
+   * @param str the string to be incremented
+   * @return the incremented string
+   * @see Increment
+   */
+  public final String incrementString(String str)  {
+    StringBuffer buffer = new StringBuffer();
+    if (str.equals("")) {
+      buffer.append(first);
+      return buffer.toString();
+    } else {
+      boolean carry = true;
+      for (int i=0;i<str.length();i++) {
+	char c = str.charAt(i);
+	if (c < first || c > last) 
+	  throw new Error("Character '" + c + "' is ouside range");
+
+	if (c == last) {
+	  if (carry == true) {
+	    buffer.append(first);
+	    carry = true;
+	  } else {
+	    buffer.append(c);
+	    carry = false;
+	  }
+	} else {
+	  if (carry == true) {
+	    buffer.append(++c);
+	    carry = false;
+	  } else {
+	    buffer.append(c);
+	    carry = false;
+	  } 
+	}
+      }
+      if (carry == true)
+	buffer.append(first);
+    }
+    return buffer.toString();
+  }
+
+
+  /**
+   * Test the incrementing of strings (never returns)
+   */
+  public static void testStringIncrement() throws IOException
+  {
+    IncrementRange n = new IncrementRange ();
+    try {
+      String tmp = "";
+      System.out.println(stringToHex(tmp));
+      while (true) {
+	//checkStr(tmp);
+	tmp = n.incrementString(tmp);
+	n.checkStr(tmp);
+      }
+    } catch (Exception e) {
+      System.out.println("Caught exception: " + e);
+    }
+
+  }
+
+  /**
+   * Test the incrementing of streams (never returns)
+   *
+   */
+  public static void testStreamIncrement() 
+  {
+    IncrementRange n = new IncrementRange ();
+    try {
+      long counter = 0;
+      String tmp = "";
+      System.out.println(stringToHex(tmp));
+      while (true) {
+	//checkStr(tmp);
+	String tmp2 = n.incrementString(tmp);
+	StringWriter wtr = new StringWriter();
+	n.incrementStream(new StringReader(tmp),wtr);
+	if (!tmp2.equals(wtr.toString()))
+	  throw new Exception("Error: \"" + tmp2 + 
+			      "\" and \"" + tmp2 + 
+			      "\"");
+	counter++;
+	if (counter % 1000000 == 0)
+	  System.out.println(counter + " " + tmp);
+
+	tmp = tmp2;
+      }
+    } catch (Exception e) {
+      System.out.println("Caught exception: " + e);
+    }
+  }
+
+  /**
+   * Tests stream incrementing 
+   *
+   * 
+   */
+  public static void main(String args[]) 
+  {
+    testStreamIncrement();
+  } 
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/selfContained/QueryDocumentStream.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/selfContained/QueryDocumentStream.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/selfContained/QueryDocumentStream.java	(revision 13928)
@@ -0,0 +1,281 @@
+/*
+ *    QueryDocumentStream.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.selfContained;
+
+// XML classes
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+import org.w3c.dom.Document;
+
+// other java classes
+import java.io.StringReader;
+
+/**
+ * QueryDocumentStream takes another document stream and removes 
+ * from the stream all documents which fail to match a XSLT query.
+ * The default query returns only those documents containing the 
+ * string "the".
+ *
+ * @author <a href="http://www.cs.waikato.ac.nz/~say1/">stuart yeates</a> (<a href="mailto:s.yeates@cs.waikato.ac.nz">s
+.yeates@cs.waikato.ac.nz</a>) at the <a href="http://www.nzdl.org">New Zealand Digital Library</a>
+ * @version $Revision$
+ * @see DocumentStream
+ * 
+ */
+public class QueryDocumentStream implements DocumentStream {
+  
+  /** The default XSLT query string. Is true (returns a non-empty document) when the input document contains the string "the". */
+  public static final String DEFAULT_QUERY_STRING =   
+    "<xsl:stylesheet version=\"1.0\" " +
+    "                    xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">" +
+    "   <xsl:output omit-xml-declaration=\"yes\"/>" +
+    
+    "   <xsl:template match=\"/*\">" +
+    "      <xsl:if test=\"contains(.,'the')\">" +
+    "         <xsl:copy-of select=\".\"/>" +
+    "      </xsl:if>" + 
+    "   </xsl:template>" +
+    "</xsl:stylesheet>";
+  /** The first part of the default quesy for a string other than "the" */
+  public static final String DEFAULT_QUERY_STRING_1_1 =   
+    "<xsl:stylesheet version=\"1.0\" " +
+    "                    xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">" +
+    "   <xsl:output omit-xml-declaration=\"yes\"/>" +
+    
+    "   <xsl:template match=\"/*\">" +
+    "      <xsl:if test=\"contains(.,'";
+
+  /** The second part of the default quesy for a string other than "the" */
+  public static final String DEFAULT_QUERY_STRING_1_2 =   
+    "')\">" +
+    "         <xsl:copy-of select=\".\"/>" +
+    "      </xsl:if>" + 
+    "   </xsl:template>" +
+    "</xsl:stylesheet>";
+
+
+  /** The query */
+  protected StreamSource query = new StreamSource(new StringReader(DEFAULT_QUERY_STRING));
+
+  /** The underlying DocumentStream object */
+  protected DocumentStream stream = null;
+
+  /** A cached Document */
+  protected Document cached = null;
+
+  /** The transformer factory */
+  TransformerFactory transformerFactory  = null;
+
+  /** The transformer */
+  Transformer transformer  = null;
+
+  /** Uses the default query (looking for the) over the default DocumentStream (all ascii strings) */
+  public QueryDocumentStream() {
+    this.query = new StreamSource(new StringReader(DEFAULT_QUERY_STRING));
+    this.stream = new GeneratedDocumentStream();
+
+    try {
+      this.transformerFactory 
+	= org.apache.xalan.processor.TransformerFactoryImpl.newInstance();
+      
+      this.transformer
+	= transformerFactory.newTransformer(query);
+    } catch (TransformerConfigurationException e) {
+      System.err.println("XMLTransformer: couldn't create transformer object: "+e.getMessage());
+    }
+  }
+  
+  /** Looks for the given string in the stream of documents  */
+  public QueryDocumentStream(DocumentStream stream, String query) {
+    String fullQuery = DEFAULT_QUERY_STRING_1_1 + query + DEFAULT_QUERY_STRING_1_2;
+    this.query = new StreamSource(new StringReader(fullQuery));
+    this.stream = stream;
+
+    try {
+      this.transformerFactory 
+	= org.apache.xalan.processor.TransformerFactoryImpl.newInstance();
+      
+      this.transformer
+	= transformerFactory.newTransformer(this.query);
+    } catch (TransformerConfigurationException e) {
+      System.err.println("XMLTransformer: couldn't create transformer object: "+e.getMessage());
+    }
+  }
+  
+
+  /** Applies the stylesheet to the stream.  */
+  public QueryDocumentStream(DocumentStream stream, StreamSource source) {
+    this.query = source;
+    this.stream = stream;
+
+    try {
+      this.transformerFactory 
+	= org.apache.xalan.processor.TransformerFactoryImpl.newInstance();
+      
+      this.transformer
+	= transformerFactory.newTransformer(query);
+    } catch (TransformerConfigurationException e) {
+      System.err.println("XMLTransformer: couldn't create transformer object: "+e.getMessage());
+    }
+  }
+  
+
+  /** The default constructor. Searches for documents containing "the" */
+  public QueryDocumentStream(DocumentStream stream) {
+    this.query = new StreamSource(new StringReader(DEFAULT_QUERY_STRING));
+    this.stream = stream;
+
+    try {
+      this.transformerFactory 
+	= org.apache.xalan.processor.TransformerFactoryImpl.newInstance();
+      
+      this.transformer
+	= transformerFactory.newTransformer(query);
+    } catch (TransformerConfigurationException e) {
+      System.err.println("XMLTransformer: couldn't create transformer object: "+e.getMessage());
+    }
+  }
+  /**
+   * Generates the nest document in the sequence
+   * 
+   * @exception java.io.Exception when something goes wrong in the XML stuff
+   * @return the next Document
+   * @see org.w3c.dom.Document
+   */
+  public Document nextDocument() throws Exception {
+
+    if (hasNextDocument() == false)
+      throw new Error("no more docs");
+    Document result = cached;
+    cached = null;
+    return result;
+  }
+  /**
+   * Are there more documents ?
+   * 
+   * @return true if there are more docs
+   */
+  public boolean hasNextDocument() throws Exception {
+    lookInStream();
+    return (cached != null);
+  }
+  /**
+   *
+   * 
+   * @exception java.io.IOException when ...
+   * @param arg2 ... 
+   * @param arg1 ...
+   * @return ...
+   */
+  protected boolean lookInStream() throws Exception {
+
+    while (stream.hasNextDocument() && cached == null) {
+      
+      Document candidate = stream.nextDocument();
+      
+      DOMSource input = new DOMSource(candidate);
+      DOMResult output = new DOMResult();
+      
+      try {
+	
+	transformer.transform(input, output);
+      
+	// if the transformed document is not empty don't cache it
+	if (output.getNode().getFirstChild() != null)
+	  cached = (Document) output.getNode();
+      
+      } catch (TransformerConfigurationException e) {
+	System.err.println("XMLTransformer: couldn't create transformer object: "+e.getMessage());
+      } catch (TransformerException e) {
+	System.err.println("XMLTransformer: couldn't transform the source: " + e.getMessage());
+	cached = null;
+	return false;
+      } catch (Exception e) {
+	System.err.println("Exception: " + e.getMessage());
+	cached = null;
+	return false;
+      }
+      
+      if (false) { // debugging info
+	
+	try {
+	  StreamResult result = new StreamResult(System.out);
+	  Transformer transformer = transformerFactory.newTransformer();
+	  
+	  Source source = new DOMSource(candidate);
+	  transformer.transform(source,result);
+	  
+	  System.out.print(" ==> ");
+	  
+	  if (cached != null) {
+	    Source source2 = new DOMSource(cached);
+	    transformer.transform(source2,result);
+	  } 
+	  System.out.println();
+	  System.out.println("======================================================");
+	  
+	} catch (TransformerConfigurationException e) {
+	  System.err.println("XMLTransformer: couldn't create transformer object: "+e.getMessage());
+	} catch (TransformerException e) {
+	  System.err.println("XMLTransformer: couldn't transform the source: " + e.getMessage());
+	  cached = null;
+	  return false;
+	} catch (Exception e) {
+	  System.err.println("Exception: " + e.getMessage());
+	  cached = null;
+	  return false;
+	}
+	
+      }
+    }
+    return cached == null;    
+  }
+
+  /**
+   * Generates an unbounded stream of documents
+   */
+  public static void main(String args[]) throws Exception
+  {
+    TransformerFactory transformerFactory = TransformerFactory.newInstance();
+    Transformer transformer = transformerFactory.newTransformer();
+    
+    GeneratedDocumentStream gStream = new GeneratedDocumentStream();
+    QueryDocumentStream qStream = new QueryDocumentStream(gStream);
+    while (qStream.hasNextDocument()) {
+      Document document = qStream.nextDocument();
+      
+      StreamResult result = new StreamResult(System.out);
+      
+      Source source = new DOMSource(document);
+      transformer.transform(source,result);
+      
+      System.out.println();
+      System.out.println("======================================================");
+    }
+  }
+  
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/selfContained/XMLUtil.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/selfContained/XMLUtil.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/selfContained/XMLUtil.java	(revision 13928)
@@ -0,0 +1,96 @@
+/*
+ *    XMLUtil.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.selfContained;
+
+// XML classes
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.apache.xerces.parsers.DOMParser;
+
+// other java classes
+import java.io.IOException;
+
+
+/**
+ * Class XMLUtil holds static global XML configuration objects. 
+ * 
+ * @author <a href="http://www.cs.waikato.ac.nz/~say1/">stuart yeates</a> (<a href="mailto:s.yeates@cs.waikato.ac.nz">s
+.yeates@cs.waikato.ac.nz</a>) at the <a href="http://www.nzdl.org">New Zealand Digital Library</a>
+ * @version $Revision$
+ * 
+ */
+class XMLUtil {
+
+  /** the singleton instance */
+  protected static XMLUtil instance = null;
+
+
+  /** JAXP parser factory */ 
+  protected DocumentBuilderFactory doc_build_fact=null;
+
+  /** JAXP parser factory */ 
+  static public DocumentBuilderFactory getDocumentBuilderFactory() {
+    if (instance == null) 
+      init();
+    return instance.doc_build_fact;
+  }
+
+  /** JAXP parser */ 
+  protected DocumentBuilder doc_builder=null;
+
+  /** JAXP parser */ 
+  static public DocumentBuilder getDocumentBuilder() {
+    if (instance == null) 
+      init();
+    return instance.doc_builder;
+   }
+
+  /** xerces parser */
+  protected DOMParser parser = null;
+
+  /** xerces parser */
+  static public DOMParser getDOMParser() {
+    if (instance == null) 
+      init();
+    return instance.parser;
+  }
+
+  /** initalise the statics */
+  static protected void init() {
+    instance = new XMLUtil();
+    try {
+      instance.doc_build_fact = DocumentBuilderFactory.newInstance();
+      
+      instance.doc_builder = instance.doc_build_fact.newDocumentBuilder(); 
+      instance.parser = new DOMParser();
+    } catch (Exception e) {
+      System.out.println("XMLConverter:exception "+e.getMessage());
+    }
+  }
+
+  /**
+   * Checks that the objects can be instantiated
+   *
+   */
+  public static void main(String args[]) throws IOException
+  {
+    XMLUtil.getDOMParser();
+  }
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/selfContained/go.dtd
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/selfContained/go.dtd	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/selfContained/go.dtd	(revision 13928)
@@ -0,0 +1,103 @@
+<!-- P is the Paragraph of HTML -->
+<!ELEMENT P (#PCDATA)>
+
+<!-- Each Go file consists of one or several GoGame -->
+<!ELEMENT Go (GoGame*)>
+
+<!-- Each GoGame consists of the game Information and the game tree -->
+
+<!ELEMENT GoGame (Information,Nodes)>
+<!ATTLIST GoGame name CDATA #IMPLIED>
+<!ELEMENT Nodes (((Node|Black|White),(Node|Variation|Black|White|Comment)*)?)>
+
+<!ELEMENT Information (Application?|BoardSize?|BlackPlayer?|BlackRank?|
+	WhitePlayer?|WhiteRank?|Date?|Time?|Komi?|Result?|Handicap?|User?|
+	Copyright?|Annotation?|BlackTeam?|WhiteTeam?|Round?|Rules?|Source?)*>
+<!ELEMENT Application (#PCDATA)>
+<!ATTLIST Application format CDATA #IMPLIED>
+<!ELEMENT BoardSize (#PCDATA)>
+<!ATTLIST BoardSize format CDATA #IMPLIED>
+<!ELEMENT BlackPlayer (#PCDATA)>
+<!ATTLIST BlackPlayer format CDATA #IMPLIED>
+<!ELEMENT WhitePlayer (#PCDATA)>
+<!ATTLIST WhitePlayer format CDATA #IMPLIED>
+<!ELEMENT BlackRank (#PCDATA)>
+<!ATTLIST BlackRank format CDATA #IMPLIED>
+<!ELEMENT WhiteRank (#PCDATA)>
+<!ATTLIST WhiteRank format CDATA #IMPLIED>
+<!ELEMENT Date (#PCDATA)>
+<!ATTLIST Date format CDATA #IMPLIED>
+<!ELEMENT Time (#PCDATA)>
+<!ATTLIST Time format CDATA #IMPLIED>
+<!ELEMENT Komi (#PCDATA)>
+<!ATTLIST Komi format CDATA #IMPLIED>
+<!ELEMENT Handicap (#PCDATA)>
+<!ATTLIST Handicap format CDATA #IMPLIED>
+<!ELEMENT Result (#PCDATA)>
+<!ATTLIST Result format CDATA #IMPLIED>
+<!ELEMENT User (#PCDATA)>
+<!ELEMENT Copyright (P+)>
+<!ELEMENT Annotation (#PCDATA)>
+<!ELEMENT BlackTeam (#PCDATA)>
+<!ELEMENT WhiteTeam (#PCDATA)>
+<!ELEMENT Round (#PCDATA)>
+<!ELEMENT Rules (#PCDATA)>
+<!ATTLIST Rules format CDATA #IMPLIED>
+<!ELEMENT Source (#PCDATA)>
+<!ATTLIST Source format CDATA #IMPLIED>
+
+<!-- Game representation in Nodes -->
+
+<!ELEMENT Node ((SGF|Comment|Black|White|AddBlack|AddWhite|Mark|Delete)*)>
+<!ATTLIST Node name CDATA #IMPLIED>
+
+<!-- Possible content of a node (unordered) -->
+
+<!-- Alternative form of specifying the position as tag content. -->
+<!-- The board position is either like D10 or 4,10 (for larger boards). -->
+<!ELEMENT at (#PCDATA)>
+
+<!ELEMENT Comment (P+)>
+<!ELEMENT Black ((at)*)>
+<!ATTLIST Black
+	at CDATA #IMPLIED
+	number CDATA #IMPLIED
+	timeleft CDATA #IMPLIED
+	annotate CDATA #IMPLIED>
+<!ELEMENT White ((at)*)>
+<!ATTLIST White
+	at CDATA #IMPLIED
+	number CDATA #IMPLIED
+	timeleft CDATA #IMPLIED
+	annotate CDATA #IMPLIED>
+<!ELEMENT AddBlack ((at)*)>
+<!ATTLIST AddBlack
+	at CDATA #IMPLIED>
+<!ELEMENT AddWhite ((at)*)>
+<!ATTLIST AddWhite
+	at CDATA #IMPLIED>
+<!ELEMENT Delete ((at)*)>
+<!ATTLIST Delete
+	at CDATA #IMPLIED>
+<!ELEMENT Mark ((at)*)>
+<!ATTLIST Mark 
+	label CDATA #IMPLIED
+	at CDATA #IMPLIED
+	type (square|circle|triangle) #IMPLIED
+	territory (black|white) #IMPLIED>
+<!ELEMENT BlackToPlay (#PCDATA)>
+<!ELEMENT WhiteToPlay (#PCDATA)>
+<!ELEMENT Line (#PCDATA)>
+<!ATTLIST Line 
+	format CDATA #IMPLIED
+	type CDATA #IMPLIED>
+
+<!-- This is to take care of SGF tags, which are not translated -->
+<!ELEMENT SGF (Arg*)>
+<!ATTLIST SGF
+	type CDATA #REQUIRED>
+<!ELEMENT Arg (#PCDATA)>
+
+<!-- Note that the Variation are ALTERNATIVES to the current node -->
+<!-- This is different from SGF and makes the file easier to read by humans -->
+<!ELEMENT Variation ((Node|Variation|White|Black|Comment)*)>
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractBrowse.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractBrowse.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractBrowse.java	(revision 13928)
@@ -0,0 +1,732 @@
+/*
+ *    AbstractBrowse.java
+ *    Copyright (C) 2005 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.service;
+
+
+// Greenstone classes
+import org.greenstone.gsdl3.util.GSXML;
+import org.greenstone.gsdl3.util.GSPath;
+import org.greenstone.gsdl3.util.MacroResolver;
+import org.greenstone.gsdl3.util.OID;
+
+// XML classes
+import org.w3c.dom.Document;
+import org.w3c.dom.Element; 
+import org.w3c.dom.NodeList;
+
+// General Java classes
+import java.util.ArrayList;
+
+import org.apache.log4j.*;
+
+/** Partially implements a generic classifier service
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ */
+public abstract class AbstractBrowse
+    extends ServiceRack {
+
+     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.AbstractBrowse.class.getName());
+
+    // the browsing services
+    private static final String CLASSIFIER_SERVICE = "ClassifierBrowse";
+    private static final String CLASSIFIER_METADATA_SERVICE = "ClassifierBrowseMetadataRetrieve";
+
+    // do we want to keep info request?
+    
+    protected static final String STRUCT_PARAM = "structure";
+    protected static final String INFO_PARAM = "info";
+    
+    protected static final String STRUCT_ANCESTORS = "ancestors";
+    protected static final String STRUCT_PARENT = "parent";
+    protected static final String STRUCT_SIBS = "siblings";
+    protected static final String STRUCT_CHILDREN = "children";
+    protected static final String STRUCT_DESCENDS = "descendants";
+    protected static final String STRUCT_ENTIRE = "entire";
+
+    protected static final String INFO_NUM_SIBS = "numSiblings";
+    protected static final String INFO_NUM_CHILDREN = "numChildren";
+    protected static final String INFO_SIB_POS = "siblingPosition";
+
+    protected Element config_info = null; // the xml from the config file
+
+    protected MacroResolver macro_resolver = null;
+
+    protected String default_document_type = null;
+    /** constructor */
+    protected AbstractBrowse()
+    {
+    }
+
+
+    /** configure this service */
+    public boolean configure(Element info, Element extra_info)
+    {
+	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+
+	logger.info("Configuring AbstractBrowse...");
+	this.config_info = info;
+
+	if (macro_resolver != null) {
+	    macro_resolver.setSiteDetails(this.site_http_address, this.cluster_name);
+	    // set up the macro resolver
+	    Element replacement_elem = (Element)GSXML.getChildByTagName(extra_info, "replaceList");
+	    if (replacement_elem != null) {
+		macro_resolver.addMacros(replacement_elem);
+	    }
+
+	}
+
+ 
+        // check that there are classifiers specified
+        Element class_list = (Element)GSXML.getChildByTagName(info, GSXML.CLASSIFIER_ELEM+GSXML.LIST_MODIFIER);
+        if (class_list == null) {
+            // no classifiers specified
+            return false;
+        }
+	
+	// get the display and format elements from the coll config file for
+	// the classifiers
+	extractExtraClassifierInfo(info, extra_info);
+	
+        // short_service_info_ - the browse one
+        Element cb_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+        cb_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_BROWSE);
+        cb_service.setAttribute(GSXML.NAME_ATT, CLASSIFIER_SERVICE);
+        this.short_service_info.appendChild(cb_service);
+	
+	// metadata retrieval for the browsing  
+        Element cbmr_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+        cbmr_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
+        cbmr_service.setAttribute(GSXML.NAME_ATT, CLASSIFIER_METADATA_SERVICE);
+        this.short_service_info.appendChild(cbmr_service);
+
+	// the format info
+	Element cb_format_info = this.doc.createElement(GSXML.FORMAT_ELEM);
+	boolean format_found = false;
+
+	// try the default format first
+	Element def_format = (Element) GSXML.getChildByTagName(info, GSXML.FORMAT_ELEM);
+	if (def_format != null) {
+	    cb_format_info.appendChild(GSXML.duplicateWithNewName(this.doc, def_format, GSXML.DEFAULT_ELEM, true));
+	    format_found = true;
+	}
+	
+	// add in to the description a simplified list of classifiers
+        NodeList classifiers = class_list.getElementsByTagName(GSXML.CLASSIFIER_ELEM);
+	for(int i=0; i<classifiers.getLength(); i++) {
+	    Element cl = (Element)classifiers.item(i);
+	    Element new_cl = (Element)this.doc.importNode(cl, false); // just import this node, not the children
+	    
+	    // get the format info out, and put inside a classifier element
+	    Element format_cl = (Element)new_cl.cloneNode(false);
+	    Element format = (Element)GSXML.getChildByTagName(cl, GSXML.FORMAT_ELEM);
+	    if (format != null) {
+		
+		//copy all the children
+		NodeList elems = format.getChildNodes();
+		for (int j=0; j<elems.getLength();j++) {
+		    format_cl.appendChild(this.doc.importNode(elems.item(j), true));
+		}
+		cb_format_info.appendChild(format_cl);
+		format_found = true;
+	    }
+	    	    
+	}
+	    
+	if (format_found) {
+	    this.format_info_map.put(CLASSIFIER_SERVICE, cb_format_info);
+	}
+
+	// look for document display format - is there a default doc type??
+	String path = GSPath.appendLink(GSXML.DISPLAY_ELEM, GSXML.FORMAT_ELEM);
+	Element display_format = (Element)GSXML.getNodeByPath(extra_info, path);
+	if (display_format != null) {
+	    // check for docType option.
+	    Element doc_type_opt = GSXML.getNamedElement(display_format, "gsf:option", GSXML.NAME_ATT, "documentType");
+	    if (doc_type_opt != null) {
+		String value = doc_type_opt.getAttribute(GSXML.VALUE_ATT);
+		if (!value.equals("")) {
+		    this.default_document_type = value;
+		}
+	    }
+	}
+
+	return true;
+    }
+
+    protected Element getServiceDescription(String service_id, String lang, String subset) {
+
+	if (service_id.equals(CLASSIFIER_SERVICE)) {
+	    
+	    Element class_list = (Element)GSXML.getChildByTagName(this.config_info, GSXML.CLASSIFIER_ELEM+GSXML.LIST_MODIFIER);
+	    if (class_list == null) {
+            // no classifiers specified
+		return null;
+	    }
+	    
+	    Element cb_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	    cb_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_BROWSE);
+	    cb_service.setAttribute(GSXML.NAME_ATT, CLASSIFIER_SERVICE);
+	    cb_service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_NAME,  getTextString(CLASSIFIER_SERVICE+".name", lang)));
+	    cb_service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_DESCRIPTION,  getTextString(CLASSIFIER_SERVICE+".description", lang)));
+	    
+	    Element cl_list = this.doc.createElement(GSXML.CLASSIFIER_ELEM+GSXML.LIST_MODIFIER);
+	    cb_service.appendChild(cl_list);
+	    NodeList classifiers = class_list.getElementsByTagName(GSXML.CLASSIFIER_ELEM);
+	    for(int i=0; i<classifiers.getLength(); i++) {
+		Element cl = (Element)classifiers.item(i);
+		Element new_cl = (Element)this.doc.importNode(cl, false); // just import this node, not the children
+		String content = cl.getAttribute(GSXML.CLASSIFIER_CONTENT_ATT);
+		cl_list.appendChild(new_cl);
+		String text = GSXML.getDisplayText(cl, 
+						   GSXML.DISPLAY_TEXT_NAME, 
+						   lang, "en");
+		if (text == null || text.equals("")) {
+		    // no display element was specified, use the metadata name
+		    // for now this looks in the class properties file
+		    // this needs to use a general metadata thing instead
+		    text = getMetadataNameText(content+".buttonname", lang);
+		}
+		if (text == null) {
+		    text = content;
+		}
+		
+		Element cl_name = GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_NAME, text);
+		new_cl.appendChild(cl_name);
+
+		// description
+		
+		String meta_name = getMetadataNameText(content, lang);
+		if (meta_name==null) {
+		    meta_name = content;
+		}
+		String [] array = {meta_name};
+		String description = getTextString("ClassifierBrowse.classifier_help", lang, array);
+		Element cl_desc = GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_DESCRIPTION, description);
+		new_cl.appendChild(cl_desc);
+		
+	    }
+	    return cb_service;
+	}
+	
+	// these ones are probably never called, but put them here just in case
+	
+	if (service_id.equals(CLASSIFIER_METADATA_SERVICE)) {
+	    
+	    Element cbmr_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	    cbmr_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
+	    cbmr_service.setAttribute(GSXML.NAME_ATT, CLASSIFIER_METADATA_SERVICE);
+	    return cbmr_service;
+	}
+
+	return null;
+    }
+
+    /** this looks for any classifier specific display or format info from extra_info and adds it in to the correct place in info */
+    protected boolean extractExtraClassifierInfo(Element info, Element extra_info) {
+	
+	if (extra_info == null) {
+	    return false;
+	}
+	
+	Document owner = info.getOwnerDocument();
+	// so far we have display and format elements that we need for classifiers
+	NodeList classifiers = info.getElementsByTagName(GSXML.CLASSIFIER_ELEM);
+	Element config_browse = (Element)GSXML.getChildByTagName(extra_info, GSXML.BROWSE_ELEM);
+
+	for (int i=0; i<classifiers.getLength();i++) {
+	    Element cl = (Element)classifiers.item(i);
+	    String name = cl.getAttribute(GSXML.NAME_ATT);
+	    Element node_extra = GSXML.getNamedElement(config_browse,
+						       GSXML.CLASSIFIER_ELEM,
+						       GSXML.NAME_ATT,
+						       name);
+	    if (node_extra == null) {
+		logger.error("GS2REtrieve: haven't found extra info for classifier named "+name);
+		continue;
+	    }
+	    
+	    // get the display elements if any - displayName
+	    NodeList display_names = node_extra.getElementsByTagName(GSXML.DISPLAY_TEXT_ELEM);
+	    if (display_names !=null) {
+		Element display = owner.createElement(GSXML.DISPLAY_ELEM);
+		for (int j=0; j<display_names.getLength(); j++) {
+		    Element e = (Element)display_names.item(j);
+		    cl.appendChild(owner.importNode(e, true));
+		    
+		}
+	    }
+	    
+	    // get the format element if any 
+	    Element format = (Element)GSXML.getChildByTagName(node_extra, GSXML.FORMAT_ELEM);
+	    if (format==null) { // try a generic one that applies to all classifiers
+		format = (Element)GSXML.getChildByTagName(extra_info,
+							  GSXML.FORMAT_ELEM);
+	    }
+	    if (format!=null) { // append to index info
+		cl.appendChild(owner.importNode(format, true));
+	    }
+	} // for each classifier
+
+	// now check for default format info
+	Element default_format = (Element)GSXML.getChildByTagName(config_browse, GSXML.FORMAT_ELEM);
+	if (default_format!=null) { // append to  info
+	    info.appendChild(owner.importNode(default_format, true));
+	}
+
+	return true;
+    }
+	    
+    protected Element processClassifierBrowse(Element request) {
+	
+	// Create a new (empty) result message
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	result.setAttribute(GSXML.FROM_ATT, CLASSIFIER_SERVICE);
+	result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+	
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	Element query_node_list = (Element) GSXML.getChildByTagName(request, GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
+	if (query_node_list == null) {
+	    logger.error(" ClassifierBrowse request specified no doc nodes.\n");
+	    return result;
+	}
+
+	// Get the parameters of the request
+	Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	if (param_list == null) {
+	    logger.error(" ClassifierBrowse request had no paramList.");
+	    return result;  // Return the empty result
+	}
+	
+	// the type of info required
+	boolean want_structure = false;
+	boolean want_info = false;
+
+	ArrayList info_types=new ArrayList();
+	// The document structure information desired
+	boolean want_ancestors = false;
+	boolean want_parent = false;
+	boolean want_siblings = false;
+	boolean want_children = false;
+	boolean want_descendants = false;
+
+	boolean want_entire_structure = false;
+	// Process the request parameters
+	NodeList params = param_list.getElementsByTagName(GSXML.PARAM_ELEM);
+	for (int i=0; i<params.getLength();i++) {
+	    
+	    Element param = (Element)params.item(i);
+	    String p_name = param.getAttribute(GSXML.NAME_ATT);
+	    String p_value = GSXML.getValue(param);
+	    // Identify the structure information desired
+	    if (p_name.equals(STRUCT_PARAM)) {
+		want_structure = true;
+		
+		// This is NOT locale sensitive
+		if (p_value.equals(STRUCT_ANCESTORS))
+		    want_ancestors = true;
+		else if (p_value.equals(STRUCT_PARENT))
+		    want_parent = true;
+		else if (p_value.equals(STRUCT_SIBS))
+		    want_siblings = true;
+		else if (p_value.equals(STRUCT_CHILDREN))
+		    want_children = true;
+		else if (p_value.equals(STRUCT_DESCENDS))
+		    want_descendants = true;
+		else if (p_value.equals(STRUCT_ENTIRE))
+		    want_entire_structure = true;
+		else
+		    logger.error("AbstractDocumentRetrieve Warning: Unknown value \"" + p_value + "\".");
+	    } else if (p_name.equals(INFO_PARAM)) {
+		want_info = true;
+		info_types.add(p_value);
+	    }
+	}
+
+	// Make sure there is no repeated information
+	if (want_ancestors)
+	    want_parent = false;
+	if (want_descendants)
+	    want_children = false;
+	
+	// the node list to hold the results
+	Element node_list = this.doc.createElement(GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
+	result.appendChild(node_list);
+	
+	// Get the nodes
+	String[] node_ids = GSXML.getAttributeValuesFromList(query_node_list, 
+							     GSXML.NODE_ID_ATT);
+	for (int i = 0; i < node_ids.length; i++) {
+	    // Add the document to the list
+	    Element node = this.doc.createElement(GSXML.CLASS_NODE_ELEM);
+	    node_list.appendChild(node);
+
+	    String node_id = node_ids[i];
+	    node.setAttribute(GSXML.NODE_ID_ATT, node_id);
+	    
+	    if (idNeedsTranslating(node_id)) {
+		node_id = translateId(node_id);
+		if (node_id == null) {
+		    continue;
+		}
+		node.setAttribute(GSXML.NODE_ID_ATT, node_id);
+	    }
+	    
+	    if (want_info) {
+
+		Element node_info_elem = this.doc.createElement("nodeStructureInfo");
+		node.appendChild(node_info_elem);
+		
+		for (int j=0; j<info_types.size(); j++) {
+		    String info_type = (String)info_types.get(j);
+		    String info_value = getStructureInfo(node_id, info_type);
+		    if (info_value != null) {
+			Element info_elem = this.doc.createElement("info");
+			info_elem.setAttribute(GSXML.NAME_ATT, info_type);
+			info_elem.setAttribute(GSXML.VALUE_ATT, info_value);
+			node_info_elem.appendChild(info_elem);
+		    }
+		}
+	    }
+	    
+	    if (want_structure) {
+		// all structure info goes into a nodeStructure elem
+		Element structure_elem = this.doc.createElement(GSXML.NODE_STRUCTURE_ELEM);
+		node.appendChild(structure_elem);
+		
+		if (want_entire_structure) {
+		    String root_id = getRootId(node_id);
+		    Element root_node = createClassifierNode(root_id); //, true, false);
+		    addDescendants(root_node, root_id, true);
+		    structure_elem.appendChild(root_node);
+		    continue; // with the next document, we dont need to do any more here
+		}
+		
+		// Add the requested structure information
+		Element base_node = createClassifierNode(node_id); //, false, false);
+		
+		//Ancestors: continually add parent nodes until the root is reached
+		Element top_node = base_node; // the top node so far
+		if (want_ancestors) {
+		    String current_id = node_id;
+		    while (true) {
+			String parent_id = getParentId(current_id);
+			//Element parent = getParent(current_id);
+			if (parent_id == null)
+			    break; // no parent
+			Element parent_node = createClassifierNode(parent_id);
+			parent_node.appendChild(top_node);
+			current_id = parent_id;//.getAttribute(GSXML.NODE_ID_ATT);
+			top_node = parent_node;
+		    }
+		}
+		// Parent: get the parent of the selected node
+		else if (want_parent) {
+		    String parent_id = getParentId(node_id);
+		    if (parent_id != null) {
+			Element parent_node = createClassifierNode(parent_id);
+			parent_node.appendChild(base_node);
+			top_node = parent_node;
+		    }
+		}
+		
+		// now the top node is the root of the structure
+		structure_elem.appendChild(top_node);
+		
+		//Siblings: get the other descendants of the selected node's parent
+		if (want_siblings) {
+		    
+		    Element parent_node = (Element)base_node.getParentNode(); // this may be the structure element if there has been no request for parents or ancestors
+		    String parent_id = getParentId(node_id);
+		    // add siblings, - returns a pointer to the new current node 
+		    base_node = addSiblings(parent_node, parent_id, node_id);
+		}
+		
+		// Children: get the descendants, but only one level deep
+		if (want_children) {
+		    addDescendants(base_node, node_id, false);
+		} 
+		// Descendants: recursively get every descendant 
+		else if (want_descendants) {
+		    addDescendants(base_node, node_id, true);
+		}
+	    } // if want structure
+	} // for each doc
+	return result;
+    }
+
+
+    protected Element processClassifierBrowseMetadataRetrieve(Element request) {
+
+	// Create a new (empty) result message
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	result.setAttribute(GSXML.FROM_ATT, CLASSIFIER_METADATA_SERVICE);
+	result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+
+	// Get the parameters of the request
+	Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	if (param_list == null) {
+	    logger.error("AbstractBrowse, ClassifierBrowseMetadataRetrieve Error: missing paramList.\n");
+	    return result;  // Return the empty result
+	}
+
+	// The metadata information required
+	ArrayList metadata_names_list = new ArrayList();
+	boolean all_metadata = false;
+	// Process the request parameters
+	Element param = (Element) param_list.getFirstChild();
+	while (param != null) {
+	    // Identify the metadata information desired
+	    if (param.getAttribute(GSXML.NAME_ATT).equals("metadata")) {
+		String metadata = GSXML.getValue(param);
+		if (metadata.equals("all")) {
+		    all_metadata = true;
+		    break;
+		}
+		metadata_names_list.add(metadata);
+	    } 
+	    param = (Element) param.getNextSibling();
+	}
+	
+	Element node_list = this.doc.createElement(GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
+	result.appendChild(node_list);
+	
+	// Get the nodes
+	Element request_node_list = (Element) GSXML.getChildByTagName(request, GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
+	if (request_node_list == null) {
+	    logger.error(" ClassifierBrowseMetadataRetrieve request had no "+GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
+ 	    return result;
+ 	}
+	
+	NodeList request_nodes = request_node_list.getChildNodes();
+	for (int i = 0; i < request_nodes.getLength(); i++) {
+	    Element request_node = (Element) request_nodes.item(i);
+	    String node_id = request_node.getAttribute(GSXML.NODE_ID_ATT);
+	    
+	    // Add the document to the results list
+	    Element new_node = (Element)this.doc.importNode(request_node, false);
+	    node_list.appendChild(new_node);
+
+	    if (idNeedsTranslating(node_id)) {
+		node_id = translateId(node_id);
+	    }
+	    if (node_id == null) {
+		continue;
+	    }
+	    
+	    Element metadata_list = getMetadataList(node_id, all_metadata, metadata_names_list);
+	    new_node.appendChild(metadata_list);
+	}
+	
+	return result;
+    }
+
+
+    /** Creates a classifier node */
+    protected Element createClassifierNode(String node_id)
+    {
+	Element node = this.doc.createElement(GSXML.CLASS_NODE_ELEM);
+	node.setAttribute(GSXML.NODE_ID_ATT, node_id);
+	return node;
+    }
+
+    /** create an element to go into the structure. A node element
+     * has the form
+     * <docNode nodeId='xxx' nodeType='leaf' docType='hierarchy'/>
+     */
+    protected Element createDocNode(String node_id) {
+	Element node = this.doc.createElement(GSXML.DOC_NODE_ELEM);
+	node.setAttribute(GSXML.NODE_ID_ATT, node_id);
+
+	String doc_type = null;
+	if (default_document_type != null) {
+	    doc_type = default_document_type;
+	} else {
+	    doc_type = getDocType(node_id);
+	}
+	node.setAttribute(GSXML.DOC_TYPE_ATT, doc_type);
+	String node_type = getNodeType(node_id, doc_type);	
+	node.setAttribute(GSXML.NODE_TYPE_ATT, node_type);
+	return node;
+    }
+
+   /** returns the node type of the specified node.
+	should be one of 
+	GSXML.NODE_TYPE_LEAF, 
+	GSXML.NODE_TYPE_INTERNAL, 
+	GSXML.NODE_TYPE_ROOT
+    */
+    protected String getNodeType(String node_id, String doc_type) {
+	if (doc_type.equals(GSXML.DOC_TYPE_SIMPLE)) {
+	    return GSXML.NODE_TYPE_LEAF;
+	}
+
+	if (getParentId(node_id)==null) {
+	    return GSXML.NODE_TYPE_ROOT;
+	}
+	if (doc_type.equals(GSXML.DOC_TYPE_PAGED)) {
+	     return GSXML.NODE_TYPE_LEAF;
+	}
+	if (getChildrenIds(node_id)==null) {
+	    return GSXML.NODE_TYPE_LEAF;
+	}
+	return GSXML.NODE_TYPE_INTERNAL;	
+	
+    }
+
+    /** adds all the children of doc_id the the doc element,
+     * and if recursive=true, adds all their children as well*/
+    protected void addDescendants(Element node, String node_id, 
+				  boolean recursive)
+    {
+	ArrayList child_ids = getChildrenIds(node_id);
+	if (child_ids==null) return;
+	for (int i=0; i< child_ids.size(); i++) {
+	    String child_id = (String)child_ids.get(i);
+	    Element child_elem;
+	    if (isDocumentId(child_id)) {
+		child_elem = createDocNode(child_id);
+	    } else {
+		child_elem = createClassifierNode(child_id);
+	    }
+	    node.appendChild(child_elem);
+	    if (recursive) {
+		addDescendants(child_elem, child_id, recursive);
+	    }
+	}
+    }
+
+    /** adds all the siblings of current_id to the parent element. 
+      returns the new current element*/
+    protected Element addSiblings(Element parent_node, String parent_id, 
+				  String current_id) {
+	Element current_node = (Element)parent_node.getFirstChild();
+	if (current_node == null) {
+	    // create a sensible error message
+	    logger.error(" there should be a first child.");
+	    return null;
+	}
+	// remove the current child,- will add it in later in its correct place
+	parent_node.removeChild(current_node);
+
+	// add in all the siblings,
+	addDescendants(parent_node, parent_id, false);
+
+	// find the node that is now the current node
+	// this assumes that the new node that was created is the same as 
+	// the old one that was removed - we may want to replace the new one 
+	// with the old one.
+	Element new_current = GSXML.getNamedElement(parent_node, current_node.getNodeName(), GSXML.NODE_ID_ATT, current_id);
+	return new_current;
+    }
+
+    /** returns true if oid ends in
+	.fc (firstchild), 
+	.lc (lastchild), 
+	.pr (parent), 
+	.ns (next sibling), 
+	.ps (prev sibling), 
+	.rt (root) 
+	.ss (specified sibling), 
+	false otherwise 
+    */
+    protected boolean idNeedsTranslating(String node_id) {
+	return OID.needsTranslating(node_id);
+    }
+
+    /** returns the list of sibling ids, including the specified node_id */
+    protected ArrayList getSiblingIds(String node_id) {
+	String parent_id = getParentId(node_id);
+	if (parent_id == null) {
+	    return null;
+	}
+	return getChildrenIds(parent_id);
+
+    }
+
+    /** if id ends in .fc, .pc etc, then translate it to the correct id */
+    abstract protected String translateId(String node_id);
+
+    /** returns the document type of the doc that the specified node 
+	belongs to. should be one of 
+	GSXML.DOC_TYPE_SIMPLE, 
+	GSXML.DOC_TYPE_PAGED, 
+	GSXML.DOC_TYPE_HIERARCHY
+    */
+    abstract protected String getDocType(String node_id);
+
+    /** returns the id of the root node of the document containing node node_id. . may be the same as node_id */
+    abstract protected String getRootId(String node_id);
+    /** returns a list of the child ids in order, null if no children */
+    abstract protected ArrayList getChildrenIds(String node_id);
+    /** returns the node id of the parent node, null if no parent */
+    abstract protected String getParentId(String node_id);
+ 
+    /** returns true if the id refers to a document (rather than 
+     * a classifier node)
+     */
+    abstract protected boolean isDocumentId(String node_id);
+
+    /** get the metadata for the classifier node node_id
+     * returns a metadataList element:
+     * <metadataList><metadata name="xxx">value</metadata></metadataList>
+     * if all_metadata is true, returns all available metadata, otherwise just
+     * returns requested metadata
+     */
+    abstract protected Element getMetadataList(String node_id,
+					       boolean all_metadata,
+					       ArrayList metadata_names);
+
+    /** returns the structural information asked for.
+     * info_type may be one of
+     * INFO_NUM_SIBS, INFO_NUM_CHILDREN, INFO_SIB_POS
+     */
+    abstract protected String getStructureInfo(String node_id, String info_type);    
+//      /** needs to get info from gdbm database - if the calling code gets it already it may pay to pass it in instead */
+//     protected String resolveTextMacros(String doc_content, String doc_id, String lang)
+//     {
+// 	DBInfo info = null;
+// 	if (doc_content.indexOf("_httpdocimg_")!=-1) {
+// 	    String top_doc_id = OID.getTop(doc_id);
+// 	    info = this.gdbm_src.getInfo(top_doc_id);
+// 	    if (info == null) {
+// 		// perhaps we had per.iods in the ids - just try the current id
+// 		top_doc_id = doc_id;
+// 		info = this.gdbm_src.getInfo(top_doc_id);
+// 	    }
+// 	    if (info != null) {
+// 		String archivedir = info.getInfo("archivedir");
+// 		String image_dir  = this.site_http_address + "/collect/"+this.cluster_name+"/index/assoc/"+archivedir;
+		
+// 		// Resolve all "_httpdocimg_"s
+// 		doc_content = doc_content.replaceAll("_httpdocimg_", image_dir);
+// 	    }
+// 	}
+// 	// resolve any collection specific macros
+// 	doc_content = macro_resolver.resolve(doc_content, lang, GS2MacroResolver.SCOPE_TEXT, doc_id, info);
+// 	return doc_content;
+//     }
+
+   
+}   
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractDocumentRetrieve.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractDocumentRetrieve.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractDocumentRetrieve.java	(revision 13928)
@@ -0,0 +1,704 @@
+/*
+ *    AbstractDocumentRetrieve.java
+ *    a base class for retrieval services
+
+ *    Copyright (C) 2005 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.service;
+
+// Greenstone classes
+//import org.greenstone.gdbm.*;
+import org.greenstone.gsdl3.core.GSException;
+import org.greenstone.gsdl3.util.GSXML;
+import org.greenstone.gsdl3.util.GSPath;
+import org.greenstone.gsdl3.util.MacroResolver;
+import org.greenstone.gsdl3.util.OID;
+
+// XML classes
+import org.w3c.dom.Document;
+import org.w3c.dom.Element; 
+import org.w3c.dom.NodeList;
+
+// General Java classes
+import java.io.File;
+import java.util.StringTokenizer;
+import java.util.Set;
+import java.util.Iterator;
+import java.util.ArrayList;
+
+
+import org.apache.log4j.*;
+
+/** Abstract class for Document Retrieval Services
+ *
+ * @author <a href="mailto:greenstone@cs.waikato.ac.nz">Katherine Don</a>
+ */
+
+public abstract class AbstractDocumentRetrieve
+    extends ServiceRack {
+
+    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.AbstractDocumentRetrieve.class.getName());
+
+    // the services on offer
+    protected static final String DOCUMENT_STRUCTURE_RETRIEVE_SERVICE = "DocumentStructureRetrieve";
+    protected static final String DOCUMENT_METADATA_RETRIEVE_SERVICE = "DocumentMetadataRetrieve";
+    protected static final String DOCUMENT_CONTENT_RETRIEVE_SERVICE = "DocumentContentRetrieve";
+    
+    protected static final String STRUCT_PARAM = "structure";
+    protected static final String INFO_PARAM = "info";
+    
+    protected static final String STRUCT_ANCESTORS = "ancestors";
+    protected static final String STRUCT_PARENT = "parent";
+    protected static final String STRUCT_SIBS = "siblings";
+    protected static final String STRUCT_CHILDREN = "children";
+    protected static final String STRUCT_DESCENDS = "descendants";
+    protected static final String STRUCT_ENTIRE = "entire";
+
+    protected static final String INFO_NUM_SIBS = "numSiblings";
+    protected static final String INFO_NUM_CHILDREN = "numChildren";
+    protected static final String INFO_SIB_POS = "siblingPosition";
+
+    // means the id is not a greenstone id and needs translating
+    protected static final String EXTID_PARAM = "ext"; 
+    
+    protected Element config_info = null; // the xml from the config file
+
+    protected String default_document_type = null;
+    protected MacroResolver macro_resolver = null;
+
+    /** does this class provide the service?? */
+    protected boolean does_metadata = true;
+    protected boolean does_content = true;
+    protected boolean does_structure = true;
+
+    /** constructor */
+    public AbstractDocumentRetrieve()
+    {
+    }
+
+    /** configure this service */
+    public boolean configure(Element info, Element extra_info)
+    {
+	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+
+	logger.info("Configuring AbstractDocumentRetrieve...");
+	this.config_info = info;
+
+	// set up short_service_info_ - for now just has name and type
+	if (does_structure) {
+	    Element dsr_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	    dsr_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
+	    dsr_service.setAttribute(GSXML.NAME_ATT, DOCUMENT_STRUCTURE_RETRIEVE_SERVICE);
+	    this.short_service_info.appendChild(dsr_service);
+	}
+
+	if (does_metadata) {
+	    Element dmr_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	    dmr_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
+	    dmr_service.setAttribute(GSXML.NAME_ATT, DOCUMENT_METADATA_RETRIEVE_SERVICE);
+	    this.short_service_info.appendChild(dmr_service);
+	}
+
+	if (does_content) {
+	    Element dcr_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	    dcr_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
+	    dcr_service.setAttribute(GSXML.NAME_ATT, DOCUMENT_CONTENT_RETRIEVE_SERVICE);
+	    this.short_service_info.appendChild(dcr_service);
+	}
+	
+	// look for document display format
+	String path = GSPath.appendLink(GSXML.DISPLAY_ELEM, GSXML.FORMAT_ELEM);
+	Element display_format = (Element)GSXML.getNodeByPath(extra_info, path);
+	if (display_format != null) {
+	    this.format_info_map.put(DOCUMENT_CONTENT_RETRIEVE_SERVICE, this.doc.importNode(display_format, true));
+	    // should we keep a copy?
+	    // check for docType option.
+	    Element doc_type_opt = GSXML.getNamedElement(display_format, "gsf:option", GSXML.NAME_ATT, "documentType");
+	    if (doc_type_opt != null) {
+		String value = doc_type_opt.getAttribute(GSXML.VALUE_ATT);
+		if (!value.equals("")) {
+		    this.default_document_type = value;
+		}
+	    }
+	}
+
+	if (macro_resolver != null) {
+	    macro_resolver.setSiteDetails(this.site_http_address, this.cluster_name);
+	    // set up the macro resolver
+	    Element replacement_elem = (Element)GSXML.getChildByTagName(extra_info, "replaceList");
+	    if (replacement_elem != null) {
+		macro_resolver.addMacros(replacement_elem);
+	    }
+	    // look for any refs to global replace lists
+	    NodeList replace_refs_elems = extra_info.getElementsByTagName("replaceListRef");
+	    for (int i=0; i<replace_refs_elems.getLength(); i++) {
+		String id = ((Element)replace_refs_elems.item(i)).getAttribute("id");
+		if (!id.equals("")) {
+		    Element replace_list = GSXML.getNamedElement(this.router.config_info, "replaceList", "id", id);
+		    if (replace_list != null) {
+			macro_resolver.addMacros(replace_list);
+		    }
+		}
+	    }
+	}
+	
+	return true;
+    }
+    
+    protected Element getServiceDescription(String service_id, String lang, String subset) {
+	
+	// these ones are probably never called, but put them here just in case
+	Element service_elem = this.doc.createElement(GSXML.SERVICE_ELEM);
+	service_elem.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
+	service_elem.setAttribute(GSXML.NAME_ATT, service_id);
+	return service_elem;
+    }
+
+    protected Element processDocumentMetadataRetrieve(Element request) {
+
+	// Create a new (empty) result message
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	result.setAttribute(GSXML.FROM_ATT, DOCUMENT_METADATA_RETRIEVE_SERVICE);
+	result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+
+	if (!does_metadata) {
+	    // shouldn't get here
+	    return result;
+	}
+
+	// Get the parameters of the request
+	Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	if (param_list == null) {
+	    GSXML.addError(this.doc, result, "DocumentMetadataRetrieve: missing "+ GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER, GSXML.ERROR_TYPE_SYNTAX);
+	    return result;  
+	}
+
+	boolean external_id = false;
+	// The metadata information required
+	ArrayList metadata_names_list = new ArrayList();
+	boolean all_metadata = false;
+	// Process the request parameters
+	Element param = (Element) param_list.getFirstChild();
+	while (param != null) {
+	    // Identify the metadata information desired
+	    if (param.getAttribute(GSXML.NAME_ATT).equals("metadata")) {
+		String metadata = GSXML.getValue(param);
+		if (metadata.equals("all")) {
+		    all_metadata = true;
+		    break;
+		}
+		metadata_names_list.add(metadata);
+	    } else if (param.getAttribute(GSXML.NAME_ATT).equals(EXTID_PARAM)&& GSXML.getValue(param).equals("1")) {
+		external_id = true;
+	    }
+	    param = (Element) param.getNextSibling();
+	}
+
+	// check that there has been some metadata specified
+	if (!all_metadata && metadata_names_list.size()==0) {
+	    GSXML.addError(this.doc, result, "DocumentMetadataRetrieve: no metadata names found in the "+ GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER, GSXML.ERROR_TYPE_SYNTAX);
+	    return result;  
+	}
+
+	// Get the documents
+	Element request_node_list = (Element) GSXML.getChildByTagName(request, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	if (request_node_list == null) {
+	    GSXML.addError(this.doc, result, "DocumentMetadataRetrieve: missing " +GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER, GSXML.ERROR_TYPE_SYNTAX);
+ 	    return result;
+ 	}
+
+	// copy the request doc node list to the response
+	Element response_node_list = (Element) this.doc.importNode(request_node_list, true);
+	result.appendChild(response_node_list);
+	
+	// use the copied list so that we add the metadata into the copy
+	// are we just adding metadata for the top level nodes? or can we accept a hierarchy here???
+	NodeList request_nodes = GSXML.getChildrenByTagName(response_node_list, GSXML.DOC_NODE_ELEM);
+	if (request_nodes.getLength()==0) {
+	    GSXML.addError(this.doc, result, "DocumentMetadataRetrieve: no "+GSXML.DOC_NODE_ELEM +" found in the "+ GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER, GSXML.ERROR_TYPE_SYNTAX);
+ 	    return result;
+ 	}
+
+	// Whew, now we have checked (almost) all the syntax of the request, now we can process it.
+	
+	for (int i = 0; i < request_nodes.getLength(); i++) {
+	    Element request_node = (Element) request_nodes.item(i);
+	    String node_id = request_node.getAttribute(GSXML.NODE_ID_ATT);
+
+	    if (external_id) {
+		// can we have .pr etc extensions with external ids?
+		node_id = translateExternalId(node_id);
+	    } else if (idNeedsTranslating(node_id)) {
+		node_id = translateId(node_id);
+	    }	    
+	    if (node_id == null) {
+		continue;
+	    }
+	    try {
+		Element metadata_list = getMetadataList(node_id, all_metadata, metadata_names_list);
+		request_node.appendChild(metadata_list);
+	    } catch (GSException e) {		
+		GSXML.addError(this.doc, result, e.getMessage(), e.getType());
+		if (e.getType().equals(GSXML.ERROR_TYPE_SYSTEM)) {
+		    // there is no point trying any others
+		    return result;
+		}
+	    } 
+	}
+		
+	return result;
+    }
+
+    protected Element processDocumentStructureRetrieve(Element request) {
+    
+	// Create a new (empty) result message
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	result.setAttribute(GSXML.FROM_ATT, DOCUMENT_STRUCTURE_RETRIEVE_SERVICE);
+	result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+	
+	if (!does_structure) {
+	    // shouldn't get here
+	    return result;
+	}
+
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+
+	// Get the parameters of the request
+	Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	if (param_list == null) {
+	    GSXML.addError(this.doc, result, "DocumentStructureRetrieve: missing "+ GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER, GSXML.ERROR_TYPE_SYNTAX);
+	    return result;  
+	}
+	
+	// get the documents of the request
+	Element query_doc_list = (Element) GSXML.getChildByTagName(request, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	if (query_doc_list == null) {
+	    GSXML.addError(this.doc, result, "DocumentStructureRetrieve: missing " +GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER, GSXML.ERROR_TYPE_SYNTAX);
+ 	    return result;
+ 	}
+	
+	// copy the doc_list to the response
+	Element response_node_list = (Element) this.doc.importNode(query_doc_list, true);
+	result.appendChild(response_node_list);
+	
+	// check that we have some doc nodes specified
+	NodeList node_list = GSXML.getChildrenByTagName(response_node_list, GSXML.DOC_NODE_ELEM);
+	if (node_list.getLength()==0) {
+	    GSXML.addError(this.doc, result, "DocumentStructureRetrieve: no "+GSXML.DOC_NODE_ELEM +" found in the "+ GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER, GSXML.ERROR_TYPE_SYNTAX);
+ 	    return result;
+ 	}
+
+	Element extid_param = GSXML.getNamedElement(param_list, GSXML.PARAM_ELEM, GSXML.NAME_ATT, EXTID_PARAM);
+	boolean external_id = false;
+	if (extid_param != null && GSXML.getValue(extid_param).equals("1")) {
+	    external_id = true;
+	}
+
+	// the type of info required
+	boolean want_structure = false;
+	boolean want_info = false;
+
+	ArrayList info_types=new ArrayList();
+	// The document structure information desired
+	boolean want_ancestors = false;
+	boolean want_parent = false;
+	boolean want_siblings = false;
+	boolean want_children = false;
+	boolean want_descendants = false;
+
+	boolean want_entire_structure = false;
+	// Process the request parameters
+	NodeList params = param_list.getElementsByTagName(GSXML.PARAM_ELEM);
+	for (int i=0; i<params.getLength();i++) {
+	    
+	    Element param = (Element)params.item(i);
+	    String p_name = param.getAttribute(GSXML.NAME_ATT);
+	    String p_value = GSXML.getValue(param);
+	    // Identify the structure information desired
+	    if (p_name.equals(STRUCT_PARAM)) {
+		want_structure = true;
+		
+		// This is NOT locale sensitive
+		if (p_value.equals(STRUCT_ANCESTORS))
+		    want_ancestors = true;
+		else if (p_value.equals(STRUCT_PARENT))
+		    want_parent = true;
+		else if (p_value.equals(STRUCT_SIBS))
+		    want_siblings = true;
+		else if (p_value.equals(STRUCT_CHILDREN))
+		    want_children = true;
+		else if (p_value.equals(STRUCT_DESCENDS))
+		    want_descendants = true;
+		else if (p_value.equals(STRUCT_ENTIRE))
+		    want_entire_structure = true;
+		else
+		    logger.error("AbstractDocumentRetrieve Warning: Unknown value \"" + p_value + "\".");
+	    } else if (p_name.equals(INFO_PARAM)) {
+		want_info = true;
+		info_types.add(p_value);
+	    }
+	}
+
+	// Make sure there is no repeated information
+	if (want_ancestors)
+	    want_parent = false;
+	if (want_descendants)
+	    want_children = false;
+
+	for (int i=0; i < node_list.getLength(); i++) {
+	    Element doc = (Element) node_list.item(i);
+	    String doc_id = doc.getAttribute(GSXML.NODE_ID_ATT);
+	    if (external_id) {
+		doc_id = translateExternalId(doc_id);
+		doc.setAttribute(GSXML.NODE_ID_ATT, doc_id);
+	    } else if (idNeedsTranslating(doc_id)) {
+		doc_id = translateId(doc_id);	
+		doc.setAttribute(GSXML.NODE_ID_ATT, doc_id);
+	    }
+	    if (doc_id == null) {
+		continue;
+	    }
+
+	    if (want_info) {
+
+		Element node_info_elem = this.doc.createElement("nodeStructureInfo");
+		doc.appendChild(node_info_elem);
+		
+		for (int j=0; j<info_types.size(); j++) {
+		    String info_type = (String)info_types.get(j);
+		    String info_value = getStructureInfo(doc_id, info_type);
+		    if (info_value != null) {
+			Element info_elem = this.doc.createElement("info");
+			info_elem.setAttribute(GSXML.NAME_ATT, info_type);
+			info_elem.setAttribute(GSXML.VALUE_ATT, info_value);
+			node_info_elem.appendChild(info_elem);
+		    }
+		}
+	    }
+	    
+	    if (want_structure) {
+		// all structure info goes into a nodeStructure elem
+		Element structure_elem = this.doc.createElement(GSXML.NODE_STRUCTURE_ELEM);
+		doc.appendChild(structure_elem);
+		
+		if (want_entire_structure) {
+		    String root_id = getRootId(doc_id);
+		    Element root_node = createDocNode(root_id); //, true, false);
+		    addDescendants(root_node, root_id, true);
+		    structure_elem.appendChild(root_node);
+		    continue; // with the next document, we dont need to do any more here
+		}
+		
+		// Add the requested structure information
+		Element base_node = createDocNode(doc_id); //, false, false);
+		
+		//Ancestors: continually add parent nodes until the root is reached
+		Element top_node = base_node; // the top node so far
+		if (want_ancestors) {
+		    String current_id = doc_id;
+		    while (true) {
+			String parent_id = getParentId(current_id);
+			//Element parent = getParent(current_id);
+			if (parent_id == null)
+			    break; // no parent
+			Element parent_node = createDocNode(parent_id);
+			parent_node.appendChild(top_node);
+			current_id = parent_id;//.getAttribute(GSXML.NODE_ID_ATT);
+			top_node = parent_node;
+		    }
+		}
+		// Parent: get the parent of the selected node
+		else if (want_parent) {
+		    String parent_id = getParentId(doc_id);
+		    if (parent_id != null) {
+			Element parent_node = createDocNode(parent_id);
+			parent_node.appendChild(base_node);
+			top_node = parent_node;
+		    }
+		}
+		
+		// now the top node is the root of the structure
+		structure_elem.appendChild(top_node);
+		
+		//Siblings: get the other descendants of the selected node's parent
+		if (want_siblings) {
+		    String parent_id = getParentId(doc_id);
+		    if (parent_id != null) {
+			// if parent == current id, then we are at the top 
+			// and can't get siblings
+			Element parent_node = (Element)base_node.getParentNode(); // this may be the structure element if there has been no request for parents or ancestors
+		    
+			// add siblings, - returns a pointer to the new current node 
+			base_node = addSiblings(parent_node, parent_id, doc_id);
+		    }
+
+		}
+		
+		// Children: get the descendants, but only one level deep
+		if (want_children) {
+		    addDescendants(base_node, doc_id, false);
+		} 
+		// Descendants: recursively get every descendant 
+		else if (want_descendants) {
+		    addDescendants(base_node, doc_id, true);
+		}
+	    } // if want structure
+	} // for each doc
+	return result;
+    }
+
+    /** Retrieve the content of a document */
+    protected Element processDocumentContentRetrieve(Element request)
+    {
+	// Create a new (empty) result message
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	result.setAttribute(GSXML.FROM_ATT, DOCUMENT_CONTENT_RETRIEVE_SERVICE);
+	result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+	
+	if (!does_content) {
+	    // shouldn't get here
+	    return result;
+	}
+
+	// Get the parameters of the request
+  	Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	Element extid_param = GSXML.getNamedElement(param_list, GSXML.PARAM_ELEM, GSXML.NAME_ATT, EXTID_PARAM);
+	boolean external_id = false;
+	if (extid_param != null && GSXML.getValue(extid_param).equals("1")) {
+	    external_id = true;
+	}
+	// Get the request content 
+	Element query_doc_list = (Element) GSXML.getChildByTagName(request, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	if (query_doc_list == null) {
+	    logger.error("Error: DocumentContentRetrieve request specified no doc nodes.\n");
+	    return result;
+	}
+	
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	Element doc_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	result.appendChild(doc_list);
+	
+	// set up the retrieval??
+
+	// Get the documents
+	String[] doc_ids = GSXML.getAttributeValuesFromList(query_doc_list, 
+							    GSXML.NODE_ID_ATT);
+	for (int i = 0; i < doc_ids.length; i++) {
+	    String doc_id = doc_ids[i];
+	    // Create the document node
+	    Element doc = this.doc.createElement(GSXML.DOC_NODE_ELEM);
+	    doc.setAttribute(GSXML.NODE_ID_ATT, doc_id);
+	    doc_list.appendChild(doc);
+
+	    if (external_id) {
+		doc_id = translateExternalId(doc_id);
+		doc.setAttribute(GSXML.NODE_ID_ATT, doc_id);
+	    } else if (idNeedsTranslating(doc_id)) {
+		doc_id = translateId(doc_id);
+		doc.setAttribute(GSXML.NODE_ID_ATT, doc_id);
+	    }
+	    if (doc_id == null) {
+		continue;
+	    }
+	    try {
+		Element node_content = getNodeContent(doc_id, lang);
+		doc.appendChild(node_content);
+	    } catch (GSException e) {
+		GSXML.addError(this.doc, result, e.getMessage());
+		return result;
+		
+	    }
+	}
+	return result;
+    }
+    
+    /** create an element to go into the structure. A node element
+     * has the form
+     * <docNode nodeId='xxx' nodeType='leaf' docType='hierarchy'/>
+     */
+    protected Element createDocNode(String node_id) {
+	Element node = this.doc.createElement(GSXML.DOC_NODE_ELEM);
+	node.setAttribute(GSXML.NODE_ID_ATT, node_id);
+
+	String doc_type = null;
+	if (default_document_type != null) {
+	    doc_type = default_document_type;
+	} else {
+	    doc_type = getDocType(node_id);
+	}
+	node.setAttribute(GSXML.DOC_TYPE_ATT, doc_type);
+	String node_type = getNodeType(node_id, doc_type);	
+	node.setAttribute(GSXML.NODE_TYPE_ATT, node_type);
+	return node;
+    }
+
+    /** adds all the children of doc_id the the doc element,
+     * and if recursive=true, adds all their children as well*/
+    protected void addDescendants(Element doc, String doc_id, 
+				  boolean recursive)
+    {
+	ArrayList child_ids = getChildrenIds(doc_id);
+	if (child_ids==null) return;
+	for (int i=0; i< child_ids.size(); i++) {
+	    String child_id = (String)child_ids.get(i);
+	    Element child_elem = createDocNode(child_id);
+	    doc.appendChild(child_elem);
+	    if (recursive && !child_elem.getAttribute(GSXML.NODE_TYPE_ATT).equals(GSXML.NODE_TYPE_LEAF)) {
+		addDescendants(child_elem, child_id, recursive);
+	    }
+	}
+    }
+
+    /** adds all the siblings of current_id to the parent element. 
+      returns the new current element*/
+    protected Element addSiblings(Element parent_node, String parent_id, 
+				  String current_id) {
+	Element current_node = (Element)parent_node.getFirstChild();
+	if (current_node == null) {
+	    // create a sensible error message
+	    logger.error(" there should be a first child.");
+	    return null;
+	}
+	// remove the current child,- will add it in later in its correct place
+	parent_node.removeChild(current_node);
+
+	// add in all the siblings,
+	addDescendants(parent_node, parent_id, false);
+
+	// find the node that is now the current node
+	// this assumes that the new node that was created is the same as 
+	// the old one that was removed - we may want to replace the new one 
+	// with the old one.
+	Element new_current = GSXML.getNamedElement(parent_node, current_node.getNodeName(), GSXML.NODE_ID_ATT, current_id);
+	return new_current;
+    }
+
+    /** returns true if oid ends in
+	.fc (firstchild), 
+	.lc (lastchild), 
+	.pr (parent), 
+	.ns (next sibling), 
+	.ps (prev sibling), 
+	.rt (root) 
+	.ss (specified sibling), 
+	false otherwise 
+    */
+    protected boolean idNeedsTranslating(String id) {
+	return OID.needsTranslating(id);
+    }
+
+    /** returns the list of sibling ids, including the specified node_id */
+    protected ArrayList getSiblingIds(String node_id) {
+	String parent_id = getParentId(node_id);
+	if (parent_id == null) {
+	    return null;
+	}
+	return getChildrenIds(parent_id);
+
+    }
+
+   /** returns the node type of the specified node.
+	should be one of 
+	GSXML.NODE_TYPE_LEAF, 
+	GSXML.NODE_TYPE_INTERNAL, 
+	GSXML.NODE_TYPE_ROOT
+    */
+    protected String getNodeType(String node_id, String doc_type) {
+	if (doc_type.equals(GSXML.DOC_TYPE_SIMPLE)) {
+	    return GSXML.NODE_TYPE_LEAF;
+	}
+
+	if (getParentId(node_id)==null) {
+	    return GSXML.NODE_TYPE_ROOT;
+	}
+	if (doc_type.equals(GSXML.DOC_TYPE_PAGED)) {
+	     return GSXML.NODE_TYPE_LEAF;
+	}
+	if (getChildrenIds(node_id)==null) {
+	    return GSXML.NODE_TYPE_LEAF;
+	}
+	return GSXML.NODE_TYPE_INTERNAL;	
+	
+    }
+
+    /** if id ends in .fc, .pc etc, then translate it to the correct id 
+     * default implementation: just remove the suffix */
+    protected String translateId(String id) {
+	return id.substring(0,id.length());
+    }
+    
+    /** if an id is not a greenstone id (an external id) then translate 
+     * it to a greenstone one 
+     * default implementation: return the id */
+    protected String translateExternalId(String id) {
+	return id;
+    }
+
+    /** returns the document type of the doc that the specified node 
+	belongs to. should be one of 
+	GSXML.DOC_TYPE_SIMPLE, 
+	GSXML.DOC_TYPE_PAGED, 
+	GSXML.DOC_TYPE_HIERARCHY
+	default implementation: return DOC_TYPE_SIMPLE
+    */
+    protected String getDocType(String node_id) {
+	return GSXML.DOC_TYPE_SIMPLE;
+    }
+	
+
+    /** returns the id of the root node of the document containing 
+     * node node_id. may be the same as node_id 
+     * default implemntation: return node_id
+    */
+    protected String getRootId(String node_id) {
+	return node_id;
+    }
+    /** returns a list of the child ids in order, null if no children 
+     * default implementation: return null */
+    protected ArrayList getChildrenIds(String node_id) {
+	return null;
+    }
+    /** returns the node id of the parent node, null if no parent 
+     * default implementation: return null */
+    protected String getParentId(String node_id) {
+	return null;
+    }
+
+    /** get the metadata for the doc node doc_id
+     * returns a metadataList element:
+     * <metadataList><metadata name="xxx">value</metadata></metadataList>
+     */
+    abstract protected Element getMetadataList(String doc_id, 
+					       boolean all_metadata, 
+					       ArrayList metadata_names) throws GSException;
+    /** returns the content of a node
+     * should return a nodeContent element:
+     * <nodeContent>text content or other elements</nodeContent>
+     * can return 
+     */
+    abstract protected Element getNodeContent(String doc_id, String lang) throws GSException;
+
+    /** returns the structural information asked for.
+     * info_type may be one of
+     * INFO_NUM_SIBS, INFO_NUM_CHILDREN, INFO_SIB_POS
+     */
+    abstract protected String getStructureInfo(String doc_id, String info_type);
+    
+}   
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractGS2DocumentRetrieve.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractGS2DocumentRetrieve.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractGS2DocumentRetrieve.java	(revision 13928)
@@ -0,0 +1,461 @@
+/*
+ *    AbstractGS2DocumentRetrieve.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.service;
+
+// Greenstone classes
+import org.greenstone.gsdl3.core.GSException;
+import org.greenstone.gsdl3.util.GSXML;
+import org.greenstone.gsdl3.util.GSFile;
+import org.greenstone.gsdl3.util.OID;
+import org.greenstone.gsdl3.util.MacroResolver;
+import org.greenstone.gsdl3.util.GS2MacroResolver;
+import org.greenstone.gsdl3.util.GSConstants;
+import org.greenstone.gsdl3.util.GDBMWrapper;
+import org.greenstone.gsdl3.util.DBInfo;
+// XML classes
+import org.w3c.dom.Document;
+import org.w3c.dom.Element; 
+import org.w3c.dom.NodeList;
+
+// General Java classes
+import java.io.File;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import java.util.Set;
+import java.util.Iterator;
+import java.util.ArrayList;
+
+import org.apache.log4j.*;
+
+/** Implements the generic retrieval and classifier services for GS2 
+ * collections.
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ * @author <a href="mailto:mdewsnip@cs.waikato.ac.nz">Michael Dewsnip</a>
+ */
+
+public abstract class AbstractGS2DocumentRetrieve
+    extends AbstractDocumentRetrieve {
+
+      static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.AbstractGS2DocumentRetrieve.class.getName());
+
+    //    protected static final String EXTLINK_PARAM = "ext"; here or in base??    
+    protected String index_stem = null;
+
+    protected GDBMWrapper gdbm_src = null;
+
+
+    /** constructor */
+    protected AbstractGS2DocumentRetrieve()
+    {
+	this.gdbm_src = new GDBMWrapper();
+	this.macro_resolver = new GS2MacroResolver(this.gdbm_src);
+    }
+
+    public void cleanUp() {
+	super.cleanUp();
+	this.gdbm_src.closeDatabase();
+    }
+    /** configure this service */
+    public boolean configure(Element info, Element extra_info)
+    {
+	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+	
+	logger.info("Configuring AbstractGS2DocumentRetrieve...");
+	//this.config_info = info;
+	
+	// the index stem is either specified in the config file or is  the collection name
+	Element index_stem_elem = (Element) GSXML.getChildByTagName(info, GSXML.INDEX_STEM_ELEM);
+	if (index_stem_elem != null) {
+	    this.index_stem = index_stem_elem.getAttribute(GSXML.NAME_ATT);
+	}
+	if (this.index_stem == null || this.index_stem.equals("")) {
+	    logger.error("AbstractGS2DocumentRetrieve.configure(): indexStem element not found, stem will default to collection name");
+	    this.index_stem = this.cluster_name;
+	}
+
+	// Open GDBM database for querying
+	String gdbm_db_file = GSFile.GDBMDatabaseFile(this.site_home, this.cluster_name, this.index_stem);
+	if (!this.gdbm_src.openDatabase(gdbm_db_file, GDBMWrapper.READER)) {
+	    logger.error("Could not open GDBM database!");
+	    return false;
+	}
+
+	return true;
+    }
+
+    /** if id ends in .fc, .pc etc, then translate it to the correct id */
+    protected String translateId(String node_id) {
+	return this.gdbm_src.translateOID(node_id);
+    }
+    
+    /** if an id is not a greenstone id (an external id) then translate 
+	it to a greenstone one*/
+    protected String translateExternalId(String node_id){
+	return this.gdbm_src.externalId2OID(node_id);
+    }
+
+    /** returns the id of the root node of the document containing node node_id. . may be the same as node_id */
+    protected String getRootId(String node_id) {
+	return OID.getTop(node_id);
+    }
+    /** returns a list of the child ids in order, null if no children */
+    protected ArrayList getChildrenIds(String node_id) {
+	DBInfo info = this.gdbm_src.getInfo(node_id);
+	if (info == null) {
+	    return null;
+	}
+
+	String contains = info.getInfo("contains");
+	if (contains.equals("")) {
+	    return null;
+	}
+	ArrayList children = new ArrayList();
+	StringTokenizer st = new StringTokenizer(contains, ";");
+	while (st.hasMoreTokens()) {
+	    String child_id = st.nextToken().replaceAll("\"", node_id);
+	    children.add(child_id);
+	}
+	return children;
+
+    }
+    /** returns the node id of the parent node, null if no parent */
+    protected String getParentId(String node_id){
+	String parent = OID.getParent(node_id);
+	if (parent.equals(node_id)) {
+	    return null;
+	}
+	return parent;
+    }
+
+    /** get the metadata for the classifier node node_id
+     * returns a metadataList element:
+     * <metadataList><metadata name="xxx">value</metadata></metadataList>
+     */
+    // assumes only one value per metadata
+    protected Element getMetadataList(String node_id, boolean all_metadata,
+				      ArrayList metadata_names)  
+	throws GSException {
+	Element metadata_list = this.doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
+	DBInfo info = this.gdbm_src.getInfo(node_id);
+	if (info == null) {
+	    return null;
+	}
+	String lang = "en"; // why do we need this??
+	if (all_metadata) {
+	    // return everything out of the database
+	    Set keys = info.getKeys();
+	    Iterator it = keys.iterator();
+	    while(it.hasNext()) {
+		String key = (String)it.next();
+		//String value = info.getInfo(key);
+		Vector values = info.getMultiInfo(key);
+		for(int i=0; i<values.size(); i++) {
+		    GSXML.addMetadata(this.doc, metadata_list, key, this.macro_resolver.resolve((String)values.elementAt(i), lang, MacroResolver.SCOPE_META, node_id));
+		}
+	    }
+	    
+	} else {
+	    for (int i=0; i<metadata_names.size(); i++) {
+		String meta_name = (String) metadata_names.get(i);
+		String value = getMetadata(node_id, info, meta_name, lang);
+		GSXML.addMetadata(this.doc, metadata_list, meta_name, value);
+	    }
+	}
+	return metadata_list;
+    }
+
+    /** returns the structural information asked for.
+     * info_type may be one of
+     * INFO_NUM_SIBS, INFO_NUM_CHILDREN, INFO_SIB_POS
+     */
+    protected String getStructureInfo(String doc_id, String info_type) {
+	String value="";
+	if (info_type.equals(INFO_NUM_SIBS)) {
+	    String parent_id = OID.getParent(doc_id);
+	    if (parent_id.equals(doc_id)) {
+		value="0";
+	    } else {
+		value = String.valueOf(getNumChildren(parent_id));
+	    }
+	    return value;
+	}
+	
+	if (info_type.equals(INFO_NUM_CHILDREN)) {
+	    return String.valueOf(getNumChildren(doc_id));
+	}
+
+	
+	if (info_type.equals(INFO_SIB_POS)) {
+	    String parent_id = OID.getParent(doc_id);
+	    if (parent_id.equals(doc_id)) {
+		return "-1";
+	    }
+	    
+	    DBInfo info = this.gdbm_src.getInfo(parent_id);
+	    if (info==null) {
+		return "-1";
+	    }
+	    
+	    String contains = info.getInfo("contains");
+	    contains = contains.replaceAll("\"", parent_id);
+	    String [] children = contains.split(";");
+	    for (int i=0;i<children.length;i++) {
+		String child_id = children[i];
+		if (child_id.equals(doc_id)) {
+		    return String.valueOf(i+1); // make it from 1 to length
+			   
+		}
+	    }
+	    
+	    return "-1";
+	} else {
+	    return null;
+	}
+
+    }
+
+    protected int getNumChildren(String node_id) {
+	DBInfo info = this.gdbm_src.getInfo(node_id);
+	if (info == null) {
+	    return 0;
+	}
+	String contains = info.getInfo("contains");
+	if (contains.equals("")) {
+	    return 0;
+	}
+	String [] children = contains.split(";");
+	return children.length;
+    }
+    
+    /** returns the document type of the doc that the specified node 
+	belongs to. should be one of 
+	GSXML.DOC_TYPE_SIMPLE, 
+	GSXML.DOC_TYPE_PAGED, 
+	GSXML.DOC_TYPE_HIERARCHY
+    */
+    protected String getDocType(String node_id) {
+	DBInfo info = this.gdbm_src.getInfo(node_id);
+	if (info == null) {
+	    return GSXML.DOC_TYPE_SIMPLE;
+	}
+	String doc_type = info.getInfo("doctype");
+	if (!doc_type.equals("")&&!doc_type.equals("doc")) {
+	    return doc_type;
+	}
+
+	String top_id = OID.getTop(node_id);
+	boolean is_top = (top_id.equals(node_id) ? true : false);
+	
+	String children = info.getInfo("contains");
+	boolean is_leaf = (children.equals("") ? true : false);
+
+	if (is_top && is_leaf) { // a single section document
+	    return GSXML.DOC_TYPE_SIMPLE;
+	}
+
+	// now we just check the top node
+	if (!is_top) { // we need to look at the top info
+	    info = this.gdbm_src.getInfo(top_id);
+	}
+	if (info == null) {
+	    return GSXML.DOC_TYPE_HIERARCHY;
+	}
+ 
+	String childtype = info.getInfo("childtype");
+	if (childtype.equals("Paged")) {
+	    return GSXML.DOC_TYPE_PAGED;
+	}
+	return GSXML.DOC_TYPE_HIERARCHY;
+    }
+
+    /** returns the content of a node
+     * should return a nodeContent element:
+     * <nodeContent>text content or other elements</nodeContent>
+     */
+    abstract protected Element getNodeContent(String doc_id, String lang) throws GSException;
+
+    protected String getMetadata(String node_id, DBInfo info, 
+				 String metadata, String lang) {
+	boolean multiple = false;
+	String relation = "";
+	String separator = ", ";
+	int pos = metadata.indexOf(GSConstants.META_RELATION_SEP);
+	if (pos ==-1) {
+	    // just a plain meta entry eg dc.Title
+	    return macro_resolver.resolve((String)info.getInfo(metadata), lang, MacroResolver.SCOPE_META, node_id);
+	}
+	
+	String temp = metadata.substring(0, pos);
+	metadata = metadata.substring(pos+1);
+	// check for all on the front
+	if (temp.equals("all")) {
+	    multiple=true;	    
+	    pos = metadata.indexOf(GSConstants.META_RELATION_SEP);
+	    if (pos ==-1) {
+		temp = "";
+	    } else {
+		temp = metadata.substring(0, pos);
+		metadata = metadata.substring(pos+1);
+	    }
+	}
+	
+	// now check for relational info
+	if (temp.equals("parent") || temp.equals("root") || temp.equals( "ancestors")) { // "current" "siblings" "children" "descendents"
+	    relation = temp;
+	    pos = metadata.indexOf(GSConstants.META_RELATION_SEP);
+	    if (pos == -1) {
+		temp = "";
+	    } else {
+		temp = metadata.substring(0, pos);
+		metadata = metadata.substring(pos+1);
+	    }
+	}
+	
+	// now look for separator info
+	if (temp.startsWith(GSConstants.META_SEPARATOR_SEP) && temp.endsWith(GSConstants.META_SEPARATOR_SEP)) {
+	    separator = temp.substring(1, temp.length()-1);
+	    
+	}
+	
+	String relation_id = node_id;
+	if (relation.equals("parent") || relation.equals("ancestors")) {
+	    relation_id = OID.getParent(node_id);
+	    // parent or ancestor does not include self
+	    if (relation_id.equals(node_id)){
+		return "";
+	    }
+	} else if (relation.equals("root")) {
+	    relation_id = OID.getTop(node_id);
+	}
+	
+	// now we either have a single node, or we have ancestors	
+	DBInfo relation_info;
+	if (relation_id.equals(node_id)) {
+	    relation_info = info;
+	} else {
+	    relation_info = this.gdbm_src.getInfo(relation_id);
+	}
+	if (relation_info == null) {
+	    return "";
+	}
+
+	StringBuffer result = new StringBuffer();
+
+	if (!multiple) {
+	    result.append(this.macro_resolver.resolve(relation_info.getInfo(metadata), lang, MacroResolver.SCOPE_META, relation_id));
+	} else {
+	    // we have multiple meta
+	    Vector values = relation_info.getMultiInfo(metadata);
+	    if (values != null) {
+		boolean first = true;
+		for (int i=0; i<values.size(); i++) {
+		    if (first) {
+			first = false;
+		    } else {
+			result.append(separator);
+		    }
+		    result.append(this.macro_resolver.resolve((String)values.elementAt(i), lang, MacroResolver.SCOPE_META, relation_id));
+		}
+	    }
+	}
+	// if not ancestors, then this is all we do
+	if (!relation.equals("ancestors")) {
+	    return result.toString();
+	}
+	
+	// now do the ancestors 
+	String current_id = relation_id;
+	relation_id = OID.getParent(current_id);
+	while (!relation_id.equals(current_id)) {
+	    relation_info = this.gdbm_src.getInfo(relation_id);
+	    if (relation_info == null) return result.toString();
+	    if (!multiple) {
+		result.insert(0, separator);
+		result.insert(0, this.macro_resolver.resolve(relation_info.getInfo(metadata), lang, MacroResolver.SCOPE_META, relation_id));
+	    } else {
+		Vector values = relation_info.getMultiInfo(metadata);
+		if (values != null) {
+		    for (int i=values.size()-1; i>=0; i--) {
+			result.insert(0, separator);
+			result.insert(0, this.macro_resolver.resolve((String)values.elementAt(i), lang, MacroResolver.SCOPE_META, relation_id));
+		    }
+		}
+		
+	    }
+	    current_id = relation_id;
+	    relation_id = OID.getParent(current_id);
+	} 
+	return result.toString();
+    }
+    
+
+    /** needs to get info from gdbm database - if the calling code gets it already it may pay to pass it in instead */
+    protected String resolveTextMacros(String doc_content, String doc_id, String lang)
+    {
+	// resolve any collection specific macros
+	doc_content = macro_resolver.resolve(doc_content, lang, MacroResolver.SCOPE_TEXT, doc_id);
+	return doc_content;
+    }
+
+    protected Element getInfo(String doc_id, String info_type) {
+
+	String value="";
+	if (info_type.equals(INFO_NUM_SIBS)) {
+	    String parent_id = OID.getParent(doc_id);
+	    if (parent_id.equals(doc_id)) {
+		value="0";
+	    } else {
+		value = String.valueOf(getNumChildren(parent_id));
+	    }
+	} else if (info_type.equals(INFO_NUM_CHILDREN)) {
+	    value = String.valueOf(getNumChildren(doc_id));
+	} else if (info_type.equals(INFO_SIB_POS)) {
+	    String parent_id = OID.getParent(doc_id);
+	    if (parent_id.equals(doc_id)) {
+		value="-1";
+	    } else {
+		DBInfo info = this.gdbm_src.getInfo(parent_id);
+		if (info==null) {
+		    value ="-1";
+		} else {
+		    String contains = info.getInfo("contains");
+		    contains = contains.replaceAll("\"", parent_id);
+		    String [] children = contains.split(";");
+		    for (int i=0;i<children.length;i++) {
+			String child_id = children[i];
+			if (child_id.equals(doc_id)) {
+			    value = String.valueOf(i+1); // make it from 1 to length
+			    break;
+			}
+		    }
+		}
+	    }
+	} else {
+	    return null;
+	}
+	Element info_elem = this.doc.createElement("info");
+	info_elem.setAttribute(GSXML.NAME_ATT, info_type);
+	info_elem.setAttribute(GSXML.VALUE_ATT, value);
+	return info_elem;
+    }
+
+}   
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractGS2FieldSearch.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractGS2FieldSearch.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractGS2FieldSearch.java	(revision 13928)
@@ -0,0 +1,642 @@
+/*
+ *    AbstractGS2FieldSearch.java
+ *    Copyright (C) 2006 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *   the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.service;
+
+
+// Greenstone classes
+import org.greenstone.mgpp.*;
+import org.greenstone.gsdl3.util.*;
+
+// XML classes
+import org.w3c.dom.Document;
+import org.w3c.dom.Element; 
+import org.w3c.dom.NodeList;
+
+// java classes
+import java.util.Iterator;
+import java.util.Set;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.Vector;
+import java.io.File;
+
+import org.apache.log4j.*;
+
+
+abstract public class AbstractGS2FieldSearch 
+    extends AbstractGS2Search 
+{
+
+    // extra services offered by mgpp collections
+    protected static final String FIELD_QUERY_SERVICE = "FieldQuery";
+    protected static final String ADVANCED_FIELD_QUERY_SERVICE = "AdvancedFieldQuery";
+
+    // extra parameters used
+    protected static final String LEVEL_PARAM = "level";
+    protected static final String RANK_PARAM = "sortBy";
+    protected static final String RANK_PARAM_RANK = "1";
+    protected static final String RANK_PARAM_NONE = "0";
+    protected static final String SIMPLE_FIELD_PARAM = "simpleField";
+    protected static final String ADVANCED_FIELD_PARAM = "complexField";
+
+    // more params for field query
+    protected static final String FIELD_QUERY_PARAM = "fqv";
+    protected static final String FIELD_STEM_PARAM = "fqs";
+    protected static final String FIELD_CASE_PARAM = "fqc";
+    protected static final String FIELD_ACCENT_PARAM="fqa";
+    protected static final String FIELD_FIELD_PARAM = "fqf";
+    protected static final String FIELD_COMBINE_PARAM = "fqk";
+    protected static final String FIELD_COMBINE_PARAM_AND = "0";
+    protected static final String FIELD_COMBINE_PARAM_OR = "1";
+    protected static final String FIELD_COMBINE_PARAM_NOT = "2";
+
+    // some stuff for config files
+    protected static final String SEARCH_TYPE_ELEM = "searchType";
+    protected static final String SEARCH_TYPE_PLAIN = "plain";
+    protected static final String SEARCH_TYPE_FORM = "form";
+    protected static final String SEARCH_TYPE_FORM_SIMPLE = "simple";
+    protected static final String SEARCH_TYPE_FORM_ADVANCED = "advanced";
+
+    protected static final String DEFAULT_LEVEL_ELEM = "defaultLevel";
+    protected static final String DEFAULT_GDBM_LEVEL_ELEM = "defaultGDBMLevel";
+    protected static final String LEVEL_ELEM = "level";
+    protected static final String FIELD_ATT = "field";
+
+
+    protected static final int TEXT_QUERY = 0;
+    protected static final int SIMPLE_QUERY = 1;
+    protected static final int ADVANCED_QUERY = 2;
+
+    protected String AND_OPERATOR = "&";
+    protected String OR_OPERATOR = "|";
+    protected String NOT_OPERATOR = "!";
+    
+   // the default level for searching
+    protected String default_level=null;
+    // default level for gdbm db
+    protected String default_gdbm_level = null;
+    // which search services will we offer??
+    protected boolean plain_search = false;
+    protected boolean simple_form_search = false;
+    protected boolean advanced_form_search = false;
+
+
+    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.AbstractGS2FieldSearch.class.getName());
+
+    /** constructor */
+    public AbstractGS2FieldSearch()
+    {
+    }
+
+    public void cleanUp() {
+	super.cleanUp();
+    }
+
+    /** configure this service */
+    public boolean configure(Element info, Element extra_info)
+    {
+	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+	// the generic config has set up the text query service, but we may not want it
+	Element search_type_list = (Element) GSXML.getChildByTagName(info, SEARCH_TYPE_ELEM + GSXML.LIST_MODIFIER);
+	if (search_type_list == null) {
+	    // assume form and plain
+	    this.plain_search = true;
+	    this.simple_form_search = true;
+	    this.advanced_form_search = true;
+	} else {
+	    NodeList types = search_type_list.getElementsByTagName(SEARCH_TYPE_ELEM);
+	    for (int i=0; i<types.getLength(); i++) {
+		Element t = (Element)types.item(i);
+		String type_name = t.getAttribute(GSXML.NAME_ATT);
+		if (type_name.equals(SEARCH_TYPE_PLAIN)) {
+		    this.plain_search = true;
+		} else if (type_name.equals(SEARCH_TYPE_FORM)) {
+		    String type_type = t.getAttribute(GSXML.TYPE_ATT);
+		    if (type_type.equals("")) {
+			this.simple_form_search = true;
+			this.advanced_form_search = true;
+		    } else if (type_type.equals(SEARCH_TYPE_FORM_SIMPLE)) {
+			this.simple_form_search = true;
+		    } else if (type_type.equals(SEARCH_TYPE_FORM_ADVANCED)) {
+			this.advanced_form_search = true;
+			
+		    }
+		}
+	    }
+	}
+
+	if (!this.plain_search) {
+	    // need to remove the TextQuery service
+	    Element tq_service = GSXML.getNamedElement(short_service_info, GSXML.SERVICE_ELEM, GSXML.NAME_ATT, TEXT_QUERY_SERVICE);
+	    short_service_info.removeChild(tq_service);
+	    
+	}
+
+       
+	// Get the default level out of <defaultLevel> (buildConfig.xml)
+	Element def = (Element) GSXML.getChildByTagName(info, DEFAULT_LEVEL_ELEM);
+	if (def != null) {
+	    this.default_level = def.getAttribute(GSXML.SHORTNAME_ATT);
+	}
+	if (this.default_level == null || this.default_level.equals("")) {
+	    logger.error("default level not specified!, assuming Doc");
+	    this.default_level = "Doc";
+	}
+
+	// Get the default GDBM level
+	def = (Element) GSXML.getChildByTagName(info, DEFAULT_GDBM_LEVEL_ELEM);
+	if (def != null) {
+	    this.default_gdbm_level = def.getAttribute(GSXML.SHORTNAME_ATT);
+	}
+	if (this.default_gdbm_level == null || this.default_gdbm_level.equals("")) {
+	    logger.error("default gdbm level not specified!, assuming Sec");
+	    this.default_gdbm_level = "Sec";
+	}
+	
+	// get display info from extra info - for levels
+	if (extra_info !=null) {
+	    Document owner = info.getOwnerDocument();
+    
+	    NodeList levels = info.getElementsByTagName(GSXML.LEVEL_ELEM);
+	    Element config_search = (Element)GSXML.getChildByTagName(extra_info, GSXML.SEARCH_ELEM);
+	    
+	    for (int i=0; i<levels.getLength();i++) {
+		Element lev = (Element)levels.item(i);
+		String name = lev.getAttribute(GSXML.NAME_ATT);
+		Element node_extra = GSXML.getNamedElement(config_search,
+							   GSXML.LEVEL_ELEM,
+							   GSXML.NAME_ATT,
+							   name);
+		if (node_extra == null) {
+		    logger.error("haven't found extra info for level named "+name);
+		    continue;
+		}
+		
+		// get the display elements if any - displayName
+		NodeList display_names = node_extra.getElementsByTagName(GSXML.DISPLAY_TEXT_ELEM);
+		if (display_names !=null) {
+		    for (int j=0; j<display_names.getLength(); j++) {
+			Element e = (Element)display_names.item(j);
+			lev.appendChild(owner.importNode(e, true));
+		    }
+		}
+	    } // for each level
+	}
+ 
+	// the format info is the same for all services
+	Element format_info = (Element)format_info_map.get(TEXT_QUERY_SERVICE);
+	
+	// set up the extra services which are available for this collection
+	if (this.simple_form_search) {
+	    // set up short_service_info_ - for now just has id and type - name will be added in on the fly
+	    Element fq_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	    fq_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_QUERY);
+	    fq_service.setAttribute(GSXML.NAME_ATT, FIELD_QUERY_SERVICE);
+	    this.short_service_info.appendChild(fq_service);
+
+	    if (format_info != null) {
+		this.format_info_map.put(FIELD_QUERY_SERVICE, format_info);
+	    }
+	}
+	
+	if (this.advanced_form_search) {
+	    Element afq_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	    afq_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_QUERY);
+	    afq_service.setAttribute(GSXML.NAME_ATT, ADVANCED_FIELD_QUERY_SERVICE);
+	    this.short_service_info.appendChild(afq_service);
+	    
+	    if (format_info != null) {
+		this.format_info_map.put(ADVANCED_FIELD_QUERY_SERVICE, format_info);
+	    }
+	}
+
+	return true;
+    }
+
+
+    protected Element getServiceDescription(String service_id, String lang, String subset) {
+	// should we check that the service is actually on offer? presumably we wont get asked for services that we haven't advertised previously.
+	
+	if (!service_id.equals(FIELD_QUERY_SERVICE) && !service_id.equals(ADVANCED_FIELD_QUERY_SERVICE)) {
+	    return super.getServiceDescription(service_id, lang, subset);
+	}
+	
+	
+	Element service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_QUERY);
+	service.setAttribute(GSXML.NAME_ATT, service_id);
+	if (subset == null || subset.equals(GSXML.DISPLAY_TEXT_ELEM+GSXML.LIST_MODIFIER)) {
+	    service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_NAME, getTextString(service_id+".name", lang)));
+	    service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_SUBMIT, getTextString(service_id+".submit", lang)));
+	    service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_DESCRIPTION, getTextString(service_id+".description", lang)));
+	
+	}
+	if (subset == null || subset.equals(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER)) {
+	    Element param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);	
+	    service.appendChild(param_list);
+	    if (service_id.equals(FIELD_QUERY_SERVICE)) {
+		
+		addCustomQueryParams(param_list, lang);
+		createParameter(MAXDOCS_PARAM, param_list, lang);
+		// create a multi param for the fields etc
+		// text box, field
+		Element multiparam = null;
+		Element param=null;
+		multiparam = GSXML.createParameterDescription(this.doc, SIMPLE_FIELD_PARAM, "", GSXML.PARAM_TYPE_MULTI, null, null, null);
+		multiparam.setAttribute("occurs", "4");
+		param_list.appendChild(multiparam);
+		
+		// the components
+		createParameter(FIELD_QUERY_PARAM, multiparam,  lang);
+		createParameter(FIELD_FIELD_PARAM, multiparam,  lang);
+		
+	    } else { 
+		createParameter(LEVEL_PARAM, param_list,  lang);
+		createParameter(RANK_PARAM, param_list, lang);
+		createParameter(MAXDOCS_PARAM, param_list,  lang);
+		
+		
+		// create a multi param for the fields etc
+		// text box, stem, case, field
+		
+		Element multiparam = null;
+		Element param=null;
+		
+		multiparam = GSXML.createParameterDescription(this.doc, ADVANCED_FIELD_PARAM, "", GSXML.PARAM_TYPE_MULTI, null, null, null);
+		multiparam.setAttribute("occurs", "4");
+		param_list.appendChild(multiparam);
+		
+		createParameter(FIELD_COMBINE_PARAM, multiparam, lang);
+		createParameter(FIELD_QUERY_PARAM, multiparam, lang);
+		if (this.does_case) {
+		    createParameter(FIELD_CASE_PARAM, multiparam, lang);
+		}
+		if (this.does_stem) {
+		    createParameter(FIELD_STEM_PARAM, multiparam, lang);
+		}
+		if (this.does_accent) {
+		    createParameter(FIELD_ACCENT_PARAM, multiparam, lang);
+		}
+		createParameter(FIELD_FIELD_PARAM, multiparam, lang);    
+		
+	    } 
+	}
+	return service;
+	
+    }
+    
+    /** add in the level params to TextQuery */
+    protected void addCustomQueryParams(Element param_list, String lang) 
+    {
+	createParameter(LEVEL_PARAM, param_list, lang);
+	super.addCustomQueryParams(param_list, lang);
+    }
+
+    /** create a param and add to the list */
+    protected void createParameter(String name, Element param_list, String lang) 
+    {
+	Element param = null;
+	if (name.equals(LEVEL_PARAM)) {
+	    ArrayList level_ids = new ArrayList();
+	    ArrayList level_names = new ArrayList();
+	    getLevelData(level_ids, level_names, lang);
+	    if (level_ids.size()>1) {
+		// the first one is the default
+		param = GSXML.createParameterDescription2(this.doc, LEVEL_PARAM, getTextString("param."+LEVEL_PARAM, lang), GSXML.PARAM_TYPE_ENUM_SINGLE, (String)level_ids.get(0), level_ids, level_names);
+	    } else {
+		// we need to set the level, but hidden, in case there is an invalid level saved
+		param = GSXML.createParameterDescription(this.doc, LEVEL_PARAM, "", GSXML.PARAM_TYPE_INVISIBLE, (String)level_ids.get(0), null, null);
+	    }
+	} else if (name.equals(RANK_PARAM)) {
+	    String [] vals1 = {RANK_PARAM_RANK, RANK_PARAM_NONE };
+	    String [] vals1_texts = { getTextString("param."+RANK_PARAM+"."+RANK_PARAM_RANK, lang), getTextString("param."+RANK_PARAM+"."+RANK_PARAM_NONE, lang)};
+	    
+	    param = GSXML.createParameterDescription(this.doc, RANK_PARAM, getTextString("param."+RANK_PARAM, lang), GSXML.PARAM_TYPE_ENUM_SINGLE, RANK_PARAM_RANK, vals1, vals1_texts );
+	    
+	} else if (name.equals(FIELD_QUERY_PARAM)) {
+	    param = GSXML.createParameterDescription(this.doc, FIELD_QUERY_PARAM, getTextString("param."+FIELD_QUERY_PARAM, lang), GSXML.PARAM_TYPE_STRING, null, null, null);
+	    
+	    
+	} else if (name.equals(FIELD_CASE_PARAM) || name.equals(FIELD_STEM_PARAM) || name.equals(FIELD_ACCENT_PARAM)) {
+	    String[] bool_ops = {"0", "1"};
+	    String[] bool_texts = {getTextString("param.boolean.off", lang, "AbstractSearch"),getTextString("param.boolean.on", lang, "AbstractSearch")}; 
+	    param = GSXML.createParameterDescription(this.doc, name, getTextString("param."+name, lang), GSXML.PARAM_TYPE_BOOLEAN, BOOLEAN_PARAM_ON, bool_ops, bool_texts);
+	    
+	} else if (name.equals(FIELD_FIELD_PARAM)) {
+	    ArrayList fields = new ArrayList();
+	    ArrayList field_names = new ArrayList();
+	    getIndexData(fields, field_names, lang);
+	    // the field list -  read from config file
+	    param = GSXML.createParameterDescription2(this.doc, name, getTextString("param."+name, lang), GSXML.PARAM_TYPE_ENUM_SINGLE, (String)fields.get(0), fields, field_names );
+	    
+	} else if (name.equals(FIELD_COMBINE_PARAM)) {
+	    
+	    String []vals = {FIELD_COMBINE_PARAM_AND, FIELD_COMBINE_PARAM_OR, FIELD_COMBINE_PARAM_NOT};
+	    String []val_texts = {getTextString("param."+FIELD_COMBINE_PARAM+"."+FIELD_COMBINE_PARAM_AND, lang), getTextString("param."+FIELD_COMBINE_PARAM+"."+FIELD_COMBINE_PARAM_OR, lang), getTextString("param."+FIELD_COMBINE_PARAM+"."+FIELD_COMBINE_PARAM_NOT, lang)}; 
+		
+	    
+	    param = GSXML.createParameterDescription(this.doc, FIELD_COMBINE_PARAM, "", GSXML.PARAM_TYPE_ENUM_SINGLE, FIELD_COMBINE_PARAM_AND, vals, val_texts);
+	    param.setAttribute(GSXML.PARAM_IGNORE_POS_ATT, "0");
+	}
+
+	if (param != null) {
+	    param_list.appendChild(param);
+	} else {
+	    super.createParameter(name, param_list, lang);
+	}
+    }
+    
+    // should cache some of this
+    protected void getLevelData(ArrayList level_ids, ArrayList level_names, String lang) 
+    {
+	Element level_list = (Element)GSXML.getChildByTagName(this.config_info, LEVEL_ELEM+GSXML.LIST_MODIFIER);
+	NodeList levels = level_list.getElementsByTagName(LEVEL_ELEM);
+	for (int i=0; i<levels.getLength(); i++) {
+	    Element level = (Element)levels.item(i);
+	    String shortname = level.getAttribute(GSXML.SHORTNAME_ATT);
+	    if (shortname.equals("")) {
+		continue;
+	    }
+	    level_ids.add(shortname);
+	    String display_name = GSXML.getDisplayText(level, GSXML.DISPLAY_TEXT_NAME, lang, "en");
+	    if (display_name.equals("")) {
+		// we'll use the name, and the dictionary
+		display_name = level.getAttribute(GSXML.NAME_ATT);
+		if (display_name.equals("")) {
+		    display_name = shortname;
+		} else {
+		    display_name = getTextString("level."+display_name, lang);
+		}
+	    }
+	    level_names.add(display_name);
+	}
+    }
+
+    // the following three functions are needed so the base class can 
+    // call the process+SERVICE_NAME methods
+    /** process a text query */
+    protected Element processTextQuery(Element request) {
+	return processAnyQuery(request, TEXT_QUERY);
+    }
+
+    /** process a field query */    
+    protected Element processFieldQuery(Element request) {
+	return processAnyQuery(request, SIMPLE_QUERY);
+    }
+
+    /** process an advanced field query */
+    protected Element processAdvancedFieldQuery(Element request) {
+	return processAnyQuery(request, ADVANCED_QUERY);
+    }
+    
+    /** process a  query */
+    protected Element processAnyQuery(Element request, int query_type)
+    {
+
+	String service_name=null;
+	String empty_query_test_param=null;
+	// set up the type specific bits
+	switch (query_type) {
+	case TEXT_QUERY:
+	    service_name = TEXT_QUERY_SERVICE; 
+	    empty_query_test_param = QUERY_PARAM;
+	    break;
+	case SIMPLE_QUERY:
+	    service_name = FIELD_QUERY_SERVICE;
+	    empty_query_test_param = FIELD_QUERY_PARAM;
+	    break;
+	case ADVANCED_QUERY:
+	    service_name = ADVANCED_FIELD_QUERY_SERVICE;
+	    empty_query_test_param = FIELD_QUERY_PARAM;
+	    break;
+	default:
+	    // should never get here
+	    logger.error("wrong query type!!");
+	    return null;
+	}
+	
+	// Create a new (empty) result message
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	result.setAttribute(GSXML.FROM_ATT, service_name);
+	result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+	
+	// Get the parameters of the request
+	Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	if (param_list == null) {
+	    logger.error("TextQuery request had no paramList.");
+	    return result;  // Return the empty result
+	}
+
+	// Process the request parameters
+	HashMap params = GSXML.extractParams(param_list, false);
+
+	// Make sure a query has been specified
+	String query = (String) params.get(empty_query_test_param);
+	if (query == null || query.equals("")) {
+	    return result;  // Return the empty result
+	}
+
+	// If a field hasn't been specified, use the default - for textQuery
+	String field = (String) params.get(INDEX_PARAM); 
+	if (field == null) {
+	    field = default_index;
+	}
+	
+	// set up the appropriate query system
+	if (!setUpQueryer(params)) {
+	    return result;
+	}
+	
+	// if field search, create the query string
+	switch (query_type) {
+	case TEXT_QUERY:
+	    query = addFieldInfo(query, field);
+	    break;
+	case SIMPLE_QUERY:
+	    query = parseFieldQueryParams(params);
+	    break;
+	case ADVANCED_QUERY:
+	    query = parseAdvancedFieldQueryParams(params);
+	    break;
+	}
+
+	
+	// run the query
+	Object query_result = runQuery(query);
+	
+	// build up the response
+	
+	// Create a metadata list to store information about the query results
+	// should we be using metadataList? or something else?
+	Element metadata_list = this.doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER); 
+	result.appendChild(metadata_list);
+	
+	// Add a metadata element specifying the number of matching documents
+	long totalDocs = numDocsMatched(query_result);
+	
+	GSXML.addMetadata(this.doc, metadata_list, "numDocsMatched", ""+totalDocs);
+
+	// Create a document list to store the matching documents, and add them
+	String [] docs = getDocIDs(query_result);
+	String [] doc_ranks = getDocRanks(query_result);
+
+	// add a metadata item to specify docs returned
+	int docs_returned = docs.length;
+	if (does_paging) {
+	    int maxdocs = Integer.parseInt((String)params.get(MAXDOCS_PARAM));
+	    docs_returned = (maxdocs < (int)totalDocs ? maxdocs : (int)totalDocs);
+	}
+	GSXML.addMetadata(this.doc, metadata_list, "numDocsReturned", ""+docs_returned);
+	// add a metadata item to specify what actual query was done - eg if stuff was stripped out etc. and then we can use the query later, cos we don't know which parameter was the query
+	GSXML.addMetadata(this.doc, metadata_list, "query", query);
+	if (docs.length>0) {
+	    Element document_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	    result.appendChild(document_list);
+	    for (int d = 0; d < docs.length; d++) {
+		String doc_id = internalNum2OID(docs[d]);
+		Element doc_node = createDocNode(doc_id, doc_ranks[d]);
+		document_list.appendChild(doc_node);
+	    }
+	}
+	// Create a term list to store the term information, and add it
+	Element term_list = this.doc.createElement(GSXML.TERM_ELEM+GSXML.LIST_MODIFIER);
+	result.appendChild(term_list);
+	addTermInfo(term_list, params, query_result);
+
+	return result;
+    }
+
+    /** methods to handle actually doing the query */
+    /** do any initialisation of the query object */
+    abstract protected boolean setUpQueryer(HashMap params);
+    /** do the query */
+    abstract protected Object runQuery(String query);
+    /** get the total number of docs that match */
+    abstract protected long numDocsMatched(Object query_result);
+    /** get the list of doc ids */
+    abstract protected String [] getDocIDs(Object query_result);
+    /** get the list of doc ranks */
+    abstract protected String [] getDocRanks(Object query_result);
+    /** add in term info if available */
+    abstract protected boolean addTermInfo(Element term_list, HashMap params,
+					   Object query_result);
+    
+    /** combines all the field params into a single query
+     * - for simple field query */
+    /** We assume the combination (AND/OR) is done by the match param */
+    protected String parseFieldQueryParams(HashMap params) {
+
+	StringBuffer final_query = new StringBuffer(256);
+	String text_line = (String)params.get(FIELD_QUERY_PARAM);
+	String[] texts = text_line.split(",", -1);
+	String field_line = (String)params.get(FIELD_FIELD_PARAM);
+	String[] fields = field_line.split(",", -1);
+	
+	for (int i=0; i<texts.length; i++) {
+	    String q = texts[i].trim();
+	    if (!q.equals("")) {
+		final_query.append(" "+addFieldInfo(q, fields[i]));
+	    }
+	}
+
+	return final_query.toString();
+    }
+
+    abstract protected String addFieldInfo(String query, String field);
+    
+    /** combines all the field params into a single query
+     * - for advanced field query */   
+    protected String parseAdvancedFieldQueryParams(HashMap params) {
+
+	StringBuffer final_query = new StringBuffer(256);
+	String text_line = (String)params.get(FIELD_QUERY_PARAM);
+	String[] texts = text_line.split(",", -1);
+	String field_line = (String)params.get(FIELD_FIELD_PARAM);
+	String[] fields = field_line.split(",", -1);
+	String [] cases = null;
+	String [] stems = null;
+	String [] accents = null;
+	if (does_case) {
+	    String case_line = (String)params.get(FIELD_CASE_PARAM);
+	    cases = case_line.split(",", -1);
+	}
+	if (does_stem) {
+	    String stem_line = (String)params.get(FIELD_STEM_PARAM);
+	    stems = stem_line.split(",", -1);
+	}
+	if (does_accent) {
+	    String accent_line = (String)params.get(FIELD_ACCENT_PARAM);
+	    accents = accent_line.split(",", -1);
+	}
+	String combine_line = (String)params.get(FIELD_COMBINE_PARAM);
+	String [] combines = combine_line.split(",", -1);
+	String combine = "";
+	for (int i=0; i<texts.length; i++) {
+	    if (i==0) {// assume first one is blank
+		combine = "";
+	    } else {
+		String x = combines[i]; 
+		if (x.equals(FIELD_COMBINE_PARAM_AND)) {
+		    combine = AND_OPERATOR;
+		} else if (x.equals(FIELD_COMBINE_PARAM_OR)) {
+		    combine = OR_OPERATOR;
+		} else if (x.equals(FIELD_COMBINE_PARAM_NOT)) {
+		    combine = NOT_OPERATOR;
+		} 
+		
+	    }
+
+	    String q = texts[i].trim();
+	    boolean modified = false;
+	    if (!q.equals("")) {
+		String c = null;
+		String s = null;
+		String a = null;
+		if (does_case) {
+		    modified = true;
+		    c = cases[i];
+		}
+		if (does_stem) {
+		    modified = true;
+		    s = stems[i];
+		}
+		if (does_accent) {
+		    modified = true;
+		    a = accents[i];
+		}
+		if (modified) {
+		    q = addStemOptions(q, s, c, a);
+		}
+		addQueryElem(final_query, q, fields[i], combine);
+	    }
+	}
+	return final_query.toString();
+    }
+    
+    abstract protected void addQueryElem(StringBuffer final_query, 
+					 String query, String field, 
+					 String combine);
+    abstract protected String addStemOptions(String query, String stem,
+					     String casef, String accent);
+    
+}
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractGS2Search.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractGS2Search.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractGS2Search.java	(revision 13928)
@@ -0,0 +1,300 @@
+/*
+ *    GS2MGSearch.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *   the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.service;
+
+
+// Greenstone classes
+import org.greenstone.mg.*;
+import org.greenstone.gsdl3.util.*;
+
+// XML classes
+import org.w3c.dom.Document;
+import org.w3c.dom.Element; 
+import org.w3c.dom.NodeList;
+
+// java
+import java.util.Vector;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.Iterator;
+import java.io.File;
+
+import org.apache.log4j.*;
+
+public abstract class AbstractGS2Search 
+    extends AbstractSearch 
+{
+
+    protected static final String EQUIV_TERM_ELEM = "equivTerm";
+
+    protected static final String STEM_ATT = "stem";
+    protected static final String NUM_DOCS_MATCH_ATT = "numDocsMatch";
+    protected static final String FREQ_ATT = "freq";
+
+    // Elements used in the config file that are specific to this class
+    protected static final String DEFAULT_INDEX_ELEM = "defaultIndex";
+    protected static final String INDEX_STEM_ELEM = "indexStem";
+    protected static final String INDEX_ELEM = "index";
+
+    // Some indexing options
+    protected static final String STEMINDEX_OPTION = "stemIndexes";
+    protected static final String MAXNUMERIC_OPTION = "maxnumeric";
+
+    /** the stem used for the index files */
+    protected String index_stem = null;
+
+    // stem indexes available
+    protected boolean does_case=true;
+    protected boolean does_stem=true;
+    protected boolean does_accent=false;
+
+    // maxnumeric - 
+    protected int maxnumeric = 4;
+
+    protected GDBMWrapper gdbm_src = null;
+
+    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.GS2MGSearch.class.getName());
+
+
+    /** constructor */
+    public AbstractGS2Search()
+    {
+	this.gdbm_src = new GDBMWrapper();
+    }
+    public void cleanUp() {
+	super.cleanUp();
+	this.gdbm_src.closeDatabase();
+    }
+
+    /** configure this service */
+    public boolean configure(Element info, Element extra_info)
+    {
+	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+
+	// do we support any of the extended features?
+	does_chunking = true;
+
+	// Get the default index out of <defaultIndex> (buildConfig.xml)
+	Element def = (Element) GSXML.getChildByTagName(info, DEFAULT_INDEX_ELEM);
+	if (def != null) {
+	    this.default_index = def.getAttribute(GSXML.SHORTNAME_ATT);
+	} // otherwise will be "", and the first one will be the default
+
+	// the index stem is either the collection name or is specified in the config file
+	Element index_stem_elem = (Element) GSXML.getChildByTagName(info, INDEX_STEM_ELEM);
+	if (index_stem_elem != null) {
+	    this.index_stem = index_stem_elem.getAttribute(GSXML.NAME_ATT);
+	}
+	if (this.index_stem == null || this.index_stem.equals("")) {
+	    logger.warn("indexStem element not found, stem will default to collection name");
+	    this.index_stem = this.cluster_name;
+	}
+	
+	// get index options
+	Element index_option_list = (Element) GSXML.getChildByTagName(info, GSXML.INDEX_OPTION_ELEM + GSXML.LIST_MODIFIER);
+	if (index_option_list != null) {
+	    NodeList options = index_option_list.getElementsByTagName(GSXML.INDEX_OPTION_ELEM);
+	    for (int i=0; i<options.getLength(); i++) {
+		Element opt = (Element)options.item(i);
+		String name = opt.getAttribute(GSXML.NAME_ATT);
+		String value = opt.getAttribute(GSXML.VALUE_ATT);
+		if (name.equals(MAXNUMERIC_OPTION)) {
+		    int maxnum = Integer.parseInt(value);
+		    if (4 <= maxnum && maxnum < 512) {
+			maxnumeric = maxnum;
+		    }
+		}
+		else if (name.equals(STEMINDEX_OPTION)) {
+		    int stemindex = Integer.parseInt(value);
+		    // stem and case are true by default, accent folding false by default
+		    if ((stemindex & 1) == 0) {
+			does_case = false;
+		    }
+		    if ((stemindex & 2) == 0) {
+			does_stem = false;
+		    }
+		    if ((stemindex & 4) != 0) {
+			does_accent = true;
+		    }
+		}
+	    }
+	}
+
+	// get display info from extra info
+	if (extra_info !=null) {
+	    Document owner = info.getOwnerDocument();
+	    // so far we have index specific display elements, and global format elements 
+	    NodeList indexes = info.getElementsByTagName(GSXML.INDEX_ELEM);
+	    Element config_search = (Element)GSXML.getChildByTagName(extra_info, GSXML.SEARCH_ELEM);
+	    
+	    for (int i=0; i<indexes.getLength();i++) {
+		Element ind = (Element)indexes.item(i);
+		String name = ind.getAttribute(GSXML.NAME_ATT);
+		Element node_extra = GSXML.getNamedElement(config_search,
+							   GSXML.INDEX_ELEM,
+							   GSXML.NAME_ATT,
+							   name);
+		if (node_extra == null) {
+		    logger.error("haven't found extra info for index named "+name);
+		    continue;
+		}
+		
+		// get the display elements if any - displayName
+		NodeList display_names = node_extra.getElementsByTagName(GSXML.DISPLAY_TEXT_ELEM);
+		if (display_names !=null) {
+		    for (int j=0; j<display_names.getLength(); j++) {
+			Element e = (Element)display_names.item(j);
+			ind.appendChild(owner.importNode(e, true));
+		    }
+		}
+	    } // for each index
+	}
+    	// Open GDBM database for querying
+	String gdbm_db_file = GSFile.GDBMDatabaseFile(this.site_home, this.cluster_name, this.index_stem);
+	if (!this.gdbm_src.openDatabase(gdbm_db_file, GDBMWrapper.READER)) {
+	    logger.error(" Could not open GDBM database!");
+	    return false;
+	}
+	return true;
+    }
+
+    protected void getIndexData(ArrayList index_ids, ArrayList index_names, String lang) {
+	// the index info -
+	Element index_list = (Element)GSXML.getChildByTagName(this.config_info, INDEX_ELEM+GSXML.LIST_MODIFIER);
+	NodeList indexes = index_list.getElementsByTagName(INDEX_ELEM);
+	int len = indexes.getLength();
+	// now add even if there is only one
+	for (int i=0; i<len; i++) {
+	    Element index = (Element)indexes.item(i);
+	    String shortname = index.getAttribute(GSXML.SHORTNAME_ATT);
+	    if (shortname.equals("")) {
+		continue;
+	    }
+	    index_ids.add(shortname);
+	    String display_name = GSXML.getDisplayText(index, GSXML.DISPLAY_TEXT_NAME, lang, "en");
+	    if (display_name.equals("")) {
+		display_name = index.getAttribute(GSXML.NAME_ATT);
+		if (display_name.equals("")) {
+		    display_name = shortname;
+		}
+	    }
+	    index_names.add(display_name);
+		
+	}
+	
+    }
+
+    protected void addCustomQueryParams(Element param_list, String lang) 
+    {
+	if (this.does_case){
+	    createParameter(CASE_PARAM, param_list, lang);
+	}
+	if (this.does_stem){
+	    createParameter(STEM_PARAM, param_list, lang);
+	}
+	if (this.does_accent){
+	    createParameter(ACCENT_PARAM, param_list, lang);
+	}
+	createParameter(MATCH_PARAM, param_list, lang);
+    }
+
+
+
+    /** returns the document type of the doc that the specified node 
+	belongs to. should be one of 
+	GSXML.DOC_TYPE_SIMPLE, 
+	GSXML.DOC_TYPE_PAGED, 
+	GSXML.DOC_TYPE_HIERARCHY
+    */
+    protected String getDocType(String node_id){
+	DBInfo info = this.gdbm_src.getInfo(node_id);
+	if (info == null) {
+	    return GSXML.DOC_TYPE_SIMPLE;
+	}
+	String doc_type = info.getInfo("doctype");
+	if (!doc_type.equals("")&&!doc_type.equals("doc")) {
+	    return doc_type;
+	}
+
+	String top_id = OID.getTop(node_id);
+	boolean is_top = (top_id.equals(node_id) ? true : false);
+	
+	String children = info.getInfo("contains");
+	boolean is_leaf = (children.equals("") ? true : false);
+
+	if (is_top && is_leaf) { // a single section document
+	    return GSXML.DOC_TYPE_SIMPLE;
+	}
+
+	// now we just check the top node
+	if (!is_top) { // we need to look at the top info
+	    info = this.gdbm_src.getInfo(top_id);
+	}
+	if (info == null) {
+	    return GSXML.DOC_TYPE_HIERARCHY;
+	}
+ 
+	String childtype = info.getInfo("childtype");
+	if (childtype.equals("Paged")) {
+	    return GSXML.DOC_TYPE_PAGED;
+	}
+	return GSXML.DOC_TYPE_HIERARCHY;
+
+    }
+    
+    /** returns true if the node has child nodes */
+    protected boolean hasChildren(String node_id){
+	DBInfo info = this.gdbm_src.getInfo(node_id);
+	if (info == null) {
+	    return false;
+	}
+	String contains = info.getInfo("contains");
+	if (contains.equals("")) {
+	    return false;
+	}
+	return true;
+    }
+    
+    /** returns true if the node has a parent */
+    protected boolean hasParent(String node_id){
+	String parent = OID.getParent(node_id);
+	if (parent.equals(node_id)) {
+	    return false;
+	}
+	return true;
+    }
+    
+   /** convert MG internal id to Greenstone oid */
+    protected String internalNum2OID(long docnum)
+    {
+	return this.gdbm_src.docnum2OID(docnum);
+	
+    }
+    protected String internalNum2OID(String docnum)
+    {
+	return this.gdbm_src.docnum2OID(docnum);
+	
+    }
+
+}
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractSearch.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractSearch.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractSearch.java	(revision 13928)
@@ -0,0 +1,333 @@
+/*
+ *    AbstractSearch.java
+ *    Copyright (C) 2005 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.service;
+
+// Greenstone classes
+import org.greenstone.gsdl3.util.GSXML;
+import org.greenstone.gsdl3.util.GSPath;
+
+// XML classes
+import org.w3c.dom.Document;
+import org.w3c.dom.Element; 
+import org.w3c.dom.NodeList;
+
+// java classes
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.apache.log4j.*;
+
+/** Partially implements a generic search service
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ */
+
+public abstract class AbstractSearch
+    extends ServiceRack 
+{
+
+   static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.AbstractSearch.class.getName());
+
+    
+    // the search service
+    protected static final String TEXT_QUERY_SERVICE = "TextQuery";
+
+    // compulsory params
+    protected static final String INDEX_PARAM = "index";
+    protected static final String QUERY_PARAM = "query";
+
+    // optional standard params - some of these have to be implemented
+    protected static final String MAXDOCS_PARAM = "maxDocs";
+    protected static final String HITS_PER_PAGE_PARAM = "hitsPerPage";
+    protected static final String START_PAGE_PARAM = "startPage";
+
+    // some other common params that may be used
+    protected static final String CASE_PARAM = "case";
+    protected static final String STEM_PARAM = "stem";
+    protected static final String ACCENT_PARAM="accent";
+
+    protected static final String BOOLEAN_PARAM_ON = "1";
+    protected static final String BOOLEAN_PARAM_OFF = "0";
+    protected static final String MATCH_PARAM = "matchMode";
+    protected static final String MATCH_PARAM_ALL = "all";
+    protected static final String MATCH_PARAM_SOME = "some";
+
+    /** can more than one index be searched at the smae time? */
+    protected boolean does_multi_index_search = false;
+    /** does this service support paging of results? */
+    protected boolean does_paging = false;
+    /** does this service support asking for a subset of results? */
+    protected boolean does_chunking = false;
+    /** the default document type - use if all documents are the same type
+     */
+    protected String default_document_type = null;
+    /** the default index, or comma separated list if more than one is 
+     * the default (with start and end commas, eg ,TI,SU,). 
+     * Should be set by configure()
+     */
+    protected String default_index = "";
+
+    public AbstractSearch()
+    {
+    }
+
+    /** sets up the short service info for TextQuery. If other services 
+     * will be provided, should be added in the subclass configure
+     * also looks for search format info, and document format info
+     */
+    public boolean configure(Element info, Element extra_info)
+    {
+	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+
+	logger.info("Configuring AbstractSearch...");
+	
+	this.config_info = info;
+
+	// set up short_service_info_ - for now just has id and type. the name (lang dependent) will be added in if the list is requested.
+	Element tq_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	tq_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_QUERY);
+	tq_service.setAttribute(GSXML.NAME_ATT, TEXT_QUERY_SERVICE);
+	this.short_service_info.appendChild(tq_service);
+
+	// add some format info to service map if there is any - look in extra info
+	// first look in buildConfig
+	Element format = (Element)GSXML.getChildByTagName(info, GSXML.FORMAT_ELEM);
+	
+	if (format==null) {
+	    String path = GSPath.appendLink(GSXML.SEARCH_ELEM, GSXML.FORMAT_ELEM);
+	    format = (Element) GSXML.getNodeByPath(extra_info, path);
+	}
+	//Element format = (Element) GSXML.getChildByTagName(info, GSXML.FORMAT_ELEM);
+	if (format != null) {
+	    this.format_info_map.put(TEXT_QUERY_SERVICE, this.doc.importNode(format, true));
+	}
+	
+	// look for document display format - for documentType
+	String path = GSPath.appendLink(GSXML.DISPLAY_ELEM, GSXML.FORMAT_ELEM);
+	Element display_format = (Element)GSXML.getNodeByPath(extra_info, path);
+	if (display_format != null) {
+	    // check for docType option.
+	    Element doc_type_opt = GSXML.getNamedElement(display_format, "gsf:option", GSXML.NAME_ATT, "documentType");
+	    if (doc_type_opt != null) {
+		String value = doc_type_opt.getAttribute(GSXML.VALUE_ATT);
+		if (!value.equals("")) {
+		    this.default_document_type = value;
+		}
+	    }
+	}
+
+	return true;
+    }
+    
+    /** returns the description of the TextQuery service. If a subclass 
+     * provides other services they need to provides their own descriptions */
+    protected Element getServiceDescription(String service, String lang, String subset) 
+    {
+	if (!service.equals(TEXT_QUERY_SERVICE)) {
+	    return null;
+	}
+
+	Element tq_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	tq_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_QUERY);
+	tq_service.setAttribute(GSXML.NAME_ATT, TEXT_QUERY_SERVICE);
+	if (subset==null || subset.equals(GSXML.DISPLAY_TEXT_ELEM+GSXML.LIST_MODIFIER)) {
+	    tq_service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_NAME, getServiceName(TEXT_QUERY_SERVICE, lang) ));
+	    tq_service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_SUBMIT, getServiceSubmit(TEXT_QUERY_SERVICE, lang) ));
+	    tq_service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_DESCRIPTION, getServiceDescription(TEXT_QUERY_SERVICE, lang)));
+	}
+	if (subset==null || subset.equals(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER)) {
+	    Element param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	    addCustomQueryParams(param_list, lang);
+	    addStandardQueryParams(param_list, lang);
+	    tq_service.appendChild(param_list);
+	}
+	return tq_service;
+	
+    }
+
+    // perhaps these should be changed to search down the class hierarchy for 
+    // values - do can just put the info in the resource bundle to use it
+    /** returns the default name for the TextQuery service */
+    protected String getServiceName(String service_id, String lang) {
+	return getTextString(service_id+".name", lang);
+    }
+    
+    /** returns the default description for the TextQuery service */
+    protected String getServiceDescription(String service_id, String lang) {
+	return getTextString(service_id+".description", lang);
+    }
+
+    /** returns the default submit button text for the TextQuery service */
+    protected String getServiceSubmit(String service_id, String lang) {
+	return getTextString(service_id+".submit", lang);
+
+    }
+    /** adds the standard query params into the service description */
+    protected void addStandardQueryParams(Element param_list, String lang) 
+    {
+	createParameter(INDEX_PARAM, param_list, lang);
+	if (does_chunking) {
+	    createParameter(MAXDOCS_PARAM, param_list, lang);
+	}
+	if (does_paging) {
+	    createParameter(HITS_PER_PAGE_PARAM, param_list, lang);
+	    createParameter(START_PAGE_PARAM, param_list, lang);
+	}
+	createParameter(QUERY_PARAM, param_list, lang);
+    }
+
+    /** adds any service specific query params into the service
+     *	default implementation: add nothing. subclasses may need to 
+     * override this to add in their specific parameters
+     */
+    protected void addCustomQueryParams(Element param_list, String lang) 
+    {
+	// default behaviour, do nothing
+    }
+
+    /** default implementations for the standard parameters plus some 
+     * other common ones 
+     * index, maxDocs, hitsPerPage, startPage, query, case, stem, 
+    */
+    protected void createParameter(String name, Element param_list, String lang) {
+	Element param = null;
+	if (name.equals(QUERY_PARAM)) {
+	    param = GSXML.createParameterDescription(this.doc, QUERY_PARAM, getTextString("param."+QUERY_PARAM, lang), GSXML.PARAM_TYPE_STRING, null, null, null);
+	    param_list.appendChild(param);
+	} else if (name.equals(INDEX_PARAM)) {
+
+	    // should we make these class fields?
+	    ArrayList index_ids = new ArrayList();
+	    ArrayList index_names = new ArrayList();
+	    getIndexData(index_ids, index_names, lang);
+	    String param_type = GSXML.PARAM_TYPE_ENUM_SINGLE;
+	    if (does_multi_index_search) {
+		param_type = GSXML.PARAM_TYPE_ENUM_MULTI;
+	    }
+	    param = GSXML.createParameterDescription2(this.doc, INDEX_PARAM, getTextString("param."+INDEX_PARAM, lang), param_type, this.default_index, index_ids, index_names);
+	    param_list.appendChild(param);
+	} else if (name.equals(MAXDOCS_PARAM) || name.equals(HITS_PER_PAGE_PARAM)) {
+	    String default_val = "100";
+	    if (name.equals(HITS_PER_PAGE_PARAM)) {
+		default_val = "10";
+	    }
+	    param = GSXML.createParameterDescription(this.doc, name, getTextString("param."+name, lang), GSXML.PARAM_TYPE_INTEGER, default_val, null, null);
+	    param_list.appendChild(param);
+	} else if (name.equals(CASE_PARAM) || name.equals(STEM_PARAM) || name.equals(ACCENT_PARAM)) {
+	    String[] bool_ops = {"0", "1"};
+	    String[] bool_texts = {getTextString("param.boolean.off", lang),getTextString("param.boolean.on", lang)}; 
+	    param = GSXML.createParameterDescription(this.doc, name, getTextString("param."+name, lang), GSXML.PARAM_TYPE_BOOLEAN, BOOLEAN_PARAM_ON, bool_ops, bool_texts);
+	    param_list.appendChild(param);
+	} else if (name.equals(MATCH_PARAM)) {
+	    String[] vals = {MATCH_PARAM_SOME, MATCH_PARAM_ALL };
+	    String[] val_texts = {getTextString("param."+MATCH_PARAM+"."+MATCH_PARAM_SOME, lang), getTextString("param."+MATCH_PARAM+"."+MATCH_PARAM_ALL, lang)}; 
+	    param = GSXML.createParameterDescription(this.doc, MATCH_PARAM, getTextString("param."+MATCH_PARAM, lang), GSXML.PARAM_TYPE_ENUM_SINGLE, MATCH_PARAM_SOME, vals, val_texts);
+	    param_list.appendChild(param);
+	} else if (name.equals(START_PAGE_PARAM)) {
+	    // start page - set to 1 for the search page
+	    param = GSXML.createParameterDescription(this.doc, START_PAGE_PARAM, "", GSXML.PARAM_TYPE_INVISIBLE, "1", null, null);
+	    param_list.appendChild(param);
+	}
+	    
+	    
+    }
+    /** create an element to go into the search results list. A node element
+     * has the form
+     * <docNode nodeId='xxx' nodeType='leaf' docType='hierarchy' rank='0.23'/>
+     */
+    protected Element createDocNode(String node_id, String rank) {
+	Element node = this.doc.createElement(GSXML.DOC_NODE_ELEM);
+	node.setAttribute(GSXML.NODE_ID_ATT, node_id);
+	node.setAttribute(GSXML.NODE_RANK_ATT, rank);
+	String doc_type = null;
+	if (default_document_type != null) {
+	    doc_type = default_document_type;
+	} else {
+	    doc_type = getDocType(node_id);
+	}
+	node.setAttribute(GSXML.DOC_TYPE_ATT, doc_type);
+	String node_type = getNodeType(node_id, doc_type);	
+	node.setAttribute(GSXML.NODE_TYPE_ATT, node_type);
+	return node;
+    }
+
+    /** returns the node type of the specified node.
+	should be one of 
+	GSXML.NODE_TYPE_LEAF, 
+	GSXML.NODE_TYPE_INTERNAL, 
+	GSXML.NODE_TYPE_ROOT
+    */
+    protected String getNodeType(String node_id, String doc_type) {
+	if (doc_type.equals(GSXML.DOC_TYPE_SIMPLE)) {
+	    return GSXML.NODE_TYPE_LEAF;
+	}
+
+	if (!hasParent(node_id)) {
+	    return GSXML.NODE_TYPE_ROOT;
+	}
+	if (doc_type.equals(GSXML.DOC_TYPE_PAGED)) {
+	     return GSXML.NODE_TYPE_LEAF;
+	}
+	if (!hasChildren(node_id)) {
+	    return GSXML.NODE_TYPE_LEAF;
+	}
+	return GSXML.NODE_TYPE_INTERNAL;	
+	
+    }
+
+
+    /** returns the document type of the doc that the specified node 
+	belongs to. should be one of 
+	GSXML.DOC_TYPE_SIMPLE, 
+	GSXML.DOC_TYPE_PAGED, 
+	GSXML.DOC_TYPE_HIERARCHY
+	default implementation returns GSXML.DOC_TYPE_SIMPLE, over ride 
+	if documents can be hierarchical
+    */
+    protected String getDocType(String node_id) {
+	return GSXML.DOC_TYPE_SIMPLE;
+    }
+    
+    /** returns true if the node has child nodes 
+     * default implementation returns false, over ride if documents can be 
+     * hierarchical 
+     */
+    protected boolean hasChildren(String node_id) {
+	return false;
+    }
+    /** returns true if the node has a parent 
+     * default implementation returns false, over ride if documents can be 
+     * hierarchical*/
+    protected boolean hasParent(String node_id) {
+	return false;
+    }
+
+    /** do the actual query 
+     * must be implemented by subclass */
+    abstract protected Element processTextQuery(Element request); 
+	
+    /** get the details about the indexes available
+     * must be implemented by subclass
+     * there must be at least one index */
+    abstract protected void getIndexData(ArrayList index_ids, ArrayList index_names, String lang);
+
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/BerryBasket.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/BerryBasket.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/BerryBasket.java	(revision 13928)
@@ -0,0 +1,625 @@
+/*
+ *    BerryBasket.java
+ *    Copyright (C) 2006 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.greenstone.gsdl3.service;
+
+import java.sql.Statement;
+import java.util.Hashtable;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import org.greenstone.gsdl3.util.GSXML;
+import org.greenstone.gsdl3.util.GSPath;
+
+import java.net.InetAddress;
+import java.util.Properties;
+import java.util.Date;
+
+import javax.mail.*;
+import javax.mail.internet.*;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import javax.swing.Timer;
+
+import org.apache.log4j.*;
+
+public class BerryBasket
+    extends ServiceRack {
+
+    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.BerryBasket.class.getName());
+
+    // the services on offer
+    // these strings must match what is found in the properties file
+    protected static final String ADD_ITEM_SERVICE = "AddItem";
+    protected static final String DISPLAY_ITEMS_SERVICE = "DisplayList";
+    protected static final String ITEM_NUM_SERVICE = "ItemNum";
+    protected static final String DELETE_ITEMS_SERVICE = "DeleteItems";
+    protected static final String SEND_MAIL_SERVICE = "SendMail";  
+    protected static final String DELETE_ITEM_SERVICE = "DeleteItem";
+
+    protected static final String ITEM_PARAM = "item";
+    protected static final String delimiter ="|";
+    protected static final int delay = 1800000;
+
+    protected Hashtable userMap = null;
+    protected Hashtable timerMap = null;
+    protected String username="";
+    protected String password="";
+
+    
+    /** constructor */
+    public BerryBasket()
+    {
+	userMap =  new Hashtable();
+        timerMap = new Hashtable();
+    }
+
+    private Hashtable updateDocMap(Element request){
+       
+	String id = request.getAttribute("uid");
+        
+    	if (userMap.containsKey(id)){	
+	    if (timerMap.containsKey(id)){
+		UserTimer timer = (UserTimer)timerMap.get(id);
+                timer.restart();
+	    }    
+	    return (Hashtable) userMap.get(id);
+           }
+	else{
+            UserTimer timer = new UserTimer(delay,id);
+            timerMap.put(id,timer);
+            timer.start();
+            Hashtable newDocs= new Hashtable(); 
+	    userMap.put(id,newDocs);
+            return newDocs;
+	}    
+    }
+
+    
+    /** configure this service */
+    public boolean configure(Element info, Element extra_info)
+    {
+	logger.info("Configuring BerryBasket...");
+	this.config_info = info;
+
+	// set up short_service_info_ - for now just has name and type
+	Element add_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	add_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what??
+	add_service.setAttribute(GSXML.NAME_ATT, ADD_ITEM_SERVICE);
+	this.short_service_info.appendChild(add_service);
+
+	
+	// set up short_service_info_ - for now just has name and type
+	Element disp_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	disp_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what??
+	disp_service.setAttribute(GSXML.NAME_ATT, DISPLAY_ITEMS_SERVICE);
+	this.short_service_info.appendChild(disp_service);
+
+	// set up short_service_info_ - for now just has name and type
+	Element num_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	num_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what??
+	num_service.setAttribute(GSXML.NAME_ATT, ITEM_NUM_SERVICE);
+	this.short_service_info.appendChild(num_service);
+
+       	// set up short_service_info_ - for now just has name and type
+	Element delete_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	delete_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what??
+	delete_service.setAttribute(GSXML.NAME_ATT, DELETE_ITEMS_SERVICE);
+	this.short_service_info.appendChild(delete_service);
+
+        // set up short_service_info_ - for now just has name and type
+	Element deleteone_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	deleteone_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what??
+	deleteone_service.setAttribute(GSXML.NAME_ATT, DELETE_ITEM_SERVICE);
+	this.short_service_info.appendChild(deleteone_service);
+
+	// set up short_service_info_ - for now just has name and type
+	Element mail_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	mail_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what??
+	mail_service.setAttribute(GSXML.NAME_ATT, SEND_MAIL_SERVICE);
+	this.short_service_info.appendChild(mail_service);
+
+
+	return true;
+	
+    }
+
+    /** returns a specific service description */
+    protected Element getServiceDescription(String service_id, String lang, String subset) {
+
+	if (service_id.equals(ADD_ITEM_SERVICE)) {
+	    Element add_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	    add_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what??
+	    add_service.setAttribute(GSXML.NAME_ATT, ADD_ITEM_SERVICE);
+	    return add_service;
+	}
+	if (service_id.equals(DISPLAY_ITEMS_SERVICE)) {
+	    
+	    Element disp_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	    disp_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what??
+	    disp_service.setAttribute(GSXML.NAME_ATT, DISPLAY_ITEMS_SERVICE);
+	    return disp_service;
+	}
+
+	if (service_id.equals(ITEM_NUM_SERVICE)) {
+	    
+	    Element num_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	    num_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what??
+	    num_service.setAttribute(GSXML.NAME_ATT, ITEM_NUM_SERVICE);
+	    return num_service;
+	}
+
+	if (service_id.equals(DELETE_ITEMS_SERVICE)) {
+	    
+	    Element del_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	    del_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what??
+	    del_service.setAttribute(GSXML.NAME_ATT, DELETE_ITEMS_SERVICE);
+	    return del_service;
+	}
+
+	if (service_id.equals(DELETE_ITEM_SERVICE)) {
+	    
+	    Element delone_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	    delone_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what??
+	    delone_service.setAttribute(GSXML.NAME_ATT, DELETE_ITEM_SERVICE);
+	    return delone_service;
+	}
+
+	if (service_id.equals(SEND_MAIL_SERVICE)) {
+	    
+	    Element mail_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	    mail_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what??
+	    mail_service.setAttribute(GSXML.NAME_ATT, SEND_MAIL_SERVICE);
+	    return mail_service;
+	}
+
+	return null;
+    }
+
+    protected Element processAddItem(Element request) {
+        Hashtable docsMap = updateDocMap(request);
+
+	// Create a new (empty) result message
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	
+	// Get the parameters of the request
+	Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	if (param_list == null) {
+	    logger.error("BerryBasket Error: AddItem request had no paramList.");
+	    return result;  // Return the empty result
+	}
+
+	HashMap params = GSXML.extractParams(param_list, false);
+
+	String item = (String)params.get("item");
+	String collection = "";
+	int pos = item.indexOf(":");
+	if (pos != -1) {
+	    collection = item.substring(0,pos);
+	    item = item.substring(pos+1);
+	}
+
+	if (docsMap.containsKey(collection)){
+	    Hashtable items = (Hashtable) docsMap.get(collection);
+            if (!items.containsKey(item)){
+                Item newItem = generateItem(collection,item);
+                items.put(item, newItem);
+                result.appendChild(newItem.wrapIntoElement());
+	    }
+	}
+	else{
+	    Hashtable items = new Hashtable();
+            Item newItem = generateItem(collection,item);
+            items.put(item, newItem);
+            docsMap.put(collection,items);
+	    result.appendChild(newItem.wrapIntoElement());
+	}
+
+	return result;
+    }
+
+    private Item generateItem(String collection, String id){
+     
+	Item item = new Item(collection, id);
+  	String to = GSPath.appendLink(collection, "DocumentMetadataRetrieve");
+	ArrayList tmp = new ArrayList();
+	tmp.add(id);  
+	Element response = getDocumentMetadata(to,"en","dumy", tmp.iterator());
+	Element doc_node = (Element)response.getElementsByTagName(GSXML.DOC_NODE_ELEM).item(0); 
+
+	String node_id = doc_node.getAttribute(GSXML.NODE_ID_ATT);
+	Element metadata_list = (Element)doc_node.getElementsByTagName(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER).item(0);
+
+	//assign title metadata if any
+	Element metadata = GSXML.getNamedElement(metadata_list,"metadata","name","Title");
+	if (metadata != null){
+	    item.title = GSXML.getNodeText(metadata).trim();
+	} 
+	//assign date metadata if any
+	metadata = GSXML.getNamedElement(metadata_list,"metadata","name","Date");
+	if (metadata != null){
+	    item.date = GSXML.getNodeText(metadata).trim();
+	}	
+ 	
+	//assign root title metadata if any
+	metadata = GSXML.getNamedElement(metadata_list,"metadata","name","root_Title");
+	if (metadata != null){
+            String rootTitle = GSXML.getNodeText(metadata).trim();
+            if (!rootTitle.equals(item.title)){
+	          item.rootTitle = rootTitle;
+	    }
+	    
+	}
+
+	return item;
+    }
+
+
+    protected Element processDeleteItems(Element request) {
+          Hashtable docsMap = updateDocMap(request);
+	
+	// Create a new (empty) result message
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	
+	// Get the parameters of the request
+	Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+        
+        //GSXML.printXMLNode(param_list);
+
+	if (param_list == null) {
+	    logger.error("BerryBasket Error: DeleteItem request had no paramList.");
+	    return result;  // Return the empty result
+	}
+
+	HashMap params = GSXML.extractParams(param_list, false);
+      
+	String param = (String)params.get("items");
+ 
+        if (param == null) return result;     
+
+        String[] items = param.split("\\|");
+ 
+	for (int i=0; i<items.length; i++){
+            String item = items[i];
+	    if (item.trim().length() == 0) continue;
+	  	    String collection = "";
+	    int pos = item.indexOf(":");
+	    if (pos != -1) {
+		collection = item.substring(0,pos);
+		item = item.substring(pos+1);
+	    }
+     
+	    if (docsMap.containsKey(collection)){
+		Hashtable itemMap = (Hashtable) docsMap.get(collection);
+		if (itemMap.containsKey(item)){
+		    itemMap.remove(item);
+		}
+		if (itemMap.size()==0){
+		    docsMap.remove(collection);
+		}
+	    }
+
+	}
+
+	return result;
+    }
+
+     protected Element processDeleteItem(Element request) {
+          Hashtable docsMap = updateDocMap(request);
+	
+	// Create a new (empty) result message
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	
+	// Get the parameters of the request
+	Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+        
+        //GSXML.printXMLNode(param_list);
+
+	if (param_list == null) {
+	    logger.error("BerryBasket Error: DeleteItem request had no paramList.");
+	    return result;  // Return the empty result
+	}
+
+	HashMap params = GSXML.extractParams(param_list, false);
+      
+	String param = (String)params.get("item");
+ 
+        if (param == null) return result;     
+
+        String item = param;
+ 
+	String collection = "";
+	int pos = item.indexOf(":");
+	
+	if (pos != -1) {
+	    collection = item.substring(0,pos);
+	    item = item.substring(pos+1);
+	}
+	
+	if (docsMap.containsKey(collection)){
+	    Hashtable itemMap = (Hashtable) docsMap.get(collection);
+	    if (itemMap.containsKey(item)){
+		itemMap.remove(item);
+	    }
+	    if (itemMap.size()==0){
+		docsMap.remove(collection);
+	    }
+	}       
+
+	return result;
+    }
+
+
+    protected Element processItemNum(Element request){
+        // GSXML.printXMLNode(request);
+	Hashtable docsMap = updateDocMap(request);
+
+	// Create a new (empty) result message
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	
+        int size = 0;
+        String ids ="";   
+        Iterator keys = docsMap.keySet().iterator();
+	
+         while(keys.hasNext()){  
+	     Hashtable items = (Hashtable) docsMap.get((String)keys.next());
+             size+=items.size();
+             Iterator values = items.values().iterator();
+             while(values.hasNext()){ 
+		 Item item = (Item)values.next();
+                 result.appendChild(item.wrapIntoElement()); 
+	     }  
+	 }
+
+        Element selement = this.doc.createElement("size");
+	selement.setAttribute("value",size+"");
+        result.appendChild(selement);
+       	
+       	return result;
+    }
+
+    
+    private Element getDocumentMetadata(String to, String lang, String uid, Iterator ids){
+	
+      	// Build a request to obtain some document metadata
+	Element dm_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element dm_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, to, lang, uid);
+	dm_message.appendChild(dm_request);
+
+	// Create a parameter list to specify the required metadata information
+	HashSet meta_names = new HashSet();
+	meta_names.add("Title"); // the default
+        meta_names.add("root_Title");
+        meta_names.add("Date");
+
+
+       	Element param_list  = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	
+	Element param = null;
+	Iterator i = meta_names.iterator();
+	while (i.hasNext()) {
+	    String name = (String)i.next();
+	    param = this.doc.createElement(GSXML.PARAM_ELEM);
+	    param_list.appendChild(param);
+	    param.setAttribute(GSXML.NAME_ATT, "metadata");
+	    param.setAttribute(GSXML.VALUE_ATT, name);
+	
+	}
+	
+	dm_request.appendChild(param_list);
+	
+	// create the doc node list for the metadata request
+	Element dm_doc_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	dm_request.appendChild(dm_doc_list);
+
+	while (ids.hasNext()){
+	    // Add the documentNode to the list
+	    Element dm_doc_node = this.doc.createElement(GSXML.DOC_NODE_ELEM);
+	    dm_doc_list.appendChild(dm_doc_node);
+	    dm_doc_node.setAttribute(GSXML.NODE_ID_ATT,(String)ids.next());
+	}
+
+	return (Element) this.router.process(dm_message);
+
+    }
+
+
+    protected Element processDisplayList(Element request) {
+	// Create a new (empty) result message
+     	Hashtable docsMap =  updateDocMap(request);
+
+	// Create a new (empty) result message
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	
+        Iterator keys = docsMap.keySet().iterator();
+	
+         while(keys.hasNext()){     
+	     String collection = (String)keys.next(); 
+             Hashtable items = (Hashtable)docsMap.get(collection);
+	     Iterator itemItr = items.values().iterator();
+
+             Element collectionNode = this.doc.createElement("collection");
+             collectionNode.setAttribute("name",collection);
+	     result.appendChild(collectionNode);
+
+	     while(itemItr.hasNext()){  
+                Item item = (Item)itemItr.next();
+	        Element itemElement = this.doc.createElement("item");
+		
+                collectionNode.appendChild(itemElement);
+		itemElement.setAttribute("name", item.docid);
+	        itemElement.setAttribute("collection", item.collection);
+		itemElement.setAttribute("title",item.title);
+		itemElement.setAttribute("date",item.date);
+               	itemElement.setAttribute("root_title",item.rootTitle);                
+ 	     }	     
+	 }
+       
+	return result;
+
+   }
+
+
+    public Element processSendMail(Element request){
+	// Create a new (empty) result message
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	
+	// Get the parameters of the request
+	Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+        
+        GSXML.printXMLNode(param_list);
+     
+	if (param_list == null) {
+	    logger.error("BerryBasket Error: SendMail request had no paramList.");
+	    return result;  // Return the empty result
+	}
+
+	HashMap params = GSXML.extractParams(param_list, false);
+      
+	String to = (String)params.get("address");
+        String subject = (String)params.get("subject");
+	String mailhost = (String)params.get("host");
+        String content =  (String)params.get("content");
+        String cc = (String)params.get("cc");
+        String bcc = (String)params.get("bcc");
+        username = (String)params.get("user");
+        password = (String)params.get("password");
+	String mailer = "msgsend";        
+       
+	try {
+	   
+	    Properties props = System.getProperties();
+	    // XXX - could use Session.getTransport() and Transport.connect()
+	    // XXX - assume we're using SMTP
+	    // TODO: need to get Mail server info from the configuration file
+	    if (mailhost != null && mailhost.trim().equals(""))
+		props.put("mail.smtp.host", mailhost);
+	    else{
+		props.put("mail.smtp.host", "webmail.cs.waikato.ac.nz"); 
+	    }
+
+	    // TODO: need to get account info from the configuration file
+            Authenticator auth = new Authenticator(){
+		 protected  PasswordAuthentication  getPasswordAuthentication(){
+		     if (username == null || username.equals("")){
+			 username = "xxxxx";
+                         password = "xxxxx";
+		     }
+		      return new PasswordAuthentication(username,password);
+		  }
+            };
+	
+           Session session = Session.getInstance(props, auth);
+
+	   Message msg = new MimeMessage(session);
+	   msg.setFrom();
+
+	   msg.setRecipients(Message.RecipientType.TO,
+			     InternetAddress.parse(to, false));
+	   if (cc != null)
+	       msg.setRecipients(Message.RecipientType.CC,
+				 InternetAddress.parse(cc, false));
+	    if (bcc != null)
+		msg.setRecipients(Message.RecipientType.BCC,
+				  InternetAddress.parse(bcc, false));
+
+	    msg.setSubject(subject);
+	    
+            msg.setText(content.replaceAll("-------","&"));
+	    msg.setHeader("X-Mailer", mailer);
+	    msg.setSentDate(new Date());
+
+	    // send the thing off
+	    Transport.send(msg);
+	    
+	    logger.info("\nMail was sent successfully.");
+            result.appendChild(this.doc.createTextNode("Mail was sent successfully."));
+	} catch (Exception e) {
+	    e.printStackTrace();
+            result.appendChild(this.doc.createTextNode(e.getMessage()));
+	}
+	
+	return result;
+    }
+
+    protected class Item {
+
+	public String collection;
+	public String docid;
+        public String title="";
+        public String query="";
+        public String date="";
+        public String rootTitle="";
+
+	public Item(String coll, String id) {
+	    this.collection = coll;
+	    this.docid = id;
+        }
+
+        public boolean equals(Object o){
+	    if (! (o instanceof Item)){
+		return false;
+	    }
+	    Item item = (Item)o;
+            String id = collection+":"+docid;
+	    String idin = item.collection+":"+item.docid;
+	    return id.equals(idin);
+
+	}
+
+        public String toString(){
+                
+	    return collection+":"+docid+":"+"["+((!rootTitle.equals(""))?(rootTitle+":"):"")+title+"]";
+	}       
+
+        public Element wrapIntoElement(){
+              Element itemElement = doc.createElement("item");  
+              itemElement.setAttribute("name", docid);
+	      itemElement.setAttribute("collection", collection);
+	      itemElement.setAttribute("title",title);
+	      itemElement.setAttribute("date",date);
+	      itemElement.setAttribute("root_title",rootTitle);
+              return itemElement; 	       
+	}
+    }
+	private class UserTimer extends Timer implements ActionListener{
+            String id="";
+
+            public UserTimer(int delay, String id){
+                super(delay,(ActionListener)null);
+                addActionListener(this);
+		this.id=id;
+	    }
+
+	 
+           public void actionPerformed(ActionEvent e){
+	       userMap.remove(id);            
+               timerMap.remove(id);
+               stop();
+	    }
+
+	}
+    
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/CrossCollectionSearch.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/CrossCollectionSearch.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/CrossCollectionSearch.java	(revision 13928)
@@ -0,0 +1,377 @@
+/*
+ *    CrossCollectionSearch.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.service;
+
+import org.greenstone.gsdl3.util.GSXML;
+import org.greenstone.gsdl3.util.GSPath;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.HashMap;
+
+import org.apache.log4j.*;
+
+/**
+ *
+ * @author <a href="mailto:greenstone@cs.waikato.ac.nz">Katherine Don</a>
+ */
+
+public class CrossCollectionSearch
+    extends ServiceRack {
+
+     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.CrossCollectionSearch.class.getName());
+    protected static final String QUERY_PARAM = "query";
+    protected static final String COLLECTION_PARAM = "collection";
+
+    // the services on offer - these proxy the actual collection ones
+    protected static final String TEXT_QUERY_SERVICE = "TextQuery";
+    protected static final String ADV_QUERY_SERVICE = "AdvTextQuery";
+    protected static final String DOCUMENT_METADATA_RETRIEVE_SERVICE = "DocumentMetadataRetrieve";
+    
+    protected String [] coll_ids_list = null;
+    protected String [] coll_names_list = null;
+
+    
+    /** constructor */
+    public CrossCollectionSearch()
+    {
+    }
+
+    public boolean configure(Element info, Element extra_info) 
+    {
+	// any parameters? colls to include??
+	logger.info("Configuring CrossCollectionSearch...");
+	// query service
+	Element ccs_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	ccs_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_QUERY);
+	ccs_service.setAttribute(GSXML.NAME_ATT, TEXT_QUERY_SERVICE);
+	this.short_service_info.appendChild(ccs_service);
+
+	// metadata service
+	Element dmr_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	dmr_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
+	dmr_service.setAttribute(GSXML.NAME_ATT, DOCUMENT_METADATA_RETRIEVE_SERVICE);
+	this.short_service_info.appendChild(dmr_service);
+
+	// get any format info
+	Element format_info = (Element)GSXML.getChildByTagName(info, GSXML.FORMAT_ELEM);
+	if (format_info != null) {
+	    this.format_info_map.put(TEXT_QUERY_SERVICE, this.doc.importNode(format_info, true));
+	} else {
+	    // add in a default format statement
+	    String format_string = "<format xmlns:gsf='http://www.greenstone.org/greenstone3/schema/ConfigFormat' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'><gsf:template match='documentNode'><td><a><xsl:attribute name='href'>?a=d&amp;c=<xsl:value-of select='@collection'/>&amp;d=<xsl:value-of select='@nodeID'/><xsl:if test=\"@nodeType='leaf'\">&amp;sib=1</xsl:if>&amp;dt=<xsl:value-of select='@docType'/>&amp;p.a=q&amp;&amp;p.s="+TEXT_QUERY_SERVICE+"&amp;p.c=";
+	    if (this.cluster_name!=null) {
+		format_string += this.cluster_name;
+	    }
+	    format_string += "</xsl:attribute><gsf:icon/></a></td><td><gsf:metadata name='Title'/> (<xsl:value-of select='@collection'/>) </td></gsf:template></format>";
+	    this.format_info_map.put(TEXT_QUERY_SERVICE, this.doc.importNode(this.converter.getDOM(format_string).getDocumentElement(), true));
+	}
+	return true;
+    }
+
+    protected Element getServiceDescription(String service, String lang, String subset) 
+    {
+	if (service.equals(TEXT_QUERY_SERVICE)) {
+
+	    Element ccs_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	    ccs_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_QUERY);
+	    ccs_service.setAttribute(GSXML.NAME_ATT, TEXT_QUERY_SERVICE);
+	    
+	    // display info
+	    if (subset==null || subset.equals(GSXML.DISPLAY_TEXT_ELEM+GSXML.LIST_MODIFIER)) {
+		ccs_service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_NAME, getTextString(TEXT_QUERY_SERVICE+".name", lang)));
+		ccs_service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_SUBMIT, getTextString(TEXT_QUERY_SERVICE+".submit", lang)));
+		ccs_service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_DESCRIPTION, getTextString(TEXT_QUERY_SERVICE+".description", lang)));
+	    }
+	    // param info
+	    if (subset==null || subset.equals(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER)) {
+		Element param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+		// collection list
+		if (coll_ids_list ==null ) {
+		    initCollectionList();
+		}
+		Element param = GSXML.createParameterDescription(this.doc, COLLECTION_PARAM, getTextString("param."+COLLECTION_PARAM, lang), GSXML.PARAM_TYPE_ENUM_MULTI, "all", coll_ids_list, coll_names_list);
+		param_list.appendChild(param);
+		// query param
+		param = GSXML.createParameterDescription(this.doc, QUERY_PARAM, getTextString("param."+QUERY_PARAM, lang), GSXML.PARAM_TYPE_STRING, null, null, null);
+		param_list.appendChild(param);
+		ccs_service.appendChild(param_list);
+	    }
+	    
+	    logger.debug("service description="+this.converter.getPrettyString(ccs_service));
+	    return ccs_service;
+	}
+	// these ones are probably never called, but put them here just in case
+	Element service_elem = this.doc.createElement(GSXML.SERVICE_ELEM);
+	service_elem.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
+	service_elem.setAttribute(GSXML.NAME_ATT, service);
+	return service_elem;
+    
+
+    }
+
+    
+    protected Element processTextQuery(Element request) {
+	// Create a new (empty) result message
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	result.setAttribute(GSXML.FROM_ATT, TEXT_QUERY_SERVICE);
+	result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	// Get the parameters of the request
+	Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	if (param_list == null) {
+	    logger.error("TextQuery request had no paramList.");
+	    return result;  // Return the empty result
+	}
+
+	// get the collection list
+	String [] colls_list;
+	Element coll_param = GSXML.getNamedElement(param_list, GSXML.PARAM_ELEM, GSXML.NAME_ATT,  COLLECTION_PARAM);
+	if (coll_param == null) {
+	    colls_list = coll_ids_list;
+	} else {
+	    String coll_list = GSXML.getValue(coll_param);
+	    if (coll_list.equals("all") || coll_list.equals("")) {
+		colls_list = coll_ids_list;
+	    } else {
+		colls_list = coll_list.split(",");
+	    }
+	}
+	
+	Element query_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	// we are sending the same request to each collection - build up the to
+	// attribute for the request
+	StringBuffer to_att = new StringBuffer();
+	for (int i=0; i<colls_list.length; i++) {
+	    if (i>0) {
+		to_att.append(",");
+	    }
+	    to_att.append(GSPath.appendLink(colls_list[i], "TextQuery"));
+	    
+	}
+	// send the query to all colls
+	Element query_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, to_att.toString(), lang, "");
+	query_message.appendChild(query_request);
+	// should we add params individually?
+	Element new_param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	query_request.appendChild(new_param_list);
+	new_param_list.appendChild(this.doc.importNode(GSXML.getNamedElement(param_list, GSXML.PARAM_ELEM, GSXML.NAME_ATT, QUERY_PARAM), true));
+	Element query_result = this.router.process(query_message);
+	
+	// gather up the data from each response
+	int numDocsMatched = 0;
+	int numDocsReturned = 0;
+
+	//term info??
+
+	NodeList metadata = query_result.getElementsByTagName(GSXML.METADATA_ELEM);
+	for (int j=0; j<metadata.getLength(); j++) {
+	    Element meta = (Element)metadata.item(j);
+	    if (meta.getAttribute(GSXML.NAME_ATT).equals("numDocsReturned")) {
+		numDocsReturned += Integer.parseInt(GSXML.getValue(meta));
+	    } else if (meta.getAttribute(GSXML.NAME_ATT).equals("numDocsMatched")) {
+		numDocsMatched += Integer.parseInt(GSXML.getValue(meta));
+	    }
+	}
+	
+	Element metadata_list = this.doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
+	result.appendChild(metadata_list);
+	GSXML.addMetadata(this.doc, metadata_list, "numDocsReturned", ""+numDocsReturned);
+	//GSXML.addMetadata(this.doc, metadata_list, "numDocsMatched", ""+numDocsMatched);
+
+	Element doc_node_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	result.appendChild(doc_node_list);
+	
+	NodeList responses = query_result.getElementsByTagName(GSXML.RESPONSE_ELEM);
+	
+	for (int k=0; k<responses.getLength(); k++) {
+	    String coll_name = GSPath.getFirstLink(((Element)responses.item(k)).getAttribute(GSXML.FROM_ATT));
+	    NodeList nodes = ((Element)responses.item(k)).getElementsByTagName(GSXML.DOC_NODE_ELEM);
+	    if (nodes==null || nodes.getLength()==0) continue;
+	    Element last_node = null;
+	    Element this_node = null;
+	    for (int n=0; n<nodes.getLength(); n++) {
+		this_node = (Element)nodes.item(n);
+		this_node.setAttribute("collection", coll_name);
+		if (k==0) {
+
+		    doc_node_list.appendChild(this.doc.importNode(this_node, true));
+		} else {
+		    if (last_node==null) {
+			last_node = (Element)GSXML.getChildByTagName(doc_node_list, GSXML.DOC_NODE_ELEM);
+		    }
+		    last_node = GSXML.insertIntoOrderedList(doc_node_list, GSXML.DOC_NODE_ELEM, last_node, this_node, "rank", true);
+		}
+		
+	    }
+	}
+	return result;
+    }
+
+//     protected Element processAdvTextQuery(Element request) 
+//     {
+	
+//     }
+    protected boolean initCollectionList() {
+	String lang="en";
+	String uid = "";
+	// first, get the message router info
+	Element coll_list_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element coll_list_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_DESCRIBE, "", lang, ""); // uid
+	coll_list_message.appendChild(coll_list_request);
+	logger.debug("coll list request = "+this.converter.getPrettyString(coll_list_request));
+	Element coll_list_response = (Element)this.router.process(coll_list_message);
+	if (coll_list_response==null) {
+	    logger.error("couldn't query the message router!");
+	    return false;
+	}
+	logger.debug("coll list response = "+this.converter.getPrettyString(coll_list_response));
+	// second, get some info from each collection. we want the coll name 
+	// and whether its got a text query service 
+	
+	NodeList colls = coll_list_response.getElementsByTagName(GSXML.COLLECTION_ELEM);
+	// we will send all the requests in a single message
+	Element metadata_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	for (int i=0; i<colls.getLength(); i++) {
+	    Element c = (Element)colls.item(i);
+	    String name = c.getAttribute(GSXML.NAME_ATT);	    
+	    Element metadata_request = GSXML.createBasicRequest(this.doc,  GSXML.REQUEST_TYPE_DESCRIBE, name, lang, uid);
+	    metadata_message.appendChild(metadata_request);
+	}
+	logger.debug("metadata request = "+this.converter.getPrettyString(metadata_message));
+	Element metadata_response = (Element)this.router.process(metadata_message);
+	logger.debug("metadata response = "+this.converter.getPrettyString(metadata_response));
+
+	NodeList coll_responses = metadata_response.getElementsByTagName(GSXML.COLLECTION_ELEM);
+	ArrayList valid_colls = new ArrayList();
+	ArrayList valid_coll_names = new ArrayList();
+	for (int i=0; i<coll_responses.getLength(); i++) {
+	    Element coll = (Element)coll_responses.item(i);
+	    Element service_list = (Element)GSXML.getChildByTagName(coll, GSXML.SERVICE_ELEM+GSXML.LIST_MODIFIER);
+	    if (service_list==null) continue;
+	    Element query_service = GSXML.getNamedElement(service_list, GSXML.SERVICE_ELEM, GSXML.NAME_ATT, TEXT_QUERY_SERVICE); // should be AbstractSearch.TEXT_QUERY_SERVICE
+	    if (query_service == null) continue;
+	    String coll_id = coll.getAttribute(GSXML.NAME_ATT);
+	    String coll_name = coll_id+": "+GSXML.getDisplayText(coll, GSXML.DISPLAY_TEXT_NAME, "en", "en"); // just use english for now until we do some caching or something
+	    valid_colls.add(coll_id);
+	    valid_coll_names.add(coll_name);
+	}
+
+	if (valid_colls.size()==0) {
+	    return false;
+	}
+	valid_colls.add(0, "all");
+	valid_coll_names.add(0, getTextString("param."+COLLECTION_PARAM+".all", "en" ));
+	this.coll_ids_list = new String[1];
+	this.coll_names_list = new String[1];
+	this.coll_ids_list = (String []) valid_colls.toArray(coll_ids_list);
+	this.coll_names_list = (String []) valid_coll_names.toArray(coll_names_list);
+	return true;
+    }
+
+    protected Element processDocumentMetadataRetrieve(Element request) {
+	// Create a new (empty) result message
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	result.setAttribute(GSXML.FROM_ATT, DOCUMENT_METADATA_RETRIEVE_SERVICE);
+	result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+	
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	// Get the parameters of the request
+	Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	if (param_list == null) {
+	    logger.error("DocumentMetadataRetrieve request had no paramList.");
+	    return result;  // Return the empty result
+	}
+	
+	NodeList query_doc_list = request.getElementsByTagName(GSXML.DOC_NODE_ELEM);
+	if (query_doc_list.getLength()==0) {
+	   logger.error("DocumentMetadataRetrieve request had no documentNodes.");
+	    return result;  // Return the empty result
+	} 
+	
+	// the resulting doc node list
+	Element result_node_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	result.appendChild(result_node_list);
+	
+	// get all the metadata params
+	Element new_param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	Element param = GSXML.createParameter(this.doc, "metadata", "Title");
+	new_param_list.appendChild(param);
+	
+	// organise the nodes into collection lists
+	HashMap coll_map = new HashMap();
+	
+	for (int i=0; i<query_doc_list.getLength(); i++) {
+	    Element doc_node = (Element)query_doc_list.item(i);
+	    String coll_name = doc_node.getAttribute("collection");
+	    Element coll_items = (Element)coll_map.get(coll_name);
+	    if (coll_items==null) {
+		coll_items=this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+		coll_map.put(coll_name, coll_items);
+	    }
+	    coll_items.appendChild(this.doc.importNode(doc_node, true));
+	}
+	
+	// create teh individual requests
+	Element meta_request_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Set mapping_set = coll_map.entrySet();
+	Iterator iter = mapping_set.iterator();
+	
+	while (iter.hasNext()) {
+	    Map.Entry e = (Map.Entry)iter.next();
+	    String cname = (String)e.getKey();
+	    Element doc_nodes = (Element)e.getValue();
+	    Element meta_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, GSPath.appendLink(cname, DOCUMENT_METADATA_RETRIEVE_SERVICE), lang, "");
+	    meta_request.appendChild(doc_nodes);
+	    meta_request.appendChild(new_param_list.cloneNode(true));
+	    meta_request_message.appendChild(meta_request);
+	    
+	}
+	Element meta_result = this.router.process(meta_request_message);
+	
+	// now need to put the doc nodes back in the right order
+	// go through the original list again. keep an element pointer to
+	// the next element in each collections list
+	NodeList meta_responses = meta_result.getElementsByTagName(GSXML.RESPONSE_ELEM);
+	for (int i=0; i<meta_responses.getLength(); i++) {
+	    String collname = GSPath.getFirstLink(((Element)meta_responses.item(i)).getAttribute(GSXML.FROM_ATT));
+	    Element first_elem = (Element)GSXML.getNodeByPath(meta_responses.item(i), "documentNodeList/documentNode");
+	    coll_map.put(collname, first_elem);
+	}
+
+	for (int i=0; i<query_doc_list.getLength(); i++) {
+	    Element doc_node = (Element)query_doc_list.item(i);
+	    Element new_node = (Element)this.doc.importNode(doc_node, false);
+	    result_node_list.appendChild(new_node);
+	    String coll_name = doc_node.getAttribute("collection");
+	
+	    Element meta_elem = (Element)coll_map.get(coll_name);
+	    GSXML.mergeMetadataLists(new_node, meta_elem);
+	    coll_map.put(coll_name, meta_elem.getNextSibling());
+	}
+	return result;
+    }
+}
+ 
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/FedoraSearch.java.tmp
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/FedoraSearch.java.tmp	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/FedoraSearch.java.tmp	(revision 13928)
@@ -0,0 +1,302 @@
+package org.greenstone.gsdl3.service;
+
+// Greenstone classes
+import org.greenstone.gsdl3.util.*;
+
+//Fedora Web Services classes
+import fedora.client.utility.AutoFinder;
+import fedora.client.APIAStubFactory;
+import fedora.client.Downloader;
+import fedora.server.access.FedoraAPIA;
+import fedora.server.types.gen.FieldSearchQuery;
+import fedora.server.types.gen.FieldSearchResult;
+import fedora.server.types.gen.ListSession;
+import fedora.server.types.gen.ObjectFields;
+import fedora.server.types.gen.Condition;
+import fedora.server.types.gen.ComparisonOperator;
+
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.transform.Templates;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+
+// XML classes
+import org.w3c.dom.Element; 
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList; 
+
+//Java classes
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Properties;
+import java.io.File;
+import java.io.InputStream;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URLConnection;
+import java.net.URL;
+import java.net.Authenticator;
+import java.net.MalformedURLException;
+import java.lang.Object;
+
+
+/**
+ *
+ * @author <a href="mailto:chi@cs.waikato.ac.nz">Chi-Yu Huang</a>
+ * @version $Revision$
+ *
+ */
+
+public class FedoraSearch
+    extends AbstractSearch {
+    
+    // the services on offer
+    // these strings must match what is found in the properties file
+    protected static final String FIELD_PARAM = "fields";
+    
+    //Parameters connect to Proxy Server
+    private String proxyUser = null;
+    private String proxyPassword = null;
+    
+    private int maxResult, matchNum;
+    
+    protected String fedora_server_url = null;
+    
+    public FedoraSearch()
+    {
+    }
+    
+    //Configure FedoraSearch Service
+    public boolean configure(Element info, Element extra_info) 
+    { 
+	Element server_elem = (Element)GSXML.getChildByTagName(info, "fedoraServer");
+	if (server_elem == null) {
+	    System.err.println("FedoraSearch.configure error: no fedoraServer element found");
+	    return false;
+	}
+	fedora_server_url = server_elem.getAttribute("url");
+	System.err.println("Fedora Server:" + fedora_server_url);
+
+	if (fedora_server_url.equals("")) {
+	    System.err.println("FedoraSearch.configure error: no url for the fedoraServer element");
+	    return false;
+	}
+	Element tq_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	tq_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_QUERY);
+	tq_service.setAttribute(GSXML.NAME_ATT, TEXT_QUERY_SERVICE);
+	this.short_service_info.appendChild(tq_service);
+	//does_paging = true;
+	
+	// add some format info to service map if there is any
+	String path = GSPath.appendLink(GSXML.SEARCH_ELEM, GSXML.FORMAT_ELEM);
+	Element format = (Element) GSXML.getNodeByPath(extra_info, path);
+	if (format != null) {
+	    this.format_info_map.put(TEXT_QUERY_SERVICE, this.doc.importNode(format, true));
+	}
+	return true;
+    }
+    
+    /** Process a text query - implemented by concrete subclasses */
+    protected Element processTextQuery(Element request) {
+	// Create a new (empty) result message
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	result.setAttribute(GSXML.FROM_ATT, TEXT_QUERY_SERVICE);
+	result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+	
+	Element doc_node_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	result.appendChild(doc_node_list);
+	
+	Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	if (param_list == null) {
+	    System.err.println("FedoraSearch Error:: TextQuery request had no paramList.");
+	    return result;  // Return the empty result
+	}
+	
+	// Process the request parameters
+	HashMap params = GSXML.extractParams(param_list, false);
+	
+	// Make sure a query has been specified
+	String query = (String) params.get(QUERY_PARAM);
+	if (query == null || query.equals("")) {
+	    return result;  // Return the empty result
+	}
+	//Check Max number of Documents hit
+	String maxDocs = (String) params.get(MAXDOCS_PARAM);
+       	String hits_per_page = (String) params.get(HITS_PER_PAGE_PARAM);
+	
+	//Check the start_page number
+	String start_page = (String) params.get(START_PAGE_PARAM);	
+
+	// tidy whitespace
+	//query = query.replaceAll("\\s+", "+");
+	matchNum = 0;
+	maxResult = 20;
+
+	try {
+	    //Search Fedora Server
+	    String host = "toetoe";
+	    int port = 8200;
+	    String user = "fedoraAdmin";
+	    String pass = "fedoraAdmin";
+	    
+	    AutoFinder finder=new AutoFinder(host, port, user, pass);
+
+	    String[] fieldsArray = new String[] {"pid", "label", "fType", "bDef",
+						 "bMech", "cModel", "state", "ownerId", "cDate", "mDate",
+						 "dcmDate", "title", "creator", "subject", "description",
+						 "publisher", "contributor", "date", "type", "format",
+						 "identifier", "source", "language", "relation", "coverage",
+						 "rights"};
+	    
+	    String match_fields = join(fieldsArray, "|");
+	    
+	    FieldSearchQuery query_fedora=fedoraSearch(query, match_fields);
+	    
+            FieldSearchResult result_fedora = finder.findObjects(fieldsArray, maxResult, query_fedora);
+	    
+	    while (result_fedora != null) {
+		System.err.println("Search Result:" + result_fedora.getResultList().length);
+		for (int i=0; i<result_fedora.getResultList().length; i++) {
+		    ObjectFields o = result_fedora.getResultList()[i];
+		    matchNum++;
+		    String pid = o.getPid();
+		    String fedora_url = fedora_server_url +"/fedora/get/" + pid;
+		    String label = o.getLabel();
+		    String[] creator = o.getCreator();
+		    String[] subject = o.getSubject();
+		    String[] publisher = o.getPublisher();
+		    String[] contributor = o.getContributor();
+		    String[] title = o.getTitle();
+		    String[] description = o.getDescription();
+		    String[] format = o.getFormat();
+		    String[] identifier = o.getIdentifier();
+		    String[] source = o.getSource();
+		    String[] language = o.getLanguage();
+
+		    Element doc_node = this.doc.createElement(GSXML.DOC_NODE_ELEM);
+		    doc_node_list.appendChild(doc_node);
+		    
+		    Element metadata_list = this.doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
+		    doc_node.appendChild(metadata_list);
+		    
+		    if (fedora_url != null) {
+			GSXML.addMetadata(this.doc, metadata_list, "URL", fedora_url);
+		    }
+		    if (o.getDescription() != null) {
+			GSXML.addMetadata(this.doc, metadata_list, "Description", description[0]);
+		    }
+		    if (title[0] != null) {
+			GSXML.addMetadata(this.doc, metadata_list, "Title", title[0]);
+		    }
+		}
+		ListSession sess=result_fedora.getListSession();
+		if (sess!=null) {
+		    result_fedora = finder.resumeFindObjects(sess.getToken());
+		} else {
+		    result_fedora = null;
+		}
+	    }
+	} catch (Exception e) {
+	    System.err.println("ERROR: " + e.getClass().getName()
+			       + ((e.getMessage()==null) ? "" : ": " + e.getMessage()));
+	}
+    	
+	Element metadata_list = this.doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
+	result.appendChild(metadata_list);
+	
+	// Add a metadata element specifying the number of matching documents
+	//System.err.println("FedoraSearch Number of Documents:" + matchNum);
+	GSXML.addMetadata(this.doc, metadata_list, "numDocsMatched", ""+matchNum);
+	
+	return result;
+    }
+
+    protected FieldSearchQuery fedoraSearch(String query_terms, String matchFields) {
+
+	FieldSearchQuery fedora_query=new FieldSearchQuery();
+	try {
+	    // check if query contains any fields name (pid, label, fType....)
+	    if (query_terms.matches("^("+ matchFields+").+")){
+		System.err.println("Implementing Specific Query....");
+
+		List conditions=fedora.server.search.Condition.getConditions(query_terms);
+		
+		Condition[] cond=new Condition[conditions.size()];
+		for (int i=0; i<conditions.size(); i++) {
+		    fedora.server.search.Condition c = (fedora.server.search.Condition) conditions.get(i);
+		    try {
+			String operator = transOperator(c.getOperator().getAbbreviation());
+			cond[i] = new Condition();
+			cond[i].setProperty(c.getProperty());
+			cond[i].setOperator(ComparisonOperator.fromValue(operator));
+			cond[i].setValue(c.getValue());
+		    } catch (Exception e){
+			e.printStackTrace();
+		    }
+		}
+		fedora_query.setConditions(cond);
+	    } else {
+		System.err.println("Implementing Simple Query...");
+		fedora_query.setTerms(query_terms);
+	    }
+	} catch (Exception e){
+	    e.printStackTrace();
+	}
+	return fedora_query;
+    }
+    
+    protected void getIndexData(ArrayList index_ids, ArrayList index_names,String lang){
+       	index_ids.add("kw");
+	index_ids.add("au");	
+	index_ids.add("su");	
+	index_ids.add("ti");
+	index_ids.add("de");
+	index_ids.add("fu");
+	index_names.add(getTextString("param."+FIELD_PARAM+".kw", lang)); 
+	index_names.add(getTextString("param."+FIELD_PARAM+".au", lang));
+	index_names.add(getTextString("param."+FIELD_PARAM+".su", lang));
+	index_names.add(getTextString("param."+FIELD_PARAM+".ti", lang));
+	index_names.add(getTextString("param."+FIELD_PARAM+".de", lang));
+	index_names.add(getTextString("param."+FIELD_PARAM+".fu", lang));
+    }
+    
+    protected String getDocType (String node_id){
+	return node_id;
+    }
+    protected boolean hasChildren(String node_id){
+	return false;
+    }
+
+    protected boolean hasParent(String node_id){
+	return false;
+    }
+    private String transOperator(String operator){
+	String oper_char ="";
+	if (operator == "~") {
+	    oper_char = "has";
+	} else if (operator == "=") {
+	    oper_char = "eq";
+	} else if (operator == ">"){
+	    oper_char = "gt";
+	} else if (operator == ">="){
+	    oper_char = "ge";
+	} else if (operator == "<"){
+	    oper_char = "lt";
+   	} else if (operator == "<="){
+	    oper_char = "le";
+	}
+	return oper_char;
+    }
+    protected String join( String[] array, String delim ) {
+        String j = "";
+        for ( int i=0; i<array.length; i++ ) {
+            if (i!=0) j += delim;
+            j += array[i];
+        }
+        return j;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GS2Browse.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GS2Browse.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GS2Browse.java	(revision 13928)
@@ -0,0 +1,279 @@
+/*
+ *    GS2Browse.java
+ *    Copyright (C) 2005 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.service;
+
+// Greenstone classes
+import org.greenstone.gsdl3.util.OID;
+import org.greenstone.gsdl3.util.GSXML;
+import org.greenstone.gsdl3.util.GSFile;
+import org.greenstone.gsdl3.util.MacroResolver;
+import org.greenstone.gsdl3.util.GS2MacroResolver;
+import org.greenstone.gsdl3.util.GDBMWrapper;
+import org.greenstone.gsdl3.util.DBInfo;
+// XML classes
+import org.w3c.dom.Document;
+import org.w3c.dom.Element; 
+import org.w3c.dom.NodeList;
+
+// General Java classes
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+import java.util.Set;
+import java.util.Iterator;
+
+import org.apache.log4j.*;
+
+/** Greenstone 2 collection classifier service
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ * @author <a href="mailto:mdewsnip@cs.waikato.ac.nz">Michael Dewsnip</a>
+ */
+
+public class GS2Browse 
+    extends AbstractBrowse 
+{
+
+     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.GS2Browse.class.getName());
+
+    protected GDBMWrapper gdbm_src = null;
+
+    public GS2Browse() 
+    {
+	this.gdbm_src = new GDBMWrapper();
+	this.macro_resolver = new GS2MacroResolver(this.gdbm_src);
+    }
+
+    public void cleanUp() {
+	super.cleanUp();
+	this.gdbm_src.closeDatabase();
+    }
+
+    public boolean configure(Element info, Element extra_info)
+    {
+	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+
+	logger.info("Configuring GS2Browse...");
+	// the index stem is either specified in the config file or is  the collection name
+	Element index_stem_elem = (Element) GSXML.getChildByTagName(info, GSXML.INDEX_STEM_ELEM);
+	String index_stem = null;
+	if (index_stem_elem != null) {
+	    index_stem = index_stem_elem.getAttribute(GSXML.NAME_ATT);
+	}
+	if (index_stem == null || index_stem.equals("")) {
+	    index_stem = this.cluster_name;
+	}
+	
+	// Open GDBM database for querying
+	String gdbm_db_file = GSFile.GDBMDatabaseFile(this.site_home, this.cluster_name, index_stem);
+	if (!this.gdbm_src.openDatabase(gdbm_db_file, GDBMWrapper.READER)) {
+	    logger.error("Could not open GDBM database!");
+	    return false;
+	}
+	return true;
+    }
+
+    /** if id ends in .fc, .pc etc, then translate it to the correct id */
+    protected String translateId(String node_id) {
+	return this.gdbm_src.translateOID(node_id);
+    }
+
+    /** returns the document type of the doc that the specified node 
+	belongs to. should be one of 
+	GSXML.DOC_TYPE_SIMPLE, 
+	GSXML.DOC_TYPE_PAGED, 
+	GSXML.DOC_TYPE_HIERARCHY
+    */
+    protected String getDocType(String node_id) {
+	DBInfo info = this.gdbm_src.getInfo(node_id);
+	if (info == null) {
+	    return GSXML.DOC_TYPE_SIMPLE;
+	}
+	String doc_type = info.getInfo("doctype");
+	if (!doc_type.equals("")&&!doc_type.equals("doc")) {
+	    return doc_type;
+	}
+
+	String top_id = OID.getTop(node_id);
+	boolean is_top = (top_id.equals(node_id) ? true : false);
+	
+	String children = info.getInfo("contains");
+	boolean is_leaf = (children.equals("") ? true : false);
+
+	if (is_top && is_leaf) { // a single section document
+	    return GSXML.DOC_TYPE_SIMPLE;
+	}
+
+	// now we just check the top node
+	if (!is_top) { // we need to look at the top info
+	    info = this.gdbm_src.getInfo(top_id);
+	}
+	if (info == null) {
+	    return GSXML.DOC_TYPE_HIERARCHY;
+	}
+ 
+	String childtype = info.getInfo("childtype");
+	if (childtype.equals("Paged")) {
+	    return GSXML.DOC_TYPE_PAGED;
+	}
+	return GSXML.DOC_TYPE_HIERARCHY;
+
+    }
+
+    /** returns the id of the root node of the document containing node node_id. . may be the same as node_id */
+    protected String getRootId(String node_id) {
+	return OID.getTop(node_id);
+    }
+    /** returns a list of the child ids in order, null if no children */
+    protected ArrayList getChildrenIds(String node_id) {
+	DBInfo info = this.gdbm_src.getInfo(node_id);
+	if (info == null) {
+	    return null;
+	}
+
+	ArrayList children = new ArrayList();
+	
+	String contains = info.getInfo("contains");
+	StringTokenizer st = new StringTokenizer(contains, ";");
+	while (st.hasMoreTokens()) {
+	    String child_id = st.nextToken().replaceAll("\"", node_id);
+	    children.add(child_id);
+	}
+	return children;
+
+    }
+    /** returns the node id of the parent node, null if no parent */
+    protected String getParentId(String node_id){
+	String parent = OID.getParent(node_id);
+	if (parent.equals(node_id)) {
+	    return null;
+	}
+	return parent;
+    }
+
+    /** get the metadata for the classifier node node_id
+     * returns a metadataList element:
+     * <metadataList><metadata name="xxx">value</metadata></metadataList>
+     * if all_metadata is true, returns all available metadata, otherwise just
+     * returns requested metadata
+     */
+    // assumes only one value per metadata
+    protected Element getMetadataList(String node_id, boolean all_metadata, 
+				      ArrayList metadata_names) {
+	String lang = "en";
+	Element metadata_list = this.doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
+	DBInfo info = this.gdbm_src.getInfo(node_id);
+	if (info == null) {
+	    return null;
+	}
+	if (all_metadata) {
+	    // return everything out of the database
+	    Set keys = info.getKeys();
+	    Iterator it = keys.iterator();
+	    while(it.hasNext()) {
+		String key = (String)it.next();
+		String value = info.getInfo(key);
+		GSXML.addMetadata(this.doc, metadata_list, key, this.macro_resolver.resolve(value, lang, GS2MacroResolver.SCOPE_META, node_id));
+	    }
+	    
+	} else {
+	    for (int i=0; i<metadata_names.size(); i++) {
+		String meta_name = (String) metadata_names.get(i);
+		String value = (String)info.getInfo(meta_name);
+		GSXML.addMetadata(this.doc, metadata_list, meta_name, value);
+	    }
+	}
+	return metadata_list;
+    }
+
+    /** returns the structural information asked for.
+     * info_type may be one of
+     * INFO_NUM_SIBS, INFO_NUM_CHILDREN, INFO_SIB_POS
+     */
+    protected String getStructureInfo(String doc_id, String info_type) {
+	String value="";
+	if (info_type.equals(INFO_NUM_SIBS)) {
+	    String parent_id = OID.getParent(doc_id);
+	    if (parent_id.equals(doc_id)) {
+		value="0";
+	    } else {
+		value = String.valueOf(getNumChildren(parent_id));
+	    }
+	    return value;
+	}
+	
+	if (info_type.equals(INFO_NUM_CHILDREN)) {
+	    return String.valueOf(getNumChildren(doc_id));
+	}
+
+	
+	if (info_type.equals(INFO_SIB_POS)) {
+	    String parent_id = OID.getParent(doc_id);
+	    if (parent_id.equals(doc_id)) {
+		return "-1";
+	    }
+	    
+	    DBInfo info = this.gdbm_src.getInfo(parent_id);
+	    if (info==null) {
+		return "-1";
+	    }
+	    
+	    String contains = info.getInfo("contains");
+	    contains = contains.replaceAll("\"", parent_id);
+	    String [] children = contains.split(";");
+	    for (int i=0;i<children.length;i++) {
+		String child_id = children[i];
+		if (child_id.equals(doc_id)) {
+		    return String.valueOf(i+1); // make it from 1 to length
+			   
+		}
+	    }
+	    
+	    return "-1";
+	} else {
+	    return null;
+	}
+
+    }
+
+    protected int getNumChildren(String node_id) {
+	DBInfo info = this.gdbm_src.getInfo(node_id);
+	if (info == null) {
+	    return 0;
+	}
+	String contains = info.getInfo("contains");
+	if (contains.equals("")) {
+	    return 0;
+	}
+	String [] children = contains.split(";");
+	return children.length;
+    }
+    
+    /** returns true if the id refers to a document (rather than 
+     * a classifier node)
+     */
+    protected boolean isDocumentId(String node_id){
+	if (node_id.startsWith("CL")) {
+	    return false;
+	}
+	return true;
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GS2Construct.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GS2Construct.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GS2Construct.java	(revision 13928)
@@ -0,0 +1,572 @@
+/*
+ *    GS2Construct.java 
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.service;
+
+import org.greenstone.gsdl3.util.*;
+import org.greenstone.gsdl3.build.*;
+
+import org.w3c.dom.Document; 
+import org.w3c.dom.Node; 
+import org.w3c.dom.Text; 
+import org.w3c.dom.Element; 
+import org.w3c.dom.NodeList; 
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
+import java.io.File;
+import java.util.Locale;
+
+import org.apache.log4j.*;
+
+/**
+ * A Services class for building collections
+ * provides a wrapper around the old perl scripts
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ * @version $Revision$
+ */
+public class GS2Construct 
+    extends ServiceRack { 
+    
+     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.GS2Construct.class.getName()); 
+
+    // services offered
+    private static final String NEW_SERVICE = "NewCollection";
+    private static final String ADD_DOC_SERVICE = "AddDocument";
+    private static final String IMPORT_SERVICE = "ImportCollection";
+    private static final String BUILD_SERVICE = "BuildCollection";
+    private static final String ACTIVATE_SERVICE = "ActivateCollection";
+    private static final String DELETE_SERVICE = "DeleteCollection";
+    private static final String RELOAD_SERVICE = "ReloadCollection";
+
+    // params used
+    private static final String COL_PARAM = "collection";
+    private static final String NEW_COL_TITLE_PARAM = "collTitle";
+    private static final String NEW_COL_ABOUT_PARAM = "collAbout";
+    private static final String CREATOR_PARAM = "creator";
+    private static final String NEW_FILE_PARAM = "newfile";
+    private static final String PROCESS_ID_PARAM = GSParams.PROCESS_ID;
+    private static final String BUILDTYPE_PARAM = "buildType";
+    private static final String BUILDTYPE_MG = "mg";
+    private static final String BUILDTYPE_MGPP = "mgpp";
+    
+    // the list of the collections - store between some method calls
+    private String[] collection_list = null;
+
+    // set of listeners for any construction commands
+    protected Map listeners = null;
+    
+    public GS2Construct() {
+	this.listeners = Collections.synchronizedMap(new HashMap());
+	
+    }
+
+    /** returns a specific service description */
+    protected Element getServiceDescription(String service, String lang, String subset) {
+
+	Element description = this.doc.createElement(GSXML.SERVICE_ELEM);
+	description.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
+	description.setAttribute(GSXML.NAME_ATT, service);
+	if (subset == null || subset.equals(GSXML.DISPLAY_TEXT_ELEM+GSXML.LIST_MODIFIER)) {
+	    description.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_NAME,  getTextString(service+".name", lang)));
+	    description.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_DESCRIPTION,  getTextString(service+".description", lang)));
+	    description.appendChild(GSXML.createDisplayTextElement(this.doc,  GSXML.DISPLAY_TEXT_SUBMIT, getTextString(service+".submit", lang)));
+	}
+	if (subset == null || subset.equals(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER)) {
+	    Element param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	    description.appendChild(param_list);
+	    
+	    if (service.equals(NEW_SERVICE)) {
+		
+		Element param = GSXML.createParameterDescription(this.doc, NEW_COL_TITLE_PARAM, getTextString("param."+NEW_COL_TITLE_PARAM, lang), GSXML.PARAM_TYPE_STRING, null, null, null);
+		param_list.appendChild(param);
+		param = GSXML.createParameterDescription(this.doc, CREATOR_PARAM, getTextString("param."+CREATOR_PARAM, lang), GSXML.PARAM_TYPE_STRING, null, null, null);
+		param_list.appendChild(param);
+		param = GSXML.createParameterDescription(this.doc, NEW_COL_ABOUT_PARAM, getTextString("param."+NEW_COL_ABOUT_PARAM, lang), GSXML.PARAM_TYPE_TEXT, null, null, null);
+		param_list.appendChild(param);
+		String[] types = {BUILDTYPE_MGPP, BUILDTYPE_MG};
+		String[] type_texts = {getTextString("param."+BUILDTYPE_PARAM+"."+BUILDTYPE_MGPP, lang), getTextString("param."+BUILDTYPE_PARAM+"."+BUILDTYPE_MG, lang)};
+		
+		param = GSXML.createParameterDescription(this.doc, BUILDTYPE_PARAM, getTextString("param."+BUILDTYPE_PARAM, lang), GSXML.PARAM_TYPE_ENUM_SINGLE, BUILDTYPE_MGPP, types, type_texts);
+		param_list.appendChild(param);
+	    }
+	    else if (service.equals(ACTIVATE_SERVICE) || service.equals(IMPORT_SERVICE) || service.equals(BUILD_SERVICE) || service.equals(RELOAD_SERVICE) || service.equals(DELETE_SERVICE)) {
+	    
+		this.collection_list = getCollectionList();
+		Element param = GSXML.createParameterDescription(this.doc, COL_PARAM, getTextString("param."+COL_PARAM, lang), GSXML.PARAM_TYPE_ENUM_SINGLE, null, this.collection_list, this.collection_list);	
+		param_list.appendChild(param);
+	    } else {
+		// invalid service name
+		return null;
+	    }
+	}
+	return description;
+    }
+
+    // each service must have a method "process<New service name>"
+
+    protected Element processNewCollection(Element request) {
+	return runCommand(request, GS2PerlConstructor.NEW);	
+    }
+    
+    /** TODO:implement this */
+    protected Element processAddDocument(Element request) {
+	// decode the file name, add it to the import directory
+	String name = GSPath.getFirstLink(request.getAttribute(GSXML.TO_ATT));
+	Element response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	response.setAttribute(GSXML.FROM_ATT, name);
+	Element status = this.doc.createElement(GSXML.STATUS_ELEM);
+	response.appendChild(status);
+	//String lang = request.getAttribute(GSXML.LANG_ATT);
+	//String request_type = request.getAttribute(GSXML.TYPE_ATT);
+	Text t = this.doc.createTextNode("AddDocument: not implemented yet");
+	status.appendChild(t);
+	status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
+	return response;
+    }
+    protected Element processImportCollection(Element request) {
+	return runCommand(request, GS2PerlConstructor.IMPORT);
+    }
+
+    protected Element processBuildCollection(Element request) {
+	return runCommand(request, GS2PerlConstructor.BUILD);
+    }
+    protected Element processActivateCollection(Element request) {
+	Element response = runCommand(request, GS2PerlConstructor.ACTIVATE);
+	// this activates the collection on disk. but now we need to tell
+	// the MR about it. but we have to wait until the process is finished.
+	Element status = (Element)GSXML.getChildByTagName(response, GSXML.STATUS_ELEM);
+	Element param_list = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	HashMap params = GSXML.extractParams(param_list, false);
+	String coll_name = (String) params.get(COL_PARAM);
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	// check for finished
+	int status_code = Integer.parseInt(status.getAttribute(GSXML.STATUS_ERROR_CODE_ATT));
+	if (GSStatus.isCompleted(status_code) && 
+	    GSStatus.isError(status_code)) {
+	    // we shouldn't carry out the next bit, just return the response
+	    return response;
+	}
+	String id = status.getAttribute(GSXML.STATUS_PROCESS_ID_ATT);
+	GS2PerlListener listener = (GS2PerlListener)this.listeners.get(id);
+	if (listener==null) {
+	    logger.error("somethings gone wrong, couldn't find the listener");
+	    status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
+	    return response;
+	}
+	while (!GSStatus.isCompleted(status_code)) {
+	    // wait for the process, and keep checking the status code
+	    // there is probably a better way to do this.
+	    try {
+		Thread.currentThread().sleep(100);
+	    } catch (Exception e) { // ignore
+	    }
+	    status_code = listener.getStatus();
+	}
+	
+	// add the rest of the messages to the status node
+	Text t = this.doc.createTextNode("\n"+listener.getUpdate());
+	status.appendChild(t);
+	status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(listener.getStatus()));
+	if (GSStatus.isError(status_code)) {
+	    return response; // without doing the next bit
+	}
+
+	t = this.doc.createTextNode("\n");
+	status.appendChild(t);
+	// once have got here, we assume
+	// the first bit proceeded successfully, now reload the collection
+	systemRequest("reload", coll_name, status, lang); // this will append more messages to the status, and overwrite the error code att
+	return response;
+	
+    }
+    protected Element processDeleteCollection(Element request) {
+
+	// the response to send back
+	String name = GSPath.getFirstLink(request.getAttribute(GSXML.TO_ATT));
+	Element response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	response.setAttribute(GSXML.FROM_ATT, name);
+	Element status = this.doc.createElement(GSXML.STATUS_ELEM);
+	response.appendChild(status);
+	Text t = null; // the text node for the error/success message
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	String request_type = request.getAttribute(GSXML.TYPE_ATT);
+	
+	Element param_list = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	HashMap params = GSXML.extractParams(param_list, false);
+	
+	boolean get_status_only = false;
+	if (request_type.equals(GSXML.REQUEST_TYPE_STATUS)) {
+	    get_status_only = true;
+	}
+	if (get_status_only) {
+	    // at the moment, delete is synchronous. but it may take ages so should do the command in another thread maybe? in which case we will want to ask for status
+	    logger.error("had a status request for delete - this shouldn't happen!!");
+	    //t = this.doc.createTextNode("");
+	    //status.appendChild(t);
+	    status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
+	    return response;
+	}
+	String coll_name = (String)params.get(COL_PARAM);	
+	String[] args={coll_name};
+	File coll_dir = new File(GSFile.collectionBaseDir(this.site_home, coll_name));
+	// check that the coll is there in the first place
+	if (!coll_dir.exists()) {
+	    t = this.doc.createTextNode(getTextString("delete.exists_error", lang, args));
+	    status.appendChild(t);
+	    status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
+	    return response;
+	}
+		
+	// try to delete the directory
+	if (!GSFile.deleteFile(coll_dir)) {
+	    t = this.doc.createTextNode(getTextString("delete.delete_error", lang, args));
+	    status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
+	    status.appendChild(t);
+	    return response;
+	}
+	systemRequest("delete", coll_name, status, lang);
+	return response;
+    }
+
+    protected Element processReloadCollection(Element request) {
+
+	// the response to send back
+	String name = GSPath.getFirstLink(request.getAttribute(GSXML.TO_ATT));
+	Element response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	response.setAttribute(GSXML.FROM_ATT, name);
+	Element status = this.doc.createElement(GSXML.STATUS_ELEM);
+	response.appendChild(status);
+	Text t = null; // the text node for the error/success message
+	
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	String request_type = request.getAttribute(GSXML.TYPE_ATT);
+	
+	Element param_list = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	HashMap params = GSXML.extractParams(param_list, false);
+	
+	boolean get_status_only = false;
+	if (request_type.equals(GSXML.REQUEST_TYPE_STATUS)) {
+	    get_status_only = true;
+	}
+	if (get_status_only) {
+	    // reload is synchronous - this makes no sense
+	    logger.error("had a status request for reload - this shouldn't happen!!");
+	    //t = this.doc.createTextNode("");
+	    //status.appendChild(t);
+	    status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
+	    return response;
+	}
+	
+	String coll_name = (String)params.get(COL_PARAM);
+	systemRequest("reload", coll_name, status, lang);
+	return response;	
+	
+    }
+
+    /** send a configure request to the message router 
+     * action name should be "delete" or "reload"
+     * response will be put into the status element
+     */
+    protected void systemRequest(String action_name, String coll_name, Element status, String lang) {
+	
+	// send the request to the MR
+	Element message = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	Element request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_SYSTEM, "", lang, "");
+	message.appendChild(request);
+	Element command = this.doc.createElement(GSXML.SYSTEM_ELEM);
+	request.appendChild(command);
+	command.setAttribute(GSXML.SYSTEM_MODULE_TYPE_ATT, GSXML.COLLECTION_ELEM);
+	command.setAttribute(GSXML.SYSTEM_MODULE_NAME_ATT, coll_name);
+
+	if (action_name.equals("delete")) {
+	    command.setAttribute(GSXML.TYPE_ATT, GSXML.SYSTEM_TYPE_DEACTIVATE);
+	} else if (action_name.equals("reload")) {
+	    command.setAttribute(GSXML.TYPE_ATT, GSXML.SYSTEM_TYPE_ACTIVATE);
+	} else {
+	    logger.error("invalid action name passed to systemRequest:"+action_name);
+	    return;
+	}
+	request.appendChild(command);
+	Element response = this.router.process(message); // at the moment, get no info in response so ignore it
+	Text t;
+	String[] args={coll_name};
+	    
+	if (response == null) {
+	    t = this.doc.createTextNode(getTextString(action_name+".configure_error", lang, args));
+	    status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
+	    status.appendChild(t);
+	    return;
+	}
+	    
+	// if we got here, we have succeeded!
+	t = this.doc.createTextNode(getTextString(action_name+".success", lang, args));
+	status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.SUCCESS));
+	status.appendChild(t);
+    }
+
+
+    /** configure the service module
+     * for now, all services have type=build - need to think about this
+     */
+    public boolean configure(Element info, Element extra_info) {
+	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+
+	logger.info("configuring GS2Construct");
+
+	Element e = null;
+	// hard code in the services for now
+
+	// set up short_service_info_ - for now just has name and type
+
+	e = this.doc.createElement(GSXML.SERVICE_ELEM);
+	e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
+	e.setAttribute(GSXML.NAME_ATT, NEW_SERVICE);
+	this.short_service_info.appendChild(e);
+
+	e = this.doc.createElement(GSXML.SERVICE_ELEM);
+	e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
+	e.setAttribute(GSXML.NAME_ATT, IMPORT_SERVICE);
+	this.short_service_info.appendChild(e);
+
+	e = this.doc.createElement(GSXML.SERVICE_ELEM);
+	e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
+	e.setAttribute(GSXML.NAME_ATT, BUILD_SERVICE);
+	this.short_service_info.appendChild(e);
+
+	e = this.doc.createElement(GSXML.SERVICE_ELEM);
+	e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
+	e.setAttribute(GSXML.NAME_ATT, ACTIVATE_SERVICE);
+	this.short_service_info.appendChild(e);
+
+	e = this.doc.createElement(GSXML.SERVICE_ELEM);
+	e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
+	e.setAttribute(GSXML.NAME_ATT, DELETE_SERVICE);
+	this.short_service_info.appendChild(e);
+
+	e = this.doc.createElement(GSXML.SERVICE_ELEM);
+	e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
+	e.setAttribute(GSXML.NAME_ATT, RELOAD_SERVICE);
+	this.short_service_info.appendChild(e);
+
+	//e = this.doc.createElement(GSXML.SERVICE_ELEM);
+	//e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
+	//e.setAttribute(GSXML.NAME_ATT, ADD_DOC_SERVICE);
+	//this.short_service_info.appendChild(e);
+
+
+	return true;
+    }
+
+    /** returns a response element */
+    protected Element runCommand(Element request, int type ) {
+	
+	// the response to send back
+	String name = GSPath.getFirstLink(request.getAttribute(GSXML.TO_ATT));
+	Element response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	response.setAttribute(GSXML.FROM_ATT, name);
+	Element status = this.doc.createElement(GSXML.STATUS_ELEM);
+	response.appendChild(status);
+
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	String request_type = request.getAttribute(GSXML.TYPE_ATT);
+
+	Element param_list = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	HashMap params = GSXML.extractParams(param_list, false);
+
+	boolean get_status_only = false;
+	if (request_type.equals(GSXML.REQUEST_TYPE_STATUS)) {
+	    get_status_only = true;
+	}
+	
+	// just check for status messages if that's all that's required
+	if (get_status_only) {
+	    String id = (String)params.get(PROCESS_ID_PARAM);
+	    status.setAttribute(GSXML.STATUS_PROCESS_ID_ATT, id);
+	    GS2PerlListener listener = (GS2PerlListener)this.listeners.get(id);
+	    if (listener==null) {
+		Text t = this.doc.createTextNode(getTextString("general.process_id_error", lang));
+		status.appendChild(t);
+		status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
+	    } else {
+		Text t = this.doc.createTextNode(listener.getUpdate());
+		status.appendChild(t);
+		status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(listener.getStatus()));
+		// check that we actually should be removing the listener here
+		if (listener.isFinished()) { // remove this listener - its job is done
+		    this.listeners.remove(id); // not working
+		}
+	    }
+	    return response;
+
+	}
+
+	// do teh actual command
+	String coll_name=null;
+	if (type==GS2PerlConstructor.NEW) {
+	    String coll_title = (String)params.get(NEW_COL_TITLE_PARAM);
+	    coll_name = createNewCollName(coll_title);
+	} else {
+	    coll_name = (String)params.get(COL_PARAM);
+	}
+	logger.error("Coll name = "+coll_name);
+	// makes a paramList of the relevant params
+	Element other_params = extractOtherParams(params, type);
+
+	//create the constructor to do the work
+
+	GS2PerlConstructor constructor = new GS2PerlConstructor("perl_build");
+	if (!constructor.configure()) {
+	    Text t = this.doc.createTextNode(getTextString("general.configure_constructor_error", lang));
+	    status.appendChild(t);
+	    status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
+	    return response;
+	}
+		
+	constructor.setSiteHome(this.site_home);
+	constructor.setCollectionName(coll_name);
+	constructor.setActionType(type);
+	constructor.setProcessParams(other_params);
+	// the listener
+	GS2PerlListener listener = new GS2PerlListener();
+	constructor.addListener(listener);
+	constructor.start();
+
+	String id = newID();
+	this.listeners.put(id, listener);
+
+	status.setAttribute(GSXML.STATUS_PROCESS_ID_ATT, id);
+	status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ACCEPTED));
+	Text t = this.doc.createTextNode(getTextString("general.process_start", lang));
+	status.appendChild(t);
+	return response;
+
+    }
+
+
+    //************************
+    // some helper functions
+    //************************
+
+    /** parse the collect directory and return a list of collection names */
+    protected String[] getCollectionList() {
+	
+	File collectDir = new File(GSFile.collectDir(this.site_home));
+	if (!collectDir.exists()) {
+	    logger.error("couldn't find collect dir: "+collectDir.toString());
+	    return null;
+	}
+	logger.info("GS2Construct: reading thru directory "+collectDir.getPath()+" to find collections.");
+	File[] contents = collectDir.listFiles();
+	int num_colls=0;
+	for (int i=0; i<contents.length;i++) {
+	    if(contents[i].isDirectory() && !contents[i].getName().startsWith("CVS")) {
+		num_colls ++;
+	    }
+	}
+	
+	String[] names= new String[num_colls];
+	
+	for (int i=0, j=0; i<contents.length;i++) {
+	    if(contents[i].isDirectory()) {
+		String colName = contents[i].getName();
+		if (!colName.startsWith("CVS")) {
+		    names[j] = colName;
+		    j++;
+		}
+		
+	    } 
+	}
+	
+	return names;
+	
+    }
+   
+    /** ids used for process id */
+    private int current_id = 0;
+    private String newID() {
+	current_id++;
+	return Integer.toString(current_id);
+    }
+
+    /** creates a new short name from the collection title */
+    protected String createNewCollName(String coll_title) {
+
+	String base_name = null;
+	// take the first 6 letters
+	if (coll_title.length()<6) {
+	    base_name = coll_title;
+	} else {
+	    base_name = coll_title.substring(0,6);
+	}
+	File coll_dir = new File(GSFile.collectionBaseDir(this.site_home, base_name));
+	if (!coll_dir.exists()) { // this name is ok - not used yet
+	    return base_name;
+	}
+	
+	// now we have to make a new name until we get a good one
+	// try name1, name2 name3 etc
+	int i=0;
+	while(coll_dir.exists()) {
+	    i++;
+	    coll_dir = new File(GSFile.collectionBaseDir(this.site_home, base_name+Integer.toString(i)));
+	}
+	return base_name+Integer.toString(i);
+	
+    }
+
+    /** takes the params from the request (in the HashMap) and extracts any
+     * that need to be passed to the constructor and puts them into a 
+     * paramList element */
+    protected Element extractOtherParams(HashMap params, int type) {
+
+	Element param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	if (type == GS2PerlConstructor.NEW) {
+	    Element param = this.doc.createElement(GSXML.PARAM_ELEM);
+	    param.setAttribute(GSXML.NAME_ATT, "creator");
+	    param.setAttribute(GSXML.VALUE_ATT, (String)params.get(CREATOR_PARAM));
+	    
+	    param_list.appendChild(param);
+	    param = this.doc.createElement(GSXML.PARAM_ELEM);
+	    param.setAttribute(GSXML.NAME_ATT, "about");
+	    param.setAttribute(GSXML.VALUE_ATT, (String)params.get(NEW_COL_ABOUT_PARAM));
+	    param_list.appendChild(param);
+	    param = this.doc.createElement(GSXML.PARAM_ELEM);
+	    param.setAttribute(GSXML.NAME_ATT, "title");
+	    param.setAttribute(GSXML.VALUE_ATT, (String)params.get(NEW_COL_TITLE_PARAM));
+	    param_list.appendChild(param);
+	    param = this.doc.createElement(GSXML.PARAM_ELEM);
+	    param.setAttribute(GSXML.NAME_ATT, "buildtype");
+	    param.setAttribute(GSXML.VALUE_ATT, (String)params.get(BUILDTYPE_PARAM));
+	    param_list.appendChild(param);
+	    return param_list;
+	}
+
+	// other ones dont have params yet
+	return null;
+    }
+	
+}
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GS2LuceneRetrieve.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GS2LuceneRetrieve.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GS2LuceneRetrieve.java	(revision 13928)
@@ -0,0 +1,158 @@
+/*
+ *    GS2LuceneRetrieve.java
+ *    Copyright (C) 2005 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.service;
+
+// Greenstone classes
+import org.greenstone.gsdl3.core.GSException;
+import org.greenstone.gsdl3.util.GSFile;
+import org.greenstone.gsdl3.util.GSXML;
+import org.greenstone.gsdl3.util.GDBMWrapper;
+import org.greenstone.gsdl3.util.DBInfo;
+import org.greenstone.gsdl3.util.GSHTML;
+import org.greenstone.gsdl3.util.OID;
+// XML classes
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Text;
+
+// General Java classes
+import java.io.File;
+
+import org.apache.log4j.Logger;
+
+/** Retrieve documents from a gs2 lucene collection. Note that this doesn't 
+    actually use lucene, as the documents are stored in XML files */
+public class GS2LuceneRetrieve
+    extends AbstractGS2DocumentRetrieve
+{
+    
+    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.GS2LuceneRetrieve.class.getName());
+    
+    
+    protected static final String DOC_LEVEL="Doc";
+    protected static final String SEC_LEVEL="Sec";
+    protected static final String ID_ATT = "gs2:id";
+
+    // Parameters used
+    private static final String LEVEL_PARAM = "level";
+    
+    // Elements used in the config file that are specific to this class
+    private static final String DEFAULT_LEVEL_ELEM = "defaultLevel";
+    
+    private String default_level = null;
+    private String text_dir = null;
+
+    private boolean text_available = true;
+    
+    public GS2LuceneRetrieve() {
+    }
+    
+    public void cleanUp() {
+	super.cleanUp();
+    }
+    
+    /** configure this service */
+    public boolean configure(Element info, Element extra_info)
+    {
+	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+	
+	// Do specific configuration
+	logger.info("Configuring GS2LuceneRetrieve...");
+	
+	text_dir = GSFile.collectionIndexDir(this.site_home, this.cluster_name) + File.separatorChar+"text"+File.separatorChar;
+	if (!(new File(text_dir).isDirectory())) {
+	    logger.error("Text directory "+text_dir+" does not exist, will be unable to retrieve text for "+cluster_name);
+	    text_available = false;
+	    return true; // return true so that we still get the other services for the collection
+	}
+	// Get the default level out of <defaultLevel> (buildConfig.xml)
+ 	Element def = (Element) GSXML.getChildByTagName(info, DEFAULT_LEVEL_ELEM);
+ 	if (def != null) {
+	    this.default_level = def.getAttribute(GSXML.SHORTNAME_ATT);
+	}
+	if (this.default_level == null || this.default_level.equals("")) {
+	    logger.error("Default level not specified for "+this.cluster_name+", assuming "+DOC_LEVEL);
+	    this.default_level = DOC_LEVEL;
+ 	}
+	
+	return true;
+	
+    }
+    
+    /** returns the content of a node
+     * should return a nodeContent element:
+     * <nodeContent>text content or other elements</nodeContent>
+     */
+    protected Element getNodeContent(String doc_id, String lang) throws GSException {	
+	String doc_content = getTextString("TextRetrievalError", lang);
+	try {
+	    if (!text_available) {
+		throw new Exception("No text directory available");
+	    }
+	    
+	    long doc_num = this.gdbm_src.OID2Docnum(doc_id);
+	    if (doc_num == -1) {
+		throw new Exception("OID "+doc_id +" couldn't be converted to lucene doc num");
+	    }
+	
+	    DBInfo info=this.gdbm_src.getInfo(OID.getTop(doc_id));
+	    if (info == null) {
+		throw new Exception("Couldn't get GDBM database entry for "+OID.getTop(doc_id));
+	    }
+	    
+	    String archivedir=info.getInfo("archivedir");
+	    File doc_xml_file = new File(text_dir+archivedir+File.separatorChar+"doc.xml");
+	    if (!doc_xml_file.isFile()) {
+		throw new Exception("Doc XML file "+doc_xml_file.getPath()+" does not exist");
+	    }
+	    Document doc_xml_doc = this.converter.getDOM(doc_xml_file);
+	    if (doc_xml_doc == null) {
+		throw new Exception("Couldn't parse file "+doc_xml_file.getPath());
+	    }
+	    Element full_document = doc_xml_doc.getDocumentElement();
+	    if (full_document == null) {
+		throw new Exception("Couldn't parse file "+doc_xml_file.getPath());
+	    }
+	    Element current_section = null;
+	    if (default_level.equals(DOC_LEVEL)) {
+		current_section = full_document;
+	    } else {
+		current_section = GSXML.getNamedElement(full_document, SEC_LEVEL, ID_ATT, String.valueOf(doc_num));
+	    }
+	    if (current_section == null) {
+		throw new Exception("Couldn't find section "+ doc_num+" in file "+doc_xml_file.getPath());
+	    }
+	    doc_content = GSXML.getNodeText(current_section);
+	    if (doc_content == null) {
+		doc_content = "";
+	    } else {
+ 		doc_content = resolveTextMacros(doc_content, doc_id, lang);
+ 	    } 
+	} catch (Exception e) {
+	    logger.error("Error trying to get document text for "+doc_id+" in collection "+this.cluster_name+": "+e);
+	}
+	
+	Element content_node = this.doc.createElement(GSXML.NODE_CONTENT_ELEM);
+	Text t = this.doc.createTextNode(doc_content);
+	content_node.appendChild(t);
+	return content_node;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GS2LuceneSearch.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GS2LuceneSearch.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GS2LuceneSearch.java	(revision 13928)
@@ -0,0 +1,273 @@
+/*
+ *    GS2LuceneSearch.java
+ *    Copyright (C) 2006 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *   the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.greenstone.gsdl3.service;
+
+// Greenstone classes
+import org.greenstone.gsdl3.util.*;
+
+// XML classes
+import org.w3c.dom.Element; 
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Document; 
+// java classes
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.io.File;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.Map;
+import java.util.Vector;
+
+// Logging
+import org.apache.log4j.Logger;
+
+import org.greenstone.LuceneWrapper.GS2LuceneQuery;
+import org.greenstone.LuceneWrapper.LuceneQueryResult;
+
+public class GS2LuceneSearch
+    extends AbstractGS2FieldSearch
+{
+    protected static final String RANK_PARAM_RANK_VALUE = "rank";
+
+    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.GS2LuceneSearch.class.getName());
+
+    private GS2LuceneQuery lucene_src=null;    
+    
+    public GS2LuceneSearch()
+    {
+	this.lucene_src = new GS2LuceneQuery();
+	// Lucene uses double operators, not single
+	AND_OPERATOR = "&&";
+	OR_OPERATOR = "||";
+
+	does_paging = true;
+	does_chunking = true;
+    }
+    
+    public void cleanUp() {
+	super.cleanUp();
+	this.lucene_src.cleanUp();
+    }
+    
+    /** configure this service */
+    public boolean configure(Element info, Element extra_info)
+    {
+	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+	
+	// Lucene doesn't do case folding or stemming or accent folding at the 
+	// moment
+	does_case = false;
+	does_stem = false;
+	does_accent = false;
+
+	return true;
+    }
+    
+    /** add in the lucene specific params to TextQuery */
+    protected void addCustomQueryParams(Element param_list, String lang) 
+    {
+	super.addCustomQueryParams(param_list, lang);
+	/** lucenes rank param is based on index fields, not ranked/not */
+	createParameter(RANK_PARAM, param_list, lang);
+    }
+    
+    /** create a param and add to the list */
+    /** we override this to do a special rank param */
+    protected void createParameter(String name, Element param_list, String lang) 
+    {
+	Element param = null;
+	if (name.equals(RANK_PARAM)) {
+	    // get the fields
+	    ArrayList fields = new ArrayList();
+	    fields.add(RANK_PARAM_RANK_VALUE);
+	    ArrayList field_names = new ArrayList();
+	    field_names.add(getTextString("param.sortBy.rank", lang)); 
+	    getSortByIndexData(fields, field_names, lang);
+	    
+	    param = GSXML.createParameterDescription2(this.doc, name, getTextString("param."+name, lang), GSXML.PARAM_TYPE_ENUM_SINGLE, (String)fields.get(0), fields, field_names );
+	}
+	if (param != null) {
+	    param_list.appendChild(param);
+	} else {
+	    super.createParameter(name, param_list, lang);
+	}
+    }
+    
+    protected void getSortByIndexData(ArrayList index_ids, ArrayList index_names, String lang) {
+	// the index info -
+	Element index_list = (Element)GSXML.getChildByTagName(this.config_info, INDEX_ELEM+GSXML.LIST_MODIFIER);
+	NodeList indexes = index_list.getElementsByTagName(INDEX_ELEM);
+	int len = indexes.getLength();
+	// now add even if there is only one
+	for (int i=0; i<len; i++) {
+	    Element index = (Element)indexes.item(i);
+	    String shortname = index.getAttribute(GSXML.SHORTNAME_ATT);
+	    if (shortname.equals("") || shortname.equals("ZZ") || shortname.equals("TX")) {
+		continue;
+	    }
+	    index_ids.add("by"+shortname);
+	    String display_name = GSXML.getDisplayText(index, GSXML.DISPLAY_TEXT_NAME, lang, "en");
+	    if (display_name.equals("")) {
+		display_name = index.getAttribute(GSXML.NAME_ATT);
+		if (display_name.equals("")) {
+		    display_name = shortname;
+		}
+	    }
+	    index_names.add(display_name);
+		
+	}
+	
+    }
+
+    /** methods to handle actually doing the query */
+
+    /** do any initialisation of the query object */
+    protected boolean setUpQueryer(HashMap params) {
+       	String indexdir = GSFile.collectionBaseDir(this.site_home, this.cluster_name) + File.separatorChar + "index"+File.separatorChar;
+	
+	String index = "didx";
+	int maxdocs = 100;
+	int hits_per_page = 20;
+	int start_page = 1;
+	// set up the query params
+    	Set entries = params.entrySet();
+    	Iterator i = entries.iterator();
+    	while (i.hasNext()) {
+    	    Map.Entry m = (Map.Entry)i.next();
+    	    String name = (String)m.getKey();
+    	    String value = (String)m.getValue();
+    	    
+    	    if (name.equals(MAXDOCS_PARAM)&& !value.equals("")) {
+		maxdocs = Integer.parseInt(value);
+	    } else if (name.equals(HITS_PER_PAGE_PARAM)) {
+		hits_per_page = Integer.parseInt(value);
+	    } else if (name.equals(START_PAGE_PARAM)) {
+		start_page = Integer.parseInt(value);
+		
+    	    } else if (name.equals(MATCH_PARAM)) {
+    		if (value.equals(MATCH_PARAM_ALL)) {
+		    this.lucene_src.setDefaultConjunctionOperator("AND");
+    		} else{
+		    this.lucene_src.setDefaultConjunctionOperator("OR");
+    		}
+    	    } else if (name.equals(RANK_PARAM)) {
+		if (value.equals(RANK_PARAM_RANK_VALUE)) {
+		    value = null;
+		}
+		this.lucene_src.setSortField(value);
+    	    } else if (name.equals(LEVEL_PARAM)) {
+		if (value.toUpperCase().equals("SEC")){
+		    index = "sidx";
+		}
+		else {
+		    index = "didx";
+		}
+	    } // ignore any others
+    	}
+	// set up start and end results if necessary
+	int start_results = 1;
+	if (start_page != 1) {
+	    start_results = ((start_page-1) * hits_per_page) + 1;
+	}
+	int end_results = hits_per_page * start_page;
+	this.lucene_src.setStartResults(start_results);
+	this.lucene_src.setEndResults(end_results);
+	
+	this.lucene_src.setIndexDir(indexdir+index);
+	this.lucene_src.initialise();
+	return true;
+    }
+    /** do the query */
+    protected Object runQuery(String query) {
+	try {
+	    LuceneQueryResult lqr=this.lucene_src.runQuery(query);
+	    return lqr;
+	} catch (Exception e) {
+	    logger.error ("exception happened in run query: ", e);
+	}
+	
+	return null;
+    }
+    /** get the total number of docs that match */
+    protected long numDocsMatched(Object query_result) {
+    	return ((LuceneQueryResult)query_result).getTotalDocs();
+    	
+    }
+    /** get the list of doc ids */
+    protected String [] getDocIDs(Object query_result) {
+    	Vector docs = ((LuceneQueryResult)query_result).getDocs();
+    	String [] doc_nums = new String [docs.size()];
+    	for (int d = 0; d < docs.size(); d++) {
+	    String doc_num = Long.toString(((LuceneQueryResult.DocInfo) docs.elementAt(d)).num_);
+    	    doc_nums[d] = doc_num;
+    	}
+    	return doc_nums;
+    }
+    /** get the list of doc ranks */
+    protected String [] getDocRanks(Object query_result) {
+    	Vector docs = ((LuceneQueryResult)query_result).getDocs();
+    	String [] doc_ranks = new String [docs.size()];
+    	for (int d = 0; d < docs.size(); d++) {
+    	    doc_ranks[d] = Float.toString(((LuceneQueryResult.DocInfo) docs.elementAt(d)).rank_);
+    	}
+    	return doc_ranks;
+    }
+    /** add in term info if available */
+    protected boolean addTermInfo(Element term_list, HashMap params,
+				  Object query_result) {
+    	String query_level = (String)params.get(LEVEL_PARAM); // the current query level
+	
+    	Vector terms = ((LuceneQueryResult)query_result).getTerms();
+    	for (int t = 0; t < terms.size(); t++) {
+    	    LuceneQueryResult.TermInfo term_info = (LuceneQueryResult.TermInfo) terms.get(t);
+    	    
+    	    Element term_elem = this.doc.createElement(GSXML.TERM_ELEM);
+    	    term_elem.setAttribute(GSXML.NAME_ATT, term_info.term_);
+    	    term_elem.setAttribute(FREQ_ATT, "" + term_info.term_freq_);
+    	    term_elem.setAttribute(NUM_DOCS_MATCH_ATT, "" + term_info.match_docs_);
+   	    term_elem.setAttribute(FIELD_ATT, term_info.field_);
+    	    term_list.appendChild(term_elem);
+    	}
+    	return true;
+    }
+    
+    protected String addFieldInfo(String query, String field) {
+	if (field.equals("") || field.equals("ZZ")) {
+	    return query;
+	}
+	return field+":("+query+")";
+    }
+    
+    protected void addQueryElem(StringBuffer s, String q, String f, String c) {
+	
+	String combine="";
+	if (s.length()>0) {
+	    combine = " "+c+" ";
+	}
+	s.append(combine + addFieldInfo(q,f));
+    }
+    
+    /** Lucene doesn't use these options at the moment */
+    protected String addStemOptions(String query, String stem,
+				    String casef, String accent) {
+	return query;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GS2MGPPRetrieve.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GS2MGPPRetrieve.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GS2MGPPRetrieve.java	(revision 13928)
@@ -0,0 +1,122 @@
+/*
+ *    GS2MGPPRetrieve.java
+ *    Copyright (C) 2005 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.service;
+
+// Greenstone classes
+import org.greenstone.mgpp.*;
+import org.greenstone.gsdl3.core.GSException;
+import org.greenstone.gsdl3.util.GSFile;
+import org.greenstone.gsdl3.util.GSXML;
+
+// XML classes
+import org.w3c.dom.Element;
+import org.w3c.dom.Text;
+
+// General Java classes
+import java.io.File;
+
+import org.apache.log4j.*;
+
+public class GS2MGPPRetrieve
+    extends AbstractGS2DocumentRetrieve
+{
+     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.GS2MGPPRetrieve.class.getName());
+
+     // Parameters used
+    private static final String LEVEL_PARAM = "level";
+
+    // Elements used in the config file that are specific to this class
+    private static final String DEFAULT_LEVEL_ELEM = "defaultLevel";
+
+    private MGPPWrapper mgpp_src = null;
+    
+    private String default_level = null;
+    private String mgpp_textdir = null;
+	
+    public GS2MGPPRetrieve() {
+	this.mgpp_src = new MGPPWrapper();
+    }
+
+    public void cleanUp() {
+	super.cleanUp();
+	this.mgpp_src.unloadIndexData();
+    }
+
+    /** configure this service */
+    public boolean configure(Element info, Element extra_info)
+    {
+	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+
+	// Do specific configuration
+	logger.info("Configuring GS2MGPPRetrieve...");
+
+	// Get the default level out of <defaultLevel> (buildConfig.xml)
+	Element def = (Element) GSXML.getChildByTagName(info, DEFAULT_LEVEL_ELEM);
+	if (def != null) {
+	    this.default_level = def.getAttribute(GSXML.SHORTNAME_ATT);
+	}
+	if (this.default_level == null || this.default_level.equals("")) {
+	    logger.error("default level not specified!");
+	    return false;
+	}
+	
+	// The location of the MGPP text files
+	mgpp_textdir = GSFile.collectionBaseDir(this.site_home, this.cluster_name) +
+	    File.separatorChar + GSFile.collectionTextPath(this.index_stem);
+
+	// Do generic configuration
+	return true;
+ 
+    }
+    
+    /** returns the content of a node
+     * should return a nodeContent element:
+     * <nodeContent>text content or other elements</nodeContent>
+     */
+    protected Element getNodeContent(String doc_id, String lang) throws GSException {
+	long doc_num = this.gdbm_src.OID2Docnum(doc_id);
+	if (doc_num == -1) {
+	    logger.error("OID "+doc_id +" couldn't be converted to mgpp num");
+	    return null;
+	}
+	Element content_node = this.doc.createElement(GSXML.NODE_CONTENT_ELEM);
+	
+	String doc_content = "";
+	try {
+	    doc_content = this.mgpp_src.getDocument(this.mgpp_textdir, 
+						    this.default_level,
+						    doc_num);
+	    if (doc_content != null) {
+		doc_content = resolveTextMacros(doc_content, doc_id, lang);
+	    } 
+	} catch (Exception e) {
+	    logger.info("exception happended with mgpp_src.getDocument()" + e);
+	    doc_content = "this is the content for section hash id "+ doc_id+", mgpp doc num "+doc_num+"\n";
+
+	}
+	Text t = this.doc.createTextNode(doc_content);
+	content_node.appendChild(t);
+	return content_node;
+
+    }
+
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GS2MGPPSearch.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GS2MGPPSearch.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GS2MGPPSearch.java	(revision 13928)
@@ -0,0 +1,264 @@
+/*
+ *    GS2MGPPSearch.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *   the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.service;
+
+
+// Greenstone classes
+import org.greenstone.mgpp.*;
+import org.greenstone.gsdl3.util.*;
+
+// XML classes
+import org.w3c.dom.Document;
+import org.w3c.dom.Element; 
+import org.w3c.dom.NodeList;
+
+// java classes
+import java.util.Iterator;
+import java.util.Set;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.Vector;
+import java.io.File;
+
+import org.apache.log4j.*;
+
+/**
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ * @author <a href="mailto:mdewsnip@cs.waikato.ac.nz">Michael Dewsnip</a>
+ */
+
+public class GS2MGPPSearch 
+    extends AbstractGS2FieldSearch 
+{
+    private MGPPWrapper mgpp_src=null;
+
+    private String physical_index_name = "idx";
+    
+    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.GS2MGPPSearch.class.getName());
+
+    /** constructor */
+    public GS2MGPPSearch()
+    {
+	this.mgpp_src = new MGPPWrapper();
+    }
+
+    public void cleanUp() {
+	super.cleanUp();
+	this.mgpp_src.unloadIndexData();
+    }
+
+    /** configure this service */
+    public boolean configure(Element info, Element extra_info)
+    {
+	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+
+	// the default level is also the level which gdbm is expecting
+	// this must not be overwritten
+	this.mgpp_src.setReturnLevel(this.default_gdbm_level);
+	// return term info
+	this.mgpp_src.setReturnTerms(true);
+	// set the default - this may be overwritten by query params
+	this.mgpp_src.setQueryLevel(this.default_level);
+	this.mgpp_src.setMaxNumeric(this.maxnumeric);
+    
+	return true;
+    }
+
+    /** add in the mgpp specific params to TextQuery */
+    protected void addCustomQueryParams(Element param_list, String lang) 
+    {
+	super.addCustomQueryParams(param_list, lang);
+	createParameter(RANK_PARAM, param_list, lang);
+    }
+
+    protected boolean setUpQueryer(HashMap params) {
+	// set up mgpp_src
+	String indexdir = GSFile.collectionBaseDir(this.site_home, this.cluster_name) + File.separatorChar + GSFile.collectionIndexPath(this.index_stem, this.physical_index_name);
+	this.mgpp_src.loadIndexData(indexdir);
+
+	// set up the query params
+	Set entries = params.entrySet();
+	Iterator i = entries.iterator();
+	while (i.hasNext()) {
+	    Map.Entry m = (Map.Entry)i.next();
+	    String name = (String)m.getKey();
+	    String value = (String)m.getValue();
+	    
+	    if (name.equals(CASE_PARAM)) {
+		boolean val = (value.equals(BOOLEAN_PARAM_ON)?true:false);
+		this.mgpp_src.setCase(val);		
+	    } else if (name.equals(STEM_PARAM)) {
+		boolean val = (value.equals(BOOLEAN_PARAM_ON)?true:false);
+		this.mgpp_src.setStem(val);
+	    } else if (name.equals(ACCENT_PARAM)) {
+		boolean val = (value.equals(BOOLEAN_PARAM_ON)?true:false);
+		this.mgpp_src.setAccentFold(val);
+	    } else if (name.equals(MAXDOCS_PARAM)&& !value.equals("")) {
+		int docs = Integer.parseInt(value);
+		this.mgpp_src.setMaxDocs(docs);
+	    } else if (name.equals(LEVEL_PARAM)) {
+		this.mgpp_src.setQueryLevel(value);
+	    } else if (name.equals(MATCH_PARAM)) {
+		int mode;
+		if (value.equals(MATCH_PARAM_ALL)) mode=1;
+		else mode=0;
+		this.mgpp_src.setMatchMode(mode);
+	    } else if (name.equals(RANK_PARAM)) {
+		if (value.equals(RANK_PARAM_RANK)) {
+		    this.mgpp_src.setSortByRank(true);
+		} else if (value.equals(RANK_PARAM_NONE)) {
+		    this.mgpp_src.setSortByRank(false);
+		}
+	    } // ignore any others
+	}
+	
+	return true;
+    }
+    
+    protected Object runQuery(String query) {
+	this.mgpp_src.runQuery(query);
+	MGPPQueryResult mqr= this.mgpp_src.getQueryResult();
+	return mqr;
+
+    }
+
+    protected long numDocsMatched(Object query_result) {
+	return ((MGPPQueryResult)query_result).getTotalDocs();
+    }
+    
+    protected String [] getDocIDs(Object query_result) {
+	
+	Vector docs = ((MGPPQueryResult)query_result).getDocs();
+	String [] doc_nums = new String [docs.size()];
+	for (int d = 0; d < docs.size(); d++) {
+	    doc_nums[d] = Long.toString((((MGPPDocInfo) docs.elementAt(d)).num_));
+	}
+	return doc_nums;
+    }
+    
+    protected String [] getDocRanks(Object query_result) {
+	
+	Vector docs = ((MGPPQueryResult)query_result).getDocs();
+	String [] doc_ranks = new String [docs.size()];
+	for (int d = 0; d < docs.size(); d++) {
+	    doc_ranks[d] = Float.toString(((MGPPDocInfo) docs.elementAt(d)).rank_);
+	}
+	return doc_ranks;
+    }
+    
+    protected boolean addTermInfo(Element term_list, HashMap params, 
+				  Object query_result) {
+
+	String query_level = (String)params.get(LEVEL_PARAM); // the current query level
+
+	Vector terms = ((MGPPQueryResult)query_result).getTerms();
+	for (int t = 0; t < terms.size(); t++) {
+	    MGPPTermInfo term_info = (MGPPTermInfo) terms.get(t);
+	    
+	    Element term_elem = this.doc.createElement(GSXML.TERM_ELEM);
+	    term_elem.setAttribute(GSXML.NAME_ATT, term_info.term_);
+	    term_elem.setAttribute(STEM_ATT, "" + term_info.stem_method_);
+	    term_elem.setAttribute(FREQ_ATT, "" + term_info.term_freq_);
+	    term_elem.setAttribute(NUM_DOCS_MATCH_ATT, "" + term_info.match_docs_);
+	    String field = term_info.tag_;
+	    if (field.equals(query_level)) {
+		// ignore
+		field = "";
+	    }
+	    term_elem.setAttribute(FIELD_ATT, field);
+	    
+	    Vector equiv_terms = term_info.equiv_terms_;
+	    Element equiv_term_list = this.doc.createElement(EQUIV_TERM_ELEM+GSXML.LIST_MODIFIER);
+	    term_elem.appendChild(equiv_term_list);
+	    
+	    for (int et = 0; et < equiv_terms.size(); et++) {
+		String equiv_term = (String) equiv_terms.get(et);
+
+		Element equiv_term_elem = this.doc.createElement(GSXML.TERM_ELEM);
+		equiv_term_elem.setAttribute(GSXML.NAME_ATT, equiv_term);
+		equiv_term_elem.setAttribute(NUM_DOCS_MATCH_ATT, "");
+		equiv_term_elem.setAttribute(FREQ_ATT, "");
+		equiv_term_list.appendChild(equiv_term_elem);
+	    }
+
+	    term_list.appendChild(term_elem);
+	}
+	return true;
+    }
+    
+
+    protected String addFieldInfo(String query, String field) {
+	if (field.equals("") || field.equals("ZZ")) {
+	    return query;
+	}
+	return "["+query+"]:"+field;
+    }
+    protected void addQueryElem(StringBuffer final_query, String query, 
+				String field, String combine) {
+
+	String comb="";
+	if (final_query.length()>0) {
+	    comb = " "+combine+" ";
+	}
+	final_query.append(comb+addFieldInfo(query,field));
+    }
+    
+    protected String addStemOptions(String query, String stem,
+				    String casef, String accent) {
+	String mods = "#";
+	if (casef != null) {
+	    if (casef.equals("1")) {
+		mods += "i";
+	    } else {
+		mods += "c";
+	    }
+	}
+	if (stem != null) {
+	    if (stem.equals("1")) {
+		mods += "s";
+	    } else {
+		mods+= "u";
+	    }
+	}
+	if (accent != null) {
+	    if (accent.equals("1")) {
+		mods += "f";
+	    } else {
+		mods += "a";
+	    }
+	}
+	
+	StringBuffer temp = new StringBuffer();
+	String [] terms = query.split(" ");
+	for (int i=0; i<terms.length; i++) {
+	    String t = terms[i].trim();
+	    // what is the TX bit about???
+	    if (!t.equals("") && !t.equals("TX")) {
+		temp.append(" "+t+mods);
+	    }
+	}
+	return temp.toString();
+    }
+
+}
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GS2MGRetrieve.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GS2MGRetrieve.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GS2MGRetrieve.java	(revision 13928)
@@ -0,0 +1,131 @@
+/*
+ *    GS2MGRetrieve.java
+ *    Copyright (C) 2005 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.service;
+
+// Greenstone classes
+import org.greenstone.mg.*;
+import org.greenstone.gsdl3.core.GSException;
+import org.greenstone.gsdl3.util.GSFile;
+import org.greenstone.gsdl3.util.GSXML;
+
+// XML classes
+import org.w3c.dom.Element;
+import org.w3c.dom.Text;
+
+// General Java classes
+import java.io.File;
+
+import org.apache.log4j.*;
+
+public class GS2MGRetrieve
+    extends AbstractGS2DocumentRetrieve
+{
+   static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.GS2MGRetrieve.class.getName());
+
+    // Elements used in the config file that are specific to this class
+    private static final String DEFAULT_INDEX_ELEM = "defaultIndex";
+    private static final String INDEX_LIST_ELEM = "indexList";
+    private static final String INDEX_ELEM = "index";
+
+    private MGWrapper mg_src = null;
+    private String mg_basedir = null;
+    private String mg_textdir = null;
+    private String default_index = null;
+    private boolean has_default_index = false;
+	
+    public GS2MGRetrieve() {
+	this.mg_src = new MGWrapper();
+    }
+
+    public void cleanUp() {
+	super.cleanUp();
+	this.mg_src.unloadIndexData();
+    }
+
+    /** configure this service */
+    public boolean configure(Element info, Element extra_info)
+    {
+	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+	
+	// Do specific configuration
+	logger.info("Configuring GS2MGRetrieve...");
+	
+	// Get the default index out of <defaultIndex> (buildConfig.xml)
+	Element def = (Element) GSXML.getChildByTagName(info, DEFAULT_INDEX_ELEM);
+	if (def != null) {
+	    this.default_index = def.getAttribute(GSXML.SHORTNAME_ATT);
+	}
+	if (this.default_index == null || this.default_index.equals("")) {
+             logger.error("default index is not specified, the content of a document will not be retrieved");
+              has_default_index = false;
+	      return true;
+	    //}
+	}
+	logger.debug("Default index: " + this.default_index);
+       
+	// The location of the MG index and text files
+	mg_basedir = GSFile.collectionBaseDir(this.site_home, this.cluster_name) + File.separatorChar;  // Needed by MG
+	mg_textdir = GSFile.collectionTextPath(this.index_stem);
+	// index is only needed to start up MG, not used so just use the default index
+	String indexpath = GSFile.collectionIndexPath(this.index_stem, this.default_index);
+	this.mg_src.setIndex(indexpath);
+	has_default_index = true;
+	return true;
+    }
+    
+    /** returns the content of a node
+     * should return a nodeContent element:
+     * <nodeContent>text content or other elements</nodeContent>
+     */
+    protected Element getNodeContent(String doc_id, String lang) throws GSException {
+	long doc_num = this.gdbm_src.OID2Docnum(doc_id);
+	if (doc_num == -1) {
+	    logger.error("OID "+doc_id +" couldn't be converted to mg num");
+	    return null;
+	}
+	Element content_node = this.doc.createElement(GSXML.NODE_CONTENT_ELEM);
+	
+         
+	String doc_content = null;
+
+	if (has_default_index ){
+            doc_content =  this.mg_src.getDocument(this.mg_basedir,
+				  	     this.mg_textdir, doc_num);
+	}
+ 
+	if (doc_content!=null) {
+	    // remove any ctrl-c or ctrl-b 
+	    doc_content = doc_content.replaceAll("\u0002|\u0003", "");
+	    // replace _httpimg_ with the correct address
+	    doc_content = resolveTextMacros(doc_content, doc_id, lang);
+	    //GSXML.addDocText(this.doc, doc, doc_content);
+	} else {
+	    logger.error("the doc content was null, not getting that section\n");
+	    doc_content = "couldn't retrieve content for this section, please check the log file for more detail\n";
+	}
+	Text t = this.doc.createTextNode(doc_content);
+	content_node.appendChild(t);
+	return content_node;
+
+    }
+
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GS2MGSearch.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GS2MGSearch.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GS2MGSearch.java	(revision 13928)
@@ -0,0 +1,232 @@
+/*
+ *    GS2MGSearch.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *   the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.service;
+
+
+// Greenstone classes
+import org.greenstone.mg.*;
+import org.greenstone.gsdl3.util.*;
+
+// XML classes
+import org.w3c.dom.Document;
+import org.w3c.dom.Element; 
+import org.w3c.dom.NodeList;
+
+// java
+import java.util.Vector;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.Iterator;
+import java.io.File;
+
+import org.apache.log4j.*;
+
+/**
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ * @author <a href="mailto:mdewsnip@cs.waikato.ac.nz">Michael Dewsnip</a>
+ */
+
+public class GS2MGSearch 
+    extends AbstractGS2Search 
+{
+
+    protected MGWrapper mg_src = null;
+
+    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.GS2MGSearch.class.getName());
+
+
+    /** constructor */
+    public GS2MGSearch()
+    {
+	this.mg_src = new MGWrapper();
+	
+    }
+    public void cleanUp() {
+	super.cleanUp();
+	this.mg_src.unloadIndexData();
+    }
+
+    /** configure this service */
+    public boolean configure(Element info, Element extra_info)
+    {
+	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+
+	this.mg_src.setMaxNumeric(this.maxnumeric);             
+
+        	
+	return true;
+    }
+    
+
+
+    /** do the actual query */
+    protected Element processTextQuery(Element request) 
+    {
+
+	// Create a new (empty) result message
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	result.setAttribute(GSXML.FROM_ATT, TEXT_QUERY_SERVICE);
+	result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+
+	// Get the parameters of the request
+	Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	if (param_list == null) {
+	    logger.error("TextQuery request had no paramList.");
+	    return result;  // Return the empty result
+	}
+
+	// Process the request parameters
+	HashMap params = GSXML.extractParams(param_list, false);
+	
+	// Make sure a query has been specified
+	String query = (String) params.get(QUERY_PARAM);
+	if (query == null || query.equals("")) {
+	    return result;  // Return the empty result
+	}
+
+	// If an index hasn't been specified, use the default
+	String index = (String) params.get(INDEX_PARAM); 
+	if (index == null) {
+	    index = this.default_index;
+	}
+
+	// The location of the MG index and text files
+	String basedir = GSFile.collectionBaseDir(this.site_home, this.cluster_name) +  File.separatorChar;  // Needed for MG
+	String textdir = GSFile.collectionTextPath(this.index_stem);
+	String indexpath = GSFile.collectionIndexPath(this.index_stem, index);
+	this.mg_src.setIndex(indexpath);
+	System.err.println("index path = "+indexpath);
+	// set the mg query parameters to the values the user has specified
+	setStandardQueryParams(params);
+	this.mg_src.runQuery(basedir, textdir, query);
+	MGQueryResult mqr = this.mg_src.getQueryResult();
+	if (mqr.isClear()) {
+	    // something has gone wrong
+	    GSXML.addError(this.doc, result, "Couldn't query the mg database", GSXML.ERROR_TYPE_SYSTEM);
+	    return result;
+	}
+	long totalDocs = mqr.getTotalDocs();
+
+	// Get the docnums out, and convert to HASH ids
+	Vector docs = mqr.getDocs();
+	if (docs.size() == 0) {
+	    logger.error("No results found...\n");
+	}
+
+	// Create a metadata list to store information about the query results
+	Element metadata_list = this.doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER); 
+	result.appendChild(metadata_list);
+
+	// Add a metadata element specifying the number of matching documents
+	// because teh total number is just the number returned, use numDocsReturned, not numDocsMatched
+	GSXML.addMetadata(this.doc, metadata_list, "numDocsReturned", ""+totalDocs);
+	// add a metadata item to specify what actual query was done - eg if stuff was stripped out etc. and then we can use the query later, cos we don't know which parameter was the query
+	GSXML.addMetadata(this.doc, metadata_list, "query", query);
+
+	if (docs.size() > 0) {
+	    // Create a document list to store the matching documents, and add them
+	    Element document_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	    result.appendChild(document_list);
+	    for (int d = 0; d < docs.size(); d++) {
+		long docnum = ((MGDocInfo) docs.elementAt(d)).num_;
+		float rank = ((MGDocInfo) docs.elementAt(d)).rank_;
+		String doc_id = internalNum2OID(docnum);
+		Element doc_node = createDocNode(doc_id, Float.toString(rank));
+		document_list.appendChild(doc_node);
+	    }
+	}
+	
+	// Create a term list to store the term information, and add it
+	Element term_list = this.doc.createElement(GSXML.TERM_ELEM+GSXML.LIST_MODIFIER);
+	result.appendChild(term_list);
+	Vector terms = mqr.getTerms();
+	for (int t = 0; t < terms.size(); t++) {
+	    MGTermInfo term_info = (MGTermInfo) terms.get(t);
+
+	    String term = term_info.term_;
+	    int stem_method = term_info.stem_method_;
+	    Vector equiv_terms = term_info.equiv_terms_;
+
+	    Element term_elem = this.doc.createElement(GSXML.TERM_ELEM);
+	    term_elem.setAttribute(GSXML.NAME_ATT, term);
+	    term_elem.setAttribute(STEM_ATT, "" + stem_method);
+
+	    Element equiv_term_list = this.doc.createElement(EQUIV_TERM_ELEM+GSXML.LIST_MODIFIER);
+	    term_elem.appendChild(equiv_term_list);
+
+	    long total_term_freq = 0;
+	    for (int et = 0; et < equiv_terms.size(); et++) {
+		MGEquivTermInfo equiv_term_info = (MGEquivTermInfo) equiv_terms.get(et);
+
+		Element equiv_term_elem = this.doc.createElement(GSXML.TERM_ELEM);
+		equiv_term_elem.setAttribute(GSXML.NAME_ATT, equiv_term_info.term_);
+		equiv_term_elem.setAttribute(NUM_DOCS_MATCH_ATT, "" + equiv_term_info.match_docs_);
+		equiv_term_elem.setAttribute(FREQ_ATT, "" + equiv_term_info.term_freq_);
+		equiv_term_list.appendChild(equiv_term_elem);
+
+		total_term_freq += equiv_term_info.term_freq_;
+	    }
+
+	    term_elem.setAttribute(FREQ_ATT, "" + total_term_freq);
+	    term_list.appendChild(term_elem);
+	}
+	return result;
+    }
+
+    // should probably use a list rather than map
+    protected boolean setStandardQueryParams(HashMap params)
+    {
+	// set the default ones
+	this.mg_src.setReturnTerms(true);
+	this.mg_src.setCase(true); // turn casefolding on by default
+	Set entries = params.entrySet();
+	Iterator i = entries.iterator();
+	while (i.hasNext()) {
+	    Map.Entry m = (Map.Entry)i.next();
+	    String name = (String)m.getKey();
+	    String value = (String)m.getValue();
+
+	    if (name.equals(CASE_PARAM)) {
+		boolean val = (value.equals(BOOLEAN_PARAM_ON) ? true : false);
+		this.mg_src.setCase(val);
+	    }
+	    else if (name.equals(STEM_PARAM)) {
+		boolean val = (value.equals(BOOLEAN_PARAM_ON) ? true : false);
+		this.mg_src.setStem(val);
+	    }
+	    else if (name.equals(MATCH_PARAM)) {
+		int mode = (value.equals(MATCH_PARAM_ALL) ? 1 : 0);
+		this.mg_src.setMatchMode(mode);
+	    }
+	    else if (name.equals(MAXDOCS_PARAM)) {
+		int docs = Integer.parseInt(value);
+		this.mg_src.setMaxDocs(docs);
+	    } // ignore any others
+	}
+	return true;
+    }
+
+
+}
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GoogleSearch.java.tmp
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GoogleSearch.java.tmp	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GoogleSearch.java.tmp	(revision 13928)
@@ -0,0 +1,227 @@
+package org.greenstone.gsdl3.service;
+
+// Greenstone classes
+import org.greenstone.gsdl3.util.*;
+
+//Google Web Services API classes
+//import com.google.soap.search.GoogleSearch;
+import com.google.soap.search.GoogleSearchFault;
+import com.google.soap.search.GoogleSearchResult;
+import com.google.soap.search.GoogleSearchResultElement;
+import com.google.soap.search.GoogleSearchDirectoryCategory;
+
+// XML classes
+import org.w3c.dom.Element; 
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList; 
+
+//Java classes
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.io.File;
+import java.io.InputStream;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URLConnection;
+import java.net.URL;
+import java.net.Authenticator;
+import java.net.PasswordAuthentication;
+import java.net.MalformedURLException;
+import java.lang.Object;
+
+
+/**
+ *
+ * @author <a href="mailto:chi@cs.waikato.ac.nz">Chi-Yu Huang</a>
+ *
+ */
+
+public class GoogleSearch
+    extends AbstractSearch {
+    
+    //Parameters connect to Proxy Server
+    private boolean using_proxy = false;
+    private String proxy_host = null;
+    private int proxy_port;
+    private String proxy_user = null;
+    private char [] proxy_passwd = null;
+
+    // google key
+    private String client_key = null;
+    
+    public GoogleSearch()
+    {
+    }
+	    
+    //Configure GoogleSearch Service
+    public boolean configure(Element info, Element extra_info) 
+    { 
+	if (!super.configure(info, extra_info)) {
+	    return false;
+	}
+	System.err.println("Configuring GoogleSearch");
+	Element server_elem = (Element)GSXML.getChildByTagName(info, "googleServer");
+	if (server_elem == null) {
+	    System.err.println("GoogleSearch.configure error: no googleServer element found");
+	    return false;
+	}
+	
+	client_key = server_elem.getAttribute("key");
+	if (client_key.equals("")) {
+	    System.err.println("GoogleSearch.configure error: no client_key for the googleServer element");
+	    return false;
+	}
+	
+	does_paging = true;
+	does_chunking = false;
+
+	// are we behind a proxy??
+	// all the details should have been set up by the Message Router
+	proxy_host = System.getProperty("http.proxyHost");
+	if (proxy_host != null && !proxy_host.equals("")) {
+	    using_proxy = true;
+	    try {
+		proxy_port = Integer.parseInt(System.getProperty("http.proxyPort").trim());
+	    } catch (Exception e) {
+		System.err.println("GoogleSearch.configure error: couldn't get proxy port, defaulting to 80");
+		proxy_port = 80;
+	    }
+	    PasswordAuthentication pa = Authenticator.requestPasswordAuthentication(proxy_host, null, proxy_port, "http", "", null);
+	    proxy_user = pa.getUserName();
+	    proxy_passwd = pa.getPassword();
+	}
+	return true;
+    }
+    
+    /** Process a text query - implemented by concrete subclasses */
+    protected Element processTextQuery(Element request) {
+	
+	//Connect to Google Web API service
+	com.google.soap.search.GoogleSearch search = new com.google.soap.search.GoogleSearch();
+
+	// Set mandatory attributes
+	search.setKey(client_key);
+
+	// proxy??
+	if (using_proxy) {
+	    search.setProxyHost(proxy_host);
+	    search.setProxyPort(proxy_port);
+	    search.setProxyUserName(proxy_user);
+	    search.setProxyPassword(new String(proxy_passwd));
+	}
+
+	//set optional attributes
+	search.setSafeSearch(true);
+	
+	// Create a new (empty) result message
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	result.setAttribute(GSXML.FROM_ATT, TEXT_QUERY_SERVICE);
+	result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+	Element doc_node_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	result.appendChild(doc_node_list);
+	Element query_metadata_list = this.doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
+	result.appendChild(query_metadata_list);
+
+	Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	if (param_list == null) {
+	    System.err.println("GoogleSearch.processTextQuery Error:: TextQuery request had no paramList.");
+	    return result;  // Return the empty result
+	}
+
+	// Process the request parameters
+	HashMap params = GSXML.extractParams(param_list, false);
+
+	// Make sure a query has been specified
+	String query = (String) params.get(QUERY_PARAM);
+	if (query == null || query.equals("")) {
+	    System.err.println("GoogleSearch.processTextQuery Error: TextQuery request had no query string.");
+	    return result;  // Return the empty result
+	}
+       	// tidy whitespace
+	query = query.replaceAll("\\s+", "+");
+	
+	search.setQueryString(query);
+
+	//Check hits_per_page
+	int hits_per_page;
+	try {
+	    hits_per_page = Integer.parseInt(((String)params.get(HITS_PER_PAGE_PARAM)).trim());
+	} catch (Exception e) {
+	    System.err.println("GoogleSearch.processTextQuery error: couldn't get hits per page param, defaulting to 10");
+	    hits_per_page = 10;
+	}
+	//Check the start_page number
+	int start_page;
+	try {
+	    start_page = Integer.parseInt(((String) params.get(START_PAGE_PARAM)).trim());
+	} catch (Exception e) {
+	    System.err.println("GoogleSearch.processTextQuery error: couldn't get start page param, defaulting to 1");
+	    start_page = 1;
+	}
+	
+	//Invoke Actual Search
+	
+	// Google only allows 10 hits per request
+	int loop = hits_per_page/10;
+	int remainder = hits_per_page%10;
+	int google_start_page = (start_page-1)*hits_per_page;
+	int pages_per_loop;
+	for (int j=0; j < loop; j++){
+	    if (j < (loop-1) || remainder == 0) {
+		pages_per_loop = 10;
+	    } else {
+		pages_per_loop = remainder;
+	    }
+	    search.setMaxResults(pages_per_loop); 
+	    search.setStartResult(google_start_page);
+	    google_start_page = google_start_page + pages_per_loop;
+	    GoogleSearchResult google_result;
+	    try{
+		google_result = search.doSearch();
+	    } catch (GoogleSearchFault ex) {
+		System.err.println("GoogleSearch.processTextQuery error: the call to the Google Web APIs failed:" + ex.toString());
+		// add the error to the result
+		return result;
+	    }
+	    if (j==0) {
+		
+		//Total amount of documents Google Search returned
+		// only need to do this on the first loop
+		
+		long numdocs_matched = google_result.getEstimatedTotalResultsCount();	    
+		GSXML.addMetadata(this.doc, query_metadata_list, "numDocsMatched", ""+numdocs_matched);
+		
+	    }
+	    GoogleSearchResultElement[] details = google_result.getResultElements();
+	    for (int i=0; i<details.length; i++){
+		Element doc_node = this.doc.createElement(GSXML.DOC_NODE_ELEM);
+		doc_node_list.appendChild(doc_node);
+		
+		Element metadata_list = this.doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
+		doc_node.appendChild(metadata_list);
+		
+		String google_url = details[i].getURL();  
+		String google_title = details[i].getTitle();
+		String google_snippet = details[i].getSnippet();
+		if (google_url !=null) {
+		    GSXML.addMetadata(this.doc, metadata_list, "URL", google_url);
+		}
+		if (google_title != null) {
+		    GSXML.addMetadata(this.doc, metadata_list, "Title", google_title);
+		}
+		if (google_snippet != null) {
+		    GSXML.addMetadata(this.doc, metadata_list, "Snippet", google_snippet);
+		}
+	    }
+	} // for each loop
+	return result;
+    }
+    
+    protected void getIndexData(ArrayList index_ids, ArrayList index_names,String lang){
+       	index_ids.add("idx");
+	index_names.add("Google main index");
+    }
+    
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GutBookRetrieve.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GutBookRetrieve.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/GutBookRetrieve.java	(revision 13928)
@@ -0,0 +1,41 @@
+package org.greenstone.gsdl3.service;
+
+import org.greenstone.gsdl3.util.*;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+import org.w3c.dom.NodeList;
+
+public class GutBookRetrieve 
+    extends XMLRetrieve {
+
+    protected Element extractTitleMeta(Element section) {
+	Element meta_elem = this.doc.createElement(GSXML.METADATA_ELEM);
+	meta_elem.setAttribute(GSXML.NAME_ATT, "Title");
+
+	Element title_elem = (Element)GSXML.getChildByTagName(section, "title");
+	if (title_elem == null) {
+	    title_elem = (Element)GSXML.getNodeByPath(section, "chapheader/title");
+	}
+	if (title_elem == null) {
+	    // find teh first title elem
+	    NodeList titles = section.getElementsByTagName("title");
+	    if (titles != null) {
+		title_elem = (Element)titles.item(0);
+	    }
+	}
+
+	if (title_elem == null) {
+	    return null; // no title found
+	}
+	
+	
+	Text t = (Text) GSXML.getNodeTextNode(title_elem);
+	
+	meta_elem.appendChild(this.doc.importNode(t, false));
+	return meta_elem;
+
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/IViaProxy.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/IViaProxy.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/IViaProxy.java	(revision 13928)
@@ -0,0 +1,508 @@
+package org.greenstone.gsdl3.service;
+
+// Greenstone classes
+import org.greenstone.gsdl3.util.*;
+
+// XML classes
+import org.w3c.dom.Element; 
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList; 
+
+import java.util.HashMap;
+import java.io.File;
+import java.io.InputStream;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URLConnection;
+import java.net.URL;
+import java.net.Authenticator;
+import java.net.MalformedURLException;
+
+import org.apache.log4j.*;
+
+/**
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ * @version $Revision$
+ */
+
+public class IViaProxy 
+    extends ServiceRack {
+   
+     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.IViaProxy.class.getName());
+    
+    // the services on offer
+    // these strings must match what is found in the properties file
+    protected static final String TEXT_QUERY_SERVICE = "TextQuery";
+    protected static final String DOC_CONTENT_SERVICE = "DocumentContentRetrieve";
+    protected static final String DOC_META_SERVICE = "DocumentMetadataRetrieve";
+    protected static final String QUERY_PARAM = "query";
+    protected static final String FIELD_PARAM = "fields";
+    // have standard gs param names for hits per page, and start page
+    // these need to be mapped to iVia params
+    protected static final String GS_HITS_PARAM = "hitsPerPage";
+    protected static final String IM_HITS_PARAM = "no_of_records_per_page";
+    protected static final String GS_START_PAGE_PARAM = "startPage";
+    protected static final String IM_START_PAGE_PARAM = "start_page_no";
+
+    protected String ivia_server_url = null;
+    
+    public boolean configure(Element info, Element extra_info) {
+	
+	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+
+	Element server_elem = (Element)GSXML.getChildByTagName(info, "iViaServer");
+	if (server_elem == null) {
+	    logger.error("no iViaServer element found");
+	    return false;
+	}
+	ivia_server_url = server_elem.getAttribute("url");
+	if (ivia_server_url.equals("")) {
+	    logger.error("no url for the iViaServer element");
+	    return false;
+	}
+	Element tq_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	tq_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_QUERY);
+	tq_service.setAttribute(GSXML.NAME_ATT, TEXT_QUERY_SERVICE);
+	this.short_service_info.appendChild(tq_service);
+
+	Element dc_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	dc_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
+	dc_service.setAttribute(GSXML.NAME_ATT, DOC_CONTENT_SERVICE);
+	this.short_service_info.appendChild(dc_service);
+
+	Element dm_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	dm_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
+	dm_service.setAttribute(GSXML.NAME_ATT, DOC_META_SERVICE);
+	this.short_service_info.appendChild(dm_service);
+	
+	// 
+	// add some format info to service map if there is any
+	String path = GSPath.appendLink(GSXML.SEARCH_ELEM, GSXML.FORMAT_ELEM);
+	Element format = (Element) GSXML.getNodeByPath(extra_info, path);
+	if (format != null) {
+	    this.format_info_map.put(TEXT_QUERY_SERVICE, this.doc.importNode(format, true));
+	}
+
+	
+	// look for document display format
+	path = GSPath.appendLink(GSXML.DISPLAY_ELEM, GSXML.FORMAT_ELEM);
+	Element display_format = (Element)GSXML.getNodeByPath(extra_info, path);
+	if (display_format != null) {
+	    this.format_info_map.put(DOC_CONTENT_SERVICE, this.doc.importNode(display_format, true));
+	    // shoudl we make a copy?
+	}
+
+	return true;
+	
+    }
+    
+    protected Element getServiceDescription(String service, String lang, String subset) {
+	
+	if (service.equals(TEXT_QUERY_SERVICE)) {
+	    Element tq_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	    tq_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_QUERY);
+	    tq_service.setAttribute(GSXML.NAME_ATT, TEXT_QUERY_SERVICE);
+	    if (subset == null || subset.equals(GSXML.DISPLAY_TEXT_ELEM + GSXML.LIST_MODIFIER)) {
+		tq_service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_NAME, getTextString(TEXT_QUERY_SERVICE+".name", lang)));
+		tq_service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_SUBMIT, getTextString(TEXT_QUERY_SERVICE+".submit", lang)));
+		tq_service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_DESCRIPTION, getTextString(TEXT_QUERY_SERVICE+".description", lang)));
+	    } 
+	    if (subset == null || subset.equals(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER)) {
+		Element param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+		tq_service.appendChild(param_list);
+		Element param = GSXML.createParameterDescription(this.doc, QUERY_PARAM, getTextString("param."+QUERY_PARAM, lang), GSXML.PARAM_TYPE_STRING, null, null, null);
+		param_list.appendChild(param);
+		String [] field_ids = {"kw", "au", "su", "ti", "de", "fu"};
+		String [] field_names = {
+		    getTextString("param."+FIELD_PARAM+".kw", lang), 
+		    getTextString("param."+FIELD_PARAM+".au", lang), 
+		    getTextString("param."+FIELD_PARAM+".su", lang), 
+		    getTextString("param."+FIELD_PARAM+".ti", lang), 
+		    getTextString("param."+FIELD_PARAM+".de", lang), 
+		    getTextString("param."+FIELD_PARAM+".fu", lang) };
+		
+		param = GSXML.createParameterDescription(this.doc, FIELD_PARAM, getTextString("param."+FIELD_PARAM, lang), GSXML.PARAM_TYPE_ENUM_MULTI, "kw,au,su,ti,de,fu", field_ids, field_names);
+		param_list.appendChild(param);
+		
+		
+		String [] hits_options = {"10", "30", "50"};
+		param = GSXML.createParameterDescription(this.doc, GS_HITS_PARAM, getTextString("param."+GS_HITS_PARAM, lang), GSXML.PARAM_TYPE_ENUM_SINGLE, "10", hits_options, hits_options);
+		param_list.appendChild(param);
+		
+		param = GSXML.createParameterDescription(this.doc, GS_START_PAGE_PARAM, "", GSXML.PARAM_TYPE_INVISIBLE, "1", null, null);
+		param_list.appendChild(param);
+	    }
+	    return tq_service;
+	} 
+	if (service.equals(DOC_META_SERVICE)) {
+	    Element dm_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	    dm_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
+	    dm_service.setAttribute(GSXML.NAME_ATT, DOC_META_SERVICE);
+	    return dm_service;
+
+	}
+	if (service.equals(DOC_CONTENT_SERVICE)) {
+	    Element dc_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	    dc_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
+	    dc_service.setAttribute(GSXML.NAME_ATT, DOC_CONTENT_SERVICE);
+	    return dc_service;
+	    
+	    
+	}
+	return null;
+    }
+   
+    /** Process a text query - implemented by concrete subclasses */
+    protected Element processTextQuery(Element request) {
+
+	// Create a new (empty) result message
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	result.setAttribute(GSXML.FROM_ATT, TEXT_QUERY_SERVICE);
+	result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+	Element doc_node_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	result.appendChild(doc_node_list);
+       
+
+	Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	if (param_list == null) {
+	    logger.error("TextQuery request had no paramList.");
+	    return result;  // Return the empty result
+	}
+
+	// Process the request parameters
+	HashMap params = GSXML.extractParams(param_list, false);
+
+	// Make sure a query has been specified
+	String query = (String) params.get(QUERY_PARAM);
+	if (query == null || query.equals("")) {
+	    return result;  // Return the empty result
+	}
+	// tidy whitespace
+	query = query.replaceAll("\\s+", "+");
+	String url_string = ivia_server_url+"/cgi-bin/canned_search?theme=gsdl3&query="+query; 
+
+	// check for fields
+	String fields = (String) params.get(FIELD_PARAM);
+	if (fields != null && !fields.equals("")) {
+	    url_string += "&fields="+fields;
+	}
+
+	//check for hits per page
+	String hits_per_page = (String) params.get(GS_HITS_PARAM);
+	if (hits_per_page != null && !hits_per_page.equals("")) {
+	    url_string += "&"+IM_HITS_PARAM+"="+hits_per_page;
+	}
+
+	// check for start page
+	String start_page = (String) params.get(GS_START_PAGE_PARAM);
+	if (start_page != null && !start_page.equals("")) {
+	    url_string += "&"+IM_START_PAGE_PARAM+"="+start_page;
+	}
+	String results_num = null;
+	String doc_ids = null;
+	try {
+	    logger.debug("IViaProxy, sending "+url_string);
+	    BufferedReader reader = makeConnection(url_string);
+	    results_num = reader.readLine();
+	    doc_ids = reader.readLine();
+	    
+	} catch (Exception e) {
+	    logger.error("exception happened during query");
+	    e.printStackTrace();
+	    return result;
+	}
+	    
+	if (results_num.startsWith("Resources: ")) {
+	    results_num = results_num.substring(11);
+	} else {
+	    logger.error("badly formatted results line: "+results_num);
+	    return result;
+	}
+	if (doc_ids.startsWith("Ids: ")) {
+	    doc_ids = doc_ids.substring(5).trim();
+	} else {
+	    logger.error("badly formatted docs line: "+doc_ids);
+	    return result;
+	}
+	
+	// get the num docs and add to a metadata list
+	Element metadata_list = this.doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER); 
+	result.appendChild(metadata_list);
+	
+	// Add a metadata element specifying the number of matching documents
+	long numdocs = Long.parseLong(results_num);
+	GSXML.addMetadata(this.doc, metadata_list, "numDocsMatched", ""+numdocs);	
+	String [] ids = doc_ids.split(" ");
+	
+	for (int d=0; d<ids.length; d++) {
+	    Element doc_node = this.doc.createElement(GSXML.DOC_NODE_ELEM);
+	    doc_node.setAttribute(GSXML.NODE_ID_ATT, ids[d]);
+	    doc_node_list.appendChild(doc_node);
+	}
+	logger.debug("IViaProxy result:");
+	logger.debug(this.converter.getString(result));
+	return result;
+	
+    }
+     
+    protected Element processDocumentMetadataRetrieve(Element request) {
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	result.setAttribute(GSXML.FROM_ATT, DOC_META_SERVICE);
+	result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+
+	// Get the parameters of the request
+	Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	if (param_list == null) {
+	    logger.error("missing paramList.\n");
+	    return result;  // Return the empty result
+	}
+
+	// The metadata information required
+	StringBuffer field_list = new StringBuffer();
+	Element param = (Element) param_list.getFirstChild();
+	while (param != null) {
+	    // Identify the metadata information desired
+	    if (param.getAttribute(GSXML.NAME_ATT).equals("metadata")) {
+		String metadata = GSXML.getValue(param);
+		if (isAcceptableMetadata(metadata)) {
+		    field_list.append(metadata);
+		    field_list.append(",");	
+		}
+	    }
+	    param = (Element) param.getNextSibling();
+	}
+	
+	if (field_list.length()==0) {
+	    logger.error("no metadata specified.\n"); 
+	    return result;
+	}
+	    
+	// Get the documents
+	Element request_node_list = (Element) GSXML.getChildByTagName(request, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	if (request_node_list == null) {
+	    logger.error("DocumentMetadataRetrieve request had no "+GSXML.DOC_NODE_ELEM+"List.\n");
+ 	    return result;
+ 	}
+	
+	StringBuffer record_id_list = new StringBuffer();
+	
+	NodeList request_nodes = request_node_list.getChildNodes();
+	for (int i = 0; i < request_nodes.getLength(); i++) {
+	    Element request_node = (Element) request_nodes.item(i);
+	    String node_id = request_node.getAttribute(GSXML.NODE_ID_ATT);
+	    record_id_list.append(node_id);
+	    record_id_list.append(",");
+	}
+
+	// do the query to the iVia server
+	String url_string = ivia_server_url+"/cgi-bin/view_record_set?theme=gsdl3&record_id_list="+record_id_list.toString()+"&field_list="+field_list.toString(); 
+
+	Element node_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	result.appendChild(node_list);
+	try {
+	    BufferedReader reader = makeConnection(url_string);
+	    String line;
+	    while ((line = reader.readLine()) != null) {
+		if (!line.startsWith("Record:")) {
+		    continue;
+		}
+		// the first line is the record
+		line=line.substring(8);
+		Element doc_node = this.doc.createElement(GSXML.DOC_NODE_ELEM);
+		doc_node.setAttribute(GSXML.NODE_ID_ATT, line);
+		Element meta_list = this.doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
+		doc_node.appendChild(meta_list);
+		while  ((line = reader.readLine()) != null) {
+		    //metadata entry
+		    int col_pos = line.indexOf(':');
+		    if (col_pos == -1) {
+			// end of the metadata for this doc
+			break; 
+		    }
+		    String name = line.substring(0,col_pos);
+		    String value = line.substring(col_pos+2); // includes a space
+		    GSXML.addMetadata(this.doc, meta_list, name, value);
+		}
+		node_list.appendChild(doc_node);
+		
+	    }
+	} catch (Exception e) {
+	    logger.error("exception happened");
+	    e.printStackTrace();
+	}
+	logger.debug("IViaProxy: returning result: ");
+	logger.debug(this.converter.getPrettyString(result));
+	return result;
+ 
+    }
+
+    protected Element processDocumentContentRetrieve(Element request) {
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	result.setAttribute(GSXML.FROM_ATT, DOC_CONTENT_SERVICE);
+	result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+	
+	// Get the request doc_list
+	Element query_doc_list = (Element) GSXML.getChildByTagName(request, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	if (query_doc_list == null) {
+	    logger.error("DocumentContentRetrieve request specified no doc nodes.\n");
+	    return result;
+	}
+
+	Element doc_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	result.appendChild(doc_list);
+	
+	// Get the documents
+	String[] doc_ids = GSXML.getAttributeValuesFromList(query_doc_list, 
+						     GSXML.NODE_ID_ATT);
+	for (int i = 0; i < doc_ids.length; i++) {
+	    String doc_id = doc_ids[i];
+	    Element doc_node = getDocument(doc_id); 
+	    doc_list.appendChild(doc_node);
+	}
+	return result;
+
+    }
+
+
+    /** gets a document by sending a request to iVia, then processes it and creates a documentNode around the text */
+    protected Element getDocument(String doc_id) {
+
+	String url_string = ivia_server_url+"/cgi-bin/view_record?theme=gsdl3&record_id="+doc_id;
+	StringBuffer buffer = new StringBuffer();
+	try {
+	    BufferedReader reader = makeConnection(url_string);
+    
+	    String line;
+	    while((line = reader.readLine())!= null) {
+		buffer.append(line);
+	    }
+
+	    
+	} catch (Exception e) {
+	    logger.error("exception happened");
+	    e.printStackTrace();
+	}
+	
+	String node_content = buffer.toString(); 
+	String escaped_content = GSXML.xmlSafe(node_content);
+	
+	StringBuffer processed_content = new StringBuffer(escaped_content.length());
+	processed_content.append("<nodeContent>");
+	int pos = 0;
+	int lastpos = 0;
+	while ((pos = escaped_content.indexOf("&lt;a ", lastpos))!= -1) {
+	    processed_content.append(escaped_content.substring(lastpos, pos));
+	    int endpos = escaped_content.indexOf("&lt;/a&gt;", pos);
+	    if (endpos == -1) {
+		break;
+	    }
+	    String link = escaped_content.substring(pos, endpos+10);
+	    link = convertLink(link);
+	    processed_content.append(link);
+	    lastpos = endpos+10;
+	}
+	processed_content.append(escaped_content.substring(lastpos)); // get the last bit
+	processed_content.append("</nodeContent>");
+	    
+	Element doc_node = this.doc.createElement(GSXML.DOC_NODE_ELEM);
+	doc_node.setAttribute(GSXML.NODE_ID_ATT, doc_id);
+	
+	Document content_doc = this.converter.getDOM(processed_content.toString());
+	if (content_doc != null) {
+	    Element content_element = content_doc.getDocumentElement();
+	    doc_node.appendChild(this.doc.importNode(content_element, true));
+	} else {
+	    logger.error("Couldn't parse the node content");
+	}
+	return doc_node;
+	
+    }
+
+    /** converts a url from an <a> element into a greenstone suitable one */
+    protected String convertLink(String aref) {
+	
+	if (aref.indexOf("href=&quot;http") != -1) {
+	    return aref; // an external link
+	}
+	String type = "other";
+	if (aref.indexOf("/cgi-bin/canned_search")!=-1) {
+	    type="query";
+	} else if (aref.indexOf("/cgi-bin/click_through") != -1) {
+	    type = "external";
+	} else if (aref.indexOf("/cgi-bin/view_record") != -1) {
+	    type="document";
+	} 
+	
+	int href_start = aref.indexOf("href=&quot;")+11;
+	int href_end = aref.indexOf("&gt;", href_start);
+	String href = aref.substring(href_start, href_end);
+	String link_content = aref.substring(href_end+4, aref.length()-10);
+	
+	if (type.equals("external")) {
+	    // the external link is everything after the http at the end.
+	    String address = href.substring(href.lastIndexOf("http"));
+	    address = address.replaceAll("%3[aA]", ":");
+	    address = address.replaceAll("%2[fF]", "/");
+
+	    return "&lt;a href=\""+address+"\"&gt;"+link_content+"&lt;/a&gt;";
+	}
+	if (type.equals("other")) {
+	    return "other type of link ("+link_content+")";
+	}
+	StringBuffer result = new StringBuffer();
+	result.append("<link type='");
+	result.append(type);
+	result.append("'");
+	if (type.equals("query")) {
+	    result.append(" service='TextQuery'");
+	}
+	result.append(">");
+	// add in the parameters
+	href = href.substring(href.indexOf("?")+1);
+	String [] params = href.split("&amp;");
+	for (int i=0; i<params.length; i++) {
+	    String param = params[i];
+	    int eq_pos = param.indexOf("=");
+	    if (eq_pos != -1) {
+		
+		result.append("<param name='"+param.substring(0, eq_pos)+"' value='"+param.substring(eq_pos+1)+"'/>");
+	    }
+	}
+	result.append(link_content);
+	result.append("</link>");
+
+	return result.toString();
+	    
+    }
+
+    // iVia craps out if we ask for a metadata which is not valid. So need
+    // to make sure we only ask for acceptable fields.
+    protected boolean isAcceptableMetadata(String meta) {
+	String valid_metadata = ",title,url,ivia_description,keywords,subjects,";
+	if (valid_metadata.indexOf(","+meta+",")!=-1) {
+	    return true;
+	}
+	return false;
+    }
+    protected BufferedReader makeConnection(String url_string) {
+	BufferedReader reader = null;
+	try {
+	    URL url = new URL(url_string);
+	    HttpURLConnection connection = (HttpURLConnection)url.openConnection();
+	    InputStream input = connection.getInputStream();
+	    reader = new BufferedReader(new InputStreamReader(input));  
+	} catch (java.net.MalformedURLException e) {
+
+	    logger.error("Malformed URL: "+url_string);
+	} catch (java.io.IOException e) {
+	    logger.error("An error occurred during IO to url "+url_string);
+	}
+	return reader;
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/IViaRetrieve.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/IViaRetrieve.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/IViaRetrieve.java	(revision 13928)
@@ -0,0 +1,262 @@
+package org.greenstone.gsdl3.service;
+
+// Greenstone classes
+import org.greenstone.gsdl3.core.GSException;
+import org.greenstone.gsdl3.util.*;
+
+// XML classes
+import org.w3c.dom.Element; 
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList; 
+
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.io.File;
+import java.io.InputStream;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URLConnection;
+import java.net.URL;
+import java.net.Authenticator;
+import java.net.MalformedURLException;
+
+import org.apache.log4j.*;
+
+/**
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ * @version $Revision$
+ * Modified by  <a href="mailto:chi@cs.waikato.ac.nz">Chi-Yu Huang</a>
+ */
+
+public class IViaRetrieve 
+    extends AbstractDocumentRetrieve {
+
+      static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.IViaRetrieve.class.getName());
+    
+
+    protected String ivia_server_url = null;
+    
+    public IViaRetrieve() {
+	does_structure = false;
+    }
+    
+    //Configure IViaRetrieve Service
+    public boolean configure(Element info, Element extra_info) 
+    {
+	if (!super.configure(info, extra_info)) {
+	    return false;
+	}
+	
+	Element server_elem = (Element)GSXML.getChildByTagName(info, "iViaServer");
+	if (server_elem == null) {
+	    logger.error("no iViaServer element found");
+	    return false;
+	}
+	ivia_server_url = server_elem.getAttribute("url");
+	if (ivia_server_url.equals("")) {
+	    logger.error("no url for the iViaServer element");
+	    return false;
+	}
+	return true;
+	
+    }
+        
+    /** gets a document by sending a request to iVia, then processes it and creates a documentNode around the text */
+    protected Element getNodeContent(String doc_id, String lang) 
+	throws GSException {
+
+	String url_string = ivia_server_url+"/cgi-bin/view_record?theme=gsdl3&record_id="+doc_id;
+
+	StringBuffer buffer = new StringBuffer();
+	try {
+	    BufferedReader reader = Misc.makeHttpConnection(url_string);
+    	    String line;
+	    while((line = reader.readLine())!= null) {
+		buffer.append(line);
+	    }
+   	} catch (java.net.MalformedURLException e) {
+	    throw new GSException("Malformed URL: "+url_string, GSXML.ERROR_TYPE_SYSTEM);
+	} catch (java.io.IOException e) {
+	    throw new GSException("IOException during connection to "+url_string+": "+e.toString(),GSXML.ERROR_TYPE_SYSTEM);
+	}
+
+	String node_content = buffer.toString(); 
+
+	String escaped_content = GSXML.xmlSafe(node_content);
+	
+	StringBuffer processed_content = new StringBuffer(escaped_content.length());
+	processed_content.append("<nodeContent>");
+	int pos = 0;
+	int lastpos = 0;
+	while ((pos = escaped_content.indexOf("&lt;a ", lastpos))!= -1) {
+	    processed_content.append(escaped_content.substring(lastpos, pos));
+	    int endpos = escaped_content.indexOf("&lt;/a&gt;", pos);
+	    if (endpos == -1) {
+		break;
+	    }
+	    String link = escaped_content.substring(pos, endpos+10);
+	    link = convertLink(link);
+	    processed_content.append(link);
+	    lastpos = endpos+10;
+	}
+	processed_content.append(escaped_content.substring(lastpos)); // get the last bit
+	processed_content.append("</nodeContent>");
+	    
+	Document content_doc = this.converter.getDOM(processed_content.toString());
+	if (content_doc == null) {
+	    logger.error("Couldn't parse node content");
+	    logger.error(processed_content.toString());
+	    return null;
+	}
+	
+	Element content_element = content_doc.getDocumentElement();
+
+	return (Element)this.doc.importNode(content_element,true);
+    }
+	
+    /** converts a url from an <a> element into a greenstone suitable one */
+    protected String convertLink(String aref) {
+	if (aref.indexOf("href=&quot;http") != -1) {
+	    return aref; // an external link
+	}
+	String type = "other";
+	if (aref.indexOf("/cgi-bin/canned_search")!=-1) {
+	    type="query";
+	} else if (aref.indexOf("/cgi-bin/click_through") != -1) {
+	    type = "external";
+	} else if (aref.indexOf("/cgi-bin/view_record") != -1) {
+	    type="document";
+	} 
+	
+	int href_start = aref.indexOf("href=&quot;")+11;
+	int href_end = aref.indexOf("&gt;", href_start);
+	String href = aref.substring(href_start, href_end);
+	String link_content = aref.substring(href_end+4, aref.length()-10);
+	
+	if (type.equals("external")) {
+	    // the external link is everything after the http at the end.
+	    String address = href.substring(href.lastIndexOf("http"));
+	    address = address.replaceAll("%3[aA]", ":");
+	    address = address.replaceAll("%2[fF]", "/");
+
+	    return "&lt;a href=\""+address+"\"&gt;"+link_content+"&lt;/a&gt;";
+	}
+	if (type.equals("other")) {
+	    return "other type of link ("+link_content+")";
+	}
+	StringBuffer result = new StringBuffer();
+	result.append("<link type='");
+	result.append(type);
+	result.append("'");
+	if (type.equals("query")) {
+	    result.append(" service='TextQuery'");
+	}
+	result.append(">");
+	// add in the parameters
+	href = href.substring(href.indexOf("?")+1);
+	String [] params = href.split("&amp;");
+	for (int i=0; i<params.length; i++) {
+	    String param = params[i];
+	    int eq_pos = param.indexOf("=");
+	    if (eq_pos != -1) {
+		
+		result.append("<param name='"+param.substring(0, eq_pos)+"' value='"+param.substring(eq_pos+1)+"'/>");
+	    }
+	}
+	result.append(link_content);
+	result.append("</link>");
+
+	return result.toString();
+    }
+
+    // iVia craps out if we ask for a metadata which is not valid. So need
+    // to make sure we only ask for acceptable fields.
+    protected boolean isAcceptableMetadata(String meta) {
+	String valid_metadata = ",title,url,ivia_description,keywords,subjects,";
+	if (valid_metadata.indexOf(","+meta+",")!=-1) {
+	    return true;
+	}
+	return false;
+    }
+
+    protected String translateId(String oid){
+	int p = oid.lastIndexOf('.');
+	if (p != oid.length()-3) {
+	    logger.info("translateoid error: '.' is not the third to last char!!");
+	    return oid;
+	}
+	String top = oid.substring(0, p);
+	return top;
+    }
+
+    protected String translateExternalId(String id){
+	return id;
+    }
+
+    protected String getDocType(String node_id){
+    	return GSXML.DOC_TYPE_SIMPLE;
+    }
+    protected String getRootId(String node_id){
+   	return node_id; 
+    }
+
+    protected ArrayList getChildrenIds(String node_id){
+	return null; 
+    }
+    
+    protected String getParentId(String node_id){
+	return null;
+    }
+    
+    protected Element getMetadataList (String doc_id,
+				       boolean all_metadata,
+				       ArrayList metadata_names) 
+	throws GSException {
+	
+	Element meta_list = this.doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
+
+	// do the query to the iVia server
+	StringBuffer field_list= new StringBuffer();
+	boolean metadata_found = false;
+
+	for (int i=0; i<metadata_names.size();i++){
+	    if (isAcceptableMetadata((String)metadata_names.get(i))){
+		metadata_found = true;
+		field_list.append((String)metadata_names.get(i));
+		field_list.append(",");
+	    }
+	}
+	if (!metadata_found){
+	    return meta_list;
+	}
+	
+	String url_string = ivia_server_url+"/cgi-bin/view_record_set?theme=gsdl3&record_id_list="+doc_id+"&field_list="+field_list.toString(); 
+	try {
+	    BufferedReader reader = Misc.makeHttpConnection(url_string);
+	    String line;
+	    while  ((line = reader.readLine()) != null) {
+		//metadata entry
+		int col_pos = line.indexOf(':');
+		if (col_pos == -1) {
+		    // end of the metadata for this doc
+		    break; 
+		}
+		String name = line.substring(0,col_pos);
+		String value = line.substring(col_pos+2); // includes a space
+		GSXML.addMetadata(this.doc, meta_list, name, value);
+	    }
+	} catch (java.net.MalformedURLException e) {
+	    throw new GSException("Malformed URL: "+url_string, GSXML.ERROR_TYPE_SYSTEM);
+	} catch (java.io.IOException e) {
+	    throw new GSException("IOException: "+e.toString(), GSXML.ERROR_TYPE_SYSTEM);
+	}
+	return meta_list;
+    }
+    
+    protected String getStructureInfo(String doc_id, String info_type){
+	return "";	
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/IViaSearch.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/IViaSearch.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/IViaSearch.java	(revision 13928)
@@ -0,0 +1,206 @@
+package org.greenstone.gsdl3.service;
+
+// Greenstone classes
+import org.greenstone.gsdl3.util.*;
+
+// XML classes
+import org.w3c.dom.Element; 
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList; 
+
+//Java classes
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.io.File;
+import java.io.BufferedReader;
+import java.net.Authenticator;
+
+import org.apache.log4j.*;
+
+/**
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ * @author <a href="mailto:chi@cs.waikato.ac.nz">Chi-Yu Huang</a>
+ */
+
+public class IViaSearch
+    extends AbstractSearch {
+    
+
+     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.IViaSearch.class.getName());
+ 
+    // have standard gs param names for hits per page, and start page
+    // these need to be mapped to iVia params
+    protected static final String IM_HITS_PARAM = "no_of_records_per_page";
+    protected static final String IM_START_PAGE_PARAM = "start_page_no";
+
+    protected String ivia_server_url = null;
+    protected ArrayList index_ids = null;
+    public IViaSearch()
+    {
+    }
+    
+    //Configure IViaSearch Service
+    public boolean configure(Element info, Element extra_info) 
+    { 
+	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+
+	Element server_elem = (Element)GSXML.getChildByTagName(info, "iViaServer");
+	if (server_elem == null) {
+	    logger.error("no iViaServer element found");
+	    return false;
+	}
+	ivia_server_url = server_elem.getAttribute("url");
+	if (ivia_server_url.equals("")) {
+	    logger.error("no url for the iViaServer element");
+	    return false;
+	}
+	does_paging = true;
+	does_multi_index_search = true;
+	this.default_index = ",kw,au,su,ti,de,fu,"; // all of them
+	index_ids = new ArrayList();
+	index_ids.add("kw");
+	index_ids.add("au");	
+	index_ids.add("su");	
+	index_ids.add("ti");
+	index_ids.add("de");
+	index_ids.add("fu");
+
+	return true;
+    }
+    
+    /** Process a text query - implemented by concrete subclasses */
+    protected Element processTextQuery(Element request) {
+	// Create a new (empty) result message
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	result.setAttribute(GSXML.FROM_ATT, TEXT_QUERY_SERVICE);
+	result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+	Element doc_node_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	result.appendChild(doc_node_list);
+	Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	if (param_list == null) {
+	    logger.error("TextQuery request had no paramList.");
+	    return result;  // Return the empty result
+	}
+
+	// Process the request parameters
+	HashMap params = GSXML.extractParams(param_list, false);
+
+	// Make sure a query has been specified
+	String query = (String) params.get(QUERY_PARAM);
+	if (query == null || query.equals("")) {
+	    return result;  // Return the empty result
+	}
+
+	// tidy whitespace
+	query = query.replaceAll("\\s+", "+");
+	String url_string = ivia_server_url+"/cgi-bin/canned_search?theme=gsdl3&query="+query; 
+
+	// check for fields
+	String fields = (String) params.get(INDEX_PARAM);
+	fields = checkFieldParam(fields); // removes invalid fields
+	if (!fields.equals("")) {
+	    url_string += "&fields="+fields;
+	}
+	//check for hits per page
+	String hits_per_page = (String) params.get(HITS_PER_PAGE_PARAM);
+	if (hits_per_page != null && !hits_per_page.equals("")) {
+	    url_string += "&"+IM_HITS_PARAM+"="+hits_per_page;
+	}
+
+	// check for start page
+	String start_page = (String) params.get(START_PAGE_PARAM);
+	if (start_page != null && !start_page.equals("")) {
+	    url_string += "&"+IM_START_PAGE_PARAM+"="+start_page;
+	}
+	String results_num = null;
+	String doc_ids = null;
+	BufferedReader reader = null;
+	try {
+	    logger.debug("sending "+url_string);
+	    reader = Misc.makeHttpConnection(url_string);
+	    results_num = reader.readLine();
+	    doc_ids = reader.readLine();
+	} catch (java.net.MalformedURLException e) {
+	    GSXML.addError(this.doc, result, "Malformed URL: "+url_string);
+	    return result;
+	} catch (java.io.IOException e) {
+	    GSXML.addError(this.doc, result, "IOException during connection to "+url_string+": "+e.toString());
+	    return result;
+	}
+	    
+	if (results_num.startsWith("Resources: ") && doc_ids.startsWith("Ids: ")) {
+	    results_num = results_num.substring(11);
+	    doc_ids = doc_ids.substring(5).trim();
+
+	} else {
+	    logger.error("badly formatted results:");
+	    StringBuffer result_string = new StringBuffer();
+	    result_string.append("Error: badly formatted result from IVia server:\n ");
+	    result_string.append(results_num);
+	    result_string.append(doc_ids);
+	    String line;
+	    try {
+		while((line = reader.readLine()) != null) {
+		    result_string.append(line);
+		}
+	    } catch (Exception e) {
+		result_string.append("Exception: "+e);
+	    }
+	    GSXML.addError(this.doc, result, result_string.toString());
+	    
+	    return result;
+	}
+	
+	// get the num docs and add to a metadata list
+	Element metadata_list = this.doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER); 
+	result.appendChild(metadata_list);
+	
+	// Add a metadata element specifying the number of matching documents
+	long numdocs = Long.parseLong(results_num);
+	GSXML.addMetadata(this.doc, metadata_list, "numDocsMatched", ""+numdocs);	
+	String [] ids = doc_ids.split(" ");
+	
+	for (int d=0; d<ids.length; d++) {
+	    Element doc_node = this.doc.createElement(GSXML.DOC_NODE_ELEM);
+	    doc_node.setAttribute(GSXML.NODE_ID_ATT, ids[d]);
+	    doc_node_list.appendChild(doc_node);
+	}
+	return result;
+    }
+     
+    protected String checkFieldParam(String fields) {
+	
+	if (fields == null) {
+	    // return the default
+	    return "";
+	}
+	StringBuffer new_fields = new StringBuffer();
+	String [] ids = fields.split(",");
+	for (int i=0; i<ids.length; i++) {
+	    if(index_ids.contains(ids[i])) {
+		new_fields.append(ids[i]);
+		new_fields.append(",");
+	    }
+	}
+	if (new_fields.length() == 0) {
+	    return "";
+	}
+	return new_fields.toString();
+    }
+    /**
+       An IVia server has a fixed list of fields to search (I think) so we can hard code them here rather than reading them in from a config file
+    */
+    protected void getIndexData(ArrayList index_ids, ArrayList index_names,String lang){
+	index_ids.addAll(this.index_ids);
+	index_names.add(getTextString("param."+INDEX_PARAM+".kw", lang)); 
+	index_names.add(getTextString("param."+INDEX_PARAM+".au", lang));
+	index_names.add(getTextString("param."+INDEX_PARAM+".su", lang));
+	index_names.add(getTextString("param."+INDEX_PARAM+".ti", lang));
+	index_names.add(getTextString("param."+INDEX_PARAM+".de", lang));
+	index_names.add(getTextString("param."+INDEX_PARAM+".fu", lang));
+    }
+    
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/LuceneSearch.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/LuceneSearch.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/LuceneSearch.java	(revision 13928)
@@ -0,0 +1,137 @@
+package org.greenstone.gsdl3.service;
+
+// Greenstone classes
+import org.greenstone.gsdl3.util.*;
+
+// XML classes
+import org.w3c.dom.Element; 
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList; 
+
+import java.util.HashMap;
+import java.util.ArrayList;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.document.*; //Document;
+import org.apache.lucene.search.Searcher;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.Hits;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.index.Term;
+
+import java.io.File;
+
+import org.apache.log4j.*;
+
+/**
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ * @version $Revision$
+ */
+
+public class LuceneSearch 
+    extends AbstractSearch {
+
+     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.LuceneSearch.class.getName());
+
+    protected static final String INDEX_ELEM = "index";
+    
+    public boolean configure(Element info, Element extra_info) {
+	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+	
+	default_index = "idx";
+	return true;
+    }
+    
+    protected void getIndexData(ArrayList index_ids, ArrayList index_names, String lang) 
+    {
+	// the index info - read from config file - cache it??
+	Element index_list = (Element)GSXML.getChildByTagName(this.config_info, INDEX_ELEM+GSXML.LIST_MODIFIER);
+	if (index_list != null) {
+	    NodeList indexes = index_list.getElementsByTagName(INDEX_ELEM);
+	    int len = indexes.getLength();
+	    // now add even if there is only one
+	    for (int i=0; i<len; i++) {
+		Element index = (Element)indexes.item(i);
+		index_ids.add(index.getAttribute(GSXML.NAME_ATT));
+		index_names.add(GSXML.getDisplayText(index, GSXML.DISPLAY_TEXT_NAME, lang, "en"));
+		
+	    }
+	} else {
+	    // there is only one index, so we assume the default
+	    index_ids.add(this.default_index);
+	    index_names.add("Default index");
+	}
+
+    }
+
+    /** Process a text query - implemented by concrete subclasses */
+    protected Element processTextQuery(Element request) {
+
+	// Create a new (empty) result message
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	result.setAttribute(GSXML.FROM_ATT, TEXT_QUERY_SERVICE);
+	result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+	Element doc_node_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	result.appendChild(doc_node_list);
+	Element metadata_list = this.doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
+	result.appendChild(metadata_list);
+	// Get the parameters of the request
+	Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	if (param_list == null) {
+	    logger.error("TextQuery request had no paramList.");
+	    GSXML.addMetadata(this.doc, metadata_list, "numDocsMatched", "0");
+	    return result;  // Return the empty result
+	}
+
+	// Process the request parameters
+	HashMap params = GSXML.extractParams(param_list, false);
+
+	// Make sure a query has been specified
+	String query_string = (String) params.get(QUERY_PARAM);
+	if (query_string == null || query_string.equals("")) {
+	    logger.error("TextQuery request had no query string.");
+	    GSXML.addMetadata(this.doc, metadata_list, "numDocsMatched", "0");
+	    return result;  // Return the empty result
+	}
+
+	// Get the index
+	String index = (String) params.get(INDEX_PARAM);
+	if (index == null || index.equals("")) {
+	    index = this.default_index; // assume the default
+	}
+        try {
+	    String index_dir = GSFile.collectionIndexDir(this.site_home, this.cluster_name);
+	    index_dir += File.separator+index;
+	    Searcher searcher = new IndexSearcher(index_dir);
+	    Analyzer analyzer = new StandardAnalyzer();
+	    
+	    Term term = new Term("content", query_string);
+        
+	    Query query = new TermQuery(term);
+
+	    Hits hits = searcher.search(query);
+	    GSXML.addMetadata(this.doc, metadata_list, "numDocsMatched", ""+hits.length());
+	    
+	    for (int i=0; i<hits.length(); i++) {
+		org.apache.lucene.document.Document luc_doc = hits.doc(i);
+		String node_id = luc_doc.get("nodeID");
+		Element node = this.doc.createElement(GSXML.DOC_NODE_ELEM);
+		node.setAttribute(GSXML.NODE_ID_ATT, node_id);
+		doc_node_list.appendChild(node);
+	    }
+	} catch (Exception e) {
+	    e.printStackTrace();
+	}
+	
+	return result;
+	    
+    }
+
+    
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/MapRetrieve.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/MapRetrieve.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/MapRetrieve.java	(revision 13928)
@@ -0,0 +1,840 @@
+package org.greenstone.gsdl3.service;
+
+// Greenstone classes
+import org.greenstone.gsdl3.util.*;
+
+// XML classes
+import org.w3c.dom.Document;
+import org.w3c.dom.Element; 
+import org.w3c.dom.NodeList;
+
+// General Java classes
+import java.io.File;
+import java.io.*;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import java.util.Set;
+import java.util.Iterator;
+import java.lang.reflect.Array;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import javax.swing.tree.DefaultMutableTreeNode;
+
+import org.apache.log4j.*;
+
+public class MapRetrieve
+    extends ServiceRack {
+
+    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.MapRetrieve.class.getName());
+
+    // the services on offer
+    protected static final String DOCUMENT_STRUCTURE_RETRIEVE_SERVICE = "DocumentStructureRetrieve";
+    protected static final String DOCUMENT_METADATA_RETRIEVE_SERVICE = "DocumentMetadataRetrieve";
+    protected static final String DOCUMENT_CONTENT_RETRIEVE_SERVICE = "DocumentContentRetrieve";
+
+    protected static final int DOCUMENT=1;
+
+    protected ArrayList index_name_list = null;
+    protected ArrayList index_display_list = null;
+    protected String files_home_dir = null; 
+    protected String temp_files_dir = null;
+    //protected String temp_image_file = null;
+    //protected String temp_image_file2 = null;
+    protected final String jpg_ext = ".jpg";
+    protected String http_image_dir = null;
+    protected String http_temp_image_dir = null;
+    private LinkedList namesInList = new LinkedList();
+
+    private DefaultMutableTreeNode tree;
+
+    /** constructor */
+    public MapRetrieve() {}
+
+
+    /** configure this service */
+    public boolean configure(Element info, Element extra_info)
+    {
+	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+
+	logger.info("Configuring MapRetrieve...");
+	this.config_info = info;
+
+	// set up short_service_info_ - for now just has name and type
+	Element dmr_service = doc.createElement(GSXML.SERVICE_ELEM);
+	dmr_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
+	dmr_service.setAttribute(GSXML.NAME_ATT, DOCUMENT_METADATA_RETRIEVE_SERVICE);
+	short_service_info.appendChild(dmr_service);
+
+	Element dcr_service = doc.createElement(GSXML.SERVICE_ELEM);
+	dcr_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
+	dcr_service.setAttribute(GSXML.NAME_ATT, DOCUMENT_CONTENT_RETRIEVE_SERVICE);
+	short_service_info.appendChild(dcr_service);
+
+	Element dsr_service = doc.createElement(GSXML.SERVICE_ELEM);
+	dsr_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
+	dsr_service.setAttribute(GSXML.NAME_ATT, DOCUMENT_STRUCTURE_RETRIEVE_SERVICE);
+	short_service_info.appendChild(dsr_service);
+
+	// set the files_home variable for this collection
+	this.files_home_dir = GSFile.collectionIndexDir(this.site_home, this.cluster_name)+ File.separator+"assoc"+File.separator; 
+	this.temp_files_dir = GSFile.collectionBaseDir(this.site_home, this.cluster_name) + File.separator + "temp"+File.separator; 
+
+	    //this.files_home_dir + "maps" + File.separator + "temp" + File.separator;
+	//this.temp_image_file = this.temp_files_dir+"temp_";
+	//this.temp_image_file2 = this.temp_files_dir+"temp2_";
+	
+	
+	this.http_image_dir = this.site_http_address + "/collect/"+this.cluster_name+"/index/assoc/maps/";
+	this.http_temp_image_dir = this.site_http_address + "/collect/"+this.cluster_name+"/temp/";
+
+	this.index_name_list = new ArrayList();
+	this.index_display_list = new ArrayList();
+	Element index_list = (Element)GSXML.getChildByTagName(this.config_info, GSXML.INDEX_ELEM+GSXML.LIST_MODIFIER);
+	Element display_index_list = (Element)GSXML.getChildByTagName(extra_info, "search");
+	if (index_list != null && display_index_list != null) {
+	    NodeList indexes = index_list.getElementsByTagName(GSXML.INDEX_ELEM);
+	    for (int i=0; i<indexes.getLength(); i++) {
+		String name = ((Element)indexes.item(i)).getAttribute(GSXML.NAME_ATT);
+		// add the index name
+		this.index_name_list.add(name);
+		// now look for the display name
+		Element this_index = GSXML.getNamedElement(display_index_list, "index", "name", name);
+		if (this_index != null) {
+		    Element disp = GSXML.getNamedElement(this_index, "displayItem", "name", "name");
+		    if (disp != null) {
+			String display = GSXML.getNodeText(disp);
+			if (!display.equals("")) {
+			    this.index_display_list.add(display);
+			    continue;
+			}
+			
+		    }
+		}
+		// add the id as default text
+		this.index_display_list.add(name);
+
+	    }
+	}
+
+	// look for document display format
+	String path = GSPath.appendLink(GSXML.DISPLAY_ELEM, GSXML.FORMAT_ELEM);
+	Element display_format = (Element)GSXML.getNodeByPath(extra_info, path);
+	if (display_format != null) {
+	    this.format_info_map.put(DOCUMENT_CONTENT_RETRIEVE_SERVICE, this.doc.importNode(display_format, true));
+	    // shoudl we make a copy?
+	}
+
+	// load the 2-dimensional tree for searching
+	try{
+	    ObjectInputStream objectin = new ObjectInputStream(new FileInputStream(this.files_home_dir+"nametree.dat"));
+	    tree = (DefaultMutableTreeNode)objectin.readObject();
+	    objectin.close();
+	}catch(IOException ioe){
+	    ioe.printStackTrace();
+	}catch(ClassNotFoundException cnfe){
+	    cnfe.printStackTrace();
+	}
+    
+
+	return true;
+    }
+
+    /** */
+    protected Element getServiceDescription(String service, String lang, String subset) 
+    {
+	if (service.equals(DOCUMENT_STRUCTURE_RETRIEVE_SERVICE)) {
+	    
+	    Element tq_service = doc.createElement(GSXML.SERVICE_ELEM);
+	    tq_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_QUERY);
+	    tq_service.setAttribute(GSXML.NAME_ATT, DOCUMENT_STRUCTURE_RETRIEVE_SERVICE);
+	    return tq_service;
+	}
+	else if (service.equals(DOCUMENT_METADATA_RETRIEVE_SERVICE)) {
+	    
+	    Element tq_service = doc.createElement(GSXML.SERVICE_ELEM);
+	    tq_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_QUERY);
+	    tq_service.setAttribute(GSXML.NAME_ATT, DOCUMENT_METADATA_RETRIEVE_SERVICE);
+	    return tq_service;
+	}
+	else if (service.equals(DOCUMENT_CONTENT_RETRIEVE_SERVICE)) {
+	    
+	    Element tq_service = doc.createElement(GSXML.SERVICE_ELEM);
+	    tq_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_QUERY);
+	    tq_service.setAttribute(GSXML.NAME_ATT, DOCUMENT_CONTENT_RETRIEVE_SERVICE);
+	    return tq_service;
+	}
+
+	return null;
+	
+    }
+
+    /** Retrieve the structure of a document */
+    protected Element processDocumentStructureRetrieve(Element request)
+    {
+	// Create a new (empty) result message
+	Element result = doc.createElement(GSXML.RESPONSE_ELEM);
+	return result;
+    }
+
+    protected Element processDocumentMetadataRetrieve(Element request) {
+	// Create a new (empty) result message
+	try{
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+
+	String uid = request.getAttribute(GSXML.USER_ID_ATT);
+	if (uid.equals("")) {
+	    logger.info("in metadata retrieve, uid = ''\n"+converter.getPrettyString(request));
+	}
+	result.setAttribute(GSXML.FROM_ATT, DOCUMENT_METADATA_RETRIEVE_SERVICE);
+	result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+
+	// Get the parameters of the request
+	Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	if (param_list == null) {
+	    logger.error("missing paramList.\n");
+	    return result;  // Return the empty result
+	}
+
+	// The metadata information required
+	Vector metadata_list = new Vector();
+	boolean all_metadata = false;
+	// Process the request parameters
+	Element param = (Element) param_list.getFirstChild();
+
+	while (param != null) {
+	    // Identify the metadata information desired
+	    if (param.getAttribute(GSXML.NAME_ATT).equals("metadata")) {
+		String metadata = GSXML.getValue(param);
+		if (metadata.equals("all")) {
+		    all_metadata = true;
+		    break;
+		}
+		metadata_list.add(metadata);
+	    }
+	    param = (Element) param.getNextSibling();
+	}
+
+	Element node_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	result.appendChild(node_list);
+	
+	// Get the documents
+	Element request_node_list = (Element) GSXML.getChildByTagName(request, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	if (request_node_list == null) {
+	    logger.error(" DocumentMetadataRetrieve request had no "+GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+ 	    return result;
+ 	}
+
+	NodeList request_nodes = request_node_list.getChildNodes();
+
+	try{
+	    //used just to ensure outfile is initialised
+	    BufferedWriter outfile = new BufferedWriter(new FileWriter(this.temp_files_dir+"emptynothingness"));
+	    
+	    for (int i = 0; i < request_nodes.getLength(); i++) {
+		Element request_node = (Element) request_nodes.item(i);
+		String node_id = request_node.getAttribute(GSXML.NODE_ID_ATT);
+		String place_data = "";
+		String year = "";
+		String coOrdinates = "";
+		String thumb = "";
+		String link = "";
+		int mapFreq = 0;
+		LinkedList place_data_list = new LinkedList();
+		LinkedList coOrdinates_list = new LinkedList();
+
+		//if this is a first displaying of the map
+		if(node_id.indexOf("```") != -1 && node_id.indexOf("imageChooser") == -1){
+		    //get the number of query terms on this map
+		    mapFreq = Integer.parseInt(node_id.substring(node_id.lastIndexOf('`',node_id.indexOf("```")-1)+1,node_id.indexOf("```")));
+		    //get the place names on this map
+		    place_data = node_id.substring(node_id.indexOf("```")+3,node_id.length());
+		    //get the map metadata
+		    node_id = node_id.substring(0,node_id.indexOf('`',node_id.indexOf("```")));
+		    
+		    try{
+			// loop for each query term on the map
+			for(int r=0; r<mapFreq; r++){
+			    // get title, type, location, and the string for creating the hyperlink for this query term
+			    String title = place_data.substring(0,place_data.indexOf('`'));
+			    String type = place_data.substring(place_data.indexOf('`')+1,place_data.indexOf('`',place_data.indexOf('`')+1));
+			    String location = place_data.substring(place_data.indexOf('`',place_data.indexOf('`')+1)+1, place_data.indexOf('`',place_data.indexOf('`',place_data.indexOf('`')+1)+1));
+			    if(place_data.indexOf("```") != -1)
+				link=place_data.substring(0,place_data.indexOf("```"));
+			    else
+				link=place_data;
+			    // resolve the type and location
+			    type = getType(type);
+			    location = getLocation(location);
+			    // remove this query term from the string
+			    if(place_data.indexOf("```") != -1)
+				place_data = place_data.substring(place_data.indexOf("```")+3,place_data.length());
+			    
+			    //add the co-ordinates of this query term to the co-ordinates list
+			    coOrdinates_list.add("`"+link.substring(link.lastIndexOf('`')+1,link.length())+"`"+link.substring(link.lastIndexOf('`',link.lastIndexOf('`')-1)+2,link.lastIndexOf('`')));
+			    
+			    // add the title, type and location to the places list
+			    place_data_list.add(title + ", " + type + ", " + location + ";");
+			}
+		    }catch(StringIndexOutOfBoundsException sioobe){sioobe.printStackTrace();}
+		}
+		
+		// Add the document to the list
+		Element new_node = (Element)this.doc.importNode(request_node, false);
+		node_list.appendChild(new_node);
+		
+		// Add the requested metadata information
+		Element node_meta_list = this.doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
+		new_node.appendChild(node_meta_list);
+		
+		// create the navigation thumbnails.  This doesn't seem to work most of the time ???????
+		for (int m = 0; m < metadata_list.size(); m++) {
+		    String metadata = (String) metadata_list.get(m);
+		    thumb = "";
+		    String value = "";
+		    if(node_id.indexOf('.') != -1) 
+			thumb = node_id.substring(0,node_id.indexOf('.'));
+		    if(node_id.indexOf('`') != -1) 
+			value = node_id.substring(node_id.lastIndexOf('`',node_id.lastIndexOf('`')-1)+1,node_id.lastIndexOf('`',node_id.lastIndexOf('`')-1)+5);
+		    year = value;
+		    
+		    place_data="";
+		    if(place_data_list.size() != 0)
+			for(int q=0; q<mapFreq; q++){
+			    link = (String)place_data_list.get(q);
+			    if(q!=0){
+				place_data = place_data + "<br>" + link;
+			    }
+			    else{
+				place_data = link;
+				coOrdinates = "``";
+			    }
+			    coOrdinates = coOrdinates+(String)coOrdinates_list.get(q);
+			}
+		    
+		    link = "<a href=\"?a=d&c="+this.cluster_name+"&d="+node_id+coOrdinates+"&dt=map\">";
+		    thumb = "<img src=\""+this.http_image_dir + thumb + "thumb.jpg\" border=0>";
+		    value = "<table><tr><td>"+link+"<p>"+place_data+"<br>"+value+"</a></td><td>"+link+thumb+"</a></td></tr></table>";
+		    if(metadata.equals("Title"))
+			if(!(place_data.equals("")) && place_data.indexOf(", , ;")==-1 && node_id.indexOf("```")==-1)
+			    GSXML.addMetadata(this.doc, node_meta_list, "Title", value);//metadata, value);
+			else
+			    GSXML.addMetadata(this.doc, node_meta_list, metadata, "");
+		    
+		    if(place_data.indexOf(", , ;")==-1){
+			if(i==0)
+			    if(!(mapFreq==0)){
+				outfile = new BufferedWriter(new FileWriter(this.temp_files_dir+"links"+uid));
+				outfile.write("<table align=\"center\"><tr>");
+			    }
+			
+			if(!(mapFreq==0)){
+			    if(i%7 == 0)
+				outfile.write("</tr><tr>");
+			    outfile.write("<td align=\"center\">"+link+thumb+"</a><br>"+link+year+"</a></td>");
+			}
+			
+			if(i == request_nodes.getLength()-1){
+			    outfile.write("</tr></table><p>");
+			    outfile.flush();
+			    outfile.close();
+			}
+		    }
+		} 
+		
+	    }
+	}catch(IOException ioe){ioe.printStackTrace();}
+	
+	return result;
+	}catch(Exception excep){excep.printStackTrace();}
+	return null;
+
+    }
+
+    protected Element processDocumentContentRetrieve(Element request){
+	// Create a new (empty) result message
+	Element result = doc.createElement(GSXML.RESPONSE_ELEM);
+	result.setAttribute(GSXML.FROM_ATT, DOCUMENT_CONTENT_RETRIEVE_SERVICE);
+	result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+	
+	String uid = request.getAttribute(GSXML.USER_ID_ATT);
+	String temp_image_file = this.temp_files_dir+"temp_"+uid+".jpg";
+	String temp_image_file2 = this.temp_files_dir+"temp_"+uid+"_2.jpg";
+
+	Element query_doc_list = (Element) GSXML.getChildByTagName(request, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	if (query_doc_list == null) {
+	    logger.error("DocumentContentRetrieve request specified no doc nodes.\n");
+	    return result;
+	}
+	
+	String legend_file = this.temp_files_dir+"legend_"+uid+".jpg";
+	String blank_file = this.files_home_dir + "blank.jpg";
+	Element doc_list = doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	result.appendChild(doc_list);
+	
+	// Get the documents
+	String[] doc_ids = GSXML.getAttributeValuesFromList(query_doc_list, 
+							     GSXML.NODE_ID_ATT);
+
+	for (int i = 0; i < doc_ids.length; i++) {
+	    String doc_id = doc_ids[i];
+	    // img_num is the name of the map file eg. 072.jpg
+	    String img_num = doc_id.substring(0,doc_id.indexOf('.'));
+	    // strings for inserting image in html
+	    String img_left = "<img border=0 src=\""+this.http_temp_image_dir;
+	    String doc_content = "";
+	    String co_ordinates = "";
+	    String img_size = "";
+	    int height = 0;
+	    int width = 0;
+	    // the number for the legend image if adding locations to the map
+	    int leg_num = 0;
+	    double ratio = 0;
+
+	    // if user has clicked on the map.  This does not resolve maps that are not North oriented.
+	    if(doc_id.indexOf("imageChooser")==0){
+		try{
+		    doc_id = doc_id.substring(doc_id.indexOf('`')+1,doc_id.length());
+		    img_num = doc_id.substring(0,doc_id.indexOf('.'));
+
+		    // get the map size
+		    String get_size[] = {"identify","-size","10000", temp_image_file};
+		    Process proc;
+		    proc = Runtime.getRuntime().exec(get_size);
+		    BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
+		    img_size = br.readLine();
+		    proc.waitFor();
+		    img_size = img_size.substring(img_size.indexOf("JPEG")+5,img_size.indexOf(" ",img_size.indexOf("JPEG")+5));
+		    width = Integer.parseInt(img_size.substring(0,img_size.indexOf("x")));
+		    height = Integer.parseInt(img_size.substring(img_size.indexOf("x")+1,img_size.length()));
+
+		    // scale image size according to the ratio
+		    ratio = Double.parseDouble(doc_id.substring(doc_id.lastIndexOf('`',doc_id.indexOf("```")-1)+1,doc_id.indexOf("```")));
+		    width = (int)(width*ratio);
+		    height = (int)(height*ratio);
+
+		    // get the position of the mouse click on the image
+		    int xclick = Integer.parseInt(doc_id.substring(doc_id.indexOf("```")+3,doc_id.lastIndexOf('`')));
+		    int yclick = Integer.parseInt(doc_id.substring(doc_id.lastIndexOf('`')+1,doc_id.length()));
+		    doc_id = doc_id.substring(doc_id.indexOf('`')+1,doc_id.indexOf("```"));
+
+		    // convert click position to percentage distance accross and down the image.
+		    double xpercent = (xclick*1.0)/width;
+		    double ypercent = (yclick*1.0)/height;
+
+		    // get the top left and bottom right co-ordinates of the map
+		    double ytop = Double.parseDouble(doc_id.substring(0,doc_id.indexOf('`')))*-1;
+		    doc_id = doc_id.substring(doc_id.indexOf('`')+1,doc_id.length());
+		    double xleft = Double.parseDouble(doc_id.substring(0,doc_id.indexOf('`')));
+		    doc_id = doc_id.substring(doc_id.indexOf('`')+1,doc_id.length());
+		    double ybot = Double.parseDouble(doc_id.substring(0,doc_id.indexOf('`')))*-1;
+		    doc_id = doc_id.substring(doc_id.indexOf('`')+1,doc_id.length());
+		    double xright = Double.parseDouble(doc_id.substring(0,doc_id.indexOf('`')));
+		    doc_id = doc_id.substring(doc_id.indexOf('`')+1,doc_id.length());
+
+		    // calculate the map co-ordinates of the mouse click
+		    xpercent = ((xright-xleft)*xpercent)+xleft;
+		    ypercent = ((ybot-ytop)*ypercent)+ytop;
+
+		    // search the tree for nearby place names
+		    namesInList.clear();
+		    findName(xpercent, ypercent, 0.1, 0.1, tree, true);
+
+		    int namesInArraySize = namesInList.size();
+		    String returnNames[]=new String[namesInArraySize];
+
+		    //put the names in an array
+		    for(int ri=0; namesInList.size()>0; ri++){
+			returnNames[ri]=(String)namesInList.getFirst();
+			returnNames[ri] = returnNames[ri].substring(0,returnNames[ri].indexOf('`'));
+			namesInList.removeFirst();
+		    }
+
+		    //sort the names
+		    Arrays.sort(returnNames);
+		    doc_content = "\n<script>\nfunction openIt(loc){\n\topener.location=loc;\n\tself.close();\n}\n</script>";
+		    for(int nameIndex=0; nameIndex < namesInArraySize; nameIndex++){
+			String tempName = returnNames[nameIndex];
+			//convert names with spaces for hyperlinks
+			if(returnNames[nameIndex].indexOf(' ') != -1){
+			    returnNames[nameIndex] = returnNames[nameIndex].replaceAll(" ","+");
+			    returnNames[nameIndex] = "%22"+returnNames[nameIndex]+"%22";
+			}
+			// add the place name to the html
+			doc_content = doc_content+"<a href=\"\" onClick=openIt('?a=q&sa=&rt=r&s=MapQuery&c="+this.cluster_name+"&startPage=1&s1.index=none&s1.maxDocs=10&s1.query="+returnNames[nameIndex]+"')>"+tempName+"</a><br>";
+		    }
+		    
+		}catch(Exception ioexception){ioexception.printStackTrace();}
+	    }
+	    else{
+		
+		try{
+		    //file for converting image    
+		    BufferedWriter bw = new BufferedWriter(new FileWriter(this.temp_files_dir + "add_x_"+uid));;
+		    Process proc;
+		    
+		    // if a new search
+		    if(doc_id.indexOf("```") != -1){
+			// copy requested map to temp.jpg
+			proc = Runtime.getRuntime().exec("cp "+this.files_home_dir+"maps"+File.separator+img_num+".jpg "+temp_image_file);
+			proc.waitFor();
+		    }
+
+		    //get the image size
+		    String get_size[] = {"identify","-size","10000", temp_image_file};
+		    proc = Runtime.getRuntime().exec(get_size);
+		    BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
+		    img_size = br.readLine();
+		    proc.waitFor();
+		    img_size = img_size.substring(img_size.indexOf("JPEG")+5,img_size.indexOf(" ",img_size.indexOf("JPEG")+5));
+		    if (img_size.indexOf("+")!=-1) {
+			img_size = img_size.substring(0, img_size.indexOf("+"));
+		    }
+		    width = Integer.parseInt(img_size.substring(0,img_size.indexOf("x")));
+		    height = Integer.parseInt(img_size.substring(img_size.indexOf("x")+1,img_size.length()));
+		    
+		    // if a new search
+		    if(doc_id.indexOf("```") != -1){
+			co_ordinates = doc_id.substring(doc_id.indexOf("```")+2, doc_id.length());
+			// get the number of places to mark on the map
+			int x_number = Integer.parseInt(doc_id.substring(doc_id.lastIndexOf('`',doc_id.indexOf("```")-1)+1,doc_id.indexOf("```")));
+
+			//write the convert command
+			bw.write("convert -font helvetica -fill red -pointsize 48 ");
+
+			for(int xi=0; xi<x_number; xi++){
+
+			    // get the co-ordinates of the place name
+			    double xco = Double.parseDouble(co_ordinates.substring(co_ordinates.lastIndexOf('`',co_ordinates.lastIndexOf('`')-1)+1,co_ordinates.lastIndexOf('`',co_ordinates.lastIndexOf('`')-1)+7));
+			    double yco = Double.parseDouble(co_ordinates.substring(co_ordinates.lastIndexOf('`')+1,co_ordinates.length()));
+			    if(xi != x_number-1)
+				co_ordinates = co_ordinates.substring(0,co_ordinates.lastIndexOf('`',co_ordinates.lastIndexOf('`')-1));
+			
+			    int index = 0;
+			    index = doc_id.indexOf('`')+2;
+			    
+			    // get the zoom ratio and the top left and bottom right co-ordinates of the map
+			    ratio = 0.4;
+			    double tly = Double.parseDouble(doc_id.substring(index,index+5));
+			    index = doc_id.indexOf('`',index)+1;
+			    double tlx = Double.parseDouble(doc_id.substring(index,index+6));
+			    index = doc_id.indexOf('`',index)+2;
+			    double bry = Double.parseDouble(doc_id.substring(index,index+5));
+			    index = doc_id.indexOf('`',index)+1;
+			    double brx = Double.parseDouble(doc_id.substring(index,index+6));
+			    index = doc_id.indexOf('`',index)+1;
+			    double orient = Double.parseDouble(doc_id.substring(index,doc_id.indexOf('`',index)));
+
+			    // find the centre of the map
+			    double xcent = ((brx-tlx)/2)+tlx;
+			    double ycent = ((bry-tly)/2)+tly;
+
+			    // get the orientation of the map
+			    orient = Math.toRadians(orient);
+
+			    // rotate the co-ordinates around the centre of the map 
+			    xco=xco-xcent;
+			    yco=yco-ycent;
+			    double oldx=xco;
+			    xco=xco*Math.cos(orient)-yco*Math.sin(orient);
+			    yco=oldx*Math.sin(orient)+yco*Math.cos(orient);
+			    xco=xco+xcent;
+			    yco=yco+ycent;
+			    xco = (xco-tlx)/(brx-tlx);
+			    yco = (yco-tly)/(bry-tly);
+
+			    // calculate the pixels for placing the mark
+			    width = (int)(xco*width)-5;
+			    height = (int)(yco*height)-5;
+			
+			    // write the options for convert
+			    bw.write("-draw 'text "+width+","+height+" \"x\"' ");
+			    bw.flush();
+			
+			    // reset the width and height variables for the image
+			    width = Integer.parseInt(img_size.substring(0,img_size.indexOf("x")));
+			    height = Integer.parseInt(img_size.substring(img_size.indexOf("x")+1,img_size.length()));
+			}
+			doc_id = doc_id.substring(0,doc_id.lastIndexOf('`',doc_id.indexOf("```")-1));
+
+			// write the end of the convert command, then command for zooming image to the right level, then command to copy the blank image over legend.jpg
+			bw.write(temp_image_file+" "+temp_image_file+";convert -scale "+((int)(ratio*width))+"x"+((int)(ratio*height))+" "+temp_image_file+" "+temp_image_file2+";cp "+blank_file +" "+legend_file);
+
+			// reset legend number
+			leg_num = 0;
+		    }
+
+		    else
+			// if changing zoom level
+			if(doc_id.substring(doc_id.lastIndexOf('`'),doc_id.length()).indexOf('.')!=-1){
+			    // get the ratio
+			    ratio = Double.parseDouble(doc_id.substring(doc_id.lastIndexOf('`')+1,doc_id.length()));
+			    // write the command for scaling image
+			    bw.write("convert -scale "+((int)(ratio*width))+"x"+((int)(ratio*height))+" "+temp_image_file+" "+temp_image_file2);
+			    doc_id = doc_id.substring(0,doc_id.lastIndexOf('`'));
+			}
+
+		        // if adding locations to map
+			else{
+
+			    // get the location type to add
+			    String restricter= doc_id.substring(doc_id.lastIndexOf('`')+1,doc_id.length());
+			    doc_id = doc_id.substring(0,doc_id.lastIndexOf('`'));
+
+			    // get the number for the legend image
+			    leg_num = Integer.parseInt(doc_id.substring(doc_id.lastIndexOf('`')+1,doc_id.length()));
+			    doc_id = doc_id.substring(0,doc_id.lastIndexOf('`'));
+
+			    //open file for location type
+			    BufferedReader inType = new BufferedReader(new FileReader(this.files_home_dir + "place_types"+File.separator + restricter + ".txt"));
+
+			    //check through the file and add any places that are in the bounds of this map.
+
+			    // check value. set to true if a place to add is found
+			    boolean add_place_type = false;
+
+			    int index = 0;
+			    index = doc_id.indexOf('`')+2;
+			    // get zoom ratio
+			    ratio = Double.parseDouble(doc_id.substring(doc_id.lastIndexOf('`')+1,doc_id.length()));
+			    // get top left and bottom right co-ordinates of the map
+			    double tly = Double.parseDouble(doc_id.substring(index,index+5));
+			    index = doc_id.indexOf('`',index)+1;
+			    double tlx = Double.parseDouble(doc_id.substring(index,index+6));
+			    index = doc_id.indexOf('`',index)+2;
+			    double bry = Double.parseDouble(doc_id.substring(index,index+5));
+			    index = doc_id.indexOf('`',index)+1;
+			    double brx = Double.parseDouble(doc_id.substring(index,index+6));
+			    index = doc_id.indexOf('`',index)+1;
+			    // get orientation of the map
+			    double orient = Double.parseDouble(doc_id.substring(index,doc_id.indexOf('`',index)));
+			    // calculate centre of map
+			    double xcent = ((brx-tlx)/2)+tlx;
+			    double ycent = ((bry-tly)/2)+tly;
+			    orient = Math.toRadians(orient);
+
+			    String type_point = "";
+			    double xco = 0.0;
+			    double yco = 0.0;
+
+			    // read the file
+			    while(inType.ready()){
+				//read a line
+				type_point = inType.readLine();
+
+				// get the co-ordinates of the point
+				xco = Double.parseDouble(type_point.substring(type_point.lastIndexOf('`')+1,type_point.length()));
+				yco = Double.parseDouble(type_point.substring(type_point.lastIndexOf('`',type_point.lastIndexOf('`')-1)+2,type_point.lastIndexOf('`')));
+
+				// if it is within the co-ordinates of the map
+				if(xco >= tlx && xco < brx && yco >= tly && yco < bry){
+				    // rotate the point around the centre according to map orientation
+				    xco=xco-xcent;
+				    yco=yco-ycent;
+				    double oldx=xco;
+				    xco=xco*Math.cos(orient)-yco*Math.sin(orient);
+				    yco=oldx*Math.sin(orient)+yco*Math.cos(orient);
+				    xco=xco+xcent;
+				    yco=yco+ycent;
+				    // get the pixels for where to place the mark
+				    xco = (xco-tlx)/(brx-tlx);
+				    yco = (yco-tly)/(bry-tly);
+				    width = (int)(xco*width)-5;
+				    height = (int)(yco*height)-5;
+
+				    //if this is the first point to be added
+				    if(!add_place_type){
+					// write the initial convert command
+					bw.write("convert -font helvetica -fill red -pointsize 36 ");
+					// toggle check value
+					add_place_type = true;
+				    }
+
+				    // write the options for the convert command
+				    bw.write("-draw 'text "+width+","+height+" \""+leg_num+"\"' ");
+				    bw.flush();
+			
+				    // reset width and height variables for the image
+				    width = Integer.parseInt(img_size.substring(0,img_size.indexOf("x")));
+				    height = Integer.parseInt(img_size.substring(img_size.indexOf("x")+1,img_size.length()));
+				}
+			    }
+
+			    //if there are places to mark on the map
+			    if(add_place_type){
+				// finish the convert command and write command for scaling image
+				bw.write(temp_image_file+" "+temp_image_file+";convert -scale "+((int)(ratio*width))+"x"+((int)(ratio*height))+" "+temp_image_file+" "+temp_image_file2);
+
+				// open file for converting the legend command
+				BufferedWriter buf = new BufferedWriter(new FileWriter(this.temp_files_dir+"add_l_"+uid));
+				if(leg_num == 1)
+				    buf.write("cp "+blank_file +" "+legend_file+";");
+				// write the command for adding to the legend
+				buf.write("convert -font helvetica -fill red -pointsize 12 -draw 'text 15,"+(leg_num*15+20)+" \""+leg_num+" "+getType(restricter)+"\"' "+legend_file+" "+legend_file);
+				buf.flush();
+				buf.close();
+				// execute the command for the legend image
+				proc = Runtime.getRuntime().exec("sh "+this.temp_files_dir+"add_l_"+uid);
+				proc.waitFor();
+			    }
+			    inType.close();
+			}
+		    bw.flush();
+		    bw.close();
+		
+		    // execute the convert commands etc.
+		    proc = Runtime.getRuntime().exec("sh "+this.temp_files_dir+"add_x_"+uid);
+		    proc.waitFor();
+		
+		}catch(Exception ioe){ioe.printStackTrace();}
+
+		//write the html for the document
+
+		String doc_content_head = "?a=d&c="+this.cluster_name+"&dt=map&d=";
+		doc_content = "<td valign=\"top\"><script>document.write('"+img_left+"legend_"+uid+".jpg"+"?'+new Date().getTime())</script>\"></td>";
+		doc_content = doc_content+"<td><script>document.write('"+img_left+"temp_"+uid+"_2.jpg?'+new Date().getTime())</script>\" onclick=\"imgClickHandler(event, this, '"+img_num+"')\"></td>";
+
+		// replace _httpimg_ with the correct address
+		doc_content = "<table><tr>"+doc_content+"</tr></table>";
+
+		String javascript = getJavascript(ratio, doc_id, leg_num);
+
+		doc_content = "<center>You are currently viewing the map at "+(int)(ratio*100)+"%<br>Select a radio button for a new zoom level.</center>"+javascript+doc_content;
+		doc_content = doc_content.replaceAll("zoomhead", doc_content_head);
+		doc_content = doc_content.replaceAll("placeChooserImage", doc_content_head+"imageChooser`"+doc_id+"`"+ratio);
+
+		// read the file for the navigation thumbnails
+		try{
+		    BufferedReader infile = new BufferedReader(new FileReader(this.temp_files_dir+"links"+uid));
+		    doc_content = doc_content + infile.readLine();
+		    infile.close();
+		}catch(Exception ioexc){ioexc.printStackTrace();}
+	    }
+
+	    // put the html in a text node
+	    Element text_doc = doc.createElement(GSXML.DOC_NODE_ELEM);
+	    text_doc.setAttribute(GSXML.NODE_ID_ATT, doc_id);
+	    GSXML.addDocText(doc, text_doc, doc_content);
+	    doc_list.appendChild(text_doc);
+	    
+	}
+        return result;
+    }
+
+    // resolves location codes for places from LINZ database
+    private String getLocation(String location){
+	String read;
+	try{
+	    BufferedReader in = new BufferedReader(new FileReader(this.files_home_dir+"files"+File.separator+"landdist.txt"));
+	    in.readLine();
+	    while(in.ready()){
+		read = in.readLine();
+		if(read.substring(0,2).equals(location)){
+		    in.close();
+		    return read.substring(3, read.length());
+		}
+	    }
+	}catch(Exception e){}
+	return "";
+    }
+
+    // resolves type codes for the LINZ database
+    private String getType(String type){
+	String read;
+	try{
+	    BufferedReader in = new BufferedReader(new FileReader(this.files_home_dir+"files"+File.separator+"pointdes.txt"));
+	    in.readLine();
+	    while(in.ready()){
+		read = in.readLine();
+		if(read.substring(0,read.indexOf('`')).toLowerCase().equals(type.toLowerCase())){
+		    in.close();
+		    return read.substring(read.indexOf('`')+1, read.indexOf(':'));
+		}
+	    }
+	}catch(Exception e){}
+	return "";
+    }
+
+    //recursive pre-order traversal of the 2-dimensional tree
+    // x & y are co-ordinates of mouse click, xoff & yoff are the distance in degrees away from x & y to search,
+    // d is the current node of the tree, xcomp controls whether searching is by x co-ordinate or y co-ordinate.
+    private void findName(double x, double y, double xoff, double yoff, DefaultMutableTreeNode d, boolean xcomp){
+	//if a leaf node return.  All leaf nodes are empty
+	if(d.isLeaf())
+	    return;
+	//get coordinates of the current node
+	double xco = Double.parseDouble(((String)d.getUserObject()).substring(((String)d.getUserObject()).length()-6,((String)d.getUserObject()).length()));
+	double yco = Double.parseDouble(((String)d.getUserObject()).substring(((String)d.getUserObject()).length()-12,((String)d.getUserObject()).length()-7));
+	//if in range
+	if((x-xoff)<xco && (x+xoff)>xco && (y-yoff)<yco && (y+yoff)>yco){
+	    //add to list
+	    namesInList.addFirst((String)d.getUserObject());
+	}
+	//if comparing the x axis
+	if(xcomp){
+	    //if need to search left subtree
+	    if((x-xoff)<xco)
+		findName(x,y,xoff,yoff,(DefaultMutableTreeNode)d.getChildAt(0),!xcomp);
+	    //if need to search right subtree
+	    if((x+xoff)>xco)
+		findName(x,y,xoff,yoff,(DefaultMutableTreeNode)d.getChildAt(1),!xcomp);
+	}
+	else{
+	    //if need to search left subtree
+	    if((y-yoff)<yco)
+		findName(x,y,xoff,yoff,(DefaultMutableTreeNode)d.getChildAt(0),!xcomp);
+	    //if need to search right subtree
+	    if((y+yoff)>yco)
+		findName(x,y,xoff,yoff,(DefaultMutableTreeNode)d.getChildAt(1),!xcomp);
+	}
+    }
+
+    // a whole lot of stuff for the html that is hidden at the bottom here because it clutters more than I already have further up!
+    private String getJavascript(double ratio, String doc_id, int leg_num)
+    {
+	String javascript = "\n<script>\nfunction imgClickHandler (evt, img, num) {\n\tif (window.event){\n\t\tvar chooserString = 'placeChooserImage' + '```' + window.event.offsetX + '`' + window.event.offsetY\n\t\tmywindow = window.open(chooserString,'Choose','width=600, height=500, scrollbars=yes, resizable=yes, toolbar=no, location=no, status=yes, menubar=no');\n\t\t//alert(window.event.offsetX + ':' + window.event.offsetY + ':' + num);\n\t}\n\telse if (evt.target) {\n\t\tvar coords = {x: 0, y: 0 };\n\t\tvar el = evt.target;\n\t\tdo {\n\t\t\tcoords.x += el.offsetLeft;\n\t\t\tcoords.y += el.offsetTop;\n\t\t}\n\t\twhile ((el = el.offsetParent));\n\t\tvar offsetX = evt.clientX - coords.x;\n\t\tvar offsetY = evt.clientY - coords.y;\n\t\talert(offsetX + ':' + offsetY + ':' + num);\n\t}\n}\nfunction leapTo (link)\n{\n\tvar new_url=link;\n\tif (  (new_url != \"\")  &&  (new_url != null)  ) \n\t\twindow.location=new_url;\n\telse \n\t\talert(\"You must make a selection.\");\n}\nfunction jumpTo (front,link,back)\n{\n\tvar new_url=front+link+back;\n\tif (  (new_url != \"\")  &&  (new_url != null)  ) \n\t\twindow.location=new_url;\n\telse \n\t\talert(\"You must make a selection.\");\n}// Deactivate Cloaking -->\n</script>";
+
+	String radioButtons = "\n<center><FORM>";
+	if(ratio != 0.4)
+	    radioButtons = radioButtons + "\n\t<INPUT TYPE=\"radio\" NAME=\"buttons1\" onClick=\"leapTo('zoomhead"+doc_id+"`0.4')\">40%";
+	if(ratio != 0.5)
+	    radioButtons = radioButtons + "\n\t<INPUT TYPE=\"radio\" NAME=\"buttons1\" onClick=\"leapTo('zoomhead"+doc_id+"`0.5')\">50%";
+	if(ratio != 0.6)
+	    radioButtons = radioButtons + "\n\t<INPUT TYPE=\"radio\" NAME=\"buttons1\" onClick=\"leapTo('zoomhead"+doc_id+"`0.6')\">60%";
+	if(ratio != 0.7)
+	    radioButtons = radioButtons + "\n\t<INPUT TYPE=\"radio\" NAME=\"buttons1\" onClick=\"leapTo('zoomhead"+doc_id+"`0.7')\">70%";
+	if(ratio != 0.8)
+	    radioButtons = radioButtons + "\n\t<INPUT TYPE=\"radio\" NAME=\"buttons1\" onClick=\"leapTo('zoomhead"+doc_id+"`0.8')\">80%";
+	if(ratio != 0.9)
+	    radioButtons = radioButtons + "\n\t<INPUT TYPE=\"radio\" NAME=\"buttons1\" onClick=\"leapTo('zoomhead"+doc_id+"`0.9')\">90%";
+	if(ratio != 1.0)
+	    radioButtons = radioButtons + "\n\t<INPUT TYPE=\"radio\" NAME=\"buttons1\" onClick=\"leapTo('zoomhead"+doc_id+"`1.0')\">100%";
+	radioButtons = radioButtons + "\n</FORM></center>";
+
+	leg_num = leg_num+1;
+
+	String doc_link = "?a=d&c="+this.cluster_name+"&dt=map&d="+doc_id+"`"+ratio+"`"+leg_num+"`";
+
+	StringBuffer dropDownBox = new StringBuffer();
+
+	dropDownBox.append("Add Locations Of Type: <form name=\"myForm\"><select name=\"s1index\" onChange=\"jumpTo('");
+	dropDownBox.append(doc_link);
+	dropDownBox.append("',document.myForm.s1index.options[document.myForm.s1index.selectedIndex].value,'')\">\n");
+
+	for (int i=0; i<this.index_name_list.size(); i++) {
+	    String name = (String)this.index_name_list.get(i);
+	    dropDownBox.append("<option value=\"");
+	    dropDownBox.append(name);
+	    dropDownBox.append("\">");
+	    String display = (String)this.index_display_list.get(i);
+	    dropDownBox.append(display);
+	    dropDownBox.append("\n");
+	}
+	// for each option, Malcolm had onClick=\"leapTo('"+doc_link+name+"')\" - dont seem to need this
+	dropDownBox.append("</select></form>\n");
+
+	return javascript + radioButtons + dropDownBox;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/MapSearch.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/MapSearch.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/MapSearch.java	(revision 13928)
@@ -0,0 +1,394 @@
+/*
+ *    MapSearch.java
+ *    Copyright (C) 2005 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.service;
+
+// Greenstone classes
+import org.greenstone.gsdl3.util.*;
+
+// XML classes
+import org.w3c.dom.Element; 
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList; 
+
+// General java classes
+import java.util.Hashtable;
+import java.util.HashMap;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.lang.reflect.Array;
+import java.util.Comparator;
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.FileInputStream;
+import java.lang.ClassNotFoundException;
+
+import org.apache.log4j.*;
+
+/**
+ *
+ * 
+ */
+public class MapSearch 
+    extends AbstractSearch {
+
+
+    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.MapSearch.class.getName());
+
+    protected String files_home_dir = null;
+
+    protected static final String FREQ_ATT = "freq";
+
+    // use the following if we add back in index searching
+    //protected String default_index = null;
+    //protected static final String DEFAULT_INDEX_ELEM = "defaultIndex";
+    //protected static final String INDEX_ELEM = "index";  
+    
+    /** Hashtable containing the place names database, indexed on the place name in lower case. */
+    public static Hashtable hashNames;
+
+    /** Constructor */
+    public MapSearch() {}
+
+    /** */
+    public boolean configure(Element info, Element extra_info)
+    {
+	if (!super.configure(info, extra_info)) {
+	    return false;
+	}
+	logger.info("Configuring MapSearch...");
+
+	// set the files_home_dir variable for this collection
+	this.files_home_dir = GSFile.collectionIndexDir(site_home, cluster_name)+File.separator+"assoc"+File.separator;
+
+	//load the hashtable
+	hashNames = new Hashtable();
+	try{
+	    ObjectInputStream in = new ObjectInputStream(new FileInputStream(this.files_home_dir+"hashnames.dat"));
+	    hashNames = (Hashtable)in.readObject();
+	    in.close();
+	}catch(IOException ioe){
+	    ioe.printStackTrace();
+	    return false;
+	}catch(ClassNotFoundException cnf){
+	    cnf.printStackTrace();
+	    return false;
+	}
+	 
+	// just in case we get the index stuff going, here is the code
+	
+	// get the display stuff for the indexes
+	
+// 	NodeList indexes = info.getElementsByTagName(GSXML.INDEX_ELEM);
+// 	if (extra_info != null) {
+// 	    Document owner = info.getOwnerDocument();
+// 	    Element config_search = (Element)GSXML.getChildByTagName(extra_info, GSXML.SEARCH_ELEM);
+// 	    if (config_search != null) {
+// 		for (int i=0; i<indexes.getLength();i++) {
+// 		    Element ind = (Element)indexes.item(i);
+// 		    String name = ind.getAttribute(GSXML.NAME_ATT);
+// 		    Element node_extra = GSXML.getNamedElement(config_search,
+// 							       GSXML.INDEX_ELEM,
+// 							       GSXML.NAME_ATT,
+// 							       name);
+// 		    if (node_extra == null) {
+// 			// no index specification for this index
+// 			continue;
+// 		    }
+		    
+// 		    // get the display elements if any - displayName
+// 		    NodeList display_names = node_extra.getElementsByTagName(GSXML.DISPLAY_TEXT_ELEM);
+// 		    if (display_names !=null) {
+// 			for (int j=0; j<display_names.getLength(); j++) {
+// 			    Element e = (Element)display_names.item(j);
+// 			    ind.appendChild(owner.importNode(e, true));
+// 			}
+// 		    }
+// 		} // for each index
+// 	    }
+// 	}
+// 	// Get the default index out of <defaultIndex> (buildConfig.xml)
+// 	Element def = (Element) GSXML.getChildByTagName(info, DEFAULT_INDEX_ELEM);
+// 	if (def != null) {
+// 	    default_index = def.getAttribute(GSXML.NAME_ATT);
+// 	}
+// 	if (default_index == null || default_index.equals("")) {
+// 	    // use the first one from the index list
+// 	    default_index = ((Element)indexes.item(0)).getAttribute(GSXML.NAME_ATT);
+// 	}
+
+	return true;
+    }
+
+    protected void getIndexData(ArrayList index_ids, ArrayList index_names, String lang) 
+    {
+	// for now, we just have one dummy index
+	index_ids.add("idx");
+	index_names.add("maps"); // get from properties
+
+	// use the following if we ever get the index search working
+// 	Element index_list = (Element)GSXML.getChildByTagName(this.config_info, INDEX_ELEM+GSXML.LIST_MODIFIER);
+// 	NodeList indexes = index_list.getElementsByTagName(INDEX_ELEM);
+// 	for (int i=0; i<indexes.getLength(); i++) {
+// 	    Element index = (Element)indexes.item(i);
+// 	    index_ids.add( index.getAttribute(GSXML.NAME_ATT));
+// 	    index_names.add(GSXML.getDisplayText(index, GSXML.DISPLAY_TEXT_NAME, lang, "en"));
+		
+// 	}
+    }
+    
+
+    /** Process a map query */
+    protected Element processTextQuery(Element request) 
+    {
+	// Create a new (empty) result message
+	Element result = doc.createElement(GSXML.RESPONSE_ELEM);
+	result.setAttribute(GSXML.FROM_ATT, TEXT_QUERY_SERVICE);
+	result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+
+	// Get the parameters of the request
+	Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	if (param_list == null) {
+	    logger.error("TextQuery request had no paramList.");
+	    return result;  // Return the empty result
+	}
+
+	// Process the request parameters
+	HashMap params = GSXML.extractParams(param_list, false);
+
+	// Make sure a query has been specified
+	String searchTerm = (String) params.get(QUERY_PARAM);
+	if (searchTerm == null || searchTerm.equals("")) {
+	    return result;  // Return the empty result
+	}
+
+	// If an index hasn't been specified, use the default
+// 	String index = (String) params.get(INDEX_PARAM); 
+// 	if (index == null) {
+// 	    index = default_index;
+// 	}
+
+	//convert the query string from the form '&quotTe Awamutu&quot Hamilton' to 'Te Awamutu+Hamilton'
+
+	//replace ' ' with '+'
+	searchTerm = searchTerm.replace(' ','+');
+
+	//replace '&quot' with '"'
+	int place = -1;
+	while(searchTerm.indexOf("&quot;",place+1) != -1){
+	    place = searchTerm.indexOf("&quot;",place+1);
+	    searchTerm = (searchTerm.substring(0,place) + "\"" + searchTerm.substring(place+6,searchTerm.length()));
+	}
+
+	//replace spaces in string enclosed in quotes
+	place = -1;
+	while(searchTerm.indexOf('"',place+1) != -1){
+	    place = searchTerm.indexOf('"',place+1);
+	    if(searchTerm.indexOf('"',place+1) != -1)
+		searchTerm = (searchTerm.substring(0,place) + searchTerm.substring(place, searchTerm.indexOf('"',place+1)).replace('+',' ') + searchTerm.substring(searchTerm.indexOf('"',place+1), searchTerm.length()));
+	    place = searchTerm.indexOf('"',place);
+	}
+
+	//remove speech marks
+	place = 0;
+	while(place != -1){
+	    place = searchTerm.indexOf('"', place);
+	    if(place != -1){
+		searchTerm = searchTerm.substring(0, place) + searchTerm.substring(place+1, searchTerm.length());
+		place=0;
+	    }
+	}
+
+	//find the number of search terms (number of '+' plus 1)
+	int words = 1;
+	place = 0;
+	while (place != -1){
+	    place = searchTerm.indexOf('+', place+1);
+	    if(place != -1) words++;
+	}
+	place = 0;
+
+	//store each search term in a string array
+	String terms[] = new String[words];
+	String terms_freq[] = new String[words];
+	for (int i=0; i<(words-1); i++){
+	    terms[i]=searchTerm.substring(place, searchTerm.indexOf('+', place));
+	    place = searchTerm.indexOf('+', place)+1;
+	}
+	terms[words-1] = searchTerm.substring(place, searchTerm.length());
+
+	Object nameArray[] = new Object[1];
+	int nameArraySize;
+	String nameData;
+	double xco, yco;
+	LinkedList mapList = new LinkedList();
+	LinkedList placeList = new LinkedList();
+	String readString = "";
+
+	//capitalise the search terms
+	for(int i=0;i<words;i++)
+	    terms[i] = terms[i].toUpperCase();
+
+	for(int k=0; k<words; k++){
+	    nameArraySize=0;
+
+
+	    if((nameArray = (Object[])hashNames.get(terms[k].toLowerCase())) != null){
+		logger.debug(hashNames.get(terms[k].toLowerCase()));
+		
+		nameArraySize = Arrays.asList(nameArray).size();
+	    }
+	    
+	    
+	    int h;
+	    for(h=0;h<nameArraySize;h++){
+
+		nameData = (String)nameArray[h];
+
+		// get the co-ordinates of the current place name
+		xco = Double.parseDouble(nameData.substring(nameData.lastIndexOf('`')+1,nameData.length()));
+		yco = Double.parseDouble(nameData.substring(nameData.lastIndexOf('`',nameData.lastIndexOf('`')-1)+2,nameData.lastIndexOf('`')));
+
+		//open the text file containing map metadata (first line is a description of the file)
+		try{
+		    BufferedReader inmap = new BufferedReader(new FileReader(this.files_home_dir + "files"+File.separator+"maps"+File.separator+"mapdata.txt"));
+		    inmap.readLine();
+
+		    // for each map
+		    while(inmap.ready()){
+			readString = inmap.readLine();
+			int indexer = 0;
+			indexer = readString.indexOf('`')+2;
+			// get the co-ordinates of the top left and bottom right corners of the map.
+			double ytop = Double.parseDouble(readString.substring(indexer,indexer+5));
+			indexer = readString.indexOf('`',indexer)+1;
+			double xtop = Double.parseDouble(readString.substring(indexer,indexer+6));
+			indexer = readString.indexOf('`',indexer)+2;
+			double ybot = Double.parseDouble(readString.substring(indexer,indexer+5));
+			indexer = readString.indexOf('`',indexer)+1;
+			double xbot = Double.parseDouble(readString.substring(indexer,indexer+6));
+
+			//if the place is within the map, put the map metadata and the placename metadata in linked list
+			if(xco >= xtop && xco < xbot && yco >= ytop && yco < ybot)
+			    mapList.add(readString+"```"+nameData);
+		    }
+		}catch(Exception e){e.printStackTrace();}
+	    }
+	}
+
+	// use an array object to sort the linked list by map number
+	Object[] mapListArray = mapList.toArray();
+	Arrays.sort(mapListArray);
+	mapList.clear();
+	for(int mla=0; mla<Array.getLength(mapListArray); mla++)
+	    mapList.addFirst(mapListArray[mla]);
+
+	//for each map, create a list of the query matches on that map
+	LinkedList tempList = new LinkedList();
+	String mapNumber = "";
+	String currentMap[] = {"",""};
+	int mapFreq = 0;
+	while(mapList.size()>0){
+	    readString = (String)mapList.removeFirst();
+	    if(mapNumber.equals(readString.substring(0,readString.indexOf('.')))){
+		currentMap[1] = currentMap[1]+readString.substring(readString.indexOf("```"),readString.length());
+		mapFreq++;
+	    }
+	    else{
+		if(!currentMap[0].equals(""))
+		    tempList.add(currentMap[0]+"`"+mapFreq+currentMap[1]);
+		currentMap[0] = readString.substring(0,readString.indexOf("```"));
+		currentMap[1] = readString.substring(readString.indexOf("```"),readString.length());
+		mapNumber = readString.substring(0,readString.indexOf('.'));
+		mapFreq=1;
+	    }
+	}
+	if(!currentMap[0].equals(""))
+	    tempList.add(currentMap[0]+"`"+mapFreq+currentMap[1]);
+
+	int totalDocs = tempList.size();
+
+	// use an array object to sort the linked list by number of matches on each map
+	Object[] tempListArray = tempList.toArray();
+	Arrays.sort(tempListArray, new MapResultSorter());
+	tempList.clear();
+	for(int tla=0; tla<Array.getLength(tempListArray); tla++)
+	    tempList.add(tempListArray[tla]);
+
+	// Create a metadata list to store information about the query results
+	Element metadata_list = doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER); 
+	result.appendChild(metadata_list);
+			
+	// Add a metadata element specifying the number of matching documents
+	GSXML.addMetadata(this.doc, metadata_list, "numDocsMatched", "" + totalDocs);
+	GSXML.addMetadata(this.doc, metadata_list, "numDocsReturned", ""+totalDocs);
+       	// Create a document list to store the matching documents, and add them
+	Element document_list = doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	result.appendChild(document_list);
+	for (int d = 0; d < totalDocs; d++) {
+	    String doc_id = (String)tempList.get(d);
+
+	    Element doc_node = doc.createElement(GSXML.DOC_NODE_ELEM);
+	    doc_node.setAttribute(GSXML.NODE_ID_ATT, doc_id);
+	    doc_node.setAttribute(GSXML.NODE_TYPE_ATT, "thumbnail");
+	    doc_node.setAttribute(GSXML.DOC_TYPE_ATT, "map");
+	    document_list.appendChild(doc_node);
+	}
+			
+	// Create a term list to store the term information, and add it
+	Element term_list = doc.createElement(GSXML.TERM_ELEM+GSXML.LIST_MODIFIER);
+	result.appendChild(term_list);	
+	
+
+	for (int t=0; t<words; t++){
+	    String term = terms[t];
+	
+	    Element term_elem = doc.createElement(GSXML.TERM_ELEM);
+  	    term_elem.setAttribute(GSXML.NAME_ATT, term);
+  	    term_elem.setAttribute(FREQ_ATT, "" + terms_freq[t]);
+
+	    term_list.appendChild(term_elem);
+	}
+	return result;
+    }
+ 
+
+    public class MapResultSorter implements Comparator {
+	
+	public int compare(Object o1, Object o2) {
+	    String first = (String)o1;
+	    String second = (String) o2;
+	    int firstInt;
+	    int secondInt;
+	    first = first.substring(first.lastIndexOf('`',first.indexOf("```")-1)+1,first.indexOf("```"));
+	    second = second.substring(second.lastIndexOf('`',second.indexOf("```")-1)+1,second.indexOf("```"));
+	    firstInt = Integer.parseInt(first);
+	    secondInt = Integer.parseInt(second);
+	    if(firstInt > secondInt)
+		return -1;
+	    else if(firstInt == secondInt)
+		return 0;
+	    else
+		return 1;
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/ModuleWrapper.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/ModuleWrapper.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/ModuleWrapper.java	(revision 13928)
@@ -0,0 +1,240 @@
+/*
+ *    ModuleWrapper.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.service;
+import org.greenstone.gsdl3.core.ModuleInterface;
+
+// XML classes
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.SAXParser;
+import org.apache.xerces.dom.TextImpl;
+import org.apache.xerces.parsers.DOMParser;
+import org.w3c.dom.Document; 
+import org.w3c.dom.Element;
+import org.w3c.dom.Node; 
+import org.w3c.dom.Node;                                                
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+
+// java classes
+import java.io.StringReader;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.security.SecureRandom;
+
+import org.apache.log4j.*;
+
+/**
+ * A classes for logging and checking all traffic to and from a ModuleInterface
+ * 
+ * if logCounter hasn't been initialised, initialise it to a random 
+ * value. This has to use secure random rather than a normal random
+ * or every time the application is run the same numbers will be
+ * generated and the search for a free range will become a linear
+ * search rather than a hash.
+ *
+ *
+ * @author <a href="mailto:s.yeates@cs.waikato.ac.nz">Stuart Yeates</a>
+ * @version $Revision$
+ */
+public class ModuleWrapper 
+  implements ModuleInterface 
+{
+
+    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service. ModuleWrapper.class.getName());
+
+  /** the module we're wrapping */
+  protected ModuleInterface inner = null;
+  /** the module we're wrapping */
+  public ModuleInterface getInner(){return inner;};
+  /** the module we're wrapping */
+  public void setInner(ModuleInterface i){inner=i;};
+
+  /** The schema of the IN XML */
+  protected String fromSchema = null;
+  /** The schema of the IN XML */
+  public String getFromSchema(){return fromSchema;};
+  /** The schema of the IN XML */
+  public void setFromSchema(String s){fromSchema=s;};
+
+  /** The schema of the OUT XML */
+  protected String toSchema = null;
+  /** The schema of the OUT XML */
+  public String getToSchema(){return toSchema;};
+  /** The schema of the OUT XML */
+  public void setToSchema(String s){toSchema=s;};
+
+  /** Are we logging the XML ? */
+  protected boolean logging = true;
+  /** Are we logging the XML ? */
+  public boolean getLogging(){return logging;};
+  /** Are we logging the XML ? */
+  public void setLogging(boolean b){logging=b;};
+
+  /** Where we are logging the XML */
+  protected String logDirectory = "/tmp/";
+  /** Where we are logging the XML */
+  public String getLogDirectory(){return logDirectory;};
+  /** Where we are logging the XML */
+  public void setLogDirectory(String s){logDirectory=s;};
+
+  /** The number of the previous log file */
+  protected static long logCounter = 0;
+
+  /** The no-args constructor */
+  public ModuleWrapper(){
+
+  }
+  
+  public void cleanUp() {}
+  
+  /** The all-args constructor */
+  public ModuleWrapper(String in,String out, ModuleInterface inner){
+    this.setFromSchema(in);
+    this.setToSchema(out);
+    this.setInner(inner);
+  }
+
+  /**
+   * Process an XML request - as a String
+   *
+   * @param xmlIn the request to process
+   * @return the response - contains any error messages
+   * @see java.lang.String
+   */
+  public String process(String xmlIn) {
+    
+    long logNumber = 0;
+    String xmlOut = "";
+    if (getLogging()) {
+      if (logCounter == 0)
+	logCounter = new SecureRandom().nextLong();
+      try {
+	logNumber = logCounter++;
+	String filename = getLogDirectory() + File.separator + logNumber + ".in";
+	File file = new File(filename);
+	
+	while (file.exists()){
+	  logCounter = new SecureRandom().nextLong();
+	  logNumber = logCounter++;
+	  filename = getLogDirectory() + File.separator + logNumber + ".in";
+	  file = new File(filename);
+	}
+	
+	FileWriter writer = new FileWriter(file);
+	writer.write(xmlIn);
+      } catch (IOException e) {
+	logger.error("caught exception: " +e );
+      }
+    }
+    xmlOut = processInner(xmlIn);
+
+    try {
+      String filename = getLogDirectory() + File.separator + logNumber + ".out";
+      File file = new File(filename);
+      FileWriter writer = new FileWriter(file);
+      writer.write(xmlOut);
+    } catch (IOException e) {
+      logger.error("caught exception: " +e );
+    }
+    return xmlOut;
+  }
+
+  /**
+   * Process an XML request - as a String
+   *
+   * @param xmlIn the request to process
+   * @return the response - contains any error messages
+   * @see java.lang.String
+   */
+  protected String processInner(String xmlIn) 
+  {
+    try {
+      DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
+      DocumentBuilder builder= factory.newDocumentBuilder();
+      DOMParser parser = new DOMParser();
+      try {
+	
+	parser.setFeature("http://xml.org/sax/features/validation",true);
+	parser.setFeature("http://apache.org/xml/features/validation/schema",true);
+	parser.setFeature("http://apache.org/xml/features/validation/dynamic", true);
+	parser.setFeature("http://apache.org/xml/features/validation/schema", true);
+	parser.setFeature("http://apache.org/xml/features/validation/schema-full-checking", true);
+	parser.setFeature("http://apache.org/xml/features/validation/schema/normalized-value", true);
+	parser.setFeature("http://apache.org/xml/features/validation/warn-on-duplicate-attdef", true);
+	parser.setFeature("http://apache.org/xml/features/validation/warn-on-undeclared-elemdef", true);
+	parser.setFeature("http://apache.org/xml/features/warn-on-duplicate-entitydef", true);
+      } catch (Exception a) {
+	logger.error("unable to set feature:" +a);
+	a.printStackTrace();
+      }
+
+      // do the pre-call checking
+      InputSource xml_source = new InputSource(new StringReader(xmlIn));  
+      try {
+	parser.parse(xml_source);
+      } catch (Exception e){  
+	logger.error("parsing error:" +e);
+	e.printStackTrace();
+	return "<response> <error class=\"ModuleWrapper\" code=1> Error: supplied string contained the parse error: " + e + " </error> </response>";
+      } 
+
+      String xmlOut = inner.process(xmlIn);
+
+      // do the post-call checking
+      InputSource xmlResult = new InputSource(new StringReader(xmlIn));  
+      try {
+	parser.parse(xmlResult);
+      } catch (Exception e){  
+	logger.error("parsing error:" +e);
+	e.printStackTrace();
+	return "<response> <error class=\"ModuleWrapper\" code=2> Error: returned string contained the parse error: " + e + "</error></response>";
+      } 
+
+      return xmlOut;
+
+    } catch (Exception e){  
+      logger.error("other error:" +e);
+      e.printStackTrace();
+      return "<response> <error class=\"ModuleWrapper\" code=3>Error: Unknown error or warning: " + e + " </error></response>";
+    } 
+  }
+
+  /**
+   * Process an XML request - as a DOM Element
+   *
+   * @param in the request to process
+   * @return the response - contains any error messages
+   * @see org.w3c.dom.Element
+   */
+  public Element process(Element xmlIn) {
+    throw new Error("Not implmented yet. Should be faked by stringizing the node.");
+  }
+}    
+                                                                           
+
+
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/PhindPhraseBrowse.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/PhindPhraseBrowse.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/PhindPhraseBrowse.java	(revision 13928)
@@ -0,0 +1,464 @@
+/*
+ *    PhindServices.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.service;
+
+import org.greenstone.gsdl3.util.*;
+
+import org.greenstone.mgpp.*;
+import org.w3c.dom.Document; 
+import org.w3c.dom.Node; 
+import org.w3c.dom.Element; 
+import org.w3c.dom.Text; 
+
+import java.util.Vector;
+import java.util.HashMap;
+import java.io.File;
+
+import org.apache.log4j.*;
+
+/** 
+ * PhindServices - the phind phrase browsing service
+ * 
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ * @version $Revision$
+ */
+public class PhindPhraseBrowse
+    extends ServiceRack {
+    
+     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.PhindPhraseBrowse.class.getName());
+
+    // the services on offer
+    private static final String PHIND_SERVICE = "PhindApplet";
+
+    private MGPPWrapper mgpp_src=null;
+    private String basepath = null;
+
+    private Element applet_description = null;
+    
+    public PhindPhraseBrowse() {
+	this.mgpp_src = new MGPPWrapper();
+	// set up the default params
+	this.mgpp_src.setQueryLevel("Document");
+	this.mgpp_src.setReturnLevel("Document");
+	this.mgpp_src.setMaxDocs(5);
+	this.mgpp_src.setStem(false);
+	this.mgpp_src.setCase(true);
+    }
+
+    public void cleanUp() {
+	super.cleanUp();
+	this.mgpp_src.unloadIndexData();
+    }
+
+    /** configure the service module
+     *
+     * @param info a DOM Element containing any config info for the service
+     * @return true if configured
+     */
+    public boolean configure(Element info, Element extra_info) {
+
+	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+
+	logger.info("configuring PhindPhraseBrowse");
+
+	// set up short_service_info_ - for now just has name and type
+	Element e = this.doc.createElement(GSXML.SERVICE_ELEM);
+	e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_APPLET);
+	e.setAttribute(GSXML.NAME_ATT, PHIND_SERVICE);
+	this.short_service_info.appendChild(e);
+
+	// set up the static applet description
+
+	applet_description = this.doc.createElement(GSXML.SERVICE_ELEM);
+	applet_description.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_APPLET);
+	applet_description.setAttribute(GSXML.NAME_ATT, PHIND_SERVICE);
+
+	// add in the applet info for the phind applet
+	// need to make this dynamic - library names etc
+	// change the applet params - have a single param with the library name
+	// this is left blank at this end, and must be filled in by applet action - if the library name is not needed, this param is left out
+	// phindcgi param now is not complete - library must be prepended to it.
+	String app_info = "<"+GSXML.APPLET_ELEM+" CODEBASE='applet' CODE='org.greenstone.applet.phind.Phind.class' ARCHIVE='phind.jar, xercesImpl.jar, xml-apis.jar' WIDTH='500' HEIGHT='400'><PARAM NAME='library' VALUE=''/> <PARAM NAME='phindcgi' VALUE='?";
+	app_info += GSParams.ACTION +"=a&amp;"+GSParams.REQUEST_TYPE +"=r&amp;"+GSParams.SERVICE+"="+PHIND_SERVICE+"&amp;"+GSParams.OUTPUT+"=xml&amp;"+GSParams.RESPONSE_ONLY+"=1'/>";
+	app_info +="<PARAM NAME='collection'   VALUE='";
+	app_info += this.cluster_name;
+	app_info += "'/> <PARAM NAME='classifier' VALUE='1'/>  <PARAM NAME='orientation'  VALUE='vertical'/> <PARAM NAME='depth' VALUE='2'/> <PARAM NAME='resultorder' VALUE='L,l,E,e,D,d'/> <PARAM NAME='backdrop' VALUE='interfaces/default/images/phindbg1.jpg'/><PARAM NAME='fontsize' VALUE='10'/> <PARAM NAME='blocksize'    VALUE='10'/>The Phind java applet.</"+GSXML.APPLET_ELEM+">";
+	
+	Document dom = this.converter.getDOM(app_info);
+	if (dom==null) {
+	    logger.error("Couldn't parse applet info");
+	    return false;
+	}
+	Element app_elem = dom.getDocumentElement();
+	applet_description.appendChild(this.doc.importNode(app_elem, true));
+
+	return true;
+    }
+
+    protected Element getServiceDescription(String service, String lang, String subset) {
+	if (!service.equals(PHIND_SERVICE)) {
+	    return null;
+	}
+	Element describe = (Element) applet_description.cloneNode(true);
+	describe.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_NAME,  getTextString(PHIND_SERVICE+".name", lang)));
+	describe.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_DESCRIPTION,  getTextString(PHIND_SERVICE+".description", lang)));
+	return describe;
+    }
+
+    protected Element processPhindApplet(Element request) {
+	
+	Element param_elem = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	HashMap params = GSXML.extractParams(param_elem, false);
+	
+	long first_e = Long.parseLong((String)params.get("pfe"));
+	long last_e = Long.parseLong((String)params.get("ple"));
+	long first_l = Long.parseLong((String)params.get("pfl"));
+	long last_l = Long.parseLong((String)params.get("pll"));
+	long first_d = Long.parseLong((String)params.get("pfd"));
+	long last_d = Long.parseLong((String)params.get("pld"));
+	
+	long phrase;
+	String phrase_str = (String)params.get("ppnum");
+	if (phrase_str == null || phrase_str.equals("")) {
+	    phrase=0;
+	} else {
+	    phrase = Long.parseLong(phrase_str);
+	}
+	String word = (String)params.get("pptext");
+	String phind_index = (String)params.get("pc");
+	// the location of the mgpp database files
+	this.basepath = GSFile.phindBaseDir(this.site_home, this.cluster_name, phind_index);
+
+	// the result element
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	result.setAttribute(GSXML.FROM_ATT, PHIND_SERVICE);
+	result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+
+	// applet result info must be in appletInfo element
+	Element applet_data = this.doc.createElement(GSXML.APPLET_DATA_ELEM);
+	result.appendChild(applet_data);
+	Element phind_data = this.doc.createElement("phindData");
+	applet_data.appendChild(phind_data);
+
+
+	// if we dont know the phrase number, look it up
+	if (phrase == 0) {
+	    if (word==null || word.equals("")) {
+		Element error = phindError("no word or phrase");
+		phind_data.appendChild(error);
+		return result;
+	    }
+	    phrase = findPhraseNumberFromWord( word);
+	}
+	if (phrase==0) {
+	    // the word is not in the collection
+	    // return a phind error string
+	    Element error = phindError("the term "+word+" is not in the collection");
+	    phind_data.appendChild(error);
+	    return result;
+	}
+	
+	// get the phrase data into the phind_data node
+	getPhraseData(phind_data, phrase, first_l, last_l,
+		      first_e, last_e,  first_d, last_d);
+	return result;
+	
+	
+    }// processPhindApplet
+    
+    protected long findPhraseNumberFromWord(String word) {
+
+	// set the mgpp index data - we are looking up pword
+	this.mgpp_src.loadIndexData(this.basepath+File.separatorChar+"pword");
+
+	this.mgpp_src.runQuery(word);
+
+	MGPPQueryResult res = this.mgpp_src.getQueryResult();
+	Vector docs = res.getDocs();
+	if (docs.size()==0) {
+	    // phrase not found
+	    return 0;
+	}
+	MGPPDocInfo doc = (MGPPDocInfo)docs.firstElement();
+	return doc.num_;
+    }
+
+    protected boolean getPhraseData(Element phind_data,
+				    long phrase, long first_l, long last_l,
+				    long first_e, long last_e, long first_d, 
+				    long last_d) {
+
+	String record = this.mgpp_src.getDocument(this.basepath+File.separatorChar+"pdata", "Document",
+					      phrase);
+	if (record.equals("")) {
+	    Element error = phindError("somethings gone wrong - we haven't got a record for phrase number "+phrase);
+	    phind_data.appendChild(error);
+	    return false;
+	}
+	
+	// parse the record - its in gordons cryptic form
+	// ":word:tf:ef:df:el:dl:lf:ll"
+	// el: e,e,e
+	// dl: d;f,d;f,
+	// lf and ll may be null
+	// l: type,dest, dest; type,dest,dest
+
+	// ignore everything up to and including first colon (has
+	// <Document>3505: at the start)
+	record = record.substring(record.indexOf(':')+1);
+
+	// split on ':'
+	String [] fields = record.split(":");
+	String word = fields[0];
+	String tf = fields[1];
+	String ef = fields[2];
+	String df = fields[3];
+
+	
+	String expansions = fields[4];
+	String documents = fields[5];
+	String lf = "0";
+	String linklist = "";
+	if (fields.length > 7) {// have thesaurus stuff
+	    lf =fields[6];
+	    linklist = fields[7];
+	}
+	
+	// the phindData attributes and phrase
+	phind_data.setAttribute("id", Long.toString(phrase));
+	phind_data.setAttribute("df", df);
+	phind_data.setAttribute("ef", ef);
+	phind_data.setAttribute("lf", lf);
+	phind_data.setAttribute("tf", tf);
+	GSXML.createTextElement(this.doc, "phrase", word);
+
+	addExpansionList(phind_data, expansions, word, ef, first_e, last_e);
+	addDocumentList(phind_data, documents, word, df, first_d, last_d);
+	if (!lf.equals("0")) {
+	    addThesaurusList(phind_data, linklist, word, lf, first_l, last_l);
+	}
+	return true;
+    }
+
+    protected boolean addExpansionList( Element phind_data, String record, 
+				       String word,
+				       String freq,
+				       long first, long last) {
+
+	Element expansion_list = this.doc.createElement("expansionList");
+	phind_data.appendChild(expansion_list);
+	expansion_list.setAttribute("length", freq);
+	expansion_list.setAttribute("start", Long.toString(first));
+	expansion_list.setAttribute("end", Long.toString(last));
+
+	// get the list of strings
+	String [] expansions = record.split(",");
+	int length = expansions.length;
+	if (length < last) last = length;
+	for (long i = first; i < last; i++) {
+	    long num  = Long.parseLong(expansions[(int)i]);
+	    Element expansion = getExpansion( num, word);
+	    expansion.setAttribute("num", Long.toString(i));
+	    expansion_list.appendChild(expansion);
+	}
+	return true;
+    }
+    
+    protected Element getExpansion(long phrase_num, 
+				   String orig_phrase) {
+	
+	// look up the phrase in the pdata thingy
+	String record = this.mgpp_src.getDocument(this.basepath+File.separatorChar+"pdata", "Document",
+					      phrase_num);
+
+	if (record ==null || record.equals("")) return null;
+
+	// ignore everything up to and including first colon 
+	record = record.substring(record.indexOf(':')+1);
+
+	String [] fields = record.split(":");
+	String phrase = fields[0];
+	String tf = fields[1];
+	//String ef = fields[2]; dont use this
+	String df = fields[3];
+
+	Element expansion = this.doc.createElement("expansion");
+	expansion.setAttribute("tf", tf);
+	expansion.setAttribute("df", df);
+	expansion.setAttribute("id", Long.toString(phrase_num));
+
+	// get teh suffix and prefix
+	String [] ends = splitPhraseOnWord(phrase, orig_phrase);
+	if (!ends[0].equals("")) {
+	    expansion.appendChild(GSXML.createTextElement(this.doc, "prefix", ends[0]));
+	}
+	if (!ends[1].equals("")) {
+	    expansion.appendChild(GSXML.createTextElement(this.doc, "suffix", ends[1]));
+	}
+
+	return expansion;
+
+    }
+
+    protected boolean addDocumentList(Element phind_data, String record, 
+				      String word,
+				      String freq,
+				      long first, long last) {
+
+	Element document_list = this.doc.createElement("documentList");
+	phind_data.appendChild(document_list);
+	document_list.setAttribute("length", freq);
+	document_list.setAttribute("start", Long.toString(first));
+	document_list.setAttribute("end", Long.toString(last));
+
+	// get the list of doc,freq
+	String [] doc_freqs = record.split(";");
+	int length = doc_freqs.length;
+	if (length<last) last=length;
+
+	for (long i = first; i < last; i++) {
+	    String doc_elem = doc_freqs[(int)i];
+	    int p = doc_elem.indexOf(',');
+	    long doc_num;
+	    String doc_freq;
+	    if (p == -1) { // there is no freq in the record
+		doc_num =Long.parseLong(doc_elem);
+		doc_freq = "1";
+	    } else {
+		doc_num = Long.parseLong(doc_elem.substring(0,p));
+		doc_freq = doc_elem.substring(p+1);
+	    }
+	    Element document = getDocument( doc_num);
+	    document.setAttribute("freq", doc_freq);
+	    document.setAttribute("num", Long.toString(i));
+	    document_list.appendChild(document);
+	}
+
+	
+	return true;
+    }
+
+
+    protected Element getDocument(long doc_num) {
+	
+	// look up the phrase in the docs thingy
+	String record = this.mgpp_src.getDocument(this.basepath+File.separatorChar+"docs", "Document",
+					      doc_num);
+	
+	if (record ==null || record.equals("")) return null;
+	
+	// ignore everything up to and including first \t
+	record = record.substring(record.indexOf('\t')+1);
+
+	String [] fields = record.split("\t");
+	String hash = fields[0];
+	String title = fields[1];
+
+	Element d = this.doc.createElement("document");
+	d.setAttribute("hash", hash);
+	d.appendChild(GSXML.createTextElement(this.doc, "title", title));
+	
+	return d;
+
+    }
+    protected boolean addThesaurusList(Element phind_data, String record,
+				       String word,
+				       String freq,
+				       long first, long last) {
+
+
+	Element thesaurus_list = this.doc.createElement("thesaurusList");
+	phind_data.appendChild(thesaurus_list);
+	thesaurus_list.setAttribute("length", freq);
+	thesaurus_list.setAttribute("start", Long.toString(first));
+	thesaurus_list.setAttribute("end", Long.toString(last));
+	
+	// get the list of type,dest,dest
+	String [] links = record.split(";");
+	int length = links.length;
+	long index = 0;
+	for (int i = 0; i < length; i++) { // go through the entries
+	    String link_info = links[(int)i];
+	    String [] items = link_info.split(",");
+	    // the first entry is teh type
+	    String type = items[0];
+	    for (int j = 1; j<items.length; j++, index++) {
+		if (index >= first && index < last) { // only output the ones we want
+		    long phrase = Long.parseLong(items[j]);
+		    Element t = getThesaurus(phrase);
+		    t.setAttribute("type", type);
+		    thesaurus_list.appendChild(t);
+		}
+	    }
+	}
+
+	return true;
+    }
+
+    protected Element getThesaurus(long phrase_num) {
+
+	// look up the phrase in the pdata thingy
+	String record = this.mgpp_src.getDocument(this.basepath+File.separatorChar+"pdata", "Document",
+					      phrase_num);
+
+	if (record ==null || record.equals("")) return null;
+
+	// ignore everything up to and including first colon 
+	record = record.substring(record.indexOf(':')+1);
+
+	String [] fields = record.split(":");
+	String phrase = fields[0];
+	String tf = fields[1];
+	//String ef = fields[2]; dont use this
+	String df = fields[3];
+
+	Element thesaurus = this.doc.createElement("thesaurus");
+	thesaurus.setAttribute("tf", tf);
+	thesaurus.setAttribute("df", df);
+	thesaurus.setAttribute("id", Long.toString(phrase_num));
+	thesaurus.appendChild(GSXML.createTextElement(this.doc, "phrase", phrase));
+	return thesaurus;
+
+    }
+
+    /** returns an array of two elements - the prefix and the suffix*/
+    protected String [] splitPhraseOnWord(String phrase, String word) {
+	
+	if (word.equals("")) {
+	    
+	    String [] res =  {phrase, ""};
+	    return res;
+	}
+	// use 2 so that we only split on the first occurrance. trailing empty strings should be included 
+	String [] result = phrase.split(word, 2);
+	return result;
+	
+    }
+
+    protected Element phindError(String message) {
+	Element e = this.doc.createElement("phindError");
+	Text t = this.doc.createTextNode(message);
+	e.appendChild(t);
+	return e;
+    }
+    
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/ServiceRack.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/ServiceRack.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/ServiceRack.java	(revision 13928)
@@ -0,0 +1,414 @@
+/*
+ *    ServiceRack.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.service;
+
+// greenstone classes
+import org.greenstone.gsdl3.util.*;
+import org.greenstone.gsdl3.core.*;
+
+// xml classes
+import org.w3c.dom.Node; 
+import org.w3c.dom.NodeList; 
+import org.w3c.dom.Element; 
+import org.w3c.dom.Document; 
+import org.xml.sax.InputSource;
+import javax.xml.parsers.*;
+import org.apache.xpath.XPathAPI;
+
+// general java classes
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.File;
+import java.util.HashMap;
+import java.util.ResourceBundle;
+import java.util.Locale;
+import java.lang.reflect.Method;
+
+import org.apache.log4j.*;
+
+/**
+ * ServiceRack - abstract base class for services
+ *
+ * A ServiceRack provides one or more Services. 
+ * This base class implements the process method.
+ *Each service is invoked
+ * by a method called process<service name> which takes one parameter - the xml request Element, and returns an XML response Element. 
+ * for example, the TextQuery service would be invoked by 
+ * processTextQuery(Element request)
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ * @version $Revision$
+ */
+public abstract class ServiceRack
+    implements ModuleInterface
+{
+
+     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.ServiceRack.class.getName());
+
+    /** the absolute address of the site home */
+    protected String site_home =null;
+    /** the http address of the site home */
+    protected String site_http_address =null;
+
+    /** the name of the cluster (or collection) that this service 
+	belongs to - if any */ 
+    protected String cluster_name = null;
+
+    /** some services can talk back to the message router */
+    protected MessageRouter router = null;
+
+    /** a converter class to create Documents etc */
+    protected XMLConverter converter = null;
+
+    /** the original config info - if need to store it */
+    protected Element config_info = null;
+
+    /** XML element for describe requests - the container doc */
+    protected Document doc = null;
+
+    /** XML element for describe requests - list of supported services
+	- this is static     */
+    protected Element short_service_info = null;
+
+    /** XML element for stylesheet requests - map of service name to format 
+	elem */
+    protected HashMap format_info_map = null;
+
+    /** A class loader that knows about the collection resources directory 
+     *  can put properties files, dtds etc  in here */
+    CollectionClassLoader class_loader = null;
+    
+    /** sets the cluster name */
+    public void setClusterName(String cluster_name) {
+	this.cluster_name = cluster_name;
+    }
+    /** sets the collect name */
+    public void setCollectionName(String coll_name) {
+	setClusterName(coll_name);
+    }
+
+    public void cleanUp() {}
+    
+    /** sets the site home */
+    public void setSiteHome(String site_home) {
+	this.site_home = site_home;
+    }
+    /** sets the site http address */
+    public void setSiteAddress(String site_address) {
+	this.site_http_address = site_address;
+    }
+
+    /** sets the message router */
+    public void setMessageRouter(MessageRouter m) {
+       this.router = m;
+    }
+
+    /** the no-args constructor */
+    public ServiceRack() {
+	this.converter = new XMLConverter();
+	this.doc = this.converter.newDOM();
+	this.short_service_info = this.doc.createElement(GSXML.SERVICE_ELEM+GSXML.LIST_MODIFIER);
+	this.format_info_map = new HashMap();
+    }
+    
+
+    /** configure the service module
+     *
+     * @param info the XML node <serviceRack name="XXX"/> with name equal
+     * to the class name (of the subclass)
+     *
+     * must configure short_service_info_ and service_info_map_
+     * @return true if configured ok
+     * must be implemented in subclasses
+     */
+    public boolean configure(Element info) {
+	return configure(info, null);
+    }
+    
+    public boolean configure(Element info, Element extra_info) {
+	// set up the class loader
+	this.class_loader = new CollectionClassLoader(this.getClass().getClassLoader(), this.site_home, this.cluster_name);
+	return true;
+    }
+
+    /**
+     * Process an XML document - convenience method that uses Strings rather than Elements. just calls process(Element).
+     *
+     * @param xml_in the Document to process - a string
+     * @return the resultant document as a string - contains any error messages
+     * @see String
+     */
+    public String process(String xml_in) {
+	
+	Document doc = this.converter.getDOM(xml_in);
+	if (doc == null) {
+	    logger.error("Couldn't parse request");
+	    logger.error(xml_in);
+	    return null;
+	}
+	Element res = process(doc.getDocumentElement());
+	return this.converter.getString(res);
+	
+    }
+
+    /** process an XML request in DOM form
+     *
+     * @param xml_in the Element node containing the request
+     * should be <message> 
+     * @return an Element with the result XML
+     * @see Element
+     */
+    public Element process(Element message) {
+
+	NodeList requests = message.getElementsByTagName(GSXML.REQUEST_ELEM);
+	Document mess_doc = message.getOwnerDocument();
+	Element mainResult = this.doc.createElement(GSXML.MESSAGE_ELEM);
+	if (requests.getLength()==0) {
+	    // no requests
+	    return mainResult; // empty message for now
+	}
+
+	for (int i=0; i<requests.getLength(); i++) {
+	    Element request = (Element)requests.item(i);
+	
+	    String type = request.getAttribute(GSXML.TYPE_ATT);
+	    if (type.equals(GSXML.REQUEST_TYPE_DESCRIBE)) {
+		Element response = processDescribe(request);
+		if (response !=null) {
+		    mainResult.appendChild(this.doc.importNode(response, true));
+		}
+		
+	    } else if (type.equals(GSXML.REQUEST_TYPE_FORMAT)) {
+		Element response = processFormat(request);
+		    mainResult.appendChild(this.doc.importNode(response, true));
+		
+	       
+	    } else {
+		// other type of request, must be processed by the subclass - 
+		// send to the service method
+		StringBuffer error_string = new StringBuffer();
+		String to = GSPath.getFirstLink(request.getAttribute(GSXML.TO_ATT));		
+		Element response = null;
+		try {
+		    Class c = this.getClass();
+		    Class []params = {Class.forName("org.w3c.dom.Element")};
+		    
+		    String method_name = "process"+to;
+		    Method m = null;
+		    while (c != null) {
+			
+			try {
+			    m = c.getDeclaredMethod(method_name, params);
+			    // if this has worked, break
+			    break;
+			} catch (NoSuchMethodException e) {
+			    c = c.getSuperclass();
+			} catch (SecurityException e) {
+			    logger.error("security exception for finding method "+method_name);
+			    error_string.append("ServiceRack.process: security exception for finding method "+method_name);
+			}
+		    } // while
+		    if (m != null) {
+			Object []args = {request};
+			try {
+			    response = (Element)m.invoke(this, args);
+			    
+			} catch (Exception e) {
+			    logger.error("Trying to call a processService type method (process"+to+") on a subclass("+this.getClass().getName()+"), but an exception happened:"+e.toString());
+			    error_string.append("Trying to call a processService type method (process"+to+") on a subclass("+this.getClass().getName()+"), but an exception happened:"+e.toString());
+			}
+		    } else {
+			logger.error("method "+method_name+" not found for class "+this.getClass().getName());
+			error_string.append("ServiceRack.process: method "+method_name+" not found for class "+this.getClass().getName());
+		    }
+		    
+		} catch (ClassNotFoundException e) {
+		    logger.error("Element class not found");
+		    error_string.append("Element class not found");
+		}
+		if (response !=null) {
+		    mainResult.appendChild(this.doc.importNode(response, true));
+		} else {
+		    // add in a dummy response
+		    logger.error("adding in an error element\n");
+		    response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+		    GSXML.addError(this.doc, response, error_string.toString());
+		    mainResult.appendChild(response);
+		    
+		}
+ 
+	    } // else process request
+	} // for each request
+	
+	return mainResult;
+		
+    }
+
+ 
+
+    /** process method for describe requests 
+     */
+    protected Element processDescribe(Element request) {
+	
+	Element response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	response.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_DESCRIBE);
+	
+	String lang = request.getAttribute(GSXML.LANG_ATT);
+	String to = GSPath.getFirstLink(request.getAttribute(GSXML.TO_ATT));
+	if (to.equals("")) { // return the service list
+	    response.appendChild(getServiceList(lang));
+	    return response;
+	} 
+	response.setAttribute(GSXML.FROM_ATT, to);
+	Element param_list = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	Element description = null;
+	if (param_list == null) {
+	    description = getServiceDescription(to, lang, null);
+	} else {
+	    NodeList params = param_list.getElementsByTagName(GSXML.PARAM_ELEM);
+	    for (int i=0; i<params.getLength(); i++) {
+		
+		Element param = (Element)params.item(i);
+		// Identify the structure information desired
+		if (param.getAttribute(GSXML.NAME_ATT).equals(GSXML.SUBSET_PARAM )) {
+		    String info = param.getAttribute(GSXML.VALUE_ATT);
+		    if (description == null) {
+			 description = getServiceDescription(to, lang, info);
+		    } else {
+			Element temp = getServiceDescription(to, lang, info);
+			GSXML.mergeElements(description, temp);
+		    }
+		}
+	    }
+	}
+	if (description != null) { // may be null if non-existant service
+	    response.appendChild(description);
+	}
+	return response;
+    
+    }
+
+    /** process method for stylesheet requests
+     */
+    protected Element processFormat(Element request) {
+	Element response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	response.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_FORMAT);
+	
+	String to = GSPath.getFirstLink(request.getAttribute(GSXML.TO_ATT));
+	
+	if (to.equals("")) { // serviceRack query - is this appropriate??
+	    return response;
+	} 
+	
+	
+	// describe a particular service	
+	if (this.format_info_map.containsKey(to)) {
+	    response.appendChild(getServiceFormat(to));
+	    response.setAttribute(GSXML.FROM_ATT, to);
+	    return response;
+	}
+	// else no format info
+	logger.error("ServiceRack describe request: no format info for "+to+".");
+	return response;
+    }	
+    
+    /** returns the service list for the subclass */
+    protected Element getServiceList(String lang) {
+	// for now, it is static and has no language stuff
+	return (Element) this.short_service_info.cloneNode(true);
+    }
+    
+    /** returns a specific service description */
+    abstract protected Element getServiceDescription(String service, String lang, String subset);
+
+    protected Element getServiceFormat(String service) {
+	Element format = (Element)((Element)this.format_info_map.get(service)).cloneNode(true);
+	return format;
+    }
+
+    /** overloaded version for no args case */
+    protected String getTextString(String key, String lang) {
+	return getTextString(key, lang, null, null);
+    }
+
+    protected String getTextString(String key, String lang, String dictionary) {
+	return getTextString(key, lang, dictionary, null);
+    }
+    protected String getTextString(String key, String lang, String [] args) {
+	return getTextString(key, lang, null, args);
+    }
+	
+    /** getTextString - retrieves a language specific text string for the given
+key and locale, from the specified resource_bundle (dictionary)
+    */
+    protected String getTextString(String key, String lang, String dictionary, String[] args) {
+
+	// we want to use the collection class loader in case there are coll specific files
+	if (dictionary != null) {
+	    // just try the one specified dictionary
+	    Dictionary dict = new Dictionary(dictionary, lang, this.class_loader);
+	    String result = dict.get(key, args);
+	    if (result == null) { // not found
+		return "_"+key+"_";
+	    }
+	    return result;
+	}
+
+	// now we try class names for dictionary names
+	String class_name = this.getClass().getName();
+	class_name = class_name.substring(class_name.lastIndexOf('.')+1);
+	Dictionary dict = new Dictionary(class_name, lang, this.class_loader);
+	String result = dict.get(key, args);
+	if (result != null) {
+	    return result;
+	}
+
+	// we have to try super classes
+	Class c = this.getClass().getSuperclass();
+	while (result == null && c != null) {
+	    class_name = c.getName();
+	    class_name = class_name.substring(class_name.lastIndexOf('.')+1);
+	    if (class_name.equals("ServiceRack")) {
+		// this is as far as we go
+		break;
+	    }
+	    dict = new Dictionary(class_name, lang, this.class_loader);
+	    result = dict.get(key, args);
+	    c = c.getSuperclass();
+	}
+	if (result == null) {
+	    return "_"+key+"_";
+	}
+	return result;
+	
+    }
+
+    protected String getMetadataNameText(String key, String lang) {
+
+	String properties_name = "metadata_names";
+	Dictionary dict = new Dictionary(properties_name, lang);
+	
+	String result = dict.get(key);
+	if (result == null) { // not found
+	    return null;
+	} 
+	return result;
+    }
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/TEIRetrieve.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/TEIRetrieve.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/TEIRetrieve.java	(revision 13928)
@@ -0,0 +1,52 @@
+package org.greenstone.gsdl3.service;
+
+
+// Greenstone classes
+import org.greenstone.gsdl3.util.*;
+
+// XML classes
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+// General Java classes
+
+// just needs to override a few methods that are TEI specific
+public class TEIRetrieve extends XMLRetrieve {
+
+   protected Element extractTitleMeta(Element section) {
+	
+	Element meta_elem = this.doc.createElement(GSXML.METADATA_ELEM);
+	meta_elem.setAttribute(GSXML.NAME_ATT, "Title");
+	
+	Element section_head = (Element)GSXML.getChildByTagName(section, "head");
+	if (section_head == null || !section_head.hasChildNodes()) {
+	    // there is no head element, so take the type attribute and make that the title
+	    String title = "("+section.getAttribute("type")+")";
+	    Text t = this.doc.createTextNode(title);
+	    meta_elem.appendChild(t);
+	} else {
+	    // add the head element as the metadata content
+	    meta_elem.appendChild(this.doc.importNode(section_head, true));
+	}
+	return meta_elem;
+    }
+
+    // this assumes that the scope refers to a top level node - this may be overwritten if the scope bit in the id is a shorthand of some sort
+    protected String translateScope(String scope) {
+	if (scope.equals("front")) {
+	    return "text/front";
+	}
+	if (scope.equals("body")) {
+	    return "text/body";
+	}
+	if (scope.equals("back")) {
+	    return "text/back";
+	}
+	if (scope.equals("full")) { // is this ever used???
+	    return "";
+	}
+	return scope;
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/XMLRetrieve.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/XMLRetrieve.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/XMLRetrieve.java	(revision 13928)
@@ -0,0 +1,448 @@
+package org.greenstone.gsdl3.service;
+
+
+// Greenstone classes
+import org.greenstone.gsdl3.util.*;
+
+// XML classes
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Text;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.NamedNodeMap;
+
+// General Java classes
+import java.io.File;
+import java.util.Vector;
+import java.util.HashMap;
+
+import org.apache.log4j.*;
+
+public class XMLRetrieve extends ServiceRack {
+
+      static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.XMLRetrieve.class.getName());
+    protected static final String CONTENT_SERVICE = "DocumentContentRetrieve";
+    protected static final String METADATA_SERVICE = "DocumentMetadataRetrieve";
+    protected static final String STRUCTURE_SERVICE = "DocumentStructureRetrieve";
+    
+    protected String toc_xsl_name = "";
+    protected String document_encoding = "";
+    protected String document_root_tag = "";
+    
+    protected Element collection_doc_list = null;
+    
+    protected boolean provide_content = true;
+    protected boolean provide_structure = true;
+    protected boolean provide_metadata = true;
+    
+
+    public boolean configure(Element info, Element extra_info) {
+	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+	logger.info("configuring XMLRetrieve...");
+	// look for the parameters
+	Element param_list = (Element)GSXML.getChildByTagName(info, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	HashMap params;
+	String services_to_provide = "";
+	if (param_list != null) {
+	    params = GSXML.extractParams(param_list, false);
+	    this.toc_xsl_name = (String)params.get("tocXSLT");
+	    this.document_encoding = (String)params.get("documentEncoding");
+	    this.document_root_tag = (String)params.get("documentRootTag");
+	    services_to_provide = (String)params.get("provideServices");
+	}
+	if (this.toc_xsl_name == null || this.toc_xsl_name.equals("")) {
+	    this.toc_xsl_name = "default_toc";
+	}
+	this.toc_xsl_name  = this.toc_xsl_name+".xsl";
+	
+	if (this.document_encoding == null || this.document_encoding.equals("")) {
+	    this.document_encoding = "UTF-8";
+	}
+	
+	if (services_to_provide != null && !services_to_provide.equals("")) {
+	    if (services_to_provide.indexOf("content")==-1) {
+		provide_content = false;
+	    }
+	    if (services_to_provide.indexOf("metadata")==-1) {
+		provide_metadata = false;
+	    }
+	    if (services_to_provide.indexOf("structure")==-1) {
+		provide_structure = false;
+	    }
+	    
+	}
+	
+	// set up short_service_info_ - for now just has name and type
+	Element retrieve_service;
+	if (provide_content) {
+	    retrieve_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	    retrieve_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
+	    retrieve_service.setAttribute(GSXML.NAME_ATT, CONTENT_SERVICE);
+	    this.short_service_info.appendChild(retrieve_service);
+	}
+	if (provide_metadata) {
+	    retrieve_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	    retrieve_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
+	    retrieve_service.setAttribute(GSXML.NAME_ATT, METADATA_SERVICE);
+	    this.short_service_info.appendChild(retrieve_service);
+	}
+	if (provide_structure) {
+	    retrieve_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	    retrieve_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
+	    retrieve_service.setAttribute(GSXML.NAME_ATT, STRUCTURE_SERVICE);
+	    this.short_service_info.appendChild(retrieve_service);
+	}
+	// find the doc list from the extra_info and keep it - should this be in collect.cfg or build.cfg??
+	collection_doc_list = (Element)GSXML.getChildByTagName(extra_info, GSXML.DOCUMENT_ELEM+GSXML.LIST_MODIFIER);
+
+	GSEntityResolver resolver = new GSEntityResolver();
+	resolver.setClassLoader(this.class_loader);
+	this.converter.setEntityResolver(resolver);
+	return true;
+    }
+
+    // this may get called but is not useful in the case of retrieve services
+    protected Element getServiceDescription(String service_id, String lang, String subset) {
+
+	Element retrieve_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	retrieve_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
+	retrieve_service.setAttribute(GSXML.NAME_ATT, service_id);
+	return retrieve_service;
+    }
+    
+    protected Element processDocumentContentRetrieve(Element request) {
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	result.setAttribute(GSXML.FROM_ATT, CONTENT_SERVICE);
+	result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+	
+	Element doc_list = (Element)GSXML.getChildByTagName(request, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	if (doc_list == null) {
+	    return result;
+	}
+	Element result_doc_list = (Element)this.doc.importNode(doc_list, true);
+	result.appendChild(result_doc_list);
+
+	NodeList docs = result_doc_list.getElementsByTagName(GSXML.DOC_NODE_ELEM);
+	for (int i=0; i<docs.getLength(); i++) {
+
+	    Element doc = (Element)docs.item(i);
+	    Element content = this.doc.createElement(GSXML.NODE_CONTENT_ELEM);
+	    doc.appendChild(content);
+
+	    String node_id = doc.getAttribute(GSXML.NODE_ID_ATT);
+	    String doc_name = getWorkName(node_id);
+	    
+	    Element doc_elem = loadDocument(doc_name); // should perhaps cache the read in docs??
+	    if (doc_elem == null) {
+		continue;
+	    } 
+
+	    
+	    // if we have asked for the whole doc, just append it
+	    if (doc_name.equals(node_id)) {
+		content.appendChild(this.doc.importNode(doc_elem, true));
+		continue;
+	    }
+		   
+	    // else we only want a sub section
+	    
+	    Element section = getSection(doc_elem, node_id);
+	    if (section != null) {
+		content.appendChild(this.doc.importNode(section, true));
+	    }
+	    
+	} // for each doc
+
+	return result;
+	
+    }
+    
+    protected Element processDocumentStructureRetrieve(Element request) {
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	result.setAttribute(GSXML.FROM_ATT, STRUCTURE_SERVICE);
+	result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+	
+	Element doc_list = (Element)GSXML.getChildByTagName(request, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	if (doc_list == null) {
+	    logger.error("no documents specified in the request. ");
+	    return result;
+	}
+
+	Element result_doc_list = (Element)this.doc.importNode(doc_list, true);
+	result.appendChild(result_doc_list);
+	// first look for the stylesheet in the collection
+	File stylesheet = new File(GSFile.collStylesheetFile(this.site_home, this.cluster_name, this.toc_xsl_name));
+	if (!stylesheet.exists()) {
+	    // now try in the site
+	    stylesheet = new File(GSFile.siteStylesheetFile(this.site_home, this.toc_xsl_name));
+	}
+	if (!stylesheet.exists()) {
+	    logger.error("couldn't find the stylesheet file to produce the table of contents:"+stylesheet.getPath());
+	    return result;
+	}
+
+	// for now, we dont have any params, and we always return the structure of the whole document
+	
+	XMLTransformer transformer = new XMLTransformer();
+	NodeList docs = result_doc_list.getElementsByTagName(GSXML.DOC_NODE_ELEM);
+
+	for (int i=0; i<docs.getLength(); i++) {
+
+	    Element doc = (Element)docs.item(i);
+	    
+	    Element structure = this.doc.createElement(GSXML.NODE_STRUCTURE_ELEM);
+	    doc.appendChild(structure);
+	    String doc_name = doc.getAttribute(GSXML.NODE_ID_ATT);
+	    // make sure we are at the top level
+	    doc_name = getWorkName(doc_name);
+	    
+	    File doc_file = new File(GSFile.collectionIndexDir(this.site_home, this.cluster_name)+File.separator+"text"+File.separatorChar+doc_name+".xml");
+	    
+	    if (!doc_file.exists()) {
+		logger.error("couldn't find file in coll "+this.cluster_name +", file "+doc_name+".xml");
+	    } else {
+		try {
+		    Node toc = transformer.transform(stylesheet, doc_file);
+		    structure.appendChild(this.doc.importNode(toc, true));
+		} catch (Exception e) {
+		    logger.error("couldn't transform the document to get the toc");
+		}
+	    }
+	    
+	}
+	
+	return result;
+	
+    }
+    
+    // this just extracts a bit of text from the section to use as the Title
+    // this should be overwritten for any format that  has something more suitable
+    protected Element processDocumentMetadataRetrieve(Element request) {
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	result.setAttribute(GSXML.FROM_ATT, METADATA_SERVICE);
+	result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+	
+	Element doc_list = (Element)GSXML.getChildByTagName(request, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	if (doc_list == null) {
+	    logger.error("no documents in the request");
+	    return result;
+	}
+
+	Element result_doc_list = (Element)this.doc.importNode(doc_list, true);
+	result.appendChild(result_doc_list);
+
+	Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	if (param_list == null) {
+	    logger.error("no metadata in the request");
+	    return result;
+	}
+	
+	Vector meta_name_list = new Vector();
+	boolean all_metadata = false;
+	// Process the request parameters
+	Element param = (Element) param_list.getFirstChild();
+	while (param != null) {
+	    // Identify the metadata information desired
+	    if (param.getAttribute(GSXML.NAME_ATT).equals("metadata")) {
+		String metadata = GSXML.getValue(param);
+		if (metadata.equals("all")) {
+		    all_metadata = true;
+		    break;
+		}
+		meta_name_list.add(metadata);
+	    }
+	    param = (Element) param.getNextSibling();
+	}
+		
+	NodeList docs = result_doc_list.getElementsByTagName(GSXML.DOC_NODE_ELEM);
+	for (int i=0; i<docs.getLength(); i++) {
+	    Element doc = (Element)docs.item(i);
+	    String node_id = doc.getAttribute(GSXML.NODE_ID_ATT);
+	    String doc_name = getWorkName(node_id);
+	    
+	    Element metadata_list = getMetadata(node_id, all_metadata, meta_name_list); 
+	    doc.appendChild(metadata_list);
+	}
+	
+	return result;
+    }
+    
+    protected Element loadDocument(String doc_name) {
+	// try to find the document
+	File doc_file = new File(GSFile.collectionIndexDir(this.site_home, this.cluster_name)+File.separator+"text"+File.separatorChar+doc_name+".xml");
+	    
+	if (!doc_file.exists()) {
+	    logger.info("couldn't find file in coll "+this.cluster_name +", file "+doc_name+".xml");
+	    return null;
+	}
+	
+	Document the_doc = null;
+	try {
+	    the_doc = this.converter.getDOM(doc_file, this.document_encoding);
+	} catch (Exception e) {
+	    logger.error("couldn't create a DOM from file "+doc_file.getPath());
+	    return null;
+	}
+	
+	return the_doc.getDocumentElement();
+
+    }
+
+    
+    protected Element getSection(Element doc_elem, String node_id) {
+	String [] bits = node_id.split("\\.");
+	if (bits.length > 4) {
+	    logger.error("badly formatted node id ("+node_id +"), cant retrieve the section");
+	    return null;
+	}
+	    
+	String id="";
+	String tagname = "";
+	String scope = "";
+	if (bits.length==2) {
+	    tagname = bits[1];
+	} else { 
+	    scope = bits[1];
+	    tagname = bits[2];
+	    
+	    if (bits.length == 4) {
+		id = bits[3];
+	    }
+	}
+	scope = translateScope(scope);
+	Element top=null;
+	if (!scope.equals("")) {
+	    top = (Element)GSXML.getNodeByPath(doc_elem, scope);
+	    if (top == null) {
+		// something gone wrong
+		return null;
+	    }
+	} else {
+	    top = doc_elem;
+	}
+	
+	NodeList elements = top.getElementsByTagName(tagname);
+	if (elements.getLength() == 0) {
+	    return null;
+	}
+	// no id, just return the first one
+	if (id.equals("")) {
+	    return (Element)elements.item(0);
+	}
+	// have an id, need to check and find the right one.
+	for (int i=0; i<elements.getLength();i++) {
+	    Element e = (Element)elements.item(i);
+	    if (e.getAttribute("gs3:id").equals(id)) {
+		return e;
+	    }
+	}
+	return null;
+	
+    }
+
+    protected Element getMetadata(String node_id, boolean all, Vector meta_name_list) {
+
+	// our default strategy here is to only return Title and root:Title
+	// ignore all others 
+	// the title of a section is just a little bit of the text inside it.
+	// the root_Title is the title from the doc info in the config file
+	Element metadata_list = this.doc.createElement(GSXML.METADATA_ELEM+ GSXML.LIST_MODIFIER);
+	String doc_name = getWorkName(node_id);
+	boolean node_is_root = false;
+	if (doc_name.equals(node_id)) {
+	    node_is_root = true;
+	}
+	
+	Element this_doc = GSXML.getNamedElement(this.collection_doc_list, GSXML.DOCUMENT_ELEM, GSXML.NAME_ATT, doc_name);
+	Element doc_meta_list  = (Element) GSXML.getChildByTagName(this_doc, GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
+	
+	boolean get_section_title = false;
+	
+	if (all) {
+	    if (node_is_root) {
+	    return (Element)this.doc.importNode(doc_meta_list, true);
+	    } else {
+		get_section_title = true;
+	    }
+	    
+	} else {
+	    // have to process metadata one by one
+	    for (int i=0; i<meta_name_list.size(); i++) {
+		String meta_name = (String) meta_name_list.elementAt(i);
+		String actual_meta_name = meta_name;
+		if (meta_name.startsWith("root_")) {
+		    actual_meta_name = meta_name.substring(5);
+		} else {
+		    // its a section level one - check to see if doc is root
+		    if (!node_is_root) {
+			if (meta_name.equals("Title")) {
+			    get_section_title = true;
+			}
+			continue; // move on to teh next metadata
+		    }
+		}
+		
+		// here, we look for the specific meta elem in doc_meta_list
+		Element meta_item = GSXML.getNamedElement(doc_meta_list, GSXML.METADATA_ELEM, GSXML.NAME_ATT, actual_meta_name);
+		if (meta_item != null) {
+		    meta_item = (Element)this.doc.importNode(meta_item, true);
+		    meta_item.setAttribute(GSXML.NAME_ATT, meta_name);
+		    metadata_list.appendChild(meta_item);
+		}
+	    } // for each metadata
+	}
+
+	// now we have processed all teh doc metadata, just have section one to go, if needed
+	if (get_section_title) {
+	    
+	    Element doc_elem = loadDocument(doc_name);
+	    if (doc_elem != null) {
+		Element section = getSection(doc_elem, node_id);
+		if (section != null) {
+		    Element title_meta = extractTitleMeta(section);
+		    if (title_meta != null) {
+			metadata_list.appendChild(title_meta);
+		    }
+		}
+	    }
+		
+	}
+	return metadata_list;
+    }
+    
+    protected Element extractTitleMeta(Element section) {
+	Element meta_elem = this.doc.createElement(GSXML.METADATA_ELEM);
+	meta_elem.setAttribute(GSXML.NAME_ATT, "Title");
+
+	String title = "dummy title";
+	Text t = this.doc.createTextNode(title);
+	meta_elem.appendChild(t);
+	return meta_elem;
+
+    }
+    // some methods for handling nodeIDs - they may be different for different colls, so they can be overwritten
+
+    // the full default nodeID looks like work.scope.tag.id
+    // the shorter versions are work, work.tag, work.scope.tag
+    protected String getWorkName(String node_id) {
+	int pos = node_id.indexOf('.');
+	if (pos == -1) {
+	    return node_id;
+	}
+	return node_id.substring(0, pos);
+    }
+    
+    // this assumes that the scope refers to a top level node - this may be overwritten if the scope bit in the id is a shorthand of some sort
+    protected String translateScope(String scope) {
+	if (this.document_root_tag != null) {
+	    return GSPath.appendLink(this.document_root_tag, scope);
+	}
+	return scope;
+    }
+    
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/XSLTServices.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/XSLTServices.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/service/XSLTServices.java	(revision 13928)
@@ -0,0 +1,268 @@
+/*
+ *    XSLTServices.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.service;
+
+import org.greenstone.gsdl3.util.*;
+import org.greenstone.gsdl3.selfContained.*;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import org.apache.xerces.dom.DocumentImpl;
+import org.apache.xerces.dom.ElementImpl;
+import org.apache.xerces.dom.TextImpl;
+import org.w3c.dom.Document; 
+import org.w3c.dom.Node; 
+import org.w3c.dom.Text; 
+import org.w3c.dom.Element; 
+import org.w3c.dom.NodeList; 
+
+import java.util.HashMap;
+import java.util.Vector;
+import java.util.Set;
+import java.util.Map;
+import java.util.Iterator;
+import java.util.Locale;
+import java.io.*;
+import java.net.URLEncoder;
+import java.net.URLDecoder;
+
+import org.apache.log4j.*;
+
+/**
+ * A ServiceRack class for XSLT query. 
+ *
+ * Document ids are formed by encoding the document using standard URLEncoding
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ * @author <a href="mailto:s.yeates@cs.waikato.ac.nz">Stuart Yeates</a>
+ * @version $Revision$
+ * @see ServiceRack
+ * @see java.net.URLEncoder
+ * @see java.net.URLDecoder
+ */
+
+public class XSLTServices 
+  extends ServiceRack {
+  
+    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.XSLTServices.class.getName());
+
+  // these strings must match what is found in the properties file
+  // the services on offer
+  private static final String XSLT_QUERY_SERVICE        = "XSLTQuery";
+  private static final String RESOURCE_RETRIEVE_SERVICE = "ResourceRetrieve";
+  // params used
+  private static final String QUERY_PARAM        = "query";
+  private static final String ALPHABET_PARAM     = "alphabet";
+  
+  private static final int RESULT_SET_SIZE        = 10;
+
+  // alphabets
+  private static final String MINIMUM_ALPHABET   = "minimum";
+  private static final String ASCII_ALPHABET     = "ascii";
+  private static final String UNICODE_ALPHABET   = "unicode";
+
+  private static final String DEFAULT_QUERY_STRING   =
+    "<xsl:stylesheet version=\"1.0\""+
+    "                xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">"+
+    "    <xsl:template match=\"*|/\">"+
+    "         <xsl:apply-templates/>"+
+    "    </xsl:template>"+
+    "    <xsl:template match=\"*|/\" mode=\"m\">"+
+    "         <xsl:apply-templates mode=\"m\"/>"+
+    "    </xsl:template>"+
+    "    <xsl:template match=\"text()|@*\">"+
+    "         <xsl:value-of select=\".\"/>"+
+    "    </xsl:template>"+
+    "    <xsl:template match=\"processing-instruction()|comment()\"/>"+
+    "</xsl:stylesheet>";
+  
+
+  private String alphabet = MINIMUM_ALPHABET;
+  private Element config_info_ = null;
+  
+
+  public XSLTServices() {
+  }
+  
+    /** configure this service */
+    public boolean configure(Element info, Element extra_info) {
+      	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+
+      logger.info("configuring XSLTServices");
+      this.config_info = info;
+    try {
+      logger.info("called with:");
+      TransformerFactory transformerFactory = TransformerFactory.newInstance();
+      Element doc = (Element)info.getFirstChild();
+      Transformer transformer = transformerFactory.newTransformer();
+      StreamResult result = new StreamResult(System.out);
+      Source source = new DOMSource(doc);
+      transformer.transform(source,result);
+    } catch (Throwable t) {
+      logger.error("Error printing XML in XSLTService::configure()");
+    }
+    return true;    
+  }
+
+    protected Element getServiceDescription(String service, String lang, String subset) {
+
+	return null;
+    }
+  
+  /** process method for specific services - must be implemented by all
+   * subclasses
+   * should implement all services supported by the servicesImpl except
+   * for describe, which is implemented by this base class
+   *
+   */
+  protected Element processService(String service, Element request){
+    if (service.equals(XSLT_QUERY_SERVICE)) {
+      return processXSLTQuery(request);
+    } else if (service.equals(RESOURCE_RETRIEVE_SERVICE)) {
+      return processResourceRetrieve(request);
+    }
+    // create the response so we can report the error
+    Element response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+    String from = GSPath.appendLink(this.cluster_name, RESOURCE_RETRIEVE_SERVICE);
+    response.setAttribute(GSXML.FROM_ATT, from);
+    response.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+    
+    logger.error("should never get here. service type wrong:"+service);
+    GSXML.addError(this.doc, response,"XSLTServices:should never get here. service type wrong:"+service);
+    return response;
+  }
+
+  /** process a document resquest query */
+  protected Element processResourceRetrieve(Element request) {
+    
+    // create the result and set the path so we know where we are
+    Element response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+    String from = GSPath.appendLink(this.cluster_name, RESOURCE_RETRIEVE_SERVICE);
+    response.setAttribute(GSXML.FROM_ATT, from);
+    response.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+
+    // get param list 
+    Element param_elem=null;
+    Node n = request.getFirstChild();
+    while (n!=null) {
+	String node_name = n.getNodeName();
+	if (node_name.equals(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER)) {
+	    param_elem = (Element)n;
+	    break;
+	}
+	n = n.getNextSibling();
+    }
+
+    if (param_elem==null) { 
+	logger.error("bad query request");
+	GSXML.addError(this.doc, response,"bad query request in XSLTServices");
+	return response; 
+    }
+    
+    // Documents are just the ids decoding using standard URL decoding
+    
+    Element doc_list = (Element)GSXML.getChildByTagName(request, GSXML.DOCUMENT_ELEM+GSXML.LIST_MODIFIER);
+    String []ids = GSXML.getAttributeValuesFromList(doc_list, GSXML.NAME_ATT);
+    for (int j=0; j<ids.length; j++) {
+      String document = null;
+      try {
+	document = URLDecoder.decode(ids[j],"UTF-8");
+      } catch (UnsupportedEncodingException e) {
+	throw new Error(e.toString());
+      }
+      // something funny with the doc - 
+      Element new_doc = this.doc.createElement(GSXML.DOCUMENT_ELEM);
+      new_doc.setAttribute(GSXML.NAME_ATT, ids[j]); //GSXML.createDocumentElement(this.doc, ids[j]);
+      GSXML.addDocText(this.doc, new_doc, document);
+      response.appendChild(new_doc);
+    }
+    
+    return response;
+  }
+  
+  /** process a XSLT query */
+  protected Element processXSLTQuery(Element request) {
+    
+    // create the result and set the path so we know where we are
+    Element response = this.doc.createElement(GSXML.RESPONSE_ELEM);
+    String from = GSPath.appendLink(this.cluster_name, XSLT_QUERY_SERVICE);
+    response.setAttribute(GSXML.FROM_ATT, from);
+    response.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+
+    // get the parameter list
+    Element param_list = 
+      (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+
+    // extract the only parameter we care about
+    HashMap params = GSXML.extractParams(param_list, false);
+    String query = (String)params.get(QUERY_PARAM);
+    
+    if (query == null || query.equals(""))
+      query = DEFAULT_QUERY_STRING;
+    
+    
+    DocumentStream stream = null;
+    if (alphabet.equals(MINIMUM_ALPHABET)){
+      stream = new GeneratedDocumentStream('a','c');
+    } else if(alphabet.equals(ASCII_ALPHABET)){
+      stream = new GeneratedDocumentStream();
+    } else if(alphabet.equals(UNICODE_ALPHABET)){
+      stream = new GeneratedDocumentStream(Character.MIN_VALUE,
+					   Character.MAX_VALUE);
+    } else {
+      logger.error("bad alphabet name : "+ alphabet);
+      GSXML.addError(this.doc, response,"XSLTServices: bad alphabet name : "+ alphabet);
+      stream = new GeneratedDocumentStream();
+    }
+
+    Element resource_list = this.doc.createElement(GSXML.RESOURCE_ELEM+GSXML.LIST_MODIFIER);
+    response.appendChild(resource_list);
+
+    // Framework to stringise the document
+    TransformerFactory transformerFactory = TransformerFactory.newInstance();
+
+    // add each resource
+    for (int d=0; d<RESULT_SET_SIZE; d++) {
+      try {
+	Document document = stream.nextDocument();
+	Element doc = (Element)document.getFirstChild();
+	Transformer transformer = transformerFactory.newTransformer();
+	StringWriter writer = new StringWriter();
+	StreamResult result = new StreamResult(writer);
+	Source source = new DOMSource(doc);
+	transformer.transform(source,result);
+	String id = writer.toString();
+	Element e = this.doc.createElement(GSXML.DOCUMENT_ELEM);
+	e.setAttribute(GSXML.NAME_ATT, id); 
+	//Node no = GSXML.createDocumentElement(this.doc, id);
+	resource_list.appendChild(e);
+      } catch (Throwable t) {
+	GSXML.addError(this.doc, response, "Error in XSLTServices finding results:" + t.toString());
+      }
+    }
+    return response; 
+  }
+}  
+ 
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/CollectionClassLoader.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/CollectionClassLoader.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/CollectionClassLoader.java	(revision 13928)
@@ -0,0 +1,45 @@
+/*
+ *    CollectionClassLoader.java
+ *    Copyright (C) 2005 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.util;
+
+import java.net.URL;
+import java.io.File;
+
+/** Looks for classes/resources in the collection resources directory 
+ */
+public class CollectionClassLoader
+    extends ClassLoader {
+
+    String base_dir = null;
+    public CollectionClassLoader(ClassLoader parent, String site_home, String collection_name) {
+	super(parent);
+	this.base_dir = GSFile.collectionResourceDir(site_home, collection_name);
+    } 
+
+    public URL findResource(String name) {
+	File resource_path = new File(this.base_dir, name);
+	try {
+	    if (resource_path.exists()) {
+		return new URL("file://"+resource_path.getAbsolutePath());
+	    }
+	} catch (Exception e) {};
+
+	return super.findResource(name);
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/DBInfo.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/DBInfo.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/DBInfo.java	(revision 13928)
@@ -0,0 +1,64 @@
+package org.greenstone.gsdl3.util;
+
+import java.util.Vector;
+import java.util.HashMap;
+import java.util.Set;
+/** class to hold info from a gdbm (or equiv) query
+ * maps a String key to a list of Strings (values)
+ * at the moment, the user must know if something has a single value or not
+ */
+public class DBInfo {
+
+    protected HashMap info_map_;
+
+    public DBInfo() {
+	info_map_ = new HashMap();
+    }
+
+    // methods for keys that can have a single value
+
+    /** set the value for a key - replaces any existing value */
+    public void setInfo(String key, String value) {
+	Vector v = new Vector();
+	v.add(value);
+	info_map_.put(key, v);
+    }
+
+    /** get the value - used for keys that have one value, otherwise just
+     * returns the first one */
+    public String getInfo(String key) {
+	Vector items = (Vector)info_map_.get(key);
+	if (items==null) {
+	    return "";
+	}
+	return (String)items.firstElement();
+    }
+
+    // methods for keys that can have multiple values
+    
+    /** add a value to a key - for keys that can have multiple values */
+    public void addInfo(String key, String value) {
+	Vector v = (Vector)info_map_.get(key);
+	if (v==null) {
+	    v = new Vector();
+	}
+	v.add(value);
+	info_map_.put(key, v);
+    }
+    /** return a vector of all values associated with a key 
+     * @return Vector of Strings
+     */
+    public Vector getMultiInfo(String key) {
+	return (Vector)info_map_.get(key);
+    }
+
+    /** returns a list of all the keys in the info */
+    public Set getKeys() {
+	return info_map_.keySet();
+    }
+    /** returns the Info as a string */
+    public String toString() {
+	return info_map_.toString();
+
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/Dictionary.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/Dictionary.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/Dictionary.java	(revision 13928)
@@ -0,0 +1,150 @@
+/*
+ *    Dictionary.java
+ *    Copyright (C) 2005 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.util;
+
+import java.util.ResourceBundle;
+import java.util.Locale;
+import java.util.Enumeration;
+
+import org.apache.log4j.*;
+
+public class Dictionary {
+
+    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.Dictionary.class.getName());
+
+    /** The locale of this dictionary. */
+    protected Locale locale = null;
+    
+    /** The resource that has been loaded */
+    protected String resource = null;
+
+    /** The ResourceBundle which contains the raw key-value mappings. Loaded from a file named "resource_locale.properties*/
+    private ResourceBundle raw = null;
+
+    /**  Constructs the Dictionary class by first creating a locale from the specified language, (or using the default locale if this didn't work), then loading a resource bundle based on this locale. 
+     */
+    public Dictionary(String resource, String lang) {
+	// Initialize.
+	
+	this.locale = new Locale(lang);
+	this.resource = resource;
+	if (this.locale == null) {
+	    this.locale = Locale.getDefault();
+	}
+	try {
+	    this.raw = ResourceBundle.getBundle(this.resource, this.locale);
+	} catch (Exception e) {
+	    logger.debug("Dictionary: couldn't locate a resource bundle for "+resource);
+	}
+    }
+
+    public Dictionary(String resource, Locale locale) {
+	this.locale = locale;
+	this.resource = resource;
+	try {
+	    this.raw = ResourceBundle.getBundle(this.resource, this.locale);
+	} catch (Exception e) {
+	    logger.debug("Dictionary: couldn't locate a resource bundle for "+resource);
+	}
+    }
+
+    /**  Constructs the Dictionary class by first creating a locale from the specified language, (or using the default locale if this didn't work), then loading a resource bundle based on this locale. A classloader is specified which can be used to find the resource.
+     */
+    public Dictionary(String resource, String lang, ClassLoader loader) {
+	// Initialize.
+	
+	this.locale = new Locale(lang);
+	this.resource = resource;
+	if (this.locale == null) {
+	    this.locale = Locale.getDefault();
+	}
+	// try the specified class loader
+	try {
+	    this.raw = ResourceBundle.getBundle(this.resource, this.locale, loader);
+	    return;
+	} catch (Exception e) {};
+	
+	try {
+	    this.raw = ResourceBundle.getBundle(this.resource, this.locale);
+	} catch (Exception ex) {
+	    logger.debug("Dictionary: couldn't locate a resource bundle for "+resource);
+	}
+	
+    }
+
+    
+    public Enumeration getKeys() {
+	if (this.raw != null) {
+	    return this.raw.getKeys();
+	}
+	return null;
+    }
+    /** Overloaded to call get with both a key and an empty argument array.
+     * @param key A <strong>String</strong> which is mapped to a initial String within the ResourceBundle.
+     * @return A <strong>String</strong> which has been referenced by the key String and that  contains no argument fields.
+     */
+    public String get(String key) {
+	return get(key, null);
+    }
+    
+    /** Used to retrieve a property value from the Locale specific ResourceBundle, based upon the key and arguments supplied. If the key cannot be found or if some other part of the call fails a default (English) error message is returned. <BR>
+     * Here the get recieves a second argument which is an array of Strings used to populate argument fields, denoted {<I>n</I>}, within the value String returned.
+     * @param key A <strong>String</strong> which is mapped to a initial String within the ResourceBundle.
+     * @param args A <strong>String[]</strong> used to populate argument fields within the complete String.
+     * @return A <strong>String</strong> which has been referenced by the key String and that either contains no argument fields, or has had the argument fields  populated  with argument Strings provided in the get call.
+     */
+    public String get(String key, String args[]) {
+	if (this.raw == null) {
+	    return null;
+	}
+	try {
+	    String initial_raw = this.raw.getString(key);
+	    // convert to unicode, copied from gatherer dictionary
+	    String initial = new String(initial_raw.getBytes("ISO-8859-1"), "UTF-8");
+	    // If the string contains arguments we have to insert them.
+	    String complete = "";
+	    // While we still have initial string left.
+	    while(initial.length() > 0 && initial.indexOf('{') != -1 && initial.indexOf('}') != -1) {
+		// Remove preamble
+		int opening = initial.indexOf('{');
+		int closing = initial.indexOf('}');
+		complete = complete + initial.substring(0, opening);
+		// Parse arg_num
+		String arg_str = initial.substring(opening + 1, closing);
+		int arg_num = Integer.parseInt(arg_str);
+		if(closing + 1 < initial.length()) {
+		    initial = initial.substring(closing + 1);
+		}
+		else {
+		    initial = "";
+		}
+		// Insert argument
+		if(args != null && 0 <= arg_num && arg_num < args.length) {
+		    complete = complete + args[arg_num];
+		}
+	    }
+	    return complete + initial;
+	}
+	catch (Exception e) {
+	    logger.debug("Dictionary Error: couldn't find string for key:" + key +" in resource "+this.resource);
+	    return null;
+	}
+    }
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GDBMWrapper.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GDBMWrapper.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GDBMWrapper.java	(revision 13928)
@@ -0,0 +1,295 @@
+package org.greenstone.gsdl3.util;
+
+import au.com.pharos.gdbm.GdbmFile;
+import au.com.pharos.packing.*;
+import au.com.pharos.gdbm.GdbmException;
+
+import org.apache.log4j.*;
+
+/** java wrapper class for gdbm - uses Java-GDBM written by Martin Pool
+ * replaces gdbmclass in the old version
+ */
+
+public class GDBMWrapper {
+
+      static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.GDBMWrapper.class.getName());
+
+
+    // Values must match those from gdbm.h - uses the definitions from GdbmFile !
+    /** Indicates that the caller will just read the database.  Many
+     * readers may share a database. */
+    public final static int READER = GdbmFile.READER;
+ 
+    /** The caller wants read/write access to an existing database and
+     * requires exclusive access. */
+    public final static int WRITER = GdbmFile.WRITER;
+ 
+    /** The caller wants exclusive read/write access, and the database
+     * should be created if it does not already exist. */
+    public final static int WRCREAT = GdbmFile.WRCREAT;
+ 
+    /** The caller wants exclusive read/write access, and the database
+     * should be replaced if it already exists. */
+    public final static int NEWDB = GdbmFile.NEWDB;
+
+    protected GdbmFile db_=null;
+
+    /** open the database filename, with mode mode - uses the constants
+	above, eg GdbmFile.WRITER */
+    public boolean openDatabase(String filename, int mode){
+	try {
+	    if (db_!=null) {
+		db_.close();
+	    }
+	    db_ = new GdbmFile(filename, mode);
+	} catch ( GdbmException e) { // the database wasn't opened or created
+	    logger.error("couldn't open database "+filename);
+	    return false;
+	} 
+	db_.setKeyPacking(new StringPacking());
+	db_.setValuePacking(new StringPacking());
+	return true;
+    }
+
+    /** cloase the database associated with this wrapper */
+    public void closeDatabase() {
+	try {
+	    if (db_ != null) {
+		db_.close();
+		db_ = null;
+	    }
+	} catch (GdbmException e) {
+	    // should never get here - close never actually throws an exception
+	    logger.error("error on close()");
+	}
+    }
+
+    /** returns a DBInfo object containing all the name-value pairs for 
+     * main_key 
+     * @see DBInfo
+     */
+    public DBInfo getInfo(String main_key) {
+	if (db_==null) {
+	    return null;
+	}
+	String s_info;
+	try {
+	    s_info = (String)db_.fetch(main_key);
+	} catch (GdbmException e) {
+	    logger.error("couldn't get record");
+	    return null;
+	}
+	if (s_info==null) {
+	    // record not present
+	    logger.error("key "+main_key+" not present in db");
+	    return null;
+	}
+	DBInfo info = new DBInfo();
+
+	String [] lines = s_info.split("\n");
+	String key;
+	String value;
+	for (int i=0; i<lines.length; i++) {
+	    logger.debug("line:"+lines[i]);
+	    int a = lines[i].indexOf('<');
+	    int b= lines[i].indexOf('>');
+	    if (a==-1 || b==-1) {
+		logger.error("bad format in db");
+	    }
+	    else {
+		key=lines[i].substring(a+1, b);
+		value=lines[i].substring(b+1);
+		logger.debug("key="+key+", val="+value);
+		info.addInfo(key, value);
+
+	    }
+	}
+	return info;
+    }
+
+    /** sets all the name-value pairs in info as the content for key key 
+     * TODO - not implemented yet */
+    public boolean setInfo(String key, DBInfo info) {
+	if (db_==null) {
+	    return false;
+	}
+	return true;
+    }
+    /** sets the key value as info 
+     * TODO - not implemented yet */
+    public boolean setInfo (String key, String info) {
+	if (db_==null) {
+	    return false;
+	}
+	return true;
+    }
+    /** deletes the entry for key 
+     * TODO - not implemented yet */
+    public boolean deleteKey(String key) {
+	if (db_==null) {
+	    return false;
+	}
+	return true;
+    }
+
+    // greenstone convenience methods - should these go into a separate class?
+    // yes I think so.
+    /** converts a greenstone OID to internal docnum */
+    public long OID2Docnum(String OID) {
+	DBInfo info = getInfo(OID);
+	if (info != null) {
+	    long real_num = Long.parseLong(info.getInfo("docnum"));
+	    return real_num;
+	}
+	return -1;
+    }
+    /** converts a docnum to greenstone OID */
+    public String docnum2OID(long docnum) {
+	return docnum2OID(Long.toString(docnum));
+    }
+    
+    /** converts a docnum to greenstone OID */
+    public String docnum2OID(String docnum) {
+	DBInfo info = getInfo(docnum);
+	String oid = info.getInfo("section");
+	return oid;
+    }
+
+    /** converts an external id to greenstone OID */
+    public String externalId2OID(String extid) {
+	DBInfo info = getInfo(extid);
+	if (info != null) {
+	    String oid = info.getInfo("section");
+	    return oid;
+	}
+	return null;
+    }
+    /** translates relative oids into proper oids:
+     * .pr (parent), .rt (root) .fc (first child), .lc (last child),
+     * .ns (next sibling), .ps (previous sibling) 
+     * .np (next page), .pp (previous page) : links sections in the order that you'd read the document
+     * a suffix is expected to be present so test before using 
+     */
+    public String translateOID(String oid) {
+
+	int p = oid.lastIndexOf('.');
+	if (p != oid.length()-3) {
+	    logger.info("translateoid error: '.' is not the third to last char!!");
+	    return oid;
+	}
+	
+	String top = oid.substring(0, p);
+	String suff = oid.substring(p+1);
+	// just in case we have multiple extensions, we must translate
+	// we process inner ones first
+	if (OID.needsTranslating(top)) {
+	    top = translateOID(top);
+	}
+	if (suff.equals("pr")) {
+	    return OID.getParent(top);
+	} 
+	if (suff.equals("rt")) {
+	    return OID.getTop(top);
+	} 
+	if (suff.equals("np")) {
+	    // try first child
+	    String node_id = translateOID(top+".fc");
+	    if (!node_id.equals(top)) {
+		return node_id;
+	    }
+	    // try next sibling
+	    node_id = translateOID(top+".ns");
+	    if (!node_id.equals(top)) {
+		return node_id;
+	    }
+	    // otherwise we keep trying parents sibling
+	    String child_id = top;
+	    String parent_id = OID.getParent(child_id);
+	    while(!parent_id.equals(child_id)) {
+		node_id = translateOID(parent_id+".ns");
+		if (!node_id.equals(parent_id)) {
+		    return node_id;
+		}
+		child_id = parent_id;
+		parent_id = OID.getParent(child_id);
+	    }
+	    return top; // we couldn't get a next page, so just return the original
+	} 
+	if (suff.equals("pp")) {
+	    String prev_sib = translateOID(top+".ps");
+	    if (prev_sib.equals(top)) {
+		// no previous sibling, so return the parent
+		return OID.getParent(top);
+	    }
+	    // there is a previous sibling, so its either this section, or the last child of the last child..
+	    String last_child = translateOID(prev_sib+".lc");
+	    while (!last_child.equals(prev_sib)) {
+		prev_sib = last_child;
+		last_child = translateOID(prev_sib+".lc");
+	    }
+	    return last_child;
+	} 
+	
+	int sibling_num = 0;
+	if (suff.equals("ss")) {
+	    // we have to remove the sib num before we get top
+	    p = top.lastIndexOf('.');
+	    sibling_num = Integer.parseInt(top.substring(p+1));
+	    top = top.substring(0, p);
+	}
+	
+	// need to get info out of gdbm db -
+	String doc_id = top;
+	if (suff.endsWith("s")) {
+	    doc_id = OID.getParent(top);
+	    if (doc_id.equals(top)) {
+		// i.e. we are already at the top
+		return top;
+	    }
+	}
+	DBInfo info = getInfo(doc_id);
+	if (info==null) {
+	    logger.info("info is null!!");
+	    return top;
+	}
+	
+	String contains = info.getInfo("contains");
+	if (contains.equals("")) {
+	    // something is wrong
+	    return top;
+	}
+	contains = contains.replaceAll("\"", doc_id);
+	String [] children = contains.split(";");
+	if (suff.equals("fc")) {
+	    return children[0];
+	} else if (suff.equals("lc")) {
+	    return children[children.length-1];
+	} else {
+	    if (suff.equals("ss")) {
+		return children[sibling_num-1];
+	    }
+	    // find the position that we are at.
+	    int i=0;
+	    while (i<children.length) {
+		if (children[i].equals(top)) {
+		    break;
+		}
+		i++;
+	    }
+	    
+	    if (suff.equals("ns")) {
+		if (i==children.length-1) {
+		    return children[i];
+		}
+		return children[i+1];
+	    } else if (suff.equals("ps")) {
+		if (i==0) {
+		    return children[i];
+		}
+		return children[i-1];
+	    }
+	}
+	
+	return top;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GS2MacroResolver.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GS2MacroResolver.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GS2MacroResolver.java	(revision 13928)
@@ -0,0 +1,116 @@
+/*
+ *    GS2MacroResolver.java
+ *    Copyright (C) 2005 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.util;
+
+import java.util.ArrayList;
+
+public class GS2MacroResolver 
+    extends MacroResolver 
+{
+
+    protected GDBMWrapper gdbm_src = null;
+    
+    // need to make it not add macros if they are already present
+    public GS2MacroResolver(GDBMWrapper gdbm) {
+	super();
+	gdbm_src = gdbm;
+    }
+
+    
+    public String resolve(String text, String lang, String scope, 
+			  String doc_oid) {
+	if (text == null || text.equals("")) return text;
+	if (scope.equals(SCOPE_TEXT) && text_macros.size()==0) return text;
+	if (scope.equals(SCOPE_META) && metadata_macros.size() ==0) return text;
+	DBInfo node_info = null;
+	DBInfo root_info = null;
+	boolean new_lang = false;
+	if (this.lang == null || !this.lang.equals(lang) ) {
+	    new_lang = true;
+	    this.lang = lang;
+	} 
+
+	ArrayList macros;
+	if (scope.equals(SCOPE_TEXT)) {
+	    macros = text_macros;
+	} else {
+	    macros = metadata_macros;
+	}
+	for (int i=0; i<macros.size(); i++) {
+	    String new_text = null;
+	    Macro m = (Macro)macros.get(i);
+	    switch (m.type) {
+	    case TYPE_DICT:
+		if (m.text==null || new_lang) {
+		    Dictionary dict = new Dictionary(m.bundle, lang);
+		    m.text = dict.get(m.key, null);
+		}
+		// we assume that dictionary entries will contain no macros
+		// otherwise we can't cache the answer because it might be 
+		// document specific
+		text = text.replaceAll(m.macro, m.text);
+		break;
+	    case TYPE_TEXT:
+		// make sure we resolve any macros in the text
+		// the (?s) treats the string as a single line, cos . 
+		// doesn't necessarily match line breaks
+		if (text.matches("(?s).*"+m.macro+".*")) {
+		    if (m.resolve) {
+			new_text = this.resolve(m.text, lang, scope, doc_oid);
+		    } else {
+			new_text = m.text;
+		    }
+		    text = text.replaceAll(m.macro, new_text);
+		}
+		break;
+	    case TYPE_META:
+		if (text.matches(".*"+m.macro+".*")) {
+		    if (node_info == null) {
+			node_info = gdbm_src.getInfo(doc_oid);
+			if (node_info == null) {
+			    break;
+			}
+		    }
+		    new_text = node_info.getInfo(m.text);
+		    if (new_text == null || new_text.equals("")) {
+			// try the root node
+			if (root_info == null && !OID.isTop(doc_oid)) {
+			    root_info = gdbm_src.getInfo(OID.getTop(doc_oid));
+			}
+			if (root_info == null) break;
+			new_text = root_info.getInfo(m.text);
+		    }
+		    if (new_text != null) {
+			if (m.resolve) {
+			    new_text = this.resolve(new_text, lang, scope, doc_oid);
+			}
+			text = text.replaceAll(m.macro, new_text);
+		    }
+		    
+		}
+		
+		break;
+	    } // switch
+	   
+	}
+	return text;
+	
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSConstants.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSConstants.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSConstants.java	(revision 13928)
@@ -0,0 +1,15 @@
+package org.greenstone.gsdl3.util;
+
+/** these constants are used for servlet args, and config variables */
+public class GSConstants {
+
+    public static final String GSDL3_HOME = "gsdl3_home";
+    public static final String INTERFACE_NAME = "interface_name";
+    public static final String SITE_NAME = "site_name";
+    public static final String LIBRARY_NAME = "library_name";
+    public static final String DEFAULT_LANG = "default_lang";
+
+
+    public static final String META_RELATION_SEP = "_";
+    public static final String META_SEPARATOR_SEP = "*";
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSEntityResolver.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSEntityResolver.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSEntityResolver.java	(revision 13928)
@@ -0,0 +1,50 @@
+package org.greenstone.gsdl3.util;
+
+
+import org.xml.sax.InputSource;
+import org.xml.sax.EntityResolver;
+import java.io.File;
+import java.net.URL;
+
+import org.apache.log4j.*;
+
+// uses a class loader to find entities
+// The class loader to use can be set by setClassLoader(), otherwise it will use the class loader that loaded itself. For the Tomcat webapp, this will be the webapp class loader, not the system class loader. the webapp classloader knows about the classes in the WEB-INF/classes dir, the system classloader knows about the ones on the classpath. The system class loader is a parent to web app classloader, so this will be used as well.
+
+public class GSEntityResolver implements EntityResolver {
+
+    ClassLoader class_loader = null;
+    
+     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.GSEntityResolver.class.getName());
+
+    public void setClassLoader(ClassLoader loader) {
+	this.class_loader = loader;
+    }
+    
+    public InputSource resolveEntity (String public_id, String system_id) {
+	
+	logger.debug("entity resolver for "+system_id);
+	String temp_id = system_id;
+	if (temp_id.startsWith("file://")) {
+	    File f = new File(system_id);
+	    if (f.exists()) {
+		return new InputSource(system_id);
+	    } else {
+		temp_id = temp_id.substring(temp_id.lastIndexOf("/")+1);
+	    }
+	} else {
+	    if (temp_id.indexOf("/")!= -1) {
+		temp_id = temp_id.substring(temp_id.lastIndexOf("/")+1);
+	    }
+	}
+	// try using a class loader
+	if (this.class_loader==null) {
+	    this.class_loader = this.getClass().getClassLoader();
+	}
+	URL url = class_loader.getResource(temp_id);
+	if (url == null) {
+	    return null;
+	}
+	return new InputSource("file://"+url.getFile());
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSFile.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSFile.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSFile.java	(revision 13928)
@@ -0,0 +1,443 @@
+/*
+ *    GSFile.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.util;
+
+import java.io.File; 
+//import org.apache.soap.encoding.soapenc.Base64;
+import org.apache.axis.encoding.Base64;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.lang.ClassLoader; // to find files on the class path
+import java.net.URL;
+import java.util.ArrayList;
+
+import org.apache.log4j.*;
+
+/**
+ * GSFile - utility class for Greenstone.
+ *
+ * all file paths are created here
+ * also has file utility methods
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ * @version $Revision$
+ * @see File
+ */
+
+public class GSFile {
+
+     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.GSFile.class.getName());
+
+    /**  site config file path */
+    static public String siteConfigFile(String site_home) {
+	return site_home + File.separatorChar+"siteConfig.xml";
+
+    }
+    /**  interface config file path */
+    static public String interfaceConfigFile(String interface_home) {
+	return interface_home + File.separatorChar+"interfaceConfig.xml";
+
+    }
+
+    /** collection directory path */
+    static public String collectDir(String site_home) {
+	return site_home+File.separatorChar+"collect";
+    }
+    
+    
+    /** collection config file path*/
+    static public String collectionConfigFile(String site_home, 
+					      String collection_name) {
+	return collectionConfigFile(collectionBaseDir(site_home, collection_name));
+    }
+    static public String collectionConfigFile(String collection_home) {
+	return collectionEtcDir(collection_home) +
+			File.separatorChar+"collectionConfig.xml";
+
+    }
+    /** collection init file path*/
+    static public String collectionInitFile(String site_home, 
+					    String collection_name) {
+	return site_home+File.separatorChar+"collect"+
+			File.separatorChar+collection_name+
+			File.separatorChar+"etc"+
+			File.separatorChar+"collectionInit.xml";
+
+    }
+
+    /** collection build config file path*/
+    static public String collectionBuildConfigFile(String site_home, 
+						   String collection_name ) {
+	return site_home+File.separatorChar+"collect"+
+			File.separatorChar+collection_name+
+			File.separatorChar+"index"+
+			File.separatorChar+"buildConfig.xml";
+    }
+    /** collection build config file path*/
+    static public String collectionBuildConfigFileBuilding(String site_home, 
+						   String collection_name ) {
+	return collectionBuildConfigFileBuilding(collectionBaseDir(site_home, collection_name));
+    }
+    static public String collectionBuildConfigFileBuilding(String collection_home ) {
+	return collection_home+
+	    File.separatorChar+"building"+
+	    File.separatorChar+"buildConfig.xml";
+    }
+
+    /** XML Transform directory path */
+    static public String xmlTransformDir(String interface_home) {
+	return interface_home+File.separatorChar+"transform";
+    }
+
+    /** collection base directory path */	 
+    static public String collectionBaseDir(String site_home,
+					   String collection_name) {
+	return site_home+File.separatorChar+"collect"+
+	    File.separatorChar+collection_name;
+    }
+    /** collection archive directory path */
+    static public String collectionArchiveDir(String site_home,
+					   String collection_name) {
+	return collectionArchiveDir(collectionBaseDir(site_home, collection_name)); 
+    }
+    static public String collectionArchiveDir(String collection_home) {
+	return collection_home+File.separatorChar+"archives";
+    }
+    
+    /** collection building directory path */	 
+    static public String collectionBuildDir(String site_home,
+					   String collection_name) {
+	return collectionBuildDir(collectionBaseDir(site_home, collection_name));
+    }
+    static public String collectionBuildDir(String collection_home) {
+	return collection_home+File.separator+"building";
+    }
+    /** collection building directory path */	 
+    static public String collectionEtcDir(String site_home,
+					   String collection_name) {
+	return collectionEtcDir(collectionBaseDir(site_home, collection_name));
+    }
+    static public String collectionEtcDir(String collection_home) {
+	return collection_home+File.separator+"etc";
+    }
+
+    /** collection building directory path */	 
+    static public String collectionImportDir(String site_home,
+					   String collection_name) {
+	return collectionImportDir(collectionBaseDir(site_home, collection_name));
+	    
+    }
+    static public String collectionImportDir(String collection_home) {
+	return collection_home + File.separatorChar+"import";
+    }
+    /** collection building directory path */	 
+    static public String collectionIndexDir(String site_home,
+					   String collection_name) {
+	return collectionIndexDir(collectionBaseDir(site_home, collection_name));
+	    
+    }
+    static public String collectionIndexDir(String collection_home) {
+	return collection_home + File.separatorChar+"index";
+    }
+    
+    /** text path (for doc retrieval) relative to collectionBaseDir */
+    static public String collectionTextPath(String index_stem) {
+	return "index"+File.separatorChar+"text"+File.separatorChar+
+	    index_stem;
+    }
+
+    /** index path (for querying) relative to collectionBaseDir */
+    static public String collectionIndexPath(String index_stem,
+					     String index_name) {
+	return "index"+File.separatorChar+index_name+File.separatorChar+
+	    index_stem;
+    }
+    
+    /** collection resources directory path */	 
+    static public String collectionResourceDir(String site_home,
+					       String collection_name) {
+	return collectionResourceDir(collectionBaseDir(site_home, collection_name));
+	    
+    }
+    static public String collectionResourceDir(String collection_home) {
+	return collection_home + File.separatorChar+"resources";
+    }
+
+    /** absolute path for an associated file */
+    static public String assocFileAbsolutePath(String site_home,
+					       String collection_name,
+					       String assoc_file_path,
+					       String filename) {
+	return collectionBaseDir(site_home, collection_name)+
+	    File.separatorChar+"index"+File.separatorChar+
+	    "assoc"+File.separatorChar+assoc_file_path+
+	    File.separatorChar+filename;
+    }
+
+    static public String siteHome(String gsdl3_home, String site_name) {
+	return gsdl3_home + File.separatorChar + "sites" + 
+	    File.separatorChar +site_name;
+    }
+
+    static public String interfaceHome(String gsdl3_home, 
+				       String interface_name) {
+	return gsdl3_home + File.separatorChar + "interfaces" + 
+	    File.separatorChar + interface_name;
+    }
+    
+    static public String siteStylesheetFile(String site_home,
+					    String filename) {
+	return site_home+File.separatorChar + "transform" +
+	    File.separatorChar + filename;
+    }
+    static public String collStylesheetFile(String site_home,
+					    String coll_name,
+					    String filename) {
+	return collectionBaseDir(site_home, coll_name) + File.separatorChar+
+	    "transform" + File.separatorChar + filename;
+    }
+	
+	
+    /** returns the absolute path to a stylesheet 
+     * stylesheets are looked for in the following places, in the 
+     * following order:
+     * current collection, current site, current interface, base interfaces
+     * returns null  if the file cannot be found 
+     *
+     * this is not so good because sites may be on a different computer */
+    static public String stylesheetFile(String gsdl3_home,
+					String site_name,
+					String collection,
+					String interface_name,
+					ArrayList base_interfaces,
+					String filename) {
+
+	String site_home = siteHome(gsdl3_home, site_name);
+	// try collection first
+	File stylesheet = null;
+	if (!collection.equals("")) {
+	    
+	    String coll_home = collectionBaseDir(site_home, collection);
+	    stylesheet = new File(coll_home +File.separatorChar+
+				  "transform"+File.separatorChar+filename);
+	    if (stylesheet.exists()) {
+		return stylesheet.getPath();
+	    }
+	}
+	
+	// try site one next	
+	stylesheet = new File(site_home +File.separatorChar+
+			      "transform"+File.separatorChar+filename);
+	if (stylesheet.exists()) {
+	    return stylesheet.getPath();
+	}
+	
+	// try current interface
+	String interface_home = interfaceHome(gsdl3_home, 
+					      interface_name);
+	stylesheet = new File(interface_home+File.separatorChar+
+			      "transform"+File.separatorChar+filename);
+	if (stylesheet.exists()) {
+	    return stylesheet.getPath();
+	}
+	// try base interface
+	if (base_interfaces==null || base_interfaces.size()==0) {
+	    return null; // no base interfaces to look for
+	}
+	for (int i=0; i<base_interfaces.size(); i++) {
+	    interface_home = interfaceHome(gsdl3_home, (String)base_interfaces.get(i));
+	    stylesheet = new File(interface_home+File.separatorChar+
+				  "transform"+File.separatorChar+filename);
+	    if (stylesheet.exists()) {
+		return stylesheet.getPath();
+	    }
+	}
+	    
+	// still can't find it and we have looked everywhere
+	return null;
+    }
+
+
+    /** base directory for phind data */
+    public static String phindBaseDir(String site_home, String coll_name,
+				      String phind_index) {
+	return site_home + File.separatorChar +
+	    "collect" + File.separatorChar +
+	    coll_name + File.separatorChar +
+	    "index" + File.separatorChar +
+	    "phind"+phind_index;
+    }
+
+    /** the gdbm database file - 
+     * note, need to change extension depending on OS */
+    static public String GDBMDatabaseFile(String site_home, 
+					  String collection_name,
+					  String index_stem) {
+
+	String db_ext = ".ldb";
+	if (Misc.isBigEndian()) {
+	    db_ext = ".bdb";
+	}
+	return site_home + File.separatorChar +
+	    "collect" + File.separatorChar +
+	    collection_name + File.separatorChar +
+	    "index" + File.separatorChar + "text" + File.separatorChar +
+	    index_stem + db_ext;
+
+    }
+
+    // some file utility methods
+
+    /** read in a file and encode it using base64
+     * encoded data returned as a String */
+    static public String base64EncodeFromFile(String in_filename) {
+	byte [] data=null;
+	try {
+	    data = readFile(in_filename);
+	} catch (Exception e) {
+	    logger.error("couldn't read the file");
+	}
+	String encodedString = Base64.encode(data);
+	return encodedString;
+
+    }
+
+    /** decode some base64 data, and write it to the specified file */
+    static public boolean base64DecodeToFile(String data, String out_filename) {
+	try {
+	    byte[] buffer=Base64.decode(data);
+	    writeFile(buffer, out_filename);
+	   
+	} catch (Exception e) {
+	    logger.error("file opening/closing errors"+e.getMessage());
+	    return false;
+	}
+	return true;
+	
+    }
+
+    /** read in a file to a byte array */
+    public static byte[] readFile(String filename) throws IOException {
+	File file = new File(filename);
+	BufferedInputStream bis = new BufferedInputStream(new
+	    FileInputStream(file));
+	int bytes = (int) file.length();
+	byte[] buffer = new byte[bytes];
+	int readBytes = bis.read(buffer);
+	bis.close();
+	return buffer;
+    }
+
+    /** write a byte array to a file */
+    public static void writeFile(byte [] buffer, String filename) throws IOException {
+	File file = new File(filename);
+	BufferedOutputStream bos = new BufferedOutputStream(new
+	    FileOutputStream(file));
+	bos.write(buffer);
+	bos.close();
+    }
+
+    public static boolean deleteFile(File f) {
+
+	if (f.isDirectory()) {
+	    File[] files = f.listFiles();
+	    for (int i=0; files!=null && i<files.length; i++) {
+		deleteFile(files[i]);
+	    }
+
+	}
+	// delete the file or directory
+	return f.delete();
+    }
+    
+    public static boolean copyFile(File source, File destination) {
+	if (!source.isFile()) {
+	    logger.error(source.getPath()+" is not a file!");
+	    return false;
+	}
+	try {
+	    destination.getParentFile().mkdirs();
+	    FileInputStream in = new FileInputStream(source);
+	    FileOutputStream out = new FileOutputStream(destination);
+	    int value = 0;
+	    while((value = in.read()) != -1) {
+		out.write(value);
+	    }
+	    in.close();
+	    out.close();
+	} catch (Exception e) {
+	    logger.error("something went wrong copying "+source.getPath()+" to "+destination.getPath());
+	    logger.error("Exception: "+e.getMessage());
+	    return false;
+	}
+
+	return true;
+    }
+    /** Recursively moves the contents of source file to destination,
+     * maintaining paths.
+     * @param source A File representing the directory whose contents you
+     * wish to move.
+     * @param destination A File representing the directory you wish to move
+     * files to.
+     * @return true if successful
+     */
+    public static boolean moveDirectory(File source, File destination) {
+
+	// first try rename
+	if (source.renameTo(destination)) {
+	    return true;
+	}
+
+	// john T. said that this sometimes doesn't work, so you have to copy files manually
+
+	// copied from gatherer Utility class
+	File input[] = source.listFiles();
+	for(int i = 0; i < input.length; i++) {
+	    File output = new File(destination, input[i].getName());
+	    if (input[i].isDirectory()) {
+		moveDirectory(input[i], output);
+	    } else {
+		// Copy the file
+		try {
+		    output.getParentFile().mkdirs();
+		    FileInputStream in = new FileInputStream(input[i]);
+		    FileOutputStream out = new FileOutputStream(output);
+		    int value = 0;
+		    while((value = in.read()) != -1) {
+			out.write(value);
+		    }
+		    in.close();
+		    out.close();
+		    // Delete file
+		    input[i].delete();
+		} catch (Exception e) {
+		    logger.error("exception: "+e.getMessage());
+		    return false;
+		}
+		
+	    }
+	}
+	return true;
+    }
+    
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSFileTest.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSFileTest.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSFileTest.java	(revision 13928)
@@ -0,0 +1,49 @@
+package org.greenstone.gsdl3.util;
+
+import junit.framework.*; 
+import java.io.File;
+
+public class GSFileTest extends TestCase {
+
+    /** what type of test - used by the testing framework */
+    public static final String TEST_ALL_TEST_TYPE="UNIT";
+
+    public GSFileTest(String name) {
+	super(name);
+    }
+
+    /** test suite that dynamically runs all the tests */
+    public static Test suite() {
+	return new TestSuite(GSFileTest.class);
+    }
+
+    public void testBase64Conversion() {
+	
+	// start off with reverse conversion - decode then encode
+	String data = "sdkfjho9w4385khrf9ow834rfia8ufd38rhf9812";
+	File outfile;
+	try {
+	    outfile = File.createTempFile("b64convert_test", "");
+	} catch (java.io.IOException e) {
+	    fail("couldn't create a temporary file in default temp dir");
+	    return;
+	}
+	String filename = outfile.getAbsolutePath();
+	
+	String newdata;
+	if (GSFile.base64DecodeToFile(data, filename)) {
+	    newdata = GSFile.base64EncodeFromFile(filename);
+
+	    assertEquals("decoded/encoded string does not match the origianl",
+			 data, newdata);
+	    // clean up
+	    outfile.delete();
+	} else {
+	    fail("couldn't decode the data string");
+	}
+
+	//try with a real file???
+	
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSHTML.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSHTML.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSHTML.java	(revision 13928)
@@ -0,0 +1,64 @@
+package org.greenstone.gsdl3.util;
+
+/** GSHTML - provides some convenience methods for dealing
+ * with html
+ */
+public class GSHTML {
+
+    /** make a string html safe */
+    public static String htmlSafe(String input) {
+
+	StringBuffer filtered = new StringBuffer(input.length());
+	char c;
+	for (int i=0; i<input.length(); i++) {
+	    c = input.charAt(i);
+	    if (c == '<') {
+		filtered.append("&lt;");
+	    } else if (c == '>') {
+		filtered.append("&gt;");
+	    } else if (c == '"') {
+		filtered.append("&quot;");
+	    } else if (c == '&') {
+		filtered.append("&amp;");
+	    } else {
+		filtered.append(c);
+	    }
+	}
+	return(filtered.toString());
+    }
+    /** undo the html safe action */
+    public static String htmlUnsafe(String input) {
+	StringBuffer filtered = new StringBuffer(input.length());
+	char c;
+	for (int i=0; i<input.length(); i++) {
+	    c = input.charAt(i);
+	    if (c =='&') {
+		int j=input.indexOf(';', i);
+		String entity = input.substring(i, j);
+		i=j;
+		if (entity.equals("&amp")) {
+		    filtered.append('&');
+		} else if (entity.equals("&lt")){
+		    filtered.append('<');
+		} else if (entity.equals("&gt")){
+		    filtered.append('>');
+		} else if (entity.equals("&quot")) {
+		    filtered.append('"');
+		} // else just ignore it.
+	    } else {
+		filtered.append(c);
+	    }
+
+	}
+	return(filtered.toString());
+    }
+    
+    /** produce a default error page */
+    public static String  errorPage(String error) {
+	String page = "<html><head><Title>GSDL3 Error!</Title></head>\n"+
+	    "<body><h1>Greenstone Error!</h1>"+
+	    "<p/>"+error+"</body></html>";
+	return page;
+    }
+	
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSParams.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSParams.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSParams.java	(revision 13928)
@@ -0,0 +1,102 @@
+package org.greenstone.gsdl3.util;
+
+import java.util.HashMap;
+
+/** keeps track of the interface parameters, and their defaults */
+public class GSParams {
+
+    public static final String ACTION = "a"; // the major type of action- eg query or browse or process
+    public static final String SUBACTION = "sa"; // subtype of action if we want different processing than the default
+    public static final String REQUEST_TYPE = "rt"; // whether the request is just to display the service form, or to actually do a request to the service
+    public static final String RESPONSE_ONLY = "ro"; // if == 1 do the request and pass back the response xml - no page formatting
+    public static final String OUTPUT = "o"; // if processing is to be done, what type of output - html/xml/other??
+    public static final String SERVICE = "s"; // the name of the service
+    public static final String CLUSTER = "c";   // these two are the same
+    public static final String COLLECTION = "c"; 
+    public static final String LANGUAGE = "l";
+    public static final String DOCUMENT = "d";
+    public static final String DOCUMENT_TYPE = "dt";
+    public static final String RESOURCE = "r";
+    public static final String PROCESS_ID = "pid"; // if a request wasn't completed, this identifies the request - used when asking for a status update
+    
+    public static final String SIBLING = "sib"; // this should not be in here
+    // internal configure args
+    public static final String SYSTEM_SUBSET = "ss";
+    public static final String SYSTEM_CLUSTER = "sc";
+    public static final String SYSTEM_MODULE_NAME = "sn";
+    public static final String SYSTEM_MODULE_TYPE = "st";
+
+    public static final String EXPAND_DOCUMENT = "ed";
+    public static final String EXPAND_CONTENTS = "ec";
+    protected HashMap param_map = null;
+    
+    public GSParams() {
+	this.param_map = new HashMap(30);
+
+	// add in all the standard params
+	addParameter(ACTION, false); 
+	addParameter(SUBACTION,  false); 
+	addParameter(REQUEST_TYPE,  false);
+	addParameter(RESPONSE_ONLY,  false);
+	addParameter(CLUSTER,  false); // we don't want to save collection 
+	//addParameter(COLLECTION); 
+	addParameter(LANGUAGE,  true); 
+	addParameter(DOCUMENT,  true); 
+	addParameter(RESOURCE,  true); 
+	addParameter(OUTPUT, false); 
+	addParameter(SERVICE, false); 
+	addParameter(PROCESS_ID, true); 
+	addParameter(SYSTEM_SUBSET, false);
+	addParameter(SYSTEM_CLUSTER, false);
+	addParameter(SYSTEM_MODULE_NAME, false);
+	addParameter(SYSTEM_MODULE_TYPE, false);
+	addParameter(SIBLING, false);
+	addParameter(DOCUMENT_TYPE, true);
+	addParameter(EXPAND_DOCUMENT, false);
+	addParameter(EXPAND_CONTENTS, false);
+ 	//addParameter();
+	// ugly hack so we don't save the extlink param
+	addParameter("s0.ext", false);
+    }
+    
+    public boolean addParameter(String name, boolean save) {
+	return addParameter(name, "", save);
+    }
+    
+    public boolean addParameter(String name, String default_value, boolean save) {
+	if (this.param_map.containsKey(name)) {
+	    // already there so could not add
+	    return false;
+	}
+
+	this.param_map.put(name, new Param(default_value, save));
+	return true;
+    }
+	
+    public boolean setParamDefault(String name, String default_value) {
+	Param p = (Param)this.param_map.get(name);
+	if (p==null) return false;
+	p.default_value = default_value;
+	return true;
+    }
+    
+    public boolean shouldSave(String name) {
+	if (name.startsWith("p.")) return false;
+	Param p = (Param)this.param_map.get(name);
+	if (p== null) return true; // if things are not in here, always save.
+	return p.save;
+    }
+    
+    private class Param {
+
+	public String default_value = null;
+	public boolean save = true;
+
+	public Param(String default_value, boolean save) {
+	    this.default_value = default_value;
+	    this.save = save;
+	}
+    }
+}
+
+    
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSPath.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSPath.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSPath.java	(revision 13928)
@@ -0,0 +1,150 @@
+/*
+ *    GSPath.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.util;
+
+/**
+ * GSPath - utility class for greenstone
+ *
+ * modifies and examines message address paths and names
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ * @version $Revision$
+ *
+ */
+
+public class GSPath {
+
+    /** adds new_link to the end of path
+     *
+     * @return the new path
+     */
+    static public String appendLink(String path, String new_link) {
+	if (path.equals("")) {
+	    return new_link;
+	}
+	return path +"/"+new_link;
+    }
+
+    /** adds new_link to the front of path
+     *
+     * @return the new path
+     */
+    static public String prependLink(String path, String new_link) {
+	if (path.equals("")) {
+	    return new_link;
+	}
+	return  new_link+"/"+path;
+    }
+
+    /** replaces the first link in the path with the specified name
+     */
+    static public String replaceFirstLink(String path, String new_first_link) {
+	path = removeFirstLink(path);
+	path = prependLink(path, new_first_link);
+	return path;
+
+    }
+    /** returns the first name in the path
+     *
+     */
+    static public String getFirstLink(String path) {
+
+	int i = path.indexOf("/");
+	if (i==0) { // have a '/' on the front
+	    path = path.substring(1);
+	    i= path.indexOf("/");
+	}
+	if (i==-1) { // '/' not found
+	    return path;
+	}
+	
+	return path.substring(0,i);
+    }
+
+    /** removes the first name in the path
+     *
+     * @return the modified path
+     */
+    static public String removeFirstLink(String path) {
+	int i = path.indexOf("/");
+	if (i==0) { // have a '/' on the front
+	    path = path.substring(1);
+	    i= path.indexOf("/");
+	}
+	if (i==-1) { // '/' not found - remove the whole path
+	    return "";
+	}
+	return path.substring(i+1); // remove the '/' char
+    }
+
+    /** removes the last name in the path
+     *
+     * @return the modified path
+     */
+    static public String removeLastLink(String path) {
+	int i = path.lastIndexOf("/");
+	if (i==-1) { // '/' not found - remove the whole path
+	    return "";
+	}
+	return path.substring(0, i); // remove the '/' char
+    }
+    
+    static public String getLastLink(String path) {
+	int i = path.lastIndexOf("/");
+	if (i==-1) { // '/' not found - remove the whole path
+	    return path;
+	}
+	return path.substring(i+1); // remove the last link
+    }
+
+    
+    static public String createPath(String [] links) {
+	String path = links[0];
+	for (int i=1; i<links.length; i++) {
+	    path = appendLink(path, links[i]);
+	}
+	return path;
+    }
+
+    static public int getIndex(String link) {
+	int i = link.indexOf("[");
+	if (i==-1) {
+	    return -1;
+	}
+	int j = link.indexOf("]");
+	String num = link.substring(i+1,j);
+	try {
+	    int index = Integer.parseInt(num);
+	    return index;
+	} catch (Exception e) {
+	    return -1;
+	}
+    }
+
+    static public String removeIndex(String link) {
+	int i = link.indexOf("[");
+	if (i==-1) {
+	    return link;
+	}
+	return link.substring(0, i);
+    }
+
+}
+
+    
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSStatus.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSStatus.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSStatus.java	(revision 13928)
@@ -0,0 +1,36 @@
+package org.greenstone.gsdl3.util;
+
+public class GSStatus {
+
+    // responses for initial request
+    public static final int SUCCESS = 1; // request succeeded
+    public static final int ACCEPTED = 2; // request accepted but not completed
+    public static final int ERROR = 3; // error and process stopped
+
+    // responses for status requests
+    public static final int CONTINUING = 10; // request still continuing
+    public static final int COMPLETED = 11; // request finished
+    public static final int HALTED = 12; // process stopped
+	    
+    // other
+    public static final int INFO = 20; // just an info message that doesnt mean anything
+
+    /** returns true if teh code indicates that a process is no longer running 
+     */
+    public static boolean isCompleted(int code) {
+	if (code == SUCCESS || code == ERROR || code == COMPLETED || code == HALTED) {
+	    return true;
+	} 
+	return false;
+    }
+
+    // there may be other types of error codes
+    public static boolean isError(int code) {
+	if (code == ERROR) {
+	    return true;
+	}
+	return false;
+    }
+
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSXML.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSXML.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSXML.java	(revision 13928)
@@ -0,0 +1,898 @@
+package org.greenstone.gsdl3.util;
+
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Document;
+import org.w3c.dom.Text;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.HashMap;
+import java.util.Vector;
+import java.util.Iterator;
+import java.util.ArrayList;
+
+//import java.util.Locale;
+
+import org.apache.log4j.*;
+
+/** various functions for extracting info out of GS XML */
+public class GSXML {
+
+    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.GSXML.class.getName());
+
+    // greenstone xml elements
+    public static final String MESSAGE_ELEM = "message";
+    public static final String REQUEST_ELEM = "request";
+    public static final String RESPONSE_ELEM = "response";
+    public static final String COLLECTION_ELEM = "collection";
+    public static final String SERVICE_ELEM = "service";
+    public static final String CLUSTER_ELEM = "serviceCluster";
+    public static final String SITE_ELEM = "site";
+    public static final String PARAM_ELEM = "param";
+    public static final String PARAM_OPTION_ELEM = "option";
+    public static final String CONTENT_ELEM = "content";
+    public static final String RESOURCE_ELEM = "resource";
+    public static final String DOCUMENT_ELEM = "document";
+    public static final String METADATA_ELEM = "metadata";
+    public static final String SERVICE_CLASS_ELEM = "serviceRack";
+    public static final String CLASSIFIER_ELEM = "classifier";
+    public static final String APPLET_ELEM = "applet";
+    public static final String APPLET_DATA_ELEM = "appletData";
+    public static final String CONFIGURE_ELEM = "configure";
+    public static final String STATUS_ELEM = "status";
+    public static final String ERROR_ELEM = "error";
+    public static final String DEFAULT_ELEM = "default";
+    public static final String STYLESHEET_ELEM = "format";//"stylesheet"; // any additional stylesheet stuff is carried in the message inside this elem
+    public static final String FORMAT_ELEM = "format"; // config files use format - should we use this instead of stylesheet??
+    public static final String TERM_ELEM = "term";
+    public static final String SYSTEM_ELEM = "system";
+
+    //config file elems
+    public static final String COLLECTION_CONFIG_ELEM = "collectionConfig";
+    public static final String COLLECTION_BUILD_ELEM = "buildConfig";
+    public static final String COLLECTION_INIT_ELEM = "collectionInit";
+    public static final String RECOGNISE_ELEM = "recognise";
+    public static final String DOC_TYPE_ELEM = "docType";
+    public static final String SEARCH_ELEM = "search";
+    public static final String INDEX_ELEM = "index";
+    public static final String INDEX_STEM_ELEM = "indexStem";
+    public static final String INDEX_OPTION_ELEM = "indexOption";
+    public static final String BROWSE_ELEM = "browse";
+    public static final String DISPLAY_ELEM = "display";
+    public static final String LEVEL_ELEM = "level";
+    public static final String SHORTNAME_ATT = "shortname";
+    public static final String NOTIFY_ELEM = "notify";
+    public static final String NOTIFY_HOST_ATT = "host";
+
+    // elems for the pages to be processed by xslt
+    public final static String PAGE_ELEM = "page";
+    public final static String CONFIGURATION_ELEM = "config";
+    public final static String PAGE_REQUEST_ELEM = "pageRequest";
+    public final static String PAGE_RESPONSE_ELEM = "pageResponse";
+    public final static String PAGE_EXTRA_ELEM = "pageExtra";
+
+    //public final static String DESCRIPTION_ELEM = "description";
+
+    public static final String  ACTION_ELEM = "action";
+    public static final String  SUBACTION_ELEM = "subaction";
+    
+    // add on to another elem type to get a list of that type
+    public static final String LIST_MODIFIER = "List";
+
+    // greenstone xml attributes
+    public static final String NAME_ATT = "name";
+    public static final String TO_ATT = "to";
+    public static final String USER_ID_ATT = "uid";
+    public static final String FROM_ATT = "from";
+    public static final String LANG_ATT = "lang";
+    public static final String TYPE_ATT = "type";
+    public static final String VALUE_ATT = "value";
+    public static final String DEFAULT_ATT = "default";
+    public static final String INFO_ATT = "info";
+    public static final String ACTION_ATT = "action";
+    public static final String SUBACTION_ATT = "subaction";
+    public static final String OUTPUT_ATT = "output";
+    public static final String ADDRESS_ATT = "address";
+    public static final String LOCAL_SITE_ATT = "localSite";
+    public static final String LOCAL_SITE_NAME_ATT = "localSiteName";
+    public static final String STATUS_ERROR_CODE_ATT = "code";
+    public static final String STATUS_PROCESS_ID_ATT = "pid";
+    public static final String PARAM_SHORTNAME_ATT = "shortname";
+    public static final String PARAM_IGNORE_POS_ATT = "ignore";
+    public static final String CLASSIFIER_CONTENT_ATT = "content";
+    public static final String ERROR_TYPE_ATT = "type";
+
+    // document stuff
+    public static final String DOC_TYPE_ATT = "docType";
+    public static final String DOC_NODE_ELEM = "documentNode";
+    public static final String NODE_CONTENT_ELEM = "nodeContent";
+    public static final String NODE_STRUCTURE_ELEM = "nodeStructure";
+    public static final String NODE_ID_ATT = "nodeID";
+    public static final String NODE_NAME_ATT = "nodeName";
+    public static final String NODE_TYPE_ATT = "nodeType";
+    public static final String NODE_RANK_ATT = "rank";
+    public static final String NODE_TYPE_ROOT = "root";
+    public static final String NODE_TYPE_INTERNAL = "internal";
+    public static final String NODE_TYPE_LEAF = "leaf";
+
+    public static final String DOC_TYPE_SIMPLE = "simple";
+    public static final String DOC_TYPE_PAGED = "paged";
+    public static final String DOC_TYPE_HIERARCHY = "hierarchy";
+
+    // classifier stuff
+    public static final String CLASS_NODE_ELEM = "classifierNode";
+    public static final String CLASS_NODE_ORIENTATION_ATT = "orientation";
+    
+    // parameter types
+    public static final String PARAM_TYPE_INTEGER = "integer";
+    public static final String PARAM_TYPE_BOOLEAN = "boolean";
+    public static final String PARAM_TYPE_ENUM_START = "enum";
+    public static final String PARAM_TYPE_ENUM_SINGLE = "enum_single";
+    public static final String PARAM_TYPE_ENUM_MULTI = "enum_multi";
+    public static final String PARAM_TYPE_STRING = "string";
+    public static final String PARAM_TYPE_TEXT = "text";
+    public static final String PARAM_TYPE_MULTI = "multi";
+    public static final String PARAM_TYPE_FILE = "file";
+    public static final String PARAM_TYPE_INVISIBLE = "invisible";
+    // stuff for text strings 
+    public static final String DISPLAY_TEXT_ELEM = "displayItem";
+    // the following are used for the name attributes
+    public static final String DISPLAY_TEXT_NAME = "name";
+    public static final String DISPLAY_TEXT_SUBMIT = "submit";
+    public static final String DISPLAY_TEXT_DESCRIPTION = "description";
+
+    // request types 
+    // get the module description
+    public static final String REQUEST_TYPE_DESCRIBE = "describe";
+    // startup a process 
+    public static final String REQUEST_TYPE_PROCESS = "process";
+    // get the status of an ongoing process
+    public static final String REQUEST_TYPE_STATUS = "status";
+    // system type request - eg reload a collection
+    public static final String REQUEST_TYPE_SYSTEM = "system"; 
+    // page requests to the Receptionist/Actions
+    public static final String REQUEST_TYPE_PAGE = "page"; // used to be cgi
+    // get any format info for a service
+    public static final String REQUEST_TYPE_FORMAT = "format"; 
+    // modify the requests
+    public static final String REQUEST_TYPE_MESSAGING = "messaging";
+
+    // service types
+    public static final String SERVICE_TYPE_QUERY = "query";
+    public static final String SERVICE_TYPE_RETRIEVE = "retrieve";
+    public static final String SERVICE_TYPE_BROWSE = "browse";
+    public static final String SERVICE_TYPE_APPLET = "applet";
+    public static final String SERVICE_TYPE_PROCESS = "process";
+    public static final String SERVICE_TYPE_ENRICH = "enrich";
+
+    // system command types and attributes
+    public static final String SYSTEM_TYPE_CONFIGURE = "configure";
+    public static final String SYSTEM_TYPE_ACTIVATE = "activate";
+    public static final String SYSTEM_TYPE_DEACTIVATE = "deactivate";
+
+    public static final String SYSTEM_SUBSET_ATT = "subset";
+    public static final String SYSTEM_MODULE_TYPE_ATT = "moduleType";
+    public static final String SYSTEM_MODULE_NAME_ATT = "moduleName";
+    
+    // communicator types
+    public static final String COMM_TYPE_SOAP_JAVA = "soap";
+    
+    // error types
+    public static final String ERROR_TYPE_SYNTAX = "syntax";
+    public static final String ERROR_TYPE_SYSTEM = "system";
+    public static final String ERROR_TYPE_INVALID_ID = "invalid_id";
+    public static final String ERROR_TYPE_OTHER = "other";
+
+    // some system wide param names
+    public static final String SUBSET_PARAM = "subset";
+
+    /** takes a list of elements, and returns an array of strings 
+     * of the values of attribute att_name */
+    public static String [] getAttributeValuesFromList(Element list,
+						       String att_name) {
+	
+	NodeList children = list.getChildNodes();
+	
+	int num_nodes = children.getLength();
+	String []ids = new String[num_nodes];
+	for (int i=0; i<num_nodes; i++) {
+	    Element e = (Element)children.item(i);
+	    String id = e.getAttribute(att_name);	    
+	    ids[i] = id;	    
+	}
+	
+	return ids;
+    }
+
+    /** takes a paramList element, and gets a HashMap of name-value pairs 
+     * if deep=true, extracts embedded params, otherwise just top level 
+     * params*/
+    public static HashMap extractParams(Element xml, boolean deep) {
+
+	if (!xml.getNodeName().equals(PARAM_ELEM+LIST_MODIFIER)) {
+	    logger.error("paramList element should have been passed to extractParams, instead it was "+xml.getNodeName());
+	    return null;
+	}
+
+	NodeList params = null;
+	if (deep) { // get all the nested ones
+	    params = xml.getElementsByTagName(PARAM_ELEM);
+	} else { // just get the top  level ones
+	    params = xml.getChildNodes();
+	}
+	HashMap param_map = new HashMap();
+	for (int i=0; i<params.getLength(); i++) {
+	    if (params.item(i).getNodeName().equals(PARAM_ELEM)) {
+		Element param = (Element)params.item(i);
+		String name=param.getAttribute(NAME_ATT);
+		String value=getValue(param); //att or content
+		int pos = name.indexOf('.');
+		if (pos == -1) { // a base param
+		    param_map.put(name, value);
+		} else { // a namespaced param
+		    
+		    String namespace = name.substring(0, pos);
+		    name = name.substring(pos+1);
+		    HashMap map = (HashMap)param_map.get(namespace);
+		    if (map == null) {
+			map = new HashMap();
+			param_map.put(namespace, map);
+		    }
+		    map.put(name, value);
+		}
+	    }
+	}
+	return param_map;
+    }
+
+    /** gets the value att or the text content */
+    public static String getValue(Element e) {
+	String val = e.getAttribute(VALUE_ATT);
+	if (val ==null || val.equals("")) {
+	    // have to get it out of the text
+	    val=getNodeText(e); 
+
+	} else {
+	    // unescape the xml stuff
+	    val = unXmlSafe(val);
+	}
+	return val;
+    }
+
+    /** extracts the text out of a node */
+    public static Node getNodeTextNode(Element param) {
+	param.normalize();
+	Node n = param.getFirstChild();
+	while (n!=null && n.getNodeType() !=Node.TEXT_NODE) {
+	    n=n.getNextSibling();
+	}
+	return n;
+    }
+    
+    /** extracts the text out of a node */
+    public static String getNodeText(Element param) {
+	Node text_node = getNodeTextNode(param);
+	if (text_node == null) {
+	    return "";
+	}
+	return text_node.getNodeValue();
+    }
+
+    public static void setNodeText(Element elem, String text) {
+	Node old_text_node = getNodeTextNode(elem);
+	elem.removeChild(old_text_node);
+	Text t = elem.getOwnerDocument().createTextNode(text);
+	elem.appendChild(t);
+    }
+	
+    /** add text to a document/subsection  element */
+    public static boolean addDocText(Document owner, Element doc, String text) {
+
+	Element content = owner.createElement(NODE_CONTENT_ELEM);
+	Text t = owner.createTextNode(text);
+	content.appendChild(t);
+	doc.appendChild(content);
+	return true;
+    }
+  
+    /** add an error message, unknown error type */
+    public static boolean addError(Document owner, Element doc, String text) {
+	return addError(owner, doc, text, ERROR_TYPE_OTHER);
+    }
+    /** add an error message */
+    public static boolean addError(Document owner, Element doc, String text,
+				   String error_type) {
+
+	Element content = owner.createElement(ERROR_ELEM);
+	content.setAttribute(ERROR_TYPE_ATT, error_type);
+	Text t = owner.createTextNode(text);
+	content.appendChild(t);
+	doc.appendChild(content);
+	return true;
+    }
+
+    /** add an error message */
+    public static boolean addError(Document owner, Element doc, Throwable error) {
+      return addError(owner, doc, error, ERROR_TYPE_OTHER);
+    }
+    
+    /** add an error message */
+    public static boolean addError(Document owner, Element doc, 
+				   Throwable error, String error_type) {
+	error.printStackTrace();
+	return addError(owner, doc, error.toString(), error_type);
+    }
+
+    public static Element createMetadataParamList(Document owner, Vector meta_values) {
+
+	Element meta_param_list = owner.createElement(PARAM_ELEM+LIST_MODIFIER);
+	Iterator i = meta_values.iterator();
+	while(i.hasNext()) {
+	    String next = (String)i.next();
+	    Element meta_param = owner.createElement(PARAM_ELEM);
+	    meta_param_list.appendChild(meta_param);
+	    meta_param.setAttribute(NAME_ATT, "metadata");
+	    meta_param.setAttribute(VALUE_ATT, next);
+	}
+	return meta_param_list;
+    }
+	
+    /** adds a metadata elem to a list */
+    public static boolean addMetadata(Document owner, Element list, 
+				      String meta_name, String meta_value) {
+	if (meta_value==null || meta_value.equals("")) {
+	    return false;
+	}
+	Element data = owner.createElement(METADATA_ELEM);
+	data.setAttribute(NAME_ATT, meta_name);
+	Text t = owner.createTextNode(meta_value);
+	data.appendChild(t);
+	list.appendChild(data);
+	return true;
+
+    }
+
+    /** copies the metadata out of teh metadataList of 'from' into
+     * the metadataList of 'to' */
+    public static boolean mergeMetadataLists(Node to, Node from) {
+	Node to_meta = getChildByTagName(to, METADATA_ELEM+LIST_MODIFIER);
+	Node from_meta = getChildByTagName(from, METADATA_ELEM+LIST_MODIFIER);
+	
+	if  (from_meta == null) { // nothing to copy
+	    return true;
+	}
+	Document to_owner = to.getOwnerDocument();
+	Node new_from = to_owner.importNode(from_meta, true);
+
+	if (to_meta == null) { // just copy the whole list
+	    to.appendChild(new_from);
+	    return true;
+	}
+	
+	// copy individual elements
+	Node child = new_from.getFirstChild();
+	while ( child != null) {
+	    to_meta.appendChild(child);
+	    child = child.getNextSibling();
+	}
+	return true;
+    }
+	
+    /** copies all the children from from to to */
+    public static boolean mergeElements(Element to, Element from) {
+
+	Document owner = to.getOwnerDocument();
+	Node child = from.getFirstChild();
+	while (child != null) {
+	    to.appendChild(owner.importNode(child, true));
+	    child = child.getNextSibling();
+	}
+	return true;
+    }
+    /** returns the (first) child element with the given name */
+    public static Node getChildByTagName(Node n, String name) {
+
+	Node child = n.getFirstChild();
+	while (child!=null) {
+	    if (child.getNodeName().equals(name)) {
+		return child;
+	    }
+	    child = child.getNextSibling();
+	}
+	return null; //not found
+    }
+    
+    /** returns the (nth) child element with the given name 
+     * index numbers start at 0 */
+    public static Node getChildByTagNameIndexed(Node n, String name, int index) {
+	if (index == -1) {
+	    return getChildByTagName(n, name);
+	}
+	int count = 0;
+	Node child = n.getFirstChild();
+	while (child!=null) {
+	    if (child.getNodeName().equals(name)) {
+		if (count == index) {
+		    return child;
+		} else {
+		    count++;
+		}
+	    }
+	    child = child.getNextSibling();
+	}
+	return null; //not found
+    }
+
+    /** takes an xpath type expression of the form name/name/... 
+	and returns the first node that matches, or null if not found */
+    public static Node getNodeByPath(Node n, String path) {
+	
+	String link = GSPath.getFirstLink(path);
+	path = GSPath.removeFirstLink(path);
+	while (!link.equals("")) {
+	    n = getChildByTagName(n, link);
+	    if (n==null) {
+		return null;
+	    }
+	    link = GSPath.getFirstLink(path);
+	    path = GSPath.removeFirstLink(path);
+	}
+	return n;
+    }
+
+    /** takes an xpath type expression of the form name/name/... 
+     * and returns the first node that matches, or null if not found 
+     * can include [i] indices. index numbers start at 0 */
+    public static Node getNodeByPathIndexed(Node n, String path) {
+	
+	String link = GSPath.getFirstLink(path);
+	int index = GSPath.getIndex(link);
+	if (index != -1) {
+	    link = GSPath.removeIndex(link);
+	}
+	path = GSPath.removeFirstLink(path);
+	while (!link.equals("")) {
+	    n = getChildByTagNameIndexed(n, link, index);
+	    if (n==null) {
+		return null;
+	    }
+	    link = GSPath.getFirstLink(path);
+	    index = GSPath.getIndex(link);
+	    if (index != -1) {
+		link = GSPath.removeIndex(link);
+	    }
+	    path = GSPath.removeFirstLink(path);
+	}
+	return n;
+    }
+
+    public static HashMap getChildrenMap(Node n) {
+	
+	HashMap map= new HashMap();
+	Node child = n.getFirstChild();
+	while (child!=null) {
+	    String name = child.getNodeName();
+	    map.put(name, child);
+	    child = child.getNextSibling();
+	}
+	return map;
+    }
+       
+    public static NodeList getChildrenByTagName(Node n, String name) {
+	MyNodeList node_list = new MyNodeList();
+	Node child = n.getFirstChild();
+	while (child!=null) {
+	    if (child.getNodeName().equals(name)) {
+		node_list.addNode(child);
+	    }
+	    child = child.getNextSibling();
+	}
+	return node_list;
+    }
+	
+
+    /** Duplicates an element, but gives it a new name */
+    public static Element duplicateWithNewName(Document owner, Element element,
+					       String element_name, boolean with_attributes)
+    {
+	return duplicateWithNewNameNS(owner, element, element_name, null, with_attributes);
+    }
+
+    /** Duplicates an element, but gives it a new name */
+    public static Element duplicateWithNewNameNS(Document owner, 
+						 Element element,
+						 String element_name, 
+						 String namespace_uri,
+						 boolean with_attributes)
+    {
+	Element duplicate;
+	if (namespace_uri == null) {
+	    duplicate = owner.createElement(element_name);
+	} else {
+	    duplicate = owner.createElementNS(namespace_uri, element_name);
+	}
+	// Copy element attributes
+	if (with_attributes) {
+	    NamedNodeMap attributes = element.getAttributes();
+	    for (int i = 0; i < attributes.getLength(); i++) {
+		Node attribute = attributes.item(i);
+		duplicate.setAttribute(attribute.getNodeName(), attribute.getNodeValue());
+	    }
+	}
+
+	// Copy element children
+	NodeList children = element.getChildNodes();
+	for (int i = 0; i < children.getLength(); i++) {
+	    Node child = children.item(i);
+	    duplicate.appendChild(owner.importNode(child, true));
+	}
+
+	return duplicate;
+    }
+
+    public static void copyAllChildren(Element to, Element from) {
+
+	Document to_doc = to.getOwnerDocument();
+	Node child = from.getFirstChild();
+	while (child != null) {
+	    to.appendChild(to_doc.importNode(child, true));
+	    child = child.getNextSibling();
+	}
+    }
+    /** returns a basic request message */
+    public static  Element createBasicRequest(Document owner, 
+					      String request_type, String to, 
+					      String lang,
+					      String uid) {
+	Element request = owner.createElement(REQUEST_ELEM);
+	request.setAttribute(TYPE_ATT, request_type);
+	request.setAttribute(LANG_ATT, lang);
+	request.setAttribute(TO_ATT, to);
+	request.setAttribute(USER_ID_ATT, uid);
+	return request;
+    }
+    
+    public static Element createTextElement(Document owner, String elem_name,
+					    String text) {
+	Element e = owner.createElement(elem_name);
+	Text t = owner.createTextNode(text);
+	e.appendChild(t);
+	return e;
+
+    }
+
+    public static Element createDisplayTextElement(Document owner, 
+						   String text_name,
+						   String text) {
+	Element e = owner.createElement(DISPLAY_TEXT_ELEM);
+	e.setAttribute(NAME_ATT, text_name);
+	Text t = owner.createTextNode(text);
+	e.appendChild(t);
+	return e;
+
+    }
+
+
+    public static Element createParameter(Document owner, String name, 
+					  String value) {
+	Element param = owner.createElement(PARAM_ELEM);
+	param.setAttribute(NAME_ATT, name);
+	param.setAttribute(VALUE_ATT, value);
+	return param;
+    }
+
+    public static void addParametersToList(Document owner, Element param_list, 
+					   HashMap params) {
+	Set items = params.entrySet();
+	Iterator i = items.iterator();
+	while(i.hasNext()) {
+	    Map.Entry m = (Map.Entry)i.next();
+	    param_list.appendChild(createParameter(owner, (String)m.getKey(), (String)m.getValue()));
+	}
+	
+    }
+
+    public static Element createParameterDescription(Document owner, 
+						     String id,
+						     String display_name,
+						     String type, 
+						     String default_value,
+						     String []option_ids,
+						     String []option_names) {
+
+	
+	Element p = owner.createElement(PARAM_ELEM);
+	p.setAttribute(NAME_ATT, id);
+	p.setAttribute(TYPE_ATT, type);
+	p.appendChild(createDisplayTextElement(owner, GSXML.DISPLAY_TEXT_NAME, display_name));
+
+	if (default_value != null) {
+	    p.setAttribute(DEFAULT_ATT, default_value);
+	}
+	if (option_ids!=null && option_names!=null) {
+	    for (int i=0; i<option_ids.length; i++) {
+		Element e = owner.createElement(PARAM_OPTION_ELEM);
+		e.setAttribute(NAME_ATT, option_ids[i]);
+		e.appendChild(createDisplayTextElement(owner, GSXML.DISPLAY_TEXT_NAME, option_names[i]));
+		p.appendChild(e);
+	    }
+	}
+	return p;
+    }
+    public static Element createParameterDescription2(Document owner, 
+						     String id,
+						     String display_name,
+						     String type, 
+						     String default_value,
+						     ArrayList option_ids,
+						     ArrayList option_names) {
+
+	
+	Element p = owner.createElement(PARAM_ELEM);
+	p.setAttribute(NAME_ATT, id);
+	p.setAttribute(TYPE_ATT, type);
+	p.appendChild(createDisplayTextElement(owner, GSXML.DISPLAY_TEXT_NAME, display_name));
+	if (default_value != null) {
+	    p.setAttribute(DEFAULT_ATT, default_value);
+	}
+	if (option_ids!=null && option_names!=null) {
+	    for (int i=0; i<option_ids.size(); i++) {
+		Element e = owner.createElement(PARAM_OPTION_ELEM);
+		e.setAttribute(NAME_ATT, (String)option_ids.get(i));
+		e.appendChild(createDisplayTextElement(owner, GSXML.DISPLAY_TEXT_NAME, (String)option_names.get(i)));
+		p.appendChild(e);
+	    }
+	}
+	return p;
+    }
+
+
+    /** returns the element parent/node_name[@attribute_name='attribute_value']
+     */
+    public static Element getNamedElement(Element parent, String node_name,
+					  String attribute_name, 
+					  String attribute_value) {
+
+	NodeList children = parent.getChildNodes();
+	for (int i=0; i<children.getLength(); i++) {
+	    Node child = children.item(i);
+	    logger.debug("getnamed elem, node nmae="+child.getNodeName());
+	    if (child.getNodeName().equals(node_name)) {
+		if (((Element)child).getAttribute(attribute_name).equals(attribute_value))
+		    return (Element)child;
+	    }
+	}
+	// not found
+	return null;
+    }
+
+    public static int SORT_TYPE_STRING = 0;
+    public static int SORT_TYPE_INT = 1;
+    public static int SORT_TYPE_FLOAT = 2;
+    
+    // sort type: 
+    public static Element insertIntoOrderedList(Element parent_node,
+						String node_name,
+						Element start_from_elem, 
+						Element new_elem, String sort_att,
+						boolean descending)
+    {
+	if (new_elem == null) return null;
+	Element cloned_elem = (Element)parent_node.getOwnerDocument().importNode(new_elem, true);
+	if (start_from_elem == null) {
+	    parent_node.appendChild(cloned_elem);
+	    return cloned_elem;
+	}
+		
+	Node current_node = start_from_elem;
+	String insert_att = cloned_elem.getAttribute(sort_att);
+	String list_att = start_from_elem.getAttribute(sort_att);
+	while ((!descending && list_att.compareTo(insert_att)<0) || (descending && list_att.compareTo(insert_att)>0)) {
+	    current_node = current_node.getNextSibling();
+	    if (current_node == null) break; // end of the list
+	    if (!current_node.getNodeName().equals(node_name)) {
+		continue; // not a valid node
+	    }
+	    list_att = ((Element)current_node).getAttribute(sort_att);
+	}
+	
+	parent_node.insertBefore(cloned_elem, current_node);
+	return cloned_elem;
+    }
+
+
+    /** Returns the appropriate language element from a display elem,
+     display is the containing element, name is the name of the element to 
+     look for, lang is the preferred language, lang_default is the fall back 
+     lang if neither lang is found, will return the first one it finds*/
+    public static String getDisplayText(Element display, String name,
+					String lang, String lang_default) {
+	
+	String def = null;
+	String first = null;
+	NodeList elems = display.getElementsByTagName(DISPLAY_TEXT_ELEM);
+	if (elems.getLength() == 0) return "";
+	for (int i=0; i<elems.getLength(); i++) {
+	    Element e = (Element)elems.item(i);
+	    String n = e.getAttribute(NAME_ATT);
+	    if (name.equals(n)) {
+		String l = e.getAttribute(LANG_ATT);
+		if (lang.equals(l)) {
+		    return getNodeText(e);
+		} else if (lang_default.equals(l)) {
+			def = getNodeText(e);
+		} else if (first == null) {
+		    first = getNodeText(e);
+		}
+	    } else {
+		continue;
+	    }
+	}
+
+	if (def != null) {
+	    return def;
+	}
+	if (first != null) {
+	    return first;
+	}
+	return "";
+    }
+    
+    // replaces < > " ' & in the original with their entities
+    public static String xmlSafe(String original) {
+
+	StringBuffer filtered = new StringBuffer(original.length());
+	char c;
+	for (int i=0; i<original.length(); i++) {
+	    c = original.charAt(i);
+	    if (c == '>') {
+		filtered.append("&gt;");
+	    } else if (c == '<') {
+		filtered.append("&lt;");
+	    } else if (c == '"') {
+		filtered.append("&quot;");
+	    } else if (c == '&') {
+		filtered.append("&amp;");
+	    } else if (c == '\'') {
+		filtered.append("&apos;");
+	    } else {
+		filtered.append(c);
+	    }
+	}
+	return filtered.toString();
+    }
+
+    
+    // replaces < > " ' & entities with their originals
+    public static String unXmlSafe(String original) {
+	
+ 	StringBuffer filtered = new StringBuffer(original.length());
+ 	char c;
+ 	for (int i=0; i<original.length(); i++) {
+ 	    c = original.charAt(i);
+ 	    if (c == '&') {
+ 		int pos = original.indexOf(";", i);
+		String entity = original.substring(i+1, pos);
+		if (entity.equals("gt")) {
+		    filtered.append(">");
+		} else if (entity.equals("lt")) {
+		    filtered.append("<");
+		} else if (entity.equals("apos")) {
+		    filtered.append("'");
+		} else if (entity.equals("amp")) {
+		    filtered.append("&");
+		} else if (entity.equals("quot")) {
+		    filtered.append("\"");
+		} else {
+		    filtered.append("&"+entity+";");
+		}
+		i = pos;
+	    }
+	    else {
+ 		filtered.append(c);
+ 	    }
+ 	}
+ 	return filtered.toString();
+     }
+
+    public static void printXMLNode(Node e) {
+	printXMLNode(e, 0) ;
+    }
+
+    public static String xmlNodeToString(Node e){
+        StringBuffer sb = new StringBuffer("");
+    	xmlNodeToString(sb,e,0); 
+	return sb.toString();
+    }
+
+    private static void xmlNodeToString(StringBuffer sb, Node e, int depth){
+     
+  	for (int i=0 ; i<depth ; i++) 
+	    sb.append(' ') ;
+
+	if (e.getNodeType() == Node.TEXT_NODE){
+	    sb.append("text") ;
+	    return ;
+	}
+	
+	sb.append('<');
+	sb.append(e.getNodeName());
+	NamedNodeMap attrs = e.getAttributes();
+	for (int i = 0; i < attrs.getLength(); i++) {
+	    Node attr = attrs.item(i);
+	    sb.append(' ');  
+	    sb.append(attr.getNodeName());
+	    sb.append("=\"");
+	    sb.append(attr.getNodeValue());   
+	    sb.append('"');
+	}
+
+	NodeList children = e.getChildNodes();
+
+	if (children == null || children.getLength() == 0)
+	    sb.append("/>\n") ;
+	else {
+	    
+	    sb.append(">\n") ;
+	    
+	    int len = children.getLength();
+	    for (int i = 0; i < len; i++) {
+		xmlNodeToString(sb,children.item(i), depth + 1);
+	    }
+	    
+	    for (int i=0 ; i<depth ; i++) 
+		 sb.append(' ') ;
+	    
+	     sb.append("</" + e.getNodeName() + ">\n");
+	}	
+
+
+    }
+   
+    public static void printXMLNode(Node e, int depth) { //recursive method call using DOM API...
+	
+	for (int i=0 ; i<depth ; i++) 
+	    System.out.print(' ') ;
+
+	if (e.getNodeType() == Node.TEXT_NODE){
+	    System.out.println("text") ;
+	    logger.debug(e.getNodeValue()) ;
+	    return ;
+	}
+	
+	System.out.print('<');
+	System.out.print(e.getNodeName());
+	NamedNodeMap attrs = e.getAttributes();
+	for (int i = 0; i < attrs.getLength(); i++) {
+	    Node attr = attrs.item(i);
+	    System.out.print(' ');  
+	    System.out.print(attr.getNodeName());
+	    System.out.print("=\"");
+	    System.out.print(attr.getNodeValue());   
+	    System.out.print('"');
+	}
+
+	NodeList children = e.getChildNodes();
+
+	if (children == null || children.getLength() == 0)
+	    System.out.println("/>") ;
+	else {
+	    
+	    System.out.println('>') ;
+	    
+	    int len = children.getLength();
+	    for (int i = 0; i < len; i++) {
+		printXMLNode(children.item(i), depth + 1);
+	    }
+	    
+	    for (int i=0 ; i<depth ; i++) 
+		System.out.print(' ') ;
+	    
+	    System.out.println("</" + e.getNodeName() + ">");
+	}	
+
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSXSLT.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSXSLT.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GSXSLT.java	(revision 13928)
@@ -0,0 +1,99 @@
+package org.greenstone.gsdl3.util;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Document;
+import org.w3c.dom.Text;
+
+import java.util.HashMap;
+import java.util.Vector;
+import java.util.ArrayList;
+
+/** various functions for manipulating Greenstone xslt  */
+public class GSXSLT {
+
+    /** takes a stylesheet Document, and adds in any child nodes from extra_xsl
+     * named templates overwrite any existing one, while match templates are
+just added to the end of teh stylesheet
+     */
+    public static void mergeStylesheets(Document main_xsl, Element extra_xsl) {
+	
+	Element main = main_xsl.getDocumentElement();
+	
+	NodeList children = extra_xsl.getElementsByTagNameNS("http://www.w3.org/1999/XSL/Transform", "template");
+	for (int i=0; i<children.getLength(); i++) {
+	    String name = ((Element)children.item(i)).getAttribute("name");
+	    if (!name.equals("")) {
+		Element old_template = GSXML.getNamedElement(main, "xsl:template", "name", name);
+		if (old_template != null) {
+		    main.removeChild(old_template);
+		}
+	    }
+		
+	    main.appendChild(main_xsl.importNode(children.item(i), true));
+	}
+
+    }
+
+    /** takes any import or include nodes, and creates absolute path names
+     * for the files
+     */
+    public static void absoluteIncludePaths(Document stylesheet, 
+					    String gsdl3_home,
+					    String site_name,
+					    String collection,
+					    String interface_name,
+					    ArrayList base_interfaces) {
+	
+	
+	Element base_node = stylesheet.getDocumentElement();
+	Node child = base_node.getFirstChild();
+	while(child != null) {
+	    String name = child.getNodeName();
+	    if (name.equals("xsl:import") || name.equals("xsl:include")) {
+		((Element)child).setAttribute("href", GSFile.stylesheetFile(gsdl3_home, site_name, collection, interface_name, base_interfaces, ((Element)child).getAttribute("href")));
+	    }
+	    child = child.getNextSibling();
+	}
+	
+    }
+
+    /** 
+     * looks through a stylesheet for <xxx:template match='template_name'>
+     * inside this template it looks for any <xxx:value-of select='metadataList/metadata[@name=yyy]> elements, and extracts the metadata names into a Vector
+     */
+    public static Vector extractWantedMetadata(Document stylesheet, String template_name) {
+	
+	Vector metadata = new Vector();
+	Element base_node = stylesheet.getDocumentElement();
+	NodeList templates = base_node.getElementsByTagNameNS("*","template");
+	for (int i=0; i<templates.getLength(); i++) {
+	    Element template = (Element)templates.item(i);
+	    String match_name = template.getAttribute("match");
+	    if (!match_name.equals(template_name)) {
+		continue; // we're only looking for specific templates
+	    }
+	    String mode = template.getAttribute("mode");
+	    if (!mode.equals("")) {   
+		continue; // we only want ones without modes - these are processing ones, not display ones
+	    }
+	    // we have one that we want to look through
+	    NodeList values = template.getElementsByTagNameNS("*", "value-of");
+	    for (int v=0; v<values.getLength(); v++) {
+		String select = ((Element)values.item(v)).getAttribute("select");
+		if (select.startsWith("metadataList/metadata[@name=")) {
+		    String []bits = select.split("'|\"");
+		    // there should be two quotes in teh string, therefore 3 items, and the second one is teh one we want
+		    String name = bits[1];
+		    metadata.add(name);
+		}
+	    }
+	}
+	return metadata;	
+    }
+
+    
+
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GlobalProperties.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GlobalProperties.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/GlobalProperties.java	(revision 13928)
@@ -0,0 +1,66 @@
+package org.greenstone.gsdl3.util;
+
+import java.util.Properties;
+import java.io.File;
+import java.io.InputStream;
+
+import org.apache.log4j.*;
+
+/** holds some global properties for the application. Read from a properties file */
+public class GlobalProperties {
+
+
+     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.GlobalProperties.class.getName());
+    private static Properties properties = null;
+    private static String properties_filename = "global.properties";
+    private static String gsdl3_home = null;
+    private static String gsdl3_web_address = null;
+    
+    // Note, that if the servlet is reloadable, then it is reloaded each time the file is changed.
+    static {
+	//load in the properties
+	properties = new Properties();
+	reload();	
+    }
+    
+    /** get the value of the property 'key'. returns null if not found */
+    public static String getProperty(String key) {
+	return properties.getProperty(key);
+    }
+
+    /** get the value of the property 'key'. 
+     * returns default_value if not found */
+    public static String getProperty(String key, String default_value) {
+	return properties.getProperty(key, default_value);
+    }
+
+    /** some special ones */
+    public static String getGSDL3Home() {
+	return gsdl3_home;
+    }
+
+    public static String getGSDL3WebAddress() {
+	return gsdl3_web_address;
+    }
+    
+    public static void reload() {
+	try {
+	    InputStream in = Class.forName("org.greenstone.gsdl3.util.GlobalProperties").getClassLoader().getResourceAsStream(properties_filename);
+	    if (in != null) {
+		logger.error("loading global properties");
+		properties.load(in);
+		in.close();
+	    } else {
+		logger.error("couldn't load global properties!");
+	    }
+	    gsdl3_home = properties.getProperty("gsdl3.home");
+	    // make sure the path separators are correct
+	    File gs3_file = new File(gsdl3_home);
+	    gsdl3_home = gs3_file.getPath();
+	    gsdl3_web_address = "http://"+ properties.getProperty("tomcat.server")+":"+ properties.getProperty("tomcat.port")+"/"+properties.getProperty("tomcat.context");
+	} catch (Exception e) {
+	    logger.error("Exception trying to reload global.properties: "+e);
+	}
+	
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/MacroResolver.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/MacroResolver.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/MacroResolver.java	(revision 13928)
@@ -0,0 +1,143 @@
+/*
+ *    MacroResolver.java
+ *    Copyright (C) 2005 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.util;
+
+import java.util.ArrayList;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+
+abstract public class MacroResolver {
+
+    public static final String SCOPE_TEXT = "text";
+    public static final String SCOPE_META = "metadata";
+    public static final String SCOPE_ALL = "all";
+
+    public static final int TYPE_TEXT = 0;
+    public static final int TYPE_META = 1;
+    public static final int TYPE_DICT = 2;
+    
+    protected ArrayList text_macros = null;
+    protected ArrayList metadata_macros = null;
+
+    String lang = null;
+
+    public MacroResolver() {
+    	this.text_macros = new ArrayList();
+	this.metadata_macros = new ArrayList();
+    }
+
+    
+    public void setSiteDetails(String site_address, String cluster_name) {
+	if (site_address != null) {
+	    addMacro(TYPE_TEXT, "_httpsite_", site_address, SCOPE_ALL, false);
+	}
+	if (cluster_name != null) {
+	    addMacro(TYPE_TEXT, "_clustername_", cluster_name, SCOPE_ALL, false);
+	}
+    }
+
+    public void addMacro(int type, String macro, String text_or_metadata, String scope, boolean resolve) {
+	Macro m = new Macro();
+	m.type = type;
+	m.macro = macro;
+	m.text = text_or_metadata;
+	m.resolve = resolve;
+	addMacro(m, scope);
+    }
+
+    public void addMacro(int type, String macro, String bundle, String key, String scope, boolean resolve) {
+	Macro m = new Macro();
+	m.type = type;
+	m.macro = macro;
+	m.bundle = bundle;
+	m.key = key;
+	m.resolve = resolve;
+	addMacro(m, scope);
+    }
+    
+    public void addMacros(Element replace_list_elem) {
+	NodeList replaces = replace_list_elem.getElementsByTagName("replace");
+	for (int i=0; i<replaces.getLength(); i++) {
+	    Element e = (Element)replaces.item(i);
+	    String scope = e.getAttribute("scope");
+	    if (scope.equals("")) {
+		scope = SCOPE_ALL;
+	    }
+	    boolean resolve = true;
+	    String resolve_str = e.getAttribute("resolve");
+	    if (resolve_str.equals("false")) {
+		resolve = false;
+	    }
+	    String from = e.getAttribute("macro");
+	    String to = e.getAttribute("text");
+	    if (!to.equals("")) {
+		addMacro(TYPE_TEXT, from, to, scope, resolve);
+	    } else {
+		String meta = e.getAttribute("metadata");
+		if (!meta.equals("")) {
+		    addMacro(TYPE_META, from, meta, scope, resolve);
+		} else {
+		    String key = e.getAttribute("key");
+		    String bundle = e.getAttribute("bundle");
+		    addMacro(TYPE_DICT, from, bundle, key, scope, resolve);
+		}
+                                                                                                             	    } 
+	}
+	
+    }
+
+    protected void addMacro(Macro m, String scope) {
+
+	if (scope.equals(SCOPE_TEXT)) {
+	    this.text_macros.add(m);
+	}
+	else if (scope.equals(SCOPE_META)) {
+	    this.metadata_macros.add(m);
+	}
+	else if (scope.equals(SCOPE_ALL)) {
+	    this.text_macros.add(m);
+	    this.metadata_macros.add(m);
+	    
+	}
+
+    }
+    
+    abstract public String resolve(String text, String lang, String scope, 
+				   String doc_oid);
+    
+    protected class Macro {
+	
+	/** type of replacement: TEXT, METADATA, DICTIONARY */
+	public int type;
+	/** the macro to replace */
+	public String macro = null;
+	/** If text type, holds the text to replace with. If metadata type, holds the metadata name */
+	public String text = null; 
+	/** If dictionary type, holds the key to look up in the dictionary */
+	public String key = null;
+	/** If dictionary type, holds the resource bundle name */
+	public String bundle = null;
+	/** If true, will try to resolve macros in the replacement text */
+	public boolean resolve = true;
+	
+    }
+	
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/Misc.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/Misc.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/Misc.java	(revision 13928)
@@ -0,0 +1,106 @@
+ /*
+ *    Misc.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.greenstone.gsdl3.util;
+
+import java.util.HashMap;
+import java.util.Set;
+import java.util.Map;
+import java.util.Iterator;
+import java.util.Properties;
+import java.io.InputStream;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+
+/** contains miscellaneous functions */
+public class Misc {
+    
+    public static void printHash(HashMap map) {
+	Set entries = map.entrySet();
+	Iterator i = entries.iterator();
+	while (i.hasNext()) {
+	    Map.Entry m = (Map.Entry)i.next();
+	    String name = (String)m.getKey();
+	    String value = (String)m.getValue();
+	}  
+    }
+    
+    /** Method to determine if the host system is Windows based.
+     * @return a boolean which is true if the platform is Windows, 
+     * false otherwise
+     */
+    public static boolean isWindows() {
+	Properties props = System.getProperties();
+	String os_name = props.getProperty("os.name","");
+	if(os_name.startsWith("Windows")) {
+	    return true;
+	}
+	return false;
+    }
+    
+    public static boolean isWindows9x() {
+        Properties props = System.getProperties();
+        String os_name = props.getProperty("os.name","");
+        if(os_name.startsWith("Windows") && os_name.indexOf("9") != -1) {
+            return true;
+        }
+        return false;
+    }
+
+    /** Method to determine if the host system is MacOS based.
+     * @return a boolean which is true if the platform is MacOS, false otherwise
+     */
+    public static boolean isMac() {
+        Properties props = System.getProperties();
+        String os_name = props.getProperty("os.name","");
+        if(os_name.startsWith("Mac OS")) {
+            return true;
+        }
+        return false;
+    }
+    
+    public static boolean isBigEndian() {
+
+	if (System.getProperty("sun.cpu.endian").equals("big")) {
+	    return true;
+	}
+	return false;
+
+    }
+
+    public static BufferedReader makeHttpConnection(String url_string)
+	throws java.net.MalformedURLException, java.io.IOException {
+	BufferedReader reader = null;
+	URL url = new URL(url_string);
+	HttpURLConnection connection = (HttpURLConnection)url.openConnection();
+	InputStream input = connection.getInputStream();
+	reader = new BufferedReader(new InputStreamReader(input));  
+	return reader;
+    }
+
+    public static void main(String [] args) {
+	isBigEndian();
+    }
+
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/MyNodeList.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/MyNodeList.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/MyNodeList.java	(revision 13928)
@@ -0,0 +1,46 @@
+/*
+ *    MyNodeList.java
+ *   
+
+ *    Copyright (C) 2005 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.util;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import java.util.ArrayList;
+
+public class MyNodeList implements NodeList {
+    private ArrayList node_list = null;
+    
+    public MyNodeList() {
+	node_list = new ArrayList();
+    }
+    public int getLength() {
+	return node_list.size();
+    }
+    
+    public Node item(int i) {
+	if (i<0 || i >= node_list.size()) return null;
+	return (Node)node_list.get(i);
+    }
+    
+    public void addNode(Node n) {
+	node_list.add(n);
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/NZDLParams.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/NZDLParams.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/NZDLParams.java	(revision 13928)
@@ -0,0 +1,25 @@
+package org.greenstone.gsdl3.util;
+
+public class NZDLParams extends GSParams {
+
+    public NZDLParams() {
+	super();
+
+	// now add in all the service ones we will be using
+	addParameter("stem",  true);	
+	addParameter("case",  true);
+	addParameter("index", true);
+	addParameter("matchMode",  true);
+	addParameter("maxDocs",  true);
+	addParameter("query", true);
+	addParameter("level",  true);
+	addParameter("qb",  true); // queryBox
+	addParameter("qm",  true); // queryMode
+	addParameter("qt",  true); // query type
+	addParameter("qfm",  true); // query form mode
+	addParameter("qfn",  true); // query form number of boxes
+	addParameter("ct",  true); // collection type - mg or mgpp
+	
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/OID.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/OID.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/OID.java	(revision 13928)
@@ -0,0 +1,86 @@
+package org.greenstone.gsdl3.util;
+
+/** utility class to handle greenstone OIDs
+ *
+ * based around OIDtools.h from gsdl
+ */
+public class OID {
+    
+    /** returns everything up to the first dot 
+	if no dot, returns oid */
+    public static String getTop(String oid) {
+	int pos = oid.indexOf('.');
+	if (pos == -1) {
+	    return oid;
+	}
+	return oid.substring(0, pos);
+	
+    }
+    /** returns true is oid is top level (ie has no dots) 
+     returns false for an empty oid */
+    public static boolean isTop(String oid) {
+	if (oid.equals("")) {
+	    return false;
+	}
+	return (oid.indexOf('.')==-1);
+    }
+	
+    /** returns the parent of oid (everything up to last dot) 
+     returns oid if oid has no parent */
+    public static String getParent(String oid) {
+	int pos = oid.lastIndexOf('.');
+	if (pos == -1) {
+	    return oid;
+	}
+	return oid.substring(0, pos);
+    }
+
+    /** returns the full name - replaces all " with parent */
+    public static String translateParent(String oid, String parent) {
+	return oid.replaceAll("\"", parent); 
+    }
+    /** does the opposite to translate_parent */
+    public static String shrinkParent(String oid) {
+	int pos = oid.lastIndexOf('.');
+	if (pos==-1) return oid;
+	return "\""+oid.substring(pos);
+    }
+    /** returns true if oid uses .fc, .lc, .pr, .ns, .ps .rt (root) .ss (specified sibling)*/
+    public static boolean needsTranslating(String oid) {
+	if (oid.length()<4) return false;
+	String tail = oid.substring(oid.length()-3);
+	return (tail.equals(".fc") || tail.equals(".lc") || 
+		tail.equals(".pr") || tail.equals(".ns") || 
+		tail.equals(".ps") || tail.equals(".rt") || 
+		tail.equals(".ss") || tail.equals(".np") ||
+		tail.equals(".pp"));
+    }
+    /** strips suffix from end */
+    public static String stripSuffix(String oid) {
+	String tail = oid.substring(oid.length()-3);
+	while (tail.equals(".fc") || tail.equals(".lc") || 
+	       tail.equals(".pr") || tail.equals(".ns") || 
+	       tail.equals(".ps") || tail.equals(".ss") || 
+	       tail.equals(".np") || tail.equals(".pp") ||
+	       tail.equals(".rt") ) {
+	    if (tail.equals(".ss")) { // have doc.sibnum.ss
+		oid = oid.substring(0, oid.length()-3);
+		int pos = oid.lastIndexOf('.');
+		//strip that too
+		oid = oid.substring(0, pos);
+	    } 
+	    oid = oid.substring(0, oid.length()-3);
+	    tail = oid.substring(oid.length()-3);
+	}
+	
+	return oid;
+    }
+    /** returns true if child is a child of parent 
+     an oid is not a child of itself */
+    public static boolean isChildOf(String parent, String child) {
+	if (parent.equals(child)) {
+	    return false;
+	}
+	return child.startsWith(parent);
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/OIDTest.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/OIDTest.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/OIDTest.java	(revision 13928)
@@ -0,0 +1,94 @@
+package org.greenstone.gsdl3.util;
+
+import junit.framework.*; 
+
+public class OIDTest extends TestCase {
+
+    /** what type of test - used by the testing framework */
+    public static final String TEST_ALL_TEST_TYPE="UNIT";
+
+    private static final String empty = "";
+    private static final String oid1="HASH123";
+    private static final String oid2="HASH123.1";
+    private static final String oid3="HASH123.1.2";
+    private static final String oidfc = oid1+".fc";
+    private static final String oidlc = oid1+".lc";
+    private static final String oidpr = oid1+".pr";
+    private static final String oidns = oid1+".ns";
+    private static final String oidps = oid1+".ps";
+
+    public OIDTest(String name) {
+	super(name);
+    }
+
+    /** test suite that dynamically runs all the tests */
+    public static Test suite() {
+	return new TestSuite(OIDTest.class);
+    }
+
+    public void testGetTop() {
+	
+	assertEquals(oid1, OID.getTop(oid1));
+	assertEquals(oid1, OID.getTop(oid2));
+	assertEquals(empty, OID.getTop(empty));
+    }
+  
+    public void testIsTop() {
+	assertTrue(!OID.isTop(empty));
+	assertTrue(OID.isTop(oid1));
+	assertTrue(!OID.isTop(oid2));
+    }
+
+    public void testGetParent() {
+
+	assertEquals(empty, OID.getParent(oid1));
+	assertEquals(oid1, OID.getParent(oid2));
+	assertEquals(empty, OID.getParent(empty));
+	
+    }
+
+    public void testTranslateParent() {
+	String short_id = "\".1";
+	assertEquals(oid2, OID.translateParent(short_id, oid1));
+	// should return the original oid if its not a shortened form
+	assertEquals(oid2, OID.translateParent(oid2, oid1));
+	
+    }
+
+    public void testShrinkParent() {
+	String short_oid2 = "\".1";
+	String short_oid3 = "\".2";
+
+	assertEquals(oid1, OID.shrinkParent(oid1));
+	assertEquals(short_oid2, OID.shrinkParent(oid2));
+	assertEquals(short_oid3, OID.shrinkParent(oid3));
+    }
+
+    public void testNeedsTranslating() {
+	assertTrue(!OID.needsTranslating(oid1));
+	assertTrue(!OID.needsTranslating(oid2));
+	assertTrue(OID.needsTranslating(oidfc));
+	assertTrue(OID.needsTranslating(oidlc));
+	assertTrue(OID.needsTranslating(oidpr));
+	assertTrue(OID.needsTranslating(oidns));
+	assertTrue(OID.needsTranslating(oidps));
+
+    }
+
+    public void testStripSuffix() {
+	assertEquals(oid1, OID.stripSuffix(oidfc));
+	assertEquals(oid1, OID.stripSuffix(oidlc));
+	assertEquals(oid1, OID.stripSuffix(oidpr));
+	assertEquals(oid1, OID.stripSuffix(oidns));
+	assertEquals(oid1, OID.stripSuffix(oidps));
+    }
+
+    public void testIsChildOf() {
+	assertTrue(OID.isChildOf(oid1, oid2));
+	assertTrue(OID.isChildOf(oid1, oid3));
+	assertTrue(OID.isChildOf(oid2, oid3));
+	assertTrue(!OID.isChildOf(oid3, oid1));
+	assertTrue(!OID.isChildOf(oid1, oid1));
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/Processing.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/Processing.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/Processing.java	(revision 13928)
@@ -0,0 +1,102 @@
+package org.greenstone.gsdl3.util;
+
+import java.io.InputStreamReader;
+
+import org.apache.log4j.*;
+
+public class Processing {
+
+      static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.Processing.class.getName());
+ 
+      /** Determine if the given process is still executing. It does this by attempting to throw an exception - not the most efficient way, but the only one as far as I know
+     * @param process the Process to test
+     * @return true if it is still executing, false otherwise
+     */
+    static public boolean processRunning(Process process) {
+	boolean process_running = false;
+
+	try {
+	    process.exitValue(); // This will throw an exception if the process hasn't ended yet.
+	}
+	catch(IllegalThreadStateException itse) {
+	    process_running = true;
+	}
+	catch(Exception exception) {
+	    exception.printStackTrace();	    
+	}
+	return process_running;
+    }
+    
+    static public int runProcess(String  command) {
+	
+	logger.error("executing command "+command);
+	int exit_value = -1;
+	try {
+	    Process prcs = Runtime.getRuntime().exec(command);
+	    
+	    InputStreamReader error_stream = new InputStreamReader( prcs.getErrorStream(), "UTF-8" );
+	    InputStreamReader output_stream = new InputStreamReader( prcs.getInputStream(), "UTF-8"  );
+	    
+	    StringBuffer error_buffer = new StringBuffer();
+	    StringBuffer output_buffer = new StringBuffer();
+	    
+	    while(processRunning(prcs)) {
+		// Hopefully this doesn't block if the process is trying to write to STDOUT.
+		if((error_stream!=null)) {// && error_stream.ready()) { 
+		    while (error_stream.ready()) {
+			error_buffer.append((char)error_stream.read());
+		    }
+		    //error_buffer = get_stream_char(error_stream,error_buffer,bos);
+		}
+		//Hopefully this won't block if the process is trying to write to STDERR
+		/*else if*/ while (output_stream.ready()) {
+		    output_buffer.append((char)output_stream.read());
+		    //output_buffer = get_stream_char(output_stream,output_buffer,bos);
+		}
+		//else {
+		try {
+		    Thread.sleep(100);
+		}
+		catch(Exception exception) {
+		}
+		// }
+	    }
+	    
+	    // Of course, just because the process is finished doesn't
+	    // mean the incoming streams are empty. Unfortunately I've
+	    // got no chance of preserving order, so I'll process the
+	    // error stream first, then the out stream
+	    while(error_stream.ready()) {
+		error_buffer.append((char)error_stream.read());
+		//error_buffer = get_stream_char(error_stream,error_buffer,bos);
+	    }
+	    
+	    while(output_stream.ready()) {
+		output_buffer.append((char)output_stream.read());
+		//output_buffer = get_stream_char(output_stream,output_buffer,bos);
+	    }
+	    
+	    // do something with the messages
+	    logger.error("err>"+error_buffer.toString());
+	    logger.error("out>"+output_buffer.toString());
+	    // Ensure that any messages still remaining in the string buffers are fired off.
+	    // Now display final message based on exit value
+	    
+	    prcs.waitFor(); 
+	    error_stream.close();
+	    output_stream.close();
+	    error_buffer = null;
+	    output_buffer = null;
+	    
+	    exit_value =  prcs.exitValue();
+	} catch (Exception e) {
+	    logger.error(e);
+	    return 1;
+	}
+	return exit_value;
+	
+	
+    }
+   
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/XMLConverter.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/XMLConverter.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/XMLConverter.java	(revision 13928)
@@ -0,0 +1,339 @@
+/*
+ *    XMLConverter.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.util;
+
+// XML classes
+import org.w3c.dom.Document; 
+import org.w3c.dom.Node; 
+import org.w3c.dom.NodeList;
+import org.w3c.dom.NamedNodeMap;
+import org.xml.sax.InputSource;
+import org.xml.sax.EntityResolver;
+import org.apache.xerces.parsers.DOMParser;
+import org.apache.xerces.dom.DocumentImpl; // for new Documents
+
+// other java classes
+import java.io.Reader;
+import java.io.InputStreamReader;
+import java.io.StringReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileReader;
+
+import org.apache.log4j.*;
+
+/** XMLConverter - utility class for greenstone
+ *
+ * parses XML Strings into Documents, converts Nodes to Strings
+ * different parsers have different behaviour - can experiment in here
+ * now we only use xerces
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ * @version $Revision$
+ *
+ */
+public class XMLConverter {
+
+     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.XMLConverter.class.getName());
+
+    /** xerces parser */
+    protected DOMParser parser = null;
+
+    private boolean outputEscaping = true;
+
+
+     /** the no-args constructor */
+    public XMLConverter() {
+	try {
+	    this.parser = new DOMParser();
+	    this.parser.setFeature("http://xml.org/sax/features/validation", false);
+	    // don't try and load external DTD - no need if we are not validating, and may cause connection errors if a proxy is not set up.
+	    this.parser.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+	    // a performance test showed that having this on lead to increased 
+	    // memory use for small-medium docs, and not much gain for large 
+	    // docs.
+	    // http://www.sosnoski.com/opensrc/xmlbench/conclusions.html
+	    this.parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false);
+	} catch (Exception e) {
+	    logger.error(e.getMessage());
+	}
+    }
+
+    /** sets the entity resolver. pass in null to unset it */
+    public void setEntityResolver(EntityResolver er) {
+	this.parser.setEntityResolver(er);
+    }
+	
+    /** returns a DOM Document */
+    public Document getDOM(String in) {
+	    
+	try {
+	    Reader reader = new StringReader(in);
+	    InputSource xml_source = new InputSource(reader);
+	    
+	    this.parser.parse(xml_source);
+	    Document doc = this.parser.getDocument();
+	    
+	    return doc;
+	    
+	} catch (Exception e) {
+	    logger.error(e.getMessage());
+	}
+	return null;
+    }
+  
+    /** returns a DOM Document */
+    public Document getDOM(File in) {
+	try {
+	    FileReader reader = new FileReader(in);
+	    InputSource xml_source = new InputSource(reader);
+	    this.parser.parse(xml_source);
+	    Document doc = this.parser.getDocument();
+	    return doc;
+
+	} catch (Exception e) {
+	    logger.error(e.getMessage(), e);
+	    
+	}
+	return null;
+    }
+
+    /** returns a DOM document */
+    public Document getDOM(File in, String encoding) {
+	try {
+	    
+	    InputStreamReader isr = new InputStreamReader(new FileInputStream(in), encoding);
+	    InputSource xml_source = new InputSource(isr);
+	    
+	    this.parser.parse(xml_source);
+	    Document doc = this.parser.getDocument();
+	    
+	    return doc;
+
+	} catch (Exception e) {
+	    logger.error(e.getMessage());
+	}
+	return null;
+    }
+    
+
+    /** creates a new empty DOM Document */
+    public Document newDOM() {
+	Document doc = new DocumentImpl(); 
+	return doc;
+    }
+
+    /** returns the Node as a String */
+    public String getString(Node xmlNode)
+    {
+	outputEscaping = true;
+	StringBuffer xmlRepresentation = new StringBuffer();
+	getString(xmlNode, xmlRepresentation, 0, false);
+	return xmlRepresentation.toString();
+    }
+
+    /** returns the node as a nicely formatted String - this introduces extra
+     * text nodes if the String is read back in as a DOM, so should only be 
+     * used for printing */
+    public String getPrettyString(Node xmlNode) {
+	
+	outputEscaping = true;
+	StringBuffer xmlRepresentation = new StringBuffer();
+	getString(xmlNode, xmlRepresentation, 0, true);
+	return xmlRepresentation.toString();
+    }
+
+    private void getString(Node xmlNode, StringBuffer xmlRepresentation, 
+			     int depth, boolean pretty)
+    {
+	
+	if (xmlNode == null) {
+	    xmlRepresentation.append("<null>");
+	    return;
+	}
+
+	short nodeType = xmlNode.getNodeType();
+	String nodeName = xmlNode.getNodeName();
+
+	if (nodeType == Node.DOCUMENT_NODE) {
+	    getString(((Document)xmlNode).getDocumentElement(), xmlRepresentation, depth, pretty);
+	    return;
+	}
+	// Handle Element nodes
+	if (nodeType == Node.ELEMENT_NODE) {
+	    if (pretty) {
+		xmlRepresentation.append("\n");
+		for (int i = 0; i < depth; i++) {
+		    xmlRepresentation.append("  ");
+		}
+	    }
+
+	    // Write opening tag
+	    xmlRepresentation.append("<");
+	    xmlRepresentation.append(nodeName);
+	    
+	    // Write the node attributes
+	    NamedNodeMap nodeAttributes = xmlNode.getAttributes();
+	    for (int i = 0; i < nodeAttributes.getLength(); i++) {
+		Node attribute = nodeAttributes.item(i);
+		xmlRepresentation.append(" ");
+		xmlRepresentation.append(attribute.getNodeName());
+		xmlRepresentation.append("=\"");
+		xmlRepresentation.append(attribute.getNodeValue());
+		xmlRepresentation.append("\"");
+	    }
+
+	    // If the node has no children, close the opening tag and return
+	    if (xmlNode.hasChildNodes() == false) {
+		// This produces somewhat ugly output, but it is necessary to compensate
+		// for display bugs in Netscape. Firstly, the space is needed before the
+		// closing bracket otherwise Netscape will ignore some tags (<br/>, for
+		// example). Also, a newline character would be expected after the tag,
+		// but this causes problems with the display of links (the link text
+		// will contain a newline character, which is displayed badly).
+		xmlRepresentation.append(" />");
+		return;
+	    }
+	    
+	    // Close the opening tag
+	    xmlRepresentation.append(">");
+	    
+	    // Apply recursively to the children of this node
+	    // hack for nodes next to text nodes - dont make them pretty
+	    // this is needed for text inside a <pre> element - any new lines 
+	    // or spaces around the span elements show up in the text
+	    NodeList children = xmlNode.getChildNodes();
+	    boolean do_pretty = pretty;
+	    for (int i = 0; i < children.getLength(); i++) {
+		if (children.item(i).getNodeType()==Node.TEXT_NODE) {
+		    do_pretty=false; // if there is a text node amongst the children, do teh following nodes in non-pretty mode - hope this doesn't stuff up something else
+		}
+		getString(children.item(i), xmlRepresentation, depth + 1, do_pretty);
+	    }
+	    
+	    // Write closing tag
+	    if (pretty) {
+		if (xmlRepresentation.charAt(xmlRepresentation.length()-1) == '\n') {
+		    for (int i = 0; i < depth; i++)
+			xmlRepresentation.append("  ");
+		}
+	    }
+	    xmlRepresentation.append("</");
+	    xmlRepresentation.append(nodeName);
+	    xmlRepresentation.append(">");
+	    if (pretty) {
+		xmlRepresentation.append("\n");
+	    }
+	}
+	
+	// Handle Text nodes
+	else if (nodeType == Node.TEXT_NODE) {
+	    String text = xmlNode.getNodeValue();
+
+	    // Perform output escaping, if required
+	    if (outputEscaping) {
+		text = text.replaceAll("&", "&amp;");  // Must be done first!!
+		text = text.replaceAll("<", "&lt;");
+		text = text.replaceAll(">", "&gt;");
+		text = text.replaceAll("\"", "&quot;");
+		text = text.replaceAll("\'", "&apos;");
+	    }
+
+	    // Remove any control-C characters
+	    text = text.replaceAll("" + (char) 3, "");
+	    xmlRepresentation.append(text);
+	}
+
+	// Handle Processing Instruction nodes
+	else if (nodeType == Node.PROCESSING_INSTRUCTION_NODE) {
+	    if (nodeName.equals("javax.xml.transform.disable-output-escaping")) {
+		outputEscaping = false;
+	    }
+	    else if (nodeName.equals("javax.xml.transform.enable-output-escaping")) {
+		outputEscaping = true;
+	    }
+	    else {
+		logger.warn("Unhandled processing instruction " + nodeName);
+	    }
+	}
+	
+	else if (nodeType == Node.COMMENT_NODE) {
+	    String text = xmlNode.getNodeValue();
+	    xmlRepresentation.append("<!-- ");
+	    xmlRepresentation.append(text);
+	    xmlRepresentation.append(" -->");
+	}
+	    
+	    
+	
+	// A type of node that is not handled yet
+	else {
+	    logger.warn("Unknown node type: " + nodeType+" "+getNodeTypeString(nodeType));
+	}
+
+	return;
+    }
+
+    protected static String getNodeTypeString(short node_type) {
+
+	String type = "";
+	switch(node_type) {
+	case Node.ATTRIBUTE_NODE: 
+	    type="ATTRIBUTE_NODE";
+	    break;
+	case Node.CDATA_SECTION_NODE:
+	    type="CDATA_SECTION_NODE";
+	    break;
+	case Node.COMMENT_NODE:
+	    type="COMMENT_NODE";
+	    break;
+	case Node.DOCUMENT_FRAGMENT_NODE:
+	    type="DOCUMENT_FRAGMENT_NODE";
+	    break;
+	case Node.DOCUMENT_NODE:
+	    type="DOCUMENT_NODE";
+	    break;
+	case Node.DOCUMENT_TYPE_NODE:
+	    type="DOCUMENT_TYPE_NODE";
+	    break;
+	case Node.ELEMENT_NODE:
+	    type="ELEMENT_NODE";
+	    break;
+	case Node.ENTITY_NODE:
+	    type="ENTITY_NODE";
+	    break;
+	case Node.ENTITY_REFERENCE_NODE:
+	    type="ENTITY_REFERENCE_NODE";
+	    break;
+	case Node.NOTATION_NODE:
+	    type="NOTATION_NODE";
+	    break;
+	case Node.PROCESSING_INSTRUCTION_NODE:
+	    type="PROCESSING_INSTRUCTION_NODE";
+	    break;
+	case Node.TEXT_NODE:
+	    type="TEXT_NODE";
+	    break;
+	default:
+	    type="UNKNOWN";
+	}
+
+	return type;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/XMLTransformer.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/XMLTransformer.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/XMLTransformer.java	(revision 13928)
@@ -0,0 +1,197 @@
+/*
+ *    XMLTransformer.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.util;
+
+// XML classes
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.dom.DOMResult;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+// other java classes
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.File;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.Map;
+import java.util.Iterator;
+
+import org.apache.log4j.*;
+
+/** XMLTransformer - utility class for greenstone
+ *
+ * transforms xml using xslt
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ * @version $Revision$
+ */
+public class XMLTransformer {
+
+    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.XMLTransformer.class.getName());
+
+  /** The transformer factory we're using */
+    TransformerFactory t_factory=null;
+  
+  /**
+   * The no-arguments constructor. 
+   *
+   * Any exceptions thrown are caught internally
+   * 
+   * @see javax.xml.transform.TransformerFactory
+   */
+    public XMLTransformer() {
+
+	// make sure we are using the xalan transformer
+	System.setProperty("javax.xml.transform.TransformerFactory", "org.apache.xalan.processor.TransformerFactoryImpl");
+	try {
+	    this.t_factory = org.apache.xalan.processor.TransformerFactoryImpl.newInstance();
+
+	} catch (Exception e) {
+	    logger.error("exception "+e.getMessage());
+	}
+    }
+
+ 
+	
+  /**
+   * Transform an XML document using a XSLT stylesheet
+   * 
+   * @param stylesheet a filename for an XSLT stylesheet
+   * @param xml_in the XML to be transformed
+   * @return the transformed XML
+   */
+    public String transform(String stylesheet, String xml_in) {
+	
+	try {
+	    // Use the TransformerFactory to process the stylesheet Source and generate a Transformer.
+	    Transformer transformer = this.t_factory.newTransformer(new StreamSource(stylesheet));
+
+	    // Use the Transformer to transform an XML Source and send the output to a Result object.
+	    StringWriter output = new StringWriter();
+
+	    transformer.transform(new StreamSource(new StringReader(xml_in)), new StreamResult(output));
+	    return output.toString();
+	} catch (TransformerConfigurationException e) {
+	    logger.error("couldn't create transformer object: "+e.getMessageAndLocation());
+	    logger.error(e.getLocationAsString());  
+	    return "";
+	} catch (TransformerException e) {
+	    logger.error("couldn't transform the source: " + e.getMessage());
+	    return "";
+	}	
+    }
+
+    public String transformToString(Document stylesheet, Document source) {
+	return transformToString(stylesheet, source, null);
+    }
+    
+    public String transformToString(Document stylesheet, Document source, HashMap parameters) {
+	
+	try {
+	    // Use the TransformerFactory to process the stylesheet Source and generate a Transformer.
+	    Transformer transformer = this.t_factory.newTransformer(new DOMSource(stylesheet));
+	    if (parameters != null) {
+		Set params = parameters.entrySet();
+		Iterator i = params.iterator();
+		while (i.hasNext()) {
+		    Map.Entry m = (Map.Entry)i.next();
+		    transformer.setParameter((String)m.getKey(), m.getValue());
+		}
+	    }
+	    //transformer.setParameter("page_lang", source.getDocumentElement().getAttribute(GSXML.LANG_ATT));
+
+	    
+	    // Use the Transformer to transform an XML Source and send the output to a Result object.
+	    StringWriter output = new StringWriter();
+	    
+	    transformer.transform(new DOMSource(source), new StreamResult(output));
+	    return output.toString();
+	} catch (TransformerConfigurationException e) {
+	    logger.error("couldn't create transformer object: "+e.getMessageAndLocation());
+	    logger.error(e.getLocationAsString());  
+	    return "";
+	} catch (TransformerException e) {
+	    logger.error("couldn't transform the source: " + e.getMessage());
+	    return "";
+	}	
+      }
+
+    public Node transform(Document stylesheet, Document source) {
+	return transform(stylesheet, source, null);
+    }
+
+    public Node transform(Document stylesheet, Document source, HashMap parameters) {
+
+	try {
+	    // Use the TransformerFactory to process the stylesheet Source and generate a Transformer.
+	    Transformer transformer = this.t_factory.newTransformer(new DOMSource(stylesheet));
+	    if (parameters != null) {
+		Set params = parameters.entrySet();
+		Iterator i = params.iterator();
+		while (i.hasNext()) {
+		    Map.Entry m = (Map.Entry)i.next();
+		    transformer.setParameter((String)m.getKey(), m.getValue());
+		}
+	    }
+
+	    DOMResult result = new DOMResult();
+	    transformer.transform(new DOMSource(source), result);
+	    return result.getNode().getFirstChild();
+	} catch (TransformerConfigurationException e) {
+	    logger.error("couldn't create transformer object: "+e.getMessageAndLocation());
+	    logger.error(e.getLocationAsString());  
+	    return null;
+	} catch (TransformerException e) {
+	    logger.error("couldn't transform the source: " + e.getMessage());
+	    return null;
+	}	
+	
+
+    }
+
+    public Node transform(File stylesheet, File source) {
+
+	try {
+	    Transformer transformer = this.t_factory.newTransformer(new StreamSource(stylesheet));
+	    
+	    DOMResult result = new DOMResult();
+	    transformer.transform(new StreamSource(source), result);
+	    return result.getNode().getFirstChild();
+	} catch (TransformerConfigurationException e) {
+	    logger.error("couldn't create transformer object: "+e.getMessageAndLocation());
+	    logger.error(e.getLocationAsString());  
+	    return null;
+	} catch (TransformerException e) {
+	    logger.error("couldn't transform the source: " + e.getMessage());
+	    return null;
+	}	
+    }
+}
+
+ 
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/XSLTUtil.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/XSLTUtil.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/gsdl3/util/XSLTUtil.java	(revision 13928)
@@ -0,0 +1,148 @@
+package org.greenstone.gsdl3.util;
+
+import java.util.Date;
+import java.util.Locale;
+import java.text.SimpleDateFormat;
+
+import org.apache.log4j.*;
+
+/** a class to contain various static methods that are used by the xslt
+ * stylesheets
+ */
+public class XSLTUtil {
+
+     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.XSLTUtil.class.getName());
+
+    /* some tests */
+    public static boolean equals(String s1, String s2) {
+	return s1.equals(s2);
+    }
+    public static boolean notEquals(String s1, String s2) {
+	return !s1.equals(s2);
+    }
+    public static boolean exists(String s1, String s2) {
+	return !s1.equals("");
+    }
+    public static boolean contains(String s1, String s2) {
+	return (s1.indexOf(s2) != -1);
+    }
+    public static boolean startsWith(String s1, String s2) {
+	return s1.startsWith(s2);
+    }
+    public static boolean endsWith(String s1, String s2) {
+	return s1.endsWith(s2);
+    }
+    public static boolean lessThan(String s1, String s2) {
+	return (s1.compareTo(s2) < 0);
+    }
+    public static boolean lessThanOrEquals(String s1, String s2) {
+	return (s1.compareTo(s2) <= 0);
+    }
+    public static boolean greaterThan(String s1, String s2) {
+	return (s1.compareTo(s2) > 0);
+    }
+    public static boolean greaterThanOrEquals(String s1, String s2) {
+	return (s1.compareTo(s2) >= 0);
+    }
+
+    /* some preprocessing functions */
+    public static String toLower(String orig) {
+	return orig.toLowerCase();
+    }
+    public static String toUpper(String orig) {
+	return orig.toUpperCase();
+    }
+
+    public static byte[] toUTF8(String orig) {
+	
+	try {
+	    byte[] utf8 = orig.getBytes("UTF-8");
+	    return utf8;
+	}
+	catch (Exception e){
+	    logger.error("unsupported encoding");
+	    return orig.getBytes();
+	}
+    }
+
+    public static String getNumberedItem(String list, int number) {
+	String [] items = list.split(",", -1);	
+	if (items.length > number) {
+	    return items[number];
+	}
+	return ""; // index out of bounds
+    }
+
+    
+    public static String tidyWhitespace(String original) {
+	
+	if (original==null || original.equals("")) {
+	    return original;
+	}
+	String new_s = original.replaceAll("\\s+", " ");
+	return new_s;
+    }
+
+
+    public static String getInterfaceText(String interface_name, String lang, String key) {
+	return getInterfaceText(interface_name, lang, key, null);
+    }
+    public static String getInterfaceText(String interface_name, String lang, String key, String args_str) {
+	String [] args = null;
+	if (args_str!=null && !args_str.equals("")) {
+	    args = args_str.split(";");
+	}
+	Dictionary dict = new Dictionary("interface_"+interface_name, lang);
+        String result = dict.get(key, args);
+
+	if (result == null && !interface_name.equals("default")) { // not found, try the default interface
+	    dict = new Dictionary("interface_default", lang);
+	    result = dict.get(key, args);
+	}
+	    
+        if (result == null) { // not found
+            return "_"+key+"_";
+        }
+        return result;
+    }
+
+    public static boolean isImage(String mimetype) {
+	if (mimetype.startsWith("image/")) {
+	    return true;
+	}
+	return false;
+    }
+
+    public static String formatDate(String date, String lang) {
+	
+	String in_pattern = "yyyyMMdd";
+	String out_pattern = "dd MMMM yyyy";
+	if (date.length()==6) {
+	    in_pattern = "yyyyMM";
+	}
+	
+	SimpleDateFormat formatter = new SimpleDateFormat(in_pattern, new Locale(lang));
+	try {
+	    Date d = formatter.parse(date);
+	    formatter.applyPattern(out_pattern);
+	    String new_date = formatter.format(d);
+	    return new_date;
+	} catch (Exception e) {
+	    return date;
+	}
+	
+    }
+
+    public static String formatLanguage(String display_lang, String lang) {
+
+	return new Locale(display_lang).getDisplayLanguage(new Locale(lang));
+    }
+
+    public static String cgiSafe(String original, String lang) {
+
+	original = original.replace('&', ' ');
+	original = original.replaceAll(" ", "%20");
+	return original;
+    }
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/server/BrowserLauncher.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/server/BrowserLauncher.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/server/BrowserLauncher.java	(revision 13928)
@@ -0,0 +1,131 @@
+package org.greenstone.server;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import org.greenstone.gsdl3.util.Misc;
+import org.apache.log4j.*;
+
+public class BrowserLauncher 
+    extends Thread {
+    
+    private String url = "about:blank" ;
+    static Logger logger = Logger.getLogger(org.greenstone.server.BrowserLauncher.class.getName());
+    private String[] default_browsers = new String[]{"firefox","mozilla"};
+    private String command = "";
+    private int state = -1; //0: launch success, 1: launch failed 
+    public final  static int LAUNCHSUCCESS = 0;
+    public final static int LAUNCHFAILED = 1;
+    private String browserPath = ""; 
+
+    public BrowserLauncher(String browserPath, String url) {
+	this.url = url;
+        this.browserPath = browserPath;
+        //use the default browser
+	if (this.browserPath.equals("")){
+	    setBrowserCommand();
+	}
+	else{
+	    this.command = this.browserPath + " " + this.url;
+	}
+    }
+
+    public BrowserLauncher(){
+
+    }
+
+    // we should try and use settings from the settings panel??
+    protected void setBrowserCommand() {
+	if(Misc.isWindows()) {
+	    // we use cmd and start
+	    if (Misc.isWindows9x()) {
+		this.command = StaticStrings.WIN_9X_OPEN_COMMAND;//"command.com /c start \""+url+"\"";
+	    } else {
+		this.command = StaticStrings.WIN_OPEN_COMMAND;//"cmd.exe /c start \"\" \""+url+"\"";
+	    }
+	} else if (Misc.isMac()) {
+	    this.command = StaticStrings.MAC_OPEN_COMMAND; // "open %1"
+	} else {
+	     // we try to look for a browser
+ 	    for (int i=0; i<default_browsers.length; i++) {
+ 		if (isAvailable(default_browsers[i])) {
+ 		    this.command = default_browsers[i] + " %1";
+ 		    break;
+ 		}
+ 	    }
+	}
+
+	this.command = this.command.replaceAll("%1",this.url);
+    }
+
+    protected boolean isAvailable(String program) {
+	try {
+             Runtime run = Runtime.getRuntime();
+             Process process = run.exec("which "+ program);
+             BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
+	     String line = null;
+	     while ((line = br.readLine()) != null){
+		 if (line.indexOf("no "+program) !=-1){
+		     return false;
+		 }
+	     }    	
+	     
+	    return true;
+	} catch (Exception e) {
+	    return false;
+	}
+    }
+
+    public  int getBrowserState(){
+	return state;
+    }
+    
+    public void run() {
+	// Call an external process using the args.
+	if(command.equals("")) {
+	    state = LAUNCHFAILED;
+            logger.error("launching command is empty");
+	    return;
+	}
+	
+        try {
+	    String prog_name = this.command.substring(0,this.command.indexOf(" "));
+	    String lower_name = prog_name.toLowerCase();
+	    if (lower_name.indexOf("mozilla") != -1 || lower_name.indexOf("firefox") != -1) { 
+		logger.info("found mozilla or firefox, trying remote it");
+                // mozilla and netscape, try using a remote command to get things in the same window
+		String new_command = prog_name +" -raise -remote openURL("+url+",new-tab)";
+		logger.info(new_command);
+		Runtime rt = Runtime.getRuntime();
+		Process process = rt.exec(new_command);
+               	state = LAUNCHSUCCESS;
+		int exitCode = process.waitFor();
+		logger.info("ExitCode:" + exitCode);              
+		if (exitCode != 0) { // if Netscape or mozilla was not open
+		    logger.info("couldn't do remote, trying original command");
+                    logger.info(this.command);
+		    process = rt.exec(this.command); // try the original command
+                    state = LAUNCHSUCCESS;
+		    //for some reseaons the following part is not executed somtimes.
+                    exitCode = process.waitFor();
+                    logger.info("ExitCode:" + exitCode);
+		}
+	    } else {
+		logger.info(this.command);
+                Runtime rt = Runtime.getRuntime();
+		Process process = rt.exec(this.command);
+                state = LAUNCHSUCCESS;
+              	//for some reseaons the following part is not executed sometimes.
+              	int exitCode = process.waitFor();
+		logger.info("ExitCode:" + exitCode);
+		
+	    }
+	}
+	catch (Exception e) {
+	    logger.error(e);
+            state = LAUNCHFAILED;
+	}
+	
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/server/RunAnt.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/server/RunAnt.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/server/RunAnt.java	(revision 13928)
@@ -0,0 +1,64 @@
+package org.greenstone.server;
+
+import java.io.IOException;
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import org.greenstone.server.StreamGobbler;
+
+import org.apache.log4j.*;
+
+public class RunAnt extends Thread {
+    private String antCmd = "";
+    static Logger logger = Logger.getLogger(org.greenstone.server.RunAnt.class.getName());
+    private int state = -1; //success: 0 error: 1    
+    public static int SUCCESS = 0;
+    public static int FAILED = 1; 
+
+    private String antSuccess = "BUILD SUCCESSFUL";
+    private String antFailed = "BUILD FAILED";
+    private String antFinished = "Total time";
+
+    public void run() {
+	 
+	 try {
+	     state = -1;
+	     Runtime run = Runtime.getRuntime();
+             Process process = run.exec(getAntCmd());
+	     BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
+	     String line = null;
+             while (!(line = br.readLine()).startsWith(antFinished)){
+                 
+		 if (line.equals(antSuccess)){
+		     state = 0;
+		 }
+     
+		 if (line.equals(antFailed)){
+		     state = 1; 
+                  }
+		 logger.info(line);
+	     }    
+	 } catch (Exception e) {
+	     logger.error(e);
+	     state = 1;
+	 } 
+    }
+  
+    public int getAntState(){
+	return state;     
+    }
+    
+    public void setAntCmd(String cmd) {
+	String osName = System.getProperty("os.name");
+      	if (osName.startsWith("Windows")) {
+	    this.antCmd = "ant.bat " + cmd;
+	} else {
+	    this.antCmd = "ant " + cmd;
+	}
+    }
+
+    public String getAntCmd() {
+	return this.antCmd;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/server/ScriptReadWrite.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/server/ScriptReadWrite.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/server/ScriptReadWrite.java	(revision 13928)
@@ -0,0 +1,102 @@
+package org.greenstone.server;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+
+public class ScriptReadWrite {
+
+    public ScriptReadWrite() {
+    }
+
+    public ArrayList readInFile(File file) {
+	try {
+	    ArrayList fileLines = new ArrayList();
+	    String oneLine = null;
+	    BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
+	    while ((oneLine = bufferedReader.readLine()) != null) {
+		fileLines.add(oneLine);
+	    }
+	    bufferedReader.close();
+	    return fileLines;
+	} catch (Exception e) {
+	    System.err.println("exception:" + e);
+	    return null;
+	}
+    }
+
+    public void writeOutFile(File file, ArrayList fileLines_in) {
+	try {
+	    PrintWriter printWriter = new PrintWriter(new BufferedWriter(new FileWriter(file)));
+	    for (int i = 0; i < fileLines_in.size(); i++) {
+		printWriter.println(fileLines_in.get(i));
+	    }
+	    printWriter.flush();
+	    printWriter.close();
+	} catch (Exception e) {
+	    System.err.println("exception:" + e);
+	}
+    }
+
+    public ArrayList queryReplace(ArrayList fileLines_ex, String param,
+				  String newValue) {
+
+	String oneLine = null;
+	String newLine = null;
+	String name = null;
+	// int oneLine_length = 0;
+	param = param.trim();
+	// int param_length = param.length();
+
+	for (int i = 0; i < fileLines_ex.size(); i++) {
+	    oneLine = ((String) fileLines_ex.get(i)).trim();
+	    // oneLine_length = oneLine.length();
+	    StringTokenizer st = new StringTokenizer(oneLine, "=");
+	    if (st.hasMoreTokens()) {
+		name = st.nextToken();
+		if (param.equals(name)) {
+		    newLine = param + "=" + newValue;
+		    fileLines_ex.set(i, newLine);
+		    break;
+		}
+	    }
+	}
+	return fileLines_ex;
+    }
+
+    public String existValue(ArrayList fileLines, String querytext) {
+	String retValue = null;
+	String oneline = null;
+	String name = null;
+	// String value=null;
+	// int oneline_length = 0;
+	querytext = querytext.trim();
+	// int querytext_length = querytext.length();
+	for (int i = 0; i < fileLines.size(); i++) {
+	    oneline = ((String) fileLines.get(i)).trim();
+	    // oneline_length = oneline.length();
+	    StringTokenizer st = new StringTokenizer(oneline, "=");
+	    if (st.hasMoreTokens()) {
+		name = st.nextToken();
+		if (querytext.equals(name)) {
+		    if (st.hasMoreTokens()) {
+			retValue = st.nextToken();
+			retValue = retValue.trim();
+			if (retValue.equals("")) {
+			    retValue = null;
+			}
+		    } else {
+			retValue = null;
+		    }
+		    break;
+		}
+	    }
+	}
+	return retValue;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/server/Server.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/server/Server.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/server/Server.java	(revision 13928)
@@ -0,0 +1,229 @@
+
+package org.greenstone.server;
+
+import java.awt.Dimension;
+import java.awt.Toolkit;
+import java.io.File;
+import java.io.InputStream;
+import java.util.Properties;
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import org.apache.log4j.*;
+
+import org.greenstone.gsdl3.util.Dictionary;
+import org.greenstone.gsdl3.util.GlobalProperties;
+
+public class Server {
+     /** Ant command for managing Tomcat */
+    static final private String START_CMD = "start";
+    static final private String RESTART_CMD = "restart";
+    static final private String CONFIGURE_CMD = "configure";
+    static final private String STOP_CMD = "stop";
+
+    public static final int SERVER_STARTED = 0;
+    public static final int SERVER_START_FAILED = 1;
+    public static final int BROWSER_LAUNCHED = 2;
+    public static final int BROWSER_LAUNCH_FAILED = 3; 
+    
+    private int server_state = -1;    
+
+    private boolean configure_required = true;
+
+    public static File build_properties_file;
+    public static Properties build_properties;
+    public static Dictionary dictionary;
+     
+    private ServerControl server_control;    
+
+    static Logger logger = Logger.getLogger(org.greenstone.server.Server.class.getName());
+    
+    public Server(String gsdl3_src_home)
+    {
+	
+	String build_properties_path=gsdl3_src_home+File.separatorChar+"build.properties";
+	this.build_properties_file = new File(build_properties_path);
+	if (!this.build_properties_file.exists()) {
+	    logger.fatal("Can't find build.properties file "+build_properties_path);
+	    System.exit(1);
+	}
+	
+	build_properties = new Properties();
+	reloadBuildProperties();
+	
+	// make it dynamic language
+	this.dictionary = new Dictionary("server", "en", this.getClass().getClassLoader());
+	
+	server_control = new ServerControl(this);
+	
+	String auto_start = build_properties.getProperty(StaticStrings.AUTOSTART_PROPERTY);
+	if (auto_start != null && auto_start.equals("true")) {
+	    restart();
+	}
+	else{
+	    start();
+	}  
+         
+   }
+
+    public int getServerState(){
+	return server_state;
+    }
+
+    private int runAnt(String cmd){
+	RunAnt runAnt = new RunAnt();
+	runAnt.setAntCmd(cmd);
+	runAnt.run();
+   	return runAnt.getAntState();
+    }
+
+
+    public void reconfigRequired(){
+	configure_required = true;
+    }
+
+    public void start() {
+        int state = -1;
+        server_state = -1;
+	server_control.updateControl();
+	stop();
+	
+  	// reconfigure if necessary
+        if (configure_required){
+	    server_control.displayMessage(dictionary.get("ServerControl.Configuring"));
+	    state = runAnt(CONFIGURE_CMD);
+	    
+	   if (state != RunAnt.SUCCESS){
+	       recordError(CONFIGURE_CMD);
+	   }
+	   GlobalProperties.reload(); // properties file may have changed, so reload it
+	   configure_required = false;
+	}
+	else{
+	    recordSuccess(CONFIGURE_CMD); 
+	}
+	
+	server_control.displayMessage(dictionary.get("ServerControl.Starting"));
+        state = runAnt(START_CMD);
+
+	if (state != RunAnt.SUCCESS){
+	    recordError(START_CMD);
+            server_state = SERVER_START_FAILED;  
+            
+	}	            
+	else{
+	    recordSuccess(START_CMD); 
+            server_state = SERVER_STARTED; 
+       	} 
+
+       	server_control.updateControl();
+    }
+    
+    private void recordError(String message){
+        message = dictionary.get("ServerControl.Error",new String[]{message,GlobalProperties.getGSDL3Home()});
+	server_control.displayMessage(message);
+	logger.error(dictionary.get("ServerControl.Failed",new String[]{message}));
+    }
+
+
+    private void recordError(String message, Exception e){
+        message = dictionary.get("ServerControl.Error",new String[]{message,GlobalProperties.getGSDL3Home()});
+	server_control.displayMessage(message);
+	logger.error(dictionary.get("ServerControl.Failed",new String[]{message}),e);
+    }
+
+    private void recordSuccess(String message){
+        message = dictionary.get("ServerControl.Success",new String[]{message});
+	server_control.displayMessage(message);
+	logger.info(message);
+    }
+
+   
+    public void launchBrowser() {
+        server_state = -1;
+        server_control.updateControl();   
+        String message = dictionary.get("ServerControl.LaunchingBrowser");
+    	server_control.displayMessage(message); 
+	String url = GlobalProperties.getGSDL3WebAddress()+ build_properties.getProperty(StaticStrings.DEFAULT_SERVLET_PROPERTY);
+	BrowserLauncher launcher = new BrowserLauncher(build_properties.getProperty(StaticStrings.BROWSER_PATH),url);
+        logger.info(message);
+
+	launcher.start();
+     
+        //wait for a while
+        while(launcher.getBrowserState() == -1){
+            try{
+		Thread.sleep(3000);
+	    }
+	    catch(Exception e){
+		logger.error(e);
+	    }
+         } 
+
+	if (launcher.getBrowserState() != BrowserLauncher.LAUNCHSUCCESS ){
+	    recordError(dictionary.get("ServerControl.LaunchBrowser")); 
+	    server_state = BROWSER_LAUNCH_FAILED; 
+	}
+	else{
+	    recordSuccess(dictionary.get("ServerControl.LaunchBrowser")); 
+	    server_state = BROWSER_LAUNCHED;
+	}    
+        
+	server_control.updateControl();        
+    }
+    
+    public void restart(){
+	start();       
+        if (server_state == SERVER_STARTED){
+	    launchBrowser();
+	}  
+    }
+
+    public void stop() {
+         server_control.displayMessage(dictionary.get("ServerControl.Stopping"));
+	 int state = runAnt(STOP_CMD);
+	
+        if (state != RunAnt.SUCCESS){
+	    recordError(STOP_CMD);
+	}
+	else{
+	    recordSuccess(STOP_CMD);
+	}
+
+    }
+    
+    public  void reloadBuildProperties() {
+	try {
+	    InputStream in = this.getClass().getClassLoader().getResourceAsStream("build.properties");
+	    
+	    if (in != null) {
+		logger.info("loading build properties");
+		build_properties.load(in);
+		in.close();
+	    } else {
+		logger.error("couldn't load build properties!");
+	    }
+	} catch (Exception e) {
+	    logger.error("Exception trying to reload build.properties: "+e);
+	}
+	
+    }
+
+  
+
+    public static void main (String[] args){
+    	if (args.length != 1) {
+	    System.err.println("Usage: java org.greenstone.server.ServerMain <gsdl3 src home> ");
+	    System.exit(1);
+	}
+	
+	File gsdl3_src_dir = new File(args[0]);
+	if (!gsdl3_src_dir.isDirectory()) {
+	    System.err.println("src directory does not exist!");
+	    System.exit(1);
+	}
+	
+	new Server(args[0]);
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/server/ServerControl.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/server/ServerControl.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/server/ServerControl.java	(revision 13928)
@@ -0,0 +1,241 @@
+package org.greenstone.server;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.File;
+import java.util.ArrayList;
+import javax.swing.*;
+import javax.swing.border.*;
+
+import org.greenstone.gsdl3.util.GlobalProperties;
+
+import org.apache.log4j.*;
+/**
+ * This class is to start or restart the library server
+ * 
+ */
+public class ServerControl extends JFrame {
+
+    static Logger logger = Logger.getLogger(org.greenstone.server.ServerControl.class.getName());
+ 
+    /** The dimension of the frame */
+    static final private Dimension FRAME_SIZE = new Dimension(350, 250);
+
+    Color bg_color = Color.white;    
+    
+    /** some components we need to refer to later */
+    private JLabel info_label;
+    private JButton enter_button;
+    private JMenu fMenu;
+    private Server server;
+    private JFrame thisframe;
+    
+    public ServerControl(Server server) {
+	super(Server.dictionary.get("ServerControl.Frame_Title"));
+ 
+	this.server = server;
+        thisframe = this;
+
+	setSize(FRAME_SIZE);
+	setDefaultCloseOperation(EXIT_ON_CLOSE);
+	Dimension screen_size = Toolkit.getDefaultToolkit().getScreenSize();
+	setLocation((screen_size.width - FRAME_SIZE.width) / 2,
+		    (screen_size.height - FRAME_SIZE.height) / 2);
+	setBackground(Color.white);
+        addWindowListener(new MyAdapter()); 
+   
+        JPanel title_panel = new JPanel();
+	title_panel.setLayout(new BorderLayout());
+
+        JLabel title_label = new JLabel();
+        String title = Server.dictionary.get("ServerControl.Title");           
+        title_label.setText(stringToHTML(title)); 
+        title_label.setOpaque(false);	
+	title_label.setHorizontalAlignment(SwingConstants.CENTER);
+        title_label.setFont(new Font("SansSerif",Font.PLAIN,18));
+       
+
+        JLabel version_label = new JLabel();
+        String version = Server.dictionary.get("ServerControl.Version", new String [] {GlobalProperties.getProperty(StaticStrings.GSDL3_VERSION_PROPERTY)}).toLowerCase();
+         
+        version_label.setText(stringToHTML(version)); 
+        version_label.setOpaque(false);	
+	version_label.setHorizontalAlignment(SwingConstants.CENTER);
+        version_label.setFont(new Font("SansSerif",Font.PLAIN,14));
+        
+        title_panel.add(title_label,BorderLayout.CENTER);
+        title_panel.add(version_label,BorderLayout.SOUTH);
+	title_panel.setBackground(bg_color);	
+	title_panel.setBorder(BorderFactory.createEmptyBorder(5,10,5,10));
+
+   	info_label = new JLabel();
+        info_label.setOpaque(false);
+        info_label.setHorizontalAlignment(SwingConstants.LEFT);
+        info_label.setVerticalAlignment(SwingConstants.CENTER);
+        info_label.setFont(new Font("SansSerif",Font.PLAIN,14));
+	info_label.setBorder(BorderFactory.createEmptyBorder(5,10,5,10));	        
+		
+        JPanel button_panel = new JPanel(new FlowLayout(FlowLayout.CENTER));
+	enter_button = new JButton();
+	enter_button.setEnabled(false);
+	enter_button.addActionListener(new EnterButtonListener());
+        enter_button.setText(Server.dictionary.get("ServerControl.EnterLibrary"));
+ 	button_panel.add(enter_button);
+	button_panel.setBackground(bg_color);	
+	button_panel.setBorder(BorderFactory.createEmptyBorder(5,10,5,10));
+
+	getContentPane().setLayout(new BorderLayout());
+	getContentPane().add(title_panel,BorderLayout.NORTH);
+	getContentPane().add(info_label,BorderLayout.CENTER);
+	getContentPane().add(button_panel,BorderLayout.SOUTH);
+	getContentPane().setBackground(bg_color);
+    	setJMenuBar(createMenu());
+	setVisible(true);
+    }
+
+    protected JMenuBar createMenu() {
+	JMenuBar menuBar = new JMenuBar();
+         fMenu = new JMenu(Server.dictionary.get("ServerControl.Menu.File"));
+	JMenuItem iConf = new JMenuItem(Server.dictionary.get("ServerControl.Menu.Settings"));
+	iConf.setBackground(Color.white);
+	iConf.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent ae) {
+		    ServerSettings serverSetting = new ServerSettings(server);
+		}
+	    });
+	
+	JMenuItem iExit = new JMenuItem(Server.dictionary.get("ServerControl.Menu.Exit"));
+	iExit.setBackground(Color.white);
+	iExit.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent ae) {
+		    Thread runInThread = new Thread(new Runnable(){
+			    public void run(){
+				server.stop();
+			    
+			    }
+			},"stop server");
+		    try{
+                        runInThread.start(); 
+		
+		    }
+		    catch(Exception e){
+			logger.error(e);
+		    }    
+		    thisframe.dispose();
+		}
+	    });
+	fMenu.add(iConf);
+	fMenu.add(iExit);
+	fMenu.setEnabled(false);
+	menuBar.add(fMenu);
+	menuBar.setBorder(new BevelBorder(BevelBorder.RAISED));
+	return menuBar;
+    }
+
+    public void updateControl(){
+      	switch (server.getServerState()){
+	case Server.SERVER_STARTED:
+	    {
+		info_label.setText(stringToHTML(Server.dictionary.get("ServerControl.Help_EnterLibrary")));
+		enter_button.setEnabled(true);
+		fMenu.setEnabled(true);
+                break;
+	    }
+	case Server.SERVER_START_FAILED:
+	    {
+		enter_button.setText(stringToHTML(Server.dictionary.get("ServerControl.StartServer")));
+		enter_button.setEnabled(true);
+		fMenu.setEnabled(true);
+		break;	
+	    }
+	case Server.BROWSER_LAUNCHED:
+	    {
+		info_label.setText(stringToHTML(Server.dictionary.get("ServerControl.Help_RestartLibrary")));
+		enter_button.setText(stringToHTML(Server.dictionary.get("ServerControl.RestartLibrary")));
+		thisframe.setState(Frame.ICONIFIED);
+		enter_button.setEnabled(true);
+                fMenu.setEnabled(true);
+		break;
+	    }
+	case Server.BROWSER_LAUNCH_FAILED:
+	    {
+		enter_button.setText(stringToHTML(Server.dictionary.get("ServerControl.EnterLibrary")));
+		enter_button.setEnabled(true);
+		fMenu.setEnabled(true);
+                 break;	
+	    }
+        default:{
+	    enter_button.setEnabled(false);
+	    fMenu.setEnabled(false);
+	}
+	}
+    }
+           
+   
+    public void displayMessage(String message){
+	info_label.setText(stringToHTML("<br>"+message));           
+    }
+    
+    private class MyAdapter extends WindowAdapter{   
+	public void windowClosing(WindowEvent env){
+            Thread runInThread = new Thread(new Runnable(){
+			    public void run(){
+				server.stop();
+				
+			    }
+		},"stop server");
+	    try{
+		runInThread.start(); 
+	    }
+	    catch(Exception e){
+		logger.error(e);
+	    }  
+	    thisframe.dispose();
+	}
+    } 
+
+    private String stringToHTML(String s){
+	return "<html><body>"+s+"</body></html>";	
+    }
+    
+    private class EnterButtonListener
+	implements ActionListener {
+	
+	public void actionPerformed(ActionEvent ev) {
+	    switch (server.getServerState()){
+	    case Server.SERVER_STARTED: case Server.BROWSER_LAUNCH_FAILED:
+		{
+		 Thread runInThread = new Thread(new Runnable(){
+			    public void run(){
+			    server.launchBrowser();
+			    }
+			},"launch browser");
+		    
+		    runInThread.start(); 
+                   break;     
+		}
+	    case Server.SERVER_START_FAILED:
+		{
+		    Thread runInThread = new Thread(new Runnable(){
+			    public void run(){
+				server.start();
+			    }
+			},"start server");
+		    runInThread.start();
+		    break;
+		}  	
+	    case Server.BROWSER_LAUNCHED:
+		{
+		    Thread runInThread = new Thread(new Runnable(){
+			    public void run(){
+				server.restart();
+				  
+			    }
+			},"restart server");
+		    runInThread.start();
+		}  
+	    }   
+	  
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/server/ServerSettings.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/server/ServerSettings.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/server/ServerSettings.java	(revision 13928)
@@ -0,0 +1,324 @@
+package org.greenstone.server;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import javax.swing.*;
+
+import org.w3c.dom.*;
+
+import org.greenstone.gsdl3.util.GSXML;
+import org.greenstone.gsdl3.util.GlobalProperties;
+import org.greenstone.gsdl3.util.XMLConverter;
+
+import org.apache.log4j.*;
+
+public class ServerSettings extends JDialog
+
+{
+
+    static Logger logger = Logger.getLogger(org.greenstone.server.ServerControl.class.getName());
+    static final int DEFPORT = 8080;
+    JCheckBox autoEnter;
+    JComboBox servlet_combobox;
+    private JSpinner portNumber_spinner = null;
+    private JTextField program_path_field = null;
+    private JButton browse_button = null; 
+    private JRadioButton default_browser_button = null ;
+    private JRadioButton other_browser_button = null;
+    private Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
+
+    static final private Dimension SIZE = new Dimension(300, 350);
+    static final Color bg_color = Color.white; 
+    private int portNum = DEFPORT;
+    private boolean autoStart = false;
+    private String servletDefault = null;
+    private String browserPath = "";
+    private boolean useDefaultBrowser = true;
+
+    private HashMap url_mappings = null;
+    private JDialog self;
+    private Server server;
+     
+    public ServerSettings(Server server) {
+	super((Frame)null, "", true);
+	this.self = this;
+        this.server = server;
+
+        try{
+	    this.portNum = Integer.parseInt(server.build_properties.getProperty(StaticStrings.TOMCAT_PORT_PROPERTY));
+	}
+        catch(Exception e){
+	    logger.error(e);
+	} 
+
+        this.browserPath = server.build_properties.getProperty(StaticStrings.BROWSER_PATH);
+        
+        if (this.browserPath == null || this.browserPath.equals("")){
+	    useDefaultBrowser = true;
+            this.browserPath = "";
+	}
+	else{
+	    useDefaultBrowser = false;
+	}
+
+	String auto_start_str = server.build_properties.getProperty(StaticStrings.AUTOSTART_PROPERTY);
+	if ((auto_start_str.trim()).equals("true")) {
+	    this.autoStart = true;
+	} else {
+	    this.autoStart = false;
+	}
+
+	this.servletDefault = server.build_properties.getProperty(StaticStrings.DEFAULT_SERVLET_PROPERTY).replaceAll("/","");
+
+	setSize(SIZE);
+	setTitle(server.dictionary.get("ServerSettings.Title"));
+
+	setLocation((screen.width - SIZE.width) / 2,
+		    (screen.height - SIZE.height) / 2);
+	setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
+
+	JLabel port_label = new JLabel(Server.dictionary.get("ServerSettings.Tomcat_Port"));
+
+	portNumber_spinner = new JSpinner(new SpinnerNumberModel(portNum,1,65535,1));
+	portNumber_spinner.setEditor(new JSpinner.NumberEditor(portNumber_spinner, "#####")); 
+
+	autoEnter = new JCheckBox(server.dictionary.get("ServerSettings.Auto_Start"));
+	
+	if (autoStart) {
+	    autoEnter.setSelected(true);
+	} else {
+	    autoEnter.setSelected(false);
+	}
+	autoEnter.setBackground(bg_color);
+
+	JLabel servlet_label = new JLabel(server.dictionary.get("ServerSettings.Servlet"));
+
+	servlet_combobox = new JComboBox();
+	servlet_combobox.setMaximumRowCount(5);
+	servlet_combobox.setBackground(bg_color);
+
+	File web_xml = new File(GlobalProperties.getProperty(StaticStrings.GSDL3_HOME_PROPERTY) + File.separator + "WEB-INF" + File.separator + "web.xml");
+	XMLConverter converter = new XMLConverter();
+	Document web_config = converter.getDOM(web_xml);
+	if (web_config == null) {
+	    logger.error("web.xml is null! "+web_xml.getAbsolutePath());
+	    return;
+	}
+
+	NodeList servlet_mappings = web_config.getElementsByTagName("servlet-mapping");
+	// make a little map class
+	url_mappings = new HashMap();
+	for (int i = 0; i < servlet_mappings.getLength(); i++) {
+	    Element map = (Element) servlet_mappings.item(i);
+	    Element servlet_name_elem = (Element) GSXML.getChildByTagName(map, "servlet-name");
+	    String name = GSXML.getNodeText(servlet_name_elem);
+	    Element url_pattern_elem = (Element) GSXML.getChildByTagName(map, "url-pattern");
+	    String pattern = GSXML.getNodeText(url_pattern_elem);
+	    // Ignore the Axis servlets
+	    if (!(name.equals("AxisServlet"))) {
+		servlet_combobox.addItem(name.trim());
+		url_mappings.put(name, pattern);
+	    }
+
+	    if (name.equals(servletDefault)) {
+		servlet_combobox.setSelectedItem(name);
+	    }
+	}
+
+	JButton save_button = new JButton(Server.dictionary.get("ServerSettings.OK"));
+	save_button.addActionListener(new SaveActionListener());
+
+	JButton exit_button = new JButton(Server.dictionary.get("ServerSettings.Cancel"));
+	exit_button.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent ev) {
+		    self.dispose();
+		}
+	    });
+
+        JPanel  port_panel = new JPanel();    
+        port_panel.setLayout(new FlowLayout(FlowLayout.LEFT));
+	port_panel.add(port_label);
+	port_panel.add(portNumber_spinner);
+	port_panel.setBackground(bg_color);
+
+        JPanel comb_panel = new JPanel();
+	comb_panel.setLayout(new FlowLayout(FlowLayout.LEFT));
+	comb_panel.add(servlet_label);
+	comb_panel.add(servlet_combobox);
+	comb_panel.setBackground(bg_color);
+
+        
+	JPanel  check_panel = new JPanel(); 
+       	check_panel.setLayout(new FlowLayout(FlowLayout.LEFT));
+        check_panel.add(autoEnter);
+        check_panel.setBackground(bg_color);
+
+	JPanel mid_panel = new JPanel();
+        mid_panel.setLayout(new GridLayout(3,1));
+	mid_panel.add(port_panel);
+	mid_panel.add(check_panel);
+	mid_panel.add(comb_panel);
+	mid_panel.setBackground(bg_color);
+	mid_panel.setBorder(BorderFactory.createEmptyBorder(5,10,5,10));
+
+
+	JPanel browser_panel = new JPanel();
+        browser_panel.setLayout(new GridLayout(4,1));
+        default_browser_button = new JRadioButton(Server.dictionary.get("ServerSettings.DefaultBrowser"));
+        other_browser_button = new JRadioButton(Server.dictionary.get("ServerSettings.OtherBrowser"));
+        other_browser_button.addActionListener(new BrowserSelectionListener());
+        default_browser_button.addActionListener(new BrowserSelectionListener());
+
+	ButtonGroup bg = new ButtonGroup();
+        bg.add(default_browser_button);
+        bg.add(other_browser_button);
+        default_browser_button.setBorder(BorderFactory.createEmptyBorder(5,10,5,0));
+        default_browser_button.setBackground(bg_color);     
+        other_browser_button.setBorder(BorderFactory.createEmptyBorder(5,10,5,0)); 
+        other_browser_button.setBackground(bg_color);
+        JPanel browse_program_panel = new JPanel();     
+        browse_program_panel.setLayout(new BorderLayout());
+        program_path_field = new JTextField(this.browserPath);
+        browse_button = new JButton(Server.dictionary.get("ServerSettings.Browse"));
+	browse_program_panel.add(program_path_field,BorderLayout.CENTER);
+        browse_program_panel.add(browse_button,BorderLayout.EAST);
+        browse_program_panel.setBorder(BorderFactory.createEmptyBorder(5,10,5,0));
+	browse_program_panel.setBackground(bg_color);
+        browser_panel.add(new JLabel(Server.dictionary.get("ServerSettings.ChooseBrowser")));
+        browser_panel.add(default_browser_button);
+	browser_panel.add(other_browser_button);
+        browser_panel.add(browse_program_panel);
+	browser_panel.setBorder(BorderFactory.createEmptyBorder(5,10,5,10));
+        browser_panel.setBackground(bg_color);
+	if (useDefaultBrowser){
+	    default_browser_button.setSelected(true);
+	    program_path_field.setEnabled(false);
+	    browse_button.setEnabled(false); 
+	}
+	else{
+	    other_browser_button.setSelected(true);
+	}
+        browse_button.addActionListener(new BrowseActionListener());       
+        
+        JPanel down_panel = new JPanel();
+	down_panel.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
+	down_panel.add(save_button);
+	down_panel.add(exit_button);
+	down_panel.setBackground(bg_color);
+	down_panel.setBorder(BorderFactory.createEmptyBorder(5,10,5,10));
+
+        getContentPane().add(mid_panel, BorderLayout.NORTH);
+        getContentPane().add(browser_panel, BorderLayout.CENTER);
+	getContentPane().add(down_panel, BorderLayout.SOUTH);
+	getContentPane().setBackground(bg_color);
+	setVisible(true);
+    }
+
+    private class BrowseActionListener 
+ 	implements ActionListener {
+	
+	public void actionPerformed(ActionEvent ev) {
+	    JFileChooser chooser = new JFileChooser();
+           int returnVal = chooser.showOpenDialog(self);        
+	   
+	    if(returnVal == JFileChooser.APPROVE_OPTION) {
+                File program_path = chooser.getSelectedFile();
+		program_path_field.setText(program_path.getPath());
+	    } 
+	}
+
+     }
+
+    private class BrowserSelectionListener 
+ 	implements ActionListener {
+	
+	public void actionPerformed(ActionEvent ev) {
+	    if (default_browser_button.isSelected()){
+		program_path_field.setEnabled(false);
+                browse_button.setEnabled(false);
+	    }
+            else{
+		program_path_field.setEnabled(true);
+                browse_button.setEnabled(true);
+	    }
+	}
+
+     }
+    
+
+    private class SaveActionListener
+	implements ActionListener {
+	
+	public void actionPerformed(ActionEvent ev) {
+	    // save everything to build_properties if things have changed
+	     boolean has_changed = false;
+             boolean require_restart = false;
+	    if (portNum != ((Integer)portNumber_spinner.getValue()).intValue()) {
+		has_changed = true;
+                require_restart = true; 
+                server.reconfigRequired();
+                portNum = ((Integer)portNumber_spinner.getValue()).intValue();
+             	logger.info("port changed, new port is "+portNumber_spinner.getValue());
+	    }
+	    if (autoStart != autoEnter.isSelected()) {
+            	has_changed = true;
+	    }
+	    if (!servletDefault.equals(servlet_combobox.getSelectedItem())) {
+         	has_changed = true;
+                require_restart = true; 
+	    }
+            //changed to use other browser
+            if (useDefaultBrowser && other_browser_button.isSelected()){
+		browserPath = program_path_field.getText();
+		has_changed = true;
+	    } 
+	    //the browser path has been changed 
+	    if ( !useDefaultBrowser && !browserPath.equals(program_path_field.getText())){
+		browserPath = program_path_field.getText();
+		 has_changed = true;
+	    }
+	    
+            //changed to use the default browser
+	    if ( default_browser_button.isSelected() && !useDefaultBrowser){
+		browserPath = "";
+		has_changed = true;
+	    }
+             
+
+	    if (has_changed) {
+		ArrayList oldFileLines = null;
+		ArrayList newFileLines = null;
+		
+		ScriptReadWrite scriptReadWrite = new ScriptReadWrite();
+		oldFileLines = scriptReadWrite.readInFile(Server.build_properties_file);
+		
+		newFileLines = scriptReadWrite.queryReplace(oldFileLines, StaticStrings.TOMCAT_PORT_PROPERTY, portNum+"");
+		
+		String newAutoEnter = (new Boolean(autoEnter.isSelected())).toString();
+		newFileLines = scriptReadWrite.queryReplace(newFileLines, StaticStrings.AUTOSTART_PROPERTY, newAutoEnter);
+		
+		String newServletDef = (String) servlet_combobox.getSelectedItem();
+		newFileLines = scriptReadWrite.queryReplace(newFileLines,StaticStrings.DEFAULT_SERVLET_PROPERTY, (String) url_mappings.get(newServletDef));
+
+		String osName = System.getProperty("os.name");
+                if (osName.startsWith("Windows")){
+		    browserPath = browserPath.replaceAll("\\\\","/");
+		}
+                 newFileLines = scriptReadWrite.queryReplace(newFileLines,StaticStrings.BROWSER_PATH, browserPath);
+
+		scriptReadWrite.writeOutFile(Server.build_properties_file,
+					     newFileLines);
+		server.reloadBuildProperties();
+		if (require_restart){
+		    JOptionPane.showMessageDialog(null,server.dictionary.get("ServerSetting.SettingChanged"),"Info", JOptionPane.INFORMATION_MESSAGE);
+		}
+	    } 
+
+	    self.dispose();
+	}
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/server/StaticStrings.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/server/StaticStrings.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/server/StaticStrings.java	(revision 13928)
@@ -0,0 +1,19 @@
+package org.greenstone.server;
+
+public class StaticStrings {
+
+    static final public String GSDL3_HOME_PROPERTY = "gsdl3.home";
+    static final public String GSDL3_VERSION_PROPERTY = "gsdl3.version";
+    static final public String AUTOSTART_PROPERTY = "server.auto.start";
+    static final public String DEFAULT_SERVLET_PROPERTY = "server.default.servlet";
+    static final public String TOMCAT_SERVER_PROPERTY = "tomcat.server";
+    static final public String TOMCAT_PORT_PROPERTY = "tomcat.port";
+    static final public String TOMCAT_CONTEXT_PROPERTY = "tomcat.context";
+    static final public String TOMCAT_INSTALL_PATH = "tomcat.installed.path";
+
+    static final public String WIN_9X_OPEN_COMMAND = "command.com /c start %1";
+    static final public String WIN_OPEN_COMMAND = "cmd.exe /c start \"\" %1";
+    static final public String MAC_OPEN_COMMAND = "open %1";
+
+    static final public String BROWSER_PATH = "browser.path";
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/server/StreamGobbler.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/server/StreamGobbler.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/server/StreamGobbler.java	(revision 13928)
@@ -0,0 +1,39 @@
+package org.greenstone.server;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import org.apache.log4j.*;
+
+class StreamGobbler{
+    static Logger logger = Logger.getLogger(org.greenstone.server.StreamGobbler.class.getName());
+    
+    public static void logError(InputStream in)
+      {
+	  try {
+	      BufferedReader br = new BufferedReader(new InputStreamReader(in));
+	      String line = null;
+              //using null as a guard doesn't work on windows 
+  	      while ((line = br.readLine()) != null){
+		  logger.error(line);
+	      }
+	  } catch (IOException ioe) {
+	      logger.error(ioe);
+	  }
+      }
+    
+    
+    public void logInfo(InputStream in){
+	try {
+	    BufferedReader br = new BufferedReader(new InputStreamReader(in));
+	    String line = null;
+	    while ((line = br.readLine()) != null){
+		  logger.info(line);
+	      }
+	  } catch (IOException ioe) {
+	      logger.error(ioe);
+	  }
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/testing/ClassFinder.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/testing/ClassFinder.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/testing/ClassFinder.java	(revision 13928)
@@ -0,0 +1,83 @@
+/** this file originally downloaded from 
+ *http://www.javaworld.com/javaworld/jw-12-2000/junit/jw-1221-junit.zip
+ *
+ */
+
+package org.greenstone.testing;
+
+import java.util.*;
+import java.io.*;
+/*
+ * This used to use JCF. However, JCF seems to have dissapeared from the web.
+ * import lti.java.jcf.*;
+ */
+
+
+/**
+ * This class is responsible for searching a directory for class files. It builds
+ * a list of fully qualified class names from the class files in the directory tree.
+ */
+public class ClassFinder {
+    final private Vector classNameList = new Vector ();
+    final private int startPackageName;
+
+    /**
+     * Construct the class finder and locate all the classes in the directory structured
+     * pointed to by <code>classPathRoot</code>. Only classes in the package <code>packageRoot</code>
+     * are considered.
+     */
+    public ClassFinder(final File classPathRoot, final String packageRoot) throws IOException {
+        startPackageName = classPathRoot.getAbsolutePath().length() + 1;
+        String directoryOffset = packageRoot.replace ('.', File.separatorChar);
+        findAndStoreTestClasses (new File (classPathRoot, directoryOffset));
+    }
+    
+    /**
+     * Given a file name, guess the fully qualified class name.
+     */
+    private String computeClassName (final File file) {
+        String absPath = file.getAbsolutePath();
+        String packageBase = absPath.substring (startPackageName, absPath.length () - 6);
+        String className;
+        className = packageBase.replace(File.separatorChar, '.');
+        return className;
+    }
+
+    /**
+     * This method does all the work. It runs down the directory structure looking
+     * for java classes.
+     */
+    private void findAndStoreTestClasses (final File currentDirectory) throws IOException {
+        String files[] = currentDirectory.list();
+        for(int i = 0;i < files.length;i++) {
+            File file = new File(currentDirectory, files[i]);
+            String fileBase = file.getName ();
+            int idx = fileBase.indexOf(".class");
+            final int CLASS_EXTENSION_LENGTH = 6;
+            
+            if(idx != -1 && (fileBase.length() - idx) == CLASS_EXTENSION_LENGTH) {
+/* 
+ * This used to use JCF. However, JCF seems to have dissapeared from the web so we fallback
+ * to a less elegant method. We compute the class name from the file name :-(
+ *               JcfClassInputStream inputStream = new JcfClassInputStream(new FileInputStream (file));
+ *               JcfClassFile classFile = new JcfClassFile (inputStream);
+ *               System.out.println ("Processing: " + classFile.getFullName ().replace ('/','.'));
+ *               classNameList.add (classFile.getFullName ().replace ('/','.'));
+ */
+                String className = computeClassName (file);
+                classNameList.add (className);
+            } else {
+                if(file.isDirectory()) {
+                    findAndStoreTestClasses (file);
+                }
+            }
+        }
+    }
+
+    /**
+     * Return the found classes.
+     */
+    public Iterator getClasses () {
+        return classNameList.iterator ();
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/testing/TestCaseLoader.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/testing/TestCaseLoader.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/java/org/greenstone/testing/TestCaseLoader.java	(revision 13928)
@@ -0,0 +1,83 @@
+package org.greenstone.testing;
+import java.util.*;
+import java.lang.reflect.*;
+import junit.framework.*;
+/**
+ * Responsible for loading classes representing valid test cases.
+ */
+public class TestCaseLoader {
+    final private Vector classList = new Vector ();
+    final private String requiredType;
+    
+    /** 
+     * Adds <code>testCaseClass</code> to the list of classdes
+     * if the class is a test case we wish to load. Calls
+     * <code>shouldLoadTestCase ()</code> to determine that.
+     */
+    private void addClassIfTestCase (final Class testCaseClass) {
+        if (shouldAddTestCase (testCaseClass)) {
+            classList.add (testCaseClass);
+        }
+    }
+
+    /**
+     * Determine if we should load this test case. 
+     */
+    private boolean shouldAddTestCase (final Class testCaseClass) {
+        boolean isOfTheCorrectType = false;
+        if (TestCase.class.isAssignableFrom(testCaseClass)) {
+            try {
+                Field testAllIgnoreThisField = testCaseClass.getDeclaredField("TEST_ALL_TEST_TYPE");
+                final int EXPECTED_MODIFIERS = Modifier.STATIC | Modifier.PUBLIC | Modifier.FINAL;
+                if (((testAllIgnoreThisField.getModifiers() & EXPECTED_MODIFIERS) != EXPECTED_MODIFIERS) ||
+                    (testAllIgnoreThisField.getType() != String.class)) {
+                    throw new IllegalArgumentException ("TEST_ALL_TEST_TYPE should be static public final String");
+                }
+                String testType = (String)testAllIgnoreThisField.get(testCaseClass);
+                isOfTheCorrectType = requiredType.equals (testType);
+            } catch (NoSuchFieldException e) {
+            } catch (IllegalAccessException e) {
+                throw new IllegalArgumentException ("The field " + testCaseClass.getName () + ".TEST_ALL_TEST_TYPE is not accessible.");
+            }
+        }
+        return isOfTheCorrectType;
+    }
+    
+       
+    
+    /**
+     * Load the classes that represent test cases we are interested. 
+     * @param classNamesIterator An iterator over a collection of fully qualified class names
+     */
+    public void loadTestCases (final Iterator classNamesIterator) {
+        while (classNamesIterator.hasNext ()) {
+            String className = (String)classNamesIterator.next ();
+	    System.out.println("trying class "+className);
+            try {
+                Class candidateClass = Class.forName (className);
+                addClassIfTestCase (candidateClass);
+            } catch (ClassNotFoundException e) {
+                System.err.println ("Cannot load class: " + className + " " + e.getMessage ());
+            } catch (NoClassDefFoundError e) {
+                System.err.println ("Cannot load class that " + className + " is dependant on");
+            }
+        }
+    }
+        
+    /**
+     * Construct this instance. Load all the test cases possible that derive
+     * from <code>baseClass</code> and cannot be ignored. 
+     * @param classNamesIterator An iterator over a collection of fully qualified class names
+     */
+    public TestCaseLoader(final String requiredType) {
+        if (requiredType == null) throw new IllegalArgumentException ("requiredType is null");
+        this.requiredType = requiredType;
+    }
+    
+    /**
+     * Obtain an iterator over the collection of test case classes loaded by <code>loadTestCases</code>
+     */
+    public Iterator getClasses () {
+        return classList.iterator ();
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/CHANGES
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/CHANGES	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/CHANGES	(revision 13928)
@@ -0,0 +1,26 @@
+Release 0006 1998-03-06
+ - Added FAQ.html
+
+Release 0005 1997-10-30
+ - Deserializing objects from databases is implemented properly
+ - Added the Closeable interface
+ - Fixed link to home page in documentation
+
+Release 0004 1997-10-24
+ - Fixed bug in autoconfig script
+
+Release 0003 1997-10-24
+ - Release-management and CVS restructurings
+
+Release 0002 1997-10-23
+ - Much more developer documentation in javadoc format
+ - Support for Serialization and QuotedVector packing
+ - Packing objects now have consistent names
+ - New distribution page, separate from mbp's home page
+ - Moved all the code into packages which use the standard Java naming
+   conventions: au.com.pharos.gdbm
+
+Release 0001 1997-10-03
+ - Functional JNI-based interface
+ - Scanty documentation
+ - GPL release disclaimer from jdg
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/FAQ.html
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/FAQ.html	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/FAQ.html	(revision 13928)
@@ -0,0 +1,173 @@
+<head><title>FAQ for JavaGDBM</title>
+</head>
+
+<h1>FAQ for JavaGDBM</h1>
+<p><pre>$Id$</pre>
+<p><a href="http://www.pharos.com.au/gdbm/"><b>Home page</b></a> |
+<a href="mailto:mbp@pharos.com.au"><b>mbp@pharos.com.au</b></a>
+
+<p><b>This is not an official publication of Pharos.  There is no
+warranty of any kind on this software or document.</b>
+
+<h3>Is this a JDBC driver?</h3>
+
+<p>(Alain Magloire)
+
+<p>No. JDBC seems mainly intended for interfaces to relational
+databases, and GDBM is not a relational database. 
+
+<p>However, JDBC does permit use of a subset to interface to
+non-relational databases.  Implementing this might be interesting: let
+me know if it's useful to you.
+
+<h3>Does JavaGDBM understand SQL?</h3>
+
+<p>(Alain Magloire)
+
+<p>No, JavaGDBM is intended to store on-disk hash tables.  They solve
+a different class of problem to that appropriate for SQL and
+relational databases.
+
+<h3>What type of database should I use?</h3>
+
+<p>Broadly, options for data storage in Java include
+
+<ul>
+<li>A hash file through JavaGDBM.
+<li>A relational database through JDBC
+<li>An object-oriented database
+<li>Serialization to a file
+</ul>
+
+<p>Make sure you choose the right tools: there is no single `best' answer.
+
+<h3>Are you maintaining GDBM?</h3>
+
+<p>No.  I understand that GDBM is still maintained by the FSF.
+
+<h3>Does it work on NT?</h3>
+
+<p>It should, but I haven't tried it.  You'll need a C compiler to
+build the native library.  Let me know if you try.
+
+<h3>Why does the test harness report exceptions</h3>
+
+<p>The test harness may report messages such as
+
+<pre>
+caught: au.com.pharos.gdbm.GdbmException: File open error: No such file or
+directory? (gdbmjava.c:101)
+</pre>
+
+<p>These are expected exceptions: the test harness is making sure that
+exceptions are thrown when they should be.
+
+<h3>I was trying to compile the Java GDBM distribution and it says gdbm.h not found</h3>
+
+<p>(Sandeep Kumar)
+
+<ol>
+<li>Make sure you have the GDBM library installed on your system.  
+If the library is not installed, you should be able to find it at 
+<a href="http://www.gnu.org/">www.gnu.org</a>
+
+<li>Make sure your compiler is configured to find the libraries and
+include files.
+
+</ol>
+
+<h3><tt>GdbmFile.h</tt> is missing</h3>
+
+<p>(Paul Matthews)
+
+<p><tt>GdbmFile.h</tt> is build by <tt>javah</tt> when the library is
+built.
+
+<h3>What is the best source to learn Java?</h3>
+
+<p>(Celil Germeyan)
+
+<p>Personally, I recommend the excellent Java series of books from
+<a href="http://www.ora.com/info/java/bibliography.html/">O'Reilly and
+Associates</a> and the
+<a href="http://java.sun.com/docs/books/index.html">Javasoft/Addison
+Wesley</a> books.
+
+<h3>I get a `not ok 40' message running the test</h3>
+
+<p>(Steve Waldman)
+
+<p>If you find a bug, either have a look at the code yourself, or
+send e-mail to 
+<a href="mailto:mbp@pharos.com.au"><tt>mbp@pharos.com.au</tt></a>.  
+There's no warranty on JavaGDBM, but I will try to respond to your
+mail and problem.
+
+<h3>I get linker errors on Solaris</h3>
+
+<p>(Alex Soto)
+
+<pre>
+Hi,
+
+    I'm hoping to use your JavaGDBM api for my application, but I'm
+having some problems compiling the libgdbmjava.so.  Here is a partial
+listing of the errors:
+
+gcc -o libgdbmjava.so -shared gdbmjava.o -lgdbm
+Text relocation remains                       referenced
+    against symbol                  offset      in file
+free                                0x258
+/usr/local/lib/libgdbm.a(gdbmreorg.o)
+free                                0xd0
+/usr/local/lib/libgdbm.a(gdbmclose.o)
+free                                0xb8
+/usr/local/lib/libgdbm.a(gdbmclose.o)
+free                                0x218
+[snipped]
+
+I have used the libgdbm.a lib before, and don't believe there is a
+problem with it.  I'm compiling to Solaris 2.6, using JDK 1.1.4.
+</pre>
+
+<p>The solution turned out to be that the gdbm native library
+must be compiled with the <tt>-fpic</tt> flag to cause the compiler to
+generate position-independant code.  
+
+<h3>What happens if a reader tries to open the database while a writer is doing something?</h3>
+
+<p>(Rich Neill)
+
+<p>Access will be denied until the writer releases its lock.  
+
+<p>JavaGDBM uses a shared-read/exclusive-write protocol at the OS
+level.  However, multiple Java threads can access a file concurrently.
+
+<h3>What platforms does JavaGDBM run on?</H3>
+
+<p>It should run on any platform that supports JDK1.1 or higher, JNI
+(Java Native Interface), and GDBM.  JavaGDBM is known to run on 
+
+<ul>
+<li>Linux/i386
+<li>Solaris/SPARC and Solaris/i86
+<li>AIX 4
+</ul>
+
+<p>If you have any information on other platforms, please let me know.
+
+<h3>You don't anticipate going Pure Java soon, do you?</h3>
+
+<p>(Brian Thorstad)
+
+<p>It's on the `long-term' TODO list.  I'd like to do it, but don't have
+any date in mind.
+
+<h3>Acknowledgements</h3>
+
+<p>Everybody who's sent in questions or comments.
+
+<p>Redhat and Javasoft, and the authors of GDBM, Linux, gcc, autoconf,
+and other software used in building JavaGDBM.
+
+</html>
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/LICENSE
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/LICENSE	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/LICENSE	(revision 13928)
@@ -0,0 +1,344 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program 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 for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/Makefile.in
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/Makefile.in	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/Makefile.in	(revision 13928)
@@ -0,0 +1,25 @@
+# Main Makefile for Java GDBM
+# Katherine Don
+
+SUBDIRS = java jni
+MDEFINES = 
+
+all install clean:
+	for subdir in $(SUBDIRS); do \
+	echo making $@ in $$subdir; \
+	(cd $$subdir && $(MAKE) $(MDEFINES) $@) || exit 1; \
+	done
+
+javaonly:
+	cd java && $(MAKE) $(MDEFINES) all
+
+installjava:
+	cd java && $(MAKE) $(MDEFINES) install
+
+distclean: 
+	rm -f Makefile config.cache config.log config.status ;\
+	for subdir in $(SUBDIRS); do \
+	echo making $@ in $$subdir; \
+	(cd $$subdir && $(MAKE) $(MDEFINES) $@) || exit 1; \
+	done	
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/README.txt
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/README.txt	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/README.txt	(revision 13928)
@@ -0,0 +1,31 @@
+A Java Interface to GDBM
+
+*****
+This is a most of the Java gdbm download. I have left out some unnecessary bits for the greenstone version. The original home page for this is no longer available, but http://aurora.regenstrief.org/~schadow/dbm-java/ has links to the original tar file.
+I have also updated the Makefiles so that it works on Windows and MacOSX.
+[kjdon, 2005]
+*****
+
+Martin Pool <m.pool@pharos.com.au>  1998-03-12
+
+ This is a Java interface to the GDBM database library written by Philip A Nelson. Like GDBM itself, this interface is free software, and comes with no warranty of any kind.
+
+GDBM is a library of database functions for implementing a hash on disk. JavaGDBM is an API for the Java programmer, not an applet or database package for end users.
+
+In Java terms, a GdbmFile is very similar to a java.util.Dictionary object, except that objects are reliably written to and retrieved from disk. An adaptor class, GdbmDictionary, presents that interface to maintain compatibility with existing code.
+
+GDBM enforces file and object locking to allow databases to be safely shared between multiple threads or processes. A database may be open read-write by one process, or read-only by any number of processes. Within each process, any number of threads may share the database. Within the limits of the operating system and hardware, GDBM will ensure that changes are atomically committed to disk, making the database safe even if the program terminates abnormally.
+
+JavaGDBM stores key/data pairs in a GdbmFile object, which represents a single disk file. Each key must be unique, and is paired with a single data item. The keys are not ordered: if you want to retrieve the objects in sorted order you can build an external index. The basic operations on
+
+As for a Dictionary, the basic operations that may be performed on a GdbmFile are to fetch, test for existence, store and delete records.
+
+Since Java objects are dynamically typed and GDBM data are typeless, JavaGDBM uses Strategy objects to allow objects to be encoded and decoded in various ways. Classes derived from the abstract Packing class may pack ojbects for storage as byte arrays, Unicode or ASCII strings, as serialized Java objects, or in a user-defined fashion. The packing strategy is defined at runtime for both the key and value of the records.
+
+Some example code is available in the test harness GdbmTest.java.
+
+The current implementation of JavaGDBM uses native glue code to link to the GDBM library via JNI, the Java Native Interface. This means that you must have a C compiler, the GDBM library, and related tools to compile the native portions JavaGDBM also requires a JDK1.1-compatible Java compiler, libraries, and runtime.
+
+If the GDBM libraries didn't come with your system, then you can download the GDBM source and install it.
+
+GDBM is known to work on Linux, NetBSD, Solaris, and AIX. 
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/TODO
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/TODO	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/TODO	(revision 13928)
@@ -0,0 +1,21 @@
+TODO for JavaGDBM
+$Id$
+
+Short-term
+
+ - Fix reported bugs
+
+Medium-term
+
+ - Modify the Makefile and configuration code to make sure JavaGDBM
+   builds on more different systems.
+
+ - Add support for non-default block sizes and other options.
+
+ - Offer more developer documentation.
+
+Long-term
+
+ - Rewrite the native code in Java to make the system 100% Pure.
+ - Offer precompiled binaries(?)
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/configure
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/configure	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/configure	(revision 13928)
@@ -0,0 +1,5337 @@
+#! /bin/sh
+# From configure.in Revision: 1.3 .
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.59.
+#
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)$' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+  	  /^X\/\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\/\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+	 case $as_dir in
+	 /*)
+	   if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+	     $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+	     $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+	     CONFIG_SHELL=$as_dir/$as_base
+	     export CONFIG_SHELL
+	     exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+	   fi;;
+	 esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='	' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" 	$as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete.  It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="jni/gdbmjava.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+#  include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S CPP EGREP JAVA_HOME javagdbm_cv_path_javah javagdbm_cv_path_java GDBM_LIBPATH GDBM_INCLUDE PKG JNIINC JNISUFFIX JNIFLAGS LIBOBJS LTLIBOBJS'
+ac_subst_files=''
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+ac_prev=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_option in
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    eval "enable_$ac_feature=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_$ac_feature='$ac_optarg'" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_$ac_package='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/-/_/g'`
+    eval "with_$ac_package=no" ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+    eval "$ac_envvar='$ac_optarg'"
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+	      localstatedir libdir includedir oldincludedir infodir mandir
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then its parent.
+  ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$0" : 'X\(//\)[^/]' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r $srcdir/$ac_unique_file; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+   { (exit 1); exit 1; }; }
+  else
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+  fi
+fi
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+  { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+   { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+  cat <<_ACEOF
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+			  [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+			  [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR           user executables [EPREFIX/bin]
+  --sbindir=DIR          system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR       program executables [EPREFIX/libexec]
+  --datadir=DIR          read-only architecture-independent data [PREFIX/share]
+  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
+  --libdir=DIR           object code libraries [EPREFIX/lib]
+  --includedir=DIR       C header files [PREFIX/include]
+  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
+  --infodir=DIR          info documentation [PREFIX/info]
+  --mandir=DIR           man documentation [PREFIX/man]
+_ACEOF
+
+  cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+  cat <<\_ACEOF
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-gdbm=dir         Use local gdbm library and headers
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
+              headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  ac_popdir=`pwd`
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d $ac_dir || continue
+    ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+    cd $ac_dir
+    # Check for guested configure; otherwise get Cygnus style configure.
+    if test -f $ac_srcdir/configure.gnu; then
+      echo
+      $SHELL $ac_srcdir/configure.gnu  --help=recursive
+    elif test -f $ac_srcdir/configure; then
+      echo
+      $SHELL $ac_srcdir/configure  --help=recursive
+    elif test -f $ac_srcdir/configure.ac ||
+	   test -f $ac_srcdir/configure.in; then
+      echo
+      $ac_configure --help
+    else
+      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi
+    cd $ac_popdir
+  done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+  cat <<\_ACEOF
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.59.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo               = `(hostinfo) 2>/dev/null               || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    2)
+      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+      # Get rid of the leading space.
+      ac_sep=" "
+      ;;
+    esac
+  done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+{
+  (set) 2>&1 |
+    case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      sed -n \
+	"s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+      ;;
+    *)
+      sed -n \
+	"s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+}
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=$`echo $ac_var`
+      echo "$ac_var='"'"'$ac_val'"'"'"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=$`echo $ac_var`
+	echo "$ac_var='"'"'$ac_val'"'"'"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      sed "/^$/d" confdefs.h | sort
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      echo "$as_me: caught signal $ac_signal"
+    echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core &&
+  rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+     ' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . $cache_file;;
+      *)                      . ./$cache_file;;
+    esac
+  fi
+else
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+	       sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+  eval ac_new_val="\$ac_env_${ac_var}_value"
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	{ echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	{ echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
+echo "$as_me:   former value:  $ac_old_val" >&2;}
+	{ echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
+echo "$as_me:   current value: $ac_new_val" >&2;}
+	ac_cache_corrupted=:
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-gdbm or --without-gdbm was given.
+if test "${with_gdbm+set}" = set; then
+  withval="$with_gdbm"
+  gdbmdir=$withval
+fi;
+
+# TODO: allow the user to specify whether they want a debugging
+# library or not?
+
+# check for compilers and other tools
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$ac_ct_CC" && break
+done
+
+  CC=$ac_ct_CC
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+     "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+  (eval $ac_link_default) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Find the output, starting from the most likely.  This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+	;;
+    conftest.$ac_ext )
+	# This is the source file.
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+	ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	# FIXME: I believe we export ac_cv_exeext for Libtool,
+	# but it would be cool to find out if it's true.  Does anybody
+	# maintain Libtool? --akim.
+	export ac_cv_exeext
+	break;;
+    * )
+	break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  fi
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  export ac_cv_exeext
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std1 is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std1.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX			-qlanglvl=ansi
+# Ultrix and OSF/1	-std1
+# HP-UX 10.20 and later	-Ae
+# HP-UX older versions	-Aa -D_HPUX_SOURCE
+# SVR4			-Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+  x|xno)
+    echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+  *)
+    echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+    CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+# Some people use a C++ compiler to compile C.  Since we use `exit',
+# in C++ we need to declare it.  In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+  choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  for ac_declaration in \
+   '' \
+   'extern "C" void std::exit (int) throw (); using std::exit;' \
+   'extern "C" void std::exit (int); using std::exit;' \
+   'extern "C" void exit (int) throw ();' \
+   'extern "C" void exit (int);' \
+   'void exit (int);'
+do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+  echo '#ifdef __cplusplus' >>confdefs.h
+  echo $ac_declaration      >>confdefs.h
+  echo '#endif'             >>confdefs.h
+fi
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+  if test -f $ac_dir/install-sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f $ac_dir/install.sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f $ac_dir/shtool; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
+echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"
+ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+	if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+	  if test $ac_prog = install &&
+	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+	    break 3
+	  fi
+	fi
+      done
+    done
+    ;;
+esac
+done
+
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL=$ac_install_sh
+  fi
+fi
+echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo "$as_me:$LINENO: checking whether ln -s works" >&5
+echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+  echo "$as_me:$LINENO: result: no, using $LN_S" >&5
+echo "${ECHO_T}no, using $LN_S" >&6
+fi
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+    then ac_cv_prog_egrep='grep -E'
+    else ac_cv_prog_egrep='egrep'
+    fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      exit(2);
+  exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+		  inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+echo "$as_me:$LINENO: checking for void *" >&5
+echo $ECHO_N "checking for void *... $ECHO_C" >&6
+if test "${ac_cv_type_void_p+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if ((void * *) 0)
+  return 0;
+if (sizeof (void *))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_void_p=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_void_p=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_void_p" >&5
+echo "${ECHO_T}$ac_cv_type_void_p" >&6
+
+echo "$as_me:$LINENO: checking size of void *" >&5
+echo $ECHO_N "checking size of void *... $ECHO_C" >&6
+if test "${ac_cv_sizeof_void_p+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$ac_cv_type_void_p" = yes; then
+  # The cast to unsigned long works around a bug in the HP C Compiler
+  # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+  # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+  # This bug is HP SR number 8606223364.
+  if test "$cross_compiling" = yes; then
+  # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (void *))) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (void *))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr $ac_mid + 1`
+		    if test $ac_lo -le $ac_mid; then
+		      ac_lo= ac_hi=
+		      break
+		    fi
+		    ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (void *))) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (void *))) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_hi=`expr '(' $ac_mid ')' - 1`
+		       if test $ac_mid -le $ac_hi; then
+			 ac_lo= ac_hi=
+			 break
+		       fi
+		       ac_mid=`expr 2 '*' $ac_mid`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo= ac_hi=
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (void *))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_void_p=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (void *), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (void *), 77
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+else
+  if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+long longval () { return (long) (sizeof (void *)); }
+unsigned long ulongval () { return (long) (sizeof (void *)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    exit (1);
+  if (((long) (sizeof (void *))) < 0)
+    {
+      long i = longval ();
+      if (i != ((long) (sizeof (void *))))
+	exit (1);
+      fprintf (f, "%ld\n", i);
+    }
+  else
+    {
+      unsigned long i = ulongval ();
+      if (i != ((long) (sizeof (void *))))
+	exit (1);
+      fprintf (f, "%lu\n", i);
+    }
+  exit (ferror (f) || fclose (f) != 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sizeof_void_p=`cat conftest.val`
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (void *), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (void *), 77
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.val
+else
+  ac_cv_sizeof_void_p=0
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_void_p" >&5
+echo "${ECHO_T}$ac_cv_sizeof_void_p" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking for int" >&5
+echo $ECHO_N "checking for int... $ECHO_C" >&6
+if test "${ac_cv_type_int+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if ((int *) 0)
+  return 0;
+if (sizeof (int))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_int=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_int=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_int" >&5
+echo "${ECHO_T}$ac_cv_type_int" >&6
+
+echo "$as_me:$LINENO: checking size of int" >&5
+echo $ECHO_N "checking size of int... $ECHO_C" >&6
+if test "${ac_cv_sizeof_int+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$ac_cv_type_int" = yes; then
+  # The cast to unsigned long works around a bug in the HP C Compiler
+  # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+  # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+  # This bug is HP SR number 8606223364.
+  if test "$cross_compiling" = yes; then
+  # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (int))) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (int))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr $ac_mid + 1`
+		    if test $ac_lo -le $ac_mid; then
+		      ac_lo= ac_hi=
+		      break
+		    fi
+		    ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (int))) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (int))) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_hi=`expr '(' $ac_mid ')' - 1`
+		       if test $ac_mid -le $ac_hi; then
+			 ac_lo= ac_hi=
+			 break
+		       fi
+		       ac_mid=`expr 2 '*' $ac_mid`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo= ac_hi=
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (int))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_int=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (int), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (int), 77
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+else
+  if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+long longval () { return (long) (sizeof (int)); }
+unsigned long ulongval () { return (long) (sizeof (int)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    exit (1);
+  if (((long) (sizeof (int))) < 0)
+    {
+      long i = longval ();
+      if (i != ((long) (sizeof (int))))
+	exit (1);
+      fprintf (f, "%ld\n", i);
+    }
+  else
+    {
+      unsigned long i = ulongval ();
+      if (i != ((long) (sizeof (int))))
+	exit (1);
+      fprintf (f, "%lu\n", i);
+    }
+  exit (ferror (f) || fclose (f) != 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sizeof_int=`cat conftest.val`
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (int), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (int), 77
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.val
+else
+  ac_cv_sizeof_int=0
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_int" >&5
+echo "${ECHO_T}$ac_cv_sizeof_int" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_INT $ac_cv_sizeof_int
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking for long" >&5
+echo $ECHO_N "checking for long... $ECHO_C" >&6
+if test "${ac_cv_type_long+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if ((long *) 0)
+  return 0;
+if (sizeof (long))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_long=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_long=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_long" >&5
+echo "${ECHO_T}$ac_cv_type_long" >&6
+
+echo "$as_me:$LINENO: checking size of long" >&5
+echo $ECHO_N "checking size of long... $ECHO_C" >&6
+if test "${ac_cv_sizeof_long+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$ac_cv_type_long" = yes; then
+  # The cast to unsigned long works around a bug in the HP C Compiler
+  # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+  # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+  # This bug is HP SR number 8606223364.
+  if test "$cross_compiling" = yes; then
+  # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long))) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr $ac_mid + 1`
+		    if test $ac_lo -le $ac_mid; then
+		      ac_lo= ac_hi=
+		      break
+		    fi
+		    ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long))) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long))) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_hi=`expr '(' $ac_mid ')' - 1`
+		       if test $ac_mid -le $ac_hi; then
+			 ac_lo= ac_hi=
+			 break
+		       fi
+		       ac_mid=`expr 2 '*' $ac_mid`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo= ac_hi=
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_long=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (long), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long), 77
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+else
+  if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+long longval () { return (long) (sizeof (long)); }
+unsigned long ulongval () { return (long) (sizeof (long)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    exit (1);
+  if (((long) (sizeof (long))) < 0)
+    {
+      long i = longval ();
+      if (i != ((long) (sizeof (long))))
+	exit (1);
+      fprintf (f, "%ld\n", i);
+    }
+  else
+    {
+      unsigned long i = ulongval ();
+      if (i != ((long) (sizeof (long))))
+	exit (1);
+      fprintf (f, "%lu\n", i);
+    }
+  exit (ferror (f) || fclose (f) != 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sizeof_long=`cat conftest.val`
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (long), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long), 77
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.val
+else
+  ac_cv_sizeof_long=0
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_long" >&5
+echo "${ECHO_T}$ac_cv_sizeof_long" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG $ac_cv_sizeof_long
+_ACEOF
+
+
+
+######## check for the JDK and tools within the JDK
+######## look in the JAVA_HOME environment variable at configure-time
+echo "$as_me:$LINENO: checking for the JDK" >&5
+echo $ECHO_N "checking for the JDK... $ECHO_C" >&6
+if test "z$JAVA_HOME" != z &&
+   test -d $JAVA_HOME &&
+   test -d $JAVA_HOME/include
+then
+
+	echo "$as_me:$LINENO: result: found in $JAVA_HOME" >&5
+echo "${ECHO_T}found in $JAVA_HOME" >&6
+else
+	{ { echo "$as_me:$LINENO: error: not found in \$JAVA_HOME" >&5
+echo "$as_me: error: not found in \$JAVA_HOME" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+# TODO: Check for specific header files in the JDK, or
+# functions/definitions within those headers?
+
+# TODO: guess which include directory to use under the JDK
+
+# Extract the first word of "javah", so it can be a program name with args.
+set dummy javah; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_javagdbm_cv_path_javah+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $javagdbm_cv_path_javah in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_javagdbm_cv_path_javah="$javagdbm_cv_path_javah" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_javagdbm_cv_path_javah="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_path_javagdbm_cv_path_javah" && ac_cv_path_javagdbm_cv_path_javah="missing_javah"
+  ;;
+esac
+fi
+javagdbm_cv_path_javah=$ac_cv_path_javagdbm_cv_path_javah
+
+if test -n "$javagdbm_cv_path_javah"; then
+  echo "$as_me:$LINENO: result: $javagdbm_cv_path_javah" >&5
+echo "${ECHO_T}$javagdbm_cv_path_javah" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+if test "$javagdbm_cv_path_javah" = missing_javah; then
+	{ { echo "$as_me:$LINENO: error: javah not found." >&5
+echo "$as_me: error: javah not found." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+# Extract the first word of "java", so it can be a program name with args.
+set dummy java; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_javagdbm_cv_path_java+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $javagdbm_cv_path_java in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_javagdbm_cv_path_java="$javagdbm_cv_path_java" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_javagdbm_cv_path_java="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_path_javagdbm_cv_path_java" && ac_cv_path_javagdbm_cv_path_java="missing"
+  ;;
+esac
+fi
+javagdbm_cv_path_java=$ac_cv_path_javagdbm_cv_path_java
+
+if test -n "$javagdbm_cv_path_java"; then
+  echo "$as_me:$LINENO: result: $javagdbm_cv_path_java" >&5
+echo "${ECHO_T}$javagdbm_cv_path_java" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+if test "$javagdbm_cv_path_java" = missing; then
+	{ { echo "$as_me:$LINENO: error: java not found." >&5
+echo "$as_me: error: java not found." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+# check for gdbm library
+#AC_CHECK_LIB(gdbm, gdbm_open, [javagdbm_cv_lib_gdbm="-lgdbm"],
+#	[javagdbm_cv_lib_gdbm=no])
+#if test "$javagdbm_cv_lib_gdbm" = "no"; then
+#	AC_MSG_ERROR([no native gdbm library found.])
+#fi
+#LIBS="$javagdbm_cv_lib_gdbm"
+
+# gdbm stuff copied from gsdl [kjdon]
+
+
+echo "$as_me:$LINENO: checking that the GDBM library is available" >&5
+echo $ECHO_N "checking that the GDBM library is available... $ECHO_C" >&6
+if test ! -z "$gdbmdir" ; then
+  # look in given directory for header file
+  if test -r $gdbmdir/include/gdbm.h ; then
+    GDBM_INCLUDE="-I$gdbmdir/include" ;
+  elif test -r $gdbmdir/gdbm.h ; then
+    GDBM_INCLUDE="-I$gdbmdir" ;
+  fi
+
+  # look in given directory for library
+  if test -r $gdbmdir/libgdbm.a ; then
+    GDBM_LIBPATH="-L$gdbmdir" ;
+  elif test -r $gdbmdir/lib/libgdbm.a ; then
+    GDBM_LIBPATH="-L$gdbmdir/lib" ;
+  elif test -r $gdbmdir/.libs/libgdbm.a ; then
+    GDBM_LIBPATH="-L$gdbmdir/.libs" ;
+  fi
+
+  if test ! -z "$GDBM_LIBPATH" -a ! -z "$GDBM_INCLUDE" ; then
+    echo "$as_me:$LINENO: result: $gdbmdir" >&5
+echo "${ECHO_T}$gdbmdir" >&6 ;
+  else
+    echo "$as_me:$LINENO: result: can't find gdbm.h and libgdbm.a in $gdbmdir" >&5
+echo "${ECHO_T}can't find gdbm.h and libgdbm.a in $gdbmdir" >&6;
+    echo "$as_me:$LINENO: checking looking for GDBM library in default locations" >&5
+echo $ECHO_N "checking looking for GDBM library in default locations... $ECHO_C" >&6
+  fi
+fi
+
+# look in default path and in /usr/local
+if test -z "$GDBM_INCLUDE" ; then
+  # try in system directory
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <gdbm.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  success=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+success=no
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+  if test $success = "no"; then
+# last chance - look in /usr/local (eg FreeBSD)
+    GDBM_LIBPATH=-L/usr/local/lib
+    GDBM_INCLUDE=-I/usr/local/include
+    ac_save_CXXFLAGS="$CXXFLAGS"
+    ac_save_LIBS="$LIBS"
+      CXXFLAGS="$CXXFLAGS -I/usr/local/include"
+      LIBS="$LIBS -L/usr/local/lib -lgdbm"
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <gdbm.h>
+#include <stdio.h>
+
+int
+main ()
+{
+printf("%s",gdbm_version);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  success=/usr/local
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+success=no
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+      CXXFLAGS=$ac_save_CXXFLAGS
+      LIBS=$ac_save_LIBS
+  fi
+
+  echo "$as_me:$LINENO: result: $success" >&5
+echo "${ECHO_T}$success" >&6
+  if test $success = "no"; then
+  { { echo "$as_me:$LINENO: error: GDBM Library not available - cannot install" >&5
+echo "$as_me: error: GDBM Library not available - cannot install" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+fi
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBGDBM  1
+_ACEOF
+
+
+
+
+
+########## set compiler options
+# TODO: is there a more appropriate way to guess which switches to use
+# with which systems/compilers?
+CFLAGS="-Wall -O2 -fpic"
+PKG="au.com.pharos.gdbm"
+
+
+
+
+# we need to set an extended JNI path for Mac OS/Darwin, as jni.h is on
+# a non-standard Path
+# is there a better way to do this??
+echo "$as_me:$LINENO: checking for OS to set JNI options" >&5
+echo $ECHO_N "checking for OS to set JNI options... $ECHO_C" >&6
+# set defaults
+JNIINC=""
+JNISUFFIX="so"
+JNIFLAGS="-shared"
+
+if test "`(uname -s) 2> /dev/null`" = 'Darwin'; then
+  echo "$as_me:$LINENO: result: Darwin" >&5
+echo "${ECHO_T}Darwin" >&6
+  JNIINC="-I/System/Library/Frameworks/JavaVM.framework/Headers/ "
+  JNISUFFIX="jnilib"
+  JNIFLAGS="-dynamiclib -fno-common -single_module -framework JavaVM"
+fi
+if test "`(uname -s) 2> /dev/null`" = 'SunOS'; then
+  echo "$as_me:$LINENO: result: Solaris" >&5
+echo "${ECHO_T}Solaris" >&6
+  JNIINC="-I\$(JAVA_HOME)/include/solaris "
+fi
+if test "`(uname -s) 2> /dev/null`" = 'Linux'; then
+  echo "$as_me:$LINENO: result: Linux" >&5
+echo "${ECHO_T}Linux" >&6
+  JNIINC="-I\$(JAVA_HOME)/include/linux "
+fi
+
+
+
+
+
+# write the output
+                              ac_config_files="$ac_config_files Makefile jni/Makefile java/Makefile"
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+  (set) 2>&1 |
+    case `(ac_space=' '; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;;
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n \
+	"s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+} |
+  sed '
+     t clear
+     : clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
+  if test -w $cache_file; then
+    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+    cat confcache >$cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[	 ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[	 ]*$//;
+}'
+fi
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then we branch to the quote section.  Otherwise,
+# look for a macro that doesn't take arguments.
+cat >confdef2opt.sed <<\_ACEOF
+t clear
+: clear
+s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\),-D\1=\2,g
+t quote
+s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\),-D\1=\2,g
+t quote
+d
+: quote
+s,[	 `~#$^&*(){}\\|;'"<>?],\\&,g
+s,\[,\\&,g
+s,\],\\&,g
+s,\$,$$,g
+p
+_ACEOF
+# We use echo to avoid assuming a particular line-breaking character.
+# The extra dot is to prevent the shell from consuming trailing
+# line-breaks from the sub-command output.  A line-break within
+# single-quotes doesn't work because, if this script is created in a
+# platform that uses two characters for line-breaks (e.g., DOS), tr
+# would break.
+ac_LF_and_DOT=`echo; echo .`
+DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'`
+rm -f confdef2opt.sed
+
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_i=`echo "$ac_i" |
+	 sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+  # 2. Add them.
+  ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)$' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+  	  /^X\/\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\/\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+	 case $as_dir in
+	 /*)
+	   if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+	     $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+	     $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+	     CONFIG_SHELL=$as_dir/$as_base
+	     export CONFIG_SHELL
+	     exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+	   fi;;
+	 esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='	' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" 	$as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.  Logging --version etc. is OK.
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.59.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+  echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+  echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+  echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+  echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number, then exit
+  -q, --quiet      do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+  --file=FILE[:TEMPLATE]
+		   instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.59,
+  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+INSTALL="$INSTALL"
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value.  By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "x$1" : 'x\([^=]*\)='`
+    ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  -*)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  *) # This is not an option, so the user has probably given explicit
+     # arguments.
+     ac_option=$1
+     ac_need_defaults=false;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --vers* | -V )
+    echo "$ac_cs_version"; exit 0 ;;
+  --he | --h)
+    # Conflict between --help and --header
+    { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    echo "$ac_cs_usage"; exit 0 ;;
+  --debug | --d* | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+    ac_need_defaults=false;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1" ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+  echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+  exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+  case "$ac_config_target" in
+  # Handling of arguments.
+  "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+  "jni/Makefile" ) CONFIG_FILES="$CONFIG_FILES jni/Makefile" ;;
+  "java/Makefile" ) CONFIG_FILES="$CONFIG_FILES java/Makefile" ;;
+  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./confstat$$-$RANDOM
+  (umask 077 && mkdir $tmp)
+} ||
+{
+   echo "$me: cannot create a temporary directory in ." >&2
+   { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+  # Protect against being on the right side of a sed subst in config.status.
+  sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+   s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@CC@,$CC,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
+s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
+s,@INSTALL_DATA@,$INSTALL_DATA,;t t
+s,@LN_S@,$LN_S,;t t
+s,@CPP@,$CPP,;t t
+s,@EGREP@,$EGREP,;t t
+s,@JAVA_HOME@,$JAVA_HOME,;t t
+s,@javagdbm_cv_path_javah@,$javagdbm_cv_path_javah,;t t
+s,@javagdbm_cv_path_java@,$javagdbm_cv_path_java,;t t
+s,@GDBM_LIBPATH@,$GDBM_LIBPATH,;t t
+s,@GDBM_INCLUDE@,$GDBM_INCLUDE,;t t
+s,@PKG@,$PKG,;t t
+s,@JNIINC@,$JNIINC,;t t
+s,@JNISUFFIX@,$JNISUFFIX,;t t
+s,@JNIFLAGS@,$JNIFLAGS,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
+
+_ACEOF
+
+  cat >>$CONFIG_STATUS <<\_ACEOF
+  # Split the substitutions into bite-sized pieces for seds with
+  # small command number limits, like on Digital OSF/1 and HP-UX.
+  ac_max_sed_lines=48
+  ac_sed_frag=1 # Number of current file.
+  ac_beg=1 # First line for current file.
+  ac_end=$ac_max_sed_lines # Line after last line for current file.
+  ac_more_lines=:
+  ac_sed_cmds=
+  while $ac_more_lines; do
+    if test $ac_beg -gt 1; then
+      sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    else
+      sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    fi
+    if test ! -s $tmp/subs.frag; then
+      ac_more_lines=false
+    else
+      # The purpose of the label and of the branching condition is to
+      # speed up the sed processing (if there are no `@' at all, there
+      # is no need to browse any of the substitutions).
+      # These are the two extra sed commands mentioned above.
+      (echo ':t
+  /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+      if test -z "$ac_sed_cmds"; then
+	ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+      else
+	ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+      fi
+      ac_sed_frag=`expr $ac_sed_frag + 1`
+      ac_beg=$ac_end
+      ac_end=`expr $ac_end + $ac_max_sed_lines`
+    fi
+  done
+  if test -z "$ac_sed_cmds"; then
+    ac_sed_cmds=cat
+  fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+	cat >$tmp/stdin
+	ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+  ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+  { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+  ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_builddir$INSTALL ;;
+  esac
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    configure_input=
+  else
+    configure_input="$ac_file.  "
+  fi
+  configure_input=$configure_input"Generated from `echo $ac_file_in |
+				     sed 's,.*/,,'` by configure."
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+	 # Absolute (can't be DOS-style, as IFS=:)
+	 test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+	 echo "$f";;
+      *) # Relative
+	 if test -f "$f"; then
+	   # Build tree
+	   echo "$f"
+	 elif test -f "$srcdir/$f"; then
+	   # Source tree
+	   echo "$srcdir/$f"
+	 else
+	   # /dev/null tree
+	   { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+	 fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+s,@INSTALL@,$ac_INSTALL,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+  rm -f $tmp/stdin
+  if test x"$ac_file" != x-; then
+    mv $tmp/out $ac_file
+  else
+    cat $tmp/out
+    rm -f $tmp/out
+  fi
+
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/configure.in
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/configure.in	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/configure.in	(revision 13928)
@@ -0,0 +1,193 @@
+dnl Process this file with autoconf to produce a configure script.
+
+dnl autoconf configuration script for the JNI part of the 
+dnl au.com.pharos.gdbm Java package
+dnl $Id$
+
+AC_REVISION($Revision$)
+
+# Copyright (C) 1997 by Pharos IP Pty Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+AC_INIT(jni/gdbmjava.c)
+
+dnl
+dnl look for libgdbm if not in standard location
+dnl
+AC_ARG_WITH(gdbm, [  --with-gdbm=dir         Use local gdbm library and headers], gdbmdir=$withval)
+
+# TODO: allow the user to specify whether they want a debugging
+# library or not?
+
+# check for compilers and other tools
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_LN_S
+
+AC_CHECK_SIZEOF(void *)
+AC_CHECK_SIZEOF(int)
+AC_CHECK_SIZEOF(long)
+
+######## check for the JDK and tools within the JDK
+######## look in the JAVA_HOME environment variable at configure-time
+AC_MSG_CHECKING([for the JDK])
+if test "z$JAVA_HOME" != z &&
+   test -d $JAVA_HOME && 
+   test -d $JAVA_HOME/include
+then
+	AC_SUBST(JAVA_HOME)
+	AC_MSG_RESULT([found in $JAVA_HOME])
+else
+	AC_MSG_ERROR([not found in \$JAVA_HOME])
+fi
+
+# TODO: Check for specific header files in the JDK, or
+# functions/definitions within those headers?
+
+# TODO: guess which include directory to use under the JDK
+
+AC_PATH_PROG(javagdbm_cv_path_javah, javah, missing_javah)
+if test "$javagdbm_cv_path_javah" = missing_javah; then
+	AC_MSG_ERROR([javah not found.])
+fi
+
+AC_PATH_PROG(javagdbm_cv_path_java, java, missing)
+if test "$javagdbm_cv_path_java" = missing; then
+	AC_MSG_ERROR([java not found.])
+fi
+
+# check for gdbm library
+#AC_CHECK_LIB(gdbm, gdbm_open, [javagdbm_cv_lib_gdbm="-lgdbm"],
+#	[javagdbm_cv_lib_gdbm=no])
+#if test "$javagdbm_cv_lib_gdbm" = "no"; then
+#	AC_MSG_ERROR([no native gdbm library found.])
+#fi
+#LIBS="$javagdbm_cv_lib_gdbm"
+
+# gdbm stuff copied from gsdl [kjdon]
+
+dnl
+dnl Check that the GDBM library is available
+dnl
+dnl check libgdbm manually, in case it's not in the standard location.
+
+AC_MSG_CHECKING(that the GDBM library is available)
+if test ! -z "$gdbmdir" ; then
+  # look in given directory for header file
+  if test -r $gdbmdir/include/gdbm.h ; then
+    GDBM_INCLUDE="-I$gdbmdir/include" ;
+  elif test -r $gdbmdir/gdbm.h ; then
+    GDBM_INCLUDE="-I$gdbmdir" ;
+  fi
+
+  # look in given directory for library
+  if test -r $gdbmdir/libgdbm.a ; then
+    GDBM_LIBPATH="-L$gdbmdir" ;
+  elif test -r $gdbmdir/lib/libgdbm.a ; then
+    GDBM_LIBPATH="-L$gdbmdir/lib" ;
+  elif test -r $gdbmdir/.libs/libgdbm.a ; then
+    GDBM_LIBPATH="-L$gdbmdir/.libs" ;
+  fi
+
+  if test ! -z "$GDBM_LIBPATH" -a ! -z "$GDBM_INCLUDE" ; then
+    AC_MSG_RESULT($gdbmdir) ;
+  else
+    AC_MSG_RESULT(can't find gdbm.h and libgdbm.a in $gdbmdir);
+    AC_MSG_CHECKING(   looking for GDBM library in default locations)
+  fi
+fi
+
+# look in default path and in /usr/local
+if test -z "$GDBM_INCLUDE" ; then
+  # try in system directory 
+  AC_TRY_COMPILE(
+  [#include <gdbm.h>
+],
+  [],
+  success=yes,
+  success=no
+  )
+
+  if test $success = "no"; then
+# last chance - look in /usr/local (eg FreeBSD)
+    GDBM_LIBPATH=-L/usr/local/lib
+    GDBM_INCLUDE=-I/usr/local/include
+    ac_save_CXXFLAGS="$CXXFLAGS"
+    ac_save_LIBS="$LIBS"
+      CXXFLAGS="$CXXFLAGS -I/usr/local/include"
+      LIBS="$LIBS -L/usr/local/lib -lgdbm"
+      AC_TRY_LINK(
+  	[#include <gdbm.h>
+#include <stdio.h>
+	],
+  	[printf("%s",gdbm_version);],
+  	success=/usr/local,
+  	success=no
+      )
+      CXXFLAGS=$ac_save_CXXFLAGS
+      LIBS=$ac_save_LIBS
+  fi
+
+  AC_MSG_RESULT($success)
+  if test $success = "no"; then
+  AC_MSG_ERROR(GDBM Library not available - cannot install)
+  fi
+fi
+dnl I don't think anything actually checks this define, but...
+AC_DEFINE(HAVE_LIBGDBM , 1)
+
+AC_SUBST(GDBM_LIBPATH)
+AC_SUBST(GDBM_INCLUDE)
+
+########## set compiler options
+# TODO: is there a more appropriate way to guess which switches to use
+# with which systems/compilers?
+CFLAGS="-Wall -O2 -fpic"
+PKG="au.com.pharos.gdbm"
+AC_SUBST(CFLAGS)
+AC_SUBST(PKG)
+AC_SUBST(LIBS)
+
+# we need to set an extended JNI path for Mac OS/Darwin, as jni.h is on
+# a non-standard Path
+# is there a better way to do this??
+AC_MSG_CHECKING(for OS to set JNI options)
+# set defaults
+JNIINC=""
+JNISUFFIX="so"
+JNIFLAGS="-shared"
+
+if test "`(uname -s) 2> /dev/null`" = 'Darwin'; then
+  AC_MSG_RESULT(Darwin)
+  JNIINC="-I/System/Library/Frameworks/JavaVM.framework/Headers/ "
+  JNISUFFIX="jnilib"
+  JNIFLAGS="-dynamiclib -fno-common -single_module -framework JavaVM"
+fi
+if test "`(uname -s) 2> /dev/null`" = 'SunOS'; then
+  AC_MSG_RESULT(Solaris)
+  JNIINC="-I\$(JAVA_HOME)/include/solaris "
+fi
+if test "`(uname -s) 2> /dev/null`" = 'Linux'; then
+  AC_MSG_RESULT(Linux)
+  JNIINC="-I\$(JAVA_HOME)/include/linux "
+fi
+
+AC_SUBST(JNIINC)
+AC_SUBST(JNISUFFIX)
+AC_SUBST(JNIFLAGS)
+
+# write the output
+AC_OUTPUT([Makefile jni/Makefile java/Makefile])
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/install-sh
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/install-sh	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/install-sh	(revision 13928)
@@ -0,0 +1,238 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+tranformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+	-c) instcmd="$cpprog"
+	    shift
+	    continue;;
+
+	-d) dir_arg=true
+	    shift
+	    continue;;
+
+	-m) chmodcmd="$chmodprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-o) chowncmd="$chownprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-g) chgrpcmd="$chgrpprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-s) stripcmd="$stripprog"
+	    shift
+	    continue;;
+
+	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
+	    shift
+	    continue;;
+
+	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+	    shift
+	    continue;;
+
+	*)  if [ x"$src" = x ]
+	    then
+		src=$1
+	    else
+		# this colon is to work around a 386BSD /bin/sh bug
+		:
+		dst=$1
+	    fi
+	    shift
+	    continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+	echo "install:	no input file specified"
+	exit 1
+else
+	true
+fi
+
+if [ x"$dir_arg" != x ]; then
+	dst=$src
+	src=""
+	
+	if [ -d $dst ]; then
+		instcmd=:
+	else
+		instcmd=mkdir
+	fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+	if [ -f $src -o -d $src ]
+	then
+		true
+	else
+		echo "install:  $src does not exist"
+		exit 1
+	fi
+	
+	if [ x"$dst" = x ]
+	then
+		echo "install:	no destination specified"
+		exit 1
+	else
+		true
+	fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+	if [ -d $dst ]
+	then
+		dst="$dst"/`basename $src`
+	else
+		true
+	fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='	
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+	pathcomp="${pathcomp}${1}"
+	shift
+
+	if [ ! -d "${pathcomp}" ] ;
+        then
+		$mkdirprog "${pathcomp}"
+	else
+		true
+	fi
+
+	pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+	$doit $instcmd $dst &&
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+	if [ x"$transformarg" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		dstfile=`basename $dst $transformbasename | 
+			sed $transformarg`$transformbasename
+	fi
+
+# don't allow the sed command to completely eliminate the filename
+
+	if [ x"$dstfile" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		true
+	fi
+
+# Make a temp file name in the proper directory.
+
+	dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+	$doit $instcmd $src $dsttmp &&
+
+	trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+	$doit $rmcmd -f $dstdir/$dstfile &&
+	$doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/Makefile.in
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/Makefile.in	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/Makefile.in	(revision 13928)
@@ -0,0 +1,31 @@
+# Makefile for Java part of JavaGDBM
+# Katherine Don, 2005
+
+JAVAC = $(JAVA_HOME)/bin/javac
+JAVAH = $(JAVA_HOME)/bin/javah
+JAR = $(JAVA_HOME)/bin/jar
+
+JAVAGDBMHOME=../
+JAVACLASSDIR=./classes
+JAVASRCDIR=.
+JAVACOPTIONS= -deprecation -g -O
+JAVACLASSPATH=$(JAVACLASSDIR):
+
+all: setup compile
+
+setup:
+	mkdir -p $(JAVACLASSDIR)
+
+compile: setup
+	$(JAVAC) -d $(JAVACLASSDIR) -sourcepath $(JAVASRCDIR) $(JAVACOPTIONS) au/com/pharos/*/*.java
+	$(JAVAH) -o $(JAVAGDBMHOME)/jni/GdbmFile.h -classpath $(JAVACLASSPATH) au.com.pharos.gdbm.GdbmFile
+	$(JAR) cf $(JAVAGDBMHOME)/javagdbm.jar -C $(JAVACLASSDIR) au
+
+clean:
+	rm -rf $(JAVACLASSDIR) $(JAVAGDBMHOME)/javagdbm.jar $(JAVAGDBMHOME)/jni/GdbmFile.h 
+
+install:
+
+distclean: clean
+	rm -f Makefile
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/dbinterface/vf/VFDbInterface.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/dbinterface/vf/VFDbInterface.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/dbinterface/vf/VFDbInterface.java	(revision 13928)
@@ -0,0 +1,37 @@
+/*
+ * (C) Pharos IP Pty Ltd 1997
+ */
+
+package au.com.pharos.dbinterface.vf;
+
+import java.util.Date;
+
+import au.com.pharos.gdbm.GdbmFile;
+
+import au.com.pharos.packing;
+
+import au.com.pharos.dbinterface.vf;
+
+public class VFDbInterface {
+
+  /* The Order database */
+  private String orderDB = "/fn/data/Orders.gdbm";
+
+  /* The Stock database */
+  private String stockDB = "/fn/data/Stock.gdbm";
+
+  /* Initialisation.  Nothing needs to happen yet. */
+  public VFDbInterface()
+  {
+    ;
+  }
+
+  /* Submit an order to the database */
+  public void submitOrder(VFOrder order)
+  {
+    GdbmFile db = new GdbmFile(orderDB);
+    db.setKeyPacking(new StringPacking());
+    db.setValuePacking(new QuotedVectorPacking());
+
+    Vector details = order.toVectorString();
+    
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/dbinterface/vf/VFItem.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/dbinterface/vf/VFItem.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/dbinterface/vf/VFItem.java	(revision 13928)
@@ -0,0 +1,106 @@
+/*
+ * (C) Pharos IP Pty Ltd 1997
+ */
+package au.com.pharos.dbinterface.vf;
+
+import java.util.Date;
+
+public class VFItem {
+
+  /* The title of the item */
+  public String title;
+
+  /* The name fo the item's distributor */
+  public String distributor;
+
+  /* The category of the item */
+  // TODO: Create a more appropriate type for this?
+  public String category;
+
+  /* The rating of the item */
+  //TODO: Again, a more appropriate type?
+  public String rating;
+
+  /* The list price */
+  public float listPrice;
+
+  /* The supplier's price */
+  public float ourPrice;
+
+  /* The release date for the item */
+  public Date releaseDate;
+
+  /* The date upon which the video is accessible to PayTV */
+  public Date payTVWindow;
+
+  /* The date upon which the video is accessible to free-to-air TV */
+  public Date tvWindow;
+
+  /* The sell-through beginning date */
+  public Date sellThruWindow;
+
+  /* Whether or not the item has an internal magazine advertisement */
+  public boolean magAdvert;
+
+  /* The recommended number of items for Budget 1 stores */
+  public short budget1;
+
+  /* For budget 2 stores */
+  public short budget2;
+
+  /* Budget 3 stores */
+  public short budget3;
+
+  /* Budget 4 stores */
+  public short budget4;
+
+  /* Will the item be advertised by the VideoIndustry Professional Association */
+  boolean vipa;
+
+  /* Initialise all the attributes */
+  public VFItem(String newTitle,
+		String newDistrib,
+		String newCat,
+		String newRating,
+		float newList,
+		float newPrice,
+		Date newRelease,
+		Date newPaytv,
+		Date newTv,
+		boolean isMagAdvert,
+		short newBudget1,
+		short newBudget2,
+		short newBudget3,
+		short newBudget4
+		boolean newvipa)
+  {
+    title = newTitle;
+    distributor = newDistrib;
+    category = newCat;
+    rating = newRating;
+    listPrice = newList;
+    ourPrice = newPrice;
+    releaseDate = newRelease;
+    payTVWindow = newPaytv;
+    tvWindow = newTv;
+    magAdvert = isMagAdvert;
+    budget1 = newBudget1;
+    budget2 = newBudget2;
+    budget3 = newBudget3;
+    budget4 = newBudget4;
+    vipa = newvipa;
+  }
+
+  public boolean equals (Object o)
+  {
+    if (!(o instanceof VFItem)) {
+      return false;
+    }
+    VFItem other = (VFItem) o;
+    if (title.equals(other.title) && distributor.equals(other.distributor) && category.equals(other.category)) {
+      return true;
+    }
+    return false;
+  }
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/dbinterface/vf/VFOrder.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/dbinterface/vf/VFOrder.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/dbinterface/vf/VFOrder.java	(revision 13928)
@@ -0,0 +1,116 @@
+/*
+ * (C) Pharos IP PTy Ltd 1997
+ */
+
+package au.com.pharos.dbinterface.vf;
+
+import java.util.Date;
+import java.util.Vector;
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+import java.text.SimpleDateFormat;
+import java.text.ParsePosition;
+
+import java.text.SimpleDateFormat;
+
+public class VFOrder {
+
+  /* The final date for submission */
+  public Date finalSubmit;
+
+  /* The date the order was created */
+  public Date orderDate;
+
+  /* A hash mapping titles requested to numbers of each title*/
+  public Hashtable orderNumbers;
+  
+  /* The name of the ordering store */
+  public String name;
+
+  public VFOrder(Date newFinal,
+		 String newName,
+		 Hashtable newOrder)
+  {
+    finalSubmit = newFinal;
+    orderNumbers = newOrder;
+    name = newName;
+    orderDate = new Date(System.currentTimeMillis());
+    if (orderDate.after(finalSubmit)) {
+      throw new IllegalArgumentException("Final submission date is earlier than present date.");
+    }
+  }
+
+  public VFOrder(Date newFinal,
+		 Date newDate,
+		 String newName,
+		 Hashtable newOrder)
+  {
+    finalSubmit = newFinal;
+    orderDate = newDate;
+    orderNumbers = newOrder;
+    name = newName;
+    orderDate = new Date(System.currentTimeMillis());
+    if (orderDate.after(finalSubmit)) {
+      throw new IllegalArgumentException("Final submission date is earlier than present date.");
+    }
+  }
+
+  public Vector toVectorString()
+  {
+    Vector result = new Vector();
+    result.addElement(new Long(finalSubmit.getTime()));
+    result.addElement(new Long(orderDate.getTime()));
+    result.addElement(orderNumbers.toString());
+    result.addElement(name);
+    return result;
+  }
+
+  public VFOrder fromVectorString(Vector input)
+       throws java.text.ParseException
+  {
+    Hashtable data = new Hashtable();
+    SimpleDateFormat form = new SimpleDateFormat();
+    for (Enumeration e = input.elements(); e.hasMoreElements(); ) {
+      System.out.println(e.nextElement());
+    }
+    try {
+      finalSubmit = new Date(((Long) input.elementAt(0)).longValue());
+    } catch (NullPointerException e) {
+      System.err.println("Waaaah!");
+      finalSubmit = new Date();
+    }
+    System.err.println("No 2:" + input.elementAt(1).toString());
+    orderDate = new Date(((Long) input.elementAt(1)).longValue());
+    name = (String) input.elementAt(3);
+    String hashString = (String) input.elementAt(2);
+    StringBuffer key = new StringBuffer();;
+    StringBuffer value = new StringBuffer();
+    String type = new String("key");
+    for (int count = 0; count < hashString.length(); count++) {
+      char i = hashString.charAt(count);
+      if (i == '{' || i == ' ') { ; }
+      else if (i == '}') { data.put(key, value); }
+      else if (i == ',') {data.put(key, value); }
+      else if (i == '=') {
+	if (type.equals("key")) {
+	  type = "value";
+	} else {
+	  type = "key";
+	}
+      } else {
+	if (type.equals("key")) {
+	  key.append(i);
+	} else {
+	  value.append(i);
+	}
+      }
+    }
+    return new VFOrder(finalSubmit, orderDate, name, data);
+  }
+	
+      
+
+
+}
+  
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/gdbm/Closeable.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/gdbm/Closeable.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/gdbm/Closeable.java	(revision 13928)
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 1997 Pharos IP Pty Ltd
+ * Confidential.  All rights reserved.
+ * $Id$
+ */
+
+package au.com.pharos.gdbm;
+
+import java.io.IOException;
+
+/** A Closeable object is one having a connection to an underlying
+ * data store that may be flushed or closed.
+ *
+ * <P>This interface is intended to complement the Dictionary and
+ * Collection interfaces by reflecting the fact that many such objects
+ * may be closed.
+ *
+ * @author Martin Pool
+ * @version $Revision$
+ **/
+public interface Closeable {
+    /** Write outstanding changes to the underlying database, and
+     * break the connection, freeing any associated resources or
+     * locks.  This generally does not imply that the data will be
+     * lost, merely that it will be released.  If this is not
+     * meaningful for a particular Closeable object, then it should be
+     * a no-op.
+     *
+     * @exception java.io.IOException passed up from the underlying
+     * database.
+     **/
+    public void close() throws IOException;
+
+    /** Write outstanding changes to the underlying database, but
+     * leave the database open.  If this is not meaningful for a
+     * particular Closeable object, then it should be a no-op.
+     *
+     * @exception java.io.IOException passed up from the underlying
+     * database.
+     **/
+    public void sync() throws IOException;
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/gdbm/GdbmDictionary.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/gdbm/GdbmDictionary.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/gdbm/GdbmDictionary.java	(revision 13928)
@@ -0,0 +1,157 @@
+/*
+ * module: pip/java/gdbm -- A Java interface to the GDBM library
+ * class:  GdbmDictionary -- Wrap up a GDBM File for use as a Dictionary
+ *
+ * Copyright (C) 1997 Pharos IP Pty Ltd
+ * $Id$
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package au.com.pharos.gdbm;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+
+/** A GDBM database, presented as a Java dictionary.
+ *
+ * <P>This is a separate class which defers most operations to
+ * GdbmFile because GdbmFile can throw IO exceptions, and because the
+ * interface assumptions for Dictionary are not the same as those of
+ * the IO library.  Perhaps they should be the same.
+ *
+ * <P>The Dictionary class will be partially replaced by the much
+ * more elegant 
+ * <A HREF="http://www.javasoft.com/products/jdk/preview/docs/guide/collections/overview.html">Collections API</A>
+ * in JDK1.2, at which time a GDBM Collections interface will probably
+ * be available.
+ *
+ * @see java.util.Dictionary
+ * @see GdbmFile
+ *
+ * @author Martin Pool
+ * @version $Revision$
+ **/
+// TODO: I wonder if this should be an inner class of GdbmFile?  It
+// would bloat that source file a bit, but would (arguably) more
+// accurately capture the intended design. -- mbp
+public class GdbmDictionary extends Dictionary implements Closeable
+{
+    // XXX: This should probably become a private field, but on the other
+    // hand it's probably useful to be able to apply GDBM-specific methods to
+    // the underlying DB.  -- mbp
+    GdbmFile db;
+
+    public GdbmDictionary(GdbmFile db) {
+	this.db = db;
+    }
+
+    private Exception caughtException;
+    
+    public Exception checkError() {
+	return caughtException;
+    }	
+
+    public int size() {
+	try {
+	    return db.size();
+	} catch (Exception e) {
+	    caughtException = e;
+	    return 0;
+	}
+    }
+
+    public boolean isEmpty() {
+	try {
+	    return db.isEmpty();
+	} catch (Exception e) {
+	    caughtException = e;
+	    return false;
+	}
+    }
+
+    public Enumeration keys() {
+	try {
+	    return db.keys();
+	} catch (Exception e) {
+	    caughtException = e;
+	    return null;
+	}
+    }
+
+    public Enumeration elements() {
+	// TODO: write an iterator class to do this
+	throw new NoSuchMethodError();
+    }
+
+    public Object get(Object key) {
+	try {
+	    return db.fetch(key);
+	} catch (Exception e) {
+	    caughtException = e;
+	    return null;
+	}
+    }
+
+    public Object put(Object key, Object value)  {
+	try {
+	    Object oldValue = db.fetch(key);
+	    db.store(key, value);
+	    return oldValue;
+	} catch (Exception e) {
+	    caughtException = e;
+	    return null;
+	}
+    }
+
+    public Object remove(Object key) {
+	try {
+	    Object oldValue = db.fetch(key);
+	    db.delete(key);
+	    return oldValue;
+	} catch (Exception e) {
+	    caughtException = e;
+	    return null;
+	}
+    }
+
+    /** Write outstanding changes to the underlying database, and
+     * close the database.
+     *
+     * @see au.com.pharos.gdbm.Closeable
+     **/
+    public void close() {
+	try {
+	    if (db != null && db.isOpen())
+		db.close();
+	    db = null;
+	} catch (GdbmException e) {
+	    ;
+	}
+    }
+
+    /** Write outstanding changes to the underlying database, but
+     * leave the database open.
+     *
+     * @see au.com.pharos.gdbm.Closeable
+     **/
+    public void sync() {
+	try {
+	    db.sync();
+	} catch (GdbmException e) {
+	    ;
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/gdbm/GdbmException.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/gdbm/GdbmException.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/gdbm/GdbmException.java	(revision 13928)
@@ -0,0 +1,45 @@
+/*
+ * module: pip/java/gdbm -- A Java interface to the GDBM library
+ * class:  GdbmException -- An exception originating in the GDBM library
+ * Copyright (C) 1997 Pharos IP Pty Ltd
+ * $Id$
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package au.com.pharos.gdbm;
+
+import java.io.IOException;
+
+/** An exception originating in the GDBM library.
+ *
+ * @author Martin Pool
+ * @version $Revision$ 
+ * @see au.com.pharos.gdbm.GdbmFile
+ */
+
+public class GdbmException extends IOException
+{
+    // TODO: Perhaps provide more information about which particular
+    // exception caused the problem?
+    /** Constructs a GdbmException with the specified reason.
+    **/
+    public GdbmException(String reason)
+    {
+	super(reason);
+    }
+}
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/gdbm/GdbmFile.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/gdbm/GdbmFile.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/gdbm/GdbmFile.java	(revision 13928)
@@ -0,0 +1,563 @@
+/*
+ * Copyright (C) 1997 Pharos IP Pty Ltd
+ * $Id$
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package au.com.pharos.gdbm;
+
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
+
+import au.com.pharos.packing.Packing;
+import au.com.pharos.packing.RawPacking;
+
+/** Java interface to a GDBM database table.
+ *
+ * <P>This database is a simple on-disk hash table.
+ *
+ * <P>Both the hash keys and values
+ * are binary strings of any length.  They are converted to and
+ * from Java objects using customizable packing strategies.
+ *
+ * <P>The implementation of this class consists of two levels: a
+ * Java-level interface, and a set of private native functions
+ * implemented in C.  As much functionality as possible is implemented
+ * in Java: the C functions generally just marshal the information for
+ * presentation to the native GDBM library.
+ *
+ * <P>The native library <CODE>gdbmjava</CODE> must be available
+ * for dynamic loading in a system-dependant manner.
+ *
+ * <p>See the GDBM documentation file, and the
+ * <A HREF="http://www.pharos.com.au/gdbm/">JavaGDBM home page</A>
+ * for more information.
+ *
+ * @see au.com.pharos.packing.Packing
+ * @see au.com.pharos.gdbm.GdbmTest
+ * @see au.com.pharos.gdbm.GdbmDictionary
+ *
+ * @author Martin Pool
+ * @version $Revision$
+ **/
+
+public class GdbmFile implements Closeable {
+    /** The GDBM handle for the database file, or 0 if the database has
+     * been closed.  Java doesn't understand it, but it stores it and
+     * passes it to the C routines. */
+    private transient volatile long dbf;
+
+    // Remember the parameters used to open the database
+    private int openFlags;
+    private String dbFilename;
+
+    // -----------------------------------------------------------------
+    // Constructors
+
+    // Values must match those from gdbm.h !
+    /** Indicates that the caller will just read the database.  Many
+     * readers may share a database. */
+    public final static int READER = 0;
+
+    /** The caller wants read/write access to an existing database and
+     * requires exclusive access. */
+    public final static int WRITER = 1;
+
+    /** The caller wants exclusive read/write access, and the database
+     * should be created if it does not already exist. */
+    public final static int WRCREAT = 2;
+
+    /** The caller wants exclusive read/write access, and the database
+     * should be replaced if it already exists. */
+    public final static int NEWDB = 3;
+
+    /** Flag indicating GDBM should write to the database without disc
+     * synchronization.  This allows faster writes, but may produce an
+     * inconsistent database in the event of abnormal termination of
+     * the writer. */
+    public final static int FAST = 16;
+
+    // TODO: Allow FAST mode to be toggled
+
+    /** Creates a new GdbmFile object representing an disk database.  The
+     * database is opened or created on disk.
+     *
+     * <P>Both key and value strategies default to
+     * RawPacking, meaning that the database will use raw byte arrays
+     * for both key and value.
+     *
+     * <P>TODO: Allow the caller to specify the block size and/or
+     * cache size.
+     *
+     * @param fileName the disk filename in which the data will be stored.
+     *
+     * @param flags any of READER, WRITER, WRCREAT, and NEWDB, optionally
+     * ORed with FAST
+     *
+     * @exception GdbmException if the database cannot be opened or
+     * created.
+     *
+     * @see GdbmFile#READER
+     * @see GdbmFile#WRITER
+     * @see GdbmFile#WRCREAT
+     * @see GdbmFile#NEWDB
+     * @see GdbmFile#FAST
+     */
+    public GdbmFile(String fileName, int flags)
+	 throws GdbmException
+    {
+	openFlags = flags;
+	dbFilename = fileName;
+	keyPacking = new RawPacking();
+	valuePacking = new RawPacking();
+	dbf = gdbm_open(fileName, flags);
+    }
+
+    /** Close the database file if it is still open.
+     *
+     * <P><B>Note</B> that the disk file is locked against access from
+     * other processes while it is open.  To prevent contention, it
+     * may be useful to explicitly close the file rather than waiting
+     * for the garbage-collector.
+     *
+     * @see GdbmFile#isOpen()
+     **/
+    public synchronized void close() throws GdbmException
+    {
+	if (dbf != 0)
+	    gdbm_close(dbf);
+	dbf = 0;		// No longer connected
+    }
+
+    /** Close the database when the GdbmFile is garbage-collected.
+     *
+     * @see GdbmFile#close()
+     */
+    public void finalize() throws GdbmException
+    {
+	close();
+    }
+
+    /* The Gdbm file is unlocked when the process terminates, but
+     * nevertheless it would be good to close it in finalization, in
+     * case the OS process continues after the JVM terminates.
+     *
+     * XXX: Unfortunately, anybody else can turn this off again: it
+     * would be nice if there was a way to avoid this. */
+    static {
+	System.runFinalizersOnExit(true);
+    }
+
+
+
+    // -----------------------------------------------------------------
+    // Packing strategies
+    private Packing keyPacking, valuePacking;
+
+    /** Set the object to be used as the packing strategy for
+     * converting key objects to and from the byte arrays stored in
+     * the database.
+     *
+     * <P>Depending on the class of Java object used as the key of your
+     * database, it may be appropriate to use a packing strategy from
+     * the
+     * <A HREF="Package-au.com.pharos.packing.html"><CODE>au.com.pharos.packing</CODE></A>
+     * package, or to define a new subclass of one of those strategies.
+     *
+     * @see au.com.pharos.packing.Packing
+     * @see GdbmFile#setValuePacking(au.com.pharos.packing.Packing)
+     **/
+    public void setKeyPacking(Packing newPacking) {
+	keyPacking = newPacking;
+    }
+
+    /** Set the object to be used as the packing strategy for
+     * converting value objects to and from the byte arrays stored
+     *  in the database.
+     *
+     * <P>Depending on the class of Java object used as the key of your
+     * database, it may be appropriate to use a packing strategy from
+     * the
+     * <A HREF="Package-au.com.pharos.packing.html"><CODE>au.com.pharos.packing</CODE></A>
+     * package, or to define a new subclass of one of those strategies.
+     *
+     * @see au.com.pharos.packing.Packing
+     * @see GdbmFile#setKeyPacking(au.com.pharos.packing.Packing )
+     **/
+    public void setValuePacking(Packing newPacking) {
+	valuePacking = newPacking;
+    }
+
+    // -----------------------------------------------------------------
+
+    /** Returns a string indicating the version of the underlying GDBM
+     * library.
+     *
+     * @return the version of the native GDBM library.
+     **/
+    public static String getLibraryVersion()
+    {
+	return gdbm_getversion();
+    }
+
+    /** Return a string indicating the version of the JavaGDBM library
+     * wrapper.
+     *
+     * <P>The most current release is available from the
+     * <A HREF="http://www.pharos.com.au/javagdbm/">JavaGDBM home page</A>.
+     *
+     * @return the release number of the JavaGDBM library
+     **/
+    public static String getWrapperVersion()
+    {
+	return gdbm_wrapperVersion();
+    }
+
+    /** Indicate whether the database is writable.
+     *
+     * <P>Databases are opened in either read-write or read-only mode,
+     * and remain in that mode until they are closed.
+     *
+     * @return true if the database may be written; otherwise false.
+     *
+     * @see GdbmFile#GdbmFile(java.lang.String, int)
+     **/
+    public boolean isWritable()
+    {
+	return (openFlags & 0x03) != READER;
+    }
+
+    /** Indicate whether the database is open or not.
+     *
+     * <P>A database is open from the point of creation until close()
+     * is called, if ever, after which it is closed.
+     *
+     * @return false if the database has been closed; otherwise true.
+     *
+     * @see GdbmFile#close()
+     **/
+    public boolean isOpen()
+    {
+	return dbf != 0;
+    }
+
+
+    /** Compact the database file.
+     *
+     * <P>If you have had a lot of deletions and would like to shrink the
+     * space used by the GDBM file, this function will reorganize the
+     * database.  GDBM will not shorten the length of a GDBM file
+     * (deleted file space will be reused) except by using this
+     * reorganization, though it will reuse the vacant space.
+     *
+     * <P>The database must be writable.
+     */
+    public void reorganize()
+	 throws GdbmException
+    {
+	gdbm_reorganize(dbf);
+    }
+    
+
+    /** Flush changes to disk.
+     *
+     * <P>This function is only required when the database is
+     * opened with the FAST flag set.  By default, changes are
+     * flushed to disk after every update.
+     *
+     * <P>The database must be writable.
+     *
+     * @see GdbmFile#FAST
+     **/
+    public void sync()
+	 throws GdbmException
+    {
+	gdbm_sync(dbf);
+    }
+
+
+
+    /** Retrieve the value corresponding to a particular key.
+     *
+     * @param key the key of the record to be retrieved
+     *
+     * @return the value of the record with the specified key; or
+     * null if the key is not present in the database.
+     */
+    public Object fetch(Object key) throws GdbmException
+    {
+	byte[] keyBytes = keyPacking.toBytes(key);
+	return valuePacking.fromBytes(gdbm_fetch(dbf, keyBytes));
+    }
+
+
+    /** Indicate whether the specified key is in the database,
+     * without returning the value.
+     *
+     * @param key the key of the record to be retrieved
+     *
+     * @return true if a record with the specified key is present;
+     * otherwise false.
+     */
+    public boolean exists(Object key) throws GdbmException
+    {
+	byte[] keyBytes = keyPacking.toBytes(key);
+	return gdbm_exists(dbf, keyBytes);
+    }
+
+
+
+    /** Store a value in the database, replacing any existing value
+     * with the same key.
+     *
+     * @param key key under which to store the value
+     *
+     * @param value value to be stored
+     *
+     * @exception GdbmException if the object is a reader; or
+     * if an IO error occurs
+     **/
+    public void store(Object key, Object value)
+	 throws GdbmException
+    {
+	byte[] keyBytes = keyPacking.toBytes(key);
+	byte[] valueBytes = valuePacking.toBytes(value);
+	gdbm_store(dbf, keyBytes, valueBytes, true);
+    }
+
+
+    
+    /** Store a value in the database, unless a record with the same
+     * key already exists.
+     *
+     * @param key key under which to store the value.
+     *
+     * @param value value to be stored.
+     *
+     * @exception GdbmException if a record with the specified key
+     * already exists; or if the object is a reader; or
+     * if an IO error occurs
+     */
+    public void storeNoReplace(Object key, Object value)
+	 throws GdbmException
+    {
+	byte[] keyBytes = keyPacking.toBytes(key);
+	byte[] valueBytes = valuePacking.toBytes(value);
+ 	gdbm_store(dbf, keyBytes, valueBytes, false);
+    }
+
+
+    
+    /** Remove a record from the database.
+     *
+     * @param key key of the record to be removed
+     *
+     * @exception GdbmException if there is no record with the
+     * specified key; or if the object is a reader; or if an IO error
+     * occurs.
+     **/
+    public void delete(Object key)
+	 throws GdbmException
+    {
+	byte[] keyBytes = keyPacking.toBytes(key);
+	gdbm_delete(dbf, keyBytes);
+    }
+
+
+
+
+
+    // -----------------------------------------------------------------
+    // Iterator support
+
+    // TODO: Use a flag/timestamp approach to throw an exception if
+    // somebody modifies the database while they're trying to iterate
+    // over it?  Approach suggested by Doug Lea's Collections API. --
+    // mbp
+
+    /** Return an enumeration which will return all of the keys for the
+     * database of the file in (apparently) random order.
+     *
+     * <P><B>Caution:</B> If the database is modified while
+     * an enumeration is in progress,
+     * then changes in the hash table may cause the enumeration to
+     * miss some records.
+     *
+     * @see java.util.Enumeration
+     **/
+    public Enumeration keys() throws GdbmException
+    {
+	// Return an inner class which will do the iteration in the
+	// context of this GdbmFile object.
+	return new KeyEnumeration();
+    }
+
+    // Synchronization is performed in the GdbmFile's methods
+    class KeyEnumeration implements Enumeration {
+	private byte[] currKey, nextKey;
+
+	KeyEnumeration() throws GdbmException {
+	    currKey = null;
+	    nextKey = getFirstKeyRaw();
+	}
+
+	public boolean hasMoreElements() {
+	    return nextKey != null;
+	}
+
+	public Object nextElement() throws NoSuchElementException {
+	    try {
+		currKey = nextKey;
+		if (currKey == null)
+		    throw new NoSuchElementException();
+		else
+		    nextKey = getNextKeyRaw(currKey);
+		return keyPacking.fromBytes(currKey);
+	    } catch ( GdbmException e ) {
+		// Can't propagate this through java.util.Enumeration, dammit
+		throw new NoSuchElementException();
+	    }
+	}
+    }
+
+    /** Start a visit to all keys in the hashtable, using raw data values.
+     *
+     * @return the first key in the hash table as a byte array; or null if
+     * the database is empty. */
+    byte[] getFirstKeyRaw() throws GdbmException
+    {
+	return gdbm_firstkey(dbf);
+    }
+
+    /** Return the first record in the hashtable.
+     *
+     * <P>Note that the database
+     * is not ordered, so the key returned is simply the first in the
+     * hashtable and effectively randomly selected.
+     *
+     * @return the first key in the hash table; or null if
+     * the database is empty.
+     *
+     * @see GdbmFile#getNextKey(java.lang.Object)
+     * @see GdbmFile#keys()
+     **/
+    Object getFirstKey() throws GdbmException
+    {
+	return keyPacking.fromBytes(getFirstKeyRaw());
+    }
+
+
+    /** Find and read the next key in the hashtable.
+     *
+     * @return the next key; or null if <EM>keyBytes</EM> is the last key
+     * in the hashtable.
+     **/
+    byte[] getNextKeyRaw(byte[] keyBytes) throws GdbmException
+    {
+	return gdbm_nextkey(dbf, keyBytes);
+    }
+
+
+    /** Check whether the database is empty.
+     *
+     * @return true if the database contains no records; otherwise
+     * false.
+     **/
+    public boolean isEmpty() throws GdbmException
+    {
+	return getFirstKeyRaw() == null;
+    }
+
+
+    /** Count the records in the database.
+     *
+     * <P>This is implemented by iterating over the database, and so is
+     * a fairly expensive operation.
+     *
+     * <P>This method locks the database to make sure the count is
+     * accurate.
+     *
+     * @return the number of records in the database
+     * @see GdbmFile#isEmpty()
+     **/
+    public synchronized int size() throws GdbmException
+    {
+	int s = 0;
+	byte[] key = getFirstKeyRaw();
+	while (key != null) {
+	    s++;
+	    key = getNextKeyRaw(key);
+	}
+	return s;
+    }
+
+
+    static {
+	String libraryFile = System.getProperty
+	    ("au.com.pharos.gdbm.libraryFile");
+
+	if (libraryFile != null) {
+	    System.load(libraryFile);
+	} else {
+	    System.loadLibrary("gdbmjava");
+	}
+    }
+
+    private synchronized native long
+    gdbm_open(String fileName, int flags)
+	 throws GdbmException;
+
+    private synchronized native void
+    gdbm_close(long dbf);
+
+    private synchronized native void
+    gdbm_store(long dbf,
+	       byte[] key,
+	       byte[] content,
+	       boolean replace);
+
+    private synchronized native byte[]
+    gdbm_fetch(long dbf,
+	       byte[] key);
+
+    private synchronized native boolean
+    gdbm_exists(long dbf,
+		byte[] key);
+
+    private synchronized native void
+    gdbm_delete(long dbf,
+		byte[] key);
+
+    private synchronized native byte[]
+    gdbm_firstkey(long dbf)
+	 throws GdbmException;
+
+    private synchronized native byte[]
+    gdbm_nextkey(long dbf, byte[] key)
+	 throws GdbmException;
+
+    private synchronized static native String
+    gdbm_getversion();
+
+    private synchronized static native String
+    gdbm_wrapperVersion();
+
+    private synchronized native void
+    gdbm_reorganize(long dbf);
+
+    private synchronized native void
+    gdbm_sync(long dbf);
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/gdbm/GdbmTest.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/gdbm/GdbmTest.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/gdbm/GdbmTest.java	(revision 13928)
@@ -0,0 +1,296 @@
+/*
+ * module: pip/java/gdbm -- A Java interface to the GDBM library
+ * class:  GdbmTest -- Test suite for this package
+ * Copyright (C) 1997 Pharos IP Pty Ltd
+ * $Id$
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package au.com.pharos.gdbm;
+
+import java.io.PrintStream;
+
+import java.util.Enumeration;
+
+import au.com.pharos.test.Test;
+import au.com.pharos.packing.Packing;
+import au.com.pharos.packing.StringPacking;
+import au.com.pharos.packing.RawPacking;
+
+/** Test harness for the Gdbm library.
+ *
+ * <P>The source of this class forms a useful demonstration of the
+ * JavaGDBM library and is commended to the intending programmer.
+ *
+ * <P>More test cases would be very welcome.
+ *
+ * @see au.com.pharos.gdbm.GdbmFile
+ * @see au.com.pharos.packing.Packing
+ * @author Martin Pool
+ * @version $Revision$
+ */
+public class GdbmTest {
+    // Don't instantiate
+    private GdbmTest() { ; }
+    
+    private static void testLongData(GdbmFile db)
+	 throws Exception
+    {
+	StringBuffer lgBuffer = new StringBuffer();
+	for (int i = 0; i < 100; i++)
+	    lgBuffer.append("ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890" +
+			    "ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890" +
+			    "ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890");
+
+	String lgString = lgBuffer.toString();
+	lgBuffer = null;
+	String smallKey = "largeDatum";
+
+	db.store(smallKey, lgString);
+	String retr = (String) db.fetch(smallKey);
+
+	Test.ok(9, retr.hashCode() == lgString.hashCode());
+	Test.ok(10, retr.equals(lgString));
+
+	db.delete(smallKey);
+	Test.ok(11, true);
+
+	db.reorganize();
+	Test.ok(12, true);
+    }
+
+
+    static final int MANY_RECORDS = 200;
+    
+    private static void testBigFile(GdbmFile db)
+	 throws Exception
+    {
+	String key;
+
+	// Test a lot of data
+	byte[] bigData = new byte[10000];
+	for (int i = 0; i < bigData.length; i++)
+	    bigData[i] = (byte)((i & 63) + 32);
+	db.setValuePacking(new RawPacking());
+	Test.ok(150, true);
+
+	// Store a series of records in the file
+	for (int i = 0; i < MANY_RECORDS; i++) {
+	    if ((i % 100) == 0)
+		System.out.print(Integer.toString(i)+ " ");
+	    db.store(Integer.toString(i, 16), bigData);
+	}
+	System.out.println();
+	Test.ok(151, true);
+
+	// Enumerate keys and values out of the file
+	int count = 0;
+	Enumeration keys = db.keys();
+	while ( keys.hasMoreElements() ) {
+	    key = (String) keys.nextElement();
+	    count++;
+	    if ((count % 100) == 0)
+		System.out.print(Integer.toString(count)+ " ");
+	}
+	System.out.println();
+	Test.ok(152, count==MANY_RECORDS);
+
+	// Delete all the records from the file
+	count = 0;
+	while ( (key = (String) db.getFirstKey()) != null ) {
+	    db.delete(key);
+	    count++;
+	    if ((count % 100) == 0)
+		System.out.print(Integer.toString(count)+ " ");
+	}
+	System.out.println();
+	Test.ok(153, count==MANY_RECORDS);
+
+	db.reorganize();
+	Test.ok(154, true);
+    }
+
+    public static void main(String[] argv) {
+	try {
+	    final String dbFile = "/tmp/java.gdbm";
+	    String key, value;
+	    boolean found;
+
+	    // Test cases, inspired by db-hash.t in the Perl5.003_93
+	    // distribution
+	    System.out.print("GDBM Database tests:\n\t" +
+			     GdbmFile.getLibraryVersion() + "\n\t" +
+			     GdbmFile.getWrapperVersion() + "\n");
+
+	    // Create a simple database
+	    GdbmFile db = new GdbmFile(dbFile, GdbmFile.NEWDB);
+	    Test.ok(1, db != null);
+
+	    // Set the packing strategy
+	    db.setKeyPacking(new StringPacking());
+	    db.setValuePacking(new StringPacking());
+
+	    // Store some data in the file
+	    db.store("mountain", "Kosciusko");
+	    Test.ok(2, true);
+
+	    // Store and read back data
+	    db.storeNoReplace("abc", "ABC");
+	    Test.ok(3, ((String) db.fetch("abc")).equals("ABC"));
+
+	    // Check whether keys exist or not
+	    Test.ok(4, db.exists("abc"));
+	    Test.ok(5, !db.exists("jimmy"));
+	    Test.ok(6, !db.exists("abc\0"));
+
+	    // Delete those records
+	    db.delete("abc");
+	    db.delete("mountain");
+
+	    Test.ok(10, !db.exists("abc"));
+	    Test.ok(11, !db.exists("mountain"));
+
+	    // Store a series of records in the file
+	    for (int i = 100; i < 200; i++)
+		db.storeNoReplace(Integer.toString(i, Character.MAX_RADIX),
+				  Integer.toString(i, Character.MIN_RADIX));
+
+	    // Enumerate keys and values out of the file
+	    int count = 0;
+	    Enumeration keys = db.keys();
+	    while ( keys.hasMoreElements() ) {
+		key = (String) keys.nextElement();
+		// System.out.print(key + "=");
+		// value = (String) db.fetch(key);
+		// System.out.println(value);
+		count++;
+	    }
+	    Test.ok(20, count==100);
+
+	    // Delete all the records from the file
+	    count = 0;
+	    while ( (key = (String) db.getFirstKey()) != null ) {
+		db.delete(key);
+		count++;
+	    }
+	    Test.ok(30, count==100);
+
+	    // Try to fetch a non-existent key
+	    boolean caught = false;
+	    try {
+		db.fetch("larry!");
+	    } catch ( GdbmException e ) {
+		// TODO: Check the exception was the one we expected?
+		caught = true;
+	    }
+	    Test.ok(40, caught);
+
+	    // Store some very large data
+	    testLongData(db);
+
+	    // Store strings containing non-ASCII characters
+	    final String euroString = "Some funny characters: «¡ æ ø â ß !»";
+	    db.store("high ASCII", euroString);
+	    Test.ok(50, db.fetch("high ASCII").equals(euroString));
+
+	    // Close the database
+	    db.close();
+	    Test.ok(60, true);
+
+	    // Try to read from a database that is closed
+	    caught = false;
+	    try {
+		db.fetch("larry!");
+	    } catch ( Exception e ) {
+		System.out.println("caught: " + e.toString());
+		caught = true;
+	    }
+	    Test.ok(70, caught);
+
+	    // Try to open a non-existent database
+	    caught = false;
+	    try {
+		db = new GdbmFile("/tmp/somenonexistentdatabase.gdbm",
+				  GdbmFile.READER);
+	    } catch ( GdbmException e ) {
+		System.out.println("caught: " + e.toString());
+		caught = true;
+	    }
+	    Test.ok(80, caught);
+
+	    // Open a database read-only
+	    db = new GdbmFile(dbFile, GdbmFile.READER);
+	    db.setKeyPacking(new StringPacking());
+	    db.setValuePacking(new StringPacking());
+	    Test.ok(90);
+
+	    // Try to insert
+	    caught = false;
+	    try {
+		db.store("apple", "crumble");
+	    } catch ( GdbmException e ) {
+		System.out.println("caught: " + e.toString());
+		caught = true;
+	    }
+	    Test.ok(91, caught);
+
+	    // Replace an existing database
+	    db.close();
+	    db = new GdbmFile(dbFile, GdbmFile.NEWDB);
+	    db.setKeyPacking(new StringPacking());
+	    db.setValuePacking(new StringPacking());
+	    Test.ok(100, !db.exists("camel"));
+
+	    // Sync to disk
+	    db.sync();
+	    Test.ok(105, true);
+
+	    // Juggle three databases at once
+	    final String dbFile2 = "/tmp/java2.gdbm";
+	    GdbmFile db2 = new GdbmFile(dbFile2, GdbmFile.NEWDB);
+	    final String dbFile3 = "/tmp/java3.gdbm";
+	    GdbmFile db3 = new GdbmFile(dbFile3, GdbmFile.NEWDB);
+	    Test.ok(110, true);
+
+	    keys = db.keys();
+	    while (keys.hasMoreElements()) {
+		key = (String) keys.nextElement();
+		value = (String) db.fetch(key);
+		db2.store(key.getBytes(), value.getBytes());
+		db3.store(key.getBytes(), value.getBytes());
+	    }
+	    Test.ok(120, true);
+
+	    keys = db2.keys();
+	    found = true;
+	    while (keys.hasMoreElements())
+		found &= db3.exists(keys.nextElement());
+	    Test.ok(130, found);
+
+	    db2.close();
+	    db3.close();
+
+	    Test.ok(140, true);
+
+	    testBigFile(db);
+
+	    db.close();
+	    Test.ok(160, true);
+	} catch (Exception e) {
+	    e.printStackTrace();
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/io/IOUtils.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/io/IOUtils.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/io/IOUtils.java	(revision 13928)
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 1997 by Pharos IP Pty Ltd
+ * All rights reserved.
+ * $Id$
+ */
+
+package au.com.pharos.io;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+
+/**
+ * Plumbing utilities for manipulating Java IO classes.
+ *
+ * <P>These utilities really ought to be part of the
+ * <CODE>java.io</CODE> package, but they're not.  Since they're
+ * pretty useful, here they are.
+ *
+ * @version $Revision$
+ * @author Martin Pool
+ **/
+public class IOUtils {
+    /** Size of blocks to read during IO. **/
+    static public final int BLOCK_SIZE = 4<<10;
+
+    static public void pumpStream(InputStream inStream,
+				  OutputStream outStream,
+				  int contentLength)
+	 throws IOException
+    {
+	int readBytes = 0;
+	byte[] block = new byte[BLOCK_SIZE];
+	int blockBytes;
+	while (readBytes < contentLength
+	       && (blockBytes = inStream.read(block)) > 0) {
+	    readBytes += blockBytes;
+	    outStream.write(block, 0, blockBytes);
+	}
+    }
+
+    static public int pumpStream(InputStream inStream,
+				 OutputStream outStream)
+	 throws IOException
+    {
+	byte[] block = new byte[BLOCK_SIZE];
+	int blockBytes, readBytes = 0;
+	while ( (blockBytes = inStream.read(block)) > 0 ) {
+	    outStream.write(block, 0, blockBytes);
+	    readBytes += blockBytes;
+	}
+	return readBytes;
+    }
+
+    /** Reads the entire contents of the stream into a
+     * newly-constructed byte array.
+     **/
+    static public byte[] readAll(InputStream inStream)
+	 throws IOException
+    {
+	ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+	pumpStream(inStream, byteStream);
+	byte[] buf = byteStream.toByteArray();
+	byteStream.close();
+	return buf;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/meta/SerializationDumper.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/meta/SerializationDumper.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/meta/SerializationDumper.java	(revision 13928)
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 1997 Pharos IP Pty Ltd
+ * $Id$
+ * Confidential. All rights reserved.
+ */
+
+package au.com.pharos.meta;
+
+import java.lang.reflect.Field;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InvalidClassException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInput;
+import java.io.ObjectInputStream;
+import java.io.ObjectStreamException;
+import java.io.OptionalDataException;
+import java.io.PrintWriter;
+
+/*
+ * TODO: Allow people to specify an input file?
+ * TODO: Allow people to customize the display format?
+ *
+ * FIXME: We should use a custom classloader to load the untrusted
+ * classes under examination and to allow for flexible handling or
+ * tracing as classes are loaded.
+ */
+
+
+/** Java utility to display in a debugging format the contents of a
+ * serialized object stream.
+ *
+ * <P>Usage:
+ * <PRE>
+ *   java au.com.pharos.meta.SerializationDumper <SERFILE
+ * </PRE>
+ *
+ * where SERFILE is the name of the serialization file.
+ *
+ * <P><B>Limitations:</B>
+ *
+ * <OL>
+ *   <P><LI>Values are displayed only for public fields, due to Java
+ *    security restrictions.
+ *   <P><LI>Only top-level objects are dumped.
+ * </OL>
+ *
+ * <P>These are fairly serious restrictions, but SerializationDumper
+ * at least checks that the stream is well-formed, and gives some
+ * indication of what it contains.
+ *
+ * @author Martin Pool
+ * @version $Revision$
+ **/
+public class SerializationDumper {
+    public static void main(String argv[])
+    {
+	try {
+	    ObjectInput in = new ObjectInputStream(System.in);
+	    PrintWriter writer = new PrintWriter(System.out);
+	    SerializationDumper dumper = new SerializationDumper();
+	    dumper.dump(in, writer);
+	    writer.flush();
+	} catch (IOException e) {
+	    e.printStackTrace();
+	}
+    }
+
+
+    /** Dump all objects read from <EM>in</EM> to <EM>out</EM>
+     * in a human-readable debugging form.
+     **/
+    public void dump(ObjectInput in, PrintWriter out)
+	 throws IOException
+    {
+	while (true) {		// exception on eof
+	    Object obj = null;
+	    try {
+		obj = in.readObject();
+		displayObject(obj, out);
+	    }
+	    catch (ClassNotFoundException e) {
+		warning(e, out);
+	    }
+	    catch (OptionalDataException e) {
+		error(e, out);
+		return;
+	    }
+	    catch (ObjectStreamException e) {
+		warning(e, out);
+	    }
+	    catch (EOFException e) {
+		return;
+	    }
+	}
+    }
+
+
+    /** Display an object in human-readable form. **/
+    private void displayObject(Object obj, PrintWriter out)
+	 throws IOException
+    {
+	if (obj == null) {
+	    out.println("(null)");
+	    return;
+	}
+
+	Class cls = obj.getClass();
+
+	// Print the header: the name, hashcode, and string
+	// representation
+	out.println(cls.getName() + "@0x" +
+		    Integer.toHexString(obj.hashCode()) + "{");
+	out.println("\t\"" + obj.toString() + "\"");
+
+	// TODO: Recursive descent of the graph, allowing for circular
+	// structures.
+
+	// Print each field of the object
+	Field[] fields = cls.getDeclaredFields();
+	for (int i = 0; i < fields.length; i++)
+	    displayField(obj, fields[i], out);
+
+	out.println("}");
+    }
+
+
+    /** Display a particular field from an object in human-readable
+      * form.  Fields which are not accessible for security reasons
+      * are noted as such, and the name and type of the field is
+      * still printed. **/
+    private void displayField(Object obj, Field fld, PrintWriter out)
+	 throws IOException
+    {
+	int flags = fld.getModifiers();
+	out.print("\t");
+	out.print(fld.toString() + ": ");
+	try {
+	    Object value = fld.get(obj);
+	    if (value == null) {
+		out.println("(null)");
+	    }
+	    else {
+		out.println(value.getClass().getName() + "@0x" +
+			    Integer.toHexString(value.hashCode()) + ":");
+		out.println("\t\t\"" + value.toString() + "\"");
+	    }
+	} catch (IllegalAccessException e) {
+	    out.println("(not accessible)");
+	}
+    }
+
+
+    /** Display a warning that an exception occurred while dumping
+     * information. **/
+    private void warning(Exception e, PrintWriter out)
+	 throws IOException
+    {
+	out.println("warning: " + e);
+    }
+
+    /** Display an exception that occurred while dumping
+     * information. **/
+    private void error(Exception e, PrintWriter out)
+	 throws IOException
+    {
+	out.println("error: " + e.toString());
+    }
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/meta/ShowClass.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/meta/ShowClass.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/meta/ShowClass.java	(revision 13928)
@@ -0,0 +1,118 @@
+// This example is from the book "Java in a Nutshell, Second Edition".
+// Written by David Flanagan.  Copyright (c) 1997 O'Reilly & Associates.
+// You may distribute this source code for non-commercial purposes only.
+// You may study, modify, and use this example for any purpose, as long as
+// this notice is retained.  Note that this example is provided "as is",
+// WITHOUT WARRANTY of any kind either expressed or implied.
+
+import java.lang.reflect.*;
+
+/** A program that displays a class synopsis for the named class */
+public class ShowClass {
+  /** The main method.  Print info about the named class */
+  public static void main(String[] args) throws ClassNotFoundException {
+    Class c = Class.forName(args[0]);
+    print_class(c);
+  }
+
+  /** Display the modifiers, name, superclass and interfaces of a class
+   *  or interface. Then go and list all constructors, fields, and methods. */
+  public static void print_class(Class c)
+  {
+    // Print modifiers, type (class or interface), name and superclass.
+    if (c.isInterface()) {
+      // The modifiers will include the "interface" keyword here...
+      System.out.print(Modifier.toString(c.getModifiers()) +  c.getName());
+    }
+    else
+      System.out.print(Modifier.toString(c.getModifiers()) + " class " +
+                       c.getName() +
+                       " extends " + c.getSuperclass().getName());
+
+    // Print interfaces or super-interfaces of the class or interface.
+    Class[] interfaces = c.getInterfaces();
+    if ((interfaces != null) && (interfaces.length > 0)) {
+      if (c.isInterface()) System.out.println(" extends ");
+      else System.out.print(" implements ");
+      for(int i = 0; i < interfaces.length; i++) {
+        if (i > 0) System.out.print(", ");
+        System.out.print(interfaces[i].getName());
+      }
+    }
+
+    System.out.println(" {");            // Begin class member listing.
+
+    // Now look up and display the members of the class.
+    System.out.println(" // Constructors");
+    Constructor[] constructors = c.getDeclaredConstructors();
+    for(int i = 0; i < constructors.length; i++)      // Display constructors.
+      print_method_or_constructor(constructors[i]);
+
+    System.out.println(" // Fields");
+    Field[] fields = c.getDeclaredFields();           // Look up fields.
+    for(int i = 0; i < fields.length; i++)            // Display them.
+      print_field(fields[i]);
+
+    System.out.println(" // Methods");
+    Method[] methods = c.getDeclaredMethods();        // Look up methods.
+    for(int i = 0; i < methods.length; i++)           // Display them.
+      print_method_or_constructor(methods[i]);
+
+    System.out.println("}");             // End class member listing.
+  }
+
+  /** Return the name of an interface or primitive type, handling arrays. */
+  public static String typename(Class t) {
+    String brackets = "";
+    while(t.isArray()) {
+      brackets += "[]";
+      t = t.getComponentType();
+    }
+    return t.getName() + brackets;
+  }
+
+  /** Return a string version of modifiers, handling spaces nicely. */
+  public static String modifiers(int m) {
+    if (m == 0) return "";
+    else return Modifier.toString(m) + " ";
+  }
+
+  /** Print the modifiers, type, and name of a field */
+  public static void print_field(Field f) {
+    System.out.println("  " +
+                       modifiers(f.getModifiers()) +
+                       typename(f.getType()) + " " + f.getName() + ";");
+  }
+
+  /** Print the modifiers, return type, name, parameter types and exception
+   *  type of a method or constructor.  Note the use of the Member interface
+   *  to allow this method to work with both Method and Constructor objects */
+  public static void print_method_or_constructor(Member member) {
+    Class returntype=null, parameters[], exceptions[];
+    if (member instanceof Method) {
+      Method m = (Method) member;
+      returntype = m.getReturnType();
+      parameters = m.getParameterTypes();
+      exceptions = m.getExceptionTypes();
+    } else {
+      Constructor c = (Constructor) member;
+      parameters = c.getParameterTypes();
+      exceptions = c.getExceptionTypes();
+    }
+
+    System.out.print("  " + modifiers(member.getModifiers()) +
+                     ((returntype!=null)? typename(returntype)+" " : "") +
+                     member.getName() + "(");
+    for(int i = 0; i < parameters.length; i++) {
+      if (i > 0) System.out.print(", ");
+      System.out.print(typename(parameters[i]));
+    }
+    System.out.print(")");
+    if (exceptions.length > 0) System.out.print(" throws ");
+    for(int i = 0; i < exceptions.length; i++) {
+      if (i > 0) System.out.print(", ");
+      System.out.print(typename(exceptions[i]));
+    }
+    System.out.println(";");
+  }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/packing/NativeStringPacking.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/packing/NativeStringPacking.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/packing/NativeStringPacking.java	(revision 13928)
@@ -0,0 +1,82 @@
+/*
+ * module: pip/java/packing -- Strategy objects for converting
+ * Java objects to and from stored data.
+ *
+ * Copyright (C) 1997 Pharos IP Pty Ltd
+ * $Id$
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package au.com.pharos.packing;
+
+/** Convert an array of bytes in a Java string without using String
+ * encodings, just using expanding 8-bit bytes to 16-bit chars.
+ *
+ * <P>This will only work for ASCII characters, of course, but for
+ * moving bulk data around it is considerably faster than using
+ * UTF-8 encoding strategies.  Naively compressing Unicode into
+ * 8-bit characters in this manner is deprecated in JDK1.1 to
+ * help ensure that programs are Unicode-safe.
+ *
+ * @author Martin Pool
+ * @version $Revision$
+ *
+ * @see au.com.pharos.packing.Packing
+ * @see au.com.pharos.packing.StringPacking
+ */
+public class NativeStringPacking extends Packing
+{
+    /** Convert an object to an ASCII String representation.
+     *
+     * @return null if obj is null; obj is obj is already a
+     * byte[]; otherwise an native 8-bite encoded version of
+     * obj.toString().
+     **/
+    public byte[] toBytes(final Object obj)
+    {
+	String str;
+	if (obj == null)
+	    return null;
+	else if (obj instanceof byte[])
+	    return (byte[]) obj;
+	else if (obj instanceof String)
+	    str = (String) obj;
+	else
+	    str = obj.toString();
+
+	int len = str.length();
+	byte[] rawArray = new byte[len];
+	str.getBytes(0, len, rawArray, 0);
+	return rawArray;		     
+    }
+
+    /** Convert an array of bytes into a String
+     *
+     * @param raw the raw data to be decoded.
+     *
+     * @return null if <em>raw</em> is null; otherwise a string with the low
+     * 8 bits of each character taken from the corresponding byte in
+     * <em>raw</em>.
+     **/
+    public Object fromBytes(final byte[] raw)
+    {
+	if (raw == null)
+	    return null;
+	else
+	    return new String(raw, 0);
+    }
+}
+    
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/packing/Packing.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/packing/Packing.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/packing/Packing.java	(revision 13928)
@@ -0,0 +1,77 @@
+/*
+ * module: pip/java/packing -- Packing strategy objects for converting
+ *           Java objects to and from stored data.
+ * class: Packing -- Abstract strategy class for packing/unpacking data
+ *
+ * $Id$
+ * Copyright (C) 1997 Pharos IP Pty Ltd
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package au.com.pharos.packing;
+
+/** A packing Packing defines a method of converting an object to
+ * and from an array of bytes for storage in a database.
+ *
+ * <P>Generally, each packing Packing should be reflexive: that is,
+ * converting any object to and from an array of bytes should yield
+ * the same object, or an object appropriately equivalent.
+ *
+ * <P>Some Packing subclasses may not be able to pack all
+ * objects, or may not be able to unpack an object from some byte
+ * arrays.  For example, only Strings can safely be stored as string
+ * representations, and not all arrays are valid Java serialization
+ * forms.  In this case, the Packing object should throw an
+ * <code>IllegalArgumentException</code> from <code>toBytes()</code>
+ * or <code>toBytes()</code>.
+ *
+ * <P>In both cases, null references should be passed through
+ * unchanged.
+ *
+ * <P>Example:
+ * <PRE>
+ *    Packing strategy = new StringPacking();
+ *    byte[] raw = strategy.toBytes("Hello world");
+ *    ... store and retrieve raw[]
+ *    String result = (String) strategy.fromBytes(raw)
+ * </PRE>
+ *
+ *
+ * @see au.com.pharos.packing.StringPacking
+ * @see au.com.pharos.packing.NativeStringPacking
+ * @see au.com.pharos.packing.RawPacking
+ * @see au.com.pharos.packing.SerializationPacking
+ *
+ * @version $Revision$
+ * @author Martin Pool
+ **/
+public abstract class Packing {
+    /** Convert an object to an array of bytes. **/
+    public abstract byte[] toBytes(Object obj) throws IllegalArgumentException;
+
+    /** Reconstitute an array of bytes into an object. **/
+    public abstract Object fromBytes(byte[] raw) throws IllegalArgumentException;
+
+    /** Helper function that generates an IllegalArgumentException */
+    protected IllegalArgumentException cantConvert(Object obj) {
+	return new IllegalArgumentException
+	    ("Can't pack object \"" + obj.toString() +
+	     "\" (" + obj.getClass().toString() + ")" + 
+	     "\n\tusing strategy " + this.toString());
+    }
+}
+
+    
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/packing/QuotedVectorPacking.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/packing/QuotedVectorPacking.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/packing/QuotedVectorPacking.java	(revision 13928)
@@ -0,0 +1,187 @@
+/*
+ * module: pip/java/packing -- Strategy objects for converting
+ *         Java objects to and from stored data.
+ * class:  QuotedVectorPacking -- Vectors of Strings packed in a Perl-
+ *         style format
+ *
+ * Copyright (C) 1997 Pharos IP Pty Ltd
+ * $Id$
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package au.com.pharos.packing;
+
+import java.util.Vector;
+
+// FIXME: Escape bad characters! -- mbp
+// TODO: Write a more formal definition of the encoding system
+// TODO: More documentation
+
+// XXX: Perhaps the strategy for encoding characters should be in a
+// separate class used by this class?  They would have to
+// interact to make sure that separator chatacters were decoded
+// properly.  Probably not worth worrying about, as this class
+// is only a compatibility measure in any case.
+
+/** Stores Vectors of strings, packed into a single string, as used by
+ * some Perl code.  The encoding format is similar to that used in
+ * Unix databases like
+ * <A HREF="file:/etc/passwd/"><CODE>/etc/passwd</CODE></A>, except that
+ * it uses escape sequences to represent characters that would
+ * normally not be allowed.
+ *
+ * <P>The strings within the vector are separated by separator characters,
+ * which default to colons.
+ *
+ * <P>The resulting packed string is UTF encoded after escaping
+ * control-characters, so non-ASCII characters should be passed through
+ * unchanged.
+ *
+ * <P>Certain characters are escaped as quoted-printable strings.
+ * These characters include colon, equals, and escape characters.  The
+ * encoding accepts and interprets any hex escape when reading data.
+ *
+ * <P>If any elements of the vector are null, they are stored as empty
+ * strings.  On unpacking, empty strings are returned as such.
+ *
+ * <P>An example of a vector encoded in this manner is:
+ * <BLOCKQUOTE>
+ * <PRE>oC7okz059wGnQ:vf:Peter Barnes%2c Pharos Business Solutions</PRE>
+ * </BLOCKQUOTE>
+ *
+ * @author Martin Pool
+ * @version $Revision$ $Date$
+ *
+ * @see java.util.Vector
+ **/
+public class QuotedVectorPacking extends Packing
+implements java.io.Serializable
+{
+    private char hexEscape;
+    private char separator;
+    
+    /** Constructs a QuotedVectorPacking using the default separator
+     * character ':' and escape character '%'.
+     **/
+    public QuotedVectorPacking() {
+	this('%', ':');
+    }
+
+
+    /** Constructs a QuotedVectorPacking with specified separator and
+     * hex-escape characters.
+     *
+     * @param hexEscape the character used to begin a three-character
+     * hex escape
+     *
+     * @param separator the character used to separate elements in the
+     * vector.
+     **/
+    public QuotedVectorPacking(char hexEscape, char separator) {
+	if (hexEscape == separator)
+	    throw new IllegalArgumentException
+		("hexEscape and separator characters are the same");
+	this.hexEscape = hexEscape;
+	this.separator = separator;
+    }
+    
+    
+    /** Convert a Vector of Strings to a QuotedVector represented as an
+     * array of bytes.
+     *
+     * @param obj the Vector to encode; or null.
+     * 
+     * @returns an array of bytes containing a packed representation of
+     * <EM>obj</EM>; or null if <EM>obj</EM> is null.
+     *
+     * @exception java.lang.ClassCastException if obj is not a Vector
+     * or null; or if any element of <EM>obj</EM> is not a String or
+     * null.
+     **/
+    public byte[] toBytes(Object obj)
+    {
+	if (obj == null)
+	    return null;
+	Vector vec = (Vector) obj;
+	StringBuffer sb = new StringBuffer();
+	Object elem;
+	for (int i = 0; i < vec.size(); i++) {
+	    if (i > 0)
+		sb.append(separator);
+	    elem = vec.elementAt(i);
+	    sb.append((elem == null) ? "" : encodeString((String) elem));
+	}
+	return sb.toString().getBytes();
+    }
+
+
+
+    /** Perform hex-escapes on a string.
+     * @returns <EM>from</EM> encoded as a quoted-printable string
+     **/
+    private String encodeString(String from) {
+	StringBuffer buf = new StringBuffer(from.length());
+	char[] chars = from.toCharArray();
+	for (int i = 0; i < chars.length; i++) {
+	    char ch = chars[i];
+	    if (ch == separator
+		|| ch == hexEscape
+		|| Character.isISOControl(ch)
+		|| (ch != ' ' && ch != '\t' && Character.isWhitespace(ch)))
+		{
+		    buf.append(hexEscape);
+		    // XXX: This will truncate high Unicode characters, but I
+		    // don't know what else we can do with them. -- mbp
+		    buf.append(Character.forDigit((ch>>4) & 0xf, 16));
+		    buf.append(Character.forDigit(ch      & 0xf, 16));
+		} else {
+		    buf.append(ch);
+		}
+	}
+	return buf.toString();
+    }
+    
+    
+
+    /** Interprets <em>raw</em> as a packed quoted Vector, and
+     * returns the unpacked Vector of strings. */
+    public Object fromBytes(byte[] raw)
+    {
+	if (raw == null)
+	    return null;
+	
+	Vector result = new Vector();
+	StringBuffer sb = new StringBuffer();
+	for (int i = 0; i < raw.length; i++) {
+	    char ch = (char) raw[i];
+	    if (ch == separator) {
+		result.addElement(sb.toString());
+		sb.setLength(0);
+	    } else if (ch == hexEscape && i < (raw.length - 2)) {
+		byte[] hexBytes = new byte[2];
+		hexBytes[0] = raw[++i];
+		hexBytes[1] = raw[++i];
+		String hex = new String(hexBytes);
+		ch = (char)Integer.parseInt(hex, 16);
+		sb.append(ch);
+	    } else {
+		sb.append(ch);
+	    }
+	}
+	result.addElement(sb.toString());
+	return result;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/packing/RawPacking.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/packing/RawPacking.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/packing/RawPacking.java	(revision 13928)
@@ -0,0 +1,60 @@
+/*
+ * module: pip/java/packing -- Strategy objects for converting
+ * Java objects to and from stored data.
+ *
+ * Copyright (C) 1997 Pharos IP Pty Ltd
+ * $Id$
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package au.com.pharos.packing;
+
+/** A packing strategy which stores only raw arrays of bytes.  Other
+ * objects cannot be stored using this strategy.
+ *
+ * @author Martin Pool
+ * @version $Revision$
+ **/
+public class RawPacking extends Packing implements java.io.Serializable
+{
+    /** Perform the trivial packing case, casting an array of bytes
+     * into the same.
+     *
+     * @throw IllegalArgumentException if <em>obj</em> is neith null nor
+     * an array of bytes.
+     */
+    public byte[] toBytes(Object obj) throws IllegalArgumentException
+    {
+	if (obj == null)
+	    return null;
+	else if (obj instanceof byte[])
+	    return (byte[]) obj;
+	else
+	    throw cantConvert(obj);
+    }
+
+    /** Performs the trivial unpacking case of returning <em>raw</em>
+     * untouched.
+     *
+     * @return either null or <em>raw</em>; always assignable to
+     * <code>byte[]</code>
+     **/
+    public Object fromBytes(byte[] raw)
+    {
+	return raw;
+    }
+}
+    
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/packing/SerializationPacking.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/packing/SerializationPacking.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/packing/SerializationPacking.java	(revision 13928)
@@ -0,0 +1,100 @@
+/*
+ * class: SerializationPacking -- Store an object as serialized data
+ *
+ * Copyright (C) 1997 Pharos IP Pty Ltd
+ * $Id$
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package au.com.pharos.packing;
+
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ObjectInputStream;
+import java.io.IOException;
+
+/** A packing strategy which stores and retrieves objects using
+ * <a href="http://www.javasoft.com/products/jdk/1.1/docs/guide/serialization/index.html">Java serialization</a>.
+ *
+ * @version $Revision$
+ * @author Martin Pool
+ * @see au.com.pharos.packing.Packing
+ **/
+public class SerializationPacking extends Packing
+implements java.io.Serializable
+{
+    /** Convert an object to a Java serialization format.
+     *
+     * @returns a buffer containing a a serialized representation of <em>obj</em>;
+     * or null if <em>obj</em> if null
+     * @exception IllegalArgumentException if <em>obj</em> (or any object
+     * referred to by <em>obj</em>) cannot be serialized
+     **/
+    public byte[] toBytes(Object obj) throws IllegalArgumentException
+    {
+	if (obj == null)
+	    return null;
+
+	// Serialize via a stream into a buffer
+	ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+	try {
+	    ObjectOutputStream objStream = new ObjectOutputStream(byteStream);
+	    objStream.writeObject(obj);
+	    // Don't close the stream, or you will lose the byte array
+	    objStream.flush();
+	} catch (IOException e) {
+	    throw new IllegalArgumentException("IOException during serialization: " +
+					       e.toString());
+	}
+
+	return byteStream.toByteArray();
+    }
+
+    /** Interprets <em>raw</em> as a Java serialization stream, and
+     * returns <B>the first</B> object read from that stream.
+     *
+     * <P><B>Note:</B>There is currently no means by which any later
+     * objects in the can be retrieved: it is assumed that the object
+     * written to the buffer contains references to all the
+     * information required.  This is consistent with the fact that
+     * toBytes() stores only a single object, so this packing strategy
+     * is completely reversable.
+     **/
+    // FIXME: Is the correct word 'reversable', 'reflexive', or
+    // something else?  -- mbp@pharos.com.au
+    public Object fromBytes(byte[] raw)
+    {
+	if (raw == null)
+	    return null;
+
+	Object obj;
+	try {
+	    ByteArrayInputStream byteStream = new ByteArrayInputStream(raw);
+	    ObjectInputStream objStream = new ObjectInputStream(byteStream);
+	    obj = objStream.readObject();
+	    objStream.close();
+	} catch (IOException e) {
+	    throw new IllegalArgumentException("Exception during deserialization: " +
+					       e.toString());
+	} catch (ClassNotFoundException e) {
+	    throw new IllegalArgumentException("Exception during deserialization: " +
+					       e.toString());
+	}	    
+	return obj;
+    }
+}
+    
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/packing/StringPacking.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/packing/StringPacking.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/packing/StringPacking.java	(revision 13928)
@@ -0,0 +1,85 @@
+/*
+ * module: pip/java/packing -- Strategy objects for converting
+ * Java objects to and from stored data.
+ *
+ * Copyright (C) 1997 Pharos IP Pty Ltd
+ * $Id$
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package au.com.pharos.packing;
+
+/** StringPacking converts Java Strings to and from byte arrays
+ * using the default UTF-8 encoding.
+ *
+ * <P>For strings containing only ASCII-7 characters, this is
+ * equivalent to <code>NativeStringPacking</code> but probably
+ * somewhat slower.  However, it will safely handle non-ASCII
+ * characters, or unusual locales.
+ *
+ * @see au.com.pharos.packing.Packing
+ * @see au.com.pharos.packing.NativeStringPacking
+ **/
+public class StringPacking extends Packing
+implements java.io.Serializable
+{
+    /** Convert a String to an array of bytes using Java's default
+     * encoding.
+     *
+     * <P>If <em>obj</em> is not a String, array of bytes, or null
+     * then it's <code>toString()</code> method is called first to
+     * convert it to an array of bytes.  This will lose information in
+     * many cases.
+     *
+     * @param obj The object to convert.
+     *
+     * @return <em>obj</em> converted to an array of bytes; or null if
+     * <em>obj</em> is null.
+     **/
+    public byte[] toBytes(Object obj)
+    {
+	if (obj == null)
+	    return null;
+	else if (obj instanceof byte[])
+	    return (byte[]) obj;
+	else if (obj instanceof String)
+	    return ((String) obj).getBytes();
+	else
+	    return obj.toString().getBytes();
+    }
+
+    /** Decode an array of bytes using the default String encoding.
+     *
+     * @param raw An array of bytes to decode.
+     *
+     * @return A String representation of <em>raw</em>; or null if
+     * <em>raw</em> is null.
+     **/     
+    public Object fromBytes(byte[] raw)
+    {
+	if (raw == null)
+	    return null;
+	else {
+	    try{
+	    return new String(raw, "UTF-8");
+	    } catch (Exception e) {
+		System.err.println("String Packing:encoding not supported");
+		return new String(raw);
+	    }
+	}
+    }
+}
+    
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/packing/TestQuotedVectorPacking.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/packing/TestQuotedVectorPacking.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/packing/TestQuotedVectorPacking.java	(revision 13928)
@@ -0,0 +1,84 @@
+/*
+ * module: pip/java/packing -- Strategy objects for converting
+ *         Java objects to and from stored data.
+ * class:  TestQuotedVectorPacking -- Test harness for QuotedVectorPacking
+ *
+ * Copyright (C) 1997 Pharos IP Pty Ltd
+ * $Id$
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package au.com.pharos.packing;
+
+import java.util.Vector;
+
+// TODO: Perhaps make this into a more general-purpose test harness
+// for testing any Packing strategy? -- mbp 19971021
+
+/** Test harness for the QuotedVectorPacking strategy class.
+ *
+ * <P><B>Usage:</B>
+ * <UL><P><CODE>java TestQuotedVectorPacking -[de] ARGS</CODE><UL>
+ *
+ * <P><B>Options</B>
+ * <DL>
+ *   <P><DT><CODE>-d</CODE><DD>Print the results of decoding
+ *      the each of the command-
+ *      line arguments as QuotedVectorPacking encoding strings
+ *
+ *   <P><DT><CODE>-e</CODE><DD>Print the results of encoding
+ *      a vector containing
+ *      all of the command-line arguments 
+ * </DL>
+ *
+ * @author Martin Pool
+ * @version $Revision$ $Date$
+ **/
+public class TestQuotedVectorPacking {
+    private TestQuotedVectorPacking() {}
+    
+    public static void main(String[] argv) {
+	Packing strat = new QuotedVectorPacking();
+	final String usage = "usage: TestQuotedVectorPacking -[ed] ARGS";
+
+	if (argv.length == 0) {
+	    System.err.println(usage);
+	    return;
+	}
+	
+	if (argv[0].equals("-e")) {
+	    Vector encode = new Vector(argv.length - 1);
+	    for (int i = 1; i < argv.length; i++) {
+		System.out.println(argv[i]);
+		encode.addElement(argv[i]);
+	    }
+	    byte[] packed = strat.toBytes(encode);
+	    System.out.print("\t");
+	    System.out.println(new String(packed));
+	} else if (argv[0].equals("-d")) {
+	    for (int i = 1; i < argv.length; i++) {
+		Vector decode = (Vector) strat.fromBytes(argv[i].getBytes());
+		System.out.println(argv[i]);
+		for (int j = 0; j < decode.size(); j++) {
+		    System.out.print("\t");
+		    System.out.println(decode.elementAt(j));
+		}
+	    }
+	} else {
+	    System.err.println(usage);
+	}
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/test/Test.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/test/Test.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/test/Test.java	(revision 13928)
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 1997 Pharos IP Pty Ltd
+ * $Id$
+ * $Source$
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package au.com.pharos.test;
+
+/** Utilities for automated testing.  This class contains only static
+ * functions and should not be instantiated.
+ *
+ * @author Martin Pool
+ * @version $Revision$ $Date$
+ **/
+// TODO: Somehow automatically generate sequence numbers, or perhaps use
+// strings to report progress
+public class Test {
+    // Don't instantiate
+    private Test() {}
+
+    static int nPassed, nFailed;
+
+    /** Register that a particular test executed successfully, and
+     * output a success or failure message.
+     *
+     * @param number test sequence number
+     **/
+    static public void ok(int no) {
+	ok(no, true);
+    }
+
+    /** Register the result of a test, and output a success or failure
+     * message.
+     *
+     * @param number test sequence number
+     * @param result whether the test was successful or not
+     */
+    static public void ok(int number, boolean passed) {
+	if (passed) {
+	    nPassed++;
+	}
+	else {
+	    System.out.print("not ");
+	    nFailed++;
+	}
+	System.out.print("ok " + number + "\n");
+    }
+
+    /**
+     * Print a summary of test results.
+     **/
+    static public void summary() {
+	System.out.print("test summary: " + nPassed + " passed, " +
+			 nFailed + " failed");
+    }
+}
+    
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/util/StringOps.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/util/StringOps.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/util/StringOps.java	(revision 13928)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 1997 by Pharos IP Pty Ltd
+ * Confidential.  All rights reserved.
+ * $Id$
+ * $Source$
+ *
+ * ``No strings attached.''
+ */
+
+package au.com.pharos.util;
+
+/**
+ * Mixed bag of string manipulation functions.  It would be nice if
+ * some of these were in <CODE>java.lang.String</CODE>, but since
+ * they're not, they're implemented as static functions within this
+ * class.
+ *
+ * Typical use:
+ * <PRE>
+ * String foo = "some string"
+ * int cnt = StringOps.countOccurrences(foo, 's');
+ * // --> cnt == 2
+ * </PRE>
+ *
+ * @author Martin Pool
+ * @version $Revision$, $Date$
+ **/
+public class StringOps
+{
+    /** This class contains only static public functions. **/
+    private StringOps() { ; }
+
+    /** Count the number of occurences of a character in a
+     * string.
+     *
+     * @param needle the character to search
+     * @param haystack string to be searched
+     *
+     * @return 0 if <EM>needle</EM> does not occur in <EM>haystack</EM>;
+     * or a positive number indicating the number of occurrences
+     **/
+    static public int countOccurrences(String haystack, char needle)
+    {
+	byte[] hay = haystack.getBytes();
+	int count = 0;
+	for (int i = 0; i < hay.length; i++)
+	    if (hay[i] == needle)
+		count++;
+	return count;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/util/test/StringOpsTest.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/util/test/StringOpsTest.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/au/com/pharos/util/test/StringOpsTest.java	(revision 13928)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 1997 by Pharos IP Pty Ltd
+ * Confidential.  All rights reserved.
+ * $Id$
+ * $Source$
+ */
+
+package au.com.pharos.util.test;
+
+import au.com.pharos.test.Test;
+
+import au.com.pharos.util.StringOps;
+
+/**
+ * Test harness for <CODE>au.com.pharos.util.StringOps</CODE>
+ *
+ * @author Martin Pool
+ * @version $Revision$ $Date$
+ **/
+public class StringOpsTest
+{
+    static public void main(String[] args)
+    {
+	new StringOpsTest().run();
+    }
+
+    public void run()
+    {
+	try {
+	    testCountOccurrences();
+	}
+	finally {
+	    Test.summary();
+	}
+    }
+
+    public void testCountOccurrences()
+    {
+	// Simple tests of countOccurences(String, char)
+	Test.ok(100, ( StringOps.countOccurrences("hello world", 'z') == 0) );
+	Test.ok(110, ( StringOps.countOccurrences("zhello world", 'z') == 1) );
+	Test.ok(120, ( StringOps.countOccurrences("hello worldz", 'z') == 1) );
+	Test.ok(130, ( StringOps.countOccurrences("z", 'z') == 1) );
+	Test.ok(140, ( StringOps.countOccurrences("zzz", 'z') == 3) );
+	Test.ok(150, ( StringOps.countOccurrences("0z0z0z", 'z') == 3) );
+	Test.ok(160, ( StringOps.countOccurrences("\0z\0z\0z", '\0') == 3) );
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/winMake.bat
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/winMake.bat	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/java/winMake.bat	(revision 13928)
@@ -0,0 +1,45 @@
+@echo off
+
+set JAVAGDBMHOME=..
+
+rem ---- Where to put class files ----
+set JAVACLASSDIR=classes
+
+rem ---- Name and location of java programs ----
+set JAVAC="%JAVA_HOME%\bin\javac"
+set JAVAH="%JAVA_HOME%\bin\javah"
+set JAVA="%JAVA_HOME%\bin\java"
+set JAVADOC="%JAVA_HOME%\bin\javadoc"
+set JAR="%JAVA_HOME%\bin\jar"
+
+set JAVACOPTIONS= -deprecation -g -O
+
+
+if ""%1"" == """" goto compile
+if ""%1"" == ""compile"" goto compile
+if ""%1"" == ""install"" goto install
+if ""%1"" == ""clean"" goto clean
+
+:unknown
+	echo Error: Unrecognized argument %1.
+	goto done
+
+:compile
+	if not exist %JAVACLASSDIR% mkdir %JAVACLASSDIR%
+	echo Compiling...
+        %JAVAC% -d %JAVACLASSDIR% %JAVACOPTIONS%  au\com\pharos\gdbm\*.java au\com\pharos\io\*.java au\com\pharos\meta\*.java au\com\pharos\packing\*.java au\com\pharos\test\*.java au\com\pharos\util\*.java
+        %JAVAH% -classpath %JAVACLASSDIR% -o %JAVAGDBMHOME%\jni\GdbmFile.h au.com.pharos.gdbm.GdbmFile
+        %JAR% cf %JAVAGDBMHOME%\javagdbm.jar -C %JAVACLASSDIR% au
+	goto done
+
+:install
+	goto done
+
+:clean
+	echo Cleaning up...
+	if exist %JAVACLASSDIR% rmdir /S /Q %JAVACLASSDIR%
+        if exist %JAVAGDBMHOME%\javagdbm.jar del %JAVAGDBMHOME%\javagdbm.jar 
+        if exist %JAVAGDBMHOME%\jni\GdbmFile.h del %JAVAGDBMHOME%\jni\GdbmFile.h 
+	goto done
+
+:done
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/jni/GdbmFile.h
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/jni/GdbmFile.h	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/jni/GdbmFile.h	(revision 13928)
@@ -0,0 +1,119 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class au_com_pharos_gdbm_GdbmFile */
+
+#ifndef _Included_au_com_pharos_gdbm_GdbmFile
+#define _Included_au_com_pharos_gdbm_GdbmFile
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef au_com_pharos_gdbm_GdbmFile_READER
+#define au_com_pharos_gdbm_GdbmFile_READER 0L
+#undef au_com_pharos_gdbm_GdbmFile_WRITER
+#define au_com_pharos_gdbm_GdbmFile_WRITER 1L
+#undef au_com_pharos_gdbm_GdbmFile_WRCREAT
+#define au_com_pharos_gdbm_GdbmFile_WRCREAT 2L
+#undef au_com_pharos_gdbm_GdbmFile_NEWDB
+#define au_com_pharos_gdbm_GdbmFile_NEWDB 3L
+#undef au_com_pharos_gdbm_GdbmFile_FAST
+#define au_com_pharos_gdbm_GdbmFile_FAST 16L
+/*
+ * Class:     au_com_pharos_gdbm_GdbmFile
+ * Method:    gdbm_open
+ * Signature: (Ljava/lang/String;I)J
+ */
+JNIEXPORT jlong JNICALL Java_au_com_pharos_gdbm_GdbmFile_gdbm_1open
+  (JNIEnv *, jobject, jstring, jint);
+
+/*
+ * Class:     au_com_pharos_gdbm_GdbmFile
+ * Method:    gdbm_close
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_au_com_pharos_gdbm_GdbmFile_gdbm_1close
+  (JNIEnv *, jobject, jlong);
+
+/*
+ * Class:     au_com_pharos_gdbm_GdbmFile
+ * Method:    gdbm_store
+ * Signature: (J[B[BZ)V
+ */
+JNIEXPORT void JNICALL Java_au_com_pharos_gdbm_GdbmFile_gdbm_1store
+  (JNIEnv *, jobject, jlong, jbyteArray, jbyteArray, jboolean);
+
+/*
+ * Class:     au_com_pharos_gdbm_GdbmFile
+ * Method:    gdbm_fetch
+ * Signature: (J[B)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_au_com_pharos_gdbm_GdbmFile_gdbm_1fetch
+  (JNIEnv *, jobject, jlong, jbyteArray);
+
+/*
+ * Class:     au_com_pharos_gdbm_GdbmFile
+ * Method:    gdbm_exists
+ * Signature: (J[B)Z
+ */
+JNIEXPORT jboolean JNICALL Java_au_com_pharos_gdbm_GdbmFile_gdbm_1exists
+  (JNIEnv *, jobject, jlong, jbyteArray);
+
+/*
+ * Class:     au_com_pharos_gdbm_GdbmFile
+ * Method:    gdbm_delete
+ * Signature: (J[B)V
+ */
+JNIEXPORT void JNICALL Java_au_com_pharos_gdbm_GdbmFile_gdbm_1delete
+  (JNIEnv *, jobject, jlong, jbyteArray);
+
+/*
+ * Class:     au_com_pharos_gdbm_GdbmFile
+ * Method:    gdbm_firstkey
+ * Signature: (J)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_au_com_pharos_gdbm_GdbmFile_gdbm_1firstkey
+  (JNIEnv *, jobject, jlong);
+
+/*
+ * Class:     au_com_pharos_gdbm_GdbmFile
+ * Method:    gdbm_nextkey
+ * Signature: (J[B)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_au_com_pharos_gdbm_GdbmFile_gdbm_1nextkey
+  (JNIEnv *, jobject, jlong, jbyteArray);
+
+/*
+ * Class:     au_com_pharos_gdbm_GdbmFile
+ * Method:    gdbm_getversion
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_au_com_pharos_gdbm_GdbmFile_gdbm_1getversion
+  (JNIEnv *, jclass);
+
+/*
+ * Class:     au_com_pharos_gdbm_GdbmFile
+ * Method:    gdbm_wrapperVersion
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_au_com_pharos_gdbm_GdbmFile_gdbm_1wrapperVersion
+  (JNIEnv *, jclass);
+
+/*
+ * Class:     au_com_pharos_gdbm_GdbmFile
+ * Method:    gdbm_reorganize
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_au_com_pharos_gdbm_GdbmFile_gdbm_1reorganize
+  (JNIEnv *, jobject, jlong);
+
+/*
+ * Class:     au_com_pharos_gdbm_GdbmFile
+ * Method:    gdbm_sync
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_au_com_pharos_gdbm_GdbmFile_gdbm_1sync
+  (JNIEnv *, jobject, jlong);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/jni/Makefile.in
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/jni/Makefile.in	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/jni/Makefile.in	(revision 13928)
@@ -0,0 +1,63 @@
+# Makefile for the native parts of the au.com.pharos.gdbm
+# Java package.
+# Modified by kjdon 2005
+
+# Copyright (C) 1997 by Pharos IP Pty Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#srcdir=@srcdir@
+libdir=@libdir@
+
+CC=@CC@
+CFLAGS=-c @CFLAGS@ $(INC) -DWRAPPER_VERSION=\"$(WRAPPER_VERSION)\" 
+#PKG=@PKG@
+GDBM_LIBS=@GDBM_LIBPATH@ -lgdbm
+LIBS= $(GDBM_LIBS) @LIBS@
+LDFLAGS = @LDFLAGS@
+JNIFLAGS=@JNIFLAGS@
+JNISUFFIX=@JNISUFFIX@
+JNIINC=@JNIINC@
+INC=-I. -I$(JAVA_HOME)/include @GDBM_INCLUDE@ @JNIINC@
+
+
+# TODO: Build versioned shared libraries?
+
+# TODO: Build shared libraries in a way that will work on different
+# platforms -- mbp
+
+WRAPPER_VERSION=0005
+NATIVE_LIB=libgdbmjava.$(JNISUFFIX)
+
+all: $(NATIVE_LIB)
+
+$(NATIVE_LIB): GdbmFile.h gdbmjava.o Makefile
+	$(CC) $(LDFLAGS) $(JNIFLAGS) -o $(NATIVE_LIB) gdbmjava.o $(LIBS)
+
+gdbmjava.o: gdbmjava.c	
+	$(CC) $(INC) $(CFLAGS) $?
+
+# no easy way to tell if a class file has changed or not
+#GdbmFile.h: 
+#	$(javah) -o GdbmFile.h -jni $(PKG).GdbmFile 
+
+clean:	
+	rm -f  *.o $(NATIVE_LIB) 
+
+distclean: clean
+	rm -f Makefile
+
+install: 
+	cp $(NATIVE_LIB) $(libdir)/
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/jni/gdbmjava.c
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/jni/gdbmjava.c	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/jni/gdbmjava.c	(revision 13928)
@@ -0,0 +1,476 @@
+/*
+ * module: pip/jni/gdbm -- A Java interface to the GDBM library
+ * file:   gdbmjava.c -- Native parts of the au.com.pharos.gdbm.GdbmFile
+ *             Java class
+ *
+ * Copyright (C) 1997 Pharos IP Pty Ltd
+ *
+ * $Id$ 
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* NOTE ON MEMORY MANAGEMENT: GDBM always mallocs memory and expects
+ * the caller to free it.  Java requires native functions to interact
+ * with it to lock and unlock buffers. */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined (__WIN32__)
+#include <gdbmdefs.h>
+#include <gdbmerrno.h>
+#define GDBM_FILE gdbm_file_info *
+extern char* gdbm_version;
+#else
+#include <gdbm.h>
+#endif
+
+#include <jni.h>
+
+#include <GdbmFile.h>
+
+#ifdef DEBUG
+#define ASSERT(x) if (!(x)) { \
+  fprintf(stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
+  abort(); }
+#else /* !DEBUG */
+#define ASSERT(x) 
+#endif /* !DEBUG */
+
+/* The Java class within which the native methods are declared */
+#define JAVA_CLASS "au.com.pharos.gdbm.GdbmFile"
+
+#define NULL_PTR_EXCEPTION(env) nullPtrException(env, __FILE__, __LINE__)
+#define GDBM_EXCEPTION(env) gdbmException(env, __FILE__, __LINE__)
+
+#define CHECK_NOT_NULL(ptr, env) if (!ptr) { NULL_PTR_EXCEPTION(env); return 0; }
+#define CHECK_NOT_NULL_VOID(ptr, env) if (!ptr) { NULL_PTR_EXCEPTION(env); return; }
+
+void gdbmException(JNIEnv *env, const char *file, int line);
+void nullPtrException(JNIEnv *env, const char *file, int line);
+
+void releaseArray(JNIEnv *env, jbyteArray array, datum *fromDatum);
+void releaseArrayAbort(JNIEnv *env, jbyteArray array, datum *fromDatum);
+int arrayToDatum(JNIEnv *env, jbyteArray fromArray, datum *toDatum);
+jbyteArray datumToArray(JNIEnv *env, datum *fromDatum);
+
+/* Convert between a jlong and a void ptr using a well-defined cast.
+ * (Casting between a pointer and an integer of different sizes spooks
+ * both gcc and mbp. */
+#if (SIZEOF_VOID_P == SIZEOF_LONG)
+#  define DBF_TO_JLONG(x) ((jlong)((long) x))
+#  define JLONG_TO_DBF(x) ((GDBM_FILE)((long) x))
+#elif (SIZEOF_VOID_P == SIZEOF_INT)
+#  define DBF_TO_JLONG(x) ((jlong)((int) (x)))
+#  define JLONG_TO_DBF(x) ((GDBM_FILE)((int) (x)))
+#else
+#  define DBF_TO_JLONG(x) ((jlong)(x))
+#  define JLONG_TO_DBF(x) ((GDBM_FILE)(x))
+#endif
+
+
+JNIEXPORT jlong JNICALL 
+Java_au_com_pharos_gdbm_GdbmFile_gdbm_1open
+    (JNIEnv *env, jobject obj, jstring fileName, jint flags)
+{
+    GDBM_FILE dbf;
+    const char *utfFileName;
+   
+    utfFileName = (*env)->GetStringUTFChars(env, fileName, 0);
+    if (!utfFileName) 
+	return 0;
+    
+    setbuf(stderr, 0);
+   
+    /* XXX: Should we let the caller specify the file mode?  I think
+     * not -- Java is above the level of octal file modes. [mbp] */
+    /* Couldn't get it to work properly on Windows without the 0 here - 
+       wouldn't allow mulitple READs on a single file [kjdon] */
+#if defined (__WIN32__) 
+    dbf = gdbm_open((char *) utfFileName, 0, flags, 0660, NULL, 0);
+#else
+    dbf = gdbm_open((char *) utfFileName, 0, flags, 0660, NULL);
+#endif
+    if (utfFileName)
+	(*env)->ReleaseStringUTFChars(env, fileName, utfFileName);
+
+    if (!dbf) {
+	GDBM_EXCEPTION(env);
+	return 0;
+    }	
+   
+    return DBF_TO_JLONG(dbf);
+}
+
+
+
+
+
+JNIEXPORT jbyteArray JNICALL 
+Java_au_com_pharos_gdbm_GdbmFile_gdbm_1firstkey
+(JNIEnv *env, jobject obj, jlong dbf)
+{
+    datum	keyDatum;
+    jbyteArray 	keyArray;
+
+    CHECK_NOT_NULL(dbf, env);
+
+    keyDatum = gdbm_firstkey(JLONG_TO_DBF(dbf));
+    if ( gdbm_errno != GDBM_NO_ERROR ) {
+	GDBM_EXCEPTION(env);
+	return 0;
+    }
+    if ( !keyDatum.dptr )
+	return 0;
+
+    keyArray = datumToArray(env, &keyDatum);
+    free(keyDatum.dptr); 
+
+    return keyArray;
+}
+
+
+
+
+
+JNIEXPORT jbyteArray JNICALL 
+Java_au_com_pharos_gdbm_GdbmFile_gdbm_1nextkey
+(JNIEnv *env, jobject this, jlong dbf, jbyteArray keyArray)
+{
+    datum	keyDatum;
+    datum	nextDatum;
+    jbyteArray	nextArray;
+
+    CHECK_NOT_NULL(dbf, env);
+
+    if (!arrayToDatum(env, keyArray, &keyDatum)) {
+	NULL_PTR_EXCEPTION(env);
+	return 0;
+    }
+    
+    nextDatum = gdbm_nextkey(JLONG_TO_DBF(dbf), keyDatum);
+    releaseArrayAbort(env, keyArray, &keyDatum);
+
+    if ( gdbm_errno != GDBM_NO_ERROR ) {
+	GDBM_EXCEPTION(env);
+	return 0;
+    }
+    if ( !nextDatum.dptr )
+	return 0;
+
+    nextArray = datumToArray(env, &nextDatum);
+    free(nextDatum.dptr);
+    
+    return nextArray;
+}
+
+
+
+
+
+
+JNIEXPORT jbyteArray JNICALL 
+Java_au_com_pharos_gdbm_GdbmFile_gdbm_1fetch
+  (JNIEnv *env, jobject this, jlong dbf, jbyteArray keyArray)
+{
+    datum 	keyDatum;
+    datum 	valueDatum;
+    jbyteArray	valueArray;
+
+    CHECK_NOT_NULL(dbf, env);
+
+    if (!arrayToDatum(env, keyArray, &keyDatum)) {
+	NULL_PTR_EXCEPTION(env);
+	return 0;
+    }
+
+    valueDatum = gdbm_fetch(JLONG_TO_DBF(dbf), keyDatum);
+    releaseArrayAbort(env, keyArray, &keyDatum);
+
+    if ( !valueDatum.dptr )
+	return 0;
+    if ( gdbm_errno != GDBM_NO_ERROR ) {
+	GDBM_EXCEPTION(env);
+	return 0;
+    }
+
+    valueArray = datumToArray(env, &valueDatum);
+    free(valueDatum.dptr);
+
+    return valueArray;
+}
+
+
+
+JNIEXPORT jboolean JNICALL 
+Java_au_com_pharos_gdbm_GdbmFile_gdbm_1exists
+  (JNIEnv *env, jobject obj, jlong dbf, jbyteArray keyArray)
+{
+    datum 	keyDatum;
+    int		result;
+
+    CHECK_NOT_NULL(dbf, env);
+    if (!arrayToDatum(env, keyArray, &keyDatum)) {
+	NULL_PTR_EXCEPTION(env);
+	return JNI_FALSE;
+    }
+    result = gdbm_exists(JLONG_TO_DBF(dbf), keyDatum);
+    if ( gdbm_errno != GDBM_NO_ERROR ) {
+	GDBM_EXCEPTION(env);
+	return 0;
+    }
+    releaseArrayAbort(env, keyArray, &keyDatum);
+    return result ? JNI_TRUE : JNI_FALSE;
+}
+
+
+
+
+
+JNIEXPORT void JNICALL 
+Java_au_com_pharos_gdbm_GdbmFile_gdbm_1store
+  (JNIEnv *env, jobject obj, jlong dbf, 
+   jbyteArray keyArray, jbyteArray valueArray, jboolean replace)
+{
+    datum	keyDatum;
+    datum	valueDatum;
+    
+    CHECK_NOT_NULL_VOID(dbf, env);
+    
+    if ( !arrayToDatum(env, keyArray, &keyDatum)
+	 || !arrayToDatum(env, valueArray, &valueDatum) ) {
+	NULL_PTR_EXCEPTION(env);
+	return;
+    }
+
+    gdbm_store(JLONG_TO_DBF(dbf), keyDatum, valueDatum, 
+	       replace ? GDBM_REPLACE : 0);
+
+    releaseArrayAbort(env, keyArray, &keyDatum);
+    releaseArrayAbort(env, valueArray, &valueDatum);
+
+    if ( gdbm_errno != GDBM_NO_ERROR )
+	GDBM_EXCEPTION(env);
+}
+
+
+
+JNIEXPORT void JNICALL 
+Java_au_com_pharos_gdbm_GdbmFile_gdbm_1delete
+   (JNIEnv *env, jobject obj, jlong dbf, jbyteArray keyArray)
+{
+    datum 	keyDatum;
+
+    CHECK_NOT_NULL_VOID(dbf, env);
+
+    if (!arrayToDatum(env, keyArray, &keyDatum)) {
+	NULL_PTR_EXCEPTION(env);
+	return;
+    }
+
+    gdbm_delete(JLONG_TO_DBF(dbf), keyDatum);
+
+    releaseArrayAbort(env, keyArray, &keyDatum);
+    
+    if ( gdbm_errno != GDBM_NO_ERROR )
+	GDBM_EXCEPTION(env);
+}
+
+
+
+JNIEXPORT jstring JNICALL 
+Java_au_com_pharos_gdbm_GdbmFile_gdbm_1getversion
+  (JNIEnv *env, jclass cls)
+{
+    return (*env)->NewStringUTF(env, gdbm_version);
+}
+
+
+JNIEXPORT jstring JNICALL 
+Java_au_com_pharos_gdbm_GdbmFile_gdbm_1wrapperVersion
+  (JNIEnv *env, jclass cls)
+{
+    return (*env)->NewStringUTF(env, "JavaGDBM release 0005 built " __DATE__);
+}
+				
+
+
+
+JNIEXPORT void JNICALL 
+Java_au_com_pharos_gdbm_GdbmFile_gdbm_1reorganize
+  (JNIEnv *env, jobject obj, jlong dbf)
+{
+    CHECK_NOT_NULL_VOID(dbf, env);
+
+    gdbm_reorganize(JLONG_TO_DBF(dbf));
+
+    if ( gdbm_errno != GDBM_NO_ERROR )
+	GDBM_EXCEPTION(env);
+}
+
+
+
+JNIEXPORT void JNICALL 
+Java_au_com_pharos_gdbm_GdbmFile_gdbm_1close
+  (JNIEnv *env, jobject obj, jlong dbf)
+{
+    CHECK_NOT_NULL_VOID(dbf, env);
+
+    gdbm_close(JLONG_TO_DBF(dbf));
+
+    if ( gdbm_errno != GDBM_NO_ERROR )
+	GDBM_EXCEPTION(env);
+}
+
+
+
+JNIEXPORT void JNICALL 
+Java_au_com_pharos_gdbm_GdbmFile_gdbm_1sync
+  (JNIEnv *env, jobject obj, jlong dbf)
+{
+    CHECK_NOT_NULL_VOID(dbf, env);
+
+    gdbm_sync(JLONG_TO_DBF(dbf));
+
+    if ( gdbm_errno != GDBM_NO_ERROR )
+	GDBM_EXCEPTION(env);
+}
+
+
+
+
+/**********************************************************************
+ *
+ * Following are support functions which aid in interfacing C to 
+ * Java. */
+
+/** Create a new Java byte array from a GDBM datum, and return a
+ * pointer thereto.  */
+
+jbyteArray datumToArray(JNIEnv *env, datum *fromDatum) 
+{
+    jbyteArray toArray;
+
+    if (!fromDatum || !fromDatum->dptr)
+	return 0;
+
+    toArray = (*env)->NewByteArray(env, fromDatum->dsize);
+    ASSERT(toArray);
+    (*env)->SetByteArrayRegion(env, toArray, 
+			       0, fromDatum->dsize, fromDatum->dptr);
+    
+    return toArray;
+}
+
+/** Convert a Java byte array to a GDBM datum.
+ *
+ * The Java array is pinned or copied for use in the datum, and must
+ * be released after use by releaseBytes. 
+ *
+ * Returns true if the array is non-null and could be pinned.  Otherwise,
+ * returns false. 
+ */
+int arrayToDatum(JNIEnv *env, jbyteArray fromArray, datum *toDatum)
+{
+    if (fromArray) {
+	toDatum->dptr = (*env)->GetByteArrayElements(env, fromArray, 0);
+	toDatum->dsize = (*env)->GetArrayLength(env, fromArray);
+	return (int) toDatum->dptr;
+    }
+    else 
+	return 0;
+}
+
+/** Release a byte array pinned or copied for use in a datum. */
+void releaseArray(JNIEnv *env, jbyteArray array, datum *fromDatum) 
+{
+    ASSERT(fromDatum->dptr);
+    (*env)->ReleaseByteArrayElements(env, array, fromDatum->dptr, 0);
+    fromDatum->dptr = 0;	/* no longer valid */
+}
+
+/** Release a byte array pinned or copied for use in a datum, aborting 
+ * any changes.  This potentially saves the runtime from having to 
+ * copy back an unchanged array. */
+void releaseArrayAbort(JNIEnv *env, jbyteArray array, datum *fromDatum) 
+{
+    ASSERT(fromDatum->dptr);
+    (*env)->ReleaseByteArrayElements(env, array, fromDatum->dptr, 
+				     JNI_ABORT);
+    fromDatum->dptr = 0;	/* no longer valid */
+}
+
+
+/** Throw a null pointer exception. */
+void nullPtrException(JNIEnv *env, const char *file, int line) 
+{
+    jclass exClass;
+    char reason[1024];
+    sprintf(reason, "Null pointer exception in GDBM wrapper (%s:%d)",
+	    file, line);
+    
+    exClass = (*env)->FindClass(env, "java/lang/NullPointerException");
+    ASSERT(exClass);
+
+    (*env)->ThrowNew(env, exClass, reason);
+}
+
+/** Translate the GDBM error into throw a Java exception, and throw
+ * same. 
+ *
+ * TODO: Throw different classes of exceptions depending on what the 
+ * underlying error is. 
+ */
+void gdbmException(JNIEnv *env, const char *file, int line) {
+    jclass exClass;
+    static char reason[1500];
+    static char srcLocation[500];
+
+    exClass = (*env)->FindClass(env, "au/com/pharos/gdbm/GdbmException");
+    ASSERT(exClass);
+
+    strncpy(reason, gdbm_strerror(gdbm_errno), 500);
+    sprintf(srcLocation, " (%s:%d)", file, line);
+
+    /* If the error code suggests that an OS or stdio error may have occurred,
+     * include supplementary information from errno. */
+    switch (gdbm_errno) {
+    case GDBM_FILE_OPEN_ERROR:
+    case GDBM_FILE_WRITE_ERROR:
+    case GDBM_FILE_SEEK_ERROR:
+    case GDBM_FILE_READ_ERROR:
+    case GDBM_MALLOC_ERROR:
+    case GDBM_REORGANIZE_FAILED:
+	strcat(reason, ": ");
+	strncat(reason, strerror(errno), 490);
+	strcat(reason, "?");
+    default:
+	/* errno is probably not useful */
+	;
+    }
+    
+    strncat(reason, srcLocation, 495);
+    gdbm_errno = GDBM_NO_ERROR;	/* this one has been handled */
+    (*env)->ThrowNew(env, exClass, reason);    
+}
+
+/* 
+ * Local variables:
+ * c-basic-offset: 4
+ * End:
+ */
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/jni/win32.mak
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/jni/win32.mak	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/jni/win32.mak	(revision 13928)
@@ -0,0 +1,72 @@
+###########################################################################
+#
+# win32 makefile -- javagdbm\jni
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999  The New Zealand Digital Library Project
+#
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+JAVAGDBMHOME = ..
+ 
+GSDLHOME= $(GSDL3HOME)\gs2build
+GDBMHOME = $(GSDLHOME)\packages\windows\gdbm\gdbm
+
+AR = lib
+CC = cl
+CPPFLAGS = 
+
+DEFS = -D__WIN32__ -DHAVE_STRING_H
+
+INCLUDES = -I"$(GDBMHOME)" -I. \
+           -I"$(JAVA_HOME)\include" -I"$(JAVA_HOME)\include\win32"           
+
+COMPILE = $(CC) -c $(CPPFLAGS) $(DEFS) $(INCLUDES)
+
+.SUFFIXES:
+.SUFFIXES: .c .obj
+.c.obj:
+	$(COMPILE) $<
+
+ANSI2KNR = 
+o = .obj
+ 
+HEADERS = \
+    GdbmFile.h
+
+SOURCES = \
+    gdbmjava.c
+
+OBJECTS = \
+    gdbmjava$o   "$(GDBMHOME)\gdbm.lib"
+ 
+all : compile link
+
+compile:
+        $(COMPILE) gdbmjava.c
+
+link:
+        $(CC) -MD -LD $(OBJECTS) -Fegdbmjava.dll
+
+install: 
+        copy gdbmjava.dll "$(GSDL3HOME)\lib\jni"
+
+clean:
+	del *$o 
Index: /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/winMake.bat
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/winMake.bat	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/src/packages/javagdbm/winMake.bat	(revision 13928)
@@ -0,0 +1,29 @@
+@echo off
+
+set MAKE=nmake
+set MAKE_OPTIONS=/f
+
+if ""%1"" == """" goto all
+if ""%1"" == ""compile"" goto go
+if ""%1"" == ""install"" goto go
+if ""%1"" == ""clean"" goto go
+
+:unknown
+	echo Error: Unrecognized argument %1.
+	goto done
+
+:go
+	if ""%2"" == ""javaonly"" goto java
+
+:all
+	cd jni
+	%MAKE% %MAKE_OPTIONS% win32.mak %1
+	cd ..
+
+:java
+	cd java
+	call winMake.bat %1
+	cd ..
+	goto done
+
+:done
Index: /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/AbstractBrowse.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/AbstractBrowse.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/AbstractBrowse.properties	(revision 13928)
@@ -0,0 +1,3 @@
+ClassifierBrowse.name=Browse
+ClassifierBrowse.description=Browse pre-defined classification hierarchies
+ClassifierBrowse.classifier_help:Browse by {0}
Index: /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/AbstractGS2FieldSearch.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/AbstractGS2FieldSearch.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/AbstractGS2FieldSearch.properties	(revision 13928)
@@ -0,0 +1,31 @@
+#query params
+param.level=Granularity to search at
+param.sortBy=Document display order
+param.sortBy.1=ranked
+param.sortBy.0=natural
+param.fqv=Word or phrase 
+param.fqf=in field
+param.fqf.all=All fields
+param.fqs=stem
+param.fqc=case
+param.fqk=
+param.fqk.0=AND
+param.fqk.1=OR
+param.fqk.2=NOT
+param.fqa=accent
+
+#levels - this should go somewhere more central perhaps?
+level.document=Document
+level.Doc=Document
+level.section=Section
+level.Sec=Section
+level.paragraph=Paragraph
+level.Para=Paragraph
+
+#service stuff
+FieldQuery.name=Form Search
+FieldQuery.description=Simple fielded search
+FieldQuery.submit=Search
+AdvancedFieldQuery.name=Advanced Search
+AdvancedFieldQuery.description=Advanced fielded searching
+AdvancedFieldQuery.submit=Search
Index: /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/AbstractSearch.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/AbstractSearch.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/AbstractSearch.properties	(revision 13928)
@@ -0,0 +1,21 @@
+#service stuff
+TextQuery.name=Text Search
+TextQuery.description=Full text and/or metadata search service
+TextQuery.submit=Search
+
+#compulsory query params
+param.index=Index to search in
+param.maxDocs=Maximum hits to return
+param.query=Query string
+param.hitsPerPage=Hits per page
+param.startPage=Start from page
+
+#optional params
+param.stem=Turn stemming 
+param.case=Turn casefolding 
+param.accent=Turn accentfolding 
+param.matchMode=Match
+param.matchMode.all=all
+param.matchMode.some=some
+param.boolean.on=on
+param.boolean.off=off
Index: /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/CrossCollectionSearch.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/CrossCollectionSearch.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/CrossCollectionSearch.properties	(revision 13928)
@@ -0,0 +1,6 @@
+TextQuery.name=Cross collection search
+TextQuery.submit=Search
+TextQuery.description=Search over multiple collections
+param.query=Query string
+param.collection=Collections to search in
+param.collection.all=All collections
Index: /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/GATEServices.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/GATEServices.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/GATEServices.properties	(revision 13928)
@@ -0,0 +1,11 @@
+# Service parameters
+param.annotationType=Annotation type
+param.annotationType.Address=Address
+param.annotationType.Date=Date
+param.annotationType.Location=Places
+param.annotationType.Organization=Organization
+param.annotationType.Person=People
+
+#service stuff
+GatePOSTag.name=Annotate document
+GatePOSTag.submit=Go
Index: /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/GS2Construct.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/GS2Construct.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/GS2Construct.properties	(revision 13928)
@@ -0,0 +1,67 @@
+#the params used by the services
+param.collection=Collection
+param.creator=Creator's email address
+param.collTitle=Collection title
+param.collAbout=Collection description
+param.buildType=Building type
+param.buildType.mg=MG
+param.buildType.mgpp=MGPP
+
+#service names and submit buttons
+DeleteCollection.name=Delete
+DeleteCollection.description=Delete a collection 
+DeleteCollection.submit=Delete
+NewCollection.name=Create
+NewCollection.description=Create a new collection
+NewCollection.submit=Create
+ImportCollection.name=Import
+ImportCollection.description=Import a collection: take the original documents and convert them to Greenstone internal format
+ImportCollection.submit=Import
+BuildCollection.name=Build
+BuildCollection.description=Build a collection: create the indexes and browsable hierarchies.
+BuildCollection.submit=Build
+ActivateCollection.name=Activate
+ActivateCollection.description=Activate a collection: Replace the old built collection with the new version
+ActivateCollection.submit=Activate
+ReloadCollection.name=Reload
+ReloadCollection.description=Reload a collection into the library
+ReloadCollection.submit=Reload
+
+#error messages used by each service - {0} is the collection name
+#DeleteCollection######
+delete.configure_error=Couldn't deactivate {0} from the library.
+delete.delete_error=Couldn't delete {0}.
+delete.success=Collection {0} deleted successfully.
+delete.exists_error=Collection {0} did not exist and couldn't be deleted.
+
+#NewCollection######
+new.success=Collection {0} created successfully.
+
+#ImportCollection#####
+import.success=Collection {0} imported successfully.
+
+#BuildCollection#####
+build.success=Collection {0} built successfully.
+
+#ActivateCollection#####
+activate.build_dir_error=Collection {0} had no building directory: couldn't be activated.
+activate.build_config_error=Collection {0} had no building config file: couldn't be activated.
+activate.rm_index_error=Couldn't remove the index directory.
+activate.rename_building_error=Couldn't rename building to index.
+activate.success=Collection {0} activated successfully.
+
+#ReloadCollection#####
+reload.success=Collection {0} reloaded successfully.
+reload.activate_error=Couldn't activate collection {0} in the library.
+
+#general stuff
+general.process_id_error=Invalid process id.
+general.configure_constructor_error=Couldn't configure the collection constructor.
+general.process_start=Starting process...
+
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/GS2Construct_fr.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/GS2Construct_fr.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/GS2Construct_fr.properties	(revision 13928)
@@ -0,0 +1,51 @@
+#the params used by the services
+param.collection=Collection <fr>
+param.creator=Creator's email address <fr>
+param.collectionName=Name of the collection <fr>
+
+#service names and submit buttons
+DeleteCollection.name=Delete a collection <fr>
+DeleteCollection.submit=Delete <fr>
+
+#messages for each service
+#DeleteCollection######
+delete.deactivate_error=Couldn't deactivate {0} from the library. <fr>
+delete.delete_error=Couldn't delete {0}. <fr>
+delete.success=Collection {0} deleted successfully. <fr>
+delete.submit=Delete <fr>
+
+#NewCollection######
+new.success=Collection {0} created successfully. <fr>
+new.submit=Create <fr>
+
+#ImportCollection#####
+import.success=Collection {0} imported successfully. <fr>
+import.submit=Import <fr>
+
+#BuildCollection#####
+build.success=Collection {0} built successfully. <fr>
+build.submit=Build <fr>
+
+#ActivateCollection#####
+#activate.build_dir_error=Collection {0} had no building directory: couldn't be activated. <fr>
+activate.build_config_error=Collection {0} had no building config file: couldn't be activated. <fr>
+activate.rm_index_error=Couldn't remove the index directory. <fr>
+activate.rename_building_error=Couldn't rename building to index. <fr>
+activate.success=Collection {0} activated successfully. <fr>
+activate.submit=Activate <fr>
+
+#ReloadCollection#####
+reload.success=Collection {0} reloaded successfully. <fr>
+reload.activate_error=Couldn't activate collection {0} in the library. <fr>
+reload.submit=Reload <fr>
+
+
+
+
+
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/GS2LuceneSearch.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/GS2LuceneSearch.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/GS2LuceneSearch.properties	(revision 13928)
@@ -0,0 +1,2 @@
+param.sortBy=Sort search results by
+param.sortBy.rank=rank
Index: /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/IViaSearch.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/IViaSearch.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/IViaSearch.properties	(revision 13928)
@@ -0,0 +1,7 @@
+#query params
+param.index.au=Author
+param.index.ti=Title
+param.index.kw=Keywords
+param.index.su=Subject
+param.index.de=Description
+param.index.fu=Full Text
Index: /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/LuceneSearch.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/LuceneSearch.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/LuceneSearch.properties	(revision 13928)
@@ -0,0 +1,5 @@
+TextQuery.name=Search
+TextQuery.submit=Search
+TextQuery.description=A simple XML search service
+
+param.query=Enter your query string
Index: /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/MapRetrieve.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/MapRetrieve.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/MapRetrieve.properties	(revision 13928)
@@ -0,0 +1,3 @@
+#service stuff
+MapRetrieve.name=Maps Retrieved
+DocumentMetadataRetrieve.name=Retrieved Documents
Index: /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/MapSearch.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/MapSearch.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/MapSearch.properties	(revision 13928)
@@ -0,0 +1,4 @@
+#service stuff
+TextQuery.name=Map Search
+TextQuery.description=Search for placenames in maps
+TextQuery.submit=Search
Index: /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/PhindPhraseBrowse.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/PhindPhraseBrowse.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/PhindPhraseBrowse.properties	(revision 13928)
@@ -0,0 +1,2 @@
+PhindApplet.name=Phrase browse
+PhindApplet.description=Java applet that allows you to browse extracted phrase hierarchies
Index: /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/TestServlet.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/TestServlet.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/TestServlet.java	(revision 13928)
@@ -0,0 +1,15 @@
+import java.io.*;
+import javax.servlet.*;
+import javax.servlet.http.*;
+
+/** a test servlet to make sure the servlet container is working */
+public class TestServlet extends HttpServlet {
+
+    public void doGet(HttpServletRequest request,
+		      HttpServletResponse response)
+	throws ServletException, IOException {
+
+	PrintWriter out = response.getWriter();
+	out.println("Hello Greenstone!");
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/Visualizer.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/Visualizer.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/Visualizer.properties	(revision 13928)
@@ -0,0 +1,2 @@
+VisApplet.name=Query Visualizer
+VisApplet.description=Visualize your query...
Index: /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/config_format.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/config_format.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/config_format.xsl	(revision 13928)
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:xslt="output.xsl"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:gsf="http://www.greenstone.org/configformat"
+  extension-element-prefixes="java">
+  
+  <xsl:output method="xml"/>
+  <xsl:namespace-alias
+    stylesheet-prefix="xslt" result-prefix="xsl"/>
+
+
+  <xsl:template match="format">
+    <format hello="yes">
+      <xsl:apply-templates/>
+    </format>
+  </xsl:template>
+  
+  <xsl:template match="gsf:template">
+    <xslt:template>
+      <xsl:copy-of select="@*"/>
+      <xsl:attribute name="priority">2</xsl:attribute> 
+      <xsl:if test=".//gsf:link/@type">
+	<xslt:param name="serviceName">service-name</xslt:param>
+      </xsl:if>
+      <xsl:if test=".//gsf:link">
+	<xslt:param name="collName">coll-name</xslt:param>
+	<xslt:variable name='library' select='ancestor::page/config/library_name'/>
+      </xsl:if>
+      <xsl:apply-templates/>
+    </xslt:template>
+  </xsl:template>
+  
+  <xsl:template match="gsf:link">
+    <xsl:choose>
+      <xsl:when test="@type='classifier'">
+	<a><xslt:attribute name='href'><xslt:value-of select='$library'/>?a=b&amp;s=<xslt:value-of select='$serviceName'/>&amp;c=<xslt:value-of select='$collName'/>&amp;cl=<xslt:value-of select='@nodeID'/><xslt:if test="classifierNode|documentNode">.pr</xslt:if></xslt:attribute>
+	  <xsl:apply-templates/>
+	</a>
+      </xsl:when>
+      <xsl:otherwise> <!-- a document link -->
+	<a><xsl:attribute name="href">{$library}?a=d&amp;c={$collName}&amp;d={@nodeID}</xsl:attribute>
+	  <xsl:apply-templates/>
+	</a>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template match="gsf:icon">
+    <xsl:choose>
+      <xsl:when test="@type='classifier'">
+	<img src='interfaces/default/images/bshelf.gif' border='0' width='20' height='16' />
+      </xsl:when>
+      <xsl:otherwise>
+	<xslt:apply-templates select="." mode="displayNodeIcon"/>
+	<!--
+	<img src='interfaces/default/images/book.gif' width='18' height='11' border='0'/>-->
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template match="gsf:metadata">    
+    <xslt:value-of><xsl:attribute name="select">metadataList/metadata[@name='<xsl:value-of select="@name"/>']</xsl:attribute></xslt:value-of>
+  </xsl:template>
+
+<!--
+  <xsl:template match="gsf:text">
+TODO
+  </xsl:template>
+-->
+  <xsl:template match="*">
+    <xsl:copy>
+      <xsl:copy-of select="@*"/>
+      <xsl:apply-templates/>
+    </xsl:copy>
+  </xsl:template>
+
+
+<!-- copied from style for now-->
+<!-- Display the appropriate image, depending on the node type -->
+<xsl:template match="documentNode" mode="displayNodeIcon">
+
+  <!-- Root node: book icon (open or closed) -->
+  <xsl:if test="@nodeType='root'">
+    <xsl:choose>
+      <xsl:when test="documentNode">
+	<img border="0" width="28" height="23"
+	     src="interfaces/default/images/openbook.gif"
+	     alt="Close this book"/>
+      </xsl:when>
+      <xsl:otherwise>
+	<img border="0" width="18" height="11"
+	     src="interfaces/default/images/book.gif"
+	     alt="Open this document and view contents"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:if>
+
+  <!-- Interior node: folder icon (open or closed) -->
+  <xsl:if test="@nodeType='interior'">
+    <xsl:choose>
+      <xsl:when test="documentNode">
+	<img border="0" width="23" height="15"
+	     src="interfaces/default/images/openfldr.gif"
+	     alt="Close this folder"/>
+      </xsl:when>
+      <xsl:otherwise>
+	<img border="0" width="23" height="15"
+	     src="interfaces/default/images/clsdfldr.gif"
+	     alt="Open this folder and view contents"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:if>
+
+  <!-- Leaf node: page icon -->
+  <xsl:if test="@nodeType='leaf'">
+    <img border="0" width="16" height="21"
+	 src="interfaces/default/images/itext.gif"
+	 alt="View the document"/>
+  </xsl:if>
+</xsl:template>
+
+</xsl:stylesheet>
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/interface_classic.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/interface_classic.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/interface_classic.properties	(revision 13928)
@@ -0,0 +1,110 @@
+nzdl=New Zealand Digital Library
+home_b=HOME
+pref_b=PREFERENCES
+help_b=HELP
+# text for the titles (in the page header)
+help_t=help
+pref_t=preferences
+about_t=about
+search_t=search
+phrases_t=phrases
+texticonpdf=View the PDF document
+texticonps=View the PostScript document
+texticonrtf=View the RTF document
+texticonmsword=View the Microsoft Word document
+texticonppt=View the PowerPoint document
+texticonxls=View the Microsoft Excel document
+#################
+# home page
+#################
+home.feedback=Feedback
+home.aboutgs=About<br/>Greenstone
+home.people=People
+home.research=Research
+home.projects=Projects
+home.software=Software
+home.publications=Publications
+home.coll_warning=This interface is designed to look and behave like the classic Greenstone 2 style interface. It makes assumptions about the services that a collection might have: it looks for the TextQuery/FormQuery/AdvancedFormQuery and ClassifierBrowse services. If a query service is present, a search button is added to the navigation bar. If more than one query service is available they come under the same button, and are selectable via the preferences page. If ClassifierBrowse is present, the classifiers provided by that service are displayed on the navigation bar instead of the service itself. Any other services are ignored. Greenstone 2 collections work exactly as they would in a Greenstone 2 library, while some other collections do not work properly.
+##################
+# about page
+##################
+aboutpage=About page
+#about.services=Services available:
+#about.description=Description:
+about.aboutcoll=About this collection
+about.howtofind=How to find information in the {0} collection
+##################
+# prefs page
+##################
+pref.searchpref=Search preferences
+pref.prespref=Presentation preferences
+pref.interfacelang=Interface language:
+pref.encoding=Encoding:
+##################
+# query page
+##################
+query.wordcount=Word count:
+query.nodocsmatch=No documents matched the query.
+query.onedocsmatch=One document matched the query.
+query.manydocsmatch={0} documents matched the query.
+query.matches=Matches
+query.results=results
+##################
+# help page
+##################
+help.numbrowseoptions=There are {0} ways to find information in this collection:
+help.simplehelpheading=How to find information in the {0} collection
+help.Searchshort=search for particular words
+help.Searchlong=<p />You can <i>search for particular words</i> that appear in the text from the "search" page. This is the first page that comes up when you begin, and can be reached from other pages by pressing the <i>search</i> button.
+help.Titleshort=access publications by title
+help.Titlelong=<p />You can <i>access publications by title</i> by pressing the <i>titles</i> button.  This brings up a list of books in alphabetic order.
+help.Organizationshort=access publications by organisation
+help.Organizationlong=<p />You can <i>access publications by organisation</i> by pressing the <i>organisations</i> button.  This brings up a list of organisations.
+help.Organisationshort=access publications by organisation
+help.Organisationlong=<p />You can <i>access publications by organisation</i> by pressing the <i>organisations</i> button.  This brings up a list of organisations.
+help.HowToshort=access publications by "how to" listing
+help.HowTolong=<p />You can <i>access publications by "how to" listing</i> by pressing the <i>how to</i> button.  This brings up a list of how to strings.
+help.Howtoshort=access publications by "how to" listing
+help.Howtolong=<p />You can <i>access publications by "how to" listing</i> by pressing the <i>how to</i> button.  This brings up a list of how to strings.
+help.Creatorshort=access publications by author
+help.Creatorlong=<p />You can <i>access publications by author</i> by pressing the <i>authors a-z</i> button.  This brings up a list of books, sorted by author name.  
+help.Subjectshort=access publications by subject
+help.Subjectlong=<p/>You can <i>access publications by subject</i> by pressing the <i>subjects</i> button.  This brings up a list of subjects, represented by bookshelves.
+help.Topicshort=access publications by topic
+help.Topiclong=<p>You can <i>access publications by topic</i> by pressing the <i>topic</i> button.  This brings up a list of topics to browse.  
+help.Toshort=access publications by To field
+help.Tolong=<p>You can <i>access publications by To field</i> by pressing the <i>to</i> button.  This brings up a list of addressees.  
+help.Fromshort=access publications by From field
+help.Fromlong=<p>You can <i>access publications by From field</i> by pressing the <i>from</i> button.  This brings up a list of senders.  
+help.Seriesshort=access publications by series
+help.Serieslong=<p>You can <i>access publications by series</i> by pressing the <i>series</i> button.  This brings up a list of those series which are currently in the collection.  
+help.Dateshort=access publications by date
+help.Datelong=<p>You can <i>access publications by date</i> by pressing the <i>dates</i> button.  This brings up a list of all the issues, sorted chronologically.  
+help.Browseshort=browse publications
+help.Browselong=<p>You can <i>browse publications</i> by pressing the <i>browse</i> button.  
+help.Peopleshort=access publications by people
+help.Peoplelong=<p>You can <i>access publications by people</i> by pressing the <i>people a-z</i> button.  This brings up a list of entries, sorted by surname.  
+help.Languageshort=access publications by language
+help.Languagelong=<p>You can <i>access publications by language</i> by pressing the <i>languages</i> button.  This brings up a list of entries, sorted by language.  
+help.Acronymshort=access publications by acronym
+help.Acronymlong=<p>You can <i>access publications by acronym occurrence</i> bypressing the <i>acronyms</i> button.  This brings up a list of the acronyms, and the places that they occur.  
+help.Phraseshort=browse phrases occurring in publications
+help.Phraselong=<p>You can <i>browse phrases occurring in publications</i> by pressing the <i>phrases</i> button.  This uses the phind phrase browser.  
+help.Artistshort=access publications by artist
+help.Artistlong=<p>You can <i>access publications by artist</i> by pressing the <i>artists</i> button.  This brings up a list of entries, sorted by artist name.  
+help.Sourceshort=access publications by filename
+help.Sourcelong=<p>You can <i>access publications by filename</i> by pressing the <i>filenames</i> button.  This brings up a list of entries, sorted by original filename.  
+help.Keywordshort=access publications by keyword
+help.Keywordlong=<p>You can <i>access publications by keyword</i> by pressing the <i>keywords</i> button.  This brings up a list of keywords. 
+help.Volumeshort=access publications by volume
+help.Volumelong=<p>You can <i>access publications by volume</i> by pressing the <i>volumes</i> button. This brings up a list of volumes. 
+help.Captionsshort=access publications by caption
+help.Captionslong=<p>You can <i>access publications by caption</i> by pressing the <i>captions</i> button. This brings up a list of captions. 
+help.Countriesshort=access publications by country
+help.Countrieslong=<p>You can <i>access publications by country</i> by pressing the <i>countries</i> button. This brings up a list of countries. 
+help.short=undefined classification
+help.defaultshort=undefined classification
+help.long=<p>Click on the <i>unknown</i> button to browse publications (listing is sorted by an unknown field).  
+help.defaultlong=<p>Click on the <i>unknown</i> button to browse publications (listing is sorted by an unknown field).  
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/interface_default.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/interface_default.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/interface_default.properties	(revision 13928)
@@ -0,0 +1,71 @@
+gsdl=Greenstone Digital Library Software
+gs3power=powered by greenstone3
+# the buttons
+home_b=HOME
+help_b=HELP
+pref_b=PREFERENCES
+# tool tips for the buttons
+home_tip=Library home page
+help_tip=Help pages
+pref_tip=Change your interface preferences
+# page titles
+help_t=help
+pref_t=preferences
+aboutpage=About page
+textframebrowser=You must have a frame enabled browser to view this.
+#######################
+# query page
+########################
+about.noservices=There are no services available for this collection.
+about.services=Services available:
+about.servicehelp=You can access the services by clicking on the buttons below or on the names on the navigation bar. The navigation bar is persistent across all pages in the collection.
+#about.description=Description:
+about.metadata=Metadata:
+
+#######################
+# query page
+########################
+query.wordcount=Word count:
+query.nodocsmatch=No documents matched the query.
+query.onedocsmatch=One document matched the query.
+query.manydocsmatch={0} documents matched the query.
+query.atleastdocsmatch=At least {0} documents matched the query.
+query.docsreturned={0} documents returned.
+query.matches=Matches
+query.results=Results
+###############
+# document page
+##################
+document.pageof=Page {0} of {1}.
+document.pages={0} pages.
+document.gotopage=Go to page
+
+##################
+# prefs page
+##################
+pref.searchpref=Search preferences
+pref.prespref=Presentation preferences
+pref.interfacelang=Interface language:
+pref.encoding=Encoding:
+pref.hitsperpage=Number of hits per page:
+pref.all=all
+pref.set_prefs=Set preferences
+pref.berrybasket=Berry basket
+pref.berrybasket.on=on
+pref.berrybasket.off=off
+
+
+##################
+# docs page
+##################
+doc.expand_doc_b=EXPAND<br />DOCUMENT
+doc.expand_doc_tip=Display the entire document
+doc.contract_doc_b=CONTRACT<br />DOCUMENT
+doc.contract_doc_tip=Return to previously selected section
+doc.expand_contents_b=EXPAND<br />CONTENTS 
+doc.expand_contents_tip=Expand only the table of contents
+doc.contract_contents_b=CONTRACT<br />CONTENTS
+doc.contract_contents_tip=Collapse the table of contents
+doc.detach_page_b=DETACH<br />PAGE
+doc.detach_page_tip=Open this page in a new window
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/interface_default_fr.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/interface_default_fr.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/interface_default_fr.properties	(revision 13928)
@@ -0,0 +1,6 @@
+nzdl=Bibliothèque Numérique Greenstone
+home=ACCUEIL
+aboutpage=About page (fr)
+about.services=Services available (fr):
+about.description=Description (fr):
+query.matches=Résultats
Index: /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/interface_nzdl.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/interface_nzdl.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/interface_nzdl.properties	(revision 13928)
@@ -0,0 +1,108 @@
+nzdl=New Zealand Digital Library
+home_b=HOME
+pref_b=PREFERENCES
+help_b=HELP
+# text for the titles (in the page header)
+home_t=home
+help_t=help
+pref_t=preferences
+about_t=about
+search_t=search
+phrases_t=phrases
+#################
+# home page
+#################
+home.feedback=Feedback
+home.aboutgs=About<br/>Greenstone
+home.people=People
+home.research=Research
+home.projects=Projects
+home.software=Software
+home.publications=Publications
+##################
+# about page
+##################
+aboutpage=About page
+#about.services=Services available:
+#about.description=Description:
+about.aboutcoll=About this collection
+about.howtofind=How to find information in the {0} collection
+##################
+# prefs page
+##################
+pref.searchpref=Search preferences
+pref.prespref=Presentation preferences
+pref.interfacelang=Interface language:
+pref.encoding=Encoding:
+##################
+# query page
+##################
+query.wordcount=Word count:
+query.nodocsmatch=No documents matched the query.
+query.onedocsmatch=One document matched the query.
+query.manydocsmatch={0} documents matched the query.
+query.matches=Matches
+query.results=results
+##################
+# help page
+##################
+help.numbrowseoptions=There are {0} ways to find information in this collection:
+help.simplehelpheading=How to find information in the {0} collection
+help.Searchshort=search for particular words
+help.Searchlong=<p />You can <i>search for particular words</i> that appear in the text from the "search" page. This is the first page that comes up when you begin, and can be reached from other pages by pressing the <i>search</i> button.
+help.Titleshort=access publications by title
+help.Titlelong=<p />You can <i>access publications by title</i> by pressing the <i>titles</i> button.  This brings up a list of books in alphabetic order.
+help.Organizationshort=access publications by organisation
+help.Organizationlong=<p />You can <i>access publications by organisation</i> by pressing the <i>organisations</i> button.  This brings up a list of organisations.
+help.Organisationshort=access publications by organisation
+help.Organisationlong=<p />You can <i>access publications by organisation</i> by pressing the <i>organisations</i> button.  This brings up a list of organisations.
+help.HowToshort=access publications by "how to" listing
+help.HowTolong=<p />You can <i>access publications by "how to" listing</i> by pressing the <i>how to</i> button.  This brings up a list of how to strings.
+help.Howtoshort=access publications by "how to" listing
+help.Howtolong=<p />You can <i>access publications by "how to" listing</i> by pressing the <i>how to</i> button.  This brings up a list of how to strings.
+help.Creatorshort=access publications by author
+help.Creatorlong=<p />You can <i>access publications by author</i> by pressing the <i>authors a-z</i> button.  This brings up a list of books, sorted by author name.  
+help.Subjectshort=access publications by subject
+help.Subjectlong=<p/>You can <i>access publications by subject</i> by pressing the <i>subjects</i> button.  This brings up a list of subjects, represented by bookshelves.
+help.Topicshort=access publications by topic
+help.Topiclong=<p>You can <i>access publications by topic</i> by pressing the <i>topic</i> button.  This brings up a list of topics to browse.  
+help.Toshort=access publications by To field
+help.Tolong=<p>You can <i>access publications by To field</i> by pressing the <i>to</i> button.  This brings up a list of addressees.  
+help.Fromshort=access publications by From field
+help.Fromlong=<p>You can <i>access publications by From field</i> by pressing the <i>from</i> button.  This brings up a list of senders.  
+help.Seriesshort=access publications by series
+help.Serieslong=<p>You can <i>access publications by series</i> by pressing the <i>series</i> button.  This brings up a list of those series which are currently in the collection.  
+help.Dateshort=access publications by date
+help.Datelong=<p>You can <i>access publications by date</i> by pressing the <i>dates</i> button.  This brings up a list of all the issues, sorted chronologically.  
+help.Browseshort=browse publications
+help.Browselong=<p>You can <i>browse publications</i> by pressing the <i>browse</i> button.  
+help.Peopleshort=access publications by people
+help.Peoplelong=<p>You can <i>access publications by people</i> by pressing the <i>people a-z</i> button.  This brings up a list of entries, sorted by surname.  
+help.Languageshort=access publications by language
+help.Languagelong=<p>You can <i>access publications by language</i> by pressing the <i>languages</i> button.  This brings up a list of entries, sorted by language.  
+help.Acronymshort=access publications by acronym
+help.Acronymlong=<p>You can <i>access publications by acronym occurrence</i> bypressing the <i>acronyms</i> button.  This brings up a list of the acronyms, and the places that they occur.  
+help.Phraseshort=browse phrases occurring in publications
+help.Phraselong=<p>You can <i>browse phrases occurring in publications</i> by pressing the <i>phrases</i> button.  This uses the phind phrase browser.  
+help.Artistshort=access publications by artist
+help.Artistlong=<p>You can <i>access publications by artist</i> by pressing the <i>artists</i> button.  This brings up a list of entries, sorted by artist name.  
+help.Sourceshort=access publications by filename
+help.Sourcelong=<p>You can <i>access publications by filename</i> by pressing the <i>filenames</i> button.  This brings up a list of entries, sorted by original filename.  
+help.Keywordshort=access publications by keyword
+help.Keywordlong=<p>You can <i>access publications by keyword</i> by pressing the <i>keywords</i> button.  This brings up a list of keywords. 
+help.Volumeshort=access publications by volume
+help.Volumelong=<p>You can <i>access publications by volume</i> by pressing the <i>volumes</i> button. This brings up a list of volumes. 
+help.Captionsshort=access publications by caption
+help.Captionslong=<p>You can <i>access publications by caption</i> by pressing the <i>captions</i> button. This brings up a list of captions. 
+help.Countriesshort=access publications by country
+help.Countrieslong=<p>You can <i>access publications by country</i> by pressing the <i>countries</i> button. This brings up a list of countries. 
+help.short=undefined classification
+help.defaultshort=undefined classification
+help.long=<p>Click on the <i>unknown</i> button to browse publications (listing is sorted by an unknown field).  
+help.defaultlong=<p>Click on the <i>unknown</i> button to browse publications (listing is sorted by an unknown field).  
+#################################
+#stuff for individual collections
+#################################
+collect.SearchBySender=search by sender
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/metadata_names.properties
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/metadata_names.properties	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/classes/metadata_names.properties	(revision 13928)
@@ -0,0 +1,36 @@
+Subject=Subject
+Subject.buttonname=subjects
+Title=Title
+Title.buttonname=titles
+Organisation=Organisation
+Organisation.buttonname=organisations
+Organization=Organisation
+Organization.buttonname=organisations
+Keyword=Keyword
+Keyword.buttonname=keywords
+HowTo=How To
+HowTo.buttonname=how to
+Howto=How To
+Howto.buttonname=how to
+Creator=Creator
+Creator.buttonname=creators
+Date=Date
+Date.buttonname=dates
+From=From
+From.buttonname=senders
+To=To
+To.buttonname=recipients
+Source=Source
+Source.buttonname=filenames
+Acronym=Acronym
+Acronym.buttonname=acronyms
+Topic=Topic
+Topic.buttonname=topics
+Collage=Collage
+Collage.buttonname=collage
+Countries=Countries
+Countries.buttonname=countries
+Language=Language
+Language.buttonname=languages
+Artist=Artist
+Artist.buttonname=artists
Index: /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/web.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/web.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/WEB-INF/web.xml	(revision 13928)
@@ -0,0 +1,286 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!DOCTYPE web-app 
+    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" 
+    "http://java.sun.com/dtd/web-app_2_3.dtd">
+
+<!-- this is based on a sample web.xml file provided by 
+http://jakarta.apache.org/tomcat/tomcat-4.0-doc/appdev/web.xml.txt
+-->
+<web-app>
+
+
+  <!-- General description of your web application -->
+  
+  <display-name>GSDL3</display-name>
+  <description>
+    Greenstone digital library version 3.
+  </description>
+  
+  
+  <!-- Context initialization parameters that define shared
+  String constants used within your application, which
+  can be customized by the system administrator who is
+  installing your application.  The values actually
+  assigned to these parameters can be retrieved in a
+  servlet or JSP page by calling:
+  
+  String value =
+  getServletContext().getInitParameter("name");
+  
+  where "name" matches the <param-name> element of
+  one of these initialization parameters.
+  
+  You can define any number of context initialization
+  parameters, including zero.
+  -->
+  
+  <context-param>
+    <param-name>webmaster</param-name>
+    <param-value>greenstone3@list.scms.waikato.ac.nz</param-value>
+    <description>
+      The EMAIL address of the administrator to whom questions
+      and comments about this application should be addressed.
+    </description>
+  </context-param>
+  
+
+  <!-- Servlet definitions for the servlets that make up
+  your web application, including initialization
+  parameters.  With Tomcat, you can also send requests
+  to servlets not listed here with a request like this:
+
+  http://localhost:8080/{context-path}/servlet/{classname}
+  
+  but this usage is not guaranteed to be portable.  It also
+  makes relative references to images and other resources
+  required by your servlet more complicated, so defining
+  all of your servlets (and defining a mapping to them with
+  a servlet-mapping element) is recommended.
+  
+  Servlet initialization parameters can be retrieved in a
+  servlet or JSP page by calling:
+  
+  String value =
+  getServletConfig().getInitParameter("name");
+  
+  where "name" matches the <param-name> element of
+  one of these initialization parameters.
+  
+  You can define any number of servlets, including zero.
+  -->
+
+  <servlet>
+    <servlet-name>tester</servlet-name>
+    <description>a test servlet</description>
+    <servlet-class>TestServlet</servlet-class>
+  </servlet>
+  
+  <servlet>
+    <servlet-name>library</servlet-name>
+    <description>standard gsdl3 library program: uses localsite and the default interface</description>
+    <servlet-class>org.greenstone.gsdl3.LibraryServlet</servlet-class>
+    <init-param>
+      <param-name>library_name</param-name>
+      <param-value>library</param-value>
+    </init-param>
+    <init-param>
+      <param-name>site_name</param-name>
+      <param-value>localsite</param-value>
+    </init-param>
+    <init-param>
+      <param-name>interface_name</param-name>
+      <param-value>default</param-value>
+    </init-param>
+    <init-param>
+      <param-name>default_lang</param-name>
+      <param-value>en</param-value>
+    </init-param>
+  </servlet>
+  
+  <servlet>
+    <servlet-name>gateway</servlet-name>
+    <description>gsdl3 library based on gateway site and default interface. It uses SOAP to talk to localsite</description>
+    <servlet-class>org.greenstone.gsdl3.LibraryServlet</servlet-class>
+    <init-param>
+      <param-name>library_name</param-name>
+      <param-value>gateway</param-value>
+    </init-param>
+    <init-param>
+      <param-name>site_name</param-name>
+      <param-value>gateway</param-value>
+    </init-param>
+    <init-param>
+      <param-name>interface_name</param-name>
+      <param-value>default</param-value>
+    </init-param>
+    <init-param>
+      <param-name>default_lang</param-name>
+      <param-value>en</param-value>
+    </init-param>
+  </servlet>
+  
+  <servlet>
+    <servlet-name>classic-library</servlet-name>
+    <description>Greenstone 2 lookalike library program: uses localsite with the classic interface</description>
+    <servlet-class>org.greenstone.gsdl3.LibraryServlet</servlet-class>
+    <init-param>
+      <param-name>library_name</param-name>
+      <param-value>classic</param-value>
+    </init-param>
+    <init-param>
+      <param-name>site_name</param-name>
+      <param-value>localsite</param-value>
+    </init-param>
+    <init-param>
+      <param-name>interface_name</param-name>
+      <param-value>classic</param-value>
+    </init-param>
+    <init-param>
+      <param-name>default_lang</param-name>
+      <param-value>en</param-value>
+    </init-param>
+    <init-param>
+      <param-name>params_class</param-name>
+      <param-value>NZDLParams</param-value>
+    </init-param>
+  </servlet>
+
+  <!-- axis servlets -->
+  <servlet>
+    <servlet-name>AxisServlet</servlet-name>
+    <display-name>Apache-Axis Servlet</display-name>
+    <servlet-class>
+        org.apache.axis.transport.http.AxisServlet
+    </servlet-class>
+  </servlet>
+
+  <servlet>
+    <servlet-name>AdminServlet</servlet-name>
+    <display-name>Axis Admin Servlet</display-name>
+    <servlet-class>
+        org.apache.axis.transport.http.AdminServlet
+    </servlet-class>
+    <load-on-startup>100</load-on-startup>
+  </servlet>
+
+  <servlet>
+    <servlet-name>SOAPMonitorService</servlet-name>
+    <display-name>SOAPMonitorService</display-name>
+    <servlet-class>
+        org.apache.axis.monitor.SOAPMonitorService
+    </servlet-class>
+    <init-param>
+      <param-name>SOAPMonitorPort</param-name>
+      <param-value>5001</param-value>
+    </init-param>
+    <load-on-startup>100</load-on-startup>
+  </servlet>
+    <!-- Define mappings that are used by the servlet container to
+         translate a particular request URI (context-relative) to a
+         particular servlet.  The examples below correspond to the
+         servlet descriptions above.  Thus, a request URI like:
+
+           http://localhost:8080/{contextpath}/graph
+
+         will be mapped to the "graph" servlet, while a request like:
+
+           http://localhost:8080/{contextpath}/saveCustomer.do
+
+         will be mapped to the "controller" servlet.
+
+	 Note: context path is determined by the servlet container - 
+	 in Tomcat, specified in server.xml -kjdon
+         You may define any number of servlet mappings, including zero.
+         It is also legal to define more than one mapping for the same
+         servlet, if you wish to.
+    -->
+    <!--
+    <servlet-mapping>
+      <servlet-name>controller</servlet-name>
+      <url-pattern>*.do</url-pattern>
+    </servlet-mapping>
+
+    <servlet-mapping>
+      <servlet-name>graph</servlet-name>
+      <url-pattern>/graph</url-pattern>
+    </servlet-mapping>
+    -->
+  
+  <servlet-mapping>
+    <servlet-name>tester</servlet-name>
+    <url-pattern>/testing</url-pattern>
+  </servlet-mapping>
+  
+  <servlet-mapping>
+    <servlet-name>library</servlet-name>
+    <url-pattern>/library</url-pattern>
+  </servlet-mapping>
+  
+  <servlet-mapping>
+    <servlet-name>gateway</servlet-name>
+    <url-pattern>/gateway</url-pattern>
+  </servlet-mapping>
+  
+  <servlet-mapping>
+    <servlet-name>classic-library</servlet-name>
+    <url-pattern>/classic</url-pattern>
+  </servlet-mapping>
+  
+  <!-- axis mappings -->
+  <servlet-mapping>
+    <servlet-name>AxisServlet</servlet-name>
+    <url-pattern>/servlet/AxisServlet</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>AxisServlet</servlet-name>
+    <url-pattern>*.jws</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>AxisServlet</servlet-name>
+    <url-pattern>/services/*</url-pattern>
+  </servlet-mapping>
+
+  <!-- uncomment this if you want to use the SOAPMonitorService. You will also 
+  need to copy the SOAPMonitorApplet*.class files from 
+  gsdl3/comms/soap/axis/web/WEB-INF/classes to the gsdl3/web directory. See the 
+  comms/soap/axis/docs/install.html Appendix for details about how to use this -->
+  <!--
+  <servlet-mapping>
+    <servlet-name>SOAPMonitorService</servlet-name>
+    <url-pattern>/SOAPMonitor</url-pattern>
+  </servlet-mapping>
+  -->
+  <!-- uncomment this if you want the admin servlet -->
+  <!--
+  <servlet-mapping>
+    <servlet-name>AdminServlet</servlet-name>
+    <url-pattern>/servlet/AdminServlet</url-pattern>
+  </servlet-mapping>
+  -->
+
+  <!-- Define the default session timeout for your application,
+  in minutes.  From a servlet or JSP page, you can modify
+  the timeout for a particular session dynamically by using
+  HttpSession.getMaxInactiveInterval(). -->
+
+  <session-config>
+    <session-timeout>30</session-timeout>    <!-- 30 minutes -->
+  </session-config>
+
+  <!-- axis mime-mappings -->
+  <mime-mapping>
+    <extension>wsdl</extension>
+    <mime-type>text/xml</mime-type>
+  </mime-mapping>
+  
+  <mime-mapping>
+    <extension>xsd</extension>
+    <mime-type>text/xml</mime-type>
+  </mime-mapping>
+  
+</web-app>
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/gs_ajax_utils.js
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/gs_ajax_utils.js	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/gs_ajax_utils.js	(revision 13928)
@@ -0,0 +1,129 @@
+
+
+function loadAsync(sUri, SOAPMessage) {
+   var xmlHttp = XmlHttp.create();
+   var async = true;
+   xmlHttp.open("POST", sUri, async);
+   xmlHttp.onreadystatechange = function () {
+      if (xmlHttp.readyState == 4){
+		var result = xmlHttp.responseText;
+			getTitle2(xmlHttp.responseXML, xmlHttp.responseText);
+    }     
+   }
+   xmlHttp.setRequestHeader("SOAPAction", " ");
+   xmlHttp.setRequestHeader("Content-Type", "Content-Type: text/xml; charset=utf-8");
+ 
+   xmlHttp.send(SOAPMessage);
+}
+
+
+function messageToSOAP(message) {
+    soapBody = '<soapenv:Body>' + message + '</soapenv:Body>'
+    soap = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' + soapBody + '</soapenv:Envelope>'
+    x= '<?xml version="1.0" encoding="UTF-8"?>' + soap;
+    return x;
+}
+
+
+
+
+function getText(element) { //get the text from possibly multiple text nodes
+if (element.hasChildNodes()) {
+	tempString = '';
+    for (j=0; j < element.childNodes.length; j++) {
+    				if (element.childNodes[j].nodeType == Node.TEXT_NODE ) { // =2
+    					tempString += element.childNodes[j].nodeValue;
+    				} 
+					else {
+						tempString += 'non text node: ';
+					}
+    } 
+	return tempString;
+}
+else {
+	return 'getText: element has no ChildNodes from which to extract Text';
+}
+}
+
+
+function newOpenTag(name) {
+	return '<' + name + '>';
+}
+
+function newCloseTag(name) {
+	return '</' + name + '>';
+}
+
+function newEmptyTag(name) {
+	return '<' + name + '/>';
+}
+
+function newElement(name, content) {
+    e = '<' + name + '>' + content;
+    e += '</' + name + '>';
+    return e;
+}
+
+
+function newElementAtt1(name, content, attName, attValue) {
+    e = '<' + name + ' ' + attName + '="' + attValue +'">' + content;
+    e += '</' + name + '>';
+    return e;
+}
+
+
+
+
+function newElementAtt(name, content, nameArray, valueArray) {
+    e = '<' + name + ' ' ;
+    for (i=0; i < nameArray.length; i++) {
+        e += newAttribute(nameArray[i], valueArray[i])
+    }
+    e += '>' + content;
+    e += '</' + name + '>';
+    return e;
+}
+
+
+function newAttribute(name, value) {
+				 return ' ' + name + '="' + value + '"';
+}
+
+/*
+var a = [];
+var b = [];
+a[0] = 'title';
+b[0] = 'test';
+a[1] = 'title2';
+b[1] = 'test2';
+
+alert( newElement('message', 'some content', a=[], b=[]));
+
+*/
+
+function countElementChildren(node) {
+  	count= 0;
+	childList = node.childNodes;
+	for(var i=0; i < (childList.length); i++) {
+		childNode = childList.item(i);
+		if ((childNode.nodeType == 1))	{ // only count elements
+				count++;
+		}
+	}
+	return count;
+}
+
+function removeAllChildren(node) {
+	while (node.hasChildNodes()) {
+		node.removeChild(node.firstChild);
+	}
+}
+
+
+function isElement(node) {
+    if (node.nodeType == 1) {
+    		return true; }
+    else {
+    		return false;
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/web/index.html
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/index.html	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/index.html	(revision 13928)
@@ -0,0 +1,47 @@
+<html>
+
+  <head>
+    <meta http-equiv="Content-Type"
+      content="text/html; charset=iso-8859-1">
+      <title>Greenstone Version 3</title>
+  </head>
+  
+  <body bgcolor="#ffffff" text="#000000" link="#006666" 
+    alink="#cc9900" vlink="#666633" background="interfaces/default/images/chalk.gif">
+    
+    <!-- page banner (_style:pagebanner_) -->
+    <center>
+      <table width=537 cellspacing=0 cellpadding=0>
+	<tr valign=top>
+	  <td rowspan=2 align=left><center><img src="interfaces/default/images/gsdlhead.gif" width=300 height=100 alt="Greenstone Digital Library Software"></center></td>
+	  <td align=right></td>
+	</tr>
+	
+	<tr>
+	  <td align=right></td>
+	</tr>
+	
+	<tr>
+	  <td colspan=2></td>
+	</tr>
+      </table>
+    </center>
+    <!-- end of page banner -->
+    
+    <center>
+      
+      <table width=537>
+	<tr><td><h3>Hello! Welcome to your Greenstone3 installation</h3></td></tr>
+	<tr><td>&nbsp;</td></tr>
+	<tr><td>What do you want to do today?</td></tr>
+	<tr><td>&nbsp;</td></tr>
+	
+	
+	<tr><td><a href="testing">Run</a> the test servlet</td></tr>
+	<tr><td><a href="library">Run</a> the standard library servlet. View the demo collections that come with Greenstone, using the default look and feel.</td></tr>
+	<tr><td><a href="classic">Run</a> the 'classic' servlet. View the same collections using the 'classic' (or Greenstone 2) look and feel.</td></tr>
+	<tr><td><a href="gateway">Run</a> the gateway servlet. This uses the standard look and feel, and talks via SOAP to the site with demo collections (localsite). Note that SOAP needs to be installed, and a SOAP server needs to be running for localsite.</td></tr>
+      </table>
+    </center>
+  </body>
+</html>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/interfaceConfig.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/interfaceConfig.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/interfaceConfig.xml	(revision 13928)
@@ -0,0 +1,21 @@
+<interfaceConfig baseInterface="default">
+  <actionList>
+    <action name='p' class='PageAction'>
+      <subaction name='home' xslt='home.xsl'/>
+      <subaction name='about' xslt='about.xsl'/>
+      <subaction name='help' xslt='help.xsl'/>
+      <subaction name='pref' xslt='pref.xsl'/>
+      <subaction name='nav' xslt='nav.xsl'/>
+      <subaction name="html" xslt="html.xsl"/>
+    </action>
+    <action name='q' class='QueryAction' xslt='query.xsl'/>
+    <action name='b' class='GS2BrowseAction' xslt='classifier.xsl'/>
+    <action name='a' class='AppletAction' xslt='applet.xsl'/>
+    <action name='d' class='DocumentAction' xslt='document.xsl'/>
+    <action name='pr' class='ProcessAction' xslt='process.xsl'/>
+    <action name='s' class='SystemAction' xslt='system.xsl'/>
+  </actionList>
+  <languageList>
+    <language name='en' displayname='English' default_encoding='utf-8'/>
+  </languageList>
+</interfaceConfig>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/style/classic.css
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/style/classic.css	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/style/classic.css	(revision 13928)
@@ -0,0 +1,220 @@
+/* classic stylesheet for greenstone3 */
+
+
+a:link { color: #006666; } 
+
+a:hover { color: #cc9900; }
+
+a:visited { color: #666633; } 
+
+
+.bgimage { background-image: url("../images/chalk.gif"); }
+
+/* this contains everything - all the other divs */
+#page {
+  margin: 0 3em 0 5em;
+  padding: 0;
+}
+
+#banner {
+  margin: 0 0 5px 0;
+  padding:0;
+ 
+}
+
+/* this div contains the bannerlinks and bannertitle paragraphs */
+div.pageinfo {
+  float: right;
+  text-align: right;
+  padding: 0;
+  margin:0 0 3px 0;	
+  width: 50%;
+}
+
+/* home, help, preferences links */
+p.bannerlinks {
+  font-family: sans-serif, arial, helvetica;
+  font-size: 10pt;
+  font-weight: bold;
+  margin:0;
+  padding:0;
+}
+
+/* the title set by the receptionist based on the page action */
+p.bannertitle {
+  font-family: sans-serif, arial, helvetica;
+  font-size: 24px;
+  font-weight: bold;
+  margin: 10px 0 0 0;
+  text-transform: lowercase;
+  white-space: nowrap;
+  padding: 6px 2px 10px 0px;
+  background-repeat: repeat-y;
+  background-position: top right; 
+  background-image: url("../images/banner_bg.png");  
+ 
+ }
+
+
+/* home, help, preferences links */
+p.bannerlinks {
+  font-family: sans-serif, arial, helvetica;
+  font-size: 10pt;
+  font-weight: bold;
+  margin:0;
+  padding:0;
+}
+
+/* the image for the collection, shown in the banner */
+div.collectimage {
+  text-align: left;
+  #height: 100%; /* for IE5/6 to make containing div the full height */
+  float: left;
+  width: 45%;
+  padding:0;
+  margin:0;
+}
+
+p.collectiontitle {
+  font-family: sans-serif, arial, helvetica;
+  font-size: 24px;
+  font-weight: bold;
+  text-transform: lowercase;
+  white-space: nowrap;
+  padding: 8px 0px 12px 2px;
+  background-repeat: repeat-y;
+  background-position: top left; 
+  margin:0;
+}
+
+a.collectiontitle {
+  color: black;
+  text-decoration: none;
+}
+
+/* make sure this is shown under the other divs (which may be floating) */
+div.bannerextra {
+   clear: both;
+}
+
+/* bg image set in style macro */
+div.divbar { /* for "select a collection" */
+  background-image: url("../images/bg_green.png"); 
+  font-family: arial;
+  font-size: 10pt;
+  font-weight: bold;
+  border: 0;
+  width: 100%; /* for ns4 */
+}
+
+/* bg image set in style macro */
+div.navbar {
+  background-image: url("../images/bg_green.png"); 	
+  min-width: 500px;
+  white-space: nowrap;
+  font-family: sans-serif, arial, helvetica;
+  font-size: 10pt;
+  font-weight: bold;
+  text-transform: lowercase;
+  border: 0;
+  width: 100%; /* for ns4 */
+}
+
+
+p.navbar { /* opt navbar text inside a divbar div */
+  text-align: center; 
+  margin: 0;
+  padding: 0;	
+}
+
+/* bg image set in style macro */
+a.navlink {
+  vertical-align: top; 
+  padding: 0 10px; 
+  color: black;
+  text-decoration: none;
+  background-image: url("../images/bg_off.png");
+  margin: 0 0 0 20px;
+}
+
+/* bg image set in style macro */
+a.navlink_sel {
+  vertical-align: top;
+  padding: 0 10px;
+  color: black;
+  text-decoration: none;
+  background-image: url("../images/bg_green.png"); 	
+}
+
+a.navlink:visited {
+  color: black;
+}
+
+/* for the nav_ns4.dm macro only (for netscape4 support) */
+a.navlink_ns4 {
+  background-color: #e8d9b1;
+}
+
+a.navlink:hover { 
+   background-image: url("../images/bg_on.png");
+ }
+
+span.narspace{
+  padding:0;
+  margin: 0 0 0 20px;		
+}
+
+div.document {
+  padding: 5px 0 0 0;
+  margin:0;
+}
+
+span.textselect { white-space: nowrap; }
+
+div.documenttext { clear: both; } /* come after any floating divs */
+
+div.heading_title {
+ font-size: 16pt;
+ font-weight: bold;
+
+} /* alternate to cover image */
+
+div.heading_image { float: left; } /* optional cover image */
+
+div.document div.buttons {
+   /* anything that holds buttons... toc_buttons but also continue button */
+   width: 100px; /* each button (inside its own div) can overflow this */
+}
+
+div#toc_buttons { /* expand/contract etc "buttons" */
+  clear: left; /* don't put next to another float on our left-hand side */
+  float: left;
+  margin: 0 15px 5px 0; 
+}
+
+div.button {
+  font-size: 11px;
+  font-weight: bold;
+  line-height: 1.2em;
+  /*background: #ffeecc; */
+  background: #f7e7c5;
+  margin: 1px;
+  border: 1px solid #eeddbb;
+  text-align: center;
+  vertical-align: middle;
+  height: 30px; /* IE6 and NS4 treat width/height as min-width/min-height */
+  width: 110px;
+}
+
+*>div.button { /* for other browsers - IE6 doesn't apply this */
+  height: auto;
+  width: auto;
+  min-height: 30px; 
+  min-width: 110px;
+}
+
+span.button {}
+span.button a { text-decoration: none; color: black; }
+span.button a:hover { /* IE6 doesn't do :hover for things that aren't <A> */
+  background: #eeddbb;
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/style/classic2.css
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/style/classic2.css	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/style/classic2.css	(revision 13928)
@@ -0,0 +1,29 @@
+ul {
+  margin:0;
+  padding:0; 
+  list-style-type: none; 
+}
+
+ul li{
+  margin:0;
+  padding:0;
+  display: inline;
+}
+
+ul#resultlist li{
+  display:block;
+}
+
+
+ul#classifiernodelist li{
+  list-style: none;
+  margin: 0;
+  padding: 0;
+  display: block;
+}
+
+ul.childrenlist{
+  margin: 0 0 0 20px ;
+  padding: 0;
+  display: block;
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/about.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/about.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/about.xsl	(revision 13928)
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+
+  <!-- style includes global params interface_name, library_name -->
+  <xsl:include href="style.xsl"/>
+  <xsl:include href="help-common.xsl"/>
+  <xsl:include href="query-common.xsl"/>
+  <xsl:include href="service-params.xsl"/>
+  <xsl:output method="html"/>  
+
+  <xsl:template name="pageTitle">
+    <xsl:value-of select="/page/pageResponse/collection/displayItem[@name='name']"/>  
+  </xsl:template>
+
+  <!-- page specific style goes here -->
+  <xsl:template name="pageStyle"/>
+
+
+  <xsl:template match="pageResponse">
+    <xsl:variable name="collName" select="/page/pageRequest/paramList/param[@name='c']/@value"/>
+      <xsl:apply-templates select="collection"><xsl:with-param name="collName" select="$collName"/></xsl:apply-templates>
+
+  </xsl:template>
+
+  <xsl:template match="collection">
+    <xsl:param name="collName"/>
+    <xsl:call-template name="standardPageBanner">
+      <xsl:with-param name="collName" select="$collName"/>
+      <xsl:with-param name="pageType">about</xsl:with-param>
+    </xsl:call-template>
+    <xsl:call-template name="navigationBar">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>
+    <div class="document">
+    <xsl:if test="/page/pageRequest/paramList/param[@name='ct']/@value = 0">
+    <xsl:apply-templates select="serviceList/service[@name='TextQuery']">
+      <xsl:with-param name="collName" select="$collName"/></xsl:apply-templates>
+    <xsl:call-template name="dividerBar"/>
+    </xsl:if>
+    </div>
+    <div>
+    <xsl:if test="displayItem[@name='description']">
+    <h3><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'about.aboutcoll')"/></h3>
+    <p><xsl:value-of select="displayItem[@name='description']" disable-output-escaping='yes'/></p>
+    </xsl:if>
+    <xsl:apply-templates select="." mode="simplehelp"/>
+    </div>	
+  </xsl:template>
+
+</xsl:stylesheet>  
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/applet.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/applet.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/applet.xsl	(revision 13928)
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+  
+  <xsl:include href="style.xsl"/>
+  
+  <xsl:output method="html"/>  
+
+  <xsl:template name="pageTitle">
+    <xsl:value-of select="pageResponse/service/applet"/>
+  </xsl:template>
+
+  <!-- page specific style goes here -->
+  <xsl:template name="pageStyle"/>
+
+  <xsl:template match="pageResponse">
+    <xsl:variable name="collName"><xsl:value-of select="../pageRequest/paramList/param[@name='c']/@value"/></xsl:variable>
+    <center>
+      <xsl:call-template name="standardPageBanner">
+	<xsl:with-param name="collName" select="$collName"/>
+	<xsl:with-param name="pageType"><xsl:choose><xsl:when test="service[@name='PhindApplet']">phrases</xsl:when><xsl:otherwise>applet</xsl:otherwise></xsl:choose></xsl:with-param>
+      </xsl:call-template>
+      <p/>
+    <xsl:call-template name="navigationBar">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>      
+<!--      <xsl:call-template name="dividerBar">
+	<xsl:with-param name="text" select="service/displayItem[@name='name']"/>
+      </xsl:call-template>-->
+      <p/>
+      <xsl:copy-of select="service/applet"/>
+      <xsl:call-template name="dividerBar"/>
+    </center>
+  </xsl:template>
+</xsl:stylesheet>  
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/classifier.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/classifier.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/classifier.xsl	(revision 13928)
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+  
+  <xsl:include href="style.xsl"/>
+  <xsl:include href="classifiertools.xsl"/>
+  
+  <xsl:output method="html"/>  
+
+  <xsl:template name="pageTitle">
+    <xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'nzdl')"/>
+  </xsl:template>
+
+  <!-- page specific style goes here -->
+  <xsl:template name="pageStyle"/>
+
+  <xsl:template match="pageResponse">
+    <xsl:variable name="collName"><xsl:value-of select="/page/pageRequest/paramList/param[@name='c']/@value"/></xsl:variable>
+    <xsl:variable name="serviceName"><xsl:value-of select="service/@name"/></xsl:variable>
+    <xsl:variable name="cl" select="/page/pageRequest/paramList/param[@name='cl']/@value"/>
+    <xsl:variable name="clTop">
+      <xsl:choose>
+	<xsl:when test="contains($cl, '.')"><xsl:value-of select="substring-before($cl, '.')"/></xsl:when>
+	<xsl:otherwise>
+	  <xsl:value-of select="$cl"/>
+	</xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+      <xsl:call-template name="standardPageBanner">
+	<xsl:with-param name="collName" select="$collName"/>
+	<xsl:with-param name="pageType">browse</xsl:with-param>
+	<xsl:with-param name="clTop" select="$clTop"/>
+      </xsl:call-template>
+      <xsl:call-template name="navigationBar">
+	<xsl:with-param name="collName" select="$collName"/>
+	<xsl:with-param name="clTop" select="$clTop"/>
+      </xsl:call-template>      
+      <div class="document">
+      <xsl:apply-templates select="classifier">
+	<xsl:with-param name="collName" select="$collName"/>
+	<xsl:with-param name="serviceName" select="$serviceName"/>
+      </xsl:apply-templates>
+      </div>
+  </xsl:template>
+  
+
+</xsl:stylesheet>
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/document.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/document.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/document.xsl	(revision 13928)
@@ -0,0 +1,412 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  xmlns:gsf="http://www.greenstone.org/greenstone3/schema/ConfigFormat"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util gsf">
+
+  <xsl:include href="style.xsl"/>
+  <xsl:include href="service-params.xsl"/>
+  <xsl:output method="html"/>
+
+  <!-- the main page layout template is here -->
+  <!-- override the one in style so we can display the doc over the whole page and get rid of the green bar down the side --> 
+  <xsl:template match="page" priority='2'>
+    <html>
+      <xsl:call-template name="pageHead"/>
+      <body>
+        <div id="page">
+           <xsl:apply-templates select="pageResponse"/>
+	   <xsl:call-template name="greenstoneFooter"/>
+	</div>  
+       </body>
+    </html>
+  </xsl:template>
+  
+  <xsl:template name="pageTitle">
+    <xsl:variable name="docID" select="/page/pageResponse/document/@selectedNode"/>
+    <xsl:for-each select='/page/pageResponse/document/descendant::documentNode[@nodeID=$docID]/ancestor-or-self::documentNode'><xsl:if test='position()!=1'>::</xsl:if><xsl:value-of select="metadataList/metadata[@name='Title']"/></xsl:for-each>
+  </xsl:template>
+
+  <!-- this is hard coded for GATE, should somehow do it dynamically-->
+  <xsl:template name="pageStyle">
+    <style type="text/css">
+      <xsl:text disable-output-escaping="yes">
+	span.Location {  display:inline; color : red }
+	span.Person {  display:inline; color : green }
+	span.Organization {  display:inline; color : yellow }
+	span.Date {  display:inline; color : blue }
+	span.query_term {display: inline; background-color : yellow }
+      </xsl:text>
+    </style>
+  </xsl:template>
+  
+  <xsl:template match="pageResponse">
+    <xsl:variable name="collName"><xsl:value-of select="/page/pageRequest/paramList/param[@name='c']/@value"/></xsl:variable>
+    <xsl:call-template name="standardPageBanner">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>
+    <xsl:call-template name="navigationBar">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>
+    <div class="document">     
+    <!-- display the document -->
+    <xsl:apply-templates select="document">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:apply-templates>
+   </div>
+  </xsl:template>
+	
+  <xsl:template match="document">
+    <xsl:param name="collName"/>
+    
+    <xsl:call-template name="documentHeading">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>
+    
+    <xsl:call-template name="documentContent">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>
+  </xsl:template>
+
+  <xsl:template name="documentHeading">
+    <xsl:param name="collName"/>
+    <xsl:variable name="doCoverImage" select="/page/pageResponse/format/gsf:option[@name='coverImages']/@value"/>
+    <xsl:variable name="doTOC" select="/page/pageResponse/format/gsf:option[@name='documentTOC']/@value"/>
+    <xsl:variable name="p.a" select="/page/pageRequest/paramList/param[@name='p.a']/@value"/>
+    <xsl:variable name="p.sa" select="/page/pageRequest/paramList/param[@name='p.sa']/@value"/>
+    <xsl:variable name="p.s" select="/page/pageRequest/paramList/param[@name='p.s']/@value"/>
+    <div class="heading_image">
+       <xsl:if test="string($doCoverImage) != 'false' and (@docType='paged' or @docType='hierarchy')">
+	<xsl:call-template name="coverImage"/> 
+       </xsl:if>
+    </div>
+    <div class="buttons" id="toc_buttons">
+        <xsl:call-template name="documentButtons">
+	    <xsl:with-param name="collName" select="$collName"/>
+	</xsl:call-template>
+    </div>
+
+    <!--<div><xsl:call-template name="enrichServices">
+	    <xsl:with-param name="collName" select="$collName"/>
+	  </xsl:call-template></div>-->
+
+    <div class="toc">
+        <table class="v_list"><tr valign="top"><td valign="top"> <a href="{$library_name}?a={$p.a}&amp;sa={$p.sa}&amp;s={$p.s}&amp;c={$collName}&amp;rt=r"><xsl:call-template name="openbookimg"><xsl:with-param name="title">Close this book and return to search/browse</xsl:with-param>
+	  </xsl:call-template></a></td><td valign="top"></td>
+         <td valign="top">
+ 	    <xsl:choose><xsl:when test="@docType='simple'"><xsl:value-of select="metadataList/metadata[@name='Title']" disable-output-escaping="yes"/></xsl:when><xsl:otherwise><xsl:value-of select="documentNode/metadataList/metadata[@name='Title']" disable-output-escaping="yes"/></xsl:otherwise></xsl:choose>
+          </td></tr>
+         </table>
+        <xsl:if test="string($doTOC) != 'false'">
+	  <table><tr valign="top"><td><img alt="" src="/gsdl/images/space.gif" width="25"/></td><td><table class="v_list">
+	    <xsl:call-template name="TOC">
+	      <xsl:with-param name="collName" select="$collName"/>
+	    </xsl:call-template>
+	    </table>
+          </td></tr></table>
+	</xsl:if>  	 	   
+      </div>
+   </xsl:template>
+
+  <xsl:template name="coverImage">
+    <img alt="" onError="src='interfaces/default/images/blank.gif'"><xsl:attribute name='src'><xsl:value-of select="/page/pageResponse/collection/metadataList/metadata[@name='httpPath']"/>/index/assoc/<xsl:value-of select="metadataList/metadata[@name='archivedir']"/>/cover.jpg</xsl:attribute></img>
+  </xsl:template>
+
+  <xsl:template name="documentButtons">
+    <xsl:param name="collName"/>
+    <xsl:variable name="docID" select="/page/pageRequest/paramList/param[@name='d']/@value"/>
+    <xsl:variable name="sib" select="/page/pageRequest/paramList/param[@name='sib']/@value"/>
+    <xsl:variable name="ec" select="/page/pageRequest/paramList/param[@name='ec']/@value"/>
+    <xsl:variable name="ed" select="/page/pageRequest/paramList/param[@name='ed']/@value"/>
+   
+   
+      <!-- expand document -->
+      <!-- this doesn't work with MG so comment it out for now -->      
+      <xsl:if test="@docType = 'hierarchy' or @docType = 'paged'">
+      <div class="button">
+        <span class="button">
+	  <xsl:choose><xsl:when test="string($ed)='1'">
+	      <a href="{$library_name}?a=d&amp;d={$docID}&amp;c={$collName}&amp;sib={$sib}&amp;ed=0"><xsl:attribute name="title"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'doc.contract_doc_tip')"/></xsl:attribute>
+		  <xsl:value-of disable-output-escaping='yes' select="util:getInterfaceText($interface_name, /page/@lang, 'doc.contract_doc_b')"/>
+	      </a>
+	    </xsl:when>
+	    <xsl:otherwise>
+	        <a href="{$library_name}?a=d&amp;d={$docID}&amp;c={$collName}&amp;sib={$sib}&amp;ed=1"><xsl:attribute name="title"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'doc.expand_doc_tip')"/></xsl:attribute>
+	   <xsl:value-of disable-output-escaping='yes' select="util:getInterfaceText($interface_name, /page/@lang, 'doc.expand_doc_b')"/>
+	      </a>
+	    </xsl:otherwise>
+	  </xsl:choose>
+         </span>
+	</div>
+      </xsl:if> 
+      
+      <!-- expand contents -->
+      <xsl:if test="@docType = 'hierarchy' and string(/page/pageResponse/format/gsf:option[@name='documentTOC']/@value) != 'false'">
+      <div class="button">
+        <span class="button">
+	  <xsl:choose><xsl:when test="string($ec)='1'">
+	      <a  href="{$library_name}?a=d&amp;d={$docID}&amp;c={$collName}&amp;sib={$sib}&amp;ec=0"><xsl:attribute name="title"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'doc.contract_contents_tip')"/></xsl:attribute>
+		 <xsl:value-of disable-output-escaping='yes' select="util:getInterfaceText($interface_name, /page/@lang, 'doc.contract_contents_b')"/>
+	      </a>
+	    </xsl:when>
+	    <xsl:otherwise>
+	      <a  href="{$library_name}?a=d&amp;d={$docID}&amp;c={$collName}&amp;sib={$sib}&amp;ec=1"><xsl:attribute name="title"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'doc.expand_contents_tip')"/></xsl:attribute>
+		<xsl:value-of disable-output-escaping='yes' select="util:getInterfaceText($interface_name, /page/@lang, 'doc.expand_contents_b')"/>
+	      </a>
+	    </xsl:otherwise>
+	  </xsl:choose>
+	 </span>
+	</div>
+      </xsl:if>
+      <!-- detach page -->
+      <xsl:variable name="paramList" select="/page/pageRequest/paramList"/>
+      <div class="button">
+        <span class="button">
+	  <a  target="_blank"><xsl:attribute name="href"><xsl:value-of select="$library_name"/>?a=d&amp;d=<xsl:value-of select="$docID"/>&amp;c=<xsl:value-of select="$collName"/>&amp;sib=<xsl:value-of select="$sib"/>&amp;dt=<xsl:value-of select="$paramList/param[@name='dt']/@value"/>&amp;ec=<xsl:value-of select="$paramList/param[@name='ec']/@value"/>&amp;et=<xsl:value-of select="$paramList/param[@name='et']/@value"/>&amp;p.a=<xsl:value-of select="$paramList/param[@name='p.a']/@value"/>&amp;p.s=<xsl:value-of select="$paramList/param[@name='p.s']/@value"/>&amp;p.sa=<xsl:value-of select="$paramList/param[@name='p.sa']/@value"/></xsl:attribute><xsl:attribute name="title"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'doc.detach_page_tip')"/></xsl:attribute>
+	    <xsl:value-of disable-output-escaping='yes' select="util:getInterfaceText($interface_name, /page/@lang, 'doc.detach_page_b')"/>
+	  </a>
+         </span>
+      </div>
+   </xsl:template>
+
+  <xsl:template name="TOC">
+    <xsl:param name="collName"/>
+    <xsl:choose>
+      <xsl:when test="@docType='hierarchy'">
+	<xsl:call-template name="hierarchicalContents">
+	  <xsl:with-param name="collName" select="$collName"/>
+	</xsl:call-template>
+      </xsl:when>
+      <xsl:when test="@docType='paged'">
+	<xsl:call-template name="pagedContents">
+	  <xsl:with-param name="collName" select="$collName"/>
+	</xsl:call-template>
+      </xsl:when>
+    </xsl:choose>
+  </xsl:template>
+    
+  <xsl:template name="hierarchicalContents">
+    <xsl:param name="collName"/>
+    <xsl:variable name="oc" select="/page/pageRequest/paramList/param[@name='oc']/@value"/>
+    <xsl:variable name="d" select="/page/pageRequest/paramList/param[@name='d']/@value"/>
+    <xsl:variable name="sib" select="/page/pageRequest/paramList/param[@name='sib']/@value"/>
+    <xsl:variable name="ec" select="/page/pageRequest/paramList/param[@name='ec']/@value"/>
+    <xsl:if test="documentNode[@nodeID]">
+	<tr valign='top'><td>
+	    <xsl:choose><xsl:when test="string($oc)='0'">
+		<a href="{$library_name}?a=d&amp;c={$collName}&amp;d={$d}&amp;sib={$sib}&amp;oc=1"><xsl:call-template name="closedfolderimg"><xsl:with-param name="title">open the table of contents</xsl:with-param></xsl:call-template></a>
+	      </xsl:when>
+	      <xsl:otherwise><a href="{$library_name}?a=d&amp;c={$collName}&amp;d={$d}&amp;sib={$sib}&amp;oc=0"><xsl:call-template name="openfolderimg"><xsl:with-param name="title">close the table of contents</xsl:with-param></xsl:call-template></a></xsl:otherwise></xsl:choose>
+	  </td><td>Table of Contents</td></tr>
+	<xsl:if test="string($oc)!='0'">
+	  <tr><td>&#160;</td><td>
+	      <table>
+		<xsl:for-each select="documentNode/documentNode[@nodeID]">
+		  <xsl:apply-templates select='.'><xsl:with-param name="collName" select="$collName"/><xsl:with-param name="ec" select="$ec"/></xsl:apply-templates>
+		</xsl:for-each>
+	      </table>
+	    </td></tr>
+	</xsl:if>
+    </xsl:if>
+  </xsl:template>
+  
+  <!-- each icon-title pair is a row in a table. children go in a table in another row -->
+  <xsl:template match="documentNode">
+    <xsl:param name="collName"/>
+    <xsl:param name="ec"/>
+    <!-- Display the appropriate image, depending on the node type -->
+    <tr><td valign="top">
+	<a><xsl:attribute name="href"><xsl:value-of select='$library_name'/>?a=d&amp;c=<xsl:value-of select='$collName'/>&amp;d=<xsl:value-of select='@nodeID'/><xsl:if test="documentNode">.pr</xsl:if><xsl:if test="@nodeType='leaf'">&amp;sib=1</xsl:if><xsl:if test="string($ec) = '1'">&amp;ec=1</xsl:if></xsl:attribute>
+	  <xsl:apply-templates select="." mode="displayNodeIcon"/>
+	</a>
+      </td>
+      
+      <!-- Display associated title, bolded if the node has content -->
+      <td valign="top">
+	<xsl:choose>
+	  <xsl:when test="nodeContent">
+	    <b><xsl:value-of disable-output-escaping="yes" select="metadataList/metadata[@name='Title']"/></b>
+	  </xsl:when>
+	  <xsl:otherwise>
+	    <xsl:value-of disable-output-escaping="yes" select="metadataList/metadata[@name='Title']"/>
+	  </xsl:otherwise>
+	</xsl:choose>
+      </td>
+    </tr>
+    <!-- Apply recursively to the children of this node -->
+    <xsl:if test="documentNode[@nodeID]">
+      <tr><td>&#160;</td><td><table>
+	    <xsl:apply-templates select="documentNode[@nodeID]">
+	      <xsl:with-param name="collName" select="$collName"/>
+	      <xsl:with-param name="ec" select="$ec"/>
+	      <!--<xsl:with-param name="depth" select="$depth + 1"/>-->
+	    </xsl:apply-templates>
+	  </table>
+	</td></tr>
+    </xsl:if>
+  </xsl:template>
+  
+  <!-- default content is to print the title and content of any documentNodes that have nodeContent -->
+  <xsl:template name="documentContent">
+    <div class="documenttext">
+      <xsl:choose>
+        <xsl:when test="@docType='simple'">
+	  <xsl:apply-templates select="nodeContent"/>
+	</xsl:when>
+        <xsl:otherwise>
+	  <xsl:apply-templates select="descendant-or-self::node()/documentNode" mode="content"/>
+        </xsl:otherwise>
+      </xsl:choose>
+    </div>
+  </xsl:template>
+  
+  <xsl:template match="documentNode" mode="content">
+    <xsl:if test="nodeContent and string(nodeContent)">
+      <xsl:if test="metadataList/metadata[@name='Title']">
+	<h3><xsl:value-of disable-output-escaping="yes" select="metadataList/metadata[@name='Title']"/></h3>
+      </xsl:if>
+      <xsl:apply-templates select="nodeContent"/>
+      </xsl:if>
+    
+  </xsl:template>
+
+  <!-- the actual text/content -->
+  <xsl:template match="nodeContent">
+    <p/>
+    <xsl:for-each select="node()">
+      <xsl:choose>
+	<xsl:when test="not(name())"><xsl:value-of select="." disable-output-escaping="yes"/></xsl:when>
+	<xsl:otherwise><xsl:apply-templates select="."/></xsl:otherwise>
+      </xsl:choose>
+    </xsl:for-each>
+  </xsl:template>
+  
+  <!-- match any file nodes -->
+  <xsl:template match="file">
+    <xsl:variable name="httpPath" select="/page/pageResponse/collection/metadataList/metadata[@name='httpPath']"/>
+    <xsl:choose>
+      <xsl:when test="util:isImage(@mimeType)">
+	<img src="{$httpPath}/{@href}"/>
+      </xsl:when>
+      <xsl:otherwise>
+	<a href="{$httpPath}/{@href}"><xsl:value-of select="@href"/></a>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  
+  <!-- match any link nodes -->
+  <xsl:template match="link">
+    <xsl:variable name="collName" select="/page/pageRequest/paramList/param[@name='c']/@value"/> 
+    <xsl:variable name="actionargs">
+      <xsl:choose>
+	<xsl:when test="@type='document'">a=d</xsl:when>
+	<xsl:when test="@type='query'">a=q&amp;s=<xsl:value-of select="@service"/>&amp;rt=r</xsl:when>
+	<xsl:otherwise>
+	  p
+	</xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <xsl:variable name="serviceargs">
+      <xsl:for-each select="param">&amp;s1.<xsl:value-of select="@name"/>=<xsl:value-of select="@value"/></xsl:for-each>
+  </xsl:variable>
+    <a href="{$library_name}?{$actionargs}&amp;c={$collName}{$serviceargs}"><xsl:value-of disable-output-escaping="yes" select="."/></a>
+  </xsl:template>
+
+  <!-- match any annotations and make them span elements -->
+  <xsl:template match="annotation">
+    <span class="{@type}"><xsl:value-of disable-output-escaping="yes" select="."/></span>
+  </xsl:template>
+  
+  <!-- paged naviagtion : INCOMPLETE!!-->
+  <xsl:template name="pagedContents">
+    <xsl:param name="collName"/>
+    <xsl:variable name="pos" select="nodeStructureInfo/info[@name='siblingPosition']/@value"/>
+    <xsl:variable name="length" select="nodeStructureInfo/info[@name='numSiblings']/@value"/>
+    <xsl:variable name="children" select="nodeStructureInfo/info[@name='numChildren']/@value"/>
+      <xsl:choose>
+	<xsl:when test="$pos=-1"><!-- a doc -->
+	  <tr valign="top">
+	    <td align="left">
+	    </td>
+	    <td align="center"><center>
+		<b><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'document.pages', $children)"/></b>
+	      </center></td>
+	    <td align="right">
+	      <a href="{$library_name}?a=d&amp;c={$collName}&amp;d={@selectedNode}.fc"><img src="interfaces/default/images/more.gif" border="0" align="absbottom" /></a>
+	    </td>
+	  </tr>
+	</xsl:when>
+	
+	<xsl:otherwise> <!-- an internal node -->	  
+	  <tr valign="top">
+	    <td align="left">
+	      <xsl:if test=" not ( $pos = 1 )">
+		<a href="{$library_name}?a=d&amp;c={$collName}&amp;d={@selectedNode}.ps"><img src="interfaces/default/images/less.gif" border="0" align="absbottom" /></a>
+	      </xsl:if>
+	    </td>
+	    <td align="center"><center>
+		<b><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'document.pageof', concat($pos, ';', $length))"/></b>
+	      </center></td>
+	    <td align="right">
+	      <xsl:if test=" not($pos = $length)">
+		<a href="{$library_name}?a=d&amp;c={$collName}&amp;d={@selectedNode}.ns"><img src="interfaces/default/images/more.gif" border="0" align="absbottom" /></a>
+	      </xsl:if>
+	    </td>
+	  </tr>
+	</xsl:otherwise>
+      </xsl:choose>
+      <tr valign="middle">
+	<td align='center' valign='top' colspan='3'>
+	  <form name="GotoForm" method="get" action="{$library_name}">
+	    <input type='hidden' name='a' value='d'/>
+	    <input type='hidden' name='c' value='{$collName}'/>
+	    <input type='hidden' name='d' value='{@selectedNode}'/>
+	    <input type="text" name="gp" size="3" maxlength="4"/>
+	    <input type="submit"><xsl:attribute name='value'><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'document.gotopage')"/></xsl:attribute></input>
+	  </form>
+	</td>
+      </tr>
+   </xsl:template>
+  
+  <xsl:template name="enrichServices">
+    <xsl:param name="collName"/>
+    <xsl:variable name="docID" select="/page/pageRequest/paramList/param[@name='d']/@value"/>
+    <xsl:variable name="request-params" select="/page/pageRequest/paramList"/>
+    <xsl:for-each select="../serviceList/service">
+      <table border='1' cellspacing='0'>
+	<tr><td>
+	    <p /><xsl:value-of select="displayItem[@name='name']"/><p/>
+	    <form name="EnrichForm" method="get" action="{$library_name}">
+	      <xsl:apply-templates select="paramList"/>
+	      <input type='hidden' name='a' value='d'/>
+	      <input type='hidden' name='d' value='{$docID}'/>
+	      <input type='hidden' name='c' value='{$collName}'/>
+	      <xsl:if test='$request-params/param[@name="sib"]'>
+		<input type='hidden' name='sib'><xsl:attribute name='value'><xsl:value-of select='$request-params/param[@name="sib"]/@value'/></xsl:attribute></input></xsl:if>
+	      <input type='hidden' name='s' value='{@name}'/>
+	      <input type='hidden' name='p.a'><xsl:attribute name='value'><xsl:value-of select='$request-params/param[@name="p.a"]'/></xsl:attribute></input>
+	      <input type='hidden' name='p.sa'><xsl:attribute name='value'><xsl:value-of select='$request-params/param[@name="p.sa"]'/></xsl:attribute></input>
+	      <input type='hidden' name='p.s'><xsl:attribute name='value'><xsl:value-of select='$request-params/param[@name="p.s"]'/></xsl:attribute></input>
+	      <input type='hidden' name='end' value='1'/>
+	      <input type="submit"><xsl:attribute name="value"><xsl:value-of select="displayItem[@name='submit']"/></xsl:attribute></input>
+	    </form>
+	  </td></tr>
+      </table>
+    </xsl:for-each>
+  </xsl:template>
+
+  <xsl:template match="paramList" mode="hidden">
+    <xsl:for-each select="param">
+      <input type='hidden' name='{@name}' value='{@value}'/><xsl:text>
+      </xsl:text>
+    </xsl:for-each>
+  </xsl:template>
+  
+</xsl:stylesheet>
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/help-common.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/help-common.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/help-common.xsl	(revision 13928)
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+
+
+  <xsl:template match="collection" mode="simplehelp">
+    <xsl:variable name="longCollName"><xsl:value-of select="displayItem[@name='name']" disable-output-escaping='yes'/></xsl:variable>
+    <!--<xsl:variable name="numoptions">5</xsl:variable>-->
+    <xsl:variable name="has_search"><xsl:choose><xsl:when test="serviceList/service[@name='TextQuery']">1</xsl:when><xsl:otherwise>0</xsl:otherwise></xsl:choose></xsl:variable>
+    <xsl:variable name="has_phrase"><xsl:choose><xsl:when test="serviceList/service[@name='PhindApplet']">1</xsl:when><xsl:otherwise>0</xsl:otherwise></xsl:choose></xsl:variable>
+    <xsl:variable name="numoptions" select="count(serviceList/service[@name='ClassifierBrowse']/classifierList/classifier)"/>
+    <h3><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'help.simplehelpheading', $longCollName)"/></h3>
+    <xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'help.numbrowseoptions', $numoptions+$has_search+$has_phrase)"/>
+    <ul>
+     <xsl:if test="$has_search =1">
+       <li><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'help.Searchshort')" disable-output-escaping='yes'/></li>
+     </xsl:if>
+     <xsl:for-each select="serviceList/service[@name='ClassifierBrowse']/classifierList/classifier">
+       <xsl:variable name="title">help.<xsl:value-of select="@content"/>short</xsl:variable>
+       <li><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, $title)" disable-output-escaping='yes'/></li>
+     </xsl:for-each>
+     <xsl:if test="$has_phrase =1">
+       <li><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'help.Phraseshort')" disable-output-escaping='yes'/></li>
+     </xsl:if>
+     </ul>
+     <xsl:if test="$has_search =1">
+       <xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'help.Searchlong')" disable-output-escaping='yes'/>
+     </xsl:if>
+     <xsl:for-each select="serviceList/service[@name='ClassifierBrowse']/classifierList/classifier">
+       <xsl:variable name="title">help.<xsl:value-of select="@content"/>long</xsl:variable>
+       <xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, $title)" disable-output-escaping='yes'/>
+     </xsl:for-each>
+     <xsl:if test="$has_phrase =1">
+       <xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'help.Phraselong')" disable-output-escaping='yes'/>
+     </xsl:if>
+     
+  </xsl:template>
+
+   
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/help.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/help.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/help.xsl	(revision 13928)
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+
+  <xsl:include href="style.xsl"/>
+  <!--<xsl:include href="help-text.xsl"/>-->
+  <xsl:include href="page-common.xsl"/>
+  
+  <xsl:output method="html"/>  
+  
+  <xsl:template name="pageTitle">
+    <xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'help_tip')"/>
+  </xsl:template>
+
+  <!-- page specific style goes here -->
+  <xsl:template name="pageStyle"/>
+
+
+  <xsl:template match="pageResponse">
+    <xsl:variable name="collName" select="/page/pageRequest/paramList/param[@name='c']/@value"/>
+    <center>
+      <xsl:call-template name="standardPageBanner">
+	<xsl:with-param name="collName" select="$collName"/>
+	<xsl:with-param name="pageType">help</xsl:with-param>
+      </xsl:call-template>
+      <xsl:call-template name="navigationBar">
+	<xsl:with-param name="collName" select="$collName"/>
+      </xsl:call-template>      
+      <p />Help text to go here!!
+    </center>
+  </xsl:template>
+
+
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/home.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/home.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/home.xsl	(revision 13928)
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+
+  <!-- style includes global params interface_name, library_name -->
+  <xsl:include href="style.xsl"/>
+
+  <xsl:output method="html"/>  
+
+  <xsl:template name="pageTitle">
+    <xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'gsdl')"/>
+  </xsl:template>
+  
+  <!-- page specific style goes here -->
+  <xsl:template name="pageStyle"/>
+
+  <xsl:template match="pageResponse">
+    <xsl:call-template name="greenstonePageBanner"/> 
+    <xsl:apply-templates select="collectionList"/>   
+  </xsl:template>
+
+  <xsl:template match="collectionList">
+    <xsl:for-each select="collection"> 
+      <xsl:variable name="ct"><xsl:choose><xsl:when test="metadataList/metadata[@name='buildType']='mgpp'">1</xsl:when><xsl:otherwise>0</xsl:otherwise></xsl:choose></xsl:variable>
+
+      <p>
+      <a href="{$library_name}?a=p&amp;sa=about&amp;c={@name}&amp;ct={$ct}">
+	  <img width="150" border="1">
+	    <xsl:attribute name="src">
+	      <xsl:value-of select="metadataList/metadata[@name='httpPath']"/>/images/<xsl:choose><xsl:when test="displayItem[@name='smallicon']"><xsl:value-of select="displayItem[@name='smallicon']"/></xsl:when><xsl:otherwise><xsl:value-of select="displayItem[@name='icon']"/></xsl:otherwise></xsl:choose>
+	    </xsl:attribute>
+	    <xsl:attribute name="alt">
+	      <xsl:value-of select="displayItem[@name='name']"/>
+	    </xsl:attribute>
+	  </img>
+	</a>
+      </p>
+    </xsl:for-each> 
+    <xsl:call-template name="collWarning"/>
+  </xsl:template> 
+  
+  <xsl:template name="collWarning">
+    <xsl:call-template name="dividerBar"/>	
+    <div>
+      <xsl:value-of select="util:getInterfaceText('classic', /page/@lang, 'home.coll_warning')"/>
+    </div>	
+   </xsl:template>
+</xsl:stylesheet>  
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/nav.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/nav.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/nav.xsl	(revision 13928)
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+  
+   <!-- style includes global params interface_name, library_name -->
+  <xsl:include href="style.xsl"/>
+
+  <xsl:output method="html"/>  
+  
+  <xsl:template match="page">
+    <html>
+      <head>
+	<title>
+	  <xsl:call-template name="pageTitle"/><xsl:text> </xsl:text>
+	</title>
+	<xsl:call-template name="globalStyle"/>
+	<base target="_top"/>
+      </head>
+      <body style="background-image: none;">
+	<center>
+	  <table width="537">
+	    <tr><td>
+		<xsl:apply-templates select="pageResponse"/>
+	      </td></tr>
+	  </table>
+	</center>
+      </body>
+    </html>
+  </xsl:template>
+
+  <xsl:template name="pageTitle">
+    <xsl:value-of select="/page/pageResponse/*/displayItem[@name='name']"/>
+  </xsl:template>
+
+  <xsl:template match="pageResponse">
+    <xsl:variable name="collName" select="/page/pageRequest/paramList/param[@name='c']/@value"/>
+    <div align="right">
+    <xsl:call-template name="top-buttons">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>
+      </div>
+    <xsl:call-template name="navigationBar">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>      
+  </xsl:template>
+
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/pref.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/pref.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/pref.xsl	(revision 13928)
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+
+  <xsl:include href="style.xsl"/>
+  <!--<xsl:include href="pref-text.xsl"/>-->
+  
+  <xsl:output method="html"/>  
+  
+  <xsl:template name="pageTitle">
+    <xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'pref_tip')"/>
+  </xsl:template>
+
+  <!-- page specific style goes here -->
+  <xsl:template name="pageStyle"/>
+
+
+  <xsl:template match="pageResponse">
+    <xsl:variable name="collName" select="/page/pageRequest/paramList/param[@name='c']/@value"/>
+    <center>
+      <xsl:call-template name="standardPageBanner">
+	<xsl:with-param name="collName" select="$collName"/>
+	<xsl:with-param name="pageType">pref</xsl:with-param>
+      </xsl:call-template>
+      <xsl:call-template name="navigationBar">
+	<xsl:with-param name="collName" select="$collName"/>
+      </xsl:call-template>
+      <form name="PrefForm" method="get" action="{$library_name}">
+	<input type='hidden' name='a' value='p'/>
+	<input type='hidden' name='sa' value='pref'/>
+	<table>
+	  <tr><td><h3><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'pref.prespref')"/></h3></td></tr>
+	  <tr><td><xsl:call-template name="pres-prefs"/></td></tr>
+	  <tr><td><xsl:call-template name="dividerBar"/></td></tr>
+	  <tr><td><h3><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'pref.searchpref')"/></h3></td></tr>
+	  <tr><td><xsl:call-template name="search-prefs"/></td></tr>
+	  <tr><td><xsl:call-template name="dividerBar"/></td></tr>
+	</table>
+      </form>
+    </center>
+  </xsl:template>
+
+  
+  <xsl:template name="pres-prefs">
+    <table>
+      <tr><td><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'pref.interfacelang')"/></td><td align='left'>English</td></tr>
+      <tr><td><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'pref.encoding')"/></td><td align='left'>UTF-8</td></tr>
+    </table>
+  </xsl:template>
+  
+  <xsl:template name="search-prefs">
+    <xsl:param name="ns">s1.</xsl:param>
+    <xsl:variable name="ct"><xsl:choose><xsl:when test="/page/pageRequest/paramList/param[@name='ct']"><xsl:value-of select="/page/pageRequest/paramList/param[@name='ct']/@value"/></xsl:when><xsl:otherwise>0</xsl:otherwise></xsl:choose></xsl:variable>
+    <table>
+      <tr><td> </td><td> </td><td align='right'><input type='submit' value='set prefs'/></td></tr>
+      <xsl:choose>
+	<xsl:when test="$ct=0">
+	  <xsl:call-template name='text-search-prefs'/>
+	</xsl:when>
+	<xsl:otherwise>
+      <!-- search type -->
+	  <xsl:variable name='querytype'><xsl:choose><xsl:when test="/page/pageRequest/paramList/param[@name='qt']"><xsl:value-of select="/page/pageRequest/paramList/param[@name='qt']/@value"/></xsl:when><xsl:otherwise>0</xsl:otherwise></xsl:choose></xsl:variable>
+	  <tr><td  rowspan='2' valign='baseline'>Type of search:</td><td><input type='radio' name='qt' value='0'><xsl:if test="$querytype=0"><xsl:attribute name="checked"></xsl:attribute></xsl:if></input></td><td align='left'> text search</td></tr>
+	  <tr><td></td><td>
+	      <table>
+		<xsl:call-template name='text-search-prefs'/>
+	      </table></td></tr>
+	  
+	  <tr><td> </td><td><input type='radio' name='qt' value='1'><xsl:if test="$querytype=1"><xsl:attribute name="checked"></xsl:attribute></xsl:if></input></td><td> form search<br /></td></tr>
+	  <tr><td></td><td></td><td>
+	      <table>
+		<!-- query form mode -->
+		<xsl:variable name="queryfmode"><xsl:choose><xsl:when test="/page/pageRequest/paramList/param[@name='qfm']"><xsl:value-of select="/page/pageRequest/paramList/param[@name='qfm']/@value"/></xsl:when><xsl:otherwise>0</xsl:otherwise></xsl:choose></xsl:variable>
+		<tr><td valign='baseline'>Form type:</td><td><input type='radio' name='qfm' value='0'><xsl:if test="$queryfmode=0"><xsl:attribute name="checked"></xsl:attribute></xsl:if></input> simple <br />
+		    <input type='radio' name='qfm' value='1'><xsl:if test="$queryfmode=1"><xsl:attribute name="checked"></xsl:attribute></xsl:if></input> advanced</td></tr>
+		<!-- query form num boxes -->
+		<xsl:variable name="numbox"><xsl:choose><xsl:when test="/page/pageRequest/paramList/param[@name='qfn']"><xsl:value-of select="/page/pageRequest/paramList/param[@name='qfn']/@value"/></xsl:when><xsl:otherwise>4</xsl:otherwise></xsl:choose></xsl:variable>
+		<tr><td colspan='2'>with <select name="qfn">
+		      <option value="2"><xsl:if test="$numbox=2"><xsl:attribute name="selected"></xsl:attribute></xsl:if>2</option> 
+		      <option value="4"><xsl:if test="$numbox=4"><xsl:attribute name="selected"></xsl:attribute></xsl:if>4</option>
+		      <option value="6"><xsl:if test="$numbox=6"><xsl:attribute name="selected"></xsl:attribute></xsl:if>6</option>
+		      <option value="8"><xsl:if test="$numbox=8"><xsl:attribute name="selected"></xsl:attribute></xsl:if>8</option>
+		    </select> fields</td></tr>
+	      </table></td></tr>
+	</xsl:otherwise>
+      </xsl:choose>
+      <!-- case folding -->
+      <xsl:variable name="casevar" select="concat($ns,'case')"/>
+      <xsl:variable name="case"><xsl:choose><xsl:when test="/page/pageRequest/paramList/param[@name=$casevar]"><xsl:value-of select="/page/pageRequest/paramList/param[@name=$casevar]/@value"/></xsl:when><xsl:otherwise>1</xsl:otherwise></xsl:choose></xsl:variable>
+      <tr><td rowspan='2' valign='baseline'>Case differences:</td><td><input type='radio' name='{$ns}case' value='1'><xsl:if test="$case=1"><xsl:attribute name="checked"></xsl:attribute></xsl:if></input></td><td> ignore case differences</td></tr>
+      <tr><td><input type='radio' name='{$ns}case' value='0'><xsl:if test="$case=0"><xsl:attribute name="checked"></xsl:attribute></xsl:if></input></td><td> upper/lower case must match</td></tr>
+      <!-- stemming -->
+      <xsl:variable name="stemvar" select="concat($ns,'stem')"/>
+      <xsl:variable name="stem"><xsl:choose><xsl:when test="/page/pageRequest/paramList/param[@name=$stemvar]"><xsl:value-of select="/page/pageRequest/paramList/param[@name=$stemvar]/@value"/></xsl:when><xsl:otherwise>0</xsl:otherwise></xsl:choose></xsl:variable>
+      <tr><td  rowspan='2' valign='baseline'>Word endings:</td><td><input type='radio' name='{$ns}stem' value='1'><xsl:if test="$stem=1"><xsl:attribute name="checked"></xsl:attribute></xsl:if></input></td><td> ignore word endings</td></tr>
+      <tr><td><input type='radio' name='{$ns}stem' value='0'><xsl:if test="$stem=0"><xsl:attribute name="checked"></xsl:attribute></xsl:if></input></td><td> whole word must match</td></tr>
+      <!-- hit display -->
+      <xsl:variable name="maxvar" select="concat($ns,'maxDocs')"/>
+      <xsl:variable name="maxdocs"><xsl:choose><xsl:when test="/page/pageRequest/paramList/param[@name=$maxvar]"><xsl:value-of select="/page/pageRequest/paramList/param[@name=$maxvar]/@value"/></xsl:when><xsl:otherwise>50</xsl:otherwise></xsl:choose></xsl:variable>
+      <xsl:variable name="hits"><xsl:choose><xsl:when test="/page/pageRequest/paramList/param[@name='hitsPerPage']"><xsl:value-of select="/page/pageRequest/paramList/param[@name='hitsPerPage']/@value"/></xsl:when><xsl:otherwise>20</xsl:otherwise></xsl:choose></xsl:variable>
+      <tr><td colspan='3'>Return up to 
+	  <select name="{$ns}maxDocs">
+	    <option value="50"><xsl:if test="$maxdocs=50"><xsl:attribute name="selected"></xsl:attribute></xsl:if>50</option>
+	    <option value="100"><xsl:if test="$maxdocs=100"><xsl:attribute name="selected"></xsl:attribute></xsl:if>100</option>
+	    <option value="200"><xsl:if test="$maxdocs=200"><xsl:attribute name="selected"></xsl:attribute></xsl:if>200</option>
+	    <option value="-1"><xsl:if test="$maxdocs=-1"><xsl:attribute name="selected"></xsl:attribute></xsl:if>all</option>
+	  </select>
+	  hits with 
+	  <select name="hitsPerPage">
+	    <option value="10"><xsl:if test="$hits=10"><xsl:attribute name="selected"></xsl:attribute></xsl:if>10 </option> 
+	    <option value="20"><xsl:if test="$hits=20"><xsl:attribute name="selected"></xsl:attribute></xsl:if>20</option>
+	    <option value="50"><xsl:if test="$hits=50"><xsl:attribute name="selected"></xsl:attribute></xsl:if>50</option>
+	    <option value="-1"><xsl:if test="$hits=-1"><xsl:attribute name="selected"></xsl:attribute></xsl:if>all</option>
+	  </select>
+	  hits per page.
+	</td></tr>
+    </table>
+  </xsl:template>
+
+  <xsl:template name="text-search-prefs">
+    <!-- query mode -->
+    <xsl:variable name="querymode"><xsl:choose><xsl:when test="/page/pageRequest/paramList/param[@name='qm']"><xsl:value-of select="/page/pageRequest/paramList/param[@name='qm']/@value"/></xsl:when><xsl:otherwise>0</xsl:otherwise></xsl:choose></xsl:variable>
+    <tr><td rowspan='2' valign='baseline'>Query mode:</td><td><input type='radio' name='qm' value='0'><xsl:if test="$querymode=0"><xsl:attribute name="checked"></xsl:attribute></xsl:if></input></td><td> simple query mode</td></tr>
+	<tr><td><input type='radio' name='qm' value='1'><xsl:if test="$querymode=1"><xsl:attribute name="checked"></xsl:attribute></xsl:if></input></td><td> advanced query mode (allows boolean searching using !, &amp;, |, and parentheses)</td></tr>
+    
+    <!-- query box size -->
+    <xsl:variable name="boxsize"><xsl:choose><xsl:when test="/page/pageRequest/paramList/param[@name='qb']"><xsl:value-of select="/page/pageRequest/paramList/param[@name='qb']/@value"/></xsl:when><xsl:otherwise>0</xsl:otherwise></xsl:choose></xsl:variable>
+    <tr><td rowspan='2' valign='baseline'>Query box size:</td><td><input type='radio' name='qb' value='0'><xsl:if test="$boxsize=0"><xsl:attribute name="checked"></xsl:attribute></xsl:if></input></td><td> regular query box</td></tr>
+	<tr><td><input type='radio' name='qb' value='1'><xsl:if test="$boxsize=1"><xsl:attribute name="checked"></xsl:attribute></xsl:if></input></td><td> large query box</td></tr>
+  </xsl:template>
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/query-common.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/query-common.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/query-common.xsl	(revision 13928)
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+
+  <!--<xsl:include href="service-params.xsl"/>-->
+  <xsl:template match="service">
+    <xsl:param name="collName"/>
+    <xsl:variable name="subaction" select="../pageRequest/@subaction"/>
+    <div class="queryform">
+     <p> 
+      <form name="QueryForm" method="get" action="{$library_name}">
+        <input type="hidden" name="a" value="q"/>
+        <input type="hidden" name="sa" value="{$subaction}"/>
+        <input type="hidden" name="rt" value="rd"/>
+        <input type="hidden" name="s" value="{@name}"/>
+        <input type="hidden" name="c" value="{$collName}"/>
+        <input type="hidden" name="startPage" value="1"/>
+      <xsl:apply-templates select="paramList"/>
+      </form>
+     </p> 
+    </div>
+  </xsl:template>
+  
+  <!-- a special handling of the param list - we override the one in service-params -->
+  <xsl:template match="paramList" priority='2'>
+    <span class="textselect">
+	  Search for <xsl:apply-templates select="param[@name='index']"><xsl:with-param name="default"><xsl:apply-templates select="param[@name='index']" mode="calculate-default"/></xsl:with-param></xsl:apply-templates><xsl:if test="param[@name='level']">at <xsl:apply-templates select="param[@name='level']"><xsl:with-param name="default"><xsl:apply-templates select="param[@name='level']" mode="calculate-default"/></xsl:with-param></xsl:apply-templates> level</xsl:if><xsl:call-template name='query_mode'/>
+    </span>	
+    <span class="querybox"> 
+     <xsl:call-template name="query-and-submit"/>
+    </span>
+  </xsl:template>
+  
+  <!-- new template for match mode -->
+  <xsl:template name='query_mode'>
+    <xsl:variable name="qt" select="/page/pageRequest/paramList/param[@name='qt']/@value"/>
+    <xsl:choose>
+      <xsl:when test="$qt=1">
+	<xsl:variable name="qfm" select="/page/pageRequest/paramList/param[@name='qfm']/@value"/>
+	<xsl:choose>
+	  <xsl:when test="$qfm=1">
+	    and display results in <xsl:apply-templates select="param[@name='sortBy']"><xsl:with-param name="default"><xsl:apply-templates select="param[@name='sortBy']" mode="calculate-default"/></xsl:with-param></xsl:apply-templates> order
+	  </xsl:when>
+	  <xsl:otherwise>
+	    which contain <xsl:apply-templates select="param[@name='matchMode']"><xsl:with-param name="default"><xsl:apply-templates select="param[@name='matchMode']" mode="calculate-default"/></xsl:with-param></xsl:apply-templates> of
+	  </xsl:otherwise>
+	</xsl:choose>
+      </xsl:when>
+      <xsl:otherwise>
+	<xsl:variable name="ct" select="/page/pageRequest/paramList/param[@name='ct']/@value"/>
+	<xsl:variable name="qm" select="/page/pageRequest/paramList/param[@name='qm']/@value"/>
+	<xsl:choose>
+	  <xsl:when test="$qm=1 and $ct=0">
+	    using ranked/bool query
+	  </xsl:when>
+	  <xsl:when test="$qm=1 and $ct=1">
+	    and display results in <xsl:apply-templates select="param[@name='sortBy']"><xsl:with-param name="default"><xsl:apply-templates select="param[@name='sortBy']" mode="calculate-default"/></xsl:with-param></xsl:apply-templates> order
+	  </xsl:when>
+	  <xsl:otherwise>
+	    which contain <xsl:apply-templates select="param[@name='matchMode']"><xsl:with-param name="default"><xsl:apply-templates select="param[@name='matchMode']" mode="calculate-default"/></xsl:with-param></xsl:apply-templates> of the words
+	  </xsl:otherwise>
+	</xsl:choose>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template match="param[@name='matchMode']" mode='query1'>
+   <xsl:param name='default'/>
+    <xsl:variable name="qfm" select="/page/pageRequest/paramList/param[@name='qfm']/@value"/>
+    <xsl:choose>
+      <xsl:when test="$qfm=1">
+	and display results in <xsl:apply-templates select="../param[@name='sortBy']"><xsl:with-param name="default" select="$default"/></xsl:apply-templates> order
+      </xsl:when>
+      <xsl:otherwise>
+	which contain <xsl:apply-templates select='.'><xsl:with-param name="default" select="$default"/></xsl:apply-templates> of the words
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  
+  <xsl:template name="query-and-submit">
+    <xsl:variable name="qt" select="/page/pageRequest/paramList/param[@name='qt']/@value"/>
+    <xsl:choose>
+      <xsl:when test="$qt=1"> <!-- doing form query -->
+	<xsl:variable name="qfm" select="/page/pageRequest/paramList/param[@name='qfm']/@value"/>
+	<xsl:choose>
+	  <xsl:when test="$qfm=1">
+	     <xsl:apply-templates select="param[@name='complexField']"/>
+	  </xsl:when>
+	  <xsl:otherwise>
+	     <xsl:apply-templates select="param[@name='simpleField']"/>
+	  </xsl:otherwise>
+	</xsl:choose>
+	    <input type="submit"><xsl:attribute name="value"><xsl:value-of select="../displayItem[@name='submit']"/></xsl:attribute></input>
+	 
+      </xsl:when>
+      <xsl:otherwise> <!-- doing text query -->
+    <xsl:variable name="qb" select="/page/pageRequest/paramList/param[@name='qb']/@value"/>
+	<xsl:choose>
+	  <xsl:when test="$qb=1"><!-- large query box -->
+	       <textarea name="query" cols='63' rows='10'>
+		  <xsl:apply-templates select="param[@name='query']" mode="calculate-default"/><xsl:text> </xsl:text><!-- put a space here just in case there is no value- mozilla craps out if have a <textarea /> element -->
+		</textarea>
+	   <input type="submit"><xsl:attribute name="value"><xsl:value-of select="../displayItem[@name='submit']"/></xsl:attribute></input>
+	   </xsl:when>
+	  <xsl:otherwise>
+	 	<xsl:variable name="qs"><xsl:apply-templates select="param[@name='query']" mode="calculate-default"/></xsl:variable>
+		<nobr><xsl:apply-templates select="param[@name='query']"><xsl:with-param name="default" select="java:org.greenstone.gsdl3.util.XSLTUtil.tidyWhitespace($qs)"/></xsl:apply-templates><input type="submit"><xsl:attribute name="value"><xsl:value-of select="../displayItem[@name='submit']"/></xsl:attribute></input></nobr>
+	   </xsl:otherwise>
+	</xsl:choose>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  
+  <!-- overwrite the multi param to use our value of occurs, not the one with the param -->
+  <xsl:template match="param[@type='multi']" priority='2'>
+    <xsl:variable name="parent" select="@name"/>
+    <table>
+      <tr>
+	<xsl:for-each select="param">
+	  <xsl:variable name='pname' select='@name'/>
+	  <td><xsl:value-of select="displayItem[@name='name']"/></td>
+	</xsl:for-each>
+      </tr>
+      <!-- the number of times to display this is the qfn variable -->
+      <xsl:variable name="numbox"><xsl:choose><xsl:when test="/page/pageRequest/paramList/param[@name='qfn']"><xsl:value-of select="/page/pageRequest/paramList/param[@name='qfn']/@value"/></xsl:when><xsl:otherwise>4</xsl:otherwise></xsl:choose></xsl:variable>
+      <xsl:apply-templates select="." mode="contents"><xsl:with-param name="occurs" select="$numbox"/><xsl:with-param name="pos" select="0"/></xsl:apply-templates>
+    </table>
+  </xsl:template>
+
+  <xsl:template match="param[@type='multi']" mode="contents">
+    <xsl:param name="occurs"/>
+    <xsl:param name="pos"/>
+ <!--   <xsl:variable name="pos" select="@occurs - $occurs"/>-->
+    <tr><xsl:for-each select="param">
+	<xsl:variable name="pname" select="@name"/>
+	<xsl:variable name="values" select="/page/pageRequest/paramList/param[@name=$pname]/@value"/>
+	<td><xsl:choose>
+	    <xsl:when test="not(@ignore) or  @ignore != $pos">      
+	      <xsl:apply-templates select='.'><xsl:with-param name="default" select="java:org.greenstone.gsdl3.util.XSLTUtil.getNumberedItem($values, $pos)"/></xsl:apply-templates>
+	    </xsl:when>
+	    <xsl:otherwise><!-- put in a hidden placeholder -->
+	      <input type="hidden" name='{@name}' value=''/>
+	    </xsl:otherwise>
+	  </xsl:choose></td>
+      </xsl:for-each></tr> 
+    <!-- recursively call this template to get multiple entries -->
+    <xsl:if test="$pos &lt; ($occurs - 1)">
+      <xsl:apply-templates select="." mode="contents"><xsl:with-param name="occurs" select="$occurs"/><xsl:with-param name="pos" select="$pos+1"/></xsl:apply-templates>
+    </xsl:if>
+  </xsl:template>
+
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/query.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/query.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/query.xsl	(revision 13928)
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+
+  
+  <xsl:include href="style.xsl"/>
+  <xsl:include href="service-params.xsl"/>
+  <xsl:include href="querytools.xsl"/>
+  <xsl:include href="query-common.xsl"/>  
+  <xsl:output method="html"/>
+  
+  <xsl:template name="pageTitle">
+    <xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'nzdl')"/>
+  </xsl:template>
+
+  <!-- page specific style goes here -->
+  <xsl:template name="pageStyle"/>
+
+
+  <xsl:template match="pageResponse">
+    <xsl:variable name="collName"><xsl:value-of select="/page/pageRequest/paramList/param[@name='c']/@value"/></xsl:variable>
+
+      <xsl:call-template name="standardPageBanner">
+	<xsl:with-param name="collName" select="$collName"/>
+	<xsl:with-param name="pageType">search</xsl:with-param>
+      </xsl:call-template>
+      <xsl:call-template name="navigationBar">
+	<xsl:with-param name="collName" select="$collName"/>
+      </xsl:call-template>      
+    <div class="document">
+     <xsl:apply-templates select="service">
+	<xsl:with-param name="collName" select="$collName"/>
+      </xsl:apply-templates>
+    <xsl:if test="documentNodeList">
+      <xsl:call-template name="query-response">
+	<xsl:with-param name="collName" select="$collName"/>
+      </xsl:call-template>
+    </xsl:if>
+   </div>
+  </xsl:template>
+  
+  <xsl:template name="query-response">
+    <xsl:param name="collName"/>
+    <xsl:call-template name="dividerBar">
+      <xsl:with-param name='text'><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'query.results')"/></xsl:with-param></xsl:call-template>
+
+    <!-- If query term information is available, display it -->
+    <xsl:call-template name="termInfo"/>    
+    <!-- If the number of matching documents is known, display it -->
+    <xsl:call-template name="matchDocs"/>
+    
+    <!-- Display the matching documents -->
+    <xsl:call-template name="resultList">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>
+    <!-- next and prev links at bottom of page -->
+    <xsl:call-template name="resultNavigation"/>
+  </xsl:template>
+
+</xsl:stylesheet>  
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/style.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/style.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/classic/transform/style.xsl	(revision 13928)
@@ -0,0 +1,368 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+  
+  <!-- some global parameters - these are set by whoever is invoking the transformation -->
+  <xsl:param name="interface_name"/>
+  <xsl:param name="library_name"/>
+
+  <!-- the main page layout template is here -->
+  <xsl:template match="page">
+    <html>
+      <xsl:call-template name="pageHead"/>
+      <body class="bgimage">
+	<div id="page">
+	   <xsl:apply-templates select="pageResponse"/>
+	   <xsl:call-template name="greenstoneFooter"/>                	   
+	</div>
+      </body>
+    </html>
+  </xsl:template>
+
+  
+  <!-- put a space in the title in case the actual value is missing - mozilla will not display a page with no title-->
+  <xsl:template name="pageHead">
+    <head>
+      <title>
+	<xsl:call-template name="pageTitle"/><xsl:text> </xsl:text>
+      </title>
+      <xsl:call-template name="globalStyle"/>
+      <xsl:call-template name="pageStyle"/>
+    </head>
+  </xsl:template>
+
+  <!-- any global style stuff should go in here -->
+  <xsl:template name="globalStyle">
+    <link rel="stylesheet" href="interfaces/classic/style/classic.css" type="text/css"/>
+     <link rel="stylesheet" href="interfaces/classic/style/classic2.css" type="text/css"/>
+  </xsl:template>
+  
+  <xsl:template name="greenstonePageBanner">
+     <div id="banner">
+        <div class="collectimage">
+            <img src="interfaces/default/images/gsdlhead.gif"><xsl:attribute name="alt"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'gsdl')"/></xsl:attribute>
+            </img>
+	  </div>
+      </div>
+      <div class="bannerextra"></div>
+      <div id="content">
+        <xsl:call-template name="dividerBar">
+            <xsl:with-param name="text" select="'select a collection'"/> 
+        </xsl:call-template>
+      </div>			
+   </xsl:template>
+
+  <xsl:template name="genericPageBanner">
+    <xsl:param name='text'/>
+    <xsl:variable name="lang" select="/page/@lang"/>
+    <center>
+      <table width="100%">
+	<tr><td align="left"></td>
+	  <td align="right">
+	    <table>
+	      <tr><td class="gsbutton">
+		  <a class="gsbutton" href="{$library_name}?a=p&amp;sa=home">
+		    <xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'home_b')"/>
+		  </a>
+		</td></tr></table>
+	  </td>
+	</tr>
+      </table>
+    </center>
+    <xsl:call-template name="dividerBar"><xsl:with-param name='text' select="$text"/></xsl:call-template>
+  </xsl:template>
+  
+  <xsl:template name="standardPageBanner">
+    <xsl:param name="collName"/>
+    <xsl:param name="pageType"/>
+    <xsl:param name="clTop"/>
+    <xsl:variable name="this-element" select="/page/pageResponse/collection"/>
+     <div id="bannar">
+      <div class="pageinfo"> 
+          <xsl:call-template name="top-buttons">
+	    <xsl:with-param name="collName" select="$collName"/>
+	    <xsl:with-param name="pageType" select="$pageType"/>
+	  </xsl:call-template>
+          <xsl:if test="not(/page/pageRequest/@action='d')">
+  	<xsl:variable name="text">
+	  <xsl:choose>
+	    <xsl:when test="$pageType='browse'">
+	      <xsl:value-of select="/page/pageResponse/collection/serviceList/service[@name='ClassifierBrowse']/classifierList/classifier[@name=$clTop]/displayItem[@name='name']"/>
+	    </xsl:when>
+	    <xsl:otherwise>
+	      <xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, concat($pageType, '_t'))"/>
+	    </xsl:otherwise>
+	  </xsl:choose>
+	</xsl:variable>
+        <p class="bannertitle"><xsl:value-of select="$text"/></p>	 
+      </xsl:if>
+     </div>
+
+     <div class="collectimage">
+       <a href="{$library_name}?a=p&amp;sa=about&amp;c={$collName}">
+	    <xsl:choose>
+	      <xsl:when test="$this-element/displayItem[@name='icon']">
+		<img border="0">
+		  <xsl:attribute name="src">
+		    <xsl:value-of select="$this-element/metadataList/metadata[@name='httpPath']"/>/images/<xsl:value-of select="$this-element/displayItem[@name='icon']"/>
+		  </xsl:attribute>	
+		  <xsl:attribute name="alt">
+		    <xsl:value-of select="$this-element/displayItem[@name='name']"/>
+		  </xsl:attribute>
+		  <xsl:attribute name="title">
+		    <xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'aboutpage')"/>
+		  </xsl:attribute>
+		</img>
+	      </xsl:when>
+	      <xsl:otherwise>
+		<b><xsl:value-of select="$this-element/displayItem[@name='name']"/>hello</b>
+	      </xsl:otherwise>
+	    </xsl:choose>
+	  </a>
+       </div>
+      </div>
+    <div class="bannerextra"></div>	
+  </xsl:template>
+  
+  <xsl:template name="top-buttons">
+    <xsl:param name="collName"/>
+    <xsl:param name="pageType"/>
+    <p class="bannerlinks">
+      	  <a class="navlink" href="{$library_name}?a=p&amp;sa=home"><xsl:attribute name="title"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'home_tip')"/></xsl:attribute>
+	    <xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'home_b')"/>
+	  </a>
+	<!-- <xsl:choose>
+	<xsl:when test="$pageType='help'">
+             <xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'help_b')"/>
+        </xsl:when>
+	<xsl:otherwise>
+	  <a class="navlink" href="{$library_name}?a=p&amp;sa=help&amp;c={$collName}"><xsl:attribute name="title"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'help_tip')"/></xsl:attribute>
+	<xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'help_b')"/>
+          </a>
+       </xsl:otherwise>
+      </xsl:choose> -->
+       <xsl:choose>
+	  <xsl:when test="$pageType='pref'">
+	      <xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'pref_b')"/>
+	   </xsl:when>
+	  <xsl:otherwise>
+	    <a class="navlink" href="{$library_name}?a=p&amp;sa=pref&amp;c={$collName}"><xsl:attribute name="title"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'pref_tip')"/></xsl:attribute>
+		<xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'pref_b')"/>
+	    </a>
+	   </xsl:otherwise>
+	</xsl:choose>      
+    </p>
+  </xsl:template>
+  
+  <xsl:template name="navigationBar">
+    <xsl:param name="collName"/>
+    <xsl:param name="clTop"/>
+    <xsl:variable name="this-element" select="/page/pageResponse/collection"/>
+    <xsl:variable name="this-service" select="/page/pageResponse/service/@name"/>
+    <xsl:variable name="classifiers" select="$this-element/serviceList/service[@name='ClassifierBrowse']/classifierList"/>
+     <div class="navbar">
+       <p class="navbar">
+	 <xsl:if test="$this-element/serviceList/service[@type='query']">
+	   <xsl:call-template name="navbar-search"><xsl:with-param name="collName" select="$collName"/></xsl:call-template>
+	 </xsl:if>
+	
+	<xsl:for-each select="$classifiers/classifier">
+	  <xsl:apply-templates select="." mode="navbar">
+	    <xsl:with-param name="collName" select="$collName"/>
+	    <xsl:with-param name="clTop" select="$clTop"/>
+	  </xsl:apply-templates>
+	</xsl:for-each>
+	
+	<xsl:if test="$this-element/serviceList/service[@name='PhindApplet']">
+	  <xsl:call-template name="navbar-phind"><xsl:with-param name="collName" select="$collName"/></xsl:call-template>
+	</xsl:if>
+       </p>
+      </div> 
+  </xsl:template>
+
+  <xsl:template name="navbar-search">
+    <xsl:param name="collName"/>
+    <xsl:choose>
+      <xsl:when test="/page/pageRequest/@action='q'">	  
+	   <span class="narspace">search</span>
+      </xsl:when>
+      <xsl:otherwise>
+	<xsl:variable name="service">
+	  <xsl:choose>
+	    <xsl:when  test="not(/page/pageRequest/paramList/param[@name='ct'])">TextQuery</xsl:when>
+	    <xsl:when test="/page/pageRequest/paramList/param[@name='ct']/@value='0'">TextQuery</xsl:when>
+	    <xsl:when test="/page/pageRequest/paramList/param[@name='qt']/@value='1'"><xsl:choose><xsl:when test="/page/pageRequest/paramList/param[@name='qfm']/@value='1'">AdvancedFieldQuery</xsl:when><xsl:otherwise>FieldQuery</xsl:otherwise></xsl:choose></xsl:when>
+	    <xsl:otherwise>TextQuery</xsl:otherwise>
+	  </xsl:choose>
+	</xsl:variable>
+	<a class="navlink" href="{$library_name}?a=q&amp;rt=d&amp;s={$service}&amp;c={$collName}"><xsl:attribute name='title'><xsl:value-of select="/page/pageResponse/collection/service[@name=$service]/displayItem[@name='description']"/></xsl:attribute>search</a>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  
+  <xsl:template name="navbar-phind">
+    <xsl:param name="collName"/>
+    <xsl:choose>
+      <xsl:when test="/page/pageRequest/paramList/param[@name='s']/@value='PhindApplet'">
+	    <span class="narspace">phrases</span>
+      </xsl:when>
+      <xsl:otherwise>
+	 <a class="navlink" href="{$library_name}?a=a&amp;rt=d&amp;s=PhindApplet&amp;c={$collName}"><xsl:if test="/page/pageResponse/collection/service[@name='PhindApplet']/displayItem[@name='description']"><xsl:attribute name='title'><xsl:value-of select="/page/pageResponse/collection/service[@name='PhindApplet']/displayItem[@name='description']"/></xsl:attribute></xsl:if>phrases</a>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template match="classifier" mode="navbar">
+    <xsl:param name="collName"/>
+    <xsl:param name="clTop"/>
+    <xsl:choose>
+      <xsl:when test="/page/pageRequest/@action='b' and $clTop=@name">
+	 <span class="narspace"><xsl:value-of select="displayItem[@name='name']"/></span>
+      </xsl:when>
+      <xsl:otherwise>
+	<a class="navlink" href="{$library_name}?a=b&amp;rt=r&amp;s=ClassifierBrowse&amp;c={$collName}&amp;cl={@name}"><xsl:attribute name='title'><xsl:value-of select="displayItem[@name='description']"/></xsl:attribute><xsl:value-of select="displayItem[@name='name']"/></a>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template name="dividerBar">   
+    <xsl:param name='text'/>
+      <xsl:choose>
+      <xsl:when test="$text">
+	 <div class="divbar"><p class="navbar"><xsl:value-of select="$text"/></p></div>
+      </xsl:when>
+      <xsl:otherwise>
+	 <div class="divbar"><xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text></div>
+      </xsl:otherwise>
+    </xsl:choose> 
+  </xsl:template>
+  
+  <xsl:template name="nzdlPageBanner">
+       <div><img src="interfaces/nzdl/images/nzdl2gr.gif" width="457" height="181" ><xsl:attribute name="alt"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'nzdl')"/></xsl:attribute></img></div>
+       <!-- end of page banner -->  
+  </xsl:template>
+
+  <xsl:template name="greenstoneFooter">
+    <div class="divbar"><p class="navbar">powered by greenstone3</p>
+    </div>
+  </xsl:template>
+  
+  <xsl:template name="imagegreenstone">
+    <img src="interfaces/nzdl/images/gsdl.gif" width="140" height="77" border="0" hspace='0'><xsl:attribute name='alt'><xsl:call-template name='textimagegreenstone'/></xsl:attribute></img>
+  </xsl:template>
+  
+  <!-- Display the appropriate image, depending on the node type -->
+  <xsl:template match="documentNode" mode="displayNodeIcon">
+    
+    <!-- Root node: book icon (open or closed) -->
+    <xsl:choose>
+      <xsl:when test="@nodeType='root'">
+	<xsl:choose>
+	  <xsl:when test="documentNode">
+	    <xsl:call-template name="openbookimg">
+	      <xsl:with-param name="title">Close this book</xsl:with-param>
+	    </xsl:call-template>
+	  </xsl:when>
+	  <xsl:otherwise>
+	    <xsl:call-template name="closedbookimg">
+	      <xsl:with-param name="title">Open this document and view contents</xsl:with-param>
+	    </xsl:call-template>
+	  </xsl:otherwise>
+	</xsl:choose>
+      </xsl:when>
+      
+      <!-- Internal node: folder icon (open or closed) -->
+      <xsl:when test="@nodeType='internal'">
+	<xsl:choose>
+	  <xsl:when test="documentNode">
+	    <xsl:call-template name="openfolderimg">
+	      <xsl:with-param name="title">Close this folder</xsl:with-param>
+	    </xsl:call-template>
+	  </xsl:when>
+	  <xsl:otherwise>
+	    <xsl:call-template name="closedfolderimg">
+	      <xsl:with-param name="title">Open this folder and view contents</xsl:with-param>
+	    </xsl:call-template>
+	  </xsl:otherwise>
+	</xsl:choose>
+      </xsl:when>
+      
+      <!-- Leaf node: page icon, and this is the default -->
+      <xsl:otherwise>
+	<xsl:call-template name="textpageimg">
+	  <xsl:with-param name="title">View the document</xsl:with-param>
+	</xsl:call-template>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+
+  <xsl:template name="openbookimg">
+    <xsl:param name="alt"/>
+    <xsl:param name="title"/>
+    <img border="0" width="28" height="23" 
+      src="interfaces/default/images/openbook.gif"
+      alt="{$alt}" title="{$title}"/>
+  </xsl:template>
+
+  <xsl:template name="closedbookimg">
+    <xsl:param name="alt"/>
+    <xsl:param name="title"/>
+    <img border="0" width="18" height="11"  
+      src="interfaces/default/images/book.gif"
+      alt="{$alt}" title="{$title}"/>
+  </xsl:template>
+
+  <xsl:template name="openfolderimg">
+    <xsl:param name="alt"/>
+    <xsl:param name="title"/>
+    <img border="0" width="23" height="15"  
+      src="interfaces/default/images/openfldr.gif"
+      alt="{$alt}" title="{$title}"/>
+  </xsl:template>
+
+  <xsl:template name="closedfolderimg">
+    <xsl:param name="alt"/>
+    <xsl:param name="title"/>
+    <img border="0" width="23" height="15" 
+      src="interfaces/default/images/clsdfldr.gif"
+      alt="{$alt}" title="{$title}"/>
+  </xsl:template>
+
+  <xsl:template name="textpageimg">
+    <xsl:param name="alt"/>
+    <xsl:param name="title"/>
+    <img border="0" width="16" height="21"
+      src="interfaces/default/images/itext.gif"
+      alt="{$alt}" title="{$title}"/>
+  </xsl:template>
+
+  <xsl:template name="bookshelfimg">
+    <xsl:param name="alt"/>
+    <xsl:param name="title"/>
+    <img border="0" width="20" height="16" 
+      src="interfaces/default/images/bshelf.gif"  
+      alt="{$alt}" title="{$title}"/>
+  </xsl:template>
+
+  <xsl:template name="iconpdf">
+    <xsl:param name="alt">PDF</xsl:param>
+    <xsl:param name="title"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'texticonpdf')"/></xsl:param>
+    <img border="0" width='26' height='26' 
+      src='interfaces/default/images/ipdf.gif' 
+      alt='{$alt}' title='{$title}'/>
+  </xsl:template>
+    
+  <xsl:template name="icondoc">
+    <xsl:param name="alt">Word</xsl:param>
+    <xsl:param name="title"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'texticonmsword')"/></xsl:param>
+    <img border="0" width='26' height='26' 
+      src='interfaces/default/images/imsword.gif' 
+      alt='{$alt}' title='{$title}'/>
+  </xsl:template>
+
+</xsl:stylesheet>  
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/interfaceConfig.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/interfaceConfig.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/interfaceConfig.xml	(revision 13928)
@@ -0,0 +1,43 @@
+<interfaceConfig>
+  <actionList>
+    <action name='p' class='PageAction'>
+      <subaction name='home' xslt='home.xsl'/>
+      <subaction name='about' xslt='about.xsl'/>
+      <subaction name='help' xslt='help.xsl'/>
+      <subaction name='pref' xslt='pref.xsl'/>
+      <subaction name='nav' xslt='nav.xsl'/><!-- used for the collection header frame -->
+      <subaction name="html" xslt="html.xsl"/> <!-- use to put an external page into a frame with a collection header-->
+    </action>
+    <action name='q' class='QueryAction' xslt='query.xsl'/>
+    <action name='b' class='GS2BrowseAction' xslt='classifier.xsl'/>
+    <action name='a' class='AppletAction' xslt='applet.xsl'/>
+    <action name='d' class='DocumentAction' xslt='document.xsl'/>
+    <action name='xd' class='XMLDocumentAction'>
+      <subaction name='toc' xslt='document-toc.xsl'/>
+      <subaction name='text' xslt='document-content.xsl'/>
+    </action>
+    <action name='pr' class='ProcessAction' xslt='process.xsl'/>
+    <action name='s' class='SystemAction' xslt='system.xsl'/>
+    <action name='g' class='GeneralAction'>
+      <subaction name="berry" xslt='berry.xsl'/>
+    </action>
+  </actionList>
+  <languageList>
+    <language name="en">
+      <displayItem name='name'>English</displayItem>
+    </language>
+    <language name="fr">
+      <displayItem name='name'>FranÃ§ais</displayItem>
+    </language>
+    <language name='es'>
+      <displayItem name='name'>EspaÃ±ol</displayItem>
+    </language>
+    <language name="jp">
+      <displayItem name='name'>ã«ã»ãã</displayItem>
+    </language>
+  </languageList>
+  <optionList>
+    <option name="highlightQueryTerms" value="true"/>
+    <option name="berryBaskets" value="true"/>
+  </optionList>
+</interfaceConfig>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/YAHOO.js
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/YAHOO.js	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/YAHOO.js	(revision 13928)
@@ -0,0 +1,63 @@
+/*
+Copyright (c) 2006 Yahoo! Inc. All rights reserved.
+version 0.9.0
+*/
+
+/**
+ * @class The Yahoo global namespace
+ */
+var YAHOO = function() {
+
+    return {
+
+        /**
+         * Yahoo presentation platform utils namespace
+         */
+        util: {},
+
+        /**
+         * Yahoo presentation platform widgets namespace
+         */
+        widget: {},
+
+        /**
+         * Yahoo presentation platform examples namespace
+         */
+        example: {},
+
+        /**
+         * Returns the namespace specified and creates it if it doesn't exist
+         *
+         * YAHOO.namespace("property.package");
+         * YAHOO.namespace("YAHOO.property.package");
+         *
+         * Either of the above would create YAHOO.property, then
+         * YAHOO.property.package
+         *
+         * @param  {String} sNameSpace String representation of the desired
+         *                             namespace
+         * @return {Object}            A reference to the namespace object
+         */
+        namespace: function( sNameSpace ) {
+
+            if (!sNameSpace || !sNameSpace.length) {
+                return null;
+            }
+
+            var levels = sNameSpace.split(".");
+
+            var currentNS = YAHOO;
+
+            // YAHOO is implied, so it is ignored if it is included
+            for (var i=(levels[0] == "YAHOO") ? 1 : 0; i<levels.length; ++i) {
+                currentNS[levels[i]] = currentNS[levels[i]] || {};
+                currentNS = currentNS[levels[i]];
+            }
+
+            return currentNS;
+
+        }
+    };
+
+} ();
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/connection.js
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/connection.js	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/connection.js	(revision 13928)
@@ -0,0 +1,465 @@
+/*
+Copyright (c) 2006 Yahoo! Inc. All rights reserved.
+version 0.9.0
+*/
+
+/**
+ * The Connection Manager provides a simplified interface to the XMLHttpRequest
+ * object.  It handles cross-browser instantiantion of XMLHttpRequest, negotiates the
+ * interactive states and server response returning the results to a pre-defined
+ * callback function you create.
+ * @ class
+ */
+YAHOO.util.Connect = {};
+
+YAHOO.util.Connect =
+{
+  /**
+   * Array of  MSFT ActiveX ids for XMLHttpRequest.
+   * @private
+   * @type array
+   */
+	_msxml_progid:[
+		'MSXML2.XMLHTTP.5.0',
+		'MSXML2.XMLHTTP.4.0',
+		'MSXML2.XMLHTTP.3.0',
+		'MSXML2.XMLHTTP',
+		'Microsoft.XMLHTTP'
+		],
+
+  /**
+   * Array of HTTP header(s)
+   * @private
+   * @type array
+   */
+	_http_header:[],
+
+ /**
+  * Property modified by setForm() to determine if the transaction
+  * should be processed as a HTML form POST.
+  * @private
+  * @type boolean
+  */
+	_isFormPost:false,
+
+ /**
+  * Property modified by setForm() to the HTML form POST body.
+  * @private
+  * @type string
+  */
+	_sFormData:null,
+
+  /**
+   * The polling frequency, in milliseconds, for HandleReadyState.
+   * when attempting to determine a transaction's XHR  readyState.
+   * The default is 300 milliseconds.
+   * @private
+   * @type int
+   */
+	_polling_interval:300,
+
+  /**
+   * A transaction counter that increments the transaction id for each transaction.
+   * @private
+   * @type int
+   */
+	_transaction_id:0,
+
+  /**
+   * Member to add an ActiveX id to the existing xml_progid array.
+   * In the event(unlikely) a new ActiveX id is introduced, it can be added
+   * without internal code modifications.
+   * @public
+   * @param string id The ActiveX id to be added to initialize the XHR object.
+   * @return void
+   */
+	setProgId:function(id)
+	{
+		this.msxml_progid.unshift(id);
+	},
+
+  /**
+   * Instantiates a XMLHttpRequest object and returns an object with two properties:
+   * the XMLHttpRequest instance and the transaction id.
+   * @private
+   * @param {int} transactionId Property containing the transaction id for this transaction.
+   * @return connection object
+   * @type object
+   */
+	createXhrObject:function(transactionId)
+	{
+		var obj,http;
+		try
+		{
+			// Instantiates XMLHttpRequest in non-IE browsers and assigns to http.
+			http = new XMLHttpRequest();
+			//  Object literal with http and id properties
+			obj = { conn:http, tId:transactionId };
+		}
+		catch(e)
+		{
+			for(var i=0; i<this._msxml_progid.length; ++i){
+				try
+				{
+					// Instantiates XMLHttpRequest for IE and assign to http.
+					http = new ActiveXObject(this._msxml_progid[i]);
+					//  Object literal with http and id properties
+					obj = { conn:http, tId:transactionId };
+				}
+				catch(e){}
+			}
+		}
+		finally
+		{
+			return obj;
+		}
+	},
+
+  /**
+   * This method is called by asyncRequest and syncRequest to create a
+   * valid connection object for the transaction.  It also passes a
+   * transaction id and increments the transaction id counter.
+   * @private
+   * @return object
+   */
+	getConnectionObject:function()
+	{
+		var o;
+		var tId = this._transaction_id;
+
+		try
+		{
+			o = this.createXhrObject(tId);
+			if(o){
+				this._transaction_id++;
+			}
+		}
+		catch(e){}
+		finally
+		{
+			return o;
+		}
+	},
+
+  /**
+   * Method for initiating an asynchronous request via the XHR object.
+   * @public
+   * @param {string} method HTTP transaction method
+   * @param {string} uri Fully qualified path of resource
+   * @param callback User-defined callback function or object
+   * @param callbackArg User-defined callback arguments
+   * @param {string} postData POST body
+   * @return {object} Returns the connection object
+   */
+	asyncRequest:function(method, uri, callback, postData)
+	{
+		var errorObj;
+		var o = this.getConnectionObject();
+
+		if(!o){
+			return null;
+		}
+		else{
+			var oConn = this;
+
+			o.conn.open(method, uri, true);
+		    this.handleReadyState(o, callback);
+
+			if(this._isFormPost){
+				postData = this._sFormData;
+				this._isFormPost = false;
+			}
+			else if(postData){
+				this.initHeader('Content-Type','application/x-www-form-urlencoded');
+			}
+
+			//Verify whether the transaction has any user-defined HTTP headers
+			//and set them.
+			if(this._http_header.length>0){
+				this.setHeader(o);
+			}
+			postData?o.conn.send(postData):o.conn.send(null);
+
+			return o;
+		}
+	},
+
+  /**
+   * This method serves as a timer that polls the XHR object's readyState
+   * property during a transaction, instead of binding a callback to the
+   * onreadystatechange event.  Upon readyState 4, handleTransactionResponse
+   * will process the response, and the timer will be cleared.
+   *
+   * @private
+   * @param {object} o The connection object
+   * @param callback User-defined callback object
+   * @param callbackArg User-defined arguments passed to the callback
+   * @return void
+   */
+	handleReadyState:function(o, callback)
+	{
+		var oConn = this;
+		var poll = window.setInterval(
+			function(){
+				if(o.conn.readyState==4){
+					oConn.handleTransactionResponse(o, callback);
+					window.clearInterval(poll);
+				}
+			}
+		,this._polling_interval);
+	},
+
+  /**
+   * This method attempts to interpret the server response and
+   * determine whether the transaction was successful, or if an error or
+   * exception was encountered.
+   *
+   * @private
+   * @param {object} o The connection object
+   * @param {function} callback - User-defined callback object
+   * @param {} callbackArg - User-defined arguments to be passed to the callback
+   * @return void
+   */
+	handleTransactionResponse:function(o, callback)
+	{
+		var httpStatus;
+		var responseObject;
+
+		try{
+			httpStatus = o.conn.status;
+		}
+		catch(e){
+			// 13030 is the custom code to indicate the condition -- in Mozilla/FF --
+			// when the o object's status and statusText properties are
+			// unavailable, and a query attempt throws an exception.
+			httpStatus = 13030;
+		}
+
+		if(httpStatus == 200){
+			responseObject = this.createResponseObject(o, callback.argument);
+			if(callback.success){
+				if(!callback.scope){
+					callback.success(responseObject);
+				}
+				else{
+					callback.success.apply(callback.scope, [responseObject]);
+				}
+			}
+		}
+		else{
+			switch(httpStatus){
+				// The following case labels are wininet.dll error codes that may be encountered.
+				// Server timeout
+				case 12002:
+				// 12029 to 12031 correspond to dropped connections.
+				case 12029:
+				case 12030:
+				case 12031:
+				// Connection closed by server.
+				case 12152:
+				// See above comments for variable status.
+				case 13030:
+					responseObject = this.createExceptionObject(o, callback.argument);
+					if(callback.failure){
+						if(!callback.scope){
+							callback.failure(responseObject);
+						}
+						else{
+							callback.failure.apply(callback.scope,[responseObject]);
+						}
+					}
+					break;
+				default:
+					responseObject = this.createResponseObject(o, callback.argument);
+					if(callback.failure){
+						if(!callback.scope){
+							callback.failure(responseObject);
+						}
+						else{
+							callback.failure.apply(callback.scope,[responseObject]);
+						}
+					}
+			}
+		}
+
+		this.releaseObject(o);
+	},
+
+  /**
+   * This method evaluates the server response, creates and returns the results via
+   * its properties.  Success and failure cases(and exceptions) will differ in their defined properties
+   * but property "type" will confirm the transaction's status.
+   * @private
+   * @param {object} o The connection object
+   * @param {} callbackArg User-defined arguments to be passed to the callback
+   * @param {boolean} isSuccess Indicates whether the transaction was successful or not.
+   * @return object
+   */
+	createResponseObject:function(o, callbackArg)
+	{
+		var obj = {};
+
+		obj.tId = o.tId;
+		obj.status = o.conn.status;
+		obj.statusText = o.conn.statusText;
+		obj.allResponseHeaders = o.conn.getAllResponseHeaders();
+		obj.responseText = o.conn.responseText;
+		obj.responseXML = o.conn.responseXML;
+		if(callbackArg){
+			obj.argument = callbackArg;
+		}
+
+		return obj;
+	},
+
+  /**
+   * If a transaction cannot be completed due to dropped or closed connections,
+   * there may be not be enough information to build a full response object.
+   * The object's property "type" value will be "failure", and two additional
+   * unique, properties are added - errorCode and errorText.
+   * @private
+   * @param {int} tId Transaction Id
+   * @param callbackArg The user-defined arguments
+   * @param {string} errorCode Error code associated with the exception.
+   * @param {string} errorText Error message describing the exception.
+   * @return object
+   */
+	createExceptionObject:function(tId, callbackArg)
+	{
+		var COMM_CODE = 0;
+		var COMM_ERROR = 'communication failure';
+
+		var obj = {};
+
+		obj.tId = tId;
+		obj.status = COMM_CODE;
+		obj.statusText = COMM_ERROR;
+		if(callbackArg){
+			obj.argument = callbackArg;
+		}
+
+		return obj;
+	},
+
+  /**
+   * Accessor that stores the HTTP headers for each transaction.
+   * @public
+   * @param {string} label The HTTP header label
+   * @param {string} value The HTTP header value
+   * @return void
+   */
+	initHeader:function(label,value)
+	{
+		var oHeader = [label,value];
+		this._http_header.push(oHeader);
+	},
+
+  /**
+   * Accessor that sets the HTTP headers for each transaction.
+   * @private
+   * @param {object} o The connection object for the transaction.
+   * @return void
+   */
+	setHeader:function(o)
+	{
+		var oHeader = this._http_header;
+		for(var i=0;i<oHeader.length;i++){
+			o.conn.setRequestHeader(oHeader[i][0],oHeader[i][1]);
+		}
+		oHeader.splice(0,oHeader.length);
+	},
+
+  /**
+   * This method assembles the form label and value pairs and
+   * constructs an encoded POST body.  Both syncRequest()
+   * and asyncRequest() will automatically initialize the
+   * transaction with a HTTP header Content-Type of
+   * application/x-www-form-urlencoded.
+   * @public
+   * @param {string} formName value of form name attribute
+   * @return void
+   */
+	setForm:function(formName)
+	{
+		this._sFormData = '';
+		var oForm = document.forms[formName];
+		var oElement, elName, elValue;
+		// iterate over the form elements collection to construct the
+		// label-value pairs.
+		for (var i=0; i<oForm.elements.length; i++){
+			oElement = oForm.elements[i];
+			elName = oForm.elements[i].name;
+			elValue = oForm.elements[i].value;
+			switch (oElement.type)
+			{
+				case 'select-multiple':
+					for(var j=0; j<oElement.options.length; j++){
+						if(oElement.options[j].selected){
+							this._sFormData += encodeURIComponent(elName) + '=' + encodeURIComponent(oElement.options[j].value) + '&';
+						}
+					}
+					break;
+				case 'radio':
+				case 'checkbox':
+					if(oElement.checked){
+						this._sFormData += encodeURIComponent(elName) + '=' + encodeURIComponent(elValue) + '&';
+					}
+					break;
+				case 'file':
+				// stub case as XMLHttpRequest will only send the file path as a string.
+					break;
+				case undefined:
+				// stub case for fieldset element which returns undefined.
+					break;
+				default:
+					this._sFormData += encodeURIComponent(elName) + '=' + encodeURIComponent(elValue) + '&';
+					break;
+			}
+		}
+		this._sFormData = this._sFormData.substr(0, this._sFormData.length - 1);
+		this._isFormPost = true;
+		this.initHeader('Content-Type','application/x-www-form-urlencoded');
+	},
+
+  /**
+   * Public method to terminate a transaction, if it has not reached readyState 4.
+   * @public
+   * @param {object} o The connection object returned by asyncRequest.
+   * @return void
+   */
+	abort:function(o)
+	{
+		if(this.isCallInProgress(o)){
+			o.conn.abort();
+			this.releaseObject(o);
+		}
+	},
+
+  /**
+   * Accessor to check if the transaction associated with the connection object
+   * is still being processed.
+   * @public
+   * @param {object} o The connection object returned by asyncRequest
+   * @return boolean
+   */
+	isCallInProgress:function(o)
+	{
+		if(o){
+			return o.conn.readyState != 4 && o.conn.readyState != 0;
+		}
+	},
+
+  /**
+   * Dereference the XHR instance and the connection object after the transaction is completed.
+   * @private
+   * @param {object} o The connection object
+   * @return void
+   */
+	releaseObject:function(o)
+	{
+			//dereference the XHR instance.
+			o.conn = null;
+			//dereference the connection object.
+			o = null;
+	}
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/dom.js
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/dom.js	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/dom.js	(revision 13928)
@@ -0,0 +1,433 @@
+/*
+Copyright (c) 2006 Yahoo! Inc. All rights reserved.
+version 0.9.0
+*/
+
+/**
+ * @class Provides helper methods for DOM elements.
+ */
+YAHOO.util.Dom = new function() {
+
+   /**
+    * Returns an HTMLElement reference
+    * @param {String | HTMLElement} Accepts either a string to use as an ID for getting a DOM reference, or an actual DOM reference.
+    * @return {HTMLElement} A DOM reference to an HTML element.
+    */
+   this.get = function(el) {
+      if (typeof el == 'string') { // accept object or id
+         el = document.getElementById(el);
+      }
+
+      return el;
+   };
+
+   /**
+    * Normalizes currentStyle and ComputedStyle.
+    * @param {String | HTMLElement} Accepts either a string to use as an ID for getting a DOM reference, or an actual DOM reference.
+    * @param {String} property The style property whose value is returned.
+    * @return {String} The current value of the style property.
+    */
+   this.getStyle = function(el, property) {
+      var value = null;
+      var dv = document.defaultView;
+
+      el = this.get(el);
+
+      if (property == 'opacity' && el.filters) {// IE opacity
+         value = 1;
+         try {
+            value = el.filters.item('DXImageTransform.Microsoft.Alpha').opacity / 100;
+         } catch(e) {
+            try {
+               value = el.filters.item('alpha').opacity / 100;
+            } catch(e) {}
+         }
+      }
+      else if (el.style[property]) {
+         value = el.style[property];
+      }
+      else if (el.currentStyle && el.currentStyle[property]) {
+         value = el.currentStyle[property];
+      }
+      else if ( dv && dv.getComputedStyle )
+      {  // convert camelCase to hyphen-case
+
+         var converted = '';
+         for(i = 0, len = property.length;i < len; ++i) {
+            if (property.charAt(i) == property.charAt(i).toUpperCase()) {
+               converted = converted + '-' + property.charAt(i).toLowerCase();
+            } else {
+               converted = converted + property.charAt(i);
+            }
+         }
+
+         if (dv.getComputedStyle(el, '').getPropertyValue(converted)) {
+            value = dv.getComputedStyle(el, '').getPropertyValue(converted);
+         }
+      }
+
+      return value;
+   };
+
+   /**
+    * Wrapper for setting style properties of HTMLElements.  Normalizes "opacity" across modern browsers.
+    * @param {String | HTMLElement} Accepts either a string to use as an ID for getting a DOM reference, or an actual DOM reference.
+    * @param {String} property The style property to be set.
+    * @param {String} val The value to apply to the given property.
+    */
+   this.setStyle = function(el, property, val) {
+      el = this.get(el);
+      switch(property) {
+         case 'opacity' :
+            if (el.filters) {
+               el.style.filter = 'alpha(opacity=' + val * 100 + ')';
+
+               if (!el.currentStyle.hasLayout) {
+                  el.style.zoom = 1;
+               }
+            } else {
+               el.style.opacity = val;
+               el.style['-moz-opacity'] = val;
+               el.style['-khtml-opacity'] = val;
+            }
+            break;
+         default :
+            el.style[property] = val;
+      }
+   };
+
+   /**
+    * Gets the current position of an element based on page coordinates.  Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
+    * @param {String | HTMLElement} Accepts either a string to use as an ID for getting a DOM reference, or an actual DOM reference.
+    */
+   this.getXY = function(el) {
+      el = this.get(el);
+
+      // has to be part of document to have pageXY
+      if (el.parentNode === null || this.getStyle(el, 'display') == 'none') {
+         return false;
+      }
+
+      /**
+       * Position of the html element (x, y)
+       * @private
+       * @type Array
+       */
+      var parent = null;
+      var pos = [];
+      var box;
+
+      if (el.getBoundingClientRect) { // IE
+         box = el.getBoundingClientRect();
+         var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
+         var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
+
+         return [box.left + scrollLeft, box.top + scrollTop];
+      }
+      else if (document.getBoxObjectFor) { // gecko
+         box = document.getBoxObjectFor(el);
+         pos = [box.x, box.y];
+      }
+      else { // safari/opera
+         pos = [el.offsetLeft, el.offsetTop];
+         parent = el.offsetParent;
+         if (parent != el) {
+            while (parent) {
+               pos[0] += parent.offsetLeft;
+               pos[1] += parent.offsetTop;
+               parent = parent.offsetParent;
+            }
+         }
+
+         // opera & (safari absolute) incorrectly account for body offsetTop
+         var ua = navigator.userAgent.toLowerCase();
+         if (
+            ua.indexOf('opera') != -1
+            || ( ua.indexOf('safari') != -1 && this.getStyle(el, 'position') == 'absolute' )
+         ) {
+            pos[1] -= document.body.offsetTop;
+         }
+      }
+
+      if (el.parentNode) { parent = el.parentNode; }
+      else { parent = null; }
+
+      while (parent && parent.tagName != 'BODY' && parent.tagName != 'HTML') {
+         pos[0] -= parent.scrollLeft;
+         pos[1] -= parent.scrollTop;
+
+         if (parent.parentNode) { parent = parent.parentNode; }
+         else { parent = null; }
+      }
+
+      return pos;
+   };
+
+   /**
+    * Gets the current X position of an element based on page coordinates.  The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
+    * @param {String | HTMLElement} Accepts either a string to use as an ID for getting a DOM reference, or an actual DOM reference.
+    */
+   this.getX = function(el) {
+      return this.getXY(el)[0];
+   };
+
+   /**
+    * Gets the current Y position of an element based on page coordinates.  Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
+    * @param {String | HTMLElement} Accepts either a string to use as an ID for getting a DOM reference, or an actual DOM reference.
+    */
+   this.getY = function(el) {
+      return this.getXY(el)[1];
+   };
+
+   /**
+    * Set the position of an html element in page coordinates, regardless of how the element is positioned.
+    * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
+    * @param {String | HTMLElement} Accepts either a string to use as an ID for getting a DOM reference, or an actual DOM reference.
+    * @param {array} pos Contains X & Y values for new position (coordinates are page-based)
+    */
+   this.setXY = function(el, pos, noRetry) {
+      el = this.get(el);
+      var pageXY = YAHOO.util.Dom.getXY(el);
+      if (pageXY === false) { return false; } // has to be part of doc to have pageXY
+
+      if (this.getStyle(el, 'position') == 'static') { // default to relative
+         this.setStyle(el, 'position', 'relative');
+      }
+
+      var delta = [
+         parseInt( YAHOO.util.Dom.getStyle(el, 'left'), 10 ),
+         parseInt( YAHOO.util.Dom.getStyle(el, 'top'), 10 )
+      ];
+
+      if ( isNaN(delta[0]) ) { delta[0] = 0; } // defalts to 'auto'
+      if ( isNaN(delta[1]) ) { delta[1] = 0; }
+
+      if (pos[0] !== null) { el.style.left = pos[0] - pageXY[0] + delta[0] + 'px'; }
+      if (pos[1] !== null) { el.style.top = pos[1] - pageXY[1] + delta[1] + 'px'; }
+
+      var newXY = this.getXY(el);
+
+      // if retry is true, try one more time if we miss
+      if (!noRetry && (newXY[0] != pos[0] || newXY[1] != pos[1]) ) {
+         this.setXY(el, pos, true);
+      }
+
+      return true;
+   };
+
+   /**
+    * Set the X position of an html element in page coordinates, regardless of how the element is positioned.
+    * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
+    * @param {String | HTMLElement} Accepts either a string to use as an ID for getting a DOM reference, or an actual DOM reference.
+    * @param {Int} x to use as the X coordinate.
+    */
+   this.setX = function(el, x) {
+      return this.setXY(el, [x, null]);
+   };
+
+   /**
+    * Set the Y position of an html element in page coordinates, regardless of how the element is positioned.
+    * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
+    * @param {String | HTMLElement} Accepts either a string to use as an ID for getting a DOM reference, or an actual DOM reference.
+    * @param {Int} Value to use as the Y coordinate.
+    */
+   this.setY = function(el, y) {
+      return this.setXY(el, [null, y]);
+   };
+
+   /**
+    * Returns the region position of the given element.
+    * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
+    * @param {String | HTMLElement} Accepts either a string to use as an ID for getting a DOM reference, or an actual DOM reference.
+    * @return {Region} A Region instance containing "top, left, bottom, right" member data.
+    */
+   this.getRegion = function(el) {
+      el = this.get(el);
+      return new YAHOO.util.Region.getRegion(el);
+   };
+
+   /**
+    * Returns the width of the client (viewport).
+    * @return {Int} The width of the viewable area of the page.
+    */
+   this.getClientWidth = function() {
+      return (
+         document.documentElement.offsetWidth
+         || document.body.offsetWidth
+      );
+   };
+
+   /**
+    * Returns the height of the client (viewport).
+    * @return {Int} The height of the viewable area of the page.
+    */
+   this.getClientHeight = function() {
+      return (
+         self.innerHeight
+         || document.documentElement.clientHeight
+         || document.body.clientHeight
+      );
+   };
+};
+
+/**
+ * @class A region is a representation of an object on a grid.  It is defined
+ * by the top, right, bottom, left extents, so is rectangular by default.  If
+ * other shapes are required, this class could be extended to support it.
+ *
+ * @param {int} t the top extent
+ * @param {int} r the right extent
+ * @param {int} b the bottom extent
+ * @param {int} l the left extent
+ * @constructor
+ */
+YAHOO.util.Region = function(t, r, b, l) {
+
+    /**
+     * The region's top extent
+     * @type int
+     */
+    this.top = t;
+
+    /**
+     * The region's right extent
+     * @type int
+     */
+    this.right = r;
+
+    /**
+     * The region's bottom extent
+     * @type int
+     */
+    this.bottom = b;
+
+    /**
+     * The region's left extent
+     * @type int
+     */
+    this.left = l;
+};
+
+/**
+ * Returns true if this region contains the region passed in
+ *
+ * @param  {Region}  region The region to evaluate
+ * @return {boolean}        True if the region is contained with this region,
+ *                          else false
+ */
+YAHOO.util.Region.prototype.contains = function(region) {
+    return ( region.left   >= this.left   &&
+             region.right  <= this.right  &&
+             region.top    >= this.top    &&
+             region.bottom <= this.bottom    );
+};
+
+/**
+ * Returns the area of the region
+ *
+ * @return {int} the region's area
+ */
+YAHOO.util.Region.prototype.getArea = function() {
+    return ( (this.bottom - this.top) * (this.right - this.left) );
+};
+
+/**
+ * Returns the region where the passed in region overlaps with this one
+ *
+ * @param  {Region} region The region that intersects
+ * @return {Region}        The overlap region, or null if there is no overlap
+ */
+YAHOO.util.Region.prototype.intersect = function(region) {
+    var t = Math.max( this.top,    region.top    );
+    var r = Math.min( this.right,  region.right  );
+    var b = Math.min( this.bottom, region.bottom );
+    var l = Math.max( this.left,   region.left   );
+
+    if (b >= t && r >= l) {
+        return new YAHOO.util.Region(t, r, b, l);
+    } else {
+        return null;
+    }
+};
+
+/**
+ * Returns the region representing the smallest region that can contain both
+ * the passed in region and this region.
+ *
+ * @param  {Region} region The region that to create the union with
+ * @return {Region}        The union region
+ */
+YAHOO.util.Region.prototype.union = function(region) {
+    var t = Math.min( this.top,    region.top    );
+    var r = Math.max( this.right,  region.right  );
+    var b = Math.max( this.bottom, region.bottom );
+    var l = Math.min( this.left,   region.left   );
+
+    return new YAHOO.util.Region(t, r, b, l);
+};
+
+/**
+ * toString
+ * @return string the region properties
+ */
+YAHOO.util.Region.prototype.toString = function() {
+    return ( "Region {" +
+             "  t: "    + this.top    +
+             ", r: "    + this.right  +
+             ", b: "    + this.bottom +
+             ", l: "    + this.left   +
+             "}" );
+}
+
+/**
+ * Returns a region that is occupied by the DOM element
+ *
+ * @param  {HTMLElement} el The element
+ * @return {Region}         The region that the element occupies
+ * @static
+ */
+YAHOO.util.Region.getRegion = function(el) {
+    var p = YAHOO.util.Dom.getXY(el);
+
+    var t = p[1];
+    var r = p[0] + el.offsetWidth;
+    var b = p[1] + el.offsetHeight;
+    var l = p[0];
+
+    return new YAHOO.util.Region(t, r, b, l);
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * @class
+ *
+ * A point is a region that is special in that it represents a single point on
+ * the grid.
+ *
+ * @param {int} x The X position of the point
+ * @param {int} y The Y position of the point
+ * @constructor
+ * @extends Region
+ */
+YAHOO.util.Point = function(x, y) {
+    /**
+     * The X position of the point
+     * @type int
+     */
+    this.x      = x;
+
+    /**
+     * The Y position of the point
+     * @type int
+     */
+    this.y      = y;
+
+    this.top    = y;
+    this.right  = x;
+    this.bottom = y;
+    this.left   = x;
+};
+
+YAHOO.util.Point.prototype = new YAHOO.util.Region();
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/dragdrop-debug.js
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/dragdrop-debug.js	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/dragdrop-debug.js	(revision 13928)
@@ -0,0 +1,2517 @@
+/*
+Copyright (c) 2006 Yahoo! Inc. All rights reserved.
+version 0.9.0
+*/
+
+/**
+ * @class Defines the interface and base operation of items that that can be
+ * dragged or can be drop targets.  It was designed to be extended, overriding
+ * the event handlers for startDrag, onDrag, onDragOver, onDragOut.
+ * Up to three html elements can be associated with a DragDrop instance:
+ * <ul>
+ * <li>linked element: the element that is passed into the constructor.
+ * This is the element which defines the boundaries for interaction with
+ * other DragDrop objects.</li>
+ * <li>handle element(s): The drag operation only occurs if the element that
+ * was clicked matches a handle element.  By default this is the linked
+ * element, but there are times that you will want only a portion of the
+ * linked element to initiate the drag operation, and the setHandleElId()
+ * method provides a way to define this.</li>
+ * <li>drag element: this represents an the element that would be moved along
+ * with the cursor during a drag operation.  By default, this is the linked
+ * element itself as in {@link YAHOO.util.DD}.  setDragElId() lets you define
+ * a separate element that would be moved, as in {@link YAHOO.util.DDProxy}
+ * </li>
+ * </ul>
+ * This class should not be instantiated until the onload event to ensure that
+ * the associated elements are available.
+ * The following would define a DragDrop obj that would interact with any
+ * other * DragDrop obj in the "group1" group:
+ * <pre>
+ *  dd = new YAHOO.util.DragDrop("div1", "group1");
+ * </pre>
+ * Since none of the event handlers have been implemented, nothing would
+ * actually happen if you were to run the code above.  Normally you would
+ * override this class or one of the default implementations, but you can
+ * also override the methods you want on an instance of the class...
+ * <pre>
+ *  dd.onDragDrop = function(e, id) {
+ *   alert("dd was dropped on " + id);
+ *  }
+ * </pre>
+ * @constructor
+ * @param {String} id of the element that is linked to this instance
+ * @param {String} sGroup the group of related DragDrop objects
+ */
+YAHOO.util.DragDrop = function(id, sGroup) {
+    if (id) {
+        this.init(id, sGroup);
+    }
+};
+
+YAHOO.util.DragDrop.prototype = {
+
+    /**
+     * The id of the element associated with this object.  This is what we
+     * refer to as the "linked element" because the size and position of
+     * this element is used to determine when the drag and drop objects have
+     * interacted.
+     *
+     * @type String
+     */
+    id: null,
+
+    /**
+     * The id of the element that will be dragged.  By default this is same
+     * as the linked element , but could be changed to another element. Ex:
+     * YAHOO.util.DDProxy
+     *
+     * @type String
+     * @private
+     */
+    dragElId: null,
+
+    /**
+     * the id of the element that initiates the drag operation.  By default
+     * this is the linked element, but could be changed to be a child of this
+     * element.  This lets us do things like only starting the drag when the
+     * header element within the linked html element is clicked.
+     *
+     * @type String
+     * @private
+     */
+    handleElId: null,
+
+    /**
+     * An array of HTML tags that will be ignored if clicked.
+     */
+    invalidHandleTypes: null,
+
+    /**
+     * The linked element's absolute X position at the time the drag was
+     * started
+     *
+     * @type int
+     * @private
+     */
+    startPageX: 0,
+
+    /**
+     * The linked element's absolute X position at the time the drag was
+     * started
+     *
+     * @type int
+     * @private
+     */
+    startPageY: 0,
+
+    /**
+     * The group defines a logical collection of DragDrop objects that are
+     * related.  Instances only get events when interacting with other
+     * DragDrop object in the same group.  This lets us define multiple
+     * groups using a single DragDrop subclass if we want.
+     *
+     */
+    groups: null,
+
+    /**
+     * Individual drag/drop instances can be locked.  This will prevent
+     * onmousedown start drag.
+     *
+     * @type boolean
+     * @private
+     */
+    locked: false,
+
+    /**
+     * Lock this instance
+     */
+    lock: function() { this.locked = true; },
+
+    /**
+     * Unlock this instace
+     */
+    unlock: function() { this.locked = false; },
+
+    /**
+     * By default, all insances can be a drop target.  This can be disabled by
+     * setting isTarget to false.
+     *
+     * @type boolean
+     */
+    isTarget: true,
+
+    /**
+     * The padding configured for this drag and drop object for calculating
+     * the drop zone intersection with this object.
+     */
+    padding: null,
+
+    /**
+     * @private
+     */
+    _domRef: null,
+
+    /**
+     * Internal typeof flag
+     * @private
+     */
+    __ygDragDrop: true,
+
+    /**
+     * Set to true when horizontal contraints are applied
+     *
+     * @type boolean
+     * @private
+     */
+    constrainX: false,
+
+    /**
+     * Set to true when vertical contraints are applied
+     *
+     * @type boolean
+     * @private
+     */
+    constrainY: false,
+
+    /**
+     * The left constraint
+     *
+     * @type int
+     * @private
+     */
+    minX: 0,
+
+    /**
+     * The right constraint
+     *
+     * @type int
+     * @private
+     */
+    maxX: 0,
+
+    /**
+     * The up constraint
+     *
+     * @type int
+     * @private
+     */
+    minY: 0,
+
+    /**
+     * The down constraint
+     *
+     * @type int
+     * @private
+     */
+    maxY: 0,
+
+    /**
+     * Maintain offsets when we resetconstraints.  Used to maintain the
+     * slider thumb value, and this needs to be fixed.
+     * @type boolean
+     */
+    maintainOffset: false,
+
+    /**
+     * Array of pixel locations the element will snap to if we specified a
+     * horizontal graduation/interval.  This array is generated automatically
+     * when you define a tick interval.
+     * @type int[]
+     */
+    xTicks: null,
+
+    /**
+     * Array of pixel locations the element will snap to if we specified a
+     * vertical graduation/interval.  This array is generated automatically
+     * when you define a tick interval.
+     * @type int[]
+     */
+    yTicks: null,
+
+    /**
+     * By default the drag and drop instance will only respond to the primary
+     * button click (left button for a right-handed mouse).  Set to true to
+     * allow drag and drop to start with any mouse click that is propogated
+     * by the browser
+     * @type boolean
+     */
+    primaryButtonOnly: true,
+
+    /**
+     * Code that executes immediately before the startDrag event
+     * @private
+     */
+    b4StartDrag: function(x, y) { },
+
+    /**
+     * Abstract method called after a drag/drop object is clicked
+     * and the drag or mousedown time thresholds have beeen met.
+     *
+     * @param {int} X click location
+     * @param {int} Y click location
+     */
+    startDrag: function(x, y) { /* override this */ },
+
+    /**
+     * Code that executes immediately before the onDrag event
+     * @private
+     */
+    b4Drag: function(e) { },
+
+    /**
+     * Abstract method called during the onMouseMove event while dragging an
+     * object.
+     *
+     * @param {Event} e
+     */
+    onDrag: function(e) { /* override this */ },
+
+    /**
+     * Code that executes immediately before the onDragEnter event
+     * @private
+     */
+    // b4DragEnter: function(e) { },
+
+    /**
+     * Abstract method called when this element fist begins hovering over
+     * another DragDrop obj
+     *
+     * @param {Event} e
+     * @param {String || YAHOO.util.DragDrop[]} id In POINT mode, the element
+     * id this is hovering over.  In INTERSECT mode, an array of one or more
+     * dragdrop items being hovered over.
+     */
+    onDragEnter: function(e, id) { /* override this */ },
+
+    /**
+     * Code that executes immediately before the onDragOver event
+     * @private
+     */
+    b4DragOver: function(e) { },
+
+    /**
+     * Abstract method called when this element is hovering over another
+     * DragDrop obj
+     *
+     * @param {Event} e
+     * @param {String || YAHOO.util.DragDrop[]} id In POINT mode, the element
+     * id this is hovering over.  In INTERSECT mode, an array of dd items
+     * being hovered over.
+     */
+    onDragOver: function(e, id) { /* override this */ },
+
+    /**
+     * Code that executes immediately before the onDragOut event
+     * @private
+     */
+    b4DragOut: function(e) { },
+
+    /**
+     * Abstract method called when we are no longer hovering over an element
+     *
+     * @param {Event} e
+     * @param {String || YAHOO.util.DragDrop[]} id In POINT mode, the element
+     * id this was hovering over.  In INTERSECT mode, an array of dd items
+     * that the mouse is no longer over.
+     */
+    onDragOut: function(e, id) { /* override this */ },
+
+    /**
+     * Code that executes immediately before the onDragDrop event
+     * @private
+     */
+    b4DragDrop: function(e) { },
+
+    /**
+     * Abstract method called when this item is dropped on another DragDrop
+     * obj
+     *
+     * @param {Event} e
+     * @param {String || YAHOO.util.DragDrop[]} id In POINT mode, the element
+     * id this was dropped on.  In INTERSECT mode, an array of dd items this
+     * was dropped on.
+     */
+    onDragDrop: function(e, id) { /* override this */ },
+
+    /**
+     * Code that executes immediately before the endDrag event
+     * @private
+     */
+    b4EndDrag: function(e) { },
+
+    /**
+     * Fired when we are done dragging the object
+     *
+     * @param {Event} e
+     */
+    endDrag: function(e) { /* override this */ },
+
+    /**
+     * Code executed immediately before the onMouseDown event
+
+     * @param {Event} e
+     * @private
+     */
+    b4MouseDown: function(e) {  },
+
+    /**
+     * Event handler that fires when a drag/drop obj gets a mousedown
+     * @param {Event} e
+     */
+    onMouseDown: function(e) { /* override this */ },
+
+    /**
+     * Event handler that fires when a drag/drop obj gets a mouseup
+     * @param {Event} e
+     */
+    onMouseUp: function(e) { /* override this */ },
+
+    /**
+     * Returns a reference to the linked element
+     *
+     * @return {Object} the html element
+     */
+    getEl: function() {
+        if (!this._domRef) {
+            this._domRef = this.DDM.getElement(this.id);
+        }
+
+        return this._domRef;
+    },
+
+    /**
+     * Returns a reference to the actual element to drag.  By default this is
+     * the same as the html element, but it can be assigned to another
+     * element. An example of this can be found in YAHOO.util.DDProxy
+     *
+     * @return {Object} the html element
+     */
+    getDragEl: function() {
+        return this.DDM.getElement(this.dragElId);
+    },
+
+    /**
+     * Sets up the DragDrop object.  Must be called in the constructor of any
+     * YAHOO.util.DragDrop subclass
+     *
+     * @param id the id of the linked element
+     * @param {String} sGroup the group of related items
+     * element is supposed to be a target only, set to false.
+     */
+    init: function(id, sGroup) {
+        this.initTarget(id, sGroup);
+        YAHOO.util.Event.addListener(id, "mousedown",
+                                          this.handleMouseDown, this, true);
+    },
+
+    /**
+     * Initializes Targeting functionality only... the object does not
+     * get a mousedown handler.
+     *
+     * @param id the id of the linked element
+     * @param {String} sGroup the group of related items
+     * element is supposed to be a target only, set to false.
+     */
+    initTarget: function(id, sGroup) {
+
+        // create a local reference to the drag and drop manager
+        this.DDM = YAHOO.util.DDM;
+
+        // create a logger instance
+        this.logger = new ygLogger("DragDrop");
+
+        // set the default padding
+        this.padding = [0, 0, 0, 0];
+
+        // initialize the groups array
+        this.groups = {};
+
+        // set the id
+        this.id = id;
+
+        // the element is a drag handle by default
+        this.setDragElId(id);
+
+        // by default, clicked anchors will not start drag operations
+        this.invalidHandleTypes = {a : "a"};
+
+        // We don't want to register this as the handle with the manager
+        // so we just set the id rather than calling the setter
+        this.handleElId = id;
+
+        // cache the position of the element if we can
+        if (document && document.body) {
+            this.setInitPosition();
+        }
+
+        // add to an interaction group
+        this.addToGroup((sGroup) ? sGroup : "default");
+
+    },
+
+    /**
+     * Configures the padding for the target zone in px.  Effectively expands
+     * (or reduces) the virtual object size for targeting calculations.
+     * Supports css-style shorthand; if only one parameter is passed, all sides
+     * will have that padding, and if only two are passed, the top and bottom
+     * will have the first param, the left and right the second.
+     * @param {int} iTop    Top pad
+     * @param {int} iRight  Right pad
+     * @param {int} iBot    Bot pad
+     * @param {int} iLeft   Left pad
+     */
+    setPadding: function(iTop, iRight, iBot, iLeft) {
+        // this.padding = [iLeft, iRight, iTop, iBot];
+        if (!iRight && 0 !== iRight) {
+            this.padding = [iTop, iTop, iTop, iTop];
+        } else if (!iBot && 0 !== iBot) {
+            this.padding = [iTop, iRight, iTop, iRight];
+        } else {
+            this.padding = [iTop, iRight, iBot, iLeft];
+        }
+    },
+
+    /**
+     * Stores the initial placement of the dd element
+     */
+    setInitPosition: function(diffX, diffY) {
+        var el = this.getEl();
+
+        if (!this.DDM.verifyEl(el)) {
+            this.logger.debug(this.id + " element is broken");
+            return;
+        }
+
+        var dx = diffX || 0;
+        var dy = diffY || 0;
+
+        var p = YAHOO.util.Dom.getXY( el );
+
+        this.initPageX = p[0] - dx;
+        this.initPageY = p[1] - dy;
+
+        this.lastPageX = p[0];
+        this.lastPageY = p[1];
+
+        this.setStartPosition(p);
+    },
+
+    /**
+     * Sets the start position of the element.  This is set when the obj
+     * is initialized, the reset when a drag is started.
+     * @param pos current position (from previous lookup)
+     * @private
+     */
+    setStartPosition: function(pos) {
+
+        var p = pos || YAHOO.util.Dom.getXY( this.getEl() );
+
+        this.startPageX = p[0];
+        this.startPageY = p[1];
+    },
+
+    /**
+     * Add this instance to a group of related drag/drop objects.  All
+     * instances belong to at least one group, and can belong to as many
+     * groups as needed.
+     *
+     * @param sGroup {string} the name of the group
+     */
+    addToGroup: function(sGroup) {
+        this.groups[sGroup] = true;
+        this.DDM.regDragDrop(this, sGroup);
+    },
+
+    /**
+     * Allows you to specify that an element other than the linked element
+     * will be moved with the cursor during a drag
+     *
+     * @param id the id of the element that will be used to initiate the drag
+     */
+    setDragElId: function(id) {
+        this.dragElId = id;
+    },
+
+    /**
+     * Allows you to specify a child of the linked element that should be
+     * used to initiate the drag operation.  An example of this would be if
+     * you have a content div with text and links.  Clicking anywhere in the
+     * content area would normally start the drag operation.  Use this method
+     * to specify that an element inside of the content div is the element
+     * that starts the drag operation.
+     *
+     * @param id the id of the element that will be used to initiate the drag
+     */
+    setHandleElId: function(id) {
+        this.handleElId = id;
+        this.DDM.regHandle(this.id, id);
+    },
+
+    /**
+     * Allows you to set an element outside of the linked element as a drag
+     * handle
+     */
+    setOuterHandleElId: function(id) {
+        this.logger.debug("Adding outer handle event: " + id);
+        YAHOO.util.Event.addListener(id, "mousedown",
+                this.handleMouseDown, this, true);
+        this.setHandleElId(id);
+    },
+
+    /**
+     * Remove all drag and drop hooks for this element
+     */
+    unreg: function() {
+        this.logger.debug("DragDrop obj cleanup " + this.id);
+        YAHOO.util.Event.removeListener(this.id, "mousedown",
+                this.handleMouseDown);
+        this._domRef = null;
+        this.DDM._remove(this);
+    },
+
+    /**
+     * Returns true if this instance is locked, or the drag drop mgr is locked
+     * (meaning that all drag/drop is disabled on the page.)
+     *
+     * @return {boolean} true if this obj or all drag/drop is locked, else
+     * false
+     */
+    isLocked: function() {
+        return (this.DDM.isLocked() || this.locked);
+    },
+
+    /**
+     * Fired when this object is clicked
+     *
+     * @param {Event} e
+     * @param {YAHOO.util.DragDrop} oDD the clicked dd object (this dd obj)
+     * @private
+     */
+    handleMouseDown: function(e, oDD) {
+
+        this.logger.debug("isLocked: " + this.isLocked());
+
+        var EU = YAHOO.util.Event;
+
+
+        var button = e.which || e.button;
+        this.logger.debug("button: " + button);
+
+        if (this.primaryButtonOnly && button > 1) {
+            this.logger.debug("Mousedown was not produced by the primary button");
+            return;
+        }
+
+        if (this.isLocked()) {
+            this.logger.debug("Drag and drop is disabled, aborting");
+            return;
+        }
+
+        this.logger.debug("mousedown " + this.id);
+
+        this.DDM.refreshCache(this.groups);
+
+        // Only process the event if we really clicked within the linked
+        // element.  The reason we make this check is that in the case that
+        // another element was moved between the clicked element and the
+        // cursor in the time between the mousedown and mouseup events. When
+        // this happens, the element gets the next mousedown event
+        // regardless of where on the screen it happened.
+        var pt = new YAHOO.util.Point(EU.getPageX(e), EU.getPageY(e));
+        if ( this.DDM.isOverTarget(pt, this) )  {
+
+            this.logger.debug("click is legit");
+
+            //  check to see if the handle was clicked
+            var srcEl = EU.getTarget(e);
+
+            if (this.isValidHandleChild(srcEl) &&
+                    (this.id == this.handleElId ||
+                     this.DDM.handleWasClicked(srcEl, this.id)) ) {
+
+                // set the initial element position
+                this.setStartPosition();
+
+                this.logger.debug("firing onMouseDown events");
+
+
+                this.b4MouseDown(e);
+                this.onMouseDown(e);
+                this.DDM.handleMouseDown(e, this);
+
+                this.DDM.stopEvent(e);
+            }
+        }
+    },
+
+    /**
+     * Allows you to specify a tag name that should not start a drag operation
+     * when clicked.  This is designed to facilitate embedding links within a
+     * drag handle that do something other than start the drag.
+     *
+     * @param {string} tagName the type of element to exclude
+     */
+    addInvalidHandleType: function(tagName) {
+        var type = tagName.toUpperCase();
+        this.invalidHandleTypes[type] = type;
+    },
+
+    /**
+     * Unsets an excluded tag name set by addInvalidHandleType
+     *
+     * @param {string} tagName the type of element to unexclude
+     */
+    removeInvalidHandleType: function(tagName) {
+        var type = tagName.toUpperCase();
+        this.invalidHandleTypes[type] = null;
+    },
+
+    /**
+     * Checks the tag exclusion list to see if this click should be ignored
+     *
+     * @param {ygNode} node
+     * @return {boolean} true if this is a valid tag type, false if not
+     */
+    isValidHandleChild: function(node) {
+        var type = node.nodeName;
+
+        if (type == "#text") {
+            // this.logger.debug("text node, getting parent node type");
+            type = node.parentNode.nodeName;
+        }
+
+        return (!this.invalidHandleTypes[type]);
+    },
+
+    /**
+     * Create the array of horizontal tick marks if an interval was specified
+     * in setXConstraint().
+     *
+     * @private
+     */
+    setXTicks: function(iStartX, iTickSize) {
+        this.xTicks = [];
+        this.xTickSize = iTickSize;
+
+        var tickMap = {};
+
+        for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
+            if (!tickMap[i]) {
+                this.xTicks[this.xTicks.length] = i;
+                tickMap[i] = true;
+            }
+        }
+
+        for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
+            if (!tickMap[i]) {
+                this.xTicks[this.xTicks.length] = i;
+                tickMap[i] = true;
+            }
+        }
+
+        this.xTicks.sort(this.DDM.numericSort) ;
+        this.logger.debug("xTicks: " + this.xTicks.join());
+    },
+
+    /**
+     * Create the array of vertical tick marks if an interval was specified in
+     * setYConstraint().
+     *
+     * @private
+     */
+    setYTicks: function(iStartY, iTickSize) {
+        this.yTicks = [];
+        this.yTickSize = iTickSize;
+
+        var tickMap = {};
+
+        for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
+            if (!tickMap[i]) {
+                this.yTicks[this.yTicks.length] = i;
+                tickMap[i] = true;
+            }
+        }
+
+        for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
+            if (!tickMap[i]) {
+                this.yTicks[this.yTicks.length] = i;
+                tickMap[i] = true;
+            }
+        }
+
+        this.yTicks.sort(this.DDM.numericSort) ;
+        this.logger.debug("yTicks: " + this.yTicks.join());
+    },
+
+    /**
+     * By default, the element can be dragged any place on the screen.  Use
+     * this method to limit the horizontal travel of the element.  Pass in
+     * 0,0 for the parameters if you want to lock the drag to the y axis.
+     *
+     * @param {int} iLeft the number of pixels the element can move to the left
+     * @param {int} iRight the number of pixels the element can move to the
+     * right
+     * @param {int} iTickSize optional parameter for specifying that the
+     * element
+     * should move iTickSize pixels at a time.
+     */
+    setXConstraint: function(iLeft, iRight, iTickSize) {
+        this.leftConstraint = iLeft;
+        this.rightConstraint = iRight;
+
+        this.minX = this.initPageX - iLeft;
+        this.maxX = this.initPageX + iRight;
+        if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
+
+        this.constrainX = true;
+        this.logger.debug("initPageX:" + this.initPageX + " minX:" + this.minX +
+                " maxX:" + this.maxX);
+    },
+
+    /**
+     * By default, the element can be dragged any place on the screen.  Set
+     * this to limit the vertical travel of the element.  Pass in 0,0 for the
+     * parameters if you want to lock the drag to the x axis.
+     *
+     * @param {int} iUp the number of pixels the element can move up
+     * @param {int} iDown the number of pixels the element can move down
+     * @param {int} iTickSize optional parameter for specifying that the
+     * element should move iTickSize pixels at a time.
+     */
+    setYConstraint: function(iUp, iDown, iTickSize) {
+        this.topConstraint = iUp;
+        this.bottomConstraint = iDown;
+
+        this.minY = this.initPageY - iUp;
+        this.maxY = this.initPageY + iDown;
+        if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
+
+        this.constrainY = true;
+
+        this.logger.debug("initPageY:" + this.initPageY + " minY:" + this.minY +
+                " maxY:" + this.maxY);
+    },
+
+    /**
+     * resetConstraints must be called if you manually reposition a dd element.
+     * @param {boolean} maintainOffset
+     */
+    resetConstraints: function() {
+
+        // this.logger.debug("init pagexy: " + this.initPageX + ", " +
+        //      this.initPageY);
+        // this.logger.debug("last pagexy: " + this.lastPageX + ", " +
+        //      this.lastPageY);
+
+        // figure out how much this thing has moved
+        var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
+        var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
+
+        // this.logger.debug("diff: " + dx + ", " + dy);
+
+        // reset the initial location
+        this.setInitPosition(dx, dy);
+
+        if (this.constrainX) {
+            this.setXConstraint( this.leftConstraint,
+                                 this.rightConstraint,
+                                 this.xTickSize        );
+        }
+
+        if (this.constrainY) {
+            this.setYConstraint( this.topConstraint,
+                                 this.bottomConstraint,
+                                 this.yTickSize         );
+        }
+    },
+
+    /**
+     * Normally the drag element is moved pixel by pixel, but we can specify
+     * that it move a number of pixels at a time.  This method resolves the
+     * location when we have it set up like this.
+     *
+     * @param {int} val where we want to place the object
+     * @param {int[]} tickArray sorted array of valid points
+     * @return {int} the closest tick
+     * @private
+     */
+    getTick: function(val, tickArray) {
+
+        if (!tickArray) {
+            // If tick interval is not defined, it is effectively 1 pixel,
+            // so we return the value passed to us.
+            return val;
+        } else if (tickArray[0] >= val) {
+            // The value is lower than the first tick, so we return the first
+            // tick.
+            return tickArray[0];
+        } else {
+            for (var i = 0; i < tickArray.length; ++i) {
+                var next = i + 1;
+                if (tickArray[next] && tickArray[next] >= val) {
+                    var diff1 = val - tickArray[i];
+                    var diff2 = tickArray[next] - val;
+                    return (diff2 > diff1) ? tickArray[i] : tickArray[next];
+                }
+            }
+
+            // The value is larger than the last tick, so we return the last
+            // tick.
+            return tickArray[tickArray.length - 1];
+        }
+    },
+
+    /**
+     * toString method
+     * @return {string} string representation of the dd obj
+     */
+    toString: function(val, tickArray) {
+        return ("YAHOO.util.DragDrop {" + this.id + "}");
+    }
+
+};
+
+/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
+
+// Only load the library once.  Rewriting the manager class would orphan
+// existing drag and drop instances.
+if (!YAHOO.util.DragDropMgr) {
+
+    /**
+     * @class Handles the element interaction for all DragDrop items in the
+     * window.  Generally, you will not call this class directly, but it does
+     * have helper methods that could be useful in your DragDrop
+     * implementations.  This class should not be instantiated; all methods
+     * are are static.
+     *
+     * @constructor
+     */
+    YAHOO.util.DragDropMgr = new function() {
+
+        /**
+         * utility package shorthand
+         * @private
+         */
+        var UTIL = YAHOO.util;
+
+        /**
+         * Two dimensional Array of registered DragDrop objects.  The first
+         * dimension is the DragDrop item group, the second the DragDrop
+         * object.
+         *
+         * @private
+         */
+        this.ids = {};
+
+        /**
+         * Array of element ids defined as drag handles.  Used to determine
+         * if the element that generated the mousedown event is actually the
+         * handle and not the html element itself.
+         *
+         * @private
+         */
+        this.handleIds = {};
+
+        /**
+         * the DragDrop object that is currently being dragged
+         *
+         * @type DragDrop
+         * @private
+         **/
+        this.dragCurrent = null;
+
+        /**
+         * the DragDrop object(s) that are being hovered over
+         *
+         * @type Array
+         * @private
+         */
+        this.dragOvers = {};
+
+        /**
+         * @private
+         */
+        this.logger = null;
+
+        /**
+         * the X distance between the cursor and the object being dragged
+         *
+         * @type int
+         * @private
+         */
+        this.deltaX = 0;
+
+        /**
+         * the Y distance between the cursor and the object being dragged
+         *
+         * @type int
+         * @private
+         */
+        this.deltaY = 0;
+
+        /**
+         * Flag to determine if we should prevent the default behavior of the
+         * events we define. By default this is true, but this can be set to
+         * false if you need the default behavior (not recommended)
+         *
+         * @type boolean
+         */
+        this.preventDefault = true;
+
+        /**
+         * Flag to determine if we should stop the propagation of the events
+         * we generate. This is true by default but you may want to set it to
+         * false if the html element contains other features that require the
+         * mouse click.
+         *
+         * @type boolean
+         */
+        this.stopPropagation = true;
+
+        /**
+         * @private
+         */
+        this.initalized = false;
+
+        /**
+         * All drag and drop can be disabled.
+         *
+         * @private
+         */
+        this.locked = false;
+
+        /**
+         * Called the first time an element is registered.
+         *
+         * @private
+         */
+        this.init = function() {
+            this.logger = new ygLogger("DragDropMgr");
+        };
+
+        /**
+         * In point mode, drag and drop interaction is defined by the
+         * location of the cursor during the drag/drop
+         * @type int
+         */
+        this.POINT     = 0;
+
+        /**
+         * In intersect mode, drag and drop interactio nis defined by the
+         * overlap of two or more drag and drop objects.
+         * @type int
+         */
+        this.INTERSECT = 1;
+
+        /**
+         * The current drag and drop mode.  Default it point mode
+         * @type int
+         */
+        this.mode = this.POINT;
+
+        /**
+         * Runs method on all drag and drop objects
+         * @private
+         */
+        this._execOnAll = function(sMethod, args) {
+            for (var i in this.ids) {
+                for (var j in this.ids[i]) {
+                    var oDD = this.ids[i][j];
+                    if (! this.isTypeOfDD(oDD)) {
+                        continue;
+                    }
+                    oDD[sMethod].apply(oDD, args);
+                }
+            }
+        };
+
+        /**
+         * Drag and drop initialization.  Sets up the global event handlers
+         * @private
+         */
+        this._onLoad = function() {
+
+            this._execOnAll("setInitPosition", []);
+
+            this.logger = new ygLogger("DragDropMgr");
+            this.logger.debug("DDM onload");
+
+            var EU = UTIL.Event;
+
+            EU.addListener(document, "mouseup",   this.handleMouseUp, this, true);
+            EU.addListener(document, "mousemove", this.handleMouseMove, this, true);
+            EU.addListener(window,   "unload",    this._onUnload, this, true);
+            EU.addListener(window,   "resize",    this._onResize, this, true);
+            // EU.addListener(window,   "mouseout",    this._test);
+
+            this.initalized = true;
+
+        };
+
+        /**
+         * Reset constraints on all drag and drop objs
+         * @private
+         */
+        this._onResize = function(e) {
+            this.logger.debug("window resize");
+            this._execOnAll("resetConstraints", []);
+        };
+
+        /**
+         * Lock all drag and drop functionality
+         */
+        this.lock = function() { this.locked = true; };
+
+        /**
+         * Unlock all drag and drop functionality
+         */
+        this.unlock = function() { this.locked = false; };
+
+        /**
+         * Is drag and drop locked?
+         *
+         * @return {boolean} True if drag and drop is locked, false otherwise.
+         */
+        this.isLocked = function() { return this.locked; };
+
+        /**
+         * Location cache that is set for all drag drop objects when a drag is
+         * initiated, cleared when the drag is finished.
+         *
+         * @private
+         */
+        this.locationCache = {};
+
+        /**
+         * Set useCache to false if you want to force object the lookup of each
+         * drag and drop linked element constantly during a drag.
+         * @type boolean
+         */
+        this.useCache = true;
+
+        /**
+         * The number of pixels that the mouse needs to move after the
+         * mousedown before the drag is initiated.  Default=3;
+         * @type int
+         */
+        this.clickPixelThresh = 3;
+
+        /**
+         * The number of milliseconds after the mousedown event to initiate the
+         * drag if we don't get a mouseup event. Default=1000
+         * @type int
+         */
+        this.clickTimeThresh = 1000;
+
+        /**
+         * Flag that indicates that either the drag pixel threshold or the
+         * mousdown time threshold has been met
+         * @type boolean
+         * @private
+         */
+        this.dragThreshMet = false;
+
+        /**
+         * Timeout used for the click time threshold
+         * @type Object
+         * @private
+         */
+        this.clickTimeout = null;
+
+        /**
+         * The X position of the mousedown event stored for later use when a
+         * drag threshold is met.
+         * @type int
+         * @private
+         */
+        this.startX = 0;
+
+        /**
+         * The Y position of the mousedown event stored for later use when a
+         * drag threshold is met.
+         * @type int
+         * @private
+         */
+        this.startY = 0;
+
+        /**
+         * Each DragDrop instance must be registered with the DragDropMgr.
+         * This is executed in ygDragDrop.init()
+         *
+         * @param {DragDrop} oDD the DragDrop object to register
+         * @param {String} sGroup the name of the group this element belongs to
+         */
+        this.regDragDrop = function(oDD, sGroup) {
+            if (!this.initialized) { this.init(); }
+
+            if (!this.ids[sGroup]) {
+                this.ids[sGroup] = {};
+            }
+            this.ids[sGroup][oDD.id] = oDD;
+        };
+
+        /**
+         * Unregisters a drag and drop item.  This is executed in
+         * ygDragDrop.unreg, use that method instead of calling this directly.
+         * @private
+         */
+        this._remove = function(oDD) {
+            for (var g in oDD.groups) {
+                if (g && this.ids[g][oDD.id]) {
+                    delete this.ids[g][oDD.id];
+                }
+            }
+            delete this.handleIds[oDD.id];
+        };
+
+        /**
+         * Each DragDrop handle element must be registered.  This is done
+         * automatically when executing ygDragDrop.setHandleElId()
+         *
+         * @param {String} sDDId the DragDrop id this element is a handle for
+         * @param {String} sHandleId the id of the element that is the drag
+         * handle
+         */
+        this.regHandle = function(sDDId, sHandleId) {
+            if (!this.handleIds[sDDId]) {
+                this.handleIds[sDDId] = {};
+            }
+            this.handleIds[sDDId][sHandleId] = sHandleId;
+        };
+
+        /**
+         * Utility function to determine if a given element has been
+         * registered as a drag drop item.
+         *
+         * @param {String} id the element id to check
+         * @return {boolean} true if this element is a DragDrop item,
+         * false otherwise
+         */
+        this.isDragDrop = function(id) {
+            return ( this.getDDById(id) ) ? true : false;
+        };
+
+        /**
+         * Returns the drag and drop instances that are in all groups the
+         * passed in instance belongs to.
+         *
+         * @param {ygDragDrop} p_oDD the obj to get related data for
+         * @param {boolean} bTargetsOnly if true, only return targetable objs
+         * @return {ygDragDrop[]} the related instances
+         */
+        this.getRelated = function(p_oDD, bTargetsOnly) {
+            var oDDs = [];
+            for (var i in p_oDD.groups) {
+                for (j in this.ids[i]) {
+                    var dd = this.ids[i][j];
+                    if (! this.isTypeOfDD(dd)) {
+                        continue;
+                    }
+                    if (!bTargetsOnly || dd.isTarget) {
+                        oDDs[oDDs.length] = dd;
+                    }
+                }
+            }
+
+            return oDDs;
+        };
+
+        /**
+         * Returns true if the specified dd target is a legal target for
+         * the specifice drag obj
+         *
+         * @param {ygDragDrop} the drag obj
+         * @param {ygDragDrop) the target
+         * @return {boolean} true if the target is a legal target for the
+         * dd obj
+         */
+        this.isLegalTarget = function (oDD, oTargetDD) {
+            var targets = this.getRelated(oDD);
+            for (var i =0;i<targets.length;++i) {
+                if (targets[i].id == oTargetDD.id) {
+                    return true;
+                }
+            }
+
+            return false;
+        };
+
+        /**
+         * My goal is to be able to transparently determine if an object is
+         * typeof ygDragDrop, and the exact subclass of ygDragDrop.  typeof
+         * returns "object", oDD.constructor.toString() always returns
+         * "ygDragDrop" and not the name of the subclass.  So for now it just
+         * evaluates a well-known variable in ygDragDrop.
+         *
+         * @param {Object} the object to evaluate
+         * @return {boolean} true if typeof oDD = ygDragDrop
+         */
+        this.isTypeOfDD = function (oDD) {
+            return (oDD && oDD.__ygDragDrop);
+        };
+
+        /**
+         * Utility function to determine if a given element has been
+         * registered as a drag drop handle for the given Drag Drop object.
+         *
+         * @param {String} id the element id to check
+         * @return {boolean} true if this element is a DragDrop handle, false
+         * otherwise
+         */
+        this.isHandle = function(sDDId, sHandleId) {
+            return ( this.handleIds[sDDId] &&
+                            this.handleIds[sDDId][sHandleId] );
+        };
+
+        /**
+         * Returns the DragDrop instance for a given id
+         *
+         * @param {String} id the id of the DragDrop object
+         * @return {DragDrop} the drag drop object, null if it is not found
+         */
+        this.getDDById = function(id) {
+            for (var i in this.ids) {
+                if (this.ids[i][id]) {
+                    return this.ids[i][id];
+                }
+            }
+            return null;
+        };
+
+        /**
+         * Fired after a registered DragDrop object gets the mousedown event.
+         * Sets up the events required to track the object being dragged
+         *
+         * @param {Event} e the event
+         * @param oDD the DragDrop object being dragged
+         * @private
+         */
+        this.handleMouseDown = function(e, oDD) {
+            this.logger.debug("mousedown - adding event handlers");
+            this.dragCurrent = oDD;
+
+            var el = oDD.getEl();
+
+            // track start position
+            this.startX = UTIL.Event.getPageX(e);
+            this.startY = UTIL.Event.getPageY(e);
+
+            this.deltaX = this.startX - el.offsetLeft;
+            this.deltaY = this.startY - el.offsetTop;
+
+            this.dragThreshMet = false;
+
+            this.clickTimeout = setTimeout(
+               "var DDM=YAHOO.util.DDM;DDM.startDrag(DDM.startX, DDM.startY)",
+               this.clickTimeThresh );
+        };
+
+        /**
+         * Fired when either the drag pixel threshol or the mousedown hold
+         * time threshold has been met.
+         *
+         * @param x {int} the X position of the original mousedown
+         * @param y {int} the Y position of the original mousedown
+         */
+        this.startDrag = function(x, y) {
+            this.logger.debug("firing drag start events");
+            clearTimeout(this.clickTimeout);
+            if (this.dragCurrent) {
+                this.dragCurrent.b4StartDrag(x, y);
+                this.dragCurrent.startDrag(x, y);
+            }
+            this.dragThreshMet = true;
+        };
+
+        /**
+         * Internal function to handle the mouseup event.  Will be invoked
+         * from the context of the document.
+         *
+         * @param {Event} e the event
+         * @private
+         */
+        this.handleMouseUp = function(e) {
+
+            if (! this.dragCurrent) {
+                return;
+            }
+
+            clearTimeout(this.clickTimeout);
+
+            if (this.dragThreshMet) {
+                this.logger.debug("mouseup detected - completing drag");
+                this.fireEvents(e, true);
+            } else {
+                this.logger.debug("drag threshold not met");
+            }
+
+            this.stopDrag(e);
+
+            this.stopEvent(e);
+        };
+
+        /**
+         * Utility to stop event propagation and event default, if these
+         * features are turned on.
+         *
+         * @param {Event} e the event as returned by this.getEvent()
+         */
+        this.stopEvent = function(e) {
+            if (this.stopPropagation) {
+                UTIL.Event.stopPropagation(e);
+            }
+
+            if (this.preventDefault) {
+                UTIL.Event.preventDefault(e);
+            }
+        };
+
+        /**
+         * Internal function to clean up event handlers after the drag
+         * operation is complete
+         *
+         * @param {Event} e the event
+         * @private
+         */
+        this.stopDrag = function(e) {
+            // this.logger.debug("mouseup - removing event handlers");
+
+            // Fire the drag end event for the item that was dragged
+            if (this.dragCurrent) {
+                if (this.dragThreshMet) {
+                    this.logger.debug("firing endDrag events");
+                    this.dragCurrent.b4EndDrag(e);
+                    this.dragCurrent.endDrag(e);
+                }
+
+                this.logger.debug("firing onMouseUp event");
+                this.dragCurrent.onMouseUp(e);
+            }
+
+            this.dragCurrent = null;
+            this.dragOvers = {};
+        };
+
+
+        /**
+         * Internal function to handle the mousemove event.  Will be invoked
+         * from the context of the html element.
+         *
+         * @TODO figure out what we can do about mouse events lost when the
+         * user drags objects beyond the window boundary.  Currently we can
+         * detect this in internet explorer by verifying that the mouse is
+         * down during the mousemove event.  Firefox doesn't give us the
+         * button state on the mousemove event.
+         *
+         * @param {Event} e the event
+         * @private
+         */
+        this.handleMouseMove = function(e) {
+            if (! this.dragCurrent) {
+                // this.logger.debug("no current drag obj");
+                return;
+            }
+
+            // var button = e.which || e.button;
+
+            this.logger.debug("which: " + e.which + ", button: "+ e.button);
+
+
+            // check for IE mouseup outside of page boundary
+            if (UTIL.Event.isIE && !e.button) {
+                this.stopEvent(e);
+                return this.handleMouseUp(e);
+                // this.logger.debug("button failure");
+            }
+
+            if (!this.dragThreshMet) {
+                var diffX = Math.abs(this.startX - UTIL.Event.getPageX(e));
+                var diffY = Math.abs(this.startY - UTIL.Event.getPageY(e));
+                // this.logger.debug("diffX: " + diffX + "diffY: " + diffY);
+                if (diffX > this.clickPixelThresh ||
+                            diffY > this.clickPixelThresh) {
+                    this.logger.debug("pixel threshold met");
+                    this.startDrag(this.startX, this.startY);
+                }
+            }
+
+            if (this.dragThreshMet) {
+                this.dragCurrent.b4Drag(e);
+                this.dragCurrent.onDrag(e);
+                this.fireEvents(e, false);
+            }
+
+            this.stopEvent(e);
+        };
+
+        /**
+         * Iterates over all of the DragDrop elements to find ones we are
+         * hovering over or dropping on
+         *
+         * @param {Event} e the event
+         * @param {boolean} isDrop is this a drop op or a mouseover op?
+         * @private
+         */
+        this.fireEvents = function(e, isDrop) {
+            var dc = this.dragCurrent;
+
+            // If the user did the mouse up outside of the window, we could
+            // get here even though we have ended the drag.
+            if (!dc || dc.isLocked()) {
+                return;
+            }
+
+            var x = UTIL.Event.getPageX(e);
+            var y = UTIL.Event.getPageY(e);
+            var pt = new YAHOO.util.Point(x,y);
+
+            // cache the previous dragOver array
+            var oldOvers = [];
+
+            var outEvts   = [];
+            var overEvts  = [];
+            var dropEvts  = [];
+            var enterEvts = [];
+
+            // Check to see if the object we were hovering over is no longer
+            // being hovered over so we can fire the onDragOut event
+            for (var i in this.dragOvers) {
+
+                var ddo = this.dragOvers[i];
+
+                if (! this.isTypeOfDD(ddo)) {
+                    continue;
+                }
+
+                if (! this.isOverTarget(pt, ddo, this.mode)) {
+                    outEvts.push( ddo );
+                }
+
+                oldOvers[i] = true;
+                delete this.dragOvers[i];
+            }
+
+            for (var sGroup in dc.groups) {
+                // this.logger.debug("Processing group " + sGroup);
+
+                if ("string" != typeof sGroup) {
+                    continue;
+                }
+
+                for (i in this.ids[sGroup]) {
+                    var oDD = this.ids[sGroup][i];
+                    if (! this.isTypeOfDD(oDD)) {
+                        continue;
+                    }
+
+                    if (oDD.isTarget && !oDD.isLocked() && oDD != dc) {
+                        if (this.isOverTarget(pt, oDD, this.mode)) {
+                            // look for drop interactions
+                            if (isDrop) {
+                                dropEvts.push( oDD );
+                            // look for drag enter and drag over interactions
+                            } else {
+
+                                // initial drag over: dragEnter fires
+                                if (!oldOvers[oDD.id]) {
+                                    enterEvts.push( oDD );
+                                // subsequent drag overs: dragOver fires
+                                } else {
+                                    overEvts.push( oDD );
+                                }
+
+                                this.dragOvers[oDD.id] = oDD;
+                            }
+                        }
+                    }
+                }
+            }
+
+            if (this.mode) {
+                if (outEvts.length > 0) {
+                    dc.b4DragOut(e, outEvts);
+                    dc.onDragOut(e, outEvts);
+                }
+
+                if (enterEvts.length > 0) {
+                    dc.onDragEnter(e, enterEvts);
+                }
+
+                if (overEvts.length > 0) {
+                    dc.b4DragOver(e, overEvts);
+                    dc.onDragOver(e, overEvts);
+                }
+
+                if (dropEvts.length > 0) {
+                    dc.b4DragDrop(e, dropEvts);
+                    dc.onDragDrop(e, dropEvts);
+                }
+
+            } else {
+                // fire dragout events
+                for (i=0; i < outEvts.length; ++i) {
+                    this.logger.debug(dc.id+" onDragOut: " + outEvts[i].id);
+                    dc.b4DragOut(e, outEvts[i].id);
+                    dc.onDragOut(e, outEvts[i].id);
+                }
+
+                // fire enter events
+                for (i=0; i < enterEvts.length; ++i) {
+                    this.logger.debug(dc.id + " dragEnter " + enterEvts[i].id);
+                    // dc.b4DragEnter(e, oDD.id);
+                    dc.onDragEnter(e, enterEvts[i].id);
+                }
+
+                // fire over events
+                for (i=0; i < overEvts.length; ++i) {
+                    this.logger.debug(dc.id + " dragOver " + overEvts[i].id);
+                    dc.b4DragOver(e, overEvts[i].id);
+                    dc.onDragOver(e, overEvts[i].id);
+                }
+
+                // fire drop events
+                for (i=0; i < dropEvts.length; ++i) {
+                    this.logger.debug(dc.id + " dragDrop " + dropEvts[i].id);
+                    dc.b4DragDrop(e, dropEvts[i].id);
+                    dc.onDragDrop(e, dropEvts[i].id);
+                }
+
+            }
+
+        };
+
+        /**
+         * Helper function for getting the best match from the list of drag
+         * and drop objects returned by the drag and drop events when we are
+         * in INTERSECT mode.  It returns either the first object that the
+         * cursor is over, or the object that has the greatest overlap with
+         * the dragged element.
+         *
+         * @param  {ygDragDrop[]} dds The array of drag and drop objects
+         * targeted
+         * @return {ygDragDrop}       The best single match
+         */
+        this.getBestMatch = function(dds) {
+            var winner = null;
+            // Return null if the input is not what we expect
+            //if (!dds || !dds.length || dds.length == 0) {
+               // winner = null;
+            // If there is only one item, it wins
+            //} else if (dds.length == 1) {
+
+            if (dds.length == 1) {
+                winner = dds[0];
+            } else {
+                // Loop through the targeted items
+                for (var i=0; i<dds.length; ++i) {
+                    var dd = dds[i];
+                    // If the cursor is over the object, it wins.  If the
+                    // cursor is over multiple matches, the first one we come
+                    // to wins.
+                    if (dd.cursorIsOver) {
+                        winner = dd;
+                        break;
+                    // Otherwise the object with the most overlap wins
+                    } else {
+                        if (!winner ||
+                            winner.overlap.getArea() < dd.overlap.getArea()) {
+                            winner = dd;
+                        }
+                    }
+                }
+            }
+
+            return winner;
+        };
+
+        /**
+         * Refreshes the cache of the top-left and bottom-right points of the
+         * drag and drop objects in the specified groups
+         *
+         * @param {Array} aGroups an associative array of groups to refresh
+         */
+        this.refreshCache = function(aGroups) {
+            this.logger.debug("refreshing element location cache");
+            for (sGroup in aGroups) {
+                if ("string" != typeof sGroup) {
+                    continue;
+                }
+                for (i in this.ids[sGroup]) {
+                    var oDD = this.ids[sGroup][i];
+
+                    if (this.isTypeOfDD(oDD)) {
+                        var loc = this.getLocation(oDD);
+                        if (loc) {
+                            this.locationCache[oDD.id] = loc;
+                        } else {
+                            delete this.locationCache[oDD.id];
+                            this.logger.debug("something is wrong with the element");
+                            // this will unregister the drag and drop object if
+                            // the element is not in a usable state
+                            oDD.unreg();
+                        }
+                    }
+                }
+            }
+        };
+
+        /**
+         * This checks to make sure an element exists and is in the DOM.  The
+         * main purpose is to handle cases where innerHTML is used to remove
+         * drag and drop objects from the DOM.  IE provides an 'unspecified
+         * error' when trying to access the offsetParent of such an element
+         * @param {HTMLElement} el the element to check
+         * @return {boolean} true if the element looks usable
+         */
+        this.verifyEl = function(el) {
+            try {
+                if (el) {
+                    var parent = el.offsetParent;
+                    if (parent) {
+                        return true;
+                    }
+                }
+            } catch(e) {
+                this.logger.debug("detected problem with an element");
+            }
+
+            return false;
+        };
+
+        /**
+         * Returns the an array containing the drag and drop element's position
+         * and size, including the ygDragDrop.padding configured for it
+         *
+         * @param {ygDragDrop} oDD the drag and drop object to get the
+         * location for
+         * @return array containing the top left and bottom right points of the
+         * element
+         */
+        this.getLocation = function(oDD) {
+            if (! this.isTypeOfDD(oDD)) {
+                this.logger.debug(oDD + " is not a DD obj");
+                return null;
+            }
+
+            var el = oDD.getEl();
+
+            if (!this.verifyEl(el)) {
+                this.logger.debug(oDD + " element is not usable");
+                return null;
+            }
+
+            // this.logger.debug(oDD.id + " padding: " + oDD.padding);
+
+            // var aPos = ygPos.getPos(el);
+            var aPos = YAHOO.util.Dom.getXY(el);
+
+            x1 = aPos[0];
+            x2 = x1 + el.offsetWidth;
+
+            y1 = aPos[1];
+            y2 = y1 + el.offsetHeight;
+
+            var t = y1 - oDD.padding[0];
+            var r = x2 + oDD.padding[1];
+            var b = y2 + oDD.padding[2];
+            var l = x1 - oDD.padding[3];
+
+            return new YAHOO.util.Region( t, r, b, l );
+
+        };
+
+        /**
+         * Checks the cursor location to see if it over the target
+         *
+         * @param {YAHOO.util.Point} pt The point to evaluate
+         * @param {ygDragDrop} oDDTarget the DragDrop object we are inspecting
+         * @return {boolean} true if the mouse is over the target
+         * @private
+         */
+        this.isOverTarget = function(pt, oDDTarget, intersect) {
+            // use cache if available
+            var loc = this.locationCache[oDDTarget.id];
+            if (!loc || !this.useCache) {
+                this.logger.debug("cache not populated");
+                loc = this.getLocation(oDDTarget);
+                this.locationCache[oDDTarget.id] = loc;
+
+                this.logger.debug("cache: " + loc);
+            }
+
+            // this.logger.debug("isOverTarget: " + x + "," + y + ", " + loc);
+
+            // var cursorIsOver =  (x >= loc[3] && x <= loc[1] && y >= loc[0] && y <= loc[2]);
+            //oDDTarget.cursorIsOver = loc.contains( new YAHOO.util.Point(x, y) );
+            oDDTarget.cursorIsOver = loc.contains( pt );
+            oDDTarget.overlap = null;
+
+            // if (this.INTERSECT == this.mode) {
+            if (intersect) {
+
+                var curRegion =
+                    YAHOO.util.Region.getRegion(this.dragCurrent.getDragEl());
+                var overlap = curRegion.intersect(loc);
+
+                if (overlap) {
+                    oDDTarget.overlap = overlap;
+                    return true;
+                } else {
+                    return false;
+                }
+
+            } else {
+                return oDDTarget.cursorIsOver;
+            }
+        };
+
+        /**
+         * @private
+         */
+        this._onUnload = function(e, me) {
+            this.unregAll();
+        };
+
+        /**
+         * Cleans up the drag and drop events and objects.
+         *
+         * @private
+         */
+        this.unregAll = function() {
+            this.logger.debug("unregister all");
+
+            if (this.dragCurrent) {
+                this.stopDrag();
+                this.dragCurrent = null;
+            }
+
+            this._execOnAll("unreg", []);
+
+            for (i in this.elementCache) {
+                delete this.elementCache[i];
+            }
+
+            this.elementCache = {};
+            this.ids = {};
+        };
+
+        /**
+         * A cache of DOM elements
+         *
+         * @private
+         */
+        this.elementCache = {};
+
+        /**
+         * Get the wrapper for the DOM element specified
+         *
+         * @param {String} id the id of the elment to get
+         * @return {YAHOO.util.DDM.ElementWrapper} the wrapped element
+         * @private
+         */
+        this.getElWrapper = function(id) {
+            var oWrapper = this.elementCache[id];
+            if (!oWrapper || !oWrapper.el) {
+                // this.logger.debug("adding element cache: " + id);
+                oWrapper = this.elementCache[id] =
+                    new this.ElementWrapper(document.getElementById(id));
+            }
+            return oWrapper;
+        };
+
+        /**
+         * Returns the actual DOM element
+         *
+         * @param {String} id the id of the elment to get
+         * @return {Object} The element
+         */
+        this.getElement = function(id) {
+            // return this.getElWrapper(id).el;
+            return document.getElementById(id);
+        };
+
+        /**
+         * Returns the style property for the DOM element (i.e.,
+         * document.getElById(id).style)
+         *
+         * @param {String} id the id of the elment to get
+         * @return {Object} The style property of the element
+         */
+        this.getCss = function(id) {
+            // return this.getElWrapper(id).css;
+            var css = null;
+            var el = document.getElementById(id);
+            if (el) {
+                css = el.style;
+            }
+
+            return css;
+        };
+
+        /**
+         * Inner class for cached elements
+         */
+        this.ElementWrapper = function(el) {
+                /**
+                 * @private
+                 */
+                this.el = el || null;
+                /**
+                 * @private
+                 */
+                this.id = this.el && el.id;
+                /**
+                 * @private
+                 */
+                this.css = this.el && el.style;
+            };
+
+        /**
+         * Returns the X position of an html element
+         * @param el the element for which to get the position
+         * @return {int} the X coordinate
+         */
+        this.getPosX = function(el) {
+            return YAHOO.util.Dom.getX(el);
+        };
+
+        /**
+         * Returns the Y position of an html element
+         * @param el the element for which to get the position
+         * @return {int} the Y coordinate
+         */
+        this.getPosY = function(el) {
+            return YAHOO.util.Dom.getY(el);
+        };
+
+        /**
+         * Swap two nodes.  In IE, we use the native method, for others we
+         * emulate the IE behavior
+         *
+         * @param n1 the first node to swap
+         * @param n2 the other node to swap
+         */
+        this.swapNode = function(n1, n2) {
+            if (n1.swapNode) {
+                n1.swapNode(n2);
+            } else {
+                // the node reference order for the swap is a little tricky.
+                var p = n2.parentNode;
+                var s = n2.nextSibling;
+                n1.parentNode.replaceChild(n2,n1);
+                p.insertBefore(n1,s);
+            }
+        };
+
+        /**
+         * @private
+         */
+        this.getScroll = function () {
+            var t, l;
+            if (document.documentElement && document.documentElement.scrollTop) {
+                t = document.documentElement.scrollTop;
+                l = document.documentElement.scrollLeft;
+            } else if (document.body) {
+                t = document.body.scrollTop;
+                l = document.body.scrollLeft;
+            }
+            return { top: t, left: l };
+        };
+
+        /**
+         * Returns the specified element style property
+         * @param {HTMLElement} el          the element
+         * @param {string}      styleProp   the style property
+         * @return {string}     The value of the style property
+         */
+        this.getStyle = function(el, styleProp) {
+            if (el.style.styleProp) {
+                return el.style.styleProp;
+            } else if (el.currentStyle) {
+                return el.currentStyle[styleProp];
+            } else if (document.defaultView) {
+                return document.defaultView.getComputedStyle(el, null).
+                    getPropertyValue(styleProp);
+            }
+        };
+
+        /**
+         * Gets the scrollTop
+         *
+         * @return {int} the document's scrollTop
+         */
+        this.getScrollTop = function () { return this.getScroll().top; };
+
+        /**
+         * Gets the scrollLeft
+         *
+         * @return {int} the document's scrollTop
+         */
+        this.getScrollLeft = function () { return this.getScroll().left; };
+
+        this.moveToEl = function (moveEl, targetEl) {
+            var aCoord = YAHOO.util.Dom.getXY(targetEl);
+            this.logger.debug("moveToEl: " + aCoord);
+            YAHOO.util.Dom.setXY(moveEl, aCoord);
+        };
+
+        /**
+         * Gets the client height
+         *
+         * @return {int} client height in px
+         */
+        this.getClientHeight = function() {
+            return (window.innerHeight) ? window.innerHeight :
+                (document.documentElement && document.documentElement.clientHeight) ?
+                document.documentElement.clientHeight : document.body.offsetHeight;
+        };
+
+        /**
+         * Gets the client width
+         *
+         * @return {int} client width in px
+         */
+        this.getClientWidth = function() {
+            return (window.innerWidth) ? window.innerWidth :
+                (document.documentElement && document.documentElement.clientWidth) ?
+                document.documentElement.clientWidth : document.body.offsetWidth;
+        };
+
+        /**
+         * numeric array sort function
+         */
+        this.numericSort = function(a, b) { return (a - b); };
+
+        /**
+         * @private
+         */
+        this._timeoutCount = 0;
+
+        /**
+         * @private
+         * Trying to make the load order less important.  Without this we get
+         * an error if this file is loaded before the Event Utility.
+         */
+        this._addListeners = function() {
+            if ( UTIL.Event &&
+                 document          &&
+                 document.body        ) {
+
+                this._onLoad();
+            } else {
+                if (this._timeoutCount > 500) {
+                    this.logger.debug("DragDrop requires the Event Utility");
+                } else {
+                    setTimeout("YAHOO.util.DDM._addListeners()", 10);
+                    this._timeoutCount += 1;
+                }
+            }
+
+        };
+
+        /**
+         * Recursively searches the immediate parent and all child nodes for
+         * the handle element in order to determine wheter or not it was
+         * clicked.
+         *
+         * @param node the html element to inspect
+         */
+        this.handleWasClicked = function(node, id) {
+            if (this.isHandle(id, node.id)) {
+                this.logger.debug("clicked node is a handle");
+                return true;
+            } else {
+                // check to see if this is a text node child of the one we want
+                var p = node.parentNode;
+                // this.logger.debug("p: " + p);
+
+                while (p) {
+                    if (this.isHandle(id, p.id)) {
+                        return true;
+                    } else {
+                        this.logger.debug(p.id + " is not a handle");
+                        p = p.parentNode;
+                    }
+                }
+            }
+
+            return false;
+        };
+
+    };
+
+    // shorter alias, save a few bytes
+    YAHOO.util.DDM = YAHOO.util.DragDropMgr;
+    YAHOO.util.DDM._addListeners();
+
+}
+
+/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
+
+/**
+ * @class a DragDrop implementation where the linked element follows the
+ * mouse cursor.
+ *
+ * @extends DragDrop
+ * @constructor
+ * @param {String} id the id of the linked element
+ * @param {String} sGroup the group of related DragDrop items
+ */
+YAHOO.util.DD = function(id, sGroup) {
+    if (id) {
+        this.init(id, sGroup);
+        this.logger.setModuleName("DD");
+    }
+};
+
+YAHOO.util.DD.prototype = new YAHOO.util.DragDrop();
+
+/**
+ * Should we auto-scroll? Defaults to true
+ *
+ * @type boolean
+ */
+YAHOO.util.DD.prototype.scroll = true;
+
+/**
+ * Sets the pointer offset to the distance between the linked element's top
+ * left corner and the location the element was clicked
+ *
+ * @param {int} iPageX the X coordinate of the click
+ * @param {int} iPageY the Y coordinate of the click
+ */
+YAHOO.util.DD.prototype.autoOffset = function(iPageX, iPageY) {
+    var el = this.getEl();
+    var aCoord = YAHOO.util.Dom.getXY(el);
+    var x = iPageX - aCoord[0];
+    var y = iPageY - aCoord[1];
+    this.setDelta(x, y);
+    this.logger.debug("autoOffset el pos: " + aCoord + ", delta: " + x + "," + y);
+};
+
+/**
+ * Sets the pointer offset.  You can call this directly to force the offset to
+ * be in a particular location (e.g., pass in 0,0 to set it to the center of the
+ * object, as done in ygDDSliderBG)
+ *
+ * @param {int} iDeltaX the distance from the left
+ * @param {int} iDeltaY the distance from the top
+ */
+YAHOO.util.DD.prototype.setDelta = function(iDeltaX, iDeltaY) {
+    this.deltaX = iDeltaX;
+    this.deltaY = iDeltaY;
+    this.logger.debug("deltaX:" + this.deltaX + ", deltaY:" + this.deltaY);
+};
+
+/**
+ * Sets the drag element to the location of the mousedown or click event,
+ * maintaining the cursor location relative to the location on the element
+ * that was clicked.  Override this if you want to place the element in a
+ * location other than where the cursor is.
+ *
+ * @param {int} iPageX the X coordinate of the mousedown or drag event
+ * @param {int} iPageY the Y coordinate of the mousedown or drag event
+ */
+
+YAHOO.util.DD.prototype.setDragElPos = function(iPageX, iPageY) {
+    this.alignElWithMouse(this.getDragEl(), iPageX, iPageY);
+};
+
+/**
+ * Sets the element to the location of the mousedown or click event,
+ * maintaining the cursor location relative to the location on the element
+ * that was clicked.  Override this if you want to place the element in a
+ * location other than where the cursor is.
+ *
+ * @param {HTMLElement} el the element to move
+ * @param {int} iPageX the X coordinate of the mousedown or drag event
+ * @param {int} iPageY the Y coordinate of the mousedown or drag event
+ */
+YAHOO.util.DD.prototype.alignElWithMouse = function(el, iPageX, iPageY) {
+    var oCoord = this.getTargetCoord(iPageX, iPageY);
+    var aCoord = [oCoord.x, oCoord.y];
+    // this.logger.debug("****alignElWithMouse : " + el.id + ", " + aCoord + ", " + el.style.display);
+    YAHOO.util.Dom.setXY(el, aCoord);
+
+    this.cachePosition(oCoord.x, oCoord.y);
+
+    this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
+};
+
+/**
+ * Saves the most recent position so that we can reset the constraints and
+ * tick marks on-demand.  We need to know this so that we can calculate the
+ * number of pixels the element is offset from its original position.
+ */
+YAHOO.util.DD.prototype.cachePosition = function(iPageX, iPageY) {
+    if (iPageX) {
+        this.lastPageX = iPageX;
+        this.lastPageY = iPageY;
+    } else {
+        var aCoord = YAHOO.util.Dom.getXY(this.getEl());
+        this.lastPageX = aCoord[0];
+        this.lastPageY = aCoord[1];
+    }
+};
+
+/**
+ * Auto-scroll the window if the dragged object has been moved beyond the
+ * visible window boundary.
+ *
+ * @param {int} x the drag element's x position
+ * @param {int} y the drag element's y position
+ * @param {int} h the height of the drag element
+ * @param {int} w the width of the drag element
+ * @private
+ */
+YAHOO.util.DD.prototype.autoScroll = function(x, y, h, w) {
+
+    if (this.scroll) {
+        // The client height
+        var clientH = this.DDM.getClientHeight();
+
+        // The client width
+        var clientW = this.DDM.getClientWidth();
+
+        // The amt scrolled down
+        var st = this.DDM.getScrollTop();
+
+        // The amt scrolled right
+        var sl = this.DDM.getScrollLeft();
+
+        // Location of the bottom of the element
+        var bot = h + y;
+
+        // Location of the right of the element
+        var right = w + x;
+
+        // The distance from the cursor to the bottom of the visible area,
+        // adjusted so that we don't scroll if the cursor is beyond the
+        // element drag constraints
+        var toBot = (clientH + st - y - this.deltaY);
+
+        // The distance from the cursor to the right of the visible area
+        var toRight = (clientW + sl - x - this.deltaX);
+
+        // this.logger.debug( " x: " + x + " y: " + y + " h: " + h +
+        // " clientH: " + clientH + " clientW: " + clientW +
+        // " st: " + st + " sl: " + sl + " bot: " + bot +
+        // " right: " + right + " toBot: " + toBot + " toRight: " + toRight);
+
+        // How close to the edge the cursor must be before we scroll
+        // var thresh = (document.all) ? 100 : 40;
+        var thresh = 40;
+
+        // How many pixels to scroll per autoscroll op.  This helps to reduce
+        // clunky scrolling. IE is more sensitive about this ... it needs this
+        // value to be higher.
+        var scrAmt = (document.all) ? 80 : 30;
+
+        // Scroll down if we are near the bottom of the visible page and the
+        // obj extends below the crease
+        if ( bot > clientH && toBot < thresh ) {
+            window.scrollTo(sl, st + scrAmt);
+        }
+
+        // Scroll up if the window is scrolled down and the top of the object
+        // goes above the top border
+        if ( y < st && st > 0 && y - st < thresh ) {
+            window.scrollTo(sl, st - scrAmt);
+        }
+
+        // Scroll right if the obj is beyond the right border and the cursor is
+        // near the border.
+        if ( right > clientW && toRight < thresh ) {
+            window.scrollTo(sl + scrAmt, st);
+        }
+
+        // Scroll left if the window has been scrolled to the right and the obj
+        // extends past the left border
+        if ( x < sl && sl > 0 && x - sl < thresh ) {
+            window.scrollTo(sl - scrAmt, st);
+        }
+    }
+};
+
+/**
+ * Finds the location the element should be placed if we want to move
+ * it to where the mouse location less the click offset would place us.
+ *
+ * @param {int} iPageX the X coordinate of the click
+ * @param {int} iPageY the Y coordinate of the click
+ * @return an object that contains the coordinates (Object.x and Object.y)
+ * @private
+ */
+YAHOO.util.DD.prototype.getTargetCoord = function(iPageX, iPageY) {
+
+    // this.logger.debug("getTargetCoord: " + iPageX + ", " + iPageY);
+
+    var x = iPageX - this.deltaX;
+    var y = iPageY - this.deltaY;
+
+    if (this.constrainX) {
+        if (x < this.minX) { x = this.minX; }
+        if (x > this.maxX) { x = this.maxX; }
+    }
+
+    if (this.constrainY) {
+        if (y < this.minY) { y = this.minY; }
+        if (y > this.maxY) { y = this.maxY; }
+    }
+
+    x = this.getTick(x, this.xTicks);
+    y = this.getTick(y, this.yTicks);
+
+    // this.logger.debug("getTargetCoord " +
+            // " iPageX: " + iPageX +
+            // " iPageY: " + iPageY +
+            // " x: " + x + ", y: " + y);
+
+    return {x:x, y:y};
+};
+
+// overrides YAHOO.util.DragDrop
+YAHOO.util.DD.prototype.b4MouseDown = function(e) {
+    // this.resetConstraints();
+    this.autoOffset(YAHOO.util.Event.getPageX(e),
+                        YAHOO.util.Event.getPageY(e));
+};
+
+// overrides YAHOO.util.DragDrop
+YAHOO.util.DD.prototype.b4Drag = function(e) {
+    this.setDragElPos(YAHOO.util.Event.getPageX(e),
+                        YAHOO.util.Event.getPageY(e));
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Debugging ygDragDrop events that can be overridden
+///////////////////////////////////////////////////////////////////////////////
+/*
+YAHOO.util.DD.prototype.startDrag = function(x, y) {
+    this.logger.debug(this.id.toString()  + " startDrag");
+};
+
+YAHOO.util.DD.prototype.onDrag = function(e) {
+    this.logger.debug(this.id.toString() + " onDrag");
+};
+
+YAHOO.util.DD.prototype.onDragEnter = function(e, id) {
+    this.logger.debug(this.id.toString() + " onDragEnter: " + id);
+};
+
+YAHOO.util.DD.prototype.onDragOver = function(e, id) {
+    this.logger.debug(this.id.toString() + " onDragOver: " + id);
+};
+
+YAHOO.util.DD.prototype.onDragOut = function(e, id) {
+    this.logger.debug(this.id.toString() + " onDragOut: " + id);
+};
+
+YAHOO.util.DD.prototype.onDragDrop = function(e, id) {
+    this.logger.debug(this.id.toString() + " onDragDrop: " + id);
+};
+
+YAHOO.util.DD.prototype.endDrag = function(e) {
+    this.logger.debug(this.id.toString() + " endDrag");
+};
+*/
+
+/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
+
+/**
+ * @class a DragDrop implementation that inserts an empty, bordered div into
+ * the document that follows the cursor during drag operations.  At the time of
+ * the click, the frame div is resized to the dimensions of the linked html
+ * element, and moved to the exact location of the linked element.
+ *
+ * @extends YAHOO.util.DD
+ * @constructor
+ * @param {String} id the id of the linked html element
+ * @param {String} sGroup the group of related DragDrop objects
+ */
+YAHOO.util.DDProxy = function(id, sGroup) {
+    if (id) {
+        this.init(id, sGroup);
+        this.initFrame();
+        this.logger.setModuleName("DDProxy");
+    }
+};
+
+YAHOO.util.DDProxy.prototype = new YAHOO.util.DD();
+
+/**
+ * A reference to the one div element we create for all instances of this class
+ *
+ * @type Object
+ */
+YAHOO.util.DDProxy.frameDiv = null;
+
+/**
+ * the drag frame div id
+ *
+ * @type String
+ */
+YAHOO.util.DDProxy.dragElId = "ygddfdiv";
+
+/**
+ * The border width of the frame.  This is used when we resize the frame to
+ * the size of the linked element.  We substract the border width to make
+ * the div the correct size.
+ *
+ * @TODO find a better way to handle this
+ *
+ * @type int
+ */
+YAHOO.util.DDProxy.prototype.borderWidth = 2;
+
+/**
+ * By default we resize the drag frame to be the same size as the element
+ * we want to drag (this is to get the frame effect).  We can turn it off
+ * if we want a different behavior (ex: ygDDMy2)
+ *
+ * @type boolean
+ */
+YAHOO.util.DDProxy.prototype.resizeFrame = true;
+
+/**
+ * By default the frame is positioned exactly where the drag element is, so
+ * we use the cursor offset provided by YAHOO.util.DD.  Another option that works only if
+ * you do not have constraints on the obj is to have the drag frame centered
+ * around the cursor.  Set centerFrame to true for this effect.  Ex:
+ * ygDDMy2
+ *
+ * @type boolean
+ */
+YAHOO.util.DDProxy.prototype.centerFrame = false;
+
+/**
+ * Create the drag frame if needed
+ */
+YAHOO.util.DDProxy.createFrame = function() {
+    var THIS = YAHOO.util.DDProxy;
+
+    if (!document || !document.body) {
+        setTimeout(THIS.createFrame, 50);
+        return;
+    }
+
+    if (!THIS.frameDiv) {
+        THIS.frameDiv = document.createElement("div");
+        THIS.frameDiv.id = THIS.dragElId;
+        var s = THIS.frameDiv.style;
+        s.position = "absolute";
+        s.visibility = "hidden";
+        s.cursor = "move";
+        s.border = "2px solid #aaa";
+        s.zIndex = 999;
+
+        document.body.appendChild(THIS.frameDiv);
+    }
+};
+
+/**
+ * Initialization for the drag frame element.  Must be called in the
+ * constructor of all subclasses
+ */
+YAHOO.util.DDProxy.prototype.initFrame = function() {
+    YAHOO.util.DDProxy.createFrame();
+    this.setDragElId(YAHOO.util.DDProxy.dragElId);
+    this.useAbsMath = true;
+};
+
+/**
+ * Resizes the drag frame to the dimensions of the clicked object, positions
+ * it over the object, and finally displays it
+ *
+ * @param {int} iPageX X click position
+ * @param {int} iPageY Y click position
+ * @private
+ */
+YAHOO.util.DDProxy.prototype.showFrame = function(iPageX, iPageY) {
+    var el = this.getEl();
+
+    var s = this.getDragEl().style;
+
+    if (this.resizeFrame) {
+        s.width = (parseInt(el.offsetWidth) - (2*this.borderWidth)) + "px";
+        s.height = (parseInt(el.offsetHeight) - (2*this.borderWidth)) + "px";
+    }
+
+    if (this.centerFrame) {
+        this.setDelta(Math.round(parseInt(s.width)/2),
+                Math.round(parseInt(s.width)/2));
+    }
+
+    this.setDragElPos(iPageX, iPageY);
+
+    s.visibility = "";
+};
+
+// overrides YAHOO.util.DragDrop
+YAHOO.util.DDProxy.prototype.b4MouseDown = function(e) {
+    var x = YAHOO.util.Event.getPageX(e);
+    var y = YAHOO.util.Event.getPageY(e);
+    this.autoOffset(x, y);
+    this.setDragElPos(x, y);
+};
+
+// overrides YAHOO.util.DragDrop
+YAHOO.util.DDProxy.prototype.b4StartDrag = function(x, y) {
+    // show the drag frame
+    this.logger.debug("start drag show frame, x: " + x + ", y: " + y);
+    this.showFrame(x, y);
+};
+
+// overrides YAHOO.util.DragDrop
+YAHOO.util.DDProxy.prototype.b4EndDrag = function(e) {
+    this.logger.debug(this.id + " b4EndDrag");
+
+    // hide the drag frame
+    var s = this.getDragEl().style;
+    s.visibility = "hidden";
+};
+
+// overrides YAHOO.util.DragDrop
+// By default we try to move the element to the last location of the frame.
+// This is so that the default behavior mirrors that of YAHOO.util.DD.
+YAHOO.util.DDProxy.prototype.endDrag = function(e) {
+    this.logger.debug(this.id + " endDrag");
+    var lel = this.getEl();
+    var del = this.getDragEl();
+
+    // Show the drag frame briefly so we can get its position
+    del.style.visibility = "";
+
+    // Hide the linked element before the move to get around a Safari
+    // rendering bug.
+    lel.style.visibility = "hidden";
+    YAHOO.util.DDM.moveToEl(lel, del);
+    del.style.visibility = "hidden";
+    lel.style.visibility = "";
+};
+
+/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
+
+/**
+ * @class a DragDrop implementation that does not move, but can be a drop
+ * target.  You would get the same result by simply omitting implementation
+ * for the event callbacks, but this way we reduce the processing cost of the
+ * event listener and the callbacks.
+ *
+ * @extends YAHOO.util.DragDrop
+ * @constructor
+ * @param {String} id the id of the element that is a drop target
+ * @param {String} sGroup the group of related DragDrop objects
+ */
+
+YAHOO.util.DDTarget = function(id, sGroup) {
+    if (id) {
+        this.initTarget(id, sGroup);
+        this.logger.setModuleName("DDTarget");
+    }
+};
+
+YAHOO.util.DDTarget.prototype = new YAHOO.util.DragDrop();
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/dragdrop.js
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/dragdrop.js	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/dragdrop.js	(revision 13928)
@@ -0,0 +1,2426 @@
+/*
+Copyright (c) 2006 Yahoo! Inc. All rights reserved.
+version 0.9.0
+*/
+
+/**
+ * @class Defines the interface and base operation of items that that can be
+ * dragged or can be drop targets.  It was designed to be extended, overriding
+ * the event handlers for startDrag, onDrag, onDragOver, onDragOut.
+ * Up to three html elements can be associated with a DragDrop instance:
+ * <ul>
+ * <li>linked element: the element that is passed into the constructor.
+ * This is the element which defines the boundaries for interaction with
+ * other DragDrop objects.</li>
+ * <li>handle element(s): The drag operation only occurs if the element that
+ * was clicked matches a handle element.  By default this is the linked
+ * element, but there are times that you will want only a portion of the
+ * linked element to initiate the drag operation, and the setHandleElId()
+ * method provides a way to define this.</li>
+ * <li>drag element: this represents an the element that would be moved along
+ * with the cursor during a drag operation.  By default, this is the linked
+ * element itself as in {@link YAHOO.util.DD}.  setDragElId() lets you define
+ * a separate element that would be moved, as in {@link YAHOO.util.DDProxy}
+ * </li>
+ * </ul>
+ * This class should not be instantiated until the onload event to ensure that
+ * the associated elements are available.
+ * The following would define a DragDrop obj that would interact with any
+ * other * DragDrop obj in the "group1" group:
+ * <pre>
+ *  dd = new YAHOO.util.DragDrop("div1", "group1");
+ * </pre>
+ * Since none of the event handlers have been implemented, nothing would
+ * actually happen if you were to run the code above.  Normally you would
+ * override this class or one of the default implementations, but you can
+ * also override the methods you want on an instance of the class...
+ * <pre>
+ *  dd.onDragDrop = function(e, id) {
+ *   alert("dd was dropped on " + id);
+ *  }
+ * </pre>
+ * @constructor
+ * @param {String} id of the element that is linked to this instance
+ * @param {String} sGroup the group of related DragDrop objects
+ */
+YAHOO.util.DragDrop = function(id, sGroup) {
+    if (id) {
+        this.init(id, sGroup);
+    }
+};
+
+YAHOO.util.DragDrop.prototype = {
+
+    /**
+     * The id of the element associated with this object.  This is what we
+     * refer to as the "linked element" because the size and position of
+     * this element is used to determine when the drag and drop objects have
+     * interacted.
+     *
+     * @type String
+     */
+    id: null,
+
+    /**
+     * The id of the element that will be dragged.  By default this is same
+     * as the linked element , but could be changed to another element. Ex:
+     * YAHOO.util.DDProxy
+     *
+     * @type String
+     * @private
+     */
+    dragElId: null,
+
+    /**
+     * the id of the element that initiates the drag operation.  By default
+     * this is the linked element, but could be changed to be a child of this
+     * element.  This lets us do things like only starting the drag when the
+     * header element within the linked html element is clicked.
+     *
+     * @type String
+     * @private
+     */
+    handleElId: null,
+
+    /**
+     * An array of HTML tags that will be ignored if clicked.
+     */
+    invalidHandleTypes: null,
+
+    /**
+     * The linked element's absolute X position at the time the drag was
+     * started
+     *
+     * @type int
+     * @private
+     */
+    startPageX: 0,
+
+    /**
+     * The linked element's absolute X position at the time the drag was
+     * started
+     *
+     * @type int
+     * @private
+     */
+    startPageY: 0,
+
+    /**
+     * The group defines a logical collection of DragDrop objects that are
+     * related.  Instances only get events when interacting with other
+     * DragDrop object in the same group.  This lets us define multiple
+     * groups using a single DragDrop subclass if we want.
+     *
+     */
+    groups: null,
+
+    /**
+     * Individual drag/drop instances can be locked.  This will prevent
+     * onmousedown start drag.
+     *
+     * @type boolean
+     * @private
+     */
+    locked: false,
+
+    /**
+     * Lock this instance
+     */
+    lock: function() { this.locked = true; },
+
+    /**
+     * Unlock this instace
+     */
+    unlock: function() { this.locked = false; },
+
+    /**
+     * By default, all insances can be a drop target.  This can be disabled by
+     * setting isTarget to false.
+     *
+     * @type boolean
+     */
+    isTarget: true,
+
+    /**
+     * The padding configured for this drag and drop object for calculating
+     * the drop zone intersection with this object.
+     */
+    padding: null,
+
+    /**
+     * @private
+     */
+    _domRef: null,
+
+    /**
+     * Internal typeof flag
+     * @private
+     */
+    __ygDragDrop: true,
+
+    /**
+     * Set to true when horizontal contraints are applied
+     *
+     * @type boolean
+     * @private
+     */
+    constrainX: false,
+
+    /**
+     * Set to true when vertical contraints are applied
+     *
+     * @type boolean
+     * @private
+     */
+    constrainY: false,
+
+    /**
+     * The left constraint
+     *
+     * @type int
+     * @private
+     */
+    minX: 0,
+
+    /**
+     * The right constraint
+     *
+     * @type int
+     * @private
+     */
+    maxX: 0,
+
+    /**
+     * The up constraint
+     *
+     * @type int
+     * @private
+     */
+    minY: 0,
+
+    /**
+     * The down constraint
+     *
+     * @type int
+     * @private
+     */
+    maxY: 0,
+
+    /**
+     * Maintain offsets when we resetconstraints.  Used to maintain the
+     * slider thumb value, and this needs to be fixed.
+     * @type boolean
+     */
+    maintainOffset: false,
+
+    /**
+     * Array of pixel locations the element will snap to if we specified a
+     * horizontal graduation/interval.  This array is generated automatically
+     * when you define a tick interval.
+     * @type int[]
+     */
+    xTicks: null,
+
+    /**
+     * Array of pixel locations the element will snap to if we specified a
+     * vertical graduation/interval.  This array is generated automatically
+     * when you define a tick interval.
+     * @type int[]
+     */
+    yTicks: null,
+
+    /**
+     * By default the drag and drop instance will only respond to the primary
+     * button click (left button for a right-handed mouse).  Set to true to
+     * allow drag and drop to start with any mouse click that is propogated
+     * by the browser
+     * @type boolean
+     */
+    primaryButtonOnly: true,
+
+    /**
+     * Code that executes immediately before the startDrag event
+     * @private
+     */
+    b4StartDrag: function(x, y) { },
+
+    /**
+     * Abstract method called after a drag/drop object is clicked
+     * and the drag or mousedown time thresholds have beeen met.
+     *
+     * @param {int} X click location
+     * @param {int} Y click location
+     */
+    startDrag: function(x, y) { /* override this */ },
+
+    /**
+     * Code that executes immediately before the onDrag event
+     * @private
+     */
+    b4Drag: function(e) { },
+
+    /**
+     * Abstract method called during the onMouseMove event while dragging an
+     * object.
+     *
+     * @param {Event} e
+     */
+    onDrag: function(e) { /* override this */ },
+
+    /**
+     * Code that executes immediately before the onDragEnter event
+     * @private
+     */
+    // b4DragEnter: function(e) { },
+
+    /**
+     * Abstract method called when this element fist begins hovering over
+     * another DragDrop obj
+     *
+     * @param {Event} e
+     * @param {String || YAHOO.util.DragDrop[]} id In POINT mode, the element
+     * id this is hovering over.  In INTERSECT mode, an array of one or more
+     * dragdrop items being hovered over.
+     */
+    onDragEnter: function(e, id) { /* override this */ },
+
+    /**
+     * Code that executes immediately before the onDragOver event
+     * @private
+     */
+    b4DragOver: function(e) { },
+
+    /**
+     * Abstract method called when this element is hovering over another
+     * DragDrop obj
+     *
+     * @param {Event} e
+     * @param {String || YAHOO.util.DragDrop[]} id In POINT mode, the element
+     * id this is hovering over.  In INTERSECT mode, an array of dd items
+     * being hovered over.
+     */
+    onDragOver: function(e, id) { /* override this */ },
+
+    /**
+     * Code that executes immediately before the onDragOut event
+     * @private
+     */
+    b4DragOut: function(e) { },
+
+    /**
+     * Abstract method called when we are no longer hovering over an element
+     *
+     * @param {Event} e
+     * @param {String || YAHOO.util.DragDrop[]} id In POINT mode, the element
+     * id this was hovering over.  In INTERSECT mode, an array of dd items
+     * that the mouse is no longer over.
+     */
+    onDragOut: function(e, id) { /* override this */ },
+
+    /**
+     * Code that executes immediately before the onDragDrop event
+     * @private
+     */
+    b4DragDrop: function(e) { },
+
+    /**
+     * Abstract method called when this item is dropped on another DragDrop
+     * obj
+     *
+     * @param {Event} e
+     * @param {String || YAHOO.util.DragDrop[]} id In POINT mode, the element
+     * id this was dropped on.  In INTERSECT mode, an array of dd items this
+     * was dropped on.
+     */
+    onDragDrop: function(e, id) { /* override this */ },
+
+    /**
+     * Code that executes immediately before the endDrag event
+     * @private
+     */
+    b4EndDrag: function(e) { },
+
+    /**
+     * Fired when we are done dragging the object
+     *
+     * @param {Event} e
+     */
+    endDrag: function(e) { /* override this */ },
+
+    /**
+     * Code executed immediately before the onMouseDown event
+
+     * @param {Event} e
+     * @private
+     */
+    b4MouseDown: function(e) {  },
+
+    /**
+     * Event handler that fires when a drag/drop obj gets a mousedown
+     * @param {Event} e
+     */
+    onMouseDown: function(e) { /* override this */ },
+
+    /**
+     * Event handler that fires when a drag/drop obj gets a mouseup
+     * @param {Event} e
+     */
+    onMouseUp: function(e) { /* override this */ },
+
+    /**
+     * Returns a reference to the linked element
+     *
+     * @return {Object} the html element
+     */
+    getEl: function() {
+        if (!this._domRef) {
+            this._domRef = this.DDM.getElement(this.id);
+        }
+
+        return this._domRef;
+    },
+
+    /**
+     * Returns a reference to the actual element to drag.  By default this is
+     * the same as the html element, but it can be assigned to another
+     * element. An example of this can be found in YAHOO.util.DDProxy
+     *
+     * @return {Object} the html element
+     */
+    getDragEl: function() {
+        return this.DDM.getElement(this.dragElId);
+    },
+
+    /**
+     * Sets up the DragDrop object.  Must be called in the constructor of any
+     * YAHOO.util.DragDrop subclass
+     *
+     * @param id the id of the linked element
+     * @param {String} sGroup the group of related items
+     * element is supposed to be a target only, set to false.
+     */
+    init: function(id, sGroup) {
+        this.initTarget(id, sGroup);
+        YAHOO.util.Event.addListener(id, "mousedown",
+                                          this.handleMouseDown, this, true);
+    },
+
+    /**
+     * Initializes Targeting functionality only... the object does not
+     * get a mousedown handler.
+     *
+     * @param id the id of the linked element
+     * @param {String} sGroup the group of related items
+     * element is supposed to be a target only, set to false.
+     */
+    initTarget: function(id, sGroup) {
+
+        // create a local reference to the drag and drop manager
+        this.DDM = YAHOO.util.DDM;
+
+
+        // set the default padding
+        this.padding = [0, 0, 0, 0];
+
+        // initialize the groups array
+        this.groups = {};
+
+        // set the id
+        this.id = id;
+
+        // the element is a drag handle by default
+        this.setDragElId(id);
+
+        // by default, clicked anchors will not start drag operations
+        this.invalidHandleTypes = {a : "a"};
+
+        // We don't want to register this as the handle with the manager
+        // so we just set the id rather than calling the setter
+        this.handleElId = id;
+
+        // cache the position of the element if we can
+        if (document && document.body) {
+            this.setInitPosition();
+        }
+
+        // add to an interaction group
+        this.addToGroup((sGroup) ? sGroup : "default");
+
+    },
+
+    /**
+     * Configures the padding for the target zone in px.  Effectively expands
+     * (or reduces) the virtual object size for targeting calculations.
+     * Supports css-style shorthand; if only one parameter is passed, all sides
+     * will have that padding, and if only two are passed, the top and bottom
+     * will have the first param, the left and right the second.
+     * @param {int} iTop    Top pad
+     * @param {int} iRight  Right pad
+     * @param {int} iBot    Bot pad
+     * @param {int} iLeft   Left pad
+     */
+    setPadding: function(iTop, iRight, iBot, iLeft) {
+        // this.padding = [iLeft, iRight, iTop, iBot];
+        if (!iRight && 0 !== iRight) {
+            this.padding = [iTop, iTop, iTop, iTop];
+        } else if (!iBot && 0 !== iBot) {
+            this.padding = [iTop, iRight, iTop, iRight];
+        } else {
+            this.padding = [iTop, iRight, iBot, iLeft];
+        }
+    },
+
+    /**
+     * Stores the initial placement of the dd element
+     */
+    setInitPosition: function(diffX, diffY) {
+        var el = this.getEl();
+
+        if (!this.DDM.verifyEl(el)) {
+            return;
+        }
+
+        var dx = diffX || 0;
+        var dy = diffY || 0;
+
+        var p = YAHOO.util.Dom.getXY( el );
+
+        this.initPageX = p[0] - dx;
+        this.initPageY = p[1] - dy;
+
+        this.lastPageX = p[0];
+        this.lastPageY = p[1];
+
+        this.setStartPosition(p);
+    },
+
+    /**
+     * Sets the start position of the element.  This is set when the obj
+     * is initialized, the reset when a drag is started.
+     * @param pos current position (from previous lookup)
+     * @private
+     */
+    setStartPosition: function(pos) {
+
+        var p = pos || YAHOO.util.Dom.getXY( this.getEl() );
+
+        this.startPageX = p[0];
+        this.startPageY = p[1];
+    },
+
+    /**
+     * Add this instance to a group of related drag/drop objects.  All
+     * instances belong to at least one group, and can belong to as many
+     * groups as needed.
+     *
+     * @param sGroup {string} the name of the group
+     */
+    addToGroup: function(sGroup) {
+        this.groups[sGroup] = true;
+        this.DDM.regDragDrop(this, sGroup);
+    },
+
+    /**
+     * Allows you to specify that an element other than the linked element
+     * will be moved with the cursor during a drag
+     *
+     * @param id the id of the element that will be used to initiate the drag
+     */
+    setDragElId: function(id) {
+        this.dragElId = id;
+    },
+
+    /**
+     * Allows you to specify a child of the linked element that should be
+     * used to initiate the drag operation.  An example of this would be if
+     * you have a content div with text and links.  Clicking anywhere in the
+     * content area would normally start the drag operation.  Use this method
+     * to specify that an element inside of the content div is the element
+     * that starts the drag operation.
+     *
+     * @param id the id of the element that will be used to initiate the drag
+     */
+    setHandleElId: function(id) {
+        this.handleElId = id;
+        this.DDM.regHandle(this.id, id);
+    },
+
+    /**
+     * Allows you to set an element outside of the linked element as a drag
+     * handle
+     */
+    setOuterHandleElId: function(id) {
+        YAHOO.util.Event.addListener(id, "mousedown",
+                this.handleMouseDown, this, true);
+        this.setHandleElId(id);
+    },
+
+    /**
+     * Remove all drag and drop hooks for this element
+     */
+    unreg: function() {
+        YAHOO.util.Event.removeListener(this.id, "mousedown",
+                this.handleMouseDown);
+        this._domRef = null;
+        this.DDM._remove(this);
+    },
+
+    /**
+     * Returns true if this instance is locked, or the drag drop mgr is locked
+     * (meaning that all drag/drop is disabled on the page.)
+     *
+     * @return {boolean} true if this obj or all drag/drop is locked, else
+     * false
+     */
+    isLocked: function() {
+        return (this.DDM.isLocked() || this.locked);
+    },
+
+    /**
+     * Fired when this object is clicked
+     *
+     * @param {Event} e
+     * @param {YAHOO.util.DragDrop} oDD the clicked dd object (this dd obj)
+     * @private
+     */
+    handleMouseDown: function(e, oDD) {
+
+
+        var EU = YAHOO.util.Event;
+
+
+        var button = e.which || e.button;
+
+        if (this.primaryButtonOnly && button > 1) {
+            return;
+        }
+
+        if (this.isLocked()) {
+            return;
+        }
+
+
+        this.DDM.refreshCache(this.groups);
+
+        // Only process the event if we really clicked within the linked
+        // element.  The reason we make this check is that in the case that
+        // another element was moved between the clicked element and the
+        // cursor in the time between the mousedown and mouseup events. When
+        // this happens, the element gets the next mousedown event
+        // regardless of where on the screen it happened.
+        var pt = new YAHOO.util.Point(EU.getPageX(e), EU.getPageY(e));
+        if ( this.DDM.isOverTarget(pt, this) )  {
+
+
+            //  check to see if the handle was clicked
+            var srcEl = EU.getTarget(e);
+
+            if (this.isValidHandleChild(srcEl) &&
+                    (this.id == this.handleElId ||
+                     this.DDM.handleWasClicked(srcEl, this.id)) ) {
+
+                // set the initial element position
+                this.setStartPosition();
+
+
+                this.b4MouseDown(e);
+                this.onMouseDown(e);
+                this.DDM.handleMouseDown(e, this);
+
+                this.DDM.stopEvent(e);
+            }
+        }
+    },
+
+    /**
+     * Allows you to specify a tag name that should not start a drag operation
+     * when clicked.  This is designed to facilitate embedding links within a
+     * drag handle that do something other than start the drag.
+     *
+     * @param {string} tagName the type of element to exclude
+     */
+    addInvalidHandleType: function(tagName) {
+        var type = tagName.toUpperCase();
+        this.invalidHandleTypes[type] = type;
+    },
+
+    /**
+     * Unsets an excluded tag name set by addInvalidHandleType
+     *
+     * @param {string} tagName the type of element to unexclude
+     */
+    removeInvalidHandleType: function(tagName) {
+        var type = tagName.toUpperCase();
+        this.invalidHandleTypes[type] = null;
+    },
+
+    /**
+     * Checks the tag exclusion list to see if this click should be ignored
+     *
+     * @param {ygNode} node
+     * @return {boolean} true if this is a valid tag type, false if not
+     */
+    isValidHandleChild: function(node) {
+        var type = node.nodeName;
+
+        if (type == "#text") {
+            type = node.parentNode.nodeName;
+        }
+
+        return (!this.invalidHandleTypes[type]);
+    },
+
+    /**
+     * Create the array of horizontal tick marks if an interval was specified
+     * in setXConstraint().
+     *
+     * @private
+     */
+    setXTicks: function(iStartX, iTickSize) {
+        this.xTicks = [];
+        this.xTickSize = iTickSize;
+
+        var tickMap = {};
+
+        for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
+            if (!tickMap[i]) {
+                this.xTicks[this.xTicks.length] = i;
+                tickMap[i] = true;
+            }
+        }
+
+        for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
+            if (!tickMap[i]) {
+                this.xTicks[this.xTicks.length] = i;
+                tickMap[i] = true;
+            }
+        }
+
+        this.xTicks.sort(this.DDM.numericSort) ;
+    },
+
+    /**
+     * Create the array of vertical tick marks if an interval was specified in
+     * setYConstraint().
+     *
+     * @private
+     */
+    setYTicks: function(iStartY, iTickSize) {
+        this.yTicks = [];
+        this.yTickSize = iTickSize;
+
+        var tickMap = {};
+
+        for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
+            if (!tickMap[i]) {
+                this.yTicks[this.yTicks.length] = i;
+                tickMap[i] = true;
+            }
+        }
+
+        for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
+            if (!tickMap[i]) {
+                this.yTicks[this.yTicks.length] = i;
+                tickMap[i] = true;
+            }
+        }
+
+        this.yTicks.sort(this.DDM.numericSort) ;
+    },
+
+    /**
+     * By default, the element can be dragged any place on the screen.  Use
+     * this method to limit the horizontal travel of the element.  Pass in
+     * 0,0 for the parameters if you want to lock the drag to the y axis.
+     *
+     * @param {int} iLeft the number of pixels the element can move to the left
+     * @param {int} iRight the number of pixels the element can move to the
+     * right
+     * @param {int} iTickSize optional parameter for specifying that the
+     * element
+     * should move iTickSize pixels at a time.
+     */
+    setXConstraint: function(iLeft, iRight, iTickSize) {
+        this.leftConstraint = iLeft;
+        this.rightConstraint = iRight;
+
+        this.minX = this.initPageX - iLeft;
+        this.maxX = this.initPageX + iRight;
+        if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
+
+        this.constrainX = true;
+    },
+
+    /**
+     * By default, the element can be dragged any place on the screen.  Set
+     * this to limit the vertical travel of the element.  Pass in 0,0 for the
+     * parameters if you want to lock the drag to the x axis.
+     *
+     * @param {int} iUp the number of pixels the element can move up
+     * @param {int} iDown the number of pixels the element can move down
+     * @param {int} iTickSize optional parameter for specifying that the
+     * element should move iTickSize pixels at a time.
+     */
+    setYConstraint: function(iUp, iDown, iTickSize) {
+        this.topConstraint = iUp;
+        this.bottomConstraint = iDown;
+
+        this.minY = this.initPageY - iUp;
+        this.maxY = this.initPageY + iDown;
+        if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
+
+        this.constrainY = true;
+
+    },
+
+    /**
+     * resetConstraints must be called if you manually reposition a dd element.
+     * @param {boolean} maintainOffset
+     */
+    resetConstraints: function() {
+
+
+        // figure out how much this thing has moved
+        var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
+        var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
+
+
+        // reset the initial location
+        this.setInitPosition(dx, dy);
+
+        if (this.constrainX) {
+            this.setXConstraint( this.leftConstraint,
+                                 this.rightConstraint,
+                                 this.xTickSize        );
+        }
+
+        if (this.constrainY) {
+            this.setYConstraint( this.topConstraint,
+                                 this.bottomConstraint,
+                                 this.yTickSize         );
+        }
+    },
+
+    /**
+     * Normally the drag element is moved pixel by pixel, but we can specify
+     * that it move a number of pixels at a time.  This method resolves the
+     * location when we have it set up like this.
+     *
+     * @param {int} val where we want to place the object
+     * @param {int[]} tickArray sorted array of valid points
+     * @return {int} the closest tick
+     * @private
+     */
+    getTick: function(val, tickArray) {
+
+        if (!tickArray) {
+            // If tick interval is not defined, it is effectively 1 pixel,
+            // so we return the value passed to us.
+            return val;
+        } else if (tickArray[0] >= val) {
+            // The value is lower than the first tick, so we return the first
+            // tick.
+            return tickArray[0];
+        } else {
+            for (var i = 0; i < tickArray.length; ++i) {
+                var next = i + 1;
+                if (tickArray[next] && tickArray[next] >= val) {
+                    var diff1 = val - tickArray[i];
+                    var diff2 = tickArray[next] - val;
+                    return (diff2 > diff1) ? tickArray[i] : tickArray[next];
+                }
+            }
+
+            // The value is larger than the last tick, so we return the last
+            // tick.
+            return tickArray[tickArray.length - 1];
+        }
+    },
+
+    /**
+     * toString method
+     * @return {string} string representation of the dd obj
+     */
+    toString: function(val, tickArray) {
+        return ("YAHOO.util.DragDrop {" + this.id + "}");
+    }
+
+};
+
+/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
+
+// Only load the library once.  Rewriting the manager class would orphan
+// existing drag and drop instances.
+if (!YAHOO.util.DragDropMgr) {
+
+    /**
+     * @class Handles the element interaction for all DragDrop items in the
+     * window.  Generally, you will not call this class directly, but it does
+     * have helper methods that could be useful in your DragDrop
+     * implementations.  This class should not be instantiated; all methods
+     * are are static.
+     *
+     * @constructor
+     */
+    YAHOO.util.DragDropMgr = new function() {
+
+        /**
+         * utility package shorthand
+         * @private
+         */
+        var UTIL = YAHOO.util;
+
+        /**
+         * Two dimensional Array of registered DragDrop objects.  The first
+         * dimension is the DragDrop item group, the second the DragDrop
+         * object.
+         *
+         * @private
+         */
+        this.ids = {};
+
+        /**
+         * Array of element ids defined as drag handles.  Used to determine
+         * if the element that generated the mousedown event is actually the
+         * handle and not the html element itself.
+         *
+         * @private
+         */
+        this.handleIds = {};
+
+        /**
+         * the DragDrop object that is currently being dragged
+         *
+         * @type DragDrop
+         * @private
+         **/
+        this.dragCurrent = null;
+
+        /**
+         * the DragDrop object(s) that are being hovered over
+         *
+         * @type Array
+         * @private
+         */
+        this.dragOvers = {};
+
+        /**
+         * @private
+         */
+
+        /**
+         * the X distance between the cursor and the object being dragged
+         *
+         * @type int
+         * @private
+         */
+        this.deltaX = 0;
+
+        /**
+         * the Y distance between the cursor and the object being dragged
+         *
+         * @type int
+         * @private
+         */
+        this.deltaY = 0;
+
+        /**
+         * Flag to determine if we should prevent the default behavior of the
+         * events we define. By default this is true, but this can be set to
+         * false if you need the default behavior (not recommended)
+         *
+         * @type boolean
+         */
+        this.preventDefault = true;
+
+        /**
+         * Flag to determine if we should stop the propagation of the events
+         * we generate. This is true by default but you may want to set it to
+         * false if the html element contains other features that require the
+         * mouse click.
+         *
+         * @type boolean
+         */
+        this.stopPropagation = true;
+
+        /**
+         * @private
+         */
+        this.initalized = false;
+
+        /**
+         * All drag and drop can be disabled.
+         *
+         * @private
+         */
+        this.locked = false;
+
+        /**
+         * Called the first time an element is registered.
+         *
+         * @private
+         */
+        this.init = function() {
+        };
+
+        /**
+         * In point mode, drag and drop interaction is defined by the
+         * location of the cursor during the drag/drop
+         * @type int
+         */
+        this.POINT     = 0;
+
+        /**
+         * In intersect mode, drag and drop interactio nis defined by the
+         * overlap of two or more drag and drop objects.
+         * @type int
+         */
+        this.INTERSECT = 1;
+
+        /**
+         * The current drag and drop mode.  Default it point mode
+         * @type int
+         */
+        this.mode = this.POINT;
+
+        /**
+         * Runs method on all drag and drop objects
+         * @private
+         */
+        this._execOnAll = function(sMethod, args) {
+            for (var i in this.ids) {
+                for (var j in this.ids[i]) {
+                    var oDD = this.ids[i][j];
+                    if (! this.isTypeOfDD(oDD)) {
+                        continue;
+                    }
+                    oDD[sMethod].apply(oDD, args);
+                }
+            }
+        };
+
+        /**
+         * Drag and drop initialization.  Sets up the global event handlers
+         * @private
+         */
+        this._onLoad = function() {
+
+            this._execOnAll("setInitPosition", []);
+
+
+            var EU = UTIL.Event;
+
+            EU.addListener(document, "mouseup",   this.handleMouseUp, this, true);
+            EU.addListener(document, "mousemove", this.handleMouseMove, this, true);
+            EU.addListener(window,   "unload",    this._onUnload, this, true);
+            EU.addListener(window,   "resize",    this._onResize, this, true);
+            // EU.addListener(window,   "mouseout",    this._test);
+
+            this.initalized = true;
+
+        };
+
+        /**
+         * Reset constraints on all drag and drop objs
+         * @private
+         */
+        this._onResize = function(e) {
+            this._execOnAll("resetConstraints", []);
+        };
+
+        /**
+         * Lock all drag and drop functionality
+         */
+        this.lock = function() { this.locked = true; };
+
+        /**
+         * Unlock all drag and drop functionality
+         */
+        this.unlock = function() { this.locked = false; };
+
+        /**
+         * Is drag and drop locked?
+         *
+         * @return {boolean} True if drag and drop is locked, false otherwise.
+         */
+        this.isLocked = function() { return this.locked; };
+
+        /**
+         * Location cache that is set for all drag drop objects when a drag is
+         * initiated, cleared when the drag is finished.
+         *
+         * @private
+         */
+        this.locationCache = {};
+
+        /**
+         * Set useCache to false if you want to force object the lookup of each
+         * drag and drop linked element constantly during a drag.
+         * @type boolean
+         */
+        this.useCache = true;
+
+        /**
+         * The number of pixels that the mouse needs to move after the
+         * mousedown before the drag is initiated.  Default=3;
+         * @type int
+         */
+        this.clickPixelThresh = 3;
+
+        /**
+         * The number of milliseconds after the mousedown event to initiate the
+         * drag if we don't get a mouseup event. Default=1000
+         * @type int
+         */
+        this.clickTimeThresh = 1000;
+
+        /**
+         * Flag that indicates that either the drag pixel threshold or the
+         * mousdown time threshold has been met
+         * @type boolean
+         * @private
+         */
+        this.dragThreshMet = false;
+
+        /**
+         * Timeout used for the click time threshold
+         * @type Object
+         * @private
+         */
+        this.clickTimeout = null;
+
+        /**
+         * The X position of the mousedown event stored for later use when a
+         * drag threshold is met.
+         * @type int
+         * @private
+         */
+        this.startX = 0;
+
+        /**
+         * The Y position of the mousedown event stored for later use when a
+         * drag threshold is met.
+         * @type int
+         * @private
+         */
+        this.startY = 0;
+
+        /**
+         * Each DragDrop instance must be registered with the DragDropMgr.
+         * This is executed in ygDragDrop.init()
+         *
+         * @param {DragDrop} oDD the DragDrop object to register
+         * @param {String} sGroup the name of the group this element belongs to
+         */
+        this.regDragDrop = function(oDD, sGroup) {
+            if (!this.initialized) { this.init(); }
+
+            if (!this.ids[sGroup]) {
+                this.ids[sGroup] = {};
+            }
+            this.ids[sGroup][oDD.id] = oDD;
+        };
+
+        /**
+         * Unregisters a drag and drop item.  This is executed in
+         * ygDragDrop.unreg, use that method instead of calling this directly.
+         * @private
+         */
+        this._remove = function(oDD) {
+            for (var g in oDD.groups) {
+                if (g && this.ids[g][oDD.id]) {
+                    delete this.ids[g][oDD.id];
+                }
+            }
+            delete this.handleIds[oDD.id];
+        };
+
+        /**
+         * Each DragDrop handle element must be registered.  This is done
+         * automatically when executing ygDragDrop.setHandleElId()
+         *
+         * @param {String} sDDId the DragDrop id this element is a handle for
+         * @param {String} sHandleId the id of the element that is the drag
+         * handle
+         */
+        this.regHandle = function(sDDId, sHandleId) {
+            if (!this.handleIds[sDDId]) {
+                this.handleIds[sDDId] = {};
+            }
+            this.handleIds[sDDId][sHandleId] = sHandleId;
+        };
+
+        /**
+         * Utility function to determine if a given element has been
+         * registered as a drag drop item.
+         *
+         * @param {String} id the element id to check
+         * @return {boolean} true if this element is a DragDrop item,
+         * false otherwise
+         */
+        this.isDragDrop = function(id) {
+            return ( this.getDDById(id) ) ? true : false;
+        };
+
+        /**
+         * Returns the drag and drop instances that are in all groups the
+         * passed in instance belongs to.
+         *
+         * @param {ygDragDrop} p_oDD the obj to get related data for
+         * @param {boolean} bTargetsOnly if true, only return targetable objs
+         * @return {ygDragDrop[]} the related instances
+         */
+        this.getRelated = function(p_oDD, bTargetsOnly) {
+            var oDDs = [];
+            for (var i in p_oDD.groups) {
+                for (j in this.ids[i]) {
+                    var dd = this.ids[i][j];
+                    if (! this.isTypeOfDD(dd)) {
+                        continue;
+                    }
+                    if (!bTargetsOnly || dd.isTarget) {
+                        oDDs[oDDs.length] = dd;
+                    }
+                }
+            }
+
+            return oDDs;
+        };
+
+        /**
+         * Returns true if the specified dd target is a legal target for
+         * the specifice drag obj
+         *
+         * @param {ygDragDrop} the drag obj
+         * @param {ygDragDrop) the target
+         * @return {boolean} true if the target is a legal target for the
+         * dd obj
+         */
+        this.isLegalTarget = function (oDD, oTargetDD) {
+            var targets = this.getRelated(oDD);
+            for (var i =0;i<targets.length;++i) {
+                if (targets[i].id == oTargetDD.id) {
+                    return true;
+                }
+            }
+
+            return false;
+        };
+
+        /**
+         * My goal is to be able to transparently determine if an object is
+         * typeof ygDragDrop, and the exact subclass of ygDragDrop.  typeof
+         * returns "object", oDD.constructor.toString() always returns
+         * "ygDragDrop" and not the name of the subclass.  So for now it just
+         * evaluates a well-known variable in ygDragDrop.
+         *
+         * @param {Object} the object to evaluate
+         * @return {boolean} true if typeof oDD = ygDragDrop
+         */
+        this.isTypeOfDD = function (oDD) {
+            return (oDD && oDD.__ygDragDrop);
+        };
+
+        /**
+         * Utility function to determine if a given element has been
+         * registered as a drag drop handle for the given Drag Drop object.
+         *
+         * @param {String} id the element id to check
+         * @return {boolean} true if this element is a DragDrop handle, false
+         * otherwise
+         */
+        this.isHandle = function(sDDId, sHandleId) {
+            return ( this.handleIds[sDDId] &&
+                            this.handleIds[sDDId][sHandleId] );
+        };
+
+        /**
+         * Returns the DragDrop instance for a given id
+         *
+         * @param {String} id the id of the DragDrop object
+         * @return {DragDrop} the drag drop object, null if it is not found
+         */
+        this.getDDById = function(id) {
+            for (var i in this.ids) {
+                if (this.ids[i][id]) {
+                    return this.ids[i][id];
+                }
+            }
+            return null;
+        };
+
+        /**
+         * Fired after a registered DragDrop object gets the mousedown event.
+         * Sets up the events required to track the object being dragged
+         *
+         * @param {Event} e the event
+         * @param oDD the DragDrop object being dragged
+         * @private
+         */
+        this.handleMouseDown = function(e, oDD) {
+            this.dragCurrent = oDD;
+
+            var el = oDD.getEl();
+
+            // track start position
+            this.startX = UTIL.Event.getPageX(e);
+            this.startY = UTIL.Event.getPageY(e);
+
+            this.deltaX = this.startX - el.offsetLeft;
+            this.deltaY = this.startY - el.offsetTop;
+
+            this.dragThreshMet = false;
+
+            this.clickTimeout = setTimeout(
+               "var DDM=YAHOO.util.DDM;DDM.startDrag(DDM.startX, DDM.startY)",
+               this.clickTimeThresh );
+        };
+
+        /**
+         * Fired when either the drag pixel threshol or the mousedown hold
+         * time threshold has been met.
+         *
+         * @param x {int} the X position of the original mousedown
+         * @param y {int} the Y position of the original mousedown
+         */
+        this.startDrag = function(x, y) {
+            clearTimeout(this.clickTimeout);
+            if (this.dragCurrent) {
+                this.dragCurrent.b4StartDrag(x, y);
+                this.dragCurrent.startDrag(x, y);
+            }
+            this.dragThreshMet = true;
+        };
+
+        /**
+         * Internal function to handle the mouseup event.  Will be invoked
+         * from the context of the document.
+         *
+         * @param {Event} e the event
+         * @private
+         */
+        this.handleMouseUp = function(e) {
+
+            if (! this.dragCurrent) {
+                return;
+            }
+
+            clearTimeout(this.clickTimeout);
+
+            if (this.dragThreshMet) {
+                this.fireEvents(e, true);
+            } else {
+            }
+
+            this.stopDrag(e);
+
+            this.stopEvent(e);
+        };
+
+        /**
+         * Utility to stop event propagation and event default, if these
+         * features are turned on.
+         *
+         * @param {Event} e the event as returned by this.getEvent()
+         */
+        this.stopEvent = function(e) {
+            if (this.stopPropagation) {
+                UTIL.Event.stopPropagation(e);
+            }
+
+            if (this.preventDefault) {
+                UTIL.Event.preventDefault(e);
+            }
+        };
+
+        /**
+         * Internal function to clean up event handlers after the drag
+         * operation is complete
+         *
+         * @param {Event} e the event
+         * @private
+         */
+        this.stopDrag = function(e) {
+
+            // Fire the drag end event for the item that was dragged
+            if (this.dragCurrent) {
+                if (this.dragThreshMet) {
+                    this.dragCurrent.b4EndDrag(e);
+                    this.dragCurrent.endDrag(e);
+                }
+
+                this.dragCurrent.onMouseUp(e);
+            }
+
+            this.dragCurrent = null;
+            this.dragOvers = {};
+        };
+
+        /**
+         * Internal function to handle the mousemove event.  Will be invoked
+         * from the context of the html element.
+         *
+         * @TODO figure out what we can do about mouse events lost when the
+         * user drags objects beyond the window boundary.  Currently we can
+         * detect this in internet explorer by verifying that the mouse is
+         * down during the mousemove event.  Firefox doesn't give us the
+         * button state on the mousemove event.
+         *
+         * @param {Event} e the event
+         * @private
+         */
+        this.handleMouseMove = function(e) {
+            if (! this.dragCurrent) {
+                return;
+            }
+
+            // var button = e.which || e.button;
+
+
+            // check for IE mouseup outside of page boundary
+            if (UTIL.Event.isIE && !e.button) {
+                this.stopEvent(e);
+                return this.handleMouseUp(e);
+            }
+
+            if (!this.dragThreshMet) {
+                var diffX = Math.abs(this.startX - UTIL.Event.getPageX(e));
+                var diffY = Math.abs(this.startY - UTIL.Event.getPageY(e));
+                if (diffX > this.clickPixelThresh ||
+                            diffY > this.clickPixelThresh) {
+                    this.startDrag(this.startX, this.startY);
+                }
+            }
+
+            if (this.dragThreshMet) {
+                this.dragCurrent.b4Drag(e);
+                this.dragCurrent.onDrag(e);
+                this.fireEvents(e, false);
+            }
+
+            this.stopEvent(e);
+        };
+
+        /**
+         * Iterates over all of the DragDrop elements to find ones we are
+         * hovering over or dropping on
+         *
+         * @param {Event} e the event
+         * @param {boolean} isDrop is this a drop op or a mouseover op?
+         * @private
+         */
+        this.fireEvents = function(e, isDrop) {
+            var dc = this.dragCurrent;
+
+            // If the user did the mouse up outside of the window, we could
+            // get here even though we have ended the drag.
+            if (!dc || dc.isLocked()) {
+                return;
+            }
+
+            var x = UTIL.Event.getPageX(e);
+            var y = UTIL.Event.getPageY(e);
+            var pt = new YAHOO.util.Point(x,y);
+
+            // cache the previous dragOver array
+            var oldOvers = [];
+
+            var outEvts   = [];
+            var overEvts  = [];
+            var dropEvts  = [];
+            var enterEvts = [];
+
+            // Check to see if the object we were hovering over is no longer
+            // being hovered over so we can fire the onDragOut event
+            for (var i in this.dragOvers) {
+
+                var ddo = this.dragOvers[i];
+
+                if (! this.isTypeOfDD(ddo)) {
+                    continue;
+                }
+
+                if (! this.isOverTarget(pt, ddo, this.mode)) {
+                    outEvts.push( ddo );
+                }
+
+                oldOvers[i] = true;
+                delete this.dragOvers[i];
+            }
+
+            for (var sGroup in dc.groups) {
+
+                if ("string" != typeof sGroup) {
+                    continue;
+                }
+
+                for (i in this.ids[sGroup]) {
+                    var oDD = this.ids[sGroup][i];
+                    if (! this.isTypeOfDD(oDD)) {
+                        continue;
+                    }
+
+                    if (oDD.isTarget && !oDD.isLocked() && oDD != dc) {
+                        if (this.isOverTarget(pt, oDD, this.mode)) {
+                            // look for drop interactions
+                            if (isDrop) {
+                                dropEvts.push( oDD );
+                            // look for drag enter and drag over interactions
+                            } else {
+
+                                // initial drag over: dragEnter fires
+                                if (!oldOvers[oDD.id]) {
+                                    enterEvts.push( oDD );
+                                // subsequent drag overs: dragOver fires
+                                } else {
+                                    overEvts.push( oDD );
+                                }
+
+                                this.dragOvers[oDD.id] = oDD;
+                            }
+                        }
+                    }
+                }
+            }
+
+            if (this.mode) {
+                if (outEvts.length > 0) {
+                    dc.b4DragOut(e, outEvts);
+                    dc.onDragOut(e, outEvts);
+                }
+
+                if (enterEvts.length > 0) {
+                    dc.onDragEnter(e, enterEvts);
+                }
+
+                if (overEvts.length > 0) {
+                    dc.b4DragOver(e, overEvts);
+                    dc.onDragOver(e, overEvts);
+                }
+
+                if (dropEvts.length > 0) {
+                    dc.b4DragDrop(e, dropEvts);
+                    dc.onDragDrop(e, dropEvts);
+                }
+
+            } else {
+                // fire dragout events
+                for (i=0; i < outEvts.length; ++i) {
+                    dc.b4DragOut(e, outEvts[i].id);
+                    dc.onDragOut(e, outEvts[i].id);
+                }
+
+                // fire enter events
+                for (i=0; i < enterEvts.length; ++i) {
+                    // dc.b4DragEnter(e, oDD.id);
+                    dc.onDragEnter(e, enterEvts[i].id);
+                }
+
+                // fire over events
+                for (i=0; i < overEvts.length; ++i) {
+                    dc.b4DragOver(e, overEvts[i].id);
+                    dc.onDragOver(e, overEvts[i].id);
+                }
+
+                // fire drop events
+                for (i=0; i < dropEvts.length; ++i) {
+                    dc.b4DragDrop(e, dropEvts[i].id);
+                    dc.onDragDrop(e, dropEvts[i].id);
+                }
+
+            }
+
+        };
+
+        /**
+         * Helper function for getting the best match from the list of drag
+         * and drop objects returned by the drag and drop events when we are
+         * in INTERSECT mode.  It returns either the first object that the
+         * cursor is over, or the object that has the greatest overlap with
+         * the dragged element.
+         *
+         * @param  {ygDragDrop[]} dds The array of drag and drop objects
+         * targeted
+         * @return {ygDragDrop}       The best single match
+         */
+        this.getBestMatch = function(dds) {
+            var winner = null;
+            // Return null if the input is not what we expect
+            //if (!dds || !dds.length || dds.length == 0) {
+               // winner = null;
+            // If there is only one item, it wins
+            //} else if (dds.length == 1) {
+
+            if (dds.length == 1) {
+                winner = dds[0];
+            } else {
+                // Loop through the targeted items
+                for (var i=0; i<dds.length; ++i) {
+                    var dd = dds[i];
+                    // If the cursor is over the object, it wins.  If the
+                    // cursor is over multiple matches, the first one we come
+                    // to wins.
+                    if (dd.cursorIsOver) {
+                        winner = dd;
+                        break;
+                    // Otherwise the object with the most overlap wins
+                    } else {
+                        if (!winner ||
+                            winner.overlap.getArea() < dd.overlap.getArea()) {
+                            winner = dd;
+                        }
+                    }
+                }
+            }
+
+            return winner;
+        };
+
+        /**
+         * Refreshes the cache of the top-left and bottom-right points of the
+         * drag and drop objects in the specified groups
+         *
+         * @param {Array} aGroups an associative array of groups to refresh
+         */
+        this.refreshCache = function(aGroups) {
+            for (sGroup in aGroups) {
+                if ("string" != typeof sGroup) {
+                    continue;
+                }
+                for (i in this.ids[sGroup]) {
+                    var oDD = this.ids[sGroup][i];
+
+                    if (this.isTypeOfDD(oDD)) {
+                        var loc = this.getLocation(oDD);
+                        if (loc) {
+                            this.locationCache[oDD.id] = loc;
+                        } else {
+                            delete this.locationCache[oDD.id];
+                            // this will unregister the drag and drop object if
+                            // the element is not in a usable state
+                            oDD.unreg();
+                        }
+                    }
+                }
+            }
+        };
+
+        /**
+         * This checks to make sure an element exists and is in the DOM.  The
+         * main purpose is to handle cases where innerHTML is used to remove
+         * drag and drop objects from the DOM.  IE provides an 'unspecified
+         * error' when trying to access the offsetParent of such an element
+         * @param {HTMLElement} el the element to check
+         * @return {boolean} true if the element looks usable
+         */
+        this.verifyEl = function(el) {
+            try {
+                if (el) {
+                    var parent = el.offsetParent;
+                    if (parent) {
+                        return true;
+                    }
+                }
+            } catch(e) {
+            }
+
+            return false;
+        };
+
+        /**
+         * Returns the an array containing the drag and drop element's position
+         * and size, including the ygDragDrop.padding configured for it
+         *
+         * @param {ygDragDrop} oDD the drag and drop object to get the
+         * location for
+         * @return array containing the top left and bottom right points of the
+         * element
+         */
+        this.getLocation = function(oDD) {
+            if (! this.isTypeOfDD(oDD)) {
+                return null;
+            }
+
+            var el = oDD.getEl();
+
+            if (!this.verifyEl(el)) {
+                return null;
+            }
+
+
+            // var aPos = ygPos.getPos(el);
+            var aPos = YAHOO.util.Dom.getXY(el);
+
+            x1 = aPos[0];
+            x2 = x1 + el.offsetWidth;
+
+            y1 = aPos[1];
+            y2 = y1 + el.offsetHeight;
+
+            var t = y1 - oDD.padding[0];
+            var r = x2 + oDD.padding[1];
+            var b = y2 + oDD.padding[2];
+            var l = x1 - oDD.padding[3];
+
+            return new YAHOO.util.Region( t, r, b, l );
+
+        };
+
+        /**
+         * Checks the cursor location to see if it over the target
+         *
+         * @param {YAHOO.util.Point} pt The point to evaluate
+         * @param {ygDragDrop} oDDTarget the DragDrop object we are inspecting
+         * @return {boolean} true if the mouse is over the target
+         * @private
+         */
+        this.isOverTarget = function(pt, oDDTarget, intersect) {
+            // use cache if available
+            var loc = this.locationCache[oDDTarget.id];
+            if (!loc || !this.useCache) {
+                loc = this.getLocation(oDDTarget);
+                this.locationCache[oDDTarget.id] = loc;
+
+            }
+
+
+            // var cursorIsOver =  (x >= loc[3] && x <= loc[1] && y >= loc[0] && y <= loc[2]);
+            //oDDTarget.cursorIsOver = loc.contains( new YAHOO.util.Point(x, y) );
+            oDDTarget.cursorIsOver = loc.contains( pt );
+            oDDTarget.overlap = null;
+
+            // if (this.INTERSECT == this.mode) {
+            if (intersect) {
+
+                var curRegion =
+                    YAHOO.util.Region.getRegion(this.dragCurrent.getDragEl());
+                var overlap = curRegion.intersect(loc);
+
+                if (overlap) {
+                    oDDTarget.overlap = overlap;
+                    return true;
+                } else {
+                    return false;
+                }
+
+            } else {
+                return oDDTarget.cursorIsOver;
+            }
+        };
+
+        /**
+         * @private
+         */
+        this._onUnload = function(e, me) {
+            this.unregAll();
+        };
+
+        /**
+         * Cleans up the drag and drop events and objects.
+         *
+         * @private
+         */
+        this.unregAll = function() {
+
+            if (this.dragCurrent) {
+                this.stopDrag();
+                this.dragCurrent = null;
+            }
+
+            this._execOnAll("unreg", []);
+
+            for (i in this.elementCache) {
+                delete this.elementCache[i];
+            }
+
+            this.elementCache = {};
+            this.ids = {};
+        };
+
+        /**
+         * A cache of DOM elements
+         *
+         * @private
+         */
+        this.elementCache = {};
+
+        /**
+         * Get the wrapper for the DOM element specified
+         *
+         * @param {String} id the id of the elment to get
+         * @return {YAHOO.util.DDM.ElementWrapper} the wrapped element
+         * @private
+         */
+        this.getElWrapper = function(id) {
+            var oWrapper = this.elementCache[id];
+            if (!oWrapper || !oWrapper.el) {
+                oWrapper = this.elementCache[id] =
+                    new this.ElementWrapper(document.getElementById(id));
+            }
+            return oWrapper;
+        };
+
+        /**
+         * Returns the actual DOM element
+         *
+         * @param {String} id the id of the elment to get
+         * @return {Object} The element
+         */
+        this.getElement = function(id) {
+            // return this.getElWrapper(id).el;
+            return document.getElementById(id);
+        };
+
+        /**
+         * Returns the style property for the DOM element (i.e.,
+         * document.getElById(id).style)
+         *
+         * @param {String} id the id of the elment to get
+         * @return {Object} The style property of the element
+         */
+        this.getCss = function(id) {
+            // return this.getElWrapper(id).css;
+            var css = null;
+            var el = document.getElementById(id);
+            if (el) {
+                css = el.style;
+            }
+
+            return css;
+        };
+
+        /**
+         * Inner class for cached elements
+         */
+        this.ElementWrapper = function(el) {
+                /**
+                 * @private
+                 */
+                this.el = el || null;
+                /**
+                 * @private
+                 */
+                this.id = this.el && el.id;
+                /**
+                 * @private
+                 */
+                this.css = this.el && el.style;
+            };
+
+        /**
+         * Returns the X position of an html element
+         * @param el the element for which to get the position
+         * @return {int} the X coordinate
+         */
+        this.getPosX = function(el) {
+            return YAHOO.util.Dom.getX(el);
+        };
+
+        /**
+         * Returns the Y position of an html element
+         * @param el the element for which to get the position
+         * @return {int} the Y coordinate
+         */
+        this.getPosY = function(el) {
+            return YAHOO.util.Dom.getY(el);
+        };
+
+        /**
+         * Swap two nodes.  In IE, we use the native method, for others we
+         * emulate the IE behavior
+         *
+         * @param n1 the first node to swap
+         * @param n2 the other node to swap
+         */
+        this.swapNode = function(n1, n2) {
+            if (n1.swapNode) {
+                n1.swapNode(n2);
+            } else {
+                // the node reference order for the swap is a little tricky.
+                var p = n2.parentNode;
+                var s = n2.nextSibling;
+                n1.parentNode.replaceChild(n2,n1);
+                p.insertBefore(n1,s);
+            }
+        };
+
+        /**
+         * @private
+         */
+        this.getScroll = function () {
+            var t, l;
+            if (document.documentElement && document.documentElement.scrollTop) {
+                t = document.documentElement.scrollTop;
+                l = document.documentElement.scrollLeft;
+            } else if (document.body) {
+                t = document.body.scrollTop;
+                l = document.body.scrollLeft;
+            }
+            return { top: t, left: l };
+        };
+
+        /**
+         * Returns the specified element style property
+         * @param {HTMLElement} el          the element
+         * @param {string}      styleProp   the style property
+         * @return {string}     The value of the style property
+         */
+        this.getStyle = function(el, styleProp) {
+            if (el.style.styleProp) {
+                return el.style.styleProp;
+            } else if (el.currentStyle) {
+                return el.currentStyle[styleProp];
+            } else if (document.defaultView) {
+                return document.defaultView.getComputedStyle(el, null).
+                    getPropertyValue(styleProp);
+            }
+        };
+
+        /**
+         * Gets the scrollTop
+         *
+         * @return {int} the document's scrollTop
+         */
+        this.getScrollTop = function () { return this.getScroll().top; };
+
+        /**
+         * Gets the scrollLeft
+         *
+         * @return {int} the document's scrollTop
+         */
+        this.getScrollLeft = function () { return this.getScroll().left; };
+
+        this.moveToEl = function (moveEl, targetEl) {
+            var aCoord = YAHOO.util.Dom.getXY(targetEl);
+            YAHOO.util.Dom.setXY(moveEl, aCoord);
+        };
+
+        /**
+         * Gets the client height
+         *
+         * @return {int} client height in px
+         */
+        this.getClientHeight = function() {
+            return (window.innerHeight) ? window.innerHeight :
+                (document.documentElement && document.documentElement.clientHeight) ?
+                document.documentElement.clientHeight : document.body.offsetHeight;
+        };
+
+        /**
+         * Gets the client width
+         *
+         * @return {int} client width in px
+         */
+        this.getClientWidth = function() {
+            return (window.innerWidth) ? window.innerWidth :
+                (document.documentElement && document.documentElement.clientWidth) ?
+                document.documentElement.clientWidth : document.body.offsetWidth;
+        };
+
+        /**
+         * numeric array sort function
+         */
+        this.numericSort = function(a, b) { return (a - b); };
+
+        /**
+         * @private
+         */
+        this._timeoutCount = 0;
+
+        /**
+         * @private
+         * Trying to make the load order less important.  Without this we get
+         * an error if this file is loaded before the Event Utility.
+         */
+        this._addListeners = function() {
+            if ( UTIL.Event &&
+                 document          &&
+                 document.body        ) {
+
+                this._onLoad();
+            } else {
+                if (this._timeoutCount > 500) {
+                } else {
+                    setTimeout("YAHOO.util.DDM._addListeners()", 10);
+                    this._timeoutCount += 1;
+                }
+            }
+
+        };
+
+        /**
+         * Recursively searches the immediate parent and all child nodes for
+         * the handle element in order to determine wheter or not it was
+         * clicked.
+         *
+         * @param node the html element to inspect
+         */
+        this.handleWasClicked = function(node, id) {
+            if (this.isHandle(id, node.id)) {
+                return true;
+            } else {
+                // check to see if this is a text node child of the one we want
+                var p = node.parentNode;
+
+                while (p) {
+                    if (this.isHandle(id, p.id)) {
+                        return true;
+                    } else {
+                        p = p.parentNode;
+                    }
+                }
+            }
+
+            return false;
+        };
+
+    };
+
+    // shorter alias, save a few bytes
+    YAHOO.util.DDM = YAHOO.util.DragDropMgr;
+    YAHOO.util.DDM._addListeners();
+
+}
+
+/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
+
+/**
+ * @class a DragDrop implementation where the linked element follows the
+ * mouse cursor.
+ *
+ * @extends DragDrop
+ * @constructor
+ * @param {String} id the id of the linked element
+ * @param {String} sGroup the group of related DragDrop items
+ */
+YAHOO.util.DD = function(id, sGroup) {
+    if (id) {
+        this.init(id, sGroup);
+    }
+};
+
+YAHOO.util.DD.prototype = new YAHOO.util.DragDrop();
+
+/**
+ * Should we auto-scroll? Defaults to true
+ *
+ * @type boolean
+ */
+YAHOO.util.DD.prototype.scroll = true;
+
+/**
+ * Sets the pointer offset to the distance between the linked element's top
+ * left corner and the location the element was clicked
+ *
+ * @param {int} iPageX the X coordinate of the click
+ * @param {int} iPageY the Y coordinate of the click
+ */
+YAHOO.util.DD.prototype.autoOffset = function(iPageX, iPageY) {
+    var el = this.getEl();
+    var aCoord = YAHOO.util.Dom.getXY(el);
+    var x = iPageX - aCoord[0];
+    var y = iPageY - aCoord[1];
+    this.setDelta(x, y);
+};
+
+/**
+ * Sets the pointer offset.  You can call this directly to force the offset to
+ * be in a particular location (e.g., pass in 0,0 to set it to the center of the
+ * object, as done in ygDDSliderBG)
+ *
+ * @param {int} iDeltaX the distance from the left
+ * @param {int} iDeltaY the distance from the top
+ */
+YAHOO.util.DD.prototype.setDelta = function(iDeltaX, iDeltaY) {
+    this.deltaX = iDeltaX;
+    this.deltaY = iDeltaY;
+};
+
+/**
+ * Sets the drag element to the location of the mousedown or click event,
+ * maintaining the cursor location relative to the location on the element
+ * that was clicked.  Override this if you want to place the element in a
+ * location other than where the cursor is.
+ *
+ * @param {int} iPageX the X coordinate of the mousedown or drag event
+ * @param {int} iPageY the Y coordinate of the mousedown or drag event
+ */
+
+YAHOO.util.DD.prototype.setDragElPos = function(iPageX, iPageY) {
+    this.alignElWithMouse(this.getDragEl(), iPageX, iPageY);
+};
+
+/**
+ * Sets the element to the location of the mousedown or click event,
+ * maintaining the cursor location relative to the location on the element
+ * that was clicked.  Override this if you want to place the element in a
+ * location other than where the cursor is.
+ *
+ * @param {HTMLElement} el the element to move
+ * @param {int} iPageX the X coordinate of the mousedown or drag event
+ * @param {int} iPageY the Y coordinate of the mousedown or drag event
+ */
+YAHOO.util.DD.prototype.alignElWithMouse = function(el, iPageX, iPageY) {
+    var oCoord = this.getTargetCoord(iPageX, iPageY);
+    var aCoord = [oCoord.x, oCoord.y];
+    YAHOO.util.Dom.setXY(el, aCoord);
+
+    this.cachePosition(oCoord.x, oCoord.y);
+
+    this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
+};
+
+/**
+ * Saves the most recent position so that we can reset the constraints and
+ * tick marks on-demand.  We need to know this so that we can calculate the
+ * number of pixels the element is offset from its original position.
+ */
+YAHOO.util.DD.prototype.cachePosition = function(iPageX, iPageY) {
+    if (iPageX) {
+        this.lastPageX = iPageX;
+        this.lastPageY = iPageY;
+    } else {
+        var aCoord = YAHOO.util.Dom.getXY(this.getEl());
+        this.lastPageX = aCoord[0];
+        this.lastPageY = aCoord[1];
+    }
+};
+
+/**
+ * Auto-scroll the window if the dragged object has been moved beyond the
+ * visible window boundary.
+ *
+ * @param {int} x the drag element's x position
+ * @param {int} y the drag element's y position
+ * @param {int} h the height of the drag element
+ * @param {int} w the width of the drag element
+ * @private
+ */
+YAHOO.util.DD.prototype.autoScroll = function(x, y, h, w) {
+
+    if (this.scroll) {
+        // The client height
+        var clientH = this.DDM.getClientHeight();
+
+        // The client width
+        var clientW = this.DDM.getClientWidth();
+
+        // The amt scrolled down
+        var st = this.DDM.getScrollTop();
+
+        // The amt scrolled right
+        var sl = this.DDM.getScrollLeft();
+
+        // Location of the bottom of the element
+        var bot = h + y;
+
+        // Location of the right of the element
+        var right = w + x;
+
+        // The distance from the cursor to the bottom of the visible area,
+        // adjusted so that we don't scroll if the cursor is beyond the
+        // element drag constraints
+        var toBot = (clientH + st - y - this.deltaY);
+
+        // The distance from the cursor to the right of the visible area
+        var toRight = (clientW + sl - x - this.deltaX);
+
+
+        // How close to the edge the cursor must be before we scroll
+        // var thresh = (document.all) ? 100 : 40;
+        var thresh = 40;
+
+        // How many pixels to scroll per autoscroll op.  This helps to reduce
+        // clunky scrolling. IE is more sensitive about this ... it needs this
+        // value to be higher.
+        var scrAmt = (document.all) ? 80 : 30;
+
+        // Scroll down if we are near the bottom of the visible page and the
+        // obj extends below the crease
+        if ( bot > clientH && toBot < thresh ) {
+            window.scrollTo(sl, st + scrAmt);
+        }
+
+        // Scroll up if the window is scrolled down and the top of the object
+        // goes above the top border
+        if ( y < st && st > 0 && y - st < thresh ) {
+            window.scrollTo(sl, st - scrAmt);
+        }
+
+        // Scroll right if the obj is beyond the right border and the cursor is
+        // near the border.
+        if ( right > clientW && toRight < thresh ) {
+            window.scrollTo(sl + scrAmt, st);
+        }
+
+        // Scroll left if the window has been scrolled to the right and the obj
+        // extends past the left border
+        if ( x < sl && sl > 0 && x - sl < thresh ) {
+            window.scrollTo(sl - scrAmt, st);
+        }
+    }
+};
+
+/**
+ * Finds the location the element should be placed if we want to move
+ * it to where the mouse location less the click offset would place us.
+ *
+ * @param {int} iPageX the X coordinate of the click
+ * @param {int} iPageY the Y coordinate of the click
+ * @return an object that contains the coordinates (Object.x and Object.y)
+ * @private
+ */
+YAHOO.util.DD.prototype.getTargetCoord = function(iPageX, iPageY) {
+
+
+    var x = iPageX - this.deltaX;
+    var y = iPageY - this.deltaY;
+
+    if (this.constrainX) {
+        if (x < this.minX) { x = this.minX; }
+        if (x > this.maxX) { x = this.maxX; }
+    }
+
+    if (this.constrainY) {
+        if (y < this.minY) { y = this.minY; }
+        if (y > this.maxY) { y = this.maxY; }
+    }
+
+    x = this.getTick(x, this.xTicks);
+    y = this.getTick(y, this.yTicks);
+
+
+    return {x:x, y:y};
+};
+
+// overrides YAHOO.util.DragDrop
+YAHOO.util.DD.prototype.b4MouseDown = function(e) {
+    // this.resetConstraints();
+    this.autoOffset(YAHOO.util.Event.getPageX(e),
+                        YAHOO.util.Event.getPageY(e));
+};
+
+// overrides YAHOO.util.DragDrop
+YAHOO.util.DD.prototype.b4Drag = function(e) {
+    this.setDragElPos(YAHOO.util.Event.getPageX(e),
+                        YAHOO.util.Event.getPageY(e));
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Debugging ygDragDrop events that can be overridden
+///////////////////////////////////////////////////////////////////////////////
+/*
+YAHOO.util.DD.prototype.startDrag = function(x, y) {
+};
+
+YAHOO.util.DD.prototype.onDrag = function(e) {
+};
+
+YAHOO.util.DD.prototype.onDragEnter = function(e, id) {
+};
+
+YAHOO.util.DD.prototype.onDragOver = function(e, id) {
+};
+
+YAHOO.util.DD.prototype.onDragOut = function(e, id) {
+};
+
+YAHOO.util.DD.prototype.onDragDrop = function(e, id) {
+};
+
+YAHOO.util.DD.prototype.endDrag = function(e) {
+};
+*/
+
+/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
+
+/**
+ * @class a DragDrop implementation that inserts an empty, bordered div into
+ * the document that follows the cursor during drag operations.  At the time of
+ * the click, the frame div is resized to the dimensions of the linked html
+ * element, and moved to the exact location of the linked element.
+ *
+ * @extends YAHOO.util.DD
+ * @constructor
+ * @param {String} id the id of the linked html element
+ * @param {String} sGroup the group of related DragDrop objects
+ */
+YAHOO.util.DDProxy = function(id, sGroup) {
+    if (id) {
+        this.init(id, sGroup);
+        this.initFrame();
+    }
+};
+
+YAHOO.util.DDProxy.prototype = new YAHOO.util.DD();
+
+/**
+ * A reference to the one div element we create for all instances of this class
+ *
+ * @type Object
+ */
+YAHOO.util.DDProxy.frameDiv = null;
+
+/**
+ * the drag frame div id
+ *
+ * @type String
+ */
+YAHOO.util.DDProxy.dragElId = "ygddfdiv";
+
+/**
+ * The border width of the frame.  This is used when we resize the frame to
+ * the size of the linked element.  We substract the border width to make
+ * the div the correct size.
+ *
+ * @TODO find a better way to handle this
+ *
+ * @type int
+ */
+YAHOO.util.DDProxy.prototype.borderWidth = 2;
+
+/**
+ * By default we resize the drag frame to be the same size as the element
+ * we want to drag (this is to get the frame effect).  We can turn it off
+ * if we want a different behavior (ex: ygDDMy2)
+ *
+ * @type boolean
+ */
+YAHOO.util.DDProxy.prototype.resizeFrame = true;
+
+/**
+ * By default the frame is positioned exactly where the drag element is, so
+ * we use the cursor offset provided by YAHOO.util.DD.  Another option that works only if
+ * you do not have constraints on the obj is to have the drag frame centered
+ * around the cursor.  Set centerFrame to true for this effect.  Ex:
+ * ygDDMy2
+ *
+ * @type boolean
+ */
+YAHOO.util.DDProxy.prototype.centerFrame = false;
+
+/**
+ * Create the drag frame if needed
+ */
+YAHOO.util.DDProxy.createFrame = function() {
+    var THIS = YAHOO.util.DDProxy;
+
+    if (!document || !document.body) {
+        setTimeout(THIS.createFrame, 50);
+        return;
+    }
+
+    if (!THIS.frameDiv) {
+        THIS.frameDiv = document.createElement("div");
+        THIS.frameDiv.id = THIS.dragElId;
+        var s = THIS.frameDiv.style;
+        s.position = "absolute";
+        s.visibility = "hidden";
+        s.cursor = "move";
+        s.border = "2px solid #aaa";
+        s.zIndex = 999;
+
+        document.body.appendChild(THIS.frameDiv);
+    }
+};
+
+/**
+ * Initialization for the drag frame element.  Must be called in the
+ * constructor of all subclasses
+ */
+YAHOO.util.DDProxy.prototype.initFrame = function() {
+    YAHOO.util.DDProxy.createFrame();
+    this.setDragElId(YAHOO.util.DDProxy.dragElId);
+    this.useAbsMath = true;
+};
+
+/**
+ * Resizes the drag frame to the dimensions of the clicked object, positions
+ * it over the object, and finally displays it
+ *
+ * @param {int} iPageX X click position
+ * @param {int} iPageY Y click position
+ * @private
+ */
+YAHOO.util.DDProxy.prototype.showFrame = function(iPageX, iPageY) {
+    var el = this.getEl();
+
+    var s = this.getDragEl().style;
+
+    if (this.resizeFrame) {
+        s.width = (parseInt(el.offsetWidth) - (2*this.borderWidth)) + "px";
+        s.height = (parseInt(el.offsetHeight) - (2*this.borderWidth)) + "px";
+    }
+
+    if (this.centerFrame) {
+        this.setDelta(Math.round(parseInt(s.width)/2),
+                Math.round(parseInt(s.width)/2));
+    }
+
+    this.setDragElPos(iPageX, iPageY);
+
+    s.visibility = "";
+};
+
+// overrides YAHOO.util.DragDrop
+YAHOO.util.DDProxy.prototype.b4MouseDown = function(e) {
+    var x = YAHOO.util.Event.getPageX(e);
+    var y = YAHOO.util.Event.getPageY(e);
+    this.autoOffset(x, y);
+    this.setDragElPos(x, y);
+};
+
+// overrides YAHOO.util.DragDrop
+YAHOO.util.DDProxy.prototype.b4StartDrag = function(x, y) {
+    // show the drag frame
+    this.showFrame(x, y);
+};
+
+// overrides YAHOO.util.DragDrop
+YAHOO.util.DDProxy.prototype.b4EndDrag = function(e) {
+
+    // hide the drag frame
+    var s = this.getDragEl().style;
+    s.visibility = "hidden";
+};
+
+// overrides YAHOO.util.DragDrop
+// By default we try to move the element to the last location of the frame.
+// This is so that the default behavior mirrors that of YAHOO.util.DD.
+YAHOO.util.DDProxy.prototype.endDrag = function(e) {
+    var lel = this.getEl();
+    var del = this.getDragEl();
+
+    // Show the drag frame briefly so we can get its position
+    del.style.visibility = "";
+
+    // Hide the linked element before the move to get around a Safari
+    // rendering bug.
+    lel.style.visibility = "hidden";
+    YAHOO.util.DDM.moveToEl(lel, del);
+    del.style.visibility = "hidden";
+    lel.style.visibility = "";
+};
+
+/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
+
+/**
+ * @class a DragDrop implementation that does not move, but can be a drop
+ * target.  You would get the same result by simply omitting implementation
+ * for the event callbacks, but this way we reduce the processing cost of the
+ * event listener and the callbacks.
+ *
+ * @extends YAHOO.util.DragDrop
+ * @constructor
+ * @param {String} id the id of the element that is a drop target
+ * @param {String} sGroup the group of related DragDrop objects
+ */
+
+YAHOO.util.DDTarget = function(id, sGroup) {
+    if (id) {
+        this.initTarget(id, sGroup);
+    }
+};
+
+YAHOO.util.DDTarget.prototype = new YAHOO.util.DragDrop();
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/event.js
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/event.js	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/event.js	(revision 13928)
@@ -0,0 +1,901 @@
+/*
+Copyright (c) 2006 Yahoo! Inc. All rights reserved.
+version 0.9.0
+*/
+
+/**
+ * @class The CustomEvent class lets you define events for your application
+ * that can be subscribed to by one or more independent component.
+ * @param {String} type The type of event, which is passed to the callback
+ *                 when the event fires
+ * @param {Object} oScope The context the event will fire from.  "this" will
+ *                 refer to this object in the callback.  Default value:
+ *                 the window object.  The listener can override this.
+ * @constructor
+ */
+YAHOO.util.CustomEvent = function(type, oScope) {
+    /**
+     * The type of event, returned to subscribers when the event fires
+     * @type string
+     */
+    this.type = type;
+
+    /**
+     * The scope the the event will fire from.  Defaults to the window obj
+     * @type object
+     */
+    this.scope = oScope || window;
+
+    /**
+     * The subscribers to this event
+     * @type array
+     */
+    this.subscribers = [];
+
+    // Register with the event utility for automatic cleanup.  Made optional
+    // so that CustomEvent can be used independently of pe.event
+    if (YAHOO.util["Event"]) {
+        YAHOO.util.Event.regCE(this);
+    }
+};
+
+YAHOO.util.CustomEvent.prototype = {
+    /**
+     * Subscribes the caller to this event
+     * @param {Function} fn       The function to execute
+     * @param {Object}   obj      An object to be passed along when the event fires
+     * @param {boolean}  bOverride If true, the obj passed in becomes the execution
+     *                            scope of the listener
+     */
+    subscribe: function(fn, obj, bOverride) {
+        this.subscribers.push( new YAHOO.util.Subscriber(fn, obj, bOverride) );
+    },
+
+    /**
+     * Unsubscribes the caller from this event
+     * @param {Function} fn  The function to execute
+     * @param {Object}   obj An object to be passed along when the event fires
+     * @return {boolean} True if the subscriber was found and detached.
+     */
+    unsubscribe: function(fn, obj) {
+        var found = false;
+        for (var i=0; i<this.subscribers.length; ++i) {
+            var s = this.subscribers[i];
+            if (s && s.contains(fn, obj)) {
+                this._delete(i);
+                found = true;
+            }
+        }
+
+        return found;
+    },
+
+    /**
+     * Notifies the subscribers.  The callback functions will be executed
+     * from the scope specified when the event was created, and with the following
+     * parameters:
+     *   <pre>
+     *   - The type of event
+     *   - All of the arguments fire() was executed with as an array
+     *   - The custom object (if any) that was passed into the subscribe() method
+     *   </pre>
+     *
+     * @param {Array} an arbitrary set of parameters to pass to the handler
+     */
+    fire: function() {
+        for (var i=0; i<this.subscribers.length; ++i) {
+            var s = this.subscribers[i];
+            if (s) {
+                var scope = (s.override) ? s.obj : this.scope;
+                s.fn.call(scope, this.type, arguments, s.obj);
+            }
+        }
+    },
+
+    /**
+     * Removes all listeners
+     */
+    unsubscribeAll: function() {
+        for (var i=0; i<this.subscribers.length; ++i) {
+            this._delete(i);
+        }
+    },
+
+    /**
+     * @private
+     */
+    _delete: function(index) {
+        var s = this.subscribers[index];
+        if (s) {
+            delete s.fn;
+            delete s.obj;
+        }
+
+        delete this.subscribers[index];
+    }
+};
+
+/////////////////////////////////////////////////////////////////////
+
+/**
+ * @class
+ * @param {Function} fn       The function to execute
+ * @param {Object}   obj      An object to be passed along when the event fires
+ * @param {boolean}  bOverride If true, the obj passed in becomes the execution
+ *                            scope of the listener
+ * @constructor
+ */
+YAHOO.util.Subscriber = function(fn, obj, bOverride) {
+    /**
+     * The callback that will be execute when the event fires
+     * @type function
+     */
+    this.fn = fn;
+
+    /**
+     * An optional custom object that will passed to the callback when
+     * the event fires
+     * @type object
+     */
+    this.obj = obj || null;
+
+    /**
+     * The default execution scope for the event listener is defined when the
+     * event is created (usually the object which contains the event).
+     * By setting override to true, the execution scope becomes the custom
+     * object passed in by the subscriber
+     * @type boolean
+     */
+    this.override = (bOverride);
+};
+
+/**
+ * Returns true if the fn and obj match this objects properties.
+ * Used by the unsubscribe method to match the right subscriber.
+ *
+ * @param {Function} fn the function to execute
+ * @param {Object} obj an object to be passed along when the event fires
+ * @return {boolean} true if the supplied arguments match this
+ *                   subscriber's signature.
+ */
+YAHOO.util.Subscriber.prototype.contains = function(fn, obj) {
+    return (this.fn == fn && this.obj == obj);
+};
+
+/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
+
+// Only load this library once.  If it is loaded a second time, existing
+// events cannot be detached.
+if (!YAHOO.util.Event) {
+
+/**
+ * The event utility provides functions to add and remove event listeners,
+ * event cleansing.  It also tries to automatically remove listeners it
+ * registers during the unload event.
+ * @class
+ * @constructor
+ */
+    YAHOO.util.Event = function() {
+
+        /**
+         * True after the onload event has fired
+         * @type boolean
+         * @private
+         */
+        var loadComplete =  false;
+
+        /**
+         * Cache of wrapped listeners
+         * @type array
+         * @private
+         */
+        var listeners = [];
+
+        /**
+         * Listeners that will be attached during the onload event
+         * @type array
+         * @private
+         */
+        var delayedListeners = [];
+
+        /**
+         * User-defined unload function that will be fired before all events
+         * are detached
+         * @type array
+         * @private
+         */
+        var unloadListeners = [];
+
+        /**
+         * Cache of the custom events that have been defined.  Used for
+         * automatic cleanup
+         * @type array
+         * @private
+         */
+        var customEvents = [];
+
+        /**
+         * Cache of DOM0 event handlers to work around issues with DOM2 events
+         * in Safari
+         * @private
+         */
+        var legacyEvents = [];
+
+        /**
+         * Listener stack for DOM0 events
+         * @private
+         */
+        var legacyHandlers = [];
+
+        return { // PREPROCESS
+
+            /**
+             * Element to bind, int constant
+             * @type int
+             */
+            EL: 0,
+
+            /**
+             * Type of event, int constant
+             * @type int
+             */
+            TYPE: 1,
+
+            /**
+             * Function to execute, int constant
+             * @type int
+             */
+            FN: 2,
+
+            /**
+             * Function wrapped for scope correction and cleanup, int constant
+             * @type int
+             */
+            WFN: 3,
+
+            /**
+             * Object passed in by the user that will be returned as a
+             * parameter to the callback, int constant
+             * @type int
+             */
+            SCOPE: 3,
+
+            /**
+             * Adjusted scope, either the element we are registering the event
+             * on or the custom object passed in by the listener, int constant
+             * @type int
+             */
+            ADJ_SCOPE: 4,
+
+            /**
+             * Safari detection is necessary to work around the preventDefault
+             * bug that makes it so you can't cancel a href click from the
+             * handler.  There is not a capabilities check we can use here.
+             * @private
+             */
+            isSafari: (navigator.userAgent.match(/safari/gi)),
+
+            /**
+             * @private
+             * IE detection needed to properly calculate pageX and pageY.
+             * capabilities checking didn't seem to work because another
+             * browser that does not provide the properties have the values
+             * calculated in a different manner than IE.
+             */
+            isIE: (!this.isSafari && navigator.userAgent.match(/msie/gi)),
+
+            /**
+             * Appends an event handler
+             *
+             * @param {Object}   el        The html element to assign the
+             *                             event to
+             * @param {String}   sType     The type of event to append
+             * @param {Function} fn        The method the event invokes
+             * @param {Object}   oScope    An arbitrary object that will be
+             *                             passed as a parameter to the handler
+             * @param {boolean}  bOverride If true, the obj passed in becomes
+             *                             the execution scope of the listener
+             * @return {boolean} True if the action was successful or defered,
+             *                        false if one or more of the elements
+             *                        could not have the event bound to it.
+             */
+            addListener: function(el, sType, fn, oScope, bOverride) {
+
+                // The el argument can be an array of elements or element ids.
+                if ( this._isValidCollection(el)) {
+                    var ok = true;
+                    for (var i=0; i< el.length; ++i) {
+                        ok = ( this.on(el[i],
+                                       sType,
+                                       fn,
+                                       oScope,
+                                       bOverride) && ok );
+                    }
+                    return ok;
+
+                } else if (typeof el == "string") {
+                    // If the el argument is a string, we assume it is
+                    // actually the id of the element.  If the page is loaded
+                    // we convert el to the actual element, otherwise we
+                    // defer attaching the event until onload event fires
+
+                    // check to see if we need to delay hooking up the event
+                    // until after the page loads.
+                    if (loadComplete) {
+                        el = this.getEl(el);
+                    } else {
+                        // defer adding the event until onload fires
+                        delayedListeners[delayedListeners.length] =
+                            [el, sType, fn, oScope, bOverride];
+
+                        return true;
+                    }
+                }
+
+                // Element should be an html element or an array if we get
+                // here.
+                if (!el) {
+                    return false;
+                }
+
+                // we need to make sure we fire registered unload events
+                // prior to automatically unhooking them.  So we hang on to
+                // these instead of attaching them to the window and fire the
+                // handles explicitly during our one unload event.
+                if ("unload" == sType && oScope !== this) {
+                    unloadListeners[unloadListeners.length] =
+                            [el, sType, fn, oScope, bOverride];
+                    return true;
+                }
+
+
+                // if the user chooses to override the scope, we use the custom
+                // object passed in, otherwise the executing scope will be the
+                // HTML element that the event is registered on
+                var scope = (bOverride) ? oScope : el;
+
+                // wrap the function so we can return the oScope object when
+                // the event fires;
+                var wrappedFn = function(e) {
+                        return fn.call(scope, YAHOO.util.Event.getEvent(e),
+                                oScope);
+                    };
+
+                var li = [el, sType, fn, wrappedFn, scope];
+                var index = listeners.length;
+                // cache the listener so we can try to automatically unload
+                listeners[index] = li;
+
+                if (this.useLegacyEvent(el, sType)) {
+                    var legacyIndex = this.getLegacyIndex(el, sType);
+                    if (legacyIndex == -1) {
+
+                        legacyIndex = legacyEvents.length;
+                        // cache the signature for the DOM0 event, and
+                        // include the existing handler for the event, if any
+                        legacyEvents[legacyIndex] =
+                            [el, sType, el["on" + sType]];
+                        legacyHandlers[legacyIndex] = [];
+
+                        el["on" + sType] =
+                            function(e) {
+                                YAHOO.util.Event.fireLegacyEvent(
+                                    YAHOO.util.Event.getEvent(e), legacyIndex);
+                            };
+                    }
+
+                    // add a reference to the wrapped listener to our custom
+                    // stack of events
+                    legacyHandlers[legacyIndex].push(index);
+
+                // DOM2 Event model
+                } else if (el.addEventListener) {
+                    el.addEventListener(sType, wrappedFn, false);
+                // Internet Explorer abstraction
+                } else if (el.attachEvent) {
+                    el.attachEvent("on" + sType, wrappedFn);
+                }
+
+                return true;
+
+            },
+
+            /**
+             * Shorthand for YAHOO.util.Event.addListener
+             * @type function
+             */
+            // on: this.addListener,
+
+            /**
+             * When using legacy events, the handler is routed to this object
+             * so we can fire our custom listener stack.
+             * @private
+             */
+            fireLegacyEvent: function(e, legacyIndex) {
+                // alert("fireLegacyEvent " + legacyIndex);
+                var ok = true;
+
+                // var el = legacyEvents[YAHOO.util.Event.EL];
+
+                /* this is not working because the property may get populated
+                // fire the event we replaced, if it exists
+                var origHandler = legacyEvents[2];
+                alert(origHandler);
+                if (origHandler && origHandler.call) {
+                    var ret = origHandler.call(el, e);
+                    ok = (ret);
+                }
+                */
+
+                var le = legacyHandlers[legacyIndex];
+                for (i=0; i < le.length; ++i) {
+                    var index = le[i];
+                    // alert(index);
+                    if (index) {
+                        var li = listeners[index];
+                        var scope = li[this.ADJ_SCOPE];
+                        var ret = li[this.WFN].call(scope, e);
+                        ok = (ok && ret);
+                        // alert(ok);
+                    }
+                }
+
+                return ok;
+            },
+
+            /**
+             * Returns the legacy event index that matches the supplied
+             * signature
+             * @private
+             */
+            getLegacyIndex: function(el, sType) {
+                for (var i=0; i < legacyEvents.length; ++i) {
+                    var le = legacyEvents[i];
+                    if (le && le[0] == el && le[1] == sType) {
+                        return i;
+                    }
+                }
+
+                return -1;
+            },
+
+            /**
+             * Logic that determines when we should automatically use legacy
+             * events instead of DOM2 events.
+             * @private
+             */
+            useLegacyEvent: function(el, sType) {
+
+                return ( (!el.addEventListener && !el.attachEvent) ||
+                                (sType == "click" && this.isSafari) );
+            },
+
+            /**
+             * Removes an event handler
+             *
+             * @param {Object} el the html element or the id of the element to
+             * assign the event to.
+             * @param {String} sType the type of event to remove
+             * @param {Function} fn the method the event invokes
+             * @return {boolean} true if the unbind was successful, false
+             * otherwise
+             */
+            removeListener: function(el, sType, fn) {
+
+                // The el argument can be a string
+                if (typeof el == "string") {
+                    el = this.getEl(el);
+                // The el argument can be an array of elements or element ids.
+                } else if ( this._isValidCollection(el)) {
+                    var ok = true;
+                    for (var i=0; i< el.length; ++i) {
+                        ok = ( this.removeListener(el[i], sType, fn) && ok );
+                    }
+                    return ok;
+                }
+
+                var cacheItem = null;
+                var index = this._getCacheIndex(el, sType, fn);
+
+                if (index >= 0) {
+                    cacheItem = listeners[index];
+                }
+
+                if (!el || !cacheItem) {
+                    return false;
+                }
+
+
+                if (el.removeEventListener) {
+                    el.removeEventListener(sType, cacheItem[this.WFN], false);
+                    // alert("adsf");
+                } else if (el.detachEvent) {
+                    el.detachEvent("on" + sType, cacheItem[this.WFN]);
+                }
+
+                // removed the wrapped handler
+                delete listeners[index][this.WFN];
+                delete listeners[index][this.FN];
+                delete listeners[index];
+
+                return true;
+
+            },
+
+            /**
+             * Returns the event's target element
+             * @param {Event} ev the event
+             * @param {boolean} resolveTextNode when set to true the target's
+             *                  parent will be returned if the target is a
+             *                  text node
+             * @return {HTMLElement} the event's target
+             */
+            getTarget: function(ev, resolveTextNode) {
+                var t = ev.target || ev.srcElement;
+
+                if (resolveTextNode && t && "#text" == t.nodeName) {
+                    return t.parentNode;
+                } else {
+                    return t;
+                }
+            },
+
+            /**
+             * Returns the event's pageX
+             * @param {Event} ev the event
+             * @return {int} the event's pageX
+             */
+            getPageX: function(ev) {
+                var x = ev.pageX;
+                if (!x && 0 !== x) {
+                    x = ev.clientX || 0;
+
+                    if ( this.isIE ) {
+                        x += this._getScrollLeft();
+                    }
+                }
+
+                return x;
+            },
+
+            /**
+             * Returns the event's pageY
+             * @param {Event} ev the event
+             * @return {int} the event's pageY
+             */
+            getPageY: function(ev) {
+                var y = ev.pageY;
+                if (!y && 0 !== y) {
+                    y = ev.clientY || 0;
+
+                    if ( this.isIE ) {
+                        y += this._getScrollTop();
+                    }
+                }
+
+                return y;
+            },
+
+            /**
+             * Returns the event's related target
+             * @param {Event} ev the event
+             * @return {HTMLElement} the event's relatedTarget
+             */
+            getRelatedTarget: function(ev) {
+                var t = ev.relatedTarget;
+                if (!t) {
+                    if (ev.type == "mouseout") {
+                        t = ev.toElement;
+                    } else if (ev.type == "mouseover") {
+                        t = ev.fromElement;
+                    }
+                }
+
+                return t;
+            },
+
+            /**
+             * Returns the time of the event.  If the time is not included, the
+             * event is modified using the current time.
+             * @param {Event} ev the event
+             * @return {Date} the time of the event
+             */
+            getTime: function(ev) {
+                if (!ev.time) {
+                    var t = new Date().getTime();
+                    try {
+                        ev.time = t;
+                    } catch(e) {
+                        // can't set the time property
+                        return t;
+                    }
+                }
+
+                return ev.time;
+            },
+
+            /**
+             * Convenience method for stopPropagation + preventDefault
+             * @param {Event} ev the event
+             */
+            stopEvent: function(ev) {
+                this.stopPropagation(ev);
+                this.preventDefault(ev);
+            },
+
+            /**
+             * Stops event propagation
+             * @param {Event} ev the event
+             */
+            stopPropagation: function(ev) {
+                if (ev.stopPropagation) {
+                    ev.stopPropagation();
+                } else {
+                    ev.cancelBubble = true;
+                }
+            },
+
+            /**
+             * Prevents the default behavior of the event
+             * @param {Event} ev the event
+             */
+            preventDefault: function(ev) {
+                if (ev.preventDefault) {
+                    ev.preventDefault();
+                } else {
+                    ev.returnValue = false;
+                }
+            },
+
+            /**
+             * Returns the event, should not be necessary for user to call
+             * @param {Event} the event parameter from the handler
+             * @return {Event} the event
+             */
+            getEvent: function(e) {
+                var ev = e || window.event;
+
+                if (!ev) {
+                    var c = this.getEvent.caller;
+                    while (c) {
+                        ev = c.arguments[0];
+                        if (ev && Event == ev.constructor) {
+                            break;
+                        }
+                        c = c.caller;
+                    }
+                }
+
+                return ev;
+            },
+
+            /**
+             * Returns the charcode for an event
+             * @param {Event} ev the event
+             * @return {int} the event's charCode
+             */
+            getCharCode: function(ev) {
+                return ev.charCode || (ev.type == "keypress") ? ev.keyCode : 0;
+            },
+
+            /**
+             * @private
+             * Locating the saved event handler data by function ref
+             */
+            _getCacheIndex: function(el, sType, fn) {
+                for (var i=0; i< listeners.length; ++i) {
+                    var li = listeners[i];
+                    if ( li                 &&
+                         li[this.FN] == fn  &&
+                         li[this.EL] == el  &&
+                         li[this.TYPE] == sType ) {
+                        return i;
+                    }
+                }
+
+                return -1;
+            },
+
+            /**
+             * We want to be able to use getElementsByTagName as a collection
+             * to attach a group of events to.  Unfortunately, different
+             * browsers return different types of collections.  This function
+             * tests to determine if the object is array-like.  It will also
+             * fail if the object is an array, but is empty.
+             * @param o the object to test
+             * @return {boolean} true if the object is array-like and populated
+             */
+            _isValidCollection: function(o) {
+                // alert(o.constructor.toString())
+                // alert(typeof o)
+
+                return ( o                    && // o is something
+                         o.length             && // o is indexed
+                         typeof o != "string" && // o is not a string
+                         !o.tagName           && // o is not an HTML element
+                         !o.alert             && // o is not a window
+                         typeof o[0] != "undefined" );
+
+            },
+
+            /**
+             * @private
+             * DOM element cache
+             */
+            elCache: {},
+
+            /**
+             * We cache elements bound by id because when the unload event
+             * fires, we can no longer use document.getElementById
+             * @private
+             */
+            getEl: function(id) {
+                /*
+                // this is a problem when replaced via document.getElementById
+                if (! this.elCache[id]) {
+                    try {
+                        var el = document.getElementById(id);
+                        if (el) {
+                            this.elCache[id] = el;
+                        }
+                    } catch (er) {
+                    }
+                }
+                return this.elCache[id];
+                */
+
+                return document.getElementById(id);
+            },
+
+            /**
+             * Clears the element cache
+             */
+            clearCache: function() {
+                for (i in this.elCache) {
+                    delete this.elCache[i];
+                }
+            },
+
+            /**
+             * Called by CustomEvent instances to provide a handle to the
+             * event * that can be removed later on.  Should be package
+             * protected.
+             * @private
+             */
+            regCE: function(ce) {
+                customEvents.push(ce);
+            },
+
+            /**
+             * @private
+             * hook up any deferred listeners
+             */
+            _load: function(e) {
+                loadComplete = true;
+            },
+
+            /**
+             * Polling function that runs before the onload event fires,
+             * attempting * to attach to DOM Nodes as soon as they are
+             * available
+             * @private
+             */
+            _tryPreloadAttach: function() {
+
+                // keep trying until after the page is loaded.  We need to
+                // check the page load state prior to trying to bind the
+                // elements so that we can be certain all elements have been
+                // tested appropriately
+                var tryAgain = !loadComplete;
+
+                for (var i=0; i < delayedListeners.length; ++i) {
+                    var d = delayedListeners[i];
+                    // There may be a race condition here, so we need to
+                    // verify the array element is usable.
+                    if (d) {
+
+                        // el will be null if document.getElementById did not
+                        // work
+                        var el = this.getEl(d[this.EL]);
+
+                        if (el) {
+                            this.on(el, d[this.TYPE], d[this.FN],
+                                    d[this.SCOPE], d[this.ADJ_SCOPE]);
+                            delete delayedListeners[i];
+                        }
+                    }
+                }
+
+                if (tryAgain) {
+                    setTimeout("YAHOO.util.Event._tryPreloadAttach()", 50);
+                }
+            },
+
+            /**
+             * Removes all listeners registered by pe.event.  Called
+             * automatically during the unload event.
+             */
+            _unload: function(e, me) {
+                for (var i=0; i < unloadListeners.length; ++i) {
+                    var l = unloadListeners[i];
+                    if (l) {
+                        var scope = (l[this.ADJ_SCOPE]) ? l[this.SCOPE]: window;
+                        l[this.FN].call(scope, this.getEvent(e), l[this.SCOPE] );
+                    }
+                }
+
+                if (listeners && listeners.length > 0) {
+                    for (i = 0; i < listeners.length; ++i) {
+                        l = listeners[i];
+                        if (l) {
+                            this.removeListener(l[this.EL], l[this.TYPE],
+                                    l[this.FN]);
+                        }
+                    }
+
+                    this.clearCache();
+                }
+
+                for (i = 0; i < customEvents.length; ++i) {
+                    customEvents[i].unsubscribeAll();
+                    delete customEvents[i];
+                }
+
+                for (i = 0; i < legacyEvents.length; ++i) {
+                    // dereference the element
+                    delete legacyEvents[i][0];
+                    // delete the array item
+                    delete legacyEvents[i];
+                }
+            },
+
+            /**
+             * Returns scrollLeft
+             * @private
+             */
+            _getScrollLeft: function() {
+                return this._getScroll()[1];
+            },
+
+            /**
+             * Returns scrollTop
+             * @private
+             */
+            _getScrollTop: function() {
+                return this._getScroll()[0];
+            },
+
+            /**
+             * Returns the scrollTop and scrollLeft.  Used to calculate the
+             * pageX and pageY in Internet Explorer
+             * @private
+             */
+            _getScroll: function() {
+                var dd = document.documentElement; db = document.body;
+                if (dd && dd.scrollTop) {
+                    return [dd.scrollTop, dd.scrollLeft];
+                } else if (db) {
+                    return [db.scrollTop, db.scrollLeft];
+                } else {
+                    return [0, 0];
+                }
+            }
+        };
+    } ();
+
+    YAHOO.util.Event.on = YAHOO.util.Event.addListener;
+
+    if (document && document.body) {
+        YAHOO.util.Event._load();
+    } else {
+        YAHOO.util.Event.on(window, "load", YAHOO.util.Event._load,
+                YAHOO.util.Event, true);
+    }
+
+    YAHOO.util.Event.on(window, "unload", YAHOO.util.Event._unload,
+                YAHOO.util.Event, true);
+
+    YAHOO.util.Event._tryPreloadAttach();
+
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/key.js
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/key.js	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/key.js	(revision 13928)
@@ -0,0 +1,34 @@
+/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
+
+YAHOO.util.Key = new function() {
+	// this.logger	= new ygLogger("ygEventUtil");
+	// DOM key constants 
+	this.DOM_VK_UNDEFINED               = 0x0;
+	this.DOM_VK_RIGHT_ALT               = 0x12;
+	this.DOM_VK_LEFT_ALT                = 0x12;
+	this.DOM_VK_LEFT_CONTROL            = 0x11;
+	this.DOM_VK_RIGHT_CONTROL           = 0x11;
+	this.DOM_VK_LEFT_SHIFT              = 0x10;
+	this.DOM_VK_RIGHT_SHIFT             = 0x10;
+	this.DOM_VK_META                    = 0x9D;
+	this.DOM_VK_BACK_SPACE              = 0x08;
+	this.DOM_VK_CAPS_LOCK               = 0x14;
+	this.DOM_VK_DELETE                  = 0x7F;
+	this.DOM_VK_END                     = 0x23;
+	this.DOM_VK_ENTER                   = 0x0D;
+	this.DOM_VK_ESCAPE                  = 0x1B;
+	this.DOM_VK_HOME                    = 0x24;
+	this.DOM_VK_NUM_LOCK                = 0x90;
+	this.DOM_VK_PAUSE                   = 0x13;
+	this.DOM_VK_PRINTSCREEN             = 0x9A;
+	this.DOM_VK_SCROLL_LOCK             = 0x91;
+	this.DOM_VK_SPACE                   = 0x20;
+	this.DOM_VK_TAB                     = 0x09;
+	this.DOM_VK_LEFT                    = 0x25;
+	this.DOM_VK_RIGHT                   = 0x27;
+	this.DOM_VK_UP                      = 0x26;
+	this.DOM_VK_DOWN                    = 0x28;
+	this.DOM_VK_PAGE_DOWN               = 0x22;
+	this.DOM_VK_PAGE_UP                 = 0x21;
+};
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/ygDDOnTop.js
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/ygDDOnTop.js	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/ygDDOnTop.js	(revision 13928)
@@ -0,0 +1,46 @@
+
+/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
+
+/**
+ * @class a DragDrop implementation that moves the object as it is being dragged,
+ * and keeps the object being dragged on top.  This is a subclass of ygDD rather
+ * than DragDrop, and inherits the implementation of most of the event listeners
+ * from that class.
+ *
+ * @extends ygDD
+ * @constructor
+ * @param {String} id the id of the linked element
+ * @param {String} sGroup the group of related DragDrop items
+ */
+function ygDDOnTop(id, sGroup) {
+	if (id) {
+		this.init(id, sGroup);
+	
+	}
+}
+
+ygDDOnTop.prototype = new YAHOO.util.DD();
+
+/**
+ * The inital z-index of the element, stored so we can restore it later
+ *
+ * @type int
+ */
+ygDDOnTop.prototype.origZ = 0;
+
+ygDDOnTop.prototype.startDrag = function(x, y) {
+
+	var style = this.getEl().style;
+
+	// store the original z-index
+	this.origZ = style.zIndex;
+
+	// The z-index needs to be set very high so the element will indeed be on top
+	style.zIndex = 999;
+}
+
+ygDDOnTop.prototype.endDrag = function(e) {
+
+	// restore the original z-index
+	this.getEl().style.zIndex = this.origZ;
+};
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/ygDDPlayer.js
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/ygDDPlayer.js	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/js/ygDDPlayer.js	(revision 13928)
@@ -0,0 +1,350 @@
+/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
+
+function ygDDStack(id, sGroup) {
+	if (id) {
+		this.init(id, sGroup);
+		this.initFrame();
+	}
+}
+
+ygDDStack.prototype = new YAHOO.util.DDTarget();
+
+ygDDPlayer.TYPE = "ygDDPlayer";
+
+/**
+ * @class a YAHOO.util.DDFramed implementation. During the drag over event, the
+ * dragged element is inserted before the dragged-over element.
+ *
+ * @extends YAHOO.util.DDProxy
+ * @constructor
+ * @param {String} id the id of the linked element
+ * @param {String} sGroup the group of related DragDrop objects
+ */
+function ygDDPlayer(id, sGroup,bl) {
+    this.initPlayer(id, sGroup);
+    this.berryList = bl;     
+            
+}
+
+ygDDPlayer.prototype = new YAHOO.util.DDProxy();
+
+ygDDPlayer.prototype.berryList = new Array();
+
+ygDDPlayer.prototype.initPlayer = function(id, sGroup) {
+	if (!id) { return; }
+
+    this.init(id, sGroup);
+    this.initFrame();
+    var s = this.getDragEl().style;
+    s.borderColor = "transparent";
+    // s.backgroundColor = "#cccccc";
+    s.opacity = 0.76;
+    s.filter = "alpha(opacity=76)";
+
+    // specify that this is not currently a drop target
+    this.isTarget = false;
+
+    this.originalStyles = [];
+
+    this.type = ygDDPlayer.TYPE;
+    this.slot = null;
+    this.startPos = YAHOO.util.Dom.getXY( this.getEl() );
+   
+}
+
+ygDDPlayer.prototype.startDrag = function(x, y) {
+	
+	var dragEl = this.getDragEl();
+	var clickEl = this.getEl();
+       
+       	dragEl.innerHTML = clickEl.innerHTML;
+	//dragEl.className = clickEl.className;
+    	//dragEl.style.color = clickEl.style.color;
+	//dragEl.style.backgroundColor = clickEl.style.backgroundColor;
+        //dragEl.style.visibility = clickEl.style.visibility;
+               
+ 	while (dragEl.hasChildNodes())	{
+        	 dragEl.removeChild(dragEl.firstChild);
+	}	
+       
+         var img = document.createElement('img');
+              img.src = 'interfaces/default/images/berry3.png';
+              img.height = 15;
+              img.width = 15;
+             img.border = 0;              
+          dragEl.appendChild(img);
+       
+        var added = true;
+
+      	var s = clickEl.style;
+	s.opacity = .1;
+	s.filter = "alpha(opacity=10)";
+
+	var targets = YAHOO.util.DDM.getRelated(this, true);
+	
+	for (var i=0; i<targets.length; i++) {
+		
+		var targetEl = this.getTargetDomRef(targets[i]);
+
+		if (!this.originalStyles[targetEl.id]) {
+			this.originalStyles[targetEl.id] = targetEl.className;
+		}
+
+		targetEl.className = "target";
+	}
+};
+
+ygDDPlayer.prototype.getTargetDomRef = function(oDD) {
+	if (oDD.player) {
+		return oDD.player.getEl();
+	} else {
+		return oDD.getEl();
+	}
+};
+
+ygDDPlayer.prototype.endDrag = function(e) {
+	// reset the linked element styles
+	var s = this.getEl().style;
+	s.opacity = 1;
+	s.filter = "alpha(opacity=100)";
+
+	this.resetTargets();
+};
+
+ygDDPlayer.prototype.resetTargets = function() {
+
+	// reset the target styles
+	var targets = YAHOO.util.DDM.getRelated(this, true);
+	for (var i=0; i<targets.length; i++) {
+		var targetEl = this.getTargetDomRef(targets[i]);
+		var oldStyle = this.originalStyles[targetEl.id];
+		if (oldStyle) {
+			targetEl.className = oldStyle;
+		}
+	}
+};
+
+var request_type = "GET";
+var addurlPath ="?a=pr&rt=r&ro=1&s=AddItem&c=&s1.id=2&o=XML&s1.item=";
+var delurlPath ="?a=pr&rt=r&ro=1&s=DeleteItem&c=&o=XML&s1.item=";
+var postdata = null;
+
+ygDDPlayer.prototype.onDragDrop = function(e, id) {
+	// get the drag and drop object that was targeted
+     var oDD;
+     var player = this;
+   
+    if ("string" == typeof id) {
+        oDD = YAHOO.util.DDM.getDDById(id);
+    } else {
+        oDD = YAHOO.util.DDM.getBestMatch(id);
+    }
+
+
+   var el = this.getEl();
+
+	// check if the slot has a player in it already
+	if (oDD.player) {
+		// check if the dragged player was already in a slot
+		if (this.slot) {
+	  		// check to see if the player that is already in the
+			// slot can go to the slot the dragged player is in
+			// YAHOO.util.DDM.isLegalTarget is a new method
+			if ( YAHOO.util.DDM.isLegalTarget(oDD.player, this.slot) ) {
+				YAHOO.util.DDM.moveToEl(oDD.player.getEl(), el);
+				this.slot.player = oDD.player;
+				oDD.player.slot = this.slot;
+			} else {
+				YAHOO.util.Dom.setXY(oDD.player.getEl(), oDD.player.startPos);
+				this.slot.player = null;
+				oDD.player.slot = null
+			}
+		} else {
+		        // the player in the slot will be moved to the dragged
+			// players start position
+			//oDD.player.slot = null;
+			//YAHOO.util.DDM.moveToEl(oDD.player.getEl(), el);
+		}
+	}else {
+		// Move the player into the emply slot
+		// I may be moving off a slot so I need to clear the player ref
+	   	if (this.slot) {
+			this.slot.player = null;
+		}
+	}
+
+     var  addurl = addurlPath + el.id;	
+     var addSuccess = function(o){ 
+                 var text = o.responseText;
+	         var result = o.responseXML;
+                 var items = result.getElementsByTagName('item');
+                 if (items.length > 0){
+                    var item = items[0];
+                    var berrybasket = YAHOO.util.Dom.get('berrybasket');
+        	    var berries = YAHOO.util.Dom.get('berries');
+                    player.berryList[player.berryList.length]= item;     
+                
+                    var itemID = item.getAttribute('collection')+":"+item.getAttribute('name');
+                    var parent =el.parentNode;
+                    parent.removeChild(el);
+ 	        	
+                    if (parent !=null && parent.id == "documentberries"){
+                         var root = YAHOO.util.Dom.get(itemID+":root");
+                         var section = YAHOO.util.Dom.get(itemID+":section");
+                         if(root!=null && root.id.indexOf(itemID) !=-1){
+                             parent.removeChild(root);
+                          }
+     
+	                  if(section!=null && section.id.indexOf(itemID) !=-1){
+                             parent.removeChild(section);
+        	          }                                                
+                     }
+                   
+
+                    if (!YAHOO.util.Dom.get('hideview') && player.berryList.length <13){
+                       
+                       while (berries.hasChildNodes()) {
+       	                   berries.removeChild(berries.firstChild);
+	                }
+                        
+                     for (var i =0; i < player.berryList.length; i++ ){
+                             var img = document.createElement('img');
+                              img.src = 'interfaces/default/images/berry3.png';
+                              img.height = 15;
+                              img.width = 15;
+                              img.border = 0;              
+                              berries.appendChild(img);
+                       }
+      	                                   
+	          }
+                 else{
+                      
+        
+                    if (YAHOO.util.Dom.get('hideview')){
+                      
+                        var berryBasket  = YAHOO.util.Dom.get('berrybasket');
+                        var berries  = YAHOO.util.Dom.get('berries');
+                        var doclist = YAHOO.util.Dom.get('doclist'); 
+                        var tid = el.id;                                  
+                        var berryItem; 
+                        var berryElement = document.createElement('li');
+                         for (var i in player.berryList){
+                             berryItem = player.berryList[i];
+                             var id = berryItem.getAttribute('collection')+":"+berryItem.getAttribute('name');
+                             if (id == tid){
+                               var title = berryItem.getAttribute('title');
+                               var root_title = berryItem.getAttribute('root_title');  
+                                if (root_title != ""){
+                                      root_title +=":";
+                                     }
+	    
+                                title = root_title+title;	
+                                if (title.length > 50){
+                                   title = title.substring(0,20)+" ... "+title.substr(title.length-35,35);
+                                }
+                                
+                               berryElement.appendChild(document.createTextNode(title));
+                               berryElement.setAttribute("class","berryitem");
+                               doclist.appendChild(berryElement);
+                               var heightStr =  berryBasket.style.height+"";
+                               var height =parseInt(heightStr.substring(0,heightStr.length-2)) +18;                             
+                               berryBasket.style.height = height;
+                               berries.style.height = height;
+                               break;
+                            }
+                         }
+                         }    
+                 
+                 }
+               }
+                
+                       
+
+         }
+
+     var addFailure = function(o){ }
+
+
+     var addcallback = {
+        	success:addSuccess,
+     	        failure:addFailure,  
+                argument:player
+                }
+    
+
+    var  delurl = delurlPath + el.id;	
+     var delSuccess = function(o){ 
+ 		 var result = o.responseXML;
+                    var parent =el.parentNode;
+                    if (parent == null) return;                   
+
+                    parent.removeChild(el);
+                     
+                    for (var i in player.berryList){
+                       var berry = player.berryList[i];
+                  
+                       var id = berry['collection']+":"+berry['name'];
+                       
+                       if (id == el.id){
+                             player.berryList.splice(i,1);
+                                    
+                             break;
+                         }
+
+                   }
+
+                   if (!parent.hasChildNodes()){
+                         var content =  YAHOO.util.Dom.get('content');
+                           while (content.hasChildNodes()) {
+		              content.removeChild(content.firstChild);
+	                }  
+                        content.appendChild(document.createTextNode('Your berry basket is empty.'));
+                     }
+                   var trashbin =  YAHOO.util.Dom.get('trashbin');
+                   if ( trashbin !=null){
+                         trashbin.style.background = 'url("interfaces/default/images/trash-full.png") 0 0 no-repeat';
+                  }
+              }                                       
+         
+
+     var delFailure = function(o){ }
+
+
+     var delcallback = {
+        	success:delSuccess,
+     	        failure:delFailure,  
+                argument:player
+                }
+    
+
+  if (id == 'berrybasket'){
+       YAHOO.util.Connect.asyncRequest(request_type , addurl , addcallback);         
+  }
+  else{
+        if (id == 'trashbin'){
+             YAHOO.util.Connect.asyncRequest(request_type , delurl , delcallback); 
+         }
+   }
+
+   this.resetTargets();  	
+   this.slot = oDD;	
+   this.slot.player = this;
+ 
+};
+
+ygDDPlayer.prototype.swap = function(el1, el2) {
+    var dom = YAHOO.util.Dom;
+	var pos1 = dom.getXY(el1);
+	var pos2 = dom.getXY(el2);
+	dom.setXY(el1, pos2);
+	dom.setXY(el2, pos1);
+};
+
+ygDDPlayer.prototype.onDragOver = function(e, id) {};
+
+ygDDPlayer.prototype.onDrag = function(e, id) {};
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/style/berry.css
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/style/berry.css	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/style/berry.css	(revision 13928)
@@ -0,0 +1,317 @@
+
+
+div.globalwrapper{
+  font-family: sans-serif, arial, helvetica;
+  margin: 0 2em 0 4em; 
+  padding:0;
+ 
+}
+
+div#content{
+  font-family: sans-serif, arial, helvetica;
+  margin: 0.5em 0 0.5em 0;
+  padding: 0; 
+
+}
+
+div.banner{
+ margin:0;
+ padding:0;
+
+}
+
+div.pageinfo{
+  float:right;
+  text-align: right;
+  padding: 0;
+  margin:0 0 3px 0;	
+  width: 50%;
+}
+
+div.basketimage{
+  float:left;
+  width: 45%;
+  padding:0;
+  margin:0;
+
+}
+
+
+div.bannerextra {
+   clear: both;
+   padding: 0.2em 0 0 0;
+}
+
+/* home, help, preferences links */
+p.bannerlinks {
+  font-weight: bold;
+  margin:0;
+  padding:0;
+}
+
+
+p.bannertitle {
+  font-family: sans-serif, arial, helvetica;
+  font-size: 24px;
+  font-weight: bold;
+  white-space: nowrap;
+  margin: 0;
+  padding: 0.5em 0 0.5em 0em;
+  background: url("../images/tile13.jpeg") 0 0 repeat-y;
+ 
+}
+
+
+a.navlink{
+  vertical-align: top;
+  padding: 0.2em 0.5em 0 0;
+  color: black;
+  text-decoration: none; 
+  background-image: url("../images/bg_off.png");
+ }
+
+a.navlink:hover {
+   background-image: url("../images/bg_on.png");
+ }
+
+p.navbar{
+  text-align: center;
+   background: url("../images/bg_green.png") 0 0 repeat-x;
+   font-weight: bold;
+}
+
+span.navlink{
+   margin:0 3em  0 3em;
+   padding:0 0.5em 0 0.5em;
+   background-image: url("../images/bg_off.png");
+   cursor: pointer;
+}
+
+span.navlink:hover {
+   background-image: url("../images/bg_on.png");
+ }
+
+img#trashbin{
+ float:right;
+}
+
+span.berryradio{
+ cursor: pointer;
+ margin:0 3em  0 3em;
+ font-weight: bold;
+}
+
+.berrycheck{
+ font-size: 80%;  
+ cursor: pointer;
+ font-weight: bold;
+ margin: 0 0 0 0.5em;
+}
+
+#urlcheck{
+ float: left;
+ padding: 0;
+ margin: 0;
+ 
+}
+
+.pick {
+  visibility:hidden;
+}
+
+div#berrybasket {
+   float:right;
+   font-family:sans-serif;
+   height:120px;
+   width: 100px;
+   padding: 4px 5px 4px 4px;
+   background-color:#E0F0E0;
+   background: url("../images/berrybasket.png") 0 0 no-repeat;
+   margin:0;
+   font-size:100%;
+   text-align:center;
+   #border:1px solid #2E8B57;	
+   z-index:10;
+   cursor: pointer;
+ }
+
+div#baskethandle {
+  padding: 0;
+  cursor:move;
+  height: 30px;
+  width:auto;
+  #background-color:#eeeeee;
+   background:transparent;
+   margin:0 ;
+  }
+
+div#berries {
+  text-align:left;
+  height: auto;
+  margin: 0;
+  padding:0;
+  overflow: hidden;   
+}
+
+
+p#documentberries {
+   font-weight: bold;
+   font-size:90%;
+}
+
+.documentberry {
+  margin:0 2em 0 0;
+  padding:0;
+  visibility:hidden;
+}
+
+
+#doclist{
+  margin: 0;
+ 
+}
+
+.content{
+ font-family:sans-serif;
+ text-align:left;
+}
+
+li.berryitem {
+   padding: 0;
+   margin: 0 ;
+   color: black;
+   font-size: 90%;
+}
+
+li.berrydoc {
+  font-size: 90%;
+  cursor: pointer;
+  padding: 0 ;
+  margin: 0 1em 0 0; 
+}
+
+a.expandcontract {
+  font-size: 90%;
+  color: red
+}
+
+
+.item {
+  font-size: 90%;
+ 
+}
+
+a.fullview:visited{
+ color:red;
+}
+
+a#hideview:visited{
+ color:red;
+}
+
+a.fullview{
+  float:left;
+  font-size: 90%;
+  margin: 0 0 0 20px;
+  padding:0;
+  cursor: pointer;
+  color:red;  
+  text-decoration:none;
+ }
+
+a#hideView{
+  float:right;
+  font-size: 90%;
+  margin:0 20px 0 0;
+  padding:0;
+  color: red;
+  cursor: pointer;
+  text-decoration:none;
+}
+
+
+.berrydelete{
+   font-family:sans-serif;
+   background-color:#E0F0E0;
+   border:1px solid #2E8B57;   
+   padding: 4px  4px 4px 4px; 
+   font-weight: bold;
+   cursor: pointer;
+   width: 6em;
+   color: red;
+   font-size: 90%;
+}
+
+.sendbutton{
+   font-family:sans-serif;
+   background-color:#E0F0E0;
+   border:1px solid #2E8B57;   
+   padding: 4px  4px 4px 4px; 
+   font-weight: bold;
+   cursor: pointer;
+   width: 5em;
+   font-size: 90%;
+   margin: 1em 0 0 0;
+}
+
+.berrybutton{
+   font-family:sans-serif;
+   background-color:#E0F0E0;
+   border:1px solid #2E8B57;   
+   padding: 4px  4px 4px 4px; 
+   font-weight: bold;
+   cursor: pointer;
+   width: 10em;
+   font-size: 90%;
+}
+
+.mailinput {
+  border:1px solid #2E8B57; 
+  width: 20em;
+  height: 1.5em;
+  font-size: 90%
+}
+
+.mailitem{
+   text-align: left;
+ }
+
+
+textarea#pretextarea {
+  font-family:sans-serif;
+  border:1px solid #2E8B57; 
+  width: 100%;
+  height: 25em;
+  font-size: 90%;
+  margin: 0.5em 0 0 0;
+  padding:0;
+}
+
+div#trashbin{
+   float: right;
+   height: 60px;
+   width:  55px;
+   padding: 0;
+   background: url("../images/trash-empty.png") 0 0 no-repeat;
+   margin:0;
+   z-index:10;
+}
+
+div#binhandle{
+ height: 60px;
+ width:  55px;
+ cursor: move;
+}
+
+span.extralink {
+  cursor:pointer;
+  font-size:80%;
+  font-weight:bold;
+  margin:0 2em 0 0;
+  color:black;
+}
+
+span.extralink:hover {
+   color: #2E8B57;
+}
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/style/core.css
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/style/core.css	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/style/core.css	(revision 13928)
@@ -0,0 +1,376 @@
+
+body {
+  padding:0;
+  margin:0;
+  font-family: sans-serif, arial, helvetica;   
+  background-image: url('../images/chalk.gif');
+  background-color: #fff; 
+  color: #000000 
+}
+
+/* this contains everything - all the other divs */
+#globalwrapper {
+  margin: .5em 3em 0 5em;
+}
+
+a:link
+{
+color: #339966;
+}
+
+a:visited
+{
+color: #066;
+}
+
+a:hover, a:active
+{
+color: #99CC33;
+}
+
+div#banner ul, ul#resultlist, ul#tocnodes, ul#docbuttons, ul.tocnode, ul#bannerlist, ul#navbarlist, ul#collectionlist, ul#servicelist, ul#classifierlist, ul#classifiernodelist, ul#queryitemlist{
+  list-style-type:none;
+  margin:0;
+  padding:0;
+}
+
+div#banner ul li, ul#bannerlist li, ul#navbarlist li {
+  display: inline;
+  margin:0;
+  padding:0;	
+}
+
+
+ul li>select, ul li>input {
+  padding: 0;
+  margin-left:5px;
+}
+
+
+div#banner {
+  margin: 0;
+  padding:0;
+  overflow: hidden;
+}
+
+div#banner p {
+  margin:0;
+  padding: 0;
+  float:left;
+  font-size: 16px;
+  text-align: left;
+  overflow:hidden	
+}
+
+div#banner p a {
+  background-image: url('../images/banner_bg.png');
+  background-repeat: repeat-y;
+}
+
+
+div#banner ul{
+  margin:0;
+  padding:0; 
+  float:right; 
+  font-size: 12px;  
+}
+
+div#banner a{
+  text-decoration: none;
+  color:#000000;
+}
+
+
+ul#bannerlist li a {
+  padding: 0 10px 0 10px; 
+  text-decoration: none;
+}
+
+ul#bannerlist li a:link, ul#bannerlist li a:visited
+{
+ background-color: #DEE79C;
+ background-image: url('../images/bg_off.png');
+ text-decoration: none
+}
+
+ul#bannerlist li a:hover{
+ background-color: #FFFF66;
+ background-image: url('../images/bg_on.png') ;
+ text-decoration: none
+}
+
+
+div#navbar{
+  clear:both;
+}
+
+ul#navbarlist{
+  margin:0;
+  padding:0; 
+  list-style-type: none; 
+  text-align:center;
+  width: 100%;
+  font-size: 80%;
+  background-image: url('../images/bg_green.png');	  
+  background-color: #99CC99
+ }
+
+ul#navbarlist li a {
+  padding: 0 20px 0 20px; 
+  margin: 0;
+  color: #000000; 
+  text-decoration: none;
+}
+
+ul#navbarlist li a:link, ul#navbarlist li a:visited{
+   background-image: url('../images/bg_off.png') ;
+ }
+
+ul#navbarlist li a:hover{
+  background-image: url('../images/bg_on.png') ;
+}
+
+
+ul#collectionlist li, ul#servicelist li{
+  display:block;
+  padding:0;
+  margin: .2em 0 0 0;
+  overflow:hidden;
+}
+
+
+ul#collectionlist img{
+  margin:0;
+  padding:0;
+  width: 150px;
+  height: 45px;
+  border: 1px solid black;
+  background-image: url('../images/collectimg_bg.png');
+  background-repeat: repeat-y;
+  overflow:hidden
+}
+
+ul#collectionlist li a.noimage{
+  display: block;
+  margin:0;
+  width: 145px;
+  height: 40px;
+  border: 1px solid black;
+  background-image: url('../images/collectimg_bg.png');
+  background-repeat: repeat-y;
+  overflow:hidden; padding-left:5px; padding-right:0; padding-top:5px; padding-bottom:0
+
+}
+
+ul#collectionlist li a{
+  font-size: 16px;
+  color: #000000;
+  text-decoration: none;  
+  font-weight: bold;
+}
+
+ul#servicelist li a{
+  margin:0 .5em 0 0;
+}
+
+ul#queryitemlist li{
+  display:block;
+  margin: .2em 0 .2em 0;
+}
+
+ul#classifierlist li{
+  list-style: none;
+  margin: 0 0 5px 0;
+  padding: 0;
+  display: block;
+  color:#000;
+}
+
+ul#classifierlist li#activeclassifier{
+  font-weight:bold;
+  padding: 0 0 0 5px;
+  margin:0 0 5px 0;
+}
+
+ ul#classifierlist li a:link, ul#classifierlist li a:visited  
+{
+   display:block;
+   margin:0;
+   background-image: url('../images/bg_off.png');
+   text-decoration: none; 
+   color:#000;
+   width:100%; padding-left:5px; padding-right:0; padding-top:2px; padding-bottom:2px
+ } 
+
+ul#classifierlist li a:hover, ul#classifierlist li a:active
+{
+  display:block;
+  margin:0;
+  background-image: url('../images/bg_on.png');
+  text-decoration: none; padding-left:5px; padding-right:0; padding-top:2px; padding-bottom:2px
+  
+}
+
+ul#classifierlist{
+   float:left;
+   font-size: 14px;
+   text-align: left;
+   width: 15%;
+   margin:0;
+   padding:0;
+}
+
+div#classifiers{
+  float:left;
+  width: 75%;
+  margin:0;
+  padding:0 0 0 10px;
+ }
+
+ul#classifiernodelist li{
+  list-style: none;
+  margin: 0;
+  padding: 5px 0 0 0;
+  display: block;
+ }
+
+ul.childrenlist{
+  margin: 0 0 0 0;
+  padding: 0 0 0 20px;
+  display: block;
+  width: 100%;
+}
+
+div#content{
+ clear: both;
+ overflow: hidden;
+ margin: .2em 0 0 0;
+}
+
+/* bg image set in style macro */
+div.divbar { 
+  clear: both; 
+  background-image: url('../images/bg_green.png'); 
+  width: 100%; 
+  text-align: center;
+  font-size:80%
+}
+
+
+/** query form style**/
+div#queryform{
+
+}
+
+/** search result style */
+div#terminfo{
+
+}
+
+div#matchdocs{
+
+}
+
+div.resultnavigation{
+ margin: 0;
+ padding:0;
+}
+
+ul#resultlist li{
+  display:block;
+}
+
+
+div.documenttext { clear: both; } /* come after any floating divs */
+
+div#documentheading{
+  font-size: 16pt;
+  font-weight: bold;
+}
+
+div#documentinfo { 
+  float:left;
+  padding:0;
+  margin:0;
+  width:24%;
+} 
+
+div#toc{
+  float:left;
+  text-align:left;
+  width:60%;
+  padding:0;
+  margin:0; 
+}
+
+ul#docbuttons li {
+   display: block;
+  font-size: 11px;
+  font-weight: bold;
+  background: #f7e7c5;
+  margin: 1px;
+  border: 1px solid #eeddbb;
+  text-align: center;
+  vertical-align: middle;
+  height: 30px; /* IE6 and NS4 treat width/height as min-width/min-height */
+  width: 110px;
+}
+
+
+ul#tocnodes li{
+ margin: 0;
+ padding: 5px 0 0 0;
+ display:block;
+}
+
+ul.tocnode {
+  margin:0;
+  padding:5px 0 0 20px;
+}
+
+ul.tocnode  a{
+ margin: 0;
+ padding:0 5px 0 0;
+ }
+
+span.bold{
+  font-weight: bold;	   
+}
+
+div.documentarrows{
+  clear: both; 
+  margin: 0 0 0 0;
+  padding: 1em 0 0 0;   
+}
+
+img.lessarrow{
+  float:left;
+  border: none;  
+}
+
+img.morearrow{
+  float:right;
+  border:none; 
+}
+
+div.formheading{
+  font-size: 16pt;
+  font-weight: bold;
+  margin: .5em 0 0;
+  padding:0;
+}
+
+ul#presprefs li, ul#berrybasketprefs li, ul#searchprefs li{
+  display: block;
+} 
+
+
+div.phrasebrowse{
+  text-align:center;
+  padding:0;
+  margin: .5em 0 .5em 0;   
+}
+
+div.QuickSearch {
+  float: right;
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/about.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/about.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/about.xsl	(revision 13928)
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+  
+  <!-- style includes global params interface_name, library_name -->
+  <xsl:include href="style.xsl"/>
+  
+  <xsl:output method="html"/>  
+
+  <xsl:template name="pageTitle">
+    <xsl:value-of select="/page/pageResponse/*/displayItem[@name='name']"/>
+  </xsl:template>
+
+  <!-- page specific style goes here -->
+  <xsl:template name="pageStyle"/>
+
+  <xsl:template match="pageResponse">
+     <xsl:variable name="collName" select="/page/pageRequest/paramList/param[@name='c']/@value"/>
+    <xsl:apply-templates select="collection|serviceCluster"><xsl:with-param name="collName" select="$collName"/></xsl:apply-templates>
+   </xsl:template>
+  
+  <xsl:template match="collection|serviceCluster">
+    <xsl:param name="collName"/>
+    <xsl:call-template name="standardPageBanner">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>
+    <xsl:call-template name="navigationBar">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>     
+    <div id="content"> 
+        <xsl:value-of select="displayItem[@name='description']" disable-output-escaping="yes"/>
+        <xsl:apply-templates select="serviceList">
+          <xsl:with-param name="collName" select="$collName"/>
+        </xsl:apply-templates>
+    </div>
+  </xsl:template>
+  
+  
+  <xsl:template match="serviceList">
+    <xsl:param name="collName"/>
+    <h3><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'about.services')"/></h3>
+    <xsl:choose>
+      <xsl:when test="service">
+	<xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'about.servicehelp')"/>
+      </xsl:when>
+      <xsl:otherwise>
+	<xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'about.noservices')"/>
+      </xsl:otherwise>
+    </xsl:choose>
+    
+    <xsl:if test="service">
+     <ul id="servicelist">  	
+      <xsl:for-each select="service">
+	    <xsl:variable name="action"><xsl:choose>
+	      <xsl:when test="@type='query'">q</xsl:when>
+	      <xsl:when test="@type='browse'">b</xsl:when>
+	      <xsl:when test="@type='process'">pr</xsl:when>
+	      <xsl:when test="@type='applet'">a</xsl:when>
+	      <xsl:otherwise>DO_NOT_DISPLAY</xsl:otherwise>
+	    </xsl:choose></xsl:variable>
+	   <xsl:if test="$action !='DO_NOT_DISPLAY'">
+	       <li><a href="{$library_name}?a={$action}&amp;rt=d&amp;s={@name}&amp;c={$collName}"><xsl:value-of select="displayItem[@name='name']"/></a><xsl:value-of select="displayItem[@name='description']"/></li>
+	  </xsl:if>
+  	</xsl:for-each>
+      </ul> 
+     </xsl:if> 
+  </xsl:template>
+
+</xsl:stylesheet>  
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/applet.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/applet.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/applet.xsl	(revision 13928)
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+  
+  <xsl:include href="style.xsl"/>
+  
+  <xsl:output method="html"/>  
+
+  <xsl:template name="pageTitle">
+    <xsl:value-of select="pageResponse/service/applet"/>
+  </xsl:template>
+
+  <!-- page specific style goes here -->
+  <xsl:template name="pageStyle"/>
+
+  <xsl:template match="pageResponse">
+    <xsl:variable name="collName"><xsl:value-of select="../pageRequest/paramList/param[@name='c']/@value"/></xsl:variable>
+     <xsl:call-template name="standardPageBanner">
+	<xsl:with-param name="collName" select="$collName"/>
+      </xsl:call-template>
+    
+    <xsl:call-template name="navigationBar">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>      
+    <div class="phrasebrowse">
+      <xsl:copy-of select="service/applet"/>
+    </div>
+    </xsl:template>
+</xsl:stylesheet>  
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/berry.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/berry.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/berry.xsl	(revision 13928)
@@ -0,0 +1,743 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+
+  <!--<xsl:include href="style.xsl"/>-->
+  <xsl:include href="service-params.xsl"/>
+  <xsl:include href="berrytools.xsl"/>
+
+  <xsl:output method="html"/>  
+
+  <xsl:param name="library_name"/>
+  
+   <!-- the main page layout template is here -->
+  <xsl:template match="page">
+    <html>
+      <xsl:call-template name="pageHead"/>	 
+      <body class="bgimage">
+	<div class='globalwrapper'>
+	  <xsl:apply-templates select="pageResponse"/>
+	</div>
+      </body>
+    </html>
+  </xsl:template>
+
+  <!-- put a space in the title in case the actual value is missing - mozilla will not display a page with no title-->
+  <xsl:template name="pageHead">
+    <head>
+      <title>
+	<xsl:call-template name="pageTitle"/>
+      </title>
+      <xsl:call-template name="pageStyle"/>
+    </head>
+  </xsl:template>
+  
+  <xsl:template name="pageTitle">
+    <xsl:value-of select="/page/pageResponse/serviceCluster/metadataList/metadata[@name='Title']"/>
+    Berry Basket
+  </xsl:template>
+
+  <!-- page specific style goes here -->
+  <xsl:template name="pageStyle" >
+    <xsl:call-template name="styleSheet" />
+    <xsl:call-template name="loadLibrary" />
+    <xsl:call-template name="buildContent" />   
+    <!-- <xsl:call-template name="showMailBox" />-->
+  </xsl:template>    
+  
+  <xsl:template match="pageResponse">
+    <xsl:variable name="clusterName"><xsl:value-of select="/page/pageRequest/paramList/param[@name='c']/@value"/></xsl:variable>
+    <xsl:call-template name="berryPageBanner" />
+    <xsl:apply-templates select="paramList"/>
+    <div id="content" ><span></span></div> 
+    <xsl:call-template name="footBanner" />
+  </xsl:template>
+  
+
+  <xsl:template match="collection">
+    <xsl:for-each select="item">
+      <xsl:text disable-output-escaping="yes">
+	var  doc = new Array();             
+      </xsl:text>
+      <xsl:for-each select="@*">
+	<xsl:text disable-output-escaping="yes">
+	  doc["</xsl:text><xsl:value-of select="name()" /><xsl:text disable-output-escaping="yes">"]='</xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes">'; </xsl:text>   
+      </xsl:for-each>
+      <xsl:text disable-output-escaping="yes"> 
+	docList[docList.length] = doc; 
+      </xsl:text>  
+    </xsl:for-each>     
+  </xsl:template>
+  
+  
+  <xsl:template name="buildContent">
+    <script type="text/javascript">
+      <xsl:text disable-output-escaping="yes">
+	var previousView;
+	var docList = new Array();
+	var urlonly = false;
+	var mailinfo = new Array();
+	mailinfo['address'] = "To: ";
+	mailinfo['cc'] = "CC: ";
+	mailinfo['bcc'] = "Bcc: ";
+	mailinfo['subject'] = "Subject: "; 
+	var textwin;
+	var mailwin;
+      </xsl:text>
+      <xsl:apply-templates select="/page/pageResponse/collection" />       
+      
+      <xsl:text disable-output-escaping="yes">
+    
+       function navigate(e){   
+             var target = e.target;
+       
+	     if (target.id.toLowerCase() == 'fullview'){  
+                  showFullView();
+              }
+
+             if (target.id.toLowerCase() == 'textview'){       
+               showTextView();
+             }
+
+             if (target.id.toLowerCase() == 'email'){       
+               showEmail();
+            }
+
+            if (target.id.toLowerCase() == 'sendmail'){       
+               sendMail();
+            }
+            
+           
+
+            if (target.id.toLowerCase() == 'urlcheck' &amp;&amp; urlonly){
+               var urlcheck = YAHOO.util.Dom.get('urlcheck');
+               urlcheck.src = 'interfaces/default/images/check3.gif';              
+               var parea  =YAHOO.util.Dom.get('pretextarea');       
+               urlonly = false;
+               populateUrlsAndMetadata(parea);
+               return;
+               
+            }
+
+            if (target.id.toLowerCase() == 'urlcheck' &amp;&amp; !urlonly ){ 
+                var urlcheck = YAHOO.util.Dom.get('urlcheck');
+                urlcheck.src = 'interfaces/default/images/check4.gif';                       
+                var parea  =YAHOO.util.Dom.get('pretextarea');
+                populateUrls(parea);        
+                urlonly = true;
+                return;
+             } 
+
+            if (target.id.toLowerCase() == 'extextview' ){
+               if (textwin != null){
+                   textwin.close();
+               }
+
+               textwin = window.open("","Berry basket plain text view","status=1,width=450,height=300");
+               textwin.moveTo(0,0);
+               var content = document.createElement('div');
+                buildPreview(content);
+                var body = textwin.document.getElementsByTagName('body')[0]; 
+                body.appendChild(content);
+                var prearea =  textwin.document.getElementsByTagName('textarea')[0];
+                prearea.cols = '55';
+                prearea.rows = '15';        
+             }
+
+             if (target.id.toLowerCase() == 'exemail' ){
+               if (mailwin != null){
+                   mailwin.close();
+               }
+               mailwin = window.open("","Berry basket mail to a friend","status=1,width=450,height=350");
+               mailwin.moveTo(0,0);
+               var content = document.createElement('div');
+               getEmailContent(content);
+               var body = mailwin.document.getElementsByTagName('body')[0]; 
+               body.appendChild(content);           
+                var prearea =  mailwin.document.getElementsByTagName('textarea')[0];
+                prearea.cols = '50';
+                prearea.rows = '11'; 
+             }
+              
+        }
+
+        function showFullView(){
+          
+             var content =  YAHOO.util.Dom.get('content'); 
+             var fullview =  YAHOO.util.Dom.get('fullview');
+
+              if (previousView != null){
+                 previousView.style.backgroundImage =  'url("interfaces/default/images/bg_on.png")'; 
+              } 
+              previousView = fullview;
+              previousView.style.backgroundImage =  'url("interfaces/default/images/bg_green.png")';
+
+               while (content.hasChildNodes()) {
+		 content.removeChild(content.firstChild);
+	       }                        
+           
+             if (docList.length == 0){
+                 content.appendChild(document.createTextNode("Your berry basket is empty."));
+                 return;
+              }
+
+ 
+            var trashbin = document.createElement('div');
+            trashbin.id ='trashbin';   
+            var binhandle = document.createElement('div');
+            binhandle.id = 'binhandle';   
+            binhandle.appendChild(document.createElement('span'));          
+            trashbin.appendChild(binhandle) 
+
+            content.appendChild(trashbin);
+
+            var dd = new ygDDOnTop('trashbin');
+            dd.setHandleElId('binhandle');      
+            new YAHOO.util.DDTarget('trashbin','trash');
+        
+            var dlist = document.createElement('div');
+            content.appendChild(dlist);                          
+            var ol =   document.createElement('ol');            
+            dlist.appendChild(ol); 
+
+             for (var i in docList){
+               var doc = docList[i];
+               var li = document.createElement('li'); 
+               var a = document.createElement('a'); 
+               var text ="";
+               a.href ="?a=d&amp;c="+doc['collection']+"&amp;d="+doc['name'];
+               a.appendChild(document.createTextNode(doc['title'])); 
+                if (doc['root_title'] != ""){
+                     li.appendChild(document.createTextNode(doc['root_title']+": ")); 
+                   }               
+               li.appendChild(a);
+               var metadata = "";
+               for (var metaItem in doc &amp;&amp; metaItem != 'title'){
+                    metadata = "\n"+metaItem+": "+ doc[metaItem]+"\n";
+               }
+               text +=metadata+"\n";
+               li.appendChild(document.createTextNode(text));
+               li.id = doc['collection']+":"+ doc['name']; 
+               li.className = 'berrydoc';
+               ol.appendChild(li);
+                new ygDDPlayer(li.id,'trash',docList); 
+         }
+
+         /**          
+           var extra = document.createElement('div');
+           var textview =  document.createElement('span'); 
+           textview.id = 'extextview';
+           textview.className = 'extralink';   
+           textview.appendChild(document.createTextNode("plain text version"));                   
+           var email =  document.createElement('span');
+           email.appendChild(document.createTextNode("email to a friend"));
+           email.id = 'exemail';      
+           email.className = 'extralink';    
+           extra.appendChild(textview);
+           extra.appendChild(email);
+           content.appendChild(extra);
+         **/ 
+        }
+
+       function showTextView(){
+             var content =  YAHOO.util.Dom.get('content'); 
+             var textview =  YAHOO.util.Dom.get('textview');
+
+              if (previousView != null &amp;&amp; textview !=null){
+                 previousView.style.backgroundImage =  'url("interfaces/default/images/bg_on.png")'; 
+              } 
+
+             if (textview !=null){
+               previousView = textview;
+               previousView.style.backgroundImage =  'url("interfaces/default/images/bg_green.png")';
+             }
+
+               while (content.hasChildNodes()) {
+		 content.removeChild(content.firstChild);
+	       }                        
+           
+             if (docList.length == 0){
+                content.appendChild(document.createTextNode("Your berry basket is empty."));
+                return;
+              }
+
+             buildPreview(content);   
+
+        
+       }
+
+       function getEmailContent(content){
+           var item ;
+           var tr;
+           var td;
+           var input;
+           
+           table = document.createElement('table');
+           table.setAttribute("class","mailtable");          
+
+          for (item in mailinfo){
+  	   tr = document.createElement('tr');       
+           td = document.createElement('td');
+           td.setAttribute("class","mailitem");
+           td.appendChild(document.createTextNode(mailinfo[item]));
+           tr.appendChild(td);
+ 
+           td = document.createElement('td');
+           input = document.createElement('input'); 
+           input.setAttribute("id", item);
+           input.setAttribute("class", "mailinput");
+           input.setAttribute("type", "text");
+           td.appendChild(input);
+           tr.appendChild(td);	        
+           table.appendChild(tr);
+          
+          }
+
+ 	   // an empty line
+           tr = document.createElement('tr');
+           td = document.createElement('td');
+           td.appendChild(document.createElement('br'));
+	   tr.appendChild(td);
+  	   table.appendChild(tr);
+
+	   content.appendChild(table);
+          
+           buildPreview(content);   
+
+           //send button
+	   input = document.createElement('input'); 
+           input.setAttribute("id", 'sendmail');
+           input.setAttribute("class", "sendbutton");
+           input.setAttribute("type", "button");
+           input.setAttribute("value", "send");        
+           content.appendChild(input);
+           
+        }
+
+      
+        function showEmail(){
+          
+             var content =  YAHOO.util.Dom.get('content'); 
+             var email =  YAHOO.util.Dom.get('email');
+
+              if (previousView != null &amp;&amp; email !=null ){
+                 previousView.style.backgroundImage =  'url("interfaces/default/images/bg_on.png")'; 
+              } 
+              
+              if (email != null){
+                previousView = email;
+               previousView.style.backgroundImage =  'url("interfaces/default/images/bg_green.png")';
+             }
+               while (content.hasChildNodes()) {
+		 content.removeChild(content.firstChild);
+	       }                        
+           
+             if (docList.length == 0){
+                content.appendChild(document.createTextNode("Your berry basket is empty."));
+                return;
+              }
+
+                   
+           var item ;
+           var tr;
+           var td;
+           var input;
+           
+           table = document.createElement('table');
+           table.setAttribute("class","mailtable");          
+
+          for (item in mailinfo){
+  	   tr = document.createElement('tr');       
+           td = document.createElement('td');
+           td.setAttribute("class","mailitem");
+           td.appendChild(document.createTextNode(mailinfo[item]));
+           tr.appendChild(td);
+ 
+           td = document.createElement('td');
+           input = document.createElement('input'); 
+           input.setAttribute("id", item);
+           input.setAttribute("class", "mailinput");
+           input.setAttribute("type", "text");
+           td.appendChild(input);
+           tr.appendChild(td);	        
+           table.appendChild(tr);
+          
+          }
+
+ 	   // an empty line
+           tr = document.createElement('tr');
+           td = document.createElement('td');
+           td.appendChild(document.createElement('br'));
+	   tr.appendChild(td);
+  	   table.appendChild(tr);
+
+	   content.appendChild(table);
+          
+           buildPreview(content);   
+
+           //send button
+	   input = document.createElement('input'); 
+           input.setAttribute("id", 'sendmail');
+           input.setAttribute("class", "sendbutton");
+           input.setAttribute("type", "button");
+           input.setAttribute("value", "send");        
+           content.appendChild(input);
+
+         }
+
+
+         function buildPreview(parent){
+             var div = document.createElement('div');
+         
+         
+             var img =  document.createElement('img');
+             img.src = 'interfaces/default/images/check3.gif';
+             img.id = 'urlcheck'; 
+             div.appendChild(img);
+       
+             var urls = document.createElement('span');
+             urls.id = 'urls';
+             urls.className = 'berrycheck';
+             urls.appendChild(document.createTextNode('URL only'));
+             div.appendChild(urls);
+
+            // var urlsmetadata = document.createElement('span');
+            // urlsmetadata.id = 'urlsmetadata'
+            // urlsmetadata.className = 'berryradio';
+            // urlsmetadata.appendChild(document.createTextNode('URLs and Metadata'));
+              
+            // div.appendChild(urlsmetadata);
+          
+          
+             parent.appendChild(div);
+
+                       
+             var parea  = document.createElement('textarea');
+             parea.id = 'pretextarea';                        
+
+             parent.appendChild(parea);        
+          
+         
+             populateUrlsAndMetadata(parea);	    
+               
+                       	
+         }
+
+        
+       function populateUrls(parea){
+          var urls="";
+          var doc_url = document.URL;
+          var root_url = doc_url.substring(0,doc_url.indexOf('?'));
+           
+          for (var i in docList){
+              var doc = docList[i];
+              urls +=root_url+"?a=d&amp;c="+doc["collection"]+"&amp;d="+doc["name"]+"\n\n";  
+                     
+          }
+
+           parea.value = urls;
+            
+         }
+
+	 function populateUrlsAndMetadata(parea){
+                       
+              var doc_url = document.URL;
+              var root_url = doc_url.substring(0,doc_url.indexOf('?'));
+              var fulltext="";
+
+              for (var i in docList){
+                   var doc = docList[i];
+                   var url =root_url+"?a=d&amp;c="+doc['collection']+"&amp;d="+doc['name']+"\n";  
+                    for (var metaItem in doc){
+                        var metadata = metaItem+": "+ doc[metaItem]+"\n";
+                      }
+                     fulltext +=url+metadata+"\n";
+                 
+              }
+
+               parea.value = fulltext;
+                  
+           }                                                    	    		 
+	                     
+          function sendMail(){
+              var  url = "?a=pr&amp;rt=r&amp;ro=1&amp;s=SendMail&amp;c=";
+                     var request_type = "POST";
+                     var postdata = ""; 
+ 	             var i;	     
+                     //get checked items
+                      for (i in mailinfo)
+			{ 
+                         
+                          var input = YAHOO.util.Dom.get(i);  
+                          var value = input.value;  
+			  postdata +="&amp;s1."+i+"="+value;	
+			}                                   
+
+
+                       var content = YAHOO.util.Dom.get('pretextarea').value;
+                       
+                       content = content.replace(/&amp;/g,'-------');  
+                       postdata +="&amp;s1.content="+content;
+                                                                
+                      
+                        var callback = {
+     			   success:function(o){
+                                    var result = o.responseText;
+                                    alert(result);     
+	 			                                                                      
+                                	} ,
+     			    failure:function(o){
+                                        alert("Sending mail falied");    
+ 				     }    
+  			 }
+                                               
+ 	               
+   			YAHOO.util.Connect.asyncRequest(request_type , url , callback, postdata);         
+         }	
+
+        YAHOO.util.Event.addListener(window,'click', navigate);
+        YAHOO.util.Event.addListener(window,'load', showFullView);
+      </xsl:text>
+    </script>    
+  </xsl:template>
+
+  <xsl:template name="styleSheet">
+    <link rel="stylesheet" href="interfaces/default/style/core.css" type="text/css"/>  
+    <link rel="stylesheet" href="interfaces/default/style/berry.css" type="text/css"/>  
+  </xsl:template>
+  
+  <xsl:template name="showMailBox">
+    <script type="text/javascript">
+      <xsl:text disable-output-escaping="yes">
+	var show = false;	
+	var table;
+	var mailserver  = new Array();     
+	mailserver['host'] = "Mail Server: ";
+	mailserver['user'] = "User Name: ";
+	mailserver['password'] = "Password: ";
+	
+	var mailinfo = new Array();
+	mailinfo['address'] = "To: ";
+	mailinfo['cc'] = "CC: ";
+	mailinfo['bcc'] = "Bcc: ";
+	mailinfo['subject'] = "Subject: "; 
+	
+	function mailBoxUpdate(e) {
+		var target = e.target;
+		if (target.id.toLowerCase() == 'sendasemail' &amp;&amp; !show){
+	       	    showMailBox();
+                    show = true;
+                }
+                else{
+                    if (target.id.toLowerCase() == 'sendasemail' &amp;&amp; show){
+                       hideMailBox();
+                       show = false;
+                    }
+
+                     if (target.id.toLowerCase() == 'sendmail'){
+                      sendMail();
+                    }
+                }
+
+
+                	
+        }
+
+       function showMailBox(){
+           var mailbox = YAHOO.util.Dom.get('mailbox');  
+           if (table != null &amp;&amp; !show){
+               mailbox.appendChild(table);
+              return;
+           }
+                        
+           var item ;
+           var tr;
+           var td;
+           var input;
+           
+           table = document.createElement('table');
+           table.setAttribute("class","mailtable");          
+
+           // mail server
+           tr = document.createElement('tr');
+           td = document.createElement('td');
+           td.setAttribute("class","mailitem");
+           td.appendChild(document.createTextNode(mailserver['host']));
+           tr.appendChild(td);
+ 
+           td = document.createElement('td');
+           input = document.createElement('input'); 
+           input.setAttribute("id", 'host');
+           input.setAttribute("class", "mailinput");
+           input.setAttribute("type", "text");
+           td.appendChild(input);
+           td.appendChild(document.createTextNode(' e.g. webmail.cs.waikato.ac.nz'));
+           tr.appendChild(td);	        
+           table.appendChild(tr);
+         
+           //user name 
+	   tr = document.createElement('tr');
+           td = document.createElement('td');
+           td.setAttribute("class","mailitem");
+           td.appendChild(document.createTextNode(mailserver['user']));
+           tr.appendChild(td);
+           td = document.createElement('td');
+           input = document.createElement('input'); 
+           input.setAttribute("id", 'user');
+           input.setAttribute("class", "mailinput");
+           input.setAttribute("type", "text");
+           td.appendChild(input);
+           tr.appendChild(td);	        
+           table.appendChild(tr);
+
+           //password 	
+	   tr = document.createElement('tr');
+           td = document.createElement('td');
+           td.setAttribute("class","mailitem");
+           td.appendChild(document.createTextNode(mailserver['password']));
+           tr.appendChild(td);
+           td = document.createElement('td');
+           input = document.createElement('input'); 
+           input.setAttribute("id", 'password');
+           input.setAttribute("class", "mailinput");
+           input.setAttribute("type", "password");
+           td.appendChild(input);
+           tr.appendChild(td);	        
+           table.appendChild(tr);
+
+           // an empty line
+           tr = document.createElement('tr');
+           td = document.createElement('td');
+           td.appendChild(document.createElement('br'));
+	   tr.appendChild(td);
+  	   table.appendChild(tr);
+
+          for (item in mailinfo){
+  	   tr = document.createElement('tr');       
+           td = document.createElement('td');
+           td.setAttribute("class","mailitem");
+           td.appendChild(document.createTextNode(mailinfo[item]));
+           tr.appendChild(td);
+ 
+           td = document.createElement('td');
+           input = document.createElement('input'); 
+           input.setAttribute("id", item);
+           input.setAttribute("class", "mailinput");
+           input.setAttribute("type", "text");
+           td.appendChild(input);
+           tr.appendChild(td);	        
+           table.appendChild(tr);
+          
+          }
+
+ 	// an empty line
+           tr = document.createElement('tr');
+           td = document.createElement('td');
+           td.appendChild(document.createElement('br'));
+	   tr.appendChild(td);
+  	   table.appendChild(tr);
+
+	//send button
+	   tr = document.createElement('tr');
+       	   td = document.createElement('td');
+           td.setAttribute("class","mailitem");
+           input = document.createElement('input'); 
+           input.setAttribute("id", 'sendmail');
+           input.setAttribute("class", "sendbutton");
+           input.setAttribute("type", "button");
+           input.setAttribute("value", "send");
+           td.appendChild(input);
+           tr.appendChild(td);	        
+           table.appendChild(tr);
+
+           
+          mailbox.appendChild(table);
+         }            
+     
+
+       function hideMailBox(){
+          var mailbox = YAHOO.util.Dom.get('mailbox');	
+          while (mailbox.hasChildNodes()) {
+		mailbox.removeChild(mailbox.firstChild);
+	   }
+         }
+      
+         function sendMail(){
+              var  url = "?a=pr&amp;rt=r&amp;ro=1&amp;s=SendMail&amp;c=";
+                     var request_type = "POST";
+                     var postdata = ""; 
+ 	             var i;	     
+                     //get checked items
+                      for (i in mailinfo)
+			{ 
+                         
+                          var input = YAHOO.util.Dom.get(i);  
+                          var value = input.value;  
+			  postdata +="&amp;s1."+i+"="+value;	
+			}                                   
+
+
+                       for (i in mailserver){
+                          var input = YAHOO.util.Dom.get(i);  
+                          var value = input.value; 
+                           postdata +="&amp;s1."+i+"="+value;
+                        }
+
+                       var content = YAHOO.util.Dom.get('pretextarea').value;
+                       
+                       content = content.replace(/&amp;/g,'-------');  
+                       postdata +="&amp;s1.content="+content;
+                                                                
+                      
+                        var callback = {
+     			   success:function(o){
+                                    var response = o.responseXML;
+            	                       
+	 			         alert(response.getAttribute('status'));                                                               
+                                	} ,
+     			    failure:function(o){
+                                        alert("Sending mail falied");    
+ 				     }    
+  			 }
+                                               
+ 	               
+   			YAHOO.util.Connect.asyncRequest(request_type , url , callback, postdata);         
+                 }	
+
+              
+            YAHOO.util.Event.addListener(window,'click',mailBoxUpdate );
+
+      </xsl:text> 
+    </script>
+  </xsl:template>
+  
+  <xsl:template name="berryPageBanner">
+    <div class='banner'>
+      <div class='pageinfo'>
+	<p class='bannerlinks'>
+	  <a class='navlink' href='{$library_name}?a=p&amp;sa=home' title='Library home page' >HOME</a>
+	  <a class='navlink' href='{$library_name}?a=p&amp;sa=help&amp;c='  title='Help pages' >HELP</a>
+	  <a class='navlink' href='{$library_name}?a=p&amp;sa=pref&amp;c=' title='Change your interface preferences'>PREFERENCES</a>
+	</p>      
+      </div>
+      <div class='basketimage'><p class='bannertitle'>Berry Basket</p></div>        
+    </div>
+    <div class="bannerextra"></div>
+    
+    <div >
+      <p class='navbar'><span id='fullview' class='navlink'>full view</span><span id='textview' class='navlink'>plain text version</span><span id='email' class='navlink'>email to a friend</span></p>
+    </div> 
+  </xsl:template>
+  
+  <xsl:template name="footBanner">
+    <div >
+      <p class='navbar'><span >powered by greenstone3</span></p>
+    </div> 
+  </xsl:template>
+  
+</xsl:stylesheet>  
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/berrytools.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/berrytools.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/berrytools.xsl	(revision 13928)
@@ -0,0 +1,402 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+
+  <xsl:param name="berryBaskets"/>
+  
+  <xsl:template name="berrybasket">
+    <div id="berrybasket" class="hide" >
+      <div id="baskethandle"><span></span></div>
+      <div id ="berries"><span></span></div>
+    </div>
+  </xsl:template>
+  
+  <xsl:template name="documentBerryBasket">
+    <xsl:param name="collName"/>
+    <xsl:param name="selectedNode"/>
+    <xsl:param name="rootNode"/>
+    <xsl:param name="docType" />
+    <div id="berrybasket" class="hide" >
+      <div id="baskethandle"><span></span></div>
+      <div id ="berries" ><span></span></div>
+    </div>
+    <xsl:choose>
+      <xsl:when test="$selectedNode = $rootNode">
+	<p id="documentberries">    
+	  <img class='pick'  id="{$collName}:{$rootNode}" src="interfaces/default/images/berry3.png" alt="in basket" width="15" height="15" border="0"/><span id="{$collName}:{$rootNode}:root" class="documentberry">the whole document</span></p>       
+      </xsl:when>
+      <xsl:otherwise>
+	<p id="documentberries">    
+	  <img class='pick'  id="{$collName}:{$rootNode}" src="interfaces/default/images/berry3.png" alt="in basket" width="15" height="15" border="0"/><span id="{$collName}:{$rootNode}:root" class="documentberry">the whole document</span><img class='pick'  id="{$collName}:{$selectedNode}" src="interfaces/default/images/berry3.png" alt="in basket" width="15" height="15" border="0"/><span id="{$collName}:{$selectedNode}:section" class="documentberry">the current section</span></p>
+      </xsl:otherwise> 
+    </xsl:choose>
+  </xsl:template>
+
+  
+  <xsl:template name="loadLibrary">
+    <script type="text/javascript" src="interfaces/default/js/YAHOO.js"><xsl:text disable-output-escaping="yes"> </xsl:text></script>
+    <script type="text/javascript" src="interfaces/default/js/event.js"><xsl:text disable-output-escaping="yes"> </xsl:text></script>
+    <script type="text/javascript" src="interfaces/default/js/connection.js"><xsl:text disable-output-escaping="yes"> </xsl:text></script>
+    <script type="text/javascript" src="interfaces/default/js/dom.js"><xsl:text disable-output-escaping="yes"> </xsl:text></script>
+    <script type="text/javascript" src="interfaces/default/js/dragdrop.js"><xsl:text disable-output-escaping="yes"> </xsl:text></script>
+    <script type="text/javascript" src="interfaces/default/js/ygDDPlayer.js"><xsl:text disable-output-escaping="yes"> </xsl:text></script>
+    <script type="text/javascript" src="interfaces/default/js/ygDDOnTop.js"><xsl:text disable-output-escaping="yes"> </xsl:text></script>
+    
+  </xsl:template>
+  
+  <xsl:template name="js-library">
+    <xsl:call-template name="loadLibrary" />	
+    <xsl:call-template name="basketCheckout" />
+  </xsl:template> 
+  
+  <!-- should be called for a documentNode -->
+  <xsl:template name="addBerry">
+    <xsl:param name="collName"/>
+    <td valign="top"><img class='pick' id="{$collName}:{@nodeID}" src="interfaces/default/images/berry3.png" alt="in basket" width="15" height="15" border="0"/></td>
+  </xsl:template>
+  
+  <xsl:template name="basketCheckout">
+    <script type="text/javascript">
+      <xsl:text disable-output-escaping="yes">
+      //used to stored the current items in berrybasket, including collection name, document id and dodument title 
+      //in the format of collection:id:[title], it is updated when the page is loaded (reloaded) or the user adds
+      // new items in the berry basket (see ygDDplayer.js). It is used to show the contents of the berry basket. 
+     var berryList =  new Array();
+     var show = false;    
+ 
+     // the default width and height of the berry basket
+     var oldHeight=90;
+     var oldWidth=140;
+     var oldBg;
+
+     var dd = new ygDDOnTop('berrybasket');
+     dd.setHandleElId('baskethandle');
+
+     var checkout = function(){
+       var request_type = "GET";
+       var url = "?a=pr&amp;rt=r&amp;ro=1&amp;s=ItemNum&amp;o=XML&amp;c="; 
+ 
+         var responseSuccess = function(o){
+	     var response = o.responseXML;
+             var size = response.getElementsByTagName('size').item(0).getAttribute('value');       
+           
+             var items = response.getElementsByTagName('item');
+             
+             for (var i=0;i &lt; items.length ; i++ ){
+ 
+                 // remove berries images from if the berry basket has already contains this item  
+                
+                 var itemID = items[i].getAttribute('collection')+":"+items[i].getAttribute('name');
+                 var item =  YAHOO.util.Dom.get(itemID);
+                 if (item != null){
+                    var parent = item.parentNode;
+                    parent.removeChild(item);
+                   
+                   if (parent !=null &amp;&amp; parent.id == "documentberries"){
+                         var root = YAHOO.util.Dom.get(itemID+":root");
+                         var section = YAHOO.util.Dom.get(itemID+":section");
+                         if(root!=null &amp;&amp; root.id.indexOf(itemID) !=-1){
+                             parent.removeChild(root);
+                          }
+     
+	                  if(section!=null &amp;&amp; section.id.indexOf(itemID) !=-1){
+                             parent.removeChild(section);
+        	          }
+                      
+                          
+                     }
+                 }
+                                
+                  berryList[berryList.length] = items[i];                   	
+	      }
+
+               //add berryimage into the berry basket
+                updateBerryImages();         
+             
+                // set berries images visible
+             // they are set to be invisible to prevent flickering when first loaded (see berry.css) 
+            
+             var berries =document.getElementsByTagName('img');
+	     var berrybasket = new YAHOO.util.DDTarget('berrybasket','basket');
+           
+             for (var j=0; j &lt; berries.length; j++){
+          
+                  var berry = berries[j]; 
+                   var parent = berry.parentNode;
+                   
+                   
+                   if (parent !=null &amp;&amp; parent.id == "documentberries"){
+                         var root = YAHOO.util.Dom.get(berry.id+":root");
+                         var section = YAHOO.util.Dom.get(berry.id+":section");
+                         if(root!=null &amp;&amp; root.id.indexOf(berry.id) !=-1){
+                             root.style.visibility ="visible" ;
+                          }
+     
+	                  if(section!=null &amp;&amp; section.id.indexOf(berry.id) !=-1){
+                             section.style.visibility ="visible" ;
+        	          }
+                      
+                          
+                     }  
+
+               if (berry.className  &amp;&amp;  berry.className  == 'pick')
+                  { 
+                    berry.style.visibility = "visible";
+                    new ygDDPlayer(berry.id,'basket',berryList); 
+                  }   
+     	      
+             }
+           
+           }
+
+         var responseFailure = function(o){
+             
+          }  
+
+        var callback = {
+        success: responseSuccess,
+        failure: responseFailure 
+      }
+
+      YAHOO.util.Connect.asyncRequest(request_type , url , callback);
+   }
+
+    function updateBerryImages(){
+     
+      for (var i =0;i &lt; berryList.length &amp;&amp; i &lt;12 ; i++ ){
+               var berries = YAHOO.util.Dom.get('berries');
+               var img = document.createElement('img');
+               img.src = 'interfaces/default/images/berry3.png';
+               img.height = 15;
+               img.width = 15;
+               img.border = 0;              
+               berries.appendChild(img);
+          }
+
+    }
+
+    function basketUpdate(e) {
+		var target = e.target;
+               
+		if ((target.id.toLowerCase() == 'berrybasket' || target.id.toLowerCase() == 'berries')  &amp;&amp; !show){
+	       	    showBasket();
+                    show = true;
+                }
+                else{
+                    if (target.id.toLowerCase() == 'hideview' &amp;&amp; show){
+                       hideBasket();
+                       show = false;
+                    }
+                }
+           
+            if (target.className == 'pick'){
+              addBerry(target);
+            }
+            
+        }
+
+     function showBasket() {
+        var berryBasket  = YAHOO.util.Dom.get('berrybasket');  
+        var basketHandle = YAHOO.util.Dom.get('baskethandle'); 
+        var berries = YAHOO.util.Dom.get('berries');   
+        var div = document.createElement('div');
+        var list = document.createElement('ol');
+        var width = 500;
+        var height = 40;
+        var i=0;
+ 
+        list.id = 'doclist';
+      
+       //remove berryImages in the berry basket 
+       while (berries.hasChildNodes()) {
+       	  berries.removeChild(berries.firstChild);
+	}
+
+       while (basketHandle.hasChildNodes()) {
+       	  basketHandle.removeChild(basketHandle.firstChild);
+	}
+
+       for (i in berryList){
+            var berryItem = berryList[i];
+            var berryElement = document.createElement('li');
+            var title = berryItem.getAttribute('title');
+            var root_title = berryItem.getAttribute('root_title'); 
+            var id = berryItem.getAttribute('collection')+":"+berryItem.getAttribute('name'); 
+
+            if (root_title != ""){
+              root_title +=":";
+            }
+	    
+            title = root_title+title;	
+            if (title.length > 50){
+               title = title.substring(0,20)+" ... "+title.substr(title.length-35,35);
+             }
+  
+            berryElement.appendChild(document.createTextNode(title));
+            berryElement.setAttribute("class","berryitem");
+            list.appendChild(berryElement);
+            height +=18;
+          } 
+      	   
+        oldHeight = berryBasket.style.height;
+        oldWidth = berryBasket.style.width;
+        oldBg = berryBasket.style.background; 
+        berryBasket.style.height = height;
+        berryBasket.style.width = width;
+        berryBasket.style.background ='url("interfaces/default/images/kete2.png") 0 0 repeat';
+        berryBasket.style.cursor = "default";         
+        berryBasket.className = "show";
+        div.appendChild(list); 	
+        berries.appendChild(div);  
+        berries.style.height = height - 40;
+
+        var links = document.createElement('div');
+        var hideView = document.createElement('a');
+        var fullView = document.createElement('a');
+        links.appendChild(hideView);
+        links.appendChild(fullView);
+        basketHandle.appendChild(links);
+        hideView.appendChild(document.createTextNode("Hide"));
+        fullView.appendChild(document.createTextNode("Full View"));
+        hideView.setAttribute("id","hideview");
+        fullView.setAttribute("href","?a=g&amp;sa=berry&amp;c=&amp;s=DisplayList&amp;rt=r");
+        fullView.setAttribute("class","fullview");
+
+        }
+
+      function hideBasket() {
+          var i = 0;
+          var berryBasket  = YAHOO.util.Dom.get('berrybasket');  
+          var basketHandle  = YAHOO.util.Dom.get('baskethandle'); 
+          var berries = YAHOO.util.Dom.get('berries'); 
+          berryBasket.style.height = oldHeight;
+          berryBasket.style.width = oldWidth;
+          berryBasket.style.background = oldBg;
+          berryBasket.style.cursor = "pointer";
+          berryBasket.className = "hide";
+
+          while (berries.hasChildNodes()) {
+		berries.removeChild(berries.firstChild);
+	}
+         
+        while (basketHandle.hasChildNodes()) {
+		basketHandle.removeChild(basketHandle.firstChild);
+	}
+         
+        updateBerryImages();
+      }    
+
+
+     function addBerry(el){
+      var  addurl = "?a=pr&amp;rt=r&amp;ro=1&amp;s=AddItem&amp;c=&amp;s1.id=2&amp;o=XML&amp;s1.item=" + el.id;	   
+      var addSuccess = function(o){ 
+ 		 var result = o.responseXML;
+                 var items = result.getElementsByTagName('item');
+                 if (items.length &gt; 0){
+                    var item = items[0];
+                    var berrybasket = YAHOO.util.Dom.get('berrybasket');
+        	    var berries = YAHOO.util.Dom.get('berries');
+                    berryList[berryList.length]= item;   
+                    var parent =el.parentNode;
+                    if (parent == null) return;     
+                    parent.removeChild(el);
+               
+                     var itemID = item.getAttribute('collection')+":"+item.getAttribute('name'); 
+                    if (parent !=null  &amp;&amp; parent.id == "documentberries"){
+                         var root = YAHOO.util.Dom.get(itemID+":root");
+                         var section = YAHOO.util.Dom.get(itemID+":section");
+                         if(root!=null  &amp;&amp; root.id.indexOf(itemID) !=-1){
+                             parent.removeChild(root);
+                          }
+     
+	                  if(section!=null  &amp;&amp; section.id.indexOf(itemID) !=-1){
+                             parent.removeChild(section);
+        	          }                                                
+                     }
+
+                    if (!YAHOO.util.Dom.get('hideview') &amp;&amp;  berryList.length &lt; 13){
+                      while (berries.hasChildNodes()) {
+       	                   berries.removeChild(berries.firstChild);
+	                }
+                        
+                     for (var i =0; i &lt; berryList.length; i++ ){
+                             var img = document.createElement('img');
+                              img.src = 'interfaces/default/images/berry3.png';
+                              img.height = 15;
+                              img.width = 15;
+                              img.border = 0;              
+                              berries.appendChild(img);
+                       }
+      	            
+                                                     
+	          }
+                 else{
+           
+                  if (YAHOO.util.Dom.get('hideview')){
+                        var berryBasket  = YAHOO.util.Dom.get('berrybasket');
+                        var berries  = YAHOO.util.Dom.get('berries');
+                        var doclist = YAHOO.util.Dom.get('doclist'); 
+                        var tid = el.id;                                  
+                        var berryItem; 
+                        var berryElement = document.createElement('li');
+                         for (var i in berryList){
+                             berryItem = berryList[i];
+                             var id = berryItem.getAttribute('collection')+":"+berryItem.getAttribute('name');
+                             if (id == tid){
+                               var title = berryItem.getAttribute('title');
+                               var root_title = berryItem.getAttribute('root_title');  
+                                if (root_title != ""){
+                                      root_title +=":";
+                                     }
+	    
+                                title = root_title+title;	
+                                if (title.length > 50){
+                                   title = title.substring(0,20)+" ... "+title.substr(title.length-35,35);
+                                }
+            
+                               berryElement.appendChild(document.createTextNode(title));
+                               berryElement.setAttribute("class","berryitem");
+                               doclist.appendChild(berryElement);
+                               var heightStr =  berryBasket.style.height+"";
+                               var height =parseInt(heightStr.substring(0,heightStr.length-2)) +18;                             
+                               berryBasket.style.height = height;
+                               berries.style.height = height;
+                               break;
+                            }
+                         }
+                             
+                      }
+                    
+                 }
+               }
+                                       
+             }
+
+           var addFailure = function(o){ }
+
+           var addcallback = {
+        	   success:addSuccess,
+     	           failure:addFailure
+                }
+
+            YAHOO.util.Connect.asyncRequest(request_type , addurl , addcallback);    
+
+         }
+
+  
+      
+     YAHOO.util.Event.addListener(window,'load', checkout); 
+     YAHOO.util.Event.addListener(window,'click', basketUpdate); 
+      </xsl:text>
+    </script>
+  </xsl:template>
+
+  <xsl:template name="berryStyleSheet">
+    <link rel="stylesheet" href="interfaces/default/style/berry.css" type="text/css"/>  
+  </xsl:template>
+  
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/classifier.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/classifier.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/classifier.xsl	(revision 13928)
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+  
+  <xsl:include href="style.xsl"/>
+  <xsl:include href="classifiertools.xsl"/>
+  <xsl:include href="berrytools.xsl"/>
+
+  <xsl:output method="html"/>  
+  <xsl:variable name="berrybasketswitch"><xsl:value-of select="/page/pageRequest/paramList/param[@name='berrybasket']/@value"/></xsl:variable> 
+
+  <xsl:template name="pageTitle">
+    <xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'gsdl')"/>
+  </xsl:template>
+
+  <!-- page specific style goes here -->
+  <xsl:template name="pageStyle">
+    <!--<xsl:if test="$berryBaskets = 'true'">-->
+    <xsl:if test="$berrybasketswitch = 'on'">
+      <xsl:call-template name="berryStyleSheet"/>  
+      <xsl:call-template name="js-library"/>
+    </xsl:if>
+  </xsl:template>
+
+
+  <xsl:template match="pageResponse">
+    <xsl:variable name="collName"><xsl:value-of select="/page/pageRequest/paramList/param[@name='c']/@value"/></xsl:variable>
+    <xsl:variable name="serviceName"><xsl:value-of select="service/@name"/></xsl:variable>
+    <xsl:call-template name="standardPageBanner">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>
+
+    <xsl:call-template name="navigationBar">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>      
+ 
+    <div id="content">
+      <xsl:apply-templates select="service/classifierList">
+        <xsl:with-param name="collName" select="$collName"/>
+        <xsl:with-param name="serviceName" select="$serviceName"/>
+      </xsl:apply-templates>
+      
+    <!--<xsl:if test="$berryBaskets = 'true'">-->
+    <xsl:if test="$berrybasketswitch = 'on'">
+      <xsl:call-template name="berrybasket" />
+    </xsl:if>  
+    <xsl:apply-templates select="classifier">
+      <xsl:with-param name="collName" select="$collName"/>
+      <xsl:with-param name="serviceName" select="$serviceName"/>
+    </xsl:apply-templates>
+    </div>
+  </xsl:template>
+  
+  <xsl:template match="classifierList">
+    <xsl:param name="collName"/>
+    <xsl:param name="serviceName"/>
+    <xsl:variable name="selected" select="/page/pageResponse/classifier/@name"/>
+   <ul id="classifierlist">
+	<xsl:for-each select="classifier">
+	  <xsl:choose>
+	    <xsl:when test="@name=$selected">
+	         <li id="activeclassifier"><xsl:value-of select="displayItem[@name='name']"/></li>
+	    </xsl:when>
+	    <xsl:otherwise>
+	      <li><a href="{$library_name}?a=b&amp;rt=r&amp;s={$serviceName}&amp;c={$collName}&amp;cl={@name}"><xsl:value-of select="displayItem[@name='name']"/></a></li></xsl:otherwise></xsl:choose>
+         
+ 	</xsl:for-each>
+    </ul>
+   </xsl:template>
+
+</xsl:stylesheet>
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/classifiertools.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/classifiertools.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/classifiertools.xsl	(revision 13928)
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+ 
+  <xsl:template match="classifier">
+    <xsl:param name="collName"/>
+    <xsl:param name="serviceName"/>
+    <div id="classifiers">
+    <xsl:variable name="cl_name"><xsl:value-of select="@name"/></xsl:variable>
+    <xsl:choose>
+      <xsl:when test="/page/pageResponse/service/classifierList/classifier[@name=$cl_name]/@horizontalAtTop">
+	<xsl:apply-templates select="." mode="horizontal-at-top">
+	  <xsl:with-param name="collName" select="$collName"/>
+	  <xsl:with-param name="serviceName" select="$serviceName"/>
+	</xsl:apply-templates>
+      </xsl:when>
+      <xsl:otherwise>
+	<xsl:apply-templates select="." mode="default">
+	  <xsl:with-param name="collName" select="$collName"/>
+	  <xsl:with-param name="serviceName" select="$serviceName"/>
+	</xsl:apply-templates>
+      </xsl:otherwise>
+    </xsl:choose>
+   </div>
+  </xsl:template>
+  
+
+  <xsl:template match="classifier" mode="horizontal-at-top">
+    <xsl:param name="collName"/>
+    <xsl:param name="serviceName"/>
+    <xsl:choose>
+      <xsl:when test="classifierNode">
+      <ul id="classifiernodelist-horizontal">
+	<xsl:for-each select='classifierNode'>
+	  <xsl:apply-templates select='.' mode="horizontal"><xsl:with-param name='collName' select='$collName'/><xsl:with-param name='serviceName' select='$serviceName'/></xsl:apply-templates>
+	</xsl:for-each>
+	</ul>
+	<ul id="childrenlist">
+	  <li>
+            <table><tr>
+	    <xsl:for-each select='classifierNode'>
+	      <xsl:apply-templates select='.' mode='process-all-children'><xsl:with-param name='collName' select='$collName'/><xsl:with-param name='serviceName' select='$serviceName'/></xsl:apply-templates>
+	    </xsl:for-each>
+             </tr></table>
+	  </li>
+	</ul>
+	</xsl:when>
+      <xsl:otherwise>
+	<!-- there were no classifier nodes -->
+	<ul id="childrenlist">
+          <xsl:for-each select='documentNode'>
+	    <li><table><tr><xsl:call-template name="documentNodeWrapper">
+		<xsl:with-param name='collName' select='$collName'/>
+		<xsl:with-param name='serviceName' select='$serviceName'/>
+	      </xsl:call-template></tr></table></li>
+	  </xsl:for-each>
+	</ul>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template match="classifier" mode="default"> <!-- the default -->
+    <xsl:param name="collName"/>
+    <xsl:param name="serviceName"/>
+    <ul id="classifiernodelist">
+      <xsl:call-template name="processNodeChildren">
+	<xsl:with-param name='collName' select='$collName'/>
+	<xsl:with-param name='serviceName' select='$serviceName'/>
+      </xsl:call-template>
+    </ul>
+  </xsl:template>
+  
+  <!-- this is a wrapper node, which the interface can use to add stuff into the query results that isn't part of and doesn't depend on the documentNode template which may come from the collection -->
+  <xsl:template name="documentNodeWrapper">
+    <xsl:param name="collName"/>
+    <xsl:param name="serviceName"/> 
+    <xsl:variable name="berrybasketswitch"><xsl:value-of select="/page/pageRequest/paramList/param[@name='berrybasket']/@value"/></xsl:variable> 
+    <!--<xsl:if test="$berryBaskets = 'true'">-->
+    <xsl:if test="$berrybasketswitch = 'on'">
+      <xsl:call-template name="addBerry">
+	<xsl:with-param name="collName" select="$collName"/>
+      </xsl:call-template> 
+    </xsl:if>
+    <xsl:apply-templates select=".">
+      <xsl:with-param name="collName" select="$collName"/>
+      <xsl:with-param name="serviceName" select="$serviceName"/>
+    </xsl:apply-templates>
+  </xsl:template>
+
+  <xsl:template match="documentNode">
+    <xsl:param name="collName"/>
+    <xsl:param name="serviceName"/>
+    <a href="{$library_name}?a=d&amp;c={$collName}&amp;d={@nodeID}&amp;dt={@docType}&amp;p.a=b&amp;p.s={$serviceName}"><xsl:apply-templates select="." mode="displayNodeIcon"/></a><xsl:value-of disable-output-escaping="yes"  select="metadataList/metadata[@name='Title']"/>
+  </xsl:template>
+
+  
+  
+  <!-- icon + title template-->
+  <xsl:template match="classifierNode">
+    <xsl:param name="collName"/>
+    <xsl:param name="serviceName"/>
+      <a><xsl:attribute name='href'><xsl:value-of select='$library_name'/>?a=b&amp;rt=r&amp;s=<xsl:value-of select='$serviceName'/>&amp;c=<xsl:value-of select='$collName'/>&amp;cl=<xsl:value-of select='@nodeID'/><xsl:if test="classifierNode|documentNode">.pr</xsl:if></xsl:attribute><xsl:call-template name="bookshelfimg"/></a><xsl:value-of disable-output-escaping="yes" select="metadataList/metadata[@name='Title']"/>
+  </xsl:template>
+  
+  <!-- the title is a link: an alternative template -->
+  <xsl:template match="classifierNode" mode="horizontal">
+    <xsl:param name="collName"/>
+    <xsl:param name="serviceName"/>
+    <li><xsl:choose>
+      <xsl:when test="classifierNode|documentNode"><b><xsl:value-of disable-output-escaping="yes" select="metadataList/metadata[@name='Title']"/><xsl:text> </xsl:text></b></xsl:when>
+      <xsl:otherwise>
+<a><xsl:attribute name='href'><xsl:value-of select='$library_name'/>?a=b&amp;rt=r&amp;s=<xsl:value-of select='$serviceName'/>&amp;c=<xsl:value-of select='$collName'/>&amp;cl=<xsl:value-of select='@nodeID'/></xsl:attribute><xsl:value-of disable-output-escaping="yes" select="metadataList/metadata[@name='Title']"/></a><xsl:text> </xsl:text></xsl:otherwise>
+    </xsl:choose>
+    </li>
+  </xsl:template>
+  
+
+  <!-- processing for the recursive bit -->
+  <xsl:template match="classifierNode" mode="process-all-children">
+    <xsl:param name="collName"/>
+    <xsl:param name="serviceName"/>
+      <xsl:call-template name="processNodeChildren">
+	  <xsl:with-param name='collName' select='$collName'/>
+	  <xsl:with-param name='serviceName' select='$serviceName'/>
+      </xsl:call-template>
+   </xsl:template>
+  
+  <xsl:template name="processNodeChildren">
+    <xsl:param name="collName"/>
+    <xsl:param name="serviceName"/>
+    <xsl:for-each select='classifierNode|documentNode'>
+      <xsl:choose><xsl:when test="name()='documentNode'">
+	 <li><table><tr>
+	    <xsl:call-template name="documentNodeWrapper">
+	      <xsl:with-param name='collName' select='$collName'/>
+	      <xsl:with-param name='serviceName' select='$serviceName'/>
+	    </xsl:call-template>
+             </tr></table>
+	  </li>
+	</xsl:when>
+	<xsl:otherwise>
+	  <li><table><tr>
+	    <xsl:apply-templates select='.'>
+	      <xsl:with-param name='collName' select='$collName'/>
+	      <xsl:with-param name='serviceName' select='$serviceName'/>
+	    </xsl:apply-templates>
+             </tr></table>
+	  </li>
+	  <xsl:if test="child::classifierNode or child::documentNode">
+	    <!--recurse into the children-->
+	    <li><ul class="childrenlist">
+	      <xsl:apply-templates select='.' mode='process-all-children'>
+		<xsl:with-param name='collName' select='$collName'/>
+		<xsl:with-param name='serviceName' select='$serviceName'/>
+	      </xsl:apply-templates>
+                </ul>
+	    </li>
+	  </xsl:if>
+	</xsl:otherwise>
+      </xsl:choose>
+    </xsl:for-each>
+  </xsl:template>
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/config_format.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/config_format.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/config_format.xsl	(revision 13928)
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:xslt="output.xsl"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:gsf="http://www.greenstone.org/greenstone3/schema/ConfigFormat"
+  extension-element-prefixes="java">
+  
+  <xsl:output method="xml"/>
+  <xsl:namespace-alias
+    stylesheet-prefix="xslt" result-prefix="xsl"/>
+
+  <xsl:template match="format">
+    <format>
+      <xsl:apply-templates/>
+    </format>
+  </xsl:template>
+  
+  <xsl:template match="gsf:template">
+    <xslt:template>
+      <xsl:copy-of select="@*"/>
+      <xsl:attribute name="priority">2</xsl:attribute> 
+      <xsl:if test=".//gsf:link">
+	<xslt:param name="serviceName"/>
+	<xslt:param name="collName"/>
+      </xsl:if>
+      <xsl:apply-templates/>
+    </xslt:template>
+  </xsl:template>
+  
+  <xsl:template match="gsf:link">
+    <xsl:choose>
+      <xsl:when test="@type='classifier'">
+	<a><xslt:attribute name='href'><xslt:value-of select='$library_name'/>?a=b&amp;rt=r&amp;s=<xslt:value-of select='$serviceName'/>&amp;c=<xslt:value-of select='$collName'/>&amp;cl=<xslt:value-of select='@nodeID'/><xslt:if test="classifierNode|documentNode">.pr</xslt:if><xslt:if test="parent::node()[@orientation='horizontal']">&amp;sib=1</xslt:if></xslt:attribute>
+	  <xsl:apply-templates/>
+	</a>
+      </xsl:when>
+      <xsl:otherwise> <!-- a document link -->
+	<a><xslt:attribute name="href"><xslt:value-of select='$library_name'/>?a=d&amp;c=<xslt:value-of select='$collName'/>&amp;d=<xslt:value-of select='@nodeID'/>&amp;dt=<xslt:value-of select='@docType'/><xslt:if test="@nodeType='leaf'">&amp;sib=1</xslt:if>&amp;p.a=<xslt:value-of select="/page/pageRequest/@action"/>&amp;p.sa=<xsl:value-of select="/page/pageRequest/@subaction"/>&amp;p.s=<xslt:value-of select="$serviceName"/></xslt:attribute><xsl:apply-templates/></a>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template match="gsf:icon">
+    <xsl:choose>
+      <xsl:when test="@type='classifier'">
+	<xslt:call-template name="bookshelfimg"/>
+      </xsl:when>
+      <xsl:otherwise>
+	<xslt:apply-templates select="." mode="displayNodeIcon"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  
+  <xsl:template match="gsf:metadata[@format]">
+    <xslt:value-of disable-output-escaping="yes"><xsl:attribute name="select">java:org.greenstone.gsdl3.util.XSLTUtil.<xsl:value-of select="@format"/>(metadataList/metadata[@name='<xsl:apply-templates select="." mode="get-metadata-name"/>'], /page/@lang )</xsl:attribute></xslt:value-of>
+  </xsl:template>
+
+  <xsl:template match="gsf:metadata">
+    <xslt:value-of disable-output-escaping="yes"><xsl:attribute name="select">metadataList/metadata[@name='<xsl:apply-templates select="." mode="get-metadata-name"/>']</xsl:attribute></xslt:value-of>
+  </xsl:template>
+
+  <xsl:template match="gsf:metadata" mode="get-metadata-name">
+    <xsl:if test="@multiple='true'">all_</xsl:if><xsl:if test='@select'><xsl:value-of select='@select'/>_</xsl:if><xsl:if test="@separator">*<xsl:value-of select='@separator'/>*_</xsl:if><xsl:value-of select="@name"/>
+  </xsl:template>
+  
+  <xsl:template match="gsf:metadata-old">
+    <xslt:value-of disable-output-escaping="yes"><xsl:attribute name="select">metadataList/metadata[@name="<xsl:choose><xsl:when test="@select='parent'">parent_</xsl:when><xsl:when test="@select='root'">root_</xsl:when><xsl:when test="@select='ancestors'">ancestors'<xsl:value-of select='@separator'/>'_</xsl:when><xsl:when test="@select='siblings'">siblings_'<xsl:value-of select='@separator'/>'_</xsl:when></xsl:choose><xsl:value-of select="@name"/>"]</xsl:attribute></xslt:value-of>
+  </xsl:template>
+  
+  <xsl:template match="gsf:text">
+    <xslt:apply-templates select="nodeContent"/>
+  </xsl:template>
+  
+  <xsl:template match="gsf:choose-metadata">
+    <xslt:choose>
+      <xsl:for-each select="gsf:metadata">
+	<xslt:when><xsl:attribute name="test">metadataList/metadata[@name='<xsl:apply-templates select="." mode="get-metadata-name"/>']</xsl:attribute>
+	  <xsl:apply-templates select="."/>
+	</xslt:when>
+      </xsl:for-each>
+      <xsl:if test="gsf:default">
+	<xslt:otherwise><xsl:apply-templates/></xslt:otherwise>
+      </xsl:if>
+    </xslt:choose>
+  </xsl:template>
+  
+  <xsl:template match="gsf:switch">
+    <xsl:variable name="meta-name"><xsl:apply-templates select="gsf:metadata" mode="get-metadata-name"/></xsl:variable>
+    <xslt:variable name="meta"><xsl:choose><xsl:when test="@preprocess"><xslt:value-of select="util:{@preprocess}(metadataList/metadata[@name='{$meta-name}'])"/></xsl:when><xsl:otherwise><xslt:value-of select="metadataList/metadata[@name='{$meta-name}']"/></xsl:otherwise></xsl:choose></xslt:variable>
+    <xslt:choose>
+      <xsl:for-each select="gsf:when">
+	<xslt:when test="util:{@test}($meta, '{@test-value}')">
+	  <xsl:apply-templates/>
+	</xslt:when>
+      </xsl:for-each>
+      <xsl:if test="gsf:otherwise">
+	<xslt:otherwise>
+	  <xsl:apply-templates select="gsf:otherwise/node()"/>
+	</xslt:otherwise>
+      </xsl:if>
+    </xslt:choose>
+  </xsl:template>
+  
+  <xsl:template match="*">
+    <xsl:copy>
+      <xsl:copy-of select="@*"/>
+      <xsl:apply-templates/>
+    </xsl:copy>
+  </xsl:template>
+
+</xsl:stylesheet>
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/document.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/document.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/document.xsl	(revision 13928)
@@ -0,0 +1,448 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  xmlns:gsf="http://www.greenstone.org/greenstone3/schema/ConfigFormat"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util gsf">
+
+  <xsl:include href="style.xsl"/>
+  <xsl:include href="service-params.xsl"/>
+  <xsl:include href="berrytools.xsl"/>
+
+  <xsl:output method="html"/>
+   <xsl:variable name="berrybasketswitch"><xsl:value-of select="/page/pageRequest/paramList/param[@name='berrybasket']/@value"/></xsl:variable> 
+  
+  <xsl:template name="pageTitle">
+    <xsl:variable name="docID" select="/page/pageResponse/document/@selectedNode"/>
+    <xsl:for-each select='/page/pageResponse/document/descendant::documentNode[@nodeID=$docID]/ancestor-or-self::documentNode'><xsl:if test='position()!=1'>::</xsl:if><xsl:value-of select="metadataList/metadata[@name='Title']"/></xsl:for-each>
+  </xsl:template>
+
+  <!-- this is hard coded for GATE, should somehow do it dynamically-->
+  <xsl:template name="pageStyle">
+    <style type="text/css">
+      <xsl:text disable-output-escaping="yes">
+	span.Location {  display:inline; color : red }
+	span.Person {  display:inline; color : green }
+	span.Organization {  display:inline; color : yellow }
+	span.Date {  display:inline; color : blue }
+	span.query_term {display: inline; background-color : yellow }
+      </xsl:text>
+    </style>
+     <!--TODO: add berry basket switch-->
+ <!--<xsl:if test="$berryBaskets = 'true'">-->
+    <xsl:if test="$berrybasketswitch = 'on'">
+     <xsl:call-template name="berryStyleSheet"/>  
+     <xsl:call-template name="js-library"/>
+    </xsl:if>
+  </xsl:template>
+  
+  <xsl:template match="pageResponse">
+    <xsl:variable name="collName"><xsl:value-of select="/page/pageRequest/paramList/param[@name='c']/@value"/></xsl:variable>
+    <xsl:call-template name="standardPageBanner">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>
+    <xsl:call-template name="navigationBar">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>
+  
+  <!--<xsl:if test="$berryBaskets = 'true'">-->
+    <xsl:if test="$berrybasketswitch = 'on'">
+    <xsl:call-template name="documentBerryBasket">
+      <xsl:with-param name="collName" select="$collName"/>
+      <xsl:with-param name="selectedNode" select="/page/pageResponse/document/@selectedNode"/>
+      <xsl:with-param name="rootNode" select="/page/pageResponse/document/documentNode[@nodeType='root']/@nodeID"/>
+      <xsl:with-param name="docType" select="/page/pageResponse/document/@docType"/>
+    </xsl:call-template>
+   </xsl:if>
+
+  <!-- display the document -->
+  <div id="content">
+    <xsl:apply-templates select="document">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:apply-templates>
+    </div>
+  </xsl:template>
+	
+  <xsl:template match="document">
+   <xsl:param name="collName"/>
+  
+    <xsl:call-template name="documentHeading">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>
+  
+    <xsl:call-template name="documentArrows">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>         
+    <xsl:call-template name="documentContent">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>
+    <xsl:call-template name="documentArrows">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>      
+ </xsl:template>
+
+  <xsl:template name="documentHeading">
+    <xsl:param name="collName"/>
+    <xsl:variable name="doCoverImage" select="/page/pageResponse/format/gsf:option[@name='coverImages']/@value"/>
+    <xsl:variable name="doTOC" select="/page/pageResponse/format/gsf:option[@name='documentTOC']/@value"/>
+    <xsl:variable name="p.a" select="/page/pageRequest/paramList/param[@name='p.a']/@value"/>
+    <xsl:variable name="p.sa" select="/page/pageRequest/paramList/param[@name='p.sa']/@value"/>
+    <xsl:variable name="p.s" select="/page/pageRequest/paramList/param[@name='p.s']/@value"/>
+    <xsl:variable name="p.c"><xsl:choose><xsl:when test="/page/pageRequest/paramList/param[@name='p.c']"><xsl:value-of select="/page/pageRequest/paramList/param[@name='p.c']/@value"/></xsl:when><xsl:otherwise><xsl:value-of select="$collName"/></xsl:otherwise></xsl:choose></xsl:variable>
+   <div id="documentheading">
+	  <a href="{$library_name}?a={$p.a}&amp;sa={$p.sa}&amp;s={$p.s}&amp;c={$p.c}&amp;rt=rd"><xsl:call-template name="openbookimg"><xsl:with-param name="title">Close this book and return to search/browse</xsl:with-param>
+	  </xsl:call-template></a>
+	     <xsl:choose><xsl:when test="@docType='simple'"><xsl:value-of select="metadataList/metadata[@name='Title']" disable-output-escaping="yes"/></xsl:when><xsl:otherwise><xsl:value-of select="documentNode/metadataList/metadata[@name='Title']" disable-output-escaping="yes"/></xsl:otherwise></xsl:choose>
+  </div>
+  
+ <div id="docheadwrapper">
+  <div id="documentinfo">
+    <xsl:if test="string($doCoverImage) != 'false' and (@docType='paged' or @docType='hierarchy')">
+       <div id="headingimage">
+         <xsl:call-template name="coverImage"/> 
+       </div>
+    </xsl:if>
+     
+     <ul id="docbuttons" >
+       <xsl:call-template name="documentButtons">
+	  <xsl:with-param name="collName" select="$collName"/>
+       </xsl:call-template>
+     </ul>
+  </div>
+    <!--<div><xsl:call-template name="enrichServices">
+	   <xsl:with-param name="collName" select="$collName"/>
+	  </xsl:call-template></div>-->
+     <xsl:if test="string($doTOC) != 'false'">
+       <div id="toc">
+	 <xsl:call-template name="TOC">
+	   <xsl:with-param name="collName" select="$collName"/>
+	 </xsl:call-template>
+       </div>
+      </xsl:if>
+      
+      </div>
+    </xsl:template>
+
+  <xsl:template name="coverImage">
+    <img><xsl:attribute name='src'><xsl:value-of select="/page/pageResponse/collection/metadataList/metadata[@name='httpPath']"/>/index/assoc/<xsl:value-of select="metadataList/metadata[@name='archivedir']"/>/cover.jpg</xsl:attribute></img>
+  </xsl:template>
+
+  <xsl:template name="documentButtons">
+    <xsl:param name="collName"/>
+    <xsl:variable name="docID" select="/page/pageRequest/paramList/param[@name='d']/@value"/>
+    <xsl:variable name="sib" select="/page/pageRequest/paramList/param[@name='sib']/@value"/>
+    <xsl:variable name="ec" select="/page/pageRequest/paramList/param[@name='ec']/@value"/>
+    <xsl:variable name="ed" select="/page/pageRequest/paramList/param[@name='ed']/@value"/>
+    
+   
+      <!-- expand document -->
+      <!-- this doesn't work with MG so comment it out for now -->
+      
+   <xsl:if test="@docType = 'hierarchy' or @docType = 'paged'">
+     <li>
+        <xsl:choose><xsl:when test="string($ed)='1'">
+	      <a href="{$library_name}?a=d&amp;d={$docID}&amp;c={$collName}&amp;sib={$sib}&amp;ed=0"><xsl:attribute name="title"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'doc.contract_doc_tip')"/></xsl:attribute>
+		  <xsl:value-of disable-output-escaping='yes' select="util:getInterfaceText($interface_name, /page/@lang, 'doc.contract_doc_b')"/>
+	      </a>
+	    </xsl:when>
+	    <xsl:otherwise>
+	  <a href="{$library_name}?a=d&amp;d={$docID}&amp;c={$collName}&amp;sib={$sib}&amp;ed=1"><xsl:attribute name="title"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'doc.expand_doc_tip')"/></xsl:attribute>
+	     <xsl:value-of disable-output-escaping='yes' select="util:getInterfaceText($interface_name, /page/@lang, 'doc.expand_doc_b')"/>
+	  </a>
+	    </xsl:otherwise>
+	  </xsl:choose>
+      	</li>
+      </xsl:if> 
+      
+      <!-- expand contents -->
+      <xsl:if test="@docType = 'hierarchy' and string(/page/pageResponse/format/gsf:option[@name='documentTOC']/@value) != 'false'">
+      <li>
+          <xsl:choose><xsl:when test="string($ec)='1'">
+	      <a href="{$library_name}?a=d&amp;d={$docID}&amp;c={$collName}&amp;sib={$sib}&amp;ec=0"><xsl:attribute name="title"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'doc.contract_contents_tip')"/></xsl:attribute>
+		<xsl:value-of disable-output-escaping='yes' select="util:getInterfaceText($interface_name, /page/@lang, 'doc.contract_contents_b')"/></a>
+	    </xsl:when>
+	    <xsl:otherwise>
+	      <a  href="{$library_name}?a=d&amp;d={$docID}&amp;c={$collName}&amp;sib={$sib}&amp;ec=1"><xsl:attribute name="title"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'doc.expand_contents_tip')"/></xsl:attribute>
+		 <xsl:value-of disable-output-escaping='yes' select="util:getInterfaceText($interface_name, /page/@lang, 'doc.expand_contents_b')"/>
+	      </a>
+	    </xsl:otherwise>
+	  </xsl:choose>
+	 </li>
+      </xsl:if>
+
+      <!-- detach page -->
+      <xsl:variable name="paramList" select="/page/pageRequest/paramList"/>
+       <li>
+	  <a target="_blank"><xsl:attribute name="href"><xsl:value-of select="$library_name"/>?a=d&amp;d=<xsl:value-of select="$docID"/>&amp;c=<xsl:value-of select="$collName"/>&amp;sib=<xsl:value-of select="$sib"/>&amp;dt=<xsl:value-of select="$paramList/param[@name='dt']/@value"/>&amp;ec=<xsl:value-of select="$paramList/param[@name='ec']/@value"/>&amp;et=<xsl:value-of select="$paramList/param[@name='et']/@value"/>&amp;p.a=<xsl:value-of select="$paramList/param[@name='p.a']/@value"/>&amp;p.s=<xsl:value-of select="$paramList/param[@name='p.s']/@value"/>&amp;p.sa=<xsl:value-of select="$paramList/param[@name='p.sa']/@value"/></xsl:attribute><xsl:attribute name="title"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'doc.detach_page_tip')"/></xsl:attribute>
+	    <xsl:value-of disable-output-escaping='yes' select="util:getInterfaceText($interface_name, /page/@lang, 'doc.detach_page_b')"/>
+	  </a></li>
+      </xsl:template>
+
+  <xsl:template name="TOC">
+    <xsl:param name="collName"/>
+    <xsl:choose>
+      <xsl:when test="@docType='hierarchy'">
+	<xsl:call-template name="hierarchicalContents">
+	  <xsl:with-param name="collName" select="$collName"/>
+	</xsl:call-template>
+      </xsl:when>
+      <xsl:when test="@docType='paged'">
+	<xsl:call-template name="pagedContents">
+	  <xsl:with-param name="collName" select="$collName"/>
+	</xsl:call-template>
+      </xsl:when>
+    </xsl:choose>
+  </xsl:template>
+    
+  <xsl:template name="hierarchicalContents">
+    <xsl:param name="collName"/>
+    <xsl:variable name="oc" select="/page/pageRequest/paramList/param[@name='oc']/@value"/>
+    <xsl:variable name="d" select="/page/pageRequest/paramList/param[@name='d']/@value"/>
+    <xsl:variable name="sib" select="/page/pageRequest/paramList/param[@name='sib']/@value"/>
+    <xsl:variable name="ec" select="/page/pageRequest/paramList/param[@name='ec']/@value"/>
+    <xsl:variable name="p.s" select="/page/pageRequest/paramList/param[@name='p.s']/@value"/>
+    <xsl:variable name="p.sa" select="/page/pageRequest/paramList/param[@name='p.sa']/@value"/>
+    <xsl:variable name="p.a" select="/page/pageRequest/paramList/param[@name='p.a']/@value"/>
+    <xsl:variable name="p.c"><xsl:choose><xsl:when test="/page/pageRequest/paramList/param[@name='p.c']"><xsl:value-of select="/page/pageRequest/paramList/param[@name='p.c']/@value"/></xsl:when><xsl:otherwise><xsl:value-of select="$collName"/></xsl:otherwise></xsl:choose></xsl:variable>
+    <xsl:if test="documentNode[@nodeID]">
+      <ul id="tocnodes">
+	<li>
+	    <xsl:choose><xsl:when test="string($oc)='0'">
+		<a href="{$library_name}?a=d&amp;c={$collName}&amp;d={$d}&amp;sib={$sib}&amp;oc=1"><xsl:call-template name="closedfolderimg"><xsl:with-param name="title">open the table of contents</xsl:with-param></xsl:call-template></a>
+	      </xsl:when>
+	      <xsl:otherwise><a href="{$library_name}?a=d&amp;c={$collName}&amp;d={$d}&amp;sib={$sib}&amp;oc=0"><xsl:call-template name="openfolderimg"><xsl:with-param name="title">close the table of contents</xsl:with-param></xsl:call-template></a></xsl:otherwise></xsl:choose>Table of Contents
+	<xsl:if test="string($oc)!='0'">
+           <ul class="tocnode">
+	    <xsl:for-each select="documentNode/documentNode[@nodeID]">
+		  <xsl:apply-templates select='.'><xsl:with-param name="collName" select="$collName"/><xsl:with-param name="ec" select="$ec"/><xsl:with-param name="p.a" select="$p.a"/><xsl:with-param name="p.s" select="$p.s"/><xsl:with-param name="p.sa" select="$p.sa"/><xsl:with-param name="p.c" select="$p.c"/></xsl:apply-templates>
+		</xsl:for-each>
+            </ul>
+	   </xsl:if>
+        </li> 
+      </ul>
+    </xsl:if>
+  </xsl:template>
+  
+  <!-- each icon-title pair is a row in a table. children go in a table in another row -->
+  <xsl:template match="documentNode">
+    <xsl:param name="collName"/>
+    <xsl:param name="ec"/>
+    <xsl:param name="p.a"/>
+    <xsl:param name="p.s"/>
+    <xsl:param name="p.sa"/>
+    <xsl:param name="p.c"/>
+    <!-- Display the appropriate image, depending on the node type -->
+     <li>
+	<a><xsl:attribute name="href"><xsl:value-of select='$library_name'/>?a=d&amp;c=<xsl:value-of select='$collName'/>&amp;d=<xsl:value-of select='@nodeID'/><xsl:if test="documentNode">.pr</xsl:if>&amp;sib=1<xsl:if test="string($ec) = '1'">&amp;ec=1</xsl:if>&amp;p.a=<xsl:value-of select="$p.a"/>&amp;p.sa=<xsl:value-of select="$p.sa"/>&amp;p.s=<xsl:value-of select="$p.s"/>&amp;p.c=<xsl:value-of select="$p.c"/></xsl:attribute>
+	  <xsl:apply-templates select="." mode="displayNodeIcon"/>
+	</a>
+      
+      <!-- Display associated title, bolded if the node has content -->
+	<xsl:choose>
+          <xsl:when test="nodeContent">
+	    <span class="bold"><xsl:value-of disable-output-escaping="yes" select="metadataList/metadata[@name='Title']"/></span>
+	  </xsl:when>
+	  <xsl:otherwise>
+	    <xsl:value-of disable-output-escaping="yes" select="metadataList/metadata[@name='Title']"/>
+	  </xsl:otherwise>
+	</xsl:choose>
+    <!-- Apply recursively to the children of this node -->
+    <xsl:if test="documentNode[@nodeID]">
+       <ul class="tocnode"> <xsl:apply-templates select="documentNode[@nodeID]">
+	      <xsl:with-param name="collName" select="$collName"/>
+	      <xsl:with-param name="ec" select="$ec"/>
+	      <xsl:with-param name="p.a" select="$p.a"/><xsl:with-param name="p.s" select="$p.s"/><xsl:with-param name="p.sa" select="$p.sa"/><xsl:with-param name="p.c" select="$p.c"/>
+	      <!--<xsl:with-param name="depth" select="$depth + 1"/>-->
+	    </xsl:apply-templates>
+       </ul>
+     </xsl:if>
+    </li>
+  </xsl:template>
+  
+  <!-- default content is to print the title and content of any documentNodes that have nodeContent -->
+  <xsl:template name="documentContent">
+   <div class="documenttext"> 
+    <xsl:choose>
+      <xsl:when test="@docType='simple'">
+	<xsl:apply-templates select="nodeContent"/>
+      </xsl:when>
+      <xsl:otherwise>
+	<xsl:apply-templates select="descendant-or-self::node()/documentNode" mode="content"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </div>
+  </xsl:template>
+  
+  <xsl:template match="documentNode" mode="content">
+    <xsl:if test="nodeContent">
+      <xsl:if test="metadataList/metadata[@name='Title']">
+	<h3><xsl:value-of disable-output-escaping="yes" select="metadataList/metadata[@name='Title']"/></h3>
+      </xsl:if>
+      <xsl:apply-templates select="nodeContent"/>
+    </xsl:if>
+  </xsl:template>
+
+  <!-- the actual text/content -->
+  <xsl:template match="nodeContent">
+    <p/>
+    <xsl:for-each select="node()">
+      <xsl:choose>
+	<xsl:when test="not(name())"><xsl:value-of select="." disable-output-escaping="yes"/></xsl:when>
+	<xsl:otherwise><xsl:apply-templates select="."/></xsl:otherwise>
+      </xsl:choose>
+    </xsl:for-each>
+  </xsl:template>
+  
+  <!-- match any file nodes -->
+  <xsl:template match="file">
+    <xsl:variable name="httpPath" select="/page/pageResponse/collection/metadataList/metadata[@name='httpPath']"/>
+    <xsl:choose>
+      <xsl:when test="util:isImage(@mimeType)">
+	<img src="{$httpPath}/{@href}"/>
+      </xsl:when>
+      <xsl:otherwise>
+	<a href="{$httpPath}/{@href}"><xsl:value-of select="@href"/></a>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  
+  <!-- match any link nodes -->
+  <xsl:template match="link">
+    <xsl:variable name="collName" select="/page/pageRequest/paramList/param[@name='c']/@value"/> 
+    <xsl:variable name="actionargs">
+      <xsl:choose>
+	<xsl:when test="@type='document'">a=d</xsl:when>
+	<xsl:when test="@type='query'">a=q&amp;s=<xsl:value-of select="@service"/>&amp;rt=rd</xsl:when>
+	<xsl:otherwise>
+	  p
+	</xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <xsl:variable name="serviceargs">
+      <xsl:for-each select="param">&amp;s1.<xsl:value-of select="@name"/>=<xsl:value-of select="@value"/></xsl:for-each>
+  </xsl:variable>
+    <a href="{$library_name}?{$actionargs}&amp;c={$collName}{$serviceargs}"><xsl:value-of disable-output-escaping="yes" select="."/></a>
+  </xsl:template>
+
+  <!-- match any annotations and make them span elements -->
+  <xsl:template match="annotation">
+    <span class="{@type}"><xsl:value-of disable-output-escaping="yes" select="."/></span>
+  </xsl:template>
+  
+  <!-- paged naviagtion : INCOMPLETE!!-->
+  <xsl:template name="pagedContents">
+    <xsl:param name="collName"/>
+    <xsl:variable name="pos" select="nodeStructureInfo/info[@name='siblingPosition']/@value"/>
+    <xsl:variable name="length" select="nodeStructureInfo/info[@name='numSiblings']/@value"/>
+    <xsl:variable name="children" select="nodeStructureInfo/info[@name='numChildren']/@value"/>
+    <table>
+      <xsl:choose>
+	<xsl:when test="$pos=-1"><!-- a doc -->
+	  <tr valign="top">
+	    <td align="left">
+	    </td>
+	    <td align="center"><center>
+		<b><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'document.pages', $children)"/></b>
+	      </center></td>
+	    <td align="right">
+	      <a href="{$library_name}?a=d&amp;c={$collName}&amp;d={@selectedNode}.fc"><img src="interfaces/default/images/more.gif" border="0" align="absbottom" /></a>
+	    </td>
+	  </tr>
+	</xsl:when>
+	
+	<xsl:otherwise> <!-- an internal node -->	  
+	  <tr valign="top">
+	    <td align="left">
+	      <xsl:if test=" not ( $pos = 1 )">
+		<a href="{$library_name}?a=d&amp;c={$collName}&amp;d={@selectedNode}.ps"><img src="interfaces/default/images/less.gif" border="0" align="absbottom" /></a>
+	      </xsl:if>
+	    </td>
+	    <td align="center"><center>
+		<b><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'document.pageof', concat($pos, ';', $length))"/></b>
+	      </center></td>
+	    <td align="right">
+	      <xsl:if test=" not($pos = $length)">
+		<a href="{$library_name}?a=d&amp;c={$collName}&amp;d={@selectedNode}.ns"><img src="interfaces/default/images/more.gif" border="0" align="absbottom" /></a>
+	      </xsl:if>
+	    </td>
+	  </tr>
+	</xsl:otherwise>
+      </xsl:choose>
+      <tr valign="middle">
+	<td align='center' valign='top' colspan='3'>
+	  <form name="GotoForm" method="get" action="{$library_name}">
+	    <input type='hidden' name='a' value='d'/>
+	    <input type='hidden' name='c' value='{$collName}'/>
+	    <input type='hidden' name='d' value='{@selectedNode}'/>
+	    <input type="text" name="gp" size="3" maxlength="4"/>
+	    <input type="submit"><xsl:attribute name='value'><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'document.gotopage')"/></xsl:attribute></input>
+	  </form>
+	</td>
+      </tr>
+    </table>
+  </xsl:template>
+  
+  <xsl:template name="enrichServices">
+    <xsl:param name="collName"/>
+    <xsl:variable name="docID" select="/page/pageRequest/paramList/param[@name='d']/@value"/>
+    <xsl:variable name="request-params" select="/page/pageRequest/paramList"/>
+    <xsl:for-each select="../serviceList/service">
+      <table border='1' cellspacing='0'>
+	<tr><td>
+	    <p /><xsl:value-of select="displayItem[@name='name']"/><p/>
+	    <form name="EnrichForm" method="get" action="{$library_name}">
+	      <xsl:apply-templates select="paramList"/>
+	      <input type='hidden' name='a' value='d'/>
+	      <input type='hidden' name='d' value='{$docID}'/>
+	      <input type='hidden' name='c' value='{$collName}'/>
+	      <xsl:if test='$request-params/param[@name="sib"]'>
+		<input type='hidden' name='sib'><xsl:attribute name='value'><xsl:value-of select='$request-params/param[@name="sib"]/@value'/></xsl:attribute></input></xsl:if>
+	      <input type='hidden' name='s' value='{@name}'/>
+	      <input type='hidden' name='p.a'><xsl:attribute name='value'><xsl:value-of select='$request-params/param[@name="p.a"]'/></xsl:attribute></input>
+	      <input type='hidden' name='p.sa'><xsl:attribute name='value'><xsl:value-of select='$request-params/param[@name="p.sa"]'/></xsl:attribute></input>
+	      <input type='hidden' name='p.s'><xsl:attribute name='value'><xsl:value-of select='$request-params/param[@name="p.s"]'/></xsl:attribute></input>
+	      <input type='hidden' name='end' value='1'/>
+	      <input type="submit"><xsl:attribute name="value"><xsl:value-of select="displayItem[@name='submit']"/></xsl:attribute></input>
+	    </form>
+	  </td></tr>
+      </table>
+    </xsl:for-each>
+  </xsl:template>
+
+  <xsl:template match="paramList" mode="hidden">
+    <xsl:for-each select="param">
+      <input type='hidden' name='{@name}' value='{@value}'/><xsl:text>
+      </xsl:text>
+    </xsl:for-each>
+  </xsl:template>
+  
+  <xsl:template name="documentArrows">
+    <xsl:param name="collName"/>
+    <div class="documentarrows">
+       <xsl:call-template name="documentArrow">
+        <xsl:with-param name="collName" select="$collName"/>
+       <xsl:with-param name="direction">back</xsl:with-param>
+     </xsl:call-template>
+    <xsl:call-template name="documentArrow">
+      <xsl:with-param name="collName" select="$collName"/>
+      <xsl:with-param name="direction">forward</xsl:with-param>
+    </xsl:call-template>
+    </div>
+    
+  </xsl:template>
+  
+  <xsl:template name="documentArrow">
+    <xsl:param name="collName"/>
+    <xsl:param name="direction"/>
+    <xsl:variable name="request-params" select="/page/pageRequest/paramList"/>
+    <xsl:if test='$request-params/param[@name="dt"]/@value != "simple"'>  
+    <a><xsl:attribute name="href"><xsl:value-of select="$library_name"/>?a=d&amp;c=<xsl:value-of select="$collName"/>&amp;d=<xsl:value-of select="@selectedNode"/><xsl:choose><xsl:when test="$direction='back'">.pp</xsl:when><xsl:otherwise>.np</xsl:otherwise></xsl:choose>&amp;sib=1&amp;p.s=<xsl:value-of select='$request-params/param[@name="p.s"]/@value'/>&amp;p.sa=<xsl:value-of select='$request-params/param[@name="p.sa"]/@value'/>&amp;p.a=<xsl:value-of select='$request-params/param[@name="p.a"]/@value'/></xsl:attribute><xsl:choose><xsl:when test="$direction='back'"><img class="lessarrow" src="interfaces/default/images/less.gif" /></xsl:when><xsl:otherwise><img class="morearrow" src="interfaces/default/images/more.gif"  /></xsl:otherwise></xsl:choose></a>
+    </xsl:if> 
+  </xsl:template>
+</xsl:stylesheet>
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/help.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/help.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/help.xsl	(revision 13928)
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+  
+   <!-- style includes global params interface_name, library_name -->
+  <xsl:include href="style.xsl"/>
+
+  <xsl:output method="html"/>  
+  
+  <xsl:template name="pageTitle">
+    <xsl:choose><xsl:when test="/page/pageResponse/*/displayItem[@name='name']"><xsl:value-of select="/page/pageResponse/*/displayItem[@name='name']"/></xsl:when><xsl:otherwise><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'gsdl')"/></xsl:otherwise></xsl:choose>: <xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'help_t')"/>
+  </xsl:template>
+
+  <!-- page specific style goes here -->
+  <xsl:template name="pageStyle"/>
+
+
+  <xsl:template match="pageResponse">
+    <xsl:variable name="collName" select="/page/pageRequest/paramList/param[@name='c']/@value"/>
+    <xsl:call-template name="standardPageBanner">
+      <xsl:with-param name="collName" select="$collName"/>
+      <xsl:with-param name="pageType">help</xsl:with-param>
+    </xsl:call-template>
+    <xsl:call-template name="navigationBar">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>      
+    
+    some help text goes here
+  </xsl:template>
+ 
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/home.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/home.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/home.xsl	(revision 13928)
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+
+  <!-- style includes global params interface_name, library_name -->
+  <xsl:include href="style.xsl"/>
+
+  <xsl:output method="html"/>  
+
+  <xsl:template name="pageTitle">
+    <xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'gsdl')"/>
+  </xsl:template>
+
+  <!-- page specific style goes here -->
+  <xsl:template name="pageStyle"/>
+
+  <xsl:template match="pageResponse">
+    <xsl:call-template name="greenstonePageBanner"/> 
+    <xsl:apply-templates select="serviceList/service[@name='TextQuery']"/>
+    <xsl:apply-templates select="collectionList"/>   
+    <xsl:apply-templates select="serviceClusterList"/>
+    <xsl:apply-templates select="serviceList"/>
+  </xsl:template>
+
+  <xsl:template match="collectionList">
+   <ul id="collectionlist">
+    <xsl:for-each select="collection"> 
+      <li>
+      
+           <xsl:choose>
+              <xsl:when test="displayItem[@name='icon']">
+              <a href="{$library_name}?a=p&amp;sa=about&amp;c={@name}">
+                <img>
+	           <xsl:attribute name="src">
+	             <xsl:value-of select="metadataList/metadata[@name='httpPath']"/>/images/<xsl:value-of select="displayItem[@name='icon']"/>
+	           </xsl:attribute>
+	           <xsl:attribute name="alt">
+	                <xsl:value-of select="displayItem[@name='name']"/>
+	           </xsl:attribute>
+	         </img> 
+               </a>  
+	      </xsl:when>
+              <xsl:otherwise>
+               <a class="noimage" href="{$library_name}?a=p&amp;sa=about&amp;c={@name}">  
+                 <xsl:value-of select="displayItem[@name='name']"/>
+               </a>
+              </xsl:otherwise>
+           </xsl:choose>         
+	 
+       </li>
+    </xsl:for-each> 
+   </ul>
+  </xsl:template> 
+  
+  <xsl:template match="serviceClusterList">
+    <xsl:for-each select="serviceCluster"> 
+      <a href="{$library_name}?a=p&amp;sa=about&amp;c={@name}"><xsl:value-of select='@name'/><xsl:value-of select="displayItem[@name='name']"/></a>
+    </xsl:for-each>
+  </xsl:template>
+
+  <xsl:template match="service[@name='TextQuery']">
+    <div class="QuickSearch">
+      <form name="QuickSearch" method="get" action="{$library_name}">
+	<input type="hidden" name="a" value="q"/>
+	<input type="hidden" name="rt" value="rd"/>
+	<input type="hidden" name="s" value="{@name}"/>
+	<input type="hidden" name="s1.collection" value="all"/>
+	<input type="text" name="s1.query" size="20"/>
+	<input type="submit" value="Quick Search"/>
+      </form>
+    </div>
+  </xsl:template>
+
+  <xsl:template match="serviceList">
+    <xsl:call-template name="dividerBar"/>
+    <ul id="servicelist">
+    <xsl:for-each select="service[@type='query']">
+      <li><a href="{$library_name}?a=q&amp;rt=d&amp;s={@name}"><xsl:value-of select="displayItem[@name='name']"/></a><xsl:value-of select="displayItem[@name='description']"/></li>
+      </xsl:for-each>
+    </ul>
+    </xsl:template>
+</xsl:stylesheet>  
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/html.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/html.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/html.xsl	(revision 13928)
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+  
+  <xsl:output method="html"/>  
+
+  <xsl:template match="page">
+    <html>
+      <head></head>
+      <frameset rows="68,*" noresize="" border="0">
+	<frame frameborder="0"><xsl:attribute name="src">?a=p&amp;sa=nav&amp;c=<xsl:value-of select="/page/pageRequest/paramList/param[@name='c']/@value" /></xsl:attribute></frame>
+	<frame frameborder="0"><xsl:attribute name="src"><xsl:value-of select="/page/pageRequest/paramList/param[@name='url']/@value"/></xsl:attribute></frame>
+	<noframes>
+	  <p><xsl:value-of select="util:getInterfaceText('default', /page/@lang, 'textframebrowser')"/></p>
+	</noframes>
+      </frameset>
+    </html>
+  </xsl:template>
+
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/nav.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/nav.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/nav.xsl	(revision 13928)
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+  
+   <!-- style includes global params interface_name, library_name -->
+  <xsl:include href="style.xsl"/>
+
+  <xsl:output method="html"/>  
+  
+  <xsl:template match="page">
+    <html>
+      <head>
+	<title>
+	  <xsl:call-template name="pageTitle"/><xsl:text> </xsl:text>
+	</title>
+	<xsl:call-template name="globalStyle"/>
+	<base target="_top"/>
+      </head>
+      <body style="background-image: none;">
+	<xsl:apply-templates select="pageResponse"/>
+      </body>
+    </html>
+  </xsl:template>
+
+  <xsl:template name="pageTitle">
+    <xsl:value-of select="/page/pageResponse/*/displayItem[@name='name']"/>
+  </xsl:template>
+
+  <xsl:template match="pageResponse">
+    <xsl:variable name="collName" select="/page/pageRequest/paramList/param[@name='c']/@value"/>
+    <div align="right">
+    <xsl:call-template name="top-buttons">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>
+      </div>
+    <xsl:call-template name="navigationBar">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>      
+  </xsl:template>
+
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/pref.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/pref.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/pref.xsl	(revision 13928)
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+  
+   <!-- style includes global params interface_name, library_name -->
+  <xsl:include href="style.xsl"/>
+
+  <xsl:output method="html"/>  
+  
+  <xsl:template name="pageTitle">
+    <xsl:choose><xsl:when test="/page/pageResponse/*/displayItem[@name='name']"><xsl:value-of select="/page/pageResponse/*/displayItem[@name='name']"/></xsl:when><xsl:otherwise><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'gsdl')"/></xsl:otherwise></xsl:choose>: <xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'pref_t')"/>
+  </xsl:template>
+
+  <!-- page specific style goes here -->
+  <xsl:template name="pageStyle"/>
+
+
+  <xsl:template match="pageResponse">
+    <xsl:variable name="collName" select="/page/pageRequest/paramList/param[@name='c']/@value"/>
+    <xsl:call-template name="standardPageBanner">
+      <xsl:with-param name="collName" select="$collName"/>
+      <xsl:with-param name="pageType">pref</xsl:with-param>
+    </xsl:call-template>
+
+    <xsl:call-template name="navigationBar">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>      
+    <div id="qureyform">
+    <form name="PrefForm" method="get" action="{$library_name}">
+      <input type='hidden' name='a' value='p'/>
+      <input type='hidden' name='sa' value='pref'/>
+      <input type='hidden' name='c' value="{$collName}"/>
+      <div class="formheading"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'pref.prespref')"/></div>
+      <ul id="presprefs"><xsl:call-template name="pres-prefs"/></ul>
+      <ul id="berrybasketprefs" ><xsl:call-template name="berrybasket-prefs"/></ul>
+      <div class="formheading"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'pref.searchpref')"/></div>
+      <ul id="searchprefs"><xsl:call-template name="search-prefs"/></ul>
+      <input type='submit'><xsl:attribute name="value"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'pref.set_prefs')"/></xsl:attribute></input>
+       </form>
+   </div>
+  </xsl:template>
+  
+  <xsl:template name="pres-prefs">
+     <li><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'pref.interfacelang')"/> <xsl:call-template name="lang-list"/></li>
+      <li><span class="rightspace"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'pref.encoding')"/></span>x</li>
+    </xsl:template>
+ 
+  <xsl:template name="lang-list">
+    <xsl:variable name="current" select="/page/@lang"/>
+    <select name="l">
+      <xsl:for-each select="/page/pageResponse/languageList/language">
+	<option value="{@name}"><xsl:if test="@name=$current"><xsl:attribute name="selected"></xsl:attribute></xsl:if><xsl:value-of select="displayItem[@name='name']"/></option>
+      </xsl:for-each>
+    </select>
+  </xsl:template>
+  
+  <xsl:template name="search-prefs">
+    <xsl:variable name="hits"><xsl:choose><xsl:when test="/page/pageRequest/paramList/param[@name='hitsPerPage']"><xsl:value-of select="/page/pageRequest/paramList/param[@name='hitsPerPage']/@value"/></xsl:when><xsl:otherwise>20</xsl:otherwise></xsl:choose></xsl:variable> 
+    <li><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'pref.hitsperpage')"/> 
+          <select name="hitsPerPage">
+	    <option value="20"><xsl:if test="$hits=20"><xsl:attribute name="selected"></xsl:attribute></xsl:if>20</option> 
+	    <option value="50"><xsl:if test="$hits=50"><xsl:attribute name="selected"></xsl:attribute></xsl:if>50</option>
+	    <option value="100"><xsl:if test="$hits=100"><xsl:attribute name="selected"></xsl:attribute></xsl:if>100</option>
+	    <option value="-1"><xsl:if test="$hits=-1"><xsl:attribute name="selected"></xsl:attribute></xsl:if><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'pref.all')"/></option>
+	  </select>
+    </li>
+  </xsl:template>
+
+ <xsl:template name="berrybasket-prefs">
+      <xsl:variable name="berrybasket"><xsl:choose><xsl:when test="/page/pageRequest/paramList/param[@name='berrybasket']"><xsl:value-of select="/page/pageRequest/paramList/param[@name='berrybasket']/@value"/></xsl:when><xsl:otherwise>off</xsl:otherwise></xsl:choose></xsl:variable>
+     
+    <li><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'pref.berrybasket')"/> <select name="berrybasket">
+        <option value="on"><xsl:if test="$berrybasket='on'"><xsl:attribute name="selected"></xsl:attribute></xsl:if><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'pref.berrybasket.on')"/></option> 
+	<option value="off"><xsl:if test="$berrybasket='off'"><xsl:attribute name="selected"></xsl:attribute></xsl:if><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'pref.berrybasket.off')"/></option>
+      </select>
+    </li>
+  </xsl:template>
+
+
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/process.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/process.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/process.xsl	(revision 13928)
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+
+  <xsl:include href="style.xsl"/>
+  <xsl:include href="service-params.xsl"/>
+
+  <xsl:output method="html"/>  
+
+  <xsl:template name="pageTitle">
+    <xsl:value-of select="/page/pageResponse/serviceCluster/metadataList/metadata[@name='Title']"/>
+  </xsl:template>
+
+  <!-- page specific style goes here -->
+  <xsl:template name="pageStyle"/>
+
+
+  <xsl:template match="pageResponse">
+    <xsl:variable name="clusterName"><xsl:value-of select="/page/pageRequest/paramList/param[@name='c']/@value"/></xsl:variable>
+    <center>
+      <xsl:call-template name="standardPageBanner">
+	<xsl:with-param name="collName" select="$clusterName"/>
+      </xsl:call-template>
+      <xsl:call-template name="navigationBar">
+	<xsl:with-param name="collName" select="$clusterName"/>
+      </xsl:call-template>      
+      <xsl:apply-templates select="service">
+	<xsl:with-param name="clusterName" select="$clusterName"/>
+      </xsl:apply-templates>
+      <xsl:apply-templates select="status">
+	<xsl:with-param name="clusterName" select="$clusterName"/>
+      </xsl:apply-templates>
+    </center>
+  </xsl:template>
+
+  <xsl:template match="service">
+    <xsl:param name="clusterName"/>
+    <xsl:variable name='subaction' select="/page/pageRequest/@subaction"/>
+    <xsl:variable name='action' select="/page/pageRequest/@action"/>
+    <xsl:variable name='lang' select="/page/@lang"/>
+    <p/>
+    <form name="BuildForm" method="get" action="{$library_name}">
+      <xsl:apply-templates select="paramList"/>
+      <input type="hidden" name="a" value="{$action}"/>
+      <input type="hidden" name="c" value="{$clusterName}"/>
+      <input type="hidden" name="sa" value="p"/>
+      <input type="hidden" name='l' value='{$lang}'/>
+      <input type="hidden" name="s" value="{@name}"/>
+      <input type="hidden" name="rt" value="r"/>
+      <input type="submit"><xsl:attribute name="value"><xsl:value-of select="displayItem[@name='submit']"/></xsl:attribute></input>
+    </form>
+    <xsl:call-template name="dividerBar"/>
+  </xsl:template>
+  
+  <xsl:template match="status">
+    <xsl:param name="clusterName"/>
+    <center/>
+    <applet code="org.greenstone.gsdl3.build.StatusDisplay.class" codebase='lib' archive='gsdl3.jar, xercesImpl.jar, xml-apis.jar' width='600' height='150'>The status display applet.
+      <param name='library'><xsl:attribute name="value"><xsl:value-of select='$library_name'/>?a=pr&amp;rt=s&amp;c=<xsl:value-of select='$clusterName'/>&amp;s=<xsl:value-of select='/page/pageResponse/service/@name'/>&amp;o=xml&amp;ro=1&amp;l=<xsl:value-of select='/page/@lang'/>&amp;pid=<xsl:value-of select="@pid"/><xsl:apply-templates select="/page/pageResponse/service/paramList" mode="cgi"/></xsl:attribute></param>
+      <param name='initial_text'><xsl:attribute name="value"><xsl:value-of select="."/></xsl:attribute></param>
+      <param name='initial_code'><xsl:attribute name="value"><xsl:value-of  select="@code"/></xsl:attribute></param></applet>
+    <xsl:call-template name="dividerBar"/>
+  </xsl:template>
+
+  
+</xsl:stylesheet>  
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/query.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/query.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/query.xsl	(revision 13928)
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+  
+  <!-- style includes global params interface_name, library_name -->
+  <xsl:include href="style.xsl"/>
+  <xsl:include href="service-params.xsl"/>
+  <xsl:include href="querytools.xsl"/>
+  <xsl:include href="berrytools.xsl"/>
+
+  <xsl:output method="html"/>
+
+   <xsl:variable name="berrybasketswitch"><xsl:value-of select="/page/pageRequest/paramList/param[@name='berrybasket']/@value"/></xsl:variable> 
+
+  <xsl:template name="pageTitle">
+    <xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'gsdl')"/>
+  </xsl:template>
+
+  <!-- page specific style goes here -->
+  <xsl:template name="pageStyle">     	
+    <!--<xsl:if test="$berryBaskets = 'true'">-->
+    <xsl:if test="$berrybasketswitch = 'on'">
+      <xsl:call-template name="berryStyleSheet"/>
+      <xsl:call-template name="js-library"/>
+    </xsl:if>
+  </xsl:template>
+  
+
+  <xsl:template match="pageResponse">
+    <xsl:variable name="collName"><xsl:value-of select="/page/pageRequest/paramList/param[@name='c']/@value"/></xsl:variable> 
+    <xsl:call-template name="standardPageBanner">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>
+    <xsl:call-template name="navigationBar">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template> 
+    <div id="content">
+    <xsl:apply-templates select="service">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:apply-templates>
+   
+    <!--<xsl:if test="$berryBaskets = 'true'">-->
+    <xsl:if test="$berrybasketswitch = 'on'">
+      <xsl:call-template name="berrybasket"/>
+    </xsl:if>
+    <xsl:if test="documentNodeList">
+      <xsl:call-template name="query-response">
+	<xsl:with-param name="collName" select="$collName"/>
+      </xsl:call-template>
+    </xsl:if>
+    </div>
+   </xsl:template>
+
+
+  <!-- layout the response -->
+  <xsl:template name="query-response">
+    <xsl:param name="collName"/>
+    <xsl:call-template name="dividerBar"><xsl:with-param name='text'><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'query.results')"/></xsl:with-param></xsl:call-template>
+    
+    <!-- If query term information is available, display it -->
+    <xsl:call-template name="termInfo"/>
+    <xsl:call-template name="matchDocs"/>
+    
+     <!-- next and prev links at top of results-->
+   
+    <xsl:call-template name="resultNavigation">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>
+   
+    <!-- Display the matching documents -->  
+   
+    <xsl:call-template name="resultList">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>
+    
+    <!-- next and prev links at bottom of page -->
+    <xsl:call-template name="resultNavigation">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>
+
+  </xsl:template>
+  
+
+  <xsl:template match="service">
+    <xsl:param name="collName"/>
+    <xsl:variable name="subaction" select="../pageRequest/@subaction"/>
+    <div id="queryform">
+    <form name="QueryForm" method="get" action="{$library_name}">
+      <input type="hidden" name="a" value="q"/>
+      <input type="hidden" name="sa" value="{$subaction}"/>
+      <input type="hidden" name="rt" value="rd"/>
+      <input type="hidden" name="s" value="{@name}"/>
+      <input type="hidden" name="c" value="{$collName}"/>
+      <xsl:if test="not(paramList/param[@name='startPage'])">
+	<input type="hidden" name="startPage" value="1"/>
+      </xsl:if>
+      <xsl:apply-templates select="paramList"/>
+      <input type="submit"><xsl:attribute name="value"><xsl:value-of select="displayItem[@name='submit']"/></xsl:attribute></input>
+    </form>
+    </div>
+  </xsl:template>
+   
+</xsl:stylesheet>  
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/querytools.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/querytools.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/querytools.xsl	(revision 13928)
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+
+  <!-- have changed this so it uses service hitsPerPage and startPage if the service description has a param called hitsPerPage,  otherwise uses interface ones -->
+  <xsl:template name="resultNavigation">
+    <xsl:param name="collName"/>
+   <div class="resultnavigation">  
+  <!-- hits type -->
+    <xsl:variable name='ht'>
+      <xsl:choose>
+	<xsl:when test="/page/pageResponse/service/paramList/param[@name='hitsPerPage']">s</xsl:when>
+	<xsl:otherwise>i</xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    
+    <xsl:variable name="param-list" select="/page/pageRequest/paramList"/>
+    <!-- hits per page -->
+    <xsl:variable name="hpp">
+      <xsl:choose>
+	<xsl:when test="$ht='s'"><xsl:value-of select="$param-list/param[@name='s1.hitsPerPage']/@value"/></xsl:when>
+	<xsl:when test="$param-list/param[@name='hitsPerPage']"><xsl:value-of select="$param-list/param[@name='hitsPerPage']/@value"/></xsl:when>
+	<xsl:otherwise>20</xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <!-- total docs - this may be in numDocsMatched or numDocsReturned metadata -->
+    <xsl:variable name="td">
+      <xsl:choose>
+	<xsl:when test="/page/pageResponse/metadataList/metadata[@name='numDocsReturned']">
+	  <xsl:value-of select="/page/pageResponse/metadataList/metadata[@name='numDocsReturned']"/>
+	</xsl:when>
+	<xsl:when test="/page/pageResponse/metadataList/metadata[@name='numDocsMatched']">
+	  <xsl:value-of select="/page/pageResponse/metadataList/metadata[@name='numDocsMatched']"/>
+	</xsl:when>
+	<xsl:otherwise> <!-- this is just a fall back - shoudl always have the metadata -->
+	  <xsl:value-of select="count(/page/pageResponse/documentNodeList/documentNode)"/>
+	</xsl:otherwise>	
+      </xsl:choose>
+    </xsl:variable>
+
+    <!-- only continue if hpp != -1 and td > hpp -->
+    <xsl:if test="not($hpp=-1) and $td &gt; $hpp">
+      <!-- start page -->
+      <xsl:variable name="here">
+	<xsl:choose>
+	  <xsl:when test="$ht='s'"><xsl:value-of select="$param-list/param[@name='s1.startPage']/@value"/></xsl:when>
+	  <xsl:when test="$param-list/param[@name='startPage']"><xsl:value-of select="$param-list/param[@name='startPage']/@value"/></xsl:when>
+	  <xsl:otherwise>1</xsl:otherwise>
+	</xsl:choose>
+      </xsl:variable>
+      <xsl:variable name="sa" select="/page/pageRequest/@subaction"/>
+      <xsl:variable name="service" select="$param-list/param[@name='s']/@value"/>
+      <xsl:variable name="prev" select="$here - 1"/>
+      <xsl:variable name="next" select="$here + 1"/>
+      <xsl:variable name="page-param"><xsl:if test="$ht='s'">s1.</xsl:if>startPage</xsl:variable>
+     
+      <div>   
+	  <div>
+	     <xsl:if test="$here &gt; 1"><a href="{$library_name}?a=q&amp;sa={$sa}&amp;c={$collName}&amp;s={$service}&amp;rt=rd&amp;{$page-param}={$prev}"><img src="interfaces/default/images/less.gif" width='30' height='16' border='0' align='top'/><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'query.matches')"/><xsl:text> </xsl:text><xsl:value-of select="number(($prev - 1)*$hpp + 1)"/> - <xsl:value-of select="number(($prev * $hpp))"/></a></xsl:if>
+	   
+	   
+	      <xsl:if test="(($here * $hpp) + 1)  &lt; $td">
+		<xsl:variable name='m' select="number($next * $hpp)"/>
+		<xsl:variable name='mm'><xsl:choose><xsl:when test="$m &lt; $td"><xsl:value-of select='$m'/></xsl:when><xsl:otherwise><xsl:value-of select='$td'/></xsl:otherwise></xsl:choose></xsl:variable>
+		<a href="{$library_name}?a=q&amp;sa={$sa}&amp;c={$collName}&amp;s={$service}&amp;rt=rd&amp;{$page-param}={$next}"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'query.matches')"/><xsl:text> </xsl:text><xsl:value-of select="number(($next - 1)*$hpp + 1)"/> - <xsl:value-of select="$mm"/><img src="interfaces/default/images/more.gif" width='30' height='16' border='0' align='top'/></a></xsl:if></div>
+	</div>
+     </xsl:if>
+   </div>
+  </xsl:template>
+    
+  <xsl:template name="matchDocs">
+    <!-- If the number of matching documents is known, display it -->
+    <div id="matchdocs">
+    <xsl:variable name="numDocsMatched" select="metadataList/metadata[@name='numDocsMatched']"/>
+    <xsl:variable name="numDocsReturned" select="metadataList/metadata[@name='numDocsReturned']"/>
+    <xsl:choose>
+      <xsl:when test="$numDocsMatched='0' or $numDocsReturned='0'">
+	<xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'query.nodocsmatch')"/>
+      </xsl:when>
+      <xsl:when test="$numDocsMatched='1' or $numDocsReturned='1'">
+	<xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'query.onedocsmatch')"/>
+      </xsl:when>
+      <xsl:when test="$numDocsMatched">
+	<xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'query.manydocsmatch', $numDocsMatched)"/>
+	<xsl:if test="$numDocsReturned"> (<xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'query.docsreturned', $numDocsReturned)"/>)</xsl:if>
+      </xsl:when>
+      <xsl:when test="$numDocsReturned">
+	<xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'query.atleastdocsmatch', $numDocsReturned)"/>
+      </xsl:when>
+    </xsl:choose>
+   </div>
+  </xsl:template>
+
+  <!-- paging is now done by the query action, so here we just print out all the docs that we have -->
+  <xsl:template name="resultList">
+     <xsl:param name="collName"/>
+    <ul id="resultlist"> 
+     <xsl:for-each select="documentNodeList/documentNode">
+	<li><table>
+	  <xsl:call-template name="documentNodeWrapper">
+	    <xsl:with-param name="collName" select="$collName"/>
+	    <xsl:with-param name="serviceName" select="/page/pageResponse/service/@name"/>
+	  </xsl:call-template>
+            </table>
+	</li>	    
+      </xsl:for-each>  
+    </ul>
+  </xsl:template>
+  
+  <!-- this is a wrapper node, which the interface can use to add stuff into the query results that isn't part of and doesn't depend on the documentNode template which may come from the collection -->
+  <xsl:template name="documentNodeWrapper">
+    <xsl:param name="collName"/>
+    <xsl:param name="serviceName"/>
+    <xsl:variable name="berrybasketswitch"><xsl:value-of select="/page/pageRequest/paramList/param[@name='berrybasket']/@value"/></xsl:variable>
+    <!--<xsl:if test="$berryBaskets = 'true'">-->
+      <xsl:if test="$berrybasketswitch = 'on'">
+      <xsl:call-template name="addBerry">
+	<xsl:with-param name="collName" select="$collName"/>
+      </xsl:call-template>
+    </xsl:if>
+    <xsl:apply-templates select=".">
+      <xsl:with-param name="collName" select="$collName"/>
+      <xsl:with-param name="serviceName" select="$serviceName"/>
+    </xsl:apply-templates>
+  </xsl:template>
+
+  
+  <!-- the default doc node template for the query results -->
+  <!-- eventually shouldn't need sib arg here -->
+  <xsl:template match="documentNode">
+    <xsl:param name="collName"/>
+    <xsl:param name="serviceName"/>
+     <a><xsl:attribute name="href"><xsl:value-of select='$library_name'/>?a=d&amp;c=<xsl:value-of select='$collName'/>&amp;d=<xsl:value-of select='@nodeID'/><xsl:if test="@nodeType='leaf'">&amp;sib=1</xsl:if>&amp;dt=<xsl:value-of select='@docType'/>&amp;p.a=q&amp;&amp;p.sa=<xsl:value-of select="/page/pageRequest/@subaction"/>&amp;p.s=<xsl:value-of select="$serviceName"/></xsl:attribute>
+	<xsl:apply-templates select="." mode="displayNodeIcon"/>
+      </a>
+    <span><xsl:value-of disable-output-escaping="yes" select="metadataList/metadata[@name='Title']"/></span>
+  </xsl:template>
+
+  <xsl:template name="termInfo">
+   <div class="terminfo">
+    <xsl:if test="count(termList/term) > 0">
+     <xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'query.wordcount')"/>
+	<xsl:for-each select="termList/term">
+	  <xsl:if test="position() > 1">, </xsl:if>
+	  <xsl:value-of select="@name"/>: <xsl:value-of select="@freq"/> 
+	</xsl:for-each>
+    </xsl:if>
+  </div>
+  </xsl:template>
+
+</xsl:stylesheet>
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/service-params.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/service-params.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/service-params.xsl	(revision 13928)
@@ -0,0 +1,188 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  extension-element-prefixes="java">
+
+<!-- handling of the different types of params on a service form 
+  - these now only output the selection box/text box etc, not the name -->
+
+  <!-- the default param list handling -->
+  <xsl:template match="paramList">
+    <xsl:param name="ns">s1.</xsl:param>
+    <ul id="queryitemlist">
+      <xsl:for-each select="param">
+	<xsl:choose>
+	  <xsl:when test="@type='multi'">
+	    <li><xsl:apply-templates select='.'><xsl:with-param name="ns" select="$ns"/></xsl:apply-templates></li>
+	  </xsl:when>
+	  <xsl:otherwise>
+	    <xsl:variable name="pvalue"><xsl:apply-templates select="." mode="calculate-default"><xsl:with-param name="ns" select="$ns"/></xsl:apply-templates></xsl:variable>
+	      <li><xsl:value-of select="displayItem[@name='name']"/><xsl:apply-templates select="."><xsl:with-param name="default" select="$pvalue"/><xsl:with-param name="ns" select="$ns"/></xsl:apply-templates></li>
+	  </xsl:otherwise>
+	</xsl:choose>
+      </xsl:for-each>
+    </ul>
+  </xsl:template>
+ 
+  <!-- puts all the params into a=p&p=h type form - need to change this if use 
+  multi params  -->
+  <xsl:template match="paramList" mode="cgi">
+    <xsl:param name="ns">s1.</xsl:param>
+    <xsl:for-each select="param">
+      <xsl:variable name='pname' select="@name"/>
+      <xsl:text>&amp;</xsl:text><xsl:value-of select="$ns"/><xsl:value-of select="@name"/>=<xsl:apply-templates select="." mode="calculate-default"><xsl:with-param name='ns' select='$ns'/></xsl:apply-templates>
+    </xsl:for-each>
+  </xsl:template>
+
+  <xsl:template match="param" mode="calculate-default">
+    <xsl:param name="ns">s1.</xsl:param>
+    <xsl:variable name="pname"><xsl:value-of select="$ns"/><xsl:value-of select="@name"/></xsl:variable>
+    <xsl:choose>
+      <xsl:when test="/page/pageRequest/paramList/param[@name=$pname]">
+	<xsl:choose>
+	  <xsl:when test="@type='enum_multi'"><xsl:text>,</xsl:text>
+	    <xsl:for-each select="/page/pageRequest/paramList/param[@name=$pname]">
+	      <xsl:value-of select="@value"/>,
+	    </xsl:for-each>
+	  </xsl:when>
+	  <xsl:otherwise>
+	    <xsl:value-of select="/page/pageRequest/paramList/param[@name=$pname]/@value"/>
+	  </xsl:otherwise>
+	</xsl:choose>
+      </xsl:when>
+      <xsl:otherwise>
+	<xsl:value-of select="@default"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <!-- invisible params - used by other stuff. in the query form, we set to teh default -->
+  <xsl:template match="param[@type='invisible']">
+    <xsl:param name="ns">s1.</xsl:param>
+    <input type='hidden' name='{$ns}{@name}' value='{@default}'/>
+  </xsl:template>
+  <!-- boolean params -->
+  <xsl:template match="param[@type='boolean']">
+    <xsl:param name="ns">s1.</xsl:param>
+    <xsl:param name="default"/>
+    <select name='{$ns}{@name}'>
+      <option value="0"><xsl:if test="$default='0'"><xsl:attribute name="selected"></xsl:attribute></xsl:if><xsl:value-of select="option[@name='0']/displayItem[@name='name']"/></option>
+      <option value="1"><xsl:if test="$default='1'"><xsl:attribute name="selected"></xsl:attribute></xsl:if><xsl:value-of select="option[@name='1']/displayItem[@name='name']"/></option>
+    </select>
+  </xsl:template>
+  
+  <!-- integer params -->
+  <xsl:template match="param[@type='integer']">
+    <xsl:param name="ns">s1.</xsl:param>
+    <xsl:param name="default"/>
+    <input type="text" name="{$ns}{@name}" size="3" value="{$default}"/>
+  </xsl:template>
+
+  <!-- single selection enum params -->
+  <xsl:template match="param[@type='enum_single']">
+    <xsl:param name="ns">s1.</xsl:param>
+    <xsl:param name="default"/>
+    <xsl:choose>
+      <xsl:when test="count(option) = 1">
+	<xsl:value-of select="option/displayItem[@name='name']"/>
+	<input type='hidden' name='{$ns}{@name}'><xsl:attribute name='value'><xsl:value-of  select='option/@name'/></xsl:attribute></input>
+      </xsl:when>
+      <xsl:otherwise>
+	<select name="{$ns}{@name}">
+	  <xsl:for-each select="option">
+	    <option value="{@name}"><xsl:if test="@name=$default"><xsl:attribute name="selected"></xsl:attribute></xsl:if><xsl:value-of select="displayItem[@name='name']"/></option>
+	  </xsl:for-each>
+	</select>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+
+  <!-- multiple selection enum params -->
+  <!-- how to do defaults for this?? -->
+  <xsl:template match="param[@type='enum_multi']">
+    <xsl:param name="ns">s1.</xsl:param>
+    <xsl:param name="default"/>
+    <select name="{$ns}{@name}" size='2'><xsl:attribute name="multiple"></xsl:attribute>
+      <xsl:for-each select="option">
+	<option value="{@name}"><xsl:if test="contains($default, concat(',', @name, ','))"><xsl:attribute name="selected"></xsl:attribute></xsl:if><xsl:value-of select="displayItem[@name='name']"/></option>
+      </xsl:for-each>
+    </select>
+  </xsl:template>
+ 
+  <!-- string params -->
+  <xsl:template match="param[@type='string']">
+    <xsl:param name="ns">s1.</xsl:param>
+    <xsl:param name="default"/>
+    <input type="text" name="{$ns}{@name}" size="50" value="{$default}"/>
+  </xsl:template>
+  
+  <!-- large string  params -->
+  <xsl:template match="param[@type='text']">
+    <xsl:param name="ns">s1.</xsl:param>
+    <xsl:param name="default"/>
+    <textarea name="{$ns}{@name}" cols="50" rows="3"><xsl:value-of select='$default'/></textarea>
+  </xsl:template>
+
+  <!-- multi params - params that are combinations of other params -->
+  <xsl:template match="param[@type='multi']">
+    <xsl:param name="ns">s1.</xsl:param>
+    <xsl:variable name="parent" select="@name"/>
+    <table>
+        <tr class="queryfieldheading"><xsl:value-of select="displayItem[@name='name']"/>
+      	<xsl:for-each select="param">
+	    <td class="queryfieldname"><xsl:value-of select="displayItem[@name='name']"/></td>
+	</xsl:for-each>
+        </tr>
+      
+        <xsl:apply-templates select="." mode="contents"><xsl:with-param name="occurs" select="@occurs"/><xsl:with-param name="ns" select="$ns"/></xsl:apply-templates>
+    </table>
+  </xsl:template>
+
+  <xsl:template match="param[@type='multi']" mode="contents">
+    <xsl:param name="ns">s1.</xsl:param>
+    <xsl:param name="occurs">1</xsl:param>
+    <xsl:variable name="pos" select="@occurs - $occurs"/>	
+    <tr class="queryfieldrow"><xsl:for-each select="param">
+	<xsl:variable name="pname" select="@name"/>
+	<xsl:variable name="values" select="/page/pageRequest/paramList/param[@name=$pname]/@value"/>
+	<td class="queryfieldcell"><xsl:choose>
+	    <xsl:when test="not(@ignore) or  @ignore != $pos">      
+	      <xsl:apply-templates select='.'><xsl:with-param name="default" select="java:org.greenstone.gsdl3.util.XSLTUtil.getNumberedItem($values, $pos)"/><xsl:with-param name="ns" select="$ns"/></xsl:apply-templates>
+	    </xsl:when>
+	    <xsl:otherwise><!-- put in a hidden placeholder -->
+	      <input type="hidden" name='{$ns}{@name}' value=''/>
+	    </xsl:otherwise>
+	  </xsl:choose></td>
+      </xsl:for-each></tr>
+    <!-- recursively call this template to get multiple entries -->
+    <xsl:if test="$occurs &gt; 1">
+      <xsl:apply-templates select="." mode="contents"><xsl:with-param name="occurs" select="$occurs - 1"/><xsl:with-param name="ns" select="$ns"/></xsl:apply-templates>
+    </xsl:if>
+  </xsl:template>
+
+  
+</xsl:stylesheet>  
+
+  <!-- a param list that puts params in pairs- wont work as is with new
+  param handling stuff -->
+  <!--
+  <xsl:template match="paramList">
+  <p/><table width="537">
+  <xsl:choose>
+  <xsl:when test='count(param)>4'>
+  <xsl:for-each select="param[position() mod 2 = 1]"> 
+  <tr><xsl:apply-templates select="."/>
+  <xsl:if test="following-sibling::param[1]"><xsl:apply-templates select='following-sibling::param[1]'/></xsl:if></tr>
+</xsl:for-each>
+</xsl:when>
+  <xsl:otherwise>
+  <xsl:for-each select="param">
+  <tr><xsl:apply-templates select='.'/></tr>
+</xsl:for-each>
+</xsl:otherwise>
+</xsl:choose>
+</table>
+</xsl:template>
+  -->
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/style.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/style.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/style.xsl	(revision 13928)
@@ -0,0 +1,307 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+
+  <!-- some global parameters - these are set by whoever is invoking the transformation -->
+  <xsl:param name="interface_name"/>
+  <xsl:param name="library_name"/>
+   <!-- global style info goes here  -->
+  <xsl:template name="globalStyle">
+    <link rel="stylesheet" href="interfaces/default/style/core.css" type="text/css"/>
+  </xsl:template>
+  
+  <!-- the main page layout template is here -->
+  <xsl:template match="page">
+    <html>
+     	 <xsl:call-template name="pageHead"/>
+	 
+   <body>
+      <div id="globalwrapper">
+	  <xsl:apply-templates select="pageResponse"/>
+		  <xsl:if test="descendant::error">
+		    <script language="Javascript">
+		      <xsl:text disable-output-escaping="yes">
+			function removeAllChildren(node) {
+			 while (node.hasChildNodes()) {
+			  node.removeChild(node.firstChild);
+			 }
+			}
+
+		      function toggleHideError(obj) {
+		      if (obj.style.display == "none") {
+			obj.style.display = "";
+			hide_link = document.getElementById("hide");
+			removeAllChildren(hide_link);
+			hide_link.appendChild(document.createTextNode("Hide Error"));
+		      } else {
+			obj.style.display = "none";
+			hide_link = document.getElementById("hide");
+			removeAllChildren(hide_link);
+			hide_link.appendChild(document.createTextNode("Show Error"));
+			
+			}
+		      }
+		      </xsl:text>
+		    </script>
+		    <p align='right'><a id="hide" href="javascript:toggleHideError(error);">Show Error</a></p>
+		    <div id="error" style="display: none;">
+		      <xsl:apply-templates select="descendant::error"/>
+		    </div>
+		  </xsl:if>
+		  <xsl:call-template name="greenstoneFooter"/>
+	 </div>
+      </body>
+    </html>
+  </xsl:template>
+
+  <!-- put a space in the title in case the actual value is missing - mozilla will not display a page with no title-->
+  <xsl:template name="pageHead">
+    <head>
+      <title>
+	<xsl:call-template name="pageTitle"/><xsl:text> </xsl:text>
+      </title>
+      <xsl:call-template name="globalStyle"/>
+      <xsl:call-template name="pageStyle"/>
+    </head>
+  </xsl:template>
+
+
+  <xsl:template name="greenstonePageBanner">
+    <div id="banner">
+        <p>
+            <img src="interfaces/default/images/gsdlhead.gif"><xsl:attribute name="alt"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'gsdl')"/></xsl:attribute>
+            </img>
+	</p>
+    </div>
+    <div id="content">
+	<xsl:call-template name="dividerBar">
+            <xsl:with-param name="text" select="'select a collection'"/> 
+        </xsl:call-template>	
+      </div>
+  </xsl:template>
+
+  <xsl:template name="greenstoneFooter">
+      <div id="footer">
+         <xsl:call-template name="dividerBar">
+            <xsl:with-param name="text" select="util:getInterfaceText($interface_name, /page/@lang, 'gs3power')"/> 
+        </xsl:call-template>
+      </div>
+  </xsl:template>
+  
+  <xsl:template match="error">
+    Error: <xsl:value-of select="."/>
+  </xsl:template>
+
+  <xsl:template name="standardPageBanner">
+    <xsl:param name="collName"/>
+    <xsl:param name="pageType"/>
+    <xsl:variable name="this-element" select="/page/pageResponse/collection|/page/pageResponse/serviceCluster"/>
+    <div  id="banner">    
+     <p>
+	  <a href="{$library_name}?a=p&amp;sa=about&amp;c={$collName}">
+	    <xsl:choose>
+	      <xsl:when test="$this-element/displayItem[@name='icon']">
+		<img border="0">
+		  <xsl:attribute name="src">
+		    <xsl:value-of select="$this-element/metadataList/metadata[@name='httpPath']"/>/images/<xsl:value-of select="$this-element/displayItem[@name='icon']"/>
+		  </xsl:attribute>	
+		  <xsl:attribute name="alt">
+		    <xsl:value-of select="$this-element/displayItem[@name='name']"/>
+		  </xsl:attribute>
+		  <xsl:attribute name="title">
+		    <xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'aboutpage')"/>
+		  </xsl:attribute>
+		</img>
+	      </xsl:when>
+	      <xsl:otherwise>
+		<xsl:value-of select="$this-element/displayItem[@name='name']"/>
+	      </xsl:otherwise>
+	    </xsl:choose>
+	  </a>
+	</p>
+        <ul id="bannerlist"> 
+	  <xsl:call-template name="top-buttons">
+	    <xsl:with-param name="collName" select="$collName"/>
+	    <xsl:with-param name="pageType" select="$pageType"/>
+	  </xsl:call-template>
+       </ul>
+    </div>
+   </xsl:template>
+  
+  <xsl:template name="top-buttons">
+    <xsl:param name="collName"/>
+    <xsl:param name="pageType"/>
+    	 <li><a  href="{$library_name}?a=p&amp;sa=home"><xsl:attribute name="title"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'home_tip')"/></xsl:attribute>
+	    <xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'home_b')"/>
+	  </a></li>
+	<xsl:choose>
+	  <xsl:when test="$pageType='help'">
+	      <li><a><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'help_b')"/></a></li>
+	  </xsl:when>
+	  <xsl:otherwise>
+	    <li><a href="{$library_name}?a=p&amp;sa=help&amp;c={$collName}"><xsl:attribute name="title"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'help_tip')"/></xsl:attribute>
+		<xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'help_b')"/>
+	      </a></li>
+	    </xsl:otherwise>
+	</xsl:choose>
+	<xsl:choose>
+	  <xsl:when test="$pageType='pref'">
+	     <li><a><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'pref_b')"/></a></li>
+	   </xsl:when>
+	  <xsl:otherwise>
+	    <li><a href="{$library_name}?a=p&amp;sa=pref&amp;c={$collName}"><xsl:attribute name="title"><xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'pref_tip')"/></xsl:attribute>
+		<xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'pref_b')"/>
+	      </a></li>
+	    </xsl:otherwise>
+	</xsl:choose>
+  </xsl:template>
+
+  <xsl:template name="navigationBar">
+    <xsl:param name="collName"/>
+    <xsl:variable name="this-element" select="/page/pageResponse/collection|/page/pageResponse/serviceCluster"/>
+    <xsl:variable name="this-service" select="/page/pageResponse/service/@name"/>
+    <xsl:choose>
+    <xsl:when test="$this-element/serviceList/service">
+    <div id="navbar">
+        <ul id="navbarlist">
+	    <xsl:for-each select="$this-element/serviceList/service">
+	      <xsl:variable name="action"><xsl:choose>
+		  <xsl:when test="@name=$this-service">CURRENT</xsl:when>
+		  <xsl:when test="@type='query'">q</xsl:when>
+		  <xsl:when test="@type='browse'">b</xsl:when>
+		  <xsl:when test="@type='process'">pr</xsl:when>
+		  <xsl:when test="@type='applet'">a</xsl:when>
+		  <xsl:otherwise>DO_NOT_DISPLAY</xsl:otherwise>
+		</xsl:choose></xsl:variable>
+	      <xsl:choose>
+		<xsl:when test="$action='CURRENT'">
+		  <li><a ><xsl:value-of select="displayItem[@name='name']"/></a></li>
+		</xsl:when>
+		<xsl:when test="$action !='DO_NOT_DISPLAY'">
+		  <li><a href="{$library_name}?a={$action}&amp;rt=d&amp;s={@name}&amp;c={$collName}"><xsl:if test="displayItem[@name='description']"><xsl:attribute name='title'><xsl:value-of select="displayItem[@name='description']"/></xsl:attribute></xsl:if><xsl:value-of select="displayItem[@name='name']"/></a></li>
+		</xsl:when>
+	      </xsl:choose>
+	    </xsl:for-each>
+           </ul>
+	 </div> 
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:call-template name="dividerBar">
+            <xsl:with-param name="text" select="'&#160;'"/> 
+        </xsl:call-template>            
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  
+  
+  <xsl:template name="dividerBar">
+   <xsl:param name='text'/>
+      <xsl:choose>
+      <xsl:when test="$text">
+	 <div class="divbar"><xsl:value-of select="$text"/></div>
+      </xsl:when>
+      <xsl:otherwise>
+	 <div class="divbar"><xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text></div>
+      </xsl:otherwise>
+    </xsl:choose> 
+  </xsl:template>
+
+  <!-- Display the appropriate image, depending on the node type -->
+  <xsl:template match="documentNode" mode="displayNodeIcon">
+      
+    <!-- Root node: book icon (open or closed) -->
+    <xsl:choose>
+      <xsl:when test="@nodeType='root'">
+	<xsl:choose>
+	  <xsl:when test="documentNode">
+	    <xsl:call-template name="openbookimg">
+	      <xsl:with-param name="title">Close this book</xsl:with-param>
+	    </xsl:call-template>
+	  </xsl:when>
+	  <xsl:otherwise>
+	    <xsl:call-template name="closedbookimg">
+	      <xsl:with-param name="title">Open this document and view contents</xsl:with-param>
+	    </xsl:call-template>
+	  </xsl:otherwise>
+	</xsl:choose>
+      </xsl:when>
+      
+      <!-- Internal node: folder icon (open or closed) -->
+      <xsl:when test="@nodeType='internal'">
+	<xsl:choose>
+	  <xsl:when test="documentNode">
+	    <xsl:call-template name="openfolderimg">
+	      <xsl:with-param name="title">Close this folder</xsl:with-param>
+	    </xsl:call-template>
+	  </xsl:when>
+	  <xsl:otherwise>
+	    <xsl:call-template name="closedfolderimg">
+	      <xsl:with-param name="title">Open this folder and view contents</xsl:with-param>
+	    </xsl:call-template>
+	  </xsl:otherwise>
+	</xsl:choose>
+      </xsl:when>
+      
+      <!-- Leaf node: page icon, and this is the default -->
+      <xsl:otherwise>
+	<xsl:call-template name="textpageimg">
+	  <xsl:with-param name="title">View the document</xsl:with-param>
+	</xsl:call-template>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template name="openbookimg">
+    <xsl:param name="alt"/>
+    <xsl:param name="title"/>
+    <img  border="0" width="28" height="23"
+      src="interfaces/default/images/openbook.gif"
+      alt="{$alt}" title="{$title}"/>
+  </xsl:template>
+
+  <xsl:template name="closedbookimg">
+    <xsl:param name="alt"/>
+    <xsl:param name="title"/>
+    <img border="0" width="18" height="11"
+      src="interfaces/default/images/book.gif"
+      alt="{$alt}" title="{$title}"/>
+  </xsl:template>
+
+  <xsl:template name="openfolderimg">
+    <xsl:param name="alt"/>
+    <xsl:param name="title"/>
+    <img border="0" width="23" height="15"
+      src="interfaces/default/images/openfldr.gif"
+      alt="{$alt}" title="{$title}"/>
+  </xsl:template>
+
+  <xsl:template name="closedfolderimg">
+    <xsl:param name="alt"/>
+    <xsl:param name="title"/>
+    <img  border="0" width="23" height="15"
+      src="interfaces/default/images/clsdfldr.gif"
+      alt="{$alt}" title="{$title}"/>
+  </xsl:template>
+
+  <xsl:template name="textpageimg">
+    <xsl:param name="alt"/>
+    <xsl:param name="title"/>
+    <img  border="0" width="16" height="21"
+      src="interfaces/default/images/itext.gif"
+      alt="{$alt}" title="{$title}"/>
+  </xsl:template>
+
+  <xsl:template name="bookshelfimg">
+    <xsl:param name="alt"/>
+    <xsl:param name="title"/>
+    <img  border="0" width="20" height="16"
+      src="interfaces/default/images/bshelf.gif"  
+      alt="{$alt}" title="{$title}"/>
+  </xsl:template>
+</xsl:stylesheet>  
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/system.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/system.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/default/transform/system.xsl	(revision 13928)
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  extension-element-prefixes="java">
+  
+  <xsl:include href="style.xsl"/>
+  
+    <xsl:template name="pageTitle">
+    <xsl:value-of select="java:org.greenstone.gsdl3.util.XSLTUtil.getInterfaceText($interface_name, /page/@lang, 'gsdl')"/>
+  </xsl:template>
+
+  <!-- page specific style goes here -->
+  <xsl:template name="pageStyle"/>
+
+  <xsl:template match="pageResponse">
+    <xsl:value-of select="status"/>
+  </xsl:template>
+  
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/nzdl/interfaceConfig.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/nzdl/interfaceConfig.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/nzdl/interfaceConfig.xml	(revision 13928)
@@ -0,0 +1,27 @@
+<interfaceConfig baseInterface="classic">
+  <actionList>
+    <action name='p' class='PageAction'>
+      <subaction name='home' xslt='home.xsl'/>
+      <subaction name='about' xslt='about.xsl'/>
+      <subaction name='gsdl' xslt='gsdl.xsl'/>
+      <subaction name='help' xslt='help.xsl'/>
+      <subaction name='pref' xslt='pref.xsl'/>
+      <subaction name='nav' xslt='nav.xsl'/>
+      <subaction name="html" xslt="html.xsl"/>
+      <subaction name='abexpl' xslt='abexpl.xsl'/>
+    </action>
+    <action name='q' class='QueryAction' xslt='query.xsl'/>
+    <action name='b' class='GS2BrowseAction' xslt='classifier.xsl'/>
+    <action name='a' class='AppletAction' xslt='applet.xsl'/>
+    <action name='d' class='DocumentAction' xslt='document.xsl'/>
+    <action name='pr' class='ProcessAction' xslt='process.xsl'/>
+    <action name='s' class='SystemAction' xslt='system.xsl'/>
+  </actionList>
+  <languageList>
+    <language name='en' displayname='English' default_encoding='utf-8'/>
+    <language name='fr' displayname='French' default-encoding='utf-8'/>
+  </languageList>
+  <optionList>
+    <option name="highlightQueryTerms" value="true"/>
+  </optionList>
+</interfaceConfig>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/nzdl/transform/gsdl-text.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/nzdl/transform/gsdl-text.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/nzdl/transform/gsdl-text.xsl	(revision 13928)
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  extension-element-prefixes="java">
+
+  <xsl:template name="aboutgs">about the greenstone software</xsl:template>
+  <xsl:template name="textgreenstone1">
+Greenstone is a suite of software which has the ability to serve digital
+library collections and build new collections.  It provides a new way of
+organizing information and publishing it on the Internet or on CD-ROM.
+Greenstone is produced by the New Zealand Digital Library Project at the
+University of Waikato, and distributed in cooperation with UNESCO and the
+Human Info NGO. It is open-source software, available from
+<i>http://greenstone.org</i> under the terms of the GNU General Public
+License.
+  </xsl:template>
+
+  <xsl:template name="textgreenstone2">
+The New Zealand Digital Library website (<a href="http://nzdl.org">http://nzdl.org</a>) contains numerous example
+collections, all created with the Greenstone software, which are publicly
+available for you to peruse. They exemplify various searching and browsing
+options, and include collections in Arabic, Chinese, French, Maori, and
+Spanish, as well as English. There are also some music collections.
+  </xsl:template>
+
+  <xsl:template name="textplatformtitle">platform</xsl:template>
+  <xsl:template name="textgreenstone3">
+Greenstone runs on Windows and Unix. The distribution includes ready-to-use
+binaries for all versions of Windows, and for Linux. It also includes
+complete source code for the system, which can be compiled using Microsoft
+C++ or gcc.  Greenstone works with associated software that is also freely
+available: the Apache Webserver and PERL. The user interface uses a Web
+    browser: typically Netscape Navigator or Internet Explorer.
+  </xsl:template>
+
+  <xsl:template name="textgreenstone4">
+Many document collections are distributed on CD-ROM using the Greenstone
+software. For example, the <i>Humanity Development Library</i> contains
+1,230 publications ranging from accounting to water sanitation. It runs on
+minimal computing facilities such as those typically found in developing
+countries. The information can be accessed by searching, browsing by
+subject, browsing by titles, browsing by organisation, browsing a list of
+how-tos, and by randomly viewing the book covers.
+  </xsl:template>
+
+  <xsl:template name="textcustomisationtitle">customisation</xsl:template>
+  <xsl:template name="textgreenstone5">
+Greenstone is specifically designed to be highly extensible and
+customisable. New document and metadata formats are accommodated by writing
+"plugins" (in Perl). Analogously, new metadata browsing structures can be
+implemented by writing "classifiers." The user interface look-and-feel can
+be altered using "macros" written in a simple macro language. A Corba
+protocol allows agents (e.g. in Java) to use all the facilities associated
+with document collections. Finally, the source code, in C++ and Perl, is
+available and accessible for modification.
+  </xsl:template>
+
+<xsl:template name="textdocumentationtitle">documentation</xsl:template>
+<xsl:template name="textdocuments">Extensive documentation for the Greenstone software is available.</xsl:template>
+
+  <xsl:template name="textmailinglisttitle">mailing list</xsl:template>
+  <xsl:template name="textmailinglist">
+There is a mailing list intended primarily for discussions about the
+Greenstone digital library software.  Active users of Greenstone should
+consider joining the mailing list and contributing to the discussions.
+To subscribe, go to  <a href="https://list.scms.waikato.ac.nz/mailman/listinfo/greenstone-users">https://list.scms.waikato.ac.nz/mailman/listinfo/greenstone-users</a>.
+
+To send a message to the list, address it to <a
+href="mailto:greenstone-users@list.scms.waikato.ac.nz"
+>greenstone-users@list.scms.waikato.ac.nz</a>.
+</xsl:template>
+
+  <xsl:template name="textbugstitle">bugs</xsl:template>
+  <xsl:template name="textreport">
+We want to ensure that this software works well for you.  Please report any
+bugs to <a href="mailto:greenstone@cs.waikato.ac.nz">greenstone@cs.waikato.ac.nz</a>
+  </xsl:template>
+
+<xsl:template name="textgs3title">in the works</xsl:template>
+
+<xsl:template name="textgs3">Greenstone 3 is a complete redesign and 
+reimplementation which 
+retains all the advantages of Greenstone 2 (the current version)--for example, 
+it is multilingual, multiplatform, and highly configurable. It 
+incorporates all the features of the existing system, and is backwards 
+compatible: that is, it can build and run existing collections without 
+modification. Written in Java, it is structured as a network of 
+independent modules that communicate using XML: thus it runs in a 
+distributed fashion and can be spread across different servers as 
+necessary. This modular design increases the flexibility and 
+extensibility of Greenstone. The new version is expected to be 
+available for experimental use by 23 December 2003. An initial design for 
+the system is outlined in "The design of Greenstone 3: An agent based 
+dynamic digital library" (download <a href="http://www.greenstone.org/manuals/gs3desig.pdf">PDF</a>).
+</xsl:template>
+
+
+  <xsl:template name="textcreditstitle">credits</xsl:template>
+
+  <xsl:template name="textwhoswho">
+The Greenstone software is a collaborative effort between many
+people. Rodger McNab and Stefan Boddie are the principal architects and
+implementors.  Contributions have been made by David Bainbridge, George
+Buchanan, Michael Dewsnip, Katherine Don, Hong Chen, Elke Duncker, 
+Carl Gutwin, Geoff Holmes, John McPherson, Craig Nevill-Manning, 
+Dynal Patel, Gordon Paynter, Bernhard Pfahringer, Todd
+Reed, Bill Rogers, John Thompson, and Stuart Yeates.
+Other members of the New Zealand Digital Library project provided advice 
+and inspiration in the design of
+the system: Mark Apperley, Sally Jo Cunningham, Matt Jones, Steve Jones, 
+Te Taka Keegan, Michel Loots, Malika Mahoui, Gary Marsden, Dave Nichols 
+and Lloyd Smith. We would also like to
+acknowledge all those who have contributed to the GNU-licensed packages
+included in this distribution: MG, GDBM, PDFTOHTML, WGET, WVWARE and XLHTML.
+  </xsl:template>
+
+  
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/nzdl/transform/gsdl.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/nzdl/transform/gsdl.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/nzdl/transform/gsdl.xsl	(revision 13928)
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+
+  <xsl:include href="style.xsl"/>
+  <xsl:include href="gsdl-text.xsl"/>
+  <xsl:include href="home-text.xsl"/>
+  <xsl:include href="page-common.xsl"/>
+
+  <xsl:output method="html"/>  
+
+ <xsl:template name="pageTitle">
+    <xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'nzdl')"/>
+  </xsl:template>
+
+  <!-- page specific style goes here -->
+  <xsl:template name="pageStyle"/>
+
+  <xsl:template match="pageResponse">
+    <center>
+    <xsl:call-template name="genericPageBanner"><xsl:with-param name='text'><xsl:call-template name="aboutgs"/></xsl:with-param></xsl:call-template>
+    </center>
+    <p />
+    <table border='0' cellspacing='0' cellpadding='0'>
+      <tr>
+	<td valign='top' align='center'><xsl:call-template name="imagegreenstone"/></td>
+	<td valign='top'><xsl:call-template name="textgreenstone1"/>
+	  <br /><br />
+	</td>
+      </tr>
+      <tr>
+	<td valign='top' align='center'>
+	  <h2><a href="http://nzdl.org">nzdl.org</a></h2>
+	</td>
+	<td valign='top'><xsl:call-template name="textgreenstone2"/>
+	  <br /><br />
+	</td>
+      </tr>
+      <tr>
+	<td valign='top' align='center'>
+	  <h2><xsl:call-template name="textplatformtitle"/></h2>
+	</td>
+	<td valign='top'><xsl:call-template name="textgreenstone3"/>
+	  <br /><br />
+	</td>
+      </tr>
+      <tr>
+	<td valign='top' align='center'>
+	  <a href="http://nzdl.org/hdl"><img border='0' width='101' height='100' src="interfaces/nzdl/images/hdlimg.jpg"/></a>
+	</td>
+	<td valign='top'>
+	  <xsl:call-template name="textgreenstone4"/>
+	  <br /><br />
+	</td>
+      </tr>
+      <tr>
+	<td valign='top' align='center'>
+	  <h2><xsl:call-template name="textcustomisationtitle"/></h2>
+	</td>
+	<td valign='top'><xsl:call-template name="textgreenstone5"/>
+	  <br /><br />
+	</td>
+      </tr>
+      <tr>
+	<td valign='top' align='center'>
+	  <h2><a href="http://www.greenstone.org/english/docs.html"><xsl:call-template name="textdocumentationtitle"/></a></h2>
+	</td>
+	<td valign='top'><xsl:call-template name="textdocuments"/>
+	<br /><br />
+	</td>
+      </tr>
+      <tr>
+	<td valign='top' align='center'>
+	  <h2><xsl:call-template name="textmailinglisttitle"/></h2>
+	</td>
+	<td valign='top'><xsl:call-template name="textmailinglist"/>
+	  <br /><br />
+	</td>
+      </tr>
+      <tr>
+	<td valign='top' align='center'>
+	  <h2><xsl:call-template name="textbugstitle"/></h2>
+	</td>
+	<td valign='top'><xsl:call-template name="textreport"/>
+	  <br /><br />
+	</td>
+      </tr>
+       <tr>
+         <td valign='top' align='center'>
+	   <h2><xsl:call-template name="textgs3title"/></h2>
+	 </td>
+	 <td valign='top'><xsl:call-template name="textgs3"/>
+	   <br /><br />
+	 </td>
+      </tr>
+
+      <tr>
+	<td valign='top' align='center'>
+	  <h2><xsl:call-template name="textcreditstitle"/></h2>
+	</td>
+	<td valign='top'><xsl:call-template name="textwhoswho"/>
+	</td>
+      </tr>
+    </table>
+    <center>
+    <p /><xsl:call-template name="dividerBar"/>
+    <xsl:call-template name="greenstone_info"/>
+    <xsl:call-template name="nzdlpagefooter"/>
+    </center>
+  </xsl:template>
+
+</xsl:stylesheet>
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/nzdl/transform/home-text.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/nzdl/transform/home-text.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/nzdl/transform/home-text.xsl	(revision 13928)
@@ -0,0 +1,192 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  extension-element-prefixes="java">
+
+  <!--<xsl:include href="style.xsl"/>-->
+<xsl:template name="textpagetitle">New Zealand Digital Library</xsl:template>
+<xsl:template name="textprojhead">The New Zealand Digital Library Project</xsl:template>
+
+<xsl:template name="textprojinfo">
+<p />
+The New Zealand Digital Library project is a research programme at
+The University of Waikato whose aim is to develop the underlying
+technology for digital libraries and make it available publicly so that
+others can use it to create their own collections. 
+<p />
+Our web site provides several document collections, including historical
+documents, humanitarian and development information, computer
+science technical reports and bibliographies, literary works, and
+magazines. All are available over the Web, and can be accessed
+through searching and browsing interfaces provided by the
+Greenstone digital library software. Behind the query interface lies a
+huge collection providing gigabytes of information. We hope you find
+what you want, or at least something intriguing!
+</xsl:template>
+
+<xsl:template name="titlesoftwareinfo">The Greenstone software</xsl:template>
+
+<xsl:template name="textsoftwareinfo">
+<p />
+The <a href="http://www.greenstone.org">Greenstone Digital Library software</a> provides a new way of
+organizing information and making it available over the Internet or on
+CD-ROM. It is open-source software, available under the terms of the
+Gnu public license. 
+<p />
+A digital library is made up of a set of collections. Each collection of
+information comprises several (typically several thousand, or even
+several million) documents, which share a uniform searching and
+browsing interface. Collections can be organized in many different
+ways while retaining a strong family resemblance. 
+
+<p>To subscribe to the Greenstone mailing list, go to <a 
+href="https://list.scms.waikato.ac.nz/mailman/listinfo/greenstone-users">https://list.scms.waikato.ac.nz/mailman/listinfo/greenstone-users</a>.</p>
+
+<p align='right'/>
+<a href="{$library_name}?a=p&amp;sa=gsdl">More...</a>
+</xsl:template>
+
+<xsl:template name="titleresearchinfo">Our research</xsl:template>
+
+<xsl:template name="textresearchinfo">
+<p />
+The goal of our research program is to explore the potential of
+internet-based digital libraries. Our vision is to develop systems that
+automatically impose structure on anarchic, uncatalogued, distributed
+repositories of information, thereby providing information consumers
+with effective tools to locate what they need and to peruse it
+conveniently and comfortably. 
+<p />
+Project members are actively working on techniques for creating,
+managing, and and mainatining collections; extracting metadata from
+legacy documents; analysing library usage and user needs; Maori,
+Arabic and Chinese language systems; internationalising the library
+interface; optical music recognition and musical collections; novel
+interfaces for formulating queries and visualising results; novel
+interfaces for browsing metadata; text mining for keyphrases,
+acronyms, and other metadata; keyphrase extraction and
+phrase-based browsing; and other research topics. 
+<p align='right'/>
+<a href="http://www.nzdl.org/html/research.html">More...</a>
+</xsl:template>
+
+<xsl:template name="titleaffiliateinfo">Our affiliates</xsl:template>
+
+<xsl:template name="textaffiliatehumaninfo">
+<p />
+<a href="http://humaninfo.org">Human Info NGO</a>
+is a registered charity responsible for the
+provision of universal low-cost
+information access through co-operation between UN Agencies,
+universities and NGOs. Human Info NGO collaborates extensively
+with the NZDL project, and use the Greenstone software. 
+</xsl:template>
+
+<xsl:template name="textaffiliateunesco">
+<p />
+<a href="http://www.unesco.org">United Nations Educational, Scientific and Cultural Organization</a>.
+The dissemination of educational, scientific and cultural information
+throughout the world, and particularly its availability
+</xsl:template>
+
+<xsl:template name="textpoem">
+<br /><h2>Kia papapounamu te moana</h2>
+
+<p />kia hora te marino,
+<br />kia tere te karohirohi,
+<br />kia papapounamu te moana
+
+<p />may peace and calmness surround you,
+<br />may you reside in the warmth of a summer's haze,
+<br />may the ocean of your travels be as smooth as the polished greenstone.
+</xsl:template>
+
+<xsl:template name="textgreenstone"> 
+<p />Greenstone is a semi-precious stone that (like this software) is sourced
+in New Zealand.  In traditional Maori society it was the most highly prized
+and sought after of all substances.  It can absorb and hold <i>wairua</i>,
+which is a spirit or life force, and is endowed with traditional virtues
+that make it an appropriate emblem for a public-domain digital library
+project.  Its lustre shows charity; its translucence, honesty; its
+toughness, courage; and the sharp edge it can take, justice.  The carved
+piece used in the Greenstone Digital Library Software logo is a <i>patu</i>
+or fighting club, and is a family heirloom of one of our project members.
+In hand-to-hand combat its delivery is very quick, very accurate, and very
+complete.  We like to think these qualities also apply to our software, the
+razor sharp edge of the <i>patu</i> symbolizing the leading edge of
+technology.
+</xsl:template>
+
+<xsl:template name="textaboutgreenstone">
+<p />Greenstone is a suite of software for building and distributing digital
+library collections. It provides a new way of organizing information and
+publishing it on the Internet or on CD-ROM.  Greenstone is produced by the
+<b>New Zealand Digital Library Project</b> at the <b>University of
+Waikato</b>, and developed and distributed in cooperation with
+<b>UNESCO</b> and the <b>Human Info NGO</b>.  It is open-source
+software, available from <a href="http://greenstone.org">http://greenstone.org</a> under the terms of
+the GNU General Public License.
+
+<p />The aim of the software is to empower users, particularly in
+universities, libraries, and other public service institutions, to
+build their own digital libraries.  Digital libraries are radically
+reforming how information is disseminated and acquired in UNESCO's
+partner communities and institutions in the fields of education,
+science and culture around the world, and particularly in developing
+countries.  We hope that this software will encourage the effective
+deployment of digital libraries to share information and place it in
+the public domain.
+
+
+<p />This software is developed and distributed as an international
+cooperative effort established in August 2000 among three parties.
+
+<table border="0">
+<tr valign="top">
+<td>
+<a href="http://nzdl.org"><b>New Zealand Digital Library Project at the University of Waikato</b></a>
+<br />
+Greenstone software grew out of this project, and this initiative
+has been endorsed by the Communication Sub-Commission of the New
+Zealand National Commission for UNESCO as part of New Zealand's
+contribution to UNESCO's programme.
+</td>
+<td></td>
+</tr>
+<tr valign="top">
+<td>
+<a href="http://www.unesco.org"><b>United Nations Educational, Scientific and Cultural Organization</b></a>
+<br />
+The dissemination of educational, scientific and cultural information
+throughout the world, and particularly its availability in developing
+countries, is central to UNESCO's goals as pursued within its
+intergovernmental Information for All Programme, and appropriate,
+accessible information and communication technology is seen as an important
+tool in this context.
+</td>
+<td><a href="http://www.unesco.org"><img src="interfaces/nzdl/images/unesco.gif" border="0"/></a></td>
+</tr>
+<tr valign="top">
+<td>
+<a href="http://humaninfo.org"><b>The Human Info NGO, based in Antwerp, Belgium</b></a>
+<br />
+This project works with UN agencies and other NGOs, and has established
+a worldwide reputation for digitizing documentation of interest to
+human development and making it widely available, free of charge to
+developing nations and on a cost-recovery basis to others.
+</td>
+<td><a href="http://humaninfo.org"><img src="interfaces/nzdl/images/ghproj2.jpg" border="0"/></a></td>
+</tr>
+</table>
+</xsl:template>
+
+  <xsl:template name="textimagegreenstone">Greenstone Digital Library Software</xsl:template>
+  
+  <xsl:template name="nzdlpagefooter">
+      <p /><xsl:call-template name="dividerBar"/>
+      <p /><a href="http://www.nzdl.org">New Zealand Digital Library Project</a>
+      <br /><a href="http://www.cs.waikato.ac.nz/cs">Department of Computer Science</a>, <a href="http://www.waikato.ac.nz">University of Waikato</a>, New Zealand
+    </xsl:template>
+    
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/nzdl/transform/home.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/nzdl/transform/home.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/nzdl/transform/home.xsl	(revision 13928)
@@ -0,0 +1,230 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+
+  <xsl:include href="style.xsl"/>
+  <xsl:include href="home-text.xsl"/>
+  <xsl:include href="page-common.xsl"/>
+
+  <xsl:output method="html"/>  
+
+  <xsl:template name="pageTitle">
+    <xsl:value-of select="util:getInterfaceText($interface_name, /page/@lang, 'nzdl')"/>
+  </xsl:template>
+
+  <!-- page specific style goes here -->
+  <xsl:template name="pageStyle"/>
+
+  <xsl:template match="pageResponse">
+    <xsl:call-template name="nzdlPageBanner"/>     
+    <center>
+    <xsl:apply-templates select="collectionList"/>
+    </center>
+    <center><xsl:call-template name="dividerBar"/></center>    
+    <p />
+    <center><h2><xsl:call-template name="textprojhead"/></h2></center>
+    
+    <table border='0' cellpadding='5'>
+      <xsl:call-template name="project_info"/>
+      <xsl:call-template name="software_info"/>
+      <xsl:call-template name="research_info"/>
+      <xsl:call-template name="affiliate_info"/>
+    </table>
+    <center>
+      <xsl:call-template name="dividerBar"/>
+      <xsl:call-template name="greenstone_info"/>
+      <p />
+      <xsl:call-template name="nzdlpagefooter"/> 
+      <br />September 2003
+    </center>
+  </xsl:template>
+
+  <xsl:template name="project_info">
+    <tr valign='top'>
+      <td>
+	<table><tr valign='middle'><td><img src="interfaces/nzdl/images/gbull.gif"/></td><td><a href="mailto:greenstone@cs.waikato.ac.nz">Feedback</a></td></tr></table>
+	<table><tr valign='middle'><td><img src="interfaces/nzdl/images/gbull.gif"/></td><td><a href="http://www.nzdl.org/html/people.html">People</a></td></tr></table>
+	<table><tr valign='middle'><td><img src="interfaces/nzdl/images/gbull.gif"/></td><td><a href="http://greenstone.cs.uct.ac.za/gsdl/cgi-bin/library">African Digital Library Centre</a></td></tr></table>
+<table><tr valign='middle'><td><img src="interfaces/nzdl/images/gbull.gif"/></td><td><a href="http://sadl.uleth.ca">Southern Alberta Digital Library Centre</a></td></tr></table>
+      </td>
+      <td><xsl:call-template name="textprojinfo"/></td>
+    </tr>
+  </xsl:template>
+
+  <xsl:template name="software_info">
+    <tr>
+      <td></td>
+      <th align='left'><xsl:call-template name="titlesoftwareinfo"/></th>
+    </tr>
+    <tr valign='top'>
+      <td>
+	<table><tr valign='middle'><td><img src="interfaces/nzdl/images/gbull.gif"/></td><td><a href="{$library_name}?a=p&amp;sa=gsdl">About<br />Greenstone 2</a></td></tr></table>
+	<table><tr valign='middle'><td><img src="interfaces/nzdl/images/gbull.gif"/></td><td><a href="http://www.greenstone.org/english/docs.html">Greenstone 2<br />Documentation</a></td></tr></table>
+      </td>
+      <td><xsl:call-template name="textsoftwareinfo"/></td>
+    </tr>
+  </xsl:template>
+  
+  <xsl:template name="research_info">
+    <tr>
+    <td></td>
+    <th align='left'><xsl:call-template name="titleresearchinfo"/></th>
+  </tr>
+    <tr valign='top'>
+      <td>
+	<table><tr valign='middle'><td><img src="interfaces/nzdl/images/gbull.gif"/></td><td><a href="http://www.nzdl.org/html/research.html">Research</a></td></tr></table>
+	<table><tr valign='middle'><td><img src="interfaces/nzdl/images/gbull.gif"/></td><td><a href="http://www.nzdl.org/html/projects.html">Projects</a></td></tr></table>
+	<table><tr valign='middle'><td><img src="interfaces/nzdl/images/gbull.gif"/></td><td><a href="http://www.nzdl.org/html/software.html">Software<br />Downloads</a></td></tr></table>
+	<table><tr valign='middle'><td><img src="interfaces/nzdl/images/gbull.gif"/></td><td><a href="http://www.cs.waikato.ac.nz/~nzdl/publications/">Publications</a></td></tr></table>
+      </td>
+      <td><xsl:call-template name="textresearchinfo"/></td>
+    </tr>
+    
+<!--    <tr valign='top'>
+      <td>
+	<table><tr valign='middle'><td><img src="interfaces/nzdl/images/gbull.gif"/></td><td><a href="http://nzdl2.cs.waikato.ac.nz/cgi-bin/zdemo/library">Z39.50<br />demo</a></td></tr></table>
+      </td><td>
+	We have an experimental facility for searching Z39.50 collections using  Greenstone.  Ultimately we plan a full bibliographic search facility, with  the ability to combine tests on different fields, and to be able to search multiple collections, including cross-searching Greenstone and Z39.50 collections.
+      </td>
+    </tr>-->
+  </xsl:template>
+
+  <xsl:template name="affiliate_info">
+    <tr>
+      <td></td>
+      <th align='left'><xsl:call-template name="titleaffiliateinfo"/></th>
+    </tr>
+    <tr valign='top'>
+      <td>
+	<img src="interfaces/nzdl/images/ghproj.jpg" alt="Human Info NGO" width='100' height='90'/>
+      </td>
+      <td><xsl:call-template name="textaffiliatehumaninfo"/></td>
+    </tr>
+    <tr valign='top'>
+      <td><img src="interfaces/nzdl/images/unesco.gif" alt="UNESCO" width='100' height='90' />
+      </td>
+      <td><xsl:call-template name='textaffiliateunesco'/></td>
+      </tr>
+  </xsl:template>
+  
+  <xsl:template match="collection">
+  <xsl:param name="extraArgs"/>
+    <xsl:variable name="ct"><xsl:choose><xsl:when test="metadataList/metadata[@name='buildType']='mgpp'">1</xsl:when><xsl:otherwise>0</xsl:otherwise></xsl:choose></xsl:variable>
+    <p />
+    <a href="{$library_name}?a=p&amp;sa=about&amp;c={@name}&amp;ct={$ct}{$extraArgs}">
+      <img width="150" border="1">
+	<xsl:attribute name="src">
+	  <xsl:value-of select="metadataList/metadata[@name='httpPath']"/>/images/<xsl:choose><xsl:when test="displayItem[@name='smallicon']"><xsl:value-of select="displayItem[@name='smallicon']"/></xsl:when><xsl:otherwise><xsl:value-of select="displayItem[@name='icon']"/></xsl:otherwise></xsl:choose>
+	</xsl:attribute>
+	<xsl:attribute name="alt">
+	  <xsl:value-of select="displayItem[@name='name']"/>
+	</xsl:attribute>
+      </img>
+    </a>
+    <p />
+  </xsl:template> 
+
+
+  <xsl:template match="collectionList">
+    <center>
+      <xsl:call-template name="dividerBar"><xsl:with-param name="text">Humanitarian and UN collections</xsl:with-param></xsl:call-template>
+      <p /><xsl:call-template name="collectfao"/>
+      <xsl:call-template name="dividerBar"><xsl:with-param name="text">Demonstration collections</xsl:with-param></xsl:call-template> 
+      <p /><xsl:call-template name="collectrest"/>
+    </center>
+  </xsl:template>
+
+  <xsl:template name="collectfao">
+    <table width="537">
+      <tr valign='top'>
+	<td align='center'>
+	  <p /><xsl:apply-templates select="collection[@name='hdl']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='fnl']"/>
+ 	  <p /><xsl:apply-templates select="collection[@name='envl']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='aginfo']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='gtz']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='cdl']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='edudev']"/>
+	  <p /><xsl:apply-templates select="collection[@name='nigeria']"/>
+	  <p /><xsl:apply-templates select="collection[@name='safem']"/>
+	  <p />firstaid<xsl:apply-templates select="collection[@name='firstaid']"/>
+	</td>
+	<td align='center'>
+	  <p /><xsl:apply-templates select="collection[@name='mhl']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='fnl1_1']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='paho']"/>
+	  <p /><xsl:apply-templates select="collection[@name='unesco']"/>
+          <p /><xsl:apply-templates select="collection[@name='muster']"/>
+	  <p /><xsl:apply-templates select="collection[@name='unescoen']"/>
+	  <p /><xsl:apply-templates select="collection[@name='dfid']"/>	
+	  <p /><xsl:apply-templates select="collection[@name='ewf']"/>	
+	  <p /><xsl:apply-templates select="collection[@name='fi1998']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='faodocs']"/>  
+	</td>
+	<td align='center'> 
+	  <p /><xsl:apply-templates select="collection[@name='ccgi']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='fnl2.2']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='who']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='tulane']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='unaids']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='aedl']"/>
+	  <p /><xsl:apply-templates select="collection[@name='whoedm']"/>
+	  <p /><xsl:apply-templates select="collection[@name='helid']"/>
+	  <p /><xsl:apply-templates select="collection[@name='ipc']"/>	
+	  <p /><xsl:apply-templates select="collection[@name='povsem']"/>
+	</td>
+      </tr>
+    </table>
+  </xsl:template>
+  
+
+  <xsl:template name="collectrest">
+    <table width='537'>
+      <tr valign='top'>
+	<td align='center'>
+	  <p /><xsl:apply-templates select="collection[@name='acrodemo']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='niupepa']"/> 
+	  <p />howto DL<xsl:apply-templates select="collection[@name='howto']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='arabic']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='chinese']">
+	  <xsl:with-param name="extraArgs">&amp;l=zh</xsl:with-param>
+	  </xsl:apply-templates>	 
+ 	  <p /><xsl:apply-templates select="collection[@name='folktale']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='demooai']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='tidbits']"/> 
+	</td>
+	<td align='center'>
+	  <p />meldex<xsl:apply-templates select="collection[@name='meldex']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='wordpdf']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='musvid']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='gberg']"/> 
+ 	  <p /><xsl:apply-templates select="collection[@name='allshake']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='aircraft']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='csbib']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='coltbib']">
+	  <xsl:with-param name="extraArgs">&amp;qt=1</xsl:with-param>
+	  </xsl:apply-templates> 
+	</td>
+	<td align='center'>
+	  <p /><xsl:apply-templates select="collection[@name='cstr']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='gsarch']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='ohist']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='hcibib']"/> 
+ 	  <p /><xsl:apply-templates select="collection[@name='whist']"/> 
+	  <p /><xsl:apply-templates select="collection[@name='beowulf']"/>
+	  <p /><xsl:apply-templates select="collection[@name='tcc']"/>
+	  <p /><xsl:apply-templates select="collection[@name='jair']"/>  
+	</td>
+      </tr>
+    </table>
+  </xsl:template>
+  
+</xsl:stylesheet>  
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/nzdl/transform/page-common.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/nzdl/transform/page-common.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/interfaces/nzdl/transform/page-common.xsl	(revision 13928)
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+  <xsl:template name="greenstone_info">
+    <p />
+    <table>
+      <tr valign='top'>
+	<td><xsl:call-template name="textpoem"/></td>
+	<td><xsl:call-template name="imagegreenstone"/></td>
+      </tr></table>
+    <p />
+    <table><tr><td><xsl:call-template name="textgreenstone"/></td></tr></table>
+  </xsl:template>
+
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/search.html
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/search.html	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/search.html	(revision 13928)
@@ -0,0 +1,224 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+<title>AJAX GS3 Search</title>
+<META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">
+<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
+<style type="text/css">
+<!-- 
+BODY, P, LI { font-family: sans-serif; } 
+H2 {font-size: 90%;}
+BUTTON {font-size: 0.8em; margin: 0 1em; color: red;}
+#searchArea {background-color:white; }
+#resultArea {background-color:white; padding: 0em 0em;}
+#resultSummary {font-size: 80%; padding: 0.2 em 0.2em;}
+#resultSummary P {padding: 0.2em 0.3em;}
+#query {padding: 0.1em 0.5em; width: 400px; height: 150px; background-color:#d3d3d3;}
+#timing {float:right; width: 250px; border: thin solid #d3d3d3; padding: 0.2em 0.2em; display: none;}
+#resultList {	list-style-image: none; 
+						list-style-type: square;
+						font-size: 85%; padding: 1em 0em 1em 2em;}
+#resultList LI {padding: 0.3em 0em; }
+-->
+</style>
+<script type="text/javascript" src="xmlextras.js">
+</script> 
+<script type="text/javascript" src="gs_ajax_utils.js">
+</script> 
+<script type="text/javascript">
+<!--
+
+localsiteServerAddress = "/gsdl3/services/localsite";
+libraryAddress = "/gsdl3/library";
+function loadAsync(sUri, SOAPMessage, callbackFunction) {
+   var xmlHttp = XmlHttp.create();
+   var async = true;
+   xmlHttp.open("POST", sUri, async);
+   xmlHttp.onreadystatechange = function () {
+      if (xmlHttp.readyState == 4){
+		var result = xmlHttp.responseText;
+			//getTitle2(xmlHttp.responseXML, xmlHttp.responseText);
+			eval(callbackFunction);
+    }     
+   }
+   xmlHttp.setRequestHeader("SOAPAction", " ");
+   xmlHttp.setRequestHeader("Content-Type", "Content-Type: text/xml; charset=utf-8");
+ 
+   xmlHttp.send(SOAPMessage);
+}
+
+
+function ajaxSearch() {
+
+searchStartTime = new Date();
+
+resultList = document.getElementById('resultList');
+removeAllChildren(resultList);
+resultSummary = document.getElementById('resultSummary');
+removeAllChildren(resultSummary);
+
+/*
+for (i=0; i < 10; i++) {
+    listElement = document.createElement('li');
+    anchor = document.createElement('a');
+    anchor.setAttribute('href', url);
+    anchor.appendChild(document.createTextNode(  text));
+    listElement.appendChild(anchor);
+    resultList.appendChild(listElement);
+}
+*/
+
+queryText = document.getElementById('queryText').value;
+
+maxdocs = newElementAtt('param', '', new Array('name', 'value'), new Array('maxDocs', '100') ) ;
+level = newElementAtt('param', '', new Array('name', 'value'), new Array('level', 'Sec') ) ;
+indexValue = newElementAtt('param', '', new Array('name', 'value'), new Array('index', 'ZZ') ) ;
+matchMode = newElementAtt('param', '', new Array('name', 'value'), new Array('matchMode', 'some') ) ;
+query = newElementAtt('param', '', new Array('name', 'value'), new Array('query', queryText) ) ;
+caseValue = newElementAtt('param', '', new Array('name', 'value'), new Array('case', '1') ) ;
+sortBy = newElementAtt('param', '', new Array('name', 'value'), new Array('sortBy', '1') ) ;
+stem = newElementAtt('param', '', new Array('name', 'value'), new Array('stem', '1') ) ;
+
+
+paramList = newElement('paramList', maxdocs + level + indexValue + matchMode + query + caseValue + sortBy + stem);
+
+collection = document.getElementById('collectionText').value;
+request = newElementAtt('request', paramList, new Array('lang', 'to', 'type', 'uid'), new Array('en',collection + '/TextQuery', 'process', '1'  ) );
+message = newElement('message', request );
+soapMessage = messageToSOAP(message);
+loadAsync(localsiteServerAddress, soapMessage, 'getResults(xmlHttp.responseXML)');
+}
+
+function getResults(xmlDoc) {
+idsReturnedTime = new Date();
+    metadataList = xmlDoc.getElementsByTagName('metadata');
+    for (i=0; i < metadataList.length; i++) {
+    	metadata = metadataList[i];
+    	if (isElement(metadata)) {
+		  nameAtt = metadata.getAttribute('name')
+    		if ( nameAtt == 'numDocsMatched') {
+    			numDocsMatched = getText(metadata);
+    		}
+    		if (nameAtt == 'numDocsReturned') {
+    			numDocsReturned = getText(metadata);
+    		}
+    		if (nameAtt  == 'query') {
+    			query = getText(metadata);
+    		}
+    	}
+    }
+    
+    resultSummary = document.getElementById('resultSummary');
+    para = document.createElement('p');
+    para.appendChild(document.createTextNode('Query: ' + query + ' Number of Matching Docs: ' + numDocsMatched + ' Number of returned documents: ' + numDocsReturned));
+    resultSummary.appendChild(para);
+    
+    documentNodeList = xmlDoc.getElementsByTagName('documentNode');
+    	
+    for (i=0; i < documentNodeList.length; i++) {
+    	documentNode = documentNodeList[i];
+    	if (isElement(documentNode)) {
+    		docIDArray[i] = documentNode.getAttribute('nodeID');
+    	}
+    }
+   
+    var docsList = '';
+    for (i=0; i < docIDArray.length; i++) {
+    	docsList += newElementAtt1('documentNode', '', 'nodeID', docIDArray[i]);
+    }
+	
+    docNodeList = newElement('documentNodeList', docsList);
+	collection = document.getElementById('collectionText').value;
+    param = newElementAtt('param', '', new Array('name', 'value'), new Array('metadata', 'Title') );
+    paramList = newElement('paramList', param);
+	request = newElementAtt('request', paramList + docNodeList, new Array('lang', 'to', 'type', 'uid'), new Array('en',collection + '/DocumentMetadataRetrieve', 'process', '1'  ) );
+    message = newElement('message', request ); 
+    soapMessage = messageToSOAP(message);
+	//alert(soapMessage);
+    loadAsync(localsiteServerAddress, soapMessage, 'displayResults(xmlHttp.responseXML)');
+}
+
+
+function displayResults(xmlDoc) {
+	metadataReturnedTime = new Date();
+	url1 = libraryAddress+'?a=d&d=';
+	url2 = '&c=' + document.getElementById('collectionText').value + '&dt=hierarchy';
+	resultList = document.getElementById('resultList');
+    metadataList = xmlDoc.getElementsByTagName('metadata');
+	//alert('in display results ' + metadataList.length + xmlDoc.xml);
+        for (i=0; i < metadataList.length; i++) {
+			  //alert('in display results ' + i);
+        	metadata = metadataList[i];
+        	if (isElement(metadata)) {
+        		if (metadata.getAttribute('name') == 'Title') {
+					
+          		  listElement = document.createElement('li');
+                anchor = document.createElement('a');
+                anchor.setAttribute('href', url1 + docIDArray[i] + url2);
+                anchor.appendChild(document.createTextNode(getText(metadata)) );
+                listElement.appendChild(anchor);
+                resultList.appendChild(listElement);
+        		}   		
+        	}
+        }
+			finishedTime = new Date();
+			displayTime();
+			
+}
+
+function displayTime() {
+searchStart = document.getElementById('searchStart');
+idsReturned = document.getElementById('idsReturned');
+metadataReturned = document.getElementById('metadataReturned');
+//removeAllChildren(searchStart);
+//searchStart.appendChild(document.createTextNode(searchStartTime.getMilliseconds() + ' ms'))
+removeAllChildren(idsReturned);
+idsReturned.appendChild(document.createTextNode(idsReturnedTime.getMilliseconds() - searchStartTime.getMilliseconds()+ ' ms'))
+removeAllChildren(metadataReturned);
+metadataReturned.appendChild(document.createTextNode(metadataReturnedTime.getMilliseconds() - idsReturnedTime.getMilliseconds()+ ' ms'))
+//alert(searchStartTime.getMilliseconds() + ' ' + idsReturnedTime.getMilliseconds() + ' ' + metadataReturnedTime.getMilliseconds() + ' ' + ' ' + finishedTime.getMilliseconds());
+}
+
+
+var docIDArray = new Array();
+var searchStartTime, idsReturnedTime, metadataReturnedTime, finishedTime;
+
+
+
+
+// -->
+</script>
+</head>
+<body>
+
+
+
+<div id="searchArea">
+
+<div id="timing">
+<p><strong>Timing</strong></p>
+<table border="0" cellpadding="0" cellspacing="0" summary="">
+<!-- <tr><td>Search started:</td><td id="searchStart"></td></tr> -->
+<tr><td>Time to get IDs:</td><td id="idsReturned"></td></tr>
+<tr><td>Time to get Metadata:</td><td id="metadataReturned"></td></tr>
+</table>
+</div> 
+
+<div id="query"><h2>Search a Greenstone 3 Collection</h2>
+<form action="">
+<p><label for="collectionText">GS3 Collection:</label>
+<input id="collectionText" type="text" value="gs2mgppdemo"/></p>
+
+<p><input id="queryText" type="text" /><input id="searchButton" type="submit" value="Search" onclick="ajaxSearch();return false;"></input></p>
+
+</form></div>
+</div>
+
+<div id="resultArea">
+<div id="resultSummary"></div>
+<ul id="resultList"></ul>
+</div>
+ 
+</body>
+</html>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/gateway/siteConfig.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/gateway/siteConfig.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/gateway/siteConfig.xml	(revision 13928)
@@ -0,0 +1,9 @@
+<siteConfig>
+  <siteList localSiteName="gateway">
+    <!-- a site element needs name and type, then either an addess attribute where the URL of the server can be accessed, or a localSite attribute, which specifies to use the local server on a local site. This second method is just for testing. The address of a SOAP server deployed by axis in greenstone would be like http://{tomcat_server}:{tomcat_port}/gsdl3/services/{site_name} -->
+    <site name="localsite" localSite="localsite" type="soap"/>
+  </siteList>
+  <serviceClusterList/>
+  <serviceRackList/>
+</siteConfig>
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/README
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/README	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/README	(revision 13928)
@@ -0,0 +1,57 @@
+The Sample XML texts collection.
+
+This README provides directions on how to rebuild the collection if necessary, 
+and how to create a new collection using this method.
+
+Building the gberg collection (linux):
+
+Starting from the gberg directory (where this README file is located):
+cd java
+javac *.java
+cd ..
+java -classpath $CLASSPATH:./java BuildXMLColl $GSDL3HOME/web/sites/localsite gberg
+mv building index
+cp etc/buildConfig.xml index
+cp import/*.dtd $GSDL3HOME/resources/dtd/
+
+The building process:
+
+There are two stages, import and build.
+Importing goes through the xml documents in the import directory and adds 
+gs3:id attributes to indexable nodes. Building makes another pass though the 
+documents, indexing any indexable nodes, and assigning them node ids. Node 
+ids are made up of several parts: document id, scope, tag name, gs3:id. 
+Document id refers to the work, and is generated from the original document 
+filename. For example, origin.xml becomes origin. The scope part is optional. 
+Tag name is the name of the node that is to be indexed, and gs3:id is its id.
+
+The class XMLTagInfo provides two methods, isIndexable and isScopable, and is 
+used to determine which tags provide scope, and which tags should be indexed. 
+This is the only part of the build code that is specific to the documents in 
+the collection.
+
+Indexable nodes are those that should be indexed individually. When a search 
+is done, these are the units that will be returned. For instance, suppose a 
+collection contains books with chapters and sections of chapters. To have 
+searching and retrieval at chapter level, the chapter nodes would be made 
+indexable. Alternatively, making the section nodes indexable would provide 
+searching at the smaller section level instead.
+
+Scopable nodes are not necessarily indexed, but are recorded as part of the 
+id as a scope. This is to speed up searching for the appropriate tag during 
+retrieval. Scopeable tags should only occur once per document.
+
+Building other collections:
+
+To use the java building stuff for other XML document collections, you can 
+just modify the XMLTagInfo.java file to include the appropriate tag names for 
+your XML documents. Then put import documents into the import directory, and 
+run the BuildXMLColl program as above. Configuration files will need to be 
+created for the collection (etc/collectionConfig.xml and 
+index/buildConfig.xml).
+
+The Greenstone runtime software has problems locating DTDs, so any DTDs for 
+your collection should be placed in the collection's resources directory.
+If DTD files are shared between collections, they can go into the 
+WEB-INF/classes directory (in gsdl3/web or tomcat/webapps/gsdl3, depending on 
+your setup).
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/etc/buildConfig.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/etc/buildConfig.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/etc/buildConfig.xml	(revision 13928)
@@ -0,0 +1,16 @@
+<buildConfig xmlns:gsf="http://www.greenstone.org/configformat" >
+  <metadataList>
+    <metadata name="numDocs">4</metadata>
+    <metadata name="buildType">lucene</metadata>
+  </metadataList>
+  <serviceRackList>
+    <serviceRack name="GutBookRetrieve">
+      <paramList>
+	<param name="tocXSLT" value="produce-toc"/>
+	<param name="documentEncoding" value="UTF-8"/>
+	<param name="documentRootTag" value="book"/>
+      </paramList>
+    </serviceRack>
+    <serviceRack name="LuceneSearch"/>
+  </serviceRackList>
+</buildConfig>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/etc/collectionConfig.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/etc/collectionConfig.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/etc/collectionConfig.xml	(revision 13928)
@@ -0,0 +1,61 @@
+<collectionConfig 
+  xmlns:gsf="http://www.greenstone.org/greenstone3/schema/ConfigFormat" 
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
+  <metadataList>
+    <metadata name="creator">greenstone@cs.waikato.ac.nz</metadata>
+  </metadataList>
+  <displayItemList>
+    <displayItem name='name' lang='en'>Sample XML Texts Collection</displayItem>
+    <displayItem name='icon' lang='en'>gberg.gif</displayItem>
+    <displayItem name='smallicon' lang='en'>gbergsm.gif</displayItem>
+    <displayItem name='description' lang='en'>
+&lt;p&gt;This collection is designed to demonstrate some of the flexibility of the Greenstone 3 architecture. Collections are not restricted to those built using the standard building process, but rather can be anything you want, as long as suitable services are provided.&lt;/p&gt; 
+&lt;p&gt; This collection contains 4 documents obtained from the &lt;a href="http://gutenberg.net/"&gt;Gutenberg project&lt;/a&gt;. Project Gutenberg documents are marked up in XML, and come with DTDs and CSS stylesheets. The collection has not been built using either Greenstone2 or Greenstone3 style building. Instead, simple java programs using the Lucene API have been created to do the indexing, and document retrieval is simply done from the original (actually slightly modified) XML documents. A description of the building process can be found in the &lt;a href="sites/localsite/collect/gberg/README"&gt;README&lt;/a&gt; file for this collection.&lt;/p&gt; 
+&lt;p&gt; This collection has a different appearance to standard collections, accomplished through the use of custom XSLT files, found in the transform directory of the collection. The 'about' page for the collection shows a list of all the documents. This is achieved by using a new about.xsl file. Document display is quite different for this collection: the display can be either table of contents style, or text style. Two new xslts were written to handle the two display types. A new document action also had to be created (XMLDocumentAction), and the interface config file was altered to map the xd action code to this new Action class.&lt;/p&gt; 
+&lt;p&gt; &amp;lt;action name='xd' class='XMLDocumentAction'&amp;gt;&lt;br/&gt;
+&amp;nbsp;&amp;nbsp;&amp;lt;subaction name='toc' xslt='document-toc.xsl'/&amp;gt;&lt;br/&gt;
+&amp;nbsp;&amp;nbsp;&amp;lt;subaction name='text' xslt='document-text.xsl'/&amp;gt;&lt;br/&gt;
+&amp;lt;/action&amp;gt;&lt;/p&gt; 
+&lt;p&gt;The collection uses a generic Greenstone Lucene search service, and a specific retrieval service class, GutBookRetrieve. This extends the generic XMLRetrieve serviceRack to handle metadata extraction for the Gutenberg documents.&lt;/p&gt; 
+&lt;p&gt;The collection configuration file can be seen &lt;a href="sites/localsite/collect/gberg/etc/collectionConfig.xml"&gt;here&lt;/a&gt;, and the building configuration file can be seen &lt;a href="sites/localsite/collect/gberg/index/buildConfig.xml"&gt;here&lt;/a&gt;.&lt;/p&gt;
+</displayItem>
+  </displayItemList>
+  <search>
+    <format>
+      <gsf:template match="documentNode">
+	<xsl:param name="collName"/>
+	<xsl:param name="serviceName"/>
+	<td>
+	<b><a href="{$library_name}?a=xd&amp;sa=text&amp;c={$collName}&amp;d={@nodeID}&amp;p.a=q&amp;p.s={$serviceName}"><xsl:choose><xsl:when test="metadataList/metadata[@name='Title']"><gsf:metadata name="Title"/></xsl:when><xsl:otherwise>(section)</xsl:otherwise></xsl:choose></a></b> from <b><a href="{$library_name}?a=xd&amp;sa=toc&amp;c={$collName}&amp;d={@nodeID}.rt&amp;p.a=q&amp;p.s={$serviceName}"><gsf:metadata name="Title" select="root"/></a></b>
+	</td>
+      </gsf:template>
+    </format>
+  </search>
+  <browse/>
+  <documentList>
+    <document name='origin'>
+      <metadataList>
+	<metadata name='Title'>On the Origin of Species</metadata>
+	<metadata name="Author">Charles Darwin</metadata>
+      </metadataList>
+    </document>
+    <document name='iliad'>
+      <metadataList>
+	<metadata name='Title'>The Iliad</metadata>
+	<metadata name="Author">Homer</metadata>
+      </metadataList>
+    </document>
+    <document name='owlcreek'>
+      <metadataList>
+	<metadata name='Title'>An Occurrence At Owl Creek Bridge</metadata>
+	<metadata name="Author">Ambrose Bierce</metadata>
+      </metadataList>
+    </document>
+    <document name='fishpatrol'>
+      <metadataList>
+	<metadata name='Title'>Tales of the Fish Patrol</metadata>
+	<metadata name="Author">Jack London</metadata>
+      </metadataList>
+    </document>
+  </documentList>
+</collectionConfig>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/etc/collectionInit.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/etc/collectionInit.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/etc/collectionInit.xml	(revision 13928)
@@ -0,0 +1,2 @@
+<collectionInit class="XMLCollection"/>
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/import/bookfrag.dtd
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/import/bookfrag.dtd	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/import/bookfrag.dtd	(revision 13928)
@@ -0,0 +1,529 @@
+<!--This is bookfrag DTD-->
+
+<!--entity declarations-->
+<!--#############################################-->
+
+<!ENTITY % stdatts 
+"ref   IDREF  #IMPLIED
+ id    ID     #IMPLIED
+ type  CDATA  #IMPLIED
+ role  CDATA  #IMPLIED
+ class CDATA  #IMPLIED"
+>
+
+<!ENTITY % inline.class "|quote|emph|ital|reference|date|place|name|graphic|txterr|mkuperr|misc ">
+
+<!ENTITY % block.class "|letter|blockquote|footnote|note|list|deflist|table|blockgraphic">
+
+
+<!-- the top level element-->
+<!--##############################################-->
+
+<!ELEMENT book (acknowledge?,meta*,frontmatter?,bookbody,backmatter?,endmeta*)>
+
+<!--begin top level element declarations-->
+<!--##############################################-->
+
+
+<!--the acknowledge element is for a simple statement 
+designed to be placed at the beginning of the visible document.
+Suggested content:
+  Name of Book
+  Author
+  PG and HWG blurb
+  Original Transcriber + date
+  Marker 
+  e.g.
+  "Origin of the Species by Charles Darwin
+  A project of Project Gutenberg and the HTML Writers Guild.
+  Transcribed by  
+  Markup by Frank Boumphrey. Jan 22 2000"
+  -->
+
+<!ELEMENT acknowledge (#PCDATA %inline.class;)*>
+<!ATTLIST acknowledge
+  %stdatts;
+>
+
+<!--the meta tags are here to provide a means for comment 
+at either the very beginning or end of the document-->
+<!ELEMENT meta EMPTY>
+<!ATTLIST meta
+   content  CDATA  #REQUIRED
+   id       ID     #IMPLIED
+>
+
+<!ELEMENT endmeta EMPTY >
+<!ATTLIST endmeta
+   content  CDATA  #REQUIRED
+   id       ID     #IMPLIED
+>
+
+
+
+<!--the bookbody element contains the body of the book it can 
+consist of either part or chapter divisions-->
+
+<!ELEMENT bookbody (part*|chapter*)>
+
+<!--
+the backmatter element contains the backmatter of the book -->
+
+<!ELEMENT backmatter ((appendix|index|glossary|biblio|note)*,colophon?)>
+
+<!--The endmeta tag is groupedwith its twin meta-->
+
+
+<!--end top level element declarations-->
+
+<!--begin frontmatter element declarations-->
+<!--##############################################-->
+
+<!ELEMENT frontmatter (htitlepage|copypage|epigraph|titlepage|
+                toc|acksect|dedication|preface|introduction|miscfm)*>
+
+<!ELEMENT htitlepage (#PCDATA|title|subtitle|author|para|poem|song %inline.class;)*>
+<!ATTLIST htitlepage
+  %stdatts;
+>
+
+<!ELEMENT copypage (#PCDATA|para|poem|song|note %inline.class;)*>
+<!ATTLIST copypage
+  %stdatts;
+>
+
+<!ELEMENT epigraph (#PCDATA|para|poem|song|note|blockquote %inline.class;)*>
+<!ATTLIST epigraph
+  %stdatts;
+>
+
+
+<!ELEMENT titlepage (#PCDATA|partnum|title|subtitle|author|pubinfo|para|poem|song|note|line %inline.class;)*>
+<!ATTLIST titlepage
+  %stdatts;
+>
+
+<!ELEMENT pubinfo (#PCDATA|para|line %inline.class;)*>
+<!ATTLIST pubinfo
+  %stdatts;
+>
+
+
+<!ELEMENT toc (#PCDATA|title|subtitle|subsubtitle|item|list|deflist %inline.class;)*>
+<!--use type or role to describe toctype="other"-->
+<!ATTLIST toc
+  toctype (contents|maps|graphics|tables|other) "contents" 
+  %stdatts;
+>
+
+<!ELEMENT acksect (#PCDATA|para|poem|song|note %inline.class;)*>
+<!ATTLIST acksect
+  %stdatts;
+>
+
+<!ELEMENT dedication (#PCDATA|title|para|poem|song|note %inline.class;)*>
+<!ATTLIST dedication
+  %stdatts;
+>
+
+
+<!ELEMENT preface ((title|chapheader)?,(para|poem|song|sect1|simplesect %block.class;)*,endchap?,preauthor?)>
+<!ATTLIST preface  %stdatts;
+>
+
+<!ELEMENT introduction ((title|chapheader)?,(para|poem|song|sect1|simplesect %block.class;)*,endchap?)>
+<!ATTLIST introduction  %stdatts;
+>
+
+<!ELEMENT miscfm (#PCDATA|para|poem|song|note %inline.class;)*>
+<!ATTLIST miscfm
+  %stdatts;
+>
+
+<!ELEMENT preauthor (#PCDATA|author %inline.class;)*>
+<!ATTLIST preauthor
+  %stdatts;
+>
+
+
+
+<!--end frontmatter element declarations-->
+
+<!--begin bookbody element declarations-->
+<!--##############################################-->
+
+
+<!ELEMENT part (acknowledge?,(titlepage|toc|htitlepage)*,chapter*)>
+<!ATTLIST part
+  %stdatts;
+>
+
+<!ELEMENT chapter ((title|chapheader)?,(para|poem|song|sect1|simplesect|page %block.class;)*,endchap?)>
+<!ATTLIST chapter  %stdatts;
+>
+
+<!--end bookbody element declarations-->
+
+<!--the lowerlevel bookbody elements-->
+<!--##############################################-->
+
+<!--the chapter heading elements-->
+<!--##############################################-->
+
+
+
+
+<!ELEMENT title (#PCDATA %inline.class;)*>
+<!ATTLIST title
+  %stdatts;
+>
+
+<!ELEMENT subtitle (#PCDATA %inline.class;)*>
+<!ATTLIST subtitle
+  %stdatts;
+>
+
+<!ELEMENT subsubtitle (#PCDATA %inline.class;)*>
+<!ATTLIST subsubtitle
+  %stdatts;
+>
+
+
+
+<!--validity constraint. Only one title,chapnum and chapsummary -->
+<!ELEMENT chapheader (title|subtitle|chapnum|chapsummary|blockquote|para|note)*>
+<!ATTLIST chapheader
+  %stdatts;
+>
+
+
+<!ELEMENT chapnum (#PCDATA %inline.class;)*>
+<!ATTLIST chapnum
+  %stdatts;
+>
+
+<!ELEMENT chapsummary (#PCDATA %inline.class;)*>
+<!ATTLIST chapsummary
+  %stdatts;
+>
+
+
+<!--begin backmatter element declarations-->
+<!--##############################################-->
+
+<!--end backmatter element declarations-->
+
+<!ELEMENT index (title|item|list|deflist|note)*>
+<!ATTLIST index
+  indtype (contents|authors|firstlines|tables|other) "contents" 
+  %stdatts;
+>
+
+<!ELEMENT glossary (title|item|list|deflist|note)*>
+<!ATTLIST glossary  
+  %stdatts;
+>
+
+<!ELEMENT biblio (title|item|list|deflist|note)*>
+<!ATTLIST biblio  
+  %stdatts;
+>
+
+
+<!ELEMENT appendix ((title|chapheader)?,(para|poem|song|sect1|simplesect %block.class;)*,endchap?)>
+<!ATTLIST appendix  %stdatts;
+>
+
+<!ELEMENT colophon (#PCDATA|para|poem|song %inline.class;)*>
+<!ATTLIST colophon
+  %stdatts;
+>
+
+<!--the block elements-->
+<!--##############################################-->
+
+
+<!--validity constraint. Only one title per paragraph-->
+<!ELEMENT para (#PCDATA|title %inline.class;)*>
+<!ATTLIST para
+  %stdatts;
+>
+
+<!ELEMENT simplesect (title,(subtitle|para|poem|song %block.class;)*)>
+<!ATTLIST simplesect
+  %stdatts;
+>
+
+<!ELEMENT sect1 (title,(sect2|simplesect|para|poem|song %block.class;)*)>
+<!ATTLIST sect1
+  %stdatts;
+>
+
+<!ELEMENT sect2 (title,(sect3|simplesect|subtitle|para|poem|song  %block.class;)*)>
+<!ATTLIST sect2
+  %stdatts;
+>
+
+<!ELEMENT sect3 (title,(sect4|simplesect|subtitle|para|poem|song  %block.class;)*)>
+<!ATTLIST sect3
+  %stdatts;
+>
+
+<!ELEMENT sect4 (title,(simplesect|subtitle|para|poem|song  %block.class;)*)>
+<!ATTLIST sect4
+  %stdatts;
+>
+
+<!ELEMENT page (#PCDATA %inline.class;)*>
+<!ATTLIST page
+  %stdatts;
+>
+
+<!ELEMENT misc (#PCDATA %inline.class;)*>
+<!ATTLIST misc
+  %stdatts;
+>
+
+
+
+<!ELEMENT blockquote (title?,(para|poem|song)*,attrib?)>
+<!ATTLIST blockquote
+  %stdatts;
+>
+
+<!ELEMENT attrib (#PCDATA %inline.class;)*>
+<!ATTLIST attrib
+  %stdatts;
+>
+
+<!ELEMENT caption (#PCDATA %inline.class;)*>
+<!ATTLIST caption
+  %stdatts;
+>
+<!--##############################################-->
+<!--poetry and songs in the text-->
+<!ELEMENT poem (#PCDATA|title|subtitle|verse|line|note|footnote %inline.class;)*>
+<!ATTLIST poem
+  %stdatts;
+>
+
+<!ELEMENT song (#PCDATA|title|subtitle|verse|line|note|footnote %inline.class;)*>
+<!ATTLIST song
+  %stdatts;
+>
+
+
+<!ELEMENT verse (title|subtitle|line|note)*>
+<!ATTLIST verse
+  %stdatts;
+>
+
+<!ELEMENT line (#PCDATA %inline.class;)*>
+<!ATTLIST line
+  %stdatts;
+>
+
+
+<!--validity constraint: Only one title per poem or per verse-->
+
+<!--end of poetry in the text-->
+
+<!--letter module-->
+
+<!ELEMENT letter (address|to|from|salut|sig|title|subtitle|para|poem|song|line|note)*>
+<!ATTLIST letter
+  %stdatts;
+>
+
+<!ELEMENT address (#PCDATA|para|line %inline.class;)*>
+<!ATTLIST address
+  %stdatts;
+>
+
+<!ELEMENT to (#PCDATA|para|line %inline.class;)*>
+<!ATTLIST to
+  %stdatts;
+>
+
+
+<!ELEMENT from (#PCDATA|para|line %inline.class;)*>
+<!ATTLIST from
+  %stdatts;
+>
+
+
+<!ELEMENT salut (#PCDATA|para|line %inline.class;)*>
+<!ATTLIST salut
+  %stdatts;
+>
+
+
+<!ELEMENT sig (#PCDATA|para|line %inline.class;)*>
+<!ATTLIST sig
+  %stdatts;
+>
+
+
+<!--end letters module-->
+<!--endchap-->
+<!--##############################################-->
+<!--
+  Endchap should only be used when there is a 
+  considerable ammount of material to be organized.
+  For the occasional note footnote and note will suffice
+-->
+
+<!ELEMENT endchap (para %block.class;)*>
+<!ATTLIST endchap  %stdatts;
+>
+
+<!--lists-->
+<!--##############################################-->
+
+
+<!ELEMENT list (title?,(list|item)*)>
+<!ATTLIST list
+  %stdatts;
+>
+
+<!ELEMENT item (#PCDATA|para|poem|song|simplesect %block.class; %inline.class;)*>
+<!ATTLIST item
+  %stdatts;
+>
+
+<!ELEMENT deflist (title?,(item,desc?,def*)*)>
+<!ATTLIST deflist
+  %stdatts;
+>
+
+<!ELEMENT desc (#PCDATA %inline.class;)*>
+<!ATTLIST desc
+  %stdatts;
+>
+
+<!ELEMENT def (#PCDATA %inline.class;)*>
+<!ATTLIST def
+  %stdatts;
+>
+<!--end lists-->
+<!--table element-->
+<!--##############################################-->
+
+
+<!ELEMENT table (title?,row*,caption?)>
+<!ATTLIST table
+  %stdatts;
+>
+
+<!ELEMENT row (cell)*>
+<!ATTLIST row
+  %stdatts;
+>
+
+<!ELEMENT cell (#PCDATA %block.class; %inline.class;)*>
+<!ATTLIST cell
+  %stdatts;
+>
+
+<!--end table-->
+
+<!--graphics-->
+<!--##############################################-->
+
+<!--
+  Note that the required desc attribute is added 
+  text composed by the marker.
+-->
+
+<!ELEMENT graphic EMPTY >
+<!ATTLIST graphic
+  desc CDATA #REQUIRED
+  href CDATA #REQUIRED
+  %stdatts;
+>
+
+<!ELEMENT blockgraphic (title?,graphic,caption?)>
+<!ATTLIST blockgraphic
+  %stdatts;
+>
+
+
+<!--the inline elements-->
+<!--##############################################-->
+
+
+
+<!ELEMENT footnote (#PCDATA %inline.class;)*>
+<!ATTLIST footnote
+  %stdatts;
+>
+
+<!ELEMENT note (#PCDATA %inline.class;)*>
+<!ATTLIST note
+  %stdatts;
+>
+
+
+<!ELEMENT quote (#PCDATA %inline.class;)*>
+<!ATTLIST quote
+  %stdatts;
+>
+
+<!ELEMENT emph (#PCDATA %inline.class;)*>
+<!ATTLIST emph
+  %stdatts;
+>
+
+<!ELEMENT ital (#PCDATA %inline.class;)*>
+<!ATTLIST ital
+  %stdatts;
+>
+
+<!ELEMENT reference (#PCDATA %inline.class;)*>
+<!ATTLIST reference
+  %stdatts;
+>
+
+<!ELEMENT author (#PCDATA %inline.class;)*>
+<!ATTLIST author
+  %stdatts;
+>
+
+<!ELEMENT date (#PCDATA %inline.class;)*>
+<!ATTLIST date
+  %stdatts;
+>
+
+<!ELEMENT place (#PCDATA %inline.class;)*>
+<!ATTLIST place
+  %stdatts;
+>
+
+<!ELEMENT name (#PCDATA %inline.class;)*>
+<!ATTLIST name
+  %stdatts;
+>
+
+
+<!--use to enclose the text you think is in error
+optional explanation if error is not obvious-->
+<!ELEMENT txterr (#PCDATA)*>
+<!ATTLIST txterr
+  explain  CDATA  #IMPLIED
+  %stdatts;
+>
+
+<!--an explanation is required-->
+<!ELEMENT mkuperr EMPTY>
+<!ATTLIST mkuperr
+  explain  CDATA  #REQUIRED
+  %stdatts;
+>
+
+<!--added as titlepage content  Feb/6/00-->
+<!ELEMENT partnum (#PCDATA %inline.class;)*>
+<!ATTLIST partnum
+  %stdatts;
+>
+
+<!--End of bookfrag dtd-->
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/import/fishpatrol.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/import/fishpatrol.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/import/fishpatrol.xml	(revision 13928)
@@ -0,0 +1,5033 @@
+<?xml version="1.0"?>
+<!DOCTYPE gutbook SYSTEM "gutbook1.dtd">
+
+<?xml-stylesheet type="text/css" href="darwin.css"?>
+
+
+<gutbook>
+<gutblurb>
+<para>
+Project Gutenberg's Etext of Tales of the Fish Patrol, by London
+#8 in our series by Jack London
+</para>
+
+<para>
+
+Copyright laws are changing all over the world, be sure to check
+the copyright laws for your country before posting these files!!
+</para>
+
+<para>
+Please take a look at the important information in this header.
+We encourage you to keep this file on your own disk, keeping an
+electronic path open for the next readers.  Do not remove this.
+</para>
+
+<para>
+
+**Welcome To The World of Free Plain Vanilla Electronic Texts**
+</para>
+
+<para>
+**Etexts Readable By Both Humans and By Computers, Since 1971**
+</para>
+
+<para>
+*These Etexts Prepared By Hundreds of Volunteers and Donations*
+</para>
+
+<para>
+Information on contacting Project Gutenberg to get Etexts, and
+further information is included below.  We need your donations.
+</para>
+
+<para>
+
+Tales of the Fish Patrol
+</para>
+
+<para>
+by Jack London
+</para>
+
+<para>
+May, 1997  [Etext #911]
+</para>
+
+<para>
+
+Project Gutenberg's Etext of Tales of the Fish Patrol, by London
+*****This file should be named totfp10.txt or totfp10.zip******
+</para>
+
+<para>
+Corrected EDITIONS of our etexts get a new NUMBER, totfp11.txt.
+VERSIONS based on separate sources get new LETTER, totfp10a.txt.
+</para>
+
+<para>
+
+Scanned and proofed by David Price
+ccx074@coventry.ac.uk
+</para>
+
+<para>
+
+We are now trying to release all our books one month in advance
+of the official release dates, for time for better editing.
+</para>
+
+<para>
+Please note:  neither this list nor its contents are final till
+midnight of the last day of the month of any such announcement.
+The official release date of all Project Gutenberg Etexts is at
+Midnight, Central Time, of the last day of the stated month.  A
+preliminary version may often be posted for suggestion, comment
+and editing by those who wish to do so.  To be sure you have an
+up to date first edition [xxxxx10x.xxx] please check file sizes
+in the first week of the next month.  Since our ftp program has
+a bug in it that scrambles the date [tried to fix and failed] a
+look at the file size will have to do, but we will try to see a
+new copy has at least one byte more or less.
+</para>
+
+<para>
+
+Information about Project Gutenberg (one page)
+</para>
+
+<para>
+We produce about two million dollars for each hour we work.  The
+fifty hours is one conservative estimate for how long it we take
+to get any etext selected, entered, proofread, edited, copyright
+searched and analyzed, the copyright letters written, etc.  This
+projected audience is one hundred million readers.  If our value
+per text is nominally estimated at one dollar then we produce $2
+million dollars per hour this year as we release thirty-two text
+files per month:  or 400 more Etexts in 1996 for a total of 800.
+If these reach just 10% of the computerized population, then the
+total should reach 80 billion Etexts.
+</para>
+
+<para>
+The Goal of Project Gutenberg is to Give Away One Trillion Etext
+Files by the December 31, 2001.  [10,000 x 100,000,000=Trillion]
+This is ten thousand titles each to one hundred million readers,
+which is only 10% of the present number of computer users.  2001
+should have at least twice as many computer users as that, so it
+will require us reaching less than 5% of the users in 2001.
+</para>
+
+<para>
+
+We need your donations more than ever!
+</para>
+
+<para>
+
+All donations should be made to "Project Gutenberg/CMU": and are
+tax deductible to the extent allowable by law.  (CMU = Carnegie-
+Mellon University).
+</para>
+
+<para>
+For these and other matters, please mail to:
+</para>
+
+<para>
+Project Gutenberg
+P. O. Box  2782
+Champaign, IL 61825
+</para>
+
+<para>
+When all other email fails try our Executive Director:
+Michael S. Hart &lt;hart@pobox.com&gt;
+</para>
+
+<para>
+We would prefer to send you this information by email
+(Internet, Bitnet, Compuserve, ATTMAIL or MCImail).
+</para>
+
+<para>
+******
+If you have an FTP program (or emulator), please
+FTP directly to the Project Gutenberg archives:
+[Mac users, do NOT point and click. . .type]
+</para>
+
+<para>
+ftp uiarchive.cso.uiuc.edu
+login:  anonymous
+password:  your@login
+cd etext/etext90 through /etext96
+or cd etext/articles [get suggest gut for more information]
+dir [to see files]
+get or mget [to get files. . .set bin for zip files]
+GET INDEX?00.GUT
+for a list of books
+and
+GET NEW GUT for general information
+and
+MGET GUT* for newsletters.
+</para>
+
+<para>
+**Information prepared by the Project Gutenberg legal advisor**
+(Three Pages)
+</para>
+
+<para>
+
+***START**THE SMALL PRINT!**FOR PUBLIC DOMAIN ETEXTS**START***
+Why is this "Small Print!" statement here?  You know: lawyers.
+They tell us you might sue us if there is something wrong with
+your copy of this etext, even if you got it for free from
+someone other than us, and even if what's wrong is not our
+fault.  So, among other things, this "Small Print!" statement
+disclaims most of our liability to you.  It also tells you how
+you can distribute copies of this etext if you want to.
+</para>
+
+<para>
+*BEFORE!* YOU USE OR READ THIS ETEXT
+By using or reading any part of this PROJECT GUTENBERG-tm
+etext, you indicate that you understand, agree to and accept
+this "Small Print!" statement.  If you do not, you can receive
+a refund of the money (if any) you paid for this etext by
+sending a request within 30 days of receiving it to the person
+you got it from.  If you received this etext on a physical
+medium (such as a disk), you must return it with your request.
+</para>
+
+<para>
+ABOUT PROJECT GUTENBERG-TM ETEXTS
+This PROJECT GUTENBERG-tm etext, like most PROJECT GUTENBERG-
+tm etexts, is a "public domain" work distributed by Professor
+Michael S. Hart through the Project Gutenberg Association at
+Carnegie-Mellon University (the "Project").  Among other
+things, this means that no one owns a United States copyright
+on or for this work, so the Project (and you!) can copy and
+distribute it in the United States without permission and
+without paying copyright royalties.  Special rules, set forth
+below, apply if you wish to copy and distribute this etext
+under the Project's "PROJECT GUTENBERG" trademark.
+</para>
+
+<para>
+To create these etexts, the Project expends considerable
+efforts to identify, transcribe and proofread public domain
+works.  Despite these efforts, the Project's etexts and any
+medium they may be on may contain "Defects".  Among other
+things, Defects may take the form of incomplete, inaccurate or
+corrupt data, transcription errors, a copyright or other
+intellectual property infringement, a defective or damaged
+disk or other etext medium, a computer virus, or computer
+codes that damage or cannot be read by your equipment.
+</para>
+
+<para>
+LIMITED WARRANTY; DISCLAIMER OF DAMAGES
+But for the "Right of Replacement or Refund" described below,
+[1] the Project (and any other party you may receive this
+etext from as a PROJECT GUTENBERG-tm etext) disclaims all
+liability to you for damages, costs and expenses, including
+legal fees, and [2] YOU HAVE NO REMEDIES FOR NEGLIGENCE OR
+UNDER STRICT LIABILITY, OR FOR BREACH OF WARRANTY OR CONTRACT,
+INCLUDING BUT NOT LIMITED TO INDIRECT, CONSEQUENTIAL, PUNITIVE
+OR INCIDENTAL DAMAGES, EVEN IF YOU GIVE NOTICE OF THE
+POSSIBILITY OF SUCH DAMAGES.
+</para>
+
+<para>
+If you discover a Defect in this etext within 90 days of
+receiving it, you can receive a refund of the money (if any)
+you paid for it by sending an explanatory note within that
+time to the person you received it from.  If you received it
+on a physical medium, you must return it with your note, and
+such person may choose to alternatively give you a replacement
+copy.  If you received it electronically, such person may
+choose to alternatively give you a second opportunity to
+receive it electronically.
+</para>
+
+<para>
+THIS ETEXT IS OTHERWISE PROVIDED TO YOU "AS-IS".  NO OTHER
+WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, ARE MADE TO YOU AS
+TO THE ETEXT OR ANY MEDIUM IT MAY BE ON, INCLUDING BUT NOT
+LIMITED TO WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
+PARTICULAR PURPOSE.
+</para>
+
+<para>
+Some states do not allow disclaimers of implied warranties or
+the exclusion or limitation of consequential damages, so the
+above disclaimers and exclusions may not apply to you, and you
+may have other legal rights.
+</para>
+
+<para>
+INDEMNITY
+You will indemnify and hold the Project, its directors,
+officers, members and agents harmless from all liability, cost
+and expense, including legal fees, that arise directly or
+indirectly from any of the following that you do or cause:
+[1] distribution of this etext, [2] alteration, modification,
+or addition to the etext, or [3] any Defect.
+</para>
+
+<para>
+DISTRIBUTION UNDER "PROJECT GUTENBERG-tm"
+You may distribute copies of this etext electronically, or by
+disk, book or any other medium if you either delete this
+"Small Print!" and all other references to Project Gutenberg,
+or:
+</para>
+
+<para>
+[1]  Only give exact copies of it.  Among other things, this
+     requires that you do not remove, alter or modify the
+     etext or this "small print!" statement.  You may however,
+     if you wish, distribute this etext in machine readable
+     binary, compressed, mark-up, or proprietary form,
+     including any form resulting from conversion by word pro-
+     cessing or hypertext software, but only so long as
+     *EITHER*:
+</para>
+
+<para>
+     [*]  The etext, when displayed, is clearly readable, and
+          does *not* contain characters other than those
+          intended by the author of the work, although tilde
+          (~), asterisk (*) and underline (_) characters may
+          be used to convey punctuation intended by the
+          author, and additional characters may be used to
+          indicate hypertext links; OR
+</para>
+
+<para>
+     [*]  The etext may be readily converted by the reader at
+          no expense into plain ASCII, EBCDIC or equivalent
+          form by the program that displays the etext (as is
+          the case, for instance, with most word processors);
+          OR
+</para>
+
+<para>
+     [*]  You provide, or agree to also provide on request at
+          no additional cost, fee or expense, a copy of the
+          etext in its original plain ASCII form (or in EBCDIC
+          or other equivalent proprietary form).
+</para>
+
+<para>
+[2]  Honor the etext refund and replacement provisions of this
+     "Small Print!" statement.
+</para>
+
+<para>
+[3]  Pay a trademark license fee to the Project of 20% of the
+     net profits you derive calculated using the method you
+     already use to calculate your applicable taxes.  If you
+     don't derive profits, no royalty is due.  Royalties are
+     payable to "Project Gutenberg Association/Carnegie-Mellon
+     University" within the 60 days following each
+     date you prepare (or were legally required to prepare)
+     your annual (or equivalent periodic) tax return.
+</para>
+
+<para>
+WHAT IF YOU *WANT* TO SEND MONEY EVEN IF YOU DON'T HAVE TO?
+The Project gratefully accepts contributions in money, time,
+scanning machines, OCR software, public domain etexts, royalty
+free copyright licenses, and every other sort of contribution
+you can think of.  Money should be paid to "Project Gutenberg
+Association / Carnegie-Mellon University".
+</para>
+
+<para>
+*END*THE SMALL PRINT! FOR PUBLIC DOMAIN ETEXTS*Ver.04.29.93*END*
+</para>
+
+
+
+<para>
+Tales of the Fish Patrol by Jack London
+Scanned and proofed by David Price
+ccx074@coventry.ac.uk
+</para>
+</gutblurb>
+
+<markupblurb>
+Original markup by Frank Boumphrey.  2/4/2000
+Validated against gutbook1.dtd using MSXML parser
+</markupblurb>
+
+
+<book>
+<acknowledge>A production of Project Gutenberg and the HTML Writers Guild. E-text by David Price. Markup by Frank Boumphrey</acknowledge>
+<frontmatter>
+<titlepage>
+<title>
+Tales of the Fish Patrol
+</title>
+<author>Jack London</author>
+</titlepage>
+</frontmatter>
+
+<bookbody>
+<chapter>
+<title>
+WHITE AND YELLOW</title>
+
+
+<para>
+San Francisco Bay is so large that often its storms are more
+disastrous to ocean-going craft than is the ocean itself in its
+violent moments.  The waters of the bay contain all manner of fish,
+wherefore its surface is ploughed by the keels of all manner of
+fishing boats manned by all manner of fishermen.  To protect the
+fish from this motley floating population many wise laws have been
+passed, and there is a fish patrol to see that these laws are
+enforced.  Exciting times are the lot of the fish patrol:  in its
+history more than one dead patrolman has marked defeat, and more
+often dead fishermen across their illegal nets have marked success.
+</para>
+
+<para>
+Wildest among the fisher-folk may be accounted the Chinese shrimp-
+catchers.  It is the habit of the shrimp to crawl along the bottom
+in vast armies till it reaches fresh water, when it turns about and
+crawls back again to the salt.  And where the tide ebbs and flows,
+the Chinese sink great bag-nets to the bottom, with gaping mouths,
+into which the shrimp crawls and from which it is transferred to
+the boiling-pot.  This in itself would not be bad, were it not for
+the small mesh of the nets, so small that the tiniest fishes,
+little new-hatched things not a quarter of an inch long, cannot
+pass through.  The beautiful beaches of Points Pedro and Pablo,
+where are the shrimp-catchers' villages, are made fearful by the
+stench from myriads of decaying fish, and against this wasteful
+destruction it has ever been the duty of the fish patrol to act.
+</para>
+
+<para>
+When I was a youngster of sixteen, a good sloop-sailor and all-
+round bay-waterman, my sloop, the Reindeer, was chartered by the
+Fish Commission, and I became for the time being a deputy
+patrolman.  After a deal of work among the Greek fishermen of the
+Upper Bay and rivers, where knives flashed at the beginning of
+trouble and men permitted themselves to be made prisoners only
+after a revolver was thrust in their faces, we hailed with delight
+an expedition to the Lower Bay against the Chinese shrimp-catchers.
+</para>
+
+<para>
+There were six of us, in two boats, and to avoid suspicion we ran
+down after dark and dropped anchor under a projecting bluff of land
+known as Point Pinole.  As the east paled with the first light of
+dawn we got under way again, and hauled close on the land breeze as
+we slanted across the bay toward Point Pedro.  The morning mists
+curled and clung to the water so that we could see nothing, but we
+busied ourselves driving the chill from our bodies with hot coffee.
+Also we had to devote ourselves to the miserable task of bailing,
+for in some incomprehensible way the Reindeer had sprung a generous
+leak.  Half the night had been spent in overhauling the ballast and
+exploring the seams, but the labor had been without avail.  The
+water still poured in, and perforce we doubled up in the cockpit
+and tossed it out again.
+</para>
+
+<para>
+After coffee, three of the men withdrew to the other boat, a
+Columbia River salmon boat, leaving three of us in the Reindeer.
+Then the two craft proceeded in company till the sun showed over
+the eastern sky-line.  Its fiery rays dispelled the clinging
+vapors, and there, before our eyes, like a picture, lay the shrimp
+fleet, spread out in a great half-moon, the tips of the crescent
+fully three miles apart, and each junk moored fast to the buoy of a
+shrimp-net.  But there was no stir, no sign of life.
+</para>
+
+<para>
+The situation dawned upon us.  While waiting for slack water, in
+which to lift their heavy nets from the bed of the bay, the Chinese
+had all gone to sleep below.  We were elated, and our plan of
+battle was swiftly formed.
+</para>
+
+<para>
+"Throw each of your two men on to a junk," whispered Le Grant to me
+from the salmon boat.  "And you make fast to a third yourself.
+We'll do the same, and there's no reason in the world why we
+shouldn't capture six junks at the least."
+</para>
+
+<para>
+Then we separated.  I put the Reindeer about on the other tack, ran
+up under the lee of a junk, shivered the mainsail into the wind and
+lost headway, and forged past the stern of the junk so slowly and
+so near that one of the patrolmen stepped lightly aboard.  Then I
+kept off, filled the mainsail, and bore away for a second junk.
+</para>
+
+<para>
+Up to this time there had been no noise, but from the first junk
+captured by the salmon boat an uproar now broke forth.  There was
+shrill Oriental yelling, a pistol shot, and more yelling.
+</para>
+
+<para>
+"It's all up.  They're warning the others," said George, the
+remaining patrolman, as he stood beside me in the cockpit.
+</para>
+
+<para>
+By this time we were in the thick of the fleet, and the alarm was
+spreading with incredible swiftness.  The decks were beginning to
+swarm with half-awakened and half-naked Chinese.  Cries and yells
+of warning and anger were flying over the quiet water, and
+somewhere a conch shell was being blown with great success.  To the
+right of us I saw the captain of a junk chop away his mooring line
+with an axe and spring to help his crew at the hoisting of the
+huge, outlandish lug-sail.  But to the left the first heads were
+popping up from below on another junk, and I rounded up the
+Reindeer alongside long enough for George to spring aboard.
+</para>
+
+<para>
+The whole fleet was now under way.  In addition to the sails they
+had gotten out long sweeps, and the bay was being ploughed in every
+direction by the fleeing junks.  I was now alone in the Reindeer,
+seeking feverishly to capture a third prize.  The first junk I took
+after was a clean miss, for it trimmed its sheets and shot away
+surprisingly into the wind.  By fully half a point it outpointed
+the Reindeer, and I began to feel respect for the clumsy craft.
+Realizing the hopelessness of the pursuit, I filled away, threw out
+the main-sheet, and drove down before the wind upon the junks to
+leeward, where I had them at a disadvantage.
+</para>
+
+<para>
+The one I had selected wavered indecisively before me, and, as I
+swung wide to make the boarding gentle, filled suddenly and darted
+away, the smart Mongols shouting a wild rhythm as they bent to the
+sweeps.  But I had been ready for this.  I luffed suddenly.
+Putting the tiller hard down, and holding it down with my body, I
+brought the main-sheet in, hand over hand, on the run, so as to
+retain all possible striking force.  The two starboard sweeps of
+the junk were crumpled up, and then the two boats came together
+with a crash.  The Reindeer's bowsprit, like a monstrous hand,
+reached over and ripped out the junk's chunky mast and towering
+sail.
+</para>
+
+<para>
+This was met by a curdling yell of rage.  A big Chinaman,
+remarkably evil-looking, with his head swathed in a yellow silk
+handkerchief and face badly pock-marked, planted a pike-pole on the
+Reindeer's bow and began to shove the entangled boats apart.
+Pausing long enough to let go the jib halyards, and just as the
+Reindeer cleared and began to drift astern, I leaped aboard the
+junk with a line and made fast.  He of the yellow handkerchief and
+pock-marked face came toward me threateningly, but I put my hand
+into my hip pocket, and he hesitated.  I was unarmed, but the
+Chinese have learned to be fastidiously careful of American hip
+pockets, and it was upon this that I depended to keep him and his
+savage crew at a distance.
+</para>
+
+<para>
+I ordered him to drop the anchor at the junk's bow, to which he
+replied, "No sabbe."  The crew responded in like fashion, and
+though I made my meaning plain by signs, they refused to
+understand.  Realizing the inexpediency of discussing the matter, I
+went forward myself, overran the line, and let the anchor go.
+</para>
+
+<para>
+"Now get aboard, four of you," I said in a loud voice, indicating
+with my fingers that four of them were to go with me and the fifth
+was to remain by the junk.  The Yellow Handkerchief hesitated; but
+I repeated the order fiercely (much more fiercely than I felt), at
+the same time sending my hand to my hip.  Again the Yellow
+Handkerchief was overawed, and with surly looks he led three of his
+men aboard the Reindeer.  I cast off at once, and, leaving the jib
+down, steered a course for George's junk.  Here it was easier, for
+there were two of us, and George had a pistol to fall back on if it
+came to the worst.  And here, as with my junk, four Chinese were
+transferred to the sloop and one left behind to take care of
+things.
+</para>
+
+<para>
+Four more were added to our passenger list from the third junk.  By
+this time the salmon boat had collected its twelve prisoners and
+came alongside, badly overloaded.  To make matters worse, as it was
+a small boat, the patrolmen were so jammed in with their prisoners
+that they would have little chance in case of trouble.
+</para>
+
+<para>
+"You'll have to help us out," said Le Grant.
+</para>
+
+<para>
+I looked over my prisoners, who had crowded into the cabin and on
+top of it.  "I can take three," I answered.
+</para>
+
+<para>
+"Make it four," he suggested, "and I'll take Bill with me."  (Bill
+was the third patrolman.)  "We haven't elbow room here, and in case
+of a scuffle one white to every two of them will be just about the
+right proportion."
+</para>
+
+<para>
+The exchange was made, and the salmon boat got up its spritsail and
+headed down the bay toward the marshes off San Rafael.  I ran up
+the jib and followed with the Reindeer.  San Rafael, where we were
+to turn our catch over to the authorities, communicated with the
+bay by way of a long and tortuous slough, or marshland creek, which
+could be navigated only when the tide was in.  Slack water had
+come, and, as the ebb was commencing, there was need for hurry if
+we cared to escape waiting half a day for the next tide.
+</para>
+
+<para>
+But the land breeze had begun to die away with the rising sun, and
+now came only in failing puffs.  The salmon boat got out its oars
+and soon left us far astern.  Some of the Chinese stood in the
+forward part of the cockpit, near the cabin doors, and once, as I
+leaned over the cockpit rail to flatten down the jib-sheet a bit, I
+felt some one brush against my hip pocket.  I made no sign, but out
+of the corner of my eye I saw that the Yellow Handkerchief had
+discovered the emptiness of the pocket which had hitherto overawed
+him.
+</para>
+
+<para>
+To make matters serious, during all the excitement of boarding the
+junks the Reindeer had not been bailed, and the water was beginning
+to slush over the cockpit floor.  The shrimp-catchers pointed at it
+and looked to me questioningly.
+</para>
+
+<para>
+"Yes," I said.  "Bime by, allee same dlown, velly quick, you no
+bail now.  Sabbe?"
+</para>
+
+<para>
+No, they did not "sabbe," or at least they shook their heads to
+that effect, though they chattered most comprehendingly to one
+another in their own lingo.  I pulled up three or four of the
+bottom boards, got a couple of buckets from a locker, and by
+unmistakable sign-language invited them to fall to.  But they
+laughed, and some crowded into the cabin and some climbed up on
+top.
+</para>
+
+<para>
+Their laughter was not good laughter.  There was a hint of menace
+in it, a maliciousness which their black looks verified.  The
+Yellow Handkerchief, since his discovery of my empty pocket, had
+become most insolent in his bearing, and he wormed about among the
+other prisoners, talking to them with great earnestness.
+</para>
+
+<para>
+Swallowing my chagrin, I stepped down into the cockpit and began
+throwing out the water.  But hardly had I begun, when the boom
+swung overhead, the mainsail filled with a jerk, and the Reindeer
+heeled over.  The day wind was springing up.  George was the
+veriest of landlubbers, so I was forced to give over bailing and
+take the tiller.  The wind was blowing directly off Point Pedro and
+the high mountains behind, and because of this was squally and
+uncertain, half the time bellying the canvas out and the other half
+flapping it idly.
+</para>
+
+<para>
+George was about the most all-round helpless man I had ever met.
+Among his other disabilities, he was a consumptive, and I knew that
+if he attempted to bail, it might bring on a hemorrhage.  Yet the
+rising water warned me that something must be done.  Again I
+ordered the shrimp-catchers to lend a hand with the buckets.  They
+laughed defiantly, and those inside the cabin, the water up to
+their ankles, shouted back and forth with those on top.
+</para>
+
+<para>
+"You'd better get out your gun and make them bail," I said to
+George.
+</para>
+
+<para>
+But he shook his head and showed all too plainly that he was
+afraid.  The Chinese could see the funk he was in as well as I
+could, and their insolence became insufferable.  Those in the cabin
+broke into the food lockers, and those above scrambled down and
+joined them in a feast on our crackers and canned goods.
+</para>
+
+<para>
+"What do we care?" George said weakly.
+</para>
+
+<para>
+I was fuming with helpless anger.  "If they get out of hand, it
+will be too late to care.  The best thing you can do is to get them
+in check right now."
+</para>
+
+<para>
+The water was rising higher and higher, and the gusts, forerunners
+of a steady breeze, were growing stiffer and stiffer.  And between
+the gusts, the prisoners, having gotten away with a week's grub,
+took to crowding first to one side and then to the other till the
+Reindeer rocked like a cockle-shell.  Yellow Handkerchief
+approached me, and, pointing out his village on the Point Pedro
+beach, gave me to understand that if I turned the Reindeer in that
+direction and put them ashore, they, in turn, would go to bailing.
+By now the water in the cabin was up to the bunks, and the bed-
+clothes were sopping.  It was a foot deep on the cockpit floor.
+Nevertheless I refused, and I could see by George's face that he
+was disappointed.
+</para>
+
+<para>
+"If you don't show some nerve, they'll rush us and throw us
+overboard," I said to him.  "Better give me your revolver, if you
+want to be safe."
+</para>
+
+<para>
+"The safest thing to do," he chattered cravenly, "is to put them
+ashore.  I, for one, don't want to be drowned for the sake of a
+handful of dirty Chinamen."
+</para>
+
+<para>
+"And I, for another, don't care to give in to a handful of dirty
+Chinamen to escape drowning," I answered hotly.
+</para>
+
+<para>
+"You'll sink the Reindeer under us all at this rate," he whined.
+"And what good that'll do I can't see."
+</para>
+
+<para>
+"Every man to his taste," I retorted.
+</para>
+
+<para>
+He made no reply, but I could see he was trembling pitifully.
+Between the threatening Chinese and the rising water he was beside
+himself with fright; and, more than the Chinese and the water, I
+feared him and what his fright might impel him to do.  I could see
+him casting longing glances at the small skiff towing astern, so in
+the next calm I hauled the skiff alongside.  As I did so his eyes
+brightened with hope; but before he could guess my intention, I
+stove the frail bottom through with a hand-axe, and the skiff
+filled to its gunwales.
+</para>
+
+<para>
+"It's sink or float together," I said.  "And if you'll give me your
+revolver, I'll have the Reindeer bailed out in a jiffy."
+</para>
+
+<para>
+"They're too many for us," he whimpered.  "We can't fight them
+all."
+</para>
+
+<para>
+I turned my back on him in disgust.  The salmon boat had long since
+passed from sight behind a little archipelago known as the Marin
+Islands, so no help could be looked for from that quarter.  Yellow
+Handkerchief came up to me in a familiar manner, the water in the
+cockpit slushing against his legs.  I did not like his looks.  I
+felt that beneath the pleasant smile he was trying to put on his
+face there was an ill purpose.  I ordered him back, and so sharply
+that he obeyed.
+</para>
+
+<para>
+"Now keep your distance," I commanded, "and don't you come closer!"
+</para>
+
+<para>
+"Wha' fo'?" he demanded indignantly.  "I t'ink-um talkee talkee
+heap good."
+</para>
+
+<para>
+"Talkee talkee," I answered bitterly, for I knew now that he had
+understood all that passed between George and me.  "What for talkee
+talkee?  You no sabbe talkee talkee."
+</para>
+
+<para>
+He grinned in a sickly fashion.  "Yep, I sabbe velly much.  I
+honest Chinaman."
+</para>
+
+<para>
+"All right," I answered.  "You sabbe talkee talkee, then you bail
+water plenty plenty.  After that we talkee talkee."
+</para>
+
+<para>
+He shook his head, at the same time pointing over his shoulder to
+his comrades.  "No can do.  Velly bad Chinamen, heap velly bad.  I
+t'ink-um - "
+</para>
+
+<para>
+"Stand back!" I shouted, for I had noticed his hand disappear
+beneath his blouse and his body prepare for a spring.
+</para>
+
+<para>
+Disconcerted, he went back into the cabin, to hold a council,
+apparently, from the way the jabbering broke forth.  The Reindeer
+was very deep in the water, and her movements had grown quite
+loggy.  In a rough sea she would have inevitably swamped; but the
+wind, when it did blow, was off the land, and scarcely a ripple
+disturbed the surface of the bay.
+</para>
+
+<para>
+"I think you'd better head for the beach," George said abruptly, in
+a manner that told me his fear had forced him to make up his mind
+to some course of action.
+</para>
+
+<para>
+"I think not," I answered shortly.
+</para>
+
+<para>
+"I command you," he said in a bullying tone.
+</para>
+
+<para>
+"I was commanded to bring these prisoners into San Rafael," was my
+reply.
+</para>
+
+<para>
+Our voices were raised, and the sound of the altercation brought
+the Chinese out of the cabin.
+</para>
+
+<para>
+"Now will you head for the beach?"
+</para>
+
+<para>
+This from George, and I found myself looking into the muzzle of his
+revolver - of the revolver he dared to use on me, but was too
+cowardly to use on the prisoners.
+</para>
+
+<para>
+My brain seemed smitten with a dazzling brightness.  The whole
+situation, in all its bearings, was focussed sharply before me -
+the shame of losing the prisoners, the worthlessness and cowardice
+of George, the meeting with Le Grant and the other patrol men and
+the lame explanation; and then there was the fight I had fought so
+hard, victory wrenched from me just as I thought I had it within my
+grasp.  And out of the tail of my eye I could see the Chinese
+crowding together by the cabin doors and leering triumphantly.  It
+would never do.
+</para>
+
+<para>
+I threw my hand up and my head down.  The first act elevated the
+muzzle, and the second removed my head from the path of the bullet
+which went whistling past.  One hand closed on George's wrist, the
+other on the revolver.  Yellow Handkerchief and his gang sprang
+toward me.  It was now or never.  Putting all my strength into a
+sudden effort, I swung George's body forward to meet them.  Then I
+pulled back with equal suddenness, ripping the revolver out of his
+fingers and jerking him off his feet.  He fell against Yellow
+Handkerchief's knees, who stumbled over him, and the pair wallowed
+in the bailing hole where the cockpit floor was torn open.  The
+next instant I was covering them with my revolver, and the wild
+shrimp-catchers were cowering and cringing away.
+</para>
+
+<para>
+But I swiftly discovered that there was all the difference in the
+world between shooting men who are attacking and men who are doing
+nothing more than simply refusing to obey.  For obey they would not
+when I ordered them into the bailing hole.  I threatened them with
+the revolver, but they sat stolidly in the flooded cabin and on the
+roof and would not move.
+</para>
+
+<para>
+Fifteen minutes passed, the Reindeer sinking deeper and deeper, her
+mainsail flapping in the calm.  But from off the Point Pedro shore
+I saw a dark line form on the water and travel toward us.  It was
+the steady breeze I had been expecting so long.  I called to the
+Chinese and pointed it out.  They hailed it with exclamations.
+Then I pointed to the sail and to the water in the Reindeer, and
+indicated by signs that when the wind reached the sail, what of the
+water aboard we would capsize.  But they jeered defiantly, for they
+knew it was in my power to luff the helm and let go the main-sheet,
+so as to spill the wind and escape damage.
+</para>
+
+<para>
+But my mind was made up.  I hauled in the main-sheet a foot or two,
+took a turn with it, and bracing my feet, put my back against the
+tiller.  This left me one hand for the sheet and one for the
+revolver.  The dark line drew nearer, and I could see them looking
+from me to it and back again with an apprehension they could not
+successfully conceal.  My brain and will and endurance were pitted
+against theirs, and the problem was which could stand the strain of
+imminent death the longer and not give in.
+</para>
+
+<para>
+Then the wind struck us.  The main-sheet tautened with a brisk
+rattling of the blocks, the boom uplifted, the sail bellied out,
+and the Reindeer heeled over - over, and over, till the lee-rail
+went under, the cabin windows went under, and the bay began to pour
+in over the cockpit rail.  So violently had she heeled over, that
+the men in the cabin had been thrown on top of one another into the
+lee bunk, where they squirmed and twisted and were washed about,
+those underneath being perilously near to drowning.
+</para>
+
+<para>
+The wind freshened a bit, and the Reindeer went over farther than
+ever.  For the moment I thought she was gone, and I knew that
+another puff like that and she surely would go.  While I pressed
+her under and debated whether I should give up or not, the Chinese
+cried for mercy.  I think it was the sweetest sound I have ever
+heard.  And then, and not until then, did I luff up and ease out
+the main-sheet.  The Reindeer righted very slowly, and when she was
+on an even keel was so much awash that I doubted if she could be
+saved.
+</para>
+
+<para>
+But the Chinese scrambled madly into the cockpit and fell to
+bailing with buckets, pots, pans, and everything they could lay
+hands on.  It was a beautiful sight to see that water flying over
+the side!  And when the Reindeer was high and proud on the water
+once more, we dashed away with the breeze on our quarter, and at
+the last possible moment crossed the mud flats and entered the
+slough.
+</para>
+
+<para>
+The spirit of the Chinese was broken, and so docile did they become
+that ere we made San Rafael they were out with the tow-rope, Yellow
+Handkerchief at the head of the line.  As for George, it was his
+last trip with the fish patrol.  He did not care for that sort of
+thing, he explained, and he thought a clerkship ashore was good
+enough for him.  And we thought so too.
+</para>
+
+
+</chapter>
+
+<chapter>
+<title>THE KING OF THE GREEKS</title>
+
+
+<para>
+Big Alec had never been captured by the fish patrol.  It was his
+boast that no man could take him alive, and it was his history that
+of the many men who had tried to take him dead none had succeeded.
+It was also history that at least two patrolmen who had tried to
+take him dead had died themselves.  Further, no man violated the
+fish laws more systematically and deliberately than Big Alec.
+</para>
+
+<para>
+He was called "Big Alec" because of his gigantic stature.  His
+height was six feet three inches, and he was correspondingly broad-
+shouldered and deep-chested.  He was splendidly muscled and hard as
+steel, and there were innumerable stories in circulation among the
+fisher-folk concerning his prodigious strength.  He was as bold and
+dominant of spirit as he was strong of body, and because of this he
+was widely known by another name, that of "The King of the Greeks."
+The fishing population was largely composed of Greeks, and they
+looked up to him and obeyed him as their chief.  And as their
+chief, he fought their fights for them, saw that they were
+protected, saved them from the law when they fell into its
+clutches, and made them stand by one another and himself in time of
+trouble.
+</para>
+
+<para>
+In the old days, the fish patrol had attempted his capture many
+disastrous times and had finally given it over, so that when the
+word was out that he was coming to Benicia, I was most anxious to
+see him.  But I did not have to hunt him up.  In his usual bold
+way, the first thing he did on arriving was to hunt us up.  Charley
+Le Grant and I at the time were under a patrol-man named Carmintel,
+and the three of us were on the Reindeer, preparing for a trip,
+when Big Alec stepped aboard.  Carmintel evidently knew him, for
+they shook hands in recognition.  Big Alec took no notice of
+Charley or me.
+</para>
+
+<para>
+"I've come down to fish sturgeon a couple of months," he said to
+Carmintel.
+</para>
+
+<para>
+His eyes flashed with challenge as he spoke, and we noticed the
+patrolman's eyes drop before him.
+</para>
+
+<para>
+"That's all right, Alec," Carmintel said in a low voice.  "I'll not
+bother you.  Come on into the cabin, and we'll talk things over,"
+he added.
+</para>
+
+<para>
+When they had gone inside and shut the doors after them, Charley
+winked with slow deliberation at me.  But I was only a youngster,
+and new to men and the ways of some men, so I did not understand.
+Nor did Charley explain, though I felt there was something wrong
+about the business.
+</para>
+
+<para>
+Leaving them to their conference, at Charley's suggestion we
+boarded our skiff and pulled over to the Old Steamboat Wharf, where
+Big Alec's ark was lying.  An ark is a house-boat of small though
+comfortable dimensions, and is as necessary to the Upper Bay
+fisherman as are nets and boats.  We were both curious to see Big
+Alec's ark, for history said that it had been the scene of more
+than one pitched battle, and that it was riddled with bullet-holes.
+</para>
+
+<para>
+We found the holes (stopped with wooden plugs and painted over),
+but there were not so many as I had expected.  Charley noted my
+look of disappointment, and laughed; and then to comfort me he gave
+an authentic account of one expedition which had descended upon Big
+Alec's floating home to capture him, alive preferably, dead if
+necessary.  At the end of half a day's fighting, the patrolmen had
+drawn off in wrecked boats, with one of their number killed and
+three wounded.  And when they returned next morning with
+reinforcements they found only the mooring-stakes of Big Alec's
+ark; the ark itself remained hidden for months in the fastnesses of
+the Suisun tules.
+</para>
+
+<para>
+"But why was he not hanged for murder?" I demanded.  "Surely the
+United States is powerful enough to bring such a man to justice."
+</para>
+
+<para>
+"He gave himself up and stood trial," Charley answered.  "It cost
+him fifty thousand dollars to win the case, which he did on
+technicalities and with the aid of the best lawyers in the state.
+Every Greek fisherman on the river contributed to the sum.  Big
+Alec levied and collected the tax, for all the world like a king.
+The United States may be all-powerful, my lad, but the fact remains
+that Big Alec is a king inside the United States, with a country
+and subjects all his own."
+</para>
+
+<para>
+"But what are you going to do about his fishing for sturgeon?  He's
+bound to fish with a 'Chinese line.'"
+</para>
+
+<para>
+Charley shrugged his shoulders.  "We'll see what we will see," he
+said enigmatically.
+</para>
+
+<para>
+Now a "Chinese line" is a cunning device invented by the people
+whose name it bears.  By a simple system of floats, weights, and
+anchors, thousands of hooks, each on a separate leader, are
+suspended at a distance of from six inches to a foot above the
+bottom.  The remarkable thing about such a line is the hook.  It is
+barbless, and in place of the barb, the hook is filed long and
+tapering to a point as sharp as that of a needle.  These hoods are
+only a few inches apart, and when several thousand of them are
+suspended just above the bottom, like a fringe, for a couple of
+hundred fathoms, they present a formidable obstacle to the fish
+that travel along the bottom.
+</para>
+
+<para>
+Such a fish is the sturgeon, which goes rooting along like a pig,
+and indeed is often called "pig-fish."  Pricked by the first hook
+it touches, the sturgeon gives a startled leap and comes into
+contact with half a dozen more hooks.  Then it threshes about
+wildly, until it receives hook after hook in its soft flesh; and
+the hooks, straining from many different angles, hold the luckless
+fish fast until it is drowned.  Because no sturgeon can pass
+through a Chinese line, the device is called a trap in the fish
+laws; and because it bids fair to exterminate the sturgeon, it is
+branded by the fish laws as illegal.  And such a line, we were
+confident, Big Alec intended setting, in open and flagrant
+violation of the law.
+</para>
+
+<para>
+Several days passed after the visit of Big Alec, during which
+Charley and I kept a sharp watch on him.  He towed his ark around
+the Solano Wharf and into the big bight at Turner's Shipyard.  The
+bight we knew to be good ground for sturgeon, and there we felt
+sure the King of the Greeks intended to begin operations.  The tide
+circled like a mill-race in and out of this bight, and made it
+possible to raise, lower, or set a Chinese line only at slack
+water.  So between the tides Charley and I made it a point for one
+or the other of us to keep a lookout from the Solano Wharf.
+</para>
+
+<para>
+On the fourth day I was lying in the sun behind the stringer-piece
+of the wharf, when I saw a skiff leave the distant shore and pull
+out into the bight.  In an instant the glasses were at my eyes and
+I was following every movement of the skiff.  There were two men in
+it, and though it was a good mile away, I made out one of them to
+be Big Alec; and ere the skiff returned to shore I made out enough
+more to know that the Greek had set his line.
+</para>
+
+<para>
+"Big Alec has a Chinese line out in the bight off Turner's
+Shipyard," Charley Le Grant said that afternoon to Carmintel.
+</para>
+
+<para>
+A fleeting expression of annoyance passed over the patrolman's
+face, and then he said, "Yes?" in an absent way, and that was all.
+</para>
+
+<para>
+Charley bit his lip with suppressed anger and turned on his heel.
+</para>
+
+<para>
+"Are you game, my lad?" he said to me later on in the evening, just
+as we finished washing down the Reindeer's decks and were preparing
+to turn in.
+</para>
+
+<para>
+A lump came up in my throat, and I could only nod my head.
+</para>
+
+<para>
+"Well, then," and Charley's eyes glittered in a determined way,
+"we've got to capture Big Alec between us, you and I, and we've got
+to do it in spite of Carmintel.  Will you lend a hand?"
+</para>
+
+<para>
+"It's a hard proposition, but we can do it," he added after a
+pause.
+</para>
+
+<para>
+"Of course we can," I supplemented enthusiastically.
+</para>
+
+<para>
+And then he said, "Of course we can," and we shook hands on it and
+went to bed.
+</para>
+
+<para>
+But it was no easy task we had set ourselves.  In order to convict
+a man of illegal fishing, it was necessary to catch him in the act
+with all the evidence of the crime about him - the hooks, the
+lines, the fish, and the man himself.  This meant that we must take
+Big Alec on the open water, where he could see us coming and
+prepare for us one of the warm receptions for which he was noted.
+</para>
+
+<para>
+"There's no getting around it," Charley said one morning.  "If we
+can only get alongside it's an even toss, and there's nothing left
+for us but to try and get alongside.  Come on, lad."
+</para>
+
+<para>
+We were in the Columbia River salmon boat, the one we had used
+against the Chinese shrimp-catchers.  Slack water had come, and as
+we dropped around the end of the Solano Wharf we saw Big Alec at
+work, running his line and removing the fish.
+</para>
+
+<para>
+"Change places," Charley commanded, "and steer just astern of him
+as though you're going into the shipyard."
+</para>
+
+<para>
+I took the tiller, and Charley sat down on a thwart amidships,
+placing his revolver handily beside him.
+</para>
+
+<para>
+"If he begins to shoot," he cautioned, "get down in the bottom and
+steer from there, so that nothing more than your hand will be
+exposed."
+</para>
+
+<para>
+I nodded, and we kept silent after that, the boat slipping gently
+through the water and Big Alec growing nearer and nearer.  We could
+see him quite plainly, gaffing the sturgeon and throwing them into
+the boat while his companion ran the line and cleared the hooks as
+he dropped them back into the water.  Nevertheless, we were five
+hundred yards away when the big fisherman hailed us.
+</para>
+
+<para>
+"Here!  You!  What do you want?" he shouted.
+</para>
+
+<para>
+"Keep going," Charley whispered, "just as though you didn't hear
+him."
+</para>
+
+<para>
+The next few moments were very anxious ones.  The fisherman was
+studying us sharply, while we were gliding up on him every second.
+</para>
+
+<para>
+"You keep off if you know what's good for you!" he called out
+suddenly, as though he had made up his mind as to who and what we
+were.  "If you don't, I'll fix you!"
+</para>
+
+<para>
+He brought a rifle to his shoulder and trained it on me.
+</para>
+
+<para>
+"Now will you keep off?" he demanded.
+</para>
+
+<para>
+I could hear Charley groan with disappointment.  "Keep off," he
+whispered; "it's all up for this time."
+</para>
+
+<para>
+I put up the tiller and eased the sheet, and the salmon boat ran
+off five or six points.  Big Alec watched us till we were out of
+range, when he returned to his work.
+</para>
+
+<para>
+"You'd better leave Big Alec alone," Carmintel said, rather sourly,
+to Charley that night.
+</para>
+
+<para>
+"So he's been complaining to you, has he?"  Charley said
+significantly.
+</para>
+
+<para>
+Carmintel flushed painfully.  "You'd better leave him alone, I tell
+you," he repeated.  "He's a dangerous man, and it won't pay to fool
+with him."
+</para>
+
+<para>
+"Yes," Charley answered softly; "I've heard that it pays better to
+leave him alone."
+</para>
+
+<para>
+This was a direct thrust at Carmintel, and we could see by the
+expression of his face that it sank home.  For it was common
+knowledge that Big Alec was as willing to bribe as to fight, and
+that of late years more than one patrolman had handled the
+fisherman's money.
+</para>
+
+<para>
+"Do you mean to say - " Carmintel began, in a bullying tone.
+</para>
+
+<para>
+But Charley cut him off shortly.  "I mean to say nothing," he said.
+"You heard what I said, and if the cap fits, why - "
+</para>
+
+<para>
+He shrugged his shoulders, and Carmintel glowered at him,
+speechless.
+</para>
+
+<para>
+"What we want is imagination," Charley said to me one day, when we
+had attempted to creep upon Big Alec in the gray of dawn and had
+been shot at for our trouble.
+</para>
+
+<para>
+And thereafter, and for many days, I cudgelled my brains trying to
+imagine some possible way by which two men, on an open stretch of
+water, could capture another who knew how to use a rifle and was
+never to be found without one.  Regularly, every slack water,
+without slyness, boldly and openly in the broad day, Big Alec was
+to be seen running his line.  And what made it particularly
+exasperating was the fact that every fisherman, from Benicia to
+Vallejo knew that he was successfully defying us.  Carmintel also
+bothered us, for he kept us busy among the shad-fishers of San
+Pablo, so that we had little time to spare on the King of the
+Greeks.  But Charley's wife and children lived at Benicia, and we
+had made the place our headquarters, so that we always returned to
+it.
+</para>
+
+<para>
+"I'll tell you what we can do," I said, after several fruitless
+weeks had passed; "we can wait some slack water till Big Alec has
+run his line and gone ashore with the fish, and then we can go out
+and capture the line.  It will put him to time and expense to make
+another, and then we'll figure to capture that too.  If we can't
+capture him, we can discourage him, you see."
+</para>
+
+<para>
+Charley saw, and said it wasn't a bad idea.  We watched our chance,
+and the next low-water slack, after Big Alec had removed the fish
+from the line and returned ashore, we went out in the salmon boat.
+We had the bearings of the line from shore marks, and we knew we
+would have no difficulty in locating it.  The first of the flood
+tide was setting in, when we ran below where we thought the line
+was stretched and dropped over a fishing-boat anchor.  Keeping a
+short rope to the anchor, so that it barely touched the bottom, we
+dragged it slowly along until it stuck and the boat fetched up hard
+and fast.
+</para>
+
+<para>
+"We've got it," Charley cried.  "Come on and lend a hand to get it
+in."
+</para>
+
+<para>
+Together we hove up the rope till the anchor I came in sight with
+the sturgeon line caught across one of the flukes.  Scores of the
+murderous-looking hooks flashed into sight as we cleared the
+anchor, and we had just started to run along the line to the end
+where we could begin to lift it, when a sharp thud in the boat
+startled us.  We looked about, but saw nothing and returned to our
+work.  An instant later there was a similar sharp thud and the
+gunwale splintered between Charley's body and mine.
+</para>
+
+<para>
+"That's remarkably like a bullet, lad," he said reflectively.  "And
+it's a long shot Big Alec's making."
+</para>
+
+<para>
+"And he's using smokeless powder," he concluded, after an
+examination of the mile-distant shore.  "That's why we can't hear
+the report."
+</para>
+
+<para>
+I looked at the shore, but could see no sign of Big Alec, who was
+undoubtedly hidden in some rocky nook with us at his mercy.  A
+third bullet struck the water, glanced, passed singing over our
+heads, and struck the water again beyond.
+</para>
+
+<para>
+"I guess we'd better get out of this," Charley remarked coolly.
+"What do you think, lad?"
+</para>
+
+<para>
+I thought so, too, and said we didn't want the line anyway.
+Whereupon we cast off and hoisted the spritsail.  The bullets
+ceased at once, and we sailed away, unpleasantly confident that Big
+Alec was laughing at our discomfiture.
+</para>
+
+<para>
+And more than that, the next day on the fishing wharf, where we
+were inspecting nets, he saw fit to laugh and sneer at us, and this
+before all the fishermen.  Charley's face went black with anger;
+but beyond promising Big Alec that in the end he would surely land
+him behind the bars, he controlled himself and said nothing.  The
+King of the Greeks made his boast that no fish patrol had ever
+taken him or ever could take him, and the fishermen cheered him and
+said it was true.  They grew excited, and it looked like trouble
+for a while; but Big Alec asserted his kingship and quelled them.
+</para>
+
+<para>
+Carmintel also laughed at Charley, and dropped sarcastic remarks,
+and made it hard for him.  But Charley refused to be angered,
+though he told me in confidence that he intended to capture Big
+Alec if it took all the rest of his life to accomplish it.
+</para>
+
+<para>
+"I don't know how I'll do it," he said, "but do it I will, as sure
+as I am Charley Le Grant.  The idea will come to me at the right
+and proper time, never fear."
+</para>
+
+<para>
+And at the right time it came, and most unexpectedly.  Fully a
+month had passed, and we were constantly up and down the river, and
+down and up the bay, with no spare moments to devote to the
+particular fisherman who ran a Chinese line in the bight of
+Turner's Shipyard.  We had called in at Selby's Smelter one
+afternoon, while on patrol work, when all unknown to us our
+opportunity happened along.  It appeared in the guise of a helpless
+yacht loaded with seasick people, so we could hardly be expected to
+recognize it as the opportunity.  It was a large sloop-yacht, and
+it was helpless inasmuch as the trade-wind was blowing half a gale
+and there were no capable sailors aboard.
+</para>
+
+<para>
+From the wharf at Selby's we watched with careless interest the
+lubberly manoeuvre performed of bringing the yacht to anchor, and
+the equally lubberly manoeuvre of sending the small boat ashore.  A
+very miserable-looking man in draggled ducks, after nearly swamping
+the boat in the heavy seas, passed us the painter and climbed out.
+He staggered about as though the wharf were rolling, and told us
+his troubles, which were the troubles of the yacht.  The only
+rough-weather sailor aboard, the man on whom they all depended, had
+been called back to San Francisco by a telegram, and they had
+attempted to continue the cruise alone.  The high wind and big seas
+of San Pablo Bay had been too much for them; all hands were sick,
+nobody knew anything or could do anything; and so they had run in
+to the smelter either to desert the yacht or to get somebody to
+bring it to Benicia.  In short, did we know of any sailors who
+would bring the yacht into Benicia?
+</para>
+
+<para>
+Charley looked at me.  The Reindeer was lying in a snug place.  We
+had nothing on hand in the way of patrol work till midnight.  With
+the wind then blowing, we could sail the yacht into Benicia in a
+couple of hours, have several more hours ashore, and come back to
+the smelter on the evening train.
+</para>
+
+<para>
+"All right, captain," Charley said to the disconsolate yachtsman,
+who smiled in sickly fashion at the title.
+</para>
+
+<para>
+"I'm only the owner," he explained.
+</para>
+
+<para>
+We rowed him aboard in much better style than he had come ashore,
+and saw for ourselves the helplessness of the passengers.  There
+were a dozen men and women, and all of them too sick even to appear
+grateful at our coming.  The yacht was rolling savagely, broad on,
+and no sooner had the owner's feet touched the deck than he
+collapsed and joined, the others.  Not one was able to bear a hand,
+so Charley and I between us cleared the badly tangled running gear,
+got up sail, and hoisted anchor.
+</para>
+
+<para>
+It was a rough trip, though a swift one.  The Carquinez Straits
+were a welter of foam and smother, and we came through them wildly
+before the wind, the big mainsail alternately dipping and flinging
+its boom skyward as we tore along.  But the people did not mind.
+They did not mind anything.  Two or three, including the owner,
+sprawled in the cockpit, shuddering when the yacht lifted and raced
+and sank dizzily into the trough, and between-whiles regarding the
+shore with yearning eyes.  The rest were huddled on the cabin floor
+among the cushions.  Now and again some one groaned, but for the
+most part they were as limp as so many dead persons.
+</para>
+
+<para>
+As the bight at Turner's Shipyard opened out, Charley edged into it
+to get the smoother water.  Benicia was in view, and we were
+bowling along over comparatively easy water, when a speck of a boat
+danced up ahead of us, directly in our course.  It was low-water
+slack.  Charley and I looked at each other.  No word was spoken,
+but at once the yacht began a most astonishing performance, veering
+and yawing as though the greenest of amateurs was at the wheel.  It
+was a sight for sailormen to see.  To all appearances, a runaway
+yacht was careering madly over the bight, and now and again
+yielding a little bit to control in a desperate effort to make
+Benicia.
+</para>
+
+<para>
+The owner forgot his seasickness long enough to look anxious.  The
+speck of a boat grew larger and larger, till we could see Big Alec
+and his partner, with a turn of the sturgeon line around a cleat,
+resting from their labor to laugh at us.  Charley pulled his
+sou'wester over his eyes, and I followed his example, though I
+could not guess the idea he evidently had in mind and intended to
+carry into execution.
+</para>
+
+<para>
+We came foaming down abreast of the skiff, so close that we could
+hear above the wind the voices of Big Alec and his mate as they
+shouted at us with all the scorn that professional watermen feel
+for amateurs, especially when amateurs are making fools of
+themselves.
+</para>
+
+<para>
+We thundered on past the fishermen, and nothing had happened.
+Charley grinned at the disappointment he saw in my face, and then
+shouted:
+</para>
+
+<para>
+"Stand by the main-sheet to jibe!"
+</para>
+
+<para>
+He put the wheel hard over, and the yacht whirled around
+obediently.  The main-sheet slacked and dipped, then shot over our
+heads after the boom and tautened with a crash on the traveller.
+The yacht heeled over almost on her beam ends, and a great wail
+went up from the seasick passengers as they swept across the cabin
+floor in a tangled mass and piled into a heap in the starboard
+bunks.
+</para>
+
+<para>
+But we had no time for them.  The yacht, completing the manoeuvre,
+headed into the wind with slatting canvas, and righted to an even
+keel.  We were still plunging ahead, and directly in our path was
+the skiff.  I saw Big Alec dive overboard and his mate leap for our
+bowsprit.  Then came the crash as we struck the boat, and a series
+of grinding bumps as it passed under our bottom.
+</para>
+
+<para>
+"That fixes his rifle," I heard Charley mutter, as he sprang upon
+the deck to look for Big Alec somewhere astern.
+</para>
+
+<para>
+The wind and sea quickly stopped our forward movement, and we began
+to drift backward over the spot where the skiff had been.  Big
+Alec's black head and swarthy face popped up within arm's reach;
+and all unsuspecting and very angry with what he took to be the
+clumsiness of amateur sailors, he was hauled aboard.  Also he was
+out of breath, for he had dived deep and stayed down long to escape
+our keel.
+</para>
+
+<para>
+The next instant, to the perplexity and consternation of the owner,
+Charley was on top of Big Alec in the cockpit, and I was helping
+bind him with gaskets.  The owner was dancing excitedly about and
+demanding an explanation, but by that time Big Alec's partner had
+crawled aft from the bowsprit and was peering apprehensively over
+the rail into the cockpit.  Charley's arm shot around his neck and
+the man landed on his back beside Big Alec.
+</para>
+
+<para>
+"More gaskets!" Charley shouted, and I made haste to supply them.
+</para>
+
+<para>
+The wrecked skiff was rolling sluggishly a short distance to
+windward, and I trimmed the sheets while Charley took the wheel and
+steered for it.
+</para>
+
+<para>
+"These two men are old offenders," he explained to the angry owner;
+"and they are most persistent violators of the fish and game laws.
+You have seen them caught in the act, and you may expect to be
+subpoenaed as witness for the state when the trial comes off."
+</para>
+
+<para>
+As he spoke he rounded alongside the skiff.  It had been torn from
+the line, a section of which was dragging to it.  He hauled in
+forty or fifty feet with a young sturgeon still fast in a tangle of
+barbless hooks, slashed that much of the line free with his knife,
+and tossed it into the cockpit beside the prisoners.
+</para>
+
+<para>
+"And there's the evidence, Exhibit A, for the people," Charley
+continued.  "Look it over carefully so that you may identify it in
+the court-room with the time and place of capture."
+</para>
+
+<para>
+And then, in triumph, with no more veering and yawing, we sailed
+into Benicia, the King of the Greeks bound hard and fast in the
+cockpit, and for the first time in his life a prisoner of the fish
+patrol.
+</para>
+
+
+</chapter>
+
+<chapter>
+<title>A RAID ON THE OYSTER PIRATES</title>
+
+
+<para>
+Of the fish patrolmen under whom we served at various times,
+Charley Le Grant and I were agreed, I think, that Neil Partington
+was the best.  He was neither dishonest nor cowardly; and while he
+demanded strict obedience when we were under his orders, at the
+same time our relations were those of easy comradeship, and he
+permitted us a freedom to which we were ordinarily unaccustomed, as
+the present story will show.
+</para>
+
+<para>
+Neil's family lived in Oakland, which is on the Lower Bay, not more
+than six miles across the water from San Francisco.  One day, while
+scouting among the Chinese shrimp-catchers of Point Pedro, he
+received word that his wife was very ill; and within the hour the
+Reindeer was bowling along for Oakland, with a stiff northwest
+breeze astern.  We ran up the Oakland Estuary and came to anchor,
+and in the days that followed, while Neil was ashore, we tightened
+up the Reindeer's rigging, overhauled the ballast, scraped down,
+and put the sloop into thorough shape.
+</para>
+
+<para>
+This done, time hung heavy on our hands.  Neil's wife was
+dangerously ill, and the outlook was a week's lie-over, awaiting
+the crisis.  Charley and I roamed the docks, wondering what we
+should do, and so came upon the oyster fleet lying at the Oakland
+City Wharf.  In the main they were trim, natty boats, made for
+speed and bad weather, and we sat down on the stringer-piece of the
+dock to study them.
+</para>
+
+<para>
+"A good catch, I guess," Charley said, pointing to the heaps of
+oysters, assorted in three sizes, which lay upon their decks.
+</para>
+
+<para>
+Pedlers were backing their wagons to the edge of the wharf, and
+from the bargaining and chaffering that went on, I managed to learn
+the selling price of the oysters.
+</para>
+
+<para>
+"That boat must have at least two hundred dollars' worth aboard," I
+calculated.  "I wonder how long it took to get the load?"
+</para>
+
+<para>
+"Three or four days," Charley answered.  "Not bad wages for two men
+- twenty-five dollars a day apiece."
+</para>
+
+<para>
+The boat we were discussing, the Ghost, lay directly beneath us.
+Two men composed its crew.  One was a squat, broad-shouldered
+fellow with remarkably long and gorilla-like arms, while the other
+was tall and well proportioned, with clear blue eyes and a mat of
+straight black hair.  So unusual and striking was this combination
+of hair and eyes that Charley and I remained somewhat longer than
+we intended.
+</para>
+
+<para>
+And it was well that we did.  A stout, elderly man, with the dress
+and carriage of a successful merchant, came up and stood beside us,
+looking down upon the deck of the Ghost.  He appeared angry, and
+the longer he looked the angrier he grew.
+</para>
+
+<para>
+"Those are my oysters," he said at last.  "I know they are my
+oysters.  You raided my beds last night and robbed me of them."
+</para>
+
+<para>
+The tall man and the short man on the Ghost looked up.
+</para>
+
+<para>
+"Hello, Taft," the short man said, with insolent familiarity.
+(Among the bayfarers he had gained the nickname of "The Centipede"
+on account of his long arms.)  "Hello, Taft," he repeated, with the
+same touch of insolence.  "Wot 'r you growling about now?"
+</para>
+
+<para>
+"Those are my oysters - that's what I said.  You've stolen them
+from my beds."
+</para>
+
+<para>
+"Yer mighty wise, ain't ye?" was the Centipede's sneering reply.
+"S'pose you can tell your oysters wherever you see 'em?"
+</para>
+
+<para>
+"Now, in my experience," broke in the tall man, "oysters is oysters
+wherever you find 'em, an' they're pretty much alike all the Bay
+over, and the world over, too, for that matter.  We're not wantin'
+to quarrel with you, Mr. Taft, but we jes' wish you wouldn't
+insinuate that them oysters is yours an' that we're thieves an'
+robbers till you can prove the goods."
+</para>
+
+<para>
+"I know they're mine; I'd stake my life on it!" Mr. Taft snorted.
+</para>
+
+<para>
+"Prove it," challenged the tall man, who we afterward learned was
+known as "The Porpoise" because of his wonderful swimming
+abilities.
+</para>
+
+<para>
+Mr. Taft shrugged his shoulders helplessly.  Of course he could not
+prove the oysters to be his, no matter how certain he might be.
+</para>
+
+<para>
+"I'd give a thousand dollars to have you men behind the bars!" he
+cried.  "I'll give fifty dollars a head for your arrest and
+conviction, all of you!"
+</para>
+
+<para>
+A roar of laughter went up from the different boats, for the rest
+of the pirates had been listening to the discussion.
+</para>
+
+<para>
+"There's more money in oysters," the Porpoise remarked dryly.
+</para>
+
+<para>
+Mr. Taft turned impatiently on his heel and walked away.  From out
+of the corner of his eye, Charley noted the way he went.  Several
+minutes later, when he had disappeared around a corner, Charley
+rose lazily to his feet.  I followed him, and we sauntered off in
+the opposite direction to that taken by Mr. Taft.
+</para>
+
+<para>
+"Come on!  Lively!" Charley whispered, when we passed from the view
+of the oyster fleet.
+</para>
+
+<para>
+Our course was changed at once, and we dodged around corners and
+raced up and down side-streets till Mr. Taft's generous form loomed
+up ahead of us.
+</para>
+
+<para>
+"I'm going to interview him about that reward," Charley explained,
+as we rapidly over-hauled the oyster-bed owner.  "Neil will be
+delayed here for a week, and you and I might as well be doing
+something in the meantime.  What do you say?"
+</para>
+
+<para>
+"Of course, of course," Mr. Taft said, when Charley had introduced
+himself and explained his errand.  "Those thieves are robbing me of
+thousands of dollars every year, and I shall be glad to break them
+up at any price, - yes, sir, at any price.  As I said, I'll give
+fifty dollars a head, and call it cheap at that.  They've robbed my
+beds, torn down my signs, terrorized my watchmen, and last year
+killed one of them.  Couldn't prove it.  All done in the blackness
+of night.  All I had was a dead watchman and no evidence.  The
+detectives could do nothing.  Nobody has been able to do anything
+with those men.  We have never succeeded in arresting one of them.
+So I say, Mr. -  What did you say your name was?"
+</para>
+
+<para>
+"Le Grant," Charley answered.
+</para>
+
+<para>
+"So I say, Mr. Le Grant, I am deeply obliged to you for the
+assistance you offer.  And I shall be glad, most glad, sir, to co-
+operate with you in every way.  My watchmen and boats are at your
+disposal.  Come and see me at the San Francisco offices any time,
+or telephone at my expense.  And don't be afraid of spending money.
+I'll foot your expenses, whatever they are, so long as they are
+within reason.  The situation is growing desperate, and something
+must be done to determine whether I or that band of ruffians own
+those oyster beds."
+</para>
+
+<para>
+"Now we'll see Neil," Charley said, when he had seen Mr. Taft upon
+his train to San Francisco.
+</para>
+
+<para>
+Not only did Neil Partington interpose no obstacle to our
+adventure, but he proved to be of the greatest assistance.  Charley
+and I knew nothing of the oyster industry, while his head was an
+encyclopaedia of facts concerning it.  Also, within an hour or so,
+he was able to bring to us a Greek boy of seventeen or eighteen who
+knew thoroughly well the ins and outs of oyster piracy.
+</para>
+
+<para>
+At this point I may as well explain that we of the fish patrol were
+free lances in a way.  While Neil Partington, who was a patrolman
+proper, received a regular salary, Charley and I, being merely
+deputies, received only what we earned - that is to say, a certain
+percentage of the fines imposed on convicted violators of the fish
+laws.  Also, any rewards that chanced our way were ours.  We
+offered to share with Partington whatever we should get from Mr.
+Taft, but the patrolman would not hear of it.  He was only too
+happy, he said, to do a good turn for us, who had done so many for
+him.
+</para>
+
+<para>
+We held a long council of war, and mapped out the following line of
+action.  Our faces were unfamiliar on the Lower Bay, but as the
+Reindeer was well known as a fish-patrol sloop, the Greek boy,
+whose name was Nicholas, and I were to sail some innocent-looking
+craft down to Asparagus Island and join the oyster pirates' fleet.
+Here, according to Nicholas's description of the beds and the
+manner of raiding, it was possible for us to catch the pirates in
+the act of stealing oysters, and at the same time to get them in
+our power.  Charley was to be on the shore, with Mr. Taft's
+watchmen and a posse of constables, to help us at the right time.
+</para>
+
+<para>
+"I know just the boat," Neil said, at the conclusion of the
+discussion, "a crazy old sloop that's lying over at Tiburon.  You
+and Nicholas can go over by the ferry, charter it for a song, and
+sail direct for the beds."
+</para>
+
+<para>
+"Good luck be with you, boys," he said at parting, two days later.
+"Remember, they are dangerous men, so be careful."
+</para>
+
+<para>
+Nicholas and I succeeded in chartering the sloop very cheaply; and
+between laughs, while getting up sail, we agreed that she was even
+crazier and older than she had been described.  She was a big,
+flat-bottomed, square-sterned craft, sloop-rigged, with a sprung
+mast, slack rigging, dilapidated sails, and rotten running-gear,
+clumsy to handle and uncertain in bringing about, and she smelled
+vilely of coal tar, with which strange stuff she had been smeared
+from stem to stern and from cabin-roof to centreboard.  And to cap
+it all, Coal Tar Maggie was printed in great white letters the
+whole length of either side.
+</para>
+
+<para>
+It was an uneventful though laughable run from Tiburon to Asparagus
+Island, where we arrived in the afternoon of the following day.
+The oyster pirates, a fleet of a dozen sloops, were lying at anchor
+on what was known as the "Deserted Beds."  The Coal Tar Maggie came
+sloshing into their midst with a light breeze astern, and they
+crowded on deck to see us.  Nicholas and I had caught the spirit of
+the crazy craft, and we handled her in most lubberly fashion.
+</para>
+
+<para>
+"Wot is it?" some one called.
+</para>
+
+<para>
+"Name it 'n' ye kin have it!" called another.
+</para>
+
+<para>
+"I swan naow, ef it ain't the old Ark itself!" mimicked the
+Centipede from the deck of the Ghost.
+</para>
+
+<para>
+"Hey!  Ahoy there, clipper ship!" another wag shouted.  "Wot's yer
+port?"
+</para>
+
+<para>
+We took no notice of the joking, but acted, after the manner of
+greenhorns, as though the Coal Tar Maggie required our undivided
+attention.  I rounded her well to windward of the Ghost, and
+Nicholas ran for'ard to drop the anchor.  To all appearances it was
+a bungle, the way the chain tangled and kept the anchor from
+reaching the bottom.  And to all appearances Nicholas and I were
+terribly excited as we strove to clear it.  At any rate, we quite
+deceived the pirates, who took huge delight in our predicament.
+</para>
+
+<para>
+But the chain remained tangled, and amid all kinds of mocking
+advice we drifted down upon and fouled the Ghost, whose bowsprit
+poked square through our mainsail and ripped a hole in it as big as
+a barn door.  The Centipede and the Porpoise doubled up on the
+cabin in paroxysms of laughter, and left us to get clear as best we
+could.  This, with much unseaman-like performance, we succeeded in
+doing, and likewise in clearing the anchor-chain, of which we let
+out about three hundred feet.  With only ten feet of water under
+us, this would permit the Coal Tar Maggie to swing in a circle six
+hundred feet in diameter, in which circle she would be able to foul
+at least half the fleet.
+</para>
+
+<para>
+The oyster pirates lay snugly together at short hawsers, the
+weather being fine, and they protested loudly at our ignorance in
+putting out such an unwarranted length of anchor-chain.  And not
+only did they protest, for they made us heave it in again, all but
+thirty feet.
+</para>
+
+<para>
+Having sufficiently impressed them with our general lubberliness,
+Nicholas and I went below to congratulate ourselves and to cook
+supper.  Hardly had we finished the meal and washed the dishes,
+when a skiff ground against the Coal Tar Maggie's side, and heavy
+feet trampled on deck.  Then the Centipede's brutal face appeared
+in the companionway, and he descended into the cabin, followed by
+the Porpoise.  Before they could seat themselves on a bunk, another
+skiff came alongside, and another, and another, till the whole
+fleet was represented by the gathering in the cabin.
+</para>
+
+<para>
+"Where'd you swipe the old tub?" asked a squat and hairy man, with
+cruel eyes and Mexican features.
+</para>
+
+<para>
+"Didn't swipe it," Nicholas answered, meeting them on their own
+ground and encouraging the idea that we had stolen the Coal Tar
+Maggie.  "And if we did, what of it?"
+</para>
+
+<para>
+"Well, I don't admire your taste, that's all," sneered he of the
+Mexican features.  "I'd rot on the beach first before I'd take a
+tub that couldn't get out of its own way."
+</para>
+
+<para>
+"How were we to know till we tried her?" Nicholas asked, so
+innocently as to cause a laugh.  "And how do you get the oysters?"
+he hurried on.  "We want a load of them; that's what we came for, a
+load of oysters."
+</para>
+
+<para>
+"What d'ye want 'em for?" demanded the Porpoise.
+</para>
+
+<para>
+"Oh, to give away to our friends, of course," Nicholas retorted.
+"That's what you do with yours, I suppose."
+</para>
+
+<para>
+This started another laugh, and as our visitors grew more genial we
+could see that they had not the slightest suspicion of our identity
+or purpose.
+</para>
+
+<para>
+"Didn't I see you on the dock in Oakland the other day?" the
+Centipede asked suddenly of me.
+</para>
+
+<para>
+"Yep," I answered boldly, taking the bull by the horns.  "I was
+watching you fellows and figuring out whether we'd go oystering or
+not.  It's a pretty good business, I calculate, and so we're going
+in for it.  That is," I hastened to add, "if you fellows don't
+mind."
+</para>
+
+<para>
+"I'll tell you one thing, which ain't two things," he replied, "and
+that is you'll have to hump yerself an' get a better boat.  We
+won't stand to be disgraced by any such box as this.  Understand?"
+</para>
+
+<para>
+"Sure," I said.  "Soon as we sell some oysters we'll outfit in
+style."
+</para>
+
+<para>
+"And if you show yerself square an' the right sort," he went on,
+"why, you kin run with us.  But if you don't" (here his voice
+became stern and menacing), "why, it'll be the sickest day of yer
+life.  Understand?"
+</para>
+
+<para>
+"Sure," I said.
+</para>
+
+<para>
+After that and more warning and advice of similar nature, the
+conversation became general, and we learned that the beds were to
+be raided that very night.  As they got into their boats, after an
+hour's stay, we were invited to join them in the raid with the
+assurance of "the more the merrier."
+</para>
+
+<para>
+"Did you notice that short, Mexican-looking chap?" Nicholas asked,
+when they had departed to their various sloops.  "He's Barchi, of
+the Sporting Life Gang, and the fellow that came with him is
+Skilling.  They're both out now on five thousand dollars' bail."
+</para>
+
+<para>
+I had heard of the Sporting Life Gang before, a crowd of hoodlums
+and criminals that terrorized the lower quarters of Oakland, and
+two-thirds of which were usually to be found in state's prison for
+crimes that ranged from perjury and ballot-box stuffing to murder.
+</para>
+
+<para>
+"They are not regular oyster pirates," Nicholas continued.
+"They've just come down for the lark and to make a few dollars.
+But we'll have to watch out for them."
+</para>
+
+<para>
+We sat in the cockpit and discussed the details of our plan till
+eleven o'clock had passed, when we heard the rattle of an oar in a
+boat from the direction of the Ghost.  We hauled up our own skiff,
+tossed in a few sacks, and rowed over.  There we found all the
+skiffs assembling, it being the intention to raid the beds in a
+body.
+</para>
+
+<para>
+To my surprise, I found barely a foot of water where we had dropped
+anchor in ten feet.  It was the big June run-out of the full moon,
+and as the ebb had yet an hour and a half to run, I knew that our
+anchorage would be dry ground before slack water.
+</para>
+
+<para>
+Mr. Taft's beds were three miles away, and for a long time we rowed
+silently in the wake of the other boats, once in a while grounding
+and our oar blades constantly striking bottom.  At last we came
+upon soft mud covered with not more than two inches of water - not
+enough to float the boats.  But the pirates at once were over the
+side, and by pushing and pulling on the flat-bottomed skiffs, we
+moved steadily along.
+</para>
+
+<para>
+The full moon was partly obscured by high-flying clouds, but the
+pirates went their way with the familiarity born of long practice.
+After half a mile of the mud, we came upon a deep channel, up which
+we rowed, with dead oyster shoals looming high and dry on either
+side.  At last we reached the picking grounds.  Two men, on one of
+the shoals, hailed us and warned us off.  But the Centipede, the
+Porpoise, Barchi, and Skilling took the lead, and followed by the
+rest of us, at least thirty men in half as many boats, rowed right
+up to the watchmen.
+</para>
+
+<para>
+"You'd better slide outa this here," Barchi said threateningly, "or
+we'll fill you so full of holes you wouldn't float in molasses."
+</para>
+
+<para>
+The watchmen wisely retreated before so overwhelming a force, and
+rowed their boat along the channel toward where the shore should
+be.  Besides, it was in the plan for them to retreat.
+</para>
+
+<para>
+We hauled the noses of the boats up on the shore side of a big
+shoal, and all hands, with sacks, spread out and began picking.
+Every now and again the clouds thinned before the face of the moon,
+and we could see the big oysters quite distinctly.  In almost no
+time sacks were filled and carried back to the boats, where fresh
+ones were obtained.  Nicholas and I returned often and anxiously to
+the boats with our little loads, but always found some one of the
+pirates coming or going.
+</para>
+
+<para>
+"Never mind," he said; "no hurry.  As they pick farther and farther
+away, it will take too long to carry to the boats.  Then they'll
+stand the full sacks on end and pick them up when the tide comes in
+and the skiffs will float to them."
+</para>
+
+<para>
+Fully half an hour went by, and the tide had begun to flood, when
+this came to pass.  Leaving the pirates at their work, we stole
+back to the boats.  One by one, and noiselessly, we shoved them off
+and made them fast in an awkward flotilla.  Just as we were shoving
+off the last skiff, our own, one of the men came upon us.  It was
+Barchi.  His quick eye took in the situation at a glance, and he
+sprang for us; but we went clear with a mighty shove, and he was
+left floundering in the water over his head.  As soon as he got
+back to the shoal he raised his voice and gave the alarm.
+</para>
+
+<para>
+We rowed with all our strength, but it was slow going with so many
+boats in tow.  A pistol cracked from the shoal, a second, and a
+third; then a regular fusillade began.  The bullets spat and spat
+all about us; but thick clouds had covered the moon, and in the dim
+darkness it was no more than random firing.  It was only by chance
+that we could be hit.
+</para>
+
+<para>
+"Wish we had a little steam launch," I panted.
+</para>
+
+<para>
+"I'd just as soon the moon stayed hidden," Nicholas panted back.
+</para>
+
+<para>
+It was slow work, but every stroke carried us farther away from the
+shoal and nearer the shore, till at last the shooting died down,
+and when the moon did come out we were too far away to be in
+danger.  Not long afterward we answered a shoreward hail, and two
+Whitehall boats, each pulled by three pairs of oars, darted up to
+us.  Charley's welcome face bent over to us, and he gripped us by
+the hands while he cried, "Oh, you joys!  You joys!  Both of you!"
+</para>
+
+<para>
+When the flotilla had been landed, Nicholas and I and a watchman
+rowed out in one of the Whitehalls, with Charley in the stern-
+sheets.  Two other Whitehalls followed us, and as the moon now
+shone brightly, we easily made out the oyster pirates on their
+lonely shoal.  As we drew closer, they fired a rattling volley from
+their revolvers, and we promptly retreated beyond range.
+</para>
+
+<para>
+"Lot of time," Charley said.  "The flood is setting in fast, and by
+the time it's up to their necks there won't be any fight left in
+them."
+</para>
+
+<para>
+So we lay on our oars and waited for the tide to do its work.  This
+was the predicament of the pirates:  because of the big run-out,
+the tide was now rushing back like a mill-race, and it was
+impossible for the strongest swimmer in the world to make against
+it the three miles to the sloops.  Between the pirates and the
+shore were we, precluding escape in that direction.  On the other
+hand, the water was rising rapidly over the shoals, and it was only
+a question of a few hours when it would be over their heads.
+</para>
+
+<para>
+It was beautifully calm, and in the brilliant white moonlight we
+watched them through our night glasses and told Charley of the
+voyage of the Coal Tar Maggie.  One o'clock came, and two o'clock,
+and the pirates were clustering on the highest shoal, waist-deep in
+water.
+</para>
+
+<para>
+"Now this illustrates the value of imagination," Charley was
+saying.  "Taft has been trying for years to get them, but he went
+at it with bull strength and failed.  Now we used our heads . . ."
+</para>
+
+<para>
+Just then I heard a scarcely audible gurgle of water, and holding
+up my hand for silence, I turned and pointed to a ripple slowly
+widening out in a growing circle.  It was not more than fifty feet
+from us.  We kept perfectly quiet and waited.  After a minute the
+water broke six feet away, and a black head and white shoulder
+showed in the moonlight.  With a snort of surprise and of suddenly
+expelled breath, the head and shoulder went down.
+</para>
+
+<para>
+We pulled ahead several strokes and drifted with the current.  Four
+pairs of eyes searched the surface of the water, but never another
+ripple showed, and never another glimpse did we catch of the black
+head and white shoulder.
+</para>
+
+<para>
+"It's the Porpoise," Nicholas said.  "It would take broad daylight
+for us to catch him."
+</para>
+
+<para>
+At a quarter to three the pirates gave their first sign of
+weakening.  We heard cries for help, in the unmistakable voice of
+the Centipede, and this time, on rowing closer, we were not fired
+upon.  The Centipede was in a truly perilous plight.  Only the
+heads and shoulders of his fellow-marauders showed above the water
+as they braced themselves against the current, while his feet were
+off the bottom and they were supporting him.
+</para>
+
+<para>
+"Now, lads," Charley said briskly, "we have got you, and you can't
+get away.  If you cut up rough, we'll have to leave you alone and
+the water will finish you.  But if you're good we'll take you
+aboard, one man at a time, and you'll all be saved.  What do you
+say?"
+</para>
+
+<para>
+"Ay," they chorused hoarsely between their chattering teeth.
+</para>
+
+<para>
+"Then one man at a time, and the short men first."
+</para>
+
+<para>
+The Centipede was the first to be pulled aboard, and he came
+willingly, though he objected when the constable put the handcuffs
+on him.  Barchi was next hauled in, quite meek and resigned from
+his soaking.  When we had ten in, our boat we drew back, and the
+second Whitehall was loaded.  The third Whitehall received nine
+prisoners only - a catch of twenty-nine in all.
+</para>
+
+<para>
+"You didn't get the Porpoise," the Centipede said exultantly, as
+though his escape materially diminished our success.
+</para>
+
+<para>
+Charley laughed.  "But we saw him just the same, a-snorting for
+shore like a puffing pig."
+</para>
+
+<para>
+It was a mild and shivering band of pirates that we marched up the
+beach to the oyster house.  In answer to Charley's knock, the door
+was flung open, and a pleasant wave of warm air rushed out upon us.
+</para>
+
+<para>
+"You can dry your clothes here, lads, and get some hot coffee,"
+Charley announced, as they filed in.
+</para>
+
+<para>
+And there, sitting ruefully by the fire, with a steaming mug in his
+hand, was the Porpoise.  With one accord Nicholas and I looked at
+Charley.  He laughed gleefully.
+</para>
+
+<para>
+"That comes of imagination," he said.  "When you see a thing,
+you've got to see it all around, or what's the good of seeing it at
+all?  I saw the beach, so I left a couple of constables behind to
+keep an eye on it.  That's all."
+</para>
+
+
+</chapter>
+
+<chapter>
+<title>THE SIEGE OF THE "LANCASHIRE QUEEN"</title>
+
+
+<para>
+Possibly our most exasperating experience on the fish patrol was
+when Charley Le Grant and I laid a two weeks' siege to a big four-
+masted English ship.  Before we had finished with the affair, it
+became a pretty mathematical problem, and it was by the merest
+chance that we came into possession of the instrument that brought
+it to a successful termination.
+</para>
+
+<para>
+After our raid on the oyster pirates we had returned to Oakland,
+where two more weeks passed before Neil Partington's wife was out
+of danger and on the highroad to recovery.  So it was after an
+absence of a month, all told, that we turned the Reindeer's nose
+toward Benicia.  When the cat's away the mice will play, and in
+these four weeks the fishermen had become very bold in violating
+the law.  When we passed Point Pedro we noticed many signs of
+activity among the shrimp-catchers, and, well into San Pablo Bay,
+we observed a widely scattered fleet of Upper Bay fishing-boats
+hastily pulling in their nets and getting up sail.
+</para>
+
+<para>
+This was suspicious enough to warrant investigation, and the first
+and only boat we succeeded in boarding proved to have an illegal
+net.  The law permitted no smaller mesh for catching shad than one
+that measured seven and one-half inches inside the knots, while the
+mesh of this particular net measured only three inches.  It was a
+flagrant breach of the rules, and the two fishermen were forthwith
+put under arrest.  Neil Partington took one of them with him to
+help manage the Reindeer, while Charley and I went on ahead with
+the other in the captured boat.
+</para>
+
+<para>
+But the shad fleet had headed over toward the Petaluma shore in
+wild flight, and for the rest of the run through San Pablo Bay we
+saw no more fishermen at all.  Our prisoner, a bronzed and bearded
+Greek, sat sullenly on his net while we sailed his craft.  It was a
+new Columbia River salmon boat, evidently on its first trip, and it
+handled splendidly.  Even when Charley praised it, our prisoner
+refused to speak or to notice us, and we soon gave him up as a most
+unsociable fellow.
+</para>
+
+<para>
+We ran up the Carquinez Straits and edged into the bight at
+Turner's Shipyard for smoother water.  Here were lying several
+English steel sailing ships, waiting for the wheat harvest; and
+here, most unexpectedly, in the precise place where we had captured
+Big Alec, we came upon two Italians in a skiff that was loaded with
+a complete "Chinese" sturgeon line.  The surprise was mutual, and
+we were on top of them before either they or we were aware.
+Charley had barely time to luff into the wind and run up to them.
+I ran forward and tossed them a line with orders to make it fast.
+One of the Italians took a turn with it over a cleat, while I
+hastened to lower our big spritsail.  This accomplished, the salmon
+boat dropped astern, dragging heavily on the skiff.
+</para>
+
+<para>
+Charley came forward to board the prize, but when I proceeded to
+haul alongside by means of the line, the Italians cast it off.  We
+at once began drifting to leeward, while they got out two pairs of
+oars and rowed their light craft directly into the wind.  This
+manoeuvre for the moment disconcerted us, for in our large and
+heavily loaded boat we could not hope to catch them with the oars.
+But our prisoner came unexpectedly to our aid.  His black eyes were
+flashing eagerly, and his face was flushed with suppressed
+excitement, as he dropped the centre-board, sprang forward with a
+single leap, and put up the sail.
+</para>
+
+<para>
+"I've always heard that Greeks don't like Italians," Charley
+laughed, as he ran aft to the tiller.
+</para>
+
+<para>
+And never in my experience have I seen a man so anxious for the
+capture of another as was our prisoner in the chase that followed.
+His eyes fairly snapped, and his nostrils quivered and dilated in a
+most extraordinary way.  Charley steered while he tended the sheet;
+and though Charley was as quick and alert as a cat, the Greek could
+hardly control his impatience.
+</para>
+
+<para>
+The Italians were cut off from the shore, which was fully a mile
+away at its nearest point.  Did they attempt to make it, we could
+haul after them with the wind abeam, and overtake them before they
+had covered an eighth of the distance.  But they were too wise to
+attempt it, contenting themselves with rowing lustily to windward
+along the starboard side of a big ship, the Lancashire Queen.  But
+beyond the ship lay an open stretch of fully two miles to the shore
+in that direction.  This, also, they dared not attempt, for we were
+bound to catch them before they could cover it.  So, when they
+reached the bow of the Lancashire Queen, nothing remained but to
+pass around and row down her port side toward the stern, which
+meant rowing to leeward and giving us the advantage.
+</para>
+
+<para>
+We in the salmon boat, sailing close on the wind, tacked about and
+crossed the ship's bow.  Then Charley put up the tiller and headed
+down the port side of the ship, the Greek letting out the sheet and
+grinning with delight.  The Italians were already half-way down the
+ship's length; but the stiff breeze at our back drove us after them
+far faster than they could row.  Closer and closer we came, and I,
+lying down forward, was just reaching out to grasp the skiff, when
+it ducked under the great stern of the Lancashire Queen.
+</para>
+
+<para>
+The chase was virtually where it had begun.  The Italians were
+rowing up the starboard side of the ship, and we were hauled close
+on the wind and slowly edging out from the ship as we worked to
+windward.  Then they darted around her bow and began the row down
+her port side, and we tacked about, crossed her bow, and went
+plunging down the wind hot after them.  And again, just as I was
+reaching for the skiff, it ducked under the ship's stern and out of
+danger.  And so it went, around and around, the skiff each time
+just barely ducking into safety.
+</para>
+
+<para>
+By this time the ship's crew had become aware of what was taking
+place, and we could see their heads in a long row as they looked at
+us over the bulwarks.  Each time we missed the skiff at the stern,
+they set up a wild cheer and dashed across to the other side of the
+Lancashire Queen to see the chase to wind-ward.  They showered us
+and the Italians with jokes and advice, and made our Greek so angry
+that at least once on each circuit he raised his fist and shook it
+at them in a rage.  They came to look for this, and at each display
+greeted it with uproarious mirth.
+</para>
+
+<para>
+"Wot a circus!" cried one.
+</para>
+
+<para>
+"Tork about yer marine hippodromes, - if this ain't one, I'd like
+to know!" affirmed another.
+</para>
+
+<para>
+"Six-days-go-as-yer-please," announced a third.  "Who says the
+dagoes won't win?"
+</para>
+
+<para>
+On the next tack to windward the Greek offered to change places
+with Charley.
+</para>
+
+<para>
+"Let-a me sail-a de boat," he demanded.  "I fix-a them, I catch-a
+them, sure."
+</para>
+
+<para>
+This was a stroke at Charley's professional pride, for pride
+himself he did upon his boat-sailing abilities; but he yielded the
+tiller to the prisoner and took his place at the sheet.  Three
+times again we made the circuit, and the Greek found that he could
+get no more speed out of the salmon boat than Charley had.
+</para>
+
+<para>
+"Better give it up," one of the sailors advised from above.
+</para>
+
+<para>
+The Greek scowled ferociously and shook his fist in his customary
+fashion.  In the meanwhile my mind had not been idle, and I had
+finally evolved an idea.
+</para>
+
+<para>
+"Keep going, Charley, one time more," I said.
+</para>
+
+<para>
+And as we laid out on the next tack to wind-ward, I bent a piece of
+line to a small grappling hook I had seen lying in the bail-hole.
+The end of the line I made fast to the ring-bolt in the bow, and
+with the hook out of sight I waited for the next opportunity to use
+it.  Once more they made their leeward pull down the port side of
+the Lancashire Queen, and once more we churned down after them
+before the wind.  Nearer and nearer we drew, and I was making
+believe to reach for them as before.  The stern of the skiff was
+not six feet away, and they were laughing at me derisively as they
+ducked under the ship's stern.  At that instant I suddenly arose
+and threw the grappling iron.  It caught fairly and squarely on the
+rail of the skiff, which was jerked backward out of safety as the
+rope tautened and the salmon boat ploughed on.
+</para>
+
+<para>
+A groan went up from the row of sailors above, which quickly
+changed to a cheer as one of the Italians whipped out a long
+sheath-knife and cut the rope.  But we had drawn them out of
+safety, and Charley, from his place in the stern-sheets, reached
+over and clutched the stern of the skiff.  The whole thing happened
+in a second of time, for the first Italian was cutting the rope and
+Charley was clutching the skiff when the second Italian dealt him a
+rap over the head with an oar, Charley released his hold and
+collapsed, stunned, into the bottom of the salmon boat, and the
+Italians bent to their oars and escaped back under the ship's
+stern.
+</para>
+
+<para>
+The Greek took both tiller and sheet and continued the chase around
+the Lancashire Queen, while I attended to Charley, on whose head a
+nasty lump was rapidly rising.  Our sailor audience was wild with
+delight, and to a man encouraged the fleeing Italians.  Charley sat
+up, with one hand on his head, and gazed about him sheepishly.
+</para>
+
+<para>
+"It will never do to let them escape now," he said, at the same
+time drawing his revolver.
+</para>
+
+<para>
+On our next circuit, he threatened the Italians with the weapon;
+but they rowed on stolidly, keeping splendid stroke and utterly
+disregarding him.
+</para>
+
+<para>
+"If you don't stop, I'll shoot," Charley said menacingly.
+</para>
+
+<para>
+But this had no effect, nor were they to be frightened into
+surrendering even when he fired several shots dangerously close to
+them.  It was too much to expect him to shoot unarmed men, and this
+they knew as well as we did; so they continued to pull doggedly
+round and round the ship.
+</para>
+
+<para>
+"We'll run them down, then!" Charley exclaimed.  "We'll wear them
+out and wind them!"
+</para>
+
+<para>
+So the chase continued.  Twenty times more we ran them around the
+Lancashire Queen, and at last we could see that even their iron
+muscles were giving out.  They were nearly exhausted, and it was
+only a matter of a few more circuits, when the game took on a new
+feature.  On the row to windward they always gained on us, so that
+they were half-way down the ship's side on the row to leeward when
+we were passing the bow.  But this last time, as we passed the bow,
+we saw them escaping up the ship's gangway, which had been suddenly
+lowered.  It was an organized move on the part of the sailors,
+evidently countenanced by the captain; for by the time we arrived
+where the gangway had been, it was being hoisted up, and the skiff,
+slung in the ship's davits, was likewise flying aloft out of reach.
+</para>
+
+<para>
+The parley that followed with the captain was short and snappy.  He
+absolutely forbade us to board the Lancashire Queen, and as
+absolutely refused to give up the two men.  By this time Charley
+was as enraged as the Greek.  Not only had he been foiled in a long
+and ridiculous chase, but he had been knocked senseless into the
+bottom of his boat by the men who had escaped him.
+</para>
+
+<para>
+"Knock off my head with little apples," he declared emphatically,
+striking the fist of one hand into the palm of the other, "if those
+two men ever escape me!  I'll stay here to get them if it takes the
+rest of my natural life, and if I don't get them, then I promise
+you I'll live unnaturally long or until I do get them, or my name's
+not Charley Le Grant!"
+</para>
+
+<para>
+And then began the siege of the Lancashire Queen, a siege memorable
+in the annals of both fishermen and fish patrol.  When the Reindeer
+came along, after a fruitless pursuit of the shad fleet, Charley
+instructed Neil Partington to send out his own salmon boat, with
+blankets, provisions, and a fisherman's charcoal stove.  By sunset
+this exchange of boats was made, and we said good-by to our Greek,
+who perforce had to go into Benicia and be locked up for his own
+violation of the law.  After supper, Charley and I kept alternate
+four-hour watches till day-light.  The fishermen made no attempt to
+escape that night, though the ship sent out a boat for scouting
+purposes to find if the coast were clear.
+</para>
+
+<para>
+By the next day we saw that a steady siege was in order, and we
+perfected our plans with an eye to our own comfort.  A dock, known
+as the Solano Wharf, which ran out from the Benicia shore, helped
+us in this.  It happened that the Lancashire Queen, the shore at
+Turner's Shipyard, and the Solano Wharf were the corners of a big
+equilateral triangle.  From ship to shore, the side of the triangle
+along which the Italians had to escape, was a distance equal to
+that from the Solano Wharf to the shore, the side of the triangle
+along which we had to travel to get to the shore before the
+Italians.  But as we could sail much faster than they could row, we
+could permit them to travel about half their side of the triangle
+before we darted out along our side.  If we allowed them to get
+more than half-way, they were certain to beat us to shore; while if
+we started before they were half-way, they were equally certain to
+beat us back to the ship.
+</para>
+
+<para>
+We found that an imaginary line, drawn from the end of the wharf to
+a windmill farther along the shore, cut precisely in half the line
+of the triangle along which the Italians must escape to reach the
+land.  This line made it easy for us to determine how far to let
+them run away before we bestirred ourselves in pursuit.  Day after
+day we would watch them through our glasses as they rowed leisurely
+along toward the half-way point; and as they drew close into line
+with the windmill, we would leap into the boat and get up sail.  At
+sight of our preparation, they would turn and row slowly back to
+the Lancashire Queen, secure in the knowledge that we could not
+overtake them.
+</para>
+
+<para>
+To guard against calms - when our salmon boat would be useless - we
+also had in readiness a light rowing skiff equipped with spoon-
+oars.  But at such times, when the wind failed us, we were forced
+to row out from the wharf as soon as they rowed from the ship.  In
+the night-time, on the other hand, we were compelled to patrol the
+immediate vicinity of the ship; which we did, Charley and I
+standing four-hour watches turn and turn about.  The Italians,
+however, preferred the daytime in which to escape, and so our long
+night vigils were without result.
+</para>
+
+<para>
+"What makes me mad," said Charley, "is our being kept from our
+honest beds while those rascally lawbreakers are sleeping soundly
+every night.  But much good may it do them," he threatened.  "I'll
+keep them on that ship till the captain charges them board, as sure
+as a sturgeon's not a catfish!"
+</para>
+
+<para>
+It was a tantalizing problem that confronted us.  As long as we
+were vigilant, they could not escape; and as long as they were
+careful, we would be unable to catch them.  Charley cudgelled his
+brains continually, but for once his imagination failed him.  It
+was a problem apparently without other solution than that of
+patience.  It was a waiting game, and whichever waited the longer
+was bound to win.  To add to our irritation, friends of the
+Italians established a code of signals with them from the shore, so
+that we never dared relax the siege for a moment.  And besides
+this, there were always one or two suspicious-looking fishermen
+hanging around the Solano Wharf and keeping watch on our actions.
+We could do nothing but "grin and bear it," as Charley said, while
+it took up all our time and prevented us from doing other work.
+</para>
+
+<para>
+The days went by, and there was no change in the situation.  Not
+that no attempts were made to change it.  One night friends from
+the shore came out in a skiff and attempted to confuse us while the
+two Italians escaped.  That they did not succeed was due to the
+lack of a little oil on the ship's davits.  For we were drawn back
+from the pursuit of the strange boat by the creaking of the davits,
+and arrived at the Lancashire Queen just as the Italians were
+lowering their skiff.  Another night, fully half a dozen skiffs
+rowed around us in the darkness, but we held on like a leech to the
+side of the ship and frustrated their plan till they grew angry and
+showered us with abuse.  Charley laughed to himself in the bottom
+of the boat.
+</para>
+
+<para>
+"It's a good sign, lad," he said to me.  "When men begin to abuse,
+make sure they're losing patience; and shortly after they lose
+patience, they lose their heads.  Mark my words, if we only hold
+out, they'll get careless some fine day, and then we'll get them."
+</para>
+
+<para>
+But they did not grow careless, and Charley confessed that this was
+one of the times when all signs failed.  Their patience seemed
+equal to ours, and the second week of the siege dragged
+monotonously along.  Then Charley's lagging imagination quickened
+sufficiently to suggest a ruse.  Peter Boyelen, a new patrolman and
+one unknown to the fisher-folk, happened to arrive in Benicia and
+we took him into our plan.  We were as secret as possible about it,
+but in some unfathomable way the friends ashore got word to the
+beleaguered Italians to keep their eyes open.
+</para>
+
+<para>
+On the night we were to put our ruse into effect, Charley and I
+took up our usual station in our rowing skiff alongside the
+Lancashire Queen.  After it was thoroughly dark, Peter Boyelen came
+out in a crazy duck boat, the kind you can pick up and carry away
+under one arm.  When we heard him coming along, paddling noisily,
+we slipped away a short distance into the darkness, and rested on
+our oars.  Opposite the gangway, having jovially hailed the anchor-
+watch of the Lancashire Queen and asked the direction of the
+Scottish Chiefs, another wheat ship, he awkwardly capsized himself.
+The man who was standing the anchor-watch ran down the gangway and
+hauled him out of the water.  This was what he wanted, to get
+aboard the ship; and the next thing he expected was to be taken on
+deck and then below to warm up and dry out.  But the captain
+inhospitably kept him perched on the lowest gang-way step,
+shivering miserably and with his feet dangling in the water, till
+we, out of very pity, rowed in from the darkness and took him off.
+The jokes and gibes of the awakened crew sounded anything but sweet
+in our ears, and even the two Italians climbed up on the rail and
+laughed down at us long and maliciously.
+</para>
+
+<para>
+"That's all right," Charley said in a low voice, which I only could
+hear.  "I'm mighty glad it's not us that's laughing first.  We'll
+save our laugh to the end, eh, lad?"
+</para>
+
+<para>
+He clapped a hand on my shoulder as he finished, but it seemed to
+me that there was more determination than hope in his voice.
+</para>
+
+<para>
+It would have been possible for us to secure the aid of United
+States marshals and board the English ship, backed by Government
+authority.  But the instructions of the Fish Commission were to the
+effect that the patrolmen should avoid complications, and this one,
+did we call on the higher powers, might well end in a pretty
+international tangle.
+</para>
+
+<para>
+The second week of the siege drew to its close, and there was no
+sign of change in the situation.  On the morning of the fourteenth
+day the change came, and it came in a guise as unexpected and
+startling to us as it was to the men we were striving to capture.
+</para>
+
+<para>
+Charley and I, after our customary night vigil by the side of the
+Lancashire Queen, rowed into the Solana Wharf.
+</para>
+
+<para>
+"Hello!" cried Charley, in surprise.  "In the name of reason and
+common sense, what is that?  Of all unmannerly craft did you ever
+see the like?"
+</para>
+
+<para>
+Well might he exclaim, for there, tied up to the dock, lay the
+strangest looking launch I had ever seen.  Not that it could be
+called a launch, either, but it seemed to resemble a launch more
+than any other kind of boat.  It was seventy feet long, but so
+narrow was it, and so bare of superstructure, that it appeared much
+smaller than it really was.  It was built wholly of steel, and was
+painted black.  Three smokestacks, a good distance apart and raking
+well aft, arose in single file amidships; while the bow, long and
+lean and sharp as a knife, plainly advertised that the boat was
+made for speed.  Passing under the stern, we read Streak, painted
+in small white letters.
+</para>
+
+<para>
+Charley and I were consumed with curiosity.  In a few minutes we
+were on board and talking with an engineer who was watching the
+sunrise from the deck.  He was quite willing to satisfy our
+curiosity, and in a few minutes we learned that the Streak had come
+in after dark from San Francisco; that this was what might be
+called the trial trip; and that she was the property of Silas Tate,
+a young mining millionaire of California, whose fad was high-speed
+yachts.  There was some talk about turbine engines, direct
+application of steam, and the absence of pistons, rods, and cranks,
+- all of which was beyond me, for I was familiar only with sailing
+craft; but I did understand the last words of the engineer.
+</para>
+
+<para>
+"Four thousand horse-power and forty-five miles an hour, though you
+wouldn't think it," he concluded proudly.
+</para>
+
+<para>
+"Say it again, man!  Say it again!" Charley exclaimed in an excited
+voice.
+</para>
+
+<para>
+"Four thousand horse-power and forty-five miles an hour," the
+engineer repeated, grinning good-naturedly.
+</para>
+
+<para>
+"Where's the owner?" was Charley's next question.  "Is there any
+way I can speak to him?"
+</para>
+
+<para>
+The engineer shook his head.  "No, I'm afraid not.  He's asleep,
+you see."
+</para>
+
+<para>
+At that moment a young man in blue uniform came on deck farther aft
+and stood regarding the sunrise.
+</para>
+
+<para>
+"There he is, that's him, that's Mr. Tate," said the engineer.
+</para>
+
+<para>
+Charley walked aft and spoke to him, and while he talked earnestly
+the young man listened with an amused expression on his face.  He
+must have inquired about the depth of water close in to the shore
+at Turner's Shipyard, for I could see Charley making gestures and
+explaining.  A few minutes later he came back in high glee.
+</para>
+
+<para>
+"Come on lad," he said.  "On to the dock with you.  We've got
+them!"
+</para>
+
+<para>
+It was our good fortune to leave the Streak when we did, for a
+little later one of the spy fishermen appeared.  Charley and I took
+up our accustomed places, on the stringer-piece, a little ahead of
+the Streak and over our own boat, where we could comfortably watch
+the Lancashire Queen.  Nothing occurred till about nine o'clock,
+when we saw the two Italians leave the ship and pull along their
+side of the triangle toward the shore.  Charley looked as
+unconcerned as could be, but before they had covered a quarter of
+the distance, he whispered to me:
+</para>
+
+<para>
+"Forty-five miles an hour . . . nothing can save them . . . they
+are ours!"
+</para>
+
+<para>
+Slowly the two men rowed along till they were nearly in line with
+the windmill.  This was the point where we always jumped into our
+salmon boat and got up the sail, and the two men, evidently
+expecting it, seemed surprised when we gave no sign.
+</para>
+
+<para>
+When they were directly in line with the windmill, as near to the
+shore as to the ship, and nearer the shore than we had ever allowed
+them before, they grew suspicious.  We followed them through the
+glasses, and saw them standing up in the skiff and trying to find
+out what we were doing.  The spy fisherman, sitting beside us on
+the stringer-piece was likewise puzzled.  He could not understand
+our inactivity.  The men in the skiff rowed nearer the shore, but
+stood up again and scanned it, as if they thought we might be in
+hiding there.  But a man came out on the beach and waved a
+handkerchief to indicate that the coast was clear.  That settled
+them.  They bent to the oars to make a dash for it.  Still Charley
+waited.  Not until they had covered three-quarters of the distance
+from the Lancashire Queen, which left them hardly more than a
+quarter of a mile to gain the shore, did Charley slap me on the
+shoulder and cry:
+</para>
+
+<para>
+"They're ours!  They're ours!"
+</para>
+
+<para>
+We ran the few steps to the side of the Streak and jumped aboard.
+Stern and bow lines were cast off in a jiffy.  The Streak shot
+ahead and away from the wharf.  The spy fisherman we had left
+behind on the stringer-piece pulled out a revolver and fired five
+shots into the air in rapid succession.  The men in the skiff gave
+instant heed to the warning, for we could see them pulling away
+like mad.
+</para>
+
+<para>
+But if they pulled like mad, I wonder how our progress can be
+described?  We fairly flew.  So frightful was the speed with which
+we displaced the water, that a wave rose up on either side our bow
+and foamed aft in a series of three stiff, up-standing waves, while
+astern a great crested billow pursued us hungrily, as though at
+each moment it would fall aboard and destroy us.  The Streak was
+pulsing and vibrating and roaring like a thing alive.  The wind of
+our progress was like a gale - a forty-five-mile gale.  We could
+not face it and draw breath without choking and strangling.  It
+blew the smoke straight back from the mouths of the smoke-stacks at
+a direct right angle to the perpendicular.  In fact, we were
+travelling as fast as an express train.  "We just streaked it," was
+the way Charley told it afterward, and I think his description
+comes nearer than any I can give.
+</para>
+
+<para>
+As for the Italians in the skiff - hardly had we started, it seemed
+to me, when we were on top of them.  Naturally, we had to slow down
+long before we got to them; but even then we shot past like a
+whirlwind and were compelled to circle back between them and the
+shore.  They had rowed steadily, rising from the thwarts at every
+stroke, up to the moment we passed them, when they recognized
+Charley and me.  That took the last bit of fight out of them.  They
+hauled in their oars, and sullenly submitted to arrest.
+</para>
+
+<para>
+"Well, Charley," Neil Partington said, as we discussed it on the
+wharf afterward, "I fail to see where your boasted imagination came
+into play this time."
+</para>
+
+<para>
+But Charley was true to his hobby.  "Imagination?" he demanded,
+pointing to the Streak.  "Look at that! just look at it!  If the
+invention of that isn't imagination, I should like to know what
+is."
+</para>
+
+<para>
+"Of course," he added, "it's the other fellow's imagination, but it
+did the work all the same."
+</para>
+
+
+</chapter>
+
+<chapter>
+<title>CHARLEY'S COUP</title>
+
+
+<para>
+Perhaps our most laughable exploit on the fish patrol, and at the
+same time our most dangerous one, was when we rounded in, at a
+single haul, an even score of wrathful fishermen.  Charley called
+it a "coop," having heard Neil Partington use the term; but I think
+he misunderstood the word, and thought it meant "coop," to catch,
+to trap.  The fishermen, however, coup or coop, must have called it
+a Waterloo, for it was the severest stroke ever dealt them by the
+fish patrol, while they had invited it by open and impudent
+defiance of the law.
+</para>
+
+<para>
+During what is called the "open season" the fishermen might catch
+as many salmon as their luck allowed and their boats could hold.
+But there was one important restriction.  From sun-down Saturday
+night to sun-up Monday morning, they were not permitted to set a
+net.  This was a wise provision on the part of the Fish Commission,
+for it was necessary to give the spawning salmon some opportunity
+to ascend the river and lay their eggs.  And this law, with only an
+occasional violation, had been obediently observed by the Greek
+fishermen who caught salmon for the canneries and the market.
+</para>
+
+<para>
+One Sunday morning, Charley received a telephone call from a friend
+in Collinsville, who told him that the full force of fishermen was
+out with its nets.  Charley and I jumped into our salmon boat and
+started for the scene of the trouble.  With a light favoring wind
+at our back we went through the Carquinez Straits, crossed Suisun
+Bay, passed the Ship Island Light, and came upon the whole fleet at
+work.
+</para>
+
+<para>
+But first let me describe the method by which they worked.  The net
+used is what is known as a gill-net.  It has a simple diamond-
+shaped mesh which measures at least seven and one-half inches
+between the knots.  From five to seven and even eight hundred feet
+in length, these nets are only a few feet wide.  They are not
+stationary, but float with the current, the upper edge supported on
+the surface by floats, the lower edge sunk by means of leaden
+weights,
+</para>
+
+<para>
+This arrangement keeps the net upright in the current and
+effectually prevents all but the smaller fish from ascending the
+river.  The salmon, swimming near the surface, as is their custom,
+run their heads through these meshes, and are prevented from going
+on through by their larger girth of body, and from going back
+because of their gills, which catch in the mesh.  It requires two
+fishermen to set such a net, - one to row the boat, while the
+other, standing in the stern, carefully pays out the net.  When it
+is all out, stretching directly across the stream, the men make
+their boat fast to one end of the net and drift along with it.
+</para>
+
+<para>
+As we came upon the fleet of law-breaking fishermen, each boat two
+or three hundred yards from its neighbors, and boats and nets
+dotting the river as far as we could see, Charley said:
+</para>
+
+<para>
+"I've only one regret, lad, and that is that I have'nt a thousand
+arms so as to be able to catch them all.  As it is, we'll only be
+able to catch one boat, for while we are tackling that one it will
+be up nets and away with the rest."
+</para>
+
+<para>
+As we drew closer, we observed none of the usual flurry and
+excitement which our appearance invariably produced.  Instead, each
+boat lay quietly by its net, while the fishermen favored us with
+not the slightest attention.
+</para>
+
+<para>
+"It's curious," Charley muttered.  "Can it be they don't recognize
+us?"
+</para>
+
+<para>
+I said that it was impossible, and Charley agreed; yet there was a
+whole fleet, manned by men who knew us only too well, and who took
+no more notice of us than if we were a hay scow or a pleasure
+yacht.
+</para>
+
+<para>
+This did not continue to be the case, however, for as we bore down
+upon the nearest net, the men to whom it belonged detached their
+boat and rowed slowly toward the shore.  The rest of the boats
+showed no, sign of uneasiness.
+</para>
+
+<para>
+"That's funny," was Charley's remark.  "But we can confiscate the
+net, at any rate."
+</para>
+
+<para>
+We lowered sail, picked up one end of the net, and began to heave
+it into the boat.  But at the first heave we heard a bullet zip-
+zipping past us on the water, followed by the faint report of a
+rifle.  The men who had rowed ashore were shooting at us.  At the
+next heave a second bullet went zipping past, perilously near.
+Charley took a turn around a pin and sat down.  There were no more
+shots.  But as soon as he began to heave in, the shooting
+recommenced.
+</para>
+
+<para>
+"That settles it," he said, flinging the end of the net overboard.
+"You fellows want it worse than we do, and you can have it."
+</para>
+
+<para>
+We rowed over toward the next net, for Charley was intent on
+finding out whether or not we were face to face with an organized
+defiance.  As we approached, the two fishermen proceeded to cast
+off from their net and row ashore, while the first two rowed back
+and made fast to the net we had abandoned.  And at the second net
+we were greeted by rifle shots till we desisted and went on to the
+third, where the manoeuvre was again repeated.
+</para>
+
+<para>
+Then we gave it up, completely routed, and hoisted sail and started
+on the long windward beat back to Benicia.  A number of Sundays
+went by, on each of which the law was persistently violated.  Yet,
+short of an armed force of soldiers, we could do nothing.  The
+fishermen had hit upon a new idea and were using it for all it was
+worth, while there seemed no way by which we could get the better
+of them.
+</para>
+
+<para>
+About this time Neil Partington happened along from the Lower Bay,
+where he had been for a number of weeks.  With him was Nicholas,
+the Greek boy who had helped us in our raid on the oyster pirates,
+and the pair of them took a hand.  We made our arrangements
+carefully.  It was planned that while Charley and I tackled the
+nets, they were to be hidden ashore so as to ambush the fishermen
+who landed to shoot at us.
+</para>
+
+<para>
+It was a pretty plan.  Even Charley said it was.  But we reckoned
+not half so well as the Greeks.  They forestalled us by ambushing
+Neil and Nicholas and taking them prisoners, while, as of old,
+bullets whistled about our ears when Charley and I attempted to
+take possession of the nets.  When we were again beaten off, Neil
+Partington and Nicholas were released.  They were rather shamefaced
+when they put in an appearance, and Charley chaffed them
+unmercifully.  But Neil chaffed back, demanding to know why
+Charley's imagination had not long since overcome the difficulty.
+</para>
+
+<para>
+"Just you wait; the idea'll come all right," Charley promised.
+</para>
+
+<para>
+"Most probably," Neil agreed.  "But I'm afraid the salmon will be
+exterminated first, and then there will be no need for it when it
+does come."
+</para>
+
+<para>
+Neil Partington, highly disgusted with his adventure, departed for
+the Lower Bay, taking Nicholas with him, and Charley and I were
+left to our own resources.  This meant that the Sunday fishing
+would be left to itself, too, until such time as Charley's idea
+happened along.  I puzzled my head a good deal to find out some way
+of checkmating the Greeks, as also did Charley, and we broached a
+thousand expedients which on discussion proved worthless.
+</para>
+
+<para>
+The fishermen, on the other hand, were in high feather, and their
+boasts went up and down the river to add to our discomfiture.
+Among all classes of them we became aware of a growing
+insubordination.  We were beaten, and they were losing respect for
+us.  With the loss of respect, contempt began to arise.  Charley
+began to be spoken of as the "olda woman," and I received my rating
+as the "pee-wee kid."  The situation was fast becoming unbearable,
+and we knew that we should have to deliver a stunning stroke at the
+Greeks in order to regain the old-time respect in which we had
+stood.
+</para>
+
+<para>
+Then one morning the idea came.  We were down on Steamboat Wharf,
+where the river steamers made their landings, and where we found a
+group of amused long-shoremen and loafers listening to the hard-
+luck tale of a sleepy-eyed young fellow in long sea-boots.  He was
+a sort of amateur fisherman, he said, fishing for the local market
+of Berkeley.  Now Berkeley was on the Lower Bay, thirty miles away.
+On the previous night, he said, he had set his net and dozed off to
+sleep in the bottom of the boat.
+</para>
+
+<para>
+The next he knew it was morning, and he opened his eyes to find his
+boat rubbing softly against the piles of Steamboat Wharf at
+Benicia.  Also he saw the river steamer Apache lying ahead of him,
+and a couple of deck-hands disentangling the shreds of his net from
+the paddle-wheel.  In short, after he had gone to sleep, his
+fisherman's riding light had gone out, and the Apache had run over
+his net.  Though torn pretty well to pieces, the net in some way
+still remained foul, and he had had a thirty-mile tow out of his
+course.
+</para>
+
+<para>
+Charley nudged me with his elbow.  I grasped his thought on the
+instant, but objected:
+</para>
+
+<para>
+"We can't charter a steamboat."
+</para>
+
+<para>
+"Don't intend to," he rejoined.  "But let's run over to Turner's
+Shipyard.  I've something in my mind there that may be of use to
+us."
+</para>
+
+<para>
+And over we went to the shipyard, where Charley led the way to the
+Mary Rebecca, lying hauled out on the ways, where she was being
+cleaned and overhauled.  She was a scow-schooner we both knew well,
+carrying a cargo of one hundred and forty tons and a spread of
+canvas greater than other schooner on the bay.
+</para>
+
+<para>
+"How d'ye do, Ole," Charley greeted a big blue-shirted Swede who
+was greasing the jaws of the main gaff with a piece of pork rind.
+</para>
+
+<para>
+Ole grunted, puffed away at his pipe, and went on greasing.  The
+captain of a bay schooner is supposed to work with his hands just
+as well as the men.
+</para>
+
+<para>
+Ole Ericsen verified Charley's conjecture that the Mary Rebecca, as
+soon as launched, would run up the San Joaquin River nearly to
+Stockton for a load of wheat.  Then Charley made his proposition,
+and Ole Ericsen shook his head.
+</para>
+
+<para>
+"Just a hook, one good-sized hook," Charley pleaded.
+</para>
+
+<para>
+"No, Ay tank not," said Ole Ericsen.  "Der Mary Rebecca yust hang
+up on efery mud-bank with that hook.  Ay don't want to lose der
+Mary Rebecca.  She's all Ay got."
+</para>
+
+<para>
+"No, no," Charley hurried to explain.  "We can put the end of the
+hook through the bottom from the outside, and fasten it on the
+inside with a nut.  After it's done its work, why, all we have to
+do is to go down into the hold, unscrew the nut, and out drops the
+hook.  Then drive a wooden peg into the hole, and the Mary Rebecca
+will be all right again."
+</para>
+
+<para>
+Ole Ericsen was obstinate for a long time; but in the end, after we
+had had dinner with him, he was brought round to consent.
+</para>
+
+<para>
+"Ay do it, by Yupiter!" he said, striking one huge fist into the
+palm of the other hand.  "But yust hurry you up wid der hook.  Der
+Mary Rebecca slides into der water to-night."
+</para>
+
+<para>
+It was Saturday, and Charley had need to hurry.  We headed for the
+shipyard blacksmith shop, where, under Charley's directions, a most
+generously curved book of heavy steel was made.  Back we hastened
+to the Mary Rebecca.  Aft of the great centre-board case, through
+what was properly her keel, a hole was bored.  The end of the hook
+was inserted from the outside, and Charley, on the inside, screwed
+the nut on tightly.  As it stood complete, the hook projected over
+a foot beneath the bottom of the schooner.  Its curve was something
+like the curve of a sickle, but deeper.
+</para>
+
+<para>
+In the late afternoon the Mary Rebecca was launched, and
+preparations were finished for the start up-river next morning.
+Charley and Ole intently studied the evening sky for signs of wind,
+for without a good breeze our project was doomed to failure.  They
+agreed that there were all the signs of a stiff westerly wind - not
+the ordinary afternoon sea-breeze, but a half-gale, which even then
+was springing up.
+</para>
+
+<para>
+Next morning found their predictions verified.  The sun was shining
+brightly, but something more than a half-gale was shrieking up the
+Carquinez Straits, and the Mary Rebecca got under way with two
+reefs in her mainsail and one in her foresail.  We found it quite
+rough in the Straits and in Suisun Bay; but as the water grew more
+land-locked it became calm, though without let-up in the wind.
+</para>
+
+<para>
+Off Ship Island Light the reefs were shaken out, and at Charley's
+suggestion a big fisherman's staysail was made all ready for
+hoisting, and the maintopsail, bunched into a cap at the masthead,
+was overhauled so that it could be set on an instant's notice.
+</para>
+
+<para>
+We were tearing along, wing-and-wing, before the wind, foresail to
+starboard and mainsail to port, as we came upon the salmon fleet.
+There they were, boats and nets, as on that first Sunday when they
+had bested us, strung out evenly over the river as far as we could
+see.  A narrow space on the right-hand side of the channel was left
+clear for steamboats, but the rest of the river was covered with
+the wide-stretching nets.  The narrow space was our logical course,
+but Charley, at the wheel, steered the Mary Rebecca straight for
+the nets.  This did not cause any alarm among the fishermen,
+because up-river sailing craft are always provided with "shoes" on
+the ends of their keels, which permit them to slip over the nets
+without fouling them.
+</para>
+
+<para>
+"Now she takes it!" Charley cried, as we dashed across the middle
+of a line of floats which marked a net.  At one end of this line
+was a small barrel buoy, at the other the two fishermen in their
+boat.  Buoy and boat at once began to draw together, and the
+fishermen to cry out, as they were jerked after us.  A couple of
+minutes later we hooked a second net, and then a third, and in this
+fashion we tore straight up through the centre of the fleet.
+</para>
+
+<para>
+The consternation we spread among the fishermen was tremendous.  As
+fast as we hooked a net the two ends of it, buoy and boat, came
+together as they dragged out astern; and so many buoys and boats,
+coming together at such breakneck speed, kept the fishermen on the
+jump to avoid smashing into one another.  Also, they shouted at us
+like mad to heave to into the wind, for they took it as some
+drunken prank on the part of scow-sailors, little dreaming that we
+were the fish patrol.
+</para>
+
+<para>
+The drag of a single net is very heavy, and Charley and Ole Ericsen
+decided that even in such a wind ten nets were all the Mary Rebecca
+could take along with her.  So when we had hooked ten nets, with
+ten boats containing twenty men streaming along behind us, we
+veered to the left out of the fleet and headed toward Collinsville.
+</para>
+
+<para>
+We were all jubilant.  Charley was handling the wheel as though he
+were steering the winning yacht home in a race.  The two sailors
+who made up the crew of the Mary Rebecca, were grinning and joking.
+Ole Ericsen was rubbing his huge hands in child-like glee.
+</para>
+
+<para>
+"Ay tank you fish patrol fallers never ban so lucky as when you
+sail with Ole Ericsen," he was saying, when a rifle cracked sharply
+astern, and a bullet gouged along the newly painted cabin, glanced
+on a nail, and sang shrilly onward into space.
+</para>
+
+<para>
+This was too much for Ole Ericsen.  At sight of his beloved
+paintwork thus defaced, he jumped up and shook his fist at the
+fishermen; but a second bullet smashed into the cabin not six
+inches from his head, and he dropped down to the deck under cover
+of the rail.
+</para>
+
+<para>
+All the fishermen had rifles, and they now opened a general
+fusillade.  We were all driven to cover - even Charley, who was
+compelled to desert the wheel.  Had it not been for the heavy drag
+of the nets, we would inevitably have broached to at the mercy of
+the enraged fishermen.  But the nets, fastened to the bottom of the
+Mary Rebecca well aft, held her stern into the wind, and she
+continued to plough on, though somewhat erratically.
+</para>
+
+<para>
+Charley, lying on the deck, could just manage to reach the lower
+spokes of the wheel; but while he could steer after a fashion, it
+was very awkward.  Ole Ericsen bethought himself of a large piece
+of sheet steel in the empty hold.
+</para>
+
+<para>
+It was in fact a plate from the side of the New Jersey, a steamer
+which had recently been wrecked outside the Golden Gate, and in the
+salving of which the Mary Rebecca had taken part.
+</para>
+
+<para>
+Crawling carefully along the deck, the two sailors, Ole, and myself
+got the heavy plate on deck and aft, where we reared it as a shield
+between the wheel and the fishermen.  The bullets whanged and
+banged against it till it rang like a bull's-eye, but Charley
+grinned in its shelter, and coolly went on steering.
+</para>
+
+<para>
+So we raced along, behind us a howling, screaming bedlam of
+wrathful Greeks, Collinsville ahead, and bullets spat-spatting all
+around us.
+</para>
+
+<para>
+"Ole," Charley said in a faint voice, "I don't know what we're
+going to do."
+</para>
+
+<para>
+Ole Ericsen, lying on his back close to the rail and grinning
+upward at the sky, turned over on his side and looked at him.  "Ay
+tank we go into Collinsville yust der same," he said.
+</para>
+
+<para>
+"But we can't stop," Charley groaned.  "I never thought of it, but
+we can't stop."
+</para>
+
+<para>
+A look of consternation slowly overspread Ole Ericsen's broad face.
+It was only too true.  We had a hornet's nest on our hands, and to
+stop at Collinsville would be to have it about our ears.
+</para>
+
+<para>
+"Every man Jack of them has a gun," one of the sailors remarked
+cheerfully.
+</para>
+
+<para>
+"Yes, and a knife, too," the other sailor added.
+</para>
+
+<para>
+It was Ole Ericsen's turn to groan.  "What for a Svaidish faller
+like me monkey with none of my biziness, I don't know," he
+soliloquized.
+</para>
+
+<para>
+A bullet glanced on the stern and sang off to starboard like a
+spiteful bee.  "There's nothing to do but plump the Mary Rebecca
+ashore and run for it," was the verdict of the first cheerful
+sailor.
+</para>
+
+<para>
+"And leaf der Mary Rebecca?" Ole demanded, with unspeakable horror
+in his voice.
+</para>
+
+<para>
+"Not unless you want to," was the response.  "But I don't want to
+be within a thousand miles of her when those fellers come aboard" -
+indicating the bedlam of excited Greeks towing behind.
+</para>
+
+<para>
+We were right in at Collinsville then, and went foaming by within
+biscuit-toss of the wharf.
+</para>
+
+<para>
+"I only hope the wind holds out," Charley said, stealing a glance
+at our prisoners.
+</para>
+
+<para>
+"What of der wind?" Ole demanded disconsolately.  "Der river will
+not hold out, and then . . . and then . . ."
+</para>
+
+<para>
+"It's head for tall timber, and the Greeks take the hindermost,"
+adjudged the cheerful sailor, while Ole was stuttering over what
+would happen when we came to the end of the river.
+</para>
+
+<para>
+We had now reached a dividing of the ways.  To the left was the
+mouth of the Sacramento River, to the right the mouth of the San
+Joaquin.  The cheerful sailor crept forward and jibed over the
+foresail as Charley put the helm to starboard and we swerved to the
+right into the San Joaquin.  The wind, from which we had been
+running away on an even keel, now caught us on our beam, and the
+Mary Rebecca was pressed down on her port side as if she were about
+to capsize.
+</para>
+
+<para>
+Still we dashed on, and still the fishermen dashed on behind.  The
+value of their nets was greater than the fines they would have to
+pay for violating the fish laws; so to cast off from their nets and
+escape, which they could easily do, would profit them nothing.
+Further, they remained by their nets instinctively, as a sailor
+remains by his ship.  And still further, the desire for vengeance
+was roused, and we could depend upon it that they would follow us
+to the ends of the earth, if we undertook to tow them that far.
+</para>
+
+<para>
+The rifle-firing had ceased, and we looked astern to see what our
+prisoners were doing.  The boats were strung along at unequal
+distances apart, and we saw the four nearest ones bunching
+together.  This was done by the boat ahead trailing a small rope
+astern to the one behind.  When this was caught, they would cast
+off from their net and heave in on the line till they were brought
+up to the boat in front.  So great was the speed at which we were
+travelling, however, that this was very slow work.  Sometimes the
+men would strain to their utmost and fail to get in an inch of the
+rope; at other times they came ahead more rapidly.
+</para>
+
+<para>
+When the four boats were near enough together for a man to pass
+from one to another, one Greek from each of three got into the
+nearest boat to us, taking his rifle with him.  This made five in
+the foremost boat, and it was plain that their intention was to
+board us.  This they undertook to do, by main strength and sweat,
+running hand over hand the float-line of a net.  And though it was
+slow, and they stopped frequently to rest, they gradually drew
+nearer.
+</para>
+
+<para>
+Charley smiled at their efforts, and said, "Give her the topsail,
+Ole."
+</para>
+
+<para>
+The cap at the mainmast head was broken out, and sheet and downhaul
+pulled flat, amid a scattering rifle fire from the boats; and the
+Mary Rebecca lay over and sprang ahead faster than ever.
+</para>
+
+<para>
+But the Greeks were undaunted.  Unable, at the increased speed, to
+draw themselves nearer by means of their hands, they rigged from
+the blocks of their boat sail what sailors call a "watch-tackle."
+One of them, held by the legs by his mates, would lean far over the
+bow and make the tackle fast to the float-line.  Then they would
+heave in on the tackle till the blocks were together, when the
+manoeuvre would be repeated.
+</para>
+
+<para>
+"Have to give her the staysail," Charley said.
+</para>
+
+<para>
+Ole Ericsen looked at the straining Mary Rebecca and shook his
+head.  "It will take der masts out of her," he said.
+</para>
+
+<para>
+"And we'll be taken out of her if you don't," Charley replied.
+</para>
+
+<para>
+Ole shot an anxious glance at his masts, another at the boat load
+of armed Greeks, and consented.
+</para>
+
+<para>
+The five men were in the bow of the boat - a bad place when a craft
+is towing.  I was watching the behavior of their boat as the great
+fisherman's staysail, far, far larger than the top-sail and used
+only in light breezes, was broken out.  As the Mary Rebecca lurched
+forward with a tremendous jerk, the nose of the boat ducked down
+into the water, and the men tumbled over one another in a wild rush
+into the stern to save the boat from being dragged sheer under
+water.
+</para>
+
+<para>
+"That settles them!" Charley remarked, though he was anxiously
+studying the behavior of the Mary Rebecca, which was being driven
+under far more canvas than she was rightly able to carry.
+</para>
+
+<para>
+"Next stop is Antioch!" announced the cheerful sailor, after the
+manner of a railway conductor.  "And next comes Merryweather!"
+</para>
+
+<para>
+"Come here, quick," Charley said to me.
+</para>
+
+<para>
+I crawled across the deck and stood upright beside him in the
+shelter of the sheet steel.
+</para>
+
+<para>
+"Feel in my inside pocket," he commanded, "and get my notebook.
+That's right.  Tear out a blank page and write what I tell you."
+</para>
+
+<para>
+And this is what I wrote:
+</para>
+
+<para>
+
+Telephone to Merryweather, to the sheriff, the constable, or the
+judge.  Tell them we are coming and to turn out the town.  Arm
+everybody.  Have them down on the wharf to meet us or we are gone
+gooses.
+</para>
+
+<para>
+
+Now make it good and fast to that marlin-spike, and stand by to
+toss it ashore."
+</para>
+
+<para>
+I did as he directed.  By then we were close to Antioch.  The wind
+was shouting through our rigging, the Mary Rebecca was half over on
+her side and rushing ahead like an ocean greyhound.  The seafaring
+folk of Antioch had seen us breaking out topsail and staysail, a
+most reckless performance in such weather, and had hurried to the
+wharf-ends in little groups to find out what was the matter.
+</para>
+
+<para>
+Straight down the water front we boomed, Charley edging in till a
+man could almost leap ashore.  When he gave the signal I tossed the
+marlinspike.  It struck the planking of the wharf a resounding
+smash, bounced along fifteen or twenty feet, and was pounced upon
+by the amazed onlookers.
+</para>
+
+<para>
+It all happened in a flash, for the next minute Antioch was behind
+and we were heeling it up the San Joaquin toward Merryweather, six
+miles away.  The river straightened out here into its general
+easterly course, and we squared away before the wind, wing-and-wing
+once more, the foresail bellying out to starboard.
+</para>
+
+<para>
+Ole Ericsen seemed sunk into a state of stolid despair.  Charley
+and the two sailors were looking hopeful, as they had good reason
+to be.  Merryweather was a coal-mining town, and, it being Sunday,
+it was reasonable to expect the men to be in town.  Further, the
+coal-miners had never lost any love for the Greek fishermen, and
+were pretty certain to render us hearty assistance.
+</para>
+
+<para>
+We strained our eyes for a glimpse of the town, and the first sight
+we caught of it gave us immense relief.  The wharves were black
+with men.  As we came closer, we could see them still arriving,
+stringing down the main street, guns in their hands and on the run.
+Charley glanced astern at the fishermen with a look of ownership in
+his eye which till then had been missing.  The Greeks were plainly
+overawed by the display of armed strength and were putting their
+own rifles away.
+</para>
+
+<para>
+We took in topsail and staysail, dropped the main peak, and as we
+got abreast of the principal wharf jibed the mainsail.  The Mary
+Rebecca shot around into the wind, the captive fishermen describing
+a great arc behind her, and forged ahead till she lost way, when
+lines we're flung ashore and she was made fast.  This was
+accomplished under a hurricane of cheers from the delighted miners.
+</para>
+
+<para>
+Ole Ericsen heaved a great sigh.  "Ay never tank Ay see my wife
+never again," he confessed.
+</para>
+
+<para>
+"Why, we were never in any danger," said Charley.
+</para>
+
+<para>
+Ole looked at him incredulously.
+</para>
+
+<para>
+"Sure, I mean it," Charley went on.  "All we had to do, any time,
+was to let go our end - as I am going to do now, so that those
+Greeks can untangle their nets."
+</para>
+
+<para>
+He went below with a monkey-wrench, unscrewed the nut, and let the
+hook drop off.  When the Greeks had hauled their nets into their
+boats and made everything shipshape, a posse of citizens took them
+off our hands and led them away to jail.
+</para>
+
+<para>
+"Ay tank Ay ban a great big fool," said Ole Ericsen.  But he
+changed his mind when the admiring townspeople crowded aboard to
+shake hands with him, and a couple of enterprising newspaper men
+took photographs of the Mary Rebecca and her captain.
+</para>
+
+
+</chapter>
+
+<chapter>
+<title>DEMETRIOS CONTOS</title>
+
+
+<para>
+It must not be thought, from what I have told of the Greek
+fishermen, that they were altogether bad.  Far from it.  But they
+were rough men, gathered together in isolated communities and
+fighting with the elements for a livelihood.  They lived far away
+from the law and its workings, did not understand it, and thought
+it tyranny.  Especially did the fish laws seem tyrannical.  And
+because of this, they looked upon the men of the fish patrol as
+their natural enemies.
+</para>
+
+<para>
+We menaced their lives, or their living, which is the same thing,
+in many ways.  We confiscated illegal traps and nets, the materials
+of which had cost them considerable sums and the making of which
+required weeks of labor.  We prevented them from catching fish at
+many times and seasons, which was equivalent to preventing them
+from making as good a living as they might have made had we not
+been in existence.  And when we captured them, they were brought
+into the courts of law, where heavy cash fines were collected from
+them.  As a result, they hated us vindictively.  As the dog is the
+natural enemy of the cat, the snake of man, so were we of the fish
+patrol the natural enemies of the fishermen.
+</para>
+
+<para>
+But it is to show that they could act generously as well as hate
+bitterly that this story of Demetrios Contos is told.  Demetrios
+Contos lived in Vallejo.  Next to Big Alec, he was the largest,
+bravest, and most influential man among the Greeks.  He had given
+us no trouble, and I doubt if he would ever have clashed with us
+had he not invested in a new salmon boat.  This boat was the cause
+of all the trouble.  He had had it built upon his own model, in
+which the lines of the general salmon boat were somewhat modified.
+</para>
+
+<para>
+To his high elation he found his new boat very fast - in fact,
+faster than any other boat on the bay or rivers.  Forthwith he grew
+proud and boastful:  and, our raid with the Mary Rebecca on the
+Sunday salmon fishers having wrought fear in their hearts, he sent
+a challenge up to Benicia.  One of the local fishermen conveyed it
+to us; it was to the effect that Demetrios Contos would sail up
+from Vallejo on the following Sunday, and in the plain sight of
+Benicia set his net and catch salmon, and that Charley Le Grant,
+patrolman, might come and get him if he could.  Of course Charley
+and I had heard nothing of the new boat.  Our own boat was pretty
+fast, and we were not afraid to have a brush with any other that
+happened along.
+</para>
+
+<para>
+Sunday came.  The challenge had been bruited abroad, and the
+fishermen and seafaring folk of Benicia turned out to a man,
+crowding Steamboat Wharf till it looked like the grand stand at a
+football match.  Charley and I had been sceptical, but the fact of
+the crowd convinced us that there was something in Demetrios
+Contos's dare.
+</para>
+
+<para>
+In the afternoon, when the sea-breeze had picked up in strength,
+his sail hove into view as he bowled along before the wind.  He
+tacked a score of feet from the wharf, waved his hand theatrically,
+like a knight about to enter the lists, received a hearty cheer in
+return, and stood away into the Straits for a couple of hundred
+yards.  Then he lowered sail, and, drifting the boat sidewise by
+means of the wind, proceeded to set his net.  He did not set much
+of it, possibly fifty feet; yet Charley and I were thunderstruck at
+the man's effrontery.  We did not know at the time, but we learned
+afterward, that the net he used was old and worthless.  It could
+catch fish, true; but a catch of any size would have torn it to
+pieces.
+</para>
+
+<para>
+Charley shook his head and said:
+</para>
+
+<para>
+"I confess, it puzzles me.  What if he has out only fifty feet?  He
+could never get it in if we once started for him.  And why does he
+come here anyway, flaunting his law-breaking in our faces?  Right
+in our home town, too."
+</para>
+
+<para>
+Charley's voice took on an aggrieved tone, and he continued for
+some minutes to inveigh against the brazenness of Demetrios Contos.
+</para>
+
+<para>
+In the meantime, the man in question was lolling in the stern of
+his boat and watching the net floats.  When a large fish is meshed
+in a gill-net, the floats by their agitation advertise the fact.
+And they evidently advertised it to Demetrios, for he pulled in
+about a dozen feet of net, and held aloft for a moment, before he
+flung it into the bottom of the boat, a big, glistening salmon.  It
+was greeted by the audience on the wharf with round after round of
+cheers.  This was more than Charley could stand.
+</para>
+
+<para>
+"Come on, lad," he called to me; and we lost no time jumping into
+our salmon boat and getting up sail.
+</para>
+
+<para>
+The crowd shouted warning to Demetrios, and as we darted out from
+the wharf we saw him slash his worthless net clear with a long
+knife.  His sail was all ready to go up, and a moment later it
+fluttered in the sunshine.  He ran aft, drew in the sheet, and
+filled on the long tack toward the Contra Costa Hills.
+</para>
+
+<para>
+By this time we were not more than thirty feet astern.  Charley was
+jubilant.  He knew our boat was fast, and he knew, further, that in
+fine sailing few men were his equals.  He was confident that we
+should surely catch Demetrios, and I shared his confidence.  But
+somehow we did not seem to gain.
+</para>
+
+<para>
+It was a pretty sailing breeze.  We were gliding sleekly through
+the water, but Demetrios was slowly sliding away from us.  And not
+only was he going faster, but he was eating into the wind a
+fraction of a point closer than we.  This was sharply impressed
+upon us when he went about under the Contra Costa Hills and passed
+us on the other tack fully one hundred feet dead to windward.
+</para>
+
+<para>
+"Whew!" Charley exclaimed.  "Either that boat is a daisy, or we've
+got a five-gallon coal-oil can fast to our keel!"
+</para>
+
+<para>
+It certainly looked it one way or the other.  And by the time
+Demetrios made the Sonoma Hills, on the other side of the Straits,
+we were so hopelessly outdistanced that Charley told me to slack
+off the sheet, and we squared away for Benicia.  The fishermen on
+Steamboat Wharf showered us with ridicule when we returned and tied
+up.  Charley and I got out and walked away, feeling rather
+sheepish, for it is a sore stroke to one's pride when he thinks he
+has a good boat and knows how to sail it, and another man comes
+along and beats him.
+</para>
+
+<para>
+Charley mooned over it for a couple of days; then word was brought
+to us, as before, that on the next Sunday Demetrios Contos would
+repeat his performance.  Charley roused himself.  He had our boat
+out of the water, cleaned and repainted its bottom, made a trifling
+alteration about the centre-board, overhauled the running gear, and
+sat up nearly all of Saturday night sewing on a new and much larger
+sail.  So large did he make it, in fact, that additional ballast
+was imperative, and we stowed away nearly five hundred extra pounds
+of old railroad iron in the bottom of the boat.
+</para>
+
+<para>
+Sunday came, and with it came Demetrios Contos, to break the law
+defiantly in open day.  Again we had the afternoon sea-breeze, and
+again Demetrios cut loose some forty or more feet of his rotten
+net, and got up sail and under way under our very noses.  But he
+had anticipated Charley's move, and his own sail peaked higher than
+ever, while a whole extra cloth had been added to the after leech.
+</para>
+
+<para>
+It was nip and tuck across to the Contra Costa Hills, neither of us
+seeming to gain or to lose.  But by the time we had made the return
+tack to the Sonoma Hills, we could see that, while we footed it at
+about equal speed, Demetrios had eaten into the wind the least bit
+more than we.  Yet Charley was sailing our boat as finely and
+delicately as it was possible to sail it, and getting more out of
+it than he ever had before.
+</para>
+
+<para>
+Of course, he could have drawn his revolver and fired at Demetrios;
+but we had long since found it contrary to our natures to shoot at
+a fleeing man guilty of only a petty offence.  Also a sort of tacit
+agreement seemed to have been reached between the patrolmen and the
+fishermen.  If we did not shoot while they ran away, they, in turn,
+did not fight if we once laid hands on them.  Thus Demetrios Contos
+ran away from us, and we did no more than try our best to overtake
+him; and, in turn, if our boat proved faster than his, or was
+sailed better, he would, we knew, make no resistance when we caught
+up with him.
+</para>
+
+<para>
+With our large sails and the healthy breeze romping up the
+Carquinez Straits, we found that our sailing was what is called
+"ticklish."  We had to be constantly on the alert to avoid a
+capsize, and while Charley steered I held the main-sheet in my hand
+with but a single turn round a pin, ready to let go at any moment.
+Demetrios, we could see, sailing his boat alone, had his hands
+full.
+</para>
+
+<para>
+But it was a vain undertaking for us to attempt to catch him.  Out
+of his inner consciousness he had evolved a boat that was better
+than ours.  And though Charley sailed fully as well, if not the
+least bit better, the boat he sailed was not so good as the
+Greek's.
+</para>
+
+<para>
+"Slack away the sheet," Charley commanded; and as our boat fell off
+before the wind, Demetrios's mocking laugh floated down to us.
+</para>
+
+<para>
+Charley shook his head, saying, "It's no use.  Demetrios has the
+better boat.  If he tries his performance again, we must meet it
+with some new scheme."
+</para>
+
+<para>
+This time it was my imagination that came to the rescue.
+</para>
+
+<para>
+"What's the matter," I suggested, on the Wednesday following, "with
+my chasing Demetrios in the boat next Sunday, while you wait for
+him on the wharf at Vallejo when he arrives?"
+</para>
+
+<para>
+Charley considered it a moment and slapped his knee.
+</para>
+
+<para>
+"A good idea!  You're beginning to use that head of yours.  A
+credit to your teacher, I must say."
+</para>
+
+<para>
+"But you mustn't chase him too far," he went on, the next moment,
+"or he'll head out into San Pablo Bay instead of running home to
+Vallejo, and there I'll be, standing lonely on the wharf and
+waiting in vain for him to arrive."
+</para>
+
+<para>
+On Thursday Charley registered an objection to my plan.
+</para>
+
+<para>
+"Everybody'll know I've gone to Vallejo, and you can depend upon it
+that Demetrios will know, too.  I'm afraid we'll have to give up
+the idea."
+</para>
+
+<para>
+This objection was only too valid, and for the rest of the day I
+struggled under my disappointment.  But that night a new way seemed
+to open to me, and in my eagerness I awoke Charley from a sound
+sleep.
+</para>
+
+<para>
+"Well," he grunted, "what's the matter?  House afire?"
+</para>
+
+<para>
+"No," I replied, "but my head is.  Listen to this.  On Sunday you
+and I will be around Benicia up to the very moment Demetrios's sail
+heaves into sight.  This will lull everybody's suspicions.  Then,
+when Demetrios's sail does heave in sight, do you stroll leisurely
+away and up-town.  All the fishermen will think you're beaten and
+that you know you're beaten."
+</para>
+
+<para>
+"So far, so good," Charley commented, while I paused to catch
+breath.
+</para>
+
+<para>
+"And very good indeed," I continued proudly.  "You stroll
+carelessly up-town, but when you're once out of sight you leg it
+for all you're worth for Dan Maloney's.  Take the little mare of
+his, and strike out on the country road for Vallejo.  The road's in
+fine condition, and you can make it in quicker time than Demetrios
+can beat all the way down against the wind."
+</para>
+
+<para>
+"And I'll arrange right away for the mare, first thing in the
+morning," Charley said, accepting the modified plan without
+hesitation.
+</para>
+
+<para>
+"But, I say," he said, a little later, this time waking me out of a
+sound sleep.
+</para>
+
+<para>
+I could hear him chuckling in the dark.
+</para>
+
+<para>
+"I say, lad, isn't it rather a novelty for the fish patrol to be
+taking to horseback?"
+</para>
+
+<para>
+"Imagination," I answered.  "It's what you're always preaching -
+'keep thinking one thought ahead of the other fellow, and you're
+bound to win out.'"
+</para>
+
+<para>
+"He! he!" he chuckled.  "And if one thought ahead, including a
+mare, doesn't take the other fellow's breath away this time, I'm
+not your humble servant, Charley Le Grant."
+</para>
+
+<para>
+"But can you manage the boat alone?" he asked, on Friday.
+"Remember, we've a ripping big sail on her."
+</para>
+
+<para>
+I argued my proficiency so well that he did not refer to the matter
+again till Saturday, when he suggested removing one whole cloth
+from the after leech.  I guess it was the disappointment written on
+my face that made him desist; for I, also, had a pride in my boat-
+sailing abilities, and I was almost wild to get out alone with the
+big sail and go tearing down the Carquinez Straits in the wake of
+the flying Greek.
+</para>
+
+<para>
+As usual, Sunday and Demetrios Contos arrived together.  It had
+become the regular thing for the fishermen to assemble on Steamboat
+Wharf to greet his arrival and to laugh at our discomfiture.  He
+lowered sail a couple of hundred yards out and set his customary
+fifty feet of rotten net.
+</para>
+
+<para>
+"I suppose this nonsense will keep up as long as his old net holds
+out," Charley grumbled, with intention, in the hearing of several
+of the Greeks.
+</para>
+
+<para>
+"Den I give-a heem my old-a net-a," one of them spoke up, promptly
+and maliciously,
+</para>
+
+<para>
+"I don't care," Charley answered.  "I've got some old net myself he
+can have - if he'll come around and ask for it."
+</para>
+
+<para>
+They all laughed at this, for they could afford to be sweet-
+tempered with a man so badly outwitted as Charley was.
+</para>
+
+<para>
+"Well, so long, lad," Charley called to me a moment later.  "I
+think I'll go up-town to Maloney's."
+</para>
+
+<para>
+"Let me take the boat out?" I asked.
+</para>
+
+<para>
+"If you want to," was his answer, as he turned on his heel and
+walked slowly away.
+</para>
+
+<para>
+Demetrios pulled two large salmon out of his net, and I jumped into
+the boat.  The fishermen crowded around in a spirit of fun, and
+when I started to get up sail overwhelmed me with all sorts of
+jocular advice.  They even offered extravagant bets to one another
+that I would surely catch Demetrios, and two of them, styling
+themselves the committee of judges, gravely asked permission to
+come along with me to see how I did it.
+</para>
+
+<para>
+But I was in no hurry.  I waited to give Charley all the time I
+could, and I pretended dissatisfaction with the stretch of the sail
+and slightly shifted the small tackle by which the huge sprit
+forces up the peak.  It was not until I was sure that Charley had
+reached Dan Maloney's and was on the little mare's back, that I
+cast off from the wharf and gave the big sail to the wind.  A stout
+puff filled it and suddenly pressed the lee gunwale down till a
+couple of buckets of water came inboard.  A little thing like this
+will happen to the best small-boat sailors, and yet, though I
+instantly let go the sheet and righted, I was cheered
+sarcastically, as though I had been guilty of a very awkward
+blunder.
+</para>
+
+<para>
+When Demetrios saw only one person in the fish patrol boat, and
+that one a boy, he proceeded to play with me.  Making a short tack
+out, with me not thirty feet behind, he returned, with his sheet a
+little free, to Steamboat Wharf.  And there he made short tacks,
+and turned and twisted and ducked around, to the great delight of
+his sympathetic audience.  I was right behind him all the time, and
+I dared to do whatever he did, even when he squared away before the
+wind and jibed his big sail over - a most dangerous trick with such
+a sail in such a wind.
+</para>
+
+<para>
+He depended upon the brisk sea breeze and the strong ebb-tide,
+which together kicked up a nasty sea, to bring me to grief.  But I
+was on my mettle, and never in all my life did I sail a boat better
+than on that day.  I was keyed up to concert pitch, my brain was
+working smoothly and quickly, my hands never fumbled once, and it
+seemed that I almost divined the thousand little things which a
+small-boat sailor must be taking into consideration every second.
+</para>
+
+<para>
+It was Demetrios who came to grief instead.  Something went wrong
+with his centre-board, so that it jammed in the case and would not
+go all the way down.  In a moment's breathing space, which he had
+gained from me by a clever trick, I saw him working impatiently
+with the centre-board, trying to force it down.  I gave him little
+time, and he was compelled quickly to return to the tiller and
+sheet.
+</para>
+
+<para>
+The centre-board made him anxious.  He gave over playing with me,
+and started on the long beat to Vallejo.  To my joy, on the first
+long tack across, I found that I could eat into the wind just a
+little bit closer than he.  Here was where another man in the boat
+would have been of value to him; for, with me but a few feet
+astern, he did not dare let go the tiller and run amidships to try
+to force down the centre-board.
+</para>
+
+<para>
+Unable to hang on as close in the eye of the wind as formerly, he
+proceeded to slack his sheet a trifle and to ease off a bit, in
+order to outfoot me.  This I permitted him to do till I had worked
+to windward, when I bore down upon him.  As I drew close, he
+feinted at coming about.  This led me to shoot into the wind to
+forestall him.  But it was only a feint, cleverly executed, and he
+held back to his course while I hurried to make up lost ground.
+</para>
+
+<para>
+He was undeniably smarter than I when it came to manoeuvring.  Time
+after time I all but had him, and each time he tricked me and
+escaped.  Besides, the wind was freshening, constantly, and each of
+us had his hands full to avoid capsizing.  As for my boat, it could
+not have been kept afloat but for the extra ballast.  I sat cocked
+over the weather gunwale, tiller in one hand and sheet in the
+other; and the sheet, with a single turn around a pin, I was very
+often forced to let go in the severer puffs.  This allowed the sail
+to spill the wind, which was equivalent to taking off so much
+driving power, and of course I lost ground.  My consolation was
+that Demetrios was as often compelled to do the same thing.
+</para>
+
+<para>
+The strong ebb-tide, racing down the Straits in the teeth of the
+wind, caused an unusually heavy and spiteful sea, which dashed
+aboard continually.  I was dripping wet, and even the sail was wet
+half-way up the after leech.  Once I did succeed in outmanoeuvring
+Demetrios, so that my bow bumped into him amidships.  Here was
+where I should have had another man.  Before I could run forward
+and leap aboard, he shoved the boats apart with an oar, laughing
+mockingly in my face as he did so.
+</para>
+
+<para>
+We were now at the mouth of the Straits, in a bad stretch of water.
+Here the Vallejo Straits and the Carquinez Straits rushed directly
+at each other.  Through the first flowed all the water of Napa
+River and the great tide-lands; through the second flowed all the
+water of Suisun Bay and the Sacramento and San Joaquin rivers.  And
+where such immense bodies of water, flowing swiftly, clashed
+together, a terrible tide-rip was produced.  To make it worse, the
+wind howled up San Pablo Bay for fifteen miles and drove in a
+tremendous sea upon the tide-rip.
+</para>
+
+<para>
+Conflicting currents tore about in all directions, colliding,
+forming whirlpools, sucks, and boils, and shooting up spitefully
+into hollow waves which fell aboard as often from leeward as from
+windward.  And through it all, confused, driven into a madness of
+motion, thundered the great smoking seas from San Pablo Bay.
+</para>
+
+<para>
+I was as wildly excited as the water.  The boat was behaving
+splendidly, leaping and lurching through the welter like a race-
+horse.  I could hardly contain myself with the joy of it.  The huge
+sail, the howling wind, the driving seas, the plunging boat - I, a
+pygmy, a mere speck in the midst of it, was mastering the elemental
+strife, flying through it and over it, triumphant and victorious.
+</para>
+
+<para>
+And just then, as I roared along like a conquering hero, the boat
+received a frightful smash and came instantly to a dead stop.  I
+was flung forward and into the bottom.  As I sprang up I caught a
+fleeting glimpse of a greenish, barnacle-covered object, and knew
+it at once for what it was, that terror of navigation, a sunken
+pile.  No man may guard against such a thing.  Water-logged and
+floating just beneath the surface, it was impossible to sight it in
+the troubled water in time to escape.
+</para>
+
+<para>
+The whole bow of the boat must have been crushed in, for in a few
+seconds the boat was half full.  Then a couple of seas filled it,
+and it sank straight down, dragged to bottom by the heavy ballast.
+So quickly did it all happen that I was entangled in the sail and
+drawn under.  When I fought my way to the surface, suffocating, my
+lungs almost bursting, I could see nothing of the oars.  They must
+have been swept away by the chaotic currents.  I saw Demetrios
+Contos looking back from his boat, and heard the vindictive and
+mocking tones of his voice as he shouted exultantly.  He held
+steadily on his course, leaving me to perish.
+</para>
+
+<para>
+There was nothing to do but to swim for it, which, in that wild
+confusion, was at the best a matter of but a few moments.  Holding
+my breath and working with my hands, I managed to get off my heavy
+sea-boots and my jacket.  Yet there was very little breath I could
+catch to hold, and I swiftly discovered that it was not so much a
+matter of swimming as of breathing.
+</para>
+
+<para>
+I was beaten and buffeted, smashed under by the great San Pablo
+whitecaps, and strangled by the hollow tide-rip waves which flung
+themselves into my eyes, nose, and mouth.  Then the strange sucks
+would grip my legs and drag me under, to spout me up in some fierce
+boiling, where, even as I tried to catch my breath, a great
+whitecap would crash down upon my head.
+</para>
+
+<para>
+It was impossible to survive any length of time.  I was breathing
+more water than air, and drowning all the time.  My senses began to
+leave me, my head to whirl around.  I struggled on, spasmodically,
+instinctively, and was barely half conscious when I felt myself
+caught by the shoulders and hauled over the gunwale of a boat.
+</para>
+
+<para>
+For some time I lay across a seat where I had been flung, face
+downward, and with the water running out of my mouth.  After a
+while, still weak and faint, I turned around to see who was my
+rescuer.  And there, in the stern, sheet in one hand and tiller in
+the other, grinning and nodding good-naturedly, sat Demetrios
+Contos.  He had intended to leave me to drown, - he said so
+afterward, - but his better self had fought the battle, conquered,
+and sent him back to me.
+</para>
+
+<para>
+"You all-a right?" he asked.
+</para>
+
+<para>
+I managed to shape a "yes" on my lips, though I could not yet
+speak.
+</para>
+
+<para>
+"You sail-a de boat verr-a good-a," he said.  "So good-a as a man."
+</para>
+
+<para>
+A compliment from Demetrios Contos was a compliment indeed, and I
+keenly appreciated it, though I could only nod my head in
+acknowledgment.
+</para>
+
+<para>
+We held no more conversation, for I was busy recovering and he was
+busy with the boat.  He ran in to the wharf at Vallejo, made the
+boat fast, and helped me out.  Then it was, as we both stood on the
+wharf, that Charley stepped out from behind a net-rack and put his
+hand on Demetrios Contos's arm.
+</para>
+
+<para>
+"He saved my life, Charley," I protested; "and I don't think he
+ought to be arrested."
+</para>
+
+<para>
+A puzzled expression came into Charley's face, which cleared
+immediately after, in a way it had when he made up his mind.
+</para>
+
+<para>
+"I can't help it, lad," he said kindly.  "I can't go back on my
+duty, and it's plain duty to arrest him.  To-day is Sunday; there
+are two salmon in his boat which he caught to-day.  What else can I
+do?"
+</para>
+
+<para>
+"But he saved my life," I persisted, unable to make any other
+argument.
+</para>
+
+<para>
+Demetrios Contos's face went black with rage when he learned
+Charley's judgment.  He had a sense of being unfairly treated.  The
+better part of his nature had triumphed, he had performed a
+generous act and saved a helpless enemy, and in return the enemy
+was taking him to jail.
+</para>
+
+<para>
+Charley and I were out of sorts with each other when we went back
+to Benicia.  I stood for the spirit of the law and not the letter;
+but by the letter Charley made his stand.  As far as he could see,
+there was nothing else for him to do.  The law said distinctly that
+no salmon should be caught on Sunday.  He was a patrolman, and it
+was his duty to enforce that law.  That was all there was to it.
+He had done his duty, and his conscience was clear.  Nevertheless,
+the whole thing seemed unjust to me, and I felt very sorry for
+Demetrios Contos.
+</para>
+
+<para>
+Two days later we went down to Vallejo to the trial.  I had to go
+along as a witness, and it was the most hateful task that I ever
+performed in my life when I testified on the witness stand to
+seeing Demetrios catch the two salmon Charley had captured him
+with.
+</para>
+
+<para>
+Demetrios had engaged a lawyer, but his case was hopeless.  The
+jury was out only fifteen minutes, and returned a verdict of
+guilty.  The judge sentenced Demetrios to pay a fine of one hundred
+dollars or go to jail for fifty days.
+</para>
+
+<para>
+Charley stepped up to the clerk of the court.  "I want to pay that
+fine," he said, at the same time placing five twenty-dollar gold
+pieces on the desk.  "It - it was the only way out of it, lad," he
+stammered, turning to me.
+</para>
+
+<para>
+The moisture rushed into my eyes as I seized his hand.  "I want to
+pay - " I began.
+</para>
+
+<para>
+"To pay your half?" he interrupted.  "I certainly shall expect you
+to pay it."
+</para>
+
+<para>
+In the meantime Demetrios had been informed by his lawyer that his
+fee likewise had been paid by Charley.
+</para>
+
+<para>
+Demetrios came over to shake Charley's hand, and all his warm
+Southern blood flamed in his face.  Then, not to be outdone in
+generosity, he insisted on paying his fine and lawyer's fee
+himself, and flew half-way into a passion because Charley refused
+to let him.
+</para>
+
+<para>
+More than anything else we ever did, I think, this action of
+Charley's impressed upon the fishermen the deeper significance of
+the law.  Also Charley was raised high in their esteem, while I
+came in for a little share of praise as a boy who knew how to sail
+a boat.  Demetrios Contos not only never broke the law again, but
+he became a very good friend of ours, and on more than one occasion
+he ran up to Benicia to have a gossip with us.
+</para>
+
+
+</chapter>
+
+<chapter>
+<title>YELLOW HANDKERCHIEF</title>
+
+
+<para>
+"I'm not wanting to dictate to you, lad," Charley said; "but I'm
+very much against your making a last raid.  You've gone safely
+through rough times with rough men, and it would be a shame to have
+something happen to you at the very end."
+</para>
+
+<para>
+"But how can I get out of making a last raid?" I demanded, with the
+cocksureness of youth.  "There always has to be a last, you know,
+to anything."
+</para>
+
+<para>
+Charley crossed his legs, leaned back, and considered the problem.
+"Very true.  But why not call the capture of Demetrios Contos the
+last?  You're back from it safe and sound and hearty, for all your
+good wetting, and - and - "  His voice broke and he could not speak
+for a moment.  "And I could never forgive myself if anything
+happened to you now."
+</para>
+
+<para>
+I laughed at Charley's fears while I gave in to the claims of his
+affection, and agreed to consider the last raid already performed.
+We had been together for two years, and now I was leaving the fish
+patrol in order to go back and finish my education.  I had earned
+and saved money to put me through three years at the high school,
+and though the beginning of the term was several months away, I
+intended doing a lot of studying for the entrance examinations.
+</para>
+
+<para>
+My belongings were packed snugly in a sea-chest, and I was all
+ready to buy my ticket and ride down on the train to Oakland, when
+Neil Partington arrived in Benicia.  The Reindeer was needed
+immediately for work far down on the Lower Bay, and Neil said he
+intended to run straight for Oakland.  As that was his home and as
+I was to live with his family while going to school, he saw no
+reason, he said, why I should not put my chest aboard and come
+along.
+</para>
+
+<para>
+So the chest went aboard, and in the middle of the afternoon we
+hoisted the Reindeer's big mainsail and cast off.  It was
+tantalizing fall weather.  The sea-breeze, which had blown steadily
+all summer, was gone, and in its place were capricious winds and
+murky skies which made the time of arriving anywhere extremely
+problematical.  We started on the first of the ebb, and as we
+slipped down the Carquinez Straits, I looked my last for some time
+upon Benicia and the bight at Turner's Shipyard, where we had
+besieged the Lancashire Queen, and had captured Big Alec, the King
+of the Greeks.  And at the mouth of the Straits I looked with not a
+little interest upon the spot where a few days before I should have
+drowned but for the good that was in the nature of Demetrios
+Contos.
+</para>
+
+<para>
+A great wall of fog advanced across San Pablo Bay to meet us, and
+in a few minutes the Reindeer was running blindly through the damp
+obscurity.  Charley, who was steering, seemed to have an instinct
+for that kind of work.  How he did it, he himself confessed that he
+did not know; but he had a way of calculating winds, currents,
+distance, time, drift, and sailing speed that was truly marvellous.
+</para>
+
+<para>
+"It looks as though it were lifting," Neil Partington said, a
+couple of hours after we had entered the fog.  "Where do you say we
+are, Charley?"
+</para>
+
+<para>
+Charley looked at his watch, "Six o'clock, and three hours more of
+ebb," he remarked casually.
+</para>
+
+<para>
+"But where do you say we are?" Neil insisted.
+</para>
+
+<para>
+Charley pondered a moment, and then answered, "The tide has edged
+us over a bit out of our course, but if the fog lifts right now, as
+it is going to lift, you'll find we're not more than a thousand
+miles off McNear's Landing."
+</para>
+
+<para>
+"You might be a little more definite by a few miles, anyway," Neil
+grumbled, showing by his tone that he disagreed.
+</para>
+
+<para>
+"All right, then," Charley said, conclusively, "not less than a
+quarter of a mile, not more than a half."
+</para>
+
+<para>
+The wind freshened with a couple of little puffs, and the fog
+thinned perceptibly.
+</para>
+
+<para>
+"McNear's is right off there," Charley said, pointing directly into
+the fog on our weather beam.
+</para>
+
+<para>
+The three of us were peering intently in that direction, when the
+Reindeer struck with a dull crash and came to a standstill.  We ran
+forward, and found her bowsprit entangled in the tanned rigging of
+a short, chunky mast.  She had collided, head on, with a Chinese
+junk lying at anchor.
+</para>
+
+<para>
+At the moment we arrived forward, five Chinese, like so many bees,
+came swarming out of the little 'tween-decks cabin, the sleep still
+in their eyes.
+</para>
+
+<para>
+Leading them came a big, muscular man, conspicuous for his pock-
+marked face and the yellow silk handkerchief swathed about his
+head.  It was Yellow Handkerchief, the Chinaman whom we had
+arrested for illegal shrimp-fishing the year before, and who, at
+that time, had nearly sunk the Reindeer, as he had nearly sunk it
+now by violating the rules of navigation.
+</para>
+
+<para>
+"What d'ye mean, you yellow-faced heathen, lying here in a fairway
+without a horn a-going?" Charley cried hotly.
+</para>
+
+<para>
+"Mean?" Neil calmly answered.  "Just take a look - that's what he
+means."
+</para>
+
+<para>
+Our eyes followed the direction indicated by Neil's finger, and we
+saw the open amidships of the junk, half filled, as we found on
+closer examination, with fresh-caught shrimps.  Mingled with the
+shrimps were myriads of small fish, from a quarter of an inch
+upward in size.
+</para>
+
+<para>
+Yellow Handkerchief had lifted the trap-net at high-water slack,
+and, taking advantage of the concealment offered by the fog, had
+boldly been lying by, waiting to lift the net again at low-water
+slack.
+</para>
+
+<para>
+"Well," Neil hummed and hawed, "in all my varied and extensive
+experience as a fish patrolman, I must say this is the easiest
+capture I ever made.  What'll we do with them, Charley?"
+</para>
+
+<para>
+"Tow the junk into San Rafael, of course," came the answer.
+Charley turned to me.  "You stand by the junk, lad, and I'll pass
+you a towing line.  If the wind doesn't fail us, we'll make the
+creek before the tide gets too low, sleep at San Rafael, and arrive
+in Oakland to-morrow by midday."
+</para>
+
+<para>
+So saying, Charley and Neil returned to the Reindeer and got under
+way, the junk towing astern.  I went aft and took charge of the
+prize, steering by means of an antiquated tiller and a rudder with
+large, diamond-shaped holes, through which the water rushed back
+and forth.
+</para>
+
+<para>
+By now the last of the fog had vanished, and Charley's estimate of
+our position was confirmed by the sight of McNear's Landing a short
+half-mile away.  Following along the west shore, we rounded Point
+Pedro in plain view of the Chinese shrimp villages, and a great to-
+do was raised when they saw one of their junks towing behind the
+familiar fish patrol sloop.
+</para>
+
+<para>
+The wind, coming off the land, was rather puffy and uncertain, and
+it would have been more to our advantage had it been stronger.  San
+Rafael Creek, up which we had to go to reach the town and turn over
+our prisoners to the authorities, ran through wide-stretching
+marshes, and was difficult to navigate on a falling tide, while at
+low tide it was impossible to navigate at all.  So, with the tide
+already half-ebbed, it was necessary for us to make time.  This the
+heavy junk prevented, lumbering along behind and holding the
+Reindeer back by just so much dead weight.
+</para>
+
+<para>
+"Tell those coolies to get up that sail," Charley finally called to
+me.  "We don't want to hang up on the mud flats for the rest of the
+night."
+</para>
+
+<para>
+I repeated the order to Yellow Handkerchief, who mumbled it huskily
+to his men.  He was suffering from a bad cold, which doubled him up
+in convulsive coughing spells and made his eyes heavy and
+bloodshot.  This made him more evil-looking than ever, and when he
+glared viciously at me I remembered with a shiver the close shave I
+had had with him at the time of his previous arrest.
+</para>
+
+<para>
+His crew sullenly tailed on to the halyards, and the strange,
+outlandish sail, lateen in rig and dyed a warm brown, rose in the
+air.  We were sailing on the wind, and when Yellow Handkerchief
+flattened down the sheet the junk forged ahead and the tow-line
+went slack.  Fast as the Reindeer could sail, the junk outsailed
+her; and to avoid running her down I hauled a little closer on the
+wind.  But the junk likewise outpointed, and in a couple of minutes
+I was abreast of the Reindeer and to windward.  The tow-line had
+now tautened, at right angles to the two boats, and the predicament
+was laughable.
+</para>
+
+<para>
+"Cast off!" I shouted.
+</para>
+
+<para>
+Charley hesitated.
+</para>
+
+<para>
+"It's all right," I added.  "Nothing can happen.  We'll make the
+creek on this tack, and you'll be right behind me all the way up to
+San Rafael."
+</para>
+
+<para>
+At this Charley cast off, and Yellow Handkerchief sent one of his
+men forward to haul in the line.  In the gathering darkness I could
+just make out the mouth of San Rafael Creek, and by the time we
+entered it I could barely see its banks.  The Reindeer was fully
+five minutes astern, and we continued to leave her astern as we
+beat up the narrow, winding channel.  With Charley behind us, it
+seemed I had little to fear from my five prisoners; but the
+darkness prevented my keeping a sharp eye on them, so I transferred
+my revolver from my trousers pocket to the side pocket of my coat,
+where I could more quickly put my hand on it.
+</para>
+
+<para>
+Yellow Handkerchief was the one I feared, and that he knew it and
+made use of it, subsequent events will show.  He was sitting a few
+feet away from me, on what then happened to be the weather side of
+the junk.  I could scarcely see the outlines of his form, but I
+soon became convinced that he was slowly, very slowly, edging
+closer to me.  I watched him carefully.  Steering with my left
+hand, I slipped my right into my pocket and got hold of the
+revolver.
+</para>
+
+<para>
+I saw him shift along for a couple of inches, and I was just about
+to order him back - the words were trembling on the tip of my
+tongue - when I was struck with great force by a heavy figure that
+had leaped through the air upon me from the lee side.  It was one
+of the crew.  He pinioned my right arm so that I could not withdraw
+my hand from my pocket, and at the same time clapped his other hand
+over my mouth.  Of course, I could have struggled away from him and
+freed my hand or gotten my mouth clear so that I might cry an
+alarm, but in a trice Yellow Handkerchief was on top of me.
+</para>
+
+<para>
+I struggled around to no purpose in the bottom of the junk, while
+my legs and arms were tied and my mouth securely bound in what I
+afterward found to be a cotton shirt.  Then I was left lying in the
+bottom.  Yellow Handkerchief took the tiller, issuing his orders in
+whispers; and from our position at the time, and from the
+alteration of the sail, which I could dimly make out above me as a
+blot against the stars, I knew the junk was being headed into the
+mouth of a small slough which emptied at that point into San Rafael
+Creek.
+</para>
+
+<para>
+In a couple of minutes we ran softly alongside the bank, and the
+sail was silently lowered.  The Chinese kept very quiet.  Yellow
+Handkerchief sat down in the bottom alongside of me, and I could
+feel him straining to repress his raspy, hacking cough.  Possibly
+seven or eight minutes later I heard Charley's voice as the
+Reindeer went past the mouth of the slough.
+</para>
+
+<para>
+"I can't tell you how relieved I am," I could plainly hear him
+saying to Neil, "that the lad has finished with the fish patrol
+without accident."
+</para>
+
+<para>
+Here Neil said something which I could not catch, and then
+Charley's voice went on:
+</para>
+
+<para>
+"The youngster takes naturally to the water, and if, when he
+finishes high school, he takes a course in navigation and goes deep
+sea, I see no reason why he shouldn't rise to be master of the
+finest and biggest ship afloat."
+</para>
+
+<para>
+It was all very flattering to me, but lying there, bound and gagged
+by my own prisoners, with the voices growing faint and fainter as
+the Reindeer slipped on through the darkness toward San Rafael, I
+must say I was not in quite the proper situation to enjoy my
+smiling future.  With the Reindeer went my last hope.  What was to
+happen next I could not imagine, for the Chinese were a different
+race from mine, and from what I knew I was confident that fair play
+was no part of their make-up.
+</para>
+
+<para>
+After waiting a few minutes longer, the crew hoisted the lateen
+sail, and Yellow Handkerchief steered down toward the mouth of San
+Rafael Creek.  The tide was getting lower, and he had difficulty in
+escaping the mud-banks.  I was hoping he would run aground, but he
+succeeded in making the Bay without accident.
+</para>
+
+<para>
+As we passed out of the creek a noisy discussion arose, which I
+knew related to me.  Yellow Handkerchief was vehement, but the
+other four as vehemently opposed him.  It was very evident that he
+advocated doing away with me and that they were afraid of the
+consequences.  I was familiar enough with the Chinese character to
+know that fear alone restrained them.  But what plan they offered
+in place of Yellow Handkerchief's murderous one, I could not make
+out.
+</para>
+
+<para>
+My feelings, as my fate hung in the balance, may be guessed.  The
+discussion developed into a quarrel, in the midst of which Yellow
+Handkerchief unshipped the heavy tiller and sprang toward me.  But
+his four companions threw themselves between, and a clumsy struggle
+took place for possession of the tiller.  In the end Yellow
+Handkerchief was overcome, and sullenly returned to the steering,
+while they soundly berated him for his rashness.
+</para>
+
+<para>
+Not long after, the sail was run down and the junk slowly urged
+forward by means of the sweeps.  I felt it ground gently on the
+soft mud.  Three of the Chinese - they all wore long sea-boots -
+got over the side, and the other two passed me across the rail.
+With Yellow Handkerchief at my legs and his two companions at my
+shoulders, they began to flounder along through the mud.  After
+some time their feet struck firmer footing, and I knew they were
+carrying me up some beach.  The location of this beach was not
+doubtful in my mind.  It could be none other than one of the Marin
+Islands, a group of rocky islets which lay off the Marin County
+shore.
+</para>
+
+<para>
+When they reached the firm sand that marked high tide, I was
+dropped, and none too gently.  Yellow Handkerchief kicked me
+spitefully in the ribs, and then the trio floundered back through
+the mud to the junk.  A moment later I heard the sail go up and
+slat in the wind as they drew in the sheet.  Then silence fell, and
+I was left to my own devices for getting free.
+</para>
+
+<para>
+I remembered having seen tricksters writhe and squirm out of ropes
+with which they were bound, but though I writhed and squirmed like
+a good fellow, the knots remained as hard as ever, and there was no
+appreciable slack.  In the course of my squirming, however, I
+rolled over upon a heap of clam-shells - the remains, evidently, of
+some yachting party's clam-bake.  This gave me an idea.  My hands
+were tied behind my back; and, clutching a shell in them, I rolled
+over and over, up the beach, till I came to the rocks I knew to be
+there.
+</para>
+
+<para>
+Rolling around and searching, I finally discovered a narrow
+crevice, into which I shoved the shell.  The edge of it was sharp,
+and across the sharp edge I proceeded to saw the rope that bound my
+wrists.  The edge of the shell was also brittle, and I broke it by
+bearing too heavily upon it.  Then I rolled back to the heap and
+returned with as many shells as I could carry in both hands.  I
+broke many shells, cut my hands a number of times, and got cramps
+in my legs from my strained position and my exertions.
+</para>
+
+<para>
+While I was suffering from the cramps, and resting, I heard a
+familiar halloo drift across the water.  It was Charley, searching
+for me.  The gag in my mouth prevented me from replying, and I
+could only lie there, helplessly fuming, while he rowed past the
+island and his voice slowly lost itself in the distance.
+</para>
+
+<para>
+I returned to the sawing process, and at the end of half an hour
+succeeded in severing the rope.  The rest was easy.  My hands once
+free, it was a matter of minutes to loosen my legs and to take the
+gag out of my mouth.  I ran around the island to make sure it was
+an island and not by any chance a portion of the mainland.  An
+island it certainly was, one of the Marin group, fringed with a
+sandy beach and surrounded by a sea of mud.  Nothing remained but
+to wait till daylight and to keep warm; for it was a cold, raw
+night for California, with just enough wind to pierce the skin and
+cause one to shiver.
+</para>
+
+<para>
+To keep up the circulation, I ran around the island a dozen times
+or so, and clambered across its rocky backbone as many times more -
+all of which was of greater service to me, as I afterward
+discovered, than merely to warm me up.  In the midst of this
+exercise I wondered if I had lost anything out of my pockets while
+rolling over and over in the sand.  A search showed the absence of
+my revolver and pocket-knife.  The first Yellow Handkerchief had
+taken; but the knife had been lost in the sand.
+</para>
+
+<para>
+I was hunting for it when the sound of rowlocks came to my ears.
+At first, of course, I thought of Charley; but on second thought I
+knew Charley would be calling out as he rowed along.  A sudden
+premonition of danger seized me.  The Marin Islands are lonely
+places; chance visitors in the dead of night are hardly to be
+expected.  What if it were Yellow Handkerchief?  The sound made by
+the rowlocks grew more distinct.  I crouched in the sand and
+listened intently.  The boat, which I judged a small skiff from the
+quick stroke of the oars, was landing in the mud about fifty yards
+up the beach.  I heard a raspy, hacking cough, and my heart stood
+still.  It was Yellow Handkerchief.  Not to be robbed of his
+revenge by his more cautious companions, he had stolen away from
+the village and come back alone.
+</para>
+
+<para>
+I did some swift thinking.  I was unarmed and helpless on a tiny
+islet, and a yellow barbarian, whom I had reason to fear, was
+coming after me.  Any place was safer than the island, and I turned
+instinctively to the water, or rather to the mud.  As he began to
+flounder ashore through the mud, I started to flounder out into it,
+going over the same course which the Chinese had taken in landing
+me and in returning to the junk.
+</para>
+
+<para>
+Yellow Handkerchief, believing me to be lying tightly bound,
+exercised no care, but came ashore noisily.  This helped me, for,
+under the shield of his noise and making no more myself than
+necessary, I managed to cover fifty feet by the time he had made
+the beach.  Here I lay down in the mud.  It was cold and clammy,
+and made me shiver, but I did not care to stand up and run the risk
+of being discovered by his sharp eyes.
+</para>
+
+<para>
+He walked down the beach straight to where he had left me lying,
+and I had a fleeting feeling of regret at not being able to see his
+surprise when he did not find me.  But it was a very fleeting
+regret, for my teeth were chattering with the cold.
+</para>
+
+<para>
+What his movements were after that I had largely to deduce from the
+facts of the situation, for I could scarcely see him in the dim
+starlight.  But I was sure that the first thing he did was to make
+the circuit of the beach to learn if landings had been made by
+other boats.  This he would have known at once by the tracks
+through the mud.
+</para>
+
+<para>
+Convinced that no boat had removed me from the island, he next
+started to find out what had become of me.  Beginning at the pile
+of clamshells, he lighted matches to trace my tracks in the sand.
+At such times I could see his villanous face plainly, and, when the
+sulphur from the matches irritated his lungs, between the raspy
+cough that followed and the clammy mud in which I was lying, I
+confess I shivered harder than ever.
+</para>
+
+<para>
+The multiplicity of my footprints puzzled him.  Then the idea that
+I might be out in the mud must have struck him, for he waded out a
+few yards in my direction, and, stooping, with his eyes searched
+the dim surface long and carefully.  He could not have been more
+than fifteen feet from me, and had he lighted a match he would
+surely have discovered me.
+</para>
+
+<para>
+He returned to the beach and clambered about, over the rocky
+backbone, again hunting for me with lighted matches, The closeness
+of the shave impelled me to further flight.  Not daring to wade
+upright, on account of the noise made by floundering and by the
+suck of the mud, I remained lying down in the mud and propelled
+myself over its surface by means of my hands.  Still keeping the
+trail made by the Chinese in going from and to the junk, I held on
+until I reached the water.  Into this I waded to a depth of three
+feet, and then I turned off to the side on a line parallel with the
+beach.
+</para>
+
+<para>
+The thought came to me of going toward Yellow Handkerchief's skiff
+and escaping in it, but at that very moment he returned to the
+beach, and, as though fearing the very thing I had in mind, he
+slushed out through the mud to assure himself that the skiff was
+safe.  This turned me in the opposite direction.  Half swimming,
+half wading, with my head just out of water and avoiding splashing,
+I succeeded in putting about a hundred feet between myself and the
+spot where the Chinese had begun to wade ashore from the junk.  I
+drew myself out on the mud and remained lying flat.
+</para>
+
+<para>
+Again Yellow Handkerchief returned to the beach and made a search
+of the island, and again he returned to the heap of clam-shells.  I
+knew what was running in his mind as well as he did himself.  No
+one could leave or land without making tracks in the mud.  The only
+tracks to be seen were those leading from his skiff and from where
+the junk had been.  I was not on the island.  I must have left it
+by one or the other of those two tracks.  He had just been over the
+one to his skiff, and was certain I had not left that way.
+Therefore I could have left the island only by going over the
+tracks of the junk landing.  This he proceeded to verify by wading
+out over them himself, lighting matches as he came along.
+</para>
+
+<para>
+When he arrived at the point where I had first lain, I knew, by the
+matches he burned and the time he took, that he had discovered the
+marks left by my body.  These he followed straight to the water and
+into it, but in three feet of water he could no longer see them.
+On the other hand, as the tide was still falling, he could easily
+make out the impression made by the junk's bow, and could have
+likewise made out the impression of any other boat if it had landed
+at that particular spot.  But there was no such mark; and I knew
+that he was absolutely convinced that I was hiding somewhere in the
+mud.
+</para>
+
+<para>
+But to hunt on a dark night for a boy in a sea of mud would be like
+hunting for a needle in a haystack, and he did not attempt it.
+Instead he went back to the beach and prowled around for some time.
+I was hoping he would give me up and go, for by this time I was
+suffering severely from the cold.  At last he waded out to his
+skiff and rowed away.  What if this departure of Yellow
+Handkerchief's were a sham?  What if he had done it merely to
+entice me ashore?
+</para>
+
+<para>
+The more I thought of it the more certain I became that he had made
+a little too much noise with his oars as he rowed away.  So I
+remained, lying in the mud and shivering.  I shivered till the
+muscles of the small of my back ached and pained me as badly as the
+cold, and I had need of all my self-control to force myself to
+remain in my miserable situation.
+</para>
+
+<para>
+It was well that I did, however, for, possibly an hour later, I
+thought I could make out something moving on the beach.  I watched
+intently, but my ears were rewarded first, by a raspy cough I knew
+only too well.  Yellow Handkerchief had sneaked back, landed on the
+other side of the island, and crept around to surprise me if I had
+returned.
+</para>
+
+<para>
+After that, though hours passed without sign of him, I was afraid
+to return to the island at all.  On the other hand, I was almost
+equally afraid that I should die of the exposure I was undergoing.
+I had never dreamed one could suffer so.  I grew so cold and numb,
+finally, that I ceased to shiver.  But my muscles and bones began
+to ache in a way that was agony.  The tide had long since begun to
+rise, and, foot by foot, it drove me in toward the beach.  High
+water came at three o'clock, and at three o'clock I drew myself up
+on the beach, more dead than alive, and too helpless to have
+offered any resistance had Yellow Handkerchief swooped down upon
+me.
+</para>
+
+<para>
+But no Yellow Handkerchief appeared.  He had given me up and gone
+back to Point Pedro.  Nevertheless, I was in a deplorable, not to
+say dangerous, condition.  I could not stand upon my feet, much
+less walk.  My clammy, muddy garments clung to me like sheets of
+ice.  I thought I should never get them off.  So numb and lifeless
+were my fingers, and so weak was I, that it seemed to take an hour
+to get off my shoes.  I had not the strength to break the porpoise-
+hide laces, and the knots defied me.  I repeatedly beat my hands
+upon the rocks to get some sort of life into them.  Sometimes I
+felt sure I was going to die.
+</para>
+
+<para>
+But in the end, - after several centuries, it seemed to me, - I got
+off the last of my clothes.  The water was now close at hand, and I
+crawled painfully into it and washed the mud from my naked body.
+Still, I could not get on my feet and walk and I was afraid to lie
+still.  Nothing remained but to crawl weakly, like a snail, and at
+the cost of constant pain, up and down the sand.  I kept this up as
+long as possible, but as the east paled with the coming of dawn I
+began to succumb.  The sky grew rosy-red, and the golden rim of the
+sun, showing above the horizon, found me lying helpless and
+motionless among the clam-shells.
+</para>
+
+<para>
+As in a dream, I saw the familiar mainsail of the Reindeer as she
+slipped out of San Rafael Creek on a light puff of morning air.
+This dream was very much broken.  There are intervals I can never
+recollect on looking back over it.  Three things, however, I
+distinctly remember:  the first sight of the Reindeer's mainsail;
+her lying at anchor a few hundred feet away and a small boat
+leaving her side; and the cabin stove roaring red-hot, myself
+swathed all over with blankets, except on the chest and shoulders,
+which Charley was pounding and mauling unmercifully, and my mouth
+and throat burning with the coffee which Neil Partington was
+pouring down a trifle too hot.
+</para>
+
+<para>
+But burn or no burn, I tell you it felt good.  By the time we
+arrived in Oakland I was as limber and strong as ever, - though
+Charlie and Neil Partington were afraid I was going to have
+pneumonia, and Mrs. Partington, for my first six months of school,
+kept an anxious eye upon me to discover the first symptoms of
+consumption.
+</para>
+
+<para>
+Time flies.  It seems but yesterday that I was a lad of sixteen on
+the fish patrol.  Yet I know that I arrived this very morning from
+China, with a quick passage to my credit, and master of the
+barkentine Harvester.  And I know that to-morrow morning I shall
+run over to Oakland to see Neil Partington and his wife and family,
+and later on up to Benicia to see Charley Le Grant and talk over
+old times.  No; I shall not go to Benicia, now that I think about
+it.  I expect to be a highly interested party to a wedding, shortly
+to take place.  Her name is Alice Partington, and, since Charley
+has promised to be best man, he will have to come down to Oakland
+instead.
+</para>
+</chapter>
+
+</bookbody>
+</book>
+<endgutblurb>
+End of Project Gutenberg's Etext of Tales of the Fish Patrol, by London
+</endgutblurb>
+
+</gutbook>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/import/gutbook1.dtd
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/import/gutbook1.dtd	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/import/gutbook1.dtd	(revision 13928)
@@ -0,0 +1,40 @@
+<!--
+GUTBOOK DTD V 1.0
+==================
+
+GENERAL NOTES
++++++++++++++
+This is gutbook dtd version 1.0
+file name is gutpoems1.dtd
+This dtd is a first pass at a dtd for marking up 
+books for project gutenberg.
+It was originally developed for marking up the Darwins books.
+
+REVISION HISTORY
+++++++++++++++++
+Original Author
+Frank Boumphrey  1/19/2000
+
+COPYRIGHT NOTICE
+++++++++++++++++
+This DTD is the copyright of the HTML writers guild.
+Permission is given in perpetuity for any one to use 
+this DTD provided that these notes and this  copyright 
+notice is included.
+
+
+-->
+
+<!--Begin gutbook DTD-->
+<!ELEMENT gutbook (gutblurb,markupblurb,book*,endmarkupblurb?,endgutblurb?)>
+
+<!ELEMENT gutblurb (#PCDATA|para|simplesect|title)*>
+<!ELEMENT markupblurb (#PCDATA|para|simplesect|title)*>
+<!ELEMENT endmarkupblurb (#PCDATA|para|simplesect|title)*>
+<!ELEMENT endgutblurb (#PCDATA|para|simplesect|title)*>
+
+<!--Include bookfrag.dtd-->
+
+<!ENTITY % bookfrag SYSTEM "bookfrag.dtd">
+%bookfrag;
+<!--end of file-->
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/import/iliad.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/import/iliad.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/import/iliad.xml	(revision 13928)
@@ -0,0 +1,16976 @@
+<?xml version="1.0"?>
+<!DOCTYPE gutbook SYSTEM "gutbook1.dtd">
+
+<?xml-stylesheet type="text/css" href="darwin.css"?>
+
+<gutbook>
+<gutblurb>
+<para>
+*******The Project Gutenberg Etext of The Iliad, by Homer*****
+translated by Samuel Butler
+#3 in our series by Homer
+</para>
+
+<para>
+Copyright laws are changing all over the world, be sure to check
+the copyright laws for your country before posting these files!!
+</para>
+
+<para>
+Please take a look at the important information in this header.
+We encourage you to keep this file on your own disk, keeping an
+electronic path open for the next readers.  Do not remove this.
+</para>
+
+<para>
+**Welcome To The World of Free Plain Vanilla Electronic Texts**
+</para>
+
+<para>
+**Etexts Readable By Both Humans and By Computers, Since 1971**
+</para>
+
+<para>
+*These Etexts Prepared By Hundreds of Volunteers and Donations*
+</para>
+
+<para>
+Information on contacting Project Gutenberg to get Etexts, and
+further information is included below.  We need your donations.
+</para>
+
+<para>
+The Iliad of Homer
+</para>
+
+<para>
+translated by Samuel Butler
+</para>
+
+<para>
+June, 2000  [Etext #2199]
+</para>
+
+<para>
+********The Project Gutenberg Etext of The Iliad, by Homer******
+******This file should be named iliad10.txt or iliad10.zip******
+</para>
+
+<para>
+Corrected EDITIONS of our etexts get a new NUMBER, iliad11.txt
+VERSIONS based on separate sources get new LETTER, iliad10a.txt
+</para>
+
+<para>
+Project Gutenberg Etexts are usually created from multiple editions,
+all of which are in the Public Domain in the United States, unless a
+copyright notice is included.  Therefore, we do NOT keep these books
+in compliance with any particular paper edition, usually otherwise.
+</para>
+
+<para>
+We are now trying to release all our books one month in advance
+of the official release dates, for time for better editing.
+</para>
+
+<para>
+Please note:  neither this list nor its contents are final till
+midnight of the last day of the month of any such announcement.
+The official release date of all Project Gutenberg Etexts is at
+Midnight, Central Time, of the last day of the stated month.  A
+preliminary version may often be posted for suggestion, comment
+and editing by those who wish to do so.  To be sure you have an
+up to date first edition [xxxxx10x.xxx] please check file sizes
+in the first week of the next month.  Since our ftp program has
+a bug in it that scrambles the date [tried to fix and failed] a
+look at the file size will have to do, but we will try to see a
+new copy has at least one byte more or less.
+</para>
+
+<para>
+Information about Project Gutenberg (one page)
+</para>
+
+<para>
+We produce about two million dollars for each hour we work.  The
+fifty hours is one conservative estimate for how long it we take
+to get any etext selected, entered, proofread, edited, copyright
+searched and analyzed, the copyright letters written, etc.  This
+projected audience is one hundred million readers.  If our value
+per text is nominally estimated at one dollar then we produce $2
+million dollars per hour this year as we release thirty-two text
+files per month, or 384 more Etexts in 1998 for a total of 1500+
+If these reach just 10% of the computerized population, then the
+total should reach over 150 billion Etexts given away.
+</para>
+
+<para>
+The Goal of Project Gutenberg is to Give Away One Trillion Etext
+Files by the December 31, 2001.  [10,000 x 100,000,000=Trillion]
+This is ten thousand titles each to one hundred million readers,
+which is only 10% of the present number of computer users.  2001
+should have at least twice as many computer users as that, so it
+will require us reaching less than 5% of the users in 2001.
+</para>
+
+<para>
+We need your donations more than ever!
+</para>
+
+<para>
+All donations should be made to "Project Gutenberg/CMU": and are
+tax deductible to the extent allowable by law.  (CMU = Carnegie-
+Mellon University).
+</para>
+
+<para>
+For these and other matters, please mail to:
+</para>
+
+<para>
+Project Gutenberg
+P. O. Box  2782
+Champaign, IL 61825
+</para>
+
+<para>
+When all other email fails try our Executive Director:
+Michael S. Hart hart@pobox.com
+</para>
+
+<para>
+We would prefer to send you this information by email
+(Internet, Bitnet, Compuserve, ATTMAIL or MCImail).
+</para>
+
+<para>
+******
+If you have an FTP program (or emulator), please
+FTP directly to the Project Gutenberg archives:
+[Mac users, do NOT point and click. . .type]
+</para>
+
+<para>
+ftp uiarchive.cso.uiuc.edu
+login:  anonymous
+password:  your@login
+cd etext/etext90 through /etext96
+or cd etext/articles [get suggest gut for more information]
+dir [to see files]
+get or mget [to get files. . .set bin for zip files]
+GET INDEX?00.GUT
+for a list of books
+and
+GET NEW GUT for general information
+and
+MGET GUT* for newsletters.
+</para>
+
+<para>
+**Information prepared by the Project Gutenberg legal advisor**
+(Three Pages)
+</para>
+
+<para>
+***START**THE SMALL PRINT!**FOR PUBLIC DOMAIN ETEXTS**START***
+Why is this "Small Print!" statement here?  You know: lawyers.
+They tell us you might sue us if there is something wrong with
+your copy of this etext, even if you got it for free from
+someone other than us, and even if what's wrong is not our
+fault.  So, among other things, this "Small Print!" statement
+disclaims most of our liability to you.  It also tells you how
+you can distribute copies of this etext if you want to.
+</para>
+
+<para>
+*BEFORE!* YOU USE OR READ THIS ETEXT
+By using or reading any part of this PROJECT GUTENBERG-tm
+etext, you indicate that you understand, agree to and accept
+this "Small Print!" statement.  If you do not, you can receive
+a refund of the money (if any) you paid for this etext by
+sending a request within 30 days of receiving it to the person
+you got it from.  If you received this etext on a physical
+medium (such as a disk), you must return it with your request.
+</para>
+
+<para>
+ABOUT PROJECT GUTENBERG-TM ETEXTS
+This PROJECT GUTENBERG-tm etext, like most PROJECT GUTENBERG-
+tm etexts, is a "public domain" work distributed by Professor
+Michael S. Hart through the Project Gutenberg Association at
+Carnegie-Mellon University (the "Project").  Among other
+things, this means that no one owns a United States copyright
+on or for this work, so the Project (and you!) can copy and
+distribute it in the United States without permission and
+without paying copyright royalties.  Special rules, set forth
+below, apply if you wish to copy and distribute this etext
+under the Project's "PROJECT GUTENBERG" trademark.
+</para>
+
+<para>
+To create these etexts, the Project expends considerable
+efforts to identify, transcribe and proofread public domain
+works.  Despite these efforts, the Project's etexts and any
+medium they may be on may contain "Defects".  Among other
+things, Defects may take the form of incomplete, inaccurate or
+corrupt data, transcription errors, a copyright or other
+intellectual property infringement, a defective or damaged
+disk or other etext medium, a computer virus, or computer
+codes that damage or cannot be read by your equipment.
+</para>
+
+<para>
+LIMITED WARRANTY; DISCLAIMER OF DAMAGES
+But for the "Right of Replacement or Refund" described below,
+[1] the Project (and any other party you may receive this
+etext from as a PROJECT GUTENBERG-tm etext) disclaims all
+liability to you for damages, costs and expenses, including
+legal fees, and [2] YOU HAVE NO REMEDIES FOR NEGLIGENCE OR
+UNDER STRICT LIABILITY, OR FOR BREACH OF WARRANTY OR CONTRACT,
+INCLUDING BUT NOT LIMITED TO INDIRECT, CONSEQUENTIAL, PUNITIVE
+OR INCIDENTAL DAMAGES, EVEN IF YOU GIVE NOTICE OF THE
+POSSIBILITY OF SUCH DAMAGES.
+</para>
+
+<para>
+If you discover a Defect in this etext within 90 days of
+receiving it, you can receive a refund of the money (if any)
+you paid for it by sending an explanatory note within that
+time to the person you received it from.  If you received it
+on a physical medium, you must return it with your note, and
+such person may choose to alternatively give you a replacement
+copy.  If you received it electronically, such person may
+choose to alternatively give you a second opportunity to
+receive it electronically.
+</para>
+
+<para>
+THIS ETEXT IS OTHERWISE PROVIDED TO YOU "AS-IS".  NO OTHER
+WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, ARE MADE TO YOU AS
+TO THE ETEXT OR ANY MEDIUM IT MAY BE ON, INCLUDING BUT NOT
+LIMITED TO WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
+PARTICULAR PURPOSE.
+</para>
+
+<para>
+Some states do not allow disclaimers of implied warranties or
+the exclusion or limitation of consequential damages, so the
+above disclaimers and exclusions may not apply to you, and you
+may have other legal rights.
+</para>
+
+<para>
+INDEMNITY
+You will indemnify and hold the Project, its directors,
+officers, members and agents harmless from all liability, cost
+and expense, including legal fees, that arise directly or
+indirectly from any of the following that you do or cause:
+[1] distribution of this etext, [2] alteration, modification,
+or addition to the etext, or [3] any Defect.
+</para>
+
+<para>
+DISTRIBUTION UNDER "PROJECT GUTENBERG-tm"
+You may distribute copies of this etext electronically, or by
+disk, book or any other medium if you either delete this
+"Small Print!" and all other references to Project Gutenberg,
+or:
+</para>
+
+<para>
+[1]  Only give exact copies of it.  Among other things, this
+     requires that you do not remove, alter or modify the
+     etext or this "small print!" statement.  You may however,
+     if you wish, distribute this etext in machine readable
+     binary, compressed, mark-up, or proprietary form,
+     including any form resulting from conversion by word pro-
+     cessing or hypertext software, but only so long as
+     *EITHER*:
+</para>
+
+<para>
+     [*]  The etext, when displayed, is clearly readable, and
+          does *not* contain characters other than those
+          intended by the author of the work, although tilde
+          (~), asterisk (*) and underline (_) characters may
+          be used to convey punctuation intended by the
+          author, and additional characters may be used to
+          indicate hypertext links; OR
+</para>
+
+<para>
+     [*]  The etext may be readily converted by the reader at
+          no expense into plain ASCII, EBCDIC or equivalent
+          form by the program that displays the etext (as is
+          the case, for instance, with most word processors);
+          OR
+</para>
+
+<para>
+     [*]  You provide, or agree to also provide on request at
+          no additional cost, fee or expense, a copy of the
+          etext in its original plain ASCII form (or in EBCDIC
+          or other equivalent proprietary form).
+</para>
+
+<para>
+[2]  Honor the etext refund and replacement provisions of this
+     "Small Print!" statement.
+</para>
+
+<para>
+[3]  Pay a trademark license fee to the Project of 20% of the
+     net profits you derive calculated using the method you
+     already use to calculate your applicable taxes.  If you
+     don't derive profits, no royalty is due.  Royalties are
+     payable to "Project Gutenberg Association/Carnegie-Mellon
+     University" within the 60 days following each
+     date you prepare (or were legally required to prepare)
+     your annual (or equivalent periodic) tax return.
+</para>
+
+<para>
+WHAT IF YOU *WANT* TO SEND MONEY EVEN IF YOU DON'T HAVE TO?
+The Project gratefully accepts contributions in money, time,
+scanning machines, OCR software, public domain etexts, royalty
+free copyright licenses, and every other sort of contribution
+you can think of.  Money should be paid to "Project Gutenberg
+Association / Carnegie-Mellon University".
+</para>
+
+<para>
+*END*THE SMALL PRINT! FOR PUBLIC DOMAIN ETEXTS*Ver.04.29.93*END*
+</para>
+</gutblurb>
+
+<markupblurb>
+Marked up by Mark Stradling Feb 2000
+Validated against gutbook1.dtd using Mozilla M13 Feb 2000
+</markupblurb>
+
+<book>
+<acknowledge>
+A project of the HTML Writrs Guild and Project Gutenberg. Markup by Mark Stradling Feb 2000
+</acknowledge>
+<frontmatter>
+<titlepage>
+<title>THE ILIAD</title>
+<para> by</para>
+<author>HOMER</author>
+<para>
+Rendered into English Prose for
+the use of those who cannot
+read the original
+</para>
+
+<para>
+by Samuel Butler
+</para>
+</titlepage>
+</frontmatter>
+<bookbody>
+<chapter>
+<title>BOOK I</title>
+
+<para>
+Sing, O goddess, the anger of Achilles son of Peleus, that
+brought countless ills upon the Achaeans. Many a brave soul did
+it send hurrying down to Hades, and many a hero did it yield a
+prey to dogs and vultures, for so were the counsels of Jove
+fulfilled from the day on which the son of Atreus, king of men,
+and great Achilles, first fell out with one another.
+</para>
+
+<para>
+And which of the gods was it that set them on to quarrel? It was
+the son of Jove and Leto; for he was angry with the king and sent
+a pestilence upon the host to plague the people, because the son
+of Atreus had dishonoured Chryses his priest. Now Chryses had
+come to the ships of the Achaeans to free his daughter, and had
+brought with him a great ransom: moreover he bore in his hand the
+sceptre of Apollo wreathed with a suppliant's wreath, and he
+besought the Achaeans, but most of all the two sons of Atreus,
+who were their chiefs.
+</para>
+
+<para>
+"Sons of Atreus," he cried, "and all other Achaeans, may the gods
+who dwell in Olympus grant you to sack the city of Priam, and to
+reach your homes in safety; but free my daughter, and accept a
+ransom for her, in reverence to Apollo, son of Jove."
+</para>
+
+<para>
+On this the rest of the Achaeans with one voice were for
+respecting the priest and taking the ransom that he offered; but
+not so Agamemnon, who spoke fiercely to him and sent him roughly
+away. "Old man," said he, "let me not find you tarrying about our
+ships, nor yet coming hereafter. Your sceptre of the god and your
+wreath shall profit you nothing. I will not free her. She shall
+grow old in my house at Argos far from her own home, busying
+herself with her loom and visiting my couch; so go, and do not
+provoke me or it shall be the worse for you."
+</para>
+
+<para>
+The old man feared him and obeyed. Not a word he spoke, but went
+by the shore of the sounding sea and prayed apart to King Apollo
+whom lovely Leto had borne. "Hear me," he cried, "O god of the
+silver bow, that protectest Chryse and holy Cilla and rulest
+Tenedos with thy might, hear me oh thou of Sminthe. If I have
+ever decked your temple with garlands, or burned your thigh-bones
+in fat of bulls or goats, grant my prayer, and let your arrows
+avenge these my tears upon the Danaans."
+</para>
+
+<para>
+Thus did he pray, and Apollo heard his prayer. He came down
+furious from the summits of Olympus, with his bow and his quiver
+upon his shoulder, and the arrows rattled on his back with the
+rage that trembled within him. He sat himself down away from the
+ships with a face as dark as night, and his silver bow rang death
+as he shot his arrow in the midst of them. First he smote their
+mules and their hounds, but presently he aimed his shafts at the
+people themselves, and all day long the pyres of the dead were
+burning.
+</para>
+
+<para>
+For nine whole days he shot his arrows among the people, but upon
+the tenth day Achilles called them in assembly--moved thereto by
+Juno, who saw the Achaeans in their death-throes and had
+compassion upon them. Then, when they were got together, he rose
+and spoke among them.
+</para>
+
+<para>
+"Son of Atreus," said he, "I deem that we should now turn roving
+home if we would escape destruction, for we are being cut down by
+war and pestilence at once. Let us ask some priest or prophet, or
+some reader of dreams (for dreams, too, are of Jove) who can tell
+us why Phoebus Apollo is so angry, and say whether it is for some
+vow that we have broken, or hecatomb that we have not offered,
+and whether he will accept the savour of lambs and goats without
+blemish, so as to take away the plague from us."
+</para>
+
+<para>
+With these words he sat down, and Calchas son of Thestor, wisest
+of augurs, who knew things past present and to come, rose to
+speak. He it was who had guided the Achaeans with their fleet to
+Ilius, through the prophesyings with which Phoebus Apollo had
+inspired him. With all sincerity and goodwill he addressed them
+thus:--
+</para>
+
+<para>
+"Achilles, loved of heaven, you bid me tell you about the anger
+of King Apollo, I will therefore do so; but consider first and
+swear that you will stand by me heartily in word and deed, for I
+know that I shall offend one who rules the Argives with might, to
+whom all the Achaeans are in subjection. A plain man cannot stand
+against the anger of a king, who if he swallow his displeasure
+now, will yet nurse revenge till he has wreaked it. Consider,
+therefore, whether or no you will protect me."
+</para>
+
+<para>
+And Achilles answered, "Fear not, but speak as it is borne in
+upon you from heaven, for by Apollo, Calchas, to whom you pray,
+and whose oracles you reveal to us, not a Danaan at our ships
+shall lay his hand upon you, while I yet live to look upon the
+face of the earth--no, not though you name Agamemnon himself, who
+is by far the foremost of the Achaeans."
+</para>
+
+<para>
+Thereon the seer spoke boldly. "The god," he said, "is angry
+neither about vow nor hecatomb, but for his priest's sake, whom
+Agamemnon has dishonoured, in that he would not free his daughter
+nor take a ransom for her; therefore has he sent these evils upon
+us, and will yet send others. He will not deliver the Danaans
+from this pestilence till Agamemnon has restored the girl without
+fee or ransom to her father, and has sent a holy hecatomb to
+Chryse. Thus we may perhaps appease him."
+</para>
+
+<para>
+With these words he sat down, and Agamemnon rose in anger. His
+heart was black with rage, and his eyes flashed fire as he
+scowled on Calchas and said, "Seer of evil, you never yet
+prophesied smooth things concerning me, but have ever loved to
+foretell that which was evil. You have brought me neither comfort
+nor performance; and now you come seeing among Danaans, and
+saying that Apollo has plagued us because I would not take a
+ransom for this girl, the daughter of Chryses. I have set my
+heart on keeping her in my own house, for I love her better even
+than my own wife Clytemnestra, whose peer she is alike in form
+and feature, in understanding and accomplishments. Still I will
+give her up if I must, for I would have the people live, not die;
+but you must find me a prize instead, or I alone among the
+Argives shall be without one. This is not well; for you behold,
+all of you, that my prize is to go elsewhither."
+</para>
+
+<para>
+And Achilles answered, "Most noble son of Atreus, covetous beyond
+all mankind, how shall the Achaeans find you another prize? We
+have no common store from which to take one. Those we took from
+the cities have been awarded; we cannot disallow the awards that
+have been made already. Give this girl, therefore, to the god,
+and if ever Jove grants us to sack the city of Troy we will
+requite you three and fourfold."
+</para>
+
+<para>
+Then Agamemnon said, "Achilles, valiant though you be, you shall
+not thus outwit me. You shall not overreach and you shall not
+persuade me. Are you to keep your own prize, while I sit tamely
+under my loss and give up the girl at your bidding? Let the
+Achaeans find me a prize in fair exchange to my liking, or I will
+come and take your own, or that of Ajax or of Ulysses; and he to
+whomsoever I may come shall rue my coming. But of this we will
+take thought hereafter; for the present, let us draw a ship into
+the sea, and find a crew for her expressly; let us put a hecatomb
+on board, and let us send Chryseis also; further, let some chief
+man among us be in command, either Ajax, or Idomeneus, or
+yourself, son of Peleus, mighty warrior that you are, that we may
+offer sacrifice and appease the the anger of the god."
+</para>
+
+<para>
+Achilles scowled at him and answered, "You are steeped in
+insolence and lust of gain. With what heart can any of the
+Achaeans do your bidding, either on foray or in open fighting? I
+came not warring here for any ill the Trojans had done me. I have
+no quarrel with them. They have not raided my cattle nor my
+horses, nor cut down my harvests on the rich plains of Phthia;
+for between me and them there is a great space, both mountain and
+sounding sea. We have followed you, Sir Insolence! for your
+pleasure, not ours--to gain satisfaction from the Trojans for
+your shameless self and for Menelaus. You forget this, and
+threaten to rob me of the prize for which I have toiled, and
+which the sons of the Achaeans have given me. Never when the
+Achaeans sack any rich city of the Trojans do I receive so good a
+prize as you do, though it is my hands that do the better part of
+the fighting. When the sharing comes, your share is far the
+largest, and I, forsooth, must go back to my ships, take what I
+can get and be thankful, when my labour of fighting is done. Now,
+therefore, I shall go back to Phthia; it will be much better for
+me to return home with my ships, for I will not stay here
+dishonoured to gather gold and substance for you."
+</para>
+
+<para>
+And Agamemnon answered, "Fly if you will, I shall make you no
+prayers to stay you. I have others here who will do me honour,
+and above all Jove, the lord of counsel. There is no king here so
+hateful to me as you are, for you are ever quarrelsome and ill-
+affected. What though you be brave? Was it not heaven that made
+you so? Go home, then, with your ships and comrades to lord it
+over the Myrmidons. I care neither for you nor for your anger;
+and thus will I do: since Phoebus Apollo is taking Chryseis from
+me, I shall send her with my ship and my followers, but I shall
+come to your tent and take your own prize Briseis, that you may
+learn how much stronger I am than you are, and that another may
+fear to set himself up as equal or comparable with me."
+</para>
+
+<para>
+The son of Peleus was furious, and his heart within his shaggy
+breast was divided whether to draw his sword, push the others
+aside, and kill the son of Atreus, or to restrain himself and
+check his anger. While he was thus in two minds, and was drawing
+his mighty sword from its scabbard, Minerva came down from heaven
+(for Juno had sent her in the love she bore to them both), and
+seized the son of Peleus by his yellow hair, visible to him
+alone, for of the others no man could see her. Achilles turned in
+amaze, and by the fire that flashed from her eyes at once knew
+that she was Minerva. "Why are you here," said he, "daughter of
+aegis-bearing Jove? To see the pride of Agamemnon, son of Atreus?
+Let me tell you--and it shall surely be--he shall pay for this
+insolence with his life."
+</para>
+
+<para>
+And Minerva said, "I come from heaven, if you will hear me, to
+bid you stay your anger. Juno has sent me, who cares for both of
+you alike. Cease, then, this brawling, and do not draw your
+sword; rail at him if you will, and your railing will not be
+vain, for I tell you--and it shall surely be--that you shall
+hereafter receive gifts three times as splendid by reason of this
+present insult. Hold, therefore, and obey."
+</para>
+
+<para>
+"Goddess," answered Achilles, "however angry a man may be, he
+must do as you two command him. This will be best, for the gods
+ever hear the prayers of him who has obeyed them."
+</para>
+
+<para>
+He stayed his hand on the silver hilt of his sword, and thrust it
+back into the scabbard as Minerva bade him. Then she went back to
+Olympus among the other gods, and to the house of aegis-bearing
+Jove.
+</para>
+
+<para>
+But the son of Peleus again began railing at the son of Atreus,
+for he was still in a rage. "Wine-bibber," he cried, "with the
+face of a dog and the heart of a hind, you never dare to go out
+with the host in fight, nor yet with our chosen men in ambuscade.
+You shun this as you do death itself. You had rather go round and
+rob his prizes from any man who contradicts you. You devour your
+people, for you are king over a feeble folk; otherwise, son of
+Atreus, henceforward you would insult no man. Therefore I say,
+and swear it with a great oath--nay, by this my sceptre which
+shalt sprout neither leaf nor shoot, nor bud anew from the day on
+which it left its parent stem upon the mountains--for the axe
+stripped it of leaf and bark, and now the sons of the Achaeans
+bear it as judges and guardians of the decrees of heaven--so
+surely and solemnly do I swear that hereafter they shall look
+fondly for Achilles and shall not find him. In the day of your
+distress, when your men fall dying by the murderous hand of
+Hector, you shall not know how to help them, and shall rend your
+heart with rage for the hour when you offered insult to the
+bravest of the Achaeans."
+</para>
+
+<para>
+With this the son of Peleus dashed his gold-bestudded sceptre on
+the ground and took his seat, while the son of Atreus was
+beginning fiercely from his place upon the other side. Then
+uprose smooth-tongued Nestor, the facile speaker of the Pylians,
+and the words fell from his lips sweeter than honey. Two
+generations of men born and bred in Pylos had passed away under
+his rule, and he was now reigning over the third. With all
+sincerity and goodwill, therefore, he addressed them thus:--
+</para>
+
+<para>
+"Of a truth," he said, "a great sorrow has befallen the Achaean
+land. Surely Priam with his sons would rejoice, and the Trojans
+be glad at heart if they could hear this quarrel between you two,
+who are so excellent in fight and counsel. I am older than either
+of you; therefore be guided by me. Moreover I have been the
+familiar friend of men even greater than you are, and they did
+not disregard my counsels. Never again can I behold such men as
+Pirithous and Dryas shepherd of his people, or as Caeneus,
+Exadius, godlike Polyphemus, and Theseus son of Aegeus, peer of
+the immortals. These were the mightiest men ever born upon this
+earth: mightiest were they, and when they fought the fiercest
+tribes of mountain savages they utterly overthrew them. I came
+from distant Pylos, and went about among them, for they would
+have me come, and I fought as it was in me to do. Not a man now
+living could withstand them, but they heard my words, and were
+persuaded by them. So be it also with yourselves, for this is the
+more excellent way. Therefore, Agamemnon, though you be strong,
+take not this girl away, for the sons of the Achaeans have
+already given her to Achilles; and you, Achilles, strive not
+further with the king, for no man who by the grace of Jove wields
+a sceptre has like honour with Agamemnon. You are strong, and
+have a goddess for your mother; but Agamemnon is stronger than
+you, for he has more people under him. Son of Atreus, check your
+anger, I implore you; end this quarrel with Achilles, who in the
+day of battle is a tower of strength to the Achaeans."
+</para>
+
+<para>
+And Agamemnon answered, "Sir, all that you have said is true, but
+this fellow must needs become our lord and master: he must be
+lord of all, king of all, and captain of all, and this shall
+hardly be. Granted that the gods have made him a great warrior,
+have they also given him the right to speak with railing?"
+</para>
+
+<para>
+Achilles interrupted him. "I should be a mean coward," he cried,
+"were I to give in to you in all things. Order other people
+about, not me, for I shall obey no longer. Furthermore I say--and
+lay my saying to your heart--I shall fight neither you nor any
+man about this girl, for those that take were those also that
+gave. But of all else that is at my ship you shall carry away
+nothing by force. Try, that others may see; if you do, my spear
+shall be reddened with your blood."
+</para>
+
+<para>
+When they had quarrelled thus angrily, they rose, and broke up
+the assembly at the ships of the Achaeans. The son of Peleus went
+back to his tents and ships with the son of Menoetius and his
+company, while Agamemnon drew a vessel into the water and chose a
+crew of twenty oarsmen. He escorted Chryseis on board and sent
+moreover a hecatomb for the god. And Ulysses went as captain.
+</para>
+
+<para>
+These, then, went on board and sailed their ways over the sea.
+But the son of Atreus bade the people purify themselves; so they
+purified themselves and cast their filth into the sea. Then they
+offered hecatombs of bulls and goats without blemish on the
+sea-shore, and the smoke with the savour of their sacrifice rose
+curling up towards heaven.
+</para>
+
+<para>
+Thus did they busy themselves throughout the host. But Agamemnon
+did not forget the threat that he had made Achilles, and called
+his trusty messengers and squires Talthybius and Eurybates. "Go,"
+said he, "to the tent of Achilles, son of Peleus; take Briseis by
+the hand and bring her hither; if he will not give her I shall
+come with others and take her--which will press him harder."
+</para>
+
+<para>
+He charged them straightly further and dismissed them, whereon
+they went their way sorrowfully by the seaside, till they came to
+the tents and ships of the Myrmidons. They found Achilles sitting
+by his tent and his ships, and ill-pleased he was when he beheld
+them. They stood fearfully and reverently before him, and never a
+word did they speak, but he knew them and said, "Welcome,
+heralds, messengers of gods and men; draw near; my quarrel is not
+with you but with Agamemnon who has sent you for the girl
+Briseis. Therefore, Patroclus, bring her and give her to them,
+but let them be witnesses by the blessed gods, by mortal men, and
+by the fierceness of Agamemnon's anger, that if ever again there
+be need of me to save the people from ruin, they shall seek and
+they shall not find. Agamemnon is mad with rage and knows not how
+to look before and after that the Achaeans may fight by their
+ships in safety."
+</para>
+
+<para>
+Patroclus did as his dear comrade had bidden him. He brought
+Briseis from the tent and gave her over to the heralds, who took
+her with them to the ships of the Achaeans--and the woman was
+loth to go. Then Achilles went all alone by the side of the hoar
+sea, weeping and looking out upon the boundless waste of waters.
+He raised his hands in prayer to his immortal mother, "Mother,"
+he cried, "you bore me doomed to live but for a little season;
+surely Jove, who thunders from Olympus, might have made that
+little glorious. It is not so. Agamemnon, son of Atreus, has done
+me dishonour, and has robbed me of my prize by force."
+</para>
+
+<para>
+As he spoke he wept aloud, and his mother heard him where she was
+sitting in the depths of the sea hard by the old man her father.
+Forthwith she rose as it were a grey mist out of the waves, sat
+down before him as he stood weeping, caressed him with her hand,
+and said, "My son, why are you weeping? What is it that grieves
+you? Keep it not from me, but tell me, that we may know it
+together."
+</para>
+
+<para>
+Achilles drew a deep sigh and said, "You know it; why tell you
+what you know well already? We went to Thebe the strong city of
+Eetion, sacked it, and brought hither the spoil. The sons of the
+Achaeans shared it duly among themselves, and chose lovely
+Chryseis as the meed of Agamemnon; but Chryses, priest of Apollo,
+came to the ships of the Achaeans to free his daughter, and
+brought with him a great ransom: moreover he bore in his hand the
+sceptre of Apollo, wreathed with a suppliant's wreath, and he
+besought the Achaeans, but most of all the two sons of Atreus who
+were their chiefs.
+</para>
+
+<para>
+"On this the rest of the Achaeans with one voice were for
+respecting the priest and taking the ransom that he offered; but
+not so Agamemnon, who spoke fiercely to him and sent him roughly
+away. So he went back in anger, and Apollo, who loved him dearly,
+heard his prayer. Then the god sent a deadly dart upon the
+Argives, and the people died thick on one another, for the arrows
+went everywhither among the wide host of the Achaeans. At last a
+seer in the fulness of his knowledge declared to us the oracles
+of Apollo, and I was myself first to say that we should appease
+him. Whereon the son of Atreus rose in anger, and threatened that
+which he has since done. The Achaeans are now taking the girl in
+a ship to Chryse, and sending gifts of sacrifice to the god; but
+the heralds have just taken from my tent the daughter of Briseus,
+whom the Achaeans had awarded to myself.
+</para>
+
+<para>
+"Help your brave son, therefore, if you are able. Go to Olympus,
+and if you have ever done him service in word or deed, implore
+the aid of Jove. Ofttimes in my father's house have I heard you
+glory in that you alone of the immortals saved the son of Saturn
+from ruin, when the others, with Juno, Neptune, and Pallas
+Minerva would have put him in bonds. It was you, goddess, who
+delivered him by calling to Olympus the hundred-handed monster
+whom gods call Briareus, but men Aegaeon, for he is stronger even
+than his father; when therefore he took his seat all-glorious
+beside the son of Saturn, the other gods were afraid, and did not
+bind him. Go, then, to him, remind him of all this, clasp his
+knees, and bid him give succour to the Trojans. Let the Achaeans
+be hemmed in at the sterns of their ships, and perish on the
+sea-shore, that they may reap what joy they may of their king,
+and that Agamemnon may rue his blindness in offering insult to
+the foremost of the Achaeans."
+</para>
+
+<para>
+Thetis wept and answered, "My son, woe is me that I should have
+borne or suckled you. Would indeed that you had lived your span
+free from all sorrow at your ships, for it is all too brief;
+alas, that you should be at once short of life and long of sorrow
+above your peers: woe, therefore, was the hour in which I bore
+you; nevertheless I will go to the snowy heights of Olympus, and
+tell this tale to Jove, if he will hear our prayer: meanwhile
+stay where you are with your ships, nurse your anger against the
+Achaeans, and hold aloof from fight. For Jove went yesterday to
+Oceanus, to a feast among the Ethiopians, and the other gods went
+with him. He will return to Olympus twelve days hence; I will
+then go to his mansion paved with bronze and will beseech him;
+nor do I doubt that I shall be able to persuade him."
+</para>
+
+<para>
+On this she left him, still furious at the loss of her that had
+been taken from him. Meanwhile Ulysses reached Chryse with the
+hecatomb. When they had come inside the harbour they furled the
+sails and laid them in the ship's hold; they slackened the
+forestays, lowered the mast into its place, and rowed the ship to
+the place where they would have her lie; there they cast out
+their mooring-stones and made fast the hawsers. They then got out
+upon the sea-shore and landed the hecatomb for Apollo; Chryseis
+also left the ship, and Ulysses led her to the altar to deliver
+her into the hands of her father. "Chryses," said he, "King
+Agamemnon has sent me to bring you back your child, and to offer
+sacrifice to Apollo on behalf of the Danaans, that we may
+propitiate the god, who has now brought sorrow upon the Argives."
+</para>
+
+<para>
+So saying he gave the girl over to her father, who received her
+gladly, and they ranged the holy hecatomb all orderly round the
+altar of the god. They washed their hands and took up the
+barley-meal to sprinkle over the victims, while Chryses lifted up
+his hands and prayed aloud on their behalf. "Hear me," he cried,
+"O god of the silver bow, that protectest Chryse and holy Cilla,
+and rulest Tenedos with thy might. Even as thou didst hear me
+aforetime when I prayed, and didst press hardly upon the
+Achaeans, so hear me yet again, and stay this fearful pestilence
+from the Danaans."
+</para>
+
+<para>
+Thus did he pray, and Apollo heard his prayer. When they had done
+praying and sprinkling the barley-meal, they drew back the heads
+of the victims and killed and flayed them. They cut out the
+thigh-bones, wrapped them round in two layers of fat, set some
+pieces of raw meat on the top of them, and then Chryses laid them
+on the wood fire and poured wine over them, while the young men
+stood near him with five-pronged spits in their hands. When the
+thigh-bones were burned and they had tasted the inward meats,
+they cut the rest up small, put the pieces upon the spits,
+roasted them till they were done, and drew them off: then, when
+they had finished their work and the feast was ready, they ate
+it, and every man had his full share, so that all were satisfied.
+As soon as they had had enough to eat and drink, pages filled the
+mixing-bowl with wine and water and handed it round, after giving
+every man his drink-offering.
+</para>
+
+<para>
+Thus all day long the young men worshipped the god with song,
+hymning him and chaunting the joyous paean, and the god took
+pleasure in their voices; but when the sun went down, and it came
+on dark, they laid themselves down to sleep by the stern cables
+of the ship, and when the child of morning, rosy-fingered Dawn,
+appeared they again set sail for the host of the Achaeans. Apollo
+sent them a fair wind, so they raised their mast and hoisted
+their white sails aloft. As the sail bellied with the wind the
+ship flew through the deep blue water, and the foam hissed
+against her bows as she sped onward. When they reached the
+wide-stretching host of the Achaeans, they drew the vessel
+ashore, high and dry upon the sands, set her strong props beneath
+her, and went their ways to their own tents and ships.
+</para>
+
+<para>
+But Achilles abode at his ships and nursed his anger. He went not
+to the honourable assembly, and sallied not forth to fight, but
+gnawed at his own heart, pining for battle and the war-cry.
+</para>
+
+<para>
+Now after twelve days the immortal gods came back in a body to
+Olympus, and Jove led the way. Thetis was not unmindful of the
+charge her son had laid upon her, so she rose from under the sea
+and went through great heaven with early morning to Olympus,
+where she found the mighty son of Saturn sitting all alone upon
+its topmost ridges. She sat herself down before him, and with her
+left hand seized his knees, while with her right she caught him
+under the chin, and besought him, saying:--
+</para>
+
+<para>
+"Father Jove, if I ever did you service in word or deed among the
+immortals, hear my prayer, and do honour to my son, whose life is
+to be cut short so early. King Agamemnon has dishonoured him by
+taking his prize and keeping her. Honour him then yourself,
+Olympian lord of counsel, and grant victory to the Trojans, till
+the Achaeans give my son his due and load him with riches in
+requital."
+</para>
+
+<para>
+Jove sat for a while silent, and without a word, but Thetis still
+kept firm hold of his knees, and besought him a second time.
+"Incline your head," said she, "and promise me surely, or else
+deny me--for you have nothing to fear--that I may learn how
+greatly you disdain me."
+</para>
+
+<para>
+At this Jove was much troubled and answered, "I shall have
+trouble if you set me quarrelling with Juno, for she will provoke
+me with her taunting speeches; even now she is always railing at
+me before the other gods and accusing me of giving aid to the
+Trojans. Go back now, lest she should find out. I will consider
+the matter, and will bring it about as you wish. See, I incline
+my head that you may believe me. This is the most solemn promise
+that I can give to any god. I never recall my word, or deceive,
+or fail to do what I say, when I have nodded my head."
+</para>
+
+<para>
+As he spoke the son of Saturn bowed his dark brows, and the
+ambrosial locks swayed on his immortal head, till vast Olympus
+reeled.
+</para>
+
+<para>
+When the pair had thus laid their plans, they parted--Jove to his
+house, while the goddess quitted the splendour of Olympus, and
+plunged into the depths of the sea. The gods rose from their
+seats, before the coming of their sire. Not one of them dared to
+remain sitting, but all stood up as he came among them. There,
+then, he took his seat. But Juno, when she saw him, knew that he
+and the old merman's daughter, silver-footed Thetis, had been
+hatching mischief, so she at once began to upbraid him.
+"Trickster," she cried, "which of the gods have you been taking
+into your counsels now? You are always settling matters in secret
+behind my back, and have never yet told me, if you could help it,
+one word of your intentions."
+</para>
+
+<para>
+"Juno," replied the sire of gods and men, "you must not expect to
+be informed of all my counsels. You are my wife, but you would
+find it hard to understand them. When it is proper for you to
+hear, there is no one, god or man, who will be told sooner, but
+when I mean to keep a matter to myself, you must not pry nor ask
+questions."
+</para>
+
+<para>
+"Dread son of Saturn," answered Juno, "what are you talking
+about? I? Pry and ask questions? Never. I let you have your own
+way in everything. Still, I have a strong misgiving that the old
+merman's daughter Thetis has been talking you over, for she was
+with you and had hold of your knees this self-same morning. I
+believe, therefore, that you have been promising her to give
+glory to Achilles, and to kill much people at the ships of the
+Achaeans."
+</para>
+
+<para>
+"Wife," said Jove, "I can do nothing but you suspect me and find
+it out. You will take nothing by it, for I shall only dislike you
+the more, and it will go harder with you. Granted that it is as
+you say; I mean to have it so; sit down and hold your tongue as I
+bid you for if I once begin to lay my hands about you, though all
+heaven were on your side it would profit you nothing."
+</para>
+
+<para>
+On this Juno was frightened, so she curbed her stubborn will and
+sat down in silence. But the heavenly beings were disquieted
+throughout the house of Jove, till the cunning workman Vulcan
+began to try and pacify his mother Juno. "It will be
+intolerable," said he, "if you two fall to wrangling and setting
+heaven in an uproar about a pack of mortals. If such ill counsels
+are to prevail, we shall have no pleasure at our banquet. Let me
+then advise my mother--and she must herself know that it will be
+better--to make friends with my dear father Jove, lest he again
+scold her and disturb our feast. If the Olympian Thunderer wants
+to hurl us all from our seats, he can do so, for he is far the
+strongest, so give him fair words, and he will then soon be in a
+good humour with us."
+</para>
+
+<para>
+As he spoke, he took a double cup of nectar, and placed it in his
+mother's hand. "Cheer up, my dear mother," said he, "and make the
+best of it. I love you dearly, and should be very sorry to see
+you get a thrashing; however grieved I might be, I could not help,
+for there is no standing against Jove. Once before when I was
+trying to help you, he caught me by the foot and flung me from
+the heavenly threshold. All day long from morn till eve, was I
+falling, till at sunset I came to ground in the island of Lemnos,
+and there I lay, with very little life left in me, till the
+Sintians came and tended me."
+</para>
+
+<para>
+Juno smiled at this, and as she smiled she took the cup from her
+son's hands. Then Vulcan drew sweet nectar from the mixing-bowl,
+and served it round among the gods, going from left to right; and
+the blessed gods laughed out a loud applause as they saw him
+bustling about the heavenly mansion.
+</para>
+
+<para>
+Thus through the livelong day to the going down of the sun they
+feasted, and every one had his full share, so that all were
+satisfied. Apollo struck his lyre, and the Muses lifted up their
+sweet voices, calling and answering one another. But when the
+sun's glorious light had faded, they went home to bed, each in
+his own abode, which lame Vulcan with his consummate skill had
+fashioned for them. So Jove, the Olympian Lord of Thunder, hied
+him to the bed in which he always slept; and when he had got on
+to it he went to sleep, with Juno of the golden throne by his
+side.
+</para>
+</chapter>
+
+<chapter>
+<title>BOOK II</title>
+
+<para>
+Now the other gods and the armed warriors on the plain slept
+soundly, but Jove was wakeful, for he was thinking how to do
+honour to Achilles, and destroyed much people at the ships of the
+Achaeans. In the end he deemed it would be best to send a lying
+dream to King Agamemnon; so he called one to him and said to it,
+"Lying Dream, go to the ships of the Achaeans, into the tent of
+Agamemnon, and say to him word for word as I now bid you. Tell
+him to get the Achaeans instantly under arms, for he shall take
+Troy. There are no longer divided counsels among the gods; Juno
+has brought them to her own mind, and woe betides the Trojans."
+</para>
+
+<para>
+The dream went when it had heard its message, and soon reached
+the ships of the Achaeans. It sought Agamemnon son of Atreus and
+found him in his tent, wrapped in a profound slumber. It hovered
+over his head in the likeness of Nestor, son of Neleus, whom
+Agamemnon honoured above all his councillors, and said:--
+</para>
+
+<para>
+"You are sleeping, son of Atreus; one who has the welfare of his
+host and so much other care upon his shoulders should dock his
+sleep. Hear me at once, for I come as a messenger from Jove, who,
+though he be not near, yet takes thought for you and pities you.
+He bids you get the Achaeans instantly under arms, for you shall
+take Troy. There are no longer divided counsels among the gods;
+Juno has brought them over to her own mind, and woe betides the
+Trojans at the hands of Jove. Remember this, and when you wake
+see that it does not escape you."
+</para>
+
+<para>
+The dream then left him, and he thought of things that were,
+surely not to be accomplished. He thought that on that same day
+he was to take the city of Priam, but he little knew what was in
+the mind of Jove, who had many another hard-fought fight in store
+alike for Danaans and Trojans. Then presently he woke, with the
+divine message still ringing in his ears; so he sat upright, and
+put on his soft shirt so fair and new, and over this his heavy
+cloak. He bound his sandals on to his comely feet, and slung his
+silver-studded sword about his shoulders; then he took the
+imperishable staff of his father, and sallied forth to the ships
+of the Achaeans.
+</para>
+
+<para>
+The goddess Dawn now wended her way to vast Olympus that she
+might herald day to Jove and to the other immortals, and
+Agamemnon sent the criers round to call the people in assembly;
+so they called them and the people gathered thereon. But first he
+summoned a meeting of the elders at the ship of Nestor king of
+Pylos, and when they were assembled he laid a cunning counsel
+before them.
+</para>
+
+<para>
+"My friends," said he, "I have had a dream from heaven in the
+dead of night, and its face and figure resembled none but
+Nestor's. It hovered over my head and said, 'You are sleeping,
+son of Atreus; one who has the welfare of his host and so much
+other care upon his shoulders should dock his sleep. Hear me at
+once, for I am a messenger from Jove, who, though he be not near,
+yet takes thought for you and pities you. He bids you get the
+Achaeans instantly under arms, for you shall take Troy. There are
+no longer divided counsels among the gods; Juno has brought them
+over to her own mind, and woe betides the Trojans at the hands of
+Jove. Remember this.' The dream then vanished and I awoke. Let us
+now, therefore, arm the sons of the Achaeans. But it will be well
+that I should first sound them, and to this end I will tell them
+to fly with their ships; but do you others go about among the
+host and prevent their doing so."
+</para>
+
+<para>
+He then sat down, and Nestor the prince of Pylos with all
+sincerity and goodwill addressed them thus: "My friends," said
+he, "princes and councillors of the Argives, if any other man of
+the Achaeans had told us of this dream we should have declared it
+false, and would have had nothing to do with it. But he who has
+seen it is the foremost man among us; we must therefore set about
+getting the people under arms."
+</para>
+
+<para>
+With this he led the way from the assembly, and the other
+sceptred kings rose with him in obedience to the word of
+Agamemnon; but the people pressed forward to hear. They swarmed
+like bees that sally from some hollow cave and flit in countless
+throng among the spring flowers, bunched in knots and clusters;
+even so did the mighty multitude pour from ships and tents to the
+assembly, and range themselves upon the wide-watered shore, while
+among them ran Wildfire Rumour, messenger of Jove, urging them
+ever to the fore. Thus they gathered in a pell-mell of mad
+confusion, and the earth groaned under the tramp of men as the
+people sought their places. Nine heralds went crying about among
+them to stay their tumult and bid them listen to the kings, till
+at last they were got into their several places and ceased their
+clamour. Then King Agamemnon rose, holding his sceptre. This was
+the work of Vulcan, who gave it to Jove the son of Saturn. Jove
+gave it to Mercury, slayer of Argus, guide and guardian. King
+Mercury gave it to Pelops, the mighty charioteer, and Pelops to
+Atreus, shepherd of his people. Atreus, when he died, left it to
+Thyestes, rich in flocks, and Thyestes in his turn left it to be
+borne by Agamemnon, that he might be lord of all Argos and of the
+isles. Leaning, then, on his sceptre, he addressed the Argives.
+</para>
+
+<para>
+"My friends," he said, "heroes, servants of Mars, the hand of
+heaven has been laid heavily upon me. Cruel Jove gave me his
+solemn promise that I should sack the city of Priam before
+returning, but he has played me false, and is now bidding me go
+ingloriously back to Argos with the loss of much people. Such is
+the will of Jove, who has laid many a proud city in the dust, as
+he will yet lay others, for his power is above all. It will be a
+sorry tale hereafter that an Achaean host, at once so great and
+valiant, battled in vain against men fewer in number than
+themselves; but as yet the end is not in sight. Think that the
+Achaeans and Trojans have sworn to a solemn covenant, and that
+they have each been numbered--the Trojans by the roll of their
+householders, and we by companies of ten; think further that each
+of our companies desired to have a Trojan householder to pour out
+their wine; we are so greatly more in number that full many a
+company would have to go without its cup-bearer. But they have in
+the town allies from other places, and it is these that hinder me
+from being able to sack the rich city of Ilius. Nine of Jove's
+years are gone; the timbers of our ships have rotted; their
+tackling is sound no longer. Our wives and little ones at home
+look anxiously for our coming, but the work that we came hither
+to do has not been done. Now, therefore, let us all do as I say:
+let us sail back to our own land, for we shall not take Troy."
+</para>
+
+<para>
+With these words he moved the hearts of the multitude, so many of
+them as knew not the cunning counsel of Agamemnon. They surged to
+and fro like the waves of the Icarian Sea, when the east and
+south winds break from heaven's clouds to lash them; or as when
+the west wind sweeps over a field of corn and the ears bow
+beneath the blast, even so were they swayed as they flew with
+loud cries towards the ships, and the dust from under their feet
+rose heavenward. They cheered each other on to draw the ships
+into the sea; they cleared the channels in front of them; they
+began taking away the stays from underneath them, and the welkin
+rang with their glad cries, so eager were they to return.
+</para>
+
+<para>
+Then surely the Argives would have returned after a fashion that
+was not fated. But Juno said to Minerva, "Alas, daughter of
+aegis-bearing Jove, unweariable, shall the Argives fly home to
+their own land over the broad sea, and leave Priam and the
+Trojans the glory of still keeping Helen, for whose sake so many
+of the Achaeans have died at Troy, far from their homes? Go about
+at once among the host, and speak fairly to them, man by man,
+that they draw not their ships into the sea."
+</para>
+
+<para>
+Minerva was not slack to do her bidding. Down she darted from the
+topmost summits of Olympus, and in a moment she was at the ships
+of the Achaeans. There she found Ulysses, peer of Jove in
+counsel, standing alone. He had not as yet laid a hand upon his
+ship, for he was grieved and sorry; so she went close up to him
+and said, "Ulysses, noble son of Laertes, are you going to fling
+yourselves into your ships and be off home to your own land in
+this way? Will you leave Priam and the Trojans the glory of still
+keeping Helen, for whose sake so many of the Achaeans have died
+at Troy, far from their homes? Go about at once among the host,
+and speak fairly to them, man by man, that they draw not their
+ships into the sea."
+</para>
+
+<para>
+Ulysses knew the voice as that of the goddess: he flung his cloak
+from him and set off to run. His servant Eurybates, a man of
+Ithaca, who waited on him, took charge of the cloak, whereon
+Ulysses went straight up to Agamemnon and received from him his
+ancestral, imperishable staff. With this he went about among the
+ships of the Achaeans.
+</para>
+
+<para>
+Whenever he met a king or chieftain, he stood by him and spoke
+him fairly. "Sir," said he, "this flight is cowardly and
+unworthy. Stand to your post, and bid your people also keep their
+places. You do not yet know the full mind of Agamemnon; he was
+sounding us, and ere long will visit the Achaeans with his
+displeasure. We were not all of us at the council to hear what he
+then said; see to it lest he be angry and do us a mischief; for
+the pride of kings is great, and the hand of Jove is with them."
+</para>
+
+<para>
+But when he came across any common man who was making a noise, he
+struck him with his staff and rebuked him, saying, "Sirrah, hold
+your peace, and listen to better men than yourself. You are a
+coward and no soldier; you are nobody either in fight or council;
+we cannot all be kings; it is not well that there should be many
+masters; one man must be supreme--one king to whom the son of
+scheming Saturn has given the sceptre of sovereignty over you
+all."
+</para>
+
+<para>
+Thus masterfully did he go about among the host, and the people
+hurried back to the council from their tents and ships with a
+sound as the thunder of surf when it comes crashing down upon the
+shore, and all the sea is in an uproar.
+</para>
+
+<para>
+The rest now took their seats and kept to their own several
+places, but Thersites still went on wagging his unbridled
+tongue--a man of many words, and those unseemly; a monger of
+sedition, a railer against all who were in authority, who cared
+not what he said, so that he might set the Achaeans in a laugh.
+He was the ugliest man of all those that came before
+Troy--bandy-legged, lame of one foot, with his two shoulders
+rounded and hunched over his chest. His head ran up to a point,
+but there was little hair on the top of it. Achilles and Ulysses
+hated him worst of all, for it was with them that he was most
+wont to wrangle; now, however, with a shrill squeaky voice he
+began heaping his abuse on Agamemnon. The Achaeans were angry and
+disgusted, yet none the less he kept on brawling and bawling at
+the son of Atreus.
+</para>
+
+<para>
+"Agamemnon," he cried, "what ails you now, and what more do you
+want? Your tents are filled with bronze and with fair women, for
+whenever we take a town we give you the pick of them. Would you
+have yet more gold, which some Trojan is to give you as a ransom
+for his son, when I or another Achaean has taken him prisoner? or
+is it some young girl to hide and lie with? It is not well that
+you, the ruler of the Achaeans, should bring them into such
+misery. Weakling cowards, women rather than men, let us sail
+home, and leave this fellow here at Troy to stew in his own meeds
+of honour, and discover whether we were of any service to him or
+no. Achilles is a much better man than he is, and see how he has
+treated him--robbing him of his prize and keeping it himself.
+Achilles takes it meekly and shows no fight; if he did, son of
+Atreus, you would never again insult him."
+</para>
+
+<para>
+Thus railed Thersites, but Ulysses at once went up to him and
+rebuked him sternly. "Check your glib tongue, Thersites," said
+be, "and babble not a word further. Chide not with princes when
+you have none to back you. There is no viler creature come before
+Troy with the sons of Atreus. Drop this chatter about kings, and
+neither revile them nor keep harping about going home. We do not
+yet know how things are going to be, nor whether the Achaeans are
+to return with good success or evil. How dare you gibe at
+Agamemnon because the Danaans have awarded him so many prizes? I
+tell you, therefore--and it shall surely be--that if I again
+catch you talking such nonsense, I will either forfeit my own
+head and be no more called father of Telemachus, or I will take
+you, strip you stark naked, and whip you out of the assembly till
+you go blubbering back to the ships."
+</para>
+
+<para>
+On this he beat him with his staff about the back and shoulders
+till he dropped and fell a-weeping. The golden sceptre raised a
+bloody weal on his back, so he sat down frightened and in pain,
+looking foolish as he wiped the tears from his eyes. The people
+were sorry for him, yet they laughed heartily, and one would turn
+to his neighbour saying, "Ulysses has done many a good thing ere
+now in fight and council, but he never did the Argives a better
+turn than when he stopped this fellow's mouth from prating
+further. He will give the kings no more of his insolence."
+</para>
+
+<para>
+Thus said the people. Then Ulysses rose, sceptre in hand, and
+Minerva in the likeness of a herald bade the people be still,
+that those who were far off might hear him and consider his
+council. He therefore with all sincerity and goodwill addressed
+them thus:--
+</para>
+
+<para>
+"King Agamemnon, the Achaeans are for making you a by-word among
+all mankind. They forget the promise they made you when they set
+out from Argos, that you should not return till you had sacked
+the town of Troy, and, like children or widowed women, they
+murmur and would set off homeward. True it is that they have had
+toil enough to be disheartened. A man chafes at having to stay
+away from his wife even for a single month, when he is on
+shipboard, at the mercy of wind and sea, but it is now nine long
+years that we have been kept here; I cannot, therefore, blame the
+Achaeans if they turn restive; still we shall be shamed if we go
+home empty after so long a stay--therefore, my friends, be
+patient yet a little longer that we may learn whether the
+prophesyings of Calchas were false or true.
+</para>
+
+<para>
+"All who have not since perished must remember as though it were
+yesterday or the day before, how the ships of the Achaeans were
+detained in Aulis when we were on our way hither to make war on
+Priam and the Trojans. We were ranged round about a fountain
+offering hecatombs to the gods upon their holy altars, and there
+was a fine plane-tree from beneath which there welled a stream of
+pure water. Then we saw a prodigy; for Jove sent a fearful
+serpent out of the ground, with blood-red stains upon its back,
+and it darted from under the altar on to the plane-tree. Now
+there was a brood of young sparrows, quite small, upon the
+topmost bough, peeping out from under the leaves, eight in all,
+and their mother that hatched them made nine. The serpent ate the
+poor cheeping things, while the old bird flew about lamenting her
+little ones; but the serpent threw his coils about her and caught
+her by the wing as she was screaming. Then, when he had eaten
+both the sparrow and her young, the god who had sent him made him
+become a sign; for the son of scheming Saturn turned him into
+stone, and we stood there wondering at that which had come to
+pass. Seeing, then, that such a fearful portent had broken in
+upon our hecatombs, Calchas forthwith declared to us the oracles
+of heaven. 'Why, Achaeans,' said he, 'are you thus speechless?
+Jove has sent us this sign, long in coming, and long ere it be
+fulfilled, though its fame shall last for ever. As the serpent
+ate the eight fledglings and the sparrow that hatched them, which
+makes nine, so shall we fight nine years at Troy, but in the
+tenth shall take the town.' This was what he said, and now it is
+all coming true. Stay here, therefore, all of you, till we take
+the city of Priam."
+</para>
+
+<para>
+On this the Argives raised a shout, till the ships rang again
+with the uproar. Nestor, knight of Gerene, then addressed them.
+"Shame on you," he cried, "to stay talking here like children,
+when you should fight like men. Where are our covenants now, and
+where the oaths that we have taken? Shall our counsels be flung
+into the fire, with our drink-offerings and the right hands of
+fellowship wherein we have put our trust? We waste our time in
+words, and for all our talking here shall be no further forward.
+Stand, therefore, son of Atreus, by your own steadfast purpose;
+lead the Argives on to battle, and leave this handful of men to
+rot, who scheme, and scheme in vain, to get back to Argos ere
+they have learned whether Jove be true or a liar. For the mighty
+son of Saturn surely promised that we should succeed, when we
+Argives set sail to bring death and destruction upon the Trojans.
+He showed us favourable signs by flashing his lightning on our
+right hands; therefore let none make haste to go till he has
+first lain with the wife of some Trojan, and avenged the toil and
+sorrow that he has suffered for the sake of Helen. Nevertheless,
+if any man is in such haste to be at home again, let him lay his
+hand to his ship that he may meet his doom in the sight of all.
+But, O king, consider and give ear to my counsel, for the word
+that I say may not be neglected lightly. Divide your men,
+Agamemnon, into their several tribes and clans, that clans and
+tribes may stand by and help one another. If you do this, and if
+the Achaeans obey you, you will find out who, both chiefs and
+peoples, are brave, and who are cowards; for they will vie
+against the other. Thus you shall also learn whether it is
+through the counsel of heaven or the cowardice of man that you
+shall fail to take the town."
+</para>
+
+<para>
+And Agamemnon answered, "Nestor, you have again outdone the sons
+of the Achaeans in counsel. Would, by Father Jove, Minerva, and
+Apollo, that I had among them ten more such councillors, for the
+city of King Priam would then soon fall beneath our hands, and we
+should sack it. But the son of Saturn afflicts me with bootless
+wranglings and strife. Achilles and I are quarrelling about this
+girl, in which matter I was the first to offend; if we can be of
+one mind again, the Trojans will not stave off destruction for a
+day. Now, therefore, get your morning meal, that our hosts join
+in fight. Whet well your spears; see well to the ordering of your
+shields; give good feeds to your horses, and look your chariots
+carefully over, that we may do battle the livelong day; for we
+shall have no rest, not for a moment, till night falls to part
+us. The bands that bear your shields shall be wet with the sweat
+upon your shoulders, your hands shall weary upon your spears,
+your horses shall steam in front of your chariots, and if I see
+any man shirking the fight, or trying to keep out of it at the
+ships, there shall be no help for him, but he shall be a prey to
+dogs and vultures."
+</para>
+
+<para>
+Thus he spoke, and the Achaeans roared applause. As when the
+waves run high before the blast of the south wind and break on
+some lofty headland, dashing against it and buffeting it without
+ceasing, as the storms from every quarter drive them, even so did
+the Achaeans rise and hurry in all directions to their ships.
+There they lighted their fires at their tents and got dinner,
+offering sacrifice every man to one or other of the gods, and
+praying each one of them that he might live to come out of the
+fight. Agamemnon, king of men, sacrificed a fat five-year-old
+bull to the mighty son of Saturn, and invited the princes and
+elders of his host. First he asked Nestor and King Idomeneus,
+then the two Ajaxes and the son of Tydeus, and sixthly Ulysses,
+peer of gods in counsel; but Menelaus came of his own accord, for
+he knew how busy his brother then was. They stood round the bull
+with the barley-meal in their hands, and Agamemnon prayed,
+saying, "Jove, most glorious, supreme, that dwellest in heaven,
+and ridest upon the storm-cloud, grant that the sun may not go
+down, nor the night fall, till the palace of Priam is laid low,
+and its gates are consumed with fire. Grant that my sword may
+pierce the shirt of Hector about his heart, and that full many of
+his comrades may bite the dust as they fall dying round him."
+</para>
+
+<para>
+Thus he prayed, but the son of Saturn would not fulfil his
+prayer. He accepted the sacrifice, yet none the less increased
+their toil continually. When they had done praying and sprinkling
+the barley-meal upon the victim, they drew back its head, killed
+it, and then flayed it. They cut out the thigh-bones, wrapped
+them round in two layers of fat, and set pieces of raw meat on
+the top of them. These they burned upon the split logs of
+firewood, but they spitted the inward meats, and held them in the
+flames to cook. When the thigh-bones were burned, and they had
+tasted the inward meats, they cut the rest up small, put the
+pieces upon spits, roasted them till they were done, and drew
+them off; then, when they had finished their work and the feast
+was ready, they ate it, and every man had his full share, so that
+all were satisfied. As soon as they had had enough to eat and
+drink, Nestor, knight of Gerene, began to speak. "King
+Agamemnon," said he, "let us not stay talking here, nor be slack
+in the work that heaven has put into our hands. Let the heralds
+summon the people to gather at their several ships; we will then
+go about among the host, that we may begin fighting at once."
+</para>
+
+<para>
+Thus did he speak, and Agamemnon heeded his words. He at once
+sent the criers round to call the people in assembly. So they
+called them, and the people gathered thereon. The chiefs about
+the son of Atreus chose their men and marshalled them, while
+Minerva went among them holding her priceless aegis that knows
+neither age nor death. From it there waved a hundred tassels of
+pure gold, all deftly woven, and each one of them worth a hundred
+oxen. With this she darted furiously everywhere among the hosts
+of the Achaeans, urging them forward, and putting courage into
+the heart of each, so that he might fight and do battle without
+ceasing. Thus war became sweeter in their eyes even than
+returning home in their ships. As when some great forest fire is
+raging upon a mountain top and its light is seen afar, even so as
+they marched the gleam of their armour flashed up into the
+firmament of heaven.
+</para>
+
+<para>
+They were like great flocks of geese, or cranes, or swans on the
+plain about the waters of Cayster, that wing their way hither and
+thither, glorying in the pride of flight, and crying as they
+settle till the fen is alive with their screaming. Even thus did
+their tribes pour from ships and tents on to the plain of the
+Scamander, and the ground rang as brass under the feet of men and
+horses. They stood as thick upon the flower-bespangled field as
+leaves that bloom in summer.
+</para>
+
+<para>
+As countless swarms of flies buzz around a herdsman's homestead
+in the time of spring when the pails are drenched with milk, even
+so did the Achaeans swarm on to the plain to charge the Trojans
+and destroy them.
+</para>
+
+<para>
+The chiefs disposed their men this way and that before the fight
+began, drafting them out as easily as goatherds draft their
+flocks when they have got mixed while feeding; and among them
+went King Agamemnon, with a head and face like Jove the lord of
+thunder, a waist like Mars, and a chest like that of Neptune. As
+some great bull that lords it over the herds upon the plain, even
+so did Jove make the son of Atreus stand peerless among the
+multitude of heroes.
+</para>
+
+<para>
+And now, O Muses, dwellers in the mansions of Olympus, tell me--
+for you are goddesses and are in all places so that you see all
+things, while we know nothing but by report--who were the chiefs
+and princes of the Danaans? As for the common soldiers, they were
+so that I could not name every single one of them though I had
+ten tongues, and though my voice failed not and my heart were of
+bronze within me, unless you, O Olympian Muses, daughters of
+aegis-bearing Jove, were to recount them to me. Nevertheless, I
+will tell the captains of the ships and all the fleet together.
+</para>
+
+<para>
+Peneleos, Leitus, Arcesilaus, Prothoenor, and Clonius were
+captains of the Boeotians. These were they that dwelt in Hyria
+and rocky Aulis, and who held Schoenus, Scolus, and the highlands
+of Eteonus, with Thespeia, Graia, and the fair city of
+Mycalessus. They also held Harma, Eilesium, and Erythrae; and
+they had Eleon, Hyle, and Peteon; Ocalea and the strong fortress
+of Medeon; Copae, Eutresis, and Thisbe the haunt of doves;
+Coronea, and the pastures of Haliartus; Plataea and Glisas; the
+fortress of Thebes the less; holy Onchestus with its famous grove
+of Neptune; Arne rich in vineyards; Midea, sacred Nisa, and
+Anthedon upon the sea. From these there came fifty ships, and in
+each there were a hundred and twenty young men of the Boeotians.
+</para>
+
+<para>
+Ascalaphus and Ialmenus, sons of Mars, led the people that dwelt
+in Aspledon and Orchomenus the realm of Minyas. Astyoche a noble
+maiden bore them in the house of Actor son of Azeus; for she had
+gone with Mars secretly into an upper chamber, and he had lain
+with her. With these there came thirty ships.
+</para>
+
+<para>
+The Phoceans were led by Schedius and Epistrophus, sons of mighty
+Iphitus the son of Naubolus. These were they that held
+Cyparissus, rocky Pytho, holy Crisa, Daulis, and Panopeus; they
+also that dwelt in Anemorea and Hyampolis, and about the waters
+of the river Cephissus, and Lilaea by the springs of the
+Cephissus; with their chieftains came forty ships, and they
+marshalled the forces of the Phoceans, which were stationed next
+to the Boeotians, on their left.
+</para>
+
+<para>
+Ajax, the fleet son of Oileus, commanded the Locrians. He was not
+so great, nor nearly so great, as Ajax the son of Telamon. He was
+a little man, and his breastplate was made of linen, but in use
+of the spear he excelled all the Hellenes and the Achaeans.
+These dwelt in Cynus, Opous, Calliarus, Bessa, Scarphe, fair
+Augeae, Tarphe, and Thronium about the river Boagrius. With him
+there came forty ships of the Locrians who dwell beyond Euboea.
+</para>
+
+<para>
+The fierce Abantes held Euboea with its cities, Chalcis, Eretria,
+Histiaea rich in vines, Cerinthus upon the sea, and the
+rock-perched town of Dium; with them were also the men of
+Carystus and Styra; Elephenor of the race of Mars was in command
+of these; he was son of Chalcodon, and chief over all the
+Abantes. With him they came, fleet of foot and wearing their hair
+long behind, brave warriors, who would ever strive to tear open
+the corslets of their foes with their long ashen spears. Of these
+there came fifty ships.
+</para>
+
+<para>
+And they that held the strong city of Athens, the people of great
+Erechtheus, who was born of the soil itself, but Jove's daughter,
+Minerva, fostered him, and established him at Athens in her own
+rich sanctuary. There, year by year, the Athenian youths worship
+him with sacrifices of bulls and rams. These were commanded by
+Menestheus, son of Peteos. No man living could equal him in the
+marshalling of chariots and foot soldiers. Nestor could alone
+rival him, for he was older. With him there came fifty ships.
+</para>
+
+<para>
+Ajax brought twelve ships from Salamis, and stationed them
+alongside those of the Athenians.
+</para>
+
+<para>
+The men of Argos, again, and those who held the walls of Tiryns,
+with Hermione, and Asine upon the gulf; Troezene, Eionae, and the
+vineyard lands of Epidaurus; the Achaean youths, moreover, who
+came from Aegina and Mases; these were led by Diomed of the loud
+battle-cry, and Sthenelus son of famed Capaneus. With them in
+command was Euryalus, son of king Mecisteus, son of Talaus; but
+Diomed was chief over them all. With these there came eighty
+ships.
+</para>
+
+<para>
+Those who held the strong city of Mycenae, rich Corinth and
+Cleonae; Orneae, Araethyrea, and Licyon, where Adrastus reigned
+of old; Hyperesia, high Gonoessa, and Pellene; Aegium and all the
+coast-land round about Helice; these sent a hundred ships under
+the command of King Agamemnon, son of Atreus. His force was far
+both finest and most numerous, and in their midst was the king
+himself, all glorious in his armour of gleaming bronze--foremost
+among the heroes, for he was the greatest king, and had most men
+under him.
+</para>
+
+<para>
+And those that dwelt in Lacedaemon, lying low among the hills,
+Pharis, Sparta, with Messe the haunt of doves; Bryseae, Augeae,
+Amyclae, and Helos upon the sea; Laas, moreover, and Oetylus;
+these were led by Menelaus of the loud battle-cry, brother to
+Agamemnon, and of them there were sixty ships, drawn up apart
+from the others. Among them went Menelaus himself, strong in
+zeal, urging his men to fight; for he longed to avenge the toil
+and sorrow that he had suffered for the sake of Helen.
+</para>
+
+<para>
+The men of Pylos and Arene, and Thryum where is the ford of the
+river Alpheus; strong Aipy, Cyparisseis, and Amphigenea; Pteleum,
+Helos, and Dorium, where the Muses met Thamyris, and stilled his
+minstrelsy for ever. He was returning from Oechalia, where
+Eurytus lived and reigned, and boasted that he would surpass even
+the Muses, daughters of aegis-bearing Jove, if they should sing
+against him; whereon they were angry, and maimed him. They robbed
+him of his divine power of song, and thenceforth he could strike
+the lyre no more. These were commanded by Nestor, knight of
+Gerene, and with him there came ninety ships.
+</para>
+
+<para>
+And those that held Arcadia, under the high mountain of Cyllene,
+near the tomb of Aepytus, where the people fight hand to hand;
+the men of Pheneus also, and Orchomenus rich in flocks; of
+Rhipae, Stratie, and bleak Enispe; of Tegea and fair Mantinea; of
+Stymphelus and Parrhasia; of these King Agapenor son of Ancaeus
+was commander, and they had sixty ships. Many Arcadians, good
+soldiers, came in each one of them, but Agamemnon found them the
+ships in which to cross the sea, for they were not a people that
+occupied their business upon the waters.
+</para>
+
+<para>
+The men, moreover, of Buprasium and of Elis, so much of it as is
+enclosed between Hyrmine, Myrsinus upon the sea-shore, the rock
+Olene and Alesium. These had four leaders, and each of them had
+ten ships, with many Epeans on board. Their captains were
+Amphimachus and Thalpius--the one, son of Cteatus, and the other,
+of Eurytus--both of the race of Actor. The two others were
+Diores, son of Amarynces, and Polyxenus, son of King Agasthenes,
+son of Augeas.
+</para>
+
+<para>
+And those of Dulichium with the sacred Echinean islands, who
+dwelt beyond the sea off Elis; these were led by Meges, peer of
+Mars, and the son of valiant Phyleus, dear to Jove, who
+quarrelled with his father, and went to settle in Dulichium. With
+him there came forty ships.
+</para>
+
+<para>
+Ulysses led the brave Cephallenians, who held Ithaca, Neritum
+with its forests, Crocylea, rugged Aegilips, Samos and Zacynthus,
+with the mainland also that was over against the islands. These
+were led by Ulysses, peer of Jove in counsel, and with him there
+came twelve ships.
+</para>
+
+<para>
+Thoas, son of Andraemon, commanded the Aetolians, who dwelt in
+Pleuron, Olenus, Pylene, Chalcis by the sea, and rocky Calydon,
+for the great king Oeneus had now no sons living, and was himself
+dead, as was also golden-haired Meleager, who had been set over
+the Aetolians to be their king. And with Thoas there came forty
+ships.
+</para>
+
+<para>
+The famous spearsman Idomeneus led the Cretans, who held Cnossus,
+and the well-walled city of Gortys; Lyctus also, Miletus and
+Lycastus that lies upon the chalk; the populous towns of Phaestus
+and Rhytium, with the other peoples that dwelt in the hundred
+cities of Crete. All these were led by Idomeneus, and by
+Meriones, peer of murderous Mars. And with these there came
+eighty ships.
+</para>
+
+<para>
+Tlepolemus, son of Hercules, a man both brave and large of
+stature, brought nine ships of lordly warriors from Rhodes. These
+dwelt in Rhodes which is divided among the three cities of
+Lindus, Ielysus, and Cameirus, that lies upon the chalk. These
+were commanded by Tlepolemus, son of Hercules by Astyochea, whom
+he had carried off from Ephyra, on the river Selleis, after
+sacking many cities of valiant warriors. When Tlepolemus grew up,
+he killed his father's uncle Licymnius, who had been a famous
+warrior in his time, but was then grown old. On this he built
+himself a fleet, gathered a great following, and fled beyond the
+sea, for he was menaced by the other sons and grandsons of
+Hercules. After a voyage, during which he suffered great
+hardship, he came to Rhodes, where the people divided into three
+communities, according to their tribes, and were dearly loved by
+Jove, the lord of gods and men; wherefore the son of Saturn
+showered down great riches upon them.
+</para>
+
+<para>
+And Nireus brought three ships from Syme--Nireus, who was the
+handsomest man that came up under Ilius of all the Danaans after
+the son of Peleus--but he was a man of no substance, and had but
+a small following.
+</para>
+
+<para>
+And those that held Nisyrus, Crapathus, and Casus, with Cos, the
+city of Eurypylus, and the Calydnian islands, these were
+commanded by Pheidippus and Antiphus, two sons of King Thessalus
+the son of Hercules. And with them there came thirty ships.
+</para>
+
+<para>
+Those again who held Pelasgic Argos, Alos, Alope, and Trachis;
+and those of Phthia and Hellas the land of fair women, who were
+called Myrmidons, Hellenes, and Achaeans; these had fifty ships,
+over which Achilles was in command. But they now took no part in
+the war, inasmuch as there was no one to marshal them; for
+Achilles stayed by his ships, furious about the loss of the girl
+Briseis, whom he had taken from Lyrnessus at his own great peril,
+when he had sacked Lyrnessus and Thebe, and had overthrown Mynes
+and Epistrophus, sons of king Evenor, son of Selepus. For her
+sake Achilles was still grieving, but ere long he was again to
+join them.
+</para>
+
+<para>
+And those that held Phylace and the flowery meadows of Pyrasus,
+sanctuary of Ceres; Iton, the mother of sheep; Antrum upon the
+sea, and Pteleum that lies upon the grass lands. Of these brave
+Protesilaus had been captain while he was yet alive, but he was
+now lying under the earth. He had left a wife behind him in
+Phylace to tear her cheeks in sorrow, and his house was only half
+finished, for he was slain by a Dardanian warrior while leaping
+foremost of the Achaeans upon the soil of Troy. Still, though his
+people mourned their chieftain, they were not without a leader,
+for Podarces, of the race of Mars, marshalled them; he was son of
+Iphiclus, rich in sheep, who was the son of Phylacus, and he was
+own brother to Protesilaus, only younger, Protesilaus being at
+once the elder and the more valiant. So the people were not
+without a leader, though they mourned him whom they had lost.
+With him there came forty ships.
+</para>
+
+<para>
+And those that held Pherae by the Boebean lake, with Boebe,
+Glaphyrae, and the populous city of Iolcus, these with their
+eleven ships were led by Eumelus, son of Admetus, whom Alcestis
+bore to him, loveliest of the daughters of Pelias.
+</para>
+
+<para>
+And those that held Methone and Thaumacia, with Meliboea and
+rugged Olizon, these were led by the skilful archer Philoctetes,
+and they had seven ships, each with fifty oarsmen all of them
+good archers; but Philoctetes was lying in great pain in the
+Island of Lemnos, where the sons of the Achaeans left him, for he
+had been bitten by a poisonous water snake. There he lay sick and
+sorry, and full soon did the Argives come to miss him. But his
+people, though they felt his loss were not leaderless, for Medon,
+the bastard son of Oileus by Rhene, set them in array.
+</para>
+
+<para>
+Those, again, of Tricca and the stony region of Ithome, and they
+that held Oechalia, the city of Oechalian Eurytus, these were
+commanded by the two sons of Aesculapius, skilled in the art of
+healing, Podalirius and Machaon. And with them there came thirty
+ships.
+</para>
+
+<para>
+The men, moreover, of Ormenius, and by the fountain of Hypereia,
+with those that held Asterius, and the white crests of Titanus,
+these were led by Eurypylus, the son of Euaemon, and with them
+there came forty ships.
+</para>
+
+<para>
+Those that held Argissa and Gyrtone, Orthe, Elone, and the white
+city of Oloosson, of these brave Polypoetes was leader. He was
+son of Pirithous, who was son of Jove himself, for Hippodameia
+bore him to Pirithous on the day when he took his revenge on the
+shaggy mountain savages and drove them from Mt. Pelion to the
+Aithices. But Polypoetes was not sole in command, for with him
+was Leonteus, of the race of Mars, who was son of Coronus, the
+son of Caeneus. And with these there came forty ships.
+</para>
+
+<para>
+Guneus brought two and twenty ships from Cyphus, and he was
+followed by the Enienes and the valiant Peraebi, who dwelt about
+wintry Dodona, and held the lands round the lovely river
+Titaresius, which sends its waters into the Peneus. They do not
+mingle with the silver eddies of the Peneus, but flow on the top
+of them like oil; for the Titaresius is a branch of dread Orcus
+and of the river Styx.
+</para>
+
+<para>
+Of the Magnetes, Prothous son of Tenthredon was commander. They
+were they that dwelt about the river Peneus and Mt. Pelion.
+Prothous, fleet of foot, was their leader, and with him there
+came forty ships.
+</para>
+
+<para>
+Such were the chiefs and princes of the Danaans. Who, then, O
+Muse, was the foremost, whether man or horse, among those that
+followed after the sons of Atreus?
+</para>
+
+<para>
+Of the horses, those of the son of Pheres were by far the finest.
+They were driven by Eumelus, and were as fleet as birds. They
+were of the same age and colour, and perfectly matched in height.
+Apollo, of the silver bow, had bred them in Perea--both of them
+mares, and terrible as Mars in battle. Of the men, Ajax, son of
+Telamon, was much the foremost so long as Achilles' anger lasted,
+for Achilles excelled him greatly and he had also better horses;
+but Achilles was now holding aloof at his ships by reason of his
+quarrel with Agamemnon, and his people passed their time upon the
+sea shore, throwing discs or aiming with spears at a mark, and in
+archery. Their horses stood each by his own chariot, champing
+lotus and wild celery. The chariots were housed under cover, but
+their owners, for lack of leadership, wandered hither and thither
+about the host and went not forth to fight.
+</para>
+
+<para>
+Thus marched the host like a consuming fire, and the earth
+groaned beneath them when the lord of thunder is angry and lashes
+the land about Typhoeus among the Arimi, where they say Typhoeus
+lies. Even so did the earth groan beneath them as they sped over
+the plain.
+</para>
+
+<para>
+And now Iris, fleet as the wind, was sent by Jove to tell the bad
+news among the Trojans. They were gathered in assembly, old and
+young, at Priam's gates, and Iris came close up to Priam,
+speaking with the voice of Priam's son Polites, who, being fleet
+of foot, was stationed as watchman for the Trojans on the tomb of
+old Aesyetes, to look out for any sally of the Achaeans. In his
+likeness Iris spoke, saying, "Old man, you talk idly, as in time
+of peace, while war is at hand. I have been in many a battle, but
+never yet saw such a host as is now advancing. They are crossing
+the plain to attack the city as thick as leaves or as the sands
+of the sea. Hector, I charge you above all others, do as I say.
+There are many allies dispersed about the city of Priam from
+distant places and speaking divers tongues. Therefore, let each
+chief give orders to his own people, setting them severally in
+array and leading them forth to battle."
+</para>
+
+<para>
+Thus she spoke, but Hector knew that it was the goddess, and at
+once broke up the assembly. The men flew to arms; all the gates
+were opened, and the people thronged through them, horse and
+foot, with the tramp as of a great multitude.
+</para>
+
+<para>
+Now there is a high mound before the city, rising by itself upon
+the plain. Men call it Batieia, but the gods know that it is the
+tomb of lithe Myrine. Here the Trojans and their allies divided
+their forces.
+</para>
+
+<para>
+Priam's son, great Hector of the gleaming helmet, commanded the
+Trojans, and with him were arrayed by far the greater number and
+most valiant of those who were longing for the fray.
+</para>
+
+<para>
+The Dardanians were led by brave Aeneas, whom Venus bore to
+Anchises, when she, goddess though she was, had lain with him
+upon the mountain slopes of Ida. He was not alone, for with him
+were the two sons of Antenor, Archilochus and Acamas, both
+skilled in all the arts of war.
+</para>
+
+<para>
+They that dwelt in Telea under the lowest spurs of Mt. Ida, men
+of substance, who drink the limpid waters of the Aesepus, and are
+of Trojan blood--these were led by Pandarus son of Lycaon, whom
+Apollo had taught to use the bow.
+</para>
+
+<para>
+They that held Adresteia and the land of Apaesus, with Pityeia,
+and the high mountain of Tereia--these were led by Adrestus and
+Amphius, whose breastplate was of linen. These were the sons of
+Merops of Percote, who excelled in all kinds of divination. He
+told them not to take part in the war, but they gave him no heed,
+for fate lured them to destruction.
+</para>
+
+<para>
+They that dwelt about Percote and Practius, with Sestos, Abydos,
+and Arisbe--these were led by Asius, son of Hyrtacus, a brave
+commander--Asius, the son of Hyrtacus, whom his powerful dark bay
+steeds, of the breed that comes from the river Selleis, had
+brought from Arisbe.
+</para>
+
+<para>
+Hippothous led the tribes of Pelasgian spearsmen, who dwelt in
+fertile Larissa--Hippothous, and Pylaeus of the race of Mars, two
+sons of the Pelasgian Lethus, son of Teutamus.
+</para>
+
+<para>
+Acamas and the warrior Peirous commanded the Thracians and those
+that came from beyond the mighty stream of the Hellespont.
+</para>
+
+<para>
+Euphemus, son of Troezenus, the son of Ceos, was captain of the
+Ciconian spearsmen.
+</para>
+
+<para>
+Pyraechmes led the Paeonian archers from distant Amydon, by the
+broad waters of the river Axius, the fairest that flow upon the
+earth.
+</para>
+
+<para>
+The Paphlagonians were commanded by stout-hearted Pylaemanes from
+Enetae, where the mules run wild in herds. These were they that
+held Cytorus and the country round Sesamus, with the cities by
+the river Parthenius, Cromna, Aegialus, and lofty Erithini.
+</para>
+
+<para>
+Odius and Epistrophus were captains over the Halizoni from
+distant Alybe, where there are mines of silver.
+</para>
+
+<para>
+Chromis, and Ennomus the augur, led the Mysians, but his skill in
+augury availed not to save him from destruction, for he fell by
+the hand of the fleet descendant of Aeacus in the river, where he
+slew others also of the Trojans.
+</para>
+
+<para>
+Phorcys, again, and noble Ascanius led the Phrygians from the far
+country of Ascania, and both were eager for the fray.
+</para>
+
+<para>
+Mesthles and Antiphus commanded the Meonians, sons of Talaemenes,
+born to him of the Gygaean lake. These led the Meonians, who
+dwelt under Mt. Tmolus.
+</para>
+
+<para>
+Nastes led the Carians, men of a strange speech. These held
+Miletus and the wooded mountain of Phthires, with the water of
+the river Maeander and the lofty crests of Mt. Mycale. These were
+commanded by Nastes and Amphimachus, the brave sons of Nomion. He
+came into the fight with gold about him, like a girl; fool that
+he was, his gold was of no avail to save him, for he fell in the
+river by the hand of the fleet descendant of Aeacus, and Achilles
+bore away his gold.
+</para>
+
+<para>
+Sarpedon and Glaucus led the Lycians from their distant land, by
+the eddying waters of the Xanthus.
+</para>
+</chapter>
+
+<chapter>
+<title>BOOK III</title>
+
+<para>
+When the companies were thus arrayed, each under its own captain,
+the Trojans advanced as a flight of wild fowl or cranes that
+scream overhead when rain and winter drive them over the flowing
+waters of Oceanus to bring death and destruction on the Pygmies,
+and they wrangle in the air as they fly; but the Achaeans marched
+silently, in high heart, and minded to stand by one another.
+</para>
+
+<para>
+As when the south wind spreads a curtain of mist upon the
+mountain tops, bad for shepherds but better than night for
+thieves, and a man can see no further than he can throw a stone,
+even so rose the dust from under their feet as they made all
+speed over the plain.
+</para>
+
+<para>
+When they were close up with one another, Alexandrus came forward
+as champion on the Trojan side. On his shoulders he bore the skin
+of a panther, his bow, and his sword, and he brandished two
+spears shod with bronze as a challenge to the bravest of the
+Achaeans to meet him in single fight. Menelaus saw him thus
+stride out before the ranks, and was glad as a hungry lion that
+lights on the carcase of some goat or horned stag, and devours it
+there and then, though dogs and youths set upon him. Even thus
+was Menelaus glad when his eyes caught sight of Alexandrus, for
+he deemed that now he should be revenged. He sprang, therefore,
+from his chariot, clad in his suit of armour.
+</para>
+
+<para>
+Alexandrus quailed as he saw Menelaus come forward, and shrank in
+fear of his life under cover of his men. As one who starts back
+affrighted, trembling and pale, when he comes suddenly upon a
+serpent in some mountain glade, even so did Alexandrus plunge
+into the throng of Trojan warriors, terror-stricken at the sight
+of the son of Atreus.
+</para>
+
+<para>
+Then Hector upbraided him. "Paris," said he, "evil-hearted Paris,
+fair to see, but woman-mad, and false of tongue, would that you
+had never been born, or that you had died unwed. Better so, than
+live to be disgraced and looked askance at. Will not the Achaeans
+mock at us and say that we have sent one to champion us who is
+fair to see but who has neither wit nor courage? Did you not,
+such as you are, get your following together and sail beyond the
+seas? Did you not from your a far country carry off a lovely
+woman wedded among a people of warriors--to bring sorrow upon
+your father, your city, and your whole country, but joy to your
+enemies, and hang-dog shamefacedness to yourself? And now can you
+not dare face Menelaus and learn what manner of man he is whose
+wife you have stolen? Where indeed would be your lyre and your
+love-tricks, your comely locks and your fair favour, when you
+were lying in the dust before him? The Trojans are a weak-kneed
+people, or ere this you would have had a shirt of stones for the
+wrongs you have done them."
+</para>
+
+<para>
+And Alexandrus answered, "Hector, your rebuke is just. You are
+hard as the axe which a shipwright wields at his work, and
+cleaves the timber to his liking. As the axe in his hand, so keen
+is the edge of your scorn. Still, taunt me not with the gifts
+that golden Venus has given me; they are precious; let not a man
+disdain them, for the gods give them where they are minded, and
+none can have them for the asking. If you would have me do battle
+with Menelaus, bid the Trojans and Achaeans take their seats,
+while he and I fight in their midst for Helen and all her wealth.
+Let him who shall be victorious and prove to be the better man
+take the woman and all she has, to bear them to his home, but let
+the rest swear to a solemn covenant of peace whereby you Trojans
+shall stay here in Troy, while the others go home to Argos and
+the land of the Achaeans."
+</para>
+
+<para>
+When Hector heard this he was glad, and went about among the
+Trojan ranks holding his spear by the middle to keep them back,
+and they all sat down at his bidding: but the Achaeans still
+aimed at him with stones and arrows, till Agamemnon shouted to
+them saying, "Hold, Argives, shoot not, sons of the Achaeans;
+Hector desires to speak."
+</para>
+
+<para>
+They ceased taking aim and were still, whereon Hector spoke.
+"Hear from my mouth," said he, "Trojans and Achaeans, the saying
+of Alexandrus, through whom this quarrel has come about. He bids
+the Trojans and Achaeans lay their armour upon the ground, while
+he and Menelaus fight in the midst of you for Helen and all her
+wealth. Let him who shall be victorious and prove to be the
+better man take the woman and all she has, to bear them to his
+own home, but let the rest swear to a solemn covenant of peace."
+</para>
+
+<para>
+Thus he spoke, and they all held their peace, till Menelaus of
+the loud battle-cry addressed them. "And now," he said, "hear me
+too, for it is I who am the most aggrieved. I deem that the
+parting of Achaeans and Trojans is at hand, as well it may be,
+seeing how much have suffered for my quarrel with Alexandrus and
+the wrong he did me. Let him who shall die, die, and let the
+others fight no more. Bring, then, two lambs, a white ram and a
+black ewe, for Earth and Sun, and we will bring a third for Jove.
+Moreover, you shall bid Priam come, that he may swear to the
+covenant himself; for his sons are high-handed and ill to trust,
+and the oaths of Jove must not be transgressed or taken in vain.
+Young men's minds are light as air, but when an old man comes he
+looks before and after, deeming that which shall be fairest upon
+both sides."
+</para>
+
+<para>
+The Trojans and Achaeans were glad when they heard this, for they
+thought that they should now have rest. They backed their
+chariots toward the ranks, got out of them, and put off their
+armour, laying it down upon the ground; and the hosts were near
+to one another with a little space between them. Hector sent two
+messengers to the city to bring the lambs and to bid Priam come,
+while Agamemnon told Talthybius to fetch the other lamb from the
+ships, and he did as Agamemnon had said.
+</para>
+
+<para>
+Meanwhile Iris went to Helen in the form of her sister-in-law,
+wife of the son of Antenor, for Helicaon, son of Antenor, had
+married Laodice, the fairest of Priam's daughters. She found her
+in her own room, working at a great web of purple linen, on which
+she was embroidering the battles between Trojans and Achaeans,
+that Mars had made them fight for her sake. Iris then came close
+up to her and said, "Come hither, child, and see the strange
+doings of the Trojans and Achaeans. Till now they have been
+warring upon the plain, mad with lust of battle, but now they
+have left off fighting, and are leaning upon their shields,
+sitting still with their spears planted beside them. Alexandrus
+and Menelaus are going to fight about yourself, and you are to be
+the wife of him who is the victor."
+</para>
+
+<para>
+Thus spoke the goddess, and Helen's heart yearned after her
+former husband, her city, and her parents. She threw a white
+mantle over her head, and hurried from her room, weeping as she
+went, not alone, but attended by two of her handmaids, Aethrae,
+daughter of Pittheus, and Clymene. And straightway they were at
+the Scaean gates.
+</para>
+
+<para>
+The two sages, Ucalegon and Antenor, elders of the people, were
+seated by the Scaean gates, with Priam, Panthous, Thymoetes,
+Lampus, Clytius, and Hiketaon of the race of Mars. These were too
+old to fight, but they were fluent orators, and sat on the tower
+like cicales that chirrup delicately from the boughs of some high
+tree in a wood. When they saw Helen coming towards the tower,
+they said softly to one another, "Small wonder that Trojans and
+Achaeans should endure so much and so long, for the sake of a
+woman so marvellously and divinely lovely. Still, fair though she
+be, let them take her and go, or she will breed sorrow for us and
+for our children after us."
+</para>
+
+<para>
+But Priam bade her draw nigh. "My child," said he, "take your
+seat in front of me that you may see your former husband, your
+kinsmen and your friends. I lay no blame upon you, it is the
+gods, not you who are to blame. It is they that have brought
+about this terrible war with the Achaeans. Tell me, then, who is
+yonder huge hero so great and goodly? I have seen men taller by a
+head, but none so comely and so royal. Surely he must be a king."
+</para>
+
+<para>
+"Sir," answered Helen, "father of my husband, dear and reverend
+in my eyes, would that I had chosen death rather than to have
+come here with your son, far from my bridal chamber, my friends,
+my darling daughter, and all the companions of my girlhood. But
+it was not to be, and my lot is one of tears and sorrow. As for
+your question, the hero of whom you ask is Agamemnon, son of
+Atreus, a good king and a brave soldier, brother-in-law as surely
+as that he lives, to my abhorred and miserable self."
+</para>
+
+<para>
+The old man marvelled at him and said, "Happy son of Atreus,
+child of good fortune. I see that the Achaeans are subject to you
+in great multitudes. When I was in Phrygia I saw much horsemen,
+the people of Otreus and of Mygdon, who were camping upon the
+banks of the river Sangarius; I was their ally, and with them
+when the Amazons, peers of men, came up against them, but even
+they were not so many as the Achaeans."
+</para>
+
+<para>
+The old man next looked upon Ulysses; "Tell me," he said, "who is
+that other, shorter by a head than Agamemnon, but broader across
+the chest and shoulders? His armour is laid upon the ground, and
+he stalks in front of the ranks as it were some great woolly ram
+ordering his ewes."
+</para>
+
+<para>
+And Helen answered, "He is Ulysses, a man of great craft, son of
+Laertes. He was born in rugged Ithaca, and excels in all manner
+of stratagems and subtle cunning."
+</para>
+
+<para>
+On this Antenor said, "Madam, you have spoken truly. Ulysses once
+came here as envoy about yourself, and Menelaus with him. I
+received them in my own house, and therefore know both of them by
+sight and conversation. When they stood up in presence of the
+assembled Trojans, Menelaus was the broader shouldered, but when
+both were seated Ulysses had the more royal presence. After a
+time they delivered their message, and the speech of Menelaus ran
+trippingly on the tongue; he did not say much, for he was a man
+of few words, but he spoke very clearly and to the point, though
+he was the younger man of the two; Ulysses, on the other hand,
+when he rose to speak, was at first silent and kept his eyes
+fixed upon the ground. There was no play nor graceful movement of
+his sceptre; he kept it straight and stiff like a man unpractised
+in oratory--one might have taken him for a mere churl or
+simpleton; but when he raised his voice, and the words came
+driving from his deep chest like winter snow before the wind,
+then there was none to touch him, and no man thought further of
+what he looked like."
+</para>
+
+<para>
+Priam then caught sight of Ajax and asked, "Who is that great and
+goodly warrior whose head and broad shoulders tower above the
+rest of the Argives?"
+</para>
+
+<para>
+"That," answered Helen, "is huge Ajax, bulwark of the Achaeans,
+and on the other side of him, among the Cretans, stands Idomeneus
+looking like a god, and with the captains of the Cretans round
+him. Often did Menelaus receive him as a guest in our house when
+he came visiting us from Crete. I see, moreover, many other
+Achaeans whose names I could tell you, but there are two whom I
+can nowhere find, Castor, breaker of horses, and Pollux the
+mighty boxer; they are children of my mother, and own brothers to
+myself. Either they have not left Lacedaemon, or else, though
+they have brought their ships, they will not show themselves in
+battle for the shame and disgrace that I have brought upon them."
+</para>
+
+<para>
+She knew not that both these heroes were already lying under the
+earth in their own land of Lacedaemon.
+</para>
+
+<para>
+Meanwhile the heralds were bringing the holy oath-offerings
+through the city--two lambs and a goatskin of wine, the gift of
+earth; and Idaeus brought the mixing bowl and the cups of gold.
+He went up to Priam and said, "Son of Laomedon, the princes of
+the Trojans and Achaeans bid you come down on to the plain and
+swear to a solemn covenant. Alexandrus and Menelaus are to fight
+for Helen in single combat, that she and all her wealth may go
+with him who is the victor. We are to swear to a solemn covenant
+of peace whereby we others shall dwell here in Troy, while the
+Achaeans return to Argos and the land of the Achaeans."
+</para>
+
+<para>
+The old man trembled as he heard, but bade his followers yoke the
+horses, and they made all haste to do so. He mounted the chariot,
+gathered the reins in his hand, and Antenor took his seat beside
+him; they then drove through the Scaean gates on to the plain.
+When they reached the ranks of the Trojans and Achaeans they left
+the chariot, and with measured pace advanced into the space
+between the hosts.
+</para>
+
+<para>
+Agamemnon and Ulysses both rose to meet them. The attendants
+brought on the oath-offerings and mixed the wine in the
+mixing-bowls; they poured water over the hands of the chieftains,
+and the son of Atreus drew the dagger that hung by his sword, and
+cut wool from the lambs' heads; this the men-servants gave about
+among the Trojan and Achaean princes, and the son of Atreus
+lifted up his hands in prayer. "Father Jove," he cried, "that
+rulest in Ida, most glorious in power, and thou oh Sun, that
+seest and givest ear to all things, Earth and Rivers, and ye who
+in the realms below chastise the soul of him that has broken his
+oath, witness these rites and guard them, that they be not vain.
+If Alexandrus kills Menelaus, let him keep Helen and all her
+wealth, while we sail home with our ships; but if Menelaus kills
+Alexandrus, let the Trojans give back Helen and all that she has;
+let them moreover pay such fine to the Achaeans as shall be
+agreed upon, in testimony among those that shall be born
+hereafter. And if Priam and his sons refuse such fine when
+Alexandrus has fallen, then will I stay here and fight on till I
+have got satisfaction."
+</para>
+
+<para>
+As he spoke he drew his knife across the throats of the victims,
+and laid them down gasping and dying upon the ground, for the
+knife had reft them of their strength. Then they poured wine from
+the mixing-bowl into the cups, and prayed to the everlasting
+gods, saying, Trojans and Achaeans among one another, "Jove, most
+great and glorious, and ye other everlasting gods, grant that the
+brains of them who shall first sin against their oaths--of them
+and their children--may be shed upon the ground even as this
+wine, and let their wives become the slaves of strangers."
+</para>
+
+<para>
+Thus they prayed, but not as yet would Jove grant them their
+prayer. Then Priam, descendant of Dardanus, spoke, saying, "Hear
+me, Trojans and Achaeans, I will now go back to the wind-beaten
+city of Ilius: I dare not with my own eyes witness this fight
+between my son and Menelaus, for Jove and the other immortals
+alone know which shall fall."
+</para>
+
+<para>
+On this he laid the two lambs on his chariot and took his seat.
+He gathered the reins in his hand, and Antenor sat beside him;
+the two then went back to Ilius. Hector and Ulysses measured the
+ground, and cast lots from a helmet of bronze to see which should
+take aim first. Meanwhile the two hosts lifted up their hands and
+prayed saying, "Father Jove, that rulest from Ida, most glorious
+in power, grant that he who first brought about this war between
+us may die, and enter the house of Hades, while we others remain
+at peace and abide by our oaths."
+</para>
+
+<para>
+Great Hector now turned his head aside while he shook the helmet,
+and the lot of Paris flew out first. The others took their
+several stations, each by his horses and the place where his arms
+were lying, while Alexandrus, husband of lovely Helen, put on his
+goodly armour. First he greaved his legs with greaves of good
+make and fitted with ancle-clasps of silver; after this he donned
+the cuirass of his brother Lycaon, and fitted it to his own body;
+he hung his silver-studded sword of bronze about his shoulders,
+and then his mighty shield. On his comely head he set his helmet,
+well-wrought, with a crest of horse-hair that nodded menacingly
+above it, and he grasped a redoubtable spear that suited his
+hands. In like fashion Menelaus also put on his armour.
+</para>
+
+<para>
+When they had thus armed, each amid his own people, they strode
+fierce of aspect into the open space, and both Trojans and
+Achaeans were struck with awe as they beheld them. They stood
+near one another on the measured ground, brandishing their
+spears, and each furious against the other. Alexandrus aimed
+first, and struck the round shield of the son of Atreus, but the
+spear did not pierce it, for the shield turned its point.
+Menelaus next took aim, praying to Father Jove as he did so.
+"King Jove," he said, "grant me revenge on Alexandrus who has
+wronged me; subdue him under my hand that in ages yet to come a
+man may shrink from doing ill deeds in the house of his host."
+</para>
+
+<para>
+He poised his spear as he spoke, and hurled it at the shield of
+Alexandrus. Through shield and cuirass it went, and tore the
+shirt by his flank, but Alexandrus swerved aside, and thus saved
+his life. Then the son of Atreus drew his sword, and drove at the
+projecting part of his helmet, but the sword fell shivered in
+three or four pieces from his hand, and he cried, looking towards
+Heaven, "Father Jove, of all gods thou art the most despiteful; I
+made sure of my revenge, but the sword has broken in my hand, my
+spear has been hurled in vain, and I have not killed him."
+</para>
+
+<para>
+With this he flew at Alexandrus, caught him by the horsehair
+plume of his helmet, and began dragging him towards the Achaeans.
+The strap of the helmet that went under his chin was choking him,
+and Menelaus would have dragged him off to his own great glory
+had not Jove's daughter Venus been quick to mark and to break the
+strap of oxhide, so that the empty helmet came away in his hand.
+This he flung to his comrades among the Achaeans, and was again
+springing upon Alexandrus to run him through with a spear, but
+Venus snatched him up in a moment (as a god can do), hid him
+under a cloud of darkness, and conveyed him to his own
+bedchamber.
+</para>
+
+<para>
+Then she went to call Helen, and found her on a high tower with
+the Trojan women crowding round her. She took the form of an old
+woman who used to dress wool for her when she was still in
+Lacedaemon, and of whom she was very fond. Thus disguised she
+plucked her by perfumed robe and said, "Come hither; Alexandrus
+says you are to go to the house; he is on his bed in his own
+room, radiant with beauty and dressed in gorgeous apparel. No one
+would think he had just come from fighting, but rather that he
+was going to a dance, or had done dancing and was sitting down."
+</para>
+
+<para>
+With these words she moved the heart of Helen to anger. When she
+marked the beautiful neck of the goddess, her lovely bosom, and
+sparkling eyes, she marvelled at her and said, "Goddess, why do
+you thus beguile me? Are you going to send me afield still
+further to some man whom you have taken up in Phrygia or fair
+Meonia? Menelaus has just vanquished Alexandrus, and is to take
+my hateful self back with him. You are come here to betray me. Go
+sit with Alexandrus yourself; henceforth be goddess no longer;
+never let your feet carry you back to Olympus; worry about him
+and look after him till he make you his wife, or, for the matter
+of that, his slave--but me? I shall not go; I can garnish his bed
+no longer; I should be a by-word among all the women of Troy.
+Besides, I have trouble on my mind."
+</para>
+
+<para>
+Venus was very angry, and said, "Bold hussy, do not provoke me;
+if you do, I shall leave you to your fate and hate you as much as
+I have loved you. I will stir up fierce hatred between Trojans
+and Achaeans, and you shall come to a bad end."
+</para>
+
+<para>
+At this Helen was frightened. She wrapped her mantle about her
+and went in silence, following the goddess and unnoticed by the
+Trojan women.
+</para>
+
+<para>
+When they came to the house of Alexandrus the maid-servants set
+about their work, but Helen went into her own room, and the
+laughter-loving goddess took a seat and set it for her facing
+Alexandrus. On this Helen, daughter of aegis-bearing Jove, sat
+down, and with eyes askance began to upbraid her husband.
+</para>
+
+<para>
+"So you are come from the fight," said she; "would that you had
+fallen rather by the hand of that brave man who was my husband.
+You used to brag that you were a better man with hands and spear
+than Menelaus. Go, then, and challenge him again--but I should
+advise you not to do so, for if you are foolish enough to meet
+him in single combat, you will soon fall by his spear."
+</para>
+
+<para>
+And Paris answered, "Wife, do not vex me with your reproaches.
+This time, with the help of Minerva, Menelaus has vanquished me;
+another time I may myself be victor, for I too have gods that
+will stand by me. Come, let us lie down together and make
+friends. Never yet was I so passionately enamoured of you as at
+this moment--not even when I first carried you off from
+Lacedaemon and sailed away with you--not even when I had converse
+with you upon the couch of love in the island of Cranae was I so
+enthralled by desire of you as now." On this he led her towards
+the bed, and his wife went with him.
+</para>
+
+<para>
+Thus they laid themselves on the bed together; but the son of
+Atreus strode among the throng, looking everywhere for
+Alexandrus, and no man, neither of the Trojans nor of the allies,
+could find him. If they had seen him they were in no mind to hide
+him, for they all of them hated him as they did death itself.
+Then Agamemnon, king of men, spoke, saying, "Hear me, Trojans,
+Dardanians, and allies. The victory has been with Menelaus;
+therefore give back Helen with all her wealth, and pay such fine
+as shall be agreed upon, in testimony among them that shall be
+born hereafter."
+</para>
+
+<para>
+Thus spoke the son of Atreus, and the Achaeans shouted in
+applause.
+</para>
+</chapter>
+
+<chapter>
+<title>BOOK IV</title>
+
+<para>
+Now the gods were sitting with Jove in council upon the golden
+floor while Hebe went round pouring out nectar for them to drink,
+and as they pledged one another in their cups of gold they looked
+down upon the town of Troy. The son of Saturn then began to tease
+Juno, talking at her so as to provoke her. "Menelaus," said he,
+"has two good friends among the goddesses, Juno of Argos, and
+Minerva of Alalcomene, but they only sit still and look on, while
+Venus keeps ever by Alexandrus' side to defend him in any danger;
+indeed she has just rescued him when he made sure that it was all
+over with him--for the victory really did lie with Menelaus. We
+must consider what we shall do about all this; shall we set them
+fighting anew or make peace between them? If you will agree to
+this last Menelaus can take back Helen and the city of Priam may
+remain still inhabited."
+</para>
+
+<para>
+Minerva and Juno muttered their discontent as they sat side by
+side hatching mischief for the Trojans. Minerva scowled at her
+father, for she was in a furious passion with him, and said
+nothing, but Juno could not contain herself. "Dread son of
+Saturn," said she, "what, pray, is the meaning of all this? Is my
+trouble, then, to go for nothing, and the sweat that I have
+sweated, to say nothing of my horses, while getting the people
+together against Priam and his children? Do as you will, but we
+other gods shall not all of us approve your counsel."
+</para>
+
+<para>
+Jove was angry and answered, "My dear, what harm have Priam and
+his sons done you that you are so hotly bent on sacking the city
+of Ilius? Will nothing do for you but you must within their walls
+and eat Priam raw, with his sons and all the other Trojans to
+boot? Have it your own way then; for I would not have this matter
+become a bone of contention between us. I say further, and lay my
+saying to your heart, if ever I want to sack a city belonging to
+friends of yours, you must not try to stop me; you will have to
+let me do it, for I am giving in to you sorely against my will.
+Of all inhabited cities under the sun and stars of heaven, there
+was none that I so much respected as Ilius with Priam and his
+whole people. Equitable feasts were never wanting about my altar,
+nor the savour of burning fat, which is honour due to ourselves."
+</para>
+
+<para>
+"My own three favourite cities," answered Juno, "are Argos,
+Sparta, and Mycenae. Sack them whenever you may be displeased
+with them. I shall not defend them and I shall not care. Even if
+I did, and tried to stay you, I should take nothing by it, for
+you are much stronger than I am, but I will not have my own work
+wasted. I too am a god and of the same race with yourself. I am
+Saturn's eldest daughter, and am honourable not on this ground
+only, but also because I am your wife, and you are king over the
+gods. Let it be a case, then, of give-and-take between us, and
+the rest of the gods will follow our lead. Tell Minerva to go and
+take part in the fight at once, and let her contrive that the
+Trojans shall be the first to break their oaths and set upon the
+Achaeans."
+</para>
+
+<para>
+The sire of gods and men heeded her words, and said to Minerva,
+"Go at once into the Trojan and Achaean hosts, and contrive that
+the Trojans shall be the first to break their oaths and set upon
+the Achaeans."
+</para>
+
+<para>
+This was what Minerva was already eager to do, so down she darted
+from the topmost summits of Olympus. She shot through the sky as
+some brilliant meteor which the son of scheming Saturn has sent
+as a sign to mariners or to some great army, and a fiery train of
+light follows in its wake. The Trojans and Achaeans were struck
+with awe as they beheld, and one would turn to his neighbour,
+saying, "Either we shall again have war and din of combat, or
+Jove the lord of battle will now make peace between us."
+</para>
+
+<para>
+Thus did they converse. Then Minerva took the form of Laodocus,
+son of Antenor, and went through the ranks of the Trojans to find
+Pandarus, the redoubtable son of Lycaon. She found him standing
+among the stalwart heroes who had followed him from the banks of
+the Aesopus, so she went close up to him and said, "Brave son of
+Lycaon, will you do as I tell you? If you dare send an arrow at
+Menelaus you will win honour and thanks from all the Trojans, and
+especially from prince Alexandrus--he would be the first to
+requite you very handsomely if he could see Menelaus mount his
+funeral pyre, slain by an arrow from your hand. Take your home
+aim then, and pray to Lycian Apollo, the famous archer; vow that
+when you get home to your strong city of Zelea you will offer a
+hecatomb of firstling lambs in his honour."
+</para>
+
+<para>
+His fool's heart was persuaded, and he took his bow from its
+case. This bow was made from the horns of a wild ibex which he
+had killed as it was bounding from a rock; he had stalked it, and
+it had fallen as the arrow struck it to the heart. Its horns were
+sixteen palms long, and a worker in horn had made them into a
+bow, smoothing them well down, and giving them tips of gold. When
+Pandarus had strung his bow he laid it carefully on the ground,
+and his brave followers held their shields before him lest the
+Achaeans should set upon him before he had shot Menelaus. Then he
+opened the lid of his quiver and took out a winged arrow that had
+not yet been shot, fraught with the pangs of death. He laid the
+arrow on the string and prayed to Lycian Apollo, the famous
+archer, vowing that when he got home to his strong city of Zelea
+he would offer a hecatomb of firstling lambs in his honour. He
+laid the notch of the arrow on the oxhide bowstring, and drew
+both notch and string to his breast till the arrow-head was near
+the bow; then when the bow was arched into a half-circle he let
+fly, and the bow twanged, and the string sang as the arrow flew
+gladly on over the heads of the throng.
+</para>
+
+<para>
+But the blessed gods did not forget thee, O Menelaus, and Jove's
+daughter, driver of the spoil, was the first to stand before thee
+and ward off the piercing arrow. She turned it from his skin as a
+mother whisks a fly from off her child when it is sleeping
+sweetly; she guided it to the part where the golden buckles of
+the belt that passed over his double cuirass were fastened, so
+the arrow struck the belt that went tightly round him. It went
+right through this and through the cuirass of cunning
+workmanship; it also pierced the belt beneath it, which he wore
+next his skin to keep out darts or arrows; it was this that
+served him in the best stead, nevertheless the arrow went through
+it and grazed the top of the skin, so that blood began flowing
+from the wound.
+</para>
+
+<para>
+As when some woman of Meonia or Caria strains purple dye on to a
+piece of ivory that is to be the cheek-piece of a horse, and is
+to be laid up in a treasure house--many a knight is fain to bear
+it, but the king keeps it as an ornament of which both horse and
+driver may be proud--even so, O Menelaus, were your shapely
+thighs and your legs down to your fair ancles stained with blood.
+</para>
+
+<para>
+When King Agamemnon saw the blood flowing from the wound he was
+afraid, and so was brave Menelaus himself till he saw that the
+barbs of the arrow and the thread that bound the arrow-head to
+the shaft were still outside the wound. Then he took heart, but
+Agamemnon heaved a deep sigh as he held Menelaus's hand in his
+own, and his comrades made moan in concert. "Dear brother," he
+cried, "I have been the death of you in pledging this covenant
+and letting you come forward as our champion. The Trojans have
+trampled on their oaths and have wounded you; nevertheless the
+oath, the blood of lambs, the drink-offerings and the right hands
+of fellowship in which we have put our trust shall not be vain.
+If he that rules Olympus fulfil it not here and now, he will yet
+fulfil it hereafter, and they shall pay dearly with their lives
+and with their wives and children. The day will surely come when
+mighty Ilius shall be laid low, with Priam and Priam's people,
+when the son of Saturn from his high throne shall overshadow them
+with his awful aegis in punishment of their present treachery.
+This shall surely be; but how, Menelaus, shall I mourn you, if it
+be your lot now to die? I should return to Argos as a by-word,
+for the Achaeans will at once go home. We shall leave Priam and
+the Trojans the glory of still keeping Helen, and the earth will
+rot your bones as you lie here at Troy with your purpose not
+fulfilled. Then shall some braggart Trojan leap upon your tomb
+and say, 'Ever thus may Agamemnon wreak his vengeance; he brought
+his army in vain; he is gone home to his own land with empty
+ships, and has left Menelaus behind him.' Thus will one of them
+say, and may the earth then swallow me."
+</para>
+
+<para>
+But Menelaus reassured him and said, "Take heart, and do not
+alarm the people; the arrow has not struck me in a mortal part,
+for my outer belt of burnished metal first stayed it, and under
+this my cuirass and the belt of mail which the bronze-smiths made
+me."
+</para>
+
+<para>
+And Agamemnon answered, "I trust, dear Menelaus, that it may be
+even so, but the surgeon shall examine your wound and lay herbs
+upon it to relieve your pain."
+</para>
+
+<para>
+He then said to Talthybius, "Talthybius, tell Machaon, son to the
+great physician, Aesculapius, to come and see Menelaus
+immediately. Some Trojan or Lycian archer has wounded him with an
+arrow to our dismay, and to his own great glory."
+</para>
+
+<para>
+Talthybius did as he was told, and went about the host trying to
+find Machaon. Presently he found standing amid the brave warriors
+who had followed him from Tricca; thereon he went up to him and
+said, "Son of Aesculapius, King Agamemnon says you are to come
+and see Menelaus immediately. Some Trojan or Lycian archer has
+wounded him with an arrow to our dismay and to his own great
+glory."
+</para>
+
+<para>
+Thus did he speak, and Machaon was moved to go. They passed
+through the spreading host of the Achaeans and went on till they
+came to the place where Menelaus had been wounded and was lying
+with the chieftains gathered in a circle round him. Machaon
+passed into the middle of the ring and at once drew the arrow
+from the belt, bending its barbs back through the force with
+which he pulled it out. He undid the burnished belt, and beneath
+this the cuirass and the belt of mail which the bronze-smiths had
+made; then, when he had seen the wound, he wiped away the blood
+and applied some soothing drugs which Chiron had given to
+Aesculapius out of the good will he bore him.
+</para>
+
+<para>
+While they were thus busy about Menelaus, the Trojans came
+forward against them, for they had put on their armour, and now
+renewed the fight.
+</para>
+
+<para>
+You would not have then found Agamemnon asleep nor cowardly and
+unwilling to fight, but eager rather for the fray. He left his
+chariot rich with bronze and his panting steeds in charge of
+Eurymedon, son of Ptolemaeus the son of Peiraeus, and bade him
+hold them in readiness against the time his limbs should weary of
+going about and giving orders to so many, for he went among the
+ranks on foot. When he saw men hasting to the front he stood by
+them and cheered them on. "Argives," said he, "slacken not one
+whit in your onset; father Jove will be no helper of liars; the
+Trojans have been the first to break their oaths and to attack
+us; therefore they shall be devoured of vultures; we shall take
+their city and carry off their wives and children in our ships."
+</para>
+
+<para>
+But he angrily rebuked those whom he saw shirking and disinclined
+to fight. "Argives," he cried, "cowardly miserable creatures,
+have you no shame to stand here like frightened fawns who, when
+they can no longer scud over the plain, huddle together, but show
+no fight? You are as dazed and spiritless as deer. Would you wait
+till the Trojans reach the sterns of our ships as they lie on the
+shore, to see whether the son of Saturn will hold his hand over
+you to protect you?"
+</para>
+
+<para>
+Thus did he go about giving his orders among the ranks. Passing
+through the crowd, he came presently on the Cretans, arming round
+Idomeneus, who was at their head, fierce as a wild boar, while
+Meriones was bringing up the battalions that were in the rear.
+Agamemnon was glad when he saw him, and spoke him fairly.
+"Idomeneus," said he, "I treat you with greater distinction than
+I do any others of the Achaeans, whether in war or in other
+things, or at table. When the princes are mixing my choicest
+wines in the mixing-bowls, they have each of them a fixed
+allowance, but your cup is kept always full like my own, that you
+may drink whenever you are minded. Go, therefore, into battle,
+and show yourself the man you have been always proud to be."
+</para>
+
+<para>
+Idomeneus answered, "I will be a trusty comrade, as I promised
+you from the first I would be. Urge on the other Achaeans, that
+we may join battle at once, for the Trojans have trampled upon
+their covenants. Death and destruction shall be theirs, seeing
+they have been the first to break their oaths and to attack us."
+</para>
+
+<para>
+The son of Atreus went on, glad at heart, till he came upon the
+two Ajaxes arming themselves amid a host of foot-soldiers. As
+when a goat-herd from some high post watches a storm drive over
+the deep before the west wind--black as pitch is the offing and a
+mighty whirlwind draws towards him, so that he is afraid and
+drives his flock into a cave--even thus did the ranks of stalwart
+youths move in a dark mass to battle under the Ajaxes, horrid
+with shield and spear. Glad was King Agamemnon when he saw them.
+"No need," he cried, "to give orders to such leaders of the
+Argives as you are, for of your own selves you spur your men on
+to fight with might and main. Would, by father Jove, Minerva, and
+Apollo that all were so minded as you are, for the city of Priam
+would then soon fall beneath our hands, and we should sack it."
+</para>
+
+<para>
+With this he left them and went onward to Nestor, the facile
+speaker of the Pylians, who was marshalling his men and urging
+them on, in company with Pelagon, Alastor, Chromius, Haemon, and
+Bias shepherd of his people. He placed his knights with their
+chariots and horses in the front rank, while the foot-soldiers,
+brave men and many, whom he could trust, were in the rear. The
+cowards he drove into the middle, that they might fight whether
+they would or no. He gave his orders to the knights first,
+bidding them hold their horses well in hand, so as to avoid
+confusion. "Let no man," he said, "relying on his strength or
+horsemanship, get before the others and engage singly with the
+Trojans, nor yet let him lag behind or you will weaken your
+attack; but let each when he meets an enemy's chariot throw his
+spear from his own; this be much the best; this is how the men of
+old took towns and strongholds; in this wise were they minded."
+</para>
+
+<para>
+Thus did the old man charge them, for he had been in many a
+fight, and King Agamemnon was glad. "I wish," he said to him,
+"that your limbs were as supple and your strength as sure as your
+judgment is; but age, the common enemy of mankind, has laid his
+hand upon you; would that it had fallen upon some other, and that
+you were still young."
+</para>
+
+<para>
+And Nestor, knight of Gerene, answered, "Son of Atreus, I too
+would gladly be the man I was when I slew mighty Ereuthalion; but
+the gods will not give us everything at one and the same time. I
+was then young, and now I am old; still I can go with my knights
+and give them that counsel which old men have a right to give.
+The wielding of the spear I leave to those who are younger and
+stronger than myself."
+</para>
+
+<para>
+Agamemnon went his way rejoicing, and presently found Menestheus,
+son of Peteos, tarrying in his place, and with him were the
+Athenians loud of tongue in battle. Near him also tarried cunning
+Ulysses, with his sturdy Cephallenians round him; they had not
+yet heard the battle-cry, for the ranks of Trojans and Achaeans
+had only just begun to move, so they were standing still, waiting
+for some other columns of the Achaeans to attack the Trojans and
+begin the fighting. When he saw this Agamemnon rebuked them and
+said, "Son of Peteos, and you other, steeped in cunning, heart of
+guile, why stand you here cowering and waiting on others? You two
+should be of all men foremost when there is hard fighting to be
+done, for you are ever foremost to accept my invitation when we
+councillors of the Achaeans are holding feast. You are glad
+enough then to take your fill of roast meats and to drink wine as
+long as you please, whereas now you would not care though you saw
+ten columns of Achaeans engage the enemy in front of you."
+</para>
+
+<para>
+Ulysses glared at him and answered, "Son of Atreus, what are you
+talking about? How can you say that we are slack? When the
+Achaeans are in full fight with the Trojans, you shall see, if
+you care to do so, that the father of Telemachus will join battle
+with the foremost of them. You are talking idly."
+</para>
+
+<para>
+When Agamemnon saw that Ulysses was angry, he smiled pleasantly
+at him and withdrew his words. "Ulysses," said he, "noble son of
+Laertes, excellent in all good counsel, I have neither fault to
+find nor orders to give you, for I know your heart is right, and
+that you and I are of a mind. Enough; I will make you amends for
+what I have said, and if any ill has now been spoken may the gods
+bring it to nothing."
+</para>
+
+<para>
+He then left them and went on to others. Presently he saw the son
+of Tydeus, noble Diomed, standing by his chariot and horses, with
+Sthenelus the son of Capaneus beside him; whereon he began to
+upbraid him. "Son of Tydeus," he said, "why stand you cowering
+here upon the brink of battle? Tydeus did not shrink thus, but
+was ever ahead of his men when leading them on against the foe--
+so, at least, say they that saw him in battle, for I never set
+eyes upon him myself. They say that there was no man like him. He
+came once to Mycenae, not as an enemy but as a guest, in company
+with Polynices to recruit his forces, for they were levying war
+against the strong city of Thebes, and prayed our people for a
+body of picked men to help them. The men of Mycenae were willing
+to let them have one, but Jove dissuaded them by showing them
+unfavourable omens. Tydeus, therefore, and Polynices went their
+way. When they had got as far the deep-meadowed and rush-grown
+banks of the Aesopus, the Achaeans sent Tydeus as their envoy,
+and he found the Cadmeans gathered in great numbers to a banquet
+in the house of Eteocles. Stranger though he was, he knew no fear
+on finding himself single-handed among so many, but challenged
+them to contests of all kinds, and in each one of them was at
+once victorious, so mightily did Minerva help him. The Cadmeans
+were incensed at his success, and set a force of fifty youths
+with two captains--the godlike hero Maeon, son of Haemon, and
+Polyphontes, son of Autophonus--at their head, to lie in wait for
+him on his return journey; but Tydeus slew every man of them,
+save only Maeon, whom he let go in obedience to heaven's omens.
+Such was Tydeus of Aetolia. His son can talk more glibly, but he
+cannot fight as his father did."
+</para>
+
+<para>
+Diomed made no answer, for he was shamed by the rebuke of
+Agamemnon; but the son of Capaneus took up his words and said,
+"Son of Atreus, tell no lies, for you can speak truth if you
+will. We boast ourselves as even better men than our fathers; we
+took seven-gated Thebes, though the wall was stronger and our men
+were fewer in number, for we trusted in the omens of the gods and
+in the help of Jove, whereas they perished through their own
+sheer folly; hold not, then, our fathers in like honour with us."
+</para>
+
+<para>
+Diomed looked sternly at him and said, "Hold your peace, my
+friend, as I bid you. It is not amiss that Agamemnon should urge
+the Achaeans forward, for the glory will be his if we take the
+city, and his the shame if we are vanquished. Therefore let us
+acquit ourselves with valour."
+</para>
+
+<para>
+As he spoke he sprang from his chariot, and his armour rang so
+fiercely about his body that even a brave man might well have
+been scared to hear it.
+</para>
+
+<para>
+As when some mighty wave that thunders on the beach when the west
+wind has lashed it into fury--it has reared its head afar and now
+comes crashing down on the shore; it bows its arching crest high
+over the jagged rocks and spews its salt foam in all
+directions--even so did the serried phalanxes of the Danaans
+march steadfastly to battle. The chiefs gave orders each to his
+own people, but the men said never a word; no man would think it,
+for huge as the host was, it seemed as though there was not a
+tongue among them, so silent were they in their obedience; and as
+they marched the armour about their bodies glistened in the sun.
+But the clamour of the Trojan ranks was as that of many thousand
+ewes that stand waiting to be milked in the yards of some rich
+flockmaster, and bleat incessantly in answer to the bleating of
+their lambs; for they had not one speech nor language, but their
+tongues were diverse, and they came from many different places.
+These were inspired of Mars, but the others by Minerva--and with
+them came Panic, Rout, and Strife whose fury never tires, sister
+and friend of murderous Mars, who, from being at first but low in
+stature, grows till she uprears her head to heaven, though her
+feet are still on earth. She it was that went about among them
+and flung down discord to the waxing of sorrow with even hand
+between them.
+</para>
+
+<para>
+When they were got together in one place shield clashed with
+shield and spear with spear in the rage of battle. The bossed
+shields beat one upon another, and there was a tramp as of a
+great multitude--death-cry and shout of triumph of slain and
+slayers, and the earth ran red with blood. As torrents swollen
+with rain course madly down their deep channels till the angry
+floods meet in some gorge, and the shepherd on the hillside hears
+their roaring from afar--even such was the toil and uproar of the
+hosts as they joined in battle.
+</para>
+
+<para>
+First Antilochus slew an armed warrior of the Trojans, Echepolus,
+son of Thalysius, fighting in the foremost ranks. He struck at
+the projecting part of his helmet and drove the spear into his
+brow; the point of bronze pierced the bone, and darkness veiled
+his eyes; headlong as a tower he fell amid the press of the
+fight, and as he dropped King Elephenor, son of Chalcodon and
+captain of the proud Abantes began dragging him out of reach of
+the darts that were falling around him, in haste to strip him of
+his armour. But his purpose was not for long; Agenor saw him
+haling the body away, and smote him in the side with his
+bronze-shod spear--for as he stooped his side was left
+unprotected by his shield--and thus he perished. Then the fight
+between Trojans and Achaeans grew furious over his body, and they
+flew upon each other like wolves, man and man crushing one upon
+the other.
+</para>
+
+<para>
+Forthwith Ajax, son of Telamon, slew the fair youth Simoeisius,
+son of Anthemion, whom his mother bore by the banks of the
+Simois, as she was coming down from Mt. Ida, where she had been
+with her parents to see their flocks. Therefore he was named
+Simoeisius, but he did not live to pay his parents for his
+rearing, for he was cut off untimely by the spear of mighty Ajax,
+who struck him in the breast by the right nipple as he was coming
+on among the foremost fighters; the spear went right through his
+shoulder, and he fell as a poplar that has grown straight and
+tall in a meadow by some mere, and its top is thick with
+branches. Then the wheelwright lays his axe to its roots that he
+may fashion a felloe for the wheel of some goodly chariot, and it
+lies seasoning by the waterside. In such wise did Ajax fell to
+earth Simoeisius, son of Anthemion. Thereon Antiphus of the
+gleaming corslet, son of Priam, hurled a spear at Ajax from amid
+the crowd and missed him, but he hit Leucus, the brave comrade of
+Ulysses, in the groin, as he was dragging the body of Simoeisius
+over to the other side; so he fell upon the body and loosed his
+hold upon it. Ulysses was furious when he saw Leucus slain, and
+strode in full armour through the front ranks till he was quite
+close; then he glared round about him and took aim, and the
+Trojans fell back as he did so. His dart was not sped in vain,
+for it struck Democoon, the bastard son of Priam, who had come to
+him from Abydos, where he had charge of his father's mares.
+Ulysses, infuriated by the death of his comrade, hit him with his
+spear on one temple, and the bronze point came through on the
+other side of his forehead. Thereon darkness veiled his eyes, and
+his armour rang rattling round him as he fell heavily to the
+ground. Hector, and they that were in front, then gave round
+while the Argives raised a shout and drew off the dead, pressing
+further forward as they did so. But Apollo looked down from
+Pergamus and called aloud to the Trojans, for he was displeased.
+"Trojans," he cried, "rush on the foe, and do not let yourselves
+be thus beaten by the Argives. Their skins are not stone nor iron
+that when hit them you do them no harm. Moreover, Achilles, the
+son of lovely Thetis, is not fighting, but is nursing his anger
+at the ships."
+</para>
+
+<para>
+Thus spoke the mighty god, crying to them from the city, while
+Jove's redoubtable daughter, the Trito-born, went about among the
+host of the Achaeans, and urged them forward whenever she beheld
+them slackening.
+</para>
+
+<para>
+Then fate fell upon Diores, son of Amarynceus, for he was struck
+by a jagged stone near the ancle of his right leg. He that hurled
+it was Peirous, son of Imbrasus, captain of the Thracians, who
+had come from Aenus; the bones and both the tendons were crushed
+by the pitiless stone. He fell to the ground on his back, and in
+his death throes stretched out his hands towards his comrades.
+But Peirous, who had wounded him, sprang on him and thrust a
+spear into his belly, so that his bowels came gushing out upon
+the ground, and darkness veiled his eyes. As he was leaving the
+body, Thoas of Aetolia struck him in the chest near the nipple,
+and the point fixed itself in his lungs. Thoas came close up to
+him, pulled the spear out of his chest, and then drawing his
+sword, smote him in the middle of the belly so that he died; but
+he did not strip him of his armour, for his Thracian comrades,
+men who wear their hair in a tuft at the top of their heads,
+stood round the body and kept him off with their long spears for
+all his great stature and valour; so he was driven back. Thus the
+two corpses lay stretched on earth near to one another, the one
+captain of the Thracians and the other of the Epeans; and many
+another fell round them.
+</para>
+
+<para>
+And now no man would have made light of the fighting if he could
+have gone about among it scatheless and unwounded, with Minerva
+leading him by the hand, and protecting him from the storm of
+spears and arrows. For many Trojans and Achaeans on that day lay
+stretched side by side face downwards upon the earth.
+</para>
+</chapter>
+
+<chapter>
+<title>BOOK V</title>
+
+<para>
+Then Pallas Minerva put valour into the heart of Diomed, son of
+Tydeus, that he might excel all the other Argives, and cover
+himself with glory. She made a stream of fire flare from his
+shield and helmet like the star that shines most brilliantly in
+summer after its bath in the waters of Oceanus--even such a fire
+did she kindle upon his head and shoulders as she bade him speed
+into the thickest hurly-burly of the fight.
+</para>
+
+<para>
+Now there was a certain rich and honourable man among the
+Trojans, priest of Vulcan, and his name was Dares. He had two
+sons, Phegeus and Idaeus, both of them skilled in all the arts of
+war. These two came forward from the main body of Trojans, and
+set upon Diomed, he being on foot, while they fought from their
+chariot. When they were close up to one another, Phegeus took aim
+first, but his spear went over Diomed's left shoulder without
+hitting him. Diomed then threw, and his spear sped not in vain,
+for it hit Phegeus on the breast near the nipple, and he fell
+from his chariot. Idaeus did not dare to bestride his brother's
+body, but sprang from the chariot and took to flight, or he would
+have shared his brother's fate; whereon Vulcan saved him by
+wrapping him in a cloud of darkness, that his old father might
+not be utterly overwhelmed with grief; but the son of Tydeus
+drove off with the horses, and bade his followers take them to
+the ships. The Trojans were scared when they saw the two sons of
+Dares, one of them in fright and the other lying dead by his
+chariot. Minerva, therefore, took Mars by the hand and said,
+"Mars, Mars, bane of men, bloodstained stormer of cities, may we
+not now leave the Trojans and Achaeans to fight it out, and see
+to which of the two Jove will vouchsafe the victory? Let us go
+away, and thus avoid his anger."
+</para>
+
+<para>
+So saying, she drew Mars out of the battle, and set him down upon
+the steep banks of the Scamander. Upon this the Danaans drove the
+Trojans back, and each one of their chieftains killed his man.
+First King Agamemnon flung mighty Odius, captain of the Halizoni,
+from his chariot. The spear of Agamemnon caught him on the broad
+of his back, just as he was turning in flight; it struck him
+between the shoulders and went right through his chest, and his
+armour rang rattling round him as he fell heavily to the ground.
+</para>
+
+<para>
+Then Idomeneus killed Phaesus, son of Borus the Meonian, who had
+come from Varne. Mighty Idomeneus speared him on the right
+shoulder as he was mounting his chariot, and the darkness of
+death enshrouded him as he fell heavily from the car.
+</para>
+
+<para>
+The squires of Idomeneus spoiled him of his armour, while
+Menelaus, son of Atreus, killed Scamandrius the son of Strophius,
+a mighty huntsman and keen lover of the chase. Diana herself had
+taught him how to kill every kind of wild creature that is bred
+in mountain forests, but neither she nor his famed skill in
+archery could now save him, for the spear of Menelaus struck him
+in the back as he was flying; it struck him between the shoulders
+and went right through his chest, so that he fell headlong and
+his armour rang rattling round him.
+</para>
+
+<para>
+Meriones then killed Phereclus the son of Tecton, who was the son
+of Hermon, a man whose hand was skilled in all manner of cunning
+workmanship, for Pallas Minerva had dearly loved him. He it was
+that made the ships for Alexandrus, which were the beginning of
+all mischief, and brought evil alike both on the Trojans and on
+Alexandrus himself; for he heeded not the decrees of heaven.
+Meriones overtook him as he was flying, and struck him on the
+right buttock. The point of the spear went through the bone into
+the bladder, and death came upon him as he cried aloud and fell
+forward on his knees.
+</para>
+
+<para>
+Meges, moreover, slew Pedaeus, son of Antenor, who, though he was
+a bastard, had been brought up by Theano as one of her own
+children, for the love she bore her husband. The son of Phyleus
+got close up to him and drove a spear into the nape of his neck:
+it went under his tongue all among his teeth, so he bit the cold
+bronze, and fell dead in the dust.
+</para>
+
+<para>
+And Eurypylus, son of Euaemon, killed Hypsenor, the son of noble
+Dolopion, who had been made priest of the river Scamander, and
+was honoured among the people as though he were a god. Eurypylus
+gave him chase as he was flying before him, smote him with his
+sword upon the arm, and lopped his strong hand from off it. The
+bloody hand fell to the ground, and the shades of death, with
+fate that no man can withstand, came over his eyes.
+</para>
+
+<para>
+Thus furiously did the battle rage between them. As for the son
+of Tydeus, you could not say whether he was more among the
+Achaeans or the Trojans. He rushed across the plain like a winter
+torrent that has burst its barrier in full flood; no dykes, no
+walls of fruitful vineyards can embank it when it is swollen with
+rain from heaven, but in a moment it comes tearing onward, and
+lays many a field waste that many a strong man's hand has
+reclaimed--even so were the dense phalanxes of the Trojans driven
+in rout by the son of Tydeus, and many though they were, they
+dared not abide his onslaught.
+</para>
+
+<para>
+Now when the son of Lycaon saw him scouring the plain and driving
+the Trojans pell-mell before him, he aimed an arrow and hit the
+front part of his cuirass near the shoulder: the arrow went right
+through the metal and pierced the flesh, so that the cuirass was
+covered with blood. On this the son of Lycaon shouted in triumph,
+"Knights Trojans, come on; the bravest of the Achaeans is
+wounded, and he will not hold out much longer if King Apollo was
+indeed with me when I sped from Lycia hither."
+</para>
+
+<para>
+Thus did he vaunt; but his arrow had not killed Diomed, who
+withdrew and made for the chariot and horses of Sthenelus, the
+son of Capaneus. "Dear son of Capaneus," said he, "come down from
+your chariot, and draw the arrow out of my shoulder."
+</para>
+
+<para>
+Sthenelus sprang from his chariot, and drew the arrow from the
+wound, whereon the blood came spouting out through the hole that
+had been made in his shirt. Then Diomed prayed, saying, "Hear me,
+daughter of aegis-bearing Jove, unweariable, if ever you loved my
+father well and stood by him in the thick of a fight, do the like
+now by me; grant me to come within a spear's throw of that man
+and kill him. He has been too quick for me and has wounded me;
+and now he is boasting that I shall not see the light of the sun
+much longer."
+</para>
+
+<para>
+Thus he prayed, and Pallas Minerva heard him; she made his limbs
+supple and quickened his hands and his feet. Then she went up
+close to him and said, "Fear not, Diomed, to do battle with the
+Trojans, for I have set in your heart the spirit of your knightly
+father Tydeus. Moreover, I have withdrawn the veil from your
+eyes, that you know gods and men apart. If, then, any other god
+comes here and offers you battle, do not fight him; but should
+Jove's daughter Venus come, strike her with your spear and wound
+her."
+</para>
+
+<para>
+When she had said this Minerva went away, and the son of Tydeus
+again took his place among the foremost fighters, three times
+more fierce even than he had been before. He was like a lion that
+some mountain shepherd has wounded, but not killed, as he is
+springing over the wall of a sheep-yard to attack the sheep. The
+shepherd has roused the brute to fury but cannot defend his
+flock, so he takes shelter under cover of the buildings, while
+the sheep, panic-stricken on being deserted, are smothered in
+heaps one on top of the other, and the angry lion leaps out over
+the sheep-yard wall. Even thus did Diomed go furiously about
+among the Trojans.
+</para>
+
+<para>
+He killed Astynous, and Hypeiron shepherd of his people, the one
+with a thrust of his spear, which struck him above the nipple,
+the other with a sword-cut on the collar-bone, that severed his
+shoulder from his neck and back. He let both of them lie, and
+went in pursuit of Abas and Polyidus, sons of the old reader of
+dreams Eurydamas: they never came back for him to read them any
+more dreams, for mighty Diomed made an end of them. He then gave
+chase to Xanthus and Thoon, the two sons of Phaenops, both of
+them very dear to him, for he was now worn out with age, and
+begat no more sons to inherit his possessions. But Diomed took
+both their lives and left their father sorrowing bitterly, for he
+nevermore saw them come home from battle alive, and his kinsmen
+divided his wealth among themselves.
+</para>
+
+<para>
+Then he came upon two sons of Priam, Echemmon and Chromius, as
+they were both in one chariot. He sprang upon them as a lion
+fastens on the neck of some cow or heifer when the herd is
+feeding in a coppice. For all their vain struggles he flung them
+both from their chariot and stripped the armour from their
+bodies. Then he gave their horses to his comrades to take them
+back to the ships.
+</para>
+
+<para>
+When Aeneas saw him thus making havoc among the ranks, he went
+through the fight amid the rain of spears to see if he could find
+Pandarus. When he had found the brave son of Lycaon he said,
+"Pandarus, where is now your bow, your winged arrows, and your
+renown as an archer, in respect of which no man here can rival
+you nor is there any in Lycia that can beat you? Lift then your
+hands to Jove and send an arrow at this fellow who is going so
+masterfully about, and has done such deadly work among the
+Trojans. He has killed many a brave man--unless indeed he is some
+god who is angry with the Trojans about their sacrifices, and and
+has set his hand against them in his displeasure."
+</para>
+
+<para>
+And the son of Lycaon answered, "Aeneas, I take him for none
+other than the son of Tydeus. I know him by his shield, the visor
+of his helmet, and by his horses. It is possible that he may be a
+god, but if he is the man I say he is, he is not making all this
+havoc without heaven's help, but has some god by his side who is
+shrouded in a cloud of darkness, and who turned my arrow aside
+when it had hit him. I have taken aim at him already and hit him
+on the right shoulder; my arrow went through the breastpiece of
+his cuirass; and I made sure I should send him hurrying to the
+world below, but it seems that I have not killed him. There must
+be a god who is angry with me. Moreover I have neither horse nor
+chariot. In my father's stables there are eleven excellent
+chariots, fresh from the builder, quite new, with cloths spread
+over them; and by each of them there stand a pair of horses,
+champing barley and rye; my old father Lycaon urged me again and
+again when I was at home and on the point of starting, to take
+chariots and horses with me that I might lead the Trojans in
+battle, but I would not listen to him; it would have been much
+better if I had done so, but I was thinking about the horses,
+which had been used to eat their fill, and I was afraid that in
+such a great gathering of men they might be ill-fed, so I left
+them at home and came on foot to Ilius armed only with my bow and
+arrows. These it seems, are of no use, for I have already hit two
+chieftains, the sons of Atreus and of Tydeus, and though I drew
+blood surely enough, I have only made them still more furious. I
+did ill to take my bow down from its peg on the day I led my band
+of Trojans to Ilius in Hector's service, and if ever I get home
+again to set eyes on my native place, my wife, and the greatness
+of my house, may some one cut my head off then and there if I do
+not break the bow and set it on a hot fire--such pranks as it
+plays me."
+</para>
+
+<para>
+Aeneas answered, "Say no more. Things will not mend till we two
+go against this man with chariot and horses and bring him to a
+trial of arms. Mount my chariot, and note how cleverly the horses
+of Tros can speed hither and thither over the plain in pursuit or
+flight. If Jove again vouchsafes glory to the son of Tydeus they
+will carry us safely back to the city. Take hold, then, of the
+whip and reins while I stand upon the car to fight, or else do
+you wait this man's onset while I look after the horses."
+</para>
+
+<para>
+"Aeneas," replied the son of Lycaon, "take the reins and drive;
+if we have to fly before the son of Tydeus the horses will go
+better for their own driver. If they miss the sound of your voice
+when they expect it they may be frightened, and refuse to take us
+out of the fight. The son of Tydeus will then kill both of us and
+take the horses. Therefore drive them yourself and I will be
+ready for him with my spear."
+</para>
+
+<para>
+They then mounted the chariot and drove full-speed towards the
+son of Tydeus. Sthenelus, son of Capaneus, saw them coming and
+said to Diomed, "Diomed, son of Tydeus, man after my own heart, I
+see two heroes speeding towards you, both of them men of might
+the one a skilful archer, Pandarus son of Lycaon, the other,
+Aeneas, whose sire is Anchises, while his mother is Venus. Mount
+the chariot and let us retreat. Do not, I pray you, press so
+furiously forward, or you may get killed."
+</para>
+
+<para>
+Diomed looked angrily at him and answered: "Talk not of flight,
+for I shall not listen to you: I am of a race that knows neither
+flight nor fear, and my limbs are as yet unwearied. I am in no
+mind to mount, but will go against them even as I am; Pallas
+Minerva bids me be afraid of no man, and even though one of them
+escape, their steeds shall not take both back again. I say
+further, and lay my saying to your heart--if Minerva sees fit to
+vouchsafe me the glory of killing both, stay your horses here and
+make the reins fast to the rim of the chariot; then be sure you
+spring Aeneas' horses and drive them from the Trojan to the
+Achaean ranks. They are of the stock that great Jove gave to Tros
+in payment for his son Ganymede, and are the finest that live and
+move under the sun. King Anchises stole the blood by putting his
+mares to them without Laomedon's knowledge, and they bore him six
+foals. Four are still in his stables, but he gave the other two
+to Aeneas. We shall win great glory if we can take them."
+</para>
+
+<para>
+Thus did they converse, but the other two had now driven close up
+to them, and the son of Lycaon spoke first. "Great and mighty
+son," said he, "of noble Tydeus, my arrow failed to lay you low,
+so I will now try with my spear."
+</para>
+
+<para>
+He poised his spear as he spoke and hurled it from him. It struck
+the shield of the son of Tydeus; the bronze point pierced it and
+passed on till it reached the breastplate. Thereon the son of
+Lycaon shouted out and said, "You are hit clean through the
+belly; you will not stand out for long, and the glory of the
+fight is mine."
+</para>
+
+<para>
+But Diomed all undismayed made answer, "You have missed, not hit,
+and before you two see the end of this matter one or other of you
+shall glut tough-shielded Mars with his blood."
+</para>
+
+<para>
+With this he hurled his spear, and Minerva guided it on to
+Pandarus's nose near the eye. It went crashing in among his white
+teeth; the bronze point cut through the root of his tongue,
+coming out under his chin, and his glistening armour rang
+rattling round him as he fell heavily to the ground. The horses
+started aside for fear, and he was reft of life and strength.
+</para>
+
+<para>
+Aeneas sprang from his chariot armed with shield and spear,
+fearing lest the Achaeans should carry off the body. He bestrode
+it as a lion in the pride of strength, with shield and spear
+before him and a cry of battle on his lips resolute to kill the
+first that should dare face him. But the son of Tydeus caught up
+a mighty stone, so huge and great that as men now are it would
+take two to lift it; nevertheless he bore it aloft with ease
+unaided, and with this he struck Aeneas on the groin where the
+hip turns in the joint that is called the "cup-bone." The stone
+crushed this joint, and broke both the sinews, while its jagged
+edges tore away all the flesh. The hero fell on his knees, and
+propped himself with his hand resting on the ground till the
+darkness of night fell upon his eyes. And now Aeneas, king of
+men, would have perished then and there, had not his mother,
+Jove's daughter Venus, who had conceived him by Anchises when he
+was herding cattle, been quick to mark, and thrown her two white
+arms about the body of her dear son. She protected him by
+covering him with a fold of her own fair garment, lest some
+Danaan should drive a spear into his breast and kill him.
+</para>
+
+<para>
+Thus, then, did she bear her dear son out of the fight. But the
+son of Capaneus was not unmindful of the orders that Diomed had
+given him. He made his own horses fast, away from the
+hurly-burly, by binding the reins to the rim of the chariot. Then
+he sprang upon Aeneas's horses and drove them from the Trojan to
+the Achaean ranks. When he had so done he gave them over to his
+chosen comrade Deipylus, whom he valued above all others as the
+one who was most like-minded with himself, to take them on to the
+ships. He then remounted his own chariot, seized the reins, and
+drove with all speed in search of the son of Tydeus.
+</para>
+
+<para>
+Now the son of Tydeus was in pursuit of the Cyprian goddess,
+spear in hand, for he knew her to be feeble and not one of those
+goddesses that can lord it among men in battle like Minerva or
+Enyo the waster of cities, and when at last after a long chase he
+caught her up, he flew at her and thrust his spear into the flesh
+of her delicate hand. The point tore through the ambrosial robe
+which the Graces had woven for her, and pierced the skin between
+her wrist and the palm of her hand, so that the immortal blood,
+or ichor, that flows in the veins of the blessed gods, came
+pouring from the wound; for the gods do not eat bread nor drink
+wine, hence they have no blood such as ours, and are immortal.
+Venus screamed aloud, and let her son fall, but Phoebus Apollo
+caught him in his arms, and hid him in a cloud of darkness, lest
+some Danaan should drive a spear into his breast and kill him;
+and Diomed shouted out as he left her, "Daughter of Jove, leave
+war and battle alone, can you not be contented with beguiling
+silly women? If you meddle with fighting you will get what will
+make you shudder at the very name of war."
+</para>
+
+<para>
+The goddess went dazed and discomfited away, and Iris, fleet as
+the wind, drew her from the throng, in pain and with her fair
+skin all besmirched. She found fierce Mars waiting on the left of
+the battle, with his spear and his two fleet steeds resting on a
+cloud; whereon she fell on her knees before her brother and
+implored him to let her have his horses. "Dear brother," she
+cried, "save me, and give me your horses to take me to Olympus
+where the gods dwell. I am badly wounded by a mortal, the son of
+Tydeus, who would now fight even with father Jove."
+</para>
+
+<para>
+Thus she spoke, and Mars gave her his gold-bedizened steeds. She
+mounted the chariot sick and sorry at heart, while Iris sat
+beside her and took the reins in her hand. She lashed her horses
+on and they flew forward nothing loth, till in a trice they were
+at high Olympus, where the gods have their dwelling. There she
+stayed them, unloosed them from the chariot, and gave them their
+ambrosial forage; but Venus flung herself on to the lap of her
+mother Dione, who threw her arms about her and caressed her,
+saying, "Which of the heavenly beings has been treating you in
+this way, as though you had been doing something wrong in the
+face of day?"
+</para>
+
+<para>
+And laughter-loving Venus answered, "Proud Diomed, the son of
+Tydeus, wounded me because I was bearing my dear son Aeneas, whom
+I love best of all mankind, out of the fight. The war is no
+longer one between Trojans and Achaeans, for the Danaans have now
+taken to fighting with the immortals."
+</para>
+
+<para>
+"Bear it, my child," replied Dione, "and make the best of it. We
+dwellers in Olympus have to put up with much at the hands of men,
+and we lay much suffering on one another. Mars had to suffer when
+Otus and Ephialtes, children of Aloeus, bound him in cruel bonds,
+so that he lay thirteen months imprisoned in a vessel of bronze.
+Mars would have then perished had not fair Eeriboea, stepmother
+to the sons of Aloeus, told Mercury, who stole him away when he
+was already well-nigh worn out by the severity of his bondage.
+Juno, again, suffered when the mighty son of Amphitryon wounded
+her on the right breast with a three-barbed arrow, and nothing
+could assuage her pain. So, also, did huge Hades, when this same
+man, the son of aegis-bearing Jove, hit him with an arrow even at
+the gates of hell, and hurt him badly. Thereon Hades went to the
+house of Jove on great Olympus, angry and full of pain; and the
+arrow in his brawny shoulder caused him great anguish till Paeeon
+healed him by spreading soothing herbs on the wound, for Hades
+was not of mortal mould. Daring, head-strong, evildoer who recked
+not of his sin in shooting the gods that dwell in Olympus. And
+now Minerva has egged this son of Tydeus on against yourself,
+fool that he is for not reflecting that no man who fights with
+gods will live long or hear his children prattling about his
+knees when he returns from battle. Let, then, the son of Tydeus
+see that he does not have to fight with one who is stronger than
+you are. Then shall his brave wife Aegialeia, daughter of
+Adrestus, rouse her whole house from sleep, wailing for the loss
+of her wedded lord, Diomed the bravest of the Achaeans."
+</para>
+
+<para>
+So saying, she wiped the ichor from the wrist of her daughter
+with both hands, whereon the pain left her, and her hand was
+healed. But Minerva and Juno, who were looking on, began to taunt
+Jove with their mocking talk, and Minerva was first to speak.
+"Father Jove," said she, "do not be angry with me, but I think
+the Cyprian must have been persuading some one of the Achaean
+women to go with the Trojans of whom she is so very fond, and
+while caressing one or other of them she must have torn her
+delicate hand with the gold pin of the woman's brooch."
+</para>
+
+<para>
+The sire of gods and men smiled, and called golden Venus to his
+side. "My child," said he, "it has not been given you to be a
+warrior. Attend, henceforth, to your own delightful matrimonial
+duties, and leave all this fighting to Mars and to Minerva."
+</para>
+
+<para>
+Thus did they converse. But Diomed sprang upon Aeneas, though he
+knew him to be in the very arms of Apollo. Not one whit did he
+fear the mighty god, so set was he on killing Aeneas and
+stripping him of his armour. Thrice did he spring forward with
+might and main to slay him, and thrice did Apollo beat back his
+gleaming shield. When he was coming on for the fourth time, as
+though he were a god, Apollo shouted to him with an awful voice
+and said, "Take heed, son of Tydeus, and draw off; think not to
+match yourself against gods, for men that walk the earth cannot
+hold their own with the immortals."
+</para>
+
+<para>
+The son of Tydeus then gave way for a little space, to avoid the
+anger of the god, while Apollo took Aeneas out of the crowd and
+set him in sacred Pergamus, where his temple stood. There, within
+the mighty sanctuary, Latona and Diana healed him and made him
+glorious to behold, while Apollo of the silver bow fashioned a
+wraith in the likeness of Aeneas, and armed as he was. Round this
+the Trojans and Achaeans hacked at the bucklers about one
+another's breasts, hewing each other's round shields and light
+hide-covered targets. Then Phoebus Apollo said to Mars, "Mars,
+Mars, bane of men, blood-stained stormer of cities, can you not
+go to this man, the son of Tydeus, who would now fight even with
+father Jove, and draw him out of the battle? He first went up to
+the Cyprian and wounded her in the hand near her wrist, and
+afterwards sprang upon me too, as though he were a god."
+</para>
+
+<para>
+He then took his seat on the top of Pergamus, while murderous
+Mars went about among the ranks of the Trojans, cheering them on,
+in the likeness of fleet Acamas chief of the Thracians. "Sons of
+Priam," said he, "how long will you let your people be thus
+slaughtered by the Achaeans? Would you wait till they are at the
+walls of Troy? Aeneas the son of Anchises has fallen, he whom we
+held in as high honour as Hector himself. Help me, then, to
+rescue our brave comrade from the stress of the fight."
+</para>
+
+<para>
+With these words he put heart and soul into them all. Then
+Sarpedon rebuked Hector very sternly. "Hector," said he, "where
+is your prowess now? You used to say that though you had neither
+people nor allies you could hold the town alone with your
+brothers and brothers-in-law. I see not one of them here; they
+cower as hounds before a lion; it is we, your allies, who bear
+the brunt of the battle. I have come from afar, even from Lycia
+and the banks of the river Xanthus, where I have left my wife, my
+infant son, and much wealth to tempt whoever is needy;
+nevertheless, I head my Lycian soldiers and stand my ground
+against any who would fight me though I have nothing here for the
+Achaeans to plunder, while you look on, without even bidding your
+men stand firm in defence of their wives. See that you fall not
+into the hands of your foes as men caught in the meshes of a net,
+and they sack your fair city forthwith. Keep this before your
+mind night and day, and beseech the captains of your allies to
+hold on without flinching, and thus put away their reproaches
+from you."
+</para>
+
+<para>
+So spoke Sarpedon, and Hector smarted under his words. He sprang
+from his chariot clad in his suit of armour, and went about among
+the host brandishing his two spears, exhorting the men to fight
+and raising the terrible cry of battle. Then they rallied and
+again faced the Achaeans, but the Argives stood compact and firm,
+and were not driven back. As the breezes sport with the chaff
+upon some goodly threshing-floor, when men are winnowing--while
+yellow Ceres blows with the wind to sift the chaff from the
+grain, and the chaff-heaps grow whiter and whiter--even so did
+the Achaeans whiten in the dust which the horses' hoofs raised to
+the firmament of heaven, as their drivers turned them back to
+battle, and they bore down with might upon the foe. Fierce Mars,
+to help the Trojans, covered them in a veil of darkness, and went
+about everywhere among them, inasmuch as Phoebus Apollo had told
+him that when he saw Pallas, Minerva leave the fray he was to put
+courage into the hearts of the Trojans--for it was she who was
+helping the Danaans. Then Apollo sent Aeneas forth from his rich
+sanctuary, and filled his heart with valour, whereon he took his
+place among his comrades, who were overjoyed at seeing him alive,
+sound, and of a good courage; but they could not ask him how it
+had all happened, for they were too busy with the turmoil raised
+by Mars and by Strife, who raged insatiably in their midst.
+</para>
+
+<para>
+The two Ajaxes, Ulysses and Diomed, cheered the Danaans on,
+fearless of the fury and onset of the Trojans. They stood as
+still as clouds which the son of Saturn has spread upon the
+mountain tops when there is no air and fierce Boreas sleeps with
+the other boisterous winds whose shrill blasts scatter the clouds
+in all directions--even so did the Danaans stand firm and
+unflinching against the Trojans. The son of Atreus went about
+among them and exhorted them. "My friends," said he, "quit
+yourselves like brave men, and shun dishonour in one another's
+eyes amid the stress of battle. They that shun dishonour more
+often live than get killed, but they that fly save neither life
+nor name."
+</para>
+
+<para>
+As he spoke he hurled his spear and hit one of those who were in
+the front rank, the comrade of Aeneas, Deicoon son of Pergasus,
+whom the Trojans held in no less honour than the sons of Priam,
+for he was ever quick to place himself among the foremost. The
+spear of King Agamemnon struck his shield and went right through
+it, for the shield stayed it not. It drove through his belt into
+the lower part of his belly, and his armour rang rattling round
+him as he fell heavily to the ground.
+</para>
+
+<para>
+Then Aeneas killed two champions of the Danaans, Crethon and
+Orsilochus. Their father was a rich man who lived in the strong
+city of Phere and was descended from the river Alpheus, whose
+broad stream flows through the land of the Pylians. The river
+begat Orsilochus, who ruled over much people and was father to
+Diocles, who in his turn begat twin sons, Crethon and Orsilochus,
+well skilled in all the arts of war. These, when they grew up,
+went to Ilius with the Argive fleet in the cause of Menelaus and
+Agamemnon sons of Atreus, and there they both of them fell. As
+two lions whom their dam has reared in the depths of some
+mountain forest to plunder homesteads and carry off sheep and
+cattle till they get killed by the hand of man, so were these two
+vanquished by Aeneas, and fell like high pine-trees to the
+ground.
+</para>
+
+<para>
+Brave Menelaus pitied them in their fall, and made his way to the
+front, clad in gleaming bronze and brandishing his spear, for
+Mars egged him on to do so with intent that he should be killed
+by Aeneas; but Antilochus the son of Nestor saw him and sprang
+forward, fearing that the king might come to harm and thus bring
+all their labour to nothing; when, therefore Aeneas and Menelaus
+were setting their hands and spears against one another eager to
+do battle, Antilochus placed himself by the side of Menelaus.
+Aeneas, bold though he was, drew back on seeing the two heroes
+side by side in front of him, so they drew the bodies of Crethon
+and Orsilochus to the ranks of the Achaeans and committed the two
+poor fellows into the hands of their comrades. They then turned
+back and fought in the front ranks.
+</para>
+
+<para>
+They killed Pylaemenes peer of Mars, leader of the Paphlagonian
+warriors. Menelaus struck him on the collar-bone as he was
+standing on his chariot, while Antilochus hit his charioteer and
+squire Mydon, the son of Atymnius, who was turning his horses in
+flight. He hit him with a stone upon the elbow, and the reins,
+enriched with white ivory, fell from his hands into the dust.
+Antilochus rushed towards him and struck him on the temples with
+his sword, whereon he fell head first from the chariot to the
+ground. There he stood for a while with his head and shoulders
+buried deep in the dust--for he had fallen on sandy soil till his
+horses kicked him and laid him flat on the ground, as Antilochus
+lashed them and drove them off to the host of the Achaeans.
+</para>
+
+<para>
+But Hector marked them from across the ranks, and with a loud cry
+rushed towards them, followed by the strong battalions of the
+Trojans. Mars and dread Enyo led them on, she fraught with
+ruthless turmoil of battle, while Mars wielded a monstrous spear,
+and went about, now in front of Hector and now behind him.
+</para>
+
+<para>
+Diomed shook with passion as he saw them. As a man crossing a
+wide plain is dismayed to find himself on the brink of some great
+river rolling swiftly to the sea--he sees its boiling waters and
+starts back in fear--even so did the son of Tydeus give ground.
+Then he said to his men, "My friends, how can we wonder that
+Hector wields the spear so well? Some god is ever by his side to
+protect him, and now Mars is with him in the likeness of mortal
+man. Keep your faces therefore towards the Trojans, but give
+ground backwards, for we dare not fight with gods."
+</para>
+
+<para>
+As he spoke the Trojans drew close up, and Hector killed two men,
+both in one chariot, Menesthes and Anchialus, heroes well versed
+in war. Ajax son of Telamon pitied them in their fall; he came
+close up and hurled his spear, hitting Amphius the son of
+Selagus, a man of great wealth who lived in Paesus and owned much
+corn-growing land, but his lot had led him to come to the aid of
+Priam and his sons. Ajax struck him in the belt; the spear
+pierced the lower part of his belly, and he fell heavily to the
+ground. Then Ajax ran towards him to strip him of his armour, but
+the Trojans rained spears upon him, many of which fell upon his
+shield. He planted his heel upon the body and drew out his spear,
+but the darts pressed so heavily upon him that he could not strip
+the goodly armour from his shoulders. The Trojan chieftains,
+moreover, many and valiant, came about him with their spears, so
+that he dared not stay; great, brave and valiant though he was,
+they drove him from them and he was beaten back.
+</para>
+
+<para>
+Thus, then, did the battle rage between them. Presently the
+strong hand of fate impelled Tlepolemus, the son of Hercules, a
+man both brave and of great stature, to fight Sarpedon; so the
+two, son and grandson of great Jove, drew near to one another,
+and Tlepolemus spoke first. "Sarpedon," said he, "councillor of
+the Lycians, why should you come skulking here you who are a man
+of peace? They lie who call you son of aegis-bearing Jove, for
+you are little like those who were of old his children. Far other
+was Hercules, my own brave and lion-hearted father, who came here
+for the horses of Laomedon, and though he had six ships only, and
+few men to follow him, sacked the city of Ilius and made a
+wilderness of her highways. You are a coward, and your people are
+falling from you. For all your strength, and all your coming from
+Lycia, you will be no help to the Trojans but will pass the gates
+of Hades vanquished by my hand."
+</para>
+
+<para>
+And Sarpedon, captain of the Lycians, answered, "Tlepolemus, your
+father overthrew Ilius by reason of Laomedon's folly in refusing
+payment to one who had served him well. He would not give your
+father the horses which he had come so far to fetch. As for
+yourself, you shall meet death by my spear. You shall yield glory
+to myself, and your soul to Hades of the noble steeds."
+</para>
+
+<para>
+Thus spoke Sarpedon, and Tlepolemus upraised his spear. They
+threw at the same moment, and Sarpedon struck his foe in the
+middle of his throat; the spear went right through, and the
+darkness of death fell upon his eyes. Tlepolemus's spear struck
+Sarpedon on the left thigh with such force that it tore through
+the flesh and grazed the bone, but his father as yet warded off
+destruction from him.
+</para>
+
+<para>
+His comrades bore Sarpedon out of the fight, in great pain by the
+weight of the spear that was dragging from his wound. They were
+in such haste and stress as they bore him that no one thought of
+drawing the spear from his thigh so as to let him walk uprightly.
+Meanwhile the Achaeans carried off the body of Tlepolemus,
+whereon Ulysses was moved to pity, and panted for the fray as he
+beheld them. He doubted whether to pursue the son of Jove, or to
+make slaughter of the Lycian rank and file; it was not decreed,
+however, that he should slay the son of Jove; Minerva, therefore,
+turned him against the main body of the Lycians. He killed
+Coeranus, Alastor, Chromius, Alcandrus, Halius, Noemon, and
+Prytanis, and would have slain yet more, had not great Hector
+marked him, and sped to the front of the fight clad in his suit
+of mail, filling the Danaans with terror. Sarpedon was glad when
+he saw him coming, and besought him, saying, "Son of Priam, let
+me not be here to fall into the hands of the Danaans. Help me,
+and since I may not return home to gladden the hearts of my wife
+and of my infant son, let me die within the walls of your city."
+</para>
+
+<para>
+Hector made him no answer, but rushed onward to fall at once upon
+the Achaeans and kill many among them. His comrades then bore
+Sarpedon away and laid him beneath Jove's spreading oak tree.
+Pelagon, his friend and comrade, drew the spear out of his thigh,
+but Sarpedon fainted and a mist came over his eyes. Presently he
+came to himself again, for the breath of the north wind as it
+played upon him gave him new life, and brought him out of the
+deep swoon into which he had fallen.
+</para>
+
+<para>
+Meanwhile the Argives were neither driven towards their ships by
+Mars and Hector, nor yet did they attack them; when they knew
+that Mars was with the Trojans they retreated, but kept their
+faces still turned towards the foe. Who, then, was first and who
+last to be slain by Mars and Hector? They were valiant Teuthras,
+and Orestes the renowned charioteer, Trechus the Aetolian
+warrior, Oenomaus, Helenus the son of Oenops, and Oresbius of the
+gleaming girdle, who was possessed of great wealth, and dwelt by
+the Cephisian lake with the other Boeotians who lived near him,
+owners of a fertile country.
+</para>
+
+<para>
+Now when the goddess Juno saw the Argives thus falling, she said
+to Minerva, "Alas, daughter of aegis-bearing Jove, unweariable,
+the promise we made Menelaus that he should not return till he
+had sacked the city of Ilius will be of no effect if we let Mars
+rage thus furiously. Let us go into the fray at once."
+</para>
+
+<para>
+Minerva did not gainsay her. Thereon the august goddess, daughter
+of great Saturn, began to harness her gold-bedizened steeds. Hebe
+with all speed fitted on the eight-spoked wheels of bronze that
+were on either side of the iron axle-tree. The felloes of the
+wheels were of gold, imperishable, and over these there was a
+tire of bronze, wondrous to behold. The naves of the wheels were
+silver, turning round the axle upon either side. The car itself
+was made with plaited bands of gold and silver, and it had a
+double top-rail running all round it. From the body of the car
+there went a pole of silver, on to the end of which she bound the
+golden yoke, with the bands of gold that were to go under the
+necks of the horses Then Juno put her steeds under the yoke,
+eager for battle and the war-cry.
+</para>
+
+<para>
+Meanwhile Minerva flung her richly embroidered vesture, made with
+her own hands, on to her father's threshold, and donned the shirt
+of Jove, arming herself for battle. She threw her tasselled aegis
+about her shoulders, wreathed round with Rout as with a fringe,
+and on it were Strife, and Strength, and Panic whose blood runs
+cold; moreover there was the head of the dread monster Gorgon,
+grim and awful to behold, portent of aegis-bearing Jove. On her
+head she set her helmet of gold, with four plumes, and coming to
+a peak both in front and behind--decked with the emblems of a
+hundred cities; then she stepped into her flaming chariot and
+grasped the spear, so stout and sturdy and strong, with which she
+quells the ranks of heroes who have displeased her. Juno lashed
+the horses on, and the gates of heaven bellowed as they flew open
+of their own accord--gates over which the Hours preside, in whose
+hands are Heaven and Olympus, either to open the dense cloud that
+hides them, or to close it. Through these the goddesses drove
+their obedient steeds, and found the son of Saturn sitting all
+alone on the topmost ridges of Olympus. There Juno stayed her
+horses, and spoke to Jove the son of Saturn, lord of all. "Father
+Jove," said she, "are you not angry with Mars for these high
+doings? how great and goodly a host of the Achaeans he has
+destroyed to my great grief, and without either right or reason,
+while the Cyprian and Apollo are enjoying it all at their ease
+and setting this unrighteous madman on to do further mischief. I
+hope, Father Jove, that you will not be angry if I hit Mars hard,
+and chase him out of the battle."
+</para>
+
+<para>
+And Jove answered, "Set Minerva on to him, for she punishes him
+more often than any one else does."
+</para>
+
+<para>
+Juno did as he had said. She lashed her horses, and they flew
+forward nothing loth midway betwixt earth and sky. As far as a
+man can see when he looks out upon the sea from some high beacon,
+so far can the loud-neighing horses of the gods spring at a
+single bound. When they reached Troy and the place where its two
+flowing streams Simois and Scamander meet, there Juno stayed them
+and took them from the chariot. She hid them in a thick cloud,
+and Simois made ambrosia spring up for them to eat; the two
+goddesses then went on, flying like turtledoves in their
+eagerness to help the Argives. When they came to the part where
+the bravest and most in number were gathered about mighty Diomed,
+fighting like lions or wild boars of great strength and
+endurance, there Juno stood still and raised a shout like that of
+brazen-voiced Stentor, whose cry was as loud as that of fifty men
+together. "Argives," she cried; "shame on cowardly creatures,
+brave in semblance only; as long as Achilles was fighting, if his
+spear was so deadly that the Trojans dared not show themselves
+outside the Dardanian gates, but now they sally far from the city
+and fight even at your ships."
+</para>
+
+<para>
+With these words she put heart and soul into them all, while
+Minerva sprang to the side of the son of Tydeus, whom she found
+near his chariot and horses, cooling the wound that Pandarus had
+given him. For the sweat caused by the hand that bore the weight
+of his shield irritated the hurt: his arm was weary with pain,
+and he was lifting up the strap to wipe away the blood. The
+goddess laid her hand on the yoke of his horses and said, "The
+son of Tydeus is not such another as his father. Tydeus was a
+little man, but he could fight, and rushed madly into the fray
+even when I told him not to do so. When he went all unattended as
+envoy to the city of Thebes among the Cadmeans, I bade him feast
+in their houses and be at peace; but with that high spirit which
+was ever present with him, he challenged the youth of the
+Cadmeans, and at once beat them in all that he attempted, so
+mightily did I help him. I stand by you too to protect you, and I
+bid you be instant in fighting the Trojans; but either you are
+tired out, or you are afraid and out of heart, and in that case I
+say that you are no true son of Tydeus the son of Oeneus."
+</para>
+
+<para>
+Diomed answered, "I know you, goddess, daughter of aegis-bearing
+Jove, and will hide nothing from you. I am not afraid nor out of
+heart, nor is there any slackness in me. I am only following your
+own instructions; you told me not to fight any of the blessed
+gods; but if Jove's daughter Venus came into battle I was to
+wound her with my spear. Therefore I am retreating, and bidding
+the other Argives gather in this place, for I know that Mars is
+now lording it in the field."
+</para>
+
+<para>
+"Diomed, son of Tydeus," replied Minerva, "man after my own
+heart, fear neither Mars nor any other of the immortals, for I
+will befriend you. Nay, drive straight at Mars, and smite him in
+close combat; fear not this raging madman, villain incarnate,
+first on one side and then on the other. But now he was holding
+talk with Juno and myself, saying he would help the Argives and
+attack the Trojans; nevertheless he is with the Trojans, and has
+forgotten the Argives."
+</para>
+
+<para>
+With this she caught hold of Sthenelus and lifted him off the
+chariot on to the ground. In a second he was on the ground,
+whereupon the goddess mounted the car and placed herself by the
+side of Diomed. The oaken axle groaned aloud under the burden of
+the awful goddess and the hero; Pallas Minerva took the whip and
+reins, and drove straight at Mars. He was in the act of stripping
+huge Periphas, son of Ochesius and bravest of the Aetolians.
+Bloody Mars was stripping him of his armour, and Minerva donned
+the helmet of Hades, that he might not see her; when, therefore,
+he saw Diomed, he made straight for him and let Periphas lie
+where he had fallen. As soon as they were at close quarters he
+let fly with his bronze spear over the reins and yoke, thinking
+to take Diomed's life, but Minerva caught the spear in her hand
+and made it fly harmlessly over the chariot. Diomed then threw,
+and Pallas Minerva drove the spear into the pit of Mars's stomach
+where his under-girdle went round him. There Diomed wounded him,
+tearing his fair flesh and then drawing his spear out again. Mars
+roared as loudly as nine or ten thousand men in the thick of a
+fight, and the Achaeans and Trojans were struck with panic, so
+terrible was the cry he raised.
+</para>
+
+<para>
+As a dark cloud in the sky when it comes on to blow after heat,
+even so did Diomed son of Tydeus see Mars ascend into the broad
+heavens. With all speed he reached high Olympus, home of the
+gods, and in great pain sat down beside Jove the son of Saturn.
+He showed Jove the immortal blood that was flowing from his
+wound, and spoke piteously, saying, "Father Jove, are you not
+angered by such doings? We gods are continually suffering in the
+most cruel manner at one another's hands while helping mortals;
+and we all owe you a grudge for having begotten that mad
+termagant of a daughter, who is always committing outrage of some
+kind. We other gods must all do as you bid us, but her you
+neither scold nor punish; you encourage her because the pestilent
+creature is your daughter. See how she has been inciting proud
+Diomed to vent his rage on the immortal gods. First he went up to
+the Cyprian and wounded her in the hand near her wrist, and then
+he sprang upon me too as though he were a god. Had I not run for
+it I must either have lain there for long enough in torments
+among the ghastly corpes, or have been eaten alive with spears
+till I had no more strength left in me."
+</para>
+
+<para>
+Jove looked angrily at him and said, "Do not come whining here,
+Sir Facing-both-ways. I hate you worst of all the gods in
+Olympus, for you are ever fighting and making mischief. You have
+the intolerable and stubborn spirit of your mother Juno: it is
+all I can do to manage her, and it is her doing that you are now
+in this plight: still, I cannot let you remain longer in such
+great pain; you are my own offspring, and it was by me that your
+mother conceived you; if, however, you had been the son of any
+other god, you are so destructive that by this time you should
+have been lying lower than the Titans."
+</para>
+
+<para>
+He then bade Paeeon heal him, whereon Paeeon spread pain-killing
+herbs upon his wound and cured him, for he was not of mortal
+mould. As the juice of the fig-tree curdles milk, and thickens it
+in a moment though it is liquid, even so instantly did Paeeon
+cure fierce Mars. Then Hebe washed him, and clothed him in goodly
+raiment, and he took his seat by his father Jove all glorious to
+behold.
+</para>
+
+<para>
+But Juno of Argos and Minerva of Alalcomene, now that they had
+put a stop to the murderous doings of Mars, went back again to
+the house of Jove.
+</para>
+</chapter>
+
+<chapter>
+<title>BOOK VI</title>
+
+<para>
+THE fight between Trojans and Achaeans was now left to rage as it
+would, and the tide of war surged hither and thither over the
+plain as they aimed their bronze-shod spears at one another
+between the streams of Simois and Xanthus.
+</para>
+
+<para>
+First, Ajax son of Telamon, tower of strength to the Achaeans,
+broke a phalanx of the Trojans, and came to the assistance of his
+comrades by killing Acamas son of Eussorus, the best man among
+the Thracians, being both brave and of great stature. The spear
+struck the projecting peak of his helmet: its bronze point then
+went through his forehead into the brain, and darkness veiled his
+eyes.
+</para>
+
+<para>
+Then Diomed killed Axylus son of Teuthranus, a rich man who lived
+in the strong city of Arisbe, and was beloved by all men; for he
+had a house by the roadside, and entertained every one who
+passed; howbeit not one of his guests stood before him to save
+his life, and Diomed killed both him and his squire Calesius, who
+was then his charioteer--so the pair passed beneath the earth.
+</para>
+
+<para>
+Euryalus killed Dresus and Opheltius, and then went in pursuit of
+Aesepus and Pedasus, whom the naiad nymph Abarbarea had borne to
+noble Bucolion. Bucolion was eldest son to Laomedon, but he was a
+bastard. While tending his sheep he had converse with the nymph,
+and she conceived twin sons; these the son of Mecisteus now slew,
+and he stripped the armour from their shoulders. Polypoetes then
+killed Astyalus, Ulysses Pidytes of Percote, and Teucer Aretaon.
+Ablerus fell by the spear of Nestor's son Antilochus, and
+Agamemnon, king of men, killed Elatus who dwelt in Pedasus by the
+banks of the river Satnioeis. Leitus killed Phylacus as he was
+flying, and Eurypylus slew Melanthus.
+</para>
+
+<para>
+Then Menelaus of the loud war-cry took Adrestus alive, for his
+horses ran into a tamarisk bush, as they were flying wildly over
+the plain, and broke the pole from the car; they went on towards
+the city along with the others in full flight, but Adrestus
+rolled out, and fell in the dust flat on his face by the wheel of
+his chariot; Menelaus came up to him spear in hand, but Adrestus
+caught him by the knees begging for his life. "Take me alive," he
+cried, "son of Atreus, and you shall have a full ransom for me:
+my father is rich and has much treasure of gold, bronze, and
+wrought iron laid by in his house. From this store he will give
+you a large ransom should he hear of my being alive and at the
+ships of the Achaeans."
+</para>
+
+<para>
+Thus did he plead, and Menelaus was for yielding and giving him
+to a squire to take to the ships of the Achaeans, but Agamemnon
+came running up to him and rebuked him. "My good Menelaus," said
+he, "this is no time for giving quarter. Has, then, your house
+fared so well at the hands of the Trojans? Let us not spare a
+single one of them--not even the child unborn and in its mother's
+womb; let not a man of them be left alive, but let all in Ilius
+perish, unheeded and forgotten."
+</para>
+
+<para>
+Thus did he speak, and his brother was persuaded by him, for his
+words were just. Menelaus, therefore, thrust Adrestus from him,
+whereon King Agamemnon struck him in the flank, and he fell: then
+the son of Atreus planted his foot upon his breast to draw his
+spear from the body.
+</para>
+
+<para>
+Meanwhile Nestor shouted to the Argives, saying, "My friends,
+Danaan warriors, servants of Mars, let no man lag that he may
+spoil the dead, and bring back much booty to the ships. Let us
+kill as many as we can; the bodies will lie upon the plain, and
+you can despoil them later at your leisure."
+</para>
+
+<para>
+With these words he put heart and soul into them all. And now the
+Trojans would have been routed and driven back into Ilius, had
+not Priam's son Helenus, wisest of augurs, said to Hector and
+Aeneas, "Hector and Aeneas, you two are the mainstays of the
+Trojans and Lycians, for you are foremost at all times, alike in
+fight and counsel; hold your ground here, and go about among the
+host to rally them in front of the gates, or they will fling
+themselves into the arms of their wives, to the great joy of our
+foes. Then, when you have put heart into all our companies, we
+will stand firm here and fight the Danaans however hard they
+press us, for there is nothing else to be done. Meanwhile do you,
+Hector, go to the city and tell our mother what is happening.
+Tell her to bid the matrons gather at the temple of Minerva in
+the acropolis; let her then take her key and open the doors of
+the sacred building; there, upon the knees of Minerva, let her
+lay the largest, fairest robe she has in her house--the one she
+sets most store by; let her, moreover, promise to sacrifice
+twelve yearling heifers that have never yet felt the goad, in the
+temple of the goddess, if she will take pity on the town, with
+the wives and little ones of the Trojans, and keep the son of
+Tydeus from falling on the goodly city of Ilius; for he fights
+with fury and fills men's souls with panic. I hold him mightiest
+of them all; we did not fear even their great champion Achilles,
+son of a goddess though he be, as we do this man: his rage is
+beyond all bounds, and there is none can vie with him in prowess"
+</para>
+
+<para>
+Hector did as his brother bade him. He sprang from his chariot,
+and went about everywhere among the host, brandishing his spears,
+urging the men on to fight, and raising the dread cry of battle.
+Thereon they rallied and again faced the Achaeans, who gave
+ground and ceased their murderous onset, for they deemed that
+some one of the immortals had come down from starry heaven to
+help the Trojans, so strangely had they rallied. And Hector
+shouted to the Trojans, "Trojans and allies, be men, my friends,
+and fight with might and main, while I go to Ilius and tell the
+old men of our council and our wives to pray to the gods and vow
+hecatombs in their honour."
+</para>
+
+<para>
+With this he went his way, and the black rim of hide that went
+round his shield beat against his neck and his ancles.
+</para>
+
+<para>
+Then Glaucus son of Hippolochus, and the son of Tydeus went into
+the open space between the hosts to fight in single combat. When
+they were close up to one another Diomed of the loud war-cry was
+the first to speak. "Who, my good sir," said he, "who are you
+among men? I have never seen you in battle until now, but you are
+daring beyond all others if you abide my onset. Woe to those
+fathers whose sons face my might. If, however, you are one of the
+immortals and have come down from heaven, I will not fight you;
+for even valiant Lycurgus, son of Dryas, did not live long when
+he took to fighting with the gods. He it was that drove the
+nursing women who were in charge of frenzied Bacchus through the
+land of Nysa, and they flung their thyrsi on the ground as
+murderous Lycurgus beat them with his oxgoad. Bacchus himself
+plunged terror-stricken into the sea, and Thetis took him to her
+bosom to comfort him, for he was scared by the fury with which
+the man reviled him. Thereon the gods who live at ease were angry
+with Lycurgus and the son of Saturn struck him blind, nor did he
+live much longer after he had become hateful to the immortals.
+Therefore I will not fight with the blessed gods; but if you are
+of them that eat the fruit of the ground, draw near and meet your
+doom."
+</para>
+
+<para>
+And the son of Hippolochus answered, son of Tydeus, why ask me of
+my lineage? Men come and go as leaves year by year upon the
+trees. Those of autumn the wind sheds upon the ground, but when
+spring returns the forest buds forth with fresh vines. Even so is
+it with the generations of mankind, the new spring up as the old
+are passing away. If, then, you would learn my descent, it is one
+that is well known to many. There is a city in the heart of
+Argos, pasture land of horses, called Ephyra, where Sisyphus
+lived, who was the craftiest of all mankind. He was the son of
+Aeolus, and had a son named Glaucus, who was father to
+Bellerophon, whom heaven endowed with the most surpassing
+comeliness and beauty. But Proetus devised his ruin, and being
+stronger than he, drove him from the land of the Argives, over
+which Jove had made him ruler. For Antea, wife of Proetus, lusted
+after him, and would have had him lie with her in secret; but
+Bellerophon was an honourable man and would not, so she told lies
+about him to Proteus. 'Proetus,' said she, 'kill Bellerophon or
+die, for he would have had converse with me against my will.' The
+king was angered, but shrank from killing Bellerophon, so he sent
+him to Lycia with lying letters of introduction, written on a
+folded tablet, and containing much ill against the bearer. He
+bade Bellerophon show these letters to his father-in-law, to the
+end that he might thus perish; Bellerophon therefore went to
+Lycia, and the gods convoyed him safely.
+</para>
+
+<para>
+"When he reached the river Xanthus, which is in Lycia, the king
+received him with all goodwill, feasted him nine days, and killed
+nine heifers in his honour, but when rosy-fingered morning
+appeared upon the tenth day, he questioned him and desired to see
+the letter from his son-in-law Proetus. When he had received the
+wicked letter he first commanded Bellerophon to kill that savage
+monster, the Chimaera, who was not a human being, but a goddess,
+for she had the head of a lion and the tail of a serpent, while
+her body was that of a goat, and she breathed forth flames of
+fire; but Bellerophon slew her, for he was guided by signs from
+heaven. He next fought the far-famed Solymi, and this, he said,
+was the hardest of all his battles. Thirdly, he killed the
+Amazons, women who were the peers of men, and as he was returning
+thence the king devised yet another plan for his destruction; he
+picked the bravest warriors in all Lycia, and placed them in
+ambuscade, but not a man ever came back, for Bellerophon killed
+every one of them. Then the king knew that he must be the valiant
+offspring of a god, so he kept him in Lycia, gave him his
+daughter in marriage, and made him of equal honour in the kingdom
+with himself; and the Lycians gave him a piece of land, the best
+in all the country, fair with vineyards and tilled fields, to
+have and to hold.
+</para>
+
+<para>
+"The king's daughter bore Bellerophon three children, Isander,
+Hippolochus, and Laodameia. Jove, the lord of counsel, lay with
+Laodameia, and she bore him noble Sarpedon; but when Bellerophon
+came to be hated by all the gods, he wandered all desolate and
+dismayed upon the Alean plain, gnawing at his own heart, and
+shunning the path of man. Mars, insatiate of battle, killed his
+son Isander while he was fighting the Solymi; his daughter was
+killed by Diana of the golden reins, for she was angered with
+her; but Hippolochus was father to myself, and when he sent me to
+Troy he urged me again and again to fight ever among the foremost
+and outvie my peers, so as not to shame the blood of my fathers
+who were the noblest in Ephyra and in all Lycia. This, then, is
+the descent I claim."
+</para>
+
+<para>
+Thus did he speak, and the heart of Diomed was glad. He planted
+his spear in the ground, and spoke to him with friendly words.
+"Then," he said, "you are an old friend of my father's house.
+Great Oeneus once entertained Bellerophon for twenty days, and
+the two exchanged presents. Oeneus gave a belt rich with purple,
+and Bellerophon a double cup, which I left at home when I set out
+for Troy. I do not remember Tydeus, for he was taken from us
+while I was yet a child, when the army of the Achaeans was cut to
+pieces before Thebes. Henceforth, however, I must be your host in
+middle Argos, and you mine in Lycia, if I should ever go there;
+let us avoid one another's spears even during a general
+engagement; there are many noble Trojans and allies whom I can
+kill, if I overtake them and heaven delivers them into my hand;
+so again with yourself, there are many Achaeans whose lives you
+may take if you can; we two, then, will exchange armour, that all
+present may know of the old ties that subsist between us."
+</para>
+
+<para>
+With these words they sprang from their chariots, grasped one
+another's hands, and plighted friendship. But the son of Saturn
+made Glaucus take leave of his wits, for he exchanged golden
+armour for bronze, the worth of a hundred head of cattle for the
+worth of nine.
+</para>
+
+<para>
+Now when Hector reached the Scaean gates and the oak tree, the
+wives and daughters of the Trojans came running towards him to
+ask after their sons, brothers, kinsmen, and husbands: he told
+them to set about praying to the gods, and many were made
+sorrowful as they heard him.
+</para>
+
+<para>
+Presently he reached the splendid palace of King Priam, adorned
+with colonnades of hewn stone. In it there were fifty
+bedchambers--all of hewn stone--built near one another, where the
+sons of Priam slept, each with his wedded wife. Opposite these,
+on the other side the courtyard, there were twelve upper rooms
+also of hewn stone for Priam's daughters, built near one another,
+where his sons-in-law slept with their wives. When Hector got
+there, his fond mother came up to him with Laodice the fairest of
+her daughters. She took his hand within her own and said, "My
+son, why have you left the battle to come hither? Are the
+Achaeans, woe betide them, pressing you hard about the city that
+you have thought fit to come and uplift your hands to Jove from
+the citadel? Wait till I can bring you wine that you may make
+offering to Jove and to the other immortals, and may then drink
+and be refreshed. Wine gives a man fresh strength when he is
+wearied, as you now are with fighting on behalf of your kinsmen."
+</para>
+
+<para>
+And Hector answered, "Honoured mother, bring no wine, lest you
+unman me and I forget my strength. I dare not make a
+drink-offering to Jove with unwashed hands; one who is
+bespattered with blood and filth may not pray to the son of
+Saturn. Get the matrons together, and go with offerings to the
+temple of Minerva driver of the spoil; there, upon the knees of
+Minerva, lay the largest and fairest robe you have in your
+house--the one you set most store by; promise, moreover, to
+sacrifice twelve yearling heifers that have never yet felt the
+goad, in the temple of the goddess if she will take pity on the
+town, with the wives and little ones of the Trojans, and keep the
+son of Tydeus from off the goodly city of Ilius, for he fights
+with fury, and fills men's souls with panic. Go, then, to the
+temple of Minerva, while I seek Paris and exhort him, if he will
+hear my words. Would that the earth might open her jaws and
+swallow him, for Jove bred him to be the bane of the Trojans, and
+of Priam and Priam's sons. Could I but see him go down into the
+house of Hades, my heart would forget its heaviness."
+</para>
+
+<para>
+His mother went into the house and called her waiting-women who
+gathered the matrons throughout the city. She then went down into
+her fragrant store-room, where her embroidered robes were kept,
+the work of Sidonian women, whom Alexandrus had brought over from
+Sidon when he sailed the seas upon that voyage during which he
+carried off Helen. Hecuba took out the largest robe, and the one
+that was most beautifully enriched with embroidery, as an
+offering to Minerva: it glittered like a star, and lay at the
+very bottom of the chest. With this she went on her way and many
+matrons with her.
+</para>
+
+<para>
+When they reached the temple of Minerva, lovely Theano, daughter
+of Cisseus and wife of Antenor, opened the doors, for the Trojans
+had made her priestess of Minerva. The women lifted up their
+hands to the goddess with a loud cry, and Theano took the robe to
+lay it upon the knees of Minerva, praying the while to the
+daughter of great Jove. "Holy Minerva," she cried, "protectress
+of our city, mighty goddess, break the spear of Diomed and lay
+him low before the Scaean gates. Do this, and we will sacrifice
+twelve heifers that have never yet known the goad, in your
+temple, if you will have pity upon the town, with the wives and
+little ones of the Trojans." Thus she prayed, but Pallas Minerva
+granted not her prayer.
+</para>
+
+<para>
+While they were thus praying to the daughter of great Jove,
+Hector went to the fair house of Alexandrus, which he had built
+for him by the foremost builders in the land. They had built him
+his house, storehouse, and courtyard near those of Priam and
+Hector on the acropolis. Here Hector entered, with a spear eleven
+cubits long in his hand; the bronze point gleamed in front of
+him, and was fastened to the shaft of the spear by a ring of
+gold. He found Alexandrus within the house, busied about his
+armour, his shield and cuirass, and handling his curved bow;
+there, too, sat Argive Helen with her women, setting them their
+several tasks; and as Hector saw him he rebuked him with words of
+scorn. "Sir," said he, "you do ill to nurse this rancour; the
+people perish fighting round this our town; you would yourself
+chide one whom you saw shirking his part in the combat. Up then,
+or ere long the city will be in a blaze."
+</para>
+
+<para>
+And Alexandrus answered, "Hector, your rebuke is just; listen
+therefore, and believe me when I tell you that I am not here so
+much through rancour or ill-will towards the Trojans, as from a
+desire to indulge my grief. My wife was even now gently urging me
+to battle, and I hold it better that I should go, for victory is
+ever fickle. Wait, then, while I put on my armour, or go first
+and I will follow. I shall be sure to overtake you."
+</para>
+
+<para>
+Hector made no answer, but Helen tried to soothe him. "Brother,"
+said she, "to my abhorred and sinful self, would that a whirlwind
+had caught me up on the day my mother brought me forth, and had
+borne me to some mountain or to the waves of the roaring sea that
+should have swept me away ere this mischief had come about. But,
+since the gods have devised these evils, would, at any rate, that
+I had been wife to a better man--to one who could smart under
+dishonour and men's evil speeches. This fellow was never yet to
+be depended upon, nor never will be, and he will surely reap what
+he has sown. Still, brother, come in and rest upon this seat, for
+it is you who bear the brunt of that toil that has been caused by
+my hateful self and by the sin of Alexandrus--both of whom Jove
+has doomed to be a theme of song among those that shall be born
+hereafter."
+</para>
+
+<para>
+And Hector answered, "Bid me not be seated, Helen, for all the
+goodwill you bear me. I cannot stay. I am in haste to help the
+Trojans, who miss me greatly when I am not among them; but urge
+your husband, and of his own self also let him make haste to
+overtake me before I am out of the city. I must go home to see my
+household, my wife and my little son, for I know not whether I
+shall ever again return to them, or whether the gods will cause
+me to fill by the hands of the Achaeans."
+</para>
+
+<para>
+Then Hector left her, and forthwith was at his own house. He did
+not find Andromache, for she was on the wall with her child and
+one of her maids, weeping bitterly. Seeing, then, that she was
+not within, he stood on the threshold of the women's rooms and
+said, "Women, tell me, and tell me true, where did Andromache go
+when she left the house? Was it to my sisters, or to my brothers'
+wives? or is she at the temple of Minerva where the other women
+are propitiating the awful goddess?"
+</para>
+
+<para>
+His good housekeeper answered, "Hector, since you bid me tell you
+truly, she did not go to your sisters nor to your brothers'
+wives, nor yet to the temple of Minerva, where the other women
+are propitiating the awful goddess, but she is on the high wall
+of Ilius, for she had heard the Trojans were being hard pressed,
+and that the Achaeans were in great force: she went to the wall
+in frenzied haste, and the nurse went with her carrying the
+child."
+</para>
+
+<para>
+Hector hurried from the house when she had done speaking, and
+went down the streets by the same way that he had come. When he
+had gone through the city and had reached the Scaean gates
+through which he would go out on to the plain, his wife came
+running towards him, Andromache, daughter of great Eetion who
+ruled in Thebe under the wooded slopes of Mt. Placus, and was
+king of the Cilicians. His daughter had married Hector, and now
+came to meet him with a nurse who carried his little child in her
+bosom--a mere babe. Hector's darling son, and lovely as a star.
+Hector had named him Scamandrius, but the people called him
+Astyanax, for his father stood alone as chief guardian of Ilius.
+Hector smiled as he looked upon the boy, but he did not speak,
+and Andromache stood by him weeping and taking his hand in her
+own. "Dear husband," said she, "your valour will bring you to
+destruction; think on your infant son, and on my hapless self who
+ere long shall be your widow--for the Achaeans will set upon you
+in a body and kill you. It would be better for me, should I lose
+you, to lie dead and buried, for I shall have nothing left to
+comfort me when you are gone, save only sorrow. I have neither
+father nor mother now. Achilles slew my father when he sacked
+Thebe the goodly city of the Cilicians. He slew him, but did not
+for very shame despoil him; when he had burned him in his
+wondrous armour, he raised a barrow over his ashes and the
+mountain nymphs, daughters of aegis-bearing Jove, planted a grove
+of elms about his tomb. I had seven brothers in my father's
+house, but on the same day they all went within the house of
+Hades. Achilles killed them as they were with their sheep and
+cattle. My mother--her who had been queen of all the land under
+Mt. Placus--he brought hither with the spoil, and freed her for a
+great sum, but the archer-queen Diana took her in the house of
+your father. Nay--Hector--you who to me are father, mother,
+brother, and dear husband--have mercy upon me; stay here upon
+this wall; make not your child fatherless, and your wife a widow;
+as for the host, place them near the fig-tree, where the city can
+be best scaled, and the wall is weakest. Thrice have the bravest
+of them come thither and assailed it, under the two Ajaxes,
+Idomeneus, the sons of Atreus, and the brave son of Tydeus,
+either of their own bidding, or because some soothsayer had told
+them."
+</para>
+
+<para>
+And Hector answered, "Wife, I too have thought upon all this, but
+with what face should I look upon the Trojans, men or women, if I
+shirked battle like a coward? I cannot do so: I know nothing save
+to fight bravely in the forefront of the Trojan host and win
+renown alike for my father and myself. Well do I know that the
+day will surely come when mighty Ilius shall be destroyed with
+Priam and Priam's people, but I grieve for none of these--not
+even for Hecuba, nor King Priam, nor for my brothers many and
+brave who may fall in the dust before their foes--for none of
+these do I grieve as for yourself when the day shall come on
+which some one of the Achaeans shall rob you for ever of your
+freedom, and bear you weeping away. It may be that you will have
+to ply the loom in Argos at the bidding of a mistress, or to
+fetch water from the springs Messeis or Hypereia, treated
+brutally by some cruel task-master; then will one say who sees
+you weeping, 'She was wife to Hector, the bravest warrior among
+the Trojans during the war before Ilius.' On this your tears will
+break forth anew for him who would have put away the day of
+captivity from you. May I lie dead under the barrow that is
+heaped over my body ere I hear your cry as they carry you into
+bondage."
+</para>
+
+<para>
+He stretched his arms towards his child, but the boy cried and
+nestled in his nurse's bosom, scared at the sight of his father's
+armour, and at the horse-hair plume that nodded fiercely from his
+helmet. His father and mother laughed to see him, but Hector took
+the helmet from his head and laid it all gleaming upon the
+ground. Then he took his darling child, kissed him, and dandled
+him in his arms, praying over him the while to Jove and to all
+the gods. "Jove," he cried, "grant that this my child may be even
+as myself, chief among the Trojans; let him be not less excellent
+in strength, and let him rule Ilius with his might. Then may one
+say of him as he comes from battle, 'The son is far better than
+the father.' May he bring back the blood-stained spoils of him
+whom he has laid low, and let his mother's heart be glad.'"
+</para>
+
+<para>
+With this he laid the child again in the arms of his wife, who
+took him to her own soft bosom, smiling through her tears. As her
+husband watched her his heart yearned towards her and he caressed
+her fondly, saying, "My own wife, do not take these things too
+bitterly to heart. No one can hurry me down to Hades before my
+time, but if a man's hour is come, be he brave or be he coward,
+there is no escape for him when he has once been born. Go, then,
+within the house, and busy yourself with your daily duties, your
+loom, your distaff, and the ordering of your servants; for war is
+man's matter, and mine above all others of them that have been
+born in Ilius."
+</para>
+
+<para>
+He took his plumed helmet from the ground, and his wife went back
+again to her house, weeping bitterly and often looking back
+towards him. When she reached her home she found her maidens
+within, and bade them all join in her lament; so they mourned
+Hector in his own house though he was yet alive, for they deemed
+that they should never see him return safe from battle, and from
+the furious hands of the Achaeans.
+</para>
+
+<para>
+Paris did not remain long in his house. He donned his goodly
+armour overlaid with bronze, and hasted through the city as fast
+as his feet could take him. As a horse, stabled and fed, breaks
+loose and gallops gloriously over the plain to the place where he
+is wont to bathe in the fair-flowing river--he holds his head
+high, and his mane streams upon his shoulders as he exults in his
+strength and flies like the wind to the haunts and feeding ground
+of the mares--even so went forth Paris from high Pergamus,
+gleaming like sunlight in his armour, and he laughed aloud as he
+sped swiftly on his way. Forthwith he came upon his brother
+Hector, who was then turning away from the place where he had
+held converse with his wife, and he was himself the first to
+speak. "Sir," said he, "I fear that I have kept you waiting when
+you are in haste, and have not come as quickly as you bade me."
+</para>
+
+<para>
+"My good brother," answered Hector, "you fight bravely, and no
+man with any justice can make light of your doings in battle. But
+you are careless and wilfully remiss. It grieves me to the heart
+to hear the ill that the Trojans speak about you, for they have
+suffered much on your account. Let us be going, and we will make
+things right hereafter, should Jove vouchsafe us to set the cup
+of our deliverance before ever-living gods of heaven in our own
+homes, when we have chased the Achaeans from Troy."
+</para>
+</chapter>
+
+<chapter>
+<title>BOOK VII</title>
+
+<para>
+WITH these words Hector passed through the gates, and his brother
+Alexandrus with him, both eager for the fray. As when heaven
+sends a breeze to sailors who have long looked for one in vain,
+and have laboured at their oars till they are faint with toil,
+even so welcome was the sight of these two heroes to the Trojans.
+</para>
+
+<para>
+Thereon Alexandrus killed Menesthius the son of Areithous; he
+lived in Arne, and was son of Areithous the Mace-man, and of
+Phylomedusa. Hector threw a spear at Eioneus and struck him dead
+with a wound in the neck under the bronze rim of his helmet.
+Glaucus, moreover, son of Hippolochus, captain of the Lycians, in
+hard hand-to-hand fight smote Iphinous son of Dexius on the
+shoulder, as he was springing on to his chariot behind his fleet
+mares; so he fell to earth from the car, and there was no life
+left in him.
+</para>
+
+<para>
+When, therefore, Minerva saw these men making havoc of the
+Argives, she darted down to Ilius from the summits of Olympus,
+and Apollo, who was looking on from Pergamus, went out to meet
+her; for he wanted the Trojans to be victorious. The pair met by
+the oak tree, and King Apollo son of Jove was first to speak.
+"What would you have", said he, "daughter of great Jove, that
+your proud spirit has sent you hither from Olympus? Have you no
+pity upon the Trojans, and would you incline the scales of
+victory in favour of the Danaans? Let me persuade you--for it
+will be better thus--stay the combat for to-day, but let them
+renew the fight hereafter till they compass the doom of Ilius,
+since you goddesses have made up your minds to destroy the city."
+</para>
+
+<para>
+And Minerva answered, "So be it, Far-Darter; it was in this mind
+that I came down from Olympus to the Trojans and Achaeans. Tell
+me, then, how do you propose to end this present fighting?"
+</para>
+
+<para>
+Apollo, son of Jove, replied, "Let us incite great Hector to
+challenge some one of the Danaans in single combat; on this the
+Achaeans will be shamed into finding a man who will fight him."
+</para>
+
+<para>
+Minerva assented, and Helenus son of Priam divined the counsel of
+the gods; he therefore went up to Hector and said, "Hector son of
+Priam, peer of gods in counsel, I am your brother, let me then
+persuade you. Bid the other Trojans and Achaeans all of them take
+their seats, and challenge the best man among the Achaeans to
+meet you in single combat. I have heard the voice of the
+ever-living gods, and the hour of your doom is not yet come."
+</para>
+
+<para>
+Hector was glad when he heard this saying, and went in among the
+Trojans, grasping his spear by the middle to hold them back, and
+they all sat down. Agamemnon also bade the Achaeans be seated.
+But Minerva and Apollo, in the likeness of vultures, perched on
+father Jove's high oak tree, proud of their men; and the ranks
+sat close ranged together, bristling with shield and helmet and
+spear. As when the rising west wind furs the face of the sea and
+the waters grow dark beneath it, so sat the companies of Trojans
+and Achaeans upon the plain. And Hector spoke thus:--
+</para>
+
+<para>
+"Hear me, Trojans and Achaeans, that I may speak even as I am
+minded; Jove on his high throne has brought our oaths and
+covenants to nothing, and foreshadows ill for both of us, till
+you either take the towers of Troy, or are yourselves vanquished
+at your ships. The princes of the Achaeans are here present in
+the midst of you; let him, then, that will fight me stand forward
+as your champion against Hector. Thus I say, and may Jove be
+witness between us. If your champion slay me, let him strip me of
+my armour and take it to your ships, but let him send my body
+home that the Trojans and their wives may give me my dues of fire
+when I am dead. In like manner, if Apollo vouchsafe me glory and
+I slay your champion, I will strip him of his armour and take it
+to the city of Ilius, where I will hang it in the temple of
+Apollo, but I will give up his body, that the Achaeans may bury
+him at their ships, and the build him a mound by the wide waters
+of the Hellespont. Then will one say hereafter as he sails his
+ship over the sea, 'This is the monument of one who died long
+since a champion who was slain by mighty Hector.' Thus will one
+say, and my fame shall not be lost."
+</para>
+
+<para>
+Thus did he speak, but they all held their peace, ashamed to
+decline the challenge, yet fearing to accept it, till at last
+Menelaus rose and rebuked them, for he was angry. "Alas," he
+cried, "vain braggarts, women forsooth not men, double-dyed
+indeed will be the stain upon us if no man of the Danaans will
+now face Hector. May you be turned every man of you into earth
+and water as you sit spiritless and inglorious in your places. I
+will myself go out against this man, but the upshot of the fight
+will be from on high in the hands of the immortal gods."
+</para>
+
+<para>
+With these words he put on his armour; and then, O Menelaus, your
+life would have come to an end at the hands of hands of Hector,
+for he was far better the man, had not the princes of the
+Achaeans sprung upon you and checked you. King Agamemnon caught
+him by the right hand and said, "Menelaus, you are mad; a truce
+to this folly. Be patient in spite of passion, do not think of
+fighting a man so much stronger than yourself as Hector son of
+Priam, who is feared by many another as well as you. Even
+Achilles, who is far more doughty than you are, shrank from
+meeting him in battle. Sit down your own people, and the Achaeans
+will send some other champion to fight Hector; fearless and fond
+of battle though he be, I ween his knees will bend gladly under
+him if he comes out alive from the hurly-burly of this fight."
+</para>
+
+<para>
+With these words of reasonable counsel he persuaded his brother,
+whereon his squires gladly stripped the armour from off his
+shoulders. Then Nestor rose and spoke, "Of a truth," said he,
+"the Achaean land is fallen upon evil times. The old knight
+Peleus, counsellor and orator among the Myrmidons, loved when I
+was in his house to question me concerning the race and lineage
+of all the Argives. How would it not grieve him could he hear of
+them as now quailing before Hector? Many a time would he lift his
+hands in prayer that his soul might leave his body and go down
+within the house of Hades. Would, by father Jove, Minerva, and
+Apollo, that I were still young and strong as when the Pylians
+and Arcadians were gathered in fight by the rapid river Celadon
+under the walls of Pheia, and round about the waters of the river
+Iardanus. The godlike hero Ereuthalion stood forward as their
+champion, with the armour of King Areithous upon his shoulders--
+Areithous whom men and women had surnamed 'the Mace-man,' because
+he fought neither with bow nor spear, but broke the battalions of
+the foe with his iron mace. Lycurgus killed him, not in fair
+fight, but by entrapping him in a narrow way where his mace
+served him in no stead; for Lycurgus was too quick for him and
+speared him through the middle, so he fell to earth on his back.
+Lycurgus then spoiled him of the armour which Mars had given him,
+and bore it in battle thenceforward; but when he grew old and
+stayed at home, he gave it to his faithful squire Ereuthalion,
+who in this same armour challenged the foremost men among us. The
+others quaked and quailed, but my high spirit bade me fight him
+though none other would venture; I was the youngest man of them
+all; but when I fought him Minerva vouchsafed me victory. He was
+the biggest and strongest man that ever I killed, and covered
+much ground as he lay sprawling upon the earth. Would that I were
+still young and strong as I then was, for the son of Priam would
+then soon find one who would face him. But you, foremost among
+the whole host though you be, have none of you any stomach for
+fighting Hector."
+</para>
+
+<para>
+Thus did the old man rebuke them, and forthwith nine men started
+to their feet. Foremost of all uprose King Agamemnon, and after
+him brave Diomed the son of Tydeus. Next were the two Ajaxes, men
+clothed in valour as with a garment, and then Idomeneus, and
+Meriones his brother in arms. After these Eurypylus son of
+Euaemon, Thoas the son of Andraemon, and Ulysses also rose. Then
+Nestor knight of Gerene again spoke, saying: "Cast lots among you
+to see who shall be chosen. If he come alive out of this fight he
+will have done good service alike to his own soul and to the
+Achaeans."
+</para>
+
+<para>
+Thus he spoke, and when each of them had marked his lot, and had
+thrown it into the helmet of Agamemnon son of Atreus, the people
+lifted their hands in prayer, and thus would one of them say as
+he looked into the vault of heaven, "Father Jove, grant that the
+lot fall on Ajax, or on the son of Tydeus, or upon the king of
+rich Mycene himself."
+</para>
+
+<para>
+As they were speaking, Nestor knight of Gerene shook the helmet,
+and from it there fell the very lot which they wanted--the lot of
+Ajax. The herald bore it about and showed it to all the
+chieftains of the Achaeans, going from left to right; but they
+none of them owned it. When, however, in due course he reached
+the man who had written upon it and had put it into the helmet,
+brave Ajax held out his hand, and the herald gave him the lot.
+When Ajax saw his mark he knew it and was glad; he threw it to
+the ground and said, "My friends, the lot is mine, and I rejoice,
+for I shall vanquish Hector. I will put on my armour; meanwhile,
+pray to King Jove in silence among yourselves that the Trojans
+may not hear you--or aloud if you will, for we fear no man. None
+shall overcome me, neither by force nor cunning, for I was born
+and bred in Salamis, and can hold my own in all things."
+</para>
+
+<para>
+With this they fell praying to King Jove the son of Saturn, and
+thus would one of them say as he looked into the vault of heaven,
+"Father Jove that rulest from Ida, most glorious in power,
+vouchsafe victory to Ajax, and let him win great glory: but if
+you wish well to Hector also and would protect him, grant to each
+of them equal fame and prowess."
+</para>
+
+<para>
+Thus they prayed, and Ajax armed himself in his suit of gleaming
+bronze. When he was in full array he sprang forward as monstrous
+Mars when he takes part among men whom Jove has set fighting with
+one another--even so did huge Ajax, bulwark of the Achaeans,
+spring forward with a grim smile on his face as he brandished his
+long spear and strode onward. The Argives were elated as they
+beheld him, but the Trojans trembled in every limb, and the heart
+even of Hector beat quickly, but he could not now retreat and
+withdraw into the ranks behind him, for he had been the
+challenger. Ajax came up bearing his shield in front of him like
+a wall--a shield of bronze with seven folds of oxhide--the work
+of Tychius, who lived in Hyle and was by far the best worker in
+leather. He had made it with the hides of seven full-fed bulls,
+and over these he had set an eighth layer of bronze. Holding this
+shield before him, Ajax son of Telamon came close up to Hector,
+and menaced him saying, "Hector, you shall now learn, man to man,
+what kind of champions the Danaans have among them even besides
+lion-hearted Achilles cleaver of the ranks of men. He now abides
+at the ships in anger with Agamemnon shepherd of his people, but
+there are many of us who are well able to face you; therefore
+begin the fight."
+</para>
+
+<para>
+And Hector answered, "Noble Ajax, son of Telamon, captain of the
+host, treat me not as though I were some puny boy or woman that
+cannot fight. I have been long used to the blood and butcheries
+of battle. I am quick to turn my leathern shield either to right
+or left, for this I deem the main thing in battle. I can charge
+among the chariots and horsemen, and in hand to hand fighting can
+delight the heart of Mars; howbeit I would not take such a man as
+you are off his guard--but I will smite you openly if I can."
+</para>
+
+<para>
+He poised his spear as he spoke, and hurled it from him. It
+struck the sevenfold shield in its outermost layer--the eighth,
+which was of bronze--and went through six of the layers but in
+the seventh hide it stayed. Then Ajax threw in his turn, and
+struck the round shield of the son of Priam. The terrible spear
+went through his gleaming shield, and pressed onward through his
+cuirass of cunning workmanship; it pierced the shirt against his
+side, but he swerved and thus saved his life. They then each of
+them drew out the spear from his shield, and fell on one another
+like savage lions or wild boars of great strength and endurance:
+the son of Priam struck the middle of Ajax's shield, but the
+bronze did not break, and the point of his dart was turned. Ajax
+then sprang forward and pierced the shield of Hector; the spear
+went through it and staggered him as he was springing forward to
+attack; it gashed his neck and the blood came pouring from the
+wound, but even so Hector did not cease fighting; he gave ground,
+and with his brawny hand seized a stone, rugged and huge, that
+was lying upon the plain; with this he struck the shield of Ajax
+on the boss that was in its middle, so that the bronze rang
+again. But Ajax in turn caught up a far larger stone, swung it
+aloft, and hurled it with prodigious force. This millstone of a
+rock broke Hector's shield inwards and threw him down on his back
+with the shield crushing him under it, but Apollo raised him at
+once. Thereon they would have hacked at one another in close
+combat with their swords, had not heralds, messengers of gods and
+men, come forward, one from the Trojans and the other from the
+Achaeans--Talthybius and Idaeus both of them honourable men;
+these parted them with their staves, and the good herald Idaeus
+said, "My sons, fight no longer, you are both of you valiant, and
+both are dear to Jove; we know this; but night is now falling,
+and the behests of night may not be well gainsaid."
+</para>
+
+<para>
+Ajax son of Telamon answered, "Idaeus, bid Hector say so, for it
+was he that challenged our princes. Let him speak first and I
+will accept his saying."
+</para>
+
+<para>
+Then Hector said, "Ajax, heaven has vouchsafed you stature and
+strength, and judgement; and in wielding the spear you excel all
+others of the Achaeans. Let us for this day cease fighting;
+hereafter we will fight anew till heaven decide between us, and
+give victory to one or to the other; night is now falling, and
+the behests of night may not be well gainsaid. Gladden, then, the
+hearts of the Achaeans at your ships, and more especially those
+of your own followers and clansmen, while I, in the great city of
+King Priam, bring comfort to the Trojans and their women, who vie
+with one another in their prayers on my behalf. Let us, moreover,
+exchange presents that it may be said among the Achaeans and
+Trojans, 'They fought with might and main, but were reconciled
+and parted in friendship.'"
+</para>
+
+<para>
+On this he gave Ajax a silver-studded sword with its sheath and
+leathern baldric, and in return Ajax gave him a girdle dyed with
+purple. Thus they parted, the one going to the host of the
+Achaeans, and the other to that of the Trojans, who rejoiced when
+they saw their hero come to them safe and unharmed from the
+strong hands of mighty Ajax. They led him, therefore, to the city
+as one that had been saved beyond their hopes. On the other side
+the Achaeans brought Ajax elated with victory to Agamemnon.
+</para>
+
+<para>
+When they reached the quarters of the son of Atreus, Agamemnon
+sacrificed for them a five-year-old bull in honour of Jove the
+son of Saturn. They flayed the carcass, made it ready, and
+divided it into joints; these they cut carefully up into smaller
+pieces, putting them on the spits, roasting them sufficiently,
+and then drawing them off. When they had done all this and had
+prepared the feast, they ate it, and every man had his full and
+equal share, so that all were satisfied, and King Agamemnon gave
+Ajax some slices cut lengthways down the loin, as a mark of
+special honour. As soon as they had had enough to eat and drink,
+old Nestor whose counsel was ever truest began to speak; with all
+sincerity and goodwill, therefore, he addressed them thus:--
+</para>
+
+<para>
+"Son of Atreus, and other chieftains, inasmuch as many of the
+Achaeans are now dead, whose blood Mars has shed by the banks of
+the Scamander, and their souls have gone down to the house of
+Hades, it will be well when morning comes that we should cease
+fighting; we will then wheel our dead together with oxen and
+mules and burn them not far from the ships, that when we sail
+hence we may take the bones of our comrades home to their
+children. Hard by the funeral pyre we will build a barrow that
+shall be raised from the plain for all in common; near this let
+us set about building a high wall, to shelter ourselves and our
+ships, and let it have well-made gates that there may be a way
+through them for our chariots. Close outside we will dig a deep
+trench all round it to keep off both horse and foot, that the
+Trojan chieftains may not bear hard upon us."
+</para>
+
+<para>
+Thus he spoke, and the princess shouted in applause. Meanwhile
+the Trojans held a council, angry and full of discord, on the
+acropolis by the gates of King Priam's palace; and wise Antenor
+spoke. "Hear me," he said, "Trojans, Dardanians, and allies, that
+I may speak even as I am minded. Let us give up Argive Helen and
+her wealth to the sons of Atreus, for we are now fighting in
+violation of our solemn covenants, and shall not prosper till we
+have done as I say."
+</para>
+
+<para>
+He then sat down and Alexandrus husband of lovely Helen rose to
+speak. "Antenor," said he, "your words are not to my liking; you
+can find a better saying than this if you will; if, however, you
+have spoken in good earnest, then indeed has heaven robbed you of
+your reason. I will speak plainly, and hereby notify to the
+Trojans that I will not give up the woman; but the wealth that I
+brought home with her from Argos I will restore, and will add yet
+further of my own."
+</para>
+
+<para>
+On this, when Paris had spoken and taken his seat, Priam of the
+race of Dardanus, peer of gods in council, rose and with all
+sincerity and goodwill addressed them thus: "Hear me, Trojans,
+Dardanians, and allies, that I may speak even as I am minded. Get
+your suppers now as hitherto throughout the city, but keep your
+watches and be wakeful. At daybreak let Idaeus go to the ships,
+and tell Agamemnon and Menelaus sons of Atreus the saying of
+Alexandrus through whom this quarrel has come about; and let him
+also be instant with them that they now cease fighting till we
+burn our dead; hereafter we will fight anew, till heaven decide
+between us and give victory to one or to the other."
+</para>
+
+<para>
+Thus did he speak, and they did even as he had said. They took
+supper in their companies and at daybreak Idaeus went his way to
+the ships. He found the Danaans, servants of Mars, in council at
+the stern of Agamemnon's ship, and took his place in the midst of
+them. "Son of Atreus," he said, "and princes of the Achaean host,
+Priam and the other noble Trojans have sent me to tell you the
+saying of Alexandrus through whom this quarrel has come about, if
+so be that you may find it acceptable. All the treasure he took
+with him in his ships to Troy--would that he had sooner
+perished--he will restore, and will add yet further of his own,
+but he will not give up the wedded wife of Menelaus, though the
+Trojans would have him do so. Priam bade me inquire further if
+you will cease fighting till we burn our dead; hereafter we will
+fight anew, till heaven decide between us and give victory to one
+or to the other."
+</para>
+
+<para>
+They all held their peace, but presently Diomed of the loud
+war-cry spoke, saying, "Let there be no taking, neither treasure,
+nor yet Helen, for even a child may see that the doom of the
+Trojans is at hand."
+</para>
+
+<para>
+The sons of the Achaeans shouted applause at the words that
+Diomed had spoken, and thereon King Agamemnon said to Idaeus,
+"Idaeus, you have heard the answer the Achaeans make you-and I
+with them. But as concerning the dead, I give you leave to burn
+them, for when men are once dead there should be no grudging them
+the rites of fire. Let Jove the mighty husband of Juno be witness
+to this covenant."
+</para>
+
+<para>
+As he spoke he upheld his sceptre in the sight of all the gods,
+and Idaeus went back to the strong city of Ilius. The Trojans and
+Dardanians were gathered in council waiting his return; when he
+came, he stood in their midst and delivered his message. As soon
+as they heard it they set about their twofold labour, some to
+gather the corpses, and others to bring in wood. The Argives on
+their part also hastened from their ships, some to gather the
+corpses, and others to bring in wood.
+</para>
+
+<para>
+The sun was beginning to beat upon the fields, fresh risen into
+the vault of heaven from the slow still currents of deep Oceanus,
+when the two armies met. They could hardly recognise their dead,
+but they washed the clotted gore from off them, shed tears over
+them, and lifted them upon their waggons. Priam had forbidden the
+Trojans to wail aloud, so they heaped their dead sadly and
+silently upon the pyre, and having burned them went back to the
+city of Ilius. The Achaeans in like manner heaped their dead
+sadly and silently on the pyre, and having burned them went back
+to their ships.
+</para>
+
+<para>
+Now in the twilight when it was not yet dawn, chosen bands of the
+Achaeans were gathered round the pyre and built one barrow that
+was raised in common for all, and hard by this they built a high
+wall to shelter themselves and their ships; they gave it strong
+gates that there might be a way through them for their chariots,
+and close outside it they dug a trench deep and wide, and they
+planted it within with stakes.
+</para>
+
+<para>
+Thus did the Achaeans toil, and the gods, seated by the side of
+Jove the lord of lightning, marvelled at their great work; but
+Neptune, lord of the earthquake, spoke, saying, "Father Jove,
+what mortal in the whole world will again take the gods into his
+counsel? See you not how the Achaeans have built a wall about
+their ships and driven a trench all round it, without offering
+hecatombs to the gods? The fame of this wall will reach as far as
+dawn itself, and men will no longer think anything of the one
+which Phoebus Apollo and myself built with so much labour for
+Laomedon."
+</para>
+
+<para>
+Jove was displeased and answered, "What, O shaker of the earth,
+are you talking about? A god less powerful than yourself might be
+alarmed at what they are doing, but your fame reaches as far as
+dawn itself. Surely when the Achaeans have gone home with their
+ships, you can shatter their wall and fling it into the sea; you
+can cover the beach with sand again, and the great wall of the
+Achaeans will then be utterly effaced."
+</para>
+
+<para>
+Thus did they converse, and by sunset the work of the Achaeans
+was completed; they then slaughtered oxen at their tents and got
+their supper. Many ships had come with wine from Lemnos, sent by
+Euneus the son of Jason, born to him by Hypsipyle. The son of
+Jason freighted them with ten thousand measures of wine, which he
+sent specially to the sons of Atreus, Agamemnon and Menelaus.
+From this supply the Achaeans bought their wine, some with
+bronze, some with iron, some with hides, some with whole heifers,
+and some again with captives. They spread a goodly banquet and
+feasted the whole night through, as also did the Trojans and
+their allies in the city. But all the time Jove boded them ill
+and roared with his portentous thunder. Pale fear got hold upon
+them, and they spilled the wine from their cups on to the ground,
+nor did any dare drink till he had made offerings to the most
+mighty son of Saturn. Then they laid themselves down to rest and
+enjoyed the boon of sleep.
+</para>
+</chapter>
+
+<chapter>
+<title>BOOK VIII</title>
+
+<para>
+NOW when Morning, clad in her robe of saffron, had begun to
+suffuse light over the earth, Jove called the gods in council on
+the topmost crest of serrated Olympus. Then he spoke and all the
+other gods gave ear. "Hear me," said he, "gods and goddesses,
+that I may speak even as I am minded. Let none of you neither
+goddess nor god try to cross me, but obey me every one of you
+that I may bring this matter to an end. If I see anyone acting
+apart and helping either Trojans or Danaans, he shall be beaten
+inordinately ere he come back again to Olympus; or I will hurl
+him down into dark Tartarus far into the deepest pit under the
+earth, where the gates are iron and the floor bronze, as far
+beneath Hades as heaven is high above the earth, that you may
+learn how much the mightiest I am among you. Try me and find out
+for yourselves. Hangs me a golden chain from heaven, and lay hold
+of it all of you, gods and goddesses together--tug as you will,
+you will not drag Jove the supreme counsellor from heaven to
+earth; but were I to pull at it myself I should draw you up with
+earth and sea into the bargain, then would I bind the chain about
+some pinnacle of Olympus and leave you all dangling in the mid
+firmament. So far am I above all others either of gods or men."
+</para>
+
+<para>
+They were frightened and all of them of held their peace, for he
+had spoken masterfully; but at last Minerva answered, "Father,
+son of Saturn, king of kings, we all know that your might is not
+to be gainsaid, but we are also sorry for the Danaan warriors,
+who are perishing and coming to a bad end. We will, however,
+since you so bid us, refrain from actual fighting, but we will
+make serviceable suggestions to the Argives that they may not all
+of them perish in your displeasure."
+</para>
+
+<para>
+Jove smiled at her and answered, "Take heart, my child,
+Trito-born; I am not really in earnest, and I wish to be kind to
+you."
+</para>
+
+<para>
+With this he yoked his fleet horses, with hoofs of bronze and
+manes of glittering gold. He girded himself also with gold about
+the body, seized his gold whip and took his seat in his chariot.
+Thereon he lashed his horses and they flew forward nothing loth
+midway twixt earth and starry heaven. After a while he reached
+many-fountained Ida, mother of wild beasts, and Gargarus, where
+are his grove and fragrant altar. There the father of gods and
+men stayed his horses, took them from the chariot, and hid them
+in a thick cloud; then he took his seat all glorious upon the
+topmost crests, looking down upon the city of Troy and the ships
+of the Achaeans.
+</para>
+
+<para>
+The Achaeans took their morning meal hastily at the ships, and
+afterwards put on their armour. The Trojans on the other hand
+likewise armed themselves throughout the city, fewer in numbers
+but nevertheless eager perforce to do battle for their wives and
+children. All the gates were flung wide open, and horse and foot
+sallied forth with the tramp as of a great multitude.
+</para>
+
+<para>
+When they were got together in one place, shield clashed with
+shield, and spear with spear, in the conflict of mail-clad men.
+Mighty was the din as the bossed shields pressed hard on one
+another--death--cry and shout of triumph of slain and slayers,
+and the earth ran red with blood.
+</para>
+
+<para>
+Now so long as the day waxed and it was still morning their
+weapons beat against one another, and the people fell, but when
+the sun had reached mid-heaven, the sire of all balanced his
+golden scales, and put two fates of death within them, one for
+the Trojans and the other for the Achaeans. He took the balance
+by the middle, and when he lifted it up the day of the Achaeans
+sank; the death-fraught scale of the Achaeans settled down upon
+the ground, while that of the Trojans rose heavenwards. Then he
+thundered aloud from Ida, and sent the glare of his lightning
+upon the Achaeans; when they saw this, pale fear fell upon them
+and they were sore afraid.
+</para>
+
+<para>
+Idomeneus dared not stay nor yet Agamemnon, nor did the two
+Ajaxes, servants of Mars, hold their ground. Nestor knight of
+Gerene alone stood firm, bulwark of the Achaeans, not of his own
+will, but one of his horses was disabled. Alexandrus husband of
+lovely Helen had hit it with an arrow just on the top of its head
+where the mane begins to grow away from the skull, a very deadly
+place. The horse bounded in his anguish as the arrow pierced his
+brain, and his struggles threw others into confusion. The old man
+instantly began cutting the traces with his sword, but Hector's
+fleet horses bore down upon him through the rout with their bold
+charioteer, even Hector himself, and the old man would have
+perished there and then had not Diomed been quick to mark, and
+with a loud cry called Ulysses to help him.
+</para>
+
+<para>
+"Ulysses," he cried, "noble son of Laertes where are you flying
+to, with your back turned like a coward? See that you are not
+struck with a spear between the shoulders. Stay here and help me
+to defend Nestor from this man's furious onset."
+</para>
+
+<para>
+Ulysses would not give ear, but sped onward to the ships of the
+Achaeans, and the son of Tydeus flinging himself alone into the
+thick of the fight took his stand before the horses of the son of
+Neleus. "Sir," said he, "these young warriors are pressing you
+hard, your force is spent, and age is heavy upon you, your squire
+is naught, and your horses are slow to move. Mount my chariot and
+see what the horses of Tros can do--how cleverly they can scud
+hither and thither over the plain either in flight or in pursuit.
+I took them from the hero Aeneas. Let our squires attend to your
+own steeds, but let us drive mine straight at the Trojans, that
+Hector may learn how furiously I too can wield my spear."
+</para>
+
+<para>
+Nestor knight of Gerene hearkened to his words. Thereon the
+doughty squires, Sthenelus and kind-hearted Eurymedon, saw to
+Nestor's horses, while the two both mounted Diomed's chariot.
+Nestor took the reins in his hands and lashed the horses on; they
+were soon close up with Hector, and the son of Tydeus aimed a
+spear at him as he was charging full speed towards them. He
+missed him, but struck his charioteer and squire Eniopeus son of
+noble Thebaeus in the breast by the nipple while the reins were
+in his hands, so that he died there and then, and the horses
+swerved as he fell headlong from the chariot. Hector was greatly
+grieved at the loss of his charioteer, but let him lie for all
+his sorrow, while he went in quest of another driver; nor did his
+steeds have to go long without one, for he presently found brave
+Archeptolemus the son of Iphitus, and made him get up behind the
+horses, giving the reins into his hand.
+</para>
+
+<para>
+All had then been lost and no help for it, for they would have
+been penned up in Ilius like sheep, had not the sire of gods and
+men been quick to mark, and hurled a fiery flaming thunderbolt
+which fell just in front of Diomed's horses with a flare of
+burning brimstone. The horses were frightened and tried to back
+beneath the car, while the reins dropped from Nestor's hands.
+Then he was afraid and said to Diomed, "Son of Tydeus, turn your
+horses in flight; see you not that the hand of Jove is against
+you? To-day he vouchsafes victory to Hector; to-morrow, if it so
+please him, he will again grant it to ourselves; no man, however
+brave, may thwart the purpose of Jove, for he is far stronger
+than any."
+</para>
+
+<para>
+Diomed answered, "All that you have said is true; there is a
+grief however which pierces me to the very heart, for Hector will
+talk among the Trojans and say, 'The son of Tydeus fled before me
+to the ships.' This is the vaunt he will make, and may earth then
+swallow me."
+</para>
+
+<para>
+"Son of Tydeus," replied Nestor, "what mean you? Though Hector
+say that you are a coward the Trojans and Dardanians will not
+believe him, nor yet the wives of the mighty warriors whom you
+have laid low."
+</para>
+
+<para>
+So saying he turned the horses back through the thick of the
+battle, and with a cry that rent the air the Trojans and Hector
+rained their darts after them. Hector shouted to him and said,
+"Son of Tydeus, the Danaans have done you honour hitherto as
+regards your place at table, the meals they give you, and the
+filling of your cup with wine. Henceforth they will despise you,
+for you are become no better than a woman. Be off, girl and
+coward that you are, you shall not scale our walls through any
+flinching upon my part; neither shall you carry off our wives in
+your ships, for I shall kill you with my own hand."
+</para>
+
+<para>
+The son of Tydeus was in two minds whether or no to turn his
+horses round again and fight him. Thrice did he doubt, and thrice
+did Jove thunder from the heights of Ida in token to the Trojans
+that he would turn the battle in their favour. Hector then
+shouted to them and said, "Trojans, Lycians, and Dardanians,
+lovers of close fighting, be men, my friends, and fight with
+might and with main; I see that Jove is minded to vouchsafe
+victory and great glory to myself, while he will deal destruction
+upon the Danaans. Fools, for having thought of building this weak
+and worthless wall. It shall not stay my fury; my horses will
+spring lightly over their trench, and when I am at their ships
+forget not to bring me fire that I may burn them, while I
+slaughter the Argives who will be all dazed and bewildered by the
+smoke."
+</para>
+
+<para>
+Then he cried to his horses, "Xanthus and Podargus, and you
+Aethon and goodly Lampus, pay me for your keep now and for all
+the honey-sweet corn with which Andromache daughter of great
+Eetion has fed you, and for she has mixed wine and water for you
+to drink whenever you would, before doing so even for me who am
+her own husband. Haste in pursuit, that we may take the shield of
+Nestor, the fame of which ascends to heaven, for it is of solid
+gold, arm-rods and all, and that we may strip from the shoulders
+of Diomed. the cuirass which Vulcan made him. Could we take these
+two things, the Achaeans would set sail in their ships this
+self-same night."
+</para>
+
+<para>
+Thus did he vaunt, but Queen Juno made high Olympus quake as she
+shook with rage upon her throne. Then said she to the mighty god
+of Neptune, "What now, wide ruling lord of the earthquake? Can
+you find no compassion in your heart for the dying Danaans, who
+bring you many a welcome offering to Helice and to Aegae? Wish
+them well then. If all of us who are with the Danaans were to
+drive the Trojans back and keep Jove from helping them, he would
+have to sit there sulking alone on Ida."
+</para>
+
+<para>
+King Neptune was greatly troubled and answered, "Juno, rash of
+tongue, what are you talking about? We other gods must not set
+ourselves against Jove, for he is far stronger than we are."
+</para>
+
+<para>
+Thus did they converse; but the whole space enclosed by the
+ditch, from the ships even to the wall, was filled with horses
+and warriors, who were pent up there by Hector son of Priam, now
+that the hand of Jove was with him. He would even have set fire
+to the ships and burned them, had not Queen Juno put it into the
+mind of Agamemnon, to bestir himself and to encourage the
+Achaeans. To this end he went round the ships and tents carrying
+a great purple cloak, and took his stand by the huge black hull
+of Ulysses' ship, which was middlemost of all; it was from this
+place that his voice would carry farthest, on the one hand
+towards the tents of Ajax son of Telamon, and on the other
+towards those of Achilles--for these two heroes, well assured of
+their own strength, had valorously drawn up their ships at the
+two ends of the line. From this spot then, with a voice that
+could be heard afar, he shouted to the Danaans, saying, "Argives,
+shame on you cowardly creatures, brave in semblance only; where
+are now our vaunts that we should prove victorious--the vaunts we
+made so vaingloriously in Lemnos, when we ate the flesh of horned
+cattle and filled our mixing-bowls to the brim? You vowed that
+you would each of you stand against a hundred or two hundred men,
+and now you prove no match even for one--for Hector, who will be
+ere long setting our ships in a blaze. Father Jove, did you ever
+so ruin a great king and rob him so utterly of his greatness?
+Yet, when to my sorrow I was coming hither, I never let my ship
+pass your altars without offering the fat and thigh-bones of
+heifers upon every one of them, so eager was I to sack the city
+of Troy. Vouchsafe me then this prayer--suffer us to escape at
+any rate with our lives, and let not the Achaeans be so utterly
+vanquished by the Trojans."
+</para>
+
+<para>
+Thus did he pray, and father Jove pitying his tears vouchsafed
+him that his people should live, not die; forthwith he sent them
+an eagle, most unfailingly portentous of all birds, with a young
+fawn in its talons; the eagle dropped the fawn by the altar on
+which the Achaeans sacrificed to Jove the lord of omens; when,
+therefore, the people saw that the bird had come from Jove, they
+sprang more fiercely upon the Trojans and fought more boldly.
+</para>
+
+<para>
+There was no man of all the many Danaans who could then boast
+that he had driven his horses over the trench and gone forth to
+fight sooner than the son of Tydeus; long before any one else
+could do so he slew an armed warrior of the Trojans, Agelaus the
+son of Phradmon. He had turned his horses in flight, but the
+spear struck him in the back midway between his shoulders and
+went right through his chest, and his armour rang rattling round
+him as he fell forward from his chariot.
+</para>
+
+<para>
+After him came Agamemnon and Menelaus, sons of Atreus, the two
+Ajaxes clothed in valour as with a garment, Idomeneus and his
+companion in arms Meriones, peer of murderous Mars, and Eurypylus
+the brave son of Euaemon. Ninth came Teucer with his bow, and
+took his place under cover of the shield of Ajax son of Telamon.
+When Ajax lifted his shield Teucer would peer round, and when he
+had hit any one in the throng, the man would fall dead; then
+Teucer would hie back to Ajax as a child to its mother, and again
+duck down under his shield.
+</para>
+
+<para>
+Which of the Trojans did brave Teucer first kill? Orsilochus, and
+then Ormenus and Ophelestes, Daetor, Chromius, and godlike
+Lycophontes, Amopaon son of Polyaemon, and Melanippus. these in
+turn did he lay low upon the earth, and King Agamemnon was glad
+when he saw him making havoc of the Trojans with his mighty bow.
+He went up to him and said, "Teucer, man after my own heart, son
+of Telamon, captain among the host, shoot on, and be at once the
+saving of the Danaans and the glory of your father Telamon, who
+brought you up and took care of you in his own house when you
+were a child, bastard though you were. Cover him with glory
+though he is far off; I will promise and I will assuredly
+perform; if aegis-bearing Jove and Minerva grant me to sack the
+city of Ilius, you shall have the next best meed of honour after
+my own--a tripod, or two horses with their chariot, or a woman
+who shall go up into your bed."
+</para>
+
+<para>
+And Teucer answered, "Most noble son of Atreus, you need not urge
+me; from the moment we began to drive them back to Ilius, I have
+never ceased so far as in me lies to look out for men whom I can
+shoot and kill; I have shot eight barbed shafts, and all of them
+have been buried in the flesh of warlike youths, but this mad dog
+I cannot hit."
+</para>
+
+<para>
+As he spoke he aimed another arrow straight at Hector, for he was
+bent on hitting him; nevertheless he missed him, and the arrow
+hit Priam's brave son Gorgythion in the breast. His mother, fair
+Castianeira, lovely as a goddess, had been married from Aesyme,
+and now he bowed his head as a garden poppy in full bloom when it
+is weighed down by showers in spring--even thus heavy bowed his
+head beneath the weight of his helmet.
+</para>
+
+<para>
+Again he aimed at Hector, for he was longing to hit him, and
+again his arrow missed, for Apollo turned it aside; but he hit
+Hector's brave charioteer Archeptolemus in the breast, by the
+nipple, as he was driving furiously into the fight. The horses
+swerved aside as he fell headlong from the chariot, and there was
+no life left in him. Hector was greatly grieved at the loss of
+his charioteer, but for all his sorrow he let him lie where he
+fell, and bade his brother Cebriones, who was hard by, take the
+reins. Cebriones did as he had said. Hector thereon with a loud
+cry sprang from his chariot to the ground, and seizing a great
+stone made straight for Teucer with intent kill him. Teucer had
+just taken an arrow from his quiver and had laid it upon the
+bow-string, but Hector struck him with the jagged stone as he was
+taking aim and drawing the string to his shoulder; he hit him
+just where the collar-bone divides the neck from the chest, a
+very deadly place, and broke the sinew of his arm so that his
+wrist was less, and the bow dropped from his hand as he fell
+forward on his knees. Ajax saw that his brother had fallen, and
+running towards him bestrode him and sheltered him with his
+shield. Meanwhile his two trusty squires, Mecisteus son of
+Echius, and Alastor, came up and bore him to the ships groaning
+in his great pain.
+</para>
+
+<para>
+Jove now again put heart into the Trojans, and they drove the
+Achaeans to their deep trench with Hector in all his glory at
+their head. As a hound grips a wild boar or lion in flank or
+buttock when he gives him chase, and watches warily for his
+wheeling, even so did Hector follow close upon the Achaeans, ever
+killing the hindmost as they rushed panic-stricken onwards. When
+they had fled through the set stakes and trench and many Achaeans
+had been laid low at the hands of the Trojans, they halted at
+their ships, calling upon one another and praying every man
+instantly as they lifted up their hands to the gods; but Hector
+wheeled his horses this way and that, his eyes glaring like those
+of Gorgo or murderous Mars.
+</para>
+
+<para>
+Juno when she saw them had pity upon them, and at once said to
+Minerva, "Alas, child of aegis-bearing Jove, shall you and I take
+no more thought for the dying Danaans, though it be the last time
+we ever do so? See how they perish and come to a bad end before
+the onset of but a single man. Hector the son of Priam rages with
+intolerable fury, and has already done great mischief."
+</para>
+
+<para>
+Minerva answered, "Would, indeed, this fellow might die in his
+own land, and fall by the hands of the Achaeans; but my father
+Jove is mad with spleen, ever foiling me, ever headstrong and
+unjust. He forgets how often I saved his son when he was worn out
+by the labours Eurystheus had laid on him. He would weep till his
+cry came up to heaven, and then Jove would send me down to help
+him; if I had had the sense to foresee all this, when Eurystheus
+sent him to the house of Hades, to fetch the hell-hound from
+Erebus, he would never have come back alive out of the deep
+waters of the river Styx. And now Jove hates me, while he lets
+Thetis have her way because she kissed his knees and took hold of
+his beard, when she was begging him to do honour to Achilles. I
+shall know what to do next time he begins calling me his
+grey-eyed darling. Get our horses ready, while I go within the
+house of aegis-bearing Jove and put on my armour; we shall then
+find out whether Priam's son Hector will be glad to meet us in
+the highways of battle, or whether the Trojans will glut hounds
+and vultures with the fat of their flesh as they be dead by the
+ships of the Achaeans."
+</para>
+
+<para>
+Thus did she speak and white-armed Juno, daughter of great
+Saturn, obeyed her words; she set about harnessing her
+gold-bedizened steeds, while Minerva daughter of aegis-bearing
+Jove flung her richly vesture, made with her own hands, on to the
+threshold of her father, and donned the shirt of Jove, arming
+herself for battle. Then she stepped into her flaming chariot,
+and grasped the spear so stout and sturdy and strong with which
+she quells the ranks of heroes who have displeased her. Juno
+lashed her horses, and the gates of heaven bellowed as they flew
+open of their own accord--gates over which the Hours preside, in
+whose hands are heaven and Olympus, either to open the dense
+cloud that hides them or to close it. Through these the goddesses
+drove their obedient steeds.
+</para>
+
+<para>
+But father Jove when he saw them from Ida was very angry, and
+sent winged Iris with a message to them. "Go," said he, "fleet
+Iris, turn them back, and see that they do not come near me, for
+if we come to fighting there will be mischief. This is what I
+say, and this is what I mean to do. I will lame their horses for
+them; I will hurl them from their chariot, and will break it in
+pieces. It will take them all ten years to heal the wounds my
+lightning shall inflict upon them; my grey-eyed daughter will
+then learn what quarrelling with her father means. I am less
+surprised and angry with Juno, for whatever I say she always
+contradicts me."
+</para>
+
+<para>
+With this Iris went her way, fleet as the wind, from the heights
+of Ida to the lofty summits of Olympus. She met the goddesses at
+the outer gates of its many valleys and gave them her message.
+"What," said she, "are you about? Are you mad? The son of Saturn
+forbids going. This is what he says, and this is he means to do,
+he will lame your horses for you, he will hurl you from your
+chariot, and will break it in pieces. It will take you all ten
+years to heal the wounds his lightning will inflict upon you,
+that you may learn, grey-eyed goddess, what quarrelling with your
+father means. He is less hurt and angry with Juno, for whatever
+he says she always contradicts him but you, bold hussy, will you
+really dare to raise your huge spear in defiance of Jove?"
+</para>
+
+<para>
+With this she left them, and Juno said to Minerva, "Of a truth,
+child of aegis-bearing Jove, I am not for fighting men's battles
+further in defiance of Jove. Let them live or die as luck will
+have it, and let Jove mete out his judgements upon the Trojans
+and Danaans according to his own pleasure."
+</para>
+
+<para>
+She turned her steeds; the Hours presently unyoked them, made
+them fast to their ambrosial mangers, and leaned the chariot
+against the end wall of the courtyard. The two goddesses then sat
+down upon their golden thrones, amid the company of the other
+gods; but they were very angry.
+</para>
+
+<para>
+Presently father Jove drove his chariot to Olympus, and entered
+the assembly of gods. The mighty lord of the earthquake unyoked
+his horses for him, set the car upon its stand, and threw a cloth
+over it. Jove then sat down upon his golden throne and Olympus
+reeled beneath him. Minerva and Juno sat alone, apart from Jove,
+and neither spoke nor asked him questions, but Jove knew what
+they meant, and said, "Minerva and Juno, why are you so angry?
+Are you fatigued with killing so many of your dear friends the
+Trojans? Be this as it may, such is the might of my hands that
+all the gods in Olympus cannot turn me; you were both of you
+trembling all over ere ever you saw the fight and its terrible
+doings. I tell you therefore-and it would have surely been--I
+should have struck you with lighting, and your chariots would
+never have brought you back again to Olympus."
+</para>
+
+<para>
+Minerva and Juno groaned in spirit as they sat side by side and
+brooded mischief for the Trojans. Minerva sat silent without a
+word, for she was in a furious passion and bitterly incensed
+against her father; but Juno could not contain herself and said,
+"What, dread son of Saturn, are you talking about? We know how
+great your power is, nevertheless we have compassion upon the
+Danaan warriors who are perishing and coming to a bad end. We
+will, however, since you so bid us, refrain from actual fighting,
+but we will make serviceable suggestions to the Argives, that
+they may not all of them perish in your displeasure."
+</para>
+
+<para>
+And Jove answered, "To-morrow morning, Juno, if you choose to do
+so, you will see the son of Saturn destroying large numbers of
+the Argives, for fierce Hector shall not cease fighting till he
+has roused the son of Peleus when they are fighting in dire
+straits at their ships' sterns about the body of Patroclus. Like
+it or no, this is how it is decreed; for aught I care, you may go
+to the lowest depths beneath earth and sea, where Iapetus and
+Saturn dwell in lone Tartarus with neither ray of light nor
+breath of wind to cheer them. You may go on and on till you get
+there, and I shall not care one whit for your displeasure; you
+are the greatest vixen living."
+</para>
+
+<para>
+Juno made him no answer. The sun's glorious orb now sank into
+Oceanus and drew down night over the land. Sorry indeed were the
+Trojans when light failed them, but welcome and thrice prayed for
+did darkness fall upon the Achaeans.
+</para>
+
+<para>
+Then Hector led the Trojans back from the ships, and held a
+council on the open space near the river, where there was a spot
+clear of corpses. They left their chariots and sat down on the
+ground to hear the speech he made them. He grasped a spear eleven
+cubits long, the bronze point of which gleamed in front of it,
+while the ring round the spear-head was of gold. Spear in hand he
+spoke. "Hear me," said he, "Trojans, Dardanians, and allies. I
+deemed but now that I should destroy the ships and all the
+Achaeans with them ere I went back to Ilius, but darkness came on
+too soon. It was this alone that saved them and their ships upon
+the seashore. Now, therefore, let us obey the behests of night,
+and prepare our suppers. Take your horses out of their chariots
+and give them their feeds of corn; then make speed to bring sheep
+and cattle from the city; bring wine also and corn for your
+horses and gather much wood, that from dark till dawn we may burn
+watchfires whose flare may reach to heaven. For the Achaeans may
+try to fly beyond the sea by night, and they must not embark
+scatheless and unmolested; many a man among them must take a dart
+with him to nurse at home, hit with spear or arrow as he is
+leaping on board his ship, that others may fear to bring war and
+weeping upon the Trojans. Moreover let the heralds tell it about
+the city that the growing youths and grey-bearded men are to camp
+upon its heaven-built walls. Let the women each of them light a
+great fire in her house, and let watch be safely kept lest the
+town be entered by surprise while the host is outside. See to it,
+brave Trojans, as I have said, and let this suffice for the
+moment; at daybreak I will instruct you further. I pray in hope
+to Jove and to the gods that we may then drive those fate-sped
+hounds from our land, for 'tis the fates that have borne them and
+their ships hither. This night, therefore, let us keep watch, but
+with early morning let us put on our armour and rouse fierce war
+at the ships of the Achaeans; I shall then know whether brave
+Diomed the son of Tydeus will drive me back from the ships to the
+wall, or whether I shall myself slay him and carry off his
+bloodstained spoils. To-morrow let him show his mettle, abide my
+spear if he dare. I ween that at break of day, he shall be among
+the first to fall and many another of his comrades round him.
+Would that I were as sure of being immortal and never growing
+old, and of being worshipped like Minerva and Apollo, as I am
+that this day will bring evil to the Argives."
+</para>
+
+<para>
+Thus spoke Hector and the Trojans shouted applause. They took
+their sweating steeds from under the yoke, and made them fast
+each by his own chariot. They made haste to bring sheep and
+cattle from the city, they brought wine also and corn from their
+houses and gathered much wood. They then offered unblemished
+hecatombs to the immortals, and the wind carried the sweet savour
+of sacrifice to heaven--but the blessed gods partook not thereof,
+for they bitterly hated Ilius with Priam and Priam's people. Thus
+high in hope they sat through the livelong night by the highways
+of war, and many a watchfire did they kindle. As when the stars
+shine clear, and the moon is bright--there is not a breath of
+air, not a peak nor glade nor jutting headland but it stands out
+in the ineffable radiance that breaks from the serene of heaven;
+the stars can all of them be told and the heart of the shepherd
+is glad--even thus shone the watchfires of the Trojans before
+Ilius midway between the ships and the river Xanthus. A thousand
+camp-fires gleamed upon the plain, and in the glow of each there
+sat fifty men, while the horses, champing oats and corn beside
+their chariots, waited till dawn should come.
+</para>
+</chapter>
+
+<chapter>
+<title>BOOK IX</title>
+
+<para>
+THUS did the Trojans watch. But Panic, comrade of blood-stained
+Rout, had taken fast hold of the Achaeans, and their princes were
+all of them in despair. As when the two winds that blow from
+Thrace--the north and the northwest--spring up of a sudden and
+rouse the fury of the main--in a moment the dark waves uprear
+their heads and scatter their sea-wrack in all directions--even
+thus troubled were the hearts of the Achaeans.
+</para>
+
+<para>
+The son of Atreus in dismay bade the heralds call the people to a
+council man by man, but not to cry the matter aloud; he made
+haste also himself to call them, and they sat sorry at heart in
+their assembly. Agamemnon shed tears as it were a running stream
+or cataract on the side of some sheer cliff; and thus, with many
+a heavy sigh he spoke to the Achaeans. "My friends," said he,
+"princes and councillors Of the Argives, the hand of heaven has
+been laid heavily upon me. Cruel Jove gave me his solemn promise
+that I should sack the city of Troy before returning, but he has
+played me false, and is now bidding me go ingloriously back to
+Argos with the loss of much people. Such is the will of Jove, who
+has laid many a proud city in the dust as he will yet lay others,
+for his power is above all. Now, therefore, let us all do as I
+say and sail back to our own country, for we shall not take
+Troy."
+</para>
+
+<para>
+Thus he spoke, and the sons of the Achaeans for a long while sat
+sorrowful there, but they all held their peace, till at last
+Diomed of the loud battle-cry made answer saying, "Son of Atreus,
+I will chide your folly, as is my right in council. Be not then
+aggrieved that I should do so. In the first place you attacked me
+before all the Danaans and said that I was a coward and no
+soldier. The Argives young and old know that you did so. But the
+son of scheming Saturn endowed you by halves only. He gave you
+honour as the chief ruler over us, but valour, which is the
+highest both right and might he did not give you. Sir, think you
+that the sons of the Achaeans are indeed as unwarlike and
+cowardly as you say they are? If your own mind is set upon going
+home--go--the way is open to you; the many ships that followed
+you from Mycene stand ranged upon the seashore; but the rest of
+us stay here till we have sacked Troy. Nay though these too
+should turn homeward with their ships, Sthenelus and myself will
+still fight on till we reach the goal of Ilius, for heaven was
+with us when we came."
+</para>
+
+<para>
+The sons of the Achaeans shouted applause at the words of Diomed,
+and presently Nestor rose to speak. "Son of Tydeus," said he, "in
+war your prowess is beyond question, and in council you excel all
+who are of your own years; no one of the Achaeans can make light
+of what you say nor gainsay it, but you have not yet come to the
+end of the whole matter. You are still young--you might be the
+youngest of my own children--still you have spoken wisely and
+have counselled the chief of the Achaeans not without discretion;
+nevertheless I am older than you and I will tell you everything;
+therefore let no man, not even King Agamemnon, disregard my
+saying, for he that foments civil discord is a clanless,
+hearthless outlaw.
+</para>
+
+<para>
+"Now, however, let us obey the behests of night and get our
+suppers, but let the sentinels every man of them camp by the
+trench that is without the wall. I am giving these instructions
+to the young men; when they have been attended to, do you, son of
+Atreus, give your orders, for you are the most royal among us
+all. Prepare a feast for your councillors; it is right and
+reasonable that you should do so; there is abundance of wine in
+your tents, which the ships of the Achaeans bring from Thrace
+daily. You have everything at your disposal wherewith to
+entertain guests, and you have many subjects. When many are got
+together, you can be guided by him whose counsel is wisest--and
+sorely do we need shrewd and prudent counsel, for the foe has lit
+his watchfires hard by our ships. Who can be other than dismayed?
+This night will either be the ruin of our host, or save it."
+</para>
+
+<para>
+Thus did he speak, and they did even as he had said. The
+sentinels went out in their armour under command of Nestor's son
+Thrasymedes, a captain of the host, and of the bold warriors
+Ascalaphus and Ialmenus: there were also Meriones, Aphareus and
+Deipyrus, and the son of Creion, noble Lycomedes. There were
+seven captains of the sentinels, and with each there went a
+hundred youths armed with long spears: they took their places
+midway between the trench and the wall, and when they had done so
+they lit their fires and got every man his supper.
+</para>
+
+<para>
+The son of Atreus then bade many councillors of the Achaeans to
+his quarters prepared a great feast in their honour. They laid
+their hands on the good things that were before them, and as soon
+as they had enough to eat and drink, old Nestor, whose counsel
+was ever truest, was the first to lay his mind before them. He,
+therefore, with all sincerity and goodwill addressed them thus.
+</para>
+
+<para>
+"With yourself, most noble son of Atreus, king of men, Agamemnon,
+will I both begin my speech and end it, for you are king over
+much people. Jove, moreover, has vouchsafed you to wield the
+sceptre and to uphold righteousness, that you may take thought
+for your people under you; therefore it behooves you above all
+others both to speak and to give ear, and to out the counsel of
+another who shall have been minded to speak wisely. All turns on
+you and on your commands, therefore I will say what I think will
+be best. No man will be of a truer mind than that which has been
+mine from the hour when you, sir, angered Achilles by taking the
+girl Briseis from his tent against my judgment. I urged you not
+to do so, but you yielded to your own pride, and dishonoured a
+hero whom heaven itself had honoured--for you still hold the
+prize that had been awarded to him. Now, however, let us think
+how we may appease him, both with presents and fair speeches that
+may conciliate him."
+</para>
+
+<para>
+And King Agamemnon answered, "Sir, you have reproved my folly
+justly. I was wrong. I own it. One whom heaven befriends is in
+himself a host, and Jove has shown that he befriends this man by
+destroying much people of the Achaeans. I was blinded with
+passion and yielded to my worser mind; therefore I will make
+amends, and will give him great gifts by way of atonement. I will
+tell them in the presence of you all. I will give him seven
+tripods that have never yet been on the fire, and ten talents of
+gold. I will give him twenty iron cauldrons and twelve strong
+horses that have won races and carried off prizes. Rich, indeed,
+both in land and gold is he that has as many prizes as my horses
+have won me. I will give him seven excellent workwomen, Lesbians,
+whom I chose for myself when he took Lesbos--all of surpassing
+beauty. I will give him these, and with them her whom I erewhile
+took from him, the daughter of Briseus; and I swear a great oath
+that I never went up into her couch, nor have been with her after
+the manner of men and women.
+</para>
+
+<para>
+"All these things will I give him now, and if hereafter the gods
+vouchsafe me to sack the city of Priam, let him come when we
+Achaeans are dividing the spoil, and load his ship with gold and
+bronze to his liking; furthermore let him take twenty Trojan
+women, the loveliest after Helen herself. Then, when we reach
+Achaean Argos, wealthiest of all lands, he shall be my son-in-law
+and I will show him like honour with my own dear son Orestes, who
+is being nurtured in all abundance. I have three daughters,
+Chrysothemis, Laodice, and lphianassa, let him take the one of
+his choice, freely and without gifts of wooing, to the house of
+Peleus; I will add such dower to boot as no man ever yet gave his
+daughter, and will give him seven well established cities,
+Cardamyle, Enope, and Hire, where there is grass; holy Pherae and
+the rich meadows of Anthea; Aepea also, and the vine-clad slopes
+of Pedasus, all near the sea, and on the borders of sandy Pylos.
+The men that dwell there are rich in cattle and sheep; they will
+honour him with gifts as though he were a god, and be obedient to
+his comfortable ordinances. All this will I do if he will now
+forgo his anger. Let him then yield; it is only Hades who is
+utterly ruthless and unyielding--and hence he is of all gods the
+one most hateful to mankind. Moreover I am older and more royal
+than himself. Therefore, let him now obey me."
+</para>
+
+<para>
+Then Nestor answered, "Most noble son of Atreus, king of men,
+Agamemnon. The gifts you offer are no small ones, let us then
+send chosen messengers, who may go to the tent of Achilles son of
+Peleus without delay. Let those go whom I shall name. Let
+Phoenix, dear to Jove, lead the way; let Ajax and Ulysses follow,
+and let the heralds Odius and Eurybates go with them. Now bring
+water for our hands, and bid all keep silence while we pray to
+Jove the son of Saturn, if so be that he may have mercy upon us."
+</para>
+
+<para>
+Thus did he speak, and his saying pleased them well.
+Men-servants poured water over the hands of the guests, while
+pages filled the mixing-bowls with wine and water, and handed it
+round after giving every man his drink-offering; then, when they
+had made their offerings, and had drunk each as much as he was
+minded, the envoys set out from the tent of Agamemnon son of
+Atreus; and Nestor, looking first to one and then to another, but
+most especially at Ulysses, was instant with them that they
+should prevail with the noble son of Peleus.
+</para>
+
+<para>
+They went their way by the shore of the sounding sea, and prayed
+earnestly to earth-encircling Neptune that the high spirit of the
+son of Aeacus might incline favourably towards them. When they
+reached the ships and tents of the Myrmidons, they found Achilles
+playing on a lyre, fair, of cunning workmanship, and its
+cross-bar was of silver. It was part of the spoils which he had
+taken when he sacked the city of Eetion, and he was now diverting
+himself with it and singing the feats of heroes. He was alone
+with Patroclus, who sat opposite to him and said nothing, waiting
+till he should cease singing. Ulysses and Ajax now came in--
+Ulysses leading the way--and stood before him. Achilles sprang
+from his seat with the lyre still in his hand, and Patroclus,
+when he saw the strangers, rose also. Achilles then greeted them
+saying, "All hail and welcome--you must come upon some great
+matter, you, who for all my anger are still dearest to me of the
+Achaeans."
+</para>
+
+<para>
+With this he led them forward, and bade them sit on seats covered
+with purple rugs; then he said to Patroclus who was close by him,
+"Son of Menoetius, set a larger bowl upon the table, mix less
+water with the wine, and give every man his cup, for these are
+very dear friends, who are now under my roof."
+</para>
+
+<para>
+Patroclus did as his comrade bade him; he set the chopping-block
+in front of the fire, and on it he laid the loin of a sheep, the
+loin also of a goat, and the chine of a fat hog. Automedon held
+the meat while Achilles chopped it; he then sliced the pieces and
+put them on spits while the son of Menoetius made the fire burn
+high. When the flame had died down, he spread the embers, laid
+the spits on top of them, lifting them up and setting them upon
+the spit-racks; and he sprinkled them with salt. When the meat
+was roasted, he set it on platters, and handed bread round the
+table in fair baskets, while Achilles dealt them their portions.
+Then Achilles took his seat facing Ulysses against the opposite
+wall, and bade his comrade Patroclus offer sacrifice to the gods;
+so he cast the offerings into the fire, and they laid their hands
+upon the good things that were before them. As soon as they had
+had enough to eat and drink, Ajax made a sign to Phoenix, and
+when he saw this, Ulysses filled his cup with wine and pledged
+Achilles.
+</para>
+
+<para>
+"Hail," said he, "Achilles, we have had no scant of good cheer,
+neither in the tent of Agamemnon, nor yet here; there has been
+plenty to eat and drink, but our thought turns upon no such
+matter. Sir, we are in the face of great disaster, and without
+your help know not whether we shall save our fleet or lose it.
+The Trojans and their allies have camped hard by our ships and by
+the wall; they have lit watchfires throughout their host and deem
+that nothing can now prevent them from falling on our fleet.
+Jove, moreover, has sent his lightnings on their right; Hector,
+in all his glory, rages like a maniac; confident that Jove is
+with him he fears neither god nor man, but is gone raving mad,
+and prays for the approach of day. He vows that he will hew the
+high sterns of our ships in pieces, set fire to their hulls, and
+make havoc of the Achaeans while they are dazed and smothered in
+smoke; I much fear that heaven will make good his boasting, and
+it will prove our lot to perish at Troy far from our home in
+Argos. Up, then, and late though it be, save the sons of the
+Achaeans who faint before the fury of the Trojans. You will
+repent bitterly hereafter if you do not, for when the harm is
+done there will be no curing it; consider ere it be too late, and
+save the Danaans from destruction.
+</para>
+
+<para>
+"My good friend, when your father Peleus sent you from Phthia to
+Agamemnon, did he not charge you saying, 'Son, Minerva and Juno
+will make you strong if they choose, but check your high temper,
+for the better part is in goodwill. Eschew vain quarrelling, and
+the Achaeans old and young will respect you more for doing so.'
+These were his words, but you have forgotten them. Even now,
+however, be appeased, and put away your anger from you. Agamemnon
+will make you great amends if you will forgive him; listen, and I
+will tell you what he has said in his tent that he will give you.
+He will give you seven tripods that have never yet been on the
+fire, and ten talents of gold; twenty iron cauldrons, and twelve
+strong horses that have won races and carried off prizes. Rich
+indeed both in land and gold is he who has as many prizes as
+these horses have won for Agamemnon. Moreover he will give you
+seven excellent workwomen, Lesbians, whom he chose for himself,
+when you took Lesbos--all of surpassing beauty. He will give you
+these, and with them her whom he erewhile took from you, the
+daughter of Briseus, and he will swear a great oath, he has never
+gone up into her couch nor been with her after the manner of men
+and women. All these things will he give you now down, and if
+hereafter the gods vouchsafe him to sack the city of Priam, you
+can come when we Achaeans are dividing the spoil, and load your
+ship with gold and bronze to your liking. You can take twenty
+Trojan women, the loveliest after Helen herself. Then, when we
+reach Achaean Argos, wealthiest of all lands, you shall be his
+son-in-law, and he will show you like honour with his own dear
+son Orestes, who is being nurtured in all abundance. Agamemnon
+has three daughters, Chrysothemis, Laodice, and Iphianassa; you
+may take the one of your choice, freely and without gifts of
+wooing, to the house of Peleus; he will add such dower to boot as
+no man ever yet gave his daughter, and will give you seven
+well-established cities, Cardamyle, Enope, and Hire where there
+is grass; holy Pheras and the rich meadows of Anthea; Aepea also,
+and the vine-clad slopes of Pedasus, all near the sea, and on the
+borders of sandy Pylos. The men that dwell there are rich in
+cattle and sheep; they will honour you with gifts as though were
+a god, and be obedient to your comfortable ordinances. All this
+will he do if you will now forgo your anger. Moreover, though you
+hate both him and his gifts with all your heart, yet pity the
+rest of the Achaeans who are being harassed in all their host;
+they will honour you as a god, and you will earn great glory at
+their hands. You might even kill Hector; he will come within your
+reach, for he is infatuated, and declares that not a Danaan whom
+the ships have brought can hold his own against him."
+</para>
+
+<para>
+Achilles answered, "Ulysses, noble son of Laertes, I should give
+you formal notice plainly and in all fixity of purpose that there
+be no more of this cajoling, from whatsoever quarter it may come.
+Him do I hate even as the gates of hell who says one thing while
+he hides another in his heart; therefore I will say what I mean.
+I will be appeased neither by Agamemnon son of Atreus nor by any
+other of the Danaans, for I see that I have no thanks for all my
+fighting. He that fights fares no better than he that does not;
+coward and hero are held in equal honour, and death deals like
+measure to him who works and him who is idle. I have taken
+nothing by all my hardships--with my life ever in my hand; as a
+bird when she has found a morsel takes it to her nestlings, and
+herself fares hardly, even so many a long night have I been
+wakeful, and many a bloody battle have I waged by day against
+those who were fighting for their women. With my ships I have
+taken twelve cities, and eleven round about Troy have I stormed
+with my men by land; I took great store of wealth from every one
+of them, but I gave all up to Agamemnon son of Atreus. He stayed
+where he was by his ships, yet of what came to him he gave
+little, and kept much himself.
+</para>
+
+<para>
+"Nevertheless he did distribute some meeds of honour among the
+chieftains and kings, and these have them still; from me alone of
+the Achaeans did he take the woman in whom I delighted--let him
+keep her and sleep with her. Why, pray, must the Argives needs
+fight the Trojans? What made the son of Atreus gather the host
+and bring them? Was it not for the sake of Helen? Are the sons of
+Atreus the only men in the world who love their wives? Any man of
+common right feeling will love and cherish her who is his own, as
+I this woman, with my whole heart, though she was but a fruitling
+of my spear. Agamemnon has taken her from me; he has played me
+false; I know him; let him tempt me no further, for he shall not
+move me. Let him look to you, Ulysses, and to the other princes
+to save his ships from burning. He has done much without me
+already. He has built a wall; he has dug a trench deep and wide
+all round it, and he has planted it within with stakes; but even
+so he stays not the murderous might of Hector. So long as I
+fought the Achaeans Hector suffered not the battle range far from
+the city walls; he would come to the Scaean gates and to the oak
+tree, but no further. Once he stayed to meet me and hardly did he
+escape my onset: now, however, since I am in no mood to fight
+him, I will to-morrow offer sacrifice to Jove and to all the
+gods; I will draw my ships into the water and then victual them
+duly; to-morrow morning, if you care to look, you will see my
+ships on the Hellespont, and my men rowing out to sea with might
+and main. If great Neptune vouchsafes me a fair passage, in three
+days I shall be in Phthia. I have much there that I left behind
+me when I came here to my sorrow, and I shall bring back still
+further store of gold, of red copper, of fair women, and of iron,
+my share of the spoils that we have taken; but one prize, he who
+gave has insolently taken away. Tell him all as I now bid you,
+and tell him in public that the Achaeans may hate him and beware
+of him should he think that he can yet dupe others for his
+effrontery never fails him.
+</para>
+
+<para>
+"As for me, hound that he is, he dares not look me in the face.
+I will take no counsel with him, and will undertake nothing in
+common with him. He has wronged me and deceived me enough, he
+shall not cozen me further; let him go his own way, for Jove has
+robbed him of his reason. I loathe his presents, and for himself
+care not one straw. He may offer me ten or even twenty times what
+he has now done, nay--not though it be all that he has in the
+world, both now or ever shall have; he may promise me the wealth
+of Orchomenus or of Egyptian Thebes, which is the richest city in
+the whole world, for it has a hundred gates through each of which
+two hundred men may drive at once with their chariots and horses;
+he may offer me gifts as the sands of the sea or the dust of the
+plain in multitude, but even so he shall not move me till I have
+been revenged in full for the bitter wrong he has done me. I will
+not marry his daughter; she may be fair as Venus, and skilful as
+Minerva, but I will have none of her: let another take her, who
+may be a good match for her and who rules a larger kingdom. If
+the gods spare me to return home, Peleus will find me a wife;
+there are Achaean women in Hellas and Phthia, daughters of kings
+that have cities under them; of these I can take whom I will and
+marry her. Many a time was I minded when at home in Phthia to woo
+and wed a woman who would make me a suitable wife, and to enjoy
+the riches of my old father Peleus. My life is more to me than
+all the wealth of Ilius while it was yet at peace before the
+Achaeans went there, or than all the treasure that lies on the
+stone floor of Apollo's temple beneath the cliffs of Pytho.
+Cattle and sheep are to be had for harrying, and a man buy both
+tripods and horses if he wants them, but when his life has once
+left him it can neither be bought nor harried back again.
+</para>
+
+<para>
+"My mother Thetis tells me that there are two ways in which I may
+meet my end. If I stay here and fight, I shall not return alive
+but my name will live for ever: whereas if I go home my name will
+die, but it will be long ere death shall take me. To the rest of
+you, then, I say, 'Go home, for you will not take Ilius.' Jove
+has held his hand over her to protect her, and her people have
+taken heart. Go, therefore, as in duty bound, and tell the
+princes of the Achaeans the message that I have sent them; tell
+them to find some other plan for the saving of their ships and
+people, for so long as my displeasure lasts the one that they
+have now hit upon may not be. As for Phoenix, let him sleep here
+that he may sail with me in the morning if he so will. But I
+will not take him by force."
+</para>
+
+<para>
+They all held their peace, dismayed at the sternness with which
+he had denied them, till presently the old knight Phoenix in his
+great fear for the ships of the Achaeans, burst into tears and
+said, "Noble Achilles, if you are now minded to return, and in
+the fierceness of your anger will do nothing to save the ships
+from burning, how, my son, can I remain here without you? Your
+father Peleus bade me go with you when he sent you as a mere lad
+from Phthia to Agamemnon. You knew nothing neither of war nor of
+the arts whereby men make their mark in council, and he sent me
+with you to train you in all excellence of speech and action.
+Therefore, my son, I will not stay here without you--no, not
+though heaven itself vouchsafe to strip my years from off me, and
+make me young as I was when I first left Hellas the land of fair
+women. I was then flying the anger of father Amyntor, son of
+Ormenus, who was furious with me in the matter of his concubine,
+of whom he was enamoured to the wronging of his wife my mother.
+My mother, therefore, prayed me without ceasing to lie with the
+woman myself, that so she hate my father, and in the course of
+time I yielded. But my father soon came to know, and cursed me
+bitterly, calling the dread Erinyes to witness. He prayed that no
+son of mine might ever sit upon knees--and the gods, Jove of the
+world below and awful Proserpine, fulfilled his curse. I took
+counsel to kill him, but some god stayed my rashness and bade me
+think on men's evil tongues and how I should be branded as the
+murderer of my father; nevertheless I could not bear to stay in
+my father's house with him so bitter a against me. My cousins and
+clansmen came about me, and pressed me sorely to remain; many a
+sheep and many an ox did they slaughter, and many a fat hog did
+they set down to roast before the fire; many a jar, too, did they
+broach of my father's wine. Nine whole nights did they set a
+guard over me taking it in turns to watch, and they kept a fire
+always burning, both in the cloister of the outer court and in
+the inner court at the doors of the room wherein I lay; but when
+the darkness of the tenth night came, I broke through the closed
+doors of my room, and climbed the wall of the outer court after
+passing quickly and unperceived through the men on guard and the
+women servants. I then fled through Hellas till I came to fertile
+Phthia, mother of sheep, and to King Peleus, who made me welcome
+and treated me as a father treats an only son who will be heir to
+all his wealth. He made me rich and set me over much people,
+establishing me on the borders of Phthia where I was chief ruler
+over the Dolopians.
+</para>
+
+<para>
+"It was I, Achilles, who had the making of you; I loved you with
+all my heart: for you would eat neither at home nor when you had
+gone out elsewhere, till I had first set you upon my knees, cut
+up the dainty morsel that you were to eat, and held the wine-cup
+to your lips. Many a time have you slobbered your wine in baby
+helplessness over my shirt; I had infinite trouble with you, but
+I knew that heaven had vouchsafed me no offspring of my own, and
+I made a son of you, Achilles, that in my hour of need you might
+protect me. Now, therefore, I say battle with your pride and beat
+it; cherish not your anger for ever; the might and majesty of
+heaven are more than ours, but even heaven may be appeased; and
+if a man has sinned he prays the gods, and reconciles them to
+himself by his piteous cries and by frankincense, with
+drink-offerings and the savour of burnt sacrifice. For prayers
+are as daughters to great Jove; halt, wrinkled, with eyes
+askance, they follow in the footsteps of sin, who, being fierce
+and fleet of foot, leaves them far behind him, and ever baneful
+to mankind outstrips them even to the ends of the world; but
+nevertheless the prayers come hobbling and healing after. If a
+man has pity upon these daughters of Jove when they draw near
+him, they will bless him and hear him too when he is praying; but
+if he deny them and will not listen to them, they go to Jove the
+son of Saturn and pray that he may presently fall into sin--to
+his ruing bitterly hereafter. Therefore, Achilles, give these
+daughters of Jove due reverence, and bow before them as all good
+men will bow. Were not the son of Atreus offering you gifts and
+promising others later--if he were still furious and implacable--
+I am not he that would bid you throw off your anger and help the
+Achaeans, no matter how great their need; but he is giving much
+now, and more hereafter; he has sent his captains to urge his
+suit, and has chosen those who of all the Argives are most
+acceptable to you; make not then their words and their coming to
+be of none effect. Your anger has been righteous so far. We have
+heard in song how heroes of old time quarrelled when they were
+roused to fury, but still they could be won by gifts, and fair
+words could soothe them.
+</para>
+
+<para>
+"I have an old story in my mind--a very old one--but you are all
+friends and I will tell it. The Curetes and the Aetolians were
+fighting and killing one another round Calydon--the Aetolians
+defending the city and the Curetes trying to destroy it. For
+Diana of the golden throne was angry and did them hurt because
+Oeneus had not offered her his harvest first-fruits. The other
+gods had all been feasted with hecatombs, but to the daughter of
+great Jove alone he had made no sacrifice. He had forgotten her,
+or somehow or other it had escaped him, and this was a grievous
+sin. Thereon the archer goddess in her displeasure sent a
+prodigious creature against him--a savage wild boar with great
+white tusks that did much harm to his orchard lands, uprooting
+apple-trees in full bloom and throwing them to the ground. But
+Meleager son of Oeneus got huntsmen and hounds from many cities
+and killed it--for it was so monstrous that not a few were
+needed, and many a man did it stretch upon his funeral pyre. On
+this the goddess set the Curetes and the Aetolians fighting
+furiously about the head and skin of the boar.
+</para>
+
+<para>
+"So long as Meleager was in the field things went badly with the
+Curetes, and for all their numbers they could not hold their
+ground under the city walls; but in the course of time Meleager
+was angered as even a wise man will sometimes be. He was incensed
+with his mother Althaea, and therefore stayed at home with his
+wedded wife fair Cleopatra, who was daughter of Marpessa daughter
+of Euenus, and of Ides the man then living. He it was who took
+his bow and faced King Apollo himself for fair Marpessa's sake;
+her father and mother then named her Alcyone, because her mother
+had mourned with the plaintive strains of the halcyon-bird when
+Phoebus Apollo had carried her off. Meleager, then, stayed at
+home with Cleopatra, nursing the anger which he felt by reason of
+his mother's curses. His mother, grieving for the death of her
+brother, prayed the gods, and beat the earth with her hands,
+calling upon Hades and on awful Proserpine; she went down upon
+her knees and her bosom was wet with tears as she prayed that
+they would kill her son--and Erinys that walks in darkness and
+knows no ruth heard her from Erebus.
+</para>
+
+<para>
+"Then was heard the din of battle about the gates of Calydon, and
+the dull thump of the battering against their walls. Thereon the
+elders of the Aetolians besought Meleager; they sent the chiefest
+of their priests, and begged him to come out and help them,
+promising him a great reward. They bade him choose fifty
+plough-gates, the most fertile in the plain of Calydon, the
+one-half vineyard and the other open plough-land. The old warrior
+Oeneus implored him, standing at the threshold of his room and
+beating the doors in supplication. His sisters and his mother
+herself besought him sore, but he the more refused them; those of
+his comrades who were nearest and dearest to him also prayed him,
+but they could not move him till the foe was battering at the
+very doors of his chamber, and the Curetes had scaled the walls
+and were setting fire to the city. Then at last his sorrowing
+wife detailed the horrors that befall those whose city is taken;
+she reminded him how the men are slain, and the city is given
+over to the flames, while the women and children are carried into
+captivity; when he heard all this, his heart was touched, and he
+donned his armour to go forth. Thus of his own inward motion he
+saved the city of the Aetolians; but they now gave him nothing of
+those rich rewards that they had offered earlier, and though he
+saved the city he took nothing by it. Be not then, my son, thus
+minded; let not heaven lure you into any such course. When the
+ships are burning it will be a harder matter to save them. Take
+the gifts, and go, for the Achaeans will then honour you as a
+god; whereas if you fight without taking them, you may beat the
+battle back, but you will not be held in like honour."
+</para>
+
+<para>
+And Achilles answered, "Phoenix, old friend and father, I have no
+need of such honour. I have honour from Jove himself, which will
+abide with me at my ships while I have breath in my body, and my
+limbs are strong. I say further--and lay my saying to your
+heart--vex me no more with this weeping and lamentation, all in
+the cause of the son of Atreus. Love him so well, and you may
+lose the love I bear you. You ought to help me rather in
+troubling those that trouble me; be king as much as I am, and
+share like honour with myself; the others shall take my answer;
+stay here yourself and sleep comfortably in your bed; at daybreak
+we will consider whether to remain or go."
+</para>
+
+<para>
+On this she nodded quietly to Patroclus as a sign that he was to
+prepare a bed for Phoenix, and that the others should take their
+leave. Ajax son of Telamon then said, "Ulysses, noble son of
+Laertes, let us be gone, for I see that our journey is vain. We
+must now take our answer, unwelcome though it be, to the Danaans
+who are waiting to receive it. Achilles is savage and
+remorseless; he is cruel, and cares nothing for the love his
+comrades lavished upon him more than on all the others. He is
+implacable--and yet if a man's brother or son has been slain he
+will accept a fine by way of amends from him that killed him, and
+the wrong-doer having paid in full remains in peace among his own
+people; but as for you, Achilles, the gods have put a wicked
+unforgiving spirit in your heart, and this, all about one single
+girl, whereas we now offer you the seven best we have, and much
+else into the bargain. Be then of a more gracious mind, respect
+the hospitality of your own roof. We are with you as messengers
+from the host of the Danaans, and would fain he held nearest and
+dearest to yourself of all the Achaeans."
+</para>
+
+<para>
+"Ajax," replied Achilles, "noble son of Telamon, you have spoken
+much to my liking, but my blood boils when I think it all over,
+and remember how the son of Atreus treated me with contumely as
+though I were some vile tramp, and that too in the presence of
+the Argives. Go, then, and deliver your message; say that I will
+have no concern with fighting till Hector, son of noble Priam,
+reaches the tents of the Myrmidons in his murderous course, and
+flings fire upon their ships. For all his lust of battle, I take
+it he will be held in check when he is at my own tent and ship."
+</para>
+
+<para>
+On this they took every man his double cup, made their
+drink-offerings, and went back to the ships, Ulysses leading the
+way. But Patroclus told his men and the maid-servants to make
+ready a comfortable bed for Phoenix; they therefore did so with
+sheepskins, a rug, and a sheet of fine linen. The old man then
+laid himself down and waited till morning came. But Achilles
+slept in an inner room, and beside him the daughter of Phorbas
+lovely Diomede, whom he had carried off from Lesbos. Patroclus
+lay on the other side of the room, and with him fair Iphis whom
+Achilles had given him when he took Scyros the city of Enyeus.
+</para>
+
+<para>
+When the envoys reached the tents of the son of Atreus, the
+Achaeans rose, pledged them in cups of gold, and began to
+question them. King Agamemnon was the first to do so. "Tell me,
+Ulysses," said he, "will he save the ships from burning, or did
+be refuse, and is he still furious?"
+</para>
+
+<para>
+Ulysses answered, "Most noble son of Atreus, king of men,
+Agamemnon, Achilles will not be calmed, but is more fiercely
+angry than ever, and spurns both you and your gifts. He bids you
+take counsel with the Achaeans to save the ships and host as you
+best may; as for himself, he said that at daybreak he should draw
+his ships into the water. He said further that he should advise
+every one to sail home likewise, for that you will not reach the
+goal of Ilius. 'Jove,' he said, 'has laid his hand over the city
+to protect it, and the people have taken heart.' This is what he
+said, and the others who were with me can tell you the same
+story--Ajax and the two heralds, men, both of them, who may be
+trusted. The old man Phoenix stayed where he was to sleep, for so
+Achilles would have it, that he might go home with him in the
+morning if he so would; but he will not take him by force."
+</para>
+
+<para>
+They all held their peace, sitting for a long time silent and
+dejected, by reason of the sternness with which Achilles had
+refused them, till presently Diomed said, "Most noble son of
+Atreus, king of men, Agamemnon, you ought not to have sued the
+son of Peleus nor offered him gifts. He is proud enough as it is,
+and you have encouraged him in his pride still further. Let him
+stay or go as he will. He will fight later when he is in the
+humour, and heaven puts it in his mind to do so. Now, therefore,
+let us all do as I say; we have eaten and drunk our fill, let us
+then take our rest, for in rest there is both strength and stay.
+But when fair rosy-fingered morn appears, forthwith bring out
+your host and your horsemen in front of the ships, urging them
+on, and yourself fighting among the foremost."
+</para>
+
+<para>
+Thus he spoke, and the other chieftains approved his words. They
+then made their drink-offerings and went every man to his own
+tent, where they laid down to rest and enjoyed the boon of sleep.
+</para>
+</chapter>
+
+<chapter>
+<title>BOOK X</title>
+
+<para>
+NOW the other princes of the Achaeans slept soundly the whole
+night through, but Agamemnon son of Atreus was troubled, so that
+he could get no rest. As when fair Juno's lord flashes his
+lightning in token of great rain or hail or snow when the
+snow-flakes whiten the ground, or again as a sign that he will
+open the wide jaws of hungry war, even so did Agamemnon heave
+many a heavy sigh, for his soul trembled within him. When he
+looked upon the plain of Troy he marvelled at the many watchfires
+burning in front of Ilius, and at the sound of pipes and flutes
+and of the hum of men, but when presently he turned towards the
+ships and hosts of the Achaeans, he tore his hair by handfuls
+before Jove on high, and groaned aloud for the very disquietness
+of his soul. In the end he deemed it best to go at once to Nestor
+son of Neleus, and see if between them they could find any way of
+the Achaeans from destruction. He therefore rose, put on his
+shirt, bound his sandals about his comely feet, flung the skin of
+a huge tawny lion over his shoulders--a skin that reached his
+feet--and took his spear in his hand.
+</para>
+
+<para>
+Neither could Menelaus sleep, for he, too, boded ill for the
+Argives who for his sake had sailed from far over the seas to
+fight the Trojans. He covered his broad back with the skin of a
+spotted panther, put a casque of bronze upon his head, and took
+his spear in his brawny hand. Then he went to rouse his brother,
+who was by far the most powerful of the Achaeans, and was
+honoured by the people as though he were a god. He found him by
+the stern of his ship already putting his goodly array about his
+shoulders, and right glad was he that his brother had come.
+</para>
+
+<para>
+Menelaus spoke first. "Why," said he, "my dear brother, are you
+thus arming? Are you going to send any of our comrades to exploit
+the Trojans? I greatly fear that no one will do you this service,
+and spy upon the enemy alone in the dead of night. It will be a
+deed of great daring."
+</para>
+
+<para>
+And King Agamemnon answered, "Menelaus, we both of us need shrewd
+counsel to save the Argives and our ships, for Jove has changed
+his mind, and inclines towards Hector's sacrifices rather than
+ours. I never saw nor heard tell of any man as having wrought
+such ruin in one day as Hector has now wrought against the sons
+of the Achaeans--and that too of his own unaided self, for he is
+son neither to god nor goddess. The Argives will rue it long and
+deeply. Run, therefore, with all speed by the line of the ships,
+and call Ajax and Idomeneus. Meanwhile I will go to Nestor, and
+bid him rise and go about among the companies of our sentinels to
+give them their instructions; they will listen to him sooner than
+to any man, for his own son, and Meriones brother in arms to
+Idomeneus, are captains over them. It was to them more
+particularly that we gave this charge."
+</para>
+
+<para>
+Menelaus replied, "How do I take your meaning? Am I to stay with
+them and wait your coming, or shall I return here as soon as I
+have given your orders?" "Wait," answered King Agamemnon, "for
+there are so many paths about the camp that we might miss one
+another. Call every man on your way, and bid him be stirring;
+name him by his lineage and by his father's name, give each all
+titular observance, and stand not too much upon your own dignity;
+we must take our full share of toil, for at our birth Jove laid
+this heavy burden upon us."
+</para>
+
+<para>
+With these instructions he sent his brother on his way, and went
+on to Nestor shepherd of his people. He found him sleeping in his
+tent hard by his own ship; his goodly armour lay beside him--his
+shield, his two spears and his helmet; beside him also lay the
+gleaming girdle with which the old man girded himself when he
+armed to lead his people into battle--for his age stayed him not.
+He raised himself on his elbow and looked up at Agamemnon. "Who
+is it," said he, "that goes thus about the host and the ships
+alone and in the dead of night, when men are sleeping? Are you
+looking for one of your mules or for some comrade? Do not stand
+there and say nothing, but speak. What is your business?"
+</para>
+
+<para>
+And Agamemnon answered, "Nestor, son of Neleus, honour to the
+Achaean name, it is I, Agamemnon son of Atreus, on whom Jove has
+laid labour and sorrow so long as there is breath in my body and
+my limbs carry me. I am thus abroad because sleep sits not upon
+my eyelids, but my heart is big with war and with the jeopardy of
+the Achaeans. I am in great fear for the Danaans. I am at sea,
+and without sure counsel; my heart beats as though it would leap
+out of my body, and my limbs fail me. If then you can do
+anything--for you too cannot sleep--let us go the round of the
+watch, and see whether they are drowsy with toil and sleeping to
+the neglect of their duty. The enemy is encamped hard and we know
+not but he may attack us by night."
+</para>
+
+<para>
+Nestor replied, "Most noble son of Atreus, king of men,
+Agamemnon, Jove will not do all for Hector that Hector thinks he
+will; he will have troubles yet in plenty if Achilles will lay
+aside his anger. I will go with you, and we will rouse others,
+either the son of Tydeus, or Ulysses, or fleet Ajax and the
+valiant son of Phyleus. Some one had also better go and call Ajax
+and King Idomeneus, for their ships are not near at hand but the
+farthest of all. I cannot however refrain from blaming Menelaus,
+much as I love him and respect him--and I will say so plainly,
+even at the risk of offending you--for sleeping and leaving all
+this trouble to yourself. He ought to be going about imploring
+aid from all the princes of the Achaeans, for we are in extreme
+danger."
+</para>
+
+<para>
+And Agamemnon answered, "Sir, you may sometimes blame him justly,
+for he is often remiss and unwilling to exert himself--not
+indeed from sloth, nor yet heedlessness, but because he looks to
+me and expects me to take the lead. On this occasion, however, he
+was awake before I was, and came to me of his own accord. I have
+already sent him to call the very men whom you have named. And
+now let us be going. We shall find them with the watch outside
+the gates, for it was there I said that we would meet them."
+</para>
+
+<para>
+"In that case," answered Nestor, "the Argives will not blame him
+nor disobey his orders when he urges them to fight or gives them
+instructions."
+</para>
+
+<para>
+With this he put on his shirt, and bound his sandals about his
+comely feet. He buckled on his purple coat, of two thicknesses,
+large, and of a rough shaggy texture, grasped his redoubtable
+bronze-shod spear, and wended his way along the line of the
+Achaean ships. First he called loudly to Ulysses peer of gods in
+counsel and woke him, for he was soon roused by the sound of the
+battle-cry. He came outside his tent and said, "Why do you go
+thus alone about the host, and along the line of the ships in the
+stillness of the night? What is it that you find so urgent?" And
+Nestor knight of Gerene answered, "Ulysses, noble son of Laertes,
+take it not amiss, for the Achaeans are in great straits. Come
+with me and let us wake some other, who may advise well with us
+whether we shall fight or fly."
+</para>
+
+<para>
+On this Ulysses went at once into his tent, put his shield about
+his shoulders and came out with them. First they went to Diomed
+son of Tydeus, and found him outside his tent clad in his armour
+with his comrades sleeping round him and using their shields as
+pillows; as for their spears, they stood upright on the spikes of
+their butts that were driven into the ground, and the burnished
+bronze flashed afar like the lightning of father Jove. The hero
+was sleeping upon the skin of an ox, with a piece of fine carpet
+under his head; Nestor went up to him and stirred him with his
+heel to rouse him, upbraiding him and urging him to bestir
+himself. "Wake up," he exclaimed, "son of Tydeus. How can you
+sleep on in this way? Can you not see that the Trojans are
+encamped on the brow of the plain hard by our ships, with but a
+little space between us and them?"
+</para>
+
+<para>
+On these words Diomed leaped up instantly and said, "Old man,
+your heart is of iron; you rest not one moment from your labours.
+Are there no younger men among the Achaeans who could go about to
+rouse the princes? There is no tiring you."
+</para>
+
+<para>
+And Nestor knight of Gerene made answer, "My son, all that you
+have said is true. I have good sons, and also much people who
+might call the chieftains, but the Achaeans are in the gravest
+danger; life and death are balanced as it were on the edge of a
+razor. Go then, for you are younger than I, and of your courtesy
+rouse Ajax and the fleet son of Phyleus."
+</para>
+
+<para>
+Diomed threw the skin of a great tawny lion about his shoulders--
+a skin that reached his feet--and grasped his spear. When he had
+roused the heroes, he brought them back with him; they then went
+the round of those who were on guard, and found the captains not
+sleeping at their posts but wakeful and sitting with their arms
+about them. As sheep dogs that watch their flocks when they are
+yarded, and hear a wild beast coming through the mountain forest
+towards them--forthwith there is a hue and cry of dogs and men,
+and slumber is broken--even so was sleep chased from the eyes of
+the Achaeans as they kept the watches of the wicked night, for
+they turned constantly towards the plain whenever they heard any
+stir among the Trojans. The old man was glad bade them be of good
+cheer. "Watch on, my children," said he, "and let not sleep get
+hold upon you, lest our enemies triumph over us."
+</para>
+
+<para>
+With this he passed the trench, and with him the other chiefs of
+the Achaeans who had been called to the council. Meriones and the
+brave son of Nestor went also, for the princes bade them. When
+they were beyond the trench that was dug round the wall they held
+their meeting on the open ground where there was a space clear of
+corpses, for it was here that when night fell Hector had turned
+back from his onslaught on the Argives. They sat down, therefore,
+and held debate with one another.
+</para>
+
+<para>
+Nestor spoke first. "My friends," said he, "is there any man bold
+enough to venture the Trojans, and cut off some straggler, or us
+news of what the enemy mean to do whether they will stay here by
+the ships away from the city, or whether, now that they have
+worsted the Achaeans, they will retire within their walls. If he
+could learn all this and come back safely here, his fame would be
+high as heaven in the mouths of all men, and he would be rewarded
+richly; for the chiefs from all our ships would each of them give
+him a black ewe with her lamb--which is a present of surpassing
+value--and he would be asked as a guest to all feasts and
+clan-gatherings."
+</para>
+
+<para>
+They all held their peace, but Diomed of the loud war-cry spoke
+saying, "Nestor, gladly will I visit the host of the Trojans over
+against us, but if another will go with me I shall do so in
+greater confidence and comfort. When two men are together, one of
+them may see some opportunity which the other has not caught
+sight of; if a man is alone he is less full of resource, and his
+wit is weaker."
+</para>
+
+<para>
+On this several offered to go with Diomed. The two Ajaxes,
+servants of Mars, Meriones, and the son of Nestor all wanted to
+go, so did Menelaus son of Atreus; Ulysses also wished to go
+among the host of the Trojans, for he was ever full of daring,
+and thereon Agamemnon king of men spoke thus: "Diomed," said he,
+"son of Tydeus, man after my own heart, choose your comrade for
+yourself--take the best man of those that have offered, for many
+would now go with you. Do not through delicacy reject the better
+man, and take the worst out of respect for his lineage, because
+he is of more royal blood."
+</para>
+
+<para>
+He said this because he feared for Menelaus. Diomed answered, "If
+you bid me take the man of my own choice, how in that case can I
+fail to think of Ulysses, than whom there is no man more eager to
+face all kinds of danger--and Pallas Minerva loves him well? If
+he were to go with me we should pass safely through fire itself,
+for he is quick to see and understand."
+</para>
+
+<para>
+"Son of Tydeus," replied Ulysses, "say neither good nor ill about
+me, for you are among Argives who know me well. Let us be going,
+for the night wanes and dawn is at hand. The stars have gone
+forward, two-thirds of the night are already spent, and the third
+is alone left us."
+</para>
+
+<para>
+They then put on their armour. Brave Thrasymedes provided the son
+of Tydeus with a sword and a shield (for he had left his own at
+his ship) and on his head he set a helmet of bull's hide without
+either peak or crest; it is called a skull-cap and is a common
+headgear. Meriones found a bow and quiver for Ulysses, and on his
+head he set a leathern helmet that was lined with a strong
+plaiting of leathern thongs, while on the outside it was thickly
+studded with boar's teeth, well and skilfully set into it; next
+the head there was an inner lining of felt. This helmet had been
+stolen by Autolycus out of Eleon when he broke into the house of
+Amyntor son of Ormenus. He gave it to Amphidamas of Cythera to
+take to Scandea, and Amphidamas gave it as a guest-gift to Molus,
+who gave it to his son Meriones; and now it was set upon the head
+of Ulysses.
+</para>
+
+<para>
+When the pair had armed, they set out, and left the other
+chieftains behind them. Pallas Minerva sent them a heron by the
+wayside upon their right hands; they could not see it for the
+darkness, but they heard its cry. Ulysses was glad when he heard
+it and prayed to Minerva: "Hear me," he cried, "daughter of
+aegis-bearing Jove, you who spy out all my ways and who are with
+me in all my hardships; befriend me in this mine hour, and grant
+that we may return to the ships covered with glory after having
+achieved some mighty exploit that shall bring sorrow to the
+Trojans."
+</para>
+
+<para>
+Then Diomed of the loud war-cry also prayed: "Hear me too," said
+he, "daughter of Jove, unweariable; be with me even as you were
+with my noble father Tydeus when he went to Thebes as envoy sent
+by the Achaeans. He left the Achaeans by the banks of the river
+Aesopus, and went to the city bearing a message of peace to the
+Cadmeians; on his return thence, with your help, goddess, he did
+great deeds of daring, for you were his ready helper. Even so
+guide me and guard me now, and in return I will offer you in
+sacrifice a broad-browed heifer of a year old, unbroken, and
+never yet brought by man under the yoke. I will gild her horns
+and will offer her up to you in sacrifice."
+</para>
+
+<para>
+Thus they prayed, and Pallas Minerva heard their prayer. When
+they had done praying to the daughter of great Jove, they went
+their way like two lions prowling by night amid the armour and
+blood-stained bodies of them that had fallen.
+</para>
+
+<para>
+Neither again did Hector let the Trojans sleep; for he too called
+the princes and councillors of the Trojans that he might set his
+counsel before them. "Is there one," said he, "who for a great
+reward will do me the service of which I will tell you? He shall
+be well paid if he will. I will give him a chariot and a couple
+of horses, the fleetest that can be found at the ships of the
+Achaeans, if he will dare this thing; and he will win infinite
+honour to boot; he must go to the ships and find out whether they
+are still guarded as heretofore, or whether now that we have
+beaten them the Achaeans design to fly, and through sheer
+exhaustion are neglecting to keep their watches."
+</para>
+
+<para>
+They all held their peace; but there was among the Trojans a
+certain man named Dolon, son of Eumedes, the famous herald--a man
+rich in gold and bronze. He was ill-favoured, but a good runner,
+and was an only son among five sisters. He it was that now
+addressed the Trojans. "I, Hector," said he, "Will to the ships
+and will exploit them. But first hold up your sceptre and swear
+that you will give me the chariot, bedight with bronze, and the
+horses that now carry the noble son of Peleus. I will make you a
+good scout, and will not fail you. I will go through the host
+from one end to the other till I come to the ship of Agamemnon,
+where I take it the princes of the Achaeans are now consulting
+whether they shall fight or fly."
+</para>
+
+<para>
+When he had done speaking Hector held up his sceptre, and swore
+him his oath saying, "May Jove the thundering husband of Juno
+bear witness that no other Trojan but yourself shall mount those
+steeds, and that you shall have your will with them for ever."
+</para>
+
+<para>
+The oath he swore was bootless, but it made Dolon more keen on
+going. He hung his bow over his shoulder, and as an overall he
+wore the skin of a grey wolf, while on his head he set a cap of
+ferret skin. Then he took a pointed javelin, and left the camp
+for the ships, but he was not to return with any news for Hector.
+When he had left the horses and the troops behind him, he made
+all speed on his way, but Ulysses perceived his coming and said
+to Diomed, "Diomed, here is some one from the camp; I am not sure
+whether he is a spy, or whether it is some thief who would
+plunder the bodies of the dead; let him get a little past us, we
+can then spring upon him and take him. If, however, he is too
+quick for us, go after him with your spear and hem him in towards
+the ships away from the Trojan camp, to prevent his getting back
+to the town."
+</para>
+
+<para>
+With this they turned out of their way and lay down among the
+corpses. Dolon suspected nothing and soon passed them, but when
+he had got about as far as the distance by which a mule-plowed
+furrow exceeds one that has been ploughed by oxen (for mules can
+plow fallow land quicker than oxen) they ran after him, and when
+he heard their footsteps he stood still, for he made sure they
+were friends from the Trojan camp come by Hector's orders to bid
+him return; when, however, they were only a spear's cast, or less
+away form him, he saw that they were enemies as fast as his legs
+could take him. The others gave chase at once, and as a couple of
+well-trained hounds press forward after a doe or hare that runs
+screaming in front of them, even so did the son of Tydeus and
+Ulysses pursue Dolon and cut him off from his own people. But
+when he had fled so far towards the ships that he would soon have
+fallen in with the outposts, Minerva infused fresh strength into
+the son of Tydeus for fear some other of the Achaeans might have
+the glory of being first to hit him, and he might himself be only
+second; he therefore sprang forward with his spear and said,
+"Stand, or I shall throw my spear, and in that case I shall soon
+make an end of you."
+</para>
+
+<para>
+He threw as he spoke, but missed his aim on purpose. The dart
+flew over the man's right shoulder, and then stuck in the ground.
+He stood stock still, trembling and in great fear; his teeth
+chattered, and he turned pale with fear. The two came breathless
+up to him and seized his hands, whereon he began to weep and
+said, "Take me alive; I will ransom myself; we have great store
+of gold, bronze, and wrought iron, and from this my father will
+satisfy you with a very large ransom, should he hear of my being
+alive at the ships of the Achaeans."
+</para>
+
+<para>
+"Fear not," replied Ulysses, "let no thought of death be in your
+mind; but tell me, and tell me true, why are you thus going about
+alone in the dead of night away from your camp and towards the
+ships, while other men are sleeping? Is it to plunder the bodies
+of the slain, or did Hector send you to spy out what was going on
+at the ships? Or did you come here of your own mere notion?"
+</para>
+
+<para>
+Dolon answered, his limbs trembling beneath him: "Hector, with
+his vain flattering promises, lured me from my better judgement.
+He said he would give me the horses of the noble son of Peleus
+and his bronze-bedizened chariot; he bade me go through the
+darkness of the flying night, get close to the enemy, and find
+out whether the ships are still guarded as heretofore, or
+whether, now that we have beaten them, the Achaeans design to
+fly, and through sheer exhaustion are neglecting to keep their
+watches."
+</para>
+
+<para>
+Ulysses smiled at him and answered, "You had indeed set your
+heart upon a great reward, but the horses of the descendant of
+Aeacus are hardly to be kept in hand or driven by any other
+mortal man than Achilles himself, whose mother was an immortal.
+But tell me, and tell me true, where did you leave Hector when
+you started? Where lies his armour and his horses? How, too, are
+the watches and sleeping-ground of the Trojans ordered? What are
+their plans? Will they stay here by the ships and away from the
+city, or now that they have worsted the Achaeans, will they
+retire within their walls?"
+</para>
+
+<para>
+And Dolon answered, "I will tell you truly all. Hector and the
+other councillors are now holding conference by the monument of
+great Ilus, away from the general tumult; as for the guards about
+which you ask me, there is no chosen watch to keep guard over the
+host. The Trojans have their watchfires, for they are bound to
+have them; they, therefore, are awake and keep each other to
+their duty as sentinels; but the allies who have come from other
+places are asleep and leave it to the Trojans to keep guard, for
+their wives and children are not here."
+</para>
+
+<para>
+Ulysses then said, "Now tell me; are they sleeping among the
+Trojan troops, or do they lie apart? Explain this that I may
+understand it."
+</para>
+
+<para>
+"I will tell you truly all," replied Dolon. "To the seaward lie
+the Carians, the Paeonian bowmen, the Leleges, the Cauconians,
+and the noble Pelasgi. The Lysians and proud Mysians, with the
+Phrygians and Meonians, have their place on the side towards
+Thymbra; but why ask about an this? If you want to find your way
+into the host of the Trojans, there are the Thracians, who have
+lately come here and lie apart from the others at the far end of
+the camp; and they have Rhesus son of Eioneus for their king. His
+horses are the finest and strongest that I have ever seen, they
+are whiter than snow and fleeter than any wind that blows. His
+chariot is bedight with silver and gold, and he has brought his
+marvellous golden armour, of the rarest workmanship--too splendid
+for any mortal man to carry, and meet only for the gods. Now,
+therefore, take me to the ships or bind me securely here, until
+you come back and have proved my words whether they be false or
+true."
+</para>
+
+<para>
+Diomed looked sternly at him and answered, "Think not, Dolon, for
+all the good information you have given us, that you shall escape
+now you are in our hands, for if we ransom you or let you go, you
+will come some second time to the ships of the Achaeans either as
+a spy or as an open enemy, but if I kill you and an end of you,
+you will give no more trouble."
+</para>
+
+<para>
+On this Dolon would have caught him by the beard to beseech him
+further, but Diomed struck him in the middle of his neck with his
+sword and cut through both sinews so that his head fell rolling
+in the dust while he was yet speaking. They took the ferret-skin
+cap from his head, and also the wolf-skin, the bow, and his long
+spear. Ulysses hung them up aloft in honour of Minerva the
+goddess of plunder, and prayed saying, "Accept these, goddess,
+for we give them to you in preference to all the gods in Olympus:
+therefore speed us still further towards the horses and
+sleeping-ground of the Thracians."
+</para>
+
+<para>
+With these words he took the spoils and set them upon a tamarisk
+tree, and they marked the place by pulling up reeds and gathering
+boughs of tamarisk that they might not miss it as they came back
+through the' flying hours of darkness. The two then went onwards
+amid the fallen armour and the blood, and came presently to the
+company of Thracian soldiers, who were sleeping, tired out with
+their day's toil; their goodly armour was lying on the ground
+beside them all orderly in three rows, and each man had his yoke
+of horses beside him. Rhesus was sleeping in the middle, and hard
+by him his horses were made fast to the topmost rim of his
+chariot. Ulysses from some way off saw him and said, "This,
+Diomed, is the man, and these are the horses about which Dolon
+whom we killed told us. Do your very utmost; dally not about your
+armour, but loose the horses at once--or else kill the men
+yourself, while I see to the horses."
+</para>
+
+<para>
+Thereon Minerva put courage into the heart of Diomed, and he
+smote them right and left. They made a hideous groaning as they
+were being hacked about, and the earth was red with their blood.
+As a lion springs furiously upon a flock of sheep or goats when
+he finds without their shepherd, so did the son of Tydeus set
+upon the Thracian soldiers till he had killed twelve. As he
+killed them Ulysses came and drew them aside by their feet one by
+one, that the horses might go forward freely without being
+frightened as they passed over the dead bodies, for they were not
+yet used to them. When the son of Tydeus came to the king, he
+killed him too (which made thirteen), as he was breathing hard,
+for by the counsel of Minerva an evil dream, the seed of Oeneus,
+hovered that night over his head. Meanwhile Ulysses untied the
+horses, made them fast one to another and drove them off,
+striking them with his bow, for he had forgotten to take the whip
+from the chariot. Then he whistled as a sign to Diomed.
+</para>
+
+<para>
+But Diomed stayed where he was, thinking what other daring deed
+he might accomplish. He was doubting whether to take the chariot
+in which the king's armour was lying, and draw it out by the
+pole, or to lift the armour out and carry it off; or whether
+again, he should not kill some more Thracians. While he was thus
+hesitating Minerva came up to him and said, "Get back, Diomed, to
+the ships or you may be driven thither, should some other god
+rouse the Trojans."
+</para>
+
+<para>
+Diomed knew that it was the goddess, and at once sprang upon the
+horses. Ulysses beat them with his bow and they flew onward to
+the ships of the Achaeans.
+</para>
+
+<para>
+But Apollo kept no blind look-out when he saw Minerva with the
+son of Tydeus. He was angry with her, and coming to the host of
+the Trojans he roused Hippocoon, a counsellor of the Thracians
+and a noble kinsman of Rhesus. He started up out of his sleep and
+saw that the horses were no longer in their place, and that the
+men were gasping in their death-agony; on this he groaned aloud,
+and called upon his friend by name. Then the whole Trojan camp
+was in an uproar as the people kept hurrying together, and they
+marvelled at the deeds of the heroes who had now got away towards
+the ships.
+</para>
+
+<para>
+When they reached the place where they had killed Hector's scout,
+Ulysses stayed his horses, and the son of Tydeus, leaping to the
+ground, placed the blood-stained spoils in the hands of Ulysses
+and remounted: then he lashed the horses onwards, and they flew
+forward nothing loth towards the ships as though of their own
+free will. Nestor was first to hear the tramp of their feet. "My
+friends," said he, "princes and counsellors of the Argives, shall
+I guess right or wrong?--but I must say what I think: there is a
+sound in my ears as of the tramp of horses. I hope it may Diomed
+and Ulysses driving in horses from the Trojans, but I much fear
+that the bravest of the Argives may have come to some harm at
+their hands."
+</para>
+
+<para>
+He had hardly done speaking when the two men came in and
+dismounted, whereon the others shook hands right gladly with them
+and congratulated them. Nestor knight of Gerene was first to
+question them. "Tell me," said he, "renowned Ulysses, how did you
+two come by these horses? Did you steal in among the Trojan
+forces, or did some god meet you and give them to you? They are
+like sunbeams. I am well conversant with the Trojans, for old
+warrior though I am I never hold back by the ships, but I never
+yet saw or heard of such horses as these are. Surely some god
+must have met you and given them to you, for you are both of you
+dear to Jove, and to Jove's daughter Minerva."
+</para>
+
+<para>
+And Ulysses answered, "Nestor son of Neleus, honour to the
+Achaean name, heaven, if it so will, can give us even better
+horses than these, for the gods are far mightier than we are.
+These horses, however, about which you ask me, are freshly come
+from Thrace. Diomed killed their king with the twelve bravest of
+his companions. Hard by the ships we took a thirteenth man--a
+scout whom Hector and the other Trojans had sent as a spy upon
+our ships."
+</para>
+
+<para>
+He laughed as he spoke and drove the horses over the ditch, while
+the other Achaeans followed him gladly. When they reached the
+strongly built quarters of the son of Tydeus, they tied the
+horses with thongs of leather to the manger, where the steeds of
+Diomed stood eating their sweet corn, but Ulysses hung the
+blood-stained spoils of Dolon at the stern of his ship, that they
+might prepare a sacred offering to Minerva. As for themselves,
+they went into the sea and washed the sweat from their bodies,
+and from their necks and thighs. When the sea-water had taken all
+the sweat from off them, and had refreshed them, they went into
+the baths and washed themselves. After they had so done and had
+anointed themselves with oil, they sat down to table, and drawing
+from a full mixing-bowl, made a drink-offering of wine to
+Minerva.
+</para>
+</chapter>
+
+<chapter>
+<title>BOOK XI</title>
+
+<para>
+AND now as Dawn rose from her couch beside Tithonus, harbinger of
+light alike to mortals and immortals, Jove sent fierce Discord
+with the ensign of war in her hands to the ships of the Achaeans.
+She took her stand by the huge black hull of Ulysses' ship which
+was middlemost of all, so that her voice might carry farthest on
+either side, on the one hand towards the tents of Ajax son of
+Telamon, and on the other towards those of Achilles--for these
+two heroes, well-assured of their own strength, had valorously
+drawn up their ships at the two ends of the line. There she took
+her stand, and raised a cry both loud and shrill that filled the
+Achaeans with courage, giving them heart to fight resolutely and
+with all their might, so that they had rather stay there and do
+battle than go home in their ships.
+</para>
+
+<para>
+The son of Atreus shouted aloud and bade the Argives gird
+themselves for battle while he put on his armour. First he girded
+his goodly greaves about his legs, making them fast with ankle-
+clasps of silver; and about his chest he set the breastplate
+which Cinyras had once given him as a guest-gift. It had been
+noised abroad as far as Cyprus that the Achaeans were about to
+sail for Troy, and therefore he gave it to the king. It had ten
+courses of dark cyanus, twelve of gold, and ten of tin. There
+were serpents of cyanus that reared themselves up towards the
+neck, three upon either side, like the rainbows which the son of
+Saturn has set in heaven as a sign to mortal men. About his
+shoulders he threw his sword, studded with bosses of gold; and
+the scabbard was of silver with a chain of gold wherewith to hang
+it. He took moreover the richly-dight shield that covered his
+body when he was in battle--fair to see, with ten circles of
+bronze running all round it. On the body of the shield there were
+twenty bosses of white tin, with another of dark cyanus in the
+middle: this last was made to show a Gorgon's head, fierce and
+grim, with Rout and Panic on either side. The band for the arm to
+go through was of silver, on which there was a writhing snake of
+cyanus with three heads that sprang from a single neck, and went
+in and out among one another. On his head Agamemnon set a helmet,
+with a peak before and behind, and four plumes of horse-hair that
+nodded menacingly above it; then he grasped two redoubtable
+bronze-shod spears, and the gleam of his armour shot from him as
+a flame into the firmament, while Juno and Minerva thundered in
+honour of the king of rich Mycene.
+</para>
+
+<para>
+Every man now left his horses in charge of his charioteer to hold
+them in readiness by the trench, while he went into battle on
+foot clad in full armour, and a mighty uproar rose on high into
+the dawning. The chiefs were armed and at the trench before the
+horses got there, but these came up presently. The son of Saturn
+sent a portent of evil sound about their host, and the dew fell
+red with blood, for he was about to send many a brave man
+hurrying down to Hades.
+</para>
+
+<para>
+The Trojans, on the other side upon the rising slope of the
+plain, were gathered round great Hector, noble Polydamas, Aeneas
+who was honoured by the Trojans like an immortal, and the three
+sons of Antenor, Polybus, Agenor, and young Acamas beauteous as a
+god. Hector's round shield showed in the front rank, and as some
+baneful star that shines for a moment through a rent in the
+clouds and is again hidden beneath them; even so was Hector now
+seen in the front ranks and now again in the hindermost, and his
+bronze armour gleamed like the lightning of aegis-bearing Jove.
+</para>
+
+<para>
+And now as a band of reapers mow swathes of wheat or barley upon
+a rich man's land, and the sheaves fall thick before them, even
+so did the Trojans and Achaeans fall upon one another; they were
+in no mood for yielding but fought like wolves, and neither side
+got the better of the other. Discord was glad as she beheld them,
+for she was the only god that went among them; the others were
+not there, but stayed quietly each in his own home among the
+dells and valleys of Olympus. All of them blamed the son of
+Saturn for wanting to give victory to the Trojans, but father
+Jove heeded them not: he held aloof from all, and sat apart in
+his all-glorious majesty, looking down upon the city of the
+Trojans, the ships of the Achaeans, the gleam of bronze, and
+alike upon the slayers and on the slain.
+</para>
+
+<para>
+Now so long as the day waxed and it was still morning, their
+darts rained thick on one another and the people perished, but as
+the hour drew nigh when a woodman working in some mountain forest
+will get his midday meal--for he has felled till his hands are
+weary; he is tired out, and must now have food--then the Danaans
+with a cry that rang through all their ranks, broke the
+battalions of the enemy. Agamemnon led them on, and slew first
+Bienor, a leader of his people, and afterwards his comrade and
+charioteer Oileus, who sprang from his chariot and was coming
+full towards him; but Agamemnon struck him on the forehead with
+his spear; his bronze visor was of no avail against the weapon,
+which pierced both bronze and bone, so that his brains were
+battered in and he was killed in full fight.
+</para>
+
+<para>
+Agamemnon stripped their shirts from off them and left them with
+their breasts all bare to lie where they had fallen. He then went
+on to kill Isus and Antiphus two sons of Priam, the one a
+bastard, the other born in wedlock; they were in the same
+chariot--the bastard driving, while noble Antiphus fought beside
+him. Achilles had once taken both of them prisoners in the glades
+of Ida, and had bound them with fresh withes as they were
+shepherding, but he had taken a ransom for them; now, however,
+Agamemnon son of Atreus smote Isus in the chest above the nipple
+with his spear, while he struck Antiphus hard by the ear and
+threw him from his chariot. Forthwith he stripped their goodly
+armour from off them and recognized them, for he had already seen
+them at ships when Achilles brought them in from Ida. As a lion
+fastens on the fawns of a hind and crushes them in his great
+jaws, robbing them of their tender life while he on his way back
+to his lair--the hind can do nothing for them even though she be
+close by, for she is in an agony of fear, and flies through the
+thick forest, sweating, and at her utmost speed before the mighty
+monster--so, no man of the Trojans could help Isus and Antiphus,
+for they were themselves flying panic before the Argives.
+</para>
+
+<para>
+Then King Agamemnon took the two sons of Antimachus, Pisander and
+brave Hippolochus. It was Antimachus who had been foremost in
+preventing Helen's being restored to Menelaus, for he was largely
+bribed by Alexandrus; and now Agamemnon took his two sons, both
+in the same chariot, trying to bring their horses to a stand--for
+they had lost hold of the reins and the horses were mad with
+fear. The son of Atreus sprang upon them like a lion, and the
+pair besought him from their chariot. "Take us alive," they
+cried, "son of Atreus, and you shall receive a great ransom for
+us. Our father Antimachus has great store of gold, bronze, and
+wrought iron, and from this he will satisfy you with a very large
+ransom should he hear of our being alive at the ships of the
+Achaeans."
+</para>
+
+<para>
+With such piteous words and tears did they beseech the king, but
+they heard no pitiful answer in return. "If," said Agamemnon,
+"you are sons of Antimachus, who once at a council of Trojans
+proposed that Menelaus and Ulysses, who had come to you as
+envoys, should be killed and not suffered to return, you shall
+now pay for the foul iniquity of your father."
+</para>
+
+<para>
+As he spoke he felled Pisander from his chariot to the earth,
+smiting him on the chest with his spear, so that he lay face
+uppermost upon the ground. Hippolochus fled, but him too did
+Agamemnon smite; he cut off his hands and his head--which he sent
+rolling in among the crowd as though it were a ball. There he let
+them both lie, and wherever the ranks were thickest thither he
+flew, while the other Achaeans followed. Foot soldiers drove the
+foot soldiers of the foe in rout before them, and slew them;
+horsemen did the like by horsemen, and the thundering tramp of
+the horses raised a cloud of dust from off the plain. King
+Agamemnon followed after, ever slaying them and cheering on the
+Achaeans. As when some mighty forest is all ablaze--the eddying
+gusts whirl fire in all directions till the thickets shrivel and
+are consumed before the blast of the flame--even so fell the
+heads of the flying Trojans before Agamemnon son of Atreus, and
+many a noble pair of steeds drew an empty chariot along the
+highways of war, for lack of drivers who were lying on the plain,
+more useful now to vultures than to their wives.
+</para>
+
+<para>
+Jove drew Hector away from the darts and dust, with the carnage
+and din of battle; but the son of Atreus sped onwards, calling
+out lustily to the Danaans. They flew on by the tomb of old Ilus,
+son of Dardanus, in the middle of the plain, and past the place
+of the wild fig-tree making always for the city--the son of
+Atreus still shouting, and with hands all bedrabbled in gore; but
+when they had reached the Scaean gates and the oak tree, there
+they halted and waited for the others to come up. Meanwhile the
+Trojans kept on flying over the middle of the plain like a herd
+of cows maddened with fright when a lion has attacked them in the
+dead of night--he springs on one of them, seizes her neck in the
+grip of his strong teeth and then laps up her blood and gorges
+himself upon her entrails--even so did King Agamemnon son of
+Atreus pursue the foe, ever slaughtering the hindmost as they
+fled pell-mell before him. Many a man was flung headlong from his
+chariot by the hand of the son of Atreus, for he wielded his
+spear with fury.
+</para>
+
+<para>
+But when he was just about to reach the high wall and the city,
+the father of gods and men came down from heaven and took his
+seat, thunderbolt in hand, upon the crest of many-fountained Ida.
+He then told Iris of the golden wings to carry a message for him.
+"Go," said he, "fleet Iris, and speak thus to Hector--say that so
+long as he sees Agamemnon heading his men and making havoc of the
+Trojan ranks, he is to keep aloof and bid the others bear the
+brunt of the battle, but when Agamemnon is wounded either by
+spear or arrow, and takes to his chariot, then will I vouchsafe
+him strength to slay till he reach the ships and night falls at
+the going down of the sun."
+</para>
+
+<para>
+Iris hearkened and obeyed. Down she went to strong Ilius from the
+crests of Ida, and found Hector son of Priam standing by his
+chariot and horses. Then she said, "Hector son of Priam, peer of
+gods in counsel, father Jove has sent me to bear you this
+message--so long as you see Agamemnon heading his men and making
+havoc of the Trojan ranks, you are to keep aloof and bid the
+others bear the brunt of the battle, but when Agamemnon is
+wounded either by spear or arrow, and takes to his chariot, then
+will Jove vouchsafe you strength to slay till you reach the
+ships, and till night falls at the going down of the sun."
+</para>
+
+<para>
+When she had thus spoken Iris left him, and Hector sprang full
+armed from his chariot to the ground, brandishing his spear as he
+went about everywhere among the host, cheering his men on to
+fight, and stirring the dread strife of battle. The Trojans then
+wheeled round, and again met the Achaeans, while the Argives on
+their part strengthened their battalions. The battle was now in
+array and they stood face to face with one another, Agamemnon
+ever pressing forward in his eagerness to be ahead of all others.
+</para>
+
+<para>
+Tell me now ye Muses that dwell in the mansions of Olympus, who,
+whether of the Trojans or of their allies, was first to face
+Agamemnon? It was Iphidamas son of Antenor, a man both brave and
+of great stature, who was brought up in fertile Thrace, the
+mother of sheep. Cisses, his mother's father, brought him up in
+his own house when he was a child--Cisses, father to fair Theano.
+When he reached manhood, Cisses would have kept him there, and
+was for giving him his daughter in marriage, but as soon as he
+had married he set out to fight the Achaeans with twelve ships
+that followed him: these he had left at Percote and had come on
+by land to Ilius. He it was that now met Agamemnon son of Atreus.
+When they were close up with one another, the son of Atreus
+missed his aim, and Iphidamas hit him on the girdle below the
+cuirass and then flung himself upon him, trusting to his strength
+of arm; the girdle, however, was not pierced, nor nearly so, for
+the point of the spear struck against the silver and was turned
+aside as though it had been lead: King Agamemnon caught it from
+his hand, and drew it towards him with the fury of a lion; he
+then drew his sword, and killed Iphidamas by striking him on the
+neck. So there the poor fellow lay, sleeping a sleep as it were
+of bronze, killed in the defence of his fellow-citizens, far from
+his wedded wife, of whom he had had no joy though he had given
+much for her: he had given a hundred-head of cattle down, and had
+promised later on to give a thousand sheep and goats mixed, from
+the countless flocks of which he was possessed. Agamemnon son of
+Atreus then despoiled him, and carried off his armour into the
+host of the Achaeans.
+</para>
+
+<para>
+When noble Coon, Antenor's eldest son, saw this, sore indeed were
+his eyes at the sight of his fallen brother. Unseen by Agamemnon
+he got beside him, spear in hand, and wounded him in the middle
+of his arm below the elbow, the point of the spear going right
+through the arm. Agamemnon was convulsed with pain, but still not
+even for this did he leave off struggling and fighting, but
+grasped his spear that flew as fleet as the wind, and sprang upon
+Coon who was trying to drag off the body of his brother--his
+father's son--by the foot, and was crying for help to all the
+bravest of his comrades; but Agamemnon struck him with a
+bronze-shod spear and killed him as he was dragging the dead body
+through the press of men under cover of his shield: he then cut
+off his head, standing over the body of Iphidamas. Thus did the
+sons of Antenor meet their fate at the hands of the son of
+Atreus, and go down into the house of Hades.
+</para>
+
+<para>
+As long as the blood still welled warm from his wound Agamemnon
+went about attacking the ranks of the enemy with spear and sword
+and with great handfuls of stone, but when the blood had ceased
+to flow and the wound grew dry, the pain became great. As the
+sharp pangs which the Eilithuiae, goddesses of childbirth,
+daughters of Juno and dispensers of cruel pain, send upon a woman
+when she is in labour--even so sharp were the pangs of the son of
+Atreus. He sprang on to his chariot, and bade his charioteer
+drive to the ships, for he was in great agony. With a loud clear
+voice he shouted to the Danaans, "My friends, princes and
+counsellors of the Argives, defend the ships yourselves, for Jove
+has not suffered me to fight the whole day through against the
+Trojans."
+</para>
+
+<para>
+With this the charioteer turned his horses towards the ships, and
+they flew forward nothing loth. Their chests were white with foam
+and their bellies with dust, as they drew the wounded king out of
+the battle.
+</para>
+
+<para>
+When Hector saw Agamemnon quit the field, he shouted to the
+Trojans and Lycians saying, "Trojans, Lycians, and Dardanian
+warriors, be men, my friends, and acquit yourselves in battle
+bravely; their best man has left them, and Jove has vouchsafed me
+a great triumph; charge the foe with your chariots that you may
+win still greater glory."
+</para>
+
+<para>
+With these words he put heart and soul into them all, and as a
+huntsman hounds his dogs on against a lion or wild boar, even so
+did Hector, peer of Mars, hound the proud Trojans on against the
+Achaeans. Full of hope he plunged in among the foremost, and fell
+on the fight like some fierce tempest that swoops down upon the
+sea, and lashes its deep blue waters into fury.
+</para>
+
+<para>
+What, then is the full tale of those whom Hector son of Priam
+killed in the hour of triumph which Jove then vouchsafed him?
+First Asaeus, Autonous, and Opites; Dolops son of Clytius,
+Opheltius and Agelaus; Aesymnus, Orus and Hipponous steadfast in
+battle; these chieftains of the Achaeans did Hector slay, and
+then he fell upon the rank and file. As when the west wind
+hustles the clouds of the white south and beats them down with
+the fierceness of its fury--the waves of the sea roll high, and
+the spray is flung aloft in the rage of the wandering wind--even
+so thick were the heads of them that fell by the hand of Hector.
+</para>
+
+<para>
+All had then been lost and no help for it, and the Achaeans would
+have fled pell-mell to their ships, had not Ulysses cried out to
+Diomed, "Son of Tydeus, what has happened to us that we thus
+forget our prowess? Come, my good fellow, stand by my side and
+help me, we shall be shamed for ever if Hector takes the ships."
+</para>
+
+<para>
+And Diomed answered, "Come what may, I will stand firm; but we
+shall have scant joy of it, for Jove is minded to give victory to
+the Trojans rather than to us."
+</para>
+
+<para>
+With these words he struck Thymbraeus from his chariot to the
+ground, smiting him in the left breast with his spear, while
+Ulysses killed Molion who was his squire. These they let lie, now
+that they had stopped their fighting; the two heroes then went on
+playing havoc with the foe, like two wild boars that turn in fury
+and rend the hounds that hunt them. Thus did they turn upon the
+Trojans and slay them, and the Achaeans were thankful to have
+breathing time in their flight from Hector.
+</para>
+
+<para>
+They then took two princes with their chariot, the two sons of
+Merops of Percote, who excelled all others in the arts of
+divination. He had forbidden his sons to go to the war, but they
+would not obey him, for fate lured them to their fall. Diomed son
+of Tydeus slew them both and stripped them of their armour, while
+Ulysses killed Hippodamus and Hypeirochus.
+</para>
+
+<para>
+And now the son of Saturn as he looked down from Ida ordained
+that neither side should have the advantage, and they kept on
+killing one another. The son of Tydeus speared Agastrophus son of
+Paeon in the hip-joint with his spear. His chariot was not at
+hand for him to fly with, so blindly confident had he been. His
+squire was in charge of it at some distance and he was fighting
+on foot among the foremost until he lost his life. Hector soon
+marked the havoc Diomed and Ulysses were making, and bore down
+upon them with a loud cry, followed by the Trojan ranks; brave
+Diomed was dismayed when he saw them, and said to Ulysses who was
+beside him, "Great Hector is bearing down upon us and we shall be
+undone; let us stand firm and wait his onset."
+</para>
+
+<para>
+He poised his spear as he spoke and hurled it, nor did he miss
+his mark. He had aimed at Hector's head near the top of his
+helmet, but bronze was turned by bronze, and Hector was
+untouched, for the spear was stayed by the visored helm made with
+three plates of metal, which Phoebus Apollo had given him. Hector
+sprang back with a great bound under cover of the ranks; he fell
+on his knees and propped himself with his brawny hand leaning on
+the ground, for darkness had fallen on his eyes. The son of
+Tydeus having thrown his spear dashed in among the foremost
+fighters, to the place where he had seen it strike the ground;
+meanwhile Hector recovered himself and springing back into his
+chariot mingled with the crowd, by which means he saved his life.
+But Diomed made at him with his spear and said, "Dog, you have
+again got away though death was close on your heels. Phoebus
+Apollo, to whom I ween you pray ere you go into battle, has again
+saved you, nevertheless I will meet you and make an end of you
+hereafter, if there is any god who will stand by me too and be my
+helper. For the present I must pursue those I can lay hands on."
+</para>
+
+<para>
+As he spoke he began stripping the spoils from the son of Paeon,
+but Alexandrus husband of lovely Helen aimed an arrow at him,
+leaning against a pillar of the monument which men had raised to
+Ilus son of Dardanus, a ruler in days of old. Diomed had taken
+the cuirass from off the breast of Agastrophus, his heavy helmet
+also, and the shield from off his shoulders, when Paris drew his
+bow and let fly an arrow that sped not from his hand in vain, but
+pierced the flat of Diomed's right foot, going right through it
+and fixing itself in the ground. Thereon Paris with a hearty
+laugh sprang forward from his hiding-place, and taunted him
+saying, "You are wounded--my arrow has not been shot in vain;
+would that it had hit you in the belly and killed you, for thus
+the Trojans, who fear you as goats fear a lion, would have had a
+truce from evil."
+</para>
+
+<para>
+Diomed all undaunted answered, "Archer, you who without your bow
+are nothing, slanderer and seducer, if you were to be tried in
+single combat fighting in full armour, your bow and your arrows
+would serve you in little stead. Vain is your boast in that you
+have scratched the sole of my foot. I care no more than if a girl
+or some silly boy had hit me. A worthless coward can inflict but
+a light wound; when I wound a man though I but graze his skin it
+is another matter, for my weapon will lay him low. His wife will
+tear her cheeks for grief and his children will be fatherless:
+there will he rot, reddening the earth with his blood, and
+vultures, not women, will gather round him."
+</para>
+
+<para>
+Thus he spoke, but Ulysses came up and stood over him. Under this
+cover he sat down to draw the arrow from his foot, and sharp was
+the pain he suffered as he did so. Then he sprang on to his
+chariot and bade the charioteer drive him to the ships, for he
+was sick at heart.
+</para>
+
+<para>
+Ulysses was now alone; not one of the Argives stood by him, for
+they were all panic-stricken. "Alas," said he to himself in his
+dismay, "what will become of me? It is ill if I turn and fly
+before these odds, but it will be worse if I am left alone and
+taken prisoner, for the son of Saturn has struck the rest of the
+Danaans with panic. But why talk to myself in this way? Well do I
+know that though cowards quit the field, a hero, whether he wound
+or be wounded, must stand firm and hold his own."
+</para>
+
+<para>
+While he was thus in two minds, the ranks of the Trojans advanced
+and hemmed him in, and bitterly did they come to rue it. As
+hounds and lusty youths set upon a wild boar that sallies from
+his lair whetting his white tusks--they attack him from every
+side and can hear the gnashing of his jaws, but for all his
+fierceness they still hold their ground--even so furiously did
+the Trojans attack Ulysses. First he sprang spear in hand upon
+Deiopites and wounded him on the shoulder with a downward blow;
+then he killed Thoon and Ennomus. After these he struck
+Chersidamas in the loins under his shield as he had just sprung
+down from his chariot; so he fell in the dust and clutched the
+earth in the hollow of his hand. These he let lie, and went on to
+wound Charops son of Hippasus own brother to noble Socus. Socus,
+hero that he was, made all speed to help him, and when he was
+close to Ulysses he said, "Far-famed Ulysses, insatiable of craft
+and toil, this day you shall either boast of having killed both
+the sons of Hippasus and stripped them of their armour, or you
+shall fall before my spear."
+</para>
+
+<para>
+With these words he struck the shield of Ulysses. The spear went
+through the shield and passed on through his richly wrought
+cuirass, tearing the flesh from his side, but Pallas Minerva did
+not suffer it to pierce the entrails of the hero. Ulysses knew
+that his hour was not yet come, but he gave ground and said to
+Socus, "Wretch, you shall now surely die. You have stayed me from
+fighting further with the Trojans, but you shall now fall by my
+spear, yielding glory to myself, and your soul to Hades of the
+noble steeds."
+</para>
+
+<para>
+Socus had turned in flight, but as he did so, the spear struck
+him in the back midway between the shoulders, and went right
+through his chest. He fell heavily to the ground and Ulysses
+vaunted over him saying, "O Socus, son of Hippasus tamer of
+horses, death has been too quick for you and you have not escaped
+him: poor wretch, not even in death shall your father and mother
+close your eyes, but the ravening vultures shall enshroud you
+with the flapping of their dark wings and devour you. Whereas
+even though I fall the Achaeans will give me my due rites of
+burial."
+</para>
+
+<para>
+So saying he drew Socus's heavy spear out of his flesh and from
+his shield, and the blood welled forth when the spear was
+withdrawn so that he was much dismayed. When the Trojans saw that
+Ulysses was bleeding they raised a great shout and came on in a
+body towards him; he therefore gave ground, and called his
+comrades to come and help him. Thrice did he cry as loudly as man
+can cry, and thrice did brave Menelaus hear him; he turned,
+therefore, to Ajax who was close beside him and said, "Ajax,
+noble son of Telamon, captain of your people, the cry of Ulysses
+rings in my ears, as though the Trojans had cut him off and were
+worsting him while he is single-handed. Let us make our way
+through the throng; it will be well that we defend him; I fear he
+may come to harm for all his valour if he be left without
+support, and the Danaans would miss him sorely."
+</para>
+
+<para>
+He led the way and mighty Ajax went with him. The Trojans had
+gathered round Ulysses like ravenous mountain jackals round the
+carcase of some horned stag that has been hit with an arrow--the
+stag has fled at full speed so long as his blood was warm and his
+strength has lasted, but when the arrow has overcome him, the
+savage jackals devour him in the shady glades of the forest. Then
+heaven sends a fierce lion thither, whereon the jackals fly in
+terror and the lion robs them of their prey--even so did Trojans
+many and brave gather round crafty Ulysses, but the hero stood at
+bay and kept them off with his spear. Ajax then came up with his
+shield before him like a wall, and stood hard by, whereon the
+Trojans fled in all directions. Menelaus took Ulysses by the
+hand, and led him out of the press while his squire brought up
+his chariot, but Ajax rushed furiously on the Trojans and killed
+Doryclus, a bastard son of Priam; then he wounded Pandocus,
+Lysandrus, Pyrasus, and Pylartes; as some swollen torrent comes
+rushing in full flood from the mountains on to the plain, big
+with the rain of heaven--many a dry oak and many a pine does it
+engulf, and much mud does it bring down and cast into the sea--
+even so did brave Ajax chase the foe furiously over the plain,
+slaying both men and horses.
+</para>
+
+<para>
+Hector did not yet know what Ajax was doing, for he was fighting
+on the extreme left of the battle by the banks of the river
+Scamander, where the carnage was thickest and the war-cry loudest
+round Nestor and brave Idomeneus. Among these Hector was making
+great slaughter with his spear and furious driving, and was
+destroying the ranks that were opposed to him; still the Achaeans
+would have given no ground, had not Alexandrus husband of lovely
+Helen stayed the prowess of Machaon, shepherd of his people, by
+wounding him in the right shoulder with a triple-barbed arrow.
+The Achaeans were in great fear that as the fight had turned
+against them the Trojans might take him prisoner, and Idomeneus
+said to Nestor, "Nestor son of Neleus, honour to the Achaean
+name, mount your chariot at once; take Machaon with you and drive
+your horses to the ships as fast as you can. A physician is worth
+more than several other men put together, for he can cut out
+arrows and spread healing herbs."
+</para>
+
+<para>
+Nestor knight of Gerene did as Idomeneus had counselled; he at
+once mounted his chariot, and Machaon son of the famed physician
+Aesculapius, went with him. He lashed his horses and they flew
+onward nothing loth towards the ships, as though of their own
+free will.
+</para>
+
+<para>
+Then Cebriones seeing the Trojans in confusion said to Hector
+from his place beside him, "Hector, here are we two fighting on
+the extreme wing of the battle, while the other Trojans are in
+pell-mell rout, they and their horses. Ajax son of Telamon is
+driving them before him; I know him by the breadth of his shield:
+let us turn our chariot and horses thither, where horse and foot
+are fighting most desperately, and where the cry of battle is
+loudest."
+</para>
+
+<para>
+With this he lashed his goodly steeds, and when they felt the
+whip they drew the chariot full speed among the Achaeans and
+Trojans, over the bodies and shields of those that had fallen:
+the axle was bespattered with blood, and the rail round the car
+was covered with splashes both from the horses' hoofs and from
+the tyres of the wheels. Hector tore his way through and flung
+himself into the thick of the fight, and his presence threw the
+Danaans into confusion, for his spear was not long idle;
+nevertheless though he went among the ranks with sword and spear,
+and throwing great stones, he avoided Ajax son of Telamon, for
+Jove would have been angry with him if he had fought a better man
+than himself.
+</para>
+
+<para>
+Then father Jove from his high throne struck fear into the heart
+of Ajax, so that he stood there dazed and threw his shield behind
+him--looking fearfully at the throng of his foes as though he
+were some wild beast, and turning hither and thither but
+crouching slowly backwards. As peasants with their hounds chase a
+lion from their stockyard, and watch by night to prevent his
+carrying off the pick of their herd--he makes his greedy spring,
+but in vain, for the darts from many a strong hand fall thick
+around him, with burning brands that scare him for all his fury,
+and when morning comes he slinks foiled and angry away--even so
+did Ajax, sorely against his will, retreat angrily before the
+Trojans, fearing for the ships of the Achaeans. Or as some lazy
+ass that has had many a cudgel broken about his back, when he
+into a field begins eating the corn--boys beat him but he is too
+many for them, and though they lay about with their sticks they
+cannot hurt him; still when he has had his fill they at last
+drive him from the field--even so did the Trojans and their
+allies pursue great Ajax, ever smiting the middle of his shield
+with their darts. Now and again he would turn and show fight,
+keeping back the battalions of the Trojans, and then he would
+again retreat; but he prevented any of them from making his way
+to the ships. Single-handed he stood midway between the Trojans
+and Achaeans: the spears that sped from their hands stuck some of
+them in his mighty shield, while many, though thirsting for his
+blood, fell to the ground ere they could reach him to the
+wounding of his fair flesh.
+</para>
+
+<para>
+Now when Eurypylus the brave son of Euaemon saw that Ajax was
+being overpowered by the rain of arrows, he went up to him and
+hurled his spear. He struck Apisaon son of Phausius in the liver
+below the midriff, and laid him low. Eurypylus sprang upon him,
+and stripped the armour from his shoulders; but when Alexandrus
+saw him, he aimed an arrow at him which struck him in the right
+thigh; the arrow broke, but the point that was left in the wound
+dragged on the thigh; he drew back, therefore, under cover of his
+comrades to save his life, shouting as he did so to the Danaans,
+"My friends, princes and counsellors of the Argives, rally to the
+defence of Ajax who is being overpowered, and I doubt whether he
+will come out of the fight alive. Hither, then, to the rescue of
+great Ajax son of Telamon."
+</para>
+
+<para>
+Even so did he cry when he was wounded; thereon the others came
+near, and gathered round him, holding their shields upwards from
+their shoulders so as to give him cover. Ajax then made towards
+them, and turned round to stand at bay as soon as he had reached
+his men.
+</para>
+
+<para>
+Thus then did they fight as it were a flaming fire. Meanwhile the
+mares of Neleus, all in a lather with sweat, were bearing Nestor
+out of the fight, and with him Machaon shepherd of his people.
+Achilles saw and took note, for he was standing on the stern of
+his ship watching the hard stress and struggle of the fight. He
+called from the ship to his comrade Patroclus, who heard him in
+the tent and came out looking like Mars himself--here indeed was
+the beginning of the ill that presently befell him. "Why," said
+he, "Achilles, do you call me? What do you want with me?" And
+Achilles answered, "Noble son of Menoetius, man after my own
+heart, I take it that I shall now have the Achaeans praying at my
+knees, for they are in great straits; go, Patroclus, and ask
+Nestor who it is that he is bearing away wounded from the field;
+from his back I should say it was Machaon son of Aesculapius, but
+I could not see his face for the horses went by me at full
+speed."
+</para>
+
+<para>
+Patroclus did as his dear comrade had bidden him, and set off
+running by the ships and tents of the Achaeans.
+</para>
+
+<para>
+When Nestor and Machaon had reached the tents of the son of
+Neleus, they dismounted, and an esquire, Eurymedon, took the
+horses from the chariot. The pair then stood in the breeze by the
+seaside to dry the sweat from their shirts, and when they had so
+done they came inside and took their seats. Fair Hecamede, whom
+Nestor had had awarded to him from Tenedos when Achilles took it,
+mixed them a mess; she was daughter of wise Arsinous, and the
+Achaeans had given her to Nestor because he excelled all of them
+in counsel. First she set for them a fair and well-made table
+that had feet of cyanus; on it there was a vessel of bronze and
+an onion to give relish to the drink, with honey and cakes of
+barley-meal. There was also a cup of rare workmanship which the
+old man had brought with him from home, studded with bosses of
+gold; it had four handles, on each of which there were two golden
+doves feeding, and it had two feet to stand on. Any one else
+would hardly have been able to lift it from the table when it was
+full, but Nestor could do so quite easily. In this the woman, as
+fair as a goddess, mixed them a mess with Pramnian wine; she
+grated goat's milk cheese into it with a bronze grater, threw in
+a handful of white barley-meal, and having thus prepared the mess
+she bade them drink it. When they had done so and had thus
+quenched their thirst, they fell talking with one another, and at
+this moment Patroclus appeared at the door.
+</para>
+
+<para>
+When the old man saw him he sprang from his seat, seized his
+hand, led him into the tent, and bade him take his place among
+them; but Patroclus stood where he was and said, "Noble sir, I
+may not stay, you cannot persuade me to come in; he that sent me
+is not one to be trifled with, and he bade me ask who the wounded
+man was whom you were bearing away from the field. I can now see
+for myself that he is Machaon, shepherd of his people. I must go
+back and tell Achilles. You, sir, know what a terrible man he is,
+and how ready to blame even where no blame should lie."
+</para>
+
+<para>
+And Nestor answered, "Why should Achilles care to know how many
+of the Achaeans may be wounded? He recks not of the dismay that
+reigns in our host; our most valiant chieftains lie disabled,
+brave Diomed, son of Tydeus, is wounded; so are Ulysses and
+Agamemnon; Eurypylus has been hit with an arrow in the thigh, and
+I have just been bringing this man from the field--he too wounded
+with an arrow. Nevertheless, Achilles, so valiant though he be,
+cares not and knows no ruth. Will he wait till the ships, do what
+we may, are in a blaze, and we perish one upon the other? As for
+me, I have no strength nor stay in me any longer; would that I
+were still young and strong as in the days when there was a fight
+between us and the men of Elis about some cattle-raiding. I then
+killed Itymoneus, the valiant son of Hypeirochus, a dweller in
+Elis, as I was driving in the spoil; he was hit by a dart thrown
+by my hand while fighting in the front rank in defence of his
+cows, so he fell and the country people around him were in great
+fear. We drove off a vast quantity of booty from the plain, fifty
+herds of cattle and as many flocks of sheep; fifty droves also of
+pigs, and as many wide-spreading flocks of goats. Of horses,
+moreover, we seized a hundred and fifty, all of them mares, and
+many had foals running with them. All these did we drive by night
+to Pylus, the city of Neleus, taking them within the city; and
+the heart of Neleus was glad in that I had taken so much, though
+it was the first time I had ever been in the field. At daybreak
+the heralds went round crying that all in Elis to whom there was
+a debt owing should come; and the leading Pylians assembled to
+divide the spoils. There were many to whom the Epeans owed
+chattels, for we men of Pylus were few and had been oppressed
+with wrong; in former years Hercules had come, and had laid his
+hand heavy upon us, so that all our best men had perished. Neleus
+had had twelve sons, but I alone was left; the others had all
+been killed. The Epeans presuming upon all this had looked down
+upon us and had done us much evil. My father chose a herd of
+cattle and a great flock of sheep--three hundred in all--and he
+took their shepherds with him, for there was a great debt due to
+him in Elis, to wit four horses, winners of prizes. They and
+their chariots with them had gone to the games and were to run
+for a tripod, but King Augeas took them, and sent back their
+driver grieving for the loss of his horses. Neleus was angered by
+what he had both said and done, and took great value in return,
+but he divided the rest, that no man might have less than his
+full share.
+</para>
+
+<para>
+"Thus did we order all things, and offer sacrifices to the gods
+throughout the city; but three days afterwards the Epeans came in
+a body, many in number, they and their chariots, in full array,
+and with them the two Moliones in their armour, though they were
+still lads and unused to fighting. Now there is a certain town,
+Thryoessa, perched upon a rock on the river Alpheus, the border
+city Pylus. This they would destroy, and pitched their camp about
+it, but when they had crossed their whole plain, Minerva darted
+down by night from Olympus and bade us set ourselves in array;
+and she found willing soldiers in Pylos, for the men meant
+fighting. Neleus would not let me arm, and hid my horses, for he
+said that as yet I could know nothing about war; nevertheless
+Minerva so ordered the fight that, all on foot as I was, I fought
+among our mounted forces and vied with the foremost of them.
+There is a river Minyeius that falls into the sea near Arene, and
+there they that were mounted (and I with them) waited till
+morning, when the companies of foot soldiers came up with us in
+force. Thence in full panoply and equipment we came towards noon
+to the sacred waters of the Alpheus, and there we offered victims
+to almighty Jove, with a bull to Alpheus, another to Neptune, and
+a herd-heifer to Minerva. After this we took supper in our
+companies, and laid us down to rest each in his armour by the
+river.
+</para>
+
+<para>
+"The Epeans were beleaguering the city and were determined to
+take it, but ere this might be there was a desperate fight in
+store for them. When the sun's rays began to fall upon the earth
+we joined battle, praying to Jove and to Minerva, and when the
+fight had begun, I was the first to kill my man and take his
+horses--to wit the warrior Mulius. He was son-in-law to Augeas,
+having married his eldest daughter, golden-haired Agamede, who
+knew the virtues of every herb which grows upon the face of the
+earth. I speared him as he was coming towards me, and when he
+fell headlong in the dust, I sprang upon his chariot and took my
+place in the front ranks. The Epeans fled in all directions when
+they saw the captain of their horsemen (the best man they had)
+laid low, and I swept down on them like a whirlwind, taking fifty
+chariots--and in each of them two men bit the dust, slain by my
+spear. I should have even killed the two Moliones, sons of Actor,
+unless their real father, Neptune lord of the earthquake, had
+hidden them in a thick mist and borne them out of the fight.
+Thereon Jove vouchsafed the Pylians a great victory, for we
+chased them far over the plain, killing the men and bringing in
+their armour, till we had brought our horses to Buprasium, rich
+in wheat, and to the Olenian rock, with the hill that is called
+Alision, at which point Minerva turned the people back. There I
+slew the last man and left him; then the Achaeans drove their
+horses back from Buprasium to Pylos and gave thanks to Jove among
+the gods, and among mortal men to Nestor.
+</para>
+
+<para>
+"Such was I among my peers, as surely as ever was, but Achilles
+is for keeping all his valour for himself; bitterly will he rue
+it hereafter when the host is being cut to pieces. My good
+friend, did not Menoetius charge you thus, on the day when he
+sent you from Phthia to Agamemnon? Ulysses and I were in the
+house, inside, and heard all that he said to you; for we came to
+the fair house of Peleus while beating up recruits throughout all
+Achaea, and when we got there we found Menoetius and yourself,
+and Achilles with you. The old knight Peleus was in the outer
+court, roasting the fat thigh-bones of a heifer to Jove the lord
+of thunder; and he held a gold chalice in his hand from which he
+poured drink-offerings of wine over the burning sacrifice. You
+two were busy cutting up the heifer, and at that moment we stood
+at the gates, whereon Achilles sprang to his feet, led us by the
+hand into the house, placed us at table, and set before us such
+hospitable entertainment as guests expect. When we had satisfied
+ourselves with meat and drink, I said my say and urged both of
+you to join us. You were ready enough to do so, and the two old
+men charged you much and straitly. Old Peleus bade his son
+Achilles fight ever among the foremost and outvie his peers,
+while Menoetius the son of Actor spoke thus to you: 'My son,'
+said he, 'Achilles is of nobler birth than you are, but you are
+older than he, though he is far the better man of the two.
+Counsel him wisely, guide him in the right way, and he will
+follow you to his own profit.' Thus did your father charge you,
+but you have forgotten; nevertheless, even now, say all this to
+Achilles if he will listen to you. Who knows but with heaven's
+help you may talk him over, for it is good to take a friend's
+advice. If, however, he is fearful about some oracle, or if his
+mother has told him something from Jove, then let him send you,
+and let the rest of the Myrmidons follow with you, if perchance
+you may bring light and saving to the Danaans. And let him send
+you into battle clad in his own armour, that the Trojans may
+mistake you for him and leave off fighting; the sons of the
+Achaeans may thus have time to get their breath, for they are
+hard pressed and there is little breathing time in battle. You,
+who are fresh, might easily drive a tired enemy back to his walls
+and away from the tents and ships."
+</para>
+
+<para>
+With these words he moved the heart of Patroclus, who set off
+running by the line of the ships to Achilles, descendant of
+Aeacus. When he had got as far as the ships of Ulysses, where was
+their place of assembly and court of justice, with their altars
+dedicated to the gods, Eurypylus son of Euaemon, met him, wounded
+in the thigh with an arrow, and limping out of the fight. Sweat
+rained from his head and shoulders, and black blood welled from
+his cruel wound, but his mind did not wander. The son of
+Menoetius when he saw him had compassion upon him and spoke
+piteously saying, "O unhappy princes and counsellors of the
+Danaans, are you then doomed to feed the hounds of Troy with your
+fat, far from your friends and your native land? Say, noble
+Eurypylus, will the Achaeans be able to hold great Hector in
+check, or will they fall now before his spear?"
+</para>
+
+<para>
+Wounded Eurypylus made answer, "Noble Patroclus, there is no hope
+left for the Achaeans but they will perish at their ships. All
+they that were princes among us are lying struck down and wounded
+at the hands of the Trojans, who are waxing stronger and
+stronger. But save me and take me to your ship; cut out the arrow
+from my thigh; wash the black blood from off it with warm water,
+and lay upon it those gracious herbs which, so they say, have
+been shown you by Achilles, who was himself shown them by Chiron,
+most righteous of all the centaurs. For of the physicians
+Podalirius and Machaon, I hear that the one is lying wounded in
+his tent and is himself in need of healing, while the other is
+fighting the Trojans upon the plain."
+</para>
+
+<para>
+"Hero Eurypylus," replied the brave son of Menoetius, "how may
+these things be? What can I do? I am on my way to bear a message
+to noble Achilles from Nestor of Gerene, bulwark of the Achaeans,
+but even so I will not be unmindful of your distress."
+</para>
+
+<para>
+With this he clasped him round the middle and led him into the
+tent, and a servant, when he saw him, spread bullock-skins on the
+ground for him to lie on. He laid him at full length and cut out
+the sharp arrow from his thigh; he washed the black blood from
+the wound with warm water; he then crushed a bitter herb, rubbing
+it between his hands, and spread it upon the wound; this was a
+virtuous herb which killed all pain; so the wound presently dried
+and the blood left off flowing.
+</para>
+</chapter>
+
+<chapter>
+<title>BOOK XII</title>
+
+<para>
+SO THE son of Menoetius was attending to the hurt of Eurypylus
+within the tent, but the Argives and Trojans still fought
+desperately, nor were the trench and the high wall above it, to
+keep the Trojans in check longer. They had built it to protect
+their ships, and had dug the trench all round it that it might
+safeguard both the ships and the rich spoils which they had
+taken, but they had not offered hecatombs to the gods. It had
+been built without the consent of the immortals, and therefore it
+did not last. So long as Hector lived and Achilles nursed his
+anger, and so long as the city of Priam remained untaken, the
+great wall of the Achaeans stood firm; but when the bravest of
+the Trojans were no more, and many also of the Argives, though
+some were yet left alive--when, moreover, the city was sacked in
+the tenth year, and the Argives had gone back with their ships to
+their own country--then Neptune and Apollo took counsel to
+destroy the wall, and they turned on to it the streams of all the
+rivers from Mount Ida into the sea, Rhesus, Heptaporus, Caresus,
+Rhodius, Grenicus, Aesopus, and goodly Scamander, with Simois,
+where many a shield and helm had fallen, and many a hero of the
+race of demigods had bitten the dust. Phoebus Apollo turned the
+mouths of all these rivers together and made them flow for nine
+days against the wall, while Jove rained the whole time that he
+might wash it sooner into the sea. Neptune himself, trident in
+hand, surveyed the work and threw into the sea all the
+foundations of beams and stones which the Achaeans had laid with
+so much toil; he made all level by the mighty stream of the
+Hellespont, and then when he had swept the wall away he spread a
+great beach of sand over the place where it had been. This done
+he turned the rivers back into their old courses.
+</para>
+
+<para>
+This was what Neptune and Apollo were to do in after time; but as
+yet battle and turmoil were still raging round the wall till its
+timbers rang under the blows that rained upon them. The Argives,
+cowed by the scourge of Jove, were hemmed in at their ships in
+fear of Hector the mighty minister of Rout, who as heretofore
+fought with the force and fury of a whirlwind. As a lion or wild
+boar turns fiercely on the dogs and men that attack him, while
+these form solid wall and shower their javelins as they face
+him--his courage is all undaunted, but his high spirit will be
+the death of him; many a time does he charge at his pursuers to
+scatter them, and they fall back as often as he does so--even so
+did Hector go about among the host exhorting his men, and
+cheering them on to cross the trench.
+</para>
+
+<para>
+But the horses dared not do so, and stood neighing upon its
+brink, for the width frightened them. They could neither jump it
+nor cross it, for it had overhanging banks all round upon either
+side, above which there were the sharp stakes that the sons of
+the Achaeans had planted so close and strong as a defence against
+all who would assail it; a horse, therefore, could not get into
+it and draw his chariot after him, but those who were on foot
+kept trying their very utmost. Then Polydamas went up to Hector
+and said, "Hector, and you other captains of the Trojans and
+allies, it is madness for us to try and drive our horses across
+the trench; it will be very hard to cross, for it is full of
+sharp stakes, and beyond these there is the wall. Our horses
+therefore cannot get down into it, and would be of no use if they
+did; moreover it is a narrow place and we should come to harm.
+If, indeed, great Jove is minded to help the Trojans, and in his
+anger will utterly destroy the Achaeans, I would myself gladly
+see them perish now and here far from Argos; but if they should
+rally and we are driven back from the ships pell-mell into the
+trench there will be not so much as a man get back to the city to
+tell the tale. Now, therefore, let us all do as I say; let our
+squires hold our horses by the trench, but let us follow Hector
+in a body on foot, clad in full armour, and if the day of their
+doom is at hand the Achaeans will not be able to withstand us."
+</para>
+
+<para>
+Thus spoke Polydamas and his saying pleased Hector, who sprang in
+full armour to the ground, and all the other Trojans, when they
+saw him do so, also left their chariots. Each man then gave his
+horses over to his charioteer in charge to hold them ready for
+him at the trench. Then they formed themselves into companies,
+made themselves ready, and in five bodies followed their leaders.
+Those that went with Hector and Polydamas were the bravest and
+most in number, and the most determined to break through the wall
+and fight at the ships. Cebriones was also joined with them as
+third in command, for Hector had left his chariot in charge of a
+less valiant soldier. The next company was led by Paris,
+Alcathous, and Agenor; the third by Helenus and Deiphobus, two
+sons of Priam, and with them was the hero Asius--Asius, the son
+of Hyrtacus, whose great black horses of the breed that comes
+from the river Selleis had brought him from Arisbe. Aeneas, the
+valiant son of Anchises, led the fourth; he and the two sons of
+Antenor, Archelochus and Acamas, men well versed in all the arts
+of war. Sarpedon was captain over the allies, and took with him
+Glaucus and Asteropaeus whom he deemed most valiant after
+himself--for he was far the best man of them all. These helped to
+array one another in their ox-hide shields, and then charged
+straight at the Danaans, for they felt sure that they would not
+hold out longer and that they should themselves now fall upon the
+ships.
+</para>
+
+<para>
+The rest of the Trojans and their allies now followed the counsel
+of Polydamas but Asius, son of Hyrtacus, would not leave his
+horses and his esquire behind him; in his foolhardiness he took
+them on with him towards the ships, nor did he fail to come by
+his end in consequence. Nevermore was he to return to wind-beaten
+Ilius, exulting in his chariot and his horses; ere he could do
+so, death of ill-omened name had overshadowed him and he had
+fallen by the spear of Idomeneus the noble son of Deucalion. He
+had driven towards the left wing of the ships, by which way the
+Achaeans used to return with their chariots and horses from the
+plain. Hither he drove and found the gates with their doors
+opened wide, and the great bar down--for the gatemen kept them
+open so as to let those of their comrades enter who might be
+flying towards the ships. Hither of set purpose did he direct his
+horses, and his men followed him with a loud cry, for they felt
+sure that the Achaeans would not hold out longer, and that they
+should now fall upon the ships. Little did they know that at the
+gates they should find two of the bravest chieftains, proud sons
+of the fighting Lapithae--the one, Polypoetes, mighty son of
+Pirithous, and the other Leonteus, peer of murderous Mars. These
+stood before the gates like two high oak trees upon the
+mountains, that tower from their wide-spreading roots, and year
+after year battle with wind and rain--even so did these two men
+await the onset of great Asius confidently and without flinching.
+The Trojans led by him and by Iamenus, Orestes, Adamas the son of
+Asius, Thoon and Oenomaus, raised a loud cry of battle and made
+straight for the wall, holding their shields of dry ox-hide above
+their heads; for a while the two defenders remained inside and
+cheered the Achaeans on to stand firm in the defence of their
+ships; when, however, they saw that the Trojans were attacking
+the wall, while the Danaans were crying out for help and being
+routed, they rushed outside and fought in front of the gates like
+two wild boars upon the mountains that abide the attack of men
+and dogs, and charging on either side break down the wood all
+round them tearing it up by the roots, and one can hear the
+clattering of their tusks, till some one hits them and makes an
+end of them--even so did the gleaming bronze rattle about their
+breasts, as the weapons fell upon them; for they fought with
+great fury, trusting to their own prowess and to those who were
+on the wall above them. These threw great stones at their
+assailants in defence of themselves their tents and their ships.
+The stones fell thick as the flakes of snow which some fierce
+blast drives from the dark clouds and showers down in sheets upon
+the earth--even so fell the weapons from the hands alike of
+Trojans and Achaeans. Helmet and shield rang out as the great
+stones rained upon them, and Asius, the son of Hyrtacus, in his
+dismay cried aloud and smote his two thighs. "Father Jove," he
+cried, "of a truth you too are altogether given to lying. I made
+sure the Argive heroes could not withstand us, whereas like
+slim-waisted wasps, or bees that have their nests in the rocks by
+the wayside--they leave not the holes wherein they have built
+undefended, but fight for their little ones against all who would
+take them--even so these men, though they be but two, will not be
+driven from the gates, but stand firm either to slay or be
+slain."
+</para>
+
+<para>
+He spoke, but moved not the mind of Jove, whose counsel it then
+was to give glory to Hector. Meanwhile the rest of the Trojans
+were fighting about the other gates; I, however, am no god to be
+able to tell about all these things, for the battle raged
+everywhere about the stone wall as it were a fiery furnace. The
+Argives, discomfited though they were, were forced to defend
+their ships, and all the gods who were defending the Achaeans
+were vexed in spirit; but the Lapithae kept on fighting with
+might and main.
+</para>
+
+<para>
+Thereon Polypoetes, mighty son of Pirithous, hit Damasus with a
+spear upon his cheek-pierced helmet. The helmet did not protect
+him, for the point of the spear went through it, and broke the
+bone, so that the brain inside was scattered about, and he died
+fighting. He then slew Pylon and Ormenus. Leonteus, of the race
+of Mars, killed Hippomachus the son of Antimachus by striking him
+with his spear upon the girdle. He then drew his sword and sprang
+first upon Antiphates whom he killed in combat, and who fell face
+upwards on the earth. After him he killed Menon, Iamenus, and
+Orestes, and laid them low one after the other.
+</para>
+
+<para>
+While they were busy stripping the armour from these heroes, the
+youths who were led on by Polydamas and Hector (and these were
+the greater part and the most valiant of those that were trying
+to break through the wall and fire the ships) were still standing
+by the trench, uncertain what they should do; for they had seen a
+sign from heaven when they had essayed to cross it--a soaring
+eagle that flew skirting the left wing of their host, with a
+monstrous blood-red snake in its talons still alive and
+struggling to escape. The snake was still bent on revenge,
+wriggling and twisting itself backwards till it struck the bird
+that held it, on the neck and breast; whereon the bird being in
+pain, let it fall, dropping it into the middle of the host, and
+then flew down the wind with a sharp cry. The Trojans were struck
+with terror when they saw the snake, portent of aegis-bearing
+Jove, writhing in the midst of them, and Polydamas went up to
+Hector and said, "Hector, at our councils of war you are ever
+given to rebuke me, even when I speak wisely, as though it were
+not well, forsooth, that one of the people should cross your will
+either in the field or at the council board; you would have them
+support you always: nevertheless I will say what I think will be
+best; let us not now go on to fight the Danaans at their ships,
+for I know what will happen if this soaring eagle which skirted
+the left wing of our host with a monstrous blood-red snake in its
+talons (the snake being still alive) was really sent as an omen
+to the Trojans on their essaying to cross the trench. The eagle
+let go her hold; she did not succeed in taking it home to her
+little ones, and so will it be--with ourselves; even though by a
+mighty effort we break through the gates and wall of the
+Achaeans, and they give way before us, still we shall not return
+in good order by the way we came, but shall leave many a man
+behind us whom the Achaeans will do to death in defence of their
+ships. Thus would any seer who was expert in these matters, and
+was trusted by the people, read the portent."
+</para>
+
+<para>
+Hector looked fiercely at him and said, "Polydamas, I like not of
+your reading. You can find a better saying than this if you will.
+If, however, you have spoken in good earnest, then indeed has
+heaven robbed you of your reason. You would have me pay no heed
+to the counsels of Jove, nor to the promises he made me--and he
+bowed his head in confirmation; you bid me be ruled rather by the
+flight of wild-fowl. What care I whether they fly towards dawn or
+dark, and whether they be on my right hand or on my left? Let us
+put our trust rather in the counsel of great Jove, king of
+mortals and immortals. There is one omen, and one only--that a
+man should fight for his country. Why are you so fearful? Though
+we be all of us slain at the ships of the Argives you are not
+likely to be killed yourself, for you are not steadfast nor
+courageous. If you will not fight, or would talk others over from
+doing so, you shall fall forthwith before my spear."
+</para>
+
+<para>
+With these words he led the way, and the others followed after
+with a cry that rent the air. Then Jove the lord of thunder sent
+the blast of a mighty wind from the mountains of Ida, that bore
+the dust down towards the ships; he thus lulled the Achaeans into
+security, and gave victory to Hector and to the Trojans, who,
+trusting to their own might and to the signs he had shown them,
+essayed to break through the great wall of the Achaeans. They
+tore down the breastworks from the walls, and overthrew the
+battlements; they upheaved the buttresses, which the Achaeans had
+set in front of the wall in order to support it; when they had
+pulled these down they made sure of breaking through the wall,
+but the Danaans still showed no sign of giving ground; they still
+fenced the battlements with their shields of ox-hide, and hurled
+their missiles down upon the foe as soon as any came below the
+wall.
+</para>
+
+<para>
+The two Ajaxes went about everywhere on the walls cheering on the
+Achaeans, giving fair words to some while they spoke sharply to
+any one whom they saw to be remiss. "My friends," they cried,
+"Argives one and all--good bad and indifferent, for there was
+never fight yet, in which all were of equal prowess--there is now
+work enough, as you very well know, for all of you. See that you
+none of you turn in flight towards the ships, daunted by the
+shouting of the foe, but press forward and keep one another in
+heart, if it may so be that Olympian Jove the lord of lightning
+will vouchsafe us to repel our foes, and drive them back towards
+the city."
+</para>
+
+<para>
+Thus did the two go about shouting and cheering the Achaeans on.
+As the flakes that fall thick upon a winter's day, when Jove is
+minded to snow and to display these his arrows to mankind--he
+lulls the wind to rest, and snows hour after hour till he has
+buried the tops of the high mountains, the headlands that jut
+into the sea, the grassy plains, and the tilled fields of men;
+the snow lies deep upon the forelands, and havens of the grey
+sea, but the waves as they come rolling in stay it that it can
+come no further, though all else is wrapped as with a mantle, so
+heavy are the heavens with snow--even thus thickly did the stones
+fall on one side and on the other, some thrown at the Trojans,
+and some by the Trojans at the Achaeans; and the whole wall was
+in an uproar.
+</para>
+
+<para>
+Still the Trojans and brave Hector would not yet have broken down
+the gates and the great bar, had not Jove turned his son Sarpedon
+against the Argives as a lion against a herd of horned cattle.
+Before him he held his shield of hammered bronze, that the smith
+had beaten so fair and round, and had lined with ox hides which
+he had made fast with rivets of gold all round the shield; this
+he held in front of him, and brandishing his two spears came on
+like some lion of the wilderness, who has been long famished for
+want of meat and will dare break even into a well-fenced
+homestead to try and get at the sheep. He may find the shepherds
+keeping watch over their flocks with dogs and spears, but he is
+in no mind to be driven from the fold till he has had a try for
+it; he will either spring on a sheep and carry it off, or be hit
+by a spear from some strong hand--even so was Sarpedon fain to
+attack the wall and break down its battlements. Then he said to
+Glaucus son of Hippolochus, "Glaucus, why in Lycia do we receive
+especial honour as regards our place at table? Why are the
+choicest portions served us and our cups kept brimming, and why
+do men look up to us as though we were gods? Moreover we hold a
+large estate by the banks of the river Xanthus, fair with orchard
+lawns and wheat-growing land; it becomes us, therefore, to take
+our stand at the head of all the Lycians and bear the brunt of
+the fight, that one may say to another, 'Our princes in Lycia eat
+the fat of the land and drink best of wine, but they are fine
+fellows; they fight well and are ever at the front in battle.' My
+good friend, if, when we were once out of this fight, we could
+escape old age and death thenceforward and forever, I should
+neither press forward myself nor bid you do so, but death in ten
+thousand shapes hangs ever over our heads, and no man can elude
+him; therefore let us go forward and either win glory for
+ourselves, or yield it to another."
+</para>
+
+<para>
+Glaucus heeded his saying, and the pair forthwith led on the host
+of Lycians. Menestheus son of Peteos was dismayed when he saw
+them, for it was against his part of the wall that they came--
+bringing destruction with them; he looked along the wall for some
+chieftain to support his comrades and saw the two Ajaxes, men
+ever eager for the fray, and Teucer, who had just come from his
+tent, standing near them; but he could not make his voice heard
+by shouting to them, so great an uproar was there from crashing
+shields and helmets and the battering of gates with a din which
+reached the skies. For all the gates had been closed, and the
+Trojans were hammering at them to try and break their way through
+them. Menestheus, therefore, sent Thootes with a message to Ajax.
+"Run, good Thootes," he said, "and call Ajax, or better still bid
+both come, for it will be all over with us here directly; the
+leaders of the Lycians are upon us, men who have ever fought
+desperately heretofore. But if they have too much on their hands
+to let them come, at any rate let Ajax son of Telamon do so, and
+let Teucer, the famous bowman, come with him."
+</para>
+
+<para>
+The messenger did as he was told, and set off running along the
+wall of the Achaeans. When he reached the Ajaxes he said to them,
+"Sirs, princes of the Argives, the son of noble Peteos bids you
+come to him for a while and help him. You had better both come if
+you can, or it will be all over with him directly; the leaders of
+the Lycians are upon him, men who have ever fought desperately
+heretofore; if you have too much on your hands to let both come,
+at any rate let Ajax, son of Telamon, do so, and let Teucer, the
+famous bowman, come with him."
+</para>
+
+<para>
+Great Ajax son of Telamon heeded the message, and at once spoke
+to the son of Oileus. "Ajax," said he, "do you two, yourself and
+brave Lycomedes, stay here and keep the Danaans in heart to fight
+their hardest. I will go over yonder, and bear my part in the
+fray, but I will come back here at once as soon as I have given
+them the help they need."
+</para>
+
+<para>
+With this, Ajax son of Telamon set off, and Teucer, his brother
+by the same father, went also, with Pandion to carry Teucer's
+bow. They went along inside the wall, and when they came to the
+tower where Menestheus was (and hard pressed indeed did they find
+him) the brave captains and leaders of the Lycians were storming
+the battlements as it were a thick dark cloud, fighting in close
+quarters, and raising the battle-cry aloud.
+</para>
+
+<para>
+First, Ajax son of Telamon killed brave Epicles, a comrade of
+Sarpedon, hitting him with a jagged stone that lay by the
+battlements at the very top of the wall. As men now are, even one
+who is in the bloom of youth could hardly lift it with his two
+hands, but Ajax raised it high aloft and flung it down, smashing
+Epicles' four-crested helmet so that the bones of his head were
+crushed to pieces, and he fell from the high wall as though he
+were diving, with no more life left in him. Then Teucer wounded
+Glaucus the brave son of Hippolochus as he was coming on to
+attack the wall. He saw his shoulder bare and aimed an arrow at
+it, which made Glaucus leave off fighting. Thereon he sprang
+covertly down for fear some of the Achaeans might see that he was
+wounded and taunt him. Sarpedon was stung with grief when he saw
+Glaucus leave him, still he did not leave off fighting, but aimed
+his spear at Alcmaon the son of Thestor and hit him. He drew his
+spear back again and Alcmaon came down headlong after it with his
+bronzed armour rattling round him. Then Sarpedon seized the
+battlement in his strong hands, and tugged at it till it all gave
+way together, and a breach was made through which many might
+pass.
+</para>
+
+<para>
+Ajax and Teucer then both of them attacked him. Teucer hit him
+with an arrow on the band that bore the shield which covered his
+body, but Jove saved his son from destruction that he might not
+fall by the ships' sterns. Meanwhile Ajax sprang on him and
+pierced his shield, but the spear did not go clean through,
+though it hustled him back that he could come on no further. He
+therefore retired a little space from the battlement, yet without
+losing all his ground, for he still thought to cover himself with
+glory. Then he turned round and shouted to the brave Lycians
+saying, "Lycians, why do you thus fail me? For all my prowess I
+cannot break through the wall and open a way to the ships
+single-handed. Come close on behind me, for the more there are of
+us the better."
+</para>
+
+<para>
+The Lycians, shamed by his rebuke, pressed closer round him who
+was their counsellor and their king. The Argives on their part
+got their men in fighting order within the wall, and there was a
+deadly struggle between them. The Lycians could not break through
+the wall and force their way to the ships, nor could the Danaans
+drive the Lycians from the wall now that they had once reached
+it. As two men, measuring-rods in hand, quarrel about their
+boundaries in a field that they own in common, and stickle for
+their rights though they be but in a mere strip, even so did the
+battlements now serve as a bone of contention, and they beat one
+another's round shields for their possession. Many a man's body
+was wounded with the pitiless bronze, as he turned round and
+bared his back to the foe, and many were struck clean through
+their shields; the wall and battlements were everywhere deluged
+with the blood alike of Trojans and of Achaeans. But even so the
+Trojans could not rout the Achaeans, who still held on; and as
+some honest hard-working woman weighs wool in her balance and
+sees that the scales be true, for she would gain some pitiful
+earnings for her little ones, even so was the fight balanced
+evenly between them till the time came when Jove gave the greater
+glory to Hector son of Priam, who was first to spring towards the
+wall of the Achaeans. When he had done so, he cried aloud to the
+Trojans, "Up, Trojans, break the wall of the Argives, and fling
+fire upon their ships."
+</para>
+
+<para>
+Thus did he hound them on, and in one body they rushed straight
+at the wall as he had bidden them, and scaled the battlements
+with sharp spears in their hands. Hector laid hold of a stone
+that lay just outside the gates and was thick at one end but
+pointed at the other; two of the best men in a town, as men now
+are, could hardly raise it from the ground and put it on to a
+waggon, but Hector lifted it quite easily by himself, for the son
+of scheming Saturn made it light for him. As a shepherd picks up
+a ram's fleece with one hand and finds it no burden, so easily
+did Hector lift the great stone and drive it right at the doors
+that closed the gates so strong and so firmly set. These doors
+were double and high, and were kept closed by two cross-bars to
+which there was but one key. When he had got close up to them,
+Hector strode towards them that his blow might gain in force and
+struck them in the middle, leaning his whole weight against them.
+He broke both hinges, and the stone fell inside by reason of its
+great weight. The portals re-echoed with the sound, the bars held
+no longer, and the doors flew open, one one way, and the other
+the other, through the force of the blow. Then brave Hector
+leaped inside with a face as dark as that of flying night. The
+gleaming bronze flashed fiercely about his body and he had two
+spears in his hand. None but a god could have withstood him as he
+flung himself into the gateway, and his eyes glared like fire.
+Then he turned round towards the Trojans and called on them to
+scale the wall, and they did as he bade them--some of them at
+once climbing over the wall, while others passed through the
+gates. The Danaans then fled panic-stricken towards their ships,
+and all was uproar and confusion.
+</para>
+</chapter>
+
+<chapter>
+<title>BOOK XIII</title>
+
+<para>
+NOW when Jove had thus brought Hector and the Trojans to the
+ships, he left them to their never-ending toil, and turned his
+keen eyes away, looking elsewhither towards the horse-breeders of
+Thrace, the Mysians, fighters at close quarters, the noble
+Hippemolgi, who live on milk, and the Abians, justest of mankind.
+He no longer turned so much as a glance towards Troy, for he did
+not think that any of the immortals would go and help either
+Trojans or Danaans.
+</para>
+
+<para>
+But King Neptune had kept no blind look-out; he had been looking
+admiringly on the battle from his seat on the topmost crests of
+wooded Samothrace, whence he could see all Ida, with the city of
+Priam and the ships of the Achaeans. He had come from under the
+sea and taken his place here, for he pitied the Achaeans who were
+being overcome by the Trojans; and he was furiously angry with
+Jove.
+</para>
+
+<para>
+Presently he came down from his post on the mountain top, and as
+he strode swiftly onwards the high hills and the forest quaked
+beneath the tread of his immortal feet. Three strides he took,
+and with the fourth he reached his goal--Aegae, where is his
+glittering golden palace, imperishable, in the depths of the sea.
+When he got there, he yoked his fleet brazen-footed steeds with
+their manes of gold all flying in the wind; he clothed himself in
+raiment of gold, grasped his gold whip, and took his stand upon
+his chariot. As he went his way over the waves the sea-monsters
+left their lairs, for they knew their lord, and came gambolling
+round him from every quarter of the deep, while the sea in her
+gladness opened a path before his chariot. So lightly did the
+horses fly that the bronze axle of the car was not even wet
+beneath it; and thus his bounding steeds took him to the ships of
+the Achaeans.
+</para>
+
+<para>
+Now there is a certain huge cavern in the depths of the sea
+midway between Tenedos and rocky Imbrus; here Neptune lord of the
+earthquake stayed his horses, unyoked them, and set before them
+their ambrosial forage. He hobbled their feet with hobbles of
+gold which none could either unloose or break, so that they might
+stay there in that place until their lord should return. This
+done he went his way to the host of the Achaeans.
+</para>
+
+<para>
+Now the Trojans followed Hector son of Priam in close array like
+a storm-cloud or flame of fire, fighting with might and main and
+raising the cry battle; for they deemed that they should take the
+ships of the Achaeans and kill all their chiefest heroes then and
+there. Meanwhile earth-encircling Neptune lord of the earthquake
+cheered on the Argives, for he had come up out of the sea and had
+assumed the form and voice of Calchas.
+</para>
+
+<para>
+First he spoke to the two Ajaxes, who were doing their best
+already, and said, "Ajaxes, you two can be the saving of the
+Achaeans if you will put out all your strength and not let
+yourselves be daunted. I am not afraid that the Trojans, who have
+got over the wall in force, will be victorious in any other part,
+for the Achaeans can hold all of them in check, but I much fear
+that some evil will befall us here where furious Hector, who
+boasts himself the son of great Jove himself, is leading them on
+like a pillar of flame. May some god, then, put it into your
+hearts to make a firm stand here, and to incite others to do the
+like. In this case you will drive him from the ships even though
+he be inspired by Jove himself."
+</para>
+
+<para>
+As he spoke the earth-encircling lord of the earthquake struck
+both of them with his sceptre and filled their hearts with
+daring. He made their legs light and active, as also their hands
+and their feet. Then, as the soaring falcon poises on the wing
+high above some sheer rock, and presently swoops down to chase
+some bird over the plain, even so did Neptune lord of the
+earthquake wing his flight into the air and leave them. Of the
+two, swift Ajax son of Oileus was the first to know who it was
+that had been speaking with them, and said to Ajax son of
+Telamon, "Ajax, this is one of the gods that dwell on Olympus,
+who in the likeness of the prophet is bidding us fight hard by
+our ships. It was not Calchas the seer and diviner of omens; I
+knew him at once by his feet and knees as he turned away, for the
+gods are soon recognised. Moreover I feel the lust of battle burn
+more fiercely within me, while my hands and my feet under me are
+more eager for the fray."
+</para>
+
+<para>
+And Ajax son of Telamon answered, "I too feel my hands grasp my
+spear more firmly; my strength is greater, and my feet more
+nimble; I long, moreover, to meet furious Hector son of Priam,
+even in single combat."
+</para>
+
+<para>
+Thus did they converse, exulting in the hunger after battle with
+which the god had filled them. Meanwhile the earth-encircler
+roused the Achaeans, who were resting in the rear by the ships
+overcome at once by hard fighting and by grief at seeing that the
+Trojans had got over the wall in force. Tears began falling from
+their eyes as they beheld them, for they made sure that they
+should not escape destruction; but the lord of the earthquake
+passed lightly about among them and urged their battalions to the
+front.
+</para>
+
+<para>
+First he went up to Teucer and Leitus, the hero Peneleos, and
+Thoas and Deipyrus; Meriones also and Antilochus, valiant
+warriors; all did he exhort. "Shame on you young Argives," he
+cried, "it was on your prowess I relied for the saving of our
+ships; if you fight not with might and main, this very day will
+see us overcome by the Trojans. Of a truth my eyes behold a great
+and terrible portent which I had never thought to see--the
+Trojans at our ships--they, who were heretofore like
+panic-stricken hinds, the prey of jackals and wolves in a forest,
+with no strength but in flight for they cannot defend themselves.
+Hitherto the Trojans dared not for one moment face the attack of
+the Achaeans, but now they have sallied far from their city and
+are fighting at our very ships through the cowardice of our
+leader and the disaffection of the people themselves, who in
+their discontent care not to fight in defence of the ships but
+are being slaughtered near them. True, King Agamemnon son of
+Atreus is the cause of our disaster by having insulted the son of
+Peleus, still this is no reason why we should leave off fighting.
+Let us be quick to heal, for the hearts of the brave heal
+quickly. You do ill to be thus remiss, you, who are the finest
+soldiers in our whole army. I blame no man for keeping out of
+battle if he is a weakling, but I am indignant with such men as
+you are. My good friends, matters will soon become even worse
+through this slackness; think, each one of you, of his own honour
+and credit, for the hazard of the fight is extreme. Great Hector
+is now fighting at our ships; he has broken through the gates and
+the strong bolt that held them."
+</para>
+
+<para>
+Thus did the earth-encircler address the Achaeans and urge them
+on. Thereon round the two Ajaxes there gathered strong bands of
+men, of whom not even Mars nor Minerva, marshaller of hosts could
+make light if they went among them, for they were the picked men
+of all those who were now awaiting the onset of Hector and the
+Trojans. They made a living fence, spear to spear, shield to
+shield, buckler to buckler, helmet to helmet, and man to man. The
+horse-hair crests on their gleaming helmets touched one another
+as they nodded forward, so closely serried were they; the spears
+they brandished in their strong hands were interlaced, and their
+hearts were set on battle.
+</para>
+
+<para>
+The Trojans advanced in a dense body, with Hector at their head
+pressing right on as a rock that comes thundering down the side
+of some mountain from whose brow the winter torrents have torn
+it; the foundations of the dull thing have been loosened by
+floods of rain, and as it bounds headlong on its way it sets the
+whole forest in an uproar; it swerves neither to right nor left
+till it reaches level ground, but then for all its fury it can go
+no further--even so easily did Hector for a while seem as though
+he would career through the tents and ships of the Achaeans till
+he had reached the sea in his murderous course; but the closely
+serried battalions stayed him when he reached them, for the sons
+of the Achaeans thrust at him with swords and spears pointed at
+both ends, and drove him from them so that he staggered and gave
+ground; thereon he shouted to the Trojans, "Trojans, Lycians, and
+Dardanians, fighters in close combat, stand firm: the Achaeans
+have set themselves as a wall against me, but they will not check
+me for long; they will give ground before me if the mightiest of
+the gods, the thundering spouse of Juno, has indeed inspired my
+onset."
+</para>
+
+<para>
+With these words he put heart and soul into them all. Deiphobus
+son of Priam went about among them intent on deeds of daring with
+his round shield before him, under cover of which he strode
+quickly forward. Meriones took aim at him with a spear, nor did
+he fail to hit the broad orb of ox-hide; but he was far from
+piercing it for the spear broke in two pieces long ere he could
+do so; moreover Deiphobus had seen it coming and had held his
+shield well away from him. Meriones drew back under cover of his
+comrades, angry alike at having failed to vanquish Deiphobus, and
+having broken his spear. He turned therefore towards the ships
+and tents to fetch a spear which he had left behind in his tent.
+</para>
+
+<para>
+The others continued fighting, and the cry of battle rose up into
+the heavens. Teucer son of Telamon was the first to kill his man,
+to wit, the warrior Imbrius, son of Mentor, rich in horses.
+Until the Achaeans came he had lived in Pedaeum, and had married
+Medesicaste, a bastard daughter of Priam; but on the arrival of
+the Danaan fleet he had gone back to Ilius, and was a great man
+among the Trojans, dwelling near Priam himself, who gave him like
+honour with his own sons. The son of Telamon now struck him under
+the ear with a spear which he then drew back again, and Imbrius
+fell headlong as an ash-tree when it is felled on the crest of
+some high mountain beacon, and its delicate green foliage comes
+toppling down to the ground. Thus did he fall with his
+bronze-dight armour ringing harshly round him, and Teucer sprang
+forward with intent to strip him of his armour; but as he was
+doing so, Hector took aim at him with a spear. Teucer saw the
+spear coming and swerved aside, whereon it hit Amphimachus, son
+of Cteatus son of Actor, in the chest as he was coming into
+battle, and his armour rang rattling round him as he fell heavily
+to the ground. Hector sprang forward to take Amphimachus's helmet
+from off his temples, and in a moment Ajax threw a spear at him,
+but did not wound him, for he was encased all over in his
+terrible armour; nevertheless the spear struck the boss of his
+shield with such force as to drive him back from the two corpses,
+which the Achaeans then drew off. Stichius and Menestheus,
+captains of the Athenians, bore away Amphimachus to the host of
+the Achaeans, while the two brave and impetuous Ajaxes did the
+like by Imbrius. As two lions snatch a goat from the hounds that
+have it in their fangs, and bear it through thick brushwood high
+above the ground in their jaws, thus did the Ajaxes bear aloft
+the body of Imbrius, and strip it of its armour. Then the son of
+Oileus severed the head from the neck in revenge for the death of
+Amphimachus, and sent it whirling over the crowd as though it had
+been a ball, till it fell in the dust at Hector's feet.
+</para>
+
+<para>
+Neptune was exceedingly angry that his grandson Amphimachus
+should have fallen; he therefore went to the tents and ships of
+the Achaeans to urge the Danaans still further, and to devise
+evil for the Trojans. Idomeneus met him, as he was taking leave
+of a comrade, who had just come to him from the fight, wounded in
+the knee. His fellow-soldiers bore him off the field, and
+Idomeneus having given orders to the physicians went on to his
+tent, for he was still thirsting for battle. Neptune spoke in the
+likeness and with the voice of Thoas son of Andraemon who ruled
+the Aetolians of all Pleuron and high Calydon, and was honoured
+among his people as though he were a god. "Idomeneus," said he,
+"lawgiver to the Cretans, what has now become of the threats with
+which the sons of the Achaeans used to threaten the Trojans?"
+</para>
+
+<para>
+And Idomeneus chief among the Cretans answered, "Thoas, no one,
+so far as I know, is in fault, for we can all fight. None are
+held back neither by fear nor slackness, but it seems to be the
+will of almighty Jove that the Achaeans should perish
+ingloriously here far from Argos: you, Thoas, have been always
+staunch, and you keep others in heart if you see any fail in
+duty; be not then remiss now, but exhort all to do their utmost."
+</para>
+
+<para>
+To this Neptune lord of the earthquake made answer, "Idomeneus,
+may he never return from Troy, but remain here for dogs to batten
+upon, who is this day wilfully slack in fighting. Get your armour
+and go, we must make all haste together if we may be of any use,
+though we are only two. Even cowards gain courage from
+companionship, and we two can hold our own with the bravest."
+</para>
+
+<para>
+Therewith the god went back into the thick of the fight, and
+Idomeneus when he had reached his tent donned his armour, grasped
+his two spears, and sallied forth. As the lightning which the son
+of Saturn brandishes from bright Olympus when he would show a
+sign to mortals, and its gleam flashes far and wide--even so did
+his armour gleam about him as he ran. Meriones his sturdy squire
+met him while he was still near his tent (for he was going to
+fetch his spear) and Idomeneus said:
+</para>
+
+<para>
+"Meriones, fleet son of Molus, best of comrades, why have you
+left the field? Are you wounded, and is the point of the weapon
+hurting you? or have you been sent to fetch me? I want no
+fetching; I had far rather fight than stay in my tent."
+</para>
+
+<para>
+"Idomeneus," answered Meriones, "I come for a spear, if I can
+find one in my tent; I have broken the one I had, in throwing it
+at the shield of Deiphobus."
+</para>
+
+<para>
+And Idomeneus captain of the Cretans answered, "You will find one
+spear, or twenty if you so please, standing up against the end
+wall of my tent. I have taken them from Trojans whom I have
+killed, for I am not one to keep my enemy at arm's length;
+therefore I have spears, bossed shields, helmets, and burnished
+corslets."
+</para>
+
+<para>
+Then Meriones said, "I too in my tent and at my ship have spoils
+taken from the Trojans, but they are not at hand. I have been at
+all times valorous, and wherever there has been hard fighting
+have held my own among the foremost. There may be those among the
+Achaeans who do not know how I fight, but you know it well enough
+yourself."
+</para>
+
+<para>
+Idomeneus answered, "I know you for a brave man: you need not
+tell me. If the best men at the ships were being chosen to go on
+an ambush--and there is nothing like this for showing what a man
+is made of; it comes out then who is cowardly and who brave; the
+coward will change colour at every touch and turn; he is full of
+fears, and keeps shifting his weight first on one knee and then
+on the other; his heart beats fast as he thinks of death, and one
+can hear the chattering of his teeth; whereas the brave man will
+not change colour nor be frightened on finding himself in ambush,
+but is all the time longing to go into action--if the best men
+were being chosen for such a service, no one could make light of
+your courage nor feats of arms. If you were struck by a dart or
+smitten in close combat, it would not be from behind, in your
+neck nor back, but the weapon would hit you in the chest or belly
+as you were pressing forward to a place in the front ranks. But
+let us no longer stay here talking like children, lest we be ill
+spoken of; go, fetch your spear from the tent at once."
+</para>
+
+<para>
+On this Meriones, peer of Mars, went to the tent and got himself
+a spear of bronze. He then followed after Idomeneus, big with
+great deeds of valour. As when baneful Mars sallies forth to
+battle, and his son Panic so strong and dauntless goes with him,
+to strike terror even into the heart of a hero--the pair have
+gone from Thrace to arm themselves among the Ephyri or the brave
+Phlegyans, but they will not listen to both the contending hosts,
+and will give victory to one side or to the other--even so did
+Meriones and Idomeneus, captains of men, go out to battle clad in
+their bronze armour. Meriones was first to speak. "Son of
+Deucalion," said he, "where would you have us begin fighting? On
+the right wing of the host, in the centre, or on the left wing,
+where I take it the Achaeans will be weakest?"
+</para>
+
+<para>
+Idomeneus answered, "There are others to defend the centre--the
+two Ajaxes and Teucer, who is the finest archer of all the
+Achaeans, and is good also in a hand-to-hand fight. These will
+give Hector son of Priam enough to do; fight as he may, he will
+find it hard to vanquish their indomitable fury, and fire the
+ships, unless the son of Saturn fling a firebrand upon them with
+his own hand. Great Ajax son of Telamon will yield to no man who
+is in mortal mould and eats the grain of Ceres, if bronze and
+great stones can overthrow him. He would not yield even to
+Achilles in hand-to-hand fight, and in fleetness of foot there is
+none to beat him; let us turn therefore towards the left wing,
+that we may know forthwith whether we are to give glory to some
+other, or he to us."
+</para>
+
+<para>
+Meriones, peer of fleet Mars, then led the way till they came to
+the part of the host which Idomeneus had named.
+</para>
+
+<para>
+Now when the Trojans saw Idomeneus coming on like a flame of
+fire, him and his squire clad in their richly wrought armour,
+they shouted and made towards him all in a body, and a furious
+hand-to-hand fight raged under the ships' sterns. Fierce as the
+shrill winds that whistle upon a day when dust lies deep on the
+roads, and the gusts raise it into a thick cloud--even such was
+the fury of the combat, and might and main did they hack at each
+other with spear and sword throughout the host. The field
+bristled with the long and deadly spears which they bore.
+Dazzling was the sheen of their gleaming helmets, their
+fresh-burnished breastplates, and glittering shields as they
+joined battle with one another. Iron indeed must be his courage
+who could take pleasure in the sight of such a turmoil, and look
+on it without being dismayed.
+</para>
+
+<para>
+Thus did the two mighty sons of Saturn devise evil for mortal
+heroes. Jove was minded to give victory to the Trojans and to
+Hector, so as to do honour to fleet Achilles, nevertheless he did
+not mean to utterly overthrow the Achaean host before Ilius, and
+only wanted to glorify Thetis and her valiant son. Neptune on the
+other hand went about among the Argives to incite them, having
+come up from the grey sea in secret, for he was grieved at seeing
+them vanquished by the Trojans, and was furiously angry with
+Jove. Both were of the same race and country, but Jove was elder
+born and knew more, therefore Neptune feared to defend the
+Argives openly, but in the likeness of man, he kept on
+encouraging them throughout their host. Thus, then, did these two
+devise a knot of war and battle, that none could unloose or
+break, and set both sides tugging at it, to the failing of men's
+knees beneath them.
+</para>
+
+<para>
+And now Idomeneus, though his hair was already flecked with grey,
+called loud on the Danaans and spread panic among the Trojans as
+he leaped in among them. He slew Othryoneus from Cabesus, a
+sojourner, who had but lately come to take part in the war. He
+sought Cassandra, the fairest of Priam's daughters, in marriage,
+but offered no gifts of wooing, for he promised a great thing, to
+wit, that he would drive the sons of the Achaeans willy nilly
+from Troy; old King Priam had given his consent and promised her
+to him, whereon he fought on the strength of the promises thus
+made to him. Idomeneus aimed a spear, and hit him as he came
+striding on. His cuirass of bronze did not protect him, and the
+spear stuck in his belly, so that he fell heavily to the ground.
+Then Idomeneus vaunted over him saying, "Othryoneus, there is no
+one in the world whom I shall admire more than I do you, if you
+indeed perform what you have promised Priam son of Dardanus in
+return for his daughter. We too will make you an offer; we will
+give you the loveliest daughter of the son of Atreus, and will
+bring her from Argos for you to marry, if you will sack the
+goodly city of Ilius in company with ourselves; so come along
+with me, that we may make a covenant at the ships about the
+marriage, and we will not be hard upon you about gifts of
+wooing."
+</para>
+
+<para>
+With this Idomeneus began dragging him by the foot through the
+thick of the fight, but Asius came up to protect the body, on
+foot, in front of his horses which his esquire drove so close
+behind him that he could feel their breath upon his shoulder. He
+was longing to strike down Idomeneus, but ere he could do so
+Idomeneus smote him with his spear in the throat under the chin,
+and the bronze point went clean through it. He fell as an oak, or
+poplar, or pine which shipwrights have felled for ship's timber
+upon the mountains with whetted axes--even thus did he lie full
+length in front of his chariot and horses, grinding his teeth and
+clutching at the bloodstained dust. His charioteer was struck
+with panic and did not dare turn his horses round and escape:
+thereupon Antilochus hit him in the middle of his body with a
+spear; his cuirass of bronze did not protect him, and the spear
+stuck in his belly. He fell gasping from his chariot and
+Antilochus, great Nestor's son, drove his horses from the Trojans
+to the Achaeans.
+</para>
+
+<para>
+Deiphobus then came close up to Idomeneus to avenge Asius, and
+took aim at him with a spear, but Idomeneus was on the look-out
+and avoided it, for he was covered by the round shield he always
+bore--a shield of oxhide and bronze with two arm-rods on the
+inside. He crouched under cover of this, and the spear flew over
+him, but the shield rang out as the spear grazed it, and the
+weapon sped not in vain from the strong hand of Deiphobus, for it
+struck Hypsenor son of Hippasus, shepherd of his people, in the
+liver under the midriff, and his limbs failed beneath him.
+Deiphobus vaunted over him and cried with a loud voice saying,
+"Of a truth Asius has not fallen unavenged; he will be glad even
+while passing into the house of Hades, strong warden of the gate,
+that I have sent some one to escort him."
+</para>
+
+<para>
+Thus did he vaunt, and the Argives were stung by his saying.
+Noble Antilochus was more angry than any one, but grief did not
+make him forget his friend and comrade. He ran up to him,
+bestrode him, and covered him with his shield; then two of his
+staunch comrades, Mecisteus son of Echius, and Alastor, stooped
+down, and bore him away groaning heavily to the ships. But
+Idomeneus ceased not his fury. He kept on striving continually
+either to enshroud some Trojan in the darkness of death, or
+himself to fall while warding off the evil day from the Achaeans.
+Then fell Alcathous son of noble Aesyetes; he was son-in-law to
+Anchises, having married his eldest daughter Hippodameia, who was
+the darling of her father and mother, and excelled all her
+generation in beauty, accomplishments, and understanding,
+wherefore the bravest man in all Troy had taken her to wife--him
+did Neptune lay low by the hand of Idomeneus, blinding his bright
+eyes and binding his strong limbs in fetters so that he could
+neither go back nor to one side, but stood stock still like
+pillar or lofty tree when Idomeneus struck him with a spear in
+the middle of his chest. The coat of mail that had hitherto
+protected his body was now broken, and rang harshly as the spear
+tore through it. He fell heavily to the ground, and the spear
+stuck in his heart, which still beat, and made the butt-end of
+the spear quiver till dread Mars put an end to his life.
+Idomeneus vaunted over him and cried with a loud voice saying,
+"Deiphobus, since you are in a mood to vaunt, shall we cry quits
+now that we have killed three men to your one? Nay, sir, stand in
+fight with me yourself, that you may learn what manner of
+Jove-begotten man am I that have come hither. Jove first begot
+Minos, chief ruler in Crete, and Minos in his turn begot a son,
+noble Deucalion. Deucalion begot me to be a ruler over many men
+in Crete, and my ships have now brought me hither, to be the bane
+of yourself, your father, and the Trojans."
+</para>
+
+<para>
+Thus did he speak, and Deiphobus was in two minds, whether to go
+back and fetch some other Trojan to help him, or to take up the
+challenge single-handed. In the end, he deemed it best to go and
+fetch Aeneas, whom he found standing in the rear, for he had long
+been aggrieved with Priam because in spite of his brave deeds he
+did not give him his due share of honour. Deiphobus went up to
+him and said, "Aeneas, prince among the Trojans, if you know any
+ties of kinship, help me now to defend the body of your sister's
+husband; come with me to the rescue of Alcathous, who being
+husband to your sister brought you up when you were a child in
+his house, and now Idomeneus has slain him."
+</para>
+
+<para>
+With these words he moved the heart of Aeneas, and he went in
+pursuit of Idomeneus, big with great deeds of valour; but
+Idomeneus was not to be thus daunted as though he were a mere
+child; he held his ground as a wild boar at bay upon the
+mountains, who abides the coming of a great crowd of men in some
+lonely place--the bristles stand upright on his back, his eyes
+flash fire, and he whets his tusks in his eagerness to defend
+himself against hounds and men--even so did famed Idomeneus hold
+his ground and budge not at the coming of Aeneas. He cried aloud
+to his comrades looking towards Ascalaphus, Aphareus, Deipyrus,
+Meriones, and Antilochus, all of them brave soldiers--"Hither my
+friends," he cried, "and leave me not single-handed--I go in
+great fear by fleet Aeneas, who is coming against me, and is a
+redoubtable dispenser of death battle. Moreover he is in the
+flower of youth when a man's strength is greatest; if I was of
+the same age as he is and in my present mind, either he or I
+should soon bear away the prize of victory."
+</para>
+
+<para>
+On this, all of them as one man stood near him, shield on
+shoulder. Aeneas on the other side called to his comrades,
+looking towards Deiphobus, Paris, and Agenor, who were leaders of
+the Trojans along with himself, and the people followed them as
+sheep follow the ram when they go down to drink after they have
+been feeding, and the heart of the shepherd is glad--even so was
+the heart of Aeneas gladdened when he saw his people follow him.
+</para>
+
+<para>
+Then they fought furiously in close combat about the body of
+Alcathous, wielding their long spears; and the bronze armour
+about their bodies rang fearfully as they took aim at one another
+in the press of the fight, while the two heroes Aeneas and
+Idomeneus, peers of Mars, outvied everyone in their desire to
+hack at each other with sword and spear. Aeneas took aim first,
+but Idomeneus was on the lookout and avoided the spear, so that
+it sped from Aeneas' strong hand in vain, and fell quivering in
+the ground. Idomeneus meanwhile smote Oenomaus in the middle of
+his belly, and broke the plate of his corslet, whereon his bowels
+came gushing out and he clutched the earth in the palms of his
+hands as he fell sprawling in the dust. Idomeneus drew his spear
+out of the body, but could not strip him of the rest of his
+armour for the rain of darts that were showered upon him:
+moreover his strength was now beginning to fail him so that he
+could no longer charge, and could neither spring forward to
+recover his own weapon nor swerve aside to avoid one that was
+aimed at him; therefore, though he still defended himself in
+hand-to-hand fight, his heavy feet could not bear him swiftly out
+of the battle. Deiphobus aimed a spear at him as he was
+retreating slowly from the field, for his bitterness against him
+was as fierce as ever, but again he missed him, and hit
+Ascalaphus, the son of Mars; the spear went through his shoulder,
+and he clutched the earth in the palms of his hands as he fell
+sprawling in the dust.
+</para>
+
+<para>
+Grim Mars of awful voice did not yet know that his son had
+fallen, for he was sitting on the summits of Olympus under the
+golden clouds, by command of Jove, where the other gods were also
+sitting, forbidden to take part in the battle. Meanwhile men
+fought furiously about the body. Deiphobus tore the helmet from
+off his head, but Meriones sprang upon him, and struck him on the
+arm with a spear so that the visored helmet fell from his hand
+and came ringing down upon the ground. Thereon Meriones sprang
+upon him like a vulture, drew the spear from his shoulder, and
+fell back under cover of his men. Then Polites, own brother of
+Deiphobus passed his arms around his waist, and bore him away
+from the battle till he got to his horses that were standing in
+the rear of the fight with the chariot and their driver. These
+took him towards the city groaning and in great pain, with the
+blood flowing from his arm.
+</para>
+
+<para>
+The others still fought on, and the battle-cry rose to heaven
+without ceasing. Aeneas sprang on Aphareus son of Caletor, and
+struck him with a spear in his throat which was turned towards
+him; his head fell on one side, his helmet and shield came down
+along with him, and death, life's foe, was shed around him.
+Antilochus spied his chance, flew forward towards Thoon, and
+wounded him as he was turning round. He laid open the vein that
+runs all the way up the back to the neck; he cut this vein clean
+away throughout its whole course, and Thoon fell in the dust face
+upwards, stretching out his hands imploringly towards his
+comrades. Antilochus sprang upon him and stripped the armour from
+his shoulders, glaring round him fearfully as he did so. The
+Trojans came about him on every side and struck his broad and
+gleaming shield, but could not wound his body, for Neptune stood
+guard over the son of Nestor, though the darts fell thickly round
+him. He was never clear of the foe, but was always in the thick
+of the fight; his spear was never idle; he poised and aimed it in
+every direction, so eager was he to hit someone from a distance
+or to fight him hand to hand.
+</para>
+
+<para>
+As he was thus aiming among the crowd, he was seen by Adamas, son
+of Asius, who rushed towards him and struck him with a spear in
+the middle of his shield, but Neptune made its point without
+effect, for he grudged him the life of Antilochus. One half,
+therefore, of the spear stuck fast like a charred stake in
+Antilochus's shield, while the other lay on the ground. Adamas
+then sought shelter under cover of his men, but Meriones followed
+after and hit him with a spear midway between the private parts
+and the navel, where a wound is particualrly painful to wretched
+mortals. There did Meriones transfix him, and he writhed
+convulsively about the spear as some bull whom mountain herdsmen
+have bound with ropes of withes and are taking away perforce.
+Even so did he move convulsively for a while, but not for very
+long, till Meriones came up and drew the spear out of his body,
+and his eyes were veiled in darkness.
+</para>
+
+<para>
+Helenus then struck Deipyrus with a great Thracian sword, hitting
+him on the temple in close combat and tearing the helmet from his
+head; the helmet fell to the ground, and one of those who were
+fighting on the Achaean side took charge of it as it rolled at
+his feet, but the eyes of Deipyrus were closed in the darkness of
+death.
+</para>
+
+<para>
+On this Menelaus was grieved, and made menacingly towards
+Helenus, brandishing his spear; but Helenus drew his bow, and the
+two attacked one another at one and the same moment, the one with
+his spear, and the other with his bow and arrow. The son of Priam
+hit the breastplate of Menelaus's corslet, but the arrow glanced
+from off it. As black beans or pulse come pattering down on to a
+threshing-floor from the broad winnowing-shovel, blown by shrill
+winds and shaken by the shovel--even so did the arrow glance off
+and recoil from the shield of Menelaus, who in his turn wounded
+the hand with which Helenus carried his bow; the spear went right
+through his hand and stuck in the bow itself, so that to his life
+he retreated under cover of his men, with his hand dragging by
+his side--for the spear weighed it down till Agenor drew it out
+and bound the hand carefully up in a woollen sling which his
+esquire had with him.
+</para>
+
+<para>
+Pisander then made straight at Menelaus--his evil destiny luring
+him on to his doom, for he was to fall in fight with you, O
+Menelaus. When the two were hard by one another the spear of the
+son of Atreus turned aside and he missed his aim; Pisander then
+struck the shield of brave Menelaus but could not pierce it, for
+the shield stayed the spear and broke the shaft; nevertheless he
+was glad and made sure of victory; forthwith, however, the son of
+Atreus drew his sword and sprang upon him. Pisander then seized
+the bronze battle-axe, with its long and polished handle of olive
+wood that hung by his side under his shield, and the two made at
+one another. Pisander struck the peak of Menelaus's crested
+helmet just under the crest itself, and Menelaus hit Pisander as
+he was coming towards him, on the forehead, just at the rise of
+his nose; the bones cracked and his two gore-bedrabbled eyes fell
+by his feet in the dust. He fell backwards to the ground, and
+Menelaus set his heel upon him, stripped him of his armour, and
+vaunted over him saying, "Even thus shall you Trojans leave the
+ships of the Achaeans, proud and insatiate of battle though you
+be, nor shall you lack any of the disgrace and shame which you
+have heaped upon myself. Cowardly she-wolves that you are, you
+feared not the anger of dread Jove, avenger of violated
+hospitality, who will one day destroy your city; you stole my
+wedded wife and wickedly carried off much treasure when you were
+her guest, and now you would fling fire upon our ships, and kill
+our heroes. A day will come when, rage as you may, you shall be
+stayed. O father Jove, you, who they say art above all, both gods
+and men, in wisdom, and from whom all things that befall us do
+proceed, how can you thus favour the Trojans--men so proud and
+overweening, that they are never tired of fighting? All things
+pall after a while--sleep, love, sweet song, and stately dance--
+still these are things of which a man would surely have his fill
+rather than of battle, whereas it is of battle that the Trojans
+are insatiate."
+</para>
+
+<para>
+So saying Menelaus stripped the blood-stained armour from the
+body of Pisander, and handed it over to his men; then he again
+ranged himself among those who were in the front of the fight.
+</para>
+
+<para>
+Harpalion son of King Pylaemenes then sprang upon him; he had
+come to fight at Troy along with his father, but he did not go
+home again. He struck the middle of Menelaus's shield with his
+spear but could not pierce it, and to save his life drew back
+under cover of his men, looking round him on every side lest he
+should be wounded. But Meriones aimed a bronze-tipped arrow at
+him as he was leaving the field, and hit him on the right
+buttock; the arrow pierced the bone through and through, and
+penetrated the bladder, so he sat down where he was and breathed
+his last in the arms of his comrades, stretched like a worm upon
+the ground and watering the earth with the blood that flowed from
+his wound. The brave Paphlagonians tended him with all due care;
+they raised him into his chariot, and bore him sadly off to the
+city of Troy; his father went also with him weeping bitterly, but
+there was no ransom that could bring his dead son to life again.
+</para>
+
+<para>
+Paris was deeply grieved by the death of Harpalion, who was his
+host when he went among the Paphlagonians; he aimed an arrow,
+therefore, in order to avenge him. Now there was a certain man
+named Euchenor, son of Polyidus the prophet, a brave man and
+wealthy, whose home was in Corinth. This Euchenor had set sail
+for Troy well knowing that it would be the death of him, for his
+good old father Polyidus had often told him that he must either
+stay at home and die of a terrible disease, or go with the
+Achaeans and perish at the hands of the Trojans; he chose,
+therefore, to avoid incurring the heavy fine the Achaeans would
+have laid upon him, and at the same time to escape the pain and
+suffering of disease. Paris now smote him on the jaw under his
+ear, whereon the life went out of him and he was enshrouded in
+the darkness of death.
+</para>
+
+<para>
+Thus then did they fight as it were a flaming fire. But Hector
+had not yet heard, and did not know that the Argives were making
+havoc of his men on the left wing of the battle, where the
+Achaeans ere long would have triumphed over them, so vigorously
+did Neptune cheer them on and help them. He therefore held on at
+the point where he had first forced his way through the gates and
+the wall, after breaking through the serried ranks of Danaan
+warriors. It was here that the ships of Ajax and Protesilaus were
+drawn up by the sea-shore; here the wall was at its lowest, and
+the fight both of man and horse raged most fiercely. The
+Boeotians and the Ionians with their long tunics, the Locrians,
+the men of Phthia, and the famous force of the Epeans could
+hardly stay Hector as he rushed on towards the ships, nor could
+they drive him from them, for he was as a wall of fire. The
+chosen men of the Athenians were in the van, led by Menestheus
+son of Peteos, with whom were also Pheidas, Stichius, and
+stalwart Bias; Meges son of Phyleus, Amphion, and Dracius
+commanded the Epeans, while Medon and staunch Podarces led the
+men of Phthia. Of these, Medon was bastard son to Oileus and
+brother of Ajax, but he lived in Phylace away from his own
+country, for he had killed the brother of his stepmother Eriopis,
+the wife of Oileus; the other, Podarces, was the son of Iphiclus,
+son of Phylacus. These two stood in the van of the Phthians, and
+defended the ships along with the Boeotians.
+</para>
+
+<para>
+Ajax son of Oileus, never for a moment left the side of Ajax, son
+of Telamon, but as two swart oxen both strain their utmost at the
+plough which they are drawing in a fallow field, and the sweat
+steams upwards from about the roots of their horns--nothing but
+the yoke divides them as they break up the ground till they reach
+the end of the field--even so did the two Ajaxes stand shoulder
+to shoulder by one another. Many and brave comrades followed the
+son of Telamon, to relieve him of his shield when he was overcome
+with sweat and toil, but the Locrians did not follow so close
+after the son of Oileus, for they could not hold their own in a
+hand-to-hand fight. They had no bronze helmets with plumes of
+horse-hair, neither had they shields nor ashen spears, but they
+had come to Troy armed with bows, and with slings of twisted wool
+from which they showered their missiles to break the ranks of the
+Trojans. The others, therefore, with their heavy armour bore the
+brunt of the fight with the Trojans and with Hector, while the
+Locrians shot from behind, under their cover; and thus the
+Trojans began to lose heart, for the arrows threw them into
+confusion.
+</para>
+
+<para>
+The Trojans would now have been driven in sorry plight from the
+ships and tents back to windy Ilius, had not Polydamas presently
+said to Hector, "Hector, there is no persuading you to take
+advice. Because heaven has so richly endowed you with the arts of
+war, you think that you must therefore excel others in counsel;
+but you cannot thus claim preeminence in all things. Heaven has
+made one man an excellent soldier; of another it has made a
+dancer or a singer and player on the lyre; while yet in another
+Jove has implanted a wise understanding of which men reap fruit
+to the saving of many, and he himself knows more about it than
+any one; therefore I will say what I think will be best. The
+fight has hemmed you in as with a circle of fire, and even now
+that the Trojans are within the wall some of them stand aloof in
+full armour, while others are fighting scattered and outnumbered
+near the ships. Draw back, therefore, and call your chieftains
+round you, that we may advise together whether to fall now upon
+the ships in the hope that heaven may vouchsafe us victory, or to
+beat a retreat while we can yet safely do so. I greatly fear that
+the Achaeans will pay us their debt of yesterday in full, for
+there is one abiding at their ships who is never weary of battle,
+and who will not hold aloof much longer."
+</para>
+
+<para>
+Thus spoke Polydamas, and his words pleased Hector well. He
+sprang in full armour from his chariot and said, "Polydamas,
+gather the chieftains here; I will go yonder into the fight, but
+will return at once when I have given them their orders."
+</para>
+
+<para>
+He then sped onward, towering like a snowy mountain, and with a
+loud cry flew through the ranks of the Trojans and their allies.
+When they heard his voice they all hastened to gather round
+Polydamas, the excellent son of Panthous, but Hector kept on
+among the foremost, looking everywhere to find Deiphobus and
+prince Helenus, Adamas son of Asius, and Asius son of Hyrtacus;
+living, indeed, and scatheless he could no longer find them, for
+the two last were lying by the sterns of the Achaean ships, slain
+by the Argives, while the others had been also stricken and
+wounded by them; but upon the left wing of the dread battle he
+found Alexandrus, husband of lovely Helen, cheering his men and
+urging them on to fight. He went up to him and upbraided him.
+"Paris," said he, "evil-hearted Paris, fair to see but woman-mad
+and false of tongue, where are Deiphobus and King Helenus? Where
+are Adamas son of Asius, and Asius son of Hyrtacus? Where too is
+Othryoneus? Ilius is undone and will now surely fall!"
+</para>
+
+<para>
+Alexandrus answered, "Hector, why find fault when there is no one
+to find fault with? I should hold aloof from battle on any day
+rather than this, for my mother bore me with nothing of the
+coward about me. From the moment when you set our men fighting
+about the ships we have been staying here and doing battle with
+the Danaans. Our comrades about whom you ask me are dead;
+Deiphobus and King Helenus alone have left the field, wounded
+both of them in the hand, but the son of Saturn saved them alive.
+Now, therefore, lead on where you would have us go, and we will
+follow with right goodwill; you shall not find us fail you in so
+far as our strength holds out, but no man can do more than in him
+lies, no matter how willing he may be."
+</para>
+
+<para>
+With these words he satisfied his brother, and the two went
+towards the part of the battle where the fight was thickest,
+about Cebriones, brave Polydamas, Phalces, Orthaeus, godlike
+Polyphetes, Palmys, Ascanius, and Morys son of Hippotion, who had
+come from fertile Ascania on the preceding day to relieve other
+troops. Then Jove urged them on to fight. They flew forth like
+the blasts of some fierce wind that strike earth in the van of a
+thunderstorm--they buffet the salt sea into an uproar; many and
+mighty are the great waves that come crashing in one after the
+other upon the shore with their arching heads all crested with
+foam--even so did rank behind rank of Trojans arrayed in gleaming
+armour follow their leaders onward. The way was led by Hector son
+of Priam, peer of murderous Mars, with his round shield before
+him--his shield of ox-hides covered with plates of bronze--and
+his gleaming helmet upon his temples. He kept stepping forward
+under cover of his shield in every direction, making trial of the
+ranks to see if they would give way before him, but he could not
+daunt the courage of the Achaeans. Ajax was the first to stride
+out and challenge him. "Sir," he cried, "draw near; why do you
+think thus vainly to dismay the Argives? We Achaeans are
+excellent soldiers, but the scourge of Jove has fallen heavily
+upon us. Your heart, forsooth, is set on destroying our ships,
+but we too have hands that can keep you at bay, and your own fair
+town shall be sooner taken and sacked by ourselves. The time is
+near when you shall pray Jove and all the gods in your flight,
+that your steeds may be swifter than hawks as they raise the dust
+on the plain and bear you back to your city."
+</para>
+
+<para>
+As he was thus speaking a bird flew by upon his right hand, and
+the host of the Achaeans shouted, for they took heart at the
+omen. But Hector answered, "Ajax, braggart and false of tongue,
+would that I were as sure of being son for evermore to
+aegis-bearing Jove, with Queen Juno for my mother, and of being
+held in like honour with Minerva and Apollo, as I am that this
+day is big with the destruction of the Achaeans; and you shall
+fall among them if you dare abide my spear; it shall rend your
+fair body and bid you glut our hounds and birds of prey with your
+fat and your flesh, as you fall by the ships of the Achaeans."
+</para>
+
+<para>
+With these words he led the way and the others followed after
+with a cry that rent the air, while the host shouted behind them.
+The Argives on their part raised a shout likewise, nor did they
+forget their prowess, but stood firm against the onslaught of the
+Trojan chieftains, and the cry from both the hosts rose up to
+heaven and to the brightness of Jove's presence.
+</para>
+</chapter>
+
+<chapter>
+<title>BOOK XIV</title>
+
+<para>
+NESTOR was sitting over his wine, but the cry of battle did not
+escape him, and he said to the son of Aesculapius, "What, noble
+Machaon, is the meaning of all this? The shouts of men fighting
+by our ships grow stronger and stronger; stay here, therefore,
+and sit over your wine, while fair Hecamede heats you a bath and
+washes the clotted blood from off you. I will go at once to the
+look-out station and see what it is all about."
+</para>
+
+<para>
+As he spoke he took up the shield of his son Thrasymedes that was
+lying in his tent, all gleaming with bronze, for Thrasymedes had
+taken his father's shield; he grasped his redoubtable bronze-shod
+spear, and as soon as he was outside saw the disastrous rout of
+the Achaeans who, now that their wall was overthrown, were flying
+pell-mell before the Trojans. As when there is a heavy swell upon
+the sea, but the waves are dumb--they keep their eyes on the
+watch for the quarter whence the fierce winds may spring upon
+them, but they stay where they are and set neither this way nor
+that, till some particular wind sweeps down from heaven to
+determine them--even so did the old man ponder whether to make
+for the crowd of Danaans, or go in search of Agamemnon. In the
+end he deemed it best to go to the son of Atreus; but meanwhile
+the hosts were fighting and killing one another, and the hard
+bronze rattled on their bodies, as they thrust at one another
+with their swords and spears.
+</para>
+
+<para>
+The wounded kings, the son of Tydeus, Ulysses, and Agamemnon son
+of Atreus, fell in Nestor as they were coming up from their
+ships--for theirs were drawn up some way from where the fighting
+was going on, being on the shore itself inasmuch as they had been
+beached first, while the wall had been built behind the
+hindermost. The stretch of the shore, wide though it was, did not
+afford room for all the ships, and the host was cramped for
+space, therefore they had placed the ships in rows one behind the
+other, and had filled the whole opening of the bay between the
+two points that formed it. The kings, leaning on their spears,
+were coming out to survey the fight, being in great anxiety, and
+when old Nestor met them they were filled with dismay. Then King
+Agamemnon said to him, "Nestor son of Neleus, honour to the
+Achaean name, why have you left the battle to come hither? I fear
+that what dread Hector said will come true, when he vaunted among
+the Trojans saying that he would not return to Ilius till he had
+fired our ships and killed us; this is what he said, and now it
+is all coming true. Alas! others of the Achaeans, like Achilles,
+are in anger with me that they refuse to fight by the sterns of
+our ships."
+</para>
+
+<para>
+Then Nestor knight of Gerene, answered, "It is indeed as you say;
+it is all coming true at this moment, and even Jove who thunders
+from on high cannot prevent it. Fallen is the wall on which we
+relied as an impregnable bulwark both for us and our fleet. The
+Trojans are fighting stubbornly and without ceasing at the ships;
+look where you may you cannot see from what quarter the rout of
+the Achaeans is coming; they are being killed in a confused mass
+and the battle-cry ascends to heaven; let us think, if counsel
+can be of any use, what we had better do; but I do not advise our
+going into battle ourselves, for a man cannot fight when he is
+wounded."
+</para>
+
+<para>
+And King Agamemnon answered, "Nestor, if the Trojans are indeed
+fighting at the rear of our ships, and neither the wall nor the
+trench has served us--over which the Danaans toiled so hard, and
+which they deemed would be an impregnable bulwark both for us and
+our fleet--I see it must be the will of Jove that the Achaeans
+should perish ingloriously here, far from Argos. I knew when Jove
+was willing to defend us, and I know now that he is raising the
+Trojans to like honour with the gods, while us, on the other
+hand, he bas bound hand and foot. Now, therefore, let us all do
+as I say; let us bring down the ships that are on the beach and
+draw them into the water; let us make them fast to their
+mooring-stones a little way out, against the fall of night--if
+even by night the Trojans will desist from fighting; we may then
+draw down the rest of the fleet. There is nothing wrong in flying
+ruin even by night. It is better for a man that he should fly and
+be saved than be caught and killed."
+</para>
+
+<para>
+Ulysses looked fiercely at him and said, "Son of Atreus, what are
+you talking about? Wretch, you should have commanded some other
+and baser army, and not been ruler over us to whom Jove has
+allotted a life of hard fighting from youth to old age, till we
+every one of us perish. Is it thus that you would quit the city
+of Troy, to win which we have suffered so much hardship? Hold
+your peace, lest some other of the Achaeans hear you say what no
+man who knows how to give good counsel, no king over so great a
+host as that of the Argives should ever have let fall from his
+lips. I despise your judgement utterly for what you have been
+saying. Would you, then, have us draw down our ships into the
+water while the battle is raging, and thus play further into the
+hands of the conquering Trojans? It would be ruin; the Achaeans
+will not go on fighting when they see the ships being drawn into
+the water, but will cease attacking and keep turning their eyes
+towards them; your counsel, therefore, sir captain, would be our
+destruction."
+</para>
+
+<para>
+Agamemnon answered, "Ulysses, your rebuke has stung me to the
+heart. I am not, however, ordering the Achaeans to draw their
+ships into the sea whether they will or no. Someone, it may be,
+old or young, can offer us better counsel which I shall rejoice
+to hear."
+</para>
+
+<para>
+Then said Diomed, "Such an one is at hand; he is not far to seek,
+if you will listen to me and not resent my speaking though I am
+younger than any of you. I am by lineage son to a noble sire,
+Tydeus, who lies buried at Thebes. For Portheus had three noble
+sons, two of whom, Agrius and Melas, abode in Pleuron and rocky
+Calydon. The third was the knight Oeneus, my father's father, and
+he was the most valiant of them all. Oeneus remained in his own
+country, but my father (as Jove and the other gods ordained it)
+migrated to Argos. He married into the family of Adrastus, and
+his house was one of great abundance, for he had large estates of
+rich corn-growing land, with much orchard ground as well, and he
+had many sheep; moreover he excelled all the Argives in the use
+of the spear. You must yourselves have heard whether these things
+are true or no; therefore when I say well despise not my words as
+though I were a coward or of ignoble birth. I say, then, let us
+go to the fight as we needs must, wounded though we be. When
+there, we may keep out of the battle and beyond the range of the
+spears lest we get fresh wounds in addition to what we have
+already, but we can spur on others, who have been indulging their
+spleen and holding aloof from battle hitherto."
+</para>
+
+<para>
+Thus did he speak; whereon they did even as he had said and set
+out, King Agamemnon leading the way.
+</para>
+
+<para>
+Meanwhile Neptune had kept no blind look-out, and came up to them
+in the semblance of an old man. He took Agamemnon's right hand in
+his own and said, "Son of Atreus, I take it Achilles is glad now
+that he sees the Achaeans routed and slain, for he is utterly
+without remorse--may he come to a bad end and heaven confound
+him. As for yourself, the blessed gods are not yet so bitterly
+angry with you but that the princes and counsellors of the
+Trojans shall again raise the dust upon the plain, and you shall
+see them flying from the ships and tents towards their city."
+</para>
+
+<para>
+With this he raised a mighty cry of battle, and sped forward to
+the plain. The voice that came from his deep chest was as that of
+nine or ten thousand men when they are shouting in the thick of a
+fight, and it put fresh courage into the hearts of the Achaeans
+to wage war and do battle without ceasing.
+</para>
+
+<para>
+Juno of the golden throne looked down as she stood upon a peak of
+Olympus and her heart was gladdened at the sight of him who was
+at once her brother and her brother-in-law, hurrying hither and
+thither amid the fighting. Then she turned her eyes to Jove as he
+sat on the topmost crests of many-fountained Ida, and loathed
+him. She set herself to think how she might hoodwink him, and in
+the end she deemed that it would be best for her to go to Ida and
+array herself in rich attire, in the hope that Jove might become
+enamoured of her, and wish to embrace her. While he was thus
+engaged a sweet and careless sleep might be made to steal over
+his eyes and senses.
+</para>
+
+<para>
+She went, therefore, to the room which her son Vulcan had made
+her, and the doors of which he had cunningly fastened by means of
+a secret key so that no other god could open them. Here she
+entered and closed the doors behind her. She cleansed all the
+dirt from her fair body with ambrosia, then she anointed herself
+with olive oil, ambrosial, very soft, and scented specially for
+herself--if it were so much as shaken in the bronze-floored house
+of Jove, the scent pervaded the universe of heaven and earth.
+With this she anointed her delicate skin, and then she plaited
+the fair ambrosial locks that flowed in a stream of golden
+tresses from her immortal head. She put on the wondrous robe
+which Minerva had worked for her with consummate art, and had
+embroidered with manifold devices; she fastened it about her
+bosom with golden clasps, and she girded herself with a girdle
+that had a hundred tassels: then she fastened her earrings, three
+brilliant pendants that glistened most beautifully, through the
+pierced lobes of her ears, and threw a lovely new veil over her
+head. She bound her sandals on to her feet, and when she had
+arrayed herself perfectly to her satisfaction, she left her room
+and called Venus to come aside and speak to her. "My dear child,"
+said she, "will you do what I am going to ask of you, or will
+refuse me because you are angry at my being on the Danaan side,
+while you are on the Trojan?"
+</para>
+
+<para>
+Jove's daughter Venus answered, "Juno, august queen of goddesses,
+daughter of mighty Saturn, say what you want, and I will do it
+for you at once, if I can, and if it can be done at all."
+</para>
+
+<para>
+Then Juno told her a lying tale and said, "I want you to endow me
+with some of those fascinating charms, the spells of which bring
+all things mortal and immortal to your feet. I am going to the
+world's end to visit Oceanus (from whom all we gods proceed) and
+mother Tethys: they received me in their house, took care of me,
+and brought me up, having taken me over from Rhaea when Jove
+imprisoned great Saturn in the depths that are under earth and
+sea. I must go and see them that I may make peace between them;
+they have been quarrelling, and are so angry that they have not
+slept with one another this long while; if I can bring them round
+and restore them to one another's embraces, they will be grateful
+to me and love me for ever afterwards."
+</para>
+
+<para>
+Thereon laughter-loving Venus said, "I cannot and must not refuse
+you, for you sleep in the arms of Jove who is our king."
+</para>
+
+<para>
+As she spoke she loosed from her bosom the curiously embroidered
+girdle into which all her charms had been wrought--love, desire,
+and that sweet flattery which steals the judgement even of the
+most prudent. She gave the girdle to Juno and said, "Take this
+girdle wherein all my charms reside and lay it in your bosom. If
+you will wear it I promise you that your errand, be it what it
+may, will not be bootless."
+</para>
+
+<para>
+When she heard this Juno smiled, and still smiling she laid the
+girdle in her bosom.
+</para>
+
+<para>
+Venus now went back into the house of Jove, while Juno darted
+down from the summits of Olympus. She passed over Pieria and fair
+Emathia, and went on and on till she came to the snowy ranges of
+the Thracian horsemen, over whose topmost crests she sped without
+ever setting foot to ground. When she came to Athos she went on
+over the, waves of the sea till she reached Lemnos, the city of
+noble Thoas. There she met Sleep, own brother to Death, and
+caught him by the hand, saying, "Sleep, you who lord it alike
+over mortals and immortals, if you ever did me a service in times
+past, do one for me now, and I shall be grateful to you ever
+after. Close Jove's keen eyes for me in slumber while I hold him
+clasped in my embrace, and I will give you a beautiful golden
+seat, that can never fall to pieces; my clubfooted son Vulcan
+shall make it for you, and he shall give it a footstool for you
+to rest your fair feet upon when you are at table."
+</para>
+
+<para>
+Then Sleep answered, "Juno, great queen of goddesses, daughter of
+mighty Saturn, I would lull any other of the gods to sleep
+without compunction, not even excepting the waters of Oceanus
+from whom all of them proceed, but I dare not go near Jove, nor
+send him to sleep unless he bids me. I have had one lesson
+already through doing what you asked me, on the day when Jove's
+mighty son Hercules set sail from Ilius after having sacked the
+city of the Trojans. At your bidding I suffused my sweet self
+over the mind of aegis-bearing Jove, and laid him to rest;
+meanwhile you hatched a plot against Hercules, and set the blasts
+of the angry winds beating upon the sea, till you took him to the
+goodly city of Cos, away from all his friends. Jove was furious
+when he awoke, and began hurling the gods about all over the
+house; he was looking more particularly for myself, and would
+have flung me down through space into the sea where I should
+never have been heard of any more, had not Night who cows both
+men and gods protected me. I fled to her and Jove left off
+looking for me in spite of his being so angry, for he did not
+dare do anything to displease Night. And now you are again asking
+me to do something on which I cannot venture."
+</para>
+
+<para>
+And Juno said, "Sleep, why do you take such notions as those into
+your head? Do you think Jove will be as anxious to help the
+Trojans, as he was about his own son? Come, I will marry you to
+one of the youngest of the Graces, and she shall be your own--
+Pasithea, whom you have always wanted to marry."
+</para>
+
+<para>
+Sleep was pleased when he heard this, and answered, "Then swear
+it to me by the dread waters of the river Styx; lay one hand on
+the bounteous earth, and the other on the sheen of the sea, so
+that all the gods who dwell down below with Saturn may be our
+witnesses, and see that you really do give me one of the youngest
+of the Graces--Pasithea, whom I have always wanted to marry."
+</para>
+
+<para>
+Juno did as he had said. She swore, and invoked all the gods of
+the nether world, who are called Titans, to witness. When she had
+completed her oath, the two enshrouded themselves in a thick mist
+and sped lightly forward, leaving Lemnos and Imbrus behind them.
+Presently they reached many-fountained Ida, mother of wild
+beasts, and Lectum where they left the sea to go on by land, and
+the tops of the trees of the forest soughed under the going of
+their feet. Here Sleep halted, and ere Jove caught sight of him
+he climbed a lofty pine-tree--the tallest that reared its head
+towards heaven on all Ida. He hid himself behind the branches and
+sat there in the semblance of the sweet-singing bird that haunts
+the mountains and is called Chalcis by the gods, but men call it
+Cymindis. Juno then went to Gargarus, the topmost peak of Ida,
+and Jove, driver of the clouds, set eyes upon her. As soon as he
+did so he became inflamed with the same passionate desire for her
+that he had felt when they had first enjoyed each other's
+embraces, and slept with one another without their dear parents
+knowing anything about it. He went up to her and said, "What do
+you want that you have come hither from Olympus--and that too
+with neither chariot nor horses to convey you?"
+</para>
+
+<para>
+Then Juno told him a lying tale and said, "I am going to the
+world's end, to visit Oceanus, from whom all we gods proceed, and
+mother Tethys; they received me into their house, took care of
+me, and brought me up. I must go and see them that I may make
+peace between them: they have been quarrelling, and are so angry
+that they have not slept with one another this long time. The
+horses that will take me over land and sea are stationed on the
+lowermost spurs of many-fountained Ida, and I have come here from
+Olympus on purpose to consult you. I was afraid you might be
+angry with me later on, if I went to the house of Oceanus without
+letting you know."
+</para>
+
+<para>
+And Jove said, "Juno, you can choose some other time for paying
+your visit to Oceanus--for the present let us devote ourselves to
+love and to the enjoyment of one another. Never yet have I been
+so overpowered by passion neither for goddess nor mortal woman as
+I am at this moment for yourself--not even when I was in love
+with the wife of Ixion who bore me Pirithous, peer of gods in
+counsel, nor yet with Danae the daintily-ancled daughter of
+Acrisius, who bore me the famed hero Perseus. Then there was the
+daughter of Phoenix, who bore me Minos and Rhadamanthus: there
+was Semele, and Alcmena in Thebes by whom I begot my lion-hearted
+son Hercules, while Semele became mother to Bacchus the comforter
+of mankind. There was queen Ceres again, and lovely Leto, and
+yourself--but with none of these was I ever so much enamoured as
+I now am with you."
+</para>
+
+<para>
+Juno again answered him with a lying tale. "Most dread son of
+Saturn," she exclaimed, "what are you talking about? Would you
+have us enjoy one another here on the top of Mount Ida, where
+everything can be seen? What if one of the ever-living gods
+should see us sleeping together, and tell the others? It would be
+such a scandal that when I had risen from your embraces I could
+never show myself inside your house again; but if you are so
+minded, there is a room which your son Vulcan has made me, and he
+has given it good strong doors; if you would so have it, let us
+go thither and lie down."
+</para>
+
+<para>
+And Jove answered, "Juno, you need not be afraid that either god
+or man will see you, for I will enshroud both of us in such a
+dense golden cloud, that the very sun for all his bright piercing
+beams shall not see through it."
+</para>
+
+<para>
+With this the son of Saturn caught his wife in his embrace;
+whereon the earth sprouted them a cushion of young grass, with
+dew-bespangled lotus, crocus, and hyacinth, so soft and thick
+that it raised them well above the ground. Here they laid
+themselves down and overhead they were covered by a fair cloud of
+gold, from which there fell glittering dew-drops.
+</para>
+
+<para>
+Thus, then, did the sire of all things repose peacefully on the
+crest of Ida, overcome at once by sleep and love, and he held his
+spouse in his arms. Meanwhile Sleep made off to the ships of the
+Achaeans, to tell earth-encircling Neptune, lord of the
+earthquake. When he had found him he said, "Now, Neptune, you can
+help the Danaans with a will, and give them victory though it be
+only for a short time while Jove is still sleeping. I have sent
+him into a sweet slumber, and Juno has beguiled him into going to
+bed with her."
+</para>
+
+<para>
+Sleep now departed and went his ways to and fro among mankind,
+leaving Neptune more eager than ever to help the Danaans. He
+darted forward among the first ranks and shouted saying,
+"Argives, shall we let Hector son of Priam have the triumph of
+taking our ships and covering himself with glory? This is what he
+says that he shall now do, seeing that Achilles is still in
+dudgeon at his ship; we shall get on very well without him if we
+keep each other in heart and stand by one another. Now,
+therefore, let us all do as I say. Let us each take the best and
+largest shield we can lay hold of, put on our helmets, and sally
+forth with our longest spears in our hands; I will lead you on,
+and Hector son of Priam, rage as he may, will not dare to hold
+out against us. If any good staunch soldier has only a small
+shield, let him hand it over to a worse man, and take a larger
+one for himself."
+</para>
+
+<para>
+Thus did he speak, and they did even as he had said. The son of
+Tydeus, Ulysses, and Agamemnon, wounded though they were, set the
+others in array, and went about everywhere effecting the
+exchanges of armour; the most valiant took the best armour, and
+gave the worse to the worse man. When they had donned their
+bronze armour they marched on with Neptune at their head. In his
+strong hand he grasped his terrible sword, keen of edge and
+flashing like lightning; woe to him who comes across it in the
+day of battle; all men quake for fear and keep away from it.
+</para>
+
+<para>
+Hector on the other side set the Trojans in array. Thereon
+Neptune and Hector waged fierce war on one another--Hector on the
+Trojan and Neptune on the Argive side. Mighty was the uproar as
+the two forces met; the sea came rolling in towards the ships and
+tents of the Achaeans, but waves do not thunder on the shore more
+loudly when driven before the blast of Boreas, nor do the flames
+of a forest fire roar more fiercely when it is well alight upon
+the mountains, nor does the wind bellow with ruder music as it
+tears on through the tops of when it is blowing its hardest, than
+the terrible shout which the Trojans and Achaeans raised as they
+sprang upon one another.
+</para>
+
+<para>
+Hector first aimed his spear at Ajax, who was turned full towards
+him, nor did he miss his aim. The spear struck him where two
+bands passed over his chest--the band of his shield and that of
+his silver-studded sword--and these protected his body. Hector
+was angry that his spear should have been hurled in vain, and
+withdrew under cover of his men. As he was thus retreating, Ajax
+son of Telamon, struck him with a stone, of which there were many
+lying about under the men's feet as they fought--brought there to
+give support to the ships' sides as they lay on the shore. Ajax
+caught up one of them and struck Hector above the rim of his
+shield close to his neck; the blow made him spin round like a top
+and reel in all directions. As an oak falls headlong when
+uprooted by the lightning flash of father Jove, and there is a
+terrible smell of brimstone--no man can help being dismayed if he
+is standing near it, for a thunderbolt is a very awful thing--
+even so did Hector fall to earth and bite the dust. His spear
+fell from his hand, but his shield and helmet were made fast
+about his body, and his bronze armour rang about him.
+</para>
+
+<para>
+The sons of the Achaeans came running with a loud cry towards
+him, hoping to drag him away, and they showered their darts on
+the Trojans, but none of them could wound him before he was
+surrounded and covered by the princes Polydamas, Aeneas, Agenor,
+Sarpedon captain of the Lycians, and noble Glaucus. Of the
+others, too, there was not one who was unmindful of him, and they
+held their round shields over him to cover him. His comrades then
+lifted him off the ground and bore him away from the battle to
+the place where his horses stood waiting for him at the rear of
+the fight with their driver and the chariot; these then took him
+towards the city groaning and in great pain. When they reached
+the ford of the fair stream of Xanthus, begotten of Immortal
+Jove, they took him from off his chariot and laid him down on the
+ground; they poured water over him, and as they did so he
+breathed again and opened his eyes. Then kneeling on his knees he
+vomited blood, but soon fell back on to the ground, and his eyes
+were again closed in darkness for he was still stunned by the
+blow.
+</para>
+
+<para>
+When the Argives saw Hector leaving the field, they took heart
+and set upon the Trojans yet more furiously. Ajax fleet son of
+Oileus began by springing on Satnius son of Enops, and wounding
+him with his spear: a fair naiad nymph had borne him to Enops as
+he was herding cattle by the banks of the river Satnioeis. The
+son of Oileus came up to him and struck him in the flank so that
+he fell, and a fierce fight between Trojans and Danaans raged
+round his body. Polydamas son of Panthous drew near to avenge
+him, and wounded Prothoenor son of Areilycus on the right
+shoulder; the terrible spear went right through his shoulder, and
+he clutched the earth as he fell in the dust. Polydamas vaunted
+loudly over him saying, "Again I take it that the spear has not
+sped in vain from the strong hand of the son of Panthous; an
+Argive has caught it in his body, and it will serve him for a
+staff as he goes down into the house of Hades."
+</para>
+
+<para>
+The Argives were maddened by this boasting. Ajax son of Telamon
+was more angry than any, for the man had fallen close beside him;
+so he aimed at Polydamas as he was retreating, but Polydamas
+saved himself by swerving aside and the spear struck Archelochus
+son of Antenor, for heaven counselled his destruction; it struck
+him where the head springs from the neck at the top joint of the
+spine, and severed both the tendons at the back of the head. His
+head, mouth, and nostrils reached the ground long before his legs
+and knees could do so, and Ajax shouted to Polydamas saying,
+"Think, Polydamas, and tell me truly whether this man is not as
+well worth killing as Prothoenor was: he seems rich, and of rich
+family, a brother, it may be, or son of the knight Antenor, for
+he is very like him."
+</para>
+
+<para>
+But he knew well who it was, and the Trojans were greatly
+angered. Acamas then bestrode his brother's body and wounded
+Promachus the Boeotian with his spear, for he was trying to drag
+his brother's body away. Acamas vaunted loudly over him saying,
+"Argive archers, braggarts that you are, toil and suffering shall
+not be for us only, but some of you too shall fall here as well
+as ourselves. See how Promachus now sleeps, vanquished by my
+spear; payment for my brother's blood has not been long delayed;
+a man, therefore, may well be thankful if he leaves a kinsman in
+his house behind him to avenge his fall."
+</para>
+
+<para>
+His taunts infuriated the Argives, and Peneleos was more enraged
+than any of them. He sprang towards Acamas, but Acamas did not
+stand his ground, and he killed Ilioneus son of the rich
+flock-master Phorbas, whom Mercury had favoured and endowed with
+greater wealth than any other of the Trojans. Ilioneus was his
+only son, and Peneleos now wounded him in the eye under his
+eyebrows, tearing the eye-ball from its socket: the spear went
+right through the eye into the nape of the neck, and he fell,
+stretching out both hands before him. Peneleos then drew his
+sword and smote him on the neck, so that both head and helmet
+came tumbling down to the ground with the spear still sticking in
+the eye; he then held up the head, as though it had been a
+poppy-head, and showed it to the Trojans, vaunting over them as
+he did so. "Trojans," he cried, "bid the father and mother of
+noble Ilioneus make moan for him in their house, for the wife
+also of Promachus son of Alegenor will never be gladdened by the
+coming of her dear husband--when we Argives return with our ships
+from Troy."
+</para>
+
+<para>
+As he spoke fear fell upon them, and every man looked round about
+to see whither he might fly for safety.
+</para>
+
+<para>
+Tell me now, O Muses that dwell on Olympus, who was the first of
+the Argives to bear away blood-stained spoils after Neptune lord
+of the earthquake had turned the fortune of war. Ajax son of
+Telamon was first to wound Hyrtius son of Gyrtius, captain of the
+staunch Mysians. Antilochus killed Phalces and Mermerus, while
+Meriones slew Morys and Hippotion, Teucer also killed Prothoon
+and Periphetes. The son of Atreus then wounded Hyperenor shepherd
+of his people, in the flank, and the bronze point made his
+entrails gush out as it tore in among them; on this his life came
+hurrying out of him at the place where he had been wounded, and
+his eyes were closed in darkness. Ajax son of Oileus killed more
+than any other, for there was no man so fleet as he to pursue
+flying foes when Jove had spread panic among them.
+</para>
+</chapter>
+
+<chapter>
+<title>BOOK XV</title>
+
+<para>
+BUT when their flight had taken them past the trench and the set
+stakes, and many had fallen by the hands of the Danaans, the
+Trojans made a halt on reaching their chariots, routed and pale
+with fear. Jove now woke on the crests of Ida, where he was lying
+with golden-throned Juno by his side, and starting to his feet he
+saw the Trojans and Achaeans, the one thrown into confusion, and
+the others driving them pell-mell before them with King Neptune
+in their midst. He saw Hector lying on the ground with his
+comrades gathered round him, gasping for breath, wandering in
+mind and vomiting blood, for it was not the feeblest of the
+Achaeans who struck him.
+</para>
+
+<para>
+The sire of gods and men had pity on him, and looked fiercely on
+Juno. "I see, Juno," said he, "you mischief-making trickster,
+that your cunning has stayed Hector from fighting and has caused
+the rout of his host. I am in half a mind to thrash you, in which
+case you will be the first to reap the fruits of your scurvy
+knavery. Do you not remember how once upon a time I had you
+hanged? I fastened two anvils on to your feet, and bound your
+hands in a chain of gold which none might break, and you hung in
+mid-air among the clouds. All the gods in Olympus were in a fury,
+but they could not reach you to set you free; when I caught any
+one of them I gripped him and hurled him from the heavenly
+threshold till he came fainting down to earth; yet even this did
+not relieve my mind from the incessant anxiety which I felt about
+noble Hercules whom you and Boreas had spitefully conveyed beyond
+the seas to Cos, after suborning the tempests; but I rescued him,
+and notwithstanding all his mighty labours I brought him back
+again to Argos. I would remind you of this that you may learn to
+leave off being so deceitful, and discover how much you are
+likely to gain by the embraces out of which you have come here to
+trick me."
+</para>
+
+<para>
+Juno trembled as he spoke, and said, "May heaven above and earth
+below be my witnesses, with the waters of the river Styx--and
+this is the most solemn oath that a blessed god can take--nay, I
+swear also by your own almighty head and by our bridal bed--
+things over which I could never possibly perjure myself--that
+Neptune is not punishing Hector and the Trojans and helping the
+Achaeans through any doing of mine; it is all of his own mere
+motion because he was sorry to see the Achaeans hard pressed at
+their ships: if I were advising him, I should tell him to do as
+you bid him."
+</para>
+
+<para>
+The sire of gods and men smiled and answered, "If you, Juno, were
+always to support me when we sit in council of the gods, Neptune,
+like it or no, would soon come round to your and my way of
+thinking. If, then, you are speaking the truth and mean what you
+say, go among the rank and file of the gods, and tell Iris and
+Apollo lord of the bow, that I want them--Iris, that she may go
+to the Achaean host and tell Neptune to leave off fighting and go
+home, and Apollo, that he may send Hector again into battle and
+give him fresh strength; he will thus forget his present
+sufferings, and drive the Achaeans back in confusion till they
+fall among the ships of Achilles son of Peleus. Achilles will
+then send his comrade Patroclus into battle, and Hector will kill
+him in front of Ilius after he has slain many warriors, and among
+them my own noble son Sarpedon. Achilles will kill Hector to
+avenge Patroclus, and from that time I will bring it about that
+the Achaeans shall persistently drive the Trojans back till they
+fulfil the counsels of Minerva and take Ilius. But I will not
+stay my anger, nor permit any god to help the Danaans till I have
+accomplished the desire of the son of Peleus, according to the
+promise I made by bowing my head on the day when Thetis touched
+my knees and besought me to give him honour."
+</para>
+
+<para>
+Juno heeded his words and went from the heights of Ida to great
+Olympus. Swift as the thought of one whose fancy carries him over
+vast continents, and he says to himself, "Now I will be here, or
+there," and he would have all manner of things--even so swiftly
+did Juno wing her way till she came to high Olympus and went in
+among the gods who were gathered in the house of Jove. When they
+saw her they all of them came up to her, and held out their cups
+to her by way of greeting. She let the others be, but took the
+cup offered her by lovely Themis, who was first to come running
+up to her. "Juno," said she, "why are you here? And you seem
+troubled--has your husband the son of Saturn been frightening
+you?"
+</para>
+
+<para>
+And Juno answered, "Themis, do not ask me about it. You know what
+a proud and cruel disposition my husband has. Lead the gods to
+table, where you and all the immortals can hear the wicked
+designs which he has avowed. Many a one, mortal and immortal,
+will be angered by them, however peaceably he may be feasting
+now."
+</para>
+
+<para>
+On this Juno sat down, and the gods were troubled throughout the
+house of Jove. Laughter sat on her lips but her brow was furrowed
+with care, and she spoke up in a rage. "Fools that we are," she
+cried, "to be thus madly angry with Jove; we keep on wanting to
+go up to him and stay him by force or by persuasion, but he sits
+aloof and cares for nobody, for he knows that he is much stronger
+than any other of the immortals. Make the best, therefore, of
+whatever ills he may choose to send each one of you; Mars, I take
+it, has had a taste of them already, for his son Ascalaphus has
+fallen in battle--the man whom of all others he loved most dearly
+and whose father he owns himself to be."
+</para>
+
+<para>
+When he heard this Mars smote his two sturdy thighs with the flat
+of his hands, and said in anger, "Do not blame me, you gods that
+dwell in heaven, if I go to the ships of the Achaeans and avenge
+the death of my son, even though it end in my being struck by
+Jove's lightning and lying in blood and dust among the corpses."
+</para>
+
+<para>
+As he spoke he gave orders to yoke his horses Panic and Rout,
+while he put on his armour. On this, Jove would have been roused
+to still more fierce and implacable enmity against the other
+immortals, had not Minerva, alarmed for the safety of the gods,
+sprung from her seat and hurried outside. She tore the helmet
+from his head and the shield from his shoulders, and she took the
+bronze spear from his strong hand and set it on one side; then
+she said to Mars, "Madman, you are undone; you have ears that
+hear not, or you have lost all judgement and understanding; have
+you not heard what Juno has said on coming straight from the
+presence of Olympian Jove? Do you wish to go through all kinds of
+suffering before you are brought back sick and sorry to Olympus,
+after having caused infinite mischief to all us others? Jove
+would instantly leave the Trojans and Achaeans to themselves; he
+would come to Olympus to punish us, and would grip us up one
+after another, guilty or not guilty. Therefore lay aside your
+anger for the death of your son; better men than he have either
+been killed already or will fall hereafter, and one cannot
+protect every one's whole family."
+</para>
+
+<para>
+With these words she took Mars back to his seat. Meanwhile Juno
+called Apollo outside, with Iris the messenger of the gods.
+"Jove," she said to them, "desires you to go to him at once on
+Mt. Ida; when you have seen him you are to do as he may then bid
+you."
+</para>
+
+<para>
+Thereon Juno left them and resumed her seat inside, while Iris
+and Apollo made all haste on their way. When they reached
+many-fountained Ida, mother of wild beasts, they found Jove
+seated on topmost Gargarus with a fragrant cloud encircling his
+head as with a diadem. They stood before his presence, and he was
+pleased with them for having been so quick in obeying the orders
+his wife had given them.
+</para>
+
+<para>
+He spoke to Iris first. "Go," said he, "fleet Iris, tell King
+Neptune what I now bid you--and tell him true. Bid him leave off
+fighting, and either join the company of the gods, or go down
+into the sea. If he takes no heed and disobeys me, let him
+consider well whether he is strong enough to hold his own against
+me if I attack him. I am older and much stronger than he is; yet
+he is not afraid to set himself up as on a level with myself, of
+whom all the other gods stand in awe."
+</para>
+
+<para>
+Iris, fleet as the wind, obeyed him, and as the cold hail or
+snowflakes that fly from out the clouds before the blast of
+Boreas, even so did she wing her way till she came close up to
+the great shaker of the earth. Then she said, "I have come, O
+dark-haired king that holds the world in his embrace, to bring
+you a message from Jove. He bids you leave off fighting, and
+either join the company of the gods or go down into the sea; if,
+however, you take no heed and disobey him, he says he will come
+down here and fight you. He would have you keep out of his reach,
+for he is older and much stronger than you are, and yet you are
+not afraid to set yourself up as on a level with himself, of whom
+all the other gods stand in awe."
+</para>
+
+<para>
+Neptune was very angry and said, "Great heavens! strong as Jove
+may be, he has said more than he can do if he has threatened
+violence against me, who am of like honour with himself. We were
+three brothers whom Rhea bore to Saturn--Jove, myself, and Hades
+who rules the world below. Heaven and earth were divided into
+three parts, and each of us was to have an equal share. When we
+cast lots, it fell to me to have my dwelling in the sea for
+evermore; Hades took the darkness of the realms under the earth,
+while air and sky and clouds were the portion that fell to Jove;
+but earth and great Olympus are the common property of all.
+Therefore I will not walk as Jove would have me. For all his
+strength, let him keep to his own third share and be contented
+without threatening to lay hands upon me as though I were nobody.
+Let him keep his bragging talk for his own sons and daughters,
+who must perforce obey him."
+</para>
+
+<para>
+Iris fleet as the wind then answered, "Am I really, Neptune, to
+take this daring and unyielding message to Jove, or will you
+reconsider your answer? Sensible people are open to argument, and
+you know that the Erinyes always range themselves on the side of
+the older person."
+</para>
+
+<para>
+Neptune answered, "Goddess Iris, your words have been spoken in
+season. It is well when a messenger shows so much discretion.
+Nevertheless it cuts me to the very heart that any one should
+rebuke so angrily another who is his own peer, and of like empire
+with himself. Now, however, I will give way in spite of my
+displeasure; furthermore let me tell you, and I mean what I say--
+if contrary to the desire of myself, Minerva driver of the spoil,
+Juno, Mercury, and King Vulcan, Jove spares steep Ilius, and will
+not let the Achaeans have the great triumph of sacking it, let
+him understand that he will incur our implacable resentment."
+</para>
+
+<para>
+Neptune now left the field to go down under the sea, and sorely
+did the Achaeans miss him. Then Jove said to Apollo, "Go, dear
+Phoebus, to Hector, for Neptune who holds the earth in his
+embrace has now gone down under the sea to avoid the severity of
+my displeasure. Had he not done so those gods who are below with
+Saturn would have come to hear of the fight between us. It is
+better for both of us that he should have curbed his anger and
+kept out of my reach, for I should have had much trouble with
+him. Take, then, your tasselled aegis, and shake it furiously, so
+as to set the Achaean heroes in a panic; take, moreover, brave
+Hector, O Far-Darter, into your own care, and rouse him to deeds
+of daring, till the Achaeans are sent flying back to their ships
+and to the Hellespont. From that point I will think it well over,
+how the Achaeans may have a respite from their troubles."
+</para>
+
+<para>
+Apollo obeyed his father's saying, and left the crests of Ida,
+flying like a falcon, bane of doves and swiftest of all birds. He
+found Hector no longer lying upon the ground, but sitting up, for
+he had just come to himself again. He knew those who were about
+him, and the sweat and hard breathing had left him from the
+moment when the will of aegis-bearing Jove had revived him.
+Apollo stood beside him and said, "Hector son of Priam, why are
+you so faint, and why are you here away from the others? Has any
+mishap befallen you?"
+</para>
+
+<para>
+Hector in a weak voice answered, "And which, kind sir, of the
+gods are you, who now ask me thus? Do you not know that Ajax
+struck me on the chest with a stone as I was killing his comrades
+at the ships of the Achaeans, and compelled me to leave off
+fighting? I made sure that this very day I should breathe my last
+and go down into the house of Hades."
+</para>
+
+<para>
+Then King Apollo said to him, "Take heart; the son of Saturn has
+sent you a mighty helper from Ida to stand by you and defend you,
+even me, Phoebus Apollo of the golden sword, who have been
+guardian hitherto not only of yourself but of your city. Now,
+therefore, order your horsemen to drive their chariots to the
+ships in great multitudes. I will go before your horses to smooth
+the way for them, and will turn the Achaeans in flight."
+</para>
+
+<para>
+As he spoke he infused great strength into the shepherd of his
+people. And as a horse, stabled and full-fed, breaks loose and
+gallops gloriously over the plain to the place where he is wont
+to take his bath in the river--he tosses his head, and his mane
+streams over his shoulders as in all the pride of his strength he
+flies full speed to the pastures where the mares are feeding--
+even so Hector, when he heard what the god said, urged his
+horsemen on, and sped forward as fast as his limbs could take
+him. As country peasants set their hounds on to a homed stag or
+wild goat--he has taken shelter under rock or thicket, and they
+cannot find him, but, lo, a bearded lion whom their shouts have
+roused stands in their path, and they are in no further humour
+for the chase--even so the Achaeans were still charging on in a
+body, using their swords and spears pointed at both ends, but
+when they saw Hector going about among his men they were afraid,
+and their hearts fell down into their feet.
+</para>
+
+<para>
+Then spoke Thoas son of Andraemon, leader of the Aetolians, a man
+who could throw a good throw, and who was staunch also in close
+fight, while few could surpass him in debate when opinions were
+divided. He then with all sincerity and goodwill addressed them
+thus: "What, in heaven's name, do I now see? Is it not Hector
+come to life again? Every one made sure he had been killed by
+Ajax son of Telamon, but it seems that one of the gods has again
+rescued him. He has killed many of us Danaans already, and I take
+it will yet do so, for the hand of Jove must be with him or he
+would never dare show himself so masterful in the forefront of
+the battle. Now, therefore, let us all do as I say; let us order
+the main body of our forces to fall back upon the ships, but let
+those of us who profess to be the flower of the army stand firm,
+and see whether we cannot hold Hector back at the point of our
+spears as soon as he comes near us; I conceive that he will then
+think better of it before he tries to charge into the press of
+the Danaans."
+</para>
+
+<para>
+Thus did he speak, and they did even as he had said. Those who
+were about Ajax and King Idomeneus, the followers moreover of
+Teucer, Meriones, and Meges peer of Mars called all their best
+men about them and sustained the fight against Hector and the
+Trojans, but the main body fell back upon the ships of the
+Achaeans.
+</para>
+
+<para>
+The Trojans pressed forward in a dense body, with Hector striding
+on at their head. Before him went Phoebus Apollo shrouded in
+cloud about his shoulders. He bore aloft the terrible aegis with
+its shaggy fringe, which Vulcan the smith had given Jove to
+strike terror into the hearts of men. With this in his hand he
+led on the Trojans.
+</para>
+
+<para>
+The Argives held together and stood their ground. The cry of
+battle rose high from either side, and the arrows flew from the
+bowstrings. Many a spear sped from strong hands and fastened in
+the bodies of many a valiant warrior, while others fell to earth
+midway, before they could taste of man's fair flesh and glut
+themselves with blood. So long as Phoebus Apollo held his aegis
+quietly and without shaking it, the weapons on either side took
+effect and the people fell, but when he shook it straight in the
+face of the Danaans and raised his mighty battle-cry their hearts
+fainted within them and they forgot their former prowess. As when
+two wild beasts spring in the dead of night on a herd of cattle
+or a large flock of sheep when the herdsman is not there--even so
+were the Danaans struck helpless, for Apollo filled them with
+panic and gave victory to Hector and the Trojans.
+</para>
+
+<para>
+The fight then became more scattered and they killed one another
+where they best could. Hector killed Stichius and Arcesilaus, the
+one, leader of the Boeotians, and the other, friend and comrade
+of Menestheus. Aeneas killed Medon and Iasus. The first was
+bastard son to Oileus, and brother to Ajax, but he lived in
+Phylace away from his own country, for he had killed a man, a
+kinsman of his stepmother Eriopis whom Oileus had married. Iasus
+had become a leader of the Athenians, and was son of Sphelus the
+son of Boucolos. Polydamas killed Mecisteus, and Polites Echius,
+in the front of the battle, while Agenor slew Clonius. Paris
+struck Deiochus from behind in the lower part of the shoulder, as
+he was flying among the foremost, and the point of the spear went
+clean through him.
+</para>
+
+<para>
+While they were spoiling these heroes of their armour, the
+Achaeans were flying pell-mell to the trench and the set stakes,
+and were forced back within their wall. Hector then cried out to
+the Trojans, "Forward to the ships, and let the spoils be. If I
+see any man keeping back on the other side the wall away from the
+ships I will have him killed: his kinsmen and kinswomen shall not
+give him his dues of fire, but dogs shall tear him in pieces in
+front of our city."
+</para>
+
+<para>
+As he spoke he laid his whip about his horses' shoulders and
+called to the Trojans throughout their ranks; the Trojans shouted
+with a cry that rent the air, and kept their horses neck and neck
+with his own. Phoebus Apollo went before, and kicked down the
+banks of the deep trench into its middle so as to make a great
+broad bridge, as broad as the throw of a spear when a man is
+trying his strength. The Trojan battalions poured over the
+bridge, and Apollo with his redoubtable aegis led the way. He
+kicked down the wall of the Achaeans as easily as a child who
+playing on the sea-shore has built a house of sand and then kicks
+it down again and destroys it--even so did you, O Apollo, shed
+toil and trouble upon the Argives, filling them with panic and
+confusion.
+</para>
+
+<para>
+Thus then were the Achaeans hemmed in at their ships, calling out
+to one another and raising their hands with loud cries every man
+to heaven. Nestor of Gerene, tower of strength to the Achaeans,
+lifted up his hands to the starry firmament of heaven, and prayed
+more fervently than any of them. "Father Jove," said he, "if ever
+any one in wheat-growing Argos burned you fat thigh-bones of
+sheep or heifer and prayed that he might return safely home,
+whereon you bowed your head to him in assent, bear it in mind
+now, and suffer not the Trojans to triumph thus over the
+Achaeans."
+</para>
+
+<para>
+All-counselling Jove thundered loudly in answer to the prayer of
+the aged son of Neleus. When they heard Jove thunder they flung
+themselves yet more fiercely on the Achaeans. As a wave breaking
+over the bulwarks of a ship when the sea runs high before a
+gale--for it is the force of the wind that makes the waves so
+great--even so did the Trojans spring over the wall with a
+shout, and drive their chariots onwards. The two sides fought
+with their double-pointed spears in hand-to-hand encounter-the
+Trojans from their chariots, and the Achaeans climbing up into
+their ships and wielding the long pikes that were lying on the
+decks ready for use in a sea-fight, jointed and shod with bronze.
+</para>
+
+<para>
+Now Patroclus, so long as the Achaeans and Trojans were fighting
+about the wall, but were not yet within it and at the ships,
+remained sitting in the tent of good Eurypylus, entertaining him
+with his conversation and spreading herbs over his wound to ease
+his pain. When, however, he saw the Trojans swarming through the
+breach in the wall, while the Achaeans were clamouring and struck
+with panic, he cried aloud, and smote his two thighs with the
+flat of his hands. "Eurypylus," said he in his dismay, "I know
+you want me badly, but I cannot stay with you any longer, for
+there is hard fighting going on; a servant shall take care of you
+now, for I must make all speed to Achilles, and induce him to
+fight if I can; who knows but with heaven's help I may persuade
+him. A man does well to listen to the advice of a friend."
+</para>
+
+<para>
+When he had thus spoken he went his way. The Achaeans stood firm
+and resisted the attack of the Trojans, yet though these were
+fewer in number, they could not drive them back from the ships,
+neither could the Trojans break the Achaean ranks and make their
+way in among the tents and ships. As a carpenter's line gives a
+true edge to a piece of ship's timber, in the hand of some
+skilled workman whom Minerva has instructed in all kinds of
+useful arts--even so level was the issue of the fight between the
+two sides, as they fought some round one and some round another.
+</para>
+
+<para>
+Hector made straight for Ajax, and the two fought fiercely about
+the same ship. Hector could not force Ajax back and fire the
+ship, nor yet could Ajax drive Hector from the spot to which
+heaven had brought him.
+</para>
+
+<para>
+Then Ajax struck Caletor son of Clytius in the chest with a spear
+as he was bringing fire towards the ship. He fell heavily to the
+ground and the torch dropped from his hand. When Hector saw his
+cousin fallen in front of the ship he shouted to the Trojans and
+Lycians saying, "Trojans, Lycians, and Dardanians good in close
+fight, bate not a jot, but rescue the son of Clytius lest the
+Achaeans strip him of his armour now that he has fallen."
+</para>
+
+<para>
+He then aimed a spear at Ajax, and missed him, but he hit
+Lycophron a follower of Ajax, who came from Cythera, but was
+living with Ajax inasmuch as he had killed a man among the
+Cythereans. Hector's spear struck him on the head below the ear,
+and he fell headlong from the ship's prow on to the ground with
+no life left in him. Ajax shook with rage and said to his
+brother, "Teucer, my good fellow, our trusty comrade the son of
+Mastor has fallen, he came to live with us from Cythera and whom
+we honoured as much as our own parents. Hector has just killed
+him; fetch your deadly arrows at once and the bow which Phoebus
+Apollo gave you."
+</para>
+
+<para>
+Teucer heard him and hastened towards him with his bow and quiver
+in his hands. Forthwith he showered his arrows on the Trojans,
+and hit Cleitus the son of Pisenor, comrade of Polydamas the
+noble son of Panthous, with the reins in his hands as he was
+attending to his horses; he was in the middle of the very
+thickest part of the fight, doing good service to Hector and the
+Trojans, but evil had now come upon him, and not one of those who
+were fain to do so could avert it, for the arrow struck him on
+the back of the neck. He fell from his chariot and his horses
+shook the empty car as they swerved aside. King Polydamas saw
+what had happened, and was the first to come up to the horses; he
+gave them in charge to Astynous son of Protiaon, and ordered him
+to look on, and to keep the horses near at hand. He then went
+back and took his place in the front ranks.
+</para>
+
+<para>
+Teucer then aimed another arrow at Hector, and there would have
+been no more fighting at the ships if he had hit him and killed
+him then and there: Jove, however, who kept watch over Hector,
+had his eyes on Teucer, and deprived him of his triumph, by
+breaking his bowstring for him just as he was drawing it and
+about to take his aim; on this the arrow went astray and the bow
+fell from his hands. Teucer shook with anger and said to his
+brother, "Alas, see how heaven thwarts us in all we do; it has
+broken my bowstring and snatched the bow from my hand, though I
+strung it this selfsame morning that it might serve me for many
+an arrow."
+</para>
+
+<para>
+Ajax son of Telamon answered, "My good fellow, let your bow and
+your arrows be, for Jove has made them useless in order to spite
+the Danaans. Take your spear, lay your shield upon your shoulder,
+and both fight the Trojans yourself and urge others to do so.
+They may be successful for the moment but if we fight as we ought
+they will find it a hard matter to take the ships."
+</para>
+
+<para>
+Teucer then took his bow and put it by in his tent. He hung a
+shield four hides thick about his shoulders, and on his comely
+head he set his helmet well wrought with a crest of horse-hair
+that nodded menacingly above it; he grasped his redoubtable
+bronze-shod spear, and forthwith he was by the side of Ajax.
+</para>
+
+<para>
+When Hector saw that Teucer's bow was of no more use to him, he
+shouted out to the Trojans and Lycians, "Trojans, Lycians, and
+Dardanians good in close fight, be men, my friends, and show your
+mettle here at the ships, for I see the weapon of one of their
+chieftains made useless by the hand of Jove. It is easy to see
+when Jove is helping people and means to help them still further,
+or again when he is bringing them down and will do nothing for
+them; he is now on our side, and is going against the Argives.
+Therefore swarm round the ships and fight. If any of you is
+struck by spear or sword and loses his life, let him die; he dies
+with honour who dies fighting for his country; and he will leave
+his wife and children safe behind him, with his house and
+allotment unplundered if only the Achaeans can be driven back to
+their own land, they and their ships."
+</para>
+
+<para>
+With these words he put heart and soul into them all. Ajax on the
+other side exhorted his comrades saying, "Shame on you Argives,
+we are now utterly undone, unless we can save ourselves by
+driving the enemy from our ships. Do you think, if Hector takes
+them, that you will be able to get home by land? Can you not hear
+him cheering on his whole host to fire our fleet, and bidding
+them remember that they are not at a dance but in battle? Our
+only course is to fight them with might and main; we had better
+chance it, life or death, once for all, than fight long and
+without issue hemmed in at our ships by worse men than
+ourselves."
+</para>
+
+<para>
+With these words he put life and soul into them all. Hector then
+killed Schedius son of Perimedes, leader of the Phoceans, and
+Ajax killed Laodamas captain of foot soldiers and son to Antenor.
+Polydamas killed Otus of Cyllene a comrade of the son of Phyleus
+and chief of the proud Epeans. When Meges saw this he sprang upon
+him, but Polydamas crouched down, and he missed him, for Apollo
+would not suffer the son of Panthous to fall in battle; but the
+spear hit Croesmus in the middle of his chest, whereon he fell
+heavily to the ground, and Meges stripped him of his armour. At
+that moment the valiant soldier Dolops son of Lampus sprang upon
+Lampus was son of Laomedon and for his valour, while his son
+Dolops was versed in all the ways of war. He then struck the
+middle of the son of Phyleus' shield with his spear, setting on
+him at close quarters, but his good corslet made with plates of
+metal saved him; Phyleus had brought it from Ephyra and the river
+Selleis, where his host, King Euphetes, had given it him to wear
+in battle and protect him. It now served to save the life of his
+son. Then Meges struck the topmost crest of Dolops's bronze
+helmet with his spear and tore away its plume of horse-hair, so
+that all newly dyed with scarlet as it was it tumbled down into
+the dust. While he was still fighting and confident of victory,
+Menelaus came up to help Meges, and got by the side of Dolops
+unperceived; he then speared him in the shoulder, from behind,
+and the point, driven so furiously, went through into his chest,
+whereon he fell headlong. The two then made towards him to strip
+him of his armour, but Hector called on all his brothers for
+help, and he especially upbraided brave Melanippus son of
+Hiketaon, who erewhile used to pasture his herds of cattle in
+Percote before the war broke out; but when the ships of the
+Danaans came, he went back to Ilius, where he was eminent among
+the Trojans, and lived near Priam who treated him as one of his
+own sons. Hector now rebuked him and said, "Why, Melanippus, are
+we thus remiss? do you take no note of the death of your kinsman,
+and do you not see how they are trying to take Dolops's armour?
+Follow me; there must be no fighting the Argives from a distance
+now, but we must do so in close combat till either we kill them
+or they take the high wall of Ilius and slay her people."
+</para>
+
+<para>
+He led on as he spoke, and the hero Melanippus followed after.
+Meanwhile Ajax son of Telamon was cheering on the Argives. "My
+friends," he cried, "be men, and fear dishonour; quit yourselves
+in battle so as to win respect from one another. Men who respect
+each other's good opinion are less likely to be killed than those
+who do not, but in flight there is neither gain nor glory."
+</para>
+
+<para>
+Thus did he exhort men who were already bent upon driving back
+the Trojans. They laid his words to heart and hedged the ships as
+with a wall of bronze, while Jove urged on the Trojans. Menelaus
+of the loud battle-cry urged Antilochus on. "Antilochus," said
+he, "you are young and there is none of the Achaeans more fleet
+of foot or more valiant than you are. See if you cannot spring
+upon some Trojan and kill him."
+</para>
+
+<para>
+He hurried away when he had thus spurred Antilochus, who at once
+darted out from the front ranks and aimed a spear, after looking
+carefully round him. The Trojans fell back as he threw, and the
+dart did not speed from his hand without effect, for it struck
+Melanippus the proud son of Hiketaon in the breast by the nipple
+as he was coming forward, and his armour rang rattling round him
+as he fell heavily to the ground. Antilochus sprang upon him as a
+dog springs on a fawn which a hunter has hit as it was breaking
+away from its covert, and killed it. Even so, O Melanippus, did
+stalwart Antilochus spring upon you to strip you of your armour;
+but noble Hector marked him, and came running up to him through
+the thick of the battle. Antilochus, brave soldier though he was,
+would not stay to face him, but fled like some savage creature
+which knows it has done wrong, and flies, when it has killed a
+dog or a man who is herding his cattle, before a body of men can
+be gathered to attack it. Even so did the son of Nestor fly, and
+the Trojans and Hector with a cry that rent the air showered
+their weapons after him; nor did he turn round and stay his
+flight till he had reached his comrades.
+</para>
+
+<para>
+The Trojans, fierce as lions, were still rushing on towards the
+ships in fulfilment of the behests of Jove who kept spurring them
+on to new deeds of daring, while he deadened the courage of the
+Argives and defeated them by encouraging the Trojans. For he
+meant giving glory to Hector son of Priam, and letting him throw
+fire upon the ships, till he had fulfilled the unrighteous prayer
+that Thetis had made him; Jove, therefore, bided his time till he
+should see the glare of a blazing ship. From that hour he was
+about so to order that the Trojans should be driven back from the
+ships and to vouchsafe glory to the Achaeans. With this purpose
+he inspired Hector son of Priam, who was cager enough already, to
+assail the ships. His fury was as that of Mars, or as when a fire
+is raging in the glades of some dense forest upon the mountains;
+he foamed at the mouth, his eyes glared under his terrible
+eye-brows, and his helmet quivered on his temples by reason of
+the fury with which he fought. Jove from heaven was with him, and
+though he was but one against many, vouchsafed him victory and
+glory; for he was doomed to an early death, and already Pallas
+Minerva was hurrying on the hour of his destruction at the hands
+of the son of Peleus. Now, however, he kept trying to break the
+ranks of the enemy wherever he could see them thickest, and in
+the goodliest armour; but do what he might he could not break
+through them, for they stood as a tower foursquare, or as some
+high cliff rising from the grey sea that braves the anger of the
+gale, and of the waves that thunder up against it. He fell upon
+them like flames of fire from every quarter. As when a wave,
+raised mountain high by wind and storm, breaks over a ship and
+covers it deep in foam, the fierce winds roar against the mast,
+the hearts of the sailors fail them for fear, and they are saved
+but by a very little from destruction--even so were the hearts of
+the Achaeans fainting within them. Or as a savage lion attacking
+a herd of cows while they are feeding by thousands in the
+low-lying meadows by some wide-watered shore--the herdsman is at
+his wit's end how to protect his herd and keeps going about now
+in the van and now in the rear of his cattle, while the lion
+springs into the thick of them and fastens on a cow so that they
+all tremble for fear--even so were the Achaeans utterly
+panic-stricken by Hector and father Jove. Nevertheless Hector
+only killed Periphetes of Mycenae; he was son of Copreus who was
+wont to take the orders of King Eurystheus to mighty Hercules,
+but the son was a far better man than the father in every way; he
+was fleet of foot, a valiant warrior, and in understanding ranked
+among the foremost men of Mycenae. He it was who then afforded
+Hector a triumph, for as he was turning back he stumbled against
+the rim of his shield which reached his feet, and served to keep
+the javelins off him. He tripped against this and fell face
+upward, his helmet ringing loudly about his head as he did so.
+Hector saw him fall and ran up to him; he then thrust a spear
+into his chest, and killed him close to his own comrades. These,
+for all their sorrow, could not help him for they were themselves
+terribly afraid of Hector.
+</para>
+
+<para>
+They had now reached the ships and the prows of those that had
+been drawn up first were on every side of them, but the Trojans
+came pouring after them. The Argives were driven back from the
+first row of ships, but they made a stand by their tents without
+being broken up and scattered; shame and fear restrained them.
+They kept shouting incessantly to one another, and Nestor of
+Gerene, tower of strength to the Achaeans, was loudest in
+imploring every man by his parents, and beseeching him to stand
+firm.
+</para>
+
+<para>
+"Be men, my friends," he cried, "and respect one another's good
+opinion. Think, all of you, on your children, your wives, your
+property, and your parents whether these be alive or dead. On
+their behalf though they are not here, I implore you to stand
+firm, and not to turn in flight."
+</para>
+
+<para>
+With these words he put heart and soul into them all. Minerva
+lifted the thick veil of darkness from their eyes, and much light
+fell upon them, alike on the side of the ships and on that where
+the fight was raging. They could see Hector and all his men, both
+those in the rear who were taking no part in the battle, and
+those who were fighting by the ships.
+</para>
+
+<para>
+Ajax could not bring himself to retreat along with the rest, but
+strode from deck to deck with a great sea-pike in his hands
+twelve cubits long and jointed with rings. As a man skilled in
+feats of horsemanship couples four horses together and comes
+tearing full speed along the public way from the country into
+some large town--many both men and women marvel as they see him
+for he keeps all the time changing his horse, springing from one
+to another without ever missing his feet while the horses are at
+a gallop--even so did Ajax go striding from one ship's deck to
+another, and his voice went up into the heavens. He kept on
+shouting his orders to the Danaans and exhorting them to defend
+their ships and tents; neither did Hector remain within the main
+body of the Trojan warriors, but as a dun eagle swoops down upon
+a flock of wild-fowl feeding near a river-geese, it may be, or
+cranes, or long-necked swans--even so did Hector make straight
+for a dark-prowed ship, rushing right towards it; for Jove with
+his mighty hand impelled him forward, and roused his people to
+follow him.
+</para>
+
+<para>
+And now the battle again raged furiously at the ships. You would
+have thought the men were coming on fresh and unwearied, so
+fiercely did they fight; and this was the mind in which they
+were--the Achaeans did not believe they should escape destruction
+but thought themselves doomed, while there was not a Trojan but
+his heart beat high with the hope of firing the ships and putting
+the Achaean heroes to the sword.
+</para>
+
+<para>
+Thus were the two sides minded. Then Hector seized the stern of
+the good ship that had brought Protesilaus to Troy, but never
+bore him back to his native land. Round this ship there raged a
+close hand-to-hand fight between Danaans and Trojans. They did
+not fight at a distance with bows and javelins, but with one mind
+hacked at one another in close combat with their mighty swords
+and spears pointed at both ends; they fought moreover with keen
+battle-axes and with hatchets. Many a good stout blade hilted and
+scabbarded with iron, fell from hand or shoulder as they fought,
+and the earth ran red with blood. Hector, when he had seized the
+ship, would not loose his hold but held on to its curved stern
+and shouted to the Trojans, "Bring fire, and raise the battle-cry
+all of you with a single voice. Now has Jove vouchsafed us a day
+that will pay us for all the rest; this day we shall take the
+ships which came hither against heaven's will, and which have
+caused us such infinite suffering through the cowardice of our
+councillors, who when I would have done battle at the ships held
+me back and forbade the host to follow me; if Jove did then
+indeed warp our judgements, himself now commands me and cheers me
+on."
+</para>
+
+<para>
+As he spoke thus the Trojans sprang yet more fiercely on the
+Achaeans, and Ajax no longer held his ground, for he was overcome
+by the darts that were flung at him, and made sure that he was
+doomed. Therefore he left the raised deck at the stern, and
+stepped back on to the seven-foot bench of the oarsmen. Here he
+stood on the look-out, and with his spear held back Trojan whom
+he saw bringing fire to the ships. All the time he kept on
+shouting at the top of his voice and exhorting the Danaans. "My
+friends," he cried, "Danaan heroes, servants of Mars, be men my
+friends, and fight with might and with main. Can we hope to find
+helpers hereafter, or a wall to shield us more surely than the
+one we have? There is no strong city within reach, whence we may
+draw fresh forces to turn the scales in our favour. We are on the
+plain of the armed Trojans with the sea behind us, and far from
+our own country. Our salvation, therefore, is in the might of our
+hands and in hard fighting."
+</para>
+
+<para>
+As he spoke he wielded his spear with still greater fury, and
+when any Trojan made towards the ships with fire at Hector's
+bidding, he would be on the look-out for him, and drive at him
+with his long spear. Twelve men did he thus kill in hand-to-hand
+fight before the ships.
+</para>
+</chapter>
+
+<chapter>
+<title>BOOK XVI</title>
+
+<para>
+THUS did they fight about the ship of Protesilaus. Then Patroclus
+drew near to Achilles with tears welling from his eyes, as from
+some spring whose crystal stream falls over the ledges of a high
+precipice. When Achilles saw him thus weeping he was sorry for
+him and said, "Why, Patroclus, do you stand there weeping like
+some silly child that comes running to her mother, and begs to be
+taken up and carried--she catches hold of her mother's dress to
+stay her though she is in a hurry, and looks tearfully up until
+her mother carries her--even such tears, Patroclus, are you now
+shedding. Have you anything to say to the Myrmidons or to myself?
+or have you had news from Phthia which you alone know? They tell
+me Menoetius son of Actor is still alive, as also Peleus son of
+Aeacus, among the Myrmidons--men whose loss we two should
+bitterly deplore; or are you grieving about the Argives and the
+way in which they are being killed at the ships, through their
+own high-handed doings? Do not hide anything from me but tell me
+that both of us may know about it."
+</para>
+
+<para>
+Then, O knight Patroclus, with a deep sigh you answered,
+"Achilles, son of Peleus, foremost champion of the Achaeans, do
+not be angry, but I weep for the disaster that has now befallen
+the Argives. All those who have been their champions so far are
+lying at the ships, wounded by sword or spear. Brave Diomed son
+of Tydeus has been hit with a spear, while famed Ulysses and
+Agamemnon have received sword-wounds; Eurypylus again has been
+struck with an arrow in the thigh; skilled apothecaries are
+attending to these heroes, and healing them of their wounds; are
+you still, O Achilles, so inexorable? May it never be my lot to
+nurse such a passion as you have done, to the baning of your own
+good name. Who in future story will speak well of you unless you
+now save the Argives from ruin? You know no pity; knight Peleus
+was not your father nor Thetis your mother, but the grey sea bore
+you and the sheer cliffs begot you, so cruel and remorseless are
+you. If however you are kept back through knowledge of some
+oracle, or if your mother Thetis has told you something from the
+mouth of Jove, at least send me and the Myrmidons with me, if I
+may bring deliverance to the Danaans. Let me moreover wear your
+armour; the Trojans may thus mistake me for you and quit the
+field, so that the hard-pressed sons of the Achaeans may have
+breathing time--which while they are fighting may hardly be. We
+who are fresh might soon drive tired men back from our ships and
+tents to their own city."
+</para>
+
+<para>
+He knew not what he was asking, nor that he was suing for his own
+destruction. Achilles was deeply moved and answered, "What, noble
+Patroclus, are you saying? I know no prophesyings which I am
+heeding, nor has my mother told me anything from the mouth of
+Jove, but I am cut to the very heart that one of my own rank
+should dare to rob me because he is more powerful than I am.
+This, after all that I have gone through, is more than I can
+endure. The girl whom the sons of the Achaeans chose for me, whom
+I won as the fruit of my spear on having sacked a city--her has
+King Agamemnon taken from me as though I were some common
+vagrant. Still, let bygones be bygones: no man may keep his anger
+for ever; I said I would not relent till battle and the cry of
+war had reached my own ships; nevertheless, now gird my armour
+about your shoulders, and lead the Myrmidons to battle, for the
+dark cloud of Trojans has burst furiously over our fleet; the
+Argives are driven back on to the beach, cooped within a narrow
+space, and the whole people of Troy has taken heart to sally out
+against them, because they see not the visor of my helmet
+gleaming near them. Had they seen this, there would not have been
+a creek nor grip that had not been filled with their dead as they
+fled back again. And so it would have been, if only King
+Agamemnon had dealt fairly by me. As it is the Trojans have beset
+our host. Diomed son of Tydeus no longer wields his spear to
+defend the Danaans, neither have I heard the voice of the son of
+Atreus coming from his hated head, whereas that of murderous
+Hector rings in my cars as he gives orders to the Trojans, who
+triumph over the Achaeans and fill the whole plain with their cry
+of battle. But even so, Patroclus, fall upon them and save the
+fleet, lest the Trojans fire it and prevent us from being able to
+return. Do, however, as I now bid you, that you may win me great
+honour from all the Danaans, and that they may restore the girl
+to me again and give me rich gifts into the bargain. When you
+have driven the Trojans from the ships, come back again. Though
+Juno's thundering husband should put triumph within your reach,
+do not fight the Trojans further in my absence, or you will rob
+me of glory that should be mine. And do not for lust of battle go
+on killing the Trojans nor lead the Achaeans on to Ilius, lest
+one of the ever-living gods from Olympus attack you--for Phoebus
+Apollo loves them well: return when you have freed the ships from
+peril, and let others wage war upon the plain. Would, by father
+Jove, Minerva, and Apollo, that not a single man of all the
+Trojans might be left alive, nor yet of the Argives, but that we
+two might be alone left to tear aside the mantle that veils the
+brow of Troy."
+</para>
+
+<para>
+Thus did they converse. But Ajax could no longer hold his ground
+for the shower of darts that rained upon him; the will of Jove
+and the javelins of the Trojans were too much for him; the helmet
+that gleamed about his temples rang with the continuous clatter
+of the missiles that kept pouring on to it and on to the
+cheek-pieces that protected his face. Moreover his left shoulder
+was tired with having held his shield so long, yet for all this,
+let fly at him as they would, they could not make him give
+ground. He could hardly draw his breath, the sweat rained from
+every pore of his body, he had not a moment's respite, and on all
+sides he was beset by danger upon danger.
+</para>
+
+<para>
+And now, tell me, O Muses that hold your mansions on Olympus, how
+fire was thrown upon the ships of the Achaeans. Hector came close
+up and let drive with his great sword at the ashen spear of Ajax.
+He cut it clean in two just behind where the point was fastened
+on to the shaft of the spear. Ajax, therefore, had now nothing
+but a headless spear, while the bronze point flew some way off
+and came ringing down on to the ground. Ajax knew the hand of
+heaven in this, and was dismayed at seeing that Jove had now left
+him utterly defenceless and was willing victory for the Trojans.
+Therefore he drew back, and the Trojans flung fire upon the ship
+which was at once wrapped in flame.
+</para>
+
+<para>
+The fire was now flaring about the ship's stern, whereon Achilles
+smote his two thighs and said to Patroclus, "Up, noble knight,
+for I see the glare of hostile fire at our fleet; up, lest they
+destroy our ships, and there be no way by which we may retreat.
+Gird on your armour at once while I call our people together."
+</para>
+
+<para>
+As he spoke Patroclus put on his armour. First he greaved his
+legs with greaves of good make, and fitted with ancle-clasps of
+silver; after this he donned the cuirass of the son of Aeacus,
+richly inlaid and studded. He hung his silver-studded sword of
+bronze about his shoulders, and then his mighty shield. On his
+comely head he set his helmet, well wrought, with a crest of
+horse-hair that nodded menacingly above it. He grasped two
+redoubtable spears that suited his hands, but he did not take the
+spear of noble Achilles, so stout and strong, for none other of
+the Achaeans could wield it, though Achilles could do so easily.
+This was the ashen spear from Mount Pelion, which Chiron had cut
+upon a mountain top and had given to Peleus, wherewith to deal
+out death among heroes. He bade Automedon yoke his horses with
+all speed, for he was the man whom he held in honour next after
+Achilles, and on whose support in battle he could rely most
+firmly. Automedon therefore yoked the fleet horses Xanthus and
+Balius, steeds that could fly like the wind: these were they whom
+the harpy Podarge bore to the west wind, as she was grazing in a
+meadow by the waters of the river Oceanus. In the side traces he
+set the noble horse Pedasus, whom Achilles had brought away with
+him when he sacked the city of Eetion, and who, mortal steed
+though he was, could take his place along with those that were
+immortal.
+</para>
+
+<para>
+Meanwhile Achilles went about everywhere among the tents, and
+bade his Myrmidons put on their armour. Even as fierce ravening
+wolves that are feasting upon a homed stag which they have killed
+upon the mountains, and their jaws are red with blood--they go in
+a pack to lap water from the clear spring with their long thin
+tongues; and they reek of blood and slaughter; they know not what
+fear is, for it is hunger drives them--even so did the leaders
+and counsellors of the Myrmidons gather round the good squire of
+the fleet descendant of Aeacus, and among them stood Achilles
+himself cheering on both men and horses.
+</para>
+
+<para>
+Fifty ships had noble Achilles brought to Troy, and in each there
+was a crew of fifty oarsmen. Over these he set five captains whom
+he could trust, while he was himself commander over them all.
+Menesthius of the gleaming corslet, son to the river Spercheius
+that streams from heaven, was captain of the first company. Fair
+Polydora daughter of Peleus bore him to ever-flowing
+Spercheius--a woman mated with a god--but he was called son of
+Borus son of Perieres, with whom his mother was living as his
+wedded wife, and who gave great wealth to gain her. The second
+company was led by noble Eudorus, son to an unwedded woman.
+Polymele, daughter of Phylas the graceful dancer, bore him; the
+mighty slayer of Argos was enamoured of her as he saw her among
+the singing women at a dance held in honour of Diana the rushing
+huntress of the golden arrows; he therefore--Mercury, giver of
+all good--went with her into an upper chamber, and lay with her
+in secret, whereon she bore him a noble son Eudorus, singularly
+fleet of foot and in fight valiant. When Ilithuia goddess of the
+pains of child-birth brought him to the light of day, and he saw
+the face of the sun, mighty Echecles son of Actor took the mother
+to wife, and gave great wealth to gain her, but her father Phylas
+brought the child up, and took care of him, doting as fondly upon
+him as though he were his own son. The third company was led by
+Pisander son of Maemalus, the finest spearman among all the
+Myrmidons next to Achilles' own comrade Patroclus. The old knight
+Phoenix was captain of the fourth company, and Alcimedon, noble
+son of Laerceus of the fifth.
+</para>
+
+<para>
+When Achilles had chosen his men and had stationed them all with
+their captains, he charged them straitly saying, "Myrmidons,
+remember your threats against the Trojans while you were at the
+ships in the time of my anger, and you were all complaining of
+me. 'Cruel son of Peleus,' you would say, 'your mother must have
+suckled you on gall, so ruthless are you. You keep us here at the
+ships against our will; if you are so relentless it were better
+we went home over the sea.' Often have you gathered and thus
+chided with me. The hour is now come for those high feats of arms
+that you have so long been pining for, therefore keep high hearts
+each one of you to do battle with the Trojans."
+</para>
+
+<para>
+With these words he put heart and soul into them all, and they
+serried their companies yet more closely when they heard the of
+their king. As the stones which a builder sets in the wall of
+some high house which is to give shelter from the winds--even so
+closely were the helmets and bossed shields set against one
+another. Shield pressed on shield, helm on helm, and man on man;
+so close were they that the horse-hair plumes on the gleaming
+ridges of their helmets touched each other as they bent their
+heads.
+</para>
+
+<para>
+In front of them all two men put on their armour--Patroclus and
+Automedon--two men, with but one mind to lead the Myrmidons. Then
+Achilles went inside his tent and opened the lid of the strong
+chest which silver-footed Thetis had given him to take on board
+ship, and which she had filled with shirts, cloaks to keep out
+the cold, and good thick rugs. In this chest he had a cup of rare
+workmanship, from which no man but himself might drink, nor would
+he make offering from it to any other god save only to father
+Jove. He took the cup from the chest and cleansed it with
+sulphur; this done he rinsed it clean water, and after he had
+washed his hands he drew wine. Then he stood in the middle of the
+court and prayed, looking towards heaven, and making his
+drink-offering of wine; nor was he unseen of Jove whose joy is in
+thunder. "King Jove," he cried, "lord of Dodona, god of the
+Pelasgi, who dwellest afar, you who hold wintry Dodona in your
+sway, where your prophets the Selli dwell around you with their
+feet unwashed and their couches made upon the ground--if you
+heard me when I prayed to you aforetime, and did me honour while
+you sent disaster on the Achaeans, vouchsafe me now the
+fulfilment of yet this further prayer. I shall stay here where my
+ships are lying, but I shall send my comrade into battle at the
+head of many Myrmidons. Grant, O all-seeing Jove, that victory
+may go with him; put your courage into his heart that Hector may
+learn whether my squire is man enough to fight alone, or whether
+his might is only then so indomitable when I myself enter the
+turmoil of war. Afterwards when he has chased the fight and the
+cry of battle from the ships, grant that he may return unharmed,
+with his armour and his comrades, fighters in close combat."
+</para>
+
+<para>
+Thus did he pray, and all-counselling Jove heard his prayer.
+Part of it he did indeed vouchsafe him--but not the whole. He
+granted that Patroclus should thrust back war and battle from the
+ships, but refused to let him come safely out of the fight.
+</para>
+
+<para>
+When he had made his drink-offering and had thus prayed, Achilles
+went inside his tent and put back the cup into his chest.
+</para>
+
+<para>
+Then he again came out, for he still loved to look upon the
+fierce fight that raged between the Trojans and Achaeans.
+</para>
+
+<para>
+Meanwhile the armed band that was about Patroclus marched on till
+they sprang high in hope upon the Trojans. They came swarming out
+like wasps whose nests are by the roadside, and whom silly
+children love to tease, whereon any one who happens to be passing
+may get stung--or again, if a wayfarer going along the road vexes
+them by accident, every wasp will come flying out in a fury to
+defend his little ones--even with such rage and courage did the
+Myrmidons swarm from their ships, and their cry of battle rose
+heavenwards. Patroclus called out to his men at the top of his
+voice, "Myrmidons, followers of Achilles son of Peleus, be men my
+friends, fight with might and with main, that we may win glory
+for the son of Peleus, who is far the foremost man at the ships
+of the Argives--he, and his close fighting followers. The son of
+Atreus King Agamemnon will thus learn his folly in showing no
+respect to the bravest of the Achaeans."
+</para>
+
+<para>
+With these words he put heart and soul into them all, and they
+fell in a body upon the Trojans. The ships rang again with the
+cry which the Achaeans raised, and when the Trojans saw the brave
+son of Menoetius and his squire all gleaming in their armour,
+they were daunted and their battalions were thrown into
+confusion, for they thought the fleet son of Peleus must now have
+put aside his anger, and have been reconciled to Agamemnon; every
+one, therefore, looked round about to see whither he might fly
+for safety.
+</para>
+
+<para>
+Patroclus first aimed a spear into the middle of the press where
+men were packed most closely, by the stern of the ship of
+Protesilaus. He hit Pyraechmes who had led his Paeonian horsemen
+from the Amydon and the broad waters of the river Axius; the
+spear struck him on the right shoulder, and with a groan he fell
+backwards in the dust; on this his men were thrown into
+confusion, for by killing their leader, who was the finest
+soldier among them, Patroclus struck panic into them all. He thus
+drove them from the ship and quenched the fire that was then
+blazing--leaving the half-burnt ship to lie where it was. The
+Trojans were now driven back with a shout that rent the skies,
+while the Danaans poured after them from their ships, shouting
+also without ceasing. As when Jove, gatherer of the
+thunder-cloud, spreads a dense canopy on the top of some lofty
+mountain, and all the peaks, the jutting headlands, and forest
+glades show out in the great light that flashes from the bursting
+heavens, even so when the Danaans had now driven back the fire
+from their ships, they took breath for a little while; but the
+fury of the fight was not yet over, for the Trojans were not
+driven back in utter rout, but still gave battle, and were ousted
+from their ground only by sheer fighting.
+</para>
+
+<para>
+The fight then became more scattered, and the chieftains killed
+one another when and how they could. The valiant son of Menoetius
+first drove his spear into the thigh of Areilycus just as he was
+turning round; the point went clean through, and broke the bone
+so that he fell forward. Meanwhile Menelaus struck Thoas in the
+chest, where it was exposed near the rim of his shield, and he
+fell dead. The son of Phyleus saw Amphiclus about to attack him,
+and ere he could do so took aim at the upper part of his thigh,
+where the muscles are thicker than in any other part; the spear
+tore through all the sinews of the leg, and his eyes were closed
+in darkness. Of the sons of Nestor one, Antilochus, speared
+Atymnius, driving the point of the spear through his throat, and
+down he fell. Maris then sprang on Antilochus in hand-to-hand
+fight to avenge his brother, and bestrode the body spear in hand;
+but valiant Thrasymedes was too quick for him, and in a moment
+had struck him in the shoulder ere he could deal his blow; his
+aim was true, and the spear severed all the muscles at the root
+of his arm, and tore them right down to the bone, so he fell
+heavily to the ground and his eyes were closed in darkness. Thus
+did these two noble comrades of Sarpedon go down to Erebus slain
+by the two sons of Nestor; they were the warrior sons of
+Amisodorus, who had reared the invincible Chimaera, to the bane
+of many. Ajax son of Oileus sprang on Cleobulus and took him
+alive as he was entangled in the crush; but he killed him then
+and there by a sword-blow on the neck. The sword reeked with his
+blood, while dark death and the strong hand of fate gripped him
+and closed his eyes.
+</para>
+
+<para>
+Peneleos and Lycon now met in close fight, for they had missed
+each other with their spears. They had both thrown without
+effect, so now they drew their swords. Lycon struck the plumed
+crest of Peneleos' helmet but his sword broke at the hilt, while
+Peneleos smote Lycon on the neck under the ear. The blade sank so
+deep that the head was held on by nothing but the skin, and there
+was no more life left in him. Meriones gave chase to Acamas on
+foot and caught him up just as he was about to mount his chariot;
+he drove a spear through his right shoulder so that he fell
+headlong from the car, and his eyes were closed in darkness.
+Idomeneus speared Erymas in the mouth; the bronze point of the
+spear went clean through it beneath the brain, crashing in among
+the white bones and smashing them up. His teeth were all of them
+knocked out and the blood came gushing in a stream from both his
+eyes; it also came gurgling up from his mouth and nostrils, and
+the darkness of death enfolded him round about.
+</para>
+
+<para>
+Thus did these chieftains of the Danaans each of them kill his
+man. As ravening wolves seize on kids or lambs, fastening on them
+when they are alone on the hillsides and have strayed from the
+main flock through the carelessness of the shepherd--and when the
+wolves see this they pounce upon them at once because they cannot
+defend themselves--even so did the Danaans now fall on the
+Trojans, who fled with ill-omened cries in their panic and had no
+more fight left in them.
+</para>
+
+<para>
+Meanwhile great Ajax kept on trying to drive a spear into Hector,
+but Hector was so skilful that he held his broad shoulders well
+under cover of his ox-hide shield, ever on the look-out for the
+whizzing of the arrows and the heavy thud of the spears. He well
+knew that the fortunes of the day had changed, but still stood
+his ground and tried to protect his comrades.
+</para>
+
+<para>
+As when a cloud goes up into heaven from Olympus, rising out of a
+clear sky when Jove is brewing a gale--even with such panic
+stricken rout did the Trojans now fly, and there was no order in
+their going. Hector's fleet horses bore him and his armour out of
+the fight, and he left the Trojan host penned in by the deep
+trench against their will. Many a yoke of horses snapped the pole
+of their chariots in the trench and left their master's car
+behind them. Patroclus gave chase, calling impetuously on the
+Danaans and full of fury against the Trojans, who, being now no
+longer in a body, filled all the ways with their cries of panic
+and rout; the air was darkened with the clouds of dust they
+raised, and the horses strained every nerve in their flight from
+the tents and ships towards the city.
+</para>
+
+<para>
+Patroclus kept on heading his horses wherever he saw most men
+flying in confusion, cheering on his men the while. Chariots were
+being smashed in all directions, and many a man came tumbling
+down from his own car to fall beneath the wheels of that of
+Patroclus, whose immortal steeds, given by the gods to Peleus,
+sprang over the trench at a bound as they sped onward. He was
+intent on trying to get near Hector, for he had set his heart on
+spearing him, but Hector's horses were now hurrying him away. As
+the whole dark earth bows before some tempest on an autumn day
+when Jove rains his hardest to punish men for giving crooked
+judgement in their courts, and arriving justice therefrom without
+heed to the decrees of heaven--all the rivers run full and the
+torrents tear many a new channel as they roar headlong from the
+mountains to the dark sea, and it fares ill with the works of
+men--even such was the stress and strain of the Trojan horses in
+their flight.
+</para>
+
+<para>
+Patroclus now cut off the battalions that were nearest to him and
+drove them back to the ships. They were doing their best to reach
+the city, but he would not let them, and bore down on them
+between the river and the ships and wall. Many a fallen comrade
+did he then avenge. First he hit Pronous with a spear on the
+chest where it was exposed near the rim of his shield, and he
+fell heavily to the ground. Next he sprang on Thestor son of
+Enops, who was sitting all huddled up in his chariot, for he had
+lost his head and the reins had been torn out of his hands.
+Patroclus went up to him and drove a spear into his right jaw; he
+thus hooked him by the teeth and the spear pulled him over the
+rim of his car, as one who sits at the end of some jutting rock
+and draws a strong fish out of the sea with a hook and a line--
+even so with his spear did he pull Thestor all gaping from his
+chariot; he then threw him down on his face and he died while
+falling. On this, as Erylaus was on to attack him, he struck him
+full on the head with a stone, and his brains were all battered
+inside his helmet, whereon he fell headlong to the ground and the
+pangs of death took hold upon him. Then he laid low, one after
+the other, Erymas, Amphoterus, Epaltes, Tlepolemus, Echius son of
+Damastor, Pyris, lpheus, Euippus and Polymelus son of Argeas.
+</para>
+
+<para>
+Now when Sarpedon saw his comrades, men who wore ungirdled
+tunics, being overcome by Patroclus son of Menoetius, he rebuked
+the Lycians saying. "Shame on you, where are you flying to? Show
+your mettle; I will myself meet this man in fight and learn who
+it is that is so masterful; he has done us much hurt, and has
+stretched many a brave man upon the ground."
+</para>
+
+<para>
+He sprang from his chariot as he spoke, and Patroclus, when he
+saw this, leaped on to the ground also. The two then rushed at
+one another with loud cries like eagle-beaked crook-taloned
+vultures that scream and tear at one another in some high
+mountain fastness.
+</para>
+
+<para>
+The son of scheming Saturn looked down upon them in pity and said
+to Juno who was his wife and sister, "Alas, that it should be the
+lot of Sarpedon whom I love so dearly to perish by the hand of
+Patroclus. I am in two minds whether to catch him up out of the
+fight and set him down safe and sound in the fertile land of
+Lycia, or to let him now fall by the hand of the son of
+Menoetius."
+</para>
+
+<para>
+And Juno answered, "Most dread son of Saturn, what is this that
+you are saying? Would you snatch a mortal man, whose doom has
+long been fated, out of the jaws of death? Do as you will, but we
+shall not all of us be of your mind. I say further, and lay my
+saying to your heart, that if you send Sarpedon safely to his own
+home, some other of the gods will be also wanting to escort his
+son out of battle, for there are many sons of gods fighting round
+the city of Troy, and you will make every one jealous. If,
+however, you are fond of him and pity him, let him indeed fall by
+the hand of Patroclus, but as soon as the life is gone out of
+him, send Death and sweet Sleep to bear him off the field and
+take him to the broad lands of Lycia, where his brothers and his
+kinsmen will bury him with mound and pillar, in due honour to the
+dead."
+</para>
+
+<para>
+The sire of gods and men assented, but he shed a rain of blood
+upon the earth in honour of his son whom Patroclus was about to
+kill on the rich plain of Troy far from his home.
+</para>
+
+<para>
+When they were now come close to one another Patroclus struck
+Thrasydemus, the brave squire of Sarpedon, in the lower part of
+the belly, and killed him. Sarpedon then aimed a spear at
+Patroclus and missed him, but he struck the horse Pedasus in the
+right shoulder, and it screamed aloud as it lay, groaning in the
+dust until the life went out of it. The other two horses began to
+plunge; the pole of the chariot cracked and they got entangled in
+the reins through the fall of the horse that was yoked along with
+them; but Automedon knew what to do; without the loss of a moment
+he drew the keen blade that hung by his sturdy thigh and cut the
+third horse adrift; whereon the other two righted themselves, and
+pulling hard at the reins again went together into battle.
+</para>
+
+<para>
+Sarpedon now took a second aim at Patroclus, and again missed
+him, the point of the spear passed over his left shoulder without
+hitting him. Patroclus then aimed in his turn, and the spear sped
+not from his hand in vain, for he hit Sarpedon just where the
+midriff surrounds the ever-beating heart. He fell like some oak
+or silver poplar or tall pine to which woodmen have laid their
+axes upon the mountains to make timber for ship-building--even so
+did he lie stretched at full length in front of his chariot and
+horses, moaning and clutching at the blood-stained dust. As when
+a lion springs with a bound upon a herd of cattle and fastens on
+a great black bull which dies bellowing in its clutches--even so
+did the leader of the Lycian warriors struggle in death as he
+fell by the hand of Patroclus. He called on his trusty comrade
+and said, "Glaucus, my brother, hero among heroes, put forth all
+your strength, fight with might and main, now if ever quit
+yourself like a valiant soldier. First go about among the Lycian
+captains and bid them fight for Sarpedon; then yourself also do
+battle to save my armour from being taken. My name will haunt you
+henceforth and for ever if the Achaeans rob me of my armour now
+that I have fallen at their ships. Do your very utmost and call
+all my people together."
+</para>
+
+<para>
+Death closed his eyes as he spoke. Patroclus planted his heel on
+his breast and drew the spear from his body, whereon his senses
+came out along with it, and he drew out both spear-point and
+Sarpedon's soul at the same time. Hard by the Myrmidons held his
+snorting steeds, who were wild with panic at finding themselves
+deserted by their lords.
+</para>
+
+<para>
+Glaucus was overcome with grief when he heard what Sarpedon said,
+for he could not help him. He had to support his arm with his
+other hand, being in great pain through the wound which Teucer's
+arrow had given him when Teucer was defending the wall as he,
+Glaucus, was assailing it. Therefore he prayed to far-darting
+Apollo saying, "Hear me O king from your seat, may be in the rich
+land of Lycia, or may be in Troy, for in all places you can hear
+the prayer of one who is in distress, as I now am. I have a
+grievous wound; my hand is aching with pain, there is no
+staunching the blood, and my whole arm drags by reason of my
+hurt, so that I cannot grasp my sword nor go among my foes and
+fight them, thou our prince, Jove's son Sarpedon, is slain. Jove
+defended not his son, do you, therefore, O king, heal me of my
+wound, ease my pain and grant me strength both to cheer on the
+Lycians and to fight along with them round the body of him who
+has fallen."
+</para>
+
+<para>
+Thus did he pray, and Apollo heard his prayer. He eased his pain,
+staunched the black blood from the wound, and gave him new
+strength. Glaucus perceived this, and was thankful that the
+mighty god had answered his prayer; forthwith, therefore, he went
+among the Lycian captains, and bade them come to fight about the
+body of Sarpedon. From these he strode on among the Trojans to
+Polydamas son of Panthous and Agenor; he then went in search of
+Aeneas and Hector, and when he had found them he said, "Hector,
+you have utterly forgotten your allies, who languish here for
+your sake far from friends and home while you do nothing to
+support them. Sarpedon leader of the Lycian warriors has fallen--
+he who was at once the right and might of Lycia; Mars has laid
+him low by the spear of Patroclus. Stand by him, my friends, and
+suffer not the Myrmidons to strip him of his armour, nor to treat
+his body with contumely in revenge for all the Danaans whom we
+have speared at the ships."
+</para>
+
+<para>
+As he spoke the Trojans were plunged in extreme and ungovernable
+grief; for Sarpedon, alien though he was, had been one of the
+main stays of their city, both as having much people with him,
+and himself the foremost among them all. Led by Hector, who was
+infuriated by the fall of Sarpedon, they made instantly for the
+Danaans with all their might, while the undaunted spirit of
+Patroclus son of Menoetius cheered on the Achaeans. First he
+spoke to the two Ajaxes, men who needed no bidding. "Ajaxes,"
+said he, "may it now please you to show yourselves the men you
+have always been, or even better--Sarpedon is fallen--he who was
+first to overleap the wall of the Achaeans; let us take the body
+and outrage it; let us strip the armour from his shoulders, and
+kill his comrades if they try to rescue his body."
+</para>
+
+<para>
+He spoke to men who of themselves were full eager; both sides,
+therefore, the Trojans and Lycians on the one hand, and the
+Myrmidons and Achaeans on the other, strengthened their
+battalions, and fought desperately about the body of Sarpedon,
+shouting fiercely the while. Mighty was the din of their armour
+as they came together, and Jove shed a thick darkness over the
+fight, to increase the toil of the battle over the body of his
+son.
+</para>
+
+<para>
+At first the Trojans made some headway against the Achaeans, for
+one of the best men among the Myrmidons was killed, Epeigeus, son
+of noble Agacles who had erewhile been king in the good city of
+Budeum; but presently, having killed a valiant kinsman of his
+own, he took refuge with Peleus and Thetis, who sent him to Ilius
+the land of noble steeds to fight the Trojans under Achilles.
+Hector now struck him on the head with a stone just as he had
+caught hold of the body, and his brains inside his helmet were
+all battered in, so that he fell face foremost upon the body of
+Sarpedon, and there died. Patroclus was enraged by the death of
+his comrade, and sped through the front ranks as swiftly as a
+hawk that swoops down on a flock of daws or starlings. Even so
+swiftly, O noble knight Patroclus, did you make straight for the
+Lycians and Trojans to avenge your comrade. Forthwith he struck
+Sthenelaus the son of Ithaemenes on the neck with a stone, and
+broke the tendons that join it to the head and spine. On this
+Hector and the front rank of his men gave ground. As far as a man
+can throw a javelin when competing for some prize, or even in
+battle--so far did the Trojans now retreat before the Achaeans.
+Glaucus, captain of the Lycians, was the first to rally them, by
+killing Bathycles son of Chalcon who lived in Hellas and was the
+richest man among the Myrmidons. Glaucus turned round suddenly,
+just as Bathycles who was pursuing him was about to lay hold of
+him, and drove his spear right into the middle of his chest,
+whereon he fell heavily to the ground, and the fall of so good a
+man filled the Achaeans with dismay, while the Trojans were
+exultant, and came up in a body round the corpse. Nevertheless
+the Achaeans, mindful of their prowess, bore straight down upon
+them.
+</para>
+
+<para>
+Meriones then killed a helmed warrior of the Trojans, Laogonus
+son of Onetor, who was priest of Jove of Mt. Ida, and was
+honoured by the people as though he were a god. Meriones struck
+him under the jaw and ear, so that life went out of him and the
+darkness of death laid hold upon him. Aeneas then aimed a spear
+at Meriones, hoping to hit him under the shield as he was
+advancing, but Meriones saw it coming and stooped forward to
+avoid it, whereon the spear flew past him and the point stuck in
+the ground, while the butt-end went on quivering till Mars robbed
+it of its force. The spear, therefore, sped from Aeneas's hand in
+vain and fell quivering to the ground. Aeneas was angry and said,
+"Meriones, you are a good dancer, but if I had hit you my spear
+would soon have made an end of you."
+</para>
+
+<para>
+And Meriones answered, "Aeneas, for all your bravery, you will
+not be able to make an end of every one who comes against you.
+You are only a mortal like myself, and if I were to hit you in
+the middle of your shield with my spear, however strong and
+self-confident you may be, I should soon vanquish you, and you
+would yield your life to Hades of the noble steeds."
+</para>
+
+<para>
+On this the son of Menoetius rebuked him and said, "Meriones,
+hero though you be, you should not speak thus; taunting speeches,
+my good friend, will not make the Trojans draw away from the dead
+body; some of them must go under ground first; blows for battle,
+and words for council; fight, therefore, and say nothing."
+</para>
+
+<para>
+He led the way as he spoke and the hero went forward with him.
+As the sound of woodcutters in some forest glade upon the
+mountains--and the thud of their axes is heard afar--even such a
+din now rose from earth-clash of bronze armour and of good
+ox-hide shields, as men smote each other with their swords and
+spears pointed at both ends. A man had need of good eyesight now
+to know Sarpedon, so covered was he from head to foot with spears
+and blood and dust. Men swarmed about the body, as flies that
+buzz round the full milk-pails in spring when they are brimming
+with milk--even so did they gather round Sarpedon; nor did Jove
+turn his keen eyes away for one moment from the fight, but kept
+looking at it all the time, for he was settling how best to kill
+Patroclus, and considering whether Hector should be allowed to
+end him now in the fight round the body of Sarpedon, and strip
+him of his armour, or whether he should let him give yet further
+trouble to the Trojans. In the end, he deemed it best that the
+brave squire of Achilles son of Peleus should drive Hector and
+the Trojans back towards the city and take the lives of many.
+First, therefore, he made Hector turn fainthearted, whereon he
+mounted his chariot and fled, bidding the other Trojans fly also,
+for he saw that the scales of Jove had turned against him.
+Neither would the brave Lycians stand firm; they were dismayed
+when they saw their king lying struck to the heart amid a heap of
+corpses--for when the son of Saturn made the fight wax hot many
+had fallen above him. The Achaeans, therefore stripped the
+gleaming armour from his shoulders and the brave son of Menoetius
+gave it to his men to take to the ships. Then Jove lord of the
+storm-cloud said to Apollo, "Dear Phoebus, go, I pray you, and
+take Sarpedon out of range of the weapons; cleanse the black
+blood from off him, and then bear him a long way off where you
+may wash him in the river, anoint him with ambrosia, and clothe
+him in immortal raiment; this done, commit him to the arms of the
+two fleet messengers, Death, and Sleep, who will carry him
+straightway to the rich land of Lycia, where his brothers and
+kinsmen will inter him, and will raise both mound and pillar to
+his memory, in due honour to the dead."
+</para>
+
+<para>
+Thus he spoke. Apollo obeyed his father's saying, and came down
+from the heights of Ida into the thick of the fight; forthwith he
+took Sarpedon out of range of the weapons, and then bore him a
+long way off, where he washed him in the river, anointed him with
+ambrosia and clothed him in immortal raiment; this done, he
+committed him to the arms of the two fleet messengers, Death, and
+Sleep, who presently set him down in the rich land of Lycia.
+</para>
+
+<para>
+Meanwhile Patroclus, with many a shout to his horses and to
+Automedon, pursued the Trojans and Lycians in the pride and
+foolishness of his heart. Had he but obeyed the bidding of the
+son of Peleus, he would have, escaped death and have been
+scatheless; but the counsels of Jove pass man's understanding; he
+will put even a brave man to flight and snatch victory from his
+grasp, or again he will set him on to fight, as he now did when
+he put a high spirit into the heart of Patroclus.
+</para>
+
+<para>
+Who then first, and who last, was slain by you, O Patroclus, when
+the gods had now called you to meet your doom? First Adrestus,
+Autonous, Echeclus, Perimus the son of Megas, Epistor and
+Melanippus; after these he killed Elasus, Mulius, and Pylartes.
+These he slew, but the rest saved themselves by flight.
+</para>
+
+<para>
+The sons of the Achaeans would now have taken Troy by the hands
+of Patroclus, for his spear flew in all directions, had not
+Phoebus Apollo taken his stand upon the wall to defeat his
+purpose and to aid the Trojans. Thrice did Patroclus charge at an
+angle of the high wall, and thrice did Apollo beat him back,
+striking his shield with his own immortal hands. When Patroclus
+was coming on like a god for yet a fourth time, Apollo shouted to
+him with an awful voice and said, "Draw back, noble Patroclus, it
+is not your lot to sack the city of the Trojan chieftains, nor
+yet will it be that of Achilles who is a far better man than you
+are." On hearing this, Patroclus withdrew to some distance and
+avoided the anger of Apollo.
+</para>
+
+<para>
+Meanwhile Hector was waiting with his horses inside the Scaean
+gates, in doubt whether to drive out again and go on fighting, or
+to call the army inside the gates. As he was thus doubting
+Phoebus Apollo drew near him in the likeness of a young and lusty
+warrior Asius, who was Hector's uncle, being own brother to
+Hecuba, and son of Dymas who lived in Phrygia by the waters of
+the river Sangarius; in his likeness Jove's son Apollo now spoke
+to Hector saying, "Hector, why have you left off fighting? It is
+ill done of you. If I were as much better a man than you, as I am
+worse, you should soon rue your slackness. Drive straight towards
+Patroclus, if so be that Apollo may grant you a triumph over him,
+and you may rule him."
+</para>
+
+<para>
+With this the god went back into the hurly-burly, and Hector bade
+Cebriones drive again into the fight. Apollo passed in among
+them, and struck panic into the Argives, while he gave triumph to
+Hector and the Trojans. Hector let the other Danaans alone and
+killed no man, but drove straight at Patroclus. Patroclus then
+sprang from his chariot to the ground, with a spear in his left
+hand, and in his right a jagged stone as large as his hand could
+hold. He stood still and threw it, nor did it go far without
+hitting some one; the cast was not in vain, for the stone struck
+Cebriones, Hector's charioteer, a bastard son of Priam, as he
+held the reins in his hands. The stone hit him on the forehead
+and drove his brows into his head for the bone was smashed, and
+his eyes fell to the ground at his feet. He dropped dead from his
+chariot as though he were diving, and there was no more life left
+in him. Over him did you then vaunt, O knight Patroclus, saying,
+"Bless my heart, how active he is, and how well he dives. If we
+had been at sea this fellow would have dived from the ship's side
+and brought up as many oysters as the whole crew could stomach,
+even in rough water, for he has dived beautifully off his chariot
+on to the ground. It seems, then, that there are divers also
+among the Trojans."
+</para>
+
+<para>
+As he spoke he flung himself on Cebriones with the spring, as it
+were, of a lion that while attacking a stockyard is himself
+struck in the chest, and his courage is his own bane--even so
+furiously, O Patroclus, did you then spring upon Cebriones.
+Hector sprang also from his chariot to the ground. The pair then
+fought over the body of Cebriones. As two lions fight fiercely on
+some high mountain over the body of a stag that they have killed,
+even so did these two mighty warriors, Patroclus son of Menoetius
+and brave Hector, hack and hew at one another over the corpse of
+Cebriones. Hector would not let him go when he had once got him
+by the head, while Patroclus kept fast hold of his feet, and a
+fierce fight raged between the other Danaans and Trojans. As the
+east and south wind buffet one another when they beat upon some
+dense forest on the mountains--there is beech and ash and
+spreading cornel; the top of the trees roar as they beat on one
+another, and one can hear the boughs cracking and breaking--even
+so did the Trojans and Achaeans spring upon one another and lay
+about each other, and neither side would give way. Many a pointed
+spear fell to ground and many a winged arrow sped from its
+bow-string about the body of Cebriones; many a great stone,
+moreover, beat on many a shield as they fought around his body,
+but there he lay in the whirling clouds of dust, all huge and
+hugely, heedless of his driving now.
+</para>
+
+<para>
+So long as the sun was still high in mid-heaven the weapons of
+either side were alike deadly, and the people fell; but when he
+went down towards the time when men loose their oxen, the
+Achaeans proved to be beyond all forecast stronger, so that they
+drew Cebriones out of range of the darts and tumult of the
+Trojans, and stripped the armour from his shoulders. Then
+Patroclus sprang like Mars with fierce intent and a terrific
+shout upon the Trojans, and thrice did he kill nine men; but as
+he was coming on like a god for a time, then, O Patroclus, was
+the hour of your end approaching, for Phoebus fought you in fell
+earnest. Patroclus did not see him as he moved about in the
+crush, for he was enshrouded in thick darkness, and the god
+struck him from behind on his back and his broad shoulders with
+the flat of his hand, so that his eyes turned dizzy. Phoebus
+Apollo beat the helmet from off his head, and it rolled rattling
+off under the horses' feet, where its horse-hair plumes were all
+begrimed with dust and blood. Never indeed had that helmet fared
+so before, for it had served to protect the head and comely
+forehead of the godlike hero Achilles. Now, however, Zeus
+delivered it over to be worn by Hector. Nevertheless the end of
+Hector also was near. The bronze-shod spear, so great and so
+strong, was broken in the hand of Patroclus, while his shield
+that covered him from head to foot fell to the ground as did also
+the band that held it, and Apollo undid the fastenings of his
+corslet.
+</para>
+
+<para>
+On this his mind became clouded; his limbs failed him, and he
+stood as one dazed; whereon Euphorbus son of Panthous a
+Dardanian, the best spearman of his time, as also the finest
+horseman and fleetest runner, came behind him and struck him in
+the back with a spear, midway between the shoulders. This man as
+soon as ever he had come up with his chariot had dismounted
+twenty men, so proficient was he in all the arts of war--he it
+was, O knight Patroclus, that first drove a weapon into you, but
+he did not quite overpower you. Euphorbus then ran back into the
+crowd, after drawing his ashen spear out of the wound; he would
+not stand firm and wait for Patroclus, unarmed though he now was,
+to attack him; but Patroclus unnerved, alike by the blow the god
+had given him and by the spear-wound, drew back under cover of
+his men in fear for his life. Hector on this, seeing him to be
+wounded and giving ground, forced his way through the ranks, and
+when close up with him struck him in the lower part of the belly
+with a spear, driving the bronze point right through it, so that
+he fell heavily to the ground to the great of the Achaeans. As
+when a lion has fought some fierce wild-boar and worsted him--the
+two fight furiously upon the mountains over some little fountain
+at which they would both drink, and the lion has beaten the boar
+till he can hardly breathe--even so did Hector son of Priam take
+the life of the brave son of Menoetius who had killed so many,
+striking him from close at hand, and vaunting over him the while.
+"Patroclus," said he, "you deemed that you should sack our city,
+rob our Trojan women of their freedom, and carry them off in your
+ships to your own country. Fool; Hector and his fleet horses were
+ever straining their utmost to defend them. I am foremost of all
+the Trojan warriors to stave the day of bondage from off them; as
+for you, vultures shall devour you here. Poor wretch, Achilles
+with all his bravery availed you nothing; and yet I ween when you
+left him he charged you straitly saying, 'Come not back to the
+ships, knight Patroclus, till you have rent the bloodstained
+shirt of murderous Hector about his body. Thus I ween did he
+charge you, and your fool's heart answered him 'yea' within you."
+</para>
+
+<para>
+Then, as the life ebbed out of you, you answered, O knight
+Patroclus: "Hector, vaunt as you will, for Jove the son of Saturn
+and Apollo have vouchsafed you victory; it is they who have
+vanquished me so easily, and they who have stripped the armour
+from my shoulders; had twenty such men as you attacked me, all of
+them would have fallen before my spear. Fate and the son of Leto
+have overpowered me, and among mortal men Euphorbus; you are
+yourself third only in the killing of me. I say further, and lay
+my saying to your heart, you too shall live but for a little
+season; death and the day of your doom are close upon you, and
+they will lay you low by the hand of Achilles son of Aeacus."
+</para>
+
+<para>
+When he had thus spoken his eyes were closed in death, his soul
+left his body and flitted down to the house of Hades, mourning
+its sad fate and bidding farewell to the youth and vigor of its
+manhood. Dead though he was, Hector still spoke to him saying,
+"Patroclus, why should you thus foretell my doom? Who knows but
+Achilles, son of lovely Thetis, may be smitten by my spear and
+die before me?"
+</para>
+
+<para>
+As he spoke he drew the bronze spear from the wound, planting his
+foot upon the body, which he thrust off and let lie on its back.
+He then went spear in hand after Automedon, squire of the fleet
+descendant of Aeacus, for he longed to lay him low, but the
+immortal steeds which the gods had given as a rich gift to Peleus
+bore him swiftly from the field.
+</para>
+</chapter>
+
+<chapter>
+<title>BOOK XVII</title>
+
+<para>
+BRAVE Menelaus son of Atreus now came to know that Patroclus had
+fallen, and made his way through the front ranks clad in full
+armour to bestride him. As a cow stands lowing over her first
+calf, even so did yellow-haired Menelaus bestride Patroclus. He
+held his round shield and his spear in front of him, resolute to
+kill any who should dare face him. But the son of Panthous had
+also noted the body, and came up to Menelaus saying, "Menelaus,
+son of Atreus, draw back, leave the body, and let the
+bloodstained spoils be. I was first of the Trojans and their
+brave allies to drive my spear into Patroclus, let me, therefore,
+have my full glory among the Trojans, or I will take aim and kill
+you."
+</para>
+
+<para>
+To this Menelaus answered in great anger "By father Jove,
+boasting is an ill thing. The pard is not more bold, nor the lion
+nor savage wild-boar, which is fiercest and most dauntless of all
+creatures, than are the proud sons of Panthous. Yet Hyperenor did
+not see out the days of his youth when he made light of me and
+withstood me, deeming me the meanest soldier among the Danaans.
+His own feet never bore him back to gladden his wife and parents.
+Even so shall I make an end of you too, if you withstand me; get
+you back into the crowd and do not face me, or it shall be worse
+for you. Even a fool may be wise after the event."
+</para>
+
+<para>
+Euphorbus would not listen, and said, "Now indeed, Menelaus,
+shall you pay for the death of my brother over whom you vaunted,
+and whose wife you widowed in her bridal chamber, while you
+brought grief unspeakable on his parents. I shall comfort these
+poor people if I bring your head and armour and place them in the
+hands of Panthous and noble Phrontis. The time is come when this
+matter shall be fought out and settled, for me or against me."
+</para>
+
+<para>
+As he spoke he struck Menelaus full on the shield, but the spear
+did not go through, for the shield turned its point. Menelaus
+then took aim, praying to father Jove as he did so; Euphorbus was
+drawing back, and Menelaus struck him about the roots of his
+throat, leaning his whole weight on the spear, so as to drive it
+home. The point went clean through his neck, and his armour rang
+rattling round him as he fell heavily to the ground. His hair
+which was like that of the Graces, and his locks so deftly bound
+in bands of silver and gold, were all bedrabbled with blood. As
+one who has grown a fine young olive tree in a clear space where
+there is abundance of water--the plant is full of promise, and
+though the winds beat upon it from every quarter it puts forth
+its white blossoms till the blasts of some fierce hurricane sweep
+down upon it and level it with the ground--even so did Menelaus
+strip the fair youth Euphorbus of his armour after he had slain
+him. Or as some fierce lion upon the mountains in the pride of
+his strength fastens on the finest heifer in a herd as it is
+feeding--first he breaks her neck with his strong jaws, and then
+gorges on her blood and entrails; dogs and shepherds raise a hue
+and cry against him, but they stand aloof and will not come close
+to him, for they are pale with fear--even so no one had the
+courage to face valiant Menelaus. The son of Atreus would have
+then carried off the armour of the son of Panthous with ease, had
+not Phoebus Apollo been angry, and in the guise of Mentes chief
+of the Cicons incited Hector to attack him. "Hector," said he,
+"you are now going after the horses of the noble son of Aeacus,
+but you will not take them; they cannot be kept in hand and
+driven by mortal man, save only by Achilles, who is son to an
+immortal mother. Meanwhile Menelaus son of Atreus has bestridden
+the body of Patroclus and killed the noblest of the Trojans,
+Euphorbus son of Panthous, so that he can fight no more."
+</para>
+
+<para>
+The god then went back into the toil and turmoil, but the soul of
+Hector was darkened with a cloud of grief; he looked along the
+ranks and saw Euphorbus lying on the ground with the blood still
+flowing from his wound, and Menelaus stripping him of his armour.
+On this he made his way to the front like a flame of fire, clad
+in his gleaming armour, and crying with a loud voice. When the
+son of Atreus heard him, he said to himself in his dismay, "Alas!
+what shall I do? I may not let the Trojans take the armour of
+Patroclus who has fallen fighting on my behalf, lest some Danaan
+who sees me should cry shame upon me. Still if for my honour's
+sake I fight Hector and the Trojans single-handed, they will
+prove too many for me, for Hector is bringing them up in force.
+Why, however, should I thus hesitate? When a man fights in
+despite of heaven with one whom a god befriends, he will soon rue
+it. Let no Danaan think ill of me if I give place to Hector, for
+the hand of heaven is with him. Yet, if I could find Ajax, the
+two of us would fight Hector and heaven too, if we might only
+save the body of Patroclus for Achilles son of Peleus. This, of
+many evils would be the least."
+</para>
+
+<para>
+While he was thus in two minds, the Trojans came up to him with
+Hector at their head; he therefore drew back and left the body,
+turning about like some bearded lion who is being chased by dogs
+and men from a stockyard with spears and hue and cry, whereon he
+is daunted and slinks sulkily off--even so did Menelaus son of
+Atreus turn and leave the body of Patroclus. When among the body
+of his men, he looked around for mighty Ajax son of Telamon, and
+presently saw him on the extreme left of the fight, cheering on
+his men and exhorting them to keep on fighting, for Phoebus
+Apollo had spread a great panic among them. He ran up to him and
+said, "Ajax, my good friend, come with me at once to dead
+Patroclus, if so be that we may take the body to Achilles--as for
+his armour, Hector already has it."
+</para>
+
+<para>
+These words stirred the heart of Ajax, and he made his way among
+the front ranks, Menelaus going with him. Hector had stripped
+Patroclus of his armour, and was dragging him away to cut off his
+head and take the body to fling before the dogs of Troy. But Ajax
+came up with his shield like wall before him, on which Hector
+withdrew under shelter of his men, and sprang on to his chariot,
+giving the armour over to the Trojans to take to the city, as a
+great trophy for himself; Ajax, therefore, covered the body of
+Patroclus with his broad shield and bestrode him; as a lion
+stands over his whelps if hunters have come upon him in a forest
+when he is with his little ones--in the pride and fierceness of
+his strength he draws his knit brows down till they cover his
+eyes--even so did Ajax bestride the body of Patroclus, and by his
+side stood Menelaus son of Atreus, nursing great sorrow in his
+heart.
+</para>
+
+<para>
+Then Glaucus son of Hippolochus looked fiercely at Hector and
+rebuked him sternly. "Hector," said he, "you make a brave show,
+but in fight you are sadly wanting. A runaway like yourself has
+no claim to so great a reputation. Think how you may now save
+your town and citadel by the hands of your own people born in
+Ilius; for you will get no Lycians to fight for you, seeing what
+thanks they have had for their incessant hardships. Are you
+likely, sir, to do anything to help a man of less note, after
+leaving Sarpedon, who was at once your guest and comrade in arms,
+to be the spoil and prey of the Danaans? So long as he lived he
+did good service both to your city and yourself; yet you had no
+stomach to save his body from the dogs. If the Lycians will
+listen to me, they will go home and leave Troy to its fate. If
+the Trojans had any of that daring fearless spirit which lays
+hold of men who are fighting for their country and harassing
+those who would attack it, we should soon bear off Patroclus into
+Ilius. Could we get this dead man away and bring him into the
+city of Priam, the Argives would readily give up the armour of
+Sarpedon, and we should get his body to boot. For he whose squire
+has been now killed is the foremost man at the ships of the
+Achaeans--he and his close-fighting followers. Nevertheless you
+dared not make a stand against Ajax, nor face him, eye to eye,
+with battle all round you, for he is a braver man than you are."
+</para>
+
+<para>
+Hector scowled at him and answered, "Glaucus, you should know
+better. I have held you so far as a man of more understanding
+than any in all Lycia, but now I despise you for saying that I am
+afraid of Ajax. I fear neither battle nor the din of chariots,
+but Jove's will is stronger than ours; Jove at one time makes
+even a strong man draw back and snatches victory from his grasp,
+while at another he will set him on to fight. Come hither then,
+my friend, stand by me and see indeed whether I shall play the
+coward the whole day through as you say, or whether I shall not
+stay some even of the boldest Danaans from fighting round the
+body of Patroclus."
+</para>
+
+<para>
+As he spoke he called loudly on the Trojans saying, "Trojans,
+Lycians, and Dardanians, fighters in close combat, be men, my
+friends, and fight might and main, while I put on the goodly
+armour of Achilles, which I took when I killed Patroclus."
+</para>
+
+<para>
+With this Hector left the fight, and ran full speed after his men
+who were taking the armour of Achilles to Troy, but had not yet
+got far. Standing for a while apart from the woeful fight, he
+changed his armour. His own he sent to the strong city of Ilius
+and to the Trojans, while he put on the immortal armour of the
+son of Peleus, which the gods had given to Peleus, who in his age
+gave it to his son; but the son did not grow old in his father's
+armour.
+</para>
+
+<para>
+When Jove, lord of the storm-cloud, saw Hector standing aloof and
+arming himself in the armour of the son of Peleus, he wagged his
+head and muttered to himself saying, "A! poor wretch, you arm in
+the armour of a hero, before whom many another trembles, and you
+reck nothing of the doom that is already close upon you. You have
+killed his comrade so brave and strong, but it was not well that
+you should strip the armour from his head and shoulders. I do
+indeed endow you with great might now, but as against this you
+shall not return from battle to lay the armour of the son of
+Peleus before Andromache."
+</para>
+
+<para>
+The son of Saturn bowed his portentous brows, and Hector fitted
+the armour to his body, while terrible Mars entered into him, and
+filled his whole body with might and valour. With a shout he
+strode in among the allies, and his armour flashed about him so
+that he seemed to all of them like the great son of Peleus
+himself. He went about among them and cheered them on--Mesthles,
+Glaucus, Medon, Thersilochus, Asteropaeus, Deisenor and
+Hippothous, Phorcys, Chromius and Ennomus the augur. All these
+did he exhort saying, "Hear me, allies from other cities who are
+here in your thousands, it was not in order to have a crowd about
+me that I called you hither each from his several city, but that
+with heart and soul you might defend the wives and little ones of
+the Trojans from the fierce Achaeans. For this do I oppress my
+people with your food and the presents that make you rich.
+Therefore turn, and charge at the foe, to stand or fall as is the
+game of war; whoever shall bring Patroclus, dead though he be,
+into the hands of the Trojans, and shall make Ajax give way
+before him, I will give him one half of the spoils while I keep
+the other. He will thus share like honour with myself."
+</para>
+
+<para>
+When he had thus spoken they charged full weight upon the Danaans
+with their spears held out before them, and the hopes of each ran
+high that he should force Ajax son of Telamon to yield up the
+body--fools that they were, for he was about to take the lives of
+many. Then Ajax said to Menelaus, "My good friend Menelaus, you
+and I shall hardly come out of this fight alive. I am less
+concerned for the body of Patroclus, who will shortly become meat
+for the dogs and vultures of Troy, than for the safety of my own
+head and yours. Hector has wrapped us round in a storm of battle
+from every quarter, and our destruction seems now certain. Call
+then upon the princes of the Danaans if there is any who can hear
+us."
+</para>
+
+<para>
+Menelaus did as he said, and shouted to the Danaans for help at
+the top of his voice. "My friends," he cried, "princes and
+counsellors of the Argives, all you who with Agamemnon and
+Menelaus drink at the public cost, and give orders each to his
+own people as Jove vouchsafes him power and glory, the fight is
+so thick about me that I cannot distinguish you severally; come
+on, therefore, every man unbidden, and think it shame that
+Patroclus should become meat and morsel for Trojan hounds."
+</para>
+
+<para>
+Fleet Ajax son of Oileus heard him and was first to force his way
+through the fight and run to help him. Next came Idomeneus and
+Meriones his esquire, peer of murderous Mars. As for the others
+that came into the fight after these, who of his own self could
+name them?
+</para>
+
+<para>
+The Trojans with Hector at their head charged in a body. As a
+great wave that comes thundering in at the mouth of some
+heaven-born river, and the rocks that jut into the sea ring with
+the roar of the breakers that beat and buffet them--even with
+such a roar did the Trojans come on; but the Achaeans in
+singleness of heart stood firm about the son of Menoetius, and
+fenced him with their bronze shields. Jove, moreover, hid the
+brightness of their helmets in a thick cloud, for he had borne no
+grudge against the son of Menoetius while he was still alive and
+squire to the descendant of Aeacus; therefore he was loth to let
+him fall a prey to the dogs of his foes the Trojans, and urged
+his comrades on to defend him.
+</para>
+
+<para>
+At first the Trojans drove the Achaeans back, and they withdrew
+from the dead man daunted. The Trojans did not succeed in killing
+any one, nevertheless they drew the body away. But the Achaeans
+did not lose it long, for Ajax, foremost of all the Danaans after
+the son of Peleus alike in stature and prowess, quickly rallied
+them and made towards the front like a wild boar upon the
+mountains when he stands at bay in the forest glades and routs
+the hounds and lusty youths that have attacked him--even so did
+Ajax son of Telamon passing easily in among the phalanxes of the
+Trojans, disperse those who had bestridden Patroclus and were
+most bent on winning glory by dragging him off to their city. At
+this moment Hippothous brave son of the Pelasgian Lethus, in his
+zeal for Hector and the Trojans, was dragging the body off by the
+foot through the press of the fight, having bound a strap round
+the sinews near the ancle; but a mischief soon befell him from
+which none of those could save him who would have gladly done so,
+for the son of Telamon sprang forward and smote him on his
+bronze-cheeked helmet. The plumed headpiece broke about the point
+of the weapon, struck at once by the spear and by the strong hand
+of Ajax, so that the bloody brain came oozing out through the
+crest-socket. His strength then failed him and he let Patroclus'
+foot drop from his hand, as he fell full length dead upon the
+body; thus he died far from the fertile land of Larissa, and
+never repaid his parents the cost of bringing him up, for his
+life was cut short early by the spear of mighty Ajax. Hector then
+took aim at Ajax with a spear, but he saw it coming and just
+managed to avoid it; the spear passed on and struck Schedius son
+of noble Iphitus, captain of the Phoceans, who dwelt in famed
+Panopeus and reigned over much people; it struck him under the
+middle of the collar-bone the bronze point went right through
+him, coming out at the bottom of his shoulder-blade, and his
+armour rang rattling round him as he fell heavily to the ground.
+Ajax in his turn struck noble Phorcys son of Phaenops in the
+middle of the belly as he was bestriding Hippothous, and broke
+the plate of his cuirass; whereon the spear tore out his entrails
+and he clutched the ground in his palm as he fell to earth.
+Hector and those who were in the front rank then gave ground,
+while the Argives raised a loud cry of triumph, and drew off the
+bodies of Phorcys and Hippothous which they stripped presently of
+their armour.
+</para>
+
+<para>
+The Trojans would now have been worsted by the brave Achaeans and
+driven back to Ilius through their own cowardice, while the
+Argives, so great was their courage and endurance, would have
+achieved a triumph even against the will of Jove, if Apollo had
+not roused Aeneas, in the likeness of Periphas son of Epytus, an
+attendant who had grown old in the service of Aeneas' aged
+father, and was at all times devoted to him. In his likeness,
+then, Apollo said, "Aeneas, can you not manage, even though
+heaven be against us, to save high Ilius? I have known men, whose
+numbers, courage, and self-reliance have saved their people in
+spite of Jove, whereas in this case he would much rather give
+victory to us than to the Danaans, if you would only fight
+instead of being so terribly afraid."
+</para>
+
+<para>
+Aeneas knew Apollo when he looked straight at him, and shouted to
+Hector saying, "Hector and all other Trojans and allies, shame on
+us if we are beaten by the Achaeans and driven back to Ilius
+through our own cowardice. A god has just come up to me and told
+me that Jove the supreme disposer will be with us. Therefore let
+us make for the Danaans, that it may go hard with them ere they
+bear away dead Patroclus to the ships."
+</para>
+
+<para>
+As he spoke he sprang out far in front of the others, who then
+rallied and again faced the Achaeans. Aeneas speared Leiocritus
+son of Arisbas, a valiant follower of Lycomedes, and Lycomedes
+was moved with pity as he saw him fall; he therefore went close
+up, and speared Apisaon son of Hippasus shepherd of his people in
+the liver under the midriff, so that he died; he had come from
+fertile Paeonia and was the best man of them all after
+Asteropaeus. Asteropaeus flew forward to avenge him and attack
+the Danaans, but this might no longer be, inasmuch as those about
+Patroclus were well covered by their shields, and held their
+spears in front of them, for Ajax had given them strict orders
+that no man was either to give ground, or to stand out before the
+others, but all were to hold well together about the body and
+fight hand to hand. Thus did huge Ajax bid them, and the earth
+ran red with blood as the corpses fell thick on one another alike
+on the side of the Trojans and allies, and on that of the
+Danaans; for these last, too, fought no bloodless fight though
+many fewer of them perished, through the care they took to defend
+and stand by one another.
+</para>
+
+<para>
+Thus did they fight as it were a flaming fire; it seemed as
+though it had gone hard even with the sun and moon, for they were
+hidden over all that part where the bravest heroes were fighting
+about the dead son of Menoetius, whereas the other Danaans and
+Achaeans fought at their ease in full daylight with brilliant
+sunshine all round them, and there was not a cloud to be seen
+neither on plain nor mountain. These last moreover would rest for
+a while and leave off fighting, for they were some distance apart
+and beyond the range of one another's weapons, whereas those who
+were in the thick of the fray suffered both from battle and
+darkness. All the best of them were being worn out by the great
+weight of their armour, but the two valiant heroes, Thrasymedes
+and Antilochus, had not yet heard of the death of Patroclus, and
+believed him to be still alive and leading the van against the
+Trojans; they were keeping themselves in reserve against the
+death or rout of their own comrades, for so Nestor had ordered
+when he sent them from the ships into battle.
+</para>
+
+<para>
+Thus through the livelong day did they wage fierce war, and the
+sweat of their toil rained ever on their legs under them, and on
+their hands and eyes, as they fought over the squire of the fleet
+son of Peleus. It was as when a man gives a great ox-hide all
+drenched in fat to his men, and bids them stretch it; whereon
+they stand round it in a ring and tug till the moisture leaves
+it, and the fat soaks in for the many that pull at it, and it is
+well stretched--even so did the two sides tug the dead body
+hither and thither within the compass of but a little space--the
+Trojans steadfastly set on dragging it into Ilius, while the
+Achaeans were no less so on taking it to their ships; and fierce
+was the fight between them. Not Mars himself the lord of hosts,
+nor yet Minerva, even in their fullest fury could make light of
+such a battle.
+</para>
+
+<para>
+Such fearful turmoil of men and horses did Jove on that day
+ordain round the body of Patroclus. Meanwhile Achilles did not
+know that he had fallen, for the fight was under the wall of Troy
+a long way off the ships. He had no idea, therefore, that
+Patroclus was dead, and deemed that he would return alive as soon
+as he had gone close up to the gates. He knew that he was not to
+sack the city neither with nor without himself, for his mother
+had often told him this when he had sat alone with her, and she
+had informed him of the counsels of great Jove. Now, however, she
+had not told him how great a disaster had befallen him in the
+death of the one who was far dearest to him of all his comrades.
+</para>
+
+<para>
+The others still kept on charging one another round the body with
+their pointed spears and killing each other. Then would one say,
+"My friends, we can never again show our faces at the ships--
+better, and greatly better, that earth should open and swallow us
+here in this place, than that we should let the Trojans have the
+triumph of bearing off Patroclus to their city."
+</para>
+
+<para>
+The Trojans also on their part spoke to one another saying,
+"Friends, though we fall to a man beside this body, let none
+shrink from fighting." With such words did they exhort each
+other. They fought and fought, and an iron clank rose through the
+void air to the brazen vault of heaven. The horses of the
+descendant of Aeacus stood out of the fight and wept when they
+heard that their driver had been laid low by the hand of
+murderous Hector. Automedon, valiant son of Diores, lashed them
+again and again; many a time did he speak kindly to them, and
+many a time did he upbraid them, but they would neither go back
+to the ships by the waters of the broad Hellespont, nor yet into
+battle among the Achaeans; they stood with their chariot stock
+still, as a pillar set over the tomb of some dead man or woman,
+and bowed their heads to the ground. Hot tears fell from their
+eyes as they mourned the loss of their charioteer, and their
+noble manes drooped all wet from under the yokestraps on either
+side the yoke.
+</para>
+
+<para>
+The son of Saturn saw them and took pity upon their sorrow. He
+wagged his head, and muttered to himself, saying, "Poor things,
+why did we give you to King Peleus who is a mortal, while you are
+yourselves ageless and immortal? Was it that you might share the
+sorrows that befall mankind? for of all creatures that live and
+move upon the earth there is none so pitiable as he is--still,
+Hector son of Priam shall drive neither you nor your chariot. I
+will not have it. It is enough that he should have the armour
+over which he vaunts so vainly. Furthermore I will give you
+strength of heart and limb to bear Automedon safely to the ships
+from battle, for I shall let the Trojans triumph still further,
+and go on killing till they reach the ships; whereon night shall
+fall and darkness overshadow the land."
+</para>
+
+<para>
+As he spoke he breathed heart and strength into the horses so
+that they shook the dust from out of their manes, and bore their
+chariot swiftly into the fight that raged between Trojans and
+Achaeans. Behind them fought Automedon full of sorrow for his
+comrade, as a vulture amid a flock of geese. In and out, and here
+and there, full speed he dashed amid the throng of the Trojans,
+but for all the fury of his pursuit he killed no man, for he
+could not wield his spear and keep his horses in hand when alone
+in the chariot; at last, however, a comrade, Alcimedon, son of
+Laerces son of Haemon caught sight of him and came up behind his
+chariot. "Automedon," said he, "what god has put this folly into
+your heart and robbed you of your right mind, that you fight the
+Trojans in the front rank single-handed? He who was your comrade
+is slain, and Hector plumes himself on being armed in the armour
+of the descendant of Aeacus."
+</para>
+
+<para>
+Automedon son of Diores answered, "Alcimedon, there is no one
+else who can control and guide the immortal steeds so well as you
+can, save only Patroclus--while he was alive--peer of gods in
+counsel. Take then the whip and reins, while I go down from the
+car and fight."
+</para>
+
+<para>
+Alcimedon sprang on to the chariot, and caught up the whip and
+reins, while Automedon leaped from off the car. When Hector saw
+him he said to Aeneas who was near him, "Aeneas, counsellor of
+the mail-clad Trojans, I see the steeds of the fleet son of
+Aeacus come into battle with weak hands to drive them. I am sure,
+if you think well, that we might take them; they will not dare
+face us if we both attack them."
+</para>
+
+<para>
+The valiant son of Anchises was of the same mind, and the pair
+went right on, with their shoulders covered under shields of
+tough dry ox-hide, overlaid with much bronze. Chromius and Aretus
+went also with them, and their hearts beat high with hope that
+they might kill the men and capture the horses--fools that they
+were, for they were not to return scatheless from their meeting
+with Automedon, who prayed to father Jove and was forthwith
+filled with courage and strength abounding. He turned to his
+trusty comrade Alcimedon and said, "Alcimedon, keep your horses
+so close up that I may feel their breath upon my back; I doubt
+that we shall not stay Hector son of Priam till he has killed us
+and mounted behind the horses; he will then either spread panic
+among the ranks of the Achaeans, or himself be killed among the
+foremost."
+</para>
+
+<para>
+On this he cried out to the two Ajaxes and Menelaus, "Ajaxes
+captains of the Argives, and Menelaus, give the dead body over to
+them that are best able to defend it, and come to the rescue of
+us living; for Hector and Aeneas who are the two best men among
+the Trojans, are pressing us hard in the full tide of war.
+Nevertheless the issue lies on the lap of heaven, I will
+therefore hurl my spear and leave the rest to Jove."
+</para>
+
+<para>
+He poised and hurled as he spoke, whereon the spear struck the
+round shield of Aretus, and went right through it for the shield
+stayed it not, so that it was driven through his belt into the
+lower part of his belly. As when some sturdy youth, axe in hand,
+deals his blow behind the horns of an ox and severs the tendons
+at the back of its neck so that it springs forward and then
+drops, even so did Aretus give one bound and then fall on his
+back the spear quivering in his body till it made an end of him.
+Hector then aimed a spear at Automedon but he saw it coming and
+stooped forward to avoid it, so that it flew past him and the
+point stuck in the ground, while the butt-end went on quivering
+till Mars robbed it of its force. They would then have fought
+hand to hand with swords had not the two Ajaxes forced their way
+through the crowd when they heard their comrade calling, and
+parted them for all their fury--for Hector, Aeneas, and Chromius
+were afraid and drew back, leaving Aretus to lie there struck to
+the heart. Automedon, peer of fleet Mars, then stripped him of
+his armour and vaunted over him saying, "I have done little to
+assuage my sorrow for the son of Menoetius, for the man I have
+killed is not so good as he was."
+</para>
+
+<para>
+As he spoke he took the blood-stained spoils and laid them upon
+his chariot; then he mounted the car with his hands and feet all
+steeped in gore as a lion that has been gorging upon a bull.
+</para>
+
+<para>
+And now the fierce groanful fight again raged about Patroclus,
+for Minerva came down from heaven and roused its fury by the
+command of far-seeing Jove, who had changed his mind and sent her
+to encourage the Danaans. As when Jove bends his bright bow in
+heaven in token to mankind either of war or of the chill storms
+that stay men from their labour and plague the flocks--even so,
+wrapped in such radiant raiment, did Minerva go in among the host
+and speak man by man to each. First she took the form and voice
+of Phoenix and spoke to Menelaus son of Atreus, who was standing
+near her. "Menelaus," said she, "it will be shame and dishonour
+to you, if dogs tear the noble comrade of Achilles under the
+walls of Troy. Therefore be staunch, and urge your men to be so
+also."
+</para>
+
+<para>
+Menelaus answered, "Phoenix, my good old friend, may Minerva
+vouchsafe me strength and keep the darts from off me, for so
+shall I stand by Patroclus and defend him; his death has gone to
+my heart, but Hector is as a raging fire and deals his blows
+without ceasing, for Jove is now granting him a time of triumph."
+</para>
+
+<para>
+Minerva was pleased at his having named herself before any of the
+other gods. Therefore she put strength into his knees and
+shoulders, and made him as bold as a fly, which, though driven
+off will yet come again and bite if it can, so dearly does it
+love man's blood--even so bold as this did she make him as he
+stood over Patroclus and threw his spear. Now there was among the
+Trojans a man named Podes, son of Eetion, who was both rich and
+valiant. Hector held him in the highest honour for he was his
+comrade and boon companion; the spear of Menelaus struck this man
+in the girdle just as he had turned in flight, and went right
+through him. Whereon he fell heavily forward, and Menelaus son of
+Atreus drew off his body from the Trojans into the ranks of his
+own people.
+</para>
+
+<para>
+Apollo then went up to Hector and spurred him on to fight, in the
+likeness of Phaenops son of Asius who lived in Abydos and was the
+most favoured of all Hector's guests. In his likeness Apollo
+said, "Hector, who of the Achaeans will fear you henceforward now
+that you have quailed before Menelaus who has ever been rated
+poorly as a soldier? Yet he has now got a corpse away from the
+Trojans single-handed, and has slain your own true comrade, a man
+brave among the foremost, Podes son of Eetion."
+</para>
+
+<para>
+A dark cloud of grief fell upon Hector as he heard, and he made
+his way to the front clad in full armour. Thereon the son of
+Saturn seized his bright tasselled aegis, and veiled Ida in
+cloud: he sent forth his lightnings and his thunders, and as he
+shook his aegis he gave victory to the Trojans and routed the
+Achaeans.
+</para>
+
+<para>
+The panic was begun by Peneleos the Boeotian, for while keeping
+his face turned ever towards the foe he had been hit with a spear
+on the upper part of the shoulder; a spear thrown by Polydamas
+had grazed the top of the bone, for Polydamas had come up to him
+and struck him from close at hand. Then Hector in close combat
+struck Leitus son of noble Alectryon in the hand by the wrist,
+and disabled him from fighting further. He looked about him in
+dismay, knowing that never again should he wield spear in battle
+with the Trojans. While Hector was in pursuit of Leitus,
+Idomeneus struck him on the breastplate over his chest near the
+nipple; but the spear broke in the shaft, and the Trojans cheered
+aloud. Hector then aimed at Idomeneus son of Deucalion as he was
+standing on his chariot, and very narrowly missed him, but the
+spear hit Coiranus, a follower and charioteer of Meriones who had
+come with him from Lyctus. Idomeneus had left the ships on foot
+and would have afforded a great triumph to the Trojans if
+Coiranus had not driven quickly up to him, he therefore brought
+life and rescue to Idomeneus, but himself fell by the hand of
+murderous Hector. For Hector hit him on the jaw under the ear;
+the end of the spear drove out his teeth and cut his tongue in
+two pieces, so that he fell from his chariot and let the reins
+fall to the ground. Meriones gathered them up from the ground and
+took them into his own hands, then he said to Idomeneus, "Lay on,
+till you get back to the ships, for you must see that the day is
+no longer ours."
+</para>
+
+<para>
+On this Idomeneus lashed the horses to the ships, for fear had
+taken hold upon him.
+</para>
+
+<para>
+Ajax and Menelaus noted how Jove had turned the scale in favour
+of the Trojans, and Ajax was first to speak. "Alas," said he,
+"even a fool may see that father Jove is helping the Trojans. All
+their weapons strike home; no matter whether it be a brave man or
+a coward that hurls them, Jove speeds all alike, whereas ours
+fall each one of them without effect. What, then, will be best
+both as regards rescuing the body, and our return to the joy of
+our friends who will be grieving as they look hitherwards; for
+they will make sure that nothing can now check the terrible hands
+of Hector, and that he will fling himself upon our ships. I wish
+that some one would go and tell the son of Peleus at once, for I
+do not think he can have yet heard the sad news that the dearest
+of his friends has fallen. But I can see not a man among the
+Achaeans to send, for they and their chariots are alike hidden in
+darkness. O father Jove, lift this cloud from over the sons of
+the Achaeans; make heaven serene, and let us see; if you will
+that we perish, let us fall at any rate by daylight."
+</para>
+
+<para>
+Father Jove heard him and had compassion upon his tears.
+Forthwith he chased away the cloud of darkness, so that the sun
+shone out and all the fighting was revealed. Ajax then said to
+Menelaus, "Look, Menelaus, and if Antilochus son of Nestor be
+still living, send him at once to tell Achilles that by far the
+dearest to him of all his comrades has fallen."
+</para>
+
+<para>
+Menelaus heeded his words and went his way as a lion from a
+stockyard--the lion is tired of attacking the men and hounds, who
+keep watch the whole night through and will not let him feast on
+the fat of their herd. In his lust of meat he makes straight at
+them but in vain, for darts from strong hands assail him, and
+burning brands which daunt him for all his hunger, so in the
+morning he slinks sulkily away--even so did Menelaus sorely
+against his will leave Patroclus, in great fear lest the Achaeans
+should be driven back in rout and let him fall into the hands of
+the foe. He charged Meriones and the two Ajaxes straitly saying,
+"Ajaxes and Meriones, leaders of the Argives, now indeed remember
+how good Patroclus was; he was ever courteous while alive, bear
+it in mind now that he is dead."
+</para>
+
+<para>
+With this Menelaus left them, looking round him as keenly as an
+eagle, whose sight they say is keener than that of any other
+bird--however high he may be in the heavens, not a hare that runs
+can escape him by crouching under bush or thicket, for he will
+swoop down upon it and make an end of it--even so, O Menelaus,
+did your keen eyes range round the mighty host of your followers
+to see if you could find the son of Nestor still alive. Presently
+Menelaus saw him on the extreme left of the battle cheering on
+his men and exhorting them to fight boldly. Menelaus went up to
+him and said, "Antilochus, come here and listen to sad news,
+which I would indeed were untrue. You must see with your own eyes
+that heaven is heaping calamity upon the Danaans, and giving
+victory to the Trojans. Patroclus has fallen, who was the bravest
+of the Achaeans, and sorely will the Danaans miss him. Run
+instantly to the ships and tell Achilles, that he may come to
+rescue the body and bear it to the ships. As for the armour,
+Hector already has it."
+</para>
+
+<para>
+Antilochus was struck with horror. For a long time he was
+speechless; his eyes filled with tears and he could find no
+utterance, but he did as Menelaus had said, and set off running
+as soon as he had given his armour to a comrade, Laodocus, who
+was wheeling his horses round, close beside him.
+</para>
+
+<para>
+Thus, then, did he run weeping from the field, to carry the bad
+news to Achilles son of Peleus. Nor were you, O Menelaus, minded
+to succour his harassed comrades, when Antilochus had left the
+Pylians--and greatly did they miss him--but he sent them noble
+Thrasymedes, and himself went back to Patroclus. He came running
+up to the two Ajaxes and said, "I have sent Antilochus to the
+ships to tell Achilles, but rage against Hector as he may, he
+cannot come, for he cannot fight without armour. What then will
+be our best plan both as regards rescuing the dead, and our own
+escape from death amid the battle-cries of the Trojans?"
+</para>
+
+<para>
+Ajax answered, "Menelaus, you have said well: do you, then, and
+Meriones stoop down, raise the body, and bear it out of the fray,
+while we two behind you keep off Hector and the Trojans, one in
+heart as in name, and long used to fighting side by side with one
+another."
+</para>
+
+<para>
+On this Menelaus and Meriones took the dead man in their arms and
+lifted him high aloft with a great effort. The Trojan host raised
+a hue and cry behind them when they saw the Achaeans bearing the
+body away, and flew after them like hounds attacking a wounded
+boar at the loo of a band of young huntsmen. For a while the
+hounds fly at him as though they would tear him in pieces, but
+now and again he turns on them in a fury, scaring and scattering
+them in all directions--even so did the Trojans for a while
+charge in a body, striking with sword and with spears pointed ai
+both the ends, but when the two Ajaxes faced them and stood at
+bay, they would turn pale and no man dared press on to fight
+further about the dead.
+</para>
+
+<para>
+In this wise did the two heroes strain every nerve to bear the
+body to the ships out of the fight. The battle raged round them
+like fierce flames that when once kindled spread like wildfire
+over a city, and the houses fall in the glare of its burning--
+even such was the roar and tramp of men and horses that pursued
+them as they bore Patroclus from the field. Or as mules that put
+forth all their strength to draw some beam or great piece of
+ship's timber down a rough mountain-track, and they pant and
+sweat as they, go even so did Menelaus and pant and sweat as they
+bore the body of Patroclus. Behind them the two Ajaxes held
+stoutly out. As some wooded mountain-spur that stretches across a
+plain will turn water and check the flow even of a great river,
+nor is there any stream strong enough to break through it--even
+so did the two Ajaxes face the Trojans and stem the tide of their
+fighting though they kept pouring on towards them and foremost
+among them all was Aeneas son of Anchises with valiant Hector. As
+a flock of daws or starlings fall to screaming and chattering
+when they see a falcon, foe to all small birds, come soaring near
+them, even so did the Achaean youth raise a babel of cries as
+they fled before Aeneas and Hector, unmindful of their former
+prowess. In the rout of the Danaans much goodly armour fell round
+about the trench, and of fighting there was no end.
+</para>
+</chapter>
+
+<chapter>
+<title>BOOK XVIII</title>
+
+<para>
+THUS then did they fight as it were a flaming fire. Meanwhile the
+fleet runner Antilochus, who had been sent as messenger, reached
+Achilles, and found him sitting by his tall ships and boding that
+which was indeed too surely true. "Alas," said he to himself in
+the heaviness of his heart, "why are the Achaeans again scouring
+the plain and flocking towards the ships? Heaven grant the gods
+be not now bringing that sorrow upon me of which my mother Thetis
+spoke, saying that while I was yet alive the bravest of the
+Myrmidons should fall before the Trojans, and see the light of
+the sun no longer. I fear the brave son of Menoetius has fallen
+through his own daring and yet I bade him return to the ships as
+soon as he had driven back those that were bringing fire against
+them, and not join battle with Hector."
+</para>
+
+<para>
+As he was thus pondering, the son of Nestor came up to him and
+told his sad tale, weeping bitterly the while. "Alas," he cried,
+"son of noble Peleus, I bring you bad tidings, would indeed that
+they were untrue. Patroclus has fallen, and a fight is raging
+about his naked body--for Hector holds his armour."
+</para>
+
+<para>
+A dark cloud of grief fell upon Achilles as he listened. He
+filled both hands with dust from off the ground, and poured it
+over his head, disfiguring his comely face, and letting the
+refuse settle over his shirt so fair and new. He flung himself
+down all huge and hugely at full length, and tore his hair with
+his hands. The bondswomen whom Achilles and Patroclus had taken
+captive screamed aloud for grief, beating their breasts, and with
+their limbs failing them for sorrow. Antilochus bent over him the
+while, weeping and holding both his hands as he lay groaning for
+he feared that he might plunge a knife into his own throat. Then
+Achilles gave a loud cry and his mother heard him as she was
+sitting in the depths of the sea by the old man her father,
+whereon she screamed, and all the goddesses daughters of Nereus
+that dwelt at the bottom of the sea, came gathering round her.
+There were Glauce, Thalia and Cymodoce, Nesaia, Speo, Thoe and
+dark-eyed Halie, Cymothoe, Actaea and Limnorea, Melite, Iaera,
+Amphithoe and Agave, Doto and Proto, Pherusa and Dynamene,
+Dexamene, Amphinome and Callianeira, Doris, Panope, and the
+famous sea-nymph Galatea, Nemertes, Apseudes and Callianassa.
+There were also Clymene, Ianeira and Ianassa, Maera, Oreithuia
+and Amatheia of the lovely locks, with other Nereids who dwell in
+the depths of the sea. The crystal cave was filled with their
+multitude and they all beat their breasts while Thetis led them
+in their lament.
+</para>
+
+<para>
+"Listen," she cried, "sisters, daughters of Nereus, that you may
+hear the burden of my sorrows. Alas, woe is me, woe in that I
+have borne the most glorious of offspring. I bore him fair and
+strong, hero among heroes, and he shot up as a sapling; I tended
+him as a plant in a goodly garden, and sent him with his ships to
+Ilius to fight the Trojans, but never shall I welcome him back to
+the house of Peleus. So long as he lives to look upon the light
+of the sun he is in heaviness, and though I go to him I cannot
+help him. Nevertheless I will go, that I may see my dear son and
+learn what sorrow has befallen him though he is still holding
+aloof from battle."
+</para>
+
+<para>
+She left the cave as she spoke, while the others followed weeping
+after, and the waves opened a path before them. When they reached
+the rich plain of Troy, they came up out of the sea in a long
+line on to the sands, at the place where the ships of the
+Myrmidons were drawn up in close order round the tents of
+Achilles. His mother went up to him as he lay groaning; she laid
+her hand upon his head and spoke piteously, saying, "My son, why
+are you thus weeping? What sorrow has now befallen you? Tell me;
+hide it not from me. Surely Jove has granted you the prayer you
+made him, when you lifted up your hands and besought him that the
+Achaeans might all of them be pent up at their ships, and rue it
+bitterly in that you were no longer with them."
+</para>
+
+<para>
+Achilles groaned and answered, "Mother, Olympian Jove has indeed
+vouchsafed me the fulfilment of my prayer, but what boots it to
+me, seeing that my dear comrade Patroclus has fallen--he whom I
+valued more than all others, and loved as dearly as my own life?
+I have lost him; aye, and Hector when he had killed him stripped
+the wondrous armour, so glorious to behold, which the gods gave
+to Peleus when they laid you in the couch of a mortal man. Would
+that you were still dwelling among the immortal sea-nymphs, and
+that Peleus had taken to himself some mortal bride. For now you
+shall have grief infinite by reason of the death of that son whom
+you can never welcome home--nay, I will not live nor go about
+among mankind unless Hector fall by my spear, and thus pay me for
+having slain Patroclus son of Menoetius."
+</para>
+
+<para>
+Thetis wept and answered, "Then, my son, is your end near at
+hand--for your own death awaits you full soon after that of
+Hector."
+</para>
+
+<para>
+Then said Achilles in his great grief, "I would die here and now,
+in that I could not save my comrade. He has fallen far from home,
+and in his hour of need my hand was not there to help him. What
+is there for me? Return to my own land I shall not, and I have
+brought no saving neither to Patroclus nor to my other comrades
+of whom so many have been slain by mighty Hector; I stay here by
+my ships a bootless burden upon the earth, I, who in fight have
+no peer among the Achaeans, though in council there are better
+than I. Therefore, perish strife both from among gods and men,
+and anger, wherein even a righteous man will harden his
+heart--which rises up in the soul of a man like smoke, and the
+taste thereof is sweeter than drops of honey. Even so has
+Agamemnon angered me. And yet--so be it, for it is over; I will
+force my soul into subjection as I needs must; I will go; I will
+pursue Hector who has slain him whom I loved so dearly, and will
+then abide my doom when it may please Jove and the other gods to
+send it. Even Hercules, the best beloved of Jove--even he could
+not escape the hand of death, but fate and Juno's fierce anger
+laid him low, as I too shall lie when I am dead if a like doom
+awaits me. Till then I will win fame, and will bid Trojan and
+Dardanian women wring tears from their tender cheeks with both
+their hands in the grievousness of their great sorrow; thus shall
+they know that he who has held aloof so long will hold aloof no
+longer. Hold me not back, therefore, in the love you bear me, for
+you shall not move me."
+</para>
+
+<para>
+Then silver-footed Thetis answered, "My son, what you have said
+is true. It is well to save your comrades from destruction, but
+your armour is in the hands of the Trojans; Hector bears it in
+triumph upon his own shoulders. Full well I know that his vaunt
+shall not be lasting, for his end is close at hand; go not,
+however, into the press of battle till you see me return hither;
+to-morrow at break of day I shall be here, and will bring you
+goodly armour from King Vulcan."
+</para>
+
+<para>
+On this she left her brave son, and as she turned away she said
+to the sea-nymphs her sisters, "Dive into the bosom of the sea
+and go to the house of the old sea-god my father. Tell him
+everything; as for me, I will go to the cunning workman Vulcan on
+high Olympus, and ask him to provide my son with a suit of
+splendid armour."
+</para>
+
+<para>
+When she had so said, they dived forthwith beneath the waves,
+while silver-footed Thetis went her way that she might bring the
+armour for her son.
+</para>
+
+<para>
+Thus, then, did her feet bear the goddess to Olympus, and
+meanwhile the Achaeans were flying with loud cries before
+murderous Hector till they reached the ships and the Hellespont,
+and they could not draw the body of Mars's servant Patroclus out
+of reach of the weapons that were showered upon him, for Hector
+son of Priam with his host and horsemen had again caught up to
+him like the flame of a fiery furnace; thrice did brave Hector
+seize him by the feet, striving with might and main to draw him
+away and calling loudly on the Trojans, and thrice did the two
+Ajaxes, clothed in valour as with a garment, beat him from off
+the body; but all undaunted he would now charge into the thick of
+the fight, and now again he would stand still and cry aloud, but
+he would give no ground. As upland shepherds that cannot chase
+some famished lion from a carcase, even so could not the two
+Ajaxes scare Hector son of Priam from the body of Patroclus.
+</para>
+
+<para>
+And now he would even have dragged it off and have won
+imperishable glory, had not Iris fleet as the wind, winged her
+way as messenger from Olympus to the son of Peleus and bidden him
+arm. She came secretly without the knowledge of Jove and of the
+other gods, for Juno sent her, and when she had got close to him
+she said, "Up, son of Peleus, mightiest of all mankind; rescue
+Patroclus about whom this fearful fight is now raging by the
+ships. Men are killing one another, the Danaans in defence of the
+dead body, while the Trojans are trying to hale it away, and take
+it to windy Ilius: Hector is the most furious of them all; he is
+for cutting the head from the body and fixing it on the stakes of
+the wall. Up, then, and bide here no longer; shrink from the
+thought that Patroclus may become meat for the dogs of Troy.
+Shame on you, should his body suffer any kind of outrage."
+</para>
+
+<para>
+And Achilles said, "Iris, which of the gods was it that sent you
+to me?"
+</para>
+
+<para>
+Iris answered, "It was Juno the royal spouse of Jove, but the son
+of Saturn does not know of my coming, nor yet does any other of
+the immortals who dwell on the snowy summits of Olympus."
+</para>
+
+<para>
+Then fleet Achilles answered her saying, "How can I go up into
+the battle? They have my armour. My mother forbade me to arm till
+I should see her come, for she promised to bring me goodly armour
+from Vulcan; I know no man whose arms I can put on, save only the
+shield of Ajax son of Telamon, and he surely must be fighting in
+the front rank and wielding his spear about the body of dead
+Patroclus."
+</para>
+
+<para>
+Iris said, "We know that your armour has been taken, but go as
+you are; go to the deep trench and show yourself before the
+Trojans, that they may fear you and cease fighting. Thus will the
+fainting sons of the Achaeans gain some brief breathing-time,
+which in battle may hardly be."
+</para>
+
+<para>
+Iris left him when she had so spoken. But Achilles dear to Jove
+arose, and Minerva flung her tasselled aegis round his strong
+shoulders; she crowned his head with a halo of golden cloud from
+which she kindled a glow of gleaming fire. As the smoke that goes
+up into heaven from some city that is being beleaguered on an
+island far out at sea--all day long do men sally from the city
+and fight their hardest, and at the going down of the sun the
+line of beacon-fires blazes forth, flaring high for those that
+dwell near them to behold, if so be that they may come with their
+ships and succour them--even so did the light flare from the head
+of Achilles, as he stood by the trench, going beyond the wall--
+but he aid not join the Achaeans for he heeded the charge which
+his mother laid upon him.
+</para>
+
+<para>
+There did he stand and shout aloud. Minerva also raised her voice
+from afar, and spread terror unspeakable among the Trojans.
+Ringing as the note of a trumpet that sounds alarm then the foe
+is at the gates of a city, even so brazen was the voice of the
+son of Aeacus, and when the Trojans heard its clarion tones they
+were dismayed; the horses turned back with their chariots for
+they boded mischief, and their drivers were awe-struck by the
+steady flame which the grey-eyed goddess had kindled above the
+head of the great son of Peleus.
+</para>
+
+<para>
+Thrice did Achilles raise his loud cry as he stood by the trench,
+and thrice were the Trojans and their brave allies thrown into
+confusion; whereon twelve of their noblest champions fell beneath
+the wheels of their chariots and perished by their own spears.
+The Achaeans to their great joy then drew Patroclus out of reach
+of the weapons, and laid him on a litter: his comrades stood
+mourning round him, and among them fleet Achilles who wept
+bitterly as he saw his true comrade lying dead upon his bier. He
+had sent him out with horses and chariots into battle, but his
+return he was not to welcome.
+</para>
+
+<para>
+Then Juno sent the busy sun, loth though he was, into the waters
+of Oceanus; so he set, and the Achaeans had rest from the tug and
+turmoil of war.
+</para>
+
+<para>
+Now the Trojans when they had come out of the fight, unyoked
+their horses and gathered in assembly before preparing their
+supper. They kept their feet, nor would any dare to sit down, for
+fear had fallen upon them all because Achilles had shown himself
+after having held aloof so long from battle. Polydamas son of
+Panthous was first to speak, a man of judgement, who alone among
+them could look both before and after. He was comrade to Hector,
+and they had been born upon the same night; with all sincerity
+and goodwill, therefore, he addressed them thus:--
+</para>
+
+<para>
+"Look to it well, my friends; I would urge you to go back now to
+your city and not wait here by the ships till morning, for we are
+far from our walls. So long as this man was at enmity with
+Agamemnon the Achaeans were easier to deal with, and I would have
+gladly camped by the ships in the hope of taking them; but now I
+go in great fear of the fleet son of Peleus; he is so daring that
+he will never bide here on the plain whereon the Trojans and
+Achaeans fight with equal valour, but he will try to storm our
+city and carry off our women. Do then as I say, and let us
+retreat. For this is what will happen. The darkness of night will
+for a time stay the son of Peleus, but if he find us here in the
+morning when he sallies forth in full armour, we shall have
+knowledge of him in good earnest. Glad indeed will he be who can
+escape and get back to Ilius, and many a Trojan will become meat
+for dogs and vultures may I never live to hear it. If we do as I
+say, little though we may like it, we shall have strength in
+counsel during the night, and the great gates with the doors that
+close them will protect the city. At dawn we can arm and take our
+stand on the walls; he will then rue it if he sallies from the
+ships to fight us. He will go back when he has given his horses
+their fill of being driven all whithers under our walls, and will
+be in no mind to try and force his way into the city. Neither
+will he ever sack it, dogs shall devour him ere he do so."
+</para>
+
+<para>
+Hector looked fiercely at him and answered, "Polydamas, your
+words are not to my liking in that you bid us go back and be pent
+within the city. Have you not had enough of being cooped up
+behind walls? In the old-days the city of Priam was famous the
+whole world over for its wealth of gold and bronze, but our
+treasures are wasted out of our houses, and much goods have been
+sold away to Phrygia and fair Meonia, for the hand of Jove has
+been laid heavily upon us. Now, therefore, that the son of
+scheming Saturn has vouchsafed me to win glory here and to hem
+the Achaeans in at their ships, prate no more in this fool's wise
+among the people. You will have no man with you; it shall not be;
+do all of you as I now say;--take your suppers in your companies
+throughout the host, and keep your watches and be wakeful every
+man of you. If any Trojan is uneasy about his possessions, let
+him gather them and give them out among the people. Better let
+these, rather than the Achaeans, have them. At daybreak we will
+arm and fight about the ships; granted that Achilles has again
+come forward to defend them, let it be as he will, but it shall
+go hard with him. I shall not shun him, but will fight him, to
+fall or conquer. The god of war deals out like measure to all,
+and the slayer may yet be slain."
+</para>
+
+<para>
+Thus spoke Hector; and the Trojans, fools that they were, shouted
+in applause, for Pallas Minerva had robbed them of their
+understanding. They gave ear to Hector with his evil counsel, but
+the wise words of Polydamas no man would heed. They took their
+supper throughout the host, and meanwhile through the whole night
+the Achaeans mourned Patroclus, and the son of Peleus led them in
+their lament. He laid his murderous hands upon the breast of his
+comrade, groaning again and again as a bearded lion when a man
+who was chasing deer has robbed him of his young in some dense
+forest; when the lion comes back he is furious, and searches
+dingle and dell to track the hunter if he can find him, for he is
+mad with rage--even so with many a sigh did Achilles speak among
+the Myrmidons saying, "Alas! vain were the words with which I
+cheered the hero Menoetius in his own house; I said that I would
+bring his brave son back again to Opoeis after he had sacked
+Ilius and taken his share of the spoils--but Jove does not give
+all men their heart's desire. The same soil shall be reddened
+here at Troy by the blood of us both, for I too shall never be
+welcomed home by the old knight Peleus, nor by my mother Thetis,
+but even in this place shall the earth cover me. Nevertheless, O
+Patroclus, now that I am left behind you, I will not bury you,
+till I have brought hither the head and armour of mighty Hector
+who has slain you. Twelve noble sons of Trojans will I behead
+before your bier to avenge you; till I have done so you shall lie
+as you are by the ships, and fair women of Troy and Dardanus,
+whom we have taken with spear and strength of arm when we sacked
+men's goodly cities, shall weep over you both night and day."
+</para>
+
+<para>
+Then Achilles told his men to set a large tripod upon the fire
+that they might wash the clotted gore from off Patroclus. Thereon
+they set a tripod full of bath water on to a clear fire: they
+threw sticks on to it to make it blaze, and the water became hot
+as the flame played about the belly of the tripod. When the water
+in the cauldron was boiling they washed the body, anointed it
+with oil, and closed its wounds with ointment that had been kept
+nine years. Then they laid it on a bier and covered it with a
+linen cloth from head to foot, and over this they laid a fair
+white robe. Thus all night long did the Myrmidons gather round
+Achilles to mourn Patroclus.
+</para>
+
+<para>
+Then Jove said to Juno his sister-wife, "So, Queen Juno, you have
+gained your end, and have roused fleet Achilles. One would think
+that the Achaeans were of your own flesh and blood."
+</para>
+
+<para>
+And Juno answered, "Dread son of Saturn, why should you say this
+thing? May not a man though he be only mortal and knows less than
+we do, do what he can for another person? And shall not I--
+foremost of all goddesses both by descent and as wife to you who
+reign in heaven--devise evil for the Trojans if I am angry with
+them?"
+</para>
+
+<para>
+Thus did they converse. Meanwhile Thetis came to the house of
+Vulcan, imperishable, star-bespangled, fairest of the abodes in
+heaven, a house of bronze wrought by the lame god's own hands.
+She found him busy with his bellows, sweating and hard at work,
+for he was making twenty tripods that were to stand by the wall
+of his house, and he set wheels of gold under them all that they
+might go of their own selves to the assemblies of the gods, and
+come back again--marvels indeed to see. They were finished all
+but the ears of cunning workmanship which yet remained to be
+fixed to them: these he was now fixing, and he was hammering at
+the rivets. While he was thus at work silver-footed Thetis came
+to the house. Charis, of graceful head-dress, wife to the
+far-famed lame god, came towards her as soon as she saw her, and
+took her hand in her own, saying, "Why have you come to our
+house, Thetis, honoured and ever welcome--for you do not visit us
+often? Come inside and let me set refreshment before you."
+</para>
+
+<para>
+The goddess led the way as she spoke, and bade Thetis sit on a
+richly decorated seat inlaid with silver; there was a footstool
+also under her feet. Then she called Vulcan and said, "Vulcan,
+come here, Thetis wants you"; and the far-famed lame god
+answered, "Then it is indeed an august and honoured goddess who
+has come here; she it was that took care of me when I was
+suffering from the heavy fall which I had through my cruel
+mother's anger--for she would have got rid of me because I was
+lame. It would have gone hardly with me had not Eurynome,
+daughter of the ever-encircling waters of Oceanus, and Thetis,
+taken me to their bosom. Nine years did I stay with them, and
+many beautiful works in bronze, brooches, spiral armlets, cups,
+and chains, did I make for them in their cave, with the roaring
+waters of Oceanus foaming as they rushed ever past it; and no one
+knew, neither of gods nor men, save only Thetis and Eurynome who
+took care of me. If, then, Thetis has come to my house I must
+make her due requital for having saved me; entertain her,
+therefore, with all hospitality, while I put by my bellows and
+all my tools."
+</para>
+
+<para>
+On this the mighty monster hobbled off from his anvil, his thin
+legs plying lustily under him. He set the bellows away from the
+fire, and gathered his tools into a silver chest. Then he took a
+sponge and washed his face and hands, his shaggy chest and brawny
+neck; he donned his shirt, grasped his strong staff, and limped
+towards the door. There were golden handmaids also who worked for
+him, and were like real young women, with sense and reason, voice
+also and strength, and all the learning of the immortals; these
+busied themselves as the king bade them, while he drew near to
+Thetis, seated her upon a goodly seat, and took her hand in his
+own, saying, "Why have you come to our house, Thetis honoured and
+ever welcome--for you do not visit us often? Say what you want,
+and I will do it for you at once if I can, and if it can be done
+at all."
+</para>
+
+<para>
+Thetis wept and answered, "Vulcan, is there another goddess in
+Olympus whom the son of Saturn has been pleased to try with so
+much affliction as he has me? Me alone of the marine goddesses
+did he make subject to a mortal husband, Peleus son of Aeacus,
+and sorely against my will did I submit to the embraces of one
+who was but mortal, and who now stays at home worn out with age.
+Neither is this all. Heaven vouchsafed me a son, hero among
+heroes, and he shot up as a sapling. I tended him as a plant in a
+goodly garden and sent him with his ships to Ilius to fight the
+Trojans, but never shall I welcome him back to the house of
+Peleus. So long as he lives to look upon the light of the sun, he
+is in heaviness, and though I go to him I cannot help him; King
+Agamemnon has made him give up the maiden whom the sons of the
+Achaeans had awarded him, and he wastes with sorrow for her sake.
+Then the Trojans hemmed the Achaeans in at their ships' sterns
+and would not let them come forth; the elders, therefore, of the
+Argives besought Achilles and offered him great treasure, whereon
+he refused to bring deliverance to them himself, but put his own
+armour on Patroclus and sent him into the fight with much people
+after him. All day long they fought by the Scaean gates and would
+have taken the city there and then, had not Apollo vouchsafed
+glory to Hector and slain the valiant son of Menoetius after he
+had done the Trojans much evil. Therefore I am suppliant at your
+knees if haply you may be pleased to provide my son, whose end is
+near at hand, with helmet and shield, with goodly greaves fitted
+with ancle-clasps, and with a breastplate, for he lost his own
+when his true comrade fell at the hands of the Trojans, and he
+now lies stretched on earth in the bitterness of his soul."
+</para>
+
+<para>
+And Vulcan answered, "Take heart, and be no more disquieted about
+this matter; would that I could hide him from death's sight when
+his hour is come, so surely as I can find him armour that shall
+amaze the eyes of all who behold it."
+</para>
+
+<para>
+When he had so said he left her and went to his bellows, turning
+them towards the fire and bidding them do their office. Twenty
+bellows blew upon the melting-pots, and they blew blasts of every
+kind, some fierce to help him when he had need of them, and
+others less strong as Vulcan willed it in the course of his work.
+He threw tough copper into the fire, and tin, with silver and
+gold; he set his great anvil on its block, and with one hand
+grasped his mighty hammer while he took the tongs in the other.
+</para>
+
+<para>
+First he shaped the shield so great and strong, adorning it all
+over and binding it round with a gleaming circuit in three
+layers; and the baldric was made of silver. He made the shield in
+five thicknesses, and with many a wonder did his cunning hand
+enrich it.
+</para>
+
+<para>
+He wrought the earth, the heavens, and the sea; the moon also at
+her full and the untiring sun, with all the signs that glorify
+the face of heaven--the Pleiads, the Hyads, huge Orion, and the
+Bear, which men also call the Wain and which turns round ever in
+one place, facing. Orion, and alone never dips into the stream of
+Oceanus.
+</para>
+
+<para>
+He wrought also two cities, fair to see and busy with the hum of
+men. In the one were weddings and wedding-feasts, and they were
+going about the city with brides whom they were escorting by
+torchlight from their chambers. Loud rose the cry of Hymen, and
+the youths danced to the music of flute and lyre, while the women
+stood each at her house door to see them.
+</para>
+
+<para>
+Meanwhile the people were gathered in assembly, for there was a
+quarrel, and two men were wrangling about the blood-money for a
+man who had been killed, the one saying before the people that he
+had paid damages in full, and the other that he had not been
+paid. Each was trying to make his own case good, and the people
+took sides, each man backing the side that he had taken; but the
+heralds kept them back, and the elders sate on their seats of
+stone in a solemn circle, holding the staves which the heralds
+had put into their hands. Then they rose and each in his turn
+gave judgement, and there were two talents laid down, to be given
+to him whose judgement should be deemed the fairest.
+</para>
+
+<para>
+About the other city there lay encamped two hosts in gleaming
+armour, and they were divided whether to sack it, or to spare it
+and accept the half of what it contained. But the men of the city
+would not yet consent, and armed themselves for a surprise; their
+wives and little children kept guard upon the walls, and with
+them were the men who were past fighting through age; but the
+others sallied forth with Mars and Pallas Minerva at their head--
+both of them wrought in gold and clad in golden raiment, great
+and fair with their armour as befitting gods, while they that
+followed were smaller. When they reached the place where they
+would lay their ambush, it was on a riverbed to which live stock
+of all kinds would come from far and near to water; here, then,
+they lay concealed, clad in full armour. Some way off them there
+were two scouts who were on the look-out for the coming of sheep
+or cattle, which presently came, followed by two shepherds who
+were playing on their pipes, and had not so much as a thought of
+danger. When those who were in ambush saw this, they cut off the
+flocks and herds and killed the shepherds. Meanwhile the
+besiegers, when they heard much noise among the cattle as they
+sat in council, sprang to their horses, and made with all speed
+towards them; when they reached them they set battle in array by
+the banks of the river, and the hosts aimed their bronze-shod
+spears at one another. With them were Strife and Riot, and fell
+Fate who was dragging three men after her, one with a fresh
+wound, and the other unwounded, while the third was dead, and she
+was dragging him along by his heel: and her robe was bedrabbled
+in men's blood. They went in and out with one another and fought
+as though they were living people haling away one another's dead.
+</para>
+
+<para>
+He wrought also a fair fallow field, large and thrice ploughed
+already. Many men were working at the plough within it, turning
+their oxen to and fro, furrow after furrow. Each time that they
+turned on reaching the headland a man would come up to them and
+give them a cup of wine, and they would go back to their furrows
+looking forward to the time when they should again reach the
+headland. The part that they had ploughed was dark behind them,
+so that the field, though it was of gold, still looked as if it
+were being ploughed--very curious to behold.
+</para>
+
+<para>
+He wrought also a field of harvest corn, and the reapers were
+reaping with sharp sickles in their hands. Swathe after swathe
+fell to the ground in a straight line behind them, and the
+binders bound them in bands of twisted straw. There were three
+binders, and behind them there were boys who gathered the cut
+corn in armfuls and kept on bringing them to be bound: among them
+all the owner of the land stood by in silence and was glad. The
+servants were getting a meal ready under an oak, for they had
+sacrificed a great ox, and were busy cutting him up, while the
+women were making a porridge of much white barley for the
+labourers' dinner.
+</para>
+
+<para>
+He wrought also a vineyard, golden and fair to see, and the vines
+were loaded with grapes. The bunches overhead were black, but the
+vines were trained on poles of silver. He ran a ditch of dark
+metal all round it, and fenced it with a fence of tin; there was
+only one path to it, and by this the vintagers went when they
+would gather the vintage. Youths and maidens all blithe and full
+of glee, carried the luscious fruit in plaited baskets; and with
+them there went a boy who made sweet music with his lyre, and
+sang the Linos-song with his clear boyish voice.
+</para>
+
+<para>
+He wrought also a herd of horned cattle. He made the cows of gold
+and tin, and they lowed as they came full speed out of the yards
+to go and feed among the waving reeds that grow by the banks of
+the river. Along with the cattle there went four shepherds, all
+of them in gold, and their nine fleet dogs went with them. Two
+terrible lions had fastened on a bellowing bull that was with the
+foremost cows, and bellow as he might they haled him, while the
+dogs and men gave chase: the lions tore through the bull's thick
+hide and were gorging on his blood and bowels, but the herdsmen
+were afraid to do anything, and only hounded on their dogs; the
+dogs dared not fasten on the lions but stood by barking and
+keeping out of harm's way.
+</para>
+
+<para>
+The god wrought also a pasture in a fair mountain dell, and a
+large flock of sheep, with a homestead and huts, and sheltered
+sheepfolds.
+</para>
+
+<para>
+Furthermore he wrought a green, like that which Daedalus once
+made in Cnossus for lovely Ariadne. Hereon there danced youths
+and maidens whom all would woo, with their hands on one another's
+wrists. The maidens wore robes of light linen, and the youths
+well woven shirts that were slightly oiled. The girls were
+crowned with garlands, while the young men had daggers of gold
+that hung by silver baldrics; sometimes they would dance deftly
+in a ring with merry twinkling feet, as it were a potter sitting
+at his work and making trial of his wheel to see whether it will
+run, and sometimes they would go all in line with one another,
+and much people was gathered joyously about the green. There was
+a bard also to sing to them and play his lyre, while two tumblers
+went about performing in the midst of them when the man struck up
+with his tune.
+</para>
+
+<para>
+All round the outermost rim of the shield he set the mighty
+stream of the river Oceanus.
+</para>
+
+<para>
+Then when he had fashioned the shield so great and strong, he
+made a breastplate also that shone brighter than fire. He made a
+helmet, close fitting to the brow, and richly worked, with a
+golden plume overhanging it; and he made greaves also of beaten
+tin.
+</para>
+
+<para>
+Lastly, when the famed lame god had made all the armour, he took
+it and set it before the mother of Achilles; whereon she darted
+like a falcon from the snowy summits of Olympus and bore away the
+gleaming armour from the house of Vulcan.
+</para>
+</chapter>
+
+<chapter>
+<title>BOOK XIX</title>
+
+<para>
+NOW when Dawn in robe of saffron was hasting from the streams of
+Oceanus, to bring light to mortals and immortals, Thetis reached
+the ships with the armour that the god had given her. She found
+her son fallen about the body of Patroclus and weeping bitterly.
+Many also of his followers were weeping round him, but when the
+goddess came among them she clasped his hand in her own, saying,
+"My son, grieve as we may we must let this man lie, for it is by
+heaven's will that he has fallen; now, therefore, accept from
+Vulcan this rich and goodly armour, which no man has ever yet
+borne upon his shoulders."
+</para>
+
+<para>
+As she spoke she set the armour before Achilles, and it rang out
+bravely as she did so. The Myrmidons were struck with awe, and
+none dared look full at it, for they were afraid; but Achilles
+was roused to still greater fury, and his eyes gleamed with a
+fierce light, for he was glad when he handled the splendid
+present which the god had made him. Then, as soon as he had
+satisfied himself with looking at it, he said to his mother,
+"Mother, the god has given me armour, meet handiwork for an
+immortal and such as no-one living could have fashioned; I will
+now arm, but I much fear that flies will settle upon the son of
+Menoetius and breed worms about his wounds, so that his body, now
+he is dead, will be disfigured and the flesh will rot."
+</para>
+
+<para>
+Silver-footed Thetis answered, "My son, be not disquieted about
+this matter. I will find means to protect him from the swarms of
+noisome flies that prey on the bodies of men who have been killed
+in battle. He may lie for a whole year, and his flesh shall still
+be as sound as ever, or even sounder. Call, therefore, the
+Achaean heroes in assembly; unsay your anger against Agamemnon;
+arm at once, and fight with might and main."
+</para>
+
+<para>
+As she spoke she put strength and courage into his heart, and she
+then dropped ambrosia and red nectar into the wounds of
+Patroclus, that his body might suffer no change.
+</para>
+
+<para>
+Then Achilles went out upon the seashore, and with a loud cry
+called on the Achaean heroes. On this even those who as yet had
+stayed always at the ships, the pilots and helmsmen, and even the
+stewards who were about the ships and served out rations, all
+came to the place of assembly because Achilles had shown himself
+after having held aloof so long from fighting. Two sons of Mars,
+Ulysses and the son of Tydeus, came limping, for their wounds
+still pained them; nevertheless they came, and took their seats
+in the front row of the assembly. Last of all came Agamemnon,
+king of men, he too wounded, for Coon son of Antenor had struck
+him with a spear in battle.
+</para>
+
+<para>
+When the Achaeans were got together Achilles rose and said, "Son
+of Atreus, surely it would have been better alike for both you
+and me, when we two were in such high anger about Briseis, surely
+it would have been better, had Diana's arrow slain her at the
+ships on the day when I took her after having sacked Lyrnessus.
+For so, many an Achaean the less would have bitten dust before
+the foe in the days of my anger. It has been well for Hector and
+the Trojans, but the Achaeans will long indeed remember our
+quarrel. Now, however, let it be, for it is over. If we have been
+angry, necessity has schooled our anger. I put it from me: I dare
+not nurse it for ever; therefore, bid the Achaeans arm forthwith
+that I may go out against the Trojans, and learn whether they
+will be in a mind to sleep by the ships or no. Glad, I ween, will
+he be to rest his knees who may fly my spear when I wield it."
+</para>
+
+<para>
+Thus did he speak, and the Achaeans rejoiced in that he had put
+away his anger.
+</para>
+
+<para>
+Then Agamemnon spoke, rising in his place, and not going into the
+middle of the assembly. "Danaan heroes," said he, "servants of
+Mars, it is well to listen when a man stands up to speak, and it
+is not seemly to interrupt him, or it will go hard even with a
+practised speaker. Who can either hear or speak in an uproar?
+Even the finest orator will be disconcerted by it. I will expound
+to the son of Peleus, and do you other Achaeans heed me and mark
+me well. Often have the Achaeans spoken to me of this matter and
+upbraided me, but it was not I that did it: Jove, and Fate, and
+Erinys that walks in darkness struck me mad when we were
+assembled on the day that I took from Achilles the meed that had
+been awarded to him. What could I do? All things are in the hand
+of heaven, and Folly, eldest of Jove's daughters, shuts men's
+eyes to their destruction. She walks delicately, not on the solid
+earth, but hovers over the heads of men to make them stumble or
+to ensnare them.
+</para>
+
+<para>
+"Time was when she fooled Jove himself, who they say is greatest
+whether of gods or men; for Juno, woman though she was, beguiled
+him on the day when Alcmena was to bring forth mighty Hercules in
+the fair city of Thebes. He told it out among the gods saying,
+'Hear me, all gods and goddesses, that I may speak even as I am
+minded; this day shall an Ilithuia, helper of women who are in
+labour, bring a man child into the world who shall be lord over
+all that dwell about him who are of my blood and lineage.' Then
+said Juno all crafty and full of guile, 'You will play false, and
+will not hold to your word. Swear me, O Olympian, swear me a
+great oath, that he who shall this day fall between the feet of a
+woman, shall be lord over all that dwell about him who are of
+your blood and lineage.'
+</para>
+
+<para>
+"Thus she spoke, and Jove suspected her not, but swore the great
+oath, to his much ruing thereafter. For Juno darted down from the
+high summit of Olympus, and went in haste to Achaean Argos where
+she knew that the noble wife of Sthenelus son of Perseus then
+was. She being with child and in her seventh month, Juno brought
+the child to birth though there was a month still wanting, but
+she stayed the offspring of Alcmena, and kept back the Ilithuiae.
+Then she went to tell Jove the son of Saturn, and said, 'Father
+Jove, lord of the lightning--I have a word for your ear. There is
+a fine child born this day, Eurystheus, son to Sthenelus the son
+of Perseus; he is of your lineage; it is well, therefore, that he
+should reign over the Argives.'
+</para>
+
+<para>
+"On this Jove was stung to the very quick, and in his rage he
+caught Folly by the hair, and swore a great oath that never
+should she again invade starry heaven and Olympus, for she was
+the bane of all. Then he whirled her round with a twist of his
+hand, and flung her down from heaven so that she fell on to the
+fields of mortal men; and he was ever angry with her when he saw
+his son groaning under the cruel labours that Eurystheus laid
+upon him. Even so did I grieve when mighty Hector was killing the
+Argives at their ships, and all the time I kept thinking of Folly
+who had so baned me. I was blind, and Jove robbed me of my
+reason; I will now make atonement, and will add much treasure by
+way of amends. Go, therefore, into battle, you and your people
+with you. I will give you all that Ulysses offered you yesterday
+in your tents: or if it so please you, wait, though you would
+fain fight at once, and my squires shall bring the gifts from my
+ship, that you may see whether what I give you is enough."
+</para>
+
+<para>
+And Achilles answered, "Son of Atreus, king of men Agamemnon, you
+can give such gifts as you think proper, or you can withhold
+them: it is in your own hands. Let us now set battle in array; it
+is not well to tarry talking about trifles, for there is a deed
+which is as yet to do. Achilles shall again be seen fighting
+among the foremost, and laying low the ranks of the Trojans: bear
+this in mind each one of you when he is fighting."
+</para>
+
+<para>
+Then Ulysses said, "Achilles, godlike and brave, send not the
+Achaeans thus against Ilius to fight the Trojans fasting, for the
+battle will be no brief one, when it is once begun, and heaven
+has filled both sides with fury; bid them first take food both
+bread and wine by the ships, for in this there is strength and
+stay. No man can do battle the livelong day to the going down of
+the sun if he is without food; however much he may want to fight
+his strength will fail him before he knows it; hunger and thirst
+will find him out, and his limbs will grow weary under him. But a
+man can fight all day if he is full fed with meat and wine; his
+heart beats high, and his strength will stay till he has routed
+all his foes; therefore, send the people away and bid them
+prepare their meal; King Agamemnon will bring out the gifts in
+presence of the assembly, that all may see them and you may be
+satisfied. Moreover let him swear an oath before the Argives that
+he has never gone up into the couch of Briseis, nor been with her
+after the manner of men and women; and do you, too, show yourself
+of a gracious mind; let Agamemnon entertain you in his tents with
+a feast of reconciliation, that so you may have had your dues in
+full. As for you, son of Atreus, treat people more righteously in
+future; it is no disgrace even to a king that he should make
+amends if he was wrong in the first instance."
+</para>
+
+<para>
+And King Agamemnon answered, "Son of Laertes, your words please
+me well, for throughout you have spoken wisely. I will swear as
+you would have me do; I do so of my own free will, neither shall
+I take the name of heaven in vain. Let, then, Achilles wait,
+though he would fain fight at once, and do you others wait also,
+till the gifts come from my tent and we ratify the oath with
+sacrifice. Thus, then, do I charge you: take some noble young
+Achaeans with you, and bring from my tents the gifts that I
+promised yesterday to Achilles, and bring the women also;
+furthermore let Talthybius find me a boar from those that are
+with the host, and make it ready for sacrifice to Jove and to the
+sun."
+</para>
+
+<para>
+Then said Achilles, "Son of Atreus, king of men Agamemnon, see to
+these matters at some other season, when there is breathing time
+and when I am calmer. Would you have men eat while the bodies of
+those whom Hector son of Priam slew are still lying mangled upon
+the plain? Let the sons of the Achaeans, say I, fight fasting and
+without food, till we have avenged them; afterwards at the going
+down of the sun let them eat their fill. As for me, Patroclus is
+lying dead in my tent, all hacked and hewn, with his feet to the
+door, and his comrades are mourning round him. Therefore I can
+take thought of nothing save only slaughter and blood and the
+rattle in the throat of the dying."
+</para>
+
+<para>
+Ulysses answered, "Achilles, son of Peleus, mightiest of all the
+Achaeans, in battle you are better than I, and that more than a
+little, but in counsel I am much before you, for I am older and
+of greater knowledge. Therefore be patient under my words.
+Fighting is a thing of which men soon surfeit, and when Jove, who
+is war's steward, weighs the upshot, it may well prove that the
+straw which our sickles have reaped is far heavier than the
+grain. It may not be that the Achaeans should mourn the dead with
+their bellies; day by day men fall thick and threefold
+continually; when should we have respite from our sorrow? Let us
+mourn our dead for a day and bury them out of sight and mind, but
+let those of us who are left eat and drink that we may arm and
+fight our foes more fiercely. In that hour let no man hold back,
+waiting for a second summons; such summons shall bode ill for him
+who is found lagging behind at our ships; let us rather sally as
+one man and loose the fury of war upon the Trojans."
+</para>
+
+<para>
+When he had thus spoken he took with him the sons of Nestor, with
+Meges son of Phyleus, Thoas, Meriones, Lycomedes son of Creontes,
+and Melanippus, and went to the tent of Agamemnon son of Atreus.
+The word was not sooner said than the deed was done: they
+brought out the seven tripods which Agamemnon had promised, with
+the twenty metal cauldrons and the twelve horses; they also
+brought the women skilled in useful arts, seven in number, with
+Briseis, which made eight. Ulysses weighed out the ten talents of
+gold and then led the way back, while the young Achaeans brought
+the rest of the gifts, and laid them in the middle of the
+assembly.
+</para>
+
+<para>
+Agamemnon then rose, and Talthybius whose voice was like that of
+a god came to him with the boar. The son of Atreus drew the knife
+which he wore by the scabbard of his mighty sword, and began by
+cutting off some bristles from the boar, lifting up his hands in
+prayer as he did so. The other Achaeans sat where they were all
+silent and orderly to hear the king, and Agamemnon looked into
+the vault of heaven and prayed saying, "I call Jove the first and
+mightiest of all gods to witness, I call also Earth and Sun and
+the Erinyes who dwell below and take vengeance on him who shall
+swear falsely, that I have laid no hand upon the girl Briseis,
+neither to take her to my bed nor otherwise, but that she has
+remained in my tents inviolate. If I swear falsely may heaven
+visit me with all the penalties which it metes out to those who
+perjure themselves."
+</para>
+
+<para>
+He cut the boar's throat as he spoke, whereon Talthybius whirled
+it round his head, and flung it into the wide sea to feed the
+fishes. Then Achilles also rose and said to the Argives, "Father
+Jove, of a truth you blind men's eyes and bane them. The son of
+Atreus had not else stirred me to so fierce an anger, nor so
+stubbornly taken Briseis from me against my will. Surely Jove
+must have counselled the destruction of many an Argive. Go, now,
+and take your food that we may begin fighting."
+</para>
+
+<para>
+On this he broke up the assembly, and every man went back to his
+own ship. The Myrmidons attended to the presents and took them
+away to the ship of Achilles. They placed them in his tents,
+while the stable-men drove the horses in among the others.
+</para>
+
+<para>
+Briseis, fair as Venus, when she saw the mangled body of
+Patroclus, flung herself upon it and cried aloud, tearing her
+breast, her neck, and her lovely face with both her hands.
+Beautiful as a goddess she wept and said, "Patroclus, dearest
+friend, when I went hence I left you living; I return, O prince,
+to find you dead; thus do fresh sorrows multiply upon me one
+after the other. I saw him to whom my father and mother married
+me, cut down before our city, and my three own dear brothers
+perished with him on the self-same day; but you, Patroclus, even
+when Achilles slew my husband and sacked the city of noble Mynes,
+told me that I was not to weep, for you said you would make
+Achilles marry me, and take me back with him to Phthia, we should
+have a wedding feast among the Myrmidons. You were always kind to
+me and I shall never cease to grieve for you."
+</para>
+
+<para>
+She wept as she spoke, and the women joined in her lament-making
+as though their tears were for Patroclus, but in truth each was
+weeping for her own sorrows. The elders of the Achaeans gathered
+round Achilles and prayed him to take food, but he groaned and
+would not do so. "I pray you," said he, "if any comrade will hear
+me, bid me neither eat nor drink, for I am in great heaviness,
+and will stay fasting even to the going down of the sun."
+</para>
+
+<para>
+On this he sent the other princes away, save only the two sons of
+Atreus and Ulysses, Nestor, Idomeneus, and the knight Phoenix,
+who stayed behind and tried to comfort him in the bitterness of
+his sorrow: but he would not be comforted till he should have
+flung himself into the jaws of battle, and he fetched sigh on
+sigh, thinking ever of Patroclus. Then he said--
+</para>
+
+<para>
+"Hapless and dearest comrade, you it was who would get a good
+dinner ready for me at once and without delay when the Achaeans
+were hasting to fight the Trojans; now, therefore, though I have
+meat and drink in my tents, yet will I fast for sorrow. Grief
+greater than this I could not know, not even though I were to
+hear of the death of my father, who is now in Phthia weeping for
+the loss of me his son, who am here fighting the Trojans in a
+strange land for the accursed sake of Helen, nor yet though I
+should hear that my son is no more--he who is being brought up in
+Scyros--if indeed Neoptolemus is still living. Till now I made
+sure that I alone was to fall here at Troy away from Argos, while
+you were to return to Phthia, bring back my son with you in your
+own ship, and show him all my property, my bondsmen, and the
+greatness of my house--for Peleus must surely be either dead, or
+what little life remains to him is oppressed alike with the
+infirmities of age and ever present fear lest he should hear the
+sad tidings of my death."
+</para>
+
+<para>
+He wept as he spoke, and the elders sighed in concert as each
+thought on what he had left at home behind him. The son of Saturn
+looked down with pity upon them, and said presently to Minerva,
+"My child, you have quite deserted your hero; is he then gone so
+clean out of your recollection? There he sits by the ships all
+desolate for the loss of his dear comrade, and though the others
+are gone to their dinner he will neither eat nor drink. Go then
+and drop nectar and ambrosia into his breast, that he may know no
+hunger."
+</para>
+
+<para>
+With these words he urged Minerva, who was already of the same
+mind. She darted down from heaven into the air like some falcon
+sailing on his broad wings and screaming. Meanwhile the Achaeans
+were arming throughout the host, and when Minerva had dropped
+nectar and ambrosia into Achilles so that no cruel hunger should
+cause his limbs to fail him, she went back to the house of her
+mighty father. Thick as the chill snow-flakes shed from the hand
+of Jove and borne on the keen blasts of the north wind, even so
+thick did the gleaming helmets, the bossed shields, the strongly
+plated breastplates, and the ashen spears stream from the ships.
+The sheen pierced the sky, the whole land was radiant with their
+flashing armour, and the sound of the tramp of their treading
+rose from under their feet. In the midst of them all Achilles put
+on his armour; he gnashed his teeth, his eyes gleamed like fire,
+for his grief was greater than he could bear. Thus, then, full of
+fury against the Trojans, did he don the gift of the god, the
+armour that Vulcan had made him.
+</para>
+
+<para>
+First he put on the goodly greaves fitted with ancle-clasps, and
+next he did on the breastplate about his chest. He slung the
+silver-studded sword of bronze about his shoulders, and then took
+up the shield so great and strong that shone afar with a
+splendour as of the moon. As the light seen by sailors from out
+at sea, when men have lit a fire in their homestead high up among
+the mountains, but the sailors are carried out to sea by wind and
+storm far from the haven where they would be--even so did the
+gleam of Achilles' wondrous shield strike up into the heavens. He
+lifted the redoubtable helmet, and set it upon his head, from
+whence it shone like a star, and the golden plumes which Vulcan
+had set thick about the ridge of the helmet, waved all around it.
+Then Achilles made trial of himself in his armour to see whether
+it fitted him, so that his limbs could play freely under it, and
+it seemed to buoy him up as though it had been wings.
+</para>
+
+<para>
+He also drew his father's spear out of the spear-stand, a spear
+so great and heavy and strong that none of the Achaeans save only
+Achilles had strength to wield it; this was the spear of Pelian
+ash from the topmost ridges of Mt. Pelion, which Chiron had once
+given to Peleus, fraught with the death of heroes. Automedon and
+Alcimus busied themselves with the harnessing of his horses; they
+made the bands fast about them, and put the bit in their mouths,
+drawing the reins back towards the chariot. Automedon, whip in
+hand, sprang up behind the horses, and after him Achilles mounted
+in full armour, resplendent as the sun-god Hyperion. Then with a
+loud voice he chided with his father's horses saying, "Xanthus
+and Balius, famed offspring of Podarge--this time when we have
+done fighting be sure and bring your driver safely back to the
+host of the Achaeans, and do not leave him dead on the plain as
+you did Patroclus."
+</para>
+
+<para>
+Then fleet Xanthus answered under the yoke--for white-armed Juno
+had endowed him with human speech--and he bowed his head till his
+mane touched the ground as it hung down from under the yoke-band.
+"Dread Achilles," said he, "we will indeed save you now, but the
+day of your death is near, and the blame will not be ours, for it
+will be heaven and stern fate that will destroy you. Neither was
+it through any sloth or slackness on our part that the Trojans
+stripped Patroclus of his armour; it was the mighty god whom
+lovely Leto bore that slew him as he fought among the foremost,
+and vouchsafed a triumph to Hector. We two can fly as swiftly as
+Zephyrus who they say is fleetest of all winds; nevertheless it
+is your doom to fall by the hand of a man and of a god."
+</para>
+
+<para>
+When he had thus said the Erinyes stayed his speech, and Achilles
+answered him in great sadness, saying, "Why, O Xanthus, do you
+thus foretell my death? You need not do so, for I well know that
+I am to fall here, far from my dear father and mother; none the
+more, however, shall I stay my hand till I have given the Trojans
+their fill of fighting."
+</para>
+
+<para>
+So saying, with a loud cry he drove his horses to the front.
+</para>
+</chapter>
+
+<chapter>
+<title>BOOK XX</title>
+
+<para>
+THUS, then, did the Achaeans arm by their ships round you, O son
+of Peleus, who were hungering for battle; while the Trojans over
+against them armed upon the rise of the plain.
+</para>
+
+<para>
+Meanwhile Jove from the top of many-delled Olympus, bade Themis
+gather the gods in council, whereon she went about and called
+them to the house of Jove. There was not a river absent except
+Oceanus, nor a single one of the nymphs that haunt fair groves,
+or springs of rivers and meadows of green grass. When they
+reached the house of cloud-compelling Jove, they took their seats
+in the arcades of polished marble which Vulcan with his
+consummate skill had made for father Jove.
+</para>
+
+<para>
+In such wise, therefore, did they gather in the house of Jove.
+Neptune also, lord of the earthquake, obeyed the call of the
+goddess, and came up out of the sea to join them. There, sitting
+in the midst of them, he asked what Jove's purpose might be.
+"Why," said he, "wielder of the lightning, have you called the
+gods in council? Are you considering some matter that concerns
+the Trojans and Achaeans--for the blaze of battle is on the point
+of being kindled between them?"
+</para>
+
+<para>
+And Jove answered, "You know my purpose, shaker of earth, and
+wherefore I have called you hither. I take thought for them even
+in their destruction. For my own part I shall stay here seated on
+Mt. Olympus and look on in peace, but do you others go about
+among Trojans and Achaeans, and help either side as you may be
+severally disposed. If Achilles fights the Trojans without
+hindrance they will make no stand against him; they have ever
+trembled at the sight of him, and now that he is roused to such
+fury about his comrade, he will override fate itself and storm
+their city."
+</para>
+
+<para>
+Thus spoke Jove and gave the word for war, whereon the gods took
+their several sides and went into battle. Juno, Pallas Minerva,
+earth-encircling Neptune, Mercury bringer of good luck and
+excellent in all cunning--all these joined the host that came
+from the ships; with them also came Vulcan in all his glory,
+limping, but yet with his thin legs plying lustily under him.
+Mars of gleaming helmet joined the Trojans, and with him Apollo
+of locks unshorn, and the archer goddess Diana, Leto, Xanthus,
+and laughter-loving Venus.
+</para>
+
+<para>
+So long as the gods held themselves aloof from mortal warriors
+the Achaeans were triumphant, for Achilles who had long refused
+to fight was now with them. There was not a Trojan but his limbs
+failed him for fear as he beheld the fleet son of Peleus all
+glorious in his armour, and looking like Mars himself. When,
+however, the Olympians came to take their part among men,
+forthwith uprose strong Strife, rouser of hosts, and Minerva
+raised her loud voice, now standing by the deep trench that ran
+outside the wall, and now shouting with all her might upon the
+shore of the sounding sea. Mars also bellowed out upon the other
+side, dark as some black thunder-cloud, and called on the Trojans
+at the top of his voice, now from the acropolis, and now speeding
+up the side of the river Simois till he came to the hill
+Callicolone.
+</para>
+
+<para>
+Thus did the gods spur on both hosts to fight, and rouse fierce
+contention also among themselves. The sire of gods and men
+thundered from heaven above, while from beneath Neptune shook the
+vast earth, and bade the high hills tremble. The spurs and crests
+of many-fountained Ida quaked, as also the city of the Trojans
+and the ships of the Achaeans. Hades, king of the realms below,
+was struck with fear; he sprang panic-stricken from his throne
+and cried aloud in terror lest Neptune, lord of the earthquake,
+should crack the ground over his head, and lay bare his mouldy
+mansions to the sight of mortals and immortals--mansions so
+ghastly grim that even the gods shudder to think of them. Such
+was the uproar as the gods came together in battle. Apollo with
+his arrows took his stand to face King Neptune, while Minerva
+took hers against the god of war; the archer-goddess Diana with
+her golden arrows, sister of far-darting Apollo, stood to face
+Juno; Mercury the lusty bringer of good luck faced Leto, while
+the mighty eddying river whom men can Scamander, but gods
+Xanthus, matched himself against Vulcan.
+</para>
+
+<para>
+The gods, then, were thus ranged against one another. But the
+heart of Achilles was set on meeting Hector son of Priam, for it
+was with his blood that he longed above all things else to glut
+the stubborn lord of battle. Meanwhile Apollo set Aeneas on to
+attack the son of Peleus, and put courage into his heart,
+speaking with the voice of Lycaon son of Priam. In his likeness
+therefore, he said to Aeneas, "Aeneas, counsellor of the Trojans,
+where are now the brave words with which you vaunted over your
+wine before the Trojan princes, saying that you would fight
+Achilles son of Peleus in single combat?"
+</para>
+
+<para>
+And Aeneas answered, "Why do you thus bid me fight the proud son
+of Peleus, when I am in no mind to do so? Were I to face him now,
+it would not be for the first time. His spear has already put me
+to Right from Ida, when he attacked our cattle and sacked
+Lyrnessus and Pedasus; Jove indeed saved me in that he vouchsafed
+me strength to fly, else had the fallen by the hands of Achilles
+and Minerva, who went before him to protect him and urged him to
+fall upon the Lelegae and Trojans. No man may fight Achilles, for
+one of the gods is always with him as his guardian angel, and
+even were it not so, his weapon flies ever straight, and fails
+not to pierce the flesh of him who is against him; if heaven
+would let me fight him on even terms he should not soon overcome
+me, though he boasts that he is made of bronze."
+</para>
+
+<para>
+Then said King Apollo, son to Jove, "Nay, hero, pray to the
+ever-living gods, for men say that you were born of Jove's
+daughter Venus, whereas Achilles is son to a goddess of inferior
+rank. Venus is child to Jove, while Thetis is but daughter to the
+old man of the sea. Bring, therefore, your spear to bear upon
+him, and let him not scare you with his taunts and menaces."
+</para>
+
+<para>
+As he spoke he put courage into the heart of the shepherd of his
+people, and he strode in full armour among the ranks of the
+foremost fighters. Nor did the son of Anchises escape the notice
+of white-armed Juno, as he went forth into the throng to meet
+Achilles. She called the gods about her, and said, "Look to it,
+you two, Neptune and Minerva, and consider how this shall be;
+Phoebus Apollo has been sending Aeneas clad in full armour to
+fight Achilles. Shall we turn him back at once, or shall one of
+us stand by Achilles and endow him with strength so that his
+heart fail not, and he may learn that the chiefs of the immortals
+are on his side, while the others who have all along been
+defending the Trojans are but vain helpers? Let us all come down
+from Olympus and join in the fight, that this day he may take no
+hurt at the hands of the Trojans. Hereafter let him suffer
+whatever fate may have spun out for him when he was begotten and
+his mother bore him. If Achilles be not thus assured by the voice
+of a god, he may come to fear presently when one of us meets him
+in battle, for the gods are terrible if they are seen face to
+face."
+</para>
+
+<para>
+Neptune lord of the earthquake answered her saying, "Juno,
+restrain your fury; it is not well; I am not in favour of forcing
+the other gods to fight us, for the advantage is too greatly on
+our own side; let us take our places on some hill out of the
+beaten track, and let mortals fight it out among themselves. If
+Mars or Phoebus Apollo begin fighting, or keep Achilles in check
+so that he cannot fight, we too, will at once raise the cry of
+battle, and in that case they will soon leave the field and go
+back vanquished to Olympus among the other gods."
+</para>
+
+<para>
+With these words the dark-haired god led the way to the high
+earth-barrow of Hercules, built round solid masonry, and made by
+the Trojans and Pallas Minerva for him fly to when the
+sea-monster was chasing him from the shore on to the plain. Here
+Neptune and those that were with him took their seats, wrapped in
+a thick cloud of darkness; but the other gods seated themselves
+on the brow of Callicolone round you, O Phoebus, and Mars the
+waster of cities.
+</para>
+
+<para>
+Thus did the gods sit apart and form their plans, but neither
+side was willing to begin battle with the other, and Jove from
+his seat on high was in command over them all. Meanwhile the
+whole plain was alive with men and horses, and blazing with the
+gleam of armour. The earth rang again under the tramp of their
+feet as they rushed towards each other, and two champions, by far
+the foremost of them all, met between the hosts to fight--to wit,
+Aeneas son of Anchises, and noble Achilles.
+</para>
+
+<para>
+Aeneas was first to stride forward in attack, his doughty helmet
+tossing defiance as he came on. He held his strong shield before
+his breast, and brandished his bronze spear. The son of Peleus
+from the other side sprang forth to meet him, like some fierce
+lion that the whole country-side has met to hunt and kill--at
+first he bodes no ill, but when some daring youth has struck him
+with a spear, he crouches openmouthed, his jaws foam, he roars
+with fury, he lashes his tail from side to side about his ribs
+and loins, and glares as he springs straight before him, to find
+out whether he is to slay, or be slain among the foremost of his
+foes--even with such fury did Achilles burn to spring upon
+Aeneas.
+</para>
+
+<para>
+When they were now close up with one another Achilles was first
+to speak. "Aeneas," said he, "why do you stand thus out before
+the host to fight me? Is it that you hope to reign over the
+Trojans in the seat of Priam? Nay, though you kill me Priam will
+not hand his kingdom over to you. He is a man of sound judgement,
+and he has sons of his own. Or have the Trojans been allotting
+you a demesne of passing richness, fair with orchard lawns and
+corn lands, if you should slay me? This you shall hardly do. I
+have discomfited you once already. Have you forgotten how when
+you were alone I chased you from your herds helter-skelter down
+the slopes of Ida? You did not turn round to look behind you; you
+took refuge in Lyrnessus, but I attacked the city, and with the
+help of Minerva and father Jove I sacked it and carried its women
+into captivity, though Jove and the other gods rescued you. You
+think they will protect you now, but they will not do so;
+therefore I say go back into the host, and do not face me, or you
+will rue it. Even a fool may be wise after the event."
+</para>
+
+<para>
+Then Aeneas answered, "Son of Peleus, think not that your words
+can scare me as though I were a child. I too, if I will, can brag
+and talk unseemly. We know one another's race and parentage as
+matters of common fame, though neither have you ever seen my
+parents nor I yours. Men say that you are son to noble Peleus,
+and that your mother is Thetis, fair-haired daughter of the sea.
+I have noble Anchises for my father, and Venus for my mother; the
+parents of one or other of us shall this day mourn a son, for it
+will be more than silly talk that shall part us when the fight is
+over. Learn, then, my lineage if you will--and it is known to
+many.
+</para>
+
+<para>
+"In the beginning Dardanus was the son of Jove, and founded
+Dardania, for Ilius was not yet stablished on the plain for men
+to dwell in, and her people still abode on the spurs of
+many-fountained Ida. Dardanus had a son, king Erichthonius, who
+was wealthiest of all men living; he had three thousand mares
+that fed by the water-meadows, they and their foals with them.
+Boreas was enamoured of them as they were feeding, and covered
+them in the semblance of a dark-maned stallion. Twelve filly
+foals did they conceive and bear him, and these, as they sped
+over the rich plain, would go bounding on over the ripe ears of
+corn and not break them; or again when they would disport
+themselves on the broad back of Ocean they could gallop on the
+crest of a breaker. Erichthonius begat Tros, king of the Trojans,
+and Tros had three noble sons, Ilus, Assaracus, and Ganymede who
+was comeliest of mortal men; wherefore the gods carried him off
+to be Jove's cupbearer, for his beauty's sake, that he might
+dwell among the immortals. Ilus begat Laomedon, and Laomedon
+begat Tithonus, Priam, Lampus, Clytius, and Hiketaon of the stock
+of Mars. But Assaracus was father to Capys, and Capys to
+Anchises, who was my father, while Hector is son to Priam.
+</para>
+
+<para>
+"Such do I declare my blood and lineage, but as for valour, Jove
+gives it or takes it as he will, for he is lord of all. And now
+let there be no more of this prating in mid-battle as though we
+were children. We could fling taunts without end at one another;
+a hundred-oared galley would not hold them. The tongue can run
+all whithers and talk all wise; it can go here and there, and as
+a man says, so shall he be gainsaid. What is the use of our
+bandying hard like women who when they fall foul of one another
+go out and wrangle in the streets, one half true and the other
+lies, as rage inspires them? No words of yours shall turn me now
+that I am fain to fight--therefore let us make trial of one
+another with our spears."
+</para>
+
+<para>
+As he spoke he drove his spear at the great and terrible shield
+of Achilles, which rang out as the point struck it. The son of
+Peleus held the shield before him with his strong hand, and he
+was afraid, for he deemed that Aeneas's spear would go through it
+quite easily, not reflecting that the god's glorious gifts were
+little likely to yield before the blows of mortal men; and indeed
+Aeneas's spear did not pierce the shield, for the layer of gold,
+gift of the god, stayed the point. It went through two layers,
+but the god had made the shield in five, two of bronze, the two
+innermost ones of tin, and one of gold; it was in this that the
+spear was stayed.
+</para>
+
+<para>
+Achilles in his turn threw, and struck the round shield of Aeneas
+at the very edge, where the bronze was thinnest; the spear of
+Pelian ash went clean through, and the shield rang under the
+blow; Aeneas was afraid, and crouched backwards, holding the
+shield away from him; the spear, however, flew over his back, and
+stuck quivering in the ground, after having gone through both
+circles of the sheltering shield. Aeneas though he had avoided
+the spear, stood still, blinded with fear and grief because the
+weapon had gone so near him; then Achilles sprang furiously upon
+him, with a cry as of death and with his keen blade drawn, and
+Aeneas seized a great stone, so huge that two men, as men now
+are, would be unable to lift it, but Aeneas wielded it quite
+easily.
+</para>
+
+<para>
+Aeneas would then have struck Achilles as he was springing
+towards him, either on the helmet, or on the shield that covered
+him, and Achilles would have closed with him and despatched him
+with his sword, had not Neptune lord of the earthquake been quick
+to mark, and said forthwith to the immortals, "Alas, I am sorry
+for great Aeneas, who will now go down to the house of Hades,
+vanquished by the son of Peleus. Fool that he was to give ear to
+the counsel of Apollo. Apollo will never save him from
+destruction. Why should this man suffer when he is guiltless, to
+no purpose, and in another's quarrel? Has he not at all times
+offered acceptable sacrifice to the gods that dwell in heaven?
+Let us then snatch him from death's jaws, lest the son of Saturn
+be angry should Achilles slay him. It is fated, moreover, that he
+should escape, and that the race of Dardanus, whom Jove loved
+above all the sons born to him of mortal women, shall not perish
+utterly without seed or sign. For now indeed has Jove hated the
+blood of Priam, while Aeneas shall reign over the Trojans, he and
+his children's children that shall be born hereafter."
+</para>
+
+<para>
+Then answered Juno, "Earth-shaker, look to this matter yourself,
+and consider concerning Aeneas, whether you will save him, or
+suffer him, brave though he be, to fall by the hand of Achilles
+son of Peleus. For of a truth we two, I and Pallas Minerva, have
+sworn full many a time before all the immortals, that never would
+we shield Trojans from destruction, not even when all Troy is
+burning in the flames that the Achaeans shall kindle."
+</para>
+
+<para>
+When earth-encircling Neptune heard this he went into the battle
+amid the clash of spears, and came to the place where Achilles
+and Aeneas were. Forthwith he shed a darkness before the eyes of
+the son of Peleus, drew the bronze-headed ashen spear from the
+shield of Aeneas, and laid it at the feet of Achilles. Then he
+lifted Aeneas on high from off the earth and hurried him away.
+Over the heads of many a band of warriors both horse and foot did
+he soar as the god's hand sped him, till he came to the very
+fringe of the battle where the Cauconians were arming themselves
+for fight. Neptune, shaker of the earth, then came near to him
+and said, "Aeneas, what god has egged you on to this folly in
+fighting the son of Peleus, who is both a mightier man of valour
+and more beloved of heaven than you are? Give way before him
+whensoever you meet him, lest you go down to the house of Hades
+even though fate would have it otherwise. When Achilles is dead
+you may then fight among the foremost undaunted, for none other
+of the Achaeans shall slay you."
+</para>
+
+<para>
+The god left him when he had given him these instructions, and at
+once removed the darkness from before the eyes of Achilles, who
+opened them wide indeed and said in great anger, "Alas! what
+marvel am I now beholding? Here is my spear upon the ground, but
+I see not him whom I meant to kill when I hurled it. Of a truth
+Aeneas also must be under heaven's protection, although I had
+thought his boasting was idle. Let him go hang; he will be in no
+mood to fight me further, seeing how narrowly he has missed being
+killed. I will now give my orders to the Danaans and attack some
+other of the Trojans."
+</para>
+
+<para>
+He sprang forward along the line and cheered his men on as he did
+so. "Let not the Trojans," he cried, "keep you at arm's length,
+Achaeans, but go for them and fight them man for man. However
+valiant I may be, I cannot give chase to so many and fight all of
+them. Even Mars, who is an immortal, or Minerva, would shrink
+from flinging himself into the jaws of such a fight and laying
+about him; nevertheless, so far as in me lies I will show no
+slackness of hand or foot nor want of endurance, not even for a
+moment; I will utterly break their ranks, and woe to the Trojan
+who shall venture within reach of my spear."
+</para>
+
+<para>
+Thus did he exhort them. Meanwhile Hector called upon the Trojans
+and declared that he would fight Achilles. "Be not afraid, proud
+Trojans," said he, "to face the son of Peleus; I could fight gods
+myself if the battle were one of words only, but they would be
+more than a match for me, if we had to use our spears. Even so
+the deed of Achilles will fall somewhat short of his word; he
+will do in part, and the other part he will clip short. I will go
+up against him though his hands be as fire--though his hands be
+fire and his strength iron."
+</para>
+
+<para>
+Thus urged the Trojans lifted up their spears against the
+Achaeans, and raised the cry of battle as they flung themselves
+into the midst of their ranks. But Phoebus Apollo came up to
+Hector and said, "Hector, on no account must you challenge
+Achilles to single combat; keep a lookout for him while you are
+under cover of the others and away from the thick of the fight,
+otherwise he will either hit you with a spear or cut you down at
+close quarters."
+</para>
+
+<para>
+Thus he spoke, and Hector drew back within the crowd, for he was
+afraid when he heard what the god had said to him. Achilles then
+sprang upon the Trojans with a terrible cry, clothed in valour as
+with a garment. First he killed Iphition son of Otrynteus, a
+leader of much people whom a naiad nymph had borne to Otrynteus
+waster of cities, in the land of Hyde under the snowy heights of
+Mt. Tmolus. Achilles struck him full on the head as he was coming
+on towards him, and split it clean in two; whereon he fell
+heavily to the ground and Achilles vaunted over him saying, "You
+be low, son of Otrynteus, mighty hero; your death is here, but
+your lineage is on the Gygaean lake where your father's estate
+lies, by Hyllus, rich in fish, and the eddying waters of Hermus."
+</para>
+
+<para>
+Thus did he vaunt, but darkness closed the eyes of the other.
+The chariots of the Achaeans cut him up as their wheels passed
+over him in the front of the battle, and after him Achilles
+killed Demoleon, a valiant man of war and son to Antenor. He
+struck him on the temple through his bronze-cheeked helmet. The
+helmet did not stay the spear, but it went right on, crushing the
+bone so that the brain inside was shed in all directions, and his
+lust of fighting was ended. Then he struck Hippodamas in the
+midriff as he was springing down from his chariot in front of
+him, and trying to escape. He breathed his last, bellowing like a
+bull bellows when young men are dragging him to offer him in
+sacrifice to the King of Helice, and the heart of the
+earth-shaker is glad; even so did he bellow as he lay dying.
+Achilles then went in pursuit of Polydorus son of Priam, whom his
+father had always forbidden to fight because he was the youngest
+of his sons, the one he loved best, and the fastest runner. He,
+in his folly and showing off the fleetness of his feet, was
+rushing about among front ranks until he lost his life, for
+Achilles struck him in the middle of the back as he was darting
+past him: he struck him just at the golden fastenings of his belt
+and where the two pieces of the double breastplate overlapped.
+The point of the spear pierced him through and came out by the
+navel, whereon he fell groaning on to his knees and a cloud of
+darkness overshadowed him as he sank holding his entrails in his
+hands.
+</para>
+
+<para>
+When Hector saw his brother Polydorus with his entrails in his
+hands and sinking down upon the ground, a mist came over his
+eyes, and he could not bear to keep longer at a distance; he
+therefore poised his spear and darted towards Achilles like a
+flame of fire. When Achilles saw him he bounded forward and
+vaunted saying, "This is he that has wounded my heart most deeply
+and has slain my beloved comrade. Not for long shall we two quail
+before one another on the highways of war."
+</para>
+
+<para>
+He looked fiercely on Hector and said, "Draw near, that you may
+meet your doom the sooner." Hector feared him not and answered,
+"Son of Peleus, think not that your words can scare me as though
+I were a child; I too if I will can brag and talk unseemly; I
+know that you are a mighty warrior, mightier by far than I,
+nevertheless the issue lies in the lap of heaven whether I, worse
+man though I be, may not slay you with my spear, for this too has
+been found keen ere now."
+</para>
+
+<para>
+He hurled his spear as he spoke, but Minerva breathed upon it,
+and though she breathed but very lightly she turned it back from
+going towards Achilles, so that it returned to Hector and lay at
+his feet in front of him. Achilles then sprang furiously on him
+with a loud cry, bent on killing him, but Apollo caught him up
+easily as a god can, and hid him in a thick darkness. Thrice did
+Achilles spring towards him spear in hand, and thrice did he
+waste his blow upon the air. When he rushed forward for the
+fourth time as though he were a god, he shouted aloud saying,
+"Hound, this time too you have escaped death--but of a truth it
+came exceedingly near you. Phoebus Apollo, to whom it seems you
+pray before you go into battle, has again saved you; but if I too
+have any friend among the gods I will surely make an end of you
+when I come across you at some other time. Now, however, I will
+pursue and overtake other Trojans."
+</para>
+
+<para>
+On this he struck Dryops with his spear, about the middle of his
+neck, and he fell headlong at his feet. There he let him lie and
+stayed Demouchus son of Philetor, a man both brave and of great
+stature, by hitting him on the knee with a spear; then he smote
+him with his sword and killed him. After this he sprang on
+Laogonus and Dardanus, sons of Bias, and threw them from their
+chariot, the one with a blow from a thrown spear, while the other
+he cut down in hand-to-hand fight. There was also Tros the son of
+Alastor--he came up to Achilles and clasped his knees in the hope
+that he would spare him and not kill him but let him go, because
+they were both of the same age. Fool, he might have known that he
+should not prevail with him, for the man was in no mood for pity
+or forbearance but was in grim earnest. Therefore when Tros laid
+hold of his knees and sought a hearing for his prayers, Achilles
+drove his sword into his liver, and the liver came rolling out,
+while his bosom was all covered with the black blood that welled
+from the wound. Thus did death close his eyes as he lay lifeless.
+</para>
+
+<para>
+Achilles then went up to Mulius and struck him on the ear with a
+spear, and the bronze spear-head came right out at the other ear.
+He also struck Echeclus son of Agenor on the head with his sword,
+which became warm with the blood, while death and stern fate
+closed the eyes of Echeclus. Next in order the bronze point of
+his spear wounded Deucalion in the fore-arm where the sinews of
+the elbow are united, whereon he waited Achilles' onset with his
+arm hanging down and death staring him in the face. Achilles cut
+his head off with a blow from his sword and flung it helmet and
+all away from him, and the marrow came oozing out of his backbone
+as he lay. He then went in pursuit of Rhigmus, noble son of
+Peires, who had come from fertile Thrace, and struck him through
+the middle with a spear which fixed itself in his belly, so that
+he fell headlong from his chariot. He also speared Areithous
+squire to Rhigmus in the back as he was turning his horses in
+flight, and thrust him from his chariot, while the horses were
+struck with panic.
+</para>
+
+<para>
+As a fire raging in some mountain glen after long drought--and
+the dense forest is in a blaze, while the wind carries great
+tongues of fire in every direction--even so furiously did
+Achilles rage, wielding his spear as though he were a god, and
+giving chase to those whom he would slay, till the dark earth ran
+with blood. Or as one who yokes broad-browed oxen that they may
+tread barley in a threshing-floor--and it is soon bruised small
+under the feet of the lowing cattle--even so did the horses of
+Achilles trample on the shields and bodies of the slain. The axle
+underneath and the railing that ran round the car were
+bespattered with clots of blood thrown up by the horses' hoofs,
+and from the tyres of the wheels; but the son of Peleus pressed
+on to win still further glory, and his hands were bedrabbled with
+gore.
+</para>
+</chapter>
+
+<chapter>
+<title>BOOK XXI</title>
+
+<para>
+NOW when they came to the ford of the full-flowing river Xanthus,
+begotten of immortal Jove, Achilles cut their forces in two: one
+half he chased over the plain towards the city by the same way
+that the Achaeans had taken when flying panic-stricken on the
+preceding day with Hector in full triumph; this way did they fly
+pell-mell, and Juno sent down a thick mist in front of them to
+stay them. The other half were hemmed in by the deep
+silver-eddying stream, and fell into it with a great uproar. The
+waters resounded, and the banks rang again, as they swam hither
+and thither with loud cries amid the whirling eddies. As locusts
+flying to a river before the blast of a grass fire--the flame
+comes on and on till at last it overtakes them and they huddle
+into the water--even so was the eddying stream of Xanthus filled
+with the uproar of men and horses, all struggling in confusion
+before Achilles.
+</para>
+
+<para>
+Forthwith the hero left his spear upon the bank, leaning it
+against a tamarisk bush, and plunged into the river like a god,
+armed with his sword only. Fell was his purpose as he hewed the
+Trojans down on every side. Their dying groans rose hideous as
+the sword smote them, and the river ran red with blood. As when
+fish fly scared before a huge dolphin, and fill every nook and
+corner of some fair haven--for he is sure to eat all he can
+catch--even so did the Trojans cower under the banks of the
+mighty river, and when Achilles' arms grew weary with killing
+them, he drew twelve youths alive out of the water, to sacrifice
+in revenge for Patroclus son of Menoetius. He drew them out like
+dazed fawns, bound their hands behind them with the girdles of
+their own shirts, and gave them over to his men to take back to
+the ships. Then he sprang into the river, thirsting for still
+further blood.
+</para>
+
+<para>
+There he found Lycaon, son of Priam seed of Dardanus, as he was
+escaping out of the water; he it was whom he had once taken
+prisoner when he was in his father's vineyard, having set upon
+him by night, as he was cutting young shoots from a wild fig-tree
+to make the wicker sides of a chariot. Achilles then caught him
+to his sorrow unawares, and sent him by sea to Lemnos, where the
+son of Jason bought him. But a guest-friend, Eetion of Imbros,
+freed him with a great sum, and sent him to Arisbe, whence he had
+escaped and returned to his father's house. He had spent eleven
+days happily with his friends after he had come from Lemnos, but
+on the twelfth heaven again delivered him into the hands of
+Achilles, who was to send him to the house of Hades sorely
+against his will. He was unarmed when Achilles caught sight of
+him, and had neither helmet nor shield; nor yet had he any spear,
+for he had thrown all his armour from him on to the bank, and was
+sweating with his struggles to get out of the river, so that his
+strength was now failing him.
+</para>
+
+<para>
+Then Achilles said to himself in his surprise, "What marvel do I
+see here? If this man can come back alive after having been sold
+over into Lemnos, I shall have the Trojans also whom I have slain
+rising from the world below. Could not even the waters of the
+grey sea imprison him, as they do many another whether he will or
+no? This time let him taste my spear, that I may know for certain
+whether mother earth who can keep even a strong man down, will be
+able to hold him, or whether thence too he will return."
+</para>
+
+<para>
+Thus did he pause and ponder. But Lycaon came up to him dazed and
+trying hard to embrace his knees, for he would fain live, not
+die. Achilles thrust at him with his spear, meaning to kill him,
+but Lycaon ran crouching up to him and caught his knees, whereby
+the spear passed over his back, and stuck in the ground,
+hungering though it was for blood. With one hand he caught
+Achilles' knees as he besought him, and with the other he
+clutched the spear and would not let it go. Then he said,
+"Achilles, have mercy upon me and spare me, for I am your
+suppliant. It was in your tents that I first broke bread on the
+day when you took me prisoner in the vineyard; after which you
+sold me away to Lemnos far from my father and my friends, and I
+brought you the price of a hundred oxen. I have paid three times
+as much to gain my freedom; it is but twelve days that I have
+come to Ilius after much suffering, and now cruel fate has again
+thrown me into your hands. Surely father Jove must hate me, that
+he has given me over to you a second time. Short of life indeed
+did my mother Laothoe bear me, daughter of aged Altes--of Altes
+who reigns over the warlike Lelegae and holds steep Pedasus on
+the river Satnioeis. Priam married his daughter along with many
+other women and two sons were born of her, both of whom you will
+have slain. Your spear slew noble Polydorus as he was fighting in
+the front ranks, and now evil will here befall me, for I fear
+that I shall not escape you since heaven has delivered me over to
+you. Furthermore I say, and lay my saying to your heart, spare
+me, for I am not of the same womb as Hector who slew your brave
+and noble comrade."
+</para>
+
+<para>
+With such words did the princely son of Priam beseech Achilles;
+but Achilles answered him sternly. "Idiot," said he, "talk not to
+me of ransom. Until Patroclus fell I preferred to give the
+Trojans quarter, and sold beyond the sea many of those whom I had
+taken alive; but now not a man shall live of those whom heaven
+delivers into my hands before the city of Ilius--and of all
+Trojans it shall fare hardest with the sons of Priam. Therefore,
+my friend, you too shall die. Why should you whine in this way?
+Patroclus fell, and he was a better man than you are. I too--see
+you not how I am great and goodly? I am son to a noble father,
+and have a goddess for my mother, but the hands of doom and death
+overshadow me all as surely. The day will come, either at dawn or
+dark, or at the noontide, when one shall take my life also in
+battle, either with his spear, or with an arrow sped from his
+bow."
+</para>
+
+<para>
+Thus did he speak, and Lycaon's heart sank within him. He loosed
+his hold of the spear, and held out both hands before him; but
+Achilles drew his keen blade, and struck him by the collar-bone
+on his neck; he plunged his two-edged sword into him to the very
+hilt, whereon he lay at full length on the ground, with the dark
+blood welling from him till the earth was soaked. Then Achilles
+caught him by the foot and flung him into the river to go down
+stream, vaunting over him the while, and saying, "Lie there among
+the fishes, who will lick the blood from your wound and gloat
+over it; your mother shall not lay you on any bier to mourn you,
+but the eddies of Scamander shall bear you into the broad bosom
+of the sea. There shall the fishes feed on the fat of Lycaon as
+they dart under the dark ripple of the waters--so perish all of
+you till we reach the citadel of strong Ilius--you in flight, and
+I following after to destroy you. The river with its broad silver
+stream shall serve you in no stead, for all the bulls you offered
+him and all the horses that you flung living into his waters.
+None the less miserably shall you perish till there is not a man
+of you but has paid in full for the death of Patroclus and the
+havoc you wrought among the Achaeans whom you have slain while I
+held aloof from battle."
+</para>
+
+<para>
+So spoke Achilles, but the river grew more and more angry, and
+pondered within himself how he should stay the hand of Achilles
+and save the Trojans from disaster. Meanwhile the son of Peleus,
+spear in hand, sprang upon Asteropaeus son of Pelegon to kill
+him. He was son to the broad river Axius and Periboea eldest
+daughter of Acessamenus; for the river had lain with her.
+Asteropaeus stood up out of the water to face him with a spear in
+either hand, and Xanthus filled him with courage, being angry for
+the death of the youths whom Achilles was slaying ruthlessly
+within his waters. When they were close up with one another
+Achilles was first to speak. "Who and whence are you," said he,
+"who dare to face me? Woe to the parents whose son stands up
+against me." And the son of Pelegon answered, "Great son of
+Peleus, why should you ask my lineage. I am from the fertile land
+of far Paeonia, captain of the Paeonians, and it is now eleven
+days that I am at Ilius. I am of the blood of the river Axius--of
+Axius that is the fairest of all rivers that run. He begot the
+famed warrior Pelegon, whose son men call me. Let us now fight,
+Achilles."
+</para>
+
+<para>
+Thus did he defy him, and Achilles raised his spear of Pelian
+ash. Asteropaeus failed with both his spears, for he could use
+both hands alike; with the one spear he struck Achilles' shield,
+but did not pierce it, for the layer of gold, gift of the god,
+stayed the point; with the other spear he grazed the elbow of
+Achilles' right arm drawing dark blood, but the spear itself went
+by him and fixed itself in the ground, foiled of its bloody
+banquet. Then Achilles, fain to kill him, hurled his spear at
+Asteropaeus, but failed to hit him and struck the steep bank of
+the river, driving the spear half its length into the earth. The
+son of Peleus then drew his sword and sprang furiously upon him.
+Asteropaeus vainly tried to draw Achilles' spear out of the bank
+by main force; thrice did he tug at it, trying with all his might
+to draw it out, and thrice he had to leave off trying; the fourth
+time he tried to bend and break it, but ere he could do so
+Achilles smote him with his sword and killed him. He struck him
+in the belly near the navel, so that all his bowels came gushing
+out on to the ground, and the darkness of death came over him as
+he lay gasping. Then Achilles set his foot on his chest and
+spoiled him of his armour, vaunting over him and saying, "Lie
+there--begotten of a river though you be, it is hard for you to
+strive with the offspring of Saturn's son. You declare yourself
+sprung from the blood of a broad river, but I am of the seed of
+mighty Jove. My father is Peleus, son of Aeacus ruler over the
+many Myrmidons, and Aeacus was the son of Jove. Therefore as Jove
+is mightier than any river that flows into the sea, so are his
+children stronger than those of any river whatsoever. Moreover
+you have a great river hard by if he can be of any use to you,
+but there is no fighting against Jove the son of Saturn, with
+whom not even King Achelous can compare, nor the mighty stream of
+deep-flowing Oceanus, from whom all rivers and seas with all
+springs and deep wells proceed; even Oceanus fears the lightnings
+of great Jove, and his thunder that comes crashing out of
+heaven."
+</para>
+
+<para>
+With this he drew his bronze spear out of the bank, and now that
+he had killed Asteropaeus, he let him lie where he was on the
+sand, with the dark water flowing over him and the eels and
+fishes busy nibbling and gnawing the fat that was about his
+kidneys. Then he went in chase of the Paeonians, who were flying
+along the bank of the river in panic when they saw their leader
+slain by the hands of the son of Peleus. Therein he slew
+Thersilochus, Mydon, Astypylus, Mnesus, Thrasius, Oeneus, and
+Ophelestes, and he would have slain yet others, had not the river
+in anger taken human form, and spoken to him from out the deep
+waters saying, "Achilles, if you excel all in strength, so do you
+also in wickedness, for the gods are ever with you to protect
+you: if, then, the son of Saturn has vouchsafed it to you to
+destroy all the Trojans, at any rate drive them out of my stream,
+and do your grim work on land. My fair waters are now filled with
+corpses, nor can I find any channel by which I may pour myself
+into the sea for I am choked with dead, and yet you go on
+mercilessly slaying. I am in despair, therefore, O captain of
+your host, trouble me no further."
+</para>
+
+<para>
+Achilles answered, "So be it, Scamander, Jove-descended; but I
+will never cease dealing out death among the Trojans, till I have
+pent them up in their city, and made trial of Hector face to
+face, that I may learn whether he is to vanquish me, or I him."
+</para>
+
+<para>
+As he spoke he set upon the Trojans with a fury like that of the
+gods. But the river said to Apollo, "Surely, son of Jove, lord of
+the silver bow, you are not obeying the commands of Jove who
+charged you straitly that you should stand by the Trojans and
+defend them, till twilight fades, and darkness is over an the
+earth."
+</para>
+
+<para>
+Meanwhile Achilles sprang from the bank into mid-stream, whereon
+the river raised a high wave and attacked him. He swelled his
+stream into a torrent, and swept away the many dead whom Achilles
+had slain and left within his waters. These he cast out on to the
+land, bellowing like a bull the while, but the living he saved
+alive, hiding them in his mighty eddies. The great and terrible
+wave gathered about Achilles, falling upon him and beating on his
+shield, so that he could not keep his feet; he caught hold of a
+great elm-tree, but it came up by the roots, and tore away the
+bank, damming the stream with its thick branches and bridging it
+all across; whereby Achilles struggled out of the stream, and
+fled full speed over the plain, for he was afraid.
+</para>
+
+<para>
+But the mighty god ceased not in his pursuit, and sprang upon him
+with a dark-crested wave, to stay his hands and save the Trojans
+from destruction. The son of Peleus darted away a spear's throw
+from him; swift as the swoop of a black hunter-eagle which is the
+strongest and fleetest of all birds, even so did he spring
+forward, and the armour rang loudly about his breast. He fled on
+in front, but the river with a loud roar came tearing after. As
+one who would water his garden leads a stream from some fountain
+over his plants, and all his ground-spade in hand he clears away
+the dams to free the channels, and the little stones run rolling
+round and round with the water as it goes merrily down the bank
+faster than the man can follow--even so did the river keep
+catching up with Achilles albeit he was a fleet runner, for the
+gods are stronger than men. As often as he would strive to stand
+his ground, and see whether or no all the gods in heaven were in
+league against him, so often would the mighty wave come beating
+down upon his shoulders, and be would have to keep flying on and
+on in great dismay; for the angry flood was tiring him out as it
+flowed past him and ate the ground from under his feet.
+</para>
+
+<para>
+Then the son of Peleus lifted up his voice to heaven saying,
+"Father Jove, is there none of the gods who will take pity upon
+me, and save me from the river? I do not care what may happen to
+me afterwards. I blame none of the other dwellers on Olympus so
+severely as I do my dear mother, who has beguiled and tricked me.
+She told me I was to fall under the walls of Troy by the flying
+arrows of Apollo; would that Hector, the best man among the
+Trojans, might there slay me; then should I fall a hero by the
+hand of a hero; whereas now it seems that I shall come to a most
+pitiable end, trapped in this river as though I were some
+swineherd's boy, who gets carried down a torrent while trying to
+cross it during a storm."
+</para>
+
+<para>
+As soon as he had spoken thus, Neptune and Minerva came up to him
+in the likeness of two men, and took him by the hand to reassure
+him. Neptune spoke first. "Son of Peleus," said he, "be not so
+exceeding fearful; we are two gods, come with Jove's sanction to
+assist you, I, and Pallas Minerva. It is not your fate to perish
+in this river; he will abate presently as you will see; moreover
+we strongly advise you, if you will be guided by us, not to stay
+your hand from fighting till you have pent the Trojan host within
+the famed walls of Ilius--as many of them as may escape. Then
+kill Hector and go back to the ships, for we will vouchsafe you a
+triumph over him."
+</para>
+
+<para>
+When they had so said they went back to the other immortals, but
+Achilles strove onward over the plain, encouraged by the charge
+the gods had laid upon him. All was now covered with the flood of
+waters, and much goodly armour of the youths that had been slain
+was rifting about, as also many corpses, but he forced his way
+against the stream, speeding right onwards, nor could the broad
+waters stay him, for Minerva had endowed him with great strength.
+Nevertheless Scamander did not slacken in his pursuit, but was
+still more furious with the son of Peleus. He lifted his waters
+into a high crest and cried aloud to Simois saying, "Dear
+brother, let the two of us unite to save this man, or he will
+sack the mighty city of King Priam, and the Trojans will not hold
+out against him. Help me at once; fill your streams with water
+from their sources, rouse all your torrents to a fury; raise your
+wave on high, and let snags and stones come thundering down you
+that we may make an end of this savage creature who is now
+lording it as though he were a god. Nothing shall serve him
+longer, not strength nor comeliness, nor his fine armour, which
+forsooth shall soon be lying low in the deep waters covered over
+with mud. I will wrap him in sand, and pour tons of shingle round
+him, so that the Achaeans shall not know how to gather his bones
+for the silt in which I shall have hidden him, and when they
+celebrate his funeral they need build no barrow."
+</para>
+
+<para>
+On this he upraised his tumultuous flood high against Achilles,
+seething as it was with foam and blood and the bodies of the
+dead. The dark waters of the river stood upright and would have
+overwhelmed the son of Peleus, but Juno, trembling lest Achilles
+should be swept away in the mighty torrent, lifted her voice on
+high and called out to Vulcan her son. "Crook-foot," she cried,
+"my child, be up and doing, for I deem it is with you that
+Xanthus is fain to fight; help us at once, kindle a fierce fire;
+I will then bring up the west and the white south wind in a
+mighty hurricane from the sea, that shall bear the flames against
+the heads and armour of the Trojans and consume them, while you
+go along the banks of Xanthus burning his trees and wrapping him
+round with fire. Let him not turn you back neither by fair words
+nor foul, and slacken not till I shout and tell you. Then you may
+stay your flames."
+</para>
+
+<para>
+On this Vulcan kindled a fierce fire, which broke out first upon
+the plain and burned the many dead whom Achilles had killed and
+whose bodies were lying about in great numbers; by this means the
+plain was dried and the flood stayed. As the north wind, blowing
+on an orchard that has been sodden with autumn rain, soon dries
+it, and the heart of the owner is glad--even so the whole plain
+was dried and the dead bodies were consumed. Then he turned
+tongues of fire on to the river. He burned the elms the willows
+and the tamarisks, the lotus also, with the rushes and marshy
+herbage that grew abundantly by the banks of the river. The eels
+and fishes that go darting about everywhere in the water, these,
+too, were sorely harassed by the flames that cunning Vulcan had
+kindled, and the river himself was scalded, so that he spoke
+saying, "Vulcan, there is no god can hold his own against you. I
+cannot fight you when you flare out your flames in this way;
+strive with me no longer. Let Achilles drive the Trojans out of
+city immediately. What have I to do with quarrelling and helping
+people?"
+</para>
+
+<para>
+He was boiling as he spoke, and all his waters were seething. As
+a cauldron upon a large fire boils when it is melting the lard of
+some fatted hog, and the lard keeps bubbling up all over when the
+dry faggots blaze under it--even so were the goodly waters of
+Xanthus heated with the fire till they were boiling. He could
+flow no longer but stayed his stream, so afflicted was he by the
+blasts of fire which cunning Vulcan had raised. Then he prayed to
+Juno and besought her saying, "Juno, why should your son vex my
+stream with such especial fury? I am not so much to blame as all
+the others are who have been helping the Trojans. I will leave
+off, since you so desire it, and let son leave off also.
+Furthermore I swear never again will I do anything to save the
+Trojans from destruction, not even when all Troy is burning in
+the flames which the Achaeans will kindle."
+</para>
+
+<para>
+As soon as Juno heard this she said to her son Vulcan, "Son
+Vulcan, hold now your flames; we ought not to use such violence
+against a god for the sake of mortals."
+</para>
+
+<para>
+When she had thus spoken Vulcan quenched his flames, and the
+river went back once more into his own fair bed.
+</para>
+
+<para>
+Xanthus was now beaten, so these two left off fighting, for Juno
+stayed them though she was still angry; but a furious quarrel
+broke out among the other gods, for they were of divided
+counsels. They fell on one another with a mighty uproar--earth
+groaned, and the spacious firmament rang out as with a blare of
+trumpets. Jove heard as he was sitting on Olympus, and laughed
+for joy when he saw the gods coming to blows among themselves.
+They were not long about beginning, and Mars piercer of shields
+opened the battle. Sword in hand he sprang at once upon Minerva
+and reviled her. "Why, vixen," said he, "have you again set the
+gods by the ears in the pride and haughtiness of your heart? Have
+you forgotten how you set Diomed son of Tydeus on to wound me,
+and yourself took visible spear and drove it into me to the hurt
+of my fair body? You shall now suffer for what you then did to
+me."
+</para>
+
+<para>
+As he spoke he struck her on the terrible tasselled aegis--so
+terrible that not even can Jove's lightning pierce it. Here did
+murderous Mars strike her with his great spear. She drew back and
+with her strong hand seized a stone that was lying on the plain--
+great and rugged and black--which men of old had set for the
+boundary of a field. With this she struck Mars on the neck, and
+brought him down. Nine roods did he cover in his fall, and his
+hair was all soiled in the dust, while his armour rang rattling
+round him. But Minerva laughed and vaunted over him saying,
+"Idiot, have you not learned how far stronger I am than you, but
+you must still match yourself against me? Thus do your mother's
+curses now roost upon you, for she is angry and would do you
+mischief because you have deserted the Achaeans and are helping
+the Trojans."
+</para>
+
+<para>
+She then turned her two piercing eyes elsewhere, whereon Jove's
+daughter Venus took Mars by the hand and led him away groaning
+all the time, for it was only with great difficulty that he had
+come to himself again. When Queen Juno saw her, she said to
+Minerva, "Look, daughter of aegis-bearing Jove, unweariable, that
+vixen Venus is again taking Mars through the crowd out of the
+battle; go after her at once."
+</para>
+
+<para>
+Thus she spoke. Minerva sped after Venus with a will, and made at
+her, striking her on the bosom with her strong hand so that she
+fell fainting to the ground, and there they both lay stretched at
+full length. Then Minerva vaunted over her saying, "May all who
+help the Trojans against the Argives prove just as redoubtable
+and stalwart as Venus did when she came across me while she was
+helping Mars. Had this been so, we should long since have ended
+the war by sacking the strong city of Ilius."
+</para>
+
+<para>
+Juno smiled as she listened. Meanwhile King Neptune turned to
+Apollo saying, "Phoebus, why should we keep each other at arm's
+length? it is not well, now that the others have begun fighting;
+it will be disgraceful to us if we return to Jove's
+bronze-floored mansion on Olympus without having fought each
+other; therefore come on, you are the younger of the two, and I
+ought not to attack you, for I am older and have had more
+experience. Idiot, you have no sense, and forget how we two alone
+of all the gods fared hardly round about Ilius when we came from
+Jove's house and worked for Laomedon a whole year at a stated
+wage and he gave us his orders. I built the Trojans the wall
+about their city, so wide and fair that it might be impregnable,
+while you, Phoebus, herded cattle for him in the dales of many
+valleyed Ida. When, however, the glad hours brought round the
+time of payment, mighty Laomedon robbed us of all our hire and
+sent us off with nothing but abuse. He threatened to bind us hand
+and foot and sell us over into some distant island. He tried,
+moreover, to cut off the ears of both of us, so we went away in a
+rage, furious about the payment he had promised us, and yet
+withheld; in spite of all this, you are now showing favour to his
+people, and will not join us in compassing the utter ruin of the
+proud Trojans with their wives and children."
+</para>
+
+<para>
+And King Apollo answered, "Lord of the earthquake, you would have
+no respect for me if I were to fight you about a pack of
+miserable mortals, who come out like leaves in summer and eat the
+fruit of the field, and presently fall lifeless to the ground.
+Let us stay this fighting at once and let them settle it among
+themselves."
+</para>
+
+<para>
+He turned away as he spoke, for he would lay no hand on the
+brother of his own father. But his sister the huntress Diana,
+patroness of wild beasts, was very angry with him and said, "So
+you would fly, Far-Darter, and hand victory over to Neptune with
+a cheap vaunt to boot. Baby, why keep your bow thus idle? Never
+let me again hear you bragging in my father's house, as you have
+often done in the presence of the immortals, that you would stand
+up and fight with Neptune."
+</para>
+
+<para>
+Apollo made her no answer, but Jove's august queen was angry and
+upbraided her bitterly. "Bold vixen," she cried, "how dare you
+cross me thus? For all your bow you will find it hard to hold
+your own against me. Jove made you as a lion among women, and
+lets you kill them whenever you choose. You will find it better
+to chase wild beasts and deer upon the mountains than to fight
+those who are stronger than you are. If you would try war, do so,
+and find out by pitting yourself against me, how far stronger I
+am than you are."
+</para>
+
+<para>
+She caught both Diana's wrists with her left hand as she spoke,
+and with her right she took the bow from her shoulders, and
+laughed as she beat her with it about the ears while Diana
+wriggled and writhed under her blows. Her swift arrows were shed
+upon the ground, and she fled weeping from under Juno's hand as a
+dove that flies before a falcon to the cleft of some hollow rock,
+when it is her good fortune to escape. Even so did she fly
+weeping away, leaving her bow and arrows behind her.
+</para>
+
+<para>
+Then the slayer of Argus, guide and guardian, said to Leto,
+"Leto, I shall not fight you; it is ill to come to blows with any
+of Jove's wives. Therefore boast as you will among the immortals
+that you worsted me in fair fight."
+</para>
+
+<para>
+Leto then gathered up Diana's bow and arrows that had fallen
+about amid the whirling dust, and when she had got them she made
+all haste after her daughter. Diana had now reached Jove's
+bronze-floored mansion on Olympus, and sat herself down with many
+tears on the knees of her father, while her ambrosial raiment was
+quivering all about her. The son of Saturn drew her towards him,
+and laughing pleasantly the while began to question her saying,
+"Which of the heavenly beings, my dear child, has been treating
+you in this cruel manner, as though you had been misconducting
+yourself in the face of everybody?" and the fair-crowned goddess
+of the chase answered, "It was your wife Juno, father, who has
+been beating me; it is always her doing when there is any
+quarrelling among the immortals."
+</para>
+
+<para>
+Thus did they converse, and meanwhile Phoebus Apollo entered the
+strong city of Ilius, for he was uneasy lest the wall should not
+hold out and the Danaans should take the city then and there,
+before its hour had come; but the rest of the ever-living gods
+went back, some angry and some triumphant to Olympus, where they
+took their seats beside Jove lord of the storm cloud, while
+Achilles still kept on dealing out death alike on the Trojans and
+on their horses. As when the smoke from some burning city ascends
+to heaven when the anger of the gods has kindled it--there is
+then toil for all, and sorrow for not a few--even so did Achilles
+bring toil and sorrow on the Trojans.
+</para>
+
+<para>
+Old King Priam stood on a high tower of the wall looking down on
+huge Achilles as the Trojans fled panic-stricken before him, and
+there was none to help them. Presently he came down from off the
+tower and with many a groan went along the wall to give orders to
+the brave warders of the gate. "Keep the gates," said he, "wide
+open till the people come flying into the city, for Achilles is
+hard by and is driving them in rout before him. I see we are in
+great peril. As soon as our people are inside and in safety,
+close the strong gates for I fear lest that terrible man should
+come bounding inside along with the others."
+</para>
+
+<para>
+As he spoke they drew back the bolts and opened the gates, and
+when these were opened there was a haven of refuge for the
+Trojans. Apollo then came full speed out of the city to meet them
+and protect them. Right for the city and the high wall, parched
+with thirst and grimy with dust, still they fied on, with
+Achilles wielding his spear furiously behind them. For he was as
+one possessed, and was thirsting after glory.
+</para>
+
+<para>
+Then had the sons of the Achaeans taken the lofty gates of Troy
+if Apollo had not spurred on Agenor, valiant and noble son to
+Antenor. He put courage into his heart, and stood by his side to
+guard him, leaning against a beech tree and shrouded in thick
+darkness. When Agenor saw Achilles he stood still and his heart
+was clouded with care. "Alas," said he to himself in his dismay,
+"if I fly before mighty Achilles, and go where all the others are
+being driven in rout, he will none the less catch me and kill me
+for a coward. How would it be were I to let Achilles drive the
+others before him, and then fly from the wall to the plain that
+is behind Ilius till I reach the spurs of Ida and can hide in the
+underwood that is thereon? I could then wash the sweat from off
+me in the river and in the evening return to Ilius. But why
+commune with myself in this way? Like enough he would see me as I
+am hurrying from the city over the plain, and would speed after
+me till he had caught me--I should stand no chance against him,
+for he is mightiest of all mankind. What, then, if I go out and
+meet him in front of the city? His flesh too, I take it, can be
+pierced by pointed bronze. Life is the same in one and all, and
+men say that he is but mortal despite the triumph that Jove son
+of Saturn vouchsafes him."
+</para>
+
+<para>
+So saying he stood on his guard and awaited Achilles, for he was
+now fain to fight him. As a leopardess that bounds from out a
+thick covert to attack a hunter--she knows no fear and is not
+dismayed by the baying of the hounds; even though the man be too
+quick for her and wound her either with thrust or spear, still,
+though the spear has pierced her she will not give in till she
+has either caught him in her grip or been killed outright--even
+so did noble Agenor son of Antenor refuse to fly till he had made
+trial of Achilles, and took aim at him with his spear, holding
+his round shield before him and crying with a loud voice. "Of a
+truth," said he, "noble Achilles, you deem that you shall this
+day sack the city of the proud Trojans. Fool, there will be
+trouble enough yet before it, for there is many a brave man of us
+still inside who will stand in front of our dear parents with our
+wives and children, to defend Ilius. Here therefore, huge and
+mighty warrior though you be, here shall you die."
+</para>
+
+<para>
+As he spoke his strong hand hurled his javelin from him, and the
+spear struck Achilles on the leg beneath the knee; the greave of
+newly wrought tin rang loudly, but the spear recoiled from the
+body of him whom it had struck, and did not pierce it, for the
+gods gift stayed it. Achilles in his turn attacked noble Agenor,
+but Apollo would not vouchsafe him glory, for he snatched Agenor
+away and hid him in a thick mist, sending him out of the battle
+unmolested Then he craftily drew the son of Peleus away from
+going after the host, for he put on the semblance of Agenor and
+stood in front of Achilles, who ran towards him to give him chase
+and pursued him over the corn lands of the plain, turning him
+towards the deep waters of the river Scamander. Apollo ran but a
+little way before him and beguiled Achilles by making him think
+all the time that he was on the point of overtaking him.
+Meanwhile the rabble of routed Trojans was thankful to crowd
+within the city till their numbers thronged it; no longer did
+they dare wait for one another outside the city walls, to learn
+who had escaped and who were fallen in fight, but all whose feet
+and knees could still carry them poured pell-mell into the town.
+</para>
+</chapter>
+
+<chapter>
+<title>BOOK XXII</title>
+
+<para>
+THUS the Trojans in the city, scared like fawns, wiped the sweat
+from off them and drank to quench their thirst, leaning against
+the goodly battlements, while the Achaeans with their shields
+laid upon their shoulders drew close up to the walls. But stern
+fate bade Hector stay where he was before Ilius and the Scaean
+gates. Then Phoebus Apollo spoke to the son of Peleus saying,
+"Why, son of Peleus, do you, who are but man, give chase to me
+who am immortal? Have you not yet found out that it is a god whom
+you pursue so furiously? You did not harass the Trojans whom you
+had routed, and now they are within their walls, while you have
+been decoyed hither away from them. Me you cannot kill, for death
+can take no hold upon me."
+</para>
+
+<para>
+Achilles was greatly angered and said, "You have baulked me,
+Far-Darter, most malicious of all gods, and have drawn me away
+from the wall, where many another man would have bitten the dust
+ere he got within Ilius; you have robbed me of great glory and
+have saved the Trojans at no risk to yourself, for you have
+nothing to fear, but I would indeed have my revenge if it were in
+my power to do so."
+</para>
+
+<para>
+On this, with fell intent he made towards the city, and as the
+winning horse in a chariot race strains every nerve when he is
+flying over the plain, even so fast and furiously did the limbs
+of Achilles bear him onwards. King Priam was first to note him as
+he scoured the plain, all radiant as the star which men call
+Orion's Hound, and whose beams blaze forth in time of harvest
+more brilliantly than those of any other that shines by night;
+brightest of them all though he be, he yet bodes ill for mortals,
+for he brings fire and fever in his train--even so did Achilles'
+armour gleam on his breast as he sped onwards. Priam raised a cry
+and beat his head with his hands as he lifted them up and shouted
+out to his dear son, imploring him to return; but Hector still
+stayed before the gates, for his heart was set upon doing battle
+with Achilles. The old man reached out his arms towards him and
+bade him for pity's sake come within the walls. "Hector," he
+cried, "my son, stay not to face this man alone and unsupported,
+or you will meet death at the hands of the son of Peleus, for he
+is mightier than you. Monster that he is; would indeed that the
+gods loved him no better than I do, for so, dogs and vultures
+would soon devour him as he lay stretched on earth, and a load of
+grief would be lifted from my heart, for many a brave son has he
+reft from me, either by killing them or selling them away in the
+islands that are beyond the sea: even now I miss two sons from
+among the Trojans who have thronged within the city, Lycaon and
+Polydorus, whom Laothoe peeress among women bore me. Should they
+be still alive and in the hands of the Achaeans, we will ransom
+them with gold and bronze, of which we have store, for the old
+man Altes endowed his daughter richly; but if they are already
+dead and in the house of Hades, sorrow will it be to us two who
+were their parents; albeit the grief of others will be more
+short-lived unless you too perish at the hands of Achilles. Come,
+then, my son, within the city, to be the guardian of Trojan men
+and Trojan women, or you will both lose your own life and afford
+a mighty triumph to the son of Peleus. Have pity also on your
+unhappy father while life yet remains to him--on me, whom the son
+of Saturn will destroy by a terrible doom on the threshold of old
+age, after I have seen my sons slain and my daughters haled away
+as captives, my bridal chambers pillaged, little children dashed
+to earth amid the rage of battle, and my sons' wives dragged away
+by the cruel hands of the Achaeans; in the end fierce hounds will
+tear me in pieces at my own gates after some one has beaten the
+life out of my body with sword or spear-hounds that I myself
+reared and fed at my own table to guard my gates, but who will
+yet lap my blood and then lie all distraught at my doors. When a
+young man falls by the sword in battle, he may lie where he is
+and there is nothing unseemly; let what will be seen, all is
+honourable in death, but when an old man is slain there is
+nothing in this world more pitiable than that dogs should defile
+his grey hair and beard and all that men hide for shame."
+</para>
+
+<para>
+The old man tore his grey hair as he spoke, but he moved not the
+heart of Hector. His mother hard by wept and moaned aloud as she
+bared her bosom and pointed to the breast which had suckled him.
+"Hector," she cried, weeping bitterly the while, "Hector, my son,
+spurn not this breast, but have pity upon me too: if I have ever
+given you comfort from my own bosom, think on it now, dear son,
+and come within the wall to protect us from this man; stand not
+without to meet him. Should the wretch kill you, neither I nor
+your richly dowered wife shall ever weep, dear offshoot of
+myself, over the bed on which you lie, for dogs will devour you
+at the ships of the Achaeans."
+</para>
+
+<para>
+Thus did the two with many tears implore their son, but they
+moved not the heart of Hector, and he stood his ground awaiting
+huge Achilles as he drew nearer towards him. As serpent in its
+den upon the mountains, full fed with deadly poisons, waits for
+the approach of man--he is filled with fury and his eyes glare
+terribly as he goes writhing round his den--even so Hector leaned
+his shield against a tower that jutted out from the wall and
+stood where he was, undaunted.
+</para>
+
+<para>
+"Alas," said he to himself in the heaviness of his heart, "if I
+go within the gates, Polydamas will be the first to heap reproach
+upon me, for it was he that urged me to lead the Trojans back to
+the city on that awful night when Achilles again came forth
+against us. I would not listen, but it would have been indeed
+better if I had done so. Now that my folly has destroyed the
+host, I dare not look Trojan men and Trojan women in the face,
+lest a worse man should say, 'Hector has ruined us by his
+self-confidence.' Surely it would be better for me to return
+after having fought Achilles and slain him, or to die gloriously
+here before the city. What, again, if I were to lay down my
+shield and helmet, lean my spear against the wall and go straight
+up to noble Achilles? What if I were to promise to give up Helen,
+who was the fountainhead of all this war, and all the treasure
+that Alexandrus brought with him in his ships to Troy, aye, and
+to let the Achaeans divide the half of everything that the city
+contains among themselves? I might make the Trojans, by the
+mouths of their princes, take a solemn oath that they would hide
+nothing, but would divide into two shares all that is within the
+city--but why argue with myself in this way? Were I to go up to
+him he would show me no kind of mercy; he would kill me then and
+there as easily as though I were a woman, when I had off my
+armour. There is no parleying with him from some rock or oak
+tree as young men and maidens prattle with one another. Better
+fight him at once, and learn to which of us Jove will vouchsafe
+victory."
+</para>
+
+<para>
+Thus did he stand and ponder, but Achilles came up to him as it
+were Mars himself, plumed lord of battle. From his right shoulder
+he brandished his terrible spear of Pelian ash, and the bronze
+gleamed around him like flashing fire or the rays of the rising
+sun. Fear fell upon Hector as he beheld him, and he dared not
+stay longer where he was but fled in dismay from before the
+gates, while Achilles darted after him at his utmost speed. As a
+mountain falcon, swiftest of all birds, swoops down upon some
+cowering dove--the dove flies before him but the falcon with a
+shrill scream follows close after, resolved to have her--even so
+did Achilles make straight for Hector with all his might, while
+Hector fled under the Trojan wall as fast as his limbs could take
+him.
+</para>
+
+<para>
+On they flew along the waggon-road that ran hard by under the
+wall, past the lookout station, and past the weather-beaten wild
+fig-tree, till they came to two fair springs which feed the river
+Scamander. One of these two springs is warm, and steam rises from
+it as smoke from a burning fire, but the other even in summer is
+as cold as hail or snow, or the ice that forms on water. Here,
+hard by the springs, are the goodly washing-troughs of stone,
+where in the time of peace before the coming of the Achaeans the
+wives and fair daughters of the Trojans used to wash their
+clothes. Past these did they fly, the one in front and the other
+giving chase behind him: good was the man that fled, but better
+far was he that followed after, and swiftly indeed did they run,
+for the prize was no mere beast for sacrifice or bullock's hide,
+as it might be for a common foot-race, but they ran for the life
+of Hector. As horses in a chariot race speed round the
+turning-posts when they are running for some great prize--a
+tripod or woman--at the games in honour of some dead hero, so did
+these two run full speed three times round the city of Priam. All
+the gods watched them, and the sire of gods and men was the first
+to speak.
+</para>
+
+<para>
+"Alas," said he, "my eyes behold a man who is dear to me being
+pursued round the walls of Troy; my heart is full of pity for
+Hector, who has burned the thigh-bones of many a heifer in my
+honour, one while on the crests of many-valleyed Ida, and again
+on the citadel of Troy; and now I see noble Achilles in full
+pursuit of him round the city of Priam. What say you? Consider
+among yourselves and decide whether we shall now save him or let
+him fall, valiant though he be, before Achilles, son of Peleus."
+</para>
+
+<para>
+Then Minerva said, "Father, wielder of the lightning, lord of
+cloud and storm, what mean you? Would you pluck this mortal whose
+doom has long been decreed out of the jaws of death? Do as you
+will, but we others shall not be of a mind with you."
+</para>
+
+<para>
+And Jove answered, "My child, Trito-born, take heart. I did not
+speak in full earnest, and I will let you have your way. Do
+without let or hindrance as you are minded."
+</para>
+
+<para>
+Thus did he urge Minerva who was already eager, and down she
+darted from the topmost summits of Olympus.
+</para>
+
+<para>
+Achilles was still in full pursuit of Hector, as a hound chasing
+a fawn which he has started from its covert on the mountains, and
+hunts through glade and thicket. The fawn may try to elude him by
+crouching under cover of a bush, but he will scent her out and
+follow her up until he gets her--even so there was no escape for
+Hector from the fleet son of Peleus. Whenever he made a set to
+get near the Dardanian gates and under the walls, that his people
+might help him by showering down weapons from above, Achilles
+would gain on him and head him back towards the plain, keeping
+himself always on the city side. As a man in a dream who fails to
+lay hands upon another whom he is pursuing--the one cannot escape
+nor the other overtake--even so neither could Achilles come up
+with Hector, nor Hector break away from Achilles; nevertheless he
+might even yet have escaped death had not the time come when
+Apollo, who thus far had sustained his strength and nerved his
+running, was now no longer to stay by him. Achilles made signs to
+the Achaean host, and shook his head to show that no man was to
+aim a dart at Hector, lest another might win the glory of having
+hit him and he might himself come in second. Then, at last, as
+they were nearing the fountains for the fourth time, the father
+of all balanced his golden scales and placed a doom in each of
+them, one for Achilles and the other for Hector. As he held the
+scales by the middle, the doom of Hector fell down deep into the
+house of Hades--and then Phoebus Apollo left him. Thereon Minerva
+went close up to the son of Peleus and said, "Noble Achilles,
+favoured of heaven, we two shall surely take back to the ships a
+triumph for the Achaeans by slaying Hector, for all his lust of
+battle. Do what Apollo may as he lies grovelling before his
+father, aegis-bearing Jove, Hector cannot escape us longer. Stay
+here and take breath, while I go up to him and persuade him to
+make a stand and fight you."
+</para>
+
+<para>
+Thus spoke Minerva. Achilles obeyed her gladly, and stood still,
+leaning on his bronze-pointed ashen spear, while Minerva left him
+and went after Hector in the form and with the voice of
+Deiphobus. She came close up to him and said, "Dear brother, I
+see you are hard pressed by Achilles who is chasing you at full
+speed round the city of Priam, let us await his onset and stand
+on our defence."
+</para>
+
+<para>
+And Hector answered, "Deiphobus, you have always been dearest to
+me of all my brothers, children of Hecuba and Priam, but
+henceforth I shall rate you yet more highly, inasmuch as you have
+ventured outside the wall for my sake when all the others remain
+inside."
+</para>
+
+<para>
+Then Minerva said, "Dear brother, my father and mother went down
+on their knees and implored me, as did all my comrades, to remain
+inside, so great a fear has fallen upon them all; but I was in an
+agony of grief when I beheld you; now, therefore, let us two make
+a stand and fight, and let there be no keeping our spears in
+reserve, that we may learn whether Achilles shall kill us and
+bear off our spoils to the ships, or whether he shall fall before
+you."
+</para>
+
+<para>
+Thus did Minerva inveigle him by her cunning, and when the two
+were now close to one another great Hector was first to speak. "I
+will-no longer fly you, son of Peleus," said he, "as I have been
+doing hitherto. Three times have I fled round the mighty city of
+Priam, without daring to withstand you, but now, let me either
+slay or be slain, for I am in the mind to face you. Let us, then,
+give pledges to one another by our gods, who are the fittest
+witnesses and guardians of all covenants; let it be agreed
+between us that if Jove vouchsafes me the longer stay and I take
+your life, I am not to treat your dead body in any unseemly
+fashion, but when I have stripped you of your armour, I am to
+give up your body to the Achaeans. And do you likewise."
+</para>
+
+<para>
+Achilles glared at him and answered, "Fool, prate not to me about
+covenants. There can be no covenants between men and lions,
+wolves and lambs can never be of one mind, but hate each other
+out and out an through. Therefore there can be no understanding
+between you and me, nor may there be any covenants between us,
+till one or other shall fall and glut grim Mars with his life's
+blood. Put forth all your strength; you have need now to prove
+yourself indeed a bold soldier and man of war. You have no more
+chance, and Pallas Minerva will forthwith vanquish you by my
+spear: you shall now pay me in full for the grief you have caused
+me on account of my comrades whom you have killed in battle."
+</para>
+
+<para>
+He poised his spear as he spoke and hurled it. Hector saw it
+coming and avoided it; he watched it and crouched down so that it
+flew over his head and stuck in the ground beyond; Minerva then
+snatched it up and gave it back to Achilles without Hector's
+seeing her; Hector thereon said to the son of Peleus, "You have
+missed your aim, Achilles, peer of the gods, and Jove has not yet
+revealed to you the hour of my doom, though you made sure that he
+had done so. You were a false-tongued liar when you deemed that I
+should forget my valour and quail before you. You shall not drive
+spear into the back of a runaway--drive it, should heaven so
+grant you power, drive it into me as I make straight towards you;
+and now for your own part avoid my spear if you can--would that
+you might receive the whole of it into your body; if you were
+once dead the Trojans would find the war an easier matter, for it
+is you who have harmed them most."
+</para>
+
+<para>
+He poised his spear as he spoke and hurled it. His aim was true
+for he hit the middle of Achilles' shield, but the spear
+rebounded from it, and did not pierce it. Hector was angry when
+he saw that the weapon had sped from his hand in vain, and stood
+there in dismay for he had no second spear. With a loud cry he
+called Deiphobus and asked him for one, but there was no man;
+then he saw the truth and said to himself, "Alas! the gods have
+lured me on to my destruction. I deemed that the hero Deiphobus
+was by my side, but he is within the wall, and Minerva has
+inveigled me; death is now indeed exceedingly near at hand and
+there is no way out of it--for so Jove and his son Apollo the
+far-darter have willed it, though heretofore they have been ever
+ready to protect me. My doom has come upon me; let me not then
+die ingloriously and without a struggle, but let me first do some
+great thing that shall be told among men hereafter."
+</para>
+
+<para>
+As he spoke he drew the keen blade that hung so great and strong
+by his side, and gathering himself together be sprang on Achilles
+like a soaring eagle which swoops down from the clouds on to some
+lamb or timid hare--even so did Hector brandish his sword and
+spring upon Achilles. Achilles mad with rage darted towards him,
+with his wondrous shield before his breast, and his gleaming
+helmet, made with four layers of metal, nodding fiercely forward.
+The thick tresses of gold with which Vulcan had crested the
+helmet floated round it, and as the evening star that shines
+brighter than all others through the stillness of night, even
+such was the gleam of the spear which Achilles poised in his
+right hand, fraught with the death of noble Hector. He eyed his
+fair flesh over and over to see where he could best wound it, but
+all was protected by the goodly armour of which Hector had
+spoiled Patroclus after he had slain him, save only the throat
+where the collar-bones divide the neck from the shoulders, and
+this is a most deadly place: here then did Achilles strike him as
+he was coming on towards him, and the point of his spear went
+right through the fleshy part of the neck, but it did not sever
+his windpipe so that he could still speak. Hector fell headlong,
+and Achilles vaunted over him saying, "Hector, you deemed that
+you should come off scatheless when you were spoiling Patroclus,
+and recked not of myself who was not with him. Fool that you
+were: for I, his comrade, mightier far than he, was still left
+behind him at the ships, and now I have laid you low. The
+Achaeans shall give him all due funeral rites, while dogs and
+vultures shall work their will upon yourself."
+</para>
+
+<para>
+Then Hector said, as the life ebbed out of him, "I pray you by
+your life and knees, and by your parents, let not dogs devour me
+at the ships of the Achaeans, but accept the rich treasure of
+gold and bronze which my father and mother will offer you, and
+send my body home, that the Trojans and their wives may give me
+my dues of fire when I am dead."
+</para>
+
+<para>
+Achilles glared at him and answered, "Dog, talk not to me neither
+of knees nor parents; would that I could be as sure of being able
+to cut your flesh into pieces and eat it raw, for the ill you
+have done me, as I am that nothing shall save you from the
+dogs--it shall not be, though they bring ten or twenty-fold
+ransom and weigh it out for me on the spot, with promise of yet
+more hereafter. Though Priam son of Dardanus should bid them
+offer me your weight in gold, even so your mother shall never lay
+you out and make lament over the son she bore, but dogs and
+vultures shall eat you utterly up."
+</para>
+
+<para>
+Hector with his dying breath then said, "I know you what you are,
+and was sure that I should not move you, for your heart is hard
+as iron; look to it that I bring not heaven's anger upon you on
+the day when Paris and Phoebus Apollo, valiant though you be,
+shall slay you at the Scaean gates."
+</para>
+
+<para>
+When he had thus said the shrouds of death enfolded him, whereon
+his soul went out of him and flew down to the house of Hades,
+lamenting its sad fate that it should enjoy youth and strength no
+longer. But Achilles said, speaking to the dead body, "Die; for
+my part I will accept my fate whensoever Jove and the other gods
+see fit to send it."
+</para>
+
+<para>
+As he spoke he drew his spear from the body and set it on one
+side; then he stripped the blood-stained armour from Hector's
+shoulders while the other Achaeans came running up to view his
+wondrous strength and beauty; and no one came near him without
+giving him a fresh wound. Then would one turn to his neighbour
+and say, "It is easier to handle Hector now than when he was
+flinging fire on to our ships" and as he spoke he would thrust
+his spear into him anew.
+</para>
+
+<para>
+When Achilles had done spoiling Hector of his armour, he stood
+among the Argives and said, "My friends, princes and counsellors
+of the Argives, now that heaven has vouchsafed us to overcome
+this man, who has done us more hurt than all the others together,
+consider whether we should not attack the city in force, and
+discover in what mind the Trojans may be. We should thus learn
+whether they will desert their city now that Hector has fallen,
+or will still hold out even though he is no longer living. But
+why argue with myself in this way, while Patroclus is still lying
+at the ships unburied, and unmourned--he whom I can never forget
+so long as I am alive and my strength fails not? Though men
+forget their dead when once they are within the house of Hades,
+yet not even there will I forget the comrade whom I have lost.
+Now, therefore, Achaean youths, let us raise the song of victory
+and go back to the ships taking this man along with us; for we
+have achieved a mighty triumph and have slain noble Hector to
+whom the Trojans prayed throughout their city as though he were a
+god."
+</para>
+
+<para>
+On this he treated the body of Hector with contumely: he pierced
+the sinews at the back of both his feet from heel to ancle and
+passed thongs of ox-hide through the slits he had made: thus he
+made the body fast to his chariot, letting the head trail upon
+the ground. Then when he had put the goodly armour on the chariot
+and had himself mounted, he lashed his horses on and they flew
+forward nothing loth. The dust rose from Hector as he was being
+dragged along, his dark hair flew all abroad, and his head once
+so comely was laid low on earth, for Jove had now delivered him
+into the hands of his foes to do him outrage in his own land.
+</para>
+
+<para>
+Thus was the head of Hector being dishonoured in the dust. His
+mother tore her hair, and flung her veil from her with a loud cry
+as she looked upon her son. His father made piteous moan, and
+throughout the city the people fell to weeping and wailing. It
+was as though the whole of frowning Ilius was being smirched with
+fire. Hardly could the people hold Priam back in his hot haste to
+rush without the gates of the city. He grovelled in the mire and
+besought them, calling each one of them by his name. "Let be, my
+friends," he cried, "and for all your sorrow, suffer me to go
+single-handed to the ships of the Achaeans. Let me beseech this
+cruel and terrible man, if maybe he will respect the feeling of
+his fellow-men, and have compassion on my old age. His own father
+is even such another as myself--Peleus, who bred him and reared
+him to be the bane of us Trojans, and of myself more than of all
+others. Many a son of mine has he slain in the flower of his
+youth, and yet, grieve for these as I may, I do so for one--
+Hector--more than for them all, and the bitterness of my sorrow
+will bring me down to the house of Hades. Would that he had died
+in my arms, for so both his ill-starred mother who bore him, and
+myself, should have had the comfort of weeping and mourning over
+him."
+</para>
+
+<para>
+Thus did he speak with many tears, and all the people of the city
+joined in his lament. Hecuba then raised the cry of wailing among
+the Trojans. "Alas, my son," she cried, "what have I left to live
+for now that you are no more? Night and day did I glory in you
+throughout the city, for you were a tower of strength to all in
+Troy, and both men and women alike hailed you as a god. So long
+as you lived you were their pride, but now death and destruction
+have fallen upon you."
+</para>
+
+<para>
+Hector's wife had as yet heard nothing, for no one had come to
+tell her that her husband had remained without the gates. She was
+at her loom in an inner part of the house, weaving a double
+purple web, and embroidering it with many flowers. She told her
+maids to set a large tripod on the fire, so as to have a warm
+bath ready for Hector when he came out of battle; poor woman, she
+knew not that he was now beyond the reach of baths, and that
+Minerva had laid him low by the hands of Achilles. She heard the
+cry coming as from the wall, and trembled in every limb; the
+shuttle fell from her hands, and again she spoke to her
+waiting-women. "Two of you," she said, "come with me that I may
+learn what it is that has befallen; I heard the voice of my
+husband's honoured mother; my own heart beats as though it would
+come into my mouth and my limbs refuse to carry me; some great
+misfortune for Priam's children must be at hand. May I never live
+to hear it, but I greatly fear that Achilles has cut off the
+retreat of brave Hector and has chased him on to the plain where
+he was singlehanded; I fear he may have put an end to the
+reckless daring which possessed my husband, who would never
+remain with the body of his men, but would dash on far in front,
+foremost of them all in valour."
+</para>
+
+<para>
+Her heart beat fast, and as she spoke she flew from the house
+like a maniac, with her waiting-women following after. When she
+reached the battlements and the crowd of people, she stood
+looking out upon the wall, and saw Hector being borne away in
+front of the city--the horses dragging him without heed or care
+over the ground towards the ships of the Achaeans. Her eyes were
+then shrouded as with the darkness of night and she fell fainting
+backwards. She tore the attiring from her head and flung it from
+her, the frontlet and net with its plaited band, and the veil
+which golden Venus had given her on the day when Hector took her
+with him from the house of Eetion, after having given countless
+gifts of wooing for her sake. Her husband's sisters and the wives
+of his brothers crowded round her and supported her, for she was
+fain to die in her distraction; when she again presently breathed
+and came to herself, she sobbed and made lament among the Trojans
+saying, "Woe is me, O Hector; woe, indeed, that to share a common
+lot we were born, you at Troy in the house of Priam, and I at
+Thebes under the wooded mountain of Placus in the house of Eetion
+who brought me up when I was a child--ill-starred sire of an
+ill-starred daughter--would that he had never begotten me. You
+are now going into the house of Hades under the secret places of
+the earth, and you leave me a sorrowing widow in your house. The
+child, of whom you and I are the unhappy parents, is as yet a
+mere infant. Now that you are gone, O Hector, you can do nothing
+for him nor he for you. Even though he escape the horrors of this
+woeful war with the Achaeans, yet shall his life henceforth be
+one of labour and sorrow, for others will seize his lands. The
+day that robs a child of his parents severs him from his own
+kind; his head is bowed, his cheeks are wet with tears, and he
+will go about destitute among the friends of his father, plucking
+one by the cloak and another by the shirt. Some one or other of
+these may so far pity him as to hold the cup for a moment towards
+him and let him moisten his lips, but he must not drink enough to
+wet the roof of his mouth; then one whose parents are alive will
+drive him from the table with blows and angry words. 'Out with
+you,' he will say, 'you have no father here,' and the child will
+go crying back to his widowed mother--he, Astyanax, who erewhile
+would sit upon his father's knees, and have none but the
+daintiest and choicest morsels set before him. When he had played
+till he was tired and went to sleep, he would lie in a bed, in
+the arms of his nurse, on a soft couch, knowing neither want nor
+care, whereas now that he has lost his father his lot will be
+full of hardship--he, whom the Trojans name Astyanax, because
+you, O Hector, were the only defence of their gates and
+battlements. The wriggling writhing worms will now eat you at the
+ships, far from your parents, when the dogs have glutted
+themselves upon you. You will lie naked, although in your house
+you have fine and goodly raiment made by hands of women. This
+will I now burn; it is of no use to you, for you can never again
+wear it, and thus you will have respect shown you by the Trojans
+both men and women."
+</para>
+
+<para>
+In such wise did she cry aloud amid her tears, and the women
+joined in her lament.
+</para>
+</chapter>
+
+<chapter>
+<title>BOOK XXIII</title>
+
+<para>
+THUS did they make their moan throughout the city, while the
+Achaeans when they reached the Hellespont went back every man to
+his own ship. But Achilles would not let the Myrmidons go, and
+spoke to his brave comrades saying, "Myrmidons, famed horsemen
+and my own trusted friends, not yet, forsooth, let us unyoke, but
+with horse and chariot draw near to the body and mourn Patroclus,
+in due honour to the dead. When we have had full comfort of
+lamentation we will unyoke our horses and take supper all of us
+here."
+</para>
+
+<para>
+On this they all joined in a cry of wailing and Achilles led them
+in their lament. Thrice did they drive their chariots all
+sorrowing round the body, and Thetis stirred within them a still
+deeper yearning. The sands of the seashore and the men's armour
+were wet with their weeping, so great a minister of fear was he
+whom they had lost. Chief in all their mourning was the son of
+Peleus: he laid his bloodstained hand on the breast of his
+friend. "Fare well," he cried, "Patroclus, even in the house of
+Hades. I will now do all that I erewhile promised you; I will
+drag Hector hither and let dogs devour him raw; twelve noble sons
+of Trojans will I also slay before your pyre to avenge you."
+</para>
+
+<para>
+As he spoke he treated the body of noble Hector with contumely,
+laying it at full length in the dust beside the bier of
+Patroclus. The others then put off every man his armour, took the
+horses from their chariots, and seated themselves in great
+multitude by the ship of the fleet descendant of Aeacus, who
+thereon feasted them with an abundant funeral banquet. Many a
+goodly ox, with many a sheep and bleating goat did they butcher
+and cut up; many a tusked boar moreover, fat and well-fed, did
+they singe and set to roast in the flames of Vulcan; and rivulets
+of blood flowed all round the place where the body was lying.
+</para>
+
+<para>
+Then the princes of the Achaeans took the son of Peleus to
+Agamemnon, but hardly could they persuade him to come with them,
+so wroth was he for the death of his comrade. As soon as they
+reached Agamemnon's tent they told the serving-men to set a large
+tripod over the fire in case they might persuade the son of
+Peleus to wash the clotted gore from this body, but he denied
+them sternly, and swore it with a solemn oath, saying, "Nay, by
+King Jove, first and mightiest of all gods, it is not meet that
+water should touch my body, till I have laid Patroclus on the
+flames, have built him a barrow, and shaved my head--for so long
+as I live no such second sorrow shall ever draw nigh me. Now,
+therefore, let us do all that this sad festival demands, but at
+break of day, King Agamemnon, bid your men bring wood, and
+provide all else that the dead may duly take into the realm of
+darkness; the fire shall thus burn him out of our sight the
+sooner, and the people shall turn again to their own labours."
+</para>
+
+<para>
+Thus did he speak, and they did even as he had said. They made
+haste to prepare the meal, they ate, and every man had his full
+share so that all were satisfied. As soon as they had had enough
+to eat and drink, the others went to their rest each in his own
+tent, but the son of Peleus lay grieving among his Myrmidons by
+the shore of the sounding sea, in an open place where the waves
+came surging in one after another. Here a very deep slumber took
+hold upon him and eased the burden of his sorrows, for his limbs
+were weary with chasing Hector round windy Ilius. Presently the
+sad spirit of Patroclus drew near him, like what he had been in
+stature, voice, and the light of his beaming eyes, clad, too, as
+he had been clad in life. The spirit hovered over his head and
+said--
+</para>
+
+<para>
+"You sleep, Achilles, and have forgotten me; you loved me living,
+but now that I am dead you think for me no further. Bury me with
+all speed that I may pass the gates of Hades; the ghosts, vain
+shadows of men that can labour no more, drive me away from them;
+they will not yet suffer me to join those that are beyond the
+river, and I wander all desolate by the wide gates of the house
+of Hades. Give me now your hand I pray you, for when you have
+once given me my dues of fire, never shall I again come forth out
+of the house of Hades. Nevermore shall we sit apart and take
+sweet counsel among the living; the cruel fate which was my
+birth-right has yawned its wide jaws around me--nay, you too
+Achilles, peer of gods, are doomed to die beneath the wall of the
+noble Trojans.
+</para>
+
+<para>
+"One prayer more will I make you, if you will grant it; let not
+my bones be laid apart from yours, Achilles, but with them; even
+as we were brought up together in your own home, what time
+Menoetius brought me to you as a child from Opoeis because by a
+sad spite I had killed the son of Amphidamas--not of set purpose,
+but in childish quarrel over the dice. The knight Peleus took me
+into his house, entreated me kindly, and named me to be your
+squire; therefore let our bones lie in but a single urn, the
+two-handled golden vase given to you by your mother."
+</para>
+
+<para>
+And Achilles answered, "Why, true heart, are you come hither to
+lay these charges upon me? will of my own self do all as you have
+bidden me. Draw closer to me, let us once more throw our arms
+around one another, and find sad comfort in the sharing of our
+sorrows."
+</para>
+
+<para>
+He opened his arms towards him as he spoke and would have clasped
+him in them, but there was nothing, and the spirit vanished as a
+vapour, gibbering and whining into the earth. Achilles sprang to
+his feet, smote his two hands, and made lamentation saying, "Of a
+truth even in the house of Hades there are ghosts and phantoms
+that have no life in them; all night long the sad spirit of
+Patroclus has hovered over head making piteous moan, telling me
+what I am to do for him, and looking wondrously like himself."
+</para>
+
+<para>
+Thus did he speak and his words set them all weeping and mourning
+about the poor dumb dead, till rosy-fingered morn appeared. Then
+King Agamemnon sent men and mules from all parts of the camp, to
+bring wood, and Meriones, squire to Idomeneus, was in charge over
+them. They went out with woodmen's axes and strong ropes in their
+hands, and before them went the mules. Up hill and down dale did
+they go, by straight ways and crooked, and when they reached the
+heights of many-fountained Ida, they laid their axes to the roots
+of many a tall branching oak that came thundering down as they
+felled it. They split the trees and bound them behind the mules,
+which then wended their way as they best could through the thick
+brushwood on to the plain. All who had been cutting wood bore
+logs, for so Meriones squire to Idomeneus had bidden them, and
+they threw them down in a line upon the seashore at the place
+where Achilles would make a mighty monument for Patroclus and for
+himself.
+</para>
+
+<para>
+When they had thrown down their great logs of wood over the whole
+ground, they stayed all of them where they were, but Achilles
+ordered his brave Myrmidons to gird on their armour, and to yoke
+each man his horses; they therefore rose, girded on their armour
+and mounted each his chariot--they and their charioteers with
+them. The chariots went before, and they that were on foot
+followed as a cloud in their tens of thousands after. In the
+midst of them his comrades bore Patroclus and covered him with
+the locks of their hair which they cut off and threw upon his
+body. Last came Achilles with his head bowed for sorrow, so noble
+a comrade was he taking to the house of Hades.
+</para>
+
+<para>
+When they came to the place of which Achilles had told them they
+laid the body down and built up the wood. Achilles then bethought
+him of another matter. He went a space away from the pyre, and
+cut off the yellow lock which he had let grow for the river
+Spercheius. He looked all sorrowfully out upon the dark sea, and
+said, "Spercheius, in vain did my father Peleus vow to you that
+when I returned home to my loved native land I should cut off
+this lock and offer you a holy hecatomb; fifty she-goats was I to
+sacrifice to you there at your springs, where is your grove and
+your altar fragrant with burnt-offerings. Thus did my father vow,
+but you have not fulfilled his prayer; now, therefore, that I
+shall see my home no more, I give this lock as a keepsake to the
+hero Patroclus."
+</para>
+
+<para>
+As he spoke he placed the lock in the hands of his dear comrade,
+and all who stood by were filled with yearning and lamentation.
+The sun would have gone down upon their mourning had not Achilles
+presently said to Agamemnon, "Son of Atreus, for it is to you
+that the people will give ear, there is a time to mourn and a
+time to cease from mourning; bid the people now leave the pyre
+and set about getting their dinners: we, to whom the dead is
+dearest, will see to what is wanted here, and let the other
+princes also stay by me."
+</para>
+
+<para>
+When King Agamemnon heard this he dismissed the people to their
+ships, but those who were about the dead heaped up wood and built
+a pyre a hundred feet this way and that; then they laid the dead
+all sorrowfully upon the top of it. They flayed and dressed many
+fat sheep and oxen before the pyre, and Achilles took fat from
+all of them and wrapped the body therein from head to foot,
+heaping the flayed carcases all round it. Against the bier he
+leaned two-handled jars of honey and unguents; four proud horses
+did he then cast upon the pyre, groaning the while he did so. The
+dead hero had had house-dogs; two of them did Achilles slay and
+threw upon the pyre; he also put twelve brave sons of noble
+Trojans to the sword and laid them with the rest, for he was full
+of bitterness and fury. Then he committed all to the resistless
+and devouring might of the fire; he groaned aloud and called on
+his dead comrade by name. "Fare well," he cried, "Patroclus, even
+in the house of Hades; I am now doing all that I have promised
+you. Twelve brave sons of noble Trojans shall the flames consume
+along with yourself, but dogs, not fire, shall devour the flesh
+of Hector son of Priam."
+</para>
+
+<para>
+Thus did he vaunt, but the dogs came not about the body of
+Hector, for Jove's daughter Venus kept them off him night and
+day, and anointed him with ambrosial oil of roses that his flesh
+might not be torn when Achilles was dragging him about. Phoebus
+Apollo moreover sent a dark cloud from heaven to earth, which
+gave shade to the whole place where Hector lay, that the heat of
+the sun might not parch his body.
+</para>
+
+<para>
+Now the pyre about dead Patroclus would not kindle. Achilles
+therefore bethought him of another matter; he went apart and
+prayed to the two winds Boreas and Zephyrus vowing them goodly
+offerings. He made them many drink-offerings from the golden cup
+and besought them to come and help him that the wood might make
+haste to kindle and the dead bodies be consumed. Fleet Iris heard
+him praying and started off to fetch the winds. They were holding
+high feast in the house of boisterous Zephyrus when Iris came
+running up to the stone threshold of the house and stood there,
+but as soon as they set eyes on her they all came towards her and
+each of them called her to him, but Iris would not sit down. "I
+cannot stay," she said, "I must go back to the streams of Oceanus
+and the land of the Ethiopians who are offering hecatombs to the
+immortals, and I would have my share; but Achilles prays that
+Boreas and shrill Zephyrus will come to him, and he vows them
+goodly offerings; he would have you blow upon the pyre of
+Patroclus for whom all the Achaeans are lamenting."
+</para>
+
+<para>
+With this she left them, and the two winds rose with a cry that
+rent the air and swept the clouds before them. They blew on and
+on until they came to the sea, and the waves rose high beneath
+them, but when they reached Troy they fell upon the pyre till the
+mighty flames roared under the blast that they blew. All night
+long did they blow hard and beat upon the fire, and all night
+long did Achilles grasp his double cup, drawing wine from a
+mixing-bowl of gold, and calling upon the spirit of dead
+Patroclus as he poured it upon the ground until the earth was
+drenched. As a father mourns when he is burning the bones of his
+bridegroom son whose death has wrung the hearts of his parents,
+even so did Achilles mourn while burning the body of his comrade,
+pacing round the bier with piteous groaning and lamentation.
+</para>
+
+<para>
+At length as the Morning Star was beginning to herald the light
+which saffron-mantled Dawn was soon to suffuse over the sea, the
+flames fell and the fire began to die. The winds then went home
+beyond the Thracian sea, which roared and boiled as they swept
+over it. The son of Peleus now turned away from the pyre and lay
+down, overcome with toil, till he fell into a sweet slumber.
+Presently they who were about the son of Atreus drew near in a
+body, and roused him with the noise and tramp of their coming. He
+sat upright and said, "Son of Atreus, and all other princes of
+the Achaeans, first pour red wine everywhere upon the fire and
+quench it; let us then gather the bones of Patroclus son of
+Menoetius, singling them out with care; they are easily found,
+for they lie in the middle of the pyre, while all else, both men
+and horses, has been thrown in a heap and burned at the outer
+edge. We will lay the bones in a golden urn, in two layers of
+fat, against the time when I shall myself go down into the house
+of Hades. As for the barrow, labour not to raise a great one now,
+but such as is reasonable. Afterwards, let those Achaeans who may
+be left at the ships when I am gone, build it both broad and
+high."
+</para>
+
+<para>
+Thus he spoke and they obeyed the word of the son of Peleus.
+First they poured red wine upon the thick layer of ashes and
+quenched the fire. With many tears they singled out the whitened
+bones of their loved comrade and laid them within a golden urn in
+two layers of fat: they then covered the urn with a linen cloth
+and took it inside the tent. They marked off the circle where the
+barrow should be, made a foundation for it about the pyre, and
+forthwith heaped up the earth. When they had thus raised a mound
+they were going away, but Achilles stayed the people and made
+them sit in assembly. He brought prizes from the
+ships--cauldrons, tripods, horses and mules, noble oxen, women
+with fair girdles, and swart iron.
+</para>
+
+<para>
+The first prize he offered was for the chariot races--a woman
+skilled in all useful arts, and a three-legged cauldron that had
+ears for handles, and would hold twenty-two measures. This was
+for the man who came in first. For the second there was a
+six-year old mare, unbroken, and in foal to a he-ass; the third
+was to have a goodly cauldron that had never yet been on the
+fire; it was still bright as when it left the maker, and would
+hold four measures. The fourth prize was two talents of gold, and
+the fifth a two-handled urn as yet unsoiled by smoke. Then he
+stood up and spoke among the Argives saying--
+</para>
+
+<para>
+"Son of Atreus, and all other Achaeans, these are the prizes that
+lie waiting the winners of the chariot races. At any other time I
+should carry off the first prize and take it to my own tent; you
+know how far my steeds excel all others--for they are immortal;
+Neptune gave them to my father Peleus, who in his turn gave them
+to myself; but I shall hold aloof, I and my steeds that have lost
+their brave and kind driver, who many a time has washed them in
+clear water and anointed their manes with oil. See how they stand
+weeping here, with their manes trailing on the ground in the
+extremity of their sorrow. But do you others set yourselves in
+order throughout the host, whosoever has confidence in his horses
+and in the strength of his chariot."
+</para>
+
+<para>
+Thus spoke the son of Peleus and the drivers of chariots
+bestirred themselves. First among them all uprose Eumelus, king
+of men, son of Admetus, a man excellent in horsemanship. Next to
+him rose mighty Diomed son of Tydeus; he yoked the Trojan horses
+which he had taken from Aeneas, when Apollo bore him out of the
+fight. Next to him, yellow-haired Menelaus son of Atreus rose and
+yoked his fleet horses, Agamemnon's mare Aethe, and his own horse
+Podargus. The mare had been given to Agamemnon by Echepolus son
+of Anchises, that he might not have to follow him to Ilius, but
+might stay at home and take his ease; for Jove had endowed him
+with great wealth and he lived in spacious Sicyon. This mare, all
+eager for the race, did Menelaus put under the yoke.
+</para>
+
+<para>
+Fourth in order Antilochus, son to noble Nestor son of Neleus,
+made ready his horses. These were bred in Pylos, and his father
+came up to him to give him good advice of which, however, he
+stood in but little need. "Antilochus," said Nestor, "you are
+young, but Jove and Neptune have loved you well, and have made
+you an excellent horseman. I need not therefore say much by way
+of instruction. You are skilful at wheeling your horses round the
+post, but the horses themselves are very slow, and it is this
+that will, I fear, mar your chances. The other drivers know less
+than you do, but their horses are fleeter; therefore, my dear
+son, see if you cannot hit upon some artifice whereby you may
+insure that the prize shall not slip through your fingers. The
+woodman does more by skill than by brute force; by skill the
+pilot guides his storm-tossed barque over the sea, and so by
+skill one driver can beat another. If a man go wide in rounding
+this way and that, whereas a man who knows what he is doing may
+have worse horses, but he will keep them well in hand when he
+sees the doubling-post; he knows the precise moment at which to
+pull the rein, and keeps his eye well on the man in front of him.
+I will give you this certain token which cannot escape your
+notice. There is a stump of a dead tree--oak or pine as it may
+be--some six feet above the ground, and not yet rotted away by
+rain; it stands at the fork of the road; it has two white stones
+set one on each side, and there is a clear course all round it.
+It may have been a monument to some one long since dead, or it
+may have been used as a doubling-post in days gone by; now,
+however, it has been fixed on by Achilles as the mark round which
+the chariots shall turn; hug it as close as you can, but as you
+stand in your chariot lean over a little to the left; urge on
+your right-hand horse with voice and lash, and give him a loose
+rein, but let the left-hand horse keep so close in, that the nave
+of your wheel shall almost graze the post; but mind the stone, or
+you will wound your horses and break your chariot in pieces,
+which would be sport for others but confusion for yourself.
+Therefore, my dear son, mind well what you are about, for if you
+can be first to round the post there is no chance of any one
+giving you the go-by later, not even though you had Adrestus's
+horse Arion behind you--a horse which is of divine race--or those
+of Laomedon, which are the noblest in this country."
+</para>
+
+<para>
+When Nestor had made an end of counselling his son he sat down in
+his place, and fifth in order Meriones got ready his horses.
+They then all mounted their chariots and cast lots. Achilles
+shook the helmet, and the lot of Antilochus son of Nestor fell
+out first; next came that of King Eumelus, and after his, those
+of Menelaus son of Atreus and of Meriones. The last place fell to
+the lot of Diomed son of Tydeus, who was the best man of them
+all. They took their places in line; Achilles showed them the
+doubling-post round which they were to turn, some way off upon
+the plain; here he stationed his father's follower Phoenix as
+umpire, to note the running, and report truly.
+</para>
+
+<para>
+At the same instant they all of them lashed their horses, struck
+them with the reins, and shouted at them with all their might.
+They flew full speed over the plain away from the ships, the dust
+rose from under them as it were a cloud or whirlwind, and their
+manes were all flying in the wind. At one moment the chariots
+seemed to touch the ground, and then again they bounded into the
+air; the drivers stood erect, and their hearts beat fast and
+furious in their lust of victory. Each kept calling on his
+horses, and the horses scoured the plain amid the clouds of dust
+that they raised.
+</para>
+
+<para>
+It was when they were doing the last part of the course on their
+way back towards the sea that their pace was strained to the
+utmost and it was seen what each could do. The horses of the
+descendant of Pheres now took the lead, and close behind them
+came the Trojan stallions of Diomed. They seemed as if about to
+mount Eumelus's chariot, and he could feel their warm breath on
+his back and on his broad shoulders, for their heads were close
+to him as they flew over the course. Diomed would have now passed
+him, or there would have been a dead heat, but Phoebus Apollo to
+spite him made him drop his whip. Tears of anger fell from his
+eyes as he saw the mares going on faster than ever, while his own
+horses lost ground through his having no whip. Minerva saw the
+trick which Apollo had played the son of Tydeus, so she brought
+him his whip and put spirit into his horses; moreover she went
+after the son of Admetus in a rage and broke his yoke for him;
+the mares went one to one side of the course, and the other to
+the other, and the pole was broken against the ground. Eumelus
+was thrown from his chariot close to the wheel; his elbows,
+mouth, and nostrils were all torn, and his forehead was bruised
+above his eyebrows; his eyes filled with tears and he could find
+no utterance. But the son of Tydeus turned his horses aside and
+shot far ahead, for Minerva put fresh strength into them and
+covered Diomed himself with glory.
+</para>
+
+<para>
+Menelaus son of Atreus came next behind him, but Antilochus
+called to his father's horses. "On with you both," he cried, "and
+do your very utmost. I do not bid you try to beat the steeds of
+the son of Tydeus, for Minerva has put running into them, and has
+covered Diomed with glory; but you must overtake the horses of
+the son of Atreus and not be left behind, or Aethe who is so
+fleet will taunt you. Why, my good fellows, are you lagging? I
+tell you, and it shall surely be--Nestor will keep neither of
+you, but will put both of you to the sword, if we win any the
+worse a prize through your carelessness. Fly after them at your
+utmost speed; I will hit on a plan for passing them in a narrow
+part of the way, and it shall not fail me."
+</para>
+
+<para>
+They feared the rebuke of their master, and for a short space
+went quicker. Presently Antilochus saw a narrow place where the
+road had sunk. The ground was broken, for the winter's rain had
+gathered and had worn the road so that the whole place was
+deepened. Menelaus was making towards it so as to get there
+first, for fear of a foul, but Antilochus turned his horses out
+of the way, and followed him a little on one side. The son of
+Atreus was afraid and shouted out, "Antilochus, you are driving
+recklessly; rein in your horses; the road is too narrow here, it
+will be wider soon, and you can pass me then; if you foul my
+chariot you may bring both of us to a mischief."
+</para>
+
+<para>
+But Antilochus plied his whip, and drove faster, as though he had
+not heard him. They went side by side for about as far as a young
+man can hurl a disc from his shoulder when he is trying his
+strength, and then Menelaus's mares drew behind, for he left off
+driving for fear the horses should foul one another and upset the
+chariots; thus, while pressing on in quest of victory, they might
+both come headlong to the ground. Menelaus then upbraided
+Antilochus and said, "There is no greater trickster living than
+you are; go, and bad luck go with you; the Achaeans say not well
+that you have understanding, and come what may you shall not bear
+away the prize without sworn protest on my part."
+</para>
+
+<para>
+Then he called on his horses and said to them, "Keep your pace,
+and slacken not; the limbs of the other horses will weary sooner
+than yours, for they are neither of them young."
+</para>
+
+<para>
+The horses feared the rebuke of their master, and went faster, so
+that they were soon nearly up with the others.
+</para>
+
+<para>
+Meanwhile the Achaeans from their seats were watching how the
+horses went, as they scoured the plain amid clouds of their own
+dust. Idomeneus captain of the Cretans was first to make out the
+running, for he was not in the thick of the crowd, but stood on
+the most commanding part of the ground. The driver was a long way
+off, but Idomeneus could hear him shouting, and could see the
+foremost horse quite plainly--a chestnut with a round white star,
+like the moon, on its forehead. He stood up and said among the
+Argives, "My friends, princes and counsellors of the Argives, can
+you see the running as well as I can? There seems to be another
+pair in front now, and another driver; those that led off at the
+start must have been disabled out on the plain. I saw them at
+first making their way round the doubling-post, but now, though I
+search the plain of Troy, I cannot find them. Perhaps the reins
+fell from the driver's hand so that he lost command of his horses
+at the doubling-post, and could not turn it. I suppose he must
+have been thrown out there, and broken his chariot, while his
+mares have left the course and gone off wildly in a panic. Come
+up and see for yourselves, I cannot make out for certain, but the
+driver seems an Aetolian by descent, ruler over the Argives,
+brave Diomed the son of Tydeus."
+</para>
+
+<para>
+Ajax the son of Oileus took him up rudely and said, "Idomeneus,
+why should you be in such a hurry to tell us all about it, when
+the mares are still so far out upon the plain? You are none of
+the youngest, nor your eyes none of the sharpest, but you are
+always laying down the law. You have no right to do so, for there
+are better men here than you are. Eumelus's horses are in front
+now, as they always have been, and he is on the chariot holding
+the reins."
+</para>
+
+<para>
+The captain of the Cretans was angry, and answered, "Ajax you are
+an excellent railer, but you have no judgement, and are wanting
+in much else as well, for you have a vile temper. I will wager
+you a tripod or cauldron, and Agamemnon son of Atreus shall
+decide whose horses are first. You will then know to your cost."
+</para>
+
+<para>
+Ajax son of Oileus was for making him an angry answer, and there
+would have been yet further brawling between them, had not
+Achilles risen in his place and said, "Cease your railing, Ajax
+and Idomeneus; is it not you would be scandalised if you saw any
+one else do the like: sit down and keep your eyes on the horses;
+they are speeding towards the winning-post and will be bere
+directly. You will then both of you know whose horses are first,
+and whose come after."
+</para>
+
+<para>
+As he was speaking, the son of Tydeus came driving in, plying his
+whip lustily from his shoulder, and his horses stepping high as
+they flew over the course. The sand and grit rained thick on the
+driver, and the chariot inlaid with gold and tin ran close behind
+his fleet horses. There was little trace of wheel-marks in the
+fine dust, and the horses came flying in at their utmost speed.
+Diomed stayed them in the middle of the crowd, and the sweat from
+their manes and chests fell in streams on to the ground.
+Forthwith he sprang from his goodly chariot, and leaned his whip
+against his horses' yoke; brave Sthenelus now lost no time, but
+at once brought on the prize, and gave the woman and the
+ear-handled cauldron to his comrades to take away. Then he
+unyoked the horses.
+</para>
+
+<para>
+Next after him came in Antilochus of the race of Neleus, who had
+passed Menelaus by a trick and not by the fleetness of his
+horses; but even so Menelaus came in as close behind him as the
+wheel is to the horse that draws both the chariot and its master.
+The end hairs of a horse's tail touch the tyre of the wheel, and
+there is never much space between wheel and horse when the
+chariot is going; Menelaus was no further than this behind
+Antilochus, though at first he had been a full disc's throw
+behind him. He had soon caught him up again, for Agamemnon's mare
+Aethe kept pulling stronger and stronger, so that if the course
+had been longer he would have passed him, and there would not
+even have been a dead heat. Idomeneus's brave squire Meriones was
+about a spear's cast behind Menelaus. His horses were slowest of
+all, and he was the worst driver. Last of them all came the son
+of Admetus, dragging his chariot and driving his horses on in
+front. When Achilles saw him he was sorry, and stood up among the
+Argives saying, "The best man is coming in last. Let us give him
+a prize for it is reasonable. He shall have the second, but the
+first must go to the son of Tydeus."
+</para>
+
+<para>
+Thus did he speak and the others all of them applauded his
+saying, and were for doing as he had said, but Nestor's son
+Antilochus stood up and claimed his rights from the son of
+Peleus. "Achilles," said he, "I shall take it much amiss if you
+do this thing; you would rob me of my prize, because you think
+Eumelus's chariot and horses were thrown out, and himself too,
+good man that he is. He should have prayed duly to the immortals;
+he would not have come in last if he had done so. If you are
+sorry for him and so choose, you have much gold in your tents,
+with bronze, sheep, cattle and horses. Take something from this
+store if you would have the Achaeans speak well of you, and give
+him a better prize even than that which you have now offered; but
+I will not give up the mare, and he that will fight me for her,
+let him come on."
+</para>
+
+<para>
+Achilles smiled as he heard this, and was pleased with
+Antilochus, who was one of his dearest comrades. So he said--
+</para>
+
+<para>
+"Antilochus, if you would have me find Eumelus another prize, I
+will give him the bronze breastplate with a rim of tin running
+all round it which I took from Asteropaeus. It will be worth much
+money to him."
+</para>
+
+<para>
+He bade his comrade Automedon bring the breastplate from his
+tent, and he did so. Achilles then gave it over to Eumelus, who
+received it gladly.
+</para>
+
+<para>
+But Menelaus got up in a rage, furiously angry with Antilochus.
+An attendant placed his staff in his hands and bade the Argives
+keep silence: the hero then addressed them. "Antilochus," said
+he, "what is this from you who have been so far blameless? You
+have made me cut a poor figure and baulked my horses by flinging
+your own in front of them, though yours are much worse than mine
+are; therefore, O princes and counsellors of the Argives, judge
+between us and show no favour, lest one of the Achaeans say,
+'Menelaus has got the mare through lying and corruption; his
+horses were far inferior to Antilochus's, but he has greater
+weight and influence.' Nay, I will determine the matter myself,
+and no man will blame me, for I shall do what is just. Come here,
+Antilochus, and stand, as our custom is, whip in hand before your
+chariot and horses; lay your hand on your steeds, and swear by
+earth-encircling Neptune that you did not purposely and
+guilefully get in the way of my horses."
+</para>
+
+<para>
+And Antilochus answered, "Forgive me; I am much younger, King
+Menelaus, than you are; you stand higher than I do and are the
+better man of the two; you know how easily young men are betrayed
+into indiscretion; their tempers are more hasty and they have
+less judgement; make due allowances therefore, and bear with me;
+I will of my own accord give up the mare that I have won, and if
+you claim any further chattel from my own possessions, I would
+rather yield it to you, at once, than fall from your good graces
+henceforth, and do wrong in the sight of heaven."
+</para>
+
+<para>
+The son of Nestor then took the mare and gave her over to
+Menelaus, whose anger was thus appeased; as when dew falls upon a
+field of ripening corn, and the lands are bristling with the
+harvest--even so, O Menelaus, was your heart made glad within
+you. He turned to Antilochus and said, "Now, Antilochus, angry
+though I have been, I can give way to you of my own free will;
+you have never been headstrong nor ill-disposed hitherto, but
+this time your youth has got the better of your judgement; be
+careful how you outwit your betters in future; no one else could
+have brought me round so easily, but your good father, your
+brother, and yourself have all of you had infinite trouble on my
+behalf; I therefore yield to your entreaty, and will give up the
+mare to you, mine though it indeed be; the people will thus see
+that I am neither harsh nor vindictive."
+</para>
+
+<para>
+With this he gave the mare over to Antilochus's comrade Noemon,
+and then took the cauldron. Meriones, who had come in fourth,
+carried off the two talents of gold, and the fifth prize, the
+two-handled urn, being unawarded, Achilles gave it to Nestor,
+going up to him among the assembled Argives and saying, "Take
+this, my good old friend, as an heirloom and memorial of the
+funeral of Patroclus--for you shall see him no more among the
+Argives. I give you this prize though you cannot win one; you can
+now neither wrestle nor fight, and cannot enter for the
+javelin-match nor foot-races, for the hand of age has been laid
+heavily upon you."
+</para>
+
+<para>
+So saying he gave the urn over to Nestor, who received it gladly
+and answered, "My son, all that you have said is true; there is
+no strength now in my legs and feet, nor can I hit out with my
+hands from either shoulder. Would that I were still young and
+strong as when the Epeans were burying King Amarynceus in
+Buprasium, and his sons offered prizes in his honour. There was
+then none that could vie with me neither of the Epeans nor the
+Pylians themselves nor the Aetolians. In boxing I overcame
+Clytomedes son of Enops, and in wrestling, Ancaeus of Pleuron who
+had come forward against me. Iphiclus was a good runner, but I
+beat him, and threw farther with my spear than either Phyleus or
+Polydorus. In chariot-racing alone did the two sons of Actor
+surpass me by crowding their horses in front of me, for they were
+angry at the way victory had gone, and at the greater part of the
+prizes remaining in the place in which they had been offered.
+They were twins, and the one kept on holding the reins, and
+holding the reins, while the other plied the whip. Such was I
+then, but now I must leave these matters to younger men; I must
+bow before the weight of years, but in those days I was eminent
+among heroes. And now, sir, go on with the funeral contests in
+honour of your comrade: gladly do I accept this urn, and my heart
+rejoices that you do not forget me but are ever mindful of my
+goodwill towards you, and of the respect due to me from the
+Achaeans. For all which may the grace of heaven be vouchsafed you
+in great abundance."
+</para>
+
+<para>
+Thereon the son of Peleus, when he had listened to all the thanks
+of Nestor, went about among the concourse of the Achaeans, and
+presently offered prizes for skill in the painful art of boxing.
+He brought out a strong mule, and made it fast in the middle of
+the crowd--a she-mule never yet broken, but six years old--when
+it is hardest of all to break them: this was for the victor, and
+for the vanquished he offered a double cup. Then he stood up and
+said among the Argives, "Son of Atreus, and all other Achaeans, I
+invite our two champion boxers to lay about them lustily and
+compete for these prizes. He to whom Apollo vouchsafes the
+greater endurance, and whom the Achaeans acknowledge as victor,
+shall take the mule back with him to his own tent, while he that
+is vanquished shall have the double cup."
+</para>
+
+<para>
+As he spoke there stood up a champion both brave and great
+stature, a skilful boxer, Epeus, son of Panopeus. He laid his
+hand on the mule and said, "Let the man who is to have the cup
+come hither, for none but myself will take the mule. I am the
+best boxer of all here present, and none can beat me. Is it not
+enough that I should fall short of you in actual fighting? Still,
+no man can be good at everything. I tell you plainly, and it
+shall come true; if any man will box with me I will bruise his
+body and break his bones; therefore let his friends stay here in
+a body and be at hand to take him away when I have done with
+him."
+</para>
+
+<para>
+They all held their peace, and no man rose save Euryalus son of
+Mecisteus, who was son of Talaus. Mecisteus went once to Thebes
+after the fall of Oedipus, to attend his funeral, and he beat all
+the people of Cadmus. The son of Tydeus was Euryalus's second,
+cheering him on and hoping heartily that he would win. First he
+put a waistband round him and then he gave him some well-cut
+thongs of ox-hide; the two men being now girt went into the
+middle of the ring, and immediately fell to; heavily indeed did
+they punish one another and lay about them with their brawny
+fists. One could hear the horrid crashing of their jaws, and they
+sweated from every pore of their skin. Presently Epeus came on
+and gave Euryalus a blow on the jaw as he was looking round;
+Euryalus could not keep his legs; they gave way under him in a
+moment and he sprang up with a bound, as a fish leaps into the
+air near some shore that is all bestrewn with sea-wrack, when
+Boreas furs the top of the waves, and then falls back into deep
+water. But noble Epeus caught hold of him and raised him up; his
+comrades also came round him and led him from the ring, unsteady
+in his gait, his head hanging on one side, and spitting great
+clots of gore. They set him down in a swoon and then went to
+fetch the double cup.
+</para>
+
+<para>
+The son of Peleus now brought out the prizes for the third
+contest and showed them to the Argives. These were for the
+painful art of wrestling. For the winner there was a great tripod
+ready for setting upon the fire, and the Achaeans valued it among
+themselves at twelve oxen. For the loser he brought out a woman
+skilled in all manner of arts, and they valued her at four oxen.
+He rose and said among the Argives, "Stand forward, you who will
+essay this contest."
+</para>
+
+<para>
+Forthwith uprose great Ajax the son of Telamon, and crafty
+Ulysses, full of wiles, rose also. The two girded themselves and
+went into the middle of the ring. They gripped each other in
+their strong hands like the rafters which some master-builder
+frames for the roof of a high house to keep the wind out. Their
+backbones cracked as they tugged at one another with their mighty
+arms--and sweat rained from them in torrents. Many a bloody weal
+sprang up on their sides and shoulders, but they kept on striving
+with might and main for victory and to win the tripod. Ulysses
+could not throw Ajax, nor Ajax him; Ulysses was too strong for
+him; but when the Achaeans began to tire of watching them, Ajax
+said to Ulysses, "Ulysses, noble son of Laertes, you shall either
+lift me, or I you, and let Jove settle it between us."
+</para>
+
+<para>
+He lifted him from the ground as he spoke, but Ulysses did not
+forget his cunning. He hit Ajax in the hollow at back of his
+knee, so that he could not keep his feet, but fell on his back
+with Ulysses lying upon his chest, and all who saw it marvelled.
+Then Ulysses in turn lifted Ajax and stirred him a little from
+the ground but could not lift him right off it, his knee sank
+under him, and the two fell side by side on the ground and were
+all begrimed with dust. They now sprang towards one another and
+were for wrestling yet a third time, but Achilles rose and stayed
+them. "Put not each other further," said he, "to such cruel
+suffering; the victory is with both alike, take each of you an
+equal prize, and let the other Achaeans now compete."
+</para>
+
+<para>
+Thus did he speak and they did even as he had said, and put on
+their shirts again after wiping the dust from off their bodies.
+</para>
+
+<para>
+The son of Peleus then offered prizes for speed in running--a
+mixing-bowl beautifully wrought, of pure silver. It would hold
+six measures, and far exceeded all others in the whole world for
+beauty; it was the work of cunning artificers in Sidon, and had
+been brought into port by Phoenicians from beyond the sea, who
+had made a present of it to Thoas. Eueneus son of Jason had given
+it to Patroclus in ransom of Priam's son Lycaon, and Achilles now
+offered it as a prize in honour of his comrade to him who should
+be the swiftest runner. For the second prize he offered a large
+ox, well fattened, while for the last there was to be half a
+talent of gold. He then rose and said among the Argives, "Stand
+forward, you who will essay this contest."
+</para>
+
+<para>
+Forthwith uprose fleet Ajax son of Oileus, with cunning Ulysses,
+and Nestor's son Antilochus, the fastest runner among all the
+youth of his time. They stood side by side and Achilles showed
+them the goal. The course was set out for them from the
+starting-post, and the son of Oileus took the lead at once, with
+Ulysses as close behind him as the shuttle is to a woman's bosom
+when she throws the woof across the warp and holds it close up to
+her; even so close behind him was Ulysses--treading in his
+footprints before the dust could settle there, and Ajax could
+feel his breath on the back of his head as he ran swiftly on. The
+Achaeans all shouted applause as they saw him straining his
+utmost, and cheered him as he shot past them; but when they were
+now nearing the end of the course Ulysses prayed inwardly to
+Minerva. "Hear me," he cried, "and help my feet, O goddess." Thus
+did he pray, and Pallas Minerva heard his prayer; she made his
+hands and his feet feel light, and when the runners were at the
+point of pouncing upon the prize, Ajax, through Minerva's spite
+slipped upon some offal that was lying there from the cattle
+which Achilles had slaughtered in honour of Patroclus, and his
+mouth and nostrils were all filled with cow dung. Ulysses
+therefore carried off the mixing-bowl, for he got before Ajax and
+came in first. But Ajax took the ox and stood with his hand on
+one of its horns, spitting the dung out of his mouth. Then he
+said to the Argives, "Alas, the goddess has spoiled my running;
+she watches over Ulysses and stands by him as though she were his
+own mother." Thus did he speak and they all of them laughed
+heartily.
+</para>
+
+<para>
+Antilochus carried off the last prize and smiled as he said to
+the bystanders, "You all see, my friends, that now too the gods
+have shown their respect for seniority. Ajax is somewhat older
+than I am, and as for Ulysses, he belongs to an earlier
+generation, but he is hale in spite of his years, and no man of
+the Achaeans can run against him save only Achilles."
+</para>
+
+<para>
+He said this to pay a compliment to the son of Peleus, and
+Achilles answered, "Antilochus, you shall not have praised me to
+no purpose; I shall give you an additional half talent of gold."
+He then gave the half talent to Antilochus, who received it
+gladly.
+</para>
+
+<para>
+Then the son of Peleus brought out the spear, helmet and shield
+that had been borne by Sarpedon, and were taken from him by
+Patroclus. He stood up and said among the Argives, "We bid two
+champions put on their armour, take their keen blades, and make
+trial of one another in the presence of the multitude; whichever
+of them can first wound the flesh of the other, cut through his
+armour, and draw blood, to him will I give this goodly Thracian
+sword inlaid with silver, which I took from Asteropaeus, but the
+armour let both hold in partnership, and I will give each of them
+a hearty meal in my own tent."
+</para>
+
+<para>
+Forthwith uprose great Ajax the son of Telamon, as also mighty
+Diomed son of Tydeus. When they had put on their armour each on
+his own side of the ring, they both went into the middle eager to
+engage, and with fire flashing from their eyes. The Achaeans
+marvelled as they beheld them, and when the two were now close up
+with one another, thrice did they spring forward and thrice try
+to strike each other in close combat. Ajax pierced Diomed's round
+shield, but did not draw blood, for the cuirass beneath the
+shield protected him; thereon the son of Tydeus from over his
+huge shield kept aiming continually at Ajax's neck with the point
+of his spear, and the Achaeans alarmed for his safety bade them
+leave off fighting and divide the prize between them. Achilles
+then gave the great sword to the son of Tydeus, with its
+scabbard, and the leathern belt with which to hang it.
+</para>
+
+<para>
+Achilles next offered the massive iron quoit which mighty Eetion
+had erewhile been used to hurl, until Achilles had slain him and
+carried it off in his ships along with other spoils. He stood up
+and said among the Argives, "Stand forward, you who would essay
+this contest. He who wins it will have a store of iron that will
+last him five years as they go rolling round, and if his fair
+fields lie far from a town his shepherd or ploughman will not
+have to make a journey to buy iron, for he will have a stock of
+it on his own premises."
+</para>
+
+<para>
+Then uprose the two mighty men Polypoetes and Leonteus, with Ajax
+son of Telamon and noble Epeus. They stood up one after the other
+and Epeus took the quoit, whirled it, and flung it from him,
+which set all the Achaeans laughing. After him threw Leonteus of
+the race of Mars. Ajax son of Telamon threw third, and sent the
+quoit beyond any mark that had been made yet, but when mighty
+Polypoetes took the quoit he hurled it as though it had been a
+stockman's stick which he sends flying about among his cattle
+when he is driving them, so far did his throw out-distance those
+of the others. All who saw it roared applause, and his comrades
+carried the prize for him and set it on board his ship.
+</para>
+
+<para>
+Achilles next offered a prize of iron for archery--ten
+double-edged axes and ten with single edges: he set up a ship's
+mast, some way off upon the sands, and with a fine string tied a
+pigeon to it by the foot; this was what they were to aim at.
+"Whoever," he said, "can hit the pigeon shall have all the axes
+and take them away with him; he who hits the string without
+hitting the bird will have taken a worse aim and shall have the
+single-edged axes."
+</para>
+
+<para>
+Then uprose King Teucer, and Meriones the stalwart squire of
+Idomeneus rose also, They cast lots in a bronze helmet and the
+lot of Teucer fell first. He let fly with his arrow forthwith,
+but he did not promise hecatombs of firstling lambs to King
+Apollo, and missed his bird, for Apollo foiled his aim; but he
+hit the string with which the bird was tied, near its foot; the
+arrow cut the string clean through so that it hung down towards
+the ground, while the bird flew up into the sky, and the Achaeans
+shouted applause. Meriones, who had his arrow ready while Teucer
+was aiming, snatched the bow out of his hand, and at once
+promised that he would sacrifice a hecatomb of firstling lambs to
+Apollo lord of the bow; then espying the pigeon high up under the
+clouds, he hit her in the middle of the wing as she was circling
+upwards; the arrow went clean through the wing and fixed itself
+in the ground at Meriones' feet, but the bird perched on the
+ship's mast hanging her head and with all her feathers drooping;
+the life went out of her, and she fell heavily from the mast.
+Meriones, therefore, took all ten double-edged axes, while Teucer
+bore off the single-edged ones to his ships.
+</para>
+
+<para>
+Then the son of Peleus brought in a spear and a cauldron that had
+never been on the fire; it was worth an ox, and was chased with a
+pattern of flowers; and those that throw the javelin stood up--to
+wit the son of Atreus, king of men Agamemnon, and Meriones,
+stalwart squire of Idomeneus. But Achilles spoke saying, "Son of
+Atreus, we know how far you excel all others both in power and in
+throwing the javelin; take the cauldron back with you to your
+ships, but if it so please you, let us give the spear to
+Meriones; this at least is what I should myself wish."
+</para>
+
+<para>
+King Agamemnon assented. So he gave the bronze spear to Meriones,
+and handed the goodly cauldron to Talthybius his esquire.
+</para>
+</chapter>
+
+<chapter>
+<title>BOOK XXIV</title>
+
+<para>
+THE assembly now broke up and the people went their ways each to
+his own ship. There they made ready their supper, and then
+bethought them of the blessed boon of sleep; but Achilles still
+wept for thinking of his dear comrade, and sleep, before whom all
+things bow, could take no hold upon him. This way and that did he
+turn as he yearned after the might and manfulness of Patroclus;
+he thought of all they had done together, and all they had gone
+through both on the field of battle and on the waves of the weary
+sea. As he dwelt on these things he wept bitterly and lay now on
+his side, now on his back, and now face downwards, till at last
+he rose and went out as one distraught to wander upon the
+seashore. Then, when he saw dawn breaking over beach and sea, he
+yoked his horses to his chariot, and bound the body of Hector
+behind it that he might drag it about. Thrice did he drag it
+round the tomb of the son of Menoetius, and then went back into
+his tent, leaving the body on the ground full length and with its
+face downwards. But Apollo would not suffer it to be disfigured,
+for he pitied the man, dead though he now was; therefore he
+shielded him with his golden aegis continually, that he might
+take no hurt while Achilles was dragging him.
+</para>
+
+<para>
+Thus shamefully did Achilles in his fury dishonour Hector; but
+the blessed gods looked down in pity from heaven, and urged
+Mercury, slayer of Argus, to steal the body. All were of this
+mind save only Juno, Neptune, and Jove's grey-eyed daughter, who
+persisted in the hate which they had ever borne towards Ilius
+with Priam and his people; for they forgave not the wrong done
+them by Alexandrus in disdaining the goddesses who came to him
+when he was in his sheepyards, and preferring her who had offered
+him a wanton to his ruin.
+</para>
+
+<para>
+When, therefore, the morning of the twelfth day had now come,
+Phoebus Apollo spoke among the immortals saying, "You gods ought
+to be ashamed of yourselves; you are cruel and hard-hearted. Did
+not Hector burn you thigh-bones of heifers and of unblemished
+goats? And now dare you not rescue even his dead body, for his
+wife to look upon, with his mother and child, his father Priam,
+and his people, who would forthwith commit him to the flames, and
+give him his due funeral rites? So, then, you would all be on the
+side of mad Achilles, who knows neither right nor ruth? He is
+like some savage lion that in the pride of his great strength and
+daring springs upon men's flocks and gorges on them. Even so has
+Achilles flung aside all pity, and all that conscience which at
+once so greatly banes yet greatly boons him that will heed it.
+man may lose one far dearer than Achilles has lost--a son, it may
+be, or a brother born from his own mother's womb; yet when he has
+mourned him and wept over him he will let him bide, for it takes
+much sorrow to kill a man; whereas Achilles, now that he has
+slain noble Hector, drags him behind his chariot round the tomb
+of his comrade. It were better of him, and for him, that he
+should not do so, for brave though he be we gods may take it ill
+that he should vent his fury upon dead clay."
+</para>
+
+<para>
+Juno spoke up in a rage. "This were well," she cried, "O lord of
+the silver bow, if you would give like honour to Hector and to
+Achilles; but Hector was mortal and suckled at a woman's breast,
+whereas Achilles is the offspring of a goddess whom I myself
+reared and brought up. I married her to Peleus, who is above
+measure dear to the immortals; you gods came all of you to her
+wedding; you feasted along with them yourself and brought your
+lyre--false, and fond of low company, that you have ever been."
+</para>
+
+<para>
+Then said Jove, "Juno, be not so bitter. Their honour shall not
+be equal, but of all that dwell in Ilius, Hector was dearest to
+the gods, as also to myself, for his offerings never failed me.
+Never was my altar stinted of its dues, nor of the
+drink-offerings and savour of sacrifice which we claim of right.
+I shall therefore permit the body of mighty Hector to be stolen;
+and yet this may hardly be without Achilles coming to know it,
+for his mother keeps night and day beside him. Let some one of
+you, therefore, send Thetis to me, and I will impart my counsel
+to her, namely that Achilles is to accept a ransom from Priam,
+and give up the body."
+</para>
+
+<para>
+On this Iris fleet as the wind went forth to carry his message.
+Down she plunged into the dark sea midway between Samos and rocky
+Imbrus; the waters hissed as they closed over her, and she sank
+into the bottom as the lead at the end of an ox-horn, that is
+sped to carry death to fishes. She found Thetis sitting in a
+great cave with the other sea-goddesses gathered round her; there
+she sat in the midst of them weeping for her noble son who was to
+fall far from his own land, on the rich plains of Troy. Iris went
+up to her and said, "Rise Thetis; Jove, whose counsels fail not,
+bids you come to him." And Thetis answered, "Why does the mighty
+god so bid me? I am in great grief, and shrink from going in and
+out among the immortals. Still, I will go, and the word that he
+may speak shall not be spoken in vain."
+</para>
+
+<para>
+The goddess took her dark veil, than which there can be no robe
+more sombre, and went forth with fleet Iris leading the way
+before her. The waves of the sea opened them a path, and when
+they reached the shore they flew up into the heavens, where they
+found the all-seeing son of Saturn with the blessed gods that
+live for ever assembled near him. Minerva gave up her seat to
+her, and she sat down by the side of father Jove. Juno then
+placed a fair golden cup in her hand, and spoke to her in words
+of comfort, whereon Thetis drank and gave her back the cup; and
+the sire of gods and men was the first to speak.
+</para>
+
+<para>
+"So, goddess," said he, "for all your sorrow, and the grief that
+I well know reigns ever in your heart, you have come hither to
+Olympus, and I will tell you why I have sent for you. This nine
+days past the immortals have been quarrelling about Achilles
+waster of cities and the body of Hector. The gods would have
+Mercury slayer of Argus steal the body, but in furtherance of our
+peace and amity henceforward, I will concede such honour to your
+son as I will now tell you. Go, then, to the host and lay these
+commands upon him; say that the gods are angry with him, and that
+I am myself more angry than them all, in that he keeps Hector at
+the ships and will not give him up. He may thus fear me and let
+the body go. At the same time I will send Iris to great Priam to
+bid him go to the ships of the Achaeans, and ransom his son,
+taking with him such gifts for Achilles as may give him
+satisfaction."
+</para>
+
+<para>
+Silver-footed Thetis did as the god had told her, and forthwith
+down she darted from the topmost summits of Olympus. She went to
+her son's tents where she found him grieving bitterly, while his
+trusty comrades round him were busy preparing their morning meal,
+for which they had killed a great woolly sheep. His mother sat
+down beside him and caressed him with her hand saying, "My son,
+how long will you keep on thus grieving and making moan? You are
+gnawing at your own heart, and think neither of food nor of
+woman's embraces; and yet these too were well, for you have no
+long time to live, and death with the strong hand of fate are
+already close beside you. Now, therefore, heed what I say, for I
+come as a messenger from Jove; he says that the gods are angry
+with you, and himself more angry than them all, in that you keep
+Hector at the ships and will not give him up. Therefore let him
+go, and accept a ransom for his body."
+</para>
+
+<para>
+And Achilles answered, "So be it. If Olympian Jove of his own
+motion thus commands me, let him that brings the ransom bear the
+body away."
+</para>
+
+<para>
+Thus did mother and son talk together at the ships in long
+discourse with one another. Meanwhile the son of Saturn sent Iris
+to the strong city of Ilius. "Go," said he, "fleet Iris, from the
+mansions of Olympus, and tell King Priam in Ilius, that he is to
+go to the ships of the Achaeans and free the body of his dear
+son. He is to take such gifts with him as shall give satisfaction
+to Achilles, and he is to go alone, with no other Trojan, save
+only some honoured servant who may drive his mules and waggon,
+and bring back the body of him whom noble Achilles has slain. Let
+him have no thought nor fear of death in his heart, for we will
+send the slayer of Argus to escort him, and bring him within the
+tent of Achilles. Achilles will not kill him nor let another do
+so, for he will take heed to his ways and sin not, and he will
+entreat a suppliant with all honourable courtesy."
+</para>
+
+<para>
+On this Iris, fleet as the wind, sped forth to deliver her
+message. She went to Priam's house, and found weeping and
+lamentation therein. His sons were seated round their father in
+the outer courtyard, and their raiment was wet with tears: the
+old man sat in the midst of them with his mantle wrapped close
+about his body, and his head and neck all covered with the filth
+which he had clutched as he lay grovelling in the mire. His
+daughters and his sons' wives went wailing about the house, as
+they thought of the many and brave men who lay dead, slain by the
+Argives. The messenger of Jove stood by Priam and spoke softly to
+him, but fear fell upon him as she did so. "Take heart," she
+said, "Priam offspring of Dardanus, take heart and fear not. I
+bring no evil tidings, but am minded well towards you. I come as
+a messenger from Jove, who though he be not near, takes thought
+for you and pities you. The lord of Olympus bids you go and
+ransom noble Hector, and take with you such gifts as shall give
+satisfaction to Achilles. You are to go alone, with no Trojan,
+save only some honoured servant who may drive your mules and
+waggon, and bring back to the city the body of him whom noble
+Achilles has slain. You are to have no thought, nor fear of
+death, for Jove will send the slayer of Argus to escort you. When
+he has brought you within Achilles' tent, Achilles will not kill
+you nor let another do so, for he will take heed to his ways and
+sin not, and he will entreat a suppliant with all honourable
+courtesy."
+</para>
+
+<para>
+Iris went her way when she had thus spoken, and Priam told his
+sons to get a mule-waggon ready, and to make the body of the
+waggon fast upon the top of its bed. Then he went down into his
+fragrant store-room, high-vaulted, and made of cedar-wood, where
+his many treasures were kept, and he called Hecuba his wife.
+"Wife," said he, "a messenger has come to me from Olympus, and
+has told me to go to the ships of the Achaeans to ransom my dear
+son, taking with me such gifts as shall give satisfaction to
+Achilles. What think you of this matter? for my own part I am
+greatly moved to pass through the camps of the Achaeans and go to
+their ships."
+</para>
+
+<para>
+His wife cried aloud as she heard him, and said, "Alas, what has
+become of that judgement for which you have been ever famous both
+among strangers and your own people? How can you venture alone to
+the ships of the Achaeans, and look into the face of him who has
+slain so many of your brave sons? You must have iron courage, for
+if the cruel savage sees you and lays hold on you, he will know
+neither respect nor pity. Let us then weep Hector from afar here
+in our own house, for when I gave him birth the threads of
+overruling fate were spun for him that dogs should eat his flesh
+far from his parents, in the house of that terrible man on whose
+liver I would fain fasten and devour it. Thus would I avenge my
+son, who showed no cowardice when Achilles slew him, and thought
+neither of flight nor of avoiding battle as he stood in defence
+of Trojan men and Trojan women."
+</para>
+
+<para>
+Then Priam said, "I would go, do not therefore stay me nor be as
+a bird of ill omen in my house, for you will not move me. Had it
+been some mortal man who had sent me some prophet or priest who
+divines from sacrifice--I should have deemed him false and have
+given him no heed; but now I have heard the goddess and seen her
+face to face, therefore I will go and her saying shall not be in
+vain. If it be my fate to die at the ships of the Achaeans even
+so would I have it; let Achilles slay me, if I may but first have
+taken my son in my arms and mourned him to my heart's
+comforting."
+</para>
+
+<para>
+So saying he lifted the lids of his chests, and took out twelve
+goodly vestments. He took also twelve cloaks of single fold,
+twelve rugs, twelve fair mantles, and an equal number of shirts.
+He weighed out ten talents of gold, and brought moreover two
+burnished tripods, four cauldrons, and a very beautiful cup which
+the Thracians had given him when he had gone to them on an
+embassy; it was very precious, but he grudged not even this, so
+eager was he to ransom the body of his son. Then he chased all
+the Trojans from the court and rebuked them with words of anger.
+"Out," he cried, "shame and disgrace to me that you are. Have you
+no grief in your own homes that you are come to plague me here?
+Is it a small thing, think you, that the son of Saturn has sent
+this sorrow upon me, to lose the bravest of my sons? Nay, you
+shall prove it in person, for now he is gone the Achaeans will
+have easier work in killing you. As for me, let me go down within
+the house of Hades, ere mine eyes behold the sacking and wasting
+of the city."
+</para>
+
+<para>
+He drove the men away with his staff, and they went forth as the
+old man sped them. Then he called to his sons, upbraiding
+Helenus, Paris, noble Agathon, Pammon, Antiphonus, Polites of the
+loud battle-cry, Deiphobus, Hippothous, and Dius. These nine did
+the old man call near him. "Come to me at once," he cried,
+"worthless sons who do me shame; would that you had all been
+killed at the ships rather than Hector. Miserable man that I am,
+I have had the bravest sons in all Troy--noble Nestor, Troilus
+the dauntless charioteer, and Hector who was a god among men, so
+that one would have thought he was son to an immortal--yet there
+is not one of them left. Mars has slain them and those of whom I
+am ashamed are alone left me. Liars, and light of foot, heroes of
+the dance, robbers of lambs and kids from your own people, why do
+you not get a waggon ready for me at once, and put all these
+things upon it that I may set out on my way?"
+</para>
+
+<para>
+Thus did he speak, and they feared the rebuke of their father.
+They brought out a strong mule-waggon, newly made, and set the
+body of the waggon fast on its bed. They took the mule-yoke from
+the peg on which it hung, a yoke of boxwood with a knob on the
+top of it and rings for the reins to go through. Then they
+brought a yoke-band eleven cubits long, to bind the yoke to the
+pole; they bound it on at the far end of the pole, and put the
+ring over the upright pin making it fast with three turns of the
+band on either side the knob, and bending the thong of the yoke
+beneath it. This done, they brought from the store-chamber the
+rich ransom that was to purchase the body of Hector, and they set
+it all orderly on the waggon; then they yoked the strong
+harness-mules which the Mysians had on a time given as a goodly
+present to Priam; but for Priam himself they yoked horses which
+the old king had bred, and kept for own use.
+</para>
+
+<para>
+Thus heedfully did Priam and his servant see to the yolking of
+their cars at the palace. Then Hecuba came to them all sorrowful,
+with a golden goblet of wine in her right hand, that they might
+make a drink-offering before they set out. She stood in front of
+the horses and said, "Take this, make a drink-offering to father
+Jove, and since you are minded to go to the ships in spite of me,
+pray that you may come safely back from the hands of your
+enemies. Pray to the son of Saturn lord of the whirlwind, who
+sits on Ida and looks down over all Troy, pray him to send his
+swift messenger on your right hand, the bird of omen which is
+strongest and most dear to him of all birds, that you may see it
+with your own eyes and trust it as you go forth to the ships of
+the Danaans. If all-seeing Jove will not send you this messenger,
+however set upon it you may be, I would not have you go to the
+ships of the Argives."
+</para>
+
+<para>
+And Priam answered, "Wife, I will do as you desire me; it is well
+to lift hands in prayer to Jove, if so be he may have mercy upon
+me."
+</para>
+
+<para>
+With this the old man bade the serving-woman pour pure water over
+his hands, and the woman came, bearing the water in a bowl. He
+washed his hands and took the cup from his wife; then he made the
+drink-offering and prayed, standing in the middle of the
+courtyard and turning his eyes to heaven. "Father Jove," he said,
+"that rulest from Ida, most glorious and most great, grant that I
+may be received kindly and compassionately in the tents of
+Achilles; and send your swift messenger upon my right hand, the
+bird of omen which is strongest and most dear to you of all
+birds, that I may see it with my own eyes and trust it as I go
+forth to the ships of the Danaans."
+</para>
+
+<para>
+So did he pray, and Jove the lord of counsel heard his prayer.
+Forthwith he sent an eagle, the most unerring portent of all
+birds that fly, the dusky hunter that men also call the Black
+Eagle. His wings were spread abroad on either side as wide as the
+well-made and well-bolted door of a rich man's chamber. He came
+to them flying over the city upon their right hands, and when
+they saw him they were glad and their hearts took comfort within
+them. The old man made haste to mount his chariot, and drove out
+through the inner gateway and under the echoing gatehouse of the
+outer court. Before him went the mules drawing the four-wheeled
+waggon, and driven by wise Idaeus; behind these were the horses,
+which the old man lashed with his whip and drove swiftly through
+the city, while his friends followed after, wailing and lamenting
+for him as though he were on his road to death. As soon as they
+had come down from the city and had reached the plain, his sons
+and sons-in-law who had followed him went back to Ilius.
+</para>
+
+<para>
+But Priam and Idaeus as they showed out upon the plain did not
+escape the ken of all-seeing Jove, who looked down upon the old
+man and pitied him; then he spoke to his son Mercury and said,
+"Mercury, for it is you who are the most disposed to escort men
+on their way, and to hear those whom you will hear, go, and so
+conduct Priam to the ships of the Achaeans that no other of the
+Danaans shall see him nor take note of him until he reach the son
+of Peleus."
+</para>
+
+<para>
+Thus he spoke and Mercury, guide and guardian, slayer of Argus,
+did as he was told. Forthwith he bound on his glittering golden
+sandals with which he could fly like the wind over land and sea;
+he took the wand with which he seals men's eyes in sleep, or
+wakes them just as he pleases, and flew holding it in his hand
+till he came to Troy and to the Hellespont. To look at, he was
+like a young man of noble birth in the hey-day of his youth and
+beauty with the down just coming upon his face.
+</para>
+
+<para>
+Now when Priam and Idaeus had driven past the great tomb of
+Ilius, they stayed their mules and horses that they might drink
+in the river, for the shades of night were falling, when,
+therefore, Idaeus saw Mercury standing near them he said to
+Priam, "Take heed, descendant of Dardanus; here is matter which
+demands consideration. I see a man who I think will presently
+fall upon us; let us fly with our horses, or at least embrace his
+knees and implore him to take compassion upon us?"
+</para>
+
+<para>
+When he heard this the old man's heart failed him, and he was in
+great fear; he stayed where he was as one dazed, and the hair
+stood on end over his whole body; but the bringer of good luck
+came up to him and took him by the hand, saying, "Whither,
+father, are you thus driving your mules and horses in the dead of
+night when other men are asleep? Are you not afraid of the fierce
+Achaeans who are hard by you, so cruel and relentless? Should
+some one of them see you bearing so much treasure through the
+darkness of the flying night, what would not your state then be?
+You are no longer young, and he who is with you is too old to
+protect you from those who would attack you. For myself, I will
+do you no harm, and I will defend you from any one else, for you
+remind me of my own father."
+</para>
+
+<para>
+And Priam answered, "It is indeed as you say, my dear son;
+nevertheless some god has held his hand over me, in that he has
+sent such a wayfarer as yourself to meet me so opportunely; you
+are so comely in mien and figure, and your judgement is so
+excellent that you must come of blessed parents."
+</para>
+
+<para>
+Then said the slayer of Argus, guide and guardian, "Sir, all that
+you have said is right; but tell me and tell me true, are you
+taking this rich treasure to send it to a foreign people where it
+may be safe, or are you all leaving strong Ilius in dismay now
+that your son has fallen who was the bravest man among you and
+was never lacking in battle with the Achaeans?"
+</para>
+
+<para>
+And Priam said, "Who are you, my friend, and who are your
+parents, that you speak so truly about the fate of my unhappy
+son?"
+</para>
+
+<para>
+The slayer of Argus, guide and guardian, answered him, "Sir, you
+would prove me, that you question me about noble Hector. Many a
+time have I set eyes upon him in battle when he was driving the
+Argives to their ships and putting them to the sword. We stood
+still and marvelled, for Achilles in his anger with the son of
+Atreus suffered us not to fight. I am his squire, and came with
+him in the same ship. I am a Myrmidon, and my father's name is
+Polyctor: he is a rich man and about as old as you are; he has
+six sons besides myself, and I am the seventh. We cast lots, and
+it fell upon me to sail hither with Achilles. I am now come from
+the ships on to the plain, for with daybreak the Achaeans will
+set battle in array about the city. They chafe at doing nothing,
+and are so eager that their princes cannot hold them back."
+</para>
+
+<para>
+Then answered Priam, "If you are indeed the squire of Achilles
+son of Peleus, tell me now the whole truth. Is my son still at
+the ships, or has Achilles hewn him limb from limb, and given him
+to his hounds?"
+</para>
+
+<para>
+"Sir," replied the slayer of Argus, guide and guardian, "neither
+hounds nor vultures have yet devoured him; he is still just lying
+at the tents by the ship of Achilles, and though it is now twelve
+days that he has lain there, his flesh is not wasted nor have the
+worms eaten him although they feed on warriors. At daybreak
+Achilles drags him cruelly round the sepulchre of his dear
+comrade, but it does him no hurt. You should come yourself and
+see how he lies fresh as dew, with the blood all washed away, and
+his wounds every one of them closed though many pierced him with
+their spears. Such care have the blessed gods taken of your brave
+son, for he was dear to them beyond all measure."
+</para>
+
+<para>
+The old man was comforted as he heard him and said, "My son, see
+what a good thing it is to have made due offerings to the
+immortals; for as sure as that he was born my son never forgot
+the gods that hold Olympus, and now they requite it to him even
+in death. Accept therefore at my hands this goodly chalice; guard
+me and with heaven's help guide me till I come to the tent of the
+son of Peleus."
+</para>
+
+<para>
+Then answered the slayer of Argus, guide and guardian, "Sir, you
+are tempting me and playing upon my youth, but you shall not move
+me, for you are offering me presents without the knowledge of
+Achilles whom I fear and hold it great guilt to defraud, lest
+some evil presently befall me; but as your guide I would go with
+you even to Argos itself, and would guard you so carefully
+whether by sea or land, that no one should attack you through
+making light of him who was with you."
+</para>
+
+<para>
+The bringer of good luck then sprang on to the chariot, and
+seizing the whip and reins he breathed fresh spirit into the
+mules and horses. When they reached the trench and the wall that
+was before the ships, those who were on guard had just been
+getting their suppers, and the slayer of Argus threw them all
+into a deep sleep. Then he drew back the bolts to open the gates,
+and took Priam inside with the treasure he had upon his waggon.
+Ere long they came to the lofty dwelling of the son of Peleus for
+which the Myrmidons had cut pine and which they had built for
+their king; when they had built it they thatched it with coarse
+tussock-grass which they had mown out on the plain, and all round
+it they made a large courtyard, which was fenced with stakes set
+close together. The gate was barred with a single bolt of pine
+which it took three men to force into its place, and three to
+draw back so as to open the gate, but Achilles could draw it by
+himself. Mercury opened the gate for the old man, and brought in
+the treasure that he was taking with him for the son of Peleus.
+Then he sprang from the chariot on to the ground and said, "Sir,
+it is I, immortal Mercury, that am come with you, for my father
+sent me to escort you. I will now leave you, and will not enter
+into the presence of Achilles, for it might anger him that a god
+should befriend mortal men thus openly. Go you within, and
+embrace the knees of the son of Peleus: beseech him by his
+father, his lovely mother, and his son; thus you may move him."
+</para>
+
+<para>
+With these words Mercury went back to high Olympus. Priam sprang
+from his chariot to the ground, leaving Idaeus where he was, in
+charge of the mules and horses. The old man went straight into
+the house where Achilles, loved of the gods, was sitting. There
+he found him with his men seated at a distance from him: only
+two, the hero Automedon, and Alcimus of the race of Mars, were
+busy in attendance about his person, for he had but just done
+eating and drinking, and the table was still there. King Priam
+entered without their seeing him, and going right up to Achilles
+he clasped his knees and kissed the dread murderous hands that
+had slain so many of his sons.
+</para>
+
+<para>
+As when some cruel spite has befallen a man that he should have
+killed some one in his own country, and must fly to a great man's
+protection in a land of strangers, and all marvel who see him,
+even so did Achilles marvel as he beheld Priam. The others looked
+one to another and marvelled also, but Priam besought Achilles
+saying, "Think of your father, O Achilles like unto the gods, who
+is such even as I am, on the sad threshold of old age. It may be
+that those who dwell near him harass him, and there is none to
+keep war and ruin from him. Yet when he hears of you being still
+alive, he is glad, and his days are full of hope that he shall
+see his dear son come home to him from Troy; but I, wretched man
+that I am, had the bravest in all Troy for my sons, and there is
+not one of them left. I had fifty sons when the Achaeans came
+here; nineteen of them were from a single womb, and the others
+were borne to me by the women of my household. The greater part
+of them has fierce Mars laid low, and Hector, him who was alone
+left, him who was the guardian of the city and ourselves, him
+have you lately slain; therefore I am now come to the ships of
+the Achaeans to ransom his body from you with a great ransom.
+Fear, O Achilles, the wrath of heaven; think on your own father
+and have compassion upon me, who am the more pitiable, for I have
+steeled myself as no man yet has ever steeled himself before me,
+and have raised to my lips the hand of him who slew my son."
+</para>
+
+<para>
+Thus spoke Priam, and the heart of Achilles yearned as he
+bethought him of his father. He took the old man's hand and moved
+him gently away. The two wept bitterly--Priam, as he lay at
+Achilles' feet, weeping for Hector, and Achilles now for his
+father and now for Patroclous, till the house was filled with
+their lamentation. But when Achilles was now sated with grief and
+had unburthened the bitterness of his sorrow, he left his seat
+and raised the old man by the hand, in pity for his white hair
+and beard; then he said, "Unhappy man, you have indeed been
+greatly daring; how could you venture to come alone to the ships
+of the Achaeans, and enter the presence of him who has slain so
+many of your brave sons? You must have iron courage: sit now upon
+this seat, and for all our grief we will hide our sorrows in our
+hearts, for weeping will not avail us. The immortals know no
+care, yet the lot they spin for man is full of sorrow; on the
+floor of Jove's palace there stand two urns, the one filled with
+evil gifts, and the other with good ones. He for whom Jove the
+lord of thunder mixes the gifts he sends, will meet now with good
+and now with evil fortune; but he to whom Jove sends none but
+evil gifts will be pointed at by the finger of scorn, the hand of
+famine will pursue him to the ends of the world, and he will go
+up and down the face of the earth, respected neither by gods nor
+men. Even so did it befall Peleus; the gods endowed him with all
+good things from his birth upwards, for he reigned over the
+Myrmidons excelling all men in prosperity and wealth, and mortal
+though he was they gave him a goddess for his bride. But even on
+him too did heaven send misfortune, for there is no race of royal
+children born to him in his house, save one son who is doomed to
+die all untimely; nor may I take care of him now that he is
+growing old, for I must stay here at Troy to be the bane of you
+and your children. And you too, O Priam, I have heard that you
+were aforetime happy. They say that in wealth and plenitude of
+offspring you surpassed all that is in Lesbos, the realm of Makar
+to the northward, Phrygia that is more inland, and those that
+dwell upon the great Hellespont; but from the day when the
+dwellers in heaven sent this evil upon you, war and slaughter
+have been about your city continually. Bear up against it, and
+let there be some intervals in your sorrow. Mourn as you may for
+your brave son, you will take nothing by it. You cannot raise him
+from the dead, ere you do so yet another sorrow shall befall
+you."
+</para>
+
+<para>
+And Priam answered, "O king, bid me not be seated, while Hector
+is still lying uncared for in your tents, but accept the great
+ransom which I have brought you, and give him to me at once that
+I may look upon him. May you prosper with the ransom and reach
+your own land in safety, seeing that you have suffered me to live
+and to look upon the light of the sun."
+</para>
+
+<para>
+Achilles looked at him sternly and said, "Vex me, sir, no longer;
+I am of myself minded to give up the body of Hector. My mother,
+daughter of the old man of the sea, came to me from Jove to bid
+me deliver it to you. Moreover I know well, O Priam, and you
+cannot hide it, that some god has brought you to the ships of the
+Achaeans, for else, no man however strong and in his prime would
+dare to come to our host; he could neither pass our guard unseen,
+nor draw the bolt of my gates thus easily; therefore, provoke me
+no further, lest I sin against the word of Jove, and suffer you
+not, suppliant though you are, within my tents."
+</para>
+
+<para>
+The old man feared him and obeyed. Then the son of Peleus sprang
+like a lion through the door of his house, not alone, but with
+him went his two squires Automedon and Alcimus who were closer to
+him than any others of his comrades now that Patroclus was no
+more. These unyoked the horses and mules, and bade Priam's herald
+and attendant be seated within the house. They lifted the ransom
+for Hector's body from the waggon. but they left two mantles and
+a goodly shirt, that Achilles might wrap the body in them when he
+gave it to be taken home. Then he called to his servants and
+ordered them to wash the body and anoint it, but he first took it
+to a place where Priam should not see it, lest if he did so, he
+should break out in the bitterness of his grief, and enrage
+Achilles, who might then kill him and sin against the word of
+Jove. When the servants had washed the body and anointed it, and
+had wrapped it in a fair shirt and mantle, Achilles himself
+lifted it on to a bier, and he and his men then laid it on the
+waggon. He cried aloud as he did so and called on the name of his
+dear comrade, "Be not angry with me, Patroclus," he said, "if you
+hear even in the house of Hades that I have given Hector to his
+father for a ransom. It has been no unworthy one, and I will
+share it equitably with you."
+</para>
+
+<para>
+Achilles then went back into the tent and took his place on the
+richly inlaid seat from which he had risen, by the wall that was
+at right angles to the one against which Priam was sitting.
+"Sir," he said, "your son is now laid upon his bier and is
+ransomed according to desire; you shall look upon him when you
+him away at daybreak; for the present let us prepare our supper.
+Even lovely Niobe had to think about eating, though her twelve
+children--six daughters and six lusty sons--had been all slain in
+her house. Apollo killed the sons with arrows from his silver
+bow, to punish Niobe, and Diana slew the daughters, because Niobe
+had vaunted herself against Leto; she said Leto had borne two
+children only, whereas she had herself borne many--whereon the
+two killed the many. Nine days did they lie weltering, and there
+was none to bury them, for the son of Saturn turned the people
+into stone; but on the tenth day the gods in heaven themselves
+buried them, and Niobe then took food, being worn out with
+weeping. They say that somewhere among the rocks on the mountain
+pastures of Sipylus, where the nymphs live that haunt the river
+Achelous, there, they say, she lives in stone and still nurses
+the sorrows sent upon her by the hand of heaven. Therefore, noble
+sir, let us two now take food; you can weep for your dear son
+hereafter as you are bearing him back to Ilius--and many a tear
+will he cost you."
+</para>
+
+<para>
+With this Achilles sprang from his seat and killed a sheep of
+silvery whiteness, which his followers skinned and made ready all
+in due order. They cut the meat carefully up into smaller pieces,
+spitted them, and drew them off again when they were well
+roasted. Automedon brought bread in fair baskets and served it
+round the table, while Achilles dealt out the meat, and they laid
+their hands on the good things that were before them. As soon as
+they had had enough to eat and drink, Priam, descendant of
+Dardanus, marvelled at the strength and beauty of Achilles for he
+was as a god to see, and Achilles marvelled at Priam as he
+listened to him and looked upon his noble presence. When they had
+gazed their fill Priam spoke first. "And now, O king," he said,
+"take me to my couch that we may lie down and enjoy the blessed
+boon of sleep. Never once have my eyes been closed from the day
+your hands took the life of my son; I have grovelled without
+ceasing in the mire of my stable-yard, making moan and brooding
+over my countless sorrows. Now, moreover, I have eaten bread and
+drunk wine; hitherto I have tasted nothing."
+</para>
+
+<para>
+As he spoke Achilles told his men and the women-servants to set
+beds in the room that was in the gatehouse, and make them with
+good red rugs, and spread coverlets on the top of them with
+woollen cloaks for Priam and Idaeus to wear. So the maids went
+out carrying a torch and got the two beds ready in all haste.
+Then Achilles said laughingly to Priam, "Dear sir, you shall lie
+outside, lest some counsellor of those who in due course keep
+coming to advise with me should see you here in the darkness of
+the flying night, and tell it to Agamemnon. This might cause
+delay in the delivery of the body. And now tell me and tell me
+true, for how many days would you celebrate the funeral rites of
+noble Hector? Tell me, that I may hold aloof from war and
+restrain the host."
+</para>
+
+<para>
+And Priam answered, "Since, then, you suffer me to bury my noble
+son with all due rites, do thus, Achilles, and I shall be
+grateful. You know how we are pent up within our city; it is far
+for us to fetch wood from the mountain, and the people live in
+fear. Nine days, therefore, will we mourn Hector in my house; on
+the tenth day we will bury him and there shall be a public feast
+in his honour; on the eleventh we will build a mound over his
+ashes, and on the twelfth, if there be need, we will fight."
+</para>
+
+<para>
+And Achilles answered, "All, King Priam, shall be as you have
+said. I will stay our fighting for as long a time as you have
+named."
+</para>
+
+<para>
+As he spoke he laid his hand on the old man's right wrist, in
+token that he should have no fear; thus then did Priam and his
+attendant sleep there in the forecourt, full of thought, while
+Achilles lay in an inner room of the house, with fair Briseis by
+his side.
+</para>
+
+<para>
+And now both gods and mortals were fast asleep through the
+livelong night, but upon Mercury alone, the bringer of good luck,
+sleep could take no hold for he was thinking all the time how to
+get King Priam away from the ships without his being seen by the
+strong force of sentinels. He hovered therefore over Priam's head
+and said, "Sir, now that Achilles has spared your life, you seem
+to have no fear about sleeping in the thick of your foes. You
+have paid a great ransom, and have received the body of your son;
+were you still alive and a prisoner the sons whom you have left
+at home would have to give three times as much to free you; and
+so it would be if Agamemnon and the other Achaeans were to know
+of your being here."
+</para>
+
+<para>
+When he heard this the old man was afraid and roused his servant.
+Mercury then yoked their horses and mules, and drove them quickly
+through the host so that no man perceived them. When they came to
+the ford of eddying Xanthus, begotten of immortal Jove, Mercury
+went back to high Olympus, and dawn in robe of saffron began to
+break over all the land. Priam and Idaeus then drove on toward
+the city lamenting and making moan, and the mules drew the body
+of Hector. No one neither man nor woman saw them, till Cassandra,
+fair as golden Venus standing on Pergamus, caught sight of her
+dear father in his chariot, and his servant that was the city's
+herald with him. Then she saw him that was lying upon the bier,
+drawn by the mules, and with a loud cry she went about the city
+saying, "Come hither Trojans, men and women, and look on Hector;
+if ever you rejoiced to see him coming from battle when he was
+alive, look now on him that was the glory of our city and all our
+people."
+</para>
+
+<para>
+At this there was not man nor woman left in the city, so great a
+sorrow had possessed them. Hard by the gates they met Priam as he
+was bringing in the body. Hector's wife and his mother were the
+first to mourn him: they flew towards the waggon and laid their
+hands upon his head, while the crowd stood weeping round them.
+They would have stayed before the gates, weeping and lamenting
+the livelong day to the going down of the sun, had not Priam
+spoken to them from the chariot and said, "Make way for the mules
+to pass you. Afterwards when I have taken the body home you shall
+have your fill of weeping."
+</para>
+
+<para>
+On this the people stood asunder, and made a way for the waggon.
+When they had borne the body within the house they laid it upon a
+bed and seated minstrels round it to lead the dirge, whereon the
+women joined in the sad music of their lament. Foremost among
+them all Andromache led their wailing as she clasped the head of
+mighty Hector in her embrace. "Husband," she cried, "you have
+died young, and leave me in your house a widow; he of whom we are
+the ill-starred parents is still a mere child, and I fear he may
+not reach manhood. Ere he can do so our city will be razed and
+overthrown, for you who watched over it are no more--you who were
+its saviour, the guardian of our wives and children. Our women
+will be carried away captives to the ships, and I among them;
+while you, my child, who will be with me will be put to some
+unseemly tasks, working for a cruel master. Or, may be, some
+Achaean will hurl you (O miserable death) from our walls, to
+avenge some brother, son, or father whom Hector slew; many of
+them have indeed bitten the dust at his hands, for your father's
+hand in battle was no light one. Therefore do the people mourn
+him. You have left, O Hector, sorrow unutterable to your parents,
+and my own grief is greatest of all, for you did not stretch
+forth your arms and embrace me as you lay dying, nor say to me
+any words that might have lived with me in my tears night and day
+for evermore."
+</para>
+
+<para>
+Bitterly did she weep the while, and the women joined in her
+lament. Hecuba in her turn took up the strains of woe. "Hector,"
+she cried, "dearest to me of all my children. So long as you were
+alive the gods loved you well, and even in death they have not
+been utterly unmindful of you; for when Achilles took any other
+of my sons, he would sell him beyond the seas, to Samos Imbrus or
+rugged Lemnos; and when he had slain you too with his sword, many
+a time did he drag you round the sepulchre of his comrade--though
+this could not give him life--yet here you lie all fresh as dew,
+and comely as one whom Apollo has slain with his painless
+shafts."
+</para>
+
+<para>
+Thus did she too speak through her tears with bitter moan, and
+then Helen for a third time took up the strain of lamentation.
+"Hector," said she, "dearest of all my brothers-in-law--for I am
+wife to Alexandrus who brought me hither to Troy--would that I
+had died ere he did so--twenty years are come and gone since I
+left my home and came from over the sea, but I have never heard
+one word of insult or unkindness from you. When another would
+chide with me, as it might be one of your brothers or sisters or
+of your brothers' wives, or my mother-in-law--for Priam was as
+kind to me as though he were my own father--you would rebuke and
+check them with words of gentleness and goodwill. Therefore my
+tears flow both for you and for my unhappy self, for there is no
+one else in Troy who is kind to me, but all shrink and shudder as
+they go by me."
+</para>
+
+<para>
+She wept as she spoke and the vast crowd that was gathered round
+her joined in her lament. Then King Priam spoke to them saying,
+"Bring wood, O Trojans, to the city, and fear no cunning ambush
+of the Argives, for Achilles when he dismissed me from the ships
+gave me his word that they should not attack us until the morning
+of the twelfth day."
+</para>
+
+<para>
+Forthwith they yoked their oxen and mules and gathered together
+before the city. Nine days long did they bring in great heaps of
+wood, and on the morning of the tenth day with many tears they
+took brave Hector forth, laid his dead body upon the summit of
+the pile, and set the fire thereto. Then when the child of
+morning, rosy-fingered dawn, appeared on the eleventh day, the
+people again assembled, round the pyre of mighty Hector. When
+they were got together, they first quenched the fire with wine
+wherever it was burning, and then his brothers and comrades with
+many a bitter tear gathered his white bones, wrapped them in soft
+robes of purple, and laid them in a golden urn, which they placed
+in a grave and covered over with large stones set close together.
+Then they built a barrow hurriedly over it keeping guard on every
+side lest the Achaeans should attack them before they had
+finished. When they had heaped up the barrow they went back again
+into the city, and being well assembled they held high feast in
+the house of Priam their king.
+</para>
+
+<para>
+Thus, then, did they celebrate the funeral of Hector tamer of
+horses.
+</para>
+</chapter>
+</bookbody>
+</book>
+<endgutblurb>
+End of The Project Gutenberg Etext of The Iliad of Homer,
+translated by Samuel Butler
+</endgutblurb>
+
+</gutbook>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/import/origin.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/import/origin.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/import/origin.xml	(revision 13928)
@@ -0,0 +1,17770 @@
+<?xml version="1.0"?>
+<!DOCTYPE gutbook SYSTEM "gutbook1.dtd">
+
+<?xml-stylesheet type="text/css" href="darwin.css"?>
+
+<gutbook>
+<gutblurb>
+<para>
+
+Project Gutenberg's Etext of On the Origin of Species, by Darwin
+#3 in our series by Charles Darwin
+</para>
+
+<para>
+This Etext is based on the First Edition, we are also working on
+the Sixth Edition, which many believe to be the best edition.
+</para>
+
+<para>
+
+Copyright laws are changing all over the world, be sure to check
+the copyright laws for your country before posting these files!!
+</para>
+
+<para>
+Please take a look at the important information in this header.
+We encourage you to keep this file on your own disk, keeping an
+electronic path open for the next readers.  Do not remove this.
+</para>
+
+<para>
+
+**Welcome To The World of Free Plain Vanilla Electronic Texts**
+</para>
+
+<para>
+**Etexts Readable By Both Humans and By Computers, Since 1971**
+</para>
+
+<para>
+*These Etexts Prepared By Hundreds of Volunteers and Donations*
+</para>
+
+<para>
+Information on contacting Project Gutenberg to get Etexts, and
+further information is included below.  We need your donations.
+</para>
+
+<para>
+
+On the Origin of Species
+</para>
+
+<para>
+by Charles Darwin
+</para>
+
+<para>
+March, 1998  [Etext #1228]
+</para>
+
+<para>
+
+Project Gutenberg's Etext of On the Origin of Species, by Darwin
+******This file should be named 1rbnh10.txt or 1rbnh10.zip******
+</para>
+
+<para>
+Corrected EDITIONS of our etexts get a new NUMBER, 1rbnh11.txt
+VERSIONS based on separate sources get new LETTER, 1rbnh10a.txt
+</para>
+
+<para>
+
+This etext was prepared by Joseph S. Miller, Pensacola, FL and
+Embry-Riddle Aeronautical University Library, Prescott, AZ.
+</para>
+
+<para>
+Project Gutenberg Etexts are usually created from multiple editions,
+all of which are in the Public Domain in the United States, unless a
+copyright notice is included.  Therefore, we do NOT keep these books
+in compliance with any particular paper edition, usually otherwise.
+</para>
+
+<para>
+
+We are now trying to release all our books one month in advance
+of the official release dates, for time for better editing.
+</para>
+
+<para>
+Please note:  neither this list nor its contents are final till
+midnight of the last day of the month of any such announcement.
+The official release date of all Project Gutenberg Etexts is at
+Midnight, Central Time, of the last day of the stated month.  A
+preliminary version may often be posted for suggestion, comment
+and editing by those who wish to do so.  To be sure you have an
+up to date first edition [xxxxx10x.xxx] please check file sizes
+in the first week of the next month.  Since our ftp program has
+a bug in it that scrambles the date [tried to fix and failed] a
+look at the file size will have to do, but we will try to see a
+new copy has at least one byte more or less.
+</para>
+
+<para>
+
+Information about Project Gutenberg (one page)
+</para>
+
+<para>
+We produce about two million dollars for each hour we work.  The
+fifty hours is one conservative estimate for how long it we take
+to get any etext selected, entered, proofread, edited, copyright
+searched and analyzed, the copyright letters written, etc.  This
+projected audience is one hundred million readers.  If our value
+per text is nominally estimated at one dollar then we produce $2
+million dollars per hour this year as we release thirty-two text
+files per month, or 384 more Etexts in 1998 for a total of 1500+
+If these reach just 10% of the computerized population, then the
+total should reach over 150 billion Etexts given away.
+</para>
+
+<para>
+The Goal of Project Gutenberg is to Give Away One Trillion Etext
+Files by the December 31, 2001.  [10,000 x 100,000,000=Trillion]
+This is ten thousand titles each to one hundred million readers,
+which is only 10% of the present number of computer users.  2001
+should have at least twice as many computer users as that, so it
+will require us reaching less than 5% of the users in 2001.
+</para>
+
+<para>
+
+We need your donations more than ever!
+</para>
+
+<para>
+
+All donations should be made to "Project Gutenberg/CMU": and are
+tax deductible to the extent allowable by law.  (CMU = Carnegie-
+Mellon University).
+</para>
+
+<para>
+For these and other matters, please mail to:
+</para>
+
+<para>
+Project Gutenberg
+P. O. Box  2782
+Champaign, IL 61825
+</para>
+
+<para>
+When all other email fails try our Executive Director:
+Michael S. Hart &lt;hart@pobox.com>
+</para>
+
+<para>
+We would prefer to send you this information by email
+(Internet, Bitnet, Compuserve, ATTMAIL or MCImail).
+</para>
+
+<para>
+******
+If you have an FTP program (or emulator), please
+FTP directly to the Project Gutenberg archives:
+[Mac users, do NOT point and click. . .type]
+</para>
+
+<para>
+ftp uiarchive.cso.uiuc.edu
+login:  anonymous
+password:  your@login
+cd etext/etext90 through /etext96
+or cd etext/articles [get suggest gut for more information]
+dir [to see files]
+get or mget [to get files. . .set bin for zip files]
+GET INDEX?00.GUT
+for a list of books
+and
+GET NEW GUT for general information
+and
+MGET GUT* for newsletters.
+</para>
+
+<para>
+**Information prepared by the Project Gutenberg legal advisor**
+(Three Pages)
+</para>
+
+<para>
+
+***START**THE SMALL PRINT!**FOR PUBLIC DOMAIN ETEXTS**START***
+Why is this "Small Print!" statement here?  You know: lawyers.
+They tell us you might sue us if there is something wrong with
+your copy of this etext, even if you got it for free from
+someone other than us, and even if what's wrong is not our
+fault.  So, among other things, this "Small Print!" statement
+disclaims most of our liability to you.  It also tells you how
+you can distribute copies of this etext if you want to.
+</para>
+
+<para>
+*BEFORE!* YOU USE OR READ THIS ETEXT
+By using or reading any part of this PROJECT GUTENBERG-tm
+etext, you indicate that you understand, agree to and accept
+this "Small Print!" statement.  If you do not, you can receive
+a refund of the money (if any) you paid for this etext by
+sending a request within 30 days of receiving it to the person
+you got it from.  If you received this etext on a physical
+medium (such as a disk), you must return it with your request.
+</para>
+
+<para>
+ABOUT PROJECT GUTENBERG-TM ETEXTS
+This PROJECT GUTENBERG-tm etext, like most PROJECT GUTENBERG-
+tm etexts, is a "public domain" work distributed by Professor
+Michael S. Hart through the Project Gutenberg Association at
+Carnegie-Mellon University (the "Project").  Among other
+things, this means that no one owns a United States copyright
+on or for this work, so the Project (and you!) can copy and
+distribute it in the United States without permission and
+without paying copyright royalties.  Special rules, set forth
+below, apply if you wish to copy and distribute this etext
+under the Project's "PROJECT GUTENBERG" trademark.
+</para>
+
+<para>
+To create these etexts, the Project expends considerable
+efforts to identify, transcribe and proofread public domain
+works.  Despite these efforts, the Project's etexts and any
+medium they may be on may contain "Defects".  Among other
+things, Defects may take the form of incomplete, inaccurate or
+corrupt data, transcription errors, a copyright or other
+intellectual property infringement, a defective or damaged
+disk or other etext medium, a computer virus, or computer
+codes that damage or cannot be read by your equipment.
+</para>
+
+<para>
+LIMITED WARRANTY; DISCLAIMER OF DAMAGES
+But for the "Right of Replacement or Refund" described below,
+[1] the Project (and any other party you may receive this
+etext from as a PROJECT GUTENBERG-tm etext) disclaims all
+liability to you for damages, costs and expenses, including
+legal fees, and [2] YOU HAVE NO REMEDIES FOR NEGLIGENCE OR
+UNDER STRICT LIABILITY, OR FOR BREACH OF WARRANTY OR CONTRACT,
+INCLUDING BUT NOT LIMITED TO INDIRECT, CONSEQUENTIAL, PUNITIVE
+OR INCIDENTAL DAMAGES, EVEN IF YOU GIVE NOTICE OF THE
+POSSIBILITY OF SUCH DAMAGES.
+</para>
+
+<para>
+If you discover a Defect in this etext within 90 days of
+receiving it, you can receive a refund of the money (if any)
+you paid for it by sending an explanatory note within that
+time to the person you received it from.  If you received it
+on a physical medium, you must return it with your note, and
+such person may choose to alternatively give you a replacement
+copy.  If you received it electronically, such person may
+choose to alternatively give you a second opportunity to
+receive it electronically.
+</para>
+
+<para>
+THIS ETEXT IS OTHERWISE PROVIDED TO YOU "AS-IS".  NO OTHER
+WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, ARE MADE TO YOU AS
+TO THE ETEXT OR ANY MEDIUM IT MAY BE ON, INCLUDING BUT NOT
+LIMITED TO WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
+PARTICULAR PURPOSE.
+</para>
+
+<para>
+Some states do not allow disclaimers of implied warranties or
+the exclusion or limitation of consequential damages, so the
+above disclaimers and exclusions may not apply to you, and you
+may have other legal rights.
+</para>
+
+<para>
+INDEMNITY
+You will indemnify and hold the Project, its directors,
+officers, members and agents harmless from all liability, cost
+and expense, including legal fees, that arise directly or
+indirectly from any of the following that you do or cause:
+[1] distribution of this etext, [2] alteration, modification,
+or addition to the etext, or [3] any Defect.
+</para>
+
+<para>
+DISTRIBUTION UNDER "PROJECT GUTENBERG-tm"
+You may distribute copies of this etext electronically, or by
+disk, book or any other medium if you either delete this
+"Small Print!" and all other references to Project Gutenberg,
+or:
+</para>
+
+<para>
+[1]  Only give exact copies of it.  Among other things, this
+     requires that you do not remove, alter or modify the
+     etext or this "small print!" statement.  You may however,
+     if you wish, distribute this etext in machine readable
+     binary, compressed, mark-up, or proprietary form,
+     including any form resulting from conversion by word pro-
+     cessing or hypertext software, but only so long as
+     *EITHER*:
+</para>
+
+<para>
+     [*]  The etext, when displayed, is clearly readable, and
+          does *not* contain characters other than those
+          intended by the author of the work, although tilde
+          (~), asterisk (*) and underline (_) characters may
+          be used to convey punctuation intended by the
+          author, and additional characters may be used to
+          indicate hypertext links; OR
+</para>
+
+<para>
+     [*]  The etext may be readily converted by the reader at
+          no expense into plain ASCII, EBCDIC or equivalent
+          form by the program that displays the etext (as is
+          the case, for instance, with most word processors);
+          OR
+</para>
+
+<para>
+     [*]  You provide, or agree to also provide on request at
+          no additional cost, fee or expense, a copy of the
+          etext in its original plain ASCII form (or in EBCDIC
+          or other equivalent proprietary form).
+</para>
+
+<para>
+[2]  Honor the etext refund and replacement provisions of this
+     "Small Print!" statement.
+</para>
+
+<para>
+[3]  Pay a trademark license fee to the Project of 20% of the
+     net profits you derive calculated using the method you
+     already use to calculate your applicable taxes.  If you
+     don't derive profits, no royalty is due.  Royalties are
+     payable to "Project Gutenberg Association/Carnegie-Mellon
+     University" within the 60 days following each
+     date you prepare (or were legally required to prepare)
+     your annual (or equivalent periodic) tax return.
+</para>
+
+<para>
+WHAT IF YOU *WANT* TO SEND MONEY EVEN IF YOU DON'T HAVE TO?
+The Project gratefully accepts contributions in money, time,
+scanning machines, OCR software, public domain etexts, royalty
+free copyright licenses, and every other sort of contribution
+you can think of.  Money should be paid to "Project Gutenberg
+Association / Carnegie-Mellon University".
+</para>
+
+<para>
+*END*THE SMALL PRINT! FOR PUBLIC DOMAIN ETEXTS*Ver.04.29.93*END*
+</para>
+
+</gutblurb>
+<markupblurb>
+Frank Boumphrey 9:25 AM 1/24/00
+Validated using MSXML and gutbook1.dtd
+</markupblurb>
+
+<book>
+<acknowledge>'On the Origin of Species' by Charles Darwin.
+  A project of Project Gutenberg and the HTML Writers Guild.
+  Transcribed by  Joseph S. Miller and
+Embry-Riddle Aeronautical University Library.
+  Markup by Frank Boumphrey. Jan 22 2000.
+For more details view the source document.
+</acknowledge>
+<frontmatter>
+<htitlepage>
+<title>
+On the Origin of Species
+</title>
+
+<author>
+by Charles Darwin
+</author>
+</htitlepage>
+
+<epigraph>
+<blockquote>
+<para>
+'But with regard to the material world, we can at least go so far as this--
+we can perceive that events are brought about not by insulated
+interpositions of Divine power, exerted in each particular case, but by the
+establishment of general laws.'
+</para>
+
+<attrib>
+W. Whewell: Bridgewater Treatise.
+</attrib>
+</blockquote>
+
+<blockquote>
+<para>
+'To conclude, therefore, let no man out of a weak conceit of sobriety, or
+an ill-applied moderation, think or maintain, that a man can search too far
+or be too well studied in the book of God's word, or in the book of God's
+works; divinity or philosophy; but rather let men endeavour an endless
+progress or proficience in both.'
+</para>
+
+<attrib>
+Bacon: Advancement of Learning.
+</attrib>
+</blockquote>
+
+
+<para>
+
+<place>Down, Bromley, Kent,</place> 
+</para>
+
+<para>
+<date>October 1st, 1859.</date>
+</para>
+</epigraph>
+
+<titlepage>
+<title>
+On the Origin of Species by Means of Natural Selection, 
+</title>
+
+<para>
+or the
+</para>
+
+<subtitle>
+Preservation of Favoured Races in the Struggle for Life.
+</subtitle>
+
+<author>
+By Charles Darwin
+</author>
+
+</titlepage>
+
+<toc>
+<title>Contents</title>
+
+<deflist>
+
+<item>
+Introduction
+</item>
+
+
+<item>
+Chapter I
+</item>
+
+<desc>
+Variation under Domestication
+</desc>
+
+<def>
+Causes of Variability -- Effects of Habit -- Correlation of Growth --
+Inheritance -- Character of Domestic Varieties -- Difficulty of
+distinguishing between Varieties and Species -- Origin of Domestic
+Varieties from one or more Species -- Domestic Pigeons, their Differences
+and Origin -- Principle of Selection anciently followed, its Effects --
+Methodical and Unconscious Selection -- Unknown Origin of our Domestic
+Productions -- Circumstances favourable to Man's power of Selection.
+</def>
+
+
+
+<item>
+Chapter II
+</item>
+
+<desc>
+Variation under Nature
+</desc>
+
+<def>
+Variability -- Individual Differences -- Doubtful species -- Wide ranging,
+much diffused, and common species vary most -- Species of the larger genera
+in any country vary more than the species of the smaller genera -- Many of
+the species of the larger genera resemble varieties in being very closely,
+but unequally, related to each other, and in having restricted ranges.
+</def>
+
+
+
+<item>
+Chapter III
+</item>
+
+<desc>
+Struggle for Existence
+</desc>
+
+<def>
+Bears on natural selection -- The term used in a wide sense -- Geometrical
+powers of increase -- Rapid increase of naturalised animals and plants --
+Nature of the checks to increase -- Competition universal -- Effects of
+climate -- Protection from the number of individuals -- Complex relations
+of all animals and plants throughout nature -- Struggle for life most
+severe between individuals and varieties of the same species; often severe
+between species of the same genus -- The relation of organism to organism
+the most important of all relations.
+</def>
+
+
+
+<item>
+Chapter IV
+</item>
+
+<desc>
+Natural Selection
+</desc>
+
+<def>
+Natural Selection -- its power compared with man's selection -- its power
+on characters of trifling importance -- its power at all ages and on both
+sexes -- Sexual Selection -- On the generality of intercrosses between
+individuals of the same species -- Circumstances favourable and
+unfavourable to Natural Selection, namely, intercrossing, isolation, number
+of individuals -- Slow action -- Extinction caused by Natural Selection --
+Divergence of Character, related to the diversity of inhabitants of any
+small area, and to naturalisation -- Action of Natural Selection, through
+Divergence of Character and Extinction, on the descendants from a common
+parent -- Explains the Grouping of all organic beings.
+</def>
+
+
+
+<item>
+Chapter V
+</item>
+
+<desc>
+Laws of Variation
+</desc>
+
+<def>
+Effects of external conditions -- Use and disuse, combined with natural
+selection; organs of flight and of vision -- Acclimatisation -- Correlation
+of growth -- Compensation and economy of growth -- False correlations --
+Multiple, rudimentary, and lowly organised structures variable -- Parts
+developed in an unusual manner are highly variable:  specific characters
+more variable than generic:  secondary sexual characters variable --
+Species of the same genus vary in an analogous manner -- Reversions to
+long-lost characters -- Summary.
+</def>
+
+
+
+<item>
+Chapter VI
+</item>
+
+<desc>
+Difficulties on Theory
+</desc>
+
+<def>
+Difficulties on the theory of descent with modification -- Transitions --
+Absence or rarity of transitional varieties -- Transitions in habits of
+life -- Diversified habits in the same species -- Species with habits
+widely different from those of their allies -- Organs of extreme perfection
+-- Means of transition -- Cases of difficulty -- Natura non facit saltum --
+Organs of small importance -- Organs not in all cases absolutely perfect --
+The law of Unity of Type and of the Conditions of Existence embraced by the
+theory of Natural Selection.
+</def>
+
+
+
+<item>
+Chapter VII
+</item>
+
+<desc>
+Instinct
+</desc>
+
+<def>
+Instincts comparable with habits, but different in their origin --
+Instincts graduated -- Aphides and ants -- Instincts variable -- Domestic
+instincts, their origin -- Natural instincts of the cuckoo, ostrich, and
+parasitic bees -- Slave-making ants -- Hive-bee, its cell-making instinct -
+- Difficulties on the theory of the Natural Selection of instincts --
+Neuter or sterile insects -- Summary.
+</def>
+
+
+
+<item>
+Chapter VIII
+</item>
+
+<desc>
+Hybridism
+</desc>
+
+<def>
+Distinction between the sterility of first crosses and of hybrids --
+Sterility various in degree, not universal, affected by close
+interbreeding, removed by domestication -- Laws governing the sterility of
+hybrids -- Sterility not a special endowment, but incidental on other
+differences -- Causes of the sterility of first crosses and of hybrids --
+Parallelism between the effects of changed conditions of life and crossing
+-- Fertility of varieties when crossed and of their mongrel offspring not
+universal -- Hybrids and mongrels compared independently of their fertility
+-- Summary.
+</def>
+
+
+
+<item>
+Chapter IX
+</item>
+
+<desc>
+On the Imperfection of the Geological Record
+</desc>
+
+<def>
+On the absence of intermediate varieties at the present day -- On the
+nature of extinct intermediate varieties; on their number -- On the vast
+lapse of time, as inferred from the rate of deposition and of denudation --
+On the poorness of our palaeontological collections -- On the intermittence
+of geological formations -- On the absence of intermediate varieties in any
+one formation -- On the sudden appearance of groups of species -- On their
+sudden appearance in the lowest known fossiliferous strata.
+</def>
+
+
+
+<item>
+Chapter X
+</item>
+
+<desc>
+On the Geological Succession of Organic Beings
+</desc>
+
+<def>
+On the slow and successive appearance of new species -- On their different
+rates of change -- Species once lost do not reappear -- Groups of species
+follow the same general rules in their appearance and disappearance as do
+single species -- On Extinction -- On simultaneous changes in the forms of
+life throughout the world -- On the affinities of extinct species to each
+other and to living species -- On the state of development of ancient forms
+-- On the succession of the same types within the same areas -- Summary of
+preceding and present chapters.
+</def>
+
+
+
+<item>
+Chapter XI
+</item>
+
+<desc>
+Geographical Distribution
+</desc>
+
+<def>
+Present distribution cannot be accounted for by differences in physical
+conditions -- Importance of barriers -- Affinity of the productions of the
+same continent -- Centres of creation -- Means of dispersal, by changes of
+climate and of the level of the land, and by occasional means -- Dispersal
+during the Glacial period co-extensive with the world.
+</def>
+
+
+
+<item>
+Chapter XII
+</item>
+
+<desc>
+Geographical Distribution -- continued
+</desc>
+
+<def>
+Distribution of fresh-water productions -- On the inhabitants of oceanic
+islands -- Absence of Batrachians and of terrestrial Mammals -- On the
+relation of the inhabitants of islands to those of the nearest mainland --
+On colonisation from the nearest source with subsequent modification --
+Summary of the last and present chapters.
+</def>
+
+
+
+<item>
+Chapter XIII
+</item>
+
+<desc>
+Mutual Affinities of Organic Beings:
+Morphology:  Embryology:  Rudimentary Organs
+</desc>
+
+<def>
+Classification, groups subordinate to groups -- Natural system -- Rules and
+difficulties in classification, explained on the theory of descent with
+modification -- Classification of varieties -- Descent always used in
+classification -- Analogical or adaptive characters -- Affinities, general,
+complex and radiating -- Extinction separates and defines groups --
+Morphology, between members of the same class, between parts of the same
+individual -- Embryology, laws of, explained by variations not supervening
+at an early age, and being inherited at a corresponding age -- Rudimentary
+Organs; their origin explained -- Summary.
+</def>
+
+
+
+<item>
+Chapter XIV
+</item>
+
+<desc>
+Recapitulation and Conclusion
+</desc>
+
+<def>
+Recapitulation of the difficulties on the theory of Natural Selection --
+Recapitulation of the general and special circumstances in its favour --
+Causes of the general belief in the immutability of species -- How far the
+theory of natural selection may be extended -- Effects of its adoption on
+the study of Natural history -- Concluding remarks.
+</def>
+</deflist>
+</toc>
+
+
+
+
+<introduction>
+<title>
+On the Origin of Species.
+
+Introduction.
+</title>
+
+<para>
+When on board H.M.S. 'Beagle,' as naturalist, I was much struck with
+certain facts in the distribution of the inhabitants of South America, and
+in the geological relations of the present to the past inhabitants of that
+continent.  These facts seemed to me to throw some light on the origin of
+species--that mystery of mysteries, as it has been called by one of our
+greatest philosophers.  On my return home, it occurred to me, in 1837, that
+something might perhaps be made out on this question by patiently
+accumulating and reflecting on all sorts of facts which could possibly have
+any bearing on it.  After five years' work I allowed myself to speculate on
+the subject, and drew up some short notes; these I enlarged in 1844 into a
+sketch of the conclusions, which then seemed to me probable:  from that
+period to the present day I have steadily pursued the same object.  I hope
+that I may be excused for entering on these personal details, as I give
+them to show that I have not been hasty in coming to a decision.
+</para>
+
+<para>
+My work is now nearly finished; but as it will take me two or three more
+years to complete it, and as my health is far from strong, I have been
+urged to publish this Abstract.  I have more especially been induced to do
+this, as Mr. Wallace, who is now studying the natural history of the Malay
+archipelago, has arrived at almost exactly the same general conclusions
+that I have on the origin of species.  Last year he sent to me a memoir on
+this subject, with a request that I would forward it to Sir Charles Lyell,
+who sent it to the Linnean Society, and it is published in the third volume
+of the Journal of that Society.  Sir C. Lyell and Dr. Hooker, who both knew
+of my work--the latter having read my sketch of 1844--honoured me by
+thinking it advisable to publish, with Mr. Wallace's excellent memoir, some
+brief extracts from my manuscripts.
+</para>
+
+<para>
+This Abstract, which I now publish, must necessarily be imperfect.  I
+cannot here give references and authorities for my several statements; and
+I must trust to the reader reposing some confidence in my accuracy.  No
+doubt errors will have crept in, though I hope I have always been cautious
+in trusting to good authorities alone.  I can here give only the general
+conclusions at which I have arrived, with a few facts in illustration, but
+which, I hope, in most cases will suffice.  No one can feel more sensible
+than I do of the necessity of hereafter publishing in detail all the facts,
+with references, on which my conclusions have been grounded; and I hope in
+a future work to do this.  For I am well aware that scarcely a single point
+is discussed in this volume on which facts cannot be adduced, often
+apparently leading to conclusions directly opposite to those at which I
+have arrived.  A fair result can be obtained only by fully stating and
+balancing the facts and arguments on both sides of each question; and this
+cannot possibly be here done.
+</para>
+
+<para>
+I much regret that want of space prevents my having the satisfaction of
+acknowledging the generous assistance which I have received from very many
+naturalists, some of them personally unknown to me.  I cannot, however, let
+this opportunity pass without expressing my deep obligations to Dr. Hooker,
+who for the last fifteen years has aided me in every possible way by his
+large stores of knowledge and his excellent judgment.
+</para>
+
+<para>
+In considering the Origin of Species, it is quite conceivable that a
+naturalist, reflecting on the mutual affinities of organic beings, on their
+embryological relations, their geographical distribution, geological
+succession, and other such facts, might come to the conclusion that each
+species had not been independently created, but had descended, like
+varieties, from other species.  Nevertheless, such a conclusion, even if
+well founded, would be unsatisfactory, until it could be shown how the
+innumerable species inhabiting this world have been modified, so as to
+acquire that perfection of structure and coadaptation which most justly
+excites our admiration.  Naturalists continually refer to external
+conditions, such as climate, food, &amp;c., as the only possible cause of
+variation.  In one very limited sense, as we shall hereafter see, this may
+be true; but it is preposterous to attribute to mere external conditions,
+the structure, for instance, of the woodpecker, with its feet, tail, beak,
+and tongue, so admirably adapted to catch insects under the bark of trees. 
+In the case of the misseltoe, which draws its nourishment from certain
+trees, which has seeds that must be transported by certain birds, and which
+has flowers with separate sexes absolutely requiring the agency of certain
+insects to bring pollen from one flower to the other, it is equally
+preposterous to account for the structure of this parasite, with its
+relations to several distinct organic beings, by the effects of external
+conditions, or of habit, or of the volition of the plant itself.
+</para>
+
+<para>
+The author of the 'Vestiges of Creation' would, I presume, say that, after
+a certain unknown number of generations, some bird had given birth to a
+woodpecker, and some plant to the misseltoe, and that these had been
+produced perfect as we now see them; but this assumption seems to me to be
+no explanation, for it leaves the case of the coadaptations of organic
+beings to each other and to their physical conditions of life, untouched
+and unexplained.
+</para>
+
+<para>
+It is, therefore, of the highest importance to gain a clear insight into
+the means of modification and coadaptation.  At the commencement of my
+observations it seemed to me probable that a careful study of domesticated
+animals and of cultivated plants would offer the best chance of making out
+this obscure problem.  Nor have I been disappointed; in this and in all
+other perplexing cases I have invariably found that our knowledge,
+imperfect though it be, of variation under domestication, afforded the best
+and safest clue.  I may venture to express my conviction of the high value
+of such studies, although they have been very commonly neglected by
+naturalists.
+</para>
+
+<para>
+From these considerations, I shall devote the first chapter of this
+Abstract to Variation under Domestication.  We shall thus see that a large
+amount of hereditary modification is at least possible, and, what is
+equally or more important, we shall see how great is the power of man in
+accumulating by his Selection successive slight variations.  I will then
+pass on to the variability of species in a state of nature; but I shall,
+unfortunately, be compelled to treat this subject far too briefly, as it
+can be treated properly only by giving long catalogues of facts.  We shall,
+however, be enabled to discuss what circumstances are most favourable to
+variation.  In the next chapter the Struggle for Existence amongst all
+organic beings throughout the world, which inevitably follows from their
+high geometrical powers of increase, will be treated of.  This is the
+doctrine of Malthus, applied to the whole animal and vegetable kingdoms. 
+As many more individuals of each species are born than can possibly
+survive; and as, consequently, there is a frequently recurring struggle for
+existence, it follows that any being, if it vary however slightly in any
+manner profitable to itself, under the complex and sometimes varying
+conditions of life, will have a better chance of surviving, and thus be
+naturally selected.  From the strong principle of inheritance, any selected
+variety will tend to propagate its new and modified form.
+</para>
+
+<para>
+This fundamental subject of Natural Selection will be treated at some
+length in the fourth chapter; and we shall then see how Natural Selection
+almost inevitably causes much Extinction of the less improved forms of life
+and induces what I have called Divergence of Character.  In the next
+chapter I shall discuss the complex and little known laws of variation and
+of correlation of growth.  In the four succeeding chapters, the most
+apparent and gravest difficulties on the theory will be given:  namely,
+first, the difficulties of transitions, or in understanding how a simple
+being or a simple organ can be changed and perfected into a highly
+developed being or elaborately constructed organ; secondly the subject of
+Instinct, or the mental powers of animals, thirdly, Hybridism, or the
+infertility of species and the fertility of varieties when intercrossed;
+and fourthly, the imperfection of the Geological Record.  In the next
+chapter I shall consider the geological succession of organic beings
+throughout time; in the eleventh and twelfth, their geographical
+distribution throughout space; in the thirteenth, their classification or
+mutual affinities, both when mature and in an embryonic condition.  In the
+last chapter I shall give a brief recapitulation of the whole work, and a
+few concluding remarks.
+</para>
+
+<para>
+No one ought to feel surprise at much remaining as yet unexplained in
+regard to the origin of species and varieties, if he makes due allowance
+for our profound ignorance in regard to the mutual relations of all the
+beings which live around us.  Who can explain why one species ranges widely
+and is very numerous, and why another allied species has a narrow range and
+is rare?  Yet these relations are of the highest importance, for they
+determine the present welfare, and, as I believe, the future success and
+modification of every inhabitant of this world.  Still less do we know of
+the mutual relations of the innumerable inhabitants of the world during the
+many past geological epochs in its history.  Although much remains obscure,
+and will long remain obscure, I can entertain no doubt, after the most
+deliberate study and dispassionate judgment of which I am capable, that the
+view which most naturalists entertain, and which I formerly
+entertained--namely, that each species has been independently created--is
+erroneous.  I am fully convinced that species are not immutable; but that
+those belonging to what are called the same genera are lineal descendants
+of some other and generally extinct species, in the same manner as the
+acknowledged varieties of any one species are the descendants of that
+species.  Furthermore, I am convinced that Natural Selection has been the
+main but not exclusive means of modification.
+</para>
+</introduction>
+</frontmatter>
+<bookbody>
+
+<chapter>
+<chapheader>
+
+<chapnum>Chapter I</chapnum>
+
+<title>Variation under Domestication</title>
+
+<chapsummary>
+Causes of Variability -- Effects of Habit -- Correlation of Growth --
+Inheritance -- Character of Domestic Varieties -- Difficulty of
+distinguishing between Varieties and Species -- Origin of Domestic
+Varieties from one or more Species -- Domestic Pigeons, their Differences
+and Origin -- Principle of Selection anciently followed, its Effects --
+Methodical and Unconscious Selection -- Unknown Origin of our Domestic
+Productions -- Circumstances favourable to Man's power of Selection.
+</chapsummary>
+</chapheader>
+
+<para>
+When we look to the individuals of the same variety or sub-variety of our
+older cultivated plants and animals, one of the first points which strikes
+us, is, that they generally differ much more from each other, than do the
+individuals of any one species or variety in a state of nature.  When we
+reflect on the vast diversity of the plants and animals which have been
+cultivated, and which have varied during all ages under the most different
+climates and treatment, I think we are driven to conclude that this greater
+variability is simply due to our domestic productions having been raised
+under conditions of life not so uniform as, and somewhat different from,
+those to which the parent-species have been exposed under nature.  There
+is, also, I think, some probability in the view propounded by Andrew
+Knight, that this variability may be partly connected with excess of food. 
+It seems pretty clear that organic beings must be exposed during several
+generations to the new conditions of life to cause any appreciable amount
+of variation; and that when the organisation has once begun to vary, it
+generally continues to vary for many generations.  No case is on record of
+a variable being ceasing to be variable under cultivation.  Our oldest
+cultivated plants, such as wheat, still often yield new varieties:  our
+oldest domesticated animals are still capable of rapid improvement or
+modification.
+</para>
+
+<para>
+It has been disputed at what period of life the causes of variability,
+whatever they may be, generally act; whether during the early or late
+period of development of the embryo, or at the instant of conception. 
+Geoffroy St. Hilaire's experiments show that unnatural treatment of the
+embryo causes monstrosities; and monstrosities cannot be separated by any
+clear line of distinction from mere variations.  But I am strongly inclined
+to suspect that the most frequent cause of variability may be attributed to
+the male and female reproductive elements having been affected prior to the
+act of conception.  Several reasons make me believe in this; but the chief
+one is the remarkable effect which confinement or cultivation has on the
+functions of the reproductive system; this system appearing to be far more
+susceptible than any other part of the organisation, to the action of any
+change in the conditions of life.  Nothing is more easy than to tame an
+animal, and few things more difficult than to get it to breed freely under
+confinement, even in the many cases when the male and female unite.  How
+many animals there are which will not breed, though living long under not
+very close confinement in their native country!  This is generally
+attributed to vitiated instincts; but how many cultivated plants display
+the utmost vigour, and yet rarely or never seed!  In some few such cases it
+has been found out that very trifling changes, such as a little more or
+less water at some particular period of growth, will determine whether or
+not the plant sets a seed.  I cannot here enter on the copious details
+which I have collected on this curious subject; but to show how singular
+the laws are which determine the reproduction of animals under confinement,
+I may just mention that carnivorous animals, even from the tropics, breed
+in this country pretty freely under confinement, with the exception of the
+plantigrades or bear family; whereas, carnivorous birds, with the rarest
+exceptions, hardly ever lay fertile eggs.  Many exotic plants have pollen
+utterly worthless, in the same exact condition as in the most sterile
+hybrids.  When, on the one hand, we see domesticated animals and plants,
+though often weak and sickly, yet breeding quite freely under confinement;
+and when, on the other hand, we see individuals, though taken young from a
+state of nature, perfectly tamed, long-lived, and healthy (of which I could
+give numerous instances), yet having their reproductive system so seriously
+affected by unperceived causes as to fail in acting, we need not be
+surprised at this system, when it does act under confinement, acting not
+quite regularly, and producing offspring not perfectly like their parents
+or variable.
+</para>
+
+<para>
+Sterility has been said to be the bane of horticulture; but on this view we
+owe variability to the same cause which produces sterility; and variability
+is the source of all the choicest productions of the garden.  I may add,
+that as some organisms will breed most freely under the most unnatural
+conditions (for instance, the rabbit and ferret kept in hutches), showing
+that their reproductive system has not been thus affected; so will some
+animals and plants withstand domestication or cultivation, and vary very
+slightly--perhaps hardly more than in a state of nature.
+</para>
+
+<para>
+A long list could easily be given of 'sporting plants;' by this term
+gardeners mean a single bud or offset, which suddenly assumes a new and
+sometimes very different character from that of the rest of the plant. 
+Such buds can be propagated by grafting, &amp;c., and sometimes by seed.  These
+'sports' are extremely rare under nature, but far from rare under
+cultivation; and in this case we see that the treatment of the parent has
+affected a bud or offset, and not the ovules or pollen.  But it is the
+opinion of most physiologists that there is no essential difference between
+a bud and an ovule in their earliest stages of formation; so that, in fact,
+'sports' support my view, that variability may be largely attributed to the
+ovules or pollen, or to both, having been affected by the treatment of the
+parent prior to the act of conception.  These cases anyhow show that
+variation is not necessarily connected, as some authors have supposed, with
+the act of generation.
+</para>
+
+<para>
+Seedlings from the same fruit, and the young of the same litter, sometimes
+differ considerably from each other, though both the young and the parents,
+as Muller has remarked, have apparently been exposed to exactly the same
+conditions of life; and this shows how unimportant the direct effects of
+the conditions of life are in comparison with the laws of reproduction, and
+of growth, and of inheritance; for had the action of the conditions been
+direct, if any of the young had varied, all would probably have varied in
+the same manner.  To judge how much, in the case of any variation, we
+should attribute to the direct action of heat, moisture, light, food, &amp;c.,
+is most difficult:  my impression is, that with animals such agencies have
+produced very little direct effect, though apparently more in the case of
+plants.  Under this point of view, Mr. Buckman's recent experiments on
+plants seem extremely valuable.  When all or nearly all the individuals
+exposed to certain conditions are affected in the same way, the change at
+first appears to be directly due to such conditions; but in some cases it
+can be shown that quite opposite conditions produce similar changes of
+structure.  Nevertheless some slight amount of change may, I think, be
+attributed to the direct action of the conditions of life--as, in some
+cases, increased size from amount of food, colour from particular kinds of
+food and from light, and perhaps the thickness of fur from climate.
+</para>
+
+<para>
+Habit also has a deciding influence, as in the period of flowering with
+plants when transported from one climate to another.  In animals it has a
+more marked effect; for instance, I find in the domestic duck that the
+bones of the wing weigh less and the bones of the leg more, in proportion
+to the whole skeleton, than do the same bones in the wild-duck; and I
+presume that this change may be safely attributed to the domestic duck
+flying much less, and walking more, than its wild parent.  The great and
+inherited development of the udders in cows and goats in countries where
+they are habitually milked, in comparison with the state of these organs in
+other countries, is another instance of the effect of use.  Not a single
+domestic animal can be named which has not in some country drooping ears;
+and the view suggested by some authors, that the drooping is due to the
+disuse of the muscles of the ear, from the animals not being much alarmed
+by danger, seems probable.
+</para>
+
+<para>
+There are many laws regulating variation, some few of which can be dimly
+seen, and will be hereafter briefly mentioned.  I will here only allude to
+what may be called correlation of growth.  Any change in the embryo or
+larva will almost certainly entail changes in the mature animal.  In
+monstrosities, the correlations between quite distinct parts are very
+curious; and many instances are given in Isidore Geoffroy St. Hilaire's
+great work on this subject.  Breeders believe that long limbs are almost
+always accompanied by an elongated head.  Some instances of correlation are
+quite whimsical; thus cats with blue eyes are invariably deaf; colour and
+constitutional peculiarities go together, of which many remarkable cases
+could be given amongst animals and plants.  From the facts collected by
+Heusinger, it appears that white sheep and pigs are differently affected
+from coloured individuals by certain vegetable poisons.  Hairless dogs have
+imperfect teeth; long-haired and coarse-haired animals are apt to have, as
+is asserted, long or many horns; pigeons with feathered feet have skin
+between their outer toes; pigeons with short beaks have small feet, and
+those with long beaks large feet.  Hence, if man goes on selecting, and
+thus augmenting, any peculiarity, he will almost certainly unconsciously
+modify other parts of the structure, owing to the mysterious laws of the
+correlation of growth.
+</para>
+
+<para>
+The result of the various, quite unknown, or dimly seen laws of variation
+is infinitely complex and diversified.  It is well worth while carefully to
+study the several treatises published on some of our old cultivated plants,
+as on the hyacinth, potato, even the dahlia, &amp;c.; and it is really
+surprising to note the endless points in structure and constitution in
+which the varieties and sub-varieties differ slightly from each other.  The
+whole organisation seems to have become plastic, and tends to depart in
+some small degree from that of the parental type.
+</para>
+
+<para>
+Any variation which is not inherited is unimportant for us.  But the number
+and diversity of inheritable deviations of structure, both those of slight
+and those of considerable physiological importance, is endless.  Dr.
+Prosper Lucas's treatise, in two large volumes, is the fullest and the best
+on this subject.  No breeder doubts how strong is the tendency to
+inheritance:  like produces like is his fundamental belief:  doubts have
+been thrown on this principle by theoretical writers alone.  When a
+deviation appears not unfrequently, and we see it in the father and child,
+we cannot tell whether it may not be due to the same original cause acting
+on both; but when amongst individuals, apparently exposed to the same
+conditions, any very rare deviation, due to some extraordinary combination
+of circumstances, appears in the parent--say, once amongst several million
+individuals--and it reappears in the child, the mere doctrine of chances
+almost compels us to attribute its reappearance to inheritance.  Every one
+must have heard of cases of albinism, prickly skin, hairy bodies, &amp;c.,
+appearing in several members of the same family.  If strange and rare
+deviations of structure are truly inherited, less strange and commoner
+deviations may be freely admitted to be inheritable.  Perhaps the correct
+way of viewing the whole subject, would be, to look at the inheritance of
+every character whatever as the rule, and non-inheritance as the anomaly.
+</para>
+
+<para>
+The laws governing inheritance are quite unknown; no one can say why the
+same peculiarity in different individuals of the same species, and in
+individuals of different species, is sometimes inherited and sometimes not
+so; why the child often reverts in certain characters to its grandfather or
+grandmother or other much more remote ancestor; why a peculiarity is often
+transmitted from one sex to both sexes or to one sex alone, more commonly
+but not exclusively to the like sex.  It is a fact of some little
+importance to us, that peculiarities appearing in the males of our domestic
+breeds are often transmitted either exclusively, or in a much greater
+degree, to males alone.  A much more important rule, which I think may be
+trusted, is that, at whatever period of life a peculiarity first appears,
+it tends to appear in the offspring at a corresponding age, though
+sometimes earlier.  In many cases this could not be otherwise:  thus the
+inherited peculiarities in the horns of cattle could appear only in the
+offspring when nearly mature; peculiarities in the silkworm are known to
+appear at the corresponding caterpillar or cocoon stage.  But hereditary
+diseases and some other facts make me believe that the rule has a wider
+extension, and that when there is no apparent reason why a peculiarity
+should appear at any particular age, yet that it does tend to appear in the
+offspring at the same period at which it first appeared in the parent.  I
+believe this rule to be of the highest importance in explaining the laws of
+embryology.  These remarks are of course confined to the first appearance
+of the peculiarity, and not to its primary cause, which may have acted on
+the ovules or male element; in nearly the same manner as in the crossed
+offspring from a short-horned cow by a long-horned bull, the greater length
+of horn, though appearing late in life, is clearly due to the male element.
+</para>
+
+<para>
+Having alluded to the subject of reversion, I may here refer to a statement
+often made by naturalists--namely, that our domestic varieties, when run
+wild, gradually but certainly revert in character to their aboriginal
+stocks.  Hence it has been argued that no deductions can be drawn from
+domestic races to species in a state of nature.  I have in vain endeavoured
+to discover on what decisive facts the above statement has so often and so
+boldly been made.  There would be great difficulty in proving its truth: 
+we may safely conclude that very many of the most strongly-marked domestic
+varieties could not possibly live in a wild state.  In many cases we do not
+know what the aboriginal stock was, and so could not tell whether or not
+nearly perfect reversion had ensued.  It would be quite necessary, in order
+to prevent the effects of intercrossing, that only a single variety should
+be turned loose in its new home.  Nevertheless, as our varieties certainly
+do occasionally revert in some of their characters to ancestral forms, it
+seems to me not improbable, that if we could succeed in naturalising, or
+were to cultivate, during many generations, the several races, for
+instance, of the cabbage, in very poor soil (in which case, however, some
+effect would have to be attributed to the direct action of the poor soil),
+that they would to a large extent, or even wholly, revert to the wild
+aboriginal stock.  Whether or not the experiment would succeed, is not of
+great importance for our line of argument; for by the experiment itself the
+conditions of life are changed.  If it could be shown that our domestic
+varieties manifested a strong tendency to reversion,--that is, to lose
+their acquired characters, whilst kept under unchanged conditions, and
+whilst kept in a considerable body, so that free intercrossing might check,
+by blending together, any slight deviations of structure, in such case, I
+grant that we could deduce nothing from domestic varieties in regard to
+species.  But there is not a shadow of evidence in favour of this view:  to
+assert that we could not breed our cart and race-horses, long and
+short-horned cattle, and poultry of various breeds, and esculent
+vegetables, for an almost infinite number of generations, would be opposed
+to all experience.  I may add, that when under nature the conditions of
+life do change, variations and reversions of character probably do occur;
+but natural selection, as will hereafter be explained, will determine how
+far the new characters thus arising shall be preserved.
+</para>
+
+<para>
+When we look to the hereditary varieties or races of our domestic animals
+and plants, and compare them with species closely allied together, we
+generally perceive in each domestic race, as already remarked, less
+uniformity of character than in true species.  Domestic races of the same
+species, also, often have a somewhat monstrous character; by which I mean,
+that, although differing from each other, and from the other species of the
+same genus, in several trifling respects, they often differ in an extreme
+degree in some one part, both when compared one with another, and more
+especially when compared with all the species in nature to which they are
+nearest allied.  With these exceptions (and with that of the perfect
+fertility of varieties when crossed,--a subject hereafter to be discussed),
+domestic races of the same species differ from each other in the same
+manner as, only in most cases in a lesser degree than, do closely-allied
+species of the same genus in a state of nature.  I think this must be
+admitted, when we find that there are hardly any domestic races, either
+amongst animals or plants, which have not been ranked by some competent
+judges as mere varieties, and by other competent judges as the descendants
+of aboriginally distinct species.  If any marked distinction existed
+between domestic races and species, this source of doubt could not so
+perpetually recur.  It has often been stated that domestic races do not
+differ from each other in characters of generic value.  I think it could be
+shown that this statement is hardly correct; but naturalists differ most
+widely in determining what characters are of generic value; all such
+valuations being at present empirical.  Moreover, on the view of the origin
+of genera which I shall presently give, we have no right to expect often to
+meet with generic differences in our domesticated productions.
+</para>
+
+<para>
+When we attempt to estimate the amount of structural difference between the
+domestic races of the same species, we are soon involved in doubt, from not
+knowing whether they have descended from one or several parent-species. 
+This point, if it could be cleared up, would be interesting; if, for
+instance, it could be shown that the greyhound, bloodhound, terrier,
+spaniel, and bull-dog, which we all know propagate their kind so truly,
+were the offspring of any single species, then such facts would have great
+weight in making us doubt about the immutability of the many very closely
+allied and natural species--for instance, of the many foxes--inhabiting
+different quarters of the world.  I do not believe, as we shall presently
+see, that all our dogs have descended from any one wild species; but, in
+the case of some other domestic races, there is presumptive, or even
+strong, evidence in favour of this view.
+</para>
+
+<para>
+It has often been assumed that man has chosen for domestication animals and
+plants having an extraordinary inherent tendency to vary, and likewise to
+withstand diverse climates.  I do not dispute that these capacities have
+added largely to the value of most of our domesticated productions; but how
+could a savage possibly know, when he first tamed an animal, whether it
+would vary in succeeding generations, and whether it would endure other
+climates?  Has the little variability of the ass or guinea-fowl, or the
+small power of endurance of warmth by the rein-deer, or of cold by the
+common camel, prevented their domestication?  I cannot doubt that if other
+animals and plants, equal in number to our domesticated productions, and
+belonging to equally diverse classes and countries, were taken from a state
+of nature, and could be made to breed for an equal number of generations
+under domestication, they would vary on an average as largely as the parent
+species of our existing domesticated productions have varied.
+</para>
+
+<para>
+In the case of most of our anciently domesticated animals and plants, I do
+not think it is possible to come to any definite conclusion, whether they
+have descended from one or several species.  The argument mainly relied on
+by those who believe in the multiple origin of our domestic animals is,
+that we find in the most ancient records, more especially on the monuments
+of Egypt, much diversity in the breeds; and that some of the breeds closely
+resemble, perhaps are identical with, those still existing.  Even if this
+latter fact were found more strictly and generally true than seems to me to
+be the case, what does it show, but that some of our breeds originated
+there, four or five thousand years ago?  But Mr. Horner's researches have
+rendered it in some degree probable that man sufficiently civilized to have
+manufactured pottery existed in the valley of the Nile thirteen or fourteen
+thousand years ago; and who will pretend to say how long before these
+ancient periods, savages, like those of Tierra del Fuego or Australia, who
+possess a semi-domestic dog, may not have existed in Egypt?
+</para>
+
+<para>
+The whole subject must, I think, remain vague; nevertheless, I may, without
+here entering on any details, state that, from geographical and other
+considerations, I think it highly probable that our domestic dogs have
+descended from several wild species.  In regard to sheep and goats I can
+form no opinion.  I should think, from facts communicated to me by Mr.
+Blyth, on the habits, voice, and constitution, &amp;c., of the humped Indian
+cattle, that these had descended from a different aboriginal stock from our
+European cattle; and several competent judges believe that these latter
+have had more than one wild parent.  With respect to horses, from reasons
+which I cannot give here, I am doubtfully inclined to believe, in
+opposition to several authors, that all the races have descended from one
+wild stock.  Mr. Blyth, whose opinion, from his large and varied stores of
+knowledge, I should value more than that of almost any one, thinks that all
+the breeds of poultry have proceeded from the common wild Indian fowl
+(Gallus bankiva).  In regard to ducks and rabbits, the breeds of which
+differ considerably from each other in structure, I do not doubt that they
+all have descended from the common wild duck and rabbit.
+</para>
+
+<para>
+The doctrine of the origin of our several domestic races from several
+aboriginal stocks, has been carried to an absurd extreme by some authors. 
+They believe that every race which breeds true, let the distinctive
+characters be ever so slight, has had its wild prototype.  At this rate
+there must have existed at least a score of species of wild cattle, as many
+sheep, and several goats in Europe alone, and several even within Great
+Britain.  One author believes that there formerly existed in Great Britain
+eleven wild species of sheep peculiar to it!  When we bear in mind that
+Britain has now hardly one peculiar mammal, and France but few distinct
+from those of Germany and conversely, and so with Hungary, Spain, &amp;c., but
+that each of these kingdoms possesses several peculiar breeds of cattle,
+sheep, &amp;c., we must admit that many domestic breeds have originated in
+Europe; for whence could they have been derived, as these several countries
+do not possess a number of peculiar species as distinct parent-stocks?  So
+it is in India.  Even in the case of the domestic dogs of the whole world,
+which I fully admit have probably descended from several wild species, I
+cannot doubt that there has been an immense amount of inherited variation. 
+Who can believe that animals closely resembling the Italian greyhound, the
+bloodhound, the bull-dog, or Blenheim spaniel, &amp;c.--so unlike all wild
+Canidae--ever existed freely in a state of nature?  It has often been
+loosely said that all our races of dogs have been produced by the crossing
+of a few aboriginal species; but by crossing we can get only forms in some
+degree intermediate between their parents; and if we account for our
+several domestic races by this process, we must admit the former existence
+of the most extreme forms, as the Italian greyhound, bloodhound, bull-dog,
+&amp;c., in the wild state.  Moreover, the possibility of making distinct races
+by crossing has been greatly exaggerated.  There can be no doubt that a
+race may be modified by occasional crosses, if aided by the careful
+selection of those individual mongrels, which present any desired
+character; but that a race could be obtained nearly intermediate between
+two extremely different races or species, I can hardly believe.  Sir J.
+Sebright expressly experimentised for this object, and failed.  The
+offspring from the first cross between two pure breeds is tolerably and
+sometimes (as I have found with pigeons) extremely uniform, and everything
+seems simple enough; but when these mongrels are crossed one with another
+for several generations, hardly two of them will be alike, and then the
+extreme difficulty, or rather utter hopelessness, of the task becomes
+apparent.  Certainly, a breed intermediate between two very distinct breeds
+could not be got without extreme care and long-continued selection; nor can
+I find a single case on record of a permanent race having been thus formed.
+</para>
+
+<para>
+On the Breeds of the Domestic Pigeon. -- Believing that it is always best
+to study some special group, I have, after deliberation, taken up domestic
+pigeons.  I have kept every breed which I could purchase or obtain, and
+have been most kindly favoured with skins from several quarters of the
+world, more especially by the Hon. W. Elliot from India, and by the Hon. C.
+Murray from Persia.  Many treatises in different languages have been
+published on pigeons, and some of them are very important, as being of
+considerably antiquity.  I have associated with several eminent fanciers,
+and have been permitted to join two of the London Pigeon Clubs.  The
+diversity of the breeds is something astonishing.  Compare the English
+carrier and the short-faced tumbler, and see the wonderful difference in
+their beaks, entailing corresponding differences in their skulls.  The
+carrier, more especially the male bird, is also remarkable from the
+wonderful development of the carunculated skin about the head, and this is
+accompanied by greatly elongated eyelids, very large external orifices to
+the nostrils, and a wide gape of mouth.  The short-faced tumbler has a beak
+in outline almost like that of a finch; and the common tumbler has the
+singular and strictly inherited habit of flying at a great height in a
+compact flock, and tumbling in the air head over heels.  The runt is a bird
+of great size, with long, massive beak and large feet; some of the
+sub-breeds of runts have very long necks, others very long wings and tails,
+others singularly short tails.  The barb is allied to the carrier, but,
+instead of a very long beak, has a very short and very broad one.  The
+pouter has a much elongated body, wings, and legs; and its enormously
+developed crop, which it glories in inflating, may well excite astonishment
+and even laughter.  The turbit has a very short and conical beak, with a
+line of reversed feathers down the breast; and it has the habit of
+continually expanding slightly the upper part of the oesophagus.  The
+Jacobin has the feathers so much reversed along the back of the neck that
+they form a hood, and it has, proportionally to its size, much elongated
+wing and tail feathers.  The trumpeter and laugher, as their names express,
+utter a very different coo from the other breeds.  The fantail has thirty
+or even forty tail-feathers, instead of twelve or fourteen, the normal
+number in all members of the great pigeon family; and these feathers are
+kept expanded, and are carried so erect that in good birds the head and
+tail touch; the oil-gland is quite aborted.  Several other less distinct
+breeds might have been specified.
+</para>
+
+<para>
+In the skeletons of the several breeds, the development of the bones of the
+face in length and breadth and curvature differs enormously.  The shape, as
+well as the breadth and length of the ramus of the lower jaw, varies in a
+highly remarkable manner.  The number of the caudal and sacral vertebrae
+vary; as does the number of the ribs, together with their relative breadth
+and the presence of processes.  The size and shape of the apertures in the
+sternum are highly variable; so is the degree of divergence and relative
+size of the two arms of the furcula.  The proportional width of the gape of
+mouth, the proportional length of the eyelids, of the orifice of the
+nostrils, of the tongue (not always in strict correlation with the length
+of beak), the size of the crop and of the upper part of the oesophagus; the
+development and abortion of the oil-gland; the number of the primary wing
+and caudal feathers; the relative length of wing and tail to each other and
+to the body; the relative length of leg and of the feet; the number of
+scutellae on the toes, the development of skin between the toes, are all
+points of structure which are variable.  The period at which the perfect
+plumage is acquired varies, as does the state of the down with which the
+nestling birds are clothed when hatched.  The shape and size of the eggs
+vary.  The manner of flight differs remarkably; as does in some breeds the
+voice and disposition.  Lastly, in certain breeds, the males and females
+have come to differ to a slight degree from each other.
+</para>
+
+<para>
+Altogether at least a score of pigeons might be chosen, which if shown to
+an ornithologist, and he were told that they were wild birds, would
+certainly, I think, be ranked by him as well-defined species.  Moreover, I
+do not believe that any ornithologist would place the English carrier, the
+short-faced tumbler, the runt, the barb, pouter, and fantail in the same
+genus; more especially as in each of these breeds several truly-inherited
+sub-breeds, or species as he might have called them, could be shown him.
+</para>
+
+<para>
+Great as the differences are between the breeds of pigeons, I am fully
+convinced that the common opinion of naturalists is correct, namely, that
+all have descended from the rock-pigeon (Columba livia), including under
+this term several geographical races or sub-species, which differ from each
+other in the most trifling respects.  As several of the reasons which have
+led me to this belief are in some degree applicable in other cases, I will
+here briefly give them.  If the several breeds are not varieties, and have
+not proceeded from the rock-pigeon, they must have descended from at least
+seven or eight aboriginal stocks; for it is impossible to make the present
+domestic breeds by the crossing of any lesser number:  how, for instance,
+could a pouter be produced by crossing two breeds unless one of the
+parent-stocks possessed the characteristic enormous crop?  The supposed
+aboriginal stocks must all have been rock-pigeons, that is, not breeding or
+willingly perching on trees.  But besides C. livia, with its geographical
+sub-species, only two or three other species of rock-pigeons are known; and
+these have not any of the characters of the domestic breeds.  Hence the
+supposed aboriginal stocks must either still exist in the countries where
+they were originally domesticated, and yet be unknown to ornithologists;
+and this, considering their size, habits, and remarkable characters, seems
+very improbable; or they must have become extinct in the wild state.  But
+birds breeding on precipices, and good fliers, are unlikely to be
+exterminated; and the common rock-pigeon, which has the same habits with
+the domestic breeds, has not been exterminated even on several of the
+smaller British islets, or on the shores of the Mediterranean.  Hence the
+supposed extermination of so many species having similar habits with the
+rock-pigeon seems to me a very rash assumption.  Moreover, the several
+above-named domesticated breeds have been transported to all parts of the
+world, and, therefore, some of them must have been carried back again into
+their native country; but not one has ever become wild or feral, though the
+dovecot-pigeon, which is the rock-pigeon in a very slightly altered state,
+has become feral in several places.  Again, all recent experience shows
+that it is most difficult to get any wild animal to breed freely under
+domestication; yet on the hypothesis of the multiple origin of our pigeons,
+it must be assumed that at least seven or eight species were so thoroughly
+domesticated in ancient times by half-civilized man, as to be quite
+prolific under confinement.
+</para>
+
+<para>
+An argument, as it seems to me, of great weight, and applicable in several
+other cases, is, that the above-specified breeds, though agreeing generally
+in constitution, habits, voice, colouring, and in most parts of their
+structure, with the wild rock-pigeon, yet are certainly highly abnormal in
+other parts of their structure:  we may look in vain throughout the whole
+great family of Columbidae for a beak like that of the English carrier, or
+that of the short-faced tumbler, or barb; for reversed feathers like those
+of the jacobin; for a crop like that of the pouter; for tail-feathers like
+those of the fantail.  Hence it must be assumed not only that
+half-civilized man succeeded in thoroughly domesticating several species,
+but that he intentionally or by chance picked out extraordinarily abnormal
+species; and further, that these very species have since all become extinct
+or unknown.  So many strange contingencies seem to me improbable in the
+highest degree.
+</para>
+
+<para>
+Some facts in regard to the colouring of pigeons well deserve
+consideration.  The rock-pigeon is of a slaty-blue, and has a white rump
+(the Indian sub-species, C. intermedia of Strickland, having it bluish);
+the tail has a terminal dark bar, with the bases of the outer feathers
+externally edged with white; the wings have two black bars; some
+semi-domestic breeds and some apparently truly wild breeds have, besides
+the two black bars, the wings chequered with black.  These several marks do
+not occur together in any other species of the whole family.  Now, in every
+one of the domestic breeds, taking thoroughly well-bred birds, all the
+above marks, even to the white edging of the outer tail-feathers, sometimes
+concur perfectly developed.  Moreover, when two birds belonging to two
+distinct breeds are crossed, neither of which is blue or has any of the
+above-specified marks, the mongrel offspring are very apt suddenly to
+acquire these characters; for instance, I crossed some uniformly white
+fantails with some uniformly black barbs, and they produced mottled brown
+and black birds; these I again crossed together, and one grandchild of the
+pure white fantail and pure black barb was of as beautiful a blue colour,
+with the white rump, double black wing-bar, and barred and white-edged
+tail-feathers, as any wild rock-pigeon!  We can understand these facts, on
+the well-known principle of reversion to ancestral characters, if all the
+domestic breeds have descended from the rock-pigeon.  But if we deny this,
+we must make one of the two following highly improbable suppositions. 
+Either, firstly, that all the several imagined aboriginal stocks were
+coloured and marked like the rock-pigeon, although no other existing
+species is thus coloured and marked, so that in each separate breed there
+might be a tendency to revert to the very same colours and markings.  Or,
+secondly, that each breed, even the purest, has within a dozen or, at most,
+within a score of generations, been crossed by the rock-pigeon:  I say
+within a dozen or twenty generations, for we know of no fact countenancing
+the belief that the child ever reverts to some one ancestor, removed by a
+greater number of generations.  In a breed which has been crossed only once
+with some distinct breed, the tendency to reversion to any character
+derived from such cross will naturally become less and less, as in each
+succeeding generation there will be less of the foreign blood; but when
+there has been no cross with a distinct breed, and there is a tendency in
+both parents to revert to a character, which has been lost during some
+former generation, this tendency, for all that we can see to the contrary,
+may be transmitted undiminished for an indefinite number of generations. 
+These two distinct cases are often confounded in treatises on inheritance.
+</para>
+
+<para>
+Lastly, the hybrids or mongrels from between all the domestic breeds of
+pigeons are perfectly fertile.  I can state this from my own observations,
+purposely made on the most distinct breeds.  Now, it is difficult, perhaps
+impossible, to bring forward one case of the hybrid offspring of two
+animals clearly distinct being themselves perfectly fertile.  Some authors
+believe that long-continued domestication eliminates this strong tendency
+to sterility:  from the history of the dog I think there is some
+probability in this hypothesis, if applied to species closely related
+together, though it is unsupported by a single experiment.  But to extend
+the hypothesis so far as to suppose that species, aboriginally as distinct
+as carriers, tumblers, pouters, and fantails now are, should yield
+offspring perfectly fertile, inter se, seems to me rash in the extreme.
+</para>
+
+<para>
+From these several reasons, namely, the improbability of man having
+formerly got seven or eight supposed species of pigeons to breed freely
+under domestication; these supposed species being quite unknown in a wild
+state, and their becoming nowhere feral; these species having very abnormal
+characters in certain respects, as compared with all other Columbidae,
+though so like in most other respects to the rock-pigeon; the blue colour
+and various marks occasionally appearing in all the breeds, both when kept
+pure and when crossed; the mongrel offspring being perfectly fertile;--from
+these several reasons, taken together, I can feel no doubt that all our
+domestic breeds have descended from the Columba livia with its geographical
+sub-species.
+</para>
+
+<para>
+In favour of this view, I may add, firstly, that C. livia, or the
+rock-pigeon, has been found capable of domestication in Europe and in
+India; and that it agrees in habits and in a great number of points of
+structure with all the domestic breeds.  Secondly, although an English
+carrier or short-faced tumbler differs immensely in certain characters from
+the rock-pigeon, yet by comparing the several sub-breeds of these breeds,
+more especially those brought from distant countries, we can make an almost
+perfect series between the extremes of structure.  Thirdly, those
+characters which are mainly distinctive of each breed, for instance the
+wattle and length of beak of the carrier, the shortness of that of the
+tumbler, and the number of tail-feathers in the fantail, are in each breed
+eminently variable; and the explanation of this fact will be obvious when
+we come to treat of selection.  Fourthly, pigeons have been watched, and
+tended with the utmost care, and loved by many people.  They have been
+domesticated for thousands of years in several quarters of the world; the
+earliest known record of pigeons is in the fifth Aegyptian dynasty, about
+3000 B.C., as was pointed out to me by Professor Lepsius; but Mr. Birch
+informs me that pigeons are given in a bill of fare in the previous
+dynasty.  In the time of the Romans, as we hear from Pliny, immense prices
+were given for pigeons; 'nay, they are come to this pass, that they can
+reckon up their pedigree and race.'  Pigeons were much valued by Akber Khan
+in India, about the year 1600; never less than 20,000 pigeons were taken
+with the court.  'The monarchs of Iran and Turan sent him some very rare
+birds;' and, continues the courtly historian, 'His Majesty by crossing the
+breeds, which method was never practised before, has improved them
+astonishingly.'  About this same period the Dutch were as eager about
+pigeons as were the old Romans.  The paramount importance of these
+considerations in explaining the immense amount of variation which pigeons
+have undergone, will be obvious when we treat of Selection.  We shall then,
+also, see how it is that the breeds so often have a somewhat monstrous
+character.  It is also a most favourable circumstance for the production of
+distinct breeds, that male and female pigeons can be easily mated for life;
+and thus different breeds can be kept together in the same aviary.
+</para>
+
+<para>
+I have discussed the probable origin of domestic pigeons at some, yet quite
+insufficient, length; because when I first kept pigeons and watched the
+several kinds, knowing well how true they bred, I felt fully as much
+difficulty in believing that they could ever have descended from a common
+parent, as any naturalist could in coming to a similar conclusion in regard
+to the many species of finches, or other large groups of birds, in nature. 
+One circumstance has struck me much; namely, that all the breeders of the
+various domestic animals and the cultivators of plants, with whom I have
+ever conversed, or whose treatises I have read, are firmly convinced that
+the several breeds to which each has attended, are descended from so many
+aboriginally distinct species.  Ask, as I have asked, a celebrated raiser
+of Hereford cattle, whether his cattle might not have descended from long
+horns, and he will laugh you to scorn.  I have never met a pigeon, or
+poultry, or duck, or rabbit fancier, who was not fully convinced that each
+main breed was descended from a distinct species.  Van Mons, in his
+treatise on pears and apples, shows how utterly he disbelieves that the
+several sorts, for instance a Ribston-pippin or Codlin-apple, could ever
+have proceeded from the seeds of the same tree.  Innumerable other examples
+could be given.  The explanation, I think, is simple:  from long-continued
+study they are strongly impressed with the differences between the several
+races; and though they well know that each race varies slightly, for they
+win their prizes by selecting such slight differences, yet they ignore all
+general arguments, and refuse to sum up in their minds slight differences
+accumulated during many successive generations.  May not those naturalists
+who, knowing far less of the laws of inheritance than does the breeder, and
+knowing no more than he does of the intermediate links in the long lines of
+descent, yet admit that many of our domestic races have descended from the
+same parents--may they not learn a lesson of caution, when they deride the
+idea of species in a state of nature being lineal descendants of other
+species?
+</para>
+
+<para>
+
+Selection. -- Let us now briefly consider the steps by which domestic races
+have been produced, either from one or from several allied species.  Some
+little effect may, perhaps, be attributed to the direct action of the
+external conditions of life, and some little to habit; but he would be a
+bold man who would account by such agencies for the differences of a dray
+and race horse, a greyhound and bloodhound, a carrier and tumbler pigeon. 
+One of the most remarkable features in our domesticated races is that we
+see in them adaptation, not indeed to the animal's or plant's own good, but
+to man's use or fancy.  Some variations useful to him have probably arisen
+suddenly, or by one step; many botanists, for instance, believe that the
+fuller's teazle, with its hooks, which cannot be rivalled by any mechanical
+contrivance, is only a variety of the wild Dipsacus; and this amount of
+change may have suddenly arisen in a seedling.  So it has probably been
+with the turnspit dog; and this is known to have been the case with the
+ancon sheep.  But when we compare the dray-horse and race-horse, the
+dromedary and camel, the various breeds of sheep fitted either for
+cultivated land or mountain pasture, with the wool of one breed good for
+one purpose, and that of another breed for another purpose; when we compare
+the many breeds of dogs, each good for man in very different ways; when we
+compare the game-cock, so pertinacious in battle, with other breeds so
+little quarrelsome, with 'everlasting layers' which never desire to sit,
+and with the bantam so small and elegant; when we compare the host of
+agricultural, culinary, orchard, and flower-garden races of plants, most
+useful to man at different seasons and for different purposes, or so
+beautiful in his eyes, we must, I think, look further than to mere
+variability.  We cannot suppose that all the breeds were suddenly produced
+as perfect and as useful as we now see them; indeed, in several cases, we
+know that this has not been their history.  The key is man's power of
+accumulative selection:  nature gives successive variations; man adds them
+up in certain directions useful to him.  In this sense he may be said to
+make for himself useful breeds.
+</para>
+
+<para>
+The great power of this principle of selection is not hypothetical.  It is
+certain that several of our eminent breeders have, even within a single
+lifetime, modified to a large extent some breeds of cattle and sheep.  In
+order fully to realise what they have done, it is almost necessary to read
+several of the many treatises devoted to this subject, and to inspect the
+animals.  Breeders habitually speak of an animal's organisation as
+something quite plastic, which they can model almost as they please.  If I
+had space I could quote numerous passages to this effect from highly
+competent authorities.  Youatt, who was probably better acquainted with the
+works of agriculturalists than almost any other individual, and who was
+himself a very good judge of an animal, speaks of the principle of
+selection as 'that which enables the agriculturist, not only to modify the
+character of his flock, but to change it altogether.  It is the magician's
+wand, by means of which he may summon into life whatever form and mould he
+pleases.'  Lord Somerville, speaking of what breeders have done for sheep,
+says:- 'It would seem as if they had chalked out upon a wall a form perfect
+in itself, and then had given it existence.'  That most skilful breeder,
+Sir John Sebright, used to say, with respect to pigeons, that 'he would
+produce any given feather in three years, but it would take him six years
+to obtain head and beak.'  In Saxony the importance of the principle of
+selection in regard to merino sheep is so fully recognised, that men follow
+it as a trade:  the sheep are placed on a table and are studied, like a
+picture by a connoisseur; this is done three times at intervals of months,
+and the sheep are each time marked and classed, so that the very best may
+ultimately be selected for breeding.
+</para>
+
+<para>
+What English breeders have actually effected is proved by the enormous
+prices given for animals with a good pedigree; and these have now been
+exported to almost every quarter of the world.  The improvement is by no
+means generally due to crossing different breeds; all the best breeders are
+strongly opposed to this practice, except sometimes amongst closely allied
+sub-breeds.  And when a cross has been made, the closest selection is far
+more indispensable even than in ordinary cases.  If selection consisted
+merely in separating some very distinct variety, and breeding from it, the
+principle would be so obvious as hardly to be worth notice; but its
+importance consists in the great effect produced by the accumulation in one
+direction, during successive generations, of differences absolutely
+inappreciable by an uneducated eye--differences which I for one have vainly
+attempted to appreciate.  Not one man in a thousand has accuracy of eye and
+judgment sufficient to become an eminent breeder.  If gifted with these
+qualities, and he studies his subject for years, and devotes his lifetime
+to it with indomitable perseverance, he will succeed, and may make great
+improvements; if he wants any of these qualities, he will assuredly fail. 
+Few would readily believe in the natural capacity and years of practice
+requisite to become even a skilful pigeon-fancier.
+</para>
+
+<para>
+The same principles are followed by horticulturists; but the variations are
+here often more abrupt.  No one supposes that our choicest productions have
+been produced by a single variation from the aboriginal stock.  We have
+proofs that this is not so in some cases, in which exact records have been
+kept; thus, to give a very trifling instance, the steadily-increasing size
+of the common gooseberry may be quoted.  We see an astonishing improvement
+in many florists' flowers, when the flowers of the present day are compared
+with drawings made only twenty or thirty years ago.  When a race of plants
+is once pretty well established, the seed-raisers do not pick out the best
+plants, but merely go over their seed-beds, and pull up the 'rogues,' as
+they call the plants that deviate from the proper standard.  With animals
+this kind of selection is, in fact, also followed; for hardly any one is so
+careless as to allow his worst animals to breed.
+</para>
+
+<para>
+In regard to plants, there is another means of observing the accumulated
+effects of selection--namely, by comparing the diversity of flowers in the
+different varieties of the same species in the flower-garden; the diversity
+of leaves, pods, or tubers, or whatever part is valued, in the
+kitchen-garden, in comparison with the flowers of the same varieties; and
+the diversity of fruit of the same species in the orchard, in comparison
+with the leaves and flowers of the same set of varieties.  See how
+different the leaves of the cabbage are, and how extremely alike the
+flowers; how unlike the flowers of the heartsease are, and how alike the
+leaves; how much the fruit of the different kinds of gooseberries differ in
+size, colour, shape, and hairiness, and yet the flowers present very slight
+differences.  It is not that the varieties which differ largely in some one
+point do not differ at all in other points; this is hardly ever, perhaps
+never, the case.  The laws of correlation of growth, the importance of
+which should never be overlooked, will ensure some differences; but, as a
+general rule, I cannot doubt that the continued selection of slight
+variations, either in the leaves, the flowers, or the fruit, will produce
+races differing from each other chiefly in these characters.
+</para>
+
+<para>
+It may be objected that the principle of selection has been reduced to
+methodical practice for scarcely more than three-quarters of a century; it
+has certainly been more attended to of late years, and many treatises have
+been published on the subject; and the result, I may add, has been, in a
+corresponding degree, rapid and important.  But it is very far from true
+that the principle is a modern discovery.  I could give several references
+to the full acknowledgment of the importance of the principle in works of
+high antiquity.  In rude and barbarous periods of English history choice
+animals were often imported, and laws were passed to prevent their
+exportation:  the destruction of horses under a certain size was ordered,
+and this may be compared to the 'roguing' of plants by nurserymen.  The
+principle of selection I find distinctly given in an ancient Chinese
+encyclopaedia.  Explicit rules are laid down by some of the Roman classical
+writers.  From passages in Genesis, it is clear that the colour of domestic
+animals was at that early period attended to.  Savages now sometimes cross
+their dogs with wild canine animals, to improve the breed, and they
+formerly did so, as is attested by passages in Pliny.  The savages in South
+Africa match their draught cattle by colour, as do some of the Esquimaux
+their teams of dogs.  Livingstone shows how much good domestic breeds are
+valued by the negroes of the interior of Africa who have not associated
+with Europeans.  Some of these facts do not show actual selection, but they
+show that the breeding of domestic animals was carefully attended to in
+ancient times, and is now attended to by the lowest savages.  It would,
+indeed, have been a strange fact, had attention not been paid to breeding,
+for the inheritance of good and bad qualities is so obvious.
+</para>
+
+<para>
+At the present time, eminent breeders try by methodical selection, with a
+distinct object in view, to make a new strain or sub-breed, superior to
+anything existing in the country.  But, for our purpose, a kind of
+Selection, which may be called Unconscious, and which results from every
+one trying to possess and breed from the best individual animals, is more
+important.  Thus, a man who intends keeping pointers naturally tries to get
+as good dogs as he can, and afterwards breeds from his own best dogs, but
+he has no wish or expectation of permanently altering the breed. 
+Nevertheless I cannot doubt that this process, continued during centuries,
+would improve and modify any breed, in the same way as Bakewell, Collins,
+&amp;c., by this very same process, only carried on more methodically, did
+greatly modify, even during their own lifetimes, the forms and qualities of
+their cattle.  Slow and insensible changes of this kind could never be
+recognised unless actual measurements or careful drawings of the breeds in
+question had been made long ago, which might serve for comparison.  In some
+cases, however, unchanged or but little changed individuals of the same
+breed may be found in less civilised districts, where the breed has been
+less improved.  There is reason to believe that King Charles's spaniel has
+been unconsciously modified to a large extent since the time of that
+monarch.  Some highly competent authorities are convinced that the setter
+is directly derived from the spaniel, and has probably been slowly altered
+from it.  It is known that the English pointer has been greatly changed
+within the last century, and in this case the change has, it is believed,
+been chiefly effected by crosses with the fox-hound; but what concerns us
+is, that the change has been effected unconsciously and gradually, and yet
+so effectually, that, though the old Spanish pointer certainly came from
+Spain, Mr. Borrow has not seen, as I am informed by him, any native dog in
+Spain like our pointer.
+</para>
+
+<para>
+By a similar process of selection, and by careful training, the whole body
+of English racehorses have come to surpass in fleetness and size the parent
+Arab stock, so that the latter, by the regulations for the Goodwood Races,
+are favoured in the weights they carry.  Lord Spencer and others have shown
+how the cattle of England have increased in weight and in early maturity,
+compared with the stock formerly kept in this country.  By comparing the
+accounts given in old pigeon treatises of carriers and tumblers with these
+breeds as now existing in Britain, India, and Persia, we can, I think,
+clearly trace the stages through which they have insensibly passed, and
+come to differ so greatly from the rock-pigeon.
+</para>
+
+<para>
+Youatt gives an excellent illustration of the effects of a course of
+selection, which may be considered as unconsciously followed, in so far
+that the breeders could never have expected or even have wished to have
+produced the result which ensued--namely, the production of two distinct
+strains.  The two flocks of Leicester sheep kept by Mr. Buckley and Mr.
+Burgess, as Mr. Youatt remarks, 'have been purely bred from the original
+stock of Mr. Bakewell for upwards of fifty years.  There is not a suspicion
+existing in the mind of any one at all acquainted with the subject that the
+owner of either of them has deviated in any one instance from the pure
+blood of Mr. Bakewell's flock, and yet the difference between the sheep
+possessed by these two gentlemen is so great that they have the appearance
+of being quite different varieties.'
+</para>
+
+<para>
+If there exist savages so barbarous as never to think of the inherited
+character of the offspring of their domestic animals, yet any one animal
+particularly useful to them, for any special purpose, would be carefully
+preserved during famines and other accidents, to which savages are so
+liable, and such choice animals would thus generally leave more offspring
+than the inferior ones; so that in this case there would be a kind of
+unconscious selection going on.  We see the value set on animals even by
+the barbarians of Tierra del Fuego, by their killing and devouring their
+old women, in times of dearth, as of less value than their dogs.
+</para>
+
+<para>
+In plants the same gradual process of improvement, through the occasional
+preservation of the best individuals, whether or not sufficiently distinct
+to be ranked at their first appearance as distinct varieties, and whether
+or not two or more species or races have become blended together by
+crossing, may plainly be recognised in the increased size and beauty which
+we now see in the varieties of the heartsease, rose, pelargonium, dahlia,
+and other plants, when compared with the older varieties or with their
+parent-stocks.  No one would ever expect to get a first-rate heartsease or
+dahlia from the seed of a wild plant.  No one would expect to raise a
+first-rate melting pear from the seed of a wild pear, though he might
+succeed from a poor seedling growing wild, if it had come from a
+garden-stock.  The pear, though cultivated in classical times, appears,
+from Pliny's description, to have been a fruit of very inferior quality.  I
+have seen great surprise expressed in horticultural works at the wonderful
+skill of gardeners, in having produced such splendid results from such poor
+materials; but the art, I cannot doubt, has been simple, and, as far as the
+final result is concerned, has been followed almost unconsciously.  It has
+consisted in always cultivating the best known variety, sowing its seeds,
+and, when a slightly better variety has chanced to appear, selecting it,
+and so onwards.  But the gardeners of the classical period, who cultivated
+the best pear they could procure, never thought what splendid fruit we
+should eat; though we owe our excellent fruit, in some small degree, to
+their having naturally chosen and preserved the best varieties they could
+anywhere find.
+</para>
+
+<para>
+A large amount of change in our cultivated plants, thus slowly and
+unconsciously accumulated, explains, as I believe, the well-known fact,
+that in a vast number of cases we cannot recognise, and therefore do not
+know, the wild parent-stocks of the plants which have been longest
+cultivated in our flower and kitchen gardens.  If it has taken centuries or
+thousands of years to improve or modify most of our plants up to their
+present standard of usefulness to man, we can understand how it is that
+neither Australia, the Cape of Good Hope, nor any other region inhabited by
+quite uncivilised man, has afforded us a single plant worth culture.  It is
+not that these countries, so rich in species, do not by a strange chance
+possess the aboriginal stocks of any useful plants, but that the native
+plants have not been improved by continued selection up to a standard of
+perfection comparable with that given to the plants in countries anciently
+civilised.
+</para>
+
+<para>
+In regard to the domestic animals kept by uncivilised man, it should not be
+overlooked that they almost always have to struggle for their own food, at
+least during certain seasons.  And in two countries very differently
+circumstanced, individuals of the same species, having slightly different
+constitutions or structure, would often succeed better in the one country
+than in the other, and thus by a process of 'natural selection,' as will
+hereafter be more fully explained, two sub-breeds might be formed.  This,
+perhaps, partly explains what has been remarked by some authors, namely,
+that the varieties kept by savages have more of the character of species
+than the varieties kept in civilised countries.
+</para>
+
+<para>
+On the view here given of the all-important part which selection by man has
+played, it becomes at once obvious, how it is that our domestic races show
+adaptation in their structure or in their habits to man's wants or fancies. 
+We can, I think, further understand the frequently abnormal character of
+our domestic races, and likewise their differences being so great in
+external characters and relatively so slight in internal parts or organs. 
+Man can hardly select, or only with much difficulty, any deviation of
+structure excepting such as is externally visible; and indeed he rarely
+cares for what is internal.  He can never act by selection, excepting on
+variations which are first given to him in some slight degree by nature. 
+No man would ever try to make a fantail, till he saw a pigeon with a tail
+developed in some slight degree in an unusual manner, or a pouter till he
+saw a pigeon with a crop of somewhat unusual size; and the more abnormal or
+unusual any character was when it first appeared, the more likely it would
+be to catch his attention.  But to use such an expression as trying to make
+a fantail, is, I have no doubt, in most cases, utterly incorrect.  The man
+who first selected a pigeon with a slightly larger tail, never dreamed what
+the descendants of that pigeon would become through long-continued, partly
+unconscious and partly methodical selection.  Perhaps the parent bird of
+all fantails had only fourteen tail-feathers somewhat expanded, like the
+present Java fantail, or like individuals of other and distinct breeds, in
+which as many as seventeen tail-feathers have been counted.  Perhaps the
+first pouter-pigeon did not inflate its crop much more than the turbit now
+does the upper part of its oesophagus,--a habit which is disregarded by all
+fanciers, as it is not one of the points of the breed.
+</para>
+
+<para>
+Nor let it be thought that some great deviation of structure would be
+necessary to catch the fancier's eye:  he perceives extremely small
+differences, and it is in human nature to value any novelty, however
+slight, in one's own possession.  Nor must the value which would formerly
+be set on any slight differences in the individuals of the same species, be
+judged of by the value which would now be set on them, after several breeds
+have once fairly been established.  Many slight differences might, and
+indeed do now, arise amongst pigeons, which are rejected as faults or
+deviations from the standard of perfection of each breed.  The common goose
+has not given rise to any marked varieties; hence the Thoulouse and the
+common breed, which differ only in colour, that most fleeting of
+characters, have lately been exhibited as distinct at our poultry-shows.
+</para>
+
+<para>
+I think these views further explain what has sometimes been noticed--namely
+that we know nothing about the origin or history of any of our domestic
+breeds.  But, in fact, a breed, like a dialect of a language, can hardly be
+said to have had a definite origin.  A man preserves and breeds from an
+individual with some slight deviation of structure, or takes more care than
+usual in matching his best animals and thus improves them, and the improved
+individuals slowly spread in the immediate neighbourhood.  But as yet they
+will hardly have a distinct name, and from being only slightly valued,
+their history will be disregarded.  When further improved by the same slow
+and gradual process, they will spread more widely, and will get recognised
+as something distinct and valuable, and will then probably first receive a
+provincial name.  In semi-civilised countries, with little free
+communication, the spreading and knowledge of any new sub-breed will be a
+slow process.  As soon as the points of value of the new sub-breed are once
+fully acknowledged, the principle, as I have called it, of unconscious
+selection will always tend,--perhaps more at one period than at another, as
+the breed rises or falls in fashion,--perhaps more in one district than in
+another, according to the state of civilisation of the inhabitants--slowly
+to add to the characteristic features of the breed, whatever they may be. 
+But the chance will be infinitely small of any record having been preserved
+of such slow, varying, and insensible changes.
+</para>
+
+<para>
+I must now say a few words on the circumstances, favourable, or the
+reverse, to man's power of selection.  A high degree of variability is
+obviously favourable, as freely giving the materials for selection to work
+on; not that mere individual differences are not amply sufficient, with
+extreme care, to allow of the accumulation of a large amount of
+modification in almost any desired direction.  But as variations manifestly
+useful or pleasing to man appear only occasionally, the chance of their
+appearance will be much increased by a large number of individuals being
+kept; and hence this comes to be of the highest importance to success.  On
+this principle Marshall has remarked, with respect to the sheep of parts of
+Yorkshire, that 'as they generally belong to poor people, and are mostly in
+small lots, they never can be improved.'  On the other hand, nurserymen,
+from raising large stocks of the same plants, are generally far more
+successful than amateurs in getting new and valuable varieties.  The
+keeping of a large number of individuals of a species in any country
+requires that the species should be placed under favourable conditions of
+life, so as to breed freely in that country.  When the individuals of any
+species are scanty, all the individuals, whatever their quality may be,
+will generally be allowed to breed, and this will effectually prevent
+selection.  But probably the most important point of all, is, that the
+animal or plant should be so highly useful to man, or so much valued by
+him, that the closest attention should be paid to even the slightest
+deviation in the qualities or structure of each individual.  Unless such
+attention be paid nothing can be effected.  I have seen it gravely
+remarked, that it was most fortunate that the strawberry began to vary just
+when gardeners began to attend closely to this plant.  No doubt the
+strawberry had always varied since it was cultivated, but the slight
+varieties had been neglected.  As soon, however, as gardeners picked out
+individual plants with slightly larger, earlier, or better fruit, and
+raised seedlings from them, and again picked out the best seedlings and
+bred from them, then, there appeared (aided by some crossing with distinct
+species) those many admirable varieties of the strawberry which have been
+raised during the last thirty or forty years.
+</para>
+
+<para>
+In the case of animals with separate sexes, facility in preventing crosses
+is an important element of success in the formation of new races,--at
+least, in a country which is already stocked with other races.  In this
+respect enclosure of the land plays a part.  Wandering savages or the
+inhabitants of open plains rarely possess more than one breed of the same
+species.  Pigeons can be mated for life, and this is a great convenience to
+the fancier, for thus many races may be kept true, though mingled in the
+same aviary; and this circumstance must have largely favoured the
+improvement and formation of new breeds.  Pigeons, I may add, can be
+propagated in great numbers and at a very quick rate, and inferior birds
+may be freely rejected, as when killed they serve for food.  On the other
+hand, cats, from their nocturnal rambling habits, cannot be matched, and,
+although so much valued by women and children, we hardly ever see a
+distinct breed kept up; such breeds as we do sometimes see are almost
+always imported from some other country, often from islands.  Although I do
+not doubt that some domestic animals vary less than others, yet the rarity
+or absence of distinct breeds of the cat, the donkey, peacock, goose, &amp;c.,
+may be attributed in main part to selection not having been brought into
+play:  in cats, from the difficulty in pairing them; in donkeys, from only
+a few being kept by poor people, and little attention paid to their
+breeding; in peacocks, from not being very easily reared and a large stock
+not kept; in geese, from being valuable only for two purposes, food and
+feathers, and more especially from no pleasure having been felt in the
+display of distinct breeds.
+</para>
+
+<para>
+To sum up on the origin of our Domestic Races of animals and plants.  I
+believe that the conditions of life, from their action on the reproductive
+system, are so far of the highest importance as causing variability.  I do
+not believe that variability is an inherent and necessary contingency,
+under all circumstances, with all organic beings, as some authors have
+thought.  The effects of variability are modified by various degrees of
+inheritance and of reversion.  Variability is governed by many unknown
+laws, more especially by that of correlation of growth.  Something may be
+attributed to the direct action of the conditions of life.  Something must
+be attributed to use and disuse.  The final result is thus rendered
+infinitely complex.  In some cases, I do not doubt that the intercrossing
+of species, aboriginally distinct, has played an important part in the
+origin of our domestic productions.  When in any country several domestic
+breeds have once been established, their occasional intercrossing, with the
+aid of selection, has, no doubt, largely aided in the formation of new
+sub-breeds; but the importance of the crossing of varieties has, I believe,
+been greatly exaggerated, both in regard to animals and to those plants
+which are propagated by seed.  In plants which are temporarily propagated
+by cuttings, buds, &amp;c., the importance of the crossing both of distinct
+species and of varieties is immense; for the cultivator here quite
+disregards the extreme variability both of hybrids and mongrels, and the
+frequent sterility of hybrids; but the cases of plants not propagated by
+seed are of little importance to us, for their endurance is only temporary. 
+Over all these causes of Change I am convinced that the accumulative action
+of Selection, whether applied methodically and more quickly, or
+unconsciously and more slowly, but more efficiently, is by far the
+predominant Power.
+</para>
+
+</chapter>
+
+<chapter>
+<chapheader>
+
+<chapnum>Chapter II</chapnum>
+
+<title>Variation Under Nature</title>
+
+<chapsummary>
+Variability -- Individual differences -- Doubtful species -- Wide ranging,
+much diffused, and common species vary most -- Species of the larger genera
+in any country vary more than the species of the smaller genera -- Many of
+the species of the larger genera resemble varieties in being very closely,
+but unequally, related to each other, and in having restricted ranges.
+</chapsummary>
+</chapheader>
+
+<para>
+Before applying the principles arrived at in the last chapter to organic
+beings in a state of nature, we must briefly discuss whether these latter
+are subject to any variation.  To treat this subject at all properly, a
+long catalogue of dry facts should be given; but these I shall reserve for
+my future work.  Nor shall I here discuss the various definitions which
+have been given of the term species.  No one definition has as yet
+satisfied all naturalists; yet every naturalist knows vaguely what he means
+when he speaks of a species.  Generally the term includes the unknown
+element of a distinct act of creation.  The term 'variety' is almost
+equally difficult to define; but here community of descent is almost
+universally implied, though it can rarely be proved.  We have also what are
+called monstrosities; but they graduate into varieties.  By a monstrosity I
+presume is meant some considerable deviation of structure in one part,
+either injurious to or not useful to the species, and not generally
+propagated.  Some authors use the term 'variation' in a technical sense, as
+implying a modification directly due to the physical conditions of life;
+and 'variations' in this sense are supposed not to be inherited:  but who
+can say that the dwarfed condition of shells in the brackish waters of the
+Baltic, or dwarfed plants on Alpine summits, or the thicker fur of an
+animal from far northwards, would not in some cases be inherited for at
+least some few generations? and in this case I presume that the form would
+be called a variety.
+</para>
+
+<para>
+Again, we have many slight differences which may be called individual
+differences, such as are known frequently to appear in the offspring from
+the same parents, or which may be presumed to have thus arisen, from being
+frequently observed in the individuals of the same species inhabiting the
+same confined locality.  No one supposes that all the individuals of the
+same species are cast in the very same mould.  These individual differences
+are highly important for us, as they afford materials for natural selection
+to accumulate, in the same manner as man can accumulate in any given
+direction individual differences in his domesticated productions.  These
+individual differences generally affect what naturalists consider
+unimportant parts; but I could show by a long catalogue of facts, that
+parts which must be called important, whether viewed under a physiological
+or classificatory point of view, sometimes vary in the individuals of the
+same species.  I am convinced that the most experienced naturalist would be
+surprised at the number of the cases of variability, even in important
+parts of structure, which he could collect on good authority, as I have
+collected, during a course of years.  It should be remembered that
+systematists are far from pleased at finding variability in important
+characters, and that there are not many men who will laboriously examine
+internal and important organs, and compare them in many specimens of the
+same species.  I should never have expected that the branching of the main
+nerves close to the great central ganglion of an insect would have been
+variable in the same species; I should have expected that changes of this
+nature could have been effected only by slow degrees:  yet quite recently
+Mr. Lubbock has shown a degree of variability in these main nerves in
+Coccus, which may almost be compared to the irregular branching of the stem
+of a tree.  This philosophical naturalist, I may add, has also quite
+recently shown that the muscles in the larvae of certain insects are very
+far from uniform.  Authors sometimes argue in a circle when they state that
+important organs never vary; for these same authors practically rank that
+character as important (as some few naturalists have honestly confessed)
+which does not vary; and, under this point of view, no instance of any
+important part varying will ever be found:  but under any other point of
+view many instances assuredly can be given.
+</para>
+
+<para>
+There is one point connected with individual differences, which seems to me
+extremely perplexing:  I refer to those genera which have sometimes been
+called 'protean' or 'polymorphic,' in which the species present an
+inordinate amount of variation; and hardly two naturalists can agree which
+forms to rank as species and which as varieties.  We may instance Rubus,
+Rosa, and Hieracium amongst plants, several genera of insects, and several
+genera of Brachiopod shells.  In most polymorphic genera some of the
+species have fixed and definite characters.  Genera which are polymorphic
+in one country seem to be, with some few exceptions, polymorphic in other
+countries, and likewise, judging from Brachiopod shells, at former periods
+of time.  These facts seem to be very perplexing, for they seem to show
+that this kind of variability is independent of the conditions of life.  I
+am inclined to suspect that we see in these polymorphic genera variations
+in points of structure which are of no service or disservice to the
+species, and which consequently have not been seized on and rendered
+definite by natural selection, as hereafter will be explained.
+</para>
+
+<para>
+Those forms which possess in some considerable degree the character of
+species, but which are so closely similar to some other forms, or are so
+closely linked to them by intermediate gradations, that naturalists do not
+like to rank them as distinct species, are in several respects the most
+important for us.  We have every reason to believe that many of these
+doubtful and closely-allied forms have permanently retained their
+characters in their own country for a long time; for as long, as far as we
+know, as have good and true species.  Practically, when a naturalist can
+unite two forms together by others having intermediate characters, he
+treats the one as a variety of the other, ranking the most common, but
+sometimes the one first described, as the species, and the other as the
+variety.  But cases of great difficulty, which I will not here enumerate,
+sometimes occur in deciding whether or not to rank one form as a variety of
+another, even when they are closely connected by intermediate links; nor
+will the commonly-assumed hybrid nature of the intermediate links always
+remove the difficulty.  In very many cases, however, one form is ranked as
+a variety of another, not because the intermediate links have actually been
+found, but because analogy leads the observer to suppose either that they
+do now somewhere exist, or may formerly have existed; and here a wide door
+for the entry of doubt and conjecture is opened.
+</para>
+
+<para>
+Hence, in determining whether a form should be ranked as a species or a
+variety, the opinion of naturalists having sound judgment and wide
+experience seems the only guide to follow.  We must, however, in many
+cases, decide by a majority of naturalists, for few well-marked and
+well-known varieties can be named which have not been ranked as species by
+at least some competent judges.
+</para>
+
+<para>
+That varieties of this doubtful nature are far from uncommon cannot be
+disputed.  Compare the several floras of Great Britain, of France or of the
+United States, drawn up by different botanists, and see what a surprising
+number of forms have been ranked by one botanist as good species, and by
+another as mere varieties.  Mr. H. C. Watson, to whom I lie under deep
+obligation for assistance of all kinds, has marked for me 182 British
+plants, which are generally considered as varieties, but which have all
+been ranked by botanists as species; and in making this list he has omitted
+many trifling varieties, but which nevertheless have been ranked by some
+botanists as species, and he has entirely omitted several highly
+polymorphic genera.  Under genera, including the most polymorphic forms,
+Mr. Babington gives 251 species, whereas Mr. Bentham gives only 112,--a
+difference of 139 doubtful forms!  Amongst animals which unite for each
+birth, and which are highly locomotive, doubtful forms, ranked by one
+zoologist as a species and by another as a variety, can rarely be found
+within the same country, but are common in separated areas.  How many of
+those birds and insects in North America and Europe, which differ very
+slightly from each other, have been ranked by one eminent naturalist as
+undoubted species, and by another as varieties, or, as they are often
+called, as geographical races!  Many years ago, when comparing, and seeing
+others compare, the birds from the separate islands of the Galapagos
+Archipelago, both one with another, and with those from the American
+mainland, I was much struck how entirely vague and arbitrary is the
+distinction between species and varieties.  On the islets of the little
+Madeira group there are many insects which are characterized as varieties
+in Mr. Wollaston's admirable work, but which it cannot be doubted would be
+ranked as distinct species by many entomologists.  Even Ireland has a few
+animals, now generally regarded as varieties, but which have been ranked as
+species by some zoologists.  Several most experienced ornithologists
+consider our British red grouse as only a strongly-marked race of a
+Norwegian species, whereas the greater number rank it as an undoubted
+species peculiar to Great Britain.  A wide distance between the homes of
+two doubtful forms leads many naturalists to rank both as distinct species;
+but what distance, it has been well asked, will suffice? if that between
+America and Europe is ample, will that between the Continent and the
+Azores, or Madeira, or the Canaries, or Ireland, be sufficient?  It must be
+admitted that many forms, considered by highly-competent judges as
+varieties, have so perfectly the character of species that they are ranked
+by other highly-competent judges as good and true species.  But to discuss
+whether they are rightly called species or varieties, before any definition
+of these terms has been generally accepted, is vainly to beat the air.
+</para>
+
+<para>
+Many of the cases of strongly-marked varieties or doubtful species well
+deserve consideration; for several interesting lines of argument, from
+geographical distribution, analogical variation, hybridism, &amp;c., have been
+brought to bear on the attempt to determine their rank.  I will here give
+only a single instance,--the well-known one of the primrose and cowslip, or
+Primula veris and elatior.  These plants differ considerably in appearance;
+they have a different flavour and emit a different odour; they flower at
+slightly different periods; they grow in somewhat different stations; they
+ascend mountains to different heights; they have different geographical
+ranges; and lastly, according to very numerous experiments made during
+several years by that most careful observer Gartner, they can be crossed
+only with much difficulty.  We could hardly wish for better evidence of the
+two forms being specifically distinct.  On the other hand, they are united
+by many intermediate links, and it is very doubtful whether these links are
+hybrids; and there is, as it seems to me, an overwhelming amount of
+experimental evidence, showing that they descend from common parents, and
+consequently must be ranked as varieties.
+</para>
+
+<para>
+Close investigation, in most cases, will bring naturalists to an agreement
+how to rank doubtful forms.  Yet it must be confessed, that it is in the
+best-known countries that we find the greatest number of forms of doubtful
+value.  I have been struck with the fact, that if any animal or plant in a
+state of nature be highly useful to man, or from any cause closely attract
+his attention, varieties of it will almost universally be found recorded. 
+These varieties, moreover, will be often ranked by some authors as species. 
+Look at the common oak, how closely it has been studied; yet a German
+author makes more than a dozen species out of forms, which are very
+generally considered as varieties; and in this country the highest
+botanical authorities and practical men can be quoted to show that the
+sessile and pedunculated oaks are either good and distinct species or mere
+varieties.
+</para>
+
+<para>
+When a young naturalist commences the study of a group of organisms quite
+unknown to him, he is at first much perplexed to determine what differences
+to consider as specific, and what as varieties; for he knows nothing of the
+amount and kind of variation to which the group is subject; and this shows,
+at least, how very generally there is some variation.  But if he confine
+his attention to one class within one country, he will soon make up his
+mind how to rank most of the doubtful forms.  His general tendency will be
+to make many species, for he will become impressed, just like the pigeon or
+poultry-fancier before alluded to, with the amount of difference in the
+forms which he is continually studying; and he has little general knowledge
+of analogical variation in other groups and in other countries, by which to
+correct his first impressions.  As he extends the range of his
+observations, he will meet with more cases of difficulty; for he will
+encounter a greater number of closely-allied forms.  But if his
+observations be widely extended, he will in the end generally be enabled to
+make up his own mind which to call varieties and which species; but he will
+succeed in this at the expense of admitting much variation,--and the truth
+of this admission will often be disputed by other naturalists.  When,
+moreover, he comes to study allied forms brought from countries not now
+continuous, in which case he can hardly hope to find the intermediate links
+between his doubtful forms, he will have to trust almost entirely to
+analogy, and his difficulties will rise to a climax.
+</para>
+
+<para>
+Certainly no clear line of demarcation has as yet been drawn between
+species and sub-species--that is, the forms which in the opinion of some
+naturalists come very near to, but do not quite arrive at the rank of
+species; or, again, between sub-species and well-marked varieties, or
+between lesser varieties and individual differences.  These differences
+blend into each other in an insensible series; and a series impresses the
+mind with the idea of an actual passage.
+</para>
+
+<para>
+Hence I look at individual differences, though of small interest to the
+systematist, as of high importance for us, as being the first step towards
+such slight varieties as are barely thought worth recording in works on
+natural history.  And I look at varieties which are in any degree more
+distinct and permanent, as steps leading to more strongly marked and more
+permanent varieties; and at these latter, as leading to sub-species, and to
+species.  The passage from one stage of difference to another and higher
+stage may be, in some cases, due merely to the long-continued action of
+different physical conditions in two different regions; but I have not much
+faith in this view; and I attribute the passage of a variety, from a state
+in which it differs very slightly from its parent to one in which it
+differs more, to the action of natural selection in accumulating (as will
+hereafter be more fully explained) differences of structure in certain
+definite directions.  Hence I believe a well-marked variety may be justly
+called an incipient species; but whether this belief be justifiable must be
+judged of by the general weight of the several facts and views given
+throughout this work.
+</para>
+
+<para>
+It need not be supposed that all varieties or incipient species necessarily
+attain the rank of species.  They may whilst in this incipient state become
+extinct, or they may endure as varieties for very long periods, as has been
+shown to be the case by Mr. Wollaston with the varieties of certain fossil
+land-shells in Madeira.  If a variety were to flourish so as to exceed in
+numbers the parent species, it would then rank as the species, and the
+species as the variety; or it might come to supplant and exterminate the
+parent species; or both might co-exist, and both rank as independent
+species.  But we shall hereafter have to return to this subject.
+</para>
+
+<para>
+From these remarks it will be seen that I look at the term species, as one
+arbitrarily given for the sake of convenience to a set of individuals
+closely resembling each other, and that it does not essentially differ from
+the term variety, which is given to less distinct and more fluctuating
+forms.  The term variety, again, in comparison with mere individual
+differences, is also applied arbitrarily, and for mere convenience sake.
+</para>
+
+<para>
+Guided by theoretical considerations, I thought that some interesting
+results might be obtained in regard to the nature and relations of the
+species which vary most, by tabulating all the varieties in several
+well-worked floras.  At first this seemed a simple task; but Mr. H. C.
+Watson, to whom I am much indebted for valuable advice and assistance on
+this subject, soon convinced me that there were many difficulties, as did
+subsequently Dr. Hooker, even in stronger terms.  I shall reserve for my
+future work the discussion of these difficulties, and the tables themselves
+of the proportional numbers of the varying species.  Dr. Hooker permits me
+to add, that after having carefully read my manuscript, and examined the
+tables, he thinks that the following statements are fairly well
+established.  The whole subject, however, treated as it necessarily here is
+with much brevity, is rather perplexing, and allusions cannot be avoided to
+the 'struggle for existence,' 'divergence of character,' and other
+questions, hereafter to be discussed.
+</para>
+
+<para>
+Alph. De Candolle and others have shown that plants which have very wide
+ranges generally present varieties; and this might have been expected, as
+they become exposed to diverse physical conditions, and as they come into
+competition (which, as we shall hereafter see, is a far more important
+circumstance) with different sets of organic beings.  But my tables further
+show that, in any limited country, the species which are most common, that
+is abound most in individuals, and the species which are most widely
+diffused within their own country (and this is a different consideration
+from wide range, and to a certain extent from commonness), often give rise
+to varieties sufficiently well-marked to have been recorded in botanical
+works.  Hence it is the most flourishing, or, as they may be called, the
+dominant species,--those which range widely over the world, are the most
+diffused in their own country, and are the most numerous in
+individuals,--which oftenest produce well-marked varieties, or, as I
+consider them, incipient species.  And this, perhaps, might have been
+anticipated; for, as varieties, in order to become in any degree permanent,
+necessarily have to struggle with the other inhabitants of the country, the
+species which are already dominant will be the most likely to yield
+offspring which, though in some slight degree modified, will still inherit
+those advantages that enabled their parents to become dominant over their
+compatriots.
+</para>
+
+<para>
+If the plants inhabiting a country and described in any Flora be divided
+into two equal masses, all those in the larger genera being placed on one
+side, and all those in the smaller genera on the other side, a somewhat
+larger number of the very common and much diffused or dominant species will
+be found on the side of the larger genera.  This, again, might have been
+anticipated; for the mere fact of many species of the same genus inhabiting
+any country, shows that there is something in the organic or inorganic
+conditions of that country favourable to the genus; and, consequently, we
+might have expected to have found in the larger genera, or those including
+many species, a large proportional number of dominant species.  But so many
+causes tend to obscure this result, that I am surprised that my tables show
+even a small majority on the side of the larger genera.  I will here allude
+to only two causes of obscurity.  Fresh-water and salt-loving plants have
+generally very wide ranges and are much diffused, but this seems to be
+connected with the nature of the stations inhabited by them, and has little
+or no relation to the size of the genera to which the species belong. 
+Again, plants low in the scale of organisation are generally much more
+widely diffused than plants higher in the scale; and here again there is no
+close relation to the size of the genera.  The cause of lowly-organised
+plants ranging widely will be discussed in our chapter on geographical
+distribution.
+</para>
+
+<para>
+From looking at species as only strongly-marked and well-defined varieties,
+I was led to anticipate that the species of the larger genera in each
+country would oftener present varieties, than the species of the smaller
+genera; for wherever many closely related species (i.e. species of the same
+genus) have been formed, many varieties or incipient species ought, as a
+general rule, to be now forming.  Where many large trees grow, we expect to
+find saplings.  Where many species of a genus have been formed through
+variation, circumstances have been favourable for variation; and hence we
+might expect that the circumstances would generally be still favourable to
+variation.  On the other hand, if we look at each species as a special act
+of creation, there is no apparent reason why more varieties should occur in
+a group having many species, than in one having few.
+</para>
+
+<para>
+To test the truth of this anticipation I have arranged the plants of twelve
+countries, and the coleopterous insects of two districts, into two nearly
+equal masses, the species of the larger genera on one side, and those of
+the smaller genera on the other side, and it has invariably proved to be
+the case that a larger proportion of the species on the side of the larger
+genera present varieties, than on the side of the smaller genera. 
+Moreover, the species of the large genera which present any varieties,
+invariably present a larger average number of varieties than do the species
+of the small genera.  Both these results follow when another division is
+made, and when all the smallest genera, with from only one to four species,
+are absolutely excluded from the tables.  These facts are of plain
+signification on the view that species are only strongly marked and
+permanent varieties; for whenever many species of the same genus have been
+formed, or where, if we may use the expression, the manufactory of species
+has been active, we ought generally to find the manufactory still in
+action, more especially as we have every reason to believe the process of
+manufacturing new species to be a slow one.  And this certainly is the
+case, if varieties be looked at as incipient species; for my tables clearly
+show as a general rule that, wherever many species of a genus have been
+formed, the species of that genus present a number of varieties, that is of
+incipient species, beyond the average.  It is not that all large genera are
+now varying much, and are thus increasing in the number of their species,
+or that no small genera are now varying and increasing; for if this had
+been so, it would have been fatal to my theory; inasmuch as geology plainly
+tells us that small genera have in the lapse of time often increased
+greatly in size; and that large genera have often come to their maxima,
+declined, and disappeared.  All that we want to show is, that where many
+species of a genus have been formed, on an average many are still forming;
+and this holds good.
+</para>
+
+<para>
+There are other relations between the species of large genera and their
+recorded varieties which deserve notice.  We have seen that there is no
+infallible criterion by which to distinguish species and well-marked
+varieties; and in those cases in which intermediate links have not been
+found between doubtful forms, naturalists are compelled to come to a
+determination by the amount of difference between them, judging by analogy
+whether or not the amount suffices to raise one or both to the rank of
+species.  Hence the amount of difference is one very important criterion in
+settling whether two forms should be ranked as species or varieties.  Now
+Fries has remarked in regard to plants, and Westwood in regard to insects,
+that in large genera the amount of difference between the species is often
+exceedingly small.  I have endeavoured to test this numerically by
+averages, and, as far as my imperfect results go, they always confirm the
+view.  I have also consulted some sagacious and most experienced observers,
+and, after deliberation, they concur in this view.  In this respect,
+therefore, the species of the larger genera resemble varieties, more than
+do the species of the smaller genera.  Or the case may be put in another
+way, and it may be said, that in the larger genera, in which a number of
+varieties or incipient species greater than the average are now
+manufacturing, many of the species already manufactured still to a certain
+extent resemble varieties, for they differ from each other by a less than
+usual amount of difference.
+</para>
+
+<para>
+Moreover, the species of the large genera are related to each other, in the
+same manner as the varieties of any one species are related to each other. 
+No naturalist pretends that all the species of a genus are equally distinct
+from each other; they may generally be divided into sub-genera, or
+sections, or lesser groups.  As Fries has well remarked, little groups of
+species are generally clustered like satellites around certain other
+species.  And what are varieties but groups of forms, unequally related to
+each other, and clustered round certain forms--that is, round their
+parent-species?  Undoubtedly there is one most important point of
+difference between varieties and species; namely, that the amount of
+difference between varieties, when compared with each other or with their
+parent-species, is much less than that between the species of the same
+genus.  But when we come to discuss the principle, as I call it, of
+Divergence of Character, we shall see how this may be explained, and how
+the lesser differences between varieties will tend to increase into the
+greater differences between species.
+</para>
+
+<para>
+There is one other point which seems to me worth notice.  Varieties
+generally have much restricted ranges:  this statement is indeed scarcely
+more than a truism, for if a variety were found to have a wider range than
+that of its supposed parent-species, their denominations ought to be
+reversed.  But there is also reason to believe, that those species which
+are very closely allied to other species, and in so far resemble varieties,
+often have much restricted ranges.  For instance, Mr. H. C. Watson has
+marked for me in the well-sifted London Catalogue of plants (4th edition)
+63 plants which are therein ranked as species, but which he considers as so
+closely allied to other species as to be of doubtful value:  these 63
+reputed species range on an average over 6.9 of the provinces into which
+Mr. Watson has divided Great Britain.  Now, in this same catalogue, 53
+acknowledged varieties are recorded, and these range over 7.7 provinces;
+whereas, the species to which these varieties belong range over 14.3
+provinces.  So that the acknowledged varieties have very nearly the same
+restricted average range, as have those very closely allied forms, marked
+for me by Mr. Watson as doubtful species, but which are almost universally
+ranked by British botanists as good and true species.
+</para>
+
+<para>
+Finally, then, varieties have the same general characters as species, for
+they cannot be distinguished from species,--except, firstly, by the
+discovery of intermediate linking forms, and the occurrence of such links
+cannot affect the actual characters of the forms which they connect; and
+except, secondly, by a certain amount of difference, for two forms, if
+differing very little, are generally ranked as varieties, notwithstanding
+that intermediate linking forms have not been discovered; but the amount of
+difference considered necessary to give to two forms the rank of species is
+quite indefinite.  In genera having more than the average number of species
+in any country, the species of these genera have more than the average
+number of varieties.  In large genera the species are apt to be closely,
+but unequally, allied together, forming little clusters round certain
+species.  Species very closely allied to other species apparently have
+restricted ranges.  In all these several respects the species of large
+genera present a strong analogy with varieties.  And we can clearly
+understand these analogies, if species have once existed as varieties, and
+have thus originated:  whereas, these analogies are utterly inexplicable if
+each species has been independently created.
+</para>
+
+<para>
+We have, also, seen that it is the most flourishing and dominant species of
+the larger genera which on an average vary most; and varieties, as we shall
+hereafter see, tend to become converted into new and distinct species.  The
+larger genera thus tend to become larger; and throughout nature the forms
+of life which are now dominant tend to become still more dominant by
+leaving many modified and dominant descendants.  But by steps hereafter to
+be explained, the larger genera also tend to break up into smaller genera. 
+And thus, the forms of life throughout the universe become divided into
+groups subordinate to groups.
+</para>
+
+</chapter>
+
+<chapter>
+<chapheader>
+
+<chapnum>Chapter III</chapnum>
+
+<title>Struggle for Existence</title>
+
+<chapsummary>
+Bears on natural selection -- The term used in a wide sense -- Geometrical
+powers of increase -- Rapid increase of naturalised animals and plants --
+Nature of the checks to increase -- Competition universal -- Effects of
+climate -- Protection from the number of individuals -- Complex relations
+of all animals and plants throughout nature -- Struggle for life most
+severe between individuals and varieties of the same species; often severe
+between species of the same genus -- The relation of organism to organism
+the most important of all relations.
+</chapsummary>
+</chapheader>
+
+<para> 
+Before entering on the subject of this chapter, I must make a few
+preliminary remarks, to show how the struggle for existence bears on
+Natural Selection.  It has been seen in the last chapter that amongst
+organic beings in a state of nature there is some individual variability;
+indeed I am not aware that this has ever been disputed.  It is immaterial
+for us whether a multitude of doubtful forms be called species or
+sub-species or varieties; what rank, for instance, the two or three hundred
+doubtful forms of British plants are entitled to hold, if the existence of
+any well-marked varieties be admitted.  But the mere existence of
+individual variability and of some few well-marked varieties, though
+necessary as the foundation for the work, helps us but little in
+understanding how species arise in nature.  How have all those exquisite
+adaptations of one part of the organisation to another part, and to the
+conditions of life, and of one distinct organic being to another being,
+been perfected?  We see these beautiful co-adaptations most plainly in the
+woodpecker and missletoe; and only a little less plainly in the humblest
+parasite which clings to the hairs of a quadruped or feathers of a bird; in
+the structure of the beetle which dives through the water; in the plumed
+seed which is wafted by the gentlest breeze; in short, we see beautiful
+adaptations everywhere and in every part of the organic world.
+</para>
+
+<para>
+Again, it may be asked, how is it that varieties, which I have called
+incipient species, become ultimately converted into good and distinct
+species, which in most cases obviously differ from each other far more than
+do the varieties of the same species?  How do those groups of species,
+which constitute what are called distinct genera, and which differ from
+each other more than do the species of the same genus, arise?  All these
+results, as we shall more fully see in the next chapter, follow inevitably
+from the struggle for life.  Owing to this struggle for life, any
+variation, however slight and from whatever cause proceeding, if it be in
+any degree profitable to an individual of any species, in its infinitely
+complex relations to other organic beings and to external nature, will tend
+to the preservation of that individual, and will generally be inherited by
+its offspring.  The offspring, also, will thus have a better chance of
+surviving, for, of the many individuals of any species which are
+periodically born, but a small number can survive.  I have called this
+principle, by which each slight variation, if useful, is preserved, by the
+term of Natural Selection, in order to mark its relation to man's power of
+selection.  We have seen that man by selection can certainly produce great
+results, and can adapt organic beings to his own uses, through the
+accumulation of slight but useful variations, given to him by the hand of
+Nature.  But Natural Selection, as we shall hereafter see, is a power
+incessantly ready for action, and is as immeasurably superior to man's
+feeble efforts, as the works of Nature are to those of Art.
+</para>
+
+<para>
+We will now discuss in a little more detail the struggle for existence.  In
+my future work this subject shall be treated, as it well deserves, at much
+greater length.  The elder De Candolle and Lyell have largely and
+philosophically shown that all organic beings are exposed to severe
+competition.  In regard to plants, no one has treated this subject with
+more spirit and ability than W. Herbert, Dean of Manchester, evidently the
+result of his great horticultural knowledge.  Nothing is easier than to
+admit in words the truth of the universal struggle for life, or more
+difficult--at least I have found it so--than constantly to bear this
+conclusion in mind.  Yet unless it be thoroughly engrained in the mind, I
+am convinced that the whole economy of nature, with every fact on
+distribution, rarity, abundance, extinction, and variation, will be dimly
+seen or quite misunderstood.  We behold the face of nature bright with
+gladness, we often see superabundance of food; we do not see, or we forget,
+that the birds which are idly singing round us mostly live on insects or
+seeds, and are thus constantly destroying life; or we forget how largely
+these songsters, or their eggs, or their nestlings, are destroyed by birds
+and beasts of prey; we do not always bear in mind, that though food may be
+now superabundant, it is not so at all seasons of each recurring year.
+</para>
+
+<para>
+I should premise that I use the term Struggle for Existence in a large and
+metaphorical sense, including dependence of one being on another, and
+including (which is more important) not only the life of the individual,
+but success in leaving progeny.  Two canine animals in a time of dearth,
+may be truly said to struggle with each other which shall get food and
+live.  But a plant on the edge of a desert is said to struggle for life
+against the drought, though more properly it should be said to be dependent
+on the moisture.  A plant which annually produces a thousand seeds, of
+which on an average only one comes to maturity, may be more truly said to
+struggle with the plants of the same and other kinds which already clothe
+the ground.  The missletoe is dependent on the apple and a few other trees,
+but can only in a far-fetched sense be said to struggle with these trees,
+for if too many of these parasites grow on the same tree, it will languish
+and die.  But several seedling missletoes, growing close together on the
+same branch, may more truly be said to struggle with each other.  As the
+missletoe is disseminated by birds, its existence depends on birds; and it
+may metaphorically be said to struggle with other fruit-bearing plants, in
+order to tempt birds to devour and thus disseminate its seeds rather than
+those of other plants.  In these several senses, which pass into each
+other, I use for convenience sake the general term of struggle for
+existence.
+</para>
+
+<para>
+A struggle for existence inevitably follows from the high rate at which all
+organic beings tend to increase.  Every being, which during its natural
+lifetime produces several eggs or seeds, must suffer destruction during
+some period of its life, and during some season or occasional year,
+otherwise, on the principle of geometrical increase, its numbers would
+quickly become so inordinately great that no country could support the
+product.  Hence, as more individuals are produced than can possibly
+survive, there must in every case be a struggle for existence, either one
+individual with another of the same species, or with the individuals of
+distinct species, or with the physical conditions of life.  It is the
+doctrine of Malthus applied with manifold force to the whole animal and
+vegetable kingdoms; for in this case there can be no artificial increase of
+food, and no prudential restraint from marriage.  Although some species may
+be now increasing, more or less rapidly, in numbers, all cannot do so, for
+the world would not hold them.
+</para>
+
+<para>
+There is no exception to the rule that every organic being naturally
+increases at so high a rate, that if not destroyed, the earth would soon be
+covered by the progeny of a single pair.  Even slow-breeding man has
+doubled in twenty-five years, and at this rate, in a few thousand years,
+there would literally not be standing room for his progeny.  Linnaeus has
+calculated that if an annual plant produced only two seeds--and there is no
+plant so unproductive as this--and their seedlings next year produced two,
+and so on, then in twenty years there would be a million plants.  The
+elephant is reckoned to be the slowest breeder of all known animals, and I
+have taken some pains to estimate its probable minimum rate of natural
+increase:  it will be under the mark to assume that it breeds when thirty
+years old, and goes on breeding till ninety years old, bringing forth three
+pair of young in this interval; if this be so, at the end of the fifth
+century there would be alive fifteen million elephants, descended from the
+first pair.
+</para>
+
+<para>
+But we have better evidence on this subject than mere theoretical
+calculations, namely, the numerous recorded cases of the astonishingly
+rapid increase of various animals in a state of nature, when circumstances
+have been favourable to them during two or three following seasons.  Still
+more striking is the evidence from our domestic animals of many kinds which
+have run wild in several parts of the world:  if the statements of the rate
+of increase of slow-breeding cattle and horses in South America, and
+latterly in Australia, had not been well authenticated, they would have
+been quite incredible.  So it is with plants:  cases could be given of
+introduced plants which have become common throughout whole islands in a
+period of less than ten years.  Several of the plants now most numerous
+over the wide plains of La Plata, clothing square leagues of surface almost
+to the exclusion of all other plants, have been introduced from Europe; and
+there are plants which now range in India, as I hear from Dr. Falconer,
+from Cape Comorin to the Himalaya, which have been imported from America
+since its discovery.  In such cases, and endless instances could be given,
+no one supposes that the fertility of these animals or plants has been
+suddenly and temporarily increased in any sensible degree.  The obvious
+explanation is that the conditions of life have been very favourable, and
+that there has consequently been less destruction of the old and young, and
+that nearly all the young have been enabled to breed.  In such cases the
+geometrical ratio of increase, the result of which never fails to be
+surprising, simply explains the extraordinarily rapid increase and wide
+diffusion of naturalised productions in their new homes.
+</para>
+
+<para>
+In a state of nature almost every plant produces seed, and amongst animals
+there are very few which do not annually pair.  Hence we may confidently
+assert, that all plants and animals are tending to increase at a
+geometrical ratio, that all would most rapidly stock every station in which
+they could any how exist, and that the geometrical tendency to increase
+must be checked by destruction at some period of life.  Our familiarity
+with the larger domestic animals tends, I think, to mislead us:  we see no
+great destruction falling on them, and we forget that thousands are
+annually slaughtered for food, and that in a state of nature an equal
+number would have somehow to be disposed of.
+</para>
+
+<para>
+The only difference between organisms which annually produce eggs or seeds
+by the thousand, and those which produce extremely few, is, that the
+slow-breeders would require a few more years to people, under favourable
+conditions, a whole district, let it be ever so large.  The condor lays a
+couple of eggs and the ostrich a score, and yet in the same country the
+condor may be the more numerous of the two:  the Fulmar petrel lays but one
+egg, yet it is believed to be the most numerous bird in the world.  One fly
+deposits hundreds of eggs, and another, like the hippobosca, a single one;
+but this difference does not determine how many individuals of the two
+species can be supported in a district.  A large number of eggs is of some
+importance to those species, which depend on a rapidly fluctuating amount
+of food, for it allows them rapidly to increase in number.  But the real
+importance of a large number of eggs or seeds is to make up for much
+destruction at some period of life; and this period in the great majority
+of cases is an early one.  If an animal can in any way protect its own eggs
+or young, a small number may be produced, and yet the average stock be
+fully kept up; but if many eggs or young are destroyed, many must be
+produced, or the species will become extinct.  It would suffice to keep up
+the full number of a tree, which lived on an average for a thousand years,
+if a single seed were produced once in a thousand years, supposing that
+this seed were never destroyed, and could be ensured to germinate in a
+fitting place.  So that in all cases, the average number of any animal or
+plant depends only indirectly on the number of its eggs or seeds.
+</para>
+
+<para>
+In looking at Nature, it is most necessary to keep the foregoing
+considerations always in mind--never to forget that every single organic
+being around us may be said to be striving to the utmost to increase in
+numbers; that each lives by a struggle at some period of its life; that
+heavy destruction inevitably falls either on the young or old, during each
+generation or at recurrent intervals.  Lighten any check, mitigate the 
+destruction ever so little, and the number of the species will almost
+instantaneously increase to any amount.  The face of Nature may be compared
+to a yielding surface, with ten thousand sharp wedges packed close together
+and driven inwards by incessant blows, sometimes one wedge being struck,
+and then another with greater force.
+</para>
+
+<para>
+What checks the natural tendency of each species to increase in number is
+most obscure.  Look at the most vigorous species; by as much as it swarms
+in numbers, by so much will its tendency to increase be still further
+increased.  We know not exactly what the checks are in even one single
+instance.  Nor will this surprise any one who reflects how ignorant we are
+on this head, even in regard to mankind, so incomparably better known than
+any other animal.  This subject has been ably treated by several authors,
+and I shall, in my future work, discuss some of the checks at considerable
+length, more especially in regard to the feral animals of South America. 
+Here I will make only a few remarks, just to recall to the reader's mind
+some of the chief points.  Eggs or very young animals seem generally to
+suffer most, but this is not invariably the case.  With plants there is a
+vast destruction of seeds, but, from some observations which I have made, I
+believe that it is the seedlings which suffer most from germinating in
+ground already thickly stocked with other plants.  Seedlings, also, are
+destroyed in vast numbers by various enemies; for instance, on a piece of
+ground three feet long and two wide, dug and cleared, and where there could
+be no choking from other plants, I marked all the seedlings of our native
+weeds as they came up, and out of the 357 no less than 295 were destroyed,
+chiefly by slugs and insects.  If turf which has long been mown, and the
+case would be the same with turf closely browsed by quadrupeds, be let to
+grow, the more vigorous plants gradually kill the less vigorous, though
+fully grown, plants:  thus out of twenty species growing on a little plot
+of turf (three feet by four) nine species perished from the other species
+being allowed to grow up freely.
+</para>
+
+<para>
+The amount of food for each species of course gives the extreme limit to
+which each can increase; but very frequently it is not the obtaining food,
+but the serving as prey to other animals, which determines the average
+numbers of a species.  Thus, there seems to be little doubt that the stock
+of partridges, grouse, and hares on any large estate depends chiefly on the
+destruction of vermin.  If not one head of game were shot during the next
+twenty years in England, and, at the same time, if no vermin were
+destroyed, there would, in all probability, be less game than at present,
+although hundreds of thousands of game animals are now annually killed.  On
+the other hand, in some cases, as with the elephant and rhinoceros, none
+are destroyed by beasts of prey:  even the tiger in India most rarely dares
+to attack a young elephant protected by its dam.
+</para>
+
+<para>
+Climate plays an important part in determining the average numbers of a
+species, and periodical seasons of extreme cold or drought, I believe to be
+the most effective of all checks.  I estimated that the winter of 1854-55
+destroyed four-fifths of the birds in my own grounds; and this is a
+tremendous destruction, when we remember that ten per cent. is an
+extraordinarily severe mortality from epidemics with man.  The action of
+climate seems at first sight to be quite independent of the struggle for
+existence; but in so far as climate chiefly acts in reducing food, it
+brings on the most severe struggle between the individuals, whether of the
+same or of distinct species, which subsist on the same kind of food.  Even
+when climate, for instance extreme cold, acts directly, it will be the
+least vigorous, or those which have got least food through the advancing
+winter, which will suffer most.  When we travel from south to north, or
+from a damp region to a dry, we invariably see some species gradually
+getting rarer and rarer, and finally disappearing; and the change of
+climate being conspicuous, we are tempted to attribute the whole effect to
+its direct action.  But this is a very false view:  we forget that each
+species, even where it most abounds, is constantly suffering enormous
+destruction at some period of its life, from enemies or from competitors
+for the same place and food; and if these enemies or competitors be in the
+least degree favoured by any slight change of climate, they will increase
+in numbers, and, as each area is already fully stocked with inhabitants,
+the other species will decrease.  When we travel southward and see a
+species decreasing in numbers, we may feel sure that the cause lies quite
+as much in other species being favoured, as in this one being hurt.  So it
+is when we travel northward, but in a somewhat lesser degree, for the
+number of species of all kinds, and therefore of competitors, decreases
+northwards; hence in going northward, or in ascending a mountain, we far
+oftener meet with stunted forms, due to the directly injurious action of
+climate, than we do in proceeding southwards or in descending a mountain. 
+When we reach the Arctic regions, or snow-capped summits, or absolute
+deserts, the struggle for life is almost exclusively with the elements.
+</para>
+
+<para>
+That climate acts in main part indirectly by favouring other species, we
+may clearly see in the prodigious number of plants in our gardens which can
+perfectly well endure our climate, but which never become naturalised, for
+they cannot compete with our native plants, nor resist destruction by our
+native animals.
+</para>
+
+<para>
+When a species, owing to highly favourable circumstances, increases
+inordinately in numbers in a small tract, epidemics--at least, this seems
+generally to occur with our game animals--often ensue:  and here we have a
+limiting check independent of the struggle for life.  But even some of
+these so-called epidemics appear to be due to parasitic worms, which have
+from some cause, possibly in part through facility of diffusion amongst the
+crowded animals, been disproportionably favoured:  and here comes in a sort
+of struggle between the parasite and its prey.
+</para>
+
+<para>
+On the other hand, in many cases, a large stock of individuals of the same
+species, relatively to the numbers of its enemies, is absolutely necessary
+for its preservation.  Thus we can easily raise plenty of corn and
+rape-seed, &amp;c., in our fields, because the seeds are in great excess
+compared with the number of birds which feed on them; nor can the birds,
+though having a superabundance of food at this one season, increase in
+number proportionally to the supply of seed, as their numbers are checked
+during winter:  but any one who has tried, knows how troublesome it is to
+get seed from a few wheat or other such plants in a garden; I have in this
+case lost every single seed.  This view of the necessity of a large stock
+of the same species for its preservation, explains, I believe, some
+singular facts in nature, such as that of very rare plants being sometimes
+extremely abundant in the few spots where they do occur; and that of some
+social plants being social, that is, abounding in individuals, even on the
+extreme confines of their range.  For in such cases, we may believe, that a
+plant could exist only where the conditions of its life were so favourable
+that many could exist together, and thus save each other from utter
+destruction.  I should add that the good effects of frequent intercrossing,
+and the ill effects of close interbreeding, probably come into play in some
+of these cases; but on this intricate subject I will not here enlarge.
+</para>
+
+<para>
+Many cases are on record showing how complex and unexpected are the checks
+and relations between organic beings, which have to struggle together in
+the same country.  I will give only a single instance, which, though a
+simple one, has interested me.  In Staffordshire, on the estate of a
+relation where I had ample means of investigation, there was a large and
+extremely barren heath, which had never been touched by the hand of man;
+but several hundred acres of exactly the same nature had been enclosed
+twenty-five years previously and planted with Scotch fir.  The change in
+the native vegetation of the planted part of the heath was most remarkable,
+more than is generally seen in passing from one quite different soil to
+another:  not only the proportional numbers of the heath-plants were wholly
+changed, but twelve species of plants (not counting grasses and carices)
+flourished in the plantations, which could not be found on the heath.  The
+effect on the insects must have been still greater, for six insectivorous
+birds were very common in the plantations, which were not to be seen on the
+heath; and the heath was frequented by two or three distinct insectivorous
+birds.  Here we see how potent has been the effect of the introduction of a
+single tree, nothing whatever else having been done, with the exception
+that the land had been enclosed, so that cattle could not enter.  But how
+important an element enclosure is, I plainly saw near Farnham, in Surrey. 
+Here there are extensive heaths, with a few clumps of old Scotch firs on
+the distant hill-tops:  within the last ten years large spaces have been
+enclosed, and self-sown firs are now springing up in multitudes, so close
+together that all cannot live.
+</para>
+
+<para>
+When I ascertained that these young trees had not been sown or planted, I
+was so much surprised at their numbers that I went to several points of
+view, whence I could examine hundreds of acres of the unenclosed heath, and
+literally I could not see a single Scotch fir, except the old planted
+clumps.  But on looking closely between the stems of the heath, I found a
+multitude of seedlings and little trees, which had been perpetually browsed
+down by the cattle.  In one square yard, at a point some hundreds yards
+distant from one of the old clumps, I counted thirty-two little trees; and
+one of them, judging from the rings of growth, had during twenty-six years
+tried to raise its head above the stems of the heath, and had failed.  No
+wonder that, as soon as the land was enclosed, it became thickly clothed
+with vigorously growing young firs.  Yet the heath was so extremely barren
+and so extensive that no one would ever have imagined that cattle would
+have so closely and effectually searched it for food.
+</para>
+
+<para>
+Here we see that cattle absolutely determine the existence of the Scotch
+fir; but in several parts of the world insects determine the existence of
+cattle.  Perhaps Paraguay offers the most curious instance of this; for
+here neither cattle nor horses nor dogs have ever run wild, though they
+swarm southward and northward in a feral state; and Azara and Rengger have
+shown that this is caused by the greater number in Paraguay of a certain
+fly, which lays its eggs in the navels of these animals when first born. 
+The increase of these flies, numerous as they are, must be habitually
+checked by some means, probably by birds.  Hence, if certain insectivorous
+birds (whose numbers are probably regulated by hawks or beasts of prey)
+were to increase in Paraguay, the flies would decrease--then cattle and
+horses would become feral, and this would certainly greatly alter (as
+indeed I have observed in parts of South America) the vegetation:  this
+again would largely affect the insects; and this, as we just have seen in
+Staffordshire, the insectivorous birds, and so onwards in ever-increasing
+circles of complexity.  We began this series by insectivorous birds, and we
+have ended with them.  Not that in nature the relations can ever be as
+simple as this.  Battle within battle must ever be recurring with varying
+success; and yet in the long-run the forces are so nicely balanced, that
+the face of nature remains uniform for long periods of time, though
+assuredly the merest trifle would often give the victory to one organic
+being over another.  Nevertheless so profound is our ignorance, and so high
+our presumption, that we marvel when we hear of the extinction of an
+organic being; and as we do not see the cause, we invoke cataclysms to
+desolate the world, or invent laws on the duration of the forms of life!
+</para>
+
+<para>
+I am tempted to give one more instance showing how plants and animals, most
+remote in the scale of nature, are bound together by a web of complex
+relations.  I shall hereafter have occasion to show that the exotic Lobelia
+fulgens, in this part of England, is never visited by insects, and
+consequently, from its peculiar structure, never can set a seed.  Many of
+our orchidaceous plants absolutely require the visits of moths to remove
+their pollen-masses and thus to fertilise them.  I have, also, reason to
+believe that humble-bees are indispensable to the fertilisation of the
+heartsease (Viola tricolor), for other bees do not visit this flower.  From
+experiments which I have tried, I have found that the visits of bees, if
+not indispensable, are at least highly beneficial to the fertilisation of
+our clovers; but humble-bees alone visit the common red clover (Trifolium
+pratense), as other bees cannot reach the nectar.  Hence I have very little
+doubt, that if the whole genus of humble-bees became extinct or very rare
+in England, the heartsease and red clover would become very rare, or wholly
+disappear.  The number of humble-bees in any district depends in a great
+degree on the number of field-mice, which destroy their combs and nests;
+and Mr. H. Newman, who has long attended to the habits of humble-bees,
+believes that 'more than two thirds of them are thus destroyed all over
+England.'  Now the number of mice is largely dependent, as every one knows,
+on the number of cats; and Mr. Newman says, 'Near villages and small towns
+I have found the nests of humble-bees more numerous than elsewhere, which I
+attribute to the number of cats that destroy the mice.'  Hence it is quite
+credible that the presence of a feline animal in large numbers in a
+district might determine, through the intervention first of mice and then
+of bees, the frequency of certain flowers in that district!
+</para>
+
+<para>
+In the case of every species, many different checks, acting at different
+periods of life, and during different seasons or years, probably come into
+play; some one check or some few being generally the most potent, but all
+concurring in determining the average number or even the existence of the
+species.  In some cases it can be shown that widely-different checks act on
+the same species in different districts.  When we look at the plants and
+bushes clothing an entangled bank, we are tempted to attribute their
+proportional numbers and kinds to what we call chance.  But how false a
+view is this!  Every one has heard that when an American forest is cut
+down, a very different vegetation springs up; but it has been observed that
+the trees now growing on the ancient Indian mounds, in the Southern United
+States, display the same beautiful diversity and proportion of kinds as in
+the surrounding virgin forests.  What a struggle between the several kinds
+of trees must here have gone on during long centuries, each annually
+scattering its seeds by the thousand; what war between insect and
+insect--between insects, snails, and other animals with birds and beasts of
+prey--all striving to increase, and all feeding on each other or on the
+trees or their seeds and seedlings, or on the other plants which first
+clothed the ground and thus checked the growth of the trees!  Throw up a
+handful of feathers, and all must fall to the ground according to definite
+laws; but how simple is this problem compared to the action and reaction of
+the innumerable plants and animals which have determined, in the course of
+centuries, the proportional numbers and kinds of trees now growing on the
+old Indian ruins!
+</para>
+
+<para>
+The dependency of one organic being on another, as of a parasite on its
+prey, lies generally between beings remote in the scale of nature.  This is
+often the case with those which may strictly be said to struggle with each
+other for existence, as in the case of locusts and grass-feeding
+quadrupeds.  But the struggle almost invariably will be most severe between
+the individuals of the same species, for they frequent the same districts,
+require the same food, and are exposed to the same dangers.  In the case of
+varieties of the same species, the struggle will generally be almost
+equally severe, and we sometimes see the contest soon decided:  for
+instance, if several varieties of wheat be sown together, and the mixed
+seed be resown, some of the varieties which best suit the soil or climate,
+or are naturally the most fertile, will beat the others and so yield more
+seed, and will consequently in a few years quite supplant the other
+varieties.  To keep up a mixed stock of even such extremely close varieties
+as the variously coloured sweet-peas, they must be each year harvested
+separately, and the seed then mixed in due proportion, otherwise the weaker
+kinds will steadily decrease in numbers and disappear.  So again with the
+varieties of sheep:  it has been asserted that certain mountain-varieties
+will starve out other mountain-varieties, so that they cannot be kept
+together.  The same result has followed from keeping together different
+varieties of the medicinal leech.  It may even be doubted whether the
+varieties of any one of our domestic plants or animals have so exactly the
+same strength, habits, and constitution, that the original proportions of a
+mixed stock could be kept up for half a dozen generations, if they were
+allowed to struggle together, like beings in a state of nature, and if the
+seed or young were not annually sorted.
+</para>
+
+<para>
+As species of the same genus have usually, though by no means invariably,
+some similarity in habits and constitution, and always in structure, the
+struggle will generally be more severe between species of the same genus,
+when they come into competition with each other, than between species of
+distinct genera.  We see this in the recent extension over parts of the
+United States of one species of swallow having caused the decrease of
+another species.  The recent increase of the missel-thrush in parts of
+Scotland has caused the decrease of the song-thrush.  How frequently we
+hear of one species of rat taking the place of another species under the
+most different climates!  In Russia the small Asiatic cockroach has
+everywhere driven before it its great congener.  One species of charlock
+will supplant another, and so in other cases.  We can dimly see why the
+competition should be most severe between allied forms, which fill nearly
+the same place in the economy of nature; but probably in no one case could
+we precisely say why one species has been victorious over another in the
+great battle of life.
+</para>
+
+<para>
+A corollary of the highest importance may be deduced from the foregoing
+remarks, namely, that the structure of every organic being is related, in
+the most essential yet often hidden manner, to that of all other organic
+beings, with which it comes into competition for food or residence, or from
+which it has to escape, or on which it preys.  This is obvious in the
+structure of the teeth and talons of the tiger; and in that of the legs and
+claws of the parasite which clings to the hair on the tiger's body.  But in
+the beautifully plumed seed of the dandelion, and in the flattened and
+fringed legs of the water-beetle, the relation seems at first confined to
+the elements of air and water.  Yet the advantage of plumed seeds no doubt
+stands in the closest relation to the land being already thickly clothed by
+other plants; so that the seeds may be widely distributed and fall on
+unoccupied ground.  In the water-beetle, the structure of its legs, so well
+adapted for diving, allows it to compete with other aquatic insects, to
+hunt for its own prey, and to escape serving as prey to other animals.
+</para>
+
+<para>
+The store of nutriment laid up within the seeds of many plants seems at
+first sight to have no sort of relation to other plants.  But from the
+strong growth of young plants produced from such seeds (as peas and beans),
+when sown in the midst of long grass, I suspect that the chief use of the
+nutriment in the seed is to favour the growth of the young seedling, whilst
+struggling with other plants growing vigorously all around.
+</para>
+
+<para>
+Look at a plant in the midst of its range, why does it not double or
+quadruple its numbers?  We know that it can perfectly well withstand a
+little more heat or cold, dampness or dryness, for elsewhere it ranges into
+slightly hotter or colder, damper or drier districts.  In this case we can
+clearly see that if we wished in imagination to give the plant the power of
+increasing in number, we should have to give it some advantage over its
+competitors, or over the animals which preyed on it.  On the confines of
+its geographical range, a change of constitution with respect to climate
+would clearly be an advantage to our plant; but we have reason to believe
+that only a few plants or animals range so far, that they are destroyed by
+the rigour of the climate alone.  Not until we reach the extreme confines
+of life, in the arctic regions or on the borders of an utter desert, will
+competition cease.  The land may be extremely cold or dry, yet there will
+be competition between some few species, or between the individuals of the
+same species, for the warmest or dampest spots.
+</para>
+
+<para>
+Hence, also, we can see that when a plant or animal is placed in a new
+country amongst new competitors, though the climate may be exactly the same
+as in its former home, yet the conditions of its life will generally be
+changed in an essential manner.  If we wished to increase its average
+numbers in its new home, we should have to modify it in a different way to
+what we should have done in its native country; for we should have to give
+it some advantage over a different set of competitors or enemies.
+</para>
+
+<para>
+It is good thus to try in our imagination to give any form some advantage
+over another.  Probably in no single instance should we know what to do, so
+as to succeed.  It will convince us of our ignorance on the mutual
+relations of all organic beings; a conviction as necessary, as it seems to
+be difficult to acquire.  All that we can do, is to keep steadily in mind
+that each organic being is striving to increase at a geometrical ratio;
+that each at some period of its life, during some season of the year,
+during each generation or at intervals, has to struggle for life, and to
+suffer great destruction.  When we reflect on this struggle, we may console
+ourselves with the full belief, that the war of nature is not incessant,
+that no fear is felt, that death is generally prompt, and that the
+vigorous, the healthy, and the happy survive and multiply.
+</para>
+
+</chapter>
+
+<chapter>
+<chapheader>
+
+<chapnum>Chapter IV</chapnum>
+
+<title>Natural Selection</title>
+
+<chapsummary>
+Natural Selection -- its power compared with man's selection -- its power
+on characters of trifling importance -- its power at all ages and on both
+sexes -- Sexual Selection -- On the generality of intercrosses between
+individuals of the same species -- Circumstances favourable and
+unfavourable to Natural Selection, namely, intercrossing, isolation, number
+of individuals -- Slow action -- Extinction caused by Natural Selection --
+Divergence of Character, related to the diversity of inhabitants of any
+small area, and to naturalisation -- Action of Natural Selection, through
+Divergence of Character and Extinction, on the descendants from a common
+parent -- Explains the Grouping of all organic beings.
+</chapsummary>
+</chapheader>
+
+<para>
+How will the struggle for existence, discussed too briefly in the last
+chapter, act in regard to variation?  Can the principle of selection, which
+we have seen is so potent in the hands of man, apply in nature?  I think we
+shall see that it can act most effectually.  Let it be borne in mind in
+what an endless number of strange peculiarities our domestic productions,
+and, in a lesser degree, those under nature, vary; and how strong the
+hereditary tendency is.  Under domestication, it may be truly said that the
+whole organisation becomes in some degree plastic.  Let it be borne in mind
+how infinitely complex and close-fitting are the mutual relations of all
+organic beings to each other and to their physical conditions of life.  Can
+it, then, be thought improbable, seeing that variations useful to man have
+undoubtedly occurred, that other variations useful in some way to each
+being in the great and complex battle of life, should sometimes occur in
+the course of thousands of generations?  If such do occur, can we doubt
+(remembering that many more individuals are born than can possibly survive)
+that individuals having any advantage, however slight, over others, would
+have the best chance of surviving and of procreating their kind?  On the
+other hand, we may feel sure that any variation in the least degree
+injurious would be rigidly destroyed.  This preservation of favourable
+variations and the rejection of injurious variations, I call Natural
+Selection.  Variations neither useful nor injurious would not be affected
+by natural selection, and would be left a fluctuating element, as perhaps
+we see in the species called polymorphic.
+</para>
+
+<para>
+We shall best understand the probable course of natural selection by taking
+the case of a country undergoing some physical change, for instance, of
+climate.  The proportional numbers of its inhabitants would almost
+immediately undergo a change, and some species might become extinct.  We
+may conclude, from what we have seen of the intimate and complex manner in
+which the inhabitants of each country are bound together, that any change
+in the numerical proportions of some of the inhabitants, independently of
+the change of climate itself, would most seriously affect many of the
+others.  If the country were open on its borders, new forms would certainly
+immigrate, and this also would seriously disturb the relations of some of
+the former inhabitants.  Let it be remembered how powerful the influence of
+a single introduced tree or mammal has been shown to be.  But in the case
+of an island, or of a country partly surrounded by barriers, into which new
+and better adapted forms could not freely enter, we should then have places
+in the economy of nature which would assuredly be better filled up, if some
+of the original inhabitants were in some manner modified; for, had the area
+been open to immigration, these same places would have been seized on by
+intruders.  In such case, every slight modification, which in the course of
+ages chanced to arise, and which in any way favoured the individuals of any
+of the species, by better adapting them to their altered conditions, would
+tend to be preserved; and natural selection would thus have free scope for
+the work of improvement.
+</para>
+
+<para>
+We have reason to believe, as stated in the first chapter, that a change in
+the conditions of life, by specially acting on the reproductive system,
+causes or increases variability; and in the foregoing case the conditions
+of life are supposed to have undergone a change, and this would manifestly
+be favourable to natural selection, by giving a better chance of profitable
+variations occurring; and unless profitable variations do occur, natural
+selection can do nothing.  Not that, as I believe, any extreme amount of
+variability is necessary; as man can certainly produce great results by
+adding up in any given direction mere individual differences, so could
+Nature, but far more easily, from having incomparably longer time at her
+disposal.  Nor do I believe that any great physical change, as of climate,
+or any unusual degree of isolation to check immigration, is actually
+necessary to produce new and unoccupied places for natural selection to
+fill up by modifying and improving some of the varying inhabitants.  For as
+all the inhabitants of each country are struggling together with nicely
+balanced forces, extremely slight modifications in the structure or habits
+of one inhabitant would often give it an advantage over others; and still
+further modifications of the same kind would often still further increase
+the advantage.  No country can be named in which all the native inhabitants
+are now so perfectly adapted to each other and to the physical conditions
+under which they live, that none of them could anyhow be improved; for in
+all countries, the natives have been so far conquered by naturalised
+productions, that they have allowed foreigners to take firm possession of
+the land.  And as foreigners have thus everywhere beaten some of the
+natives, we may safely conclude that the natives might have been modified
+with advantage, so as to have better resisted such intruders.
+</para>
+
+<para>
+As man can produce and certainly has produced a great result by his
+methodical and unconscious means of selection, what may not nature effect? 
+Man can act only on external and visible characters:  nature cares nothing
+for appearances, except in so far as they may be useful to any being.  She
+can act on every internal organ, on every shade of constitutional
+difference, on the whole machinery of life.  Man selects only for his own
+good; Nature only for that of the being which she tends.  Every selected
+character is fully exercised by her; and the being is placed under
+well-suited conditions of life.  Man keeps the natives of many climates in
+the same country; he seldom exercises each selected character in some
+peculiar and fitting manner; he feeds a long and a short beaked pigeon on
+the same food; he does not exercise a long-backed or long-legged quadruped
+in any peculiar manner; he exposes sheep with long and short wool to the
+same climate.  He does not allow the most vigorous males to struggle for
+the females.  He does not rigidly destroy all inferior animals, but
+protects during each varying season, as far as lies in his power, all his
+productions.  He often begins his selection by some half-monstrous form; or
+at least by some modification prominent enough to catch his eye, or to be
+plainly useful to him.  Under nature, the slightest difference of structure
+or constitution may well turn the nicely-balanced scale in the struggle for
+life, and so be preserved.  How fleeting are the wishes and efforts of man!
+how short his time! and consequently how poor will his products be,
+compared with those accumulated by nature during whole geological periods. 
+Can we wonder, then, that nature's productions should be far 'truer' in
+character than man's productions; that they should be infinitely better
+adapted to the most complex conditions of life, and should plainly bear the
+stamp of far higher workmanship?
+</para>
+
+<para>
+It may be said that natural selection is daily and hourly scrutinising,
+throughout the world, every variation, even the slightest; rejecting that
+which is bad, preserving and adding up all that is good; silently and
+insensibly working, whenever and wherever opportunity offers, at the
+improvement of each organic being in relation to its organic and inorganic
+conditions of life.  We see nothing of these slow changes in progress,
+until the hand of time has marked the long lapse of ages, and then so
+imperfect is our view into long past geological ages, that we only see that
+the forms of life are now different from what they formerly were.
+</para>
+
+<para>
+Although natural selection can act only through and for the good of each
+being, yet characters and structures, which we are apt to consider as of
+very trifling importance, may thus be acted on.  When we see leaf-eating
+insects green, and bark-feeders mottled-grey; the alpine ptarmigan white in
+winter, the red-grouse the colour of heather, and the black-grouse that of
+peaty earth, we must believe that these tints are of service to these birds
+and insects in preserving them from danger.  Grouse, if not destroyed at
+some period of their lives, would increase in countless numbers; they are
+known to suffer largely from birds of prey; and hawks are guided by
+eyesight to their prey,--so much so, that on parts of the Continent persons
+are warned not to keep white pigeons, as being the most liable to
+destruction.  Hence I can see no reason to doubt that natural selection
+might be most effective in giving the proper colour to each kind of grouse,
+and in keeping that colour, when once acquired, true and constant.  Nor
+ought we to think that the occasional destruction of an animal of any
+particular colour would produce little effect:  we should remember how
+essential it is in a flock of white sheep to destroy every lamb with the
+faintest trace of black.  In plants the down on the fruit and the colour of
+the flesh are considered by botanists as characters of the most trifling
+importance:  yet we hear from an excellent horticulturist, Downing, that in
+the United States smooth-skinned fruits suffer far more from a beetle, a
+curculio, than those with down; that purple plums suffer far more from a
+certain disease than yellow plums; whereas another disease attacks
+yellow-fleshed peaches far more than those with other coloured flesh.  If,
+with all the aids of art, these slight differences make a great difference
+in cultivating the several varieties, assuredly, in a state of nature,
+where the trees would have to struggle with other trees and with a host of
+enemies, such differences would effectually settle which variety, whether a
+smooth or downy, a yellow or purple fleshed fruit, should succeed.
+</para>
+
+<para>
+In looking at many small points of difference between species, which, as
+far as our ignorance permits us to judge, seem to be quite unimportant, we
+must not forget that climate, food, &amp;c., probably produce some slight and
+direct effect.  It is, however, far more necessary to bear in mind that
+there are many unknown laws of correlation of growth, which, when one part
+of the organisation is modified through variation, and the modifications
+are accumulated by natural selection for the good of the being, will cause
+other modifications, often of the most unexpected nature.
+</para>
+
+<para>
+As we see that those variations which under domestication appear at any
+particular period of life, tend to reappear in the offspring at the same
+period;--for instance, in the seeds of the many varieties of our culinary
+and agricultural plants; in the caterpillar and cocoon stages of the
+varieties of the silkworm; in the eggs of poultry, and in the colour of the
+down of their chickens; in the horns of our sheep and cattle when nearly
+adult;--so in a state of nature, natural selection will be enabled to act
+on and modify organic beings at any age, by the accumulation of profitable
+variations at that age, and by their inheritance at a corresponding age. 
+If it profit a plant to have its seeds more and more widely disseminated by
+the wind, I can see no greater difficulty in this being effected through
+natural selection, than in the cotton-planter increasing and improving by
+selection the down in the pods on his cotton-trees.  Natural selection may
+modify and adapt the larva of an insect to a score of contingencies, wholly
+different from those which concern the mature insect.  These modifications
+will no doubt affect, through the laws of correlation, the structure of the
+adult; and probably in the case of those insects which live only for a few
+hours, and which never feed, a large part of their structure is merely the
+correlated result of successive changes in the structure of their larvae. 
+So, conversely, modifications in the adult will probably often affect the
+structure of the larva; but in all cases natural selection will ensure that
+modifications consequent on other modifications at a different period of
+life, shall not be in the least degree injurious:  for if they became so,
+they would cause the extinction of the species.
+</para>
+
+<para>
+Natural selection will modify the structure of the young in relation to the
+parent, and of the parent in relation to the young.  In social animals it
+will adapt the structure of each individual for the benefit of the
+community; if each in consequence profits by the selected change.  What
+natural selection cannot do, is to modify the structure of one species,
+without giving it any advantage, for the good of another species; and
+though statements to this effect may be found in works of natural history,
+I cannot find one case which will bear investigation.  A structure used
+only once in an animal's whole life, if of high importance to it, might be
+modified to any extent by natural selection; for instance, the great jaws
+possessed by certain insects, and used exclusively for opening the
+cocoon--or the hard tip to the beak of nestling birds, used for breaking
+the egg.  It has been asserted, that of the best short-beaked
+tumbler-pigeons more perish in the egg than are able to get out of it; so
+that fanciers assist in the act of hatching.  Now, if nature had to make
+the beak of a full-grown pigeon very short for the bird's own advantage,
+the process of modification would be very slow, and there would be
+simultaneously the most rigorous selection of the young birds within the
+egg, which had the most powerful and hardest beaks, for all with weak beaks
+would inevitably perish:  or, more delicate and more easily broken shells
+might be selected, the thickness of the shell being known to vary like
+every other structure.
+</para>
+
+<para>
+Sexual Selection. -- Inasmuch as peculiarities often appear under
+domestication in one sex and become hereditarily attached to that sex, the
+same fact probably occurs under nature, and if so, natural selection will
+be able to modify one sex in its functional relations to the other sex, or
+in relation to wholly different habits of life in the two sexes, as is
+sometimes the case with insects.  And this leads me to say a few words on
+what I call Sexual Selection.  This depends, not on a struggle for
+existence, but on a struggle between the males for possession of the
+females; the result is not death to the unsuccessful competitor, but few or
+no offspring.  Sexual selection is, therefore, less rigorous than natural
+selection.  Generally, the most vigorous males, those which are best fitted
+for their places in nature, will leave most progeny.  But in many cases,
+victory will depend not on general vigour, but on having special weapons,
+confined to the male sex.  A hornless stag or spurless cock would have a
+poor chance of leaving offspring.  Sexual selection by always allowing the
+victor to breed might surely give indomitable courage, length to the spur,
+and strength to the wing to strike in the spurred leg, as well as the
+brutal cock-fighter, who knows well that he can improve his breed by
+careful selection of the best cocks.  How low in the scale of nature this
+law of battle descends, I know not; male alligators have been described as
+fighting, bellowing, and whirling round, like Indians in a war-dance, for
+the possession of the females; male salmons have been seen fighting all day
+long; male stag-beetles often bear wounds from the huge mandibles of other
+males.  The war is, perhaps, severest between the males of polygamous
+animals, and these seem oftenest provided with special weapons.  The males
+of carnivorous animals are already well armed; though to them and to
+others, special means of defence may be given through means of sexual
+selection, as the mane to the lion, the shoulder-pad to the boar, and the
+hooked jaw to the male salmon; for the shield may be as important for
+victory, as the sword or spear.
+</para>
+
+<para>
+Amongst birds, the contest is often of a more peaceful character.  All
+those who have attended to the subject, believe that there is the severest
+rivalry between the males of many species to attract by singing the
+females.  The rock-thrush of Guiana, birds of Paradise, and some others,
+congregate; and successive males display their gorgeous plumage and perform
+strange antics before the females, which standing by as spectators, at last
+choose the most attractive partner.  Those who have closely attended to
+birds in confinement well know that they often take individual preferences
+and dislikes:  thus Sir R. Heron has described how one pied peacock was
+eminently attractive to all his hen birds.  It may appear childish to
+attribute any effect to such apparently weak means:  I cannot here enter on
+the details necessary to support this view; but if man can in a short time
+give elegant carriage and beauty to his bantams, according to his standard
+of beauty, I can see no good reason to doubt that female birds, by
+selecting, during thousands of generations, the most melodious or beautiful
+males, according to their standard of beauty, might produce a marked
+effect.  I strongly suspect that some well-known laws with respect to the
+plumage of male and female birds, in comparison with the plumage of the
+young, can be explained on the view of plumage having been chiefly modified
+by sexual selection, acting when the birds have come to the breeding age or
+during the breeding season; the modifications thus produced being inherited
+at corresponding ages or seasons, either by the males alone, or by the
+males and females; but I have not space here to enter on this subject.
+</para>
+
+<para>
+Thus it is, as I believe, that when the males and females of any animal
+have the same general habits of life, but differ in structure, colour, or
+ornament, such differences have been mainly caused by sexual selection;
+that is, individual males have had, in successive generations, some slight
+advantage over other males, in their weapons, means of defence, or charms;
+and have transmitted these advantages to their male offspring.  Yet, I
+would not wish to attribute all such sexual differences to this agency: 
+for we see peculiarities arising and becoming attached to the male sex in
+our domestic animals (as the wattle in male carriers, horn-like
+protuberances in the cocks of certain fowls, &amp;c.), which we cannot believe
+to be either useful to the males in battle, or attractive to the females. 
+We see analogous cases under nature, for instance, the tuft of hair on the
+breast of the turkey-cock, which can hardly be either useful or ornamental
+to this bird;--indeed, had the tuft appeared under domestication, it would
+have been called a monstrosity.
+</para>
+
+<para>
+
+Illustrations of the action of Natural Selection. -- In order to make it
+clear how, as I believe, natural selection acts, I must beg permission to
+give one or two imaginary illustrations.  Let us take the case of a wolf,
+which preys on various animals, securing some by craft, some by strength,
+and some by fleetness; and let us suppose that the fleetest prey, a deer
+for instance, had from any change in the country increased in numbers, or
+that other prey had decreased in numbers, during that season of the year
+when the wolf is hardest pressed for food.  I can under such circumstances
+see no reason to doubt that the swiftest and slimmest wolves would have the
+best chance of surviving, and so be preserved or selected,--provided always
+that they retained strength to master their prey at this or at some other
+period of the year, when they might be compelled to prey on other animals. 
+I can see no more reason to doubt this, than that man can improve the
+fleetness of his greyhounds by careful and methodical selection, or by that
+unconscious selection which results from each man trying to keep the best
+dogs without any thought of modifying the breed.
+</para>
+
+<para>
+Even without any change in the proportional numbers of the animals on which
+our wolf preyed, a cub might be born with an innate tendency to pursue
+certain kinds of prey.  Nor can this be thought very improbable; for we
+often observe great differences in the natural tendencies of our domestic
+animals; one cat, for instance, taking to catch rats, another mice; one
+cat, according to Mr. St. John, bringing home winged game, another hares or
+rabbits, and another hunting on marshy ground and almost nightly catching
+woodcocks or snipes.  The tendency to catch rats rather than mice is known
+to be inherited.  Now, if any slight innate change of habit or of structure
+benefited an individual wolf, it would have the best chance of surviving
+and of leaving offspring.  Some of its young would probably inherit the
+same habits or structure, and by the repetition of this process, a new
+variety might be formed which would either supplant or coexist with the
+parent-form of wolf.  Or, again, the wolves inhabiting a mountainous
+district, and those frequenting the lowlands, would naturally be forced to
+hunt different prey; and from the continued preservation of the individuals
+best fitted for the two sites, two varieties might slowly be formed.  These
+varieties would cross and blend where they met; but to this subject of
+intercrossing we shall soon have to return.  I may add, that, according to
+Mr. Pierce, there are two varieties of the wolf inhabiting the Catskill
+Mountains in the United States, one with a light greyhound-like form, which
+pursues deer, and the other more bulky, with shorter legs, which more
+frequently attacks the shepherd's flocks.
+</para>
+
+<para>
+Let us now take a more complex case.  Certain plants excrete a sweet juice,
+apparently for the sake of eliminating something injurious from their sap: 
+this is effected by glands at the base of the stipules in some Leguminosae,
+and at the back of the leaf of the common laurel.  This juice, though small
+in quantity, is greedily sought by insects.  Let us now suppose a little
+sweet juice or nectar to be excreted by the inner bases of the petals of a
+flower.  In this case insects in seeking the nectar would get dusted with
+pollen, and would certainly often transport the pollen from one flower to
+the stigma of another flower.  The flowers of two distinct individuals of
+the same species would thus get crossed; and the act of crossing, we have
+good reason to believe (as will hereafter be more fully alluded to), would
+produce very vigorous seedlings, which consequently would have the best
+chance of flourishing and surviving.  Some of these seedlings would
+probably inherit the nectar-excreting power.  Those individual flowers
+which had the largest glands or nectaries, and which excreted most nectar,
+would be oftenest visited by insects, and would be oftenest crossed; and so
+in the long-run would gain the upper hand.  Those flowers, also, which had
+their stamens and pistils placed, in relation to the size and habits of the
+particular insects which visited them, so as to favour in any degree the
+transportal of their pollen from flower to flower, would likewise be
+favoured or selected.  We might have taken the case of insects visiting
+flowers for the sake of collecting pollen instead of nectar; and as pollen
+is formed for the sole object of fertilisation, its destruction appears a
+simple loss to the plant; yet if a little pollen were carried, at first
+occasionally and then habitually, by the pollen-devouring insects from
+flower to flower, and a cross thus effected, although nine-tenths of the
+pollen were destroyed, it might still be a great gain to the plant; and
+those individuals which produced more and more pollen, and had larger and
+larger anthers, would be selected.
+</para>
+
+<para>
+When our plant, by this process of the continued preservation or natural
+selection of more and more attractive flowers, had been rendered highly
+attractive to insects, they would, unintentionally on their part, regularly
+carry pollen from flower to flower; and that they can most effectually do
+this, I could easily show by many striking instances.  I will give only
+one--not as a very striking case, but as likewise illustrating one step in
+the separation of the sexes of plants, presently to be alluded to.  Some
+holly-trees bear only male flowers, which have four stamens producing
+rather a small quantity of pollen, and a rudimentary pistil; other
+holly-trees bear only female flowers; these have a full-sized pistil, and
+four stamens with shrivelled anthers, in which not a grain of pollen can be
+detected.  Having found a female tree exactly sixty yards from a male tree,
+I put the stigmas of twenty flowers, taken from different branches, under
+the microscope, and on all, without exception, there were pollen-grains,
+and on some a profusion of pollen.  As the wind had set for several days
+from the female to the male tree, the pollen could not thus have been
+carried.  The weather had been cold and boisterous, and therefore not
+favourable to bees, nevertheless every female flower which I examined had
+been effectually fertilised by the bees, accidentally dusted with pollen,
+having flown from tree to tree in search of nectar.  But to return to our
+imaginary case:  as soon as the plant had been rendered so highly
+attractive to insects that pollen was regularly carried from flower to
+flower, another process might commence.  No naturalist doubts the advantage
+of what has been called the 'physiological division of labour;' hence we
+may believe that it would be advantageous to a plant to produce stamens
+alone in one flower or on one whole plant, and pistils alone in another
+flower or on another plant.  In plants under culture and placed under new
+conditions of life, sometimes the male organs and sometimes the female
+organs become more or less impotent; now if we suppose this to occur in
+ever so slight a degree under nature, then as pollen is already carried
+regularly from flower to flower, and as a more complete separation of the
+sexes of our plant would be advantageous on the principle of the division
+of labour, individuals with this tendency more and more increased, would be
+continually favoured or selected, until at last a complete separation of
+the sexes would be effected.
+</para>
+
+<para>
+Let us now turn to the nectar-feeding insects in our imaginary case:  we
+may suppose the plant of which we have been slowly increasing the nectar by
+continued selection, to be a common plant; and that certain insects
+depended in main part on its nectar for food.  I could give many facts,
+showing how anxious bees are to save time; for instance, their habit of
+cutting holes and sucking the nectar at the bases of certain flowers, which
+they can, with a very little more trouble, enter by the mouth.  Bearing
+such facts in mind, I can see no reason to doubt that an accidental
+deviation in the size and form of the body, or in the curvature and length
+of the proboscis, &amp;c., far too slight to be appreciated by us, might profit
+a bee or other insect, so that an individual so characterised would be able
+to obtain its food more quickly, and so have a better chance of living and
+leaving descendants.  Its descendants would probably inherit a tendency to
+a similar slight deviation of structure.  The tubes of the corollas of the
+common red and incarnate clovers (Trifolium pratense and incarnatum) do not
+on a hasty glance appear to differ in length; yet the hive-bee can easily
+suck the nectar out of the incarnate clover, but not out of the common red
+clover, which is visited by humble-bees alone; so that whole fields of the
+red clover offer in vain an abundant supply of precious nectar to the
+hive-bee.  Thus it might be a great advantage to the hive-bee to have a
+slightly longer or differently constructed proboscis.  On the other hand, I
+have found by experiment that the fertility of clover greatly depends on
+bees visiting and moving parts of the corolla, so as to push the pollen on
+to the stigmatic surface.  Hence, again, if humble-bees were to become rare
+in any country, it might be a great advantage to the red clover to have a
+shorter or more deeply divided tube to its corolla, so that the hive-bee
+could visit its flowers.  Thus I can understand how a flower and a bee
+might slowly become, either simultaneously or one after the other, modified
+and adapted in the most perfect manner to each other, by the continued
+preservation of individuals presenting mutual and slightly favourable
+deviations of structure.
+</para>
+
+<para>
+I am well aware that this doctrine of natural selection, exemplified in the
+above imaginary instances, is open to the same objections which were at
+first urged against Sir Charles Lyell's noble views on 'the modern changes
+of the earth, as illustrative of geology;' but we now very seldom hear the
+action, for instance, of the coast-waves, called a trifling and
+insignificant cause, when applied to the excavation of gigantic valleys or
+to the formation of the longest lines of inland cliffs.  Natural selection
+can act only by the preservation and accumulation of infinitesimally small
+inherited modifications, each profitable to the preserved being; and as
+modern geology has almost banished such views as the excavation of a great
+valley by a single diluvial wave, so will natural selection, if it be a
+true principle, banish the belief of the continued creation of new organic
+beings, or of any great and sudden modification in their structure.
+</para>
+
+<para>
+On the Intercrossing of Individuals. -- I must here introduce a short
+digression.  In the case of animals and plants with separated sexes, it is
+of course obvious that two individuals must always unite for each birth;
+but in the case of hermaphrodites this is far from obvious.  Nevertheless I
+am strongly inclined to believe that with all hermaphrodites two
+individuals, either occasionally or habitually, concur for the reproduction
+of their kind.  This view, I may add, was first suggested by Andrew Knight. 
+We shall presently see its importance; but I must here treat the subject
+with extreme brevity, though I have the materials prepared for an ample
+discussion.  All vertebrate animals, all insects, and some other large
+groups of animals, pair for each birth.  Modern research has much
+diminished the number of supposed hermaphrodites, and of real
+hermaphrodites a large number pair; that is, two individuals regularly
+unite for reproduction, which is all that concerns us.  But still there are
+many hermaphrodite animals which certainly do not habitually pair, and a
+vast majority of plants are hermaphrodites.  What reason, it may be asked,
+is there for supposing in these cases that two individuals ever concur in
+reproduction?  As it is impossible here to enter on details, I must trust
+to some general considerations alone.
+</para>
+
+<para>
+In the first place, I have collected so large a body of facts, showing, in
+accordance with the almost universal belief of breeders, that with animals
+and plants a cross between different varieties, or between individuals of
+the same variety but of another strain, gives vigour and fertility to the
+offspring; and on the other hand, that close interbreeding diminishes
+vigour and fertility; that these facts alone incline me to believe that it
+is a general law of nature (utterly ignorant though we be of the meaning of
+the law) that no organic being self-fertilises itself for an eternity of
+generations; but that a cross with another individual is
+occasionally--perhaps at very long intervals--indispensable.
+</para>
+
+<para>
+On the belief that this is a law of nature, we can, I think, understand
+several large classes of facts, such as the following, which on any other
+view are inexplicable.  Every hybridizer knows how unfavourable exposure to
+wet is to the fertilisation of a flower, yet what a multitude of flowers
+have their anthers and stigmas fully exposed to the weather! but if an
+occasional cross be indispensable, the fullest freedom for the entrance of
+pollen from another individual will explain this state of exposure, more
+especially as the plant's own anthers and pistil generally stand so close
+together that self-fertilisation seems almost inevitable.  Many flowers, on
+the other hand, have their organs of fructification closely enclosed, as in
+the great papilionaceous or pea-family; but in several, perhaps in all,
+such flowers, there is a very curious adaptation between the structure of
+the flower and the manner in which bees suck the nectar; for, in doing
+this, they either push the flower's own pollen on the stigma, or bring
+pollen from another flower.  So necessary are the visits of bees to
+papilionaceous flowers, that I have found, by experiments published
+elsewhere, that their fertility is greatly diminished if these visits be
+prevented.  Now, it is scarcely possible that bees should fly from flower
+to flower, and not carry pollen from one to the other, to the great good,
+as I believe, of the plant.  Bees will act like a camel-hair pencil, and it
+is quite sufficient just to touch the anthers of one flower and then the
+stigma of another with the same brush to ensure fertilisation; but it must
+not be supposed that bees would thus produce a multitude of hybrids between
+distinct species; for if you bring on the same brush a plant's own pollen
+and pollen from another species, the former will have such a prepotent
+effect, that it will invariably and completely destroy, as has been shown
+by Gartner, any influence from the foreign pollen.
+</para>
+
+<para>
+When the stamens of a flower suddenly spring towards the pistil, or slowly
+move one after the other towards it, the contrivance seems adapted solely
+to ensure self-fertilisation; and no doubt it is useful for this end:  but,
+the agency of insects is often required to cause the stamens to spring
+forward, as Kolreuter has shown to be the case with the barberry; and
+curiously in this very genus, which seems to have a special contrivance for
+self-fertilisation, it is well known that if very closely-allied forms or
+varieties are planted near each other, it is hardly possible to raise pure
+seedlings, so largely do they naturally cross.  In many other cases, far
+from there being any aids for self-fertilisation, there are special
+contrivances, as I could show from the writings of C. C. Sprengel and from
+my own observations, which effectually prevent the stigma receiving pollen
+from its own flower:  for instance, in Lobelia fulgens, there is a really
+beautiful and elaborate contrivance by which every one of the infinitely
+numerous pollen-granules are swept out of the conjoined anthers of each
+flower, before the stigma of that individual flower is ready to receive
+them; and as this flower is never visited, at least in my garden, by
+insects, it never sets a seed, though by placing pollen from one flower on
+the stigma of another, I raised plenty of seedlings; and whilst another
+species of Lobelia growing close by, which is visited by bees, seeds
+freely.  In very many other cases, though there be no special mechanical
+contrivance to prevent the stigma of a flower receiving its own pollen,
+yet, as C. C. Sprengel has shown, and as I can confirm, either the anthers
+burst before the stigma is ready for fertilisation, or the stigma is ready
+before the pollen of that flower is ready, so that these plants have in
+fact separated sexes, and must habitually be crossed.  How strange are
+these facts!  How strange that the pollen and stigmatic surface of the same
+flower, though placed so close together, as if for the very purpose of
+self-fertilisation, should in so many cases be mutually useless to each
+other!  How simply are these facts explained on the view of an occasional
+cross with a distinct individual being advantageous or indispensable!
+</para>
+
+<para>
+If several varieties of the cabbage, radish, onion, and of some other
+plants, be allowed to seed near each other, a large majority, as I have
+found, of the seedlings thus raised will turn out mongrels:  for instance,
+I raised 233 seedling cabbages from some plants of different varieties
+growing near each other, and of these only 78 were true to their kind, and
+some even of these were not perfectly true.  Yet the pistil of each
+cabbage-flower is surrounded not only by its own six stamens, but by those
+of the many other flowers on the same plant.  How, then, comes it that such
+a vast number of the seedlings are mongrelized?  I suspect that it must
+arise from the pollen of a distinct variety having a prepotent effect over
+a flower's own pollen; and that this is part of the general law of good
+being derived from the intercrossing of distinct individuals of the same
+species.  When distinct species are crossed the case is directly the
+reverse, for a plant's own pollen is always prepotent over foreign pollen;
+but to this subject we shall return in a future chapter.
+</para>
+
+<para>
+In the case of a gigantic tree covered with innumerable flowers, it may be
+objected that pollen could seldom be carried from tree to tree, and at most
+only from flower to flower on the same tree, and that flowers on the same
+tree can be considered as distinct individuals only in a limited sense.  I
+believe this objection to be valid, but that nature has largely provided
+against it by giving to trees a strong tendency to bear flowers with
+separated sexes.  When the sexes are separated, although the male and
+female flowers may be produced on the same tree, we can see that pollen
+must be regularly carried from flower to flower; and this will give a
+better chance of pollen being occasionally carried from tree to tree.  That
+trees belonging to all Orders have their sexes more often separated than
+other plants, I find to be the case in this country; and at my request Dr.
+Hooker tabulated the trees of New Zealand, and Dr. Asa Gray those of the
+United States, and the result was as I anticipated.  On the other hand, Dr.
+Hooker has recently informed me that he finds that the rule does not hold
+in Australia; and I have made these few remarks on the sexes of trees
+simply to call attention to the subject.
+</para>
+
+<para>
+Turning for a very brief space to animals:  on the land there are some
+hermaphrodites, as land-mollusca and earth-worms; but these all pair.  As
+yet I have not found a single case of a terrestrial animal which fertilises
+itself.  We can understand this remarkable fact, which offers so strong a
+contrast with terrestrial plants, on the view of an occasional cross being
+indispensable, by considering the medium in which terrestrial animals live,
+and the nature of the fertilising element; for we know of no means,
+analogous to the action of insects and of the wind in the case of plants,
+by which an occasional cross could be effected with terrestrial animals
+without the concurrence of two individuals.  Of aquatic animals, there are
+many self-fertilising hermaphrodites; but here currents in the water offer
+an obvious means for an occasional cross.  And, as in the case of flowers,
+I have as yet failed, after consultation with one of the highest
+authorities, namely, Professor Huxley, to discover a single case of an
+hermaphrodite animal with the organs of reproduction so perfectly enclosed
+within the body, that access from without and the occasional influence of a
+distinct individual can be shown to be physically impossible.  Cirripedes
+long appeared to me to present a case of very great difficulty under this
+point of view; but I have been enabled, by a fortunate chance, elsewhere to
+prove that two individuals, though both are self-fertilising
+hermaphrodites, do sometimes cross.
+</para>
+
+<para>
+It must have struck most naturalists as a strange anomaly that, in the case
+of both animals and plants, species of the same family and even of the same
+genus, though agreeing closely with each other in almost their whole
+organisation, yet are not rarely, some of them hermaphrodites, and some of
+them unisexual.  But if, in fact, all hermaphrodites do occasionally
+intercross with other individuals, the difference between hermaphrodites
+and unisexual species, as far as function is concerned, becomes very small.
+</para>
+
+<para>
+From these several considerations and from the many special facts which I
+have collected, but which I am not here able to give, I am strongly
+inclined to suspect that, both in the vegetable and animal kingdoms, an
+occasional intercross with a distinct individual is a law of nature.  I am
+well aware that there are, on this view, many cases of difficulty, some of
+which I am trying to investigate.  Finally then, we may conclude that in
+many organic beings, a cross between two individuals is an obvious
+necessity for each birth; in many others it occurs perhaps only at long
+intervals; but in none, as I suspect, can self-fertilisation go on for
+perpetuity.
+</para>
+
+<para>
+Circumstances favourable to Natural Selection. -- This is an extremely
+intricate subject.  A large amount of inheritable and diversified
+variability is favourable, but I believe mere individual differences
+suffice for the work.  A large number of individuals, by giving a better
+chance for the appearance within any given period of profitable variations,
+will compensate for a lesser amount of variability in each individual, and
+is, I believe, an extremely important element of success.  Though nature
+grants vast periods of time for the work of natural selection, she does not
+grant an indefinite period; for as all organic beings are striving, it may
+be said, to seize on each place in the economy of nature, if any one
+species does not become modified and improved in a corresponding degree
+with its competitors, it will soon be exterminated.
+</para>
+
+<para>
+In man's methodical selection, a breeder selects for some definite object,
+and free intercrossing will wholly stop his work.  But when many men,
+without intending to alter the breed, have a nearly common standard of
+perfection, and all try to get and breed from the best animals, much
+improvement and modification surely but slowly follow from this unconscious
+process of selection, notwithstanding a large amount of crossing with
+inferior animals.  Thus it will be in nature; for within a confined area,
+with some place in its polity not so perfectly occupied as might be,
+natural selection will always tend to preserve all the individuals varying
+in the right direction, though in different degrees, so as better to fill
+up the unoccupied place.  But if the area be large, its several districts
+will almost certainly present different conditions of life; and then if
+natural selection be modifying and improving a species in the several
+districts, there will be intercrossing with the other individuals of the
+same species on the confines of each.  And in this case the effects of
+intercrossing can hardly be counterbalanced by natural selection always
+tending to modify all the individuals in each district in exactly the same
+manner to the conditions of each; for in a continuous area, the conditions
+will generally graduate away insensibly from one district to another.  The
+intercrossing will most affect those animals which unite for each birth,
+which wander much, and which do not breed at a very quick rate.  Hence in
+animals of this nature, for instance in birds, varieties will generally be
+confined to separated countries; and this I believe to be the case.  In
+hermaphrodite organisms which cross only occasionally, and likewise in
+animals which unite for each birth, but which wander little and which can
+increase at a very rapid rate, a new and improved variety might be quickly
+formed on any one spot, and might there maintain itself in a body, so that
+whatever intercrossing took place would be chiefly between the individuals
+of the same new variety.  A local variety when once thus formed might
+subsequently slowly spread to other districts.  On the above principle,
+nurserymen always prefer getting seed from a large body of plants of the
+same variety, as the chance of intercrossing with other varieties is thus
+lessened.
+</para>
+
+<para>
+Even in the case of slow-breeding animals, which unite for each birth, we
+must not overrate the effects of intercrosses in retarding natural
+selection; for I can bring a considerable catalogue of facts, showing that
+within the same area, varieties of the same animal can long remain
+distinct, from haunting different stations, from breeding at slightly
+different seasons, or from varieties of the same kind preferring to pair
+together.
+</para>
+
+<para>
+Intercrossing plays a very important part in nature in keeping the
+individuals of the same species, or of the same variety, true and uniform
+in character.  It will obviously thus act far more efficiently with those
+animals which unite for each birth; but I have already attempted to show
+that we have reason to believe that occasional intercrosses take place with
+all animals and with all plants.  Even if these take place only at long
+intervals, I am convinced that the young thus produced will gain so much in
+vigour and fertility over the offspring from long-continued
+self-fertilisation, that they will have a better chance of surviving and
+propagating their kind; and thus, in the long run, the influence of
+intercrosses, even at rare intervals, will be great.  If there exist
+organic beings which never intercross, uniformity of character can be
+retained amongst them, as long as their conditions of life remain the same,
+only through the principle of inheritance, and through natural selection
+destroying any which depart from the proper type; but if their conditions
+of life change and they undergo modification, uniformity of character can
+be given to their modified offspring, solely by natural selection
+preserving the same favourable variations.
+</para>
+
+<para>
+Isolation, also, is an important element in the process of natural
+selection.  In a confined or isolated area, if not very large, the organic
+and inorganic conditions of life will generally be in a great degree
+uniform; so that natural selection will tend to modify all the individuals
+of a varying species throughout the area in the same manner in relation to
+the same conditions.  Intercrosses, also, with the individuals of the same
+species, which otherwise would have inhabited the surrounding and
+differently circumstanced districts, will be prevented.  But isolation
+probably acts more efficiently in checking the immigration of better
+adapted organisms, after any physical change, such as of climate or
+elevation of the land, &amp;c.; and thus new places in the natural economy of
+the country are left open for the old inhabitants to struggle for, and
+become adapted to, through modifications in their structure and
+constitution.  Lastly, isolation, by checking immigration and consequently
+competition, will give time for any new variety to be slowly improved; and
+this may sometimes be of importance in the production of new species.  If,
+however, an isolated area be very small, either from being surrounded by
+barriers, or from having very peculiar physical conditions, the total
+number of the individuals supported on it will necessarily be very small;
+and fewness of individuals will greatly retard the production of new
+species through natural selection, by decreasing the chance of the
+appearance of favourable variations.
+</para>
+
+<para>
+If we turn to nature to test the truth of these remarks, and look at any
+small isolated area, such as an oceanic island, although the total number
+of the species inhabiting it, will be found to be small, as we shall see in
+our chapter on geographical distribution; yet of these species a very large
+proportion are endemic,--that is, have been produced there, and nowhere
+else.  Hence an oceanic island at first sight seems to have been highly
+favourable for the production of new species.  But we may thus greatly
+deceive ourselves, for to ascertain whether a small isolated area, or a
+large open area like a continent, has been most favourable for the
+production of new organic forms, we ought to make the comparison within
+equal times; and this we are incapable of doing.
+</para>
+
+<para>
+Although I do not doubt that isolation is of considerable importance in the
+production of new species, on the whole I am inclined to believe that
+largeness of area is of more importance, more especially in the production
+of species, which will prove capable of enduring for a long period, and of
+spreading widely.  Throughout a great and open area, not only will there be
+a better chance of favourable variations arising from the large number of
+individuals of the same species there supported, but the conditions of life
+are infinitely complex from the large number of already existing species;
+and if some of these many species become modified and improved, others will
+have to be improved in a corresponding degree or they will be exterminated. 
+Each new form, also, as soon as it has been much improved, will be able to
+spread over the open and continuous area, and will thus come into
+competition with many others.  Hence more new places will be formed, and
+the competition to fill them will be more severe, on a large than on a
+small and isolated area.  Moreover, great areas, though now continuous,
+owing to oscillations of level, will often have recently existed in a
+broken condition, so that the good effects of isolation will generally, to
+a certain extent, have concurred.  Finally, I conclude that, although small
+isolated areas probably have been in some respects highly favourable for
+the production of new species, yet that the course of modification will
+generally have been more rapid on large areas; and what is more important,
+that the new forms produced on large areas, which already have been
+victorious over many competitors, will be those that will spread most
+widely, will give rise to most new varieties and species, and will thus
+play an important part in the changing history of the organic world.
+</para>
+
+<para>
+We can, perhaps, on these views, understand some facts which will be again
+alluded to in our chapter on geographical distribution; for instance, that
+the productions of the smaller continent of Australia have formerly
+yielded, and apparently are now yielding, before those of the larger
+Europaeo-Asiatic area.  Thus, also, it is that continental productions have
+everywhere become so largely naturalised on islands.  On a small island,
+the race for life will have been less severe, and there will have been less
+modification and less extermination.  Hence, perhaps, it comes that the
+flora of Madeira, according to Oswald Heer, resembles the extinct tertiary
+flora of Europe.  All fresh-water basins, taken together, make a small area
+compared with that of the sea or of the land; and, consequently, the
+competition between fresh-water productions will have been less severe than
+elsewhere; new forms will have been more slowly formed, and old forms more
+slowly exterminated.  And it is in fresh water that we find seven genera of
+Ganoid fishes, remnants of a once preponderant order:  and in fresh water
+we find some of the most anomalous forms now known in the world, as the
+Ornithorhynchus and Lepidosiren, which, like fossils, connect to a certain
+extent orders now widely separated in the natural scale.  These anomalous
+forms may almost be called living fossils; they have endured to the present
+day, from having inhabited a confined area, and from having thus been
+exposed to less severe competition.
+</para>
+
+<para>
+To sum up the circumstances favourable and unfavourable to natural
+selection, as far as the extreme intricacy of the subject permits.  I
+conclude, looking to the future, that for terrestrial productions a large
+continental area, which will probably undergo many oscillations of level,
+and which consequently will exist for long periods in a broken condition,
+will be the most favourable for the production of many new forms of life,
+likely to endure long and to spread widely.  For the area will first have
+existed as a continent, and the inhabitants, at this period numerous in
+individuals and kinds, will have been subjected to very severe competition. 
+When converted by subsidence into large separate islands, there will still
+exist many individuals of the same species on each island:  intercrossing
+on the confines of the range of each species will thus be checked:  after
+physical changes of any kind, immigration will be prevented, so that new
+places in the polity of each island will have to be filled up by
+modifications of the old inhabitants; and time will be allowed for the
+varieties in each to become well modified and perfected.  When, by renewed
+elevation, the islands shall be re-converted into a continental area, there
+will again be severe competition:  the most favoured or improved varieties
+will be enabled to spread:  there will be much extinction of the less
+improved forms, and the relative proportional numbers of the various
+inhabitants of the renewed continent will again be changed; and again there
+will be a fair field for natural selection to improve still further the
+inhabitants, and thus produce new species.
+</para>
+
+<para>
+That natural selection will always act with extreme slowness, I fully
+admit.  Its action depends on there being places in the polity of nature,
+which can be better occupied by some of the inhabitants of the country
+undergoing modification of some kind.  The existence of such places will
+often depend on physical changes, which are generally very slow, and on the
+immigration of better adapted forms having been checked.  But the action of
+natural selection will probably still oftener depend on some of the
+inhabitants becoming slowly modified; the mutual relations of many of the
+other inhabitants being thus disturbed.  Nothing can be effected, unless
+favourable variations occur, and variation itself is apparently always a
+very slow process.  The process will often be greatly retarded by free
+intercrossing.  Many will exclaim that these several causes are amply
+sufficient wholly to stop the action of natural selection.  I do not
+believe so.  On the other hand, I do believe that natural selection will
+always act very slowly, often only at long intervals of time, and generally
+on only a very few of the inhabitants of the same region at the same time. 
+I further believe, that this very slow, intermittent action of natural
+selection accords perfectly well with what geology tells us of the rate and
+manner at which the inhabitants of this world have changed.
+</para>
+
+<para>
+Slow though the process of selection may be, if feeble man can do much by
+his powers of artificial selection, I can see no limit to the amount of
+change, to the beauty and infinite complexity of the coadaptations between
+all organic beings, one with another and with their physical conditions of
+life, which may be effected in the long course of time by nature's power of
+selection.
+</para>
+
+<para>
+Extinction. -- This subject will be more fully discussed in our chapter on
+Geology; but it must be here alluded to from being intimately connected
+with natural selection.  Natural selection acts solely through the
+preservation of variations in some way advantageous, which consequently
+endure.  But as from the high geometrical powers of increase of all organic
+beings, each area is already fully stocked with inhabitants, it follows
+that as each selected and favoured form increases in number, so will the
+less favoured forms decrease and become rare.  Rarity, as geology tells us,
+is the precursor to extinction.  We can, also, see that any form
+represented by few individuals will, during fluctuations in the seasons or
+in the number of its enemies, run a good chance of utter extinction.  But
+we may go further than this; for as new forms are continually and slowly
+being produced, unless we believe that the number of specific forms goes on
+perpetually and almost indefinitely increasing, numbers inevitably must
+become extinct.  That the number of specific forms has not indefinitely
+increased, geology shows us plainly; and indeed we can see reason why they
+should not have thus increased, for the number of places in the polity of
+nature is not indefinitely great,--not that we have any means of knowing
+that any one region has as yet got its maximum of species.  Probably no
+region is as yet fully stocked, for at the Cape of Good Hope, where more
+species of plants are crowded together than in any other quarter of the
+world, some foreign plants have become naturalised, without causing, as far
+as we know, the extinction of any natives.
+</para>
+
+<para>
+Furthermore, the species which are most numerous in individuals will have
+the best chance of producing within any given period favourable variations. 
+We have evidence of this, in the facts given in the second chapter, showing
+that it is the common species which afford the greatest number of recorded
+varieties, or incipient species.  Hence, rare species will be less quickly
+modified or improved within any given period, and they will consequently be
+beaten in the race for life by the modified descendants of the commoner
+species.
+</para>
+
+<para>
+From these several considerations I think it inevitably follows, that as
+new species in the course of time are formed through natural selection,
+others will become rarer and rarer, and finally extinct.  The forms which
+stand in closest competition with those undergoing modification and
+improvement, will naturally suffer most.  And we have seen in the chapter
+on the Struggle for Existence that it is the most closely-allied
+forms,--varieties of the same species, and species of the same genus or of
+related genera,--which, from having nearly the same structure,
+constitution, and habits, generally come into the severest competition with
+each other.  Consequently, each new variety or species, during the progress
+of its formation, will generally press hardest on its nearest kindred, and
+tend to exterminate them.  We see the same process of extermination amongst
+our domesticated productions, through the selection of improved forms by
+man.  Many curious instances could be given showing how quickly new breeds
+of cattle, sheep, and other animals, and varieties of flowers, take the
+place of older and inferior kinds.  In Yorkshire, it is historically known
+that the ancient black cattle were displaced by the long-horns, and that
+these 'were swept away by the short-horns' (I quote the words of an
+agricultural writer) 'as if by some murderous pestilence.'
+</para>
+
+<para>
+Divergence of Character. -- The principle, which I have designated by this
+term, is of high importance on my theory, and explains, as I believe,
+several important facts.  In the first place, varieties, even
+strongly-marked ones, though having somewhat of the character of
+species--as is shown by the hopeless doubts in many cases how to rank
+them--yet certainly differ from each other far less than do good and
+distinct species.  Nevertheless, according to my view, varieties are
+species in the process of formation, or are, as I have called them,
+incipient species.  How, then, does the lesser difference between varieties
+become augmented into the greater difference between species?  That this
+does habitually happen, we must infer from most of the innumerable species
+throughout nature presenting well-marked differences; whereas varieties,
+the supposed prototypes and parents of future well-marked species, present
+slight and ill-defined differences.  Mere chance, as we may call it, might
+cause one variety to differ in some character from its parents, and the
+offspring of this variety again to differ from its parent in the very same
+character and in a greater degree; but this alone would never account for
+so habitual and large an amount of difference as that between varieties of
+the same species and species of the same genus.
+</para>
+
+<para>
+As has always been my practice, let us seek light on this head from our
+domestic productions.  We shall here find something analogous.  A fancier
+is struck by a pigeon having a slightly shorter beak; another fancier is
+struck by a pigeon having a rather longer beak; and on the acknowledged
+principle that 'fanciers do not and will not admire a medium standard, but
+like extremes,' they both go on (as has actually occurred with
+tumbler-pigeons) choosing and breeding from birds with longer and longer
+beaks, or with shorter and shorter beaks.  Again, we may suppose that at an
+early period one man preferred swifter horses; another stronger and more
+bulky horses.  The early differences would be very slight; in the course of
+time, from the continued selection of swifter horses by some breeders, and
+of stronger ones by others, the differences would become greater, and would
+be noted as forming two sub-breeds; finally, after the lapse of centuries,
+the sub-breeds would become converted into two well-established and
+distinct breeds.  As the differences slowly become greater, the inferior
+animals with intermediate characters, being neither very swift nor very
+strong, will have been neglected, and will have tended to disappear.  Here,
+then, we see in man's productions the action of what may be called the
+principle of divergence, causing differences, at first barely appreciable,
+steadily to increase, and the breeds to diverge in character both from each
+other and from their common parent.
+</para>
+
+<para>
+But how, it may be asked, can any analogous principle apply in nature?  I
+believe it can and does apply most efficiently, from the simple
+circumstance that the more diversified the descendants from any one species
+become in structure, constitution, and habits, by so much will they be
+better enabled to seize on many and widely diversified places in the polity
+of nature, and so be enabled to increase in numbers.
+</para>
+
+<para>
+We can clearly see this in the case of animals with simple habits.  Take
+the case of a carnivorous quadruped, of which the number that can be
+supported in any country has long ago arrived at its full average.  If its
+natural powers of increase be allowed to act, it can succeed in increasing
+(the country not undergoing any change in its conditions) only by its
+varying descendants seizing on places at present occupied by other animals: 
+some of them, for instance, being enabled to feed on new kinds of prey,
+either dead or alive; some inhabiting new stations, climbing trees,
+frequenting water, and some perhaps becoming less carnivorous.  The more
+diversified in habits and structure the descendants of our carnivorous
+animal became, the more places they would be enabled to occupy.  What
+applies to one animal will apply throughout all time to all animals--that
+is, if they vary--for otherwise natural selection can do nothing.  So it
+will be with plants.  It has been experimentally proved, that if a plot of
+ground be sown with several distinct genera of grasses, a greater number of
+plants and a greater weight of dry herbage can thus be raised.  The same
+has been found to hold good when first one variety and then several mixed
+varieties of wheat have been sown on equal spaces of ground.  Hence, if any
+one species of grass were to go on varying, and those varieties were
+continually selected which differed from each other in at all the same
+manner as distinct species and genera of grasses differ from each other, a
+greater number of individual plants of this species of grass, including its
+modified descendants, would succeed in living on the same piece of ground. 
+And we well know that each species and each variety of grass is annually
+sowing almost countless seeds; and thus, as it may be said, is striving its
+utmost to increase its numbers.  Consequently, I cannot doubt that in the
+course of many thousands of generations, the most distinct varieties of any
+one species of grass would always have the best chance of succeeding and of
+increasing in numbers, and thus of supplanting the less distinct varieties;
+and varieties, when rendered very distinct from each other, take the rank
+of species.
+</para>
+
+<para>
+The truth of the principle, that the greatest amount of life can be
+supported by great diversification of structure, is seen under many natural
+circumstances.  In an extremely small area, especially if freely open to
+immigration, and where the contest between individual and individual must
+be severe, we always find great diversity in its inhabitants.  For
+instance, I found that a piece of turf, three feet by four in size, which
+had been exposed for many years to exactly the same conditions, supported
+twenty species of plants, and these belonged to eighteen genera and to
+eight orders, which shows how much these plants differed from each other. 
+So it is with the plants and insects on small and uniform islets; and so in
+small ponds of fresh water.  Farmers find that they can raise most food by
+a rotation of plants belonging to the most different orders:  nature
+follows what may be called a simultaneous rotation.  Most of the animals
+and plants which live close round any small piece of ground, could live on
+it (supposing it not to be in any way peculiar in its nature), and may be
+said to be striving to the utmost to live there; but, it is seen, that
+where they come into the closest competition with each other, the
+advantages of diversification of structure, with the accompanying
+differences of habit and constitution, determine that the inhabitants,
+which thus jostle each other most closely, shall, as a general rule, belong
+to what we call different genera and orders.
+</para>
+
+<para>
+The same principle is seen in the naturalisation of plants through man's
+agency in foreign lands.  It might have been expected that the plants which
+have succeeded in becoming naturalised in any land would generally have
+been closely allied to the indigenes; for these are commonly looked at as
+specially created and adapted for their own country.  It might, also,
+perhaps have been expected that naturalised plants would have belonged to a
+few groups more especially adapted to certain stations in their new homes. 
+But the case is very different; and Alph. De Candolle has well remarked in
+his great and admirable work, that floras gain by naturalisation,
+proportionally with the number of the native genera and species, far more
+in new genera than in new species.  To give a single instance:  in the last
+edition of Dr. Asa Gray's 'Manual of the Flora of the Northern United
+States,' 260 naturalised plants are enumerated, and these belong to 162
+genera.  We thus see that these naturalised plants are of a highly
+diversified nature.  They differ, moreover, to a large extent from the
+indigenes, for out of the 162 genera, no less than 100 genera are not there
+indigenous, and thus a large proportional addition is made to the genera of
+these States.
+</para>
+
+<para>
+By considering the nature of the plants or animals which have struggled
+successfully with the indigenes of any country, and have there become
+naturalised, we can gain some crude idea in what manner some of the natives
+would have had to be modified, in order to have gained an advantage over
+the other natives; and we may, I think, at least safely infer that
+diversification of structure, amounting to new generic differences, would
+have been profitable to them.
+</para>
+
+<para>
+The advantage of diversification in the inhabitants of the same region is,
+in fact, the same as that of the physiological division of labour in the
+organs of the same individual body--a subject so well elucidated by Milne
+Edwards.  No physiologist doubts that a stomach by being adapted to digest
+vegetable matter alone, or flesh alone, draws most nutriment from these
+substances.  So in the general economy of any land, the more widely and
+perfectly the animals and plants are diversified for different habits of
+life, so will a greater number of individuals be capable of there
+supporting themselves.  A set of animals, with their organisation but
+little diversified, could hardly compete with a set more perfectly
+diversified in structure.  It may be doubted, for instance, whether the
+Australian marsupials, which are divided into groups differing but little
+from each other, and feebly representing, as Mr. Waterhouse and others have
+remarked, our carnivorous, ruminant, and rodent mammals, could successfully
+compete with these well-pronounced orders.  In the Australian mammals, we
+see the process of diversification in an early and incomplete stage of
+development.
+</para>
+
+<para>
+After the foregoing discussion, which ought to have been much amplified, we
+may, I think, assume that the modified descendants of any one species will
+succeed by so much the better as they become more diversified in structure,
+and are thus enabled to encroach on places occupied by other beings.  Now
+let us see how this principle of great benefit being derived from
+divergence of character, combined with the principles of natural selection
+and of extinction, will tend to act.
+</para>
+
+<para>
+The accompanying diagram will aid us in understanding this rather
+perplexing subject.  Let A to L represent the species of a genus large in
+its own country; these species are supposed to resemble each other in
+unequal degrees, as is so generally the case in nature, and as is
+represented in the diagram by the letters standing at unequal distances.  I
+have said a large genus, because we have seen in the second chapter, that
+on an average more of the species of large genera vary than of small
+genera; and the varying species of the large genera present a greater
+number of varieties.  We have, also, seen that the species, which are the
+commonest and the most widely-diffused, vary more than rare species with
+restricted ranges.  Let (A) be a common, widely-diffused, and varying
+species, belonging to a genus large in its own country.  The little fan of
+diverging dotted lines of unequal lengths proceeding from (A), may
+represent its varying offspring.  The variations are supposed to be
+extremely slight, but of the most diversified nature; they are not supposed
+all to appear simultaneously, but often after long intervals of time; nor
+are they all supposed to endure for equal periods.  Only those variations
+which are in some way profitable will be preserved or naturally selected. 
+And here the importance of the principle of benefit being derived from
+divergence of character comes in; for this will generally lead to the most
+different or divergent variations (represented by the outer dotted lines)
+being preserved and accumulated by natural selection.  When a dotted line
+reaches one of the horizontal lines, and is there marked by a small
+numbered letter, a sufficient amount of variation is supposed to have been
+accumulated to have formed a fairly well-marked variety, such as would be
+thought worthy of record in a systematic work.
+</para>
+
+<para>
+The intervals between the horizontal lines in the diagram, may represent
+each a thousand generations; but it would have been better if each had
+represented ten thousand generations.  After a thousand generations,
+species (A) is supposed to have produced two fairly well-marked varieties,
+namely a1 and m1.  These two varieties will generally continue to be
+exposed to the same conditions which made their parents variable, and the
+tendency to variability is in itself hereditary, consequently they will
+tend to vary, and generally to vary in nearly the same manner as their
+parents varied.  Moreover, these two varieties, being only slightly
+modified forms, will tend to inherit those advantages which made their
+common parent (A) more numerous than most of the other inhabitants of the
+same country; they will likewise partake of those more general advantages
+which made the genus to which the parent-species belonged, a large genus in
+its own country.  And these circumstances we know to be favourable to the
+production of new varieties.
+</para>
+
+<para>
+If, then, these two varieties be variable, the most divergent of their
+variations will generally be preserved during the next thousand
+generations.  And after this interval, variety a1 is supposed in the
+diagram to have produced variety a2, which will, owing to the principle of
+divergence, differ more from (A) than did variety  a1.  Variety m1 is
+supposed to have produced two varieties, namely m2 and s2, differing from
+each other, and more considerably from their common parent (A).  We may
+continue the process by similar steps for any length of time; some of the
+varieties, after each thousand generations, producing only a single
+variety, but in a more and more modified condition, some producing two or
+three varieties, and some failing to produce any.  Thus the varieties or
+modified descendants, proceeding from the common parent (A), will generally
+go on increasing in number and diverging in character.  In the diagram the
+process is represented up to the ten-thousandth generation, and under a
+condensed and simplified form up to the fourteen-thousandth generation.
+</para>
+
+<para>
+But I must here remark that I do not suppose that the process ever goes on
+so regularly as is represented in the diagram, though in itself made
+somewhat irregular.  I am far from thinking that the most divergent
+varieties will invariably prevail and multiply:  a medium form may often
+long endure, and may or may not produce more than one modified descendant;
+for natural selection will always act according to the nature of the places
+which are either unoccupied or not perfectly occupied by other beings; and
+this will depend on infinitely complex relations.  But as a general rule,
+the more diversified in structure the descendants from any one species can
+be rendered, the more places they will be enabled to seize on, and the more
+their modified progeny will be increased.  In our diagram the line of
+succession is broken at regular intervals by small numbered letters marking
+the successive forms which have become sufficiently distinct to be recorded
+as varieties.  But these breaks are imaginary, and might have been inserted
+anywhere, after intervals long enough to have allowed the accumulation of a
+considerable amount of divergent variation.
+</para>
+
+<para>
+As all the modified descendants from a common and widely-diffused species,
+belonging to a large genus, will tend to partake of the same advantages
+which made their parent successful in life, they will generally go on
+multiplying in number as well as diverging in character:  this is
+represented in the diagram by the several divergent branches proceeding
+from (A).  The modified offspring from the later and more highly improved
+branches in the lines of descent, will, it is probable, often take the
+place of, and so destroy, the earlier and less improved branches:  this is
+represented in the diagram by some of the lower branches not reaching to
+the upper horizontal lines.  In some cases I do not doubt that the process
+of modification will be confined to a single line of descent, and the
+number of the descendants will not be increased; although the amount of
+divergent modification may have been increased in the successive
+generations.  This case would be represented in the diagram, if all the
+lines proceeding from (A) were removed, excepting that from a1 to a10.  In
+the same way, for instance, the English race-horse and English pointer have
+apparently both gone on slowly diverging in character from their original
+stocks, without either having given off any fresh branches or races.
+</para>
+
+<para>
+After ten thousand generations, species (A) is supposed to have produced
+three forms, a10, f10, and m10, which, from having diverged in character
+during the successive generations, will have come to differ largely, but
+perhaps unequally, from each other and from their common parent.  If we
+suppose the amount of change between each horizontal line in our diagram to
+be excessively small, these three forms may still be only well-marked
+varieties; or they may have arrived at the doubtful category of
+sub-species; but we have only to suppose the steps in the process of
+modification to be more numerous or greater in amount, to convert these
+three forms into well-defined species:  thus the diagram illustrates the
+steps by which the small differences distinguishing varieties are increased
+into the larger differences distinguishing species.  By continuing the same
+process for a greater number of generations (as shown in the diagram in a
+condensed and simplified manner), we get eight species, marked by the
+letters between a14 and m14, all descended from (A).  Thus, as I believe,
+species are multiplied and genera are formed.
+</para>
+
+<para>
+In a large genus it is probable that more than one species would vary.  In
+the diagram I have assumed that a second species (I) has produced, by
+analogous steps, after ten thousand generations, either two well-marked
+varieties (w10 and z10) or two species, according to the amount of change
+supposed to be represented between the horizontal lines.  After fourteen
+thousand generations, six new species, marked by the letters n14 to z14,
+are supposed to have been produced.  In each genus, the species, which are
+already extremely different in character, will generally tend to produce
+the greatest number of modified descendants; for these will have the best
+chance of filling new and widely different places in the polity of nature: 
+hence in the diagram I have chosen the extreme species (A), and the nearly
+extreme species (I), as those which have largely varied, and have given
+rise to new varieties and species.  The other nine species (marked by
+capital letters) of our original genus, may for a long period continue
+transmitting unaltered descendants; and this is shown in the diagram by the
+dotted lines not prolonged far upwards from want of space.
+</para>
+
+<para>
+But during the process of modification, represented in the diagram, another
+of our principles, namely that of extinction, will have played an important
+part.  As in each fully stocked country natural selection necessarily acts
+by the selected form having some advantage in the struggle for life over
+other forms, there will be a constant tendency in the improved descendants
+of any one species to supplant and exterminate in each stage of descent
+their predecessors and their original parent.  For it should be remembered
+that the competition will generally be most severe between those forms
+which are most nearly related to each other in habits, constitution, and
+structure.  Hence all the intermediate forms between the earlier and later
+states, that is between the less and more improved state of a species, as
+well as the original parent-species itself, will generally tend to become
+extinct.  So it probably will be with many whole collateral lines of
+descent, which will be conquered by later and improved lines of descent. 
+If, however, the modified offspring of a species get into some distinct
+country, or become quickly adapted to some quite new station, in which
+child and parent do not come into competition, both may continue to exist.
+</para>
+
+<para>
+If then our diagram be assumed to represent a considerable amount of
+modification, species (A) and all the earlier varieties will have become
+extinct, having been replaced by eight new species (a14 to m14); and (I)
+will have been replaced by six (n14 to z14) new species.
+</para>
+
+<para>
+But we may go further than this.  The original species of our genus were
+supposed to resemble each other in unequal degrees, as is so generally the
+case in nature; species (A) being more nearly related to B, C, and D, than
+to the other species; and species (I) more to G, H, K, L, than to the
+others.  These two species (A) and (I), were also supposed to be very
+common and widely diffused species, so that they must originally have had
+some advantage over most of the other species of the genus.  Their modified
+descendants, fourteen in number at the fourteen-thousandth generation, will
+probably have inherited some of the same advantages:  they have also been
+modified and improved in a diversified manner at each stage of descent, so
+as to have become adapted to many related places in the natural economy of
+their country.  It seems, therefore, to me extremely probable that they
+will have taken the places of, and thus exterminated, not only their
+parents (A) and (I), but likewise some of the original species which were
+most nearly related to their parents.  Hence very few of the original
+species will have transmitted offspring to the fourteen-thousandth
+generation.  We may suppose that only one (F), of the two species which
+were least closely related to the other nine original species, has
+transmitted descendants to this late stage of descent.
+</para>
+
+<para>
+The new species in our diagram descended from the original eleven species,
+will now be fifteen in number.  Owing to the divergent tendency of natural
+selection, the extreme amount of difference in character between species
+a14 and z14 will be much greater than that between the most different of
+the original eleven species.  The new species, moreover, will be allied to
+each other in a widely different manner.  Of the eight descendants from (A)
+the three marked a14, q14, p14, will be nearly related from having recently
+branched off from a10; b14 and f14, from having diverged at an earlier
+period from a5, will be in some degree distinct from the three first-named
+species; and lastly, o14, e14, and m14, will be nearly related one to the
+other, but from having diverged at the first commencement of the process of
+modification, will be widely different from the other five species, and may
+constitute a sub-genus or even a distinct genus.  
+</para>
+
+<para>
+The six descendants from (I) will form two sub-genera or even genera.  But
+as the original species (I) differed largely from (A), standing nearly at
+the extreme points of the original genus, the six descendants from (I)
+will, owing to inheritance, differ considerably from the eight descendants
+from (A); the two groups, moreover, are supposed to have gone on diverging
+in different directions.  The intermediate species, also (and this is a
+very important consideration), which connected the original species (A) and
+(I), have all become, excepting (F), extinct, and have left no descendants. 
+Hence the six new species descended from (I), and the eight descended from
+(A), will have to be ranked as very distinct genera, or even as distinct
+sub-families.
+</para>
+
+<para>
+Thus it is, as I believe, that two or more genera are produced by descent,
+with modification, from two or more species of the same genus.  And the two
+or more parent-species are supposed to have descended from some one species
+of an earlier genus.  In our diagram, this is indicated by the broken
+lines, beneath the capital letters, converging in sub-branches downwards
+towards a single point; this point representing a single species, the
+supposed single parent of our several new sub-genera and genera.
+</para>
+
+<para>
+It is worth while to reflect for a moment on the character of the new
+species F14, which is supposed not to have diverged much in character, but
+to have retained the form of (F), either unaltered or altered only in a
+slight degree.  In this case, its affinities to the other fourteen new
+species will be of a curious and circuitous nature.  Having descended from
+a form which stood between the two parent-species (A) and (I), now supposed
+to be extinct and unknown, it will be in some degree intermediate in
+character between the two groups descended from these species.  But as
+these two groups have gone on diverging in character from the type of their
+parents, the new species (F14) will not be directly intermediate between
+them, but rather between types of the two groups; and every naturalist will
+be able to bring some such case before his mind.
+</para>
+
+<para>
+In the diagram, each horizontal line has hitherto been supposed to
+represent a thousand generations, but each may represent a million or
+hundred million generations, and likewise a section of the successive
+strata of the earth's crust including extinct remains.  We shall, when we
+come to our chapter on Geology, have to refer again to this subject, and I
+think we shall then see that the diagram throws light on the affinities of
+extinct beings, which, though generally belonging to the same orders, or
+families, or genera, with those now living, yet are often, in some degree,
+intermediate in character between existing groups; and we can understand
+this fact, for the extinct species lived at very ancient epochs when the
+branching lines of descent had diverged less.
+</para>
+
+<para>
+I see no reason to limit the process of modification, as now explained, to
+the formation of genera alone.  If, in our diagram, we suppose the amount
+of change represented by each successive group of diverging dotted lines to
+be very great, the forms marked a14 to p14, those marked b14 and f14, and
+those marked o14 to m14, will form three very distinct genera.  We shall
+also have two very distinct genera descended from (I) and as these latter
+two genera, both from continued divergence of character and from
+inheritance from a different parent, will differ widely from the three
+genera descended from (A), the two little groups of genera will form two
+distinct families, or even orders, according to the amount of divergent
+modification supposed to be represented in the diagram.  And the two new
+families, or orders, will have descended from two species of the original
+genus; and these two species are supposed to have descended from one
+species of a still more ancient and unknown genus.
+</para>
+
+<para>
+We have seen that in each country it is the species of the larger genera
+which oftenest present varieties or incipient species.  This, indeed, might
+have been expected; for as natural selection acts through one form having
+some advantage over other forms in the struggle for existence, it will
+chiefly act on those which already have some advantage; and the largeness
+of any group shows that its species have inherited from a common ancestor
+some advantage in common.  Hence, the struggle for the production of new
+and modified descendants, will mainly lie between the larger groups, which
+are all trying to increase in number.  One large group will slowly conquer
+another large group, reduce its numbers, and thus lessen its chance of
+further variation and improvement.  Within the same large group, the later
+and more highly perfected sub-groups, from branching out and seizing on
+many new places in the polity of Nature, will constantly tend to supplant
+and destroy the earlier and less improved sub-groups.  Small and broken
+groups and sub-groups will finally tend to disappear.  Looking to the
+future, we can predict that the groups of organic beings which are now
+large and triumphant, and which are least broken up, that is, which as yet
+have suffered least extinction, will for a long period continue to
+increase.  But which groups will ultimately prevail, no man can predict;
+for we well know that many groups, formerly most extensively developed,
+have now become extinct.  Looking still more remotely to the future, we may
+predict that, owing to the continued and steady increase of the larger
+groups, a multitude of smaller groups will become utterly extinct, and
+leave no modified descendants; and consequently that of the species living
+at any one period, extremely few will transmit descendants to a remote
+futurity.  I shall have to return to this subject in the chapter on
+Classification, but I may add that on this view of extremely few of the
+more ancient species having transmitted descendants, and on the view of all
+the descendants of the same species making a class, we can understand how
+it is that there exist but very few classes in each main division of the
+animal and vegetable kingdoms.  Although extremely few of the most ancient
+species may now have living and modified descendants, yet at the most
+remote geological period, the earth may have been as well peopled with many
+species of many genera, families, orders, and classes, as at the present
+day.
+</para>
+
+<para>
+Summary of Chapter -- If during the long course of ages and under varying
+conditions of life, organic beings vary at all in the several parts of
+their organisation, and I think this cannot be disputed; if there be, owing
+to the high geometrical powers of increase of each species, at some age,
+season, or year, a severe struggle for life, and this certainly cannot be
+disputed; then, considering the infinite complexity of the relations of all
+organic beings to each other and to their conditions of existence, causing
+an infinite diversity in structure, constitution, and habits, to be
+advantageous to them, I think it would be a most extraordinary fact if no
+variation ever had occurred useful to each being's own welfare, in the same
+way as so many variations have occurred useful to man.  But if variations
+useful to any organic being do occur, assuredly individuals thus
+characterised will have the best chance of being preserved in the struggle
+for life; and from the strong principle of inheritance they will tend to
+produce offspring similarly characterised.  This principle of preservation,
+I have called, for the sake of brevity, Natural Selection.  Natural
+selection, on the principle of qualities being inherited at corresponding
+ages, can modify the egg, seed, or young, as easily as the adult.  Amongst
+many animals, sexual selection will give its aid to ordinary selection, by
+assuring to the most vigorous and best adapted males the greatest number of
+offspring.  Sexual selection will also give characters useful to the males
+alone, in their struggles with other males.
+</para>
+
+<para>
+Whether natural selection has really thus acted in nature, in modifying and
+adapting the various forms of life to their several conditions and
+stations, must be judged of by the general tenour and balance of evidence
+given in the following chapters.  But we already see how it entails
+extinction; and how largely extinction has acted in the world's history,
+geology plainly declares.  Natural selection, also, leads to divergence of
+character; for more living beings can be supported on the same area the
+more they diverge in structure, habits, and constitution, of which we see
+proof by looking at the inhabitants of any small spot or at naturalised
+productions.  Therefore during the modification of the descendants of any
+one species, and during the incessant struggle of all species to increase
+in numbers, the more diversified these descendants become, the better will
+be their chance of succeeding in the battle of life.  Thus the small
+differences distinguishing varieties of the same species, will steadily
+tend to increase till they come to equal the greater differences between
+species of the same genus, or even of distinct genera.
+</para>
+
+<para>
+We have seen that it is the common, the widely-diffused, and widely-ranging
+species, belonging to the larger genera, which vary most; and these will
+tend to transmit to their modified offspring that superiority which now
+makes them dominant in their own countries.  Natural selection, as has just
+been remarked, leads to divergence of character and to much extinction of
+the less improved and intermediate forms of life.  On these principles, I
+believe, the nature of the affinities of all organic beings may be
+explained.  It is a truly wonderful fact--the wonder of which we are apt to
+overlook from familiarity--that all animals and all plants throughout all
+time and space should be related to each other in group subordinate to
+group, in the manner which we everywhere behold--namely, varieties of the
+same species most closely related together, species of the same genus less
+closely and unequally related together, forming sections and sub-genera,
+species of distinct genera much less closely related, and genera related in
+different degrees, forming sub-families, families, orders, sub-classes, and
+classes.  The several subordinate groups in any class cannot be ranked in a
+single file, but seem rather to be clustered round points, and these round
+other points, and so on in almost endless cycles.  On the view that each
+species has been independently created, I can see no explanation of this
+great fact in the classification of all organic beings; but, to the best of
+my judgment, it is explained through inheritance and the complex action of
+natural selection, entailing extinction and divergence of character, as we
+have seen illustrated in the diagram.
+</para>
+
+<para>
+The affinities of all the beings of the same class have sometimes been
+represented by a great tree.  I believe this simile largely speaks the
+truth.  The green and budding twigs may represent existing species; and
+those produced during each former year may represent the long succession of
+extinct species.  At each period of growth all the growing twigs have tried
+to branch out on all sides, and to overtop and kill the surrounding twigs
+and branches, in the same manner as species and groups of species have
+tried to overmaster other species in the great battle for life.  The limbs
+divided into great branches, and these into lesser and lesser branches,
+were themselves once, when the tree was small, budding twigs; and this
+connexion of the former and present buds by ramifying branches may well
+represent the classification of all extinct and living species in groups
+subordinate to groups.  Of the many twigs which flourished when the tree
+was a mere bush, only two or three, now grown into great branches, yet
+survive and bear all the other branches; so with the species which lived
+during long-past geological periods, very few now have living and modified
+descendants.  From the first growth of the tree, many a limb and branch has
+decayed and dropped off; and these lost branches of various sizes may
+represent those whole orders, families, and genera which have now no living
+representatives, and which are known to us only from having been found in a
+fossil state.  As we here and there see a thin straggling branch springing
+from a fork low down in a tree, and which by some chance has been favoured
+and is still alive on its summit, so we occasionally see an animal like the
+Ornithorhynchus or Lepidosiren, which in some small degree connects by its
+affinities two large branches of life, and which has apparently been saved
+from fatal competition by having inhabited a protected station.  As buds
+give rise by growth to fresh buds, and these, if vigorous, branch out and
+overtop on all sides many a feebler branch, so by generation I believe it
+has been with the great Tree of Life, which fills with its dead and broken
+branches the crust of the earth, and covers the surface with its ever
+branching and beautiful ramifications.
+</para>
+
+</chapter>
+
+<chapter>
+<chapheader>
+
+<chapnum>Chapter V</chapnum>
+
+<title>Laws of Variation</title>
+
+<chapsummary>
+Effects of external conditions -- Use and disuse, combined with natural
+selection; organs of flight and of vision -- Acclimatisation -- Correlation
+of growth -- Compensation and economy of growth -- False correlations --
+Multiple, rudimentary, and lowly organised structures variable -- Parts
+developed in an unusual manner are highly variable: specific characters
+more variable than generic:  secondary sexual characters variable --
+Species of the same genus vary in an analogous manner -- Reversions to long
+lost characters -- Summary.
+</chapsummary>
+</chapheader>
+
+<para>
+I have hitherto sometimes spoken as if the variations--so common and
+multiform in organic beings under domestication, and in a lesser degree in
+those in a state of nature--had been due to chance.  This, of course, is a
+wholly incorrect expression, but it serves to acknowledge plainly our
+ignorance of the cause of each particular variation.  Some authors believe
+it to be as much the function of the reproductive system to produce
+individual differences, or very slight deviations of structure, as to make
+the child like its parents.  But the much greater variability, as well as
+the greater frequency of monstrosities, under domestication or cultivation,
+than under nature, leads me to believe that deviations of structure are in
+some way due to the nature of the conditions of life, to which the parents
+and their more remote ancestors have been exposed during several
+generations.  I have remarked in the first chapter--but a long catalogue of
+facts which cannot be here given would be necessary to show the truth of
+the remark--that the reproductive system is eminently susceptible to
+changes in the conditions of life; and to this system being functionally
+disturbed in the parents, I chiefly attribute the varying or plastic
+condition of the offspring.  The male and female sexual elements seem to be
+affected before that union takes place which is to form a new being.  In
+the case of 'sporting' plants, the bud, which in its earliest condition
+does not apparently differ essentially from an ovule, is alone affected. 
+But why, because the reproductive system is disturbed, this or that part
+should vary more or less, we are profoundly ignorant.  Nevertheless, we can
+here and there dimly catch a faint ray of light, and we may feel sure that
+there must be some cause for each deviation of structure, however slight.
+</para>
+
+<para>
+How much direct effect difference of climate, food, &amp;c., produces on any
+being is extremely doubtful.  My impression is, that the effect is
+extremely small in the case of animals, but perhaps rather more in that of
+plants.  We may, at least, safely conclude that such influences cannot have
+produced the many striking and complex co-adaptations of structure between
+one organic being and another, which we see everywhere throughout nature. 
+Some little influence may be attributed to climate, food, &amp;c.:  thus, E.
+Forbes speaks confidently that shells at their southern limit, and when
+living in shallow water, are more brightly coloured than those of the same
+species further north or from greater depths.  Gould believes that birds of
+the same species are more brightly coloured under a clear atmosphere, than
+when living on islands or near the coast.  So with insects, Wollaston is
+convinced that residence near the sea affects their colours.  Moquin-Tandon
+gives a list of plants which when growing near the sea-shore have their
+leaves in some degree fleshy, though not elsewhere fleshy.  Several other
+such cases could be given.
+</para>
+
+<para>
+The fact of varieties of one species, when they range into the zone of
+habitation of other species, often acquiring in a very slight degree some
+of the characters of such species, accords with our view that species of
+all kinds are only well-marked and permanent varieties.  Thus the species
+of shells which are confined to tropical and shallow seas are generally
+brighter-coloured than those confined to cold and deeper seas.  The birds
+which are confined to continents are, according to Mr. Gould,
+brighter-coloured than those of islands.  The insect-species confined to
+sea-coasts, as every collector knows, are often brassy or lurid.  Plants
+which live exclusively on the sea-side are very apt to have fleshy leaves. 
+He who believes in the creation of each species, will have to say that this
+shell, for instance, was created with bright colours for a warm sea; but
+that this other shell became bright-coloured by variation when it ranged
+into warmer or shallower waters.
+</para>
+
+<para>
+When a variation is of the slightest use to a being, we cannot tell how
+much of it to attribute to the accumulative action of natural selection,
+and how much to the conditions of life.  Thus, it is well known to furriers
+that animals of the same species have thicker and better fur the more
+severe the climate is under which they have lived; but who can tell how
+much of this difference may be due to the warmest-clad individuals having
+been favoured and preserved during many generations, and how much to the
+direct action of the severe climate? for it would appear that climate has
+some direct action on the hair of our domestic quadrupeds.
+</para>
+
+<para>
+Instances could be given of the same variety being produced under
+conditions of life as different as can well be conceived; and, on the other
+hand, of different varieties being produced from the same species under the
+same conditions.  Such facts show how indirectly the conditions of life
+must act.  Again, innumerable instances are known to every naturalist of
+species keeping true, or not varying at all, although living under the most
+opposite climates.  Such considerations as these incline me to lay very
+little weight on the direct action of the conditions of life.  Indirectly,
+as already remarked, they seem to play an important part in affecting the
+reproductive system, and in thus inducing variability; and natural
+selection will then accumulate all profitable variations, however slight,
+until they become plainly developed and appreciable by us.
+</para>
+
+<para>
+Effects of Use and Disuse. -- From the facts alluded to in the first
+chapter, I think there can be little doubt that use in our domestic animals
+strengthens and enlarges certain parts, and disuse diminishes them; and
+that such modifications are inherited.  Under free nature, we can have no
+standard of comparison, by which to judge of the effects of long-continued
+use or disuse, for we know not the parent-forms; but many animals have
+structures which can be explained by the effects of disuse.  As Professor
+Owen has remarked, there is no greater anomaly in nature than a bird that
+cannot fly; yet there are several in this state.  The logger-headed duck of
+South America can only flap along the surface of the water, and has its
+wings in nearly the same condition as the domestic Aylesbury duck.  As the
+larger ground-feeding birds seldom take flight except to escape danger, I
+believe that the nearly wingless condition of several birds, which now
+inhabit or have lately inhabited several oceanic islands, tenanted by no
+beast of prey, has been caused by disuse.  The ostrich indeed inhabits
+continents and is exposed to danger from which it cannot escape by flight,
+but by kicking it can defend itself from enemies, as well as any of the
+smaller quadrupeds.  We may imagine that the early progenitor of the
+ostrich had habits like those of a bustard, and that as natural selection
+increased in successive generations the size and weight of its body, its
+legs were used more, and its wings less, until they became incapable of
+flight.
+</para>
+
+<para>
+Kirby has remarked (and I have observed the same fact) that the anterior
+tarsi, or feet, of many male dung-feeding beetles are very often broken
+off; he examined seventeen specimens in his own collection, and not one had
+even a relic left.  In the Onites apelles the tarsi are so habitually lost,
+that the insect has been described as not having them.  In some other
+genera they are present, but in a rudimentary condition.  In the Ateuchus
+or sacred beetle of the Egyptians, they are totally deficient.  There is
+not sufficient evidence to induce us to believe that mutilations are ever
+inherited; and I should prefer explaining the entire absence of the
+anterior tarsi in Ateuchus, and their rudimentary condition in some other
+genera, by the long-continued effects of disuse in their progenitors; for
+as the tarsi are almost always lost in many dung-feeding beetles, they must
+be lost early in life, and therefore cannot be much used by these insects.
+</para>
+
+<para>
+In some cases we might easily put down to disuse modifications of structure
+which are wholly, or mainly, due to natural selection.  Mr. Wollaston has
+discovered the remarkable fact that 200 beetles, out of the 550 species
+inhabiting Madeira, are so far deficient in wings that they cannot fly; and
+that of the twenty-nine endemic genera, no less than twenty-three genera
+have all their species in this condition!  Several facts, namely, that
+beetles in many parts of the world are very frequently blown to sea and
+perish; that the beetles in Madeira, as observed by Mr. Wollaston, lie much
+concealed, until the wind lulls and the sun shines; that the proportion of
+wingless beetles is larger on the exposed Dezertas than in Madeira itself;
+and especially the extraordinary fact, so strongly insisted on by Mr.
+Wollaston, of the almost entire absence of certain large groups of beetles,
+elsewhere excessively numerous, and which groups have habits of life almost
+necessitating frequent flight;--these several considerations have made me
+believe that the wingless condition of so many Madeira beetles is mainly
+due to the action of natural selection, but combined probably with disuse. 
+For during thousands of successive generations each individual beetle which
+flew least, either from its wings having been ever so little less perfectly
+developed or from indolent habit, will have had the best chance of
+surviving from not being blown out to sea; and, on the other hand, those
+beetles which most readily took to flight will oftenest have been blown to
+sea and thus have been destroyed.
+</para>
+
+<para>
+The insects in Madeira which are not ground-feeders, and which, as the
+flower-feeding coleoptera and lepidoptera, must habitually use their wings
+to gain their subsistence, have, as Mr. Wollaston suspects, their wings not
+at all reduced, but even enlarged.  This is quite compatible with the
+action of natural selection.  For when a new insect first arrived on the
+island, the tendency of natural selection to enlarge or to reduce the
+wings, would depend on whether a greater number of individuals were saved
+by successfully battling with the winds, or by giving up the attempt and
+rarely or never flying.  As with mariners shipwrecked near a coast, it
+would have been better for the good swimmers if they had been able to swim
+still further, whereas it would have been better for the bad swimmers if
+they had not been able to swim at all and had stuck to the wreck.
+</para>
+
+<para>
+The eyes of moles and of some burrowing rodents are rudimentary in size,
+and in some cases are quite covered up by skin and fur.  This state of the
+eyes is probably due to gradual reduction from disuse, but aided perhaps by
+natural selection.  In South America, a burrowing rodent, the tuco-tuco, or
+Ctenomys, is even more subterranean in its habits than the mole; and I was
+assured by a Spaniard, who had often caught them, that they were frequently
+blind; one which I kept alive was certainly in this condition, the cause,
+as appeared on dissection, having been inflammation of the nictitating
+membrane.  As frequent inflammation of the eyes must be injurious to any
+animal, and as eyes are certainly not indispensable to animals with
+subterranean habits, a reduction in their size with the adhesion of the
+eyelids and growth of fur over them, might in such case be an advantage;
+and if so, natural selection would constantly aid the effects of disuse.
+</para>
+
+<para>
+It is well known that several animals, belonging to the most different
+classes, which inhabit the caves of Styria and of Kentucky, are blind.  In
+some of the crabs the foot-stalk for the eye remains, though the eye is
+gone; the stand for the telescope is there, though the telescope with its
+glasses has been lost.  As it is difficult to imagine that eyes, though
+useless, could be in any way injurious to animals living in darkness, I
+attribute their loss wholly to disuse.  In one of the blind animals,
+namely, the cave-rat, the eyes are of immense size; and Professor Silliman
+thought that it regained, after living some days in the light, some slight
+power of vision.  In the same manner as in Madeira the wings of some of the
+insects have been enlarged, and the wings of others have been reduced by
+natural selection aided by use and disuse, so in the case of the cave-rat
+natural selection seems to have struggled with the loss of light and to
+have increased the size of the eyes; whereas with all the other inhabitants
+of the caves, disuse by itself seems to have done its work.
+</para>
+
+<para>
+It is difficult to imagine conditions of life more similar than deep
+limestone caverns under a nearly similar climate; so that on the common
+view of the blind animals having been separately created for the American
+and European caverns, close similarity in their organisation and affinities
+might have been expected; but, as Schiodte and others have remarked, this
+is not the case, and the cave-insects of the two continents are not more
+closely allied than might have been anticipated from the general
+resemblance of the other inhabitants of North America and Europe.  On my
+view we must suppose that American animals, having ordinary powers of
+vision, slowly migrated by successive generations from the outer world into
+the deeper and deeper recesses of the Kentucky caves, as did European
+animals into the caves of Europe.  We have some evidence of this gradation
+of habit; for, as Schiodte remarks, 'animals not far remote from ordinary
+forms, prepare the transition from light to darkness.  Next follow those
+that are constructed for twilight; and, last of all, those destined for
+total darkness.'  By the time that an animal had reached, after numberless
+generations, the deepest recesses, disuse will on this view have more or
+less perfectly obliterated its eyes, and natural selection will often have
+effected other changes, such as an increase in the length of the antennae
+or palpi, as a compensation for blindness.  Notwithstanding such
+modifications, we might expect still to see in the cave-animals of America,
+affinities to the other inhabitants of that continent, and in those of
+Europe, to the inhabitants of the European continent.  And this is the case
+with some of the American cave-animals, as I hear from Professor Dana; and
+some of the European cave-insects are very closely allied to those of the
+surrounding country.  It would be most difficult to give any rational
+explanation of the affinities of the blind cave-animals to the other
+inhabitants of the two continents on the ordinary view of their independent
+creation.  That several of the inhabitants of the caves of the Old and New
+Worlds should be closely related, we might expect from the well-known
+relationship of most of their other productions.  Far from feeling any
+surprise that some of the cave-animals should be very anomalous, as Agassiz
+has remarked in regard to the blind fish, the Amblyopsis, and as is the
+case with the blind Proteus with reference to the reptiles of Europe, I am
+only surprised that more wrecks of ancient life have not been preserved,
+owing to the less severe competition to which the inhabitants of these dark
+abodes will probably have been exposed.
+</para>
+
+<para>
+Acclimatisation. -- Habit is hereditary with plants, as in the period of
+flowering, in the amount of rain requisite for seeds to germinate, in the
+time of sleep, &amp;c., and this leads me to say a few words on
+acclimatisation.  As it is extremely common for species of the same genus
+to inhabit very hot and very cold countries, and as I believe that all the
+species of the same genus have descended from a single parent, if this view
+be correct, acclimatisation must be readily effected during long-continued
+descent.  It is notorious that each species is adapted to the climate of
+its own home:  species from an arctic or even from a temperate region
+cannot endure a tropical climate, or conversely.  So again, many succulent
+plants cannot endure a damp climate.  But the degree of adaptation of
+species to the climates under which they live is often overrated.  We may
+infer this from our frequent inability to predict whether or not an
+imported plant will endure our climate, and from the number of plants and
+animals brought from warmer countries which here enjoy good health.  We
+have reason to believe that species in a state of nature are limited in
+their ranges by the competition of other organic beings quite as much as,
+or more than, by adaptation to particular climates.  But whether or not the
+adaptation be generally very close, we have evidence, in the case of some
+few plants, of their becoming, to a certain extent, naturally habituated to
+different temperatures, or becoming acclimatised:  thus the pines and
+rhododendrons, raised from seed collected by Dr. Hooker from trees growing
+at different heights on the Himalaya, were found in this country to possess
+different constitutional powers of resisting cold.  Mr. Thwaites informs me
+that he has observed similar facts in Ceylon, and analogous observations
+have been made by Mr. H. C. Watson on European species of plants brought
+from the Azores to England.  In regard to animals, several authentic cases
+could be given of species within historical times having largely extended
+their range from warmer to cooler latitudes, and conversely; but we do not
+positively know that these animals were strictly adapted to their native
+climate, but in all ordinary cases we assume such to be the case; nor do we
+know that they have subsequently become acclimatised to their new homes.
+</para>
+
+<para>
+As I believe that our domestic animals were originally chosen by
+uncivilised man because they were useful and bred readily under
+confinement, and not because they were subsequently found capable of
+far-extended transportation, I think the common and extraordinary capacity
+in our domestic animals of not only withstanding the most different
+climates but of being perfectly fertile (a far severer test) under them,
+may be used as an argument that a large proportion of other animals, now in
+a state of nature, could easily be brought to bear widely different
+climates.  We must not, however, push the foregoing argument too far, on
+account of the probable origin of some of our domestic animals from several
+wild stocks:  the blood, for instance, of a tropical and arctic wolf or
+wild dog may perhaps be mingled in our domestic breeds.  The rat and mouse
+cannot be considered as domestic animals, but they have been transported by
+man to many parts of the world, and now have a far wider range than any
+other rodent, living free under the cold climate of Faroe in the north and
+of the Falklands in the south, and on many islands in the torrid zones. 
+Hence I am inclined to look at adaptation to any special climate as a
+quality readily grafted on an innate wide flexibility of constitution,
+which is common to most animals.  On this view, the capacity of enduring
+the most different climates by man himself and by his domestic animals, and
+such facts as that former species of the elephant and rhinoceros were
+capable of enduring a glacial climate, whereas the living species are now
+all tropical or sub-tropical in their habits, ought not to be looked at as
+anomalies, but merely as examples of a very common flexibility of
+constitution, brought, under peculiar circumstances, into play.
+</para>
+
+<para>
+How much of the acclimatisation of species to any peculiar climate is due
+to mere habit, and how much to the natural selection of varieties having
+different innate constitutions, and how much to both means combined, is a
+very obscure question.  That habit or custom has some influence I must
+believe, both from analogy, and from the incessant advice given in
+agricultural works, even in the ancient Encyclopaedias of China, to be very
+cautious in transposing animals from one district to another; for it is not
+likely that man should have succeeded in selecting so many breeds and
+sub-breeds with constitutions specially fitted for their own districts: 
+the result must, I think, be due to habit.  On the other hand, I can see no
+reason to doubt that natural selection will continually tend to preserve
+those individuals which are born with constitutions best adapted to their
+native countries.  In treatises on many kinds of cultivated plants, certain
+varieties are said to withstand certain climates better than others:  this
+is very strikingly shown in works on fruit trees published in the United
+States, in which certain varieties are habitually recommended for the
+northern, and others for the southern States; and as most of these
+varieties are of recent origin, they cannot owe their constitutional
+differences to habit.  The case of the Jerusalem artichoke, which is never
+propagated by seed, and of which consequently new varieties have not been
+produced, has even been advanced--for it is now as tender as ever it
+was--as proving that acclimatisation cannot be effected!  The case, also,
+of the kidney-bean has been often cited for a similar purpose, and with
+much greater weight; but until some one will sow, during a score of
+generations, his kidney-beans so early that a very large proportion are
+destroyed by frost, and then collect seed from the few survivors, with care
+to prevent accidental crosses, and then again get seed from these
+seedlings, with the same precautions, the experiment cannot be said to have
+been even tried.  Nor let it be supposed that no differences in the
+constitution of seedling kidney-beans ever appear, for an account has been
+published how much more hardy some seedlings appeared to be than others.
+</para>
+
+<para>
+On the whole, I think we may conclude that habit, use, and disuse, have, in
+some cases, played a considerable part in the modification of the
+constitution, and of the structure of various organs; but that the effects
+of use and disuse have often been largely combined with, and sometimes
+overmastered by, the natural selection of innate differences.
+</para>
+
+<para>
+Correlation of Growth. -- I mean by this expression that the whole
+organisation is so tied together during its growth and development, that
+when slight variations in any one part occur, and are accumulated through
+natural selection, other parts become modified.  This is a very important
+subject, most imperfectly understood.  The most obvious case is, that
+modifications accumulated solely for the good of the young or larva, will,
+it may safely be concluded, affect the structure of the adult; in the same
+manner as any malconformation affecting the early embryo, seriously affects
+the whole organisation of the adult.  The several parts of the body which
+are homologous, and which, at an early embryonic period, are alike, seem
+liable to vary in an allied manner:  we see this in the right and left
+sides of the body varying in the same manner; in the front and hind legs,
+and even in the jaws and limbs, varying together, for the lower jaw is
+believed to be homologous with the limbs.  These tendencies, I do not
+doubt, may be mastered more or less completely by natural selection:  thus
+a family of stags once existed with an antler only on one side; and if this
+had been of any great use to the breed it might probably have been rendered
+permanent by natural selection.
+</para>
+
+<para>
+Homologous parts, as has been remarked by some authors, tend to cohere;
+this is often seen in monstrous plants; and nothing is more common than the
+union of homologous parts in normal structures, as the union of the petals
+of the corolla into a tube.  Hard parts seem to affect the form of
+adjoining soft parts; it is believed by some authors that the diversity in
+the shape of the pelvis in birds causes the remarkable diversity in the
+shape of their kidneys.  Others believe that the shape of the pelvis in the
+human mother influences by pressure the shape of the head of the child.  In
+snakes, according to Schlegel, the shape of the body and the manner of
+swallowing determine the position of several of the most important viscera.
+</para>
+
+<para>
+The nature of the bond of correlation is very frequently quite obscure.  M.
+Is. Geoffroy St. Hilaire has forcibly remarked, that certain
+malconformations very frequently, and that others rarely coexist, without
+our being able to assign any reason.  What can be more singular than the
+relation between blue eyes and deafness in cats, and the tortoise-shell
+colour with the female sex; the feathered feet and skin between the outer
+toes in pigeons, and the presence of more or less down on the young birds
+when first hatched, with the future colour of their plumage; or, again, the
+relation between the hair and teeth in the naked Turkish dog, though here
+probably homology comes into play?  With respect to this latter case of
+correlation, I think it can hardly be accidental, that if we pick out the
+two orders of mammalia which are most abnormal in their dermal coverings,
+viz. Cetacea (whales) and Edentata (armadilloes, scaly ant-eaters, &amp;c.),
+that these are likewise the most abnormal in their teeth.
+</para>
+
+<para>
+I know of no case better adapted to show the importance of the laws of
+correlation in modifying important structures, independently of utility
+and, therefore, of natural selection, than that of the difference between
+the outer and inner flowers in some Compositous and Umbelliferous plants. 
+Every one knows the difference in the ray and central florets of, for
+instance, the daisy, and this difference is often accompanied with the
+abortion of parts of the flower.  But, in some Compositous plants, the
+seeds also differ in shape and sculpture; and even the ovary itself, with
+its accessory parts, differs, as has been described by Cassini.  These
+differences have been attributed by some authors to pressure, and the shape
+of the seeds in the ray-florets in some Compositae countenances this idea;
+but, in the case of the corolla of the Umbelliferae, it is by no means, as
+Dr. Hooker informs me, in species with the densest heads that the inner and
+outer flowers most frequently differ.  It might have been thought that the
+development of the ray-petals by drawing nourishment from certain other
+parts of the flower had caused their abortion; but in some Compositae there
+is a difference in the seeds of the outer and inner florets without any
+difference in the corolla.  Possibly, these several differences may be
+connected with some difference in the flow of nutriment towards the central
+and external flowers:  we know, at least, that in irregular flowers, those
+nearest to the axis are oftenest subject to peloria, and become regular.  I
+may add, as an instance of this, and of a striking case of correlation,
+that I have recently observed in some garden pelargoniums, that the central
+flower of the truss often loses the patches of darker colour in the two
+upper petals; and that when this occurs, the adherent nectary is quite
+aborted; when the colour is absent from only one of the two upper petals,
+the nectary is only much shortened.
+</para>
+
+<para>
+With respect to the difference in the corolla of the central and exterior
+flowers of a head or umbel, I do not feel at all sure that C. C. Sprengel's
+idea that the ray-florets serve to attract insects, whose agency is highly
+advantageous in the fertilisation of plants of these two orders, is so
+far-fetched, as it may at first appear:  and if it be advantageous, natural
+selection may have come into play.  But in regard to the differences both
+in the internal and external structure of the seeds, which are not always
+correlated with any differences in the flowers, it seems impossible that
+they can be in any way advantageous to the plant:  yet in the Umbelliferae
+these differences are of such apparent importance--the seeds being in some
+cases, according to Tausch, orthospermous in the exterior flowers and
+coelospermous in the central flowers,--that the elder De Candolle founded
+his main divisions of the order on analogous differences.  Hence we see
+that modifications of structure, viewed by systematists as of high value,
+may be wholly due to unknown laws of correlated growth, and without being,
+as far as we can see, of the slightest service to the species.
+</para>
+
+<para>
+We may often falsely attribute to correlation of growth, structures which
+are common to whole groups of species, and which in truth are simply due to
+inheritance; for an ancient progenitor may have acquired through natural
+selection some one modification in structure, and, after thousands of
+generations, some other and independent modification; and these two
+modifications, having been transmitted to a whole group of descendants with
+diverse habits, would naturally be thought to be correlated in some
+necessary manner.  So, again, I do not doubt that some apparent
+correlations, occurring throughout whole orders, are entirely due to the
+manner alone in which natural selection can act.  For instance, Alph. De
+Candolle has remarked that winged seeds are never found in fruits which do
+not open:  I should explain the rule by the fact that seeds could not
+gradually become winged through natural selection, except in fruits which
+opened; so that the individual plants producing seeds which were a little
+better fitted to be wafted further, might get an advantage over those
+producing seed less fitted for dispersal; and this process could not
+possibly go on in fruit which did not open.
+</para>
+
+<para>
+The elder Geoffroy and Goethe propounded, at about the same period, their
+law of compensation or balancement of growth; or, as Goethe expressed it,
+'in order to spend on one side, nature is forced to economise on the other
+side.'  I think this holds true to a certain extent with our domestic
+productions:  if nourishment flows to one part or organ in excess, it
+rarely flows, at least in excess, to another part; thus it is difficult to
+get a cow to give much milk and to fatten readily.  The same varieties of
+the cabbage do not yield abundant and nutritious foliage and a copious
+supply of oil-bearing seeds.  When the seeds in our fruits become
+atrophied, the fruit itself gains largely in size and quality.  In our
+poultry, a large tuft of feathers on the head is generally accompanied by a
+diminished comb, and a large beard by diminished wattles.  With species in
+a state of nature it can hardly be maintained that the law is of universal
+application; but many good observers, more especially botanists, believe in
+its truth.  I will not, however, here give any instances, for I see hardly
+any way of distinguishing between the effects, on the one hand, of a part
+being largely developed through natural selection and another and adjoining
+part being reduced by this same process or by disuse, and, on the other
+hand, the actual withdrawal of nutriment from one part owing to the excess
+of growth in another and adjoining part.
+</para>
+
+<para>
+I suspect, also, that some of the cases of compensation which have been
+advanced, and likewise some other facts, may be merged under a more general
+principle, namely, that natural selection is continually trying to
+economise in every part of the organisation.  If under changed conditions
+of life a structure before useful becomes less useful, any diminution,
+however slight, in its development, will be seized on by natural selection,
+for it will profit the individual not to have its nutriment wasted in
+building up an useless structure.  I can thus only understand a fact with
+which I was much struck when examining cirripedes, and of which many other
+instances could be given:  namely, that when a cirripede is parasitic
+within another and is thus protected, it loses more or less completely its
+own shell or carapace.  This is the case with the male Ibla, and in a truly
+extraordinary manner with the Proteolepas:  for the carapace in all other
+cirripedes consists of the three highly-important anterior segments of the
+head enormously developed, and furnished with great nerves and muscles; but
+in the parasitic and protected Proteolepas, the whole anterior part of the
+head is reduced to the merest rudiment attached to the bases of the
+prehensile antennae.  Now the saving of a large and complex structure, when
+rendered superfluous by the parasitic habits of the Proteolepas, though
+effected by slow steps, would be a decided advantage to each successive
+individual of the species; for in the struggle for life to which every
+animal is exposed, each individual Proteolepas would have a better chance
+of supporting itself, by less nutriment being wasted in developing a
+structure now become useless.
+</para>
+
+<para>
+Thus, as I believe, natural selection will always succeed in the long run
+in reducing and saving every part of the organisation, as soon as it is
+rendered superfluous, without by any means causing some other part to be
+largely developed in a corresponding degree.  And, conversely, that natural
+selection may perfectly well succeed in largely developing any organ,
+without requiring as a necessary compensation the reduction of some
+adjoining part.
+</para>
+
+<para>
+It seems to be a rule, as remarked by Is. Geoffroy St. Hilaire, both in
+varieties and in species, that when any part or organ is repeated many
+times in the structure of the same individual (as the vertebrae in snakes,
+and the stamens in polyandrous flowers) the number is variable; whereas the
+number of the same part or organ, when it occurs in lesser numbers, is
+constant.  The same author and some botanists have further remarked that
+multiple parts are also very liable to variation in structure.  Inasmuch as
+this 'vegetative repetition,' to use Prof. Owen's expression, seems to be a
+sign of low organisation; the foregoing remark seems connected with the
+very general opinion of naturalists, that beings low in the scale of nature
+are more variable than those which are higher.  I presume that lowness in
+this case means that the several parts of the organisation have been but
+little specialised for particular functions; and as long as the same part
+has to perform diversified work, we can perhaps see why it should remain
+variable, that is, why natural selection should have preserved or rejected
+each little deviation of form less carefully than when the part has to
+serve for one special purpose alone.  In the same way that a knife which
+has to cut all sorts of things may be of almost any shape; whilst a tool
+for some particular object had better be of some particular shape.  Natural
+selection, it should never be forgotten, can act on each part of each
+being, solely through and for its advantage.
+</para>
+
+<para>
+Rudimentary parts, it has been stated by some authors, and I believe with
+truth, are apt to be highly variable.  We shall have to recur to the
+general subject of rudimentary and aborted organs; and I will here only add
+that their variability seems to be owing to their uselessness, and
+therefore to natural selection having no power to check deviations in their
+structure.  Thus rudimentary parts are left to the free play of the various
+laws of growth, to the effects of long-continued disuse, and to the
+tendency to reversion.
+</para>
+
+<para>
+A part developed in any species in an extraordinary degree or manner, in
+comparison with the same part in allied species, tends to be highly
+variable. -- Several years ago I was much struck with a remark, nearly to
+the above effect, published by Mr. Waterhouse.  I infer also from an
+observation made by Professor Owen, with respect to the length of the arms
+of the ourang-outang, that he has come to a nearly similar conclusion.  It
+is hopeless to attempt to convince any one of the truth of this proposition
+without giving the long array of facts which I have collected, and which
+cannot possibly be here introduced.  I can only state my conviction that it
+is a rule of high generality.  I am aware of several causes of error, but I
+hope that I have made due allowance for them.  It should be understood that
+the rule by no means applies to any part, however unusually developed,
+unless it be unusually developed in comparison with the same part in
+closely allied species.  Thus, the bat's wing is a most abnormal structure
+in the class mammalia; but the rule would not here apply, because there is
+a whole group of bats having wings; it would apply only if some one species
+of bat had its wings developed in some remarkable manner in comparison with
+the other species of the same genus.  The rule applies very strongly in the
+case of secondary sexual characters, when displayed in any unusual manner. 
+The term, secondary sexual characters, used by Hunter, applies to
+characters which are attached to one sex, but are not directly connected
+with the act of reproduction.  The rule applies to males and females; but
+as females more rarely offer remarkable secondary sexual characters, it
+applies more rarely to them.  The rule being so plainly applicable in the
+case of secondary sexual characters, may be due to the great variability of
+these characters, whether or not displayed in any unusual manner--of which
+fact I think there can be little doubt.  But that our rule is not confined
+to secondary sexual characters is clearly shown in the case of
+hermaphrodite cirripedes; and I may here add, that I particularly attended
+to Mr. Waterhouse's remark, whilst investigating this Order, and I am fully
+convinced that the rule almost invariably holds good with cirripedes.  I
+shall, in my future work, give a list of the more remarkable cases; I will
+here only briefly give one, as it illustrates the rule in its largest
+application.  The opercular valves of sessile cirripedes (rock barnacles)
+are, in every sense of the word, very important structures, and they differ
+extremely little even in different genera; but in the several species of
+one genus, Pyrgoma, these valves present a marvellous amount of
+diversification:  the homologous valves in the different species being
+sometimes wholly unlike in shape; and the amount of variation in the
+individuals of several of the species is so great, that it is no
+exaggeration to state that the varieties differ more from each other in the
+characters of these important valves than do other species of distinct
+genera.
+</para>
+
+<para>
+As birds within the same country vary in a remarkably small degree, I have
+particularly attended to them, and the rule seems to me certainly to hold
+good in this class.  I cannot make out that it applies to plants, and this
+would seriously have shaken my belief in its truth, had not the great
+variability in plants made it particularly difficult to compare their
+relative degrees of variability.
+</para>
+
+<para>
+When we see any part or organ developed in a remarkable degree or manner in
+any species, the fair presumption is that it is of high importance to that
+species; nevertheless the part in this case is eminently liable to
+variation.  Why should this be so?  On the view that each species has been
+independently created, with all its parts as we now see them, I can see no
+explanation.  But on the view that groups of species have descended from
+other species, and have been modified through natural selection, I think we
+can obtain some light.  In our domestic animals, if any part, or the whole
+animal, be neglected and no selection be applied, that part (for instance,
+the comb in the Dorking fowl) or the whole breed will cease to have a
+nearly uniform character.  The breed will then be said to have degenerated. 
+In rudimentary organs, and in those which have been but little specialised
+for any particular purpose, and perhaps in polymorphic groups, we see a
+nearly parallel natural case; for in such cases natural selection either
+has not or cannot come into full play, and thus the organisation is left in
+a fluctuating condition.  But what here more especially concerns us is,
+that in our domestic animals those points, which at the present time are
+undergoing rapid change by continued selection, are also eminently liable
+to variation.  Look at the breeds of the pigeon; see what a prodigious
+amount of difference there is in the beak of the different tumblers, in the
+beak and wattle of the different carriers, in the carriage and tail of our
+fantails, &amp;c., these being the points now mainly attended to by English
+fanciers.  Even in the sub-breeds, as in the short-faced tumbler, it is
+notoriously difficult to breed them nearly to perfection, and frequently
+individuals are born which depart widely from the standard.  There may be
+truly said to be a constant struggle going on between, on the one hand, the
+tendency to reversion to a less modified state, as well as an innate
+tendency to further variability of all kinds, and, on the other hand, the
+power of steady selection to keep the breed true.  In the long run
+selection gains the day, and we do not expect to fail so far as to breed a
+bird as coarse as a common tumbler from a good short-faced strain.  But as
+long as selection is rapidly going on, there may always be expected to be
+much variability in the structure undergoing modification.  It further
+deserves notice that these variable characters, produced by man's
+selection, sometimes become attached, from causes quite unknown to us, more
+to one sex than to the other, generally to the male sex, as with the wattle
+of carriers and the enlarged crop of pouters.
+</para>
+
+<para>
+Now let us turn to nature.  When a part has been developed in an
+extraordinary manner in any one species, compared with the other species of
+the same genus, we may conclude that this part has undergone an
+extraordinary amount of modification, since the period when the species
+branched off from the common progenitor of the genus.  This period will
+seldom be remote in any extreme degree, as species very rarely endure for
+more than one geological period.  An extraordinary amount of modification
+implies an unusually large and long-continued amount of variability, which
+has continually been accumulated by natural selection for the benefit of
+the species.  But as the variability of the extraordinarily-developed part
+or organ has been so great and long-continued within a period not
+excessively remote, we might, as a general rule, expect still to find more
+variability in such parts than in other parts of the organisation, which
+have remained for a much longer period nearly constant.  And this, I am
+convinced, is the case.  That the struggle between natural selection on the
+one hand, and the tendency to reversion and variability on the other hand,
+will in the course of time cease; and that the most abnormally developed
+organs may be made constant, I can see no reason to doubt.  Hence when an
+organ, however abnormal it may be, has been transmitted in approximately
+the same condition to many modified descendants, as in the case of the wing
+of the bat, it must have existed, according to my theory, for an immense
+period in nearly the same state; and thus it comes to be no more variable
+than any other structure.  It is only in those cases in which the
+modification has been comparatively recent and extraordinarily great that
+we ought to find the generative variability, as it may be called, still
+present in a high degree.  For in this case the variability will seldom as
+yet have been fixed by the continued selection of the individuals varying
+in the required manner and degree, and by the continued rejection of those
+tending to revert to a former and less modified condition.
+</para>
+
+<para>
+The principle included in these remarks may be extended.  It is notorious
+that specific characters are more variable than generic.  To explain by a
+simple example what is meant.  If some species in a large genus of plants
+had blue flowers and some had red, the colour would be only a specific
+character, and no one would be surprised at one of the blue species varying
+into red, or conversely; but if all the species had blue flowers, the
+colour would become a generic character, and its variation would be a more
+unusual circumstance.  I have chosen this example because an explanation is
+not in this case applicable, which most naturalists would advance, namely,
+that specific characters are more variable than generic, because they are
+taken from parts of less physiological importance than those commonly used
+for classing genera.  I believe this explanation is partly, yet only
+indirectly, true; I shall, however, have to return to this subject in our
+chapter on Classification.  It would be almost superfluous to adduce
+evidence in support of the above statement, that specific characters are
+more variable than generic; but I have repeatedly noticed in works on
+natural history, that when an author has remarked with surprise that some
+important organ or part, which is generally very constant throughout large
+groups of species, has differed considerably in closely-allied species,
+that it has, also, been variable in the individuals of some of the species. 
+And this fact shows that a character, which is generally of generic value,
+when it sinks in value and becomes only of specific value, often becomes
+variable, though its physiological importance may remain the same. 
+Something of the same kind applies to monstrosities:  at least Is. Geoffroy
+St. Hilaire seems to entertain no doubt, that the more an organ normally
+differs in the different species of the same group, the more subject it is
+to individual anomalies.
+</para>
+
+<para>
+On the ordinary view of each species having been independently created, why
+should that part of the structure, which differs from the same part in
+other independently-created species of the same genus, be more variable
+than those parts which are closely alike in the several species?  I do not
+see that any explanation can be given.  But on the view of species being
+only strongly marked and fixed varieties, we might surely expect to find
+them still often continuing to vary in those parts of their structure which
+have varied within a moderately recent period, and which have thus come to
+differ.  Or to state the case in another manner:--the points in which all
+the species of a genus resemble each other, and in which they differ from
+the species of some other genus, are called generic characters; and these
+characters in common I attribute to inheritance from a common progenitor,
+for it can rarely have happened that natural selection will have modified
+several species, fitted to more or less widely-different habits, in exactly
+the same manner:  and as these so-called generic characters have been
+inherited from a remote period, since that period when the species first
+branched off from their common progenitor, and subsequently have not varied
+or come to differ in any degree, or only in a slight degree, it is not
+probable that they should vary at the present day.  On the other hand, the
+points in which species differ from other species of the same genus, are
+called specific characters; and as these specific characters have varied
+and come to differ within the period of the branching off of the species
+from a common progenitor, it is probable that they should still often be in
+some degree variable,--at least more variable than those parts of the
+organisation which have for a very long period remained constant.
+</para>
+
+<para>
+In connexion with the present subject, I will make only two other remarks. 
+I think it will be admitted, without my entering on details, that secondary
+sexual characters are very variable; I think it also will be admitted that
+species of the same group differ from each other more widely in their
+secondary sexual characters, than in other parts of their organisation;
+compare, for instance, the amount of difference between the males of
+gallinaceous birds, in which secondary sexual characters are strongly
+displayed, with the amount of difference between their females; and the
+truth of this proposition will be granted.  The cause of the original
+variability of secondary sexual characters is not manifest; but we can see
+why these characters should not have been rendered as constant and uniform
+as other parts of the organisation; for secondary sexual characters have
+been accumulated by sexual selection, which is less rigid in its action
+than ordinary selection, as it does not entail death, but only gives fewer
+offspring to the less favoured males.  Whatever the cause may be of the
+variability of secondary sexual characters, as they are highly variable,
+sexual selection will have had a wide scope for action, and may thus
+readily have succeeded in giving to the species of the same group a greater
+amount of difference in their sexual characters, than in other parts of
+their structure.
+</para>
+
+<para>
+It is a remarkable fact, that the secondary sexual differences between the
+two sexes of the same species are generally displayed in the very same
+parts of the organisation in which the different species of the same genus
+differ from each other.  Of this fact I will give in illustration two
+instances, the first which happen to stand on my list; and as the
+differences in these cases are of a very unusual nature, the relation can
+hardly be accidental.  The same number of joints in the tarsi is a
+character generally common to very large groups of beetles, but in the
+Engidae, as Westwood has remarked, the number varies greatly; and the
+number likewise differs in the two sexes of the same species:  again in
+fossorial hymenoptera, the manner of neuration of the wings is a character
+of the highest importance, because common to large groups; but in certain
+genera the neuration differs in the different species, and likewise in the
+two sexes of the same species.  This relation has a clear meaning on my
+view of the subject:  I look at all the species of the same genus as having
+as certainly descended from the same progenitor, as have the two sexes of
+any one of the species.  Consequently, whatever part of the structure of
+the common progenitor, or of its early descendants, became variable;
+variations of this part would it is highly probable, be taken advantage of
+by natural and sexual selection, in order to fit the several species to
+their several places in the economy of nature, and likewise to fit the two
+sexes of the same species to each other, or to fit the males and females to
+different habits of life, or the males to struggle with other males for the
+possession of the females.
+</para>
+
+<para>
+Finally, then, I conclude that the greater variability of specific
+characters, or those which distinguish species from species, than of
+generic characters, or those which the species possess in common;--that the
+frequent extreme variability of any part which is developed in a species in
+an extraordinary manner in comparison with the same part in its congeners;
+and the not great degree of variability in a part, however extraordinarily
+it may be developed, if it be common to a whole group of species;--that the
+great variability of secondary sexual characters, and the great amount of
+difference in these same characters between closely allied species;--that
+secondary sexual and ordinary specific differences are generally displayed
+in the same parts of the organisation,--are all principles closely
+connected together.  All being mainly due to the species of the same group
+having descended from a common progenitor, from whom they have inherited
+much in common,--to parts which have recently and largely varied being more
+likely still to go on varying than parts which have long been inherited and
+have not varied,--to natural selection having more or less completely,
+according to the lapse of time, overmastered the tendency to reversion and
+to further variability,--to sexual selection being less rigid than ordinary
+selection,--and to variations in the same parts having been accumulated by
+natural and sexual selection, and thus adapted for secondary sexual, and
+for ordinary specific purposes.
+</para>
+
+<para>
+Distinct species present analogous variations; and a variety of one species
+often assumes some of the characters of an allied species, or reverts to
+some of the characters of an early progenitor. -- These propositions will
+be most readily understood by looking to our domestic races.  The most
+distinct breeds of pigeons, in countries most widely apart, present
+sub-varieties with reversed feathers on the head and feathers on the
+feet,--characters not possessed by the aboriginal rock-pigeon; these then
+are analogous variations in two or more distinct races.  The frequent
+presence of fourteen or even sixteen tail-feathers in the pouter, may be
+considered as a variation representing the normal structure of another
+race, the fantail.  I presume that no one will doubt that all such
+analogous variations are due to the several races of the pigeon having
+inherited from a common parent the same constitution and tendency to
+variation, when acted on by similar unknown influences.  In the vegetable
+kingdom we have a case of analogous variation, in the enlarged stems, or
+roots as commonly called, of the Swedish turnip and Ruta baga, plants which
+several botanists rank as varieties produced by cultivation from a common
+parent:  if this be not so, the case will then be one of analogous
+variation in two so-called distinct species; and to these a third may be
+added, namely, the common turnip.  According to the ordinary view of each
+species having been independently created, we should have to attribute this
+similarity in the enlarged stems of these three plants, not to the vera
+causa of community of descent, and a consequent tendency to vary in a like
+manner, but to three separate yet closely related acts of creation.
+</para>
+
+<para>
+With pigeons, however, we have another case, namely, the occasional
+appearance in all the breeds, of slaty-blue birds with two black bars on
+the wings, a white rump, a bar at the end of the tail, with the outer
+feathers externally edged near their bases with white.  As all these marks
+are characteristic of the parent rock-pigeon, I presume that no one will
+doubt that this is a case of reversion, and not of a new yet analogous
+variation appearing in the several breeds.  We may I think confidently come
+to this conclusion, because, as we have seen, these coloured marks are
+eminently liable to appear in the crossed offspring of two distinct and
+differently coloured breeds; and in this case there is nothing in the
+external conditions of life to cause the reappearance of the slaty-blue,
+with the several marks, beyond the influence of the mere act of crossing on
+the laws of inheritance.
+</para>
+
+<para>
+No doubt it is a very surprising fact that characters should reappear after
+having been lost for many, perhaps for hundreds of generations.  But when a
+breed has been crossed only once by some other breed, the offspring
+occasionally show a tendency to revert in character to the foreign breed
+for many generations--some say, for a dozen or even a score of generations. 
+After twelve generations, the proportion of blood, to use a common
+expression, of any one ancestor, is only 1 in 2048; and yet, as we see, it
+is generally believed that a tendency to reversion is retained by this very
+small proportion of foreign blood.  In a breed which has not been crossed,
+but in which both parents have lost some character which their progenitor
+possessed, the tendency, whether strong or weak, to reproduce the lost
+character might be, as was formerly remarked, for all that we can see to
+the contrary, transmitted for almost any number of generations.  When a
+character which has been lost in a breed, reappears after a great number of
+generations, the most probable hypothesis is, not that the offspring
+suddenly takes after an ancestor some hundred generations distant, but that
+in each successive generation there has been a tendency to reproduce the
+character in question, which at last, under unknown favourable conditions,
+gains an ascendancy.  For instance, it is probable that in each generation
+of the barb-pigeon, which produces most rarely a blue and black-barred
+bird, there has been a tendency in each generation in the plumage to assume
+this colour.  This view is hypothetical, but could be supported by some
+facts; and I can see no more abstract improbability in a tendency to
+produce any character being inherited for an endless number of generations,
+than in quite useless or rudimentary organs being, as we all know them to
+be, thus inherited.  Indeed, we may sometimes observe a mere tendency to
+produce a rudiment inherited:  for instance, in the common snapdragon
+(Antirrhinum) a rudiment of a fifth stamen so often appears, that this
+plant must have an inherited tendency to produce it.
+</para>
+
+<para>
+As all the species of the same genus are supposed, on my theory, to have
+descended from a common parent, it might be expected that they would
+occasionally vary in an analogous manner; so that a variety of one species
+would resemble in some of its characters another species; this other
+species being on my view only a well-marked and permanent variety.  But
+characters thus gained would probably be of an unimportant nature, for the
+presence of all important characters will be governed by natural selection,
+in accordance with the diverse habits of the species, and will not be left
+to the mutual action of the conditions of life and of a similar inherited
+constitution.  It might further be expected that the species of the same
+genus would occasionally exhibit reversions to lost ancestral characters. 
+As, however, we never know the exact character of the common ancestor of a
+group, we could not distinguish these two cases:  if, for instance, we did
+not know that the rock-pigeon was not feather-footed or turn-crowned, we
+could not have told, whether these characters in our domestic breeds were
+reversions or only analogous variations; but we might have inferred that
+the blueness was a case of reversion, from the number of the markings,
+which are correlated with the blue tint, and which it does not appear
+probable would all appear together from simple variation.  More especially
+we might have inferred this, from the blue colour and marks so often
+appearing when distinct breeds of diverse colours are crossed.  Hence,
+though under nature it must generally be left doubtful, what cases are
+reversions to an anciently existing character, and what are new but
+analogous variations, yet we ought, on my theory, sometimes to find the
+varying offspring of a species assuming characters (either from reversion
+or from analogous variation) which already occur in some other members of
+the same group.  And this undoubtedly is the case in nature.
+</para>
+
+<para>
+A considerable part of the difficulty in recognising a variable species in
+our systematic works, is due to its varieties mocking, as it were, some of
+the other species of the same genus.  A considerable catalogue, also, could
+be given of forms intermediate between two other forms, which themselves
+must be doubtfully ranked as either varieties or species; and this shows,
+unless all these forms be considered as independently created species, that
+the one in varying has assumed some of the characters of the other, so as
+to produce the intermediate form.  But the best evidence is afforded by
+parts or organs of an important and uniform nature occasionally varying so
+as to acquire, in some degree, the character of the same part or organ in
+an allied species.  I have collected a long list of such cases; but here,
+as before, I lie under a great disadvantage in not being able to give them. 
+I can only repeat that such cases certainly do occur, and seem to me very
+remarkable.
+</para>
+
+<para>
+I will, however, give one curious and complex case, not indeed as affecting
+any important character, but from occurring in several species of the same
+genus, partly under domestication and partly under nature.  It is a case
+apparently of reversion.  The ass not rarely has very distinct transverse
+bars on its legs, like those on the legs of a zebra:  it has been asserted
+that these are plainest in the foal, and from inquiries which I have made,
+I believe this to be true.  It has also been asserted that the stripe on
+each shoulder is sometimes double.  The shoulder stripe is certainly very
+variable in length and outline.  A white ass, but not an albino, has been
+described without either spinal or shoulder-stripe; and these stripes are
+sometimes very obscure, or actually quite lost, in dark-coloured asses. 
+The koulan of Pallas is said to have been seen with a double
+shoulder-stripe.  The hemionus has no shoulder-stripe; but traces of it, as
+stated by Mr. Blyth and others, occasionally appear:  and I have been
+informed by Colonel Poole that foals of this species are generally striped
+on the legs, and faintly on the shoulder.  The quagga, though so plainly
+barred like a zebra over the body, is without bars on the legs; but Dr.
+Gray has figured one specimen with very distinct zebra-like bars on the
+hocks.
+</para>
+
+<para>
+With respect to the horse, I have collected cases in England of the spinal
+stripe in horses of the most distinct breeds, and of all colours;
+transverse bars on the legs are not rare in duns, mouse-duns, and in one
+instance in a chestnut:  a faint shoulder-stripe may sometimes be seen in
+duns, and I have seen a trace in a bay horse.  My son made a careful
+examination and sketch for me of a dun Belgian cart-horse with a double
+stripe on each shoulder and with leg-stripes; and a man, whom I can
+implicitly trust, has examined for me a small dun Welch pony with three
+short parallel stripes on each shoulder.
+</para>
+
+<para>
+In the north-west part of India the Kattywar breed of horses is so
+generally striped, that, as I hear from Colonel Poole, who examined the
+breed for the Indian Government, a horse without stripes is not considered
+as purely-bred.  The spine is always striped; the legs are generally
+barred; and the shoulder-stripe, which is sometimes double and sometimes
+treble, is common; the side of the face, moreover, is sometimes striped. 
+The stripes are plainest in the foal; and sometimes quite disappear in old
+horses.  Colonel Poole has seen both gray and bay Kattywar horses striped
+when first foaled.  I have, also, reason to suspect, from information given
+me by Mr. W. W. Edwards, that with the English race-horse the spinal stripe
+is much commoner in the foal than in the full-grown animal.  Without here
+entering on further details, I may state that I have collected cases of leg
+and shoulder stripes in horses of very different breeds, in various
+countries from Britain to Eastern China; and from Norway in the north to
+the Malay Archipelago in the south.  In all parts of the world these
+stripes occur far oftenest in duns and mouse-duns; by the term dun a large
+range of colour is included, from one between brown and black to a close
+approach to cream-colour.
+</para>
+
+<para>
+I am aware that Colonel Hamilton Smith, who has written on this subject,
+believes that the several breeds of the horse have descended from several
+aboriginal species--one of which, the dun, was striped; and that the
+above-described appearances are all due to ancient crosses with the dun
+stock.  But I am not at all satisfied with this theory, and should be loth
+to apply it to breeds so distinct as the heavy Belgian cart-horse, Welch
+ponies, cobs, the lanky Kattywar race, &amp;c., inhabiting the most distant
+parts of the world.
+</para>
+
+<para>
+Now let us turn to the effects of crossing the several species of the
+horse-genus.  Rollin asserts, that the common mule from the ass and horse
+is particularly apt to have bars on its legs.  I once saw a mule with its
+legs so much striped that any one at first would have thought that it must
+have been the product of a zebra; and Mr. W. C. Martin, in his excellent
+treatise on the horse, has given a figure of a similar mule.  In four
+coloured drawings, which I have seen, of hybrids between the ass and zebra,
+the legs were much more plainly barred than the rest of the body; and in
+one of them there was a double shoulder-stripe.  In Lord Moreton's famous
+hybrid from a chestnut mare and male quagga, the hybrid, and even the pure
+offspring subsequently produced from the mare by a black Arabian sire, were
+much more plainly barred across the legs than is even the pure quagga. 
+Lastly, and this is another most remarkable case, a hybrid has been figured
+by Dr. Gray (and he informs me that he knows of a second case) from the ass
+and the hemionus; and this hybrid, though the ass seldom has stripes on its
+legs and the hemionus has none and has not even a shoulder-stripe,
+nevertheless had all four legs barred, and had three short
+shoulder-stripes, like those on the dun Welch pony, and even had some
+zebra-like stripes on the sides of its face.  With respect to this last
+fact, I was so convinced that not even a stripe of colour appears from what
+would commonly be called an accident, that I was led solely from the
+occurrence of the face-stripes on this hybrid from the ass and hemionus, to
+ask Colonel Poole whether such face-stripes ever occur in the eminently
+striped Kattywar breed of horses, and was, as we have seen, answered in the
+affirmative.
+</para>
+
+<para>
+What now are we to say to these several facts?  We see several very
+distinct species of the horse-genus becoming, by simple variation, striped
+on the legs like a zebra, or striped on the shoulders like an ass.  In the
+horse we see this tendency strong whenever a dun tint appears--a tint which
+approaches to that of the general colouring of the other species of the
+genus.  The appearance of the stripes is not accompanied by any change of
+form or by any other new character.  We see this tendency to become striped
+most strongly displayed in hybrids from between several of the most
+distinct species.  Now observe the case of the several breeds of pigeons: 
+they are descended from a pigeon (including two or three sub-species or
+geographical races) of a bluish colour, with certain bars and other marks;
+and when any breed assumes by simple variation a bluish tint, these bars
+and other marks invariably reappear; but without any other change of form
+or character.  When the oldest and truest breeds of various colours are
+crossed, we see a strong tendency for the blue tint and bars and marks to
+reappear in the mongrels.  I have stated that the most probable hypothesis
+to account for the reappearance of very ancient characters, is--that there
+is a tendency in the young of each successive generation to produce the
+long-lost character, and that this tendency, from unknown causes, sometimes
+prevails.  And we have just seen that in several species of the horse-genus
+the stripes are either plainer or appear more commonly in the young than in
+the old.  Call the breeds of pigeons, some of which have bred true for
+centuries, species; and how exactly parallel is the case with that of the
+species of the horse-genus!  For myself, I venture confidently to look back
+thousands on thousands of generations, and I see an animal striped like a
+zebra, but perhaps otherwise very differently constructed, the common
+parent of our domestic horse, whether or not it be descended from one or
+more wild stocks, of the ass, the hemionus, quagga, and zebra.
+</para>
+
+<para>
+He who believes that each equine species was independently created, will, I
+presume, assert that each species has been created with a tendency to vary,
+both under nature and under domestication, in this particular manner, so as
+often to become striped like other species of the genus; and that each has
+been created with a strong tendency, when crossed with species inhabiting
+distant quarters of the world, to produce hybrids resembling in their
+stripes, not their own parents, but other species of the genus.  To admit
+this view is, as it seems to me, to reject a real for an unreal, or at
+least for an unknown, cause.  It makes the works of God a mere mockery and
+deception; I would almost as soon believe with the old and ignorant
+cosmogonists, that fossil shells had never lived, but had been created in
+stone so as to mock the shells now living on the sea-shore.
+</para>
+
+<para>
+Summary. -- Our ignorance of the laws of variation is profound.  Not in one
+case out of a hundred can we pretend to assign any reason why this or that
+part differs, more or less, from the same part in the parents.  But
+whenever we have the means of instituting a comparison, the same laws
+appear to have acted in producing the lesser differences between varieties
+of the same species, and the greater differences between species of the
+same genus.  The external conditions of life, as climate and food, &amp;c.,
+seem to have induced some slight modifications.  Habit in producing
+constitutional differences, and use in strengthening, and disuse in
+weakening and diminishing organs, seem to have been more potent in their
+effects.  Homologous parts tend to vary in the same way, and homologous
+parts tend to cohere.  Modifications in hard parts and in external parts
+sometimes affect softer and internal parts.  When one part is largely
+developed, perhaps it tends to draw nourishment from the adjoining parts;
+and every part of the structure which can be saved without detriment to the
+individual, will be saved.  Changes of structure at an early age will
+generally affect parts subsequently developed; and there are very many
+other correlations of growth, the nature of which we are utterly unable to
+understand.  Multiple parts are variable in number and in structure,
+perhaps arising from such parts not having been closely specialised to any
+particular function, so that their modifications have not been closely
+checked by natural selection.  It is probably from this same cause that
+organic beings low in the scale of nature are more variable than those
+which have their whole organisation more specialised, and are higher in the
+scale.  Rudimentary organs, from being useless, will be disregarded by
+natural selection, and hence probably are variable.  Specific
+characters--that is, the characters which have come to differ since the
+several species of the same genus branched off from a common parent--are
+more variable than generic characters, or those which have long been
+inherited, and have not differed within this same period.  In these remarks
+we have referred to special parts or organs being still variable, because
+they have recently varied and thus come to differ; but we have also seen in
+the second Chapter that the same principle applies to the whole individual;
+for in a district where many species of any genus are found--that is, where
+there has been much former variation and differentiation, or where the
+manufactory of new specific forms has been actively at work--there, on an
+average, we now find most varieties or incipient species.  Secondary sexual
+characters are highly variable, and such characters differ much in the
+species of the same group.  Variability in the same parts of the
+organisation has generally been taken advantage of in giving secondary
+sexual differences to the sexes of the same species, and specific
+differences to the several species of the same genus.  Any part or organ
+developed to an extraordinary size or in an extraordinary manner, in
+comparison with the same part or organ in the allied species, must have
+gone through an extraordinary amount of modification since the genus arose;
+and thus we can understand why it should often still be variable in a much
+higher degree than other parts; for variation is a long-continued and slow
+process, and natural selection will in such cases not as yet have had time
+to overcome the tendency to further variability and to reversion to a less
+modified state.  But when a species with any extraordinarily-developed
+organ has become the parent of many modified descendants--which on my view
+must be a very slow process, requiring a long lapse of time--in this case,
+natural selection may readily have succeeded in giving a fixed character to
+the organ, in however extraordinary a manner it may be developed.  Species
+inheriting nearly the same constitution from a common parent and exposed to
+similar influences will naturally tend to present analogous variations, and
+these same species may occasionally revert to some of the characters of
+their ancient progenitors.  Although new and important modifications may
+not arise from reversion and analogous variation, such modifications will
+add to the beautiful and harmonious diversity of nature.
+</para>
+
+<para>
+Whatever the cause may be of each slight difference in the offspring from
+their parents--and a cause for each must exist--it is the steady
+accumulation, through natural selection, of such differences, when
+beneficial to the individual, that gives rise to all the more important
+modifications of structure, by which the innumerable beings on the face of
+this earth are enabled to struggle with each other, and the best adapted to
+survive.
+</para>
+
+</chapter>
+
+<chapter>
+<chapheader>
+
+<chapnum>Chapter VI</chapnum>
+
+<title>Difficulties on Theory</title>
+
+<chapsummary>
+Difficulties on the theory of descent with modification -- Transitions --
+Absence or rarity of transitional varieties -- Transitions in habits of
+life -- Diversified habits in the same species -- Species with habits
+widely different from those of their allies -- Organs of extreme perfection
+-- Means of transition -- Cases of difficulty -- Natura non facit saltum --
+Organs of small importance -- Organs not in all cases absolutely perfect --
+The law of Unity of Type and of the Conditions of Existence embraced by the
+theory of Natural Selection.
+</chapsummary>
+</chapheader>
+
+<para>
+Long before having arrived at this part of my work, a crowd of difficulties
+will have occurred to the reader.  Some of them are so grave that to this
+day I can never reflect on them without being staggered; but, to the best
+of my judgment, the greater number are only apparent, and those that are
+real are not, I think, fatal to my theory.
+</para>
+
+<para>
+These difficulties and objections may be classed under the following
+heads:- Firstly, why, if species have descended from other species by
+insensibly fine gradations, do we not everywhere see innumerable
+transitional forms?  Why is not all nature in confusion instead of the
+species being, as we see them, well defined?
+</para>
+
+<para>
+Secondly, is it possible that an animal having, for instance, the structure
+and habits of a bat, could have been formed by the modification of some
+animal with wholly different habits?  Can we believe that natural selection
+could produce, on the one hand, organs of trifling importance, such as the
+tail of a giraffe, which serves as a fly-flapper, and, on the other hand,
+organs of such wonderful structure, as the eye, of which we hardly as yet
+fully understand the inimitable perfection?
+</para>
+
+<para>
+Thirdly, can instincts be acquired and modified through natural selection? 
+What shall we say to so marvellous an instinct as that which leads the bee
+to make cells, which have practically anticipated the discoveries of
+profound mathematicians?
+</para>
+
+<para>
+Fourthly, how can we account for species, when crossed, being sterile and
+producing sterile offspring, whereas, when varieties are crossed, their
+fertility is unimpaired?
+</para>
+
+<para>
+The two first heads shall be here discussed--Instinct and Hybridism in
+separate chapters.
+</para>
+
+<para>
+On the absence or rarity of transitional varieties. -- As natural selection
+acts solely by the preservation of profitable modifications, each new form
+will tend in a fully-stocked country to take the place of, and finally to
+exterminate, its own less improved parent or other less-favoured forms with
+which it comes into competition.  Thus extinction and natural selection
+will, as we have seen, go hand in hand.  Hence, if we look at each species
+as descended from some other unknown form, both the parent and all the
+transitional varieties will generally have been exterminated by the very
+process of formation and perfection of the new form.
+</para>
+
+<para>
+But, as by this theory innumerable transitional forms must have existed,
+why do we not find them embedded in countless numbers in the crust of the
+earth?  It will be much more convenient to discuss this question in the
+chapter on the Imperfection of the geological record; and I will here only
+state that I believe the answer mainly lies in the record being
+incomparably less perfect than is generally supposed; the imperfection of
+the record being chiefly due to organic beings not inhabiting profound
+depths of the sea, and to their remains being embedded and preserved to a
+future age only in masses of sediment sufficiently thick and extensive to
+withstand an enormous amount of future degradation; and such fossiliferous
+masses can be accumulated only where much sediment is deposited on the
+shallow bed of the sea, whilst it slowly subsides.  These contingencies
+will concur only rarely, and after enormously long intervals.  Whilst the
+bed of the sea is stationary or is rising, or when very little sediment is
+being deposited, there will be blanks in our geological history.  The crust
+of the earth is a vast museum; but the natural collections have been made
+only at intervals of time immensely remote.
+</para>
+
+<para>
+But it may be urged that when several closely-allied species inhabit the
+same territory we surely ought to find at the present time many
+transitional forms.  Let us take a simple case:  in travelling from north
+to south over a continent, we generally meet at successive intervals with
+closely allied or representative species, evidently filling nearly the same
+place in the natural economy of the land.  These representative species
+often meet and interlock; and as the one becomes rarer and rarer, the other
+becomes more and more frequent, till the one replaces the other.  But if we
+compare these species where they intermingle, they are generally as
+absolutely distinct from each other in every detail of structure as are
+specimens taken from the metropolis inhabited by each.  By my theory these
+allied species have descended from a common parent; and during the process
+of modification, each has become adapted to the conditions of life of its
+own region, and has supplanted and exterminated its original parent and all
+the transitional varieties between its past and present states.  Hence we
+ought not to expect at the present time to meet with numerous transitional
+varieties in each region, though they must have existed there, and may be
+embedded there in a fossil condition.  But in the intermediate region,
+having intermediate conditions of life, why do we not now find
+closely-linking intermediate varieties?  This difficulty for a long time
+quite confounded me.  But I think it can be in large part explained.
+</para>
+
+<para>
+In the first place we should be extremely cautious in inferring, because an
+area is now continuous, that it has been continuous during a long period. 
+Geology would lead us to believe that almost every continent has been
+broken up into islands even during the later tertiary periods; and in such
+islands distinct species might have been separately formed without the
+possibility of intermediate varieties existing in the intermediate zones. 
+By changes in the form of the land and of climate, marine areas now
+continuous must often have existed within recent times in a far less
+continuous and uniform condition than at present.  But I will pass over
+this way of escaping from the difficulty; for I believe that many perfectly
+defined species have been formed on strictly continuous areas; though I do
+not doubt that the formerly broken condition of areas now continuous has
+played an important part in the formation of new species, more especially
+with freely-crossing and wandering animals.
+</para>
+
+<para>
+In looking at species as they are now distributed over a wide area, we
+generally find them tolerably numerous over a large territory, then
+becoming somewhat abruptly rarer and rarer on the confines, and finally
+disappearing.  Hence the neutral territory between two representative
+species is generally narrow in comparison with the territory proper to
+each.  We see the same fact in ascending mountains, and sometimes it is
+quite remarkable how abruptly, as Alph. De Candolle has observed, a common
+alpine species disappears.  The same fact has been noticed by Forbes in
+sounding the depths of the sea with the dredge.  To those who look at
+climate and the physical conditions of life as the all-important elements
+of distribution, these facts ought to cause surprise, as climate and height
+or depth graduate away insensibly.  But when we bear in mind that almost
+every species, even in its metropolis, would increase immensely in numbers,
+were it not for other competing species; that nearly all either prey on or
+serve as prey for others; in short, that each organic being is either
+directly or indirectly related in the most important manner to other
+organic beings, we must see that the range of the inhabitants of any
+country by no means exclusively depends on insensibly changing physical
+conditions, but in large part on the presence of other species, on which it
+depends, or by which it is destroyed, or with which it comes into
+competition; and as these species are already defined objects (however they
+may have become so), not blending one into another by insensible
+gradations, the range of any one species, depending as it does on the range
+of others, will tend to be sharply defined.  Moreover, each species on the
+confines of its range, where it exists in lessened numbers, will, during
+fluctuations in the number of its enemies or of its prey, or in the
+seasons, be extremely liable to utter extermination; and thus its
+geographical range will come to be still more sharply defined.
+</para>
+
+<para>
+If I am right in believing that allied or representative species, when
+inhabiting a continuous area, are generally so distributed that each has a
+wide range, with a comparatively narrow neutral territory between them, in
+which they become rather suddenly rarer and rarer; then, as varieties do
+not essentially differ from species, the same rule will probably apply to
+both; and if we in imagination adapt a varying species to a very large
+area, we shall have to adapt two varieties to two large areas, and a third
+variety to a narrow intermediate zone.  The intermediate variety,
+consequently, will exist in lesser numbers from inhabiting a narrow and
+lesser area; and practically, as far as I can make out, this rule holds
+good with varieties in a state of nature.  I have met with striking
+instances of the rule in the case of varieties intermediate between
+well-marked varieties in the genus Balanus.  And it would appear from
+information given me by Mr. Watson, Dr. Asa Gray, and Mr. Wollaston, that
+generally when varieties intermediate between two other forms occur, they
+are much rarer numerically than the forms which they connect.  Now, if we
+may trust these facts and inferences, and therefore conclude that varieties
+linking two other varieties together have generally existed in lesser
+numbers than the forms which they connect, then, I think, we can understand
+why intermediate varieties should not endure for very long periods;--why as
+a general rule they should be exterminated and disappear, sooner than the
+forms which they originally linked together.
+</para>
+
+<para>
+For any form existing in lesser numbers would, as already remarked, run a
+greater chance of being exterminated than one existing in large numbers;
+and in this particular case the intermediate form would be eminently liable
+to the inroads of closely allied forms existing on both sides of it.  But a
+far more important consideration, as I believe, is that, during the process
+of further modification, by which two varieties are supposed on my theory
+to be converted and perfected into two distinct species, the two which
+exist in larger numbers from inhabiting larger areas, will have a great
+advantage over the intermediate variety, which exists in smaller numbers in
+a narrow and intermediate zone.  For forms existing in larger numbers will
+always have a better chance, within any given period, of presenting further
+favourable variations for natural selection to seize on, than will the
+rarer forms which exist in lesser numbers.  Hence, the more common forms,
+in the race for life, will tend to beat and supplant the less common forms,
+for these will be more slowly modified and improved.  It is the same
+principle which, as I believe, accounts for the common species in each
+country, as shown in the second chapter, presenting on an average a greater
+number of well-marked varieties than do the rarer species.  I may
+illustrate what I mean by supposing three varieties of sheep to be kept,
+one adapted to an extensive mountainous region; a second to a comparatively
+narrow, hilly tract; and a third to wide plains at the base; and that the
+inhabitants are all trying with equal steadiness and skill to improve their
+stocks by selection; the chances in this case will be strongly in favour of
+the great holders on the mountains or on the plains improving their breeds
+more quickly than the small holders on the intermediate narrow, hilly
+tract; and consequently the improved mountain or plain breed will soon take
+the place of the less improved hill breed; and thus the two breeds, which
+originally existed in greater numbers, will come into close contact with
+each other, without the interposition of the supplanted, intermediate
+hill-variety.
+</para>
+
+<para>
+To sum up, I believe that species come to be tolerably well-defined
+objects, and do not at any one period present an inextricable chaos of
+varying and intermediate links:  firstly, because new varieties are very
+slowly formed, for variation is a very slow process, and natural selection
+can do nothing until favourable variations chance to occur, and until a
+place in the natural polity of the country can be better filled by some
+modification of some one or more of its inhabitants.  And such new places
+will depend on slow changes of climate, or on the occasional immigration of
+new inhabitants, and, probably, in a still more important degree, on some
+of the old inhabitants becoming slowly modified, with the new forms thus
+produced and the old ones acting and reacting on each other.  So that, in
+any one region and at any one time, we ought only to see a few species
+presenting slight modifications of structure in some degree permanent; and
+this assuredly we do see.
+</para>
+
+<para>
+Secondly, areas now continuous must often have existed within the recent
+period in isolated portions, in which many forms, more especially amongst
+the classes which unite for each birth and wander much, may have separately
+been rendered sufficiently distinct to rank as representative species.  In
+this case, intermediate varieties between the several representative
+species and their common parent, must formerly have existed in each broken
+portion of the land, but these links will have been supplanted and
+exterminated during the process of natural selection, so that they will no
+longer exist in a living state.
+</para>
+
+<para>
+Thirdly, when two or more varieties have been formed in different portions
+of a strictly continuous area, intermediate varieties will, it is probable,
+at first have been formed in the intermediate zones, but they will
+generally have had a short duration.  For these intermediate varieties
+will, from reasons already assigned (namely from what we know of the actual
+distribution of closely allied or representative species, and likewise of
+acknowledged varieties), exist in the intermediate zones in lesser numbers
+than the varieties which they tend to connect.  From this cause alone the
+intermediate varieties will be liable to accidental extermination; and
+during the process of further modification through natural selection, they
+will almost certainly be beaten and supplanted by the forms which they
+connect; for these from existing in greater numbers will, in the aggregate,
+present more variation, and thus be further improved through natural
+selection and gain further advantages.
+</para>
+
+<para>
+Lastly, looking not to any one time, but to all time, if my theory be true,
+numberless intermediate varieties, linking most closely all the species of
+the same group together, must assuredly have existed; but the very process
+of natural selection constantly tends, as has been so often remarked, to
+exterminate the parent forms and the intermediate links.  Consequently
+evidence of their former existence could be found only amongst fossil
+remains, which are preserved, as we shall in a future chapter attempt to
+show, in an extremely imperfect and intermittent record.
+</para>
+
+<para>
+On the origin and transitions of organic beings with peculiar habits and
+structure. -- It has been asked by the opponents of such views as I hold,
+how, for instance, a land carnivorous animal could have been converted into
+one with aquatic habits; for how could the animal in its transitional state
+have subsisted?  It would be easy to show that within the same group
+carnivorous animals exist having every intermediate grade between truly
+aquatic and strictly terrestrial habits; and as each exists by a struggle
+for life, it is clear that each is well adapted in its habits to its place
+in nature.  Look at the Mustela vison of North America, which has webbed
+feet and which resembles an otter in its fur, short legs, and form of tail;
+during summer this animal dives for and preys on fish, but during the long
+winter it leaves the frozen waters, and preys like other polecats on mice
+and land animals.  If a different case had been taken, and it had been
+asked how an insectivorous quadruped could possibly have been converted
+into a flying bat, the question would have been far more difficult, and I
+could have given no answer.  Yet I think such difficulties have very little
+weight.
+</para>
+
+<para>
+Here, as on other occasions, I lie under a heavy disadvantage, for out of
+the many striking cases which I have collected, I can give only one or two
+instances of transitional habits and structures in closely allied species
+of the same genus; and of diversified habits, either constant or
+occasional, in the same species.  And it seems to me that nothing less than
+a long list of such cases is sufficient to lessen the difficulty in any
+particular case like that of the bat.
+</para>
+
+<para>
+Look at the family of squirrels; here we have the finest gradation from
+animals with their tails only slightly flattened, and from others, as Sir
+J. Richardson has remarked, with the posterior part of their bodies rather
+wide and with the skin on their flanks rather full, to the so-called flying
+squirrels; and flying squirrels have their limbs and even the base of the
+tail united by a broad expanse of skin, which serves as a parachute and
+allows them to glide through the air to an astonishing distance from tree
+to tree.  We cannot doubt that each structure is of use to each kind of
+squirrel in its own country, by enabling it to escape birds or beasts of
+prey, or to collect food more quickly, or, as there is reason to believe,
+by lessening the danger from occasional falls.  But it does not follow from
+this fact that the structure of each squirrel is the best that it is
+possible to conceive under all natural conditions.  Let the climate and
+vegetation change, let other competing rodents or new beasts of prey
+immigrate, or old ones become modified, and all analogy would lead us to
+believe that some at least of the squirrels would decrease in numbers or
+become exterminated, unless they also became modified and improved in
+structure in a corresponding manner.  Therefore, I can see no difficulty,
+more especially under changing conditions of life, in the continued
+preservation of individuals with fuller and fuller flank-membranes, each
+modification being useful, each being propagated, until by the accumulated
+effects of this process of natural selection, a perfect so-called flying
+squirrel was produced.
+</para>
+
+<para>
+Now look at the Galeopithecus or flying lemur, which formerly was falsely
+ranked amongst bats.  It has an extremely wide flank-membrane, stretching
+from the corners of the jaw to the tail, and including the limbs and the
+elongated fingers:  the flank membrane is, also, furnished with an extensor
+muscle.  Although no graduated links of structure, fitted for gliding
+through the air, now connect the Galeopithecus with the other Lemuridae,
+yet I can see no difficulty in supposing that such links formerly existed,
+and that each had been formed by the same steps as in the case of the less
+perfectly gliding squirrels; and that each grade of structure had been
+useful to its possessor.  Nor can I see any insuperable difficulty in
+further believing it possible that the membrane-connected fingers and
+fore-arm of the Galeopithecus might be greatly lengthened by natural
+selection; and this, as far as the organs of flight are concerned, would
+convert it into a bat.  In bats which have the wing-membrane extended from
+the top of the shoulder to the tail, including the hind-legs, we perhaps
+see traces of an apparatus originally constructed for gliding through the
+air rather than for flight.
+</para>
+
+<para>
+If about a dozen genera of birds had become extinct or were unknown, who
+would have ventured to have surmised that birds might have existed which
+used their wings solely as flappers, like the logger-headed duck
+(Micropterus of Eyton); as fins in the water and front legs on the land,
+like the penguin; as sails, like the ostrich; and functionally for no
+purpose, like the Apteryx.  Yet the structure of each of these birds is
+good for it, under the conditions of life to which it is exposed, for each
+has to live by a struggle; but it is not necessarily the best possible
+under all possible conditions.  It must not be inferred from these remarks
+that any of the grades of wing-structure here alluded to, which perhaps may
+all have resulted from disuse, indicate the natural steps by which birds
+have acquired their perfect power of flight; but they serve, at least, to
+show what diversified means of transition are possible.
+</para>
+
+<para>
+Seeing that a few members of such water-breathing classes as the Crustacea
+and Mollusca are adapted to live on the land, and seeing that we have
+flying birds and mammals, flying insects of the most diversified types, and
+formerly had flying reptiles, it is conceivable that flying-fish, which now
+glide far through the air, slightly rising and turning by the aid of their
+fluttering fins, might have been modified into perfectly winged animals. 
+If this had been effected, who would have ever imagined that in an early
+transitional state they had been inhabitants of the open ocean, and had
+used their incipient organs of flight exclusively, as far as we know, to
+escape being devoured by other fish?
+</para>
+
+<para>
+When we see any structure highly perfected for any particular habit, as the
+wings of a bird for flight, we should bear in mind that animals displaying
+early transitional grades of the structure will seldom continue to exist to
+the present day, for they will have been supplanted by the very process of
+perfection through natural selection.  Furthermore, we may conclude that
+transitional grades between structures fitted for very different habits of
+life will rarely have been developed at an early period in great numbers
+and under many subordinate forms.  Thus, to return to our imaginary
+illustration of the flying-fish, it does not seem probable that fishes
+capable of true flight would have been developed under many subordinate
+forms, for taking prey of many kinds in many ways, on the land and in the
+water, until their organs of flight had come to a high stage of perfection,
+so as to have given them a decided advantage over other animals in the
+battle for life.  Hence the chance of discovering species with transitional
+grades of structure in a fossil condition will always be less, from their
+having existed in lesser numbers, than in the case of species with fully
+developed structures.
+</para>
+
+<para>
+I will now give two or three instances of diversified and of changed habits
+in the individuals of the same species.  When either case occurs, it would
+be easy for natural selection to fit the animal, by some modification of
+its structure, for its changed habits, or exclusively for one of its
+several different habits.  But it is difficult to tell, and immaterial for
+us, whether habits generally change first and structure afterwards; or
+whether slight modifications of structure lead to changed habits; both
+probably often change almost simultaneously.  Of cases of changed habits it
+will suffice merely to allude to that of the many British insects which now
+feed on exotic plants, or exclusively on artificial substances.  Of
+diversified habits innumerable instances could be given:  I have often
+watched a tyrant flycatcher (Saurophagus sulphuratus) in South America,
+hovering over one spot and then proceeding to another, like a kestrel, and
+at other times standing stationary on the margin of water, and then dashing
+like a kingfisher at a fish.  In our own country the larger titmouse (Parus
+major) may be seen climbing branches, almost like a creeper; it often, like
+a shrike, kills small birds by blows on the head; and I have many times
+seen and heard it hammering the seeds of the yew on a branch, and thus
+breaking them like a nuthatch.  In North America the black bear was seen by
+Hearne swimming for hours with widely open mouth, thus catching, like a
+whale, insects in the water.  Even in so extreme a case as this, if the
+supply of insects were constant, and if better adapted competitors did not
+already exist in the country, I can see no difficulty in a race of bears
+being rendered, by natural selection, more and more aquatic in their
+structure and habits, with larger and larger mouths, till a creature was
+produced as monstrous as a whale.
+</para>
+
+<para>
+As we sometimes see individuals of a species following habits widely
+different from those both of their own species and of the other species of
+the same genus, we might expect, on my theory, that such individuals would
+occasionally have given rise to new species, having anomalous habits, and
+with their structure either slightly or considerably modified from that of
+their proper type.  And such instances do occur in nature.  Can a more
+striking instance of adaptation be given than that of a woodpecker for
+climbing trees and for seizing insects in the chinks of the bark?  Yet in
+North America there are woodpeckers which feed largely on fruit, and others
+with elongated wings which chase insects on the wing; and on the plains of
+La Plata, where not a tree grows, there is a woodpecker, which in every
+essential part of its organisation, even in its colouring, in the harsh
+tone of its voice, and undulatory flight, told me plainly of its close
+blood-relationship to our common species; yet it is a woodpecker which
+never climbs a tree!
+</para>
+
+<para>
+Petrels are the most aerial and oceanic of birds, yet in the quiet Sounds
+of Tierra del Fuego, the Puffinuria berardi, in its general habits, in its
+astonishing power of diving, its manner of swimming, and of flying when
+unwillingly it takes flight, would be mistaken by any one for an auk or
+grebe; nevertheless, it is essentially a petrel, but with many parts of its
+organisation profoundly modified.  On the other hand, the acutest observer
+by examining the dead body of the water-ouzel would never have suspected
+its sub-aquatic habits; yet this anomalous member of the strictly
+terrestrial thrush family wholly subsists by diving,--grasping the stones
+with its feet and using its wings under water.
+</para>
+
+<para>
+He who believes that each being has been created as we now see it, must
+occasionally have felt surprise when he has met with an animal having
+habits and structure not at all in agreement.  What can be plainer than
+that the webbed feet of ducks and geese are formed for swimming? yet there
+are upland geese with webbed feet which rarely or never go near the water;
+and no one except Audubon has seen the frigate-bird, which has all its four
+toes webbed, alight on the surface of the sea.  On the other hand, grebes
+and coots are eminently aquatic, although their toes are only bordered by
+membrane.  What seems plainer than that the long toes of grallatores are
+formed for walking over swamps and floating plants, yet the water-hen is
+nearly as aquatic as the coot; and the landrail nearly as terrestrial as
+the quail or partridge.  In such cases, and many others could be given,
+habits have changed without a corresponding change of structure.  The
+webbed feet of the upland goose may be said to have become rudimentary in
+function, though not in structure.  In the frigate-bird, the deeply-scooped
+membrane between the toes shows that structure has begun to change.
+</para>
+
+<para>
+He who believes in separate and innumerable acts of creation will say, that
+in these cases it has pleased the Creator to cause a being of one type to
+take the place of one of another type; but this seems to me only restating
+the fact in dignified language.  He who believes in the struggle for
+existence and in the principle of natural selection, will acknowledge that
+every organic being is constantly endeavouring to increase in numbers; and
+that if any one being vary ever so little, either in habits or structure,
+and thus gain an advantage over some other inhabitant of the country, it
+will seize on the place of that inhabitant, however different it may be
+from its own place.  Hence it will cause him no surprise that there should
+be geese and frigate-birds with webbed feet, either living on the dry land
+or most rarely alighting on the water; that there should be long-toed
+corncrakes living in meadows instead of in swamps; that there should be
+woodpeckers where not a tree grows; that there should be diving thrushes,
+and petrels with the habits of auks.
+</para>
+
+<para>
+Organs of extreme perfection and complication. -- To suppose that the eye,
+with all its inimitable contrivances for adjusting the focus to different
+distances, for admitting different amounts of light, and for the correction
+of spherical and chromatic aberration, could have been formed by natural
+selection, seems, I freely confess, absurd in the highest possible degree. 
+Yet reason tells me, that if numerous gradations from a perfect and complex
+eye to one very imperfect and simple, each grade being useful to its
+possessor, can be shown to exist; if further, the eye does vary ever so
+slightly, and the variations be inherited, which is certainly the case; and
+if any variation or modification in the organ be ever useful to an animal
+under changing conditions of life, then the difficulty of believing that a
+perfect and complex eye could be formed by natural selection, though
+insuperable by our imagination, can hardly be considered real.  How a nerve
+comes to be sensitive to light, hardly concerns us more than how life
+itself first originated; but I may remark that several facts make me
+suspect that any sensitive nerve may be rendered sensitive to light, and
+likewise to those coarser vibrations of the air which produce sound.
+</para>
+
+<para>
+In looking for the gradations by which an organ in any species has been
+perfected, we ought to look exclusively to its lineal ancestors; but this
+is scarcely ever possible, and we are forced in each case to look to
+species of the same group, that is to the collateral descendants from the
+same original parent-form, in order to see what gradations are possible,
+and for the chance of some gradations having been transmitted from the
+earlier stages of descent, in an unaltered or little altered condition. 
+Amongst existing Vertebrata, we find but a small amount of gradation in the
+structure of the eye, and from fossil species we can learn nothing on this
+head.  In this great class we should probably have to descend far beneath
+the lowest known fossiliferous stratum to discover the earlier stages, by
+which the eye has been perfected.
+</para>
+
+<para>
+In the Articulata we can commence a series with an optic nerve merely
+coated with pigment, and without any other mechanism; and from this low
+stage, numerous gradations of structure, branching off in two fundamentally
+different lines, can be shown to exist, until we reach a moderately high
+stage of perfection.  In certain crustaceans, for instance, there is a
+double cornea, the inner one divided into facets, within each of which
+there is a lens-shaped swelling.  In other crustaceans the transparent
+cones which are coated by pigment, and which properly act only by excluding
+lateral pencils of light, are convex at their upper ends and must act by
+convergence; and at their lower ends there seems to be an imperfect
+vitreous substance.  With these facts, here far too briefly and imperfectly
+given, which show that there is much graduated diversity in the eyes of
+living crustaceans, and bearing in mind how small the number of living
+animals is in proportion to those which have become extinct, I can see no
+very great difficulty (not more than in the case of many other structures)
+in believing that natural selection has converted the simple apparatus of
+an optic nerve merely coated with pigment and invested by transparent
+membrane, into an optical instrument as perfect as is possessed by any
+member of the great Articulate class.
+</para>
+
+<para>
+He who will go thus far, if he find on finishing this treatise that large
+bodies of facts, otherwise inexplicable, can be explained by the theory of
+descent, ought not to hesitate to go further, and to admit that a structure
+even as perfect as the eye of an eagle might be formed by natural
+selection, although in this case he does not know any of the transitional
+grades.  His reason ought to conquer his imagination; though I have felt
+the difficulty far too keenly to be surprised at any degree of hesitation
+in extending the principle of natural selection to such startling lengths.
+</para>
+
+<para>
+It is scarcely possible to avoid comparing the eye to a telescope.  We know
+that this instrument has been perfected by the long-continued efforts of
+the highest human intellects; and we naturally infer that the eye has been
+formed by a somewhat analogous process.  But may not this inference be
+presumptuous?  Have we any right to assume that the Creator works by
+intellectual powers like those of man?  If we must compare the eye to an
+optical instrument, we ought in imagination to take a thick layer of
+transparent tissue, with a nerve sensitive to light beneath, and then
+suppose every part of this layer to be continually changing slowly in
+density, so as to separate into layers of different densities and
+thicknesses, placed at different distances from each other, and with the
+surfaces of each layer slowly changing in form.  Further we must suppose
+that there is a power always intently watching each slight accidental
+alteration in the transparent layers; and carefully selecting each
+alteration which, under varied circumstances, may in any way, or in any
+degree, tend to produce a distincter image.  We must suppose each new state
+of the instrument to be multiplied by the million; and each to be preserved
+till a better be produced, and then the old ones to be destroyed.  In
+living bodies, variation will cause the slight alterations, generation will
+multiply them almost infinitely, and natural selection will pick out with
+unerring skill each improvement.  Let this process go on for millions on
+millions of years; and during each year on millions of individuals of many
+kinds; and may we not believe that a living optical instrument might thus
+be formed as superior to one of glass, as the works of the Creator are to
+those of man?
+</para>
+
+<para>
+If it could be demonstrated that any complex organ existed, which could not
+possibly have been formed by numerous, successive, slight modifications, my
+theory would absolutely break down.  But I can find out no such case.  No
+doubt many organs exist of which we do not know the transitional grades,
+more especially if we look to much-isolated species, round which, according
+to my theory, there has been much extinction.  Or again, if we look to an
+organ common to all the members of a large class, for in this latter case
+the organ must have been first formed at an extremely remote period, since
+which all the many members of the class have been developed; and in order
+to discover the early transitional grades through which the organ has
+passed, we should have to look to very ancient ancestral forms, long since
+become extinct.
+</para>
+
+<para>
+We should be extremely cautious in concluding that an organ could not have
+been formed by transitional gradations of some kind.  Numerous cases could
+be given amongst the lower animals of the same organ performing at the same
+time wholly distinct functions; thus the alimentary canal respires,
+digests, and excretes in the larva of the dragon-fly and in the fish
+Cobites.  In the Hydra, the animal may be turned inside out, and the
+exterior surface will then digest and the stomach respire.  In such cases
+natural selection might easily specialise, if any advantage were thus
+gained, a part or organ, which had performed two functions, for one
+function alone, and thus wholly change its nature by insensible steps.  Two
+distinct organs sometimes perform simultaneously the same function in the
+same individual; to give one instance, there are fish with gills or
+branchiae that breathe the air dissolved in the water, at the same time
+that they breathe free air in their swimbladders, this latter organ having
+a ductus pneumaticus for its supply, and being divided by highly vascular
+partitions.  In these cases, one of the two organs might with ease be
+modified and perfected so as to perform all the work by itself, being aided
+during the process of modification by the other organ; and then this other
+organ might be modified for some other and quite distinct purpose, or be
+quite obliterated.
+</para>
+
+<para>
+The illustration of the swimbladder in fishes is a good one, because it
+shows us clearly the highly important fact that an organ originally
+constructed for one purpose, namely flotation, may be converted into one
+for a wholly different purpose, namely respiration.  The swimbladder has,
+also, been worked in as an accessory to the auditory organs of certain
+fish, or, for I do not know which view is now generally held, a part of the
+auditory apparatus has been worked in as a complement to the swimbladder. 
+All physiologists admit that the swimbladder is homologous, or 'ideally
+similar,' in position and structure with the lungs of the higher vertebrate
+animals:  hence there seems to me to be no great difficulty in believing
+that natural selection has actually converted a swimbladder into a lung, or
+organ used exclusively for respiration.
+</para>
+
+<para>
+I can, indeed, hardly doubt that all vertebrate animals having true lungs
+have descended by ordinary generation from an ancient prototype, of which
+we know nothing, furnished with a floating apparatus or swimbladder.  We
+can thus, as I infer from Professor Owen's interesting description of these
+parts, understand the strange fact that every particle of food and drink
+which we swallow has to pass over the orifice of the trachea, with some
+risk of falling into the lungs, notwithstanding the beautiful contrivance
+by which the glottis is closed.  In the higher Vertebrata the branchiae
+have wholly disappeared--the slits on the sides of the neck and the
+loop-like course of the arteries still marking in the embryo their former
+position.  But it is conceivable that the now utterly lost branchiae might
+have been gradually worked in by natural selection for some quite distinct
+purpose:  in the same manner as, on the view entertained by some
+naturalists that the branchiae and dorsal scales of Annelids are homologous
+with the wings and wing-covers of insects, it is probable that organs which
+at a very ancient period served for respiration have been actually
+converted into organs of flight.
+</para>
+
+<para>
+In considering transitions of organs, it is so important to bear in mind
+the probability of conversion from one function to another, that I will
+give one more instance.  Pedunculated cirripedes have two minute folds of
+skin, called by me the ovigerous frena, which serve, through the means of a
+sticky secretion, to retain the eggs until they are hatched within the
+sack.  These cirripedes have no branchiae, the whole surface of the body
+and sack, including the small frena, serving for respiration.  The
+Balanidae or sessile cirripedes, on the other hand, have no ovigerous
+frena, the eggs lying loose at the bottom of the sack, in the well-enclosed
+shell; but they have large folded branchiae.  Now I think no one will
+dispute that the ovigerous frena in the one family are strictly homologous
+with the branchiae of the other family; indeed, they graduate into each
+other.  Therefore I do not doubt that little folds of skin, which
+originally served as ovigerous frena, but which, likewise, very slightly
+aided the act of respiration, have been gradually converted by natural
+selection into branchiae, simply through an increase in their size and the
+obliteration of their adhesive glands.  If all pedunculated cirripedes had
+become extinct, and they have already suffered far more extinction than
+have sessile cirripedes, who would ever have imagined that the branchiae in
+this latter family had originally existed as organs for preventing the ova
+from being washed out of the sack?
+</para>
+
+<para>
+Although we must be extremely cautious in concluding that any organ could
+not possibly have been produced by successive transitional gradations, yet,
+undoubtedly, grave cases of difficulty occur, some of which will be
+discussed in my future work.
+</para>
+
+<para>
+One of the gravest is that of neuter insects, which are often very
+differently constructed from either the males or fertile females; but this
+case will be treated of in the next chapter.  The electric organs of fishes
+offer another case of special difficulty; it is impossible to conceive by
+what steps these wondrous organs have been produced; but, as Owen and
+others have remarked, their intimate structure closely resembles that of
+common muscle; and as it has lately been shown that Rays have an organ
+closely analogous to the electric apparatus, and yet do not, as Matteuchi
+asserts, discharge any electricity, we must own that we are far too
+ignorant to argue that no transition of any kind is possible.
+</para>
+
+<para>
+The electric organs offer another and even more serious difficulty; for
+they occur in only about a dozen fishes, of which several are widely remote
+in their affinities.  Generally when the same organ appears in several
+members of the same class, especially if in members having very different
+habits of life, we may attribute its presence to inheritance from a common
+ancestor; and its absence in some of the members to its loss through disuse
+or natural selection.  But if the electric organs had been inherited from
+one ancient progenitor thus provided, we might have expected that all
+electric fishes would have been specially related to each other.  Nor does
+geology at all lead to the belief that formerly most fishes had electric
+organs, which most of their modified descendants have lost.  The presence
+of luminous organs in a few insects, belonging to different families and
+orders, offers a parallel case of difficulty.  Other cases could be given;
+for instance in plants, the very curious contrivance of a mass of
+pollen-grains, borne on a foot-stalk with a sticky gland at the end, is the
+same in Orchis and Asclepias,--genera almost as remote as possible amongst
+flowering plants.  In all these cases of two very distinct species
+furnished with apparently the same anomalous organ, it should be observed
+that, although the general appearance and function of the organ may be the
+same, yet some fundamental difference can generally be detected.  I am
+inclined to believe that in nearly the same way as two men have sometimes
+independently hit on the very same invention, so natural selection, working
+for the good of each being and taking advantage of analogous variations,
+has sometimes modified in very nearly the same manner two parts in two
+organic beings, which owe but little of their structure in common to
+inheritance from the same ancestor.
+</para>
+
+<para>
+Although in many cases it is most difficult to conjecture by what
+transitions an organ could have arrived at its present state; yet,
+considering that the proportion of living and known forms to the extinct
+and unknown is very small, I have been astonished how rarely an organ can
+be named, towards which no transitional grade is known to lead.  The truth
+of this remark is indeed shown by that old canon in natural history of
+'Natura non facit saltum.'  We meet with this admission in the writings of
+almost every experienced naturalist; or, as Milne Edwards has well
+expressed it, nature is prodigal in variety, but niggard in innovation. 
+Why, on the theory of Creation, should this be so?  Why should all the
+parts and organs of many independent beings, each supposed to have been
+separately created for its proper place in nature, be so invariably linked
+together by graduated steps?  Why should not Nature have taken a leap from
+structure to structure?  On the theory of natural selection, we can clearly
+understand why she should not; for natural selection can act only by taking
+advantage of slight successive variations; she can never take a leap, but
+must advance by the shortest and slowest steps.
+</para>
+
+<para>
+Organs of little apparent importance. -- As natural selection acts by life
+and death,--by the preservation of individuals with any favourable
+variation, and by the destruction of those with any unfavourable deviation
+of structure,--I have sometimes felt much difficulty in understanding the
+origin of simple parts, of which the importance does not seem sufficient to
+cause the preservation of successively varying individuals.  I have
+sometimes felt as much difficulty, though of a very different kind, on this
+head, as in the case of an organ as perfect and complex as the eye.
+</para>
+
+<para>
+In the first place, we are much too ignorant in regard to the whole economy
+of any one organic being, to say what slight modifications would be of
+importance or not.  In a former chapter I have given instances of most
+trifling characters, such as the down on fruit and the colour of the flesh,
+which, from determining the attacks of insects or from being correlated
+with constitutional differences, might assuredly be acted on by natural
+selection.  The tail of the giraffe looks like an artificially constructed
+fly-flapper; and it seems at first incredible that this could have been
+adapted for its present purpose by successive slight modifications, each
+better and better, for so trifling an object as driving away flies; yet we
+should pause before being too positive even in this case, for we know that
+the distribution and existence of cattle and other animals in South America
+absolutely depends on their power of resisting the attacks of insects:  so
+that individuals which could by any means defend themselves from these
+small enemies, would be able to range into new pastures and thus gain a
+great advantage.  It is not that the larger quadrupeds are actually
+destroyed (except in some rare cases) by the flies, but they are
+incessantly harassed and their strength reduced, so that they are more
+subject to disease, or not so well enabled in a coming dearth to search for
+food, or to escape from beasts of prey.
+</para>
+
+<para>
+Organs now of trifling importance have probably in some cases been of high
+importance to an early progenitor, and, after having been slowly perfected
+at a former period, have been transmitted in nearly the same state,
+although now become of very slight use; and any actually injurious
+deviations in their structure will always have been checked by natural
+selection.  Seeing how important an organ of locomotion the tail is in most
+aquatic animals, its general presence and use for many purposes in so many
+land animals, which in their lungs or modified swim-bladders betray their
+aquatic origin, may perhaps be thus accounted for.  A well-developed tail
+having been formed in an aquatic animal, it might subsequently come to be
+worked in for all sorts of purposes, as a fly-flapper, an organ of
+prehension, or as an aid in turning, as with the dog, though the aid must
+be slight, for the hare, with hardly any tail, can double quickly enough.
+</para>
+
+<para>
+In the second place, we may sometimes attribute importance to characters
+which are really of very little importance, and which have originated from
+quite secondary causes, independently of natural selection.  We should
+remember that climate, food, &amp;c., probably have some little direct
+influence on the organisation; that characters reappear from the law of
+reversion; that correlation of growth will have had a most important
+influence in modifying various structures; and finally, that sexual
+selection will often have largely modified the external characters of
+animals having a will, to give one male an advantage in fighting with
+another or in charming the females.  Moreover when a modification of
+structure has primarily arisen from the above or other unknown causes, it
+may at first have been of no advantage to the species, but may subsequently
+have been taken advantage of by the descendants of the species under new
+conditions of life and with newly acquired habits.
+</para>
+
+<para>
+To give a few instances to illustrate these latter remarks.  If green
+woodpeckers alone had existed, and we did not know that there were many
+black and pied kinds, I dare say that we should have thought that the green
+colour was a beautiful adaptation to hide this tree-frequenting bird from
+its enemies; and consequently that it was a character of importance and
+might have been acquired through natural selection; as it is, I have no
+doubt that the colour is due to some quite distinct cause, probably to
+sexual selection.  A trailing bamboo in the Malay Archipelago climbs the
+loftiest trees by the aid of exquisitely constructed hooks clustered around
+the ends of the branches, and this contrivance, no doubt, is of the highest
+service to the plant; but as we see nearly similar hooks on many trees
+which are not climbers, the hooks on the bamboo may have arisen from
+unknown laws of growth, and have been subsequently taken advantage of by
+the plant undergoing further modification and becoming a climber.  The
+naked skin on the head of a vulture is generally looked at as a direct
+adaptation for wallowing in putridity; and so it may be, or it may possibly
+be due to the direct action of putrid matter; but we should be very
+cautious in drawing any such inference, when we see that the skin on the
+head of the clean-feeding male turkey is likewise naked.  The sutures in
+the skulls of young mammals have been advanced as a beautiful adaptation
+for aiding parturition, and no doubt they facilitate, or may be
+indispensable for this act; but as sutures occur in the skulls of young
+birds and reptiles, which have only to escape from a broken egg, we may
+infer that this structure has arisen from the laws of growth, and has been
+taken advantage of in the parturition of the higher animals.
+</para>
+
+<para>
+We are profoundly ignorant of the causes producing slight and unimportant
+variations; and we are immediately made conscious of this by reflecting on
+the differences in the breeds of our domesticated animals in different
+countries,--more especially in the less civilized countries where there has
+been but little artificial selection.  Careful observers are convinced that
+a damp climate affects the growth of the hair, and that with the hair the
+horns are correlated.  Mountain breeds always differ from lowland breeds;
+and a mountainous country would probably affect the hind limbs from
+exercising them more, and possibly even the form of the pelvis; and then by
+the law of homologous variation, the front limbs and even the head would
+probably be affected.  The shape, also, of the pelvis might affect by
+pressure the shape of the head of the young in the womb.  The laborious
+breathing necessary in high regions would, we have some reason to believe,
+increase the size of the chest; and again correlation would come into play. 
+Animals kept by savages in different countries often have to struggle for
+their own subsistence, and would be exposed to a certain extent to natural
+selection, and individuals with slightly different constitutions would
+succeed best under different climates; and there is reason to believe that
+constitution and colour are correlated.  A good observer, also, states that
+in cattle susceptibility to the attacks of flies is correlated with colour,
+as is the liability to be poisoned by certain plants; so that colour would
+be thus subjected to the action of natural selection.  But we are far too
+ignorant to speculate on the relative importance of the several known and
+unknown laws of variation; and I have here alluded to them only to show
+that, if we are unable to account for the characteristic differences of our
+domestic breeds, which nevertheless we generally admit to have arisen
+through ordinary generation, we ought not to lay too much stress on our
+ignorance of the precise cause of the slight analogous differences between
+species.  I might have adduced for this same purpose the differences
+between the races of man, which are so strongly marked; I may add that some
+little light can apparently be thrown on the origin of these differences,
+chiefly through sexual selection of a particular kind, but without here
+entering on copious details my reasoning would appear frivolous.
+</para>
+
+<para>
+The foregoing remarks lead me to say a few words on the protest lately made
+by some naturalists, against the utilitarian doctrine that every detail of
+structure has been produced for the good of its possessor.  They believe
+that very many structures have been created for beauty in the eyes of man,
+or for mere variety.  This doctrine, if true, would be absolutely fatal to
+my theory.  Yet I fully admit that many structures are of no direct use to
+their possessors.  Physical conditions probably have had some little effect
+on structure, quite independently of any good thus gained.  Correlation of
+growth has no doubt played a most important part, and a useful modification
+of one part will often have entailed on other parts diversified changes of
+no direct use.  So again characters which formerly were useful, or which
+formerly had arisen from correlation of growth, or from other unknown
+cause, may reappear from the law of reversion, though now of no direct use. 
+The effects of sexual selection, when displayed in beauty to charm the
+females, can be called useful only in rather a forced sense.  But by far
+the most important consideration is that the chief part of the organisation
+of every being is simply due to inheritance; and consequently, though each
+being assuredly is well fitted for its place in nature, many structures now
+have no direct relation to the habits of life of each species.  Thus, we
+can hardly believe that the webbed feet of the upland goose or of the
+frigate-bird are of special use to these birds; we cannot believe that the
+same bones in the arm of the monkey, in the fore leg of the horse, in the
+wing of the bat, and in the flipper of the seal, are of special use to
+these animals.  We may safely attribute these structures to inheritance. 
+But to the progenitor of the upland goose and of the frigate-bird, webbed
+feet no doubt were as useful as they now are to the most aquatic of
+existing birds.  So we may believe that the progenitor of the seal had not
+a flipper, but a foot with five toes fitted for walking or grasping; and we
+may further venture to believe that the several bones in the limbs of the
+monkey, horse, and bat, which have been inherited from a common progenitor,
+were formerly of more special use to that progenitor, or its progenitors,
+than they now are to these animals having such widely diversified habits. 
+Therefore we may infer that these several bones might have been acquired
+through natural selection, subjected formerly, as now, to the several laws
+of inheritance, reversion, correlation of growth, &amp;c.  Hence every detail
+of structure in every living creature (making some little allowance for the
+direct action of physical conditions) may be viewed, either as having been
+of special use to some ancestral form, or as being now of special use to
+the descendants of this form--either directly, or indirectly through the
+complex laws of growth.
+</para>
+
+<para>
+Natural selection cannot possibly produce any modification in any one
+species exclusively for the good of another species; though throughout
+nature one species incessantly takes advantage of, and profits by, the
+structure of another.  But natural selection can and does often produce
+structures for the direct injury of other species, as we see in the fang of
+the adder, and in the ovipositor of the ichneumon, by which its eggs are
+deposited in the living bodies of other insects.  If it could be proved
+that any part of the structure of any one species had been formed for the
+exclusive good of another species, it would annihilate my theory, for such
+could not have been produced through natural selection.  Although many
+statements may be found in works on natural history to this effect, I
+cannot find even one which seems to me of any weight.  It is admitted that
+the rattlesnake has a poison-fang for its own defence and for the
+destruction of its prey; but some authors suppose that at the same time
+this snake is furnished with a rattle for its own injury, namely, to warn
+its prey to escape.  I would almost as soon believe that the cat curls the
+end of its tail when preparing to spring, in order to warn the doomed
+mouse.  But I have not space here to enter on this and other such cases.
+</para>
+
+<para>
+Natural selection will never produce in a being anything injurious to
+itself, for natural selection acts solely by and for the good of each.  No
+organ will be formed, as Paley has remarked, for the purpose of causing
+pain or for doing an injury to its possessor.  If a fair balance be struck
+between the good and evil caused by each part, each will be found on the
+whole advantageous.  After the lapse of time, under changing conditions of
+life, if any part comes to be injurious, it will be modified; or if it be
+not so, the being will become extinct, as myriads have become extinct.
+</para>
+
+<para>
+Natural selection tends only to make each organic being as perfect as, or
+slightly more perfect than, the other inhabitants of the same country with
+which it has to struggle for existence.  And we see that this is the degree
+of perfection attained under nature.  The endemic productions of New
+Zealand, for instance, are perfect one compared with another; but they are
+now rapidly yielding before the advancing legions of plants and animals
+introduced from Europe.  Natural selection will not produce absolute
+perfection, nor do we always meet, as far as we can judge, with this high
+standard under nature.  The correction for the aberration of light is said,
+on high authority, not to be perfect even in that most perfect organ, the
+eye.  If our reason leads us to admire with enthusiasm a multitude of
+inimitable contrivances in nature, this same reason tells us, though we may
+easily err on both sides, that some other contrivances are less perfect. 
+Can we consider the sting of the wasp or of the bee as perfect, which, when
+used against many attacking animals, cannot be withdrawn, owing to the
+backward serratures, and so inevitably causes the death of the insect by
+tearing out its viscera?
+</para>
+
+<para>
+If we look at the sting of the bee, as having originally existed in a
+remote progenitor as a boring and serrated instrument, like that in so many
+members of the same great order, and which has been modified but not
+perfected for its present purpose, with the poison originally adapted to
+cause galls subsequently intensified, we can perhaps understand how it is
+that the use of the sting should so often cause the insect's own death: 
+for if on the whole the power of stinging be useful to the community, it
+will fulfil all the requirements of natural selection, though it may cause
+the death of some few members.  If we admire the truly wonderful power of
+scent by which the males of many insects find their females, can we admire
+the production for this single purpose of thousands of drones, which are
+utterly useless to the community for any other end, and which are
+ultimately slaughtered by their industrious and sterile sisters?  It may be
+difficult, but we ought to admire the savage instinctive hatred of the
+queen-bee, which urges her instantly to destroy the young queens her
+daughters as soon as born, or to perish herself in the combat; for
+undoubtedly this is for the good of the community; and maternal love or
+maternal hatred, though the latter fortunately is most rare, is all the
+same to the inexorable principle of natural selection.  If we admire the
+several ingenious contrivances, by which the flowers of the orchis and of
+many other plants are fertilised through insect agency, can we consider as
+equally perfect the elaboration by our fir-trees of dense clouds of pollen,
+in order that a few granules may be wafted by a chance breeze on to the
+ovules?
+</para>
+
+<para>
+Summary of Chapter -- We have in this chapter discussed some of the
+difficulties and objections which may be urged against my theory.  Many of
+them are very grave; but I think that in the discussion light has been
+thrown on several facts, which on the theory of independent acts of
+creation are utterly obscure.  We have seen that species at any one period
+are not indefinitely variable, and are not linked together by a multitude
+of intermediate gradations, partly because the process of natural selection
+will always be very slow, and will act, at any one time, only on a very few
+forms; and partly because the very process of natural selection almost
+implies the continual supplanting and extinction of preceding and
+intermediate gradations.  Closely allied species, now living on a
+continuous area, must often have been formed when the area was not
+continuous, and when the conditions of life did not insensibly graduate
+away from one part to another.  When two varieties are formed in two
+districts of a continuous area, an intermediate variety will often be
+formed, fitted for an intermediate zone; but from reasons assigned, the
+intermediate variety will usually exist in lesser numbers than the two
+forms which it connects; consequently the two latter, during the course of
+further modification, from existing in greater numbers, will have a great
+advantage over the less numerous intermediate variety, and will thus
+generally succeed in supplanting and exterminating it.
+</para>
+
+<para>
+We have seen in this chapter how cautious we should be in concluding that
+the most different habits of life could not graduate into each other; that
+a bat, for instance, could not have been formed by natural selection from
+an animal which at first could only glide through the air.
+</para>
+
+<para>
+We have seen that a species may under new conditions of life change its
+habits, or have diversified habits, with some habits very unlike those of
+its nearest congeners.  Hence we can understand, bearing in mind that each
+organic being is trying to live wherever it can live, how it has arisen
+that there are upland geese with webbed feet, ground woodpeckers, diving
+thrushes, and petrels with the habits of auks.
+</para>
+
+<para>
+Although the belief that an organ so perfect as the eye could have been
+formed by natural selection, is more than enough to stagger any one; yet in
+the case of any organ, if we know of a long series of gradations in
+complexity, each good for its possessor, then, under changing conditions of
+life, there is no logical impossibility in the acquirement of any
+conceivable degree of perfection through natural selection.  In the cases
+in which we know of no intermediate or transitional states, we should be
+very cautious in concluding that none could have existed, for the
+homologies of many organs and their intermediate states show that wonderful
+metamorphoses in function are at least possible.  For instance, a
+swim-bladder has apparently been converted into an air-breathing lung.  The
+same organ having performed simultaneously very different functions, and
+then having been specialised for one function; and two very distinct organs
+having performed at the same time the same function, the one having been
+perfected whilst aided by the other, must often have largely facilitated
+transitions.
+</para>
+
+<para>
+We are far too ignorant, in almost every case, to be enabled to assert that
+any part or organ is so unimportant for the welfare of a species, that
+modifications in its structure could not have been slowly accumulated by
+means of natural selection.  But we may confidently believe that many
+modifications, wholly due to the laws of growth, and at first in no way
+advantageous to a species, have been subsequently taken advantage of by the
+still further modified descendants of this species.  We may, also, believe
+that a part formerly of high importance has often been retained (as the
+tail of an aquatic animal by its terrestrial descendants), though it has
+become of such small importance that it could not, in its present state,
+have been acquired by natural selection,--a power which acts solely by the
+preservation of profitable variations in the struggle for life.
+</para>
+
+<para>
+Natural selection will produce nothing in one species for the exclusive
+good or injury of another; though it may well produce parts, organs, and
+excretions highly useful or even indispensable, or highly injurious to
+another species, but in all cases at the same time useful to the owner. 
+Natural selection in each well-stocked country, must act chiefly through
+the competition of the inhabitants one with another, and consequently will
+produce perfection, or strength in the battle for life, only according to
+the standard of that country.  Hence the inhabitants of one country,
+generally the smaller one, will often yield, as we see they do yield, to
+the inhabitants of another and generally larger country.  For in the larger
+country there will have existed more individuals, and more diversified
+forms, and the competition will have been severer, and thus the standard of
+perfection will have been rendered higher.  Natural selection will not
+necessarily produce absolute perfection; nor, as far as we can judge by our
+limited faculties, can absolute perfection be everywhere found.
+</para>
+
+<para>
+On the theory of natural selection we can clearly understand the full
+meaning of that old canon in natural history, 'Natura non facit saltum.' 
+This canon, if we look only to the present inhabitants of the world, is not
+strictly correct, but if we include all those of past times, it must by my
+theory be strictly true.
+</para>
+
+<para>
+It is generally acknowledged that all organic beings have been formed on
+two great laws--Unity of Type, and the Conditions of Existence.  By unity
+of type is meant that fundamental agreement in structure, which we see in
+organic beings of the same class, and which is quite independent of their
+habits of life.  On my theory, unity of type is explained by unity of
+descent.  The expression of conditions of existence, so often insisted on
+by the illustrious Cuvier, is fully embraced by the principle of natural
+selection.  For natural selection acts by either now adapting the varying
+parts of each being to its organic and inorganic conditions of life; or by
+having adapted them during long-past periods of time:  the adaptations
+being aided in some cases by use and disuse, being slightly affected by the
+direct action of the external conditions of life, and being in all cases
+subjected to the several laws of growth.  Hence, in fact, the law of the
+Conditions of Existence is the higher law; as it includes, through the
+inheritance of former adaptations, that of Unity of Type.
+</para>
+
+</chapter>
+
+<chapter>
+<chapheader>
+
+<chapnum>Chapter VII</chapnum>
+
+<title>Instinct</title>
+
+<chapsummary>
+Instincts comparable with habits, but different in their origin --
+Instincts graduated -- Aphides and ants -- Instincts variable -- Domestic
+instincts, their origin -- Natural instincts of the cuckoo, ostrich, and
+parasitic bees -- Slave-making ants -- Hive-bee, its cell-making instinct -
+- Difficulties on the theory of the Natural Selection of instincts --
+Neuter or sterile insects -- Summary.
+</chapsummary>
+</chapheader>
+
+<para>
+The subject of instinct might have been worked into the previous chapters;
+but I have thought that it would be more convenient to treat the subject
+separately, especially as so wonderful an instinct as that of the hive-bee
+making its cells will probably have occurred to many readers, as a
+difficulty sufficient to overthrow my whole theory.  I must premise, that I
+have nothing to do with the origin of the primary mental powers, any more
+than I have with that of life itself.  We are concerned only with the
+diversities of instinct and of the other mental qualities of animals within
+the same class.
+</para>
+
+<para>
+I will not attempt any definition of instinct.  It would be easy to show
+that several distinct mental actions are commonly embraced by this term;
+but every one understands what is meant, when it is said that instinct
+impels the cuckoo to migrate and to lay her eggs in other birds' nests.  An
+action, which we ourselves should require experience to enable us to
+perform, when performed by an animal, more especially by a very young one,
+without any experience, and when performed by many individuals in the same
+way, without their knowing for what purpose it is performed, is usually
+said to be instinctive.  But I could show that none of these characters of
+instinct are universal.  A little dose, as Pierre Huber expresses it, of
+judgment or reason, often comes into play, even in animals very low in the
+scale of nature.
+</para>
+
+<para>
+Frederick Cuvier and several of the older metaphysicians have compared
+instinct with habit.  This comparison gives, I think, a remarkably accurate
+notion of the frame of mind under which an instinctive action is performed,
+but not of its origin.  How unconsciously many habitual actions are
+performed, indeed not rarely in direct opposition to our conscious will!
+yet they may be modified by the will or reason.  Habits easily become
+associated with other habits, and with certain periods of time and states
+of the body.  When once acquired, they often remain constant throughout
+life.  Several other points of resemblance between instincts and habits
+could be pointed out.  As in repeating a well-known song, so in instincts,
+one action follows another by a sort of rhythm; if a person be interrupted
+in a song, or in repeating anything by rote, he is generally forced to go
+back to recover the habitual train of thought:  so P. Huber found it was
+with a caterpillar, which makes a very complicated hammock; for if he took
+a caterpillar which had completed its hammock up to, say, the sixth stage
+of construction, and put it into a hammock completed up only to the third
+stage, the caterpillar simply re-performed the fourth, fifth, and sixth
+stages of construction.  If, however, a caterpillar were taken out of a
+hammock made up, for instance, to the third stage, and were put into one
+finished up to the sixth stage, so that much of its work was already done
+for it, far from feeling the benefit of this, it was much embarrassed, and,
+in order to complete its hammock, seemed forced to start from the third
+stage, where it had left off, and thus tried to complete the already
+finished work.  If we suppose any habitual action to become inherited--and
+I think it can be shown that this does sometimes happen--then the
+resemblance between what originally was a habit and an instinct becomes so
+close as not to be distinguished.  If Mozart, instead of playing the
+pianoforte at three years old with wonderfully little practice, had played
+a tune with no practice at all, be might truly be said to have done so
+instinctively.  But it would be the most serious error to suppose that the
+greater number of instincts have been acquired by habit in one generation,
+and then transmitted by inheritance to succeeding generations.  It can be
+clearly shown that the most wonderful instincts with which we are
+acquainted, namely, those of the hive-bee and of many ants, could not
+possibly have been thus acquired.
+</para>
+
+<para>
+It will be universally admitted that instincts are as important as
+corporeal structure for the welfare of each species, under its present
+conditions of life.  Under changed conditions of life, it is at least
+possible that slight modifications of instinct might be profitable to a
+species; and if it can be shown that instincts do vary ever so little, then
+I can see no difficulty in natural selection preserving and continually
+accumulating variations of instinct to any extent that may be profitable. 
+It is thus, as I believe, that all the most complex and wonderful instincts
+have originated.  As modifications of corporeal structure arise from, and
+are increased by, use or habit, and are diminished or lost by disuse, so I
+do not doubt it has been with instincts.  But I believe that the effects of
+habit are of quite subordinate importance to the effects of the natural
+selection of what may be called accidental variations of instincts;--that
+is of variations produced by the same unknown causes which produce slight
+deviations of bodily structure.
+</para>
+
+<para>
+No complex instinct can possibly be produced through natural selection,
+except by the slow and gradual accumulation of numerous, slight, yet
+profitable, variations.  Hence, as in the case of corporeal structures, we
+ought to find in nature, not the actual transitional gradations by which
+each complex instinct has been acquired--for these could be found only in
+the lineal ancestors of each species--but we ought to find in the
+collateral lines of descent some evidence of such gradations; or we ought
+at least to be able to show that gradations of some kind are possible; and
+this we certainly can do.  I have been surprised to find, making allowance
+for the instincts of animals having been but little observed except in
+Europe and North America, and for no instinct being known amongst extinct
+species, how very generally gradations, leading to the most complex
+instincts, can be discovered.  The canon of 'Natura non facit saltum'
+applies with almost equal force to instincts as to bodily organs.  Changes
+of instinct may sometimes be facilitated by the same species having
+different instincts at different periods of life, or at different seasons
+of the year, or when placed under different circumstances, &amp;c.; in which
+case either one or the other instinct might be preserved by natural
+selection.  And such instances of diversity of instinct in the same species
+can be shown to occur in nature.
+</para>
+
+<para>
+Again as in the case of corporeal structure, and conformably with my
+theory, the instinct of each species is good for itself, but has never, as
+far as we can judge, been produced for the exclusive good of others.  One
+of the strongest instances of an animal apparently performing an action for
+the sole good of another, with which I am acquainted, is that of aphides
+voluntarily yielding their sweet excretion to ants:  that they do so
+voluntarily, the following facts show.  I removed all the ants from a group
+of about a dozen aphides on a dock-plant, and prevented their attendance
+during several hours.  After this interval, I felt sure that the aphides
+would want to excrete.  I watched them for some time through a lens, but
+not one excreted; I then tickled and stroked them with a hair in the same
+manner, as well as I could, as the ants do with their antennae; but not one
+excreted.  Afterwards I allowed an ant to visit them, and it immediately
+seemed, by its eager way of running about, to be well aware what a rich
+flock it had discovered; it then began to play with its antennae on the
+abdomen first of one aphis and then of another; and each aphis, as soon as
+it felt the antennae, immediately lifted up its abdomen and excreted a
+limpid drop of sweet juice, which was eagerly devoured by the ant.  Even
+the quite young aphides behaved in this manner, showing that the action was
+instinctive, and not the result of experience.  But as the excretion is
+extremely viscid, it is probably a convenience to the aphides to have it
+removed; and therefore probably the aphides do not instinctively excrete
+for the sole good of the ants.  Although I do not believe that any animal
+in the world performs an action for the exclusive good of another of a
+distinct species, yet each species tries to take advantage of the instincts
+of others, as each takes advantage of the weaker bodily structure of
+others.  So again, in some few cases, certain instincts cannot be
+considered as absolutely perfect; but as details on this and other such
+points are not indispensable, they may be here passed over.
+</para>
+
+<para>
+As some degree of variation in instincts under a state of nature, and the
+inheritance of such variations, are indispensable for the action of natural
+selection, as many instances as possible ought to have been here given; but
+want of space prevents me.  I can only assert, that instincts certainly do
+vary--for instance, the migratory instinct, both in extent and direction,
+and in its total loss.  So it is with the nests of birds, which vary partly
+in dependence on the situations chosen, and on the nature and temperature
+of the country inhabited, but often from causes wholly unknown to us: 
+Audubon has given several remarkable cases of differences in nests of the
+same species in the northern and southern United States.  Fear of any
+particular enemy is certainly an instinctive quality, as may be seen in
+nestling birds, though it is strengthened by experience, and by the sight
+of fear of the same enemy in other animals.  But fear of man is slowly
+acquired, as I have elsewhere shown, by various animals inhabiting desert
+islands; and we may see an instance of this, even in England, in the
+greater wildness of all our large birds than of our small birds; for the
+large birds have been most persecuted by man.  We may safely attribute the
+greater wildness of our large birds to this cause; for in uninhabited
+islands large birds are not more fearful than small; and the magpie, so
+wary in England, is tame in Norway, as is the hooded crow in Egypt.
+</para>
+
+<para>
+That the general disposition of individuals of the same species, born in a
+state of nature, is extremely diversified, can be shown by a multitude of
+facts.  Several cases also, could be given, of occasional and strange
+habits in certain species, which might, if advantageous to the species,
+give rise, through natural selection, to quite new instincts.  But I am
+well aware that these general statements, without facts given in detail,
+can produce but a feeble effect on the reader's mind.  I can only repeat my
+assurance, that I do not speak without good evidence.
+</para>
+
+<para>
+The possibility, or even probability, of inherited variations of instinct
+in a state of nature will be strengthened by briefly considering a few
+cases under domestication.  We shall thus also be enabled to see the
+respective parts which habit and the selection of so-called accidental
+variations have played in modifying the mental qualities of our domestic
+animals.  A number of curious and authentic instances could be given of the
+inheritance of all shades of disposition and tastes, and likewise of the
+oddest tricks, associated with certain frames of mind or periods of time. 
+But let us look to the familiar case of the several breeds of dogs:  it
+cannot be doubted that young pointers (I have myself seen a striking
+instance) will sometimes point and even back other dogs the very first time
+that they are taken out; retrieving is certainly in some degree inherited
+by retrievers; and a tendency to run round, instead of at, a flock of
+sheep, by shepherd-dogs.  I cannot see that these actions, performed
+without experience by the young, and in nearly the same manner by each
+individual, performed with eager delight by each breed, and without the end
+being known,--for the young pointer can no more know that he points to aid
+his master, than the white butterfly knows why she lays her eggs on the
+leaf of the cabbage,--I cannot see that these actions differ essentially
+from true instincts.  If we were to see one kind of wolf, when young and
+without any training, as soon as it scented its prey, stand motionless like
+a statue, and then slowly crawl forward with a peculiar gait; and another
+kind of wolf rushing round, instead of at, a herd of deer, and driving them
+to a distant point, we should assuredly call these actions instinctive. 
+Domestic instincts, as they may be called, are certainly far less fixed or
+invariable than natural instincts; but they have been acted on by far less
+rigorous selection, and have been transmitted for an incomparably shorter
+period, under less fixed conditions of life.
+</para>
+
+<para>
+How strongly these domestic instincts, habits, and dispositions are
+inherited, and how curiously they become mingled, is well shown when
+different breeds of dogs are crossed.  Thus it is known that a cross with a
+bull-dog has affected for many generations the courage and obstinacy of
+greyhounds; and a cross with a greyhound has given to a whole family of
+shepherd-dogs a tendency to hunt hares.  These domestic instincts, when
+thus tested by crossing, resemble natural instincts, which in a like manner
+become curiously blended together, and for a long period exhibit traces of
+the instincts of either parent:  for example, Le Roy describes a dog, whose
+great-grandfather was a wolf, and this dog showed a trace of its wild
+parentage only in one way, by not coming in a straight line to his master
+when called.
+</para>
+
+<para>
+Domestic instincts are sometimes spoken of as actions which have become
+inherited solely from long-continued and compulsory habit, but this, I
+think, is not true.  No one would ever have thought of teaching, or
+probably could have taught, the tumbler-pigeon to tumble,--an action which,
+as I have witnessed, is performed by young birds, that have never seen a
+pigeon tumble.  We may believe that some one pigeon showed a slight
+tendency to this strange habit, and that the long-continued selection of
+the best individuals in successive generations made tumblers what they now
+are; and near Glasgow there are house-tumblers, as I hear from Mr. Brent,
+which cannot fly eighteen inches high without going head over heels.  It
+may be doubted whether any one would have thought of training a dog to
+point, had not some one dog naturally shown a tendency in this line; and
+this is known occasionally to happen, as I once saw in a pure terrier. 
+When the first tendency was once displayed, methodical selection and the
+inherited effects of compulsory training in each successive generation
+would soon complete the work; and unconscious selection is still at work,
+as each man tries to procure, without intending to improve the breed, dogs
+which will stand and hunt best.  On the other hand, habit alone in some
+cases has sufficed; no animal is more difficult to tame than the young of
+the wild rabbit; scarcely any animal is tamer than the young of the tame
+rabbit; but I do not suppose that domestic rabbits have ever been selected
+for tameness; and I presume that we must attribute the whole of the
+inherited change from extreme wildness to extreme tameness, simply to habit
+and long-continued close confinement.
+</para>
+
+<para>
+Natural instincts are lost under domestication:  a remarkable instance of
+this is seen in those breeds of fowls which very rarely or never become
+'broody,' that is, never wish to sit on their eggs.  Familiarity alone
+prevents our seeing how universally and largely the minds of our domestic
+animals have been modified by domestication.  It is scarcely possible to
+doubt that the love of man has become instinctive in the dog.  All wolves,
+foxes, jackals, and species of the cat genus, when kept tame, are most
+eager to attack poultry, sheep, and pigs; and this tendency has been found
+incurable in dogs which have been brought home as puppies from countries,
+such as Tierra del Fuego and Australia, where the savages do not keep these
+domestic animals.  How rarely, on the other hand, do our civilised dogs,
+even when quite young, require to be taught not to attack poultry, sheep,
+and pigs!  No doubt they occasionally do make an attack, and are then
+beaten; and if not cured, they are destroyed; so that habit, with some
+degree of selection, has probably concurred in civilising by inheritance
+our dogs.  On the other hand, young chickens have lost, wholly by habit,
+that fear of the dog and cat which no doubt was originally instinctive in
+them, in the same way as it is so plainly instinctive in young pheasants,
+though reared under a hen.  It is not that chickens have lost all fear, but
+fear only of dogs and cats, for if the hen gives the danger-chuckle, they
+will run (more especially young turkeys) from under her, and conceal
+themselves in the surrounding grass or thickets; and this is evidently done
+for the instinctive purpose of allowing, as we see in wild ground-birds,
+their mother to fly away.  But this instinct retained by our chickens has
+become useless under domestication, for the mother-hen has almost lost by
+disuse the power of flight.
+</para>
+
+<para>
+Hence, we may conclude, that domestic instincts have been acquired and
+natural instincts have been lost partly by habit, and partly by man
+selecting and accumulating during successive generations, peculiar mental
+habits and actions, which at first appeared from what we must in our
+ignorance call an accident.  In some cases compulsory habit alone has
+sufficed to produce such inherited mental changes; in other cases
+compulsory habit has done nothing, and all has been the result of
+selection, pursued both methodically and unconsciously; but in most cases,
+probably, habit and selection have acted together.
+</para>
+
+<para>
+We shall, perhaps, best understand how instincts in a state of nature have
+become modified by selection, by considering a few cases.  I will select
+only three, out of the several which I shall have to discuss in my future
+work,--namely, the instinct which leads the cuckoo to lay her eggs in other
+birds' nests; the slave-making instinct of certain ants; and the
+comb-making power of the hive-bee:  these two latter instincts have
+generally, and most justly, been ranked by naturalists as the most
+wonderful of all known instincts.
+</para>
+
+<para>
+It is now commonly admitted that the more immediate and final cause of the
+cuckoo's instinct is, that she lays her eggs, not daily, but at intervals
+of two or three days; so that, if she were to make her own nest and sit on
+her own eggs, those first laid would have to be left for some time
+unincubated, or there would be eggs and young birds of different ages in
+the same nest.  If this were the case, the process of laying and hatching
+might be inconveniently long, more especially as she has to migrate at a
+very early period; and the first hatched young would probably have to be
+fed by the male alone.  But the American cuckoo is in this predicament; for
+she makes her own nest and has eggs and young successively hatched, all at
+the same time.  It has been asserted that the American cuckoo occasionally
+lays her eggs in other birds' nests; but I hear on the high authority of
+Dr. Brewer, that this is a mistake.  Nevertheless, I could give several
+instances of various birds which have been known occasionally to lay their
+eggs in other birds' nests.  Now let us suppose that the ancient progenitor
+of our European cuckoo had the habits of the American cuckoo; but that
+occasionally she laid an egg in another bird's nest.  If the old bird
+profited by this occasional habit, or if the young were made more vigorous
+by advantage having been taken of the mistaken maternal instinct of another
+bird, than by their own mother's care, encumbered as she can hardly fail to
+be by having eggs and young of different ages at the same time; then the
+old birds or the fostered young would gain an advantage.  And analogy would
+lead me to believe, that the young thus reared would be apt to follow by
+inheritance the occasional and aberrant habit of their mother, and in their
+turn would be apt to lay their eggs in other birds' nests, and thus be
+successful in rearing their young.  By a continued process of this nature,
+I believe that the strange instinct of our cuckoo could be, and has been,
+generated.  I may add that, according to Dr. Gray and to some other
+observers, the European cuckoo has not utterly lost all maternal love and
+care for her own offspring.
+</para>
+
+<para>
+The occasional habit of birds laying their eggs in other birds' nests,
+either of the same or of a distinct species, is not very uncommon with the
+Gallinaceae; and this perhaps explains the origin of a singular instinct in
+the allied group of ostriches.  For several hen ostriches, at least in the
+case of the American species, unite and lay first a few eggs in one nest
+and then in another; and these are hatched by the males.  This instinct may
+probably be accounted for by the fact of the hens laying a large number of
+eggs; but, as in the case of the cuckoo, at intervals of two or three days. 
+This instinct, however, of the American ostrich has not as yet been
+perfected; for a surprising number of eggs lie strewed over the plains, so
+that in one day's hunting I picked up no less than twenty lost and wasted
+eggs.
+</para>
+
+<para>
+Many bees are parasitic, and always lay their eggs in the nests of bees of
+other kinds.  This case is more remarkable than that of the cuckoo; for
+these bees have not only their instincts but their structure modified in
+accordance with their parasitic habits; for they do not possess the
+pollen-collecting apparatus which would be necessary if they had to store
+food for their own young.  Some species, likewise, of Sphegidae (wasp-like
+insects) are parasitic on other species; and M. Fabre has lately shown good
+reason for believing that although the Tachytes nigra generally makes its
+own burrow and stores it with paralysed prey for its own larvae to feed on,
+yet that when this insect finds a burrow already made and stored by another
+sphex, it takes advantage of the prize, and becomes for the occasion
+parasitic.  In this case, as with the supposed case of the cuckoo, I can
+see no difficulty in natural selection making an occasional habit
+permanent, if of advantage to the species, and if the insect whose nest and
+stored food are thus feloniously appropriated, be not thus exterminated.
+</para>
+
+<para>
+Slave-making instinct. -- This remarkable instinct was first discovered in
+the Formica (Polyerges) rufescens by Pierre Huber, a better observer even
+than his celebrated father.  This ant is absolutely dependent on its
+slaves; without their aid, the species would certainly become extinct in a
+single year.  The males and fertile females do no work.  The workers or
+sterile females, though most energetic and courageous in capturing slaves,
+do no other work.  They are incapable of making their own nests, or of
+feeding their own larvae.  When the old nest is found inconvenient, and
+they have to migrate, it is the slaves which determine the migration, and
+actually carry their masters in their jaws.  So utterly helpless are the
+masters, that when Huber shut up thirty of them without a slave, but with
+plenty of the food which they like best, and with their larvae and pupae to
+stimulate them to work, they did nothing; they could not even feed
+themselves, and many perished of hunger.  Huber then introduced a single
+slave (F. fusca), and she instantly set to work, fed and saved the
+survivors; made some cells and tended the larvae, and put all to rights. 
+What can be more extraordinary than these well-ascertained facts?  If we
+had not known of any other slave-making ant, it would have been hopeless to
+have speculated how so wonderful an instinct could have been perfected.
+</para>
+
+<para>
+Formica sanguinea was likewise first discovered by P. Huber to be a
+slave-making ant.  This species is found in the southern parts of England,
+and its habits have been attended to by Mr. F. Smith, of the British
+Museum, to whom I am much indebted for information on this and other
+subjects.  Although fully trusting to the statements of Huber and Mr.
+Smith, I tried to approach the subject in a sceptical frame of mind, as any
+one may well be excused for doubting the truth of so extraordinary and
+odious an instinct as that of making slaves.  Hence I will give the
+observations which I have myself made, in some little detail.  I opened
+fourteen nests of F. sanguinea, and found a few slaves in all.  Males and
+fertile females of the slave-species are found only in their own proper
+communities, and have never been observed in the nests of F. sanguinea. 
+The slaves are black and not above half the size of their red masters, so
+that the contrast in their appearance is very great.  When the nest is
+slightly disturbed, the slaves occasionally come out, and like their
+masters are much agitated and defend their nest:  when the nest is much
+disturbed and the larvae and pupae are exposed, the slaves work
+energetically with their masters in carrying them away to a place of
+safety.  Hence, it is clear, that the slaves feel quite at home.  During
+the months of June and July, on three successive years, I have watched for
+many hours several nests in Surrey and Sussex, and never saw a slave either
+leave or enter a nest.  As, during these months, the slaves are very few in
+number, I thought that they might behave differently when more numerous;
+but Mr. Smith informs me that he has watched the nests at various hours
+during May, June and August, both in Surrey and Hampshire, and has never
+seen the slaves, though present in large numbers in August, either leave or
+enter the nest.  Hence he considers them as strictly household slaves.  The
+masters, on the other hand, may be constantly seen bringing in materials
+for the nest, and food of all kinds.  During the present year, however, in
+the month of July, I came across a community with an unusually large stock
+of slaves, and I observed a few slaves mingled with their masters leaving
+the nest, and marching along the same road to a tall Scotch-fir-tree,
+twenty-five yards distant, which they ascended together, probably in search
+of aphides or cocci.  According to Huber, who had ample opportunities for
+observation, in Switzerland the slaves habitually work with their masters
+in making the nest, and they alone open and close the doors in the morning
+and evening; and, as Huber expressly states, their principal office is to
+search for aphides.  This difference in the usual habits of the masters and
+slaves in the two countries, probably depends merely on the slaves being
+captured in greater numbers in Switzerland than in England.
+</para>
+
+<para>
+One day I fortunately chanced to witness a migration from one nest to
+another, and it was a most interesting spectacle to behold the masters
+carefully carrying, as Huber has described, their slaves in their jaws. 
+Another day my attention was struck by about a score of the slave-makers
+haunting the same spot, and evidently not in search of food; they
+approached and were vigorously repulsed by an independent community of the
+slave species (F. fusca); sometimes as many as three of these ants clinging
+to the legs of the slave-making F. sanguinea.  The latter ruthlessly killed
+their small opponents, and carried their dead bodies as food to their nest,
+twenty-nine yards distant; but they were prevented from getting any pupae
+to rear as slaves.  I then dug up a small parcel of the pupae of F. fusca
+from another nest, and put them down on a bare spot near the place of
+combat; they were eagerly seized, and carried off by the tyrants, who
+perhaps fancied that, after all, they had been victorious in their late
+combat.
+</para>
+
+<para>
+At the same time I laid on the same place a small parcel of the pupae of
+another species, F. flava, with a few of these little yellow ants still
+clinging to the fragments of the nest.  This species is sometimes, though
+rarely, made into slaves, as has been described by Mr. Smith.  Although so
+small a species, it is very courageous, and I have seen it ferociously
+attack other ants.  In one instance I found to my surprise an independent
+community of F. flava under a stone beneath a nest of the slave-making F.
+sanguinea; and when I had accidentally disturbed both nests, the little
+ants attacked their big neighbours with surprising courage.  Now I was
+curious to ascertain whether F. sanguinea could distinguish the pupae of F.
+fusca, which they habitually make into slaves, from those of the little and
+furious F. flava, which they rarely capture, and it was evident that they
+did at once distinguish them:  for we have seen that they eagerly and
+instantly seized the pupae of F. fusca, whereas they were much terrified
+when they came across the pupae, or even the earth from the nest of F.
+flava, and quickly ran away; but in about a quarter of an hour, shortly
+after all the little yellow ants had crawled away, they took heart and
+carried off the pupae.
+</para>
+
+<para>
+One evening I visited another community of F. sanguinea, and found a number
+of these ants entering their nest, carrying the dead bodies of F. fusca
+(showing that it was not a migration) and numerous pupae.  I traced the
+returning file burthened with booty, for about forty yards, to a very thick
+clump of heath, whence I saw the last individual of F. sanguinea emerge,
+carrying a pupa; but I was not able to find the desolated nest in the thick
+heath.  The nest, however, must have been close at hand, for two or three
+individuals of F. fusca were rushing about in the greatest agitation, and
+one was perched motionless with its own pupa in its mouth on the top of a
+spray of heath over its ravaged home.
+</para>
+
+<para>
+Such are the facts, though they did not need confirmation by me, in regard
+to the wonderful instinct of making slaves.  Let it be observed what a
+contrast the instinctive habits of F. sanguinea present with those of the
+F. rufescens.  The latter does not build its own nest, does not determine
+its own migrations, does not collect food for itself or its young, and
+cannot even feed itself:  it is absolutely dependent on its numerous
+slaves.  Formica sanguinea, on the other hand, possesses much fewer slaves,
+and in the early part of the summer extremely few.  The masters determine
+when and where a new nest shall be formed, and when they migrate, the
+masters carry the slaves.  Both in Switzerland and England the slaves seem
+to have the exclusive care of the larvae, and the masters alone go on
+slave-making expeditions.  In Switzerland the slaves and masters work
+together, making and bringing materials for the nest:  both, but chiefly
+the slaves, tend, and milk as it may be called, their aphides; and thus
+both collect food for the community.  In England the masters alone usually
+leave the nest to collect building materials and food for themselves, their
+slaves and larvae.  So that the masters in this country receive much less
+service from their slaves than they do in Switzerland.
+</para>
+
+<para>
+By what steps the instinct of F. sanguinea originated I will not pretend to
+conjecture.  But as ants, which are not slave-makers, will, as I have seen,
+carry off pupae of other species, if scattered near their nests, it is
+possible that pupae originally stored as food might become developed; and
+the ants thus unintentionally reared would then follow their proper
+instincts, and do what work they could.  If their presence proved useful to
+the species which had seized them--if it were more advantageous to this
+species to capture workers than to procreate them--the habit of collecting
+pupae originally for food might by natural selection be strengthened and
+rendered permanent for the very different purpose of raising slaves.  When
+the instinct was once acquired, if carried out to a much less extent even
+than in our British F. sanguinea, which, as we have seen, is less aided by
+its slaves than the same species in Switzerland, I can see no difficulty in
+natural selection increasing and modifying the instinct--always supposing
+each modification to be of use to the species--until an ant was formed as
+abjectly dependent on its slaves as is the Formica rufescens.
+</para>
+
+<para>
+Cell-making instinct of the Hive-Bee. -- I will not here enter on minute
+details on this subject, but will merely give an outline of the conclusions
+at which I have arrived.  He must be a dull man who can examine the
+exquisite structure of a comb, so beautifully adapted to its end, without
+enthusiastic admiration.  We hear from mathematicians that bees have
+practically solved a recondite problem, and have made their cells of the
+proper shape to hold the greatest possible amount of honey, with the least
+possible consumption of precious wax in their construction.  It has been
+remarked that a skilful workman, with fitting tools and measures, would
+find it very difficult to make cells of wax of the true form, though this
+is perfectly effected by a crowd of bees working in a dark hive.  Grant
+whatever instincts you please, and it seems at first quite inconceivable
+how they can make all the necessary angles and planes, or even perceive
+when they are correctly made.  But the difficulty is not nearly so great as
+it at first appears:  all this beautiful work can be shown, I think, to
+follow from a few very simple instincts.
+</para>
+
+<para>
+I was led to investigate this subject by Mr. Waterhouse, who has shown that
+the form of the cell stands in close relation to the presence of adjoining
+cells; and the following view may, perhaps, be considered only as a
+modification of this theory.  Let us look to the great principle of
+gradation, and see whether Nature does not reveal to us her method of work. 
+At one end of a short series we have humble-bees, which use their old
+cocoons to hold honey, sometimes adding to them short tubes of wax, and
+likewise making separate and very irregular rounded cells of wax.  At the
+other end of the series we have the cells of the hive-bee, placed in a
+double layer:  each cell, as is well known, is an hexagonal prism, with the
+basal edges of its six sides bevelled so as to join on to a pyramid, formed
+of three rhombs.  These rhombs have certain angles, and the three which
+form the pyramidal base of a single cell on one side of the comb, enter
+into the composition of the bases of three adjoining cells on the opposite
+side.  In the series between the extreme perfection of the cells of the
+hive-bee and the simplicity of those of the humble-bee, we have the cells
+of the Mexican Melipona domestica, carefully described and figured by
+Pierre Huber.  The Melipona itself is intermediate in structure between the
+hive and humble bee, but more nearly related to the latter:  it forms a
+nearly regular waxen comb of cylindrical cells, in which the young are
+hatched, and, in addition, some large cells of wax for holding honey. 
+These latter cells are nearly spherical and of nearly equal sizes, and are
+aggregated into an irregular mass.  But the important point to notice, is
+that these cells are always made at that degree of nearness to each other,
+that they would have intersected or broken into each other, if the spheres
+had been completed; but this is never permitted, the bees building
+perfectly flat walls of wax between the spheres which thus tend to
+intersect.  Hence each cell consists of an outer spherical portion and of
+two, three, or more perfectly flat surfaces, according as the cell adjoins
+two, three or more other cells.  When one cell comes into contact with
+three other cells, which, from the spheres being nearly of the same size,
+is very frequently and necessarily the case, the three flat surfaces are
+united into a pyramid; and this pyramid, as Huber has remarked, is
+manifestly a gross imitation of the three-sided pyramidal basis of the cell
+of the hive-bee.  As in the cells of the hive-bee, so here, the three plane
+surfaces in any one cell necessarily enter into the construction of three
+adjoining cells.  It is obvious that the Melipona saves wax by this manner
+of building; for the flat walls between the adjoining cells are not double,
+but are of the same thickness as the outer spherical portions, and yet each
+flat portion forms a part of two cells.
+</para>
+
+<para>
+Reflecting on this case, it occurred to me that if the Melipona had made
+its spheres at some given distance from each other, and had made them of
+equal sizes and had arranged them symmetrically in a double layer, the
+resulting structure would probably have been as perfect as the comb of the
+hive-bee.  Accordingly I wrote to Professor Miller, of Cambridge, and this
+geometer has kindly read over the following statement, drawn up from his
+information, and tells me that it is strictly correct:-
+</para>
+
+<para>
+If a number of equal spheres be described with their centres placed in two
+parallel layers; with the centre of each sphere at the distance of radius x
+sqrt(2) or radius x 1.41421 (or at some lesser distance), from the centres
+of the six surrounding spheres in the same layer; and at the same distance
+from the centres of the adjoining spheres in the other and parallel layer;
+then, if planes of intersection between the several spheres in both layers
+be formed, there will result a double layer of hexagonal prisms united
+together by pyramidal bases formed of three rhombs; and the rhombs and the
+sides of the hexagonal prisms will have every angle identically the same
+with the best measurements which have been made of the cells of the
+hive-bee.
+</para>
+
+<para>
+Hence we may safely conclude that if we could slightly modify the instincts
+already possessed by the Melipona, and in themselves not very wonderful,
+this bee would make a structure as wonderfully perfect as that of the
+hive-bee.  We must suppose the Melipona to make her cells truly spherical,
+and of equal sizes; and this would not be very surprising, seeing that she
+already does so to a certain extent, and seeing what perfectly cylindrical
+burrows in wood many insects can make, apparently by turning round on a
+fixed point.  We must suppose the Melipona to arrange her cells in level
+layers, as she already does her cylindrical cells; and we must further
+suppose, and this is the greatest difficulty, that she can somehow judge
+accurately at what distance to stand from her fellow-labourers when several
+are making their spheres; but she is already so far enabled to judge of
+distance, that she always describes her spheres so as to intersect largely;
+and then she unites the points of intersection by perfectly flat surfaces. 
+We have further to suppose, but this is no difficulty, that after hexagonal
+prisms have been formed by the intersection of adjoining spheres in the
+same layer, she can prolong the hexagon to any length requisite to hold the
+stock of honey; in the same way as the rude humble-bee adds cylinders of
+wax to the circular mouths of her old cocoons.  By such modifications of
+instincts in themselves not very wonderful,--hardly more wonderful than
+those which guide a bird to make its nest,--I believe that the hive-bee has
+acquired, through natural selection, her inimitable architectural powers.
+</para>
+
+<para>
+But this theory can be tested by experiment.  Following the example of Mr.
+Tegetmeier, I separated two combs, and put between them a long, thick,
+square strip of wax:  the bees instantly began to excavate minute circular
+pits in it; and as they deepened these little pits, they made them wider
+and wider until they were converted into shallow basins, appearing to the
+eye perfectly true or parts of a sphere, and of about the diameter of a
+cell.  It was most interesting to me to observe that wherever several bees
+had begun to excavate these basins near together, they had begun their work
+at such a distance from each other, that by the time the basins had
+acquired the above stated width (i.e. about the width of an ordinary cell),
+and were in depth about one sixth of the diameter of the sphere of which
+they formed a part, the rims of the basins intersected or broke into each
+other.  As soon as this occurred, the bees ceased to excavate, and began to
+build up flat walls of wax on the lines of intersection between the basins,
+so that each hexagonal prism was built upon the festooned edge of a smooth
+basin, instead of on the straight edges of a three-sided pyramid as in the
+case of ordinary cells.
+</para>
+
+<para>
+I then put into the hive, instead of a thick, square piece of wax, a thin
+and narrow, knife-edged ridge, coloured with vermilion.  The bees instantly
+began on both sides to excavate little basins near to each other, in the
+same way as before; but the ridge of wax was so thin, that the bottoms of
+the basins, if they had been excavated to the same depth as in the former
+experiment, would have broken into each other from the opposite sides.  The
+bees, however, did not suffer this to happen, and they stopped their
+excavations in due time; so that the basins, as soon as they had been a
+little deepened, came to have flat bottoms; and these flat bottoms, formed
+by thin little plates of the vermilion wax having been left ungnawed, were
+situated, as far as the eye could judge, exactly along the planes of
+imaginary intersection between the basins on the opposite sides of the
+ridge of wax.  In parts, only little bits, in other parts, large portions
+of a rhombic plate had been left between the opposed basins, but the work,
+from the unnatural state of things, had not been neatly performed.  The
+bees must have worked at very nearly the same rate on the opposite sides of
+the ridge of vermilion wax, as they circularly gnawed away and deepened the
+basins on both sides, in order to have succeeded in thus leaving flat
+plates between the basins, by stopping work along the intermediate planes
+or planes of intersection.
+</para>
+
+<para>
+Considering how flexible thin wax is, I do not see that there is any
+difficulty in the bees, whilst at work on the two sides of a strip of wax,
+perceiving when they have gnawed the wax away to the proper thinness, and
+then stopping their work.  In ordinary combs it has appeared to me that the
+bees do not always succeed in working at exactly the same rate from the
+opposite sides; for I have noticed half-completed rhombs at the base of a
+just-commenced cell, which were slightly concave on one side, where I
+suppose that the bees had excavated too quickly, and convex on the opposed
+side, where the bees had worked less quickly.  In one well-marked instance,
+I put the comb back into the hive, and allowed the bees to go on working
+for a short time, and again examined the cell, and I found that the rhombic
+plate had been completed, and had become perfectly flat:  it was absolutely
+impossible, from the extreme thinness of the little rhombic plate, that
+they could have effected this by gnawing away the convex side; and I
+suspect that the bees in such cases stand in the opposed cells and push and
+bend the ductile and warm wax (which as I have tried is easily done) into
+its proper intermediate plane, and thus flatten it.
+</para>
+
+<para>
+From the experiment of the ridge of vermilion wax, we can clearly see that
+if the bees were to build for themselves a thin wall of wax, they could
+make their cells of the proper shape, by standing at the proper distance
+from each other, by excavating at the same rate, and by endeavouring to
+make equal spherical hollows, but never allowing the spheres to break into
+each other.  Now bees, as may be clearly seen by examining the edge of a
+growing comb, do make a rough, circumferential wall or rim all round the
+comb; and they gnaw into this from the opposite sides, always working
+circularly as they deepen each cell.  They do not make the whole
+three-sided pyramidal base of any one cell at the same time, but only the
+one rhombic plate which stands on the extreme growing margin, or the two
+plates, as the case may be; and they never complete the upper edges of the
+rhombic plates, until the hexagonal walls are commenced.  Some of these
+statements differ from those made by the justly celebrated elder Huber, but
+I am convinced of their accuracy; and if I had space, I could show that
+they are conformable with my theory.
+</para>
+
+<para>
+Huber's statement that the very first cell is excavated out of a little
+parallel-sided wall of wax, is not, as far as I have seen, strictly
+correct; the first commencement having always been a little hood of wax;
+but I will not here enter on these details.  We see how important a part
+excavation plays in the construction of the cells; but it would be a great
+error to suppose that the bees cannot build up a rough wall of wax in the
+proper position--that is, along the plane of intersection between two
+adjoining spheres.  I have several specimens showing clearly that they can
+do this.  Even in the rude circumferential rim or wall of wax round a
+growing comb, flexures may sometimes be observed, corresponding in position
+to the planes of the rhombic basal plates of future cells.  But the rough
+wall of wax has in every case to be finished off, by being largely gnawed
+away on both sides.  The manner in which the bees build is curious; they
+always make the first rough wall from ten to twenty times thicker than the
+excessively thin finished wall of the cell, which will ultimately be left. 
+We shall understand how they work, by supposing masons first to pile up a
+broad ridge of cement, and then to begin cutting it away equally on both
+sides near the ground, till a smooth, very thin wall is left in the middle;
+the masons always piling up the cut-away cement, and adding fresh cement,
+on the summit of the ridge.  We shall thus have a thin wall steadily
+growing upward; but always crowned by a gigantic coping.  From all the
+cells, both those just commenced and those completed, being thus crowned by
+a strong coping of wax, the bees can cluster and crawl over the comb
+without injuring the delicate hexagonal walls, which are only about one
+four-hundredth of an inch in thickness; the plates of the pyramidal basis
+being about twice as thick.  By this singular manner of building, strength
+is continually given to the comb, with the utmost ultimate economy of wax.
+</para>
+
+<para>
+It seems at first to add to the difficulty of understanding how the cells
+are made, that a multitude of bees all work together; one bee after working
+a short time at one cell going to another, so that, as Huber has stated, a
+score of individuals work even at the commencement of the first cell.  I
+was able practically to show this fact, by covering the edges of the
+hexagonal walls of a single cell, or the extreme margin of the
+circumferential rim of a growing comb, with an extremely thin layer of
+melted vermilion wax; and I invariably found that the colour was most
+delicately diffused by the bees--as delicately as a painter could have done
+with his brush--by atoms of the coloured wax having been taken from the
+spot on which it had been placed, and worked into the growing edges of the
+cells all round.  The work of construction seems to be a sort of balance
+struck between many bees, all instinctively standing at the same relative
+distance from each other, all trying to sweep equal spheres, and then
+building up, or leaving ungnawed, the planes of intersection between these
+spheres.  It was really curious to note in cases of difficulty, as when two
+pieces of comb met at an angle, how often the bees would entirely pull down
+and rebuild in different ways the same cell, sometimes recurring to a shape
+which they had at first rejected.
+</para>
+
+<para>
+When bees have a place on which they can stand in their proper positions
+for working,--for instance, on a slip of wood, placed directly under the
+middle of a comb growing downwards so that the comb has to be built over
+one face of the slip--in this case the bees can lay the foundations of one
+wall of a new hexagon, in its strictly proper place, projecting beyond the
+other completed cells.  It suffices that the bees should be enabled to
+stand at their proper relative distances from each other and from the walls
+of the last completed cells, and then, by striking imaginary spheres, they
+can build up a wall intermediate between two adjoining spheres; but, as far
+as I have seen, they never gnaw away and finish off the angles of a cell
+till a large part both of that cell and of the adjoining cells has been
+built.  This capacity in bees of laying down under certain circumstances a
+rough wall in its proper place between two just-commenced cells, is
+important, as it bears on a fact, which seems at first quite subversive of
+the foregoing theory; namely, that the cells on the extreme margin of
+wasp-combs are sometimes strictly hexagonal; but I have not space here to
+enter on this subject.  Nor does there seem to me any great difficulty in a
+single insect (as in the case of a queen-wasp) making hexagonal cells, if
+she work alternately on the inside and outside of two or three cells
+commenced at the same time, always standing at the proper relative distance
+from the parts of the cells just begun, sweeping spheres or cylinders, and
+building up intermediate planes.  It is even conceivable that an insect
+might, by fixing on a point at which to commence a cell, and then moving
+outside, first to one point, and then to five other points, at the proper
+relative distances from the central point and from each other, strike the
+planes of intersection, and so make an isolated hexagon:  but I am not
+aware that any such case has been observed; nor would any good be derived
+from a single hexagon being built, as in its construction more materials
+would be required than for a cylinder.
+</para>
+
+<para>
+As natural selection acts only by the accumulation of slight modifications
+of structure or instinct, each profitable to the individual under its
+conditions of life, it may reasonably be asked, how a long and graduated
+succession of modified architectural instincts, all tending towards the
+present perfect plan of construction, could have profited the progenitors
+of the hive-bee?  I think the answer is not difficult:  it is known that
+bees are often hard pressed to get sufficient nectar; and I am informed by
+Mr. Tegetmeier that it has been experimentally found that no less than from
+twelve to fifteen pounds of dry sugar are consumed by a hive of bees for
+the secretion of each pound of wax; so that a prodigious quantity of fluid
+nectar must be collected and consumed by the bees in a hive for the
+secretion of the wax necessary for the construction of their combs. 
+Moreover, many bees have to remain idle for many days during the process of
+secretion.  A large store of honey is indispensable to support a large
+stock of bees during the winter; and the security of the hive is known
+mainly to depend on a large number of bees being supported.  Hence the
+saving of wax by largely saving honey must be a most important element of
+success in any family of bees.  Of course the success of any species of bee
+may be dependent on the number of its parasites or other enemies, or on
+quite distinct causes, and so be altogether independent of the quantity of
+honey which the bees could collect.  But let us suppose that this latter
+circumstance determined, as it probably often does determine, the numbers
+of a humble-bee which could exist in a country; and let us further suppose
+that the community lived throughout the winter, and consequently required a
+store of honey:  there can in this case be no doubt that it would be an
+advantage to our humble-bee, if a slight modification of her instinct led
+her to make her waxen cells near together, so as to intersect a little; for
+a wall in common even to two adjoining cells, would save some little wax. 
+Hence it would continually be more and more advantageous to our humble-bee,
+if she were to make her cells more and more regular, nearer together, and
+aggregated into a mass, like the cells of the Melipona; for in this case a
+large part of the bounding surface of each cell would serve to bound other
+cells, and much wax would be saved.  Again, from the same cause, it would
+be advantageous to the Melipona, if she were to make her cells closer
+together, and more regular in every way than at present; for then, as we
+have seen, the spherical surfaces would wholly disappear, and would all be
+replaced by plane surfaces; and the Melipona would make a comb as perfect
+as that of the hive-bee.  Beyond this stage of perfection in architecture,
+natural selection could not lead; for the comb of the hive-bee, as far as
+we can see, is absolutely perfect in economising wax.
+</para>
+
+<para>
+Thus, as I believe, the most wonderful of all known instincts, that of the
+hive-bee, can be explained by natural selection having taken advantage of
+numerous, successive, slight modifications of simpler instincts; natural
+selection having by slow degrees, more and more perfectly, led the bees to
+sweep equal spheres at a given distance from each other in a double layer,
+and to build up and excavate the wax along the planes of intersection.  The
+bees, of course, no more knowing that they swept their spheres at one
+particular distance from each other, than they know what are the several
+angles of the hexagonal prisms and of the basal rhombic plates.  The motive
+power of the process of natural selection having been economy of wax; that
+individual swarm which wasted least honey in the secretion of wax, having
+succeeded best, and having transmitted by inheritance its newly acquired
+economical instinct to new swarms, which in their turn will have had the
+best chance of succeeding in the struggle for existence.
+</para>
+
+<para>
+No doubt many instincts of very difficult explanation could be opposed to
+the theory of natural selection,--cases, in which we cannot see how an
+instinct could possibly have originated; cases, in which no intermediate
+gradations are known to exist; cases of instinct of apparently such
+trifling importance, that they could hardly have been acted on by natural
+selection; cases of instincts almost identically the same in animals so
+remote in the scale of nature, that we cannot account for their similarity
+by inheritance from a common parent, and must therefore believe that they
+have been acquired by independent acts of natural selection.  I will not
+here enter on these several cases, but will confine myself to one special
+difficulty, which at first appeared to me insuperable, and actually fatal
+to my whole theory.  I allude to the neuters or sterile females in
+insect-communities:  for these neuters often differ widely in instinct and
+in structure from both the males and fertile females, and yet, from being
+sterile, they cannot propagate their kind.
+</para>
+
+<para>
+The subject well deserves to be discussed at great length, but I will here
+take only a single case, that of working or sterile ants.  How the workers
+have been rendered sterile is a difficulty; but not much greater than that
+of any other striking modification of structure; for it can be shown that
+some insects and other articulate animals in a state of nature occasionally
+become sterile; and if such insects had been social, and it had been
+profitable to the community that a number should have been annually born
+capable of work, but incapable of procreation, I can see no very great
+difficulty in this being effected by natural selection.  But I must pass
+over this preliminary difficulty.  The great difficulty lies in the working
+ants differing widely from both the males and the fertile females in
+structure, as in the shape of the thorax and in being destitute of wings
+and sometimes of eyes, and in instinct.  As far as instinct alone is
+concerned, the prodigious difference in this respect between the workers
+and the perfect females, would have been far better exemplified by the
+hive-bee.  If a working ant or other neuter insect had been an animal in
+the ordinary state, I should have unhesitatingly assumed that all its
+characters had been slowly acquired through natural selection; namely, by
+an individual having been born with some slight profitable modification of
+structure, this being inherited by its offspring, which again varied and
+were again selected, and so onwards.  But with the working ant we have an
+insect differing greatly from its parents, yet absolutely sterile; so that
+it could never have transmitted successively acquired modifications of
+structure or instinct to its progeny.  It may well be asked how is it
+possible to reconcile this case with the theory of natural selection?
+</para>
+
+<para>
+First, let it be remembered that we have innumerable instances, both in our
+domestic productions and in those in a state of nature, of all sorts of
+differences of structure which have become correlated to certain ages, and
+to either sex.  We have differences correlated not only to one sex, but to
+that short period alone when the reproductive system is active, as in the
+nuptial plumage of many birds, and in the hooked jaws of the male salmon. 
+We have even slight differences in the horns of different breeds of cattle
+in relation to an artificially imperfect state of the male sex; for oxen of
+certain breeds have longer horns than in other breeds, in comparison with
+the horns of the bulls or cows of these same breeds.  Hence I can see no
+real difficulty in any character having become correlated with the sterile
+condition of certain members of insect-communities:  the difficulty lies in
+understanding how such correlated modifications of structure could have
+been slowly accumulated by natural selection.
+</para>
+
+<para>
+This difficulty, though appearing insuperable, is lessened, or, as I
+believe, disappears, when it is remembered that selection may be applied to
+the family, as well as to the individual, and may thus gain the desired
+end.  Thus, a well-flavoured vegetable is cooked, and the individual is
+destroyed; but the horticulturist sows seeds of the same stock, and
+confidently expects to get nearly the same variety; breeders of cattle wish
+the flesh and fat to be well marbled together; the animal has been
+slaughtered, but the breeder goes with confidence to the same family.  I
+have such faith in the powers of selection, that I do not doubt that a
+breed of cattle, always yielding oxen with extraordinarily long horns,
+could be slowly formed by carefully watching which individual bulls and
+cows, when matched, produced oxen with the longest horns; and yet no one ox
+could ever have propagated its kind.  Thus I believe it has been with
+social insects:  a slight modification of structure, or instinct,
+correlated with the sterile condition of certain members of the community,
+has been advantageous to the community:  consequently the fertile males and
+females of the same community flourished, and transmitted to their fertile
+offspring a tendency to produce sterile members having the same
+modification.  And I believe that this process has been repeated, until
+that prodigious amount of difference between the fertile and sterile
+females of the same species has been produced, which we see in many social
+insects.
+</para>
+
+<para>
+But we have not as yet touched on the climax of the difficulty; namely, the
+fact that the neuters of several ants differ, not only from the fertile
+females and males, but from each other, sometimes to an almost incredible
+degree, and are thus divided into two or even three castes.  The castes,
+moreover, do not generally graduate into each other, but are perfectly well
+defined; being as distinct from each other, as are any two species of the
+same genus, or rather as any two genera of the same family.  Thus in
+Eciton, there are working and soldier neuters, with jaws and instincts
+extraordinarily different:  in Cryptocerus, the workers of one caste alone
+carry a wonderful sort of shield on their heads, the use of which is quite
+unknown:  in the Mexican Myrmecocystus, the workers of one caste never
+leave the nest; they are fed by the workers of another caste, and they have
+an enormously developed abdomen which secretes a sort of honey, supplying
+the place of that excreted by the aphides, or the domestic cattle as they
+may be called, which our European ants guard or imprison.
+</para>
+
+<para>
+It will indeed be thought that I have an overweening confidence in the
+principle of natural selection, when I do not admit that such wonderful and
+well-established facts at once annihilate my theory.  In the simpler case
+of neuter insects all of one caste or of the same kind, which have been
+rendered by natural selection, as I believe to be quite possible, different
+from the fertile males and females,--in this case, we may safely conclude
+from the analogy of ordinary variations, that each successive, slight,
+profitable modification did not probably at first appear in all the
+individual neuters in the same nest, but in a few alone; and that by the
+long-continued selection of the fertile parents which produced most neuters
+with the profitable modification, all the neuters ultimately came to have
+the desired character.  On this view we ought occasionally to find
+neuter-insects of the same species, in the same nest, presenting gradations
+of structure; and this we do find, even often, considering how few
+neuter-insects out of Europe have been carefully examined.  Mr. F. Smith
+has shown how surprisingly the neuters of several British ants differ from
+each other in size and sometimes in colour; and that the extreme forms can
+sometimes be perfectly linked together by individuals taken out of the same
+nest:  I have myself compared perfect gradations of this kind.  It often
+happens that the larger or the smaller sized workers are the most numerous;
+or that both large and small are numerous, with those of an intermediate
+size scanty in numbers.  Formica flava has larger and smaller workers, with
+some of intermediate size; and, in this species, as Mr. F. Smith has
+observed, the larger workers have simple eyes (ocelli), which though small
+can be plainly distinguished, whereas the smaller workers have their ocelli
+rudimentary.  Having carefully dissected several specimens of these
+workers, I can affirm that the eyes are far more rudimentary in the smaller
+workers than can be accounted for merely by their proportionally lesser
+size; and I fully believe, though I dare not assert so positively, that the
+workers of intermediate size have their ocelli in an exactly intermediate
+condition.  So that we here have two bodies of sterile workers in the same
+nest, differing not only in size, but in their organs of vision, yet
+connected by some few members in an intermediate condition.  I may digress
+by adding, that if the smaller workers had been the most useful to the
+community, and those males and females had been continually selected, which
+produced more and more of the smaller workers, until all the workers had
+come to be in this condition; we should then have had a species of ant with
+neuters very nearly in the same condition with those of Myrmica.  For the
+workers of Myrmica have not even rudiments of ocelli, though the male and
+female ants of this genus have well-developed ocelli.
+</para>
+
+<para>
+I may give one other case:  so confidently did I expect to find gradations
+in important points of structure between the different castes of neuters in
+the same species, that I gladly availed myself of Mr. F. Smith's offer of
+numerous specimens from the same nest of the driver ant (Anomma) of West
+Africa.  The reader will perhaps best appreciate the amount of difference
+in these workers, by my giving not the actual measurements, but a strictly
+accurate illustration:  the difference was the same as if we were to see a
+set of workmen building a house of whom many were five feet four inches
+high, and many sixteen feet high; but we must suppose that the larger
+workmen had heads four instead of three times as big as those of the
+smaller men, and jaws nearly five times as big.  The jaws, moreover, of the
+working ants of the several sizes differed wonderfully in shape, and in the
+form and number of the teeth.  But the important fact for us is, that
+though the workers can be grouped into castes of different sizes, yet they
+graduate insensibly into each other, as does the widely-different structure
+of their jaws.  I speak confidently on this latter point, as Mr. Lubbock
+made drawings for me with the camera lucida of the jaws which I had
+dissected from the workers of the several sizes.
+</para>
+
+<para>
+With these facts before me, I believe that natural selection, by acting on
+the fertile parents, could form a species which should regularly produce
+neuters, either all of large size with one form of jaw, or all of small
+size with jaws having a widely different structure; or lastly, and this is
+our climax of difficulty, one set of workers of one size and structure, and
+simultaneously another set of workers of a different size and structure;--a
+graduated series having been first formed, as in the case of the driver
+ant, and then the extreme forms, from being the most useful to the
+community, having been produced in greater and greater numbers through the
+natural selection of the parents which generated them; until none with an
+intermediate structure were produced.
+</para>
+
+<para>
+Thus, as I believe, the wonderful fact of two distinctly defined castes of
+sterile workers existing in the same nest, both widely different from each
+other and from their parents, has originated.  We can see how useful their
+production may have been to a social community of insects, on the same
+principle that the division of labour is useful to civilised man.  As ants
+work by inherited instincts and by inherited tools or weapons, and not by
+acquired knowledge and manufactured instruments, a perfect division of
+labour could be effected with them only by the workers being sterile; for
+had they been fertile, they would have intercrossed, and their instincts
+and structure would have become blended.  And nature has, as I believe,
+effected this admirable division of labour in the communities of ants, by
+the means of natural selection.  But I am bound to confess, that, with all
+my faith in this principle, I should never have anticipated that natural
+selection could have been efficient in so high a degree, had not the case
+of these neuter insects convinced me of the fact.  I have, therefore,
+discussed this case, at some little but wholly insufficient length, in
+order to show the power of natural selection, and likewise because this is
+by far the most serious special difficulty, which my theory has
+encountered.  The case, also, is very interesting, as it proves that with
+animals, as with plants, any amount of modification in structure can be
+effected by the accumulation of numerous, slight, and as we must call them
+accidental, variations, which are in any manner profitable, without
+exercise or habit having come into play.  For no amount of exercise, or
+habit, or volition, in the utterly sterile members of a community could
+possibly have affected the structure or instincts of the fertile members,
+which alone leave descendants.  I am surprised that no one has advanced
+this demonstrative case of neuter insects, against the well-known doctrine
+of Lamarck.
+</para>
+
+<para>
+Summary. -- I have endeavoured briefly in this chapter to show that the
+mental qualities of our domestic animals vary, and that the variations are
+inherited.  Still more briefly I have attempted to show that instincts vary
+slightly in a state of nature.  No one will dispute that instincts are of
+the highest importance to each animal.  Therefore I can see no difficulty,
+under changing conditions of life, in natural selection accumulating slight
+modifications of instinct to any extent, in any useful direction.  In some
+cases habit or use and disuse have probably come into play.  I do not
+pretend that the facts given in this chapter strengthen in any great degree
+my theory; but none of the cases of difficulty, to the best of my judgment,
+annihilate it.  On the other hand, the fact that instincts are not always
+absolutely perfect and are liable to mistakes;--that no instinct has been
+produced for the exclusive good of other animals, but that each animal
+takes advantage of the instincts of others;--that the canon in natural
+history, of 'natura non facit saltum' is applicable to instincts as well as
+to corporeal structure, and is plainly explicable on the foregoing views,
+but is otherwise inexplicable,--all tend to corroborate the theory of
+natural selection.
+</para>
+
+<para>
+This theory is, also, strengthened by some few other facts in regard to
+instincts; as by that common case of closely allied, but certainly
+distinct, species, when inhabiting distant parts of the world and living
+under considerably different conditions of life, yet often retaining nearly
+the same instincts.  For instance, we can understand on the principle of
+inheritance, how it is that the thrush of South America lines its nest with
+mud, in the same peculiar manner as does our British thrush:  how it is
+that the male wrens (Troglodytes) of North America, build 'cock-nests,' to
+roost in, like the males of our distinct Kitty-wrens,--a habit wholly
+unlike that of any other known bird.  Finally, it may not be a logical
+deduction, but to my imagination it is far more satisfactory to look at
+such instincts as the young cuckoo ejecting its foster-brothers,--ants
+making slaves,--the larvae of ichneumonidae feeding within the live bodies
+of caterpillars,--not as specially endowed or created instincts, but as
+small consequences of one general law, leading to the advancement of all
+organic beings, namely, multiply, vary, let the strongest live and the
+weakest die.
+</para>
+
+</chapter>
+
+<chapter>
+<chapheader>
+
+<chapnum>Chapter VIII</chapnum>
+
+<title>Hybridism</title>
+
+<chapsummary>
+Distinction between the sterility of first crosses and of hybrids --
+Sterility various in degree, not universal, affected by close
+interbreeding, removed by domestication -- Laws governing the sterility of
+hybrids -- Sterility not a special endowment, but incidental on other
+differences -- Causes of the sterility of first crosses and of hybrids --
+Parallelism between the effects of changed conditions of life and crossing
+-- Fertility of varieties when crossed and of their mongrel offspring not
+universal -- Hybrids and mongrels compared independently of their fertility
+-- Summary.
+</chapsummary>
+</chapheader>
+
+<para>
+The view generally entertained by naturalists is that species, when
+intercrossed, have been specially endowed with the quality of sterility, in
+order to prevent the confusion of all organic forms.  This view certainly
+seems at first probable, for species within the same country could hardly
+have kept distinct had they been capable of crossing freely.  The
+importance of the fact that hybrids are very generally sterile, has, I
+think, been much underrated by some late writers.  On the theory of natural
+selection the case is especially important, inasmuch as the sterility of
+hybrids could not possibly be of any advantage to them, and therefore could
+not have been acquired by the continued preservation of successive
+profitable degrees of sterility.  I hope, however, to be able to show that
+sterility is not a specially acquired or endowed quality, but is incidental
+on other acquired differences.
+</para>
+
+<para>
+In treating this subject, two classes of facts, to a large extent
+fundamentally different, have generally been confounded together; namely,
+the sterility of two species when first crossed, and the sterility of the
+hybrids produced from them.
+</para>
+
+<para>
+Pure species have of course their organs of reproduction in a perfect
+condition, yet when intercrossed they produce either few or no offspring. 
+Hybrids, on the other hand, have their reproductive organs functionally
+impotent, as may be clearly seen in the state of the male element in both
+plants and animals; though the organs themselves are perfect in structure,
+as far as the microscope reveals.  In the first case the two sexual
+elements which go to form the embryo are perfect; in the second case they
+are either not at all developed, or are imperfectly developed.  This
+distinction is important, when the cause of the sterility, which is common
+to the two cases, has to be considered.  The distinction has probably been
+slurred over, owing to the sterility in both cases being looked on as a
+special endowment, beyond the province of our reasoning powers.
+</para>
+
+<para>
+The fertility of varieties, that is of the forms known or believed to have
+descended from common parents, when intercrossed, and likewise the
+fertility of their mongrel offspring, is, on my theory, of equal importance
+with the sterility of species; for it seems to make a broad and clear
+distinction between varieties and species.
+</para>
+
+<para>
+First, for the sterility of species when crossed and of their hybrid
+offspring.  It is impossible to study the several memoirs and works of
+those two conscientious and admirable observers, Kolreuter and Gartner, who
+almost devoted their lives to this subject, without being deeply impressed
+with the high generality of some degree of sterility.  Kolreuter makes the
+rule universal; but then he cuts the knot, for in ten cases in which he
+found two forms, considered by most authors as distinct species, quite
+fertile together, he unhesitatingly ranks them as varieties.  Gartner,
+also, makes the rule equally universal; and he disputes the entire
+fertility of Kolreuter's ten cases.  But in these and in many other cases,
+Gartner is obliged carefully to count the seeds, in order to show that
+there is any degree of sterility.  He always compares the maximum number of
+seeds produced by two species when crossed and by their hybrid offspring,
+with the average number produced by both pure parent-species in a state of
+nature.  But a serious cause of error seems to me to be here introduced:  a
+plant to be hybridised must be castrated, and, what is often more
+important, must be secluded in order to prevent pollen being brought to it
+by insects from other plants.  Nearly all the plants experimentised on by
+Gartner were potted, and apparently were kept in a chamber in his house. 
+That these processes are often injurious to the fertility of a plant cannot
+be doubted; for Gartner gives in his table about a score of cases of plants
+which he castrated, and artificially fertilised with their own pollen, and
+(excluding all cases such as the Leguminosae, in which there is an
+acknowledged difficulty in the manipulation) half of these twenty plants
+had their fertility in some degree impaired.  Moreover, as Gartner during
+several years repeatedly crossed the primrose and cowslip, which we have
+such good reason to believe to be varieties, and only once or twice
+succeeded in getting fertile seed; as he found the common red and blue
+pimpernels (Anagallis arvensis and coerulea), which the best botanists rank
+as varieties, absolutely sterile together; and as he came to the same
+conclusion in several other analogous cases; it seems to me that we may
+well be permitted to doubt whether many other species are really so
+sterile, when intercrossed, as Gartner believes.
+</para>
+
+<para>
+It is certain, on the one hand, that the sterility of various species when
+crossed is so different in degree and graduates away so insensibly, and, on
+the other hand, that the fertility of pure species is so easily affected by
+various circumstances, that for all practical purposes it is most difficult
+to say where perfect fertility ends and sterility begins.  I think no
+better evidence of this can be required than that the two most experienced
+observers who have ever lived, namely, Kolreuter and Gartner, should have
+arrived at diametrically opposite conclusions in regard to the very same
+species.  It is also most instructive to compare--but I have not space here
+to enter on details--the evidence advanced by our best botanists on the
+question whether certain doubtful forms should be ranked as species or
+varieties, with the evidence from fertility adduced by different
+hybridisers, or by the same author, from experiments made during different
+years.  It can thus be shown that neither sterility nor fertility affords
+any clear distinction between species and varieties; but that the evidence
+from this source graduates away, and is doubtful in the same degree as is
+the evidence derived from other constitutional and structural differences.
+</para>
+
+<para>
+In regard to the sterility of hybrids in successive generations; though
+Gartner was enabled to rear some hybrids, carefully guarding them from a
+cross with either pure parent, for six or seven, and in one case for ten
+generations, yet he asserts positively that their fertility never
+increased, but generally greatly decreased.  I do not doubt that this is
+usually the case, and that the fertility often suddenly decreases in the
+first few generations.  Nevertheless I believe that in all these
+experiments the fertility has been diminished by an independent cause,
+namely, from close interbreeding.  I have collected so large a body of
+facts, showing that close interbreeding lessens fertility, and, on the
+other hand, that an occasional cross with a distinct individual or variety
+increases fertility, that I cannot doubt the correctness of this almost
+universal belief amongst breeders.  Hybrids are seldom raised by
+experimentalists in great numbers; and as the parent-species, or other
+allied hybrids, generally grow in the same garden, the visits of insects
+must be carefully prevented during the flowering season:  hence hybrids
+will generally be fertilised during each generation by their own individual
+pollen; and I am convinced that this would be injurious to their fertility,
+already lessened by their hybrid origin.  I am strengthened in this
+conviction by a remarkable statement repeatedly made by Gartner, namely,
+that if even the less fertile hybrids be artificially fertilised with
+hybrid pollen of the same kind, their fertility, notwithstanding the
+frequent ill effects of manipulation, sometimes decidedly increases, and
+goes on increasing.  Now, in artificial fertilisation pollen is as often
+taken by chance (as I know from my own experience) from the anthers of
+another flower, as from the anthers of the flower itself which is to be
+fertilised; so that a cross between two flowers, though probably on the
+same plant, would be thus effected.  Moreover, whenever complicated
+experiments are in progress, so careful an observer as Gartner would have
+castrated his hybrids, and this would have insured in each generation a
+cross with the pollen from a distinct flower, either from the same plant or
+from another plant of the same hybrid nature.  And thus, the strange fact
+of the increase of fertility in the successive generations of artificially
+fertilised hybrids may, I believe, be accounted for by close interbreeding
+having been avoided.
+</para>
+
+<para>
+Now let us turn to the results arrived at by the third most experienced
+hybridiser, namely, the Hon. and Rev. W. Herbert.  He is as emphatic in his
+conclusion that some hybrids are perfectly fertile--as fertile as the pure
+parent-species--as are Kolreuter and Gartner that some degree of sterility
+between distinct species is a universal law of nature.  He experimentised
+on some of the very same species as did Gartner.  The difference in their
+results may, I think, be in part accounted for by Herbert's great
+horticultural skill, and by his having hothouses at his command.  Of his
+many important statements I will here give only a single one as an example,
+namely, that 'every ovule in a pod of Crinum capense fertilised by C.
+revolutum produced a plant, which (he says) I never saw to occur in a case
+of its natural fecundation.'  So that we here have perfect, or even more
+than commonly perfect, fertility in a first cross between two distinct
+species.
+</para>
+
+<para>
+This case of the Crinum leads me to refer to a most singular fact, namely,
+that there are individual plants, as with certain species of Lobelia, and
+with all the species of the genus Hippeastrum, which can be far more easily
+fertilised by the pollen of another and distinct species, than by their own
+pollen.  For these plants have been found to yield seed to the pollen of a
+distinct species, though quite sterile with their own pollen,
+notwithstanding that their own pollen was found to be perfectly good, for
+it fertilised distinct species.  So that certain individual plants and all
+the individuals of certain species can actually be hybridised much more
+readily than they can be self-fertilised!  For instance, a bulb of
+Hippeastrum aulicum produced four flowers; three were fertilised by Herbert
+with their own pollen, and the fourth was subsequently fertilised by the
+pollen of a compound hybrid descended from three other and distinct
+species:  the result was that 'the ovaries of the three first flowers soon
+ceased to grow, and after a few days perished entirely, whereas the pod
+impregnated by the pollen of the hybrid made vigorous growth and rapid
+progress to maturity, and bore good seed, which vegetated freely.'  In a
+letter to me, in 1839, Mr. Herbert told me that he had then tried the
+experiment during five years, and he continued to try it during several
+subsequent years, and always with the same result.  This result has, also,
+been confirmed by other observers in the case of Hippeastrum with its
+sub-genera, and in the case of some other genera, as Lobelia, Passiflora
+and Verbascum.  Although the plants in these experiments appeared perfectly
+healthy, and although both the ovules and pollen of the same flower were
+perfectly good with respect to other species, yet as they were functionally
+imperfect in their mutual self-action, we must infer that the plants were
+in an unnatural state.  Nevertheless these facts show on what slight and
+mysterious causes the lesser or greater fertility of species when crossed,
+in comparison with the same species when self-fertilised, sometimes
+depends.
+</para>
+
+<para>
+The practical experiments of horticulturists, though not made with
+scientific precision, deserve some notice.  It is notorious in how
+complicated a manner the species of Pelargonium, Fuchsia, Calceolaria,
+Petunia, Rhododendron, &amp;c., have been crossed, yet many of these hybrids
+seed freely.  For instance, Herbert asserts that a hybrid from Calceolaria
+integrifolia and plantaginea, species most widely dissimilar in general
+habit, 'reproduced itself as perfectly as if it had been a natural species
+from the mountains of Chile.'  I have taken some pains to ascertain the
+degree of fertility of some of the complex crosses of Rhododendrons, and I
+am assured that many of them are perfectly fertile.  Mr. C. Noble, for
+instance, informs me that he raises stocks for grafting from a hybrid
+between Rhod. Ponticum and Catawbiense, and that this hybrid 'seeds as
+freely as it is possible to imagine.'  Had hybrids, when fairly treated,
+gone on decreasing in fertility in each successive generation, as Gartner
+believes to be the case, the fact would have been notorious to nurserymen. 
+Horticulturists raise large beds of the same hybrids, and such alone are
+fairly treated, for by insect agency the several individuals of the same
+hybrid variety are allowed to freely cross with each other, and the
+injurious influence of close interbreeding is thus prevented.  Any one may
+readily convince himself of the efficiency of insect-agency by examining
+the flowers of the more sterile kinds of hybrid rhododendrons, which
+produce no pollen, for he will find on their stigmas plenty of pollen
+brought from other flowers.
+</para>
+
+<para>
+In regard to animals, much fewer experiments have been carefully tried than
+with plants.  If our systematic arrangements can be trusted, that is if the
+genera of animals are as distinct from each other, as are the genera of
+plants, then we may infer that animals more widely separated in the scale
+of nature can be more easily crossed than in the case of plants; but the
+hybrids themselves are, I think, more sterile.  I doubt whether any case of
+a perfectly fertile hybrid animal can be considered as thoroughly well
+authenticated.  It should, however, be borne in mind that, owing to few
+animals breeding freely under confinement, few experiments have been fairly
+tried:  for instance, the canary-bird has been crossed with nine other
+finches, but as not one of these nine species breeds freely in confinement,
+we have no right to expect that the first crosses between them and the
+canary, or that their hybrids, should be perfectly fertile.  Again, with
+respect to the fertility in successive generations of the more fertile
+hybrid animals, I hardly know of an instance in which two families of the
+same hybrid have been raised at the same time from different parents, so as
+to avoid the ill effects of close interbreeding.  On the contrary, brothers
+and sisters have usually been crossed in each successive generation, in
+opposition to the constantly repeated admonition of every breeder.  And in
+this case, it is not at all surprising that the inherent sterility in the
+hybrids should have gone on increasing.  If we were to act thus, and pair
+brothers and sisters in the case of any pure animal, which from any cause
+had the least tendency to sterility, the breed would assuredly be lost in a
+very few generations.
+</para>
+
+<para>
+Although I do not know of any thoroughly well-authenticated cases of
+perfectly fertile hybrid animals, I have some reason to believe that the
+hybrids from Cervulus vaginalis and Reevesii, and from Phasianus colchicus
+with P. torquatus and with P. versicolor are perfectly fertile.  The
+hybrids from the common and Chinese geese (A. cygnoides), species which are
+so different that they are generally ranked in distinct genera, have often
+bred in this country with either pure parent, and in one single instance
+they have bred inter se.  This was effected by Mr. Eyton, who raised two
+hybrids from the same parents but from different hatches; and from these
+two birds he raised no less than eight hybrids (grandchildren of the pure
+geese) from one nest.  In India, however, these cross-bred geese must be
+far more fertile; for I am assured by two eminently capable judges, namely
+Mr. Blyth and Capt. Hutton, that whole flocks of these crossed geese are
+kept in various parts of the country; and as they are kept for profit,
+where neither pure parent-species exists, they must certainly be highly
+fertile.
+</para>
+
+<para>
+A doctrine which originated with Pallas, has been largely accepted by
+modern naturalists; namely, that most of our domestic animals have
+descended from two or more aboriginal species, since commingled by
+intercrossing.  On this view, the aboriginal species must either at first
+have produced quite fertile hybrids, or the hybrids must have become in
+subsequent generations quite fertile under domestication.  This latter
+alternative seems to me the most probable, and I am inclined to believe in
+its truth, although it rests on no direct evidence.  I believe, for
+instance, that our dogs have descended from several wild stocks; yet, with
+perhaps the exception of certain indigenous domestic dogs of South America,
+all are quite fertile together; and analogy makes me greatly doubt, whether
+the several aboriginal species would at first have freely bred together and
+have produced quite fertile hybrids.  So again there is reason to believe
+that our European and the humped Indian cattle are quite fertile together;
+but from facts communicated to me by Mr. Blyth, I think they must be
+considered as distinct species.  On this view of the origin of many of our
+domestic animals, we must either give up the belief of the almost universal
+sterility of distinct species of animals when crossed; or we must look at
+sterility, not as an indelible characteristic, but as one capable of being
+removed by domestication.
+</para>
+
+<para>
+Finally, looking to all the ascertained facts on the intercrossing of
+plants and animals, it may be concluded that some degree of sterility, both
+in first crosses and in hybrids, is an extremely general result; but that
+it cannot, under our present state of knowledge, be considered as
+absolutely universal.
+</para>
+
+<para>
+Laws governing the Sterility of first Crosses and of Hybrids. -- We will
+now consider a little more in detail the circumstances and rules governing
+the sterility of first crosses and of hybrids.  Our chief object will be to
+see whether or not the rules indicate that species have specially been
+endowed with this quality, in order to prevent their crossing and blending
+together in utter confusion.  The following rules and conclusions are
+chiefly drawn up from Gartner's admirable work on the hybridisation of
+plants.  I have taken much pains to ascertain how far the rules apply to
+animals, and considering how scanty our knowledge is in regard to hybrid
+animals, I have been surprised to find how generally the same rules apply
+to both kingdoms.
+</para>
+
+<para>
+It has been already remarked, that the degree of fertility, both of first
+crosses and of hybrids, graduates from zero to perfect fertility.  It is
+surprising in how many curious ways this gradation can be shown to exist;
+but only the barest outline of the facts can here be given.  When pollen
+from a plant of one family is placed on the stigma of a plant of a distinct
+family, it exerts no more influence than so much inorganic dust.  From this
+absolute zero of fertility, the pollen of different species of the same
+genus applied to the stigma of some one species, yields a perfect gradation
+in the number of seeds produced, up to nearly complete or even quite
+complete fertility; and, as we have seen, in certain abnormal cases, even
+to an excess of fertility, beyond that which the plant's own pollen will
+produce.  So in hybrids themselves, there are some which never have
+produced, and probably never would produce, even with the pollen of either
+pure parent, a single fertile seed:  but in some of these cases a first
+trace of fertility may be detected, by the pollen of one of the pure
+parent-species causing the flower of the hybrid to wither earlier than it
+otherwise would have done; and the early withering of the flower is well
+known to be a sign of incipient fertilisation.  From this extreme degree of
+sterility we have self-fertilised hybrids producing a greater and greater
+number of seeds up to perfect fertility.
+</para>
+
+<para>
+Hybrids from two species which are very difficult to cross, and which
+rarely produce any offspring, are generally very sterile; but the
+parallelism between the difficulty of making a first cross, and the
+sterility of the hybrids thus produced--two classes of facts which are
+generally confounded together--is by no means strict.  There are many
+cases, in which two pure species can be united with unusual facility, and
+produce numerous hybrid-offspring, yet these hybrids are remarkably
+sterile.  On the other hand, there are species which can be crossed very
+rarely, or with extreme difficulty, but the hybrids, when at last produced,
+are very fertile.  Even within the limits of the same genus, for instance
+in Dianthus, these two opposite cases occur.
+</para>
+
+<para>
+The fertility, both of first crosses and of hybrids, is more easily
+affected by unfavourable conditions, than is the fertility of pure species. 
+But the degree of fertility is likewise innately variable; for it is not
+always the same when the same two species are crossed under the same
+circumstances, but depends in part upon the constitution of the individuals
+which happen to have been chosen for the experiment.  So it is with
+hybrids, for their degree of fertility is often found to differ greatly in
+the several individuals raised from seed out of the same capsule and
+exposed to exactly the same conditions.
+</para>
+
+<para>
+By the term systematic affinity is meant, the resemblance between species
+in structure and in constitution, more especially in the structure of parts
+which are of high physiological importance and which differ little in the
+allied species.  Now the fertility of first crosses between species, and of
+the hybrids produced from them, is largely governed by their systematic
+affinity.  This is clearly shown by hybrids never having been raised
+between species ranked by systematists in distinct families; and on the
+other hand, by very closely allied species generally uniting with facility. 
+But the correspondence between systematic affinity and the facility of
+crossing is by no means strict.  A multitude of cases could be given of
+very closely allied species which will not unite, or only with extreme
+difficulty; and on the other hand of very distinct species which unite with
+the utmost facility.  In the same family there may be a genus, as Dianthus,
+in which very many species can most readily be crossed; and another genus,
+as Silene, in which the most persevering efforts have failed to produce
+between extremely close species a single hybrid.  Even within the limits of
+the same genus, we meet with this same difference; for instance, the many
+species of Nicotiana have been more largely crossed than the species of
+almost any other genus; but Gartner found that N. acuminata, which is not a
+particularly distinct species, obstinately failed to fertilise, or to be
+fertilised by, no less than eight other species of Nicotiana.  Very many
+analogous facts could be given.
+</para>
+
+<para>
+No one has been able to point out what kind, or what amount, of difference
+in any recognisable character is sufficient to prevent two species
+crossing.  It can be shown that plants most widely different in habit and
+general appearance, and having strongly marked differences in every part of
+the flower, even in the pollen, in the fruit, and in the cotyledons, can be
+crossed.  Annual and perennial plants, deciduous and evergreen trees,
+plants inhabiting different stations and fitted for extremely different
+climates, can often be crossed with ease.
+</para>
+
+<para>
+By a reciprocal cross between two species, I mean the case, for instance,
+of a stallion-horse being first crossed with a female-ass, and then a
+male-ass with a mare:  these two species may then be said to have been
+reciprocally crossed.  There is often the widest possible difference in the
+facility of making reciprocal crosses.  Such cases are highly important,
+for they prove that the capacity in any two species to cross is often
+completely independent of their systematic affinity, or of any recognisable
+difference in their whole organisation.  On the other hand, these cases
+clearly show that the capacity for crossing is connected with
+constitutional differences imperceptible by us, and confined to the
+reproductive system.  This difference in the result of reciprocal crosses
+between the same two species was long ago observed by Kolreuter.  To give
+an instance:  Mirabilis jalappa can easily be fertilised by the pollen of
+M. longiflora, and the hybrids thus produced are sufficiently fertile; but
+Kolreuter tried more than two hundred times, during eight following years,
+to fertilise reciprocally M. longiflora with the pollen of M. jalappa, and
+utterly failed.  Several other equally striking cases could be given. 
+Thuret has observed the same fact with certain sea-weeds or Fuci.  Gartner,
+moreover, found that this difference of facility in making reciprocal
+crosses is extremely common in a lesser degree.  He has observed it even
+between forms so closely related (as Matthiola annua and glabra) that many
+botanists rank them only as varieties.  It is also a remarkable fact, that
+hybrids raised from reciprocal crosses, though of course compounded of the
+very same two species, the one species having first been used as the father
+and then as the mother, generally differ in fertility in a small, and
+occasionally in a high degree.
+</para>
+
+<para>
+Several other singular rules could be given from Gartner:  for instance,
+some species have a remarkable power of crossing with other species; other
+species of the same genus have a remarkable power of impressing their
+likeness on their hybrid offspring; but these two powers do not at all
+necessarily go together.  There are certain hybrids which instead of
+having, as is usual, an intermediate character between their two parents,
+always closely resemble one of them; and such hybrids, though externally so
+like one of their pure parent-species, are with rare exceptions extremely
+sterile.  So again amongst hybrids which are usually intermediate in
+structure between their parents, exceptional and abnormal individuals
+sometimes are born, which closely resemble one of their pure parents; and
+these hybrids are almost always utterly sterile, even when the other
+hybrids raised from seed from the same capsule have a considerable degree
+of fertility.  These facts show how completely fertility in the hybrid is
+independent of its external resemblance to either pure parent.
+</para>
+
+<para>
+Considering the several rules now given, which govern the fertility of
+first crosses and of hybrids, we see that when forms, which must be
+considered as good and distinct species, are united, their fertility
+graduates from zero to perfect fertility, or even to fertility under
+certain conditions in excess.  That their fertility, besides being
+eminently susceptible to favourable and unfavourable conditions, is
+innately variable.  That it is by no means always the same in degree in the
+first cross and in the hybrids produced from this cross.  That the
+fertility of hybrids is not related to the degree in which they resemble in
+external appearance either parent.  And lastly, that the facility of making
+a first cross between any two species is not always governed by their
+systematic affinity or degree of resemblance to each other.  This latter
+statement is clearly proved by reciprocal crosses between the same two
+species, for according as the one species or the other is used as the
+father or the mother, there is generally some difference, and occasionally
+the widest possible difference, in the facility of effecting an union.  The
+hybrids, moreover, produced from reciprocal crosses often differ in
+fertility.
+</para>
+
+<para>
+Now do these complex and singular rules indicate that species have been
+endowed with sterility simply to prevent their becoming confounded in
+nature?  I think not.  For why should the sterility be so extremely
+different in degree, when various species are crossed, all of which we must
+suppose it would be equally important to keep from blending together?  Why
+should the degree of sterility be innately variable in the individuals of
+the same species?  Why should some species cross with facility, and yet
+produce very sterile hybrids; and other species cross with extreme
+difficulty, and yet produce fairly fertile hybrids?  Why should there often
+be so great a difference in the result of a reciprocal cross between the
+same two species?  Why, it may even be asked, has the production of hybrids
+been permitted? to grant to species the special power of producing hybrids,
+and then to stop their further propagation by different degrees of
+sterility, not strictly related to the facility of the first union between
+their parents, seems to be a strange arrangement.
+</para>
+
+<para>
+The foregoing rules and facts, on the other hand, appear to me clearly to
+indicate that the sterility both of first crosses and of hybrids is simply
+incidental or dependent on unknown differences, chiefly in the reproductive
+systems, of the species which are crossed.  The differences being of so
+peculiar and limited a nature, that, in reciprocal crosses between two
+species the male sexual element of the one will often freely act on the
+female sexual element of the other, but not in a reversed direction.  It
+will be advisable to explain a little more fully by an example what I mean
+by sterility being incidental on other differences, and not a specially
+endowed quality.  As the capacity of one plant to be grafted or budded on
+another is so entirely unimportant for its welfare in a state of nature, I
+presume that no one will suppose that this capacity is a specially endowed
+quality, but will admit that it is incidental on differences in the laws of
+growth of the two plants.  We can sometimes see the reason why one tree
+will not take on another, from differences in their rate of growth, in the
+hardness of their wood, in the period of the flow or nature of their sap,
+&amp;c.; but in a multitude of cases we can assign no reason whatever.  Great
+diversity in the size of two plants, one being woody and the other
+herbaceous, one being evergreen and the other deciduous, and adaptation to
+widely different climates, does not always prevent the two grafting
+together.  As in hybridisation, so with grafting, the capacity is limited
+by systematic affinity, for no one has been able to graft trees together
+belonging to quite distinct families; and, on the other hand, closely
+allied species, and varieties of the same species, can usually, but not
+invariably, be grafted with ease.  But this capacity, as in hybridisation,
+is by no means absolutely governed by systematic affinity.  Although many
+distinct genera within the same family have been grafted together, in other
+cases species of the same genus will not take on each other.  The pear can
+be grafted far more readily on the quince, which is ranked as a distinct
+genus, than on the apple, which is a member of the same genus.  Even
+different varieties of the pear take with different degrees of facility on
+the quince; so do different varieties of the apricot and peach on certain
+varieties of the plum.
+</para>
+
+<para>
+As Gartner found that there was sometimes an innate difference in different
+individuals of the same two species in crossing; so Sagaret believes this
+to be the case with different individuals of the same two species in being
+grafted together.  As in reciprocal crosses, the facility of effecting an
+union is often very far from equal, so it sometimes is in grafting; the
+common gooseberry, for instance, cannot be grafted on the currant, whereas
+the currant will take, though with difficulty, on the gooseberry.
+</para>
+
+<para>
+We have seen that the sterility of hybrids, which have their reproductive
+organs in an imperfect condition, is a very different case from the
+difficulty of uniting two pure species, which have their reproductive
+organs perfect; yet these two distinct cases run to a certain extent
+parallel.  Something analogous occurs in grafting; for Thouin found that
+three species of Robinia, which seeded freely on their own roots, and which
+could be grafted with no great difficulty on another species, when thus
+grafted were rendered barren.  On the other hand, certain species of
+Sorbus, when grafted on other species, yielded twice as much fruit as when
+on their own roots.  We are reminded by this latter fact of the
+extraordinary case of Hippeastrum, Lobelia, &amp;c., which seeded much more
+freely when fertilised with the pollen of distinct species, than when
+self-fertilised with their own pollen.
+</para>
+
+<para>
+We thus see, that although there is a clear and fundamental difference
+between the mere adhesion of grafted stocks, and the union of the male and
+female elements in the act of reproduction, yet that there is a rude degree
+of parallelism in the results of grafting and of crossing distinct species. 
+And as we must look at the curious and complex laws governing the facility
+with which trees can be grafted on each other as incidental on unknown
+differences in their vegetative systems, so I believe that the still more
+complex laws governing the facility of first crosses, are incidental on
+unknown differences, chiefly in their reproductive systems.  These
+differences, in both cases, follow to a certain extent, as might have been
+expected, systematic affinity, by which every kind of resemblance and
+dissimilarity between organic beings is attempted to be expressed.  The
+facts by no means seem to me to indicate that the greater or lesser
+difficulty of either grafting or crossing together various species has been
+a special endowment; although in the case of crossing, the difficulty is as
+important for the endurance and stability of specific forms, as in the case
+of grafting it is unimportant for their welfare.
+</para>
+
+<para>
+Causes of the Sterility of first Crosses and of Hybrids. -- We may now look
+a little closer at the probable causes of the sterility of first crosses
+and of hybrids.  These two cases are fundamentally different, for, as just
+remarked, in the union of two pure species the male and female sexual
+elements are perfect, whereas in hybrids they are imperfect.  Even in first
+crosses, the greater or lesser difficulty in effecting a union apparently
+depends on several distinct causes.  There must sometimes be a physical
+impossibility in the male element reaching the ovule, as would be the case
+with a plant having a pistil too long for the pollen-tubes to reach the
+ovarium.  It has also been observed that when pollen of one species is
+placed on the stigma of a distantly allied species, though the pollen-tubes
+protrude, they do not penetrate the stigmatic surface.  Again, the male
+element may reach the female element, but be incapable of causing an embryo
+to be developed, as seems to have been the case with some of Thuret's
+experiments on Fuci.  No explanation can be given of these facts, any more
+than why certain trees cannot be grafted on others.  Lastly, an embryo may
+be developed, and then perish at an early period.  This latter alternative
+has not been sufficiently attended to; but I believe, from observations
+communicated to me by Mr. Hewitt, who has had great experience in
+hybridising gallinaceous birds, that the early death of the embryo is a
+very frequent cause of sterility in first crosses.  I was at first very
+unwilling to believe in this view; as hybrids, when once born, are
+generally healthy and long-lived, as we see in the case of the common mule. 
+Hybrids, however, are differently circumstanced before and after birth: 
+when born and living in a country where their two parents can live, they
+are generally placed under suitable conditions of life.  But a hybrid
+partakes of only half of the nature and constitution of its mother, and
+therefore before birth, as long as it is nourished within its mother's womb
+or within the egg or seed produced by the mother, it may be exposed to
+conditions in some degree unsuitable, and consequently be liable to perish
+at an early period; more especially as all very young beings seem eminently
+sensitive to injurious or unnatural conditions of life.
+</para>
+
+<para>
+In regard to the sterility of hybrids, in which the sexual elements are
+imperfectly developed, the case is very different.  I have more than once
+alluded to a large body of facts, which I have collected, showing that when
+animals and plants are removed from their natural conditions, they are
+extremely liable to have their reproductive systems seriously affected. 
+This, in fact, is the great bar to the domestication of animals.  Between
+the sterility thus superinduced and that of hybrids, there are many points
+of similarity.  In both cases the sterility is independent of general
+health, and is often accompanied by excess of size or great luxuriance.  In
+both cases, the sterility occurs in various degrees; in both, the male
+element is the most liable to be affected; but sometimes the female more
+than the male.  In both, the tendency goes to a certain extent with
+systematic affinity, or whole groups of animals and plants are rendered
+impotent by the same unnatural conditions; and whole groups of species tend
+to produce sterile hybrids.  On the other hand, one species in a group will
+sometimes resist great changes of conditions with unimpaired fertility; and
+certain species in a group will produce unusually fertile hybrids.  No one
+can tell, till he tries, whether any particular animal will breed under
+confinement or any plant seed freely under culture; nor can he tell, till
+he tries, whether any two species of a genus will produce more or less
+sterile hybrids.  Lastly, when organic beings are placed during several
+generations under conditions not natural to them, they are extremely liable
+to vary, which is due, as I believe, to their reproductive systems having
+been specially affected, though in a lesser degree than when sterility
+ensues.  So it is with hybrids, for hybrids in successive generations are
+eminently liable to vary, as every experimentalist has observed.
+</para>
+
+<para>
+Thus we see that when organic beings are placed under new and unnatural
+conditions, and when hybrids are produced by the unnatural crossing of two
+species, the reproductive system, independently of the general state of
+health, is affected by sterility in a very similar manner.  In the one
+case, the conditions of life have been disturbed, though often in so slight
+a degree as to be inappreciable by us; in the other case, or that of
+hybrids,the external conditions have remained the same, but the
+organisation has been disturbed by two different structures and
+constitutions having been blended into one.  For it is scarcely possible
+that two organisations should be compounded into one, without some
+disturbance occurring in the development, or periodical action, or mutual
+relation of the different parts and organs one to another, or to the
+conditions of life.  When hybrids are able to breed inter se, they transmit
+to their offspring from generation to generation the same compounded
+organisation, and hence we need not be surprised that their sterility,
+though in some degree variable, rarely diminishes.
+</para>
+
+<para>
+It must, however, be confessed that we cannot understand, excepting on
+vague hypotheses, several facts with respect to the sterility of hybrids;
+for instance, the unequal fertility of hybrids produced from reciprocal
+crosses; or the increased sterility in those hybrids which occasionally and
+exceptionally resemble closely either pure parent.  Nor do I pretend that
+the foregoing remarks go to the root of the matter:  no explanation is
+offered why an organism, when placed under unnatural conditions, is
+rendered sterile.  All that I have attempted to show, is that in two cases,
+in some respects allied, sterility is the common result,--in the one case
+from the conditions of life having been disturbed, in the other case from
+the organisation having been disturbed by two organisations having been
+compounded into one.
+</para>
+
+<para>
+It may seem fanciful, but I suspect that a similar parallelism extends to
+an allied yet very different class of facts.  It is an old and almost
+universal belief, founded, I think, on a considerable body of evidence,
+that slight changes in the conditions of life are beneficial to all living
+things.  We see this acted on by farmers and gardeners in their frequent
+exchanges of seed, tubers, &amp;c., from one soil or climate to another, and
+back again.  During the convalescence of animals, we plainly see that great
+benefit is derived from almost any change in the habits of life.  Again,
+both with plants and animals, there is abundant evidence, that a cross
+between very distinct individuals of the same species, that is between
+members of different strains or sub-breeds, gives vigour and fertility to
+the offspring.  I believe, indeed, from the facts alluded to in our fourth
+chapter, that a certain amount of crossing is indispensable even with
+hermaphrodites; and that close interbreeding continued during several
+generations between the nearest relations, especially if these be kept
+under the same conditions of life, always induces weakness and sterility in
+the progeny.
+</para>
+
+<para>
+Hence it seems that, on the one hand, slight changes in the conditions of
+life benefit all organic beings, and on the other hand, that slight
+crosses, that is crosses between the males and females of the same species
+which have varied and become slightly different, give vigour and fertility
+to the offspring.  But we have seen that greater changes, or changes of a
+particular nature, often render organic beings in some degree sterile; and
+that greater crosses, that is crosses between males and females which have
+become widely or specifically different, produce hybrids which are
+generally sterile in some degree.  I cannot persuade myself that this
+parallelism is an accident or an illusion.  Both series of facts seem to be
+connected together by some common but unknown bond, which is essentially
+related to the principle of life.
+</para>
+
+<para>
+Fertility of Varieties when crossed, and of their Mongrel off-spring. -- It
+may be urged, as a most forcible argument, that there must be some
+essential distinction between species and varieties, and that there must be
+some error in all the foregoing remarks, inasmuch as varieties, however
+much they may differ from each other in external appearance, cross with
+perfect facility, and yield perfectly fertile offspring.  I fully admit
+that this is almost invariably the case.  But if we look to varieties
+produced under nature, we are immediately involved in hopeless
+difficulties; for if two hitherto reputed varieties be found in any degree
+sterile together, they are at once ranked by most naturalists as species. 
+For instance, the blue and red pimpernel, the primrose and cowslip, which
+are considered by many of our best botanists as varieties, are said by
+Gartner not to be quite fertile when crossed, and he consequently ranks
+them as undoubted species.  If we thus argue in a circle, the fertility of
+all varieties produced under nature will assuredly have to be granted.
+</para>
+
+<para>
+If we turn to varieties, produced, or supposed to have been produced, under
+domestication, we are still involved in doubt.  For when it is stated, for
+instance, that the German Spitz dog unites more easily than other dogs with
+foxes, or that certain South American indigenous domestic dogs do not
+readily cross with European dogs, the explanation which will occur to
+everyone, and probably the true one, is that these dogs have descended from
+several aboriginally distinct species.  Nevertheless the perfect fertility
+of so many domestic varieties, differing widely from each other in
+appearance, for instance of the pigeon or of the cabbage, is a remarkable
+fact; more especially when we reflect how many species there are, which,
+though resembling each other most closely, are utterly sterile when
+intercrossed.  Several considerations, however, render the fertility of
+domestic varieties less remarkable than at first appears.  It can, in the
+first place, be clearly shown that mere external dissimilarity between two
+species does not determine their greater or lesser degree of sterility when
+crossed; and we may apply the same rule to domestic varieties.  In the
+second place, some eminent naturalists believe that a long course of
+domestication tends to eliminate sterility in the successive generations of
+hybrids, which were at first only slightly sterile; and if this be so, we
+surely ought not to expect to find sterility both appearing and
+disappearing under nearly the same conditions of life.  Lastly, and this
+seems to me by far the most important consideration, new races of animals
+and plants are produced under domestication by man's methodical and
+unconscious power of selection, for his own use and pleasure:  he neither
+wishes to select, nor could select, slight differences in the reproductive
+system, or other constitutional differences correlated with the
+reproductive system.  He supplies his several varieties with the same food;
+treats them in nearly the same manner, and does not wish to alter their
+general habits of life.  Nature acts uniformly and slowly during vast
+periods of time on the whole organisation, in any way which may be for each
+creature's own good; and thus she may, either directly, or more probably
+indirectly, through correlation, modify the reproductive system in the
+several descendants from any one species.  Seeing this difference in the
+process of selection, as carried on by man and nature, we need not be
+surprised at some difference in the result.
+</para>
+
+<para>
+I have as yet spoken as if the varieties of the same species were
+invariably fertile when intercrossed.  But it seems to me impossible to
+resist the evidence of the existence of a certain amount of sterility in
+the few following cases, which I will briefly abstract.  The evidence is at
+least as good as that from which we believe in the sterility of a multitude
+of species.  The evidence is, also, derived from hostile witnesses, who in
+all other cases consider fertility and sterility as safe criterions of
+specific distinction.  Gartner kept during several years a dwarf kind of
+maize with yellow seeds, and a tall variety with red seeds, growing near
+each other in his garden; and although these plants have separated sexes,
+they never naturally crossed.  He then fertilised thirteen flowers of the
+one with the pollen of the other; but only a single head produced any seed,
+and this one head produced only five grains.  Manipulation in this case
+could not have been injurious, as the plants have separated sexes.  No one,
+I believe, has suspected that these varieties of maize are distinct
+species; and it is important to notice that the hybrid plants thus raised
+were themselves perfectly fertile; so that even Gartner did not venture to
+consider the two varieties as specifically distinct.
+</para>
+
+<para>
+Girou de Buzareingues crossed three varieties of gourd, which like the
+maize has separated sexes, and he asserts that their mutual fertilisation
+is by so much the less easy as their differences are greater.  How far
+these experiments may be trusted, I know not; but the forms experimentised
+on, are ranked by Sagaret, who mainly founds his classification by the test
+of infertility, as varieties.
+</para>
+
+<para>
+The following case is far more remarkable, and seems at first quite
+incredible; but it is the result of an astonishing number of experiments
+made during many years on nine species of Verbascum, by so good an observer
+and so hostile a witness, as Gartner:  namely, that yellow and white
+varieties of the same species of Verbascum when intercrossed produce less
+seed, than do either coloured varieties when fertilised with pollen from
+their own coloured flowers.  Moreover, he asserts that when yellow and
+white varieties of one species are crossed with yellow and white varieties
+of a distinct species, more seed is produced by the crosses between the
+same coloured flowers, than between those which are differently coloured. 
+Yet these varieties of Verbascum present no other difference besides the
+mere colour of the flower; and one variety can sometimes be raised from the
+seed of the other.
+</para>
+
+<para>
+From observations which I have made on certain varieties of hollyhock, I am
+inclined to suspect that they present analogous facts.
+</para>
+
+<para>
+Kolreuter, whose accuracy has been confirmed by every subsequent observer,
+has proved the remarkable fact, that one variety of the common tobacco is
+more fertile, when crossed with a widely distinct species, than are the
+other varieties.  He experimentised on five forms, which are commonly
+reputed to be varieties, and which he tested by the severest trial, namely,
+by reciprocal crosses, and he found their mongrel offspring perfectly
+fertile.  But one of these five varieties, when used either as father or
+mother, and crossed with the Nicotiana glutinosa, always yielded hybrids
+not so sterile as those which were produced from the four other varieties
+when crossed with N. glutinosa.  Hence the reproductive system of this one
+variety must have been in some manner and in some degree modified.
+</para>
+
+<para>
+From these facts; from the great difficulty of ascertaining the infertility
+of varieties in a state of nature, for a supposed variety if infertile in
+any degree would generally be ranked as species; from man selecting only
+external characters in the production of the most distinct domestic
+varieties, and from not wishing or being able to produce recondite and
+functional differences in the reproductive system; from these several
+considerations and facts, I do not think that the very general fertility of
+varieties can be proved to be of universal occurrence, or to form a
+fundamental distinction between varieties and species.  The general
+fertility of varieties does not seem to me sufficient to overthrow the view
+which I have taken with respect to the very general, but not invariable,
+sterility of first crosses and of hybrids, namely, that it is not a special
+endowment, but is incidental on slowly acquired modifications, more
+especially in the reproductive systems of the forms which are crossed.
+</para>
+
+<para>
+Hybrids and Mongrels compared, independently of their fertility. --
+Independently of the question of fertility, the offspring of species when
+crossed and of varieties when crossed may be compared in several other
+respects.  Gartner, whose strong wish was to draw a marked line of
+distinction between species and varieties, could find very few and, as it
+seems to me, quite unimportant differences between the so-called hybrid
+offspring of species, and the so-called mongrel offspring of varieties. 
+And, on the other hand, they agree most closely in very many important
+respects.
+</para>
+
+<para>
+I shall here discuss this subject with extreme brevity.  The most important
+distinction is, that in the first generation mongrels are more variable
+than hybrids; but Gartner admits that hybrids from species which have long
+been cultivated are often variable in the first generation; and I have
+myself seen striking instances of this fact.  Gartner further admits that
+hybrids between very closely allied species are more variable than those
+from very distinct species; and this shows that the difference in the
+degree of variability graduates away.  When mongrels and the more fertile
+hybrids are propagated for several generations an extreme amount of
+variability in their offspring is notorious; but some few cases both of
+hybrids and mongrels long retaining uniformity of character could be given. 
+The variability, however, in the successive generations of mongrels is,
+perhaps, greater than in hybrids.
+</para>
+
+<para>
+This greater variability of mongrels than of hybrids does not seem to me at
+all surprising.  For the parents of mongrels are varieties, and mostly
+domestic varieties (very few experiments having been tried on natural
+varieties), and this implies in most cases that there has been recent
+variability; and therefore we might expect that such variability would
+often continue and be super-added to that arising from the mere act of
+crossing.  The slight degree of variability in hybrids from the first cross
+or in the first generation, in contrast with their extreme variability in
+the succeeding generations, is a curious fact and deserves attention.  For
+it bears on and corroborates the view which I have taken on the cause of
+ordinary variability; namely, that it is due to the reproductive system
+being eminently sensitive to any change in the conditions of life, being
+thus often rendered either impotent or at least incapable of its proper
+function of producing offspring identical with the parent-form.  Now
+hybrids in the first generation are descended from species (excluding those
+long cultivated) which have not had their reproductive systems in any way
+affected, and they are not variable; but hybrids themselves have their
+reproductive systems seriously affected, and their descendants are highly
+variable.
+</para>
+
+<para>
+But to return to our comparison of mongrels and hybrids:  Gartner states
+that mongrels are more liable than hybrids to revert to either parent-form;
+but this, if it be true, is certainly only a difference in degree.  Gartner
+further insists that when any two species, although most closely allied to
+each other, are crossed with a third species, the hybrids are widely
+different from each other; whereas if two very distinct varieties of one
+species are crossed with another species, the hybrids do not differ much. 
+But this conclusion, as far as I can make out, is founded on a single
+experiment; and seems directly opposed to the results of several
+experiments made by Kolreuter.
+</para>
+
+<para>
+These alone are the unimportant differences, which Gartner is able to point
+out, between hybrid and mongrel plants.  On the other hand, the resemblance
+in mongrels and in hybrids to their respective parents, more especially in
+hybrids produced from nearly related species, follows according to Gartner
+the same laws.  When two species are crossed, one has sometimes a prepotent
+power of impressing its likeness on the hybrid; and so I believe it to be
+with varieties of plants.  With animals one variety certainly often has
+this prepotent power over another variety.  Hybrid plants produced from a
+reciprocal cross, generally resemble each other closely; and so it is with
+mongrels from a reciprocal cross.  Both hybrids and mongrels can be reduced
+to either pure parent-form, by repeated crosses in successive generations
+with either parent.
+</para>
+
+<para>
+These several remarks are apparently applicable to animals; but the subject
+is here excessively complicated, partly owing to the existence of secondary
+sexual characters; but more especially owing to prepotency in transmitting
+likeness running more strongly in one sex than in the other, both when one
+species is crossed with another, and when one variety is crossed with
+another variety.  For instance, I think those authors are right, who
+maintain that the ass has a prepotent power over the horse, so that both
+the mule and the hinny more resemble the ass than the horse; but that the
+prepotency runs more strongly in the male-ass than in the female, so that
+the mule, which is the offspring of the male-ass and mare, is more like an
+ass, than is the hinny, which is the offspring of the female-ass and
+stallion.
+</para>
+
+<para>
+Much stress has been laid by some authors on the supposed fact, that
+mongrel animals alone are born closely like one of their parents; but it
+can be shown that this does sometimes occur with hybrids; yet I grant much
+less frequently with hybrids than with mongrels.  Looking to the cases
+which I have collected of cross-bred animals closely resembling one parent,
+the resemblances seem chiefly confined to characters almost monstrous in
+their nature, and which have suddenly appeared--such as albinism, melanism,
+deficiency of tail or horns, or additional fingers and toes; and do not
+relate to characters which have been slowly acquired by selection. 
+Consequently, sudden reversions to the perfect character of either parent
+would be more likely to occur with mongrels, which are descended from
+varieties often suddenly produced and semi-monstrous in character, than
+with hybrids, which are descended from species slowly and naturally
+produced.  On the whole I entirely agree with Dr. Prosper Lucas, who, after
+arranging an enormous body of facts with respect to animals, comes to the
+conclusion, that the laws of resemblance of the child to its parents are
+the same, whether the two parents differ much or little from each other,
+namely in the union of individuals of the same variety, or of different
+varieties, or of distinct species.
+</para>
+
+<para>
+Laying aside the question of fertility and sterility, in all other respects
+there seems to be a general and close similarity in the offspring of
+crossed species, and of crossed varieties.  If we look at species as having
+been specially created, and at varieties as having been produced by
+secondary laws, this similarity would be an astonishing fact.  But it
+harmonises perfectly with the view that there is no essential distinction
+between species and varieties.
+</para>
+
+<para>
+Summary of Chapter -- First crosses between forms sufficiently distinct to
+be ranked as species, and their hybrids, are very generally, but not
+universally, sterile.  The sterility is of all degrees, and is often so
+slight that the two most careful experimentalists who have ever lived, have
+come to diametrically opposite conclusions in ranking forms by this test. 
+The sterility is innately variable in individuals of the same species, and
+is eminently susceptible of favourable and unfavourable conditions.  The
+degree of sterility does not strictly follow systematic affinity, but is
+governed by several curious and complex laws.  It is generally different,
+and sometimes widely different, in reciprocal crosses between the same two
+species.  It is not always equal in degree in a first cross and in the
+hybrid produced from this cross.
+</para>
+
+<para>
+In the same manner as in grafting trees, the capacity of one species or
+variety to take on another, is incidental on generally unknown differences
+in their vegetative systems, so in crossing, the greater or less facility
+of one species to unite with another, is incidental on unknown differences
+in their reproductive systems.  There is no more reason to think that
+species have been specially endowed with various degrees of sterility to
+prevent them crossing and blending in nature, than to think that trees have
+been specially endowed with various and somewhat analogous degrees of
+difficulty in being grafted together in order to prevent them becoming
+inarched in our forests.
+</para>
+
+<para>
+The sterility of first crosses between pure species, which have their
+reproductive systems perfect, seems to depend on several circumstances; in
+some cases largely on the early death of the embryo.  The sterility of
+hybrids, which have their reproductive systems imperfect, and which have
+had this system and their whole organisation disturbed by being compounded
+of two distinct species, seems closely allied to that sterility which so
+frequently affects pure species, when their natural conditions of life have
+been disturbed.  This view is supported by a parallelism of another
+kind;--namely, that the crossing of forms only slightly different is
+favourable to the vigour and fertility of their offspring; and that slight
+changes in the conditions of life are apparently favourable to the vigour
+and fertility of all organic beings.  It is not surprising that the degree
+of difficulty in uniting two species, and the degree of sterility of their
+hybrid-offspring should generally correspond, though due to distinct
+causes; for both depend on the amount of difference of some kind between
+the species which are crossed.  Nor is it surprising that the facility of
+effecting a first cross, the fertility of the hybrids produced, and the
+capacity of being grafted together--though this latter capacity evidently
+depends on widely different circumstances--should all run, to a certain
+extent, parallel with the systematic affinity of the forms which are
+subjected to experiment; for systematic affinity attempts to express all
+kinds of resemblance between all species.
+</para>
+
+<para>
+First crosses between forms known to be varieties, or sufficiently alike to
+be considered as varieties, and their mongrel offspring, are very
+generally, but not quite universally, fertile.  Nor is this nearly general
+and perfect fertility surprising, when we remember how liable we are to
+argue in a circle with respect to varieties in a state of nature; and when
+we remember that the greater number of varieties have been produced under
+domestication by the selection of mere external differences, and not of
+differences in the reproductive system.  In all other respects, excluding
+fertility, there is a close general resemblance between hybrids and
+mongrels.  Finally, then, the facts briefly given in this chapter do not
+seem to me opposed to, but even rather to support the view, that there is
+no fundamental distinction between species and varieties.
+</para>
+
+</chapter>
+
+<chapter>
+<chapheader>
+
+<chapnum>Chapter IX</chapnum>
+
+<title>On the Imperfection of the Geological Record</title>
+
+<chapsummary>
+On the absence of intermediate varieties at the present day -- On the
+nature of extinct intermediate varieties; on their number -- On the vast
+lapse of time, as inferred from the rate of deposition and of denudation --
+On the poorness of our palaeontological collections -- On the intermittence
+of geological formations -- On the absence of intermediate varieties in any
+one formation -- On the sudden appearance of groups of species -- On their
+sudden appearance in the lowest known fossiliferous strata.
+</chapsummary>
+</chapheader>
+
+<para>
+In the sixth chapter I enumerated the chief objections which might be
+justly urged against the views maintained in this volume.  Most of them
+have now been discussed.  One, namely the distinctness of specific forms,
+and their not being blended together by innumerable transitional links, is
+a very obvious difficulty.  I assigned reasons why such links do not
+commonly occur at the present day, under the circumstances apparently most
+favourable for their presence, namely on an extensive and continuous area
+with graduated physical conditions.  I endeavoured to show, that the life
+of each species depends in a more important manner on the presence of other
+already defined organic forms, than on climate; and, therefore, that the
+really governing conditions of life do not graduate away quite insensibly
+like heat or moisture.  I endeavoured, also, to show that intermediate
+varieties, from existing in lesser numbers than the forms which they
+connect, will generally be beaten out and exterminated during the course of
+further modification and improvement.  The main cause, however, of
+innumerable intermediate links not now occurring everywhere throughout
+nature depends on the very process of natural selection, through which new
+varieties continually take the places of and exterminate their
+parent-forms.  But just in proportion as this process of extermination has
+acted on an enormous scale, so must the number of intermediate varieties,
+which have formerly existed on the earth, be truly enormous.  Why then is
+not every geological formation and every stratum full of such intermediate
+links?  Geology assuredly does not reveal any such finely graduated organic
+chain; and this, perhaps, is the most obvious and gravest objection which
+can be urged against my theory.  The explanation lies, as I believe, in the
+extreme imperfection of the geological record.
+</para>
+
+<para>
+In the first place it should always be borne in mind what sort of
+intermediate forms must, on my theory, have formerly existed.  I have found
+it difficult, when looking at any two species, to avoid picturing to
+myself, forms directly intermediate between them.  But this is a wholly
+false view; we should always look for forms intermediate between each
+species and a common but unknown progenitor; and the progenitor will
+generally have differed in some respects from all its modified descendants. 
+To give a simple illustration:  the fantail and pouter pigeons have both
+descended from the rock-pigeon; if we possessed all the intermediate
+varieties which have ever existed, we should have an extremely close series
+between both and the rock-pigeon; but we should have no varieties directly
+intermediate between the fantail and pouter; none, for instance, combining
+a tail somewhat expanded with a crop somewhat enlarged, the characteristic
+features of these two breeds.  These two breeds, moreover, have become so
+much modified, that if we had no historical or indirect evidence regarding
+their origin, it would not have been possible to have determined from a
+mere comparison of their structure with that of the rock-pigeon, whether
+they had descended from this species or from some other allied species,
+such as C. oenas.
+</para>
+
+<para>
+So with natural species, if we look to forms very distinct, for instance to
+the horse and tapir, we have no reason to suppose that links ever existed
+directly intermediate between them, but between each and an unknown common
+parent.  The common parent will have had in its whole organisation much
+general resemblance to the tapir and to the horse; but in some points of
+structure may have differed considerably from both, even perhaps more than
+they differ from each other.  Hence in all such cases, we should be unable
+to recognise the parent-form of any two or more species, even if we closely
+compared the structure of the parent with that of its modified descendants,
+unless at the same time we had a nearly perfect chain of the intermediate
+links.
+</para>
+
+<para>
+It is just possible by my theory, that one of two living forms might have
+descended from the other; for instance, a horse from a tapir; and in this
+case direct intermediate links will have existed between them.  But such a
+case would imply that one form had remained for a very long period
+unaltered, whilst its descendants had undergone a vast amount of change;
+and the principle of competition between organism and organism, between
+child and parent, will render this a very rare event; for in all cases the
+new and improved forms of life will tend to supplant the old and unimproved
+forms.
+</para>
+
+<para>
+By the theory of natural selection all living species have been connected
+with the parent-species of each genus, by differences not greater than we
+see between the varieties of the same species at the present day; and these
+parent-species, now generally extinct, have in their turn been similarly
+connected with more ancient species; and so on backwards, always converging
+to the common ancestor of each great class.  So that the number of
+intermediate and transitional links, between all living and extinct
+species, must have been inconceivably great.  But assuredly, if this theory
+be true, such have lived upon this earth.
+</para>
+
+<para>
+On the lapse of Time. -- Independently of our not finding fossil remains of
+such infinitely numerous connecting links, it may be objected, that time
+will not have sufficed for so great an amount of organic change, all
+changes having been effected very slowly through natural selection.  It is
+hardly possible for me even to recall to the reader, who may not be a
+practical geologist, the facts leading the mind feebly to comprehend the
+lapse of time.  He who can read Sir Charles Lyell's grand work on the
+Principles of Geology, which the future historian will recognise as having
+produced a revolution in natural science, yet does not admit how
+incomprehensibly vast have been the past periods of time, may at once close
+this volume.  Not that it suffices to study the Principles of Geology, or
+to read special treatises by different observers on separate formations,
+and to mark how each author attempts to give an inadequate idea of the
+duration of each formation or even each stratum.  A man must for years
+examine for himself great piles of superimposed strata, and watch the sea
+at work grinding down old rocks and making fresh sediment, before he can
+hope to comprehend anything of the lapse of time, the monuments of which we
+see around us.
+</para>
+
+<para>
+It is good to wander along lines of sea-coast, when formed of moderately
+hard rocks, and mark the process of degradation.  The tides in most cases
+reach the cliffs only for a short time twice a day, and the waves eat into
+them only when they are charged with sand or pebbles; for there is reason
+to believe that pure water can effect little or nothing in wearing away
+rock.  At last the base of the cliff is undermined, huge fragments fall
+down, and these remaining fixed, have to be worn away, atom by atom, until
+reduced in size they can be rolled about by the waves, and then are more
+quickly ground into pebbles, sand, or mud.  But how often do we see along
+the bases of retreating cliffs rounded boulders, all thickly clothed by
+marine productions, showing how little they are abraded and how seldom they
+are rolled about!  Moreover, if we follow for a few miles any line of rocky
+cliff, which is undergoing degradation, we find that it is only here and
+there, along a short length or round a promontory, that the cliffs are at
+the present time suffering.  The appearance of the surface and the
+vegetation show that elsewhere years have elapsed since the waters washed
+their base.
+</para>
+
+<para>
+He who most closely studies the action of the sea on our shores, will, I
+believe, be most deeply impressed with the slowness with which rocky coasts
+are worn away.  The observations on this head by Hugh Miller, and by that
+excellent observer Mr. Smith of Jordan Hill, are most impressive.  With the
+mind thus impressed, let any one examine beds of conglomerate many thousand
+feet in thickness, which, though probably formed at a quicker rate than
+many other deposits, yet, from being formed of worn and rounded pebbles,
+each of which bears the stamp of time, are good to show how slowly the mass
+has been accumulated.  Let him remember Lyell's profound remark, that the
+thickness and extent of sedimentary formations are the result and measure
+of the degradation which the earth's crust has elsewhere suffered.  And
+what an amount of degradation is implied by the sedimentary deposits of
+many countries!  Professor Ramsay has given me the maximum thickness, in
+most cases from actual measurement, in a few cases from estimate, of each
+formation in different parts of Great Britain; and this is the result:-
+</para>
+
+<list>
+                                                 <item>Feet</item>
+<item>Palaeozoic strata (not including igneous beds)..57,154</item>
+<item>Secondary strata................................13,190</item>
+<item>Tertiary strata..................................2,240</item>
+</list>
+
+<para>
+--making altogether 72,584 feet; that is, very nearly thirteen and
+three-quarters British miles.  Some of these formations, which are
+represented in England by thin beds, are thousands of feet in thickness on
+the Continent.  Moreover, between each successive formation, we have, in
+the opinion of most geologists, enormously long blank periods.  So that the
+lofty pile of sedimentary rocks in Britain, gives but an inadequate idea of
+the time which has elapsed during their accumulation; yet what time this
+must have consumed!  Good observers have estimated that sediment is
+deposited by the great Mississippi river at the rate of only 600 feet in a
+hundred thousand years.  This estimate may be quite erroneous; yet,
+considering over what wide spaces very fine sediment is transported by the
+currents of the sea, the process of accumulation in any one area must be
+extremely slow.
+</para>
+
+<para>
+But the amount of denudation which the strata have in many places suffered,
+independently of the rate of accumulation of the degraded matter, probably
+offers the best evidence of the lapse of time.  I remember having been much
+struck with the evidence of denudation, when viewing volcanic islands,
+which have been worn by the waves and pared all round into perpendicular
+cliffs of one or two thousand feet in height; for the gentle slope of the
+lava-streams, due to their formerly liquid state, showed at a glance how
+far the hard, rocky beds had once extended into the open ocean.  The same
+story is still more plainly told by faults,--those great cracks along which
+the strata have been upheaved on one side, or thrown down on the other, to
+the height or depth of thousands of feet; for since the crust cracked, the
+surface of the land has been so completely planed down by the action of the
+sea, that no trace of these vast dislocations is externally visible.
+</para>
+
+<para>
+The Craven fault, for instance, extends for upwards of 30 miles, and along
+this line the vertical displacement of the strata has varied from 600 to
+3000 feet.  Prof. Ramsay has published an account of a downthrow in
+Anglesea of 2300 feet; and he informs me that he fully believes there is
+one in Merionethshire of 12,000 feet; yet in these cases there is nothing
+on the surface to show such prodigious movements; the pile of rocks on the
+one or other side having been smoothly swept away.  The consideration of
+these facts impresses my mind almost in the same manner as does the vain
+endeavour to grapple with the idea of eternity.
+</para>
+
+<para>
+I am tempted to give one other case, the well-known one of the denudation
+of the Weald.  Though it must be admitted that the denudation of the Weald
+has been a mere trifle, in comparison with that which has removed masses of
+our palaeozoic strata, in parts ten thousand feet in thickness, as shown in
+Prof. Ramsay's masterly memoir on this subject.  Yet it is an admirable
+lesson to stand on the North Downs and to look at the distant South Downs;
+for, remembering that at no great distance to the west the northern and
+southern escarpments meet and close, one can safely picture to oneself the
+great dome of rocks which must have covered up the Weald within so limited
+a period as since the latter part of the Chalk formation.  The distance
+from the northern to the southern Downs is about 22 miles, and the
+thickness of the several formations is on an average about 1100 feet, as I
+am informed by Prof. Ramsay.  But if, as some geologists suppose, a range
+of older rocks underlies the Weald, on the flanks of which the overlying
+sedimentary deposits might have accumulated in thinner masses than
+elsewhere, the above estimate would be erroneous; but this source of doubt
+probably would not greatly affect the estimate as applied to the western
+extremity of the district.  If, then, we knew the rate at which the sea
+commonly wears away a line of cliff of any given height, we could measure
+the time requisite to have denuded the Weald.  This, of course, cannot be
+done; but we may, in order to form some crude notion on the subject, assume
+that the sea would eat into cliffs 500 feet in height at the rate of one
+inch in a century.  This will at first appear much too small an allowance;
+but it is the same as if we were to assume a cliff one yard in height to be
+eaten back along a whole line of coast at the rate of one yard in nearly
+every twenty-two years.  I doubt whether any rock, even as soft as chalk,
+would yield at this rate excepting on the most exposed coasts; though no
+doubt the degradation of a lofty cliff would be more rapid from the
+breakage of the fallen fragments.  On the other hand, I do not believe that
+any line of coast, ten or twenty miles in length, ever suffers degradation
+at the same time along its whole indented length; and we must remember that
+almost all strata contain harder layers or nodules, which from long
+resisting attrition form a breakwater at the base.  Hence, under ordinary
+circumstances, I conclude that for a cliff 500 feet in height, a denudation
+of one inch per century for the whole length would be an ample allowance. 
+At this rate, on the above data, the denudation of the Weald must have
+required 306,662,400 years; or say three hundred million years.
+</para>
+
+<para>
+The action of fresh water on the gently inclined Wealden district, when
+upraised, could hardly have been great, but it would somewhat reduce the
+above estimate.  On the other hand, during oscillations of level, which we
+know this area has undergone, the surface may have existed for millions of
+years as land, and thus have escaped the action of the sea:  when deeply
+submerged for perhaps equally long periods, it would, likewise, have
+escaped the action of the coast-waves.  So that in all probability a far
+longer period than 300 million years has elapsed since the latter part of
+the Secondary period.
+</para>
+
+<para>
+I have made these few remarks because it is highly important for us to gain
+some notion, however imperfect, of the lapse of years.  During each of
+these years, over the whole world, the land and the water has been peopled
+by hosts of living forms.  What an infinite number of generations, which
+the mind cannot grasp, must have succeeded each other in the long roll of
+years!  Now turn to our richest geological museums, and what a paltry
+display we behold!
+</para>
+
+<para>
+On the poorness of our Palaeontological collections. -- That our
+palaeontological collections are very imperfect, is admitted by every one. 
+The remark of that admirable palaeontologist, the late Edward Forbes,
+should not be forgotten, namely, that numbers of our fossil species are
+known and named from single and often broken specimens, or from a few
+specimens collected on some one spot.  Only a small portion of the surface
+of the earth has been geologically explored, and no part with sufficient
+care, as the important discoveries made every year in Europe prove.  No
+organism wholly soft can be preserved.  Shells and bones will decay and
+disappear when left on the bottom of the sea, where sediment is not
+accumulating.  I believe we are continually taking a most erroneous view,
+when we tacitly admit to ourselves that sediment is being deposited over
+nearly the whole bed of the sea, at a rate sufficiently quick to embed and
+preserve fossil remains.  Throughout an enormously large proportion of the
+ocean, the bright blue tint of the water bespeaks its purity.  The many
+cases on record of a formation conformably covered, after an enormous
+interval of time, by another and later formation, without the underlying
+bed having suffered in the interval any wear and tear, seem explicable only
+on the view of the bottom of the sea not rarely lying for ages in an
+unaltered condition.  The remains which do become embedded, if in sand or
+gravel, will when the beds are upraised generally be dissolved by the
+percolation of rain-water.  I suspect that but few of the very many animals
+which live on the beach between high and low watermark are preserved.  For
+instance, the several species of the Chthamalinae (a sub-family of sessile
+cirripedes) coat the rocks all over the world in infinite numbers:  they
+are all strictly littoral, with the exception of a single Mediterranean
+species, which inhabits deep water and has been found fossil in Sicily,
+whereas not one other species has hitherto been found in any tertiary
+formation:  yet it is now known that the genus Chthamalus existed during
+the chalk period.  The molluscan genus Chiton offers a partially analogous
+case.
+</para>
+
+<para>
+With respect to the terrestrial productions which lived during the
+Secondary and Palaeozoic periods, it is superfluous to state that our
+evidence from fossil remains is fragmentary in an extreme degree.  For
+instance, not a land shell is known belonging to either of these vast
+periods, with one exception discovered by Sir C. Lyell in the carboniferous
+strata of North America.  In regard to mammiferous remains, a single glance
+at the historical table published in the Supplement to Lyell's Manual, will
+bring home the truth, how accidental and rare is their preservation, far
+better than pages of detail.  Nor is their rarity surprising, when we
+remember how large a proportion of the bones of tertiary mammals have been
+discovered either in caves or in lacustrine deposits; and that not a cave
+or true lacustrine bed is known belonging to the age of our secondary or
+palaeozoic formations.
+</para>
+
+<para>
+But the imperfection in the geological record mainly results from another
+and more important cause than any of the foregoing; namely, from the
+several formations being separated from each other by wide intervals of
+time.  When we see the formations tabulated in written works, or when we
+follow them in nature, it is difficult to avoid believing that they are
+closely consecutive.  But we know, for instance, from Sir R. Murchison's
+great work on Russia, what wide gaps there are in that country between the
+superimposed formations; so it is in North America, and in many other parts
+of the world.  The most skilful geologist, if his attention had been
+exclusively confined to these large territories, would never have suspected
+that during the periods which were blank and barren in his own country,
+great piles of sediment, charged with new and peculiar forms of life, had
+elsewhere been accumulated.  And if in each separate territory, hardly any
+idea can be formed of the length of time which has elapsed between the
+consecutive formations, we may infer that this could nowhere be
+ascertained.  The frequent and great changes in the mineralogical
+composition of consecutive formations, generally implying great changes in
+the geography of the surrounding lands, whence the sediment has been
+derived, accords with the belief of vast intervals of time having elapsed
+between each formation.
+</para>
+
+<para>
+But we can, I think, see why the geological formations of each region are
+almost invariably intermittent; that is, have not followed each other in
+close sequence.  Scarcely any fact struck me more when examining many
+hundred miles of the South American coasts, which have been upraised
+several hundred feet within the recent period, than the absence of any
+recent deposits sufficiently extensive to last for even a short geological
+period.  Along the whole west coast, which is inhabited by a peculiar
+marine fauna, tertiary beds are so scantily developed, that no record of
+several successive and peculiar marine faunas will probably be preserved to
+a distant age.  A little reflection will explain why along the rising coast
+of the western side of South America, no extensive formations with recent
+or tertiary remains can anywhere be found, though the supply of sediment
+must for ages have been great, from the enormous degradation of the
+coast-rocks and from muddy streams entering the sea.  The explanation, no
+doubt, is, that the littoral and sub-littoral deposits are continually worn
+away, as soon as they are brought up by the slow and gradual rising of the
+land within the grinding action of the coast-waves.
+</para>
+
+<para>
+We may, I think, safely conclude that sediment must be accumulated in
+extremely thick, solid, or extensive masses, in order to withstand the
+incessant action of the waves, when first upraised and during subsequent
+oscillations of level.  Such thick and extensive accumulations of sediment
+may be formed in two ways; either, in profound depths of the sea, in which
+case, judging from the researches of E. Forbes, we may conclude that the
+bottom will be inhabited by extremely few animals, and the mass when
+upraised will give a most imperfect record of the forms of life which then
+existed; or, sediment may be accumulated to any thickness and extent over a
+shallow bottom, if it continue slowly to subside.  In this latter case, as
+long as the rate of subsidence and supply of sediment nearly balance each
+other, the sea will remain shallow and favourable for life, and thus a
+fossiliferous formation thick enough, when upraised, to resist any amount
+of degradation, may be formed.
+</para>
+
+<para>
+I am convinced that all our ancient formations, which are rich in fossils,
+have thus been formed during subsidence.  Since publishing my views on this
+subject in 1845, I have watched the progress of Geology, and have been
+surprised to note how author after author, in treating of this or that
+great formation, has come to the conclusion that it was accumulated during
+subsidence.  I may add, that the only ancient tertiary formation on the
+west coast of South America, which has been bulky enough to resist such
+degradation as it has as yet suffered, but which will hardly last to a
+distant geological age, was certainly deposited during a downward
+oscillation of level, and thus gained considerable thickness.
+</para>
+
+<para>
+All geological facts tell us plainly that each area has undergone numerous
+slow oscillations of level, and apparently these oscillations have affected
+wide spaces.  Consequently formations rich in fossils and sufficiently
+thick and extensive to resist subsequent degradation, may have been formed
+over wide spaces during periods of subsidence, but only where the supply of
+sediment was sufficient to keep the sea shallow and to embed and preserve
+the remains before they had time to decay.  On the other hand, as long as
+the bed of the sea remained stationary, thick deposits could not have been
+accumulated in the shallow parts, which are the most favourable to life. 
+Still less could this have happened during the alternate periods of
+elevation; or, to speak more accurately, the beds which were then
+accumulated will have been destroyed by being upraised and brought within
+the limits of the coast-action.
+</para>
+
+<para>
+Thus the geological record will almost necessarily be rendered
+intermittent.  I feel much confidence in the truth of these views, for they
+are in strict accordance with the general principles inculcated by Sir C.
+Lyell; and E. Forbes independently arrived at a similar conclusion.
+</para>
+
+<para>
+One remark is here worth a passing notice.  During periods of elevation the
+area of the land and of the adjoining shoal parts of the sea will be
+increased, and new stations will often be formed;--all circumstances most
+favourable, as previously explained, for the formation of new varieties and
+species; but during such periods there will generally be a blank in the
+geological record.  On the other hand, during subsidence, the inhabited
+area and number of inhabitants will decrease (excepting the productions on
+the shores of a continent when first broken up into an archipelago), and
+consequently during subsidence, though there will be much extinction, fewer
+new varieties or species will be formed; and it is during these very
+periods of subsidence, that our great deposits rich in fossils have been
+accumulated.  Nature may almost be said to have guarded against the
+frequent discovery of her transitional or linking forms.
+</para>
+
+<para>
+From the foregoing considerations it cannot be doubted that the geological
+record, viewed as a whole, is extremely imperfect; but if we confine our
+attention to any one formation, it becomes more difficult to understand,
+why we do not therein find closely graduated varieties between the allied
+species which lived at its commencement and at its close.  Some cases are
+on record of the same species presenting distinct varieties in the upper
+and lower parts of the same formation, but, as they are rare, they may be
+here passed over.  Although each formation has indisputably required a vast
+number of years for its deposition, I can see several reasons why each
+should not include a graduated series of links between the species which
+then lived; but I can by no means pretend to assign due proportional weight
+to the following considerations.
+</para>
+
+<para>
+Although each formation may mark a very long lapse of years, each perhaps
+is short compared with the period requisite to change one species into
+another.  I am aware that two palaeontologists, whose opinions are worthy
+of much deference, namely Bronn and Woodward, have concluded that the
+average duration of each formation is twice or thrice as long as the
+average duration of specific forms.  But insuperable difficulties, as it
+seems to me, prevent us coming to any just conclusion on this head.  When
+we see a species first appearing in the middle of any formation, it would
+be rash in the extreme to infer that it had not elsewhere previously
+existed.  So again when we find a species disappearing before the uppermost
+layers have been deposited, it would be equally rash to suppose that it
+then became wholly extinct.  We forget how small the area of Europe is
+compared with the rest of the world; nor have the several stages of the
+same formation throughout Europe been correlated with perfect accuracy.
+</para>
+
+<para>
+With marine animals of all kinds, we may safely infer a large amount of
+migration during climatal and other changes; and when we see a species
+first appearing in any formation, the probability is that it only then
+first immigrated into that area.  It is well known, for instance, that
+several species appeared somewhat earlier in the palaeozoic beds of North
+America than in those of Europe; time having apparently been required for
+their migration from the American to the European seas.  In examining the
+latest deposits of various quarters of the world, it has everywhere been
+noted, that some few still existing species are common in the deposit, but
+have become extinct in the immediately surrounding sea; or, conversely,
+that some are now abundant in the neighbouring sea, but are rare or absent
+in this particular deposit.  It is an excellent lesson to reflect on the
+ascertained amount of migration of the inhabitants of Europe during the
+Glacial period, which forms only a part of one whole geological period; and
+likewise to reflect on the great changes of level, on the inordinately
+great change of climate, on the prodigious lapse of time, all included
+within this same glacial period.  Yet it may be doubted whether in any
+quarter of the world, sedimentary deposits, including fossil remains, have
+gone on accumulating within the same area during the whole of this period. 
+It is not, for instance, probable that sediment was deposited during the
+whole of the glacial period near the mouth of the Mississippi, within that
+limit of depth at which marine animals can flourish; for we know what vast
+geographical changes occurred in other parts of America during this space
+of time.  When such beds as were deposited in shallow water near the mouth
+of the Mississippi during some part of the glacial period shall have been
+upraised, organic remains will probably first appear and disappear at
+different levels, owing to the migration of species and to geographical
+changes.  And in the distant future, a geologist examining these beds,
+might be tempted to conclude that the average duration of life of the
+embedded fossils had been less than that of the glacial period, instead of
+having been really far greater, that is extending from before the glacial
+epoch to the present day.
+</para>
+
+<para>
+In order to get a perfect gradation between two forms in the upper and
+lower parts of the same formation, the deposit must have gone on
+accumulating for a very long period, in order to have given sufficient time
+for the slow process of variation; hence the deposit will generally have to
+be a very thick one; and the species undergoing modification will have had
+to live on the same area throughout this whole time.  But we have seen that
+a thick fossiliferous formation can only be accumulated during a period of
+subsidence; and to keep the depth approximately the same, which is
+necessary in order to enable the same species to live on the same space,
+the supply of sediment must nearly have counterbalanced the amount of
+subsidence.  But this same movement of subsidence will often tend to sink
+the area whence the sediment is derived, and thus diminish the supply
+whilst the downward movement continues.  In fact, this nearly exact
+balancing between the supply of sediment and the amount of subsidence is
+probably a rare contingency; for it has been observed by more than one
+palaeontologist, that very thick deposits are usually barren of organic
+remains, except near their upper or lower limits.
+</para>
+
+<para>
+It would seem that each separate formation, like the whole pile of
+formations in any country, has generally been intermittent in its
+accumulation.  When we see, as is so often the case, a formation composed
+of beds of different mineralogical composition, we may reasonably suspect
+that the process of deposition has been much interrupted, as a change in
+the currents of the sea and a supply of sediment of a different nature will
+generally have been due to geographical changes requiring much time.  Nor
+will the closest inspection of a formation give any idea of the time which
+its deposition has consumed.  Many instances could be given of beds only a
+few feet in thickness, representing formations, elsewhere thousands of feet
+in thickness, and which must have required an enormous period for their
+accumulation; yet no one ignorant of this fact would have suspected the
+vast lapse of time represented by the thinner formation.  Many cases could
+be given of the lower beds of a formation having been upraised, denuded,
+submerged, and then re-covered by the upper beds of the same
+formation,--facts, showing what wide, yet easily overlooked, intervals have
+occurred in its accumulation.  In other cases we have the plainest evidence
+in great fossilised trees, still standing upright as they grew, of many
+long intervals of time and changes of level during the process of
+deposition, which would never even have been suspected, had not the trees
+chanced to have been preserved:  thus, Messrs. Lyell and Dawson found
+carboniferous beds 1400 feet thick in Nova Scotia, with ancient
+root-bearing strata, one above the other, at no less than sixty-eight
+different levels.  Hence, when the same species occur at the bottom,
+middle, and top of a formation, the probability is that they have not lived
+on the same spot during the whole period of deposition, but have
+disappeared and reappeared, perhaps many times, during the same geological
+period.  So that if such species were to undergo a considerable amount of
+modification during any one geological period, a section would not probably
+include all the fine intermediate gradations which must on my theory have
+existed between them, but abrupt, though perhaps very slight, changes of
+form.
+</para>
+
+<para>
+It is all-important to remember that naturalists have no golden rule by
+which to distinguish species and varieties; they grant some little
+variability to each species, but when they meet with a somewhat greater
+amount of difference between any two forms, they rank both as species,
+unless they are enabled to connect them together by close intermediate
+gradations.  And this from the reasons just assigned we can seldom hope to
+effect in any one geological section.  Supposing B and C to be two species,
+and a third, A, to be found in an underlying bed; even if A were strictly
+intermediate between B and C, it would simply be ranked as a third and
+distinct species, unless at the same time it could be most closely
+connected with either one or both forms by intermediate varieties.  Nor
+should it be forgotten, as before explained, that A might be the actual
+progenitor of B and C, and yet might not at all necessarily be strictly
+intermediate between them in all points of structure.  So that we might
+obtain the parent-species and its several modified descendants from the
+lower and upper beds of a formation, and unless we obtained numerous
+transitional gradations, we should not recognise their relationship, and
+should consequently be compelled to rank them all as distinct species.
+</para>
+
+<para>
+It is notorious on what excessively slight differences many
+palaeontologists have founded their species; and they do this the more
+readily if the specimens come from different sub-stages of the same
+formation.  Some experienced conchologists are now sinking many of the very
+fine species of D'Orbigny and others into the rank of varieties; and on
+this view we do find the kind of evidence of change which on my theory we
+ought to find.  Moreover, if we look to rather wider intervals, namely, to
+distinct but consecutive stages of the same great formation, we find that
+the embedded fossils, though almost universally ranked as specifically
+different, yet are far more closely allied to each other than are the
+species found in more widely separated formations; but to this subject I
+shall have to return in the following chapter.
+</para>
+
+<para>
+One other consideration is worth notice:  with animals and plants that can
+propagate rapidly and are not highly locomotive, there is reason to
+suspect, as we have formerly seen, that their varieties are generally at
+first local; and that such local varieties do not spread widely and
+supplant their parent-forms until they have been modified and perfected in
+some considerable degree.  According to this view, the chance of
+discovering in a formation in any one country all the early stages of
+transition between any two forms, is small, for the successive changes are
+supposed to have been local or confined to some one spot.  Most marine
+animals have a wide range; and we have seen that with plants it is those
+which have the widest range, that oftenest present varieties; so that with
+shells and other marine animals, it is probably those which have had the
+widest range, far exceeding the limits of the known geological formations
+of Europe, which have oftenest given rise, first to local varieties and
+ultimately to new species; and this again would greatly lessen the chance
+of our being able to trace the stages of transition in any one geological
+formation.
+</para>
+
+<para>
+It should not be forgotten, that at the present day, with perfect specimens
+for examination, two forms can seldom be connected by intermediate
+varieties and thus proved to be the same species, until many specimens have
+been collected from many places; and in the case of fossil species this
+could rarely be effected by palaeontologists.  We shall, perhaps, best
+perceive the improbability of our being enabled to connect species by
+numerous, fine, intermediate, fossil links, by asking ourselves whether,
+for instance, geologists at some future period will be able to prove, that
+our different breeds of cattle, sheep, horses, and dogs have descended from
+a single stock or from several aboriginal stocks; or, again, whether
+certain sea-shells inhabiting the shores of North America, which are ranked
+by some conchologists as distinct species from their European
+representatives, and by other conchologists as only varieties, are really
+varieties or are, as it is called, specifically distinct.  This could be
+effected only by the future geologist discovering in a fossil state
+numerous intermediate gradations; and such success seems to me improbable
+in the highest degree.
+</para>
+
+<para>
+Geological research, though it has added numerous species to existing and
+extinct genera, and has made the intervals between some few groups less
+wide than they otherwise would have been, yet has done scarcely anything in
+breaking down the distinction between species, by connecting them together
+by numerous, fine, intermediate varieties; and this not having been
+effected, is probably the gravest and most obvious of all the many
+objections which may be urged against my views.  Hence it will be worth
+while to sum up the foregoing remarks, under an imaginary illustration. 
+The Malay Archipelago is of about the size of Europe from the North Cape to
+the Mediterranean, and from Britain to Russia; and therefore equals all the
+geological formations which have been examined with any accuracy, excepting
+those of the United States of America.  I fully agree with Mr.
+Godwin-Austen, that the present condition of the Malay Archipelago, with
+its numerous large islands separated by wide and shallow seas, probably
+represents the former state of Europe, when most of our formations were
+accumulating.  The Malay Archipelago is one of the richest regions of the
+whole world in organic beings; yet if all the species were to be collected
+which have ever lived there, how imperfectly would they represent the
+natural history of the world!
+</para>
+
+<para>
+But we have every reason to believe that the terrestrial productions of the
+archipelago would be preserved in an excessively imperfect manner in the
+formations which we suppose to be there accumulating.  I suspect that not
+many of the strictly littoral animals, or of those which lived on naked
+submarine rocks, would be embedded; and those embedded in gravel or sand,
+would not endure to a distant epoch.  Wherever sediment did not accumulate
+on the bed of the sea, or where it did not accumulate at a sufficient rate
+to protect organic bodies from decay, no remains could be preserved.
+</para>
+
+<para>
+In our archipelago, I believe that fossiliferous formations could be formed
+of sufficient thickness to last to an age, as distant in futurity as the
+secondary formations lie in the past, only during periods of subsidence. 
+These periods of subsidence would be separated from each other by enormous
+intervals, during which the area would be either stationary or rising;
+whilst rising, each fossiliferous formation would be destroyed, almost as
+soon as accumulated, by the incessant coast-action, as we now see on the
+shores of South America.  During the periods of subsidence there would
+probably be much extinction of life; during the periods of elevation, there
+would be much variation, but the geological record would then be least
+perfect.
+</para>
+
+<para>
+It may be doubted whether the duration of any one great period of
+subsidence over the whole or part of the archipelago, together with a
+contemporaneous accumulation of sediment, would exceed the average duration
+of the same specific forms; and these contingencies are indispensable for
+the preservation of all the transitional gradations between any two or more
+species.  If such gradations were not fully preserved, transitional
+varieties would merely appear as so many distinct species.  It is, also,
+probable that each great period of subsidence would be interrupted by
+oscillations of level, and that slight climatal changes would intervene
+during such lengthy periods; and in these cases the inhabitants of the
+archipelago would have to migrate, and no closely consecutive record of
+their modifications could be preserved in any one formation.
+</para>
+
+<para>
+Very many of the marine inhabitants of the archipelago now range thousands
+of miles beyond its confines; and analogy leads me to believe that it would
+be chiefly these far-ranging species which would oftenest produce new
+varieties; and the varieties would at first generally be local or confined
+to one place, but if possessed of any decided advantage, or when further
+modified and improved, they would slowly spread and supplant their
+parent-forms.  When such varieties returned to their ancient homes, as they
+would differ from their former state, in a nearly uniform, though perhaps
+extremely slight degree, they would, according to the principles followed
+by many palaeontologists, be ranked as new and distinct species.
+</para>
+
+<para>
+If then, there be some degree of truth in these remarks, we have no right
+to expect to find in our geological formations, an infinite number of those
+fine transitional forms, which on my theory assuredly have connected all
+the past and present species of the same group into one long and branching
+chain of life.  We ought only to look for a few links, some more closely,
+some more distantly related to each other; and these links, let them be
+ever so close, if found in different stages of the same formation, would,
+by most palaeontologists, be ranked as distinct species.  But I do not
+pretend that I should ever have suspected how poor a record of the
+mutations of life, the best preserved geological section presented, had not
+the difficulty of our not discovering innumerable transitional links
+between the species which appeared at the commencement and close of each
+formation, pressed so hardly on my theory.
+</para>
+
+<para>
+On the sudden appearance of whole groups of Allied Species. -- The abrupt
+manner in which whole groups of species suddenly appear in certain
+formations, has been urged by several palaeontologists, for instance, by
+Agassiz, Pictet, and by none more forcibly than by Professor Sedgwick, as a
+fatal objection to the belief in the transmutation of species.  If numerous
+species, belonging to the same genera or families, have really started into
+life all at once, the fact would be fatal to the theory of descent with
+slow modification through natural selection.  For the development of a
+group of forms, all of which have descended from some one progenitor, must
+have been an extremely slow process; and the progenitors must have lived
+long ages before their modified descendants.  But we continually over-rate
+the perfection of the geological record, and falsely infer, because certain
+genera or families have not been found beneath a certain stage, that they
+did not exist before that stage.  We continually forget how large the world
+is, compared with the area over which our geological formations have been
+carefully examined; we forget that groups of species may elsewhere have
+long existed and have slowly multiplied before they invaded the ancient
+archipelagoes of Europe and of the United States.  We do not make due
+allowance for the enormous intervals of time, which have probably elapsed
+between our consecutive formations,--longer perhaps in some cases than the
+time required for the accumulation of each formation.  These intervals will
+have given time for the multiplication of species from some one or some few
+parent-forms; and in the succeeding formation such species will appear as
+if suddenly created.
+</para>
+
+<para>
+I may here recall a remark formerly made, namely that it might require a
+long succession of ages to adapt an organism to some new and peculiar line
+of life, for instance to fly through the air; but that when this had been
+effected, and a few species had thus acquired a great advantage over other
+organisms, a comparatively short time would be necessary to produce many
+divergent forms, which would be able to spread rapidly and widely
+throughout the world.
+</para>
+
+<para>
+I will now give a few examples to illustrate these remarks; and to show how
+liable we are to error in supposing that whole groups of species have
+suddenly been produced.  I may recall the well-known fact that in
+geological treatises, published not many years ago, the great class of
+mammals was always spoken of as having abruptly come in at the commencement
+of the tertiary series.  And now one of the richest known accumulations of
+fossil mammals belongs to the middle of the secondary series; and one true
+mammal has been discovered in the new red sandstone at nearly the
+commencement of this great series.  Cuvier used to urge that no monkey
+occurred in any tertiary stratum; but now extinct species have been
+discovered in India, South America, and in Europe even as far back as the
+eocene stage.  The most striking case, however, is that of the Whale
+family; as these animals have huge bones, are marine, and range over the
+world, the fact of not a single bone of a whale having been discovered in
+any secondary formation, seemed fully to justify the belief that this great
+and distinct order had been suddenly produced in the interval between the
+latest secondary and earliest tertiary formation.  But now we may read in
+the Supplement to Lyell's 'Manual,' published in 1858, clear evidence of
+the existence of whales in the upper greensand, some time before the close
+of the secondary period.
+</para>
+
+<para>
+I may give another instance, which from having passed under my own eyes has
+much struck me.  In a memoir on Fossil Sessile Cirripedes, I have stated
+that, from the number of existing and extinct tertiary species; from the
+extraordinary abundance of the individuals of many species all over the
+world, from the Arctic regions to the equator, inhabiting various zones of
+depths from the upper tidal limits to 50 fathoms; from the perfect manner
+in which specimens are preserved in the oldest tertiary beds; from the ease
+with which even a fragment of a valve can be recognised; from all these
+circumstances, I inferred that had sessile cirripedes existed during the
+secondary periods, they would certainly have been preserved and discovered;
+and as not one species had been discovered in beds of this age, I concluded
+that this great group had been suddenly developed at the commencement of
+the tertiary series.  This was a sore trouble to me, adding as I thought
+one more instance of the abrupt appearance of a great group of species. 
+But my work had hardly been published, when a skilful palaeontologist, M.
+Bosquet, sent me a drawing of a perfect specimen of an unmistakeable
+sessile cirripede, which he had himself extracted from the chalk of
+Belgium.  And, as if to make the case as striking as possible, this sessile
+cirripede was a Chthamalus, a very common, large, and ubiquitous genus, of
+which not one specimen has as yet been found even in any tertiary stratum. 
+Hence we now positively know that sessile cirripedes existed during the
+secondary period; and these cirripedes might have been the progenitors of
+our many tertiary and existing species.
+</para>
+
+<para>
+The case most frequently insisted on by palaeontologists of the apparently
+sudden appearance of a whole group of species, is that of the teleostean
+fishes, low down in the Chalk period.  This group includes the large
+majority of existing species.  Lately, Professor Pictet has carried their
+existence one sub-stage further back; and some palaeontologists believe
+that certain much older fishes, of which the affinities are as yet
+imperfectly known, are really teleostean.  Assuming, however, that the
+whole of them did appear, as Agassiz believes, at the commencement of the
+chalk formation, the fact would certainly be highly remarkable; but I
+cannot see that it would be an insuperable difficulty on my theory, unless
+it could likewise be shown that the species of this group appeared suddenly
+and simultaneously throughout the world at this same period.  It is almost
+superfluous to remark that hardly any fossil-fish are known from south of
+the equator; and by running through Pictet's Palaeontology it will be seen
+that very few species are known from several formations in Europe.  Some
+few families of fish now have a confined range; the teleostean fish might
+formerly have had a similarly confined range, and after having been largely
+developed in some one sea, might have spread widely.  Nor have we any right
+to suppose that the seas of the world have always been so freely open from
+south to north as they are at present.  Even at this day, if the Malay
+Archipelago were converted into land, the tropical parts of the Indian
+Ocean would form a large and perfectly enclosed basin, in which any great
+group of marine animals might be multiplied; and here they would remain
+confined, until some of the species became adapted to a cooler climate, and
+were enabled to double the southern capes of Africa or Australia, and thus
+reach other and distant seas.
+</para>
+
+<para>
+From these and similar considerations, but chiefly from our ignorance of
+the geology of other countries beyond the confines of Europe and the United
+States; and from the revolution in our palaeontological ideas on many
+points, which the discoveries of even the last dozen years have effected,
+it seems to me to be about as rash in us to dogmatize on the succession of
+organic beings throughout the world, as it would be for a naturalist to
+land for five minutes on some one barren point in Australia, and then to
+discuss the number and range of its productions.
+</para>
+
+<para>
+On the sudden appearance of groups of Allied Species in the lowest known
+fossiliferous strata. -- There is another and allied difficulty, which is
+much graver.  I allude to the manner in which numbers of species of the
+same group, suddenly appear in the lowest known fossiliferous rocks.  Most
+of the arguments which have convinced me that all the existing species of
+the same group have descended from one progenitor, apply with nearly equal
+force to the earliest known species.  For instance, I cannot doubt that all
+the Silurian trilobites have descended from some one crustacean, which must
+have lived long before the Silurian age, and which probably differed
+greatly from any known animal.  Some of the most ancient Silurian animals,
+as the Nautilus, Lingula, &amp;c., do not differ much from living species; and
+it cannot on my theory be supposed, that these old species were the
+progenitors of all the species of the orders to which they belong, for they
+do not present characters in any degree intermediate between them.  If,
+moreover, they had been the progenitors of these orders, they would almost
+certainly have been long ago supplanted and exterminated by their numerous
+and improved descendants.
+</para>
+
+<para>
+Consequently, if my theory be true, it is indisputable that before the
+lowest Silurian stratum was deposited, long periods elapsed, as long as, or
+probably far longer than, the whole interval from the Silurian age to the
+present day; and that during these vast, yet quite unknown, periods of
+time, the world swarmed with living creatures.
+</para>
+
+<para>
+To the question why we do not find records of these vast primordial
+periods, I can give no satisfactory answer.  Several of the most eminent
+geologists, with Sir R. Murchison at their head, are convinced that we see
+in the organic remains of the lowest Silurian stratum the dawn of life on
+this planet.  Other highly competent judges, as Lyell and the late E.
+Forbes, dispute this conclusion.  We should not forget that only a small
+portion of the world is known with accuracy.  M. Barrande has lately added
+another and lower stage to the Silurian system, abounding with new and
+peculiar species.  Traces of life have been detected in the Longmynd beds
+beneath Barrande's so-called primordial zone.  The presence of phosphatic
+nodules and bituminous matter in some of the lowest azoic rocks, probably
+indicates the former existence of life at these periods.  But the
+difficulty of understanding the absence of vast piles of fossiliferous
+strata, which on my theory no doubt were somewhere accumulated before the
+Silurian epoch, is very great.  If these most ancient beds had been wholly
+worn away by denudation, or obliterated by metamorphic action, we ought to
+find only small remnants of the formations next succeeding them in age, and
+these ought to be very generally in a metamorphosed condition.  But the
+descriptions which we now possess of the Silurian deposits over immense
+territories in Russia and in North America, do not support the view, that
+the older a formation is, the more it has suffered the extremity of
+denudation and metamorphism.
+</para>
+
+<para>
+The case at present must remain inexplicable; and may be truly urged as a
+valid argument against the views here entertained.  To show that it may
+hereafter receive some explanation, I will give the following hypothesis. 
+From the nature of the organic remains, which do not appear to have
+inhabited profound depths, in the several formations of Europe and of the
+United States; and from the amount of sediment, miles in thickness, of
+which the formations are composed, we may infer that from first to last
+large islands or tracts of land, whence the sediment was derived, occurred
+in the neighbourhood of the existing continents of Europe and North
+America.  But we do not know what was the state of things in the intervals
+between the successive formations; whether Europe and the United States
+during these intervals existed as dry land, or as a submarine surface near
+land, on which sediment was not deposited, or again as the bed of an open
+and unfathomable sea.
+</para>
+
+<para>
+Looking to the existing oceans, which are thrice as extensive as the land,
+we see them studded with many islands; but not one oceanic island is as yet
+known to afford even a remnant of any palaeozoic or secondary formation. 
+Hence we may perhaps infer, that during the palaeozoic and secondary
+periods, neither continents nor continental islands existed where our
+oceans now extend; for had they existed there, palaeozoic and secondary
+formations would in all probability have been accumulated from sediment
+derived from their wear and tear; and would have been at least partially
+upheaved by the oscillations of level, which we may fairly conclude must
+have intervened during these enormously long periods.  If then we may infer
+anything from these facts, we may infer that where our oceans now extend,
+oceans have extended from the remotest period of which we have any record;
+and on the other hand, that where continents now exist, large tracts of
+land have existed, subjected no doubt to great oscillations of level, since
+the earliest silurian period.  The coloured map appended to my volume on
+Coral Reefs, led me to conclude that the great oceans are still mainly
+areas of subsidence, the great archipelagoes still areas of oscillations of
+level, and the continents areas of elevation.  But have we any right to
+assume that things have thus remained from eternity?  Our continents seem
+to have been formed by a preponderance, during many oscillations of level,
+of the force of elevation; but may not the areas of preponderant movement
+have changed in the lapse of ages?  At a period immeasurably antecedent to
+the silurian epoch, continents may have existed where oceans are now spread
+out; and clear and open oceans may have existed where our continents now
+stand.  Nor should we be justified in assuming that if, for instance, the
+bed of the Pacific Ocean were now converted into a continent, we should
+there find formations older than the silurian strata, supposing such to
+have been formerly deposited; for it might well happen that strata which
+had subsided some miles nearer to the centre of the earth, and which had
+been pressed on by an enormous weight of superincumbent water, might have
+undergone far more metamorphic action than strata which have always
+remained nearer to the surface.  The immense areas in some parts of the
+world, for instance in South America, of bare metamorphic rocks, which must
+have been heated under great pressure, have always seemed to me to require
+some special explanation; and we may perhaps believe that we see in these
+large areas, the many formations long anterior to the silurian epoch in a
+completely metamorphosed condition.
+</para>
+
+<para>
+The several difficulties here discussed, namely our not finding in the
+successive formations infinitely numerous transitional links between the
+many species which now exist or have existed; the sudden manner in which
+whole groups of species appear in our European formations; the almost
+entire absence, as at present known, of fossiliferous formations beneath
+the Silurian strata, are all undoubtedly of the gravest nature.  We see
+this in the plainest manner by the fact that all the most eminent
+palaeontologists, namely Cuvier, Owen, Agassiz, Barrande, Falconer, E.
+Forbes, &amp;c., and all our greatest geologists, as Lyell, Murchison,
+Sedgwick, &amp;c., have unanimously, often vehemently, maintained the
+immutability of species.  But I have reason to believe that one great
+authority, Sir Charles Lyell, from further reflexion entertains grave
+doubts on this subject.  I feel how rash it is to differ from these great
+authorities, to whom, with others, we owe all our knowledge.  Those who
+think the natural geological record in any degree perfect, and who do not
+attach much weight to the facts and arguments of other kinds given in this
+volume, will undoubtedly at once reject my theory.  For my part, following
+out Lyell's metaphor, I look at the natural geological record, as a history
+of the world imperfectly kept, and written in a changing dialect; of this
+history we possess the last volume alone, relating only to two or three
+countries.  Of this volume, only here and there a short chapter has been
+preserved; and of each page, only here and there a few lines.  Each word of
+the slowly-changing language, in which the history is supposed to be
+written, being more or less different in the interrupted succession of
+chapters, may represent the apparently abruptly changed forms of life,
+entombed in our consecutive, but widely separated formations.  On this
+view, the difficulties above discussed are greatly diminished, or even
+disappear.
+</para>
+
+</chapter>
+
+<chapter>
+<chapheader>
+
+<chapnum>Chapter X</chapnum>
+
+<title>On the Geological Succession of Organic Beings</title>
+
+<chapsummary>
+On the slow and successive appearance of new species -- On their different
+rates of change -- Species once lost do not reappear -- Groups of species
+follow the same general rules in their appearance and disappearance as do
+single species -- On Extinction -- On simultaneous changes in the forms of
+life throughout the world -- On the affinities of extinct species to each
+other and to living species -- On the state of development of ancient forms
+-- On the succession of the same types within the same areas -- Summary of
+preceding and present chapters.
+</chapsummary>
+</chapheader>
+
+<para>
+Let us now see whether the several facts and rules relating to the
+geological succession of organic beings, better accord with the common view
+of the immutability of species, or with that of their slow and gradual
+modification, through descent and natural selection.
+</para>
+
+<para>
+New species have appeared very slowly, one after another, both on the land
+and in the waters.  Lyell has shown that it is hardly possible to resist
+the evidence on this head in the case of the several tertiary stages; and
+every year tends to fill up the blanks between them, and to make the
+percentage system of lost and new forms more gradual.  In some of the most
+recent beds, though undoubtedly of high antiquity if measured by years,
+only one or two species are lost forms, and only one or two are new forms,
+having here appeared for the first time, either locally, or, as far as we
+know, on the face of the earth.  If we may trust the observations of
+Philippi in Sicily, the successive changes in the marine inhabitants of
+that island have been many and most gradual.  The secondary formations are
+more broken; but, as Bronn has remarked, neither the appearance nor
+disappearance of their many now extinct species has been simultaneous in
+each separate formation.
+</para>
+
+<para>
+Species of different genera and classes have not changed at the same rate,
+or in the same degree.  In the oldest tertiary beds a few living shells may
+still be found in the midst of a multitude of extinct forms.  Falconer has
+given a striking instance of a similar fact, in an existing crocodile
+associated with many strange and lost mammals and reptiles in the
+sub-Himalayan deposits.  The Silurian Lingula differs but little from the
+living species of this genus; whereas most of the other Silurian Molluscs
+and all the Crustaceans have changed greatly.  The productions of the land
+seem to change at a quicker rate than those of the sea, of which a striking
+instance has lately been observed in Switzerland.  There is some reason to
+believe that organisms, considered high in the scale of nature, change more
+quickly than those that are low:  though there are exceptions to this rule. 
+The amount of organic change, as Pictet has remarked, does not strictly
+correspond with the succession of our geological formations; so that
+between each two consecutive formations, the forms of life have seldom
+changed in exactly the same degree.  Yet if we compare any but the most
+closely related formations, all the species will be found to have undergone
+some change.  When a species has once disappeared from the face of the
+earth, we have reason to believe that the same identical form never
+reappears.  The strongest apparent exception to this latter rule, is that
+of the so-called 'colonies' of M. Barrande, which intrude for a period in
+the midst of an older formation, and then allow the pre-existing fauna to
+reappear; but Lyell's explanation, namely, that it is a case of temporary
+migration from a distinct geographical province, seems to me satisfactory.
+</para>
+
+<para>
+These several facts accord well with my theory.  I believe in no fixed law
+of development, causing all the inhabitants of a country to change
+abruptly, or simultaneously, or to an equal degree.  The process of
+modification must be extremely slow.  The variability of each species is
+quite independent of that of all others.  Whether such variability be taken
+advantage of by natural selection, and whether the variations be
+accumulated to a greater or lesser amount, thus causing a greater or lesser
+amount of modification in the varying species, depends on many complex
+contingencies,--on the variability being of a beneficial nature, on the
+power of intercrossing, on the rate of breeding, on the slowly changing
+physical conditions of the country, and more especially on the nature of
+the other inhabitants with which the varying species comes into
+competition.  Hence it is by no means surprising that one species should
+retain the same identical form much longer than others; or, if changing,
+that it should change less.  We see the same fact in geographical
+distribution; for instance, in the land-shells and coleopterous insects of
+Madeira having come to differ considerably from their nearest allies on the
+continent of Europe, whereas the marine shells and birds have remained
+unaltered.  We can perhaps understand the apparently quicker rate of change
+in terrestrial and in more highly organised productions compared with
+marine and lower productions, by the more complex relations of the higher
+beings to their organic and inorganic conditions of life, as explained in a
+former chapter.  When many of the inhabitants of a country have become
+modified and improved, we can understand, on the principle of competition,
+and on that of the many all-important relations of organism to organism,
+that any form which does not become in some degree modified and improved,
+will be liable to be exterminated.  Hence we can see why all the species in
+the same region do at last, if we look to wide enough intervals of time,
+become modified; for those which do not change will become extinct.
+</para>
+
+<para>
+In members of the same class the average amount of change, during long and
+equal periods of time, may, perhaps, be nearly the same; but as the
+accumulation of long-enduring fossiliferous formations depends on great
+masses of sediment having been deposited on areas whilst subsiding, our
+formations have been almost necessarily accumulated at wide and irregularly
+intermittent intervals; consequently the amount of organic change exhibited
+by the fossils embedded in consecutive formations is not equal.  Each
+formation, on this view, does not mark a new and complete act of creation,
+but only an occasional scene, taken almost at hazard, in a slowly changing
+drama.
+</para>
+
+<para>
+We can clearly understand why a species when once lost should never
+reappear, even if the very same conditions of life, organic and inorganic,
+should recur.  For though the offspring of one species might be adapted
+(and no doubt this has occurred in innumerable instances) to fill the exact
+place of another species in the economy of nature, and thus supplant it;
+yet the two forms--the old and the new--would not be identically the same;
+for both would almost certainly inherit different characters from their
+distinct progenitors.  For instance, it is just possible, if our
+fantail-pigeons were all destroyed, that fanciers, by striving during long
+ages for the same object, might make a new breed hardly distinguishable
+from our present fantail; but if the parent rock-pigeon were also
+destroyed, and in nature we have every reason to believe that the
+parent-form will generally be supplanted and exterminated by its improved
+offspring, it is quite incredible that a fantail, identical with the
+existing breed, could be raised from any other species of pigeon, or even
+from the other well-established races of the domestic pigeon, for the
+newly-formed fantail would be almost sure to inherit from its new
+progenitor some slight characteristic differences.
+</para>
+
+<para>
+Groups of species, that is, genera and families, follow the same general
+rules in their appearance and disappearance as do single species, changing
+more or less quickly, and in a greater or lesser degree.  A group does not
+reappear after it has once disappeared; or its existence, as long as it
+lasts, is continuous.  I am aware that there are some apparent exceptions
+to this rule, but the exceptions are surprisingly few, so few, that E.
+Forbes, Pictet, and Woodward (though all strongly opposed to such views as
+I maintain) admit its truth; and the rule strictly accords with my theory. 
+For as all the species of the same group have descended from some one
+species, it is clear that as long as any species of the group have appeared
+in the long succession of ages, so long must its members have continuously
+existed, in order to have generated either new and modified or the same old
+and unmodified forms.  Species of the genus Lingula, for instance, must
+have continuously existed by an unbroken succession of generations, from
+the lowest Silurian stratum to the present day.
+</para>
+
+<para>
+We have seen in the last chapter that the species of a group sometimes
+falsely appear to have come in abruptly; and I have attempted to give an
+explanation of this fact, which if true would have been fatal to my views. 
+But such cases are certainly exceptional; the general rule being a gradual
+increase in number, till the group reaches its maximum, and then, sooner or
+later, it gradually decreases.  If the number of the species of a genus, or
+the number of the genera of a family, be represented by a vertical line of
+varying thickness, crossing the successive geological formations in which
+the species are found, the line will sometimes falsely appear to begin at
+its lower end, not in a sharp point, but abruptly; it then gradually
+thickens upwards, sometimes keeping for a space of equal thickness, and
+ultimately thins out in the upper beds, marking the decrease and final
+extinction of the species.  This gradual increase in number of the species
+of a group is strictly conformable with my theory; as the species of the
+same genus, and the genera of the same family, can increase only slowly and
+progressively; for the process of modification and the production of a
+number of allied forms must be slow and gradual,--one species giving rise
+first to two or three varieties, these being slowly converted into species,
+which in their turn produce by equally slow steps other species, and so on,
+like the branching of a great tree from a single stem, till the group
+becomes large.
+</para>
+
+<para>
+On Extinction. -- We have as yet spoken only incidentally of the
+disappearance of species and of groups of species.  On the theory of
+natural selection the extinction of old forms and the production of new and
+improved forms are intimately connected together.  The old notion of all
+the inhabitants of the earth having been swept away at successive periods
+by catastrophes, is very generally given up, even by those geologists, as
+Elie de Beaumont, Murchison, Barrande, &amp;c., whose general views would
+naturally lead them to this conclusion.  On the contrary, we have every
+reason to believe, from the study of the tertiary formations, that species
+and groups of species gradually disappear, one after another, first from
+one spot, then from another, and finally from the world.  Both single
+species and whole groups of species last for very unequal periods; some
+groups, as we have seen, having endured from the earliest known dawn of
+life to the present day; some having disappeared before the close of the
+palaeozoic period.  No fixed law seems to determine the length of time
+during which any single species or any single genus endures.  There is
+reason to believe that the complete extinction of the species of a group is
+generally a slower process than their production:  if the appearance and
+disappearance of a group of species be represented, as before, by a
+vertical line of varying thickness, the line is found to taper more
+gradually at its upper end, which marks the progress of extermination, than
+at its lower end, which marks the first appearance and increase in numbers
+of the species.  In some cases, however, the extermination of whole groups
+of beings, as of ammonites towards the close of the secondary period, has
+been wonderfully sudden.
+</para>
+
+<para>
+The whole subject of the extinction of species has been involved in the
+most gratuitous mystery.  Some authors have even supposed that as the
+individual has a definite length of life, so have species a definite
+duration.  No one I think can have marvelled more at the extinction of
+species, than I have done.  When I found in La Plata the tooth of a horse
+embedded with the remains of Mastodon, Megatherium, Toxodon, and other
+extinct monsters, which all co-existed with still living shells at a very
+late geological period, I was filled with astonishment; for seeing that the
+horse, since its introduction by the Spaniards into South America, has run
+wild over the whole country and has increased in numbers at an unparalleled
+rate, I asked myself what could so recently have exterminated the former
+horse under conditions of life apparently so favourable.  But how utterly
+groundless was my astonishment!  Professor Owen soon perceived that the
+tooth, though so like that of the existing horse, belonged to an extinct
+species.  Had this horse been still living, but in some degree rare, no
+naturalist would have felt the least surprise at its rarity; for rarity is
+the attribute of a vast number of species of all classes, in all countries. 
+If we ask ourselves why this or that species is rare, we answer that
+something is unfavourable in its conditions of life; but what that
+something is, we can hardly ever tell.  On the supposition of the fossil
+horse still existing as a rare species, we might have felt certain from the
+analogy of all other mammals, even of the slow-breeding elephant, and from
+the history of the naturalisation of the domestic horse in South America,
+that under more favourable conditions it would in a very few years have
+stocked the whole continent.  But we could not have told what the
+unfavourable conditions were which checked its increase, whether some one
+or several contingencies, and at what period of the horse's life, and in
+what degree, they severally acted.  If the conditions had gone on, however
+slowly, becoming less and less favourable, we assuredly should not have
+perceived the fact, yet the fossil horse would certainly have become rarer
+and rarer, and finally extinct;--its place being seized on by some more
+successful competitor.
+</para>
+
+<para>
+It is most difficult always to remember that the increase of every living
+being is constantly being checked by unperceived injurious agencies; and
+that these same unperceived agencies are amply sufficient to cause rarity,
+and finally extinction.  We see in many cases in the more recent tertiary
+formations, that rarity precedes extinction; and we know that this has been
+the progress of events with those animals which have been exterminated,
+either locally or wholly, through man's agency.  I may repeat what I
+published in 1845, namely, that to admit that species generally become rare
+before they become extinct--to feel no surprise at the rarity of a species,
+and yet to marvel greatly when it ceases to exist, is much the same as to
+admit that sickness in the individual is the forerunner of death--to feel
+no surprise at sickness, but when the sick man dies, to wonder and to
+suspect that he died by some unknown deed of violence.
+</para>
+
+<para>
+The theory of natural selection is grounded on the belief that each new
+variety, and ultimately each new species, is produced and maintained by
+having some advantage over those with which it comes into competition; and
+the consequent extinction of less-favoured forms almost inevitably follows. 
+It is the same with our domestic productions:  when a new and slightly
+improved variety has been raised, it at first supplants the less improved
+varieties in the same neighbourhood; when much improved it is transported
+far and near, like our short-horn cattle, and takes the place of other
+breeds in other countries.  Thus the appearance of new forms and the
+disappearance of old forms, both natural and artificial, are bound
+together.  In certain flourishing groups, the number of new specific forms
+which have been produced within a given time is probably greater than that
+of the old forms which have been exterminated; but we know that the number
+of species has not gone on indefinitely increasing, at least during the
+later geological periods, so that looking to later times we may believe
+that the production of new forms has caused the extinction of about the
+same number of old forms.
+</para>
+
+<para>
+The competition will generally be most severe, as formerly explained and
+illustrated by examples, between the forms which are most like each other
+in all respects.  Hence the improved and modified descendants of a species
+will generally cause the extermination of the parent-species; and if many
+new forms have been developed from any one species, the nearest allies of
+that species, i.e. the species of the same genus, will be the most liable
+to extermination.  Thus, as I believe, a number of new species descended
+from one species, that is a new genus, comes to supplant an old genus,
+belonging to the same family.  But it must often have happened that a new
+species belonging to some one group will have seized on the place occupied
+by a species belonging to a distinct group, and thus caused its
+extermination; and if many allied forms be developed from the successful
+intruder, many will have to yield their places; and it will generally be
+allied forms, which will suffer from some inherited inferiority in common. 
+But whether it be species belonging to the same or to a distinct class,
+which yield their places to other species which have been modified and
+improved, a few of the sufferers may often long be preserved, from being
+fitted to some peculiar line of life, or from inhabiting some distant and
+isolated station, where they have escaped severe competition.  For
+instance, a single species of Trigonia, a great genus of shells in the
+secondary formations, survives in the Australian seas; and a few members of
+the great and almost extinct group of Ganoid fishes still inhabit our fresh
+waters.  Therefore the utter extinction of a group is generally, as we have
+seen, a slower process than its production.
+</para>
+
+<para>
+With respect to the apparently sudden extermination of whole families or
+orders, as of Trilobites at the close of the palaeozoic period and of
+Ammonites at the close of the secondary period, we must remember what has
+been already said on the probable wide intervals of time between our
+consecutive formations; and in these intervals there may have been much
+slow extermination.  Moreover, when by sudden immigration or by unusually
+rapid development, many species of a new group have taken possession of a
+new area, they will have exterminated in a correspondingly rapid manner
+many of the old inhabitants; and the forms which thus yield their places
+will commonly be allied, for they will partake of some inferiority in
+common.
+</para>
+
+<para>
+Thus, as it seems to me, the manner in which single species and whole
+groups of species become extinct, accords well with the theory of natural
+selection.  We need not marvel at extinction; if we must marvel, let it be
+at our presumption in imagining for a moment that we understand the many
+complex contingencies, on which the existence of each species depends.  If
+we forget for an instant, that each species tends to increase inordinately,
+and that some check is always in action, yet seldom perceived by us, the
+whole economy of nature will be utterly obscured.  Whenever we can
+precisely say why this species is more abundant in individuals than that;
+why this species and not another can be naturalised in a given country;
+then, and not till then, we may justly feel surprise why we cannot account
+for the extinction of this particular species or group of species.
+</para>
+
+<para>
+On the Forms of Life changing almost simultaneously throughout the World. -
+- Scarcely any palaeontological discovery is more striking than the fact,
+that the forms of life change almost simultaneously throughout the world. 
+Thus our European Chalk formation can be recognised in many distant parts
+of the world, under the most different climates, where not a fragment of
+the mineral chalk itself can be found; namely, in North America, in
+equatorial South America, in Tierra del Fuego, at the Cape of Good Hope,
+and in the peninsula of India.  For at these distant points, the organic
+remains in certain beds present an unmistakeable degree of resemblance to
+those of the Chalk.  It is not that the same species are met with; for in
+some cases not one species is identically the same, but they belong to the
+same families, genera, and sections of genera, and sometimes are similarly
+characterised in such trifling points as mere superficial sculpture. 
+Moreover other forms, which are not found in the Chalk of Europe, but which
+occur in the formations either above or below, are similarly absent at
+these distant points of the world.  In the several successive palaeozoic
+formations of Russia, Western Europe and North America, a similar
+parallelism in the forms of life has been observed by several authors:  so
+it is, according to Lyell, with the several European and North American
+tertiary deposits.  Even if the few fossil species which are common to the
+Old and New Worlds be kept wholly out of view, the general parallelism in
+the successive forms of life, in the stages of the widely separated
+palaeozoic and tertiary periods, would still be manifest, and the several
+formations could be easily correlated.
+</para>
+
+<para>
+These observations, however, relate to the marine inhabitants of distant
+parts of the world:  we have not sufficient data to judge whether the
+productions of the land and of fresh water change at distant points in the
+same parallel manner.  We may doubt whether they have thus changed:  if the
+Megatherium, Mylodon, Macrauchenia, and Toxodon had been brought to Europe
+from La Plata, without any information in regard to their geological
+position, no one would have suspected that they had coexisted with still
+living sea-shells; but as these anomalous monsters coexisted with the
+Mastodon and Horse, it might at least have been inferred that they had
+lived during one of the latter tertiary stages.
+</para>
+
+<para>
+When the marine forms of life are spoken of as having changed
+simultaneously throughout the world, it must not be supposed that this
+expression relates to the same thousandth or hundred-thousandth year, or
+even that it has a very strict geological sense; for if all the marine
+animals which live at the present day in Europe, and all those that lived
+in Europe during the pleistocene period (an enormously remote period as
+measured by years, including the whole glacial epoch), were to be compared
+with those now living in South America or in Australia, the most skilful
+naturalist would hardly be able to say whether the existing or the
+pleistocene inhabitants of Europe resembled most closely those of the
+southern hemisphere.  So, again, several highly competent observers believe
+that the existing productions of the United States are more closely related
+to those which lived in Europe during certain later tertiary stages, than
+to those which now live here; and if this be so, it is evident that
+fossiliferous beds deposited at the present day on the shores of North
+America would hereafter be liable to be classed with somewhat older
+European beds.  Nevertheless, looking to a remotely future epoch, there
+can, I think, be little doubt that all the more modern marine formations,
+namely, the upper pliocene, the pleistocene and strictly modern beds, of
+Europe, North and South America, and Australia, from containing fossil
+remains in some degree allied, and from not including those forms which are
+only found in the older underlying deposits, would be correctly ranked as
+simultaneous in a geological sense.
+</para>
+
+<para>
+The fact of the forms of life changing simultaneously, in the above large
+sense, at distant parts of the world, has greatly struck those admirable
+observers, MM. de Verneuil and d'Archiac.  After referring to the
+parallelism of the palaeozoic forms of life in various parts of Europe,
+they add, 'If struck by this strange sequence, we turn our attention to
+North America, and there discover a series of analogous phenomena, it will
+appear certain that all these modifications of species, their extinction,
+and the introduction of new ones, cannot be owing to mere changes in marine
+currents or other causes more or less local and temporary, but depend on
+general laws which govern the whole animal kingdom.'  M. Barrande has made
+forcible remarks to precisely the same effect.  It is, indeed, quite futile
+to look to changes of currents, climate, or other physical conditions, as
+the cause of these great mutations in the forms of life throughout the
+world, under the most different climates.  We must, as Barrande has
+remarked, look to some special law.  We shall see this more clearly when we
+treat of the present distribution of organic beings, and find how slight is
+the relation between the physical conditions of various countries, and the
+nature of their inhabitants.
+</para>
+
+<para>
+This great fact of the parallel succession of the forms of life throughout
+the world, is explicable on the theory of natural selection.  New species
+are formed by new varieties arising, which have some advantage over older
+forms; and those forms, which are already dominant, or have some advantage
+over the other forms in their own country, would naturally oftenest give
+rise to new varieties or incipient species; for these latter must be
+victorious in a still higher degree in order to be preserved and to
+survive.  We have distinct evidence on this head, in the plants which are
+dominant, that is, which are commonest in their own homes, and are most
+widely diffused, having produced the greatest number of new varieties.  It
+is also natural that the dominant, varying, and far-spreading species,
+which already have invaded to a certain extent the territories of other
+species, should be those which would have the best chance of spreading
+still further, and of giving rise in new countries to new varieties and
+species.  The process of diffusion may often be very slow, being dependent
+on climatal and geographical changes, or on strange accidents, but in the
+long run the dominant forms will generally succeed in spreading.  The
+diffusion would, it is probable, be slower with the terrestrial inhabitants
+of distinct continents than with the marine inhabitants of the continuous
+sea.  We might therefore expect to find, as we apparently do find, a less
+strict degree of parallel succession in the productions of the land than of
+the sea.
+</para>
+
+<para>
+Dominant species spreading from any region might encounter still more
+dominant species, and then their triumphant course, or even their
+existence, would cease.  We know not at all precisely what are all the
+conditions most favourable for the multiplication of new and dominant
+species; but we can, I think, clearly see that a number of individuals,
+from giving a better chance of the appearance of favourable variations, and
+that severe competition with many already existing forms, would be highly
+favourable, as would be the power of spreading into new territories.  A
+certain amount of isolation, recurring at long intervals of time, would
+probably be also favourable, as before explained.  One quarter of the world
+may have been most favourable for the production of new and dominant
+species on the land, and another for those in the waters of the sea.  If
+two great regions had been for a long period favourably circumstanced in an
+equal degree, whenever their inhabitants met, the battle would be prolonged
+and severe; and some from one birthplace and some from the other might be
+victorious.  But in the course of time, the forms dominant in the highest
+degree, wherever produced, would tend everywhere to prevail.  As they
+prevailed, they would cause the extinction of other and inferior forms; and
+as these inferior forms would be allied in groups by inheritance, whole
+groups would tend slowly to disappear; though here and there a single
+member might long be enabled to survive.
+</para>
+
+<para>
+Thus, as it seems to me, the parallel, and, taken in a large sense,
+simultaneous, succession of the same forms of life throughout the world,
+accords well with the principle of new species having been formed by
+dominant species spreading widely and varying; the new species thus
+produced being themselves dominant owing to inheritance, and to having
+already had some advantage over their parents or over other species; these
+again spreading, varying, and producing new species.  The forms which are
+beaten and which yield their places to the new and victorious forms, will
+generally be allied in groups, from inheriting some inferiority in common;
+and therefore as new and improved groups spread throughout the world, old
+groups will disappear from the world; and the succession of forms in both
+ways will everywhere tend to correspond.
+</para>
+
+<para>
+There is one other remark connected with this subject worth making.  I have
+given my reasons for believing that all our greater fossiliferous
+formations were deposited during periods of subsidence; and that blank
+intervals of vast duration occurred during the periods when the bed of the
+sea was either stationary or rising, and likewise when sediment was not
+thrown down quickly enough to embed and preserve organic remains.  During
+these long and blank intervals I suppose that the inhabitants of each
+region underwent a considerable amount of modification and extinction, and
+that there was much migration from other parts of the world.  As we have
+reason to believe that large areas are affected by the same movement, it is
+probable that strictly contemporaneous formations have often been
+accumulated over very wide spaces in the same quarter of the world; but we
+are far from having any right to conclude that this has invariably been the
+case, and that large areas have invariably been affected by the same
+movements.  When two formations have been deposited in two regions during
+nearly, but not exactly the same period, we should find in both, from the
+causes explained in the foregoing paragraphs, the same general succession
+in the forms of life; but the species would not exactly correspond; for
+there will have been a little more time in the one region than in the other
+for modification, extinction, and immigration.
+</para>
+
+<para>
+I suspect that cases of this nature have occurred in Europe.  Mr.
+Prestwich, in his admirable Memoirs on the eocene deposits of England and
+France, is able to draw a close general parallelism between the successive
+stages in the two countries; but when he compares certain stages in England
+with those in France, although he finds in both a curious accordance in the
+numbers of the species belonging to the same genera, yet the species
+themselves differ in a manner very difficult to account for, considering
+the proximity of the two areas,--unless, indeed, it be assumed that an
+isthmus separated two seas inhabited by distinct, but contemporaneous,
+faunas.  Lyell has made similar observations on some of the later tertiary
+formations.  Barrande, also, shows that there is a striking general
+parallelism in the successive Silurian deposits of Bohemia and Scandinavia;
+nevertheless he finds a surprising amount of difference in the species.  If
+the several formations in these regions have not been deposited during the
+same exact periods,--a formation in one region often corresponding with a
+blank interval in the other,--and if in both regions the species have gone
+on slowly changing during the accumulation of the several formations and
+during the long intervals of time between them; in this case, the several
+formations in the two regions could be arranged in the same order, in
+accordance with the general succession of the form of life, and the order
+would falsely appear to be strictly parallel; nevertheless the species
+would not all be the same in the apparently corresponding stages in the two
+regions.
+</para>
+
+<para>
+On the Affinities of extinct Species to each other, and to living forms. --
+Let us now look to the mutual affinities of extinct and living species. 
+They all fall into one grand natural system; and this fact is at once
+explained on the principle of descent.  The more ancient any form is, the
+more, as a general rule, it differs from living forms.  But, as Buckland
+long ago remarked, all fossils can be classed either in still existing
+groups, or between them.  That the extinct forms of life help to fill up
+the wide intervals between existing genera, families, and orders, cannot be
+disputed.  For if we confine our attention either to the living or to the
+extinct alone, the series is far less perfect than if we combine both into
+one general system.  With respect to the Vertebrata, whole pages could be
+filled with striking illustrations from our great palaeontologist, Owen,
+showing how extinct animals fall in between existing groups.  Cuvier ranked
+the Ruminants and Pachyderms, as the two most distinct orders of mammals;
+but Owen has discovered so many fossil links, that he has had to alter the
+whole classification of these two orders; and has placed certain pachyderms
+in the same sub-order with ruminants:  for example, he dissolves by fine
+gradations the apparently wide difference between the pig and the camel. 
+In regard to the Invertebrata, Barrande, and a higher authority could not
+be named, asserts that he is every day taught that palaeozoic animals,
+though belonging to the same orders, families, or genera with those living
+at the present day, were not at this early epoch limited in such distinct
+groups as they now are.
+</para>
+
+<para>
+Some writers have objected to any extinct species or group of species being
+considered as intermediate between living species or groups.  If by this
+term it is meant that an extinct form is directly intermediate in all its
+characters between two living forms, the objection is probably valid.  But
+I apprehend that in a perfectly natural classification many fossil species
+would have to stand between living species, and some extinct genera between
+living genera, even between genera belonging to distinct families.  The
+most common case, especially with respect to very distinct groups, such as
+fish and reptiles, seems to be, that supposing them to be distinguished at
+the present day from each other by a dozen characters, the ancient members
+of the same two groups would be distinguished by a somewhat lesser number
+of characters, so that the two groups, though formerly quite distinct, at
+that period made some small approach to each other.
+</para>
+
+<para>
+It is a common belief that the more ancient a form is, by so much the more
+it tends to connect by some of its characters groups now widely separated
+from each other.  This remark no doubt must be restricted to those groups
+which have undergone much change in the course of geological ages; and it
+would be difficult to prove the truth of the proposition, for every now and
+then even a living animal, as the Lepidosiren, is discovered having
+affinities directed towards very distinct groups.  Yet if we compare the
+older Reptiles and Batrachians, the older Fish, the older Cephalopods, and
+the eocene Mammals, with the more recent members of the same classes, we
+must admit that there is some truth in the remark.
+</para>
+
+<para>
+Let us see how far these several facts and inferences accord with the
+theory of descent with modification.  As the subject is somewhat complex, I
+must request the reader to turn to the diagram in the fourth chapter.  We
+may suppose that the numbered letters represent genera, and the dotted
+lines diverging from them the species in each genus.  The diagram is much
+too simple, too few genera and too few species being given, but this is
+unimportant for us.  The horizontal lines may represent successive
+geological formations, and all the forms beneath the uppermost line may be
+considered as extinct.  The three existing genera, a14, q14, p14, will form
+a small family; b14 and f14 a closely allied family or sub-family; and o14,
+e14, m14, a third family.  These three families, together with the many
+extinct genera on the several lines of descent diverging from the
+parent-form A, will form an order; for all will have inherited something in
+common from their ancient and common progenitor.  On the principle of the
+continued tendency to divergence of character, which was formerly
+illustrated by this diagram, the more recent any form is, the more it will
+generally differ from its ancient progenitor.  Hence we can understand the
+rule that the most ancient fossils differ most from existing forms.  We
+must not, however, assume that divergence of character is a necessary
+contingency; it depends solely on the descendants from a species being thus
+enabled to seize on many and different places in the economy of nature. 
+Therefore it is quite possible, as we have seen in the case of some
+Silurian forms, that a species might go on being slightly modified in
+relation to its slightly altered conditions of life, and yet retain
+throughout a vast period the same general characteristics.  This is
+represented in the diagram by the letter F14.
+</para>
+
+<para>
+All the many forms, extinct and recent, descended from A, make, as before
+remarked, one order; and this order, from the continued effects of
+extinction and divergence of character, has become divided into several
+sub-families and families, some of which are supposed to have perished at
+different periods, and some to have endured to the present day.
+</para>
+
+<para>
+By looking at the diagram we can see that if many of the extinct forms,
+supposed to be embedded in the successive formations, were discovered at
+several points low down in the series, the three existing families on the
+uppermost line would be rendered less distinct from each other.  If, for
+instance, the genera a1, a5, a10, f8, m3, m6, m9 were disinterred, these
+three families would be so closely linked together that they probably would
+have to be united into one great family, in nearly the same manner as has
+occurred with ruminants and pachyderms.  Yet he who objected to call the
+extinct genera, which thus linked the living genera of three families
+together, intermediate in character, would be justified, as they are
+intermediate, not directly, but only by a long and circuitous course
+through many widely different forms.  If many extinct forms were to be
+discovered above one of the middle horizontal lines or geological
+formations--for instance, above No. VI.--but none from beneath this line,
+then only the two families on the left hand (namely, a14, &amp;c., and b14,
+&amp;c.) would have to be united into one family; and the two other families
+(namely, a14 to f14 now including five genera, and o14 to m14) would yet
+remain distinct.  These two families, however, would be less distinct from
+each other than they were before the discovery of the fossils.  If, for
+instance, we suppose the existing genera of the two families to differ from
+each other by a dozen characters, in this case the genera, at the early
+period marked VI., would differ by a lesser number of characters; for at
+this early stage of descent they have not diverged in character from the
+common progenitor of the order, nearly so much as they subsequently
+diverged.  Thus it comes that ancient and extinct genera are often in some
+slight degree intermediate in character between their modified descendants,
+or between their collateral relations.
+</para>
+
+<para>
+In nature the case will be far more complicated than is represented in the
+diagram; for the groups will have been more numerous, they will have
+endured for extremely unequal lengths of time, and will have been modified
+in various degrees.  As we possess only the last volume of the geological
+record, and that in a very broken condition, we have no right to expect,
+except in very rare cases, to fill up wide intervals in the natural system,
+and thus unite distinct families or orders.  All that we have a right to
+expect, is that those groups, which have within known geological periods
+undergone much modification, should in the older formations make some
+slight approach to each other; so that the older members should differ less
+from each other in some of their characters than do the existing members of
+the same groups; and this by the concurrent evidence of our best
+palaeontologists seems frequently to be the case.
+</para>
+
+<para>
+Thus, on the theory of descent with modification, the main facts with
+respect to the mutual affinities of the extinct forms of life to each other
+and to living forms, seem to me explained in a satisfactory manner.  And
+they are wholly inexplicable on any other view.
+</para>
+
+<para>
+On this same theory, it is evident that the fauna of any great period in
+the earth's history will be intermediate in general character between that
+which preceded and that which succeeded it.  Thus, the species which lived
+at the sixth great stage of descent in the diagram are the modified
+offspring of those which lived at the fifth stage, and are the parents of
+those which became still more modified at the seventh stage; hence they
+could hardly fail to be nearly intermediate in character between the forms
+of life above and below.  We must, however, allow for the entire extinction
+of some preceding forms, and for the coming in of quite new forms by
+immigration, and for a large amount of modification, during the long and
+blank intervals between the successive formations.  Subject to these
+allowances, the fauna of each geological period undoubtedly is intermediate
+in character, between the preceding and succeeding faunas.  I need give
+only one instance, namely, the manner in which the fossils of the Devonian
+system, when this system was first discovered, were at once recognised by
+palaeontologists as intermediate in character between those of the
+overlying carboniferous, and underlying Silurian system.  But each fauna is
+not necessarily exactly intermediate, as unequal intervals of time have
+elapsed between consecutive formations.
+</para>
+
+<para>
+It is no real objection to the truth of the statement, that the fauna of
+each period as a whole is nearly intermediate in character between the
+preceding and succeeding faunas, that certain genera offer exceptions to
+the rule.  For instance, mastodons and elephants, when arranged by Dr.
+Falconer in two series, first according to their mutual affinities and then
+according to their periods of existence, do not accord in arrangement.  The
+species extreme in character are not the oldest, or the most recent; nor
+are those which are intermediate in character, intermediate in age.  But
+supposing for an instant, in this and other such cases, that the record of
+the first appearance and disappearance of the species was perfect, we have
+no reason to believe that forms successively produced necessarily endure
+for corresponding lengths of time:  a very ancient form might occasionally
+last much longer than a form elsewhere subsequently produced, especially in
+the case of terrestrial productions inhabiting separated districts.  To
+compare small things with great:  if the principal living and extinct races
+of the domestic pigeon were arranged as well as they could be in serial
+affinity, this arrangement would not closely accord with the order in time
+of their production, and still less with the order of their disappearance;
+for the parent rock-pigeon now lives; and many varieties between the
+rock-pigeon and the carrier have become extinct; and carriers which are
+extreme in the important character of length of beak originated earlier
+than short-beaked tumblers, which are at the opposite end of the series in
+this same respect.
+</para>
+
+<para>
+Closely connected with the statement, that the organic remains from an
+intermediate formation are in some degree intermediate in character, is the
+fact, insisted on by all palaeontologists, that fossils from two
+consecutive formations are far more closely related to each other, than are
+the fossils from two remote formations.  Pictet gives as a well-known
+instance, the general resemblance of the organic remains from the several
+stages of the chalk formation, though the species are distinct in each
+stage.  This fact alone, from its generality, seems to have shaken
+Professor Pictet in his firm belief in the immutability of species.  He who
+is acquainted with the distribution of existing species over the globe,
+will not attempt to account for the close resemblance of the distinct
+species in closely consecutive formations, by the physical conditions of
+the ancient areas having remained nearly the same.  Let it be remembered
+that the forms of life, at least those inhabiting the sea, have changed
+almost simultaneously throughout the world, and therefore under the most
+different climates and conditions.  Consider the prodigious vicissitudes of
+climate during the pleistocene period, which includes the whole glacial
+period, and note how little the specific forms of the inhabitants of the
+sea have been affected.
+</para>
+
+<para>
+On the theory of descent, the full meaning of the fact of fossil remains
+from closely consecutive formations, though ranked as distinct species,
+being closely related, is obvious.  As the accumulation of each formation
+has often been interrupted, and as long blank intervals have intervened
+between successive formations, we ought not to expect to find, as I
+attempted to show in the last chapter, in any one or two formations all the
+intermediate varieties between the species which appeared at the
+commencement and close of these periods; but we ought to find after
+intervals, very long as measured by years, but only moderately long as
+measured geologically, closely allied forms, or, as they have been called
+by some authors, representative species; and these we assuredly do find. 
+We find, in short, such evidence of the slow and scarcely sensible mutation
+of specific forms, as we have a just right to expect to find.
+</para>
+
+<para>
+On the state of Development of Ancient Forms. -- There has been much
+discussion whether recent forms are more highly developed than ancient.  I
+will not here enter on this subject, for naturalists have not as yet
+defined to each other's satisfaction what is meant by high and low forms. 
+But in one particular sense the more recent forms must, on my theory, be
+higher than the more ancient; for each new species is formed by having had
+some advantage in the struggle for life over other and preceding forms.  If
+under a nearly similar climate, the eocene inhabitants of one quarter of
+the world were put into competition with the existing inhabitants of the
+same or some other quarter, the eocene fauna or flora would certainly be
+beaten and exterminated; as would a secondary fauna by an eocene, and a
+palaeozoic fauna by a secondary fauna.  I do not doubt that this process of
+improvement has affected in a marked and sensible manner the organisation
+of the more recent and victorious forms of life, in comparison with the
+ancient and beaten forms; but I can see no way of testing this sort of
+progress.  Crustaceans, for instance, not the highest in their own class,
+may have beaten the highest molluscs.  From the extraordinary manner in
+which European productions have recently spread over New Zealand, and have
+seized on places which must have been previously occupied, we may believe,
+if all the animals and plants of Great Britain were set free in New
+Zealand, that in the course of time a multitude of British forms would
+become thoroughly naturalized there, and would exterminate many of the
+natives.  On the other hand, from what we see now occurring in New Zealand,
+and from hardly a single inhabitant of the southern hemisphere having
+become wild in any part of Europe, we may doubt, if all the productions of
+New Zealand were set free in Great Britain, whether any considerable number
+would be enabled to seize on places now occupied by our native plants and
+animals.  Under this point of view, the productions of Great Britain may be
+said to be higher than those of New Zealand.  Yet the most skilful
+naturalist from an examination of the species of the two countries could
+not have foreseen this result.
+</para>
+
+<para>
+Agassiz insists that ancient animals resemble to a certain extent the
+embryos of recent animals of the same classes; or that the geological
+succession of extinct forms is in some degree parallel to the embryological
+development of recent forms.  I must follow Pictet and Huxley in thinking
+that the truth of this doctrine is very far from proved.  Yet I fully
+expect to see it hereafter confirmed, at least in regard to subordinate
+groups, which have branched off from each other within comparatively recent
+times.  For this doctrine of Agassiz accords well with the theory of
+natural selection.  In a future chapter I shall attempt to show that the
+adult differs from its embryo, owing to variations supervening at a not
+early age, and being inherited at a corresponding age.  This process,
+whilst it leaves the embryo almost unaltered, continually adds, in the
+course of successive generations, more and more difference to the adult.
+</para>
+
+<para>
+Thus the embryo comes to be left as a sort of picture, preserved by nature,
+of the ancient and less modified condition of each animal.  This view may
+be true, and yet it may never be capable of full proof.  Seeing, for
+instance, that the oldest known mammals, reptiles, and fish strictly belong
+to their own proper classes, though some of these old forms are in a slight
+degree less distinct from each other than are the typical members of the
+same groups at the present day, it would be vain to look for animals having
+the common embryological character of the Vertebrata, until beds far
+beneath the lowest Silurian strata are discovered--a discovery of which the
+chance is very small.
+</para>
+
+<para>
+On the Succession of the same Types within the same areas, during the later
+tertiary periods. -- Mr. Clift many years ago showed that the fossil
+mammals from the Australian caves were closely allied to the living
+marsupials of that continent.  In South America, a similar relationship is
+manifest, even to an uneducated eye, in the gigantic pieces of armour like
+those of the armadillo, found in several parts of La Plata; and Professor
+Owen has shown in the most striking manner that most of the fossil mammals,
+buried there in such numbers, are related to South American types.  This
+relationship is even more clearly seen in the wonderful collection of
+fossil bones made by MM. Lund and Clausen in the caves of Brazil.  I was so
+much impressed with these facts that I strongly insisted, in 1839 and 1845,
+on this 'law of the succession of types,'--on 'this wonderful relationship
+in the same continent between the dead and the living.'  Professor Owen has
+subsequently extended the same generalisation to the mammals of the Old
+World.  We see the same law in this author's restorations of the extinct
+and gigantic birds of New Zealand.  We see it also in the birds of the
+caves of Brazil.  Mr. Woodward has shown that the same law holds good with
+sea-shells, but from the wide distribution of most genera of molluscs, it
+is not well displayed by them.  Other cases could be added, as the relation
+between the extinct and living land-shells of Madeira; and between the
+extinct and living brackish-water shells of the Aralo-Caspian Sea.
+</para>
+
+<para>
+Now what does this remarkable law of the succession of the same types
+within the same areas mean?  He would be a bold man, who after comparing
+the present climate of Australia and of parts of South America under the
+same latitude, would attempt to account, on the one hand, by dissimilar
+physical conditions for the dissimilarity of the inhabitants of these two
+continents, and, on the other hand, by similarity of conditions, for the
+uniformity of the same types in each during the later tertiary periods. 
+Nor can it be pretended that it is an immutable law that marsupials should
+have been chiefly or solely produced in Australia; or that Edentata and
+other American types should have been solely produced in South America. 
+For we know that Europe in ancient times was peopled by numerous
+marsupials; and I have shown in the publications above alluded to, that in
+America the law of distribution of terrestrial mammals was formerly
+different from what it now is.  North America formerly partook strongly of
+the present character of the southern half of the continent; and the
+southern half was formerly more closely allied, than it is at present, to
+the northern half.  In a similar manner we know from Falconer and Cautley's
+discoveries, that northern India was formerly more closely related in its
+mammals to Africa than it is at the present time.  Analogous facts could be
+given in relation to the distribution of marine animals.
+</para>
+
+<para>
+On the theory of descent with modification, the great law of the long
+enduring, but not immutable, succession of the same types within the same
+areas, is at once explained; for the inhabitants of each quarter of the
+world will obviously tend to leave in that quarter, during the next
+succeeding period of time, closely allied though in some degree modified
+descendants.  If the inhabitants of one continent formerly differed greatly
+from those of another continent, so will their modified descendants still
+differ in nearly the same manner and degree.  But after very long intervals
+of time and after great geographical changes, permitting much
+inter-migration, the feebler will yield to the more dominant forms, and
+there will be nothing immutable in the laws of past and present
+distribution.
+</para>
+
+<para>
+It may be asked in ridicule, whether I suppose that the megatherium and
+other allied huge monsters have left behind them in South America the
+sloth, armadillo, and anteater, as their degenerate descendants.  This
+cannot for an instant be admitted.  These huge animals have become wholly
+extinct, and have left no progeny.  But in the caves of Brazil, there are
+many extinct species which are closely allied in size and in other
+characters to the species still living in South America; and some of these
+fossils may be the actual progenitors of living species.  It must not be
+forgotten that, on my theory, all the species of the same genus have
+descended from some one species; so that if six genera, each having eight
+species, be found in one geological formation, and in the next succeeding
+formation there be six other allied or representative genera with the same
+number of species, then we may conclude that only one species of each of
+the six older genera has left modified descendants, constituting the six
+new genera.  The other seven species of the old genera have all died out
+and have left no progeny.  Or, which would probably be a far commoner case,
+two or three species of two or three alone of the six older genera will
+have been the parents of the six new genera; the other old species and the
+other whole genera having become utterly extinct.  In failing orders, with
+the genera and species decreasing in numbers, as apparently is the case of
+the Edentata of South America, still fewer genera and species will have
+left modified blood-descendants.
+</para>
+
+<para>
+Summary of the preceding and present Chapters -- I have attempted to show
+that the geological record is extremely imperfect; that only a small
+portion of the globe has been geologically explored with care; that only
+certain classes of organic beings have been largely preserved in a fossil
+state; that the number both of specimens and of species, preserved in our
+museums, is absolutely as nothing compared with the incalculable number of
+generations which must have passed away even during a single formation;
+that, owing to subsidence being necessary for the accumulation of
+fossiliferous deposits thick enough to resist future degradation, enormous
+intervals of time have elapsed between the successive formations; that
+there has probably been more extinction during the periods of subsidence,
+and more variation during the periods of elevation, and during the latter
+the record will have been least perfectly kept; that each single formation
+has not been continuously deposited; that the duration of each formation
+is, perhaps, short compared with the average duration of specific forms;
+that migration has played an important part in the first appearance of new
+forms in any one area and formation; that widely ranging species are those
+which have varied most, and have oftenest given rise to new species; and
+that varieties have at first often been local.  All these causes taken
+conjointly, must have tended to make the geological record extremely
+imperfect, and will to a large extent explain why we do not find
+interminable varieties, connecting together all the extinct and existing
+forms of life by the finest graduated steps.
+</para>
+
+<para>
+He who rejects these views on the nature of the geological record, will
+rightly reject my whole theory.  For he may ask in vain where are the
+numberless transitional links which must formerly have connected the
+closely allied or representative species, found in the several stages of
+the same great formation.  He may disbelieve in the enormous intervals of
+time which have elapsed between our consecutive formations; he may overlook
+how important a part migration must have played, when the formations of any
+one great region alone, as that of Europe, are considered; he may urge the
+apparent, but often falsely apparent, sudden coming in of whole groups of
+species.  He may ask where are the remains of those infinitely numerous
+organisms which must have existed long before the first bed of the Silurian
+system was deposited:  I can answer this latter question only
+hypothetically, by saying that as far as we can see, where our oceans now
+extend they have for an enormous period extended, and where our oscillating
+continents now stand they have stood ever since the Silurian epoch; but
+that long before that period, the world may have presented a wholly
+different aspect; and that the older continents, formed of formations older
+than any known to us, may now all be in a metamorphosed condition, or may
+lie buried under the ocean.
+</para>
+
+<para>
+Passing from these difficulties, all the other great leading facts in
+palaeontology seem to me simply to follow on the theory of descent with
+modification through natural selection.  We can thus understand how it is
+that new species come in slowly and successively; how species of different
+classes do not necessarily change together, or at the same rate, or in the
+same degree; yet in the long run that all undergo modification to some
+extent.  The extinction of old forms is the almost inevitable consequence
+of the production of new forms.  We can understand why when a species has
+once disappeared it never reappears.  Groups of species increase in numbers
+slowly, and endure for unequal periods of time; for the process of
+modification is necessarily slow, and depends on many complex
+contingencies.  The dominant species of the larger dominant groups tend to
+leave many modified descendants, and thus new sub-groups and groups are
+formed.  As these are formed, the species of the less vigorous groups, from
+their inferiority inherited from a common progenitor, tend to become
+extinct together, and to leave no modified offspring on the face of the
+earth.  But the utter extinction of a whole group of species may often be a
+very slow process, from the survival of a few descendants, lingering in
+protected and isolated situations.  When a group has once wholly
+disappeared, it does not reappear; for the link of generation has been
+broken.
+</para>
+
+<para>
+We can understand how the spreading of the dominant forms of life, which
+are those that oftenest vary, will in the long run tend to people the world
+with allied, but modified, descendants; and these will generally succeed in
+taking the places of those groups of species which are their inferiors in
+the struggle for existence.  Hence, after long intervals of time, the
+productions of the world will appear to have changed simultaneously.
+</para>
+
+<para>
+We can understand how it is that all the forms of life, ancient and recent,
+make together one grand system; for all are connected by generation.  We
+can understand, from the continued tendency to divergence of character, why
+the more ancient a form is, the more it generally differs from those now
+living.  Why ancient and extinct forms often tend to fill up gaps between
+existing forms, sometimes blending two groups previously classed as
+distinct into one; but more commonly only bringing them a little closer
+together.  The more ancient a form is, the more often, apparently, it
+displays characters in some degree intermediate between groups now
+distinct; for the more ancient a form is, the more nearly it will be
+related to, and consequently resemble, the common progenitor of groups,
+since become widely divergent.  Extinct forms are seldom directly
+intermediate between existing forms; but are intermediate only by a long
+and circuitous course through many extinct and very different forms.  We
+can clearly see why the organic remains of closely consecutive formations
+are more closely allied to each other, than are those of remote formations;
+for the forms are more closely linked together by generation:  we can
+clearly see why the remains of an intermediate formation are intermediate
+in character.
+</para>
+
+<para>
+The inhabitants of each successive period in the world's history have
+beaten their predecessors in the race for life, and are, in so far, higher
+in the scale of nature; and this may account for that vague yet ill-defined
+sentiment, felt by many palaeontologists, that organisation on the whole
+has progressed.  If it should hereafter be proved that ancient animals
+resemble to a certain extent the embryos of more recent animals of the same
+class, the fact will be intelligible.  The succession of the same types of
+structure within the same areas during the later geological periods ceases
+to be mysterious, and is simply explained by inheritance.
+</para>
+
+<para>
+If then the geological record be as imperfect as I believe it to be, and it
+may at least be asserted that the record cannot be proved to be much more
+perfect, the main objections to the theory of natural selection are greatly
+diminished or disappear.  On the other hand, all the chief laws of
+palaeontology plainly proclaim, as it seems to me, that species have been
+produced by ordinary generation:  old forms having been supplanted by new
+and improved forms of life, produced by the laws of variation still acting
+round us, and preserved by Natural Selection.
+</para>
+
+</chapter>
+
+<chapter>
+<chapheader>
+
+<chapnum>Chapter XI</chapnum>
+
+<title>Geographical Distribution</title>
+
+<chapsummary>
+Present distribution cannot be accounted for by differences in physical
+conditions -- Importance of barriers -- Affinity of the productions of the
+same continent -- Centres of creation -- Means of dispersal, by changes of
+climate and of the level of the land, and by occasional means -- Dispersal
+during the Glacial period co-extensive with the world.
+</chapsummary>
+</chapheader>
+
+<para>
+In considering the distribution of organic beings over the face of the
+globe, the first great fact which strikes us is, that neither the
+similarity nor the dissimilarity of the inhabitants of various regions can
+be accounted for by their climatal and other physical conditions.  Of late,
+almost every author who has studied the subject has come to this
+conclusion.  The case of America alone would almost suffice to prove its
+truth:  for if we exclude the northern parts where the circumpolar land is
+almost continuous, all authors agree that one of the most fundamental
+divisions in geographical distribution is that between the New and Old
+Worlds; yet if we travel over the vast American continent, from the central
+parts of the United States to its extreme southern point, we meet with the
+most diversified conditions; the most humid districts, arid deserts, lofty
+mountains, grassy plains, forests, marshes, lakes, and great rivers, under
+almost every temperature.  There is hardly a climate or condition in the
+Old World which cannot be paralleled in the New--at least as closely as the
+same species generally require; for it is a most rare case to find a group
+of organisms confined to any small spot, having conditions peculiar in only
+a slight degree; for instance, small areas in the Old World could be
+pointed out hotter than any in the New World, yet these are not inhabited
+by a peculiar fauna or flora.  Notwithstanding this parallelism in the
+conditions of the Old and New Worlds, how widely different are their living
+productions!
+</para>
+
+<para>
+In the southern hemisphere, if we compare large tracts of land in
+Australia, South Africa, and western South America, between latitudes 25
+deg and 35 deg, we shall find parts extremely similar in all their
+conditions, yet it would not be possible to point out three faunas and
+floras more utterly dissimilar.  Or again we may compare the productions of
+South America south of lat. 35 deg with those north of 25 deg, which
+consequently inhabit a considerably different climate, and they will be
+found incomparably more closely related to each other, than they are to the
+productions of Australia or Africa under nearly the same climate. 
+Analogous facts could be given with respect to the inhabitants of the sea.
+</para>
+
+<para>
+A second great fact which strikes us in our general review is, that
+barriers of any kind, or obstacles to free migration, are related in a
+close and important manner to the differences between the productions of
+various regions.  We see this in the great difference of nearly all the
+terrestrial productions of the New and Old Worlds, excepting in the
+northern parts, where the land almost joins, and where, under a slightly
+different climate, there might have been free migration for the northern
+temperate forms, as there now is for the strictly arctic productions.  We
+see the same fact in the great difference between the inhabitants of
+Australia, Africa, and South America under the same latitude:  for these
+countries are almost as much isolated from each other as is possible.  On
+each continent, also, we see the same fact; for on the opposite sides of
+lofty and continuous mountain-ranges, and of great deserts, and sometimes
+even of large rivers, we find different productions; though as mountain
+chains, deserts, &amp;c., are not as impassable, or likely to have endured so
+long as the oceans separating continents, the differences are very inferior
+in degree to those characteristic of distinct continents.
+</para>
+
+<para>
+Turning to the sea, we find the same law.  No two marine faunas are more
+distinct, with hardly a fish, shell, or crab in common, than those of the
+eastern and western shores of South and Central America; yet these great
+faunas are separated only by the narrow, but impassable, isthmus of Panama. 
+Westward of the shores of America, a wide space of open ocean extends, with
+not an island as a halting-place for emigrants; here we have a barrier of
+another kind, and as soon as this is passed we meet in the eastern islands
+of the Pacific, with another and totally distinct fauna.  So that here
+three marine faunas range far northward and southward, in parallel lines
+not far from each other, under corresponding climates; but from being
+separated from each other by impassable barriers, either of land or open
+sea, they are wholly distinct.  On the other hand, proceeding still further
+westward from the eastern islands of the tropical parts of the Pacific, we
+encounter no impassable barriers, and we have innumerable islands as
+halting-places, until after travelling over a hemisphere we come to the
+shores of Africa; and over this vast space we meet with no well-defined and
+distinct marine faunas.  Although hardly one shell, crab or fish is common
+to the above-named three approximate faunas of Eastern and Western America
+and the eastern Pacific islands, yet many fish range from the Pacific into
+the Indian Ocean, and many shells are common to the eastern islands of the
+Pacific and the eastern shores of Africa, on almost exactly opposite
+meridians of longitude.
+</para>
+
+<para>
+A third great fact, partly included in the foregoing statements, is the
+affinity of the productions of the same continent or sea, though the
+species themselves are distinct at different points and stations.  It is a
+law of the widest generality, and every continent offers innumerable
+instances.  Nevertheless the naturalist in travelling, for instance, from
+north to south never fails to be struck by the manner in which successive
+groups of beings, specifically distinct, yet clearly related, replace each
+other.  He hears from closely allied, yet distinct kinds of birds, notes
+nearly similar, and sees their nests similarly constructed, but not quite
+alike, with eggs coloured in nearly the same manner.  The plains near the
+Straits of Magellan are inhabited by one species of Rhea (American
+ostrich), and northward the plains of La Plata by another species of the
+same genus; and not by a true ostrich or emeu, like those found in Africa
+and Australia under the same latitude.  On these same plains of La Plata,
+we see the agouti and bizcacha, animals having nearly the same habits as
+our hares and rabbits and belonging to the same order of Rodents, but they
+plainly display an American type of structure.  We ascend the lofty peaks
+of the Cordillera and we find an alpine species of bizcacha; we look to the
+waters, and we do not find the beaver or musk-rat, but the coypu and
+capybara, rodents of the American type.  Innumerable other instances could
+be given.  If we look to the islands off the American shore, however much
+they may differ in geological structure, the inhabitants, though they may
+be all peculiar species, are essentially American.  We may look back to
+past ages, as shown in the last chapter, and we find American types then
+prevalent on the American continent and in the American seas.  We see in
+these facts some deep organic bond, prevailing throughout space and time,
+over the same areas of land and water, and independent of their physical
+conditions.  The naturalist must feel little curiosity, who is not led to
+inquire what this bond is.
+</para>
+
+<para>
+This bond, on my theory, is simply inheritance, that cause which alone, as
+far as we positively know, produces organisms quite like, or, as we see in
+the case of varieties nearly like each other.  The dissimilarity of the
+inhabitants of different regions may be attributed to modification through
+natural selection, and in a quite subordinate degree to the direct
+influence of different physical conditions.  The degree of dissimilarity
+will depend on the migration of the more dominant forms of life from one
+region into another having been effected with more or less ease, at periods
+more or less remote;--on the nature and number of the former
+immigrants;--and on their action and reaction, in their mutual struggles
+for life;--the relation of organism to organism being, as I have already
+often remarked, the most important of all relations.  Thus the high
+importance of barriers comes into play by checking migration; as does time
+for the slow process of modification through natural selection. 
+Widely-ranging species, abounding in individuals, which have already
+triumphed over many competitors in their own widely-extended homes will
+have the best chance of seizing on new places, when they spread into new
+countries.  In their new homes they will be exposed to new conditions, and
+will frequently undergo further modification and improvement; and thus they
+will become still further victorious, and will produce groups of modified
+descendants.  On this principle of inheritance with modification, we can
+understand how it is that sections of genera, whole genera, and even
+families are confined to the same areas, as is so commonly and notoriously
+the case.
+</para>
+
+<para>
+I believe, as was remarked in the last chapter, in no law of necessary
+development.  As the variability of each species is an independent
+property, and will be taken advantage of by natural selection, only so far
+as it profits the individual in its complex struggle for life, so the
+degree of modification in different species will be no uniform quantity. 
+If, for instance, a number of species, which stand in direct competition
+with each other, migrate in a body into a new and afterwards isolated
+country, they will be little liable to modification; for neither migration
+nor isolation in themselves can do anything.  These principles come into
+play only by bringing organisms into new relations with each other, and in
+a lesser degree with the surrounding physical conditions.  As we have seen
+in the last chapter that some forms have retained nearly the same character
+from an enormously remote geological period, so certain species have
+migrated over vast spaces, and have not become greatly modified.
+</para>
+
+<para>
+On these views, it is obvious, that the several species of the same genus,
+though inhabiting the most distant quarters of the world, must originally
+have proceeded from the same source, as they have descended from the same
+progenitor.  In the case of those species, which have undergone during
+whole geological periods but little modification, there is not much
+difficulty in believing that they may have migrated from the same region;
+for during the vast geographical and climatal changes which will have
+supervened since ancient times, almost any amount of migration is possible. 
+But in many other cases, in which we have reason to believe that the
+species of a genus have been produced within comparatively recent times,
+there is great difficulty on this head.  It is also obvious that the
+individuals of the same species, though now inhabiting distant and isolated
+regions, must have proceeded from one spot, where their parents were first
+produced:  for, as explained in the last chapter, it is incredible that
+individuals identically the same should ever have been produced through
+natural selection from parents specifically distinct.
+</para>
+
+<para>
+We are thus brought to the question which has been largely discussed by
+naturalists, namely, whether species have been created at one or more
+points of the earth's surface.  Undoubtedly there are very many cases of
+extreme difficulty, in understanding how the same species could possibly
+have migrated from some one point to the several distant and isolated
+points, where now found.  Nevertheless the simplicity of the view that each
+species was first produced within a single region captivates the mind.  He
+who rejects it, rejects the vera causa of ordinary generation with
+subsequent migration, and calls in the agency of a miracle.  It is
+universally admitted, that in most cases the area inhabited by a species is
+continuous; and when a plant or animal inhabits two points so distant from
+each other, or with an interval of such a nature, that the space could not
+be easily passed over by migration, the fact is given as something
+remarkable and exceptional.  The capacity of migrating across the sea is
+more distinctly limited in terrestrial mammals, than perhaps in any other
+organic beings; and, accordingly, we find no inexplicable cases of the same
+mammal inhabiting distant points of the world.  No geologist will feel any
+difficulty in such cases as Great Britain having been formerly united to
+Europe, and consequently possessing the same quadrupeds.  But if the same
+species can be produced at two separate points, why do we not find a single
+mammal common to Europe and Australia or South America?  The conditions of
+life are nearly the same, so that a multitude of European animals and
+plants have become naturalised in America and Australia; and some of the
+aboriginal plants are identically the same at these distant points of the
+northern and southern hemispheres?  The answer, as I believe, is, that
+mammals have not been able to migrate, whereas some plants, from their
+varied means of dispersal, have migrated across the vast and broken
+interspace.  The great and striking influence which barriers of every kind
+have had on distribution, is intelligible only on the view that the great
+majority of species have been produced on one side alone, and have not been
+able to migrate to the other side.  Some few families, many sub-families,
+very many genera, and a still greater number of sections of genera are
+confined to a single region; and it has been observed by several
+naturalists, that the most natural genera, or those genera in which the
+species are most closely related to each other, are generally local, or
+confined to one area.  What a strange anomaly it would be, if, when coming
+one step lower in the series, to the individuals of the same species, a
+directly opposite rule prevailed; and species were not local, but had been
+produced in two or more distinct areas!
+</para>
+
+<para>
+Hence it seems to me, as it has to many other naturalists, that the view of
+each species having been produced in one area alone, and having
+subsequently migrated from that area as far as its powers of migration and
+subsistence under past and present conditions permitted, is the most
+probable.  Undoubtedly many cases occur, in which we cannot explain how the
+same species could have passed from one point to the other.  But the
+geographical and climatal changes, which have certainly occurred within
+recent geological times, must have interrupted or rendered discontinuous
+the formerly continuous range of many species.  So that we are reduced to
+consider whether the exceptions to continuity of range are so numerous and
+of so grave a nature, that we ought to give up the belief, rendered
+probable by general considerations, that each species has been produced
+within one area, and has migrated thence as far as it could.  It would be
+hopelessly tedious to discuss all the exceptional cases of the same
+species, now living at distant and separated points; nor do I for a moment
+pretend that any explanation could be offered of many such cases.  But
+after some preliminary remarks, I will discuss a few of the most striking
+classes of facts; namely, the existence of the same species on the summits
+of distant mountain-ranges, and at distant points in the arctic and
+antarctic regions; and secondly (in the following chapter), the wide
+distribution of freshwater productions; and thirdly, the occurrence of the
+same terrestrial species on islands and on the mainland, though separated
+by hundreds of miles of open sea.  If the existence of the same species at
+distant and isolated points of the earth's surface, can in many instances
+be explained on the view of each species having migrated from a single
+birthplace; then, considering our ignorance with respect to former climatal
+and geographical changes and various occasional means of transport, the
+belief that this has been the universal law, seems to me incomparably the
+safest.
+</para>
+
+<para>
+In discussing this subject, we shall be enabled at the same time to
+consider a point equally important for us, namely, whether the several
+distinct species of a genus, which on my theory have all descended from a
+common progenitor, can have migrated (undergoing modification during some
+part of their migration) from the area inhabited by their progenitor.  If
+it can be shown to be almost invariably the case, that a region, of which
+most of its inhabitants are closely related to, or belong to the same
+genera with the species of a second region, has probably received at some
+former period immigrants from this other region, my theory will be
+strengthened; for we can clearly understand, on the principle of
+modification, why the inhabitants of a region should be related to those of
+another region, whence it has been stocked.  A volcanic island, for
+instance, upheaved and formed at the distance of a few hundreds of miles
+from a continent, would probably receive from it in the course of time a
+few colonists, and their descendants, though modified, would still be
+plainly related by inheritance to the inhabitants of the continent.  Cases
+of this nature are common, and are, as we shall hereafter more fully see,
+inexplicable on the theory of independent creation.  This view of the
+relation of species in one region to those in another, does not differ much
+(by substituting the word variety for species) from that lately advanced in
+an ingenious paper by Mr. Wallace, in which he concludes, that 'every
+species has come into existence coincident both in space and time with a
+pre-existing closely allied species.'  And I now know from correspondence,
+that this coincidence he attributes to generation with modification.
+</para>
+
+<para>
+The previous remarks on 'single and multiple centres of creation' do not
+directly bear on another allied question,--namely whether all the
+individuals of the same species have descended from a single pair, or
+single hermaphrodite, or whether, as some authors suppose, from many
+individuals simultaneously created.  With those organic beings which never
+intercross (if such exist), the species, on my theory, must have descended
+from a succession of improved varieties, which will never have blended with
+other individuals or varieties, but will have supplanted each other; so
+that, at each successive stage of modification and improvement, all the
+individuals of each variety will have descended from a single parent.  But
+in the majority of cases, namely, with all organisms which habitually unite
+for each birth, or which often intercross, I believe that during the slow
+process of modification the individuals of the species will have been kept
+nearly uniform by intercrossing; so that many individuals will have gone on
+simultaneously changing, and the whole amount of modification will not have
+been due, at each stage, to descent from a single parent.  To illustrate
+what I mean:  our English racehorses differ slightly from the horses of
+every other breed; but they do not owe their difference and superiority to
+descent from any single pair, but to continued care in selecting and
+training many individuals during many generations.
+</para>
+
+<para>
+Before discussing the three classes of facts, which I have selected as
+presenting the greatest amount of difficulty on the theory of 'single
+centres of creation,' I must say a few words on the means of dispersal.
+</para>
+
+<para>
+Means of Dispersal. -- Sir C. Lyell and other authors have ably treated
+this subject.  I can give here only the briefest abstract of the more
+important facts.  Change of climate must have had a powerful influence on
+migration:  a region when its climate was different may have been a high
+road for migration, but now be impassable; I shall, however, presently have
+to discuss this branch of the subject in some detail.  Changes of level in
+the land must also have been highly influential:  a narrow isthmus now
+separates two marine faunas; submerge it, or let it formerly have been
+submerged, and the two faunas will now blend or may formerly have blended: 
+where the sea now extends, land may at a former period have connected
+islands or possibly even continents together, and thus have allowed
+terrestrial productions to pass from one to the other.  No geologist will
+dispute that great mutations of level have occurred within the period of
+existing organisms.  Edward Forbes insisted that all the islands in the
+Atlantic must recently have been connected with Europe or Africa, and
+Europe likewise with America.  Other authors have thus hypothetically
+bridged over every ocean, and have united almost every island to some
+mainland.  If indeed the arguments used by Forbes are to be trusted, it
+must be admitted that scarcely a single island exists which has not
+recently been united to some continent.  This view cuts the Gordian knot of
+the dispersal of the same species to the most distant points, and removes
+many a difficulty:  but to the best of any judgment we are not authorized
+in admitting such enormous geographical changes within the period of
+existing species.  It seems to me that we have abundant evidence of great
+oscillations of level in our continents; but not of such vast changes in
+their position and extension, as to have united them within the recent
+period to each other and to the several intervening oceanic islands.  I
+freely admit the former existence of many islands, now buried beneath the
+sea, which may have served as halting places for plants and for many
+animals during their migration.  In the coral-producing oceans such sunken
+islands are now marked, as I believe, by rings of coral or atolls standing
+over them.  Whenever it is fully admitted, as I believe it will some day
+be, that each species has proceeded from a single birthplace, and when in
+the course of time we know something definite about the means of
+distribution, we shall be enabled to speculate with security on the former
+extension of the land.  But I do not believe that it will ever be proved
+that within the recent period continents which are now quite separate, have
+been continuously, or almost continuously, united with each other, and with
+the many existing oceanic islands.  Several facts in distribution,--such as
+the great difference in the marine faunas on the opposite sides of almost
+every continent,--the close relation of the tertiary inhabitants of several
+lands and even seas to their present inhabitants,--a certain degree of
+relation (as we shall hereafter see) between the distribution of mammals
+and the depth of the sea,--these and other such facts seem to me opposed to
+the admission of such prodigious geographical revolutions within the recent
+period, as are necessitated on the view advanced by Forbes and admitted by
+his many followers.  The nature and relative proportions of the inhabitants
+of oceanic islands likewise seem to me opposed to the belief of their
+former continuity with continents.  Nor does their almost universally
+volcanic composition favour the admission that they are the wrecks of
+sunken continents;--if they had originally existed as mountain-ranges on
+the land, some at least of the islands would have been formed, like other
+mountain-summits, of granite, metamorphic schists, old fossiliferous or
+other such rocks, instead of consisting of mere piles of volcanic matter.
+</para>
+
+<para>
+I must now say a few words on what are called accidental means, but which
+more properly might be called occasional means of distribution.  I shall
+here confine myself to plants.  In botanical works, this or that plant is
+stated to be ill adapted for wide dissemination; but for transport across
+the sea, the greater or less facilities may be said to be almost wholly
+unknown.  Until I tried, with Mr. Berkeley's aid, a few experiments, it was
+not even known how far seeds could resist the injurious action of
+sea-water.  To my surprise I found that out of 87 kinds, 64 germinated
+after an immersion of 28 days, and a few survived an immersion of 137 days. 
+For convenience sake I chiefly tried small seeds, without the capsule or
+fruit; and as all of these sank in a few days, they could not be floated
+across wide spaces of the sea, whether or not they were injured by the
+salt-water.  Afterwards I tried some larger fruits, capsules, &amp;c., and some
+of these floated for a long time.  It is well known what a difference there
+is in the buoyancy of green and seasoned timber; and it occurred to me that
+floods might wash down plants or branches, and that these might be dried on
+the banks, and then by a fresh rise in the stream be washed into the sea. 
+Hence I was led to dry stems and branches of 94 plants with ripe fruit, and
+to place them on sea water.  The majority sank quickly, but some which
+whilst green floated for a very short time, when dried floated much longer;
+for instance, ripe hazel-nuts sank immediately, but when dried, they
+floated for 90 days and afterwards when planted they germinated; an
+asparagus plant with ripe berries floated for 23 days, when dried it
+floated for 85 days, and the seeds afterwards germinated:  the ripe seeds
+of Helosciadium sank in two days, when dried they floated for above 90
+days, and afterwards germinated.  Altogether out of the 94 dried plants, 18
+floated for above 28 days, and some of the 18 floated for a very much
+longer period.  So that as 64/87 seeds germinated after an immersion of 28
+days; and as 18/94 plants with ripe fruit (but not all the same species as
+in the foregoing experiment) floated, after being dried, for above 28 days,
+as far as we may infer anything from these scanty facts, we may conclude
+that the seeds of 14/100 plants of any country might be floated by
+sea-currents during 28 days, and would retain their power of germination. 
+In Johnston's Physical Atlas, the average rate of the several Atlantic
+currents is 33 miles per diem (some currents running at the rate of 60
+miles per diem); on this average, the seeds of 14/100 plants belonging to
+one country might be floated across 924 miles of sea to another country;
+and when stranded, if blown to a favourable spot by an inland gale, they
+would germinate.
+</para>
+
+<para>
+Subsequently to my experiments, M. Martens tried similar ones, but in a
+much better manner, for he placed the seeds in a box in the actual sea, so
+that they were alternately wet and exposed to the air like really floating
+plants.  He tried 98 seeds, mostly different from mine; but he chose many
+large fruits and likewise seeds from plants which live near the sea; and
+this would have favoured the average length of their flotation and of their
+resistance to the injurious action of the salt-water.  On the other hand he
+did not previously dry the plants or branches with the fruit; and this, as
+we have seen, would have caused some of them to have floated much longer. 
+The result was that 18/98 of his seeds floated for 42 days, and were then
+capable of germination.  But I do not doubt that plants exposed to the
+waves would float for a less time than those protected from violent
+movement as in our experiments.  Therefore it would perhaps be safer to
+assume that the seeds of about 10/100 plants of a flora, after having been
+dried, could be floated across a space of sea 900 miles in width, and would
+then germinate.  The fact of the larger fruits often floating longer than
+the small, is interesting; as plants with large seeds or fruit could hardly
+be transported by any other means; and Alph. de Candolle has shown that
+such plants generally have restricted ranges.
+</para>
+
+<para>
+But seeds may be occasionally transported in another manner.  Drift timber
+is thrown up on most islands, even on those in the midst of the widest
+oceans; and the natives of the coral-islands in the Pacific, procure stones
+for their tools, solely from the roots of drifted trees, these stones being
+a valuable royal tax.  I find on examination, that when irregularly shaped
+stones are embedded in the roots of trees, small parcels of earth are very
+frequently enclosed in their interstices and behind them,--so perfectly
+that not a particle could be washed away in the longest transport:  out of
+one small portion of earth thus completely enclosed by wood in an oak about
+50 years old, three dicotyledonous plants germinated:  I am certain of the
+accuracy of this observation.  Again, I can show that the carcasses of
+birds, when floating on the sea, sometimes escape being immediately
+devoured; and seeds of many kinds in the crops of floating birds long
+retain their vitality:  peas and vetches, for instance, are killed by even
+a few days' immersion in sea-water; but some taken out of the crop of a
+pigeon, which had floated on artificial salt-water for 30 days, to my
+surprise nearly all germinated.
+</para>
+
+<para>
+Living birds can hardly fail to be highly effective agents in the
+transportation of seeds.  I could give many facts showing how frequently
+birds of many kinds are blown by gales to vast distances across the ocean. 
+We may I think safely assume that under such circumstances their rate of
+flight would often be 35 miles an hour; and some authors have given a far
+higher estimate.  I have never seen an instance of nutritious seeds passing
+through the intestines of a bird; but hard seeds of fruit will pass
+uninjured through even the digestive organs of a turkey.  In the course of
+two months, I picked up in my garden 12 kinds of seeds, out of the
+excrement of small birds, and these seemed perfect, and some of them, which
+I tried, germinated.  But the following fact is more important:  the crops
+of birds do not secrete gastric juice, and do not in the least injure, as I
+know by trial, the germination of seeds; now after a bird has found and
+devoured a large supply of food, it is positively asserted that all the
+grains do not pass into the gizzard for 12 or even 18 hours.  A bird in
+this interval might easily be blown to the distance of 500 miles, and hawks
+are known to look out for tired birds, and the contents of their torn crops
+might thus readily get scattered.  Mr. Brent informs me that a friend of
+his had to give up flying carrier-pigeons from France to England, as the
+hawks on the English coast destroyed so many on their arrival.  Some hawks
+and owls bolt their prey whole, and after an interval of from twelve to
+twenty hours, disgorge pellets, which, as I know from experiments made in
+the Zoological Gardens, include seeds capable of germination.  Some seeds
+of the oat, wheat, millet, canary, hemp, clover, and beet germinated after
+having been from twelve to twenty-one hours in the stomachs of different
+birds of prey; and two seeds of beet grew after having been thus retained
+for two days and fourteen hours.  Freshwater fish, I find, eat seeds of
+many land and water plants:  fish are frequently devoured by birds, and
+thus the seeds might be transported from place to place.  I forced many
+kinds of seeds into the stomachs of dead fish, and then gave their bodies
+to fishing-eagles, storks, and pelicans; these birds after an interval of
+many hours, either rejected the seeds in pellets or passed them in their
+excrement; and several of these seeds retained their power of germination. 
+Certain seeds, however, were always killed by this process.
+</para>
+
+<para>
+Although the beaks and feet of birds are generally quite clean, I can show
+that earth sometimes adheres to them:  in one instance I removed twenty-two
+grains of dry argillaceous earth from one foot of a partridge, and in this
+earth there was a pebble quite as large as the seed of a vetch.  Thus seeds
+might occasionally be transported to great distances; for many facts could
+be given showing that soil almost everywhere is charged with seeds. 
+Reflect for a moment on the millions of quails which annually cross the
+Mediterranean; and can we doubt that the earth adhering to their feet would
+sometimes include a few minute seeds?  But I shall presently have to recur
+to this subject.
+</para>
+
+<para>
+As icebergs are known to be sometimes loaded with earth and stones, and
+have even carried brushwood, bones, and the nest of a land-bird, I can
+hardly doubt that they must occasionally have transported seeds from one
+part to another of the arctic and antarctic regions, as suggested by Lyell;
+and during the Glacial period from one part of the now temperate regions to
+another.  In the Azores, from the large number of the species of plants
+common to Europe, in comparison with the plants of other oceanic islands
+nearer to the mainland, and (as remarked by Mr. H. C. Watson) from the
+somewhat northern character of the flora in comparison with the latitude, I
+suspected that these islands had been partly stocked by ice-borne seeds,
+during the Glacial epoch.  At my request Sir C. Lyell wrote to M. Hartung
+to inquire whether he had observed erratic boulders on these islands, and
+he answered that he had found large fragments of granite and other rocks,
+which do not occur in the archipelago.  Hence we may safely infer that
+icebergs formerly landed their rocky burthens on the shores of these
+mid-ocean islands, and it is at least possible that they may have brought
+thither the seeds of northern plants.
+</para>
+
+<para>
+Considering that the several above means of transport, and that several
+other means, which without doubt remain to be discovered, have been in
+action year after year, for centuries and tens of thousands of years, it
+would I think be a marvellous fact if many plants had not thus become
+widely transported.  These means of transport are sometimes called
+accidental, but this is not strictly correct:  the currents of the sea are
+not accidental, nor is the direction of prevalent gales of wind.  It should
+be observed that scarcely any means of transport would carry seeds for very
+great distances; for seeds do not retain their vitality when exposed for a
+great length of time to the action of seawater; nor could they be long
+carried in the crops or intestines of birds.  These means, however, would
+suffice for occasional transport across tracts of sea some hundred miles in
+breadth, or from island to island, or from a continent to a neighbouring
+island, but not from one distant continent to another.  The floras of
+distant continents would not by such means become mingled in any great
+degree; but would remain as distinct as we now see them to be.  The
+currents, from their course, would never bring seeds from North America to
+Britain, though they might and do bring seeds from the West Indies to our
+western shores, where, if not killed by so long an immersion in salt-water,
+they could not endure our climate.  Almost every year, one or two
+land-birds are blown across the whole Atlantic Ocean, from North America to
+the western shores of Ireland and England; but seeds could be transported
+by these wanderers only by one means, namely, in dirt sticking to their
+feet, which is in itself a rare accident.  Even in this case, how small
+would the chance be of a seed falling on favourable soil, and coming to
+maturity!  But it would be a great error to argue that because a
+well-stocked island, like Great Britain, has not, as far as is known (and
+it would be very difficult to prove this), received within the last few
+centuries, through occasional means of transport, immigrants from Europe or
+any other continent, that a poorly-stocked island, though standing more
+remote from the mainland, would not receive colonists by similar means.  I
+do not doubt that out of twenty seeds or animals transported to an island,
+even if far less well-stocked than Britain, scarcely more than one would be
+so well fitted to its new home, as to become naturalised.  But this, as it
+seems to me, is no valid argument against what would be effected by
+occasional means of transport, during the long lapse of geological time,
+whilst an island was being upheaved and formed, and before it had become
+fully stocked with inhabitants.  On almost bare land, with few or no
+destructive insects or birds living there, nearly every seed, which chanced
+to arrive, would be sure to germinate and survive.
+</para>
+
+<para>
+Dispersal during the Glacial period. -- The identity of many plants and
+animals, on mountain-summits, separated from each other by hundreds of
+miles of lowlands, where the Alpine species could not possibly exist, is
+one of the most striking cases known of the same species living at distant
+points, without the apparent possibility of their having migrated from one
+to the other.  It is indeed a remarkable fact to see so many of the same
+plants living on the snowy regions of the Alps or Pyrenees, and in the
+extreme northern parts of Europe; but it is far more remarkable, that the
+plants on the White Mountains, in the United States of America, are all the
+same with those of Labrador, and nearly all the same, as we hear from Asa
+Gray, with those on the loftiest mountains of Europe.  Even as long ago as
+1747, such facts led Gmelin to conclude that the same species must have
+been independently created at several distinct points; and we might have
+remained in this same belief, had not Agassiz and others called vivid
+attention to the Glacial period, which, as we shall immediately see,
+affords a simple explanation of these facts.  We have evidence of almost
+every conceivable kind, organic and inorganic, that within a very recent
+geological period, central Europe and North America suffered under an
+Arctic climate.  The ruins of a house burnt by fire do not tell their tale
+more plainly, than do the mountains of Scotland and Wales, with their
+scored flanks, polished surfaces, and perched boulders, of the icy streams
+with which their valleys were lately filled.  So greatly has the climate of
+Europe changed, that in Northern Italy, gigantic moraines, left by old
+glaciers, are now clothed by the vine and maize.  Throughout a large part
+of the United States, erratic boulders, and rocks scored by drifted
+icebergs and coast-ice, plainly reveal a former cold period.
+</para>
+
+<para>
+The former influence of the glacial climate on the distribution of the
+inhabitants of Europe, as explained with remarkable clearness by Edward
+Forbes, is substantially as follows.  But we shall follow the changes more
+readily, by supposing a new glacial period to come slowly on, and then pass
+away, as formerly occurred.  As the cold came on, and as each more southern
+zone became fitted for arctic beings and ill-fitted for their former more
+temperate inhabitants, the latter would be supplanted and arctic
+productions would take their places.  The inhabitants of the more temperate
+regions would at the same time travel southward, unless they were stopped
+by barriers, in which case they would perish.  The mountains would become
+covered with snow and ice, and their former Alpine inhabitants would
+descend to the plains.  By the time that the cold had reached its maximum,
+we should have a uniform arctic fauna and flora, covering the central parts
+of Europe, as far south as the Alps and Pyrenees, and even stretching into
+Spain.  The now temperate regions of the United States would likewise be
+covered by arctic plants and animals, and these would be nearly the same
+with those of Europe; for the present circumpolar inhabitants, which we
+suppose to have everywhere travelled southward, are remarkably uniform
+round the world.  We may suppose that the Glacial period came on a little
+earlier or later in North America than in Europe, so will the southern
+migration there have been a little earlier or later; but this will make no
+difference in the final result.
+</para>
+
+<para>
+As the warmth returned, the arctic forms would retreat northward, closely
+followed up in their retreat by the productions of the more temperate
+regions.  And as the snow melted from the bases of the mountains, the
+arctic forms would seize on the cleared and thawed ground, always ascending
+higher and higher, as the warmth increased, whilst their brethren were
+pursuing their northern journey.  Hence, when the warmth had fully
+returned, the same arctic species, which had lately lived in a body
+together on the lowlands of the Old and New Worlds, would be left isolated
+on distant mountain-summits (having been exterminated on all lesser
+heights) and in the arctic regions of both hemispheres.
+</para>
+
+<para>
+Thus we can understand the identity of many plants at points so immensely
+remote as on the mountains of the United States and of Europe.  We can thus
+also understand the fact that the Alpine plants of each mountain-range are
+more especially related to the arctic forms living due north or nearly due
+north of them:  for the migration as the cold came on, and the re-migration
+on the returning warmth, will generally have been due south and north.  The
+Alpine plants, for example, of Scotland, as remarked by Mr. H. C. Watson,
+and those of the Pyrenees, as remarked by Ramond, are more especially
+allied to the plants of northern Scandinavia; those of the United States to
+Labrador; those of the mountains of Siberia to the arctic regions of that
+country.  These views, grounded as they are on the perfectly
+well-ascertained occurrence of a former Glacial period, seem to me to
+explain in so satisfactory a manner the present distribution of the Alpine
+and Arctic productions of Europe and America, that when in other regions we
+find the same species on distant mountain-summits, we may almost conclude
+without other evidence, that a colder climate permitted their former
+migration across the low intervening tracts, since become too warm for
+their existence.
+</para>
+
+<para>
+If the climate, since the Glacial period, has ever been in any degree
+warmer than at present (as some geologists in the United States believe to
+have been the case, chiefly from the distribution of the fossil Gnathodon),
+then the arctic and temperate productions will at a very late period have
+marched a little further north, and subsequently have retreated to their
+present homes; but I have met with no satisfactory evidence with respect to
+this intercalated slightly warmer period, since the Glacial period.
+</para>
+
+<para>
+The arctic forms, during their long southern migration and re-migration
+northward, will have been exposed to nearly the same climate, and, as is
+especially to be noticed, they will have kept in a body together;
+consequently their mutual relations will not have been much disturbed, and,
+in accordance with the principles inculcated in this volume, they will not
+have been liable to much modification.  But with our Alpine productions,
+left isolated from the moment of the returning warmth, first at the bases
+and ultimately on the summits of the mountains, the case will have been
+somewhat different; for it is not likely that all the same arctic species
+will have been left on mountain ranges distant from each other, and have
+survived there ever since; they will, also, in all probability have become
+mingled with ancient Alpine species, which must have existed on the
+mountains before the commencement of the Glacial epoch, and which during
+its coldest period will have been temporarily driven down to the plains;
+they will, also, have been exposed to somewhat different climatal
+influences.  Their mutual relations will thus have been in some degree
+disturbed; consequently they will have been liable to modification; and
+this we find has been the case; for if we compare the present Alpine plants
+and animals of the several great European mountain-ranges, though very many
+of the species are identically the same, some present varieties, some are
+ranked as doubtful forms, and some few are distinct yet closely allied or
+representative species.
+</para>
+
+<para>
+In illustrating what, as I believe, actually took place during the Glacial
+period, I assumed that at its commencement the arctic productions were as
+uniform round the polar regions as they are at the present day.  But the
+foregoing remarks on distribution apply not only to strictly arctic forms,
+but also to many sub-arctic and to some few northern temperate forms, for
+some of these are the same on the lower mountains and on the plains of
+North America and Europe; and it may be reasonably asked how I account for
+the necessary degree of uniformity of the sub-arctic and northern temperate
+forms round the world, at the commencement of the Glacial period.  At the
+present day, the sub-arctic and northern temperate productions of the Old
+and New Worlds are separated from each other by the Atlantic Ocean and by
+the extreme northern part of the Pacific.  During the Glacial period, when
+the inhabitants of the Old and New Worlds lived further southwards than at
+present, they must have been still more completely separated by wider
+spaces of ocean.  I believe the above difficulty may be surmounted by
+looking to still earlier changes of climate of an opposite nature.  We have
+good reason to believe that during the newer Pliocene period, before the
+Glacial epoch, and whilst the majority of the inhabitants of the world were
+specifically the same as now, the climate was warmer than at the present
+day.  Hence we may suppose that the organisms now living under the climate
+of latitude 60 deg, during the Pliocene period lived further north under
+the Polar Circle, in latitude 66 deg-67 deg; and that the strictly arctic
+productions then lived on the broken land still nearer to the pole.  Now if
+we look at a globe, we shall see that under the Polar Circle there is
+almost continuous land from western Europe, through Siberia, to eastern
+America.  And to this continuity of the circumpolar land, and to the
+consequent freedom for intermigration under a more favourable climate, I
+attribute the necessary amount of uniformity in the sub-arctic and northern
+temperate productions of the Old and New Worlds, at a period anterior to
+the Glacial epoch.
+</para>
+
+<para>
+Believing, from reasons before alluded to, that our continents have long
+remained in nearly the same relative position, though subjected to large,
+but partial oscillations of level, I am strongly inclined to extend the
+above view, and to infer that during some earlier and still warmer period,
+such as the older Pliocene period, a large number of the same plants and
+animals inhabited the almost continuous circumpolar land; and that these
+plants and animals, both in the Old and New Worlds, began slowly to migrate
+southwards as the climate became less warm, long before the commencement of
+the Glacial period.  We now see, as I believe, their descendants, mostly in
+a modified condition, in the central parts of Europe and the United States. 
+On this view we can understand the relationship, with very little identity,
+between the productions of North America and Europe,--a relationship which
+is most remarkable, considering the distance of the two areas, and their
+separation by the Atlantic Ocean.  We can further understand the singular
+fact remarked on by several observers, that the productions of Europe and
+America during the later tertiary stages were more closely related to each
+other than they are at the present time; for during these warmer periods
+the northern parts of the Old and New Worlds will have been almost
+continuously united by land, serving as a bridge, since rendered impassable
+by cold, for the inter-migration of their inhabitants.
+</para>
+
+<para>
+During the slowly decreasing warmth of the Pliocene period, as soon as the
+species in common, which inhabited the New and Old Worlds, migrated south
+of the Polar Circle, they must have been completely cut off from each
+other.  This separation, as far as the more temperate productions are
+concerned, took place long ages ago.  And as the plants and animals
+migrated southward, they will have become mingled in the one great region
+with the native American productions, and have had to compete with them;
+and in the other great region, with those of the Old World.  Consequently
+we have here everything favourable for much modification,--for far more
+modification than with the Alpine productions, left isolated, within a much
+more recent period, on the several mountain-ranges and on the arctic lands
+of the two Worlds.  Hence it has come, that when we compare the now living
+productions of the temperate regions of the New and Old Worlds, we find
+very few identical species (though Asa Gray has lately shown that more
+plants are identical than was formerly supposed), but we find in every
+great class many forms, which some naturalists rank as geographical races,
+and others as distinct species; and a host of closely allied or
+representative forms which are ranked by all naturalists as specifically
+distinct.
+</para>
+
+<para>
+As on the land, so in the waters of the sea, a slow southern migration of a
+marine fauna, which during the Pliocene or even a somewhat earlier period,
+was nearly uniform along the continuous shores of the Polar Circle, will
+account, on the theory of modification, for many closely allied forms now
+living in areas completely sundered.  Thus, I think, we can understand the
+presence of many existing and tertiary representative forms on the eastern
+and western shores of temperate North America; and the still more striking
+case of many closely allied crustaceans (as described in Dana's admirable
+work), of some fish and other marine animals, in the Mediterranean and in
+the seas of Japan,--areas now separated by a continent and by nearly a
+hemisphere of equatorial ocean.
+</para>
+
+<para>
+These cases of relationship, without identity, of the inhabitants of seas
+now disjoined, and likewise of the past and present inhabitants of the
+temperate lands of North America and Europe, are inexplicable on the theory
+of creation.  We cannot say that they have been created alike, in
+correspondence with the nearly similar physical conditions of the areas;
+for if we compare, for instance, certain parts of South America with the
+southern continents of the Old World, we see countries closely
+corresponding in all their physical conditions, but with their inhabitants
+utterly dissimilar.
+</para>
+
+<para>
+But we must return to our more immediate subject, the Glacial period.  I am
+convinced that Forbes's view may be largely extended.  In Europe we have
+the plainest evidence of the cold period, from the western shores of
+Britain to the Oural range, and southward to the Pyrenees.  We may infer,
+from the frozen mammals and nature of the mountain vegetation, that Siberia
+was similarly affected.  Along the Himalaya, at points 900 miles apart,
+glaciers have left the marks of their former low descent; and in Sikkim,
+Dr. Hooker saw maize growing on gigantic ancient moraines.  South of the
+equator, we have some direct evidence of former glacial action in New
+Zealand; and the same plants, found on widely separated mountains in this
+island, tell the same story.  If one account which has been published can
+be trusted, we have direct evidence of glacial action in the south-eastern
+corner of Australia.
+</para>
+
+<para>
+Looking to America; in the northern half, ice-borne fragments of rock have
+been observed on the eastern side as far south as lat. 36 deg-37 deg, and
+on the shores of the Pacific, where the climate is now so different, as far
+south as lat. 46 deg; erratic boulders have, also, been noticed on the
+Rocky Mountains.  In the Cordillera of Equatorial South America, glaciers
+once extended far below their present level.  In central Chile I was
+astonished at the structure of a vast mound of detritus, about 800 feet in
+height, crossing a valley of the Andes; and this I now feel convinced was a
+gigantic moraine, left far below any existing glacier.  Further south on
+both sides of the continent, from lat. 41 deg to the southernmost
+extremity, we have the clearest evidence of former glacial action, in huge
+boulders transported far from their parent source.
+</para>
+
+<para>
+We do not know that the Glacial epoch was strictly simultaneous at these
+several far distant points on opposite sides of the world.  But we have
+good evidence in almost every case, that the epoch was included within the
+latest geological period.  We have, also, excellent evidence, that it
+endured for an enormous time, as measured by years, at each point.  The
+cold may have come on, or have ceased, earlier at one point of the globe
+than at another, but seeing that it endured for long at each, and that it
+was contemporaneous in a geological sense, it seems to me probable that it
+was, during a part at least of the period, actually simultaneous throughout
+the world.  Without some distinct evidence to the contrary, we may at least
+admit as probable that the glacial action was simultaneous on the eastern
+and western sides of North America, in the Cordillera under the equator and
+under the warmer temperate zones, and on both sides of the southern
+extremity of the continent.  If this be admitted, it is difficult to avoid
+believing that the temperature of the whole world was at this period
+simultaneously cooler.  But it would suffice for my purpose, if the
+temperature was at the same time lower along certain broad belts of
+longitude.
+</para>
+
+<para>
+On this view of the whole world, or at least of broad longitudinal belts,
+having been simultaneously colder from pole to pole, much light can be
+thrown on the present distribution of identical and allied species.  In
+America, Dr. Hooker has shown that between forty and fifty of the flowering
+plants of Tierra del Fuego, forming no inconsiderable part of its scanty
+flora, are common to Europe, enormously remote as these two points are; and
+there are many closely allied species.  On the lofty mountains of
+equatorial America a host of peculiar species belonging to European genera
+occur.  On the highest mountains of Brazil, some few European genera were
+found by Gardner, which do not exist in the wide intervening hot countries. 
+So on the Silla of Caraccas the illustrious Humboldt long ago found species
+belonging to genera characteristic of the Cordillera.  On the mountains of
+Abyssinia, several European forms and some few representatives of the
+peculiar flora of the Cape of Good Hope occur.  At the Cape of Good Hope a
+very few European species, believed not to have been introduced by man, and
+on the mountains, some few representative European forms are found, which
+have not been discovered in the intertropical parts of Africa.  On the
+Himalaya, and on the isolated mountain-ranges of the peninsula of India, on
+the heights of Ceylon, and on the volcanic cones of Java, many plants
+occur, either identically the same or representing each other, and at the
+same time representing plants of Europe, not found in the intervening hot
+lowlands.  A list of the genera collected on the loftier peaks of Java
+raises a picture of a collection made on a hill in Europe!  Still more
+striking is the fact that southern Australian forms are clearly represented
+by plants growing on the summits of the mountains of Borneo.  Some of these
+Australian forms, as I hear from Dr. Hooker, extend along the heights of
+the peninsula of Malacca, and are thinly scattered, on the one hand over
+India and on the other as far north as Japan.
+</para>
+
+<para>
+On the southern mountains of Australia, Dr. F. Muller has discovered
+several European species; other species, not introduced by man, occur on
+the lowlands; and a long list can be given, as I am informed by Dr. Hooker,
+of European genera, found in Australia, but not in the intermediate torrid
+regions.  In the admirable 'Introduction to the Flora of New Zealand,' by
+Dr. Hooker, analogous and striking facts are given in regard to the plants
+of that large island.  Hence we see that throughout the world, the plants
+growing on the more lofty mountains, and on the temperate lowlands of the
+northern and southern hemispheres, are sometimes identically the same; but
+they are much oftener specifically distinct, though related to each other
+in a most remarkable manner.
+</para>
+
+<para>
+This brief abstract applies to plants alone:  some strictly analogous facts
+could be given on the distribution of terrestrial animals.  In marine
+productions, similar cases occur; as an example, I may quote a remark by
+the highest authority, Prof. Dana, that 'it is certainly a wonderful fact
+that New Zealand should have a closer resemblance in its crustacea to Great
+Britain, its antipode, than to any other part of the world.'  Sir J.
+Richardson, also, speaks of the reappearance on the shores of New Zealand,
+Tasmania, &amp;c., of northern forms of fish.  Dr. Hooker informs me that
+twenty-five species of Algae are common to New Zealand and to Europe, but
+have not been found in the intermediate tropical seas.
+</para>
+
+<para>
+It should be observed that the northern species and forms found in the
+southern parts of the southern hemisphere, and on the mountain-ranges of
+the intertropical regions, are not arctic, but belong to the northern
+temperate zones.  As Mr. H. C. Watson has recently remarked, 'In receding
+from polar towards equatorial latitudes, the Alpine or mountain floras
+really become less and less arctic.'  Many of the forms living on the
+mountains of the warmer regions of the earth and in the southern hemisphere
+are of doubtful value, being ranked by some naturalists as specifically
+distinct, by others as varieties; but some are certainly identical, and
+many, though closely related to northern forms, must be ranked as distinct
+species.
+</para>
+
+<para>
+Now let us see what light can be thrown on the foregoing facts, on the
+belief, supported as it is by a large body of geological evidence, that the
+whole world, or a large part of it, was during the Glacial period
+simultaneously much colder than at present.  The Glacial period, as
+measured by years, must have been very long; and when we remember over what
+vast spaces some naturalised plants and animals have spread within a few
+centuries, this period will have been ample for any amount of migration. 
+As the cold came slowly on, all the tropical plants and other productions
+will have retreated from both sides towards the equator, followed in the
+rear by the temperate productions, and these by the arctic; but with the
+latter we are not now concerned.  The tropical plants probably suffered
+much extinction; how much no one can say; perhaps formerly the tropics
+supported as many species as we see at the present day crowded together at
+the Cape of Good Hope, and in parts of temperate Australia.  As we know
+that many tropical plants and animals can withstand a considerable amount
+of cold, many might have escaped extermination during a moderate fall of
+temperature, more especially by escaping into the warmest spots.  But the
+great fact to bear in mind is, that all tropical productions will have
+suffered to a certain extent.  On the other hand, the temperate
+productions, after migrating nearer to the equator, though they will have
+been placed under somewhat new conditions, will have suffered less.  And it
+is certain that many temperate plants, if protected from the inroads of
+competitors, can withstand a much warmer climate than their own.  Hence, it
+seems to me possible, bearing in mind that the tropical productions were in
+a suffering state and could not have presented a firm front against
+intruders, that a certain number of the more vigorous and dominant
+temperate forms might have penetrated the native ranks and have reached or
+even crossed the equator.  The invasion would, of course, have been greatly
+favoured by high land, and perhaps by a dry climate; for Dr. Falconer
+informs me that it is the damp with the heat of the tropics which is so
+destructive to perennial plants from a temperate climate.  On the other
+hand, the most humid and hottest districts will have afforded an asylum to
+the tropical natives.  The mountain-ranges north-west of the Himalaya, and
+the long line of the Cordillera, seem to have afforded two great lines of
+invasion:  and it is a striking fact, lately communicated to me by Dr.
+Hooker, that all the flowering plants, about forty-six in number, common to
+Tierra del Fuego and to Europe still exist in North America, which must
+have lain on the line of march.  But I do not doubt that some temperate
+productions entered and crossed even the lowlands of the  tropics at the
+period when the cold was most intense,--when arctic forms had migrated some
+twenty-five degrees of latitude from their native country and covered the
+land at the foot of the Pyrenees.  At this period of extreme cold, I
+believe that the climate under the equator at the level of the sea was
+about the same with that now felt there at the height of six or seven
+thousand feet.  During this the coldest period, I suppose that large spaces
+of the tropical lowlands were clothed with a mingled tropical and temperate
+vegetation, like that now growing with strange luxuriance at the base of
+the Himalaya, as graphically described by Hooker.
+</para>
+
+<para>
+Thus, as I believe, a considerable number of plants, a few terrestrial
+animals, and some marine productions, migrated during the Glacial period
+from the northern and southern temperate zones into the intertropical
+regions, and some even crossed the equator.  As the warmth returned, these
+temperate forms would naturally ascend the higher mountains, being
+exterminated on the lowlands; those which had not reached the equator,
+would re-migrate northward or southward towards their former homes; but the
+forms, chiefly northern, which had crossed the equator, would travel still
+further from their homes into the more temperate latitudes of the opposite
+hemisphere.  Although we have reason to believe from geological evidence
+that the whole body of arctic shells underwent scarcely any modification
+during their long southern migration and re-migration northward, the case
+may have been wholly different with those intruding forms which settled
+themselves on the intertropical mountains, and in the southern hemisphere. 
+These being surrounded by strangers will have had to compete with many new
+forms of life; and it is probable that selected modifications in their
+structure, habits, and constitutions will have profited them.  Thus many of
+these wanderers, though still plainly related by inheritance to their
+brethren of the northern or southern hemispheres, now exist in their new
+homes as well-marked varieties or as distinct species.
+</para>
+
+<para>
+It is a remarkable fact, strongly insisted on by Hooker in regard to
+America, and by Alph. de Candolle in regard to Australia, that many more
+identical plants and allied forms have apparently migrated from the north
+to the south, than in a reversed direction.  We see, however, a few
+southern vegetable forms on the mountains of Borneo and Abyssinia.  I
+suspect that this preponderant migration from north to south is due to the
+greater extent of land in the north, and to the northern forms having
+existed in their own homes in greater numbers, and having consequently been
+advanced through natural selection and competition to a higher stage of
+perfection or dominating power, than the southern forms.  And thus, when
+they became commingled during the Glacial period, the northern forms were
+enabled to beat the less powerful southern forms.  Just in the same manner
+as we see at the present day, that very many European productions cover the
+ground in La Plata, and in a lesser degree in Australia, and have to a
+certain extent beaten the natives; whereas extremely few southern forms
+have become naturalised in any part of Europe, though hides, wool, and
+other objects likely to carry seeds have been largely imported into Europe
+during the last two or three centuries from La Plata, and during the last
+thirty or forty years from Australia.  Something of the same kind must have
+occurred on the intertropical mountains:  no doubt before the Glacial
+period they were stocked with endemic Alpine forms; but these have almost
+everywhere largely yielded to the more dominant forms, generated in the
+larger areas and more efficient workshops of the north.  In many islands
+the native productions are nearly equalled or even outnumbered by the
+naturalised; and if the natives have not been actually exterminated, their
+numbers have been greatly reduced, and this is the first stage towards
+extinction.  A mountain is an island on the land; and the intertropical
+mountains before the Glacial period must have been completely isolated; and
+I believe that the productions of these islands on the land yielded to
+those produced within the larger areas of the north, just in the same way
+as the productions of real islands have everywhere lately yielded to
+continental forms, naturalised by man's agency.
+</para>
+
+<para>
+I am far from supposing that all difficulties are removed on the view here
+given in regard to the range and affinities of the allied species which
+live in the northern and southern temperate zones and on the mountains of
+the intertropical regions.  Very many difficulties remain to be solved.  I
+do not pretend to indicate the exact lines and means of migration, or the
+reason why certain species and not others have migrated; why certain
+species have been modified and have given rise to new groups of forms, and
+others have remained unaltered.  We cannot hope to explain such facts,
+until we can say why one species and not another becomes naturalised by
+man's agency in a foreign land; why one ranges twice or thrice as far, and
+is twice or thrice as common, as another species within their own homes.
+</para>
+
+<para>
+I have said that many difficulties remain to be solved:  some of the most
+remarkable are stated with admirable clearness by Dr. Hooker in his
+botanical works on the antarctic regions.  These cannot be here discussed. 
+I will only say that as far as regards the occurrence of identical species
+at points so enormously remote as Kerguelen Land, New Zealand, and Fuegia,
+I believe that towards the close of the Glacial period, icebergs, as
+suggested by Lyell, have been largely concerned in their dispersal.  But
+the existence of several quite distinct species, belonging to genera
+exclusively confined to the south, at these and other distant points of the
+southern hemisphere, is, on my theory of descent with modification, a far
+more remarkable case of difficulty.  For some of these species are so
+distinct, that we cannot suppose that there has been time since the
+commencement of the Glacial period for their migration, and for their
+subsequent modification to the necessary degree.  The facts seem to me to
+indicate that peculiar and very distinct species have migrated in radiating
+lines from some common centre; and I am inclined to look in the southern,
+as in the northern hemisphere, to a former and warmer period, before the
+commencement of the Glacial period, when the antarctic lands, now covered
+with ice, supported a highly peculiar and isolated flora.  I suspect that
+before this flora was exterminated by the Glacial epoch, a few forms were
+widely dispersed to various points of the southern hemisphere by occasional
+means of transport, and by the aid, as halting-places, of existing and now
+sunken islands, and perhaps at the commencement of the Glacial period, by
+icebergs.  By these means, as I believe, the southern shores of America,
+Australia, New Zealand have become slightly tinted by the same peculiar
+forms of vegetable life.
+</para>
+
+<para>
+Sir C. Lyell in a striking passage has speculated, in language almost
+identical with mine, on the effects of great alternations of climate on
+geographical distribution.  I believe that the world has recently felt one
+of his great cycles of change; and that on this view, combined with
+modification through natural selection, a multitude of facts in the present
+distribution both of the same and of allied forms of life can be explained. 
+The living waters may be said to have flowed during one short period from
+the north and from the south, and to have crossed at the equator; but to
+have flowed with greater force from the north so as to have freely
+inundated the south.  As the tide leaves its drift in horizontal lines,
+though rising higher on the shores where the tide rises highest, so have
+the living waters left their living drift on our mountain-summits, in a
+line gently rising from the arctic lowlands to a great height under the
+equator.  The various beings thus left stranded may be compared with savage
+races of man, driven up and surviving in the mountain-fastnesses of almost
+every land, which serve as a record, full of interest to us, of the former
+inhabitants of the surrounding lowlands.
+</para>
+
+</chapter>
+
+<chapter>
+<chapheader>
+
+<chapnum>Chapter XII</chapnum>
+
+<title>Geographical Distribution--continued</title>
+
+<chapsummary>
+Distribution of fresh-water productions -- On the inhabitants of oceanic
+islands -- Absence of Batrachians and of terrestrial Mammals -- On the
+relation of the inhabitants of islands to those of the nearest mainland --
+On colonisation from the nearest source with subsequent modification --
+Summary of the last and present chapters.
+</chapsummary>
+</chapheader>
+
+<para>
+As lakes and river-systems are separated from each other by barriers of
+land, it might have been thought that fresh-water productions would not
+have ranged widely within the same country, and as the sea is apparently a
+still more impassable barrier, that they never would have extended to
+distant countries.  But the case is exactly the reverse.  Not only have
+many fresh-water species, belonging to quite different classes, an enormous
+range, but allied species prevail in a remarkable manner throughout the
+world.  I well remember, when first collecting in the fresh waters of
+Brazil, feeling much surprise at the similarity of the fresh-water insects,
+shells, &amp;c., and at the dissimilarity of the surrounding terrestrial
+beings, compared with those of Britain.
+</para>
+
+<para>
+But this power in fresh-water productions of ranging widely, though so
+unexpected, can, I think, in most cases be explained by their having become
+fitted, in a manner highly useful to them, for short and frequent
+migrations from pond to pond, or from stream to stream; and liability to
+wide dispersal would follow from this capacity as an almost necessary
+consequence.  We can here consider only a few cases.  In regard to fish, I
+believe that the same species never occur in the fresh waters of distant
+continents.  But on the same continent the species often range widely and
+almost capriciously; for two river-systems will have some fish in common
+and some different.  A few facts seem to favour the possibility of their
+occasional transport by accidental means; like that of the live fish not
+rarely dropped by whirlwinds in India, and the vitality of their ova when
+removed from the water.  But I am inclined to attribute the dispersal of
+fresh-water fish mainly to slight changes within the recent period in the
+level of the land, having caused rivers to flow into each other. 
+Instances, also, could be given of this having occurred during floods,
+without any change of level.  We have evidence in the loess of the Rhine of
+considerable changes of level in the land within a very recent geological
+period, and when the surface was peopled by existing land and fresh-water
+shells.  The wide difference of the fish on opposite sides of continuous
+mountain-ranges, which from an early period must have parted river-systems
+and completely prevented their inosculation, seems to lead to this same
+conclusion.  With respect to allied fresh-water fish occurring at very
+distant points of the world, no doubt there are many cases which cannot at
+present be explained:  but some fresh-water fish belong to very ancient
+forms, and in such cases there will have been ample time for great
+geographical changes, and consequently time and means for much migration. 
+In the second place, salt-water fish can with care be slowly accustomed to
+live in fresh water; and, according to Valenciennes, there is hardly a
+single group of fishes confined exclusively to fresh water, so that we may
+imagine that a marine member of a fresh-water group might travel far along
+the shores of the sea, and subsequently become modified and adapted to the
+fresh waters of a distant land.
+</para>
+
+<para>
+Some species of fresh-water shells have a very wide range, and allied
+species, which, on my theory, are descended from a common parent and must
+have proceeded from a single source, prevail throughout the world.  Their
+distribution at first perplexed me much, as their ova are not likely to be
+transported by birds, and they are immediately killed by sea water, as are
+the adults.  I could not even understand how some naturalised species have
+rapidly spread throughout the same country.  But two facts, which I have
+observed--and no doubt many others remain to be observed--throw some light
+on this subject.  When a duck suddenly emerges from a pond covered with
+duck-weed, I have twice seen these little plants adhering to its back; and
+it has happened to me, in removing a little duck-weed from one aquarium to
+another, that I have quite unintentionally stocked the one with fresh-water
+shells from the other.  But another agency is perhaps more effectual:  I
+suspended a duck's feet, which might represent those of a bird sleeping in
+a natural pond, in an aquarium, where many ova of fresh-water shells were
+hatching; and I found that numbers of the extremely minute and just hatched
+shells crawled on the feet, and clung to them so firmly that when taken out
+of the water they could not be jarred off, though at a somewhat more
+advanced age they would voluntarily drop off.  These just hatched molluscs,
+though aquatic in their nature, survived on the duck's feet, in damp air,
+from twelve to twenty hours; and in this length of time a duck or heron
+might fly at least six or seven hundred miles, and would be sure to alight
+on a pool or rivulet, if blown across sea to an oceanic island or to any
+other distant point.  Sir Charles Lyell also informs me that a Dyticus has
+been caught with an Ancylus (a fresh-water shell like a limpet) firmly
+adhering to it; and a water-beetle of the same family, a Colymbetes, once
+flew on board the 'Beagle,' when forty-five miles distant from the nearest
+land:  how much farther it might have flown with a favouring gale no one
+can tell.
+</para>
+
+<para>
+With respect to plants, it has long been known what enormous ranges many
+fresh-water and even marsh-species have, both over continents and to the
+most remote oceanic islands.  This is strikingly shown, as remarked by
+Alph. de Candolle, in large groups of terrestrial plants, which have only a
+very few aquatic members; for these latter seem immediately to acquire, as
+if in consequence, a very wide range.  I think favourable means of
+dispersal explain this fact.  I have before mentioned that earth
+occasionally, though rarely, adheres in some quantity to the feet and beaks
+of birds.  Wading birds, which frequent the muddy edges of ponds, if
+suddenly flushed, would be the most likely to have muddy feet.  Birds of
+this order I can show are the greatest wanderers, and are occasionally
+found on the most remote and barren islands in the open ocean; they would
+not be likely to alight on the surface of the sea, so that the dirt would
+not be washed off their feet; when making land, they would be sure to fly
+to their natural fresh-water haunts.  I do not believe that botanists are
+aware how charged the mud of ponds is with seeds:  I have tried several
+little experiments, but will here give only the most striking case:  I took
+in February three table-spoonfuls of mud from three different points,
+beneath water, on the edge of a little pond; this mud when dry weighed only
+6 3/4 ounces; I kept it covered up in my study for six months, pulling up
+and counting each plant as it grew; the plants were of many kinds, and were
+altogether 537 in number; and yet the viscid mud was all contained in a
+breakfast cup!  Considering these facts, I think it would be an
+inexplicable circumstance if water-birds did not transport the seeds of
+fresh-water plants to vast distances, and if consequently the range of
+these plants was not very great.  The same agency may have come into play
+with the eggs of some of the smaller fresh-water animals.
+</para>
+
+<para>
+Other and unknown agencies probably have also played a part.  I have stated
+that fresh-water fish eat some kinds of seeds, though they reject many
+other kinds after having swallowed them; even small fish swallow seeds of
+moderate size, as of the yellow water-lily and Potamogeton.  Herons and
+other birds, century after century, have gone on daily devouring fish; they
+then take flight and go to other waters, or are blown across the sea; and
+we have seen that seeds retain their power of germination, when rejected in
+pellets or in excrement, many hours afterwards.  When I saw the great size
+of the seeds of that fine water-lily, the Nelumbium, and remembered Alph.
+de Candolle's remarks on this plant, I thought that its distribution must
+remain quite inexplicable; but Audubon states that he found the seeds of
+the great southern water-lily (probably, according to Dr. Hooker, the
+Nelumbium luteum) in a heron's stomach; although I do not know the fact,
+yet analogy makes me believe that a heron flying to another pond and
+getting a hearty meal of fish, would probably reject from its stomach a
+pellet containing the seeds of the Nelumbium undigested; or the seeds might
+be dropped by the bird whilst feeding its young, in the same way as fish
+are known sometimes to be dropped.
+</para>
+
+<para>
+In considering these several means of distribution, it should be remembered
+that when a pond or stream is first formed, for instance, on a rising
+islet, it will be unoccupied; and a single seed or egg will have a good
+chance of succeeding.  Although there will always be a struggle for life
+between the individuals of the species, however few, already occupying any
+pond, yet as the number of kinds is small, compared with those on the land,
+the competition will probably be less severe between aquatic than between
+terrestrial species; consequently an intruder from the waters of a foreign
+country, would have a better chance of seizing on a place, than in the case
+of terrestrial colonists.  We should, also, remember that some, perhaps
+many, fresh-water productions are low in the scale of nature, and that we
+have reason to believe that such low beings change or become modified less
+quickly than the high; and this will give longer time than the average for
+the migration of the same aquatic species.  We should not forget the
+probability of many species having formerly ranged as continuously as
+fresh-water productions ever can range, over immense areas, and having
+subsequently become extinct in intermediate regions.  But the wide
+distribution of fresh-water plants and of the lower animals, whether
+retaining the same identical form or in some degree modified, I believe
+mainly depends on the wide dispersal of their seeds and eggs by animals,
+more especially by fresh-water birds, which have large powers of flight,
+and naturally travel from one to another and often distant piece of water. 
+Nature, like a careful gardener, thus takes her seeds from a bed of a
+particular nature, and drops them in another equally well fitted for them.
+</para>
+
+<para>
+On the Inhabitants of Oceanic Islands. -- We now come to the last of the
+three classes of facts, which I have selected as presenting the greatest
+amount of difficulty, on the view that all the individuals both of the same
+and of allied species have descended from a single parent; and therefore
+have all proceeded from a common birthplace, notwithstanding that in the
+course of time they have come to inhabit distant points of the globe.  I
+have already stated that I cannot honestly admit Forbes's view on
+continental extensions, which, if legitimately followed out, would lead to
+the belief that within the recent period all existing islands have been
+nearly or quite joined to some continent.  This view would remove many
+difficulties, but it would not, I think, explain all the facts in regard to
+insular productions.  In the following remarks I shall not confine myself
+to the mere question of dispersal; but shall consider some other facts,
+which bear on the truth of the two theories of independent creation and of
+descent with modification.
+</para>
+
+<para>
+The species of all kinds which inhabit oceanic islands are few in number
+compared with those on equal continental areas:  Alph. de Candolle admits
+this for plants, and Wollaston for insects.  If we look to the large size
+and varied stations of New Zealand, extending over 780 miles of latitude,
+and compare its flowering plants, only 750 in number, with those on an
+equal area at the Cape of Good Hope or in Australia, we must, I think,
+admit that something quite independently of any difference in physical
+conditions has caused so great a difference in number.  Even the uniform
+county of Cambridge has 847 plants, and the little island of Anglesea 764,
+but a few ferns and a few introduced plants are included in these numbers,
+and the comparison in some other respects is not quite fair.  We have
+evidence that the barren island of Ascension aboriginally possessed under
+half-a-dozen flowering plants; yet many have become naturalised on it, as
+they have on New Zealand and on every other oceanic island which can be
+named.  In St. Helena there is reason to believe that the naturalised
+plants and animals have nearly or quite exterminated many native
+productions.  He who admits the doctrine of the creation of each separate
+species, will have to admit, that a sufficient number of the best adapted
+plants and animals have not been created on oceanic islands; for man has
+unintentionally stocked them from various sources far more fully and
+perfectly than has nature.
+</para>
+
+<para>
+Although in oceanic islands the number of kinds of inhabitants is scanty,
+the proportion of endemic species (i.e. those found nowhere else in the
+world) is often extremely large.  If we compare, for instance, the number
+of the endemic land-shells in Madeira, or of the endemic birds in the
+Galapagos Archipelago, with the number found on any continent, and then
+compare the area of the islands with that of the continent, we shall see
+that this is true.  This fact might have been expected on my theory, for,
+as already explained, species occasionally arriving after long intervals in
+a new and isolated district, and having to compete with new associates,
+will be eminently liable to modification, and will often produce groups of
+modified descendants.  But it by no means follows, that, because in an
+island nearly all the species of one class are peculiar, those of another
+class, or of another section of the same class, are peculiar; and this
+difference seems to depend on the species which do not become modified
+having immigrated with facility and in a body, so that their mutual
+relations have not been much disturbed.  Thus in the Galapagos Islands
+nearly every land-bird, but only two out of the eleven marine birds, are
+peculiar; and it is obvious that marine birds could arrive at these islands
+more easily than land-birds.  Bermuda, on the other hand, which lies at
+about the same distance from North America as the Galapagos Islands do from
+South America, and which has a very peculiar soil, does not possess one
+endemic land bird; and we know from Mr. J. M. Jones's admirable account of
+Bermuda, that very many North American birds, during their great annual
+migrations, visit either periodically or occasionally this island.  Madeira
+does not possess one peculiar bird, and many European and African birds are
+almost every year blown there, as I am informed by Mr. E. V. Harcourt.  So
+that these two islands of Bermuda and Madeira have been stocked by birds,
+which for long ages have struggled together in their former homes, and have
+become mutually adapted to each other; and when settled in their new homes,
+each kind will have been kept by the others to their proper places and
+habits, and will consequently have been little liable to modification. 
+Madeira, again, is inhabited by a wonderful number of peculiar land-shells,
+whereas not one species of sea-shell is confined to its shores:  now,
+though we do not know how seashells are dispersed, yet we can see that
+their eggs or larvae, perhaps attached to seaweed or floating timber, or to
+the feet of wading-birds, might be transported far more easily than
+land-shells, across three or four hundred miles of open sea.  The different
+orders of insects in Madeira apparently present analogous facts.
+</para>
+
+<para>
+Oceanic islands are sometimes deficient in certain classes, and their
+places are apparently occupied by the other inhabitants; in the Galapagos
+Islands reptiles, and in New Zealand gigantic wingless birds, take the
+place of mammals.  In the plants of the Galapagos Islands, Dr. Hooker has
+shown that the proportional numbers of the different orders are very
+different from what they are elsewhere.  Such cases are generally accounted
+for by the physical conditions of the islands; but this explanation seems
+to me not a little doubtful.  Facility of immigration, I believe, has been
+at least as important as the nature of the conditions.
+</para>
+
+<para>
+Many remarkable little facts could be given with respect to the inhabitants
+of remote islands.  For instance, in certain islands not tenanted by
+mammals, some of the endemic plants have beautifully hooked seeds; yet few
+relations are more striking than the adaptation of hooked seeds for
+transportal by the wool and fur of quadrupeds.  This case presents no
+difficulty on my view, for a hooked seed might be transported to an island
+by some other means; and the plant then becoming slightly modified, but
+still retaining its hooked seeds, would form an endemic species, having as
+useless an appendage as any rudimentary organ,--for instance, as the
+shrivelled wings under the soldered elytra of many insular beetles.  Again,
+islands often possess trees or bushes belonging to orders which elsewhere
+include only herbaceous species; now trees, as Alph. de Candolle has shown,
+generally have, whatever the cause may be, confined ranges.  Hence trees
+would be little likely to reach distant oceanic islands; and an herbaceous
+plant, though it would have no chance of successfully competing in stature
+with a fully developed tree, when established on an island and having to
+compete with herbaceous plants alone, might readily gain an advantage by
+growing taller and taller and overtopping the other plants.  If so, natural
+selection would often tend to add to the stature of herbaceous plants when
+growing on an island, to whatever order they belonged, and thus convert
+them first into bushes and ultimately into trees.
+</para>
+
+<para>
+With respect to the absence of whole orders on oceanic islands, Bory St.
+Vincent long ago remarked that Batrachians (frogs, toads, newts) have never
+been found on any of the many islands with which the great oceans are
+studded.  I have taken pains to verify this assertion, and I have found it
+strictly true.  I have, however, been assured that a frog exists on the
+mountains of the great island of New Zealand; but I suspect that this
+exception (if the information be correct) may be explained through glacial
+agency.  This general absence of frogs, toads, and newts on so many oceanic
+islands cannot be accounted for by their physical conditions; indeed it
+seems that islands are peculiarly well fitted for these animals; for frogs
+have been introduced into Madeira, the Azores, and Mauritius, and have
+multiplied so as to become a nuisance.  But as these animals and their
+spawn are known to be immediately killed by sea-water, on my view we can
+see that there would be great difficulty in their transportal across the
+sea, and therefore why they do not exist on any oceanic island.  But why,
+on the theory of creation, they should not have been created there, it
+would be very difficult to explain.
+</para>
+
+<para>
+Mammals offer another and similar case.  I have carefully searched the
+oldest voyages, but have not finished my search; as yet I have not found a
+single instance, free from doubt, of a terrestrial mammal (excluding
+domesticated animals kept by the natives) inhabiting an island situated
+above 300 miles from a continent or great continental island; and many
+islands situated at a much less distance are equally barren.  The Falkland
+Islands, which are inhabited by a wolf-like fox, come nearest to an
+exception; but this group cannot be considered as oceanic, as it lies on a
+bank connected with the mainland; moreover, icebergs formerly brought
+boulders to its western shores, and they may have formerly transported
+foxes, as so frequently now happens in the arctic regions.  Yet it cannot
+be said that small islands will not support small mammals, for they occur
+in many parts of the world on very small islands, if close to a continent;
+and hardly an island can be named on which our smaller quadrupeds have not
+become naturalised and greatly multiplied.  It cannot be said, on the
+ordinary view of creation, that there has not been time for the creation of
+mammals; many volcanic islands are sufficiently ancient, as shown by the
+stupendous degradation which they have suffered and by their tertiary
+strata:  there has also been time for the production of endemic species
+belonging to other classes; and on continents it is thought that mammals
+appear and disappear at a quicker rate than other and lower animals. 
+Though terrestrial mammals do not occur on oceanic islands, aerial mammals
+do occur on almost every island.  New Zealand possesses two bats found
+nowhere else in the world:  Norfolk Island, the Viti Archipelago, the Bonin
+Islands, the Caroline and Marianne Archipelagoes, and Mauritius, all
+possess their peculiar bats.  Why, it may be asked, has the supposed
+creative force produced bats and no other mammals on remote islands?  On my
+view this question can easily be answered; for no terrestrial mammal can be
+transported across a wide space of sea, but bats can fly across.  Bats have
+been seen wandering by day far over the Atlantic Ocean; and two North
+American species either regularly or occasionally visit Bermuda, at the
+distance of 600 miles from the mainland.  I hear from Mr. Tomes, who has
+specially studied this family, that many of the same species have enormous
+ranges, and are found on continents and on far distant islands.  Hence we
+have only to suppose that such wandering species have been modified through
+natural selection in their new homes in relation to their new position, and
+we can understand the presence of endemic bats on islands, with the absence
+of all terrestrial mammals.
+</para>
+
+<para>
+Besides the absence of terrestrial mammals in relation to the remoteness of
+islands from continents, there is also a relation, to a certain extent
+independent of distance, between the depth of the sea separating an island
+from the neighbouring mainland, and the presence in both of the same
+mammiferous species or of allied species in a more or less modified
+condition.  Mr. Windsor Earl has made some striking observations on this
+head in regard to the great Malay Archipelago, which is traversed near
+Celebes by a space of deep ocean; and this space separates two widely
+distinct mammalian faunas.  On either side the islands are situated on
+moderately deep submarine banks, and they are inhabited by closely allied
+or identical quadrupeds.  No doubt some few anomalies occur in this great
+archipelago, and there is much difficulty in forming a judgment in some
+cases owing to the probable naturalisation of certain mammals through man's
+agency; but we shall soon have much light thrown on the natural history of
+this archipelago by the admirable zeal and researches of Mr. Wallace.  I
+have not as yet had time to follow up this subject in all other quarters of
+the world; but as far as I have gone, the relation generally holds good. 
+We see Britain separated by a shallow channel from Europe, and the mammals
+are the same on both sides; we meet with analogous facts on many islands
+separated by similar channels from Australia.  The West Indian Islands
+stand on a deeply submerged bank, nearly 1000 fathoms in depth, and here we
+find American forms, but the species and even the genera are distinct.  As
+the amount of modification in all cases depends to a certain degree on the
+lapse of time, and as during changes of level it is obvious that islands
+separated by shallow channels are more likely to have been continuously
+united within a recent period to the mainland than islands separated by
+deeper channels, we can understand the frequent relation between the depth
+of the sea and the degree of affinity of the mammalian inhabitants of
+islands with those of a neighbouring continent,--an inexplicable relation
+on the view of independent acts of creation.
+</para>
+
+<para>
+All the foregoing remarks on the inhabitants of oceanic islands,--namely,
+the scarcity of kinds--the richness in endemic forms in particular classes
+or sections of classes,--the absence of whole groups, as of batrachians,
+and of terrestrial mammals notwithstanding the presence of aerial
+bats,--the singular proportions of certain orders of plants,--herbaceous
+forms having been developed into trees, &amp;c.,--seem to me to accord better
+with the view of occasional means of transport having been largely
+efficient in the long course of time, than with the view of all our oceanic
+islands having been formerly connected by continuous land with the nearest
+continent; for on this latter view the migration would probably have been
+more complete; and if modification be admitted, all the forms of life would
+have been more equally modified, in accordance with the paramount
+importance of the relation of organism to organism.
+</para>
+
+<para>
+I do not deny that there are many and grave difficulties in understanding
+how several of the inhabitants of the more remote islands, whether still
+retaining the same specific form or modified since their arrival, could
+have reached their present homes.  But the probability of many islands
+having existed as halting-places, of which not a wreck now remains, must
+not be overlooked.  I will here give a single instance of one of the cases
+of difficulty.  Almost all oceanic islands, even the most isolated and
+smallest, are inhabited by land-shells, generally by endemic species, but
+sometimes by species found elsewhere.  Dr. Aug. A. Gould has given several
+interesting cases in regard to the land-shells of the islands of the
+Pacific.  Now it is notorious that land-shells are very easily killed by
+salt; their eggs, at least such as I have tried, sink in sea-water and are
+killed by it.  Yet there must be, on my view, some unknown, but highly
+efficient means for their transportal.  Would the just-hatched young
+occasionally crawl on and adhere to the feet of birds roosting on the
+ground, and thus get transported?  It occurred to me that land-shells, when
+hybernating and having a membranous diaphragm over the mouth of the shell,
+might be floated in chinks of drifted timber across moderately wide arms of
+the sea.  And I found that several species did in this state withstand
+uninjured an immersion in sea-water during seven days:  one of these shells
+was the Helix pomatia, and after it had again hybernated I put it in
+sea-water for twenty days, and it perfectly recovered.  As this species has
+a thick calcareous operculum, I removed it, and when it had formed a new
+membranous one, I immersed it for fourteen days in sea-water, and it
+recovered and crawled away:  but more experiments are wanted on this head.
+</para>
+
+<para>
+The most striking and important fact for us in regard to the inhabitants of
+islands, is their affinity to those of the nearest mainland, without being
+actually the same species.  Numerous instances could be given of this fact. 
+I will give only one, that of the Galapagos Archipelago, situated under the
+equator, between 500 and 600 miles from the shores of South America.  Here
+almost every product of the land and water bears the unmistakeable stamp of
+the American continent.  There are twenty-six land birds, and twenty-five
+of these are ranked by Mr. Gould as distinct species, supposed to have been
+created here; yet the close affinity of most of these birds to American
+species in every character, in their habits, gestures, and tones of voice,
+was manifest.  So it is with the other animals, and with nearly all the
+plants, as shown by Dr. Hooker in his admirable memoir on the Flora of this
+archipelago.  The naturalist, looking at the inhabitants of these volcanic
+islands in the Pacific, distant several hundred miles from the continent,
+yet feels that he is standing on American land.  Why should this be so? why
+should the species which are supposed to have been created in the Galapagos
+Archipelago, and nowhere else, bear so plain a stamp of affinity to those
+created in America?  There is nothing in the conditions of life, in the
+geological nature of the islands, in their height or climate, or in the
+proportions in which the several classes are associated together, which
+resembles closely the conditions of the South American coast:  in fact
+there is a considerable dissimilarity in all these respects.  On the other
+hand, there is a considerable degree of resemblance in the volcanic nature
+of the soil, in climate, height, and size of the islands, between the
+Galapagos and Cape de Verde Archipelagos:  but what an entire and absolute
+difference in their inhabitants!  The inhabitants of the Cape de Verde
+Islands are related to those of Africa, like those of the Galapagos to
+America.  I believe this grand fact can receive no sort of explanation on
+the ordinary view of independent creation; whereas on the view here
+maintained, it is obvious that the Galapagos Islands would be likely to
+receive colonists, whether by occasional means of transport or by formerly
+continuous land, from America; and the Cape de Verde Islands from Africa;
+and that such colonists would be liable to modification;--the principle of
+inheritance still betraying their original birthplace.
+</para>
+
+<para>
+Many analogous facts could be given:  indeed it is an almost universal rule
+that the endemic productions of islands are related to those of the nearest
+continent, or of other near islands.  The exceptions are few, and most of
+them can be explained.  Thus the plants of Kerguelen Land, though standing
+nearer to Africa than to America, are related, and that very closely, as we
+know from Dr. Hooker's account, to those of America:  but on the view that
+this island has been mainly stocked by seeds brought with earth and stones
+on icebergs, drifted by the prevailing currents, this anomaly disappears. 
+New Zealand in its endemic plants is much more closely related to
+Australia, the nearest mainland, than to any other region:  and this is
+what might have been expected; but it is also plainly related to South
+America, which, although the next nearest continent, is so enormously
+remote, that the fact becomes an anomaly.  But this difficulty almost
+disappears on the view that both New Zealand, South America, and other
+southern lands were long ago partially stocked from a nearly intermediate
+though distant point, namely from the antarctic islands, when they were
+clothed with vegetation, before the commencement of the Glacial period. 
+The affinity, which, though feeble, I am assured by Dr. Hooker is real,
+between the flora of the south-western corner of Australia and of the Cape
+of Good Hope, is a far more remarkable case, and is at present
+inexplicable:  but this affinity is confined to the plants, and will, I do
+not doubt, be some day explained.
+</para>
+
+<para>
+The law which causes the inhabitants of an archipelago, though specifically
+distinct, to be closely allied to those of the nearest continent, we
+sometimes see displayed on a small scale, yet in a most interesting manner,
+within the limits of the same archipelago.  Thus the several islands of the
+Galapagos Archipelago are tenanted, as I have elsewhere shown, in a quite
+marvellous manner, by very closely related species; so that the inhabitants
+of each separate island, though mostly distinct, are related in an
+incomparably closer degree to each other than to the inhabitants of any
+other part of the world.  And this is just what might have been expected on
+my view, for the islands are situated so near each other that they would
+almost certainly receive immigrants from the same original source, or from
+each other.  But this dissimilarity between the endemic inhabitants of the
+islands may be used as an argument against my views; for it may be asked,
+how has it happened in the several islands situated within sight of each
+other, having the same geological nature, the same height, climate, &amp;c.,
+that many of the immigrants should have been differently modified, though
+only in a small degree.  This long appeared to me a great difficulty:  but
+it arises in chief part from the deeply-seated error of considering the
+physical conditions of a country as the most important for its inhabitants;
+whereas it cannot, I think, be disputed that the nature of the other
+inhabitants, with which each has to compete, is at least as important, and
+generally a far more important element of success.  Now if we look to those
+inhabitants of the Galapagos Archipelago which are found in other parts of
+the world (laying on one side for the moment the endemic species, which
+cannot be here fairly included, as we are considering how they have come to
+be modified since their arrival), we find a considerable amount of
+difference in the several islands.  This difference might indeed have been
+expected on the view of the islands having been stocked by occasional means
+of transport--a seed, for instance, of one plant having been brought to one
+island, and that of another plant to another island.  Hence when in former
+times an immigrant settled on any one or more of the islands, or when it
+subsequently spread from one island to another, it would undoubtedly be
+exposed to different conditions of life in the different islands, for it
+would have to compete with different sets of organisms:  a plant, for
+instance, would find the best-fitted ground more perfectly occupied by
+distinct plants in one island than in another, and it would be exposed to
+the attacks of somewhat different enemies.  If then it varied, natural
+selection would probably favour different varieties in the different
+islands.  Some species, however, might spread and yet retain the same
+character throughout the group, just as we see on continents some species
+spreading widely and remaining the same.
+</para>
+
+<para>
+The really surprising fact in this case of the Galapagos Archipelago, and
+in a lesser degree in some analogous instances, is that the new species
+formed in the separate islands have not quickly spread to the other
+islands.  But the islands, though in sight of each other, are separated by
+deep arms of the sea, in most cases wider than the British Channel, and
+there is no reason to suppose that they have at any former period been
+continuously united.  The currents of the sea are rapid and sweep across
+the archipelago, and gales of wind are extraordinarily rare; so that the
+islands are far more effectually separated from each other than they appear
+to be on a map.  Nevertheless a good many species, both those found in
+other parts of the world and those confined to the archipelago, are common
+to the several islands, and we may infer from certain facts that these have
+probably spread from some one island to the others.  But we often take, I
+think, an erroneous view of the probability of closely allied species
+invading each other's territory, when put into free intercommunication. 
+Undoubtedly if one species has any advantage whatever over another, it will
+in a very brief time wholly or in part supplant it; but if both are equally
+well fitted for their own places in nature, both probably will hold their
+own places and keep separate for almost any length of time.  Being familiar
+with the fact that many species, naturalised through man's agency, have
+spread with astonishing rapidity over new countries, we are apt to infer
+that most species would thus spread; but we should remember that the forms
+which become naturalised in new countries are not generally closely allied
+to the aboriginal inhabitants, but are very distinct species, belonging in
+a large proportion of cases, as shown by Alph. de Candolle, to distinct
+genera.  In the Galapagos Archipelago, many even of the birds, though so
+well adapted for flying from island to island, are distinct on each; thus
+there are three closely-allied species of mocking-thrush, each confined to
+its own island.  Now let us suppose the mocking-thrush of Chatham Island to
+be blown to Charles Island, which has its own mocking-thrush:  why should
+it succeed in establishing itself there?  We may safely infer that Charles
+Island is well stocked with its own species, for annually more eggs are
+laid there than can possibly be reared; and we may infer that the
+mocking-thrush peculiar to Charles Island is at least as well fitted for
+its home as is the species peculiar to Chatham Island.  Sir C. Lyell and
+Mr. Wollaston have communicated to me a remarkable fact bearing on this
+subject; namely, that Madeira and the adjoining islet of Porto Santo
+possess many distinct but representative land-shells, some of which live in
+crevices of stone; and although large quantities of stone are annually
+transported from Porto Santo to Madeira, yet this latter island has not
+become colonised by the Porto Santo species:  nevertheless both islands
+have been colonised by some European land-shells, which no doubt had some
+advantage over the indigenous species.  From these considerations I think
+we need not greatly marvel at the endemic and representative species, which
+inhabit the several islands of the Galapagos Archipelago, not having
+universally spread from island to island.  In many other instances, as in
+the several districts of the same continent, pre-occupation has probably
+played an important part in checking the commingling of species under the
+same conditions of life.  Thus, the south-east and south-west corners of
+Australia have nearly the same physical conditions, and are united by
+continuous land, yet they are inhabited by a vast number of distinct
+mammals, birds, and plants.
+</para>
+
+<para>
+The principle which determines the general character of the fauna and flora
+of oceanic islands, namely, that the inhabitants, when not identically the
+same, yet are plainly related to the inhabitants of that region whence
+colonists could most readily have been derived,--the colonists having been
+subsequently modified and better fitted to their new homes,--is of the
+widest application throughout nature.  We see this on every mountain, in
+every lake and marsh.  For Alpine species, excepting in so far as the same
+forms, chiefly of plants, have spread widely throughout the world during
+the recent Glacial epoch, are related to those of the surrounding
+lowlands;--thus we have in South America, Alpine humming-birds, Alpine
+rodents, Alpine plants, &amp;c., all of strictly American forms, and it is
+obvious that a mountain, as it became slowly upheaved, would naturally be
+colonised from the surrounding lowlands.  So it is with the inhabitants of
+lakes and marshes, excepting in so far as great facility of transport has
+given the same general forms to the whole world.  We see this same
+principle in the blind animals inhabiting the caves of America and of
+Europe.  Other analogous facts could be given.  And it will, I believe, be
+universally found to be true, that wherever in two regions, let them be
+ever so distant, many closely allied or representative species occur, there
+will likewise be found some identical species, showing, in accordance with
+the foregoing view, that at some former period there has been
+intercommunication or migration between the two regions.  And wherever many
+closely-allied species occur, there will be found many forms which some
+naturalists rank as distinct species, and some as varieties; these doubtful
+forms showing us the steps in the process of modification.
+</para>
+
+<para>
+This relation between the power and extent of migration of a species,
+either at the present time or at some former period under different
+physical conditions, and the existence at remote points of the world of
+other species allied to it, is shown in another and more general way.  Mr.
+Gould remarked to me long ago, that in those genera of birds which range
+over the world, many of the species have very wide ranges.  I can hardly
+doubt that this rule is generally true, though it would be difficult to
+prove it.  Amongst mammals, we see it strikingly displayed in Bats, and in
+a lesser degree in the Felidae and Canidae.  We see it, if we compare the
+distribution of butterflies and beetles.  So it is with most fresh-water
+productions, in which so many genera range over the world, and many
+individual species have enormous ranges.  It is not meant that in
+world-ranging genera all the species have a wide range, or even that they
+have on an average a wide range; but only that some of the species range
+very widely; for the facility with which widely-ranging species vary and
+give rise to new forms will largely determine their average range.  For
+instance, two varieties of the same species inhabit America and Europe, and
+the species thus has an immense range; but, if the variation had been a
+little greater, the two varieties would have been ranked as distinct
+species, and the common range would have been greatly reduced.  Still less
+is it meant, that a species which apparently has the capacity of crossing
+barriers and ranging widely, as in the case of certain powerfully-winged
+birds, will necessarily range widely; for we should never forget that to
+range widely implies not only the power of crossing barriers, but the more
+important power of being victorious in distant lands in the struggle for
+life with foreign associates.  But on the view of all the species of a
+genus having descended from a single parent, though now distributed to the
+most remote points of the world, we ought to find, and I believe as a
+general rule we do find, that some at least of the species range very
+widely; for it is necessary that the unmodified parent should range widely,
+undergoing modification during its diffusion, and should place itself under
+diverse conditions favourable for the conversion of its offspring, firstly
+into new varieties and ultimately into new species.
+</para>
+
+<para>
+In considering the wide distribution of certain genera, we should bear in
+mind that some are extremely ancient, and must have branched off from a
+common parent at a remote epoch; so that in such cases there will have been
+ample time for great climatal and geographical changes and for accidents of
+transport; and consequently for the migration of some of the species into
+all quarters of the world, where they may have become slightly modified in
+relation to their new conditions.  There is, also, some reason to believe
+from geological evidence that organisms low in the scale within each great
+class, generally change at a slower rate than the higher forms; and
+consequently the lower forms will have had a better chance of ranging
+widely and of still retaining the same specific character.  This fact,
+together with the seeds and eggs of many low forms being very minute and
+better fitted for distant transportation, probably accounts for a law which
+has long been observed, and which has lately been admirably discussed by
+Alph. de Candolle in regard to plants, namely, that the lower any group of
+organisms is, the more widely it is apt to range.
+</para>
+
+<para>
+The relations just discussed,--namely, low and slowly-changing organisms
+ranging more widely than the high,--some of the species of widely-ranging
+genera themselves ranging widely,--such facts, as alpine, lacustrine, and
+marsh productions being related (with the exceptions before specified) to
+those on the surrounding low lands and dry lands, though these stations are
+so different--the very close relation of the distinct species which inhabit
+the islets of the same archipelago,--and especially the striking relation
+of the inhabitants of each whole archipelago or island to those of the
+nearest mainland,--are, I think, utterly inexplicable on the ordinary view
+of the independent creation of each species, but are explicable on the view
+of colonisation from the nearest and readiest source, together with the
+subsequent modification and better adaptation of the colonists to their new
+homes.
+</para>
+
+<para>
+Summary of last and present Chapters -- In these chapters I have
+endeavoured to show, that if we make due allowance for our ignorance of the
+full effects of all the changes of climate and of the level of the land,
+which have certainly occurred within the recent period, and of other
+similar changes which may have occurred within the same period; if we
+remember how profoundly ignorant we are with respect to the many and
+curious means of occasional transport,--a subject which has hardly ever
+been properly experimentised on; if we bear in mind how often a species may
+have ranged continuously over a wide area, and then have become extinct in
+the intermediate tracts, I think the difficulties in believing that all the
+individuals of the same species, wherever located, have descended from the
+same parents, are not insuperable.  And we are led to this conclusion,
+which has been arrived at by many naturalists under the designation of
+single centres of creation, by some general considerations, more especially
+from the importance of barriers and from the analogical distribution of
+sub-genera, genera, and families.
+</para>
+
+<para>
+With respect to the distinct species of the same genus, which on my theory
+must have spread from one parent-source; if we make the same allowances as
+before for our ignorance, and remember that some forms of life change most
+slowly, enormous periods of time being thus granted for their migration, I
+do not think that the difficulties are insuperable; though they often are
+in this case, and in that of the individuals of the same species, extremely
+grave.
+</para>
+
+<para>
+As exemplifying the effects of climatal changes on distribution, I have
+attempted to show how important has been the influence of the modern
+Glacial period, which I am fully convinced simultaneously affected the
+whole world, or at least great meridional belts.  As showing how
+diversified are the means of occasional transport, I have discussed at some
+little length the means of dispersal of fresh-water productions.
+</para>
+
+<para>
+If the difficulties be not insuperable in admitting that in the long course
+of time the individuals of the same species, and likewise of allied
+species, have proceeded from some one source; then I think all the grand
+leading facts of geographical distribution are explicable on the theory of
+migration (generally of the more dominant forms of life), together with
+subsequent modification and the multiplication of new forms.  We can thus
+understand the high importance of barriers, whether of land or water, which
+separate our several zoological and botanical provinces.  We can thus
+understand the localisation of sub-genera, genera, and families; and how it
+is that under different latitudes, for instance in South America, the
+inhabitants of the plains and mountains, of the forests, marshes, and
+deserts, are in so mysterious a manner linked together by affinity, and are
+likewise linked to the extinct beings which formerly inhabited the same
+continent.  Bearing in mind that the mutual relations of organism to
+organism are of the highest importance, we can see why two areas having
+nearly the same physical conditions should often be inhabited by very
+different forms of life; for according to the length of time which has
+elapsed since new inhabitants entered one region; according to the nature
+of the communication which allowed certain forms and not others to enter,
+either in greater or lesser numbers; according or not, as those which
+entered happened to come in more or less direct competition with each other
+and with the aborigines; and according as the immigrants were capable of
+varying more or less rapidly, there would ensue in different regions,
+independently of their physical conditions, infinitely diversified
+conditions of life,--there would be an almost endless amount of organic
+action and reaction,--and we should find, as we do find, some groups of
+beings greatly, and some only slightly modified,--some developed in great
+force, some existing in scanty numbers--in the different great geographical
+provinces of the world.
+</para>
+
+<para>
+On these same principles, we can understand, as I have endeavoured to show,
+why oceanic islands should have few inhabitants, but of these a great
+number should be endemic or peculiar; and why, in relation to the means of
+migration, one group of beings, even within the same class, should have all
+its species endemic, and another group should have all its species common
+to other quarters of the world.  We can see why whole groups of organisms,
+as batrachians and terrestrial mammals, should be absent from oceanic
+islands, whilst the most isolated islands possess their own peculiar
+species of aerial mammals or bats.  We can see why there should be some
+relation between the presence of mammals, in a more or less modified
+condition, and the depth of the sea between an island and the mainland.  We
+can clearly see why all the inhabitants of an archipelago, though
+specifically distinct on the several islets, should be closely related to
+each other, and likewise be related, but less closely, to those of the
+nearest continent or other source whence immigrants were probably derived. 
+We can see why in two areas, however distant from each other, there should
+be a correlation, in the presence of identical species, of varieties, of
+doubtful species, and of distinct but representative species.
+</para>
+
+<para>
+As the late Edward Forbes often insisted, there is a striking parallelism
+in the laws of life throughout time and space:  the laws governing the
+succession of forms in past times being nearly the same with those
+governing at the present time the differences in different areas.  We see
+this in many facts.  The endurance of each species and group of species is
+continuous in time; for the exceptions to the rule are so few, that they
+may fairly be attributed to our not having as yet discovered in an
+intermediate deposit the forms which are therein absent, but which occur
+above and below:  so in space, it certainly is the general rule that the
+area inhabited by a single species, or by a group of species, is
+continuous; and the exceptions, which are not rare, may, as I have
+attempted to show, be accounted for by migration at some former period
+under different conditions or by occasional means of transport, and by the
+species having become extinct in the intermediate tracts.  Both in time and
+space, species and groups of species have their points of maximum
+development.  Groups of species, belonging either to a certain period of
+time, or to a certain area, are often characterised by trifling characters
+in common, as of sculpture or colour.  In looking to the long succession of
+ages, as in now looking to distant provinces throughout the world, we find
+that some organisms differ little, whilst others belonging to a different
+class, or to a different order, or even only to a different family of the
+same order, differ greatly.  In both time and space the lower members of
+each class generally change less than the higher; but there are in both
+cases marked exceptions to the rule.  On my theory these several relations
+throughout time and space are intelligible; for whether we look to the
+forms of life which have changed during successive ages within the same
+quarter of the world, or to those which have changed after having migrated
+into distant quarters, in both cases the forms within each class have been
+connected by the same bond of ordinary generation; and the more nearly any
+two forms are related in blood, the nearer they will generally stand to
+each other in time and space; in both cases the laws of variation have been
+the same, and modifications have been accumulated by the same power of
+natural selection.
+</para>
+
+</chapter>
+
+<chapter>
+<chapheader>
+
+
+<chapnum>Chapter XIII</chapnum>
+
+<title>Mutual Affinities of Organic Beings:
+Morphology:  Embryology:  Rudimentary Organs</title>
+
+<chapsummary>
+Classification, groups subordinate to groups -- Natural system -- Rules and
+difficulties in classification, explained on the theory of descent with
+modification -- Classification of varieties -- Descent always used in
+classification -- Analogical or adaptive characters -- Affinities, general,
+complex and radiating -- Extinction separates and defines groups --
+Morphology, between members of the same class, between parts of the same
+individual -- Embryology, laws of, explained by variations not supervening
+at an early age, and being inherited at a corresponding age -- Rudimentary
+Organs; their origin explained -- Summary.
+</chapsummary>
+</chapheader>
+
+<para>
+From the first dawn of life, all organic beings are found to resemble each
+other in descending degrees, so that they can be classed in groups under
+groups.  This classification is evidently not arbitrary like the grouping
+of the stars in constellations.  The existence of groups would have been of
+simple signification, if one group had been exclusively fitted to inhabit
+the land, and another the water; one to feed on flesh, another on vegetable
+matter, and so on; but the case is widely different in nature; for it is
+notorious how commonly members of even the same subgroup have different
+habits.  In our second and fourth chapters, on Variation and on Natural
+Selection, I have attempted to show that it is the widely ranging, the much
+diffused and common, that is the dominant species belonging to the larger
+genera, which vary most.  The varieties, or incipient species, thus
+produced ultimately become converted, as I believe, into new and distinct
+species; and these, on the principle of inheritance, tend to produce other
+new and dominant species.  Consequently the groups which are now large, and
+which generally include many dominant species, tend to go on increasing
+indefinitely in size.  I further attempted to show that from the varying
+descendants of each species trying to occupy as many and as different
+places as possible in the economy of nature, there is a constant tendency
+in their characters to diverge.  This conclusion was supported by looking
+at the great diversity of the forms of life which, in any small area, come
+into the closest competition, and by looking to certain facts in
+naturalisation.
+</para>
+
+<para>
+I attempted also to show that there is a constant tendency in the forms
+which are increasing in number and diverging in character, to supplant and
+exterminate the less divergent, the less improved, and preceding forms.  I
+request the reader to turn to the diagram illustrating the action, as
+formerly explained, of these several principles; and he will see that the
+inevitable result is that the modified descendants proceeding from one
+progenitor become broken up into groups subordinate to groups.  In the
+diagram each letter on the uppermost line may represent a genus including
+several species; and all the genera on this line form together one class,
+for all have descended from one ancient but unseen parent, and,
+consequently, have inherited something in common.  But the three genera on
+the left hand have, on this same principle, much in common, and form a
+sub-family, distinct from that including the next two genera on the right
+hand, which diverged from a common parent at the fifth stage of descent. 
+These five genera have also much, though less, in common; and they form a
+family distinct from that including the three genera still further to the
+right hand, which diverged at a still earlier period.  And all these
+genera, descended from (A), form an order distinct from the genera
+descended from (I).  So that we here have many species descended from a
+single progenitor grouped into genera; and the genera are included in, or
+subordinate to, sub-families, families, and orders, all united into one
+class.  Thus, the grand fact in natural history of the subordination of
+group under group, which, from its familiarity, does not always
+sufficiently strike us, is in my judgment fully explained.
+</para>
+
+<para>
+Naturalists try to arrange the species, genera, and families in each class,
+on what is called the Natural System.  But what is meant by this system? 
+Some authors look at it merely as a scheme for arranging together those
+living objects which are most alike, and for separating those which are
+most unlike; or as an artificial means for enunciating, as briefly as
+possible, general propositions,--that is, by one sentence to give the
+characters common, for instance, to all mammals, by another those common to
+all carnivora, by another those common to the dog-genus, and then by adding
+a single sentence, a full description is given of each kind of dog.  The
+ingenuity and utility of this system are indisputable.  But many
+naturalists think that something more is meant by the Natural System; they
+believe that it reveals the plan of the Creator; but unless it be specified
+whether order in time or space, or what else is meant by the plan of the
+Creator, it seems to me that nothing is thus added to our knowledge.  Such
+expressions as that famous one of Linnaeus, and which we often meet with in
+a more or less concealed form, that the characters do not make the genus,
+but that the genus gives the characters, seem to imply that something more
+is included in our classification, than mere resemblance.  I believe that
+something more is included; and that propinquity of descent,--the only
+known cause of the similarity of organic beings,--is the bond, hidden as it
+is by various degrees of modification, which is partially revealed to us by
+our classifications.
+</para>
+
+<para>
+Let us now consider the rules followed in classification, and the
+difficulties which are encountered on the view that classification either
+gives some unknown plan of creation, or is simply a scheme for enunciating
+general propositions and of placing together the forms most like each
+other.  It might have been thought (and was in ancient times thought) that
+those parts of the structure which determined the habits of life, and the
+general place of each being in the economy of nature, would be of very high
+importance in classification.  Nothing can be more false.  No one regards
+the external similarity of a mouse to a shrew, of a dugong to a whale, of a
+whale to a fish, as of any importance.  These resemblances, though so
+intimately connected with the whole life of the being, are ranked as merely
+'adaptive or analogical characters;' but to the consideration of these
+resemblances we shall have to recur.  It may even be given as a general
+rule, that the less any part of the organisation is concerned with special
+habits, the more important it becomes for classification.  As an instance: 
+Owen, in speaking of the dugong, says, 'The generative organs being those
+which are most remotely related to the habits and food of an animal, I have
+always regarded as affording very clear indications of its true affinities. 
+We are least likely in the modifications of these organs to mistake a
+merely adaptive for an essential character.'  So with plants, how
+remarkable it is that the organs of vegetation, on which their whole life
+depends, are of little signification, excepting in the first main
+divisions; whereas the organs of reproduction, with their product the seed,
+are of paramount importance!
+</para>
+
+<para>
+We must not, therefore, in classifying, trust to resemblances in parts of
+the organisation, however important they may be for the welfare of the
+being in relation to the outer world.  Perhaps from this cause it has
+partly arisen, that almost all naturalists lay the greatest stress on
+resemblances in organs of high vital or physiological importance.  No doubt
+this view of the classificatory importance of organs which are important is
+generally, but by no means always, true.  But their importance for
+classification, I believe, depends on their greater constancy throughout
+large groups of species; and this constancy depends on such organs having
+generally been subjected to less change in the adaptation of the species to
+their conditions of life.  That the mere physiological importance of an
+organ does not determine its classificatory value, is almost shown by the
+one fact, that in allied groups, in which the same organ, as we have every
+reason to suppose, has nearly the same physiological value, its
+classificatory value is widely different.  No naturalist can have worked at
+any group without being struck with this fact; and it has been most fully
+acknowledged in the writings of almost every author.  It will suffice to
+quote the highest authority, Robert Brown, who in speaking of certain
+organs in the Proteaceae, says their generic importance, 'like that of all
+their parts, not only in this but, as I apprehend, in every natural family,
+is very unequal, and in some cases seems to be entirely lost.'  Again in
+another work he says, the genera of the Connaraceae 'differ in having one
+or more ovaria, in the existence or absence of albumen, in the imbricate or
+valvular aestivation.  Any one of these characters singly is frequently of
+more than generic importance, though here even when all taken together they
+appear insufficient to separate Cnestis from Connarus.'  To give an example
+amongst insects, in one great division of the Hymenoptera, the antennae, as
+Westwood has remarked, are most constant in structure; in another division
+they differ much, and the differences are of quite subordinate value in
+classification; yet no one probably will say that the antennae in these two
+divisions of the same order are of unequal physiological importance.  Any
+number of instances could be given of the varying importance for
+classification of the same important organ within the same group of beings.
+</para>
+
+<para>
+Again, no one will say that rudimentary or atrophied organs are of high
+physiological or vital importance; yet, undoubtedly, organs in this
+condition are often of high value in classification.  No one will dispute
+that the rudimentary teeth in the upper jaws of young ruminants, and
+certain rudimentary bones of the leg, are highly serviceable in exhibiting
+the close affinity between Ruminants and Pachyderms.  Robert Brown has
+strongly insisted on the fact that the rudimentary florets are of the
+highest importance in the classification of the Grasses.
+</para>
+
+<para>
+Numerous instances could be given of characters derived from parts which
+must be considered of very trifling physiological importance, but which are
+universally admitted as highly serviceable in the definition of whole
+groups.  For instance, whether or not there is an open passage from the
+nostrils to the mouth, the only character, according to Owen, which
+absolutely distinguishes fishes and reptiles--the inflection of the angle
+of the jaws in Marsupials--the manner in which the wings of insects are
+folded--mere colour in certain Algae--mere pubescence on parts of the
+flower in grasses--the nature of the dermal covering, as hair or feathers,
+in the Vertebrata.  If the Ornithorhynchus had been covered with feathers
+instead of hair, this external and trifling character would, I think, have
+been considered by naturalists as important an aid in determining the
+degree of affinity of this strange creature to birds and reptiles, as an
+approach in structure in any one internal and important organ.
+</para>
+
+<para>
+The importance, for classification, of trifling characters, mainly depends
+on their being correlated with several other characters of more or less
+importance.  The value indeed of an aggregate of characters is very evident
+in natural history.  Hence, as has often been remarked, a species may
+depart from its allies in several characters, both of high physiological
+importance and of almost universal prevalence, and yet leave us in no doubt
+where it should be ranked.  Hence, also, it has been found, that a
+classification founded on any single character, however important that may
+be, has always failed; for no part of the organisation is universally
+constant.  The importance of an aggregate of characters, even when none are
+important, alone explains, I think, that saying of Linnaeus, that the
+characters do not give the genus, but the genus gives the characters; for
+this saying seems founded on an appreciation of many trifling points of
+resemblance, too slight to be defined.  Certain plants, belonging to the
+Malpighiaceae, bear perfect and degraded flowers; in the latter, as A. de
+Jussieu has remarked, 'the greater number of the characters proper to the
+species, to the genus, to the family, to the class, disappear, and thus
+laugh at our classification.'  But when Aspicarpa produced in France,
+during several years, only degraded flowers, departing so wonderfully in a
+number of the most important points of structure from the proper type of
+the order, yet M. Richard sagaciously saw, as Jussieu observes, that this
+genus should still be retained amongst the Malpighiaceae.  This case seems
+to me well to illustrate the spirit with which our classifications are
+sometimes necessarily founded.
+</para>
+
+<para>
+Practically when naturalists are at work, they do not trouble themselves
+about the physiological value of the characters which they use in defining
+a group, or in allocating any particular species.  If they find a character
+nearly uniform, and common to a great number of forms, and not common to
+others, they use it as one of high value; if common to some lesser number,
+they use it as of subordinate value.  This principle has been broadly
+confessed by some naturalists to be the true one; and by none more clearly
+than by that excellent botanist, Aug. St. Hilaire.  If certain characters
+are always found correlated with others, though no apparent bond of
+connexion can be discovered between them, especial value is set on them. 
+As in most groups of animals, important organs, such as those for
+propelling the blood, or for aerating it, or those for propagating the
+race, are found nearly uniform, they are considered as highly serviceable
+in classification; but in some groups of animals all these, the most
+important vital organs, are found to offer characters of quite subordinate
+value.
+</para>
+
+<para>
+We can see why characters derived from the embryo should be of equal
+importance with those derived from the adult, for our classifications of
+course include all ages of each species.  But it is by no means obvious, on
+the ordinary view, why the structure of the embryo should be more important
+for this purpose than that of the adult, which alone plays its full part in
+the economy of nature.  Yet it has been strongly urged by those great
+naturalists, Milne Edwards and Agassiz, that embryonic characters are the
+most important of any in the classification of animals; and this doctrine
+has very generally been admitted as true.  The same fact holds good with
+flowering plants, of which the two main divisions have been founded on
+characters derived from the embryo,--on the number and position of the
+embryonic leaves or cotyledons, and on the mode of development of the
+plumule and radicle.  In our discussion on embryology, we shall see why
+such characters are so valuable, on the view of classification tacitly
+including the idea of descent.
+</para>
+
+<para>
+Our classifications are often plainly influenced by chains of affinities. 
+Nothing can be easier than to define a number of characters common to all
+birds; but in the case of crustaceans, such definition has hitherto been
+found impossible.  There are crustaceans at the opposite ends of the
+series, which have hardly a character in common; yet the species at both
+ends, from being plainly allied to others, and these to others, and so
+onwards, can be recognised as unequivocally belonging to this, and to no
+other class of the Articulata.
+</para>
+
+<para>
+Geographical distribution has often been used, though perhaps not quite
+logically, in classification, more especially in very large groups of
+closely allied forms.  Temminck insists on the utility or even necessity of
+this practice in certain groups of birds; and it has been followed by
+several entomologists and botanists.
+</para>
+
+<para>
+Finally, with respect to the comparative value of the various groups of
+species, such as orders, sub-orders, families, sub-families, and genera,
+they seem to be, at least at present, almost arbitrary.  Several of the
+best botanists, such as Mr. Bentham and others, have strongly insisted on
+their arbitrary value.  Instances could be given amongst plants and
+insects, of a group of forms, first ranked by practised naturalists as only
+a genus, and then raised to the rank of a sub-family or family; and this
+has been done, not because further research has detected important
+structural differences, at first overlooked, but because numerous allied
+species, with slightly different grades of difference, have been
+subsequently discovered.
+</para>
+	
+<para>
+All the foregoing rules and aids and difficulties in classification are
+explained, if I do not greatly deceive myself, on the view that the natural
+system is founded on descent with modification; that the characters which
+naturalists consider as showing true affinity between any two or more
+species, are those which have been inherited from a common parent, and, in
+so far, all true classification is genealogical; that community of descent
+is the hidden bond which naturalists have been unconsciously seeking, and
+not some unknown plan of creation, or the enunciation of general
+propositions, and the mere putting together and separating objects more or
+less alike.
+</para>
+
+<para>
+But I must explain my meaning more fully.  I believe that the arrangement
+of the groups within each class, in due subordination and relation to the
+other groups, must be strictly genealogical in order to be natural; but
+that the amount of difference in the several branches or groups, though
+allied in the same degree in blood to their common progenitor, may differ
+greatly, being due to the different degrees of modification which they have
+undergone; and this is expressed by the forms being ranked under different
+genera, families, sections, or orders.  The reader will best understand
+what is meant, if he will take the trouble of referring to the diagram in
+the fourth chapter.  We will suppose the letters A to L to represent allied
+genera, which lived during the Silurian epoch, and these have descended
+from a species which existed at an unknown anterior period.  Species of
+three of these genera (A, F, and I) have transmitted modified descendants
+to the present day, represented by the fifteen genera (a14 to z14) on the
+uppermost horizontal line.  Now all these modified descendants from a
+single species, are represented as related in blood or descent to the same
+degree; they may metaphorically be called cousins to the same millionth
+degree; yet they differ widely and in different degrees from each other. 
+The forms descended from A, now broken up into two or three families,
+constitute a distinct order from those descended from I, also broken up
+into two families.  Nor can the existing species, descended from A, be
+ranked in the same genus with the parent A; or those from I, with the
+parent I.  But the existing genus F14 may be supposed to have been but
+slightly modified; and it will then rank with the parent-genus F; just as
+some few still living organic beings belong to Silurian genera.  So that
+the amount or value of the differences between organic beings all related
+to each other in the same degree in blood, has come to be widely different. 
+Nevertheless their genealogical arrangement remains strictly true, not only
+at the present time, but at each successive period of descent.  All the
+modified descendants from A will have inherited something in common from
+their common parent, as will all the descendants from I; so will it be with
+each subordinate branch of descendants, at each successive period.  If,
+however, we choose to suppose that any of the descendants of A or of I have
+been so much modified as to have more or less completely lost traces of
+their parentage, in this case, their places in a natural classification
+will have been more or less completely lost,--as sometimes seems to have
+occurred with existing organisms.  All the descendants of the genus F,
+along its whole line of descent, are supposed to have been but little
+modified, and they yet form a single genus.  But this genus, though much
+isolated, will still occupy its proper intermediate position; for F
+originally was intermediate in character between A and I, and the several
+genera descended from these two genera will have inherited to a certain
+extent their characters.  This natural arrangement is shown, as far as is
+possible on paper, in the diagram, but in much too simple a manner.  If a
+branching diagram had not been used, and only the names of the groups had
+been written in a linear series, it would have been still less possible to
+have given a natural arrangement; and it is notoriously not possible to
+represent in a series, on a flat surface, the affinities which we discover
+in nature amongst the beings of the same group.  Thus, on the view which I
+hold, the natural system is genealogical in its arrangement, like a
+pedigree; but the degrees of modification which the different groups have
+undergone, have to be expressed by ranking them under different so-called
+genera, sub-families, families, sections, orders, and classes.
+</para>
+
+<para>
+It may be worth while to illustrate this view of classification, by taking
+the case of languages.  If we possessed a perfect pedigree of mankind, a
+genealogical arrangement of the races of man would afford the best
+classification of the various languages now spoken throughout the world;
+and if all extinct languages, and all intermediate and slowly changing
+dialects, had to be included, such an arrangement would, I think, be the
+only possible one.  Yet it might be that some very ancient language had
+altered little, and had given rise to few new languages, whilst others
+(owing to the spreading and subsequent isolation and states of civilisation
+of the several races, descended from a common race) had altered much, and
+had given rise to many new languages and dialects.  The various degrees of
+difference in the languages from the same stock, would have to be expressed
+by groups subordinate to groups; but the proper or even only possible
+arrangement would still be genealogical; and this would be strictly
+natural, as it would connect together all languages, extinct and modern, by
+the closest affinities, and would give the filiation and origin of each
+tongue.
+</para>
+
+<para>
+In confirmation of this view, let us glance at the classification of
+varieties, which are believed or known to have descended from one species. 
+These are grouped under species, with sub-varieties under varieties; and
+with our domestic productions, several other grades of difference are
+requisite, as we have seen with pigeons.  The origin of the existence of
+groups subordinate to groups, is the same with varieties as with species,
+namely, closeness of descent with various degrees of modification.  Nearly
+the same rules are followed in classifying varieties, as with species. 
+Authors have insisted on the necessity of classing varieties on a natural
+instead of an artificial system; we are cautioned, for instance, not to
+class two varieties of the pine-apple together, merely because their fruit,
+though the most important part, happens to be nearly identical; no one puts
+the swedish and common turnips together, though the esculent and thickened
+stems are so similar.  Whatever part is found to be most constant, is used
+in classing varieties:  thus the great agriculturist Marshall says the
+horns are very useful for this purpose with cattle, because they are less
+variable than the shape or colour of the body, &amp;c.; whereas with sheep the
+horns are much less serviceable, because less constant.  In classing
+varieties, I apprehend if we had a real pedigree, a genealogical
+classification would be universally preferred; and it has been attempted by
+some authors.  For we might feel sure, whether there had been more or less
+modification, the principle of inheritance would keep the forms together
+which were allied in the greatest number of points.  In tumbler pigeons,
+though some sub-varieties differ from the others in the important character
+of having a longer beak, yet all are kept together from having the common
+habit of tumbling; but the short-faced breed has nearly or quite lost this
+habit; nevertheless, without any reasoning or thinking on the subject,
+these tumblers are kept in the same group, because allied in blood and
+alike in some other respects.  If it could be proved that the Hottentot had
+descended from the Negro, I think he would be classed under the Negro
+group, however much he might differ in colour and other important
+characters from negroes.
+</para>
+
+<para>
+With species in a state of nature, every naturalist has in fact brought
+descent into his classification; for he includes in his lowest grade, or
+that of a species, the two sexes; and how enormously these sometimes differ
+in the most important characters, is known to every naturalist:  scarcely a
+single fact can be predicated in common of the males and hermaphrodites of
+certain cirripedes, when adult, and yet no one dreams of separating them. 
+The naturalist includes as one species the several larval stages of the
+same individual, however much they may differ from each other and from the
+adult; as he likewise includes the so-called alternate generations of
+Steenstrup, which can only in a technical sense be considered as the same
+individual.  He includes monsters; he includes varieties, not solely
+because they closely resemble the parent-form, but because they are
+descended from it.  He who believes that the cowslip is descended from the
+primrose, or conversely, ranks them together as a single species, and gives
+a single definition.  As soon as three Orchidean forms (Monochanthus,
+Myanthus, and Catasetum), which had previously been ranked as three
+distinct genera, were known to be sometimes produced on the same spike,
+they were immediately included as a single species.  But it may be asked,
+what ought we to do, if it could be proved that one species of kangaroo had
+been produced, by a long course of modification, from a bear?  Ought we to
+rank this one species with bears, and what should we do with the other
+species?  The supposition is of course preposterous; and I might answer by
+the argumentum ad hominem, and ask what should be done if a perfect
+kangaroo were seen to come out of the womb of a bear?  According to all
+analogy, it would be ranked with bears; but then assuredly all the other
+species of the kangaroo family would have to be classed under the bear
+genus.  The whole case is preposterous; for where there has been close
+descent in common, there will certainly be close resemblance or affinity.
+</para>
+
+<para>
+As descent has universally been used in classing together the individuals
+of the same species, though the males and females and larvae are sometimes
+extremely different; and as it has been used in classing varieties which
+have undergone a certain, and sometimes a considerable amount of
+modification, may not this same element of descent have been unconsciously
+used in grouping species under genera, and genera under higher groups,
+though in these cases the modification has been greater in degree, and has
+taken a longer time to complete?  I believe it has thus been unconsciously
+used; and only thus can I understand the several rules and guides which
+have been followed by our best systematists.  We have no written pedigrees;
+we have to make out community of descent by resemblances of any kind. 
+Therefore we choose those characters which, as far as we can judge, are the
+least likely to have been modified in relation to the conditions of life to
+which each species has been recently exposed.  Rudimentary structures on
+this view are as good as, or even sometimes better than, other parts of the
+organisation.  We care not how trifling a character may be--let it be the
+mere inflection of the angle of the jaw, the manner in which an insect's
+wing is folded, whether the skin be covered by hair or feathers--if it
+prevail throughout many and different species, especially those having very
+different habits of life, it assumes high value; for we can account for its
+presence in so many forms with such different habits, only by its
+inheritance from a common parent.  We may err in this respect in regard to
+single points of structure, but when several characters, let them be ever
+so trifling, occur together throughout a large group of beings having
+different habits, we may feel almost sure, on the theory of descent, that
+these characters have been inherited from a common ancestor.  And we know
+that such correlated or aggregated characters have especial value in
+classification.
+</para>
+
+<para>
+We can understand why a species or a group of species may depart, in
+several of its most important characteristics, from its allies, and yet be
+safely classed with them.  This may be safely done, and is often done, as
+long as a sufficient number of characters, let them be ever so unimportant,
+betrays the hidden bond of community of descent.  Let two forms have not a
+single character in common, yet if these extreme forms are connected
+together by a chain of intermediate groups, we may at once infer their
+community of descent, and we put them all into the same class.  As we find
+organs of high physiological importance--those which serve to preserve life
+under the most diverse conditions of existence--are generally the most
+constant, we attach especial value to them; but if these same organs, in
+another group or section of a group, are found to differ much, we at once
+value them less in our classification.  We shall hereafter, I think,
+clearly see why embryological characters are of such high classificatory
+importance.  Geographical distribution may sometimes be brought usefully
+into play in classing large and widely-distributed genera, because all the
+species of the same genus, inhabiting any distinct and isolated region,
+have in all probability descended from the same parents.
+</para>
+
+<para>
+We can understand, on these views, the very important distinction between
+real affinities and analogical or adaptive resemblances.  Lamarck first
+called attention to this distinction, and he has been ably followed by
+Macleay and others.  The resemblance, in the shape of the body and in the
+fin-like anterior limbs, between the dugong, which is a pachydermatous
+animal, and the whale, and between both these mammals and fishes, is
+analogical.  Amongst insects there are innumerable instances:  thus
+Linnaeus, misled by external appearances, actually classed an homopterous
+insect as a moth.  We see something of the same kind even in our domestic
+varieties, as in the thickened stems of the common and swedish turnip.  The
+resemblance of the greyhound and racehorse is hardly more fanciful than the
+analogies which have been drawn by some authors between very distinct
+animals.  On my view of characters being of real importance for
+classification, only in so far as they reveal descent, we can clearly
+understand why analogical or adaptive character, although of the utmost
+importance to the welfare of the being, are almost valueless to the
+systematist.  For animals, belonging to two most distinct lines of descent,
+may readily become adapted to similar conditions, and thus assume a close
+external resemblance; but such resemblances will not reveal--will rather
+tend to conceal their blood-relationship to their proper lines of descent. 
+We can also understand the apparent paradox, that the very same characters
+are analogical when one class or order is compared with another, but give
+true affinities when the members of the same class or order are compared
+one with another:  thus the shape of the body and fin-like limbs are only
+analogical when whales are compared with fishes, being adaptations in both
+classes for swimming through the water; but the shape of the body and
+fin-like limbs serve as characters exhibiting true affinity between the
+several members of the whale family; for these cetaceans agree in so many
+characters, great and small, that we cannot doubt that they have inherited
+their general shape of body and structure of limbs from a common ancestor. 
+So it is with fishes.
+</para>
+
+<para>
+As members of distinct classes have often been adapted by successive slight
+modifications to live under nearly similar circumstances,--to inhabit for
+instance the three elements of land, air, and water,--we can perhaps
+understand how it is that a numerical parallelism has sometimes been
+observed between the sub-groups in distinct classes.  A naturalist, struck
+by a parallelism of this nature in any one class, by arbitrarily raising or
+sinking the value of the groups in other classes (and all our experience
+shows that this valuation has hitherto been arbitrary), could easily extend
+the parallelism over a wide range; and thus the septenary, quinary,
+quaternary, and ternary classifications have probably arisen.
+</para>
+
+<para>
+As the modified descendants of dominant species, belonging to the larger
+genera, tend to inherit the advantages, which made the groups to which they
+belong large and their parents dominant, they are almost sure to spread
+widely, and to seize on more and more places in the economy of nature.  The
+larger and more dominant groups thus tend to go on increasing in size; and
+they consequently supplant many smaller and feebler groups.  Thus we can
+account for the fact that all organisms, recent and extinct, are included
+under a few great orders, under still fewer classes, and all in one great
+natural system.  As showing how few the higher groups are in number, and
+how widely spread they are throughout the world, the fact is striking, that
+the discovery of Australia has not added a single insect belonging to a new
+order; and that in the vegetable kingdom, as I learn from Dr. Hooker, it
+has added only two or three orders of small size.
+</para>
+
+<para>
+In the chapter on geological succession I attempted to show, on the
+principle of each group having generally diverged much in character during
+the long-continued process of modification, how it is that the more ancient
+forms of life often present characters in some slight degree intermediate
+between existing groups.  A few old and intermediate parent-forms having
+occasionally transmitted to the present day descendants but little
+modified, will give to us our so-called osculant or aberrant groups.  The
+more aberrant any form is, the greater must be the number of connecting
+forms which on my theory have been exterminated and utterly lost.  And we
+have some evidence of aberrant forms having suffered severely from
+extinction, for they are generally represented by extremely few species;
+and such species as do occur are generally very distinct from each other,
+which again implies extinction.  The genera Ornithorhynchus and
+Lepidosiren, for example, would not have been less aberrant had each been
+represented by a dozen species instead of by a single one; but such
+richness in species, as I find after some investigation, does not commonly
+fall to the lot of aberrant genera.  We can, I think, account for this fact
+only by looking at aberrant forms as failing groups conquered by more
+successful competitors, with a few members preserved by some unusual
+coincidence of favourable circumstances.
+</para>
+
+<para>
+Mr. Waterhouse has remarked that, when a member belonging to one group of
+animals exhibits an affinity to a quite distinct group, this affinity in
+most cases is general and not special:  thus, according to Mr. Waterhouse,
+of all Rodents, the bizcacha is most nearly related to Marsupials; but in
+the points in which it approaches this order, its relations are general,
+and not to any one marsupial species more than to another.  As the points
+of affinity of the bizcacha to Marsupials are believed to be real and not
+merely adaptive, they are due on my theory to inheritance in common. 
+Therefore we must suppose either that all Rodents, including the bizcacha,
+branched off from some very ancient Marsupial, which will have had a
+character in some degree intermediate with respect to all existing
+Marsupials; or that both Rodents and Marsupials branched off from a common
+progenitor, and that both groups have since undergone much modification in
+divergent directions.  On either view we may suppose that the bizcacha has
+retained, by inheritance, more of the character of its ancient progenitor
+than have other Rodents; and therefore it will not be specially related to
+any one existing Marsupial, but indirectly to all or nearly all Marsupials,
+from having partially retained the character of their common progenitor, or
+of an early member of the group.  On the other hand, of all Marsupials, as
+Mr. Waterhouse has remarked, the phascolomys resembles most nearly, not any
+one species, but the general order of Rodents.  In this case, however, it
+may be strongly suspected that the resemblance is only analogical, owing to
+the phascolomys having become adapted to habits like those of a Rodent. 
+The elder De Candolle has made nearly similar observations on the general
+nature of the affinities of distinct orders of plants.
+</para>
+
+<para>
+On the principle of the multiplication and gradual divergence in character
+of the species descended from a common parent, together with their
+retention by inheritance of some characters in common, we can understand
+the excessively complex and radiating affinities by which all the members
+of the same family or higher group are connected together.  For the common
+parent of a whole family of species, now broken up by extinction into
+distinct groups and sub-groups, will have transmitted some of its
+characters, modified in various ways and degrees, to all; and the several
+species will consequently be related to each other by circuitous lines of
+affinity of various lengths (as may be seen in the diagram so often
+referred to), mounting up through many predecessors.  As it is difficult to
+show the blood-relationship between the numerous kindred of any ancient and
+noble family, even by the aid of a genealogical tree, and almost impossible
+to do this without this aid, we can understand the extraordinary difficulty
+which naturalists have experienced in describing, without the aid of a
+diagram, the various affinities which they perceive between the many living
+and extinct members of the same great natural class.
+</para>
+
+<para>
+Extinction, as we have seen in the fourth chapter, has played an important
+part in defining and widening the intervals between the several groups in
+each class.  We may thus account even for the distinctness of whole classes
+from each other--for instance, of birds from all other vertebrate
+animals--by the belief that many ancient forms of life have been utterly
+lost, through which the early progenitors of birds were formerly connected
+with the early progenitors of the other vertebrate classes.  There has been
+less entire extinction of the forms of life which once connected fishes
+with batrachians.  There has been still less in some other classes, as in
+that of the Crustacea, for here the most wonderfully diverse forms are
+still tied together by a long, but broken, chain of affinities.  Extinction
+has only separated groups:  it has by no means made them; for if every form
+which has ever lived on this earth were suddenly to reappear, though it
+would be quite impossible to give definitions by which each group could be
+distinguished from other groups, as all would blend together by steps as
+fine as those between the finest existing varieties, nevertheless a natural
+classification, or at least a natural arrangement, would be possible.  We
+shall see this by turning to the diagram:  the letters, A to L, may
+represent eleven Silurian genera, some of which have produced large groups
+of modified descendants.  Every intermediate link between these eleven
+genera and their primordial parent, and every intermediate link in each
+branch and sub-branch of their descendants, may be supposed to be still
+alive; and the links to be as fine as those between the finest varieties. 
+In this case it would be quite impossible to give any definition by which
+the several members of the several groups could be distinguished from their
+more immediate parents; or these parents from their ancient and unknown
+progenitor.  Yet the natural arrangement in the diagram would still hold
+good; and, on the principle of inheritance, all the forms descended from A,
+or from I, would have something in common.  In a tree we can specify this
+or that branch, though at the actual fork the two unite and blend together. 
+We could not, as I have said, define the several groups; but we could pick
+out types, or forms, representing most of the characters of each group,
+whether large or small, and thus give a general idea of the value of the
+differences between them.  This is what we should be driven to, if we were
+ever to succeed in collecting all the forms in any class which have lived
+throughout all time and space.  We shall certainly never succeed in making
+so perfect a collection:  nevertheless, in certain classes, we are tending
+in this direction; and Milne Edwards has lately insisted, in an able paper,
+on the high importance of looking to types, whether or not we can separate
+and define the groups to which such types belong.
+</para>
+
+<para>
+Finally, we have seen that natural selection, which results from the
+struggle for existence, and which almost inevitably induces extinction and
+divergence of character in the many descendants from one dominant
+parent-species, explains that great and universal feature in the affinities
+of all organic beings, namely, their subordination in group under group. 
+We use the element of descent in classing the individuals of both sexes and
+of all ages, although having few characters in common, under one species;
+we use descent in classing acknowledged varieties, however different they
+may be from their parent; and I believe this element of descent is the
+hidden bond of connexion which naturalists have sought under the term of
+the Natural System.  On this idea of the natural system being, in so far as
+it has been perfected, genealogical in its arrangement, with the grades of
+difference between the descendants from a common parent, expressed by the
+terms genera, families, orders, &amp;c., we can understand the rules which we
+are compelled to follow in our classification.  We can understand why we
+value certain resemblances far more than others; why we are permitted to
+use rudimentary and useless organs, or others of trifling physiological
+importance; why, in comparing one group with a distinct group, we summarily
+reject analogical or adaptive characters, and yet use these same characters
+within the limits of the same group.  We can clearly see how it is that all
+living and extinct forms can be grouped together in one great system; and
+how the several members of each class are connected together by the most
+complex and radiating lines of affinities.  We shall never, probably,
+disentangle the inextricable web of affinities between the members of any
+one class; but when we have a distinct object in view, and do not look to
+some unknown plan of creation, we may hope to make sure but slow progress.
+</para>
+
+<para>
+Morphology. -- We have seen that the members of the same class,
+independently of their habits of life, resemble each other in the general
+plan of their organisation.  This resemblance is often expressed by the
+term 'unity of type;' or by saying that the several parts and organs in the
+different species of the class are homologous.  The whole subject is
+included under the general name of Morphology.  This is the most
+interesting department of natural history, and may be said to be its very
+soul.  What can be more curious than that the hand of a man, formed for
+grasping, that of a mole for digging, the leg of the horse, the paddle of
+the porpoise, and the wing of the bat, should all be constructed on the
+same pattern, and should include the same bones, in the same relative
+positions?  Geoffroy St. Hilaire has insisted strongly on the high
+importance of relative connexion in homologous organs:  the parts may
+change to almost any extent in form and size, and yet they always remain
+connected together in the same order.  We never find, for instance, the
+bones of the arm and forearm, or of the thigh and leg, transposed.  Hence
+the same names can be given to the homologous bones in widely different
+animals.  We see the same great law in the construction of the mouths of
+insects:  what can be more different than the immensely long spiral
+proboscis of a sphinx-moth, the curious folded one of a bee or bug, and the
+great jaws of a beetle?--yet all these organs, serving for such different
+purposes, are formed by infinitely numerous modifications of an upper lip,
+mandibles, and two pairs of maxillae.  Analogous laws govern the
+construction of the mouths and limbs of crustaceans.  So it is with the
+flowers of plants.
+</para>
+
+<para>
+Nothing can be more hopeless than to attempt to explain this similarity of
+pattern in members of the same class, by utility or by the doctrine of
+final causes.  The hopelessness of the attempt has been expressly admitted
+by Owen in his most interesting work on the 'Nature of Limbs.'  On the
+ordinary view of the independent creation of each being, we can only say
+that so it is;--that it has so pleased the Creator to construct each animal
+and plant.
+</para>
+
+<para>
+The explanation is manifest on the theory of the natural selection of
+successive slight modifications,--each modification being profitable in
+some way to the modified form, but often affecting by correlation of growth
+other parts of the organisation.  In changes of this nature, there will be
+little or no tendency to modify the original pattern, or to transpose
+parts.  The bones of a limb might be shortened and widened to any extent,
+and become gradually enveloped in thick membrane, so as to serve as a fin;
+or a webbed foot might have all its bones, or certain bones, lengthened to
+any extent, and the membrane connecting them increased to any extent, so as
+to serve as a wing:  yet in all this great amount of modification there
+will be no tendency to alter the framework of bones or the relative
+connexion of the several parts.  If we suppose that the ancient progenitor,
+the archetype as it may be called, of all mammals, had its limbs
+constructed on the existing general pattern, for whatever purpose they
+served, we can at once perceive the plain signification of the homologous
+construction of the limbs throughout the whole class.  So with the mouths
+of insects, we have only to suppose that their common progenitor had an
+upper lip, mandibles, and two pair of maxillae, these parts being perhaps
+very simple in form; and then natural selection will account for the
+infinite diversity in structure and function of the mouths of insects. 
+Nevertheless, it is conceivable that the general pattern of an organ might
+become so much obscured as to be finally lost, by the atrophy and
+ultimately by the complete abortion of certain parts, by the soldering
+together of other parts, and by the doubling or multiplication of
+others,--variations which we know to be within the limits of possibility. 
+In the paddles of the extinct gigantic sea-lizards, and in the mouths of
+certain suctorial crustaceans, the general pattern seems to have been thus
+to a certain extent obscured.
+</para>
+
+<para>
+There is another and equally curious branch of the present subject; namely,
+the comparison not of the same part in different members of a class, but of
+the different parts or organs in the same individual.  Most physiologists
+believe that the bones of the skull are homologous with--that is correspond
+in number and in relative connexion with--the elemental parts of a certain
+number of vertebrae.  The anterior and posterior limbs in each member of
+the vertebrate and articulate classes are plainly homologous.  We see the
+same law in comparing the wonderfully complex jaws and legs in crustaceans. 
+It is familiar to almost every one, that in a flower the relative position
+of the sepals, petals, stamens, and pistils, as well as their intimate
+structure, are intelligible on the view that they consist of metamorphosed
+leaves, arranged in a spire.  In monstrous plants, we often get direct
+evidence of the possibility of one organ being transformed into another;
+and we can actually see in embryonic crustaceans and in many other animals,
+and in flowers, that organs, which when mature become extremely different,
+are at an early stage of growth exactly alike.
+</para>
+
+<para>
+How inexplicable are these facts on the ordinary view of creation!  Why
+should the brain be enclosed in a box composed of such numerous and such
+extraordinarily shaped pieces of bone?  As Owen has remarked, the benefit
+derived from the yielding of the separate pieces in the act of parturition
+of mammals, will by no means explain the same construction in the skulls of
+birds.  Why should similar bones have been created in the formation of the
+wing and leg of a bat, used as they are for such totally different
+purposes?  Why should one crustacean, which has an extremely complex mouth
+formed of many parts, consequently always have fewer legs; or conversely,
+those with many legs have simpler mouths?  Why should the sepals, petals,
+stamens, and pistils in any individual flower, though fitted for such
+widely different purposes, be all constructed on the same pattern?
+</para>
+
+<para>
+On the theory of natural selection, we can satisfactorily answer these
+questions.  In the vertebrata, we see a series of internal vertebrae
+bearing certain processes and appendages; in the articulata, we see the
+body divided into a series of segments, bearing external appendages; and in
+flowering plants, we see a series of successive spiral whorls of leaves. 
+An indefinite repetition of the same part or organ is the common
+characteristic (as Owen has observed) of all low or little-modified forms;
+therefore we may readily believe that the unknown progenitor of the
+vertebrata possessed many vertebrae; the unknown progenitor of the
+articulata, many segments; and the unknown progenitor of flowering plants,
+many spiral whorls of leaves.  We have formerly seen that parts many times
+repeated are eminently liable to vary in number and structure; consequently
+it is quite probable that natural selection, during a long-continued course
+of modification, should have seized on a certain number of the primordially
+similar elements, many times repeated, and have adapted them to the most
+diverse purposes.  And as the whole amount of modification will have been
+effected by slight successive steps, we need not wonder at discovering in
+such parts or organs, a certain degree of fundamental resemblance, retained
+by the strong principle of inheritance.
+</para>
+
+<para>
+In the great class of molluscs, though we can homologise the parts of one
+species with those of another and distinct species, we can indicate but few
+serial homologies; that is, we are seldom enabled to say that one part or
+organ is homologous with another in the same individual.  And we can
+understand this fact; for in molluscs, even in the lowest members of the
+class, we do not find nearly so much indefinite repetition of any one part,
+as we find in the other great classes of the animal and vegetable kingdoms.
+</para>
+
+<para>
+Naturalists frequently speak of the skull as formed of metamorphosed
+vertebrae:  the jaws of crabs as metamorphosed legs; the stamens and
+pistils of flowers as metamorphosed leaves; but it would in these cases
+probably be more correct, as Professor Huxley has remarked, to speak of
+both skull and vertebrae, both jaws and legs, &amp;c.,--as having been
+metamorphosed, not one from the other, but from some common element. 
+Naturalists, however, use such language only in a metaphorical sense:  they
+are far from meaning that during a long course of descent, primordial
+organs of any kind--vertebrae in the one case and legs in the other--have
+actually been modified into skulls or jaws.  Yet so strong is the
+appearance of a modification of this nature having occurred, that
+naturalists can hardly avoid employing language having this plain
+signification.  On my view these terms may be used literally; and the
+wonderful fact of the jaws, for instance, of a crab retaining numerous
+characters, which they would probably have retained through inheritance, if
+they had really been metamorphosed during a long course of descent from
+true legs, or from some simple appendage, is explained.
+</para>
+
+<para>
+Embryology. -- It has already been casually remarked that certain organs in
+the individual, which when mature become widely different and serve for
+different purposes, are in the embryo exactly alike.  The embryos, also, of
+distinct animals within the same class are often strikingly similar:  a
+better proof of this cannot be given, than a circumstance mentioned by
+Agassiz, namely, that having forgotten to ticket the embryo of some
+vertebrate animal, he cannot now tell whether it be that of a mammal, bird,
+or reptile.  The vermiform larvae of moths, flies, beetles, &amp;c., resemble
+each other much more closely than do the mature insects; but in the case of
+larvae, the embryos are active, and have been adapted for special lines of
+life.  A trace of the law of embryonic resemblance, sometimes lasts till a
+rather late age:  thus birds of the same genus, and of closely allied
+genera, often resemble each other in their first and second plumage; as we
+see in the spotted feathers in the thrush group.  In the cat tribe, most of
+the species are striped or spotted in lines; and stripes can be plainly
+distinguished in the whelp of the lion.  We occasionally though rarely see
+something of this kind in plants:  thus the embryonic leaves of the ulex or
+furze, and the first leaves of the phyllodineous acaceas, are pinnate or
+divided like the ordinary leaves of the leguminosae.
+</para>
+
+<para>
+The points of structure, in which the embryos of widely different animals
+of the same class resemble each other, often have no direct relation to
+their conditions of existence.  We cannot, for instance, suppose that in
+the embryos of the vertebrata the peculiar loop-like course of the arteries
+near the branchial slits are related to similar conditions,--in the young
+mammal which is nourished in the womb of its mother, in the egg of the bird
+which is hatched in a nest, and in the spawn of a frog under water.  We
+have no more reason to believe in such a relation, than we have to believe
+that the same bones in the hand of a man, wing of a bat, and fin of a
+porpoise, are related to similar conditions of life.  No one will suppose
+that the stripes on the whelp of a lion, or the spots on the young
+blackbird, are of any use to these animals, or are related to the
+conditions to which they are exposed.
+</para>
+
+<para>
+The case, however, is different when an animal during any part of its
+embryonic career is active, and has to provide for itself.  The period of
+activity may come on earlier or later in life; but whenever it comes on,
+the adaptation of the larva to its conditions of life is just as perfect
+and as beautiful as in the adult animal.  From such special adaptations,
+the similarity of the larvae or active embryos of allied animals is
+sometimes much obscured; and cases could be given of the larvae of two
+species, or of two groups of species, differing quite as much, or even
+more, from each other than do their adult parents.  In most cases, however,
+the larvae, though active, still obey more or less closely the law of
+common embryonic resemblance.  Cirripedes afford a good instance of this: 
+even the illustrious Cuvier did not perceive that a barnacle was, as it
+certainly is, a crustacean; but a glance at the larva shows this to be the
+case in an unmistakeable manner.  So again the two main divisions of
+cirripedes, the pedunculated and sessile, which differ widely in external
+appearance, have larvae in all their several stages barely distinguishable.
+</para>
+
+<para>
+The embryo in the course of development generally rises in organisation:  I
+use this expression, though I am aware that it is hardly possible to define
+clearly what is meant by the organisation being higher or lower.  But no
+one probably will dispute that the butterfly is higher than the
+caterpillar.  In some cases, however, the mature animal is generally
+considered as lower in the scale than the larva, as with certain parasitic
+crustaceans.  To refer once again to cirripedes:  the larvae in the first
+stage have three pairs of legs, a very simple single eye, and a
+probosciformed mouth, with which they feed largely, for they increase much
+in size.  In the second stage, answering to the chrysalis stage of
+butterflies, they have six pairs of beautifully constructed natatory legs,
+a pair of magnificent compound eyes, and extremely complex antennae; but
+they have a closed and imperfect mouth, and cannot feed:  their function at
+this stage is, to search by their well-developed organs of sense, and to
+reach by their active powers of swimming, a proper place on which to become
+attached and to undergo their final metamorphosis.  When this is completed
+they are fixed for life:  their legs are now converted into prehensile
+organs; they again obtain a well-constructed mouth; but they have no
+antennae, and their two eyes are now reconverted into a minute, single, and
+very simple eye-spot.  In this last and complete state, cirripedes may be
+considered as either more highly or more lowly organised than they were in
+the larval condition.  But in some genera the larvae become developed
+either into hermaphrodites having the ordinary structure, or into what I
+have called complemental males:  and in the latter, the development has
+assuredly been retrograde; for the male is a mere sack, which lives for a
+short time, and is destitute of mouth, stomach, or other organ of
+importance, excepting for reproduction.
+</para>
+
+<para>
+We are so much accustomed to see differences in structure between the
+embryo and the adult, and likewise a close similarity in the embryos of
+widely different animals within the same class, that we might be led to
+look at these facts as necessarily contingent in some manner on growth. 
+But there is no obvious reason why, for instance, the wing of a bat, or the
+fin of a porpoise, should not have been sketched out with all the parts in
+proper proportion, as soon as any structure became visible in the embryo. 
+And in some whole groups of animals and in certain members of other groups,
+the embryo does not at any period differ widely from the adult:  thus Owen
+has remarked in regard to cuttle-fish, 'there is no metamorphosis; the
+cephalopodic character is manifested long before the parts of the embryo
+are completed;' and again in spiders, 'there is nothing worthy to be called
+a metamorphosis.'  The larvae of insects, whether adapted to the most
+diverse and active habits, or quite inactive, being fed by their parents or
+placed in the midst of proper nutriment, yet nearly all pass through a
+similar worm-like stage of development; but in some few cases, as in that
+of Aphis, if we look to the admirable drawings by Professor Huxley of the
+development of this insect, we see no trace of the vermiform stage.
+</para>
+
+<para>
+How, then, can we explain these several facts in embryology,--namely the
+very general, but not universal difference in structure between the embryo
+and the adult;--of parts in the same individual embryo, which ultimately
+become very unlike and serve for diverse purposes, being at this early
+period of growth alike;--of embryos of different species within the same
+class, generally, but not universally, resembling each other;--of the
+structure of the embryo not being closely related to its conditions of
+existence, except when the embryo becomes at any period of life active and
+has to provide for itself;--of the embryo apparently having sometimes a
+higher organisation than the mature animal, into which it is developed.  I
+believe that all these facts can be explained, as follows, on the view of
+descent with modification.
+</para>
+
+<para>
+It is commonly assumed, perhaps from monstrosities often affecting the
+embryo at a very early period, that slight variations necessarily appear at
+an equally early period.  But we have little evidence on this head--indeed
+the evidence rather points the other way; for it is notorious that breeders
+of cattle, horses, and various fancy animals, cannot positively tell, until
+some time after the animal has been born, what its merits or form will
+ultimately turn out.  We see this plainly in our own children; we cannot
+always tell whether the child will be tall or short, or what its precise
+features will be.  The question is not, at what period of life any
+variation has been caused, but at what period it is fully displayed.  The
+cause may have acted, and I believe generally has acted, even before the
+embryo is formed; and the variation may be due to the male and female
+sexual elements having been affected by the conditions to which either
+parent, or their ancestors, have been exposed.  Nevertheless an effect thus
+caused at a very early period, even before the formation of the embryo, may
+appear late in life; as when an hereditary disease, which appears in old
+age alone, has been communicated to the offspring from the reproductive
+element of one parent.  Or again, as when the horns of cross-bred cattle
+have been affected by the shape of the horns of either parent.  For the
+welfare of a very young animal, as long as it remains in its mother's womb,
+or in the egg, or as long as it is nourished and protected by its parent,
+it must be quite unimportant whether most of its characters are fully
+acquired a little earlier or later in life.  It would not signify, for
+instance, to a bird which obtained its food best by having a long beak,
+whether or not it assumed a beak of this particular length, as long as it
+was fed by its parents.  Hence, I conclude, that it is quite possible, that
+each of the many successive modifications, by which each species has
+acquired its present structure, may have supervened at a not very early
+period of life; and some direct evidence from our domestic animals supports
+this view.  But in other cases it is quite possible that each successive
+modification, or most of them, may have appeared at an extremely early
+period.
+</para>
+
+<para>
+I have stated in the first chapter, that there is some evidence to render
+it probable, that at whatever age any variation first appears in the
+parent, it tends to reappear at a corresponding age in the offspring. 
+Certain variations can only appear at corresponding ages, for instance,
+peculiarities in the caterpillar, cocoon, or imago states of the silk-moth;
+or, again, in the horns of almost full-grown cattle.  But further than
+this, variations which, for all that we can see, might have appeared
+earlier or later in life, tend to appear at a corresponding age in the
+offspring and parent.  I am far from meaning that this is invariably the
+case; and I could give a good many cases of variations (taking the word in
+the largest sense) which have supervened at an earlier age in the child
+than in the parent.
+</para>
+
+<para>
+These two principles, if their truth be admitted, will, I believe, explain
+all the above specified leading facts in embryology.  But first let us look
+at a few analogous cases in domestic varieties.  Some authors who have
+written on Dogs, maintain that the greyhound and bulldog, though appearing
+so different, are really varieties most closely allied, and have probably
+descended from the same wild stock; hence I was curious to see how far
+their puppies differed from each other:  I was told by breeders that they
+differed just as much as their parents, and this, judging by the eye,
+seemed almost to be the case; but on actually measuring the old dogs and
+their six-days old puppies, I found that the puppies had not nearly
+acquired their full amount of proportional difference.  So, again, I was
+told that the foals of cart and race-horses differed as much as the
+full-grown animals; and this surprised me greatly, as I think it probable
+that the difference between these two breeds has been wholly caused by
+selection under domestication; but having had careful measurements made of
+the dam and of a three-days old colt of a race and heavy cart-horse, I find
+that the colts have by no means acquired their full amount of proportional
+difference.
+</para>
+
+<para>
+As the evidence appears to me conclusive, that the several domestic breeds
+of Pigeon have descended from one wild species, I compared young pigeons of
+various breeds, within twelve hours after being hatched; I carefully
+measured the proportions (but will not here give details) of the beak,
+width of mouth, length of nostril and of eyelid, size of feet and length of
+leg, in the wild stock, in pouters, fantails, runts, barbs, dragons,
+carriers, and tumblers.  Now some of these birds, when mature, differ so
+extraordinarily in length and form of beak, that they would, I cannot
+doubt, be ranked in distinct genera, had they been natural productions. 
+But when the nestling birds of these several breeds were placed in a row,
+though most of them could be distinguished from each other, yet their
+proportional differences in the above specified several points were
+incomparably less than in the full-grown birds.  Some characteristic points
+of difference--for instance, that of the width of mouth--could hardly be
+detected in the young.  But there was one remarkable exception to this
+rule, for the young of the short-faced tumbler differed from the young of
+the wild rock-pigeon and of the other breeds, in all its proportions,
+almost exactly as much as in the adult state.
+</para>
+
+<para>
+The two principles above given seem to me to explain these facts in regard
+to the later embryonic stages of our domestic varieties.  Fanciers select
+their horses, dogs, and pigeons, for breeding, when they are nearly grown
+up:  they are indifferent whether the desired qualities and structures have
+been acquired earlier or later in life, if the full-grown animal possesses
+them.  And the cases just given, more especially that of pigeons, seem to
+show that the characteristic differences which give value to each breed,
+and which have been accumulated by man's selection, have not generally
+first appeared at an early period of life, and have been inherited by the
+offspring at a corresponding not early period.  But the case of the
+short-faced tumbler, which when twelve hours old had acquired its proper
+proportions, proves that this is not the universal rule; for here the
+characteristic differences must either have appeared at an earlier period
+than usual, or, if not so, the differences must have been inherited, not at
+the corresponding, but at an earlier age.
+</para>
+
+<para>
+Now let us apply these facts and the above two principles--which latter,
+though not proved true, can be shown to be in some degree probable--to
+species in a state of nature.  Let us take a genus of birds, descended on
+my theory from some one parent-species, and of which the several new
+species have become modified through natural selection in accordance with
+their diverse habits.  Then, from the many slight successive steps of
+variation having supervened at a rather late age, and having been inherited
+at a corresponding age, the young of the new species of our supposed genus
+will manifestly tend to resemble each other much more closely than do the
+adults, just as we have seen in the case of pigeons.  We may extend this
+view to whole families or even classes.  The fore-limbs, for instance,
+which served as legs in the parent-species, may become, by a long course of
+modification, adapted in one descendant to act as hands, in another as
+paddles, in another as wings; and on the above two principles--namely of
+each successive modification supervening at a rather late age, and being
+inherited at a corresponding late age--the fore-limbs in the embryos of the
+several descendants of the parent-species will still resemble each other
+closely, for they will not have been modified.  But in each individual new
+species, the embryonic fore-limbs will differ greatly from the fore-limbs
+in the mature animal; the limbs in the latter having undergone much
+modification at a rather late period of life, and having thus been
+converted into hands, or paddles, or wings.  Whatever influence
+long-continued exercise or use on the one hand, and disuse on the other,
+may have in modifying an organ, such influence will mainly affect the
+mature animal, which has come to its full powers of activity and has to
+gain its own living; and the effects thus produced will be inherited at a
+corresponding mature age.  Whereas the young will remain unmodified, or be
+modified in a lesser degree, by the effects of use and disuse.
+</para>
+
+<para>
+In certain cases the successive steps of variation might supervene, from
+causes of which we are wholly ignorant, at a very early period of life, or
+each step might be inherited at an earlier period than that at which it
+first appeared.  In either case (as with the short-faced tumbler) the young
+or embryo would closely resemble the mature parent-form.  We have seen that
+this is the rule of development in certain whole groups of animals, as with
+cuttle-fish and spiders, and with a few members of the great class of
+insects, as with Aphis.  With respect to the final cause of the young in
+these cases not undergoing any metamorphosis, or closely resembling their
+parents from their earliest age, we can see that this would result from the
+two following contingencies; firstly, from the young, during a course of
+modification carried on for many generations, having to provide for their
+own wants at a very early stage of development, and secondly, from their
+following exactly the same habits of life with their parents; for in this
+case, it would be indispensable for the existence of the species, that the
+child should be modified at a very early age in the same manner with its
+parents, in accordance with their similar habits.  Some further
+explanation, however, of the embryo not undergoing any metamorphosis is
+perhaps requisite.  If, on the other hand, it profited the young to follow
+habits of life in any degree different from those of their parent, and
+consequently to be constructed in a slightly different manner, then, on the
+principle of inheritance at corresponding ages, the active young or larvae
+might easily be rendered by natural selection different to any conceivable
+extent from their parents.  Such differences might, also, become correlated
+with successive stages of development; so that the larvae, in the first
+stage, might differ greatly from the larvae in the second stage, as we have
+seen to be the case with cirripedes.  The adult might become fitted for
+sites or habits, in which organs of locomotion or of the senses, &amp;c., would
+be useless; and in this case the final metamorphosis would be said to be
+retrograde.
+</para>
+
+<para>
+As all the organic beings, extinct and recent, which have ever lived on
+this earth have to be classed together, and as all have been connected by
+the finest gradations, the best, or indeed, if our collections were nearly
+perfect, the only possible arrangement, would be genealogical.  Descent
+being on my view the hidden bond of connexion which naturalists have been
+seeking under the term of the natural system.  On this view we can
+understand how it is that, in the eyes of most naturalists, the structure
+of the embryo is even more important for classification than that of the
+adult.  For the embryo is the animal in its less modified state; and in so
+far it reveals the structure of its progenitor.  In two groups of animal,
+however much they may at present differ from each other in structure and
+habits, if they pass through the same or similar embryonic stages, we may
+feel assured that they have both descended from the same or nearly similar
+parents, and are therefore in that degree closely related.  Thus, community
+in embryonic structure reveals community of descent.  It will reveal this
+community of descent, however much the structure of the adult may have been
+modified and obscured; we have seen, for instance, that cirripedes can at
+once be recognised by their larvae as belonging to the great class of
+crustaceans.  As the embryonic state of each species and group of species
+partially shows us the structure of their less modified ancient
+progenitors, we can clearly see why ancient and extinct forms of life
+should resemble the embryos of their descendants,--our existing species. 
+Agassiz believes this to be a law of nature; but I am bound to confess that
+I only hope to see the law hereafter proved true.  It can be proved true in
+those cases alone in which the ancient state, now supposed to be
+represented in many embryos, has not been obliterated, either by the
+successive variations in a long course of modification having supervened at
+a very early age, or by the variations having been inherited at an earlier
+period than that at which they first appeared.  It should also be borne in
+mind, that the supposed law of resemblance of ancient forms of life to the
+embryonic stages of recent forms, may be true, but yet, owing to the
+geological record not extending far enough back in time, may remain for a
+long period, or for ever, incapable of demonstration.
+</para>
+
+<para>
+Thus, as it seems to me, the leading facts in embryology, which are second
+in importance to none in natural history, are explained on the principle of
+slight modifications not appearing, in the many descendants from some one
+ancient progenitor, at a very early period in the life of each, though
+perhaps caused at the earliest, and being inherited at a corresponding not
+early period.  Embryology rises greatly in interest, when we thus look at
+the embryo as a picture, more or less obscured, of the common parent-form
+of each great class of animals.
+</para>
+
+<para>
+Rudimentary, atrophied, or aborted organs. -- Organs or parts in this
+strange condition, bearing the stamp of inutility, are extremely common
+throughout nature.  For instance, rudimentary mammae are very general in
+the males of mammals:  I presume that the 'bastard-wing' in birds may be
+safely considered as a digit in a rudimentary state:  in very many snakes
+one lobe of the lungs is rudimentary; in other snakes there are rudiments
+of the pelvis and hind limbs.  Some of the cases of rudimentary organs are
+extremely curious; for instance, the presence of teeth in foetal whales,
+which when grown up have not a tooth in their heads; and the presence of
+teeth, which never cut through the gums, in the upper jaws of our unborn
+calves.  It has even been stated on good authority that rudiments of teeth
+can be detected in the beaks of certain embryonic birds.  Nothing can be
+plainer than that wings are formed for flight, yet in how many insects do
+we see wings so reduced in size as to be utterly incapable of flight, and
+not rarely lying under wing-cases, firmly soldered together!
+</para>
+
+<para>
+The meaning of rudimentary organs is often quite unmistakeable:  for
+instance there are beetles of the same genus (and even of the same species)
+resembling each other most closely in all respects, one of which will have
+full-sized wings, and another mere rudiments of membrane; and here it is
+impossible to doubt, that the rudiments represent wings.  Rudimentary
+organs sometimes retain their potentiality, and are merely not developed: 
+this seems to be the case with the mammae of male mammals, for many
+instances are on record of these organs having become well developed in
+full-grown males, and having secreted milk.  So again there are normally
+four developed and two rudimentary teats in the udders of the genus Bos,
+but in our domestic cows the two sometimes become developed and give milk. 
+In individual plants of the same species the petals sometimes occur as mere
+rudiments, and sometimes in a well-developed state.  In plants with
+separated sexes, the male flowers often have a rudiment of a pistil; and
+Kolreuter found that by crossing such male plants with an hermaphrodite
+species, the rudiment of the pistil in the hybrid offspring was much
+increased in size; and this shows that the rudiment and the perfect pistil
+are essentially alike in nature.
+</para>
+
+<para>
+An organ serving for two purposes, may become rudimentary or utterly
+aborted for one, even the more important purpose; and remain perfectly
+efficient for the other.  Thus in plants, the office of the pistil is to
+allow the pollen-tubes to reach the ovules protected in the ovarium at its
+base.  The pistil consists of a stigma supported on the style; but in some
+Compositae, the male florets, which of course cannot be fecundated, have a
+pistil, which is in a rudimentary state, for it is not crowned with a
+stigma; but the style remains well developed, and is clothed with hairs as
+in other compositae, for the purpose of brushing the pollen out of the
+surrounding anthers.  Again, an organ may become rudimentary for its proper
+purpose, and be used for a distinct object:  in certain fish the
+swim-bladder seems to be rudimentary for its proper function of giving
+buoyancy, but has become converted into a nascent breathing organ or lung. 
+Other similar instances could be given.
+</para>
+
+<para>
+Rudimentary organs in the individuals of the same species are very liable
+to vary in degree of development and in other respects.  Moreover, in
+closely allied species, the degree to which the same organ has been
+rendered rudimentary occasionally differs much.  This latter fact is well
+exemplified in the state of the wings of the female moths in certain
+groups.  Rudimentary organs may be utterly aborted; and this implies, that
+we find in an animal or plant no trace of an organ, which analogy would
+lead us to expect to find, and which is occasionally found in monstrous
+individuals of the species.  Thus in the snapdragon (antirrhinum) we
+generally do not find a rudiment of a fifth stamen; but this may sometimes
+be seen.  In tracing the homologies of the same part in different members
+of a class, nothing is more common, or more necessary, than the use and
+discovery of rudiments.  This is well shown in the drawings given by Owen
+of the bones of the leg of the horse, ox, and rhinoceros.
+</para>
+
+<para>
+It is an important fact that rudimentary organs, such as teeth in the upper
+jaws of whales and ruminants, can often be detected in the embryo, but
+afterwards wholly disappear.  It is also, I believe, a universal rule, that
+a rudimentary part or organ is of greater size relatively to the adjoining
+parts in the embryo, than in the adult; so that the organ at this early age
+is less rudimentary, or even cannot be said to be in any degree
+rudimentary.  Hence, also, a rudimentary organ in the adult, is often said
+to have retained its embryonic condition.
+</para>
+
+<para>
+I have now given the leading facts with respect to rudimentary organs.  In
+reflecting on them, every one must be struck with astonishment:  for the
+same reasoning power which tells us plainly that most parts and organs are
+exquisitely adapted for certain purposes, tells us with equal plainness
+that these rudimentary or atrophied organs, are imperfect and useless.  In
+works on natural history rudimentary organs are generally said to have been
+created 'for the sake of symmetry,' or in order 'to complete the scheme of
+nature;' but this seems to me no explanation, merely a restatement of the
+fact.  Would it be thought sufficient to say that because planets revolve
+in elliptic courses round the sun, satellites follow the same course round
+the planets, for the sake of symmetry, and to complete the scheme of
+nature?  An eminent physiologist accounts for the presence of rudimentary
+organs, by supposing that they serve to excrete matter in excess, or
+injurious to the system; but can we suppose that the minute papilla, which
+often represents the pistil in male flowers, and which is formed merely of
+cellular tissue, can thus act?  Can we suppose that the formation of
+rudimentary teeth which are subsequently absorbed, can be of any service to
+the rapidly growing embryonic calf by the excretion of precious phosphate
+of lime?  When a man's fingers have been amputated, imperfect nails
+sometimes appear on the stumps:  I could as soon believe that these
+vestiges of nails have appeared, not from unknown laws of growth, but in
+order to excrete horny matter, as that the rudimentary nails on the fin of
+the manatee were formed for this purpose.
+</para>
+
+<para>
+On my view of descent with modification, the origin of rudimentary organs
+is simple.  We have plenty of cases of rudimentary organs in our domestic
+productions,--as the stump of a tail in tailless breeds,--the vestige of an
+ear in earless breeds,--the reappearance of minute dangling horns in
+hornless breeds of cattle, more especially, according to Youatt, in young
+animals,--and the state of the whole flower in the cauliflower.  We often
+see rudiments of various parts in monsters.  But I doubt whether any of
+these cases throw light on the origin of rudimentary organs in a state of
+nature, further than by showing that rudiments can be produced; for I doubt
+whether species under nature ever undergo abrupt changes.  I believe that
+disuse has been the main agency; that it has led in successive generations
+to the gradual reduction of various organs, until they have become
+rudimentary,--as in the case of the eyes of animals inhabiting dark
+caverns, and of the wings of birds inhabiting oceanic islands, which have
+seldom been forced to take flight, and have ultimately lost the power of
+flying.  Again, an organ useful under certain conditions, might become
+injurious under others, as with the wings of beetles living on small and
+exposed islands; and in this case natural selection would continue slowly
+to reduce the organ, until it was rendered harmless and rudimentary.
+</para>
+
+<para>
+Any change in function, which can be effected by insensibly small steps, is
+within the power of natural selection; so that an organ rendered, during
+changed habits of life, useless or injurious for one purpose, might easily
+be modified and used for another purpose.  Or an organ might be retained
+for one alone of its former functions.  An organ, when rendered useless,
+may well be variable, for its variations cannot be checked by natural
+selection.  At whatever period of life disuse or selection reduces an
+organ, and this will generally be when the being has come to maturity and
+to its full powers of action, the principle of inheritance at corresponding
+ages will reproduce the organ in its reduced state at the same age, and
+consequently will seldom affect or reduce it in the embryo.  Thus we can
+understand the greater relative size of rudimentary organs in the embryo,
+and their lesser relative size in the adult.  But if each step of the
+process of reduction were to be inherited, not at the corresponding age,
+but at an extremely early period of life (as we have good reason to believe
+to be possible) the rudimentary part would tend to be wholly lost, and we
+should have a case of complete abortion.  The principle, also, of economy,
+explained in a former chapter, by which the materials forming any part or
+structure, if not useful to the possessor, will be saved as far as is
+possible, will probably often come into play; and this will tend to cause
+the entire obliteration of a rudimentary organ.
+</para>
+
+<para>
+As the presence of rudimentary organs is thus due to the tendency in every
+part of the organisation, which has long existed, to be inherited--we can
+understand, on the genealogical view of classification, how it is that
+systematists have found rudimentary parts as useful as, or even sometimes
+more useful than, parts of high physiological importance.  Rudimentary
+organs may be compared with the letters in a word, still retained in the
+spelling, but become useless in the pronunciation, but which serve as a
+clue in seeking for its derivation.  On the view of descent with
+modification, we may conclude that the existence of organs in a
+rudimentary, imperfect, and useless condition, or quite aborted, far from
+presenting a strange difficulty, as they assuredly do on the ordinary
+doctrine of creation, might even have been anticipated, and can be
+accounted for by the laws of inheritance.
+</para>
+
+<para>
+Summary. -- In this chapter I have attempted to show, that the
+subordination of group to group in all organisms throughout all time; that
+the nature of the relationship, by which all living and extinct beings are
+united by complex, radiating, and circuitous lines of affinities into one
+grand system; the rules followed and the difficulties encountered by
+naturalists in their classifications; the value set upon characters, if
+constant and prevalent, whether of high vital importance, or of the most
+trifling importance, or, as in rudimentary organs, of no importance; the
+wide opposition in value between analogical or adaptive characters, and
+characters of true affinity; and other such rules;--all naturally follow on
+the view of the common parentage of those forms which are considered by
+naturalists as allied, together with their modification through natural
+selection, with its contingencies of extinction and divergence of
+character.  In considering this view of classification, it should be borne
+in mind that the element of descent has been universally used in ranking
+together the sexes, ages, and acknowledged varieties of the same species,
+however different they may be in structure.  If we extend the use of this
+element of descent,--the only certainly known cause of similarity in
+organic beings,--we shall understand what is meant by the natural system: 
+it is genealogical in its attempted arrangement, with the grades of
+acquired difference marked by the terms varieties, species, genera,
+families, orders, and classes.
+</para>
+
+<para>
+On this same view of descent with modification, all the great facts in
+Morphology become intelligible,--whether we look to the same pattern
+displayed in the homologous organs, to whatever purpose applied, of the
+different species of a class; or to the homologous parts constructed on the
+same pattern in each individual animal and plant.
+</para>
+
+<para>
+On the principle of successive slight variations, not necessarily or
+generally supervening at a very early period of life, and being inherited
+at a corresponding period, we can understand the great leading facts in
+Embryology; namely, the resemblance in an individual embryo of the
+homologous parts, which when matured will become widely different from each
+other in structure and function; and the resemblance in different species
+of a class of the homologous parts or organs, though fitted in the adult
+members for purposes as different as possible.  Larvae are active embryos,
+which have become specially modified in relation to their habits of life,
+through the principle of modifications being inherited at corresponding
+ages.  On this same principle--and bearing in mind, that when organs are
+reduced in size, either from disuse or selection, it will generally be at
+that period of life when the being has to provide for its own wants, and
+bearing in mind how strong is the principle of inheritance--the occurrence
+of rudimentary organs and their final abortion, present to us no
+inexplicable difficulties; on the contrary, their presence might have been
+even anticipated.  The importance of embryological characters and of
+rudimentary organs in classification is intelligible, on the view that an
+arrangement is only so far natural as it is genealogical.
+</para>
+
+<para>
+Finally, the several classes of facts which have been considered in this
+chapter, seem to me to proclaim so plainly, that the innumerable species,
+genera, and families of organic beings, with which this world is peopled,
+have all descended, each within its own class or group, from common
+parents, and have all been modified in the course of descent, that I should
+without hesitation adopt this view, even if it were unsupported by other
+facts or arguments.
+</para>
+
+</chapter>
+
+<chapter>
+<chapheader>
+
+<chapnum>Chapter XIV</chapnum>
+
+<title>Recapitulation and Conclusion</title>
+
+<chapsummary>
+Recapitulation of the difficulties on the theory of Natural Selection --
+Recapitulation of the general and special circumstances in its favour --
+Causes of the general belief in the immutability of species -- How far the
+theory of natural selection may be extended -- Effects of its adoption on
+the study of Natural history -- Concluding remarks.
+</chapsummary>
+</chapheader>
+
+<para>
+As this whole volume is one long argument, it may be convenient to the
+reader to have the leading facts and inferences briefly recapitulated.
+</para>
+
+<para>
+That many and grave objections may be advanced against the theory of
+descent with modification through natural selection, I do not deny.  I have
+endeavoured to give to them their full force.  Nothing at first can appear
+more difficult to believe than that the more complex organs and instincts
+should have been perfected, not by means superior to, though analogous
+with, human reason, but by the accumulation of innumerable slight
+variations, each good for the individual possessor.  Nevertheless, this
+difficulty, though appearing to our imagination insuperably great, cannot
+be considered real if we admit the following propositions, namely,--that
+gradations in the perfection of any organ or instinct, which we may
+consider, either do now exist or could have existed, each good of its
+kind,--that all organs and instincts are, in ever so slight a degree,
+variable,--and, lastly, that there is a struggle for existence leading to
+the preservation of each profitable deviation of structure or instinct. 
+The truth of these propositions cannot, I think, be disputed.
+</para>
+
+<para>
+It is, no doubt, extremely difficult even to conjecture by what gradations
+many structures have been perfected, more especially amongst broken and
+failing groups of organic beings; but we see so many strange gradations in
+nature, as is proclaimed by the canon, 'Natura non facit saltum,' that we
+ought to be extremely cautious in saying that any organ or instinct, or any
+whole being, could not have arrived at its present state by many graduated
+steps.  There are, it must be admitted, cases of special difficulty on the
+theory of natural selection; and one of the most curious of these is the
+existence of two or three defined castes of workers or sterile females in
+the same community of ants; but I have attempted to show how this
+difficulty can be mastered.
+</para>
+
+<para>
+With respect to the almost universal sterility of species when first
+crossed, which forms so remarkable a contrast with the almost universal
+fertility of varieties when crossed, I must refer the reader to the
+recapitulation of the facts given at the end of the eighth chapter, which
+seem to me conclusively to show that this sterility is no more a special
+endowment than is the incapacity of two trees to be grafted together, but
+that it is incidental on constitutional differences in the reproductive
+systems of the intercrossed species.  We see the truth of this conclusion
+in the vast difference in the result, when the same two species are crossed
+reciprocally; that is, when one species is first used as the father and
+then as the mother.
+</para>
+
+<para>
+The fertility of varieties when intercrossed and of their mongrel offspring
+cannot be considered as universal; nor is their very general fertility
+surprising when we remember that it is not likely that either their
+constitutions or their reproductive systems should have been profoundly
+modified.  Moreover, most of the varieties which have been experimentised
+on have been produced under domestication; and as domestication apparently
+tends to eliminate sterility, we ought not to expect it also to produce
+sterility.
+</para>
+
+<para>
+The sterility of hybrids is a very different case from that of first
+crosses, for their reproductive organs are more or less functionally
+impotent; whereas in first crosses the organs on both sides are in a
+perfect condition.  As we continually see that organisms of all kinds are
+rendered in some degree sterile from their constitutions having been
+disturbed by slightly different and new conditions of life, we need not
+feel surprise at hybrids being in some degree sterile, for their
+constitutions can hardly fail to have been disturbed from being compounded
+of two distinct organisations.  This parallelism is supported by another
+parallel, but directly opposite, class of facts; namely, that the vigour
+and fertility of all organic beings are increased by slight changes in
+their conditions of life, and that the offspring of slightly modified forms
+or varieties acquire from being crossed increased vigour and fertility.  So
+that, on the one hand, considerable changes in the conditions of life and
+crosses between greatly modified forms, lessen fertility; and on the other
+hand, lesser changes in the conditions of life and crosses between less
+modified forms, increase fertility.
+</para>
+
+<para>
+Turning to geographical distribution, the difficulties encountered on the
+theory of descent with modification are grave enough.  All the individuals
+of the same species, and all the species of the same genus, or even higher
+group, must have descended from common parents; and therefore, in however
+distant and isolated parts of the world they are now found, they must in
+the course of successive generations have passed from some one part to the
+others.  We are often wholly unable even to conjecture how this could have
+been effected.  Yet, as we have reason to believe that some species have
+retained the same specific form for very long periods, enormously long as
+measured by years, too much stress ought not to be laid on the occasional
+wide diffusion of the same species; for during very long periods of time
+there will always be a good chance for wide migration by many means.  A
+broken or interrupted range may often be accounted for by the extinction of
+the species in the intermediate regions.  It cannot be denied that we are
+as yet very ignorant of the full extent of the various climatal and
+geographical changes which have affected the earth during modern periods;
+and such changes will obviously have greatly facilitated migration.  As an
+example, I have attempted to show how potent has been the influence of the
+Glacial period on the distribution both of the same and of representative
+species throughout the world.  We are as yet profoundly ignorant of the
+many occasional means of transport.  With respect to distinct species of
+the same genus inhabiting very distant and isolated regions, as the process
+of modification has necessarily been slow, all the means of migration will
+have been possible during a very long period; and consequently the
+difficulty of the wide diffusion of species of the same genus is in some
+degree lessened.
+</para>
+
+<para>
+As on the theory of natural selection an interminable number of
+intermediate forms must have existed, linking together all the species in
+each group by gradations as fine as our present varieties, it may be asked,
+Why do we not see these linking forms all around us?  Why are not all
+organic beings blended together in an inextricable chaos?  With respect to
+existing forms, we should remember that we have no right to expect
+(excepting in rare cases) to discover directly connecting links between
+them, but only between each and some extinct and supplanted form.  Even on
+a wide area, which has during a long period remained continuous, and of
+which the climate and other conditions of life change insensibly in going
+from a district occupied by one species into another district occupied by a
+closely allied species, we have no just right to expect often to find
+intermediate varieties in the intermediate zone.  For we have reason to
+believe that only a few species are undergoing change at any one period;
+and all changes are slowly effected.  I have also shown that the
+intermediate varieties which will at first probably exist in the
+intermediate zones, will be liable to be supplanted by the allied forms on
+either hand; and the latter, from existing in greater numbers, will
+generally be modified and improved at a quicker rate than the intermediate
+varieties, which exist in lesser numbers; so that the intermediate
+varieties will, in the long run, be supplanted and exterminated.
+</para>
+
+<para>
+On this doctrine of the extermination of an infinitude of connecting links,
+between the living and extinct inhabitants of the world, and at each
+successive period between the extinct and still older species, why is not
+every geological formation charged with such links?  Why does not every
+collection of fossil remains afford plain evidence of the gradation and
+mutation of the forms of life?  We meet with no such evidence, and this is
+the most obvious and forcible of the many objections which may be urged
+against my theory.  Why, again, do whole groups of allied species appear,
+though certainly they often falsely appear, to have come in suddenly on the
+several geological stages?  Why do we not find great piles of strata
+beneath the Silurian system, stored with the remains of the progenitors of
+the Silurian groups of fossils?  For certainly on my theory such strata
+must somewhere have been deposited at these ancient and utterly unknown
+epochs in the world's history.
+</para>
+
+<para>
+I can answer these questions and grave objections only on the supposition
+that the geological record is far more imperfect than most geologists
+believe.  It cannot be objected that there has not been time sufficient for
+any amount of organic change; for the lapse of time has been so great as to
+be utterly inappreciable by the human intellect.  The number of specimens
+in all our museums is absolutely as nothing compared with the countless
+generations of countless species which certainly have existed.  We should
+not be able to recognise a species as the parent of any one or more species
+if we were to examine them ever so closely, unless we likewise possessed
+many of the intermediate links between their past or parent and present
+states; and these many links we could hardly ever expect to discover, owing
+to the imperfection of the geological record.  Numerous existing doubtful
+forms could be named which are probably varieties; but who will pretend
+that in future ages so many fossil links will be discovered, that
+naturalists will be able to decide, on the common view, whether or not
+these doubtful forms are varieties?  As long as most of the links between
+any two species are unknown, if any one link or intermediate variety be
+discovered, it will simply be classed as another and distinct species. 
+Only a small portion of the world has been geologically explored.  Only
+organic beings of certain classes can be preserved in a fossil condition,
+at least in any great number.  Widely ranging species vary most, and
+varieties are often at first local,--both causes rendering the discovery of
+intermediate links less likely.  Local varieties will not spread into other
+and distant regions until they are considerably modified and improved; and
+when they do spread, if discovered in a geological formation, they will
+appear as if suddenly created there, and will be simply classed as new
+species.  Most formations have been intermittent in their accumulation; and
+their duration, I am inclined to believe, has been shorter than the average
+duration of specific forms.  Successive formations are separated from each
+other by enormous blank intervals of time; for fossiliferous formations,
+thick enough to resist future degradation, can be accumulated only where
+much sediment is deposited on the subsiding bed of the sea.  During the
+alternate periods of elevation and of stationary level the record will be
+blank.  During these latter periods there will probably be more variability
+in the forms of life; during periods of subsidence, more extinction.
+</para>
+
+<para>
+With respect to the absence of fossiliferous formations beneath the lowest
+Silurian strata, I can only recur to the hypothesis given in the ninth
+chapter.  That the geological record is imperfect all will admit; but that
+it is imperfect to the degree which I require, few will be inclined to
+admit.  If we look to long enough intervals of time, geology plainly
+declares that all species have changed; and they have changed in the manner
+which my theory requires, for they have changed slowly and in a graduated
+manner.  We clearly see this in the fossil remains from consecutive
+formations invariably being much more closely related to each other, than
+are the fossils from formations distant from each other in time.
+</para>
+
+<para>
+Such is the sum of the several chief objections and difficulties which may
+justly be urged against my theory; and I have now briefly recapitulated the
+answers and explanations which can be given to them.  I have felt these
+difficulties far too heavily during many years to doubt their weight.  But
+it deserves especial notice that the more important objections relate to
+questions on which we are confessedly ignorant; nor do we know how ignorant
+we are.  We do not know all the possible transitional gradations between
+the simplest and the most perfect organs; it cannot be pretended that we
+know all the varied means of Distribution during the long lapse of years,
+or that we know how imperfect the Geological Record is.  Grave as these
+several difficulties are, in my judgment they do not overthrow the theory
+of descent with modification.
+</para>
+
+<para>
+Now let us turn to the other side of the argument.  Under domestication we
+see much variability.  This seems to be mainly due to the reproductive
+system being eminently susceptible to changes in the conditions of life; so
+that this system, when not rendered impotent, fails to reproduce offspring
+exactly like the parent-form.  Variability is governed by many complex
+laws,--by correlation of growth, by use and disuse, and by the direct
+action of the physical conditions of life.  There is much difficulty in
+ascertaining how much modification our domestic productions have undergone;
+but we may safely infer that the amount has been large, and that
+modifications can be inherited for long periods.  As long as the conditions
+of life remain the same, we have reason to believe that a modification,
+which has already been inherited for many generations, may continue to be
+inherited for an almost infinite number of generations.  On the other hand
+we have evidence that variability, when it has once come into play, does
+not wholly cease; for new varieties are still occasionally produced by our
+most anciently domesticated productions.
+</para>
+
+<para>
+Man does not actually produce variability; he only unintentionally exposes
+organic beings to new conditions of life, and then nature acts on the
+organisation, and causes variability.  But man can and does select the
+variations given to him by nature, and thus accumulate them in any desired
+manner.  He thus adapts animals and plants for his own benefit or pleasure. 
+He may do this methodically, or he may do it unconsciously by preserving
+the individuals most useful to him at the time, without any thought of
+altering the breed.  It is certain that he can largely influence the
+character of a breed by selecting, in each successive generation,
+individual differences so slight as to be quite inappreciable by an
+uneducated eye.  This process of selection has been the great agency in the
+production of the most distinct and useful domestic breeds.  That many of
+the breeds produced by man have to a large extent the character of natural
+species, is shown by the inextricable doubts whether very many of them are
+varieties or aboriginal species.
+</para>
+
+<para>
+There is no obvious reason why the principles which have acted so
+efficiently under domestication should not have acted under nature.  In the
+preservation of favoured individuals and races, during the
+constantly-recurrent Struggle for Existence, we see the most powerful and
+ever-acting means of selection.  The struggle for existence inevitably
+follows from the high geometrical ratio of increase which is common to all
+organic beings.  This high rate of increase is proved by calculation, by
+the effects of a succession of peculiar seasons, and by the results of
+naturalisation, as explained in the third chapter.  More individuals are
+born than can possibly survive.  A grain in the balance will determine
+which individual shall live and which shall die,--which variety or species
+shall increase in number, and which shall decrease, or finally become
+extinct.  As the individuals of the same species come in all respects into
+the closest competition with each other, the struggle will generally be
+most severe between them; it will be almost equally severe between the
+varieties of the same species, and next in severity between the species of
+the same genus.  But the struggle will often be very severe between beings
+most remote in the scale of nature.  The slightest advantage in one being,
+at any age or during any season, over those with which it comes into
+competition, or better adaptation in however slight a degree to the
+surrounding physical conditions, will turn the balance.
+</para>
+
+<para>
+With animals having separated sexes there will in most cases be a struggle
+between the males for possession of the females.  The most vigorous
+individuals, or those which have most successfully struggled with their
+conditions of life, will generally leave most progeny.  But success will
+often depend on having special weapons or means of defence, or on the
+charms of the males; and the slightest advantage will lead to victory.
+</para>
+
+<para>
+As geology plainly proclaims that each land has undergone great physical
+changes, we might have expected that organic beings would have varied under
+nature, in the same way as they generally have varied under the changed
+conditions of domestication.  And if there be any variability under nature,
+it would be an unaccountable fact if natural selection had not come into
+play.  It has often been asserted, but the assertion is quite incapable of
+proof, that the amount of variation under nature is a strictly limited
+quantity.  Man, though acting on external characters alone and often
+capriciously, can produce within a short period a great result by adding up
+mere individual differences in his domestic productions; and every one
+admits that there are at least individual differences in species under
+nature.  But, besides such differences, all naturalists have admitted the
+existence of varieties, which they think sufficiently distinct to be worthy
+of record in systematic works.  No one can draw any clear distinction
+between individual differences and slight varieties; or between more
+plainly marked varieties and sub-species, and species.  Let it be observed
+how naturalists differ in the rank which they assign to the many
+representative forms in Europe and North America.
+</para>
+
+<para>
+If then we have under nature variability and a powerful agent always ready
+to act and select, why should we doubt that variations in any way useful to
+beings, under their excessively complex relations of life, would be
+preserved, accumulated, and inherited?  Why, if man can by patience select
+variations most useful to himself, should nature fail in selecting
+variations useful, under changing conditions of life, to her living
+products?  What limit can be put to this power, acting during long ages and
+rigidly scrutinising the whole constitution, structure, and habits of each
+creature,--favouring the good and rejecting the bad?  I can see no limit to
+this power, in slowly and beautifully adapting each form to the most
+complex relations of life.  The theory of natural selection, even if we
+looked no further than this, seems to me to be in itself probable.  I have
+already recapitulated, as fairly as I could, the opposed difficulties and
+objections:  now let us turn to the special facts and arguments in favour
+of the theory.
+</para>
+
+<para>
+On the view that species are only strongly marked and permanent varieties,
+and that each species first existed as a variety, we can see why it is that
+no line of demarcation can be drawn between species, commonly supposed to
+have been produced by special acts of creation, and varieties which are
+acknowledged to have been produced by secondary laws.  On this same view we
+can understand how it is that in each region where many species of a genus
+have been produced, and where they now flourish, these same species should
+present many varieties; for where the manufactory of species has been
+active, we might expect, as a general rule, to find it still in action; and
+this is the case if varieties be incipient species.  Moreover, the species
+of the large genera, which afford the greater number of varieties or
+incipient species, retain to a certain degree the character of varieties;
+for they differ from each other by a less amount of difference than do the
+species of smaller genera.  The closely allied species also of the larger
+genera apparently have restricted ranges, and they are clustered in little
+groups round other species--in which respects they resemble varieties. 
+These are strange relations on the view of each species having been
+independently created, but are intelligible if all species first existed as
+varieties.
+</para>
+
+<para>
+As each species tends by its geometrical ratio of reproduction to increase
+inordinately in number; and as the modified descendants of each species
+will be enabled to increase by so much the more as they become more
+diversified in habits and structure, so as to be enabled to seize on many
+and widely different places in the economy of nature, there will be a
+constant tendency in natural selection to preserve the most divergent
+offspring of any one species.  Hence during a long-continued course of
+modification, the slight differences, characteristic of varieties of the
+same species, tend to be augmented into the greater differences
+characteristic of species of the same genus.  New and improved varieties
+will inevitably supplant and exterminate the older, less improved and
+intermediate varieties; and thus species are rendered to a large extent
+defined and distinct objects.  Dominant species belonging to the larger
+groups tend to give birth to new and dominant forms; so that each large
+group tends to become still larger, and at the same time more divergent in
+character.  But as all groups cannot thus succeed in increasing in size,
+for the world would not hold them, the more dominant groups beat the less
+dominant.  This tendency in the large groups to go on increasing in size
+and diverging in character, together with the almost inevitable contingency
+of much extinction, explains the arrangement of all the forms of life, in
+groups subordinate to groups, all within a few great classes, which we now
+see everywhere around us, and which has prevailed throughout all time. 
+This grand fact of the grouping of all organic beings seems to me utterly
+inexplicable on the theory of creation.
+</para>
+
+<para>
+As natural selection acts solely by accumulating slight, successive,
+favourable variations, it can produce no great or sudden modification; it
+can act only by very short and slow steps.  Hence the canon of 'Natura non
+facit saltum,' which every fresh addition to our knowledge tends to make
+more strictly correct, is on this theory simply intelligible.  We can
+plainly see why nature is prodigal in variety, though niggard in
+innovation.  But why this should be a law of nature if each species has
+been independently created, no man can explain.
+</para>
+
+<para>
+Many other facts are, as it seems to me, explicable on this theory.  How
+strange it is that a bird, under the form of woodpecker, should have been
+created to prey on insects on the ground; that upland geese, which never or
+rarely swim, should have been created with webbed feet; that a thrush
+should have been created to dive and feed on sub-aquatic insects; and that
+a petrel should have been created with habits and structure fitting it for
+the life of an auk or grebe! and so on in endless other cases.  But on the
+view of each species constantly trying to increase in number, with natural
+selection always ready to adapt the slowly varying descendants of each to
+any unoccupied or ill-occupied place in nature, these facts cease to be
+strange, or perhaps might even have been anticipated.
+</para>
+
+<para>
+As natural selection acts by competition, it adapts the inhabitants of each
+country only in relation to the degree of perfection of their associates;
+so that we need feel no surprise at the inhabitants of any one country,
+although on the ordinary view supposed to have been specially created and
+adapted for that country, being beaten and supplanted by the naturalised
+productions from another land.  Nor ought we to marvel if all the
+contrivances in nature be not, as far as we can judge, absolutely perfect;
+and if some of them be abhorrent to our ideas of fitness.  We need not
+marvel at the sting of the bee causing the bee's own death; at drones being
+produced in such vast numbers for one single act, and being then
+slaughtered by their sterile sisters; at the astonishing waste of pollen by
+our fir-trees; at the instinctive hatred of the queen bee for her own
+fertile daughters; at ichneumonidae feeding within the live bodies of
+caterpillars; and at other such cases.  The wonder indeed is, on the theory
+of natural selection, that more cases of the want of absolute perfection
+have not been observed.
+</para>
+
+<para>
+The complex and little known laws governing variation are the same, as far
+as we can see, with the laws which have governed the production of
+so-called specific forms.  In both cases physical conditions seem to have
+produced but little direct effect; yet when varieties enter any zone, they
+occasionally assume some of the characters of the species proper to that
+zone.  In both varieties and species, use and disuse seem to have produced
+some effect; for it is difficult to resist this conclusion when we look,
+for instance, at the logger-headed duck, which has wings incapable of
+flight, in nearly the same condition as in the domestic duck; or when we
+look at the burrowing tucutucu, which is occasionally blind, and then at
+certain moles, which are habitually blind and have their eyes covered with
+skin; or when we look at the blind animals inhabiting the dark caves of
+America and Europe.  In both varieties and species correlation of growth
+seems to have played a most important part, so that when one part has been
+modified other parts are necessarily modified.  In both varieties and
+species reversions to long-lost characters occur.  How inexplicable on the
+theory of creation is the occasional appearance of stripes on the shoulder
+and legs of the several species of the horse-genus and in their hybrids! 
+How simply is this fact explained if we believe that these species have
+descended from a striped progenitor, in the same manner as the several
+domestic breeds of pigeon have descended from the blue and barred
+rock-pigeon!
+</para>
+
+<para>
+On the ordinary view of each species having been independently created, why
+should the specific characters, or those by which the species of the same
+genus differ from each other, be more variable than the generic characters
+in which they all agree?  Why, for instance, should the colour of a flower
+be more likely to vary in any one species of a genus, if the other species,
+supposed to have been created independently, have differently coloured
+flowers, than if all the species of the genus have the same coloured
+flowers?  If species are only well-marked varieties, of which the
+characters have become in a high degree permanent, we can understand this
+fact; for they have already varied since they branched off from a common
+progenitor in certain characters, by which they have come to be
+specifically distinct from each other; and therefore these same characters
+would be more likely still to be variable than the generic characters which
+have been inherited without change for an enormous period.  It is
+inexplicable on the theory of creation why a part developed in a very
+unusual manner in any one species of a genus, and therefore, as we may
+naturally infer, of great importance to the species, should be eminently
+liable to variation; but, on my view, this part has undergone, since the
+several species branched off from a common progenitor, an unusual amount of
+variability and modification, and therefore we might expect this part
+generally to be still variable.  But a part may be developed in the most
+unusual manner, like the wing of a bat, and yet not be more variable than
+any other structure, if the part be common to many subordinate forms, that
+is, if it has been inherited for a very long period; for in this case it
+will have been rendered constant by long-continued natural selection.
+</para>
+
+<para>
+Glancing at instincts, marvellous as some are, they offer no greater
+difficulty than does corporeal structure on the theory of the natural
+selection of successive, slight, but profitable modifications.  We can thus
+understand why nature moves by graduated steps in endowing different
+animals of the same class with their several instincts.  I have attempted
+to show how much light the principle of gradation throws on the admirable
+architectural powers of the hive-bee.  Habit no doubt sometimes comes into
+play in modifying instincts; but it certainly is not indispensable, as we
+see, in the case of neuter insects, which leave no progeny to inherit the
+effects of long-continued habit.  On the view of all the species of the
+same genus having descended from a common parent, and having inherited much
+in common, we can understand how it is that allied species, when placed
+under considerably different conditions of life, yet should follow nearly
+the same instincts; why the thrush of South America, for instance, lines
+her nest with mud like our British species.  On the view of instincts
+having been slowly acquired through natural selection we need not marvel at
+some instincts being apparently not perfect and liable to mistakes, and at
+many instincts causing other animals to suffer.
+</para>
+
+<para>
+If species be only well-marked and permanent varieties, we can at once see
+why their crossed offspring should follow the same complex laws in their
+degrees and kinds of resemblance to their parents,--in being absorbed into
+each other by successive crosses, and in other such points,--as do the
+crossed offspring of acknowledged varieties.  On the other hand, these
+would be strange facts if species have been independently created, and
+varieties have been produced by secondary laws.
+</para>
+
+<para>
+If we admit that the geological record is imperfect in an extreme degree,
+then such facts as the record gives, support the theory of descent with
+modification.  New species have come on the stage slowly and at successive
+intervals; and the amount of change, after equal intervals of time, is
+widely different in different groups.  The extinction of species and of
+whole groups of species, which has played so conspicuous a part in the
+history of the organic world, almost inevitably follows on the principle of
+natural selection; for old forms will be supplanted by new and improved
+forms.  Neither single species nor groups of species reappear when the
+chain of ordinary generation has once been broken.  The gradual diffusion
+of dominant forms, with the slow modification of their descendants, causes
+the forms of life, after long intervals of time, to appear as if they had
+changed simultaneously throughout the world.  The fact of the fossil
+remains of each formation being in some degree intermediate in character
+between the fossils in the formations above and below, is simply explained
+by their intermediate position in the chain of descent.  The grand fact
+that all extinct organic beings belong to the same system with recent
+beings, falling either into the same or into intermediate groups, follows
+from the living and the extinct being the offspring of common parents.  As
+the groups which have descended from an ancient progenitor have generally
+diverged in character, the progenitor with its early descendants will often
+be intermediate in character in comparison with its later descendants; and
+thus we can see why the more ancient a fossil is, the oftener it stands in
+some degree intermediate between existing and allied groups.  Recent forms
+are generally looked at as being, in some vague sense, higher than ancient
+and extinct forms; and they are in so far higher as the later and more
+improved forms have conquered the older and less improved organic beings in
+the struggle for life.  Lastly, the law of the long endurance of allied
+forms on the same continent,--of marsupials in Australia, of edentata in
+America, and other such cases,--is intelligible, for within a confined
+country, the recent and the extinct will naturally be allied by descent.
+</para>
+
+<para>
+Looking to geographical distribution, if we admit that there has been
+during the long course of ages much migration from one part of the world to
+another, owing to former climatal and geographical changes and to the many
+occasional and unknown means of dispersal, then we can understand, on the
+theory of descent with modification, most of the great leading facts in
+Distribution.  We can see why there should be so striking a parallelism in
+the distribution of organic beings throughout space, and in their
+geological succession throughout time; for in both cases the beings have
+been connected by the bond of ordinary generation, and the means of
+modification have been the same.  We see the full meaning of the wonderful
+fact, which must have struck every traveller, namely, that on the same
+continent, under the most diverse conditions, under heat and cold, on
+mountain and lowland, on deserts and marshes, most of the inhabitants
+within each great class are plainly related; for they will generally be
+descendants of the same progenitors and early colonists.  On this same
+principle of former migration, combined in most cases with modification, we
+can understand, by the aid of the Glacial period, the identity of some few
+plants, and the close alliance of many others, on the most distant
+mountains, under the most different climates; and likewise the close
+alliance of some of the inhabitants of the sea in the northern and southern
+temperate zones, though separated by the whole intertropical ocean. 
+Although two areas may present the same physical conditions of life, we
+need feel no surprise at their inhabitants being widely different, if they
+have been for a long period completely separated from each other; for as
+the relation of organism to organism is the most important of all
+relations, and as the two areas will have received colonists from some
+third source or from each other, at various periods and in different
+proportions, the course of modification in the two areas will inevitably be
+different.
+</para>
+
+<para>
+On this view of migration, with subsequent modification, we can see why
+oceanic islands should be inhabited by few species, but of these, that many
+should be peculiar.  We can clearly see why those animals which cannot
+cross wide spaces of ocean, as frogs and terrestrial mammals, should not
+inhabit oceanic islands; and why, on the other hand, new and peculiar
+species of bats, which can traverse the ocean, should so often be found on
+islands far distant from any continent.  Such facts as the presence of
+peculiar species of bats, and the absence of all other mammals, on oceanic
+islands, are utterly inexplicable on the theory of independent acts of
+creation.
+</para>
+
+<para>
+The existence of closely allied or representative species in any two areas,
+implies, on the theory of descent with modification, that the same parents
+formerly inhabited both areas; and we almost invariably find that wherever
+many closely allied species inhabit two areas, some identical species
+common to both still exist.  Wherever many closely allied yet distinct
+species occur, many doubtful forms and varieties of the same species
+likewise occur.  It is a rule of high generality that the inhabitants of
+each area are related to the inhabitants of the nearest source whence
+immigrants might have been derived.  We see this in nearly all the plants
+and animals of the Galapagos archipelago, of Juan Fernandez, and of the
+other American islands being related in the most striking manner to the
+plants and animals of the neighbouring American mainland; and those of the
+Cape de Verde archipelago and other African islands to the African
+mainland.  It must be admitted that these facts receive no explanation on
+the theory of creation.
+</para>
+
+<para>
+The fact, as we have seen, that all past and present organic beings
+constitute one grand natural system, with group subordinate to group, and
+with extinct groups often falling in between recent groups, is intelligible
+on the theory of natural selection with its contingencies of extinction and
+divergence of character.  On these same principles we see how it is, that
+the mutual affinities of the species and genera within each class are so
+complex and circuitous.  We see why certain characters are far more
+serviceable than others for classification;--why adaptive characters,
+though of paramount importance to the being, are of hardly any importance
+in classification; why characters derived from rudimentary parts, though of
+no service to the being, are often of high classificatory value; and why
+embryological characters are the most valuable of all.  The real affinities
+of all organic beings are due to inheritance or community of descent.  The
+natural system is a genealogical arrangement, in which we have to discover
+the lines of descent by the most permanent characters, however slight their
+vital importance may be.
+</para>
+
+<para>
+The framework of bones being the same in the hand of a man, wing of a bat,
+fin of the porpoise, and leg of the horse,--the same number of vertebrae
+forming the neck of the giraffe and of the elephant,--and innumerable other
+such facts, at once explain themselves on the theory of descent with slow
+and slight successive modifications.  The similarity of pattern in the wing
+and leg of a bat, though used for such different purpose,--in the jaws and
+legs of a crab,--in the petals, stamens, and pistils of a flower, is
+likewise intelligible on the view of the gradual modification of parts or
+organs, which were alike in the early progenitor of each class.  On the
+principle of successive variations not always supervening at an early age,
+and being inherited at a corresponding not early period of life, we can
+clearly see why the embryos of mammals, birds, reptiles, and fishes should
+be so closely alike, and should be so unlike the adult forms.  We may cease
+marvelling at the embryo of an air-breathing mammal or bird having
+branchial slits and arteries running in loops, like those in a fish which
+has to breathe the air dissolved in water, by the aid of well-developed
+branchiae.
+</para>
+
+<para>
+Disuse, aided sometimes by natural selection, will often tend to reduce an
+organ, when it has become useless by changed habits or under changed
+conditions of life; and we can clearly understand on this view the meaning
+of rudimentary organs.  But disuse and selection will generally act on each
+creature, when it has come to maturity and has to play its full part in the
+struggle for existence, and will thus have little power of acting on an
+organ during early life; hence the organ will not be much reduced or
+rendered rudimentary at this early age.  The calf, for instance, has
+inherited teeth, which never cut through the gums of the upper jaw, from an
+early progenitor having well-developed teeth; and we may believe, that the
+teeth in the mature animal were reduced, during successive generations, by
+disuse or by the tongue and palate having been fitted by natural selection
+to browse without their aid; whereas in the calf, the teeth have been left
+untouched by selection or disuse, and on the principle of inheritance at
+corresponding ages have been inherited from a remote period to the present
+day.  On the view of each organic being and each separate organ having been
+specially created, how utterly inexplicable it is that parts, like the
+teeth in the embryonic calf or like the shrivelled wings under the soldered
+wing-covers of some beetles, should thus so frequently bear the plain stamp
+of inutility!  Nature may be said to have taken pains to reveal, by
+rudimentary organs and by homologous structures, her scheme of
+modification, which it seems that we wilfully will not understand.
+</para>
+
+<para>
+I have now recapitulated the chief facts and considerations which have
+thoroughly convinced me that species have changed, and are still slowly
+changing by the preservation and accumulation of successive slight
+favourable variations.  Why, it may be asked, have all the most eminent
+living naturalists and geologists rejected this view of the mutability of
+species?  It cannot be asserted that organic beings in a state of nature
+are subject to no variation; it cannot be proved that the amount of
+variation in the course of long ages is a limited quantity; no clear
+distinction has been, or can be, drawn between species and well-marked
+varieties.  It cannot be maintained that species when intercrossed are
+invariably sterile, and varieties invariably fertile; or that sterility is
+a special endowment and sign of creation.  The belief that species were
+immutable productions was almost unavoidable as long as the history of the
+world was thought to be of short duration; and now that we have acquired
+some idea of the lapse of time, we are too apt to assume, without proof,
+that the geological record is so perfect that it would have afforded us
+plain evidence of the mutation of species, if they had undergone mutation.
+</para>
+
+<para>
+But the chief cause of our natural unwillingness to admit that one species
+has given birth to other and distinct species, is that we are always slow
+in admitting any great change of which we do not see the intermediate
+steps.  The difficulty is the same as that felt by so many geologists, when
+Lyell first insisted that long lines of inland cliffs had been formed, and
+great valleys excavated, by the slow action of the coast-waves.  The mind
+cannot possibly grasp the full meaning of the term of a hundred million
+years; it cannot add up and perceive the full effects of many slight
+variations, accumulated during an almost infinite number of generations.
+</para>
+
+<para>
+Although I am fully convinced of the truth of the views given in this
+volume under the form of an abstract, I by no means expect to convince
+experienced naturalists whose minds are stocked with a multitude of facts
+all viewed, during a long course of years, from a point of view directly
+opposite to mine.  It is so easy to hide our ignorance under such
+expressions as the 'plan of creation,' 'unity of design,' &amp;c., and to think
+that we give an explanation when we only restate a fact.  Any one whose
+disposition leads him to attach more weight to unexplained difficulties
+than to the explanation of a certain number of facts will certainly reject
+my theory.  A few naturalists, endowed with much flexibility of mind, and
+who have already begun to doubt on the immutability of species, may be
+influenced by this volume; but I look with confidence to the future, to
+young and rising naturalists, who will be able to view both sides of the
+question with impartiality.  Whoever is led to believe that species are
+mutable will do good service by conscientiously expressing his conviction;
+for only thus can the load of prejudice by which this subject is
+overwhelmed be removed.
+</para>
+
+<para>
+Several eminent naturalists have of late published their belief that a
+multitude of reputed species in each genus are not real species; but that
+other species are real, that is, have been independently created.  This
+seems to me a strange conclusion to arrive at.  They admit that a multitude
+of forms, which till lately they themselves thought were special creations,
+and which are still thus looked at by the majority of naturalists, and
+which consequently have every external characteristic feature of true
+species,--they admit that these have been produced by variation, but they
+refuse to extend the same view to other and very slightly different forms. 
+Nevertheless they do not pretend that they can define, or even conjecture,
+which are the created forms of life, and which are those produced by
+secondary laws.  They admit variation as a vera causa in one case, they
+arbitrarily reject it in another, without assigning any distinction in the
+two cases.  The day will come when this will be given as a curious
+illustration of the blindness of preconceived opinion.  These authors seem
+no more startled at a miraculous act of creation than at an ordinary birth. 
+But do they really believe that at innumerable periods in the earth's
+history certain elemental atoms have been commanded suddenly to flash into
+living tissues?  Do they believe that at each supposed act of creation one
+individual or many were produced?  Were all the infinitely numerous kinds
+of animals and plants created as eggs or seed, or as full grown? and in the
+case of mammals, were they created bearing the false marks of nourishment
+from the mother's womb?  Although naturalists very properly demand a full
+explanation of every difficulty from those who believe in the mutability of
+species, on their own side they ignore the whole subject of the first
+appearance of species in what they consider reverent silence.
+</para>
+
+<para>
+It may be asked how far I extend the doctrine of the modification of
+species.  The question is difficult to answer, because the more distinct
+the forms are which we may consider, by so much the arguments fall away in
+force.  But some arguments of the greatest weight extend very far.  All the
+members of whole classes can be connected together by chains of affinities,
+and all can be classified on the same principle, in groups subordinate to
+groups.  Fossil remains sometimes tend to fill up very wide intervals
+between existing orders.  Organs in a rudimentary condition plainly show
+that an early progenitor had the organ in a fully developed state; and this
+in some instances necessarily implies an enormous amount of modification in
+the descendants.  Throughout whole classes various structures are formed on
+the same pattern, and at an embryonic age the species closely resemble each
+other.  Therefore I cannot doubt that the theory of descent with
+modification embraces all the members of the same class.  I believe that
+animals have descended from at most only four or five progenitors, and
+plants from an equal or lesser number.
+</para>
+
+<para>
+Analogy would lead me one step further, namely, to the belief that all
+animals and plants have descended from some one prototype.  But analogy may
+be a deceitful guide.  Nevertheless all living things have much in common,
+in their chemical composition, their germinal vesicles, their cellular
+structure, and their laws of growth and reproduction.  We see this even in
+so trifling a circumstance as that the same poison often similarly affects
+plants and animals; or that the poison secreted by the gall-fly produces
+monstrous growths on the wild rose or oak-tree.  Therefore I should infer
+from analogy that probably all the organic beings which have ever lived on
+this earth have descended from some one primordial form, into which life
+was first breathed.
+</para>
+
+<para>
+When the views entertained in this volume on the origin of species, or when
+analogous views are generally admitted, we can dimly foresee that there
+will be a considerable revolution in natural history.  Systematists will be
+able to pursue their labours as at present; but they will not be
+incessantly haunted by the shadowy doubt whether this or that form be in
+essence a species.  This I feel sure, and I speak after experience, will be
+no slight relief.  The endless disputes whether or not some fifty species
+of British brambles are true species will cease.  Systematists will have
+only to decide (not that this will be easy) whether any form be
+sufficiently constant and distinct from other forms, to be capable of
+definition; and if definable, whether the differences be sufficiently
+important to deserve a specific name.  This latter point will become a far
+more essential consideration than it is at present; for differences,
+however slight, between any two forms, if not blended by intermediate
+gradations, are looked at by most naturalists as sufficient to raise both
+forms to the rank of species.  Hereafter we shall be compelled to
+acknowledge that the only distinction between species and well-marked
+varieties is, that the latter are known, or believed, to be connected at
+the present day by intermediate gradations, whereas species were formerly
+thus connected.  Hence, without quite rejecting the consideration of the
+present existence of intermediate gradations between any two forms, we
+shall be led to weigh more carefully and to value higher the actual amount
+of difference between them.  It is quite possible that forms now generally
+acknowledged to be merely varieties may hereafter be thought worthy of
+specific names, as with the primrose and cowslip; and in this case
+scientific and common language will come into accordance.  In short, we
+shall have to treat species in the same manner as those naturalists treat
+genera, who admit that genera are merely artificial combinations made for
+convenience.  This may not be a cheering prospect; but we shall at least be
+freed from the vain search for the undiscovered and undiscoverable essence
+of the term species.
+</para>
+
+<para>
+The other and more general departments of natural history will rise greatly
+in interest.  The terms used by naturalists of affinity, relationship,
+community of type, paternity, morphology, adaptive characters, rudimentary
+and aborted organs, &amp;c., will cease to be metaphorical, and will have a
+plain signification.  When we no longer look at an organic being as a
+savage looks at a ship, as at something wholly beyond his comprehension;
+when we regard every production of nature as one which has had a history;
+when we contemplate every complex structure and instinct as the summing up
+of many contrivances, each useful to the possessor, nearly in the same way
+as when we look at any great mechanical invention as the summing up of the
+labour, the experience, the reason, and even the blunders of numerous
+workmen; when we thus view each organic being, how far more interesting, I
+speak from experience, will the study of natural history become!
+</para>
+
+<para>
+A grand and almost untrodden field of inquiry will be opened, on the causes
+and laws of variation, on correlation of growth, on the effects of use and
+disuse, on the direct action of external conditions, and so forth.  The
+study of domestic productions will rise immensely in value.  A new variety
+raised by man will be a far more important and interesting subject for
+study than one more species added to the infinitude of already recorded
+species.  Our classifications will come to be, as far as they can be so
+made, genealogies; and will then truly give what may be called the plan of
+creation.  The rules for classifying will no doubt become simpler when we
+have a definite object in view.  We possess no pedigrees or armorial
+bearings; and we have to discover and trace the many diverging lines of
+descent in our natural genealogies, by characters of any kind which have
+long been inherited.  Rudimentary organs will speak infallibly with respect
+to the nature of long-lost structures.  Species and groups of species,
+which are called aberrant, and which may fancifully be called living
+fossils, will aid us in forming a picture of the ancient forms of life. 
+Embryology will reveal to us the structure, in some degree obscured, of the
+prototypes of each great class.
+</para>
+
+<para>
+When we can feel assured that all the individuals of the same species, and
+all the closely allied species of most genera, have within a not very
+remote period descended from one parent, and have migrated from some one
+birthplace; and when we better know the many means of migration, then, by
+the light which geology now throws, and will continue to throw, on former
+changes of climate and of the level of the land, we shall surely be enabled
+to trace in an admirable manner the former migrations of the inhabitants of
+the whole world.  Even at present, by comparing the differences of the
+inhabitants of the sea on the opposite sides of a continent, and the nature
+of the various inhabitants of that continent in relation to their apparent
+means of immigration, some light can be thrown on ancient geography.
+</para>
+
+<para>
+The noble science of Geology loses glory from the extreme imperfection of
+the record.  The crust of the earth with its embedded remains must not be
+looked at as a well-filled museum, but as a poor collection made at hazard
+and at rare intervals.  The accumulation of each great fossiliferous
+formation will be recognised as having depended on an unusual concurrence
+of circumstances, and the blank intervals between the successive stages as
+having been of vast duration.  But we shall be able to gauge with some
+security the duration of these intervals by a comparison of the preceding
+and succeeding organic forms.  We must be cautious in attempting to
+correlate as strictly contemporaneous two formations, which include few
+identical species, by the general succession of their forms of life.  As
+species are produced and exterminated by slowly acting and still existing
+causes, and not by miraculous acts of creation and by catastrophes; and as
+the most important of all causes of organic change is one which is almost
+independent of altered and perhaps suddenly altered physical conditions,
+namely, the mutual relation of organism to organism,--the improvement of
+one being entailing the improvement or the extermination of others; it
+follows, that the amount of organic change in the fossils of consecutive
+formations probably serves as a fair measure of the lapse of actual time. 
+A number of species, however, keeping in a body might remain for a long
+period unchanged, whilst within this same period, several of these species,
+by migrating into new countries and coming into competition with foreign
+associates, might become modified; so that we must not overrate the
+accuracy of organic change as a measure of time.  During early periods of
+the earth's history, when the forms of life were probably fewer and
+simpler, the rate of change was probably slower; and at the first dawn of
+life, when very few forms of the simplest structure existed, the rate of
+change may have been slow in an extreme degree.  The whole history of the
+world, as at present known, although of a length quite incomprehensible by
+us, will hereafter be recognised as a mere fragment of time, compared with
+the ages which have elapsed since the first creature, the progenitor of
+innumerable extinct and living descendants, was created.
+</para>
+
+<para>
+In the distant future I see open fields for far more important researches. 
+Psychology will be based on a new foundation, that of the necessary
+acquirement of each mental power and capacity by gradation.  Light will be
+thrown on the origin of man and his history.
+</para>
+
+<para>
+Authors of the highest eminence seem to be fully satisfied with the view
+that each species has been independently created.  To my mind it accords
+better with what we know of the laws impressed on matter by the Creator,
+that the production and extinction of the past and present inhabitants of
+the world should have been due to secondary causes, like those determining
+the birth and death of the individual.  When I view all beings not as
+special creations, but as the lineal descendants of some few beings which
+lived long before the first bed of the Silurian system was deposited, they
+seem to me to become ennobled.  Judging from the past, we may safely infer
+that not one living species will transmit its unaltered likeness to a
+distant futurity.  And of the species now living very few will transmit
+progeny of any kind to a far distant futurity; for the manner in which all
+organic beings are grouped, shows that the greater number of species of
+each genus, and all the species of many genera, have left no descendants,
+but have become utterly extinct.  We can so far take a prophetic glance
+into futurity as to foretel that it will be the common and widely-spread
+species, belonging to the larger and dominant groups, which will ultimately
+prevail and procreate new and dominant species.  As all the living forms of
+life are the lineal descendants of those which lived long before the
+Silurian epoch, we may feel certain that the ordinary succession by
+generation has never once been broken, and that no cataclysm has desolated
+the whole world.  Hence we may look with some confidence to a secure future
+of equally inappreciable length.  And as natural selection works solely by
+and for the good of each being, all corporeal and mental endowments will
+tend to progress towards perfection.
+</para>
+
+<para>
+It is interesting to contemplate an entangled bank, clothed with many
+plants of many kinds, with birds singing on the bushes, with various
+insects flitting about, and with worms crawling through the damp earth, and
+to reflect that these elaborately constructed forms, so different from each
+other, and dependent on each other in so complex a manner, have all been
+produced by laws acting around us.  These laws, taken in the largest sense,
+being Growth with Reproduction; Inheritance which is almost implied by
+reproduction; Variability from the indirect and direct action of the
+external conditions of life, and from use and disuse; a Ratio of Increase
+so high as to lead to a Struggle for Life, and as a consequence to Natural
+Selection, entailing Divergence of Character and the Extinction of
+less-improved forms.  Thus, from the war of nature, from famine and death,
+the most exalted object which we are capable of conceiving, namely, the
+production of the higher animals, directly follows.  There is grandeur in
+this view of life, with its several powers, having been originally breathed
+into a few forms or into one; and that, whilst this planet has gone cycling
+on according to the fixed law of gravity, from so simple a beginning
+endless forms most beautiful and most wonderful have been, and are being,
+evolved.
+</para>
+</chapter>
+</bookbody>
+<backmatter>
+
+<index>
+
+<title>
+Subject Index
+</title>
+
+<item>
+Aberrant groups
+</item>
+
+<item>
+Abyssinia, plants of
+</item>
+
+<item>
+Acclimatisation
+</item>
+
+<item>
+Affinities of extinct species; of organic beings
+</item>
+
+<item>
+Agassiz on Amblyopsis; on groups of species suddenly appearing; on
+embryological succession; on the glacial period; on embryological
+characters; on the embryos of vertebrata; on parallelism of embryological
+development and geological succession
+</item>
+<item>
+Algae of New Zealand
+</item>
+
+<item>
+Alligators, males, fighting
+</item>
+
+<item>
+Amblyopsis, blind fish
+</item>
+
+<item>
+America, North, productions allied to those of Europe; boulders and
+glaciers of; South, no modern formations on west coast
+</item>
+
+<item>
+Ammonites, sudden extinction of
+</item>
+
+<item>
+Anagallis, sterility of
+</item>
+
+<item>
+Analog of variations
+</item>
+
+<item>
+Ancylus
+</item>
+
+<item>
+Animals, not domesticated from being variable; domestic; descended from
+several stocks; acclimatisation of; of Australia; with thicker fur in cold
+climates; blind, in caves; extinct, of Australia
+</item>
+
+<item>
+Anomma
+</item>
+
+<item>
+Antarctic islands, ancient flora of
+</item>
+
+<item>
+Antirrhinum
+</item>
+
+<item>
+Ants attending aphides; slave-making instinct
+</item>
+
+<item>
+Ants, neuter, structure of
+</item>
+
+<item>
+Aphides attended by ants
+</item>
+
+<item>
+Aphis, development of
+</item>
+
+<item>
+Apteryx
+</item>
+
+<item>
+Arab horses
+</item>
+
+<item>
+Aralo-Caspian Sea
+</item>
+
+<item>
+Archiac, M. de, on the succession of species
+</item>
+
+<item>
+Artichoke, Jerusalem
+</item>
+
+<item>
+Ascension, plants of
+</item>
+
+<item>
+Asclepias, pollen of
+</item>
+
+<item>
+Asparagus
+</item>
+
+<item>
+Aspicarpa
+</item>
+
+<item>
+Asses, striped
+</item>
+
+<item>
+Ateuchus
+</item>
+
+<item>
+Audubon, on habits of frigate-bird; on variation in birds'-nests; on heron
+eating seeds
+</item>
+
+<item>
+Australia, animals of; dogs of; extinct animals of; European plants in
+</item>
+
+<item>
+Azara on flies destroying cattle
+</item>
+
+<item>
+Azores, flora of
+</item>
+
+<item>
+Babington, Mr., on British plants
+</item>
+
+<item>
+Balancement of growth
+</item>
+
+<item>
+Bamboo with hooks
+</item>
+
+<item>
+Barberry, flowers of
+</item>
+
+<item>
+Barrande, M., on Silurian colonies; on the succession of species; on
+parallelism of palaeozoic formations; on affinities of ancient species
+</item>
+
+<item>
+Barriers, importance of
+</item>
+
+<item>
+Batrachians on islands
+</item>
+
+<item>
+Bats, how structure acquired; distribution of
+</item>
+
+<item>
+Bear, catching water-insects
+</item>
+
+<item>
+Bee, sting of; queen, killing rivals
+</item>
+
+<item>
+Bees fertilizing flowers; hive; not sucking the red clover; cell-making
+instinct; humble, cells of; parasitic
+</item>
+
+<item>
+Beetles, wingless, in Madeira; with deficient tarsi
+</item>
+
+<item>
+Bentham, Mr., on British plants; on classification
+</item>
+
+<item>
+Berkeley, Mr., on seeds in salt-water
+</item>
+
+<item>
+Bermuda, birds of
+</item>
+
+<item>
+Birds acquiring fear; annually cross the Atlantic; colour of, on
+continents; fossil, in caves of Brazil; of Madeira, Bermuda, and Galapagos;
+song of males; transporting seeds; waders; wingless; with traces of
+embryonic teeth
+</item>
+
+<item>
+Bizcacha, affinities of
+</item>
+
+<item>
+Bladder for swimming in fish
+</item>
+
+<item>
+Blindness of cave animals
+</item>
+
+<item>
+Blyth, Mr., on distinctness of Indian cattle; on striped Hemionus; on
+crossed geese
+</item>
+
+<item>
+Boar; shoulder-pad of
+</item>
+
+<item>
+Borrow, Mr., on the Spanish pointer
+</item>
+
+<item>
+Bory St. Vincent, on Batrachians
+</item>
+
+<item>
+Bosquet, M., on fossil Chthamalus
+</item>
+
+<item>
+Boulders, erratic, on the Azores
+</item>
+
+<item>
+Branchiae
+</item>
+
+<item>
+Brent, Mr., on house-tumblers; on hawks killing pigeons
+</item>
+
+<item>
+Brewer, Dr., on American cuckoo
+</item>
+
+<item>
+Britain, mammals of
+</item>
+
+<item>
+Bronn, on duration of specific forms
+</item>
+
+<item>
+Brown, Robert, on classification
+</item>
+
+<item>
+Buckman, on variation in plants
+</item>
+
+<item>
+Buzareingues on sterility of varieties
+</item>
+
+<item>
+Cabbage, varieties of, crossed
+</item>
+
+<item>
+Calceolaria
+</item>
+
+<item>
+Canary-birds, sterility of hybrids
+</item>
+
+<item>
+Cape de Verde islands
+</item>
+
+<item>
+Cape of Good Hope, plants of
+</item>
+
+<item>
+Carrier-pigeons killed by hawks
+</item>
+
+<item>
+Cassini on flowers of composita
+</item>
+
+<item>
+Catasetum
+</item>
+
+<item>
+Cats, with blue eyes, deaf; variation in habits of; curling tail when going
+to spring
+</item>
+
+<item>
+Cattle destroying fir-trees; destroyed by flies in La Plata; breeds of,
+locally extinct; fertility of Indian and European breeds
+</item>
+
+<item>
+Cave, inhabitants of, blind
+</item>
+
+<item>
+Centres of creation
+</item>
+
+<item>
+Cephalopodae, development of
+</item>
+
+<item>
+Cervulus
+</item>
+
+<item>
+Cetacea, teeth and hair
+</item>
+
+<item>
+Ceylon, plants of
+</item>
+
+<item>
+Chalk formation
+</item>
+
+<item>
+Charlock
+</item>
+
+<item>
+Checks to increase; mutual
+</item>
+
+<item>
+Chickens, instinctive tameness of
+</item>
+
+<item>
+Chthamalinae
+</item>
+
+<item>
+Chthamalus, cretacean species of
+</item>
+
+<item>
+Circumstances favourable to selection of domestic products; to natural
+selection
+</item>
+
+<item>
+Cirripedes capable of crossing; carapace aborted; their ovigerous frena;
+fossil; larvae of
+</item>
+
+<item>
+Clift, Mr., on the succession of types
+</item>
+
+<item>
+Climate, effects of, in checking increase of beings; adaptation of, to
+organisms
+</item>
+
+<item>
+Cobites, intestine of
+</item>
+
+<item>
+Cockroach
+</item>
+
+<item>
+Collections, palaeontological, poor
+</item>
+
+<item>
+Colour, influenced by climate; in relation to attacks by flies
+</item>
+
+<item>
+Columba livia, parent of domestic pigeons
+</item>
+
+<item>
+Colymbetes
+</item>
+
+<item>
+Compositae, outer and inner florets of; male flowers of
+</item>
+
+<item>
+Conclusion, general
+</item>
+
+<item>
+Conditions, slight changes in, favourable to fertility
+</item>
+
+<item>
+Coot
+</item>
+
+<item>
+Coral-islands, seeds drifted to; reefs, indicating movements of earth
+</item>
+
+<item>
+Corn-crake
+</item>
+
+<item>
+Correlation of growth in domestic productions; of growth
+</item>
+
+<item>
+Cowslip
+</item>
+
+<item>
+Creation, single centres of
+</item>
+
+<item>
+Crinum
+</item>
+
+<item>
+Crosses, reciprocal
+</item>
+
+<item>
+Crossing of domestic animals, importance in altering breeds; advantages of;
+unfavourable to selection
+</item>
+
+<item>
+Crustacea of New Zealand
+</item>
+
+<item>
+Crustacean, blind
+</item>
+
+<item>
+Cryptocerus
+</item>
+
+<item>
+Ctenomys, blind
+</item>
+
+<item>
+Cuckoo, instinct of
+</item>
+
+<item>
+Currants, grafts of
+</item>
+
+<item>
+Currents of sea, rate of
+</item>
+
+<item>
+Cuvier on conditions of existence; on fossil monkeys; Fred., on instinct
+</item>
+
+<item>
+Dana, Prof., on blind cave-animals; on relations of crustaceans of Japan,
+on crustaceans of New Zealand
+</item>
+
+<item>
+De Candolle on struggle for existence; on umbelliferae; on general
+affinities; Alph., on low plants, widely dispersed; on widely-ranging
+plants being variable; on naturalisation; on winged seeds; on Alpine
+species suddenly becoming rare; on distribution of plants with large seeds;
+on vegetation of Australia; on fresh-water plants; on insular plants
+</item>
+
+<item>
+Degradation of coast-rocks
+</item>
+
+<item>
+Denudation, rate of; of oldest rocks
+</item>
+
+<item>
+Development of ancient forms
+</item>
+
+<item>
+Devonian system
+</item>
+
+<item>
+Dianthus, fertility of crosses
+</item>
+
+<item>
+Dirt on feet of birds
+</item>
+
+<item>
+Division, physiological, of labour
+</item>
+
+<item>
+Dogs, hairless, with imperfect teeth; descended from several wild stocks;
+domestic instincts of; inherited civilisation of; fertility of breeds
+together; of crosses; proportions of, when young
+</item>
+
+<item>
+Downing, Mr., on fruit-trees in America
+</item>
+
+<item>
+Downs, North and South
+</item>
+
+<item>
+Dragon-flies, intestines of
+</item>
+
+<item>
+Drift-timber
+</item>
+
+<item>
+Driver-ant
+</item>
+
+<item>
+Drones killed by other bees
+</item>
+
+<item>
+Duck, domestic, wings of, reduced; logger-headed
+</item>
+
+<item>
+Duckweed
+</item>
+
+<item>
+Dugong, affinities of
+</item>
+
+<item>
+Dung-beetles with deficient tarsi
+</item>
+
+<item>
+Dyticus
+</item>
+
+<item>
+Earl, Mr., W., on the Malay Archipelago
+</item>
+
+<item>
+Ears, drooping, in domestic animals; rudimentary
+</item>
+
+<item>
+Earth, seeds in roots of trees
+</item>
+
+<item>
+Eciton
+</item>
+
+<item>
+Edentata, teeth and hair; fossil species of
+</item>
+
+<item>
+Edwards, Milne, on physiological divisions of labour; on gradations of
+structure; on embryological characters
+</item>
+
+<item>
+Eggs, young birds escaping from
+</item>
+
+<item>
+Electric organs
+</item>
+
+<item>
+Elephant, rate increase; of glacial period
+</item>
+
+<item>
+Existence, struggle for; conditions of
+</item>
+
+<item>
+Eye, structure of; correction for aberration
+</item>
+
+<item>
+Eyes reduced in moles
+</item>
+
+<item>
+Fabre, M., on parasitic sphex
+</item>
+
+<item>
+Falconer, Dr., on naturalisation of plants in India; on fossil crocodile;
+on elephants and mastodons; and Cautley on mammals of sub-Himalayan beds
+</item>
+
+<item>
+Falkland Island, wolf of
+</item>
+
+<item>
+Faults
+</item>
+
+<item>
+Fear, instinctive, in birds
+</item>
+
+<item>
+Feet of birds, young molluscs adhering to
+</item>
+
+<item>
+Fertility of hybrids, from slight changes in conditions; of crossed
+varieties
+</item>
+
+<item>
+Fir-trees destroyed by cattle; pollen of
+</item>
+
+<item>
+Fish, flying; teleostean, sudden appearance of; eating seeds; fresh-water,
+distribution of
+</item>
+
+<item>
+Fishes, ganoid, now confined to fresh water; electric organs of; of
+southern hemisphere
+</item>
+
+<item>
+Flight, powers of, how acquired
+</item>
+
+<item>
+Flowers, structure of; in relation to crossing; of composite and
+umbelliferae
+</item>
+
+<item>
+Forbes, E., on colours of shells; on abrupt range of shells in depth; on
+poorness of palaeontological collections; on continuous succession of
+genera; on continental extensions; on distribution during glacial period;
+on parallelism in time and space
+</item>
+
+<item>
+Forests, changes in, in America
+</item>
+
+<item>
+Formation, Devonian
+</item>
+
+<item>
+Formations, thickness of, in Britain; intermittent
+</item>
+
+<item>
+Formica rufescens; sanguinea; flava, neuter of
+</item>
+
+<item>
+Frena, ovigerous, of cirripedes
+</item>
+
+<item>
+Fresh-water productions, dispersal of
+</item>
+
+<item>
+Fries on species in large genera being closely allied to other species
+</item>
+
+<item>
+Frigate-bird
+</item>
+
+<item>
+Frogs on islands
+</item>
+
+<item>
+Fruit-trees, gradual improvement of; in United States; varieties of,
+acclimatised in United States
+</item>
+
+<item>
+Fuci, crossed
+</item>
+
+<item>
+Fur, thicker in cold climates
+</item>
+
+<item>
+Furze
+</item>
+
+<item>
+Galapagos Archipelago, birds of; productions of
+</item>
+
+<item>
+Galeopithecus
+</item>
+
+<item>
+Game, increase of, checked by vermin
+</item>
+
+<item>
+Gartner on sterility of hybrids; on reciprocal crosses; on crossed maize
+and verbascum; on comparison of hybrids and mongrels
+</item>
+
+<item>
+Geese, fertility when crossed; upland
+</item>
+
+<item>
+Genealogy important in classification
+</item>
+
+<item>
+Geoffroy St. Hilaire on balancement; on homologous organs; Isidore, on
+variability of repeated parts; on correlation in monstrosities; on
+correlation; on variable parts being often monstrous
+</item>
+
+<item>
+Geographical distribution
+</item>
+
+<item>
+Geology, future progress of
+</item>
+
+<item>
+Giraffe, tail of
+</item>
+
+<item>
+Glacial period
+</item>
+
+<item>
+Gmelin on Distribution
+</item>
+
+<item>
+Gnathodon, fossil
+</item>
+
+<item>
+Godwin-Austin, Mr., on the Malay Archipelago
+</item>
+
+<item>
+Goethe on compensation of growth
+</item>
+
+<item>
+Gooseberry, grafts of
+</item>
+
+<item>
+Gould, Dr. A., on land-shells; Mr., on colours of birds; on birds of the
+Galapagos; on distribution of genera of birds
+</item>
+
+<item>
+Gourds, crossed
+</item>
+
+<item>
+Grafts, capacity of
+</item>
+
+<item>
+Grasses, varieties of
+</item>
+
+<item>
+Gray, Dr. Asa, on trees of United States; on naturalised plants in the
+United States; on rarity of intermediate varieties; on Alpine plants; Dr.
+J.E., on striped mule
+</item>
+
+<item>
+Grebe
+</item>
+
+<item>
+Grouse, colours of; red, a doubtful species
+</item>
+
+<item>
+Growth, compensation of; correlation of, in domestic products; correlation
+of
+</item>
+
+<item>
+Habit, effect of, under domestication; effect of, under nature;
+diversified, of same species
+</item>
+
+<item>
+Hair and teeth, correlated
+</item>
+
+<item>
+Harcourt, Mr. E.V., on the birds of Madeira
+</item>
+
+<item>
+Hartung, M., on boulders in the Azores
+</item>
+
+<item>
+Hazel-nuts
+</item>
+
+<item>
+Hearne on habits of bears
+</item>
+
+<item>
+Heath, changes in vegetation
+</item>
+
+<item>
+Heer, O., on plants of Madeira
+</item>
+
+<item>
+Helix pomatia
+</item>
+
+<item>
+Helosciadium
+</item>
+
+<item>
+Hemionus, striped
+</item>
+
+<item>
+Herbert, W., on struggle for existence; on sterility of hybrids
+</item>
+
+<item>
+Hermaphrodites crossing
+</item>
+
+<item>
+Heron eating seed
+</item>
+
+<item>
+Heron, Sir R., on peacocks
+</item>
+
+<item>
+Heusinger, on white animals not poisoned by certain plants
+</item>
+
+<item>
+Hewitt, Mr., on sterility of first crosses
+</item>
+
+<item>
+Himalaya, glaciers of; plants of
+</item>
+
+<item>
+Hippeastrum
+</item>
+
+<item>
+Holly-trees, sexes of
+</item>
+
+<item>
+Hollyhock, varieties of, crossed
+</item>
+
+<item>
+Hooker, Dr., on trees of New Zealand
+</item>
+
+<item>
+Hooker, Dr., on acclimatisation of Himalayan trees; on flowers of
+umbelliferae; on glaciers of Himalaya; on algae of New Zealand; on
+vegetation at the base of the Himalaya; on plants of Tierra del Fuego; on
+Australian plants; on relations of flora of South America; on flora of the
+Antarctic lands; on the plants of the Galapagos
+</item>
+
+<item>
+Hooks on bamboos; to seeds on islands
+</item>
+
+<item>
+Horner, Mr., on the antiquity of Egyptians
+</item>
+
+<item>
+Horns, rudimentary
+</item>
+
+<item>
+Horse, fossil, in La Plata
+</item>
+
+<item>
+Horses destroyed by flies in La Plata; striped; proportions of, when young
+</item>
+
+<item>
+Horticulturists, selection applied by
+</item>
+
+<item>
+Huber on cells of bees; P., on reason blended with instinct; on habitual
+nature of instincts; on slave-making ants; on Melipona domestica
+</item>
+
+<item>
+Humble-bees; cells of
+</item>
+
+<item>
+Hunter, J., on secondary sexual characters
+</item>
+
+<item>
+Hutton, Captain, on crossed geese
+</item>
+
+<item>
+Huxley, Prof., on structure of hermaphrodites; on embryological succession;
+on homologous organs; on the development of aphis
+</item>
+
+<item>
+Hybrids and mongrels compared
+</item>
+
+<item>
+Hybridism
+</item>
+
+<item>
+Hydra, structure of
+</item>
+
+<item>
+Ibla
+</item>
+
+<item>
+Icebergs transporting seeds
+</item>
+
+<item>
+Individuals, numbers favourable to selection; many, whether simultaneously
+created
+</item>
+
+<item>
+Insects, colour of, fitted for habitation; sea-side colours of; blind, in
+caves; luminous; neuter
+</item>
+
+<item>
+Instincts, domestic
+</item>
+
+<item>
+Intercrossing, advantages of
+</item>
+
+<item>
+Japan, productions of
+</item>
+
+<item>
+Java, plants of
+</item>
+
+<item>
+Jones, Mr. J.M., on the birds of Bermuda
+</item>
+
+<item>
+Jussieu on classification
+</item>
+
+<item>
+Kentucky, caves of
+</item>
+
+<item>
+Kerguelen-land, flora of
+</item>
+
+<item>
+Kidney-bean, acclimatisation of
+</item>
+
+<item>
+Kidneys of birds
+</item>
+
+<item>
+Kirby on tarsi deficient in beetles
+</item>
+
+<item>
+Knight, Andrew, on cause of variation
+</item>
+
+<item>
+Kolreuter on the barberry; on sterility of hybrids; on reciprocal crosses;
+on crossed varieties of nicotiana; on crossing male and hermaphrodite
+flowers
+</item>
+
+<item>
+Land-shells, distribution of, of Madeira, naturalised
+</item>
+
+<item>
+Languages, classification of
+</item>
+
+<item>
+Lapse, great, of time
+</item>
+
+<item>
+Larvae
+</item>
+
+<item>
+Laurel, nectar secreted by the leaves
+</item>
+
+<item>
+Laws of variation
+</item>
+
+<item>
+Leech, varieties of
+</item>
+
+<item>
+Leguminosae, nectar secreted by glands
+</item>
+
+<item>
+Lepidosiren
+</item>
+
+<item>
+Life, struggle for
+</item>
+
+<item>
+Lingula, Silurian
+</item>
+
+<item>
+Linnaeus, aphorism of
+</item>
+
+<item>
+Lion, mane of; young of, striped
+</item>
+
+<item>
+Lobelia fulgens
+</item>
+
+<item>
+Lobelia, sterility of crosses
+</item>
+
+<item>
+Loess of the Rhine
+</item>
+
+<item>
+Lowness of structure connected with variability
+</item>
+
+<item>
+Lowness, related to wide distribution
+</item>
+
+<item>
+Lubbock, Mr., on the nerves of coccus
+</item>
+
+<item>
+Lucas, Dr. P., on inheritance; on resemblance of child to parent
+</item>
+
+<item>
+Lund and Clausen on fossils of Brazil
+</item>
+
+<item>
+Lyell, Sir C., on the struggle for existence; on modern changes of the
+earth; on measure of denudation; on a carboniferous land-shell; on fossil
+whales; on strata beneath Silurian system; on the imperfection of the
+geological record; on the appearance of species; on Barrande's colonies; on
+tertiary formations of Europe and North America; on parallelism of tertiary
+formations; on transport of seeds by icebergs; on great alternations of
+climate; on the distribution of fresh-water shells; on land-shells of
+Madeira
+</item>
+
+<item>
+Lyell and Dawson on fossilized trees in Nova Scotia
+</item>
+
+<item>
+Macleay on analogical characters
+</item>
+
+<item>
+Madeira, plants of; beetles of, wingless; fossil land-shells of; birds of
+</item>
+
+<item>
+Magpie tame in Norway
+</item>
+
+<item>
+Maize, crossed
+</item>
+
+<item>
+Malay Archipelago compared with Europe; mammals of
+</item>
+
+<item>
+Malpighiaceae
+</item>
+
+<item>
+Mammae, rudimentary
+</item>
+
+<item>
+Mammals, fossil, in secondary formation; insular
+</item>
+
+<item>
+Man, origin of races of
+</item>
+
+<item>
+Manatee, rudimentary nails of
+</item>
+
+<item>
+Marsupials of Australia, fossil species of
+</item>
+
+<item>
+Martens, M., experiment on seeds
+</item>
+
+<item>
+Martin, Mr. W.C., on striped mules
+</item>
+
+<item>
+Matteuchi on the electric organs of rays
+</item>
+
+<item>
+Matthiola, reciprocal crosses of
+</item>
+
+<item>
+Means of dispersal
+</item>
+
+<item>
+Melipona domestica
+</item>
+
+<item>
+Metamorphism of oldest rocks
+</item>
+
+<item>
+Mice destroying bees; acclimatisation of
+</item>
+
+<item>
+Migration, bears on first appearance of fossils
+</item>
+
+<item>
+Miller, Prof., on the cells of bees
+</item>
+
+<item>
+Mirabilis, crosses of
+</item>
+
+<item>
+Missel-thrush
+</item>
+
+<item>
+Misseltoe, complex relations of
+</item>
+
+<item>
+Mississippi, rate of deposition at mouth
+</item>
+
+<item>
+Mocking-thrush of the Galapagos
+</item>
+
+<item>
+Modification of species, how far applicable
+</item>
+
+<item>
+Moles, blind
+</item>
+
+<item>
+Mongrels, fertility and sterility of; and hybrids compared
+</item>
+
+<item>
+Monkeys, fossil
+</item>
+
+<item>
+Monocanthus
+</item>
+
+<item>
+Mons, Van, on the origin of fruit-trees
+</item>
+
+<item>
+Mozart, musical powers of
+</item>
+
+<item>
+Mud, seeds in
+</item>
+
+<item>
+Mules, striped
+</item>
+
+<item>
+Muller, Dr. F., on Alpine Australian plants
+</item>
+
+<item>
+Murchison, Sir, R., on the formations of Russia; on azoic formations; on
+extinction
+</item>
+
+<item>
+Mustela vison
+</item>
+
+<item>
+Myanthus
+</item>
+
+<item>
+Myrmecocystus
+</item>
+
+<item>
+Myrmica, eyes of
+</item>
+
+<item>
+Nails, rudimentary
+</item>
+
+<item>
+Natural history, future progress of
+</item>
+
+<item>
+Naturalisation of forms distinct from the indigenous species; in New
+Zealand
+</item>
+
+<item>
+Nautilus, Silurian
+</item>
+
+<item>
+Nectar of plants
+</item>
+
+<item>
+Nectaries, how formed
+</item>
+
+<item>
+Nelumbium luteum
+</item>
+
+<item>
+Nests, variation in
+</item>
+
+<item>
+Neuter insects
+</item>
+
+<item>
+New Zealand, productions of, not perfect; naturalised products of; fossil
+birds of; glacial action in; crustaceans of; algae of; number of plants of;
+flora of
+</item>
+
+<item>
+Nicotiana, crossed varieties of; certain species very sterile
+</item>
+
+<item>
+Noble, Mr., on fertility of Rhododendron
+</item>
+
+<item>
+Nodules, phosphatic, in azoic rocks
+</item>
+
+<item>
+Oak, varieties of
+</item>
+
+<item>
+Onites apelles
+</item>
+
+<item>
+Orchis, pollen of
+</item>
+
+<item>
+Ornithorhynchus
+</item>
+
+<item>
+Ostrich not capable of flight; habit of laying eggs together; American, two
+species of
+</item>
+
+<item>
+Otter, habits of, how acquired
+</item>
+
+<item>
+Ouzel, water
+</item>
+
+<item>
+Owen, Prof., on birds not flying; on vegetative repetition; on variable
+length of arms in ourang-outang; on the swim-bladder of fishes; on electric
+organs; on fossil horse of La Plata; on relations of ruminants and
+pachyderms; on fossil birds of New Zealand; on succession of types; on
+affinities of the dugong; on homologous organs; on the metamorphosis of
+cephalopods and spiders
+</item>
+
+<item>
+Pacific Ocean, faunas of
+</item>
+
+<item>
+Paley, on no organ formed to give pain
+</item>
+
+<item>
+Pallas, on the fertility of the wild stocks of domestic animals
+</item>
+
+<item>
+Paraguay, cattle destroyed by flies
+</item>
+
+<item>
+Parasites
+</item>
+
+<item>
+Partridge, dirt on feet
+</item>
+
+<item>
+Parts greatly developed, variable, degrees of utility of
+</item>
+
+<item>
+Parus major
+</item>
+
+<item>
+Passiflora
+</item>
+
+<item>
+Peaches in United States
+</item>
+
+<item>
+Pear, grafts of
+</item>
+
+<item>
+Pelargonium, flowers of, sterility of
+</item>
+
+<item>
+Peloria
+</item>
+
+<item>
+Pelvis of women
+</item>
+
+<item>
+Period, glacial
+</item>
+
+<item>
+Petrels, habits of
+</item>
+
+<item>
+Phasianus, fertility of hybrids
+</item>
+
+<item>
+Pheasant, young, wild
+</item>
+
+<item>
+Pictet, Prof., on groups of species suddenly appearing; on rate of organic
+change; on continuous succession of genera; on close alliance of fossils in
+consecutive formations; on embryological succession
+</item>
+
+<item>
+Pierce, Mr., on varieties of wolves
+</item>
+
+<item>
+Pigeons with feathered feet and skin between toes; breeds described, and
+origin of; breeds of, how produced; tumbler, not being able to get out of
+egg; reverting to blue colour; instinct of tumbling; carriers, killed by
+hawks; young of
+</item>
+
+<item>
+Pistil, rudimentary
+</item>
+
+<item>
+Plants, poisonous, not affecting certain coloured animals; selection
+applied to; gradual improvement of; not improved in barbarous countries;
+destroyed by insects; in midst of range, have to struggle with other
+plants; nectar of; fleshy, on sea-shores; fresh-water, distribution of; low
+in scale; widely distributed
+</item>
+
+<item>
+Plumage, laws of change in sexes of birds
+</item>
+
+<item>
+Plums in the United States
+</item>
+
+<item>
+Pointer dog, origin of; habits of
+</item>
+
+<item>
+Poison not affecting certain coloured animals
+</item>
+
+<item>
+Poison, similar effect of, on animals and plants
+</item>
+
+<item>
+Pollen of fir-trees
+</item>
+
+<item>
+Poole, Col., on striped hemionus
+</item>
+
+<item>
+Prestwich, Mr., on English and French eocene formation
+</item>
+
+<item>
+Primrose; sterility of
+</item>
+
+<item>
+Primula, varieties of
+</item>
+
+<item>
+Proteolepas
+</item>
+
+<item>
+Proteus
+</item>
+
+<item>
+Psychology, future progress of
+</item>
+
+<item>
+Quagga, striped
+</item>
+
+<item>
+Quince, grafts of
+</item>
+
+<item>
+Rabbit, disposition of young
+</item>
+
+<item>
+Race-horses, Arab; English
+</item>
+
+<item>
+Races, domestic, characters of
+</item>
+
+<item>
+Ramond on plants of Pyrenees
+</item>
+
+<item>
+Ramsay, Prof., on thickness of the British formations; on faults
+</item>
+
+<item>
+Ratio of increase
+</item>
+
+<item>
+Rats, supplanting each other; acclimatisation of; blind in cave
+</item>
+
+<item>
+Rattle-snake
+</item>
+
+<item>
+Reason and instinct
+</item>
+
+<item>
+Recapitulation, general
+</item>
+
+<item>
+Reciprocity of crosses
+</item>
+
+<item>
+Record, geological, imperfect
+</item>
+
+<item>
+Rengger on flies destroying cattle
+</item>
+
+<item>
+Resemblance to parents in mongrels and hybrids
+</item>
+
+<item>
+Reversion, law of inheritance
+</item>
+
+<item>
+Rhododendron, sterility of
+</item>
+
+<item>
+Richard, Prof., on Aspicarpa
+</item>
+
+<item>
+Richardson, Sir J., on structure of squirrels; on fishes of the southern
+hemisphere
+</item>
+
+<item>
+Robinia, grafts of
+</item>
+
+<item>
+Rodents, blind
+</item>
+
+<item>
+Rudimentary organs
+</item>
+
+<item>
+Rudiments important for classification
+</item>
+
+<item>
+Sageret on grafts
+</item>
+
+<item>
+Salmons, males fighting, and hooked jaws of
+</item>
+
+<item>
+Salt-water, how far injurious to seeds
+</item>
+
+<item>
+Saurophagus sulphuratus
+</item>
+
+<item>
+Schiodte on blind insects
+</item>
+
+<item>
+Schlegel on snakes
+</item>
+
+<item>
+Sea-water, how far injurious to seeds
+</item>
+
+<item>
+Sebright, Sir J., on crossed animals; on selection of pigeons
+</item>
+
+<item>
+Sedgwick, Prof., on groups of species suddenly appearing
+</item>
+
+<item>
+Seedlings destroyed by insects
+</item>
+
+<item>
+Seeds, nutriment in; winged; power of resisting salt-water; in crops and
+intestines of birds; eaten by fish; in mud; hooked, on islands
+</item>
+
+<item>
+Selection of domestic products, principle not of recent origin;
+unconscious; natural; sexual; natural, circumstances favourable to
+</item>
+
+<item>
+Sexes, relations of
+</item>
+
+<item>
+Sexual characters variable; selection
+</item>
+
+<item>
+Sheep, Merino, their selection; two sub-breeds unintentionally produced;
+mountain, varieties of
+</item>
+
+<item>
+Shells, colours of, littoral, seldom embedded; fresh-water, dispersal of;
+of Madeira; land, distribution of
+</item>
+
+<item>
+Silene, fertility of crosses
+</item>
+
+<item>
+Silliman, Prof., on blind rat
+</item>
+
+<item>
+Skulls of young mammals
+</item>
+
+<item>
+Slave-making instinct
+</item>
+
+<item>
+Smith, Col. Hamilton, on striped horses; Mr. Fred., on slave-making ants;
+Mr., of Jordan Hill, on degradation of coast-rocks
+</item>
+
+<item>
+Snap-dragon
+</item>
+
+<item>
+Somerville, Lord, on selection of sheep
+</item>
+
+<item>
+Sorbus, grafts of
+</item>
+
+<item>
+Spaniel, King Charles's breed
+</item>
+
+<item>
+Species, groups of, suddenly appearing; beneath Silurian formations;
+successively appearing; changing simultaneously throughout the world
+</item>
+
+<item>
+Spencer, Lord, on increase in size of cattle
+</item>
+
+<item>
+Sphex, parasitic
+</item>
+
+<item>
+Spiders, development of
+</item>
+
+<item>
+Spitz-dog crossed with fox
+</item>
+
+<item>
+Sports in plants
+</item>
+
+<item>
+Sprengel, C.C., on crossing; on ray-florets
+</item>
+
+<item>
+Squirrels, gradations in structure
+</item>
+
+<item>
+Staffordshire, heath, changes in
+</item>
+
+<item>
+Stag-beetles, fighting
+</item>
+
+<item>
+Sterility from changed conditions of life; of hybrids; laws of; causes of;
+from unfavourable conditions; of certain varieties
+</item>
+
+<item>
+St. Helena, productions of
+</item>
+
+<item>
+St. Hilaire, Aug., on classification
+</item>
+
+<item>
+St. John, Mr., on habits of cats
+</item>
+
+<item>
+Sting of bee
+</item>
+
+<item>
+Stocks, aboriginal, of domestic animal
+</item>
+
+<item>
+Strata, thickness of, in Britain
+</item>
+
+<item>
+Stripes of horses
+</item>
+
+<item>
+Swallow, one species supplanting another
+</item>
+
+<item>
+Swim-bladder
+</item>
+
+<item>
+Tail of giraffe; of aquatic animals; rudimentary
+</item>
+
+<item>
+Tarsi deficient
+</item>
+
+<item>
+Tausch on umbelliferous flowers
+</item>
+
+<item>
+Teeth and hair correlated; embryonic, traces of, in birds; rudimentary, in
+embryonic calf
+</item>
+
+<item>
+Tegetmeier, Mr., on cells of bees
+</item>
+
+<item>
+Temminck on distribution aiding classification
+</item>
+
+<item>
+Thouin on grafts
+</item>
+
+<item>
+Thrush, aquatic species of; mocking, of the Galapagos; young of, spotted;
+nest of
+</item>
+
+<item>
+Thuret, M., on crossed fuci
+</item>
+
+<item>
+Thwaites, Mr., on acclimatisation
+</item>
+
+<item>
+Tierra del Fuego, dogs of; plants of
+</item>
+
+<item>
+Timber-drift
+</item>
+
+<item>
+Time, lapse of
+</item>
+
+<item>
+Titmouse
+</item>
+
+<item>
+Toads on islands
+</item>
+
+<item>
+Tobacco, crossed varieties of
+</item>
+
+<item>
+Tomes, Mr., on the distribution of bats
+</item>
+
+<item>
+Transitions in varieties
+</item>
+
+<item>
+Trees on islands belong to peculiar orders; with separated sexes
+</item>
+
+<item>
+Trifolium pratense; incarnatum
+</item>
+
+<item>
+Trigonia
+</item>
+
+<item>
+Trilobites; sudden extinction of
+</item>
+
+<item>
+Troglodytes
+</item>
+
+<item>
+Tucutucu, blind
+</item>
+
+<item>
+Tumbler pigeons, habits of, hereditary; young of
+</item>
+
+<item>
+Turkey-cock, brush of hair on breast
+</item>
+
+<item>
+Turkey, naked skin on head; young, wild
+</item>
+
+<item>
+Turnip and cabbage, analogous variations of
+</item>
+
+<item>
+Type, unity of
+</item>
+
+<item>
+Types, succession of, in same areas
+</item>
+
+<item>
+Udders enlarged by use; rudimentary
+</item>
+
+<item>
+Ulex, young leaves of
+</item>
+
+<item>
+Umbelliferae, outer and inner florets of
+</item>
+
+<item>
+Unity of type
+</item>
+
+<item>
+Use, effects of, under domestication
+</item>
+
+<item>
+Utility, how far important in the construction of each part
+</item>
+
+<item>
+Valenciennes on fresh-water fish
+</item>
+
+<item>
+Variability of mongrels and hybrids
+</item>
+
+<item>
+Variations appear at corresponding ages; analogous in distinct species
+</item>
+
+<item>
+Varieties, natural; struggle between; domestic, extinction of;
+transitional; when crossed, fertile; when crossed, sterile; classification
+of
+</item>
+
+<item>
+Verbascum, sterility of; varieties of, crossed
+</item>
+
+<item>
+Verneuil, M. de, on the succession of species
+</item>
+
+<item>
+Viola tricolor
+</item>
+
+<item>
+Volcanic islands, denudation of
+</item>
+
+<item>
+Vulture, naked skin on head
+</item>
+
+<item>
+Wading-birds
+</item>
+
+<item>
+Wallace, Mr., on origin of species; on law of geographical distribution; on
+the Malay Archipelago
+</item>
+
+<item>
+Wasp, sting of
+</item>
+
+<item>
+Water, fresh, productions of
+</item>
+
+<item>
+Water-hen
+</item>
+
+<item>
+Waterhouse, Mr., on Australian marsupials; on greatly developed parts being
+variable; on the cells of bees; on general affinities
+</item>
+
+<item>
+Water-ouzel
+</item>
+
+<item>
+Watson, Mr. H.C., on range of varieties of British plants; on
+acclimatisation; on flora of Azores; on Alpine plants; on rarity of
+intermediate varieties
+</item>
+
+<item>
+Weald, denudation of
+</item>
+
+<item>
+Web of feet in water-birds
+</item>
+
+<item>
+West Indian islands, mammals of
+</item>
+
+<item>
+Westwood on species in large genera being closely allied to others; on the
+tarsi of Engidae; on the antennae of hymenopterous insects
+</item>
+
+<item>
+Whales, fossil
+</item>
+
+<item>
+Wheat, varieties of
+</item>
+
+<item>
+White Mountains, flora of
+</item>
+
+<item>
+Wings, reduction of size
+</item>
+
+<item>
+Wings of insects homologous with branchiae; rudimentary, in insects
+</item>
+
+<item>
+Wolf crossed with dog; of Falkland Isles
+</item>
+
+<item>
+Wollaston, Mr., on varieties of insects; on fossil varieties of land-shells
+in Madeira; on colours of insects on sea-shore; on wingless beetles; on
+rarity of intermediate varieties; on insular insects; on land-shells of
+Madeira, naturalised
+</item>
+
+<item>
+Wolves, varieties of
+</item>
+
+<item>
+Woodpecker, habits of; green colour of
+</item>
+
+<item>
+Woodward, Mr., on the duration of specific forms; on the continuous
+succession of genera; on the succession of types
+</item>
+
+<item>
+World, species changing simultaneously throughout
+</item>
+
+<item>
+Wrens, nest of
+</item>
+
+<item>
+Youatt, Mr., on selection, on sub-breeds of sheep; on rudimentary horns in
+young cattle
+</item>
+
+<item>
+Zebra, stripes on 
+</item>
+
+</index>
+</backmatter>
+</book>
+<endgutblurb>
+End of this Project Gutenberg Etext of the First Edition of On the Origin
+of Species by Charles Darwin
+</endgutblurb>
+</gutbook>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/import/owlcreek.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/import/owlcreek.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/import/owlcreek.xml	(revision 13928)
@@ -0,0 +1,869 @@
+<?xml version="1.0"?>
+<!DOCTYPE gutbook SYSTEM "gutbook1.dtd">
+
+<?xml-stylesheet type="text/css" href="darwin.css"?>
+
+<gutbook>
+<gutblurb>
+<para>
+The Project Gutenberg Etext of An Occurrence at Owl Creek Bridge
+</para>
+
+<para>
+[This was the #1 rated Twilight Zone epidose of all time]
+#2 in our Ambrose Bierce series
+</para>
+
+<para>
+Copyright laws are changing all over the world, be sure to check
+the copyright laws for your country before posting these files!!
+</para>
+
+<para>
+Please take a look at the important information in this header.
+We encourage you to keep this file on your own disk, keeping an
+electronic path open for the next readers.  Do not remove this.
+</para>
+
+<para>
+**Welcome To The World of Free Plain Vanilla Electronic Texts**
+</para>
+
+<para>
+**Etexts Readable By Both Humans and By Computers, Since 1971**
+</para>
+
+<para>
+*These Etexts Prepared By Hundreds of Volunteers and Donations*
+</para>
+
+<para>
+Information on contacting Project Gutenberg to get Etexts, and
+further information is included below.  We need your donations.
+</para>
+
+<para>
+An Occurrence At Owl Creek Bridge
+</para>
+
+<para>
+by Ambrose Bierce
+</para>
+
+<para>
+December, 1995  [Etext #375]
+</para>
+
+<para>
+The Project Gutenberg Etext of An Occurrence at Owl Creek Bridge
+*****This file should be named owlcr10.txt or owlcr10.zip******
+</para>
+
+<para>
+Corrected EDITIONS of our etexts get a new NUMBER, owlcr11.txt.
+VERSIONS based on separate sources get new LETTER, owlcr10a.txt.
+</para>
+
+<para>
+We are now trying to release all our books one month in advance
+of the official release dates, for time for better editing.
+</para>
+
+<para>
+Please note:  neither this list nor its contents are final till
+midnight of the last day of the month of any such announcement.
+The official release date of all Project Gutenberg Etexts is at
+Midnight, Central Time, of the last day of the stated month.  A
+preliminary version may often be posted for suggestion, comment
+and editing by those who wish to do so.  To be sure you have an
+up to date first edition [xxxxx10x.xxx] please check file sizes
+in the first week of the next month.  Since our ftp program has
+a bug in it that scrambles the date [tried to fix and failed] a
+look at the file size will have to do, but we will try to see a
+new copy has at least one byte more or less.
+</para>
+
+<para>
+Information about Project Gutenberg (one page)
+</para>
+
+<para>
+We produce about two million dollars for each hour we work.  The
+fifty hours is one conservative estimate for how long it we take
+to get any etext selected, entered, proofread, edited, copyright
+searched and analyzed, the copyright letters written, etc.  This
+projected audience is one hundred million readers.  If our value
+per text is nominally estimated at one dollar then we produce $4
+million dollars per hour this year as we release some eight text
+files per month:  thus upping our productivity from $2 million.
+</para>
+
+<para>
+The Goal of Project Gutenberg is to Give Away One Trillion Etext
+Files by the December 31, 2001.  [10,000 x 100,000,000=Trillion]
+This is ten thousand titles each to one hundred million readers,
+which is 10% of the expected number of computer users by the end
+of the year 2001.
+</para>
+
+<para>
+We need your donations more than ever!
+</para>
+
+<para>
+All donations should be made to "Project Gutenberg/IBC", and are
+tax deductible to the extent allowable by law ("IBC" is Illinois
+Benedictine College).  (Subscriptions to our paper newsletter go
+to IBC, too)
+</para>
+
+<para>
+For these and other matters, please mail to:
+</para>
+
+<para>
+Project Gutenberg
+P. O. Box  2782
+Champaign, IL 61825
+</para>
+
+<para>
+When all other email fails try our Michael S. Hart, Executive
+Director:
+hart@vmd.cso.uiuc.edu (internet)   hart@uiucvmd   (bitnet)
+</para>
+
+<para>
+We would prefer to send you this information by email
+(Internet, Bitnet, Compuserve, ATTMAIL or MCImail).
+</para>
+
+<para>
+******
+If you have an FTP program (or emulator), please
+FTP directly to the Project Gutenberg archives:
+[Mac users, do NOT point and click. . .type]
+</para>
+
+<para>
+ftp uiarchive.cso.uiuc.edu
+login:  anonymous
+password:  your@login
+cd etext/etext90 through /etext96
+or cd etext/articles [get suggest gut for more information]
+dir [to see files]
+get or mget [to get files. . .set bin for zip files]
+GET INDEX?00.GUT
+for a list of books
+and
+GET NEW GUT for general information
+and
+MGET GUT* for newsletters.
+</para>
+
+<para>
+**Information prepared by the Project Gutenberg legal advisor**
+(Three Pages)
+</para>
+
+<para>
+***START**THE SMALL PRINT!**FOR PUBLIC DOMAIN ETEXTS**START***
+Why is this "Small Print!" statement here?  You know: lawyers.
+They tell us you might sue us if there is something wrong with
+your copy of this etext, even if you got it for free from
+someone other than us, and even if what's wrong is not our
+fault.  So, among other things, this "Small Print!" statement
+disclaims most of our liability to you.  It also tells you how
+you can distribute copies of this etext if you want to.
+</para>
+
+<para>
+*BEFORE!* YOU USE OR READ THIS ETEXT
+By using or reading any part of this PROJECT GUTENBERG-tm
+etext, you indicate that you understand, agree to and accept
+this "Small Print!" statement.  If you do not, you can receive
+a refund of the money (if any) you paid for this etext by
+sending a request within 30 days of receiving it to the person
+you got it from.  If you received this etext on a physical
+medium (such as a disk), you must return it with your request.
+</para>
+
+<para>
+ABOUT PROJECT GUTENBERG-TM ETEXTS
+This PROJECT GUTENBERG-tm etext, like most PROJECT GUTENBERG-
+tm etexts, is a "public domain" work distributed by Professor
+Michael S. Hart through the Project Gutenberg Association at
+Illinois Benedictine College (the "Project").  Among other
+things, this means that no one owns a United States copyright
+on or for this work, so the Project (and you!) can copy and
+distribute it in the United States without permission and
+without paying copyright royalties.  Special rules, set forth
+below, apply if you wish to copy and distribute this etext
+under the Project's "PROJECT GUTENBERG" trademark.
+</para>
+
+<para>
+To create these etexts, the Project expends considerable
+efforts to identify, transcribe and proofread public domain
+works.  Despite these efforts, the Project's etexts and any
+medium they may be on may contain "Defects".  Among other
+things, Defects may take the form of incomplete, inaccurate or
+corrupt data, transcription errors, a copyright or other
+intellectual property infringement, a defective or damaged
+disk or other etext medium, a computer virus, or computer
+codes that damage or cannot be read by your equipment.
+</para>
+
+<para>
+LIMITED WARRANTY; DISCLAIMER OF DAMAGES
+But for the "Right of Replacement or Refund" described below,
+[1] the Project (and any other party you may receive this
+etext from as a PROJECT GUTENBERG-tm etext) disclaims all
+liability to you for damages, costs and expenses, including
+legal fees, and [2] YOU HAVE NO REMEDIES FOR NEGLIGENCE OR
+UNDER STRICT LIABILITY, OR FOR BREACH OF WARRANTY OR CONTRACT,
+INCLUDING BUT NOT LIMITED TO INDIRECT, CONSEQUENTIAL, PUNITIVE
+OR INCIDENTAL DAMAGES, EVEN IF YOU GIVE NOTICE OF THE
+POSSIBILITY OF SUCH DAMAGES.
+</para>
+
+<para>
+If you discover a Defect in this etext within 90 days of
+receiving it, you can receive a refund of the money (if any)
+you paid for it by sending an explanatory note within that
+time to the person you received it from.  If you received it
+on a physical medium, you must return it with your note, and
+such person may choose to alternatively give you a replacement
+copy.  If you received it electronically, such person may
+choose to alternatively give you a second opportunity to
+receive it electronically.
+</para>
+
+<para>
+THIS ETEXT IS OTHERWISE PROVIDED TO YOU "AS-IS".  NO OTHER
+WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, ARE MADE TO YOU AS
+TO THE ETEXT OR ANY MEDIUM IT MAY BE ON, INCLUDING BUT NOT
+LIMITED TO WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
+PARTICULAR PURPOSE.
+</para>
+
+<para>
+Some states do not allow disclaimers of implied warranties or
+the exclusion or limitation of consequential damages, so the
+above disclaimers and exclusions may not apply to you, and you
+may have other legal rights.
+</para>
+
+<para>
+INDEMNITY
+You will indemnify and hold the Project, its directors,
+officers, members and agents harmless from all liability, cost
+and expense, including legal fees, that arise directly or
+indirectly from any of the following that you do or cause:
+[1] distribution of this etext, [2] alteration, modification,
+or addition to the etext, or [3] any Defect.
+</para>
+
+<para>
+DISTRIBUTION UNDER "PROJECT GUTENBERG-tm"
+You may distribute copies of this etext electronically, or by
+disk, book or any other medium if you either delete this
+"Small Print!" and all other references to Project Gutenberg,
+or:
+</para>
+
+<para>
+[1]  Only give exact copies of it.  Among other things, this
+     requires that you do not remove, alter or modify the
+     etext or this "small print!" statement.  You may however,
+     if you wish, distribute this etext in machine readable
+     binary, compressed, mark-up, or proprietary form,
+     including any form resulting from conversion by word pro-
+     cessing or hypertext software, but only so long as
+     *EITHER*:
+</para>
+
+<para>
+     [*]  The etext, when displayed, is clearly readable, and
+          does *not* contain characters other than those
+          intended by the author of the work, although tilde
+          (~), asterisk (*) and underline (_) characters may
+          be used to convey punctuation intended by the
+          author, and additional characters may be used to
+          indicate hypertext links; OR
+</para>
+
+<para>
+     [*]  The etext may be readily converted by the reader at
+          no expense into plain ASCII, EBCDIC or equivalent
+          form by the program that displays the etext (as is
+          the case, for instance, with most word processors);
+          OR
+</para>
+
+<para>
+     [*]  You provide, or agree to also provide on request at
+          no additional cost, fee or expense, a copy of the
+          etext in its original plain ASCII form (or in EBCDIC
+          or other equivalent proprietary form).
+</para>
+
+<para>
+[2]  Honor the etext refund and replacement provisions of this
+     "Small Print!" statement.
+</para>
+
+<para>
+[3]  Pay a trademark license fee to the Project of 20% of the
+     net profits you derive calculated using the method you
+     already use to calculate your applicable taxes.  If you
+     don't derive profits, no royalty is due.  Royalties are
+     payable to "Project Gutenberg Association / Illinois
+     Benedictine College" within the 60 days following each
+     date you prepare (or were legally required to prepare)
+     your annual (or equivalent periodic) tax return.
+</para>
+
+<para>
+WHAT IF YOU *WANT* TO SEND MONEY EVEN IF YOU DON'T HAVE TO?
+The Project gratefully accepts contributions in money, time,
+scanning machines, OCR software, public domain etexts, royalty
+free copyright licenses, and every other sort of contribution
+you can think of.  Money should be paid to "Project Gutenberg
+Association / Illinois Benedictine College".
+</para>
+
+<para>
+*END*THE SMALL PRINT! FOR PUBLIC DOMAIN ETEXTS*Ver.04.29.93*END*
+</para>
+</gutblurb>
+
+<markupblurb>
+Marked up by John Hanna Feb 2000
+Validated against gutbook1.dtd using MSXML Feb 2000
+Checked FB Feb 2000
+</markupblurb>
+
+<book>
+<acknowledge>A project of the HTML Writrs Guild and Project Gutenberg. Markup by an anonymous Project Gutenberg Volunteer, Markup by John Hanna Feb 2000</acknowledge>
+<frontmatter>
+<titlepage>
+<title>AN OCCURRENCE AT OWL CREEK BRIDGE</title>
+<para>by</para>
+<author>Ambrose Bierce</author>
+<para>
+THE MILLENNIUM FULCRUM EDITION, 1988
+</para>
+</titlepage>
+</frontmatter>
+<bookbody>
+<part>
+
+<chapter>
+<title>I</title>
+<para>
+A man stood upon a railroad bridge in northern Alabama,
+looking down into the swift water twenty feet below.  The
+man's hands were behind his back, the wrists bound with a
+cord.  A rope closely encircled his neck.  It was attached to
+a stout cross-timber above his head and the slack feel to the
+level of his knees.  Some loose boards laid upon the ties
+supporting the rails of the railway supplied a footing for
+him and his executioners -- two private soldiers of the
+Federal army, directed by a sergeant who in civil life may
+have been a deputy sheriff.  At a short remove upon the same
+temporary platform was an officer in the uniform of his rank,
+armed.  He was a captain.  A sentinel at each end of the
+bridge stood with his rifle in the position known as
+"support," that is to say, vertical in front of the left
+shoulder, the hammer resting on the forearm thrown straight
+across the chest -- a formal and unnatural position,
+enforcing an erect carriage of the body.  It did not appear
+to be the duty of these two men to know what was occurring at
+the center of the bridge; they merely blockaded the two ends
+of the foot planking that traversed it.
+</para>
+
+<para>
+Beyond one of the sentinels nobody was in sight; the railroad
+ran straight away into a forest for a hundred yards, then,
+curving, was lost to view.  Doubtless there was an outpost
+farther along.  The other bank of the stream was open ground
+-- a gentle slope topped with a stockade of vertical tree
+trunks, loopholed for rifles, with a single embrasure
+through which protruded the muzzle of a brass cannon
+commanding the bridge.  Midway up the slope between the
+bridge and fort were the spectators -- a single company of
+infantry in line, at "parade rest," the butts of their rifles
+on the ground, the barrels inclining slightly backward
+against the right shoulder, the hands crossed upon the stock.
+A lieutenant stood at the right of the line, the point
+of his sword upon the ground, his left hand resting upon his
+right.  Excepting the group of four at the center of the
+bridge, not a man moved.  The company faced the bridge,
+staring stonily, motionless.  The sentinels, facing the
+banks of the stream, might have been statues to adorn the
+bridge.  The captain stood with folded arms, silent,
+observing the work of his subordinates, but making no sign.
+Death is a dignitary who when he comes announced is to be
+received with formal manifestations of respect, even by those
+most familiar with him.  In the code of military etiquette
+silence and fixity are forms of deference.
+</para>
+
+<para>
+The man who was engaged in being hanged was apparently about
+thirty-five years of age.  He was a civilian, if one might
+judge from his habit, which was that of a planter.  His
+features were good -- a straight nose, firm mouth, broad
+forehead, from which his long, dark hair was combed straight
+back, falling behind his ears to the collar of his well
+fitting frock coat.  He wore a moustache and pointed beard,
+but no whiskers; his eyes were large and dark gray, and had a
+kindly expression which one would hardly have expected in one
+whose neck was in the hemp.  Evidently this was no vulgar
+assassin.  The liberal military code makes provision for
+hanging many kinds of persons, and gentlemen are not
+excluded.
+</para>
+
+<para>
+The preparations being complete, the two private soldiers
+stepped aside and each drew away the plank upon which he had
+been standing.  The sergeant turned to the captain, saluted
+and placed himself immediately behind that officer, who in
+turn moved apart one pace.  These movements left the
+condemned man and the sergeant standing on the two ends of
+the same plank, which spanned three of the cross-ties of the
+bridge.  The end upon which the civilian stood almost, but
+not quite, reached a fourth.  This plank had been held in
+place by the weight of the captain; it was now held by that
+of the sergeant.  At a signal from the former the latter
+would step aside, the plank would tilt and the condemned man
+go down between two ties.  The arrangement commended itself
+to his judgement as simple and effective.  His face had not
+been covered nor his eyes bandaged.  He looked a moment at
+his "unsteadfast footing," then let his gaze wander to the
+swirling water of the stream racing madly beneath his feet.
+A piece of dancing driftwood caught his attention and his
+eyes followed it down the current.  How slowly it appeared
+to move!  What a sluggish stream!
+</para>
+
+<para>
+He closed his eyes in order to fix his last thoughts upon his
+wife and children.  The water, touched to gold by the early
+sun, the brooding mists under the banks at some distance down
+the stream, the fort, the soldiers, the piece of drift -- all
+had distracted him.  And now he became conscious of a new
+disturbance.  Striking through the thought of his dear
+ones was sound which he could neither ignore nor understand,
+a sharp, distinct, metallic percussion like the stroke of a
+blacksmith's hammer upon the anvil; it had the same ringing
+quality.  He wondered what it was, and whether immeasurably
+distant or near by -- it seemed both.  Its recurrence was
+regular, but as slow as the tolling of a death knell.  He
+awaited each new stroke with impatience and -- he knew not
+why -- apprehension.  The intervals of silence grew
+progressively longer; the delays became maddening.  With
+their greater infrequency the sounds increased in strength
+and sharpness.  They hurt his ear like the trust of a knife;
+he feared he would shriek.  What he heard was the ticking of
+his watch.
+</para>
+
+<para>
+He unclosed his eyes and saw again the water below him.  "If
+I could free my hands," he thought, "I might throw off the
+noose and spring into the stream.  By diving I could evade
+the bullets and, swimming vigorously, reach the bank, take
+to the woods and get away home.  My home, thank God, is as
+yet outside their lines; my wife and little ones are still
+beyond the invader's farthest advance."
+</para>
+
+<para>
+As these thoughts, which have here to be set down in words,
+were flashed into the doomed man's brain rather than evolved
+from it the captain nodded to the sergeant.  The sergeant
+stepped aside.
+</para>
+</chapter>
+
+<chapter>
+<title>II</title>
+<para>
+Peyton Fahrquhar was a well to do planter, of an old and
+highly respected Alabama family.  Being a slave owner and
+like other slave owners a politician, he was naturally an
+original secessionist and ardently devoted to the Southern
+cause.  Circumstances of an imperious nature, which it is
+unnecessary to relate here, had prevented him from taking
+service with that gallant army which had fought the
+disastrous campaigns ending with the fall of Corinth, and he
+chafed under the inglorious restraint, longing for the
+release of his energies, the larger life of the soldier, the
+opportunity for distinction.  That opportunity, he felt,
+would come, as it comes to all in wartime.  Meanwhile he
+did what he could.  No service was too humble for him to
+perform in the aid of the South, no adventure to perilous for
+him to undertake if consistent with the character of a
+civilian who was at heart a soldier, and who in good faith
+and without too much qualification assented to at least a
+part of the frankly villainous dictum that all is fair in
+love and war.
+</para>
+
+<para>
+One evening while Fahrquhar and his wife were sitting on a
+rustic bench near the entrance to his grounds, a gray-clad
+soldier rode up to the gate and asked for a drink of water.
+Mrs. Fahrquhar was only too happy to serve him with her own
+white hands.  While she was fetching the water her husband
+approached the dusty horseman and inquired eagerly for news
+from the front.
+</para>
+
+<para>
+"The Yanks are repairing the railroads," said the man, "and
+are getting ready for another advance.  They have reached the
+Owl Creek bridge, put it in order and built a stockade on the
+north bank.  The commandant has issued an order, which is
+posted everywhere, declaring that any civilian caught
+interfering with the railroad, its bridges, tunnels, or
+trains will be summarily hanged.  I saw the order."
+</para>
+
+<para>
+"How far is it to the Owl Creek bridge?" Fahrquhar asked.
+</para>
+
+<para>
+"About thirty miles."
+</para>
+
+<para>
+"Is there no force on this side of the creek?"
+</para>
+
+<para>
+"Only a picket post half a mile out, on the railroad, and a
+single sentinel at this end of the bridge."
+</para>
+
+<para>
+"Suppose a man -- a civilian and student of hanging --
+should elude the picket post and perhaps get the better of
+the sentinel," said Fahrquhar, smiling, "what could he
+accomplish?"
+</para>
+
+<para>
+The soldier reflected.  "I was there a month ago," he
+replied.  "I observed that the flood of last winter had
+lodged a great quantity of driftwood against the wooden pier
+at this end of the bridge.  It is now dry and would burn like
+tinder."
+</para>
+
+<para>
+The lady had now brought the water, which the soldier drank.
+He thanked her ceremoniously, bowed to her husband and rode
+away.  An hour later, after nightfall, he repassed the
+plantation, going northward in the direction from which he
+had come.  He was a Federal scout.
+</para>
+</chapter>
+
+<chapter>
+<title>III</title>
+<para>
+ As Peyton Fahrquhar fell straight downward through the
+bridge he lost consciousness and was as one already dead.
+From this state he was awakened -- ages later, it seemed to
+him -- by the pain of a sharp pressure upon his throat,
+followed by a sense of suffocation.  Keen, poignant agonies
+seemed to shoot from his neck downward through every fiber of
+his body and limbs.  These pains appeared to flash along well
+defined lines of ramification and to beat with an
+inconceivably rapid periodicity.  They seemed like streams of
+pulsating fire heating him to an intolerable temperature.  As
+to his head, he was conscious of nothing but a feeling of
+fullness -- of congestion.  These sensations were
+unaccompanied by thought.  The intellectual part of his
+nature was already effaced; he had power only to feel, and
+feeling was torment.  He was conscious of motion.
+Encompassed in a luminous cloud, of which he was now merely
+the fiery heart, without material substance, he swung
+through unthinkable arcs of oscillation, like a vast
+pendulum.  Then all at once, with terrible suddenness, the
+light about him shot upward with the noise of a loud splash;
+a frightful roaring was in his ears, and all was cold and
+dark.  The power of thought was restored; he knew that the
+rope had broken and he had fallen into the stream.  There was
+no additional strangulation; the noose about his neck
+was already suffocating him and kept the water from his
+lungs.  To die of hanging at the bottom of a river! -- the
+idea seemed to him ludicrous.  He opened his eyes in the
+darkness and saw above him a gleam of light, but how distant,
+how inaccessible!  He was still sinking, for the light became
+fainter and fainter until it was a mere glimmer.  Then it
+began to grow and brighten, and he knew that he was rising
+toward the surface -- knew it with reluctance, for he was now
+very comfortable.  "To be hanged and drowned," he thought,
+"that is not so bad; but I do not wish to be shot.  No; I
+will not be shot; that is not fair."
+</para>
+
+<para>
+He was not conscious of an effort, but a sharp pain in his
+wrist apprised him that he was trying to free his hands.  He
+gave the struggle his attention, as an idler might observe
+the feat of a juggler, without interest in the outcome.  What
+splendid effort! -- what magnificent, what superhuman
+strength!  Ah, that was a fine endeavor!  Bravo!  The cord
+fell away; his arms parted and floated upward, the hands
+dimly seen on each side in the growing light.  He watched
+them with a new interest as first one and then the other
+pounced upon the noose at his neck.  They tore it away and
+thrust it fiercely aside, its undulations resembling those of
+a water snake.  "Put it back, put it back!"  He thought he
+shouted these words to his hands, for the undoing of the
+noose had been succeeded by the direst pang that he had yet
+experienced.  His neck ached horribly; his brain was on fire,
+his heart, which had been fluttering faintly, gave a great
+leap, trying to force itself out at his mouth.  His whole
+body was racked and wrenched with an insupportable anguish!
+But his disobedient hands gave no heed to the command.  They
+beat the water vigorously with quick, downward strokes,
+forcing him to the surface.  He felt his head emerge; his
+eyes were blinded by the sunlight; his chest expanded
+convulsively, and with a supreme and crowning agony his lungs
+engulfed a great draught of air, which instantly he expelled
+in a shriek!
+</para>
+
+<para>
+He was now in full possession of his physical senses.  They
+were, indeed, preternaturally keen and alert.  Something in
+the awful disturbance of his organic system had so exalted
+and refined them that they made record of things never before
+perceived.  He felt the ripples upon his face and heard their
+separate sounds as they struck.  He looked at the forest on
+the bank of the stream, saw the individual trees, the leaves
+and the veining of each leaf -- he saw the very insects upon
+them:  the locusts, the brilliant bodied flies, the gray
+spiders stretching their webs from twig to twig.  He noted
+the prismatic colors in all the dewdrops upon a million
+blades of grass.  The humming of the gnats that danced above
+the eddies of the stream, the beating of the dragon flies'
+wings, the strokes of the water spiders' legs, like oars
+which had lifted their boat -- all these made audible
+music.  A fish slid along beneath his eyes and he heard the
+rush of its body parting the water.
+</para>
+
+<para>
+He had come to the surface facing down the stream; in a
+moment the visible world seemed to wheel slowly round,
+himself the pivotal point, and he saw the bridge, the fort,
+the soldiers upon the bridge, the captain, the sergeant, the
+two privates, his executioners.  They were in silhouette
+against the blue sky.  They shouted and gesticulated,
+pointing at him.  The captain had drawn his pistol, but did
+not fire; the others were unarmed.  Their movements were
+grotesque and horrible, their forms gigantic.
+</para>
+
+<para>
+Suddenly he heard a sharp report and something struck the
+water smartly within a few inches of his head, spattering his
+face with spray.  He heard a second report, and saw one of
+the sentinels with his rifle at his shoulder, a light cloud
+of blue smoke rising from the muzzle.  The man in the water
+saw the eye of the man on the bridge gazing into his own
+through the sights of the rifle.  He observed that it was a
+gray eye and remembered having read that gray eyes were
+keenest, and that all famous marksmen had them.
+Nevertheless, this one had missed.
+</para>
+
+<para>
+A counter-swirl had caught Fahrquhar and turned him half
+round; he was again looking at the forest on the bank
+opposite the fort.  The sound of a clear, high voice in a
+monotonous singsong now rang out behind him and came across
+the water with a distinctness that pierced and subdued all
+other sounds, even the beating of the ripples in his ears.
+Although no soldier, he had frequented camps enough to know
+the dread significance of that deliberate, drawling,
+aspirated chant; the lieutenant on shore was taking a part in
+the morning's work.  How coldly and pitilessly -- with what
+an even, calm intonation, presaging, and enforcing
+tranquility in the men -- with what accurately measured
+interval fell those cruel words:
+</para>
+
+<para>
+"Company! . . . Attention!  . . . Shoulder arms! . . . Ready!
+. . . Aim!  . . . Fire!"
+</para>
+
+<para>
+Fahrquhar dived -- dived as deeply as he could.  The water
+roared in his ears like the voice of Niagara, yet he heard
+the dull thunder of the volley and, rising again toward the
+surface, met shining bits of metal, singularly flattened,
+oscillating slowly downward.  Some of them touched him on the
+face and hands, then fell away, continuing their descent.
+One lodged between his collar and neck; it was uncomfortably
+warm and he snatched it out.
+</para>
+
+<para>
+As he rose to the surface, gasping for breath, he saw that he
+had been a long time under water; he was perceptibly farther
+downstream -- nearer to safety.  The soldiers had almost
+finished reloading; the metal ramrods flashed all at once in
+the sunshine as they were drawn from the barrels,
+turned in the air, and thrust into their sockets.  The two
+sentinels fired again, independently and ineffectually.
+</para>
+
+<para>
+The hunted man saw all this over his shoulder; he was now
+swimming vigorously with the current.  His brain was as
+energetic as his arms and legs; he thought with the rapidity
+of lightning:
+</para>
+
+<para>
+"The officer," he reasoned, "will not make that martinet's
+error a second time.  It is as easy to dodge a volley as a
+single shot.  He has probably already given the command to
+fire at will.  God help me, I cannot dodge them all!"
+</para>
+
+<para>
+An appalling splash within two yards of him was followed by a
+loud, rushing sound, DIMINUENDO, which seemed to travel back
+through the air to the fort and died in an explosion which
+stirred the very river to its deeps!  A rising sheet of water
+curved over him, fell down upon him, blinded him, strangled
+him!  The cannon had taken an hand in the game.  As he shook
+his head free from the commotion of the smitten water he
+heard the deflected shot humming through the air ahead, and
+in an instant it was cracking and smashing the branches in
+the forest beyond.
+</para>
+
+<para>
+"They will not do that again," he thought; "the next time
+they will use a charge of grape.  I must keep my eye upon
+the gun; the smoke will apprise me -- the report arrives too
+late; it lags behind the missile.  That is a good gun."
+</para>
+
+<para>
+Suddenly he felt himself whirled round and round -- spinning
+like a top.  The water, the banks, the forests, the now
+distant bridge, fort and men, all were commingled and
+blurred.  Objects were represented by their colors only;
+circular horizontal streaks of color -- that was all he saw.
+He had been caught in a vortex and was being whirled on with
+a velocity of advance and gyration that made him giddy and
+sick.  In few moments he was flung upon the gravel at the
+foot of the left bank of the stream -- the southern bank --
+and behind a projecting point which concealed him from his
+enemies.  The sudden arrest of his motion, the abrasion of
+one of his hands on the gravel, restored him, and he wept
+with delight.  He dug his fingers into the sand, threw it
+over himself in handfuls and audibly blessed it.  It looked
+like diamonds, rubies, emeralds; he could think of nothing
+beautiful which it did not resemble.  The trees upon the bank
+were giant garden plants; he noted a definite order in their
+arrangement, inhaled the fragrance of their blooms.  A
+strange roseate light shone through the spaces among their
+trunks and the wind made in their branches the music of
+AEolian harps.  He had not wish to perfect his escape -- he
+was content to remain in that enchanting spot until retaken.
+</para>
+
+<para>
+A whiz and a rattle of grapeshot among the branches high
+above his head roused him from his dream.  The baffled
+cannoneer had fired him a random farewell.  He sprang
+to his feet, rushed up the sloping bank, and plunged into the
+forest.
+</para>
+
+<para>
+All that day he traveled, laying his course by the rounding
+sun.  The forest seemed interminable; nowhere did he
+discover a break in it, not even a woodman's road.  He had
+not known that he lived in so wild a region.  There was
+something uncanny in the revelation.
+</para>
+
+<para>
+By nightfall he was fatigued, footsore, famished.  The
+thought of his wife and children urged him on.  At last he
+found a road which led him in what he knew to be the right
+direction.  It was as wide and straight as a city street, yet
+it seemed untraveled.  No fields bordered it, no dwelling
+anywhere.  Not so much as the barking of a dog suggested
+human habitation.  The black bodies of the trees formed a
+straight wall on both sides, terminating on the horizon in a
+point, like a diagram in a lesson in perspective.  Overhead,
+as he looked up through this rift in the wood, shone great
+golden stars looking unfamiliar and grouped in strange
+constellations.  He was sure they were arranged in some order
+which had a secret and malign significance.  The wood on
+either side was full of singular noises, among which -- once,
+twice, and again -- he distinctly heard whispers in an
+unknown tongue.
+</para>
+
+<para>
+His neck was in pain and lifting his hand to it found it
+horribly swollen.  He knew that it had a circle of black
+where the rope had bruised it.  His eyes felt congested; he
+could no longer close them.  His tongue was swollen with
+thirst; he relieved its fever by thrusting it forward from
+between his teeth into the cold air.  How softly the turf had
+carpeted the untraveled avenue -- he could no longer feel the
+roadway beneath his feet!
+</para>
+
+<para>
+Doubtless, despite his suffering, he had fallen asleep while
+walking, for now he sees another scene -- perhaps he has
+merely recovered from a delirium.  He stands at the gate of
+his own home.  All is as he left it, and all bright and
+beautiful in the morning sunshine.  He must have traveled the
+entire night.  As he pushes open the gate and passes up the
+wide white walk, he sees a flutter of female garments; his
+wife, looking fresh and cool and sweet, steps down from the
+veranda to meet him.  At the bottom of the steps she stands
+waiting, with a smile of ineffable joy, an attitude of
+matchless grace and dignity.  Ah, how beautiful she is!  He
+springs forwards with extended arms.  As he is about to clasp
+her he feels a stunning blow upon the back of the neck; a
+blinding white light blazes all about him with a sound like
+the shock of a cannon -- then all is darkness and silence!
+</para>
+
+<para>
+Peyton Fahrquhar was dead; his body, with a broken neck,
+swung gently from side to side beneath the timbers of the
+Owl Creek bridge.
+</para>
+
+<para>
+End of The Project Gutenberg Etext of An Occurrence at Owl Creek Bridge
+</para>
+</chapter>
+</part>
+</bookbody>
+</book>
+</gutbook>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/index/buildConfig.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/index/buildConfig.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/index/buildConfig.xml	(revision 13928)
@@ -0,0 +1,16 @@
+<buildConfig xmlns:gsf="http://www.greenstone.org/greenstone3/schema/ConfigFormat" >
+  <metadataList>
+    <metadata name="numDocs">4</metadata>
+    <metadata name="buildType">lucene</metadata>
+  </metadataList>
+  <serviceRackList>
+    <serviceRack name="GutBookRetrieve">
+      <paramList>
+	<param name="tocXSLT" value="produce-toc"/>
+	<param name="documentEncoding" value="UTF-8"/>
+	<param name="documentRootTag" value="book"/>
+      </paramList>
+    </serviceRack>
+    <serviceRack name="LuceneSearch"/>
+  </serviceRackList>
+</buildConfig>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/java/BuildXMLColl.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/java/BuildXMLColl.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/java/BuildXMLColl.java	(revision 13928)
@@ -0,0 +1,59 @@
+/**
+ *
+ * class for building a simple  XML collection 
+ * @author  kjdon@cs.waikato.ac.nz
+ * @version 
+ */
+
+
+import org.greenstone.gsdl3.util.GSFile;
+
+import java.io.File;
+
+public class BuildXMLColl {
+
+    public static void main (String args[]) throws Exception { 
+	if (args.length != 2) {
+	    System.out.println("Usage: java BuildXMLColl site-home coll-name");
+	    return;
+	}
+ 
+	String site_home = args[0];
+	String coll_name = args[1];
+
+	File import_dir = new File(GSFile.collectionImportDir(site_home, coll_name));
+	File building_dir = new File(GSFile.collectionBuildDir(site_home, coll_name));
+
+	if (!import_dir.exists()) {
+	    System.out.println("Couldn't find import dir for collection "+coll_name);
+	    return;
+	}
+
+	if (building_dir.exists()) {
+	    // get rid of it
+	    GSFile.deleteFile(building_dir);
+	}
+	building_dir.mkdir();
+	
+	File idx_dir = new File(building_dir.getPath()+File.separator+"idx"+File.separator+"temp.txt");
+	idx_dir = idx_dir.getParentFile();
+	File text_dir = new File(building_dir.getPath()+File.separator+"text"+File.separator+"temp.txt");
+	text_dir = text_dir.getParentFile();
+	idx_dir.mkdir();
+	text_dir.mkdir();
+	
+	// first we import the coll
+	ImportXML importer = new ImportXML();
+	importer.setOutDir(text_dir);
+	importer.init();
+	importer.importFile(import_dir);
+	importer.finish();
+	
+	// then we index it
+	IndexXML indexer = new IndexXML();
+	indexer.setOutDir(idx_dir);
+	indexer.init();
+	indexer.indexFile(text_dir);
+	indexer.finish();
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/java/ImportXML.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/java/ImportXML.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/java/ImportXML.java	(revision 13928)
@@ -0,0 +1,116 @@
+/**
+ *
+ * @author  kjdon@cs.waikato.ac.nz
+ * @version 
+ */
+
+
+// gsdl3 classes
+import org.greenstone.gsdl3.util.XMLConverter;
+import org.greenstone.gsdl3.util.GSFile;
+// XML classes
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.traversal.NodeIterator;
+import org.w3c.dom.traversal.NodeFilter;
+import org.w3c.dom.traversal.DocumentTraversal;
+import org.apache.xml.serialize.XMLSerializer;
+import org.xml.sax.InputSource;
+import org.xml.sax.EntityResolver;
+// java classes
+import java.io.File;
+import java.io.FileOutputStream;
+
+public class ImportXML
+    implements EntityResolver {
+    File out_dir = null;
+    XMLConverter converter = null;
+
+    String base_path = null;
+    public ImportXML() {
+	converter = new XMLConverter();
+	converter.setEntityResolver(this);
+	
+    }
+    public void setOutDir(File out_dir) {
+	this.out_dir = out_dir;
+    }
+    public void init() {
+
+    }
+    public void importFile(File file) throws Exception {
+	importFile(file, "");
+    }
+    protected void importFile(File file, String local_path) throws Exception {
+
+	if (file.isDirectory()) {
+	    File files []  = file.listFiles();
+	    for (int i=0; i<files.length; i++) {
+		//if (files[i].getName().endsWith(".xml")) {
+		importFile(files[i], local_path+File.separator+files[i].getName());
+		    //}
+	    }
+	    return;
+	}
+
+	base_path = file.getPath();
+	base_path = base_path.substring(0, base_path.lastIndexOf(File.separatorChar));
+	System.out.println("base path = "+base_path);
+	// now we have an actual file
+	System.out.println("processing file "+file.getPath());
+	File out_file = new File (out_dir, local_path);
+	String name = file.getName();
+	if (name.endsWith(".dtd")) {
+	    if (!GSFile.copyFile(file, out_file)) {
+		System.err.println("couldn't copy dtd file "+file.getPath()+" to "+out_file.getPath()+"- please do the copy yourself");
+	    }
+	    //copy the file
+	    return;
+	}
+	if (!name.endsWith(".xml")) {
+	    // now we ignore any that don't end in .xml
+	    return;
+	}
+	// now do the importing
+	Document doc = converter.getDOM(file);
+	
+        String gs3NS = "http://www.greenstone.org/gs3";
+	
+        Element rootNode = doc.getDocumentElement();
+        
+        rootNode.setAttribute("xmlns:gs3", gs3NS);
+       
+        DocumentTraversal traversal = (DocumentTraversal)doc;
+        NodeIterator i = traversal.createNodeIterator(doc, NodeFilter.SHOW_ELEMENT, null, true);
+        
+        Element element = null;
+        Node node = null;
+        int id = 0;
+        while ((node = i.nextNode()) != null) {
+            element = (Element)node;
+	    if (XMLTagInfo.isIndexable(element.getNodeName())) {
+		element.setAttribute("gs3:id", Integer.toString(id++));
+	    }
+        }
+        
+        XMLSerializer gs3Serializer = new XMLSerializer(new FileOutputStream(out_file), null);
+        gs3Serializer.asDOMSerializer().serialize(doc);
+        
+    }
+
+    public void finish() {
+    }
+    
+    public InputSource resolveEntity (String public_id, String system_id) {
+	
+	if (system_id.startsWith("file://")) {
+	    return new InputSource(system_id);
+	}
+	if (!system_id.startsWith(File.separator)) {
+	    system_id = base_path+File.separatorChar+system_id;
+	}
+	return new InputSource("file://"+system_id);
+    }
+
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/java/IndexXML.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/java/IndexXML.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/java/IndexXML.java	(revision 13928)
@@ -0,0 +1,43 @@
+
+/**
+ *
+ * @author  kjdon@cs.waikato.ac.nz
+ * @version 
+ */
+
+import java.io.File;
+
+public class IndexXML extends Object {
+
+    File out_dir = null;
+    Indexer indexer = null;
+    
+    public void setOutDir(File out_dir) {
+	this.out_dir = out_dir;
+    }
+
+    public void init() {
+	indexer = new Indexer(out_dir, true);
+    }
+    public void finish() {
+	indexer.finish();
+    }
+    public void indexFile(File file) {
+	
+	if (file.isDirectory()) {
+	    File[] files = file.listFiles();
+	    for (int i=0; i<files.length; i++) {
+		if (files[i].isDirectory() || files[i].getName().endsWith(".xml")) {
+		    indexFile(files[i]);
+		}
+	    }
+	    
+	} else {
+	    String name = file.getName();
+	    name = name.substring(0, name.lastIndexOf('.'));
+	    System.out.println("Indexing "+file.getPath()+" with id "+name);
+	    this.indexer.index(name, file);
+	}
+    }
+        
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/java/Indexer.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/java/Indexer.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/java/Indexer.java	(revision 13928)
@@ -0,0 +1,202 @@
+import org.greenstone.gsdl3.util.GSEntityResolver;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+//import org.xml.sax.SAXParseException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+//import org.apache.lucene.document.DateField;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+//import org.apache.lucene.analysis.SimpleAnalyzer;
+
+import java.util.Stack;
+import java.io.FileInputStream;
+import java.io.File;
+import java.net.URL;
+
+
+
+public class Indexer extends DefaultHandler {
+    IndexWriter writer = null;
+    SAXParser sax_parser = null;
+    Stack stack = null;
+    String path = "";
+    String current_node = "";
+    String current_contents = "";
+    Document current_doc = null;
+    String scope = "";
+    protected String file_id = null;
+    private String base_path = null;
+    /** pass in true if want to create a new index, false if want to use the existing one */
+    public Indexer (File index_dir, boolean create) {
+	try {
+	    stack = new Stack();
+	    SAXParserFactory sax_factory = SAXParserFactory.newInstance();
+	    sax_parser = sax_factory.newSAXParser();
+	    writer = new IndexWriter(index_dir.getPath(), new StandardAnalyzer(), create);
+	    if (create) {
+		writer.optimize();
+	    }
+
+	} catch (Exception e) {
+
+	}
+    }
+
+    /** index one document */
+    public void index (String file_id, File file) {
+	this.file_id = file_id;
+	this.path = "";
+	this.base_path = file.getPath();
+	this.base_path = this.base_path.substring(0, this.base_path.lastIndexOf(File.separatorChar));
+	try {
+            sax_parser.parse(new InputSource(new FileInputStream(file)), this);
+        }
+        catch (Exception e) {
+	    println("parse error:");
+            e.printStackTrace();
+	}
+    }
+    
+    /** optimise the index */
+    public void finish() {
+	try {
+	    writer.optimize();
+	    writer.close();
+	} catch (Exception e) {}
+    }
+
+    protected void println(String s) { System.out.println(s); }
+
+    public void startDocument() throws SAXException {
+        println("Starting to index " + file_id);
+    }
+    public void endDocument() throws SAXException {
+        println("... indexing finished.");
+    }
+    public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
+	path = appendPathLink(path, qName, atts);
+	if (XMLTagInfo.isScopable(qName)) {
+	    scope = qName;
+	}
+	if (XMLTagInfo.isIndexable(qName)) {
+	    pushOnStack();
+	    current_node = qName;	
+	    System.out.println("going to index "+qName );
+	    String node_id = "";
+	    String id = "<"+qName;
+	    for (int i=0; i<atts.getLength(); i++) {
+		String name = atts.getQName(i);
+		String value = atts.getValue(i);
+		if (name!=null && value != null) {
+		    id += " "+name+"="+value;
+		}
+		if (name.equals("gs3:id")) {
+		    node_id = value;
+		}
+	    }
+	    id += "/>";
+
+	    if (scope.equals(qName)) {
+		current_doc.add(Field.UnIndexed("nodeID", this.file_id+"."+qName));
+	    } else {
+		current_doc.add(Field.UnIndexed("nodeID", this.file_id+"."+scope+"."+qName+"."+node_id));
+	    }
+	}
+    }
+    public void endElement(String uri, String localName, String qName) throws SAXException {
+	if (XMLTagInfo.isIndexable(qName) && qName.equals(current_node)) {
+	    current_doc.add(Field.UnStored("content", current_contents));
+	    try {
+		writer.addDocument(current_doc);
+	    } catch (java.io.IOException e) {
+		e.printStackTrace();
+	    }
+	    popOffStack();
+	}
+	
+	path = removePathLink(path);
+    }
+
+    public void characters(char ch[], int start, int length) throws SAXException {
+	String data = new String(ch, start, length).trim();
+	if (data.length() > 0 ) {
+	    current_contents += data;
+	}
+    }
+    
+    protected String appendPathLink(String path, String qName, Attributes atts) {
+
+	path = path + "/"+qName;
+	if (atts.getLength()>0) {
+	    String id = atts.getValue("gs3:id");
+	    if (id != null) {
+		path +=  "[@gs3:id='"+id+"']";
+	    }
+	}
+	return path;
+    }
+    protected String  removePathLink(String path) {
+
+	int i=path.lastIndexOf('/');
+	if (i==-1) {
+	    path="";
+	} else {
+	    path = path.substring(0, i);
+	}
+	return path;
+    }
+    /** these are what we save on the stack */
+    private class MyDocument {
+
+	public Document doc = null;
+	public String contents = null;
+	public String tagname = "";
+	
+    }
+    protected void pushOnStack() {
+	if (current_doc != null) {
+	    MyDocument save = new MyDocument();
+	    save.doc = current_doc;
+	    save.contents = current_contents;
+	    save.tagname = current_node;
+	    stack.push(save);
+	}
+	current_doc = new Document();
+	current_contents = "";
+	current_node = "";
+    }
+
+    protected void popOffStack() {
+	if (!stack.empty()) {
+	    MyDocument saved = (MyDocument)stack.pop();
+	    current_doc = saved.doc;
+	    current_contents = saved.contents;
+	    current_node = saved.tagname;
+	} else {
+	    current_doc = new Document();
+	    current_contents = "";
+	    current_node = "";
+	}
+    }
+
+    public InputSource resolveEntity (String public_id, String system_id) {
+	
+	if (system_id.startsWith("file://")) {
+	    return new InputSource(system_id);
+	}
+	if (!system_id.startsWith(File.separator)) {
+	    system_id = base_path+File.separatorChar+system_id;
+	}
+	return new InputSource("file://"+system_id);
+    }
+
+}
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/java/Search.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/java/Search.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/java/Search.java	(revision 13928)
@@ -0,0 +1,84 @@
+/*
+ * search.java
+ *
+ * Created on 25 February 2003, 02:25
+ */
+
+
+/**
+ *
+ * @author  kjdon@cs.waikato.ac.nz
+ * @version 
+ */
+
+import java.io.IOException;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.search.Searcher;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.Hits;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.index.Term;
+
+public class Search  {
+
+    public static void main (String args[]) {
+	
+	if (args.length == 0) {
+	    System.out.println("Usage: Search <index directory>");
+	    return;
+	}
+        try {
+	    Searcher searcher = new IndexSearcher(args[0]);
+	    Analyzer analyzer = new StandardAnalyzer();
+
+	    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
+	    while (true) {
+		System.out.print("Query: ");
+		String line = in.readLine();
+		
+		if (line.length() == -1)
+		    break;
+		
+		Term term = new Term("content",line);
+		
+		Query query = new TermQuery(term);
+		System.out.println("Searching for: " + query.toString("content"));
+		
+		Hits hits = searcher.search(query);
+		System.out.println(hits.length() + " total matching documents");
+		
+		final int HITS_PER_PAGE=10;
+		
+		for (int start = 0; start < hits.length(); start += HITS_PER_PAGE) {
+		    int end = Math.min(hits.length(), start + HITS_PER_PAGE);
+		    for (int i = start; i < end; i++) {
+			Document doc = hits.doc(i);
+			String node_id= doc.get("nodeID");
+			System.out.println(i + ". ID: "+node_id);
+		    }
+		    
+		    if (hits.length() > end) {
+			System.out.print("more (y/n) ? ");
+			line = in.readLine();
+			if (line.length() == 0 || line.charAt(0) == 'n')
+			    break;
+		    }
+		}
+		
+	    }
+	    
+	    searcher.close();
+	}
+	catch (Exception e) {
+	    System.out.println(" caught a " + e.getClass() +
+			       "\n with message: " + e.getMessage());
+        }
+    }
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/java/XMLTagInfo.java
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/java/XMLTagInfo.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/java/XMLTagInfo.java	(revision 13928)
@@ -0,0 +1,23 @@
+/** XMLTagInfo
+ * contains any methods that are specific to what kind of XML you are working on
+ */
+
+public class XMLTagInfo {
+
+    public static boolean isIndexable(String tag) {
+	if (tag.equals("chapter") || tag.equals("part") || tag.equals("frontmatter") || tag.equals("appendix") || tag.equals("index") || tag.equals("glossary") || tag.equals("biblio")) {
+	    return true;
+	} 
+	return false;
+    }
+
+    public static boolean isScopable(String tag) {
+
+	if (tag.equals("bookbody") || tag.equals("frontmatter") || tag.equals("backmatter")) {
+	    return true;
+	} 
+	return false;
+    }
+
+    
+}
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/resources/bookfrag.dtd
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/resources/bookfrag.dtd	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/resources/bookfrag.dtd	(revision 13928)
@@ -0,0 +1,529 @@
+<!--This is bookfrag DTD-->
+
+<!--entity declarations-->
+<!--#############################################-->
+
+<!ENTITY % stdatts 
+"ref   IDREF  #IMPLIED
+ id    ID     #IMPLIED
+ type  CDATA  #IMPLIED
+ role  CDATA  #IMPLIED
+ class CDATA  #IMPLIED"
+>
+
+<!ENTITY % inline.class "|quote|emph|ital|reference|date|place|name|graphic|txterr|mkuperr|misc ">
+
+<!ENTITY % block.class "|letter|blockquote|footnote|note|list|deflist|table|blockgraphic">
+
+
+<!-- the top level element-->
+<!--##############################################-->
+
+<!ELEMENT book (acknowledge?,meta*,frontmatter?,bookbody,backmatter?,endmeta*)>
+
+<!--begin top level element declarations-->
+<!--##############################################-->
+
+
+<!--the acknowledge element is for a simple statement 
+designed to be placed at the beginning of the visible document.
+Suggested content:
+  Name of Book
+  Author
+  PG and HWG blurb
+  Original Transcriber + date
+  Marker 
+  e.g.
+  "Origin of the Species by Charles Darwin
+  A project of Project Gutenberg and the HTML Writers Guild.
+  Transcribed by  
+  Markup by Frank Boumphrey. Jan 22 2000"
+  -->
+
+<!ELEMENT acknowledge (#PCDATA %inline.class;)*>
+<!ATTLIST acknowledge
+  %stdatts;
+>
+
+<!--the meta tags are here to provide a means for comment 
+at either the very beginning or end of the document-->
+<!ELEMENT meta EMPTY>
+<!ATTLIST meta
+   content  CDATA  #REQUIRED
+   id       ID     #IMPLIED
+>
+
+<!ELEMENT endmeta EMPTY >
+<!ATTLIST endmeta
+   content  CDATA  #REQUIRED
+   id       ID     #IMPLIED
+>
+
+
+
+<!--the bookbody element contains the body of the book it can 
+consist of either part or chapter divisions-->
+
+<!ELEMENT bookbody (part*|chapter*)>
+
+<!--
+the backmatter element contains the backmatter of the book -->
+
+<!ELEMENT backmatter ((appendix|index|glossary|biblio|note)*,colophon?)>
+
+<!--The endmeta tag is groupedwith its twin meta-->
+
+
+<!--end top level element declarations-->
+
+<!--begin frontmatter element declarations-->
+<!--##############################################-->
+
+<!ELEMENT frontmatter (htitlepage|copypage|epigraph|titlepage|
+                toc|acksect|dedication|preface|introduction|miscfm)*>
+
+<!ELEMENT htitlepage (#PCDATA|title|subtitle|author|para|poem|song %inline.class;)*>
+<!ATTLIST htitlepage
+  %stdatts;
+>
+
+<!ELEMENT copypage (#PCDATA|para|poem|song|note %inline.class;)*>
+<!ATTLIST copypage
+  %stdatts;
+>
+
+<!ELEMENT epigraph (#PCDATA|para|poem|song|note|blockquote %inline.class;)*>
+<!ATTLIST epigraph
+  %stdatts;
+>
+
+
+<!ELEMENT titlepage (#PCDATA|partnum|title|subtitle|author|pubinfo|para|poem|song|note|line %inline.class;)*>
+<!ATTLIST titlepage
+  %stdatts;
+>
+
+<!ELEMENT pubinfo (#PCDATA|para|line %inline.class;)*>
+<!ATTLIST pubinfo
+  %stdatts;
+>
+
+
+<!ELEMENT toc (#PCDATA|title|subtitle|subsubtitle|item|list|deflist %inline.class;)*>
+<!--use type or role to describe toctype="other"-->
+<!ATTLIST toc
+  toctype (contents|maps|graphics|tables|other) "contents" 
+  %stdatts;
+>
+
+<!ELEMENT acksect (#PCDATA|para|poem|song|note %inline.class;)*>
+<!ATTLIST acksect
+  %stdatts;
+>
+
+<!ELEMENT dedication (#PCDATA|title|para|poem|song|note %inline.class;)*>
+<!ATTLIST dedication
+  %stdatts;
+>
+
+
+<!ELEMENT preface ((title|chapheader)?,(para|poem|song|sect1|simplesect %block.class;)*,endchap?,preauthor?)>
+<!ATTLIST preface  %stdatts;
+>
+
+<!ELEMENT introduction ((title|chapheader)?,(para|poem|song|sect1|simplesect %block.class;)*,endchap?)>
+<!ATTLIST introduction  %stdatts;
+>
+
+<!ELEMENT miscfm (#PCDATA|para|poem|song|note %inline.class;)*>
+<!ATTLIST miscfm
+  %stdatts;
+>
+
+<!ELEMENT preauthor (#PCDATA|author %inline.class;)*>
+<!ATTLIST preauthor
+  %stdatts;
+>
+
+
+
+<!--end frontmatter element declarations-->
+
+<!--begin bookbody element declarations-->
+<!--##############################################-->
+
+
+<!ELEMENT part (acknowledge?,(titlepage|toc|htitlepage)*,chapter*)>
+<!ATTLIST part
+  %stdatts;
+>
+
+<!ELEMENT chapter ((title|chapheader)?,(para|poem|song|sect1|simplesect|page %block.class;)*,endchap?)>
+<!ATTLIST chapter  %stdatts;
+>
+
+<!--end bookbody element declarations-->
+
+<!--the lowerlevel bookbody elements-->
+<!--##############################################-->
+
+<!--the chapter heading elements-->
+<!--##############################################-->
+
+
+
+
+<!ELEMENT title (#PCDATA %inline.class;)*>
+<!ATTLIST title
+  %stdatts;
+>
+
+<!ELEMENT subtitle (#PCDATA %inline.class;)*>
+<!ATTLIST subtitle
+  %stdatts;
+>
+
+<!ELEMENT subsubtitle (#PCDATA %inline.class;)*>
+<!ATTLIST subsubtitle
+  %stdatts;
+>
+
+
+
+<!--validity constraint. Only one title,chapnum and chapsummary -->
+<!ELEMENT chapheader (title|subtitle|chapnum|chapsummary|blockquote|para|note)*>
+<!ATTLIST chapheader
+  %stdatts;
+>
+
+
+<!ELEMENT chapnum (#PCDATA %inline.class;)*>
+<!ATTLIST chapnum
+  %stdatts;
+>
+
+<!ELEMENT chapsummary (#PCDATA %inline.class;)*>
+<!ATTLIST chapsummary
+  %stdatts;
+>
+
+
+<!--begin backmatter element declarations-->
+<!--##############################################-->
+
+<!--end backmatter element declarations-->
+
+<!ELEMENT index (title|item|list|deflist|note)*>
+<!ATTLIST index
+  indtype (contents|authors|firstlines|tables|other) "contents" 
+  %stdatts;
+>
+
+<!ELEMENT glossary (title|item|list|deflist|note)*>
+<!ATTLIST glossary  
+  %stdatts;
+>
+
+<!ELEMENT biblio (title|item|list|deflist|note)*>
+<!ATTLIST biblio  
+  %stdatts;
+>
+
+
+<!ELEMENT appendix ((title|chapheader)?,(para|poem|song|sect1|simplesect %block.class;)*,endchap?)>
+<!ATTLIST appendix  %stdatts;
+>
+
+<!ELEMENT colophon (#PCDATA|para|poem|song %inline.class;)*>
+<!ATTLIST colophon
+  %stdatts;
+>
+
+<!--the block elements-->
+<!--##############################################-->
+
+
+<!--validity constraint. Only one title per paragraph-->
+<!ELEMENT para (#PCDATA|title %inline.class;)*>
+<!ATTLIST para
+  %stdatts;
+>
+
+<!ELEMENT simplesect (title,(subtitle|para|poem|song %block.class;)*)>
+<!ATTLIST simplesect
+  %stdatts;
+>
+
+<!ELEMENT sect1 (title,(sect2|simplesect|para|poem|song %block.class;)*)>
+<!ATTLIST sect1
+  %stdatts;
+>
+
+<!ELEMENT sect2 (title,(sect3|simplesect|subtitle|para|poem|song  %block.class;)*)>
+<!ATTLIST sect2
+  %stdatts;
+>
+
+<!ELEMENT sect3 (title,(sect4|simplesect|subtitle|para|poem|song  %block.class;)*)>
+<!ATTLIST sect3
+  %stdatts;
+>
+
+<!ELEMENT sect4 (title,(simplesect|subtitle|para|poem|song  %block.class;)*)>
+<!ATTLIST sect4
+  %stdatts;
+>
+
+<!ELEMENT page (#PCDATA %inline.class;)*>
+<!ATTLIST page
+  %stdatts;
+>
+
+<!ELEMENT misc (#PCDATA %inline.class;)*>
+<!ATTLIST misc
+  %stdatts;
+>
+
+
+
+<!ELEMENT blockquote (title?,(para|poem|song)*,attrib?)>
+<!ATTLIST blockquote
+  %stdatts;
+>
+
+<!ELEMENT attrib (#PCDATA %inline.class;)*>
+<!ATTLIST attrib
+  %stdatts;
+>
+
+<!ELEMENT caption (#PCDATA %inline.class;)*>
+<!ATTLIST caption
+  %stdatts;
+>
+<!--##############################################-->
+<!--poetry and songs in the text-->
+<!ELEMENT poem (#PCDATA|title|subtitle|verse|line|note|footnote %inline.class;)*>
+<!ATTLIST poem
+  %stdatts;
+>
+
+<!ELEMENT song (#PCDATA|title|subtitle|verse|line|note|footnote %inline.class;)*>
+<!ATTLIST song
+  %stdatts;
+>
+
+
+<!ELEMENT verse (title|subtitle|line|note)*>
+<!ATTLIST verse
+  %stdatts;
+>
+
+<!ELEMENT line (#PCDATA %inline.class;)*>
+<!ATTLIST line
+  %stdatts;
+>
+
+
+<!--validity constraint: Only one title per poem or per verse-->
+
+<!--end of poetry in the text-->
+
+<!--letter module-->
+
+<!ELEMENT letter (address|to|from|salut|sig|title|subtitle|para|poem|song|line|note)*>
+<!ATTLIST letter
+  %stdatts;
+>
+
+<!ELEMENT address (#PCDATA|para|line %inline.class;)*>
+<!ATTLIST address
+  %stdatts;
+>
+
+<!ELEMENT to (#PCDATA|para|line %inline.class;)*>
+<!ATTLIST to
+  %stdatts;
+>
+
+
+<!ELEMENT from (#PCDATA|para|line %inline.class;)*>
+<!ATTLIST from
+  %stdatts;
+>
+
+
+<!ELEMENT salut (#PCDATA|para|line %inline.class;)*>
+<!ATTLIST salut
+  %stdatts;
+>
+
+
+<!ELEMENT sig (#PCDATA|para|line %inline.class;)*>
+<!ATTLIST sig
+  %stdatts;
+>
+
+
+<!--end letters module-->
+<!--endchap-->
+<!--##############################################-->
+<!--
+  Endchap should only be used when there is a 
+  considerable ammount of material to be organized.
+  For the occasional note footnote and note will suffice
+-->
+
+<!ELEMENT endchap (para %block.class;)*>
+<!ATTLIST endchap  %stdatts;
+>
+
+<!--lists-->
+<!--##############################################-->
+
+
+<!ELEMENT list (title?,(list|item)*)>
+<!ATTLIST list
+  %stdatts;
+>
+
+<!ELEMENT item (#PCDATA|para|poem|song|simplesect %block.class; %inline.class;)*>
+<!ATTLIST item
+  %stdatts;
+>
+
+<!ELEMENT deflist (title?,(item,desc?,def*)*)>
+<!ATTLIST deflist
+  %stdatts;
+>
+
+<!ELEMENT desc (#PCDATA %inline.class;)*>
+<!ATTLIST desc
+  %stdatts;
+>
+
+<!ELEMENT def (#PCDATA %inline.class;)*>
+<!ATTLIST def
+  %stdatts;
+>
+<!--end lists-->
+<!--table element-->
+<!--##############################################-->
+
+
+<!ELEMENT table (title?,row*,caption?)>
+<!ATTLIST table
+  %stdatts;
+>
+
+<!ELEMENT row (cell)*>
+<!ATTLIST row
+  %stdatts;
+>
+
+<!ELEMENT cell (#PCDATA %block.class; %inline.class;)*>
+<!ATTLIST cell
+  %stdatts;
+>
+
+<!--end table-->
+
+<!--graphics-->
+<!--##############################################-->
+
+<!--
+  Note that the required desc attribute is added 
+  text composed by the marker.
+-->
+
+<!ELEMENT graphic EMPTY >
+<!ATTLIST graphic
+  desc CDATA #REQUIRED
+  href CDATA #REQUIRED
+  %stdatts;
+>
+
+<!ELEMENT blockgraphic (title?,graphic,caption?)>
+<!ATTLIST blockgraphic
+  %stdatts;
+>
+
+
+<!--the inline elements-->
+<!--##############################################-->
+
+
+
+<!ELEMENT footnote (#PCDATA %inline.class;)*>
+<!ATTLIST footnote
+  %stdatts;
+>
+
+<!ELEMENT note (#PCDATA %inline.class;)*>
+<!ATTLIST note
+  %stdatts;
+>
+
+
+<!ELEMENT quote (#PCDATA %inline.class;)*>
+<!ATTLIST quote
+  %stdatts;
+>
+
+<!ELEMENT emph (#PCDATA %inline.class;)*>
+<!ATTLIST emph
+  %stdatts;
+>
+
+<!ELEMENT ital (#PCDATA %inline.class;)*>
+<!ATTLIST ital
+  %stdatts;
+>
+
+<!ELEMENT reference (#PCDATA %inline.class;)*>
+<!ATTLIST reference
+  %stdatts;
+>
+
+<!ELEMENT author (#PCDATA %inline.class;)*>
+<!ATTLIST author
+  %stdatts;
+>
+
+<!ELEMENT date (#PCDATA %inline.class;)*>
+<!ATTLIST date
+  %stdatts;
+>
+
+<!ELEMENT place (#PCDATA %inline.class;)*>
+<!ATTLIST place
+  %stdatts;
+>
+
+<!ELEMENT name (#PCDATA %inline.class;)*>
+<!ATTLIST name
+  %stdatts;
+>
+
+
+<!--use to enclose the text you think is in error
+optional explanation if error is not obvious-->
+<!ELEMENT txterr (#PCDATA)*>
+<!ATTLIST txterr
+  explain  CDATA  #IMPLIED
+  %stdatts;
+>
+
+<!--an explanation is required-->
+<!ELEMENT mkuperr EMPTY>
+<!ATTLIST mkuperr
+  explain  CDATA  #REQUIRED
+  %stdatts;
+>
+
+<!--added as titlepage content  Feb/6/00-->
+<!ELEMENT partnum (#PCDATA %inline.class;)*>
+<!ATTLIST partnum
+  %stdatts;
+>
+
+<!--End of bookfrag dtd-->
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/resources/gutbook1.dtd
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/resources/gutbook1.dtd	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/resources/gutbook1.dtd	(revision 13928)
@@ -0,0 +1,40 @@
+<!--
+GUTBOOK DTD V 1.0
+==================
+
+GENERAL NOTES
++++++++++++++
+This is gutbook dtd version 1.0
+file name is gutpoems1.dtd
+This dtd is a first pass at a dtd for marking up 
+books for project gutenberg.
+It was originally developed for marking up the Darwins books.
+
+REVISION HISTORY
+++++++++++++++++
+Original Author
+Frank Boumphrey  1/19/2000
+
+COPYRIGHT NOTICE
+++++++++++++++++
+This DTD is the copyright of the HTML writers guild.
+Permission is given in perpetuity for any one to use 
+this DTD provided that these notes and this  copyright 
+notice is included.
+
+
+-->
+
+<!--Begin gutbook DTD-->
+<!ELEMENT gutbook (gutblurb,markupblurb,book*,endmarkupblurb?,endgutblurb?)>
+
+<!ELEMENT gutblurb (#PCDATA|para|simplesect|title)*>
+<!ELEMENT markupblurb (#PCDATA|para|simplesect|title)*>
+<!ELEMENT endmarkupblurb (#PCDATA|para|simplesect|title)*>
+<!ELEMENT endgutblurb (#PCDATA|para|simplesect|title)*>
+
+<!--Include bookfrag.dtd-->
+
+<!ENTITY % bookfrag SYSTEM "bookfrag.dtd">
+%bookfrag;
+<!--end of file-->
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/transform/about.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/transform/about.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/transform/about.xsl	(revision 13928)
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+
+  <!-- style includes global params interface_name, library_name -->
+  <xsl:include href="style.xsl"/>
+
+  <xsl:output method="html"/>  
+
+  <xsl:template name="pageTitle">
+    Sample XML Texts Collection
+  </xsl:template>
+
+  <!-- page specific style goes here -->
+  <xsl:template name="pageStyle"/>
+
+  <xsl:template match="pageResponse">
+    <xsl:apply-templates select="collection"/>
+  </xsl:template>
+
+  <xsl:template match="collection">
+    <xsl:variable name="collName" select="@name"/>
+    <xsl:call-template name="standardPageBanner">
+      <xsl:with-param name="collName" select="$collName"/>
+      <xsl:with-param name="pageType">about</xsl:with-param>
+    </xsl:call-template>
+    <xsl:call-template name="navigationBar">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>      
+    <p/><xsl:value-of select="displayItem[@name='description']" disable-output-escaping='yes'/>
+    <p/><xsl:apply-templates select="documentList">
+      <xsl:with-param name="collName" select="@name"/>
+    </xsl:apply-templates>
+  </xsl:template>
+  
+  <xsl:template match="documentList">
+    <xsl:param name="collName"/>
+    <ul>
+      <xsl:for-each select="document">
+	<li><a href="{$library_name}?a=xd&amp;sa=toc&amp;sc=full&amp;c={$collName}&amp;d={@name}"><xsl:value-of select="metadataList/metadata[@name='Title']"/></a></li>
+      </xsl:for-each>
+    </ul>
+  </xsl:template>
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/transform/darwin.css
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/transform/darwin.css	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/transform/darwin.css	(revision 13928)
@@ -0,0 +1,342 @@
+/*This is darwin.css*/
+
+ gutblurb{
+  display:none;
+ }
+
+ markupblurb
+  {
+  display:none;
+
+  }
+ endgutblurb{
+  display:none;
+ }
+
+ para,sect1,sect2,sect3,sect4,simplesect{
+  display:block;
+  }
+
+
+ title1,item,chapter,chapnum,chapsummary,desc,def,letter
+{
+  display:block;
+  }
+
+ blockquote,footnote,note,list,deflist,blockgraphic{
+  display:block;
+  }
+
+ quote,emph,ital,reference,date,place,name,graphic,misc{
+  display:inline;
+  }
+
+  acknowledge{
+  display:block;
+  text-align:center;
+  font-size:8pt;
+  font-family:arial,sans-serif;
+  margin-top:8pt;
+  margin-bottom:12pt;
+  }
+
+ htitlepage title1{
+  display:block;
+  text-align:center;
+  font-size:16pt;
+  font-family:arial,sans-serif;
+  margin-top:8pt;
+  margin-bottom:12pt;
+  }
+
+ htitlepage subtitle{
+  display:block;
+  text-align:center;
+  font-size:14pt;
+  font-family:arial,sans-serif;
+  margin-top:8pt;
+  margin-bottom:12pt;
+  }
+
+  htitlepage author{
+  display:block;
+  text-align:center;
+  font-size:14pt;
+  font-family:arial,sans-serif;
+  margin-top:8pt;
+  margin-bottom:12pt;
+  }
+
+  epigraph{
+  display:block;
+  text-align:center;
+  font-size:12pt;
+  margin-top:8pt;
+  margin-bottom:12pt;
+  }
+
+
+  epigraph blockquote{
+  display:block;
+  text-align:left;
+  font-size:12pt;
+  margin-top:8pt;
+  margin-left:24pt;
+  margin-right:24pt;
+  margin-bottom:12pt;
+  }
+
+  epigraph attrib{
+  display:block;
+  text-align:left;
+  font-size:12pt;
+  margin-top:8pt;
+  margin-right:24pt;
+  margin-left:24pt;
+  margin-bottom:12pt;
+  }
+
+ titlepage title1{
+  display:block;
+  text-align:center;
+  font-size:16pt;
+  font-family:arial,sans-serif;
+  margin-top:8pt;
+  margin-bottom:12pt;
+  }
+
+  titlepage para{
+  display:block;
+  text-align:center;
+  font-size:12pt;
+  font-family:arial,sans-serif;
+  margin-top:8pt;
+  margin-bottom:12pt;
+  }
+
+  titlepage line{
+  display:block;
+  text-align:center;
+  font-size:12pt;
+  font-family:arial,sans-serif;
+  margin-top:8pt;
+  margin-bottom:12pt;
+  }
+
+  titlepage subtitle{
+  display:block;
+  text-align:center;
+  font-size:14pt;
+  font-family:arial,sans-serif;
+  margin-top:8pt;
+  margin-bottom:12pt;
+  }
+
+
+
+  titlepage author{
+  display:block;
+  text-align:center;
+  font-size:14pt;
+  font-family:arial,sans-serif;
+  margin-top:8pt;
+  margin-bottom:12pt;
+  }
+
+ titlepage partnum{
+  display:block;
+  text-align:center;
+  font-size:16pt;
+  font-family:arial,sans-serif;
+  margin-top:8pt;
+  margin-bottom:12pt;
+  }
+
+ dedication title1{
+  display:block;
+  text-align:center;
+  font-size:16pt;
+  font-family:arial,sans-serif;
+  margin-top:8pt;
+  margin-bottom:12pt;
+  }
+
+  toc title1{
+  display:block;
+  text-align:left;
+  font-size:14pt;
+  font-family:arial,sans-serif;
+  margin-top:12pt;
+  margin-left:24pt;
+  margin-bottom:12pt;
+  }
+
+  toc subtitle{
+  display:block;
+  text-align:left;
+  font-weight:bold;
+  font-size:13pt;
+  font-family:arial,sans-serif;
+  margin-top:12pt;
+  margin-left:24pt;
+  margin-bottom:12pt;
+  }
+
+
+  toc item{
+  display:block;
+  text-align:left;
+  font-size:12pt;
+  font-family:arial,sans-serif;
+  margin-top:12pt;
+  margin-left:36pt;
+  margin-bottom:12pt;
+  }
+
+
+  toc def{
+  display:block;
+  text-align:left;
+  font-size:12pt;
+  font-family:times new roman,serif;
+  margin-top:12pt;
+  margin-left:48pt;
+  margin-right:24pt;
+
+  margin-bottom:12pt;
+  }
+
+  toc desc{
+  display:block;
+  text-align:left;
+  font-size:10pt;
+  font-family:arial,sans-serif;
+  margin-top:12pt;
+  margin-left:42pt;
+  margin-bottom:12pt;
+  }
+
+ preface title1{
+  display:block;
+  text-align:left;
+  font-size:14pt;
+  font-family:arial,sans-serif;
+  margin-top:12pt;
+  margin-left:12pt;
+  margin-bottom:12pt;
+  }
+
+  introduction title1{
+  display:block;
+  text-align:left;
+  font-size:14pt;
+  font-family:arial,sans-serif;
+  margin-top:12pt;
+  margin-left:12pt;
+  margin-bottom:12pt;
+  }
+
+  salut,sig,para{
+  display:block;
+  text-align:left;
+  font-size:12pt;
+  font-family:times new roman,serif;
+  margin-top:12pt;
+  margin-left:24pt;
+  margin-right:24pt;
+  margin-bottom:12pt;
+  }
+
+  poem{
+  display:block;
+  text-align:left;
+  font-size:12pt;
+  margin-left:24pt;
+  margin-top:18pt;
+  margin-bottom:18pt;
+  }
+
+  line{
+  display:block;
+  text-align:left;
+  font-size:12pt;
+  margin-left:24pt;
+  margin-right:24pt;
+  }
+
+  chapter title1{
+  display:block;
+  text-align:left;
+  font-size:14pt;
+  font-family:arial,sans-serif;
+  margin-top:12pt;
+  margin-left:12pt;
+  margin-bottom:12pt;
+  }
+
+  chapter chapnum{
+  display:block;
+  text-align:center;
+  font-size:14pt;
+  font-family:arial,sans-serif;
+  margin-top:12pt;
+  margin-bottom:12pt;
+  }
+
+  chapter chapsummary{
+  display:block;
+  text-align:left;
+  font-size:12pt;
+  font-style:italic;
+  font-family:times new roman,serif;
+  margin-top:12pt;
+  margin-left:48pt;
+  margin-right:36pt;
+  margin-bottom:12pt;
+  }
+
+  chapter blockquote para{
+  display:block;
+  text-align:left;
+  font-size:11pt;
+  
+  margin-top:8pt;
+  margin-left:48pt;
+  margin-right:48pt;
+  margin-bottom:12pt;
+  }
+
+
+  index item{
+  display:block;
+  text-align:left;
+  font-size:12pt;
+  font-family:times new roman,serif;
+  margin-top:8pt;
+  margin-left:12pt;
+  margin-bottom:8pt;
+  }
+
+  index title1{
+  display:block;
+  text-align:left;
+  font-size:14pt;
+  font-family:arial,sans-serif;
+  margin-top:12pt;
+  margin-left:12pt;
+  margin-bottom:12pt;
+  }
+
+  list item{
+  color:black;
+  display:block;
+  text-align:left;
+  font-size:12pt;
+  font-family:times new roman,serif;
+  margin-top:8pt;
+  margin-left:48pt;
+  margin-bottom:8pt;
+  }
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/transform/document-content.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/transform/document-content.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/transform/document-content.xsl	(revision 13928)
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+
+  <!-- style includes global params interface_name, library_name -->
+  <xsl:include href="style.xsl"/>
+
+  <xsl:output method="html"/> 
+  
+  <xsl:template name="pageTitle">
+    <xsl:value-of select="/page/pageResponse/documentNode/metadataList/metadata[@name='root_Title']"/>
+  </xsl:template>
+  
+  <!-- page specific style goes here -->
+  <xsl:template name="pageStyle">
+    <link type="text/css" href="sites/localsite/collect/gberg/transform/darwin.css" rel="stylesheet"/>
+  </xsl:template>
+
+  <xsl:template match="pageResponse">
+    <xsl:variable name="collName"><xsl:value-of select="/page/pageRequest/paramList/param[@name='c']/@value"/></xsl:variable>
+    <xsl:call-template name="standardPageBanner">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>
+    <xsl:call-template name="navigationBar">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>      
+    <!-- display the document -->
+    <xsl:apply-templates select="documentNode">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:apply-templates>
+    <xsl:call-template name="dividerBar"/>
+  </xsl:template>
+
+  <xsl:template match="documentNode">
+    <xsl:param name="collName"/>
+    <xsl:variable name="docname"><xsl:choose><xsl:when test="contains(@nodeID, '.')"><xsl:value-of select="substring-before(@nodeID, '.')"/></xsl:when><xsl:otherwise><xsl:value-of select="@nodeID"/></xsl:otherwise></xsl:choose></xsl:variable>
+    <h1>
+      <center>
+	<a href="{$library_name}?a=xd&amp;sa=toc&amp;c={$collName}&amp;d={$docname}"><xsl:attribute name="title">Go to the document contents</xsl:attribute><xsl:value-of select="metadataList/metadata[@name='root_Title']"/>&#160;</a>
+      </center>
+    </h1>
+    <xsl:apply-templates select="nodeContent/*"/>
+  </xsl:template>
+
+  <xsl:template match="gutblurb | markupblurb | endmarkupblurb | endgutblurb">
+  </xsl:template>
+
+  <xsl:template match="gutbook | book | frontmatter | bookbody | backmatter | titlepage| htitlepage | toc | dedication | preface | introduction | chapter |  part | chapheader | index | appendix | glossary">
+    <xsl:copy>
+      <xsl:copy-of select="@*"/>
+      <xsl:apply-templates/>
+    </xsl:copy>
+  </xsl:template>
+
+<!-- dont seem to be able to apply styles to title tags - cos they are special to html. so we rename title to title1-->
+  <xsl:template match="title">
+    <title1>
+      <xsl:apply-templates/>
+    </title1>
+  </xsl:template>  
+    
+  <xsl:template match="*">
+    <xsl:copy-of select="."/>
+  </xsl:template>
+
+  <xsl:template match="metadataList">
+  </xsl:template>
+
+</xsl:stylesheet>
+
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/transform/document-toc.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/transform/document-toc.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/transform/document-toc.xsl	(revision 13928)
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:gs3="http://www.greenstone.org/gs3"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+
+  <!-- style includes global params interface_name, library_name -->
+  <xsl:include href="style.xsl"/>
+
+  <xsl:output method="html"/> 
+  
+  <xsl:template name="pageTitle">
+    <xsl:value-of select="/page/pageResponse/documentNode/metadataList/metadata[@name='root_Title']"/>: Table of Contents
+  </xsl:template>
+  
+  <!-- page specific style goes here -->
+  <xsl:template name="pageStyle"/>
+  
+
+  <xsl:template match="pageResponse">
+    <xsl:variable name="collName"><xsl:value-of select="/page/pageRequest/paramList/param[@name='c']/@value"/></xsl:variable>
+    <xsl:call-template name="standardPageBanner">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>
+    <xsl:call-template name="navigationBar">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:call-template>      
+    <!-- display the document -->
+    <xsl:apply-templates select="documentNode">
+      <xsl:with-param name="collName" select="$collName"/>
+    </xsl:apply-templates>
+    <xsl:call-template name="dividerBar"/>
+  </xsl:template>
+
+  <xsl:template match="documentNode">
+    <xsl:param name="collName"/>
+    <xsl:variable name="docname"><xsl:choose><xsl:when test="contains(@nodeID, '.')"><xsl:value-of select="substring-before(@nodeID, '.')"/></xsl:when><xsl:otherwise><xsl:value-of select="@nodeID"/></xsl:otherwise></xsl:choose></xsl:variable>
+    <h1>
+      <center>
+	<xsl:value-of select="metadataList/metadata[@name='root_Title']"/>
+      </center>
+    </h1>
+    <xsl:apply-templates select="nodeStructure/gutbook/book"><xsl:with-param name="collName" select="$collName"/><xsl:with-param name="docName" select="$docname"/></xsl:apply-templates>
+  </xsl:template>
+  
+  <xsl:template match="book">
+    <xsl:param name="collName"/>
+    <xsl:param name="docName"/>
+    <h1>
+      Contents
+    </h1>
+    <ul class="toc">
+      <xsl:if test="acknowledge">
+	<li class='toc'>
+	  <a href="{$library_name}?a=xd&amp;sa=text&amp;d={$docName}.acknowledge&amp;c={$collName}">Acknowledgements</a>
+	</li>
+      </xsl:if>
+      <xsl:if test="frontmatter">
+	<li class='toc'>
+	  <a href="{$library_name}?a=xd&amp;sa=text&amp;d={$docName}.frontmatter&amp;c={$collName}">About this document</a>
+	</li>
+      </xsl:if>
+      <li class='toc'><a href="{$library_name}?a=xd&amp;sa=text&amp;d={$docName}&amp;c={$collName}">Full version</a>
+      </li>
+    </ul>
+    <xsl:apply-templates select="bookbody"><xsl:with-param name="collName" select="$collName"/><xsl:with-param name="docName" select="$docName"/></xsl:apply-templates>
+    <xsl:if test="backmatter">
+      <ul class='toc'>
+	<li class='toc'>
+	<a href="{$library_name}?a=xd&amp;sa=text&amp;d={$docName}.backmatter&amp;c={$collName}">Back matter (may include appendices, index, glossary etc)</a>
+	</li>
+      </ul>
+    </xsl:if>
+  </xsl:template>
+    
+  <xsl:template match="bookbody">
+    <xsl:param name="collName"/>
+    <xsl:param name="docName"/>
+    <ul class="toc">
+      <xsl:apply-templates select="part|chapter">
+	<xsl:with-param name="collName" select="$collName"/>
+	<xsl:with-param name="docName" select="$docName"/>
+      </xsl:apply-templates>
+    </ul>
+  </xsl:template>
+
+  <xsl:template match="part">
+    <xsl:param name="collName"/>
+    <xsl:param name="docName"/>
+    <li class='toc'>
+      <a href="{$library_name}?a=xd&amp;sa=text&amp;c={$collName}&amp;d={$docName}.bookbody.part.{@gs3:id}">Part <xsl:value-of select="position()"/></a>
+      <xsl:if test="chapter">
+	<ul class='toc'>
+	  <xsl:apply-templates select="chapter">
+	  <xsl:with-param name="collName" select="$collName"/>
+	  <xsl:with-param name="docName" select="$docName"/>
+	</xsl:apply-templates>
+	</ul>
+      </xsl:if>
+    </li>
+  </xsl:template>
+
+  <xsl:template match="chapter">
+    <xsl:param name="collName"/>
+    <xsl:param name="docName"/>
+    <li class='toc'>
+      <a href="{$library_name}?a=xd&amp;sa=text&amp;c={$collName}&amp;d={$docName}.bookbody.chapter.{@gs3:id}">
+	<xsl:choose>
+	  <xsl:when test="title">
+	    <xsl:value-of select="title"/>
+	  </xsl:when>
+	  <xsl:when test="chapheader">
+	    <xsl:value-of select="chapheader/chapnum"/>: <xsl:value-of select="chapheader/title"/>
+	  </xsl:when>
+	  <xsl:otherwise>
+	    Chapter <xsl:value-of select="position()"/>
+	  </xsl:otherwise>
+	</xsl:choose>
+      </a>
+    </li>
+  </xsl:template>
+   
+</xsl:stylesheet>
+
+
+
+
+
+
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/transform/produce-toc.xsl
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/transform/produce-toc.xsl	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gberg/transform/produce-toc.xsl	(revision 13928)
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:java="http://xml.apache.org/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+  
+  <xsl:output method="xml"/>
+
+  <xsl:strip-space elements='*'/>
+
+  <xsl:template match="gutbook | book | acknowledge | frontmatter | bookbody | backmatter | part | chapter | chapheader "><xsl:copy><xsl:for-each select="@*"><xsl:copy/></xsl:for-each><xsl:apply-templates/></xsl:copy></xsl:template>
+
+  <xsl:template match="title | chapnum">
+    <xsl:copy-of select="."/>
+  </xsl:template>
+
+  <!-- any thing else is ignored -->
+  <xsl:template match="*"></xsl:template>
+  
+</xsl:stylesheet>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgdemo/README
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgdemo/README	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgdemo/README	(revision 13928)
@@ -0,0 +1,19 @@
+This collection is based on the original demo collection that comes with 
+Greenstone2. I built the collection using Greenstone2, then copied it 
+across to Greenstone3. I ran the convert_coll_from_gs2.pl Perl script to 
+generate the collectionConfig.xml and buildConfig.xml files, then edited 
+them by hand. I also generated new images for the collection, based on its 
+new name.
+
+The changes I made were:
+
+collectionConfig.xml:
+--------------------
+* More readable XML
+* Changed the English name and description displayItems, and removed the other language items, as they no longer are an accurate translation.
+* added a new displayItem to classifier CL4.
+* changed the image names
+
+buildConfig.xml:
+----------------
+* More readable XML
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgdemo/etc/collect.cfg
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgdemo/etc/collect.cfg	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgdemo/etc/collect.cfg	(revision 13928)
@@ -0,0 +1,70 @@
+creator		greenstone@cs.waikato.ac.nz
+maintainer	greenstone@cs.waikato.ac.nz
+public		true
+
+buildtype	mg
+
+indexes		section:text section:Title document:text
+
+#levels	document
+
+indexoptions	casefold stem
+
+#defaultlevel	document
+
+plugin		GAPlug
+plugin		HTMLPlug -description_tags
+plugin		MetadataXMLPlug
+plugin		ArcPlug
+plugin		RecPlug
+
+classify	Hierarchy -metadata dls.Subject -sort dls.Title -buttonname Subject
+classify	AZList -metadata dls.Title
+classify	AZCompactList -metadata dls.Organization -sort dls.Title -mingroup 1 -buttonname Organization
+classify	List -metadata dls.Keyword -buttonname Howto
+
+format SearchVList "<td valign=top>[link][icon][/link]</td><td>{If}{[parent(All\': \'):Title],[parent(All\': \'):Title]:}[link][Title][/link]</td>"
+
+format CL4VList "<br>[link][dls.Keyword][/link]"
+
+format DocumentText "<h3>[Title]</h3>\\n\\n<p>[Text]"
+format DocumentImages true
+format DocumentButtons "Expand Text|Expand Contents|Detach|Highlight"
+
+format VList "<td valign=\"top\">[link][icon][/link]</td>
+<td valign=\"top\">[ex.srclink]{Or}{[ex.thumbicon],[ex.srcicon]}[ex./srclink]</td>
+<td valign=\"top\">[highlight]
+{Or}{[dc.Title],[exp.Title],[ex.Title],Untitled}
+[/highlight]{If}{[ex.Source],<br><i>([ex.Source])</i>}</td>"
+
+format HList "[link][highlight][ex.Title][/highlight][/link]"
+
+format DocumentHeading "{Or}{[parent(Top):Title],[Title],untitled}<br>"
+
+collectionmeta	iconcollectionsmall [l=en] "_httpprefix_/collect/gs2mgdemo/images/gs2mgdemo_sm.gif"
+collectionmeta	iconcollection [l=en] "_httpprefix_/collect/gs2mgdemo/images/gs2mgdemo.gif"
+
+# -- English strings ----------------
+collectionmeta	collectionname [l=en] "Greenstone2 MG demo collection"
+collectionmeta	collectionextra [l=en] "This is a demonstration collection for the Greenstone3 digital library software. It contains a small subset (11 books) of the Humanitarian and Development Libraries. It is a Greenstone2 collection, built with MG. The Greenstone2 configuration files have been converted to Greenstone3 equivalents, enabling it to be served using Greenstone3."
+
+collectionmeta	.section:text [l=en] "chapters"
+collectionmeta	.section:Title [l=en] "section titles"
+collectionmeta	.document:text [l=en] "entire documents"
+
+# -- French strings ----------------
+collectionmeta	.section:text [l=fr] "chapitres"
+collectionmeta	.section:Title [l=fr] "titres des sections"
+collectionmeta	.document:text [l=fr] "documents entiers"
+
+# -- Spanish strings ----------------
+collectionmeta	.section:text [l=es] "capÃ­tulos"
+collectionmeta	.section:Title [l=es] "tÃ­tulos de las secciones"
+collectionmeta	.document:text [l=es] "documentos enteros"
+
+# -- Russian strings ----------------
+collectionmeta	.section:text [l=ru] "ÐÐ»Ð°Ð²Ñ"
+collectionmeta	.section:Title [l=ru] "ÐÐ°Ð·Ð²Ð°ÐœÐžÑ ÑÐ°Ð·ÐŽÐµÐ»ÐŸÐ²"
+collectionmeta	.document:text [l=ru] "ÐÐŸÐ»ÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ"
+collectionmeta	.document [l=en] "document"
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgdemo/etc/collectionConfig.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgdemo/etc/collectionConfig.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgdemo/etc/collectionConfig.xml	(revision 13928)
@@ -0,0 +1,80 @@
+<collectionConfig xmlns:gsf="http://www.greenstone.org/greenstone3/schema/ConfigFormat" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+><metadataList
+><metadata name="creator"
+>greenstone@cs.waikato.ac.nz</metadata
+><metadata name="public"
+>true</metadata
+></metadataList
+><displayItemList
+><displayItem name="description" lang="en"
+>This is a demonstration collection for the Greenstone3 digital library software. It contains a small subset (11 books) of the Humanitarian and Development Libraries. It is a Greenstone2 collection, built with MG. The Greenstone2 configuration files have been converted to Greenstone3 equivalents, enabling it to be served using Greenstone3.</displayItem
+><displayItem name="name" lang="en"
+>Greenstone2 MG demo collection</displayItem
+><displayItem name="icon" lang="en"
+>gs2mgdemo.gif</displayItem
+><displayItem name="smallicon" lang="en"
+>gs2mgdemo_sm.gif</displayItem
+></displayItemList
+><search
+><index name="document:text"
+><displayItem name="name" lang="ru"
+>ÐÐŸÐ»ÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ</displayItem
+><displayItem name="name" lang="en"
+>entire documents</displayItem
+><displayItem name="name" lang="fr"
+>documents entiers</displayItem
+><displayItem name="name" lang="es"
+>documentos enteros</displayItem
+></index
+><index name="section:Title"
+><displayItem name="name" lang="ru"
+>ÐÐ°Ð·Ð²Ð°ÐœÐžÑ ÑÐ°Ð·ÐŽÐµÐ»ÐŸÐ²</displayItem
+><displayItem name="name" lang="en"
+>section titles</displayItem
+><displayItem name="name" lang="fr"
+>titres des sections</displayItem
+><displayItem name="name" lang="es"
+>tÃ­tulos de las secciones</displayItem
+></index
+><index name="section:text"
+><displayItem name="name" lang="ru"
+>ÐÐ»Ð°Ð²Ñ</displayItem
+><displayItem name="name" lang="en"
+>chapters</displayItem
+><displayItem name="name" lang="fr"
+>chapitres</displayItem
+><displayItem name="name" lang="es"
+>capÃ­tulos</displayItem
+></index
+><format
+><gsf:template match="documentNode"
+><td valign='top'><gsf:link type='document'><gsf:icon type='document'/></gsf:link></td><td><gsf:switch><gsf:metadata name='Title' select='ancestors' separator=': ' /><gsf:when test='exists' ><gsf:metadata name='Title' select='ancestors' separator=': ' />:</gsf:when></gsf:switch><gsf:link type='document'><gsf:metadata name='Title' /></gsf:link></td></gsf:template
+></format
+></search
+><browse
+><format
+><gsf:template match="documentNode"
+><td valign="top"><gsf:link type='document'><gsf:icon type='document'/></gsf:link></td> <td valign="top"><gsf:metadata name='srclink' /><gsf:choose-metadata><gsf:metadata name='thumbicon' /><gsf:metadata name='srcicon' /></gsf:choose-metadata><gsf:metadata name='/srclink' /></td> <td valign="top"> <gsf:choose-metadata><gsf:metadata name='dc.Title' /><gsf:metadata name='exp.Title' /><gsf:metadata name='Title' /><gsf:default>Untitled</gsf:default></gsf:choose-metadata> <gsf:switch><gsf:metadata name='Source' /><gsf:when test='exists' ><br /><i>(<gsf:metadata name='Source' />)</i></gsf:when></gsf:switch></td></gsf:template
+><gsf:template match="classifierNode"
+><td valign="top"><gsf:link type='classifier'><gsf:icon type='classifier'/></gsf:link></td> <td valign="top"><gsf:metadata name='srclink' /><gsf:choose-metadata><gsf:metadata name='thumbicon' /><gsf:metadata name='srcicon' /></gsf:choose-metadata><gsf:metadata name='/srclink' /></td> <td valign="top"> <gsf:choose-metadata><gsf:metadata name='dc.Title' /><gsf:metadata name='exp.Title' /><gsf:metadata name='Title' /><gsf:default>Untitled</gsf:default></gsf:choose-metadata> <gsf:switch><gsf:metadata name='Source' /><gsf:when test='exists' ><br /><i>(<gsf:metadata name='Source' />)</i></gsf:when></gsf:switch></td></gsf:template
+><gsf:template match="classifierNode" mode="horizontal"
+><gsf:link type='horizontal'><gsf:metadata name='Title' /></gsf:link></gsf:template
+></format
+><classifier name="CL1"
+></classifier
+><classifier name="CL2"
+></classifier
+><classifier name="CL3"
+></classifier
+><classifier name="CL4"
+><format
+><gsf:template match="documentNode"
+><br /><gsf:link type='document'><gsf:metadata name='dls.Keyword' /></gsf:link></gsf:template
+><gsf:template match="classifierNode"
+><br /><gsf:link type='classifier'><gsf:metadata name='dls.Keyword' /></gsf:link></gsf:template
+></format
+></classifier
+></browse
+><replaceListRef id="gs2-standard"
+ /></collectionConfig
+>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgdemo/gs2mgdemo.col
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgdemo/gs2mgdemo.col	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgdemo/gs2mgdemo.col	(revision 13928)
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE GathererCollection [
+  <!ELEMENT GathererCollection (Argument*, GathererConfig, BuildConfig)>
+  <!ELEMENT GathererConfig    (Arguments*)>
+  <!ELEMENT BuildConfig       (Build, Import)>
+  <!ELEMENT Build             (Arguments*)>
+  <!ELEMENT Import            (Arguments*)>
+  <!ELEMENT Argument          (#PCDATA)>
+  <!ATTLIST Argument
+            name              CDATA #REQUIRED
+				enabled           CDATA "true">
+]>
+<GathererCollection>
+    <Argument name="built">false</Argument>
+    <Argument name="imported">true</Argument>
+    <GathererConfig/>
+    <BuildConfig>
+        <Build/>
+        <Import/>
+    </BuildConfig>
+</GathererCollection>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgdemo/index/buildConfig.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgdemo/index/buildConfig.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgdemo/index/buildConfig.xml	(revision 13928)
@@ -0,0 +1,37 @@
+<buildConfig xmlns:gsf="http://www.greenstone.org/greenstone3/schema/ConfigFormat"
+><metadataList
+><metadata name="numDocs"
+>11</metadata
+><metadata name="buildType"
+>mg</metadata
+></metadataList
+><serviceRackList
+><serviceRack name="GS2MGRetrieve"
+><defaultIndex shortname="ste"
+ /><indexStem name="gs2mgdemo"
+ /></serviceRack
+><serviceRack name="GS2Browse"
+><indexStem name="gs2mgdemo"
+ /><classifierList
+><classifier name="CL1" content="Subject"
+ /><classifier name="CL2" content="dls.Title"
+ /><classifier name="CL3" content="Organization"
+ /><classifier name="CL4" content="Howto"
+ /></classifierList
+></serviceRack
+><serviceRack name="GS2MGSearch"
+><defaultIndex shortname="ste"
+ /><indexList
+><index name="section:text" shortname="ste"
+ /><index name="section:Title" shortname="sti"
+ /><index name="document:text" shortname="dte"
+ /></indexList
+><indexStem name="gs2mgdemo"
+ /><indexOptionList
+><indexOption name="stemIndexes" value="3"
+ /><indexOption name="maxnumeric" value="4"
+ /></indexOptionList
+></serviceRack
+></serviceRackList
+></buildConfig
+>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgppdemo/README
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgppdemo/README	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgppdemo/README	(revision 13928)
@@ -0,0 +1,17 @@
+This collection is based on the original demo collection that comes with 
+Greenstone2. I converted the collect.cfg file so that the collection used MGPP,
+then built the collection using Greenstone2, and copied it 
+across to Greenstone3. I ran the convert_coll_from_gs2.pl Perl script to 
+generate the collectionConfig.xml and buildConfig.xml files, then edited 
+them by hand. I also generated new images for the collection, based on its 
+new name.
+
+The changes I made were:
+
+collectionConfig.xml:
+--------------------
+* More readable XML
+
+buildConfig.xml:
+----------------
+* More readable XML
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgppdemo/etc/collect.cfg
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgppdemo/etc/collect.cfg	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgppdemo/etc/collect.cfg	(revision 13928)
@@ -0,0 +1,61 @@
+creator		greenstone@cs.waikato.ac.nz
+maintainer	greenstone@cs.waikato.ac.nz
+public		true
+
+buildtype	mgpp
+
+format SearchTypes "form,plain"
+
+indexes		allfields text dls.Title dls.Subject dls.Organization
+
+levels	section document
+
+indexoptions	accentfold casefold stem
+
+defaultlevel	document
+
+plugin		GAPlug
+plugin		HTMLPlug -description_tags
+plugin		MetadataXMLPlug
+plugin		ArcPlug
+plugin		RecPlug
+
+classify	AZList -metadata dls.Title
+classify	Hierarchy -metadata dls.Subject -sort dls.Title
+classify	AZCompactList -metadata dls.Organization -sort dls.Title -mingroup 1 -buttonname Organization
+classify	List -metadata dls.Keyword -buttonname Howto
+
+format SearchVList "<td valign=top>[link][icon][/link]</td><td>{If}{[parent(All\': \'):Title],[parent(All\': \'):Title]:}[link][Title][/link]</td>"
+
+format DocumentText "<h3>[Title]</h3>\\n\\n<p>[Text]"
+format DocumentImages true
+format DocumentButtons "Expand Text|Expand Contents|Detach|Highlight"
+
+format CL4VList "<td>[link][dls.Keyword][/link]</td>"
+
+format VList "<td valign=\"top\">[link][icon][/link]</td>
+<td valign=\"top\">[ex.srclink]{Or}{[ex.thumbicon],[ex.srcicon]}[ex./srclink]</td>
+<td valign=\"top\">[highlight]
+{Or}{[dc.Title],[exp.Title],[ex.Title],Untitled}
+[/highlight]{If}{[ex.Source],<br><i>([ex.Source])</i>}</td>"
+
+format HList "[link][highlight][ex.Title][/highlight][/link]"
+
+format DocumentHeading "{Or}{[parent(Top):Title],[Title],untitled}<br>"
+
+collectionmeta	iconcollectionsmall [l=en] "_httpprefix_/collect/gs2mgppdemo/images/gs2mgppdemo_sm.gif"
+collectionmeta	iconcollection [l=en] "_httpprefix_/collect/gs2mgppdemo/images/gs2mgppdemo.gif"
+
+collectionmeta	collectionname [l=en] "Greenstone2 MGPP demo collection"
+collectionmeta	collectionextra [l=en] "This is a demonstration collection
+for the Greenstone3 digital library software. It contains a small subset
+(11 books) of the Humanitarian and Development Libraries. It is a Greenstone2
+collection, built with MGPP, which provides form based searching.
+The Greenstone2 configuration files have been converted to Greenstone3
+equivalents, enabling it to be served using Greenstone3."
+
+collectionmeta	.text [l=en] "text"
+collectionmeta	.allfields [l=en] "all fields"
+collectionmeta	.dls.Subject [l=en] "subjects"
+collectionmeta	.dls.Title [l=en] " titles"
+collectionmeta	.dls.Organization [l=en] "organisations"
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgppdemo/etc/collectionConfig.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgppdemo/etc/collectionConfig.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgppdemo/etc/collectionConfig.xml	(revision 13928)
@@ -0,0 +1,74 @@
+<collectionConfig xmlns:gsf="http://www.greenstone.org/greenstone3/schema/ConfigFormat" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+><metadataList
+><metadata name="creator"
+>greenstone@cs.waikato.ac.nz</metadata
+><metadata name="public"
+>true</metadata
+></metadataList
+><displayItemList
+><displayItem name="description" lang="en"
+>This is a demonstration collection for the Greenstone3 digital library software. It contains a small subset (11 books) of the Humanitarian and Development Libraries. It is a Greenstone2 collection, built with MGPP, which provides form based searching. The Greenstone2 configuration files have been converted to Greenstone3 equivalents, enabling it to be served using Greenstone3.</displayItem
+><displayItem name="smallicon" lang="en"
+>gs2mgppdemo_sm.gif</displayItem
+><displayItem name="icon" lang="en"
+>gs2mgppdemo.gif</displayItem
+><displayItem name="name" lang="en"
+>Greenstone2 MGPP demo collection</displayItem
+></displayItemList
+><search
+><index name="dls.Organization"
+><displayItem name="name" lang="en"
+>organisations</displayItem
+></index
+><index name="dls.Title"
+><displayItem name="name" lang="en"
+> titles</displayItem
+></index
+><index name="text"
+><displayItem name="name" lang="en"
+>text</displayItem
+></index
+><index name="allfields"
+><displayItem name="name" lang="en"
+>all fields</displayItem
+></index
+><index name="dls.Subject"
+><displayItem name="name" lang="en"
+>subjects</displayItem
+></index
+><level name="document"
+></level
+><level name="section"
+></level
+><format
+><gsf:template match="documentNode"
+><td valign='top'><gsf:link type='document'><gsf:icon type='document'/></gsf:link></td><td><gsf:switch><gsf:metadata name='Title' select='ancestors' separator=': ' /><gsf:when test='exists' ><gsf:metadata name='Title' select='ancestors' separator=': ' />:</gsf:when></gsf:switch><gsf:link type='document'><gsf:metadata name='Title' /></gsf:link></td></gsf:template
+></format
+></search
+><browse
+><format
+><gsf:template match="documentNode"
+><td valign="top"><gsf:link type='document'><gsf:icon type='document'/></gsf:link></td> <td valign="top"><gsf:metadata name='srclink' /><gsf:choose-metadata><gsf:metadata name='thumbicon' /><gsf:metadata name='srcicon' /></gsf:choose-metadata><gsf:metadata name='/srclink' /></td> <td valign="top"> <gsf:choose-metadata><gsf:metadata name='dc.Title' /><gsf:metadata name='exp.Title' /><gsf:metadata name='Title' /><gsf:default>Untitled</gsf:default></gsf:choose-metadata> <gsf:switch><gsf:metadata name='Source' /><gsf:when test='exists' ><br /><i>(<gsf:metadata name='Source' />)</i></gsf:when></gsf:switch></td></gsf:template
+><gsf:template match="classifierNode"
+><td valign="top"><gsf:link type='classifier'><gsf:icon type='classifier'/></gsf:link></td> <td valign="top"><gsf:metadata name='srclink' /><gsf:choose-metadata><gsf:metadata name='thumbicon' /><gsf:metadata name='srcicon' /></gsf:choose-metadata><gsf:metadata name='/srclink' /></td> <td valign="top"> <gsf:choose-metadata><gsf:metadata name='dc.Title' /><gsf:metadata name='exp.Title' /><gsf:metadata name='Title' /><gsf:default>Untitled</gsf:default></gsf:choose-metadata> <gsf:switch><gsf:metadata name='Source' /><gsf:when test='exists' ><br /><i>(<gsf:metadata name='Source' />)</i></gsf:when></gsf:switch></td></gsf:template
+><gsf:template match="classifierNode" mode="horizontal"
+><gsf:link type='horizontal'><gsf:metadata name='Title' /></gsf:link></gsf:template
+></format
+><classifier name="CL1"
+></classifier
+><classifier name="CL2"
+></classifier
+><classifier name="CL3"
+></classifier
+><classifier name="CL4"
+><format
+><gsf:template match="documentNode"
+><td><gsf:link type='document'><gsf:metadata name='dls.Keyword' /></gsf:link></td></gsf:template
+><gsf:template match="classifierNode"
+><td><gsf:link type='classifier'><gsf:metadata name='dls.Keyword' /></gsf:link></td></gsf:template
+></format
+></classifier
+></browse
+><replaceListRef id="gs2-standard"
+ /></collectionConfig
+>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgppdemo/gs2mgppdemo.col
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgppdemo/gs2mgppdemo.col	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgppdemo/gs2mgppdemo.col	(revision 13928)
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE GathererCollection [
+  <!ELEMENT GathererCollection (Argument*, GathererConfig, BuildConfig)>
+  <!ELEMENT GathererConfig    (Arguments*)>
+  <!ELEMENT BuildConfig       (Build, Import)>
+  <!ELEMENT Build             (Arguments*)>
+  <!ELEMENT Import            (Arguments*)>
+  <!ELEMENT Argument          (#PCDATA)>
+  <!ATTLIST Argument
+            name              CDATA #REQUIRED
+				enabled           CDATA "true">
+]>
+<GathererCollection>
+    <Argument name="built">false</Argument>
+    <Argument name="imported">true</Argument>
+    <GathererConfig/>
+    <BuildConfig>
+        <Build/>
+        <Import/>
+    </BuildConfig>
+</GathererCollection>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgppdemo/index/buildConfig.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgppdemo/index/buildConfig.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/gs2mgppdemo/index/buildConfig.xml	(revision 13928)
@@ -0,0 +1,49 @@
+<buildConfig xmlns:gsf="http://www.greenstone.org/greenstone3/schema/ConfigFormat"
+><metadataList
+><metadata name="numDocs"
+>11</metadata
+><metadata name="buildType"
+>mgpp</metadata
+></metadataList
+><serviceRackList
+><serviceRack name="GS2MGPPRetrieve"
+><defaultLevel shortname="Sec"
+ /><indexStem name="gs2mgppdemo"
+ /></serviceRack
+><serviceRack name="GS2Browse"
+><indexStem name="gs2mgppdemo"
+ /><classifierList
+><classifier name="CL1" content="dls.Title"
+ /><classifier name="CL2" content="dls.Subject"
+ /><classifier name="CL3" content="Organization"
+ /><classifier name="CL4" content="Howto"
+ /></classifierList
+></serviceRack
+><serviceRack name="GS2MGPPSearch"
+><defaultIndex shortname="ZZ"
+ /><indexList
+><index name="allfields" shortname="ZZ"
+ /><index name="text" shortname="TX"
+ /><index name="dls.Title" shortname="DL"
+ /><index name="dls.Subject" shortname="DS"
+ /><index name="dls.Organization" shortname="DO"
+ /></indexList
+><indexStem name="gs2mgppdemo"
+ /><indexOptionList
+><indexOption name="stemIndexes" value="7"
+ /><indexOption name="maxnumeric" value="4"
+ /></indexOptionList
+><defaultLevel shortname="Sec"
+ /><defaultGDBMLevel shortname="Sec"
+ /><levelList
+><level name="section" shortname="Sec"
+ /><level name="document" shortname="Doc"
+ /></levelList
+><searchTypeList
+><searchType name="form"
+ /><searchType name="plain"
+ /></searchTypeList
+></serviceRack
+></serviceRackList
+></buildConfig
+>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/infomine/README
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/infomine/README	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/infomine/README	(revision 13928)
@@ -0,0 +1,105 @@
+This collection talks to the iVia installation at INFOMINE, Riverside, 
+California. The software should work with any iVia installation. 
+
+Cgi scripts are called to do searching of and retrieval from the database. 
+All three are fairly generic CGI scripts; iVia's "theming" ability is used to
+ get the data back in the format we want-- there is a gsdl3 theme. 
+
+To create a new collection that talks to an iVia database, you need to create 
+the two configuration files, collectionConfig.xml, and buildConfig.xml. 
+The collectionConfig.xml needs to contain any display information for the 
+collection, and any metadata that is available. Also it can contain format 
+information for document display or search result lists if the default is 
+not useful.
+
+The buildConfig.xml file needs to specify the IViaProxy serviceRack 
+class. Inside this element should be the url of the iVia installation that
+you want to connect to. Here is an example:
+
+<buildConfig> 
+  <metadataList/>
+  <serviceRackList>                                                            
+    <serviceRack name="IViaProxy">
+      <iViaServer url="http://infominehelper.ucr.edu"/>
+    </serviceRack>
+  </serviceRackList>
+</buildConfig>
+
+
+The following describes the iVia cgi scripts.
+
+For performing a search:
+************************
+
+  <serverhome>/cgi-bin/canned_search
+
+Parameters:
+  Required parameters: theme=gsdl3&query=xxx
+  Useful parameters: no_of_records_per_page=10&start_page_no=1&fields='kw,su'
+  Other parameters: http://infomine.ucr.edu/help/adders/index.php?section=11
+  Example: http://infomine.ucr.edu/cgi-bin/canned_search?query=tree&
+              theme=gsdl3&no_of_records_per_page=10&start_page_no=1
+
+Fields include Title (ti), Subject (su), Keyword (kw), Author (au), 
+Description (de) and full text (fu). 'all' will search all fields.
+It's possible to do uch more advanced searches including phrase searching 
+and bolean queries.
+
+The canned_search result page will look something like this:
+  Resources: 58
+  Ids:  1015 22128 1730 6020 2981 1014 20147 2097 46569 4360
+
+For getting an HTML representation of a record:
+***********************************************
+
+  <serverhome>/cgi-bin/view_record
+
+Parameters:
+  Required parameters: theme=gsdl3&record_id=x
+  Example: http://infomine.ucr.edu/cgi-bin/view_record?theme=gsdl3&
+                record_id=2097
+
+The result page will be an HTML fragment; specifically, it will be an HTML
+table.  Again, the formatting is quite flexible.  There's one current
+problem: a lot of the data is displayed as hypertext links to new infomine
+searches; This should be changed eventually.
+
+For now, the Greenstone services process the records, replacing infomine 
+links with Greenstone links where possible. 
+
+For getting metadata for a set of records:
+******************************************
+
+  <serverhome>/cgi-bin/view_record_set
+
+Parameters:
+  Required parameters: theme=gsdl3&record_id_list=id1,id2,id3
+  Optional parameter: field_list=f1,f2,f3
+  Example: http://infomine.ucr.edu/cgi-bin/view_record_set?theme=gsdl3&
+                record_id_list=1015,2128,1730&field_list=url,title
+
+The result will look like this:
+
+  Record: 1015
+  url: http://www.fruit.affrc.go.jp/index-e.html
+  title: National Institute of Fruit Tree Science (Japan)
+
+  Record: 2128
+  url: http://www.publish.csiro.au/journals/ajb/
+  title: Australian Journal of Botany
+
+  Record: 1730
+  url: http://usda.mannlib.cornell.edu/reports/erssor/specialty/fts-bb/
+  title: Fruit and Tree Nuts : USDA Economics and Statistics System
+
+There are many different metadata fields that can be requested, including
+keywords, subjects, ivia_description, access, expert_created, foreign_source,
+foreign_id, and so on.  
+
+Note that the metadata always fits on one line (whitespace is explicitly
+normalised to space) to make parsing easier.  Generally, the metadata is
+in ISO-8859-15 format (i.e. ISO-8859-1 plus the Euro currency symbol). 
+Metadata is usually plain text, though the description field may contain
+HTML entities and limited set of HTML elements (bold tags, italic tags,
+links, and a few others).
+
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/infomine/etc/collectionConfig.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/infomine/etc/collectionConfig.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/infomine/etc/collectionConfig.xml	(revision 13928)
@@ -0,0 +1,39 @@
+<collectionConfig xmlns:gsf="http://www.greenstone.org/greenstone3/schema/ConfigFormat" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
+  <metadataList/>
+  <displayItemList>
+    <displayItem name='name' lang=''>Infomine proxy demo</displayItem>
+    <displayItem name='description' lang='en'>&lt;p&gt;This is a demonstration collection that acts as a proxy to the iVia database at &lt;a href="http://infomine.ucr.edu/"&gt;INFOMINE&lt;/a&gt;, Riverside, California. No data is stored locally; instead, the search and retrieval services invoke cgi scripts at infomine to query the database, and retrieve records and metadata.&lt;/p&gt;
+&lt;p&gt;A &lt;a
+    href="sites/localsite/collect/infomine/README"&gt;README&lt;/a&gt; file
+    describes the cgi scripts and how to invoke them. The configuration
+    files for the collection are very basic, and merely specify display 
+    information for the collection, and specify the IViaProxy service
+    rack. The collection configuration can be seen &lt;a
+    href="sites/localsite/collect/infomine/etc/collectionConfig.xml"&gt;here&lt;/a&gt;,
+    and the building configuration file can be seen &lt;a
+    href="sites/localsite/collect/infomine/index/buildConfig.xml"&gt;here&lt;/a&gt;.
+       You may need to "view page source" to see the raw XML. &lt;/p&gt; 
+</displayItem>    
+    <displayItem name='icon' lang='en'>infomine.gif</displayItem>  
+    <displayItem name='smallicon' lang='en'>infomine.gif</displayItem>  
+  </displayItemList>  
+  <search>
+    <format>
+      <gsf:template match="documentNode">
+	<td valign='top'><gsf:link><gsf:icon/></gsf:link></td><td>
+	  <table><tr><td><a><xsl:attribute name='href'><gsf:metadata name="url"/></xsl:attribute><b><gsf:metadata name="title"/></b></a></td></tr>
+	    <tr><td><gsf:metadata name="ivia_description"/></td></tr>
+	    <tr><td><b><gsf:metadata name="url"/></b></td></tr>
+	    <tr><td>[<gsf:link>View Full Record</gsf:link>]</td></tr></table>
+	</td>
+      </gsf:template>
+    </format>
+  </search>
+  <display>
+  <format>
+  <gsf:template name="documentHeading">
+  <gsf:metadata name="title"/>
+</gsf:template>	
+</format>
+</display>
+</collectionConfig>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/infomine/index/buildConfig.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/infomine/index/buildConfig.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/collect/infomine/index/buildConfig.xml	(revision 13928)
@@ -0,0 +1,11 @@
+<buildConfig> 
+  <metadataList/>
+  <serviceRackList>                                                            
+    <serviceRack name="IViaSearch">
+    <iViaServer url="http://infominehelper.ucr.edu"/>
+    </serviceRack>
+    <serviceRack name="IViaRetrieve">
+    <iViaServer url="http://infominehelper.ucr.edu"/>
+    </serviceRack>
+  </serviceRackList>
+</buildConfig>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/siteConfig.xml
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/siteConfig.xml	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/sites/localsite/siteConfig.xml	(revision 13928)
@@ -0,0 +1,35 @@
+<siteConfig xmlns:gsf='http://www.greenstone.org/greenstone3/schema/ConfigFormat' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
+  <siteList/>
+  <serviceRackList>
+    <!-- uncomment to provide the GATE tagging service -->
+    <!--<serviceRack name="GATEServices"/>-->
+    <serviceRack name="BerryBasket"/>
+    <serviceRack name="CrossCollectionSearch">
+      <format>
+	<!-- this format is used for the search results -->
+	<gsf:template match="documentNode">
+	  <td><a><xsl:attribute name='href'>?a=d&amp;c=<xsl:value-of select='@collection'/>&amp;d=<xsl:value-of select='@nodeID'/><xsl:if test="@nodeType='leaf'">&amp;sib=1</xsl:if>&amp;dt=<xsl:value-of select='@docType'/>&amp;p.a=q&amp;&amp;p.s=TextQuery&amp;p.c=</xsl:attribute><gsf:icon/></a></td>
+	  <td>[<a href='?a=p&amp;sa=about&amp;c={@collection}'><xsl:value-of select='@collection'/></a>]</td>
+	  <td><gsf:metadata name='Title'/></td>
+	</gsf:template>
+      </format>
+    </serviceRack>
+  </serviceRackList>
+  <serviceClusterList/>
+  <!-- this is a global replace list for all collections. At this stage it only applies to greenstone 2 collections. It will attempt to resolve most of the common macros that appear in metadata. You can add more items here if you want them to apply to all collections. To turn this on/off for a particular collection, add <replaceListRef id='xx'/> into the collectionConfig for each set that you want to use -->
+  <replaceList  id="gs2-standard">
+    <replace macro="_iconpdf_" scope="metadata" text="&lt;img src='interfaces/default/images/ipdf.gif' border='0'/&gt;" resolve="false"/>
+    <replace macro="_icondoc_" scope="metadata" text="&lt;img src='interfaces/default/images/imsword.gif' border='0'/&gt;" resolve="false"/>
+    <replace macro="_iconps_" scope="metadata" text="&lt;img src='interfaces/default/images/ips.gif' border='0'/&gt;" resolve="false"/>
+     <replace macro="_iconrtf_" scope="metadata" text="&lt;img src='interfaces/default/images/irtf.gif' border='0'/&gt;" resolve="false"/>
+    <replace macro="\[archivedir\]" scope="all" metadata="archivedir" resolve="false"/>
+    <replace macro="\[assocfilepath\]" scope="metadata" metadata="assocfilepath" resolve="false"/>
+    <replace macro="\[Image\]" scope="metadata" metadata="Image" resolve="false"/>
+    <replace macro="\[Thumb\]" scope="metadata" metadata="Thumb" resolve="false"/>
+    <!-- _httpsite_ and _clustername_ are macros that are defined in the java code -->
+    <replace macro="_httpcollection_" scope="metadata" text="_httpsite_/collect/_clustername_" resolve="true"/>
+    <replace macro="_httpprefix_" scope="metadata" text="_httpsite_" resolve="true"/>
+    <replace macro="_httpdocimg_" scope="text" text="_httpsite_/collect/_clustername_/index/assoc/[archivedir]/" resolve="true"/>
+    <replace macro="\[collection\]" scope="all" text="_clustername_" resolve="true"/>
+  </replaceList>
+</siteConfig>
Index: /tags/greenstone-3_02-distribution/gsdl3/web/xmlextras.js
===================================================================
--- /tags/greenstone-3_02-distribution/gsdl3/web/xmlextras.js	(revision 13928)
+++ /tags/greenstone-3_02-distribution/gsdl3/web/xmlextras.js	(revision 13928)
@@ -0,0 +1,149 @@
+//<script>
+//////////////////
+// Helper Stuff //
+//////////////////
+
+// used to find the Automation server name
+function getDomDocumentPrefix() {
+	if (getDomDocumentPrefix.prefix)
+		return getDomDocumentPrefix.prefix;
+	
+	var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"];
+	var o;
+	for (var i = 0; i < prefixes.length; i++) {
+		try {
+			// try to create the objects
+			o = new ActiveXObject(prefixes[i] + ".DomDocument");
+			return getDomDocumentPrefix.prefix = prefixes[i];
+		}
+		catch (ex) {};
+	}
+	
+	throw new Error("Could not find an installed XML parser");
+}
+
+function getXmlHttpPrefix() {
+	if (getXmlHttpPrefix.prefix)
+		return getXmlHttpPrefix.prefix;
+	
+	var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"];
+	var o;
+	for (var i = 0; i < prefixes.length; i++) {
+		try {
+			// try to create the objects
+			o = new ActiveXObject(prefixes[i] + ".XmlHttp");
+			return getXmlHttpPrefix.prefix = prefixes[i];
+		}
+		catch (ex) {};
+	}
+	
+	throw new Error("Could not find an installed XML parser");
+}
+
+//////////////////////////
+// Start the Real stuff //
+//////////////////////////
+
+
+// XmlHttp factory
+function XmlHttp() {}
+
+XmlHttp.create = function () {
+	try {
+		if (window.XMLHttpRequest) {
+			var req = new XMLHttpRequest();
+			
+			// some versions of Moz do not support the readyState property
+			// and the onreadystate event so we patch it!
+			if (req.readyState == null) {
+				req.readyState = 1;
+				req.addEventListener("load", function () {
+					req.readyState = 4;
+					if (typeof req.onreadystatechange == "function")
+						req.onreadystatechange();
+				}, false);
+			}
+			
+			return req;
+		}
+		if (window.ActiveXObject) {
+			return new ActiveXObject(getXmlHttpPrefix() + ".XmlHttp");
+		}
+	}
+	catch (ex) {}
+	// fell through
+	throw new Error("Your browser does not support XmlHttp objects");
+};
+
+// XmlDocument factory
+function XmlDocument() {}
+
+XmlDocument.create = function () {
+	try {
+		// DOM2
+		if (document.implementation && document.implementation.createDocument) {
+			var doc = document.implementation.createDocument("", "", null);
+			
+			// some versions of Moz do not support the readyState property
+			// and the onreadystate event so we patch it!
+			if (doc.readyState == null) {
+				doc.readyState = 1;
+				doc.addEventListener("load", function () {
+					doc.readyState = 4;
+					if (typeof doc.onreadystatechange == "function")
+						doc.onreadystatechange();
+				}, false);
+			}
+			
+			return doc;
+		}
+		if (window.ActiveXObject)
+			return new ActiveXObject(getDomDocumentPrefix() + ".DomDocument");
+	}
+	catch (ex) {}
+	throw new Error("Your browser does not support XmlDocument objects");
+};
+
+// Create the loadXML method and xml getter for Mozilla
+if (window.DOMParser &&
+	window.XMLSerializer &&
+	window.Node && Node.prototype && Node.prototype.__defineGetter__) {
+
+	// XMLDocument did not extend the Document interface in some versions
+	// of Mozilla. Extend both!
+	//XMLDocument.prototype.loadXML = 
+	Document.prototype.loadXML = function (s) {
+		
+		// parse the string to a new doc	
+		var doc2 = (new DOMParser()).parseFromString(s, "text/xml");
+		
+		// remove all initial children
+		while (this.hasChildNodes())
+			this.removeChild(this.lastChild);
+			
+		// insert and import nodes
+		for (var i = 0; i < doc2.childNodes.length; i++) {
+			this.appendChild(this.importNode(doc2.childNodes[i], true));
+		}
+	};
+	
+	
+	/*
+	 * xml getter
+	 *
+	 * This serializes the DOM tree to an XML String
+	 *
+	 * Usage: var sXml = oNode.xml
+	 *
+	 */
+	// XMLDocument did not extend the Document interface in some versions
+	// of Mozilla. Extend both!
+	/*
+	XMLDocument.prototype.__defineGetter__("xml", function () {
+		return (new XMLSerializer()).serializeToString(this);
+	});
+	*/
+	Document.prototype.__defineGetter__("xml", function () {
+		return (new XMLSerializer()).serializeToString(this);
+	});
+}
Index: /tags/greenstone-3_02-distribution/indexers/Makefile.in
===================================================================
--- /tags/greenstone-3_02-distribution/indexers/Makefile.in	(revision 13928)
+++ /tags/greenstone-3_02-distribution/indexers/Makefile.in	(revision 13928)
@@ -0,0 +1,93 @@
+###########################################################################
+#
+# Makefile -- Makefile for indexers used by Greenstone
+#
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 2007 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+# INDEXERDIRS contains the packages that we want to make and install.  It
+# is assumed that each package will have at least four rules: all, install,
+# clean, and distclean.
+
+ENABLE_ACCENTFOLD=@ENABLE_ACCENTFOLD@
+ifeq ($(ENABLE_ACCENTFOLD), 1)
+UNAC=packages/unac
+else
+UNAC=
+endif
+
+INDEXERDIRS = $(UNAC) mg mgpp lucene-gs 
+
+all install clean:
+	for odir in $(INDEXERDIRS); do \
+          echo making $@ in $$odir; \
+          (cd $$odir && $(MAKE) $(MDEFINES) $@) || exit 1; \
+        done
+
+nojava:
+	for odir in $(UNAC); do \
+          echo making $@ in $$odir; \
+          (cd $$odir && $(MAKE) $(MDEFINES) all) || exit 1; \
+        done
+	for odir in mg mgpp; do \
+          echo making $@ in $$odir; \
+          (cd $$odir && $(MAKE) $(MDEFINES) $@) || exit 1; \
+        done
+
+install-nojava:
+	for odir in $(UNAC); do \
+          echo making $@ in $$odir; \
+          (cd $$odir && $(MAKE) $(MDEFINES) install) || exit 1; \
+        done
+	for odir in mg mgpp; do \
+          echo making $@ in $$odir; \
+          (cd $$odir && $(MAKE) $(MDEFINES) $@) || exit 1; \
+        done
+
+javaonly:
+	for odir in mg mgpp; do \
+          echo making $@ in $$odir; \
+          (cd $$odir && $(MAKE) $(MDEFINES) $@) || exit 1; \
+        done
+	for odir in lucene-gs; do \
+          echo making $@ in $$odir; \
+          (cd $$odir && $(MAKE) $(MDEFINES) all) || exit 1; \
+        done
+
+install-javaonly:
+	for odir in mg mgpp; do \
+          echo making $@ in $$odir; \
+          (cd $$odir && $(MAKE) $(MDEFINES) $@) || exit 1; \
+        done
+	for odir in lucene-gs; do \
+          echo making $@ in $$odir; \
+          (cd $$odir && $(MAKE) $(MDEFINES) install) || exit 1; \
+        done
+
+
+distclean:
+	for odir in $(INDEXERDIRS); do \
+          echo making $@ in $$odir; \
+          (cd $$odir && $(MAKE) $(MDEFINES) $@) || exit 1; \
+        done
+	rm -f Makefile config.status config.log
Index: /tags/greenstone-3_02-distribution/indexers/README.txt
===================================================================
--- /tags/greenstone-3_02-distribution/indexers/README.txt	(revision 13928)
+++ /tags/greenstone-3_02-distribution/indexers/README.txt	(revision 13928)
@@ -0,0 +1,1 @@
+A temporary readme file for new indexers project for greenstone.
Index: /tags/greenstone-3_02-distribution/indexers/config.guess
===================================================================
--- /tags/greenstone-3_02-distribution/indexers/config.guess	(revision 13928)
+++ /tags/greenstone-3_02-distribution/indexers/config.guess	(revision 13928)
@@ -0,0 +1,1298 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+#   Free Software Foundation, Inc.
+
+timestamp='2001-07-12'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Written by Per Bothner <bothner@cygnus.com>.
+# Please send patches to <config-patches@gnu.org>.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+
+dummy=dummy-$$
+trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script.
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int dummy(){}" > $dummy.c ;
+	for c in cc gcc c89 ; do
+	  ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ;
+	  if test $? = 0 ; then
+	     CC_FOR_BUILD="$c"; break ;
+	  fi ;
+	done ;
+	rm -f $dummy.c $dummy.o $dummy.rel ;
+	if test x"$CC_FOR_BUILD" = x ; then
+	  CC_FOR_BUILD=no_compiler_found ;
+	fi
+	;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+	# Netbsd (nbsd) targets should (where applicable) match one or
+	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	# Determine the machine/vendor (is the vendor relevant).
+	case "${UNAME_MACHINE}" in
+	    amiga) machine=m68k-unknown ;;
+	    arm32) machine=arm-unknown ;;
+	    atari*) machine=m68k-atari ;;
+	    sun3*) machine=m68k-sun ;;
+	    mac68k) machine=m68k-apple ;;
+	    macppc) machine=powerpc-apple ;;
+	    hp3[0-9][05]) machine=m68k-hp ;;
+	    ibmrt|romp-ibm) machine=romp-ibm ;;
+	    *) machine=${UNAME_MACHINE}-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently, or will in the future.
+	case "${UNAME_MACHINE}" in
+	    i386|sparc|amiga|arm*|hp300|mvme68k|vax|atari|luna68k|mac68k|news68k|next68k|pc532|sun3*|x68k)
+		eval $set_cc_for_build
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep __ELF__ >/dev/null
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+	        os=netbsd
+		;;
+	esac
+	# The OS release
+	release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	echo "${machine}-${os}${release}"
+	exit 0 ;;
+    alpha:OSF1:*:*)
+	if test $UNAME_RELEASE = "V4.0"; then
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+	fi
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	cat <<EOF >$dummy.s
+	.data
+\$Lformat:
+	.byte 37,100,45,37,120,10,0	# "%d-%x\n"
+
+	.text
+	.globl main
+	.align 4
+	.ent main
+main:
+	.frame \$30,16,\$26,0
+	ldgp \$29,0(\$27)
+	.prologue 1
+	.long 0x47e03d80 # implver \$0
+	lda \$2,-1
+	.long 0x47e20c21 # amask \$2,\$1
+	lda \$16,\$Lformat
+	mov \$0,\$17
+	not \$1,\$18
+	jsr \$26,printf
+	ldgp \$29,0(\$26)
+	mov 0,\$16
+	jsr \$26,exit
+	.end main
+EOF
+	eval $set_cc_for_build
+	$CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
+	if test "$?" = 0 ; then
+		case `./$dummy` in
+			0-0)
+				UNAME_MACHINE="alpha"
+				;;
+			1-0)
+				UNAME_MACHINE="alphaev5"
+				;;
+			1-1)
+				UNAME_MACHINE="alphaev56"
+				;;
+			1-101)
+				UNAME_MACHINE="alphapca56"
+				;;
+			2-303)
+				UNAME_MACHINE="alphaev6"
+				;;
+			2-307)
+				UNAME_MACHINE="alphaev67"
+				;;
+		esac
+	fi
+	rm -f $dummy.s $dummy
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	exit 0 ;;
+    Alpha\ *:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# Should we change UNAME_MACHINE based on the output of uname instead
+	# of the specific Alpha model?
+	echo alpha-pc-interix
+	exit 0 ;;
+    21064:Windows_NT:50:3)
+	echo alpha-dec-winnt3.5
+	exit 0 ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit 0;;
+    amiga:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit 0 ;;
+    arc64:OpenBSD:*:*)
+	echo mips64el-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    arc:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    hkmips:OpenBSD:*:*)
+	echo mips-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    pmax:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    sgi:OpenBSD:*:*)
+	echo mips-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    wgrisc:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit 0 ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit 0;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit 0;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit 0 ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit 0 ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    i86pc:SunOS:5.*:*)
+	echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:*:*)
+	case "`/usr/bin/arch -k`" in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+	exit 0 ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit 0 ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit 0 ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos${UNAME_RELEASE}
+	exit 0 ;;
+    atari*:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit 0 ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit 0 ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit 0 ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit 0 ;;
+    sun3*:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mac68k:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mvme68k:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mvme88k:OpenBSD:*:*)
+	echo m88k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten${UNAME_RELEASE}
+	exit 0 ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit 0 ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit 0 ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit 0 ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit 0 ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	sed 's/^	//' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	eval $set_cc_for_build
+	$CC_FOR_BUILD $dummy.c -o $dummy \
+	  && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+	  && rm -f $dummy.c $dummy && exit 0
+	rm -f $dummy.c $dummy
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit 0 ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit 0 ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit 0 ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit 0 ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit 0 ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit 0 ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+	then
+	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+	       [ ${TARGET_BINARY_INTERFACE}x = x ]
+	    then
+		echo m88k-dg-dgux${UNAME_RELEASE}
+	    else
+		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+	    fi
+	else
+	    echo i586-dg-dgux${UNAME_RELEASE}
+	fi
+ 	exit 0 ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit 0 ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit 0 ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit 0 ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit 0 ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+	exit 0 ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	echo romp-ibm-aix      # uname -m gives an 8 hex-code CPU id
+	exit 0 ;;              # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit 0 ;;
+    ia64:AIX:*:*)
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+	exit 0 ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		sed 's/^		//' << EOF >$dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		eval $set_cc_for_build
+		$CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
+		rm -f $dummy.c $dummy
+		echo rs6000-ibm-aix3.2.5
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit 0 ;;
+    *:AIX:*:[45])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+	exit 0 ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit 0 ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+	echo romp-ibm-bsd4.4
+	exit 0 ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+	exit 0 ;;                           # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit 0 ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit 0 ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit 0 ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit 0 ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	case "${UNAME_MACHINE}" in
+	    9000/31? )            HP_ARCH=m68000 ;;
+	    9000/[34]?? )         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+              case "${HPUX_REV}" in
+                11.[0-9][0-9])
+                  if [ -x /usr/bin/getconf ]; then
+                    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+                        esac ;;
+                    esac
+                  fi ;;
+              esac
+              if [ "${HP_ARCH}" = "" ]; then
+              sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+              	{
+              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+              	case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+              	    switch (bits)
+              		{
+              		case 64: puts ("hppa2.0w"); break;
+              		case 32: puts ("hppa2.0n"); break;
+              		default: puts ("hppa2.0"); break;
+              		} break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+              	    puts ("hppa2.0"); break;
+              #endif
+              	default: puts ("hppa1.0"); break;
+              	}
+                  exit (0);
+              }
+EOF
+	eval $set_cc_for_build
+	(CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy`
+	if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi
+	rm -f $dummy.c $dummy
+	fi ;;
+	esac
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit 0 ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux${HPUX_REV}
+	exit 0 ;;
+    3050*:HI-UX:*:*)
+	sed 's/^	//' << EOF >$dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	eval $set_cc_for_build
+	$CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
+	rm -f $dummy.c $dummy
+	echo unknown-hitachi-hiuxwe2
+	exit 0 ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+	echo hppa1.1-hp-bsd
+	exit 0 ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit 0 ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit 0 ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+	echo hppa1.1-hp-osf
+	exit 0 ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit 0 ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo ${UNAME_MACHINE}-unknown-osf1mk
+	else
+	    echo ${UNAME_MACHINE}-unknown-osf1
+	fi
+	exit 0 ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit 0 ;;
+    hppa*:OpenBSD:*:*)
+	echo hppa-unknown-openbsd
+	exit 0 ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+        exit 0 ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+        exit 0 ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+        exit 0 ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+        exit 0 ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+        exit 0 ;;
+    CRAY*X-MP:*:*:*)
+	echo xmp-cray-unicos
+        exit 0 ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*[A-Z]90:*:*:*)
+	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+	      -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*T3D:*:*:*)
+	echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY-2:*:*:*)
+	echo cray2-cray-unicos
+        exit 0 ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit 0 ;;
+    hp300:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    *:BSD/OS:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    *:FreeBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	exit 0 ;;
+    *:OpenBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+	exit 0 ;;
+    i*:CYGWIN*:*)
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit 0 ;;
+    i*:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
+	exit 0 ;;
+    i*:PW*:*)
+	echo ${UNAME_MACHINE}-pc-pw32
+	exit 0 ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+	# UNAME_MACHINE based on the output of uname instead of i386?
+	echo i386-pc-interix
+	exit 0 ;;
+    i*:UWIN*:*)
+	echo ${UNAME_MACHINE}-pc-uwin
+	exit 0 ;;
+    p*:CYGWIN*:*)
+	echo powerpcle-unknown-cygwin
+	exit 0 ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    *:GNU:*:*)
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit 0 ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit 0 ;;
+    arm*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux
+	exit 0 ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    mips:Linux:*:*)
+	case `sed -n '/^byte/s/^.*: \(.*\) endian/\1/p' < /proc/cpuinfo` in
+	  big)    echo mips-unknown-linux-gnu && exit 0 ;;
+	  little) echo mipsel-unknown-linux-gnu && exit 0 ;;
+	esac
+	;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-gnu
+	exit 0 ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev67 ;;
+        esac
+	objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+	if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+	exit 0 ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) echo hppa1.1-unknown-linux-gnu ;;
+	  PA8*) echo hppa2.0-unknown-linux-gnu ;;
+	  *)    echo hppa-unknown-linux-gnu ;;
+	esac
+	exit 0 ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-gnu
+	exit 0 ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo ${UNAME_MACHINE}-ibm-linux
+	exit 0 ;;
+    sh*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    x86_64:Linux:*:*)
+	echo x86_64-unknown-linux-gnu
+	exit 0 ;;
+    i*86:Linux:*:*)
+	# The BFD linker knows what the default object file format is, so
+	# first see if it will tell us. cd to the root directory to prevent
+	# problems with other programs or directories called `ld' in the path.
+	ld_supported_targets=`cd /; ld --help 2>&1 \
+			 | sed -ne '/supported targets:/!d
+				    s/[ 	][ 	]*/ /g
+				    s/.*supported targets: *//
+				    s/ .*//
+				    p'`
+        case "$ld_supported_targets" in
+	  elf32-i386)
+		TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+		;;
+	  a.out-i386-linux)
+		echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+		exit 0 ;;		
+	  coff-i386)
+		echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+		exit 0 ;;
+	  "")
+		# Either a pre-BFD a.out linker (linux-gnuoldld) or
+		# one that does not give us useful --help.
+		echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+		exit 0 ;;
+	esac
+	# Determine whether the default compiler is a.out or elf
+	cat >$dummy.c <<EOF
+#include <features.h>
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+#ifdef __ELF__
+# ifdef __GLIBC__
+#  if __GLIBC__ >= 2
+    printf ("%s-pc-linux-gnu\n", argv[1]);
+#  else
+    printf ("%s-pc-linux-gnulibc1\n", argv[1]);
+#  endif
+# else
+   printf ("%s-pc-linux-gnulibc1\n", argv[1]);
+# endif
+#else
+  printf ("%s-pc-linux-gnuaout\n", argv[1]);
+#endif
+  return 0;
+}
+EOF
+	eval $set_cc_for_build
+	$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0
+	rm -f $dummy.c $dummy
+	test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+	;;
+    i*86:DYNIX/ptx:4*:*)
+	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+	# earlier versions are messed up and put the nodename in both
+	# sysname and nodename.
+	echo i386-sequent-sysv4
+	exit 0 ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+	exit 0 ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+	else
+		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+	fi
+	exit 0 ;;
+    i*86:*:5:[78]*)
+	case `/bin/uname -X | grep "^Machine"` in
+	    *486*)	     UNAME_MACHINE=i486 ;;
+	    *Pentium)	     UNAME_MACHINE=i586 ;;
+	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+	esac
+	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+	exit 0 ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	exit 0 ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit 0 ;;
+    pc:*:*:*)
+	# Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i386.
+	echo i386-pc-msdosdjgpp
+        exit 0 ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit 0 ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit 0 ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+	fi
+	exit 0 ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit 0 ;;
+    M68*:*:R3V[567]*:*)
+	test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+    3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && echo i486-ncr-sysv4 && exit 0 ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit 0 ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv${UNAME_RELEASE}
+	exit 0 ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit 0 ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit 0 ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo ${UNAME_MACHINE}-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit 0 ;;
+    PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                           # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit 0 ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes@openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit 0 ;;
+    *:*:*:FTX*)
+	# From seanf@swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit 0 ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux${UNAME_RELEASE}
+	exit 0 ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit 0 ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if [ -d /usr/nec ]; then
+	        echo mips-nec-sysv${UNAME_RELEASE}
+	else
+	        echo mips-unknown-sysv${UNAME_RELEASE}
+	fi
+        exit 0 ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit 0 ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit 0 ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit 0 ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux${UNAME_RELEASE}
+	exit 0 ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux${UNAME_RELEASE}
+	exit 0 ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+	exit 0 ;;
+    *:Rhapsody:*:*)
+	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+	exit 0 ;;
+    *:Darwin:*:*)
+	echo `uname -p`-apple-darwin${UNAME_RELEASE}
+	exit 0 ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	if test "${UNAME_MACHINE}" = "x86pc"; then
+		UNAME_MACHINE=pc
+	fi
+	echo `uname -p`-${UNAME_MACHINE}-nto-qnx
+	exit 0 ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit 0 ;;
+    NSR-[KW]:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk${UNAME_RELEASE}
+	exit 0 ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit 0 ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit 0 ;;
+    DS/*:UNIX_System_V:*:*)
+	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+	exit 0 ;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "$cputype" = "386"; then
+	    UNAME_MACHINE=i386
+	else
+	    UNAME_MACHINE="$cputype"
+	fi
+	echo ${UNAME_MACHINE}-unknown-plan9
+	exit 0 ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit 0 ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit 0 ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit 0 ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit 0 ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit 0 ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit 0 ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+	  ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+	printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+	printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+eval $set_cc_for_build
+$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0
+rm -f $dummy.c $dummy
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+	echo c1-convex-bsd
+	exit 0 ;;
+    c2*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit 0 ;;
+    c34*)
+	echo c34-convex-bsd
+	exit 0 ;;
+    c38*)
+	echo c38-convex-bsd
+	exit 0 ;;
+    c4*)
+	echo c4-convex-bsd
+	exit 0 ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+    ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
Index: /tags/greenstone-3_02-distribution/indexers/config.sub
===================================================================
--- /tags/greenstone-3_02-distribution/indexers/config.sub	(revision 13928)
+++ /tags/greenstone-3_02-distribution/indexers/config.sub	(revision 13928)
@@ -0,0 +1,1375 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+#   Free Software Foundation, Inc.
+
+timestamp='2001-06-08'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Please send patches to <config-patches@gnu.org>.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit 0;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+	-sun*os*)
+		# Prevent following clause from handling this invalid input.
+		;;
+	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+	-apple | -axis)
+		os=
+		basic_machine=$1
+		;;
+	-sim | -cisco | -oki | -wec | -winbond)
+		os=
+		basic_machine=$1
+		;;
+	-scout)
+		;;
+	-wrs)
+		os=-vxworks
+		basic_machine=$1
+		;;
+	-chorusos*)
+		os=-chorusos
+		basic_machine=$1
+		;;
+ 	-chorusrdb)
+ 		os=-chorusrdb
+		basic_machine=$1
+ 		;;
+	-hiux*)
+		os=-hiuxwe2
+		;;
+	-sco5)
+		os=-sco3.2v5
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco4)
+		os=-sco3.2v4
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2.[4-9]*)
+		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2v[4-9]*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco*)
+		os=-sco3.2v2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-udk*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-isc)
+		os=-isc2.2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-clix*)
+		basic_machine=clipper-intergraph
+		;;
+	-isc*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-lynx*)
+		os=-lynxos
+		;;
+	-ptx*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+		;;
+	-windowsnt*)
+		os=`echo $os | sed -e 's/windowsnt/winnt/'`
+		;;
+	-psos*)
+		os=-psos
+		;;
+	-mint | -mint[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+	# Recognize the basic CPU types without company name.
+	# Some are omitted here because they have special meanings below.
+	tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc \
+	        | arm | arme[lb] | arm[bl]e | armv[2345] | armv[345][lb] | strongarm | xscale \
+		| pyramid | mn10200 | mn10300 | tron | a29k \
+		| 580 | i960 | h8300 \
+		| x86 | ppcbe | mipsbe | mipsle | shbe | shle \
+		| hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \
+		| hppa64 \
+		| alpha | alphaev[4-8] | alphaev56 | alphapca5[67] \
+		| alphaev6[78] \
+		| we32k | ns16k | clipper | i370 | sh | sh[34] \
+		| powerpc | powerpcle \
+		| 1750a | dsp16xx | pdp10 | pdp11 \
+		| mips16 | mips64 | mipsel | mips64el \
+		| mips64orion | mips64orionel | mipstx39 | mipstx39el \
+		| mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \
+		| mips64vr5000 | mips64vr5000el | mcore | s390 | s390x \
+		| sparc | sparclet | sparclite | sparc64 | sparcv9 | sparcv9b \
+		| v850 | c4x \
+		| thumb | d10v | d30v | fr30 | avr | openrisc | tic80 \
+		| pj | pjl | h8500 | z8k)
+		basic_machine=$basic_machine-unknown
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12)
+		# Motorola 68HC11/12.
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+		;;
+
+	# We use `pc' rather than `unknown'
+	# because (1) that's what they normally are, and
+	# (2) the word "unknown" tends to confuse beginning users.
+	i*86 | x86_64)
+	  basic_machine=$basic_machine-pc
+	  ;;
+	# Object if more than one company name word.
+	*-*-*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+	# Recognize the basic CPU types with company name.
+	# FIXME: clean up the formatting here.
+	vax-* | tahoe-* | i*86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \
+	      | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | c[123]* \
+	      | arm-*  | armbe-* | armle-* | armv*-* | strongarm-* | xscale-* \
+	      | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
+	      | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \
+	      | xmp-* | ymp-* \
+	      | x86-* | ppcbe-* | mipsbe-* | mipsle-* | shbe-* | shle-* \
+	      | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \
+	      | hppa2.0n-* | hppa64-* \
+	      | alpha-* | alphaev[4-8]-* | alphaev56-* | alphapca5[67]-* \
+	      | alphaev6[78]-* \
+	      | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \
+	      | clipper-* | orion-* \
+	      | sparclite-* | pdp10-* | pdp11-* | sh-* | sh[34]-* | sh[34]eb-* \
+	      | powerpc-* | powerpcle-* | sparc64-* | sparcv9-* | sparcv9b-* | sparc86x-* \
+	      | mips16-* | mips64-* | mipsel-* \
+	      | mips64el-* | mips64orion-* | mips64orionel-* \
+	      | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \
+	      | mipstx39-* | mipstx39el-* | mcore-* \
+	      | f30[01]-* | f700-* | s390-* | s390x-* | sv1-* | t3e-* \
+	      | [cjt]90-* \
+	      | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \
+	      | thumb-* | v850-* | d30v-* | tic30-* | tic80-* | c30-* | fr30-* \
+	      | bs2000-* | tic54x-* | c54x-* | x86_64-* | pj-* | pjl-*)
+		;;
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	386bsd)
+		basic_machine=i386-unknown
+		os=-bsd
+		;;
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		basic_machine=m68000-att
+		;;
+	3b*)
+		basic_machine=we32k-att
+		;;
+	a29khif)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	adobe68k)
+		basic_machine=m68010-adobe
+		os=-scout
+		;;
+	alliant | fx80)
+		basic_machine=fx80-alliant
+		;;
+	altos | altos3068)
+		basic_machine=m68k-altos
+		;;
+	am29k)
+		basic_machine=a29k-none
+		os=-bsd
+		;;
+	amdahl)
+		basic_machine=580-amdahl
+		os=-sysv
+		;;
+	amiga | amiga-*)
+		basic_machine=m68k-unknown
+		;;
+	amigaos | amigados)
+		basic_machine=m68k-unknown
+		os=-amigaos
+		;;
+	amigaunix | amix)
+		basic_machine=m68k-unknown
+		os=-sysv4
+		;;
+	apollo68)
+		basic_machine=m68k-apollo
+		os=-sysv
+		;;
+	apollo68bsd)
+		basic_machine=m68k-apollo
+		os=-bsd
+		;;
+	aux)
+		basic_machine=m68k-apple
+		os=-aux
+		;;
+	balance)
+		basic_machine=ns32k-sequent
+		os=-dynix
+		;;
+	convex-c1)
+		basic_machine=c1-convex
+		os=-bsd
+		;;
+	convex-c2)
+		basic_machine=c2-convex
+		os=-bsd
+		;;
+	convex-c32)
+		basic_machine=c32-convex
+		os=-bsd
+		;;
+	convex-c34)
+		basic_machine=c34-convex
+		os=-bsd
+		;;
+	convex-c38)
+		basic_machine=c38-convex
+		os=-bsd
+		;;
+	cray | ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
+	cray2)
+		basic_machine=cray2-cray
+		os=-unicos
+		;;
+	[cjt]90)
+		basic_machine=${basic_machine}-cray
+		os=-unicos
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	da30 | da30-*)
+		basic_machine=m68k-da30
+		;;
+	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+		basic_machine=mips-dec
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		basic_machine=m68k-motorola
+		;;
+	delta88)
+		basic_machine=m88k-motorola
+		os=-sysv3
+		;;
+	dpx20 | dpx20-*)
+		basic_machine=rs6000-bull
+		os=-bosx
+		;;
+	dpx2* | dpx2*-bull)
+		basic_machine=m68k-bull
+		os=-sysv3
+		;;
+	ebmon29k)
+		basic_machine=a29k-amd
+		os=-ebmon
+		;;
+	elxsi)
+		basic_machine=elxsi-elxsi
+		os=-bsd
+		;;
+	encore | umax | mmax)
+		basic_machine=ns32k-encore
+		;;
+	es1800 | OSE68k | ose68k | ose | OSE)
+		basic_machine=m68k-ericsson
+		os=-ose
+		;;
+	fx2800)
+		basic_machine=i860-alliant
+		;;
+	genix)
+		basic_machine=ns32k-ns
+		;;
+	gmicro)
+		basic_machine=tron-gmicro
+		os=-sysv
+		;;
+	go32)
+		basic_machine=i386-pc
+		os=-go32
+		;;
+	h3050r* | hiux*)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	h8300hms)
+		basic_machine=h8300-hitachi
+		os=-hms
+		;;
+	h8300xray)
+		basic_machine=h8300-hitachi
+		os=-xray
+		;;
+	h8500hms)
+		basic_machine=h8500-hitachi
+		os=-hms
+		;;
+	harris)
+		basic_machine=m88k-harris
+		os=-sysv3
+		;;
+	hp300-*)
+		basic_machine=m68k-hp
+		;;
+	hp300bsd)
+		basic_machine=m68k-hp
+		os=-bsd
+		;;
+	hp300hpux)
+		basic_machine=m68k-hp
+		os=-hpux
+		;;
+	hp3k9[0-9][0-9] | hp9[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		basic_machine=m68000-hp
+		;;
+	hp9k3[2-9][0-9])
+		basic_machine=m68k-hp
+		;;
+	hp9k6[0-9][0-9] | hp6[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k7[0-79][0-9] | hp7[0-79][0-9])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k78[0-9] | hp78[0-9])
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][13679] | hp8[0-9][13679])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hppa-next)
+		os=-nextstep3
+		;;
+	hppaosf)
+		basic_machine=hppa1.1-hp
+		os=-osf
+		;;
+	hppro)
+		basic_machine=hppa1.1-hp
+		os=-proelf
+		;;
+	i370-ibm* | ibm*)
+		basic_machine=i370-ibm
+		;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+	i*86v32)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv32
+		;;
+	i*86v4*)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv4
+		;;
+	i*86v)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv
+		;;
+	i*86sol2)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-solaris2
+		;;
+	i386mach)
+		basic_machine=i386-mach
+		os=-mach
+		;;
+	i386-vsta | vsta)
+		basic_machine=i386-unknown
+		os=-vsta
+		;;
+	iris | iris4d)
+		basic_machine=mips-sgi
+		case $os in
+		    -irix*)
+			;;
+		    *)
+			os=-irix4
+			;;
+		esac
+		;;
+	isi68 | isi)
+		basic_machine=m68k-isi
+		os=-sysv
+		;;
+	m88k-omron*)
+		basic_machine=m88k-omron
+		;;
+	magnum | m3230)
+		basic_machine=mips-mips
+		os=-sysv
+		;;
+	merlin)
+		basic_machine=ns32k-utek
+		os=-sysv
+		;;
+	mingw32)
+		basic_machine=i386-pc
+		os=-mingw32
+		;;
+	miniframe)
+		basic_machine=m68000-convergent
+		;;
+	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+	mipsel*-linux*)
+		basic_machine=mipsel-unknown
+		os=-linux-gnu
+		;;
+	mips*-linux*)
+		basic_machine=mips-unknown
+		os=-linux-gnu
+		;;
+	mips3*-*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+		;;
+	mips3*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+		;;
+	mmix*)
+		basic_machine=mmix-knuth
+		os=-mmixware
+		;;
+	monitor)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	msdos)
+		basic_machine=i386-pc
+		os=-msdos
+		;;
+	mvs)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+	ncr3000)
+		basic_machine=i486-ncr
+		os=-sysv4
+		;;
+	netbsd386)
+		basic_machine=i386-unknown
+		os=-netbsd
+		;;
+	netwinder)
+		basic_machine=armv4l-rebel
+		os=-linux
+		;;
+	news | news700 | news800 | news900)
+		basic_machine=m68k-sony
+		os=-newsos
+		;;
+	news1000)
+		basic_machine=m68030-sony
+		os=-newsos
+		;;
+	news-3600 | risc-news)
+		basic_machine=mips-sony
+		os=-newsos
+		;;
+	necv70)
+		basic_machine=v70-nec
+		os=-sysv
+		;;
+	next | m*-next )
+		basic_machine=m68k-next
+		case $os in
+		    -nextstep* )
+			;;
+		    -ns2*)
+		      os=-nextstep2
+			;;
+		    *)
+		      os=-nextstep3
+			;;
+		esac
+		;;
+	nh3000)
+		basic_machine=m68k-harris
+		os=-cxux
+		;;
+	nh[45]000)
+		basic_machine=m88k-harris
+		os=-cxux
+		;;
+	nindy960)
+		basic_machine=i960-intel
+		os=-nindy
+		;;
+	mon960)
+		basic_machine=i960-intel
+		os=-mon960
+		;;
+	nonstopux)
+		basic_machine=mips-compaq
+		os=-nonstopux
+		;;
+	np1)
+		basic_machine=np1-gould
+		;;
+	nsr-tandem)
+		basic_machine=nsr-tandem
+		;;
+	op50n-* | op60c-*)
+		basic_machine=hppa1.1-oki
+		os=-proelf
+		;;
+	OSE68000 | ose68000)
+		basic_machine=m68000-ericsson
+		os=-ose
+		;;
+	os68k)
+		basic_machine=m68k-none
+		os=-os68k
+		;;
+	pa-hitachi)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	paragon)
+		basic_machine=i860-intel
+		os=-osf
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+        pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	pentium | p5 | k5 | k6 | nexgen)
+		basic_machine=i586-pc
+		;;
+	pentiumpro | p6 | 6x86 | athlon)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2)
+		basic_machine=i686-pc
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-*)
+		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumii-* | pentium2-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pn)
+		basic_machine=pn-gould
+		;;
+	power)	basic_machine=power-ibm
+		;;
+	ppc)	basic_machine=powerpc-unknown
+	        ;;
+	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppcle | powerpclittle | ppc-le | powerpc-little)
+		basic_machine=powerpcle-unknown
+	        ;;
+	ppcle-* | powerpclittle-*)
+		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ps2)
+		basic_machine=i386-ibm
+		;;
+	pw32)
+		basic_machine=i586-unknown
+		os=-pw32
+		;;
+	rom68k)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	rm[46]00)
+		basic_machine=mips-siemens
+		;;
+	rtpc | rtpc-*)
+		basic_machine=romp-ibm
+		;;
+	sa29200)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	sparclite-wrs)
+		basic_machine=sparclite-wrs
+		os=-vxworks
+		;;
+	sps7)
+		basic_machine=m68k-bull
+		os=-sysv2
+		;;
+	spur)
+		basic_machine=spur-unknown
+		;;
+	st2000)
+		basic_machine=m68k-tandem
+		;;
+	stratus)
+		basic_machine=i860-stratus
+		os=-sysv4
+		;;
+	sun2)
+		basic_machine=m68000-sun
+		;;
+	sun2os3)
+		basic_machine=m68000-sun
+		os=-sunos3
+		;;
+	sun2os4)
+		basic_machine=m68000-sun
+		os=-sunos4
+		;;
+	sun3os3)
+		basic_machine=m68k-sun
+		os=-sunos3
+		;;
+	sun3os4)
+		basic_machine=m68k-sun
+		os=-sunos4
+		;;
+	sun4os3)
+		basic_machine=sparc-sun
+		os=-sunos3
+		;;
+	sun4os4)
+		basic_machine=sparc-sun
+		os=-sunos4
+		;;
+	sun4sol2)
+		basic_machine=sparc-sun
+		os=-solaris2
+		;;
+	sun3 | sun3-*)
+		basic_machine=m68k-sun
+		;;
+	sun4)
+		basic_machine=sparc-sun
+		;;
+	sun386 | sun386i | roadrunner)
+		basic_machine=i386-sun
+		;;
+	sv1)
+		basic_machine=sv1-cray
+		os=-unicos
+		;;
+	symmetry)
+		basic_machine=i386-sequent
+		os=-dynix
+		;;
+	t3e)
+		basic_machine=t3e-cray
+		os=-unicos
+		;;
+	tic54x | c54x*)
+		basic_machine=tic54x-unknown
+		os=-coff
+		;;
+	tx39)
+		basic_machine=mipstx39-unknown
+		;;
+	tx39el)
+		basic_machine=mipstx39el-unknown
+		;;
+	tower | tower-32)
+		basic_machine=m68k-ncr
+		;;
+	udi29k)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	ultra3)
+		basic_machine=a29k-nyu
+		os=-sym1
+		;;
+	v810 | necv810)
+		basic_machine=v810-nec
+		os=-none
+		;;
+	vaxv)
+		basic_machine=vax-dec
+		os=-sysv
+		;;
+	vms)
+		basic_machine=vax-dec
+		os=-vms
+		;;
+	vpp*|vx|vx-*)
+               basic_machine=f301-fujitsu
+               ;;
+	vxworks960)
+		basic_machine=i960-wrs
+		os=-vxworks
+		;;
+	vxworks68)
+		basic_machine=m68k-wrs
+		os=-vxworks
+		;;
+	vxworks29k)
+		basic_machine=a29k-wrs
+		os=-vxworks
+		;;
+	w65*)
+		basic_machine=w65-wdc
+		os=-none
+		;;
+	w89k-*)
+		basic_machine=hppa1.1-winbond
+		os=-proelf
+		;;
+	windows32)
+		basic_machine=i386-pc
+		os=-windows32-msvcrt
+		;;
+	xmp)
+		basic_machine=xmp-cray
+		os=-unicos
+		;;
+        xps | xps100)
+		basic_machine=xps100-honeywell
+		;;
+	z8k-*-coff)
+		basic_machine=z8k-unknown
+		os=-sim
+		;;
+	none)
+		basic_machine=none-none
+		os=-none
+		;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		basic_machine=hppa1.1-winbond
+		;;
+	op50n)
+		basic_machine=hppa1.1-oki
+		;;
+	op60c)
+		basic_machine=hppa1.1-oki
+		;;
+	mips)
+		if [ x$os = x-linux-gnu ]; then
+			basic_machine=mips-unknown
+		else
+			basic_machine=mips-mips
+		fi
+		;;
+	romp)
+		basic_machine=romp-ibm
+		;;
+	rs6000)
+		basic_machine=rs6000-ibm
+		;;
+	vax)
+		basic_machine=vax-dec
+		;;
+	pdp10)
+		# there are many clones, so DEC is not a safe bet
+		basic_machine=pdp10-unknown
+		;;
+	pdp11)
+		basic_machine=pdp11-dec
+		;;
+	we32k)
+		basic_machine=we32k-att
+		;;
+	sh3 | sh4)
+		basic_machine=sh-unknown
+		;;
+	sparc | sparcv9 | sparcv9b)
+		basic_machine=sparc-sun
+		;;
+        cydra)
+		basic_machine=cydra-cydrome
+		;;
+	orion)
+		basic_machine=orion-highlevel
+		;;
+	orion105)
+		basic_machine=clipper-highlevel
+		;;
+	mac | mpw | mac-mpw)
+		basic_machine=m68k-apple
+		;;
+	pmac | pmac-mpw)
+		basic_machine=powerpc-apple
+		;;
+	c4x*)
+		basic_machine=c4x-none
+		os=-coff
+		;;
+	*-unknown)
+		# Make sure to match an already-canonicalized machine name.
+		;;
+	*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+	*-digital*)
+		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+		;;
+	*-commodore*)
+		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+	# -solaris* is a basic system type, with this one exception.
+	-solaris1 | -solaris1.*)
+		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		;;
+	-solaris)
+		os=-solaris2
+		;;
+	-svr4*)
+		os=-sysv4
+		;;
+	-unixware*)
+		os=-sysv4.2uw
+		;;
+	-gnu/linux*)
+		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+		;;
+	# First accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST END IN A *, to match a version number.
+	# -sysv* is not here because it comes later, after sysvr4.
+	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+	      | -aos* \
+	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+	      | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+	      | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+	      | -chorusos* | -chorusrdb* \
+	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
+	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* | -os2*)
+	# Remember, each alternative MUST END IN *, to match a version number.
+		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto*)
+		os=-nto-qnx
+		;;
+	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+		;;
+	-mac*)
+		os=`echo $os | sed -e 's|mac|macos|'`
+		;;
+	-linux*)
+		os=`echo $os | sed -e 's|linux|linux-gnu|'`
+		;;
+	-sunos5*)
+		os=`echo $os | sed -e 's|sunos5|solaris2|'`
+		;;
+	-sunos6*)
+		os=`echo $os | sed -e 's|sunos6|solaris3|'`
+		;;
+	-opened*)
+		os=-openedition
+		;;
+	-wince*)
+		os=-wince
+		;;
+	-osfrose*)
+		os=-osfrose
+		;;
+	-osf*)
+		os=-osf
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-386bsd)
+		os=-bsd
+		;;
+	-ctix* | -uts*)
+		os=-sysv
+		;;
+	-ns2 )
+	        os=-nextstep2
+		;;
+	-nsk*)
+		os=-nsk
+		;;
+	# Preserve the version number of sinix5.
+	-sinix5.*)
+		os=`echo $os | sed -e 's|sinix|sysv|'`
+		;;
+	-sinix*)
+		os=-sysv4
+		;;
+	-triton*)
+		os=-sysv3
+		;;
+	-oss*)
+		os=-sysv3
+		;;
+	-svr4)
+		os=-sysv4
+		;;
+	-svr3)
+		os=-sysv3
+		;;
+	-sysvr4)
+		os=-sysv4
+		;;
+	# This must come after -sysvr4.
+	-sysv*)
+		;;
+	-ose*)
+		os=-ose
+		;;
+	-es1800*)
+		os=-ose
+		;;
+	-xenix)
+		os=-xenix
+		;;
+        -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+	        os=-mint
+		;;
+	-none)
+		;;
+	*)
+		# Get rid of the `-' at the beginning of $os.
+		os=`echo $os | sed 's/[^-]*-//'`
+		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+		exit 1
+		;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+	*-acorn)
+		os=-riscix1.2
+		;;
+	arm*-rebel)
+		os=-linux
+		;;
+	arm*-semi)
+		os=-aout
+		;;
+	pdp10-*)
+		os=-tops20
+		;;
+        pdp11-*)
+		os=-none
+		;;
+	*-dec | vax-*)
+		os=-ultrix4.2
+		;;
+	m68*-apollo)
+		os=-domain
+		;;
+	i386-sun)
+		os=-sunos4.0.2
+		;;
+	m68000-sun)
+		os=-sunos3
+		# This also exists in the configure program, but was not the
+		# default.
+		# os=-sunos4
+		;;
+	m68*-cisco)
+		os=-aout
+		;;
+	mips*-cisco)
+		os=-elf
+		;;
+	mips*-*)
+		os=-elf
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=-sysv3
+		;;
+	sparc-* | *-sun)
+		os=-sunos4.1.1
+		;;
+	*-be)
+		os=-beos
+		;;
+	*-ibm)
+		os=-aix
+		;;
+	*-wec)
+		os=-proelf
+		;;
+	*-winbond)
+		os=-proelf
+		;;
+	*-oki)
+		os=-proelf
+		;;
+	*-hp)
+		os=-hpux
+		;;
+	*-hitachi)
+		os=-hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=-sysv
+		;;
+	*-cbm)
+		os=-amigaos
+		;;
+	*-dg)
+		os=-dgux
+		;;
+	*-dolphin)
+		os=-sysv3
+		;;
+	m68k-ccur)
+		os=-rtu
+		;;
+	m88k-omron*)
+		os=-luna
+		;;
+	*-next )
+		os=-nextstep
+		;;
+	*-sequent)
+		os=-ptx
+		;;
+	*-crds)
+		os=-unos
+		;;
+	*-ns)
+		os=-genix
+		;;
+	i370-*)
+		os=-mvs
+		;;
+	*-next)
+		os=-nextstep3
+		;;
+        *-gould)
+		os=-sysv
+		;;
+        *-highlevel)
+		os=-bsd
+		;;
+	*-encore)
+		os=-bsd
+		;;
+        *-sgi)
+		os=-irix
+		;;
+        *-siemens)
+		os=-sysv4
+		;;
+	*-masscomp)
+		os=-rtu
+		;;
+	f30[01]-fujitsu | f700-fujitsu)
+		os=-uxpv
+		;;
+	*-rom68k)
+		os=-coff
+		;;
+	*-*bug)
+		os=-coff
+		;;
+	*-apple)
+		os=-macos
+		;;
+	*-atari*)
+		os=-mint
+		;;
+	*)
+		os=-none
+		;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+	*-unknown)
+		case $os in
+			-riscix*)
+				vendor=acorn
+				;;
+			-sunos*)
+				vendor=sun
+				;;
+			-aix*)
+				vendor=ibm
+				;;
+			-beos*)
+				vendor=be
+				;;
+			-hpux*)
+				vendor=hp
+				;;
+			-mpeix*)
+				vendor=hp
+				;;
+			-hiux*)
+				vendor=hitachi
+				;;
+			-unos*)
+				vendor=crds
+				;;
+			-dgux*)
+				vendor=dg
+				;;
+			-luna*)
+				vendor=omron
+				;;
+			-genix*)
+				vendor=ns
+				;;
+			-mvs* | -opened*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+			-vxsim* | -vxworks*)
+				vendor=wrs
+				;;
+			-aux*)
+				vendor=apple
+				;;
+			-hms*)
+				vendor=hitachi
+				;;
+			-mpw* | -macos*)
+				vendor=apple
+				;;
+			-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+				vendor=atari
+				;;
+		esac
+		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+		;;
+esac
+
+echo $basic_machine$os
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
Index: /tags/greenstone-3_02-distribution/indexers/configure
===================================================================
--- /tags/greenstone-3_02-distribution/indexers/configure	(revision 13928)
+++ /tags/greenstone-3_02-distribution/indexers/configure	(revision 13928)
@@ -0,0 +1,2367 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.59.
+#
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)$' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+  	  /^X\/\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\/\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+	 case $as_dir in
+	 /*)
+	   if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+	     $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+	     $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+	     CONFIG_SHELL=$as_dir/$as_base
+	     export CONFIG_SHELL
+	     exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+	   fi;;
+	 esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='	' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" 	$as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete.  It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="mgpp/text/MGQuery.cpp"
+ac_subdirs_all="$ac_subdirs_all packages/unac"
+ac_subdirs_all="$ac_subdirs_all mg mgpp"
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS ENABLE_ACCENTFOLD subdirs LIBOBJS LTLIBOBJS'
+ac_subst_files=''
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+ac_prev=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_option in
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    eval "enable_$ac_feature=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_$ac_feature='$ac_optarg'" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_$ac_package='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/-/_/g'`
+    eval "with_$ac_package=no" ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+    eval "$ac_envvar='$ac_optarg'"
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+	      localstatedir libdir includedir oldincludedir infodir mandir
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then its parent.
+  ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$0" : 'X\(//\)[^/]' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r $srcdir/$ac_unique_file; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+   { (exit 1); exit 1; }; }
+  else
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+  fi
+fi
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+  { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+   { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+  cat <<_ACEOF
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+			  [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+			  [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR           user executables [EPREFIX/bin]
+  --sbindir=DIR          system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR       program executables [EPREFIX/libexec]
+  --datadir=DIR          read-only architecture-independent data [PREFIX/share]
+  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
+  --libdir=DIR           object code libraries [EPREFIX/lib]
+  --includedir=DIR       C header files [PREFIX/include]
+  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
+  --infodir=DIR          info documentation [PREFIX/info]
+  --mandir=DIR           man documentation [PREFIX/man]
+_ACEOF
+
+  cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --disable-accentfold    Disable Accent Folding support
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-unac=dir       Use specified unac directory
+
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  ac_popdir=`pwd`
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d $ac_dir || continue
+    ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+    cd $ac_dir
+    # Check for guested configure; otherwise get Cygnus style configure.
+    if test -f $ac_srcdir/configure.gnu; then
+      echo
+      $SHELL $ac_srcdir/configure.gnu  --help=recursive
+    elif test -f $ac_srcdir/configure; then
+      echo
+      $SHELL $ac_srcdir/configure  --help=recursive
+    elif test -f $ac_srcdir/configure.ac ||
+	   test -f $ac_srcdir/configure.in; then
+      echo
+      $ac_configure --help
+    else
+      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi
+    cd $ac_popdir
+  done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+  cat <<\_ACEOF
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.59.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo               = `(hostinfo) 2>/dev/null               || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    2)
+      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+      # Get rid of the leading space.
+      ac_sep=" "
+      ;;
+    esac
+  done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+{
+  (set) 2>&1 |
+    case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      sed -n \
+	"s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+      ;;
+    *)
+      sed -n \
+	"s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+}
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=$`echo $ac_var`
+      echo "$ac_var='"'"'$ac_val'"'"'"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=$`echo $ac_var`
+	echo "$ac_var='"'"'$ac_val'"'"'"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      sed "/^$/d" confdefs.h | sort
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      echo "$as_me: caught signal $ac_signal"
+    echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core &&
+  rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+     ' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . $cache_file;;
+      *)                      . ./$cache_file;;
+    esac
+  fi
+else
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+	       sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+  eval ac_new_val="\$ac_env_${ac_var}_value"
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	{ echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	{ echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
+echo "$as_me:   former value:  $ac_old_val" >&2;}
+	{ echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
+echo "$as_me:   current value: $ac_new_val" >&2;}
+	ac_cache_corrupted=:
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --enable-accentfolding or --disable-accentfolding was given.
+if test "${enable_accentfolding+set}" = set; then
+  enableval="$enable_accentfolding"
+  ENABLE_ACCENTFOLD=0
+else
+  ENABLE_ACCENTFOLD=1
+fi;
+cat >>confdefs.h <<_ACEOF
+#define ENABLE_ACCENTFOLD $ENABLE_ACCENTFOLD
+_ACEOF
+
+
+
+
+# Check whether --with-unac or --without-unac was given.
+if test "${with_unac+set}" = set; then
+  withval="$with_unac"
+  UNAC_DIR=$withval
+fi;
+
+if test $ENABLE_ACCENTFOLD = 1; then
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+  if test -f $ac_dir/install-sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f $ac_dir/install.sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f $ac_dir/shtool; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
+echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"
+ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
+
+
+
+subdirs="$subdirs packages/unac"
+
+fi
+
+
+
+subdirs="$subdirs mg mgpp"
+
+
+          ac_config_files="$ac_config_files Makefile"
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+  (set) 2>&1 |
+    case `(ac_space=' '; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;;
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n \
+	"s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+} |
+  sed '
+     t clear
+     : clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
+  if test -w $cache_file; then
+    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+    cat confcache >$cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[	 ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[	 ]*$//;
+}'
+fi
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then we branch to the quote section.  Otherwise,
+# look for a macro that doesn't take arguments.
+cat >confdef2opt.sed <<\_ACEOF
+t clear
+: clear
+s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\),-D\1=\2,g
+t quote
+s,^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\),-D\1=\2,g
+t quote
+d
+: quote
+s,[	 `~#$^&*(){}\\|;'"<>?],\\&,g
+s,\[,\\&,g
+s,\],\\&,g
+s,\$,$$,g
+p
+_ACEOF
+# We use echo to avoid assuming a particular line-breaking character.
+# The extra dot is to prevent the shell from consuming trailing
+# line-breaks from the sub-command output.  A line-break within
+# single-quotes doesn't work because, if this script is created in a
+# platform that uses two characters for line-breaks (e.g., DOS), tr
+# would break.
+ac_LF_and_DOT=`echo; echo .`
+DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'`
+rm -f confdef2opt.sed
+
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_i=`echo "$ac_i" |
+	 sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+  # 2. Add them.
+  ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)$' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+  	  /^X\/\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\/\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+	 case $as_dir in
+	 /*)
+	   if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+	     $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+	     $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+	     CONFIG_SHELL=$as_dir/$as_base
+	     export CONFIG_SHELL
+	     exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+	   fi;;
+	 esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='	' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" 	$as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.  Logging --version etc. is OK.
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.59.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+  echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+  echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+  echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+  echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number, then exit
+  -q, --quiet      do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+  --file=FILE[:TEMPLATE]
+		   instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.59,
+  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value.  By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "x$1" : 'x\([^=]*\)='`
+    ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  -*)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  *) # This is not an option, so the user has probably given explicit
+     # arguments.
+     ac_option=$1
+     ac_need_defaults=false;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --vers* | -V )
+    echo "$ac_cs_version"; exit 0 ;;
+  --he | --h)
+    # Conflict between --help and --header
+    { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    echo "$ac_cs_usage"; exit 0 ;;
+  --debug | --d* | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+    ac_need_defaults=false;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1" ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+  echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+  exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+  case "$ac_config_target" in
+  # Handling of arguments.
+  "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./confstat$$-$RANDOM
+  (umask 077 && mkdir $tmp)
+} ||
+{
+   echo "$me: cannot create a temporary directory in ." >&2
+   { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+  # Protect against being on the right side of a sed subst in config.status.
+  sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+   s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@ENABLE_ACCENTFOLD@,$ENABLE_ACCENTFOLD,;t t
+s,@subdirs@,$subdirs,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
+
+_ACEOF
+
+  cat >>$CONFIG_STATUS <<\_ACEOF
+  # Split the substitutions into bite-sized pieces for seds with
+  # small command number limits, like on Digital OSF/1 and HP-UX.
+  ac_max_sed_lines=48
+  ac_sed_frag=1 # Number of current file.
+  ac_beg=1 # First line for current file.
+  ac_end=$ac_max_sed_lines # Line after last line for current file.
+  ac_more_lines=:
+  ac_sed_cmds=
+  while $ac_more_lines; do
+    if test $ac_beg -gt 1; then
+      sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    else
+      sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    fi
+    if test ! -s $tmp/subs.frag; then
+      ac_more_lines=false
+    else
+      # The purpose of the label and of the branching condition is to
+      # speed up the sed processing (if there are no `@' at all, there
+      # is no need to browse any of the substitutions).
+      # These are the two extra sed commands mentioned above.
+      (echo ':t
+  /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+      if test -z "$ac_sed_cmds"; then
+	ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+      else
+	ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+      fi
+      ac_sed_frag=`expr $ac_sed_frag + 1`
+      ac_beg=$ac_end
+      ac_end=`expr $ac_end + $ac_max_sed_lines`
+    fi
+  done
+  if test -z "$ac_sed_cmds"; then
+    ac_sed_cmds=cat
+  fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+	cat >$tmp/stdin
+	ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+	ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+  ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+  { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+  ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    configure_input=
+  else
+    configure_input="$ac_file.  "
+  fi
+  configure_input=$configure_input"Generated from `echo $ac_file_in |
+				     sed 's,.*/,,'` by configure."
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+	 # Absolute (can't be DOS-style, as IFS=:)
+	 test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+	 echo "$f";;
+      *) # Relative
+	 if test -f "$f"; then
+	   # Build tree
+	   echo "$f"
+	 elif test -f "$srcdir/$f"; then
+	   # Source tree
+	   echo "$srcdir/$f"
+	 else
+	   # /dev/null tree
+	   { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+	 fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+  rm -f $tmp/stdin
+  if test x"$ac_file" != x-; then
+    mv $tmp/out $ac_file
+  else
+    cat $tmp/out
+    rm -f $tmp/out
+  fi
+
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
+
+#
+# CONFIG_SUBDIRS section.
+#
+if test "$no_recursion" != yes; then
+
+  # Remove --cache-file and --srcdir arguments so they do not pile up.
+  ac_sub_configure_args=
+  ac_prev=
+  for ac_arg in $ac_configure_args; do
+    if test -n "$ac_prev"; then
+      ac_prev=
+      continue
+    fi
+    case $ac_arg in
+    -cache-file | --cache-file | --cache-fil | --cache-fi \
+    | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+      ac_prev=cache_file ;;
+    -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+    | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \
+    | --c=*)
+      ;;
+    --config-cache | -C)
+      ;;
+    -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+      ac_prev=srcdir ;;
+    -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+      ;;
+    -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+      ac_prev=prefix ;;
+    -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+      ;;
+    *) ac_sub_configure_args="$ac_sub_configure_args $ac_arg" ;;
+    esac
+  done
+
+  # Always prepend --prefix to ensure using the same prefix
+  # in subdir configurations.
+  ac_sub_configure_args="--prefix=$prefix $ac_sub_configure_args"
+
+  ac_popdir=`pwd`
+  for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue
+
+    # Do not complain, so a configure script can configure whichever
+    # parts of a large source tree are present.
+    test -d $srcdir/$ac_dir || continue
+
+    { echo "$as_me:$LINENO: configuring in $ac_dir" >&5
+echo "$as_me: configuring in $ac_dir" >&6;}
+    { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+    ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+
+    cd $ac_dir
+
+    # Check for guested configure; otherwise get Cygnus style configure.
+    if test -f $ac_srcdir/configure.gnu; then
+      ac_sub_configure="$SHELL '$ac_srcdir/configure.gnu'"
+    elif test -f $ac_srcdir/configure; then
+      ac_sub_configure="$SHELL '$ac_srcdir/configure'"
+    elif test -f $ac_srcdir/configure.in; then
+      ac_sub_configure=$ac_configure
+    else
+      { echo "$as_me:$LINENO: WARNING: no configuration information is in $ac_dir" >&5
+echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;}
+      ac_sub_configure=
+    fi
+
+    # The recursion is here.
+    if test -n "$ac_sub_configure"; then
+      # Make the cache file name correct relative to the subdirectory.
+      case $cache_file in
+      [\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;;
+      *) # Relative path.
+	ac_sub_cache_file=$ac_top_builddir$cache_file ;;
+      esac
+
+      { echo "$as_me:$LINENO: running $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5
+echo "$as_me: running $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;}
+      # The eval makes quoting arguments work.
+      eval $ac_sub_configure $ac_sub_configure_args \
+	   --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir ||
+	{ { echo "$as_me:$LINENO: error: $ac_sub_configure failed for $ac_dir" >&5
+echo "$as_me: error: $ac_sub_configure failed for $ac_dir" >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+
+    cd $ac_popdir
+  done
+fi
+
+
+
Index: /tags/greenstone-3_02-distribution/indexers/configure.ac
===================================================================
--- /tags/greenstone-3_02-distribution/indexers/configure.ac	(revision 13928)
+++ /tags/greenstone-3_02-distribution/indexers/configure.ac	(revision 13928)
@@ -0,0 +1,23 @@
+dnl
+dnl Disable accent folding
+dnl
+
+AC_INIT(mgpp/text/MGQuery.cpp)
+AC_ARG_ENABLE(accentfolding, [  --disable-accentfold    Disable Accent Folding support], ENABLE_ACCENTFOLD=0, ENABLE_ACCENTFOLD=1)
+AC_DEFINE_UNQUOTED(ENABLE_ACCENTFOLD, $ENABLE_ACCENTFOLD)
+AC_SUBST(ENABLE_ACCENTFOLD)
+
+dnl
+dnl Specify location of unac - if specified, will be passed to cascading configures
+dnl
+AC_ARG_WITH(unac, [  --with-unac=dir       Use specified unac directory], UNAC_DIR=$withval)
+
+if test $ENABLE_ACCENTFOLD = 1; then
+AC_CONFIG_SUBDIRS(packages/unac)
+fi
+
+AC_CONFIG_SUBDIRS(mg mgpp)
+
+AC_OUTPUT(Makefile)
+
+
Index: /tags/greenstone-3_02-distribution/indexers/install-sh
===================================================================
--- /tags/greenstone-3_02-distribution/indexers/install-sh	(revision 13928)
+++ /tags/greenstone-3_02-distribution/indexers/install-sh	(revision 13928)
@@ -0,0 +1,238 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+tranformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+	-c) instcmd="$cpprog"
+	    shift
+	    continue;;
+
+	-d) dir_arg=true
+	    shift
+	    continue;;
+
+	-m) chmodcmd="$chmodprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-o) chowncmd="$chownprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-g) chgrpcmd="$chgrpprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-s) stripcmd="$stripprog"
+	    shift
+	    continue;;
+
+	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
+	    shift
+	    continue;;
+
+	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+	    shift
+	    continue;;
+
+	*)  if [ x"$src" = x ]
+	    then
+		src=$1
+	    else
+		# this colon is to work around a 386BSD /bin/sh bug
+		:
+		dst=$1
+	    fi
+	    shift
+	    continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+	echo "install:	no input file specified"
+	exit 1
+else
+	true
+fi
+
+if [ x"$dir_arg" != x ]; then
+	dst=$src
+	src=""
+	
+	if [ -d $dst ]; then
+		instcmd=:
+	else
+		instcmd=mkdir
+	fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+	if [ -f $src -o -d $src ]
+	then
+		true
+	else
+		echo "install:  $src does not exist"
+		exit 1
+	fi
+	
+	if [ x"$dst" = x ]
+	then
+		echo "install:	no destination specified"
+		exit 1
+	else
+		true
+	fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+	if [ -d $dst ]
+	then
+		dst="$dst"/`basename $src`
+	else
+		true
+	fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='	
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+	pathcomp="${pathcomp}${1}"
+	shift
+
+	if [ ! -d "${pathcomp}" ] ;
+        then
+		$mkdirprog "${pathcomp}"
+	else
+		true
+	fi
+
+	pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+	$doit $instcmd $dst &&
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+	if [ x"$transformarg" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		dstfile=`basename $dst $transformbasename | 
+			sed $transformarg`$transformbasename
+	fi
+
+# don't allow the sed command to completely eliminate the filename
+
+	if [ x"$dstfile" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		true
+	fi
+
+# Make a temp file name in the proper directory.
+
+	dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+	$doit $instcmd $src $dsttmp &&
+
+	trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+	$doit $rmcmd -f $dstdir/$dstfile &&
+	$doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
Index: /tags/greenstone-3_02-distribution/indexers/lucene-gs/Makefile
===================================================================
--- /tags/greenstone-3_02-distribution/indexers/lucene-gs/Makefile	(revision 13928)
+++ /tags/greenstone-3_02-distribution/indexers/lucene-gs/Makefile	(revision 13928)
@@ -0,0 +1,21 @@
+LUCENE_JAR = ./lib/lucene-core-2.0.0.jar
+CLASSPATH = $(LUCENE_JAR):classes
+
+all: compile jar
+
+compile:
+	mkdir -p classes
+	javac -classpath $(CLASSPATH):. -d classes -sourcepath src/ src/org/greenstone/LuceneWrapper/*.java
+
+jar:
+	cd classes && jar xf ../$(LUCENE_JAR)
+	jar cvf LuceneWrapper.jar -C classes .
+
+install:
+
+clean:
+	/bin/rm -f classes/org/greenstone/LuceneWrapper/*.class
+
+distclean: clean
+	if test -e classes; then /bin/rm -r classes; fi
+	if test -e LuceneWrapper.jar; then /bin/rm -r LuceneWrapper.jar; fi
Index: /tags/greenstone-3_02-distribution/indexers/lucene-gs/lib/lucene-license.txt
===================================================================
--- /tags/greenstone-3_02-distribution/indexers/lucene-gs/lib/lucene-license.txt	(revision 13928)
+++ /tags/greenstone-3_02-distribution/indexers/lucene-gs/lib/lucene-license.txt	(revision 13928)
@@ -0,0 +1,204 @@
+Lucene v 1.4.1 is licensed under the Apache Software License 2.0
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
Index: /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/GS2IndexModifier.java
===================================================================
--- /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/GS2IndexModifier.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/GS2IndexModifier.java	(revision 13928)
@@ -0,0 +1,132 @@
+/** @file GS2IndexModifier.java
+ *
+ *  Extends the standard IndexModifier so that a use can retrieve documents and
+ *  the underlying IndexReader and IndexWriter. 
+ *
+ *  Addresses the problem that the Lucene standard IndexModifier can't actually
+ *  return a specified Document object, nor does it expose the IndexReader and
+ *  IndexWriter so the user can access their methods instead.
+ *
+ *  A component of the Greenstone digital library software from the New Zealand 
+ *  Digital Library Project at the University of Waikato, New Zealand.
+ *
+ *  This program is free software; you can redistribute it and/or modify it 
+ *  under the terms of the GNU General Public License as published by the Free 
+ *  Software Foundation; either version 2 of the License, or (at your option) 
+ *  any later version.
+ *
+ *  This program 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 for 
+ *  more details.
+ *
+ *  You should have received a copy of the GNU General Public License along 
+ *  with this program; if not, write to the Free Software Foundation, Inc., 675
+ *  Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Copyright (c) 2006 DL Consulting Ltd., New Zealand
+ */
+
+package org.greenstone.LuceneWrapper;
+
+import java.io.IOException;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.index.IndexModifier;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.index.TermPositions;
+import org.apache.lucene.search.Searcher;
+import org.apache.lucene.search.IndexSearcher;
+
+/**
+ */
+public class GS2IndexModifier
+    extends IndexModifier
+{
+    /** **/
+    private boolean debug = true;
+
+    /**
+     */
+    public GS2IndexModifier (String dir_name, Analyzer analyzer)
+        throws IOException
+    {
+        super(dir_name, analyzer, false);
+    }
+    /** GS2IndexModifier() **/
+
+    /**
+     */
+    protected void debug(String message)
+    {
+        if(debug)
+            {
+                System.err.println(message);
+            }
+    }
+    /** debug() **/
+
+    /**
+     */
+    public Document document(int n)
+        throws IOException
+    {
+        // Ensure the reader exists
+        createIndexReader();
+        return indexReader.document(n);
+    }
+    /** document() **/
+
+    /**
+     */
+    public int getDocNumByNodeID(int node_id)
+        throws IOException
+    {
+        debug("GS2IndexModifier.getDocument(" + node_id + ")");
+        int doc_num = -1;
+        // Create a new term to encapsulate this node id
+        Term term = new Term("nodeID", String.valueOf(node_id));
+        debug("Searching using term: " + term.toString());
+        // Ensure the indexReader exists
+        createIndexReader();
+        // We can return an enumeration of docNums which contains this term
+        TermPositions term_positions = indexReader.termPositions(term);
+        // If the size of term_positions is not 1 then somethings gone wrong in
+        // that the original terms did not uniquely identify a document.
+        if (term_positions.next())
+            {
+                doc_num = term_positions.doc();
+            }
+        else
+            {
+                debug("Term doesn't exists in index");
+            }
+        term_positions.close();
+        // To the garbage collection with thee
+        term_positions = null;
+        term = null;
+        // Done
+        return doc_num;
+    }
+    /** getDocumentByNodeID() **/
+
+    /**
+     */
+    public IndexReader getIndexReader()
+    {
+        return indexReader;
+    }
+    /** getIndexReader() **/
+
+    /**
+     */
+    public IndexWriter getIndexWriter()
+    {
+        return indexWriter;
+    }
+    /** getIndexWriter() **/
+}
+/** GS2IndexModifier **/
Index: /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/GS2LuceneDelete.java
===================================================================
--- /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/GS2LuceneDelete.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/GS2LuceneDelete.java	(revision 13928)
@@ -0,0 +1,191 @@
+/** @file GS2LuceneDelete.java
+ *
+ *  Provides a wrapper to the document deleting features of Lucene. 
+ *
+ *  This java application makes use of the existing Lucene class IndexModifier 
+ *  to access and make changes to the information stored about documents in a
+ *  Lucene database. This is an essential component of the IncrementalBuilder
+ *  PERL module, and endevours to make editing the text and metadata of 
+ *  documents without having to rebuild the entire collection a reality (in
+ *  other words, true incremental/dynamic building).
+ *
+ *  A component of the Greenstone digital library software from the New Zealand 
+ *  Digital Library Project at the University of Waikato, New Zealand.
+ *
+ *  This program is free software; you can redistribute it and/or modify it 
+ *  under the terms of the GNU General Public License as published by the Free 
+ *  Software Foundation; either version 2 of the License, or (at your option) 
+ *  any later version.
+ *
+ *  This program 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 for 
+ *  more details.
+ *
+ *  You should have received a copy of the GNU General Public License along 
+ *  with this program; if not, write to the Free Software Foundation, Inc., 675
+ *  Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Copyright (c) 2006 DL Consulting Ltd., New Zealand
+ */
+
+package org.greenstone.LuceneWrapper;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+
+
+/** Contains methods for deleting a document that has previously been indexed
+ *  into a Lucene database.
+ *  @author John Thompson, DL Consulting Ltd. (unless stated otherwise)
+ */
+public class GS2LuceneDelete
+{
+    /** This is the main entry point to the deletor and is responsible for 
+     *  parsing the arguments and creating an instance of the deletor class.
+     *
+     *  @param  args The arguments passed into the application as a string
+     *               array
+     *  @return An integer describing the exit state of the application
+     *  @throws Exception on any fatal error state
+     */
+    static public void main (String args[])
+        throws Exception
+    {
+        // Parse arguments
+        int node_id = -1;
+        String index_path = "";
+
+        for (int i = 0; i < args.length; i += 2)
+            {
+                if (args[i].equals("--index"))
+                    {
+                        index_path = args[i + 1];
+                    }
+                else if (args[i].equals("--nodeid"))
+                    {
+                        String temp = args[i + 1];
+                        node_id = Integer.parseInt(temp);
+                        temp = null; // Off to the gc with you!
+                    }
+                else 
+                    {
+                        System.out.println("Error! Unknown argument: " + args[i]);
+                        GS2LuceneDelete.printUsage();
+                    }
+            }
+
+        // Check arguments
+        if(index_path.equals(""))
+            {
+                System.out.println("Error! Missing index path");
+                GS2LuceneDelete.printUsage();
+            }
+        if(node_id == -1)
+            {
+                System.out.println("Error! Missing or invalid Node ID");
+                GS2LuceneDelete.printUsage();
+            }
+
+
+        // Instantiate deletor, and perform the delete
+        GS2LuceneDelete deletor = new GS2LuceneDelete(index_path);
+        deletor.deleteDocument(node_id);
+        deletor.destroy();
+        deletor = null;
+    }
+    /** main() **/
+
+    /** **/
+    private boolean debug = true;
+
+    /** **/
+    private GS2IndexModifier index_modifier;
+
+    /** Constructor which takes the path to the Lucene index to be edited.
+     *
+     *  @param  index_path The full path to the index directory as a String
+     */
+    public GS2LuceneDelete(String index_path)
+        throws IOException
+    {
+        Analyzer analyzer = new StandardAnalyzer();
+        index_modifier = new GS2IndexModifier(index_path, analyzer);
+    }
+    /** GS2LuceneDelete **/
+
+    /** When called prints a debug message but only if debugging is enabled.
+     */
+    public void debug(String message)
+    {
+        if(debug)
+            {
+                System.err.println(message);
+            }
+    }
+    /** debug() **/
+
+    /** Destructor which unallocates connection to Lucene.
+     */
+    public void destroy()
+        throws IOException
+    {
+        index_modifier.close();
+        index_modifier = null;
+    }
+
+    /** Delete the indicated document from the Lucene index. This process is
+     *  very similar to the initial step of index editing.
+     *
+     *  @param  node_id   The unique identifier of a Lucene document as an
+     *                    integer
+     */
+    public void deleteDocument(int node_id)
+        throws IOException
+    {
+        debug("GS2LuceneDelete.deleteDocument(" + node_id + ")");
+        debug("- Initial number of documents in index: " + index_modifier.docCount());
+        // Retrieve the document requested
+        int doc_num = index_modifier.getDocNumByNodeID(node_id);
+        if (doc_num != -1)
+            {
+                debug("* Found document #" + doc_num);
+                // Retrieve the actual document
+                Document document = index_modifier.document(doc_num);
+                // Remove the document from the index before modifying
+                index_modifier.deleteDocument(doc_num);
+                debug("* Removed document from index");
+            }
+        else
+            {
+                debug("- No such document!");
+            }
+        debug("- Final number of documents in index: " + index_modifier.docCount());
+    }
+    /** editIndex() **/
+
+    /** Display program usage message.
+     */
+    static public void printUsage()
+    {
+        System.out.println("usage: GS2LuceneDelete --index <path> --nodeid <int>");
+        System.out.println("");
+        System.out.println("where:");
+        System.out.println("  index    - is the full path to the directory containing the directory");
+        System.out.println("             to edit, including the level (ie didx, sidx)");
+        System.out.println("  nodeid   - the unique identifier of the document to delete. This is the");
+        System.out.println("             same as the docnum in the GDBM");
+        System.out.println("");
+        System.exit(0);
+    }
+    /** printUsage() **/
+
+}
+/** class GS2LuceneDelete **/
Index: /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/GS2LuceneEditor.java
===================================================================
--- /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/GS2LuceneEditor.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/GS2LuceneEditor.java	(revision 13928)
@@ -0,0 +1,358 @@
+/** @file GS2LuceneEditor.java
+ *
+ *  Provides a wrapper to the index/document editing features of Lucene. 
+ *
+ *  This java application makes use of the existing Lucene class IndexModifier 
+ *  to access and make changes to the information stored about documents in a
+ *  Lucene database. This is an essential component of the IncrementalBuilder
+ *  PERL module, and endevours to make editing the text and metadata of 
+ *  documents without having to rebuild the entire collection a reality (in
+ *  other words, true incremental/dynamic building).
+ *
+ *  A component of the Greenstone digital library software from the New Zealand 
+ *  Digital Library Project at the University of Waikato, New Zealand.
+ *
+ *  This program is free software; you can redistribute it and/or modify it 
+ *  under the terms of the GNU General Public License as published by the Free 
+ *  Software Foundation; either version 2 of the License, or (at your option) 
+ *  any later version.
+ *
+ *  This program 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 for 
+ *  more details.
+ *
+ *  You should have received a copy of the GNU General Public License along 
+ *  with this program; if not, write to the Free Software Foundation, Inc., 675
+ *  Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Copyright (c) 2006 DL Consulting Ltd., New Zealand
+ */
+
+package org.greenstone.LuceneWrapper;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+
+
+/** Contains methods for modifying a document that has previously been indexed
+ *  into a Lucene database.
+ *  @author John Thompson, DL Consulting Ltd.
+ */
+public class GS2LuceneEditor
+{
+    /** This is the main entry point to the editor and is responsible for 
+     *  parsing the arguments and creating an instance of the editor class.
+     *
+     *  @param  args The arguments passed into the application as a string
+     *               array
+     *  @return An integer describing the exit state of the application
+     *  @throws Exception on any fatal error state
+     *
+     *  @author John Thompson, DL Consulting Ltd.
+     */
+    static public void main (String args[])
+        throws Exception
+    {
+        // Parse arguments
+        int node_id = -1;
+        String field = "";
+        String index_path = "";
+        String new_value = "";
+        String old_value = "";
+
+        for (int i = 0; i < args.length; i += 2)
+            {
+                if (args[i].equals("--index"))
+                    {
+                        index_path = args[i + 1];
+                    }
+                else if (args[i].equals("--nodeid"))
+                    {
+                        String temp = args[i + 1];
+                        node_id = Integer.parseInt(temp);
+                        temp = null; // Off to the gc with you!
+                    }
+                else if (args[i].equals("--field"))
+                    {
+                        field = args[i + 1];
+                    }
+                else if (args[i].equals("--oldvalue"))
+                    {
+                        old_value = args[i + 1];
+                    }
+                else if (args[i].equals("--newvalue"))
+                    {
+                        new_value = args[i + 1];
+                    }
+                else 
+                    {
+                        System.out.println("Error! Unknown argument: " + args[i]);
+                        GS2LuceneEditor.printUsage();
+                    }
+            }
+
+        // Check arguments
+        if(index_path.equals(""))
+            {
+                System.out.println("Error! Missing index path");
+                GS2LuceneEditor.printUsage();
+            }
+        if(field.equals(""))
+            {
+                System.out.println("Error! Missing field");
+                GS2LuceneEditor.printUsage();
+            }
+        if(node_id == -1)
+            {
+                System.out.println("Error! Missing or invalid Node ID");
+                GS2LuceneEditor.printUsage();
+            }
+        if(old_value.equals("") && new_value.equals(""))
+            {
+                System.out.println("Error! No modification requested");
+                GS2LuceneEditor.printUsage(); 
+            }
+
+
+        // Instantiate editor, and perform the edit
+        GS2LuceneEditor editor = new GS2LuceneEditor(index_path);
+        editor.editIndex(node_id, field, old_value, new_value);
+        editor.destroy();
+        editor = null;
+    }
+    /** main() **/
+
+    /** **/
+    private boolean debug = true;
+
+    /** **/
+    private GS2IndexModifier index_modifier;
+
+    /** Constructor which takes the path to the Lucene index to be edited.
+     *
+     *  @param  index_path The full path to the index directory as a String
+     *
+     *  @author John Thompson, DL Consulting Ltd.
+     */
+    public GS2LuceneEditor(String index_path)
+        throws IOException
+    {
+        Analyzer analyzer = new StandardAnalyzer();
+        // create an index in /tmp/index, overwriting an existing one:
+        index_modifier = new GS2IndexModifier(index_path, analyzer);
+    }
+    /** GS2LuceneEditor **/
+
+    /**
+     */
+    public void debug(String message)
+    {
+        if(debug)
+            {
+                System.err.println(message);
+            }
+    }
+    /** debug() **/
+
+    /** Destructor which unallocates connection to Lucene.
+     */
+    public void destroy()
+        throws IOException
+    {
+        index_modifier.close();
+        index_modifier = null;
+    }
+
+    /** Make an edit to a Lucene index.
+     *
+     *  @param  oid       The unique identifier of a Lucene document as an
+     *                    integer
+     *  @param  field     The field to be modified as a String
+     *  @param  old_value The existing value to be changed or removed as a 
+     *                    String
+     *  @param  old_value The replacement value to be changed or added as a 
+     *                    String
+     *
+     *  @author John Thompson, DL Consulting Ltd.
+     */
+    public void editIndex(int node_id, String field, String old_value, String new_value)
+        throws IOException
+    {
+        debug("GS2LuceneEditor.editIndex(" + node_id + ",'" + field + "','" + old_value + "','" + new_value + "')");
+        debug("- Initial number of documents in index: " + index_modifier.docCount());
+        // Retrieve the document requested
+        int doc_num = index_modifier.getDocNumByNodeID(node_id);
+        if (doc_num != -1)
+            {
+                debug("* Found document #" + doc_num);
+                // Retrieve the actual document
+                Document document = index_modifier.document(doc_num);
+                // Remove the document from the index before modifying
+                index_modifier.deleteDocument(doc_num);
+                debug("* Removed document from index prior to editing");
+                // Retrieve the requested fields values, and turn it into a 
+                // vector
+                debug("* Modifying the value of the field: " + field);
+                doEdit(document, field, old_value, new_value);
+
+                // We have to do a similar modification to the ZZ field
+                // too
+                debug("* Modifying the value of the field: ZZ");
+                doEdit(document, "ZZ", old_value, new_value);
+
+                // Re-index document
+                index_modifier.addDocument(document);
+                debug("* Reindexing modified document");
+            }
+        else
+            {
+                debug("- No such document!");
+                Document document = new Document();
+
+                // Retrieve the requested fields values, and turn it into a 
+                // vector
+                debug("* Adding the value to the field: " + field);
+                doEdit(document, field, old_value, new_value);
+
+                // We have to do a similar modification to the ZZ field
+                // too
+                debug("* Adding the value to the field: ZZ");
+                doEdit(document, "ZZ", old_value, new_value);
+
+                // We also have to initialize the nodeId value
+                document.add(new Field("nodeID", String.valueOf(node_id), Field.Store.YES, Field.Index.TOKENIZED));
+
+                // Re-index document
+                index_modifier.addDocument(document);
+                debug("* Indexing new document");
+            }
+
+
+    }
+    /** editIndex() **/
+
+    /**
+     */
+    protected void doEdit(Document document, String field, String old_value, String new_value)
+    {
+        if (debug)
+            {
+                debug("GS2LuceneEditor.doEdit(Document, \"" + field + "\", \"" + old_value + "\", \"" + new_value + "\")");
+            }
+
+        String values_raw[] = document.getValues(field);
+        if(values_raw != null)
+            {
+                Vector values = new Vector(Arrays.asList(values_raw));
+                // Remove all the values for this field (no other safe way to
+                // do this
+                document.removeFields(field);
+                // DEBUG
+                if (debug)
+                    {
+                        debug("- Before modification:");
+                        for(int i = 0; i < values.size(); i++)
+                            {
+                                debug("\t" + field + "[" + i + "]: " + values.get(i));
+                            }
+                    }
+                // If old_value is set, remove it from the values array
+                if(!old_value.equals(""))
+                    {
+                        // Remove all occurances of this metadata - this means
+                        // it becomes a bit dangerous to have multiple pieces
+                        // of metadata with exactly the same metadata - but
+                        // this is only for indexing purposes so its not so
+                        // bad.
+                        while(values.contains(old_value))
+                            {
+                                values.remove(old_value);
+                            }
+                    }                
+                // If new_value is set, add it to the values array
+                if(!new_value.equals("") && !values.contains(new_value))
+                    {
+                        values.add(new_value);
+                    }
+                // DEBUG
+                if(debug)
+                    {
+                        debug("- After modification:");
+                        for(int i = 0; i < values.size(); i++)
+                            {
+                                debug("\t" + field + "[" + i + "]: " + values.get(i));
+                            }
+                    }
+                // Add all the values for this field
+                for(int i = 0; i < values.size(); i++)
+                    {
+                        document.add(new Field(field, (String)values.get(i), Field.Store.YES, Field.Index.TOKENIZED));
+                    }
+                values.clear();
+                values = null;
+            }
+        // We may be adding a value to a field that current has no values
+        else if (!new_value.equals(""))
+            {
+                Vector values = new Vector();
+                values.add(new_value);
+                // DEBUG
+                if(debug)
+                    {
+                        debug("- Brand spanking new values:");
+                        for(int i = 0; i < values.size(); i++)
+                            {
+                                debug("\t" + field + "[" + i + "]: " + values.get(i));
+                            }
+                    }
+                // Add all the values for this field
+                for(int i = 0; i < values.size(); i++)
+                    {
+                        document.add(new Field(field, (String)values.get(i), Field.Store.YES, Field.Index.TOKENIZED));
+                    }
+                values.clear();
+                values = null;
+            }
+        // Can't do a removal unless something exists
+        else
+            {
+                debug("- No such field for this document: " + field);
+            }
+        values_raw = null;
+    }
+    /** doEdit() **/
+
+    /**
+     */
+    static public void printUsage()
+    {
+        System.out.println("usage: GS2LuceneEditor --index <path> --nodeid <int> --field <string>");
+        System.out.println("                      [--oldvalue <string>] [--newvalue <string>]");
+        System.out.println("");
+        System.out.println("where:");
+        System.out.println("  index    - is the full path to the directory containing the directory");
+        System.out.println("             to edit, including the level (ie didx, sidx)");
+        System.out.println("  nodeid   - the unique identifier of the document to change. This is the");
+        System.out.println("             same as the docnum in the GDBM");
+        System.out.println("  field    - the two letter code of the metadata field to edit. These can");
+        System.out.println("             found in the build.cfg file. ZZ is not a valid field as it");
+        System.out.println("             is handled as a special case");
+        System.out.println("  oldvalue - the current value of the metadata field if it is to be");
+        System.out.println("             replaced or removed");
+        System.out.println("  newvalue - the new value for the metadata field if it is to be replaced");
+        System.out.println("             or added");
+        System.out.println("");
+        System.exit(0);
+    }
+    /** printUsage() **/
+
+}
+/** class GS2LuceneEditor **/
Index: /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/GS2LuceneIndexer.java
===================================================================
--- /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/GS2LuceneIndexer.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/GS2LuceneIndexer.java	(revision 13928)
@@ -0,0 +1,127 @@
+/**********************************************************************
+ *
+ * GS2LuceneIndexer.java 
+ *
+ * Copyright 2004 The New Zealand Digital Library Project
+ *
+ * A component of the Greenstone digital library software
+ * from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *********************************************************************/
+
+package org.greenstone.LuceneWrapper;
+
+
+import java.io.*;
+import java.util.Vector;
+
+/**
+ * class for indexing XML generated by lucenebuildproc.pm
+  */
+
+public class GS2LuceneIndexer {
+
+    public static void main (String args[]) throws Exception 
+    { 
+
+	int verbosity = 1;
+	boolean create = false;
+
+	Vector filtered_args = new Vector();
+
+	int argc = args.length;
+	int i = 0;
+	while (i<argc) {
+	    if (args[i].startsWith("-")) {
+
+		// -create causes build to be incremental
+		if (args[i].equals("-create")) {
+		    create = true;
+		}
+
+		// -verbosity [num]
+		else if (args[i].equals("-verbosity")) {
+		    i++;
+		    if (i<argc) {
+			verbosity = Integer.parseInt(args[i]);
+		    }
+		}
+		else {
+		    System.out.println("Unrecognised option: " + args[i]);
+		}
+	    }
+	    else {
+		filtered_args.add((Object)args[i]);
+	    }
+	    i++;
+	}
+
+	if (filtered_args.size() != 3) {
+	    System.out.println("Usage: java GS2LuceneIndexer [-create|-verbosity [num]] doc-tag-level building_dir index");
+	    return;
+	}
+ 
+	String doc_tag_level     = (String)filtered_args.get(0);
+	String building_dirname  = (String)filtered_args.get(1);
+	String index_dirname     = (String)filtered_args.get(2);
+
+	String import_dirname = building_dirname + File.separator + "text";
+
+	File import_dir   = new File(import_dirname);
+	File building_dir = new File(building_dirname);
+
+	if (!import_dir.exists()) {
+	    System.out.println("Couldn't find import directory: "+import_dirname);
+	    return;
+	}
+
+	File idx_dir = new File(building_dir.getPath()+File.separator+index_dirname+File.separator);
+	idx_dir.mkdir();
+	
+	// Set up indexer
+	IndexXML indexer = new IndexXML(doc_tag_level,idx_dir, create);
+	indexer.init();	
+
+	// Read from stdin the files to process
+	try {
+	    InputStreamReader isr = new InputStreamReader(System.in, "UTF-8");
+	    BufferedReader brin = new BufferedReader(isr);
+
+	    StringBuffer xml_text = new StringBuffer(1024);
+	    String line = null;
+	    while ((line = brin.readLine()) != null) {
+		xml_text.append(line);
+		if (line.startsWith("</Doc>")) {
+		    indexer.indexFile(xml_text.toString());
+		    xml_text = new StringBuffer(1024);
+		}
+		//File xml_file = new File(import_dir + File.separator + line);
+		//indexer.indexFile(xml_file); // ****
+	    }
+
+	    brin.close();
+	    isr.close();
+
+	} catch (IOException e) {
+	    System.err.println("Error: unable to read from stdin");
+	    e.printStackTrace();
+	}
+
+	indexer.finish();
+    }
+}
Index: /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/GS2LuceneQuery.java
===================================================================
--- /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/GS2LuceneQuery.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/GS2LuceneQuery.java	(revision 13928)
@@ -0,0 +1,599 @@
+/**********************************************************************
+ *
+ * GS2LuceneQuery.java 
+ *
+ * Copyright 2004 The New Zealand Digital Library Project
+ *
+ * A component of the Greenstone digital library software
+ * from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *********************************************************************/
+package org.greenstone.LuceneWrapper;
+
+
+import java.io.*;
+import java.util.*;
+import java.util.regex.*;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.index.TermDocs;
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.search.BooleanQuery.TooManyClauses;
+import org.apache.lucene.search.Filter;
+import org.apache.lucene.search.Hit;
+import org.apache.lucene.search.Hits;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.RangeFilter;
+import org.apache.lucene.search.Searcher;
+import org.apache.lucene.search.ScoreDoc;
+import org.apache.lucene.search.Sort;
+import org.apache.lucene.search.TopFieldDocs;
+
+
+public class GS2LuceneQuery
+{
+
+
+    static private String TEXTFIELD = "TX";
+
+    // Use the standard set of English stop words by default
+    static private String[] stop_words = StandardAnalyzer.STOP_WORDS;
+
+    private String full_indexdir="";
+    private String default_conjunction_operator = "OR";
+    private String fuzziness = null;
+    private String sort_field = null;
+    private Sort sorter=new Sort();
+    private String filter_string = null;
+    private Filter filter = null;
+    private int start_results=1;
+    private int end_results=Integer.MAX_VALUE;
+
+    private QueryParser query_parser = null;
+    private QueryParser query_parser_no_stop_words = null;
+    private Searcher searcher = null;
+    private IndexReader reader = null;
+    
+    public GS2LuceneQuery() {
+
+	// Create one query parser with the standard set of stop words, and one with none
+
+	query_parser = new QueryParser(TEXTFIELD, new StandardAnalyzer(stop_words));
+    	query_parser_no_stop_words = new QueryParser(TEXTFIELD, new StandardAnalyzer(new String[] { }));
+    }
+    
+    
+    public boolean initialise() {
+
+    	if (full_indexdir==null || full_indexdir.length()==-1){
+	    System.out.println("Index directory is not indicated ");
+	    return false;
+    	}
+        try {
+    	    searcher = new IndexSearcher(full_indexdir);
+    	    reader = ((IndexSearcher) searcher).getIndexReader();
+	    
+	}
+	catch (IOException exception) {
+    	    exception.printStackTrace();
+	    return false;
+    	}
+	return true;
+
+    }
+    
+    public LuceneQueryResult runQuery(String query_string) {
+	
+	if (query_string == null || query_string.equals("")) {
+	    System.out.println("The query word is not indicated ");
+	    return null;
+	}
+
+ 	LuceneQueryResult lucene_query_result=new LuceneQueryResult();
+	lucene_query_result.clear();
+	    
+	try {    	        
+	    Query query_including_stop_words = query_parser_no_stop_words.parse(query_string);
+	    query_including_stop_words = query_including_stop_words.rewrite(reader);
+		
+	    Query query = parseQuery(reader, query_parser, query_string, fuzziness);
+	    query = query.rewrite(reader);
+		
+	    // Get the list of expanded query terms and their frequencies 
+	    // num docs matching, and total frequency	    
+	    HashSet terms = new HashSet();
+	    query.extractTerms(terms);
+	    
+	    Iterator iter = terms.iterator();
+	    while (iter.hasNext()) {
+		    
+		Term term = (Term) iter.next();
+		
+		// Get the term frequency over all the documents
+		TermDocs term_docs = reader.termDocs(term);
+		int term_freq = term_docs.freq();
+		int match_docs = 0;
+		if (term_freq != 0) match_docs++;
+		while (term_docs.next()) {
+		    term_freq += term_docs.freq();
+		    if (term_docs.freq()!= 0) {
+			match_docs++;
+		    }
+		}
+
+		// Create a term 
+		lucene_query_result.addTerm(term.text(), term.field(), match_docs, term_freq);
+	    }
+	
+	    // Get the list of stop words removed from the query
+	    HashSet terms_including_stop_words = new HashSet();
+	    query_including_stop_words.extractTerms(terms_including_stop_words);
+	    Iterator terms_including_stop_words_iter = terms_including_stop_words.iterator();
+	    while (terms_including_stop_words_iter.hasNext()) {
+		Term term = (Term) terms_including_stop_words_iter.next();
+		if (!terms.contains(term)) {
+		    lucene_query_result.addStopWord(term.text());
+		}
+	    }
+	    
+	    // do the query
+	    // Simple case for getting all the matching documents
+	    if (end_results == Integer.MAX_VALUE) {
+		// Perform the query (filter and sorter may be null)
+		Hits hits = searcher.search(query, filter, sorter);
+		lucene_query_result.setTotalDocs(hits.length());
+
+		// Output the matching documents
+		lucene_query_result.setStartResults(start_results);
+		lucene_query_result.setEndResults(hits.length());
+
+		for (int i = start_results; i <= hits.length(); i++) {
+		    Document doc = hits.doc(i - 1);
+		    lucene_query_result.addDoc(Long.parseLong(doc.get("nodeID").trim()), hits.score(i-1));
+		}
+	    }
+
+	    // Slightly more complicated case for returning a subset of the matching documents
+	    else {
+		// Perform the query (filter may be null)
+		TopFieldDocs hits = searcher.search(query, filter, end_results, sorter);
+		lucene_query_result.setTotalDocs(hits.totalHits);
+		
+		lucene_query_result.setStartResults(start_results);
+		lucene_query_result.setEndResults(end_results < hits.scoreDocs.length ? end_results: hits.scoreDocs.length);
+
+		// Output the matching documents
+		for (int i = start_results; (i <= hits.scoreDocs.length && i <= end_results); i++) {
+		    Document doc = reader.document(hits.scoreDocs[i - 1].doc);
+		    lucene_query_result.addDoc(Long.parseLong(doc.get("nodeID").trim()), hits.scoreDocs[i-1].score);
+		}
+	    }
+	}
+	
+	catch (ParseException parse_exception) {
+	    lucene_query_result.setError(LuceneQueryResult.PARSE_ERROR);
+	}
+	catch (TooManyClauses too_many_clauses_exception) {
+	    lucene_query_result.setError(LuceneQueryResult.TOO_MANY_CLAUSES_ERROR);
+	}
+	catch (IOException exception) {
+	    lucene_query_result.setError(LuceneQueryResult.IO_ERROR);
+	    exception.printStackTrace();
+	}
+	catch (Exception exception) {
+	    lucene_query_result.setError(LuceneQueryResult.OTHER_ERROR);
+	    exception.printStackTrace();
+	}
+	return lucene_query_result;
+    }
+
+    public void setDefaultConjunctionOperator(String default_conjunction_operator) {
+	this.default_conjunction_operator = default_conjunction_operator.toUpperCase();
+	if (default_conjunction_operator == "AND") {
+	    query_parser.setDefaultOperator(query_parser.AND_OPERATOR);
+	    query_parser_no_stop_words.setDefaultOperator(query_parser.AND_OPERATOR);
+	} else { // default is OR
+	    query_parser.setDefaultOperator(query_parser.OR_OPERATOR);
+	    query_parser_no_stop_words.setDefaultOperator(query_parser.OR_OPERATOR);
+	}
+    }
+    
+    public String getDefaultConjunctionOperator() {
+	return this.default_conjunction_operator;
+    }
+    
+    public void setEndResults(int end_results) {
+	this.end_results = end_results;
+    }
+    public int getEndResults() {
+	return this.end_results;
+    }
+        
+    public void setFilterString(String filter_string) {
+	this.filter_string = filter_string;
+	this.filter = parseFilterString(filter_string);
+    }
+    public String getFilterString() {
+	return this.filter_string ;
+    }
+    
+    public Filter getFilter() {
+	return this.filter;
+    }
+
+    public void setIndexDir(String full_indexdir) {
+	this.full_indexdir = full_indexdir;
+    }
+    
+    public void setFuzziness(String fuzziness) {
+	this.fuzziness = fuzziness;
+    }
+    public String getFuzziness() {
+	return this.fuzziness;
+    }
+    
+    public void setSortField(String sort_field) {
+	this.sort_field = sort_field;
+	if (sort_field == null) {
+	    this.sorter = new Sort();
+	} else {
+	    this.sorter = new Sort(sort_field);
+	}
+    }
+    public String getSortField() {
+	return this.sort_field;
+    }
+        
+    public void setStartResults(int start_results) {
+	if (start_results < 1) {
+	    start_results = 1;
+	}
+	this.start_results = start_results;
+    }
+    public int getStartResults() {
+	return this.start_results;
+    }
+        
+    public void cleanUp() {
+	try {
+	    if (searcher != null) {
+		searcher.close();
+	    }
+	} catch (IOException exception) {
+	    exception.printStackTrace();
+	}
+    }
+
+    private Query parseQuery(IndexReader reader, QueryParser query_parser, String query_string, String fuzziness)
+	throws java.io.IOException, org.apache.lucene.queryParser.ParseException
+    {
+	// Split query string into the search terms and the filter terms
+	// * The first +(...) term contains the search terms so count
+	//   up '(' and stop when we finish matching ')'
+	int offset = 0;
+	int paren_count = 0;
+	boolean seen_paren = false;
+	while (offset < query_string.length() && (!seen_paren || paren_count > 0)) {
+	    if (query_string.charAt(offset) == '(') {
+		paren_count++;
+		seen_paren = true;
+	    }
+	    if (query_string.charAt(offset) == ')') {
+		paren_count--;
+	    }
+	    offset++;
+	}
+	String query_prefix = query_string.substring(0, offset);
+	String query_suffix = query_string.substring(offset);
+	
+	///ystem.err.println("Prefix: " + query_prefix);
+	///ystem.err.println("Suffix: " + query_suffix);
+	
+	Query query = query_parser.parse(query_prefix);
+	query = query.rewrite(reader);
+	
+	// If this is a fuzzy search, then we need to add the fuzzy
+	// flag to each of the query terms
+	if (fuzziness != null && query.toString().length() > 0) {
+	    
+	    // Revert the query to a string
+	    System.err.println("Rewritten query: " + query.toString());
+	    // Search through the string for TX:<term> query terms
+	    // and append the ~ operator. Note that this search will
+	    // not change phrase searches (TX:"<term> <term>") as
+	    // fuzzy searching is not possible for these entries.
+	    // Yahoo! Time for a state machine!
+	    StringBuffer mutable_query_string = new StringBuffer(query.toString());
+	    int o = 0; // Offset
+	    // 0 = BASE, 1 = SEEN_T, 2 = SEEN_TX, 3 = SEEN_TX:
+	    int s = 0; // State
+	    while(o < mutable_query_string.length()) {
+		char c = mutable_query_string.charAt(o);
+		if (s == 0 && c == TEXTFIELD.charAt(0)) {
+		    ///ystem.err.println("Found T!");
+		    s = 1;
+		}
+		else if (s == 1) {
+		    if (c == TEXTFIELD.charAt(1)) {
+			///ystem.err.println("Found X!");
+			s = 2;
+		    }
+		    else {
+			s = 0; // Reset
+		    }
+		}
+		else if (s == 2) {
+		    if (c == ':') {
+			///ystem.err.println("Found TX:!");
+			s = 3;
+		    }
+		    else {
+			s = 0; // Reset
+		    }
+		}
+		else if (s == 3) {
+		    // Don't process phrases
+		    if (c == '"') {
+			///ystem.err.println("Stupid phrase...");
+			s = 0; // Reset
+		    }
+		    // Found the end of the term... add the
+		    // fuzzy search indicator
+		    // Nor outside the scope of parentheses
+		    else if (Character.isWhitespace(c) || c == ')') {
+			///ystem.err.println("Yahoo! Found fuzzy term.");
+			mutable_query_string.insert(o, '~' + fuzziness);
+			o++;
+			s = 0; // Reset
+		    }
+		}
+		o++;
+	    }
+	    // If we were in the state of looking for the end of a
+	    // term - then we just found it!
+	    if (s == 3) {
+		    
+		mutable_query_string.append('~' + fuzziness);
+	    }
+	    // Reparse the query
+	    ///ystem.err.println("Fuzzy query: " + mutable_query_string.toString() + query_suffix);
+	    query = query_parser.parse(mutable_query_string.toString() + query_suffix);
+	}
+	else {
+	    query = query_parser.parse(query_prefix + query_suffix);
+	}
+	
+	return query;
+    }
+
+    private Filter parseFilterString(String filter_string)
+    {
+	Filter result = null;
+	Pattern pattern = Pattern.compile("\\s*\\+(\\w+)\\:([\\{\\[])(\\d+)\\s+TO\\s+(\\d+)([\\}\\]])\\s*");
+	Matcher matcher = pattern.matcher(filter_string);
+	if (matcher.matches()) {
+	    String field_name = matcher.group(1);
+	    boolean include_lower = matcher.group(2).equals("[");
+	    String lower_term = matcher.group(3);
+	    String upper_term = matcher.group(4);
+	    boolean include_upper = matcher.group(5).equals("]");
+	    result = new RangeFilter(field_name, lower_term, upper_term, include_lower, include_upper);
+	}
+	else {
+	    System.err.println("Error: Could not understand filter string \"" + filter_string + "\"");
+	}
+	return result;
+    }
+
+    
+    /** command line program and auxiliary methods */
+
+    // Fairly self-explanatory I should hope
+    static private boolean query_result_caching_enabled = false;
+
+    static public void main (String args[])
+    {
+	if (args.length == 0) {
+	    System.out.println("Usage: GS2LuceneQuery <index directory> [-fuzziness value] [-filter filter_string] [-sort sort_field] [-dco AND|OR] [-startresults number -endresults number] [query]");
+	    return;
+	}
+
+	try {
+	    String index_directory = args[0];
+	    
+	    GS2LuceneQuery queryer = new GS2LuceneQuery();
+	    queryer.setIndexDir(index_directory);
+
+	    // Prepare the index cache directory, if query result caching is enabled
+	    if (query_result_caching_enabled) {
+		// Make the index cache directory if it doesn't already exist
+		File index_cache_directory = new File(index_directory, "cache");
+		if (!index_cache_directory.exists()) {
+		    index_cache_directory.mkdir();
+		}
+
+		// Disable caching if the index cache directory isn't available
+		if (!index_cache_directory.exists() || !index_cache_directory.isDirectory()) {
+		    query_result_caching_enabled = false;
+		}
+	    }
+
+	    String query_string = null;
+
+	    // Parse the command-line arguments
+            for (int i = 1; i < args.length; i++) {
+		if (args[i].equals("-sort")) {
+		    i++;
+		    queryer.setSortField(args[i]);
+		}
+		else if (args[i].equals("-filter")) {
+		    i++;
+		    queryer.setFilterString(args[i]);
+		}
+		else if (args[i].equals("-dco")) {
+		    i++;
+		    queryer.setDefaultConjunctionOperator(args[i]);
+		}
+		else if (args[i].equals("-fuzziness")) {
+		    i++;
+		    queryer.setFuzziness(args[i]);
+		}
+		else if (args[i].equals("-startresults")) {
+		    i++;
+		    if (args[i].matches("\\d+")) {
+			queryer.setStartResults(Integer.parseInt(args[i]));
+		    }
+		}
+		else if (args[i].equals("-endresults")) {
+		    i++;
+		    if (args[i].matches("\\d+")) {
+			queryer.setEndResults(Integer.parseInt(args[i]));
+		    }
+		}
+		else {
+		    query_string = args[i];
+		}
+	    }
+	    
+	    if (!queryer.initialise()) {
+		return;
+	    }
+	    
+	    // The query string has been specified as a command-line argument
+	    if (query_string != null) {
+		runQueryCaching(index_directory, queryer, query_string);
+	    }
+
+	    // Read queries from STDIN
+	    else {
+		BufferedReader in = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
+		while (true) {
+		    // Read the query from STDIN
+		    query_string = in.readLine();
+		    if (query_string == null || query_string.length() == -1) {
+			break;
+		    }
+		    runQueryCaching(index_directory, queryer, query_string);
+		    
+		}
+	    }
+	    queryer.cleanUp();
+	}
+ 	catch (IOException exception) {
+ 	    exception.printStackTrace();
+ 	}
+    }
+
+    private static void runQueryCaching(String index_directory, GS2LuceneQuery queryer, String query_string) 
+	throws IOException
+    {
+	StringBuffer query_results_xml = new StringBuffer();
+
+	// Check if this query result has been cached from a previous search (if it's enabled)
+	File query_result_cache_file = null;
+	if (query_result_caching_enabled) {
+	    // Generate the cache file name from the query options
+	    String query_result_cache_file_name = query_string + "-";
+	    String fuzziness = queryer.getFuzziness();
+	    query_result_cache_file_name += ((fuzziness != null) ? fuzziness : "") + "-";
+	    String filter_string = queryer.getFilterString();
+	    query_result_cache_file_name += ((filter_string != null) ? filter_string : "") + "-";
+	    String sort_string = queryer.getSortField();
+	    query_result_cache_file_name += ((sort_string != null) ? sort_string : "") + "-";
+	    String default_conjunction_operator = queryer.getDefaultConjunctionOperator();
+	    query_result_cache_file_name += default_conjunction_operator + "-";
+	    int start_results = queryer.getStartResults();
+	    int end_results = queryer.getEndResults();
+	    query_result_cache_file_name += start_results + "-" + end_results;
+	    query_result_cache_file_name = fileSafe(query_result_cache_file_name);
+
+	    // If the query result cache file exists, just return its contents and we're done
+	    File index_cache_directory = new File(index_directory, "cache");
+	    query_result_cache_file = new File(index_cache_directory, query_result_cache_file_name);
+	    if (query_result_cache_file.exists() && query_result_cache_file.isFile()) {
+		FileInputStream fis = new FileInputStream(query_result_cache_file);
+		InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
+		BufferedReader buffered_reader = new BufferedReader(isr);
+		String line = "";
+		while ((line = buffered_reader.readLine()) != null) {
+		    query_results_xml.append(line + "\n");
+		}
+		String query_results_xml_string = query_results_xml.toString();
+		query_results_xml_string = query_results_xml_string.replaceFirst("cached=\"false\"", "cached=\"true\"");
+		System.out.print(query_results_xml_string);
+		return;
+	    }
+	}
+	
+	// not cached
+	query_results_xml.append("<ResultSet cached=\"false\">\n");
+	query_results_xml.append("<QueryString>" + LuceneQueryResult.xmlSafe(query_string) + "</QueryString>\n");
+	Filter filter = queryer.getFilter();
+	if (filter != null) {
+	    query_results_xml.append("<FilterString>" + filter.toString() + "</FilterString>\n");
+	}
+	
+	LuceneQueryResult query_result = queryer.runQuery(query_string);
+	if (query_result == null) {
+	    System.err.println("Couldn't run the query");
+	    return;
+	}
+	
+	if (query_result.getError() != LuceneQueryResult.NO_ERROR) {
+	    query_results_xml.append("<Error type=\""+query_result.getErrorString()+"\" />\n");
+	} else {
+	    query_results_xml.append(query_result.getXMLString());
+	}
+	query_results_xml.append("</ResultSet>\n");
+
+	System.out.print(query_results_xml);
+
+	// Cache this query result, if desired
+	if (query_result_caching_enabled) {
+	    FileWriter query_result_cache_file_writer = new FileWriter(query_result_cache_file);
+	    query_result_cache_file_writer.write(query_results_xml.toString());
+	    query_result_cache_file_writer.close();
+	}
+    }
+    
+    private static String fileSafe(String text)
+    {
+	StringBuffer file_safe_text = new StringBuffer();
+	for (int i = 0; i < text.length(); i++) {
+	    char character = text.charAt(i);
+	    if ((character >= 'A' && character <= 'Z') || (character >= 'a' && character <= 'z') || (character >= '0' && character <= '9') || character == '-') {
+		file_safe_text.append(character);
+	    }
+	    else {
+		file_safe_text.append('%');
+		file_safe_text.append((int) character);
+	    }
+	}
+	return file_safe_text.toString();
+    }
+
+    
+}
+
+
Index: /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/IndexXML.java
===================================================================
--- /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/IndexXML.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/IndexXML.java	(revision 13928)
@@ -0,0 +1,68 @@
+/**********************************************************************
+ *
+ * IndexXML.java 
+ *
+ * Copyright 2004 The New Zealand Digital Library Project
+ *
+ * A component of the Greenstone digital library software
+ * from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *********************************************************************/
+package org.greenstone.LuceneWrapper;
+
+
+import java.io.File;
+
+public class IndexXML extends Object {
+
+    String doc_tag_level_ = null;
+    File out_dir_         = null;
+    Indexer indexer_      = null;
+    boolean create_index_ = false;
+
+    public IndexXML(String doc_tag_level, File out_dir, boolean create)
+    {
+	doc_tag_level_ = doc_tag_level;
+	out_dir_ = out_dir;
+	create_index_ = create;
+    }
+
+    public void init() 
+    {
+	indexer_ = new Indexer(doc_tag_level_, out_dir_, create_index_);
+    }
+
+    public void finish() 
+    {
+	indexer_.finish();
+    }
+
+    public void indexFile(File file) 
+    {
+	String name = file.getName();
+	name = name.substring(0, name.lastIndexOf('.'));
+	System.out.println("Indexing "+file.getPath()+" with id "+name);
+	indexer_.index(name, file);
+    }    
+
+    public void indexFile(String xml_text) 
+    {
+	indexer_.index(xml_text);
+    }    
+
+}
Index: /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/Indexer.java
===================================================================
--- /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/Indexer.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/Indexer.java	(revision 13928)
@@ -0,0 +1,284 @@
+/**********************************************************************
+ *
+ * Indexer.java 
+ *
+ * Copyright 2004 The New Zealand Digital Library Project
+ *
+ * A component of the Greenstone digital library software
+ * from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *********************************************************************/
+package org.greenstone.LuceneWrapper;
+
+
+import org.xml.sax.Attributes;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+
+import java.util.Stack;
+import java.io.FileInputStream;
+import java.io.File;
+import java.io.StringReader;
+import java.net.URL;
+
+
+
+public class Indexer extends DefaultHandler 
+{
+    IndexWriter writer_   = null;
+    SAXParser sax_parser_ = null;
+    String doc_tag_level_ = null;
+
+    Stack stack_ = null;
+    String path_ = "";
+
+    Document current_doc_ = null;
+    String current_node_ = "";
+    String indexable_current_node_ = "";
+    String current_contents_ = "";
+
+    protected String file_id_ = null;
+
+    /** pass in true if want to create a new index, false if want to use the existing one */
+    public Indexer (String doc_tag_level, File index_dir, boolean create) 
+    {
+	doc_tag_level_ = doc_tag_level;
+
+	try {
+	    stack_ = new Stack();
+	    SAXParserFactory sax_factory = SAXParserFactory.newInstance();
+	    sax_parser_ = sax_factory.newSAXParser();
+
+	    XMLReader reader = sax_parser_.getXMLReader(); 
+	    reader.setFeature("http://xml.org/sax/features/validation", false);
+
+	    writer_ = new IndexWriter(index_dir.getPath(), new StandardAnalyzer(), create);
+	    // by default, will only index 10,000 words per document
+	    // Can throw out_of_memory errors
+	    writer_.setMaxFieldLength(Integer.MAX_VALUE);
+	    if (create) {
+		writer_.optimize();
+	    }
+
+	} catch (Exception e) {
+	    // do nothing!
+	}
+    }
+
+    /** index one document */
+    public void index (String file_id, File file) 
+    {
+	file_id_ = file_id;
+	path_ = "";
+	String base_path = file.getPath();
+	base_path = base_path.substring(0, base_path.lastIndexOf(File.separatorChar));
+
+	try {	    
+            sax_parser_.parse(new InputSource(new FileInputStream(file)), this);
+        }
+        catch (Exception e) {
+	    println("parse error:");
+            e.printStackTrace();
+	}
+    }
+
+    /** index one document stored as string*/
+    public void index (String xml_text) 
+    {
+	file_id_ = "<xml doc on stdin>";
+	path_ = "";
+
+	try {
+            sax_parser_.parse(new InputSource(new StringReader(xml_text)), this);
+        }
+        catch (Exception e) {
+	    println("parse error:");
+            e.printStackTrace();
+	}
+    }
+    
+    public void finish() 
+    {
+	/** optimise the index */
+	try {
+	    writer_.optimize();
+	    writer_.close();
+	} 
+	catch (Exception e) {
+	}
+    }
+
+    protected void print(String s) 
+    { 
+	System.out.print(s); 
+    }
+
+    protected void println(String s) 
+    { 
+	System.out.println(s); 
+    }
+
+    public void startDocument() throws SAXException 
+    {
+        println("Starting to index " + file_id_);
+        print("[");
+    }
+
+    public void endDocument() throws SAXException 
+    {
+        println("]");
+        println("... indexing finished.");
+    }
+
+    public void startElement(String uri, String localName, String qName, Attributes atts) 
+	throws SAXException 
+    {
+	path_ = appendPathLink(path_, qName, atts);
+
+	if (qName.equals(doc_tag_level_)) {
+	    pushOnStack(); // start new doc
+	    current_node_ = qName;
+	    String node_id = atts.getValue("gs2:id");
+
+	    print(" " + qName + ": " + node_id );
+	    current_doc_.add(new Field("nodeID", node_id, Field.Store.YES, Field.Index.NO));
+	}
+
+	if (XMLTagInfo.isIndexable(atts)) {
+	    indexable_current_node_ = qName;	
+	}
+	else {
+	    indexable_current_node_ = "";
+	}
+
+    }
+    public void endElement(String uri, String localName, String qName) throws SAXException 
+    {
+	if (qName.equals(indexable_current_node_))
+            {
+                current_doc_.add(new Field(qName, current_contents_, Field.Store.NO, Field.Index.TOKENIZED, Field.TermVector.YES));
+                // We only need the term vector for the TX field
+                if (!qName.equals("TX"))
+                    {
+                        current_doc_.add(new Field("by" + qName, current_contents_, Field.Store.NO, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
+                    }
+
+                current_contents_ = "";
+            }
+
+	if (qName.equals(doc_tag_level_)) {
+	    try {
+		writer_.addDocument(current_doc_);
+	    } 
+	    catch (java.io.IOException e) {
+		e.printStackTrace();
+	    }
+	    popOffStack(); // end document
+	}
+	
+	path_ = removePathLink(path_);
+    }
+
+    public void characters(char ch[], int start, int length) throws SAXException 
+    {
+	String data = new String(ch, start, length).trim();
+	if (data.length() > 0 ) {
+	    current_contents_ += data;
+	}
+    }
+    
+    protected String appendPathLink(String path, String qName, Attributes atts) 
+    {
+
+	path = path + "/"+qName;
+	if (atts.getLength()>0) {
+	    String id = atts.getValue("gs2:id");
+	    if (id != null) {
+		path +=  "[@gs2:id='"+id+"']";
+	    }
+	    else {
+		id = atts.getValue("gs3:id");
+		if (id != null) {
+		    path +=  "[@gs3:id='"+id+"']";
+		}
+	    }
+	}
+	return path;
+    }
+    protected String  removePathLink(String path) 
+    {
+
+	int i=path.lastIndexOf('/');
+	if (i==-1) {
+	    path="";
+	} else {
+	    path = path.substring(0, i);
+	}
+	return path;
+    }
+    /** these are what we save on the stack */
+    private class MyDocument 
+    {
+	public Document doc = null;
+	public String contents = null;
+	public String tagname = "";
+	
+    }
+
+    protected void pushOnStack() 
+    {
+	if (current_doc_ != null) {
+	    MyDocument save = new MyDocument();
+	    save.doc = current_doc_;
+	    save.contents = current_contents_;
+	    save.tagname = current_node_;
+	    stack_.push(save);
+	}
+	current_doc_ = new Document();
+	current_contents_ = "";
+	current_node_ = "";
+    }
+
+    protected void popOffStack() 
+    {
+	if (!stack_.empty()) {
+	    MyDocument saved = (MyDocument)stack_.pop();
+	    current_doc_ = saved.doc;
+	    current_contents_ = saved.contents;
+	    current_node_ = saved.tagname;
+	} else {
+	    current_doc_ = new Document();
+	    current_contents_ = "";
+	    current_node_ = "";
+	}
+    }
+
+
+}
+
+
Index: /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/LuceneQueryResult.java
===================================================================
--- /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/LuceneQueryResult.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/LuceneQueryResult.java	(revision 13928)
@@ -0,0 +1,250 @@
+/**********************************************************************
+ *
+ * LuceneQueryResult.java 
+ *
+ * Copyright 2007 The New Zealand Digital Library Project
+ *
+ * A component of the Greenstone digital library software
+ * from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *********************************************************************/
+
+package org.greenstone.LuceneWrapper;
+
+import java.util.Vector;
+
+/** a QueryResult class for a lucene search
+ *
+ */
+public class LuceneQueryResult {
+    
+    public static final int NO_ERROR = 0;
+    public static final int PARSE_ERROR = 1;
+    public static final int TOO_MANY_CLAUSES_ERROR = 2;
+    public static final int IO_ERROR = 3;
+    public static final int OTHER_ERROR = 4;
+    
+    /** the list of DocInfo */
+    protected Vector docs_=null;
+    /** the list of TermInfo */
+    protected Vector terms_=null;
+    /** the list of stopwords found in the query */
+    protected Vector stopwords_ = null;
+    /** the total number of docs found - not necessarily the size of docs_*/
+    protected int total_num_docs_=0;
+    /** the start result number if we are retrieving only a portion of the results */
+    protected int start_results_ = 0;
+    /** the end result number if we are retrieving only a portion of the results */
+    protected int end_results_ = 0;
+    /** whether an error has occurred and what kind it is*/
+    protected int error_ = NO_ERROR;
+
+    LuceneQueryResult() {
+	docs_ = new Vector();
+	terms_ = new Vector();
+	stopwords_ = new Vector();
+    }
+    
+    /** clear the info from the last query - should be called before setting any new docs/terms */
+    public void clear() {
+	total_num_docs_=0;
+	docs_.clear();
+	terms_.clear();
+	stopwords_.clear();
+	error_ = NO_ERROR;
+    }
+
+    /** returns the result as a String - useful for printing out results */
+    public String toString() {
+	
+	String result = "";
+	result += "docs (ranks): ";
+	for (int i=0; i<docs_.size(); i++) {
+	    result += ((DocInfo)docs_.elementAt(i)).toString()+", ";
+	}
+	result += "\nterms: ";
+	for (int i=0; i<terms_.size(); i++) {
+	    result += ((TermInfo)terms_.elementAt(i)).toString()+", ";
+	}
+	result += "\nactual number of docs found = "+total_num_docs_;
+	
+	return result;
+    }
+    /** a shorter representation - just terms and total docs - not the 
+	individual docnums and ranks */
+    public String toShortString() {
+	String result = "";
+	result += "\nterms: ";
+	for (int i=0; i<terms_.size(); i++) {
+	    result += ((TermInfo)terms_.elementAt(i)).toString()+", ";
+	}
+	result += "\nactual number of docs found = "+total_num_docs_;
+	return result;
+    }
+    
+    public void setTotalDocs(int num) {
+	total_num_docs_=num;
+    }
+    
+    public void setStartResults(int start) {
+	start_results_ = start;
+    }
+
+    public void setEndResults(int end) {
+	end_results_ = end;
+    }
+
+    public void addDoc(long doc, float rank) {
+	DocInfo doc_info = new DocInfo(doc, rank);
+	docs_.add(doc_info);
+    }
+    
+    public void addTerm(String term, String field, int match, int freq) {
+	TermInfo ti = new TermInfo();
+	ti.term_=term;
+	ti.field_=field;
+	ti.match_docs_=match;
+	ti.term_freq_=freq;
+	terms_.add(ti);
+    }
+    public void addStopWord(String stopword) {
+	stopwords_.add(stopword);
+    }
+    public Vector getDocs() {
+	return docs_;
+    }
+    
+    public int getError() {
+	return error_;
+    }
+    
+    public String getErrorString() {
+	if (error_ == PARSE_ERROR) {
+	    return "PARSE_EXCEPTION";
+	}
+	if (error_ == TOO_MANY_CLAUSES_ERROR) {
+	    return "TOO_MANY_CLAUSES";
+	}
+	if (error_ == IO_ERROR) {
+	    return "IO_ERROR";
+	}
+	if (error_ == NO_ERROR) {
+	    return "NO_ERROR";
+	}
+	return "UNKNOWN";
+    }
+
+    public Vector getTerms() {
+	return terms_;
+    }
+    
+    public Vector getStopWords() {
+	return stopwords_;
+    }
+    public int getTotalDocs() {
+	return total_num_docs_;
+    }
+    
+    public void setError(int error) {
+	error_ = error;
+    }
+    
+    public String getXMLString() {
+	StringBuffer buffer = new StringBuffer();
+
+	// terms
+	buffer.append("<QueryTermsInfo num=\"" + terms_.size() + "\"/>\n");
+	for (int i=0; i<terms_.size(); i++) {
+	    buffer.append(((TermInfo)terms_.elementAt(i)).toXMLString()+"\n");
+	}
+
+	// stopwords
+	for (int i=0; i<stopwords_.size(); i++) {
+	    buffer.append("<StopWord value=\"" + (String)stopwords_.elementAt(i)+"\" />\n");
+	}
+	
+	// results
+	buffer.append("<MatchingDocsInfo num=\"" + total_num_docs_ + "\"/>\n");
+	buffer.append("<StartResults num=\"" + start_results_ + "\"/>\n");
+	buffer.append("<EndResults num=\"" + end_results_ + "\"/>\n");
+	
+	for (int i=0; i< docs_.size(); i++) {
+	    buffer.append(((DocInfo)docs_.elementAt(i)).toXMLString()+"\n");
+	}
+
+	return buffer.toString();
+    }
+
+ 
+    public class TermInfo {
+	
+	/** the term itself */
+	public String term_=null;
+	/** the field for which this term was queried */
+	public String field_=null;
+	/** the number of documents containing this term */
+	public int match_docs_=0;
+	/** overall term freq for this term */
+	public int term_freq_=0;
+	
+	public TermInfo() {
+	}
+	
+	/** output the class as a string */
+	public String toString() {
+	    String result="";
+	    result +="<"+field_+">\""+term_+" docs("+match_docs_;
+	    result +=")freq("+term_freq_+")";
+	    return result;
+	}
+
+	/** output as an XML element */
+	public String toXMLString() {
+	    return "<Term value=\"" + xmlSafe(term_) + "\" field=\"" + field_ + "\" freq=\"" + term_freq_ + "\" />";
+	}
+    }
+
+    public class DocInfo {
+	
+	public long num_=0;
+	public float rank_=0;
+	
+	public DocInfo(long doc, float rank) {
+	    num_=doc;
+	    rank_=rank;
+	}
+	public String toString(){
+	    return ""+num_+"("+rank_+")";
+	}
+	public String toXMLString() {
+	    return "<Match id=\"" + num_ + "\" rank=\"" + rank_ +"\" />";
+	}
+    }
+
+    // where should this go???
+    
+    public static String xmlSafe(String text) {
+	text = text.replaceAll("&","&amp;amp;");
+	text = text.replaceAll("<","&amp;lt;");
+	text = text.replaceAll(">","&amp;gt;");
+	text = text.replaceAll("'","&amp;#039;");
+	text = text.replaceAll("\\\"","&amp;quot;");
+	return text;
+    }
+ 
+}
Index: /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/XMLTagInfo.java
===================================================================
--- /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/XMLTagInfo.java	(revision 13928)
+++ /tags/greenstone-3_02-distribution/indexers/lucene-gs/src/org/greenstone/LuceneWrapper/XMLTagInfo.java	(revision 13928)
@@ -0,0 +1,62 @@
+/**********************************************************************
+ *
+ * XMLTagInfo.java 
+ *
+ * Copyright 2006 The New Zealand Digital Library Project
+ *
+ * A component of the Greenstone digital library software
+ * from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *********************************************************************/
+
+package org.greenstone.LuceneWrapper;
+
+
+import org.xml.sax.Attributes;
+
+/** XMLTagInfo
+ * contains any methods that are specific to what kind of XML you are working on
+ */
+
+public class XMLTagInfo {
+
+    public static boolean isDocumentLevel(Attributes atts) 
+    {
+	boolean is_doc_level = false;
+	String id = atts.getValue("gs2:id");
+	if (id!=null) {
+	    is_doc_level = true;
+	}
+	return is_doc_level;
+    }
+
+    public static boolean isIndexable(Attributes atts) 
+    {
+	boolean is_indexable = false;
+
+	String index = atts.getValue("index");
+	if (index!=null) {
+	    if (index.equals("1")) {
+		is_indexable = true;
+	    }
+	}
+	return is_indexable;
+    }
+
+    
+}
Index: /tags/greenstone-3_02-distribution/indexers/lucene-gs/winMake.bat
===================================================================
--- /tags/greenstone-3_02-distribution/indexers/lucene-gs/winMake.bat	(revision 13928)
+++ /tags/greenstone-3_02-distribution/indexers/lucene-gs/winMake.bat	(revision 13928)
@@ -0,0 +1,50 @@
+@echo off
+
+set LUCENEHOME=.
+
+rem ---- Where to put class files ----
+set JAVACLASSDIR=classes
+
+rem ---- Name and location of java programs ----
+set JAVAC="%JAVA_HOME%\bin\javac"
+set JAVAH="%JAVA_HOME%\bin\javah"
+set JAVA="%JAVA_HOME%\bin\java"
+set JAVADOC="%JAVA_HOME%\bin\javadoc"
+set JAR="%JAVA_HOME%\bin\jar"
+
+set JAVACOPTIONS=-deprecation -g -O
+
+set LUCENE_JAR=.\lib\lucene-core-2.0.0.jar
+set MYCLASSPATH=%LUCENE_JAR%;%JAVACLASSDIR%
+
+
+if ""%1"" == """" goto all
+if ""%1"" == ""all"" goto all
+if ""%1"" == ""install"" goto install
+if ""%1"" == ""clean"" goto clean
+
+:unknown
+	echo Error: Unrecognized argument %1.
+	goto done
+
+:all
+	if not exist %JAVACLASSDIR% mkdir %JAVACLASSDIR%
+	echo Compiling Greenstone Lucene Java classes ...
+	%JAVAC% -d %JAVACLASSDIR% -classpath %MYCLASSPATH% %JAVACOPTIONS% -sourcepath src src\org\greenstone\LuceneWrapper\*.java
+	cd %JAVACLASSDIR%
+	%JAR% xf ..\%LUCENE_JAR%
+	cd ..
+	%JAR% cf LuceneWrapper.jar -C %JAVACLASSDIR% .
+	goto done
+
+:install
+	goto done
+
+:clean
+	echo Cleaning up Greenstone Lucene ...
+	if exist %JAVACLASSDIR% rmdir /S /Q %JAVACLASSDIR%
+        if exist LuceneWrapper.jar del LuceneWrapper.jar
+	goto done 
+
+:done
+
Index: /tags/greenstone-3_02-distribution/indexers/winMake.bat
===================================================================
--- /tags/greenstone-3_02-distribution/indexers/winMake.bat	(revision 13928)
+++ /tags/greenstone-3_02-distribution/indexers/winMake.bat	(revision 13928)
@@ -0,0 +1,69 @@
+@echo off
+
+set MAKE=nmake
+set MAKE_OPTIONS=/f
+
+if ""%1"" == """" goto all
+if ""%1"" == ""all"" goto go
+if ""%1"" == ""install"" goto go
+if ""%1"" == ""clean"" goto clean
+
+:unknown
+	echo Error: Unrecognized argument %1.
+	goto done
+
+:clean
+	del bin\*
+
+:go
+	if ""%2"" == ""javaonly"" goto java
+	if ""%2"" == ""nojava"" goto nojava
+
+:all
+	mkdir bin
+	cd packages\unac
+	%MAKE% %MAKE_OPTIONS% win32.mak %1
+	cd ..\..
+
+	cd mg
+	call winMake.bat %1 
+	cd ..
+
+	cd mgpp
+	call winMake.bat %1 
+	cd ..
+	
+	cd lucene-gs
+	call winMake.bat %1
+	cd ..
+	goto done
+
+:java
+	cd mg
+	call winMake.bat %1 javaonly
+	cd ..
+
+	cd mgpp
+	call winMake.bat %1 javaonly
+	cd ..
+	
+	cd lucene-gs
+	call winMake.bat %1 
+	cd ..
+	goto done
+
+:nojava
+	cd packages\unac
+	%MAKE% %MAKE_OPTIONS% win32.mak %1
+	cd ..\..
+
+	cd mg
+	call winMake.bat %1 nojava
+	cd ..
+
+	cd mgpp
+	call winMake.bat %1 nojava
+	cd ..
+	goto done
+
+:done
